Repository navigation
feat(testkit-settlement): B06 Privy and Arc sponsor evidence - #41
Merged
Merged
Conversation
Adds a fail-closed verifier for the Privy and Arc sponsor evidence, a CLI that publishes a sanitized report, an evidence index, and the B06 handoff document. The live Arc Testnet run already happened and is recorded in docs/settlement/LIVE_EVIDENCE.md, so this milestone re-verifies that record rather than executing another payment. What it checks is the binding rather than the label: - Privy denials only count when the broadcast and settlement counters were observed at zero, and a drill that omits the amounts it compared fails rather than skipping the check. - The Arc settlement must match the pinned network and token, carry a canonical integer amount, and publish an explorer link that is https, on an allowed host, and contains the transaction hash on screen. - The lost-response drill must reach UNKNOWN, reconcile to the original transaction, and leave exactly one settlement. - The mainnet profile must be disabled, unpinned, and carry no chain, RPC, explorer, or token value. Readiness is the absence of usable values, not a flag. - Qualification statuses are computed, so any failing section or a non-live record downgrades a sponsor to NOT VERIFIED. The sanitization audit applies the arc-adapter redaction contract at every level, including scalars nested in arrays and the query string of an allowlisted URL. Two public fields need a narrow exemption from the generic rules: token_contract matches the token key pattern, and explorer_url embeds the transaction hash. Both are load-bearing evidence, so the exemption lives here with a per-field shape check rather than widening the shared adapter contract for every caller.
selezenart
marked this pull request as ready for review
September 8, 2026 21:30
Deploying with
|
| Status | Name | Latest Commit | Updated (UTC) |
|---|---|---|---|
| ✅ Deployment successful! View logs |
oneshot | 8ea308b | Sep 08 2026, 09:53 PM |
Gate B and the following Gate A round found three ways the evidence engine could report a pass it had not earned. Receipt validation stopped at the receipt level, so a malformed log entry threw from inside the adapter instead of producing a listed failure. Every log is now checked for address, data, logIndex, and a string topics array. The public-field allowlist shared one permissive guard, which would have accepted a short JWT-shaped string under token_symbol or explorer_host. That guard is gone; each allowlisted field now has its own shape: EVM address, asset symbol, decimal count, hostname, https URL. The replay check matched REPLAY as a substring, so a tampered NOT_REPLAYED would have satisfied a check asserting the opposite. It now matches REPLAYED or RETURNED_EXISTING_RESULT exactly, with tests for the tampered spellings.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
Adds the B06 sponsor evidence bundle: a fail-closed verifier for the Privy
authorization boundary and the Arc Testnet settlement rail, a CLI that publishes
a sanitized report, an evidence index, and the handoff document.
The live Arc Testnet run already happened and is recorded on
develop(
docs/settlement/LIVE_EVIDENCE.md, statusLIVE_RUN). B06 re-verifies thatrecord rather than executing another payment: a second live settlement would
spend testnet funds to prove nothing the recorded run does not already prove.
Verify with one command:
Scope and acceptance criteria
NOT VERIFIEDwhere proof is absentHandoff artifact:
docs/settlement/B06_SPONSOR_EVIDENCE.md.Product and security invariants
Invariant notes:
recorded evidence. The recovery record must show exactly one settlement and
zero replacement submissions, and a tampered counter fails the bundle.
UNKNOWNwithout blind retry: the drill must showUNKNOWNreconcilingto the original transaction through a read-only lookup.
verifier reads recorded evidence and repository state only.
bigintfrom canonical integer strings.contract at every level, including scalars nested in arrays and the query
string of an allowlisted URL.
Test matrix cases selected: Privy denial, lost payment response, same request
twice. Each is asserted in both directions — the recorded evidence passes, and a
tampered record fails.
Note on the redaction allowlist
Two public fields trip the adapter's generic rules:
token_contractmatches thetokenkey-name pattern, andexplorer_urlembeds the 32-byte transactionhash. Both are load-bearing — drop them and the bundle no longer proves which
asset moved or where to verify it.
packages/arc-adapter/src/redaction.tsis deliberately not modified. Theexemption lives in B06 with a per-field shape check:
token_contractmust be anEVM address,
explorer_urlmust be an https URL with no embedded credentialsand is still scanned for credential patterns with the transaction hash stripped.
No other caller of the shared contract is affected.
Validation
Commands and results:
Independent review evidence
Gate A — exact candidate tree before push
Three rounds. Round three is the tree that was pushed.
Round 1 —
83d9e8091f8fe093bfdac83681187560ba1504b9—VERDICT: FAILOne blocking finding, since fixed: the sanitization walk recursed into arrays
but returned early for scalar elements, so a PEM key or JWT nested in an array
passed the audit while the same value under a scalar key failed. A hole in a
security-enforcing check. Fixed, and the fix is asserted by tests in the failure
direction.
Round 2 —
1f9f5ed88d25ae9cc18c7ad2ed4f809f72247cbc—VERDICT: PASSNo blocking findings. Three non-blocking, all fixed rather than carried:
receipt validation stopped at "non-null object";
checkMainnetReadinessreadthe compile-time profile so the enabled and carries-values directions were
unassertable; and
evidence:b06ran the compiled output without building. Thereviewer's residual risk about
token_contractaccepting any short public valueis closed by requiring an EVM address shape.
Round 3 — the reviewed and pushed tree
Base commit SHA:
0291b684e187557e13c47869359cbab445ee4148Candidate tree SHA:
e9f89504866075b50201814f4a5da0d494c29028Candidate commit SHA:
310daf16703957650e6422420fddedc3b627ab59Reviewer tool:
free-pi-cliReviewer model:
deepseek-v4-flashVerdict:
VERDICT: PASSFindings or residual risks: no blocking findings. Three non-blocking, carried:
parseReceiptvalidates receipt-level fields but not each log entry'sshape; a malformed log still exits non-zero rather than producing a listed
failure.
develop; there is no fileoverlap with the commits merged since.
arc.transfer-identity-recordedpasses conditionally because the publishedbundle carries no raw receipt. Capturing a sanitized receipt would let the
bundle exercise
verifyReceiptend to end.The reviewed tree equals the committed tree.
Gate B — exact remote PR head
310daf16703957650e6422420fddedc3b627ab59e9f89504866075b50201814f4a5da0d494c29028free-pi-clideepseek-v4-flashVERDICT: PASSparseReceiptvalidates receipt-level fields but not individual log entryshapes; a malformed log throws from inside
verifyReceiptrather thanproducing a listed failure. Fail-closed either way.
isPublicIdentifierwould accept a short JWT-shaped string under ahypothetical
token_symbolorexplorer_hostkey. Not reachable in thecurrent bundle, where
token_contractrequires an EVM address shape andexplorer_urlrequires https plus a content scan.OFFLINE_PROTECTED/UNPUBLISHEDterminology drift betweendocs/settlement/LIVE_EVIDENCE.mdandpackages/arc-adapter/src/profiles.ts,left to its own change in a base-owned file.
Reviewer evidence: head tree equals the Gate A tree; branch diff is exactly 8
files with no path overlap against the commits merged into
developsince thefork point; the B06 test file was re-run independently on the exact head; all
five mainnet-readiness artifacts and every cited adapter file exist in the head
tree.
Milestone readiness: scope and acceptance criteria PASS, tests and required
checks PASS, security/privacy/secrets PASS, documentation and operations PASS,
ready for human review PASS.
Agent policy / repository-policyand all applicable CI checks pass.Risk and rollback
Residual risks:
listed check.
not exercised on it; the check says so rather than claiming otherwise.
docs/settlement/LIVE_EVIDENCE.mdlabels the mainnet profileOFFLINE_PROTECTEDwhileprofiles.tsand B06 useUNPUBLISHED. Realterminology drift in a base-owned file; left for its own change.
Rollback: additive. Reverting the commit removes the evidence module, its CLI,
tests, the index, and the document. Nothing else imports them.
Human merge