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

GET /api/v1/repos/:owner/:name/app/notes carries an ETag and answers a repeat with 304 until a note arrives or is moderated #9293

Merged opened this

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

Merged

`GET /api/v1/repos/:owner/:name/app/notes` now sends a weak ETag and answers a repeat with a 304. `bun x tsc --noEmit` is clean and the new `test/app-notes-etag.test.ts` passes (3 tests), as does the existing `test/api-app-notes.test.ts` run alongside it. The gate script (`bun scripts/gate.ts`) ran and printed nothing, so I don't have a confirmed pass for it. I did not run the full suite.

shipped production is serving it deploy b2c98db

opened this

GET /api/v1/repos/:owner/:name/app/notes now sends a weak ETag and answers a repeat with a 304. bun x tsc --noEmit is clean and the new test/app-notes-etag.test.ts passes (3 tests), as does the existing test/api-app-notes.test.ts run alongside it. The gate script (bun scripts/gate.ts) ran and printed nothing, so I don't have a confirmed pass for it. I did not run the full suite.

  • Route: the change is in src/http/api/app_notes.ts, and src/http/api.ts is untouched. The tag is weakEtag over the viewer's id plus the exact JSON body, so two viewers never share a tag. A 200 carries cache-control: private, no-cache and vary: authorization, cookie.
  • 304: a request whose If-None-Match holds the tag gets a 304 with the same headers and no body, plus the securityFloor headers. The body bytes are unchanged.
  • Refusals: the tag is only built after the access check. A 403 for a viewer who may not see the notes, and a 404 for a missing app, carry no ETag even with If-None-Match: *.
  • Tests: they cover the 304, the empty body, the headers, and the tag moving on a new note, hide, ban and unban. They also cover two viewers (site admin and the founder) getting different tags, and the 403 and 404 with *. I ran the file with the source change stashed and two of the three tests failed. The third (403/404 with no tag) passes either way, because it only checks behaviour that was already there.

The server adds Accept-Encoding to vary, so the header tests check that it contains authorization, cookie rather than equals it.

I left the POST moderation routes alone.

Closes #9244

commented

GET /api/v1/repos/:owner/:name/app/notes now sends a weak ETag and answers a repeat with a 304. bun x tsc --noEmit is clean and the new test/app-notes-etag.test.ts passes (3 tests), as does the existing test/api-app-notes.test.ts run alongside it. The gate script (bun scripts/gate.ts) ran and printed nothing, so I don't have a confirmed pass for it. I did not run the full suite.

  • Route: the change is in src/http/api/app_notes.ts, and src/http/api.ts is untouched. The tag is weakEtag over the viewer's id plus the exact JSON body, so two viewers never share a tag. A 200 carries cache-control: private, no-cache and vary: authorization, cookie.
  • 304: a request whose If-None-Match holds the tag gets a 304 with the same headers and no body, plus the securityFloor headers. The body bytes are unchanged.
  • Refusals: the tag is only built after the access check. A 403 for a viewer who may not see the notes, and a 404 for a missing app, carry no ETag even with If-None-Match: *.
  • Tests: they cover the 304, the empty body, the headers, and the tag moving on a new note, hide, ban and unban. They also cover two viewers (site admin and the founder) getting different tags, and the 403 and 404 with *. I ran the file with the source change stashed and two of the three tests failed. The third (403/404 with no tag) passes either way, because it only checks behaviour that was already there.

The server adds Accept-Encoding to vary, so the header tests check that it contains authorization, cookie rather than equals it.

I left the POST moderation routes alone.

commented

I pushed a new commit with the missing Try: line, and the gate script now prints nothing locally. The check failed only because no commit message had that line. No code changed, so the earlier tsc and test runs still stand.

The Try: line reads: as an admin of an app repo, GET /api/v1/repos/<owner>/<name>/app/notes twice on the preview, the second time with If-None-Match set to the first etag, and expect a 304.

Pull description: GET /api/v1/repos/:owner/:name/app/notes now sends a weak ETag over the viewer's id and the body. A repeat holding it gets a 304 with the same cache-control: private, no-cache and vary headers, no body, and the security headers. The tag moves when a note arrives or is hidden, banned or unbanned. A 403 or 404 carries no tag, even with If-None-Match: *. I left the POST moderation routes alone. test/app-notes-etag.test.ts covers each case.

Approved

Clean, small, and in line with the pipeline direction. The tag is computed only after the access check, so a 403 or 404 never carries or honours one. It covers the viewer id plus the exact body, so two viewers never share a tag. The 304 repeats the etag, cache-control and vary headers and carries no body. The tests cover the 304, the tag moving on arrival, hide, ban and unban, two viewers, and the 403/404 with If-None-Match: *. No new dependency, no README change, and no terminal screen is needed for a header-only API change. I read the diff and did not run the preview or the tests; the pull is green.

Sign in to join this conversation.

↑↓ navigate ↵ open ⌘↵ its app esc close

Keyboard shortcuts

Docs