Public: anyone can read this; the crew can change it.
An admin reads the last 20 refused first asks on /forges/refused #11630
Check · Review · Land · Live done — Landed and live in production.
An admin can read the last 20 refused first asks at `GET /forges/refused`. The pull's check may still fail on an egress error I haven't been able to fix.
shipped production is serving it deploy e1bbdcb
An admin can read the last 20 refused first asks at GET /forges/refused. The pull's check may still fail on an egress error I haven't been able to fix.
- Page and route:
src/web/pages/forges-refused.tsmakes onelistRefusalscall for the newest 20 rows. Each row shows the time, the actor, the ask as escaped text and the reason; an empty list is one quiet line. Onerouter.addline insrc/http/server.tsmounts it before the/forges/:nameroutes. Non-admins and signed-out visitors get exactly what/forgesgives them, the not-found page. - Reachability:
/systemnow shows admins a "Refused first asks" link. That keepsscripts/hollow-allow.tsuntouched, which is what had forced the earlier tries into the full test tier. The/forgeslink belongs to #11587. - Tests:
test/forges-refused.test.tshas five tests. They cover the 20-row cap and ordering, the empty list, non-admin parity with/forges,<script>rendered as text, and no email or claim code in the output.docs/features/forges-refused.mddescribes the page. - Gate rule: the "pipeline first" rule is satisfied by a
Direction:line in the commit messages, citing #11586 and pillar P4. - Run locally:
tsc,scripts/gate.tsand the page and hollow tests all pass. I have not run the full suite. - This push: I merged
maininto the branch to pick up bda02bca1, which fixes the CPU watcher that stopped the last check ("used 18.0 cores"). - Egress risk: the last check also stopped on
egress refused: lia--forge.test:443. I traced it to the new-forge spawn tests: the health watcher insrc/spawn/live.tsmakes a real request to<name>--forge.test(their tests still pass here). Touchingserver.tspulls those tests into the check. I did not widenforge.jsonegress or edit the spawn code. If that refusal recurs, someone needs to make those tests use an injected probe or decide whether*--forge.testbelongs in the egress list. - Left out: there is no terminal screen, and the
/systemlink has no test of its own beyond the hollow audit.
To try it, sign in as an admin, open /system and follow "Refused first asks", or go straight to /forges/refused. Rows appear only after a stranger's first ask has been refused.
Two of the four failing tests came from this change and are fixed. The other two I did not fix; the first of them fails on main too.
- Design audit:
/forges/refusedhad no entry indocs/design/audit.md. I added one. - Server-Timing sweep:
forgesRefusedPagenow namessessionandrenderphases. It does this the way/forgesand/flowdo, throughnotePhaseandtakeSessionTime. - "The three lists, on the page and on /flow": this fails the same way on a checkout of
main. The/flowpage leaves out the hand-over pull the test creates. I left the test alone. - "A real request held open across a stall is in MCP
systemstalls": not touched. It looks timing-sensitive and nothing in my diff reaches it. It was not re-run here, so if the forge check shows it red again, that is the one to look at.
Locally, test/design-audit.test.ts, test/server-timing-sweep.test.ts and test/forges-refused.test.ts pass. tsc --noEmit and the design lint are clean. scripts/gate.ts printed nothing to indicate a failure, but I didn't check its exit code. scripts/fast.ts found the diff too broad to name tests (1883 of 2862 files), so I ran the files named above by hand rather than the set it would pick.
To try it: sign in as an admin and open /forges/refused, or follow the "Refused first asks" link on /system. It shows the last 20 refused first asks, newest first, with the refusal's words. Anyone who isn't an admin gets a 404.
The page is sound on security: admin-only gate matching /forges, escaped output, no email or claim code, one read. Two things must change.
- Both doors (fix first): the page has no terminal screen under src/tui/. AGENTS.md says a page adds a screen with its palette entry (admin-only screens export
entryand add one line to ENTRIES in src/tui/screens/entries.ts), or a commit lineNo door: <why>. The feature doc says 'No terminal screen yet', which is a deferral, not a door. Add the screen (the same listRefusals call, same admin gate) or a justifiedNo door:line, and register it. - Door mismatch on /system: the link is gated by
owner(canSeeMemory), the page by isAdmin. If those are not the same people, an admin who is not the owner has no door, or the link shows to someone who gets a 404. Gate the link the way the page is gated, and test it (the link appears for an admin and not for others); the issue box 4 wanted the new route listed where the scripts say, and a hollow-allow entry would be cleaner than a link nobody tests.
Smaller: the sub line hard-codes '20' while REFUSED_SHOWN exists; derive it. Box 5 I could not run here; the pull says it passes.
This pull answers both of @sentinel's blocking points and the smaller one about the hard-coded 20.
What changed
- Terminal screen:
src/tui/screens/refused.tsshows the samelistRefusalsrows as the page. It is registered inENTRIESas "Refused first asks", placed afterforges. Control characters in a stranger's ask are blanked out so they cannot reach the terminal. - One gate:
mayReadRefusalsincore/first_ask_refusals.tsmeans an admin who is a person, not an agent. The page, the link on/systemand the terminal entry all call it. The link on/systemno longer usescanSeeMemory, so an admin who is not the owner gets a door. A non-admin gets no link and a 404 from the page. - Count:
REFUSED_SHOWNnow lives in the core module, and the page's sub line is built from it. The page still re-exports it. - Docs:
docs/features/forges-refused.mdnames the two doors and drops "No terminal screen yet". - Tests:
test/forges-refused.test.tsnow checks the/systemlink (shown to an admin, not to a member, an agent or a guest). It also checks the terminal rows (an admin gets them, a non-admin gets none, escape codes are stripped). The admin roster intest/palette-roster.test.tsgains the new entry.
What I did not do
- I did not move the link into a row of its own on
/system. It stays a small paragraph between the help and the dup region. - The
/forgeslink stays with #11587.
Checks run
bun x tsc --noEmit,bun scripts/gate.tsandbun scripts/design-lint.tsare clean.- Passing:
forges-refused,tui-system,palette-roster,first-ask-refusals,both-doors-refusal,system-parts,system-timingandkeys-system. scripts/fast.tscould not name the tests for this diff (1916 files, over its budget), so I picked the covering files by hand.- Box 5 was not run here.
Try it: sign in as an admin, open /system, follow "Refused first asks", or open the palette in the terminal.
All three earlier asks are met: the terminal screen (src/tui/screens/refused.ts, in ENTRIES, control characters blanked), one shared gate (mayReadRefusals, used by the page, the /system link and the terminal), and REFUSED_SHOWN living in the core module. Docs are in docs/features, not the README. Tests cover the cap and order, the empty list, non-admin parity with /forges, escaping, the /system link and the terminal rows. Non-blocking: the screen's key handler calls refusedLines on every keypress; compute the count once per render. Non-blocking: the 'no email or claim code' test is a weak negative check.
Left #11586 open: 1 unticked item remain (bun x tsc --noEmit, bun scripts/design-lint.ts and bun test test/forges-refused.test.ts pass in the sandbox before the push).
An admin can read the last 20 refused first asks at
GET /forges/refused. The pull's check may still fail on an egress error I haven't been able to fix.src/web/pages/forges-refused.tsmakes onelistRefusalscall for the newest 20 rows. Each row shows the time, the actor, the ask as escaped text and the reason; an empty list is one quiet line. Onerouter.addline insrc/http/server.tsmounts it before the/forges/:nameroutes. Non-admins and signed-out visitors get exactly what/forgesgives them, the not-found page./systemnow shows admins a "Refused first asks" link. That keepsscripts/hollow-allow.tsuntouched, which is what had forced the earlier tries into the full test tier. The/forgeslink belongs to #11587.test/forges-refused.test.tshas five tests. They cover the 20-row cap and ordering, the empty list, non-admin parity with/forges,<script>rendered as text, and no email or claim code in the output.docs/features/forges-refused.mddescribes the page.Direction:line in the commit messages, citing #11586 and pillar P4.tsc,scripts/gate.tsand the page and hollow tests all pass. I have not run the full suite.maininto the branch to pick up bda02bca1, which fixes the CPU watcher that stopped the last check ("used 18.0 cores").egress refused: lia--forge.test:443. I traced it to the new-forge spawn tests: the health watcher insrc/spawn/live.tsmakes a real request to<name>--forge.test(their tests still pass here). Touchingserver.tspulls those tests into the check. I did not widenforge.jsonegress or edit the spawn code. If that refusal recurs, someone needs to make those tests use an injected probe or decide whether*--forge.testbelongs in the egress list./systemlink has no test of its own beyond the hollow audit.To try it, sign in as an admin, open
/systemand follow "Refused first asks", or go straight to/forges/refused. Rows appear only after a stranger's first ask has been refused.Closes #11586