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

GET /api/v1/admin/drills carries an ETag and answers a repeat with 304 until a drill runs or its result changes #9233

Merged opened this

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

Merged

`GET /api/v1/admin/drills` now carries a weak ETag, and a repeat holding it gets a 304 until a drill's recorded result changes. The new test and the existing `test/api-admin-drills.test.ts` pass (8 tests), and `tsc` and `scripts/gate.ts` are clean. I did not run the full suite; the forge runs it on push. I also did not call the `keep_plan` tool, so there is no plan on the issue.

shipped production is serving it deploy 78f82e5

opened this

GET /api/v1/admin/drills now carries a weak ETag, and a repeat holding it gets a 304 until a drill's recorded result changes. The new test and the existing test/api-admin-drills.test.ts pass (8 tests), and tsc and scripts/gate.ts are clean. I did not run the full suite; the forge runs it on push. I also did not call the keep_plan tool, so there is no plan on the issue.

  • What changed: src/http/api/drills.ts now serialises the body once. The ETag comes from weakEtag over those exact bytes, so the body is byte-for-byte what it was. Both the 200 and the 304 carry etag, cache-control: private, no-cache and vary: authorization, cookie. The 304 has no body and keeps the securityFloor headers. src/http/api.ts is untouched.
  • Access check: the tag is computed only after the person-admin check. No session (401), a non-admin member (403) and an agent admin (403) answer as before with no ETag, even with If-None-Match: *.
  • When the tag moves: it moves when a drill result is recorded, which is the only state the body shows. The body has no "running" field, so a drill that has started but not finished does not change it.
  • Viewers: every viewer allowed through gets the same body, so two admins share a tag. That is correct, since the tag follows the bytes. The issue's "two viewers shown different bodies never share an etag" can't arise here, and the test shows two admins sharing a tag.
  • Tests: test/drills-etag.test.ts covers the headers and floor on the 200 and the 304, the tag moving after each of two recorded drills, a second admin matching the tag, and the 401/403 cases with If-None-Match: *.

To try it, fetch /api/v1/admin/drills as a person admin with a bearer token, then repeat with If-None-Match set to the returned etag. That repeat is a 304.

Closes #9205

commented

GET /api/v1/admin/drills now carries a weak ETag, and a repeat holding it gets a 304 until a drill's recorded result changes. The new test and the existing test/api-admin-drills.test.ts pass (8 tests), and tsc and scripts/gate.ts are clean. I did not run the full suite; the forge runs it on push. I also did not call the keep_plan tool, so there is no plan on the issue.

  • What changed: src/http/api/drills.ts now serialises the body once. The ETag comes from weakEtag over those exact bytes, so the body is byte-for-byte what it was. Both the 200 and the 304 carry etag, cache-control: private, no-cache and vary: authorization, cookie. The 304 has no body and keeps the securityFloor headers. src/http/api.ts is untouched.
  • Access check: the tag is computed only after the person-admin check. No session (401), a non-admin member (403) and an agent admin (403) answer as before with no ETag, even with If-None-Match: *.
  • When the tag moves: it moves when a drill result is recorded, which is the only state the body shows. The body has no "running" field, so a drill that has started but not finished does not change it.
  • Viewers: every viewer allowed through gets the same body, so two admins share a tag. That is correct, since the tag follows the bytes. The issue's "two viewers shown different bodies never share an etag" can't arise here, and the test shows two admins sharing a tag.
  • Tests: test/drills-etag.test.ts covers the headers and floor on the 200 and the 304, the tag moving after each of two recorded drills, a second admin matching the tag, and the 401/403 cases with If-None-Match: *.

To try it, fetch /api/v1/admin/drills as a person admin with a bearer token, then repeat with If-None-Match set to the returned etag. That repeat is a 304.

commented

No code change is needed, and I pushed nothing. The preview deploy didn't fail: it booted, / answered, and the log ends done: https://lab--9233--forge-trevato-apps.open-platform.sh.

The line "no tests declared, none run" only says the preview deploy runs no tests. forge.json has no test command under app, because this repo runs its tests through the check block on each push. That is how the repo was set up before my change, so I left it alone.

The tests I ran locally are the new test/drills-etag.test.ts and test/api-admin-drills.test.ts, and both pass. bun x tsc --noEmit and scripts/gate.ts were clean. The forge's check runs against pull #9233 and its verdict is what lands it. I haven't seen that verdict. If it fails, send me its log.

commented

The check failed because no commit message had a "Try:" line. I added an empty commit that has one and pushed it (2703aa0a). The local gate (scripts/gate.ts) printed nothing when I ran it, and I read that as passing. I haven't seen the forge's re-run of the check on the new push.

The line reads: "Try: GET /api/v1/admin/drills as a person admin with a bearer token, then repeat with If-None-Match set to the returned etag and see a bodiless 304".

The code is unchanged, so the tests I ran earlier still stand.

Approved

Clean. The tag is a weakEtag over the exact bytes sent and is computed only after the person-admin check, so the 401 and 403 carry no ETag. The 200 and the 304 both carry etag, private no-cache and vary. The 304 has no body and keeps the floor headers. The tests cover each of these. Preview answers 401 without an admin token, as expected. The body has no running field, so a drill that has started but not finished cannot move the tag; the tag follows what the body shows, which is right.

Sign in to join this conversation.

↑↓ navigate ↵ open ⌘↵ its app esc close

Keyboard shortcuts

Docs