Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
- Authentication-redaction amendment: 2026-08-08
- HTTP teardown-boundary amendment: 2026-08-08
- Successful bodyless-HEAD abort amendment: 2026-08-08
- Mediated bodyless-HEAD abort reconciliation amendment: 2026-08-09

## Context

Expand Down Expand Up @@ -106,15 +107,21 @@ single terminal as CDP completion only when the request has already matched an e
policy, the admitted method is exactly `HEAD`, the request body is absent, the resource type is
exactly `fetch`, both observer response statuses are present, `2xx` and equal, and no mediated
failure exists. This is not immediate lifecycle completion: the request remains open until the
mediated observer subsequently emits its normal finish. Only then may the completed-request count
advance and the zero-open teardown boundary become eligible.
mediated observer subsequently emits either its normal finish or the exact corresponding `aborted`
terminal. The latter is accepted only after the existing bounded CDP exception has set an explicit
per-request completion marker. An ordinary `cdp-finished` terminal is not that marker, and a mediated
abort observed before the marker remains a terminal pending failure that cannot be retroactively
cleared. Only a normal mediated finish or this ordered, marker-bound second half may advance the
completed-request count and make the zero-open teardown boundary eligible.

The exception is response-bound and fail-closed. A `GET`, body-bearing request, non-`fetch`
resource, missing or unequal response, non-`2xx` response, uncorrelated CDP request, any failure
class other than `aborted`, duplicate CDP terminal, later mediated failure or absent mediated finish
still stops the proof or leaves it incomplete. The recorder emits only the fixed signed event code
`http-cdp-head-aborted-after-response` plus the existing opaque correlation token; it does not add a
URL, request identifier, header, body, credential, token or provider diagnostic to evidence.
class other than `aborted`, duplicate terminal, an early mediated abort, an ordinary CDP completion
followed by a mediated abort, or absent mediated terminal still stops the proof or leaves it
incomplete. The recorder emits only the fixed signed event codes
`http-cdp-head-aborted-after-response` and, for the ordered second half,
`http-mediated-head-aborted-after-response`, plus the existing opaque correlation token. It does not
add a URL, request identifier, header, body, credential, token or provider diagnostic to evidence.

## Authentication failure redaction flow

