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

GET /api/v1/releases?shipped=true carries an ETag and answers a repeat with 304 until something new goes live #9135

Merged opened this

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

Merged

`GET /api/v1/releases` now carries a weak ETag on both lists, and a repeat that sends `If-None-Match` gets a 304 with no body.

shipped production is serving it deploy d480d55

opened this

GET /api/v1/releases now carries a weak ETag on both lists, and a repeat that sends If-None-Match gets a 304 with no body.

The tag is computed from the exact JSON sent, using weakEtag and holds from src/http/etag.ts. tsc and scripts/gate.ts are clean, and the tests in test/api-releases.test.ts, test/mcp-releases.test.ts, test/changelog-api.test.ts and test/admin-gate.test.ts pass. I did not run the full suite; the forge's check does that on the push.

  • ?shipped=true (with or without repo) answers cache-control: public, max-age=60.
  • Kept releases (no shipped) answer cache-control: private, no-cache and vary: authorization, cookie. The server adds Accept-Encoding to that vary, so the test only checks the start of the header.
  • Refusals: access is checked before tags are compared, so a reader who is now refused gets the 403 even when holding a valid tag. A 403 or a 422 for an invalid shipped carries no tag.
  • OpenAPI: the route description in getApiV1Releases.ts names the etag header and the 304, and the route lists 304 under alsoStatus.
  • Tests: new cases in test/api-releases.test.ts check 200 then 304 on each list. They also check that a refused reader never gets a 304, that recording a new release changes the kept-releases tag, and that an invalid shipped has no tag.

I did not add an assertion that the shipped-list tag itself changes when a new release ships. The test only checks the kept-releases tag. If you want the shipped case covered, say so.

To try it: curl -i "$URL/api/v1/releases?shipped=true", then repeat with -H 'if-none-match: <etag>' to get the 304.

🤖 Generated with Claude Code

Closes #9129

commented

GET /api/v1/releases now carries a weak ETag on both lists, and a repeat that sends If-None-Match gets a 304 with no body.

The tag is computed from the exact JSON sent, using weakEtag and holds from src/http/etag.ts. tsc and scripts/gate.ts are clean, and the tests in test/api-releases.test.ts, test/mcp-releases.test.ts, test/changelog-api.test.ts and test/admin-gate.test.ts pass. I did not run the full suite; the forge's check does that on the push.

  • ?shipped=true (with or without repo) answers cache-control: public, max-age=60.
  • Kept releases (no shipped) answer cache-control: private, no-cache and vary: authorization, cookie. The server adds Accept-Encoding to that vary, so the test only checks the start of the header.
  • Refusals: access is checked before tags are compared, so a reader who is now refused gets the 403 even when holding a valid tag. A 403 or a 422 for an invalid shipped carries no tag.
  • OpenAPI: the route description in getApiV1Releases.ts names the etag header and the 304, and the route lists 304 under alsoStatus.
  • Tests: new cases in test/api-releases.test.ts check 200 then 304 on each list. They also check that a refused reader never gets a 304, that recording a new release changes the kept-releases tag, and that an invalid shipped has no tag.

I did not add an assertion that the shipped-list tag itself changes when a new release ships. The test only checks the kept-releases tag. If you want the shipped case covered, say so.

To try it: curl -i "$URL/api/v1/releases?shipped=true", then repeat with -H 'if-none-match: <etag>' to get the 304.

🤖 Generated with Claude Code

commented

The preview deploy didn't fail because of my change, so I changed nothing and pushed nothing.

  • The log shows a good deploy. It ends with ready, serving and done for https://lab--9135--forge-trevato-apps.open-platform.sh, and / answers 200.
  • The new behaviour is live there. GET /api/v1/releases?shipped=true returns etag: W/"3b57wutsov8xj" and cache-control: public, max-age=60.
  • "No tests declared, none run" is not a failure. forge.json has no app.test, so the preview deploy runs no tests. Tests belong to the check block, which runs on each push.
  • Local checks passed before the push. The type check and scripts/gate.ts were clean. The release tests I ran were test/api-releases.test.ts, test/mcp-releases.test.ts, test/changelog-api.test.ts and test/admin-gate.test.ts. I did not run the full suite, so the forge's check log is still the verdict.

I won't invent a test entry in forge.json to quiet that line. If the deploy is meant to be red, send me the actual error.

commented

GET /api/v1/releases now sends an ETag and answers a repeat request that carries it with 304, until something new goes live.

The failing check was a commit-message rule, not the code. A pull that changes src/http/api/releases.ts needs a Try: line in one of its commit messages. I added an empty commit with that line and pushed, so no code changed. I did not re-run the tests or the gate locally. The forge's check will run on this push.

Try: curl -si -H "authorization: Bearer $FORGE_TOKEN" https://lab--9135--forge-trevato-apps.open-platform.sh/api/v1/releases. Then repeat the request with If-None-Match set to the ETag it returned, and expect 304.

🤖 Generated with Claude Code

Changes requested — before the latest push

Code is sound: tag from the exact bytes, access checked before the tag compare, 403/422 carry no tag, OpenAPI names etag and 304. One miss: box 3 asks that recording a new shipped release gives 200 with a new tag, and the test only proves it for the kept list (as the builder admitted). Fix: in test/api-releases.test.ts, after recordRelease, fetch ?shipped=true again with the first shipped etag in If-None-Match and expect 200 and a different etag (if shipped output does not reflect recordRelease, make the test arrange whatever shippedAnswer reads, so the shipped tag demonstrably changes). No other changes needed.

commented

test/api-releases.test.ts now proves the ?shipped=true tag changes when a new pull merges.

I reworked the arrangement you suggested. recordRelease does not reach the shipped output, because shippedAnswer reads merged pull rows, not recorded releases. So the test inserts a merged pull on the public repo instead. It then requests ?shipped=true with the earlier shipped etag in If-None-Match. It expects a 200 and a different etag. The kept-list check after recordRelease is unchanged.

bun test test/api-releases.test.ts passes (7 tests), bun x tsc --noEmit is clean, and bun scripts/gate.ts printed nothing. I did not run the rest of the suite locally; the forge's check does that on this push.

The change is test-only. The commit carries a Try: line for the gate.

Try: curl -si https://lab--9135--forge-trevato-apps.open-platform.sh/api/v1/releases?shipped=true. Then repeat it with If-None-Match set to the returned ETag and expect 304.

🤖 Generated with Claude Code

Approved

The earlier ask, a test that the ?shipped=true tag changes when a new pull merges, is met: the test inserts a merged pull and expects 200 with a new tag. The etag comes from the JSON sent, access is checked before the tags are compared, a 403 or 422 carries no tag, the cache headers match the issue, and OpenAPI names the etag and 304. I read the diff and the etag helpers; I did not run the tests or fetch the preview this round.

Sign in to join this conversation.

↑↓ navigate ↵ open ⌘↵ its app esc close

Keyboard shortcuts

Docs