A child forge asks its parent for GET /releases.json (releasesJson in src/web/standards.ts) every FRESH_MS (10 minutes, src/core/parent_releases.ts), and downloads the whole list every time, although the list changes only when the parent ships a release.
Done:
[ ] /releases.json answers with a strong ETag: a hash of the body, computed once per origin and kept, since the releases come from a file loaded at boot. A matching If-None-Match answers 304 with no body and the same cache-control.
[ ] src/core/parent_releases.ts keeps the ETag beside its copy and sends it as If-None-Match. A 304 counts as a fresh fetch: fetchedAt moves and the copy is unchanged. A 200 replaces both the copy and the ETag. A missing or malformed ETag is ignored.
[ ] test/standards.test.ts covers two cases: an ETag on the 200, and a 304 on a match. test/parent-releases-idle.test.ts, or a new test, shows a child that gets a 304 keeps its releases and moves fetchedAt. Each test fails without the change.
Files: src/web/standards.ts, src/core/parent_releases.ts, test/standards.test.ts, test/parent-releases-idle.test.ts.
Risk: a stored ETag that is never cleared could hide a new release. A 200 always replaces it, and nothing but the parent's answer sets it.
A child forge asks its parent for
GET /releases.json(releasesJsoninsrc/web/standards.ts) everyFRESH_MS(10 minutes,src/core/parent_releases.ts), and downloads the whole list every time, although the list changes only when the parent ships a release.Done:
/releases.jsonanswers with a strongETag: a hash of the body, computed once per origin and kept, since the releases come from a file loaded at boot. A matchingIf-None-Matchanswers304with no body and the samecache-control.src/core/parent_releases.tskeeps the ETag beside its copy and sends it asIf-None-Match. A304counts as a fresh fetch:fetchedAtmoves and the copy is unchanged. A200replaces both the copy and the ETag. A missing or malformed ETag is ignored.test/standards.test.tscovers two cases: an ETag on the 200, and a 304 on a match.test/parent-releases-idle.test.ts, or a new test, shows a child that gets a 304 keeps its releases and movesfetchedAt. Each test fails without the change.Files: src/web/standards.ts, src/core/parent_releases.ts, test/standards.test.ts, test/parent-releases-idle.test.ts. Risk: a stored ETag that is never cleared could hide a new release. A 200 always replaces it, and nothing but the parent's answer sets it.