D1 interactive demo -- demo.pay.vauban.tech

Vauban Pay developer demo

Three interactive panels: (1) JCS canonicalisation per RFC 8785 with live SHA-256 recomputation; (2) bounded-spend authorization fixture vectors you can reproduce client-side; (3) the first live receipt emission on Starknet Sepolia.

All cryptographic operations in this demo run in your browser via the Web Crypto API and a TypeScript JCS implementation (RFC 8785). No server call is made for the canonicalisation or hashing steps.

Section 1 / 3

Canonical JCS reproducer

Paste any JSON object below. The right panel shows the JCS-canonicalised bytes (RFC 8785 ; alphabetical key order, no whitespace, recursive sort) and the SHA-256 of those bytes.

This is the exact canonicalisation step used to produce expected_delegation_grant_hash and expected_settlement_receipt_hash in every Vauban Pay fixture. Five independent implementations (Rust, Python, Node.js, TypeScript, Go) produce the same bytes from the same JSON input.

Input JSON (paste here)
JCS output

RFC 8785 reference: rfc-editor.org/rfc/rfc8785. Implementation: TypeScript port of the JCS algorithm (alphabetical sort, deterministic number serialisation).

AP2 Cross-Protocol

AP2 open_mandate_hash ; conformance validation

serde_jcs@0.2.0 (Rust) ; Vauban Pay implementation ; 3rd independent impl (AP2/issues/265, 2026-05-23)

The AP2 open_mandate_hash is defined as SHA-256(JCS_RFC8785(unsigned_mandate_body)). The same JCS canonicalisation rule that underpins x402 STARK receipts applies here ; different protocol, same derivation.

7 conformance vectors from AP2 issue #265 were verified byte-for-byte by the Vauban Pay Rust runner (runner-ap2-omh.rs) using serde_jcs@0.2.0. This makes Vauban Pay the 3rd independent implementation to verify these vectors.

7/7 vectors 4/4 pair invariants 3rd independent impl serde_jcs@0.2.0 RFC 8785

