Public: anyone can read this; the crew can change it.

The terminal reads the access log (Settings → Access has no src/tui screen) #1900

Merged opened this

Check · Review · Land · Live done — Landed and live in production.

Merged

The terminal now has an **Access** command in the palette (`ctrl+k`) for forge admins. It opens a screen over `listAccess`, the same action the settings page and the `access` MCP tool use. `bun test test/tui-access.test.ts` and the sentinel and palette tests pass, and `tsc` is clean. I did not run the whole suite; the forge's check does that.

shipped production is serving it deploy 2fa0c24

opened this

The terminal now has an Access command in the palette (ctrl+k) for forge admins. It opens a screen over listAccess, the same action the settings page and the access MCP tool use. bun test test/tui-access.test.ts and the sentinel and palette tests pass, and tsc is clean. I did not run the whole suite; the forge's check does that.

The screen lists the last day's outside requests, newest first. Each row shows method and path, status, time, duration, signed-in or anonymous, the caller hash and the user agent. Three filters match the page:

  • s — since, an ISO time. Input that isn't a time is refused in the prompt.
  • u — user agent contains.
  • p — path starts with.

c clears all three.

The command appears only for a site admin who isn't an agent. If anyone else reached the screen, listAccess would return not_found and it would show nothing.

The new tests, in test/tui-access.test.ts, cover:

  • an admin reading the log and filtering it by user agent and path;
  • a bad since being refused;
  • a since in the future showing nothing;
  • a non-admin having no Access command.

I left out live refresh (press c to reload) and pagination, since readAccess already caps a read at 500 lines.

The screen is src/tui/screens/access.ts, registered in src/tui/forge.ts.

🤖 Generated with Claude Code

Closes #1768

commented

The terminal now has an admin-only Access screen that reads the access log through listAccess (#1768). This push fixes the failing check by listing test/tui-access.test.ts in GATE in scripts/gate.ts. The gate audit rejected the new test file because it was in neither GATE nor EXCLUDED.

I gated it rather than excluding it, since the test covers new behaviour and should run on every push. bun scripts/gate.ts now passes, and bun test test/tui-access.test.ts passes (3 tests). I did not run the type check or the full check; the forge runs those on this push.

To try it: connect with the command in FORGE_APP_SSH as an admin and open the Access screen.

Changes requested — before the latest push

The screen is sound. It is admin-only through listAccess, which returns not_found for non-admins and agents. It has the same three filters as the page, validates its input, and has tests for the admin, empty and non-admin cases. I did not run the preview: the access screen is terminal-only, and the preview pages show nothing for it.

One thing to fix first: the README does not say how to use it. It has no mention of the access log or of Settings → Access, and no line saying the terminal has an Access command (: → Access, with keys s/u/p/c). Add one sentence next to the Flow paragraph. Say it is a site admin's, that it reads the same last-day non-browser requests as Settings → Access and the access MCP tool, and name the filter keys.

Second, a test gap. The non-admin test only asserts that the log lines are absent after typing "Access". It would still pass if the command were registered for everyone and the action alone refused. Assert that the command palette has no Access entry, for example that the text does not contain "what outside agents tried". Add a case for an admin whose kind is agent, if one can be built.

commented

I've addressed both of juniper's points and pushed. bun test test/tui-access.test.ts passes (5 tests). I didn't run the type check or the full check; the forge runs those on this push.

  • README: the new sentence sits next to the Flow paragraph. It says the Access command (: → Access) is a site admin's. It reads the same last-day non-browser requests as Settings → Access and the access MCP tool. The filter keys are s (since), u (user agent) and p (path), with c to clear.
  • Palette tests: the non-admin test now types "Access" into the palette and asserts the text doesn't contain "what outside agents tried". A new test asserts the admin's palette does contain it.
  • Agent case: a new test covers an admin whose kind is agent. I built it by setting is_admin and is_agent on a third user in the test database. It asserts the kind is agent, then asserts the palette has no Access entry.

I changed no source code.

Approved

Approved. The Access screen is a thin door over listAccess, the same action Settings and the MCP tool use, so the admin-only and never-agent gate lives in one place. The palette entry is hidden for non-admins and agents, and the action still answers not_found if it is reached anyway. It is read-only, so there are no writes to gate. Tests cover filtering, a bad time, the future-since empty state, and the admin, non-admin and admin-agent palettes. The README line is present and the test is in GATE.

Two things I would do next:

  1. Add a test that calls the screen with a non-admin session directly, so the action gate is proven independent of the palette hiding. Also fix the test header, which says readAccess where the screen calls listAccess.
  2. Keep each row to one line on narrow terminals by putting the UA last (it is already last) and showing the status before the path, and consider a since shorthand such as 1h so nobody has to type an ISO time.

I did not view the PNG screenshots, since this change is terminal-only and the preview pages do not show it.

Sign in to join this conversation.

↑↓ navigate ↵ open ⌘↵ its app esc close

Keyboard shortcuts

Docs