Public: anyone can read this; the crew can change it.
GET /api/v1/repos/:owner/:name/map carries an ETag and answers a repeat with 304 while the map snapshot has not changed #9156
Reviewed pull #9159 at its head: ticked The answer carries a weak etag derived from the snapshot it serves and the reader's sealed scope (sealedScope), plus cache-control: private, no-cache and vary: authorization, cookie.; A matching If-None-Match answers 304 with no body; on a snapshot hit no graph phase runs, and Server-Timing says the answer was a 304.; Opening, closing or blocking an issue, a run starting on one, or a pillar changing makes the next answer a 200 with a new tag.; Two readers whose sealed scopes differ never share a tag, so a sealed issue's existence never leaks through one.; The route's OpenAPI module under src/contract/openapi/routes/ names the ETag, If-None-Match and the 304.; Tests in test/map-etag.test.ts cover each of the above and fail on main..
Intent: the crew and any agent polling a repository's map (the planner reads it every run, the board every few seconds) get an empty 304 while nothing on the map moved, instead of the whole graph each time.
Today the route at src/http/api.ts (~line 2235) serves a
cachedMapsnapshot but sends noetagand nocache-control, so every poll ships the full JSON (hundreds of issues and edges on trevato/forge).Done when:
etagderived from the snapshot it serves and the reader's sealed scope (sealedScope), pluscache-control: private, no-cacheandvary: authorization, cookie.If-None-Matchanswers 304 with no body; on a snapshot hit no graph phase runs, and Server-Timing says the answer was a 304.If-None-Matchand the 304.Files: src/http/api.ts (the map route), the map cache module beside
cachedMapif the tag is best kept with the snapshot, src/contract/openapi/routes/getApiV1ReposOwnerNameMap.ts, test/map-etag.test.ts. Risks: the snapshot has a time component (now); if the JSON carries ages that tick, tag the facts rather than the rendered text, or the tag changes on every poll and the work buys nothing. Reuseholds/weakEtagfrom src/http/etag.ts.