Conformance vectors (AP2 issue #265, v0)

Vector ID JCS Hash
ap2-omh-v0-baseline-001 OK OK
ap2-omh-v0-object-key-order-002 OK OK
ap2-omh-v0-array-order-003 OK OK
ap2-omh-v0-optional-fields-004 OK OK
ap2-omh-v0-unicode-nfc-006a OK OK
ap2-omh-v0-unicode-nfd-006b OK OK
ap2-omh-v0-mixed-types-005 OK OK

Pair invariants (4 / 4 verified)

Invariant Rule Result
001 == 002 Object key order ; JCS sorts, hash must match PASS
001 != 003 Array order significant ; JCS preserves, hash must differ PASS
001 != 004 Optional fields not collapsed ; hash must differ PASS
006a != 006b No Unicode normalisation ; NFC ≠ NFD, hash must differ PASS

CROSS-PROTOCOL BRIDGE

One canonicalisation layer, two protocols.

AP2 ; agentic mandates

open_mandate_hash = SHA-256(JCS(unsigned_mandate_body))

x402 ; STARK receipts (IETF I-D)

open_receipt_hash = SHA-256(JCS(receipt_core))

Both derivations share the identical SHA-256(JCS(•)) construction. A conforming implementation of either protocol can reuse the same JCS canonicalisation library and hash function ; no protocol-specific variant is required. The Axis 0 substrate (RFC 8785) is the shared foundation.

Runner provenance. Verification executed by crates/zkpay-x402/examples/runner-ap2-omh.rs (committed in vauban-zkpay). The runner ingests the AP2 v0 vector file, serialises each unsigned_mandate_body through serde_jcs::to_string, computes SHA-256 over the UTF-8 bytes, and asserts byte-for-byte equality against the pinned expected digest. 7/7 assertions pass, 4/4 pair invariant checks pass. Library: serde_jcs@0.2.0 (Rust). Hash: sha2@0.10.
AP2 issue #265 ; open_mandate_hash IETF I-D ; draft-vauban-x402-stark-receipts Verified 2026-05-23 ; serde_jcs@0.2.0 ; runner-ap2-omh.rs
Axis 0 / 4

Axis 0 ; Canonicalisation substrate

AlgoVoi (chopmob-cloud) ; 4 vector sets / 53 vectors / 37 pair invariants / 5-impl byte-for-byte

The substrate layer defines the single JCS canonicalisation rule (RFC 8785) that every coalition axis follows before hashing. Any JSON object passed into any axis is first serialised to deterministic bytes: alphabetical Unicode code-point key order at every nesting level, no whitespace, Unicode NFC normalisation on string values, float rejection (non-finite numbers are protocol errors), and deterministic number representation per RFC 8785 §3.2.2.

The four AlgoVoi-authored vector sets (53 vectors total, 37 pair invariants) serve as the normative conformance anchors. A conforming implementation must reproduce each pinned SHA-256 digest byte-for-byte. Five independent implementations across five languages and four non-overlapping author sets all pass 53/53 vectors and 37/37 pair invariants.

Regulatory retention obligations (MiCA Art. 80, AMLR Art. 56, DORA Art. 14) require auditors to pin a specific vector revision for multi-year reference. The in-tree mirror at fixtures/canonicalisation-substrate/v0/ provides that repo-tagged anchor in place of mutable gist URLs.

53 vectors | 37 pair invariants | 5-impl matrix | RFC 8785

Vector sets (in-tree mirror)

File Vectors Pair invariants Layer
ap2-omh-v0.json 7 4 AP2 OMH v0
ctef_vectors.json 7 included CTEF-APS ; trust-evidence container
privacy_class_v0.1.json 13 12 privacy_class v0 ; attestation
per_chain_envelope_v0.json 19 9 per_chain_envelope v0 ; chain-native-value

Cross-implementation conformance matrix (re-verified 2026-05-21)

Library Lang Maintainer Result
rfc8785@0.1.4 Python Trail of Bits 53/53 + 37/37
canonicalize@3.0.0 JS Erdtman + Rundgren 53/53 + 37/37
gowebpki/jcs v1.0.1 Go GoWebPKI 53/53 + 37/37
cyberphone/json-canonicalization Java Rundgren (RFC 8785 reference) 53/53 + 37/37
serde_jcs 0.2.0 Rust Vauban Pay (5th-impl runner) 53/53 + 37/37
Cross-axis binding role. This substrate is the foundation on which Axes 1 through 4 sit. The same RFC 8785 JCS rules apply across every axis ; there is no axis-specific canonicalisation variant. A conforming implementation hashes the JCS-canonical bytes of any structured object (payment intent, settlement receipt, delegation grant, work-receipt manifest) using the same algorithm regardless of which axis is asserting the hash. One mutation to the substrate rules breaks all four axes simultaneously, which is the intended property.
GitHub PR #2412 AlgoVoi owned-surface Coalition v3 discipline thread #2326

Vector provenance: each JSON file is a byte-for-byte mirror of the canonical AlgoVoi gist at the timestamp recorded in its published_at field. Provenance verification: gh api gists/<id> | diff - against the in-tree file. RFC 8785 reference: rfc-editor.org/rfc/rfc8785.

Axis 1 / Coalition

STARK receipts ; Vauban Pay

LIVE ; Sepolia 2026-05-23

Vauban Pay (pay.vauban.tech) ; Rust, serde_jcs 0.2.0, Stwo Circle STARK M31

The STARK receipts layer introduces BoundReceipt<T>: a deterministic CBOR (RFC 8949) envelope that wraps any settlement receipt type and binds it to a action_ref work-proof computed via SHA-256(JCS(RFC 8785)) over the canonicalized action preimage. The envelope is compact by construction: the fixture vector encodes 197 bytes of canonical CBOR from a four-field settlement receipt plus a 32-byte action_ref.

The IETF Internet-Draft draft-vauban-x402-stark-receipts (submitted 2026-05-21) formalizes the encoding rules: receipt_core is JCS-canonicalized first, SHA-256 is computed over those bytes to produce the receipt_core_hash anchored on Starknet, and the BoundReceipt envelope carries both the raw receipt and the action_ref in a single CBOR-deterministic byte string that any compliant verifier can recompute offline.

Cross-axis binding is structural: the same payment_hash and action_ref appear verbatim in Axes 2 (FeedOracle hybrid-PQC), 3 (andysalvo work-receipt), and 4 (nobulex composite). One mutation to either field invalidates all axes simultaneously ; the Axis 1 CBOR envelope is the on-chain settlement anchor for the entire coalition fixture set.

~197 CBOR bytes CBOR (RFC 8949) SHA-256(JCS(RFC 8785)) Stwo Circle STARK M31 Starknet Sepolia
LIVE TX PaymentReceiptEmitted ; Starknet Sepolia 2026-05-23
tx_hash
0x6bcbb2440007419557110871c5e46962ec33d5b0fe0afe98b4a5a0e29c4044f
Verified on Voyager (Sepolia) ; block explorer canonical
receipt_core_hash
0x438f7ea2b67036873bd7248481ffa9adca548a654c6330520d37526f9bb014
felt252 (masked) anchored on-chain via PaymentDemoEmitter
payment_amount
50000 centimes USDC (= 500.00 USDC)
currency
0x55534443 ASCII decode: "USDC"
timestamp_ms
1779548263147 2026-05-23 (Unix ms)
tx_emitter
0x5f4802a628e6a5342f9487253d1447c70583cea92358d2ce5781d67baf08d9
contract
Block explorer

Verify on-chain

Fetch the live receipt from Starknet Sepolia via self-hosted RPC. Enter any tx hash or use the demo transaction pre-filled below.

fixtures/x402-interop/ vector-stark-vauban-pay-v1.json
receipt_format
stark-vauban-pay-v1 PASS
payment_hash
2ed186ebc66947eaac6a05a88c7bc096ee07ac11a2c44bb5580bd72b3670f580
SHA-256(utf8(x402-payment-base-0xUSDC-50000-base-mainnet-demo)). Shared with FeedOracle fixture verbatim ; documents a hypothetical x402 USDC-Base settlement for fixture purposes.
action_ref
10d8a38c01d8672176aa6e5209a368fde3e1831640d69e15283142b35880c2c1
SHA-256(JCS(RFC 8785)) over {"action_type":"sanctions_screen","agent_id":"did:web:agent-7.example.com","scope":"counterparty-due-diligence","timestamp_ms":1747728000000}. Shared with Axes 2 and 3.
inner_receipt
payment_id 550e8400-e29b-41d4-a716-446655440000 • block 9786058 (Starknet Sepolia) • settled_at 1700000005 (2023-11-14T22:13:25Z)
bound_receipt_cbor_b64
omdyZWNlaXB0pGpwYXltZW50X2lkeCQ1NTBlODQwMC1lMjliLTQxZDQtYTcxNi00NDY2NTU0NDAwMDBndHhfaGFzaHcweHN0YXJrX2ZpeHR1cmVfdHhfaGFzaGxibG9ja19udW1iZXIaAJVSampzZXR0bGVkX2F0GmVT8QVqYWN0aW9uX3JlZpggEBjYGKMYjAEY2BhnGCEYdhiqGG4YUgkYoxhoGP0Y4xjhGIMWGEAY1hieFRgoGDEYQhizGFgYgBjCGME
197 CBOR bytes ; canonical CBOR (RFC 8949 deterministic encoding). Computed by crates/zkpay-x402/examples/compute-fixture.rs using ciborium 0.2 + vauban-zkpay-x402 0.1.0.
Verify
cargo test --package vauban-zkpay-x402 bound_receipt_interop_fixture 2>&1 | tail -3

Tamper evidence model

The CBOR envelope is deterministic: a conforming encoder (ciborium 0.2, RFC 8949 deterministic) always produces the exact same byte sequence from the same input. Flipping any byte in bound_receipt_cbor_hex either causes CBOR decode failure or yields a different action_ref ; the on-chain receipt_core_hash no longer matches. There is no structurally valid mutation that preserves the digest.

Two conformance failure cases are documented inline in the fixture JSON: case 1 mutates the action_ref_preimage_jcs (breaks the work-proof binding across all axes) ; case 2 mutates the CBOR payload directly (breaks the STARK on-chain anchor). Both are independently detectable without contacting any external service.

Cross-axis binding ; coalition fixture set

This vector shares payment_hash and action_ref verbatim with the FeedOracle hybrid-PQC receipt (Axis 2) and the andysalvo action-ref-verify vector 0008 (Axis 3). The FeedOracle coalition gist documents the shared anchor at gist.github.com/feedoracle/704ab891170e2b43050f6f0ae00e6923. Axis 1 is the settlement proof layer ; Axes 2 and 3 add post-quantum signature integrity and work-receipt accountability over the same underlying payment event.

IETF I-D draft-vauban-x402-stark-receipts (submitted 2026-05-21) is the normative specification governing the BoundReceipt<T> encoding. The Vauban Rust crate is the 5th independent implementation in the coalition cross-implementation matrix, complementing the Python, JS, Go, and Java runners that pass the Axis 0 substrate vectors (53/53 + 37/37).

IETF Internet-Draft

draft-vauban-x402-stark-receipts
Submitted 2026-05-21 ; IETF Datatracker

Coalition thread

x402-foundation/x402#2326
Multi-axis coalition fixture discipline (v3)

Fixture file

fixtures/x402-interop/vector-stark-vauban-pay-v1.json
In-tree ; verifiable offline

FeedOracle coalition gist

gist.github.com/feedoracle/704ab…
Shared payment_hash + action_ref anchor

Apache 2.0. Authored by Vauban Pay as the 5th-impl contributor to the x402-foundation coalition fixture set. The CBOR encoding uses ciborium 0.2 (Rust). The Stwo Circle STARK M31 prover is a stub reference in this fixture ; the production proof path is wired in Sprint 3+4 of the vauban-zkpay roadmap.

Zero-Trust Verification

Zero-Trust Receipt Verifier

Starknet Sepolia

Verify a Vauban Pay receipt without trusting Vauban. Every cryptographic step runs in your browser ; the on-chain check calls Starknet directly. No server involved.

How to use
  1. 1
    Edit the receipt in panel 01 Build — watch the hash recompute on every keystroke. Then hit Toggle Tamper Test to see how changing a single digit breaks the fingerprint.
  2. 2
    Click "Verify on-chain" in panel 02 Verify — your browser queries the Starknet node directly and checks that the hash in the receipt matches what was recorded on-chain. No login, no API key.
  3. 3
    See the proof chain in panel 03 Understand — a six-step diagram from raw JSON to on-chain event.

Want to verify your own receipt? Replace the JSON in panel 01 and the tx hash in panel 02 with your own values.

01 Build Canonicalize + hash
JCS canonical ...
SHA-256 ...
felt252 mask ...
Byte dump (first 32) ...
02 Verify On-chain via Starknet RPC
03 Understand Cryptographic flow

Zero-trust means no party needs to trust Vauban's servers. The verification is deterministic and reproducible by anyone with access to the JSON and the public Starknet Sepolia node.

JSON receipt
The plain-text payment receipt with type, amount, hash, and network fields.
JCS
JCS canonicalize (RFC 8785)
Keys sorted alphabetically, no whitespace. Deterministic bytes regardless of source language.
SHA
SHA-256 (Web Crypto API)
Runs in your browser. Produces a 32-byte digest of the canonical bytes.
F252
felt252 mask
BigInt AND with (2^251 - 1) to fit the Starknet felt252 field. This is the value anchored on-chain.
STK
Starknet emit_receipt
The felt252 is stored on-chain via the PaymentDemoEmitter contract event.
On-chain event
Anyone can read keys[1] from the emitted event and compare with their locally computed felt252.
Contract 0x044dd87a94a801cf775d4c5e4b6703102d4e97e1cd1d0a8879341219ae4f19ff
View on Voyager
Section 2 / 3

Bounded-spend authorization fixture vectors

Three vectors from fixtures/bounded-spend-authorization-sample/v0/vectors/ shipped at commit 1c35845. Each vector carries a DelegationGrant and a SettlementReceipt with pinned JCS hashes. Click "Reproduce" to recompute the hash client-side and compare.

The DelegationGrant authorises the agent to spend up to 1 USDC per transaction and 100 USDC per 24-hour rolling period, with a single listed merchant, in USDC on Starknet Sepolia.

Axis 2 / Coalition

Hybrid post-quantum receipt

FeedOracle (@feedoracle) ; ES256K + ML-DSA-65 dual signature, FIPS 204, NIST IR 8547 transition-compliant

Both classical (ES256K, secp256k1 ECDSA) and post-quantum (ML-DSA-65, FIPS 204 lattice-based) signatures are required for receipt acceptance ; an attacker must defeat both simultaneously to forge a valid receipt. Both signatures cover identical JCS-canonical bytes derived via SHA-256(JCS(RFC 8785)(receipt_core)), ensuring deterministic, implementation-independent verification.

The receipt core is canonicalized once and shared between both signature schemes. This avoids ambiguity: one canonical byte string, two independent cryptographic commitments. Offline verification against a public JWKS requires no facilitator callback.

Cross-axis binding is achieved via the same payment_hash and action_ref fields present in Axes 1, 3, and 4. A single mutation to either value invalidates all axes simultaneously, making multi-axis tamper evidence structurally guaranteed.

~3.3 KB receipt ES256K + ML-DSA-65 FIPS 204 NIST IR 8547 SHA-256(JCS(RFC 8785))
fixtures/hybrid-pqc/v0/ Conformance vectors ; PR #2411
0001
baseline-hybrid-pqc PASS
Nominal receipt core. Both ES256K and ML-DSA-65 signatures cover SHA-256(JCS(core)). Canonical baseline for cross-implementation comparison.
0002
field-name-load-bearing FAIL
Field name substitution: observed_at (RFC 3339 string) vs observed_at_ms (epoch integer). Different canonical byte string produces a divergent digest ; both signatures reject.
0003
hybrid-signature-tamper-evidence FAIL
One byte flipped in the signed receipt core. Both ES256K and ML-DSA-65 signatures fail independently, demonstrating that tamper evidence holds against both classical and lattice-based verification paths.
0008
interop-shared-payment-hash PASS
Cross-layer binding. Carries the same payment_hash (2ed186eb...0f580) and action_ref (10d8a38c...0c2c1) as action-ref-verify v0 vector 0008 (Axis 3) and the zkpay STARK set (Axis 1). One payment, three axes, shared binding.

Regulatory alignment + cross-axis binding

ML-DSA-65 (FIPS 204, August 2024) is listed in NIST IR 8547 as an approved post-quantum algorithm for the NIST PQC transition. The EU PQC Roadmap (ANSSI, BSI Joint Position 2024) explicitly names ML-DSA as a priority migration target for digital signatures ; this axis demonstrates a concrete conformance fixture against that roadmap. The hybrid construction satisfies both the NIST transition requirement (ML-DSA primary) and classical backward compatibility (ES256K) during the migration window.

Cross-axis binding is structural: payment_hash and action_ref are shared across Axes 1, 2, 3, and 4 of the coalition fixture set. Axis 2 vector 0008 is the interoperability proof point for this binding.

Source PR

x402-foundation/x402#2411

FeedOracle JWKS (live)

tooloracle.io/.well-known/jwks.json
kid: feedoracle-mldsa65-1, alg: ML-DSA-65, FIPS 204

Reproduce

pip install cryptography pqcrypto

Apache 2.0. Contributed by FeedOracle to the x402-foundation coalition fixture set. Fixture structure follows the fixtures/<suite>/<version>/ convention established in PR #2398 (Axis 3, andysalvo). No changes to protocol code or repo CI dependencies.

Axis 3 ; Work-receipt binding

Work-receipt binding

andysalvo (@andysalvo) ;  action_ref = SHA-256(JCS(preimage)), no ZK overhead, HTTP-client verifiable

The work-receipt axis is the simplest of the four coalition axes: a pure 32-byte SHA-256 digest of the JCS-canonicalised (RFC 8785) preimage object, producing the action_ref that binds a payment to whatever the agent produced after the payment was settled.

Deterministic by construction: the same preimage fields in any key order canonicalise to the same bytes, and the same bytes hash to the same 32-byte digest. Any HTTP client with a JSON parser and a SHA-256 primitive can reproduce and verify the digest independently, with no prover, no trusted setup, and no external dependency.

This axis defines the canonical action_ref value that the other axes bind to: Axis 1 (STARK) includes it in the proof statement; Axis 2 (Hybrid-PQC) signs over the pair (payment_hash, action_ref). One mutation to action_ref breaks the binding across all axes simultaneously.

PR #2398 ; x402-foundation/x402 action-ref-verify conformance vectors
32-byte hash RFC 8785 JCS no ZK overhead pure HTTP-client verifiable

Canonical action_ref (all axes bind to this value)

action_ref: 10d8a38c01d8672176aa6e5209a368fde3e1831640d69e15283142b35880c2c1

SHA-256 of JCS(preimage) per RFC 8785. Three independent implementations (Node.js, Python, Rust) reproduced identical digests from the same preimage fields with no shared code (PR #2398 §Source).

Role in the coalition

Axis 3 is the anchor of the cross-axis binding. The action_ref it produces is consumed as a first-class input by Axis 1 (included in the STARK proof statement) and Axis 2 (covered by the hybrid-PQC signature). The minimal-overhead path makes it the right starting point for non-ZK consumers: any buyer can verify the binding without a prover, complementary to Axis 1 which proves predicates over the receipt and Axis 2 which proves signature integrity.

PR #2398 ships 9 cross-language conformance vectors covering the canonical happy path, float/integer precision traps, trailing-whitespace sensitivity, extra-field tolerance, RFC 8785 negative-zero handling, unicode key stress, cross-layer binding, and load-bearing field-name disambiguation (timestamp_ms vs timestamp).

6 PASS vectors 3 FAIL vectors data-only ; zero code changes
View PR #2398 on GitHub feat(fixtures): action-ref-verify conformance vectors ; andysalvo

Vectors derived from action-ref-verify v0.3.0 (Apache-2.0, andysalvo). No code changes, no added dependencies, no CI modifications ; conformance data only. Reproducible by any SHA-256 + RFC 8785 implementation.

Coalition axis 4 / 4

Axis 4 ; Composite trust-query

nobulex (@arian-gogani) ; tri-party composite envelope, multi-emitter evidence rows. Preimage algorithm: AlgoVoi (@chopmob-cloud).

The composite trust-query is the multi-stakeholder evidence envelope: one query against (payment_hash, action_ref) returns N evidence rows, each from a distinct emitter, each independently signed and framework-declared.

This is the composition-layer axis. Axes 0, 1, 2, 3 contribute rows. Axis 4 defines the envelope that assembles and binds them under a single query surface.

tri-party scaffold verascore-evidence-schema-v0.1 multi-emitter framework-declared rows tetra-party anticipated

COMPOSITE ANCHOR

Both fields are present in every emitter row. They are the join key that makes the composite meaningful. A supervisor re-verifying at year 5 confirms all rows bind to the same anchor.

payment_hash

2ed186ebc66947eaac6a05a88c7bc096ee07ac11a2c44bb5580bd72b3670f580

action_ref (Axis 3)

10d8a38c01d8672176aa6e5209a368fde3e1831640d69e15283142b35880c2c1
Current emitters
Multi-emitter evidence rows
Each row is independently verifiable: emitter identity, evidence type, regulatory framework, and signed receipt are declared per-row. A composite policy evaluator can apply strict (any FAIL aborts) or weighted (per-row override) strategies at the hook layer.
3 confirmed emitters independently signed per-row framework
Full tri-party response (vectors 0001/0002 ; identical composite digest despite row rotation)

Emitter 1 ; AlgoVoi

Compliance screening

Frameworks: UK MLR 2017, EU FSF, OFSI, OFAC. ~20ms p50, ~45ms p99. Session-level amortisation. evidenceType: behavioral

source_id: algovoi.compliance-screening

Emitter 2 ; Vauban Pay

STARK proof-of-payment-conditions

Settlement chain: Starknet. Stwo Circle STARK M31 prover. evidenceType: cryptographic

source_id: vauban.stark-proof-of-payment-conditions

Emitter 3 ; nobulex (@arian-gogani)

Bilateral receipt

Schema: verascore-evidence-schema-v0.1. Tri-party envelope author ; composite-layer co-design. evidenceType: observational

source_id: nobulex.verascore-evidence-schema-v0.1

Emitter 4 ; risk-check (anticipated)

AlexanderLawson17 / AlgoVoi production reference. AML/sanctions screen, session-scoped amortisation. Slots in as 4th emitter row; no envelope schema change required. Spec: x402 PR #2422.

Partial bi-party response (STARK row absent ; (payment_hash, action_ref) still anchors cleanly)

A composite query may return fewer rows than the declared emitter set. The (payment_hash, action_ref) anchor is sufficient to bind the partial composite. A policy evaluator marks the absent row as PENDING or UNKNOWN rather than failing the query.

Emitter 1 ; AlgoVoi ; present

compliance-screening row ; ALLOW ; jurisdiction_flags: ["UK", "EU"]

Emitter 2 ; Vauban Pay ; absent (STARK prover timeout)

row status: PENDING ; policy decision at evaluator layer

Emitter 3 ; nobulex ; present

verascore-evidence-schema-v0.1 row ; observational evidence confirmed

Composite hash derivation
Preimage algorithm
Source-id lexicographic sort defines the canonical row order. Per-row sig fields are excluded from the preimage before hashing. Attribution: AlgoVoi (@chopmob-cloud), x402 issue #2322.

Step 1 ; lexicographic sort of source_ids

[
  "algovoi.compliance-screening",
  "nobulex.verascore-evidence-schema-v0.1",
  "vauban.stark-proof-of-payment-conditions"
]

Step 2 ; composite hash

SHA-256(JCS([row_algovoi, row_nobulex, row_vauban]))

Per-row sig fields are excluded from the preimage before hashing. A verifier strips sig from each row, builds the sorted JCS array, then recomputes the composite digest.

Structural rule ; for evidenceType: behavioral, anchor_chains ⊆ contributing_chains is REQUIRED. A behavioral emitter cannot anchor receipts on a chain it has not observed.

For evidenceType: regulatory or cryptographic, the anchor chain is an independent infrastructure choice (per x402 PR #2322).

x402 issue #2322 ; bazaar Compliance category x402 issue #2421 ; risk-check extension Panel updated 2026-05-22 per AlgoVoi composite preimage spec.
Phase 2 -- Agentic commerce

Vauban Pay MCP server

mcp.vauban.tech/pay/mcp exposes 4 MCP tools over StreamableHTTP. Any MCP-compatible agent (Claude Code, CC/Preste SDK) can call them to run a complete x402 payment cycle: DelegationGrant authorization, bounded-spend payment emission, and cryptographic audit verification on Starknet Sepolia.

JWT Bearer auth via auth.vauban.tech (OAuth 2.1 PKCE). The server declares its resource metadata at /.well-known/oauth-protected-resource. Supported scopes: pay:read, pay:write, pay:admin.

Tool registry

jcs_hash
JCS (RFC 8785) canonicalize a JSON object and compute its SHA-256 hash. Returns base64 canonical bytes + hex digest.
read-only
request_delegation_grant
Create a DelegationGrant authorization object with caps, scope, and expiry. Returns the grant hash (JCS+SHA-256, canon_version x402-jcs-v1.0.0).
HITL gate
make_payment
Submit a bounded-spend authorization. In chain mode (Sepolia signer set), emits a real PaymentReceiptEmitted event and returns a SettlementReceipt with tx_hash + Voyager link.
on-chain
verify_receipt
Verify a SettlementReceipt. Local JCS mode (receipt + expected_hash) or on-chain mode (tx_hash): reads the Sepolia event, reconstructs the receipt, computes JCS hash, returns audit-ready proof bundle.
audit

Agent flow: 402 paywall → on-chain proof

0
Configure pay-mcp in Claude Code
Add to .claude/settings.json or ~/.claude.json:
{
  "mcpServers": {
    "pay": {
      "type": "http",
      "url": "https://mcp.vauban.tech/pay/mcp"
    }
  }
}
First launch opens browser for one-time OAuth 2.1 PKCE via auth.vauban.tech.
1
Agent encounters a 402 paywall
The upstream API returns 402 Payment Required with x402 headers:
HTTP/1.1 402 Payment Required
X-Payment-Required: version=2,
  network=starknet-sepolia,
  recipient=0x044dd87a94a801c...,
  amount=50000,
  currency=USDC,
  scope=api.vauban.tech/pay/data
2
HITL: request_delegation_grant
Agent requests a DelegationGrant; user reviews caps and approves:
Tool call
request_delegation_grant({
  delegator: "0x005f4802...",
  delegatee: "claude-code-agent",
  scope:
    "api.vauban.tech/pay/data",
  expires_at:
    "2026-05-23T04:00:00Z",
  cap_per_tx: 100000,
  cap_per_period: 1000000
})
Result
{
  "canon_version":
    "x402-jcs-v1.0.0",
  "grant_hash":
    "a4f7e29b1c83d5f0...",
  "grant_jcs_b64":
    "eyJ0eXBlIjoiRGVs..."
}
Human-in-the-loop gate: user reviews amount + scope before approval. Cap enforced on-chain by PaymentDemoEmitter.
3
make_payment -- chain mode
Agent submits the payment; pay-mcp emits a real Starknet Sepolia tx:
Tool call
make_payment({
  amount: 50000,
  currency: "USDC",
  recipient:
    "0x044dd87a...",
  scope:
    "api.vauban.tech/pay/data"
})
Result
{
  "status": "submitted",
  "payment_hash":
    "4eacfd4049ca47af...",
  "tx_hash":
    "0x02919a45344660ce...",
  "voyager_url":
    "https://sepolia.voyager.online/tx/0x02919a..."
}
4
verify_receipt -- on-chain audit
Agent reads the on-chain event and returns an audit-ready proof bundle:
verify_receipt({ tx_hash: "0x02919a45344660ce..." })

// Result:
{
  "verified": true,
  "tx_hash":
    "0x02919a45344660ce8ca9cbd5ecf96afbc56664c67d...",
  "voyager_url":
    "https://sepolia.voyager.online/tx/0x02919a...",
  "on_chain_event": {
    "receipt_core_hash":
      "0x4eacfd4049ca47afc28a3c46d4d592d2e3237ca3...",
    "payment_amount": "50000",
    "currency_decoded": "USDC",
    "timestamp_ms": "1779527515000",
    "tx_emitter": "0x005f4802..."
  },
  "reconstructed_receipt": {
    "type": "SettlementReceipt",
    "canon_version": "x402-jcs-v1.0.0",
    "network": "starknet-sepolia",
    "contract_address": "0x044dd87a94a801cf..."
  },
  "computed_jcs_hash":
    "sha256:4eacfd4049ca47afc28a3c46d4d592d2e3237ca3...",
  "contract_address": "0x044dd87a..."
}
EU AI Act Art. 12 audit log: every payment receipt is cryptographically anchored on Starknet Sepolia. Any auditor can re-derive the JCS hash off-chain and compare against receipt_core_hash from the on-chain event.
Architecture

pay-mcp is a stateless StreamableHTTP MCP server (Node.js 22, TypeScript). Chain mode activates when PAY_MCP_SEPOLIA_ACCOUNT_ADDRESS and PAY_MCP_SEPOLIA_PRIVATE_KEY are set in the pod environment. The Starknet signer uses an OZ account on Sepolia (0x005f4802a628e6a5...) to invoke PaymentDemoEmitter at 0x044dd87a94a801cf775d4c5e4b6703102d4e97e1cd1d0a8879341219ae4f19ff. Settlement receipts are JCS-hashed per x402 LF spec and stored as receipt_core_hash in the PaymentReceiptEmitted event.

Source (pay-mcp) PaymentDemoEmitter (Voyager) Live tx (Voyager) IETF I-D (STARK Receipts)
Section 3 / 3

Live Sepolia receipt

The first PaymentReceiptEmitted event on Starknet Sepolia. The on-chain receipt_core_hash is SHA-256(JCS(receipt_core)). Any buyer can re-derive the digest off-chain and compare against Voyager.

Live -- Starknet Sepolia PaymentDemoEmitter contract
Contract
0x044dd87a94a801cf775d4c5e4b6703102d4e97e1cd1d0a8879341219ae4f19ff
View on Voyager
First emission tx
0x014483073ca64c1f5113f0d7011c65f47005604307a725341b214b3727beadd3
View on Voyager
Class hash
0x4048125390be67a16ae197be1fac1e6bd1fa04c4830b5db219be2e2e1090a4f
Network
Starknet Sepolia (testnet) ; RPC via https://sepolia.rpc.vauban.tech/rpc/v0_10
Block explorer
sepolia.voyager.online  (Voyager ; canonical ; Starkscan retired)

Cross-axis binding

The four coalition axes share the same payment_hash and action_ref. One mutation to either value breaks all axes simultaneously.

Axis Implementation Bound field Value (truncated)
Axis 0 ; Substrate AlgoVoi (Go + Rust 5th-impl) payment_hash 2ed186eb...0f580
Axis 1 ; STARK Vauban (Rust, Stwo Circle STARK M31) payment_hash + action_ref payment_hash: 2ed186eb...0f580
action_ref: 10d8a38c...0c2c1
Axis 2 ; Hybrid-PQC FeedOracle (Python, ES256K + ML-DSA-65) payment_hash + action_ref payment_hash: 2ed186eb...0f580
action_ref: 10d8a38c...0c2c1
Axis 3 ; Work-receipt andysalvo (Node.js, RFC 8785 JCS) action_ref 10d8a38c...0c2c1
payment_hash (full): 2ed186ebc66947eaac6a05a88c7bc096ee07ac11a2c44bb5580bd72b3670f580
action_ref (full): 10d8a38c01d8672176aa6e5209a368fde3e1831640d69e15283142b35880c2c1
Axis 1 core digest: sha256:89e01af0770494243e7ba6d003332688ca7107dd05c52cc8c73f470b13d5767f

Bounded-spend fixture vectors bind to this same payment_hash / action_ref pair via the cross_axis_binding field. The Axis 1 core digest is referenced in each vector's settlement_receipt.evidence.intent_proof_ref.claim_hash.