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

The API's board reads name their Server-Timing phases: session, boards, render #3949

Merged opened this

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

Merged

`GET /api/v1/boards`, `/api/v1/boards/pins` and `/api/v1/boards/:slug` now name their Server-Timing phases. `bun x tsc --noEmit` did not run here. `bun install` and `bun x tsc` both failed with "bun is unable to write files to tempdir: ReadOnlyFileSystem", and setting `BUN_TMPDIR` didn't help. The forge's check will be the first type check of this change. I added no import line.

shipped production is serving it deploy aafe9dc

opened this

GET /api/v1/boards, /api/v1/boards/pins and /api/v1/boards/:slug now name their Server-Timing phases. bun x tsc --noEmit did not run here. bun install and bun x tsc both failed with "bun is unable to write files to tempdir: ReadOnlyFileSystem", and setting BUN_TMPDIR didn't help. The forge's check will be the first type check of this change. I added no import line.

  • Phases: each handler notes session first, wraps its read (listAllBoards, listPinnedPanels, showBoard) in timePhaseAsync(..., "boards", ...), and builds the JSON answer inside timePhase(..., "render", ...). The code follows the pull-read route in the same file.
  • Refusals: the 401 and 403 from boardsAdmin return before the read, so they keep their status and body and name only session. A 404 from a missing board still names session, boards and render.
  • Not changed: the JSON bodies, every other handler, and GET /api/v1/boards/:slug/panels/:id (left to #3920).
  • Tests: test/api-boards-timing.test.ts is new and has three tests, all passing here:

- a signed-in admin's successful read of each of the three routes names session, boards, render, in that order; - a missing board answers 404 with the same phases; - an unauthenticated request answers 401 with session only.

Without the api.ts change all three fail. test/board-pins.test.ts also still passes.

To try it, sign in as a site admin and read /api/v1/boards with curl -i. The Server-Timing header lists the three phases after app.

Closes #3936

commented

GET /api/v1/boards, /api/v1/boards/pins and /api/v1/boards/:slug now name their Server-Timing phases. bun x tsc --noEmit did not run here. bun install and bun x tsc both failed with "bun is unable to write files to tempdir: ReadOnlyFileSystem", and setting BUN_TMPDIR didn't help. The forge's check will be the first type check of this change. I added no import line.

  • Phases: each handler notes session first, wraps its read (listAllBoards, listPinnedPanels, showBoard) in timePhaseAsync(..., "boards", ...), and builds the JSON answer inside timePhase(..., "render", ...). The code follows the pull-read route in the same file.
  • Refusals: the 401 and 403 from boardsAdmin return before the read, so they keep their status and body and name only session. A 404 from a missing board still names session, boards and render.
  • Not changed: the JSON bodies, every other handler, and GET /api/v1/boards/:slug/panels/:id (left to #3920).
  • Tests: test/api-boards-timing.test.ts is new and has three tests, all passing here:

- a signed-in admin's successful read of each of the three routes names session, boards, render, in that order; - a missing board answers 404 with the same phases; - an unauthenticated request answers 401 with session only.

Without the api.ts change all three fail. test/board-pins.test.ts also still passes.

To try it, sign in as a site admin and read /api/v1/boards with curl -i. The Server-Timing header lists the three phases after app.

Approved — before the latest push

Read every changed line. The three board reads (GET /api/v1/boards, /boards/pins, /boards/:slug) now note session, time their read as boards, and build the answer under render. This is the same pattern the pull-read route in src/http/api.ts already uses, and route_timing.ts is already imported there, so no import line was needed. The authorization path is unchanged: boardsAdmin still runs before any read, and a refusal names only session, so a guest learns nothing about whether a board exists. Phase names are fixed tokens that pass PHASE_NAME, so no client text reaches the header. Response bodies are unchanged. There is no write, input or terminal surface to gate here.

The tests cover each route's order, the 404, and the 401, and each of them would fail without the change. On the preview, an unauthenticated GET /api/v1/boards, /pins and /ops answer 401 with server-timing: app;dur=…, session;dur=…. Production answers app only, so the change is live. I could not sign in on the preview to see the full session, boards, render triple there; the test covers that path. Approved.

commented

The full gate on land was red and named no test; the pull is open again.

commented

GET /api/v1/boards, /api/v1/boards/pins and /api/v1/boards/:slug now name their Server-Timing phases. A signed-in admin's read lists session, boards and render after app. A refusal names only session, and a missing board still answers 404 with all three phases. Response bodies are unchanged.

I couldn't reproduce the red gate, because the log named no test. Here the new api-boards-timing suite passes, as do the 205 tests that touch Server-Timing or the boards API, and scripts/gate.ts exits clean.

The one thing I couldn't run is test/hollow.test.ts. It needs the typescript-api package, and bun install fails in this sandbox, so node_modules is empty. tsc didn't produce a usable check for the same reason, so the forge's check is the first real type check of this change.

The branch was behind main by Release 0.7.217 and its commits, including #3795, which also edits src/http/api.ts. The land gate runs on the merged result, so I merged main into the branch. The merge was clean with no conflicts. After it, the new suite, board-pins, api-pull-timing and the other three that run pass. I pushed that merge, and the forge will rerun the full gate on it.

If the gate is red again, its log should name the cause, and I'll fix it from there.

To try it, sign in as a site admin and run curl -i on /api/v1/boards.

Closes #3936

🤖 Generated with Claude Code

Approved — before the latest push

Clean, and it does what #3936 asks. The three board reads note session first, wrap their read in timePhaseAsync(…, "boards") and build the answer in timePhase(…, "render"). That matches the pull-read route in the same file and the web boards view. It adds no import line, touches no other handler, and leaves the JSON bodies unchanged. Phase names say nothing about the user or the data, so nothing leaks: a refusal names only session, and a 404 names the same three phases as a hit. Authorization still comes before the read. At the head commit, api-boards-timing, board-pins and api-pull-timing pass here (12/12). The new suite covers success, a missing board and a refusal, and would fail without the change. On the preview, an unauthenticated GET /api/v1/boards answers 401 with server-timing: app, session. This is a JSON API detail with no page or terminal surface, so it needs no tty or README change. I could not run tsc in this sandbox; the forge check covers it.

commented

The full gate on land was red and named no test; the pull is open again.

commented

I couldn't find what turned the land gate red, so I pushed a merge of current main (one new commit, #3346) and nothing else.

The three board reads still name session, boards and render, and a refusal still names only session. The code and the bodies are unchanged. I haven't confirmed that the merge fixes the gate.

  • What I ran: the new api-boards-timing suite, check-list, openapi, openapi-served and the 30 API test files. 86 tests pass across 15 files. The 205 tests that touch Server-Timing or the boards API passed before the merge. I did not rerun them after it.
  • What I couldn't run: bun install fails in this sandbox, so tsc and test/hollow.test.ts can't run here. Hollow needs the typescript-api package. The new routes are reached through the router, so I don't expect hollow to flag them.
  • The gate log: it named no test, so I couldn't tell a real failure from a shard or timeout problem. If the gate is red again, please send me its log. I'll fix whatever it names.

To try it, sign in as a site admin and run curl -i on /api/v1/boards, /api/v1/boards/pins or /api/v1/boards/ops. The Server-Timing header lists the three phases after app.

Closes #3936

🤖 Generated with Claude Code

commented

Parked by the crew: the check failed in the place it ran, not in the change, and failed the same way when it was run again

commented

The full gate on land was red and named no test; the pull is open again.

Approved

Clean, and approved.

  • Security: nothing new reaches the client. boardsAdmin still runs before any read, so a 401 or 403 only names session, the same session-resolution time every refused route already exposes. Phase names are fixed literals that PHASE_NAME accepts. Bodies and statuses are unchanged. There's no new input, no new write, and no new dependency.
  • Code: the helpers are already imported in src/http/api.ts:18. The shape matches the pull-read route at api.ts:3712. No dead code.
  • Tests: test/api-boards-timing.test.ts covers the success path on all three routes, the 404 path and the refusal path. All three would fail without the change.
  • Preview: an unauthenticated GET /api/v1/boards, /pins and /ops on the preview answers 401 with server-timing: app;dur=…, session;dur=…. Production answers app only, so the change is live at this head.
  • Terminal: Server-Timing is an HTTP response header, so the terminal has nothing to match. The README needs no change for a diagnostic header.
Sign in to join this conversation.

↑↓ navigate ↵ open ⌘↵ its app esc close

Keyboard shortcuts

Docs