SW-RR-01. The activation marker was read with response.text() whenever no
Content-Length was present, so a large or non-terminating body could consume
the whole activation step. It now reads through a bounded reader that stops one
byte past the ceiling, cancels its reader, applies a read deadline and decodes
UTF-8 fatally.
SW-RR-02. A matching nonce is not identity. An activation or reset result whose
event.source is null can no longer stand in for the expected worker; only a
strict identity match is admitted.
SW-RR-03. The build generator and the shared manifest decoder now read one
exported extension table, so .mjs and .png stop being emitted-then-refused.
.json is deliberately outside it: every JSON file in a build output is a control
document the generator already excludes, not a cacheable asset.
SW-RR-04. Both caches.open and cache.match are closed as a miss. Letting a
match rejection propagate rejected respondWith itself, so the entry never
reached its network fallback.
WP-RR-01. focus and openWindow now carry the certainty phase showNotification
already had — NOT_APPLIED, MAYBE_APPLIED, CONFIRMED — and an effect that lands
after the handler deadline is observed exactly once. The evidence never
authorizes a retry.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
SW-06: correlate activation, reset and drain replies by source object identity
against the captured waiting worker or controller, so an arbitrary same-origin
source cannot close this page's admission, and end a request immediately as
PROTOCOL_MISMATCH when the source is swapped instead of waiting for the drain
timeout. requestActivation() and resetOwnedCaches() are single-flight, so ten
concurrent callers share one nonce, listener and postMessage.
SW-07: an empty in-scope client set is vacuously drained rather than rejecting
a waiting worker when the requester already closed.
SW-08: isolate per-client postMessage failures. A client that cannot receive the
drain request fails immediately instead of holding pending state to the timeout,
skipWaiting() is the activation commit and its failure is a rejection, and the
accepted and reload notifications are sent afterwards as best effort.
SW-09: fence late install work. A fenced worker starts no new candidate work, a
late response body from a non-cooperative fetch is cancelled, a throwing digest
maps to a closed outcome, and a second exact delete of the owned candidate cache
is registered once the abandoned install settles - without extending the public
60s bound.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
SW-URL-01: canonicalize each generated root-relative manifest URL against the
registration scope once, re-check same-origin, and share that absolute identity
across install cache keys, fetch classification and cache lookup or delete.
Previously every verified asset fell through to the network.
SW-01: serve verified static requests only from the current release cache. A
CacheStorage-wide match could return a previous release's response for the same
URL while the delete targeted a cache that was never read. The worker scope
facade no longer exposes a wide match at all.
SW-02: cache reset deletes only names that parse as owned, so a foreign cache
sharing the ca-static-v1- prefix survives.
SW-03: unregister() resolving to false is a FAILED unregister, not UNREGISTERED.
SW-04: staged removal reports what happened - ABSENT, UNREGISTERED and PURGED
map to DISABLED, OWNERSHIP_MISMATCH to INCOMPATIBLE and FAILED to FAILED - so a
later release cannot delete the worker while a registration or owned cache is
still present.
SW-05: add the runtime-neutral service-worker-static-manifest codec that owns
exact row keys, the extension and content-type allowlist, the root-relative URL
rule and the length-prefixed canonical bytes. The generator and the build gate
hash those same bytes, and the build gate now decodes and recomputes the set
digest instead of type-casting the manifest.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>