@accord-protocol/conformance
v0.4.2
Published
Accord Protocol conformance suite and CLI. Exercises L0 schema, L1 transport, L2 rail, L3 security and L4 registry compatibility against an Accord implementation. Supports HTTP and MCP-stdio probing, plus ed25519 signing of conformance results. The output
Downloads
483
Maintainers
Readme
@accord-protocol/conformance
Accord Protocol conformance suite. Library + CLI that exercises all five levels (L0 schema, L1 transport, L2 rail, L3 security, L4 registry) against an Accord implementation. The output is the source of truth for "Accord-compatible (L)" badge claims* per TRADEMARK.md.
Public docs: Website · Conformance guide · What conformance does not prove
Install
npm install --save-dev @accord-protocol/conformance @accord-protocol/core
# or run on the fly:
npx accord-conformance runCLI subcommands
accord-conformance run [flags] # default if no subcommand (back-compat)
accord-conformance keygen # generate ed25519 keypair
accord-conformance sign --key 0x... <input.json> # sign any Accord JSON object
accord-conformance verify [--expected-key 0x...] <signed.json>run is invoked by default if no subcommand is given, so prior usage like npx accord-conformance --levels L0,L1 still works.
For an end-to-end keygen / run / sign / verify walkthrough with a working signed artifact, see docs/conformance-signed-example.md.
Levels
L0 Schema-compatible — objects validate against schemas/v0
L1 Transport-compatible — Accord/402 or Accord/MCP roundtrip works
L2 Rail-compatible — at least one rail adapter passes verifyPayment + settle
L3 Security-compatible — production-safety gates fire on mainnet writes
L4 Registry-certified — listed in the public registry with passing conformanceThis package ships all five levels (L0 + L1 + L2 + L3 + L4). The CLI runs them in-process by default, or against a live HTTP endpoint via --target <url>.
$ npx accord-conformance --levels L0,L1,L2,L3,L4
L0 PASS (20/20 pass, 0 fail, 0 inconclusive)
L1 PASS (13/13 pass, 0 fail, 0 inconclusive)
L2 PASS (24/24 pass, 0 fail, 0 inconclusive)
L3 PASS (12/12 pass, 0 fail, 0 inconclusive)
L4 PASS (13/13 pass, 0 fail, 0 inconclusive)
Achieved: L4L3 — what it checks (security gates)
Probes assertProductionSafety() and the audit-manifest verifiers in both rail SDKs:
- Mainnet writes without
scriptErgoTree→INSECURE_MAINNET_MODE - Mainnet writes with arbitrary tree but no
auditPolicy→UNAUDITED_ERGOTREE - The documented
dangerouslyAllowInsecureMainnetP2PK/dangerouslyAllowUnauditedContractescape hatches still work - Testnet always allowed
verifyAuditedErgoTree({ requireMainnet: true })rejects on a draft-pre-audit manifest- Both audit manifests are in
draft-pre-auditstatus with all entriesmainnetAllowed: false - Same probes run for the Base/EVM rail's
assertProductionSafety+verifyAuditedContract
L4 — what it checks (registry validation)
Static-validates the registry/ folder:
registry/{providers,verifiers,rails,manifests}/*.jsonparse + carry the righttypeliteral +version: "v0"registry/revocations.jsonis a well-formed array- Each rail record's
manifestfield points at a manifest file that exists - Provider records'
accepted_rails[]only name rails registered inregistry/rails/ conformance.level(when claimed) is one of L0–L4
Network mode (HTTP probing)
--target <url> makes the L1 transport probe a real HTTP endpoint instead of running in-process. Three probes:
$ npx accord-conformance --levels L1 --target https://provider.example/api/run
1. POST without Accord-* headers → expects 402 + Accord-Version, Accord-Agreement-Required, WWW-Authenticate: Accord402
2. POST with X-Accord-Agreement-Id but no payment → expects 402 + body.error in {MISSING_PAYMENT, UNKNOWN_AGREEMENT}
3. POST with both headers (only when --agreement-id + --payment supplied) → expects 200 + x-accord-agreement-hash + body { output, _meta }Optional flags for the happy-path probe:
npx accord-conformance --levels L1 \
--target https://provider.example/api/run \
--agreement-id acc_01HX… \
--payment '{"value":"0.001"}'MCP-stdio mode
--target stdio:./build/mcp-server.js spawns a child process and probes its JSON-RPC over stdin/stdout per the MCP spec:
npx accord-conformance run --levels L1 \
--target stdio:./build/mcp-server.jsFour checks:
initialize→ server returnsprotocolVersiontools/list→ returns at least one tool whoseinputSchemadeclaresaccord_agreement_id+accord_paymenttools/callwithoutaccord_agreement_id→_meta.accord_error_code == MISSING_AGREEMENT_IDtools/callwith agreement-id but no payment →_meta.accord_error_code ∈ {MISSING_PAYMENT, UNKNOWN_AGREEMENT}
Conformance-result signing
Sign a conformance result so the registry / verifiers can confirm provenance:
# 1. Generate keypair (one-time setup)
$ npx accord-conformance keygen
# 2. Run + sign + submit
$ npx accord-conformance run --levels L0,L1,L2,L3,L4 --json > result.json
$ npx accord-conformance sign \
--key 0x<your private key> \
--signer 'verifier://your-id' \
-o signed.json \
result.json
# 3. Anyone can verify
$ npx accord-conformance verify signed.json
$ npx accord-conformance verify --expected-key 0x<your public key> signed.jsonThe signing input is BLAKE2b-256(canonical_json_bytes(object_without_signature)) — same algorithm as ACCORD-002 §5 receipts. Tampering with any field after signing breaks the signature; verify exits non-zero with code BAD_SIGNATURE.
The same sign/verify subcommands work on any Accord JSON object — Agreement, Verification Receipt, audit manifest, registry record. The signature shape (scheme: "ed25519", hex-encoded public_key + signature + ISO-8601 signed_at) is uniform across artifacts.
L1 — what it checks
L1 exercises the Accord/MCP and Accord/402 transports against the reference @accord-protocol/{mcp,gateway} implementations with a Mock rail + a synthetic verifier:
- MCP —
wrapAccordMcprejects calls withoutaccord_agreement_id; happy path runs the handler;_meta.accord_agreement_hashis the canonical-bytes blake2b256; embedded Verification + Settlement Receipts pass core's validators. - Accord/402 — no Accord-* request headers → 402 with the right response headers (
Accord-Version,Accord-Agreement-Required,WWW-Authenticate: Accord402); valid request → 200 with{ output, _meta }body andx-accord-agreement-hashresponse header; embedded receipts validate; second use of the samepayment_idis rejected withREPLAY_DETECTED.
L2 — what it checks
L2 exercises each of the four reference rails (rails-ergo, rails-rosen, rails-base, rails-x402) with a stub backend, six checks per rail:
verifyPayment(happy)returnsok=truepayment_idis a non-empty string (suitable for replay protection)rail.settle()is implemented and returns a Settlement Receipt- The Settlement Receipt passes core's
validateSettlementReceiptagainst the same Agreement id/hash, rail, currency, and decimals receipt.modeis inRAIL_MODE_ALLOWLIST[rail]verifyPayment(garbage)returns a structuredok=falseresult
A third-party rail can be tested with the same harness by passing it via runL2({ extraRails: [...] }).
$ npx accord-conformance --levels L0,L1,L2
L0 PASS (20/20 pass, 0 fail, 0 inconclusive)
L1 PASS (13/13 pass, 0 fail, 0 inconclusive)
L2 PASS (24/24 pass, 0 fail, 0 inconclusive)
Achieved: L2$ npx accord-conformance --levels L0,L1
L0 PASS (20/20 pass, 0 fail, 0 inconclusive)
L1 PASS (13/13 pass, 0 fail, 0 inconclusive)
Achieved: L1CLI
# Run L0 against the current repo
npx accord-conformance
# Explicit
npx accord-conformance --levels L0
# Request more levels (some may report inconclusive until they ship)
npx accord-conformance --levels L0,L1,L2
# JSON output — what you submit to the registry
npx accord-conformance --json > conformance-result.json
# Run against a specific repo dir
npx accord-conformance --repo-root /path/to/your/accord-protocol-forkExit codes:
- 0 — every requested level passed
- 1 — at least one fail or inconclusive at the requested levels
- 2 — CLI usage error
Library
import { runConformance } from "@accord-protocol/conformance";
const result = await runConformance({
repoRoot: process.cwd(),
levels: ["L0"],
});
console.log(result.achieved_level); // "L0" | "L1" | … | nullThe ConformanceResult is JSON-shaped — same as the CLI's --json output. Submit it to registry.accordprotocol.ai to claim a badge.
L0 — what it checks
For every fixture in test-vectors/{agreement,verification-receipt,settlement-receipt}/v0/:
- JSON Schema validation against the matching
schemas/<kind>.v0.schema.json.- Filenames that start with
invalid-are expected to fail validation. The check passes iff ajv rejects.
- Filenames that start with
- Canonical-bytes equality against the pinned
<name>.canonical.txtsidecar (for accept-case fixtures). accord_hash_v0equality against the pinned<name>.hash.txtsidecar (for accept-case fixtures).
Missing pinned sidecars are reported as inconclusive (not fail) — the implementation isn't broken, the fixtures just need re-deriving via node scripts/derive-fixture-hashes.mjs.
Current limits
- L1 / L2 transport / rail tests — planned transport/rail conformance scope.
- A network-mode CLI (
--target https://provider.example) — for L0 the implementation under test is a directory of schemas + fixtures, not a live endpoint. L1 / L2 will introduce HTTP / MCP probing. - Conformance-result signing. The result JSON is plain text today; v1 may add an issuer signature so the registry can verify provenance.
License
MIT.
