Fix #382: cache-class-by-mutability law + guard #389

Merged
crueber merged 2 commits from fix/issue-382 into main 2026-09-12 16:12:08 +00:00
Owner

Supersedes #259 systemic remainder (after #381/#384/#385 merged).

Law: addressability does not decide the cache class — mutability does (07_api.md section 4, DEVIATIONS.md D-API-3). SWR's stale-serve window is only safe for content whose staleness is bounded by ref movement; user-mutable GETs revalidate every read (version ETag keeps 304 economics).

What changed:

  1. New stdlib-only leaf internal/cachepolicy — the five header values + rule doc + Check guard (SWR + version-ETag fails). api + issues/social/releases/pulls/identity alias it; zero literal stragglers.
  2. Per-package cacheclass_test.go contract: every served cacheable GET pinned to its exact class + Check per pair + ExposedTemplates coverage (row or explicit mutation-only set). Break-verified: summary flipped to SWR goes red, revert goes green.
  3. Re-audit: only SWR outside git content is the ref-derived pull diff + unversioned owners/ownerRepos/owners-detailed listings (boundary-documented in section 4). ETag-suffix simplification deferred per the amendment (zero benefit, nonzero churn).
  4. Docs: 07_api section 3 summary line (was stale SWR after #381) + section 4 bullets + Decisions; D-API-3; 01_overview tree row. Client unchanged (data.js invalidate already covers same-view updates).

Verification: gofmt/vet clean; -race green on all 7 touched packages (cachepolicy, api, issues, social, releases, pulls, identity); coverage cachepolicy 100.0%, api 95.3%, issues 96.3%, social 99.5%, releases 99.8%, pulls 97.7%, identity 95.6% (all at/above the 95% gate). No new deps, no client changes, git-content headers byte-identical.

Supersedes #259 systemic remainder (after #381/#384/#385 merged). **Law**: addressability does not decide the cache class — mutability does (07_api.md section 4, DEVIATIONS.md D-API-3). SWR's stale-serve window is only safe for content whose staleness is bounded by ref movement; user-mutable GETs revalidate every read (version ETag keeps 304 economics). **What changed**: 1. New stdlib-only leaf `internal/cachepolicy` — the five header values + rule doc + `Check` guard (SWR + version-ETag fails). api + issues/social/releases/pulls/identity alias it; zero literal stragglers. 2. Per-package `cacheclass_test.go` contract: every served cacheable GET pinned to its exact class + `Check` per pair + `ExposedTemplates` coverage (row or explicit mutation-only set). Break-verified: summary flipped to SWR goes red, revert goes green. 3. Re-audit: only SWR outside git content is the ref-derived pull diff + unversioned owners/ownerRepos/owners-detailed listings (boundary-documented in section 4). ETag-suffix simplification deferred per the amendment (zero benefit, nonzero churn). 4. Docs: 07_api section 3 summary line (was stale SWR after #381) + section 4 bullets + Decisions; D-API-3; 01_overview tree row. Client unchanged (data.js invalidate already covers same-view updates). **Verification**: gofmt/vet clean; -race green on all 7 touched packages (cachepolicy, api, issues, social, releases, pulls, identity); coverage cachepolicy 100.0%, api 95.3%, issues 96.3%, social 99.5%, releases 99.8%, pulls 97.7%, identity 95.6% (all at/above the 95% gate). No new deps, no client changes, git-content headers byte-identical.
07_api.md section 4 grows the systemic remainder of the #280/#381 line:
mutability (not addressability) decides the cache class, stated as law,
with the listings boundary and the ETag-suffix retention note.

New stdlib-only leaf internal/cachepolicy holds the five header values
plus the rule doc plus the Check guard (SWR + version-ETag fails);
internal/api and the issues/social/releases/pulls/identity surfaces
alias it (issues keeps ccThread as an alias) - nothing redeclares.

Per-package cacheclass_test.go pins every served cacheable GET to its
exact class, runs Check on each pair, and covers every ExposedTemplates
entry via row or explicit mutation-only set. Re-audit: only SWR left
outside git content is the ref-derived pull diff and the unversioned
SWR listings (both boundary-documented); ETag-suffix simplification
deferred per the amendment's risk-free-only clause. Client unchanged:
data.js invalidate + mutation reconcile already cover same-view updates.

Decisions: 07_api Decisions, DEVIATIONS.md D-API-3, 01_overview tree row.
Sign in to join this conversation.
No description provided.