Conformance Test Suite
Pass all six mandatory suites to earn the SignedReceipt v1 compatible badge. The suite is open-source under Apache-2.0 at github.com/signedreceipt/conformance .
Run the suite
cargo install signedreceipt
git clone https://github.com/signedreceipt/conformance
signedreceipt conformance ./conformance/fixtures/ --json Expected output when all tests pass:
Suite: canonicalisation PASS 12/12
Suite: signature PASS 18/18
Suite: chain-linking PASS 20/20
Suite: claim-schema PASS 15/15
Suite: key-discovery PASS 10/10
Suite: version-compat PASS 8/8
Total: PASS 83/83 (6 suites) Suite 1 — canonicalisation
Every implementation MUST produce byte-identical output from the same abstract receipt using RFC 8785 JCS. The suite checks twelve fixtures:
| Fixture | Type | What it tests |
|---|---|---|
canon-01.json | Known-good | Minimal valid receipt; canonical form matches reference bytes |
canon-02.json | Known-good | All optional fields present; canonical form matches reference bytes |
canon-03.json | Known-good | Unicode in sub field; canonical form encodes as UTF-8 with no BOM |
canon-bad-01.json | Known-bad | Duplicate key in JSON object — MUST reject |
canon-bad-02.json | Known-bad | BOM at start of file — MUST reject |
canon-bad-03.json | Known-bad | Non-LF newlines in string value — MUST reject |
canon-bad-04.json | Known-bad | Trailing comma — MUST reject |
Suite 2 — signature
Signature verification using ECDSA P-256 SHA-256. DER-encoded signatures are explicitly rejected; only the 64-byte compact form is valid. Eighteen fixtures:
| Fixture | Type | What it tests |
|---|---|---|
sig-01.json | Known-good | Valid P-256 signature, compact 64-byte form |
sig-02.json | Known-good | Signature from a rotated (retired) key with valid nbf/exp window |
sig-03.json | Known-good | Signature from desktop device key (iss contains /keys/desktop/) |
sig-bad-01.json | Known-bad | Single bit flipped in sig field — MUST reject |
sig-bad-02.json | Known-bad | DER-encoded signature — MUST reject |
sig-bad-03.json | Known-bad | Wrong key used (key A signing, key B declared in kid) — MUST reject |
sig-bad-04.json | Known-bad | Signature over non-canonical form — MUST reject |
sig-bad-05.json | Known-bad | sig field included in signed payload — MUST reject |
sig-bad-06.json | Known-bad | Key expired (exp in the past) — MUST reject |
sig-bad-07.json | Known-bad | Key not yet valid (nbf in the future) — MUST reject |
Suite 3 — chain-linking
Receipt chains are valid iff every receipt's prev_hash matches
the SHA-256 of its predecessor's canonical bytes including the sig
field, and seq increments by exactly 1 with no gaps.
Twenty fixtures:
| Fixture | Type | What it tests |
|---|---|---|
chain-good-01/ | Known-good | Three-receipt chain: seq 0, 1, 2; all links valid |
chain-good-02/ | Known-good | Single receipt with prev_hash null (first in session) |
chain-good-03/ | Known-good | Cross-chain link: child chain referencing parent jti |
chain-bad-01/ | Known-bad | Seq gap: 0, 1, 3 (missing 2) — MUST reject |
chain-bad-02/ | Known-bad | Fork: two receipts both claim seq=1 — MUST reject |
chain-bad-03/ | Known-bad | Wrong prev_hash (single byte changed) — MUST reject |
chain-bad-04/ | Known-bad | Non-null prev_hash on seq=0 receipt — MUST reject |
chain-bad-05/ | Known-bad | seq decrement (1, 0) — MUST reject |
Suite 4 — claim-schema
Required fields must be present and valid. No plaintext PII may appear in any signed field. Fifteen fixtures:
| Fixture | Type | What it tests |
|---|---|---|
schema-good-01.json | Known-good | Minimal valid claims object |
schema-good-02.json | Known-good | All claim types present: tokenisation, routing, egress, countersignature |
schema-good-03.json | Known-good | Vendor extension claims under x-vendor-* namespace — MUST pass through |
schema-bad-01.json | Known-bad | Missing required v field — MUST reject |
schema-bad-02.json | Known-bad | Email address in sub field — MUST reject (PII check) |
schema-bad-03.json | Known-bad | Phone number in claims.tokenisation detector fingerprint — MUST reject |
schema-bad-04.json | Known-bad | Credit card pattern in routing_decision.reason — MUST reject |
schema-bad-05.json | Known-bad | Non-ULID jti — MUST reject |
schema-bad-06.json | Known-bad | Unknown tokenisation level enum value — MUST reject |
Suite 5 — key-discovery
Implementations MUST resolve kid via the issuer's
/.well-known/cloakapi-receipt-pubkeys.jwks or an equivalent
endpoint. Unknown kids MUST be rejected. Ten fixtures:
| Fixture | Type | What it tests |
|---|---|---|
key-good-01 | Known-good | Current kid resolves to active key |
key-good-02 | Known-good | Retired kid resolves to retired key within its validity window |
key-bad-01 | Known-bad | Unknown kid — MUST reject |
key-bad-02 | Known-bad | Retired kid outside validity window (past exp) — MUST reject |
key-bad-03 | Known-bad | JWKS endpoint unreachable and no cached key — MUST reject (not silently pass) |
Suite 6 — version-compatibility
v1 envelope required fields must be present. Unknown x-* vendor
claims MUST be ignored (not rejected). Future versions of the spec MUST NOT
cause v1 verifiers to crash. Eight fixtures:
| Fixture | Type | What it tests |
|---|---|---|
compat-good-01.json | Known-good | v1 receipt with x-acme-audit vendor extension — MUST verify OK |
compat-good-02.json | Known-good | v1 receipt with unknown top-level field (forward-compat) — MUST verify OK |
compat-bad-01.json | Known-bad | v field set to v0 (no such version) — MUST reject |
compat-bad-02.json | Known-bad | v field set to v2 (future, not yet implemented) — MUST reject with version-unknown error |
Badge criteria
To display the "SignedReceipt v1 compatible" badge, your implementation must:
- Pass 100% of all six mandatory suites (83/83 fixtures).
- Run the suite against a publicly hosted endpoint or a local test server.
- Submit a pull request to github.com/signedreceipt/conformance with your implementation output in
implementations/<your-impl-name>/result.json. - The PR is reviewed by the SignedReceipt maintainers. On merge, your implementation is listed at signedreceipt.org/implementations.
Submission
# Run the suite and save results
signedreceipt conformance ./conformance/fixtures/ --json > result.json
# Fork and submit
git clone https://github.com/signedreceipt/conformance
cd conformance
mkdir -p implementations/your-impl-name
cp /path/to/result.json implementations/your-impl-name/result.json
cp /path/to/implementation-info.json implementations/your-impl-name/info.json
git checkout -b add-your-impl
git add implementations/
git commit -m "Add conformance results for your-impl-name v1.0"
git push origin add-your-impl
# Open a PR at github.com/signedreceipt/conformance
The info.json file should contain:
{
"name": "your-impl-name",
"version": "1.0.0",
"language": "typescript",
"repo": "https://github.com/your-org/your-impl",
"contact": "your@email.com"
} Reference implementations
Both reference implementations pass 100% of mandatory suites:
- Rust:
github.com/signedreceipt/reference-rust
—
cargo install signedreceipt - TypeScript:
github.com/signedreceipt/reference-typescript
—
npm install @signedreceipt/core