diff --git a/integrations/xchk-registry/CROSSWALK.md b/integrations/xchk-registry/CROSSWALK.md new file mode 100644 index 00000000..90df3b49 --- /dev/null +++ b/integrations/xchk-registry/CROSSWALK.md @@ -0,0 +1,126 @@ +# xChk Sealed Receipts Cross-walk + +xChk is a registry that licenses AI agents under a verified person and seals a record of each gated act, with the person's own passkey assertion on the acts they answered. This page shows how a TRACE record points at one of those receipts, so a reader can find the approval, check who gave it and against what, and do so offline. It is for teams whose runtime emits Trust Records and whose approvals go through an xChk registry. + +> **Non-normative.** This document is informative only. Nothing here changes TRACE v0.2 schema fields, wire formats, required claims, or conformance requirements. "TRACE" means the Trust Record defined in [`spec/trace-v0.2.md`](https://github.com/agentrust-io/trace-spec/blob/main/spec/trace-v0.2.md). + +--- + +## Purpose + +TRACE records the runtime side: what ran, where, under which policy, which tools were called. An xChk registry records the authority side: for each act an agent proposed, what the gate decided, and when a person was asked, who answered, how they proved it was them, and what exactly they answered. A runtime that produces its own Trust Record and an xChk registry are different parties in different places; in the fixtures here the registry is also the producer, so one key signs the Trust Record, the seal and the binding, and what the fixtures show is one party pointing at its own receipt and the receipt verifying on its own terms. The `references` block (spec section 3.1.2) registers `rel: "approval-outcome"` for "an attributable human approval attached to a step-up or defer decision". This cross-walk shows an xChk sealed receipt as that referenced object, and what a relying party may establish from one. + +The [CHAP cross-walk](https://github.com/agentrust-io/trace-spec/blob/main/docs/crosswalks/chap-review-decisions.md) does the same for a review log and names, in its boundary, what a log without signatures cannot show: who wrote it. The receipt here is the case where that is answered: the approval carries the approver's WebAuthn assertion over the record it answered, and the registry's signature binding that credential to a named, identity-proofed person. + +## What an xChk sealed receipt is + +A **record** is the gate's account of one act: plate, sequence, time, tool, a summary of the command, a digest of its parameters, the decision (`allow`, `attest`, `forbid`, and for an answered ask `approved`, `denied` or `expired`), and for a ceremony the approver's email and method. `approved` and `denied` are the answers a person gave; `expired` is an ask nobody answered within its life, and it is on the record too. Its hash is `sha256` over its canonical form (keys sorted by UTF-16 code unit, no whitespace, JSON scalars with integers only among numbers), which for these records is byte for byte RFC 8785. + +The **record** is the referenced object; its hash is the reference's `id` and `digest`. A **bundle** is the carrier the registry serves for it at `/api/receipt//bundle`: the record; the Merkle path from its hash to the **seal** the registry wrote over that window of the plate's chain; the seal's fields and hash; the registry's signatures over the seal hash (Ed25519, and ML-DSA-65 where the registry runs hybrid); the published public keys those check against; when the seal has been anchored, the raw Ravencoin transaction carrying the seal hash and the Merkle block that places it; and, when a person answered, the **approver block**: + +- `assertion`: the passkey's `clientDataJSON`, `authenticatorData` and ECDSA P-256 signature from the ceremony that answered; +- `publicKey`: the credential's public key as an uncompressed P-256 point; +- `credentialId`, `email`, `authLevel` (the identity proofing behind the credential), `authMethod`, `verifiedAt`; +- `binding`: the registry's signature over `{recordHash, attestationId, credentialId, publicKey, approverEmail, authLevel, authMethod, verifiedAt}`, tying that credential to that person for that record. +- `challenge` (ceremonies from 18 October 2026, rule `ask-v1`): the three facts the device signed over, fixed before the answer: the attestation id, the prompt the person saw, the digest of the action's parameters. The challenge in `clientDataJSON` is `sha256` over their canonical JSON, so the assertion itself names the ask it answered. A bundle without it is from an earlier ceremony whose challenge was a nonce, and there only `binding` pairs the assertion with the record. + +Beside it, `basis` (the rule that made the gate ask) and `decision` (the ask as the person saw it and the answer as they gave it, including an amendment when they approved with changes). The bundle carries its own `howToVerify` steps, and the registry publishes a standard-library-only verifier, `verify_receipt.py`, that runs them with no network. + +## Field mapping + +| TRACE `references` field | Value for an xChk receipt | Notes | +|---|---|---| +| `rel` | `approval-outcome` | Registered value. The registry belongs in `resolver`, not in a vendor `rel`. | +| `id` | the record hash, 64 hex | Unique and stable in the registry; the bundle is served under it. | +| `resolver` | the registry origin, e.g. `https://in.xchk.io` | The party obliged to keep `id` resolvable. | +| `retention` | the registry's undertaking | Optional. A sealed and anchored record is kept for the life of the plate's chain; the registry's legal-hold rules can extend it. Nothing in either specification enforces it. | +| `digest` | `sha256:` + the record hash | Over the record, not the bundle. The record's canonical form is RFC 8785 for these records, so `rfc8785.dumps(bundle.record)` hashed equals both the registry's `recordHash` and this digest. One number, recomputable on either side. | + +The producer in the fixtures is the registry itself, minting a software-only Trust Record per run (`origin` absent: the gate is in the execution path): one `approval-outcome` per act a person was asked about, approved or not. Each fixture record is cut from that to a single reference, so that one case fails one step; the run's own record carries them all. A runtime producing its own Trust Record would carry the same entries, taken from the gate's answers. + +## Verifier obligations for this profile + +Given a Trust Record and access to the registry named in `resolver`: + +1. Verify the Trust Record as usual. This step does not touch the reference, and an unresolvable reference is not a reason to reject the record (section 3.1.2, rule 3). A record that does not verify ends here: nothing it carries, the reference included, is evidence, and no approval verdict is drawn from it (`record-invalid`), whatever the bundle it points at says. +2. Resolve `id` at `/api/receipt//bundle`. If there is no such receipt, report the approval as unconfirmed. +3. Recompute `sha256` over the RFC 8785 form of `bundle.record` and compare it with `digest`. A mismatch means the registry no longer serves the record the Trust Record pointed at. +4. Run the bundle's offline checks: the record hash; the Merkle path to the seal root; the seal hash; the registry's signatures over it; the approver's assertion (ECDSA P-256 over `authenticatorData || sha256(clientDataJSON)`, a `webauthn.get` ceremony, the user-verified flag set); the registry's binding, and that the binding names this record hash, this credential, and **this public key** (the bundle's own `howToVerify` and `approver.rules` state the same); when `approver.challenge` is present, that `clientDataJSON.challenge` equals `sha256` over the canonical `challenge.fields` and that those fields are this ceremony's id, `decision.prompt` and `decision.actionParamsHash`, recomputed and never read from the bundle's `expected`; that the decision block cites the sealed record (`decision.attestationHash` equals `record.attestationHash`, and is present: every ceremony record the registry has written since 7 August 2026 carries the hash and every decision block it issues cites it, so a decision block without the citation is refused, not skipped); the anchor when present. Any failure contradicts the approval. Then (2 Nov 2026) run it again with `--keys` and the registry's key document, saved once from `/.well-known/xchk-keys.json`: every key the bundle pins must be in it, active or retired, and the bundle's root key must be its root, or the keys the signatures were checked with were never the registry's. Two honest limits of the offline run: without that document the registry keys the script checks against are the ones the bundle carries, so every signature check proves consistency under the bundle's own keys and nothing more (the bundle's SLH-DSA root statement lists them and needs a FIPS 205 implementation the script does not ship); and the ML-DSA-65 half of each hybrid signature needs `dilithium-py`, without which the script reports that half as pending, never as passed. In this repository's test only the Ed25519 half is verified. +5. Read `record.disposition`. `approved` is an approval. `denied` and `expired` (asked, no answer within the ask's life) are not, and both are on the record. `decision.amendment`, when present, is informational: the registry's record that the person approved with changes, carried for the reader. This verifier does not authenticate the amendment's scope against a signed statement, and a relying party must not let it widen or narrow what it treats as approved (see the boundary). The approval a relying party may rely on is of the ask as proposed. +6. Where the relying party holds the executed call, compare it with `record.paramsHash` (the digest the gate took over the tool and its parameters). +7. Apply your own floor to `approver.authLevel`: it names the identity proofing the registry did for that credential, and the relying party trusts the registry for it as it trusts any issuer. + +Every step from 2 to 5 has a fixture that fails at that step; step 4 has three (the approver's key, the challenge, and the registry's keys). + +Two rules the verifier enforces that a relying party must not relax (19 October 2026): + +- **The ask names the ceremony the record and the binding commit to.** With rule `ask-v1`, the `attestationId` the + device signed over must equal the `attestationId` in the sealed record and the one in the registry-signed + `binding`, not only the outer `approver.attestationId`, which is unsigned. Without this, a genuine answer by the + same credential to a *different* ask, placed beside this record's genuine binding, passes every other check; the + test suite carries that transplant and it is refused. +- **Absence of failure is not confirmation.** The verifier's exit 0 means no check failed; steps it could not run + are listed as pending, not passed. An approval verdict needs the approval evidence to have been present and + checked: run the verifier with `--require-approval` (exit 3 names what is missing), as the fixture test does. + A bundle stripped of its approver still has an intact record and seal; it is an unverified approval, never a + confirmed one. The reverse holds too: approval evidence intact with the seal, the Merkle path to it or the + registry's signature over it missing is an approval whose place in the sealed chain is unchecked. Strict mode + refuses it (`seal-chain-incomplete`, with `sealChainMissing` naming the part), and the fixture verdict reports it as + `approval-unsealed`, distinct from a sealed confirmation. The verifier's `--json` output is the structured form of this: the checks that ran, with OK or + FAIL, the count of steps that could not run, the approval evidence still missing, and `boundIdentity`, the person + and proofing level taken only from the registry-signed binding, never from the readable `approver.email` or + `authLevel` beside it; a caller acts on that, not on the exit code alone. Both fields are null whenever the exit is + not 0 (2 Nov 2026): a report that does not verify names nobody and commits to nothing; `withheld` names them, so + absent and withheld read apart. +- **The registry's keys are the relying party's to pin, not the bundle's to declare** (2 Nov 2026, review of #350 by + drk-ram). He re-signed fixture `01` under his own Ed25519 and ML-DSA-65 keys, rewrote the pinned key list and the + root statement's list to match, and `--require-approval` still exited 0: every key the verifier checks with is the + one the bundle carries, so the checks prove the bundle is consistent under its own keys. The fixture test now pins + the registry's key document (`examples/approval-outcome/xchk-keys/`, as served on 2 Nov 2026) and passes it to the + verifier with `--keys`; a bundle whose keys are not in it, or a relying party that pinned no document, gets the + verdict `approval-consistent-key-not-pinned`, never `approval-confirmed`. Fixture `09` is that re-keyed bundle. The + verifier's `--json` report carries `keyDocument` (null when none was supplied) so a caller can tell the two apart. + A revoked key is refused however the document says it (the `revoked` list, a `revokedAt`, or a `status` other than + active or retired), and a revoked entry published without its public key is matched by key id. Limits, by design: a + retired key's `notBefore`/`notAfter` are not compared with the seal's time; the document's `registry` string is never + compared with the bundle's `wellKnown`, because the relying party chose the document and only key material decides; + and a bundle that pins no key has nothing to check, so `keyDocument.allPinned` is null there and the verdict falls + to the seal-chain rules above. +- **An amendment the sealed record does not commit to is refused.** `decision.amendment` is readable text. The + verifier checks that the sealed `record.paramsHash` recomputes over the amended command (the served + `amendment.boundAs`, itself unsigned, counts only when it hashes to the sealed digest) and, where the ask carries a + digest, that `originalParamsHash` equals `decision.actionParamsHash`; an amendment typed into a bundle after issue, + or edited after issue, contradicts the approval, and the fixture test carries both mutations. This is a refusal + only: a committed amendment does not authenticate its scope, and `decision.amendment` stays informational (see + the boundary). + +## Boundary + +Composed this way, a Trust Record and an xChk receipt establish that the record points at a specific sealed act, that the act is unchanged and sits in a chain the registry signed (and anchored, once the seal's anchor has confirmed; the fixtures' seals had not), that a named person whose credential the registry bound answered it with a user-verified passkey, and what they answered. They do not establish: + +- **That the approval was checked before the act ran.** A Trust Record is issued per execution, so it cannot carry a commitment someone needs to check beforehand. In xChk the gate holds the act until the ask is answered and the receipt is the gate's own record of that order, but the Trust Record does not carry the gate's ordering claim; `authorized-intent`, through the PIC/TRACE bridge, is the relation for a pre-execution authorization, and is the natural next profile for these receipts. +- **That the executed act is the approved one.** `record.paramsHash` binds the ask to the parameters the gate saw; binding that to what the runtime executed is the runtime's job, by comparing the call it made with that digest. +- **Which ask the assertion answered, for a ceremony before 18 October 2026.** In those bundles the passkey challenge was a nonce, so the assertion proves a user-verified ceremony by that credential at that origin and the registry's `binding` is the only thing that pairs it with the record: a reader who does not take the registry's word on the pairing has the Merkle chain and the anchor for the record, not for the pairing. From that date the challenge is derived from the ask and the assertion names it (fixture `08`). +- **That an amendment is the person's.** `decision.amendment.command` is what the registry records the person + approved with changes. It is informational: this verifier does not authenticate the amendment's scope against a + signed statement (the passkey assertion covers the ask as proposed; the amended command is committed by the + registry's seal over the record, not by a signature of the person's), and a relying party must not let an unsigned + amendment widen or narrow what it treats as approved. Further limits: an amendment removed from a bundle after + issue leaves a plain approval that verifies; the unamended `record.paramsHash` and the signed `actionParamsHash` + are different digests of the same act that this verifier does not relate; a ceremony record sealed before + 19 September 2026 carries no `paramsHash` at all, so its amendment is reported as not checkable. This is under + separate assessment and is the one open item of this crosswalk. +- **That the policy was right or the person was the right person.** `basis` says which rule asked and `authLevel` says how the person was proofed; whether either suffices is the relying party's policy. + +## Conformance fixtures + +Nine records and eight bundles in [`examples/approval-outcome/`](examples/approval-outcome/), minted by the registry at `in.xchk.io` for one run of one plate: approval confirmed; the bundle altered after issue; a declined ask; an ask nobody answered; a reference to no receipt; an impersonated approver, whose assertion verifies with the key the bundle offers while the registry's binding names another; and an approval with changes, a worked example under the boundary's limitations (`decision.amendment` is informational and its scope is not yet authenticated); the approver's own assertion from another approval in the run, which passes every check but the one on the challenge the device signed; and (derived, not minted) the confirmed approval re-signed under keys that are not the registry's, which passes every check but the key document's. [`tests/test_approval_outcome_fixtures.py`](tests/test_approval_outcome_fixtures.py) recomputes every verdict from the committed bytes, with the registry's key document pinned beside the fixtures. + +## References + +- TRACE v0.2 specification, section 3.1.2 (`references`): [`spec/trace-v0.2.md`](https://github.com/agentrust-io/trace-spec/blob/main/spec/trace-v0.2.md) +- xChk registry: ; receipt endpoint `/api/receipt//bundle`; published keys `/.well-known/xchk-keys.json` (pinned beside the fixtures as served on 2 Nov 2026, and passed to the verifier with `--keys`) +- `verify_receipt.py`, the registry's offline verifier (MIT), as the registry serves it: ; vendored beside this document as [`verify_receipt.py`](verify_receipt.py) +- The fixture generator, `scripts/trace-fixtures.js`, is part of the registry's own code, which is not public; regeneration is the registry operator's +- RFC 8785, JSON Canonicalization Scheme: +- WebAuthn Level 3, assertion signature: diff --git a/integrations/xchk-registry/NOTICE b/integrations/xchk-registry/NOTICE index 1c021478..502e067a 100644 --- a/integrations/xchk-registry/NOTICE +++ b/integrations/xchk-registry/NOTICE @@ -4,3 +4,12 @@ examples/01-trust-record.json: a Trust Record minted and signed by the registry ENG-WNP3, run 3057 (18 October 2026), cut to one approval-outcome reference. examples/expected.json pins the registry's seal key, as published at https://in.xchk.io/.well-known/xchk-keys.json, so the test runs offline. The record carries the plate owner's identifiers; he chose to publish it. + +examples/approval-outcome/: eight Trust Records and seven receipt bundles minted and signed by the registry at +https://in.xchk.io for plate ENG-WNP3, run 3057 (17 October 2026), with expected.json as the registry's own record +of each case; the altered copies (02, 06, 08) were made by the registry's fixture generator. They carry the plate +owner's identifiers; he chose to publish them. + +verify_receipt.py: the xChk registry's offline receipt verifier, copyright (c) 2026 Sean MacGuire, MIT License +(the notice in the file's header), vendored for the fixtures' tests as the registry serves it at +https://in.xchk.io/verify/verify_receipt.py. Not part of the agentrust-trace package. diff --git a/integrations/xchk-registry/README.md b/integrations/xchk-registry/README.md index d9867c4b..6265110d 100644 --- a/integrations/xchk-registry/README.md +++ b/integrations/xchk-registry/README.md @@ -48,11 +48,33 @@ was made against, and `verified_at_overridden`, so a historical verdict is never reported it; this tool passes no revocation bundle or store, so it reports `no_check_performed`, which is not an affirming appraisal (section 3.2.3). A stale or tampered record is `invalid`, with the reason. +## Approval-outcome references: the crosswalk and fixtures + +What an `approval-outcome` reference resolves to, and what a relying party may conclude from it, is in +[`CROSSWALK.md`](CROSSWALK.md), with nine records and eight receipt bundles in +[`examples/approval-outcome/`](examples/approval-outcome/) (one case per way the composition can fail, each +recomputed from the committed bytes by `tests/test_approval_outcome_fixtures.py`) and the registry's offline receipt +verifier vendored as [`verify_receipt.py`](verify_receipt.py) (MIT; standard library only). The verifier binds the +passkey's signed ask to the ceremony the sealed record and the registry-signed binding commit to, and its +`--require-approval` mode refuses to call an approval verified when the approval evidence is absent; its `--keys` +mode (2 Nov 2026) checks the keys the bundle pins against the registry's key document, saved once from +`/.well-known/xchk-keys.json`, without which every signature check proves only that the bundle is consistent under +its own keys. All three are covered by `tests/test_verify_receipt_regressions.py`. + +What this integration does **not** ship: a relying-party verdict in code. The composition logic lives in the fixture +test as the worked example; a packaged `assess()` with structured verifier results, identity taken only from the +signed binding, and an authenticated amendment scope is under separate assessment and follows in this directory +once settled. Until then `decision.amendment` is informational, as the crosswalk's boundary says. + +Adopters: xChk (in.xchk.io) mints the Trust Record per run and points at its sealed receipts as `approval-outcome` +references; the registry is the only relying party so far (software-only, Level 0). + ## Run it ``` pip install -e "integrations/xchk-registry[test]" agentrust-trace-tests -pytest integrations/xchk-registry/tests -q # offline; REGISTRY_LIVE=1 adds one live key fetch +pytest integrations/xchk-registry/tests -q # offline; REGISTRY_LIVE=1 adds one live key fetch; dilithium-py (in [test]) is required +python integrations/xchk-registry/verify_receipt.py integrations/xchk-registry/examples/approval-outcome/01-approval-confirmed.bundle.json --require-approval --keys integrations/xchk-registry/examples/approval-outcome/xchk-keys/in.xchk.io.2026-11-02.json trace-tests verify --record integrations/xchk-registry/examples/01-trust-record.json --level 0 --max-age 315360000 ``` diff --git a/integrations/xchk-registry/examples/approval-outcome/01-approval-confirmed.bundle.json b/integrations/xchk-registry/examples/approval-outcome/01-approval-confirmed.bundle.json new file mode 100644 index 00000000..8a6a92a1 --- /dev/null +++ b/integrations/xchk-registry/examples/approval-outcome/01-approval-confirmed.bundle.json @@ -0,0 +1,368 @@ +{ + "format": "xchk-receipt-bundle/2", + "issuer": { + "name": "xChk registry", + "base": "https://in.xchk.io", + "servedAt": "2026-10-17T15:54:51.987Z", + "headline": "ENG-WNP3: APPROVED terminal in global at 2026-10-17T15:46:00.571Z — approved by sean@maclawran.ca." + }, + "recordHash": "aa2bfd5b1d9b6307ed22eb0daa4213383beecb57d7d31ec011060ac98f7fe0b5", + "record": { + "v": 1, + "agentId": "6acbf860a627414b66045478", + "plate": "ENG-WNP3", + "seq": 9819, + "ts": "2026-10-17T15:46:00.571Z", + "harness": "claude", + "runSeq": 3057, + "runRef": "ENG WNP3.3057", + "area": "global", + "tool": "terminal", + "summary": "P=\".ab1-probe-approve1-$(date +%s)\"; rm -f \"$P\" && echo \"probe 1 ran (nothing existed to remove)\"", + "paramsHash": "a791bccfa14f0666b7082aab7586455f1898da48651cbbbb643e0df3402655c6", + "amount": null, + "disposition": "approved", + "code": null, + "reason": null, + "deskCondition": "normal", + "continuityClass": "standard", + "authRef": "c2486b7f4874e5d08aba0725", + "prevHash": "25607c8e2e529dddce618b49b1c11da6b302a6687c6d44b335f304e904dc796f", + "rvnBlock": "000000000001303bd2857ce3c400c92e8bcf8b97c14eda4f85650e03f91ef3e3@4585364", + "approverEmail": "sean@maclawran.ca", + "authMethod": "webauthn", + "attestationId": "6ad398295f7026f62ae7b863", + "attestationHash": "d7896ca4608bcdd8581ce6c0bb5917e541d40d635334e1a8746d7fc1bc230d5e", + "photoUrl": "https://xchk-main.s3.us-east-005.backblazeb2.com/xchk/xchk/baseline/att_6ad398295f7026f62ae7b863/0.jpg", + "model": "claude-fable-5-1" + }, + "canonicalization": { + "profile": "JSON with object keys sorted (code-unit order), no whitespace, scalars as JSON.stringify would emit them, undefined omitted, integers only; hash = sha256 over the UTF-8 bytes", + "hashedConditionalKeys": [ + "rvnBlock", + "approverEmail", + "authMethod", + "requiredAuthMethod", + "attestationId", + "attestationHash", + "photoUrl", + "labelsHash", + "delegationHash", + "model", + "tokensIn", + "tokensOut", + "tokensCacheRead", + "contextPct", + "actor", + "chargeCode", + "workspace", + "policyHash", + "outcomeOf", + "resultHash", + "endedAt", + "artifactHash" + ], + "note": "conditional keys are present only when the record carried them; absent keys are absent from the bytes, not null" + }, + "merkle": { + "proof": [ + { + "side": "L", + "hash": "25607c8e2e529dddce618b49b1c11da6b302a6687c6d44b335f304e904dc796f" + }, + { + "side": "R", + "hash": "61cbbb71667c7ad8ed2fb67feadf3454a801ced41e3d303ba7b8297524c0e86b" + }, + { + "side": "R", + "hash": "c7f7fb52d081b787566876416919dca904cef18613bb63efa3e28b0ab8eeced5" + }, + { + "side": "R", + "hash": "30e986cfeef36f573d77f3f49948c8bc3248ee8e068d439c149ee72dbe2dad8b" + }, + { + "side": "R", + "hash": "b1f52c8bef88f4187114b4cfab6922468a0e2f3775dc9b6fa7d1479458d02019" + }, + { + "side": "R", + "hash": "b8de3bc958dcdcd07dfc74b47a39ede41e6c649d39f09505b88802fbfb5e7739" + } + ], + "leafCount": 37, + "rule": "node = sha256(left_hex + right_hex) over the hex strings; an odd node is promoted unhashed; the leaf is the record hash" + }, + "seal": { + "v": 1, + "agentId": "6acbf860a627414b66045478", + "plate": "ENG-WNP3", + "sealSeq": 1496, + "windowStart": "2026-10-17T15:44:25.565Z", + "windowEnd": "2026-10-17T15:53:48.404Z", + "count": 37, + "issuedCount": 37, + "seqStart": 9818, + "seqEnd": 9854, + "merkleRoot": "2662a87b9401541c4917428bda73596a608ad5ea556acdc110639e2e618092e9", + "deskCondition": "normal", + "prevSealHash": "82904359e52743e49d8c822814094b1519e02214578adef89487469b555c68c5", + "rvnBlock": "00000000000081b33c166cf1961e598cb91d40a6fef817b0d2d8aaf3b6b62753@4585373", + "profileHash": "9bbe0635c0a05cc8107d40ad5bb2d8b227c8125d395f41620bcd371123319701", + "sealHash": "a00007915e398e7a5f6fdd0863a7ebc0f3eac99da656b85a4fad0d06a8c15710", + "rule": "sealHash = sha256(canonical({v, agentId, plate, sealSeq, windowStart, windowEnd, count, issuedCount, seqStart, seqEnd, merkleRoot, deskCondition, prevSealHash[, rvnBlock][, profileHash]}))" + }, + "registrySignature": { + "alg": "ed25519+ml-dsa-65", + "keyId": "5ecb3da505414c4f", + "signature": "v+SHukcW2TmkZbafId5igQnOU75fbb51UNUJFRwp5DdQd1ebk+9Z7wZ9BXfBpmZUWLBgm3ZuNlP+IbVZrKH3Bg==", + "signedAt": "2026-10-17T15:53:48.458Z", + "signatures": [ + { + "alg": "ed25519", + "keyId": "5ecb3da505414c4f", + "signature": "v+SHukcW2TmkZbafId5igQnOU75fbb51UNUJFRwp5DdQd1ebk+9Z7wZ9BXfBpmZUWLBgm3ZuNlP+IbVZrKH3Bg==" + }, + { + "alg": "ml-dsa-65", + "keyId": "8bb85bc1f41c568c", + "signature": "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" + } + ], + "signedOver": "the UTF-8 bytes of seal.sealHash", + "publicKeyRaw": "mn02E1XyTkaVN6DEOemU5OADMUAUjPHw67oR5KKIM3k=", + "publicKeyPem": "-----BEGIN PUBLIC KEY-----\nMCowBQYDK2VwAyEAmn02E1XyTkaVN6DEOemU5OADMUAUjPHw67oR5KKIM3k=\n-----END PUBLIC KEY-----\n", + "wellKnown": "https://in.xchk.io/.well-known/xchk-keys.json", + "keys": [ + { + "alg": "ed25519", + "keyId": "5ecb3da505414c4f", + "publicKeyRaw": "mn02E1XyTkaVN6DEOemU5OADMUAUjPHw67oR5KKIM3k=" + }, + { + "alg": "ml-dsa-65", + "keyId": "8bb85bc1f41c568c", + "publicKeyRaw": "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" + } + ], + "retired": [], + "publicKeyRawPq": "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", + "keyIdPq": "8bb85bc1f41c568c", + "root": { + "alg": "slh-dsa-sha2-128s", + "standard": "FIPS 205", + "keyId": "acc7ad1aeb3ef177", + "publicKeyRaw": "4aIhDuj3TZPwqb9HT8TzVJnkvle4jVUMhWkn/BfmypM=", + "statement": { + "v": 1, + "registry": "https://in.xchk.io", + "keys": [ + { + "alg": "ed25519", + "keyId": "5ecb3da505414c4f", + "publicKeyRaw": "mn02E1XyTkaVN6DEOemU5OADMUAUjPHw67oR5KKIM3k=" + }, + { + "alg": "ml-dsa-65", + "keyId": "8bb85bc1f41c568c", + "publicKeyRaw": "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" + } + ], + "retired": [], + "oidc": [ + { + "kid": "XWUv0uGESGdIG1MjOzbVjcwxB0CYtK0oZ9SZxNkH7h8", + "kty": "RSA", + "alg": "RS256", + "n": "zQwdJyTuyqQvB5zIXp9ULjX22k-R95Ls5j3IVUwLcI87I2VPUjsvy9oDGl5cq8Jl7Rt21d966AakANr8J1vT7gMpcmPOcEGVDdgdCprRs8cWNDo5uJ4ejt1LW65zRqW8xsxqHPm1aOxvjeUQfNgZFLn3VlSX01zgjggBLSwL18stLbyIzA2zcj4lpV-IrnBO3S6VUusoaO__kXjHv1-aH64wpVcsNLrBX6MWsnHM-KptbhKrk_qqXMJ7dokBxiIAH32VjZ73kTbVcSXoU2FshM_eQaonhYcRoD8PTXN3rxMaisj2pka9XZ1Apqy-EHf1dCoUphYxd_--FcT5PDQZaQ", + "e": "AQAB" + } + ], + "issuedAt": "2026-10-17T15:48:57.541Z" + }, + "signature": "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", + "rule": "SLH-DSA-SHA2-128s verify(publicKeyRaw, canonical(statement) bytes, signature); statement.keys are the keys this registry signs with" + }, + "rule": "HYBRID: for each entry in signatures, verify(keys[alg,keyId].publicKeyRaw, sealHash bytes, signature) — Ed25519 for alg ed25519, ML-DSA-65 (FIPS 204) for alg ml-dsa-65; ALL must verify. keyId = sha256(SPKI or raw key)[:16]. root, when present, is the SLH-DSA-SHA2-128s statement of these keys." + }, + "approver": { + "email": "sean@maclawran.ca", + "authLevel": "didit", + "authMethod": "webauthn", + "attestationId": "6ad398295f7026f62ae7b863", + "credentialId": "Yqa88hkURHnPqSTiV3o1jA", + "publicKey": { + "format": "ec-p256-uncompressed", + "alg": "ES256", + "raw": "BIWcVSzcT4ocdVb/bHtVrZNK/4RKRn1xhg6SE8TSy3QGpnJUufsDz2z+G1PqK3yP/7q5IPI9PEfjC77W/OxqD5k=" + }, + "assertion": { + "clientDataJSON": "eyJ0eXBlIjoid2ViYXV0aG4uZ2V0IiwiY2hhbGxlbmdlIjoiNUVMY0t2aUhybWxuUElaME9Ca0hMZE9tM05aalVKdEN5U3d5QUItcElNYyIsIm9yaWdpbiI6Imh0dHBzOi8vaW4ueGNoay5pbyIsImNyb3NzT3JpZ2luIjpmYWxzZX0", + "authenticatorData": "dcRETaEWF68z8NRCzR6PN99N5Mn8aYw-RadnYwZSFr0dAAAAAA", + "signature": "MEUCIQDCuR26urn4n7AYJ2_Ohd9_KJ7hRp6pEm2qG1mqjnjMbAIgdUuoz3nO2St6MasEmX3TvKYiv8MoFn1UA9_li9nWCB8", + "encoding": "base64url" + }, + "challenge": { + "rule": "ask-v1", + "fields": { + "v": 1, + "attestationId": "6ad398295f7026f62ae7b863", + "prompt": "ENG-WNP3.3057 (via Claude Code) wants to P=\".ab1-probe-approve1-$(date +%s)\"; rm -f \"$P\" && echo \"probe 1 ran (nothing existed to remove)\"", + "actionParamsHash": "5eee3b37a63eb957436a2bd51633d8a3c9a54f96c66e71f45fbd2d458373ca68" + }, + "expected": "5ELcKviHrmlnPIZ0OBkHLdOm3NZjUJtCySwyAB-pIMc", + "note": "the challenge the approver's device signed = base64url(sha256(canonical(fields))); fields are the ask as issued, before any answer; recompute, do not trust `expected`" + }, + "binding": { + "fields": { + "v": 1, + "recordHash": "aa2bfd5b1d9b6307ed22eb0daa4213383beecb57d7d31ec011060ac98f7fe0b5", + "attestationId": "6ad398295f7026f62ae7b863", + "credentialId": "Yqa88hkURHnPqSTiV3o1jA", + "publicKey": "BIWcVSzcT4ocdVb/bHtVrZNK/4RKRn1xhg6SE8TSy3QGpnJUufsDz2z+G1PqK3yP/7q5IPI9PEfjC77W/OxqD5k=", + "approverEmail": "sean@maclawran.ca", + "authLevel": "didit", + "authMethod": "webauthn", + "verifiedAt": "2026-10-17T15:46:00.404Z" + }, + "signature": "LpDId3mnpJVZn4ntyVIwrgy/sT1vdKmomgr8eoShKHRJhvh7xr7qvVD3ZhKaaYxa5rcL/E0JQX8ICh+Y/1vSDA==", + "keyId": "5ecb3da505414c4f", + "signedAt": "2026-10-17T15:54:51.971Z", + "alg": "ed25519+ml-dsa-65", + "signatures": [ + { + "alg": "ed25519", + "keyId": "5ecb3da505414c4f", + "signature": "LpDId3mnpJVZn4ntyVIwrgy/sT1vdKmomgr8eoShKHRJhvh7xr7qvVD3ZhKaaYxa5rcL/E0JQX8ICh+Y/1vSDA==" + }, + { + "alg": "ml-dsa-65", + "keyId": "8bb85bc1f41c568c", + "signature": "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" + } + ], + "rule": "registry signature(s) over canonical(fields): each of `signatures` with the registrySignature.keys entry of the same alg/keyId (hybrid: all must verify); `signature` is the Ed25519 half" + }, + "rules": [ + "assertion: WebAuthn signature = ECDSA-P256/SHA-256 over authenticatorData || sha256(clientDataJSON), verified with publicKey.raw (uncompressed point); clientDataJSON.type must be \"webauthn.get\"; authenticatorData flags must include UV (user verified)", + "binding: verify each of binding.signatures (or binding.signature with alg ed25519) over canonical(binding.fields) with the matching registrySignature.keys entry — Ed25519 and, when present, ML-DSA-65; all must verify; binding.fields.recordHash must equal recordHash, binding.fields.credentialId must equal the assertion credential, and binding.fields.publicKey must equal approver.publicKey.raw (17 Oct 2026: an assertion re-signed by another key, with that key offered, passes every other check)", + "challenge: when approver.challenge is present (rule ask-v1, ceremonies from 18 Oct 2026), clientDataJSON.challenge must equal base64url(sha256(canonical(challenge.fields))) with fields.attestationId = approver.attestationId, fields.prompt = decision.prompt and fields.actionParamsHash = decision.actionParamsHash: the device signed over the ask, so the assertion itself names the act it answered. Absent, the challenge was a nonce and only the binding pairs the assertion with the record (an assertion by the same credential over another ask passes every other check)" + ] + }, + "basis": { + "asked": { + "seq": 9818, + "ts": "2026-10-17T15:45:45.315Z", + "area": "global", + "tool": "terminal", + "summary": "P=\".ab1-probe-approve1-$(date +%s)\"; rm -f \"$P\" && echo \"probe 1 ran (nothing existed to remove)\"", + "paramsHash": "a791bccfa14f0666b7082aab7586455f1898da48651cbbbb643e0df3402655c6", + "code": "hook_escalation", + "reason": "destructive filesystem command outside scratch roots", + "recordHash": "25607c8e2e529dddce618b49b1c11da6b302a6687c6d44b335f304e904dc796f", + "model": "claude-fable-5-1" + }, + "grant": { + "area": "global", + "disposition": "allow", + "policyId": null, + "maxAmount": null, + "resources": [] + }, + "authorizeDisposition": "attest", + "area": "global", + "objective": null, + "rule": "asked = the attest record this ceremony answers (same plate, same action summary, raised just before the ceremony; cite it by recordHash); grant = the plate's grant rows as they stood when the ceremony was raised; asked.reason is the registry's stated reason for asking" + }, + "decision": { + "prompt": "ENG-WNP3.3057 (via Claude Code) wants to P=\".ab1-probe-approve1-$(date +%s)\"; rm -f \"$P\" && echo \"probe 1 ran (nothing existed to remove)\"", + "response": "approved", + "status": "completed", + "createdAt": "2026-10-17T15:45:45.553Z", + "respondedAt": "2026-10-17T15:46:00.404Z", + "by": "sean@maclawran.ca", + "authMethod": "webauthn", + "requiredAuthMethod": null, + "amendment": null, + "actionParamsHash": "5eee3b37a63eb957436a2bd51633d8a3c9a54f96c66e71f45fbd2d458373ca68", + "attestationHash": "d7896ca4608bcdd8581ce6c0bb5917e541d40d635334e1a8746d7fc1bc230d5e", + "attestationHashRule": "sha256 over the registry's canonical attestation JSON (utils/attestationHashUtils.computeAttestationHash: id, prompt, response, status, respondedAt, approver, method, amendment, delivery, chain …); recomputable on the registry, cited here so the record and this decision are bound" + }, + "legalHolds": null, + "anchor": { + "rvnTxId": null, + "rvnAnchoredAt": null, + "rvnBlock": "00000000000081b33c166cf1961e598cb91d40a6fef817b0d2d8aaf3b6b62753@4585373", + "explorer": null, + "otsProof": "8AgHtW3WwcdWHAjwIDmHgtDWxTNE7J5/xgGaHDFnrQrc3inlHM3qhjw4tw0GCPAQXdqsoXnzk3MwpP23KriFggjxIPLwuvDSO69qmiS9474S+Avisk6Nj3GHF2cAlCMhKZEgCPAgcg99+b7AHf2ZK3gpBTOQs3DbDNA7V9MlZXNzGCHcjq4I8CBgv3qhup4MMtQ5Z6CeKEgdkDbyf3ckONgeLlOyncp01gjxBGrTmg3wCL37YWeTW8icAIPf4w0u+QyOLi1odHRwczovL2FsaWNlLmJ0Yy5jYWxlbmRhci5vcGVudGltZXN0YW1wcy5vcmc=", + "otsCalendar": "https://a.pool.opentimestamps.org", + "otsBlockHeight": null, + "rule": "the anchor transaction carries sealHash in OP_RETURN; its raw bytes are captured once the transaction confirms (a few minutes) — download the bundle again for the offline anchor check, or use the explorer link" + }, + "howToVerify": [ + "1. canonicalize `record` per `canonicalization.profile`, sha256 it, compare to `recordHash`", + "2. walk `merkle.proof` from `recordHash` (L: sha256(step+cur), R: sha256(cur+step)); the result must equal `seal.merkleRoot`", + "3. canonicalize the seal fields per `seal.rule`, sha256 it, compare to `seal.sealHash`", + "4. verify every entry of `registrySignature.signatures` over the seal hash with the key of the same alg/keyId in `registrySignature.keys` (Ed25519 + ML-DSA-65 when hybrid); older bundles: Ed25519-verify `signature` with `publicKeyRaw`", + "5. if `approver` is present: verify the WebAuthn assertion with `approver.publicKey.raw`, then Ed25519-verify `approver.binding.signature` over canonical(`approver.binding.fields`) with the registry key, and require `approver.binding.fields.publicKey` to equal `approver.publicKey.raw`: the binding, not the bundle, names the key the assertion may be checked with; when `approver.challenge` is present, recompute base64url(sha256(canonical(`challenge.fields`))) and require it to equal `clientDataJSON.challenge`, with the fields equal to `approver.attestationId`, `decision.prompt` and `decision.actionParamsHash`", + "6. if `anchor.proof` is present: check the OP_RETURN, the txid, the header hash and the merkleblock; else look up `anchor.rvnTxId` on any Ravencoin explorer", + "8. if `seal.profileHash` is present: `profile.document` must be present, sha256(canonical(document)) must equal it, and `profile.signature` must verify over the hash with the registry keys; absent profileHash = sealed before profiles", + "7. if `basis`/`decision` are present: `basis.asked.recordHash` is another record on the same chain (fetch its bundle and run steps 1–4); `decision.attestationHash` equals `record.attestationHash`; `decision.amendment.command`, when present, is what ran" + ], + "profile": { + "profileHash": "9bbe0635c0a05cc8107d40ad5bb2d8b227c8125d395f41620bcd371123319701", + "document": { + "v": 1, + "name": "org", + "registry": "in.xchk.io", + "dials": { + "identity": [ + "email", + "domain" + ], + "registration": "person", + "anchoring": [ + "rvn", + "ots" + ], + "signing": "ed25519+ml-dsa-65", + "actSummary": { + "kept": "registry", + "maxChars": 400 + }, + "inbound": "on", + "operatorAccess": "recorded", + "actRecords": "kept", + "publicRecord": "plate", + "principalDomains": [ + "maclawran.ca" + ] + } + }, + "signature": { + "alg": "ed25519+ml-dsa-65", + "keyId": "5ecb3da505414c4f", + "signature": "3wM2ISHYyVQSahc6iEv70t47+skkAxg7sS7Nu6p82ZVT/WgN6iUdc+A+padJl1DJRcTJQErs3ppXsM8ZTQlEAQ==", + "signedAt": "2026-10-17T15:48:48.412Z", + "signatures": [ + { + "alg": "ed25519", + "keyId": "5ecb3da505414c4f", + "signature": "3wM2ISHYyVQSahc6iEv70t47+skkAxg7sS7Nu6p82ZVT/WgN6iUdc+A+padJl1DJRcTJQErs3ppXsM8ZTQlEAQ==" + }, + { + "alg": "ml-dsa-65", + "keyId": "8bb85bc1f41c568c", + "signature": "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" + } + ] + }, + "rule": "sha256(canonical(document)) = seal.profileHash; verify signature over the UTF-8 bytes of profileHash with the same registrySignature.keys as the seal; document.dials are the rules this node ran under when it sealed the window" + }, + "verifier": { + "html": "https://in.xchk.io/verify-receipt.html", + "python": "https://in.xchk.io/verify/verify_receipt.py", + "license": "MIT" + } +} diff --git a/integrations/xchk-registry/examples/approval-outcome/01-approval-confirmed.json b/integrations/xchk-registry/examples/approval-outcome/01-approval-confirmed.json new file mode 100644 index 00000000..ca850981 --- /dev/null +++ b/integrations/xchk-registry/examples/approval-outcome/01-approval-confirmed.json @@ -0,0 +1,47 @@ +{ + "eat_profile": "tag:agentrust-io.com,2026:trace-v0.2", + "iat": 1792252491, + "subject": "did:web:in.xchk.io:plate:ENG-WNP3", + "model": { + "provider": "anthropic", + "model_id": "claude-fable-5-1" + }, + "runtime": { + "platform": "software-only", + "measurement": "sha256:c60a771a8f6e4fda60fbb2b745397c800c38da090f153f72e302147a1851746a" + }, + "policy": { + "bundle_hash": "sha256:8e1e29b1e2b1470b57fba453991d3c9ef0d0ae19ba59927c014525177ee741ae", + "enforcement_mode": "enforce" + }, + "data_class": "internal", + "tool_transcript": { + "hash": "sha256:54ea01281f1acf13dec96c509cb243c5ee87b826524044ac8c2700a63cd9f2bb", + "call_count": 101 + }, + "references": [ + { + "rel": "approval-outcome", + "id": "aa2bfd5b1d9b6307ed22eb0daa4213383beecb57d7d31ec011060ac98f7fe0b5", + "resolver": "https://in.xchk.io", + "digest": "sha256:aa2bfd5b1d9b6307ed22eb0daa4213383beecb57d7d31ec011060ac98f7fe0b5" + } + ], + "build_provenance": { + "slsa_level": 0, + "digest": "sha256:c60a771a8f6e4fda60fbb2b745397c800c38da090f153f72e302147a1851746a" + }, + "appraisal": { + "status": "none", + "verifier": "https://in.xchk.io" + }, + "cnf": { + "jwk": { + "kty": "OKP", + "crv": "Ed25519", + "x": "mn02E1XyTkaVN6DEOemU5OADMUAUjPHw67oR5KKIM3k", + "kid": "5ecb3da505414c4f" + } + }, + "signature": "Vjgt2d7DVF_KmYdb3UXuOaL4YxRO1k46Uj91QkI5vc0EC5NraQ7U7S58DuD35d8GMy70wW-I08OtkRiCKTfPAQ" +} diff --git a/integrations/xchk-registry/examples/approval-outcome/02-bundle-altered-after-issue.bundle.json b/integrations/xchk-registry/examples/approval-outcome/02-bundle-altered-after-issue.bundle.json new file mode 100644 index 00000000..9d600adb --- /dev/null +++ b/integrations/xchk-registry/examples/approval-outcome/02-bundle-altered-after-issue.bundle.json @@ -0,0 +1,368 @@ +{ + "format": "xchk-receipt-bundle/2", + "issuer": { + "name": "xChk registry", + "base": "https://in.xchk.io", + "servedAt": "2026-10-17T15:54:51.987Z", + "headline": "ENG-WNP3: APPROVED terminal in global at 2026-10-17T15:46:00.571Z — approved by sean@maclawran.ca." + }, + "recordHash": "aa2bfd5b1d9b6307ed22eb0daa4213383beecb57d7d31ec011060ac98f7fe0b5", + "record": { + "v": 1, + "agentId": "6acbf860a627414b66045478", + "plate": "ENG-WNP3", + "seq": 9819, + "ts": "2026-10-17T15:46:00.571Z", + "harness": "claude", + "runSeq": 3057, + "runRef": "ENG WNP3.3057", + "area": "global", + "tool": "terminal", + "summary": "P=\".ab1-probe-approve1-$(date +%s)\"; rm -f \"$P\" && echo \"probe 1 ran (nothing existed to remove)\" (edited after issue)", + "paramsHash": "a791bccfa14f0666b7082aab7586455f1898da48651cbbbb643e0df3402655c6", + "amount": null, + "disposition": "approved", + "code": null, + "reason": null, + "deskCondition": "normal", + "continuityClass": "standard", + "authRef": "c2486b7f4874e5d08aba0725", + "prevHash": "25607c8e2e529dddce618b49b1c11da6b302a6687c6d44b335f304e904dc796f", + "rvnBlock": "000000000001303bd2857ce3c400c92e8bcf8b97c14eda4f85650e03f91ef3e3@4585364", + "approverEmail": "sean@maclawran.ca", + "authMethod": "webauthn", + "attestationId": "6ad398295f7026f62ae7b863", + "attestationHash": "d7896ca4608bcdd8581ce6c0bb5917e541d40d635334e1a8746d7fc1bc230d5e", + "photoUrl": "https://xchk-main.s3.us-east-005.backblazeb2.com/xchk/xchk/baseline/att_6ad398295f7026f62ae7b863/0.jpg", + "model": "claude-fable-5-1" + }, + "canonicalization": { + "profile": "JSON with object keys sorted (code-unit order), no whitespace, scalars as JSON.stringify would emit them, undefined omitted, integers only; hash = sha256 over the UTF-8 bytes", + "hashedConditionalKeys": [ + "rvnBlock", + "approverEmail", + "authMethod", + "requiredAuthMethod", + "attestationId", + "attestationHash", + "photoUrl", + "labelsHash", + "delegationHash", + "model", + "tokensIn", + "tokensOut", + "tokensCacheRead", + "contextPct", + "actor", + "chargeCode", + "workspace", + "policyHash", + "outcomeOf", + "resultHash", + "endedAt", + "artifactHash" + ], + "note": "conditional keys are present only when the record carried them; absent keys are absent from the bytes, not null" + }, + "merkle": { + "proof": [ + { + "side": "L", + "hash": "25607c8e2e529dddce618b49b1c11da6b302a6687c6d44b335f304e904dc796f" + }, + { + "side": "R", + "hash": "61cbbb71667c7ad8ed2fb67feadf3454a801ced41e3d303ba7b8297524c0e86b" + }, + { + "side": "R", + "hash": "c7f7fb52d081b787566876416919dca904cef18613bb63efa3e28b0ab8eeced5" + }, + { + "side": "R", + "hash": "30e986cfeef36f573d77f3f49948c8bc3248ee8e068d439c149ee72dbe2dad8b" + }, + { + "side": "R", + "hash": "b1f52c8bef88f4187114b4cfab6922468a0e2f3775dc9b6fa7d1479458d02019" + }, + { + "side": "R", + "hash": "b8de3bc958dcdcd07dfc74b47a39ede41e6c649d39f09505b88802fbfb5e7739" + } + ], + "leafCount": 37, + "rule": "node = sha256(left_hex + right_hex) over the hex strings; an odd node is promoted unhashed; the leaf is the record hash" + }, + "seal": { + "v": 1, + "agentId": "6acbf860a627414b66045478", + "plate": "ENG-WNP3", + "sealSeq": 1496, + "windowStart": "2026-10-17T15:44:25.565Z", + "windowEnd": "2026-10-17T15:53:48.404Z", + "count": 37, + "issuedCount": 37, + "seqStart": 9818, + "seqEnd": 9854, + "merkleRoot": "2662a87b9401541c4917428bda73596a608ad5ea556acdc110639e2e618092e9", + "deskCondition": "normal", + "prevSealHash": "82904359e52743e49d8c822814094b1519e02214578adef89487469b555c68c5", + "rvnBlock": "00000000000081b33c166cf1961e598cb91d40a6fef817b0d2d8aaf3b6b62753@4585373", + "profileHash": "9bbe0635c0a05cc8107d40ad5bb2d8b227c8125d395f41620bcd371123319701", + "sealHash": "a00007915e398e7a5f6fdd0863a7ebc0f3eac99da656b85a4fad0d06a8c15710", + "rule": "sealHash = sha256(canonical({v, agentId, plate, sealSeq, windowStart, windowEnd, count, issuedCount, seqStart, seqEnd, merkleRoot, deskCondition, prevSealHash[, rvnBlock][, profileHash]}))" + }, + "registrySignature": { + "alg": "ed25519+ml-dsa-65", + "keyId": "5ecb3da505414c4f", + "signature": "v+SHukcW2TmkZbafId5igQnOU75fbb51UNUJFRwp5DdQd1ebk+9Z7wZ9BXfBpmZUWLBgm3ZuNlP+IbVZrKH3Bg==", + "signedAt": "2026-10-17T15:53:48.458Z", + "signatures": [ + { + "alg": "ed25519", + "keyId": "5ecb3da505414c4f", + "signature": "v+SHukcW2TmkZbafId5igQnOU75fbb51UNUJFRwp5DdQd1ebk+9Z7wZ9BXfBpmZUWLBgm3ZuNlP+IbVZrKH3Bg==" + }, + { + "alg": "ml-dsa-65", + "keyId": "8bb85bc1f41c568c", + "signature": "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" + } + ], + "signedOver": "the UTF-8 bytes of seal.sealHash", + "publicKeyRaw": "mn02E1XyTkaVN6DEOemU5OADMUAUjPHw67oR5KKIM3k=", + "publicKeyPem": "-----BEGIN PUBLIC KEY-----\nMCowBQYDK2VwAyEAmn02E1XyTkaVN6DEOemU5OADMUAUjPHw67oR5KKIM3k=\n-----END PUBLIC KEY-----\n", + "wellKnown": "https://in.xchk.io/.well-known/xchk-keys.json", + "keys": [ + { + "alg": "ed25519", + "keyId": "5ecb3da505414c4f", + "publicKeyRaw": "mn02E1XyTkaVN6DEOemU5OADMUAUjPHw67oR5KKIM3k=" + }, + { + "alg": "ml-dsa-65", + "keyId": "8bb85bc1f41c568c", + "publicKeyRaw": "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" + } + ], + "retired": [], + "publicKeyRawPq": "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", + "keyIdPq": "8bb85bc1f41c568c", + "root": { + "alg": "slh-dsa-sha2-128s", + "standard": "FIPS 205", + "keyId": "acc7ad1aeb3ef177", + "publicKeyRaw": "4aIhDuj3TZPwqb9HT8TzVJnkvle4jVUMhWkn/BfmypM=", + "statement": { + "v": 1, + "registry": "https://in.xchk.io", + "keys": [ + { + "alg": "ed25519", + "keyId": "5ecb3da505414c4f", + "publicKeyRaw": "mn02E1XyTkaVN6DEOemU5OADMUAUjPHw67oR5KKIM3k=" + }, + { + "alg": "ml-dsa-65", + "keyId": "8bb85bc1f41c568c", + "publicKeyRaw": "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" + } + ], + "retired": [], + "oidc": [ + { + "kid": "XWUv0uGESGdIG1MjOzbVjcwxB0CYtK0oZ9SZxNkH7h8", + "kty": "RSA", + "alg": "RS256", + "n": "zQwdJyTuyqQvB5zIXp9ULjX22k-R95Ls5j3IVUwLcI87I2VPUjsvy9oDGl5cq8Jl7Rt21d966AakANr8J1vT7gMpcmPOcEGVDdgdCprRs8cWNDo5uJ4ejt1LW65zRqW8xsxqHPm1aOxvjeUQfNgZFLn3VlSX01zgjggBLSwL18stLbyIzA2zcj4lpV-IrnBO3S6VUusoaO__kXjHv1-aH64wpVcsNLrBX6MWsnHM-KptbhKrk_qqXMJ7dokBxiIAH32VjZ73kTbVcSXoU2FshM_eQaonhYcRoD8PTXN3rxMaisj2pka9XZ1Apqy-EHf1dCoUphYxd_--FcT5PDQZaQ", + "e": "AQAB" + } + ], + "issuedAt": "2026-10-17T15:48:57.541Z" + }, + "signature": "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", + "rule": "SLH-DSA-SHA2-128s verify(publicKeyRaw, canonical(statement) bytes, signature); statement.keys are the keys this registry signs with" + }, + "rule": "HYBRID: for each entry in signatures, verify(keys[alg,keyId].publicKeyRaw, sealHash bytes, signature) — Ed25519 for alg ed25519, ML-DSA-65 (FIPS 204) for alg ml-dsa-65; ALL must verify. keyId = sha256(SPKI or raw key)[:16]. root, when present, is the SLH-DSA-SHA2-128s statement of these keys." + }, + "approver": { + "email": "sean@maclawran.ca", + "authLevel": "didit", + "authMethod": "webauthn", + "attestationId": "6ad398295f7026f62ae7b863", + "credentialId": "Yqa88hkURHnPqSTiV3o1jA", + "publicKey": { + "format": "ec-p256-uncompressed", + "alg": "ES256", + "raw": "BIWcVSzcT4ocdVb/bHtVrZNK/4RKRn1xhg6SE8TSy3QGpnJUufsDz2z+G1PqK3yP/7q5IPI9PEfjC77W/OxqD5k=" + }, + "assertion": { + "clientDataJSON": "eyJ0eXBlIjoid2ViYXV0aG4uZ2V0IiwiY2hhbGxlbmdlIjoiNUVMY0t2aUhybWxuUElaME9Ca0hMZE9tM05aalVKdEN5U3d5QUItcElNYyIsIm9yaWdpbiI6Imh0dHBzOi8vaW4ueGNoay5pbyIsImNyb3NzT3JpZ2luIjpmYWxzZX0", + "authenticatorData": "dcRETaEWF68z8NRCzR6PN99N5Mn8aYw-RadnYwZSFr0dAAAAAA", + "signature": "MEUCIQDCuR26urn4n7AYJ2_Ohd9_KJ7hRp6pEm2qG1mqjnjMbAIgdUuoz3nO2St6MasEmX3TvKYiv8MoFn1UA9_li9nWCB8", + "encoding": "base64url" + }, + "challenge": { + "rule": "ask-v1", + "fields": { + "v": 1, + "attestationId": "6ad398295f7026f62ae7b863", + "prompt": "ENG-WNP3.3057 (via Claude Code) wants to P=\".ab1-probe-approve1-$(date +%s)\"; rm -f \"$P\" && echo \"probe 1 ran (nothing existed to remove)\"", + "actionParamsHash": "5eee3b37a63eb957436a2bd51633d8a3c9a54f96c66e71f45fbd2d458373ca68" + }, + "expected": "5ELcKviHrmlnPIZ0OBkHLdOm3NZjUJtCySwyAB-pIMc", + "note": "the challenge the approver's device signed = base64url(sha256(canonical(fields))); fields are the ask as issued, before any answer; recompute, do not trust `expected`" + }, + "binding": { + "fields": { + "v": 1, + "recordHash": "aa2bfd5b1d9b6307ed22eb0daa4213383beecb57d7d31ec011060ac98f7fe0b5", + "attestationId": "6ad398295f7026f62ae7b863", + "credentialId": "Yqa88hkURHnPqSTiV3o1jA", + "publicKey": "BIWcVSzcT4ocdVb/bHtVrZNK/4RKRn1xhg6SE8TSy3QGpnJUufsDz2z+G1PqK3yP/7q5IPI9PEfjC77W/OxqD5k=", + "approverEmail": "sean@maclawran.ca", + "authLevel": "didit", + "authMethod": "webauthn", + "verifiedAt": "2026-10-17T15:46:00.404Z" + }, + "signature": "LpDId3mnpJVZn4ntyVIwrgy/sT1vdKmomgr8eoShKHRJhvh7xr7qvVD3ZhKaaYxa5rcL/E0JQX8ICh+Y/1vSDA==", + "keyId": "5ecb3da505414c4f", + "signedAt": "2026-10-17T15:54:51.971Z", + "alg": "ed25519+ml-dsa-65", + "signatures": [ + { + "alg": "ed25519", + "keyId": "5ecb3da505414c4f", + "signature": "LpDId3mnpJVZn4ntyVIwrgy/sT1vdKmomgr8eoShKHRJhvh7xr7qvVD3ZhKaaYxa5rcL/E0JQX8ICh+Y/1vSDA==" + }, + { + "alg": "ml-dsa-65", + "keyId": "8bb85bc1f41c568c", + "signature": "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" + } + ], + "rule": "registry signature(s) over canonical(fields): each of `signatures` with the registrySignature.keys entry of the same alg/keyId (hybrid: all must verify); `signature` is the Ed25519 half" + }, + "rules": [ + "assertion: WebAuthn signature = ECDSA-P256/SHA-256 over authenticatorData || sha256(clientDataJSON), verified with publicKey.raw (uncompressed point); clientDataJSON.type must be \"webauthn.get\"; authenticatorData flags must include UV (user verified)", + "binding: verify each of binding.signatures (or binding.signature with alg ed25519) over canonical(binding.fields) with the matching registrySignature.keys entry — Ed25519 and, when present, ML-DSA-65; all must verify; binding.fields.recordHash must equal recordHash, binding.fields.credentialId must equal the assertion credential, and binding.fields.publicKey must equal approver.publicKey.raw (17 Oct 2026: an assertion re-signed by another key, with that key offered, passes every other check)", + "challenge: when approver.challenge is present (rule ask-v1, ceremonies from 18 Oct 2026), clientDataJSON.challenge must equal base64url(sha256(canonical(challenge.fields))) with fields.attestationId = approver.attestationId, fields.prompt = decision.prompt and fields.actionParamsHash = decision.actionParamsHash: the device signed over the ask, so the assertion itself names the act it answered. Absent, the challenge was a nonce and only the binding pairs the assertion with the record (an assertion by the same credential over another ask passes every other check)" + ] + }, + "basis": { + "asked": { + "seq": 9818, + "ts": "2026-10-17T15:45:45.315Z", + "area": "global", + "tool": "terminal", + "summary": "P=\".ab1-probe-approve1-$(date +%s)\"; rm -f \"$P\" && echo \"probe 1 ran (nothing existed to remove)\"", + "paramsHash": "a791bccfa14f0666b7082aab7586455f1898da48651cbbbb643e0df3402655c6", + "code": "hook_escalation", + "reason": "destructive filesystem command outside scratch roots", + "recordHash": "25607c8e2e529dddce618b49b1c11da6b302a6687c6d44b335f304e904dc796f", + "model": "claude-fable-5-1" + }, + "grant": { + "area": "global", + "disposition": "allow", + "policyId": null, + "maxAmount": null, + "resources": [] + }, + "authorizeDisposition": "attest", + "area": "global", + "objective": null, + "rule": "asked = the attest record this ceremony answers (same plate, same action summary, raised just before the ceremony; cite it by recordHash); grant = the plate's grant rows as they stood when the ceremony was raised; asked.reason is the registry's stated reason for asking" + }, + "decision": { + "prompt": "ENG-WNP3.3057 (via Claude Code) wants to P=\".ab1-probe-approve1-$(date +%s)\"; rm -f \"$P\" && echo \"probe 1 ran (nothing existed to remove)\"", + "response": "approved", + "status": "completed", + "createdAt": "2026-10-17T15:45:45.553Z", + "respondedAt": "2026-10-17T15:46:00.404Z", + "by": "sean@maclawran.ca", + "authMethod": "webauthn", + "requiredAuthMethod": null, + "amendment": null, + "actionParamsHash": "5eee3b37a63eb957436a2bd51633d8a3c9a54f96c66e71f45fbd2d458373ca68", + "attestationHash": "d7896ca4608bcdd8581ce6c0bb5917e541d40d635334e1a8746d7fc1bc230d5e", + "attestationHashRule": "sha256 over the registry's canonical attestation JSON (utils/attestationHashUtils.computeAttestationHash: id, prompt, response, status, respondedAt, approver, method, amendment, delivery, chain …); recomputable on the registry, cited here so the record and this decision are bound" + }, + "legalHolds": null, + "anchor": { + "rvnTxId": null, + "rvnAnchoredAt": null, + "rvnBlock": "00000000000081b33c166cf1961e598cb91d40a6fef817b0d2d8aaf3b6b62753@4585373", + "explorer": null, + "otsProof": "8AgHtW3WwcdWHAjwIDmHgtDWxTNE7J5/xgGaHDFnrQrc3inlHM3qhjw4tw0GCPAQXdqsoXnzk3MwpP23KriFggjxIPLwuvDSO69qmiS9474S+Avisk6Nj3GHF2cAlCMhKZEgCPAgcg99+b7AHf2ZK3gpBTOQs3DbDNA7V9MlZXNzGCHcjq4I8CBgv3qhup4MMtQ5Z6CeKEgdkDbyf3ckONgeLlOyncp01gjxBGrTmg3wCL37YWeTW8icAIPf4w0u+QyOLi1odHRwczovL2FsaWNlLmJ0Yy5jYWxlbmRhci5vcGVudGltZXN0YW1wcy5vcmc=", + "otsCalendar": "https://a.pool.opentimestamps.org", + "otsBlockHeight": null, + "rule": "the anchor transaction carries sealHash in OP_RETURN; its raw bytes are captured once the transaction confirms (a few minutes) — download the bundle again for the offline anchor check, or use the explorer link" + }, + "howToVerify": [ + "1. canonicalize `record` per `canonicalization.profile`, sha256 it, compare to `recordHash`", + "2. walk `merkle.proof` from `recordHash` (L: sha256(step+cur), R: sha256(cur+step)); the result must equal `seal.merkleRoot`", + "3. canonicalize the seal fields per `seal.rule`, sha256 it, compare to `seal.sealHash`", + "4. verify every entry of `registrySignature.signatures` over the seal hash with the key of the same alg/keyId in `registrySignature.keys` (Ed25519 + ML-DSA-65 when hybrid); older bundles: Ed25519-verify `signature` with `publicKeyRaw`", + "5. if `approver` is present: verify the WebAuthn assertion with `approver.publicKey.raw`, then Ed25519-verify `approver.binding.signature` over canonical(`approver.binding.fields`) with the registry key, and require `approver.binding.fields.publicKey` to equal `approver.publicKey.raw`: the binding, not the bundle, names the key the assertion may be checked with; when `approver.challenge` is present, recompute base64url(sha256(canonical(`challenge.fields`))) and require it to equal `clientDataJSON.challenge`, with the fields equal to `approver.attestationId`, `decision.prompt` and `decision.actionParamsHash`", + "6. if `anchor.proof` is present: check the OP_RETURN, the txid, the header hash and the merkleblock; else look up `anchor.rvnTxId` on any Ravencoin explorer", + "8. if `seal.profileHash` is present: `profile.document` must be present, sha256(canonical(document)) must equal it, and `profile.signature` must verify over the hash with the registry keys; absent profileHash = sealed before profiles", + "7. if `basis`/`decision` are present: `basis.asked.recordHash` is another record on the same chain (fetch its bundle and run steps 1–4); `decision.attestationHash` equals `record.attestationHash`; `decision.amendment.command`, when present, is what ran" + ], + "profile": { + "profileHash": "9bbe0635c0a05cc8107d40ad5bb2d8b227c8125d395f41620bcd371123319701", + "document": { + "v": 1, + "name": "org", + "registry": "in.xchk.io", + "dials": { + "identity": [ + "email", + "domain" + ], + "registration": "person", + "anchoring": [ + "rvn", + "ots" + ], + "signing": "ed25519+ml-dsa-65", + "actSummary": { + "kept": "registry", + "maxChars": 400 + }, + "inbound": "on", + "operatorAccess": "recorded", + "actRecords": "kept", + "publicRecord": "plate", + "principalDomains": [ + "maclawran.ca" + ] + } + }, + "signature": { + "alg": "ed25519+ml-dsa-65", + "keyId": "5ecb3da505414c4f", + "signature": "3wM2ISHYyVQSahc6iEv70t47+skkAxg7sS7Nu6p82ZVT/WgN6iUdc+A+padJl1DJRcTJQErs3ppXsM8ZTQlEAQ==", + "signedAt": "2026-10-17T15:48:48.412Z", + "signatures": [ + { + "alg": "ed25519", + "keyId": "5ecb3da505414c4f", + "signature": "3wM2ISHYyVQSahc6iEv70t47+skkAxg7sS7Nu6p82ZVT/WgN6iUdc+A+padJl1DJRcTJQErs3ppXsM8ZTQlEAQ==" + }, + { + "alg": "ml-dsa-65", + "keyId": "8bb85bc1f41c568c", + "signature": "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" + } + ] + }, + "rule": "sha256(canonical(document)) = seal.profileHash; verify signature over the UTF-8 bytes of profileHash with the same registrySignature.keys as the seal; document.dials are the rules this node ran under when it sealed the window" + }, + "verifier": { + "html": "https://in.xchk.io/verify-receipt.html", + "python": "https://in.xchk.io/verify/verify_receipt.py", + "license": "MIT" + } +} diff --git a/integrations/xchk-registry/examples/approval-outcome/02-bundle-altered-after-issue.json b/integrations/xchk-registry/examples/approval-outcome/02-bundle-altered-after-issue.json new file mode 100644 index 00000000..ca850981 --- /dev/null +++ b/integrations/xchk-registry/examples/approval-outcome/02-bundle-altered-after-issue.json @@ -0,0 +1,47 @@ +{ + "eat_profile": "tag:agentrust-io.com,2026:trace-v0.2", + "iat": 1792252491, + "subject": "did:web:in.xchk.io:plate:ENG-WNP3", + "model": { + "provider": "anthropic", + "model_id": "claude-fable-5-1" + }, + "runtime": { + "platform": "software-only", + "measurement": "sha256:c60a771a8f6e4fda60fbb2b745397c800c38da090f153f72e302147a1851746a" + }, + "policy": { + "bundle_hash": "sha256:8e1e29b1e2b1470b57fba453991d3c9ef0d0ae19ba59927c014525177ee741ae", + "enforcement_mode": "enforce" + }, + "data_class": "internal", + "tool_transcript": { + "hash": "sha256:54ea01281f1acf13dec96c509cb243c5ee87b826524044ac8c2700a63cd9f2bb", + "call_count": 101 + }, + "references": [ + { + "rel": "approval-outcome", + "id": "aa2bfd5b1d9b6307ed22eb0daa4213383beecb57d7d31ec011060ac98f7fe0b5", + "resolver": "https://in.xchk.io", + "digest": "sha256:aa2bfd5b1d9b6307ed22eb0daa4213383beecb57d7d31ec011060ac98f7fe0b5" + } + ], + "build_provenance": { + "slsa_level": 0, + "digest": "sha256:c60a771a8f6e4fda60fbb2b745397c800c38da090f153f72e302147a1851746a" + }, + "appraisal": { + "status": "none", + "verifier": "https://in.xchk.io" + }, + "cnf": { + "jwk": { + "kty": "OKP", + "crv": "Ed25519", + "x": "mn02E1XyTkaVN6DEOemU5OADMUAUjPHw67oR5KKIM3k", + "kid": "5ecb3da505414c4f" + } + }, + "signature": "Vjgt2d7DVF_KmYdb3UXuOaL4YxRO1k46Uj91QkI5vc0EC5NraQ7U7S58DuD35d8GMy70wW-I08OtkRiCKTfPAQ" +} diff --git a/integrations/xchk-registry/examples/approval-outcome/03-decision-is-a-denial.bundle.json b/integrations/xchk-registry/examples/approval-outcome/03-decision-is-a-denial.bundle.json new file mode 100644 index 00000000..64ef12ef --- /dev/null +++ b/integrations/xchk-registry/examples/approval-outcome/03-decision-is-a-denial.bundle.json @@ -0,0 +1,368 @@ +{ + "format": "xchk-receipt-bundle/2", + "issuer": { + "name": "xChk registry", + "base": "https://in.xchk.io", + "servedAt": "2026-10-17T15:54:52.124Z", + "headline": "ENG-WNP3: DENIED terminal in global at 2026-10-17T15:47:01.118Z — denied by sean@maclawran.ca." + }, + "recordHash": "24e7d14e03dbf72472d55d8a7266c1a0f98fe3f6e8600b1601fa17159ce43778", + "record": { + "v": 1, + "agentId": "6acbf860a627414b66045478", + "plate": "ENG-WNP3", + "seq": 9829, + "ts": "2026-10-17T15:47:01.118Z", + "harness": "claude", + "runSeq": 3057, + "runRef": "ENG WNP3.3057", + "area": "global", + "tool": "terminal", + "summary": "P=\".ab1-probe-DENY-$(date +%s)\"; rm -f \"$P\" && echo \"probe 3 ran (should not have)\"", + "paramsHash": "44a0989b444605481160f40a49763f27d6aa590153f85c97fa1833bdb0bf89d2", + "amount": null, + "disposition": "denied", + "code": null, + "reason": null, + "deskCondition": "normal", + "continuityClass": "standard", + "authRef": "ff5889c3dd4b72ea575f5d63", + "prevHash": "7fd55cc08bc34757f0d99f0a8912a0d7c39201fd318f46c741f4c9b0e2006fd7", + "rvnBlock": "00000000000429cd3e982adaae95411ba7139c5d7e2631701f4738af6a4e7f9d@4585365", + "approverEmail": "sean@maclawran.ca", + "authMethod": "webauthn", + "attestationId": "6ad398695f7026f62ae7bbd0", + "attestationHash": "746ec01a00227689788df3ae071adeaee5a74c732ae209440134ee0f7105713c", + "photoUrl": "https://xchk-main.s3.us-east-005.backblazeb2.com/xchk/xchk/baseline/att_6ad398695f7026f62ae7bbd0/0.jpg", + "model": "claude-fable-5-1" + }, + "canonicalization": { + "profile": "JSON with object keys sorted (code-unit order), no whitespace, scalars as JSON.stringify would emit them, undefined omitted, integers only; hash = sha256 over the UTF-8 bytes", + "hashedConditionalKeys": [ + "rvnBlock", + "approverEmail", + "authMethod", + "requiredAuthMethod", + "attestationId", + "attestationHash", + "photoUrl", + "labelsHash", + "delegationHash", + "model", + "tokensIn", + "tokensOut", + "tokensCacheRead", + "contextPct", + "actor", + "chargeCode", + "workspace", + "policyHash", + "outcomeOf", + "resultHash", + "endedAt", + "artifactHash" + ], + "note": "conditional keys are present only when the record carried them; absent keys are absent from the bytes, not null" + }, + "merkle": { + "proof": [ + { + "side": "L", + "hash": "7fd55cc08bc34757f0d99f0a8912a0d7c39201fd318f46c741f4c9b0e2006fd7" + }, + { + "side": "L", + "hash": "c85565761a40aada18d67620ed535e2522e2c61d08624d1eb9db9c646b8fd010" + }, + { + "side": "R", + "hash": "b1042b9f55b7a89a97c43321a7b71a3f156891b27292c200a01e7359d45f00c3" + }, + { + "side": "L", + "hash": "212253386d1769fdee55ca4d09c77642da7fcea34d7dccccad308e7175a26f32" + }, + { + "side": "R", + "hash": "b1f52c8bef88f4187114b4cfab6922468a0e2f3775dc9b6fa7d1479458d02019" + }, + { + "side": "R", + "hash": "b8de3bc958dcdcd07dfc74b47a39ede41e6c649d39f09505b88802fbfb5e7739" + } + ], + "leafCount": 37, + "rule": "node = sha256(left_hex + right_hex) over the hex strings; an odd node is promoted unhashed; the leaf is the record hash" + }, + "seal": { + "v": 1, + "agentId": "6acbf860a627414b66045478", + "plate": "ENG-WNP3", + "sealSeq": 1496, + "windowStart": "2026-10-17T15:44:25.565Z", + "windowEnd": "2026-10-17T15:53:48.404Z", + "count": 37, + "issuedCount": 37, + "seqStart": 9818, + "seqEnd": 9854, + "merkleRoot": "2662a87b9401541c4917428bda73596a608ad5ea556acdc110639e2e618092e9", + "deskCondition": "normal", + "prevSealHash": "82904359e52743e49d8c822814094b1519e02214578adef89487469b555c68c5", + "rvnBlock": "00000000000081b33c166cf1961e598cb91d40a6fef817b0d2d8aaf3b6b62753@4585373", + "profileHash": "9bbe0635c0a05cc8107d40ad5bb2d8b227c8125d395f41620bcd371123319701", + "sealHash": "a00007915e398e7a5f6fdd0863a7ebc0f3eac99da656b85a4fad0d06a8c15710", + "rule": "sealHash = sha256(canonical({v, agentId, plate, sealSeq, windowStart, windowEnd, count, issuedCount, seqStart, seqEnd, merkleRoot, deskCondition, prevSealHash[, rvnBlock][, profileHash]}))" + }, + "registrySignature": { + "alg": "ed25519+ml-dsa-65", + "keyId": "5ecb3da505414c4f", + "signature": "v+SHukcW2TmkZbafId5igQnOU75fbb51UNUJFRwp5DdQd1ebk+9Z7wZ9BXfBpmZUWLBgm3ZuNlP+IbVZrKH3Bg==", + "signedAt": "2026-10-17T15:53:48.458Z", + "signatures": [ + { + "alg": "ed25519", + "keyId": "5ecb3da505414c4f", + "signature": "v+SHukcW2TmkZbafId5igQnOU75fbb51UNUJFRwp5DdQd1ebk+9Z7wZ9BXfBpmZUWLBgm3ZuNlP+IbVZrKH3Bg==" + }, + { + "alg": "ml-dsa-65", + "keyId": "8bb85bc1f41c568c", + "signature": "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" + } + ], + "signedOver": "the UTF-8 bytes of seal.sealHash", + "publicKeyRaw": "mn02E1XyTkaVN6DEOemU5OADMUAUjPHw67oR5KKIM3k=", + "publicKeyPem": "-----BEGIN PUBLIC KEY-----\nMCowBQYDK2VwAyEAmn02E1XyTkaVN6DEOemU5OADMUAUjPHw67oR5KKIM3k=\n-----END PUBLIC KEY-----\n", + "wellKnown": "https://in.xchk.io/.well-known/xchk-keys.json", + "keys": [ + { + "alg": "ed25519", + "keyId": "5ecb3da505414c4f", + "publicKeyRaw": "mn02E1XyTkaVN6DEOemU5OADMUAUjPHw67oR5KKIM3k=" + }, + { + "alg": "ml-dsa-65", + "keyId": "8bb85bc1f41c568c", + "publicKeyRaw": "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" + } + ], + "retired": [], + "publicKeyRawPq": "e7eet5v+xU8RgatEwvNj1cMMdHutsiouMGJ1Q32cMarb3CsMTIAY3JSVXWhmPqk+5q7aAwyI0nvSyGpPuK/C7uq5dv1ARQ/qaHRzwRnVN75jHTdyiL7qwHXWhYkqFL9rpHuo3hViiWhk20EWprNbHKLE8k9BKP+FBrqaFlvJ7NLIVbg/GmHuD09NGpT1H9MGTRjwlrw1FXZvMS9ZLhUdY3zjGec1KsPRiteJuosdgiWeYkWxPkzsmVgyRQDVj2Wi7zZjqOrYWuhi2b3DVb9hZ7zeuzxX7CY7Lm1Qmy//Ix4v0+DaTbcjNB+s+U2ChXUbu2Z1mqqgklZle5YY35MXbZ0UyRvVIN9Rd7AAYavNrPNS9idb25oqifkQWn5d1Q9+ztlLecAf1dD8oHhV6C03zOj+smmGpWkys11DqODLXX+0/Kp4ESFvN4qMzhlmRO6I2ECyIb/n+0AvMxK97afyP0m/PdaAE94Rn4+0oAN+xQwKv8CXnYI9xTAOmOtkGcMUK6dUt+Um+RHyz7gF4MZ381SfBDk0q1/s8ZLjZfq+LJdKUkgX1D+frAHvw97zmwA4gTbTE4+GHxlTlr3+PAbDgfeSPCGWljW74miMNW/+S07jpnUW4Amd5yOR1QNThtA8qHmvJd19F03kndxsLGpH1PwdUAsNcrSkvOl2p9X4dv57nOzXxFJtIP/JX72AB+neT0+ORSbtx5GdmaqaLvOpzeYFOAbzGbjqGw9EGJ/eAOR//CZiX0T2/qPQjntadvlJHM2DQYD8CwYNX4EDOZ/sczVtOQ6h205CzLo6jWAs3P6YkaEd0XLNSnj/dyQDYN0sfJn3FJWgEh0DsPfbXynGfb6I2SVdp+ht7dWPEzoEpmC3RUjw3Bi2P7k9gxDkZ62+qjY5Sb23PRuu3cO4BPD7XYj5a2B8C3Hv7kjkruiYUofJKf19H3iYQFUmtBzzdX8fx1/0NO+jchIUGApOhIjLe9/6Go66a5bjTnqNvyXNuJycOWyQTBDaumAqQilY9Yq8vW4k3HupWnzbYTEz18rBorb+0hbCzPGivpOuMgTxE6LdRUVN77FmddyQP2gN0iaIlNzXtJc8sfjT7th8JznIq5jjVhBK2cgVxB7ySGnNUXsbRJ+p+uiOTMf7O6o/T/6eb+79+XCxPunIiwW5JOQvE6GPS63bvuiYchsae2dgcsdaYUXsoe0FEAMqM+G+LsPaoYJildycC27UflXMMpbLUB0N3j1F5RTYGQLsORpzi/oEB9ptYK25hBICYryB4xteIhQcVWu32Ntt47M/2fN0lumWAFfoP593UtKNGcUM7G9zhSJfn6m+0R+sMixGvYw0NesnWp9fKnLAAIUrPvW7mnvYfSlUeVS076hzVR5JOEsZbrkRQg5/9njU0GaB22kYCEo5u0B6WiePz9OTWfTxz7xu6PaRTqOG2B0qLn81J12UTegOYPAZUlAj42i/llqpOfEWrlreIaT8kWLtxoafpaXl7kfX8a0ydzzD8dQ7JuswDMqRRbNnCcNIMyvU71v9LJW+rlAvrAVVQP7vhflJA7mPVNt6+bXRv1aMVfRVFM4kALWzYK2/6qoaDmC7OLHQuNqT44CFbj/6Z2gNcQO72tfLB005GvdbqiT8PJylpZ+TOFH7eqQFmmgIeQbeSVQZnqlq0KMtElArNRK8a4J+Zdh+yKNJ85xcFrcaFKlRPQdpetlvZYdRtFPf7iFMr3ubqYM7aNtvHrbXuaeMmZT9w35RJRtBSxQH43eNpf3zXh/VzkaKTSw7T9Un4FnTNG59O7rVYzxf0RKVI0wzwO9nRHGNa/sDjyCBu/vL7ElJ7FwbQudGLJQL07iBFJESKzfNm8heFO2lME8O05EBmsbLo3VMsTXyhi4M75cSGc5GaEt6FXuPh+ycboROYzNEpzffT2DYS3yZK+KF5hS0/lMm3NEyp4lYpk1cLydljNm/XONhGaSnEEBZLNicFKT4wWKZbRLzU1r87UQm//lWNRDxK3sFaegcjScGCewbXghEjsHRlQlIqnqAIFUTyvHiQVJqk+qnGDGRnGn47hmvZ3/RUvx6gMX/PYul5aDYcBihXh88SzwV88rB1tIRscPte4XroBNoqB2Q97OCpSm1aQ1R52ESz+bWdELdpDZpn/q+wx+vXp2NswIHncmz5VtfA9dHIAgcM7n7tUl/U6BVjmAW7X93Eh/YYxXzAU4/ZCxLYcluDhrg73H+le1BpIZ7j/MrV+fbHsQEtiUZzg/RjrwSaabCXakfKMlxDZ6ODwBE0OkuiNlkztrQCqR6c1/Pvg7fMUP0vxlsIyd47aBCgdC/OFUmAVBC1nq7HOxJ5wlkKeIQTL/q8QWwyhrDTsK/7CHjJ9awUhO8uCbrx7X8Yc77q6QJg7KEHm6gTQSEhq8cvnmtn40iQv8mzTDg7HqFOuPNLFLsjdDF7KByOIYsPGw1A8JJ+ATpcHo0sHjjA8/ye5uayNhtGpaGdsOG7HxhB1e98uSvr1fUCmzs4orc/HJuDbWCaVMjP5TdOTVmcKoylzEY9adZpFibKJV89j5iX46fxS4uURxIaLiYENo/2IS4+StY0sBbFTMRfy/9jWw3oQQ=", + "keyIdPq": "8bb85bc1f41c568c", + "root": { + "alg": "slh-dsa-sha2-128s", + "standard": "FIPS 205", + "keyId": "acc7ad1aeb3ef177", + "publicKeyRaw": "4aIhDuj3TZPwqb9HT8TzVJnkvle4jVUMhWkn/BfmypM=", + "statement": { + "v": 1, + "registry": "https://in.xchk.io", + "keys": [ + { + "alg": "ed25519", + "keyId": "5ecb3da505414c4f", + "publicKeyRaw": "mn02E1XyTkaVN6DEOemU5OADMUAUjPHw67oR5KKIM3k=" + }, + { + "alg": "ml-dsa-65", + "keyId": "8bb85bc1f41c568c", + "publicKeyRaw": "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" + } + ], + "retired": [], + "oidc": [ + { + "kid": "XWUv0uGESGdIG1MjOzbVjcwxB0CYtK0oZ9SZxNkH7h8", + "kty": "RSA", + "alg": "RS256", + "n": "zQwdJyTuyqQvB5zIXp9ULjX22k-R95Ls5j3IVUwLcI87I2VPUjsvy9oDGl5cq8Jl7Rt21d966AakANr8J1vT7gMpcmPOcEGVDdgdCprRs8cWNDo5uJ4ejt1LW65zRqW8xsxqHPm1aOxvjeUQfNgZFLn3VlSX01zgjggBLSwL18stLbyIzA2zcj4lpV-IrnBO3S6VUusoaO__kXjHv1-aH64wpVcsNLrBX6MWsnHM-KptbhKrk_qqXMJ7dokBxiIAH32VjZ73kTbVcSXoU2FshM_eQaonhYcRoD8PTXN3rxMaisj2pka9XZ1Apqy-EHf1dCoUphYxd_--FcT5PDQZaQ", + "e": "AQAB" + } + ], + "issuedAt": "2026-10-17T15:48:57.541Z" + }, + "signature": "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", + "rule": "SLH-DSA-SHA2-128s verify(publicKeyRaw, canonical(statement) bytes, signature); statement.keys are the keys this registry signs with" + }, + "rule": "HYBRID: for each entry in signatures, verify(keys[alg,keyId].publicKeyRaw, sealHash bytes, signature) — Ed25519 for alg ed25519, ML-DSA-65 (FIPS 204) for alg ml-dsa-65; ALL must verify. keyId = sha256(SPKI or raw key)[:16]. root, when present, is the SLH-DSA-SHA2-128s statement of these keys." + }, + "approver": { + "email": "sean@maclawran.ca", + "authLevel": "didit", + "authMethod": "webauthn", + "attestationId": "6ad398695f7026f62ae7bbd0", + "credentialId": "Yqa88hkURHnPqSTiV3o1jA", + "publicKey": { + "format": "ec-p256-uncompressed", + "alg": "ES256", + "raw": "BIWcVSzcT4ocdVb/bHtVrZNK/4RKRn1xhg6SE8TSy3QGpnJUufsDz2z+G1PqK3yP/7q5IPI9PEfjC77W/OxqD5k=" + }, + "assertion": { + "clientDataJSON": "eyJ0eXBlIjoid2ViYXV0aG4uZ2V0IiwiY2hhbGxlbmdlIjoiOGNuUXVBaHhfWDRCVS1ENmVsdW5LOVdxOG5oWVV3dnV2WUNfODJsVkI1USIsIm9yaWdpbiI6Imh0dHBzOi8vaW4ueGNoay5pbyIsImNyb3NzT3JpZ2luIjpmYWxzZX0", + "authenticatorData": "dcRETaEWF68z8NRCzR6PN99N5Mn8aYw-RadnYwZSFr0dAAAAAA", + "signature": "MEUCIQCF-2nVcrrFpD1Y_0uuRsgmDmj8niRa8Tr4Uq8qcuHZewIgMLDsPQxmrKWH0xk7P0k36AyiwzjyrlsERKs9CMFMgGM", + "encoding": "base64url" + }, + "challenge": { + "rule": "ask-v1", + "fields": { + "v": 1, + "attestationId": "6ad398695f7026f62ae7bbd0", + "prompt": "ENG-WNP3.3057 (via Claude Code) wants to P=\".ab1-probe-DENY-$(date +%s)\"; rm -f \"$P\" && echo \"probe 3 ran (should not have)\"", + "actionParamsHash": "fc1fc0b0dde019c96f48005583d363ad84e5aab176b4dfc2e460202e509874e0" + }, + "expected": "8cnQuAhx_X4BU-D6elunK9Wq8nhYUwvuvYC_82lVB5Q", + "note": "the challenge the approver's device signed = base64url(sha256(canonical(fields))); fields are the ask as issued, before any answer; recompute, do not trust `expected`" + }, + "binding": { + "fields": { + "v": 1, + "recordHash": "24e7d14e03dbf72472d55d8a7266c1a0f98fe3f6e8600b1601fa17159ce43778", + "attestationId": "6ad398695f7026f62ae7bbd0", + "credentialId": "Yqa88hkURHnPqSTiV3o1jA", + "publicKey": "BIWcVSzcT4ocdVb/bHtVrZNK/4RKRn1xhg6SE8TSy3QGpnJUufsDz2z+G1PqK3yP/7q5IPI9PEfjC77W/OxqD5k=", + "approverEmail": "sean@maclawran.ca", + "authLevel": "didit", + "authMethod": "webauthn", + "verifiedAt": "2026-10-17T15:47:01.080Z" + }, + "signature": "7tWT9iBArp2kwiaPpIdAS9v851rhhrZaDY6iW7G8F7KaBAdV8riBQBTj724j7LPiieVj5pzs4CobkaZ5bzgjDw==", + "keyId": "5ecb3da505414c4f", + "signedAt": "2026-10-17T15:54:52.112Z", + "alg": "ed25519+ml-dsa-65", + "signatures": [ + { + "alg": "ed25519", + "keyId": "5ecb3da505414c4f", + "signature": "7tWT9iBArp2kwiaPpIdAS9v851rhhrZaDY6iW7G8F7KaBAdV8riBQBTj724j7LPiieVj5pzs4CobkaZ5bzgjDw==" + }, + { + "alg": "ml-dsa-65", + "keyId": "8bb85bc1f41c568c", + "signature": "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" + } + ], + "rule": "registry signature(s) over canonical(fields): each of `signatures` with the registrySignature.keys entry of the same alg/keyId (hybrid: all must verify); `signature` is the Ed25519 half" + }, + "rules": [ + "assertion: WebAuthn signature = ECDSA-P256/SHA-256 over authenticatorData || sha256(clientDataJSON), verified with publicKey.raw (uncompressed point); clientDataJSON.type must be \"webauthn.get\"; authenticatorData flags must include UV (user verified)", + "binding: verify each of binding.signatures (or binding.signature with alg ed25519) over canonical(binding.fields) with the matching registrySignature.keys entry — Ed25519 and, when present, ML-DSA-65; all must verify; binding.fields.recordHash must equal recordHash, binding.fields.credentialId must equal the assertion credential, and binding.fields.publicKey must equal approver.publicKey.raw (17 Oct 2026: an assertion re-signed by another key, with that key offered, passes every other check)", + "challenge: when approver.challenge is present (rule ask-v1, ceremonies from 18 Oct 2026), clientDataJSON.challenge must equal base64url(sha256(canonical(challenge.fields))) with fields.attestationId = approver.attestationId, fields.prompt = decision.prompt and fields.actionParamsHash = decision.actionParamsHash: the device signed over the ask, so the assertion itself names the act it answered. Absent, the challenge was a nonce and only the binding pairs the assertion with the record (an assertion by the same credential over another ask passes every other check)" + ] + }, + "basis": { + "asked": { + "seq": 9828, + "ts": "2026-10-17T15:46:49.298Z", + "area": "global", + "tool": "terminal", + "summary": "P=\".ab1-probe-DENY-$(date +%s)\"; rm -f \"$P\" && echo \"probe 3 ran (should not have)\"", + "paramsHash": "44a0989b444605481160f40a49763f27d6aa590153f85c97fa1833bdb0bf89d2", + "code": "hook_escalation", + "reason": "destructive filesystem command outside scratch roots", + "recordHash": "7fd55cc08bc34757f0d99f0a8912a0d7c39201fd318f46c741f4c9b0e2006fd7", + "model": "claude-fable-5-1" + }, + "grant": { + "area": "global", + "disposition": "allow", + "policyId": null, + "maxAmount": null, + "resources": [] + }, + "authorizeDisposition": "attest", + "area": "global", + "objective": null, + "rule": "asked = the attest record this ceremony answers (same plate, same action summary, raised just before the ceremony; cite it by recordHash); grant = the plate's grant rows as they stood when the ceremony was raised; asked.reason is the registry's stated reason for asking" + }, + "decision": { + "prompt": "ENG-WNP3.3057 (via Claude Code) wants to P=\".ab1-probe-DENY-$(date +%s)\"; rm -f \"$P\" && echo \"probe 3 ran (should not have)\"", + "response": "declined", + "status": "declined", + "createdAt": "2026-10-17T15:46:49.523Z", + "respondedAt": "2026-10-17T15:47:01.080Z", + "by": "sean@maclawran.ca", + "authMethod": "webauthn", + "requiredAuthMethod": null, + "amendment": null, + "actionParamsHash": "fc1fc0b0dde019c96f48005583d363ad84e5aab176b4dfc2e460202e509874e0", + "attestationHash": "746ec01a00227689788df3ae071adeaee5a74c732ae209440134ee0f7105713c", + "attestationHashRule": "sha256 over the registry's canonical attestation JSON (utils/attestationHashUtils.computeAttestationHash: id, prompt, response, status, respondedAt, approver, method, amendment, delivery, chain …); recomputable on the registry, cited here so the record and this decision are bound" + }, + "legalHolds": null, + "anchor": { + "rvnTxId": null, + "rvnAnchoredAt": null, + "rvnBlock": "00000000000081b33c166cf1961e598cb91d40a6fef817b0d2d8aaf3b6b62753@4585373", + "explorer": null, + "otsProof": "8AgHtW3WwcdWHAjwIDmHgtDWxTNE7J5/xgGaHDFnrQrc3inlHM3qhjw4tw0GCPAQXdqsoXnzk3MwpP23KriFggjxIPLwuvDSO69qmiS9474S+Avisk6Nj3GHF2cAlCMhKZEgCPAgcg99+b7AHf2ZK3gpBTOQs3DbDNA7V9MlZXNzGCHcjq4I8CBgv3qhup4MMtQ5Z6CeKEgdkDbyf3ckONgeLlOyncp01gjxBGrTmg3wCL37YWeTW8icAIPf4w0u+QyOLi1odHRwczovL2FsaWNlLmJ0Yy5jYWxlbmRhci5vcGVudGltZXN0YW1wcy5vcmc=", + "otsCalendar": "https://a.pool.opentimestamps.org", + "otsBlockHeight": null, + "rule": "the anchor transaction carries sealHash in OP_RETURN; its raw bytes are captured once the transaction confirms (a few minutes) — download the bundle again for the offline anchor check, or use the explorer link" + }, + "howToVerify": [ + "1. canonicalize `record` per `canonicalization.profile`, sha256 it, compare to `recordHash`", + "2. walk `merkle.proof` from `recordHash` (L: sha256(step+cur), R: sha256(cur+step)); the result must equal `seal.merkleRoot`", + "3. canonicalize the seal fields per `seal.rule`, sha256 it, compare to `seal.sealHash`", + "4. verify every entry of `registrySignature.signatures` over the seal hash with the key of the same alg/keyId in `registrySignature.keys` (Ed25519 + ML-DSA-65 when hybrid); older bundles: Ed25519-verify `signature` with `publicKeyRaw`", + "5. if `approver` is present: verify the WebAuthn assertion with `approver.publicKey.raw`, then Ed25519-verify `approver.binding.signature` over canonical(`approver.binding.fields`) with the registry key, and require `approver.binding.fields.publicKey` to equal `approver.publicKey.raw`: the binding, not the bundle, names the key the assertion may be checked with; when `approver.challenge` is present, recompute base64url(sha256(canonical(`challenge.fields`))) and require it to equal `clientDataJSON.challenge`, with the fields equal to `approver.attestationId`, `decision.prompt` and `decision.actionParamsHash`", + "6. if `anchor.proof` is present: check the OP_RETURN, the txid, the header hash and the merkleblock; else look up `anchor.rvnTxId` on any Ravencoin explorer", + "8. if `seal.profileHash` is present: `profile.document` must be present, sha256(canonical(document)) must equal it, and `profile.signature` must verify over the hash with the registry keys; absent profileHash = sealed before profiles", + "7. if `basis`/`decision` are present: `basis.asked.recordHash` is another record on the same chain (fetch its bundle and run steps 1–4); `decision.attestationHash` equals `record.attestationHash`; `decision.amendment.command`, when present, is what ran" + ], + "profile": { + "profileHash": "9bbe0635c0a05cc8107d40ad5bb2d8b227c8125d395f41620bcd371123319701", + "document": { + "v": 1, + "name": "org", + "registry": "in.xchk.io", + "dials": { + "identity": [ + "email", + "domain" + ], + "registration": "person", + "anchoring": [ + "rvn", + "ots" + ], + "signing": "ed25519+ml-dsa-65", + "actSummary": { + "kept": "registry", + "maxChars": 400 + }, + "inbound": "on", + "operatorAccess": "recorded", + "actRecords": "kept", + "publicRecord": "plate", + "principalDomains": [ + "maclawran.ca" + ] + } + }, + "signature": { + "alg": "ed25519+ml-dsa-65", + "keyId": "5ecb3da505414c4f", + "signature": "3wM2ISHYyVQSahc6iEv70t47+skkAxg7sS7Nu6p82ZVT/WgN6iUdc+A+padJl1DJRcTJQErs3ppXsM8ZTQlEAQ==", + "signedAt": "2026-10-17T15:48:48.412Z", + "signatures": [ + { + "alg": "ed25519", + "keyId": "5ecb3da505414c4f", + "signature": "3wM2ISHYyVQSahc6iEv70t47+skkAxg7sS7Nu6p82ZVT/WgN6iUdc+A+padJl1DJRcTJQErs3ppXsM8ZTQlEAQ==" + }, + { + "alg": "ml-dsa-65", + "keyId": "8bb85bc1f41c568c", + "signature": "Zb3O5PtSKMTE1QIBj1+w+IUyik8fJP0Dmp2qw1ekD2oasV+VXfozxa/RyJyURSrRi9CAddYUiRYPiH/dZmI1Hu2h0KNnNYJlEKbQbsIHx94sYCtVGNbD11saLwr/4I0iccCltJQVzxczreLdEhrhB/+Rn4+doXcWdWe+27/PwHrGoTg1wxcI/cooaNJCdcgerBqOhAe7c9yBihEfWC1u3nl76gApp5cFxAaScbBnJawFKucoOYlnzt8AIuoT1ccPKIw2r6gqhxOMLD+k3YFUSKu7ahEnKbiQQe5ha5rxv5h5O5G2z9q1zUU6L6rfzck664zzFybicPPUOFJe12n9Ndm+BvYL+SwNQMob0hoMeZ9DY1m6uoESHmwPLkXa8xdtmLel6HpOzB/1IV0xJgNrXeaUuPiqz/7cPabqOrcMKY/oSnSCThdqrH4Hq3621MrYAyTM4Xe5RXx9bjeucWOrkwDUQ2cTIfS+VCmNDWfBsLM1SecsR/EqWCQS77QHi67mUL1c8pPh2PuyUxAeec5Km7t7avHbaE2odXR/gcLrqkjk9vBsKJC1CHE50PsmXpMc+bnmwb6rTIRw/TsZskSy1zqmAj+SArKDcKGVcqVeQ40rCRfGeRDpEcxgjQQDtGzgqGAoK6i5Wet+gxI2QjmtLo+qpOmqrlvz58lVcGvYtmYeEjn83jx9ZThE06ewRVs/f6/JK6Bzee+2eokPpiuXVBaYXW92kAbYUZAqGmDYo1qvxhAnG7EeCk3kpTeBbeTl6EoFFL3jxZW5JVJPv9J4c3wQ6yOE37JigM19fKfcXyCBRqgk9BHriapm5MpaExmBN0EiIFSUYODXEWevw2KSy8xEAWpjSmecvAwJObZIPiLwTFjuv5w8D+r/oUt1ctr/gTxQ7i3XA2qZshIxHFtYzty7lF/nb3y9D5oJ2Zx5iFFEkvedHl1VzIFwcixW8O7GyHqZCHFTFpn9Iw0M9HONGsn7c1nuaNwyZfIJt4kll/Qj+2V0tsFd9J853cszdrG/Xup/rRIFj41wPDMoc2u+0RG+Iosu6xwf3triKj4jdID2ssTu+3Oq4OOY38JWBNG7XEhtgiiI7wnYc5iXqutgyOG/C/u2iATiuNPeGApJpZBvniO400OkmMvwOF0FfUJiK0GCt2GtmJYeeZ2juVLEdR6iVFtVzEIAR5Z5aTObTZM3IhTxGanM59xeKMOszYpip09a8XqMq13i4h+zgOZ+EU9FF9nOH+U+XoTaAaEFtKfV88Y8z9/CjabkpehU+0dplztr368tfm+aqIggWdkLy49Z5YkFo5RPO1vP7teQbxZUZXMNsh3yhAndDgb4MGfdokzg/np8TX3PSVeISfHdjWBN9EbypBWjDvRkQkpj8rzcC/hvMByY3dNU3UD9oCKZXFBXl49YIB45Ul6WvbgIZiZSvb1jMKsfAKZejbrZ61x8lHPfeyWG0dY6mmprZAIMdf1oKc03aeXOcNx3tyTTtANr4VqwtW8neW69N0V6vIV5yYjyWn4tgoK5G4DP0WWftIH6+39CT6KMszwpfYNTawHt1e8nXonGn4DTm/GKidJCJpEamDXPwGCJbC2F6yHbUFFy3o6ICTw1MPD720r8n8F3CZgiaFsloB4YLcTA657xn1OMpbD2VA4WLGW2SzqTfDtHILcKuGs7Oj7lYxlF7Gs/+ILEEbqgbhNmHi3cQIoC7Wyc7Iib4sXqySKk17o8H40dE0CgHkJ/++ub2+eHexlFdd1NBqGUE9BOBPnqR+1gkvIJ1KSzGy5SLKRbiXZraUDyfnpylXW+dY3/68GAWdrIH0QKvdnG+qgAVgsXKA9UNyEF3sXq6YTrTXQG8w4QL6N/AqMWUGICf/0L6bxSYIaoVzh1gXmWhHOyYWf4+nSDzbKMtnbDKUJ4YvmZ3beG2s00KllebdnOuGlBWXCX4OJmCvjtyz3WEZzl3mbhqHr29/c7UrcYT+H54pDqg8vyY3SfT4lgvEXpuboXOP7Gug/VJ5mtUHw0Cd5JuxX4KXr00Fy8P2kI/5eoa38IfNxilmQZXwCV1tkLyQ+CIQLhk2lkrUDr8NzEuXFvTg4692LndmLkDU3NeUlFDxY59HrMNs3zuVZa1x5oWk2dXyg6EfWIm4a1rPhL/d3tvwx/aSEiG55SC3H7fXIXb0gipC+fRtkKXfJCYJKHkYoNAL9jxzv8MEJaXVrbW5xpBrIqo3uQZ03cVbysQtvCwTMdd+NIZD3ny+R6cFM23NHoFgXJRk1r145Hq2zUmPJ/aDx9/l2qvAsozNkasnIfFPYAw2QA8CrtU4P2g/l4RLTBxWdEPa2fGN24OuMW/tlUzE1U7ypKSFpIHPa8hB6y7KhNPDsNGwoQoTKCoO3tYkQ1hWcaa95HSA+N/CTTHUYlKcA5J13ooeZTBVzp24hq6GwWIo9Wphqpvf7MAjrH9I3j9fyQkRgB2FV2hFztqLNsMd+KYL9oJ5FSArkYzZvgJNBnb+U9k88HFRDqgsIPDdJ6wo8CE8aczYrCyIRazbew5y1eNTW7At6LIY59T+TTCjwQYlBIQGn5f/NZP5hMmgQ8Z5lveiEhfd4TGvnA3RJvVswuiPSB2kl3FVIkwLdLsON+lkMQargJLqUVcasRaCqoIiHS3Im3bxbS9Z2ObH7B38uz43Q45+NOoD+X/ig0try+5O37C9J5p9mLDQ4U4gFhTwaNIjBER/jwt7wkW0OWi1VICwqS+knN51XsBgkLcDgH+sQUZC46M6OKsrYC5mwn+gq/xaTLj6QPaVI0gVU6up7cgDKYfvjvOBkSL0zJkrHDfyXcBsU9FsmWQgq9EptgTORzshvBUlV92Bt6ilhbEFpQFMcTMjmmyx4slEm+h2NnYQBzJP7u1JEIdj7FWLksLoijfjj5jj0zY9myN4XJxWtVeSLYA+ofntcYXkEPUvfwdoA9HwFkt3B2STxVT++MlJew+My9H49HsgzBJAHpfu7kyVeelgUPjLGk3YPQgdbCuUYwsktRPfLXDzV1Xv2SII09lMstuy1WdB+U8mT/PnBaQh2N/7Xy0oPbXfMWqZ3V3LflGqwQTRo/GVPr9ABPwNdZ3M00VPDZ31ps6aHd9PPqXWGRY8V1yETvX+FyNQsThmF0tIkjoAp2Cn5244hEVdDb15qbb5K+PNHta//0kzWSggwxmsr7j6GfUXFjJ66oxVX44oPySqn1LZSk8TCkyOWOT+0fKHEdxNko2dqzbjz2/Nt9k6LJdUX6hcN6IW5uGcnyywgJ9RfCQjZoyvsD9fQ/2W6Zsiy5Okfd/0c1JkYTdLihE8zVx2ajsV/MCRbHDQZ4o1Rw8IJY/m61RtPkcLE3uSpmTkxSwTi1oeQdiMBf+gqZ+Zc6u3aWMRNyQ1DOyfTQbBWFk9ph/d9VPrmucPdFYOa9e4w6mbTm8McGrsxr3K6QJ/nkLGw7se3vaXwkG5ppznSvGSFWAR3bGE3vBdPqXU9DOIK2uYzI3+0YxXHe5iSbOLYxqHEEjq231jey73eScieDN2bWVaVSrEPIO+B+ecHJ+lFGScMLN7ouzvP+ppapLtE//8RAubZX1xWr9LCmewO0e2HwBg+EPnh7FQv//DxCDgz54zN3xuozWUVrJAE/BHo/BrEQG3vvPB/3IBK4JjWSJRKeoEoe/q2C+b5rkk+QPic/VfSDtZM/CIRyQu/pNgZyY9lv3KFGKDcpon2AbNh67OK78rCkvvS7czZI1o2Do71AMNUaTWDz/dLmidbbVbxQXHrAgR34iplKwoEY44i4k1Masm9NUC7uZyo4wNBX11um5ovIi2owhVtDZQOEgpbPk7f4MC2n6oXSghiTaCxaqG62p8uFaT40Xp1n3kkLo/11RzTgVDCTtQ+cffAkb9G6ZNbPjGxTdAHoiJiOzwYF91CITM8xl12J5nSi3UsgeFSaZRRvfn+vDgnkb4ZRb3vBi+5BtVaJw1yqzWDPmWOflM3SgjAPH0+Y/rvIkNhUNqcj090gVVT1UtOtJVyLDbwRJ2R/iANFO/2vOVZtxHwxx2ucj0TP7j9m0/EvEv0W+NMYGq8maREbtq1sBtfAs9z7QF95WGznTw4099ErR1tzym2QogHIyD6myZ1f1bYTKRJxekrBi8DQu9fMe9U2yrI5krKLBZNt3yl9eHvdNKcEdSyCXLWl4HjinufRh1hNk8wg5HoYCu/5JXkQJvLtn1ZaoqqIOVPOsgZWwcoo3kO1cKwTseyL7yYmTuqmqv8tEVWSDFgjCTFtmPYckRrEK8zi59XSoAaNUmYAIBK4v4QPUiYEjTF5zs+zGfsLRphEK9DuQ7yd2hxDFZ6IfYdXgrrB5wxidZXd82RmbnKixdwlX2fg4xQpSWOexdjdMEOHnp+yutDi9AAAAAAAAAAAAAAAAAAABQsSFx8p" + } + ] + }, + "rule": "sha256(canonical(document)) = seal.profileHash; verify signature over the UTF-8 bytes of profileHash with the same registrySignature.keys as the seal; document.dials are the rules this node ran under when it sealed the window" + }, + "verifier": { + "html": "https://in.xchk.io/verify-receipt.html", + "python": "https://in.xchk.io/verify/verify_receipt.py", + "license": "MIT" + } +} diff --git a/integrations/xchk-registry/examples/approval-outcome/03-decision-is-a-denial.json b/integrations/xchk-registry/examples/approval-outcome/03-decision-is-a-denial.json new file mode 100644 index 00000000..0db3a5d9 --- /dev/null +++ b/integrations/xchk-registry/examples/approval-outcome/03-decision-is-a-denial.json @@ -0,0 +1,47 @@ +{ + "eat_profile": "tag:agentrust-io.com,2026:trace-v0.2", + "iat": 1792252491, + "subject": "did:web:in.xchk.io:plate:ENG-WNP3", + "model": { + "provider": "anthropic", + "model_id": "claude-fable-5-1" + }, + "runtime": { + "platform": "software-only", + "measurement": "sha256:c60a771a8f6e4fda60fbb2b745397c800c38da090f153f72e302147a1851746a" + }, + "policy": { + "bundle_hash": "sha256:8e1e29b1e2b1470b57fba453991d3c9ef0d0ae19ba59927c014525177ee741ae", + "enforcement_mode": "enforce" + }, + "data_class": "internal", + "tool_transcript": { + "hash": "sha256:54ea01281f1acf13dec96c509cb243c5ee87b826524044ac8c2700a63cd9f2bb", + "call_count": 101 + }, + "references": [ + { + "rel": "approval-outcome", + "id": "24e7d14e03dbf72472d55d8a7266c1a0f98fe3f6e8600b1601fa17159ce43778", + "resolver": "https://in.xchk.io", + "digest": "sha256:24e7d14e03dbf72472d55d8a7266c1a0f98fe3f6e8600b1601fa17159ce43778" + } + ], + "build_provenance": { + "slsa_level": 0, + "digest": "sha256:c60a771a8f6e4fda60fbb2b745397c800c38da090f153f72e302147a1851746a" + }, + "appraisal": { + "status": "none", + "verifier": "https://in.xchk.io" + }, + "cnf": { + "jwk": { + "kty": "OKP", + "crv": "Ed25519", + "x": "mn02E1XyTkaVN6DEOemU5OADMUAUjPHw67oR5KKIM3k", + "kid": "5ecb3da505414c4f" + } + }, + "signature": "RHTiHD6m3ej14lwbVL8nIGpOo82wFcyhPaunSXLePWAXsr0UF6Y9E6_UhoA93Lsv4FMyJ3h3JFWJWUtt3I5DBw" +} diff --git a/integrations/xchk-registry/examples/approval-outcome/04-no-answer.bundle.json b/integrations/xchk-registry/examples/approval-outcome/04-no-answer.bundle.json new file mode 100644 index 00000000..f43ba362 --- /dev/null +++ b/integrations/xchk-registry/examples/approval-outcome/04-no-answer.bundle.json @@ -0,0 +1,322 @@ +{ + "format": "xchk-receipt-bundle/2", + "issuer": { + "name": "xChk registry", + "base": "https://in.xchk.io", + "servedAt": "2026-10-17T15:54:52.144Z", + "headline": "ENG-WNP3: EXPIRED terminal in global at 2026-10-17T15:39:25.139Z — no answer; sean@maclawran.ca was asked." + }, + "recordHash": "5cad45602b4554d5172ee747157b276bc0ad619d146a8b7bf6052ec3fea9c98f", + "record": { + "v": 1, + "agentId": "6acbf860a627414b66045478", + "plate": "ENG-WNP3", + "seq": 9817, + "ts": "2026-10-17T15:39:25.139Z", + "harness": "claude", + "runSeq": 3057, + "runRef": "ENG WNP3.3057", + "area": "global", + "tool": "terminal", + "summary": "P=\".ab1-probe-approve1-$(date +%s)\"; rm -f \"$P\" && echo \"probe 1 ran (nothing existed to remove)\"", + "paramsHash": "a791bccfa14f0666b7082aab7586455f1898da48651cbbbb643e0df3402655c6", + "amount": null, + "disposition": "expired", + "code": "unanswered", + "reason": "no answer before 2026-10-17T15:29:52.066Z; 1 asked, request delivered", + "deskCondition": "normal", + "continuityClass": "standard", + "authRef": "aa3506a540e21e96a1419c5f", + "prevHash": "e1ee8e640301cbed047dffac887edf36b18167a2b2a1864510a66ad1f36421e4", + "rvnBlock": "0000000000001c5a7d36ec39105e89b0610efdfe8f78aec4b0d19431b56de79a@4585355", + "approverEmail": "sean@maclawran.ca", + "attestationId": "6ad392185f7026f62ae79919", + "attestationHash": "1e69771d9b4a58cb0614014f630396bd70fbf064676417eb049ce7a2ffa554fa", + "model": "claude-fable-5-1" + }, + "canonicalization": { + "profile": "JSON with object keys sorted (code-unit order), no whitespace, scalars as JSON.stringify would emit them, undefined omitted, integers only; hash = sha256 over the UTF-8 bytes", + "hashedConditionalKeys": [ + "rvnBlock", + "approverEmail", + "authMethod", + "requiredAuthMethod", + "attestationId", + "attestationHash", + "photoUrl", + "labelsHash", + "delegationHash", + "model", + "tokensIn", + "tokensOut", + "tokensCacheRead", + "contextPct", + "actor", + "chargeCode", + "workspace", + "policyHash", + "outcomeOf", + "resultHash", + "endedAt", + "artifactHash" + ], + "note": "conditional keys are present only when the record carried them; absent keys are absent from the bytes, not null" + }, + "merkle": { + "proof": [], + "leafCount": 1, + "rule": "node = sha256(left_hex + right_hex) over the hex strings; an odd node is promoted unhashed; the leaf is the record hash" + }, + "seal": { + "v": 1, + "agentId": "6acbf860a627414b66045478", + "plate": "ENG-WNP3", + "sealSeq": 1494, + "windowStart": "2026-10-17T15:34:25.565Z", + "windowEnd": "2026-10-17T15:39:25.565Z", + "count": 1, + "issuedCount": 1, + "seqStart": 9817, + "seqEnd": 9817, + "merkleRoot": "5cad45602b4554d5172ee747157b276bc0ad619d146a8b7bf6052ec3fea9c98f", + "deskCondition": "normal", + "prevSealHash": "30018484d035590c6000764111fd2c578786234b506275c74019e24f048ca0b8", + "rvnBlock": "0000000000001c5a7d36ec39105e89b0610efdfe8f78aec4b0d19431b56de79a@4585355", + "profileHash": "9bbe0635c0a05cc8107d40ad5bb2d8b227c8125d395f41620bcd371123319701", + "sealHash": "47ebb87c0307bb71ee8dec7cb5eda8357ca24ad328332f17a07add2d56430616", + "rule": "sealHash = sha256(canonical({v, agentId, plate, sealSeq, windowStart, windowEnd, count, issuedCount, seqStart, seqEnd, merkleRoot, deskCondition, prevSealHash[, rvnBlock][, profileHash]}))" + }, + "registrySignature": { + "alg": "ed25519+ml-dsa-65", + "keyId": "5ecb3da505414c4f", + "signature": "jYR2b8Ci8uMdHRGnvXjjYd3fVycS24CyzeW/pdQBdTAxAiyjs3iaCFN6auV4FbRpooWwjXGk+6CyagPdco1PDA==", + "signedAt": "2026-10-17T15:39:25.625Z", + "signatures": [ + { + "alg": "ed25519", + "keyId": "5ecb3da505414c4f", + "signature": "jYR2b8Ci8uMdHRGnvXjjYd3fVycS24CyzeW/pdQBdTAxAiyjs3iaCFN6auV4FbRpooWwjXGk+6CyagPdco1PDA==" + }, + { + "alg": "ml-dsa-65", + "keyId": "8bb85bc1f41c568c", + "signature": "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" + } + ], + "signedOver": "the UTF-8 bytes of seal.sealHash", + "publicKeyRaw": "mn02E1XyTkaVN6DEOemU5OADMUAUjPHw67oR5KKIM3k=", + "publicKeyPem": "-----BEGIN PUBLIC KEY-----\nMCowBQYDK2VwAyEAmn02E1XyTkaVN6DEOemU5OADMUAUjPHw67oR5KKIM3k=\n-----END PUBLIC KEY-----\n", + "wellKnown": "https://in.xchk.io/.well-known/xchk-keys.json", + "keys": [ + { + "alg": "ed25519", + "keyId": "5ecb3da505414c4f", + "publicKeyRaw": "mn02E1XyTkaVN6DEOemU5OADMUAUjPHw67oR5KKIM3k=" + }, + { + "alg": "ml-dsa-65", + "keyId": "8bb85bc1f41c568c", + "publicKeyRaw": "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" + } + ], + "retired": [], + "publicKeyRawPq": "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", + "keyIdPq": "8bb85bc1f41c568c", + "root": { + "alg": "slh-dsa-sha2-128s", + "standard": "FIPS 205", + "keyId": "acc7ad1aeb3ef177", + "publicKeyRaw": "4aIhDuj3TZPwqb9HT8TzVJnkvle4jVUMhWkn/BfmypM=", + "statement": { + "v": 1, + "registry": "https://in.xchk.io", + "keys": [ + { + "alg": "ed25519", + "keyId": "5ecb3da505414c4f", + "publicKeyRaw": "mn02E1XyTkaVN6DEOemU5OADMUAUjPHw67oR5KKIM3k=" + }, + { + "alg": "ml-dsa-65", + "keyId": "8bb85bc1f41c568c", + "publicKeyRaw": "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" + } + ], + "retired": [], + "oidc": [ + { + "kid": "XWUv0uGESGdIG1MjOzbVjcwxB0CYtK0oZ9SZxNkH7h8", + "kty": "RSA", + "alg": "RS256", + "n": "zQwdJyTuyqQvB5zIXp9ULjX22k-R95Ls5j3IVUwLcI87I2VPUjsvy9oDGl5cq8Jl7Rt21d966AakANr8J1vT7gMpcmPOcEGVDdgdCprRs8cWNDo5uJ4ejt1LW65zRqW8xsxqHPm1aOxvjeUQfNgZFLn3VlSX01zgjggBLSwL18stLbyIzA2zcj4lpV-IrnBO3S6VUusoaO__kXjHv1-aH64wpVcsNLrBX6MWsnHM-KptbhKrk_qqXMJ7dokBxiIAH32VjZ73kTbVcSXoU2FshM_eQaonhYcRoD8PTXN3rxMaisj2pka9XZ1Apqy-EHf1dCoUphYxd_--FcT5PDQZaQ", + "e": "AQAB" + } + ], + "issuedAt": "2026-10-17T15:48:57.541Z" + }, + "signature": "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", + "rule": "SLH-DSA-SHA2-128s verify(publicKeyRaw, canonical(statement) bytes, signature); statement.keys are the keys this registry signs with" + }, + "rule": "HYBRID: for each entry in signatures, verify(keys[alg,keyId].publicKeyRaw, sealHash bytes, signature) — Ed25519 for alg ed25519, ML-DSA-65 (FIPS 204) for alg ml-dsa-65; ALL must verify. keyId = sha256(SPKI or raw key)[:16]. root, when present, is the SLH-DSA-SHA2-128s statement of these keys." + }, + "approver": { + "email": "sean@maclawran.ca", + "authLevel": "didit", + "authMethod": null, + "attestationId": "6ad392185f7026f62ae79919", + "credentialId": null, + "publicKey": null, + "assertion": null, + "challenge": null, + "binding": { + "fields": { + "v": 1, + "recordHash": "5cad45602b4554d5172ee747157b276bc0ad619d146a8b7bf6052ec3fea9c98f", + "attestationId": "6ad392185f7026f62ae79919", + "credentialId": null, + "publicKey": null, + "approverEmail": "sean@maclawran.ca", + "authLevel": "didit", + "authMethod": null, + "verifiedAt": null + }, + "signature": "wGHKXIv3UijlqKMVfLgKozm/iwPxkoLVw8fGrxepAOsqOqDtr0PwfC23ZXKD/L5qljqGA6BU+SXfVjIHqmxNAg==", + "keyId": "5ecb3da505414c4f", + "signedAt": "2026-10-17T15:54:52.137Z", + "alg": "ed25519+ml-dsa-65", + "signatures": [ + { + "alg": "ed25519", + "keyId": "5ecb3da505414c4f", + "signature": "wGHKXIv3UijlqKMVfLgKozm/iwPxkoLVw8fGrxepAOsqOqDtr0PwfC23ZXKD/L5qljqGA6BU+SXfVjIHqmxNAg==" + }, + { + "alg": "ml-dsa-65", + "keyId": "8bb85bc1f41c568c", + "signature": "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" + } + ], + "rule": "registry signature(s) over canonical(fields): each of `signatures` with the registrySignature.keys entry of the same alg/keyId (hybrid: all must verify); `signature` is the Ed25519 half" + }, + "rules": [ + "assertion: WebAuthn signature = ECDSA-P256/SHA-256 over authenticatorData || sha256(clientDataJSON), verified with publicKey.raw (uncompressed point); clientDataJSON.type must be \"webauthn.get\"; authenticatorData flags must include UV (user verified)", + "binding: verify each of binding.signatures (or binding.signature with alg ed25519) over canonical(binding.fields) with the matching registrySignature.keys entry — Ed25519 and, when present, ML-DSA-65; all must verify; binding.fields.recordHash must equal recordHash, binding.fields.credentialId must equal the assertion credential, and binding.fields.publicKey must equal approver.publicKey.raw (17 Oct 2026: an assertion re-signed by another key, with that key offered, passes every other check)", + "challenge: when approver.challenge is present (rule ask-v1, ceremonies from 18 Oct 2026), clientDataJSON.challenge must equal base64url(sha256(canonical(challenge.fields))) with fields.attestationId = approver.attestationId, fields.prompt = decision.prompt and fields.actionParamsHash = decision.actionParamsHash: the device signed over the ask, so the assertion itself names the act it answered. Absent, the challenge was a nonce and only the binding pairs the assertion with the record (an assertion by the same credential over another ask passes every other check)" + ] + }, + "basis": { + "asked": { + "seq": 9812, + "ts": "2026-10-17T15:19:51.834Z", + "area": "global", + "tool": "terminal", + "summary": "P=\".ab1-probe-approve1-$(date +%s)\"; rm -f \"$P\" && echo \"probe 1 ran (nothing existed to remove)\"", + "paramsHash": "a791bccfa14f0666b7082aab7586455f1898da48651cbbbb643e0df3402655c6", + "code": "hook_escalation", + "reason": "destructive filesystem command outside scratch roots", + "recordHash": "8717d7ccb12e1d0fb80af136c831c671bf27e9c144745f4245a1934e35b184f5", + "model": "claude-fable-5-1" + }, + "grant": { + "area": "global", + "disposition": "allow", + "policyId": null, + "maxAmount": null, + "resources": [] + }, + "authorizeDisposition": "attest", + "area": "global", + "objective": null, + "rule": "asked = the attest record this ceremony answers (same plate, same action summary, raised just before the ceremony; cite it by recordHash); grant = the plate's grant rows as they stood when the ceremony was raised; asked.reason is the registry's stated reason for asking" + }, + "decision": { + "prompt": "ENG-WNP3.3057 (via Claude Code) wants to P=\".ab1-probe-approve1-$(date +%s)\"; rm -f \"$P\" && echo \"probe 1 ran (nothing existed to remove)\"", + "response": null, + "status": "expired", + "createdAt": "2026-10-17T15:19:52.067Z", + "respondedAt": null, + "by": "sean@maclawran.ca", + "authMethod": null, + "requiredAuthMethod": null, + "amendment": null, + "actionParamsHash": "5eee3b37a63eb957436a2bd51633d8a3c9a54f96c66e71f45fbd2d458373ca68", + "attestationHash": "1e69771d9b4a58cb0614014f630396bd70fbf064676417eb049ce7a2ffa554fa", + "attestationHashRule": "sha256 over the registry's canonical attestation JSON (utils/attestationHashUtils.computeAttestationHash: id, prompt, response, status, respondedAt, approver, method, amendment, delivery, chain …); recomputable on the registry, cited here so the record and this decision are bound" + }, + "legalHolds": null, + "anchor": { + "rvnTxId": null, + "rvnAnchoredAt": null, + "rvnBlock": "0000000000001c5a7d36ec39105e89b0610efdfe8f78aec4b0d19431b56de79a@4585355", + "explorer": null, + "otsProof": "8AjnN+R8gx/FPgjwEBMIiV8LHKiJNIumZjEfIwoI8CBNZp2hOx7wmsySeat5YyckKR8s9rGsiOez6ABxrvP71AjwIA9NiYbwY9Y3Ad5LlKD77NLe+Ve8Qfl0k9ig5ycZmW94CPAggIJUV9oFR0XOGuog24U6A9FbYMPVvYSzyg39YeOhZ9sI8QRq05au8AgBAAVW+fEs7gCD3+MNLvkMji4taHR0cHM6Ly9hbGljZS5idGMuY2FsZW5kYXIub3BlbnRpbWVzdGFtcHMub3Jn", + "otsCalendar": "https://a.pool.opentimestamps.org", + "otsBlockHeight": null, + "rule": "the anchor transaction carries sealHash in OP_RETURN; its raw bytes are captured once the transaction confirms (a few minutes) — download the bundle again for the offline anchor check, or use the explorer link" + }, + "howToVerify": [ + "1. canonicalize `record` per `canonicalization.profile`, sha256 it, compare to `recordHash`", + "2. walk `merkle.proof` from `recordHash` (L: sha256(step+cur), R: sha256(cur+step)); the result must equal `seal.merkleRoot`", + "3. canonicalize the seal fields per `seal.rule`, sha256 it, compare to `seal.sealHash`", + "4. verify every entry of `registrySignature.signatures` over the seal hash with the key of the same alg/keyId in `registrySignature.keys` (Ed25519 + ML-DSA-65 when hybrid); older bundles: Ed25519-verify `signature` with `publicKeyRaw`", + "5. if `approver` is present: verify the WebAuthn assertion with `approver.publicKey.raw`, then Ed25519-verify `approver.binding.signature` over canonical(`approver.binding.fields`) with the registry key, and require `approver.binding.fields.publicKey` to equal `approver.publicKey.raw`: the binding, not the bundle, names the key the assertion may be checked with; when `approver.challenge` is present, recompute base64url(sha256(canonical(`challenge.fields`))) and require it to equal `clientDataJSON.challenge`, with the fields equal to `approver.attestationId`, `decision.prompt` and `decision.actionParamsHash`", + "6. if `anchor.proof` is present: check the OP_RETURN, the txid, the header hash and the merkleblock; else look up `anchor.rvnTxId` on any Ravencoin explorer", + "8. if `seal.profileHash` is present: `profile.document` must be present, sha256(canonical(document)) must equal it, and `profile.signature` must verify over the hash with the registry keys; absent profileHash = sealed before profiles", + "7. if `basis`/`decision` are present: `basis.asked.recordHash` is another record on the same chain (fetch its bundle and run steps 1–4); `decision.attestationHash` equals `record.attestationHash`; `decision.amendment.command`, when present, is what ran" + ], + "profile": { + "profileHash": "9bbe0635c0a05cc8107d40ad5bb2d8b227c8125d395f41620bcd371123319701", + "document": { + "v": 1, + "name": "org", + "registry": "in.xchk.io", + "dials": { + "identity": [ + "email", + "domain" + ], + "registration": "person", + "anchoring": [ + "rvn", + "ots" + ], + "signing": "ed25519+ml-dsa-65", + "actSummary": { + "kept": "registry", + "maxChars": 400 + }, + "inbound": "on", + "operatorAccess": "recorded", + "actRecords": "kept", + "publicRecord": "plate", + "principalDomains": [ + "maclawran.ca" + ] + } + }, + "signature": { + "alg": "ed25519+ml-dsa-65", + "keyId": "5ecb3da505414c4f", + "signature": "3wM2ISHYyVQSahc6iEv70t47+skkAxg7sS7Nu6p82ZVT/WgN6iUdc+A+padJl1DJRcTJQErs3ppXsM8ZTQlEAQ==", + "signedAt": "2026-10-17T15:48:48.412Z", + "signatures": [ + { + "alg": "ed25519", + "keyId": "5ecb3da505414c4f", + "signature": "3wM2ISHYyVQSahc6iEv70t47+skkAxg7sS7Nu6p82ZVT/WgN6iUdc+A+padJl1DJRcTJQErs3ppXsM8ZTQlEAQ==" + }, + { + "alg": "ml-dsa-65", + "keyId": "8bb85bc1f41c568c", + "signature": "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" + } + ] + }, + "rule": "sha256(canonical(document)) = seal.profileHash; verify signature over the UTF-8 bytes of profileHash with the same registrySignature.keys as the seal; document.dials are the rules this node ran under when it sealed the window" + }, + "verifier": { + "html": "https://in.xchk.io/verify-receipt.html", + "python": "https://in.xchk.io/verify/verify_receipt.py", + "license": "MIT" + } +} diff --git a/integrations/xchk-registry/examples/approval-outcome/04-no-answer.json b/integrations/xchk-registry/examples/approval-outcome/04-no-answer.json new file mode 100644 index 00000000..6d1868b8 --- /dev/null +++ b/integrations/xchk-registry/examples/approval-outcome/04-no-answer.json @@ -0,0 +1,47 @@ +{ + "eat_profile": "tag:agentrust-io.com,2026:trace-v0.2", + "iat": 1792252491, + "subject": "did:web:in.xchk.io:plate:ENG-WNP3", + "model": { + "provider": "anthropic", + "model_id": "claude-fable-5-1" + }, + "runtime": { + "platform": "software-only", + "measurement": "sha256:c60a771a8f6e4fda60fbb2b745397c800c38da090f153f72e302147a1851746a" + }, + "policy": { + "bundle_hash": "sha256:8e1e29b1e2b1470b57fba453991d3c9ef0d0ae19ba59927c014525177ee741ae", + "enforcement_mode": "enforce" + }, + "data_class": "internal", + "tool_transcript": { + "hash": "sha256:54ea01281f1acf13dec96c509cb243c5ee87b826524044ac8c2700a63cd9f2bb", + "call_count": 101 + }, + "references": [ + { + "rel": "approval-outcome", + "id": "5cad45602b4554d5172ee747157b276bc0ad619d146a8b7bf6052ec3fea9c98f", + "resolver": "https://in.xchk.io", + "digest": "sha256:5cad45602b4554d5172ee747157b276bc0ad619d146a8b7bf6052ec3fea9c98f" + } + ], + "build_provenance": { + "slsa_level": 0, + "digest": "sha256:c60a771a8f6e4fda60fbb2b745397c800c38da090f153f72e302147a1851746a" + }, + "appraisal": { + "status": "none", + "verifier": "https://in.xchk.io" + }, + "cnf": { + "jwk": { + "kty": "OKP", + "crv": "Ed25519", + "x": "mn02E1XyTkaVN6DEOemU5OADMUAUjPHw67oR5KKIM3k", + "kid": "5ecb3da505414c4f" + } + }, + "signature": "F5wyIJ_83-UasK-nt6vEs7226b1zFc9__v2rbURahybpXva6lr06YiXnbnULXl7kENa_gXiK-Kt-KD0kZkVFCw" +} diff --git a/integrations/xchk-registry/examples/approval-outcome/05-reference-unresolvable.json b/integrations/xchk-registry/examples/approval-outcome/05-reference-unresolvable.json new file mode 100644 index 00000000..8cb8395f --- /dev/null +++ b/integrations/xchk-registry/examples/approval-outcome/05-reference-unresolvable.json @@ -0,0 +1,47 @@ +{ + "eat_profile": "tag:agentrust-io.com,2026:trace-v0.2", + "iat": 1792252491, + "subject": "did:web:in.xchk.io:plate:ENG-WNP3", + "model": { + "provider": "anthropic", + "model_id": "claude-fable-5-1" + }, + "runtime": { + "platform": "software-only", + "measurement": "sha256:c60a771a8f6e4fda60fbb2b745397c800c38da090f153f72e302147a1851746a" + }, + "policy": { + "bundle_hash": "sha256:8e1e29b1e2b1470b57fba453991d3c9ef0d0ae19ba59927c014525177ee741ae", + "enforcement_mode": "enforce" + }, + "data_class": "internal", + "tool_transcript": { + "hash": "sha256:54ea01281f1acf13dec96c509cb243c5ee87b826524044ac8c2700a63cd9f2bb", + "call_count": 101 + }, + "references": [ + { + "rel": "approval-outcome", + "id": "c92c8c55d333d24204fcb453596cf1c784ea2755e6fc963c1176314c3e2bee9f", + "resolver": "https://in.xchk.io", + "digest": "sha256:c92c8c55d333d24204fcb453596cf1c784ea2755e6fc963c1176314c3e2bee9f" + } + ], + "build_provenance": { + "slsa_level": 0, + "digest": "sha256:c60a771a8f6e4fda60fbb2b745397c800c38da090f153f72e302147a1851746a" + }, + "appraisal": { + "status": "none", + "verifier": "https://in.xchk.io" + }, + "cnf": { + "jwk": { + "kty": "OKP", + "crv": "Ed25519", + "x": "mn02E1XyTkaVN6DEOemU5OADMUAUjPHw67oR5KKIM3k", + "kid": "5ecb3da505414c4f" + } + }, + "signature": "TaVzV55F5ZytJNu4GkusOvDfbrJs-XjKrdNciutBuztiT1fdx-nFfUZNYkgtBWlJni9qqTDJ_ItYNlE5cdp0CA" +} diff --git a/integrations/xchk-registry/examples/approval-outcome/06-assertion-from-another-credential.bundle.json b/integrations/xchk-registry/examples/approval-outcome/06-assertion-from-another-credential.bundle.json new file mode 100644 index 00000000..9682f694 --- /dev/null +++ b/integrations/xchk-registry/examples/approval-outcome/06-assertion-from-another-credential.bundle.json @@ -0,0 +1,368 @@ +{ + "format": "xchk-receipt-bundle/2", + "issuer": { + "name": "xChk registry", + "base": "https://in.xchk.io", + "servedAt": "2026-10-17T15:54:51.987Z", + "headline": "ENG-WNP3: APPROVED terminal in global at 2026-10-17T15:46:00.571Z — approved by sean@maclawran.ca." + }, + "recordHash": "aa2bfd5b1d9b6307ed22eb0daa4213383beecb57d7d31ec011060ac98f7fe0b5", + "record": { + "v": 1, + "agentId": "6acbf860a627414b66045478", + "plate": "ENG-WNP3", + "seq": 9819, + "ts": "2026-10-17T15:46:00.571Z", + "harness": "claude", + "runSeq": 3057, + "runRef": "ENG WNP3.3057", + "area": "global", + "tool": "terminal", + "summary": "P=\".ab1-probe-approve1-$(date +%s)\"; rm -f \"$P\" && echo \"probe 1 ran (nothing existed to remove)\"", + "paramsHash": "a791bccfa14f0666b7082aab7586455f1898da48651cbbbb643e0df3402655c6", + "amount": null, + "disposition": "approved", + "code": null, + "reason": null, + "deskCondition": "normal", + "continuityClass": "standard", + "authRef": "c2486b7f4874e5d08aba0725", + "prevHash": "25607c8e2e529dddce618b49b1c11da6b302a6687c6d44b335f304e904dc796f", + "rvnBlock": "000000000001303bd2857ce3c400c92e8bcf8b97c14eda4f85650e03f91ef3e3@4585364", + "approverEmail": "sean@maclawran.ca", + "authMethod": "webauthn", + "attestationId": "6ad398295f7026f62ae7b863", + "attestationHash": "d7896ca4608bcdd8581ce6c0bb5917e541d40d635334e1a8746d7fc1bc230d5e", + "photoUrl": "https://xchk-main.s3.us-east-005.backblazeb2.com/xchk/xchk/baseline/att_6ad398295f7026f62ae7b863/0.jpg", + "model": "claude-fable-5-1" + }, + "canonicalization": { + "profile": "JSON with object keys sorted (code-unit order), no whitespace, scalars as JSON.stringify would emit them, undefined omitted, integers only; hash = sha256 over the UTF-8 bytes", + "hashedConditionalKeys": [ + "rvnBlock", + "approverEmail", + "authMethod", + "requiredAuthMethod", + "attestationId", + "attestationHash", + "photoUrl", + "labelsHash", + "delegationHash", + "model", + "tokensIn", + "tokensOut", + "tokensCacheRead", + "contextPct", + "actor", + "chargeCode", + "workspace", + "policyHash", + "outcomeOf", + "resultHash", + "endedAt", + "artifactHash" + ], + "note": "conditional keys are present only when the record carried them; absent keys are absent from the bytes, not null" + }, + "merkle": { + "proof": [ + { + "side": "L", + "hash": "25607c8e2e529dddce618b49b1c11da6b302a6687c6d44b335f304e904dc796f" + }, + { + "side": "R", + "hash": "61cbbb71667c7ad8ed2fb67feadf3454a801ced41e3d303ba7b8297524c0e86b" + }, + { + "side": "R", + "hash": "c7f7fb52d081b787566876416919dca904cef18613bb63efa3e28b0ab8eeced5" + }, + { + "side": "R", + "hash": "30e986cfeef36f573d77f3f49948c8bc3248ee8e068d439c149ee72dbe2dad8b" + }, + { + "side": "R", + "hash": "b1f52c8bef88f4187114b4cfab6922468a0e2f3775dc9b6fa7d1479458d02019" + }, + { + "side": "R", + "hash": "b8de3bc958dcdcd07dfc74b47a39ede41e6c649d39f09505b88802fbfb5e7739" + } + ], + "leafCount": 37, + "rule": "node = sha256(left_hex + right_hex) over the hex strings; an odd node is promoted unhashed; the leaf is the record hash" + }, + "seal": { + "v": 1, + "agentId": "6acbf860a627414b66045478", + "plate": "ENG-WNP3", + "sealSeq": 1496, + "windowStart": "2026-10-17T15:44:25.565Z", + "windowEnd": "2026-10-17T15:53:48.404Z", + "count": 37, + "issuedCount": 37, + "seqStart": 9818, + "seqEnd": 9854, + "merkleRoot": "2662a87b9401541c4917428bda73596a608ad5ea556acdc110639e2e618092e9", + "deskCondition": "normal", + "prevSealHash": "82904359e52743e49d8c822814094b1519e02214578adef89487469b555c68c5", + "rvnBlock": "00000000000081b33c166cf1961e598cb91d40a6fef817b0d2d8aaf3b6b62753@4585373", + "profileHash": "9bbe0635c0a05cc8107d40ad5bb2d8b227c8125d395f41620bcd371123319701", + "sealHash": "a00007915e398e7a5f6fdd0863a7ebc0f3eac99da656b85a4fad0d06a8c15710", + "rule": "sealHash = sha256(canonical({v, agentId, plate, sealSeq, windowStart, windowEnd, count, issuedCount, seqStart, seqEnd, merkleRoot, deskCondition, prevSealHash[, rvnBlock][, profileHash]}))" + }, + "registrySignature": { + "alg": "ed25519+ml-dsa-65", + "keyId": "5ecb3da505414c4f", + "signature": "v+SHukcW2TmkZbafId5igQnOU75fbb51UNUJFRwp5DdQd1ebk+9Z7wZ9BXfBpmZUWLBgm3ZuNlP+IbVZrKH3Bg==", + "signedAt": "2026-10-17T15:53:48.458Z", + "signatures": [ + { + "alg": "ed25519", + "keyId": "5ecb3da505414c4f", + "signature": "v+SHukcW2TmkZbafId5igQnOU75fbb51UNUJFRwp5DdQd1ebk+9Z7wZ9BXfBpmZUWLBgm3ZuNlP+IbVZrKH3Bg==" + }, + { + "alg": "ml-dsa-65", + "keyId": "8bb85bc1f41c568c", + "signature": "Ku1IkguGrTeVOA0OuzpgAMTW/aO8CFbq/LATFrbdUeWhA5nc+2WlpaMPNVBkEfFvcQN9eCwitvBsvd2eDv4mDSCccM9kGF+ivnB8bNGHqtFXWwekAeZf3N6niHa7miik2kJuuIyCOhLbI8Y3epv+TOC4Oi3rRlDyiQAXl1DuNF8tTb7LGV8CzpxhbRDar/zbI+M8yqJJWPh99VDBzFuHrTNej9zX142zpHMYG6efUgu4JJKsS0g0BsFCBBBPcCuau+qKfd4vr/8x2yZ/RSWddYcGgIeQ5hBDzZH+vqYUIKczdQwsMyuirPIWGUHaqSsa87Gjbu+ab79IZYYVWhEAv85l0sLG6ZsVhYMB+2zgEc9h6MNk8Vu36ek360btN2qOR0tm7KOSLiSQkjgZ7aAzVlGqoDtkvO50PewzyM34dqLo4iF1/JIKHk2EgcXrni+5V+4kM4D3akJkpMBLQ2hA46NPR3kTeiGygdEr6qv1kPTMvoVEjlTeYznVBbc5VinW7fsig8KY9Y9vEaIpu9UL6moULY9QvDnTSQ6R+0lt2IwIltND82nIaZZsCdSGUxVd+xwFsQrAji0St6EioLLRScJCOTXmzFVDxIg4OVOnCAOGbXxcrYnbSDcqCVD52un9Iw80MaxYLj4D/DWUvS5MdU+0FkKe4mxx0TQb54IdTucd+m+1FutSZHL3k3vTELmwj/qJ7vlpsjslBnj6cgqEiVFvDOTVkrcrf3+j7GHYwpejqJgvKifLbD209jTwW1BQuqWXw7vOPt6wIlWN4jPIqJEznEbK5Kn6AIiP9dCfquNGd7D8YVqypvQ8vx9vD5Dbe+HyWisw7UHAq0zSNIXFjTHDCw4hfb42KjHiz1FVEfhacP61nFxH+lcLZsil/RU37wE33RoUDnGucQ7dObmal+ftn4BHhD5gWTFy8N3OQATuWcAb2kMRJ6JUoGio8vLZx7B8XWiV5tEsfQ8OTL9snfj13ny7GyDJ5II3sFN6R/mxjKIBlSe+/S58LO7S7qD9fmasTmUyrpV/CtF8PF0jQQibHEXCNgTv4M4M4y47ZoLSFJYOsBgW/oP3u0jLz7pfez9iJMzFHOTzTkH0tX0ldx0RmwSR0yN8eY3G3eyKRFNLS83qJAQQcEDzR4TCZ+9K7K5TFvI0uV8nh+wTo0gYJxQY4L45N89LHbRI/emCcbG3HfdgyAlb6jp6kajxdc0dMHycPACio11Cepcqsml8ek/nM3JN3jDEGDhxEfEy5hNWFAF1C5t/ku+gmrm6m0WYqt8DN9FSqAYGWIHYoWxj7ilGBhcYccYw5elD85KbO1eSEGdHPblDWq9AxfbI465g4Ftr2umTZPOlT44T3ZeKWU6g4t81S+Nvz1TorGgsWCxitQ1JtnDNB3q8r3BrqHEVrwT1IAZDp/A+3gEJKoAa/h7Fum8XemhfQ+eESLtS+C9bFWSh4IsdPud+xduHwsyqkzLRvJQdm3GBT8ve2l3WH54ykBfvUGvi/rtOUhVbAFw6hqClMq9pA4J/52AyR4JTNVkUICCYWUNyCgKovl8d/Bn5VO1mVIEJso0qZUGKaUDK9FpCWc+FJ/cmQs+/inUa8LVoArnTGyTSyTP0mt6MYO/n8H0RoXzYZ1JsqwIdMeQFtmc5KxYeUUt2mzQN0YiMcIX/Pk6DrdjGMR/cQKeDwOYFZ5yeaJlHGhq/UMRC9lRsA0/xCczLjvq05bMJ/M0Gj8z5OI7+zOXTCEJOibY1jkQf7xYTCZaJ9EzsYwN8LusK+e7mA5tQnXgbsUg4Rf/cUh9DKvMxsOio8BtRxNX/fjkkTFvBIM84nexRTfzTZemcw8sy/43Gb6gutqdbiINIcm6T8VAYJ2/FokVMRcMvwl2cYR7IRf+SbBD6lUNR9aVqFHf/0i8DOA/1Xk260ooeDtVabHqe0HuqMtz34QG4Snd+nnOxapxAU6qfg1RCIaxIuR7EmGoeNsh0CVZWwpNAB3RaedwtFsQ+n9Lfc88Cwf4pYZmmqnnR3F1Kcgdu/UMXXwM2oggFURpLzb4/qpAgzlHf71P7rR8X8FClHOZ8mp29VrswG914tz/Miy04ydvMaQt29KRrU3Y2Ls9AcyxHFyabuFl7HZXFEnZc4jQHgvrGEi9sGitlrfS23Dg338TZL8s78ONE1X6I48djto3eAPGA7kR/N4ZcPLwhZMJIDmik412bjl14X0e4MkQJnLImaK91t0RHm6Qqzav6lhpXTjXmb2qZbj9sVZqy4THKsnlokyLAaeQkEHFddHPzxkeMvXBZcPt+9E3hck2ZMLjNVr3qFa7031A/32oCw8gwK/NOj/Rzxio1H+DPG8NUZCW7IU67TQ56B1z9dwSvxw3DjouBWKLoi5lbmN36u9qy3lja0VvgymkELHbNQeGLk4t9AQkNt/4st3RJKe/Sbzdl84ePHuF0LELe0LjW9r+cHqgWkTrHWK/mrC+cJlVTaqeSm78S3025HU6+7TfZJrz+7BaJ7PCqcA/OUQuBHX5gf0JDiJzd0XBV/ajq1rENxnm5orRYIUNghgRCl3o2/4JHlQfH3rPNLiIQPiGrfkHOQlVclDcZ0Rue2ap9YumeYao00w56CMLstJ8cWuaLXbqi56wOcX8LtwjTuR4gleDG3YX4UCEB2hDA5GYem+Iigs6ecVgj/WF3pD5Kp6RMWB/djBuBYjtl07NZzPf+D3bfCVTHUeEMOu42pH7ANV6zH6Uc+tUkzcGCJWLfoRmn9SaRkX1d4VhKPv8WFXRv7G82sFF4gp6ykqwTHMEPkIDUDTVDOHBa7gPjpJpylWg4VxSko9nQrPW5pDrWA9Hz09nq56yl6pDE2H9aNya3uhAz8lYWfyiRcuFlQWih6VpkRiAOMQiQHeVZqBDZw1tQACod3AZHuFBrlDo2g+9FXem3IBMqjTjYbRi4kqCLBj8bJMwmUxISA8kqOvzjnlwvLQOV/y61N8qAJYbbbdWUV/uiV3HbFyOrX6Hpd6uoFxEMWLsuiGWuIHF2hICVeAxWmwWOQLxiSN+QH6j8q8/4PiSELk2kmPt+bKT5LJBEZ+2CuKyGIAj0L7wG13gxlCY5lB43wcpZmlqSUAOhTUSqdGvaWUfoeOXUA5swoI+hz3WepkbkKz5jfVCj86KsB3b1cglKSLFPNFVR3OivHWQTbKkrdmvCAUSgP8nWkINgIarih89mCKn1F1hRhSrJav3FXtQM43SuIA4ZlPuvayBeh/k9PiXt+OUcQZaguPgpzIRhY4AxKuoj6XIZHb4OkVNrE79mj15oMktaMXx3Setqti08TwADk4LeRygSzGqR9Wph416GuidMMRL6w7f5iymaw59YPBwEXHDMeUg6EEJRLrFA1gW+IituOqb+zMI+d6pmxydTJ6bynDTHq3CY1R87ndtHQiCHLax590SEaX2nvU5qao5ZqTFmx/nEUlF3P3kKeFu2oBLE1YHHuOq3lP9iwsYtXJCwFtzz1UMX41VBgBonN/EYMgw4+Mw0Ch0mXwWqgykOBYLBox51S6JPwnu0qOIQw2Fgvad6ASfZ2F1YcLNfYmoMB4JKBRkfw7KIs2Gbvt4lvLXqTb5O2rjDaYENfPMm+oI4puoZHZOcWLCROlasVRnDVWGei/dAxvu6gI4iB7TLl3P7C7UknJNwV50Nqm/K6TEtpUw9vmEOTTZlrj7ee920T9s41aWfagWMdBvtSQ+blQYU35Tnk6vU9n8Mfs/YiHgy62JK89X8St/20LmSTES70DFe3uBwEvMmAgVxqY+zsTJeX7gQPRzKyis62BuhktuEbVrRVF8CVEsPMfEq5XCAgYBIPMAKA+vn9CySiEmT6D08RAFL0o5DxzXxK7VXocgMI6rkqB2XETus+5896Hikai0mTWRmxRd4NG9aqGwaxJj2SLGhk6t+iU3K699fjHmU9msh4nDGyZdlvCU/V06XpAKlZ/TeSpPI5Gn9QfJJYPjuUTGGinBh/9MIObrhGq/AL2A0RRsPWozY+KPGMp4EZAmMsvMf85X2pUmlBVsVIap1BW+L+GB1mJx3fTiOG1wGnGBhOYmdq3UaKuqsDirUPKNvU03E9bPeSH0ZPD6u7+/Fj0ro3B5W8ez/A+nukQcWx5ONyuv2zLCiX3or0UZNmJO09BFYo5agu1z+BQYOvku9iJTZC2cksrzuoAd06hx29cGoeUvivL6mK2X0hu8FyOOe9pJb0FPmYIlnpn90L49by0SXujg4Fv6q7l4f2aYqXQe3z4/vrfByDvs9it2rjwQ1asX/ZDBPmK4WmFDZ4JtLywHuTR7GgcVBsB4YilA0Kc5WNMxm7b33Pm8/qzkYW3uTpN7rQJSmsrXNL159l/YPeX6HvMjWMVNwcb2/wuj4/wQOncbr9v4AAAAAAAAAAAAAAAAABw0SGSMq" + } + ], + "signedOver": "the UTF-8 bytes of seal.sealHash", + "publicKeyRaw": "mn02E1XyTkaVN6DEOemU5OADMUAUjPHw67oR5KKIM3k=", + "publicKeyPem": "-----BEGIN PUBLIC KEY-----\nMCowBQYDK2VwAyEAmn02E1XyTkaVN6DEOemU5OADMUAUjPHw67oR5KKIM3k=\n-----END PUBLIC KEY-----\n", + "wellKnown": "https://in.xchk.io/.well-known/xchk-keys.json", + "keys": [ + { + "alg": "ed25519", + "keyId": "5ecb3da505414c4f", + "publicKeyRaw": "mn02E1XyTkaVN6DEOemU5OADMUAUjPHw67oR5KKIM3k=" + }, + { + "alg": "ml-dsa-65", + "keyId": "8bb85bc1f41c568c", + "publicKeyRaw": "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" + } + ], + "retired": [], + "publicKeyRawPq": "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", + "keyIdPq": "8bb85bc1f41c568c", + "root": { + "alg": "slh-dsa-sha2-128s", + "standard": "FIPS 205", + "keyId": "acc7ad1aeb3ef177", + "publicKeyRaw": "4aIhDuj3TZPwqb9HT8TzVJnkvle4jVUMhWkn/BfmypM=", + "statement": { + "v": 1, + "registry": "https://in.xchk.io", + "keys": [ + { + "alg": "ed25519", + "keyId": "5ecb3da505414c4f", + "publicKeyRaw": "mn02E1XyTkaVN6DEOemU5OADMUAUjPHw67oR5KKIM3k=" + }, + { + "alg": "ml-dsa-65", + "keyId": "8bb85bc1f41c568c", + "publicKeyRaw": "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" + } + ], + "retired": [], + "oidc": [ + { + "kid": "XWUv0uGESGdIG1MjOzbVjcwxB0CYtK0oZ9SZxNkH7h8", + "kty": "RSA", + "alg": "RS256", + "n": "zQwdJyTuyqQvB5zIXp9ULjX22k-R95Ls5j3IVUwLcI87I2VPUjsvy9oDGl5cq8Jl7Rt21d966AakANr8J1vT7gMpcmPOcEGVDdgdCprRs8cWNDo5uJ4ejt1LW65zRqW8xsxqHPm1aOxvjeUQfNgZFLn3VlSX01zgjggBLSwL18stLbyIzA2zcj4lpV-IrnBO3S6VUusoaO__kXjHv1-aH64wpVcsNLrBX6MWsnHM-KptbhKrk_qqXMJ7dokBxiIAH32VjZ73kTbVcSXoU2FshM_eQaonhYcRoD8PTXN3rxMaisj2pka9XZ1Apqy-EHf1dCoUphYxd_--FcT5PDQZaQ", + "e": "AQAB" + } + ], + "issuedAt": "2026-10-17T15:48:57.541Z" + }, + "signature": "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", + "rule": "SLH-DSA-SHA2-128s verify(publicKeyRaw, canonical(statement) bytes, signature); statement.keys are the keys this registry signs with" + }, + "rule": "HYBRID: for each entry in signatures, verify(keys[alg,keyId].publicKeyRaw, sealHash bytes, signature) — Ed25519 for alg ed25519, ML-DSA-65 (FIPS 204) for alg ml-dsa-65; ALL must verify. keyId = sha256(SPKI or raw key)[:16]. root, when present, is the SLH-DSA-SHA2-128s statement of these keys." + }, + "approver": { + "email": "sean@maclawran.ca", + "authLevel": "didit", + "authMethod": "webauthn", + "attestationId": "6ad398295f7026f62ae7b863", + "credentialId": "Yqa88hkURHnPqSTiV3o1jA", + "publicKey": { + "format": "ec-p256-uncompressed", + "alg": "ES256", + "raw": "BCZqv4O2q7lpplcEIo8P3acudWVPjPAhFJ6CyQm910rIfpMkbkCIQsv435UOPILzMOfnW9mBu4c7F4JzUBnBrS0=" + }, + "assertion": { + "clientDataJSON": "eyJ0eXBlIjoid2ViYXV0aG4uZ2V0IiwiY2hhbGxlbmdlIjoiNUVMY0t2aUhybWxuUElaME9Ca0hMZE9tM05aalVKdEN5U3d5QUItcElNYyIsIm9yaWdpbiI6Imh0dHBzOi8vaW4ueGNoay5pbyIsImNyb3NzT3JpZ2luIjpmYWxzZX0", + "authenticatorData": "dcRETaEWF68z8NRCzR6PN99N5Mn8aYw-RadnYwZSFr0dAAAAAA", + "signature": "MEUCICT3xUYI7EsskkcUqIDe6idfryqpxzf03mEOE9sdISFCAiEAhxH_umnYg-eauARdoAUtoWghvhuSvNjK5fnIeax_0B4", + "encoding": "base64url" + }, + "challenge": { + "rule": "ask-v1", + "fields": { + "v": 1, + "attestationId": "6ad398295f7026f62ae7b863", + "prompt": "ENG-WNP3.3057 (via Claude Code) wants to P=\".ab1-probe-approve1-$(date +%s)\"; rm -f \"$P\" && echo \"probe 1 ran (nothing existed to remove)\"", + "actionParamsHash": "5eee3b37a63eb957436a2bd51633d8a3c9a54f96c66e71f45fbd2d458373ca68" + }, + "expected": "5ELcKviHrmlnPIZ0OBkHLdOm3NZjUJtCySwyAB-pIMc", + "note": "the challenge the approver's device signed = base64url(sha256(canonical(fields))); fields are the ask as issued, before any answer; recompute, do not trust `expected`" + }, + "binding": { + "fields": { + "v": 1, + "recordHash": "aa2bfd5b1d9b6307ed22eb0daa4213383beecb57d7d31ec011060ac98f7fe0b5", + "attestationId": "6ad398295f7026f62ae7b863", + "credentialId": "Yqa88hkURHnPqSTiV3o1jA", + "publicKey": "BIWcVSzcT4ocdVb/bHtVrZNK/4RKRn1xhg6SE8TSy3QGpnJUufsDz2z+G1PqK3yP/7q5IPI9PEfjC77W/OxqD5k=", + "approverEmail": "sean@maclawran.ca", + "authLevel": "didit", + "authMethod": "webauthn", + "verifiedAt": "2026-10-17T15:46:00.404Z" + }, + "signature": "LpDId3mnpJVZn4ntyVIwrgy/sT1vdKmomgr8eoShKHRJhvh7xr7qvVD3ZhKaaYxa5rcL/E0JQX8ICh+Y/1vSDA==", + "keyId": "5ecb3da505414c4f", + "signedAt": "2026-10-17T15:54:51.971Z", + "alg": "ed25519+ml-dsa-65", + "signatures": [ + { + "alg": "ed25519", + "keyId": "5ecb3da505414c4f", + "signature": "LpDId3mnpJVZn4ntyVIwrgy/sT1vdKmomgr8eoShKHRJhvh7xr7qvVD3ZhKaaYxa5rcL/E0JQX8ICh+Y/1vSDA==" + }, + { + "alg": "ml-dsa-65", + "keyId": "8bb85bc1f41c568c", + "signature": "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" + } + ], + "rule": "registry signature(s) over canonical(fields): each of `signatures` with the registrySignature.keys entry of the same alg/keyId (hybrid: all must verify); `signature` is the Ed25519 half" + }, + "rules": [ + "assertion: WebAuthn signature = ECDSA-P256/SHA-256 over authenticatorData || sha256(clientDataJSON), verified with publicKey.raw (uncompressed point); clientDataJSON.type must be \"webauthn.get\"; authenticatorData flags must include UV (user verified)", + "binding: verify each of binding.signatures (or binding.signature with alg ed25519) over canonical(binding.fields) with the matching registrySignature.keys entry — Ed25519 and, when present, ML-DSA-65; all must verify; binding.fields.recordHash must equal recordHash, binding.fields.credentialId must equal the assertion credential, and binding.fields.publicKey must equal approver.publicKey.raw (17 Oct 2026: an assertion re-signed by another key, with that key offered, passes every other check)", + "challenge: when approver.challenge is present (rule ask-v1, ceremonies from 18 Oct 2026), clientDataJSON.challenge must equal base64url(sha256(canonical(challenge.fields))) with fields.attestationId = approver.attestationId, fields.prompt = decision.prompt and fields.actionParamsHash = decision.actionParamsHash: the device signed over the ask, so the assertion itself names the act it answered. Absent, the challenge was a nonce and only the binding pairs the assertion with the record (an assertion by the same credential over another ask passes every other check)" + ] + }, + "basis": { + "asked": { + "seq": 9818, + "ts": "2026-10-17T15:45:45.315Z", + "area": "global", + "tool": "terminal", + "summary": "P=\".ab1-probe-approve1-$(date +%s)\"; rm -f \"$P\" && echo \"probe 1 ran (nothing existed to remove)\"", + "paramsHash": "a791bccfa14f0666b7082aab7586455f1898da48651cbbbb643e0df3402655c6", + "code": "hook_escalation", + "reason": "destructive filesystem command outside scratch roots", + "recordHash": "25607c8e2e529dddce618b49b1c11da6b302a6687c6d44b335f304e904dc796f", + "model": "claude-fable-5-1" + }, + "grant": { + "area": "global", + "disposition": "allow", + "policyId": null, + "maxAmount": null, + "resources": [] + }, + "authorizeDisposition": "attest", + "area": "global", + "objective": null, + "rule": "asked = the attest record this ceremony answers (same plate, same action summary, raised just before the ceremony; cite it by recordHash); grant = the plate's grant rows as they stood when the ceremony was raised; asked.reason is the registry's stated reason for asking" + }, + "decision": { + "prompt": "ENG-WNP3.3057 (via Claude Code) wants to P=\".ab1-probe-approve1-$(date +%s)\"; rm -f \"$P\" && echo \"probe 1 ran (nothing existed to remove)\"", + "response": "approved", + "status": "completed", + "createdAt": "2026-10-17T15:45:45.553Z", + "respondedAt": "2026-10-17T15:46:00.404Z", + "by": "sean@maclawran.ca", + "authMethod": "webauthn", + "requiredAuthMethod": null, + "amendment": null, + "actionParamsHash": "5eee3b37a63eb957436a2bd51633d8a3c9a54f96c66e71f45fbd2d458373ca68", + "attestationHash": "d7896ca4608bcdd8581ce6c0bb5917e541d40d635334e1a8746d7fc1bc230d5e", + "attestationHashRule": "sha256 over the registry's canonical attestation JSON (utils/attestationHashUtils.computeAttestationHash: id, prompt, response, status, respondedAt, approver, method, amendment, delivery, chain …); recomputable on the registry, cited here so the record and this decision are bound" + }, + "legalHolds": null, + "anchor": { + "rvnTxId": null, + "rvnAnchoredAt": null, + "rvnBlock": "00000000000081b33c166cf1961e598cb91d40a6fef817b0d2d8aaf3b6b62753@4585373", + "explorer": null, + "otsProof": "8AgHtW3WwcdWHAjwIDmHgtDWxTNE7J5/xgGaHDFnrQrc3inlHM3qhjw4tw0GCPAQXdqsoXnzk3MwpP23KriFggjxIPLwuvDSO69qmiS9474S+Avisk6Nj3GHF2cAlCMhKZEgCPAgcg99+b7AHf2ZK3gpBTOQs3DbDNA7V9MlZXNzGCHcjq4I8CBgv3qhup4MMtQ5Z6CeKEgdkDbyf3ckONgeLlOyncp01gjxBGrTmg3wCL37YWeTW8icAIPf4w0u+QyOLi1odHRwczovL2FsaWNlLmJ0Yy5jYWxlbmRhci5vcGVudGltZXN0YW1wcy5vcmc=", + "otsCalendar": "https://a.pool.opentimestamps.org", + "otsBlockHeight": null, + "rule": "the anchor transaction carries sealHash in OP_RETURN; its raw bytes are captured once the transaction confirms (a few minutes) — download the bundle again for the offline anchor check, or use the explorer link" + }, + "howToVerify": [ + "1. canonicalize `record` per `canonicalization.profile`, sha256 it, compare to `recordHash`", + "2. walk `merkle.proof` from `recordHash` (L: sha256(step+cur), R: sha256(cur+step)); the result must equal `seal.merkleRoot`", + "3. canonicalize the seal fields per `seal.rule`, sha256 it, compare to `seal.sealHash`", + "4. verify every entry of `registrySignature.signatures` over the seal hash with the key of the same alg/keyId in `registrySignature.keys` (Ed25519 + ML-DSA-65 when hybrid); older bundles: Ed25519-verify `signature` with `publicKeyRaw`", + "5. if `approver` is present: verify the WebAuthn assertion with `approver.publicKey.raw`, then Ed25519-verify `approver.binding.signature` over canonical(`approver.binding.fields`) with the registry key, and require `approver.binding.fields.publicKey` to equal `approver.publicKey.raw`: the binding, not the bundle, names the key the assertion may be checked with; when `approver.challenge` is present, recompute base64url(sha256(canonical(`challenge.fields`))) and require it to equal `clientDataJSON.challenge`, with the fields equal to `approver.attestationId`, `decision.prompt` and `decision.actionParamsHash`", + "6. if `anchor.proof` is present: check the OP_RETURN, the txid, the header hash and the merkleblock; else look up `anchor.rvnTxId` on any Ravencoin explorer", + "8. if `seal.profileHash` is present: `profile.document` must be present, sha256(canonical(document)) must equal it, and `profile.signature` must verify over the hash with the registry keys; absent profileHash = sealed before profiles", + "7. if `basis`/`decision` are present: `basis.asked.recordHash` is another record on the same chain (fetch its bundle and run steps 1–4); `decision.attestationHash` equals `record.attestationHash`; `decision.amendment.command`, when present, is what ran" + ], + "profile": { + "profileHash": "9bbe0635c0a05cc8107d40ad5bb2d8b227c8125d395f41620bcd371123319701", + "document": { + "v": 1, + "name": "org", + "registry": "in.xchk.io", + "dials": { + "identity": [ + "email", + "domain" + ], + "registration": "person", + "anchoring": [ + "rvn", + "ots" + ], + "signing": "ed25519+ml-dsa-65", + "actSummary": { + "kept": "registry", + "maxChars": 400 + }, + "inbound": "on", + "operatorAccess": "recorded", + "actRecords": "kept", + "publicRecord": "plate", + "principalDomains": [ + "maclawran.ca" + ] + } + }, + "signature": { + "alg": "ed25519+ml-dsa-65", + "keyId": "5ecb3da505414c4f", + "signature": "3wM2ISHYyVQSahc6iEv70t47+skkAxg7sS7Nu6p82ZVT/WgN6iUdc+A+padJl1DJRcTJQErs3ppXsM8ZTQlEAQ==", + "signedAt": "2026-10-17T15:48:48.412Z", + "signatures": [ + { + "alg": "ed25519", + "keyId": "5ecb3da505414c4f", + "signature": "3wM2ISHYyVQSahc6iEv70t47+skkAxg7sS7Nu6p82ZVT/WgN6iUdc+A+padJl1DJRcTJQErs3ppXsM8ZTQlEAQ==" + }, + { + "alg": "ml-dsa-65", + "keyId": "8bb85bc1f41c568c", + "signature": "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" + } + ] + }, + "rule": "sha256(canonical(document)) = seal.profileHash; verify signature over the UTF-8 bytes of profileHash with the same registrySignature.keys as the seal; document.dials are the rules this node ran under when it sealed the window" + }, + "verifier": { + "html": "https://in.xchk.io/verify-receipt.html", + "python": "https://in.xchk.io/verify/verify_receipt.py", + "license": "MIT" + } +} diff --git a/integrations/xchk-registry/examples/approval-outcome/06-assertion-from-another-credential.json b/integrations/xchk-registry/examples/approval-outcome/06-assertion-from-another-credential.json new file mode 100644 index 00000000..ca850981 --- /dev/null +++ b/integrations/xchk-registry/examples/approval-outcome/06-assertion-from-another-credential.json @@ -0,0 +1,47 @@ +{ + "eat_profile": "tag:agentrust-io.com,2026:trace-v0.2", + "iat": 1792252491, + "subject": "did:web:in.xchk.io:plate:ENG-WNP3", + "model": { + "provider": "anthropic", + "model_id": "claude-fable-5-1" + }, + "runtime": { + "platform": "software-only", + "measurement": "sha256:c60a771a8f6e4fda60fbb2b745397c800c38da090f153f72e302147a1851746a" + }, + "policy": { + "bundle_hash": "sha256:8e1e29b1e2b1470b57fba453991d3c9ef0d0ae19ba59927c014525177ee741ae", + "enforcement_mode": "enforce" + }, + "data_class": "internal", + "tool_transcript": { + "hash": "sha256:54ea01281f1acf13dec96c509cb243c5ee87b826524044ac8c2700a63cd9f2bb", + "call_count": 101 + }, + "references": [ + { + "rel": "approval-outcome", + "id": "aa2bfd5b1d9b6307ed22eb0daa4213383beecb57d7d31ec011060ac98f7fe0b5", + "resolver": "https://in.xchk.io", + "digest": "sha256:aa2bfd5b1d9b6307ed22eb0daa4213383beecb57d7d31ec011060ac98f7fe0b5" + } + ], + "build_provenance": { + "slsa_level": 0, + "digest": "sha256:c60a771a8f6e4fda60fbb2b745397c800c38da090f153f72e302147a1851746a" + }, + "appraisal": { + "status": "none", + "verifier": "https://in.xchk.io" + }, + "cnf": { + "jwk": { + "kty": "OKP", + "crv": "Ed25519", + "x": "mn02E1XyTkaVN6DEOemU5OADMUAUjPHw67oR5KKIM3k", + "kid": "5ecb3da505414c4f" + } + }, + "signature": "Vjgt2d7DVF_KmYdb3UXuOaL4YxRO1k46Uj91QkI5vc0EC5NraQ7U7S58DuD35d8GMy70wW-I08OtkRiCKTfPAQ" +} diff --git a/integrations/xchk-registry/examples/approval-outcome/07-amended.bundle.json b/integrations/xchk-registry/examples/approval-outcome/07-amended.bundle.json new file mode 100644 index 00000000..50430c40 --- /dev/null +++ b/integrations/xchk-registry/examples/approval-outcome/07-amended.bundle.json @@ -0,0 +1,374 @@ +{ + "format": "xchk-receipt-bundle/2", + "issuer": { + "name": "xChk registry", + "base": "https://in.xchk.io", + "servedAt": "2026-10-17T15:54:52.045Z", + "headline": "ENG-WNP3: APPROVED terminal in global at 2026-10-17T15:47:43.996Z — approved by sean@maclawran.ca." + }, + "recordHash": "236de6c9aa5f147034e5aaebb6f235c1d90c999a5fe469cd5c07ed9b7405d10f", + "record": { + "v": 1, + "agentId": "6acbf860a627414b66045478", + "plate": "ENG-WNP3", + "seq": 9831, + "ts": "2026-10-17T15:47:43.996Z", + "harness": "claude", + "runSeq": 3057, + "runRef": "ENG WNP3.3057", + "area": "global", + "tool": "terminal", + "summary": "P=\".ab1-probe-amend-$(date +%s)\"; rm -f \"$P\" && echo \"probe 4 ran as proposed\"", + "paramsHash": "9c5776ec712db8b2c988f54e5846ccc673e7d7d4c8a2837539b30660b443284f", + "amount": null, + "disposition": "approved", + "code": null, + "reason": null, + "deskCondition": "normal", + "continuityClass": "standard", + "authRef": "9ce83dcdaa0f47171dd10aa7", + "prevHash": "1a98f5c74ea6e30b12055596e62b41a93723e1d804b528e6f12aa86ad7e4f82e", + "rvnBlock": "00000000000429cd3e982adaae95411ba7139c5d7e2631701f4738af6a4e7f9d@4585365", + "approverEmail": "sean@maclawran.ca", + "authMethod": "webauthn", + "attestationId": "6ad3987b5f7026f62ae7bcdf", + "attestationHash": "0f18cebd74639f960eb3d04f7781c80677c5adc0750333c0aa100ae8775819bb", + "photoUrl": "https://xchk-main.s3.us-east-005.backblazeb2.com/xchk/xchk/baseline/att_6ad3987b5f7026f62ae7bcdf/0.jpg", + "model": "claude-fable-5-1" + }, + "canonicalization": { + "profile": "JSON with object keys sorted (code-unit order), no whitespace, scalars as JSON.stringify would emit them, undefined omitted, integers only; hash = sha256 over the UTF-8 bytes", + "hashedConditionalKeys": [ + "rvnBlock", + "approverEmail", + "authMethod", + "requiredAuthMethod", + "attestationId", + "attestationHash", + "photoUrl", + "labelsHash", + "delegationHash", + "model", + "tokensIn", + "tokensOut", + "tokensCacheRead", + "contextPct", + "actor", + "chargeCode", + "workspace", + "policyHash", + "outcomeOf", + "resultHash", + "endedAt", + "artifactHash" + ], + "note": "conditional keys are present only when the record carried them; absent keys are absent from the bytes, not null" + }, + "merkle": { + "proof": [ + { + "side": "L", + "hash": "1a98f5c74ea6e30b12055596e62b41a93723e1d804b528e6f12aa86ad7e4f82e" + }, + { + "side": "R", + "hash": "040298e963f0ee9b89576db41892c8b4d9f15f9d09ac459e315e029e775e2dfe" + }, + { + "side": "L", + "hash": "bf783b1d326ccee4a2722f740ccf07a4e21e1e813a8ab4a49c7ac4481e587c49" + }, + { + "side": "L", + "hash": "212253386d1769fdee55ca4d09c77642da7fcea34d7dccccad308e7175a26f32" + }, + { + "side": "R", + "hash": "b1f52c8bef88f4187114b4cfab6922468a0e2f3775dc9b6fa7d1479458d02019" + }, + { + "side": "R", + "hash": "b8de3bc958dcdcd07dfc74b47a39ede41e6c649d39f09505b88802fbfb5e7739" + } + ], + "leafCount": 37, + "rule": "node = sha256(left_hex + right_hex) over the hex strings; an odd node is promoted unhashed; the leaf is the record hash" + }, + "seal": { + "v": 1, + "agentId": "6acbf860a627414b66045478", + "plate": "ENG-WNP3", + "sealSeq": 1496, + "windowStart": "2026-10-17T15:44:25.565Z", + "windowEnd": "2026-10-17T15:53:48.404Z", + "count": 37, + "issuedCount": 37, + "seqStart": 9818, + "seqEnd": 9854, + "merkleRoot": "2662a87b9401541c4917428bda73596a608ad5ea556acdc110639e2e618092e9", + "deskCondition": "normal", + "prevSealHash": "82904359e52743e49d8c822814094b1519e02214578adef89487469b555c68c5", + "rvnBlock": "00000000000081b33c166cf1961e598cb91d40a6fef817b0d2d8aaf3b6b62753@4585373", + "profileHash": "9bbe0635c0a05cc8107d40ad5bb2d8b227c8125d395f41620bcd371123319701", + "sealHash": "a00007915e398e7a5f6fdd0863a7ebc0f3eac99da656b85a4fad0d06a8c15710", + "rule": "sealHash = sha256(canonical({v, agentId, plate, sealSeq, windowStart, windowEnd, count, issuedCount, seqStart, seqEnd, merkleRoot, deskCondition, prevSealHash[, rvnBlock][, profileHash]}))" + }, + "registrySignature": { + "alg": "ed25519+ml-dsa-65", + "keyId": "5ecb3da505414c4f", + "signature": "v+SHukcW2TmkZbafId5igQnOU75fbb51UNUJFRwp5DdQd1ebk+9Z7wZ9BXfBpmZUWLBgm3ZuNlP+IbVZrKH3Bg==", + "signedAt": "2026-10-17T15:53:48.458Z", + "signatures": [ + { + "alg": "ed25519", + "keyId": "5ecb3da505414c4f", + "signature": "v+SHukcW2TmkZbafId5igQnOU75fbb51UNUJFRwp5DdQd1ebk+9Z7wZ9BXfBpmZUWLBgm3ZuNlP+IbVZrKH3Bg==" + }, + { + "alg": "ml-dsa-65", + "keyId": "8bb85bc1f41c568c", + "signature": "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" + } + ], + "signedOver": "the UTF-8 bytes of seal.sealHash", + "publicKeyRaw": "mn02E1XyTkaVN6DEOemU5OADMUAUjPHw67oR5KKIM3k=", + "publicKeyPem": "-----BEGIN PUBLIC KEY-----\nMCowBQYDK2VwAyEAmn02E1XyTkaVN6DEOemU5OADMUAUjPHw67oR5KKIM3k=\n-----END PUBLIC KEY-----\n", + "wellKnown": "https://in.xchk.io/.well-known/xchk-keys.json", + "keys": [ + { + "alg": "ed25519", + "keyId": "5ecb3da505414c4f", + "publicKeyRaw": "mn02E1XyTkaVN6DEOemU5OADMUAUjPHw67oR5KKIM3k=" + }, + { + "alg": "ml-dsa-65", + "keyId": "8bb85bc1f41c568c", + "publicKeyRaw": "e7eet5v+xU8RgatEwvNj1cMMdHutsiouMGJ1Q32cMarb3CsMTIAY3JSVXWhmPqk+5q7aAwyI0nvSyGpPuK/C7uq5dv1ARQ/qaHRzwRnVN75jHTdyiL7qwHXWhYkqFL9rpHuo3hViiWhk20EWprNbHKLE8k9BKP+FBrqaFlvJ7NLIVbg/GmHuD09NGpT1H9MGTRjwlrw1FXZvMS9ZLhUdY3zjGec1KsPRiteJuosdgiWeYkWxPkzsmVgyRQDVj2Wi7zZjqOrYWuhi2b3DVb9hZ7zeuzxX7CY7Lm1Qmy//Ix4v0+DaTbcjNB+s+U2ChXUbu2Z1mqqgklZle5YY35MXbZ0UyRvVIN9Rd7AAYavNrPNS9idb25oqifkQWn5d1Q9+ztlLecAf1dD8oHhV6C03zOj+smmGpWkys11DqODLXX+0/Kp4ESFvN4qMzhlmRO6I2ECyIb/n+0AvMxK97afyP0m/PdaAE94Rn4+0oAN+xQwKv8CXnYI9xTAOmOtkGcMUK6dUt+Um+RHyz7gF4MZ381SfBDk0q1/s8ZLjZfq+LJdKUkgX1D+frAHvw97zmwA4gTbTE4+GHxlTlr3+PAbDgfeSPCGWljW74miMNW/+S07jpnUW4Amd5yOR1QNThtA8qHmvJd19F03kndxsLGpH1PwdUAsNcrSkvOl2p9X4dv57nOzXxFJtIP/JX72AB+neT0+ORSbtx5GdmaqaLvOpzeYFOAbzGbjqGw9EGJ/eAOR//CZiX0T2/qPQjntadvlJHM2DQYD8CwYNX4EDOZ/sczVtOQ6h205CzLo6jWAs3P6YkaEd0XLNSnj/dyQDYN0sfJn3FJWgEh0DsPfbXynGfb6I2SVdp+ht7dWPEzoEpmC3RUjw3Bi2P7k9gxDkZ62+qjY5Sb23PRuu3cO4BPD7XYj5a2B8C3Hv7kjkruiYUofJKf19H3iYQFUmtBzzdX8fx1/0NO+jchIUGApOhIjLe9/6Go66a5bjTnqNvyXNuJycOWyQTBDaumAqQilY9Yq8vW4k3HupWnzbYTEz18rBorb+0hbCzPGivpOuMgTxE6LdRUVN77FmddyQP2gN0iaIlNzXtJc8sfjT7th8JznIq5jjVhBK2cgVxB7ySGnNUXsbRJ+p+uiOTMf7O6o/T/6eb+79+XCxPunIiwW5JOQvE6GPS63bvuiYchsae2dgcsdaYUXsoe0FEAMqM+G+LsPaoYJildycC27UflXMMpbLUB0N3j1F5RTYGQLsORpzi/oEB9ptYK25hBICYryB4xteIhQcVWu32Ntt47M/2fN0lumWAFfoP593UtKNGcUM7G9zhSJfn6m+0R+sMixGvYw0NesnWp9fKnLAAIUrPvW7mnvYfSlUeVS076hzVR5JOEsZbrkRQg5/9njU0GaB22kYCEo5u0B6WiePz9OTWfTxz7xu6PaRTqOG2B0qLn81J12UTegOYPAZUlAj42i/llqpOfEWrlreIaT8kWLtxoafpaXl7kfX8a0ydzzD8dQ7JuswDMqRRbNnCcNIMyvU71v9LJW+rlAvrAVVQP7vhflJA7mPVNt6+bXRv1aMVfRVFM4kALWzYK2/6qoaDmC7OLHQuNqT44CFbj/6Z2gNcQO72tfLB005GvdbqiT8PJylpZ+TOFH7eqQFmmgIeQbeSVQZnqlq0KMtElArNRK8a4J+Zdh+yKNJ85xcFrcaFKlRPQdpetlvZYdRtFPf7iFMr3ubqYM7aNtvHrbXuaeMmZT9w35RJRtBSxQH43eNpf3zXh/VzkaKTSw7T9Un4FnTNG59O7rVYzxf0RKVI0wzwO9nRHGNa/sDjyCBu/vL7ElJ7FwbQudGLJQL07iBFJESKzfNm8heFO2lME8O05EBmsbLo3VMsTXyhi4M75cSGc5GaEt6FXuPh+ycboROYzNEpzffT2DYS3yZK+KF5hS0/lMm3NEyp4lYpk1cLydljNm/XONhGaSnEEBZLNicFKT4wWKZbRLzU1r87UQm//lWNRDxK3sFaegcjScGCewbXghEjsHRlQlIqnqAIFUTyvHiQVJqk+qnGDGRnGn47hmvZ3/RUvx6gMX/PYul5aDYcBihXh88SzwV88rB1tIRscPte4XroBNoqB2Q97OCpSm1aQ1R52ESz+bWdELdpDZpn/q+wx+vXp2NswIHncmz5VtfA9dHIAgcM7n7tUl/U6BVjmAW7X93Eh/YYxXzAU4/ZCxLYcluDhrg73H+le1BpIZ7j/MrV+fbHsQEtiUZzg/RjrwSaabCXakfKMlxDZ6ODwBE0OkuiNlkztrQCqR6c1/Pvg7fMUP0vxlsIyd47aBCgdC/OFUmAVBC1nq7HOxJ5wlkKeIQTL/q8QWwyhrDTsK/7CHjJ9awUhO8uCbrx7X8Yc77q6QJg7KEHm6gTQSEhq8cvnmtn40iQv8mzTDg7HqFOuPNLFLsjdDF7KByOIYsPGw1A8JJ+ATpcHo0sHjjA8/ye5uayNhtGpaGdsOG7HxhB1e98uSvr1fUCmzs4orc/HJuDbWCaVMjP5TdOTVmcKoylzEY9adZpFibKJV89j5iX46fxS4uURxIaLiYENo/2IS4+StY0sBbFTMRfy/9jWw3oQQ=" + } + ], + "retired": [], + "publicKeyRawPq": "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", + "keyIdPq": "8bb85bc1f41c568c", + "root": { + "alg": "slh-dsa-sha2-128s", + "standard": "FIPS 205", + "keyId": "acc7ad1aeb3ef177", + "publicKeyRaw": "4aIhDuj3TZPwqb9HT8TzVJnkvle4jVUMhWkn/BfmypM=", + "statement": { + "v": 1, + "registry": "https://in.xchk.io", + "keys": [ + { + "alg": "ed25519", + "keyId": "5ecb3da505414c4f", + "publicKeyRaw": "mn02E1XyTkaVN6DEOemU5OADMUAUjPHw67oR5KKIM3k=" + }, + { + "alg": "ml-dsa-65", + "keyId": "8bb85bc1f41c568c", + "publicKeyRaw": "e7eet5v+xU8RgatEwvNj1cMMdHutsiouMGJ1Q32cMarb3CsMTIAY3JSVXWhmPqk+5q7aAwyI0nvSyGpPuK/C7uq5dv1ARQ/qaHRzwRnVN75jHTdyiL7qwHXWhYkqFL9rpHuo3hViiWhk20EWprNbHKLE8k9BKP+FBrqaFlvJ7NLIVbg/GmHuD09NGpT1H9MGTRjwlrw1FXZvMS9ZLhUdY3zjGec1KsPRiteJuosdgiWeYkWxPkzsmVgyRQDVj2Wi7zZjqOrYWuhi2b3DVb9hZ7zeuzxX7CY7Lm1Qmy//Ix4v0+DaTbcjNB+s+U2ChXUbu2Z1mqqgklZle5YY35MXbZ0UyRvVIN9Rd7AAYavNrPNS9idb25oqifkQWn5d1Q9+ztlLecAf1dD8oHhV6C03zOj+smmGpWkys11DqODLXX+0/Kp4ESFvN4qMzhlmRO6I2ECyIb/n+0AvMxK97afyP0m/PdaAE94Rn4+0oAN+xQwKv8CXnYI9xTAOmOtkGcMUK6dUt+Um+RHyz7gF4MZ381SfBDk0q1/s8ZLjZfq+LJdKUkgX1D+frAHvw97zmwA4gTbTE4+GHxlTlr3+PAbDgfeSPCGWljW74miMNW/+S07jpnUW4Amd5yOR1QNThtA8qHmvJd19F03kndxsLGpH1PwdUAsNcrSkvOl2p9X4dv57nOzXxFJtIP/JX72AB+neT0+ORSbtx5GdmaqaLvOpzeYFOAbzGbjqGw9EGJ/eAOR//CZiX0T2/qPQjntadvlJHM2DQYD8CwYNX4EDOZ/sczVtOQ6h205CzLo6jWAs3P6YkaEd0XLNSnj/dyQDYN0sfJn3FJWgEh0DsPfbXynGfb6I2SVdp+ht7dWPEzoEpmC3RUjw3Bi2P7k9gxDkZ62+qjY5Sb23PRuu3cO4BPD7XYj5a2B8C3Hv7kjkruiYUofJKf19H3iYQFUmtBzzdX8fx1/0NO+jchIUGApOhIjLe9/6Go66a5bjTnqNvyXNuJycOWyQTBDaumAqQilY9Yq8vW4k3HupWnzbYTEz18rBorb+0hbCzPGivpOuMgTxE6LdRUVN77FmddyQP2gN0iaIlNzXtJc8sfjT7th8JznIq5jjVhBK2cgVxB7ySGnNUXsbRJ+p+uiOTMf7O6o/T/6eb+79+XCxPunIiwW5JOQvE6GPS63bvuiYchsae2dgcsdaYUXsoe0FEAMqM+G+LsPaoYJildycC27UflXMMpbLUB0N3j1F5RTYGQLsORpzi/oEB9ptYK25hBICYryB4xteIhQcVWu32Ntt47M/2fN0lumWAFfoP593UtKNGcUM7G9zhSJfn6m+0R+sMixGvYw0NesnWp9fKnLAAIUrPvW7mnvYfSlUeVS076hzVR5JOEsZbrkRQg5/9njU0GaB22kYCEo5u0B6WiePz9OTWfTxz7xu6PaRTqOG2B0qLn81J12UTegOYPAZUlAj42i/llqpOfEWrlreIaT8kWLtxoafpaXl7kfX8a0ydzzD8dQ7JuswDMqRRbNnCcNIMyvU71v9LJW+rlAvrAVVQP7vhflJA7mPVNt6+bXRv1aMVfRVFM4kALWzYK2/6qoaDmC7OLHQuNqT44CFbj/6Z2gNcQO72tfLB005GvdbqiT8PJylpZ+TOFH7eqQFmmgIeQbeSVQZnqlq0KMtElArNRK8a4J+Zdh+yKNJ85xcFrcaFKlRPQdpetlvZYdRtFPf7iFMr3ubqYM7aNtvHrbXuaeMmZT9w35RJRtBSxQH43eNpf3zXh/VzkaKTSw7T9Un4FnTNG59O7rVYzxf0RKVI0wzwO9nRHGNa/sDjyCBu/vL7ElJ7FwbQudGLJQL07iBFJESKzfNm8heFO2lME8O05EBmsbLo3VMsTXyhi4M75cSGc5GaEt6FXuPh+ycboROYzNEpzffT2DYS3yZK+KF5hS0/lMm3NEyp4lYpk1cLydljNm/XONhGaSnEEBZLNicFKT4wWKZbRLzU1r87UQm//lWNRDxK3sFaegcjScGCewbXghEjsHRlQlIqnqAIFUTyvHiQVJqk+qnGDGRnGn47hmvZ3/RUvx6gMX/PYul5aDYcBihXh88SzwV88rB1tIRscPte4XroBNoqB2Q97OCpSm1aQ1R52ESz+bWdELdpDZpn/q+wx+vXp2NswIHncmz5VtfA9dHIAgcM7n7tUl/U6BVjmAW7X93Eh/YYxXzAU4/ZCxLYcluDhrg73H+le1BpIZ7j/MrV+fbHsQEtiUZzg/RjrwSaabCXakfKMlxDZ6ODwBE0OkuiNlkztrQCqR6c1/Pvg7fMUP0vxlsIyd47aBCgdC/OFUmAVBC1nq7HOxJ5wlkKeIQTL/q8QWwyhrDTsK/7CHjJ9awUhO8uCbrx7X8Yc77q6QJg7KEHm6gTQSEhq8cvnmtn40iQv8mzTDg7HqFOuPNLFLsjdDF7KByOIYsPGw1A8JJ+ATpcHo0sHjjA8/ye5uayNhtGpaGdsOG7HxhB1e98uSvr1fUCmzs4orc/HJuDbWCaVMjP5TdOTVmcKoylzEY9adZpFibKJV89j5iX46fxS4uURxIaLiYENo/2IS4+StY0sBbFTMRfy/9jWw3oQQ=" + } + ], + "retired": [], + "oidc": [ + { + "kid": "XWUv0uGESGdIG1MjOzbVjcwxB0CYtK0oZ9SZxNkH7h8", + "kty": "RSA", + "alg": "RS256", + "n": "zQwdJyTuyqQvB5zIXp9ULjX22k-R95Ls5j3IVUwLcI87I2VPUjsvy9oDGl5cq8Jl7Rt21d966AakANr8J1vT7gMpcmPOcEGVDdgdCprRs8cWNDo5uJ4ejt1LW65zRqW8xsxqHPm1aOxvjeUQfNgZFLn3VlSX01zgjggBLSwL18stLbyIzA2zcj4lpV-IrnBO3S6VUusoaO__kXjHv1-aH64wpVcsNLrBX6MWsnHM-KptbhKrk_qqXMJ7dokBxiIAH32VjZ73kTbVcSXoU2FshM_eQaonhYcRoD8PTXN3rxMaisj2pka9XZ1Apqy-EHf1dCoUphYxd_--FcT5PDQZaQ", + "e": "AQAB" + } + ], + "issuedAt": "2026-10-17T15:48:57.541Z" + }, + "signature": "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", + "rule": "SLH-DSA-SHA2-128s verify(publicKeyRaw, canonical(statement) bytes, signature); statement.keys are the keys this registry signs with" + }, + "rule": "HYBRID: for each entry in signatures, verify(keys[alg,keyId].publicKeyRaw, sealHash bytes, signature) — Ed25519 for alg ed25519, ML-DSA-65 (FIPS 204) for alg ml-dsa-65; ALL must verify. keyId = sha256(SPKI or raw key)[:16]. root, when present, is the SLH-DSA-SHA2-128s statement of these keys." + }, + "approver": { + "email": "sean@maclawran.ca", + "authLevel": "didit", + "authMethod": "webauthn", + "attestationId": "6ad3987b5f7026f62ae7bcdf", + "credentialId": "Yqa88hkURHnPqSTiV3o1jA", + "publicKey": { + "format": "ec-p256-uncompressed", + "alg": "ES256", + "raw": "BIWcVSzcT4ocdVb/bHtVrZNK/4RKRn1xhg6SE8TSy3QGpnJUufsDz2z+G1PqK3yP/7q5IPI9PEfjC77W/OxqD5k=" + }, + "assertion": { + "clientDataJSON": "eyJ0eXBlIjoid2ViYXV0aG4uZ2V0IiwiY2hhbGxlbmdlIjoiUmtwTF84UldDRXFCRzRvS3JVajFoT01kN2RqMnYtd2M4LWJwUjJjTDVlSSIsIm9yaWdpbiI6Imh0dHBzOi8vaW4ueGNoay5pbyIsImNyb3NzT3JpZ2luIjpmYWxzZX0", + "authenticatorData": "dcRETaEWF68z8NRCzR6PN99N5Mn8aYw-RadnYwZSFr0dAAAAAA", + "signature": "MEUCICB7UHe97FKVdN7ZSSHJw3tpOr-yJbVWgd69iV3fu31XAiEAiOWHcoPCRyRL52J9XHQ394x59sBZHFEpCx8XUy95AM8", + "encoding": "base64url" + }, + "challenge": { + "rule": "ask-v1", + "fields": { + "v": 1, + "attestationId": "6ad3987b5f7026f62ae7bcdf", + "prompt": "ENG-WNP3.3057 (via Claude Code) wants to P=\".ab1-probe-amend-$(date +%s)\"; rm -f \"$P\" && echo \"probe 4 ran as proposed\"", + "actionParamsHash": "db7d3f4a8d2c2ff292abe443dad96212e9cfd3a46118bd4f513cec76ebefd3ab" + }, + "expected": "RkpL_8RWCEqBG4oKrUj1hOMd7dj2v-wc8-bpR2cL5eI", + "note": "the challenge the approver's device signed = base64url(sha256(canonical(fields))); fields are the ask as issued, before any answer; recompute, do not trust `expected`" + }, + "binding": { + "fields": { + "v": 1, + "recordHash": "236de6c9aa5f147034e5aaebb6f235c1d90c999a5fe469cd5c07ed9b7405d10f", + "attestationId": "6ad3987b5f7026f62ae7bcdf", + "credentialId": "Yqa88hkURHnPqSTiV3o1jA", + "publicKey": "BIWcVSzcT4ocdVb/bHtVrZNK/4RKRn1xhg6SE8TSy3QGpnJUufsDz2z+G1PqK3yP/7q5IPI9PEfjC77W/OxqD5k=", + "approverEmail": "sean@maclawran.ca", + "authLevel": "didit", + "authMethod": "webauthn", + "verifiedAt": "2026-10-17T15:47:43.952Z" + }, + "signature": "ApYnn0/ky6MBb8c8Nbp0U/veQ+emRTO3lK3Ti91CwSaKrw5RqtHTFqA6RmKZSLuPCOyfIhzEC3ZsYdZmpxE3CA==", + "keyId": "5ecb3da505414c4f", + "signedAt": "2026-10-17T15:54:52.033Z", + "alg": "ed25519+ml-dsa-65", + "signatures": [ + { + "alg": "ed25519", + "keyId": "5ecb3da505414c4f", + "signature": "ApYnn0/ky6MBb8c8Nbp0U/veQ+emRTO3lK3Ti91CwSaKrw5RqtHTFqA6RmKZSLuPCOyfIhzEC3ZsYdZmpxE3CA==" + }, + { + "alg": "ml-dsa-65", + "keyId": "8bb85bc1f41c568c", + "signature": "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" + } + ], + "rule": "registry signature(s) over canonical(fields): each of `signatures` with the registrySignature.keys entry of the same alg/keyId (hybrid: all must verify); `signature` is the Ed25519 half" + }, + "rules": [ + "assertion: WebAuthn signature = ECDSA-P256/SHA-256 over authenticatorData || sha256(clientDataJSON), verified with publicKey.raw (uncompressed point); clientDataJSON.type must be \"webauthn.get\"; authenticatorData flags must include UV (user verified)", + "binding: verify each of binding.signatures (or binding.signature with alg ed25519) over canonical(binding.fields) with the matching registrySignature.keys entry — Ed25519 and, when present, ML-DSA-65; all must verify; binding.fields.recordHash must equal recordHash, binding.fields.credentialId must equal the assertion credential, and binding.fields.publicKey must equal approver.publicKey.raw (17 Oct 2026: an assertion re-signed by another key, with that key offered, passes every other check)", + "challenge: when approver.challenge is present (rule ask-v1, ceremonies from 18 Oct 2026), clientDataJSON.challenge must equal base64url(sha256(canonical(challenge.fields))) with fields.attestationId = approver.attestationId, fields.prompt = decision.prompt and fields.actionParamsHash = decision.actionParamsHash: the device signed over the ask, so the assertion itself names the act it answered. Absent, the challenge was a nonce and only the binding pairs the assertion with the record (an assertion by the same credential over another ask passes every other check)" + ] + }, + "basis": { + "asked": { + "seq": 9830, + "ts": "2026-10-17T15:47:07.348Z", + "area": "global", + "tool": "terminal", + "summary": "P=\".ab1-probe-amend-$(date +%s)\"; rm -f \"$P\" && echo \"probe 4 ran as proposed\"", + "paramsHash": "4be379baea38a39f1db7f336789fbe10894588df64fa2c3b3b085f627545f07c", + "code": "hook_escalation", + "reason": "destructive filesystem command outside scratch roots", + "recordHash": "1a98f5c74ea6e30b12055596e62b41a93723e1d804b528e6f12aa86ad7e4f82e", + "model": "claude-fable-5-1" + }, + "grant": { + "area": "global", + "disposition": "allow", + "policyId": null, + "maxAmount": null, + "resources": [] + }, + "authorizeDisposition": "attest", + "area": "global", + "objective": null, + "rule": "asked = the attest record this ceremony answers (same plate, same action summary, raised just before the ceremony; cite it by recordHash); grant = the plate's grant rows as they stood when the ceremony was raised; asked.reason is the registry's stated reason for asking" + }, + "decision": { + "prompt": "ENG-WNP3.3057 (via Claude Code) wants to P=\".ab1-probe-amend-$(date +%s)\"; rm -f \"$P\" && echo \"probe 4 ran as proposed\"", + "response": "approved", + "status": "completed", + "createdAt": "2026-10-17T15:47:07.600Z", + "respondedAt": "2026-10-17T15:47:43.952Z", + "by": "sean@maclawran.ca", + "authMethod": "webauthn", + "requiredAuthMethod": null, + "amendment": { + "command": "P=\".ab1-probe-amend-$(date +%s)\"; rm -f \"$P\" && echo \"CHANGED probe 4 ran as proposed\"", + "byEmail": "sean@maclawran.ca", + "at": "2026-10-17T15:47:43.962Z", + "area": "global", + "originalParamsHash": "db7d3f4a8d2c2ff292abe443dad96212e9cfd3a46118bd4f513cec76ebefd3ab" + }, + "actionParamsHash": "db7d3f4a8d2c2ff292abe443dad96212e9cfd3a46118bd4f513cec76ebefd3ab", + "attestationHash": "0f18cebd74639f960eb3d04f7781c80677c5adc0750333c0aa100ae8775819bb", + "attestationHashRule": "sha256 over the registry's canonical attestation JSON (utils/attestationHashUtils.computeAttestationHash: id, prompt, response, status, respondedAt, approver, method, amendment, delivery, chain …); recomputable on the registry, cited here so the record and this decision are bound" + }, + "legalHolds": null, + "anchor": { + "rvnTxId": null, + "rvnAnchoredAt": null, + "rvnBlock": "00000000000081b33c166cf1961e598cb91d40a6fef817b0d2d8aaf3b6b62753@4585373", + "explorer": null, + "otsProof": "8AgHtW3WwcdWHAjwIDmHgtDWxTNE7J5/xgGaHDFnrQrc3inlHM3qhjw4tw0GCPAQXdqsoXnzk3MwpP23KriFggjxIPLwuvDSO69qmiS9474S+Avisk6Nj3GHF2cAlCMhKZEgCPAgcg99+b7AHf2ZK3gpBTOQs3DbDNA7V9MlZXNzGCHcjq4I8CBgv3qhup4MMtQ5Z6CeKEgdkDbyf3ckONgeLlOyncp01gjxBGrTmg3wCL37YWeTW8icAIPf4w0u+QyOLi1odHRwczovL2FsaWNlLmJ0Yy5jYWxlbmRhci5vcGVudGltZXN0YW1wcy5vcmc=", + "otsCalendar": "https://a.pool.opentimestamps.org", + "otsBlockHeight": null, + "rule": "the anchor transaction carries sealHash in OP_RETURN; its raw bytes are captured once the transaction confirms (a few minutes) — download the bundle again for the offline anchor check, or use the explorer link" + }, + "howToVerify": [ + "1. canonicalize `record` per `canonicalization.profile`, sha256 it, compare to `recordHash`", + "2. walk `merkle.proof` from `recordHash` (L: sha256(step+cur), R: sha256(cur+step)); the result must equal `seal.merkleRoot`", + "3. canonicalize the seal fields per `seal.rule`, sha256 it, compare to `seal.sealHash`", + "4. verify every entry of `registrySignature.signatures` over the seal hash with the key of the same alg/keyId in `registrySignature.keys` (Ed25519 + ML-DSA-65 when hybrid); older bundles: Ed25519-verify `signature` with `publicKeyRaw`", + "5. if `approver` is present: verify the WebAuthn assertion with `approver.publicKey.raw`, then Ed25519-verify `approver.binding.signature` over canonical(`approver.binding.fields`) with the registry key, and require `approver.binding.fields.publicKey` to equal `approver.publicKey.raw`: the binding, not the bundle, names the key the assertion may be checked with; when `approver.challenge` is present, recompute base64url(sha256(canonical(`challenge.fields`))) and require it to equal `clientDataJSON.challenge`, with the fields equal to `approver.attestationId`, `decision.prompt` and `decision.actionParamsHash`", + "6. if `anchor.proof` is present: check the OP_RETURN, the txid, the header hash and the merkleblock; else look up `anchor.rvnTxId` on any Ravencoin explorer", + "8. if `seal.profileHash` is present: `profile.document` must be present, sha256(canonical(document)) must equal it, and `profile.signature` must verify over the hash with the registry keys; absent profileHash = sealed before profiles", + "7. if `basis`/`decision` are present: `basis.asked.recordHash` is another record on the same chain (fetch its bundle and run steps 1–4); `decision.attestationHash` equals `record.attestationHash`; `decision.amendment.command`, when present, is what ran" + ], + "profile": { + "profileHash": "9bbe0635c0a05cc8107d40ad5bb2d8b227c8125d395f41620bcd371123319701", + "document": { + "v": 1, + "name": "org", + "registry": "in.xchk.io", + "dials": { + "identity": [ + "email", + "domain" + ], + "registration": "person", + "anchoring": [ + "rvn", + "ots" + ], + "signing": "ed25519+ml-dsa-65", + "actSummary": { + "kept": "registry", + "maxChars": 400 + }, + "inbound": "on", + "operatorAccess": "recorded", + "actRecords": "kept", + "publicRecord": "plate", + "principalDomains": [ + "maclawran.ca" + ] + } + }, + "signature": { + "alg": "ed25519+ml-dsa-65", + "keyId": "5ecb3da505414c4f", + "signature": "3wM2ISHYyVQSahc6iEv70t47+skkAxg7sS7Nu6p82ZVT/WgN6iUdc+A+padJl1DJRcTJQErs3ppXsM8ZTQlEAQ==", + "signedAt": "2026-10-17T15:48:48.412Z", + "signatures": [ + { + "alg": "ed25519", + "keyId": "5ecb3da505414c4f", + "signature": "3wM2ISHYyVQSahc6iEv70t47+skkAxg7sS7Nu6p82ZVT/WgN6iUdc+A+padJl1DJRcTJQErs3ppXsM8ZTQlEAQ==" + }, + { + "alg": "ml-dsa-65", + "keyId": "8bb85bc1f41c568c", + "signature": "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" + } + ] + }, + "rule": "sha256(canonical(document)) = seal.profileHash; verify signature over the UTF-8 bytes of profileHash with the same registrySignature.keys as the seal; document.dials are the rules this node ran under when it sealed the window" + }, + "verifier": { + "html": "https://in.xchk.io/verify-receipt.html", + "python": "https://in.xchk.io/verify/verify_receipt.py", + "license": "MIT" + } +} diff --git a/integrations/xchk-registry/examples/approval-outcome/07-amended.json b/integrations/xchk-registry/examples/approval-outcome/07-amended.json new file mode 100644 index 00000000..42212ecd --- /dev/null +++ b/integrations/xchk-registry/examples/approval-outcome/07-amended.json @@ -0,0 +1,47 @@ +{ + "eat_profile": "tag:agentrust-io.com,2026:trace-v0.2", + "iat": 1792252491, + "subject": "did:web:in.xchk.io:plate:ENG-WNP3", + "model": { + "provider": "anthropic", + "model_id": "claude-fable-5-1" + }, + "runtime": { + "platform": "software-only", + "measurement": "sha256:c60a771a8f6e4fda60fbb2b745397c800c38da090f153f72e302147a1851746a" + }, + "policy": { + "bundle_hash": "sha256:8e1e29b1e2b1470b57fba453991d3c9ef0d0ae19ba59927c014525177ee741ae", + "enforcement_mode": "enforce" + }, + "data_class": "internal", + "tool_transcript": { + "hash": "sha256:54ea01281f1acf13dec96c509cb243c5ee87b826524044ac8c2700a63cd9f2bb", + "call_count": 101 + }, + "references": [ + { + "rel": "approval-outcome", + "id": "236de6c9aa5f147034e5aaebb6f235c1d90c999a5fe469cd5c07ed9b7405d10f", + "resolver": "https://in.xchk.io", + "digest": "sha256:236de6c9aa5f147034e5aaebb6f235c1d90c999a5fe469cd5c07ed9b7405d10f" + } + ], + "build_provenance": { + "slsa_level": 0, + "digest": "sha256:c60a771a8f6e4fda60fbb2b745397c800c38da090f153f72e302147a1851746a" + }, + "appraisal": { + "status": "none", + "verifier": "https://in.xchk.io" + }, + "cnf": { + "jwk": { + "kty": "OKP", + "crv": "Ed25519", + "x": "mn02E1XyTkaVN6DEOemU5OADMUAUjPHw67oR5KKIM3k", + "kid": "5ecb3da505414c4f" + } + }, + "signature": "60lSb4QmsCBSkmtQU5lO_OOGDCjaI02z0UJJXaccnOMvtVR_wuufsoM9xSexN2S6rbmhTtmKsm42iF3kBHtlBw" +} diff --git a/integrations/xchk-registry/examples/approval-outcome/08-assertion-over-another-ask.bundle.json b/integrations/xchk-registry/examples/approval-outcome/08-assertion-over-another-ask.bundle.json new file mode 100644 index 00000000..03bbf4c1 --- /dev/null +++ b/integrations/xchk-registry/examples/approval-outcome/08-assertion-over-another-ask.bundle.json @@ -0,0 +1,368 @@ +{ + "format": "xchk-receipt-bundle/2", + "issuer": { + "name": "xChk registry", + "base": "https://in.xchk.io", + "servedAt": "2026-10-17T15:54:51.987Z", + "headline": "ENG-WNP3: APPROVED terminal in global at 2026-10-17T15:46:00.571Z — approved by sean@maclawran.ca." + }, + "recordHash": "aa2bfd5b1d9b6307ed22eb0daa4213383beecb57d7d31ec011060ac98f7fe0b5", + "record": { + "v": 1, + "agentId": "6acbf860a627414b66045478", + "plate": "ENG-WNP3", + "seq": 9819, + "ts": "2026-10-17T15:46:00.571Z", + "harness": "claude", + "runSeq": 3057, + "runRef": "ENG WNP3.3057", + "area": "global", + "tool": "terminal", + "summary": "P=\".ab1-probe-approve1-$(date +%s)\"; rm -f \"$P\" && echo \"probe 1 ran (nothing existed to remove)\"", + "paramsHash": "a791bccfa14f0666b7082aab7586455f1898da48651cbbbb643e0df3402655c6", + "amount": null, + "disposition": "approved", + "code": null, + "reason": null, + "deskCondition": "normal", + "continuityClass": "standard", + "authRef": "c2486b7f4874e5d08aba0725", + "prevHash": "25607c8e2e529dddce618b49b1c11da6b302a6687c6d44b335f304e904dc796f", + "rvnBlock": "000000000001303bd2857ce3c400c92e8bcf8b97c14eda4f85650e03f91ef3e3@4585364", + "approverEmail": "sean@maclawran.ca", + "authMethod": "webauthn", + "attestationId": "6ad398295f7026f62ae7b863", + "attestationHash": "d7896ca4608bcdd8581ce6c0bb5917e541d40d635334e1a8746d7fc1bc230d5e", + "photoUrl": "https://xchk-main.s3.us-east-005.backblazeb2.com/xchk/xchk/baseline/att_6ad398295f7026f62ae7b863/0.jpg", + "model": "claude-fable-5-1" + }, + "canonicalization": { + "profile": "JSON with object keys sorted (code-unit order), no whitespace, scalars as JSON.stringify would emit them, undefined omitted, integers only; hash = sha256 over the UTF-8 bytes", + "hashedConditionalKeys": [ + "rvnBlock", + "approverEmail", + "authMethod", + "requiredAuthMethod", + "attestationId", + "attestationHash", + "photoUrl", + "labelsHash", + "delegationHash", + "model", + "tokensIn", + "tokensOut", + "tokensCacheRead", + "contextPct", + "actor", + "chargeCode", + "workspace", + "policyHash", + "outcomeOf", + "resultHash", + "endedAt", + "artifactHash" + ], + "note": "conditional keys are present only when the record carried them; absent keys are absent from the bytes, not null" + }, + "merkle": { + "proof": [ + { + "side": "L", + "hash": "25607c8e2e529dddce618b49b1c11da6b302a6687c6d44b335f304e904dc796f" + }, + { + "side": "R", + "hash": "61cbbb71667c7ad8ed2fb67feadf3454a801ced41e3d303ba7b8297524c0e86b" + }, + { + "side": "R", + "hash": "c7f7fb52d081b787566876416919dca904cef18613bb63efa3e28b0ab8eeced5" + }, + { + "side": "R", + "hash": "30e986cfeef36f573d77f3f49948c8bc3248ee8e068d439c149ee72dbe2dad8b" + }, + { + "side": "R", + "hash": "b1f52c8bef88f4187114b4cfab6922468a0e2f3775dc9b6fa7d1479458d02019" + }, + { + "side": "R", + "hash": "b8de3bc958dcdcd07dfc74b47a39ede41e6c649d39f09505b88802fbfb5e7739" + } + ], + "leafCount": 37, + "rule": "node = sha256(left_hex + right_hex) over the hex strings; an odd node is promoted unhashed; the leaf is the record hash" + }, + "seal": { + "v": 1, + "agentId": "6acbf860a627414b66045478", + "plate": "ENG-WNP3", + "sealSeq": 1496, + "windowStart": "2026-10-17T15:44:25.565Z", + "windowEnd": "2026-10-17T15:53:48.404Z", + "count": 37, + "issuedCount": 37, + "seqStart": 9818, + "seqEnd": 9854, + "merkleRoot": "2662a87b9401541c4917428bda73596a608ad5ea556acdc110639e2e618092e9", + "deskCondition": "normal", + "prevSealHash": "82904359e52743e49d8c822814094b1519e02214578adef89487469b555c68c5", + "rvnBlock": "00000000000081b33c166cf1961e598cb91d40a6fef817b0d2d8aaf3b6b62753@4585373", + "profileHash": "9bbe0635c0a05cc8107d40ad5bb2d8b227c8125d395f41620bcd371123319701", + "sealHash": "a00007915e398e7a5f6fdd0863a7ebc0f3eac99da656b85a4fad0d06a8c15710", + "rule": "sealHash = sha256(canonical({v, agentId, plate, sealSeq, windowStart, windowEnd, count, issuedCount, seqStart, seqEnd, merkleRoot, deskCondition, prevSealHash[, rvnBlock][, profileHash]}))" + }, + "registrySignature": { + "alg": "ed25519+ml-dsa-65", + "keyId": "5ecb3da505414c4f", + "signature": "v+SHukcW2TmkZbafId5igQnOU75fbb51UNUJFRwp5DdQd1ebk+9Z7wZ9BXfBpmZUWLBgm3ZuNlP+IbVZrKH3Bg==", + "signedAt": "2026-10-17T15:53:48.458Z", + "signatures": [ + { + "alg": "ed25519", + "keyId": "5ecb3da505414c4f", + "signature": "v+SHukcW2TmkZbafId5igQnOU75fbb51UNUJFRwp5DdQd1ebk+9Z7wZ9BXfBpmZUWLBgm3ZuNlP+IbVZrKH3Bg==" + }, + { + "alg": "ml-dsa-65", + "keyId": "8bb85bc1f41c568c", + "signature": "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" + } + ], + "signedOver": "the UTF-8 bytes of seal.sealHash", + "publicKeyRaw": "mn02E1XyTkaVN6DEOemU5OADMUAUjPHw67oR5KKIM3k=", + "publicKeyPem": "-----BEGIN PUBLIC KEY-----\nMCowBQYDK2VwAyEAmn02E1XyTkaVN6DEOemU5OADMUAUjPHw67oR5KKIM3k=\n-----END PUBLIC KEY-----\n", + "wellKnown": "https://in.xchk.io/.well-known/xchk-keys.json", + "keys": [ + { + "alg": "ed25519", + "keyId": "5ecb3da505414c4f", + "publicKeyRaw": "mn02E1XyTkaVN6DEOemU5OADMUAUjPHw67oR5KKIM3k=" + }, + { + "alg": "ml-dsa-65", + "keyId": "8bb85bc1f41c568c", + "publicKeyRaw": "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" + } + ], + "retired": [], + "publicKeyRawPq": "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", + "keyIdPq": "8bb85bc1f41c568c", + "root": { + "alg": "slh-dsa-sha2-128s", + "standard": "FIPS 205", + "keyId": "acc7ad1aeb3ef177", + "publicKeyRaw": "4aIhDuj3TZPwqb9HT8TzVJnkvle4jVUMhWkn/BfmypM=", + "statement": { + "v": 1, + "registry": "https://in.xchk.io", + "keys": [ + { + "alg": "ed25519", + "keyId": "5ecb3da505414c4f", + "publicKeyRaw": "mn02E1XyTkaVN6DEOemU5OADMUAUjPHw67oR5KKIM3k=" + }, + { + "alg": "ml-dsa-65", + "keyId": "8bb85bc1f41c568c", + "publicKeyRaw": "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" + } + ], + "retired": [], + "oidc": [ + { + "kid": "XWUv0uGESGdIG1MjOzbVjcwxB0CYtK0oZ9SZxNkH7h8", + "kty": "RSA", + "alg": "RS256", + "n": "zQwdJyTuyqQvB5zIXp9ULjX22k-R95Ls5j3IVUwLcI87I2VPUjsvy9oDGl5cq8Jl7Rt21d966AakANr8J1vT7gMpcmPOcEGVDdgdCprRs8cWNDo5uJ4ejt1LW65zRqW8xsxqHPm1aOxvjeUQfNgZFLn3VlSX01zgjggBLSwL18stLbyIzA2zcj4lpV-IrnBO3S6VUusoaO__kXjHv1-aH64wpVcsNLrBX6MWsnHM-KptbhKrk_qqXMJ7dokBxiIAH32VjZ73kTbVcSXoU2FshM_eQaonhYcRoD8PTXN3rxMaisj2pka9XZ1Apqy-EHf1dCoUphYxd_--FcT5PDQZaQ", + "e": "AQAB" + } + ], + "issuedAt": "2026-10-17T15:48:57.541Z" + }, + "signature": "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", + "rule": "SLH-DSA-SHA2-128s verify(publicKeyRaw, canonical(statement) bytes, signature); statement.keys are the keys this registry signs with" + }, + "rule": "HYBRID: for each entry in signatures, verify(keys[alg,keyId].publicKeyRaw, sealHash bytes, signature) — Ed25519 for alg ed25519, ML-DSA-65 (FIPS 204) for alg ml-dsa-65; ALL must verify. keyId = sha256(SPKI or raw key)[:16]. root, when present, is the SLH-DSA-SHA2-128s statement of these keys." + }, + "approver": { + "email": "sean@maclawran.ca", + "authLevel": "didit", + "authMethod": "webauthn", + "attestationId": "6ad398295f7026f62ae7b863", + "credentialId": "Yqa88hkURHnPqSTiV3o1jA", + "publicKey": { + "format": "ec-p256-uncompressed", + "alg": "ES256", + "raw": "BIWcVSzcT4ocdVb/bHtVrZNK/4RKRn1xhg6SE8TSy3QGpnJUufsDz2z+G1PqK3yP/7q5IPI9PEfjC77W/OxqD5k=" + }, + "assertion": { + "clientDataJSON": "eyJ0eXBlIjoid2ViYXV0aG4uZ2V0IiwiY2hhbGxlbmdlIjoiWk4yQ2hBNUFta2d4ZFlRTTBmQmt2dUNodlN3MlRGYkNiUTFleDYtZV9nTSIsIm9yaWdpbiI6Imh0dHBzOi8vaW4ueGNoay5pbyIsImNyb3NzT3JpZ2luIjpmYWxzZX0", + "authenticatorData": "dcRETaEWF68z8NRCzR6PN99N5Mn8aYw-RadnYwZSFr0dAAAAAA", + "signature": "MEQCIE-K_G0S-XzSq-cPL06uEI15VLwHx-BuSh4tIz53DBTrAiB-4X-cBD_216b-Vpkkx5QIEGE-LaY_UOebBSrC-CekMQ", + "encoding": "base64url" + }, + "challenge": { + "rule": "ask-v1", + "fields": { + "v": 1, + "attestationId": "6ad398295f7026f62ae7b863", + "prompt": "ENG-WNP3.3057 (via Claude Code) wants to P=\".ab1-probe-approve1-$(date +%s)\"; rm -f \"$P\" && echo \"probe 1 ran (nothing existed to remove)\"", + "actionParamsHash": "5eee3b37a63eb957436a2bd51633d8a3c9a54f96c66e71f45fbd2d458373ca68" + }, + "expected": "5ELcKviHrmlnPIZ0OBkHLdOm3NZjUJtCySwyAB-pIMc", + "note": "the challenge the approver's device signed = base64url(sha256(canonical(fields))); fields are the ask as issued, before any answer; recompute, do not trust `expected`" + }, + "binding": { + "fields": { + "v": 1, + "recordHash": "aa2bfd5b1d9b6307ed22eb0daa4213383beecb57d7d31ec011060ac98f7fe0b5", + "attestationId": "6ad398295f7026f62ae7b863", + "credentialId": "Yqa88hkURHnPqSTiV3o1jA", + "publicKey": "BIWcVSzcT4ocdVb/bHtVrZNK/4RKRn1xhg6SE8TSy3QGpnJUufsDz2z+G1PqK3yP/7q5IPI9PEfjC77W/OxqD5k=", + "approverEmail": "sean@maclawran.ca", + "authLevel": "didit", + "authMethod": "webauthn", + "verifiedAt": "2026-10-17T15:46:00.404Z" + }, + "signature": "LpDId3mnpJVZn4ntyVIwrgy/sT1vdKmomgr8eoShKHRJhvh7xr7qvVD3ZhKaaYxa5rcL/E0JQX8ICh+Y/1vSDA==", + "keyId": "5ecb3da505414c4f", + "signedAt": "2026-10-17T15:54:51.971Z", + "alg": "ed25519+ml-dsa-65", + "signatures": [ + { + "alg": "ed25519", + "keyId": "5ecb3da505414c4f", + "signature": "LpDId3mnpJVZn4ntyVIwrgy/sT1vdKmomgr8eoShKHRJhvh7xr7qvVD3ZhKaaYxa5rcL/E0JQX8ICh+Y/1vSDA==" + }, + { + "alg": "ml-dsa-65", + "keyId": "8bb85bc1f41c568c", + "signature": "TJEgpLndNxJYVin/7SngNRFwnWSHtuq+z9F1Nzgl9O46gwXOXaJKc10lC0gl0maHVweIbdepmRHSVTd8y5UPV99gysMAchoamFWb1I5sWNFvAXS3X/9cztT6ckccMGW7YxHZhCRvFve6nLxa2yBNyZeNYZbNGez/dMOCRFJqoAKNcWnkoGSQwkWNvfXMRFjQiDyb6oT0IudhgJ7ckdGW5vJ+WJJtGgoUwms1gTmPdiuPGg7gPXeZTavuC2StabynYXAHXk74FxGHjbI0oXQc6mcgdb2lrLrkicQwI/zioLFOMbpY1vpPu+RYo7bL5Bb8xg0VbSt07x7L6Ji+S6RhJIiNM8QzR+DhYzGYIehHBgHXEHv3duJ8vkrpNjheKVCOiMI3Fy/YS09wiFFsgEA3Jj6u8g8MEzMvaeDlfL2H2NFGpkEgOMsDAh9XNGuGmNBFME6J0N0vx2FLAYmYwGSzkwVhH95QUyevKcdStcLfh1/RgOHucOxGiyPMxO77vgZ0DFwjbI9DGkd8KeJ6RlmakBuO0YFjMez3uepNqSSpkC6Fzaj+6S8sFH5Uw2yhTdvEj2FD/BOyXlzJTkLiq6VdRNIotnatN/EElkYcQM61nbV5CCXI5ZP9S7eQGPIj4+pgPrHzBvFsHb6v21SQNeu9tcHPoDyrQJophdM/zwZV7ZvJEsIsUCilD43RtiyqdoZGzwuVNF+iJ5jVXfg/MtXEDuMebzn3KRvV0BEbDnN//33XXn880b/Pl2iVbjPby7DW4svrZ7hFWHiUjqjiYfgr0WL0SOzFzDEhX5e5TKzoG6ewOdFu3PWVTlPkHrsZdNrJt9Xo/wfZbQ3gTUKsNOKrihDhVk/YzYOyWb2ecYrxYrXSaUuwy2xiBoQh96Q3xNAjWwtNvi+VPU6e0JXAV7oGyb8HCl5BTU5b+xZ6WvIdn0vvaS+vQHoj8uzYK5o0ooHRXF+o+2U4onGjfsMIDNqmSLF+eZBIUsJwLP4DCNQJ6r9xacJWylGiYKLIiMMORGKb50mRuxcL62NUSONfzMa1qnsQs4XskH9dl9hmJn4ZzKs/CV0loCAA8Hj1+PQnGEuf8L7Sx16iNKYmb2RdCld/BvVHj9ymzIF5ctU8yb+YZjDIUWQV4ZwlsA0gyi+JQ/1J36oTUv1NljGxrXR0Ax5EKlyTaDRIeNog5Mu+ciamfb6C4QZDsqspDX3jUYkpRLZ++6bDnnSP6NNiUdvrt6YyhbORgBVvZwkHC2JtYXZCurAwVwmOOpIwRmm7I1AATmQGtgFzPcblj9uiFZTbGRmJlsNKG8VMKrHagLEMDagEhwVgn6WPI4p3IZ3v3QtNWuuRNE6mkcLFgbM0MuJyIwWMSs4j56JaRE8rmlXpuzXBYGemQi/KR6Q77F0wIR5SZtKbbne1xMiRGLC3OA121Vjg2yl1Jsdw5gJ+JLp967tCFETQhf+ySQZE7WGibPX6UAjoI6RqO9F+9f/WDxk1EwFhwpFuytuhQv4hrOTN87BUrYVgRc4e4KHKBGJOcOa7LB9ChtY7+aM8pzI9UXms9TZY5QYOaRRZB8rMY6Z6EYdIHa7cGwiXufgyP+z3AIlv/Mgtm2pigNr7O56dg8C3d57BnqimQclS+Jd8FDYXjDi0k0iJneqQsvshm+LM7pcvLvrBTCkh8c8jyRXXK2r9KIlIbGCoz3QntlhsAdTuO3WFvjcuZ1CR++1Q64PkOAYEs5MyDUP4FfQ/FrfyJVG6CTO3bFcklEOWiJJBRdEaUR/j3GJnX5Ohk5nKASx+3AXHWKnECi0WDtaemM/UEVnJ1tSn6uCo2Yk+iG/Z9sbWdyGU8CPDRqNcdRlM+LnEDfPxwqvGGBmxLah5zNask+7NkkeShEHhxlwbA13YL1QHglXDBb1gKJPgbDST6SNAPp9FJWXhlqvLgCN840wxbJ/BZGwR45Ms7a1iJT0BEg57LZ3esqTh+B2fF8bgMG4AbWDEOizsoMMm4atjwPOYXSp09aA/sNmAB5bLFAN747N2KpB2Noy3CsMVtgzufDFefBUsOvHu51GvqXLAkaEfd1ini/xDL7yKGmqjr8sI6aXoQ+Xt9Nu4YHf6nEibtyTJ6CcjnwFlunX1M43UwmwlY9Yi7d6gs+jpatxdqAAvhcIE2vLfQyLsh6lgV95CHq3SmWCX9+SoTud5hBWU4cp/BZTZ8s/1KDUvVbkWfsqAnmoeadoMvdDcE1HVdJjeB4ASpZRLcJNrSq1C3rsgrg8ZxAkL/pgRjUERnvpaH/26VNGHooWwH6+9ZdC6Wldzn9kN9lRvERvhVRYRcAERJ/0oASh32thGYAaKo65st/1hmEM4o+aYueU2J4p1SvmXOaNDtWYOPGX4wN27pH3GNQSuAGtNaNHEw6ajfzZGOTV0FM0v+aA8rM7zMwYZ359MEeampU/59Y12xkUdkwXw5HYKx+WSiAL/tA/pN9EhVIyCr0UtYhyu7vyRQW9x78IRxkzy0O0/xjxQQQ4VAZGiAHUOU/JYiHst8k5cs9cl+DqTDbLFKo8WeeH4x5AGXvSdyMSa8AHG5LmilNpBSiF4VeuWIGyf+ZSEh5ITEycBYnRyRJDEE7DxfO7fZP3YlbJW/NZ6HZGlvS3sqychcyxxLbktebEigGXjNlCilhyl3CWJ3aFc7YB7HfglUZDVVj8x5+yVwCGXUFqKrNma8OXBHvz+I0NW76xOdNRH4kiSNDNx5LXOKj8OVmSbBjVGjjqYfI/ts29Cc95nU5PorWqUn0HZ8I6M99gkIyOrB2MDpo1Dewd0YsgVNSoa97qM8+OH7m4leBFWW+zjth+ReoSBZiDFm4Yh8dEd5fkpRccnwOclUzGXcvspcxtHSISTpXDBALQVhlOrZDUdxjw2EYIU9UdWAacwKMZ4Kcih5fMvNdGdgzA+EMKFQZa6Mq+ykJubMVnK8whgmB0nyTm4U7J1GnTln7y4N6T0NMpWuC4oWyy7MbrKh4eYoQv7Q3I3iFjxcLV6AUVZQg8M506xsxg514hA9m8q1kvGHaEbOgrwBTzHjVKIdY8mjvs04QL66rZ67+QjItnl/i3mSdCUazmIdolnSxcJ4rxbWAyHRtFNbwAwIyUnF3lE30DmVdiG7NmZkyffZ3LavC9oBH/xkJdrvNbZQvJmDgAHlhmGn9dDYVQNwsYKd/Y/TTKNFFgKLezo2g9fcxbr2hMEOcI9CaQV7EMBka9rylakepBlkZmq9/cQKQJbTDOJZfZra5y3rpbij/jG8qTqahrl4zOEBlI5n/gOX3dFeDtYqSWgAsGbmWfLqVkxJSOn/n7g/QyGodrFMCBFeNMk+06E1yw6fSafZWNZJ0ydy7Kf50AxaFCOFYxWSCaCZln0qntxreMs5Rjt02zMqSLXltVnB+B42Bmk2fXh20iR1D+Ny5CXBc1I+PC1DpAc4T2DbBm8fIUczWT66H6iEjKwx3Jf2GPgreEPmEKuhKhC2z88LUzJwnUOKWyO5VYygv5r+Nssrq3qZdkT5zpPI+426iRFsUBKqKANWbq8OL2UGkSjaP74KHxm9vfsLmO6vueZLqku/3cuOhdTA2TDhT4lAFvlOEMN/hm70g9LCMdKt6xmUKgqLbP/F+2XhZ1rqCsaQXj2MKFe8xXI5tI3pw0HN1wl+/bAxhWvtKBIUTPrQYoTb6n2ox8KAh+a47g12Ftc7qwhdHsfm1Ekgo2sNbfzwll0JN3FOpK92s6AMSMqGBsL9vYZJRpZ0QaxjI2Vu7vLGXfcZwGPdHLdmLJwm4Wd1e82UgmIyjolSQ+nZOMxfJgbRDtOKi8mDTgwBywlevhzKg+unOjR1xyBMkm3FHBPZHSVmMgLHkAm+rqtAOxyMGPLY8fsQ8+gxaVYHEEtrQIJbur3uQaf/IlRg/9TJNQyVm+C/+a7VW75EMlS/J1rCoWywveRAyDYR+oVSCy0DHC6CYP2ImtHxTDjxlmh7eOnVxLG/+S+2cd5+r+u+0R6DAbUe5Ca57BQo1qu8Xy0MSWnw/7uPShdp1JMThIK7LeMEe+hwxh+g5F5qqf9HcIT7fJ6h8rFkVAeO8vKzdwEcsCOsHUCOG2eBoRUE9PE0Fis3YmpkJY02T19qhfMT2ffg3Hb5UJ+frHBeoNJJ2XWNgFHvisg7kJ4WOtuFNb7slN3Z1jmHwLSoBom2TKQUuZBw0aks/d8J4GrC8E2zF5Sfs8Zw28Pa9chSeFYreFDJFQq6rwK+XTkx+9g4TY/WyTOEgueop+exMoLM7WHNahtIpEXqy1og3kenD1nW1ioMO3Av2oiVJ4z9fd8kiL5HinSH3HImzRoVfg9SwuvRSwbrHzEjd4QFF50kpO4xMne3zdGR6CtxMXq8/lQaoiUpfUqWqcydq+y9Rqbp97k+AAAAAAAAAAAAAAAAAAACxUbHiMp" + } + ], + "rule": "registry signature(s) over canonical(fields): each of `signatures` with the registrySignature.keys entry of the same alg/keyId (hybrid: all must verify); `signature` is the Ed25519 half" + }, + "rules": [ + "assertion: WebAuthn signature = ECDSA-P256/SHA-256 over authenticatorData || sha256(clientDataJSON), verified with publicKey.raw (uncompressed point); clientDataJSON.type must be \"webauthn.get\"; authenticatorData flags must include UV (user verified)", + "binding: verify each of binding.signatures (or binding.signature with alg ed25519) over canonical(binding.fields) with the matching registrySignature.keys entry — Ed25519 and, when present, ML-DSA-65; all must verify; binding.fields.recordHash must equal recordHash, binding.fields.credentialId must equal the assertion credential, and binding.fields.publicKey must equal approver.publicKey.raw (17 Oct 2026: an assertion re-signed by another key, with that key offered, passes every other check)", + "challenge: when approver.challenge is present (rule ask-v1, ceremonies from 18 Oct 2026), clientDataJSON.challenge must equal base64url(sha256(canonical(challenge.fields))) with fields.attestationId = approver.attestationId, fields.prompt = decision.prompt and fields.actionParamsHash = decision.actionParamsHash: the device signed over the ask, so the assertion itself names the act it answered. Absent, the challenge was a nonce and only the binding pairs the assertion with the record (an assertion by the same credential over another ask passes every other check)" + ] + }, + "basis": { + "asked": { + "seq": 9818, + "ts": "2026-10-17T15:45:45.315Z", + "area": "global", + "tool": "terminal", + "summary": "P=\".ab1-probe-approve1-$(date +%s)\"; rm -f \"$P\" && echo \"probe 1 ran (nothing existed to remove)\"", + "paramsHash": "a791bccfa14f0666b7082aab7586455f1898da48651cbbbb643e0df3402655c6", + "code": "hook_escalation", + "reason": "destructive filesystem command outside scratch roots", + "recordHash": "25607c8e2e529dddce618b49b1c11da6b302a6687c6d44b335f304e904dc796f", + "model": "claude-fable-5-1" + }, + "grant": { + "area": "global", + "disposition": "allow", + "policyId": null, + "maxAmount": null, + "resources": [] + }, + "authorizeDisposition": "attest", + "area": "global", + "objective": null, + "rule": "asked = the attest record this ceremony answers (same plate, same action summary, raised just before the ceremony; cite it by recordHash); grant = the plate's grant rows as they stood when the ceremony was raised; asked.reason is the registry's stated reason for asking" + }, + "decision": { + "prompt": "ENG-WNP3.3057 (via Claude Code) wants to P=\".ab1-probe-approve1-$(date +%s)\"; rm -f \"$P\" && echo \"probe 1 ran (nothing existed to remove)\"", + "response": "approved", + "status": "completed", + "createdAt": "2026-10-17T15:45:45.553Z", + "respondedAt": "2026-10-17T15:46:00.404Z", + "by": "sean@maclawran.ca", + "authMethod": "webauthn", + "requiredAuthMethod": null, + "amendment": null, + "actionParamsHash": "5eee3b37a63eb957436a2bd51633d8a3c9a54f96c66e71f45fbd2d458373ca68", + "attestationHash": "d7896ca4608bcdd8581ce6c0bb5917e541d40d635334e1a8746d7fc1bc230d5e", + "attestationHashRule": "sha256 over the registry's canonical attestation JSON (utils/attestationHashUtils.computeAttestationHash: id, prompt, response, status, respondedAt, approver, method, amendment, delivery, chain …); recomputable on the registry, cited here so the record and this decision are bound" + }, + "legalHolds": null, + "anchor": { + "rvnTxId": null, + "rvnAnchoredAt": null, + "rvnBlock": "00000000000081b33c166cf1961e598cb91d40a6fef817b0d2d8aaf3b6b62753@4585373", + "explorer": null, + "otsProof": "8AgHtW3WwcdWHAjwIDmHgtDWxTNE7J5/xgGaHDFnrQrc3inlHM3qhjw4tw0GCPAQXdqsoXnzk3MwpP23KriFggjxIPLwuvDSO69qmiS9474S+Avisk6Nj3GHF2cAlCMhKZEgCPAgcg99+b7AHf2ZK3gpBTOQs3DbDNA7V9MlZXNzGCHcjq4I8CBgv3qhup4MMtQ5Z6CeKEgdkDbyf3ckONgeLlOyncp01gjxBGrTmg3wCL37YWeTW8icAIPf4w0u+QyOLi1odHRwczovL2FsaWNlLmJ0Yy5jYWxlbmRhci5vcGVudGltZXN0YW1wcy5vcmc=", + "otsCalendar": "https://a.pool.opentimestamps.org", + "otsBlockHeight": null, + "rule": "the anchor transaction carries sealHash in OP_RETURN; its raw bytes are captured once the transaction confirms (a few minutes) — download the bundle again for the offline anchor check, or use the explorer link" + }, + "howToVerify": [ + "1. canonicalize `record` per `canonicalization.profile`, sha256 it, compare to `recordHash`", + "2. walk `merkle.proof` from `recordHash` (L: sha256(step+cur), R: sha256(cur+step)); the result must equal `seal.merkleRoot`", + "3. canonicalize the seal fields per `seal.rule`, sha256 it, compare to `seal.sealHash`", + "4. verify every entry of `registrySignature.signatures` over the seal hash with the key of the same alg/keyId in `registrySignature.keys` (Ed25519 + ML-DSA-65 when hybrid); older bundles: Ed25519-verify `signature` with `publicKeyRaw`", + "5. if `approver` is present: verify the WebAuthn assertion with `approver.publicKey.raw`, then Ed25519-verify `approver.binding.signature` over canonical(`approver.binding.fields`) with the registry key, and require `approver.binding.fields.publicKey` to equal `approver.publicKey.raw`: the binding, not the bundle, names the key the assertion may be checked with; when `approver.challenge` is present, recompute base64url(sha256(canonical(`challenge.fields`))) and require it to equal `clientDataJSON.challenge`, with the fields equal to `approver.attestationId`, `decision.prompt` and `decision.actionParamsHash`", + "6. if `anchor.proof` is present: check the OP_RETURN, the txid, the header hash and the merkleblock; else look up `anchor.rvnTxId` on any Ravencoin explorer", + "8. if `seal.profileHash` is present: `profile.document` must be present, sha256(canonical(document)) must equal it, and `profile.signature` must verify over the hash with the registry keys; absent profileHash = sealed before profiles", + "7. if `basis`/`decision` are present: `basis.asked.recordHash` is another record on the same chain (fetch its bundle and run steps 1–4); `decision.attestationHash` equals `record.attestationHash`; `decision.amendment.command`, when present, is what ran" + ], + "profile": { + "profileHash": "9bbe0635c0a05cc8107d40ad5bb2d8b227c8125d395f41620bcd371123319701", + "document": { + "v": 1, + "name": "org", + "registry": "in.xchk.io", + "dials": { + "identity": [ + "email", + "domain" + ], + "registration": "person", + "anchoring": [ + "rvn", + "ots" + ], + "signing": "ed25519+ml-dsa-65", + "actSummary": { + "kept": "registry", + "maxChars": 400 + }, + "inbound": "on", + "operatorAccess": "recorded", + "actRecords": "kept", + "publicRecord": "plate", + "principalDomains": [ + "maclawran.ca" + ] + } + }, + "signature": { + "alg": "ed25519+ml-dsa-65", + "keyId": "5ecb3da505414c4f", + "signature": "3wM2ISHYyVQSahc6iEv70t47+skkAxg7sS7Nu6p82ZVT/WgN6iUdc+A+padJl1DJRcTJQErs3ppXsM8ZTQlEAQ==", + "signedAt": "2026-10-17T15:48:48.412Z", + "signatures": [ + { + "alg": "ed25519", + "keyId": "5ecb3da505414c4f", + "signature": "3wM2ISHYyVQSahc6iEv70t47+skkAxg7sS7Nu6p82ZVT/WgN6iUdc+A+padJl1DJRcTJQErs3ppXsM8ZTQlEAQ==" + }, + { + "alg": "ml-dsa-65", + "keyId": "8bb85bc1f41c568c", + "signature": "Zb3O5PtSKMTE1QIBj1+w+IUyik8fJP0Dmp2qw1ekD2oasV+VXfozxa/RyJyURSrRi9CAddYUiRYPiH/dZmI1Hu2h0KNnNYJlEKbQbsIHx94sYCtVGNbD11saLwr/4I0iccCltJQVzxczreLdEhrhB/+Rn4+doXcWdWe+27/PwHrGoTg1wxcI/cooaNJCdcgerBqOhAe7c9yBihEfWC1u3nl76gApp5cFxAaScbBnJawFKucoOYlnzt8AIuoT1ccPKIw2r6gqhxOMLD+k3YFUSKu7ahEnKbiQQe5ha5rxv5h5O5G2z9q1zUU6L6rfzck664zzFybicPPUOFJe12n9Ndm+BvYL+SwNQMob0hoMeZ9DY1m6uoESHmwPLkXa8xdtmLel6HpOzB/1IV0xJgNrXeaUuPiqz/7cPabqOrcMKY/oSnSCThdqrH4Hq3621MrYAyTM4Xe5RXx9bjeucWOrkwDUQ2cTIfS+VCmNDWfBsLM1SecsR/EqWCQS77QHi67mUL1c8pPh2PuyUxAeec5Km7t7avHbaE2odXR/gcLrqkjk9vBsKJC1CHE50PsmXpMc+bnmwb6rTIRw/TsZskSy1zqmAj+SArKDcKGVcqVeQ40rCRfGeRDpEcxgjQQDtGzgqGAoK6i5Wet+gxI2QjmtLo+qpOmqrlvz58lVcGvYtmYeEjn83jx9ZThE06ewRVs/f6/JK6Bzee+2eokPpiuXVBaYXW92kAbYUZAqGmDYo1qvxhAnG7EeCk3kpTeBbeTl6EoFFL3jxZW5JVJPv9J4c3wQ6yOE37JigM19fKfcXyCBRqgk9BHriapm5MpaExmBN0EiIFSUYODXEWevw2KSy8xEAWpjSmecvAwJObZIPiLwTFjuv5w8D+r/oUt1ctr/gTxQ7i3XA2qZshIxHFtYzty7lF/nb3y9D5oJ2Zx5iFFEkvedHl1VzIFwcixW8O7GyHqZCHFTFpn9Iw0M9HONGsn7c1nuaNwyZfIJt4kll/Qj+2V0tsFd9J853cszdrG/Xup/rRIFj41wPDMoc2u+0RG+Iosu6xwf3triKj4jdID2ssTu+3Oq4OOY38JWBNG7XEhtgiiI7wnYc5iXqutgyOG/C/u2iATiuNPeGApJpZBvniO400OkmMvwOF0FfUJiK0GCt2GtmJYeeZ2juVLEdR6iVFtVzEIAR5Z5aTObTZM3IhTxGanM59xeKMOszYpip09a8XqMq13i4h+zgOZ+EU9FF9nOH+U+XoTaAaEFtKfV88Y8z9/CjabkpehU+0dplztr368tfm+aqIggWdkLy49Z5YkFo5RPO1vP7teQbxZUZXMNsh3yhAndDgb4MGfdokzg/np8TX3PSVeISfHdjWBN9EbypBWjDvRkQkpj8rzcC/hvMByY3dNU3UD9oCKZXFBXl49YIB45Ul6WvbgIZiZSvb1jMKsfAKZejbrZ61x8lHPfeyWG0dY6mmprZAIMdf1oKc03aeXOcNx3tyTTtANr4VqwtW8neW69N0V6vIV5yYjyWn4tgoK5G4DP0WWftIH6+39CT6KMszwpfYNTawHt1e8nXonGn4DTm/GKidJCJpEamDXPwGCJbC2F6yHbUFFy3o6ICTw1MPD720r8n8F3CZgiaFsloB4YLcTA657xn1OMpbD2VA4WLGW2SzqTfDtHILcKuGs7Oj7lYxlF7Gs/+ILEEbqgbhNmHi3cQIoC7Wyc7Iib4sXqySKk17o8H40dE0CgHkJ/++ub2+eHexlFdd1NBqGUE9BOBPnqR+1gkvIJ1KSzGy5SLKRbiXZraUDyfnpylXW+dY3/68GAWdrIH0QKvdnG+qgAVgsXKA9UNyEF3sXq6YTrTXQG8w4QL6N/AqMWUGICf/0L6bxSYIaoVzh1gXmWhHOyYWf4+nSDzbKMtnbDKUJ4YvmZ3beG2s00KllebdnOuGlBWXCX4OJmCvjtyz3WEZzl3mbhqHr29/c7UrcYT+H54pDqg8vyY3SfT4lgvEXpuboXOP7Gug/VJ5mtUHw0Cd5JuxX4KXr00Fy8P2kI/5eoa38IfNxilmQZXwCV1tkLyQ+CIQLhk2lkrUDr8NzEuXFvTg4692LndmLkDU3NeUlFDxY59HrMNs3zuVZa1x5oWk2dXyg6EfWIm4a1rPhL/d3tvwx/aSEiG55SC3H7fXIXb0gipC+fRtkKXfJCYJKHkYoNAL9jxzv8MEJaXVrbW5xpBrIqo3uQZ03cVbysQtvCwTMdd+NIZD3ny+R6cFM23NHoFgXJRk1r145Hq2zUmPJ/aDx9/l2qvAsozNkasnIfFPYAw2QA8CrtU4P2g/l4RLTBxWdEPa2fGN24OuMW/tlUzE1U7ypKSFpIHPa8hB6y7KhNPDsNGwoQoTKCoO3tYkQ1hWcaa95HSA+N/CTTHUYlKcA5J13ooeZTBVzp24hq6GwWIo9Wphqpvf7MAjrH9I3j9fyQkRgB2FV2hFztqLNsMd+KYL9oJ5FSArkYzZvgJNBnb+U9k88HFRDqgsIPDdJ6wo8CE8aczYrCyIRazbew5y1eNTW7At6LIY59T+TTCjwQYlBIQGn5f/NZP5hMmgQ8Z5lveiEhfd4TGvnA3RJvVswuiPSB2kl3FVIkwLdLsON+lkMQargJLqUVcasRaCqoIiHS3Im3bxbS9Z2ObH7B38uz43Q45+NOoD+X/ig0try+5O37C9J5p9mLDQ4U4gFhTwaNIjBER/jwt7wkW0OWi1VICwqS+knN51XsBgkLcDgH+sQUZC46M6OKsrYC5mwn+gq/xaTLj6QPaVI0gVU6up7cgDKYfvjvOBkSL0zJkrHDfyXcBsU9FsmWQgq9EptgTORzshvBUlV92Bt6ilhbEFpQFMcTMjmmyx4slEm+h2NnYQBzJP7u1JEIdj7FWLksLoijfjj5jj0zY9myN4XJxWtVeSLYA+ofntcYXkEPUvfwdoA9HwFkt3B2STxVT++MlJew+My9H49HsgzBJAHpfu7kyVeelgUPjLGk3YPQgdbCuUYwsktRPfLXDzV1Xv2SII09lMstuy1WdB+U8mT/PnBaQh2N/7Xy0oPbXfMWqZ3V3LflGqwQTRo/GVPr9ABPwNdZ3M00VPDZ31ps6aHd9PPqXWGRY8V1yETvX+FyNQsThmF0tIkjoAp2Cn5244hEVdDb15qbb5K+PNHta//0kzWSggwxmsr7j6GfUXFjJ66oxVX44oPySqn1LZSk8TCkyOWOT+0fKHEdxNko2dqzbjz2/Nt9k6LJdUX6hcN6IW5uGcnyywgJ9RfCQjZoyvsD9fQ/2W6Zsiy5Okfd/0c1JkYTdLihE8zVx2ajsV/MCRbHDQZ4o1Rw8IJY/m61RtPkcLE3uSpmTkxSwTi1oeQdiMBf+gqZ+Zc6u3aWMRNyQ1DOyfTQbBWFk9ph/d9VPrmucPdFYOa9e4w6mbTm8McGrsxr3K6QJ/nkLGw7se3vaXwkG5ppznSvGSFWAR3bGE3vBdPqXU9DOIK2uYzI3+0YxXHe5iSbOLYxqHEEjq231jey73eScieDN2bWVaVSrEPIO+B+ecHJ+lFGScMLN7ouzvP+ppapLtE//8RAubZX1xWr9LCmewO0e2HwBg+EPnh7FQv//DxCDgz54zN3xuozWUVrJAE/BHo/BrEQG3vvPB/3IBK4JjWSJRKeoEoe/q2C+b5rkk+QPic/VfSDtZM/CIRyQu/pNgZyY9lv3KFGKDcpon2AbNh67OK78rCkvvS7czZI1o2Do71AMNUaTWDz/dLmidbbVbxQXHrAgR34iplKwoEY44i4k1Masm9NUC7uZyo4wNBX11um5ovIi2owhVtDZQOEgpbPk7f4MC2n6oXSghiTaCxaqG62p8uFaT40Xp1n3kkLo/11RzTgVDCTtQ+cffAkb9G6ZNbPjGxTdAHoiJiOzwYF91CITM8xl12J5nSi3UsgeFSaZRRvfn+vDgnkb4ZRb3vBi+5BtVaJw1yqzWDPmWOflM3SgjAPH0+Y/rvIkNhUNqcj090gVVT1UtOtJVyLDbwRJ2R/iANFO/2vOVZtxHwxx2ucj0TP7j9m0/EvEv0W+NMYGq8maREbtq1sBtfAs9z7QF95WGznTw4099ErR1tzym2QogHIyD6myZ1f1bYTKRJxekrBi8DQu9fMe9U2yrI5krKLBZNt3yl9eHvdNKcEdSyCXLWl4HjinufRh1hNk8wg5HoYCu/5JXkQJvLtn1ZaoqqIOVPOsgZWwcoo3kO1cKwTseyL7yYmTuqmqv8tEVWSDFgjCTFtmPYckRrEK8zi59XSoAaNUmYAIBK4v4QPUiYEjTF5zs+zGfsLRphEK9DuQ7yd2hxDFZ6IfYdXgrrB5wxidZXd82RmbnKixdwlX2fg4xQpSWOexdjdMEOHnp+yutDi9AAAAAAAAAAAAAAAAAAABQsSFx8p" + } + ] + }, + "rule": "sha256(canonical(document)) = seal.profileHash; verify signature over the UTF-8 bytes of profileHash with the same registrySignature.keys as the seal; document.dials are the rules this node ran under when it sealed the window" + }, + "verifier": { + "html": "https://in.xchk.io/verify-receipt.html", + "python": "https://in.xchk.io/verify/verify_receipt.py", + "license": "MIT" + } +} diff --git a/integrations/xchk-registry/examples/approval-outcome/08-assertion-over-another-ask.json b/integrations/xchk-registry/examples/approval-outcome/08-assertion-over-another-ask.json new file mode 100644 index 00000000..ca850981 --- /dev/null +++ b/integrations/xchk-registry/examples/approval-outcome/08-assertion-over-another-ask.json @@ -0,0 +1,47 @@ +{ + "eat_profile": "tag:agentrust-io.com,2026:trace-v0.2", + "iat": 1792252491, + "subject": "did:web:in.xchk.io:plate:ENG-WNP3", + "model": { + "provider": "anthropic", + "model_id": "claude-fable-5-1" + }, + "runtime": { + "platform": "software-only", + "measurement": "sha256:c60a771a8f6e4fda60fbb2b745397c800c38da090f153f72e302147a1851746a" + }, + "policy": { + "bundle_hash": "sha256:8e1e29b1e2b1470b57fba453991d3c9ef0d0ae19ba59927c014525177ee741ae", + "enforcement_mode": "enforce" + }, + "data_class": "internal", + "tool_transcript": { + "hash": "sha256:54ea01281f1acf13dec96c509cb243c5ee87b826524044ac8c2700a63cd9f2bb", + "call_count": 101 + }, + "references": [ + { + "rel": "approval-outcome", + "id": "aa2bfd5b1d9b6307ed22eb0daa4213383beecb57d7d31ec011060ac98f7fe0b5", + "resolver": "https://in.xchk.io", + "digest": "sha256:aa2bfd5b1d9b6307ed22eb0daa4213383beecb57d7d31ec011060ac98f7fe0b5" + } + ], + "build_provenance": { + "slsa_level": 0, + "digest": "sha256:c60a771a8f6e4fda60fbb2b745397c800c38da090f153f72e302147a1851746a" + }, + "appraisal": { + "status": "none", + "verifier": "https://in.xchk.io" + }, + "cnf": { + "jwk": { + "kty": "OKP", + "crv": "Ed25519", + "x": "mn02E1XyTkaVN6DEOemU5OADMUAUjPHw67oR5KKIM3k", + "kid": "5ecb3da505414c4f" + } + }, + "signature": "Vjgt2d7DVF_KmYdb3UXuOaL4YxRO1k46Uj91QkI5vc0EC5NraQ7U7S58DuD35d8GMy70wW-I08OtkRiCKTfPAQ" +} diff --git a/integrations/xchk-registry/examples/approval-outcome/09-re-keyed-outside-the-registry.bundle.json b/integrations/xchk-registry/examples/approval-outcome/09-re-keyed-outside-the-registry.bundle.json new file mode 100644 index 00000000..420f7eb5 --- /dev/null +++ b/integrations/xchk-registry/examples/approval-outcome/09-re-keyed-outside-the-registry.bundle.json @@ -0,0 +1,369 @@ +{ + "format": "xchk-receipt-bundle/2", + "issuer": { + "name": "xChk registry", + "base": "https://in.xchk.io", + "servedAt": "2026-10-17T15:54:51.987Z", + "headline": "ENG-WNP3: APPROVED terminal in global at 2026-10-17T15:46:00.571Z — approved by sean@maclawran.ca." + }, + "recordHash": "aa2bfd5b1d9b6307ed22eb0daa4213383beecb57d7d31ec011060ac98f7fe0b5", + "record": { + "v": 1, + "agentId": "6acbf860a627414b66045478", + "plate": "ENG-WNP3", + "seq": 9819, + "ts": "2026-10-17T15:46:00.571Z", + "harness": "claude", + "runSeq": 3057, + "runRef": "ENG WNP3.3057", + "area": "global", + "tool": "terminal", + "summary": "P=\".ab1-probe-approve1-$(date +%s)\"; rm -f \"$P\" && echo \"probe 1 ran (nothing existed to remove)\"", + "paramsHash": "a791bccfa14f0666b7082aab7586455f1898da48651cbbbb643e0df3402655c6", + "amount": null, + "disposition": "approved", + "code": null, + "reason": null, + "deskCondition": "normal", + "continuityClass": "standard", + "authRef": "c2486b7f4874e5d08aba0725", + "prevHash": "25607c8e2e529dddce618b49b1c11da6b302a6687c6d44b335f304e904dc796f", + "rvnBlock": "000000000001303bd2857ce3c400c92e8bcf8b97c14eda4f85650e03f91ef3e3@4585364", + "approverEmail": "sean@maclawran.ca", + "authMethod": "webauthn", + "attestationId": "6ad398295f7026f62ae7b863", + "attestationHash": "d7896ca4608bcdd8581ce6c0bb5917e541d40d635334e1a8746d7fc1bc230d5e", + "photoUrl": "https://xchk-main.s3.us-east-005.backblazeb2.com/xchk/xchk/baseline/att_6ad398295f7026f62ae7b863/0.jpg", + "model": "claude-fable-5-1" + }, + "canonicalization": { + "profile": "JSON with object keys sorted (code-unit order), no whitespace, scalars as JSON.stringify would emit them, undefined omitted, integers only; hash = sha256 over the UTF-8 bytes", + "hashedConditionalKeys": [ + "rvnBlock", + "approverEmail", + "authMethod", + "requiredAuthMethod", + "attestationId", + "attestationHash", + "photoUrl", + "labelsHash", + "delegationHash", + "model", + "tokensIn", + "tokensOut", + "tokensCacheRead", + "contextPct", + "actor", + "chargeCode", + "workspace", + "policyHash", + "outcomeOf", + "resultHash", + "endedAt", + "artifactHash" + ], + "note": "conditional keys are present only when the record carried them; absent keys are absent from the bytes, not null" + }, + "merkle": { + "proof": [ + { + "side": "L", + "hash": "25607c8e2e529dddce618b49b1c11da6b302a6687c6d44b335f304e904dc796f" + }, + { + "side": "R", + "hash": "61cbbb71667c7ad8ed2fb67feadf3454a801ced41e3d303ba7b8297524c0e86b" + }, + { + "side": "R", + "hash": "c7f7fb52d081b787566876416919dca904cef18613bb63efa3e28b0ab8eeced5" + }, + { + "side": "R", + "hash": "30e986cfeef36f573d77f3f49948c8bc3248ee8e068d439c149ee72dbe2dad8b" + }, + { + "side": "R", + "hash": "b1f52c8bef88f4187114b4cfab6922468a0e2f3775dc9b6fa7d1479458d02019" + }, + { + "side": "R", + "hash": "b8de3bc958dcdcd07dfc74b47a39ede41e6c649d39f09505b88802fbfb5e7739" + } + ], + "leafCount": 37, + "rule": "node = sha256(left_hex + right_hex) over the hex strings; an odd node is promoted unhashed; the leaf is the record hash" + }, + "seal": { + "v": 1, + "agentId": "6acbf860a627414b66045478", + "plate": "ENG-WNP3", + "sealSeq": 1496, + "windowStart": "2026-10-17T15:44:25.565Z", + "windowEnd": "2026-10-17T15:53:48.404Z", + "count": 37, + "issuedCount": 37, + "seqStart": 9818, + "seqEnd": 9854, + "merkleRoot": "2662a87b9401541c4917428bda73596a608ad5ea556acdc110639e2e618092e9", + "deskCondition": "normal", + "prevSealHash": "82904359e52743e49d8c822814094b1519e02214578adef89487469b555c68c5", + "rvnBlock": "00000000000081b33c166cf1961e598cb91d40a6fef817b0d2d8aaf3b6b62753@4585373", + "profileHash": "9bbe0635c0a05cc8107d40ad5bb2d8b227c8125d395f41620bcd371123319701", + "sealHash": "a00007915e398e7a5f6fdd0863a7ebc0f3eac99da656b85a4fad0d06a8c15710", + "rule": "sealHash = sha256(canonical({v, agentId, plate, sealSeq, windowStart, windowEnd, count, issuedCount, seqStart, seqEnd, merkleRoot, deskCondition, prevSealHash[, rvnBlock][, profileHash]}))" + }, + "registrySignature": { + "alg": "ed25519+ml-dsa-65", + "keyId": "b92fea3af39de611", + "signature": "QldeZFtegiFGnWiEiGxh4Vyg5FszPKUj1zmiNOvgkBb13HKYCMDO3qrVzxcTe4f3H5NrZDTxOem3CXLIU4LiCw==", + "signedAt": "2026-10-17T15:53:48.458Z", + "signatures": [ + { + "alg": "ed25519", + "keyId": "b92fea3af39de611", + "signature": "QldeZFtegiFGnWiEiGxh4Vyg5FszPKUj1zmiNOvgkBb13HKYCMDO3qrVzxcTe4f3H5NrZDTxOem3CXLIU4LiCw==" + }, + { + "alg": "ml-dsa-65", + "keyId": "21d121387565faa0", + "signature": "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" + } + ], + "signedOver": "the UTF-8 bytes of seal.sealHash", + "publicKeyRaw": "bGhG90elzuZCwxezg1aYU0MQuObgrHYH7LuEnI3gQLg=", + "publicKeyPem": "-----BEGIN PUBLIC KEY-----\nMCowBQYDK2VwAyEAbGhG90elzuZCwxezg1aYU0MQuObgrHYH7LuEnI3gQLg=\n-----END PUBLIC KEY-----\n", + "wellKnown": "https://in.xchk.io/.well-known/xchk-keys.json", + "keys": [ + { + "alg": "ed25519", + "keyId": "b92fea3af39de611", + "publicKeyRaw": "bGhG90elzuZCwxezg1aYU0MQuObgrHYH7LuEnI3gQLg=" + }, + { + "alg": "ml-dsa-65", + "keyId": "21d121387565faa0", + "publicKeyRaw": "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" + } + ], + "retired": [], + "publicKeyRawPq": "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", + "keyIdPq": "21d121387565faa0", + "root": { + "alg": "slh-dsa-sha2-128s", + "standard": "FIPS 205", + "keyId": "acc7ad1aeb3ef177", + "publicKeyRaw": "4aIhDuj3TZPwqb9HT8TzVJnkvle4jVUMhWkn/BfmypM=", + "statement": { + "v": 1, + "registry": "https://in.xchk.io", + "keys": [ + { + "alg": "ed25519", + "keyId": "b92fea3af39de611", + "publicKeyRaw": "bGhG90elzuZCwxezg1aYU0MQuObgrHYH7LuEnI3gQLg=" + }, + { + "alg": "ml-dsa-65", + "keyId": "21d121387565faa0", + "publicKeyRaw": "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" + } + ], + "retired": [], + "oidc": [ + { + "kid": "XWUv0uGESGdIG1MjOzbVjcwxB0CYtK0oZ9SZxNkH7h8", + "kty": "RSA", + "alg": "RS256", + "n": "zQwdJyTuyqQvB5zIXp9ULjX22k-R95Ls5j3IVUwLcI87I2VPUjsvy9oDGl5cq8Jl7Rt21d966AakANr8J1vT7gMpcmPOcEGVDdgdCprRs8cWNDo5uJ4ejt1LW65zRqW8xsxqHPm1aOxvjeUQfNgZFLn3VlSX01zgjggBLSwL18stLbyIzA2zcj4lpV-IrnBO3S6VUusoaO__kXjHv1-aH64wpVcsNLrBX6MWsnHM-KptbhKrk_qqXMJ7dokBxiIAH32VjZ73kTbVcSXoU2FshM_eQaonhYcRoD8PTXN3rxMaisj2pka9XZ1Apqy-EHf1dCoUphYxd_--FcT5PDQZaQ", + "e": "AQAB" + } + ], + "issuedAt": "2026-10-17T15:48:57.541Z" + }, + "signature": "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", + "rule": "SLH-DSA-SHA2-128s verify(publicKeyRaw, canonical(statement) bytes, signature); statement.keys are the keys this registry signs with" + }, + "rule": "HYBRID: for each entry in signatures, verify(keys[alg,keyId].publicKeyRaw, sealHash bytes, signature) — Ed25519 for alg ed25519, ML-DSA-65 (FIPS 204) for alg ml-dsa-65; ALL must verify. keyId = sha256(SPKI or raw key)[:16]. root, when present, is the SLH-DSA-SHA2-128s statement of these keys." + }, + "approver": { + "email": "sean@maclawran.ca", + "authLevel": "didit", + "authMethod": "webauthn", + "attestationId": "6ad398295f7026f62ae7b863", + "credentialId": "Yqa88hkURHnPqSTiV3o1jA", + "publicKey": { + "format": "ec-p256-uncompressed", + "alg": "ES256", + "raw": "BIWcVSzcT4ocdVb/bHtVrZNK/4RKRn1xhg6SE8TSy3QGpnJUufsDz2z+G1PqK3yP/7q5IPI9PEfjC77W/OxqD5k=" + }, + "assertion": { + "clientDataJSON": "eyJ0eXBlIjoid2ViYXV0aG4uZ2V0IiwiY2hhbGxlbmdlIjoiNUVMY0t2aUhybWxuUElaME9Ca0hMZE9tM05aalVKdEN5U3d5QUItcElNYyIsIm9yaWdpbiI6Imh0dHBzOi8vaW4ueGNoay5pbyIsImNyb3NzT3JpZ2luIjpmYWxzZX0", + "authenticatorData": "dcRETaEWF68z8NRCzR6PN99N5Mn8aYw-RadnYwZSFr0dAAAAAA", + "signature": "MEUCIQDCuR26urn4n7AYJ2_Ohd9_KJ7hRp6pEm2qG1mqjnjMbAIgdUuoz3nO2St6MasEmX3TvKYiv8MoFn1UA9_li9nWCB8", + "encoding": "base64url" + }, + "challenge": { + "rule": "ask-v1", + "fields": { + "v": 1, + "attestationId": "6ad398295f7026f62ae7b863", + "prompt": "ENG-WNP3.3057 (via Claude Code) wants to P=\".ab1-probe-approve1-$(date +%s)\"; rm -f \"$P\" && echo \"probe 1 ran (nothing existed to remove)\"", + "actionParamsHash": "5eee3b37a63eb957436a2bd51633d8a3c9a54f96c66e71f45fbd2d458373ca68" + }, + "expected": "5ELcKviHrmlnPIZ0OBkHLdOm3NZjUJtCySwyAB-pIMc", + "note": "the challenge the approver's device signed = base64url(sha256(canonical(fields))); fields are the ask as issued, before any answer; recompute, do not trust `expected`" + }, + "binding": { + "fields": { + "v": 1, + "recordHash": "aa2bfd5b1d9b6307ed22eb0daa4213383beecb57d7d31ec011060ac98f7fe0b5", + "attestationId": "6ad398295f7026f62ae7b863", + "credentialId": "Yqa88hkURHnPqSTiV3o1jA", + "publicKey": "BIWcVSzcT4ocdVb/bHtVrZNK/4RKRn1xhg6SE8TSy3QGpnJUufsDz2z+G1PqK3yP/7q5IPI9PEfjC77W/OxqD5k=", + "approverEmail": "sean@maclawran.ca", + "authLevel": "didit", + "authMethod": "webauthn", + "verifiedAt": "2026-10-17T15:46:00.404Z" + }, + "signature": "PNGlMU6aTOEQ7fzbG+sveIr3ZndQ2w7dIXMNxPn7C7ncIENCxNvyzbbbWWNTa9X0IyHgQIyiMDG19SevSbOMAg==", + "keyId": "b92fea3af39de611", + "signedAt": "2026-10-17T15:54:51.971Z", + "alg": "ed25519+ml-dsa-65", + "signatures": [ + { + "alg": "ed25519", + "keyId": "b92fea3af39de611", + "signature": "PNGlMU6aTOEQ7fzbG+sveIr3ZndQ2w7dIXMNxPn7C7ncIENCxNvyzbbbWWNTa9X0IyHgQIyiMDG19SevSbOMAg==" + }, + { + "alg": "ml-dsa-65", + "keyId": "21d121387565faa0", + "signature": "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" + } + ], + "rule": "registry signature(s) over canonical(fields): each of `signatures` with the registrySignature.keys entry of the same alg/keyId (hybrid: all must verify); `signature` is the Ed25519 half" + }, + "rules": [ + "assertion: WebAuthn signature = ECDSA-P256/SHA-256 over authenticatorData || sha256(clientDataJSON), verified with publicKey.raw (uncompressed point); clientDataJSON.type must be \"webauthn.get\"; authenticatorData flags must include UV (user verified)", + "binding: verify each of binding.signatures (or binding.signature with alg ed25519) over canonical(binding.fields) with the matching registrySignature.keys entry — Ed25519 and, when present, ML-DSA-65; all must verify; binding.fields.recordHash must equal recordHash, binding.fields.credentialId must equal the assertion credential, and binding.fields.publicKey must equal approver.publicKey.raw (17 Oct 2026: an assertion re-signed by another key, with that key offered, passes every other check)", + "challenge: when approver.challenge is present (rule ask-v1, ceremonies from 18 Oct 2026), clientDataJSON.challenge must equal base64url(sha256(canonical(challenge.fields))) with fields.attestationId = approver.attestationId, fields.prompt = decision.prompt and fields.actionParamsHash = decision.actionParamsHash: the device signed over the ask, so the assertion itself names the act it answered. Absent, the challenge was a nonce and only the binding pairs the assertion with the record (an assertion by the same credential over another ask passes every other check)" + ] + }, + "basis": { + "asked": { + "seq": 9818, + "ts": "2026-10-17T15:45:45.315Z", + "area": "global", + "tool": "terminal", + "summary": "P=\".ab1-probe-approve1-$(date +%s)\"; rm -f \"$P\" && echo \"probe 1 ran (nothing existed to remove)\"", + "paramsHash": "a791bccfa14f0666b7082aab7586455f1898da48651cbbbb643e0df3402655c6", + "code": "hook_escalation", + "reason": "destructive filesystem command outside scratch roots", + "recordHash": "25607c8e2e529dddce618b49b1c11da6b302a6687c6d44b335f304e904dc796f", + "model": "claude-fable-5-1" + }, + "grant": { + "area": "global", + "disposition": "allow", + "policyId": null, + "maxAmount": null, + "resources": [] + }, + "authorizeDisposition": "attest", + "area": "global", + "objective": null, + "rule": "asked = the attest record this ceremony answers (same plate, same action summary, raised just before the ceremony; cite it by recordHash); grant = the plate's grant rows as they stood when the ceremony was raised; asked.reason is the registry's stated reason for asking" + }, + "decision": { + "prompt": "ENG-WNP3.3057 (via Claude Code) wants to P=\".ab1-probe-approve1-$(date +%s)\"; rm -f \"$P\" && echo \"probe 1 ran (nothing existed to remove)\"", + "response": "approved", + "status": "completed", + "createdAt": "2026-10-17T15:45:45.553Z", + "respondedAt": "2026-10-17T15:46:00.404Z", + "by": "sean@maclawran.ca", + "authMethod": "webauthn", + "requiredAuthMethod": null, + "amendment": null, + "actionParamsHash": "5eee3b37a63eb957436a2bd51633d8a3c9a54f96c66e71f45fbd2d458373ca68", + "attestationHash": "d7896ca4608bcdd8581ce6c0bb5917e541d40d635334e1a8746d7fc1bc230d5e", + "attestationHashRule": "sha256 over the registry's canonical attestation JSON (utils/attestationHashUtils.computeAttestationHash: id, prompt, response, status, respondedAt, approver, method, amendment, delivery, chain …); recomputable on the registry, cited here so the record and this decision are bound" + }, + "legalHolds": null, + "anchor": { + "rvnTxId": null, + "rvnAnchoredAt": null, + "rvnBlock": "00000000000081b33c166cf1961e598cb91d40a6fef817b0d2d8aaf3b6b62753@4585373", + "explorer": null, + "otsProof": "8AgHtW3WwcdWHAjwIDmHgtDWxTNE7J5/xgGaHDFnrQrc3inlHM3qhjw4tw0GCPAQXdqsoXnzk3MwpP23KriFggjxIPLwuvDSO69qmiS9474S+Avisk6Nj3GHF2cAlCMhKZEgCPAgcg99+b7AHf2ZK3gpBTOQs3DbDNA7V9MlZXNzGCHcjq4I8CBgv3qhup4MMtQ5Z6CeKEgdkDbyf3ckONgeLlOyncp01gjxBGrTmg3wCL37YWeTW8icAIPf4w0u+QyOLi1odHRwczovL2FsaWNlLmJ0Yy5jYWxlbmRhci5vcGVudGltZXN0YW1wcy5vcmc=", + "otsCalendar": "https://a.pool.opentimestamps.org", + "otsBlockHeight": null, + "rule": "the anchor transaction carries sealHash in OP_RETURN; its raw bytes are captured once the transaction confirms (a few minutes) — download the bundle again for the offline anchor check, or use the explorer link" + }, + "howToVerify": [ + "1. canonicalize `record` per `canonicalization.profile`, sha256 it, compare to `recordHash`", + "2. walk `merkle.proof` from `recordHash` (L: sha256(step+cur), R: sha256(cur+step)); the result must equal `seal.merkleRoot`", + "3. canonicalize the seal fields per `seal.rule`, sha256 it, compare to `seal.sealHash`", + "4. verify every entry of `registrySignature.signatures` over the seal hash with the key of the same alg/keyId in `registrySignature.keys` (Ed25519 + ML-DSA-65 when hybrid); older bundles: Ed25519-verify `signature` with `publicKeyRaw`", + "5. if `approver` is present: verify the WebAuthn assertion with `approver.publicKey.raw`, then Ed25519-verify `approver.binding.signature` over canonical(`approver.binding.fields`) with the registry key, and require `approver.binding.fields.publicKey` to equal `approver.publicKey.raw`: the binding, not the bundle, names the key the assertion may be checked with; when `approver.challenge` is present, recompute base64url(sha256(canonical(`challenge.fields`))) and require it to equal `clientDataJSON.challenge`, with the fields equal to `approver.attestationId`, `decision.prompt` and `decision.actionParamsHash`", + "6. if `anchor.proof` is present: check the OP_RETURN, the txid, the header hash and the merkleblock; else look up `anchor.rvnTxId` on any Ravencoin explorer", + "8. if `seal.profileHash` is present: `profile.document` must be present, sha256(canonical(document)) must equal it, and `profile.signature` must verify over the hash with the registry keys; absent profileHash = sealed before profiles", + "7. if `basis`/`decision` are present: `basis.asked.recordHash` is another record on the same chain (fetch its bundle and run steps 1–4); `decision.attestationHash` equals `record.attestationHash`; `decision.amendment.command`, when present, is what ran" + ], + "profile": { + "profileHash": "9bbe0635c0a05cc8107d40ad5bb2d8b227c8125d395f41620bcd371123319701", + "document": { + "v": 1, + "name": "org", + "registry": "in.xchk.io", + "dials": { + "identity": [ + "email", + "domain" + ], + "registration": "person", + "anchoring": [ + "rvn", + "ots" + ], + "signing": "ed25519+ml-dsa-65", + "actSummary": { + "kept": "registry", + "maxChars": 400 + }, + "inbound": "on", + "operatorAccess": "recorded", + "actRecords": "kept", + "publicRecord": "plate", + "principalDomains": [ + "maclawran.ca" + ] + } + }, + "signature": { + "alg": "ed25519+ml-dsa-65", + "keyId": "b92fea3af39de611", + "signature": "mxIQW/SOiSZl0Oi1ed3++PohlkaVCBFahqtxmuoggethqrJkYpqsqIBHYeBMIn9zZ1X9Q09kwD58vjSB2lWVAg==", + "signedAt": "2026-10-17T15:48:48.412Z", + "signatures": [ + { + "alg": "ed25519", + "keyId": "b92fea3af39de611", + "signature": "mxIQW/SOiSZl0Oi1ed3++PohlkaVCBFahqtxmuoggethqrJkYpqsqIBHYeBMIn9zZ1X9Q09kwD58vjSB2lWVAg==" + }, + { + "alg": "ml-dsa-65", + "keyId": "21d121387565faa0", + "signature": "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" + } + ] + }, + "rule": "sha256(canonical(document)) = seal.profileHash; verify signature over the UTF-8 bytes of profileHash with the same registrySignature.keys as the seal; document.dials are the rules this node ran under when it sealed the window" + }, + "verifier": { + "html": "https://in.xchk.io/verify-receipt.html", + "python": "https://in.xchk.io/verify/verify_receipt.py", + "license": "MIT" + }, + "fixtureNote": "TEST FIXTURE, 2 Nov 2026: fixture 01 re-signed under keys that are not the registry's (rekey_fixture.py, beside the tests). Every offline check passes without --keys; with the registry's key document the pinned keys fail by name." +} diff --git a/integrations/xchk-registry/examples/approval-outcome/09-re-keyed-outside-the-registry.json b/integrations/xchk-registry/examples/approval-outcome/09-re-keyed-outside-the-registry.json new file mode 100644 index 00000000..ca850981 --- /dev/null +++ b/integrations/xchk-registry/examples/approval-outcome/09-re-keyed-outside-the-registry.json @@ -0,0 +1,47 @@ +{ + "eat_profile": "tag:agentrust-io.com,2026:trace-v0.2", + "iat": 1792252491, + "subject": "did:web:in.xchk.io:plate:ENG-WNP3", + "model": { + "provider": "anthropic", + "model_id": "claude-fable-5-1" + }, + "runtime": { + "platform": "software-only", + "measurement": "sha256:c60a771a8f6e4fda60fbb2b745397c800c38da090f153f72e302147a1851746a" + }, + "policy": { + "bundle_hash": "sha256:8e1e29b1e2b1470b57fba453991d3c9ef0d0ae19ba59927c014525177ee741ae", + "enforcement_mode": "enforce" + }, + "data_class": "internal", + "tool_transcript": { + "hash": "sha256:54ea01281f1acf13dec96c509cb243c5ee87b826524044ac8c2700a63cd9f2bb", + "call_count": 101 + }, + "references": [ + { + "rel": "approval-outcome", + "id": "aa2bfd5b1d9b6307ed22eb0daa4213383beecb57d7d31ec011060ac98f7fe0b5", + "resolver": "https://in.xchk.io", + "digest": "sha256:aa2bfd5b1d9b6307ed22eb0daa4213383beecb57d7d31ec011060ac98f7fe0b5" + } + ], + "build_provenance": { + "slsa_level": 0, + "digest": "sha256:c60a771a8f6e4fda60fbb2b745397c800c38da090f153f72e302147a1851746a" + }, + "appraisal": { + "status": "none", + "verifier": "https://in.xchk.io" + }, + "cnf": { + "jwk": { + "kty": "OKP", + "crv": "Ed25519", + "x": "mn02E1XyTkaVN6DEOemU5OADMUAUjPHw67oR5KKIM3k", + "kid": "5ecb3da505414c4f" + } + }, + "signature": "Vjgt2d7DVF_KmYdb3UXuOaL4YxRO1k46Uj91QkI5vc0EC5NraQ7U7S58DuD35d8GMy70wW-I08OtkRiCKTfPAQ" +} diff --git a/integrations/xchk-registry/examples/approval-outcome/README.md b/integrations/xchk-registry/examples/approval-outcome/README.md new file mode 100644 index 00000000..02fdea8c --- /dev/null +++ b/integrations/xchk-registry/examples/approval-outcome/README.md @@ -0,0 +1,117 @@ +# xChk sealed receipts as `approval-outcome` references + +A TRACE Trust Record can point at the human decision an act was taken under. These +fixtures show that composition with the sealed receipts of an xChk registry +(): the record carries a `references` entry with +`rel: "approval-outcome"` whose `id` is the receipt's record hash, and the registry +serves the receipt as a bundle at `/api/receipt//bundle` that verifies offline with +no network and no shared secret, down to the approver's own passkey assertion. + +Full mapping and rationale: +[`CROSSWALK.md`](../../CROSSWALK.md). + +Every record here was minted and signed by the registry at `in.xchk.io` for one run of +plate `ENG-WNP3` on 18 October 2026 (`expected.json` names the run and the signing key), +by `scripts/trace-fixtures.js`, part of the registry's own code (not public), which also +fetched each bundle from the public receipt endpoint and made the altered copies. It is not +run here, because the registry is not a dependency of this repository; its record of each +case is `expected.json`. +[`tests/test_approval_outcome_fixtures.py`](../../tests/test_approval_outcome_fixtures.py) +re-verifies all of it on every run without xChk: the TRACE signatures with this +repository's library, each reference digest with `rfc8785`, and each bundle with +`verify_receipt.py`, the registry's standard-library-only offline verifier, vendored one level up +as the registry serves it at (MIT, per its header; listed in +`NOTICE`). Run with no extras, the verifier checks the Ed25519 half of each registry +signature and reports the ML-DSA-65 half as pending, so "bundle verifies" here means no +check failed and the Ed25519 signatures passed. + +## Fixture cases + +Expected results are machine-readable in [`expected.json`](expected.json). Every record +verifies as a TRACE record; what differs is what the reference resolves to and whether the +bundle it resolves to still verifies. A record that does not verify is `record-invalid` before +any of that is read; the test carries `01` with one signed field changed for that case. + +| Record | Bundle | Reference | Digest | Bundle verifies | Disposition | Verdict | +|---|---|---|---|---|---|---| +| `01-approval-confirmed.json` | its own | resolves | matches | yes | `approved` | approval confirmed | +| `02-bundle-altered-after-issue.json` | `record.summary` edited after issue | resolves | **differs** | **no** (record hash) | `approved` | approval contradicted | +| `03-decision-is-a-denial.json` | its own | resolves | matches | yes | `denied` | not an approval | +| `04-no-answer.json` | an ask nobody answered | resolves | matches | yes | `expired` | not an approval | +| `05-reference-unresolvable.json` | none | **no such receipt** | n/a | n/a | n/a | approval unconfirmed | +| `06-assertion-from-another-credential.json` | the approver's key and assertion replaced by another key's | resolves | matches | **no** (binding names a different key) | `approved` | approval contradicted | +| `07-amended.json` | its own; `decision.amendment` present (informational) | resolves | matches | yes | `approved` | approval confirmed, as amended (a worked example, see below) | +| `08-assertion-over-another-ask.json` | the approver's assertion from another approval in the run | resolves | matches | **no** (the challenge the device signed names another ask) | `approved` | approval contradicted | +| `09-re-keyed-outside-the-registry.json` | `01` re-signed under keys that are not the registry's, key list and root statement rewritten to match | resolves | matches | yes (under its own keys) | `approved` | approval consistent, **key not pinned** | + +`02`, `06`, `08` and `09` are the same approval as `01` with the served bundle changed afterwards; the +Trust Record is identical and still verifies, because the record is a pointer and the +tampering is on the thing pointed at. In `06` the assertion is a valid ECDSA P-256 +signature by a key that is not the one the registry's signed binding names for this +credential: an impersonated approver. A verifier that checks the assertion against the +key the bundle offers, and not against the key the binding names, passes it; the bundle's +own `howToVerify` step 5 and the vendored verifier both require the two to be equal. + +In `08` everything about the approver is genuine: the credential is the one the binding +names, the signature verifies with that key, the user was verified. The assertion is the +same person's answer to a different ask in the same run. What tells the two apart is the +challenge the device signed: since 18 October 2026 the registry derives it from the ask +(`approver.challenge`, rule `ask-v1`: the attestation id, the prompt the person saw, the +digest of the action's parameters), and the verifier recomputes it from the bundle's own +`decision` block. A bundle from before that date carries no `challenge`; the verifier +reports that step as pending and the registry's binding is then the only pairing. + +`09` (2 Nov 2026, review of #350 by drk-ram) is `01` re-signed under Ed25519 and ML-DSA-65 keys +that are not the registry's, with the pinned key list and the root statement's key list +rewritten to match (`tests/rekey_fixture.py` rebuilds it; the root's own SLH-DSA signature is +left as it was, which the Python verifier only reports as pending). Every offline check +passes, `--require-approval` included, because every key the verifier checks with is the one +the bundle carries. What tells it from `01` is the registry's key document, +`xchk-keys/in.xchk.io.2026-11-02.json`, saved from `/.well-known/xchk-keys.json` and passed to +the verifier with `--keys`: a key the document does not list fails by name. The test pins that +document as the relying party would; a relying party that pins none can reach no verdict above +"approval consistent, key not pinned", for `01` as much as for `09`. Unlike the other cases +this one is derived, not minted, and its line in `expected.json` was written by hand. What the +document check does not do: compare a retired key's `notBefore`/`notAfter` with the seal's time, +or the document's `registry` with the bundle's `wellKnown` (only key material decides). + +`05` is what spec section 3.1.2 rule 3 requires: a verifier must not reject a record +because a reference cannot be resolved. The record verifies, and the approval it points at +is reported as unconfirmed, which is a different answer from "no approval". + +`03` is a declined ask and `04` an ask nobody answered within its life: both verify, both +are on the record, neither is an approval. `07` was approved with changes. Its label, "approval confirmed, as +amended", is a worked example under the cross-walk's boundary, not an acceptance rule: +`decision.amendment` is informational, and its scope is not yet authenticated against a +signed statement, so a relying party must not let it change what it treats as approved. +What the verifier does check is a refusal: the sealed record's `paramsHash` must recompute +over the amended command (the test recomputes it with `rfc8785`), so an amendment typed +into `01` after issue, or `07`'s amended command edited after issue, is contradicted, +never "as amended". Until the private assessment settles the relying-party contract, the +approval to rely on is of the ask as proposed. + +`anchored.bundle.json` (2 Nov 2026) is one more genuine receipt, approved by the same person on 29 Oct 2026 and +fetched from the registry's bundle endpoint as served. It is not a crosswalk case and `expected.json` does not list +it: it is here because it is the first fixture to carry `anchor.proof` (a batched Ravencoin anchor: the raw +transaction, block header and merkleblock, with this seal's path to the anchored manifest root) and an OpenTimestamps +proof already upgraded to a Bitcoin block. The anchor-chain rows of `verdict-contract.json` name it as their fixture; +the 17 Oct cases predate batched anchoring, so until it arrived those seven guards of the verifier were pinned by no +test (a guard-mutation sweep found them). + +`anchored-unbatched.bundle.json` (3 Nov 2026) pins the other anchor shape: an unbatched anchor, whose transaction +carries the seal hash itself, so the verifier checks that hash in the OP_RETURN instead of walking a manifest path. It +is an allow record anchored on 10 Aug 2026, fetched from the registry's bundle endpoint as served. Every unbatched +receipt with a captured raw transaction was anchored 8 to 10 Aug 2026, before bundles carried the passkey assertion +and the ask-v1 challenge, so strict mode refuses any of them by design (exit 3, nothing failed); +`verdict-contract.json` lists it under `defaultModeFixtures` and its row runs in the default mode. + +## Running the checks + +``` +pytest integrations/xchk-registry/tests -q +``` + +Regeneration is the registry operator's: the generator runs on the registry with the seal +key and writes this directory. A new run points at new receipts and replaces every file; +`09` is then rebuilt from the new `01` with `tests/rekey_fixture.py`, and the key document is +saved again from the registry. diff --git a/integrations/xchk-registry/examples/approval-outcome/anchored-unbatched.bundle.json b/integrations/xchk-registry/examples/approval-outcome/anchored-unbatched.bundle.json new file mode 100644 index 00000000..473a26f4 --- /dev/null +++ b/integrations/xchk-registry/examples/approval-outcome/anchored-unbatched.bundle.json @@ -0,0 +1,197 @@ +{ + "format": "xchk-receipt-bundle/2", + "issuer": { + "name": "xChk registry", + "base": "https://in.xchk.io", + "servedAt": "2026-11-04T03:13:36.737Z", + "headline": "FIN-RKPC: ALLOW terminal in global at 2026-08-10T19:28:21.107Z." + }, + "recordHash": "02c97e5bcb50e28198a908eeb3d8509aeedc7dd90ace6a227bacb9cfc68ae65c", + "record": { + "v": 1, + "agentId": "6a778719293eca43c21a24d8", + "plate": "FIN-RKPC", + "seq": 2273, + "ts": "2026-08-10T19:28:21.107Z", + "harness": "claude", + "runSeq": 39, + "runRef": "FIN RKPC.39", + "area": "global", + "tool": "terminal", + "summary": "grep -n \"function buildWall\" -A 30 pewpew.html | head -40", + "paramsHash": "1fd294f7d16ed07048e23f3caba904483c5e7a950a1c488608db0f919fed1c30", + "amount": null, + "disposition": "allow", + "code": null, + "reason": null, + "deskCondition": "normal", + "continuityClass": "standard", + "authRef": "c7d748f61fbd6dee43e67282", + "prevHash": "9f1705bd33f913e8d52808eedd9a1a7c5b0f599c0fc97a06c1ecefe2301dfbca", + "rvnBlock": "000000000009c36a5a3225df6b2084ecc4bd222b939f47510a748a6243d613df@4491987" + }, + "canonicalization": { + "profile": "JSON with object keys sorted (code-unit order), no whitespace, scalars as JSON.stringify would emit them, undefined omitted, integers only; hash = sha256 over the UTF-8 bytes", + "hashedConditionalKeys": [ + "rvnBlock", + "approverEmail", + "authMethod", + "requiredAuthMethod", + "attestationId", + "attestationHash", + "photoUrl", + "labelsHash", + "delegationHash", + "model", + "tokensIn", + "tokensOut", + "tokensCacheRead", + "contextPct", + "actor", + "surface", + "chargeCode", + "workspace", + "policyHash", + "outcomeOf", + "resultHash", + "endedAt", + "artifactHash" + ], + "note": "conditional keys are present only when the record carried them; absent keys are absent from the bytes, not null" + }, + "merkle": { + "proof": [ + { + "side": "R", + "hash": "9cdbc3ab0a2a9bbe7d39d3d52d29d6f6a8c9708a6cca52d724cc44f7c7f1d670" + }, + { + "side": "R", + "hash": "fb0b6efd63c0bd8b0a80be72373fb2c3eab1b825dcd7cadb7e96c2c6bcf86226" + }, + { + "side": "R", + "hash": "9a221f0d555a6168b20c19085a94df34684ecdc9b59fe0b655eb204d036fecab" + } + ], + "leafCount": 6, + "rule": "node = sha256(left_hex + right_hex) over the hex strings; an odd node is promoted unhashed; the leaf is the record hash" + }, + "seal": { + "v": 1, + "agentId": "6a778719293eca43c21a24d8", + "plate": "FIN-RKPC", + "sealSeq": 505, + "windowStart": "2026-08-10T19:25:26.634Z", + "windowEnd": "2026-08-10T19:30:26.634Z", + "count": 6, + "issuedCount": 6, + "seqStart": 2273, + "seqEnd": 2278, + "merkleRoot": "af972febe8e37e506cb1a9887ad2310306e2157aa5adc53b70d8d9fa560ec1f0", + "deskCondition": "normal", + "prevSealHash": "e31cc11afb6bff65250f86dcbc533e71bd669e197f6e4aaa2efe7eb5887c9023", + "rvnBlock": "000000000009c36a5a3225df6b2084ecc4bd222b939f47510a748a6243d613df@4491987", + "sealHash": "a7015b9dc14d4afd7ac4ba32553c492df41ba04f894e01bf0d3dbb60bc757d9d", + "rule": "sealHash = sha256(canonical({v, agentId, plate, sealSeq, windowStart, windowEnd, count, issuedCount, seqStart, seqEnd, merkleRoot, deskCondition, prevSealHash[, rvnBlock][, profileHash]}))" + }, + "registrySignature": { + "alg": "ed25519", + "keyId": "5ecb3da505414c4f", + "signature": "bwAp2zdbU0tDSHafB2t/oKO/dzcLb0fZVrs9Sbft+LomiC05qCvmGIMmD7uwge9lxE2jmwzcKaXm1+XGmX2HAQ==", + "signedAt": "2026-09-16T11:40:41.720Z", + "signedOver": "the UTF-8 bytes of seal.sealHash", + "publicKeyRaw": "mn02E1XyTkaVN6DEOemU5OADMUAUjPHw67oR5KKIM3k=", + "publicKeyPem": "-----BEGIN PUBLIC KEY-----\nMCowBQYDK2VwAyEAmn02E1XyTkaVN6DEOemU5OADMUAUjPHw67oR5KKIM3k=\n-----END PUBLIC KEY-----\n", + "wellKnown": "https://in.xchk.io/.well-known/xchk-keys.json", + "keys": [ + { + "alg": "ed25519", + "keyId": "5ecb3da505414c4f", + "publicKeyRaw": "mn02E1XyTkaVN6DEOemU5OADMUAUjPHw67oR5KKIM3k=" + }, + { + "alg": "ml-dsa-65", + "keyId": "8bb85bc1f41c568c", + "publicKeyRaw": "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" + } + ], + "retired": [], + "publicKeyRawPq": "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", + "keyIdPq": "8bb85bc1f41c568c", + "root": { + "alg": "slh-dsa-sha2-128s", + "standard": "FIPS 205", + "keyId": "acc7ad1aeb3ef177", + "publicKeyRaw": "4aIhDuj3TZPwqb9HT8TzVJnkvle4jVUMhWkn/BfmypM=", + "statement": { + "v": 1, + "registry": "https://in.xchk.io", + "keys": [ + { + "alg": "ed25519", + "keyId": "5ecb3da505414c4f", + "publicKeyRaw": "mn02E1XyTkaVN6DEOemU5OADMUAUjPHw67oR5KKIM3k=" + }, + { + "alg": "ml-dsa-65", + "keyId": "8bb85bc1f41c568c", + "publicKeyRaw": "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" + } + ], + "retired": [], + "oidc": [ + { + "kid": "XWUv0uGESGdIG1MjOzbVjcwxB0CYtK0oZ9SZxNkH7h8", + "kty": "RSA", + "alg": "RS256", + "n": "zQwdJyTuyqQvB5zIXp9ULjX22k-R95Ls5j3IVUwLcI87I2VPUjsvy9oDGl5cq8Jl7Rt21d966AakANr8J1vT7gMpcmPOcEGVDdgdCprRs8cWNDo5uJ4ejt1LW65zRqW8xsxqHPm1aOxvjeUQfNgZFLn3VlSX01zgjggBLSwL18stLbyIzA2zcj4lpV-IrnBO3S6VUusoaO__kXjHv1-aH64wpVcsNLrBX6MWsnHM-KptbhKrk_qqXMJ7dokBxiIAH32VjZ73kTbVcSXoU2FshM_eQaonhYcRoD8PTXN3rxMaisj2pka9XZ1Apqy-EHf1dCoUphYxd_--FcT5PDQZaQ", + "e": "AQAB" + } + ], + "issuedAt": "2026-11-04T02:57:45.938Z" + }, + "signature": "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", + "rule": "SLH-DSA-SHA2-128s verify(publicKeyRaw, canonical(statement) bytes, signature); statement.keys are the keys this registry signs with" + }, + "rule": "Ed25519 verify(publicKeyRaw, sealHash bytes, signature). The key is pinned here; a reader with a network can confirm it against wellKnown." + }, + "approver": null, + "basis": null, + "decision": null, + "legalHolds": null, + "anchor": { + "rvnTxId": "d3bc04ae76c82825aae063f422e80bd7f9605dfe31e98bcfc8b56a974dfe3939", + "rvnAnchoredAt": "2026-08-10T19:30:27.309Z", + "rvnBlock": "000000000009c36a5a3225df6b2084ecc4bd222b939f47510a748a6243d613df@4491987", + "explorer": "https://ravencoin.network/tx/d3bc04ae76c82825aae063f422e80bd7f9605dfe31e98bcfc8b56a974dfe3939", + "proof": { + "txid": "d3bc04ae76c82825aae063f422e80bd7f9605dfe31e98bcfc8b56a974dfe3939", + "txHex": "0200000001ac8a55744cb3c47a3e09f060703c1bce7a9eeb6885037a98b419e65e18e8928c010000006b483045022100fe6febb8ae0473df255be0e0e6767a3886f509cf774dea8df452230f5ce95f46022009c2cf172c6e593822d3c20ec05c9ad163484e56d95472ec21ad957a253c3354012102ec67849f5df4099ea26e70374005f389c17d405a20393e5901bce7975a291e58feffffff0200000000000000004b6a4978436b020836613761a7015b9dc14d4afd7ac4ba32553c492df41ba04f894e01bf0d3dbb60bc757d9de31cc11afb6bff65250f86dcbc533e71bd669e197f6e4aaa2efe7eb5887c9023786ad9f5160000001976a914faec6a44022d8146cb11bc68a188e0ada8e68aac88ac00000000", + "blockHash": "000000000003f62688f19fdb7074210e9db516e34df6397593f1f0d6add9f262", + "blockHeight": 4503603, + "blockTime": "2026-08-21T11:25:18.000Z", + "headerHex": "00000030001a98c5945e3cca497e099674c38917fa2b1559fdfcc97636a101000000000009380b225d25b1b195e8a23b04f6db8773455623f63fceb11a65c78ddd1ade1c9e35886ae4c0051b33b84400c2a5b1f3e94cf0162e563bffaf7ff35745bb17a5a9d124cea8d6c1a6b4e060ccbc4031e66258a6ea", + "merkleRoot": "1cde1add8dc7651ab1ce3ff62356457387dbf6043ba2e895b1b1255d220b3809", + "merkleBlockHex": "00000030001a98c5945e3cca497e099674c38917fa2b1559fdfcc97636a101000000000009380b225d25b1b195e8a23b04f6db8773455623f63fceb11a65c78ddd1ade1c9e35886ae4c0051b33b84400c2a5b1f3e94cf0162e563bffaf7ff35745bb17a5a9d124cea8d6c1a6b4e060ccbc4031e66258a6ea0500000004fc6e218700a7087371004e106e9bb5d458c3c25cc639894c0d2b52aba8a5337fac8a55744cb3c47a3e09f060703c1bce7a9eeb6885037a98b419e65e18e8928c3939fe4d976ab5c8cf8be931fe5d60f9d70be822f463e0aa2528c876ae04bcd3b439a29f00041037321a966eee882b70873a6dd8a1a4226ec9eae6ed4a80affd012b", + "capturedAt": "2026-09-17T12:46:46.972Z" + }, + "rule": "proof.txHex is the raw anchor transaction: its OP_RETURN payload is \"xCk\" + version + flags + 4 id bytes + hash(32), where hash is sealHash, or — when anchor.manifest is present — the manifest root that anchor.manifest.path reaches from sealHash (side L: sha256(sibling + current); side R: sha256(current + sibling)); sha256d(txHex) reversed = proof.txid; sha256d(headerHex) reversed = proof.blockHash; proof.merkleBlockHex is a Bitcoin-style merkleblock whose partial Merkle tree reproduces the header Merkle root and includes txid. The one outside fact left: that blockHash is on the Ravencoin chain." + }, + "howToVerify": [ + "1. canonicalize `record` per `canonicalization.profile`, sha256 it, compare to `recordHash`", + "2. walk `merkle.proof` from `recordHash` (L: sha256(step+cur), R: sha256(cur+step)); the result must equal `seal.merkleRoot`", + "3. canonicalize the seal fields per `seal.rule`, sha256 it, compare to `seal.sealHash`", + "4. verify every entry of `registrySignature.signatures` over the seal hash with the key of the same alg/keyId in `registrySignature.keys` (Ed25519 + ML-DSA-65 when hybrid); older bundles: Ed25519-verify `signature` with `publicKeyRaw`", + "5. if `approver` is present: verify the WebAuthn assertion with `approver.publicKey.raw`, then verify every entry of `approver.binding.signatures` over canonical(`approver.binding.fields`) with the registry keys as in step 4, requiring each algorithm `binding.fields.signing` names when present (older bundles: Ed25519-verify `binding.signature`), and require `approver.binding.fields.publicKey` to equal `approver.publicKey.raw`: the binding, not the bundle, names the key the assertion may be checked with; when `approver.challenge` is present, recompute base64url(sha256(canonical(`challenge.fields`))) and require it to equal `clientDataJSON.challenge`, with the fields equal to `approver.attestationId`, which must also equal `record.attestationId` and `binding.fields.attestationId`, `decision.prompt` and `decision.actionParamsHash`", + "6. if `anchor.proof` is present: check the OP_RETURN (the seal hash, or the manifest root that `anchor.manifest.path` reaches from the seal hash), the txid, the header hash and the merkleblock; else look up `anchor.rvnTxId` on any Ravencoin explorer", + "8. if `seal.profileHash` is present: `profile.document` must be present, sha256(canonical(document)) must equal it, and `profile.signature` must verify over the hash with the registry keys; absent profileHash = sealed before profiles", + "7. if `basis`/`decision` are present: `basis.asked.recordHash` is another record on the same chain (fetch its bundle and run steps 1–4); `decision.attestationHash` equals `record.attestationHash`; when `decision.amendment.command` is present (approved WITH CHANGES), `record.paramsHash` must equal sha256(canonical(`amendment.boundAs`)) with `boundAs.command` equal to the amended command, and, when `decision.actionParamsHash` is present, `amendment.originalParamsHash` must equal it (approver.rules has the detail): the sealed record, not the readable amendment text, says what ran; the passkey covers the ask as proposed and the amendment rests on the registry seal" + ], + "profile": null, + "verifier": { + "html": "https://in.xchk.io/verify-receipt.html", + "python": "https://in.xchk.io/verify/verify_receipt.py", + "license": "MIT" + } +} \ No newline at end of file diff --git a/integrations/xchk-registry/examples/approval-outcome/anchored.bundle.json b/integrations/xchk-registry/examples/approval-outcome/anchored.bundle.json new file mode 100644 index 00000000..bbce9da5 --- /dev/null +++ b/integrations/xchk-registry/examples/approval-outcome/anchored.bundle.json @@ -0,0 +1,422 @@ +{ + "format": "xchk-receipt-bundle/2", + "issuer": { + "name": "xChk registry", + "base": "https://in.xchk.io", + "servedAt": "2026-11-02T05:32:04.561Z", + "headline": "ENG-WNP3: APPROVED terminal in global at 2026-10-29T14:13:36.956Z — approved by sean@maclawran.ca." + }, + "recordHash": "3bc674cd2218dbc323cfda5fadc0dffb8e4b0e0c0d902fcad7d820abe445bdc0", + "record": { + "v": 1, + "agentId": "6acbf860a627414b66045478", + "plate": "ENG-WNP3", + "seq": 28267, + "ts": "2026-10-29T14:13:36.956Z", + "harness": "claude", + "runSeq": 3155, + "runRef": "ENG WNP3.3155", + "area": "global", + "tool": "terminal", + "summary": "cd /Volumes/2TB-FAST/sean-overflow/src/xchk/xchk-mobile && python3 - <<'EOF'\nimport re\nsrc = open('src/app/(app)/addresses.tsx').read()\n# a component, not a screen: no router, no SafeAreaView, no back header\nsrc = src.replace(\"import { router } from 'expo-router';\\n\", \"\")\nsrc = src.replace(\"import {", + "paramsHash": "89eabdeb5917a7cd4499dcf48e6f1b81f7ee68c18932030e1101f76332e0d703", + "amount": null, + "disposition": "approved", + "code": null, + "reason": null, + "deskCondition": "normal", + "continuityClass": "standard", + "authRef": "f121055255d093ef751b7bf3", + "prevHash": "7a1a772cc3baecf8dcde1a42c83b9be8474d1501ff54b15f449512f45ac6189c", + "rvnBlock": "000000000000d301a85d416d3c101c3b575fb403b208f72d9c54ce1de00d4fd9@4602433", + "approverEmail": "sean@maclawran.ca", + "authMethod": "webauthn", + "attestationId": "6ae3547fda55b3109d3ae9e8", + "attestationHash": "2e9763100632884a54440bc2305cec220b850c17df66ae0e50956f14cc74db12", + "photoUrl": "https://xchk-main.s3.us-east-005.backblazeb2.com/xchk/xchk/baseline/att_6ae3547fda55b3109d3ae9e8/0.jpg", + "model": "claude-fable-5-1" + }, + "canonicalization": { + "profile": "JSON with object keys sorted (code-unit order), no whitespace, scalars as JSON.stringify would emit them, undefined omitted, integers only; hash = sha256 over the UTF-8 bytes", + "hashedConditionalKeys": [ + "rvnBlock", + "approverEmail", + "authMethod", + "requiredAuthMethod", + "attestationId", + "attestationHash", + "photoUrl", + "labelsHash", + "delegationHash", + "model", + "tokensIn", + "tokensOut", + "tokensCacheRead", + "contextPct", + "actor", + "surface", + "chargeCode", + "workspace", + "policyHash", + "outcomeOf", + "resultHash", + "endedAt", + "artifactHash" + ], + "note": "conditional keys are present only when the record carried them; absent keys are absent from the bytes, not null" + }, + "merkle": { + "proof": [ + { + "side": "L", + "hash": "7a1a772cc3baecf8dcde1a42c83b9be8474d1501ff54b15f449512f45ac6189c" + }, + { + "side": "R", + "hash": "3622cdb4f1fcf707316a534aeccbd08a5ab33ba7cfb77425bd0c8f7580e9b742" + }, + { + "side": "L", + "hash": "fe77fe106c891d8f6e2255880567341f049c333cc23e073471b6cedd9a60e6bf" + }, + { + "side": "L", + "hash": "85dfcd491d74acbfeeb4d4fa5545a499c025e96d96496c2b6a494da067d19475" + }, + { + "side": "L", + "hash": "7f84d572480b1283c01d1f42d83ec141e608e2e927c309816ff7d02eb9d75c17" + }, + { + "side": "R", + "hash": "b6adef791cbb06583b43784630fe2d79a2e8ce20959ac7916899e62a89a1ff61" + }, + { + "side": "R", + "hash": "0e8b369f118f0738e94f5900fec0e6a1ccef9fe344b01c943a64a6a70f7ec087" + } + ], + "leafCount": 67, + "rule": "node = sha256(left_hex + right_hex) over the hex strings; an odd node is promoted unhashed; the leaf is the record hash" + }, + "seal": { + "v": 1, + "agentId": "6acbf860a627414b66045478", + "plate": "ENG-WNP3", + "sealSeq": 4543, + "windowStart": "2026-10-29T14:10:20.371Z", + "windowEnd": "2026-10-29T14:15:20.372Z", + "count": 67, + "issuedCount": 67, + "seqStart": 28238, + "seqEnd": 28304, + "merkleRoot": "41a1b02a90911cfa51c981e0f0359242a2be2e5b72f2028fda9a1e3d582ee98b", + "deskCondition": "normal", + "prevSealHash": "e8ba411548675cc381d31d1186cd3e13f0c25cc7baf42d68ff07b74e077bdbd2", + "rvnBlock": "00000000000019eff1378d25dd9f4d129bfd76c7177d0b558d11018dfa4f1088@4602434", + "profileHash": "9bbe0635c0a05cc8107d40ad5bb2d8b227c8125d395f41620bcd371123319701", + "sealHash": "22c0710c0a8ec0bed3e1694907652aaa549895660563b445a0a712c27a4e8056", + "rule": "sealHash = sha256(canonical({v, agentId, plate, sealSeq, windowStart, windowEnd, count, issuedCount, seqStart, seqEnd, merkleRoot, deskCondition, prevSealHash[, rvnBlock][, profileHash]}))" + }, + "registrySignature": { + "alg": "ed25519+ml-dsa-65", + "keyId": "5ecb3da505414c4f", + "signature": "dfbgkk0GAxxXLE6hJmhy+gVvcR0CdhceVDtl+RIPvD/WFeNpiIf6Cj+mjFTYwQTiM+LftudcO5+7+2L4cwPLCQ==", + "signedAt": "2026-10-29T14:15:20.386Z", + "signatures": [ + { + "alg": "ed25519", + "keyId": "5ecb3da505414c4f", + "signature": "dfbgkk0GAxxXLE6hJmhy+gVvcR0CdhceVDtl+RIPvD/WFeNpiIf6Cj+mjFTYwQTiM+LftudcO5+7+2L4cwPLCQ==" + }, + { + "alg": "ml-dsa-65", + "keyId": "8bb85bc1f41c568c", + "signature": "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" + } + ], + "signedOver": "the UTF-8 bytes of seal.sealHash", + "publicKeyRaw": "mn02E1XyTkaVN6DEOemU5OADMUAUjPHw67oR5KKIM3k=", + "publicKeyPem": "-----BEGIN PUBLIC KEY-----\nMCowBQYDK2VwAyEAmn02E1XyTkaVN6DEOemU5OADMUAUjPHw67oR5KKIM3k=\n-----END PUBLIC KEY-----\n", + "wellKnown": "https://in.xchk.io/.well-known/xchk-keys.json", + "keys": [ + { + "alg": "ed25519", + "keyId": "5ecb3da505414c4f", + "publicKeyRaw": "mn02E1XyTkaVN6DEOemU5OADMUAUjPHw67oR5KKIM3k=" + }, + { + "alg": "ml-dsa-65", + "keyId": "8bb85bc1f41c568c", + "publicKeyRaw": "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" + } + ], + "retired": [], + "publicKeyRawPq": "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", + "keyIdPq": "8bb85bc1f41c568c", + "root": { + "alg": "slh-dsa-sha2-128s", + "standard": "FIPS 205", + "keyId": "acc7ad1aeb3ef177", + "publicKeyRaw": "4aIhDuj3TZPwqb9HT8TzVJnkvle4jVUMhWkn/BfmypM=", + "statement": { + "v": 1, + "registry": "https://in.xchk.io", + "keys": [ + { + "alg": "ed25519", + "keyId": "5ecb3da505414c4f", + "publicKeyRaw": "mn02E1XyTkaVN6DEOemU5OADMUAUjPHw67oR5KKIM3k=" + }, + { + "alg": "ml-dsa-65", + "keyId": "8bb85bc1f41c568c", + "publicKeyRaw": "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" + } + ], + "retired": [], + "oidc": [ + { + "kid": "XWUv0uGESGdIG1MjOzbVjcwxB0CYtK0oZ9SZxNkH7h8", + "kty": "RSA", + "alg": "RS256", + "n": "zQwdJyTuyqQvB5zIXp9ULjX22k-R95Ls5j3IVUwLcI87I2VPUjsvy9oDGl5cq8Jl7Rt21d966AakANr8J1vT7gMpcmPOcEGVDdgdCprRs8cWNDo5uJ4ejt1LW65zRqW8xsxqHPm1aOxvjeUQfNgZFLn3VlSX01zgjggBLSwL18stLbyIzA2zcj4lpV-IrnBO3S6VUusoaO__kXjHv1-aH64wpVcsNLrBX6MWsnHM-KptbhKrk_qqXMJ7dokBxiIAH32VjZ73kTbVcSXoU2FshM_eQaonhYcRoD8PTXN3rxMaisj2pka9XZ1Apqy-EHf1dCoUphYxd_--FcT5PDQZaQ", + "e": "AQAB" + } + ], + "issuedAt": "2026-11-02T03:01:07.385Z" + }, + "signature": "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", + "rule": "SLH-DSA-SHA2-128s verify(publicKeyRaw, canonical(statement) bytes, signature); statement.keys are the keys this registry signs with" + }, + "rule": "HYBRID: for each entry in signatures, verify(keys[alg,keyId].publicKeyRaw, sealHash bytes, signature) — Ed25519 for alg ed25519, ML-DSA-65 (FIPS 204) for alg ml-dsa-65; ALL must verify. keyId = sha256(SPKI or raw key)[:16]. root, when present, is the SLH-DSA-SHA2-128s statement of these keys." + }, + "approver": { + "email": "sean@maclawran.ca", + "authLevel": "didit", + "authMethod": "webauthn", + "identity": { + "provider": "entra", + "tenantId": "9c592cb8-bcbe-4dad-94c6-66d89526a4ac", + "subjectId": "fe7c5241-a2c1-448d-badb-3e723d3aee31" + }, + "attestationId": "6ae3547fda55b3109d3ae9e8", + "credentialId": "Yqa88hkURHnPqSTiV3o1jA", + "publicKey": { + "format": "ec-p256-uncompressed", + "alg": "ES256", + "raw": "BIWcVSzcT4ocdVb/bHtVrZNK/4RKRn1xhg6SE8TSy3QGpnJUufsDz2z+G1PqK3yP/7q5IPI9PEfjC77W/OxqD5k=" + }, + "assertion": { + "clientDataJSON": "eyJ0eXBlIjoid2ViYXV0aG4uZ2V0IiwiY2hhbGxlbmdlIjoidDBfNmFPN2RqeHItR3hJZ2lLOFRpRjh5b1pRX2F3dVA2aWJ1eHNpb0k4MCIsIm9yaWdpbiI6Imh0dHBzOi8vaW4ueGNoay5pbyIsImNyb3NzT3JpZ2luIjpmYWxzZX0", + "authenticatorData": "dcRETaEWF68z8NRCzR6PN99N5Mn8aYw-RadnYwZSFr0dAAAAAA", + "signature": "MEQCIA6dRZOhJgL_9Ct4zCXNFUWBA6n89ov2GJ3FGmCVAh-YAiA3ZhMm8A88rd-EHqo7_KoL9Pgqux_dZLhnuUXOZGj-kQ", + "encoding": "base64url" + }, + "challenge": { + "rule": "ask-v1", + "fields": { + "v": 1, + "attestationId": "6ae3547fda55b3109d3ae9e8", + "prompt": "ENG-WNP3.3155 (via Claude Code) wants to cd /Volumes/2TB-FAST/sean-overflow/src/xchk/xchk-mobile && python3 - <<'EOF'\nimport re\nsrc = open('src/app/(app)/addresses.tsx').read()\n# a component, not a screen: no router, no SafeAreaView, no back header\nsrc = src.replace(\"import { router } from 'expo-router';\\n\", \"\")\nsrc = src.replace(\"import {", + "actionParamsHash": "2384d7b017afc6cb318da59b7532fe89db7f68323d6e69168171c7cc50048ea3" + }, + "expected": "t0_6aO7djxr-GxIgiK8TiF8yoZQ_awuP6ibuxsioI80", + "note": "the challenge the approver's device signed = base64url(sha256(canonical(fields))); fields are the ask as issued, before any answer; recompute, do not trust `expected`" + }, + "binding": { + "fields": { + "v": 1, + "recordHash": "3bc674cd2218dbc323cfda5fadc0dffb8e4b0e0c0d902fcad7d820abe445bdc0", + "attestationId": "6ae3547fda55b3109d3ae9e8", + "credentialId": "Yqa88hkURHnPqSTiV3o1jA", + "publicKey": "BIWcVSzcT4ocdVb/bHtVrZNK/4RKRn1xhg6SE8TSy3QGpnJUufsDz2z+G1PqK3yP/7q5IPI9PEfjC77W/OxqD5k=", + "approverEmail": "sean@maclawran.ca", + "authLevel": "didit", + "authMethod": "webauthn", + "verifiedAt": "2026-10-29T14:13:36.833Z", + "identityProvider": "entra", + "tenantId": "9c592cb8-bcbe-4dad-94c6-66d89526a4ac", + "subjectId": "fe7c5241-a2c1-448d-badb-3e723d3aee31" + }, + "signature": "/+gqJ0c+WI9qOWM3ZNcfPEO3L56EhGoq89rwQA24SQ8NUmdvXAVQLC/1aXWzlYEcZdtWXb3gtaNtvo4LcZOxBw==", + "keyId": "5ecb3da505414c4f", + "signedAt": "2026-11-02T05:32:04.556Z", + "alg": "ed25519+ml-dsa-65", + "signatures": [ + { + "alg": "ed25519", + "keyId": "5ecb3da505414c4f", + "signature": "/+gqJ0c+WI9qOWM3ZNcfPEO3L56EhGoq89rwQA24SQ8NUmdvXAVQLC/1aXWzlYEcZdtWXb3gtaNtvo4LcZOxBw==" + }, + { + "alg": "ml-dsa-65", + "keyId": "8bb85bc1f41c568c", + "signature": "SPKyIaCG/4yP/1i9ekoE8ncIuScbvZljvmEUqMDBKnqz9QqgRLDsmAMBBHRR1sDqxE8QBgJ20+eAEtelsB1yPK7mh49NkvYPyIowJ6Ci76z0hjFX/y2h8Um6wqJSmglx//dXHjnMzvITlmYgmso/zQ/9M7rfgdHABH+kuiwGqoU87k99Z+TIGgH4fgPw6lFexHbxalaIver0TejBiWKt3LEuaMpeWkuC1fYb1oDgg6b2VUAJ377puHdL7tU7joWuKJLSPczzwaxdUAfRewaIvp/neFzybFlOBoR9H7PhpdofQ6cJvYrAZArspeC+XiuJJQA42YGrkWhwUs2/fYD6W3FHfmXyyPQXvEj3EQjH98cVUIP6MCpI76+BGhyEWsbPKGdy30OoO1Mxa3IfIu82ox2BwMJ0VTUQ4EORMdjTxD3nJUvyYuoQVBrNXI4q8/oAesscjg6jSEXGUzQ4/4AR695ytqG//KPuoYB9Mbkl+BAydErZQhzS3Dt+POfhby7FQpCU5Cia6fbDFpjsyam66t/9fyaFc5wsz0p9t9WtsTkOy3dPLDdv8DSU01FYK3jC18KAfg+hHEYaTYNKo5vqKeGX2vLHOg1nceP1KIuabhUE3cKtP808d15oZ58NlzbKivSPeTNIZwi2auWtK46H0BrF9cq/gkuZBHq2i6r8nZjq8oH4ttdwiErkJg2tm5UUfxkNBZMNSDf4PFPdFMdZ+kzkLzqvozgxtWhLgDpg909ze74eBL114MML5rtXqHKHt2xnsyjE3XTxZ/35eRM2gkRqG2aZnxDn0wZ2O4iXmVdKFEWzyzKjXcGwfErYHt+WTC8vQbG86S4xfKc+oteFg9j7OCsa1pbkl8dO0+J86tOB6l8L6xxQtXrjpKIrMTPVUfEVSgXYEVoQY4mLFbLs8NcuBbo+WpCs5nptXewMmEqtAz6QJe33Cxe/6Wa3sf+FFO8IwS84n9KfpmIKGaJDIoHY6yO/p2GTMfDhOemvIYXvzI7/18fH9TyDabvA2hd6qx8BUc3hxv9k7ketAg+r9nA/OB87fAHXWCFRR3hLacj0vkAp846eM2nU7kss6ZwKe5W1X6YoDbgH7UzSxXo9vKm2Ai3QMzT2dnysesx7RZqrwgDA4h03dZuxIsnk96MIyVWRoH+HLZXqc0YLKjOBpRNJ7XK5OfpCzwGNDAfF60zL5ZQjueXY97gcBQZA7YXhOawzfdXgQ/XEJ3n9Mhu9tkKBhhxB95ShdA+3MlE1lLoJfDx7PslumITAek2+pugYxkWa0VxyHXQ982tpVB8m72x37FDB/AHaNnOxu+jkeCDBLVmS4maJSUlVfO6hBqfkWTUR/Tqu6CkCqhyno7usgrekA2B8hyJadlWEivR1wjx8rQKvt5+NEKnaduLYLQcyEEzBiTG35+oZUa3hKe+1b9yPVoL/4GKA3BIY2Rr0ORmsbFN0RUZP048Si71J2se1CVcyAHa1u11Fngr9XLINOl1SQD1pVowtoqDCHtOEYCKMk57zOQ8IGqThg4Yksi5KY3Rfu8SbpptwpCvndR8563UG9QT3WPiscK9b1RjsqKgbpwhA4RaCgLknKx3rd0+ezMBcDWfUkcnNaVd9H/IrIYyXsQy2Afp/+J6z4PeXZPFljvxUPuAhC4CMovXarqOsCWvHKYUsPsv6ORlk8tJVNcumNierosbuxcdI2OlmwYSLCS23mId9olCCu1+NSHGLwtvA8vTvbSLu9ppbuN3OGy62R4NLjDDcNunndF1vPNEhNiqdSTNtdh5rvUV61x2QmgrjkTO92L9UPYvyKh3Od+A/jpyZW0KVYJ7M7rIHIWYh1IbLE7ARsIcG/6+cx1pHuSgTHlaVbuF5W0I+2xbcOBSHsP3O5dzgs6QyeCrd0F8UmhywBUQrdlmDYUUb1OPFa0QD8DOIKp/Avox7wGI2wBcIui9BijzOZ6jmO47YfCCsKYIfHOAZ+uVvzDXWQIVzDhx+7FkabiOnreTSsMyRWpuaC1DsRrWbn4/iRVnVhC0dP01hJDhsq5anCz1LEOpLmXsAsT9LVCFl3auRWxeAJS7xytosWnzpqh2gBWnUAxmJennR63j5sIcp8z6XdXmXeshVI++Ujrd2KSVqDoibZAv/3hvUhOCVwRPDUZF/97484flac7CZosN9cWWB8vSMQ4y4rFEBF0anrQ98TkDBIUeDTlY+m53Xx414Kgqei4q80JRgySPvTFDAHFGactyHQsQeU/Qc0bCJPijr7VuPV9z6mqaUYF6jII24yJcN/KdaBawtQIBwQePb9SitA5/1hMmEazvmF2u5pzKNaYZIJ/YQGiUSNOw6Ab4CM7sbnE/U53X8Nbe6XZ13QKvVzDjxq2ecRL/SmxNl0doCfzJo+utrpIVa6mt4xpssz1cM7DlD46QBZ55a61r+MYt+OwDi/trXRrlce+quT56OJ+S+RwZzUvDH/s8La4lAnsX4K+DhLWXi5uRcG3s9i3vz/1yG2QnUqO3/CMWHdcg/pKBMp34CTFJQpNfhGbRabC9o1NsqY+NOaG+PXfFObPHNgIOKZXlLpucKHsB+v/FY8ZHTgPibjh+DlGH+3ze/crWRPxfz6zTxDfVZbTObjn4YqtaH5wJ8hKxIDlckbJYhHp/jbFb1tipBLMudjaSY9Q2pXWL/SPkfnyXJVWX+dBZ7KGsrq3x4elSONnVjH4EFeDpe4YS5+fM5QZ6ZcSbtTdp6PwOvtBSxyfMUI0W2i/rw8eJOaEitMEOqhIxRQz2BoyUHQbCDRnz0B+jO/81cSScVzAWEPt90fijcSzmV06gqonK5477jB96xhJd170qcI+Bb7nGy8kje3I6/xAJI2anSquY6JAHG7re1DhuxIpcW8hravWan3WnEVHI2wgDJ7LB6SWRmpgYAhSUFcsjY/N7T5FsXwT89bGdlrhq6knl5di3WlU58JXPIUr77jvaoqXYMtiGQQjtc13SkAixem0JXU3BR56lcWyww/OWRoErVD3Q0ANvqWig3KJK4PHTr0EcfcvDMEF1gNlP6Xkvb8i6RuBhcYJXFl+utmO7ci+hPHdobs7BNsjlf/lYJ76Sm8dGpKNeE6SD2sDx291r/I1BzrX+4LkGJY2RTr+m4PHEE0Q5q9Pcso1ld0WR2pO/mAsmlKoFcuS25WcTCptzsPqPibztsFS1AtuVV9QDcr/aN/vFSs5Giqig6xztSI+T+sHpLFDnfWF4xHq6vB063dV0Xw15ph8GynO5kaA+U8zHzunpedlevjdE5I9LZXpW3aGWxnFP4O/29m8uiNXgKUe6F3C4m31eMl/WtVJ+JJim4dqR3MxVkDSQWApmxjZk0LFFLerzDzWyopPKoF1OkN7RdPaJwa/OvOEzStglsseQAyd3+SJ/NebdxnQ7p8B0u4HMSM4R1efn4c0PVX0qYaV7acZv6OPU2bPvArBbNcqvIyE4rG5VP5347fJYn2glfwARizqIrqr4hQT/bGR0sbscQdcH/zJSArxqt4CeKzRn3Q+6yk3HfEf6JxbVyUP543b9EJD3TXzrIxXHJFaSyCzY5et8O0R5ZJL/exGEjJIMSWbcLxdtfTLLAY1DNhOfpnkwOs9vPZ4fenarXi8LTFOxqtwBBsRIyRoiaUKavS4rUL37JJU8YCcwGuB6a3MjZGaJaDiDcDfxJ3c/F/Kx8qVaqRfqup18ZfmyDTTOrhgY82cw7zXqUBmEn2Wduohvbb+wA9uis7O2MFvvP2t6ZpVeklZTsmHuGfBhi4kYojj3n+gOO6a3M2VEFH9aAoSdU/UQe0ELaMJ8kx3flOfsUxsaOvO2rAFykVpQKk2ZiBSNa5t9cI16F8T7DurEYylpOnmRoBtUUki/8IMEg901TkTdPH0KT/Dc5jsgpPZlIIx5VQxEzX1+VkrzSaPG3syCiO+iL7k+pTwZMNxyHHnkgDH9Nlxg8bZoh/1FmXq+0YLhEieQ02A9qPpxG5BYf8b2Lc7bu249eqVzib0LcXxQdAkqCUdOSaZf7uhAALsbichlqDEe7oYYtFEqtS7NrSaIULc8SfCkCPke5/usE98yh5IOEVBSDodhyg4Jt1dxhHvyZArbFU1KgtiHcu+laIdTW7phvWXZcHbE5TO46C1BkmfxwePGoANYNDupqyEGYYr2woXPJD+RzpqjbOqfGgyDxX2oTUn8JENPFa/vXypfo3ywHCnRkChZO8ryUKvJzolKUfEsflb6ZFjtwEoxrHJhzKxbyNFIruvH+M0vftV7EnGPywMPCdk9zavFdDt7n5EcoFg0RWWHI1f92KNGCcraH/mH27wwEY4OdQPaKo7r1SBxqH8ACDxmanam4udvk+Q8yWml9kq7N2wgJCysyQ1lxeJrO4v0cUvEYND1AdX6cpLLHAAAAAAAAAAAAAwsUISQu" + } + ], + "rule": "registry signature(s) over canonical(fields): each of `signatures` with the registrySignature.keys entry of the same alg/keyId (hybrid: all must verify); `signature` is the Ed25519 half" + }, + "rules": [ + "assertion: WebAuthn signature = ECDSA-P256/SHA-256 over authenticatorData || sha256(clientDataJSON), verified with publicKey.raw (uncompressed point); clientDataJSON.type must be \"webauthn.get\"; authenticatorData flags must include UV (user verified)", + "binding: verify each of binding.signatures (or binding.signature with alg ed25519) over canonical(binding.fields) with the matching registrySignature.keys entry — Ed25519 and, when present, ML-DSA-65; all must verify; binding.fields.recordHash must equal recordHash, binding.fields.credentialId must equal the assertion credential, and binding.fields.publicKey must equal approver.publicKey.raw (17 Oct 2026: an assertion re-signed by another key, with that key offered, passes every other check)", + "identity: when binding.fields.identityProvider is present (18 Oct 2026), approver.identity must equal {provider: fields.identityProvider, tenantId: fields.tenantId, subjectId: fields.subjectId}: the tenant that vouched for the approver is inside the registry-signed binding, and the readable copy beside it may not differ", + "challenge: when approver.challenge is present (rule ask-v1, ceremonies from 18 Oct 2026), clientDataJSON.challenge must equal base64url(sha256(canonical(challenge.fields))) with fields.attestationId = approver.attestationId AND = record.attestationId AND = binding.fields.attestationId (19 Oct 2026: the sealed record and the signed binding name the ceremony; approver.attestationId alone is unsigned, and a genuine answer to another ask by the same credential would otherwise pass beside the binding of this record), fields.prompt = decision.prompt and fields.actionParamsHash = decision.actionParamsHash: the device signed over the ask, so the assertion itself names the act it answered. Absent, the challenge was a nonce and only the binding pairs the assertion with the record (an assertion by the same credential over another ask passes every other check)", + "amendment: when decision.amendment.command is present (approved WITH CHANGES), record.paramsHash must equal sha256(canonical(amendment.boundAs)) and amendment.boundAs.command must equal the amended command (its first 2000 UTF-16 code units): the SEALED record commits to the amended command; boundAs is the exact action binding the registry hashed ({tool, command, path, summary, amount, artifactHash}), served because record.tool and record.summary are capped, trimmed copies. A record with no paramsHash (ceremonies sealed before 19 Sep 2026) commits to no command: the amendment is then readable text, not checkable, and never confirmed. A bundle without boundAs (served before 19 Oct 2026) is checked with {tool: record.tool, command, path: null, summary: record.summary, amount: null, artifactHash: null}, exact only for a summary under the 400-char cap: download it again. When decision.actionParamsHash is present, amendment.originalParamsHash must equal it (the amendment cites the ask the person signed); an escalated approver's ask before 19 Oct 2026 carries no action digest and the citation is then not checkable. The passkey covers the ask as proposed; the amendment rests on the registry seal, not on a signature by the person (19 Oct 2026)" + ] + }, + "basis": { + "asked": { + "seq": 28266, + "ts": "2026-10-29T14:13:18.994Z", + "area": "engineering", + "tool": "terminal", + "summary": "cd /Volumes/2TB-FAST/sean-overflow/src/xchk/xchk-mobile && python3 - <<'EOF'\nimport re\nsrc = open('src/app/(app)/addresses.tsx').read()\n# a component, not a screen: no router, no SafeAreaView, no back header\nsrc = src.replace(\"import { router } from 'expo-router';\\n\", \"\")\nsrc = src.replace(\"import {", + "paramsHash": "89eabdeb5917a7cd4499dcf48e6f1b81f7ee68c18932030e1101f76332e0d703", + "code": "hook_escalation", + "reason": "destructive filesystem command outside scratch roots", + "recordHash": "7a1a772cc3baecf8dcde1a42c83b9be8474d1501ff54b15f449512f45ac6189c", + "model": "claude-fable-5-1" + }, + "grant": { + "area": "engineering", + "disposition": "allow", + "policyId": null, + "policyName": null, + "maxAmount": null, + "resources": [] + }, + "authorizeDisposition": "attest", + "area": "global", + "objective": null, + "rule": "asked = the attest record this ceremony answers (same plate, same action summary, raised just before the ceremony; cite it by recordHash); grant = the plate's grant rows as they stood when the ceremony was raised; asked.reason is the registry's stated reason for asking" + }, + "decision": { + "prompt": "ENG-WNP3.3155 (via Claude Code) wants to cd /Volumes/2TB-FAST/sean-overflow/src/xchk/xchk-mobile && python3 - <<'EOF'\nimport re\nsrc = open('src/app/(app)/addresses.tsx').read()\n# a component, not a screen: no router, no SafeAreaView, no back header\nsrc = src.replace(\"import { router } from 'expo-router';\\n\", \"\")\nsrc = src.replace(\"import {", + "response": "approved", + "status": "completed", + "createdAt": "2026-10-29T14:13:19.370Z", + "respondedAt": "2026-10-29T14:13:36.833Z", + "by": "sean@maclawran.ca", + "authMethod": "webauthn", + "requiredAuthMethod": null, + "amendment": null, + "actionParamsHash": "2384d7b017afc6cb318da59b7532fe89db7f68323d6e69168171c7cc50048ea3", + "attestationHash": "2e9763100632884a54440bc2305cec220b850c17df66ae0e50956f14cc74db12", + "attestationHashRule": "sha256 over the registry's canonical attestation JSON (utils/attestationHashUtils.computeAttestationHash: id, prompt, response, status, respondedAt, approver, method, amendment, delivery, chain …); recomputable on the registry, cited here so the record and this decision are bound" + }, + "legalHolds": null, + "anchor": { + "rvnTxId": "355ab6a3462aa7827cf1e7e659acc0069f4cdc5552ba88056cdd578aa47c5e7c", + "rvnAnchoredAt": "2026-10-29T14:15:34.887Z", + "rvnBlock": "00000000000019eff1378d25dd9f4d129bfd76c7177d0b558d11018dfa4f1088@4602434", + "explorer": "https://ravencoin.network/tx/355ab6a3462aa7827cf1e7e659acc0069f4cdc5552ba88056cdd578aa47c5e7c", + "manifest": { + "root": "182e387fabca21e04efb5b1247b9d01d18c242d7afabb877e4801402cd1996b1", + "index": 0, + "count": 32, + "path": [ + { + "side": "R", + "hash": "4147f23e2ce6f5262d96d2f4d632897719bb7316d5ae27d47c12cd12738aa2e4" + }, + { + "side": "R", + "hash": "f7a5b3e112f30c1e6dd9881eb01bed38d733770cbcc9da4dc14576d97c9f0bad" + }, + { + "side": "R", + "hash": "578424b55e4e093629c157a25cc3d1a50f7dc2dab4b27bbce54b7d25b0e95a18" + }, + { + "side": "R", + "hash": "0bcefddcc8b6adc6f9374b660b981d12c2e82f6a79011f28487d9a30bfd519fa" + }, + { + "side": "R", + "hash": "db3c7feefc127fc674d488ba8e23edd5c521bb6159534d2fc00a3f88336cd552" + } + ] + }, + "otsProof": "8AiR+FL3QJHX+QjxIMxdACvgGcqagiipbLhbgdz2ZRHssoKVtg8saXZTIWrnCPAggXjWEaO5cVDtZtkXH2ClQ3/eWewLmXBqZvANqxI/MoMI8BD6ZmOUPiVhwDyBoXvFCEoKCPEgQHp3gnLBWqmVOIN4pxPKrBTS09EE6QmnKMuozk6iUV0I8QRq41T48AhsW5n1L5oEwAjxIPW9L9fNpqhd+H1sIE/Xv0hZdTFqrO1ZptIHbFWy55NACPEgWPdm4fi6XJsZiyuubjZgc6EwV4O+eKS3ny0fNSQbkWwI8SAM71ydXtWTN0EOZudKvzB+3sahCfOFTU3WYLRVWlq7gAjxIDpbSBIh0KgXrF+jCXfGNRPZWIMDd+wkSZ1kvPPZYvjeCPAgOFfmppzK8eam72hk+RnPRamaLftTEOggqUSwZa+qdwwI8CBYhNbGK3/rROT0yROGIdMqSlTSrq5M7CqXcP7UB4toAgjwIJ6QEujTqpo6oBbsyVVVEST2gntOy4zxnC0XnTUo4B12CPEgwOsjLHTbVj0Mno7y4w0eEl9PacabTzhMJxGDvgGUVN0I8CCtnquxFTDTUcf7i0sn6k9q8JqP70h0lQ8Hb7J+ZQWBLgjxINLPfr6bPW+330Ud9WrByxY7ms+iO8bBaaZqrdBNLyMzCPAgEhtMVlwFKC0njtwNgm/sRdc5CLHXqjTfHd9lLuIKpnoI8SDhzz1n8PM0qWsTH8ga3JIY9RezQ0E6GTndxmPHdhWu8AjxIOVGpp+ONNBbTGUXQRwAPmTP1eC1gCtzISy9i64Bi8s1CPFZAQAAAAFvttwqw5GOSt9BDKCuhtJsQjKFM9OVrZsw6wT2/KIZfQAAAAAA/v///wK5NAEAAAAAABYAFKH1Mqm5cgKqvwAnUW4R7RUwmudsAAAAAAAAAAAiaiDwBIHbDgAICPAgdP9Q5ea2KEi+QKzMzDQu2kg6wbVXeVe0AxWdvQeAlTQICPEgLR/rII0V0oU/c0FYxMqVLSzZlJzXzhYMMBLnKKz+/ssICPEghEj7hmytzxk077hZrdPFGi+Iah7hJnE66vOR4OQ793IICPAgmZqq9MtpkBwr21j6KKs4009gnKmWx2KYf7IyoCjnAxgICPAgrkbfTO4QaZXxmbY+TO1VRc7P/iQVjomNUOJT3barm58ICPAgj67vf4nMHgGmSvJ6ovG6/Qcuy93C3UTc7iKV2re5OpwICPAgdBZrK+cy6jm+w1r6Ja1rryxjHOX/GZX/qyS5L42aLqgICPAgWr9TlH7EXFAwCIcrtQyuyaUp3Bl78f/mKJYTZprQpPIICPEgB5qt69T+D5LmyTi5dNIu59n1Vd7t+uaVlUUNPpHZAuwICPEgQir4uKViH+8woJsFLtMzV10Kv8vmJf44ngpPYcBlUk8ICPAg5cIV/B7uGmp3en2vRzZzevqq8x8IQ/en3zsmh9UNpWcICPEgS5gajJrjET5k0n1K/uD83tzCIy9TUAEAKWRHFolx2tkICAAFiJYNc9cZAQOCtzs=", + "otsCalendar": "https://a.pool.opentimestamps.org", + "otsBlockHeight": 973698, + "proof": { + "txid": "355ab6a3462aa7827cf1e7e659acc0069f4cdc5552ba88056cdd578aa47c5e7c", + "txHex": "0200000001b780ddcf9c27e2e318383a55a8d7f14d349c5585b5bc32fc39d85bdb2bce82ec010000006a4730440220012f2e8112ec20172d630badd5184a7dbf9efd5a7a653d7ff714dcdd37b6558a022013d5ca122f53864200c3c1888ba9ea1d404711d51a5cd783887883989f317f4b01210371203199ae65b79adf15056312afe2047468f2b6943ef9edbe985c1036dd8291feffffff0200000000000000004b6a4978436b02087365616c182e387fabca21e04efb5b1247b9d01d18c242d7afabb877e4801402cd1996b1d7d0aab2119075c395ded9b71294a74c82f3d3be25dbbaf10b7d859e6ee5b8f0c04f9603bf0000001976a914b58335666ec0f67c4c9a8e8642e77cf75763c04f88ac00000000", + "blockHash": "00000000000450c3259d1ceef41e7b50917b122bca4bc62bb746fb5d7300f8b1", + "blockHeight": 4602435, + "blockTime": "2026-10-29T14:15:43.000Z", + "headerHex": "0000003088104ffa8d01118d550b7d17c776fd9b124d9fdd258d37f1ef19000000000000d6c025ab434f484befaa52ebb22efba3975b556fa6836579ca403d739b4f92d20f55e36ab9f7071b433a460086c264ead6a3008d32d5b2973c318694f40697306a1afbc03f02b4153ecbbb3f705ee152ae524b55", + "merkleRoot": "d2924f9b733d40ca796583a66f555b97a3fb2eb2eb52aaef4b484f43ab25c0d6", + "merkleBlockHex": "0000003088104ffa8d01118d550b7d17c776fd9b124d9fdd258d37f1ef19000000000000d6c025ab434f484befaa52ebb22efba3975b556fa6836579ca403d739b4f92d20f55e36ab9f7071b433a460086c264ead6a3008d32d5b2973c318694f40697306a1afbc03f02b4153ecbbb3f705ee152ae524b55070000000350ebf02ef024389eeee32e449964a4f62e39eaadce6723bc45815ff99a3db52b65a26f3db0d604e985439de3575ca967d10d6207eef0a559b7c49060a753ea787c5e7ca48a57dd6c0588ba5255dc4c9f06c0ac59e6e7f17c82a72a46a3b65a350135", + "capturedAt": "2026-10-29T14:17:26.920Z" + }, + "rule": "proof.txHex is the raw anchor transaction: its OP_RETURN payload is \"xCk\" + version + flags + 4 id bytes + hash(32), where hash is sealHash, or — when anchor.manifest is present — the manifest root that anchor.manifest.path reaches from sealHash (side L: sha256(sibling + current); side R: sha256(current + sibling)); sha256d(txHex) reversed = proof.txid; sha256d(headerHex) reversed = proof.blockHash; proof.merkleBlockHex is a Bitcoin-style merkleblock whose partial Merkle tree reproduces the header Merkle root and includes txid. The one outside fact left: that blockHash is on the Ravencoin chain." + }, + "howToVerify": [ + "1. canonicalize `record` per `canonicalization.profile`, sha256 it, compare to `recordHash`", + "2. walk `merkle.proof` from `recordHash` (L: sha256(step+cur), R: sha256(cur+step)); the result must equal `seal.merkleRoot`", + "3. canonicalize the seal fields per `seal.rule`, sha256 it, compare to `seal.sealHash`", + "4. verify every entry of `registrySignature.signatures` over the seal hash with the key of the same alg/keyId in `registrySignature.keys` (Ed25519 + ML-DSA-65 when hybrid); older bundles: Ed25519-verify `signature` with `publicKeyRaw`", + "5. if `approver` is present: verify the WebAuthn assertion with `approver.publicKey.raw`, then Ed25519-verify `approver.binding.signature` over canonical(`approver.binding.fields`) with the registry key, and require `approver.binding.fields.publicKey` to equal `approver.publicKey.raw`: the binding, not the bundle, names the key the assertion may be checked with; when `approver.challenge` is present, recompute base64url(sha256(canonical(`challenge.fields`))) and require it to equal `clientDataJSON.challenge`, with the fields equal to `approver.attestationId`, which must also equal `record.attestationId` and `binding.fields.attestationId`, `decision.prompt` and `decision.actionParamsHash`", + "6. if `anchor.proof` is present: check the OP_RETURN (the seal hash, or the manifest root that `anchor.manifest.path` reaches from the seal hash), the txid, the header hash and the merkleblock; else look up `anchor.rvnTxId` on any Ravencoin explorer", + "8. if `seal.profileHash` is present: `profile.document` must be present, sha256(canonical(document)) must equal it, and `profile.signature` must verify over the hash with the registry keys; absent profileHash = sealed before profiles", + "7. if `basis`/`decision` are present: `basis.asked.recordHash` is another record on the same chain (fetch its bundle and run steps 1–4); `decision.attestationHash` equals `record.attestationHash`; when `decision.amendment.command` is present (approved WITH CHANGES), `record.paramsHash` must equal sha256(canonical(`amendment.boundAs`)) with `boundAs.command` equal to the amended command, and, when `decision.actionParamsHash` is present, `amendment.originalParamsHash` must equal it (approver.rules has the detail): the sealed record, not the readable amendment text, says what ran; the passkey covers the ask as proposed and the amendment rests on the registry seal" + ], + "profile": { + "profileHash": "9bbe0635c0a05cc8107d40ad5bb2d8b227c8125d395f41620bcd371123319701", + "document": { + "v": 1, + "name": "org", + "registry": "in.xchk.io", + "dials": { + "identity": [ + "email", + "domain" + ], + "registration": "person", + "anchoring": [ + "rvn", + "ots" + ], + "signing": "ed25519+ml-dsa-65", + "actSummary": { + "kept": "registry", + "maxChars": 400 + }, + "inbound": "on", + "operatorAccess": "recorded", + "actRecords": "kept", + "publicRecord": "plate", + "principalDomains": [ + "maclawran.ca" + ] + } + }, + "signature": { + "alg": "ed25519+ml-dsa-65", + "keyId": "5ecb3da505414c4f", + "signature": "3wM2ISHYyVQSahc6iEv70t47+skkAxg7sS7Nu6p82ZVT/WgN6iUdc+A+padJl1DJRcTJQErs3ppXsM8ZTQlEAQ==", + "signedAt": "2026-11-01T23:56:34.092Z", + "signatures": [ + { + "alg": "ed25519", + "keyId": "5ecb3da505414c4f", + "signature": "3wM2ISHYyVQSahc6iEv70t47+skkAxg7sS7Nu6p82ZVT/WgN6iUdc+A+padJl1DJRcTJQErs3ppXsM8ZTQlEAQ==" + }, + { + "alg": "ml-dsa-65", + "keyId": "8bb85bc1f41c568c", + "signature": "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" + } + ] + }, + "rule": "sha256(canonical(document)) = seal.profileHash; verify signature over the UTF-8 bytes of profileHash with the same registrySignature.keys as the seal; document.dials are the rules this node ran under when it sealed the window" + }, + "verifier": { + "html": "https://in.xchk.io/verify-receipt.html", + "python": "https://in.xchk.io/verify/verify_receipt.py", + "license": "MIT" + } +} \ No newline at end of file diff --git a/integrations/xchk-registry/examples/approval-outcome/expected.json b/integrations/xchk-registry/examples/approval-outcome/expected.json new file mode 100644 index 00000000..5b9cf1e3 --- /dev/null +++ b/integrations/xchk-registry/examples/approval-outcome/expected.json @@ -0,0 +1,117 @@ +{ + "trace_signer_jwk": { + "kty": "OKP", + "crv": "Ed25519", + "x": "mn02E1XyTkaVN6DEOemU5OADMUAUjPHw67oR5KKIM3k", + "kid": "5ecb3da505414c4f" + }, + "resolver": "https://in.xchk.io", + "plate": "ENG-WNP3", + "runSeq": 3057, + "generated_at": "2026-10-17T15:54:52.151Z", + "cases": { + "01-approval-confirmed.json": { + "bundle": "01-approval-confirmed.bundle.json", + "reference": "aa2bfd5b1d9b6307ed22eb0daa4213383beecb57d7d31ec011060ac98f7fe0b5", + "trace_record_verifies": true, + "reference_resolves": true, + "digest_matches": true, + "bundle_verifies": true, + "disposition": "approved", + "verdict": "approval-confirmed", + "registry_keys_pinned": true + }, + "02-bundle-altered-after-issue.json": { + "bundle": "02-bundle-altered-after-issue.bundle.json", + "reference": "aa2bfd5b1d9b6307ed22eb0daa4213383beecb57d7d31ec011060ac98f7fe0b5", + "trace_record_verifies": true, + "reference_resolves": true, + "digest_matches": false, + "bundle_verifies": false, + "disposition": "approved", + "verdict": "approval-contradicted", + "registry_keys_pinned": null + }, + "03-decision-is-a-denial.json": { + "bundle": "03-decision-is-a-denial.bundle.json", + "reference": "24e7d14e03dbf72472d55d8a7266c1a0f98fe3f6e8600b1601fa17159ce43778", + "trace_record_verifies": true, + "reference_resolves": true, + "digest_matches": true, + "bundle_verifies": true, + "disposition": "denied", + "verdict": "not-an-approval", + "registry_keys_pinned": null + }, + "04-no-answer.json": { + "bundle": "04-no-answer.bundle.json", + "reference": "5cad45602b4554d5172ee747157b276bc0ad619d146a8b7bf6052ec3fea9c98f", + "trace_record_verifies": true, + "reference_resolves": true, + "digest_matches": true, + "bundle_verifies": true, + "disposition": "expired", + "verdict": "not-an-approval", + "registry_keys_pinned": null + }, + "05-reference-unresolvable.json": { + "bundle": null, + "reference": "c92c8c55d333d24204fcb453596cf1c784ea2755e6fc963c1176314c3e2bee9f", + "trace_record_verifies": true, + "reference_resolves": false, + "digest_matches": null, + "bundle_verifies": null, + "disposition": null, + "verdict": "approval-unconfirmed", + "registry_keys_pinned": null + }, + "06-assertion-from-another-credential.json": { + "bundle": "06-assertion-from-another-credential.bundle.json", + "reference": "aa2bfd5b1d9b6307ed22eb0daa4213383beecb57d7d31ec011060ac98f7fe0b5", + "trace_record_verifies": true, + "reference_resolves": true, + "digest_matches": true, + "bundle_verifies": false, + "disposition": "approved", + "verdict": "approval-contradicted", + "registry_keys_pinned": null + }, + "07-amended.json": { + "bundle": "07-amended.bundle.json", + "reference": "236de6c9aa5f147034e5aaebb6f235c1d90c999a5fe469cd5c07ed9b7405d10f", + "trace_record_verifies": true, + "reference_resolves": true, + "digest_matches": true, + "bundle_verifies": true, + "disposition": "approved", + "amended": true, + "verdict": "approval-confirmed-as-amended", + "registry_keys_pinned": true + }, + "08-assertion-over-another-ask.json": { + "bundle": "08-assertion-over-another-ask.bundle.json", + "reference": "aa2bfd5b1d9b6307ed22eb0daa4213383beecb57d7d31ec011060ac98f7fe0b5", + "trace_record_verifies": true, + "reference_resolves": true, + "digest_matches": true, + "bundle_verifies": false, + "disposition": "approved", + "verdict": "approval-contradicted", + "registry_keys_pinned": null + }, + "09-re-keyed-outside-the-registry.json": { + "bundle": "09-re-keyed-outside-the-registry.bundle.json", + "reference": "aa2bfd5b1d9b6307ed22eb0daa4213383beecb57d7d31ec011060ac98f7fe0b5", + "trace_record_verifies": true, + "reference_resolves": true, + "digest_matches": true, + "bundle_verifies": true, + "disposition": "approved", + "verdict": "approval-consistent-key-not-pinned", + "registry_keys_pinned": false, + "note": "Derived, not minted: 01 re-signed under keys that are not the registry's by tests/rekey_fixture.py on 2 Nov 2026 (review of #350, drk-ram); the Trust Record is 01's. Added to this file by hand with the registry_keys_pinned field; the generator has not been re-run." + } + }, + "xchk_keys": "xchk-keys/in.xchk.io.2026-11-02.json", + "xchk_keys_note": "The registry's /.well-known/xchk-keys.json as served on 2 Nov 2026, pinned so the assessor checks the bundles' keys against the registry's offline; without it every verdict above approval-consistent-key-not-pinned is unreachable." +} diff --git a/integrations/xchk-registry/examples/approval-outcome/xchk-keys/in.xchk.io.2026-11-02.json b/integrations/xchk-registry/examples/approval-outcome/xchk-keys/in.xchk.io.2026-11-02.json new file mode 100644 index 00000000..a1aee80c --- /dev/null +++ b/integrations/xchk-registry/examples/approval-outcome/xchk-keys/in.xchk.io.2026-11-02.json @@ -0,0 +1 @@ +{"registry":"https://in.xchk.io","keys":[{"keyId":"5ecb3da505414c4f","alg":"ed25519","use":["seal","identity-binding"],"status":"active","notBefore":null,"notAfter":null,"revokedAt":null,"publicKeyRaw":"mn02E1XyTkaVN6DEOemU5OADMUAUjPHw67oR5KKIM3k=","publicKeySpkiDer":"MCowBQYDK2VwAyEAmn02E1XyTkaVN6DEOemU5OADMUAUjPHw67oR5KKIM3k=","publicKeyPem":"-----BEGIN PUBLIC KEY-----\nMCowBQYDK2VwAyEAmn02E1XyTkaVN6DEOemU5OADMUAUjPHw67oR5KKIM3k=\n-----END PUBLIC KEY-----\n"},{"keyId":"8bb85bc1f41c568c","alg":"ml-dsa-65","use":["seal","identity-binding","plate","portfolio"],"status":"active","notBefore":null,"notAfter":null,"revokedAt":null,"publicKeyRaw":"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","standard":"FIPS 204"},{"keyId":"555543785b177aec","alg":"ed25519","use":["revocation-bundle"],"status":"active","notBefore":null,"notAfter":null,"revokedAt":null,"publicKeyRaw":"pCN7hG3+DmJ7BuwKkI8VccuxmejeydxbRURnQSkajB0="}],"retired":[],"revoked":[],"root":{"alg":"slh-dsa-sha2-128s","standard":"FIPS 205","keyId":"acc7ad1aeb3ef177","publicKeyRaw":"4aIhDuj3TZPwqb9HT8TzVJnkvle4jVUMhWkn/BfmypM=","statement":{"v":1,"registry":"https://in.xchk.io","keys":[{"alg":"ed25519","keyId":"5ecb3da505414c4f","publicKeyRaw":"mn02E1XyTkaVN6DEOemU5OADMUAUjPHw67oR5KKIM3k="},{"alg":"ml-dsa-65","keyId":"8bb85bc1f41c568c","publicKeyRaw":"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"}],"retired":[],"oidc":[{"kid":"XWUv0uGESGdIG1MjOzbVjcwxB0CYtK0oZ9SZxNkH7h8","kty":"RSA","alg":"RS256","n":"zQwdJyTuyqQvB5zIXp9ULjX22k-R95Ls5j3IVUwLcI87I2VPUjsvy9oDGl5cq8Jl7Rt21d966AakANr8J1vT7gMpcmPOcEGVDdgdCprRs8cWNDo5uJ4ejt1LW65zRqW8xsxqHPm1aOxvjeUQfNgZFLn3VlSX01zgjggBLSwL18stLbyIzA2zcj4lpV-IrnBO3S6VUusoaO__kXjHv1-aH64wpVcsNLrBX6MWsnHM-KptbhKrk_qqXMJ7dokBxiIAH32VjZ73kTbVcSXoU2FshM_eQaonhYcRoD8PTXN3rxMaisj2pka9XZ1Apqy-EHf1dCoUphYxd_--FcT5PDQZaQ","e":"AQAB"}],"issuedAt":"2026-11-02T03:01:07.385Z"},"signature":"CT06acNG0QWuCHhltKfyu/5KMRGvE8/jsVUnzQVQs0Sc4PuZkmHJa7Fog9lQbq7g2eD2MLPLsEkWF1T+gbH3cSVH9NbVDVN4RLLTowgeDhEkiQY9Bq4jZRtGnE3z6SuHqBw4LJwHJTYtesWvxN6SZJLYsvCMbqnIZ8E1YOgTw7WWEn8t9/A/5btUrY9tjHzS4abixkWiiVLeSVsTt+kZfyzzPdr4/cZloS8WSBETG17S1mUBbC5CnAKULUS+5hPK0RQJ3wYWNoRRQLUrTVn+CkgbNLVy+squmFcFg8G7IWSp+6/L9dAXcAoC0KHGPY290S4QV6t64va4aqkyIYtRkCH6U0Nih9GZaRVuy1QV4bqBeB4IUekaT5gzsMmSc8eU9g3AyH+7dPJZBqh+QJybZGjUETf7/hYCNYdHpRO2UzCDd36ailb1AsDzIpQql/ohaLm/xCtAC43649LM+SpbZwgxV1Jgo3qM/Aom2UjNCGojClwMfOCFhiTj5jKOwbCjEvwqrFgzR0Ztytihi15xlOhJW120XYZUj3QSc6QH6nHmxNDMnnXmvjE2V1Uzu8gVk6pGOugZOXL3n/nfIn1pSwlluCl9/ZZ8ZXXzJsLwgXtDZ9WQx5rsvAe+nsitWB81DB1gYUaLYf9frqs6CMGAUpxM+Aurw5LlorQWUmytDkR1PMSTTuQlkhPmxO70VJAsikMdMuTkzdreJ6lffZdeSUKuXpbCaJORfUHiSU1k9JRONlFuekoggRyOb9dhHReYu6G4YICj+9qfbsO/tjIM0Gux9AJdd2PBcTjBpLRNktnrTTTpyVJNZBA9Rw2IShQxExNZZEtkFz9AFiXr+p9eiImQMlH8z3+Lq55GJHEiwf5aTKzQpdmDQLcvgxBuZYeea3MQUIAnL6LAAhxQ2kmw0BTSYyg6RSL7ZqD+X869qsXkKhNgwue9q9zliKs4JrWdmKOhE2vWhN13Ws35rr3TVJN1n/kMoZpZC6wps/JhYMCJk3yY6EhAmCIo/V3QMIM/T+axLjfIQ8gLiz6CFIhKkMOyYOqd4u3YLdHGnRZaLT9VnWB4Gb5RztJX/hwOvEc/ruzL2Wo4MqMbeyewPGVpTZyNxiOah1yJBc+Z14/PmK1Bt6Msx2KtzBkmMfb+WFKvDWYdWiVTIXHNYruBv5Fnj6sgbdOR8W1q4rQ1f7SMYjfd6AJnk4P+FAk0es/jnbYMrvfnP7id9SFEOMSWk+wHFMQkdr5snqTU1SJ2AU4865LdMRVW5PVJ1JUkCmxOb4HET35hYo4u0K3Z7NCj7mtAKX69E99PMMx7pRWdWMN90LKa8xJRcbV/sV7i+vtQ7ciFaJonZ0aMao2A2EuYsIwcpdCOFQUbyJqurpvaZOrj5RBTGB3b9uOzQiMbs514PhRcdwgljb9Zw8a4J/9pQNy9YYMqX8jn2K7ElMcuaK9FVY6adZGmz5JdHpQQuCrf6K8NXZXpIZsD0gZP6BbmGgY+RwIq2eICHUrtBZs6KmFOFPK0K7MHPbQKpSPwMOlZyX4l8pIxcr0NqXTMNQc7BRfgZshgEC47JiKhsZ3m2xq3N7TUdEQ14W1260h28sD9xK2724hXgt/mCxPNQ4W7WSkzWcnMHiUkZfRYwB6Ru/oy85CVrvGhaQIbwcvpbpV2o9sOOv7Ta9PHrtRL1XA8O4KudkrGj75+0XhQatH3EDCA9so9i2v0Izwn3upXCniZgOGODaXpkiTdhV2H9Dmxg5OTDQwq2VEAoOC8OY6MlYTtl1EXuyzl/+TwCw6H3cots4jgDzuzph5+mYbVRj80ctb15G6V3J08b4fIvkdlTq3yUi7cKhU7Pqj8/1YF21L/pg/f0FGzL7bajAE4+J17iOTpnMeLktOP5/knO6sCimU/+z65c1ctg9p/9XHgpuA2pUWGlr36y+1AAYZ4ukKGKFsoDYCGOJxPVOtvwGd3Zb1L9gW1OlIXz+ED2g67epvCfckaNpuaYRy4Wzg1knVE/3k5EoAxzcO/5AqL9nMhW5y5t1gSnxTVlTBbaE6qn7vQ9rtXZOaKszDGVZzB9cqMuOhSfDK/8vhhgwVOb7BTt37iyDFCU7ufWP7lHBVl7IG7kJ4OqoJbziUFxtkecEsTwTTHsoixFeWw1IFyEAzXdozah80Kervg5ktn/Q6tV2QIGM5WTGWUyotLrvJ9f/eDekUnYoPNURp3Q0Ha+ucUqRjIzfMvNX0Kyz9gR4uAZWw3czNsYoqZZB68qs95jpXK1zdM/aV6zRqmbdRmwTXmh8RMQrKu9RiT1KbkJ1jwiDkC0YO6cye9M5rkvg13LVd/fQ8wGm9MxDrckeRVU6JlSxBq17hCCC3LVQ4z1cceSebnZGSmTIzQEcZNKa0Fu2MNFSiFSVNoJZzyYTcvkz6CZS3J8HyARlPNt2//TXD2vl8fwjECMuPM7AxnUKA6QTYLAfAfwvv+eHj4QHaafZyNXINSX+0USZfJ/gBFn0LXSdwra7xsWnVEoddQRzfx+dRSCHQJS3eIs6e6Cq+C1SY5jXIyTEMVuAw5ETB2KlxTqleB9jVz/e6OweY6NsLZoDsCixNBUp7XAb7DxVnmG5O5qXhtzXV+FM0n1WzTQXfwHDaCUxBJoRxJHG9R831tlO42OGLklQ5oHLYv9FthaMkq2mfctQdqUiwSO0SjkEt/KynsOmTd2Ry5CN9DQnlxQfFZko72rJMTN8cFGMxemz88kRVUyocLTPpilP1BHsGxMxuY1ibwKed7fSfWzGfFSFzL38YEoCmNJFQNM+oNjsu8ZWO1x6Nk7P/JXLsjcxZpASw0W1caPTErOoxF8Ra3cIC/SvjUGpmMLTgSySIQ9deKrhN8jyIq6uznVjQVonJRRyBMyOuu+DheSv/8swNO+yoVVRpa6P9mvfhz38owRzCOqFBUbj0x3iJe6nsj4VNRagluaGFI++rpOHr/ZAeXtuRbbHkZxihJCnSIb2u1wc5HryLJ8m/4zmkCV7WsQhNn3DZRfoFiKD140xq+RqYrgnCLC6w3+kFc3kF9b5JL1fWjPPglbDD9JJ05BA8u+HqyA9rn1mXvOR4WYGukPhbdIt/SPijhu8Z3RgCI1FE8mMOYcJO+mu6Jwmg+aChV6bqiZrvKa7uQ9PnH2LE4LzL0hZ+GEtEZJ5c/b/9qXQB+3NZAvkrGuVhYSPretmQMWcb9Za/OmDFJtllCF93c6uAVFPhk5b1UfpckwwMYKiJrmqMuRuq2hsnf9+yHzpuiCJmAeMOHMS+3Z0br8UL4zPB+KNNGuXhaGqlLgilcbw9B2TgkAXNTH714Mc9lbXmS87+s6iova+xCVhR1lxMEAYMMjsl2C0UQRpLouX4n7mhutGJ6/Gr9sFCtVODYUH3J8cDPHX1Yd/FUkko7iy+AnwcWKnchyZaMJRW4BQt49ttQxtOhpS4ny6PVGZ46jrf4ADfAHzcOxbtzznSrxkFDkIEzYnp8Z6866qZmyhVus5drRrKbVk+UJk6pwh9WKEdnmHsfYQmdfo/w4QVyGpYoPJ/3KhfGLLXkJgFPLNC+w5B9pcH6bqiK2SnQEUbKMLDygmvA5uYzNrr3MxG9MUBAJOrskwha3IyoigI7ivoKLYNNNwxBIceK4J4MMwZQVBDg/qmkEHH5cKKxpeUMaszy5U20btrJcQtEavq03u4XH8yFnjZPBA2S72wJpJApe58ICm7sY1oCbFbVr4DRCQdfHfQh9awbn1da6H5Q6fvymYn6UIBv16Z8qy5GBvJYI3quaRDNoSlze+ZUnbYZolLNLbawCR3NRE41zsAQk2kQzLGccvesGGhvc5f2AAVGCDj6JLtRFOUI3nL32dKgAOCmZGNfMxyvH9a8GguJV4OwPxwZA0oqvKPLuX/cDxeo+0vMP+PQinXLVZdFcsFSDmAmPkVmLUP47WZVV/VY0/DbyJo2ebuWgkCy8Twh7fGA9jn7BjLIE3JvDgcIL+C0BDJ6IsX7G8/SBoBE9wyYuPb+93oi2x46sg5VNZCOGVVF7yp3SaGDr6k+8Amr6Sy5Uni92o5EoPwQDMDHAam1eMxTTQWOYh7sxvMG+FUlFGE+jA3s5QuIg/mM+GDeYha7EoYbJjmJ3LmHXBkIRhKPZTUUZqfSnnVIpdepdRiVFmnBCuO65el8Sq4xwP6BmNfTsEIUMWT5Ge/6coJksr3LIxBQeBkRvNVyU1HINvzb+EfDp2henn76ltzJGZlZdT3LwlayFxxSEVitK3Eb9zlvpykaPWW9QpTv7kbtxBCU2aaKPdFRli0iGJF4pPX6n3uaUFpVt2vF0RLZ7U4fsJCRs3bu7rtvyfJFDFn9bjP4ZzobsKBRdHDqqIUpo7DEACk7e+6uZGe0x0+xrsTpUkeBAkfYickRIh0nmteC8tkZ/fO/Ci/yBrW9VwWPP5dDo5EXbNAGZNaEsTdmtDRD6kck+XcgrQ2WG03taAzu2QwdL5cp4RIRJiqQYuV/XiIS6B8GFyNm8zfqEU2YLV5RDbkWCsedfATj7Fgirm4l15B2ykV9NWs66WrGRLSpso7GokTqYltfjGkM5r2jfVx2o7eeeCkUR0t4Y36yzcGTWEdZnxTbsL/BRUpHFediUeQLTcP7NswEm8fUs8kDyeEU0rRbXQG/aQHvsGwTh/qrsAJK9yH8ouaLTn8thNHDF6noatUMJSjKheezxIocO0IJ/H95XpBdemNxwjhZCqMVeLsAoT23pWqIc7uE7anPg3EyTjcimSomtWmNWzqpIAtcwCqHvd3LbeDIg0wDDKHeIMCRRi8Vmzq8tv3tasc/0XEsKSki2FrAc1IcNhwmaPSy/+TiW/cgolltqK1Z/7urQlKc7U9TGPRetbFn3DdHK3MWFyrZGn56bqCs8jzryxfnUwLNNg1VqpIasJSTLU2Kzu2HbD9HMdtNN5r1EBnNYPSJWIstAp+M4FKySD3+0ovDybi2Z2A6u0W4PZI37+qtMKgiSO/Iyk1GhwvFGH215uESPGeOtR1nIZm1wYnxIS8g7SGDCW6wyZJZbjEVlPb78ZRDKv+eny0alolPGGUgZFEJSPA9qWQLs+/n9jtSxu27WScNqH2d+MRd2Keq4XT1ZC+RV8nAiSPosZnnAzhdVhihuySbghhdP7kske7Qrh9r1F87eEVfVrrG2W/1OyGSAoBRwOhTXv7kPf0CX9Lg6NN6BbvEnkptkoZy0M0JnEac7HdmiAuMAen4iM7k3lCZMkiQS3Ab0sQWe9oe7hkOgu3GmrtjwO3b3QnLxMKYbWdhQ7NrMGpMjsuGBXcdw5PfqVmCNKrmPTcCsaizmvv1DvobYm0wVdSRqkuMwuVdN4i/NRKYhwFT8I4sQUnY5pfwhWUEUezqOoJ3fYsTZax7mUR/ddq8Ba+ttd/M0b7bYjHOOfoCZzAyB5rqemndukzdG7AahvSgb4rsTJFFDKruQVugZlgU/IHr3n5mZySSjBXt9JLxLlbgWo6mYM67YC1OaRXAHnTnaNm4RAMoX0B29GbqWAOEZgL+zw7GKL8T8J5c/qV0Ugz1KQbviJlea31YtVT1m5oUwSS8ki/8J9DuHMkB9btg6JkL7FGfdnx8oVKukU1pSLQIsZCeFsT1KpWNVg86ODyx4a0qqkb68k9CkEkwZr7XMAyyQr8/pkvw7dY2xXuhvilrKjvdA3XIyWYr8J+ILqBsGk+ftKFsE80+AUe32TjVR1k0JmkceE7Ge1qwW/xvVUdVPJdmL9cfIFLAbY6pflx5Fm8FDvTQHFeTQnn8br05Vwed/omjBwN0h0+TedbZas2XJgXZg0Rxp8QN9CtYkMYntZxWINJcrZxfC0kZ0yT5SeLZ47MljhdyG+q46oIqE6fmOMO5WD93+VB2xsmOUkoVqerZdIg1ytmNTWbBFGJ+y5V3JQXOoPiaDC/az2R1dFjz7FYXCqTR8fdgHhrbKMFL4fZ2OOtn4jzeDclXDZ7YC5c+yCjZ4G8o0/MsBG7xdVxFRFiFVUN9rlXUkHQjSpd/KFgS4xJ9BC+j8MSVQ66KmstapkODiy8KwXhnDAAe9mwcghWZPaiUdJcO3pjIIMSwhpJea11IM4D0wlzC7NCm24WxRldwjTbfpqiDds50jMv3pG/0UC9Cl7Qes7iefaCUX/4dM1PgpTpobYxyv9WQF7XB3/VhxV/X7hGjCr93g0mtnjRsBKpWzysdiyPUBtDpP88nOlIbLUyHbP9ZMzZiqs3W+9Jl1DGTbz2/58LgHDl3WQSOXBspXzZcUkvZg76B5oiB9eB8Pz3knUVkI7tVe7XsxilhCH9NmvaBHt2w0Qp+tS5YaVWh5s+j7LB3C+mRSyRxkDY95pFeZI0xkLbS7UhCvo+oMgH6krIpH3Z8g2Au2T2kUZaWbTOQ8J6qV1nEWW12XaYWm2FbN9doE33GzdNRsvAG92Gi31t8u4P8KG3Xk5+JKrJxTqagdN9wUAVjyPVxiKfREb8fn8i6UdcZNRajQb1M2+lTBde2Zbk16EXImINkbYxYpZfYgz6rzOwdVBvwvmEzLnPfv3XEhEmOXlq91mxvCEDLkPtVaxTKE/IBqxxnrIkgQ4XQwZduK3axGDSRsrIOsW7FSeHlvcnUeI3DMn7uavFeqVvsPU/klPvLJ/fckr/lDHn35urfxCA5qWUBlNFb9cFCbbrT23HOz5iZyclbj9ApPXbg57mqmGQ4ssTgzNzImsKoiWXVvzKep6BwYmYUEVuxrxmbksmfefmhCTB2Uq4+JrLi7ImiqNiGz46S8/1IzqYenmDinLntsA+UeUVSWlcDvr+kbFbjW2qxLWv9bbXZtxwFPFsxj7NS+JwOkE++R1w+uEb4YBtlvSQFWKm0IarvPd0QwPCS3DChjUqYa447MeXdK4qn1RdflTbol014OO+d61NTDljKZ75E87w7xoVHUz6Mt8FVDaXED/rRbJ8BDV5X85vSaorMJnxB0qVuO/aoXzH3lJZ5QGgJTjRztZ0EHKPGd1tw1ElB+DXIAzpT4KKZbTwc83WlfhBGOw0NW5dq7ZqHUp9ZIiBpFC8M+vnox4gM+VIbIxToBGAl3jDcgGTfT0sWMdkA1Ej5+8++qrNr3JiyT9s0N/H7pmFUQlkhKlASC8N6WLKN/YXsd1c8am9qmZKGHJI3XErvFbi3FyQAI3iWTDbXX+ii5wCM1mkvQUF7JUHh2LCMlUNOx9bAzupSxTCc9CdlzRkpA5ay5893MQRparKB7rBtsAkUC/5W0FsP+wXLW6bU5dacRlGdF1mp/tlRcJa2Hj8W9U/kwQ0APd7U83PIBPhM0sGo+lLibKZ1Ero6WBzSMSua6wCd592yAJ2KzfE07pCUBIzhlwxiTGLLnT7ljdg09OmDurN5asEYoY/ks1ziZ0tPS1M487j8fzcbSK7gIofFbKZZ4GWEPGXrx9OIWt0xPv8DN57ztxMEkHYuDMdw/xMrLH03XC+PvVxR4BUGohQruK/BiO+9FXYXRB9Jwgp6AUJxUVs4q8UVyGTyW+XoewGxyx8aJjjKunQ1M5fALVFMC8ddxb6lIrHPdnYbWIlaeUlX0/YQ1/v0IiVljpEF+EjI6vk/stc/TRHN7xDy5koY8OpBs7nmW0kKEtqbpII4ANhnyCp76zxSr7rBg41ufX89ZWVHqLeMMi8VHpZ7qPp05vUPWkFTvc3Iy3ApktTksuG4Izuuzu6k70GQj1zIcWhIrN8Y6XuhBd68OXGi7xN4IX7Ds6K62X+d08uKn9UdlVfVpDAOoIb0diOWO3IxyNF1rJtP+WM0GWt3ul/HZelIC09VkE28Hltz8zrENorJ0SqYSxPyO1ZaAMv1iwtM+nQoa5MbTYn75bprKK/P+Cj5fd1BeO+Vrt2fu/qowlmtOEmvD4jRV+br839rLqU6VIZtvnBibxO38po2XyvJjsN8Fzaw/ehxhslRArU/ATl5ypx8zT3Y5bNyMNKK1xOwAR1dxQ3jVPoS85CuRoSmMd5rJ8ZClynmxJR/mSRG0HGZ5RDT4DpXPsuIFSKfuMMXmvy/51U81S1ohppMILvNiovmmNTLdNW8NWWNmWaIVFcG+zh18MmH62WdD4iXxXagofMO7dQFQ7ohdc3RMqOS65/yPI9qnyPQ9rIqrk6MGKTrNaRlVHfskVS98BHI+p2v+H0R9zu/IKo6jsDXfZ9QIN+bi6dt5g+tMJFHMmExsD96Zznsoksi9zmuhNlUtUGBhwyyQxjUxzRHwww/YOJbn9/NvAWos6PRzqA247e7y59DUOumoG4IpP+asOXX+mCSzqt9p2fy77aYwni0nAD8yV8kwTt/qZ5ckbouhp+4vaEI2fCZB1+Xy8pHL6hg7mG/IcC2To2JyI8MxoPpOLURUgmlJWG3hEqedN6bmN77O4YFezCQNQbq1uN+WLqnY5ec7nM+HNtxTZJk+ni764QjzM5KuGeeexME9SQ5hql3IOMwrOMtmw7lyO3wbBpy5HaoqOcjU6Jh0xD14NVPbrlPAx3YfpeC73yMdFyVeAAPaMhAcDQK9jOtlcZUEJsW4JRpghFSObg1uA9HGtgyHGaS+Y0oRLTrLYw2RlUiCWyeUL1hFy6QViV8I9xOK4rgTLDkN0wlhW1QmcPgWP3vtSQAgC+fJvGGQ5ajy6Bo4O6Eczp/AjaFt708vsEkmrHa2BRV0WsEvg84q74h8TQoghIoICFWx3FnRs/QJW1TINLakBcU2JNXHylNmCAHTNcgO0cYdzHHF5q944IcpqEdB36pfcKi/IdeWv4Xh32KfJrCOXSm0RBztLjur2+sOqWHFaHn6WHEbxttVzvLBD37CdIyMUjR2tpC0888QMOV1dLvHCzTk2tQaBZdoCSx6Tz8ARy+SGujomBbXfLWoxrQdazngz8AQNTk3LjWZRcuoHV7kwhN+72EaiUONOYYfOVPCu1jYOAB2mP9aBUiOtxSYOUyPfa/iu54MlBF3EYoIlZAKnbhIrjEm5RThInsr5u+3pOpMtJ4o7B4KcSEXwpAcjYrjlE0+/VC4rEqmbxYBpao3B9RlFxH67++AvRSBVqZ/hupY0Zd06lKBmRZcpbGATDxFOpS2/8kU8tbCjTRdAsMcw0biGu6TjNqZ3lsjkchFy1eQPvYa4oK+HoYPS7tQ9YYZN64ikak49yksImz3IzhJMErT6SOCOXeSS8NENmeg1CcoODPwlEg3gHZ4pqvmL1/Rc74pI0mM2Uyq2hw27Z3Kus/qQeDDa8WiCeKxDUQT6fciYVz74PUX4M3RjmaIkto6EPRt32/svuxh2gX7xbW/tfOd3mYAp2SOb2kcRq17gXIHK1gYONgHq57uDCanxIU2fQ5eAofEWcYVijmPCLrcMGid2P4GrtRkfm2taG/a1x4yOM9WeeNpucWUwIb4bQfoGRphwvUus/w4EBlfIJfW0aFWTktY+Hca15OfOOFhH8xuYdL8wHVUTnk0GP7kCpgOmQSiapvp4AcyRmC2rOP2sv8U8LjUAsFe8EDMVYDZLPqNw1e7UbR1aJqpF/xfKSNKfmpHj1mn4N+QaLnOfgyem35f/LzwieNX6auESwfPqG7dLD/XSLdOdURUBsKEHkgJEEtvFb72i2nSjlkQtTag3HPXPJZuDySSDweLvWF77zS36W6AIgOSu0oPCZPAVK3j9ah/A2fD5EnVSyevL0z0s2tTTMeXw3pIYzicKFcur5oBsYM/7DdF/WCJRDVzNIRf3h3dKQy/GGqWmFhf74tvDEfmVg0UvGMXq4/qRVlkaaXIJvpkNXVyrikLcqaRvIfnbazee94iFOSX/aieaq5PwcJnPwaSo4+YXXJ5qucvrm0EAyEK7SAl2jw8ULO8W8c+YA3JSID9TRDLy1StO0Dix3+dOKdZRcudRQnKlEUWs47/yNjy34OAzEMY+52AzV6hZBlmNKUpSwAU5+YZpmLsZ2fa0p1aQMcIuFgKO8/O9IE4laZwTFYOKvlHEPNyigu0PBgQqP7rDxmaGkiNoc9a8L5cNiMKskvV+jhIRZ8P6XSfKgW8CpIABHuBf7EMphn9PyzUlXDgTqodABp5smLg9CW3UIMAPD0igrgMmDuBUObbcptI1k+uYSZ6A2vwi07693jyBJCqGEObHMF+v52VRud7qN2w+4btATO07vto/QZkEMhC3jgBtEkm1G5gNSQg8L19yZ0YMrVzfNjuxGPhwwfz0DXQpisM4xWJG4MUKxAZuH2LgzfaZ/9Zhhw4MMcIxNeRQM4TC4GQKV2Dz5j7rro+Ee53O5QcD9Pv0kTrAJdEGZEcPKNklZxREa5w+ZehTPP3ajpCN/Z7jYxY9thj0L5rd6AlXHZ++ChuqGZucGP7Pl0BTFN1u7gplyUiCtVDWlmnwN+Lr/SG2NQl7Mwst7FkZyw8GPBgHq2cPmO6cRJASr+uKm5m/YEprkhCNkWEyTHlCY/EiAXSZ2HEiW9AjcC2ZxhUFROfjWPaPSQZwDBkKx9Q9SGdDoDWiGk435XRc0BNZ8gaTxhSdM=","rule":"SLH-DSA-SHA2-128s verify(publicKeyRaw, canonical(statement) bytes, signature); statement.keys are the keys this registry signs with"},"revocation":{"bundle":"https://in.xchk.io/.well-known/xchk-revocation.json","logId":"https://in.xchk.io/seals","bundleKeyId":"555543785b177aec","format":"TraceRevocationBundle/1.0"},"hybrid":"every seal and binding carries both Ed25519 and ML-DSA-65 over the same bytes; a hybrid verifier requires both","servedAt":"2026-11-02T03:01:09.306Z"} \ No newline at end of file diff --git a/integrations/xchk-registry/examples/approval-outcome/xchk-keys/xchk.me.2026-11-02.json b/integrations/xchk-registry/examples/approval-outcome/xchk-keys/xchk.me.2026-11-02.json new file mode 100644 index 00000000..552ea34b --- /dev/null +++ b/integrations/xchk-registry/examples/approval-outcome/xchk-keys/xchk.me.2026-11-02.json @@ -0,0 +1 @@ +{"registry":"https://xchk.me","keys":[{"keyId":"9366514f736f4718","alg":"ed25519","use":["seal","identity-binding"],"status":"active","notBefore":null,"notAfter":null,"revokedAt":null,"publicKeyRaw":"f8dQDGlPkpnbumezn7WWcNl2FN2xw2/KGZov+sIWjEQ=","publicKeySpkiDer":"MCowBQYDK2VwAyEAf8dQDGlPkpnbumezn7WWcNl2FN2xw2/KGZov+sIWjEQ=","publicKeyPem":"-----BEGIN PUBLIC KEY-----\nMCowBQYDK2VwAyEAf8dQDGlPkpnbumezn7WWcNl2FN2xw2/KGZov+sIWjEQ=\n-----END PUBLIC KEY-----\n"},{"keyId":"9f43e01120587a46","alg":"ml-dsa-65","use":["seal","identity-binding","plate","portfolio"],"status":"active","notBefore":null,"notAfter":null,"revokedAt":null,"publicKeyRaw":"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","standard":"FIPS 204"},{"keyId":"4b815216014ce4ef","alg":"ed25519","use":["revocation-bundle"],"status":"active","notBefore":null,"notAfter":null,"revokedAt":null,"publicKeyRaw":"Wce96F1gFlaZe4BtBNiGNyZZPKGynlrPMdsAQlY657E="}],"retired":[],"revoked":[],"root":{"alg":"slh-dsa-sha2-128s","standard":"FIPS 205","keyId":"0e60af7c61ea570f","publicKeyRaw":"miY/Uhr/IG1o+RANs+mfys1z6H4zqeQtUHeIsExBdu4=","statement":{"v":1,"registry":"https://xchk.me","keys":[{"alg":"ed25519","keyId":"9366514f736f4718","publicKeyRaw":"f8dQDGlPkpnbumezn7WWcNl2FN2xw2/KGZov+sIWjEQ="},{"alg":"ml-dsa-65","keyId":"9f43e01120587a46","publicKeyRaw":"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"}],"retired":[],"oidc":[{"kid":"pejRTJO9JukSx_XuNys89v62yZLGefAiKbeD7k-GXIc","kty":"RSA","alg":"RS256","n":"vrefusamq8SyyJwDS6ynMCucjM-BJIDaKQmFgJZ8UyxSEhFjZae1NtH-KFxhnjbuGmSIMUh2i1o-tHZyaJF5PzFAySGhL9FNi3XHZDcwoZM7-0oYnLdc03iggOQM3-mrvfd8wJpkRYo-GvgjNp34ac_QNIZxvjvy1XD-b5Uc69lH90UKyrBO8o77qrPwA4agoSKIHiM6083HCc_FzP41_AweU-bCxKFkSxgHRuMBpqPjY_IxD_4_JcAWrpRlEFTcxlaqYK-5mbum2Gvbxrjr4gEUbLSf5gJ_cvVnItAZEf2BvnDODkZ13NXyT7eO5EpWTH0gDesegPBugT6cBAKwuw","e":"AQAB"}],"issuedAt":"2026-11-02T03:02:26.567Z"},"signature":"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","rule":"SLH-DSA-SHA2-128s verify(publicKeyRaw, canonical(statement) bytes, signature); statement.keys are the keys this registry signs with"},"revocation":{"bundle":"https://xchk.me/.well-known/xchk-revocation.json","logId":"https://xchk.me/seals","bundleKeyId":"4b815216014ce4ef","format":"TraceRevocationBundle/1.0"},"hybrid":"every seal and binding carries both Ed25519 and ML-DSA-65 over the same bytes; a hybrid verifier requires both","servedAt":"2026-11-02T03:02:29.941Z"} \ No newline at end of file diff --git a/integrations/xchk-registry/pyproject.toml b/integrations/xchk-registry/pyproject.toml index 15813811..bede9b67 100644 --- a/integrations/xchk-registry/pyproject.toml +++ b/integrations/xchk-registry/pyproject.toml @@ -14,7 +14,7 @@ dependencies = [ ] [project.optional-dependencies] -test = ["pytest"] +test = ["pytest", "rfc8785", "cryptography", "dilithium-py"] [tool.setuptools] py-modules = ["xchk_trace_record"] diff --git a/integrations/xchk-registry/tests/conftest.py b/integrations/xchk-registry/tests/conftest.py new file mode 100644 index 00000000..f780f164 --- /dev/null +++ b/integrations/xchk-registry/tests/conftest.py @@ -0,0 +1,20 @@ +"""The suite needs the post-quantum verifier (2 Nov 2026). Since the hybrid-signature fix, a required ML-DSA-65 half +that cannot be checked is a strict-mode refusal, not a pass: a label is not a signature. So without `dilithium-py` +every hybrid receipt exits 3 under --require-approval, and these tests would fail by the dozen for the wrong reason +(13 of them did, in a venv that had only pytest). Stop before the first test and say so instead.""" +from __future__ import annotations + +import sys +from pathlib import Path + +import pytest + +sys.path.insert(0, str(Path(__file__).resolve().parent.parent)) +import verify_receipt as v # noqa: E402 + + +def pytest_sessionstart(session): + if v.ml_dsa_65_verify(b"\x00" * 32, b"m", b"s") is None: + pytest.exit("these tests need dilithium-py: the verifier checks the ML-DSA-65 half of every hybrid receipt, and " + "without it --require-approval refuses every hybrid receipt by design. pip install dilithium-py " + "(pure Python, MIT)", returncode=1) diff --git a/integrations/xchk-registry/tests/rekey_fixture.py b/integrations/xchk-registry/tests/rekey_fixture.py new file mode 100755 index 00000000..696bb023 --- /dev/null +++ b/integrations/xchk-registry/tests/rekey_fixture.py @@ -0,0 +1,81 @@ +#!/usr/bin/env python3 +"""Re-sign a genuine receipt bundle under keys of your own (2 Nov 2026). + +Reproduces drk-ram's exercise in review of agentrust-io/integrations#350: take fixture 01, replace the registry's Ed25519 +and ML-DSA-65 keys with freshly generated ones everywhere they appear — the pinned key list, the legacy single-key fields, +the root statement's key list — and re-sign the seal hash, the profile hash and the identity binding with them. Every +check the verifier can run offline then passes, --require-approval included, because every key it checks with is the +one the bundle carries. Only --keys, with the registry's published key document, tells this bundle from a real one. + +The root's SLH-DSA-SHA2-128s signature is left as it was: no library here signs FIPS 205, and the Python verifier only +reports it as WAIT. (The browser page, which does verify SLH-DSA, fails this bundle on that signature: a re-keyer who +also rotates the root passes there too, and the key document catches that root in both verifiers.) + +Run (needs `pip install cryptography dilithium-py`): + python3 integrations/xchk-registry/tests/rekey_fixture.py integrations/xchk-registry/examples/approval-outcome/01-approval-confirmed.bundle.json \\ + integrations/xchk-registry/examples/approval-outcome/09-re-keyed-outside-the-registry.bundle.json +The private keys are generated for the run and discarded. The output differs on every run; the fixture is committed once. +""" +import base64 +import json +import sys +from pathlib import Path + +from cryptography.hazmat.primitives import serialization +from cryptography.hazmat.primitives.asymmetric.ed25519 import Ed25519PrivateKey +from dilithium_py.ml_dsa import ML_DSA_65 + +sys.path.insert(0, str(Path(__file__).resolve().parent.parent)) +import verify_receipt as v # noqa: E402 + + +def b64(b: bytes) -> str: + return base64.b64encode(b).decode("ascii") + + +def main(src: str, dst: str) -> None: + bundle = json.loads(Path(src).read_text(encoding="utf-8")) + rs = bundle["registrySignature"] + old = {k["alg"]: k for k in v.pinned_keys(rs)} + assert set(old) == {"ed25519", "ml-dsa-65"}, "expects a hybrid-signed bundle" + + ed_priv = Ed25519PrivateKey.generate() + ed_pub = ed_priv.public_key().public_bytes(serialization.Encoding.Raw, serialization.PublicFormat.Raw) + pq_pub, pq_priv = ML_DSA_65.keygen() + new = {"ed25519": {"alg": "ed25519", "keyId": v.key_id_for("ed25519", ed_pub), "publicKeyRaw": b64(ed_pub)}, + "ml-dsa-65": {"alg": "ml-dsa-65", "keyId": v.key_id_for("ml-dsa-65", pq_pub), "publicKeyRaw": b64(pq_pub)}} + sign = {"ed25519": lambda m: b64(ed_priv.sign(m)), "ml-dsa-65": lambda m: b64(ML_DSA_65.sign(pq_priv, m))} + + def resign(obj: dict, msg: bytes) -> None: + """Rewrite a registry signature object: every entry of `signatures`, and the legacy single Ed25519 fields.""" + obj["signatures"] = [{"alg": a, "keyId": new[a]["keyId"], "signature": sign[a](msg)} for a in ("ed25519", "ml-dsa-65")] + obj["keyId"] = new["ed25519"]["keyId"] + obj["signature"] = sign["ed25519"](msg) + + resign(rs, bundle["seal"]["sealHash"].encode("utf-8")) + rs["keys"] = [new["ed25519"], new["ml-dsa-65"]] + rs["publicKeyRaw"] = new["ed25519"]["publicKeyRaw"] + rs["publicKeyPem"] = ed_priv.public_key().public_bytes(serialization.Encoding.PEM, serialization.PublicFormat.SubjectPublicKeyInfo).decode("ascii") + rs["publicKeyRawPq"] = new["ml-dsa-65"]["publicKeyRaw"] + rs["keyIdPq"] = new["ml-dsa-65"]["keyId"] + stated = rs.get("root", {}).get("statement", {}).get("keys") + if isinstance(stated, list): + rs["root"]["statement"]["keys"] = [new.get(k.get("alg"), k) if k.get("keyId") == old.get(k.get("alg"), {}).get("keyId") else k for k in stated] + prof = bundle.get("profile") or {} + if prof.get("signature") and bundle["seal"].get("profileHash"): + resign(prof["signature"], bundle["seal"]["profileHash"].encode("utf-8")) + bd = (bundle.get("approver") or {}).get("binding") + if bd and bd.get("fields"): + resign(bd, v.canonical(bd["fields"]).encode("utf-8")) + bundle["fixtureNote"] = ("TEST FIXTURE, 2 Nov 2026: fixture 01 re-signed under keys that are not the registry's (rekey_fixture.py, beside the tests). " + "Every offline check passes without --keys; with the registry's key document the pinned keys fail by name.") + Path(dst).write_text(json.dumps(bundle, indent=2, ensure_ascii=False) + "\n", encoding="utf-8") + print(f"wrote {dst}: keys {new['ed25519']['keyId']} (ed25519), {new['ml-dsa-65']['keyId']} (ml-dsa-65); the registry's were " + f"{old['ed25519']['keyId']}, {old['ml-dsa-65']['keyId']}") + + +if __name__ == "__main__": + if len(sys.argv) != 3: + print(__doc__) + sys.exit(2) + main(sys.argv[1], sys.argv[2]) diff --git a/integrations/xchk-registry/tests/test_approval_outcome_fixtures.py b/integrations/xchk-registry/tests/test_approval_outcome_fixtures.py new file mode 100644 index 00000000..e4ff4709 --- /dev/null +++ b/integrations/xchk-registry/tests/test_approval_outcome_fixtures.py @@ -0,0 +1,390 @@ +"""xChk sealed receipts as TRACE `approval-outcome` references. + +Re-verifies examples/approval-outcome/ without xChk installed. The fixtures were +minted by the registry at in.xchk.io (scripts/trace-fixtures.js in minitru/xchk-server), +which also wrote expected.json. A generator's own summary of its output is a claim, so +every outcome here is recomputed from the committed bytes and compared with +expected.json, never read from it: the Trust Records with this repository's library, +the reference digests with rfc8785, and the bundles with the registry's own +standard-library verifier, vendored beside the fixtures and run as a subprocess. +""" + +from __future__ import annotations + +import copy +import hashlib +import json +import subprocess +import sys +from pathlib import Path + +import pytest +import rfc8785 +from cryptography.exceptions import InvalidSignature + +from agentrust_trace import verify_record + +XCHK_DIR = Path(__file__).resolve().parents[1] / "examples" / "approval-outcome" +VERIFIER = Path(__file__).resolve().parents[1] / "verify_receipt.py" +# 2 Nov 2026 (review of #350, drk-ram): the registry's key document, /.well-known/xchk-keys.json as served on 2 Nov 2026, +# pinned here as the relying party would pin it (the Trust Record signer is pinned the same way in expected.json). The +# verifier checks every signature with the keys the BUNDLE carries; only this document says those keys are the registry's. +KEY_DOCUMENT = XCHK_DIR / "xchk-keys" / "in.xchk.io.2026-11-02.json" +# The fixtures were minted on 17 Oct 2026; a historical record is re-verified under an explicit, finite bound (ten +# years, the same as the workflow), never by switching the bound off (section 3.2.2). +MAX_AGE = 315360000 +EXPECTED = json.loads((XCHK_DIR / "expected.json").read_text(encoding="utf-8")) +CASES = sorted(EXPECTED["cases"]) +OUTCOME_KEYS = ("trace_record_verifies", "reference_resolves", "digest_matches", "bundle_verifies", + "disposition", "registry_keys_pinned", "verdict") + + +def _load(name: str) -> dict: + return json.loads((XCHK_DIR / name).read_text(encoding="utf-8")) + + +def _jcs_sha256(obj: object) -> str: + return "sha256:" + hashlib.sha256(rfc8785.dumps(obj)).hexdigest() + + +def _verify(bundle_path: Path, require_approval: bool = False, key_document: Path | None = None) -> dict: + """The registry's offline verifier, run as it ships, with --json: the structured report (exit, result, the checks + that ran, the pending count, the approval evidence still missing, the amendment's standing). Exit 0 means no check + FAILED (pending steps are listed, not failed); with --require-approval it also means the approval evidence was + present and checked. Absence of failure is not verification of an approval, so the verdict below asks for both, + and it reads the amendment from the report, never from the bundle's unsigned text. With --keys (2 Nov 2026) the + bundle's pinned keys are also checked against the registry's key document; `keyDocument.allPinned` says so.""" + args = [sys.executable, "-I", str(VERIFIER), str(bundle_path), "--json"] + (["--require-approval"] if require_approval else []) + if key_document is not None: + args += ["--keys", str(key_document)] + proc = subprocess.run(args, capture_output=True, text=True, check=False, timeout=60) + report = json.loads(proc.stdout) + assert report["exit"] == proc.returncode + return report + + +def _approval_reference(record: dict) -> dict: + refs = [r for r in record["references"] if r["rel"] == "approval-outcome"] + assert len(refs) == 1, "one approval-outcome per fixture" + return refs[0] + + +def _record_verifies(record: dict) -> bool: + try: + verify_record(record, EXPECTED["trace_signer_jwk"], max_age_seconds=MAX_AGE) + except (InvalidSignature, ValueError): + return False + return True + + +def _assess(record: dict, bundle_name: str | None, bundle_override: dict | None = None, tmp_dir: Path | None = None, + key_document: Path | None = KEY_DOCUMENT) -> dict: + """What a relying party concludes about the approval a record points at. `bundle_override` lets a test present + a mutated bundle for the same record; it is written to `tmp_dir` for the verifier. `key_document` is the registry's + key document the relying party pinned (2 Nov 2026); None means it pinned nothing, and the strongest verdict is then + approval-consistent-key-not-pinned: consistent under the bundle's own keys, which is all the verifier can check.""" + verifies = _record_verifies(record) + if not verifies: + # A Trust Record that does not verify is not evidence of anything, including the reference it carries: no + # verdict about the approval is drawn from it, with or without a bundle (review of #350, 20 Oct 2026). Before + # this, the record check ran and was reported but did not decide the verdict, so a record with one signed field + # changed still reached approval-confirmed through its intact bundle. + return {"trace_record_verifies": False, "reference_resolves": None, + "digest_matches": None, "bundle_verifies": None, "disposition": None, + "registry_keys_pinned": None, "verdict": "record-invalid"} + reference = _approval_reference(record) + assert reference["resolver"] == EXPECTED["resolver"] + assert len(reference["id"]) == 64 + if bundle_name is None: + return {"trace_record_verifies": verifies, "reference_resolves": False, + "digest_matches": None, "bundle_verifies": None, "disposition": None, + "registry_keys_pinned": None, "verdict": "approval-unconfirmed"} + if bundle_override is not None: + bundle = bundle_override + assert tmp_dir is not None + bundle_path = tmp_dir / bundle_name + bundle_path.write_text(json.dumps(bundle), encoding="utf-8") + else: + bundle = _load(bundle_name) + bundle_path = XCHK_DIR / bundle_name + digest_matches = _jcs_sha256(bundle["record"]) == reference["digest"] + report = _verify(bundle_path) + bundle_ok = report["exit"] == 0 + disposition = bundle["record"].get("disposition") + # an approval is "as amended" only when the verifier found the SEALED record committing to the amended command and + # the amendment citing the signed ask; the bundle's decision.amendment text selects nothing on its own + amended = bool(report["amendment"] and report["amendment"]["committed"]) + keys_pinned = None + if not (digest_matches and bundle_ok): + verdict = "approval-contradicted" + elif disposition != "approved": + verdict = "not-an-approval" + elif (strict := _verify(bundle_path, require_approval=True))["exit"] != 0: + # approved on the record, but the evidence that would confirm it is absent: not contradicted, not confirmed. + # Approval evidence present with the seal chain incomplete is its own verdict (review of #350, 20 Oct 2026): + # the person's answer checks out, the receipt's place in the sealed chain does not. + verdict = "approval-unverified" if strict["approvalEvidenceMissing"] else "approval-unsealed" + elif key_document is None or (pinned := _verify(bundle_path, require_approval=True, key_document=key_document))["exit"] != 0: + # 2 Nov 2026 (review of #350, drk-ram): every check so far was made with the keys the bundle carries, so a + # bundle re-signed under someone else's keys reaches this point with every check passed (fixture 09). Only the + # registry's key document, pinned by the relying party, says the keys are the registry's. Without it, or with + # a key the document does not list, the approval is consistent, never confirmed. + keys_pinned = False if key_document is not None else None + if key_document is not None: + assert pinned["keyDocument"] is not None, f"the verifier could not read the pinned key document {key_document}: {pinned['transcript'][-1]}" + assert pinned["keyDocument"]["allPinned"] is False, "the only check --keys adds is the key document's" + verdict = "approval-consistent-key-not-pinned" + elif amended: + keys_pinned = True + verdict = "approval-confirmed-as-amended" + else: + keys_pinned = True + verdict = "approval-confirmed" + return {"trace_record_verifies": verifies, "reference_resolves": True, + "digest_matches": digest_matches, "bundle_verifies": bundle_ok, + "disposition": disposition, "registry_keys_pinned": keys_pinned, "verdict": verdict} + + +def test_the_committed_records_are_exactly_the_declared_cases() -> None: + committed = { + p.name for p in XCHK_DIR.glob("0*.json") if not p.name.endswith(".bundle.json") + } + assert committed == set(CASES) + for name in CASES: + bundle = EXPECTED["cases"][name]["bundle"] + assert bundle is None or (XCHK_DIR / bundle).is_file() + + +@pytest.mark.parametrize("name", CASES) +def test_every_case_verifies_as_a_trust_record(name: str) -> None: + """Rule 3 of section 3.1.2: the record stands whatever the reference resolves to.""" + verify_record(_load(name), EXPECTED["trace_signer_jwk"], max_age_seconds=MAX_AGE) + + +@pytest.mark.parametrize("name", CASES) +def test_the_outcome_is_recomputed_from_the_committed_bytes(name: str) -> None: + got = _assess(_load(name), EXPECTED["cases"][name]["bundle"]) + want = {k: EXPECTED["cases"][name][k] for k in OUTCOME_KEYS} + assert got == want + + +def test_the_record_signature_covers_the_reference() -> None: + record = copy.deepcopy(_load("01-approval-confirmed.json")) + _approval_reference(record)["id"] = "0" * 64 + with pytest.raises(InvalidSignature): + verify_record(record, EXPECTED["trace_signer_jwk"], max_age_seconds=MAX_AGE) + + +def test_a_stale_record_is_rejected_under_the_default_bound() -> None: + """The bound is finite and explicit; the fixtures are historical, so the library's default 24 hours rejects them.""" + with pytest.raises(ValueError): + verify_record(_load("01-approval-confirmed.json"), EXPECTED["trace_signer_jwk"]) + + +@pytest.mark.parametrize("strip", ["approver", "assertion", "binding", "challenge"]) +def test_missing_approval_evidence_is_not_a_confirmation(strip: str, tmp_path: Path) -> None: + """Removing evidence leaves the verifier with pending steps and exit 0; an approval verdict needs more than + 'nothing failed'. The record stays approved on its face; the verdict is unverified, never confirmed.""" + record, bundle = _load("01-approval-confirmed.json"), _load("01-approval-confirmed.bundle.json") + if strip == "approver": + bundle.pop("approver") + else: + bundle["approver"].pop(strip) + got = _assess(record, "01-approval-confirmed.bundle.json", bundle_override=bundle, tmp_dir=tmp_path) + assert got["digest_matches"] and got["bundle_verifies"] + assert got["verdict"] == "approval-unverified" + + +def test_an_assertion_for_another_ceremony_by_the_same_credential_is_refused(tmp_path: Path) -> None: + """The genuine denial's passkey answer (same credential, another ceremony), placed beside the approval's genuine + signed binding, with the outer attestation id edited to agree with it. Every signature is real; the ask does + not name the ceremony the sealed record and the binding commit to.""" + record = _load("01-approval-confirmed.json") + good, denied = _load("01-approval-confirmed.bundle.json"), _load("03-decision-is-a-denial.bundle.json") + assert good["approver"]["credentialId"] == denied["approver"]["credentialId"] + b = copy.deepcopy(good) + for k in ("assertion", "challenge", "attestationId"): + b["approver"][k] = copy.deepcopy(denied["approver"][k]) + b["decision"] = copy.deepcopy(denied["decision"]) + assert b["record"] == good["record"] and b["approver"]["binding"] == good["approver"]["binding"] + got = _assess(record, "01-approval-confirmed.bundle.json", bundle_override=b, tmp_dir=tmp_path) + assert got["digest_matches"] and not got["bundle_verifies"] + assert got["verdict"] == "approval-contradicted" + + +def test_unsigned_outer_labels_are_not_the_evidence() -> None: + """The approver's email and assurance a relying party reports must come from the signed binding; the outer + fields are not evidence. This pins the binding's values as the ones to read.""" + bundle = _load("01-approval-confirmed.bundle.json") + bound = bundle["approver"]["binding"]["fields"] + assert bound["approverEmail"] == bundle["approver"]["email"] + assert bound["authLevel"] == bundle["approver"]["authLevel"] + bundle["approver"]["email"] = "synthetic-other-person@example.invalid" + bundle["approver"]["authLevel"] = "synthetic-elevated-assurance" + assert bundle["approver"]["binding"]["fields"] == bound, "the signed statement is untouched by an outer edit" + + +def test_the_reference_digest_is_the_registry_record_hash() -> None: + """One number on both sides: rfc8785 over bundle.record equals the registry's own hash.""" + bundle = _load("01-approval-confirmed.bundle.json") + assert _jcs_sha256(bundle["record"]) == "sha256:" + bundle["recordHash"] + reference = _approval_reference(_load("01-approval-confirmed.json")) + assert reference["digest"] == "sha256:" + bundle["recordHash"] + + +def test_the_altered_bundle_differs_in_one_field_only() -> None: + before = _load("01-approval-confirmed.bundle.json") + after = _load("02-bundle-altered-after-issue.bundle.json") + assert after["record"]["summary"] != before["record"]["summary"] + after["record"]["summary"] = before["record"]["summary"] + assert after == before + + +def test_the_impersonated_approver_offers_a_key_the_binding_does_not_name() -> None: + """The assertion in 06 verifies with the key the bundle offers; the binding names another.""" + before = _load("01-approval-confirmed.bundle.json") + after = _load("06-assertion-from-another-credential.bundle.json") + a_before, a_after = before["approver"], after["approver"] + assert a_after["publicKey"]["raw"] != a_before["publicKey"]["raw"] + assert a_after["binding"] == a_before["binding"] + assert a_after["binding"]["fields"]["publicKey"] == a_before["publicKey"]["raw"] + for field in ("authenticatorData", "clientDataJSON"): + assert a_after["assertion"][field] == a_before["assertion"][field] + assert a_after["assertion"]["signature"] != a_before["assertion"]["signature"] + + +def test_the_crossed_assertion_is_the_same_persons_answer_to_another_ask() -> None: + """08: key, binding and user verification all genuine; the challenge the device signed names + another ask.""" + before = _load("01-approval-confirmed.bundle.json") + after = _load("08-assertion-over-another-ask.bundle.json") + a_before, a_after = before["approver"], after["approver"] + assert a_after["publicKey"] == a_before["publicKey"] + assert a_after["binding"] == a_before["binding"] + assert a_after["credentialId"] == a_before["credentialId"] + assert a_after["challenge"] == a_before["challenge"] + assert a_after["challenge"]["rule"] == "ask-v1" + assert a_after["assertion"] != a_before["assertion"] + a_after["assertion"] = a_before["assertion"] + assert after == before + + +def test_an_amendment_typed_into_the_bundle_is_not_an_approval_with_changes(tmp_path: Path) -> None: + """decision.amendment is unsigned text. Added to the plain approval after issue, with every signature intact, it + selects nothing: the sealed record's paramsHash does not recompute over it, the verifier fails, and the verdict + is contradicted, never 'as amended'.""" + record, bundle = _load("01-approval-confirmed.json"), _load("01-approval-confirmed.bundle.json") + bundle["decision"]["amendment"] = {"command": "synthetic alternate command", "byEmail": bundle["decision"]["by"], + "at": bundle["decision"]["respondedAt"], + "originalParamsHash": bundle["decision"]["actionParamsHash"]} + got = _assess(record, "01-approval-confirmed.bundle.json", bundle_override=bundle, tmp_dir=tmp_path) + assert got["digest_matches"] and not got["bundle_verifies"] + assert got["verdict"] == "approval-contradicted" + + +def test_the_amended_command_is_the_one_the_sealed_record_commits_to(tmp_path: Path) -> None: + """07 as committed: record.paramsHash is the registry's action-binding digest over the AMENDED command with the + record's own tool and summary (recomputed here with rfc8785, not with the verifier), and the amendment cites the + ask the person signed. Edit either and the approval is contradicted.""" + record, bundle = _load("07-amended.json"), _load("07-amended.bundle.json") + am = bundle["decision"]["amendment"] + binding = {"tool": bundle["record"]["tool"], "command": am["command"][:2000], "path": None, + "summary": bundle["record"]["summary"][:2000], "amount": None, "artifactHash": None} + assert bundle["record"]["paramsHash"] == hashlib.sha256(rfc8785.dumps(binding)).hexdigest() + assert am["originalParamsHash"] == bundle["decision"]["actionParamsHash"] == bundle["approver"]["challenge"]["fields"]["actionParamsHash"] + assert bundle["record"]["paramsHash"] != am["originalParamsHash"], "the sealed act is not the ask as proposed" + assert _assess(record, "07-amended.bundle.json")["verdict"] == "approval-confirmed-as-amended" + for mutate in (lambda b: b["decision"]["amendment"].__setitem__("command", am["command"] + " ; synthetic extra"), + lambda b: b["decision"]["amendment"].__setitem__("originalParamsHash", "0" * 64), + lambda b: b["decision"]["amendment"].pop("originalParamsHash")): + b = copy.deepcopy(bundle) + mutate(b) + got = _assess(record, "07-amended.bundle.json", bundle_override=b, tmp_dir=tmp_path) + assert got["digest_matches"] and not got["bundle_verifies"] + assert got["verdict"] == "approval-contradicted" + + +def test_the_crossed_ask_stripped_of_its_challenge_is_never_confirmed(tmp_path: Path) -> None: + """08 with approver.challenge removed. The bundle cannot tell an ask-v1 ceremony whose challenge was deleted from a + ceremony before ask-v1, so the verdict falls from contradicted to unverified: weaker evidence, never a + confirmation. Pinned here so a change that lets it reach 'approval-confirmed' fails.""" + record, bundle = _load("08-assertion-over-another-ask.json"), _load("08-assertion-over-another-ask.bundle.json") + bundle["approver"].pop("challenge") + got = _assess(record, "08-assertion-over-another-ask.bundle.json", bundle_override=bundle, tmp_dir=tmp_path) + assert got["verdict"] == "approval-unverified" + + +def test_relabelled_identity_is_reported_from_the_binding(tmp_path: Path) -> None: + """The verifier's structured report names the person from the registry-signed binding, not the readable labels.""" + bundle = _load("01-approval-confirmed.bundle.json") + bound = bundle["approver"]["binding"]["fields"] + bundle["approver"]["email"] = "synthetic-other-person@example.invalid" + bundle["approver"]["authLevel"] = "synthetic-elevated-assurance" + p = tmp_path / "relabelled.bundle.json" + p.write_text(json.dumps(bundle), encoding="utf-8") + report = _verify(p, require_approval=True) + assert report["exit"] == 0 + assert report["boundIdentity"]["email"] == bound["approverEmail"] + assert report["boundIdentity"]["authLevel"] == bound["authLevel"] + + +@pytest.mark.parametrize("strip", ["seal", "merkle", "seal+merkle", "seal-signature"]) +def test_an_approval_without_its_seal_chain_is_not_confirmed(strip: str, tmp_path: Path) -> None: + """Review of #350 (noah-ing, 20 Oct 2026): the approval evidence intact, the seal, the Merkle path or the registry's + signature over the seal removed. Strict mode refuses, and the verdict is approval-unsealed, never confirmed.""" + record, bundle = _load("01-approval-confirmed.json"), _load("01-approval-confirmed.bundle.json") + if strip in ("seal", "seal+merkle"): + bundle.pop("seal") + if strip in ("merkle", "seal+merkle"): + bundle.pop("merkle") + if strip == "seal-signature": + bundle["registrySignature"].pop("signature", None) + bundle["registrySignature"].pop("signatures", None) + got = _assess(record, "01-approval-confirmed.bundle.json", bundle_override=bundle, tmp_dir=tmp_path) + assert got["digest_matches"] and got["bundle_verifies"] + assert got["verdict"] == "approval-unsealed" + + +def test_a_bundle_re_keyed_outside_the_registry_is_consistent_never_confirmed(tmp_path: Path) -> None: + """Review of #350 (drk-ram, 2 Nov 2026): fixture 01 re-signed under his own Ed25519 and ML-DSA-65 keys, the pinned + key list and the root statement's list rewritten to match (09, rebuilt by tests/rekey_fixture.py). The verifier + passed it under --require-approval and this assessor said approval-confirmed, because every key either checks is + the one the bundle carries. Now: with the registry's key document pinned, 09 is approval-consistent-key-not-pinned + and 01 is confirmed; with no document pinned, even 01 is only consistent. The Trust Record is 01's, unchanged: the + record points at the same sealed receipt, and the tampering is on the carrier.""" + before, after = _load("01-approval-confirmed.bundle.json"), _load("09-re-keyed-outside-the-registry.bundle.json") + assert after["record"] == before["record"] and after["seal"] == before["seal"] and after["merkle"] == before["merkle"] + assert after["approver"]["assertion"] == before["approver"]["assertion"] + assert {k["keyId"] for k in after["registrySignature"]["keys"]}.isdisjoint({k["keyId"] for k in before["registrySignature"]["keys"]}) + record = _load("09-re-keyed-outside-the-registry.json") + assert record == _load("01-approval-confirmed.json") + got = _assess(record, "09-re-keyed-outside-the-registry.bundle.json") + assert got["digest_matches"] and got["bundle_verifies"] and got["registry_keys_pinned"] is False + assert got["verdict"] == "approval-consistent-key-not-pinned" + assert _verify(XCHK_DIR / "09-re-keyed-outside-the-registry.bundle.json", require_approval=True)["exit"] == 0, "the finding: strict mode alone passes it" + control = _assess(_load("01-approval-confirmed.json"), "01-approval-confirmed.bundle.json") + assert control["verdict"] == "approval-confirmed" and control["registry_keys_pinned"] is True + unpinned = _assess(_load("01-approval-confirmed.json"), "01-approval-confirmed.bundle.json", key_document=None) + assert unpinned["verdict"] == "approval-consistent-key-not-pinned" and unpinned["registry_keys_pinned"] is None + assert _assess(_load("07-amended.json"), "07-amended.bundle.json", key_document=None)["verdict"] == "approval-consistent-key-not-pinned" + # a verdict below confirmed is unchanged by the document: a contradicted bundle stays contradicted, pinned or not + assert _assess(_load("02-bundle-altered-after-issue.json"), "02-bundle-altered-after-issue.bundle.json", key_document=None)["verdict"] == "approval-contradicted" + + +@pytest.mark.parametrize("field,value", [("data_class", "public")]) +def test_a_tampered_trust_record_is_never_a_confirmed_approval(field: str, value: str) -> None: + """The intact record confirms; the same record with one signed field changed and the bundle and reference untouched + is record-invalid, not approval-confirmed (review of #350, 20 Oct 2026).""" + record = _load("01-approval-confirmed.json") + bundle = EXPECTED["cases"]["01-approval-confirmed.json"]["bundle"] + control = _assess(record, bundle) + assert control["trace_record_verifies"] is True + assert control["verdict"] == "approval-confirmed" + altered = copy.deepcopy(record) + assert altered[field] != value + altered[field] = value + result = _assess(altered, bundle) + assert result["trace_record_verifies"] is False + assert result["verdict"] == "record-invalid" + # the same holds with no bundle to read: an invalid record is not even an unconfirmed approval + assert _assess(altered, None)["verdict"] == "record-invalid" diff --git a/integrations/xchk-registry/tests/test_verdict_contract.py b/integrations/xchk-registry/tests/test_verdict_contract.py new file mode 100644 index 00000000..fe13c4de --- /dev/null +++ b/integrations/xchk-registry/tests/test_verdict_contract.py @@ -0,0 +1,201 @@ +"""Tests generated from verdict-contract.json (20 Oct 2026; vendored beside the verifier 2 Nov 2026). + +The oracle is the contract, not the verifier: each evidence row is deleted and/or tampered in a copy of a real, +genuine receipt, and the verifier must do what the row promises. A row the verifier cannot honour fails here first, +before a reviewer finds it. Run: pytest integrations/xchk-registry/tests -q +""" +from __future__ import annotations + +import base64 +import copy +import io +import json +import sys +from contextlib import redirect_stdout +from pathlib import Path + +import pytest + +HERE = Path(__file__).resolve().parent +sys.path.insert(0, str(HERE.parent)) +import verify_receipt as v # noqa: E402 + +CONTRACT = json.loads((HERE.parent / "verdict-contract.json").read_text(encoding="utf-8")) +FIXTURES = HERE.parent / "examples" / "approval-outcome" +_LOADED: dict = {} + + +def _fixture(row=None): + """The genuine receipt a row runs on: its own `fixture` when it names one (2 Nov 2026: the anchor-chain rows need a + receipt that carries anchor.proof, which no 17 Oct fixture does), else the contract's.""" + name = (row or {}).get("fixture", CONTRACT["fixture"]) + if name not in _LOADED: + _LOADED[name] = json.loads((FIXTURES / name).read_text(encoding="utf-8")) + return copy.deepcopy(_LOADED[name]) + + +FIXTURE_NAMES = sorted({CONTRACT["fixture"], *(r["fixture"] for r in CONTRACT["evidence"] if r.get("fixture"))}) +DEFAULT_MODE_FIXTURES = CONTRACT.get("defaultModeFixtures", {}) # 3 Nov 2026: fixture -> why strict mode cannot pass it +KEY_DOCUMENT = str(HERE.parent / "examples" / "approval-outcome" / CONTRACT["keyDocument"]) # 2 Nov 2026: rows with "keys": true run with --keys + + +def _walk(doc, path): + keys = path.split(".") + node = doc + for k in keys[:-1]: + node = node[int(k)] if isinstance(node, list) else node[k] + last = keys[-1] + return node, (int(last) if isinstance(node, list) else last) + + +def _delete(doc, path): + node, k = _walk(doc, path) + if isinstance(node, list): + node.pop(k) + else: + node.pop(k) + + +def _tamper(doc, path): + node, k = _walk(doc, path) + val = node[k] + if isinstance(val, bool): + node[k] = not val + elif isinstance(val, int): + node[k] = val + 1 + elif isinstance(val, str) and val: + i = len(val) // 2 # the middle: never padding, never a prefix + alphabet = "0123456789abcdef" if all(c in "0123456789abcdef" for c in val) else "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789" + swap = next(c for c in alphabet if c != val[i]) + node[k] = val[:i] + swap + val[i + 1:] + else: + raise AssertionError(f"contract row {path!r} points at a value that cannot be tampered: {val!r}") + + +def _reb64(original: str, raw: bytes) -> str: + """Re-encode in the alphabet and padding the bundle used, so only the bytes change.""" + urlsafe = "-" in original or "_" in original + out = (base64.urlsafe_b64encode if urlsafe else base64.b64encode)(raw).decode() + return out.rstrip("=") if not original.endswith("=") else out + + +def _clear_user_verified(doc, path): + """2 Nov 2026 (review of #350, drk-ram): the UV guard is pinned only by clearing the flag itself, bit 0x04 of the + authenticator data's flags byte (offset 32); a character swap anywhere else fails the signature, not this check.""" + node, k = _walk(doc, path) + raw = bytearray(v.b64d(node[k])) + assert raw[32] & 0x04, "the genuine ceremony was user-verified" + raw[32] &= 0xFB + node[k] = _reb64(node[k], bytes(raw)) + + +def _retype_as_registration(doc, path): + node, k = _walk(doc, path) + cd = json.loads(v.b64d(node[k]).decode("utf-8")) + assert cd["type"] == "webauthn.get" + cd["type"] = "webauthn.create" + node[k] = _reb64(node[k], json.dumps(cd, separators=(",", ":")).encode("utf-8")) + + +def _corrupt_op_return_root(doc, path): + """2 Nov 2026: the OP_RETURN guard is pinned only by altering the 32-byte root the transaction committed (payload + 'xCk' + 6 bytes + root); a swap anywhere else in the raw transaction fails sha256d(transaction) = txid first.""" + node, k = _walk(doc, path) + tx = bytearray(bytes.fromhex(node[k])) + i = tx.find(b"xCk") + assert i >= 0, "the genuine anchor transaction carries an xCk payload" + tx[i + 9] ^= 0x01 + node[k] = bytes(tx).hex() + + +def _corrupt_merkle_branch(doc, path): + """2 Nov 2026: the partial-Merkle-tree guard is pinned by altering the first branch hash, which sits after the + block header (120 bytes on Ravencoin), the tx count (4) and the hash count (1); a swap in the header part of the + merkleblock fails the header guard instead.""" + node, k = _walk(doc, path) + mb = bytearray(bytes.fromhex(node[k])) + hdr_len = len(bytes.fromhex(doc["anchor"]["proof"]["headerHex"])) + assert len(mb) > hdr_len + 5 + 32, "the genuine merkleblock carries at least one branch hash" + mb[hdr_len + 5] ^= 0x01 + node[k] = bytes(mb).hex() + + +def _shorten_ots_root(doc, path): + """2 Nov 2026: the 32-byte-root guard is pinned by retagging the final sha256 op before the Bitcoin attestation as + sha1 (0x02), so the replay ends in 20 bytes; a character swap elsewhere replays to a different 32-byte root, which + only the chain can contradict, and the verifier rightly reports it as an outside fact.""" + node, k = _walk(doc, path) + raw = bytearray(base64.b64decode(node[k])) + i = raw.find(v.OTS_BITCOIN) + assert i > 2 and raw[i - 1] == 0x00 and raw[i - 2] == 0x08, "the genuine proof ends in sha256 then the Bitcoin attestation" + raw[i - 2] = 0x02 + node[k] = _reb64(node[k], bytes(raw)) + + +OPS = {"clear-user-verified": _clear_user_verified, "retype-as-registration": _retype_as_registration, + "corrupt-op-return-root": _corrupt_op_return_root, "corrupt-merkle-branch": _corrupt_merkle_branch, + "shorten-ots-root": _shorten_ots_root} + + +def _run(doc, tmp_path, strict, keys=False): + p = tmp_path / "c.json" + p.write_text(json.dumps(doc), encoding="utf-8") + out = io.StringIO() + with redirect_stdout(out): + code, report = v.verify(str(p), require_approval=strict, keys_path=KEY_DOCUMENT if keys else None) + return code, report, out.getvalue() + + +@pytest.mark.parametrize("name", FIXTURE_NAMES) +def test_the_genuine_receipt_passes(name, tmp_path): + """Strict mode, except for a fixture the contract lists in defaultModeFixtures (3 Nov 2026): that one passes the + default run, and strict mode refuses it as the contract says, with nothing failed (exit 3, not 1).""" + strict = name not in DEFAULT_MODE_FIXTURES + if not strict: + code, _, out = _run(_fixture({"fixture": name}), tmp_path, strict=True) + assert code == 3, f"{name}: {DEFAULT_MODE_FIXTURES[name]}\n{out[-900:]}" + code, report, out = _run(_fixture({"fixture": name}), tmp_path, strict=strict) + assert code == 0, out + assert report["keyDocument"] is None + code, report, out = _run(_fixture({"fixture": name}), tmp_path, strict=strict, keys=True) + assert code == 0 and report["keyDocument"]["allPinned"] is True, out + if name == "anchored-unbatched.bundle.json": # 3 Nov 2026: the unbatched OP_RETURN guard ran and passed + assert "OK the raw anchor transaction's OP_RETURN carries this seal hash" in out, out[-900:] + if name == "anchored.bundle.json": # 2 Nov 2026: every anchor guard, and the identity-provider guard, ran and passed on the fixture that pins them + for text in ("manifest path (", "the raw anchor transaction's OP_RETURN carries that manifest root", "sha256d(transaction) = txid", + "merkleblock header is the block header shipped with the bundle", "partial Merkle tree reproduces the header's Merkle root", + "OpenTimestamps proof replays from the seal hash to a 32-byte Merkle root", + "binding names the identity provider that vouched for the approver"): + assert "OK " + text in out, f"the anchored fixture did not run the guard {text!r}\n{out[-900:]}" + + +DELETES = [r for r in CONTRACT["evidence"] if r.get("delete")] +TAMPERS = [r for r in CONTRACT["evidence"] if r.get("tamper")] + + +@pytest.mark.parametrize("row", DELETES, ids=[r["path"] for r in DELETES]) +def test_deleting_evidence_never_passes_strict_mode(row, tmp_path): + doc = _fixture(row) + for extra in row.get("delete_with", []): + _delete(doc, extra) + _delete(doc, row["path"]) + assert row["delete"] in ("strict-refuses", "fails") + if row["delete"] == "fails": # 20 Oct 2026: removing it is a failed check even in the default run + code, report, out = _run(doc, tmp_path, strict=False, keys=row.get("keys", False)) + assert code == 1, f"{row['path']} deleted, default exit {code}: {row['why']}\n{out[-600:]}" + if row.get("fail_text"): # 2 Nov 2026: and it is THIS check that failed, not a neighbour + assert "FAIL " + row["fail_text"] in out, f"{row['path']} deleted: no FAIL line starting {row['fail_text']!r}\n{out[-900:]}" + code, report, out = _run(doc, tmp_path, strict=True, keys=row.get("keys", False)) + assert code in (1, 3), f"{row['path']} deleted, strict exit {code}: {row['why']}\n{out[-600:]}" + + +@pytest.mark.parametrize("row", TAMPERS, ids=[(r["fixture"].split(".")[0] + "/" if r.get("fixture") else "") + r.get("tamper_key", r["path"]) + (":" + r["op"] if r.get("op") else "") for r in TAMPERS]) +def test_altering_evidence_fails(row, tmp_path): + doc = _fixture(row) + (OPS[row["op"]] if row.get("op") else _tamper)(doc, row.get("tamper_key", row["path"])) + code, report, out = _run(doc, tmp_path, strict=False, keys=row.get("keys", False)) + assert row["tamper"] == "fails" + assert code == 1, f"{row.get('tamper_key', row['path'])} altered, exit {code}: {row['why']}\n{out[-600:]}" + if row.get("fail_text"): # 2 Nov 2026 (review of #350, drk-ram): exit 1 alone pins nothing; the guard's own line must be there + assert "FAIL " + row["fail_text"] in out, f"{row['path']} altered: no FAIL line starting {row['fail_text']!r}\n{out[-900:]}" + assert report["boundIdentity"] is None and report["amendment"] is None diff --git a/integrations/xchk-registry/tests/test_verify_receipt_regressions.py b/integrations/xchk-registry/tests/test_verify_receipt_regressions.py new file mode 100644 index 00000000..5e5cc0c8 --- /dev/null +++ b/integrations/xchk-registry/tests/test_verify_receipt_regressions.py @@ -0,0 +1,766 @@ +"""Regressions for the vendored verify_receipt.py (19 Oct 2026). + +Two real bundles from the same credential: 01-approval-confirmed (an approved act on ENG-WNP3, 18 Oct 2026) and +03-decision-is-a-denial (a denial, the public trace-spec fixture at f152453e). Every signature in both is genuine. +The mutations below use nothing but the bundles' own bytes — no key, no re-signing — and each one must be refused. + +Run: pytest integrations/xchk-registry/tests -q (the verifier itself is standard-library only) +""" +from __future__ import annotations + +import copy +import hashlib +import io +import json +import sys +from contextlib import redirect_stdout +from pathlib import Path + +HERE = Path(__file__).resolve().parent +sys.path.insert(0, str(HERE.parent)) +import verify_receipt as v # noqa: E402 + +FX = HERE.parent / "examples" / "approval-outcome" + + +def load(name): + return json.loads((FX / name).read_text(encoding="utf-8")) + + +def run(bundle, tmp_path, name="b.json", **kw): + p = tmp_path / name + p.write_text(json.dumps(bundle), encoding="utf-8") + out = io.StringIO() + with redirect_stdout(out): + code = v.main(str(p), **kw) + return code, out.getvalue() + + +def test_controls_verify(tmp_path): + good, denied = load("01-approval-confirmed.bundle.json"), load("03-decision-is-a-denial.bundle.json") + assert good["approver"]["credentialId"] == denied["approver"]["credentialId"], "the two ceremonies share a credential" + assert good["approver"]["attestationId"] != denied["approver"]["attestationId"], "and are different ceremonies" + for b in (good, denied): + code, out = run(b, tmp_path) + assert code == 0, out + assert "the signed ask names the ceremony the sealed record commits to" in out + assert "the signed ask names the ceremony the registry bound to this credential" in out + assert "FAIL" not in out + # strict mode: the full approval has every piece of approval evidence + code, out = run(good, tmp_path, require_approval=True) + assert code == 0, out + + +def test_ceremony_transplant_is_refused(tmp_path): + """Finding 1: a genuine answer to ANOTHER ask by the same credential, beside this record's genuine signed binding. + Before the fix every check passed and the bundle read as this record's approval.""" + good, denied = load("01-approval-confirmed.bundle.json"), load("03-decision-is-a-denial.bundle.json") + b = copy.deepcopy(good) + for k in ("assertion", "challenge", "attestationId"): + b["approver"][k] = copy.deepcopy(denied["approver"][k]) + b["decision"] = copy.deepcopy(denied["decision"]) + assert b["record"] == good["record"] and b["approver"]["binding"] == good["approver"]["binding"] + assert b["approver"]["challenge"]["fields"]["attestationId"] == b["approver"]["attestationId"], "the outer field agrees with the transplant" + code, out = run(b, tmp_path) + assert code == 1, out + assert "FAIL the signed ask names the ceremony the sealed record commits to" in out + assert "FAIL the signed ask names the ceremony the registry bound to this credential" in out + # the device-side checks still pass on their own: the assertion is real, just not for this record + assert "OK passkey assertion signature verifies" in out + assert "OK the challenge the device signed is sha256 over the ask" in out + + +def test_missing_evidence_is_not_an_approval(tmp_path): + """Finding 2: stripping evidence leaves WAIT steps, exit 0, and a caller that read 0 as 'approval verified' was + wrong. Default semantics are unchanged (nothing failed); strict mode refuses.""" + good = load("01-approval-confirmed.bundle.json") + for what, strip in ( + ("approver block", lambda b: b.pop("approver")), + ("passkey assertion", lambda b: b["approver"].pop("assertion")), + ("registry-signed identity binding", lambda b: b["approver"].pop("binding")), + ("ask-v1 challenge", lambda b: b["approver"].pop("challenge")), + ): + b = copy.deepcopy(good) + strip(b) + code, out = run(b, tmp_path) + assert code == 0 and "RESULT: verifies offline" in out and "pending" in out, (what, out) + code, out = run(b, tmp_path, require_approval=True) + assert code == 3, (what, out) + assert "does NOT verify AS AN APPROVAL" in out, (what, out) + stripped = {k: good[k] for k in ("format", "record", "recordHash")} + code, out = run(stripped, tmp_path, require_approval=True) + assert code == 3, out + + +def test_relabelled_identity_is_not_what_is_printed(tmp_path): + """Finding 3 (the verifier's share of it): the identity line comes from the SIGNED binding, so an unsigned edit of + the outer email/authLevel changes nothing a reader is shown by the binding check.""" + good = load("01-approval-confirmed.bundle.json") + b = copy.deepcopy(good) + b["approver"]["email"] = "synthetic-other-person@example.invalid" + b["approver"]["authLevel"] = "synthetic-elevated-assurance" + code, out = run(b, tmp_path) + assert code == 0 + bound_email = good["approver"]["binding"]["fields"]["approverEmail"] + assert f"credential ↔ {bound_email}" in out + assert "synthetic-other-person" not in out.split("identity binding")[1].split("\n")[0] + + +def test_strict_flag_on_the_command_line(tmp_path): + import subprocess + good = load("01-approval-confirmed.bundle.json") + stripped = {k: good[k] for k in ("format", "record", "recordHash")} + p = tmp_path / "s.json" + p.write_text(json.dumps(stripped), encoding="utf-8") + r = subprocess.run([sys.executable, "-I", str(HERE.parent / "verify_receipt.py"), str(p), "--require-approval"], capture_output=True, text=True) + assert r.returncode == 3, r.stdout + r = subprocess.run([sys.executable, "-I", str(HERE.parent / "verify_receipt.py"), str(p)], capture_output=True, text=True) + assert r.returncode == 0, r.stdout + + +def test_amendment_is_what_the_sealed_record_commits_to(tmp_path): + """Finding 3: decision.amendment is unsigned text. 07 is a genuine approval with changes: the sealed record's + paramsHash recomputes over the amended action binding and the amendment cites the signed ask. An amendment typed + into the plain approval after issue, an amended command edited after issue, or an amendment citing another ask + all fail.""" + amended = load("07-amended.bundle.json") + code, out = run(amended, tmp_path, require_approval=True) + assert code == 0, out + assert "OK the sealed record commits to the amended action binding" in out + assert "OK the bound command is the amended command" in out + assert "OK the amendment cites the ask the person answered" in out + assert "approved WITH CHANGES" in out + good = load("01-approval-confirmed.bundle.json") + b = copy.deepcopy(good) + b["decision"]["amendment"] = {"command": "synthetic alternate command", "byEmail": good["decision"]["by"], + "at": good["decision"]["respondedAt"], "originalParamsHash": good["decision"]["actionParamsHash"]} + code, out = run(b, tmp_path) + assert code == 1 and "FAIL the sealed record commits to the amended action binding" in out, out + b = copy.deepcopy(amended) + b["decision"]["amendment"]["command"] += " ; synthetic extra" + code, out = run(b, tmp_path) + assert code == 1 and "FAIL the sealed record commits to the amended action binding" in out, out + b = copy.deepcopy(amended) + b["decision"]["amendment"]["originalParamsHash"] = "0" * 64 + code, out = run(b, tmp_path) + assert code == 1 and "FAIL the amendment cites the ask the person answered" in out, out + + +def _boundas(bundle): + """The exact preimage the registry hashed for 07, as a bundle served from 19 Oct 2026 carries it.""" + rec, am = bundle["record"], bundle["decision"]["amendment"] + return {"tool": rec["tool"], "command": am["command"], "path": None, "summary": rec["summary"], "amount": None, "artifactHash": None} + + +def test_the_served_preimage_is_checked_against_the_seal_and_the_amendment(tmp_path): + """amendment.boundAs is unsigned too: it counts only when it hashes to the SEALED paramsHash and its command is the + amended command. A preimage of another act, or a true preimage beside an edited amendment text, fails.""" + amended = load("07-amended.bundle.json") + b = copy.deepcopy(amended) + b["decision"]["amendment"]["boundAs"] = _boundas(amended) + code, out = run(b, tmp_path, require_approval=True) + assert code == 0 and "sha256 over amendment.boundAs" in out, out + b2 = copy.deepcopy(b) + b2["decision"]["amendment"]["boundAs"]["summary"] = "synthetic other summary" + code, out = run(b2, tmp_path) + assert code == 1 and "FAIL the sealed record commits to the amended action binding" in out, out + b3 = copy.deepcopy(b) + b3["decision"]["amendment"]["command"] = "synthetic alternate command" + code, out = run(b3, tmp_path) + assert code == 1 and "FAIL the bound command is the amended command" in out, out + for shape in (None, [], "x", {"command": 7}, {"tool": 1.5}): + b4 = copy.deepcopy(amended) + b4["decision"]["amendment"]["boundAs"] = shape + code, out = run(b4, tmp_path) + assert code in (0, 1) and "Traceback" not in out, (shape, out) + + +def test_a_long_summary_needs_the_served_preimage(): + """The record keeps the summary capped at 400 chars and trimmed; the registry hashed the full one (up to 2000). + Rebuilt from the record the binding cannot match; the served preimage does. JS slicing counts UTF-16 units.""" + full = " " + "\U0001F600" * 300 + "y" * 1600 + " " + rec = {"tool": "terminal", "summary": full[:400].strip()} + am = {"command": "rm -rf build/tmp"} + served = {"tool": "terminal", "command": "rm -rf build/tmp", "path": None, "summary": v.js_slice(full, 2000), "amount": None, "artifactHash": None} + rec["paramsHash"] = v.sha256_hex(v.canonical(served)) + rebuilt, was_served = v.amended_binding(rec, am) + assert not was_served and v.sha256_hex(v.canonical(rebuilt)) != rec["paramsHash"] + got, was_served = v.amended_binding(rec, dict(am, boundAs=served)) + assert was_served and v.sha256_hex(v.canonical(got)) == rec["paramsHash"] + assert len(v.js_slice(full, 2000).encode("utf-16-le")) == 4000 and len(v.js_slice(full, 2000)) < 2000 + + +def test_an_escalated_ask_without_a_digest_skips_only_the_citation(tmp_path): + """A second approver's ask carries no action digest (decision.actionParamsHash null): the citation is reported as + not checkable, the seal commitment is still required. Later on 20 Oct 2026: not checkable means pending and NOT + committed (it was reported committed before), and strict mode refuses.""" + b = copy.deepcopy(load("07-amended.bundle.json")) + b.pop("approver") + b["decision"]["actionParamsHash"] = None + code, out = run(b, tmp_path) + assert code == 0 and "the amendment's citation of it cannot be checked" in out and "OK the sealed record commits" in out, out + b["decision"]["amendment"]["command"] += " ; synthetic extra" + code, out = run(b, tmp_path) + assert code == 1, out + + +def test_json_report_names_what_ran(tmp_path): + """Finding 2: a caller acts on the structured report, not on exit 0. `checks` lists only what RAN; a stripped + bundle has fewer checks, the missing evidence named and exit 3 in strict mode; the amendment's standing is explicit + (null when none; committed only when the sealed record commits to it).""" + import subprocess + good = load("01-approval-confirmed.bundle.json") + p = tmp_path / "g.json" + p.write_text(json.dumps(good), encoding="utf-8") + out = io.StringIO() + with redirect_stdout(out): + code, rep = v.verify(str(p)) + assert code == 0 and rep["result"] == "verifies" and rep["exit"] == 0 and rep["amendment"] is None + assert rep["checks"] and all(c["status"] == "OK" for c in rep["checks"]) and rep["approvalEvidenceMissing"] == [] + full = len(rep["checks"]) + stripped = {k: good[k] for k in ("format", "record", "recordHash")} + p.write_text(json.dumps(stripped), encoding="utf-8") + with redirect_stdout(out): + code, rep = v.verify(str(p), require_approval=True) + assert code == 3 and rep["result"] == "approval-evidence-missing" + assert "approver block" in rep["approvalEvidenceMissing"] and len(rep["checks"]) < full + amended = load("07-amended.bundle.json") + p.write_text(json.dumps(amended), encoding="utf-8") + r = subprocess.run([sys.executable, "-I", str(HERE.parent / "verify_receipt.py"), str(p), "--json", "--require-approval"], capture_output=True, text=True, check=False) + rep = json.loads(r.stdout) + assert r.returncode == 0 and rep["exit"] == 0 and rep["amendment"]["committed"] is True + assert rep["amendment"]["command"] == amended["decision"]["amendment"]["command"] + assert any("approved WITH CHANGES" in line for line in rep["transcript"]) + + +def test_a_decision_that_is_not_an_object_is_a_verdict_not_a_crash(tmp_path): + good = load("01-approval-confirmed.bundle.json") + b = copy.deepcopy(good) + b["decision"] = "string" + code, out = run(b, tmp_path) + assert code == 1, out + + +def test_wrong_types_end_in_a_verdict_never_a_traceback(tmp_path): + """A type-mutation sweep over every field (19 Oct 2026) found 35 lines that raised on a string where an object + belongs, a float in a sealed body, a lone surrogate, bad base64. Each now ends in exit 1 and a JSON report.""" + good = load("01-approval-confirmed.bundle.json") + cases = [(("issuer",), None), (("record",), "x"), (("record", "seq"), 1.5), (("record", "summary"), "\ud83d"), + (("registrySignature",), "x"), (("registrySignature", "signatures"), [None]), (("seal",), -1), + (("approver", "binding", "fields"), "x"), (("approver", "challenge"), "x"), (("anchor",), "x"), + (("legalHolds",), "x")] + for path, val in cases: + b = copy.deepcopy(good) + node = b + for k in path[:-1]: + node = node[k] + node[path[-1]] = val + p = tmp_path / "m.json" + p.write_text(json.dumps(b), encoding="utf-8") + out = io.StringIO() + with redirect_stdout(out): + code, rep = v.verify(str(p), require_approval=True) + assert code == 1 and rep["exit"] == 1 and rep["result"] == "fails", (path, val, out.getvalue()[-300:]) + json.dumps(rep) + + +def test_identity_is_reported_from_the_signed_binding_only(tmp_path): + """Finding 3, the matrix row 'change only outer approver.email and authLevel': the structured report's identity + comes from approver.binding.fields; the relabelled bundle reports the bound person, and the transcript says the + readable labels differ.""" + good = load("01-approval-confirmed.bundle.json") + bound = good["approver"]["binding"]["fields"] + b = copy.deepcopy(good) + b["approver"]["email"] = "synthetic-other-person@example.invalid" + b["approver"]["authLevel"] = "synthetic-elevated-assurance" + p = tmp_path / "r.json" + p.write_text(json.dumps(b), encoding="utf-8") + out = io.StringIO() + with redirect_stdout(out): + code, rep = v.verify(str(p), require_approval=True) + assert code == 0, out.getvalue() + assert rep["boundIdentity"]["email"] == bound["approverEmail"] and rep["boundIdentity"]["authLevel"] == bound["authLevel"] + assert "synthetic" not in json.dumps(rep["boundIdentity"]) + assert "readable approver labels differ from the signed binding" in out.getvalue() + p.write_text(json.dumps(good), encoding="utf-8") + with redirect_stdout(io.StringIO()) as quiet: + code, rep = v.verify(str(p)) + assert code == 0 and "labels differ" not in quiet.getvalue() + + +def test_an_amendment_on_a_record_that_seals_no_digest_is_pending_not_failed(tmp_path): + """Ceremony records sealed before 19 Sep 2026 carry no paramsHash, so the seal commits to no command. The amendment + is then not checkable: a WAIT, committed false, and never the 'sealed record commits' FAIL (that falsely failed + four genuine September receipts). Built from 07 with paramsHash removed: the record hash then fails, as it must, + and the amendment line is still the WAIT.""" + b = copy.deepcopy(load("07-amended.bundle.json")) + del b["record"]["paramsHash"] + p = tmp_path / "nd.json" + p.write_text(json.dumps(b), encoding="utf-8") + out = io.StringIO() + with redirect_stdout(out): + code, rep = v.verify(str(p)) + text = out.getvalue() + assert rep["amendment"] is None # 2 Nov 2026: the record hash fails below, and a report that does not verify commits to nothing + assert "seals no action digest" in text and "FAIL the sealed record commits" not in text + assert "FAIL record hash recomputed" in text and code == 1 + + +def test_approval_evidence_without_the_seal_chain_is_not_a_sealed_approval(tmp_path): + """Review of #350 (noah-ing, 20 Oct 2026): from the valid 01 receipt, deleting only the seal, only the Merkle path, + both, or only the registry's signature over the seal left the approval evidence intact and strict mode passed. + Strict mode now also requires the seal chain and says which part is missing; the default run still exits 0 with + the steps pending, as before.""" + good = load("01-approval-confirmed.bundle.json") + cases = { + "seal": (lambda b: b.pop("seal"), "the seal over the record's window"), + "merkle": (lambda b: b.pop("merkle"), "the Merkle path from the record to the seal"), + "seal+merkle": (lambda b: (b.pop("seal"), b.pop("merkle")), "the seal over the record's window"), + "seal signature": (lambda b: [b["registrySignature"].pop(k, None) for k in ("signature", "signatures")], "the registry's signature over the seal"), + } + for name, (mutate, missing) in cases.items(): + b = copy.deepcopy(good) + mutate(b) + p = tmp_path / "s.json" + p.write_text(json.dumps(b), encoding="utf-8") + with redirect_stdout(io.StringIO()) as out: + code, rep = v.verify(str(p), require_approval=True) + assert code == 3 and rep["result"] == "seal-chain-incomplete", (name, out.getvalue()[-400:]) + assert missing in rep["sealChainMissing"] and rep["approvalEvidenceMissing"] == [], name + assert "does NOT verify AS A SEALED APPROVAL" in out.getvalue(), name + with redirect_stdout(io.StringIO()): + code, rep = v.verify(str(p)) + assert code == 0 and rep["result"] == "verifies" and missing in rep["sealChainMissing"], name + p = tmp_path / "g.json" + p.write_text(json.dumps(good), encoding="utf-8") + with redirect_stdout(io.StringIO()): + code, rep = v.verify(str(p), require_approval=True) + assert code == 0 and rep["sealChainMissing"] == [], "the sealed control still passes strict mode" + + +def test_a_decision_citing_another_record_is_refused(tmp_path): + """Section 5b (20 Oct 2026): the decision block must cite the sealed record's attestationHash. The browser verifier + has checked this since 19 Sep; the Python verifier did not, until a written contract of what each piece of evidence + must do found the gap. The mutation uses another real ceremony's value, from the denial bundle.""" + good, denied = load("01-approval-confirmed.bundle.json"), load("03-decision-is-a-denial.bundle.json") + assert good["decision"]["attestationHash"] == good["record"]["attestationHash"] + b = copy.deepcopy(good) + b["decision"]["attestationHash"] = denied["decision"]["attestationHash"] + assert b["decision"]["attestationHash"] != good["record"]["attestationHash"] + code, out = run(b, tmp_path) + assert code == 1, out + assert "the decision block does NOT cite this record's attestation hash" in out + code, out = run(good, tmp_path) + assert code == 0 and "the decision block cites this record's attestation hash" in out, out + + +def test_a_decision_without_the_citation_is_refused(tmp_path): + """Section 5b, later on 20 Oct 2026 (review of #350, private): the check above ran only when the citation was present, + so a decision block with `attestationHash` removed (or null) skipped it and the verdict stayed approval-confirmed. + Every ceremony record the registry has written since the ledger began (7 Aug 2026) carries the attestation hash, sealed + before the record is appended, and every decision block it issues cites it: a decision block with no citation was never + issued. Its absence is a failed check in the default run and in strict mode, never a pending step.""" + good = load("01-approval-confirmed.bundle.json") + assert good["decision"]["attestationHash"] + for mutate in (lambda d: d.pop("attestationHash"), lambda d: d.__setitem__("attestationHash", None), lambda d: d.__setitem__("attestationHash", "")): + b = copy.deepcopy(good) + mutate(b["decision"]) + code, out = run(b, tmp_path) + assert code == 1, out + assert "the decision block carries NO attestation-hash citation" in out + code, out = run(b, tmp_path, require_approval=True) + assert code == 1, out + code, out = run(good, tmp_path, require_approval=True) + assert code == 0, out + + +def test_an_amendment_without_the_asks_digest_is_never_committed(tmp_path): + """Later on 20 Oct 2026 (review of #350, the class of 5b): without decision.actionParamsHash the citation leg of 5c + defaulted to 'cites', so a bundle with the digest removed reported the amendment COMMITTED on a check that never ran. + With the challenge present the removal fails in 5a; without one (a bundle issued before 18 Oct 2026) nothing failed. + Now: citation pending, never committed, strict mode refuses, and the control still commits.""" + import io as _io + from contextlib import redirect_stdout as _rs + good = load("07-amended.bundle.json") + assert good["decision"]["actionParamsHash"] and good["approver"].get("challenge") + + def rep_of(b, strict=False): + p = tmp_path / "amend.json" + p.write_text(json.dumps(b), encoding="utf-8") + out = _io.StringIO() + with _rs(out): + code, rep = v.verify(str(p), require_approval=strict) + return code, rep, out.getvalue() + + code, rep, _ = rep_of(copy.deepcopy(good)) + assert code == 0 and rep["amendment"]["committed"] is True and rep["amendment"]["citesAsk"] is True + b = copy.deepcopy(good) + b["decision"].pop("actionParamsHash") + b["approver"].pop("challenge") # the shape of a bundle issued before 18 Oct 2026 + code, rep, out = rep_of(b) + assert code == 0, out # nothing FAILED: the steps that could not run are pending + assert rep["amendment"]["committed"] is False and rep["amendment"]["citesAsk"] is None, rep["amendment"] + assert "the amendment's citation of it cannot be checked" in out + code, rep, _ = rep_of(b, strict=True) + assert code == 3 and "the ask's action digest (decision.actionParamsHash), which the amendment must cite" in rep["approvalEvidenceMissing"] + b = copy.deepcopy(good) + b["decision"].pop("actionParamsHash") # challenge kept: the signed ask no longer matches + code, rep, _ = rep_of(b) + assert code == 1 and rep["amendment"] is None # 2 Nov 2026: withheld on a failed verdict + + +def test_a_hybrid_signature_with_a_half_removed_is_refused(tmp_path): + """Review of #350 (rajnisht7, 2 Nov 2026): the verifier checked only the signatures a bundle carried, so a hybrid + signature with either half removed, the list removed down to the legacy single field, or the `alg` label rewritten + to match, still verified under --require-approval. The required set now comes from signed fields (the sealed + profile's signing dial; for older seals the seal's windowStart), on the seal, the profile and the binding alike.""" + for name in ("01-approval-confirmed.bundle.json", "07-amended.bundle.json"): + good = load(name) + assert [s["alg"] for s in good["registrySignature"]["signatures"]] == ["ed25519", "ml-dsa-65"] + assert good["profile"]["document"]["dials"]["signing"] == "ed25519+ml-dsa-65" + for drop in ("ml-dsa-65", "ed25519"): + b = copy.deepcopy(good) + b["registrySignature"]["signatures"] = [s for s in b["registrySignature"]["signatures"] if s["alg"] != drop] + code, out = run(b, tmp_path, require_approval=True) + assert code == 1 and f"the {drop} signature this receipt requires is missing" in out, out + b = copy.deepcopy(good) + del b["registrySignature"]["signatures"] # the legacy single Ed25519 field is left + code, out = run(b, tmp_path) + assert code == 1 and "ml-dsa-65 signature this receipt requires is missing" in out, out + b = copy.deepcopy(good) + b["registrySignature"]["signatures"] = b["registrySignature"]["signatures"][:1] + b["registrySignature"]["alg"] = "ed25519" # relabelled to match: the label is not consulted + code, out = run(b, tmp_path) + assert code == 1 and "ml-dsa-65 signature this receipt requires is missing" in out, out + for where in (("profile", "signature"), ("approver", "binding")): + b = copy.deepcopy(good) + obj = b[where[0]][where[1]] + obj["signatures"] = [s for s in obj["signatures"] if s["alg"] != "ml-dsa-65"] + code, out = run(b, tmp_path) + assert code == 1 and "ml-dsa-65 signature this receipt requires is missing" in out, (where, out) + + +def test_a_report_that_does_not_verify_names_nobody_and_commits_to_nothing(tmp_path): + """Review of #350 (rajnisht7, 2 Nov 2026): on a receipt whose seal signature is corrupted, boundIdentity and + amendment.committed were still fully populated, so a caller reading them before the exit code could act on them. + Both are null on every non-zero exit, strict refusals included.""" + def rep_of(b, strict=False): + p = tmp_path / "r.json" + p.write_text(json.dumps(b), encoding="utf-8") + with redirect_stdout(io.StringIO()): + return v.verify(str(p), require_approval=strict) + good = load("07-amended.bundle.json") + code, rep = rep_of(good) + assert code == 0 and rep["boundIdentity"]["email"] and rep["amendment"]["committed"] is True + b = copy.deepcopy(good) + sig = b["registrySignature"]["signatures"][0]["signature"] + i = len(sig) // 2 + b["registrySignature"]["signatures"][0]["signature"] = sig[:i] + ("A" if sig[i] != "A" else "B") + sig[i + 1:] + code, rep = rep_of(b) + assert code == 1 and rep["failed"] >= 1 and rep["boundIdentity"] is None and rep["amendment"] is None, rep + b = copy.deepcopy(good) + del b["seal"] # strict refuses: nothing failed, nothing is reported either + code, rep = rep_of(b, strict=True) + assert code == 3 and rep["boundIdentity"] is None and rep["amendment"] is None, rep + + +def test_the_verifier_writes_utf8_whatever_the_console_locale(tmp_path): + """Review of #350 (drk-ram, 2 Nov 2026, Windows): under a cp1252 console the human lines (U+2194, an em dash) and + the --json report raised UnicodeEncodeError, exit 1 with a traceback — the exit of a failed check. The CLI now + reconfigures stdout to UTF-8; here PYTHONIOENCODING stands in for the Windows console.""" + import os + import subprocess + env = dict(os.environ, PYTHONIOENCODING="cp1252", PYTHONUTF8="0", PYTHONLEGACYWINDOWSSTDIO="1") + bundle = str(FX / "01-approval-confirmed.bundle.json") + for flags in ([], ["--json", "--require-approval"]): + r = subprocess.run([sys.executable, str(HERE.parent / "verify_receipt.py"), bundle] + flags, capture_output=True, env=env, timeout=180) + assert r.returncode == 0 and b"UnicodeEncodeError" not in r.stderr, r.stderr.decode(errors="replace")[-600:] + if flags: + assert json.loads(r.stdout.decode("utf-8"))["exit"] == 0 + + +def test_required_algs_reads_signed_fields_only(): + """2 Nov 2026 (review): the profile's signing dial decides when a profile is sealed; the seal's own windowStart + otherwise; nothing when the bundle is not sealed. The alg label and the key list are never consulted.""" + pre, post = {"windowStart": "2026-09-06T14:55:12.187Z"}, {"windowStart": "2026-10-17T15:44:25.565Z"} + assert v.required_algs(pre, None) == {"ed25519"} + assert v.required_algs(post, None) == {"ed25519", "ml-dsa-65"} + assert v.required_algs(post, {"dials": {"signing": "ed25519"}}) == {"ed25519"} + assert v.required_algs(pre, {"dials": {"signing": "ed25519+ml-dsa-65"}}) == {"ed25519", "ml-dsa-65"} + assert v.required_algs(post, {"dials": {"signing": "none"}}) == {"ed25519", "ml-dsa-65"} # no dial: the date decides + assert v.required_algs(None, None) is None and v.required_algs({"windowStart": 5}, None) is None + assert v.binding_required({"signing": "ed25519"}, {"ed25519", "ml-dsa-65"}) == {"ed25519"} + assert v.binding_required({"approverEmail": "x"}, {"ed25519"}) == {"ed25519"} + + +def test_an_edited_dial_does_not_relax_the_requirement(tmp_path): + """The profile's signing dial is read only from a document that hashes to the sealed profileHash, so an editor who + writes `signing: ed25519` into the bundle and strips the post-quantum half gets BOTH failures: the profile no longer + hashes, and the date fallback still requires the half. (The review's mutant that skips the genuine-dial branch + cannot be killed with today's fixtures: every sealed profile is from after the switch and agrees with the date; a + receipt from a registry whose sealed profile says `ed25519` after the switch would pin it.) A binding that carries + its own mode inside the signed fields is decided by that mode; editing it fails the binding's signature instead.""" + good = load("01-approval-confirmed.bundle.json") + b = copy.deepcopy(good) + b["profile"]["document"]["dials"]["signing"] = "ed25519" + b["registrySignature"]["signatures"] = b["registrySignature"]["signatures"][:1] + code, out = run(b, tmp_path) + assert code == 1 and "FAIL profile document does NOT hash" in out + assert "registry signature over the seal hash: the ml-dsa-65 signature this receipt requires is missing" in out, out + b = copy.deepcopy(good) + b["approver"]["binding"]["fields"]["signing"] = "ed25519" + b["approver"]["binding"]["signatures"] = b["approver"]["binding"]["signatures"][:1] + code, out = run(b, tmp_path) + assert code == 1 and "DOES NOT verify" in out # the edited fields no longer match the signature + assert "identity binding" in out and "this receipt requires is missing" not in out, out + + +def test_a_required_half_that_cannot_be_checked_here_is_not_a_pass(tmp_path, monkeypatch): + """Review of round one (2 Nov 2026): without dilithium-py the ML-DSA slot is a WAIT, and a required WAIT counted as + present, so garbage in that slot passed even --require-approval. Now strict mode refuses and names the half; the + default run stays a WAIT, as every unverifiable step does. With dilithium-py present the same garbage simply fails.""" + def rep_of(b, strict=False): + p = tmp_path / "w.json" + p.write_text(json.dumps(b), encoding="utf-8") + out = io.StringIO() + with redirect_stdout(out): + code, rep = v.verify(str(p), require_approval=strict) + return code, rep, out.getvalue() + good = load("01-approval-confirmed.bundle.json") + b = copy.deepcopy(good) + b["registrySignature"]["signatures"][1]["signature"] = "AAAA" + if v.ml_dsa_65_verify(b"\x00" * 32, b"m", b"s") is not None: # dilithium-py present: the garbage half is a failed check + code, rep, out = rep_of(b, strict=True) + assert code == 1 and "ml-dsa-65 signature DOES NOT verify" in out + monkeypatch.setattr(v, "ml_dsa_65_verify", lambda *a: None) # the stock install: the half cannot be checked + code, rep, out = rep_of(b) + assert code == 0 and rep["pending"] >= 1 and "WAIT registry signature over the seal hash: ml-dsa-65" in out, out + code, rep, out = rep_of(b, strict=True) + # with no ML-DSA at all, the binding's and the profile's halves are unverifiable too: strict names every one of them + assert code == 3 and rep["result"] in ("seal-chain-incomplete", "approval-evidence-missing"), out + assert any(s.startswith("registry signature over the seal hash: its ml-dsa-65 half, which this receipt requires") for s in rep["sealChainMissing"]), rep + assert any("identity binding" in s and "ml-dsa-65 half" in s for s in rep["approvalEvidenceMissing"]), rep + b = copy.deepcopy(good) + b["approver"]["binding"]["signatures"][1]["signature"] = "AAAA" + code, rep, out = rep_of(b, strict=True) + assert code == 3 and any("identity binding" in s and "ml-dsa-65 half" in s for s in rep["approvalEvidenceMissing"]), rep + + +def test_withheld_names_what_a_failed_report_leaves_out(tmp_path): + """So a consumer can tell absent from withheld (review of round one): null fields come with `withheld` naming them + on every non-zero exit, and `withheld` is empty on a verdict of 0.""" + def rep_of(b, strict=False): + p = tmp_path / "wh.json" + p.write_text(json.dumps(b), encoding="utf-8") + with redirect_stdout(io.StringIO()): + return v.verify(str(p), require_approval=strict) + good = load("07-amended.bundle.json") + code, rep = rep_of(good) + assert code == 0 and rep["withheld"] == [] and rep["amendment"]["committed"] is True + b = copy.deepcopy(good) + del b["seal"] + code, rep = rep_of(b, strict=True) + assert code == 3 and rep["withheld"] == ["boundIdentity", "amendment"] and rep["boundIdentity"] is None + + +def test_the_artifact_check_pins_the_file(tmp_path): + """The --artifact path: the file's sha256 against the record's artifactHash. No fixture is a file-write record, so + the record hash fails here by construction; the two file lines are what this pins (unpinned until 2 Nov 2026).""" + good = load("01-approval-confirmed.bundle.json") + f1, f2 = tmp_path / "written.bin", tmp_path / "other.bin" + f1.write_bytes(b"the bytes this action wrote") + f2.write_bytes(b"some other bytes") + b = copy.deepcopy(good) + b["record"]["artifactHash"] = hashlib.sha256(f1.read_bytes()).hexdigest() + p = tmp_path / "a.json" + p.write_text(json.dumps(b), encoding="utf-8") + for f, want in ((f1, "OK file"), (f2, "FAIL file")): + out = io.StringIO() + with redirect_stdout(out): + code = v.main(str(p), str(f)) + assert code == 1 and f"{want} {f} is {'the one' if want.startswith('OK') else 'NOT the one'} this action wrote" in out.getvalue(), out.getvalue() + out = io.StringIO() + with redirect_stdout(out): + v.main(str(p), artifact_path=str(f1)) # the keyword form the CLI uses + assert "is the one this action wrote" in out.getvalue() + out = io.StringIO() + with redirect_stdout(out): + pg = tmp_path / "g.json" + pg.write_text(json.dumps(good), encoding="utf-8") + v.main(str(pg), str(f1)) + assert "FAIL this record carries no artifactHash" in out.getvalue() + + +KEY_DOCUMENTS = FX / "xchk-keys" # the registries' /.well-known/xchk-keys.json as served on 2 Nov 2026 + + +def _rep(bundle, tmp_path, strict=False, keys=None): + p = tmp_path / "k.json" + p.write_text(json.dumps(bundle), encoding="utf-8") + out = io.StringIO() + with redirect_stdout(out): + code, rep = v.verify(str(p), require_approval=strict, keys_path=keys) + return code, rep, out.getvalue() + + +def test_a_bundle_re_keyed_outside_the_registry_passes_until_the_key_document_is_supplied(tmp_path): + """Review of #350 (drk-ram, 2 Nov 2026): fixture 01 re-signed under his own Ed25519 and ML-DSA-65 keys, the pinned + list and the root statement's list rewritten to match, still exited 0 under --require-approval, because every key + the verifier checks is the one the bundle carries. Fixture 09 is that bundle (verify/tests/rekey_fixture.py). With + --keys and the registry's published key document, every pinned key fails BY NAME; the genuine receipts pass.""" + rekeyed = load("09-re-keyed-outside-the-registry.bundle.json") + genuine = load("01-approval-confirmed.bundle.json") + assert rekeyed["record"] == genuine["record"] and rekeyed["seal"] == genuine["seal"], "the sealed content is untouched" + own = {k["alg"]: k["keyId"] for k in rekeyed["registrySignature"]["keys"]} + assert own != {k["alg"]: k["keyId"] for k in genuine["registrySignature"]["keys"]} + code, rep, out = _rep(rekeyed, tmp_path, strict=True) # the finding, reproduced + assert code == 0 and "FAIL" not in out and rep["keyDocument"] is None, out + assert "checked against THEMSELVES only" in out + doc = str(KEY_DOCUMENTS / "in.xchk.io.2026-11-02.json") + code, rep, out = _rep(rekeyed, tmp_path, strict=True, keys=doc) # closed + assert code == 1 and rep["result"] == "fails", out + for alg, kid in own.items(): + assert f"FAIL the registry's key document does not list pinned key {alg}/{kid}" in out, out + assert rep["keyDocument"] == {"registry": "https://in.xchk.io", "servedAt": "2026-11-02T03:01:09.306Z", "allPinned": False} + assert rep["boundIdentity"] is None + for name in ("01-approval-confirmed", "03-decision-is-a-denial", "07-amended"): + code, rep, out = _rep(load(name + ".bundle.json"), tmp_path, keys=doc) + assert code == 0 and rep["keyDocument"]["allPinned"] is True, (name, out) + assert "lists pinned key ed25519/5ecb3da505414c4f" in out and "is the registry's root key" in out, (name, out) + + +def test_the_other_registrys_key_document_refuses_this_registrys_receipt(tmp_path): + """xchk.me publishes its own keys and root: an in.xchk.io receipt checked against it fails on every pinned key and on + the root. The document the relying party pins decides which registry it trusts.""" + code, rep, out = _rep(load("01-approval-confirmed.bundle.json"), tmp_path, keys=str(KEY_DOCUMENTS / "xchk.me.2026-11-02.json")) + assert code == 1 and rep["keyDocument"]["allPinned"] is False, out + assert "FAIL the registry's key document does not list pinned key ed25519/5ecb3da505414c4f" in out + assert "FAIL the bundle's root key acc7ad1aeb3ef177 is NOT the registry's root key" in out + + +def test_a_retired_key_still_pins_and_a_revoked_key_fails(tmp_path): + """A receipt sealed under a key the registry has since retired must keep verifying (the document keeps retired keys); + one sealed under a key the registry revoked must not. Neither registry has retired or revoked a key yet (2 Nov 2026), + so the two states are made from the real document.""" + real = json.loads((KEY_DOCUMENTS / "in.xchk.io.2026-11-02.json").read_text(encoding="utf-8")) + good = load("01-approval-confirmed.bundle.json") + pinned = {k["keyId"] for k in good["registrySignature"]["keys"]} + for state, want_code in (("retired", 0), ("revoked", 1)): + doc = copy.deepcopy(real) + moved = [k for k in doc["keys"] if k["keyId"] in pinned] + doc["keys"] = [k for k in doc["keys"] if k["keyId"] not in pinned] # the revocation-bundle key stays active + doc[state] = [dict(k, status=state, **({"revokedAt": "2026-11-01T00:00:00Z"} if state == "revoked" else {})) for k in moved] + p = tmp_path / f"{state}.json" + p.write_text(json.dumps(doc), encoding="utf-8") + code, rep, out = _rep(good, tmp_path, strict=True, keys=str(p)) + assert code == want_code, (state, out) + if state == "retired": + assert "lists pinned key ed25519/5ecb3da505414c4f as retired" in out and rep["keyDocument"]["allPinned"] is True + else: + assert "FAIL the registry's key document lists pinned key ed25519/5ecb3da505414c4f as REVOKED since 2026-11-01T00:00:00Z" in out + assert rep["keyDocument"]["allPinned"] is False + + +def test_a_key_document_that_cannot_be_read_is_a_refusal_not_a_skipped_check(tmp_path): + """Fail closed: --keys names a file that is missing, not JSON, or not a key document → exit 2, never a pass.""" + good = load("01-approval-confirmed.bundle.json") + bad = tmp_path / "notkeys.json" + for content in (None, "{not json", json.dumps({"registry": "x"}), json.dumps([]), json.dumps({"keys": []})): + if content is None: + bad.unlink(missing_ok=True) + else: + bad.write_text(content, encoding="utf-8") + code, rep, out = _rep(good, tmp_path, keys=str(bad)) + assert code == 2 and rep["result"] == "unreadable" and "could not read key document" in out, (content, out) + + +def test_keys_on_the_command_line(tmp_path): + import subprocess + script = str(HERE.parent / "verify_receipt.py") + bundle = str(FX / "09-re-keyed-outside-the-registry.bundle.json") + doc = str(KEY_DOCUMENTS / "in.xchk.io.2026-11-02.json") + r = subprocess.run([sys.executable, "-I", script, bundle, "--require-approval"], capture_output=True, text=True, check=False) + assert r.returncode == 0, r.stdout + r = subprocess.run([sys.executable, "-I", script, bundle, "--keys", doc, "--require-approval", "--json"], capture_output=True, text=True, check=False) + rep = json.loads(r.stdout) + assert r.returncode == 1 and rep["exit"] == 1 and rep["keyDocument"]["allPinned"] is False, r.stdout[-400:] + assert any("does not list pinned key" in line for line in rep["transcript"]) + r = subprocess.run([sys.executable, "-I", script, "--keys", doc, bundle], capture_output=True, text=True, check=False) # flag first + assert r.returncode == 1, r.stdout[-400:] + for argv in ([bundle, "--keys"], [bundle, "--keys", "--json"], [bundle, "--kyes", doc]): # a flag with no file, or a misspelt flag + r = subprocess.run([sys.executable, "-I", script] + argv, capture_output=True, text=True, check=False) + assert r.returncode == 2, (argv, r.stdout[-200:]) + + +def test_a_revoked_key_is_refused_however_the_document_says_it(tmp_path): + """Review of the key-pinning change (2 Nov 2026): list membership alone read `status: revoked` left in place as + pinned, and a revoked entry published without its public key (the registry serves publicKeyRaw null on revoked + keys) fell through to "never published", exit 1 for the wrong reason. Three shapes of the same revocation.""" + real = json.loads((KEY_DOCUMENTS / "in.xchk.io.2026-11-02.json").read_text(encoding="utf-8")) + good = load("01-approval-confirmed.bundle.json") + ed = next(k for k in real["keys"] if k["alg"] == "ed25519" and k["keyId"] == "5ecb3da505414c4f") + shapes = { + "status revoked in place": lambda d: ed.update(status="revoked", revokedAt="2026-11-01T00:00:00Z"), + "revoked entry with null key still in keys": lambda d: ed.update(status="revoked", revokedAt="2026-11-01T00:00:00Z", publicKeyRaw=None), + "revoked entry with null key in the revoked list": lambda d: (d["keys"].remove(ed), d["revoked"].append(dict(ed, status="revoked", revokedAt="2026-11-01T00:00:00Z", publicKeyRaw=None))), + } + for name, shape in shapes.items(): + doc = copy.deepcopy(real) + ed = next(k for k in doc["keys"] if k["keyId"] == "5ecb3da505414c4f") + shape(doc) + p = tmp_path / "rv.json" + p.write_text(json.dumps(doc), encoding="utf-8") + code, rep, out = _rep(good, tmp_path, strict=True, keys=str(p)) + assert code == 1 and rep["keyDocument"]["allPinned"] is False, (name, out) + assert "FAIL the registry's key document lists pinned key ed25519/5ecb3da505414c4f as REVOKED since 2026-11-01T00:00:00Z" in out, (name, out) + assert "never published" not in out, (name, out) + + +def test_the_right_key_id_under_a_different_public_key_fails(tmp_path): + """The document and the bundle agree on alg and keyId but not on the key: the pinned key is not the one the registry + published under that id. Asserted on its own (the contract's keyId tamper covers only the id).""" + real = json.loads((KEY_DOCUMENTS / "in.xchk.io.2026-11-02.json").read_text(encoding="utf-8")) + doc = copy.deepcopy(real) + ed = next(k for k in doc["keys"] if k["keyId"] == "5ecb3da505414c4f") + ed["publicKeyRaw"] = "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA=" # 32 zero bytes: a valid Ed25519 key, not the registry's + p = tmp_path / "diff.json" + p.write_text(json.dumps(doc), encoding="utf-8") + code, rep, out = _rep(load("01-approval-confirmed.bundle.json"), tmp_path, keys=str(p)) + assert code == 1 and rep["keyDocument"]["allPinned"] is False, out + assert "FAIL the registry's key document lists keyId 5ecb3da505414c4f with a DIFFERENT ed25519 public key" in out, out + + +def test_a_root_only_mismatch_is_not_pinned(tmp_path): + """Every pinned key listed, only the root wrong or absent: allPinned must be False, not merely exit 1 (a mutant that + dropped the root from allPinned survived the first sweep); a document with no root does not skip the check.""" + real = json.loads((KEY_DOCUMENTS / "in.xchk.io.2026-11-02.json").read_text(encoding="utf-8")) + other = json.loads((KEY_DOCUMENTS / "xchk.me.2026-11-02.json").read_text(encoding="utf-8")) + good = load("01-approval-confirmed.bundle.json") + doc = copy.deepcopy(real) + doc["root"] = other["root"] + p = tmp_path / "root.json" + p.write_text(json.dumps(doc), encoding="utf-8") + code, rep, out = _rep(good, tmp_path, keys=str(p)) + assert code == 1 and rep["keyDocument"]["allPinned"] is False, out + assert "FAIL the bundle's root key acc7ad1aeb3ef177 is NOT the registry's root key" in out and "lists pinned key ed25519/5ecb3da505414c4f\n" in out, out + doc = copy.deepcopy(real) + del doc["root"] + p.write_text(json.dumps(doc), encoding="utf-8") + code, rep, out = _rep(good, tmp_path, keys=str(p)) + assert code == 1 and rep["keyDocument"]["allPinned"] is False, out + assert "FAIL the bundle carries root key acc7ad1aeb3ef177 but the registry's key document publishes no root key" in out, out + + +def test_key_document_shapes_a_bom_loads_and_non_keys_are_unreadable(tmp_path): + """A copy saved by an editor with a byte-order mark is the same document; a `keys` list of non-keys is not a key + document and is exit 2, as the docstring promises, never exit 1 with a null registry.""" + good = load("01-approval-confirmed.bundle.json") + real = (KEY_DOCUMENTS / "in.xchk.io.2026-11-02.json").read_bytes() + p = tmp_path / "bom.json" + p.write_bytes(b"\xef\xbb\xbf" + real) + code, rep, out = _rep(good, tmp_path, keys=str(p)) + assert code == 0 and rep["keyDocument"]["allPinned"] is True, out + for shape in ({"keys": [1, 2]}, {"keys": [{"alg": "ed25519"}]}, {"keys": [{"alg": "ed25519", "keyId": "x"}], "revoked": ["y"]}): + p.write_text(json.dumps(shape), encoding="utf-8") + code, rep, out = _rep(good, tmp_path, keys=str(p)) + assert code == 2 and rep["result"] == "unreadable" and rep["keyDocument"] is None, (shape, out) diff --git a/integrations/xchk-registry/verdict-contract.json b/integrations/xchk-registry/verdict-contract.json new file mode 100644 index 00000000..05910f33 --- /dev/null +++ b/integrations/xchk-registry/verdict-contract.json @@ -0,0 +1,68 @@ +{ + "about": "What verify_receipt.py promises about a receipt bundle, written down so tests come from the promise and not from the code (20 Oct 2026, after four review rounds on agentrust-io/integrations#350 each found a hole the code's own tests could not). Every entry is one piece of evidence in a bundle. 'delete' = what removing it must do; 'tamper' = what altering its value must do. Outcomes: 'strict-refuses' = with --require-approval the exit is never 0 (1 or 3); 'fails' = in the default run the exit is 1 (for 'delete', removing it is a failed check in the default run, and so in strict mode too). A new check in the verifier gets a row here first; a row that cannot be honoured is a bug in the verifier, not in this file. A row with 'keys': true runs with --keys and the key document named in keyDocument (2 Nov 2026): without a key document the verifier checks the bundle's keys only against themselves. A row may name its own 'fixture' (2 Nov 2026): the anchor-chain rows run on anchored.bundle.json, a receipt sealed on 29 Oct 2026 and fetched from in.xchk.io on 2 Nov 2026, the first fixture to carry anchor.proof (a batched Ravencoin anchor with its manifest path) and an OpenTimestamps proof upgraded to a Bitcoin block; the 17 Oct fixtures and the 20 Oct corpus predate batched anchoring and left all seven anchor guards unpinned (guard-mutation sweep, 2 Nov 2026). A fixture listed in defaultModeFixtures runs its genuine check in the default run, not strict mode, for the reason given there (3 Nov 2026).", + "fixture": "01-approval-confirmed.bundle.json", + "keyDocument": "xchk-keys/in.xchk.io.2026-11-02.json", + "defaultModeFixtures": { + "anchored-unbatched.bundle.json": "an UNBATCHED anchor (the transaction carries this seal hash itself, no manifest) with its raw transaction captured, so the unbatched OP_RETURN guard runs; every such receipt was anchored between 8 and 10 Aug 2026, before bundles carried the passkey assertion and before the ask-v1 challenge (18 Oct 2026), so strict mode refuses any of them by design (exit 3, nothing failed). This one is an allow record of Sean's agent in seal #505, anchored 10 Aug 2026, fetched from in.xchk.io on 3 Nov 2026 exactly as served (review of #350 by drk-ram, 2 Nov 2026: the unbatched branch had no fixture)." + }, + "evidence": [ + {"path": "recordHash", "fail_text": "record hash recomputed", "delete": "strict-refuses", "tamper": "fails", "why": "the record is identified by its hash"}, + {"path": "record.summary", "fail_text": "record hash recomputed", "tamper": "fails", "why": "the sealed record is hashed; any edit changes the hash"}, + {"path": "record.paramsHash", "fail_text": "record hash recomputed", "tamper": "fails", "why": "the digest of the act is inside the sealed record"}, + {"path": "record.disposition", "tamper": "fails", "why": "approved/denied is inside the sealed record"}, + {"path": "record.attestationId", "tamper": "fails", "why": "the ceremony the record commits to"}, + {"path": "record.attestationHash", "tamper": "fails", "why": "the decision is bound to the record by this hash"}, + {"path": "seal", "delete": "strict-refuses", "why": "no seal: the record's window is not sealed in this bundle"}, + {"path": "seal.sealHash", "fail_text": "seal #", "tamper": "fails", "why": "recomputed from the seal fields"}, + {"path": "seal.merkleRoot", "fail_text": "Merkle path (", "tamper": "fails", "why": "the Merkle path must reach it, and it is in the seal hash"}, + {"path": "seal.count", "fail_text": "seal #", "tamper": "fails", "why": "every seal field is in the seal hash"}, + {"path": "merkle", "delete": "strict-refuses", "why": "no path from the record to the seal"}, + {"path": "merkle.proof", "delete": "strict-refuses", "why": "no path from the record to the seal"}, + {"path": "merkle.proof.0.hash", "fail_text": "Merkle path (", "tamper": "fails", "why": "a step of the path"}, + {"path": "registrySignature.signatures", "delete_with": ["registrySignature.signature"], "delete": "strict-refuses", "why": "no registry signature over the seal"}, + {"path": "registrySignature.signatures.0.signature", "fail_text": "registry signature over the seal hash: ed25519 signature DOES NOT verify", "tamper": "fails", "why": "the registry's signature over the seal hash"}, + {"path": "registrySignature.keys.0.publicKeyRaw", "fail_text": "registry signature over the seal hash: pinned ed25519 key's id recomputes to", "tamper": "fails", "why": "the pinned key the signatures verify with"}, + {"path": "registrySignature.signatures.1", "fail_text": "registry signature over the seal hash: the ml-dsa-65 signature this receipt requires is missing", "delete": "fails", "why": "the sealed profile says hybrid signing: a hybrid signature with its ML-DSA-65 half removed is not the registry's signature (2 Nov 2026)"}, + {"path": "registrySignature.signatures.0", "fail_text": "registry signature over the seal hash: the ed25519 signature this receipt requires is missing", "delete": "fails", "why": "the same with the Ed25519 half removed"}, + {"path": "profile.signature.signatures.1", "fail_text": "registry signature over the profile hash: the ml-dsa-65 signature this receipt requires is missing", "delete": "fails", "why": "the profile's own hybrid signature with a half removed"}, + {"path": "approver.binding.signatures.1", "fail_text": "identity binding: credential ↔ sean@maclawran.ca (level didit): the ml-dsa-65 signature this receipt requires is missing", "delete": "fails", "why": "the identity binding's hybrid signature with a half removed"}, + {"path": "profile.document", "fail_text": "profile document does NOT hash to the seal's profileHash", "delete": "strict-refuses", "tamper_key": "profile.document.name", "tamper": "fails", "why": "the node profile the seal names"}, + {"path": "approver", "delete": "strict-refuses", "why": "no approval evidence"}, + {"path": "approver.assertion", "delete": "strict-refuses", "why": "no passkey assertion"}, + {"path": "approver.assertion.signature", "fail_text": "passkey assertion signature verifies", "tamper": "fails", "why": "the person's signature"}, + {"path": "approver.assertion.authenticatorData", "tamper": "fails", "why": "signed by the person's key"}, + {"path": "approver.assertion.clientDataJSON", "tamper": "fails", "why": "signed by the person's key; carries the challenge"}, + {"path": "approver.publicKey.raw", "fail_text": "binding names the public key the assertion was checked with", "tamper": "fails", "why": "must be the key the registry bound"}, + {"path": "approver.credentialId", "fail_text": "binding names the credential that signed the assertion", "tamper": "fails", "why": "must be the credential the registry bound"}, + {"path": "approver.attestationId", "tamper": "fails", "why": "must be the ceremony the signed ask names"}, + {"path": "approver.binding", "delete": "strict-refuses", "why": "no registry-signed identity binding"}, + {"path": "approver.binding.fields.approverEmail", "tamper": "fails", "why": "the person, signed by the registry"}, + {"path": "approver.binding.fields.recordHash", "fail_text": "binding names this record hash", "tamper": "fails", "why": "the binding names this record"}, + {"path": "approver.binding.fields.credentialId", "fail_text": "binding names the credential that signed the assertion", "tamper": "fails", "why": "the binding names the credential (2 Nov 2026: pinned by its FAIL line; review of #350 by drk-ram found this guard and twelve others unpinned)"}, + {"path": "approver.assertion.authenticatorData", "op": "clear-user-verified", "fail_text": "authenticator reports USER VERIFIED", "tamper": "fails", "why": "the authenticator's user-verified flag; cleared, the ceremony was not user-verified (and the signature no longer covers the data)"}, + {"path": "approver.assertion.clientDataJSON", "op": "retype-as-registration", "fail_text": "assertion is a WebAuthn 'get' ceremony", "tamper": "fails", "why": "a registration ceremony is not an answer"}, + {"path": "registrySignature.root.statement.keys.0.publicKeyRaw", "fail_text": "every key pinned in this bundle is listed in the root's key statement", "tamper": "fails", "why": "the root's statement must list the keys the bundle pins"}, + {"path": "profile.signature", "delete": "fails", "fail_text": "profile carries no registry signature", "why": "an unsigned profile is a failed check, not a pending step"}, + {"path": "approver.binding.signatures.0.signature", "fail_text": "identity binding: credential ↔ sean@maclawran.ca (level didit): ed25519 signature DOES NOT verify", "tamper": "fails", "why": "the registry's signature over the binding"}, + {"path": "approver.challenge", "delete": "strict-refuses", "why": "no ask-bound challenge"}, + {"path": "approver.challenge.fields.attestationId", "fail_text": "the signed ask names this ceremony", "tamper": "fails", "why": "the ask the device signed over"}, + {"path": "approver.challenge.fields.prompt", "fail_text": "the signed ask carries the prompt the person saw", "tamper": "fails", "why": "the prompt the device signed over"}, + {"path": "approver.challenge.fields.actionParamsHash", "fail_text": "the signed ask carries the digest of the action's parameters", "tamper": "fails", "why": "the act the device signed over"}, + {"path": "decision.prompt", "fail_text": "the signed ask carries the prompt the person saw", "tamper": "fails", "why": "must be the prompt the device signed over"}, + {"path": "decision.actionParamsHash", "delete": "fails", "tamper": "fails", "why": "must be the act the device signed over; removed, the signed ask no longer matches it (and on an amended receipt the amendment's citation of the ask is unchecked: pending, never committed)"}, + {"path": "decision.attestationHash", "delete": "fails", "tamper": "fails", "why": "the decision must cite the sealed record's attestation hash; a decision block without the citation was never issued by the registry (every ceremony record since 7 Aug 2026 carries the hash and every issued decision block cites it), so its absence is a failure, not a pending step (20 Oct 2026, review of #350)"}, + {"path": "registrySignature.keys.0.keyId", "keys": true, "fail_text": "the registry's key document does not list pinned key ed25519/", "tamper": "fails", "why": "with --keys every key the bundle pins must be in the registry's published key document by alg, keyId and raw key; a key the registry never published fails by name (2 Nov 2026, review of #350 by drk-ram: a bundle re-signed under his own keys, root statement included, passed strict mode because every key checked was the bundle's own)"}, + {"path": "registrySignature.keys.1.keyId", "keys": true, "fail_text": "the registry's key document does not list pinned key ml-dsa-65/", "tamper": "fails", "why": "the same for the post-quantum key"}, + {"path": "registrySignature.root.publicKeyRaw", "keys": true, "fail_text": "the bundle's root key", "tamper": "fails", "why": "with --keys the bundle's root key must be the document's root: a re-keyer who rotates the root statement too is caught here (without --keys the root signature is only WAIT in the Python verifier)"}, + {"fixture": "anchored.bundle.json", "path": "anchor.manifest.root", "fail_text": "manifest path (", "tamper": "fails", "why": "the manifest path from the seal hash must reach the anchored root"}, + {"fixture": "anchored.bundle.json", "path": "anchor.manifest.path.0.hash", "fail_text": "manifest path (", "tamper": "fails", "why": "a step of the path from the seal hash to the anchored root"}, + {"fixture": "anchored.bundle.json", "path": "anchor.proof.txHex", "op": "corrupt-op-return-root", "fail_text": "the raw anchor transaction's OP_RETURN carries that manifest root", "tamper": "fails", "why": "the root the transaction actually committed must be the one the path reaches (a swap elsewhere in the transaction fails sha256d first, so the op corrupts the committed root itself)"}, + {"fixture": "anchored.bundle.json", "path": "anchor.proof.txid", "fail_text": "sha256d(transaction) = txid", "tamper": "fails", "why": "the txid must be the hash of the raw transaction shipped"}, + {"fixture": "anchored.bundle.json", "path": "anchor.proof.headerHex", "fail_text": "merkleblock header is the block header shipped with the bundle", "tamper": "fails", "why": "the merkleblock must open with the very header the bundle ships"}, + {"fixture": "anchored.bundle.json", "path": "anchor.proof.merkleBlockHex", "op": "corrupt-merkle-branch", "fail_text": "partial Merkle tree reproduces the header's Merkle root", "tamper": "fails", "why": "a branch hash of the partial tree (the op lands past the header, where a middle swap would fail the header check instead)"}, + {"fixture": "anchored.bundle.json", "path": "anchor.otsProof", "op": "shorten-ots-root", "fail_text": "OpenTimestamps proof replays from the seal hash to a 32-byte Merkle root", "tamper": "fails", "why": "the replay must end in a 32-byte Bitcoin Merkle root (a character swap elsewhere replays to a different 32-byte root, which only the chain can contradict, so the op retags the final sha256 as sha1)"}, + {"fixture": "anchored.bundle.json", "path": "approver.identity.subjectId", "fail_text": "binding names the identity provider that vouched for the approver", "tamper": "fails", "why": "the readable identity beside the binding must be the one the registry signed (2 Nov 2026: the anchored receipt was approved by an Entra-vouched approver, the first committed fixture whose binding carries the identity-provider trio, so this guard is pinned here and not on its own fixture)"}, + {"fixture": "anchored.bundle.json", "path": "approver.identity.tenantId", "fail_text": "binding names the identity provider that vouched for the approver", "tamper": "fails", "why": "the same for the tenant that vouched"}, + {"fixture": "anchored-unbatched.bundle.json", "path": "anchor.proof.txHex", "op": "corrupt-op-return-root", "fail_text": "the raw anchor transaction's OP_RETURN carries this seal hash", "tamper": "fails", "why": "an unbatched anchor commits the seal hash itself; the hash the transaction committed must be this seal's (3 Nov 2026, review of #350 by drk-ram: this branch had no fixture)"} + ] +} diff --git a/integrations/xchk-registry/verify_receipt.py b/integrations/xchk-registry/verify_receipt.py new file mode 100755 index 00000000..5c2b1e20 --- /dev/null +++ b/integrations/xchk-registry/verify_receipt.py @@ -0,0 +1,1089 @@ +#!/usr/bin/env python3 +"""Verify an xChk receipt bundle with no network. Standard library only (post-quantum half optional, see below). +Flags: --require-approval (exit 3 unless the approval evidence AND the seal chain — seal, Merkle path, registry +signature over the seal — are present and checked), --json (a structured +report on stdout instead of the human lines; see verify()), --keys xchk-keys.json (the registry's key document, fetched +once from https:///.well-known/xchk-keys.json: every key the bundle pins must be in it, or a check fails). + +MIT License. Copyright (c) 2026 Sean MacGuire. Permission is hereby granted, free of charge, to any person +obtaining a copy of this file, to deal in it without restriction, subject to this notice being included. +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND. + +Usage: python3 verify_receipt.py xchk-receipt-.json [file] [--require-approval] [--json] [--keys xchk-keys.json] +Exit: 0 = every offline check passed; 1 = a check failed; 2 = could not read the bundle; + 3 = --require-approval and the approval evidence or the seal chain is missing. +Changes: verify/CHANGELOG.md (https://in.xchk.io/verify/CHANGELOG.md). A copy saved before 20 Oct 2026 can accept +evidence it should refuse: download it again. + +With a second argument (5 Oct 2026), also checks that FILE is the one this receipt's action wrote: sha256 of its +bytes equals the record's artifactHash, which check 1 has already tied to the record hash. That proves which plate +and run left those bytes on the host, as the host reported it; it does not prove the content is true. + +Checks (each reproduces the rule the registry used to write the bytes; bundle formats /1 and /2): + 1. record hash = sha256(canonical(record)) canonical = sorted keys, no whitespace, JSON scalars, UTF-8 + 2. Merkle path from the record hash to the seal root node = sha256(left_hex + right_hex); odd node promoted unhashed + 3. seal hash = sha256(canonical(seal fields)) + 4. registry sig EVERY signature the seal carries, and every one it must carry (2 Nov 2026), over the seal-hash bytes, each with the pinned key of its alg and + keyId: Ed25519 (pure Python, below) and — since 24 Sep 2026 — ML-DSA-65 (FIPS 204). A hybrid must + pass both. Unknown algs fail. Key ids are recomputed from the pinned keys. + The ML-DSA half needs `pip install dilithium-py` (pure Python, MIT); without it that half is + reported as WAIT, never as a pass, and the exit code is 1 only if something actually failed. + 4b. root the SLH-DSA-SHA2-128s (FIPS 205) key statement, when the bundle carries one: shown, and checked that + every pinned key is listed in it; the SLH-DSA signature itself needs a library this script does not + ship (WAIT) — pin the root's public key once and check it with any FIPS 205 implementation. + 4c. key document with --keys (2 Nov 2026): every key the bundle pins is in the registry's published key document, + active or retired, by alg, keyId and raw public key, and the bundle's root key is the document's root. + Without it checks 4, 4b and 5 prove the bundle is consistent under ITS OWN keys, not that those keys + are the registry's: a bundle re-signed under someone else's keys passes them all. + 5. approver the passkey assertion that answered: ECDSA P-256 over authenticatorData || sha256(clientDataJSON), + user-verified flag set; then the registry's identity binding (same rules as 4) tying that credential + to this person for THIS record hash + 6. anchor the raw Ravencoin transaction carries the seal hash in OP_RETURN — or, for a batched anchor, a + manifest root that anchor.manifest.path reaches from the seal hash; sha256d(tx) is the txid; the + merkleblock's partial Merkle tree reproduces its header's Merkle root and includes the txid. + Left for you to confirm on any explorer: that block hash + Merkle root are on the chain + (Ravencoin's block hash is a KAWPOW hash, which this script does not compute). +""" +import base64 +import hashlib +import io +import json +import sys +from contextlib import redirect_stdout +from typing import Optional + +try: # optional post-quantum half: https://pypi.org/project/dilithium-py (pure Python) + from dilithium_py.ml_dsa import ML_DSA_65 as _ML_DSA_65 +except Exception: # noqa: BLE001 + _ML_DSA_65 = None + +# ----------------------------------------------------------------------------------------------------- canonical + +SEAL_KEYS = ["v", "agentId", "plate", "sealSeq", "windowStart", "windowEnd", "count", "issuedCount", + "seqStart", "seqEnd", "merkleRoot", "deskCondition", "prevSealHash", "rvnBlock", "profileHash"] +# rvnBlock and profileHash (6 Oct 2026) enter the hash only when the seal carries them + + +def canonical(value): + if isinstance(value, bool) or value is None or isinstance(value, (int, str)): + return json.dumps(value, ensure_ascii=False, separators=(",", ":")) + if isinstance(value, float): + raise ValueError(f"non-integer number {value} is outside the sealed value profile") + if isinstance(value, list): + return "[" + ",".join(canonical(v) for v in value) + "]" + if isinstance(value, dict): + return "{" + ",".join(json.dumps(k, ensure_ascii=False, separators=(",", ":")) + ":" + canonical(value[k]) + for k in sorted(value.keys())) + "}" + raise ValueError(f"unsupported value type {type(value).__name__}") + + +def js_slice(s: str, n: int) -> str: + """String(s).slice(0, n) as the registry (JavaScript) computes it: n UTF-16 code units, not n code points.""" + return s.encode("utf-16-le", "surrogatepass")[:2 * n].decode("utf-16-le", "surrogatepass") + + +def amended_binding(rec: dict, am: dict): + """19 Oct 2026 (GHSA-w2fx-3qmx-rx85, finding 3). For an act approved WITH CHANGES the registry seals, as + record.paramsHash, sha256 over the canonical action binding {tool, command, path, summary, amount, artifactHash} + with the AMENDED command (its ceremonyParamsHash). The digest is inside the sealed record, so the Merkle chain + commits to the amended command; decision.amendment is readable text and an unsigned edit of it cannot change what + was sealed. Returns (binding, served): the bundle serves the exact preimage as amendment.boundAs, because the + record's tool and summary are capped, trimmed copies (80 and 400 chars); a bundle served before that carries none, + and the binding is rebuilt from the record, exact only for a summary under the cap.""" + if isinstance(am.get("boundAs"), dict): + return am["boundAs"], True + summ = rec.get("summary") + return ({"tool": rec.get("tool"), "command": js_slice(str(am["command"]), 2000), "path": None, + "summary": (js_slice(str(summ), 2000) if summ else None), "amount": None, "artifactHash": None}, False) + + +def sha256_hex(s: str) -> str: + return hashlib.sha256(s.encode("utf-8")).hexdigest() + + +def sha256d(b: bytes) -> bytes: + return hashlib.sha256(hashlib.sha256(b).digest()).digest() + + +def b64d(s) -> bytes: + if isinstance(s, dict): + s = s.get("signature", "") + s = str(s).replace("-", "+").replace("_", "/") + return base64.b64decode(s + "=" * (-len(s) % 4)) + +# ------------------------------------------------------------------------------------------------------- Ed25519 +# Reference algorithm (Bernstein et al.), affine arithmetic; a few hundred ms per signature, no dependencies. + +_q = 2 ** 255 - 19 +_l = 2 ** 252 + 27742317777372353535851937790883648493 + + +def _inv(x): + return pow(x, _q - 2, _q) + + +_d = (-121665 * _inv(121666)) % _q +_I = pow(2, (_q - 1) // 4, _q) + + +def _xrecover(y): + xx = (y * y - 1) * _inv(_d * y * y + 1) + x = pow(xx, (_q + 3) // 8, _q) + if (x * x - xx) % _q != 0: + x = (x * _I) % _q + if x % 2 != 0: + x = _q - x + return x + + +_By = (4 * _inv(5)) % _q +_B = (_xrecover(_By), _By) + + +def _add(P, Q): + x1, y1 = P + x2, y2 = Q + x3 = (x1 * y2 + x2 * y1) * _inv(1 + _d * x1 * x2 * y1 * y2) + y3 = (y1 * y2 + x1 * x2) * _inv(1 - _d * x1 * x2 * y1 * y2) + return (x3 % _q, y3 % _q) + + +def _mul(P, e): + Q = (0, 1) + while e: + if e & 1: + Q = _add(Q, P) + P = _add(P, P) + e >>= 1 + return Q + + +def _decodepoint(b: bytes): + y = int.from_bytes(b, "little") & ((1 << 255) - 1) + x = _xrecover(y) + if (x & 1) != (b[31] >> 7): + x = _q - x + if (-x * x + y * y - 1 - _d * x * x * y * y) % _q != 0: + raise ValueError("point not on curve") + return (x, y) + + +def ed25519_verify(pub_raw: bytes, msg: bytes, sig: bytes) -> bool: + if len(sig) != 64 or len(pub_raw) != 32: + return False + try: + R = _decodepoint(sig[:32]) + A = _decodepoint(pub_raw) + except ValueError: + return False + S = int.from_bytes(sig[32:], "little") + if S >= _l: + return False + h = int.from_bytes(hashlib.sha512(sig[:32] + pub_raw + msg).digest(), "little") % _l + return _mul(_B, S) == _add(R, _mul(A, h)) + +# ---------------------------------------------------------------------------------------- key ids + registry sigs + +ED_SPKI_PREFIX = bytes.fromhex("302a300506032b6570032100") + + +def key_id_for(alg: str, pub_raw: bytes) -> str: + """Ed25519 ids hash the SPKI DER; post-quantum ids hash the raw public key. 16 hex chars.""" + data = ED_SPKI_PREFIX + pub_raw if alg == "ed25519" else pub_raw + return hashlib.sha256(data).hexdigest()[:16] + + +def ml_dsa_65_verify(pub_raw: bytes, msg: bytes, sig: bytes): + """True/False, or None when dilithium-py is not installed.""" + if _ML_DSA_65 is None: + return None + try: + return bool(_ML_DSA_65.verify(pub_raw, msg, sig)) + except Exception: # noqa: BLE001 + return False + + +def pinned_keys(rs: dict) -> list: + keys = rs.get("keys") + if isinstance(keys, list) and keys: + return keys + if rs.get("publicKeyRaw"): # pre-hybrid bundle: one Ed25519 key + alg = rs.get("alg") if rs.get("alg") and rs.get("alg") != "ed25519+ml-dsa-65" else "ed25519" + return [{"alg": alg, "keyId": rs.get("keyId"), "publicKeyRaw": rs["publicKeyRaw"]}] + return [] + +# ---------------------------------------------------------------------------------- registry key document (--keys) +# 2 Nov 2026 (review of agentrust-io/integrations#350, drk-ram): every key this script checks a signature with is the key +# the bundle carries, so a bundle re-signed under someone else's keys — the key list, the root statement's list and every +# signature rewritten together — passed every check, --require-approval included; "verifies" meant "consistent under its +# own keys". The relying party closes that gap by supplying the registry's key document, fetched once from +# https:///.well-known/xchk-keys.json and kept as a file: every key the bundle pins must be in it, active or +# retired, by alg, keyId and raw public key, and a revoked or unlisted key is a failed check that names the key. This +# script never fetches the document; a document it cannot read is exit 2, never a pass. + + +def load_key_document(path: str) -> dict: + """The registry's key document as a dict with `keys`, `retired`, `revoked` lists (missing ones empty), every entry a + key with `alg` and `keyId`. Raises ValueError when the file is not a key document; read as utf-8-sig so a copy saved + by an editor that writes a byte-order mark still loads (2 Nov 2026, review).""" + with open(path, "r", encoding="utf-8-sig") as f: + doc = json.load(f) + if not isinstance(doc, dict) or not isinstance(doc.get("keys"), list) or not doc["keys"]: + raise ValueError("not an xchk-keys.json document (no `keys` list)") + for k in ("retired", "revoked"): + if not isinstance(doc.get(k), list): + doc[k] = [] + for name in ("keys", "retired", "revoked"): + for x in doc[name]: + if not (isinstance(x, dict) and isinstance(x.get("alg"), str) and isinstance(x.get("keyId"), str)): + raise ValueError(f"`{name}` entry is not a key (alg and keyId are required)") + return doc + + +def _entry_revoked(x: dict, where: str) -> bool: + """A key the registry no longer stands behind, however the document says it: in the `revoked` list, or carrying + `revokedAt`, or with a `status` that is neither active nor retired (2 Nov 2026, review: `status: revoked` left in + place in `keys` read as pinned).""" + return where == "revoked" or bool(x.get("revokedAt")) or x.get("status") not in (None, "active", "retired") + + +def key_document_check(ok, keys: list, root, doc: dict) -> bool: + """Every key the bundle pins against the registry's key document; the bundle's root key against the document's. + Returns True only when every pinned key is listed as active or retired by alg, keyId and raw public key, none is + revoked, and the bundle's root key, when it carries one, is the document's root. FAILs go through ok(). Limits, by + design: a retired key's notBefore/notAfter are not compared with the seal's time; the document's `registry` string + is never compared with the bundle's `wellKnown` (the relying party chose the document; only key material decides); + with no key pinned in the bundle there is nothing to check and the caller reports allPinned as null.""" + registry = doc.get("registry") or "the registry" + listed = [(x, name) for name in ("keys", "retired", "revoked") for x in doc[name]] + all_ok = True + for k in keys: + label = f"{k.get('alg')}/{k.get('keyId')}" + hits = [(x, where) for x, where in listed if x.get("alg") == k.get("alg") and x.get("keyId") == k.get("keyId")] + exact = [(x, where) for x, where in hits if x.get("publicKeyRaw") == k.get("publicKeyRaw")] + # a revoked entry may be published without its public key (the registry serves publicKeyRaw: null on revoked + # keys): it is matched by alg and keyId, so a revocation is never read as "never published" + by_id = [(x, where) for x, where in hits if x.get("publicKeyRaw") is None and _entry_revoked(x, where)] + x, where = (exact or by_id or [(None, None)])[0] + if x is None: + all_ok = False + if hits: + ok(False, f"the registry's key document lists keyId {k.get('keyId')} with a DIFFERENT {k.get('alg')} public key — the bundle's pinned key is not the one the registry published under that id") + else: + ok(False, f"the registry's key document does not list pinned key {label} — a receipt signed with a key the registry never published is not the registry's") + elif _entry_revoked(x, where): + all_ok = False + ok(False, f"the registry's key document lists pinned key {label} as REVOKED" + (f" since {x.get('revokedAt')}" if x.get("revokedAt") else "")) + elif where == "retired" or x.get("status") == "retired": + ok(True, f"the registry's key document ({registry}) lists pinned key {label} as retired") + else: + ok(True, f"the registry's key document ({registry}) lists pinned key {label}") + droot = doc.get("root") + if isinstance(root, dict) and root.get("publicKeyRaw"): + rid = key_id_for(str(root.get("alg", "")), b64d(root["publicKeyRaw"])) + if isinstance(droot, dict) and droot.get("publicKeyRaw"): + is_root = root.get("alg") == droot.get("alg") and root["publicKeyRaw"] == droot["publicKeyRaw"] + all_ok = all_ok and is_root + ok(is_root, f"the bundle's root key {rid} is the registry's root key" if is_root + else f"the bundle's root key {rid} is NOT the registry's root key {droot.get('keyId')} — the key statement vouching for the pinned keys is not the registry's") + else: + # 2 Nov 2026 (review): a document with no usable root used to skip this check and still report every key pinned + all_ok = False + ok(False, f"the bundle carries root key {rid} but the registry's key document publishes no root key to check it against") + return all_ok + + +# 2 Nov 2026 (review of agentrust-io/integrations#350, rajnisht7): the signatures a receipt MUST carry come from signed +# fields only. The `alg` label and the pinned key list are unsigned and an editor of the bundle can rewrite them; the +# sealed profile's `signing` dial is hashed into the seal (profileHash, 6 Oct 2026), and for a seal older than profiles +# the seal's own windowStart is hashed. Both registries issued their first hybrid seal in the same minute. +HYBRID_SINCE = "2026-09-24T14:40:00Z" # last Ed25519-only seal 14:38:47Z, first hybrid 14:43:43Z (in.xchk.io and xchk.me) + + +def required_algs(seal, profile_doc): + """The algorithms every registry signature in this bundle must carry, read from signed fields; None when the bundle + is not sealed, in which case whatever is present is checked and nothing is required. Pure.""" + dials = profile_doc.get("dials") if isinstance(profile_doc, dict) else None + dial = dials.get("signing") if isinstance(dials, dict) else None + if isinstance(dial, str) and dial not in ("", "none"): + return set(dial.split("+")) + ws = seal.get("windowStart") if isinstance(seal, dict) else None + if isinstance(ws, str) and ws.endswith("Z"): # ISO-8601 UTC as the registry writes it: lexical order is time order + return {"ed25519", "ml-dsa-65"} if ws >= HYBRID_SINCE else {"ed25519"} + return None + + +def binding_required(fields, fallback): + """The identity binding is signed when the bundle is fetched, under the registry's mode THEN, so the seal's date says + nothing about it: a seal from before the switch carries a hybrid binding. Nothing signed in the binding named the + mode (review of #350, 2 Nov 2026); when the registry signs it in as `signing`, it decides, and until then the seal's + set is the signed proxy, which covers the binding only for seals from after the switch. Pure.""" + dial = fields.get("signing") if isinstance(fields, dict) else None + return set(dial.split("+")) if isinstance(dial, str) and dial not in ("", "none") else fallback + + +def registry_verify(ok, sig_obj: dict, msg: bytes, keys: list, what: str, required=None, unverified=None) -> int: + """Verify every signature the object lists, and require every one `required` names (2 Nov 2026). Returns the number + of WAITs (unverifiable halves); FAILs go through ok(). A required half that cannot be checked here is appended to + `unverified` (strict mode refuses on it): a label is not a signature, and without dilithium-py the ML-DSA slot + would otherwise pass on its label alone (review of #350, 2 Nov 2026).""" + sigs = sig_obj.get("signatures") if isinstance(sig_obj.get("signatures"), list) and sig_obj.get("signatures") else None + if not sigs and sig_obj.get("signature"): + alg = sig_obj.get("alg") if sig_obj.get("alg") and sig_obj.get("alg") != "ed25519+ml-dsa-65" else "ed25519" + sigs = [{"alg": alg, "keyId": sig_obj.get("keyId"), "signature": sig_obj["signature"]}] + if not sigs: + ok(False, f"{what}: no signature to check") + return 0 + waits = 0 + for sig in sigs: + alg = sig.get("alg") + key = next((k for k in keys if k.get("alg") == alg and (not sig.get("keyId") or not k.get("keyId") or k.get("keyId") == sig.get("keyId"))), None) + if not key: + ok(False, f"{what}: no pinned key for alg {alg!r} keyId {sig.get('keyId')!r}") + continue + pub = b64d(key["publicKeyRaw"]) + kid = key_id_for(alg, pub) + if key.get("keyId") and kid != key.get("keyId"): + ok(False, f"{what}: pinned {alg} key's id recomputes to {kid}, not {key.get('keyId')}") + continue + if alg == "ed25519": + r = ed25519_verify(pub, msg, b64d(sig["signature"])) + elif alg == "ml-dsa-65": + r = ml_dsa_65_verify(pub, msg, b64d(sig["signature"])) + else: + r = False + if r is None: + waits += 1 + print(f" WAIT {what}: {alg} signature present (keyId {kid}) — install dilithium-py to verify the post-quantum half") + if unverified is not None and required and alg in required: + unverified.append(f"{what}: its {alg} half, which this receipt requires, cannot be checked here (install dilithium-py)") + else: + ok(r, f"{what}: {alg} signature {'verifies' if r else 'DOES NOT verify'} with pinned key {kid}" + (" (FIPS 204, post-quantum)" if alg == "ml-dsa-65" else "")) + present = {s.get("alg") for s in sigs} + for alg in sorted(required or ()): + if alg not in present: + ok(False, f"{what}: the {alg} signature this receipt requires is missing — a hybrid signature with a half removed is not the registry's signature") + if len(sigs) > 1 and waits == 0: + print(f" .. {what}: HYBRID — {' + '.join(s.get('alg', '?') for s in sigs)}, every half checked") + return waits + +# --------------------------------------------------------------------------------------------------- ECDSA P-256 + +_p = 0xffffffff00000001000000000000000000000000ffffffffffffffffffffffff +_n = 0xffffffff00000000ffffffffffffffffbce6faada7179e84f3b9cac2fc632551 +_Gx = 0x6b17d1f2e12c4247f8bce6e563a440f277037d812deb33a0f4a13945d898c296 +_Gy = 0x4fe342e2fe1a7f9b8ee7eb4a7c0f9e162bce33576b315ececbb6406837bf51f5 +_b = 0x5ac635d8aa3a93e7b3ebbd55769886bc651d06b0cc53b0f63bce3c3e27d2604b + + +def _p256_add(P, Q): + if P is None: + return Q + if Q is None: + return P + x1, y1 = P + x2, y2 = Q + if x1 == x2 and (y1 + y2) % _p == 0: + return None + if P == Q: + lam = (3 * x1 * x1 - 3) * pow(2 * y1, _p - 2, _p) % _p + else: + lam = (y2 - y1) * pow(x2 - x1, _p - 2, _p) % _p + x3 = (lam * lam - x1 - x2) % _p + return (x3, (lam * (x1 - x3) - y1) % _p) + + +def _p256_mul(P, e): + Q = None + while e: + if e & 1: + Q = _p256_add(Q, P) + P = _p256_add(P, P) + e >>= 1 + return Q + + +def _der_sig(sig: bytes): + if len(sig) < 8 or sig[0] != 0x30 or sig[2] != 0x02: + raise ValueError("not a DER ECDSA signature") + rl = sig[3] + r = int.from_bytes(sig[4:4 + rl], "big") + if sig[4 + rl] != 0x02: + raise ValueError("not a DER ECDSA signature") + sl = sig[5 + rl] + s = int.from_bytes(sig[6 + rl:6 + rl + sl], "big") + return r, s + + +def p256_verify(pub_uncompressed: bytes, msg: bytes, der_sig: bytes) -> bool: + if len(pub_uncompressed) != 65 or pub_uncompressed[0] != 4: + return False + Qx = int.from_bytes(pub_uncompressed[1:33], "big") + Qy = int.from_bytes(pub_uncompressed[33:65], "big") + if (Qy * Qy - (Qx ** 3 - 3 * Qx + _b)) % _p != 0: + return False + try: + r, s = _der_sig(der_sig) + except ValueError: + return False + if not (1 <= r < _n and 1 <= s < _n): + return False + e = int.from_bytes(hashlib.sha256(msg).digest(), "big") + w = pow(s, _n - 2, _n) + u1 = (e * w) % _n + u2 = (r * w) % _n + X = _p256_add(_p256_mul((_Gx, _Gy), u1), _p256_mul((Qx, Qy), u2)) + return X is not None and X[0] % _n == r + +# ------------------------------------------------------------------------------------------------- anchor proof + + +def _varint(b: bytes, i: int): + v = b[i] + if v < 0xfd: + return v, i + 1 + if v == 0xfd: + return int.from_bytes(b[i + 1:i + 3], "little"), i + 3 + if v == 0xfe: + return int.from_bytes(b[i + 1:i + 5], "little"), i + 5 + return int.from_bytes(b[i + 1:i + 9], "little"), i + 9 + + +def tx_op_return_payloads(tx: bytes): + """Every OP_RETURN payload in a legacy (non-witness) transaction.""" + i = 4 + n_in, i = _varint(tx, i) + for _ in range(n_in): + i += 36 + sl, i = _varint(tx, i) + i += sl + 4 + n_out, i = _varint(tx, i) + out = [] + for _ in range(n_out): + i += 8 + sl, i = _varint(tx, i) + script = tx[i:i + sl] + i += sl + if script and script[0] == 0x6a: + j = 1 + if j < len(script): + op = script[j] + if op <= 0x4b: + out.append(script[j + 1:j + 1 + op]) + elif op == 0x4c: + out.append(script[j + 2:j + 2 + script[j + 1]]) + elif op == 0x4d: + ln = int.from_bytes(script[j + 1:j + 3], "little") + out.append(script[j + 3:j + 3 + ln]) + return out + + +def merkleblock_check(mb: bytes, header_len: int, txid_hex: str): + """Parse a Bitcoin-style merkleblock; return (merkle_root_hex, txid_included, computed_root_matches_header).""" + header = mb[:header_len] + root_in_header = header[36:68][::-1].hex() + i = header_len + ntx = int.from_bytes(mb[i:i + 4], "little") + i += 4 + nh, i = _varint(mb, i) + hashes = [mb[i + 32 * k:i + 32 * (k + 1)] for k in range(nh)] + i += 32 * nh + nf, i = _varint(mb, i) + flags = mb[i:i + nf] + bits = [] + for byte in flags: + for k in range(8): + bits.append((byte >> k) & 1) + height = 0 + while (1 << height) < ntx: + height += 1 + state = {"h": 0, "b": 0, "matched": []} + + def width(h): + return (ntx + (1 << h) - 1) >> h + + def walk(h, pos): + flag = bits[state["b"]] + state["b"] += 1 + if h == 0 or flag == 0: + hsh = hashes[state["h"]] + state["h"] += 1 + if h == 0 and flag: + state["matched"].append(hsh) + return hsh + left = walk(h - 1, pos * 2) + right = walk(h - 1, pos * 2 + 1) if pos * 2 + 1 < width(h - 1) else left + return sha256d(left + right) + + computed = walk(height, 0)[::-1].hex() + included = any(m[::-1].hex() == txid_hex for m in state["matched"]) + return root_in_header, included, computed == root_in_header + +# --------------------------------------------------------------------------------------------------------- main + + +def file_sha256(path: str) -> str: + digest = hashlib.sha256() + with open(path, "rb") as f: + for chunk in iter(lambda: f.read(1024 * 1024), b""): + digest.update(chunk) + return digest.hexdigest() + + +# ------------------------------------------------------------------------------------------ OpenTimestamps (6 Oct 2026) +# A second, independent anchor: the seal hash was submitted to an OpenTimestamps calendar, which commits it to Bitcoin. +# Wire format of python-opentimestamps (core/op.py, notary.py, timestamp.py), dependency-free here: +# timestamp := (0xff op timestamp)* (0x00 attestation | op timestamp); op := tag [varbytes arg] +# 0xf0 append · 0xf1 prepend · 0xf2 reverse · 0xf3 hexlify · 0x02 sha1 · 0x03 ripemd160 · 0x08 sha256 +# attestation := 8-byte tag, varbytes payload; 83dfe30d2ef90c8e pending (varbytes uri) · 0588960d73d71901 bitcoin (varuint height) +# The message at a Bitcoin attestation is the block's Merkle root in header byte order: the one fact left to the reader. +OTS_OPS = {0xF0: "append", 0xF1: "prepend", 0xF2: "reverse", 0xF3: "hexlify", 0x02: "sha1", 0x03: "ripemd160", 0x08: "sha256"} +OTS_PENDING = bytes.fromhex("83dfe30d2ef90c8e") +OTS_BITCOIN = bytes.fromhex("0588960d73d71901") + + +class _OtsReader: + def __init__(self, b: bytes): + self.b, self.i = b, 0 + + def byte(self) -> int: + if self.i >= len(self.b): + raise ValueError("ots: truncated") + v = self.b[self.i] + self.i += 1 + return v + + def take(self, n: int) -> bytes: + if self.i + n > len(self.b): + raise ValueError("ots: truncated") + v = self.b[self.i:self.i + n] + self.i += n + return v + + def varuint(self) -> int: + v, shift = 0, 0 + while True: + c = self.byte() + v |= (c & 0x7F) << shift + if not c & 0x80: + return v + shift += 7 + if shift > 56: + raise ValueError("ots: varuint too long") + + def varbytes(self, mx: int = 4096) -> bytes: + n = self.varuint() + if n > mx: + raise ValueError("ots: varbytes too long") + return self.take(n) + + +def _ots_apply(op: str, arg, msg: bytes) -> bytes: + if op == "append": + return msg + arg + if op == "prepend": + return arg + msg + if op == "reverse": + return msg[::-1] + if op == "hexlify": + return msg.hex().encode("ascii") + if op == "sha1": + return hashlib.sha1(msg).digest() + if op == "ripemd160": + return hashlib.new("ripemd160", msg).digest() + if op == "sha256": + return hashlib.sha256(msg).digest() + raise ValueError(f"ots: unsupported op {op}") + + +def ots_attestations(proof: bytes, digest: bytes) -> list: + """Replay a calendar proof from the digest: [(kind, value, msg)] with kind 'pending' (value = uri) or 'bitcoin' (value = height).""" + r = _OtsReader(proof) + out = [] + + def timestamp(msg: bytes, depth: int): + if depth > 256: + raise ValueError("ots: too deep") + tag = r.byte() + while tag == 0xFF: + node(msg, r.byte(), depth) + tag = r.byte() + node(msg, tag, depth) + + def node(msg: bytes, tag: int, depth: int): + if tag == 0x00: + att = r.take(8) + payload = r.varbytes(8192) + if att == OTS_PENDING: + out.append(("pending", _OtsReader(payload).varbytes(1000).decode("utf-8", "replace"), msg)) + elif att == OTS_BITCOIN: + out.append(("bitcoin", _OtsReader(payload).varuint(), msg)) + else: + out.append(("unknown", att.hex(), msg)) + return + op = OTS_OPS.get(tag) + if not op: + raise ValueError(f"ots: unknown op tag 0x{tag:02x}") + arg = r.varbytes() if op in ("append", "prepend") else None + timestamp(_ots_apply(op, arg, msg), depth + 1) + + timestamp(digest, 0) + if r.i != len(proof): + raise ValueError("ots: trailing bytes") + return out + + +def main(path: str, artifact_path: Optional[str] = None, require_approval: bool = False, keys_path: Optional[str] = None) -> int: + """Human-readable run; the exit code is the verdict (0 verifies, 1 a check failed, 2 unreadable, 3 strict mode and + the approval evidence is missing). verify() returns the same code with a structured report (--json).""" + return verify(path, artifact_path, require_approval, keys_path)[0] + + +def verify(path: str, artifact_path: Optional[str] = None, require_approval: bool = False, keys_path: Optional[str] = None): + """(exit code, report) for one bundle file. A bundle whose fields have the wrong TYPES (a string where an object + belongs, a float in a sealed body, a lone surrogate, bad base64) ends in a failed check and exit 1, never a + traceback and never a pass (19 Oct 2026: a type-mutation sweep over every field found 35 crashing lines; the + field-removal sweep had covered only absence). `pending` is null when the run stopped on such a bundle.""" + report = {"result": None, "exit": None, "failed": 0, "pending": 0, "approvalEvidenceMissing": [], "sealChainMissing": [], + "boundIdentity": None, "amendment": None, "withheld": [], "keyDocument": None, "checks": []} + try: + return _verify(path, artifact_path, require_approval, report, keys_path) + except (KeyError, TypeError, AttributeError, ValueError, IndexError, OverflowError) as exc: + text = f"the bundle is malformed ({type(exc).__name__}: {str(exc)[:160]}); it cannot be what the registry issued" + print(" FAIL " + text) + report["checks"].append({"status": "FAIL", "text": text}) + failed = sum(1 for c in report["checks"] if c["status"] == "FAIL") + print(f"\nRESULT: does NOT verify ({failed} check(s) failed)") + report.update(exit=1, result="fails", failed=failed, pending=None, boundIdentity=None, amendment=None, withheld=["boundIdentity", "amendment"]) + return 1, report + + +def _verify(path, artifact_path, require_approval, report, keys_path=None): + """Returns (exit code, report). The report is what a caller may act on (19 Oct 2026, GHSA-w2fx-3qmx-rx85, finding + 2): `checks` lists every check that RAN with OK or FAIL; `pending` counts steps that could not run here; a step + that did not run is in neither. `approvalEvidenceMissing` names what an approval verdict still needs; + `sealChainMissing` names what is missing of the seal, the Merkle path to it and the registry's signature over it + (20 Oct 2026: approval evidence present does not make the receipt sealed; strict mode requires both). + require_approval: exit 3 unless the APPROVAL evidence is present and checked — an approver block, a passkey + assertion with a key, a registry-signed binding, and an ask-v1 challenge. Without it, a bundle stripped of its + approver still exits 0 (nothing FAILED, the steps were only WAIT), and a caller that reads 0 as "approval + verified" is wrong. Absence of failure is not verification. `boundIdentity` is the email, proofing level and method + from the registry-signed binding, never the readable labels beside it (null without a binding). Both are null, and `withheld` names them, whenever the exit is not 0 (2 Nov 2026). `amendment` is null when the decision carries none, + else {command, committed}: committed only when the sealed record's paramsHash recomputes over that command AND + the amendment cites the ask the person signed (finding 3). `keyDocument` (2 Nov 2026) is null when no --keys document + was supplied — the bundle's keys were then checked only against themselves — else {registry, servedAt, allPinned}: + allPinned is true only when every key the bundle pins is in the document and its root key is the document's.""" + checks = report["checks"] + + def done(code, result): + report.update(exit=code, result=result, failed=failed, pending=pending) + if code != 0: + # 2 Nov 2026 (review of #350, rajnisht7): with the seal signature corrupted, boundIdentity and amendment + # (committed: true) were still filled in, and a caller that read them before the exit code took them as + # verified. A report that does not verify names nobody and commits to nothing. + report.update(boundIdentity=None, amendment=None, withheld=["boundIdentity", "amendment"]) + return code, report + + failed = 0 + pending = 0 + # 20 Oct 2026 (review of #350, noah-ing): the approval evidence being present does not make the receipt sealed. The + # seal, the Merkle path to it and the registry's signature over it are a second, separate requirement of strict mode, + # reported apart so "approved, and sealed" is never read off "approved" alone. + seal_chain_missing = report["sealChainMissing"] + approval_evidence_missing = report["approvalEvidenceMissing"] # what an approval verdict still needs (strict mode refuses on any) + try: + with open(path, "r", encoding="utf-8") as f: + b = json.load(f) + except Exception as exc: # noqa: BLE001 + print(f"could not read bundle: {exc}") + return done(2, "unreadable") + if b.get("format") not in ("xchk-receipt-bundle/1", "xchk-receipt-bundle/2"): + print(f"not an xChk receipt bundle (format={b.get('format')!r})") + return done(2, "unreadable") + key_doc = None + if keys_path: + try: + key_doc = load_key_document(keys_path) + except Exception as exc: # noqa: BLE001 — a key document that cannot be read is no key document: refuse, never skip + print(f"could not read key document {keys_path}: {exc}") + return done(2, "unreadable") + report["keyDocument"] = {"registry": key_doc.get("registry"), "servedAt": key_doc.get("servedAt"), "allPinned": None} + + def ok(cond, text): + nonlocal failed + print((" OK " if cond else " FAIL ") + text) + checks.append({"status": "OK" if cond else "FAIL", "text": text}) + if not cond: + failed += 1 + + rec = b.get("record") or {} + print(f"xChk receipt {b.get('recordHash')} ({b.get('format')})") + print(f" {b.get('issuer', {}).get('headline', '')}") + + # 1. record hash + mine = sha256_hex(canonical(rec)) + ok(mine == b.get("recordHash"), f"record hash recomputed: {mine}") + print(f" .. {'chained to previous record ' + rec['prevHash'] if rec.get('prevHash') else 'first record on its chain'}") + + # 1b. the file, when one was given: its bytes against the digest sealed in the record + if artifact_path: + want = rec.get("artifactHash") + if not want: + ok(False, "this record carries no artifactHash: it is not the outcome record of a file write") + else: + try: + got = file_sha256(artifact_path) + ok(got == want, f"file {artifact_path} is the one this action wrote: sha256 {got}" if got == want + else f"file {artifact_path} is NOT the one this action wrote: sha256 {got}, record says {want}") + except OSError as exc: + ok(False, f"could not read {artifact_path}: {exc}") + if rec.get("outcomeOf"): + print(f" .. written under decision {rec['outcomeOf']} by {rec.get('plate')}, run {rec.get('runRef') or rec.get('runSeq')}") + + # 2. merkle + seal = b.get("seal") + required = required_algs(seal, None) # 2 Nov 2026: refined below once the sealed profile has hashed + merkle = b.get("merkle") + if seal and merkle and isinstance(merkle.get("proof"), list): + # 19 Oct 2026: a bundle with no record hash, or a malformed proof step, is a failed check, never a crash — every + # input ends in a verdict and an exit code (a field-removal sweep found the KeyError on `recordHash`). + cur = b.get("recordHash") + if not (isinstance(cur, str) and len(cur) == 64): + ok(False, "bundle names a 64-hex record hash for the Merkle path to start from") + else: + try: + for step in merkle["proof"]: + cur = sha256_hex(step["hash"] + cur) if step.get("side") == "L" else sha256_hex(cur + step["hash"]) + ok(cur == seal.get("merkleRoot"), f"Merkle path ({len(merkle['proof'])} steps) reaches seal root {seal.get('merkleRoot')}") + except (KeyError, TypeError, AttributeError) as exc: + ok(False, f"Merkle proof is malformed ({exc!r}); the path to the seal cannot be walked") + else: + pending += 1 + seal_chain_missing.append("the seal over the record's window" if not seal else "the Merkle path from the record to the seal") + print(" WAIT not sealed when the bundle was made — download it again later" if not seal + else " WAIT no Merkle path from the record to the seal in this bundle — the record's place under the seal cannot be checked") + + # 3. seal hash + if seal: + fields = {k: seal[k] for k in SEAL_KEYS if k in seal and not (k in ("rvnBlock", "profileHash") and seal[k] is None)} + sh = sha256_hex(canonical(fields)) + ok(sh == seal.get("sealHash"), f"seal #{seal.get('sealSeq')} hash recomputed: {sh}") + + # 3b. the node profile the seal names (6 Oct 2026): which rules produced this record, checkable here, offline + ph = seal.get("profileHash") + if ph: + prof = b.get("profile") or {} + doc = prof.get("document") + if not isinstance(doc, dict): + ok(False, f"seal names profile {ph[:12]}… but the bundle does not carry it ({prof.get('note') or 'missing'})") + else: + dh = sha256_hex(canonical(doc)) + ok(dh == ph, f"profile document hashes to the seal's profileHash: {dh}" if dh == ph + else f"profile document does NOT hash to the seal's profileHash: {dh}, seal says {ph}") + if dh == ph: + required = required_algs(seal, doc) + psig = prof.get("signature") or {} + pkeys = pinned_keys(b.get("registrySignature") or {}) + if (psig.get("signature") or psig.get("signatures")) and pkeys: + pending += registry_verify(ok, psig, ph.encode("utf-8"), pkeys, "registry signature over the profile hash", required, seal_chain_missing) + else: + ok(False, "profile carries no registry signature") + print(f" .. sealed under profile \"{doc.get('name')}\" of {doc.get('registry')} ({ph[:12]}…): " + + ", ".join(f"{k}={json.dumps(v, separators=(',', ':'))}" for k, v in sorted((doc.get("dials") or {}).items()))) + else: + print(" .. sealed before profiles (no profileHash in the seal)") + + # 4. registry signature(s) — Ed25519, or hybrid Ed25519 + ML-DSA-65 + rs = b.get("registrySignature") or {} + keys = pinned_keys(rs) + # 4c. the registry's key document, when the relying party supplied one (2 Nov 2026): the keys the signatures above and + # below are checked with must be keys the registry published, or every signature check proves only self-consistency + if key_doc is not None and keys: + report["keyDocument"]["allPinned"] = key_document_check(ok, keys, rs.get("root"), key_doc) + if seal and (rs.get("signature") or rs.get("signatures")) and keys: + # 19 Oct 2026: a seal with no hash is a failed check, never a crash (field-removal sweep) + if not isinstance(seal.get("sealHash"), str): + ok(False, "seal names its hash, for the registry signature to be checked over") + else: + pending += registry_verify(ok, rs, seal["sealHash"].encode("utf-8"), keys, "registry signature over the seal hash", required, seal_chain_missing) + pinned = ", ".join(f"{k.get('alg')}/{k.get('keyId')}" for k in keys) # 18 Oct 2026: no nested same-quote f-string (3.12-only syntax) + if key_doc is not None: + print(f" .. keys pinned in the bundle: {pinned}; checked against the key document of {key_doc.get('registry')} served {key_doc.get('servedAt')}") + else: + print(f" .. keys pinned in the bundle: {pinned}; checked against THEMSELVES only — pass --keys with the document from {rs.get('wellKnown')} to check they are the registry's") + elif seal: + pending += 1 + seal_chain_missing.append("the registry's signature over the seal") + print(f" WAIT no registry signature in this bundle ({rs.get('note') or 'unsigned'})") + + # 4b. root key statement (SLH-DSA-SHA2-128s) + root = rs.get("root") + if isinstance(root, dict) and root.get("statement") and root.get("signature"): + stated = root["statement"].get("keys") or [] + listed = all(any(x.get("alg") == k.get("alg") and x.get("keyId") == k.get("keyId") and x.get("publicKeyRaw") == k.get("publicKeyRaw") for x in stated) for k in keys) + ok(listed, "every key pinned in this bundle is listed in the root's key statement") + rid = key_id_for(root.get("alg", ""), b64d(root.get("publicKeyRaw", ""))) + pending += 1 + print(f" WAIT root {root.get('alg')} signature over canonical(statement) — pin root keyId {rid} and verify with any FIPS 205 implementation (not shipped in this script)") + + # 5. approver + ap = b.get("approver") + if not ap: + approval_evidence_missing.append("approver block") + if ap: + a = ap.get("assertion") or {} + pk = ap.get("publicKey") or {} + if a.get("signature") and a.get("authenticatorData") and a.get("clientDataJSON") and pk.get("format") == "ec-p256-uncompressed": + auth = b64d(a["authenticatorData"]) + cdj = b64d(a["clientDataJSON"]) + try: + cd = json.loads(cdj.decode("utf-8")) + except Exception: # noqa: BLE001 + cd = {} + uv = len(auth) > 32 and bool(auth[32] & 0x04) + sig_ok = p256_verify(b64d(pk["raw"]), auth + hashlib.sha256(cdj).digest(), b64d(a["signature"])) + ok(sig_ok, f"passkey assertion signature verifies with the enrolled credential {str(ap.get('credentialId'))[:16]}…") + ok(cd.get("type") == "webauthn.get", f"assertion is a WebAuthn 'get' ceremony (type={cd.get('type')!r})") + ok(uv, "authenticator reports USER VERIFIED (biometric/PIN) for that ceremony") + else: + pending += 1 + approval_evidence_missing.append("passkey assertion with its ES256 key") + print(" WAIT approver assertion or an ES256 public key not present in this bundle — the ceremony cannot be re-run here") + bd = ap.get("binding") or {} + if (bd.get("signature") or bd.get("signatures")) and keys and bd.get("fields"): + f = bd["fields"] + pending += registry_verify(ok, bd, canonical(f).encode("utf-8"), keys, f"identity binding: credential ↔ {f.get('approverEmail')} (level {f.get('authLevel')})", binding_required(f, required), approval_evidence_missing) + ok(f.get("recordHash") == b.get("recordHash"), "binding names this record hash") + ok(f.get("credentialId") == ap.get("credentialId"), "binding names the credential that signed the assertion") + # 17 Oct 2026: the key the assertion was checked with must be the key the registry bound to that credential, + # or an attacker who swaps both the key and the assertion for their own passes check 5 with every registry + # signature intact (TRACE fixture 06-assertion-from-another-credential). + ok(f.get("publicKey") == pk.get("raw"), "binding names the public key the assertion was checked with") + # 19 Oct 2026 (GHSA-w2fx-3qmx-rx85, finding 3): the person the registry bound to this record (who answered, or for an + # expired ask who was asked) and their proofing are reported ONLY from the registry-signed binding; the readable approver.email/authLevel/authMethod beside it are not evidence. + report["boundIdentity"] = {"email": f.get("approverEmail"), "authLevel": f.get("authLevel"), + "authMethod": f.get("authMethod"), "source": "approver.binding.fields (registry-signed)"} + outer = (ap.get("email"), ap.get("authLevel"), ap.get("authMethod")) + if outer != (f.get("approverEmail"), f.get("authLevel"), f.get("authMethod")): + print(" .. the bundle's readable approver labels differ from the signed binding; the binding is what the registry signed and what is reported") + # 18 Oct 2026: the identity provider that vouched for the approver (Entra tenant + subject) rides INSIDE the + # signed binding; the readable copy at approver.identity must agree with what the registry signed. + if f.get("identityProvider"): + ident = ap.get("identity") or {} + ok(ident.get("provider") == f.get("identityProvider") and ident.get("tenantId") == f.get("tenantId") + and ident.get("subjectId") == f.get("subjectId"), + f"binding names the identity provider that vouched for the approver: {f.get('identityProvider')} tenant {f.get('tenantId')} subject {str(f.get('subjectId'))[:8]}…") + else: + pending += 1 + approval_evidence_missing.append("registry-signed identity binding") + print(" WAIT no signed identity binding (registry signing not configured when the bundle was made)") + # 18 Oct 2026 (AB-1): what the device signed over. With rule ask-v1 the challenge is sha256 over the ask as + # issued (attestation id, the prompt the person saw, the digest of the action's parameters), so the assertion + # itself names the act it answered; recompute it from the bundle's own decision block, never from `expected`. + # Without it the challenge was a nonce and only the registry's binding pairs the assertion with the record: + # an assertion by the same credential over another ask passes every other check. + ch = ap.get("challenge") or {} + if ch.get("rule") == "ask-v1" and isinstance(ch.get("fields"), dict) and a.get("clientDataJSON"): + f = ch["fields"] + dec = b.get("decision") if isinstance(b.get("decision"), dict) else {} # 19 Oct 2026: a non-object decision is a failed check, never a crash + try: + cd = json.loads(b64d(a["clientDataJSON"]).decode("utf-8")) + except Exception: # noqa: BLE001 + cd = {} + recomputed = base64.urlsafe_b64encode(hashlib.sha256(canonical(f).encode("utf-8")).digest()).decode("ascii").rstrip("=") + ok(cd.get("challenge") == recomputed, "the challenge the device signed is sha256 over the ask (rule ask-v1)") + ok(f.get("attestationId") == ap.get("attestationId"), "the signed ask names this ceremony") + # 19 Oct 2026 (GHSA-w2fx-3qmx-rx85, finding 1): the ask must name the ceremony the REGISTRY committed to — + # the sealed record's attestationId and the signed binding's — not merely the outer approver field, which an + # unsigned edit of the bundle sets to whatever the transplanted assertion needs. Without this, a genuine + # answer to ANOTHER ask by the same credential rides beside this record's binding and reads as its approval. + rec_att = (b.get("record") or {}).get("attestationId") + ok(rec_att is not None and f.get("attestationId") == rec_att, "the signed ask names the ceremony the sealed record commits to") + bound_att = (bd.get("fields") or {}).get("attestationId") if isinstance(bd.get("fields"), dict) else None + if bound_att is not None: + ok(f.get("attestationId") == bound_att, "the signed ask names the ceremony the registry bound to this credential") + ok(f.get("prompt") == dec.get("prompt"), "the signed ask carries the prompt the person saw") + ok(f.get("actionParamsHash") == dec.get("actionParamsHash"), "the signed ask carries the digest of the action's parameters") + else: + pending += 1 + approval_evidence_missing.append("ask-v1 challenge (the device signed over this ask)") + print(" WAIT challenge not derived from the ask (ceremony before 18 Oct 2026): the binding alone pairs this assertion with the record") + + # 5b. the decision block cites this record (20 Oct 2026; the browser verifier has checked it since 19 Sep, this one + # never did — found by the verdict contract): decision.attestationHash must be the sealed record's attestationHash, + # or a decision from another ceremony could ride beside this record. + # The citation is required, not optional (later on 20 Oct 2026, review of #350: with the citation REMOVED the + # check did not run and the verdict stayed confirmed). Every ceremony record the registry has written since the + # ledger began (7 Aug 2026) carries the attestation hash — it is sealed before the record is appended — and every + # decision block the issuer emits cites it. A decision block with no citation is not one the registry issued. + dec_b = b.get("decision") if isinstance(b.get("decision"), dict) else {} + if dec_b: + cited = dec_b.get("attestationHash") + if not cited: + ok(False, "the decision block carries NO attestation-hash citation: every decision block the registry issues cites the sealed record") + else: + ok(cited == rec.get("attestationHash"), + "the decision block cites this record's attestation hash" if cited == rec.get("attestationHash") + else f"the decision block does NOT cite this record's attestation hash ({str(cited)[:12]}…, record says {str(rec.get('attestationHash'))[:12]}…)") + + # 5c. approved WITH CHANGES (19 Oct 2026, GHSA-w2fx-3qmx-rx85, finding 3). decision.amendment is readable, unsigned + # text. What makes an amendment the approved act is the SEALED record: the registry hashes the amended command into + # record.paramsHash, so the Merkle chain commits to it, and amendment.originalParamsHash names the ask the person's + # passkey signed over. Without both, an amendment is a claim and is refused: an amendment typed into a bundle after + # issue fails here, and so does an amended command edited after issue. The person's signature covers the ask AS + # PROPOSED; the amendment's scope rests on the registry's seal, not on a signature by the person, and a relying party + # that needs the person's own signature over the amended text does not have it in this bundle. + dec = b.get("decision") if isinstance(b.get("decision"), dict) else {} + am = dec.get("amendment") + if isinstance(am, dict) and am.get("command") and rec.get("paramsHash") is None: + # 19 Oct 2026: a ceremony record sealed before 19 Sep 2026 carries no action digest (DM-3 added it), so the seal + # commits to no command at all. The amendment is then unchecked readable text: pending, never confirmed, and + # not a failure of a receipt that is otherwise intact (four genuine September receipts failed on this). + pending += 1 + print(" WAIT approved WITH CHANGES, but this record seals no action digest (ceremonies before 19 Sep 2026): the seal does not" + " commit to the amended command, so the amendment is readable text only and is not checkable here") + report["amendment"] = {"command": str(am["command"]), "checkable": False, "committed": False} + elif isinstance(am, dict) and am.get("command"): + binding, served = amended_binding(rec, am) + try: + sealed = rec.get("paramsHash") == sha256_hex(canonical(binding)) + except (ValueError, UnicodeError): + sealed = False # a binding outside the sealed value profile cannot be what was sealed + ok(sealed, "the sealed record commits to the amended action binding (record.paramsHash = sha256 over " + + ("amendment.boundAs)" if served else "it, rebuilt from the record: a bundle served before 19 Oct 2026; if this fails, download it again)")) + try: + same_command = isinstance(binding.get("command"), str) and binding["command"] == js_slice(str(am["command"]), 2000) + except UnicodeError: + same_command = False + ok(same_command, "the bound command is the amended command") + # Later on 20 Oct 2026 (review of #350, same class as 5b): without the ask's action digest the citation leg + # defaulted to "cites", so a bundle with decision.actionParamsHash removed reported the amendment COMMITTED on + # the strength of a check that never ran (the challenge, when present, catches the removal first; a bundle + # without one did not). Every amended receipt in the corpus carries the digest. Without it the citation is + # pending, the amendment is never committed, and strict mode refuses. + if dec.get("actionParamsHash") is not None: + cites = am.get("originalParamsHash") == dec.get("actionParamsHash") + ok(cites, "the amendment cites the ask the person answered (originalParamsHash = the signed ask's actionParamsHash)") + else: + cites = None + pending += 1 + approval_evidence_missing.append("the ask's action digest (decision.actionParamsHash), which the amendment must cite") + print(" WAIT the ask carries no action digest: the amendment's citation of it cannot be checked, so the amendment is not committed") + print(" .. approved WITH CHANGES: the passkey signed the ask as proposed; the registry sealed the amended command as the act." + " The amendment's scope rests on the registry's seal, not on a signature by the person.") + report["amendment"] = {"command": str(am["command"]), "checkable": True, "citesAsk": cites, + "committed": bool(sealed and same_command and cites)} + + # 6. anchor + anchor = b.get("anchor") or {} + proof = anchor.get("proof") + if proof and proof.get("txHex") and seal: + tx = bytes.fromhex(proof["txHex"]) + payloads = tx_op_return_payloads(tx) + committed = [p[9:41].hex() for p in payloads if p[:3] == b"xCk"] + manifest = anchor.get("manifest") + if manifest and isinstance(manifest.get("path"), list): + # 22 Oct 2026: a BATCHED anchor — the transaction carries a manifest root over many seals; this seal's path + # walks its hash to that root with the same rule as the record→seal path. A malformed path is a failed + # check, never a crash. + cur = seal.get("sealHash") or "" + try: + for step in manifest["path"]: + cur = sha256_hex(step["hash"] + cur) if step.get("side") == "L" else sha256_hex(cur + step["hash"]) + ok(cur == manifest.get("root"), f"manifest path ({len(manifest['path'])} steps) reaches root {manifest.get('root')} (this seal is 1 of {manifest.get('count')})") + except (KeyError, TypeError, AttributeError) as exc: + cur = None + ok(False, f"manifest path is malformed ({exc!r}); the path to the anchored root cannot be walked") + ok(cur is not None and cur in committed, "the raw anchor transaction's OP_RETURN carries that manifest root") + else: + ok((seal.get("sealHash") or "") in committed, "the raw anchor transaction's OP_RETURN carries this seal hash") + ok(sha256d(tx)[::-1].hex() == proof.get("txid"), f"sha256d(transaction) = txid {proof.get('txid')}") + hdr = bytes.fromhex(proof["headerHex"]) if proof.get("headerHex") else b"" + mb = bytes.fromhex(proof["merkleBlockHex"]) if proof.get("merkleBlockHex") else b"" + if hdr and mb: + root_hdr, included, root_ok = merkleblock_check(mb, len(hdr), proof["txid"]) + ok(mb[:len(hdr)] == hdr, "merkleblock header is the block header shipped with the bundle") + ok(root_ok and included, f"partial Merkle tree reproduces the header's Merkle root {root_hdr} and includes the txid") + print(f" WAIT one outside fact left: Ravencoin block {proof.get('blockHash')} (height {proof.get('blockHeight')}) has Merkle root {root_hdr}. Any explorer confirms it; the block hash itself is a KAWPOW hash this script does not compute.") + else: + pending += 1 + print(" WAIT anchor proof lacks header/merkleblock") + elif anchor.get("rvnTxId"): + pending += 1 + print(f" WAIT anchor: Ravencoin tx {anchor['rvnTxId']} — raw bytes not yet captured in this bundle (download again after a confirmation), or confirm its OP_RETURN on an explorer:") + print(f" {anchor.get('explorer') or 'https://ravencoin.network/tx/' + anchor['rvnTxId']}") + elif seal: + pending += 1 + print(" WAIT seal not yet anchored when the bundle was made") + + # 3c. legal holds (7 Oct 2026): existence and scope only; the reason and the names are not on a public receipt + for h in (b.get("legalHolds") or []): + print(f" .. under a legal hold on the {h.get('scope')} since {h.get('placedAt')}" + + (f", until {h.get('until')}" if h.get("until") else ", until released") + f" (hold {str(h.get('id'))[:8]}…)") + + # 6b. OpenTimestamps (6 Oct 2026): the second anchor, replayed from the seal hash to its attestations + if seal and anchor.get("otsProof"): + try: + atts = ots_attestations(base64.b64decode(anchor["otsProof"]), bytes.fromhex(seal.get("sealHash") or "")) + btc = [a for a in atts if a[0] == "bitcoin"] + pend = [a for a in atts if a[0] == "pending"] + if btc: + for _, height, root in btc: + ok(len(root) == 32, f"OpenTimestamps proof replays from the seal hash to a 32-byte Merkle root at Bitcoin block {height}") + pending += 1 + print(f" WAIT one outside fact left: Bitcoin block {height} has Merkle root {root[::-1].hex()}. Any Bitcoin explorer confirms it.") + elif pend: + pending += 1 + print(f" WAIT OpenTimestamps: the seal hash is committed at {', '.join(sorted({a[1] for a in pend}))}, not yet in a Bitcoin block when the bundle was made — download again later") + else: + ok(False, "OpenTimestamps proof carries no attestation this script knows") + except Exception as exc: # noqa: BLE001 — a proof that does not replay is a failed check, not a crash + ok(False, f"OpenTimestamps proof does not replay: {exc}") + + if failed: + print(f"\nRESULT: does NOT verify ({failed} check(s) failed)") + return done(1, "fails") + if require_approval and (approval_evidence_missing or seal_chain_missing): + if approval_evidence_missing: # the wording of 19 Oct 2026, unchanged: callers match on it + print("\nRESULT: does NOT verify AS AN APPROVAL — evidence missing: " + "; ".join(approval_evidence_missing) + + ("; seal chain incomplete: " + "; ".join(seal_chain_missing) if seal_chain_missing else "") + + " (nothing failed; the steps were never run)") + else: + print("\nRESULT: does NOT verify AS A SEALED APPROVAL — seal chain incomplete: " + "; ".join(seal_chain_missing) + + " (the approval evidence checks out; nothing failed; the seal steps were never run)") + return done(3, "approval-evidence-missing" if approval_evidence_missing else "seal-chain-incomplete") + print("\nRESULT: verifies offline" + (f" — {pending} step(s) pending (see WAIT)" if pending else "") + "; only the block's presence on the chain is left to you") + return done(0, "verifies") + + +if __name__ == "__main__": + # 2 Nov 2026 (review of agentrust-io/integrations#350, drk-ram, on Windows): the human lines carry U+2194 and an em + # dash and the JSON report is written with ensure_ascii=False, so under a cp1252 console the verifier died with a + # UnicodeEncodeError and exit 1 — indistinguishable from "a check failed". A verifier's output encoding is its own + # business, not the console's: stdout is UTF-8 from here on, whatever the locale, and `python -I` cannot undo it. + if hasattr(sys.stdout, "reconfigure"): + sys.stdout.reconfigure(encoding="utf-8") + flags = {"--require-approval", "--json"} + args = sys.argv[1:] + keys_path = None + if "--keys" in args: # 2 Nov 2026: --keys , the registry's key document saved as a file + i = args.index("--keys") + if i + 1 >= len(args) or args[i + 1].startswith("--"): + print(__doc__) + sys.exit(2) + keys_path = args[i + 1] + del args[i:i + 2] + argv = [x for x in args if x not in flags] + if len(argv) not in (1, 2) or any(x.startswith("--") for x in argv): + print(__doc__) + sys.exit(2) + if "--json" in sys.argv: + # 19 Oct 2026: one JSON object on stdout for a caller that acts on the result — the checks that ran, what is + # pending, what an approval verdict still needs, the amendment's standing — and the human lines as `transcript`. + buf = io.StringIO() + with redirect_stdout(buf): + code, report = verify(*argv, require_approval=("--require-approval" in sys.argv), keys_path=keys_path) + report["transcript"] = buf.getvalue().rstrip("\n").split("\n") + print(json.dumps(report, ensure_ascii=False, indent=2)) + sys.exit(code) + sys.exit(main(*argv, require_approval=("--require-approval" in sys.argv), keys_path=keys_path))