fix(web): revalidate stable UI assets - #3934
Conversation
e2b1319 to
44a4a82
Compare
|
Updated the branch per the digest direction:
I rebased onto current |
Helix-Harness: pi Helix-Model: openai-codex/gpt-5.6-sol
Helix-Harness: pi Helix-Model: openai-codex/gpt-5.6-sol
Helix-Harness: pi Helix-Model: openai-codex/gpt-5.6-sol
Helix-Harness: pi Helix-Model: openai-codex/gpt-5.6-sol
Helix-Harness: pi Helix-Model: openai-codex/gpt-5.6-sol
Helix-Harness: pi Helix-Model: openai-codex/gpt-5.6-sol
Helix-Harness: pi Helix-Model: openai-codex/gpt-5.6-sol
Helix-Harness: pi Helix-Model: openai-codex/gpt-5.6-sol
Helix-Harness: pi Helix-Model: openai-codex/gpt-5.6-sol
Helix-Harness: pi Helix-Model: openai-codex/gpt-5.6-sol
Helix-Harness: pi Helix-Model: openai-codex/gpt-5.6-sol
2968770 to
8ff967e
Compare
The UI cache split, the immutable-assets manifest, the route-only SPA fallback, Vary, and File-Digest stay. Dropped: q-value negotiation and 406, the saturating range parser, If-Range and weak validators, the per-process nonce in every ETag (which invalidated every no-cache file in every browser on each restart), the refresher and webmanifest range/HEAD paths, and the path hardening and tests around a generator whose input is our own build's metafile. Embedded and installed-s9pk ETags go back to path + mtime, with the content encoding appended so the identity and compressed representations validate separately. A ranged request always serves identity bytes: a gzip of an identity slice is not a valid 206, since a range applies after content coding. An unparsable or unsatisfiable Range is ignored instead of answered with 500. The Refresh Needed dialog keeps one button, Refresh, in both browser and PWA modes.
…e-revalidation # Conflicts: # projects/start-os/CHANGELOG.md # projects/start-tunnel/CHANGELOG.md # projects/start-tunnel/release-notes/1.3.1.md
|
VM-tested head Passed live checks:
The workflow-dispatch image used Test setup caveat unrelated to this diff: |
Helix-Harness: pi Helix-Model: openai-codex/gpt-5.6-sol
|
Merged current Verified:
|
Summary
immutable-assets.txtare servedpublic, max-age=31536000, immutable; everything else (index.html,assets/**, the service worker) isno-cacheand revalidates against an ETag. The manifest is generated from the build's esbuild metafile (--stats-json), which lists only content-hashed outputs; a development build declares none.index.htmlfor extensionless routes only, so a stale hashed chunk gets a 404 instead of a cached HTML body.Vary: Accept-Encoding. A ranged request always serves identity bytes; an unparsable or unsatisfiable Range is ignored.File-Digest(the BLAKE3 of the decoded file) on full, ranged, gzip, and HEAD responses, and HEAD no longer reads the archive. The s9pk routes answer GET and HEAD only.Verification
cargo test -p start-core net::static_server --features=test— 9 passedcargo check -p startwrt-corecargo +nightly-2026-05-28 fmt --all --check, prettier on every touched filenpm run check:i18n,npm run check:i18n:tunnel,npm run check:uinpm run build:tunnel: the production manifest holds 34 entries, every one achunk-*/main-*/polyfills-*/styles-*hashed bundle;stats.jsonis removed;index.html,assets/**and3rdpartylicenses.txtare absentcheckForUpdate()+activateUpdate()followed by one reload loaded the new bundleCloses #3765