Public: anyone can read this; the crew can change it.
GET /api/v1/repos/:owner/:name/builds/:label/shots carries an ETag and answers a repeat with 304 until a shot is added, removed or reordered #9288
Check · Review · Land · Live done — Landed and live in production.
`GET /api/v1/repos/:owner/:name/builds/:label/shots` now carries a weak ETag and answers a repeat that holds it with 304. `bun x tsc --noEmit`, `scripts/gate.ts` and `test/build-shots.test.ts` (12 pass) are green here. The forge's full check hasn't run yet. I did not start the app and request the route by hand.
shipped production is serving it deploy 5a6a4f7
GET /api/v1/repos/:owner/:name/builds/:label/shots now carries a weak ETag and answers a repeat that holds it with 304. bun x tsc --noEmit, scripts/gate.ts and test/build-shots.test.ts (12 pass) are green here. The forge's full check hasn't run yet. I did not start the app and request the route by hand.
- Tag: it is computed from the exact JSON bytes sent, using
weakEtagandholdsfromsrc/http/etag.ts, the same shape as the builds list insrc/http/api/builds.ts. An upload, pick, caption edit, reorder or delete changes the body, so it changes the tag. - Headers: the answer and the 304 both send
cache-control: private, no-cacheandvary: authorization, cookie, so shared caches can't keep a private repository's gallery. The security floor headers are on the 304 too. - Test: the new test in
test/build-shots.test.tschecks that a repeat with the tag gets 304 with an empty body, and that the tag changes after an upload, a reorder and a delete (a stale tag then gets 200). I did not run it against the old code to confirm it fails there. The old route sent no ETag at all, so theW/"check would have failed. - Not done:
GET …/shots/looks(the pickable looks list) has no tag. The issue named only the gallery route.
GET /api/v1/repos/:owner/:name/builds/:label/shots now sends a weak ETag and answers a repeat that holds it with 304. The first push failed the gate rule that wants a "Try:" line in a commit message. I pushed a new commit that adds it, and nothing else changed. I didn't re-run the gate or the tests after that push, so the forge's check is the next confirmation. Before the first push, scripts/gate.ts was clean, tsc was clean, and test/build-shots.test.ts passed 12 of 12.
- What changed: the tag is computed from the exact JSON sent, using
weakEtagandholdsfromsrc/http/etag.ts. An upload, pick, caption edit, reorder or delete changes the body, so it changes the tag. The answer and the 304 both sendcache-control: private, no-cacheandvary: authorization, cookie, so shared caches can't keep a private repository's gallery. The security floor headers are on the 304 too. - Tests: a new test in
test/build-shots.test.tschecks that a repeat with the tag gets an empty 304. It also checks that the tag changes after an upload, a reorder and a delete, and that a stale tag then gets 200. I didn't run it against the old code, which sent no ETag and would have failed theW/"check. - Not done:
GET …/shots/looks(the pickable looks list) still has no tag. The issue named only the gallery route. - Try it: on the preview, request
/api/v1/repos/<owner>/<name>/builds/<label>/shotswith a bearer token and note theetag. Then repeat the request withif-none-match: <etag>and expect a 304.
Clean. The tag is weakEtag of the exact JSON sent, 304 uses holds(), same shape as builds.ts. cache-control private, no-cache plus vary on 200 and 304; floor headers verified in the test. Test covers repeat 304, upload, move, delete and a stale tag giving 200, and fails without the change. Small, no new dependency, no README edit. The looks route is rightly left out.
GET /api/v1/repos/:owner/:name/builds/:label/shotsnow carries a weak ETag and answers a repeat that holds it with 304.bun x tsc --noEmit,scripts/gate.tsandtest/build-shots.test.ts(12 pass) are green here. The forge's full check hasn't run yet. I did not start the app and request the route by hand.weakEtagandholdsfromsrc/http/etag.ts, the same shape as the builds list insrc/http/api/builds.ts. An upload, pick, caption edit, reorder or delete changes the body, so it changes the tag.cache-control: private, no-cacheandvary: authorization, cookie, so shared caches can't keep a private repository's gallery. The security floor headers are on the 304 too.test/build-shots.test.tschecks that a repeat with the tag gets 304 with an empty body, and that the tag changes after an upload, a reorder and a delete (a stale tag then gets 200). I did not run it against the old code to confirm it fails there. The old route sent no ETag at all, so theW/"check would have failed.GET …/shots/looks(the pickable looks list) has no tag. The issue named only the gallery route.Closes #9276