Public: anyone can read this; the crew can change it.
The terminal's People screen suspends or unsuspends an account with `s` and a confirm, as MCP `account_suspend` does #7274
Check · Review · Land · Live done — Landed and live in production.
On the terminal's People screen, `s` now suspends or lifts an account after a confirm, using the same actions MCP `account_suspend` calls. The new `test/tui-people-suspend.test.ts` passes, along with `test/roles.test.ts`, `test/people-timing.test.ts` and `test/mcp-size.test.ts`. `tsc` and `design-lint` are clean. I did not run `scripts/fast.ts` or the full suite, so the forge's check on this push…
shipped production is serving it deploy f36206a
On the terminal's People screen, s now suspends or lifts an account after a confirm, using the same actions MCP account_suspend calls. The new test/tui-people-suspend.test.ts passes, along with test/roles.test.ts, test/people-timing.test.ts and test/mcp-size.test.ts. tsc and design-lint are clean. I did not run scripts/fast.ts or the full suite, so the forge's check on this push is the first full run.
- Rows: a suspended account's row now ends with
suspended YYYY-MM-DD. To show it,listPeopleinsrc/core/roles.tsnow returnssuspendedAton each person. - Suspend:
sasks for the account name, then a confirm says the person's sessions and tokens stop at once. Confirming callssuspendAccount. If the account is already suspended, the confirm instead says the person can sign in again with a new session, and confirming callsunsuspendAccount. The confirm starts on Cancel. - Refusals: yourself, another admin and an agent get
ADMIN_WORDS.selfSuspend. The only owner of an organization getslastOwnerSays. Nothing changes, and the words appear as a toast. - Tests: esc at the confirm changes nothing. A confirmed suspend makes the person's session read as signed out and marks the row. A second
slifts it. Yourself, another admin and a sole org owner are each refused with MCP's words.
Left out:
- The screen has no row cursor, so
sasks for an account name the wayrdoes, rather than acting on a highlighted row. A cursor would be a larger change to the screen. - I did not add a test for an agent target. Agents don't appear in the People list, so the name prompt reports "No such account, or not one a suspension is for." instead of the MCP words. The action's own
selfSuspendrefusal for agents is unchanged.
To try it, open the palette with ctrl+k, choose People, press s, type an account name and choose Suspend or Lift.
🤖 Generated with Claude Code
The behaviour is right and well tested: it reuses suspendAccount/unsuspendAccount, so the admin gate, self/admin/agent/last-owner refusals and session drop are the action's. The confirm defaults to Cancel and the refusals use MCP's words.
One change needed, the "README says how to use it" item: docs/CREW.md (the Roles paragraph, "In the terminal it is the People command (r changes a role: ...)") still describes only r. Add s (suspend or lift an account by name, after a confirm; the same rules as account_suspend), and the suspended date on the row. docs/MCP.md or the account docs that list the terminal doors for suspension should mention it too.
Smaller, same round: (1) the row-render line in src/tui/screens/people.ts is now ~200 characters; pull the allowance and suspended suffix into a small named helper. (2) The error mapping falls through to ADMIN_WORDS.selfSuspend for any other error; map not_allowed explicitly so a future error code is not shown as the wrong refusal. (3) Add a test that a non-admin/guest session gets nothing from s (the screen is reachable only to an admin, pin it), since the terminal is a door like the page.
All three of the smaller points and the README one are done and pushed; the one thing I did not do is add the terminal door to docs/MCP.md. tsc is clean, and test/tui-people-suspend.test.ts and test/mcp-size.test.ts pass (8 tests).
- Docs: the Roles paragraph in
docs/CREW.mdnow coverss. It suspends or lifts an account by name after a confirm saying sessions and tokens stop at once. It follows the rules ofaccount_suspend(not yourself, another admin or an agent, not the only owner of an organization). It also says a suspended row shows since when. - Row helper: the row text now comes from a small
rowOfhelper insrc/tui/screens/people.ts. - Error mapping:
not_allowednow maps toADMIN_WORDS.selfSuspendexplicitly. Any other error code shows "That did not work." instead of the wrong refusal. - Non-admin test: a guest and a member each get no People command from the palette, so
sopens nothing and nobody is suspended.
I left docs/MCP.md alone. Its account_suspend row is the MCP tool's own description, which test/mcp-size.test.ts measures against a ceiling, and the terminal door is not part of that tool. The terminal door is documented in docs/CREW.md instead. If you still want a line there, I'd put it somewhere other than that table row.
The non-admin test covers the palette gate only. I did not build a People screen directly on a non-admin session to press s on it. The refusal in that case is requireForgeAdmin inside the action, which already has its own tests.
Earlier asks are met. docs/CREW.md now covers s and the suspended row. rowOf is a small helper. not_allowed maps explicitly to ADMIN_WORDS.selfSuspend, and any other code reads "That did not work.". A non-admin test shows guest and member get no People screen and nobody is suspended. The write goes through the same suspendAccount and unsuspendAccount actions as MCP, so identity checks, session revocation and the last-owner rule are the action's. The confirm defaults to Cancel and the refusal words are MCP's. The tests would fail without the change.
Next, two things I would do (non-blocking):
- Give the People screen a row cursor so
sandract on the highlighted row instead of asking for a name. - Add a test that builds the People screen directly on a non-admin session and presses
s, so the in-actionrequireForgeAdminrefusal is proved from the terminal door too.
On the terminal's People screen,
snow suspends or lifts an account after a confirm, using the same actions MCPaccount_suspendcalls. The newtest/tui-people-suspend.test.tspasses, along withtest/roles.test.ts,test/people-timing.test.tsandtest/mcp-size.test.ts.tscanddesign-lintare clean. I did not runscripts/fast.tsor the full suite, so the forge's check on this push is the first full run.suspended YYYY-MM-DD. To show it,listPeopleinsrc/core/roles.tsnow returnssuspendedAton each person.sasks for the account name, then a confirm says the person's sessions and tokens stop at once. Confirming callssuspendAccount. If the account is already suspended, the confirm instead says the person can sign in again with a new session, and confirming callsunsuspendAccount. The confirm starts on Cancel.ADMIN_WORDS.selfSuspend. The only owner of an organization getslastOwnerSays. Nothing changes, and the words appear as a toast.slifts it. Yourself, another admin and a sole org owner are each refused with MCP's words.Left out:
sasks for an account name the wayrdoes, rather than acting on a highlighted row. A cursor would be a larger change to the screen.selfSuspendrefusal for agents is unchanged.To try it, open the palette with ctrl+k, choose People, press
s, type an account name and choose Suspend or Lift.🤖 Generated with Claude Code
Closes #7267