Expand All @@ -138,7 +145,7 @@ inspection itself is adversarial.
```mermaid
stateDiagram-v2
state "Pending: HTTP lifecycle still open" as Pending
state "HEAD abort pending: matching 2xx responses; mediated finish required" as HeadAbortPending
state "HEAD abort pending: bounded CDP-abort marker set; mediated terminal required" as HeadAbortPending
state "Ready: zero open HTTP at this instant" as Ready
state "Sealed: atomic teardown boundary accepted" as Sealed
state "Stopped: proof fails closed" as Stopped
Expand All @@ -148,8 +155,9 @@ stateDiagram-v2
[*] --> Pending: observer attached
Pending --> Pending: HTTP lifecycle incomplete
Pending --> HeadAbortPending: admitted bodyless HEAD/fetch; matching 2xx responses; CDP aborted
HeadAbortPending --> Ready: mediated observer finishes normally and zero other HTTP is open
HeadAbortPending --> Stopped: mismatch, duplicate, mediated failure or incomplete finalization
HeadAbortPending --> Ready: mediated observer finishes normally or emits exact aborted terminal; zero other HTTP is open
HeadAbortPending --> Stopped: mismatch, duplicate, other failure or incomplete finalization
Pending --> Stopped: early mediated abort remains a pending failure until teardown stops
Pending --> Ready: zero open HTTP and all health checks pass
Ready --> Pending: HTTP opens before atomic seal
Ready --> Sealed: sealHttpTeardown revalidates atomically
Expand Down Expand Up @@ -179,7 +187,8 @@ as a harmless teardown cancellation.
incomplete product request behind teardown timing.
- Ignore cancelled CDP fetches broadly: rejected because cancellation alone does not prove that a
request was safe, complete or superseded. The accepted exception requires an exact admitted,
bodyless `HEAD`/`fetch` request, matching successful responses and later normal mediated finish.
bodyless `HEAD`/`fetch` request and matching successful responses. It then requires either a later
normal mediated finish or an exact later mediated abort bound to the explicit CDP-abort marker.
- Poll until the open count reaches zero without an atomic seal: rejected because a request can open
between the final poll and page closure.

Expand All @@ -194,7 +203,9 @@ HTTP teardown seal prevents page closure from laundering an active or newly open
accepted browser result; late HTTP traffic and missing seals remain fixed-code failures. The
bodyless-HEAD rule does not admit a request or relax its identity, credential, origin, method, body,
resource-type, response-status or occurrence policy. It only reconciles one bounded post-response
CDP terminal while retaining the independent mediated completion requirement.
CDP terminal while retaining an independent mediated terminal requirement. The mediated-abort form
is deliberately ordered: it cannot create the CDP marker, use an ordinary CDP completion or clear an
earlier failure.

## Data implications

Expand Down Expand Up @@ -228,7 +239,8 @@ waits for zero open HTTP and may schedule approximately five seconds of polling
final atomic seal, plus event-loop and readiness or sealing overhead. A legitimate late request can
therefore stop or delay proof, but the page can no longer close while silently creating an accepted
cancellation. A successfully answered bodyless `HEAD` count may survive Chromium's later CDP abort,
but it remains pending until the mediated observer finishes; all wider or incomplete abort shapes
but it remains pending until the mediated observer finishes normally or emits the exact later abort
paired with that explicit CDP-abort marker; all wider, reverse-order or incomplete abort shapes
continue to stop.

## Related architecture
Expand Down
59 changes: 44 additions & 15 deletions scripts/product-proof-live-evidence.mjs
Original file line number Diff line number Diff line change
Expand Up @@ -1078,6 +1078,22 @@ export function createProductProofLiveRecorder(options, dependencies = {}) {
});
};

const hasBoundedHeadAbortShape = (pending) =>
pending.policy !== undefined &&
pending.request.method === 'HEAD' &&
pending.request.postData === null &&
pending.request.resourceType === 'fetch';

const hasBoundedSuccessfulHeadResponses = (pending) =>
hasBoundedHeadAbortShape(pending) &&
Number.isInteger(pending.cdpResponse) &&
pending.cdpResponse >= 200 &&
pending.cdpResponse <= 299 &&
Number.isInteger(pending.mediatedResponse) &&
pending.mediatedResponse >= 200 &&
pending.mediatedResponse <= 299 &&
pending.cdpResponse === pending.mediatedResponse;

const connectionByCdpId = (cdpId) =>
[...connections.values()].find((entry) => entry.cdpId === cdpId);

Expand Down Expand Up @@ -1228,6 +1244,7 @@ export function createProductProofLiveRecorder(options, dependencies = {}) {
pendingCdp?.correlationToken ?? `request-${String(requestOrdinal).padStart(6, '0')}`;
const entry = {
cdpComplete: pendingCdp?.cdpComplete ?? false,
cdpHeadAbortCompleted: pendingCdp?.cdpHeadAbortCompleted ?? false,
cdpId: pendingCdp?.rawId ?? null,
cdpResponse: pendingCdp?.cdpResponse ?? null,
correlationToken,
Expand Down Expand Up @@ -1273,6 +1290,7 @@ export function createProductProofLiveRecorder(options, dependencies = {}) {
const correlationToken = `request-${String(requestOrdinal).padStart(6, '0')}`;
pendingCdpRequests.set(cdpId, {
cdpComplete: false,
cdpHeadAbortCompleted: false,
cdpResponse: null,
correlationToken,
mediatedComplete: false,
Expand Down Expand Up @@ -1391,38 +1409,49 @@ export function createProductProofLiveRecorder(options, dependencies = {}) {
}
const failureCode = fixedNetworkFailureCode(event);
const boundedHeadAbortCandidate =
!mediated &&
event.failureClass === 'aborted' &&
pending.policy !== undefined &&
pending.request.method === 'HEAD' &&
pending.request.postData === null &&
pending.request.resourceType === 'fetch';
if (boundedHeadAbortCandidate && pending.cdpComplete) {
event.failureClass === 'aborted' && hasBoundedHeadAbortShape(pending);
if (!mediated && boundedHeadAbortCandidate && pending.cdpComplete) {
httpFailureDiagnostic = createHttpFailureDiagnostic(pending, 'cdp');
return stop('live_failure_duplicate');
}
if (
!mediated &&
boundedHeadAbortCandidate &&
pending.mediatedFailure === null &&
Number.isInteger(pending.cdpResponse) &&
pending.cdpResponse >= 200 &&
pending.cdpResponse <= 299 &&
Number.isInteger(pending.mediatedResponse) &&
pending.mediatedResponse >= 200 &&
pending.mediatedResponse <= 299 &&
pending.cdpResponse === pending.mediatedResponse
hasBoundedSuccessfulHeadResponses(pending)
) {
pending.cdpComplete = true;
pending.cdpHeadAbortCompleted = true;
if (pending.mediatedComplete) completedRequestCount += 1;
return allow('http-cdp-head-aborted-after-response', {
correlation_token: pending.correlationToken,
kind: 'http-complete',
});
}
if (
mediated &&
boundedHeadAbortCandidate &&
hasBoundedSuccessfulHeadResponses(pending) &&
pending.cdpComplete &&
pending.cdpHeadAbortCompleted
) {
if (pending.mediatedComplete || pending.mediatedFailure !== null) {
return stop('live_failure_duplicate');
}
pending.mediatedComplete = true;
completedRequestCount += 1;
return allow('http-mediated-head-aborted-after-response', {
correlation_token: pending.correlationToken,
kind: 'http-complete',
});
}
if (!mediated) {
httpFailureDiagnostic = createHttpFailureDiagnostic(pending, 'cdp');
return stop(failureCode);
}
if (pending.mediatedFailure !== null) return stop('live_failure_duplicate');
if (pending.mediatedFailure !== null) {
return stop('live_failure_duplicate');
}
pending.mediatedFailure = Object.freeze({
code: failureCode,
diagnostic: createHttpFailureDiagnostic(pending, 'mediated'),
Expand Down
Loading