Task: Build the administrator's Rescue access screen
Table of Contents
This page documents a task in the Implement the credentials journeys in ores.web story. It captures the goal, current status, acceptance, and any notes or results.
1. Goal
Run Rescue access in
ores.web against the real server, on variant B of the accepted prototype: the
account's security state leads and names the action it suggests, and the
recovery action and the lock control sit under it.
The administrator finds the colleague, reads the account and its login record, and locks or unlocks the account through two BFF routes this task adds. The recovery link is drawn as the primary action and is unavailable, with the reason on the screen, because nothing in the tree sends mail, no subject requests a reset and no table holds a token.
2. Status
| Field | Value |
|---|---|
| State | DONE |
| Parent story | Implement the credentials journeys in ores.web |
| Now | Nothing. |
| Waiting on | Nothing. |
| Next | Nothing. |
| Last touched | 2026-10-01 |
3. Acceptance
- The screen is reachable from the signed-in shell and reads the account list, one account and that account's login record through the BFF routes that already serve them.
- Lock and unlock are one control that shows the state it produces, and each one
writes through its own BFF route and its own subject
(
iam.v1.accounts.lock,iam.v1.accounts.unlock), each guarded by the permission the catalogue grants. - The screen states what a lock does not do: it leaves open sessions open.
- Send the recovery link is drawn as the primary action and is unavailable, and the screen says why: no mail path, no token store and no subject.
- Every panel whose data has no read path says the data is not available.
- The rejected variants and the design decisions stay on the prototype task; the build carries variant B and no other.
4. Plan
- Add the two write routes the journey needs —
POST /api/accounts/:username/lockandPOST /api/accounts/:username/unlock— with their wire schemas, their BFF handler tests and their client methods. - Build
/rescuefrom the accepted variant B, composingAppShellwith the shared primitives and the account, login-record and session reads the group already landed. - Answer the fallback question the prototype raised, and record the answer.
- Drive the screen against the running fleet, then land it.
5. Notes
The one question this task must answer first. The accepted prototype keeps an
administrator-typed password as a collapsed fallback for a mailbox that cannot
receive, and asks whether it survives the build. It does not. The product owner
settled the direction when they replaced the reset form with the emailed link,
and a control that has to disclaim its own record — an administrator who types a
password knows that password — is worse than no control. The
iam.v1.accounts.reset-password subject stays without a browser caller, the
screen draws no password field, and
Rescue access is corrected in this
branch to match. The link is the whole mechanism.
The recovery link is not this task. It needs a token table, a request subject, a completion subject and a mail path, and it is filed as The tree has no way to send an email, and password recovery needs one. This task draws the action and states the gap, which is what the story's rule asks of a control the server cannot perform.
The role the screen assumes. iam::accounts:lock, iam::accounts:unlock and
iam::accounts:reset_password are the administrator's; iam::accounts:read and
iam::login_info:read are what the reads need. The inventory records where the
catalogue grants them, and a role that holds the writes without the reads would
see the screen refuse its own panels.
6. Test Scenarios
Manual QA scenarios (scaffolded via compass add test_scenario)
that verify this task. Link
new ones here as they're created; the scenario doc itself links back
via its "Verifies task" field.
| Scenario | State | Notes |
|---|---|---|
7. PRs
| PR | Title |
|---|---|
| #2493 | [web] Build the administrator's Rescue access screen |
8. Review
| Comment summary | File | Decision | Notes |
|---|---|---|---|
9. Result
Built 2026-10-01.
Rescue access is a route behind the signed-in shell. It reads the tenant's
accounts, one account and that account's login record through the routes the
group already landed, and it writes through two routes this task adds:
POST /api/accounts/:accountId/lock and POST /api/accounts/:accountId/unlock,
each forwarding to the subject that already existed. The screen is the accepted
prototype's variant B.
The prototype's open question is answered and recorded on the parent story: the
administrator-typed password fallback does not ship. The screen draws no password
field, iam.v1.accounts.reset-password keeps no browser caller, and
Rescue access and its wireframe are
corrected to match.
The account list has no page yet, so /rescue with no username picks a colleague
out of the tenant's accounts and links to /rescue?username=<username>. The
accepted variant does not keep the roster in view, so a control returns to the
picker. Every panel the server cannot serve says so: the recovery link is drawn
unavailable with its reason, and the lock panel states that a lock leaves open
sessions open.
Verification. npm run typecheck passes across the three packages, Prettier is
clean, and the suites are green: bff 102 tests in 21 files, web 192 in 18,
wire-protocol 51 in 7. Six of the web tests render the loaded screen from a
fixture and assert the state it names, the recovery link being unavailable with
its reason, the absence of any password field, and the gap list.
The write path was driven end to end against the running fleet on port 21803:
a fresh sign-in, iam::accounts:lock through the new route, the login record
then reading locked: true, unlock through the new route, the record reading
locked: false, and a fresh sign-in answering 200 again. The lock also refused a
fresh sign-in with 401 while it was in force, which is what proves the write
reached the server's own state rather than the route's copy of it.
The per-account refusal is covered by a route test rather than by the fleet: nothing in the environment holds a second person account, and locking the only one leaves nobody who can unlock it.
What is still missing. The screen has no test that drives the browser, because
the package has no DOM harness; the panels are rendered from a fixture instead.
And the roles the screen assumes are worth checking before a tenant administrator
uses it: the reads need iam::accounts:read and iam::login_info:read, and the
writes need iam::accounts:lock and iam::accounts:unlock.