All 64 finding IDs across the five reviews now carry an explicit state and none
remains NOT_STARTED: 51 fixed, 6 promotion-blocked by design, 4 deferred to the
multi-release wire migrations, 2 cohesion refactors not performed, and 1 browser
hypothesis unverified.
BT-UP-05 records that the extraction was attempted and reverted rather than
half-landed, with the specific reason: the five internal owners need a
shared-internals module for roughly forty types, constants and helpers to avoid
an import cycle.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
BT-UP-06: close() previously aborted the lifetime and closed the checkpoint
store immediately, so a caller could not wait for an active operation's terminal
settlement and a late provider result could still race the store.
The runtime now tracks every admitted operation until it settles. close() stays
the compatibility facade that closes admission and starts the drain, while
dispose() returns that same single-flight promise: it aborts the operation
registry, awaits actual settlement, and only then closes the checkpoint store
and cancellation channel. lifecycle() exposes OPEN, CLOSING and CLOSED, and a
draining runtime refuses new admission.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
BT-PRE-02: add the top-level PRESIGNED_TRANSFER_V1 protocol literal to the
capability request and response. A missing, V0 or V2 envelope is closed as
POLICY_REJECTED before the vault registers anything. The server negotiates by
request shape; fields are never dual-emitted into a strict decoder, and the
nested PRESIGNED_MULTIPART_V1 binding protocol is unchanged.
BT-PRE-03: aborting a controller does not settle a fetch that ignores its
signal, so both presigned scopes now race the task, cancel a late response body
and survive a throwing scheduler without leaking the external abort listener.
BT-PRE-04: the vault owns its registration invariants, re-checking method,
href/origin/path agreement, embedded credentials, byte bounds, digest shape and
expiry, so a second issuer cannot register a weaker capability of the same type.
BT-PRE-05: decode each path segment once and require it to round-trip through
the canonical uppercase percent encoder, closing %2f, %5c, %252e%252e, mixed-case
escapes and encoded NUL while still admitting valid opaque UTF-8 segments.
BT-UP-02: inject and snapshot the upload transport clock and scheduler, so
Retry-After delta-seconds and HTTP-date resolve against the same captured now
and a clock rollback clamps to zero instead of producing a negative delay.
BT-IMG-01: make the image resolve() lifetime signal required, replacing the
hidden PRIMARY_REQUIRED preset precondition with a type-level one, and add the
negative typecheck fixture and gate that prove it.
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>
Record the focused subsystem suites, repository gates and the exact status of
every gate that is not green, with attribution rather than assumption:
- ci-artifact-contract remains at its baseline 19 sandbox failures and is never
claimed as green
- WebKit browser capabilities are UNVERIFIED because the engine cannot launch
here; chromium passes
- the two runtime-removal fixtures fail on pre-existing reduced-fixture
arithmetic in scripts/contracts/ci-gates.ts, which is unchanged since the
baseline revision
- provider and staging rollback matrices are UNVERIFIED, not PASS
Also record what was deliberately not performed: the Task 17 extraction refactor
and the multi-release V2 wire rollouts, together with the in-repo prerequisites
that did land for each.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
STO-06: the IndexedDB codec migration commit chain runs entirely inside
IndexedDB callbacks, so up to maxRows records could keep executing past the
caller's cooperative deadline. The monotonic budget is now re-checked before
each record's first write; a started record still completes atomically, the
checkpoint advances only to the last safe key, and a clock failure aborts the
transaction rather than committing an unbounded batch.
STO-07: every OPFS worker request and response now carries
OPFS_WORKER_PROTOCOL_VERSION = 2, responses echo their request kind, and the
client validates the envelope and failure shape strictly while remembering the
expected kind per pending request. A page/worker release mismatch or a reply for
a different operation closes as UNSUPPORTED instead of being decoded as a value
of the wrong shape. UNSUPPORTED is used deliberately: the closed browser-data
taxonomy has no INCOMPATIBLE code and none was invented.
SW-10 and the OPFS/Web Push V2 wire rollouts remain deferred: they are
expand/dual-read/drain/contract deployments across releases rather than a single
in-repo change. The ledger records them as DEFERRED_TO_MIGRATION.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
WP-01: a CAS receipt is only evidence when it names the expected key and the
exact next revision. Write and remove now share one validator, so a stale or
arbitrary repository receipt can no longer be packaged as a confirmed control.
WP-05: a pre-aborted command records the operation the caller requested instead
of always reporting an inspection.
WP-06: bounded fan-out is reported honestly. The subscriptionchange client
handoff and the notification cleanup both emit countBucket and truncated, and an
incomplete cleanup returns { complete: false } and is observed as DEGRADED
separately from revoke authority.
WP-07: the user-visible native notification effect is tracked through
NOT_APPLIED, MAYBE_APPLIED and CONFIRMED phases and surfaced as observation
evidence, never as retry authorization.
WP-02, WP-03 and WP-04 stay open: they need the V2 wire protocol with server
request-shape negotiation, which belongs to the versioned-migration task rather
than this correctness pass. The ledger records them as DEFERRED_TO_MIGRATION.
Web Push remains NOT_SELECTED and AVAILABLE_NOT_COMPOSED.
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>
BT-X-01: add the shared abortable-operation utility with golden tests for first
terminal owner, idempotent close, listener and timer cleanup under a throwing
scheduler, observed late rejection and late-handle compensation. It carries no
subsystem result taxonomy.
BT-PRE-01: make the presigned download lease lazy and single-start. open() now
validates, claims and consumes the capability without any network I/O; the
fetch, the transfer deadline and the expiry recheck happen at first stream
consumption. The source gained close(), which discards an unused lease with no
I/O and otherwise cancels the body and releases the scope exactly once.
BT-UP-01: require removeEventListener in the AbortSignal structural guard and
isolate release cleanup so a hostile facade cannot replace a typed terminal
result with a rejection.
BT-UP-03: deleteDatabase cannot be cancelled after dispatch, so a blocked
deadline now returns PENDING with effect UNKNOWN instead of a failure that reads
as NOT_APPLIED. A realm-scoped (factory, databaseName) registry prevents
recreating the partition until the native request settles.
BT-UP-04: reject non-finite and negative upload clocks as a dependency failure
instead of letting them bypass every capability expiry comparison.
BT-IMG-02: replace the naive Cache-Control quote stripping with a quote- and
escape-aware tokenizer, so max-age="60 or 60" is no longer read as 60 and a
comma inside a quoted extension is not a directive boundary.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
R-04: install the RPC contract bindings as exact immutable snapshots. Registry
and row data are copied from own data descriptors into frozen null-prototype
maps before validation, so a getter is never invoked, extra and symbol keys and
malformed descriptors are composition-time TypeErrors, and the runtime reads
only the snapshot. A post-validation mutation can no longer change replay
policy, deadlines, byte ceilings or transport selection.
R-01: bound transport stream cleanup. The generation is fenced and listeners
released immediately, and iterator.return() is awaited only within a cleanup
bound, so a non-cooperative iterator cannot keep the application generator, its
listeners or the total deadline alive. Unresolved cleanup stays observed.
R-05: reject oversized WebSocket text frames before allocating an encoded copy
and count UTF-8 bytes incrementally with an early exit, matching TextEncoder for
surrogate pairs and lone surrogates.
R-06: canonicalise clock and generation-fence failures into the closed Result
taxonomy instead of letting them escape as native rejections, with listener and
timer cleanup on every exit path.
Browser RPC remains AVAILABLE_NOT_COMPOSED; R-07 transport evidence is still
required before composition.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
R-02: add an OPEN/DRAINING/CLOSED lifecycle orthogonal to freshness. Effect and
recovery authorities are now awaited under a deadline: on expiry the commit
capability is revoked and the work aborted, the caller gets a bounded
non-retryable IDLE_TIMEOUT, and the underlying task is retained rather than
dropped. A draining stream refuses new events and recovery, and close() returns
a Promise that succeeds only once every retained task actually settled,
reporting IDLE_TIMEOUT otherwise.
R-03: a handoff fail-close moves active, probe, quiescing and transition leases
into a retired-writer set before clearing their references, and close() waits on
current and retired writers together, so an abandoned non-cooperative writer can
no longer make teardown report a false success.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
N-06: export one idempotency-key authority from mutation-intent.ts and use it
in the V2 client. A caller-supplied key is validated before credentials, timers
and fetch, and an invalid value is rejected as VALIDATION_REJECTED /
IDEMPOTENCY_KEY_INVALID rather than trimmed, regenerated or dropped, so a keyed
command can no longer replay while sending no key.
N-07: bound the legacy credential wait by the existing attempt controller,
which already carries the total deadline and the caller signal, so a
non-cooperative owner cannot hold the request open and no extra timer is
introduced. The owner receives the operation context, and the failure follows
ownership: deadline to REQUEST_TIMEOUT, caller to REQUEST_ABORTED, and only a
genuine rejection to AUTH_INTEGRATION_FAILURE. None of these paths fetch.
N-08: readBoundedJson delegates to the common bounded reader, so cancel and
releaseLock throws stay isolated inside the closed result, and the V2
content-type mismatch now cancels the response body.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
N-05: the conditional-validator key was a colon join over components that may
themselves contain colons, so two distinct valid bindings could collide and one
definition's ETag could be prepared for another. The key is now a validated,
byte-bounded fixed tuple encoded with JSON.stringify.
N-09: capture localStorage exactly once and compare StorageEvent.storageArea
against that object identity, so a pulse from sessionStorage or any other area
is rejected instead of matching on key and value alone. The pulse key is
registered in the storage registry as CACHE_INVALIDATION_PULSE.
N-10: race loadPage against the caller signal and re-check before observing a
page, so a non-cooperative loader can neither hold loadAll forever nor have a
post-abort completion accumulated into a successful result.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
STO-03: reject at composition any policy that enables Vary variants while
stripping vary from the stored response allowlist, since every stored variant
would collide on the same cache key.
STO-04: extract one verifyReleaseCandidate authority shared by the stage fast
path and activation. A matching release marker is a claim, not evidence, so a
restage now re-verifies each entry, deletes only the owned candidate on a
mismatch and refetches. Abort or an unreadable candidate is never stage success
and never moves the active pointer.
STO-05: split the availability guard. Staging keeps the fetcher requirement
with ONLINE_ONLY recovery; activation, rollback and cleanup need only cache
storage and the mutation lock, so an offline rollback or quota-recovery cleanup
is no longer reported UNSUPPORTED.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Replace the boolean browser-managed target validator with
resolveBrowserManagedTarget, which returns the parsed canonical absolute URL,
and hand that exact value to the host. Previously the raw href was passed on,
so a relative target was re-resolved against document.baseURI and a hostile
<base> could send the navigation to an origin the policy never approved.
STO-08 stays UNVERIFIED: the capability spec does not exercise the system
picker, so the receiver-binding hypothesis is neither reproduced nor refuted
and no source change was made for it.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Repair the compensating half of the OPFS put saga.
The coordinator now owns a single abortPreparedPut() driven by a
composition-owned bounded signal instead of the caller's already aborted one,
and the worker client no longer issues a duplicate fire-and-forget abort.
Journal rows and budget reservations are released only after the physical
effect is confirmed CLEANED or ALREADY_CLEAN; a timeout, malformed response or
EFFECT_UNKNOWN keeps PREPARING/FILES_READY and returns OBJECT_RECONCILE.
New writes carry a transaction-unique physicalGenerationId through the staging
receipt, manifest path and prepared object, so a late compensation deletes only
its own transaction's directory even when a newer transaction legitimately
reuses the same logical generation. v1 paths, receipts and prepared objects stay
readable through the rollback window.
Abort and cleanup hold the origin mutation lease through physical deletion and
staging removal. A transaction that never reached staging returns ALREADY_CLEAN
without waiting for the lease, which would otherwise deadlock against the BEGIN
it is cancelling.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Give the best-effort telemetry adapter a terminal ACTIVE/DISPOSED lifecycle.
dispose() now removes the pagehide listener, clears the queue, invalidates
scheduled callback generations and aborts the in-flight sink; emit after
dispose is a no-op and a sink that ignores the abort cannot reschedule or
update post-dispose state. flush() joins the active delivery instead of
resolving early, and runtime infrastructure teardown disposes telemetry first.
Telemetry and diagnostics capacities are validated at construction against a
documented ceiling, so NaN or Infinity can no longer disable eviction.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Separate per-attempt physical state from the logical execution history. The
executor now keeps one monotonic certainty accumulator joined through
joinMutationEffectCertainty, records MAYBE_APPLIED at dispatch, and reads the
accumulator from every retry-loop fence, final-invariant, cancellation and
timeout return.
A retry-time scope fence landing between the loop-entry check and the
pre-dispatch invariant can no longer downgrade an already dispatched command to
NOT_STARTED.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Install the REST auth profile registry once at composition and make it the
single transport authority for V3. Contract composition now rejects an
unregistered authProfileId, so the executor never resolves a profile at
runtime.
The credential collaborator contributes proof headers only: Fetch credentials
come from the resolved profile, transport-owned and forbidden headers are
rejected, headers outside the profile's allowed set are rejected, and a missing
required header fails closed as AUTH_INTEGRATION_FAILURE with zero fetch calls.
The final invariant re-proves credentials mode and the exact header sets.
Demo mode satisfies the strict bearer profile with a fixed non-secret marker
instead of weakening REFERENCE_EXTERNAL_BEARER. Credential owners now receive
the operation lifetime through AuthOperationContext.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Project one typed HttpExecutionObservation per logical V3 execution through a
closed composition-root projector: only registered diagnostic context keys and
bucketed values reach the sinks, and terminal non-abort failures now emit
exactly one api.request.failed telemetry event. Caller cancellation and scope
fencing record a diagnostic but never a failure event.
routeId becomes a required input at the installed operation-executor boundary
so the feature gateway's low-cardinality route identity survives to the sink.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>