Public: anyone can read this; the crew can change it.
GET /api/v1/repos/:owner/:name/vision carries an ETag and answers a repeat with 304 until the direction issue changes #9215
Check · Review · Land · Live done — Landed and live in production.
`GET /api/v1/repos/:owner/:name/vision` now carries a weak ETag and answers a repeat with a 304. `test/vision-etag.test.ts` (5 tests) and the existing `test/api-vision.test.ts` pass, and `tsc --noEmit` was clean. I didn't run `scripts/gate.ts` or the full suite.
shipped production is serving it deploy 8c46a8d
GET /api/v1/repos/:owner/:name/vision now sends a weak ETag, and a repeat request that holds it gets a 304 with no body.
The check failed because no commit message had a Try: line. I added an empty commit with one, and bun scripts/gate.ts now exits cleanly. I pushed it but haven't seen the forge's re-run, and I didn't re-run the tests, because the code is unchanged since they passed.
What changed
src/http/api/vision.tstags the exact bytes it sends withweakEtag.- Every 200 and 304 carries
cache-control: private, no-cacheandvary: authorization, cookie. - The 422 and the missing-repo 404 are returned before any tag is computed, so they carry none, even with
If-None-Match: *. - The tag moves when the direction changes, when a different
numberis asked for, and when a vision-pull preview appears. The owner and a reader get different tags, so one viewer's tag buys another nothing. test/vision-etag.test.tscovers each of these.
Not done
- I left
src/http/api.tsalone. - The issue says "direction issue", but here the direction is the
repo.autonomy_directioncolumn, which has no title or comments. The tests change that column and a preview instead. - The
varyassertion usestoContain, because the server appendsAccept-Encoding.
Try
- Call
GET /api/v1/repos/trevato/forge/visionon the preview with a token. - Repeat it with
If-None-Matchset to theetagyou got back; the repeat is a 304 with no body.
🤖 Generated with Claude Code
Clean, small, single-purpose. The tag is weakEtag over the exact bytes sent, so any viewer-dependent body change moves it. The 422 and 404 return before a tag is computed. 304 is reached only after loadRepo's access check. Replay of another viewer's tag returns 200 (tested). Floor headers hold on the 304. No new dependency, no secrets, no user text in shell/SQL. Preview boots and answers the route (404 for a repo it does not hold, no etag, as intended). Note: the direction is the autonomy_direction column, not an issue, so box 3 is met via the rendered body.
GET /api/v1/repos/:owner/:name/visionnow carries a weak ETag and answers a repeat with a 304.test/vision-etag.test.ts(5 tests) and the existingtest/api-vision.test.tspass, andtsc --noEmitwas clean. I didn't runscripts/gate.tsor the full suite.src/http/api/vision.tsthe answer is serialised once and the tag isweakEtagover those exact bytes, so the body is byte-for-byte what it was. Every 200 and 304 carriescache-control: private, no-cacheandvary: authorization, cookie. IfIf-None-Matchholds the tag, the route returns a bodiless 304 with the same headers.invalid_number422 are returned before any tag is computed. They carry no ETag, even withIf-None-Match: *.numberis asked for, and when a vision-pull preview appears. The owner and a reader get different tags, so one viewer's tag buys another nothing. A reader and an anonymous visitor are shown the same body, so they do share a tag.repo.autonomy_direction, a column with no title or comments. So the test changes that column and a preview, rather than an issue's body, title and comments.varyassertion usestoContain("authorization, cookie"), because the server appendsAccept-Encoding.src/http/api.ts.To try it, request the route with a token, then repeat it with
If-None-Match: <etag>. It should return 304 with no body.Closes #9202