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.
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.
RFC 8785 reference: rfc-editor.org/rfc/rfc8785. Implementation: TypeScript port of the JCS algorithm (alphabetical sort, deterministic number serialisation).
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.
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 |
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.
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.
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.
Nominal receipt core. Both ES256K and ML-DSA-65 signatures cover SHA-256(JCS(core)). Canonical baseline for cross-implementation comparison.
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.
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.
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#2411FeedOracle JWKS (live)
tooloracle.io/.well-known/jwks.jsonkid: 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.
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.
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.
Axis 4 ; Composite trust-query
nobulex (@arian-gogani) ; tri-party composite envelope, multi-emitter evidence rows,
cross-axis binding via shared (payment_hash, action_ref)
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.
The current scaffold is tri-party (three confirmed emitters). The envelope schema is designed for N-party extension; a tetra-party configuration is anticipated once the risk-check extension referenced in x402 issue #2421 lands.
This is the composition-layer axis. The other axes (Axis 0 ; substrate, Axis 1 ; STARK, Axis 2 ; hybrid-PQC, Axis 3 ; work-receipt) contribute rows. Axis 4 defines the envelope that assembles and binds them under a single query surface.
Emitter 1 ; AlgoVoi
Compliance screening
Frameworks: UK MLR 2017, EU FSF, OFSI, OFAC.
Behavioral accumulator across 8 chains.
evidenceType: behavioral
Emitter 2 ; Vauban Pay
STARK proof-of-payment-conditions
Settlement chain: Starknet.
Stwo Circle STARK M31 prover ; cryptographic evidence.
evidenceType: cryptographic
Emitter 3 ; nobulex (@arian-gogani)
Bilateral receipt
Schema: verascore-evidence-schema-v0.1.
Tri-party envelope author ; composite-layer co-design.
evidenceType: observational
Emitter 4 ; placeholder
Reserved for risk-check (#2421) or fiscal_authority extension. N-party envelope; no schema change required at the composite layer.
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.
This asymmetry is structural: it reflects what each evidence class can legitimately attest about (per x402 bazaar spec, PR #2322).
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.
0x4048125390be67a16ae197be1fac1e6bd1fa04c4830b5db219be2e2e1090a4f https://sepolia.rpc.vauban.tech/rpc/v0_10Cross-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...0f580action_ref: 10d8a38c...0c2c1 |
| Axis 2 ; Hybrid-PQC | FeedOracle (Python, ES256K + ML-DSA-65) | payment_hash + action_ref | payment_hash: 2ed186eb...0f580action_ref: 10d8a38c...0c2c1 |
| Axis 3 ; Work-receipt | andysalvo (Node.js, RFC 8785 JCS) | action_ref | 10d8a38c...0c2c1 |
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.