Each *-conformance/README.md now has a line that begins **Provenance.**: the generator that writes the corpus and its input, and for an input not generated here its source and licence. OER/2's corpus is settled and left as it is. byte-exact-conformance and quantum-ops-conformance get a README. wai-rs/tests/vectors/README.md gives a row per vector directory. Where the staged-delivery, staged-measurement and telemetry READMEs called their content "synthetic", that sentence is now their provenance line. Two vectors are recorded as not generated, from the provenance audit: int_video's video_real (a pan over a third-party picture) and neural-conformance's photo (a third-party picture, with a decoder trained on unrecorded images). Their lines say so and that they are to be replaced; the photo bullet no longer names the picture's source product. tests/corpus_provenance.rs requires the line in every corpus and a row for every vector directory; CI runs it with the carriage tests. CONTRIBUTING states the rule: corpus content is generated here, or recorded with a licence that permits redistribution, and a word like "synthetic" is not a provenance line. Co-Authored-By: Claude Opus 5.5 <[email protected]>
5.8 KiB
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