v0.7.7 — two releases shipped to a browser that never received them
buildStamp()'s no-git fallback was the literal "nogit", and the .s9pk Dockerfile copies the tree in without .git — so git rev-parse fails on every packaged build. That string is also the cache-bust key every module URL carries, so v0.7.4, v0.7.5 and v0.7.6 all published ./web/main.js?v=nogit, byte-identical, and returning browsers refetched nothing. v0.7.5's setup screen and v0.7.6's door fix were both correct and neither arrived. The fallback is now the package version plus the build timestamp, always distinct. And serveStatic sent no Cache-Control at all, which is the other half — a cached play.html pins a player to the whole build it names. A request carrying ?v= is now immutable for a year; everything else is no-cache. ?v= rather than "not HTML" because build-web.ts tags the modules and nothing else. Neither half is sufficient alone. 864 tests pass, two new. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01AdG46Ja2PEDBkpqiDazMoX
This commit is contained in:
co-authored by
Claude Sonnet 5
parent
b4f09f05cb
commit
af68aac78d
@@ -19,6 +19,46 @@ page as `v0.1.0 · <sha> · <date>`, so what is deployed can always be identifie
|
||||
|
||||
---
|
||||
|
||||
## 0.7.7 — 2026-08-30
|
||||
|
||||
### Two releases shipped to a browser that never received them
|
||||
|
||||
Jesse installed v0.7.5, clicked **Play solitaire**, and landed in a dealt game instead of the new
|
||||
setup screen. v0.7.6 diagnosed that as a routing bug, fixed it, installed, verified — and it happened
|
||||
again, identically. The second report is what made the real cause findable: the fix was correct both
|
||||
times and neither one ever reached the browser.
|
||||
|
||||
**`buildStamp()`'s no-git fallback was the literal `nogit`, and the `.s9pk` build has no git.** The
|
||||
Dockerfile copies the working tree in without `.git`, so `git rev-parse` fails there on every
|
||||
packaged build — and that string is not only the visible stamp, it is the cache-bust key every module
|
||||
URL carries. So v0.7.4, v0.7.5 and v0.7.6 all published `./web/main.js?v=nogit`, byte-identical, and
|
||||
a returning player's browser correctly concluded it had the file already. The fallback is now the
|
||||
package version plus the build's own timestamp, which is always distinct and needs nothing from the
|
||||
environment. Proven rather than assumed: two builds of an identical git-less tree now stamp
|
||||
`0.7.6-mtf6l8rm` and `0.7.6-mtf6lant`.
|
||||
|
||||
**And the server sent no `Cache-Control` at all**, which is the other half — the pages are the one
|
||||
thing that cannot be versioned in their own URL, since a player types the address or follows a
|
||||
bookmark, so a cached `play.html` pins that player to the whole build it names including every `?v=`
|
||||
inside it. Fixed the exact way round that matters: a request carrying `?v=` may be stored for a year
|
||||
and marked `immutable`, and anything else is `no-cache`. `?v=` rather than "not HTML" because
|
||||
`build-web.ts` tags the modules and nothing else — a year of `immutable` on an untagged image or on
|
||||
the replay manifest would outlive several releases of it.
|
||||
|
||||
Neither half is sufficient alone: without the varying tag there is nothing for a fresh page to point
|
||||
at, and without the header the fresh page is itself served from cache.
|
||||
|
||||
**What this says about the two releases before it.** v0.7.5's setup screen and v0.7.6's door fix were
|
||||
both real, both correct, and both verified on `phoenix.local` by reading what the server served —
|
||||
which was true, and was never the thing in doubt. What went unverified was the browser, and a
|
||||
hard-reload would have told us on the first report. Worth remembering the next time a fix "has had no
|
||||
effect": check that it arrived before re-diagnosing it.
|
||||
|
||||
864 tests pass, two of them new — one pinning the no-git fallback as something that varies per build,
|
||||
one pinning the header rule and that the `?v=` flag actually reaches `serveStatic`.
|
||||
|
||||
---
|
||||
|
||||
## 0.7.6 — 2026-08-29
|
||||
|
||||
### The solitaire door could not reach solitaire
|
||||
|
||||
Reference in New Issue
Block a user