edge: correct the X-Carlos-Version freshness comment — cache hits can lag
Review caught the prior comment overclaiming "can't go stale": that's true only for uncached responses. A cache hit answers from GetFor/writeCached before the wrapped handler ever runs, replaying whatever header maybeStore froze at store time, for up to DefaultCacheMaxTTL or until a Carlos-Purge — Reload never purges e.cache. Comment-only fix; documents the true contract (fresh uncached, TTL-bounded lag on a hit, fails safe since a stale entry can only read as the OLD version, never false-positive as the new one).
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
1 file changed,
+16
−3
internal/edge/edge.go+16 −3
diff --git a/internal/edge/edge.go b/internal/edge/edge.go| index 5f5f873a3..ad2df5014 100644 |
| --- a/internal/edge/edge.go |
| +++ b/internal/edge/edge.go |
| @@ -298,9 +298,22 @@ func (e *Edge) Reload() error { |
| // The deploy watch's proof and the human "verify with the binary you |
| // built" tell (carlos-deploy spec §7): the version this route is |
| // serving, from the row the adopt pass stamps AFTER the restart. |
| - // Server:-header-grade disclosure, ruled public 2026-08-08. Reload |
| - // rebuilds these handlers on every registry change — Fingerprint is |
| - // content-accurate since #15 closed, so the header can't go stale. |
| + // Server:-header-grade disclosure, ruled public 2026-08-08. |
| + // |
| + // Freshness contract: on every UNCACHED response, this is live — |
| + // Reload rebuilds these handlers on every registry change, and |
| + // Fingerprint is content-accurate since #15 closed, so an uncached |
| + // header can't go stale. A CACHE HIT bypasses this handler entirely |
| + // (ServeHTTP's GetFor/writeCached path, ahead of the wrapped proxy) |
| + // and replays whatever header maybeStore froze at store time, so it |
| + // can lag a promote by up to the cache's TTL (clamped to |
| + // DefaultCacheMaxTTL, 5 minutes) or until a Carlos-Purge evicts the |
| + // entry — Reload never purges e.cache. That lag is one-directional |
| + // and fails safe for the watch: a stale entry only ever carries the |
| + // OLD version, so it can read as "not yet" but never false-positive |
| + // as the new one. A watcher that needs the fresh answer within the |
| + // TTL window must bust the cache (e.g. a unique query string). |
| + |
| if t.Version != "" { |
| proxy = versionHeader(t.Version, proxy) |
| } |