Skip to content

feat(adapter): failure taxonomy, evidence lookup, drift hardening, and frozen ports (B04) - #17

Merged
selezenart merged 2 commits into
milestone/b03-live-settlement-harnessfrom
milestone/b04-ambiguity-integration
Sep 7, 2026
Merged

selezenart merged 2 commits into
milestone/b03-live-settlement-harnessfrom
milestone/b04-ambiguity-integration

Conversation

@selezenart

Copy link
Copy Markdown
Collaborator

Summary

Implements B04 — provider ambiguity and production adapter pack for the
Coder B lane: the surface Coder A composes against, plus the conservative
classification behind it.

Stacked on B03 (PR #14) → B02 (#12) → B01 (#11). Review those first.

Scope and acceptance criteria

  • The change is limited to the stated milestone or issue.

  • Acceptance criteria are listed and satisfied.

  • No unrelated cleanup is included.

  • B04.1 failure taxonomy — DNS, refusal, TLS, timeout, 429, 5xx, truncated,
    malformed, and lost-success all classified, with only documented pre-broadcast
    proof marked DEFINITELY_NOT_SUBMITTED.

  • B04.2 lifecycle lookup — the five EvidencePort results with sanitized
    evidence; NOT_FOUND never grants resubmission.

  • B04.3 mismatch cases — wrong hash, chain, wallet, recipient, amount,
    multiple Transfers, and contradictory states all preserve ambiguity.

  • B04.4 hardening — policy and Arc identity rechecked, failing closed on any
    change; webhooks remain disabled.

  • B04.5 entry point — only frozen ports and sanitized errors exported, with
    an asserted import boundary and a compatibility manifest.

Product and security invariants

  • Tenant isolation remains fail-closed.
  • Sponsor authorization, auditability, and daily caps remain enforced where applicable.
  • Recipients cannot modify sponsor controls or access sponsor-only data.
  • No secret, token, production identifier, or personal data is committed.
  • Any non-applicable invariant is explained below.

Invariant notes:

No durable product state or tenant boundary exists in this diff. What this
change turns on:

  • One question decides retry safety: did the request reach the network? DNS
    failure, connection refusal, and a failed TLS handshake all occur before any
    application data is sent. A reset, timeout, truncation, or an interrupted TLS
    connection
    may follow a delivered request. The first group permits a retry;
    the second never does.
  • 429 stays ambiguous. A rate limiter may reject before or after queuing the
    work, so it is not proof of non-submission.
  • Unknown errors fail closed. Any code this build has not seen classifies
    post-send. An unknown failure cannot be proof that nothing happened.
  • NOT_FOUND is never permission. permitsResubmission returns false for
    every observation, and evidence is bound to the exact request before it is
    interpreted, so a receipt from another chain, hash, or wallet cannot resolve
    this intent.
  • Drift fails closed in both directions, a lowered cap included. Judging
    whether a change is benign is not this module's job.

Validation

packages/arc-adapter        : lint, typecheck, build PASS; 193 tests PASS
packages/privy-adapter      : lint, typecheck, build PASS;  96 tests PASS
packages/testkit-settlement : lint, typecheck, build PASS;  56 tests PASS
total                       : 345 tests PASS
markdownlint-cli2           : 0 errors over 58 files

Independent review evidence

Gate A — exact candidate tree before push

  • Base commit SHA: 8be8d09b8ab5da19031af28fcee9da128a16f82b (develop)

  • Candidate tree SHA: f0c2c6f51899665bdf56fff8fbb3bf277927c155

  • Reviewer tool: free-pi-cli 0.2.19

  • Reviewer model: glm-5.3-flash

  • Verdict: VERDICT: PASS

  • Blocking findings: None

  • The reviewed tree equals the committed tree.

The reviewer was asked specifically to attack the pre-broadcast/post-send
boundary per error code, and to hunt for any path turning NOT_FOUND into a
settlement right. It concluded the 4xx-except-429 mapping is defensible under
standard HTTP semantics and that NOT_FOUND cannot become a settlement right
anywhere in the tree.

Non-blocking finding, fixed in 154d8cc after the reviewed tree:
PersistedIdentity declared a nonce nobody read, implying a wrong-nonce
defence that does not exist. Removed. That commit is not covered by the verdict
above; it deletes one unused field and changes no behaviour, and all 345 tests
still pass.

Gate B — exact remote PR head

  • Verdict: NOT RUN (no CI gate covers these packages; see below)

Risk and rollback

  • CI still does not lint or test these packages. The ESLint and TypeScript
    job finds no root pnpm-lock.yaml and skips. All 345 tests are local only.
    This gap has now persisted across four milestones and is the largest
    outstanding risk in the lane.
  • npm versus pnpm unresolved; the package-local lockfiles should be dropped
    when Coder A scaffolds the workspace root. Note PR A02: durable PostgreSQL intent ledger and API boundary #15 (A02) is open and may
    do exactly that.
  • Everything provider-facing is modelled, not observed. The Privy policy
    shape, Arc receipt shapes, and the wallet/policy identifier formats all come
    from documentation. COMPATIBILITY_MANIFEST.liveGapsForGateP4 lists these in
    code so fixtures cannot pass as live evidence. Privy and Arc claims remain
    NOT VERIFIED.

Rollback: additive packages and docs on a short-lived branch. Revert or close.

Human merge

  • A human owner has reviewed the evidence and will perform the merge.

…, ports

Implements B04 for the Coder B lane: the production adapter surface, plus the
conservative classification behind it.

Failure taxonomy (B04.1). Turns on one question: did the request reach the
network? DNS failure, connection refusal, and a failed TLS handshake all
happen before any application data is sent, so nothing can have been
broadcast and a retry is safe. A reset, a timeout, a truncated response, an
interrupted TLS connection, 429, and 5xx may all follow a delivered request,
so none of them permit a retry. HTTP 429 stays ambiguous rather than counting
as a rejection, because a rate limiter may reject before or after queuing the
work. Any error code this build has never seen classifies post-send: an
unknown failure cannot be proof that nothing happened.

Evidence lookup (B04.2, B04.3). NOT_FOUND is the dangerous result and gets the
strictest treatment. Absence can mean never broadcast, or invisible to this
node, or replaced, so permitsResubmission returns false for every observation
and no code path converts an absent result into a settlement right. Evidence is
bound to the exact request before it is interpreted, so a receipt from another
chain, another hash, or another wallet cannot resolve this intent. A receipt
that exists for our hash but does not prove our settlement is contradictory and
stays unbound rather than being resolved by guess. Hashless discovery is
deliberately absent: that is Coder C's Subgraph MCP path, and a second, weaker
way to decide a payment happened must not grow here.

Drift hardening (B04.4). The settlement boundary depends on a Privy policy, a
wallet, a chain, a token, and a cap that all live outside this repository and
can change with no commit and no review. detectDrift compares observed identity
against a reviewed baseline and fails closed on any difference, including a
lowered cap: judging whether a change is benign is not this module's job.
assertNoDrift throws rather than returning a value a caller could ignore.
Webhooks stay disabled, since signature verification is unproven and polling is
already complete.

Production entry point (B04.5). Exports only the frozen ports and coarse
sanitized error codes, so provider error text carrying bodies and headers never
crosses the seam. A test asserts no import reaches an A- or C-owned package
rather than trusting review to catch it. The compatibility manifest states what
the host must supply, what the adapter does not do, and its live gaps, so
fixtures cannot masquerade as live evidence.
The review noted that PersistedIdentity declared a nonce nobody reads, which
implies a wrong-nonce defence that does not exist: binding is done on the
transaction hash alone. Removed, with a comment recording why, rather than
leaving a field that overstates what the type checks.
@cloudflare-workers-and-pages

Copy link
Copy Markdown

Deploying with  Cloudflare Workers  Cloudflare Workers

The latest updates on your project. Learn more about integrating Git with Workers.

Status Name Latest Commit Updated (UTC)
❌ Deployment failed
View logs
oneshot 154d8cc Sep 07 2026, 03:17 PM

@selezenart
selezenart merged commit 329ad33 into milestone/b03-live-settlement-harness Sep 7, 2026
3 of 4 checks passed
@SuPuHe
SuPuHe deleted the milestone/b04-ambiguity-integration branch September 7, 2026 21:15
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant