open-standards/wai/signer-conformance
Repository files (latest commit first)
Filename Latest commit message Latest commit date
2026-10-21 12:56:01 -04:00
..
.gitattributes wai: key discovery, signing authority and module revocation 2026-10-01 07:12:20 -04:00
README.md wai: every corpus states the provenance of its content 2026-10-07 10:09:21 -04:00
signer_verify.py wai: bearer receipts corpus, second implementation, HTTP index step 6, registry, SPEC §5, CHANGELOG, CI step 2026-10-21 12:56:01 -04:00
vectors.json Merge main (#186 merged as ae9a1ca6: strict Ed25519) into wai/w5-4-measure-web 2026-10-08 02:00:51 -04:00

signer-conformance

Conformance for key discovery, signing authority and module authorisation (§7): the forms of a signer_id, an origin's key log, anchoring, the confirmation a verifier reports beside a receipt's or claim's verdict, and the checks a sink runs before it runs a decoder or reconstruct module.

Provenance. Generated here by wai_signer_vectors, from published one-byte seeds (below). No media.

Each vector declares one verdict, set from the text in the generator and never copied from a verifier. A verifier that reaches another verdict — another level, step, reason, head or anchor path — does not conform.

Files

file what it is
vectors.json The corpus. Regenerate with wai_signer_vectors gen .; wai_signer_vectors verify . checks the canonical fixture, a byte-identical regeneration and every verdict.
signer_verify.py A second verifier, written from §7, that shares no code with wai-rs. It takes from ../claim-conformance/claim_verify.py only what §7 reuses of §3.1: the JSON reading, JCS, BLAKE3, the strict Ed25519 rule, the RFC 3339 syntax and claim verification.

Procedures

confirm (§7.4) runs on an item and reports confirmed with the origin, key-id, head revision_hash and anchor path — and, where they apply, moved_to, retired_until, untimed=true, expected= and also_delivers= — or unconfirmed or refused at a §7.4 step (1–7, or 6a) with a reason of §7.7. For a reconstruct-session claim whose energy is not null, the verdict goes on with ; figure and the confirmation of its energy figure, an item of its own (§7.5) that needs reconstruct-session and the energy authority of its class. The item is either receipt, a claim's wire form, which is first verified under §3.1 (a claim that fails is reject step=<n> reason=<label>, and is never confirmed), or context.item: the kind (group or family), signer_pubkey, signer_id, classes (for a group, the acquisition classes its objects' labelled leaves and its labelled total carry; for a family receipt, the acquisition classes its figures' labels carry) and its signed time (or null). The authorities an item needs are derived from it by §7.5's table. The context also holds revisions (revision texts the verifier holds, in any order; one that fails rule 1 is not held), anchors (origin, revision, path, acquired_at, and pinned_revision for a pinned record, which a forward move keeps) and, optionally, expected_origin (origin and source, relying-party or subject).

anchor (§7.3) runs on a key-log document (log) retrieved for origin by path (pinned or fetched, with acquired_at), and optionally current: an anchor already held, with the revisions held with it. It reports anchored revision=<hash> anchor=<path> — with pinned_revision=<hash> where a pinned record moved forward — not_anchored reason=<label> or replaced reason=key_log_replaced.

module (§7.9) runs on a module's bytes (module, hex), whether they are a module or a pinned parameter set (object), a grant, the capability being decoded, the sink's module_origins (each an origin and source), the revisions, anchors and statuses the sink holds, its trusted clock (now, or null for none) and whether the envelope leaves a fallback. It reports run with the granting key's origin, key-id, head, anchor path, where its module origin came from (expected=) and kill_latency_s, or fallback or inert at a §7.9 check with its reason; a digest another anchored origin revokes adds revoked_by=<origin>. A parameter set that is not held adds the refusal SPEC §3.1's check 5 reports: refusal=prior_revoked where its digest is revoked, refusal=prior_not_authorised for any other check. A parameter set whose digest the head of an anchor the sink holds revokes is reported at check 5 with revoked_by=<that origin> and prior_revoked whichever check its grant failed first, unless the grant reached check 5 itself. For a parameter set grant may be null, a sink that holds no grant: the set is then refused as revoked where its digest is, and otherwise reported as no_grant refusal=prior_not_authorised.

Keys, origins and times

Everything is synthetic. Keys are Ed25519 from published one-byte seeds and attest nothing: 0x61 the root in use, 0x62 the key it commits to, 0x68 the key that one commits to, 0x63 and 0x66 delivery keys (0x66 also meters), 0x64 and 0x69 metering keys, 0x65 and 0x6e lawful-basis keys, 0x6b and 0x6c module-granting keys, 0x60 a key added later, 0x67, 0x6a and 0x6f keys an attacker holds, 0x70, 0x71 and 0x72 the root, committed key and module-granting key of a second origin, 0x73 and 0x74 a measurement key and an operating-point key, 0x75 a key that signs family receipts with a ModelBased figure, 0x76 and 0x77 a sink's key for stage and a relay's for delivery-gap, and 0x78 and 0x79 a sink's keys for reconstruct-session, the second also holding energy/OnChipCounter. jwp-receipts §7.8 says such a key must never be listed in a real key log: every anchored verdict here carries note=published_test_key, which is what a verifier reports on finding one. Origins are reserved example names (publisher.example, with and without port 8443, service.example, other.example). Times are in September 2026 and invented.

signer_verify.py needs Python 3 with the cryptography package. CI runs it on the linux runner (independent-verifiers in wai-conformance.yml), and requires its verdicts output to equal wai_signer_vectors verdicts line for line. By hand:

python3 signer_verify.py            # every vector, and the fixture against wai-rs
python3 signer_verify.py fixture    # the fixture's bytes, signature and hash
python3 signer_verify.py verdicts vectors.json