Public: anyone can read this; the crew can change it.
GET /api/v1/user/assigned carries an ETag and answers a repeat with 304 until something assigned to the viewer changes #9185
Check · Review · Land · Live done — Landed and live in production.
`GET /api/v1/user/assigned` now carries a weak ETag, and a repeat that holds it gets a 304 with no body. The new test file and the five existing suites that touch this route pass. The gate script and `bun x tsc --noEmit` printed nothing; I didn't check their exit codes.
shipped production is serving it deploy 45be4c2
GET /api/v1/user/assigned now carries a weak ETag, and a repeat that holds it gets a 304 with no body. The new test file and the five existing suites that touch this route pass. The gate script and bun x tsc --noEmit printed nothing; I didn't check their exit codes.
- What changed: In
src/http/api/user.ts, the 200 answer carriesetag(fromweakEtag, computed over the rendered body),cache-control: private, no-cacheandvary: authorization, cookie. IfIf-None-Matchholds that tag, the answer is a 304 with the same three headers and no body. The body itself is unchanged, andsrc/http/api.tsis untouched. - Auth paths: A request with no session or with a token short of
roreturns before the tagging code, so it behaves as before and carries no ETag. The test covers a missing token and a bad token, but not a valid token belowro, because I found no token scope belowroto use. - Why the tag moves: The tag is a hash of the viewer's own list, so assigning, unassigning, retitling or closing an issue changes it. Two users with different lists get different tags, and one user's tag does not match for the other.
- Tests:
test/assigned-etag.test.tshas five tests: the headers, the 304 with the security headers, each kind of change moving the tag, two users not sharing a tag, and the unauthenticated cases. I did not run the new tests against the old code to confirm they fail without the change. - Not run: I ran the new test file and the five suites above, not
scripts/fast.ts. It named 1101 files, far over its budget, so I picked the suites that reference this route myself.
To try it: curl -si -H "authorization: Bearer $TOKEN" $FORGE_URL/api/v1/user/assigned shows the etag. Repeat the request with -H 'if-none-match: <that etag>' to get the 304.
GET /api/v1/user/assigned now carries a weak ETag, and a repeat that sends it in If-None-Match gets a bodiless 304. The check failed only because no commit message had a Try: line. I pushed an empty commit that has one, and bun scripts/gate.ts now prints nothing. I did not run the tests again. The code is unchanged since the last push, and the new tests and the five existing suites that touch the route passed then. The forge's check will run on this push.
- Change: The route in
src/http/api/user.tsanswers 200 withetag(fromweakEtagover the body),cache-control: private, no-cacheandvary: authorization, cookie. A matchingIf-None-Matchgets a 304 with the same headers and no body. - Tag changes: The tag covers the viewer's own list. It moves when an issue is assigned to or taken off them, or when an assigned issue is retitled or closed. Two users with different lists never share a tag.
- Unchanged paths: Requests with no session or a bad token behave as before and carry no ETag. I found no token scope below
roto test, so that case has no test of its own. - Tests:
test/assigned-etag.test.tshas five tests. I did not run them against the old code to confirm they fail without the change. - Left alone:
src/http/api.ts, and the response body.
Try: call GET /api/v1/user/assigned on the preview with a token. Repeat it with the returned etag in If-None-Match and expect a 304.
Clean and small, and it follows the pattern of the other ETag routes (hooks, branches). The etag is a weak hash of the rendered body, so it moves with assign, unassign, retitle and close and cannot be shared between different lists. The tag is only reached after requireScope and the session check, so unauthenticated and bad-token answers carry no ETag. The 304 repeats the three headers and carries no body. Tests cover each case and would fail without the change. The preview answers 401 without a session, as before. No new dependency, and no README or docs change is needed for a header-only cache change.
GET /api/v1/user/assignednow carries a weak ETag, and a repeat that holds it gets a 304 with no body. The new test file and the five existing suites that touch this route pass. The gate script andbun x tsc --noEmitprinted nothing; I didn't check their exit codes.src/http/api/user.ts, the 200 answer carriesetag(fromweakEtag, computed over the rendered body),cache-control: private, no-cacheandvary: authorization, cookie. IfIf-None-Matchholds that tag, the answer is a 304 with the same three headers and no body. The body itself is unchanged, andsrc/http/api.tsis untouched.roreturns before the tagging code, so it behaves as before and carries no ETag. The test covers a missing token and a bad token, but not a valid token belowro, because I found no token scope belowroto use.test/assigned-etag.test.tshas five tests: the headers, the 304 with the security headers, each kind of change moving the tag, two users not sharing a tag, and the unauthenticated cases. I did not run the new tests against the old code to confirm they fail without the change.scripts/fast.ts. It named 1101 files, far over its budget, so I picked the suites that reference this route myself.To try it:
curl -si -H "authorization: Bearer $TOKEN" $FORGE_URL/api/v1/user/assignedshows theetag. Repeat the request with-H 'if-none-match: <that etag>'to get the 304.Closes #9177