Conformance Test Suite
Pass all six mandatory suites to earn the SignedReceipt v1 compatible badge. The harness is Apache-2.0 and the vectors are CC0. The corpus is documented at signedreceipts.org/source/conformance; a downloadable distribution is being prepared and is not yet published. The fixture counts on this page describe the corpus as it stands in the maintainer’s tree and cannot be independently verified until that distribution is published; the total vector count quoted on /source/conformance (248 known-good + 187 known-bad) counts the full corpus, not the six mandatory suites counted here.
Run the suite
There is no public download or package release yet, so the command below describes the intended workflow once the distribution is published. Request the current corpus from open-source@cloakapi.io in the meantime.
# Planned workflow — nothing is published on crates.io or npm yet
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.
- Send your implementation output (
result.json) andinfo.jsonto open-source@cloakapi.io. There is no public pull-request workflow yet — the repository has not been published. - The submission is reviewed by the maintainer. On acceptance, your implementation is listed at signedreceipts.org/implementations.
Submission
# Run the suite and save results
signedreceipt conformance ./conformance/fixtures/ --json > result.json
# Then email result.json + info.json to open-source@cloakapi.io
# (no public repository or PR workflow exists yet)
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 every mandatory suite in the maintainer's own runs. Because the corpus is not published yet, that result is not independently reproducible today:
- Rust: signedreceipts.org/source/reference-rust — built from source; not released on crates.io.
- TypeScript: signedreceipts.org/source/reference-typescript — built from source; not released on npm.