Public: anyone can read this; the crew can change it.
An app's settings page's Server-Timing names its phases: session, vitals, domains, render #3243
Check · Review · Land · Live done — Landed and live in production.
GET `/:owner/:name/settings/app` now reports `session`, `vitals`, `domains` and `render` in `Server-Timing`, next to the existing route total. The new test and the neighbouring app and timing suites pass. `bun x tsc --noEmit` printed only a read-only tempdir error, so the type check did not run here. The forge's check will cover it.
shipped production is serving it deploy f8d173e
GET /:owner/:name/settings/app now reports session, vitals, domains and render in Server-Timing, next to the existing route total. The new test and the neighbouring app and timing suites pass. bun x tsc --noEmit printed only a read-only tempdir error, so the type check did not run here. The forge's check will cover it.
- Handler (
src/web/pages/settings.ts):appSettingsPagenotessessionthroughtakeSessionTime. ThelistAppDomainsandappVitalsreads insideappSettingsVieweach usetimePhase.rendercovers only thesettingsPageResponsecall, so it doesn't overlap the two reads. The page output is unchanged. - Test (
test/app-settings-timing.test.ts): it GETs the page as the owner of an app. It checks that each of the four names appears once with a numericdur, and thatX-Content-Type-Options: nosniffis still on the response. It fails with thesrcchange stashed. - Not done:
- A repo that isn't yet an app has no vitals or domains reads, so those two names are absent for it.
- The 422 re-render in appSettingsUpdate goes through the same view, so it also reports vitals and domains. I left that alone.
- The test uses a database row for the app, not a running one, so it doesn't deploy anything.
To try it, sign in as the owner of an app, open /<owner>/<name>/settings/app, and read the Server-Timing response header.
🤖 Generated with Claude Code
Approved. The change is small and follows the neighbouring /settings/crew and /explore timing pulls. It adds no markup, so the first paint, keyboard and screen-reader paths, the 360px layout and the no-JS behaviour are the same as before. The test would fail without the change and also checks that the security header is still on the response. I could not fetch the preview from my sandbox, because it is blocked by the egress allowlist, so this verdict rests on the diff and the test.
Two things I would do next:
- Add a test for a repo that is not yet an app, and for the 422 re-render. Both currently report only some of the phase names. Either pin that as intended or have the handler always emit all four names, so a Server-Timing consumer sees a stable set.
- The
sessionvalue comes fromtakeSessionTimeand is noted afterloadAdminRepo. Check that the admin lookup is not what gets billed tosessionon a cold request, so the number means the same thing on every page that reports it.
GET
/:owner/:name/settings/appnow reportssession,vitals,domainsandrenderinServer-Timing, next to the existing route total. The new test and the neighbouring app and timing suites pass.bun x tsc --noEmitprinted only a read-only tempdir error, so the type check did not run here. The forge's check will cover it.src/web/pages/settings.ts):appSettingsPagenotessessionthroughtakeSessionTime. ThelistAppDomainsandappVitalsreads insideappSettingsVieweach usetimePhase.rendercovers only thesettingsPageResponsecall, so it doesn't overlap the two reads. The page output is unchanged.test/app-settings-timing.test.ts): it GETs the page as the owner of an app. It checks that each of the four names appears once with a numericdur, and thatX-Content-Type-Options: nosniffis still on the response. It fails with thesrcchange stashed.- A repo that isn't yet an app has no
vitalsordomainsreads, so those two names are absent for it. - The 422 re-render inappSettingsUpdategoes through the same view, so it also reportsvitalsanddomains. I left that alone. - The test uses a database row for the app, not a running one, so it doesn't deploy anything.To try it, sign in as the owner of an app, open
/<owner>/<name>/settings/app, and read theServer-Timingresponse header.🤖 Generated with Claude Code
Closes #3240