A sink is a computer that runs named, pinned models: codec priors, DRED's weights, an exact upscale's prior, enhancement and generator models. Nothing said which of them a fleet's sinks may run, revoked one across a fleet, or rolled up what each class of device ran. extensions/model-governance.md registers the record `wai.sink.models`, in the `models` profile (core/profiles.json, CORE.md's table), outside the core. An operator signs a model policy (`wai-model-policy`): classes of devices, enrolled by key or vouched for by an attestation key (`wai-model-device`), and for each class the parameter sets it may run by the digest a pin names (SPEC §3.1), per capability and role (decode, upscale, enhance, generate), with the least tier each must run at; a span, a successor that takes its place from its own start, and the operator's key log (jwp-receipts §7), whose `revoked_modules` revoke a set from the first revision that lists it: the list SPEC §3.1 check 5 already reads at a sink. A device signs a run report (`wai-model-run`) from what it already states: each decode's neural-dispatch report with the set it read (a sealed set's opened digest too), and its sessions' exact-upscale presentation statements, whose sink-made pictures name their prior or model. A verifier refuses a set outside the policy (`model_not_in_policy`), a revoked set run at or after its revocation (`model_revoked`), a period outside the policy's time in force (`policy_expired`, `policy_not_yet_valid`), a run below the policy's tier (`model_tier_below_policy`) and a float path claiming decode-equivalence (neural-dispatch's `dispatch_tier_refused`). The operator's roll-up (`wai-model-rollup`) states per class the reports, the devices that reported and those enrolled that did not, and each set's decodes by unit, frames and pixels, recomputed from the reports (`rollup_mismatch`). neural-dispatch §5, exact-upscale §6.2 and fleet §1 point to it; no record they define changes. The reference is the `model_policy` module of wai-rs (feature `model_policy`, in `full`); `wai model verify` (catalogue `model.verify`) verifies a bundle (`*.wai-models.json`), and `wai verify` reads a bundle and each record alone. The corpus is live-conformance/models/ (57 bundles: 3 accepted, 54 refused, every reason of §10 and every reused reason at least once), and model_policy_verify.py is its second implementation, written from the text: it agrees on every outcome, reason, place and statement, 14 of 14 mutated copies fail, and 51 of 51 weakened verifiers are caught. vectors.json has one SHA-256 when generated on x86_64 and on arm64. 22 faults planted in the reference (a capability or role ignored, the revocation instant excluded, a sealed set's inner identity ignored, the successor's start ignored, expiry unchecked, a float path's claimed tier believed, silent devices and units miscounted, the signing domain, a period's end included, the attestation's span, a statement counted twice, overlap, the roll-up's signer and reports, a path's arithmetic, pictures' revocation, the tier compared the wrong way, the successor chain, the key log ignored, an unnamed model admitted) each fail its tests. The registry export, the operation catalogue and Studio's actions are regenerated by their tools. Co-Authored-By: Claude Opus 5.5 <[email protected]>
31 KiB
WAI Extension: Model Governance
Status: Draft. Registers the record
wai.sink.models: which parameter sets a fleet's sinks may run, and what they ran. An operator signs a model policy: its sinks in classes, each class's devices named by their keys or vouched for by an attestation key, and for each class the parameter sets it may run, each named by the SHA-256 a pin names it by (SPEC §3.1), for a capability and a role (a codec's or DRED's set, an exact upscale's prior, an enhancement model, a generator), with the determinism tier it must run at; the policy holds for a span, a successor takes its place, and the operator's key log (jwp-receipts §7) revokes a set by its digest. A sink signs a run report for a period, built from what it already states: the report of neural-dispatch §5 for each neural decode it ran (the unit, the backend and the tier), with the set the decode read, and the presentation statements of exact-upscale §6.2 its sessions signed (the pictures it presented that were transmitted, derived exactly, edited or generated, each sink-made one with the digest of the prior or model that made it). A verifier holding the policy, the key log and the report refuses a report in which a set outside the policy ran, a revoked set ran after its revocation, the policy was no longer in force, or a path in floating point claims a decode that needsdecode-equivalence. The operator signs a roll-up per period: for each class, the reports, the devices that reported and those that did not, and each set that ran with its decodes by unit, its frames and its pixels; a verifier recomputes it from the reports. No new transport, and nothing a sink signs today changes. The reference implementation is themodel_policymodule ofwai-rs(featuremodel_policy); the corpus islive-conformance/models/, and its second implementation islive-conformance/model_policy_verify.py. Keywords MUST, MUST NOT, SHOULD, MAY are RFC 2119/8174.Texts read for this revision: the WAI texts this one cites; RFC 3339; RFC 8032; RFC 8785; FIPS 180-4.
1. Scope
In scope: the records of this extension, their encodings, signatures and identities (§3); the model policy, its classes and the sets each may run, its span and its successor (§4); the device attestation that places a device in a class (§5); the run report and the runs it states (§6); the roll-up (§7); the bundle a verifier is given and its verification (§8).
Out of scope: how a sink obtains a set, which prior-carriage states; how a sink is told to load or unload one; whether a set's bytes are the ones a pin names, which SPEC §3.1 checks at the sink before any decode; who may sign a decoder module, which jwp-receipts §7.9 governs; and the presentation of a run to a viewer, which synthesis states. A policy says which sets a fleet's sinks may run. It does not stop a sink from running another: a sink that runs one says so in its report, and a report that leaves a run out is §12's concern.
Relationship to the core spec: wai.sink.models is a record (SPEC §5): a
signed record a WAI tool emits and verifies. It names no payload format and is not
dispatchable.
Relationship to fleet: a fleet enrols the nodes that carry media to sinks; this extension enrols the sinks, by their own keys, in classes of a policy. The two share no record.
2. Terms
- Operator: the party that runs a fleet of sinks. Its operator key, an Ed25519 key (RFC 8032), signs its policies and roll-ups. Its key log, where it keeps one, is published under an origin of jwp-receipts §7.1.
- Device: a sink of the fleet, named by its Ed25519 key, the device key, which signs its run reports.
- Attestation key: an Ed25519 key that vouches for devices (§5): the operator's own provisioning key, or a key of the party that made the devices.
- Class: a named set of devices that run under the same rules.
- Set: a parameter set (SPEC §3.1), named by the digest a pin names it by: its SHA-256
in the pin's form. A prior of exact-upscale is pinned with no form, by the SHA-256 of its one
file (exact-upscale §3.5). A sealed set (prior-carriage §18.2) has a second identity, the
SHA-256 of its plaintext,
inner. - Role: what a set is run as.
decode: the set a capability decodes against, a codec's networks and tables, DRED's weights (opus-dred §4.1) or a generator a capability decodes through.upscale: the prior ofwai-upscale:sr2orwai-upscale:sr4(exact-upscale §3), which makes aderivedpicture.enhance: a model that edits a transmitted picture by a step no verifier recomputes, which makes anassertedpicture.generate: a model that makes asynthesizedpicture. A tone map reads no parameter set (exact-tonemap), and no policy names one. - Tier: a token of SPEC §3.1, ordered
none<entropy-consistency<decode-equivalence. - Run: one use of a set by a device: a decode (§6.2) or a sink-made picture (§6.3).
- Time: a log date-time is jwp-receipts §7.2's (
YYYY-MM-DDTHH:MM:SSZ), and two of them compare as strings; a date-time is jwp-receipts §2.4.3's. A date-time is compared with another, or with a log date-time, by the instant it names, as jwp-receipts §7.4 compares two: brought to UTC by its offset, then by its second as written, then by its fraction. A span or a period runs from its first instant (included) to its last (excluded).
3. Records
The records of this extension are JSON objects under the encodings exact-upscale §2 uses: byte
strings in lowercase hexadecimal, unsigned integers of at most 2^53 − 1 in plain decimal, no
other number, no boolean, terms and date-times as jwp-receipts §2.4.3 defines them, no member
named twice, at most 32 levels of nesting, exactly the members a section lists at every level,
and a kind naming the record. One that does not read so is record_malformed.
Every record carries signer_pubkey (32 bytes), issued_at (a date-time, when its signer
signed it) and sig (64 bytes):
sig = Ed25519(signer_key, "wai:sink-models\x01" || JCS(record without "sig"))
link_hash = BLAKE3("wai:sink-models-link\x01" || JCS(record))
JCS is RFC 8785, over the values these records carry as jwp-receipts §2.4.3 reduces it. The
signature is verified strictly (SPEC §7 Signatures): a key that fails step 1 or 2
is bad_key, and a signature that fails a later step bad_signature. A record is named by its
link hash.
A name is 1 to 64 bytes of a–z, 0–9, -, _ and .. An origin is an origin of
jwp-receipts §7.1: https://, a host and, where one other than 443 is written, : and a port.
4. The model policy
4.1 Layout
A model policy, kind "wai-model-policy", is signed by the operator key:
| member | type | meaning |
|---|---|---|
kind |
string | "wai-model-policy" |
seq |
integer | 0 for the operator's first policy; one more than the policy it supersedes |
supersedes |
32 B hex or null |
the link hash of the policy it replaces; null exactly when seq is 0 |
not_before, not_after |
log date-time | its span |
key_log |
string or null |
the origin whose key log revokes sets for this fleet (§4.4), or null for none |
classes |
array | the classes (below) |
issued_at |
date-time | when the operator signed it |
signer_pubkey |
32 B hex | the operator key |
signer_id |
string | 1 to 2048 bytes: the operator key's signer_id (jwp-receipts §7.1) |
sig |
64 B hex | §3 |
A class:
| member | type | meaning |
|---|---|---|
name |
string | its name (§3) |
devices |
array of 32 B hex | the device keys the policy enrols in it |
attesters |
array of 32 B hex | the attestation keys whose devices are in it (§5) |
sets |
array | the sets its devices may run, each an entry (below) |
An entry:
| member | type | meaning |
|---|---|---|
sha256 |
32 B hex | the set's digest (§2) |
capability |
term | for decode, the capability the set is decoded through; for every other role, wai.media.upscale, the record whose presentation statement states the run (exact-upscale §6.2) |
role |
string | decode, upscale, enhance or generate |
tier |
string | the least tier a run of the set holds (§6.2, §6.3) |
4.2 Rules
A policy reads when it has the members and types of §4.1 at every level, its times are log
date-times and each entry's capability is a term; otherwise it is record_malformed. A policy
that reads and whose signature verifies is refused policy_invalid when it breaks any of these:
supersedesisnullexactly whenseqis 0;not_beforeis beforenot_after;key_logisnullor an origin (§3);classesholds 1 to 256 classes, in strictly ascending order ofname, eachnamea name (§3);- in each class:
devicesholds at most 4096 keys andattestersat most 16, each list in strictly ascending order and at least one of them not empty;setsholds 1 to 1024 entries, in strictly ascending order of (sha256,capability,role), compared as byte strings; - in each entry:
roleis one of the four of §2 andtiera tier token; forupscale,enhanceandgenerate,capabilityiswai.media.upscale; and forenhanceandgenerate,tierisnone, since a picture no verifier recomputes holds no tier (§6.3).
A device may be in several classes, and a set in several entries.
4.3 The successor
A policy is replaced by its successor: a policy of the same operator key whose supersedes
is its link hash, whose seq is one more than its own, and whose not_before is not before its
own. A policy is in force from its not_before until the earlier of its not_after and its
successor's not_before, where a verifier holds its successor. So a successor that begins
before its predecessor's span ends takes its place from then, and a gap between a policy's
not_after and its successor's not_before is a time when neither is in force.
A successor states its classes whole: a set that it does not list is not permitted from its
not_before, whatever its predecessor listed.
4.4 Revocation
A policy that names a key_log takes its revocations from that origin's key log (jwp-receipts
§7.2): a set is revoked from the issued_at of the first revision of the log whose
revoked_modules lists its digest, and stays revoked, since every later revision lists it (rule
6 there). This is the list SPEC §3.1 check 5 reads at the sink, under the same digest, so a set
the operator revokes is refused at every sink of the fleet that holds the log, and a report of a
run after the revocation is refused here (§6.2, §6.3). A verifier reads the log as jwp-receipts
§7.3 checks a log before anchoring it, for the policy's origin, as a log its relying party pins.
A policy that names no key log revokes nothing: its successor drops a set instead (§4.3).
5. The device attestation
A device attestation, kind "wai-model-device", is signed by an attestation key and
places a device in each class that names the key in attesters:
| member | type | meaning |
|---|---|---|
kind |
string | "wai-model-device" |
device |
32 B hex | the device key |
not_before, not_after |
log date-time | the span it holds |
issued_at |
date-time | when its signer signed it |
signer_pubkey |
32 B hex | the attestation key |
sig |
64 B hex | §3 |
One whose not_before is not before its not_after, or whose device is its signer_pubkey,
is record_malformed.
6. The run report
6.1 Layout
A run report, kind "wai-model-run", is signed by a device key for a period:
| member | type | meaning |
|---|---|---|
kind |
string | "wai-model-run" |
policy |
32 B hex | the link hash of the policy the device ran under |
class |
string | the name (§3) of the class it ran as |
attestation |
32 B hex or null |
the link hash of the device attestation that places it in the class; null when the class enrols its key |
from, to |
log date-time | the period, from before to |
decodes |
array | at most 65 536 decode entries (§6.2), in order of at, each at not before the one before it |
presentations |
array of 32 B hex | at most 4096 link hashes of presentation statements its sessions signed (§6.3), in strictly ascending order |
issued_at |
date-time | when it signed it |
signer_pubkey |
32 B hex | the device key |
sig |
64 B hex | §3 |
A report that breaks a rule of this section is record_malformed. A report with no decode and no
presentation states that the device ran no set in the period.
6.2 Decodes
A decode entry:
| member | type | meaning |
|---|---|---|
at |
log date-time | when the decode ran, on the device's clock |
set |
object | {"sha256", "inner"}: the digest of the set the decode read, as its pin named it, or as a pin over the bytes it read would name them where it was unpinned (SPEC §3.1, Pin by default, item 4); and, for a sealed set, its inner digest, null otherwise |
dispatch |
object | the report the sink gave for the decode (neural-dispatch §5), as it gave it |
The dispatch member reads as neural-dispatch §5 states its report: exactly the members kind
("wai-neural-dispatch/1"), capability (a term), needed (a tier token), ran and refused
(an array of at most 16 paths). A path has exactly unit (npu, gpu or cpu), backend
(model-runtime, webnn, onnx-runtime, wai-ops or wgsl) and arithmetic; the path in
ran adds tier (a tier token) and placement (null, or exactly npu, gpu, cpu and
unknown, each an integer); a refused path adds reason, a code of neural-dispatch §7. A path's
arithmetic is its backend's (neural-dispatch §1: float for model-runtime, webnn and
onnx-runtime, integer for wai-ops and wgsl), and a path in integer names no npu
(neural-dispatch §3). In a run report, ran is a path: a decode that no path ran ran no set,
and is not a run. A decode entry that breaks a rule of this paragraph is record_malformed.
A decode's capability is its dispatch's capability, its unit the unit of ran, and
its tier the tier of ran. A verifier checks each decode entry of a report, in order, and
the first check that fails is the reason:
atis in the report's period (outside_period).- Its path's tier is the one neural-dispatch §3 lets it hold: a path in
floatruns no decode whoseneededisdecode-equivalence, and holds no tier ofdecode-equivalence(dispatch_tier_refused). A neural processor's run claimed atdecode-equivalenceis refused here, whatever the device says of it. - The device's class has an entry whose
sha256is the set'ssha256, whosecapabilityis the decode's and whoseroleisdecode(model_not_in_policy). - The decode's tier is not below that entry's
tier(model_tier_below_policy). - Where the policy names a key log: neither the set's
sha256nor itsinneris revoked from an instant at or beforeat(model_revoked). A sealed set has two identities, and SPEC §3.1 check 5 runs over both; so does this check.
6.3 Pictures a sink made
Each link hash in presentations names a presentation statement (exact-upscale §6.2), signed
under a key of one of the device's sessions. The run report binds the statement to the device;
the statement is not changed. A statement's instant is its issued_at: a sink signs a span's
statement once the span has ended, so every picture it states was made at or before that
instant.
Each picture a statement lists (each entry of its frames) whose made is not transmitted is
a run of the set its made_by names, in the role its category gives: derived runs an upscale set, asserted an
enhance set and synthesized a generate set, each for the capability wai.media.upscale;
its tier is decode-equivalence for derived, whose derivation is integer throughout
(exact-upscale §3), and none for the other two. A verifier checks each statement a report
names, in order, and then each of its pictures, in order; the first check that fails is the
reason:
- The verifier holds the statement (
presentation_unknown). - No earlier report, and no earlier position of this one, names it (
record_duplicate): one statement is counted once. - Its instant is in the report's period (
outside_period). - For each picture whose
madeis nottransmitted: itsmade_byis notnull, and the device's class has an entry whosesha256is itsmade_by, whosecapabilityiswai.media.upscaleand whoseroleis the picture's (model_not_in_policy). Anassertedpicture whose model the statement does not name (exact-upscale §6.2 allowsnull) was made by a model no policy can permit. - Its tier is not below that entry's
tier(model_tier_below_policy). - Where the policy names a key log: its
made_byis not revoked from an instant at or before the statement's instant (model_revoked).
A picture's pixels are its count in its own category: pixels.derived for derived,
pixels.asserted for asserted, pixels.synthesized for synthesized, as the statement
counts them (exact-upscale §6.3).
6.4 The device and its policy
Before its runs, a verifier checks a report's device and policy, in this order:
- The policy it names is one the verifier holds (
policy_unknown). - The policy is in force over the whole period (§4.3): its
not_beforeis not afterfrom(policy_not_yet_valid), andtois not after the end of the time it is in force (policy_expired). A report of a period that runs past a policy'snot_after, or past its successor'snot_before, is refused here. - The device is in the class: the policy has a class of that
name, and eitherattestationisnulland the class'sdevicesholds the report'ssigner_pubkey, orattestationnames a device attestation the verifier holds whosesigner_pubkeyis one of the class'sattesters, whosedeviceis the report'ssigner_pubkeyand whose span holds the period: itsnot_beforenot afterfromandtonot after itsnot_after(device_not_in_class).
Of two reports by one device whose periods share an instant, the later is refused
(record_overlap): a device states each instant of its runs once.
7. The roll-up
7.1 Layout
A roll-up, kind "wai-model-rollup", is signed by the operator key for a period:
| member | type | meaning |
|---|---|---|
kind |
string | "wai-model-rollup" |
policy |
32 B hex | the link hash of the policy every report it rests on names |
from, to |
log date-time | the period, from before to |
reports |
array of 32 B hex | the link hashes of the reports it rests on, at most 65 536, in strictly ascending order |
classes |
array | one class line for each class of the policy, in the policy's order |
issued_at |
date-time | when the operator signed it |
signer_pubkey |
32 B hex | the operator key |
signer_id |
string | as §4.1 |
sig |
64 B hex | §3 |
A class line has exactly class (its name), reports, devices and silent (integers) and
sets (an array of set lines); a set line has exactly sha256, capability, role,
decodes, frames, pixels (integers) and units, which has exactly npu, gpu and cpu
(integers). A roll-up that does not read so is record_malformed.
7.2 The figures
A class line's figures are computed from the reports the roll-up rests on whose class is its
name:
| figure | what it is |
|---|---|
reports |
those reports |
devices |
the distinct device keys that signed them |
silent |
the class's devices (the keys the policy enrols) that signed none of them |
sets |
one set line for each (sha256, capability, role) of a run in those reports, in strictly ascending order of the three |
and a set line's, over those reports' runs of that set, capability and role:
| figure | what it is |
|---|---|
decodes |
its decode entries (§6.2) |
units |
of those, how many ran on each unit |
frames |
its sink-made pictures (§6.3) |
pixels |
the sum of their pixels (§6.3) |
A device attested into a class is never silent: a policy names the attestation keys of such a
class, not its devices, so only a device that reports is known to be in it.
8. The bundle and its verification
8.1 The bundle
A bundle is JSON text (RFC 8259) in which no object names a member twice, no string holds a
surrogate that is not one of a pair, and nothing is nested more than 32 levels deep, the bundle
being the first; whether a number or a boolean it holds is one a record may carry is the
record's question (§3). It is one object with exactly these members: kind, the string
"wai-model-bundle"; policies, an array of 1 to 64 policies, each one the successor of the one
before it; key_log, a key log of jwp-receipts §7.2 (the document, with its kind and
revisions) or null; attestations, an array of device attestations; presentations, an
array of presentation statements; reports, an array of run reports; and rollup, a roll-up or
null; each record an object. A bundle that is not such an object is refused
record_malformed, at ["bundle"]. A file that holds one is named with the suffix
.wai-models.json.
8.2 Steps
A verifier given a bundle runs these steps and stops at the first refusal, which it reports with the reason and where:
- Policies, in order, at
["policy", i]: each reads and its signature verifies (§3:record_malformed,bad_key,bad_signature); it keeps §4.2's rules (policy_invalid); and each but the first is the successor (§4.3) of the one before it (policy_chain_break). - The key log: for each policy, in order, that names a
key_log, the bundle holds a key log (key_log_absent, at["policy", i]), and the log passes jwp-receipts §7.3's checks before anchoring for that origin, at["key_log"], with the reasons of jwp-receipts §7.7 (key_log_malformed,origin_mismatch,key_log_signature_invalid,key_log_chain_break,key_log_root_not_committed,key_log_rewrites_history). - Device attestations, in order, at
["attestation", i]: each reads and its signature verifies (§3, §5); and none has the link hash of one before it (record_duplicate). - Presentation statements, in order, at
["presentation", i]: each reads and its signature verifies as exact-upscale §2 and §6.2 have it (record_malformed,bad_key,bad_signature); and none has the link hash of one before it (record_duplicate). - Run reports, in order, at
["report", i]: each reads and its signature verifies (§3, §6.1); its device and policy (§6.4); its decodes, at["report", i, "decode", j](§6.2); the statements it names, at["report", i, "presentation", j], and their pictures, at["report", i, "presentation", j, "frame", k](§6.3); and it shares no instant with an earlier report of its device (record_overlap). - The roll-up, where the bundle holds one, at
["rollup"]:- it reads and its signature verifies (§3, §7.1);
- its
signer_pubkeyis the policies' (wrong_operator); - its
policyis one the verifier holds (policy_unknown); - its
reportsare exactly the link hashes of the bundle's reports, and each of them names itspolicy(rollup_mismatch): a roll-up rests on exactly the reports its bundle holds; - each report's period lies in its period: the report's
fromnot before itsfrom, and the report'stonot after itsto(outside_period); - its
classesare §7.2's, recomputed (rollup_mismatch).
8.3 Outcome
-
refuse: the reason and where.
-
accept, as a JSON object with these members:
policies: for each policy, in order,link(its link hash),seq,not_before,not_afterandin_force_until, the end of the time it is in force (§4.3);key_log:nullwhere no policy names one; otherwiseorigin,head(the latest revision'srevision_hash) andrevoked, for each digest of the latest revision'srevoked_modules, in its order,sha256andsince, the instant it was revoked from (§4.4);reports: for each report, in order,link,device(its key),class,from,to,decodes(its decode entries) andframes(its sink-made pictures);rollup:nullwhere the bundle holds none; otherwiselinkandclasses, its class lines.
Byte strings are in lowercase hexadecimal, and
refuseis{"reason", "at"},atthe place as §8.2 writes it.
9. The operation
wai model verify <bundle> verifies a bundle (§8) and writes its outcome as JSON, exiting 1 when
it is refused; wai verify reads a bundle under a path as it reads a fleet report bundle
(*.wai-models.json, or a JSON file whose kind is wai-model-bundle), and reads a policy, a
device attestation, a run report or a roll-up alone: it reads, its signature verifies and, for a
policy, it keeps §4.2's rules. A record alone is checked against nothing else, and says nothing
of the policy a report names or of the reports a roll-up rests on.
10. Reasons
The codes this extension adds, each with where it is raised:
| reason | raised at |
|---|---|
policy_invalid |
§4.2, §8.2 step 1 |
policy_chain_break |
§4.3, §8.2 step 1 |
policy_unknown |
§6.4, §8.2 steps 5 and 6 |
policy_not_yet_valid |
§6.4 |
policy_expired |
§4.3, §6.4 |
key_log_absent |
§8.2 step 2 |
device_not_in_class |
§6.4 |
model_not_in_policy |
§6.2, §6.3 |
model_tier_below_policy |
§6.2, §6.3 |
model_revoked |
§4.4, §6.2, §6.3 |
presentation_unknown |
§6.3 |
wrong_operator |
§8.2 step 6 |
rollup_mismatch |
§7.2, §8.2 step 6 |
A verifier of this extension also raises, with the meaning this text gives them:
dispatch_tier_refused (§6.2), which neural-dispatch §7 adds; outside_period (§6.2, §6.3,
§8.2 step 6), record_duplicate (§6.3, §8.2 steps 3 and 4) and record_overlap (§6.4), which
receipt-ledger §10 adds; the key-log reasons of §8.2 step 2, which jwp-receipts §7.7 adds;
record_malformed, bad_key and bad_signature, for what does not read and for its
signature.
11. Conformance
live-conformance/models/ holds the corpus, in one file,
vectors.json, written by wai_model_policy_vectors gen from fixed seeds: synthetic keys,
digests and instants, dispatch reports written by the reference's own neural_dispatch
functions, and presentation statements signed as exact-upscale §6.2 has them. Each vector is a
bundle with the outcome §8.3 gives it:
- Accepted: a week of a fleet of set-top boxes enrolled by key and signage players vouched for by an attestation key, under a policy whose key log revokes one set, with decodes on a neural processor in floating point, on the CPU's integer interpreter and of DRED's weights; a sink's upscaled, edited and generated pictures; the revoked set run before its revocation; a device that ran nothing; a device enrolled and silent; and the roll-up recomputed. A policy and its successor, with reports under each in its time. A fleet with no key log, and reports with no roll-up.
- Refused: each reason of §10 at least once, each vector a control of one defect: among them
a set outside the policy, a revoked set run after its revocation (by its digest, and by a sealed
set's
inner), a report past its policy's span and one past its successor's start, a neural processor's float run claimed atdecode-equivalence, a roll-up that does not recompute, and a report with its signature changed; and each reason it reuses.
wai_model_policy_vectors verify and the test tests/model_policy.rs check that the file
regenerates byte for byte, that wai-rs gives every vector its outcome, that every reason of
§10 refuses a vector, and that §10 lists exactly the reference's codes.
live-conformance/model_policy_verify.py is the second implementation, written from this text:
it shares no code with wai-rs; it verifies signatures with WAI's strict rule written from RFC
8032 (claim-conformance/_ed25519.py) and link hashes with BLAKE3 written from its
specification (claim-conformance/_blake3.py), reads presentation statements with the
exact-upscale corpus's second implementation (upscale_verify.py), reads the key log from
jwp-receipts §7.2 itself, gives every vector the same outcome, reason and place, requires every
mutated copy of the corpus to fail, and drops each of its own checks in turn and requires the
corpus to catch the weakened verifier.
12. Security and privacy considerations
- What a report rests on. A run report is the device's statement of what it ran. A device that runs a set and leaves the run out of its report is not caught by this verification: a policy says what may run, and the sink's own refusals (SPEC §3.1 check 5, jwp-receipts §7.9) are what stop a revoked set at a sink that follows them. A report is checked against the policy, the key log and the statements the verifier holds, and a verifier that holds a device's dispatch reports or statements from elsewhere (its own sessions, a player's log) checks them against the report's.
- Clocks.
atis the device's clock, and a statement'sissued_atits session's. A device whose clock runs slow can place a run before a revocation that preceded it. A revocation takes effect at a sink when the sink holds the revision that lists it (jwp-receipts §7.9, Kill latency); a fleet that needs a revocation to bind reports from an instant publishes the revision before that instant. - Floating point. A path in floating point holds no tier above its capability's, on a neural
processor or anywhere else (neural-dispatch §3). A policy that requires
decode-equivalencefor a set is therefore met only by an integer path, and a report that claims it for a float path is refused, not believed. - Keys. The operator key enrols devices and signs roll-ups; one who holds it can enrol any device and permit any set, so it is kept as fleet §12 keeps an organisation key. An attestation key vouches for every device it signs for, in every class that names it; a class that names a maker's key admits every device that maker vouches for. A device key signs its reports and no one else's.
- What a report reveals. A presentation statement is signed under a session's key and names no device (exact-upscale §10). A run report binds the statements it names to a device key, and a set's digest can name a title (prior-carriage §18.3): a run report shows which titles a device presented. It travels to the operator, and from it to those the operator shows its devices' records to. A roll-up names classes, sets and counts, and no device.