Commit Graph
103 Commits
Author SHA1 Message Date
DongHyeonkaandClaude Opus 5 000a2581af fix: complete presigned capability and upload transport contracts
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>
2026-08-14 02:19:00 +09:00
DongHyeonkaandClaude Opus 5 976c8a8da4 fix: harden Service Worker activation and install lifecycle
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>
2026-08-14 02:03:07 +09:00
DongHyeonkaandClaude Opus 5 f6098242be fix: bound migration commits and version the OPFS worker protocol
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>
2026-08-14 00:41:12 +09:00
DongHyeonkaandClaude Opus 5 fce8e046ea fix: bind Web Push mutations to exact authority
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>
2026-08-14 00:34:09 +09:00
DongHyeonkaandClaude Opus 5 58efe6ddbd fix: make Service Worker cache and removal outcomes truthful
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>
2026-08-14 00:25:11 +09:00
DongHyeonkaandClaude Opus 5 cc4e875c2d fix: bound browser transfer leases and effect reporting
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>
2026-08-14 00:13:54 +09:00
DongHyeonkaandClaude Opus 5 8f67974f68 fix: install bounded Browser RPC stream leases
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>
2026-08-14 00:00:15 +09:00
DongHyeonkaandClaude Opus 5 2f29ccbf1a fix: retain realtime work through draining
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>
2026-08-13 23:52:46 +09:00
DongHyeonkaandClaude Opus 5 c9e820aed5 fix: harden the legacy HTTP rollback path
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>
2026-08-13 23:46:03 +09:00
DongHyeonkaandClaude Opus 5 4fe924ee0f fix: harden bounded state sidecars
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>
2026-08-13 23:35:48 +09:00
DongHyeonkaandClaude Opus 5 b893d95b36 fix: make public cache staging repairable
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>
2026-08-13 23:28:22 +09:00
DongHyeonkaandClaude Opus 5 ba79060a83 fix: execute canonical browser download targets
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>
2026-08-13 23:23:46 +09:00
DongHyeonkaandClaude Opus 5 618da9abf5 fix: preserve OPFS recovery authority during cleanup
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>
2026-08-13 23:21:58 +09:00
DongHyeonkaandClaude Opus 5 6d1e44f206 fix: terminate telemetry work on disposal
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>
2026-08-13 23:05:43 +09:00
DongHyeonkaandClaude Opus 5 e06e4377ca fix: preserve command effect certainty across retries
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>
2026-08-13 23:01:48 +09:00
DongHyeonkaandClaude Opus 5 4e87bacdf3 fix: enforce installed HTTP auth profiles
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>
2026-08-13 22:56:44 +09:00
DongHyeonkaandClaude Opus 5 67cc5b6d2c fix: restore V3 HTTP observability
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>
2026-08-13 22:42:51 +09:00
DongHyeonka 4dc033cf33 refactor: adapter 구현중.. 2026-08-13 16:02:21 +09:00
DongHyeonka 30ceac23c1 fix: harden provider and promotion evidence 2026-08-02 16:28:24 +09:00
DongHyeonka 42ffb79997 fix: reject empty removal fixture scans 2026-08-02 15:02:57 +09:00
DongHyeonka f49d147b01 fix: harden CI evidence and removal contracts 2026-08-02 14:48:04 +09:00
DongHyeonka 1bb2cc4a20 refactor: generate CI workflow from gate contracts 2026-08-02 13:53:25 +09:00
DongHyeonka d2eb320936 test: harden HTTP scenario execution evidence 2026-08-02 11:36:27 +09:00
DongHyeonka abdd90ad5d test: execute the HTTP scenario catalog 2026-08-02 11:17:28 +09:00
DongHyeonka 76bf9f1aa3 test: lock V8 coverage counter semantics 2026-08-02 10:12:34 +09:00
DongHyeonka 5cecbb9820 refactor: align coverage counter provenance 2026-08-02 09:31:28 +09:00
DongHyeonka 6e05a35790 fix: reject empty coverage counters 2026-08-02 09:10:35 +09:00
DongHyeonka 8d6fbb97e9 fix: close coverage evidence races 2026-08-02 08:43:44 +09:00
DongHyeonka 67cd37659d fix: harden repository coverage evidence 2026-08-02 08:20:25 +09:00
DongHyeonka 5a73f7a1b5 fix: measure repository-wide risk coverage 2026-08-02 07:52:46 +09:00
DongHyeonka f487823442 fix: enforce exact local evidence defaults 2026-08-02 07:11:33 +09:00
DongHyeonka 1b4b0c2821 fix: recompute local promotion evidence 2026-08-02 07:02:39 +09:00
DongHyeonka 92e5cace5c fix: close immutable promotion trust gaps 2026-08-02 06:39:41 +09:00
DongHyeonka 7c5ed80407 fix: promote immutable verified release bundles 2026-08-02 06:08:06 +09:00
DongHyeonka 100a3bb6ba fix: make security fixtures fail closed 2026-08-02 05:40:58 +09:00
DongHyeonka 76d0ab0f62 fix: cover every tracked release input 2026-08-02 05:26:36 +09:00
DongHyeonka d6c98489ee fix: fail closed on release input discovery 2026-08-02 05:11:30 +09:00
DongHyeonka 381d5549e2 fix: preserve artifact writer failures 2026-08-02 04:46:33 +09:00
DongHyeonka c9f5887cac refactor: validate generated evidence artifacts 2026-08-02 04:33:01 +09:00
DongHyeonka 2c3cab2518 fix: select rollback artifact pairs atomically 2026-08-02 04:03:14 +09:00
DongHyeonka 172a26b8bd fix: fail closed in release drill verification 2026-08-02 03:54:58 +09:00
DongHyeonka 990603e24a fix: unify release runtime coherence verification 2026-08-02 03:38:49 +09:00
DongHyeonka 184bd98d92 fix: preserve reconciliation authorities 2026-08-02 03:15:22 +09:00
DongHyeonka d9afccdd60 fix: retain uncertain optimistic mutations 2026-08-02 02:42:56 +09:00
DongHyeonka 15645541b7 fix: reject credential idempotency headers 2026-08-02 01:33:07 +09:00
DongHyeonka fa2f699125 fix: reject invalid keyed mutation intents 2026-08-02 01:21:50 +09:00
DongHyeonka cbcc7b5ed7 fix: preserve logical mutation intent 2026-08-02 01:07:19 +09:00
DongHyeonka 53d181fbe4 fix: baseline invalidation registry contracts 2026-08-02 00:28:17 +09:00
DongHyeonka 0eb23875cb fix: harden invalidation registry governance 2026-08-01 23:59:11 +09:00
DongHyeonka 73a50426d6 fix: index many-to-many query invalidation 2026-08-01 23:17:09 +09:00