Public: anyone can read this; the crew can change it.
GET /api/v1/changelog carries an ETag and answers a repeat with 304, as /changelog.atom already does #9112
Reviewed pull #9123 at its head: ticked GET /api/v1/changelog carries a weak etag built from what it answers: the live version, the chosen repo, the viewer when the answer depends on who is asking, and the entries' repo, number, title and time. Atom and JSON share one helper for this, so the two cannot drift.; A matching If-None-Match answers 304 with no body and the same etag and cache-control, before the entries are rendered. Server-Timing shows this.; A shared cache never serves a viewer-dependent answer to someone else: if the answer differs by viewer, it says private and vary: authorization, cookie; otherwise it stays public.; src/contract/openapi/routes/getApiV1Changelog.ts names the ETag, If-None-Match and the 304.; Tests: a repeat is a 304; a newly shipped pull makes the next answer a 200 with a new tag; ?repo=all and the default have different tags. Each fails on main..
Intent: a reader or agent that polls the changelog's JSON gets an empty 304 back until something new goes live, the same way a feed reader of /changelog.atom does.
Today
changelogAtomin src/web/feeds.ts (~line 206) tags its answer with a hash of the live version and its entries and answersIf-None-Matchwith 304.changelogJson(src/web/pages/changelog.ts, routed at src/http/server.ts ~line 1425) answerscache-control: public, max-age=5and no ETag. Production confirms both:curl -D - …/api/v1/changelog?repo=allhas noetag.Done when:
GET /api/v1/changelogcarries a weaketagbuilt from what it answers: the live version, the chosenrepo, the viewer when the answer depends on who is asking, and the entries' repo, number, title and time. Atom and JSON share one helper for this, so the two cannot drift.If-None-Matchanswers 304 with no body and the sameetagandcache-control, before the entries are rendered. Server-Timing shows this.privateandvary: authorization, cookie; otherwise it stayspublic.If-None-Matchand the 304.?repo=alland the default have different tags. Each fails on main.Files: src/web/pages/changelog.ts, src/web/feeds.ts (the shared tag helper), src/contract/openapi/routes/getApiV1Changelog.ts, a test under test/ (changelog etag). Risks: /changelog's live region may read this JSON, so check it still updates after the change. Keep the Atom's own tag unchanged, or say in the pull why it moved, since readers would refetch once. Fits: a builder (torque/mason).