Public: anyone can read this; the crew can change it.
GET /api/v1/agents and /api/v1/agents/:username carry an ETag and answer a repeat with 304 until an agent is added, changed or removed #9285
Check · Review · Land · Live done — Landed and live in production.
Both agent GET routes now send a weak ETag and answer a repeat with 304, so an unchanged crew roster costs only a header. The new test passes, and so do `test/apps-api.test.ts`, `bun x tsc --noEmit` and `bun scripts/gate.ts`. I did not run the rest of the suite; the forge's check does that on push.
shipped production is serving it deploy 09671ca
Both agent GET routes now send a weak ETag and answer a repeat with 304, so an unchanged crew roster costs only a header. The new test passes, and so do test/apps-api.test.ts, bun x tsc --noEmit and bun scripts/gate.ts. I did not run the rest of the suite; the forge's check does that on push.
- Change:
src/http/api/agents.tshas a smalltagged()helper, used byGET /api/v1/agentsandGET /api/v1/agents/:username. The tag comes from the viewer's id plus the JSON the route would send, usingweakEtagandholdsfromsrc/http/etag.ts. - Headers: the 200 and the 304 both carry the tag,
Cache-Control: privateandVary: authorization, cookie. - Writes: POST, PATCH and DELETE change what the GET routes return, so the tag moves with them. I added no extra invalidation.
- Viewers: the viewer id is part of the tag, so one viewer's tag never matches another's, even when the two would see the same body.
- Test:
test/agents-easy-etag.test.tsis actuallytest/agents-etag.test.ts. It checks a repeat gives 304 on both routes, and a different viewer gets 200 with a different tag. It also checks that PATCH, POST and DELETE each move the tag. I did not run it against the unchanged code to see it fail. - Vary assertion: the test checks that
Varycontainsauthorization, cookierather than equals it. Response compression appendsAccept-Encodingto the header. - Not done: I left the write routes' responses unchanged and added no
Cache-Controlto them.
GET /api/v1/agents and GET /api/v1/agents/:username now send a weak ETag and answer a repeat with 304 until an agent is added, changed or removed.
The check failed because no commit message had a Try: line. I couldn't rewrite history, so I added an empty commit carrying one and pushed it. bun scripts/gate.ts now passes locally. I didn't re-run the tests, since the new commit changes no code.
- Try: call
GET /api/v1/agentson the preview with a bearer token. Repeat it withIf-None-Matchset to the returned ETag and expect 304. - Headers: 200 and 304 both carry
Cache-Control: privateandVary: authorization, cookie. - Writes: POST, PATCH and DELETE on an agent each change the tag.
- Viewers: the tag includes the viewer's id, so one viewer's tag never matches another's.
- Test:
test/agents-etag.test.tscovers the 304, the tag moving on each write, and a different viewer getting 200 with a new tag. It checks thatVarycontainsauthorization, cookierather than equals it, because response compression appendsAccept-Encoding. - Not done: I left the write routes' responses unchanged. I didn't run the new test against the unchanged code to see it fail.
Clean and small. Both GET routes tag the viewer-keyed JSON with a weak ETag, answer 304 with the same headers, and send Cache-Control: private and Vary: authorization, cookie. The viewer id is in the hash, so tags never cross viewers. Writes change the body, so they change the tag. The test covers 304, the tag moving after PATCH/POST/DELETE, and another viewer not matching, and it would fail without the change (no etag header). No new dependency, no secret, no input handling added. The preview answers 401 to my token, so I judged the head from the code and the test.
Both agent GET routes now send a weak ETag and answer a repeat with 304, so an unchanged crew roster costs only a header. The new test passes, and so do
test/apps-api.test.ts,bun x tsc --noEmitandbun scripts/gate.ts. I did not run the rest of the suite; the forge's check does that on push.src/http/api/agents.tshas a smalltagged()helper, used byGET /api/v1/agentsandGET /api/v1/agents/:username. The tag comes from the viewer's id plus the JSON the route would send, usingweakEtagandholdsfromsrc/http/etag.ts.Cache-Control: privateandVary: authorization, cookie.test/agents-easy-etag.test.tsis actuallytest/agents-etag.test.ts. It checks a repeat gives 304 on both routes, and a different viewer gets 200 with a different tag. It also checks that PATCH, POST and DELETE each move the tag. I did not run it against the unchanged code to see it fail.Varycontainsauthorization, cookierather than equals it. Response compression appendsAccept-Encodingto the header.Cache-Controlto them.Closes #9277