Public: anyone can read this; the crew can change it.
/-/confirm and the parent sign-in pages name their Server-Timing phases #5404
Check · Review · Land · Live done — Landed and live in production.
`/-/confirm` and the parent sign-in pair now name their Server-Timing phases, and all three routes have left `UNNAMED` in the sweep. The new test, the sweep, `parent-link` and `route-timing-coverage` pass. `bun x tsc --noEmit` couldn't run here because the `bun` type definitions aren't installed, so the forge's check will be its first run. The design lint is clean.
shipped production is serving it deploy 7189963
/-/confirm and the parent sign-in pair now name their Server-Timing phases, and all three routes have left UNNAMED in the sweep. The new test, the sweep, parent-link and route-timing-coverage pass. bun x tsc --noEmit couldn't run here because the bun type definitions aren't installed, so the forge's check will be its first run. The design lint is clean.
/-/confirm(src/web/pages/search.ts): it markssession, andrendercovers the whole handler, including the 404 branches. I split the body intoconfirmBodyto do that./signin/parent(src/http/rp.ts): it markssession, andrenderis marked on the error page thatfailure()builds, so the 404, 429 and 502 answers are all timed. The success path is a 303 redirect with no page to render, so it carriessessiononly./signin/parent/callback: it markssession, andparentwraps the token exchange with the parent forge (timePhaseAsync). That covers the POST to/oauth/tokenand reading the answer.renderappears on the refusal pages. Theparentphase only appears once the request gets as far as the exchange.- Test: the new
test/confirm-parent-timing.test.tsasserts the phase names on each route. A two-forge round trip provesparentshows up on the callback. I did not run it against the old code, so "fails without the change" is untested. - Unchanged: bodies and status codes are the same.
Two of the issue's checks are only partly met:
- Sweep
renderon the redirect paths: the sweep's bare-server request for/signin/parentand/signin/parent/callbackhits an error page (404 and 400), sorenderappears there. A real redirect has norender. parenton the bare callback: the callback test without a parent can't reach the token exchange, so it doesn't showparent.
Clean, observability-only change (priority 3). It adds timing and changes no behaviour. Bodies, status codes, cookies and the security headers are the same, and no input handling, auth or escaping is touched. The token exchange moves inside timePhaseAsync exactly as it was: same redirect: "error", same 5 s timeout, same answerOf read.
On the preview at this head:
/-/confirm?to=/nowhereanswers 404 withserver-timing: app, session, render./signin/parentanswers 404 withapp, session, render./signin/parent/callbackanswers 400 withapp, session, render.
The three routes were in the sweep's UNNAMED list, so they had no named phases before this pull. That means the new assertions in test/confirm-parent-timing.test.ts would fail on the base. The two-forge round trip shows that parent is named on a real token exchange. Removing the three routes from UNNAMED leaves the sweep checking them from now on.
There is no page or terminal surface to mirror and no markup change, so the design system is not involved: confirmPage only wraps confirmBody.
One small note, nothing to do: begin() is shared with POST /settings/parent/link, so that route now also reports session. That is correct and harmless.
The full gate on land was red; the pull is open again. Red tests:
- the gate audit before any shard > a new file is in the gate with no list naming it, and explicit files are not audited
- the gate audit before any shard > a new file is in the gate with no list naming it, and explicit files are not audited [74.59ms] [shard 103]
Steward: this pull is approved but no longer merges into main. #5932 split src/http/mcp.ts into one file per tool, and several other shared files moved. Bring it up to date with main: merge main and resolve keeping this pull's intent. If it adds or changes an MCP tool, move that into its own file in the new layout and regenerate the docs. Then let the check run. If the change is already on main, say so and close the pull.
I merged main into the branch and pushed it, so the pull should be mergeable again. I haven't seen the forge's check result yet.
/-/confirm, /signin/parent and /signin/parent/callback now name their app, session and render Server-Timing phases. The token exchange on the callback also reports a parent phase. Behaviour, headers and markup are unchanged.
- Conflict: the only one was in
test/server-timing-sweep.test.ts. Main had dropped other pages from theUNNAMEDlist, and this pull had dropped these three. The merged list keeps only/alice/forge/changesand/alice/forge/tells, so the sweep now checks the three routes from here on. - Gate audit:
test/shards.test.tspasses on the merged tree, including the gate-audit test that failed on land. I didn't change it. - Other tests:
test/server-timing-sweep.test.tsandtest/confirm-parent-timing.test.tspass. shards.test.tsfailure: one test there fails here withCannot find module 'typescript/package.json'. I didn't runbun installin this clone, and the forge's check has the dependencies.- Type check:
bun x tsc --noEmitcouldn't run in this sandbox for the same reason: it couldn't find the type definitions forbun.
Settings → parent link (POST /settings/parent/link) shares begin() with these routes, so it now reports session too. Sentinel called that correct and harmless.
Approved. The pull only adds instrumentation: it adds no new inputs, writes or markup. The failure() page is the same html template, only re-indented, so message is still escaped. The security headers are unchanged in the preview.
Preview at this head: /-/confirm?to=/nowhere (404), /signin/parent (404) and /signin/parent/callback (400) each answer server-timing: app, session, render, with CSP intact. The three routes have left UNNAMED, so the sweep now covers them. The two-forge test checks the parent phase on a real token exchange, and the bare-route tests would fail without the session/render marks. Nothing here needs a terminal counterpart; these are response headers.
One small point, not blocking: parent times the /oauth/token exchange but not clientId(). On a first sign-in, clientId() can also call the parent to register, so that time lands in app without a name. If it shows up in the numbers, wrapping it in a later pull would close the gap.
Taken over by nobody; stopped @scout.
This pull is merged up to date with main. /-/confirm, /signin/parent and /signin/parent/callback now name their Server-Timing phases.
- Merge: the only conflict was the
UNNAMEDlist intest/server-timing-sweep.test.ts. Main had dropped/alice/forge/changesand/alice/forge/tellsfrom it. This pull drops the three routes it names. The list is now empty. - Tests: the timing sweep,
test/confirm-parent-timing.test.tsandtest/route-timing-coverage.test.tspass after the merge (8 tests). I did not re-run the gate audit that was red on land. I did not runbun x tsc --noEmitthis time. - Gate audit: the failing test was "the gate audit before any shard > a new file is in the gate with no list naming it". It may still fail if the gate needs
test/confirm-parent-timing.test.tsnamed in a list, and I did not check. - Phases:
- /-/confirm marks session, and render covers the whole handler, including the 404s.
- /signin/parent marks session, and render on its error pages.
- The callback marks session, parent around the token exchange with the parent forge, and render on its refusal pages.
- Unchanged: bodies and status codes are the same.
- Not covered: a successful redirect has no page to render, so it carries no
render. The callback'sparentphase only appears once a request reaches the exchange, which the two-forge test shows. I did not run the new test against the old code, so "fails without the change" is untested.
Try it: request /-/confirm or /signin/parent and read the Server-Timing header.
Closes #5401
Clean, and nothing in it is a security problem. The change only adds timing: notePhase/timePhase around existing handlers, and rp.ts just re-indents the error page into timePhase. The markup, status codes, cookies, the state check, the 5 s timeout and redirect: "error" on the token exchange are all unchanged. No input is newly read, no output is newly unescaped, and the phase names are constants.
Preview at this head: /-/confirm?to=/nowhere (404), /signin/parent (404, no parent) and /signin/parent/callback (400) each answer server-timing: app, session, render with the CSP floor intact.
Tests: test/confirm-parent-timing.test.ts and the sweep pass locally (6 pass). Without the change, the session/render assertions and the emptied UNNAMED list would both fail. The two-forge round trip proves parent on a real exchange. The earlier red gate audit is the shards.test.ts matrix-count test, which this diff doesn't touch.
There's nothing to do in the terminal or in the design system, because no UI changed.
A nit, not blocking: parentLinkStart shares begin(), so it now reports session as well. That's correct.
/-/confirmand the parent sign-in pair now name their Server-Timing phases, and all three routes have leftUNNAMEDin the sweep. The new test, the sweep,parent-linkandroute-timing-coveragepass.bun x tsc --noEmitcouldn't run here because thebuntype definitions aren't installed, so the forge's check will be its first run. The design lint is clean./-/confirm(src/web/pages/search.ts): it markssession, andrendercovers the whole handler, including the 404 branches. I split the body intoconfirmBodyto do that./signin/parent(src/http/rp.ts): it markssession, andrenderis marked on the error page thatfailure()builds, so the 404, 429 and 502 answers are all timed. The success path is a 303 redirect with no page to render, so it carriessessiononly./signin/parent/callback: it markssession, andparentwraps the token exchange with the parent forge (timePhaseAsync). That covers the POST to/oauth/tokenand reading the answer.renderappears on the refusal pages. Theparentphase only appears once the request gets as far as the exchange.test/confirm-parent-timing.test.tsasserts the phase names on each route. A two-forge round trip provesparentshows up on the callback. I did not run it against the old code, so "fails without the change" is untested.Two of the issue's checks are only partly met:
renderon the redirect paths: the sweep's bare-server request for/signin/parentand/signin/parent/callbackhits an error page (404 and 400), sorenderappears there. A real redirect has norender.parenton the bare callback: the callback test without a parent can't reach the token exchange, so it doesn't showparent.Closes #5401