stellar:testnet.
What Rail402 conforms to
Five of these are verified and proven on chain. The sixth, the full upstream e2e suite, is partial for a diagnosed defect in the upstream harness rather than in Rail402, described in full below rather than glossed.
Tested with stock clients
Conformance is not a self-report. The@rail402.dev/conformance harness clones the upstream x402 repository at a pinned spec commit, installs a proxy that points the suite’s own, unmodified clients at a Rail402 deployment, and runs the upstream e2e scenarios. Two of those scenarios settle real testnet USDC through stock axios and stock fetch clients:
Both are settlements produced by the x402 project’s own test code, in a real stablecoin, with no Rail402-specific client.
The upstream e2e suite
Two of the suite’s four scenarios pass and settle real USDC (above). The other two fail, and the cause is two defects in the upstream harness itself, diagnosed and documented:mockFacilitatorUrlis never assigned. The suite declares the field its resource servers read to find a facilitator, but never sets it, so the mock facilitator the suite starts is never wired to any resource server, and every non-Stellar route fails route validation. Wiring it by hand drops the error count from 13 to 4.- Multi-family servers fail closed on unsupported routes. The express, fastify, and hono servers register the union of every protocol family’s routes, and the resource server initializer fails closed on any route it cannot serve, so a single-chain facilitator returns an error on every route, including the Stellar one. The remaining 4 failures are
batch-settlement/evmscenarios that no environment switch can omit.
next server is the exception, because its per-file routes bypass the union. Its Stellar route produced a valid 402 from the facilitator and built a stock payment payload, failing only when the test payer held no USDC, which is why the payer is now funded and --servers=next is wired into the harness.
A non-null reason on every rejection
Every rejection carries a machine-readable reason, and this holds at the type level, not by convention. The shared error registry makesreason non-optional on the rejection type and resolves it from a registered default, so a rejection cannot be constructed with an empty reason. The registry holds 122 codes across nine surfaces (facilitator, Bazaar, MCP, settlement, explorer, config, and the protocol codes reproduced byte for byte from the spec), each with a provenance marking whether it is a spec code, a library code, or Rail402’s own.
The guarantee is audited live, not asserted. A rejection audit exercises 19 of 19 rejection paths against a deployed facilitator, including a stripped auth entry and a cleared auth-entry signature (the first coverage of the upstream validateAuthEntries branch), and checks that each returns a registered code, the expected code, and actionable prose. The results are in docs/status/rejection-audit.json.
Conformance is a moving target
Conformance holds only as long as the wire format does, and the discovery conventions are still evolving under the x402 Foundation. Keeping conformance current is treated as a first-class, ongoing task: a daily spec-drift check detects an upstream change within a day and measures its impact. Drift, not inability, is the failure mode this guards against.Next steps
Run the conformance harness
Point the upstream suite at any deployment yourself.
Verify it yourself
Every settled hash, on chain.
Error registry
The 122-code registry behind the reason guarantee.