From 40796bb37b79e0cf87fc5be71da191dad8a4bc73 Mon Sep 17 00:00:00 2001 From: Transaction Science Date: Tue, 6 Oct 2026 08:55:52 -0400 Subject: [PATCH 01/27] wai: the reconstruct-session claim class, its authorities and its figure profile (text) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit jwp-receipts §2.4.12 registers reconstruct-session, the next free number after W1-5's stage (§2.4.10) and delivery-gap (§2.4.11): a sink's statement of one session — decoders and host, paths and switches, late presentations, the output tree, counted and transferred bytes, the classical rendition it did not need, the stage claims it signed, and its decode energy where metered. The session names its sets' stage claims rather than restating their objects and units; step 6 checks it against its outputs, objects, entry envelopes and those stage claims. §3.1 gains seventeen reasons, §5.11 the corpus, §7.5 the authority and the energy figure as a second item. energy-measurement §6.1 widens the claim-link profile; delivery-telemetry's claim member now names a registered class; staged-measurement §8.6-§8.7 and Appendix C say how a tool checks the rail and seals a session's figure. Co-Authored-By: Claude Opus 5.5 --- wai/extensions/delivery-telemetry.md | 2 +- wai/extensions/energy-measurement.md | 2 +- wai/extensions/jwp-receipts.md | 285 +++++++++++++++++++++++++-- wai/extensions/staged-measurement.md | 17 +- 4 files changed, 289 insertions(+), 17 deletions(-) diff --git a/wai/extensions/delivery-telemetry.md b/wai/extensions/delivery-telemetry.md index 1e1d1b29b..36f65d90d 100644 --- a/wai/extensions/delivery-telemetry.md +++ b/wai/extensions/delivery-telemetry.md @@ -46,7 +46,7 @@ every observation can be reported. A string a report carries is printable ASCII. | `capable` | object or `null` | for `capable`: `{ outcome, reason, classical_floor }` (§2.3) | | `cohort` | string or `null` | `control` or `wai`: the arm the content's service assigned the session to | | `metrics` | object or `null` | `{ msd_ms, bsa, bsda_ms, dfa }`: media start delay, buffer starvations and their total duration since the session began, and dropped frames since the session began | -| `claim` | 64 hexadecimal digits or `null` | on `end` only: the link hash of the session's `reconstruct-session` claim, where the sink sealed one | +| `claim` | 64 hexadecimal digits or `null` | on `end` only: the link hash of the session's `reconstruct-session` claim ([jwp-receipts](jwp-receipts.md) §2.4.12), where the sink sealed one | §2.2 **The object** has exactly the members `ot`, `url`, `content_hash`, `capability`, `rendition`, `layer`, `layers_total`, `layer_cap`, `counted`, `transferred`, `d_ms`, diff --git a/wai/extensions/energy-measurement.md b/wai/extensions/energy-measurement.md index f3cbeeed3..b9ceccf1b 100644 --- a/wai/extensions/energy-measurement.md +++ b/wai/extensions/energy-measurement.md @@ -939,7 +939,7 @@ where the figure's class is, and which key signed it. | figure profile | receipt | `subject_type` and identity | figure; its class | index | signed by | |---|---|---|---|---|---| | `moq-jwp:object` | JWP object receipt (jwp-receipts §2.4.2), accepted under its group (§3) | `object`: its §2.1 content hash; the claim's `group` is the group receipt's link hash | `joules_micro`; the label in its leaf (jwp-receipts §2.2) | its leaf index | the group receipt's `signer_pubkey` | -| `moq-jwp:claim-link` | `energy` claim (jwp-receipts §2.4.5) | `receipt`: its `link_hash` | `joules_micro`; its class | `null` | its `signer_pubkey` | +| `moq-jwp:claim-link` | `energy` claim (jwp-receipts §2.4.5), or `reconstruct-session` claim whose `energy` is not `null` (§2.4.12) | `receipt`: its `link_hash` | `joules_micro`; its class (for a session, `energy.joules_micro` and the class `energy` writes) | `null` | its `signer_pubkey` | | `wai:energy-binding-id` | energy binding ([energy-binding](energy-binding.md) §2) | `receipt`: `BLAKE3("wai:energy-binding-id\x01" ‖ JCS(body))` (energy-binding §4) | `microjoules`; `acquisition` | `null` | no Ed25519 key | | `wai:video-receipt-id`, `wai:video-manifest-receipt-id`, `wai:video-ssai-receipt-id`, `wai:video-keys-receipt-id`, `wai:video-package-receipt-id`, `wai:video-channel-receipt-id` | the `wai.video.int_motion` receipt and the `wai.video.*` OTT receipts | `receipt`: its receipt hash | `joules_micro`; its class | `null` | its `signer_pubkey` | | `wai:world-receipt-id`, `wai:film-receipt-id`, `wai:haptic-receipt-id`, `wai:score-receipt-id`, `wai:splat4d-receipt-id`, `wai:audio-receipt-id`, `wai:ternary-receipt-id` | the world-session, film and reel, haptic, score, 4D-splat, audio-scene and ternary-reconstruction receipts | `receipt`: its receipt hash, over the payload in the form it was signed (§2.8) | `joules_micro`; its optional label | `null` | its `signer_pubkey` | diff --git a/wai/extensions/jwp-receipts.md b/wai/extensions/jwp-receipts.md index dee2fe269..95ff1118b 100644 --- a/wai/extensions/jwp-receipts.md +++ b/wai/extensions/jwp-receipts.md @@ -36,14 +36,21 @@ In scope: class. `group` and `object` receipts are the **delivery** class; a `claim` receipt (§2.4.3) carries one of the others — `energy`, `lawful-basis`, `log-inclusion`, `measurement`, `operating-point`, - `stage`, `delivery-gap` (§2.4.5–§2.4.11) — on one envelope, one canonical - form and one signature rule, so a statement other than delivery does not - need a field set of its own. + `stage`, `delivery-gap`, `reconstruct-session` (§2.4.5–§2.4.12) — on one + envelope, one canonical form and one signature rule, so a statement other + than delivery does not need a field set of its own. - **Objects not delivered** (§3, §4.4): an object a subscriber did not receive is accounted for by its receipt, checked without the object's bytes and reported as `inclusion-verified`, never as delivered; a relay forwards the receipts of the objects it does not forward, and may say why in a `delivery-gap` claim (§2.4.11). +- **What a sink reconstructed** (§2.4.12): a `reconstruct-session` claim + records one session of a sink — its decoders and host, its paths and + switches, its late presentations, a commitment to every output it + presented, the bytes it counted and received, the classical rendition it + did not need, the `stage` claims it signed about the stage sets it + observed, and its decode energy where metered — checkable against the + outputs, the objects, the envelopes and those `stage` claims. - An optional acquisition-class label on the object receipt, bound with the object's figure and origin into its Merkle leaf (§2.2, §2.4.2); an optional class for the group total, signed under a labelled group payload @@ -315,7 +322,7 @@ is present and `null`, so one claim has one canonical form. | `subject` | 32 B hex | For `object`: the §2.1 content hash of the object the claim is about. For `receipt`: the link hash of a receipt — §3 step 3's for a group receipt, `link_hash` below for a claim — or, for a class that names a figure profile (§2.4.8–§2.4.9), the identity that profile defines ([energy-measurement](energy-measurement.md) §6.1). | | `seq` | integer | Strictly increasing across the claims of one `signer_pubkey`. | | `issued_at` | string | A date-time (below) at which the signer issued the claim. Self-asserted, like `group_end`. | -| `body` | object | Class-scoped; its members are fixed by `class` and by nothing else (§2.4.5–§2.4.9, §2.6). | +| `body` | object | Class-scoped; its members are fixed by `class` and by nothing else (§2.4.5–§2.4.12, §2.6). | | `signer_pubkey` | 32 B hex | Ed25519 verifying key per RFC 8032. | | `signer_id` | string | Bound identity string, as for a group receipt (§2.4.1, §7.1). | | `parent_receipt_hash` | 32 B hex or `null` | `link_hash` of this signer's previous claim; `null` for its first. | @@ -386,6 +393,7 @@ key. | `operating-point` | `claim` | `object` or `receipt`, as its figure profile fixes | §2.4.9 | the party that records the request, the commitment and the delivery | | `stage` | `claim` | `object` (the stage set's base) | §2.4.10 | the party that observed the stage set | | `delivery-gap` | `claim` | `object` (the object not forwarded) | §2.4.11 | the relay that did not forward it | +| `reconstruct-session` | `claim` | `object` (the session's entry object) | §2.4.12 | the sink that reconstructed: the key its decoder host holds | Rules: @@ -915,6 +923,183 @@ stops at step 5: it establishes that the relay says it did not forward an object this content hash, not that the publisher sent one. An accepted claim says nothing about whether the object reached anyone by another path. +#### 2.4.12. `class: "reconstruct-session"` + +A sink that reconstructed a title **MAY** record what it did in a `reconstruct-session` +claim: the decoders it used, against which parameter sets and on which host; which path +each unit took and why it switched; the presentations it made after their deadline; a +commitment to every output it presented; the bytes it counted and received; the declared +length of the classical rendition it did not need; the `stage` claims it signed about the +stage sets it observed; and, where its decode was metered, the decode's energy. Its +subject is the §2.1 content hash of the session's **entry object**: the first envelope +the session dispatched. It is signed by the sink, with the key its decoder host holds. It +asserts what that key reports and nothing more, and it is not evidence that a person +watched. + +A session claim and a `stage` claim (§2.4.10) are about different things, and neither +repeats the other. A `stage` claim is about one stage set: each layer object with its +status and the evidence of its receipt, the units presented at each stage on time, the +conflicts and deadline misses, the delivered stage and the set's envelope bytes. A session +claim is about a title, which can hold several stage sets and envelopes that are no part of +one. It names the `stage` claims its sink signed about the title's sets (`stage_sets`), and +commits to every output it presented across the title, late ones included +(`output_root`). A unit's highest stage is read from the outputs, and a set's layer objects +from its `stage` claim. Step 6 checks the two against each other. + +| member | type | meaning | +|---|---|---| +| `session_nonce` | 32 B hex | Fresh random bytes per session, derived from nothing that identifies a person, a device or an account. | +| `media` | string | The entry object's manifest `media` (SPEC §3), as written: 1 to 32 of `a`–`z`, `0`–`9` and `-`. | +| `host` | object | The decoder host (below). | +| `decoders` | array | The decoder entries (below), in **first-use order**: taking the presentations in order of (`layers`, `unit`), each entry is first named after the entry before it. | +| `units` | integer | The units presented at least once. | +| `leaf_count` | integer | The presentations: one per (unit, layers) presented. | +| `output_root` | 32 B hex or `null` | The root of the output tree over the presentations ([staged-measurement](staged-measurement.md) Appendix C), each leaf's `decoder` an index into `decoders`. `null` exactly when `leaf_count` is 0. | +| `primary_units` | integer | The units whose presentation at their largest `layers` came through a decoder entry whose `path` is `primary`. | +| `fallback_units` | integer | The same, for `fallback`. | +| `switches` | array | At most 1024 path switches, each `{ "unit": integer, "from": string, "to": string, "reason": string }`, in order of `unit`: `from` and `to` are `primary` or `fallback`, and `reason` is a term of [delivery-telemetry](delivery-telemetry.md) §5. | +| `switches_total` | integer | Every switch, including any not written. | +| `deadline_us` | integer or `null` | The time, in microseconds, within which the sink's schedule had each unit presented; `null` where it ran under none. | +| `missed` | integer | The presentations made after their unit's deadline. | +| `missed_units` | array | At most 256 of them, each `{ "unit": integer, "layers": integer, "late_us": integer }`: which presentation, and how many microseconds late; in order of (`unit`, `layers`). | +| `stage_sets` | array | For each stage set the sink signed a `stage` claim about, `{ "first_unit": integer, "claim": 32 B hex }`: the title's unit that is the set's unit 0, and that claim's `link_hash`; in order of (`first_unit`, `claim`). | +| `framing` | string | The framing label of the counted members ([staged-measurement](staged-measurement.md) §3, its §3.3): `registered`. | +| `counted_primary` | integer | The counted bytes (staged-measurement §3) of the countable objects received for the `primary` path. | +| `counted_fallback` | integer | The same, for `fallback`. | +| `counted_discarded` | integer | The counted bytes of the countable objects received and never presented. They are in the two members above as well. | +| `uncounted` | integer | The objects received that are not countable (staged-measurement §3.2). Their bytes are in no counted member. | +| `transferred` | integer | Bytes of WAI objects as received, whole or as byte ranges, without transport or receipts. | +| `receipt_bytes` | integer | Bytes of receipts and claims received (staged-measurement §3.5). | +| `classical_declared` | integer or `null` | The sum, over the entry envelopes that carry a classical rendition the sink did not decode, of that rendition's length as its `WAI2` rendition table declares it (SPEC §7.1). Never estimated. | +| `classical_source` | term or `null` | Where `classical_declared` comes from: `wai2-table`, or a term a later extension registers here. | +| `energy` | object or `null` | `null` when the decode was unmetered. Otherwise `{ "joules_micro", "energy_provenance", "energy_uncertainty", "energy_counter_filtering", "energy_calibration_ref" }`, each written as §2.4.5 writes it (below). | + +The **host** is `{ "profile": string, "target": term or null, "build": object, "threads": +integer }`. `profile` is `native-ffi` (a native process), `browser-baseline` (a browser +decoding on its processor), `browser-gpu` (a browser decoding on its graphics processor) +or `edge-wasi` (a WebAssembly host outside a browser), until an extension of sink +profiles registers the set; `target` the platform the host ran on; `build` the build of +its decoders, as §2.4.8 writes a build; and `threads` its decode workers, written as the +largest power of two not above their number, so that it does not single out a machine. + +A **decoder entry**: + +| member | type | meaning | +|---|---|---| +| `capability` | term | The capability decoded. | +| `rendition` | integer or `null` | Its `WAI2` rendition index (SPEC §7.1); `null` for a `WAI1` envelope. | +| `path` | string | `primary` or `fallback`. | +| `decoder` | string | `builtin:@` — `` 1 to 64 of `a`–`z`, `0`–`9`, `_` and `-`, `` 1 to 64 of ASCII letters, digits, `.`, `+` and `-`, beginning with a digit — or `module:sha256:` followed by a module's digest (§7.9), 64 lowercase hexadecimal digits. | +| `variant` | term or `null` | A decode path within the decoder, where it has more than one, such as an exact and a floating-point path. | +| `pin` | 32 B hex or `null` | The `sha256` of the parameter-set pin the sink verified (SPEC §3.1). | +| `tier` | string or `null` | That pin's declared tier as SPEC §3.1 reads it: `decode-equivalence`, `entropy-consistency` or `none`. `null` exactly when `pin` is. | +| `module_status` | string or `null` | For a `module:` decoder, the anchor its grant was confirmed under (§7.9): `pinned` or `fetched`. `null` for a `builtin:` decoder. | +| `leaves` | integer | The presentations decoded through the entry. | + +`energy` is the decode energy of one completion of the presentations the claim commits +to — the decodes behind its `leaf_count` leaves, the work unit +[staged-measurement](staged-measurement.md) §8 names (its §8.1) — on the host's +processor rails (its §8.4), with its acquisition class. It is the figure of profile +`moq-jwp:claim-link` ([energy-measurement](energy-measurement.md) §6.1), named by this +claim's `link_hash`, and its producer publishes its report in a `measurement` claim +(§2.4.8) signed with the same key (energy-measurement §6). A decode that was not metered +has `energy` `null`, never a figure of 0 (energy-measurement §2). + +§3.1 step 2 reads the members in the table's order, and the members of the host, of +each decoder entry, switch, `missed_units` entry and `stage_sets` entry, and of `energy` +and its `energy_uncertainty`, as it reaches them; it checks their types, and +`host.profile`, `host.build.profile`, `path`, `from`, `to` and `framing` against the +values the tables give them. + +Rules, checked at §3.1 step 4 in this order: +1. `primary_units` and `fallback_units` **MUST** sum to `units` (`session_path_sum`). +2. The entries' `leaves` **MUST** sum to `leaf_count`; `leaf_count` **MUST NOT** be below + `units`; and `units` is 0 exactly when `leaf_count` is (`session_leaf_sum`). +3. `output_root` **MUST** be `null` exactly when `leaf_count` is 0 + (`session_root_presence`). +4. `threads` **MUST** be a power of two (`session_host_malformed`). +5. Each decoder entry **MUST** be as its table says: `decoder` of its grammar; + `rendition` at most 65535; `tier` `null` exactly when `pin` is, and otherwise one of + its three values; `module_status` `null` exactly for a `builtin:` decoder, and + otherwise `pinned` or `fetched`; `leaves` at least 1. No two entries **MAY** be equal + in every member but `leaves` (`session_decoder_malformed`). +6. A `tier` that is not `null` **MUST NOT** exceed the class tier of its entry's + `capability` (SPEC §3.1 *Tier*) (`session_tier_exceeds_class`). +7. Each switch's `from` **MUST** differ from its `to`, and its `reason` **MUST** be a + term of delivery-telemetry §5. The switches **MUST** be in non-decreasing order of + `unit`, at most 1024 of them, and no more than `switches_total` + (`session_switch_invalid`). +8. `missed` **MUST NOT** exceed `leaf_count`, and **MUST** be 0 when `deadline_us` is + `null`. `missed_units` **MUST** hold at most 256 entries and no more than `missed`, in + strictly increasing order of (`unit`, `layers`), each with `layers` from 1 to 65535 + and `late_us` at least 1 (`session_missed_invalid`). +9. `stage_sets` **MUST** be in strictly increasing order of (`first_unit`, `claim`) + (`session_stage_sets_invalid`). +10. `counted_discarded` **MUST NOT** exceed the sum of `counted_primary` and + `counted_fallback` (`session_counted_invalid`). +11. `classical_source` **MUST** be `null` exactly when `classical_declared` is, and + otherwise `wai2-table` (`session_classical_invalid`). +12. Where `energy` is not `null`, its `joules_micro` **MUST NOT** be 0 + (`energy_zero_figure`), and its class is admitted as §2.4.5's rule 2 admits one + (`energy_unknown_acquisition`, `energy_legacy_acquisition`, + `energy_acquisition_evidence`). + +**Against the outputs** (§3.1 step 6). The context is the list of presentations, each +`{ "unit", "layers", "decoder", "out_digest" }`: a unit, the layers it was presented +at, the index of the decoder entry that produced it, and the SHA-256 of its output +(staged-measurement Appendix C). In order: +1. The list has `leaf_count` entries and no (`unit`, `layers`) twice, and the root of its + output tree is `output_root` (`session_output_mismatch`). +2. It agrees with the members it gives (`session_output_inconsistent`): every `decoder` + names an entry and every `layers` is at least 1; its distinct units number `units`; + each entry's `leaves` is the number of presentations naming it; the entries are in + first-use order; `primary_units` and `fallback_units` count the units whose + presentation at their largest `layers` names an entry on that path; and every + `missed_units` entry names a presentation of the list. +3. A verifier that holds the objects **MAY** decode a presentation again where its + entry's `capability` has the replicate class `neural-int-exact` or `standard-defined` + (SPEC §7), and then **MUST** find its `out_digest` + (`session_output_irreproducible`). Every other presentation is checked for + membership only. + +**Against the objects** (§3.1 step 6). The context lists each object received: +`{ "content_hash", "path", "counted", "transferred", "presented" }`, with `counted` the +object's counted bytes, or `null` for one that is not countable. `counted_primary` and +`counted_fallback` are the sums of `counted` over the objects of each path, +`counted_discarded` its sum over the objects not presented, `uncounted` the number of +objects whose `counted` is `null`, and `transferred` the sum of `transferred` +(`session_counted_mismatch`). + +**Against the entry envelopes** (§3.1 step 6). The context lists each entry envelope that +carries a classical rendition, `{ "envelope", "rendition" }`: its bytes and that +rendition's index. Each envelope is a `WAI2` envelope (SPEC §7.1) whose entry at +`rendition` is selectable — not a companion or a refinement, and a capability a sink may +dispatch; that capability's replicate class is `standard-defined`, `standard-tolerance` or +`standard-unclassified`, and it is the capability of no decoder entry; and the lengths +the envelopes' rendition tables give those renditions sum to `classical_declared`, which +is `null` exactly when the list is empty (`session_classical_mismatch`). + +**Against the stage claims** (§3.1 step 6). The context is the wire form of each `stage` +claim the verifier holds of those `stage_sets` names. In order, for each: +1. it passes §3.1 steps 1–4 (`context_invalid`); +2. it is a `stage` claim, signed by this claim's `signer_pubkey`, and its `link_hash` is + the `claim` of an entry of `stage_sets` (`context_mismatch`); +3. where the verifier holds the outputs as well: with `f` that entry's `first_unit` and + `n` the units the `stage` claim counts, every unit from `f` to `f + n − 1` is presented, + and, for every stage `s` from 1 up, the units among them presented at more than `s` + layers are no fewer than the units the `stage` claim counts at stage `s` or above + (`session_stage_disagrees`). A unit presented on time at a stage was presented at + every lower stage before it, and late presentations are leaves of the tree as well, so + the tree can hold more than a `stage` claim counts and never less. + +An accepted claim establishes that its signer reported this session. Its outputs are +committed to by the tree, and are reproducible where its decoders are byte-exact; its +byte totals are checkable against the objects, its classical length against the +envelopes, and its stage sets against their `stage` claims. Its timings, missed deadlines, +switches and energy are its signer's statements (energy-measurement §5). The `claim` an +`end` observation carries ([delivery-telemetry](delivery-telemetry.md) §2, its §2.1) +is this claim's `link_hash`. + ### 2.5. Worked example Manifest JSON (group receipt, formatted for readability — wire form @@ -1379,7 +1564,8 @@ order listed. is not 64 of them; a value outside an enumeration this extension defines here (`record`, `binding_type`, a bracket's `opening`, a build's `profile`, a stage's `tier`, a stage object's `status` and `evidence`, a - gap's `reason`); a date-time that is not one of §2.4.3 (a gap's + gap's `reason`, a session's `framing`, its host's `profile`, and the paths + of its decoder entries and switches); a date-time that is not one of §2.4.3 (a gap's `observed_at`); a URI that is not absolute; a term that is not one of §2.4.3 (empty, longer than 2048 bytes, or holding a White_Space or control character); or a malformed @@ -1404,10 +1590,13 @@ order listed. samples, liveness facts that do not show a live rail, a zero window, completion or thread count, or a busy mean not above its idle mean; the figure and least uncertainty a bracket gives; an empty point; and - which points and predictions are present together; and, in a `stage` + which points and predictions are present together; in a `stage` claim, the vocabulary, a point's parameter and range, a reason of staged-delivery's, and how the units, the objects and the delivered stage - agree. + agree; and, in a `reconstruct-session` claim, how its counts agree, a + decoder entry's grammar and tier, the switches' reasons and order, the + missed presentations, the order of its stage sets, its counted bytes and + its classical rendition. 3. **Signature.** Ed25519 (RFC 8032). This step restates RFC 8032's own decoding and range rules, and fixes the two choices on which RFC 8032 verifiers differ — whether a key or `R` of small order is @@ -1431,7 +1620,7 @@ order listed. for a signature made without any private key — under the identity, `R` = [s]B with `S` = s verifies for every message — so such a key is refused before its signature is examined. -4. **Class rules**, per §2.4.5–§2.4.9 and §2.6, each with its own +4. **Class rules**, per §2.4.5–§2.4.12 and §2.6, each with its own reason (below). They run after the signature because a rule about what a signer said only means something once it is established who said it. @@ -1459,7 +1648,10 @@ order listed. publisher key of a verified delivery receipt for the declaration's subject (§2.6.3), and never against the declaration alone; a `delivery-gap` claim against the object receipt at its coordinates, - verified by inclusion at least (§2.4.11). A + verified by inclusion at least (§2.4.11); a `reconstruct-session` claim + against its outputs, the objects it received, its entry envelopes and the + `stage` claims it names, in that order, each that the verifier holds, the + `stage` claims verified under steps 1–4 (§2.4.12). A declaration is verified here under steps 1–4, and one that fails them — or is not JSON — is `context_invalid`: its members, `signer_pubkey` among them, are its signer's only once its signature @@ -1488,7 +1680,7 @@ and never folds it in: confirmation changes the outcome of no step here. | step | reason | raised when | |---|---|---| -| 4 | `energy_zero_figure` | `joules_micro` is 0 in an `energy`, `measurement` or `operating-point` claim | +| 4 | `energy_zero_figure` | `joules_micro` is 0 in an `energy`, `measurement` or `operating-point` claim, or in a `reconstruct-session` claim's `energy` | | 4 | `energy_unknown_acquisition` | `energy_provenance` names no class of energy-measurement §2 | | 4 | `energy_legacy_acquisition` | `energy_provenance` is the legacy `HwShunt` | | 4 | `energy_acquisition_evidence` | the class's evidence is missing, carried by a class that has none, or below the resolution floor (§2.4.5 rule 2) | @@ -1528,6 +1720,17 @@ and never folds it in: confirmation changes the outcome of no step here. | 4 | `stage_objects_malformed` | a reported object out of order, at layer 0 or above 255, over no unit (a `partial` one over fewer than two), outside the units when its span was checked, with a reason where none belongs or none where one does; applied or partial with evidence other than `delivered-verified` beside a stated `op_delivered`; dropped with `delivered-verified` evidence; arrived with no bytes or dropped with some; objects counting no fewer bytes than the set; or two `applied` objects of one layer over one unit | | 4 | `stage_units_unsupported` | an `applied` object of layer *s* outside the spans of layer *s* − 1's `applied` and `partial` objects, or a `partial` one that does not meet them; or more units at stage *s* or above than layer *s* can have reached, a `partial` object counting no more than its span less one | | 4 | `stage_delivered_disagrees` | `op_delivered` is not the stage the reported objects give | +| 4 | `session_path_sum` | a session's `primary_units` and `fallback_units` do not sum to `units` | +| 4 | `session_leaf_sum` | the decoder entries' `leaves` do not sum to `leaf_count`, `leaf_count` is below `units`, or one of `units` and `leaf_count` is 0 and the other is not | +| 4 | `session_root_presence` | `output_root` is `null` with presentations, or a hash with none | +| 4 | `session_host_malformed` | the host's `threads` is not a power of two | +| 4 | `session_decoder_malformed` | a decoder entry's `decoder` is not of its grammar, its `rendition` is above 65535, its `tier` is present without `pin` or absent with it or is not a tier, its `module_status` does not fit its decoder, or its `leaves` is 0; or two entries differ only in `leaves` | +| 4 | `session_tier_exceeds_class` | a decoder entry's `tier` exceeds its capability's class tier | +| 4 | `session_switch_invalid` | a switch between equal paths or for a reason delivery-telemetry §5 does not list, switches out of order, more than 1024 written, or more written than `switches_total` | +| 4 | `session_missed_invalid` | `missed` above `leaf_count`, or not 0 with no deadline; `missed_units` holding more than 256 entries or more than `missed`, out of order, or an entry with `layers` 0 or above 65535 or `late_us` 0 | +| 4 | `session_stage_sets_invalid` | `stage_sets` out of order, or an entry twice | +| 4 | `session_counted_invalid` | `counted_discarded` above `counted_primary` and `counted_fallback` together | +| 4 | `session_classical_invalid` | `classical_source` present without `classical_declared` or absent with it, or not `wai2-table` | | 6 | `energy_disagrees_with_delivery` | the figure differs from the `object` receipt's | | 6 | `energy_class_disagrees_with_delivery` | the object's leaf is labelled, and the `energy` claim's class or evidence differs from the label | | 6 | `figure_disagrees` | the receipt a `measurement` or `operating-point` claim names carries another figure at `figure_index` | @@ -1538,7 +1741,7 @@ and never folds it in: confirmation changes the outcome of no step here. | 6 | `figure_not_held` | a `measurement` claim is checked without the receipt that carries its figure (§2.4.8) | | 6 | `energy_oer_invalid` | the named OER receipt reports any reason under oer-receipts | | 6 | `energy_disagrees_with_oer` | the named OER receipt states another grade or figure | -| 6 | `context_invalid` | a receipt a claim is checked against — a declaration a decision or a recovery record names, or the receipt that carries a figure — does not verify | +| 6 | `context_invalid` | a receipt a claim is checked against — a declaration a decision or a recovery record names, the receipt that carries a figure, or a `stage` claim a session names — does not verify | | 6 | `decision_declaration_mismatch` | a decision does not match the declaration it names | | 6 | `decision_purpose_not_declared` | a decision is about a purpose its declaration does not list | | 6 | `recovery_declaration_mismatch` | a recovery record does not match the declaration it names | @@ -1546,6 +1749,12 @@ and never folds it in: confirmation changes the outcome of no step here. | 6 | `recovery_value_mismatch` | the value does not match under the algorithm's rule | | 6 | `recovery_no_matcher` | the verifier has no matcher for the algorithm | | 6 | `gap_subject_mismatch` | the object receipt at a `delivery-gap` claim's coordinates names another object | +| 6 | `session_output_mismatch` | a session's presentations are not `leaf_count`, repeat a (unit, layers), or give another `output_root` | +| 6 | `session_output_inconsistent` | the presentations name an entry that does not exist or a `layers` of 0, or give another `units`, another entry's `leaves`, another first-use order, other `primary_units` or `fallback_units`, or no presentation for a `missed_units` entry | +| 6 | `session_output_irreproducible` | a presentation decoded again, through a decoder its replicate class makes byte-exact, gives another `out_digest` | +| 6 | `session_counted_mismatch` | the objects received give other counted, uncounted or transferred bytes | +| 6 | `session_classical_mismatch` | an entry envelope's rendition is not a selectable classical rendition the session did not decode, or the envelopes give another `classical_declared` | +| 6 | `session_stage_disagrees` | a `stage` claim the session names counts a unit the session never presented, or more units at a stage than the session presented at it or above | ### 3.2. Recovery through a soft binding, and the ancestor rule @@ -1993,6 +2202,26 @@ The corpus of §5.8 checks the authorities both classes need (§7.5). bodies around every rule and gaps against receipts at and away from their coordinates. +### 5.11. Session claims (`claim-conformance/`) + +The corpus of §5.6 holds the class of §2.4.12: an unmetered session (`energy` `null`) +and a session metered under `OnChipCounter` with its evidence, each accepted against +its outputs, the objects it received, its entry envelopes and the `stage` claims it +names; output trees from 1 to 33 leaves; a presentation whose re-decode, as the vector +states it, gives another digest through a byte-exact decoder +(`session_output_irreproducible`) and through a decoder checked for membership only +(accepted); a `stage` claim that verifies, one that does not, one by another key and one +the session does not name; every reason of §2.4.12's rules and checks; a metered +session's figure of zero (`energy_zero_figure`) and every acquisition-class reason; and +step 2's enumerations and order. `claim_verify.py` gives every outcome. `differential.py` +generates sessions around every rule — units, leaves and paths off by one, switches and +missed presentations at and past their caps, a `null` deadline with misses, presences +that disagree, decoder indices out of range, leaves moved between entries, entries out of +first-use order, stage claims against presentations that reach and miss their stages, +and every acquisition class — with their outputs and objects, and requires the two +verifiers to agree. The corpus of §5.8 checks the authority a session needs, and the +authorities its energy figure needs (§7.5). + --- ## 6. Security considerations @@ -2149,6 +2378,15 @@ authority. A confirmed claim is worth exactly as much as that confirmation; an unconfirmed one, as much as the verifier's own reason to trust the key that signed it. +A `reconstruct-session` claim says what a sink played. It carries no +identifier of a person, a device or an account: its `session_nonce` is fresh +for each session, and its host states a profile, a platform, a build and a +rounded worker count. A sink key used for many sessions links them, so a sink +that does not mean its sessions to be linked signs each with a key of its own, +under a `did:key` (§7.1). Where its claim goes is the sink's choice; delivery +telemetry carries only its `link_hash` +([delivery-telemetry](delivery-telemetry.md) §2, §8). + ### 6.8. Soft binding - **A copied watermark.** A watermark decoded from an object shows @@ -2439,7 +2677,8 @@ confirmation later keeps those revisions and its anchor record. A verifier confirms only an item it has accepted: a `group` receipt that passed §3 steps 1–2, whose `object` receipts share its confirmation; a -`claim` accepted under §3.1; a receipt of another WAI family whose signed +`claim` accepted under §3.1, and the energy figure of an accepted +`reconstruct-session` claim, which is an item of its own (§7.5); a receipt of another WAI family whose signed bytes include its `signer_pubkey` and `signer_id` and whose own verification passed; or a module grant whose signature verified (§7.9). Its inputs are the item's `signer_pubkey`, `signer_id`, the authorities @@ -2536,7 +2775,8 @@ A confirmation needs every one of them: | item | authorities | |---|---| | a `group` receipt, and the `object` receipts under it | `delivery`; and `energy/` for each acquisition class an `object` receipt under it labels, where its leaf binds a label (§2.2), and for the class a labelled group payload signs for the group's total (§2.3) | -| a `claim` | its class's authority: `energy/` followed by its `energy_provenance` for `energy`, for example `energy/OnChipCounter`; `lawful-basis/declaration` or `lawful-basis/decision` by its `record`; its class name for every other class — `log-inclusion`, `soft-binding`, `binding-recovery`, `measurement`, `operating-point`, `stage` and `delivery-gap`. And `energy/` followed by its `energy_provenance` whenever its body carries that member, whatever its class | +| a `claim` | its class's authority: `energy/` followed by its `energy_provenance` for `energy`, for example `energy/OnChipCounter`; `lawful-basis/declaration` or `lawful-basis/decision` by its `record`; its class name for every other class — `log-inclusion`, `soft-binding`, `binding-recovery`, `measurement`, `operating-point`, `stage`, `delivery-gap` and `reconstruct-session`. And `energy/` followed by its `energy_provenance` whenever its body carries that member, whatever its class | +| the energy figure of a `reconstruct-session` claim whose `energy` is not `null` | `reconstruct-session`, and `energy/` followed by `energy.energy_provenance` | | a receipt of another WAI family that signs its own `signer_pubkey` and `signer_id` | `receipt`; and `energy/` for each class its figures carry a label for | | a module grant (§7.9) | `module/decoder` or `module/reconstruct`, by its `form` | @@ -2563,7 +2803,11 @@ has confirmed, with the authority `delivery`, the group receipt that carries a claim's subject (for a claim whose `subject_type` is `object`), or under which it has confirmed the receipt a claim's subject names (`subject_type` `receipt`). It reports which. §7.9 expects one of the -sink's module origins. +sink's module origins. A `reconstruct-session` claim is a sink's statement +about an object a publisher delivered, so its subject's origin is not the +sink's: a verifier expects an origin for a session only where its relying +party names one. A session signed under a `did:key` is unconfirmed (§7.4 step +1), which is the normal case for a sink's ephemeral key. §2.4.4's *signed by* column names the party each class expects. Which of its keys is that party is the origin's decision, and its log records it: @@ -2606,6 +2850,19 @@ its keys is that party is the origin's decision, and its log records it: (§2.4.11). Neither is pinned-only, and neither is `delivery`: an origin gives `stage` to the sinks it speaks for and `delivery-gap` to its relays, and a key that holds `delivery` alone signs neither. +- **Reconstruct session.** `reconstruct-session` lets a key sign what a sink + reconstructed (§2.4.12). It is not pinned-only and it is not `delivery`: an + origin gives it to the sinks it speaks for. A session's energy figure is a + second item, since the session's other members stand without it: it needs + `reconstruct-session` and the energy authority of its class, every one of + them, and is reported with `also_delivers` where that class is a hardware + class. A verifier reports the session's confirmation and its figure's side by + side, and **MUST NOT** report the figure as its origin's unless it confirmed the + figure. A key that holds `reconstruct-session` and not the figure's energy + authority confirms a session whose figure is refused (`authority_not_granted`); + under a fetched anchor, a hardware-class figure is unconfirmed + (`anchor_not_pinned`) beside a confirmed session. The origin then stands behind + the session, and not behind its figure. - **Log inclusion.** A confirmation says under whose authority the log's evidence was attached. It does not check `log_receipt`: §2.4.7 is unchanged. diff --git a/wai/extensions/staged-measurement.md b/wai/extensions/staged-measurement.md index 869138ab6..7c86f86db 100644 --- a/wai/extensions/staged-measurement.md +++ b/wai/extensions/staged-measurement.md @@ -233,6 +233,20 @@ reading from a whole-system rail that includes a display is not published. §8.5 A rail that is not live in a bracket (energy-measurement §3.1) gives no figure; the decode is unmetered. +§8.6 Before a tool brackets a decode, it reads the power reader at rest and checks that +the rail is live there under the same rule: a reader that gives no sample is absent, and +one whose samples do not show a live rail is stale. Either way the tool brackets nothing, +and the decode is unmetered with that reason. A reader of an energy counter gives power +as the counter's successive differences over the time between its reads, across the +counter's wrap. + +§8.7 A sink records a session's decode figure in its session claim +([jwp-receipts](jwp-receipts.md) §2.4.12): the energy of one completion of the +presentations the claim commits to, under §8.1–§8.5, or `null` where the decode was +unmetered. A tool that signs a session claim seals a figure in it only where its verdict +is clean (§8.3), and publishes the bracket in a `measurement` claim about the session +claim, signed with the same key (energy-measurement §6). + ## 9. Deduplication §9.1 Over a set of objects: @@ -578,7 +592,8 @@ node = SHA-256("wai:out-node\x01" ‖ left ‖ right) - `decoder` is the index of the decoder entry that produced the output: entries are (capability, pin) pairs in first-use order, presentations taken by (layers, unit). For a title, the base's capability with the pin it verified, then each refinement - capability. + capability. For a session claim, the entries are its decoder entries + ([jwp-receipts](jwp-receipts.md) §2.4.12), in the same order. - Leaves are ordered by (unit, layers), and a (unit, layers) given twice is refused. - The root over `n ≥ 1` leaves is RFC 6962's Merkle tree hash: one leaf is itself; otherwise `node(MTH(D[0:k]), MTH(D[k:n]))`, with `k` the largest power of two below -- 2.54.0 (Apple Git-157) From 445deea0ba3394fd0143e6d06dfa9fd29609e1eb Mon Sep 17 00:00:00 2001 From: Transaction Science Date: Tue, 6 Oct 2026 09:07:07 -0400 Subject: [PATCH 02/27] wai-rs: the reconstruct-session claim class, its step-6 checks and its corpus MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit claim_receipt::session reads and checks a session body (jwp-receipts §2.4.12): step 2 in the member table's order, the twelve step-4 rules, and the step-6 checks against the presentations (the output tree, first-use order, paths, missed presentations, re-decodes through byte-exact decoders), the objects received, the entry envelopes' classical rendition and the stage claims the session names. A session's metered figure is viewed under moq-jwp:claim-link, and figure_authorities() gives its second confirmation item. The output tree builds under receipt_claims too; receipt_claims takes telemetry (no dependency) for delivery-telemetry §5's switch reasons. claim-conformance gains the session vectors, appended: the earlier vectors are an unchanged prefix, pinned by digest like the two prefixes before. Co-Authored-By: Claude Opus 5.5 --- wai/claim-conformance/vectors.json | 8515 ++++++++++++++++- wai/wai-rs/Cargo.toml | 4 +- wai/wai-rs/include/wai.h | 7 - wai/wai-rs/src/claim_receipt.rs | 260 +- .../src/claim_receipt/corpus/session.rs | 887 ++ wai/wai-rs/src/claim_receipt/session.rs | 932 ++ wai/wai-rs/src/energy_figure.rs | 10 +- wai/wai-rs/src/lib.rs | 5 +- 8 files changed, 10603 insertions(+), 17 deletions(-) create mode 100644 wai/wai-rs/src/claim_receipt/corpus/session.rs create mode 100644 wai/wai-rs/src/claim_receipt/session.rs diff --git a/wai/claim-conformance/vectors.json b/wai/claim-conformance/vectors.json index 861321598..42c1e67ce 100644 --- a/wai/claim-conformance/vectors.json +++ b/wai/claim-conformance/vectors.json @@ -1,5 +1,5 @@ { - "about": "jwp-receipts section 2.4.3-2.4.11, 2.6 and 3.1-3.2: typed claim receipts and the soft binding class. Every vector is synthetic: keys are Ed25519 from fixed 32-byte seeds (0x11 publisher, 0x22 meter, 0x33 operator, 0x44 sink, 0x55 resolver, 0x66 relay) and attest nothing; figures are invented; algorithm names, endpoints, logs and registries use reserved example domains; vocabulary terms are illustrative and are not checked against the vocabulary. Expected outcomes are declared per vector in the generator, not copied from a verifier. Regenerate with `wai_claim_vectors gen`.", + "about": "jwp-receipts section 2.4.3-2.4.12, 2.6 and 3.1-3.2: typed claim receipts and the soft binding class. Every vector is synthetic: keys are Ed25519 from fixed 32-byte seeds (0x11 publisher, 0x22 meter, 0x33 operator, 0x44 sink, 0x55 resolver, 0x66 relay) and attest nothing; figures are invented; algorithm names, endpoints, logs and registries use reserved example domains; vocabulary terms are illustrative and are not checked against the vocabulary. Expected outcomes are declared per vector in the generator, not copied from a verifier. Regenerate with `wai_claim_vectors gen`.", "vectors": [ { "name": "energy_accept", @@ -5032,6 +5032,8519 @@ "step": 1, "reason": "subject_type_not_admitted" } + }, + { + "name": "session_accept", + "about": "an unmetered session: five units, a stage set refined to three layers, a switch to the fallback, one late presentation and a classical rendition not needed; every context held", + "procedure": "claim", + "receipt": "{\"body\":{\"classical_declared\":700,\"classical_source\":\"wai2-table\",\"counted_discarded\":1904,\"counted_fallback\":0,\"counted_primary\":5607,\"deadline_us\":40000,\"decoders\":[{\"capability\":\"wai.video.int_hyper\",\"decoder\":\"builtin:wai@0.4.0\",\"leaves\":4,\"module_status\":null,\"path\":\"primary\",\"pin\":\"7b4371854df0aa1645ac6525b373387c0617b873d5a57748932ee0f386ea164b\",\"rendition\":0,\"tier\":\"decode-equivalence\",\"variant\":null},{\"capability\":\"wai.video.av1\",\"decoder\":\"builtin:wai@0.4.0\",\"leaves\":1,\"module_status\":null,\"path\":\"fallback\",\"pin\":null,\"rendition\":null,\"tier\":null,\"variant\":null},{\"capability\":\"wai.video.int_refine\",\"decoder\":\"builtin:wai@0.4.0\",\"leaves\":4,\"module_status\":null,\"path\":\"primary\",\"pin\":null,\"rendition\":null,\"tier\":null,\"variant\":null}],\"energy\":null,\"fallback_units\":1,\"framing\":\"registered\",\"host\":{\"build\":{\"profile\":\"release\",\"target\":\"aarch64-unknown-linux-gnu\",\"toolchain\":\"rustc 1.95.0\"},\"profile\":\"native-ffi\",\"target\":\"aarch64-unknown-linux-gnu\",\"threads\":4},\"leaf_count\":9,\"media\":\"video\",\"missed\":1,\"missed_units\":[{\"late_us\":1200,\"layers\":1,\"unit\":4}],\"output_root\":\"3cb2c68a7fe160511bd3fbbbd6945b5d54fac6b499e33769b1ea6828f04bb312\",\"primary_units\":4,\"receipt_bytes\":640,\"session_nonce\":\"57c5462dfdabd1b7bdd204d34ba33649c057eb535349f29f45eb8f8c7d4a7e7f\",\"stage_sets\":[{\"claim\":\"b636e8894207d2fe59add1e1cacf3b52ea760fccb4dc3f0abce79be90e871640\",\"first_unit\":0}],\"switches\":[{\"from\":\"primary\",\"reason\":\"set-incomplete\",\"to\":\"fallback\",\"unit\":4}],\"switches_total\":1,\"transferred\":13607,\"uncounted\":2,\"units\":5},\"class\":\"reconstruct-session\",\"issued_at\":\"2026-09-27T12:00:00Z\",\"kind\":\"claim\",\"parent_receipt_hash\":null,\"seq\":0,\"sig\":\"2871039f189db43685c214c860ac86567712af1e35d3254c371e7faaf8582734b5216c7ba4015383ad9013aac4c34ba1aebf410a56615d5bf2f5d73622c1410e\",\"signer_id\":\"did:example:sink\",\"signer_pubkey\":\"d759793bbc13a2819a827c76adb6fba8a49aee007f49f2d0992d99b825ad2c48\",\"subject\":\"64c0713cb176874607bf8670295242184b7868a9ff7c55554a5ae08de2c301c1\",\"subject_type\":\"object\"}", + "context": { + "outputs": [ + { + "unit": 0, + "layers": 1, + "decoder": 0, + "out_digest": "55f7e628ca707e2ca3159709eeb68b9000813f2916a299acd33a23e6fe012584" + }, + { + "unit": 1, + "layers": 1, + "decoder": 0, + "out_digest": "a3ee8a4b96eceb663f3d94417957d02f897fc166dc96ebe9bf447c4a36a36264" + }, + { + "unit": 2, + "layers": 1, + "decoder": 0, + "out_digest": "00576d2c4d09ef5d7aa807f9b3b1587e200dea6f6694b4da062b41aa2a5ab8af" + }, + { + "unit": 3, + "layers": 1, + "decoder": 0, + "out_digest": "26cd9b2805b604b26e08d9a461db599c4e249bfd4df41a3befb202bc6d0e0700" + }, + { + "unit": 4, + "layers": 1, + "decoder": 1, + "out_digest": "1cd1984bc553c43ee5a48fe7e182a77e60d8ef3c2b0f959ef1a0efd3813b411f" + }, + { + "unit": 0, + "layers": 2, + "decoder": 2, + "out_digest": "cedffc10c0d2e777c954459c198af496e316170b3a8c35276a3f473edf438a0e" + }, + { + "unit": 1, + "layers": 2, + "decoder": 2, + "out_digest": "f0348794b5be95fd5c4e8f268957b6d188c35f76146f4479c960124a4392841d" + }, + { + "unit": 2, + "layers": 2, + "decoder": 2, + "out_digest": "446c9941549464ba1b15c36c6e738380f8918f4a63a47ebbbdd67058a1975a80" + }, + { + "unit": 0, + "layers": 3, + "decoder": 2, + "out_digest": "a80c01cb3ded2f965b69ec4a5b3f1dcb6996e05454d9963e0b05455f9f27bc2f" + } + ], + "redecoded": [ + { + "index": 0, + "out_digest": "55f7e628ca707e2ca3159709eeb68b9000813f2916a299acd33a23e6fe012584" + } + ], + "objects": [ + { + "content_hash": "64c0713cb176874607bf8670295242184b7868a9ff7c55554a5ae08de2c301c1", + "path": "primary", + "counted": null, + "transferred": 5000, + "presented": true + }, + { + "content_hash": "47a2c23727d2eb9d2beef0931c3e9b2675408d372660420cce427dc27fd21fe1", + "path": "primary", + "counted": 900, + "transferred": 900, + "presented": true + }, + { + "content_hash": "6b74be11e64461c7d972fc5cb6ba15e98427e9d6e60622b0a753222138de28cf", + "path": "primary", + "counted": 901, + "transferred": 901, + "presented": true + }, + { + "content_hash": "5e7a38ca5c04442cbe00b040d58e4494f5aa36fb81e8bbe0d304fd2d1ce722b2", + "path": "primary", + "counted": 902, + "transferred": 902, + "presented": true + }, + { + "content_hash": "792a12990c5207ca83a86b7420815f1f2d34918553a0130a4f9570a11354f2ca", + "path": "primary", + "counted": 903, + "transferred": 903, + "presented": false + }, + { + "content_hash": "be5055af8e32359265852c512667b10ab6a07455e5ab06603e278763f6633a85", + "path": "primary", + "counted": 1000, + "transferred": 1000, + "presented": true + }, + { + "content_hash": "1c6eae0ed41ed7fc1b2f00b46ea1de98f21a6d6cbf62bf6b22cf76a664a49376", + "path": "primary", + "counted": 1001, + "transferred": 1001, + "presented": false + }, + { + "content_hash": "13b04249eca2b1a9061dba8ca2846169d3f5fa3548d9e138a0cf2cb553798cf4", + "path": "fallback", + "counted": null, + "transferred": 3000, + "presented": true + } + ], + "envelopes": [ + { + "envelope": "57414932b30000007b22776169223a22312e31222c226d65646961223a22766964656f222c22696e74656e74223a227265706c6963617465222c2272656e646974696f6e73223a5b7b226361706162696c697479223a227761692e766964656f2e696e745f6879706572222c226b696e64223a22696e745f6879706572227d2c7b226361706162696c697479223a227761692e766964656f2e617663222c226b696e64223a22617663227d5d2c22746172676574223a6e756c6c7d020000000000c8000000c8000000bc020000111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111122222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222", + "rendition": 1 + } + ], + "stage_claims": [ + "{\"body\":{\"bytes_envelopes\":10607,\"conflicts\":0,\"deadline_misses\":2,\"objects\":[{\"bytes\":900,\"evidence\":\"none\",\"layer\":1,\"object\":\"47a2c23727d2eb9d2beef0931c3e9b2675408d372660420cce427dc27fd21fe1\",\"reason\":null,\"status\":\"applied\",\"units\":{\"count\":1,\"from\":0}},{\"bytes\":901,\"evidence\":\"none\",\"layer\":1,\"object\":\"6b74be11e64461c7d972fc5cb6ba15e98427e9d6e60622b0a753222138de28cf\",\"reason\":null,\"status\":\"applied\",\"units\":{\"count\":1,\"from\":1}},{\"bytes\":902,\"evidence\":\"none\",\"layer\":1,\"object\":\"5e7a38ca5c04442cbe00b040d58e4494f5aa36fb81e8bbe0d304fd2d1ce722b2\",\"reason\":null,\"status\":\"applied\",\"units\":{\"count\":1,\"from\":2}},{\"bytes\":903,\"evidence\":\"none\",\"layer\":1,\"object\":\"792a12990c5207ca83a86b7420815f1f2d34918553a0130a4f9570a11354f2ca\",\"reason\":null,\"status\":\"late\",\"units\":{\"count\":1,\"from\":3}},{\"bytes\":1000,\"evidence\":\"none\",\"layer\":2,\"object\":\"be5055af8e32359265852c512667b10ab6a07455e5ab06603e278763f6633a85\",\"reason\":null,\"status\":\"applied\",\"units\":{\"count\":1,\"from\":0}},{\"bytes\":1001,\"evidence\":\"none\",\"layer\":2,\"object\":\"1c6eae0ed41ed7fc1b2f00b46ea1de98f21a6d6cbf62bf6b22cf76a664a49376\",\"reason\":null,\"status\":\"late\",\"units\":{\"count\":1,\"from\":1}}],\"op_committed\":null,\"op_delivered\":null,\"op_requested\":null,\"presented\":{\"wai-stage:layers\":0},\"stage_hash\":null,\"tier\":\"none\",\"units_by_stage\":[1,2,1],\"vocabulary\":\"urn:wai:staged-delivery:1\"},\"class\":\"stage\",\"issued_at\":\"2026-09-27T12:00:00Z\",\"kind\":\"claim\",\"parent_receipt_hash\":null,\"seq\":0,\"sig\":\"96eb16ba17662e0981fcaf390e1172cefae5c4b2ca5fcf1df3ea10b5176fb0225169a07938ffcb0362d8c35472dab6d39711c331765ebc083bb3b6a55b20da02\",\"signer_id\":\"did:example:sink\",\"signer_pubkey\":\"d759793bbc13a2819a827c76adb6fba8a49aee007f49f2d0992d99b825ad2c48\",\"subject\":\"3844a5152c86c7892dc6c942553da2496c949edd7e32dbbc1a013c4c5d41f54f\",\"subject_type\":\"object\"}" + ] + }, + "expected": { + "outcome": "accept", + "link_hash": "cc336d348fd5b500a1a37f5e6a2f6c72ab4cfe83b76cc508ed4f0aae6eeeb741" + } + }, + { + "name": "session_metered_accept", + "about": "the same session metered under OnChipCounter with its declared uncertainty and filtering state", + "procedure": "claim", + "receipt": "{\"body\":{\"classical_declared\":700,\"classical_source\":\"wai2-table\",\"counted_discarded\":1904,\"counted_fallback\":0,\"counted_primary\":5607,\"deadline_us\":40000,\"decoders\":[{\"capability\":\"wai.video.int_hyper\",\"decoder\":\"builtin:wai@0.4.0\",\"leaves\":4,\"module_status\":null,\"path\":\"primary\",\"pin\":\"7b4371854df0aa1645ac6525b373387c0617b873d5a57748932ee0f386ea164b\",\"rendition\":0,\"tier\":\"decode-equivalence\",\"variant\":null},{\"capability\":\"wai.video.av1\",\"decoder\":\"builtin:wai@0.4.0\",\"leaves\":1,\"module_status\":null,\"path\":\"fallback\",\"pin\":null,\"rendition\":null,\"tier\":null,\"variant\":null},{\"capability\":\"wai.video.int_refine\",\"decoder\":\"builtin:wai@0.4.0\",\"leaves\":4,\"module_status\":null,\"path\":\"primary\",\"pin\":null,\"rendition\":null,\"tier\":null,\"variant\":null}],\"energy\":{\"energy_calibration_ref\":null,\"energy_counter_filtering\":\"Unknown\",\"energy_provenance\":\"OnChipCounter\",\"energy_uncertainty\":{\"relative_ppm\":20000,\"window_us\":1000000},\"joules_micro\":250000},\"fallback_units\":1,\"framing\":\"registered\",\"host\":{\"build\":{\"profile\":\"release\",\"target\":\"aarch64-unknown-linux-gnu\",\"toolchain\":\"rustc 1.95.0\"},\"profile\":\"native-ffi\",\"target\":\"aarch64-unknown-linux-gnu\",\"threads\":4},\"leaf_count\":9,\"media\":\"video\",\"missed\":1,\"missed_units\":[{\"late_us\":1200,\"layers\":1,\"unit\":4}],\"output_root\":\"3cb2c68a7fe160511bd3fbbbd6945b5d54fac6b499e33769b1ea6828f04bb312\",\"primary_units\":4,\"receipt_bytes\":640,\"session_nonce\":\"57c5462dfdabd1b7bdd204d34ba33649c057eb535349f29f45eb8f8c7d4a7e7f\",\"stage_sets\":[{\"claim\":\"b636e8894207d2fe59add1e1cacf3b52ea760fccb4dc3f0abce79be90e871640\",\"first_unit\":0}],\"switches\":[{\"from\":\"primary\",\"reason\":\"set-incomplete\",\"to\":\"fallback\",\"unit\":4}],\"switches_total\":1,\"transferred\":13607,\"uncounted\":2,\"units\":5},\"class\":\"reconstruct-session\",\"issued_at\":\"2026-09-27T12:00:00Z\",\"kind\":\"claim\",\"parent_receipt_hash\":null,\"seq\":0,\"sig\":\"756af8a7612a6238db2bbbc819d72b5fe002e981b618197e1661af71956e72023973f13c2a57cee989ae30edfc828285a63d8b79af4c486a5eab3c2de9e6760f\",\"signer_id\":\"did:example:sink\",\"signer_pubkey\":\"d759793bbc13a2819a827c76adb6fba8a49aee007f49f2d0992d99b825ad2c48\",\"subject\":\"64c0713cb176874607bf8670295242184b7868a9ff7c55554a5ae08de2c301c1\",\"subject_type\":\"object\"}", + "context": { + "outputs": [ + { + "unit": 0, + "layers": 1, + "decoder": 0, + "out_digest": "55f7e628ca707e2ca3159709eeb68b9000813f2916a299acd33a23e6fe012584" + }, + { + "unit": 1, + "layers": 1, + "decoder": 0, + "out_digest": "a3ee8a4b96eceb663f3d94417957d02f897fc166dc96ebe9bf447c4a36a36264" + }, + { + "unit": 2, + "layers": 1, + "decoder": 0, + "out_digest": "00576d2c4d09ef5d7aa807f9b3b1587e200dea6f6694b4da062b41aa2a5ab8af" + }, + { + "unit": 3, + "layers": 1, + "decoder": 0, + "out_digest": "26cd9b2805b604b26e08d9a461db599c4e249bfd4df41a3befb202bc6d0e0700" + }, + { + "unit": 4, + "layers": 1, + "decoder": 1, + "out_digest": "1cd1984bc553c43ee5a48fe7e182a77e60d8ef3c2b0f959ef1a0efd3813b411f" + }, + { + "unit": 0, + "layers": 2, + "decoder": 2, + "out_digest": "cedffc10c0d2e777c954459c198af496e316170b3a8c35276a3f473edf438a0e" + }, + { + "unit": 1, + "layers": 2, + "decoder": 2, + "out_digest": "f0348794b5be95fd5c4e8f268957b6d188c35f76146f4479c960124a4392841d" + }, + { + "unit": 2, + "layers": 2, + "decoder": 2, + "out_digest": "446c9941549464ba1b15c36c6e738380f8918f4a63a47ebbbdd67058a1975a80" + }, + { + "unit": 0, + "layers": 3, + "decoder": 2, + "out_digest": "a80c01cb3ded2f965b69ec4a5b3f1dcb6996e05454d9963e0b05455f9f27bc2f" + } + ], + "redecoded": [ + { + "index": 0, + "out_digest": "55f7e628ca707e2ca3159709eeb68b9000813f2916a299acd33a23e6fe012584" + } + ], + "objects": [ + { + "content_hash": "64c0713cb176874607bf8670295242184b7868a9ff7c55554a5ae08de2c301c1", + "path": "primary", + "counted": null, + "transferred": 5000, + "presented": true + }, + { + "content_hash": "47a2c23727d2eb9d2beef0931c3e9b2675408d372660420cce427dc27fd21fe1", + "path": "primary", + "counted": 900, + "transferred": 900, + "presented": true + }, + { + "content_hash": "6b74be11e64461c7d972fc5cb6ba15e98427e9d6e60622b0a753222138de28cf", + "path": "primary", + "counted": 901, + "transferred": 901, + "presented": true + }, + { + "content_hash": "5e7a38ca5c04442cbe00b040d58e4494f5aa36fb81e8bbe0d304fd2d1ce722b2", + "path": "primary", + "counted": 902, + "transferred": 902, + "presented": true + }, + { + "content_hash": "792a12990c5207ca83a86b7420815f1f2d34918553a0130a4f9570a11354f2ca", + "path": "primary", + "counted": 903, + "transferred": 903, + "presented": false + }, + { + "content_hash": "be5055af8e32359265852c512667b10ab6a07455e5ab06603e278763f6633a85", + "path": "primary", + "counted": 1000, + "transferred": 1000, + "presented": true + }, + { + "content_hash": "1c6eae0ed41ed7fc1b2f00b46ea1de98f21a6d6cbf62bf6b22cf76a664a49376", + "path": "primary", + "counted": 1001, + "transferred": 1001, + "presented": false + }, + { + "content_hash": "13b04249eca2b1a9061dba8ca2846169d3f5fa3548d9e138a0cf2cb553798cf4", + "path": "fallback", + "counted": null, + "transferred": 3000, + "presented": true + } + ], + "envelopes": [ + { + "envelope": "57414932b30000007b22776169223a22312e31222c226d65646961223a22766964656f222c22696e74656e74223a227265706c6963617465222c2272656e646974696f6e73223a5b7b226361706162696c697479223a227761692e766964656f2e696e745f6879706572222c226b696e64223a22696e745f6879706572227d2c7b226361706162696c697479223a227761692e766964656f2e617663222c226b696e64223a22617663227d5d2c22746172676574223a6e756c6c7d020000000000c8000000c8000000bc020000111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111122222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222", + "rendition": 1 + } + ], + "stage_claims": [ + "{\"body\":{\"bytes_envelopes\":10607,\"conflicts\":0,\"deadline_misses\":2,\"objects\":[{\"bytes\":900,\"evidence\":\"none\",\"layer\":1,\"object\":\"47a2c23727d2eb9d2beef0931c3e9b2675408d372660420cce427dc27fd21fe1\",\"reason\":null,\"status\":\"applied\",\"units\":{\"count\":1,\"from\":0}},{\"bytes\":901,\"evidence\":\"none\",\"layer\":1,\"object\":\"6b74be11e64461c7d972fc5cb6ba15e98427e9d6e60622b0a753222138de28cf\",\"reason\":null,\"status\":\"applied\",\"units\":{\"count\":1,\"from\":1}},{\"bytes\":902,\"evidence\":\"none\",\"layer\":1,\"object\":\"5e7a38ca5c04442cbe00b040d58e4494f5aa36fb81e8bbe0d304fd2d1ce722b2\",\"reason\":null,\"status\":\"applied\",\"units\":{\"count\":1,\"from\":2}},{\"bytes\":903,\"evidence\":\"none\",\"layer\":1,\"object\":\"792a12990c5207ca83a86b7420815f1f2d34918553a0130a4f9570a11354f2ca\",\"reason\":null,\"status\":\"late\",\"units\":{\"count\":1,\"from\":3}},{\"bytes\":1000,\"evidence\":\"none\",\"layer\":2,\"object\":\"be5055af8e32359265852c512667b10ab6a07455e5ab06603e278763f6633a85\",\"reason\":null,\"status\":\"applied\",\"units\":{\"count\":1,\"from\":0}},{\"bytes\":1001,\"evidence\":\"none\",\"layer\":2,\"object\":\"1c6eae0ed41ed7fc1b2f00b46ea1de98f21a6d6cbf62bf6b22cf76a664a49376\",\"reason\":null,\"status\":\"late\",\"units\":{\"count\":1,\"from\":1}}],\"op_committed\":null,\"op_delivered\":null,\"op_requested\":null,\"presented\":{\"wai-stage:layers\":0},\"stage_hash\":null,\"tier\":\"none\",\"units_by_stage\":[1,2,1],\"vocabulary\":\"urn:wai:staged-delivery:1\"},\"class\":\"stage\",\"issued_at\":\"2026-09-27T12:00:00Z\",\"kind\":\"claim\",\"parent_receipt_hash\":null,\"seq\":0,\"sig\":\"96eb16ba17662e0981fcaf390e1172cefae5c4b2ca5fcf1df3ea10b5176fb0225169a07938ffcb0362d8c35472dab6d39711c331765ebc083bb3b6a55b20da02\",\"signer_id\":\"did:example:sink\",\"signer_pubkey\":\"d759793bbc13a2819a827c76adb6fba8a49aee007f49f2d0992d99b825ad2c48\",\"subject\":\"3844a5152c86c7892dc6c942553da2496c949edd7e32dbbc1a013c4c5d41f54f\",\"subject_type\":\"object\"}" + ] + }, + "expected": { + "outcome": "accept", + "link_hash": "93d7ea35e77a906d4a1a7933fbe81145d1d4be3e0144a8cb2087e7950d07db06" + } + }, + { + "name": "session_no_context_accept", + "about": "the model session checked with no context: steps 1-5 only", + "procedure": "claim", + "receipt": "{\"body\":{\"classical_declared\":700,\"classical_source\":\"wai2-table\",\"counted_discarded\":1904,\"counted_fallback\":0,\"counted_primary\":5607,\"deadline_us\":40000,\"decoders\":[{\"capability\":\"wai.video.int_hyper\",\"decoder\":\"builtin:wai@0.4.0\",\"leaves\":4,\"module_status\":null,\"path\":\"primary\",\"pin\":\"7b4371854df0aa1645ac6525b373387c0617b873d5a57748932ee0f386ea164b\",\"rendition\":0,\"tier\":\"decode-equivalence\",\"variant\":null},{\"capability\":\"wai.video.av1\",\"decoder\":\"builtin:wai@0.4.0\",\"leaves\":1,\"module_status\":null,\"path\":\"fallback\",\"pin\":null,\"rendition\":null,\"tier\":null,\"variant\":null},{\"capability\":\"wai.video.int_refine\",\"decoder\":\"builtin:wai@0.4.0\",\"leaves\":4,\"module_status\":null,\"path\":\"primary\",\"pin\":null,\"rendition\":null,\"tier\":null,\"variant\":null}],\"energy\":null,\"fallback_units\":1,\"framing\":\"registered\",\"host\":{\"build\":{\"profile\":\"release\",\"target\":\"aarch64-unknown-linux-gnu\",\"toolchain\":\"rustc 1.95.0\"},\"profile\":\"native-ffi\",\"target\":\"aarch64-unknown-linux-gnu\",\"threads\":4},\"leaf_count\":9,\"media\":\"video\",\"missed\":1,\"missed_units\":[{\"late_us\":1200,\"layers\":1,\"unit\":4}],\"output_root\":\"3cb2c68a7fe160511bd3fbbbd6945b5d54fac6b499e33769b1ea6828f04bb312\",\"primary_units\":4,\"receipt_bytes\":640,\"session_nonce\":\"57c5462dfdabd1b7bdd204d34ba33649c057eb535349f29f45eb8f8c7d4a7e7f\",\"stage_sets\":[{\"claim\":\"b636e8894207d2fe59add1e1cacf3b52ea760fccb4dc3f0abce79be90e871640\",\"first_unit\":0}],\"switches\":[{\"from\":\"primary\",\"reason\":\"set-incomplete\",\"to\":\"fallback\",\"unit\":4}],\"switches_total\":1,\"transferred\":13607,\"uncounted\":2,\"units\":5},\"class\":\"reconstruct-session\",\"issued_at\":\"2026-09-27T12:00:00Z\",\"kind\":\"claim\",\"parent_receipt_hash\":null,\"seq\":0,\"sig\":\"2871039f189db43685c214c860ac86567712af1e35d3254c371e7faaf8582734b5216c7ba4015383ad9013aac4c34ba1aebf410a56615d5bf2f5d73622c1410e\",\"signer_id\":\"did:example:sink\",\"signer_pubkey\":\"d759793bbc13a2819a827c76adb6fba8a49aee007f49f2d0992d99b825ad2c48\",\"subject\":\"64c0713cb176874607bf8670295242184b7868a9ff7c55554a5ae08de2c301c1\",\"subject_type\":\"object\"}", + "expected": { + "outcome": "accept", + "link_hash": "cc336d348fd5b500a1a37f5e6a2f6c72ab4cfe83b76cc508ed4f0aae6eeeb741" + } + }, + { + "name": "session_stage_claim_without_outputs_accept", + "about": "the stage claim the session names, held without the outputs: only its identity is checked", + "procedure": "claim", + "receipt": "{\"body\":{\"classical_declared\":700,\"classical_source\":\"wai2-table\",\"counted_discarded\":1904,\"counted_fallback\":0,\"counted_primary\":5607,\"deadline_us\":40000,\"decoders\":[{\"capability\":\"wai.video.int_hyper\",\"decoder\":\"builtin:wai@0.4.0\",\"leaves\":4,\"module_status\":null,\"path\":\"primary\",\"pin\":\"7b4371854df0aa1645ac6525b373387c0617b873d5a57748932ee0f386ea164b\",\"rendition\":0,\"tier\":\"decode-equivalence\",\"variant\":null},{\"capability\":\"wai.video.av1\",\"decoder\":\"builtin:wai@0.4.0\",\"leaves\":1,\"module_status\":null,\"path\":\"fallback\",\"pin\":null,\"rendition\":null,\"tier\":null,\"variant\":null},{\"capability\":\"wai.video.int_refine\",\"decoder\":\"builtin:wai@0.4.0\",\"leaves\":4,\"module_status\":null,\"path\":\"primary\",\"pin\":null,\"rendition\":null,\"tier\":null,\"variant\":null}],\"energy\":null,\"fallback_units\":1,\"framing\":\"registered\",\"host\":{\"build\":{\"profile\":\"release\",\"target\":\"aarch64-unknown-linux-gnu\",\"toolchain\":\"rustc 1.95.0\"},\"profile\":\"native-ffi\",\"target\":\"aarch64-unknown-linux-gnu\",\"threads\":4},\"leaf_count\":9,\"media\":\"video\",\"missed\":1,\"missed_units\":[{\"late_us\":1200,\"layers\":1,\"unit\":4}],\"output_root\":\"3cb2c68a7fe160511bd3fbbbd6945b5d54fac6b499e33769b1ea6828f04bb312\",\"primary_units\":4,\"receipt_bytes\":640,\"session_nonce\":\"57c5462dfdabd1b7bdd204d34ba33649c057eb535349f29f45eb8f8c7d4a7e7f\",\"stage_sets\":[{\"claim\":\"b636e8894207d2fe59add1e1cacf3b52ea760fccb4dc3f0abce79be90e871640\",\"first_unit\":0}],\"switches\":[{\"from\":\"primary\",\"reason\":\"set-incomplete\",\"to\":\"fallback\",\"unit\":4}],\"switches_total\":1,\"transferred\":13607,\"uncounted\":2,\"units\":5},\"class\":\"reconstruct-session\",\"issued_at\":\"2026-09-27T12:00:00Z\",\"kind\":\"claim\",\"parent_receipt_hash\":null,\"seq\":0,\"sig\":\"2871039f189db43685c214c860ac86567712af1e35d3254c371e7faaf8582734b5216c7ba4015383ad9013aac4c34ba1aebf410a56615d5bf2f5d73622c1410e\",\"signer_id\":\"did:example:sink\",\"signer_pubkey\":\"d759793bbc13a2819a827c76adb6fba8a49aee007f49f2d0992d99b825ad2c48\",\"subject\":\"64c0713cb176874607bf8670295242184b7868a9ff7c55554a5ae08de2c301c1\",\"subject_type\":\"object\"}", + "context": { + "stage_claims": [ + "{\"body\":{\"bytes_envelopes\":10607,\"conflicts\":0,\"deadline_misses\":2,\"objects\":[{\"bytes\":900,\"evidence\":\"none\",\"layer\":1,\"object\":\"47a2c23727d2eb9d2beef0931c3e9b2675408d372660420cce427dc27fd21fe1\",\"reason\":null,\"status\":\"applied\",\"units\":{\"count\":1,\"from\":0}},{\"bytes\":901,\"evidence\":\"none\",\"layer\":1,\"object\":\"6b74be11e64461c7d972fc5cb6ba15e98427e9d6e60622b0a753222138de28cf\",\"reason\":null,\"status\":\"applied\",\"units\":{\"count\":1,\"from\":1}},{\"bytes\":902,\"evidence\":\"none\",\"layer\":1,\"object\":\"5e7a38ca5c04442cbe00b040d58e4494f5aa36fb81e8bbe0d304fd2d1ce722b2\",\"reason\":null,\"status\":\"applied\",\"units\":{\"count\":1,\"from\":2}},{\"bytes\":903,\"evidence\":\"none\",\"layer\":1,\"object\":\"792a12990c5207ca83a86b7420815f1f2d34918553a0130a4f9570a11354f2ca\",\"reason\":null,\"status\":\"late\",\"units\":{\"count\":1,\"from\":3}},{\"bytes\":1000,\"evidence\":\"none\",\"layer\":2,\"object\":\"be5055af8e32359265852c512667b10ab6a07455e5ab06603e278763f6633a85\",\"reason\":null,\"status\":\"applied\",\"units\":{\"count\":1,\"from\":0}},{\"bytes\":1001,\"evidence\":\"none\",\"layer\":2,\"object\":\"1c6eae0ed41ed7fc1b2f00b46ea1de98f21a6d6cbf62bf6b22cf76a664a49376\",\"reason\":null,\"status\":\"late\",\"units\":{\"count\":1,\"from\":1}}],\"op_committed\":null,\"op_delivered\":null,\"op_requested\":null,\"presented\":{\"wai-stage:layers\":0},\"stage_hash\":null,\"tier\":\"none\",\"units_by_stage\":[1,2,1],\"vocabulary\":\"urn:wai:staged-delivery:1\"},\"class\":\"stage\",\"issued_at\":\"2026-09-27T12:00:00Z\",\"kind\":\"claim\",\"parent_receipt_hash\":null,\"seq\":0,\"sig\":\"96eb16ba17662e0981fcaf390e1172cefae5c4b2ca5fcf1df3ea10b5176fb0225169a07938ffcb0362d8c35472dab6d39711c331765ebc083bb3b6a55b20da02\",\"signer_id\":\"did:example:sink\",\"signer_pubkey\":\"d759793bbc13a2819a827c76adb6fba8a49aee007f49f2d0992d99b825ad2c48\",\"subject\":\"3844a5152c86c7892dc6c942553da2496c949edd7e32dbbc1a013c4c5d41f54f\",\"subject_type\":\"object\"}" + ] + }, + "expected": { + "outcome": "accept", + "link_hash": "cc336d348fd5b500a1a37f5e6a2f6c72ab4cfe83b76cc508ed4f0aae6eeeb741" + } + }, + { + "name": "session_path_sum", + "about": "primary_units counts one unit more than were presented", + "procedure": "claim", + "receipt": "{\"body\":{\"classical_declared\":700,\"classical_source\":\"wai2-table\",\"counted_discarded\":1904,\"counted_fallback\":0,\"counted_primary\":5607,\"deadline_us\":40000,\"decoders\":[{\"capability\":\"wai.video.int_hyper\",\"decoder\":\"builtin:wai@0.4.0\",\"leaves\":4,\"module_status\":null,\"path\":\"primary\",\"pin\":\"7b4371854df0aa1645ac6525b373387c0617b873d5a57748932ee0f386ea164b\",\"rendition\":0,\"tier\":\"decode-equivalence\",\"variant\":null},{\"capability\":\"wai.video.av1\",\"decoder\":\"builtin:wai@0.4.0\",\"leaves\":1,\"module_status\":null,\"path\":\"fallback\",\"pin\":null,\"rendition\":null,\"tier\":null,\"variant\":null},{\"capability\":\"wai.video.int_refine\",\"decoder\":\"builtin:wai@0.4.0\",\"leaves\":4,\"module_status\":null,\"path\":\"primary\",\"pin\":null,\"rendition\":null,\"tier\":null,\"variant\":null}],\"energy\":null,\"fallback_units\":1,\"framing\":\"registered\",\"host\":{\"build\":{\"profile\":\"release\",\"target\":\"aarch64-unknown-linux-gnu\",\"toolchain\":\"rustc 1.95.0\"},\"profile\":\"native-ffi\",\"target\":\"aarch64-unknown-linux-gnu\",\"threads\":4},\"leaf_count\":9,\"media\":\"video\",\"missed\":1,\"missed_units\":[{\"late_us\":1200,\"layers\":1,\"unit\":4}],\"output_root\":\"3cb2c68a7fe160511bd3fbbbd6945b5d54fac6b499e33769b1ea6828f04bb312\",\"primary_units\":5,\"receipt_bytes\":640,\"session_nonce\":\"57c5462dfdabd1b7bdd204d34ba33649c057eb535349f29f45eb8f8c7d4a7e7f\",\"stage_sets\":[{\"claim\":\"b636e8894207d2fe59add1e1cacf3b52ea760fccb4dc3f0abce79be90e871640\",\"first_unit\":0}],\"switches\":[{\"from\":\"primary\",\"reason\":\"set-incomplete\",\"to\":\"fallback\",\"unit\":4}],\"switches_total\":1,\"transferred\":13607,\"uncounted\":2,\"units\":5},\"class\":\"reconstruct-session\",\"issued_at\":\"2026-09-27T12:00:00Z\",\"kind\":\"claim\",\"parent_receipt_hash\":null,\"seq\":0,\"sig\":\"576fdd67ac5cee27ddab54afc769a63ac02335b588accd94f3b0f166c1299742591321170aec45e3fd3aaa57d3399910526fa834316909a92291f7cd18eb440c\",\"signer_id\":\"did:example:sink\",\"signer_pubkey\":\"d759793bbc13a2819a827c76adb6fba8a49aee007f49f2d0992d99b825ad2c48\",\"subject\":\"64c0713cb176874607bf8670295242184b7868a9ff7c55554a5ae08de2c301c1\",\"subject_type\":\"object\"}", + "expected": { + "outcome": "reject", + "step": 4, + "reason": "session_path_sum" + } + }, + { + "name": "session_leaf_sum", + "about": "the entries' leaves sum to one more than leaf_count", + "procedure": "claim", + "receipt": "{\"body\":{\"classical_declared\":700,\"classical_source\":\"wai2-table\",\"counted_discarded\":1904,\"counted_fallback\":0,\"counted_primary\":5607,\"deadline_us\":40000,\"decoders\":[{\"capability\":\"wai.video.int_hyper\",\"decoder\":\"builtin:wai@0.4.0\",\"leaves\":4,\"module_status\":null,\"path\":\"primary\",\"pin\":\"7b4371854df0aa1645ac6525b373387c0617b873d5a57748932ee0f386ea164b\",\"rendition\":0,\"tier\":\"decode-equivalence\",\"variant\":null},{\"capability\":\"wai.video.av1\",\"decoder\":\"builtin:wai@0.4.0\",\"leaves\":1,\"module_status\":null,\"path\":\"fallback\",\"pin\":null,\"rendition\":null,\"tier\":null,\"variant\":null},{\"capability\":\"wai.video.int_refine\",\"decoder\":\"builtin:wai@0.4.0\",\"leaves\":5,\"module_status\":null,\"path\":\"primary\",\"pin\":null,\"rendition\":null,\"tier\":null,\"variant\":null}],\"energy\":null,\"fallback_units\":1,\"framing\":\"registered\",\"host\":{\"build\":{\"profile\":\"release\",\"target\":\"aarch64-unknown-linux-gnu\",\"toolchain\":\"rustc 1.95.0\"},\"profile\":\"native-ffi\",\"target\":\"aarch64-unknown-linux-gnu\",\"threads\":4},\"leaf_count\":9,\"media\":\"video\",\"missed\":1,\"missed_units\":[{\"late_us\":1200,\"layers\":1,\"unit\":4}],\"output_root\":\"3cb2c68a7fe160511bd3fbbbd6945b5d54fac6b499e33769b1ea6828f04bb312\",\"primary_units\":4,\"receipt_bytes\":640,\"session_nonce\":\"57c5462dfdabd1b7bdd204d34ba33649c057eb535349f29f45eb8f8c7d4a7e7f\",\"stage_sets\":[{\"claim\":\"b636e8894207d2fe59add1e1cacf3b52ea760fccb4dc3f0abce79be90e871640\",\"first_unit\":0}],\"switches\":[{\"from\":\"primary\",\"reason\":\"set-incomplete\",\"to\":\"fallback\",\"unit\":4}],\"switches_total\":1,\"transferred\":13607,\"uncounted\":2,\"units\":5},\"class\":\"reconstruct-session\",\"issued_at\":\"2026-09-27T12:00:00Z\",\"kind\":\"claim\",\"parent_receipt_hash\":null,\"seq\":0,\"sig\":\"19a1e695a7be7033967d5a9de523ba0402ebcbf240ace5e30a12907399848f080083e8a5e16dcaa5d2ef9c9a624ac3d3a6132ca705c3ed67bd13c576114d1e04\",\"signer_id\":\"did:example:sink\",\"signer_pubkey\":\"d759793bbc13a2819a827c76adb6fba8a49aee007f49f2d0992d99b825ad2c48\",\"subject\":\"64c0713cb176874607bf8670295242184b7868a9ff7c55554a5ae08de2c301c1\",\"subject_type\":\"object\"}", + "expected": { + "outcome": "reject", + "step": 4, + "reason": "session_leaf_sum" + } + }, + { + "name": "session_leaf_count_below_units", + "about": "fewer leaves than units: a unit counted as presented with no presentation", + "procedure": "claim", + "receipt": "{\"body\":{\"classical_declared\":700,\"classical_source\":\"wai2-table\",\"counted_discarded\":1904,\"counted_fallback\":0,\"counted_primary\":5607,\"deadline_us\":40000,\"decoders\":[{\"capability\":\"wai.video.int_hyper\",\"decoder\":\"builtin:wai@0.4.0\",\"leaves\":4,\"module_status\":null,\"path\":\"primary\",\"pin\":\"7b4371854df0aa1645ac6525b373387c0617b873d5a57748932ee0f386ea164b\",\"rendition\":0,\"tier\":\"decode-equivalence\",\"variant\":null},{\"capability\":\"wai.video.av1\",\"decoder\":\"builtin:wai@0.4.0\",\"leaves\":1,\"module_status\":null,\"path\":\"fallback\",\"pin\":null,\"rendition\":null,\"tier\":null,\"variant\":null},{\"capability\":\"wai.video.int_refine\",\"decoder\":\"builtin:wai@0.4.0\",\"leaves\":4,\"module_status\":null,\"path\":\"primary\",\"pin\":null,\"rendition\":null,\"tier\":null,\"variant\":null}],\"energy\":null,\"fallback_units\":1,\"framing\":\"registered\",\"host\":{\"build\":{\"profile\":\"release\",\"target\":\"aarch64-unknown-linux-gnu\",\"toolchain\":\"rustc 1.95.0\"},\"profile\":\"native-ffi\",\"target\":\"aarch64-unknown-linux-gnu\",\"threads\":4},\"leaf_count\":9,\"media\":\"video\",\"missed\":1,\"missed_units\":[{\"late_us\":1200,\"layers\":1,\"unit\":4}],\"output_root\":\"3cb2c68a7fe160511bd3fbbbd6945b5d54fac6b499e33769b1ea6828f04bb312\",\"primary_units\":9,\"receipt_bytes\":640,\"session_nonce\":\"57c5462dfdabd1b7bdd204d34ba33649c057eb535349f29f45eb8f8c7d4a7e7f\",\"stage_sets\":[{\"claim\":\"b636e8894207d2fe59add1e1cacf3b52ea760fccb4dc3f0abce79be90e871640\",\"first_unit\":0}],\"switches\":[{\"from\":\"primary\",\"reason\":\"set-incomplete\",\"to\":\"fallback\",\"unit\":4}],\"switches_total\":1,\"transferred\":13607,\"uncounted\":2,\"units\":10},\"class\":\"reconstruct-session\",\"issued_at\":\"2026-09-27T12:00:00Z\",\"kind\":\"claim\",\"parent_receipt_hash\":null,\"seq\":0,\"sig\":\"27fe8f42b9ebcb72352925b6fdd40c06b873ad183efd5040a67e5aa99fa1d525d3966f96cd9d8b5e766ea6638eb397fbb4e5df56566fd03abb90f4e46ac51400\",\"signer_id\":\"did:example:sink\",\"signer_pubkey\":\"d759793bbc13a2819a827c76adb6fba8a49aee007f49f2d0992d99b825ad2c48\",\"subject\":\"64c0713cb176874607bf8670295242184b7868a9ff7c55554a5ae08de2c301c1\",\"subject_type\":\"object\"}", + "expected": { + "outcome": "reject", + "step": 4, + "reason": "session_leaf_sum" + } + }, + { + "name": "session_no_units_with_leaves", + "about": "leaves with no unit presented", + "procedure": "claim", + "receipt": "{\"body\":{\"classical_declared\":700,\"classical_source\":\"wai2-table\",\"counted_discarded\":1904,\"counted_fallback\":0,\"counted_primary\":5607,\"deadline_us\":40000,\"decoders\":[{\"capability\":\"wai.video.int_hyper\",\"decoder\":\"builtin:wai@0.4.0\",\"leaves\":4,\"module_status\":null,\"path\":\"primary\",\"pin\":\"7b4371854df0aa1645ac6525b373387c0617b873d5a57748932ee0f386ea164b\",\"rendition\":0,\"tier\":\"decode-equivalence\",\"variant\":null},{\"capability\":\"wai.video.av1\",\"decoder\":\"builtin:wai@0.4.0\",\"leaves\":1,\"module_status\":null,\"path\":\"fallback\",\"pin\":null,\"rendition\":null,\"tier\":null,\"variant\":null},{\"capability\":\"wai.video.int_refine\",\"decoder\":\"builtin:wai@0.4.0\",\"leaves\":4,\"module_status\":null,\"path\":\"primary\",\"pin\":null,\"rendition\":null,\"tier\":null,\"variant\":null}],\"energy\":null,\"fallback_units\":0,\"framing\":\"registered\",\"host\":{\"build\":{\"profile\":\"release\",\"target\":\"aarch64-unknown-linux-gnu\",\"toolchain\":\"rustc 1.95.0\"},\"profile\":\"native-ffi\",\"target\":\"aarch64-unknown-linux-gnu\",\"threads\":4},\"leaf_count\":9,\"media\":\"video\",\"missed\":1,\"missed_units\":[{\"late_us\":1200,\"layers\":1,\"unit\":4}],\"output_root\":\"3cb2c68a7fe160511bd3fbbbd6945b5d54fac6b499e33769b1ea6828f04bb312\",\"primary_units\":0,\"receipt_bytes\":640,\"session_nonce\":\"57c5462dfdabd1b7bdd204d34ba33649c057eb535349f29f45eb8f8c7d4a7e7f\",\"stage_sets\":[{\"claim\":\"b636e8894207d2fe59add1e1cacf3b52ea760fccb4dc3f0abce79be90e871640\",\"first_unit\":0}],\"switches\":[{\"from\":\"primary\",\"reason\":\"set-incomplete\",\"to\":\"fallback\",\"unit\":4}],\"switches_total\":1,\"transferred\":13607,\"uncounted\":2,\"units\":0},\"class\":\"reconstruct-session\",\"issued_at\":\"2026-09-27T12:00:00Z\",\"kind\":\"claim\",\"parent_receipt_hash\":null,\"seq\":0,\"sig\":\"f17896a5e03058cdfdd725c0f775d2261e06991b3d4096e2e839df79367f0c1a2d4135d6f879004fa9910e74e76f34788a2a6d6da2a9cb92da737b195ef1de0a\",\"signer_id\":\"did:example:sink\",\"signer_pubkey\":\"d759793bbc13a2819a827c76adb6fba8a49aee007f49f2d0992d99b825ad2c48\",\"subject\":\"64c0713cb176874607bf8670295242184b7868a9ff7c55554a5ae08de2c301c1\",\"subject_type\":\"object\"}", + "expected": { + "outcome": "reject", + "step": 4, + "reason": "session_leaf_sum" + } + }, + { + "name": "session_root_absent", + "about": "presentations and no output root", + "procedure": "claim", + "receipt": "{\"body\":{\"classical_declared\":700,\"classical_source\":\"wai2-table\",\"counted_discarded\":1904,\"counted_fallback\":0,\"counted_primary\":5607,\"deadline_us\":40000,\"decoders\":[{\"capability\":\"wai.video.int_hyper\",\"decoder\":\"builtin:wai@0.4.0\",\"leaves\":4,\"module_status\":null,\"path\":\"primary\",\"pin\":\"7b4371854df0aa1645ac6525b373387c0617b873d5a57748932ee0f386ea164b\",\"rendition\":0,\"tier\":\"decode-equivalence\",\"variant\":null},{\"capability\":\"wai.video.av1\",\"decoder\":\"builtin:wai@0.4.0\",\"leaves\":1,\"module_status\":null,\"path\":\"fallback\",\"pin\":null,\"rendition\":null,\"tier\":null,\"variant\":null},{\"capability\":\"wai.video.int_refine\",\"decoder\":\"builtin:wai@0.4.0\",\"leaves\":4,\"module_status\":null,\"path\":\"primary\",\"pin\":null,\"rendition\":null,\"tier\":null,\"variant\":null}],\"energy\":null,\"fallback_units\":1,\"framing\":\"registered\",\"host\":{\"build\":{\"profile\":\"release\",\"target\":\"aarch64-unknown-linux-gnu\",\"toolchain\":\"rustc 1.95.0\"},\"profile\":\"native-ffi\",\"target\":\"aarch64-unknown-linux-gnu\",\"threads\":4},\"leaf_count\":9,\"media\":\"video\",\"missed\":1,\"missed_units\":[{\"late_us\":1200,\"layers\":1,\"unit\":4}],\"output_root\":null,\"primary_units\":4,\"receipt_bytes\":640,\"session_nonce\":\"57c5462dfdabd1b7bdd204d34ba33649c057eb535349f29f45eb8f8c7d4a7e7f\",\"stage_sets\":[{\"claim\":\"b636e8894207d2fe59add1e1cacf3b52ea760fccb4dc3f0abce79be90e871640\",\"first_unit\":0}],\"switches\":[{\"from\":\"primary\",\"reason\":\"set-incomplete\",\"to\":\"fallback\",\"unit\":4}],\"switches_total\":1,\"transferred\":13607,\"uncounted\":2,\"units\":5},\"class\":\"reconstruct-session\",\"issued_at\":\"2026-09-27T12:00:00Z\",\"kind\":\"claim\",\"parent_receipt_hash\":null,\"seq\":0,\"sig\":\"e1cd31b53b608ff382765b499ecfe732446dde7df7c8f00591fd0b6a1934224bbc7632adeee489a0e95c63d86476bbc8d592472e366742d3b3d0d7a9b1b47605\",\"signer_id\":\"did:example:sink\",\"signer_pubkey\":\"d759793bbc13a2819a827c76adb6fba8a49aee007f49f2d0992d99b825ad2c48\",\"subject\":\"64c0713cb176874607bf8670295242184b7868a9ff7c55554a5ae08de2c301c1\",\"subject_type\":\"object\"}", + "expected": { + "outcome": "reject", + "step": 4, + "reason": "session_root_presence" + } + }, + { + "name": "session_root_without_leaves", + "about": "an output root over no presentation", + "procedure": "claim", + "receipt": "{\"body\":{\"classical_declared\":700,\"classical_source\":\"wai2-table\",\"counted_discarded\":1904,\"counted_fallback\":0,\"counted_primary\":5607,\"deadline_us\":40000,\"decoders\":[],\"energy\":null,\"fallback_units\":0,\"framing\":\"registered\",\"host\":{\"build\":{\"profile\":\"release\",\"target\":\"aarch64-unknown-linux-gnu\",\"toolchain\":\"rustc 1.95.0\"},\"profile\":\"native-ffi\",\"target\":\"aarch64-unknown-linux-gnu\",\"threads\":4},\"leaf_count\":0,\"media\":\"video\",\"missed\":0,\"missed_units\":[],\"output_root\":\"3cb2c68a7fe160511bd3fbbbd6945b5d54fac6b499e33769b1ea6828f04bb312\",\"primary_units\":0,\"receipt_bytes\":640,\"session_nonce\":\"57c5462dfdabd1b7bdd204d34ba33649c057eb535349f29f45eb8f8c7d4a7e7f\",\"stage_sets\":[{\"claim\":\"b636e8894207d2fe59add1e1cacf3b52ea760fccb4dc3f0abce79be90e871640\",\"first_unit\":0}],\"switches\":[{\"from\":\"primary\",\"reason\":\"set-incomplete\",\"to\":\"fallback\",\"unit\":4}],\"switches_total\":1,\"transferred\":13607,\"uncounted\":2,\"units\":0},\"class\":\"reconstruct-session\",\"issued_at\":\"2026-09-27T12:00:00Z\",\"kind\":\"claim\",\"parent_receipt_hash\":null,\"seq\":0,\"sig\":\"f79c76bba02ac19514fd956f93cf98a3a11eed3481e8cb424900feaaef8e8a337224394d6971d2cbd431eeb77eb2a1918749cf4d81d417fb94c2e161c26cf50d\",\"signer_id\":\"did:example:sink\",\"signer_pubkey\":\"d759793bbc13a2819a827c76adb6fba8a49aee007f49f2d0992d99b825ad2c48\",\"subject\":\"64c0713cb176874607bf8670295242184b7868a9ff7c55554a5ae08de2c301c1\",\"subject_type\":\"object\"}", + "expected": { + "outcome": "reject", + "step": 4, + "reason": "session_root_presence" + } + }, + { + "name": "session_threads_not_power_of_two", + "about": "three decode workers, written as they are rather than rounded down to two", + "procedure": "claim", + "receipt": "{\"body\":{\"classical_declared\":700,\"classical_source\":\"wai2-table\",\"counted_discarded\":1904,\"counted_fallback\":0,\"counted_primary\":5607,\"deadline_us\":40000,\"decoders\":[{\"capability\":\"wai.video.int_hyper\",\"decoder\":\"builtin:wai@0.4.0\",\"leaves\":4,\"module_status\":null,\"path\":\"primary\",\"pin\":\"7b4371854df0aa1645ac6525b373387c0617b873d5a57748932ee0f386ea164b\",\"rendition\":0,\"tier\":\"decode-equivalence\",\"variant\":null},{\"capability\":\"wai.video.av1\",\"decoder\":\"builtin:wai@0.4.0\",\"leaves\":1,\"module_status\":null,\"path\":\"fallback\",\"pin\":null,\"rendition\":null,\"tier\":null,\"variant\":null},{\"capability\":\"wai.video.int_refine\",\"decoder\":\"builtin:wai@0.4.0\",\"leaves\":4,\"module_status\":null,\"path\":\"primary\",\"pin\":null,\"rendition\":null,\"tier\":null,\"variant\":null}],\"energy\":null,\"fallback_units\":1,\"framing\":\"registered\",\"host\":{\"build\":{\"profile\":\"release\",\"target\":\"aarch64-unknown-linux-gnu\",\"toolchain\":\"rustc 1.95.0\"},\"profile\":\"native-ffi\",\"target\":\"aarch64-unknown-linux-gnu\",\"threads\":3},\"leaf_count\":9,\"media\":\"video\",\"missed\":1,\"missed_units\":[{\"late_us\":1200,\"layers\":1,\"unit\":4}],\"output_root\":\"3cb2c68a7fe160511bd3fbbbd6945b5d54fac6b499e33769b1ea6828f04bb312\",\"primary_units\":4,\"receipt_bytes\":640,\"session_nonce\":\"57c5462dfdabd1b7bdd204d34ba33649c057eb535349f29f45eb8f8c7d4a7e7f\",\"stage_sets\":[{\"claim\":\"b636e8894207d2fe59add1e1cacf3b52ea760fccb4dc3f0abce79be90e871640\",\"first_unit\":0}],\"switches\":[{\"from\":\"primary\",\"reason\":\"set-incomplete\",\"to\":\"fallback\",\"unit\":4}],\"switches_total\":1,\"transferred\":13607,\"uncounted\":2,\"units\":5},\"class\":\"reconstruct-session\",\"issued_at\":\"2026-09-27T12:00:00Z\",\"kind\":\"claim\",\"parent_receipt_hash\":null,\"seq\":0,\"sig\":\"f99372f92f5765dfd45af947b0b1fbd7c3bc3f7183468a23faa9d57d1ce7e8a0121488e4d54bf359b57b29d1a8f56f36387a3344025603b6dcd59200bd3a1d0e\",\"signer_id\":\"did:example:sink\",\"signer_pubkey\":\"d759793bbc13a2819a827c76adb6fba8a49aee007f49f2d0992d99b825ad2c48\",\"subject\":\"64c0713cb176874607bf8670295242184b7868a9ff7c55554a5ae08de2c301c1\",\"subject_type\":\"object\"}", + "expected": { + "outcome": "reject", + "step": 4, + "reason": "session_host_malformed" + } + }, + { + "name": "session_decoder_no_version", + "about": "a builtin decoder with no version", + "procedure": "claim", + "receipt": "{\"body\":{\"classical_declared\":700,\"classical_source\":\"wai2-table\",\"counted_discarded\":1904,\"counted_fallback\":0,\"counted_primary\":5607,\"deadline_us\":40000,\"decoders\":[{\"capability\":\"wai.video.int_hyper\",\"decoder\":\"builtin:wai@0.4.0\",\"leaves\":4,\"module_status\":null,\"path\":\"primary\",\"pin\":\"7b4371854df0aa1645ac6525b373387c0617b873d5a57748932ee0f386ea164b\",\"rendition\":0,\"tier\":\"decode-equivalence\",\"variant\":null},{\"capability\":\"wai.video.av1\",\"decoder\":\"builtin:wai\",\"leaves\":1,\"module_status\":null,\"path\":\"fallback\",\"pin\":null,\"rendition\":null,\"tier\":null,\"variant\":null},{\"capability\":\"wai.video.int_refine\",\"decoder\":\"builtin:wai@0.4.0\",\"leaves\":4,\"module_status\":null,\"path\":\"primary\",\"pin\":null,\"rendition\":null,\"tier\":null,\"variant\":null}],\"energy\":null,\"fallback_units\":1,\"framing\":\"registered\",\"host\":{\"build\":{\"profile\":\"release\",\"target\":\"aarch64-unknown-linux-gnu\",\"toolchain\":\"rustc 1.95.0\"},\"profile\":\"native-ffi\",\"target\":\"aarch64-unknown-linux-gnu\",\"threads\":4},\"leaf_count\":9,\"media\":\"video\",\"missed\":1,\"missed_units\":[{\"late_us\":1200,\"layers\":1,\"unit\":4}],\"output_root\":\"3cb2c68a7fe160511bd3fbbbd6945b5d54fac6b499e33769b1ea6828f04bb312\",\"primary_units\":4,\"receipt_bytes\":640,\"session_nonce\":\"57c5462dfdabd1b7bdd204d34ba33649c057eb535349f29f45eb8f8c7d4a7e7f\",\"stage_sets\":[{\"claim\":\"b636e8894207d2fe59add1e1cacf3b52ea760fccb4dc3f0abce79be90e871640\",\"first_unit\":0}],\"switches\":[{\"from\":\"primary\",\"reason\":\"set-incomplete\",\"to\":\"fallback\",\"unit\":4}],\"switches_total\":1,\"transferred\":13607,\"uncounted\":2,\"units\":5},\"class\":\"reconstruct-session\",\"issued_at\":\"2026-09-27T12:00:00Z\",\"kind\":\"claim\",\"parent_receipt_hash\":null,\"seq\":0,\"sig\":\"4c0c16de7fc2ba944b10c2ea38418098705813f329a52282b80bc649fd7c97da705a1f685aaaf81c0f5dda35939a1262ee8d05003eef35d30544625aa7dab10d\",\"signer_id\":\"did:example:sink\",\"signer_pubkey\":\"d759793bbc13a2819a827c76adb6fba8a49aee007f49f2d0992d99b825ad2c48\",\"subject\":\"64c0713cb176874607bf8670295242184b7868a9ff7c55554a5ae08de2c301c1\",\"subject_type\":\"object\"}", + "expected": { + "outcome": "reject", + "step": 4, + "reason": "session_decoder_malformed" + } + }, + { + "name": "session_decoder_version_not_a_digit", + "about": "a builtin decoder whose version begins with a letter", + "procedure": "claim", + "receipt": "{\"body\":{\"classical_declared\":700,\"classical_source\":\"wai2-table\",\"counted_discarded\":1904,\"counted_fallback\":0,\"counted_primary\":5607,\"deadline_us\":40000,\"decoders\":[{\"capability\":\"wai.video.int_hyper\",\"decoder\":\"builtin:wai@0.4.0\",\"leaves\":4,\"module_status\":null,\"path\":\"primary\",\"pin\":\"7b4371854df0aa1645ac6525b373387c0617b873d5a57748932ee0f386ea164b\",\"rendition\":0,\"tier\":\"decode-equivalence\",\"variant\":null},{\"capability\":\"wai.video.av1\",\"decoder\":\"builtin:wai@v0.4.0\",\"leaves\":1,\"module_status\":null,\"path\":\"fallback\",\"pin\":null,\"rendition\":null,\"tier\":null,\"variant\":null},{\"capability\":\"wai.video.int_refine\",\"decoder\":\"builtin:wai@0.4.0\",\"leaves\":4,\"module_status\":null,\"path\":\"primary\",\"pin\":null,\"rendition\":null,\"tier\":null,\"variant\":null}],\"energy\":null,\"fallback_units\":1,\"framing\":\"registered\",\"host\":{\"build\":{\"profile\":\"release\",\"target\":\"aarch64-unknown-linux-gnu\",\"toolchain\":\"rustc 1.95.0\"},\"profile\":\"native-ffi\",\"target\":\"aarch64-unknown-linux-gnu\",\"threads\":4},\"leaf_count\":9,\"media\":\"video\",\"missed\":1,\"missed_units\":[{\"late_us\":1200,\"layers\":1,\"unit\":4}],\"output_root\":\"3cb2c68a7fe160511bd3fbbbd6945b5d54fac6b499e33769b1ea6828f04bb312\",\"primary_units\":4,\"receipt_bytes\":640,\"session_nonce\":\"57c5462dfdabd1b7bdd204d34ba33649c057eb535349f29f45eb8f8c7d4a7e7f\",\"stage_sets\":[{\"claim\":\"b636e8894207d2fe59add1e1cacf3b52ea760fccb4dc3f0abce79be90e871640\",\"first_unit\":0}],\"switches\":[{\"from\":\"primary\",\"reason\":\"set-incomplete\",\"to\":\"fallback\",\"unit\":4}],\"switches_total\":1,\"transferred\":13607,\"uncounted\":2,\"units\":5},\"class\":\"reconstruct-session\",\"issued_at\":\"2026-09-27T12:00:00Z\",\"kind\":\"claim\",\"parent_receipt_hash\":null,\"seq\":0,\"sig\":\"d663f2941f6827f84c103a9f5e4c718ae6ea9631b213f5513b4033ba94943c3b6af852874c46ad53ee93e9ae41e281d7cd284249b8546e5e9d630793d8489904\",\"signer_id\":\"did:example:sink\",\"signer_pubkey\":\"d759793bbc13a2819a827c76adb6fba8a49aee007f49f2d0992d99b825ad2c48\",\"subject\":\"64c0713cb176874607bf8670295242184b7868a9ff7c55554a5ae08de2c301c1\",\"subject_type\":\"object\"}", + "expected": { + "outcome": "reject", + "step": 4, + "reason": "session_decoder_malformed" + } + }, + { + "name": "session_decoder_module_short_digest", + "about": "a module decoder whose digest is 63 digits", + "procedure": "claim", + "receipt": "{\"body\":{\"classical_declared\":700,\"classical_source\":\"wai2-table\",\"counted_discarded\":1904,\"counted_fallback\":0,\"counted_primary\":5607,\"deadline_us\":40000,\"decoders\":[{\"capability\":\"wai.video.int_hyper\",\"decoder\":\"builtin:wai@0.4.0\",\"leaves\":4,\"module_status\":null,\"path\":\"primary\",\"pin\":\"7b4371854df0aa1645ac6525b373387c0617b873d5a57748932ee0f386ea164b\",\"rendition\":0,\"tier\":\"decode-equivalence\",\"variant\":null},{\"capability\":\"wai.video.av1\",\"decoder\":\"module:sha256:7b4371854df0aa1645ac6525b373387c0617b873d5a57748932ee0f386ea164\",\"leaves\":1,\"module_status\":\"pinned\",\"path\":\"fallback\",\"pin\":null,\"rendition\":null,\"tier\":null,\"variant\":null},{\"capability\":\"wai.video.int_refine\",\"decoder\":\"builtin:wai@0.4.0\",\"leaves\":4,\"module_status\":null,\"path\":\"primary\",\"pin\":null,\"rendition\":null,\"tier\":null,\"variant\":null}],\"energy\":null,\"fallback_units\":1,\"framing\":\"registered\",\"host\":{\"build\":{\"profile\":\"release\",\"target\":\"aarch64-unknown-linux-gnu\",\"toolchain\":\"rustc 1.95.0\"},\"profile\":\"native-ffi\",\"target\":\"aarch64-unknown-linux-gnu\",\"threads\":4},\"leaf_count\":9,\"media\":\"video\",\"missed\":1,\"missed_units\":[{\"late_us\":1200,\"layers\":1,\"unit\":4}],\"output_root\":\"3cb2c68a7fe160511bd3fbbbd6945b5d54fac6b499e33769b1ea6828f04bb312\",\"primary_units\":4,\"receipt_bytes\":640,\"session_nonce\":\"57c5462dfdabd1b7bdd204d34ba33649c057eb535349f29f45eb8f8c7d4a7e7f\",\"stage_sets\":[{\"claim\":\"b636e8894207d2fe59add1e1cacf3b52ea760fccb4dc3f0abce79be90e871640\",\"first_unit\":0}],\"switches\":[{\"from\":\"primary\",\"reason\":\"set-incomplete\",\"to\":\"fallback\",\"unit\":4}],\"switches_total\":1,\"transferred\":13607,\"uncounted\":2,\"units\":5},\"class\":\"reconstruct-session\",\"issued_at\":\"2026-09-27T12:00:00Z\",\"kind\":\"claim\",\"parent_receipt_hash\":null,\"seq\":0,\"sig\":\"c9d8fbd740a62c17515674bcaf5f0bd45f4df312303e4b16083f3b51a3ac01cff3241fefb15faafed9b7e1534c27599cd565b12192fa5887e55490c42481520b\",\"signer_id\":\"did:example:sink\",\"signer_pubkey\":\"d759793bbc13a2819a827c76adb6fba8a49aee007f49f2d0992d99b825ad2c48\",\"subject\":\"64c0713cb176874607bf8670295242184b7868a9ff7c55554a5ae08de2c301c1\",\"subject_type\":\"object\"}", + "expected": { + "outcome": "reject", + "step": 4, + "reason": "session_decoder_malformed" + } + }, + { + "name": "session_decoder_tier_without_pin", + "about": "a tier with no pin verified", + "procedure": "claim", + "receipt": "{\"body\":{\"classical_declared\":700,\"classical_source\":\"wai2-table\",\"counted_discarded\":1904,\"counted_fallback\":0,\"counted_primary\":5607,\"deadline_us\":40000,\"decoders\":[{\"capability\":\"wai.video.int_hyper\",\"decoder\":\"builtin:wai@0.4.0\",\"leaves\":4,\"module_status\":null,\"path\":\"primary\",\"pin\":\"7b4371854df0aa1645ac6525b373387c0617b873d5a57748932ee0f386ea164b\",\"rendition\":0,\"tier\":\"decode-equivalence\",\"variant\":null},{\"capability\":\"wai.video.av1\",\"decoder\":\"builtin:wai@0.4.0\",\"leaves\":1,\"module_status\":null,\"path\":\"fallback\",\"pin\":null,\"rendition\":null,\"tier\":\"none\",\"variant\":null},{\"capability\":\"wai.video.int_refine\",\"decoder\":\"builtin:wai@0.4.0\",\"leaves\":4,\"module_status\":null,\"path\":\"primary\",\"pin\":null,\"rendition\":null,\"tier\":null,\"variant\":null}],\"energy\":null,\"fallback_units\":1,\"framing\":\"registered\",\"host\":{\"build\":{\"profile\":\"release\",\"target\":\"aarch64-unknown-linux-gnu\",\"toolchain\":\"rustc 1.95.0\"},\"profile\":\"native-ffi\",\"target\":\"aarch64-unknown-linux-gnu\",\"threads\":4},\"leaf_count\":9,\"media\":\"video\",\"missed\":1,\"missed_units\":[{\"late_us\":1200,\"layers\":1,\"unit\":4}],\"output_root\":\"3cb2c68a7fe160511bd3fbbbd6945b5d54fac6b499e33769b1ea6828f04bb312\",\"primary_units\":4,\"receipt_bytes\":640,\"session_nonce\":\"57c5462dfdabd1b7bdd204d34ba33649c057eb535349f29f45eb8f8c7d4a7e7f\",\"stage_sets\":[{\"claim\":\"b636e8894207d2fe59add1e1cacf3b52ea760fccb4dc3f0abce79be90e871640\",\"first_unit\":0}],\"switches\":[{\"from\":\"primary\",\"reason\":\"set-incomplete\",\"to\":\"fallback\",\"unit\":4}],\"switches_total\":1,\"transferred\":13607,\"uncounted\":2,\"units\":5},\"class\":\"reconstruct-session\",\"issued_at\":\"2026-09-27T12:00:00Z\",\"kind\":\"claim\",\"parent_receipt_hash\":null,\"seq\":0,\"sig\":\"695a006d7999728586e4f633eb6744631eb44feac4abfa06a8dee392e76d6bd14c51de57b9451fc4e879e74a3ea4e6dc2ab914210d5d6744a465336da33dcd05\",\"signer_id\":\"did:example:sink\",\"signer_pubkey\":\"d759793bbc13a2819a827c76adb6fba8a49aee007f49f2d0992d99b825ad2c48\",\"subject\":\"64c0713cb176874607bf8670295242184b7868a9ff7c55554a5ae08de2c301c1\",\"subject_type\":\"object\"}", + "expected": { + "outcome": "reject", + "step": 4, + "reason": "session_decoder_malformed" + } + }, + { + "name": "session_decoder_unknown_tier", + "about": "a pin whose tier is not a tier of SPEC 3.1", + "procedure": "claim", + "receipt": "{\"body\":{\"classical_declared\":700,\"classical_source\":\"wai2-table\",\"counted_discarded\":1904,\"counted_fallback\":0,\"counted_primary\":5607,\"deadline_us\":40000,\"decoders\":[{\"capability\":\"wai.video.int_hyper\",\"decoder\":\"builtin:wai@0.4.0\",\"leaves\":4,\"module_status\":null,\"path\":\"primary\",\"pin\":\"7b4371854df0aa1645ac6525b373387c0617b873d5a57748932ee0f386ea164b\",\"rendition\":0,\"tier\":\"bit-exact\",\"variant\":null},{\"capability\":\"wai.video.av1\",\"decoder\":\"builtin:wai@0.4.0\",\"leaves\":1,\"module_status\":null,\"path\":\"fallback\",\"pin\":null,\"rendition\":null,\"tier\":null,\"variant\":null},{\"capability\":\"wai.video.int_refine\",\"decoder\":\"builtin:wai@0.4.0\",\"leaves\":4,\"module_status\":null,\"path\":\"primary\",\"pin\":null,\"rendition\":null,\"tier\":null,\"variant\":null}],\"energy\":null,\"fallback_units\":1,\"framing\":\"registered\",\"host\":{\"build\":{\"profile\":\"release\",\"target\":\"aarch64-unknown-linux-gnu\",\"toolchain\":\"rustc 1.95.0\"},\"profile\":\"native-ffi\",\"target\":\"aarch64-unknown-linux-gnu\",\"threads\":4},\"leaf_count\":9,\"media\":\"video\",\"missed\":1,\"missed_units\":[{\"late_us\":1200,\"layers\":1,\"unit\":4}],\"output_root\":\"3cb2c68a7fe160511bd3fbbbd6945b5d54fac6b499e33769b1ea6828f04bb312\",\"primary_units\":4,\"receipt_bytes\":640,\"session_nonce\":\"57c5462dfdabd1b7bdd204d34ba33649c057eb535349f29f45eb8f8c7d4a7e7f\",\"stage_sets\":[{\"claim\":\"b636e8894207d2fe59add1e1cacf3b52ea760fccb4dc3f0abce79be90e871640\",\"first_unit\":0}],\"switches\":[{\"from\":\"primary\",\"reason\":\"set-incomplete\",\"to\":\"fallback\",\"unit\":4}],\"switches_total\":1,\"transferred\":13607,\"uncounted\":2,\"units\":5},\"class\":\"reconstruct-session\",\"issued_at\":\"2026-09-27T12:00:00Z\",\"kind\":\"claim\",\"parent_receipt_hash\":null,\"seq\":0,\"sig\":\"79d54c222a24aa717b1aaba701afd4ecb6c4d19f91e46303d669ae5db1c45f17c26fc8a509280c99c5d673192298fc1d8603a4a38d6c4939d9f5bd551ba8f10a\",\"signer_id\":\"did:example:sink\",\"signer_pubkey\":\"d759793bbc13a2819a827c76adb6fba8a49aee007f49f2d0992d99b825ad2c48\",\"subject\":\"64c0713cb176874607bf8670295242184b7868a9ff7c55554a5ae08de2c301c1\",\"subject_type\":\"object\"}", + "expected": { + "outcome": "reject", + "step": 4, + "reason": "session_decoder_malformed" + } + }, + { + "name": "session_decoder_builtin_with_module_status", + "about": "a module status on a builtin decoder", + "procedure": "claim", + "receipt": "{\"body\":{\"classical_declared\":700,\"classical_source\":\"wai2-table\",\"counted_discarded\":1904,\"counted_fallback\":0,\"counted_primary\":5607,\"deadline_us\":40000,\"decoders\":[{\"capability\":\"wai.video.int_hyper\",\"decoder\":\"builtin:wai@0.4.0\",\"leaves\":4,\"module_status\":null,\"path\":\"primary\",\"pin\":\"7b4371854df0aa1645ac6525b373387c0617b873d5a57748932ee0f386ea164b\",\"rendition\":0,\"tier\":\"decode-equivalence\",\"variant\":null},{\"capability\":\"wai.video.av1\",\"decoder\":\"builtin:wai@0.4.0\",\"leaves\":1,\"module_status\":\"fetched\",\"path\":\"fallback\",\"pin\":null,\"rendition\":null,\"tier\":null,\"variant\":null},{\"capability\":\"wai.video.int_refine\",\"decoder\":\"builtin:wai@0.4.0\",\"leaves\":4,\"module_status\":null,\"path\":\"primary\",\"pin\":null,\"rendition\":null,\"tier\":null,\"variant\":null}],\"energy\":null,\"fallback_units\":1,\"framing\":\"registered\",\"host\":{\"build\":{\"profile\":\"release\",\"target\":\"aarch64-unknown-linux-gnu\",\"toolchain\":\"rustc 1.95.0\"},\"profile\":\"native-ffi\",\"target\":\"aarch64-unknown-linux-gnu\",\"threads\":4},\"leaf_count\":9,\"media\":\"video\",\"missed\":1,\"missed_units\":[{\"late_us\":1200,\"layers\":1,\"unit\":4}],\"output_root\":\"3cb2c68a7fe160511bd3fbbbd6945b5d54fac6b499e33769b1ea6828f04bb312\",\"primary_units\":4,\"receipt_bytes\":640,\"session_nonce\":\"57c5462dfdabd1b7bdd204d34ba33649c057eb535349f29f45eb8f8c7d4a7e7f\",\"stage_sets\":[{\"claim\":\"b636e8894207d2fe59add1e1cacf3b52ea760fccb4dc3f0abce79be90e871640\",\"first_unit\":0}],\"switches\":[{\"from\":\"primary\",\"reason\":\"set-incomplete\",\"to\":\"fallback\",\"unit\":4}],\"switches_total\":1,\"transferred\":13607,\"uncounted\":2,\"units\":5},\"class\":\"reconstruct-session\",\"issued_at\":\"2026-09-27T12:00:00Z\",\"kind\":\"claim\",\"parent_receipt_hash\":null,\"seq\":0,\"sig\":\"040ec8f7757ee72ec9dec34427ae971867f057e3e12b9986ddccb9f13983965e54da1c417e01ae888c2274d1210d255b49eade36068442dba6040fb7e9dc4c09\",\"signer_id\":\"did:example:sink\",\"signer_pubkey\":\"d759793bbc13a2819a827c76adb6fba8a49aee007f49f2d0992d99b825ad2c48\",\"subject\":\"64c0713cb176874607bf8670295242184b7868a9ff7c55554a5ae08de2c301c1\",\"subject_type\":\"object\"}", + "expected": { + "outcome": "reject", + "step": 4, + "reason": "session_decoder_malformed" + } + }, + { + "name": "session_decoder_module_without_status", + "about": "a module decoder with no module status", + "procedure": "claim", + "receipt": "{\"body\":{\"classical_declared\":700,\"classical_source\":\"wai2-table\",\"counted_discarded\":1904,\"counted_fallback\":0,\"counted_primary\":5607,\"deadline_us\":40000,\"decoders\":[{\"capability\":\"wai.video.int_hyper\",\"decoder\":\"builtin:wai@0.4.0\",\"leaves\":4,\"module_status\":null,\"path\":\"primary\",\"pin\":\"7b4371854df0aa1645ac6525b373387c0617b873d5a57748932ee0f386ea164b\",\"rendition\":0,\"tier\":\"decode-equivalence\",\"variant\":null},{\"capability\":\"wai.video.av1\",\"decoder\":\"module:sha256:7b4371854df0aa1645ac6525b373387c0617b873d5a57748932ee0f386ea164b\",\"leaves\":1,\"module_status\":null,\"path\":\"fallback\",\"pin\":null,\"rendition\":null,\"tier\":null,\"variant\":null},{\"capability\":\"wai.video.int_refine\",\"decoder\":\"builtin:wai@0.4.0\",\"leaves\":4,\"module_status\":null,\"path\":\"primary\",\"pin\":null,\"rendition\":null,\"tier\":null,\"variant\":null}],\"energy\":null,\"fallback_units\":1,\"framing\":\"registered\",\"host\":{\"build\":{\"profile\":\"release\",\"target\":\"aarch64-unknown-linux-gnu\",\"toolchain\":\"rustc 1.95.0\"},\"profile\":\"native-ffi\",\"target\":\"aarch64-unknown-linux-gnu\",\"threads\":4},\"leaf_count\":9,\"media\":\"video\",\"missed\":1,\"missed_units\":[{\"late_us\":1200,\"layers\":1,\"unit\":4}],\"output_root\":\"3cb2c68a7fe160511bd3fbbbd6945b5d54fac6b499e33769b1ea6828f04bb312\",\"primary_units\":4,\"receipt_bytes\":640,\"session_nonce\":\"57c5462dfdabd1b7bdd204d34ba33649c057eb535349f29f45eb8f8c7d4a7e7f\",\"stage_sets\":[{\"claim\":\"b636e8894207d2fe59add1e1cacf3b52ea760fccb4dc3f0abce79be90e871640\",\"first_unit\":0}],\"switches\":[{\"from\":\"primary\",\"reason\":\"set-incomplete\",\"to\":\"fallback\",\"unit\":4}],\"switches_total\":1,\"transferred\":13607,\"uncounted\":2,\"units\":5},\"class\":\"reconstruct-session\",\"issued_at\":\"2026-09-27T12:00:00Z\",\"kind\":\"claim\",\"parent_receipt_hash\":null,\"seq\":0,\"sig\":\"05aff18486b1e6c74e40011c1b081a59b38f100f35013581b61b50374d1cb7a94bf91b4afa2ed5f7da2cdf306d538ff5ad161363369073b87075bc8e75fb1b0d\",\"signer_id\":\"did:example:sink\",\"signer_pubkey\":\"d759793bbc13a2819a827c76adb6fba8a49aee007f49f2d0992d99b825ad2c48\",\"subject\":\"64c0713cb176874607bf8670295242184b7868a9ff7c55554a5ae08de2c301c1\",\"subject_type\":\"object\"}", + "expected": { + "outcome": "reject", + "step": 4, + "reason": "session_decoder_malformed" + } + }, + { + "name": "session_decoder_rendition_past_u16", + "about": "a rendition index past 65535", + "procedure": "claim", + "receipt": "{\"body\":{\"classical_declared\":700,\"classical_source\":\"wai2-table\",\"counted_discarded\":1904,\"counted_fallback\":0,\"counted_primary\":5607,\"deadline_us\":40000,\"decoders\":[{\"capability\":\"wai.video.int_hyper\",\"decoder\":\"builtin:wai@0.4.0\",\"leaves\":4,\"module_status\":null,\"path\":\"primary\",\"pin\":\"7b4371854df0aa1645ac6525b373387c0617b873d5a57748932ee0f386ea164b\",\"rendition\":65536,\"tier\":\"decode-equivalence\",\"variant\":null},{\"capability\":\"wai.video.av1\",\"decoder\":\"builtin:wai@0.4.0\",\"leaves\":1,\"module_status\":null,\"path\":\"fallback\",\"pin\":null,\"rendition\":null,\"tier\":null,\"variant\":null},{\"capability\":\"wai.video.int_refine\",\"decoder\":\"builtin:wai@0.4.0\",\"leaves\":4,\"module_status\":null,\"path\":\"primary\",\"pin\":null,\"rendition\":null,\"tier\":null,\"variant\":null}],\"energy\":null,\"fallback_units\":1,\"framing\":\"registered\",\"host\":{\"build\":{\"profile\":\"release\",\"target\":\"aarch64-unknown-linux-gnu\",\"toolchain\":\"rustc 1.95.0\"},\"profile\":\"native-ffi\",\"target\":\"aarch64-unknown-linux-gnu\",\"threads\":4},\"leaf_count\":9,\"media\":\"video\",\"missed\":1,\"missed_units\":[{\"late_us\":1200,\"layers\":1,\"unit\":4}],\"output_root\":\"3cb2c68a7fe160511bd3fbbbd6945b5d54fac6b499e33769b1ea6828f04bb312\",\"primary_units\":4,\"receipt_bytes\":640,\"session_nonce\":\"57c5462dfdabd1b7bdd204d34ba33649c057eb535349f29f45eb8f8c7d4a7e7f\",\"stage_sets\":[{\"claim\":\"b636e8894207d2fe59add1e1cacf3b52ea760fccb4dc3f0abce79be90e871640\",\"first_unit\":0}],\"switches\":[{\"from\":\"primary\",\"reason\":\"set-incomplete\",\"to\":\"fallback\",\"unit\":4}],\"switches_total\":1,\"transferred\":13607,\"uncounted\":2,\"units\":5},\"class\":\"reconstruct-session\",\"issued_at\":\"2026-09-27T12:00:00Z\",\"kind\":\"claim\",\"parent_receipt_hash\":null,\"seq\":0,\"sig\":\"28e79ef1717fb5f4beef683539b161f70fd4b0c903aa791587b5a6a8f635f78c8da535ec92ddf9f41af0399c10d121010f5b8416f3dcad379d1e9c2c32069f04\",\"signer_id\":\"did:example:sink\",\"signer_pubkey\":\"d759793bbc13a2819a827c76adb6fba8a49aee007f49f2d0992d99b825ad2c48\",\"subject\":\"64c0713cb176874607bf8670295242184b7868a9ff7c55554a5ae08de2c301c1\",\"subject_type\":\"object\"}", + "expected": { + "outcome": "reject", + "step": 4, + "reason": "session_decoder_malformed" + } + }, + { + "name": "session_decoder_twice", + "about": "two entries that differ only in their leaves", + "procedure": "claim", + "receipt": "{\"body\":{\"classical_declared\":700,\"classical_source\":\"wai2-table\",\"counted_discarded\":1904,\"counted_fallback\":0,\"counted_primary\":5607,\"deadline_us\":40000,\"decoders\":[{\"capability\":\"wai.video.int_hyper\",\"decoder\":\"builtin:wai@0.4.0\",\"leaves\":4,\"module_status\":null,\"path\":\"primary\",\"pin\":\"7b4371854df0aa1645ac6525b373387c0617b873d5a57748932ee0f386ea164b\",\"rendition\":0,\"tier\":\"decode-equivalence\",\"variant\":null},{\"capability\":\"wai.video.av1\",\"decoder\":\"builtin:wai@0.4.0\",\"leaves\":1,\"module_status\":null,\"path\":\"fallback\",\"pin\":null,\"rendition\":null,\"tier\":null,\"variant\":null},{\"capability\":\"wai.video.int_refine\",\"decoder\":\"builtin:wai@0.4.0\",\"leaves\":3,\"module_status\":null,\"path\":\"primary\",\"pin\":null,\"rendition\":null,\"tier\":null,\"variant\":null},{\"capability\":\"wai.video.int_refine\",\"decoder\":\"builtin:wai@0.4.0\",\"leaves\":1,\"module_status\":null,\"path\":\"primary\",\"pin\":null,\"rendition\":null,\"tier\":null,\"variant\":null}],\"energy\":null,\"fallback_units\":1,\"framing\":\"registered\",\"host\":{\"build\":{\"profile\":\"release\",\"target\":\"aarch64-unknown-linux-gnu\",\"toolchain\":\"rustc 1.95.0\"},\"profile\":\"native-ffi\",\"target\":\"aarch64-unknown-linux-gnu\",\"threads\":4},\"leaf_count\":9,\"media\":\"video\",\"missed\":1,\"missed_units\":[{\"late_us\":1200,\"layers\":1,\"unit\":4}],\"output_root\":\"3cb2c68a7fe160511bd3fbbbd6945b5d54fac6b499e33769b1ea6828f04bb312\",\"primary_units\":4,\"receipt_bytes\":640,\"session_nonce\":\"57c5462dfdabd1b7bdd204d34ba33649c057eb535349f29f45eb8f8c7d4a7e7f\",\"stage_sets\":[{\"claim\":\"b636e8894207d2fe59add1e1cacf3b52ea760fccb4dc3f0abce79be90e871640\",\"first_unit\":0}],\"switches\":[{\"from\":\"primary\",\"reason\":\"set-incomplete\",\"to\":\"fallback\",\"unit\":4}],\"switches_total\":1,\"transferred\":13607,\"uncounted\":2,\"units\":5},\"class\":\"reconstruct-session\",\"issued_at\":\"2026-09-27T12:00:00Z\",\"kind\":\"claim\",\"parent_receipt_hash\":null,\"seq\":0,\"sig\":\"4de4c56ff100f7d7dfdf949cad8eacc7b174d36f67ddf06edfd42371d2a9499dfec7cd23e3a578a8955b81a1c1aa82e376807c3fc34b4b915904ff6d39c2a105\",\"signer_id\":\"did:example:sink\",\"signer_pubkey\":\"d759793bbc13a2819a827c76adb6fba8a49aee007f49f2d0992d99b825ad2c48\",\"subject\":\"64c0713cb176874607bf8670295242184b7868a9ff7c55554a5ae08de2c301c1\",\"subject_type\":\"object\"}", + "expected": { + "outcome": "reject", + "step": 4, + "reason": "session_decoder_malformed" + } + }, + { + "name": "session_decoder_no_leaves", + "about": "an entry through which nothing was presented", + "procedure": "claim", + "receipt": "{\"body\":{\"classical_declared\":700,\"classical_source\":\"wai2-table\",\"counted_discarded\":1904,\"counted_fallback\":0,\"counted_primary\":5607,\"deadline_us\":40000,\"decoders\":[{\"capability\":\"wai.video.int_hyper\",\"decoder\":\"builtin:wai@0.4.0\",\"leaves\":4,\"module_status\":null,\"path\":\"primary\",\"pin\":\"7b4371854df0aa1645ac6525b373387c0617b873d5a57748932ee0f386ea164b\",\"rendition\":0,\"tier\":\"decode-equivalence\",\"variant\":null},{\"capability\":\"wai.video.av1\",\"decoder\":\"builtin:wai@0.4.0\",\"leaves\":1,\"module_status\":null,\"path\":\"fallback\",\"pin\":null,\"rendition\":null,\"tier\":null,\"variant\":null},{\"capability\":\"wai.video.int_refine\",\"decoder\":\"builtin:wai@0.4.0\",\"leaves\":4,\"module_status\":null,\"path\":\"primary\",\"pin\":null,\"rendition\":null,\"tier\":null,\"variant\":null},{\"capability\":\"wai.video.avc\",\"decoder\":\"builtin:wai@0.4.0\",\"leaves\":0,\"module_status\":null,\"path\":\"fallback\",\"pin\":null,\"rendition\":null,\"tier\":null,\"variant\":null}],\"energy\":null,\"fallback_units\":1,\"framing\":\"registered\",\"host\":{\"build\":{\"profile\":\"release\",\"target\":\"aarch64-unknown-linux-gnu\",\"toolchain\":\"rustc 1.95.0\"},\"profile\":\"native-ffi\",\"target\":\"aarch64-unknown-linux-gnu\",\"threads\":4},\"leaf_count\":9,\"media\":\"video\",\"missed\":1,\"missed_units\":[{\"late_us\":1200,\"layers\":1,\"unit\":4}],\"output_root\":\"3cb2c68a7fe160511bd3fbbbd6945b5d54fac6b499e33769b1ea6828f04bb312\",\"primary_units\":4,\"receipt_bytes\":640,\"session_nonce\":\"57c5462dfdabd1b7bdd204d34ba33649c057eb535349f29f45eb8f8c7d4a7e7f\",\"stage_sets\":[{\"claim\":\"b636e8894207d2fe59add1e1cacf3b52ea760fccb4dc3f0abce79be90e871640\",\"first_unit\":0}],\"switches\":[{\"from\":\"primary\",\"reason\":\"set-incomplete\",\"to\":\"fallback\",\"unit\":4}],\"switches_total\":1,\"transferred\":13607,\"uncounted\":2,\"units\":5},\"class\":\"reconstruct-session\",\"issued_at\":\"2026-09-27T12:00:00Z\",\"kind\":\"claim\",\"parent_receipt_hash\":null,\"seq\":0,\"sig\":\"25705d6c93ff7aadcf621901fcc2e4bedbe7d8175317f807cfb540ffa300c477f06073c14d73e6c178c7d9138d099104b87faa548ad3ae7465658f5cbdd61d03\",\"signer_id\":\"did:example:sink\",\"signer_pubkey\":\"d759793bbc13a2819a827c76adb6fba8a49aee007f49f2d0992d99b825ad2c48\",\"subject\":\"64c0713cb176874607bf8670295242184b7868a9ff7c55554a5ae08de2c301c1\",\"subject_type\":\"object\"}", + "expected": { + "outcome": "reject", + "step": 4, + "reason": "session_decoder_malformed" + } + }, + { + "name": "session_tier_exceeds_class", + "about": "a refinement capability's entry pinned at decode-equivalence, above its class's tier", + "procedure": "claim", + "receipt": "{\"body\":{\"classical_declared\":700,\"classical_source\":\"wai2-table\",\"counted_discarded\":1904,\"counted_fallback\":0,\"counted_primary\":5607,\"deadline_us\":40000,\"decoders\":[{\"capability\":\"wai.video.int_hyper\",\"decoder\":\"builtin:wai@0.4.0\",\"leaves\":4,\"module_status\":null,\"path\":\"primary\",\"pin\":\"7b4371854df0aa1645ac6525b373387c0617b873d5a57748932ee0f386ea164b\",\"rendition\":0,\"tier\":\"decode-equivalence\",\"variant\":null},{\"capability\":\"wai.video.av1\",\"decoder\":\"builtin:wai@0.4.0\",\"leaves\":1,\"module_status\":null,\"path\":\"fallback\",\"pin\":null,\"rendition\":null,\"tier\":null,\"variant\":null},{\"capability\":\"wai.video.int_refine\",\"decoder\":\"builtin:wai@0.4.0\",\"leaves\":4,\"module_status\":null,\"path\":\"primary\",\"pin\":\"7b4371854df0aa1645ac6525b373387c0617b873d5a57748932ee0f386ea164b\",\"rendition\":null,\"tier\":\"decode-equivalence\",\"variant\":null}],\"energy\":null,\"fallback_units\":1,\"framing\":\"registered\",\"host\":{\"build\":{\"profile\":\"release\",\"target\":\"aarch64-unknown-linux-gnu\",\"toolchain\":\"rustc 1.95.0\"},\"profile\":\"native-ffi\",\"target\":\"aarch64-unknown-linux-gnu\",\"threads\":4},\"leaf_count\":9,\"media\":\"video\",\"missed\":1,\"missed_units\":[{\"late_us\":1200,\"layers\":1,\"unit\":4}],\"output_root\":\"3cb2c68a7fe160511bd3fbbbd6945b5d54fac6b499e33769b1ea6828f04bb312\",\"primary_units\":4,\"receipt_bytes\":640,\"session_nonce\":\"57c5462dfdabd1b7bdd204d34ba33649c057eb535349f29f45eb8f8c7d4a7e7f\",\"stage_sets\":[{\"claim\":\"b636e8894207d2fe59add1e1cacf3b52ea760fccb4dc3f0abce79be90e871640\",\"first_unit\":0}],\"switches\":[{\"from\":\"primary\",\"reason\":\"set-incomplete\",\"to\":\"fallback\",\"unit\":4}],\"switches_total\":1,\"transferred\":13607,\"uncounted\":2,\"units\":5},\"class\":\"reconstruct-session\",\"issued_at\":\"2026-09-27T12:00:00Z\",\"kind\":\"claim\",\"parent_receipt_hash\":null,\"seq\":0,\"sig\":\"df762899b56dd6cedebe8e412fe962bf2789bc6ab0447ce938702c6799273c67c288729c483acb7d4d37e4daa0f091c4ba3fcc50e87f9ad16a6f02ab7cb1eb0b\",\"signer_id\":\"did:example:sink\",\"signer_pubkey\":\"d759793bbc13a2819a827c76adb6fba8a49aee007f49f2d0992d99b825ad2c48\",\"subject\":\"64c0713cb176874607bf8670295242184b7868a9ff7c55554a5ae08de2c301c1\",\"subject_type\":\"object\"}", + "expected": { + "outcome": "reject", + "step": 4, + "reason": "session_tier_exceeds_class" + } + }, + { + "name": "session_switch_to_same_path", + "about": "a switch from the primary path to the primary path", + "procedure": "claim", + "receipt": "{\"body\":{\"classical_declared\":700,\"classical_source\":\"wai2-table\",\"counted_discarded\":1904,\"counted_fallback\":0,\"counted_primary\":5607,\"deadline_us\":40000,\"decoders\":[{\"capability\":\"wai.video.int_hyper\",\"decoder\":\"builtin:wai@0.4.0\",\"leaves\":4,\"module_status\":null,\"path\":\"primary\",\"pin\":\"7b4371854df0aa1645ac6525b373387c0617b873d5a57748932ee0f386ea164b\",\"rendition\":0,\"tier\":\"decode-equivalence\",\"variant\":null},{\"capability\":\"wai.video.av1\",\"decoder\":\"builtin:wai@0.4.0\",\"leaves\":1,\"module_status\":null,\"path\":\"fallback\",\"pin\":null,\"rendition\":null,\"tier\":null,\"variant\":null},{\"capability\":\"wai.video.int_refine\",\"decoder\":\"builtin:wai@0.4.0\",\"leaves\":4,\"module_status\":null,\"path\":\"primary\",\"pin\":null,\"rendition\":null,\"tier\":null,\"variant\":null}],\"energy\":null,\"fallback_units\":1,\"framing\":\"registered\",\"host\":{\"build\":{\"profile\":\"release\",\"target\":\"aarch64-unknown-linux-gnu\",\"toolchain\":\"rustc 1.95.0\"},\"profile\":\"native-ffi\",\"target\":\"aarch64-unknown-linux-gnu\",\"threads\":4},\"leaf_count\":9,\"media\":\"video\",\"missed\":1,\"missed_units\":[{\"late_us\":1200,\"layers\":1,\"unit\":4}],\"output_root\":\"3cb2c68a7fe160511bd3fbbbd6945b5d54fac6b499e33769b1ea6828f04bb312\",\"primary_units\":4,\"receipt_bytes\":640,\"session_nonce\":\"57c5462dfdabd1b7bdd204d34ba33649c057eb535349f29f45eb8f8c7d4a7e7f\",\"stage_sets\":[{\"claim\":\"b636e8894207d2fe59add1e1cacf3b52ea760fccb4dc3f0abce79be90e871640\",\"first_unit\":0}],\"switches\":[{\"from\":\"primary\",\"reason\":\"set-incomplete\",\"to\":\"primary\",\"unit\":4}],\"switches_total\":1,\"transferred\":13607,\"uncounted\":2,\"units\":5},\"class\":\"reconstruct-session\",\"issued_at\":\"2026-09-27T12:00:00Z\",\"kind\":\"claim\",\"parent_receipt_hash\":null,\"seq\":0,\"sig\":\"ee8f22b915e03ea5667301eda13abbb4c0aa6067f408e05a5f57e9041dc26ba1f1fd18c1ccdb55d9accdc0fe34f32355948171a1c88865e15fb8b29ba4c81003\",\"signer_id\":\"did:example:sink\",\"signer_pubkey\":\"d759793bbc13a2819a827c76adb6fba8a49aee007f49f2d0992d99b825ad2c48\",\"subject\":\"64c0713cb176874607bf8670295242184b7868a9ff7c55554a5ae08de2c301c1\",\"subject_type\":\"object\"}", + "expected": { + "outcome": "reject", + "step": 4, + "reason": "session_switch_invalid" + } + }, + { + "name": "session_switch_unknown_reason", + "about": "a switch for a reason delivery-telemetry section 5 does not list", + "procedure": "claim", + "receipt": "{\"body\":{\"classical_declared\":700,\"classical_source\":\"wai2-table\",\"counted_discarded\":1904,\"counted_fallback\":0,\"counted_primary\":5607,\"deadline_us\":40000,\"decoders\":[{\"capability\":\"wai.video.int_hyper\",\"decoder\":\"builtin:wai@0.4.0\",\"leaves\":4,\"module_status\":null,\"path\":\"primary\",\"pin\":\"7b4371854df0aa1645ac6525b373387c0617b873d5a57748932ee0f386ea164b\",\"rendition\":0,\"tier\":\"decode-equivalence\",\"variant\":null},{\"capability\":\"wai.video.av1\",\"decoder\":\"builtin:wai@0.4.0\",\"leaves\":1,\"module_status\":null,\"path\":\"fallback\",\"pin\":null,\"rendition\":null,\"tier\":null,\"variant\":null},{\"capability\":\"wai.video.int_refine\",\"decoder\":\"builtin:wai@0.4.0\",\"leaves\":4,\"module_status\":null,\"path\":\"primary\",\"pin\":null,\"rendition\":null,\"tier\":null,\"variant\":null}],\"energy\":null,\"fallback_units\":1,\"framing\":\"registered\",\"host\":{\"build\":{\"profile\":\"release\",\"target\":\"aarch64-unknown-linux-gnu\",\"toolchain\":\"rustc 1.95.0\"},\"profile\":\"native-ffi\",\"target\":\"aarch64-unknown-linux-gnu\",\"threads\":4},\"leaf_count\":9,\"media\":\"video\",\"missed\":1,\"missed_units\":[{\"late_us\":1200,\"layers\":1,\"unit\":4}],\"output_root\":\"3cb2c68a7fe160511bd3fbbbd6945b5d54fac6b499e33769b1ea6828f04bb312\",\"primary_units\":4,\"receipt_bytes\":640,\"session_nonce\":\"57c5462dfdabd1b7bdd204d34ba33649c057eb535349f29f45eb8f8c7d4a7e7f\",\"stage_sets\":[{\"claim\":\"b636e8894207d2fe59add1e1cacf3b52ea760fccb4dc3f0abce79be90e871640\",\"first_unit\":0}],\"switches\":[{\"from\":\"primary\",\"reason\":\"too-slow\",\"to\":\"fallback\",\"unit\":4}],\"switches_total\":1,\"transferred\":13607,\"uncounted\":2,\"units\":5},\"class\":\"reconstruct-session\",\"issued_at\":\"2026-09-27T12:00:00Z\",\"kind\":\"claim\",\"parent_receipt_hash\":null,\"seq\":0,\"sig\":\"30d101217ddaf5674399103aa355e9c35955ce46f187238bf5cd8c486889bb0e36eca96aab404796cc7a205b5c00a3a4a636a2830514853038404c3009695000\",\"signer_id\":\"did:example:sink\",\"signer_pubkey\":\"d759793bbc13a2819a827c76adb6fba8a49aee007f49f2d0992d99b825ad2c48\",\"subject\":\"64c0713cb176874607bf8670295242184b7868a9ff7c55554a5ae08de2c301c1\",\"subject_type\":\"object\"}", + "expected": { + "outcome": "reject", + "step": 4, + "reason": "session_switch_invalid" + } + }, + { + "name": "session_switch_out_of_order", + "about": "two switches in decreasing order of unit", + "procedure": "claim", + "receipt": "{\"body\":{\"classical_declared\":700,\"classical_source\":\"wai2-table\",\"counted_discarded\":1904,\"counted_fallback\":0,\"counted_primary\":5607,\"deadline_us\":40000,\"decoders\":[{\"capability\":\"wai.video.int_hyper\",\"decoder\":\"builtin:wai@0.4.0\",\"leaves\":4,\"module_status\":null,\"path\":\"primary\",\"pin\":\"7b4371854df0aa1645ac6525b373387c0617b873d5a57748932ee0f386ea164b\",\"rendition\":0,\"tier\":\"decode-equivalence\",\"variant\":null},{\"capability\":\"wai.video.av1\",\"decoder\":\"builtin:wai@0.4.0\",\"leaves\":1,\"module_status\":null,\"path\":\"fallback\",\"pin\":null,\"rendition\":null,\"tier\":null,\"variant\":null},{\"capability\":\"wai.video.int_refine\",\"decoder\":\"builtin:wai@0.4.0\",\"leaves\":4,\"module_status\":null,\"path\":\"primary\",\"pin\":null,\"rendition\":null,\"tier\":null,\"variant\":null}],\"energy\":null,\"fallback_units\":1,\"framing\":\"registered\",\"host\":{\"build\":{\"profile\":\"release\",\"target\":\"aarch64-unknown-linux-gnu\",\"toolchain\":\"rustc 1.95.0\"},\"profile\":\"native-ffi\",\"target\":\"aarch64-unknown-linux-gnu\",\"threads\":4},\"leaf_count\":9,\"media\":\"video\",\"missed\":1,\"missed_units\":[{\"late_us\":1200,\"layers\":1,\"unit\":4}],\"output_root\":\"3cb2c68a7fe160511bd3fbbbd6945b5d54fac6b499e33769b1ea6828f04bb312\",\"primary_units\":4,\"receipt_bytes\":640,\"session_nonce\":\"57c5462dfdabd1b7bdd204d34ba33649c057eb535349f29f45eb8f8c7d4a7e7f\",\"stage_sets\":[{\"claim\":\"b636e8894207d2fe59add1e1cacf3b52ea760fccb4dc3f0abce79be90e871640\",\"first_unit\":0}],\"switches\":[{\"from\":\"fallback\",\"reason\":\"recovered\",\"to\":\"primary\",\"unit\":5},{\"from\":\"primary\",\"reason\":\"set-incomplete\",\"to\":\"fallback\",\"unit\":4}],\"switches_total\":2,\"transferred\":13607,\"uncounted\":2,\"units\":5},\"class\":\"reconstruct-session\",\"issued_at\":\"2026-09-27T12:00:00Z\",\"kind\":\"claim\",\"parent_receipt_hash\":null,\"seq\":0,\"sig\":\"2ca72d76e2bdc81414a5f706d9a752c2a3251f5aaf8a709082b483d4258d4d6109f00f35752a8ab68cb7ce0e273880afae9aba77aabcba149d13f398ff426205\",\"signer_id\":\"did:example:sink\",\"signer_pubkey\":\"d759793bbc13a2819a827c76adb6fba8a49aee007f49f2d0992d99b825ad2c48\",\"subject\":\"64c0713cb176874607bf8670295242184b7868a9ff7c55554a5ae08de2c301c1\",\"subject_type\":\"object\"}", + "expected": { + "outcome": "reject", + "step": 4, + "reason": "session_switch_invalid" + } + }, + { + "name": "session_switches_above_total", + "about": "one switch written and switches_total 0", + "procedure": "claim", + "receipt": "{\"body\":{\"classical_declared\":700,\"classical_source\":\"wai2-table\",\"counted_discarded\":1904,\"counted_fallback\":0,\"counted_primary\":5607,\"deadline_us\":40000,\"decoders\":[{\"capability\":\"wai.video.int_hyper\",\"decoder\":\"builtin:wai@0.4.0\",\"leaves\":4,\"module_status\":null,\"path\":\"primary\",\"pin\":\"7b4371854df0aa1645ac6525b373387c0617b873d5a57748932ee0f386ea164b\",\"rendition\":0,\"tier\":\"decode-equivalence\",\"variant\":null},{\"capability\":\"wai.video.av1\",\"decoder\":\"builtin:wai@0.4.0\",\"leaves\":1,\"module_status\":null,\"path\":\"fallback\",\"pin\":null,\"rendition\":null,\"tier\":null,\"variant\":null},{\"capability\":\"wai.video.int_refine\",\"decoder\":\"builtin:wai@0.4.0\",\"leaves\":4,\"module_status\":null,\"path\":\"primary\",\"pin\":null,\"rendition\":null,\"tier\":null,\"variant\":null}],\"energy\":null,\"fallback_units\":1,\"framing\":\"registered\",\"host\":{\"build\":{\"profile\":\"release\",\"target\":\"aarch64-unknown-linux-gnu\",\"toolchain\":\"rustc 1.95.0\"},\"profile\":\"native-ffi\",\"target\":\"aarch64-unknown-linux-gnu\",\"threads\":4},\"leaf_count\":9,\"media\":\"video\",\"missed\":1,\"missed_units\":[{\"late_us\":1200,\"layers\":1,\"unit\":4}],\"output_root\":\"3cb2c68a7fe160511bd3fbbbd6945b5d54fac6b499e33769b1ea6828f04bb312\",\"primary_units\":4,\"receipt_bytes\":640,\"session_nonce\":\"57c5462dfdabd1b7bdd204d34ba33649c057eb535349f29f45eb8f8c7d4a7e7f\",\"stage_sets\":[{\"claim\":\"b636e8894207d2fe59add1e1cacf3b52ea760fccb4dc3f0abce79be90e871640\",\"first_unit\":0}],\"switches\":[{\"from\":\"primary\",\"reason\":\"set-incomplete\",\"to\":\"fallback\",\"unit\":4}],\"switches_total\":0,\"transferred\":13607,\"uncounted\":2,\"units\":5},\"class\":\"reconstruct-session\",\"issued_at\":\"2026-09-27T12:00:00Z\",\"kind\":\"claim\",\"parent_receipt_hash\":null,\"seq\":0,\"sig\":\"41fc95e80197051e5de6fee8a001af26a209c5bf69cb5c590dca2c24079a5b7fded4c1f456a39755ef06e92939dd29412ad38cf76162d29c7ef718bace3cbe0d\",\"signer_id\":\"did:example:sink\",\"signer_pubkey\":\"d759793bbc13a2819a827c76adb6fba8a49aee007f49f2d0992d99b825ad2c48\",\"subject\":\"64c0713cb176874607bf8670295242184b7868a9ff7c55554a5ae08de2c301c1\",\"subject_type\":\"object\"}", + "expected": { + "outcome": "reject", + "step": 4, + "reason": "session_switch_invalid" + } + }, + { + "name": "session_missed_without_deadline", + "about": "a presentation counted as missed with no deadline to miss", + "procedure": "claim", + "receipt": "{\"body\":{\"classical_declared\":700,\"classical_source\":\"wai2-table\",\"counted_discarded\":1904,\"counted_fallback\":0,\"counted_primary\":5607,\"deadline_us\":null,\"decoders\":[{\"capability\":\"wai.video.int_hyper\",\"decoder\":\"builtin:wai@0.4.0\",\"leaves\":4,\"module_status\":null,\"path\":\"primary\",\"pin\":\"7b4371854df0aa1645ac6525b373387c0617b873d5a57748932ee0f386ea164b\",\"rendition\":0,\"tier\":\"decode-equivalence\",\"variant\":null},{\"capability\":\"wai.video.av1\",\"decoder\":\"builtin:wai@0.4.0\",\"leaves\":1,\"module_status\":null,\"path\":\"fallback\",\"pin\":null,\"rendition\":null,\"tier\":null,\"variant\":null},{\"capability\":\"wai.video.int_refine\",\"decoder\":\"builtin:wai@0.4.0\",\"leaves\":4,\"module_status\":null,\"path\":\"primary\",\"pin\":null,\"rendition\":null,\"tier\":null,\"variant\":null}],\"energy\":null,\"fallback_units\":1,\"framing\":\"registered\",\"host\":{\"build\":{\"profile\":\"release\",\"target\":\"aarch64-unknown-linux-gnu\",\"toolchain\":\"rustc 1.95.0\"},\"profile\":\"native-ffi\",\"target\":\"aarch64-unknown-linux-gnu\",\"threads\":4},\"leaf_count\":9,\"media\":\"video\",\"missed\":1,\"missed_units\":[{\"late_us\":1200,\"layers\":1,\"unit\":4}],\"output_root\":\"3cb2c68a7fe160511bd3fbbbd6945b5d54fac6b499e33769b1ea6828f04bb312\",\"primary_units\":4,\"receipt_bytes\":640,\"session_nonce\":\"57c5462dfdabd1b7bdd204d34ba33649c057eb535349f29f45eb8f8c7d4a7e7f\",\"stage_sets\":[{\"claim\":\"b636e8894207d2fe59add1e1cacf3b52ea760fccb4dc3f0abce79be90e871640\",\"first_unit\":0}],\"switches\":[{\"from\":\"primary\",\"reason\":\"set-incomplete\",\"to\":\"fallback\",\"unit\":4}],\"switches_total\":1,\"transferred\":13607,\"uncounted\":2,\"units\":5},\"class\":\"reconstruct-session\",\"issued_at\":\"2026-09-27T12:00:00Z\",\"kind\":\"claim\",\"parent_receipt_hash\":null,\"seq\":0,\"sig\":\"48f5992408061eaebd7349565f82961debab1b4f6ca2c662937a3faab752905655f7165084fc4ad3156b211e5ed42d916afe8d23687733aeb867a42be1e59001\",\"signer_id\":\"did:example:sink\",\"signer_pubkey\":\"d759793bbc13a2819a827c76adb6fba8a49aee007f49f2d0992d99b825ad2c48\",\"subject\":\"64c0713cb176874607bf8670295242184b7868a9ff7c55554a5ae08de2c301c1\",\"subject_type\":\"object\"}", + "expected": { + "outcome": "reject", + "step": 4, + "reason": "session_missed_invalid" + } + }, + { + "name": "session_missed_above_leaves", + "about": "more presentations missed than presented", + "procedure": "claim", + "receipt": "{\"body\":{\"classical_declared\":700,\"classical_source\":\"wai2-table\",\"counted_discarded\":1904,\"counted_fallback\":0,\"counted_primary\":5607,\"deadline_us\":40000,\"decoders\":[{\"capability\":\"wai.video.int_hyper\",\"decoder\":\"builtin:wai@0.4.0\",\"leaves\":4,\"module_status\":null,\"path\":\"primary\",\"pin\":\"7b4371854df0aa1645ac6525b373387c0617b873d5a57748932ee0f386ea164b\",\"rendition\":0,\"tier\":\"decode-equivalence\",\"variant\":null},{\"capability\":\"wai.video.av1\",\"decoder\":\"builtin:wai@0.4.0\",\"leaves\":1,\"module_status\":null,\"path\":\"fallback\",\"pin\":null,\"rendition\":null,\"tier\":null,\"variant\":null},{\"capability\":\"wai.video.int_refine\",\"decoder\":\"builtin:wai@0.4.0\",\"leaves\":4,\"module_status\":null,\"path\":\"primary\",\"pin\":null,\"rendition\":null,\"tier\":null,\"variant\":null}],\"energy\":null,\"fallback_units\":1,\"framing\":\"registered\",\"host\":{\"build\":{\"profile\":\"release\",\"target\":\"aarch64-unknown-linux-gnu\",\"toolchain\":\"rustc 1.95.0\"},\"profile\":\"native-ffi\",\"target\":\"aarch64-unknown-linux-gnu\",\"threads\":4},\"leaf_count\":9,\"media\":\"video\",\"missed\":10,\"missed_units\":[{\"late_us\":1200,\"layers\":1,\"unit\":4}],\"output_root\":\"3cb2c68a7fe160511bd3fbbbd6945b5d54fac6b499e33769b1ea6828f04bb312\",\"primary_units\":4,\"receipt_bytes\":640,\"session_nonce\":\"57c5462dfdabd1b7bdd204d34ba33649c057eb535349f29f45eb8f8c7d4a7e7f\",\"stage_sets\":[{\"claim\":\"b636e8894207d2fe59add1e1cacf3b52ea760fccb4dc3f0abce79be90e871640\",\"first_unit\":0}],\"switches\":[{\"from\":\"primary\",\"reason\":\"set-incomplete\",\"to\":\"fallback\",\"unit\":4}],\"switches_total\":1,\"transferred\":13607,\"uncounted\":2,\"units\":5},\"class\":\"reconstruct-session\",\"issued_at\":\"2026-09-27T12:00:00Z\",\"kind\":\"claim\",\"parent_receipt_hash\":null,\"seq\":0,\"sig\":\"2cd0c5bf9d49d988092d4e6f7e13591c4e560aa378bcaef6fdec9600d2eb67ae406a7f817e0ea108a8e36c6982efd91f31559a2aa9f3030bd32e7196bb208403\",\"signer_id\":\"did:example:sink\",\"signer_pubkey\":\"d759793bbc13a2819a827c76adb6fba8a49aee007f49f2d0992d99b825ad2c48\",\"subject\":\"64c0713cb176874607bf8670295242184b7868a9ff7c55554a5ae08de2c301c1\",\"subject_type\":\"object\"}", + "expected": { + "outcome": "reject", + "step": 4, + "reason": "session_missed_invalid" + } + }, + { + "name": "session_missed_units_above_missed", + "about": "two missed presentations written and missed 1", + "procedure": "claim", + "receipt": "{\"body\":{\"classical_declared\":700,\"classical_source\":\"wai2-table\",\"counted_discarded\":1904,\"counted_fallback\":0,\"counted_primary\":5607,\"deadline_us\":40000,\"decoders\":[{\"capability\":\"wai.video.int_hyper\",\"decoder\":\"builtin:wai@0.4.0\",\"leaves\":4,\"module_status\":null,\"path\":\"primary\",\"pin\":\"7b4371854df0aa1645ac6525b373387c0617b873d5a57748932ee0f386ea164b\",\"rendition\":0,\"tier\":\"decode-equivalence\",\"variant\":null},{\"capability\":\"wai.video.av1\",\"decoder\":\"builtin:wai@0.4.0\",\"leaves\":1,\"module_status\":null,\"path\":\"fallback\",\"pin\":null,\"rendition\":null,\"tier\":null,\"variant\":null},{\"capability\":\"wai.video.int_refine\",\"decoder\":\"builtin:wai@0.4.0\",\"leaves\":4,\"module_status\":null,\"path\":\"primary\",\"pin\":null,\"rendition\":null,\"tier\":null,\"variant\":null}],\"energy\":null,\"fallback_units\":1,\"framing\":\"registered\",\"host\":{\"build\":{\"profile\":\"release\",\"target\":\"aarch64-unknown-linux-gnu\",\"toolchain\":\"rustc 1.95.0\"},\"profile\":\"native-ffi\",\"target\":\"aarch64-unknown-linux-gnu\",\"threads\":4},\"leaf_count\":9,\"media\":\"video\",\"missed\":1,\"missed_units\":[{\"late_us\":10,\"layers\":1,\"unit\":3},{\"late_us\":1200,\"layers\":1,\"unit\":4}],\"output_root\":\"3cb2c68a7fe160511bd3fbbbd6945b5d54fac6b499e33769b1ea6828f04bb312\",\"primary_units\":4,\"receipt_bytes\":640,\"session_nonce\":\"57c5462dfdabd1b7bdd204d34ba33649c057eb535349f29f45eb8f8c7d4a7e7f\",\"stage_sets\":[{\"claim\":\"b636e8894207d2fe59add1e1cacf3b52ea760fccb4dc3f0abce79be90e871640\",\"first_unit\":0}],\"switches\":[{\"from\":\"primary\",\"reason\":\"set-incomplete\",\"to\":\"fallback\",\"unit\":4}],\"switches_total\":1,\"transferred\":13607,\"uncounted\":2,\"units\":5},\"class\":\"reconstruct-session\",\"issued_at\":\"2026-09-27T12:00:00Z\",\"kind\":\"claim\",\"parent_receipt_hash\":null,\"seq\":0,\"sig\":\"b3a1512065c2469ee7e15d8c5d929bcac65d83b23c5ead1930c8ff184eab11ac57a62c33075e5be071cd27c8ab123e1216c9f5d07a34a8ef2853d2c825c0e104\",\"signer_id\":\"did:example:sink\",\"signer_pubkey\":\"d759793bbc13a2819a827c76adb6fba8a49aee007f49f2d0992d99b825ad2c48\",\"subject\":\"64c0713cb176874607bf8670295242184b7868a9ff7c55554a5ae08de2c301c1\",\"subject_type\":\"object\"}", + "expected": { + "outcome": "reject", + "step": 4, + "reason": "session_missed_invalid" + } + }, + { + "name": "session_missed_not_late", + "about": "a missed presentation zero microseconds late", + "procedure": "claim", + "receipt": "{\"body\":{\"classical_declared\":700,\"classical_source\":\"wai2-table\",\"counted_discarded\":1904,\"counted_fallback\":0,\"counted_primary\":5607,\"deadline_us\":40000,\"decoders\":[{\"capability\":\"wai.video.int_hyper\",\"decoder\":\"builtin:wai@0.4.0\",\"leaves\":4,\"module_status\":null,\"path\":\"primary\",\"pin\":\"7b4371854df0aa1645ac6525b373387c0617b873d5a57748932ee0f386ea164b\",\"rendition\":0,\"tier\":\"decode-equivalence\",\"variant\":null},{\"capability\":\"wai.video.av1\",\"decoder\":\"builtin:wai@0.4.0\",\"leaves\":1,\"module_status\":null,\"path\":\"fallback\",\"pin\":null,\"rendition\":null,\"tier\":null,\"variant\":null},{\"capability\":\"wai.video.int_refine\",\"decoder\":\"builtin:wai@0.4.0\",\"leaves\":4,\"module_status\":null,\"path\":\"primary\",\"pin\":null,\"rendition\":null,\"tier\":null,\"variant\":null}],\"energy\":null,\"fallback_units\":1,\"framing\":\"registered\",\"host\":{\"build\":{\"profile\":\"release\",\"target\":\"aarch64-unknown-linux-gnu\",\"toolchain\":\"rustc 1.95.0\"},\"profile\":\"native-ffi\",\"target\":\"aarch64-unknown-linux-gnu\",\"threads\":4},\"leaf_count\":9,\"media\":\"video\",\"missed\":1,\"missed_units\":[{\"late_us\":0,\"layers\":1,\"unit\":4}],\"output_root\":\"3cb2c68a7fe160511bd3fbbbd6945b5d54fac6b499e33769b1ea6828f04bb312\",\"primary_units\":4,\"receipt_bytes\":640,\"session_nonce\":\"57c5462dfdabd1b7bdd204d34ba33649c057eb535349f29f45eb8f8c7d4a7e7f\",\"stage_sets\":[{\"claim\":\"b636e8894207d2fe59add1e1cacf3b52ea760fccb4dc3f0abce79be90e871640\",\"first_unit\":0}],\"switches\":[{\"from\":\"primary\",\"reason\":\"set-incomplete\",\"to\":\"fallback\",\"unit\":4}],\"switches_total\":1,\"transferred\":13607,\"uncounted\":2,\"units\":5},\"class\":\"reconstruct-session\",\"issued_at\":\"2026-09-27T12:00:00Z\",\"kind\":\"claim\",\"parent_receipt_hash\":null,\"seq\":0,\"sig\":\"5e1593a3cb7510f7a3f32bee98c9c5c00c045235261f66e66a16f8b0597ec257e33ae4134fcdde4dce0b041343eab64b4e1aee9e488c8052976bd9f5e63edd03\",\"signer_id\":\"did:example:sink\",\"signer_pubkey\":\"d759793bbc13a2819a827c76adb6fba8a49aee007f49f2d0992d99b825ad2c48\",\"subject\":\"64c0713cb176874607bf8670295242184b7868a9ff7c55554a5ae08de2c301c1\",\"subject_type\":\"object\"}", + "expected": { + "outcome": "reject", + "step": 4, + "reason": "session_missed_invalid" + } + }, + { + "name": "session_missed_out_of_order", + "about": "missed presentations out of order", + "procedure": "claim", + "receipt": "{\"body\":{\"classical_declared\":700,\"classical_source\":\"wai2-table\",\"counted_discarded\":1904,\"counted_fallback\":0,\"counted_primary\":5607,\"deadline_us\":40000,\"decoders\":[{\"capability\":\"wai.video.int_hyper\",\"decoder\":\"builtin:wai@0.4.0\",\"leaves\":4,\"module_status\":null,\"path\":\"primary\",\"pin\":\"7b4371854df0aa1645ac6525b373387c0617b873d5a57748932ee0f386ea164b\",\"rendition\":0,\"tier\":\"decode-equivalence\",\"variant\":null},{\"capability\":\"wai.video.av1\",\"decoder\":\"builtin:wai@0.4.0\",\"leaves\":1,\"module_status\":null,\"path\":\"fallback\",\"pin\":null,\"rendition\":null,\"tier\":null,\"variant\":null},{\"capability\":\"wai.video.int_refine\",\"decoder\":\"builtin:wai@0.4.0\",\"leaves\":4,\"module_status\":null,\"path\":\"primary\",\"pin\":null,\"rendition\":null,\"tier\":null,\"variant\":null}],\"energy\":null,\"fallback_units\":1,\"framing\":\"registered\",\"host\":{\"build\":{\"profile\":\"release\",\"target\":\"aarch64-unknown-linux-gnu\",\"toolchain\":\"rustc 1.95.0\"},\"profile\":\"native-ffi\",\"target\":\"aarch64-unknown-linux-gnu\",\"threads\":4},\"leaf_count\":9,\"media\":\"video\",\"missed\":2,\"missed_units\":[{\"late_us\":1200,\"layers\":1,\"unit\":4},{\"late_us\":10,\"layers\":1,\"unit\":3}],\"output_root\":\"3cb2c68a7fe160511bd3fbbbd6945b5d54fac6b499e33769b1ea6828f04bb312\",\"primary_units\":4,\"receipt_bytes\":640,\"session_nonce\":\"57c5462dfdabd1b7bdd204d34ba33649c057eb535349f29f45eb8f8c7d4a7e7f\",\"stage_sets\":[{\"claim\":\"b636e8894207d2fe59add1e1cacf3b52ea760fccb4dc3f0abce79be90e871640\",\"first_unit\":0}],\"switches\":[{\"from\":\"primary\",\"reason\":\"set-incomplete\",\"to\":\"fallback\",\"unit\":4}],\"switches_total\":1,\"transferred\":13607,\"uncounted\":2,\"units\":5},\"class\":\"reconstruct-session\",\"issued_at\":\"2026-09-27T12:00:00Z\",\"kind\":\"claim\",\"parent_receipt_hash\":null,\"seq\":0,\"sig\":\"75e7876e6a0bf036771e0f5e3e48d82afe04432c18b0f3bdb854be1118f444c892c496b0a1f99883b589be1395398da69ebabb8e83856df7bfce8ac47dd9bc00\",\"signer_id\":\"did:example:sink\",\"signer_pubkey\":\"d759793bbc13a2819a827c76adb6fba8a49aee007f49f2d0992d99b825ad2c48\",\"subject\":\"64c0713cb176874607bf8670295242184b7868a9ff7c55554a5ae08de2c301c1\",\"subject_type\":\"object\"}", + "expected": { + "outcome": "reject", + "step": 4, + "reason": "session_missed_invalid" + } + }, + { + "name": "session_stage_set_twice", + "about": "one stage set listed twice", + "procedure": "claim", + "receipt": "{\"body\":{\"classical_declared\":700,\"classical_source\":\"wai2-table\",\"counted_discarded\":1904,\"counted_fallback\":0,\"counted_primary\":5607,\"deadline_us\":40000,\"decoders\":[{\"capability\":\"wai.video.int_hyper\",\"decoder\":\"builtin:wai@0.4.0\",\"leaves\":4,\"module_status\":null,\"path\":\"primary\",\"pin\":\"7b4371854df0aa1645ac6525b373387c0617b873d5a57748932ee0f386ea164b\",\"rendition\":0,\"tier\":\"decode-equivalence\",\"variant\":null},{\"capability\":\"wai.video.av1\",\"decoder\":\"builtin:wai@0.4.0\",\"leaves\":1,\"module_status\":null,\"path\":\"fallback\",\"pin\":null,\"rendition\":null,\"tier\":null,\"variant\":null},{\"capability\":\"wai.video.int_refine\",\"decoder\":\"builtin:wai@0.4.0\",\"leaves\":4,\"module_status\":null,\"path\":\"primary\",\"pin\":null,\"rendition\":null,\"tier\":null,\"variant\":null}],\"energy\":null,\"fallback_units\":1,\"framing\":\"registered\",\"host\":{\"build\":{\"profile\":\"release\",\"target\":\"aarch64-unknown-linux-gnu\",\"toolchain\":\"rustc 1.95.0\"},\"profile\":\"native-ffi\",\"target\":\"aarch64-unknown-linux-gnu\",\"threads\":4},\"leaf_count\":9,\"media\":\"video\",\"missed\":1,\"missed_units\":[{\"late_us\":1200,\"layers\":1,\"unit\":4}],\"output_root\":\"3cb2c68a7fe160511bd3fbbbd6945b5d54fac6b499e33769b1ea6828f04bb312\",\"primary_units\":4,\"receipt_bytes\":640,\"session_nonce\":\"57c5462dfdabd1b7bdd204d34ba33649c057eb535349f29f45eb8f8c7d4a7e7f\",\"stage_sets\":[{\"claim\":\"b636e8894207d2fe59add1e1cacf3b52ea760fccb4dc3f0abce79be90e871640\",\"first_unit\":0},{\"claim\":\"b636e8894207d2fe59add1e1cacf3b52ea760fccb4dc3f0abce79be90e871640\",\"first_unit\":0}],\"switches\":[{\"from\":\"primary\",\"reason\":\"set-incomplete\",\"to\":\"fallback\",\"unit\":4}],\"switches_total\":1,\"transferred\":13607,\"uncounted\":2,\"units\":5},\"class\":\"reconstruct-session\",\"issued_at\":\"2026-09-27T12:00:00Z\",\"kind\":\"claim\",\"parent_receipt_hash\":null,\"seq\":0,\"sig\":\"7fcacef4024dda2162c97e76b4943f69456a00966b900fc036c0ec990e05c3d3db26f898da22182a71820854ee20c7cdb0d2ccc2bd0fe63281843c2ce13a0707\",\"signer_id\":\"did:example:sink\",\"signer_pubkey\":\"d759793bbc13a2819a827c76adb6fba8a49aee007f49f2d0992d99b825ad2c48\",\"subject\":\"64c0713cb176874607bf8670295242184b7868a9ff7c55554a5ae08de2c301c1\",\"subject_type\":\"object\"}", + "expected": { + "outcome": "reject", + "step": 4, + "reason": "session_stage_sets_invalid" + } + }, + { + "name": "session_discarded_above_counted", + "about": "more bytes discarded than were counted", + "procedure": "claim", + "receipt": "{\"body\":{\"classical_declared\":700,\"classical_source\":\"wai2-table\",\"counted_discarded\":5608,\"counted_fallback\":0,\"counted_primary\":5607,\"deadline_us\":40000,\"decoders\":[{\"capability\":\"wai.video.int_hyper\",\"decoder\":\"builtin:wai@0.4.0\",\"leaves\":4,\"module_status\":null,\"path\":\"primary\",\"pin\":\"7b4371854df0aa1645ac6525b373387c0617b873d5a57748932ee0f386ea164b\",\"rendition\":0,\"tier\":\"decode-equivalence\",\"variant\":null},{\"capability\":\"wai.video.av1\",\"decoder\":\"builtin:wai@0.4.0\",\"leaves\":1,\"module_status\":null,\"path\":\"fallback\",\"pin\":null,\"rendition\":null,\"tier\":null,\"variant\":null},{\"capability\":\"wai.video.int_refine\",\"decoder\":\"builtin:wai@0.4.0\",\"leaves\":4,\"module_status\":null,\"path\":\"primary\",\"pin\":null,\"rendition\":null,\"tier\":null,\"variant\":null}],\"energy\":null,\"fallback_units\":1,\"framing\":\"registered\",\"host\":{\"build\":{\"profile\":\"release\",\"target\":\"aarch64-unknown-linux-gnu\",\"toolchain\":\"rustc 1.95.0\"},\"profile\":\"native-ffi\",\"target\":\"aarch64-unknown-linux-gnu\",\"threads\":4},\"leaf_count\":9,\"media\":\"video\",\"missed\":1,\"missed_units\":[{\"late_us\":1200,\"layers\":1,\"unit\":4}],\"output_root\":\"3cb2c68a7fe160511bd3fbbbd6945b5d54fac6b499e33769b1ea6828f04bb312\",\"primary_units\":4,\"receipt_bytes\":640,\"session_nonce\":\"57c5462dfdabd1b7bdd204d34ba33649c057eb535349f29f45eb8f8c7d4a7e7f\",\"stage_sets\":[{\"claim\":\"b636e8894207d2fe59add1e1cacf3b52ea760fccb4dc3f0abce79be90e871640\",\"first_unit\":0}],\"switches\":[{\"from\":\"primary\",\"reason\":\"set-incomplete\",\"to\":\"fallback\",\"unit\":4}],\"switches_total\":1,\"transferred\":13607,\"uncounted\":2,\"units\":5},\"class\":\"reconstruct-session\",\"issued_at\":\"2026-09-27T12:00:00Z\",\"kind\":\"claim\",\"parent_receipt_hash\":null,\"seq\":0,\"sig\":\"caefb18554e61b1d05b3c955957786972f1d5d9fe1fdc477baccea163701edb4409684ad6a78ac31648eb4cf5badc9b1db7d7b62538c4549a408420fc68bd100\",\"signer_id\":\"did:example:sink\",\"signer_pubkey\":\"d759793bbc13a2819a827c76adb6fba8a49aee007f49f2d0992d99b825ad2c48\",\"subject\":\"64c0713cb176874607bf8670295242184b7868a9ff7c55554a5ae08de2c301c1\",\"subject_type\":\"object\"}", + "expected": { + "outcome": "reject", + "step": 4, + "reason": "session_counted_invalid" + } + }, + { + "name": "session_classical_without_source", + "about": "a classical length with no source", + "procedure": "claim", + "receipt": "{\"body\":{\"classical_declared\":700,\"classical_source\":null,\"counted_discarded\":1904,\"counted_fallback\":0,\"counted_primary\":5607,\"deadline_us\":40000,\"decoders\":[{\"capability\":\"wai.video.int_hyper\",\"decoder\":\"builtin:wai@0.4.0\",\"leaves\":4,\"module_status\":null,\"path\":\"primary\",\"pin\":\"7b4371854df0aa1645ac6525b373387c0617b873d5a57748932ee0f386ea164b\",\"rendition\":0,\"tier\":\"decode-equivalence\",\"variant\":null},{\"capability\":\"wai.video.av1\",\"decoder\":\"builtin:wai@0.4.0\",\"leaves\":1,\"module_status\":null,\"path\":\"fallback\",\"pin\":null,\"rendition\":null,\"tier\":null,\"variant\":null},{\"capability\":\"wai.video.int_refine\",\"decoder\":\"builtin:wai@0.4.0\",\"leaves\":4,\"module_status\":null,\"path\":\"primary\",\"pin\":null,\"rendition\":null,\"tier\":null,\"variant\":null}],\"energy\":null,\"fallback_units\":1,\"framing\":\"registered\",\"host\":{\"build\":{\"profile\":\"release\",\"target\":\"aarch64-unknown-linux-gnu\",\"toolchain\":\"rustc 1.95.0\"},\"profile\":\"native-ffi\",\"target\":\"aarch64-unknown-linux-gnu\",\"threads\":4},\"leaf_count\":9,\"media\":\"video\",\"missed\":1,\"missed_units\":[{\"late_us\":1200,\"layers\":1,\"unit\":4}],\"output_root\":\"3cb2c68a7fe160511bd3fbbbd6945b5d54fac6b499e33769b1ea6828f04bb312\",\"primary_units\":4,\"receipt_bytes\":640,\"session_nonce\":\"57c5462dfdabd1b7bdd204d34ba33649c057eb535349f29f45eb8f8c7d4a7e7f\",\"stage_sets\":[{\"claim\":\"b636e8894207d2fe59add1e1cacf3b52ea760fccb4dc3f0abce79be90e871640\",\"first_unit\":0}],\"switches\":[{\"from\":\"primary\",\"reason\":\"set-incomplete\",\"to\":\"fallback\",\"unit\":4}],\"switches_total\":1,\"transferred\":13607,\"uncounted\":2,\"units\":5},\"class\":\"reconstruct-session\",\"issued_at\":\"2026-09-27T12:00:00Z\",\"kind\":\"claim\",\"parent_receipt_hash\":null,\"seq\":0,\"sig\":\"dd15a867bdc47ceefe86de6ae42e9845a02b1be5e940a8d766b049c52271bdaedc77e10eb811a3def5dc65a668c3595a269e8dcbe2936cff930864f3a4228b0c\",\"signer_id\":\"did:example:sink\",\"signer_pubkey\":\"d759793bbc13a2819a827c76adb6fba8a49aee007f49f2d0992d99b825ad2c48\",\"subject\":\"64c0713cb176874607bf8670295242184b7868a9ff7c55554a5ae08de2c301c1\",\"subject_type\":\"object\"}", + "expected": { + "outcome": "reject", + "step": 4, + "reason": "session_classical_invalid" + } + }, + { + "name": "session_classical_source_unregistered", + "about": "a classical source no extension registers", + "procedure": "claim", + "receipt": "{\"body\":{\"classical_declared\":700,\"classical_source\":\"referenced\",\"counted_discarded\":1904,\"counted_fallback\":0,\"counted_primary\":5607,\"deadline_us\":40000,\"decoders\":[{\"capability\":\"wai.video.int_hyper\",\"decoder\":\"builtin:wai@0.4.0\",\"leaves\":4,\"module_status\":null,\"path\":\"primary\",\"pin\":\"7b4371854df0aa1645ac6525b373387c0617b873d5a57748932ee0f386ea164b\",\"rendition\":0,\"tier\":\"decode-equivalence\",\"variant\":null},{\"capability\":\"wai.video.av1\",\"decoder\":\"builtin:wai@0.4.0\",\"leaves\":1,\"module_status\":null,\"path\":\"fallback\",\"pin\":null,\"rendition\":null,\"tier\":null,\"variant\":null},{\"capability\":\"wai.video.int_refine\",\"decoder\":\"builtin:wai@0.4.0\",\"leaves\":4,\"module_status\":null,\"path\":\"primary\",\"pin\":null,\"rendition\":null,\"tier\":null,\"variant\":null}],\"energy\":null,\"fallback_units\":1,\"framing\":\"registered\",\"host\":{\"build\":{\"profile\":\"release\",\"target\":\"aarch64-unknown-linux-gnu\",\"toolchain\":\"rustc 1.95.0\"},\"profile\":\"native-ffi\",\"target\":\"aarch64-unknown-linux-gnu\",\"threads\":4},\"leaf_count\":9,\"media\":\"video\",\"missed\":1,\"missed_units\":[{\"late_us\":1200,\"layers\":1,\"unit\":4}],\"output_root\":\"3cb2c68a7fe160511bd3fbbbd6945b5d54fac6b499e33769b1ea6828f04bb312\",\"primary_units\":4,\"receipt_bytes\":640,\"session_nonce\":\"57c5462dfdabd1b7bdd204d34ba33649c057eb535349f29f45eb8f8c7d4a7e7f\",\"stage_sets\":[{\"claim\":\"b636e8894207d2fe59add1e1cacf3b52ea760fccb4dc3f0abce79be90e871640\",\"first_unit\":0}],\"switches\":[{\"from\":\"primary\",\"reason\":\"set-incomplete\",\"to\":\"fallback\",\"unit\":4}],\"switches_total\":1,\"transferred\":13607,\"uncounted\":2,\"units\":5},\"class\":\"reconstruct-session\",\"issued_at\":\"2026-09-27T12:00:00Z\",\"kind\":\"claim\",\"parent_receipt_hash\":null,\"seq\":0,\"sig\":\"e5a11165ef5d31d66d1f7c80cd855377a0f7c2fcc2780f809470b4d39ca6f70642123e433746f3896e5709db085abddf0ef8f7d1a0c16f8691d54e507bf18f0a\",\"signer_id\":\"did:example:sink\",\"signer_pubkey\":\"d759793bbc13a2819a827c76adb6fba8a49aee007f49f2d0992d99b825ad2c48\",\"subject\":\"64c0713cb176874607bf8670295242184b7868a9ff7c55554a5ae08de2c301c1\",\"subject_type\":\"object\"}", + "expected": { + "outcome": "reject", + "step": 4, + "reason": "session_classical_invalid" + } + }, + { + "name": "session_energy_zero", + "about": "a decode figure of zero: the unmetered session is energy null", + "procedure": "claim", + "receipt": "{\"body\":{\"classical_declared\":700,\"classical_source\":\"wai2-table\",\"counted_discarded\":1904,\"counted_fallback\":0,\"counted_primary\":5607,\"deadline_us\":40000,\"decoders\":[{\"capability\":\"wai.video.int_hyper\",\"decoder\":\"builtin:wai@0.4.0\",\"leaves\":4,\"module_status\":null,\"path\":\"primary\",\"pin\":\"7b4371854df0aa1645ac6525b373387c0617b873d5a57748932ee0f386ea164b\",\"rendition\":0,\"tier\":\"decode-equivalence\",\"variant\":null},{\"capability\":\"wai.video.av1\",\"decoder\":\"builtin:wai@0.4.0\",\"leaves\":1,\"module_status\":null,\"path\":\"fallback\",\"pin\":null,\"rendition\":null,\"tier\":null,\"variant\":null},{\"capability\":\"wai.video.int_refine\",\"decoder\":\"builtin:wai@0.4.0\",\"leaves\":4,\"module_status\":null,\"path\":\"primary\",\"pin\":null,\"rendition\":null,\"tier\":null,\"variant\":null}],\"energy\":{\"energy_calibration_ref\":null,\"energy_counter_filtering\":\"Unknown\",\"energy_provenance\":\"OnChipCounter\",\"energy_uncertainty\":{\"relative_ppm\":20000,\"window_us\":1000000},\"joules_micro\":0},\"fallback_units\":1,\"framing\":\"registered\",\"host\":{\"build\":{\"profile\":\"release\",\"target\":\"aarch64-unknown-linux-gnu\",\"toolchain\":\"rustc 1.95.0\"},\"profile\":\"native-ffi\",\"target\":\"aarch64-unknown-linux-gnu\",\"threads\":4},\"leaf_count\":9,\"media\":\"video\",\"missed\":1,\"missed_units\":[{\"late_us\":1200,\"layers\":1,\"unit\":4}],\"output_root\":\"3cb2c68a7fe160511bd3fbbbd6945b5d54fac6b499e33769b1ea6828f04bb312\",\"primary_units\":4,\"receipt_bytes\":640,\"session_nonce\":\"57c5462dfdabd1b7bdd204d34ba33649c057eb535349f29f45eb8f8c7d4a7e7f\",\"stage_sets\":[{\"claim\":\"b636e8894207d2fe59add1e1cacf3b52ea760fccb4dc3f0abce79be90e871640\",\"first_unit\":0}],\"switches\":[{\"from\":\"primary\",\"reason\":\"set-incomplete\",\"to\":\"fallback\",\"unit\":4}],\"switches_total\":1,\"transferred\":13607,\"uncounted\":2,\"units\":5},\"class\":\"reconstruct-session\",\"issued_at\":\"2026-09-27T12:00:00Z\",\"kind\":\"claim\",\"parent_receipt_hash\":null,\"seq\":0,\"sig\":\"8ee9698c408b755e6f3517e81a2a4c99eabc41fbe31925b7932854cbb0fc85481327b469bffcbdd00db6f8bfb2f81d4fae2e338d05b62ba94b2ed69d0871f005\",\"signer_id\":\"did:example:sink\",\"signer_pubkey\":\"d759793bbc13a2819a827c76adb6fba8a49aee007f49f2d0992d99b825ad2c48\",\"subject\":\"64c0713cb176874607bf8670295242184b7868a9ff7c55554a5ae08de2c301c1\",\"subject_type\":\"object\"}", + "expected": { + "outcome": "reject", + "step": 4, + "reason": "energy_zero_figure" + } + }, + { + "name": "session_energy_unknown_acquisition", + "about": "a class energy-measurement section 2 does not name", + "procedure": "claim", + "receipt": "{\"body\":{\"classical_declared\":700,\"classical_source\":\"wai2-table\",\"counted_discarded\":1904,\"counted_fallback\":0,\"counted_primary\":5607,\"deadline_us\":40000,\"decoders\":[{\"capability\":\"wai.video.int_hyper\",\"decoder\":\"builtin:wai@0.4.0\",\"leaves\":4,\"module_status\":null,\"path\":\"primary\",\"pin\":\"7b4371854df0aa1645ac6525b373387c0617b873d5a57748932ee0f386ea164b\",\"rendition\":0,\"tier\":\"decode-equivalence\",\"variant\":null},{\"capability\":\"wai.video.av1\",\"decoder\":\"builtin:wai@0.4.0\",\"leaves\":1,\"module_status\":null,\"path\":\"fallback\",\"pin\":null,\"rendition\":null,\"tier\":null,\"variant\":null},{\"capability\":\"wai.video.int_refine\",\"decoder\":\"builtin:wai@0.4.0\",\"leaves\":4,\"module_status\":null,\"path\":\"primary\",\"pin\":null,\"rendition\":null,\"tier\":null,\"variant\":null}],\"energy\":{\"energy_calibration_ref\":null,\"energy_counter_filtering\":\"Unknown\",\"energy_provenance\":\"Measured\",\"energy_uncertainty\":{\"relative_ppm\":20000,\"window_us\":1000000},\"joules_micro\":250000},\"fallback_units\":1,\"framing\":\"registered\",\"host\":{\"build\":{\"profile\":\"release\",\"target\":\"aarch64-unknown-linux-gnu\",\"toolchain\":\"rustc 1.95.0\"},\"profile\":\"native-ffi\",\"target\":\"aarch64-unknown-linux-gnu\",\"threads\":4},\"leaf_count\":9,\"media\":\"video\",\"missed\":1,\"missed_units\":[{\"late_us\":1200,\"layers\":1,\"unit\":4}],\"output_root\":\"3cb2c68a7fe160511bd3fbbbd6945b5d54fac6b499e33769b1ea6828f04bb312\",\"primary_units\":4,\"receipt_bytes\":640,\"session_nonce\":\"57c5462dfdabd1b7bdd204d34ba33649c057eb535349f29f45eb8f8c7d4a7e7f\",\"stage_sets\":[{\"claim\":\"b636e8894207d2fe59add1e1cacf3b52ea760fccb4dc3f0abce79be90e871640\",\"first_unit\":0}],\"switches\":[{\"from\":\"primary\",\"reason\":\"set-incomplete\",\"to\":\"fallback\",\"unit\":4}],\"switches_total\":1,\"transferred\":13607,\"uncounted\":2,\"units\":5},\"class\":\"reconstruct-session\",\"issued_at\":\"2026-09-27T12:00:00Z\",\"kind\":\"claim\",\"parent_receipt_hash\":null,\"seq\":0,\"sig\":\"0482fb674a1f7f63070d5fe2374aedeb50c5a967b8cd31a9299608597bb75344daba4036c36d42dbbbc71aa137cb9a5ecf1d3355c3a9816fbdea5bb05ce2bf0b\",\"signer_id\":\"did:example:sink\",\"signer_pubkey\":\"d759793bbc13a2819a827c76adb6fba8a49aee007f49f2d0992d99b825ad2c48\",\"subject\":\"64c0713cb176874607bf8670295242184b7868a9ff7c55554a5ae08de2c301c1\",\"subject_type\":\"object\"}", + "expected": { + "outcome": "reject", + "step": 4, + "reason": "energy_unknown_acquisition" + } + }, + { + "name": "session_energy_legacy_acquisition", + "about": "the legacy HwShunt", + "procedure": "claim", + "receipt": "{\"body\":{\"classical_declared\":700,\"classical_source\":\"wai2-table\",\"counted_discarded\":1904,\"counted_fallback\":0,\"counted_primary\":5607,\"deadline_us\":40000,\"decoders\":[{\"capability\":\"wai.video.int_hyper\",\"decoder\":\"builtin:wai@0.4.0\",\"leaves\":4,\"module_status\":null,\"path\":\"primary\",\"pin\":\"7b4371854df0aa1645ac6525b373387c0617b873d5a57748932ee0f386ea164b\",\"rendition\":0,\"tier\":\"decode-equivalence\",\"variant\":null},{\"capability\":\"wai.video.av1\",\"decoder\":\"builtin:wai@0.4.0\",\"leaves\":1,\"module_status\":null,\"path\":\"fallback\",\"pin\":null,\"rendition\":null,\"tier\":null,\"variant\":null},{\"capability\":\"wai.video.int_refine\",\"decoder\":\"builtin:wai@0.4.0\",\"leaves\":4,\"module_status\":null,\"path\":\"primary\",\"pin\":null,\"rendition\":null,\"tier\":null,\"variant\":null}],\"energy\":{\"energy_calibration_ref\":null,\"energy_counter_filtering\":\"Unknown\",\"energy_provenance\":\"HwShunt\",\"energy_uncertainty\":{\"relative_ppm\":20000,\"window_us\":1000000},\"joules_micro\":250000},\"fallback_units\":1,\"framing\":\"registered\",\"host\":{\"build\":{\"profile\":\"release\",\"target\":\"aarch64-unknown-linux-gnu\",\"toolchain\":\"rustc 1.95.0\"},\"profile\":\"native-ffi\",\"target\":\"aarch64-unknown-linux-gnu\",\"threads\":4},\"leaf_count\":9,\"media\":\"video\",\"missed\":1,\"missed_units\":[{\"late_us\":1200,\"layers\":1,\"unit\":4}],\"output_root\":\"3cb2c68a7fe160511bd3fbbbd6945b5d54fac6b499e33769b1ea6828f04bb312\",\"primary_units\":4,\"receipt_bytes\":640,\"session_nonce\":\"57c5462dfdabd1b7bdd204d34ba33649c057eb535349f29f45eb8f8c7d4a7e7f\",\"stage_sets\":[{\"claim\":\"b636e8894207d2fe59add1e1cacf3b52ea760fccb4dc3f0abce79be90e871640\",\"first_unit\":0}],\"switches\":[{\"from\":\"primary\",\"reason\":\"set-incomplete\",\"to\":\"fallback\",\"unit\":4}],\"switches_total\":1,\"transferred\":13607,\"uncounted\":2,\"units\":5},\"class\":\"reconstruct-session\",\"issued_at\":\"2026-09-27T12:00:00Z\",\"kind\":\"claim\",\"parent_receipt_hash\":null,\"seq\":0,\"sig\":\"4f46b62927cf7d956e271973766ed29e170f00aade1d3d5f9f985df264d9a1ec28841642c995c056cebb1f9fedbcbba499edcd0360b42f94529a701d81e10f03\",\"signer_id\":\"did:example:sink\",\"signer_pubkey\":\"d759793bbc13a2819a827c76adb6fba8a49aee007f49f2d0992d99b825ad2c48\",\"subject\":\"64c0713cb176874607bf8670295242184b7868a9ff7c55554a5ae08de2c301c1\",\"subject_type\":\"object\"}", + "expected": { + "outcome": "reject", + "step": 4, + "reason": "energy_legacy_acquisition" + } + }, + { + "name": "session_energy_no_uncertainty", + "about": "an OnChipCounter figure with no declared uncertainty", + "procedure": "claim", + "receipt": "{\"body\":{\"classical_declared\":700,\"classical_source\":\"wai2-table\",\"counted_discarded\":1904,\"counted_fallback\":0,\"counted_primary\":5607,\"deadline_us\":40000,\"decoders\":[{\"capability\":\"wai.video.int_hyper\",\"decoder\":\"builtin:wai@0.4.0\",\"leaves\":4,\"module_status\":null,\"path\":\"primary\",\"pin\":\"7b4371854df0aa1645ac6525b373387c0617b873d5a57748932ee0f386ea164b\",\"rendition\":0,\"tier\":\"decode-equivalence\",\"variant\":null},{\"capability\":\"wai.video.av1\",\"decoder\":\"builtin:wai@0.4.0\",\"leaves\":1,\"module_status\":null,\"path\":\"fallback\",\"pin\":null,\"rendition\":null,\"tier\":null,\"variant\":null},{\"capability\":\"wai.video.int_refine\",\"decoder\":\"builtin:wai@0.4.0\",\"leaves\":4,\"module_status\":null,\"path\":\"primary\",\"pin\":null,\"rendition\":null,\"tier\":null,\"variant\":null}],\"energy\":{\"energy_calibration_ref\":null,\"energy_counter_filtering\":\"Unknown\",\"energy_provenance\":\"OnChipCounter\",\"energy_uncertainty\":null,\"joules_micro\":250000},\"fallback_units\":1,\"framing\":\"registered\",\"host\":{\"build\":{\"profile\":\"release\",\"target\":\"aarch64-unknown-linux-gnu\",\"toolchain\":\"rustc 1.95.0\"},\"profile\":\"native-ffi\",\"target\":\"aarch64-unknown-linux-gnu\",\"threads\":4},\"leaf_count\":9,\"media\":\"video\",\"missed\":1,\"missed_units\":[{\"late_us\":1200,\"layers\":1,\"unit\":4}],\"output_root\":\"3cb2c68a7fe160511bd3fbbbd6945b5d54fac6b499e33769b1ea6828f04bb312\",\"primary_units\":4,\"receipt_bytes\":640,\"session_nonce\":\"57c5462dfdabd1b7bdd204d34ba33649c057eb535349f29f45eb8f8c7d4a7e7f\",\"stage_sets\":[{\"claim\":\"b636e8894207d2fe59add1e1cacf3b52ea760fccb4dc3f0abce79be90e871640\",\"first_unit\":0}],\"switches\":[{\"from\":\"primary\",\"reason\":\"set-incomplete\",\"to\":\"fallback\",\"unit\":4}],\"switches_total\":1,\"transferred\":13607,\"uncounted\":2,\"units\":5},\"class\":\"reconstruct-session\",\"issued_at\":\"2026-09-27T12:00:00Z\",\"kind\":\"claim\",\"parent_receipt_hash\":null,\"seq\":0,\"sig\":\"36876196eabfee0b83b0c398146688a3e69789d6308c05be9a34289303055831ec92d68f577a86942c1610cbd251e2eb36e43545a2de75f1e3ed78fe376f440a\",\"signer_id\":\"did:example:sink\",\"signer_pubkey\":\"d759793bbc13a2819a827c76adb6fba8a49aee007f49f2d0992d99b825ad2c48\",\"subject\":\"64c0713cb176874607bf8670295242184b7868a9ff7c55554a5ae08de2c301c1\",\"subject_type\":\"object\"}", + "expected": { + "outcome": "reject", + "step": 4, + "reason": "energy_acquisition_evidence" + } + }, + { + "name": "session_energy_below_resolution", + "about": "a 1 microjoule OnChipCounter figure declared below the resolution floor", + "procedure": "claim", + "receipt": "{\"body\":{\"classical_declared\":700,\"classical_source\":\"wai2-table\",\"counted_discarded\":1904,\"counted_fallback\":0,\"counted_primary\":5607,\"deadline_us\":40000,\"decoders\":[{\"capability\":\"wai.video.int_hyper\",\"decoder\":\"builtin:wai@0.4.0\",\"leaves\":4,\"module_status\":null,\"path\":\"primary\",\"pin\":\"7b4371854df0aa1645ac6525b373387c0617b873d5a57748932ee0f386ea164b\",\"rendition\":0,\"tier\":\"decode-equivalence\",\"variant\":null},{\"capability\":\"wai.video.av1\",\"decoder\":\"builtin:wai@0.4.0\",\"leaves\":1,\"module_status\":null,\"path\":\"fallback\",\"pin\":null,\"rendition\":null,\"tier\":null,\"variant\":null},{\"capability\":\"wai.video.int_refine\",\"decoder\":\"builtin:wai@0.4.0\",\"leaves\":4,\"module_status\":null,\"path\":\"primary\",\"pin\":null,\"rendition\":null,\"tier\":null,\"variant\":null}],\"energy\":{\"energy_calibration_ref\":null,\"energy_counter_filtering\":\"Unknown\",\"energy_provenance\":\"OnChipCounter\",\"energy_uncertainty\":{\"relative_ppm\":288675,\"window_us\":1000000},\"joules_micro\":1},\"fallback_units\":1,\"framing\":\"registered\",\"host\":{\"build\":{\"profile\":\"release\",\"target\":\"aarch64-unknown-linux-gnu\",\"toolchain\":\"rustc 1.95.0\"},\"profile\":\"native-ffi\",\"target\":\"aarch64-unknown-linux-gnu\",\"threads\":4},\"leaf_count\":9,\"media\":\"video\",\"missed\":1,\"missed_units\":[{\"late_us\":1200,\"layers\":1,\"unit\":4}],\"output_root\":\"3cb2c68a7fe160511bd3fbbbd6945b5d54fac6b499e33769b1ea6828f04bb312\",\"primary_units\":4,\"receipt_bytes\":640,\"session_nonce\":\"57c5462dfdabd1b7bdd204d34ba33649c057eb535349f29f45eb8f8c7d4a7e7f\",\"stage_sets\":[{\"claim\":\"b636e8894207d2fe59add1e1cacf3b52ea760fccb4dc3f0abce79be90e871640\",\"first_unit\":0}],\"switches\":[{\"from\":\"primary\",\"reason\":\"set-incomplete\",\"to\":\"fallback\",\"unit\":4}],\"switches_total\":1,\"transferred\":13607,\"uncounted\":2,\"units\":5},\"class\":\"reconstruct-session\",\"issued_at\":\"2026-09-27T12:00:00Z\",\"kind\":\"claim\",\"parent_receipt_hash\":null,\"seq\":0,\"sig\":\"509f60eaf1a8408555c1630ea28824c2edb3d9ad321f46bab6062e55892fa125e079f1155c37a3df4961e425985a4130f196d15a979a13035cd93441f415d203\",\"signer_id\":\"did:example:sink\",\"signer_pubkey\":\"d759793bbc13a2819a827c76adb6fba8a49aee007f49f2d0992d99b825ad2c48\",\"subject\":\"64c0713cb176874607bf8670295242184b7868a9ff7c55554a5ae08de2c301c1\",\"subject_type\":\"object\"}", + "expected": { + "outcome": "reject", + "step": 4, + "reason": "energy_acquisition_evidence" + } + }, + { + "name": "session_about_a_receipt", + "about": "a session whose subject is a receipt", + "procedure": "claim", + "receipt": "{\"body\":{\"classical_declared\":700,\"classical_source\":\"wai2-table\",\"counted_discarded\":1904,\"counted_fallback\":0,\"counted_primary\":5607,\"deadline_us\":40000,\"decoders\":[{\"capability\":\"wai.video.int_hyper\",\"decoder\":\"builtin:wai@0.4.0\",\"leaves\":4,\"module_status\":null,\"path\":\"primary\",\"pin\":\"7b4371854df0aa1645ac6525b373387c0617b873d5a57748932ee0f386ea164b\",\"rendition\":0,\"tier\":\"decode-equivalence\",\"variant\":null},{\"capability\":\"wai.video.av1\",\"decoder\":\"builtin:wai@0.4.0\",\"leaves\":1,\"module_status\":null,\"path\":\"fallback\",\"pin\":null,\"rendition\":null,\"tier\":null,\"variant\":null},{\"capability\":\"wai.video.int_refine\",\"decoder\":\"builtin:wai@0.4.0\",\"leaves\":4,\"module_status\":null,\"path\":\"primary\",\"pin\":null,\"rendition\":null,\"tier\":null,\"variant\":null}],\"energy\":null,\"fallback_units\":1,\"framing\":\"registered\",\"host\":{\"build\":{\"profile\":\"release\",\"target\":\"aarch64-unknown-linux-gnu\",\"toolchain\":\"rustc 1.95.0\"},\"profile\":\"native-ffi\",\"target\":\"aarch64-unknown-linux-gnu\",\"threads\":4},\"leaf_count\":9,\"media\":\"video\",\"missed\":1,\"missed_units\":[{\"late_us\":1200,\"layers\":1,\"unit\":4}],\"output_root\":\"3cb2c68a7fe160511bd3fbbbd6945b5d54fac6b499e33769b1ea6828f04bb312\",\"primary_units\":4,\"receipt_bytes\":640,\"session_nonce\":\"57c5462dfdabd1b7bdd204d34ba33649c057eb535349f29f45eb8f8c7d4a7e7f\",\"stage_sets\":[{\"claim\":\"b636e8894207d2fe59add1e1cacf3b52ea760fccb4dc3f0abce79be90e871640\",\"first_unit\":0}],\"switches\":[{\"from\":\"primary\",\"reason\":\"set-incomplete\",\"to\":\"fallback\",\"unit\":4}],\"switches_total\":1,\"transferred\":13607,\"uncounted\":2,\"units\":5},\"class\":\"reconstruct-session\",\"issued_at\":\"2026-09-27T12:00:00Z\",\"kind\":\"claim\",\"parent_receipt_hash\":null,\"seq\":0,\"sig\":\"c93617905d7e4b565e20a97793d9efe4749d25e1aed192148191047d7cd54e8e9e5dba891fe57f38f136b0d3b5d62944308829fb93dad175e34da5f78588470f\",\"signer_id\":\"did:example:sink\",\"signer_pubkey\":\"d759793bbc13a2819a827c76adb6fba8a49aee007f49f2d0992d99b825ad2c48\",\"subject\":\"64c0713cb176874607bf8670295242184b7868a9ff7c55554a5ae08de2c301c1\",\"subject_type\":\"receipt\"}", + "expected": { + "outcome": "reject", + "step": 1, + "reason": "subject_type_not_admitted" + } + }, + { + "name": "session_missing_member", + "about": "a session with no uncounted member", + "procedure": "claim", + "receipt": "{\"body\":{\"classical_declared\":700,\"classical_source\":\"wai2-table\",\"counted_discarded\":1904,\"counted_fallback\":0,\"counted_primary\":5607,\"deadline_us\":40000,\"decoders\":[{\"capability\":\"wai.video.int_hyper\",\"decoder\":\"builtin:wai@0.4.0\",\"leaves\":4,\"module_status\":null,\"path\":\"primary\",\"pin\":\"7b4371854df0aa1645ac6525b373387c0617b873d5a57748932ee0f386ea164b\",\"rendition\":0,\"tier\":\"decode-equivalence\",\"variant\":null},{\"capability\":\"wai.video.av1\",\"decoder\":\"builtin:wai@0.4.0\",\"leaves\":1,\"module_status\":null,\"path\":\"fallback\",\"pin\":null,\"rendition\":null,\"tier\":null,\"variant\":null},{\"capability\":\"wai.video.int_refine\",\"decoder\":\"builtin:wai@0.4.0\",\"leaves\":4,\"module_status\":null,\"path\":\"primary\",\"pin\":null,\"rendition\":null,\"tier\":null,\"variant\":null}],\"energy\":null,\"fallback_units\":1,\"framing\":\"registered\",\"host\":{\"build\":{\"profile\":\"release\",\"target\":\"aarch64-unknown-linux-gnu\",\"toolchain\":\"rustc 1.95.0\"},\"profile\":\"native-ffi\",\"target\":\"aarch64-unknown-linux-gnu\",\"threads\":4},\"leaf_count\":9,\"media\":\"video\",\"missed\":1,\"missed_units\":[{\"late_us\":1200,\"layers\":1,\"unit\":4}],\"output_root\":\"3cb2c68a7fe160511bd3fbbbd6945b5d54fac6b499e33769b1ea6828f04bb312\",\"primary_units\":4,\"receipt_bytes\":640,\"session_nonce\":\"57c5462dfdabd1b7bdd204d34ba33649c057eb535349f29f45eb8f8c7d4a7e7f\",\"stage_sets\":[{\"claim\":\"b636e8894207d2fe59add1e1cacf3b52ea760fccb4dc3f0abce79be90e871640\",\"first_unit\":0}],\"switches\":[{\"from\":\"primary\",\"reason\":\"set-incomplete\",\"to\":\"fallback\",\"unit\":4}],\"switches_total\":1,\"transferred\":13607,\"units\":5},\"class\":\"reconstruct-session\",\"issued_at\":\"2026-09-27T12:00:00Z\",\"kind\":\"claim\",\"parent_receipt_hash\":null,\"seq\":0,\"sig\":\"d67f72309842d73d9a1a1c056811127b37326a9a7457235ce45289d9f70c9a208e34e93e2520c62962090b86481f0c0d40356af1fc4723060f4d08abdbbe5b0a\",\"signer_id\":\"did:example:sink\",\"signer_pubkey\":\"d759793bbc13a2819a827c76adb6fba8a49aee007f49f2d0992d99b825ad2c48\",\"subject\":\"64c0713cb176874607bf8670295242184b7868a9ff7c55554a5ae08de2c301c1\",\"subject_type\":\"object\"}", + "expected": { + "outcome": "reject", + "step": 2, + "reason": "missing_required_field" + } + }, + { + "name": "session_unknown_member", + "about": "a session with a member the class does not define", + "procedure": "claim", + "receipt": "{\"body\":{\"classical_declared\":700,\"classical_source\":\"wai2-table\",\"counted_discarded\":1904,\"counted_fallback\":0,\"counted_primary\":5607,\"deadline_us\":40000,\"decoders\":[{\"capability\":\"wai.video.int_hyper\",\"decoder\":\"builtin:wai@0.4.0\",\"leaves\":4,\"module_status\":null,\"path\":\"primary\",\"pin\":\"7b4371854df0aa1645ac6525b373387c0617b873d5a57748932ee0f386ea164b\",\"rendition\":0,\"tier\":\"decode-equivalence\",\"variant\":null},{\"capability\":\"wai.video.av1\",\"decoder\":\"builtin:wai@0.4.0\",\"leaves\":1,\"module_status\":null,\"path\":\"fallback\",\"pin\":null,\"rendition\":null,\"tier\":null,\"variant\":null},{\"capability\":\"wai.video.int_refine\",\"decoder\":\"builtin:wai@0.4.0\",\"leaves\":4,\"module_status\":null,\"path\":\"primary\",\"pin\":null,\"rendition\":null,\"tier\":null,\"variant\":null}],\"energy\":null,\"fallback_units\":1,\"framing\":\"registered\",\"host\":{\"build\":{\"profile\":\"release\",\"target\":\"aarch64-unknown-linux-gnu\",\"toolchain\":\"rustc 1.95.0\"},\"profile\":\"native-ffi\",\"target\":\"aarch64-unknown-linux-gnu\",\"threads\":4},\"leaf_count\":9,\"media\":\"video\",\"missed\":1,\"missed_units\":[{\"late_us\":1200,\"layers\":1,\"unit\":4}],\"output_root\":\"3cb2c68a7fe160511bd3fbbbd6945b5d54fac6b499e33769b1ea6828f04bb312\",\"primary_units\":4,\"receipt_bytes\":640,\"refinements_missing\":0,\"session_nonce\":\"57c5462dfdabd1b7bdd204d34ba33649c057eb535349f29f45eb8f8c7d4a7e7f\",\"stage_sets\":[{\"claim\":\"b636e8894207d2fe59add1e1cacf3b52ea760fccb4dc3f0abce79be90e871640\",\"first_unit\":0}],\"switches\":[{\"from\":\"primary\",\"reason\":\"set-incomplete\",\"to\":\"fallback\",\"unit\":4}],\"switches_total\":1,\"transferred\":13607,\"uncounted\":2,\"units\":5},\"class\":\"reconstruct-session\",\"issued_at\":\"2026-09-27T12:00:00Z\",\"kind\":\"claim\",\"parent_receipt_hash\":null,\"seq\":0,\"sig\":\"f0709ac3b7d28bf4a257db21e09f1726d4f9495d65078b125620eabe33b52f8c18524af88f6e7a8e2241b6c84fcc618d95979c7a57ad1896e8b80f58f8a18a0d\",\"signer_id\":\"did:example:sink\",\"signer_pubkey\":\"d759793bbc13a2819a827c76adb6fba8a49aee007f49f2d0992d99b825ad2c48\",\"subject\":\"64c0713cb176874607bf8670295242184b7868a9ff7c55554a5ae08de2c301c1\",\"subject_type\":\"object\"}", + "expected": { + "outcome": "reject", + "step": 2, + "reason": "unknown_member" + } + }, + { + "name": "session_media_uppercase", + "about": "media with an uppercase letter", + "procedure": "claim", + "receipt": "{\"body\":{\"classical_declared\":700,\"classical_source\":\"wai2-table\",\"counted_discarded\":1904,\"counted_fallback\":0,\"counted_primary\":5607,\"deadline_us\":40000,\"decoders\":[{\"capability\":\"wai.video.int_hyper\",\"decoder\":\"builtin:wai@0.4.0\",\"leaves\":4,\"module_status\":null,\"path\":\"primary\",\"pin\":\"7b4371854df0aa1645ac6525b373387c0617b873d5a57748932ee0f386ea164b\",\"rendition\":0,\"tier\":\"decode-equivalence\",\"variant\":null},{\"capability\":\"wai.video.av1\",\"decoder\":\"builtin:wai@0.4.0\",\"leaves\":1,\"module_status\":null,\"path\":\"fallback\",\"pin\":null,\"rendition\":null,\"tier\":null,\"variant\":null},{\"capability\":\"wai.video.int_refine\",\"decoder\":\"builtin:wai@0.4.0\",\"leaves\":4,\"module_status\":null,\"path\":\"primary\",\"pin\":null,\"rendition\":null,\"tier\":null,\"variant\":null}],\"energy\":null,\"fallback_units\":1,\"framing\":\"registered\",\"host\":{\"build\":{\"profile\":\"release\",\"target\":\"aarch64-unknown-linux-gnu\",\"toolchain\":\"rustc 1.95.0\"},\"profile\":\"native-ffi\",\"target\":\"aarch64-unknown-linux-gnu\",\"threads\":4},\"leaf_count\":9,\"media\":\"Video\",\"missed\":1,\"missed_units\":[{\"late_us\":1200,\"layers\":1,\"unit\":4}],\"output_root\":\"3cb2c68a7fe160511bd3fbbbd6945b5d54fac6b499e33769b1ea6828f04bb312\",\"primary_units\":4,\"receipt_bytes\":640,\"session_nonce\":\"57c5462dfdabd1b7bdd204d34ba33649c057eb535349f29f45eb8f8c7d4a7e7f\",\"stage_sets\":[{\"claim\":\"b636e8894207d2fe59add1e1cacf3b52ea760fccb4dc3f0abce79be90e871640\",\"first_unit\":0}],\"switches\":[{\"from\":\"primary\",\"reason\":\"set-incomplete\",\"to\":\"fallback\",\"unit\":4}],\"switches_total\":1,\"transferred\":13607,\"uncounted\":2,\"units\":5},\"class\":\"reconstruct-session\",\"issued_at\":\"2026-09-27T12:00:00Z\",\"kind\":\"claim\",\"parent_receipt_hash\":null,\"seq\":0,\"sig\":\"f910814fa94d7da137a4bf6de3e461fc5e0cd9615b567d5066dfa718986faeb3ea7ca1fec73a11a0ea51fe5cb9db42443b0ca3fa4ea775b6f714e0f36e261808\",\"signer_id\":\"did:example:sink\",\"signer_pubkey\":\"d759793bbc13a2819a827c76adb6fba8a49aee007f49f2d0992d99b825ad2c48\",\"subject\":\"64c0713cb176874607bf8670295242184b7868a9ff7c55554a5ae08de2c301c1\",\"subject_type\":\"object\"}", + "expected": { + "outcome": "reject", + "step": 2, + "reason": "field_type" + } + }, + { + "name": "session_framing_unknown", + "about": "a framing label this revision does not define", + "procedure": "claim", + "receipt": "{\"body\":{\"classical_declared\":700,\"classical_source\":\"wai2-table\",\"counted_discarded\":1904,\"counted_fallback\":0,\"counted_primary\":5607,\"deadline_us\":40000,\"decoders\":[{\"capability\":\"wai.video.int_hyper\",\"decoder\":\"builtin:wai@0.4.0\",\"leaves\":4,\"module_status\":null,\"path\":\"primary\",\"pin\":\"7b4371854df0aa1645ac6525b373387c0617b873d5a57748932ee0f386ea164b\",\"rendition\":0,\"tier\":\"decode-equivalence\",\"variant\":null},{\"capability\":\"wai.video.av1\",\"decoder\":\"builtin:wai@0.4.0\",\"leaves\":1,\"module_status\":null,\"path\":\"fallback\",\"pin\":null,\"rendition\":null,\"tier\":null,\"variant\":null},{\"capability\":\"wai.video.int_refine\",\"decoder\":\"builtin:wai@0.4.0\",\"leaves\":4,\"module_status\":null,\"path\":\"primary\",\"pin\":null,\"rendition\":null,\"tier\":null,\"variant\":null}],\"energy\":null,\"fallback_units\":1,\"framing\":\"wai-measure/0\",\"host\":{\"build\":{\"profile\":\"release\",\"target\":\"aarch64-unknown-linux-gnu\",\"toolchain\":\"rustc 1.95.0\"},\"profile\":\"native-ffi\",\"target\":\"aarch64-unknown-linux-gnu\",\"threads\":4},\"leaf_count\":9,\"media\":\"video\",\"missed\":1,\"missed_units\":[{\"late_us\":1200,\"layers\":1,\"unit\":4}],\"output_root\":\"3cb2c68a7fe160511bd3fbbbd6945b5d54fac6b499e33769b1ea6828f04bb312\",\"primary_units\":4,\"receipt_bytes\":640,\"session_nonce\":\"57c5462dfdabd1b7bdd204d34ba33649c057eb535349f29f45eb8f8c7d4a7e7f\",\"stage_sets\":[{\"claim\":\"b636e8894207d2fe59add1e1cacf3b52ea760fccb4dc3f0abce79be90e871640\",\"first_unit\":0}],\"switches\":[{\"from\":\"primary\",\"reason\":\"set-incomplete\",\"to\":\"fallback\",\"unit\":4}],\"switches_total\":1,\"transferred\":13607,\"uncounted\":2,\"units\":5},\"class\":\"reconstruct-session\",\"issued_at\":\"2026-09-27T12:00:00Z\",\"kind\":\"claim\",\"parent_receipt_hash\":null,\"seq\":0,\"sig\":\"0a65617e643bfd62fee98053430d02054215c11d00059c93c0cc298aefbb6864a7b85a3e107b1c3925b7fca38166906b8173c3efee45174f7e2069541410d704\",\"signer_id\":\"did:example:sink\",\"signer_pubkey\":\"d759793bbc13a2819a827c76adb6fba8a49aee007f49f2d0992d99b825ad2c48\",\"subject\":\"64c0713cb176874607bf8670295242184b7868a9ff7c55554a5ae08de2c301c1\",\"subject_type\":\"object\"}", + "expected": { + "outcome": "reject", + "step": 2, + "reason": "field_type" + } + }, + { + "name": "session_host_profile_unknown", + "about": "a host profile outside its enumeration", + "procedure": "claim", + "receipt": "{\"body\":{\"classical_declared\":700,\"classical_source\":\"wai2-table\",\"counted_discarded\":1904,\"counted_fallback\":0,\"counted_primary\":5607,\"deadline_us\":40000,\"decoders\":[{\"capability\":\"wai.video.int_hyper\",\"decoder\":\"builtin:wai@0.4.0\",\"leaves\":4,\"module_status\":null,\"path\":\"primary\",\"pin\":\"7b4371854df0aa1645ac6525b373387c0617b873d5a57748932ee0f386ea164b\",\"rendition\":0,\"tier\":\"decode-equivalence\",\"variant\":null},{\"capability\":\"wai.video.av1\",\"decoder\":\"builtin:wai@0.4.0\",\"leaves\":1,\"module_status\":null,\"path\":\"fallback\",\"pin\":null,\"rendition\":null,\"tier\":null,\"variant\":null},{\"capability\":\"wai.video.int_refine\",\"decoder\":\"builtin:wai@0.4.0\",\"leaves\":4,\"module_status\":null,\"path\":\"primary\",\"pin\":null,\"rendition\":null,\"tier\":null,\"variant\":null}],\"energy\":null,\"fallback_units\":1,\"framing\":\"registered\",\"host\":{\"build\":{\"profile\":\"release\",\"target\":\"aarch64-unknown-linux-gnu\",\"toolchain\":\"rustc 1.95.0\"},\"profile\":\"native\",\"target\":\"aarch64-unknown-linux-gnu\",\"threads\":4},\"leaf_count\":9,\"media\":\"video\",\"missed\":1,\"missed_units\":[{\"late_us\":1200,\"layers\":1,\"unit\":4}],\"output_root\":\"3cb2c68a7fe160511bd3fbbbd6945b5d54fac6b499e33769b1ea6828f04bb312\",\"primary_units\":4,\"receipt_bytes\":640,\"session_nonce\":\"57c5462dfdabd1b7bdd204d34ba33649c057eb535349f29f45eb8f8c7d4a7e7f\",\"stage_sets\":[{\"claim\":\"b636e8894207d2fe59add1e1cacf3b52ea760fccb4dc3f0abce79be90e871640\",\"first_unit\":0}],\"switches\":[{\"from\":\"primary\",\"reason\":\"set-incomplete\",\"to\":\"fallback\",\"unit\":4}],\"switches_total\":1,\"transferred\":13607,\"uncounted\":2,\"units\":5},\"class\":\"reconstruct-session\",\"issued_at\":\"2026-09-27T12:00:00Z\",\"kind\":\"claim\",\"parent_receipt_hash\":null,\"seq\":0,\"sig\":\"3d5e3dbff553be8bd04d95673b1e8347ccb42a773a650e6216471129ae246232d76c6eda2131468cf497cba18a976625fbdfac0856295d3a426aa1e262419803\",\"signer_id\":\"did:example:sink\",\"signer_pubkey\":\"d759793bbc13a2819a827c76adb6fba8a49aee007f49f2d0992d99b825ad2c48\",\"subject\":\"64c0713cb176874607bf8670295242184b7868a9ff7c55554a5ae08de2c301c1\",\"subject_type\":\"object\"}", + "expected": { + "outcome": "reject", + "step": 2, + "reason": "field_type" + } + }, + { + "name": "session_decoder_path_unknown", + "about": "a decoder entry on a path that is neither primary nor fallback", + "procedure": "claim", + "receipt": "{\"body\":{\"classical_declared\":700,\"classical_source\":\"wai2-table\",\"counted_discarded\":1904,\"counted_fallback\":0,\"counted_primary\":5607,\"deadline_us\":40000,\"decoders\":[{\"capability\":\"wai.video.int_hyper\",\"decoder\":\"builtin:wai@0.4.0\",\"leaves\":4,\"module_status\":null,\"path\":\"secondary\",\"pin\":\"7b4371854df0aa1645ac6525b373387c0617b873d5a57748932ee0f386ea164b\",\"rendition\":0,\"tier\":\"decode-equivalence\",\"variant\":null},{\"capability\":\"wai.video.av1\",\"decoder\":\"builtin:wai@0.4.0\",\"leaves\":1,\"module_status\":null,\"path\":\"fallback\",\"pin\":null,\"rendition\":null,\"tier\":null,\"variant\":null},{\"capability\":\"wai.video.int_refine\",\"decoder\":\"builtin:wai@0.4.0\",\"leaves\":4,\"module_status\":null,\"path\":\"primary\",\"pin\":null,\"rendition\":null,\"tier\":null,\"variant\":null}],\"energy\":null,\"fallback_units\":1,\"framing\":\"registered\",\"host\":{\"build\":{\"profile\":\"release\",\"target\":\"aarch64-unknown-linux-gnu\",\"toolchain\":\"rustc 1.95.0\"},\"profile\":\"native-ffi\",\"target\":\"aarch64-unknown-linux-gnu\",\"threads\":4},\"leaf_count\":9,\"media\":\"video\",\"missed\":1,\"missed_units\":[{\"late_us\":1200,\"layers\":1,\"unit\":4}],\"output_root\":\"3cb2c68a7fe160511bd3fbbbd6945b5d54fac6b499e33769b1ea6828f04bb312\",\"primary_units\":4,\"receipt_bytes\":640,\"session_nonce\":\"57c5462dfdabd1b7bdd204d34ba33649c057eb535349f29f45eb8f8c7d4a7e7f\",\"stage_sets\":[{\"claim\":\"b636e8894207d2fe59add1e1cacf3b52ea760fccb4dc3f0abce79be90e871640\",\"first_unit\":0}],\"switches\":[{\"from\":\"primary\",\"reason\":\"set-incomplete\",\"to\":\"fallback\",\"unit\":4}],\"switches_total\":1,\"transferred\":13607,\"uncounted\":2,\"units\":5},\"class\":\"reconstruct-session\",\"issued_at\":\"2026-09-27T12:00:00Z\",\"kind\":\"claim\",\"parent_receipt_hash\":null,\"seq\":0,\"sig\":\"3172c4811df5a8c76b8dc87c8da7470efe0546367968d772ce98f49663092de59451516546a8ce1ddf9790a7c7ce21cfaa7fe3e8b2c379a661efb27ff50eda0d\",\"signer_id\":\"did:example:sink\",\"signer_pubkey\":\"d759793bbc13a2819a827c76adb6fba8a49aee007f49f2d0992d99b825ad2c48\",\"subject\":\"64c0713cb176874607bf8670295242184b7868a9ff7c55554a5ae08de2c301c1\",\"subject_type\":\"object\"}", + "expected": { + "outcome": "reject", + "step": 2, + "reason": "field_type" + } + }, + { + "name": "session_decoder_entry_unknown_member", + "about": "a decoder entry with a component member, which the entry does not define", + "procedure": "claim", + "receipt": "{\"body\":{\"classical_declared\":700,\"classical_source\":\"wai2-table\",\"counted_discarded\":1904,\"counted_fallback\":0,\"counted_primary\":5607,\"deadline_us\":40000,\"decoders\":[{\"capability\":\"wai.video.int_hyper\",\"component\":\"c0\",\"decoder\":\"builtin:wai@0.4.0\",\"leaves\":4,\"module_status\":null,\"path\":\"primary\",\"pin\":\"7b4371854df0aa1645ac6525b373387c0617b873d5a57748932ee0f386ea164b\",\"rendition\":0,\"tier\":\"decode-equivalence\",\"variant\":null},{\"capability\":\"wai.video.av1\",\"decoder\":\"builtin:wai@0.4.0\",\"leaves\":1,\"module_status\":null,\"path\":\"fallback\",\"pin\":null,\"rendition\":null,\"tier\":null,\"variant\":null},{\"capability\":\"wai.video.int_refine\",\"decoder\":\"builtin:wai@0.4.0\",\"leaves\":4,\"module_status\":null,\"path\":\"primary\",\"pin\":null,\"rendition\":null,\"tier\":null,\"variant\":null}],\"energy\":null,\"fallback_units\":1,\"framing\":\"registered\",\"host\":{\"build\":{\"profile\":\"release\",\"target\":\"aarch64-unknown-linux-gnu\",\"toolchain\":\"rustc 1.95.0\"},\"profile\":\"native-ffi\",\"target\":\"aarch64-unknown-linux-gnu\",\"threads\":4},\"leaf_count\":9,\"media\":\"video\",\"missed\":1,\"missed_units\":[{\"late_us\":1200,\"layers\":1,\"unit\":4}],\"output_root\":\"3cb2c68a7fe160511bd3fbbbd6945b5d54fac6b499e33769b1ea6828f04bb312\",\"primary_units\":4,\"receipt_bytes\":640,\"session_nonce\":\"57c5462dfdabd1b7bdd204d34ba33649c057eb535349f29f45eb8f8c7d4a7e7f\",\"stage_sets\":[{\"claim\":\"b636e8894207d2fe59add1e1cacf3b52ea760fccb4dc3f0abce79be90e871640\",\"first_unit\":0}],\"switches\":[{\"from\":\"primary\",\"reason\":\"set-incomplete\",\"to\":\"fallback\",\"unit\":4}],\"switches_total\":1,\"transferred\":13607,\"uncounted\":2,\"units\":5},\"class\":\"reconstruct-session\",\"issued_at\":\"2026-09-27T12:00:00Z\",\"kind\":\"claim\",\"parent_receipt_hash\":null,\"seq\":0,\"sig\":\"2f5217a90a6e6dcd1d9a0aa870b62d50ed3e01c43616dd4e6758e03699146c22dcba3e460db50fb01d015512582ffea1755f2d2db30d861e8940b6b61d1c8c0d\",\"signer_id\":\"did:example:sink\",\"signer_pubkey\":\"d759793bbc13a2819a827c76adb6fba8a49aee007f49f2d0992d99b825ad2c48\",\"subject\":\"64c0713cb176874607bf8670295242184b7868a9ff7c55554a5ae08de2c301c1\",\"subject_type\":\"object\"}", + "expected": { + "outcome": "reject", + "step": 2, + "reason": "unknown_member" + } + }, + { + "name": "session_count_as_string", + "about": "units written as a string", + "procedure": "claim", + "receipt": "{\"body\":{\"classical_declared\":700,\"classical_source\":\"wai2-table\",\"counted_discarded\":1904,\"counted_fallback\":0,\"counted_primary\":5607,\"deadline_us\":40000,\"decoders\":[{\"capability\":\"wai.video.int_hyper\",\"decoder\":\"builtin:wai@0.4.0\",\"leaves\":4,\"module_status\":null,\"path\":\"primary\",\"pin\":\"7b4371854df0aa1645ac6525b373387c0617b873d5a57748932ee0f386ea164b\",\"rendition\":0,\"tier\":\"decode-equivalence\",\"variant\":null},{\"capability\":\"wai.video.av1\",\"decoder\":\"builtin:wai@0.4.0\",\"leaves\":1,\"module_status\":null,\"path\":\"fallback\",\"pin\":null,\"rendition\":null,\"tier\":null,\"variant\":null},{\"capability\":\"wai.video.int_refine\",\"decoder\":\"builtin:wai@0.4.0\",\"leaves\":4,\"module_status\":null,\"path\":\"primary\",\"pin\":null,\"rendition\":null,\"tier\":null,\"variant\":null}],\"energy\":null,\"fallback_units\":1,\"framing\":\"registered\",\"host\":{\"build\":{\"profile\":\"release\",\"target\":\"aarch64-unknown-linux-gnu\",\"toolchain\":\"rustc 1.95.0\"},\"profile\":\"native-ffi\",\"target\":\"aarch64-unknown-linux-gnu\",\"threads\":4},\"leaf_count\":9,\"media\":\"video\",\"missed\":1,\"missed_units\":[{\"late_us\":1200,\"layers\":1,\"unit\":4}],\"output_root\":\"3cb2c68a7fe160511bd3fbbbd6945b5d54fac6b499e33769b1ea6828f04bb312\",\"primary_units\":4,\"receipt_bytes\":640,\"session_nonce\":\"57c5462dfdabd1b7bdd204d34ba33649c057eb535349f29f45eb8f8c7d4a7e7f\",\"stage_sets\":[{\"claim\":\"b636e8894207d2fe59add1e1cacf3b52ea760fccb4dc3f0abce79be90e871640\",\"first_unit\":0}],\"switches\":[{\"from\":\"primary\",\"reason\":\"set-incomplete\",\"to\":\"fallback\",\"unit\":4}],\"switches_total\":1,\"transferred\":13607,\"uncounted\":2,\"units\":\"5\"},\"class\":\"reconstruct-session\",\"issued_at\":\"2026-09-27T12:00:00Z\",\"kind\":\"claim\",\"parent_receipt_hash\":null,\"seq\":0,\"sig\":\"d16db648eacd7914df37040d08ca6346c8048cb0fe2102244b60f08e929f1677e71c2112a161356d4a2896365f3411e789dc6f51bf8a04121b36fe50aa6e5704\",\"signer_id\":\"did:example:sink\",\"signer_pubkey\":\"d759793bbc13a2819a827c76adb6fba8a49aee007f49f2d0992d99b825ad2c48\",\"subject\":\"64c0713cb176874607bf8670295242184b7868a9ff7c55554a5ae08de2c301c1\",\"subject_type\":\"object\"}", + "expected": { + "outcome": "reject", + "step": 2, + "reason": "field_type" + } + }, + { + "name": "session_host_read_before_decoders", + "about": "a host profile outside its enumeration and a decoder entry with no leaves member: the host is read first", + "procedure": "claim", + "receipt": "{\"body\":{\"classical_declared\":700,\"classical_source\":\"wai2-table\",\"counted_discarded\":1904,\"counted_fallback\":0,\"counted_primary\":5607,\"deadline_us\":40000,\"decoders\":[{\"capability\":\"wai.video.int_hyper\",\"decoder\":\"builtin:wai@0.4.0\",\"module_status\":null,\"path\":\"primary\",\"pin\":\"7b4371854df0aa1645ac6525b373387c0617b873d5a57748932ee0f386ea164b\",\"rendition\":0,\"tier\":\"decode-equivalence\",\"variant\":null},{\"capability\":\"wai.video.av1\",\"decoder\":\"builtin:wai@0.4.0\",\"leaves\":1,\"module_status\":null,\"path\":\"fallback\",\"pin\":null,\"rendition\":null,\"tier\":null,\"variant\":null},{\"capability\":\"wai.video.int_refine\",\"decoder\":\"builtin:wai@0.4.0\",\"leaves\":4,\"module_status\":null,\"path\":\"primary\",\"pin\":null,\"rendition\":null,\"tier\":null,\"variant\":null}],\"energy\":null,\"fallback_units\":1,\"framing\":\"registered\",\"host\":{\"build\":{\"profile\":\"release\",\"target\":\"aarch64-unknown-linux-gnu\",\"toolchain\":\"rustc 1.95.0\"},\"profile\":\"native\",\"target\":\"aarch64-unknown-linux-gnu\",\"threads\":4},\"leaf_count\":9,\"media\":\"video\",\"missed\":1,\"missed_units\":[{\"late_us\":1200,\"layers\":1,\"unit\":4}],\"output_root\":\"3cb2c68a7fe160511bd3fbbbd6945b5d54fac6b499e33769b1ea6828f04bb312\",\"primary_units\":4,\"receipt_bytes\":640,\"session_nonce\":\"57c5462dfdabd1b7bdd204d34ba33649c057eb535349f29f45eb8f8c7d4a7e7f\",\"stage_sets\":[{\"claim\":\"b636e8894207d2fe59add1e1cacf3b52ea760fccb4dc3f0abce79be90e871640\",\"first_unit\":0}],\"switches\":[{\"from\":\"primary\",\"reason\":\"set-incomplete\",\"to\":\"fallback\",\"unit\":4}],\"switches_total\":1,\"transferred\":13607,\"uncounted\":2,\"units\":5},\"class\":\"reconstruct-session\",\"issued_at\":\"2026-09-27T12:00:00Z\",\"kind\":\"claim\",\"parent_receipt_hash\":null,\"seq\":0,\"sig\":\"9e5199f06c35e327ed17fbaeb3f5571035b78cec6d36548c42330d958c091cb5a266f0833c29ed6db7f21789729fd2cf1bc831a047857899566e71e185294805\",\"signer_id\":\"did:example:sink\",\"signer_pubkey\":\"d759793bbc13a2819a827c76adb6fba8a49aee007f49f2d0992d99b825ad2c48\",\"subject\":\"64c0713cb176874607bf8670295242184b7868a9ff7c55554a5ae08de2c301c1\",\"subject_type\":\"object\"}", + "expected": { + "outcome": "reject", + "step": 2, + "reason": "field_type" + } + }, + { + "name": "session_energy_member_missing", + "about": "an energy object with no calibration reference member", + "procedure": "claim", + "receipt": "{\"body\":{\"classical_declared\":700,\"classical_source\":\"wai2-table\",\"counted_discarded\":1904,\"counted_fallback\":0,\"counted_primary\":5607,\"deadline_us\":40000,\"decoders\":[{\"capability\":\"wai.video.int_hyper\",\"decoder\":\"builtin:wai@0.4.0\",\"leaves\":4,\"module_status\":null,\"path\":\"primary\",\"pin\":\"7b4371854df0aa1645ac6525b373387c0617b873d5a57748932ee0f386ea164b\",\"rendition\":0,\"tier\":\"decode-equivalence\",\"variant\":null},{\"capability\":\"wai.video.av1\",\"decoder\":\"builtin:wai@0.4.0\",\"leaves\":1,\"module_status\":null,\"path\":\"fallback\",\"pin\":null,\"rendition\":null,\"tier\":null,\"variant\":null},{\"capability\":\"wai.video.int_refine\",\"decoder\":\"builtin:wai@0.4.0\",\"leaves\":4,\"module_status\":null,\"path\":\"primary\",\"pin\":null,\"rendition\":null,\"tier\":null,\"variant\":null}],\"energy\":{\"energy_counter_filtering\":\"Unknown\",\"energy_provenance\":\"OnChipCounter\",\"energy_uncertainty\":{\"relative_ppm\":20000,\"window_us\":1000000},\"joules_micro\":250000},\"fallback_units\":1,\"framing\":\"registered\",\"host\":{\"build\":{\"profile\":\"release\",\"target\":\"aarch64-unknown-linux-gnu\",\"toolchain\":\"rustc 1.95.0\"},\"profile\":\"native-ffi\",\"target\":\"aarch64-unknown-linux-gnu\",\"threads\":4},\"leaf_count\":9,\"media\":\"video\",\"missed\":1,\"missed_units\":[{\"late_us\":1200,\"layers\":1,\"unit\":4}],\"output_root\":\"3cb2c68a7fe160511bd3fbbbd6945b5d54fac6b499e33769b1ea6828f04bb312\",\"primary_units\":4,\"receipt_bytes\":640,\"session_nonce\":\"57c5462dfdabd1b7bdd204d34ba33649c057eb535349f29f45eb8f8c7d4a7e7f\",\"stage_sets\":[{\"claim\":\"b636e8894207d2fe59add1e1cacf3b52ea760fccb4dc3f0abce79be90e871640\",\"first_unit\":0}],\"switches\":[{\"from\":\"primary\",\"reason\":\"set-incomplete\",\"to\":\"fallback\",\"unit\":4}],\"switches_total\":1,\"transferred\":13607,\"uncounted\":2,\"units\":5},\"class\":\"reconstruct-session\",\"issued_at\":\"2026-09-27T12:00:00Z\",\"kind\":\"claim\",\"parent_receipt_hash\":null,\"seq\":0,\"sig\":\"750f04c38c93fd4e0b40d809057168172498c952a34dabedaee42eeba4ae14bacf4c3790c65d0c9d1ac5e996e4fcbfe655b6b0b64538a38de25fdc8f01843208\",\"signer_id\":\"did:example:sink\",\"signer_pubkey\":\"d759793bbc13a2819a827c76adb6fba8a49aee007f49f2d0992d99b825ad2c48\",\"subject\":\"64c0713cb176874607bf8670295242184b7868a9ff7c55554a5ae08de2c301c1\",\"subject_type\":\"object\"}", + "expected": { + "outcome": "reject", + "step": 2, + "reason": "missing_required_field" + } + }, + { + "name": "session_energy_rewritten", + "about": "an unmetered session given a figure after signing", + "procedure": "claim", + "receipt": "{\"body\":{\"classical_declared\":700,\"classical_source\":\"wai2-table\",\"counted_discarded\":1904,\"counted_fallback\":0,\"counted_primary\":5607,\"deadline_us\":40000,\"decoders\":[{\"capability\":\"wai.video.int_hyper\",\"decoder\":\"builtin:wai@0.4.0\",\"leaves\":4,\"module_status\":null,\"path\":\"primary\",\"pin\":\"7b4371854df0aa1645ac6525b373387c0617b873d5a57748932ee0f386ea164b\",\"rendition\":0,\"tier\":\"decode-equivalence\",\"variant\":null},{\"capability\":\"wai.video.av1\",\"decoder\":\"builtin:wai@0.4.0\",\"leaves\":1,\"module_status\":null,\"path\":\"fallback\",\"pin\":null,\"rendition\":null,\"tier\":null,\"variant\":null},{\"capability\":\"wai.video.int_refine\",\"decoder\":\"builtin:wai@0.4.0\",\"leaves\":4,\"module_status\":null,\"path\":\"primary\",\"pin\":null,\"rendition\":null,\"tier\":null,\"variant\":null}],\"energy\":{\"energy_calibration_ref\":null,\"energy_counter_filtering\":null,\"energy_provenance\":\"ModelBased\",\"energy_uncertainty\":null,\"joules_micro\":9},\"fallback_units\":1,\"framing\":\"registered\",\"host\":{\"build\":{\"profile\":\"release\",\"target\":\"aarch64-unknown-linux-gnu\",\"toolchain\":\"rustc 1.95.0\"},\"profile\":\"native-ffi\",\"target\":\"aarch64-unknown-linux-gnu\",\"threads\":4},\"leaf_count\":9,\"media\":\"video\",\"missed\":1,\"missed_units\":[{\"late_us\":1200,\"layers\":1,\"unit\":4}],\"output_root\":\"3cb2c68a7fe160511bd3fbbbd6945b5d54fac6b499e33769b1ea6828f04bb312\",\"primary_units\":4,\"receipt_bytes\":640,\"session_nonce\":\"57c5462dfdabd1b7bdd204d34ba33649c057eb535349f29f45eb8f8c7d4a7e7f\",\"stage_sets\":[{\"claim\":\"b636e8894207d2fe59add1e1cacf3b52ea760fccb4dc3f0abce79be90e871640\",\"first_unit\":0}],\"switches\":[{\"from\":\"primary\",\"reason\":\"set-incomplete\",\"to\":\"fallback\",\"unit\":4}],\"switches_total\":1,\"transferred\":13607,\"uncounted\":2,\"units\":5},\"class\":\"reconstruct-session\",\"issued_at\":\"2026-09-27T12:00:00Z\",\"kind\":\"claim\",\"parent_receipt_hash\":null,\"seq\":0,\"sig\":\"2871039f189db43685c214c860ac86567712af1e35d3254c371e7faaf8582734b5216c7ba4015383ad9013aac4c34ba1aebf410a56615d5bf2f5d73622c1410e\",\"signer_id\":\"did:example:sink\",\"signer_pubkey\":\"d759793bbc13a2819a827c76adb6fba8a49aee007f49f2d0992d99b825ad2c48\",\"subject\":\"64c0713cb176874607bf8670295242184b7868a9ff7c55554a5ae08de2c301c1\",\"subject_type\":\"object\"}", + "expected": { + "outcome": "reject", + "step": 3, + "reason": "signature_verify_failed" + } + }, + { + "name": "session_output_mismatch", + "about": "a presentation's output differs from the one the tree commits to", + "procedure": "claim", + "receipt": "{\"body\":{\"classical_declared\":700,\"classical_source\":\"wai2-table\",\"counted_discarded\":1904,\"counted_fallback\":0,\"counted_primary\":5607,\"deadline_us\":40000,\"decoders\":[{\"capability\":\"wai.video.int_hyper\",\"decoder\":\"builtin:wai@0.4.0\",\"leaves\":4,\"module_status\":null,\"path\":\"primary\",\"pin\":\"7b4371854df0aa1645ac6525b373387c0617b873d5a57748932ee0f386ea164b\",\"rendition\":0,\"tier\":\"decode-equivalence\",\"variant\":null},{\"capability\":\"wai.video.av1\",\"decoder\":\"builtin:wai@0.4.0\",\"leaves\":1,\"module_status\":null,\"path\":\"fallback\",\"pin\":null,\"rendition\":null,\"tier\":null,\"variant\":null},{\"capability\":\"wai.video.int_refine\",\"decoder\":\"builtin:wai@0.4.0\",\"leaves\":4,\"module_status\":null,\"path\":\"primary\",\"pin\":null,\"rendition\":null,\"tier\":null,\"variant\":null}],\"energy\":null,\"fallback_units\":1,\"framing\":\"registered\",\"host\":{\"build\":{\"profile\":\"release\",\"target\":\"aarch64-unknown-linux-gnu\",\"toolchain\":\"rustc 1.95.0\"},\"profile\":\"native-ffi\",\"target\":\"aarch64-unknown-linux-gnu\",\"threads\":4},\"leaf_count\":9,\"media\":\"video\",\"missed\":1,\"missed_units\":[{\"late_us\":1200,\"layers\":1,\"unit\":4}],\"output_root\":\"3cb2c68a7fe160511bd3fbbbd6945b5d54fac6b499e33769b1ea6828f04bb312\",\"primary_units\":4,\"receipt_bytes\":640,\"session_nonce\":\"57c5462dfdabd1b7bdd204d34ba33649c057eb535349f29f45eb8f8c7d4a7e7f\",\"stage_sets\":[{\"claim\":\"b636e8894207d2fe59add1e1cacf3b52ea760fccb4dc3f0abce79be90e871640\",\"first_unit\":0}],\"switches\":[{\"from\":\"primary\",\"reason\":\"set-incomplete\",\"to\":\"fallback\",\"unit\":4}],\"switches_total\":1,\"transferred\":13607,\"uncounted\":2,\"units\":5},\"class\":\"reconstruct-session\",\"issued_at\":\"2026-09-27T12:00:00Z\",\"kind\":\"claim\",\"parent_receipt_hash\":null,\"seq\":0,\"sig\":\"2871039f189db43685c214c860ac86567712af1e35d3254c371e7faaf8582734b5216c7ba4015383ad9013aac4c34ba1aebf410a56615d5bf2f5d73622c1410e\",\"signer_id\":\"did:example:sink\",\"signer_pubkey\":\"d759793bbc13a2819a827c76adb6fba8a49aee007f49f2d0992d99b825ad2c48\",\"subject\":\"64c0713cb176874607bf8670295242184b7868a9ff7c55554a5ae08de2c301c1\",\"subject_type\":\"object\"}", + "context": { + "outputs": [ + { + "unit": 0, + "layers": 1, + "decoder": 0, + "out_digest": "55f7e628ca707e2ca3159709eeb68b9000813f2916a299acd33a23e6fe012584" + }, + { + "unit": 1, + "layers": 1, + "decoder": 0, + "out_digest": "a3ee8a4b96eceb663f3d94417957d02f897fc166dc96ebe9bf447c4a36a36264" + }, + { + "unit": 2, + "layers": 1, + "decoder": 0, + "out_digest": "00576d2c4d09ef5d7aa807f9b3b1587e200dea6f6694b4da062b41aa2a5ab8af" + }, + { + "unit": 3, + "layers": 1, + "decoder": 0, + "out_digest": "4ea5ea656c476572de882be10e3f2b81e2da7d201c7b075321d2901c7e271819" + }, + { + "unit": 4, + "layers": 1, + "decoder": 1, + "out_digest": "1cd1984bc553c43ee5a48fe7e182a77e60d8ef3c2b0f959ef1a0efd3813b411f" + }, + { + "unit": 0, + "layers": 2, + "decoder": 2, + "out_digest": "cedffc10c0d2e777c954459c198af496e316170b3a8c35276a3f473edf438a0e" + }, + { + "unit": 1, + "layers": 2, + "decoder": 2, + "out_digest": "f0348794b5be95fd5c4e8f268957b6d188c35f76146f4479c960124a4392841d" + }, + { + "unit": 2, + "layers": 2, + "decoder": 2, + "out_digest": "446c9941549464ba1b15c36c6e738380f8918f4a63a47ebbbdd67058a1975a80" + }, + { + "unit": 0, + "layers": 3, + "decoder": 2, + "out_digest": "a80c01cb3ded2f965b69ec4a5b3f1dcb6996e05454d9963e0b05455f9f27bc2f" + } + ] + }, + "expected": { + "outcome": "reject", + "step": 6, + "reason": "session_output_mismatch" + } + }, + { + "name": "session_output_one_short", + "about": "a list one presentation short of leaf_count", + "procedure": "claim", + "receipt": "{\"body\":{\"classical_declared\":700,\"classical_source\":\"wai2-table\",\"counted_discarded\":1904,\"counted_fallback\":0,\"counted_primary\":5607,\"deadline_us\":40000,\"decoders\":[{\"capability\":\"wai.video.int_hyper\",\"decoder\":\"builtin:wai@0.4.0\",\"leaves\":4,\"module_status\":null,\"path\":\"primary\",\"pin\":\"7b4371854df0aa1645ac6525b373387c0617b873d5a57748932ee0f386ea164b\",\"rendition\":0,\"tier\":\"decode-equivalence\",\"variant\":null},{\"capability\":\"wai.video.av1\",\"decoder\":\"builtin:wai@0.4.0\",\"leaves\":1,\"module_status\":null,\"path\":\"fallback\",\"pin\":null,\"rendition\":null,\"tier\":null,\"variant\":null},{\"capability\":\"wai.video.int_refine\",\"decoder\":\"builtin:wai@0.4.0\",\"leaves\":4,\"module_status\":null,\"path\":\"primary\",\"pin\":null,\"rendition\":null,\"tier\":null,\"variant\":null}],\"energy\":null,\"fallback_units\":1,\"framing\":\"registered\",\"host\":{\"build\":{\"profile\":\"release\",\"target\":\"aarch64-unknown-linux-gnu\",\"toolchain\":\"rustc 1.95.0\"},\"profile\":\"native-ffi\",\"target\":\"aarch64-unknown-linux-gnu\",\"threads\":4},\"leaf_count\":9,\"media\":\"video\",\"missed\":1,\"missed_units\":[{\"late_us\":1200,\"layers\":1,\"unit\":4}],\"output_root\":\"3cb2c68a7fe160511bd3fbbbd6945b5d54fac6b499e33769b1ea6828f04bb312\",\"primary_units\":4,\"receipt_bytes\":640,\"session_nonce\":\"57c5462dfdabd1b7bdd204d34ba33649c057eb535349f29f45eb8f8c7d4a7e7f\",\"stage_sets\":[{\"claim\":\"b636e8894207d2fe59add1e1cacf3b52ea760fccb4dc3f0abce79be90e871640\",\"first_unit\":0}],\"switches\":[{\"from\":\"primary\",\"reason\":\"set-incomplete\",\"to\":\"fallback\",\"unit\":4}],\"switches_total\":1,\"transferred\":13607,\"uncounted\":2,\"units\":5},\"class\":\"reconstruct-session\",\"issued_at\":\"2026-09-27T12:00:00Z\",\"kind\":\"claim\",\"parent_receipt_hash\":null,\"seq\":0,\"sig\":\"2871039f189db43685c214c860ac86567712af1e35d3254c371e7faaf8582734b5216c7ba4015383ad9013aac4c34ba1aebf410a56615d5bf2f5d73622c1410e\",\"signer_id\":\"did:example:sink\",\"signer_pubkey\":\"d759793bbc13a2819a827c76adb6fba8a49aee007f49f2d0992d99b825ad2c48\",\"subject\":\"64c0713cb176874607bf8670295242184b7868a9ff7c55554a5ae08de2c301c1\",\"subject_type\":\"object\"}", + "context": { + "outputs": [ + { + "unit": 0, + "layers": 1, + "decoder": 0, + "out_digest": "55f7e628ca707e2ca3159709eeb68b9000813f2916a299acd33a23e6fe012584" + }, + { + "unit": 1, + "layers": 1, + "decoder": 0, + "out_digest": "a3ee8a4b96eceb663f3d94417957d02f897fc166dc96ebe9bf447c4a36a36264" + }, + { + "unit": 2, + "layers": 1, + "decoder": 0, + "out_digest": "00576d2c4d09ef5d7aa807f9b3b1587e200dea6f6694b4da062b41aa2a5ab8af" + }, + { + "unit": 3, + "layers": 1, + "decoder": 0, + "out_digest": "26cd9b2805b604b26e08d9a461db599c4e249bfd4df41a3befb202bc6d0e0700" + }, + { + "unit": 4, + "layers": 1, + "decoder": 1, + "out_digest": "1cd1984bc553c43ee5a48fe7e182a77e60d8ef3c2b0f959ef1a0efd3813b411f" + }, + { + "unit": 0, + "layers": 2, + "decoder": 2, + "out_digest": "cedffc10c0d2e777c954459c198af496e316170b3a8c35276a3f473edf438a0e" + }, + { + "unit": 1, + "layers": 2, + "decoder": 2, + "out_digest": "f0348794b5be95fd5c4e8f268957b6d188c35f76146f4479c960124a4392841d" + }, + { + "unit": 2, + "layers": 2, + "decoder": 2, + "out_digest": "446c9941549464ba1b15c36c6e738380f8918f4a63a47ebbbdd67058a1975a80" + } + ] + }, + "expected": { + "outcome": "reject", + "step": 6, + "reason": "session_output_mismatch" + } + }, + { + "name": "session_output_repeated", + "about": "a (unit, layers) presented twice", + "procedure": "claim", + "receipt": "{\"body\":{\"classical_declared\":700,\"classical_source\":\"wai2-table\",\"counted_discarded\":1904,\"counted_fallback\":0,\"counted_primary\":5607,\"deadline_us\":40000,\"decoders\":[{\"capability\":\"wai.video.int_hyper\",\"decoder\":\"builtin:wai@0.4.0\",\"leaves\":4,\"module_status\":null,\"path\":\"primary\",\"pin\":\"7b4371854df0aa1645ac6525b373387c0617b873d5a57748932ee0f386ea164b\",\"rendition\":0,\"tier\":\"decode-equivalence\",\"variant\":null},{\"capability\":\"wai.video.av1\",\"decoder\":\"builtin:wai@0.4.0\",\"leaves\":1,\"module_status\":null,\"path\":\"fallback\",\"pin\":null,\"rendition\":null,\"tier\":null,\"variant\":null},{\"capability\":\"wai.video.int_refine\",\"decoder\":\"builtin:wai@0.4.0\",\"leaves\":4,\"module_status\":null,\"path\":\"primary\",\"pin\":null,\"rendition\":null,\"tier\":null,\"variant\":null}],\"energy\":null,\"fallback_units\":1,\"framing\":\"registered\",\"host\":{\"build\":{\"profile\":\"release\",\"target\":\"aarch64-unknown-linux-gnu\",\"toolchain\":\"rustc 1.95.0\"},\"profile\":\"native-ffi\",\"target\":\"aarch64-unknown-linux-gnu\",\"threads\":4},\"leaf_count\":9,\"media\":\"video\",\"missed\":1,\"missed_units\":[{\"late_us\":1200,\"layers\":1,\"unit\":4}],\"output_root\":\"3cb2c68a7fe160511bd3fbbbd6945b5d54fac6b499e33769b1ea6828f04bb312\",\"primary_units\":4,\"receipt_bytes\":640,\"session_nonce\":\"57c5462dfdabd1b7bdd204d34ba33649c057eb535349f29f45eb8f8c7d4a7e7f\",\"stage_sets\":[{\"claim\":\"b636e8894207d2fe59add1e1cacf3b52ea760fccb4dc3f0abce79be90e871640\",\"first_unit\":0}],\"switches\":[{\"from\":\"primary\",\"reason\":\"set-incomplete\",\"to\":\"fallback\",\"unit\":4}],\"switches_total\":1,\"transferred\":13607,\"uncounted\":2,\"units\":5},\"class\":\"reconstruct-session\",\"issued_at\":\"2026-09-27T12:00:00Z\",\"kind\":\"claim\",\"parent_receipt_hash\":null,\"seq\":0,\"sig\":\"2871039f189db43685c214c860ac86567712af1e35d3254c371e7faaf8582734b5216c7ba4015383ad9013aac4c34ba1aebf410a56615d5bf2f5d73622c1410e\",\"signer_id\":\"did:example:sink\",\"signer_pubkey\":\"d759793bbc13a2819a827c76adb6fba8a49aee007f49f2d0992d99b825ad2c48\",\"subject\":\"64c0713cb176874607bf8670295242184b7868a9ff7c55554a5ae08de2c301c1\",\"subject_type\":\"object\"}", + "context": { + "outputs": [ + { + "unit": 0, + "layers": 1, + "decoder": 0, + "out_digest": "55f7e628ca707e2ca3159709eeb68b9000813f2916a299acd33a23e6fe012584" + }, + { + "unit": 1, + "layers": 1, + "decoder": 0, + "out_digest": "a3ee8a4b96eceb663f3d94417957d02f897fc166dc96ebe9bf447c4a36a36264" + }, + { + "unit": 2, + "layers": 1, + "decoder": 0, + "out_digest": "00576d2c4d09ef5d7aa807f9b3b1587e200dea6f6694b4da062b41aa2a5ab8af" + }, + { + "unit": 3, + "layers": 1, + "decoder": 0, + "out_digest": "26cd9b2805b604b26e08d9a461db599c4e249bfd4df41a3befb202bc6d0e0700" + }, + { + "unit": 4, + "layers": 1, + "decoder": 1, + "out_digest": "1cd1984bc553c43ee5a48fe7e182a77e60d8ef3c2b0f959ef1a0efd3813b411f" + }, + { + "unit": 0, + "layers": 2, + "decoder": 2, + "out_digest": "cedffc10c0d2e777c954459c198af496e316170b3a8c35276a3f473edf438a0e" + }, + { + "unit": 1, + "layers": 2, + "decoder": 2, + "out_digest": "f0348794b5be95fd5c4e8f268957b6d188c35f76146f4479c960124a4392841d" + }, + { + "unit": 2, + "layers": 2, + "decoder": 2, + "out_digest": "446c9941549464ba1b15c36c6e738380f8918f4a63a47ebbbdd67058a1975a80" + }, + { + "unit": 0, + "layers": 2, + "decoder": 2, + "out_digest": "cedffc10c0d2e777c954459c198af496e316170b3a8c35276a3f473edf438a0e" + } + ] + }, + "expected": { + "outcome": "reject", + "step": 6, + "reason": "session_output_mismatch" + } + }, + { + "name": "session_output_leaves_moved", + "about": "a leaf moved from the base's entry to the refinement's: the sums still agree", + "procedure": "claim", + "receipt": "{\"body\":{\"classical_declared\":700,\"classical_source\":\"wai2-table\",\"counted_discarded\":1904,\"counted_fallback\":0,\"counted_primary\":5607,\"deadline_us\":40000,\"decoders\":[{\"capability\":\"wai.video.int_hyper\",\"decoder\":\"builtin:wai@0.4.0\",\"leaves\":3,\"module_status\":null,\"path\":\"primary\",\"pin\":\"7b4371854df0aa1645ac6525b373387c0617b873d5a57748932ee0f386ea164b\",\"rendition\":0,\"tier\":\"decode-equivalence\",\"variant\":null},{\"capability\":\"wai.video.av1\",\"decoder\":\"builtin:wai@0.4.0\",\"leaves\":1,\"module_status\":null,\"path\":\"fallback\",\"pin\":null,\"rendition\":null,\"tier\":null,\"variant\":null},{\"capability\":\"wai.video.int_refine\",\"decoder\":\"builtin:wai@0.4.0\",\"leaves\":5,\"module_status\":null,\"path\":\"primary\",\"pin\":null,\"rendition\":null,\"tier\":null,\"variant\":null}],\"energy\":null,\"fallback_units\":1,\"framing\":\"registered\",\"host\":{\"build\":{\"profile\":\"release\",\"target\":\"aarch64-unknown-linux-gnu\",\"toolchain\":\"rustc 1.95.0\"},\"profile\":\"native-ffi\",\"target\":\"aarch64-unknown-linux-gnu\",\"threads\":4},\"leaf_count\":9,\"media\":\"video\",\"missed\":1,\"missed_units\":[{\"late_us\":1200,\"layers\":1,\"unit\":4}],\"output_root\":\"3cb2c68a7fe160511bd3fbbbd6945b5d54fac6b499e33769b1ea6828f04bb312\",\"primary_units\":4,\"receipt_bytes\":640,\"session_nonce\":\"57c5462dfdabd1b7bdd204d34ba33649c057eb535349f29f45eb8f8c7d4a7e7f\",\"stage_sets\":[{\"claim\":\"b636e8894207d2fe59add1e1cacf3b52ea760fccb4dc3f0abce79be90e871640\",\"first_unit\":0}],\"switches\":[{\"from\":\"primary\",\"reason\":\"set-incomplete\",\"to\":\"fallback\",\"unit\":4}],\"switches_total\":1,\"transferred\":13607,\"uncounted\":2,\"units\":5},\"class\":\"reconstruct-session\",\"issued_at\":\"2026-09-27T12:00:00Z\",\"kind\":\"claim\",\"parent_receipt_hash\":null,\"seq\":0,\"sig\":\"923b92a3dc751dfbddcaa51181f80ff1c90c388cf1c33c9030e7fd33666e18d556cc25b1064d130ef2cd77323a4d1976a7f392f39bf075b41ee9978b8a736c0c\",\"signer_id\":\"did:example:sink\",\"signer_pubkey\":\"d759793bbc13a2819a827c76adb6fba8a49aee007f49f2d0992d99b825ad2c48\",\"subject\":\"64c0713cb176874607bf8670295242184b7868a9ff7c55554a5ae08de2c301c1\",\"subject_type\":\"object\"}", + "context": { + "outputs": [ + { + "unit": 0, + "layers": 1, + "decoder": 0, + "out_digest": "55f7e628ca707e2ca3159709eeb68b9000813f2916a299acd33a23e6fe012584" + }, + { + "unit": 1, + "layers": 1, + "decoder": 0, + "out_digest": "a3ee8a4b96eceb663f3d94417957d02f897fc166dc96ebe9bf447c4a36a36264" + }, + { + "unit": 2, + "layers": 1, + "decoder": 0, + "out_digest": "00576d2c4d09ef5d7aa807f9b3b1587e200dea6f6694b4da062b41aa2a5ab8af" + }, + { + "unit": 3, + "layers": 1, + "decoder": 0, + "out_digest": "26cd9b2805b604b26e08d9a461db599c4e249bfd4df41a3befb202bc6d0e0700" + }, + { + "unit": 4, + "layers": 1, + "decoder": 1, + "out_digest": "1cd1984bc553c43ee5a48fe7e182a77e60d8ef3c2b0f959ef1a0efd3813b411f" + }, + { + "unit": 0, + "layers": 2, + "decoder": 2, + "out_digest": "cedffc10c0d2e777c954459c198af496e316170b3a8c35276a3f473edf438a0e" + }, + { + "unit": 1, + "layers": 2, + "decoder": 2, + "out_digest": "f0348794b5be95fd5c4e8f268957b6d188c35f76146f4479c960124a4392841d" + }, + { + "unit": 2, + "layers": 2, + "decoder": 2, + "out_digest": "446c9941549464ba1b15c36c6e738380f8918f4a63a47ebbbdd67058a1975a80" + }, + { + "unit": 0, + "layers": 3, + "decoder": 2, + "out_digest": "a80c01cb3ded2f965b69ec4a5b3f1dcb6996e05454d9963e0b05455f9f27bc2f" + } + ] + }, + "expected": { + "outcome": "reject", + "step": 6, + "reason": "session_output_inconsistent" + } + }, + { + "name": "session_output_no_such_entry", + "about": "a presentation naming a fourth entry of three", + "procedure": "claim", + "receipt": "{\"body\":{\"classical_declared\":700,\"classical_source\":\"wai2-table\",\"counted_discarded\":1904,\"counted_fallback\":0,\"counted_primary\":5607,\"deadline_us\":40000,\"decoders\":[{\"capability\":\"wai.video.int_hyper\",\"decoder\":\"builtin:wai@0.4.0\",\"leaves\":4,\"module_status\":null,\"path\":\"primary\",\"pin\":\"7b4371854df0aa1645ac6525b373387c0617b873d5a57748932ee0f386ea164b\",\"rendition\":0,\"tier\":\"decode-equivalence\",\"variant\":null},{\"capability\":\"wai.video.av1\",\"decoder\":\"builtin:wai@0.4.0\",\"leaves\":1,\"module_status\":null,\"path\":\"fallback\",\"pin\":null,\"rendition\":null,\"tier\":null,\"variant\":null},{\"capability\":\"wai.video.int_refine\",\"decoder\":\"builtin:wai@0.4.0\",\"leaves\":4,\"module_status\":null,\"path\":\"primary\",\"pin\":null,\"rendition\":null,\"tier\":null,\"variant\":null}],\"energy\":null,\"fallback_units\":1,\"framing\":\"registered\",\"host\":{\"build\":{\"profile\":\"release\",\"target\":\"aarch64-unknown-linux-gnu\",\"toolchain\":\"rustc 1.95.0\"},\"profile\":\"native-ffi\",\"target\":\"aarch64-unknown-linux-gnu\",\"threads\":4},\"leaf_count\":9,\"media\":\"video\",\"missed\":1,\"missed_units\":[{\"late_us\":1200,\"layers\":1,\"unit\":4}],\"output_root\":\"6fd710c07ffabdf37934ac2b6296bd04132b15c9fc6d1cdaa6c4a403a86ea180\",\"primary_units\":4,\"receipt_bytes\":640,\"session_nonce\":\"57c5462dfdabd1b7bdd204d34ba33649c057eb535349f29f45eb8f8c7d4a7e7f\",\"stage_sets\":[{\"claim\":\"b636e8894207d2fe59add1e1cacf3b52ea760fccb4dc3f0abce79be90e871640\",\"first_unit\":0}],\"switches\":[{\"from\":\"primary\",\"reason\":\"set-incomplete\",\"to\":\"fallback\",\"unit\":4}],\"switches_total\":1,\"transferred\":13607,\"uncounted\":2,\"units\":5},\"class\":\"reconstruct-session\",\"issued_at\":\"2026-09-27T12:00:00Z\",\"kind\":\"claim\",\"parent_receipt_hash\":null,\"seq\":0,\"sig\":\"61c84641c2406ae41ddb4b8f720be8d886f11e4e01af199f44933cbebac855c0902add5beb6ff2658bd8500448ecfe5ccefdff2c39944278d7e722816000080f\",\"signer_id\":\"did:example:sink\",\"signer_pubkey\":\"d759793bbc13a2819a827c76adb6fba8a49aee007f49f2d0992d99b825ad2c48\",\"subject\":\"64c0713cb176874607bf8670295242184b7868a9ff7c55554a5ae08de2c301c1\",\"subject_type\":\"object\"}", + "context": { + "outputs": [ + { + "unit": 0, + "layers": 1, + "decoder": 0, + "out_digest": "55f7e628ca707e2ca3159709eeb68b9000813f2916a299acd33a23e6fe012584" + }, + { + "unit": 1, + "layers": 1, + "decoder": 0, + "out_digest": "a3ee8a4b96eceb663f3d94417957d02f897fc166dc96ebe9bf447c4a36a36264" + }, + { + "unit": 2, + "layers": 1, + "decoder": 0, + "out_digest": "00576d2c4d09ef5d7aa807f9b3b1587e200dea6f6694b4da062b41aa2a5ab8af" + }, + { + "unit": 3, + "layers": 1, + "decoder": 0, + "out_digest": "26cd9b2805b604b26e08d9a461db599c4e249bfd4df41a3befb202bc6d0e0700" + }, + { + "unit": 4, + "layers": 1, + "decoder": 3, + "out_digest": "1cd1984bc553c43ee5a48fe7e182a77e60d8ef3c2b0f959ef1a0efd3813b411f" + }, + { + "unit": 0, + "layers": 2, + "decoder": 2, + "out_digest": "cedffc10c0d2e777c954459c198af496e316170b3a8c35276a3f473edf438a0e" + }, + { + "unit": 1, + "layers": 2, + "decoder": 2, + "out_digest": "f0348794b5be95fd5c4e8f268957b6d188c35f76146f4479c960124a4392841d" + }, + { + "unit": 2, + "layers": 2, + "decoder": 2, + "out_digest": "446c9941549464ba1b15c36c6e738380f8918f4a63a47ebbbdd67058a1975a80" + }, + { + "unit": 0, + "layers": 3, + "decoder": 2, + "out_digest": "a80c01cb3ded2f965b69ec4a5b3f1dcb6996e05454d9963e0b05455f9f27bc2f" + } + ] + }, + "expected": { + "outcome": "reject", + "step": 6, + "reason": "session_output_inconsistent" + } + }, + { + "name": "session_output_not_first_use_order", + "about": "the refinement's entry listed before the fallback's, which is first named earlier taking the presentations by layers and unit", + "procedure": "claim", + "receipt": "{\"body\":{\"classical_declared\":700,\"classical_source\":\"wai2-table\",\"counted_discarded\":1904,\"counted_fallback\":0,\"counted_primary\":5607,\"deadline_us\":40000,\"decoders\":[{\"capability\":\"wai.video.int_hyper\",\"decoder\":\"builtin:wai@0.4.0\",\"leaves\":4,\"module_status\":null,\"path\":\"primary\",\"pin\":\"7b4371854df0aa1645ac6525b373387c0617b873d5a57748932ee0f386ea164b\",\"rendition\":0,\"tier\":\"decode-equivalence\",\"variant\":null},{\"capability\":\"wai.video.int_refine\",\"decoder\":\"builtin:wai@0.4.0\",\"leaves\":4,\"module_status\":null,\"path\":\"primary\",\"pin\":null,\"rendition\":null,\"tier\":null,\"variant\":null},{\"capability\":\"wai.video.av1\",\"decoder\":\"builtin:wai@0.4.0\",\"leaves\":1,\"module_status\":null,\"path\":\"fallback\",\"pin\":null,\"rendition\":null,\"tier\":null,\"variant\":null}],\"energy\":null,\"fallback_units\":1,\"framing\":\"registered\",\"host\":{\"build\":{\"profile\":\"release\",\"target\":\"aarch64-unknown-linux-gnu\",\"toolchain\":\"rustc 1.95.0\"},\"profile\":\"native-ffi\",\"target\":\"aarch64-unknown-linux-gnu\",\"threads\":4},\"leaf_count\":9,\"media\":\"video\",\"missed\":1,\"missed_units\":[{\"late_us\":1200,\"layers\":1,\"unit\":4}],\"output_root\":\"c004bf75c08a534d4d5af4b8cbe9c9fa4c708f6f54d94b052851c3f6c79df9d2\",\"primary_units\":4,\"receipt_bytes\":640,\"session_nonce\":\"57c5462dfdabd1b7bdd204d34ba33649c057eb535349f29f45eb8f8c7d4a7e7f\",\"stage_sets\":[{\"claim\":\"b636e8894207d2fe59add1e1cacf3b52ea760fccb4dc3f0abce79be90e871640\",\"first_unit\":0}],\"switches\":[{\"from\":\"primary\",\"reason\":\"set-incomplete\",\"to\":\"fallback\",\"unit\":4}],\"switches_total\":1,\"transferred\":13607,\"uncounted\":2,\"units\":5},\"class\":\"reconstruct-session\",\"issued_at\":\"2026-09-27T12:00:00Z\",\"kind\":\"claim\",\"parent_receipt_hash\":null,\"seq\":0,\"sig\":\"6305e79576f8e4b078f99db13485adac817431d14130a284e40089584bb208695743ebf9d9aa623c7207db84f7ce01c4f1b38d49a92f7292ed015aa178bec307\",\"signer_id\":\"did:example:sink\",\"signer_pubkey\":\"d759793bbc13a2819a827c76adb6fba8a49aee007f49f2d0992d99b825ad2c48\",\"subject\":\"64c0713cb176874607bf8670295242184b7868a9ff7c55554a5ae08de2c301c1\",\"subject_type\":\"object\"}", + "context": { + "outputs": [ + { + "unit": 0, + "layers": 1, + "decoder": 0, + "out_digest": "55f7e628ca707e2ca3159709eeb68b9000813f2916a299acd33a23e6fe012584" + }, + { + "unit": 1, + "layers": 1, + "decoder": 0, + "out_digest": "a3ee8a4b96eceb663f3d94417957d02f897fc166dc96ebe9bf447c4a36a36264" + }, + { + "unit": 2, + "layers": 1, + "decoder": 0, + "out_digest": "00576d2c4d09ef5d7aa807f9b3b1587e200dea6f6694b4da062b41aa2a5ab8af" + }, + { + "unit": 3, + "layers": 1, + "decoder": 0, + "out_digest": "26cd9b2805b604b26e08d9a461db599c4e249bfd4df41a3befb202bc6d0e0700" + }, + { + "unit": 4, + "layers": 1, + "decoder": 2, + "out_digest": "1cd1984bc553c43ee5a48fe7e182a77e60d8ef3c2b0f959ef1a0efd3813b411f" + }, + { + "unit": 0, + "layers": 2, + "decoder": 1, + "out_digest": "cedffc10c0d2e777c954459c198af496e316170b3a8c35276a3f473edf438a0e" + }, + { + "unit": 1, + "layers": 2, + "decoder": 1, + "out_digest": "f0348794b5be95fd5c4e8f268957b6d188c35f76146f4479c960124a4392841d" + }, + { + "unit": 2, + "layers": 2, + "decoder": 1, + "out_digest": "446c9941549464ba1b15c36c6e738380f8918f4a63a47ebbbdd67058a1975a80" + }, + { + "unit": 0, + "layers": 3, + "decoder": 1, + "out_digest": "a80c01cb3ded2f965b69ec4a5b3f1dcb6996e05454d9963e0b05455f9f27bc2f" + } + ] + }, + "expected": { + "outcome": "reject", + "step": 6, + "reason": "session_output_inconsistent" + } + }, + { + "name": "session_output_paths_disagree", + "about": "three units counted on the primary path and two on the fallback, where the presentations give four and one: the sum still agrees", + "procedure": "claim", + "receipt": "{\"body\":{\"classical_declared\":700,\"classical_source\":\"wai2-table\",\"counted_discarded\":1904,\"counted_fallback\":0,\"counted_primary\":5607,\"deadline_us\":40000,\"decoders\":[{\"capability\":\"wai.video.int_hyper\",\"decoder\":\"builtin:wai@0.4.0\",\"leaves\":4,\"module_status\":null,\"path\":\"primary\",\"pin\":\"7b4371854df0aa1645ac6525b373387c0617b873d5a57748932ee0f386ea164b\",\"rendition\":0,\"tier\":\"decode-equivalence\",\"variant\":null},{\"capability\":\"wai.video.av1\",\"decoder\":\"builtin:wai@0.4.0\",\"leaves\":1,\"module_status\":null,\"path\":\"fallback\",\"pin\":null,\"rendition\":null,\"tier\":null,\"variant\":null},{\"capability\":\"wai.video.int_refine\",\"decoder\":\"builtin:wai@0.4.0\",\"leaves\":4,\"module_status\":null,\"path\":\"primary\",\"pin\":null,\"rendition\":null,\"tier\":null,\"variant\":null}],\"energy\":null,\"fallback_units\":2,\"framing\":\"registered\",\"host\":{\"build\":{\"profile\":\"release\",\"target\":\"aarch64-unknown-linux-gnu\",\"toolchain\":\"rustc 1.95.0\"},\"profile\":\"native-ffi\",\"target\":\"aarch64-unknown-linux-gnu\",\"threads\":4},\"leaf_count\":9,\"media\":\"video\",\"missed\":1,\"missed_units\":[{\"late_us\":1200,\"layers\":1,\"unit\":4}],\"output_root\":\"3cb2c68a7fe160511bd3fbbbd6945b5d54fac6b499e33769b1ea6828f04bb312\",\"primary_units\":3,\"receipt_bytes\":640,\"session_nonce\":\"57c5462dfdabd1b7bdd204d34ba33649c057eb535349f29f45eb8f8c7d4a7e7f\",\"stage_sets\":[{\"claim\":\"b636e8894207d2fe59add1e1cacf3b52ea760fccb4dc3f0abce79be90e871640\",\"first_unit\":0}],\"switches\":[{\"from\":\"primary\",\"reason\":\"set-incomplete\",\"to\":\"fallback\",\"unit\":4}],\"switches_total\":1,\"transferred\":13607,\"uncounted\":2,\"units\":5},\"class\":\"reconstruct-session\",\"issued_at\":\"2026-09-27T12:00:00Z\",\"kind\":\"claim\",\"parent_receipt_hash\":null,\"seq\":0,\"sig\":\"156a9719edae731e550ae53bd2e6b1be6d577f4035953f4f3adcf37d6b1869c0c9c929bf2f08d6858d777c2504101adf7bece912b73397dbf5275fe03490aa06\",\"signer_id\":\"did:example:sink\",\"signer_pubkey\":\"d759793bbc13a2819a827c76adb6fba8a49aee007f49f2d0992d99b825ad2c48\",\"subject\":\"64c0713cb176874607bf8670295242184b7868a9ff7c55554a5ae08de2c301c1\",\"subject_type\":\"object\"}", + "context": { + "outputs": [ + { + "unit": 0, + "layers": 1, + "decoder": 0, + "out_digest": "55f7e628ca707e2ca3159709eeb68b9000813f2916a299acd33a23e6fe012584" + }, + { + "unit": 1, + "layers": 1, + "decoder": 0, + "out_digest": "a3ee8a4b96eceb663f3d94417957d02f897fc166dc96ebe9bf447c4a36a36264" + }, + { + "unit": 2, + "layers": 1, + "decoder": 0, + "out_digest": "00576d2c4d09ef5d7aa807f9b3b1587e200dea6f6694b4da062b41aa2a5ab8af" + }, + { + "unit": 3, + "layers": 1, + "decoder": 0, + "out_digest": "26cd9b2805b604b26e08d9a461db599c4e249bfd4df41a3befb202bc6d0e0700" + }, + { + "unit": 4, + "layers": 1, + "decoder": 1, + "out_digest": "1cd1984bc553c43ee5a48fe7e182a77e60d8ef3c2b0f959ef1a0efd3813b411f" + }, + { + "unit": 0, + "layers": 2, + "decoder": 2, + "out_digest": "cedffc10c0d2e777c954459c198af496e316170b3a8c35276a3f473edf438a0e" + }, + { + "unit": 1, + "layers": 2, + "decoder": 2, + "out_digest": "f0348794b5be95fd5c4e8f268957b6d188c35f76146f4479c960124a4392841d" + }, + { + "unit": 2, + "layers": 2, + "decoder": 2, + "out_digest": "446c9941549464ba1b15c36c6e738380f8918f4a63a47ebbbdd67058a1975a80" + }, + { + "unit": 0, + "layers": 3, + "decoder": 2, + "out_digest": "a80c01cb3ded2f965b69ec4a5b3f1dcb6996e05454d9963e0b05455f9f27bc2f" + } + ] + }, + "expected": { + "outcome": "reject", + "step": 6, + "reason": "session_output_inconsistent" + } + }, + { + "name": "session_output_units_disagree", + "about": "six units stated over five presented", + "procedure": "claim", + "receipt": "{\"body\":{\"classical_declared\":700,\"classical_source\":\"wai2-table\",\"counted_discarded\":1904,\"counted_fallback\":0,\"counted_primary\":5607,\"deadline_us\":40000,\"decoders\":[{\"capability\":\"wai.video.int_hyper\",\"decoder\":\"builtin:wai@0.4.0\",\"leaves\":4,\"module_status\":null,\"path\":\"primary\",\"pin\":\"7b4371854df0aa1645ac6525b373387c0617b873d5a57748932ee0f386ea164b\",\"rendition\":0,\"tier\":\"decode-equivalence\",\"variant\":null},{\"capability\":\"wai.video.av1\",\"decoder\":\"builtin:wai@0.4.0\",\"leaves\":1,\"module_status\":null,\"path\":\"fallback\",\"pin\":null,\"rendition\":null,\"tier\":null,\"variant\":null},{\"capability\":\"wai.video.int_refine\",\"decoder\":\"builtin:wai@0.4.0\",\"leaves\":4,\"module_status\":null,\"path\":\"primary\",\"pin\":null,\"rendition\":null,\"tier\":null,\"variant\":null}],\"energy\":null,\"fallback_units\":1,\"framing\":\"registered\",\"host\":{\"build\":{\"profile\":\"release\",\"target\":\"aarch64-unknown-linux-gnu\",\"toolchain\":\"rustc 1.95.0\"},\"profile\":\"native-ffi\",\"target\":\"aarch64-unknown-linux-gnu\",\"threads\":4},\"leaf_count\":9,\"media\":\"video\",\"missed\":1,\"missed_units\":[{\"late_us\":1200,\"layers\":1,\"unit\":4}],\"output_root\":\"3cb2c68a7fe160511bd3fbbbd6945b5d54fac6b499e33769b1ea6828f04bb312\",\"primary_units\":5,\"receipt_bytes\":640,\"session_nonce\":\"57c5462dfdabd1b7bdd204d34ba33649c057eb535349f29f45eb8f8c7d4a7e7f\",\"stage_sets\":[{\"claim\":\"b636e8894207d2fe59add1e1cacf3b52ea760fccb4dc3f0abce79be90e871640\",\"first_unit\":0}],\"switches\":[{\"from\":\"primary\",\"reason\":\"set-incomplete\",\"to\":\"fallback\",\"unit\":4}],\"switches_total\":1,\"transferred\":13607,\"uncounted\":2,\"units\":6},\"class\":\"reconstruct-session\",\"issued_at\":\"2026-09-27T12:00:00Z\",\"kind\":\"claim\",\"parent_receipt_hash\":null,\"seq\":0,\"sig\":\"fdb4237fa08d4b6004c00c4d5127c4bb2be1c2b4da6609665001b818e1e9cc2745f31dc7f1ac822deac4fbc737cbcb6e57855a933f28d87cee3ae6e4e4729b09\",\"signer_id\":\"did:example:sink\",\"signer_pubkey\":\"d759793bbc13a2819a827c76adb6fba8a49aee007f49f2d0992d99b825ad2c48\",\"subject\":\"64c0713cb176874607bf8670295242184b7868a9ff7c55554a5ae08de2c301c1\",\"subject_type\":\"object\"}", + "context": { + "outputs": [ + { + "unit": 0, + "layers": 1, + "decoder": 0, + "out_digest": "55f7e628ca707e2ca3159709eeb68b9000813f2916a299acd33a23e6fe012584" + }, + { + "unit": 1, + "layers": 1, + "decoder": 0, + "out_digest": "a3ee8a4b96eceb663f3d94417957d02f897fc166dc96ebe9bf447c4a36a36264" + }, + { + "unit": 2, + "layers": 1, + "decoder": 0, + "out_digest": "00576d2c4d09ef5d7aa807f9b3b1587e200dea6f6694b4da062b41aa2a5ab8af" + }, + { + "unit": 3, + "layers": 1, + "decoder": 0, + "out_digest": "26cd9b2805b604b26e08d9a461db599c4e249bfd4df41a3befb202bc6d0e0700" + }, + { + "unit": 4, + "layers": 1, + "decoder": 1, + "out_digest": "1cd1984bc553c43ee5a48fe7e182a77e60d8ef3c2b0f959ef1a0efd3813b411f" + }, + { + "unit": 0, + "layers": 2, + "decoder": 2, + "out_digest": "cedffc10c0d2e777c954459c198af496e316170b3a8c35276a3f473edf438a0e" + }, + { + "unit": 1, + "layers": 2, + "decoder": 2, + "out_digest": "f0348794b5be95fd5c4e8f268957b6d188c35f76146f4479c960124a4392841d" + }, + { + "unit": 2, + "layers": 2, + "decoder": 2, + "out_digest": "446c9941549464ba1b15c36c6e738380f8918f4a63a47ebbbdd67058a1975a80" + }, + { + "unit": 0, + "layers": 3, + "decoder": 2, + "out_digest": "a80c01cb3ded2f965b69ec4a5b3f1dcb6996e05454d9963e0b05455f9f27bc2f" + } + ] + }, + "expected": { + "outcome": "reject", + "step": 6, + "reason": "session_output_inconsistent" + } + }, + { + "name": "session_output_missed_not_presented", + "about": "a missed presentation of unit 4 at two layers, which was never presented", + "procedure": "claim", + "receipt": "{\"body\":{\"classical_declared\":700,\"classical_source\":\"wai2-table\",\"counted_discarded\":1904,\"counted_fallback\":0,\"counted_primary\":5607,\"deadline_us\":40000,\"decoders\":[{\"capability\":\"wai.video.int_hyper\",\"decoder\":\"builtin:wai@0.4.0\",\"leaves\":4,\"module_status\":null,\"path\":\"primary\",\"pin\":\"7b4371854df0aa1645ac6525b373387c0617b873d5a57748932ee0f386ea164b\",\"rendition\":0,\"tier\":\"decode-equivalence\",\"variant\":null},{\"capability\":\"wai.video.av1\",\"decoder\":\"builtin:wai@0.4.0\",\"leaves\":1,\"module_status\":null,\"path\":\"fallback\",\"pin\":null,\"rendition\":null,\"tier\":null,\"variant\":null},{\"capability\":\"wai.video.int_refine\",\"decoder\":\"builtin:wai@0.4.0\",\"leaves\":4,\"module_status\":null,\"path\":\"primary\",\"pin\":null,\"rendition\":null,\"tier\":null,\"variant\":null}],\"energy\":null,\"fallback_units\":1,\"framing\":\"registered\",\"host\":{\"build\":{\"profile\":\"release\",\"target\":\"aarch64-unknown-linux-gnu\",\"toolchain\":\"rustc 1.95.0\"},\"profile\":\"native-ffi\",\"target\":\"aarch64-unknown-linux-gnu\",\"threads\":4},\"leaf_count\":9,\"media\":\"video\",\"missed\":1,\"missed_units\":[{\"late_us\":1200,\"layers\":2,\"unit\":4}],\"output_root\":\"3cb2c68a7fe160511bd3fbbbd6945b5d54fac6b499e33769b1ea6828f04bb312\",\"primary_units\":4,\"receipt_bytes\":640,\"session_nonce\":\"57c5462dfdabd1b7bdd204d34ba33649c057eb535349f29f45eb8f8c7d4a7e7f\",\"stage_sets\":[{\"claim\":\"b636e8894207d2fe59add1e1cacf3b52ea760fccb4dc3f0abce79be90e871640\",\"first_unit\":0}],\"switches\":[{\"from\":\"primary\",\"reason\":\"set-incomplete\",\"to\":\"fallback\",\"unit\":4}],\"switches_total\":1,\"transferred\":13607,\"uncounted\":2,\"units\":5},\"class\":\"reconstruct-session\",\"issued_at\":\"2026-09-27T12:00:00Z\",\"kind\":\"claim\",\"parent_receipt_hash\":null,\"seq\":0,\"sig\":\"62c8939717083440bdc00aa78bfacdd2d29da27e15a65493a8e8cb2b7c6ab0632585ce4daf082bda5688a3741fbc82926a44b1b6682bb4378f691357e108b901\",\"signer_id\":\"did:example:sink\",\"signer_pubkey\":\"d759793bbc13a2819a827c76adb6fba8a49aee007f49f2d0992d99b825ad2c48\",\"subject\":\"64c0713cb176874607bf8670295242184b7868a9ff7c55554a5ae08de2c301c1\",\"subject_type\":\"object\"}", + "context": { + "outputs": [ + { + "unit": 0, + "layers": 1, + "decoder": 0, + "out_digest": "55f7e628ca707e2ca3159709eeb68b9000813f2916a299acd33a23e6fe012584" + }, + { + "unit": 1, + "layers": 1, + "decoder": 0, + "out_digest": "a3ee8a4b96eceb663f3d94417957d02f897fc166dc96ebe9bf447c4a36a36264" + }, + { + "unit": 2, + "layers": 1, + "decoder": 0, + "out_digest": "00576d2c4d09ef5d7aa807f9b3b1587e200dea6f6694b4da062b41aa2a5ab8af" + }, + { + "unit": 3, + "layers": 1, + "decoder": 0, + "out_digest": "26cd9b2805b604b26e08d9a461db599c4e249bfd4df41a3befb202bc6d0e0700" + }, + { + "unit": 4, + "layers": 1, + "decoder": 1, + "out_digest": "1cd1984bc553c43ee5a48fe7e182a77e60d8ef3c2b0f959ef1a0efd3813b411f" + }, + { + "unit": 0, + "layers": 2, + "decoder": 2, + "out_digest": "cedffc10c0d2e777c954459c198af496e316170b3a8c35276a3f473edf438a0e" + }, + { + "unit": 1, + "layers": 2, + "decoder": 2, + "out_digest": "f0348794b5be95fd5c4e8f268957b6d188c35f76146f4479c960124a4392841d" + }, + { + "unit": 2, + "layers": 2, + "decoder": 2, + "out_digest": "446c9941549464ba1b15c36c6e738380f8918f4a63a47ebbbdd67058a1975a80" + }, + { + "unit": 0, + "layers": 3, + "decoder": 2, + "out_digest": "a80c01cb3ded2f965b69ec4a5b3f1dcb6996e05454d9963e0b05455f9f27bc2f" + } + ] + }, + "expected": { + "outcome": "reject", + "step": 6, + "reason": "session_output_inconsistent" + } + }, + { + "name": "session_output_irreproducible", + "about": "the base's first presentation decoded again gives another digest", + "procedure": "claim", + "receipt": "{\"body\":{\"classical_declared\":700,\"classical_source\":\"wai2-table\",\"counted_discarded\":1904,\"counted_fallback\":0,\"counted_primary\":5607,\"deadline_us\":40000,\"decoders\":[{\"capability\":\"wai.video.int_hyper\",\"decoder\":\"builtin:wai@0.4.0\",\"leaves\":4,\"module_status\":null,\"path\":\"primary\",\"pin\":\"7b4371854df0aa1645ac6525b373387c0617b873d5a57748932ee0f386ea164b\",\"rendition\":0,\"tier\":\"decode-equivalence\",\"variant\":null},{\"capability\":\"wai.video.av1\",\"decoder\":\"builtin:wai@0.4.0\",\"leaves\":1,\"module_status\":null,\"path\":\"fallback\",\"pin\":null,\"rendition\":null,\"tier\":null,\"variant\":null},{\"capability\":\"wai.video.int_refine\",\"decoder\":\"builtin:wai@0.4.0\",\"leaves\":4,\"module_status\":null,\"path\":\"primary\",\"pin\":null,\"rendition\":null,\"tier\":null,\"variant\":null}],\"energy\":null,\"fallback_units\":1,\"framing\":\"registered\",\"host\":{\"build\":{\"profile\":\"release\",\"target\":\"aarch64-unknown-linux-gnu\",\"toolchain\":\"rustc 1.95.0\"},\"profile\":\"native-ffi\",\"target\":\"aarch64-unknown-linux-gnu\",\"threads\":4},\"leaf_count\":9,\"media\":\"video\",\"missed\":1,\"missed_units\":[{\"late_us\":1200,\"layers\":1,\"unit\":4}],\"output_root\":\"3cb2c68a7fe160511bd3fbbbd6945b5d54fac6b499e33769b1ea6828f04bb312\",\"primary_units\":4,\"receipt_bytes\":640,\"session_nonce\":\"57c5462dfdabd1b7bdd204d34ba33649c057eb535349f29f45eb8f8c7d4a7e7f\",\"stage_sets\":[{\"claim\":\"b636e8894207d2fe59add1e1cacf3b52ea760fccb4dc3f0abce79be90e871640\",\"first_unit\":0}],\"switches\":[{\"from\":\"primary\",\"reason\":\"set-incomplete\",\"to\":\"fallback\",\"unit\":4}],\"switches_total\":1,\"transferred\":13607,\"uncounted\":2,\"units\":5},\"class\":\"reconstruct-session\",\"issued_at\":\"2026-09-27T12:00:00Z\",\"kind\":\"claim\",\"parent_receipt_hash\":null,\"seq\":0,\"sig\":\"2871039f189db43685c214c860ac86567712af1e35d3254c371e7faaf8582734b5216c7ba4015383ad9013aac4c34ba1aebf410a56615d5bf2f5d73622c1410e\",\"signer_id\":\"did:example:sink\",\"signer_pubkey\":\"d759793bbc13a2819a827c76adb6fba8a49aee007f49f2d0992d99b825ad2c48\",\"subject\":\"64c0713cb176874607bf8670295242184b7868a9ff7c55554a5ae08de2c301c1\",\"subject_type\":\"object\"}", + "context": { + "outputs": [ + { + "unit": 0, + "layers": 1, + "decoder": 0, + "out_digest": "55f7e628ca707e2ca3159709eeb68b9000813f2916a299acd33a23e6fe012584" + }, + { + "unit": 1, + "layers": 1, + "decoder": 0, + "out_digest": "a3ee8a4b96eceb663f3d94417957d02f897fc166dc96ebe9bf447c4a36a36264" + }, + { + "unit": 2, + "layers": 1, + "decoder": 0, + "out_digest": "00576d2c4d09ef5d7aa807f9b3b1587e200dea6f6694b4da062b41aa2a5ab8af" + }, + { + "unit": 3, + "layers": 1, + "decoder": 0, + "out_digest": "26cd9b2805b604b26e08d9a461db599c4e249bfd4df41a3befb202bc6d0e0700" + }, + { + "unit": 4, + "layers": 1, + "decoder": 1, + "out_digest": "1cd1984bc553c43ee5a48fe7e182a77e60d8ef3c2b0f959ef1a0efd3813b411f" + }, + { + "unit": 0, + "layers": 2, + "decoder": 2, + "out_digest": "cedffc10c0d2e777c954459c198af496e316170b3a8c35276a3f473edf438a0e" + }, + { + "unit": 1, + "layers": 2, + "decoder": 2, + "out_digest": "f0348794b5be95fd5c4e8f268957b6d188c35f76146f4479c960124a4392841d" + }, + { + "unit": 2, + "layers": 2, + "decoder": 2, + "out_digest": "446c9941549464ba1b15c36c6e738380f8918f4a63a47ebbbdd67058a1975a80" + }, + { + "unit": 0, + "layers": 3, + "decoder": 2, + "out_digest": "a80c01cb3ded2f965b69ec4a5b3f1dcb6996e05454d9963e0b05455f9f27bc2f" + } + ], + "redecoded": [ + { + "index": 0, + "out_digest": "1acdc303256c57c92dc63bb841d386b7e918e9fd4939eae6f3ac5a2b829f340f" + } + ] + }, + "expected": { + "outcome": "reject", + "step": 6, + "reason": "session_output_irreproducible" + } + }, + { + "name": "session_output_membership_only_accept", + "about": "the fallback's presentation, through a decoder checked for membership only, decoded again with another digest: not checked", + "procedure": "claim", + "receipt": "{\"body\":{\"classical_declared\":700,\"classical_source\":\"wai2-table\",\"counted_discarded\":1904,\"counted_fallback\":0,\"counted_primary\":5607,\"deadline_us\":40000,\"decoders\":[{\"capability\":\"wai.video.int_hyper\",\"decoder\":\"builtin:wai@0.4.0\",\"leaves\":4,\"module_status\":null,\"path\":\"primary\",\"pin\":\"7b4371854df0aa1645ac6525b373387c0617b873d5a57748932ee0f386ea164b\",\"rendition\":0,\"tier\":\"decode-equivalence\",\"variant\":null},{\"capability\":\"wai.video.av1\",\"decoder\":\"builtin:wai@0.4.0\",\"leaves\":1,\"module_status\":null,\"path\":\"fallback\",\"pin\":null,\"rendition\":null,\"tier\":null,\"variant\":null},{\"capability\":\"wai.video.int_refine\",\"decoder\":\"builtin:wai@0.4.0\",\"leaves\":4,\"module_status\":null,\"path\":\"primary\",\"pin\":null,\"rendition\":null,\"tier\":null,\"variant\":null}],\"energy\":null,\"fallback_units\":1,\"framing\":\"registered\",\"host\":{\"build\":{\"profile\":\"release\",\"target\":\"aarch64-unknown-linux-gnu\",\"toolchain\":\"rustc 1.95.0\"},\"profile\":\"native-ffi\",\"target\":\"aarch64-unknown-linux-gnu\",\"threads\":4},\"leaf_count\":9,\"media\":\"video\",\"missed\":1,\"missed_units\":[{\"late_us\":1200,\"layers\":1,\"unit\":4}],\"output_root\":\"3cb2c68a7fe160511bd3fbbbd6945b5d54fac6b499e33769b1ea6828f04bb312\",\"primary_units\":4,\"receipt_bytes\":640,\"session_nonce\":\"57c5462dfdabd1b7bdd204d34ba33649c057eb535349f29f45eb8f8c7d4a7e7f\",\"stage_sets\":[{\"claim\":\"b636e8894207d2fe59add1e1cacf3b52ea760fccb4dc3f0abce79be90e871640\",\"first_unit\":0}],\"switches\":[{\"from\":\"primary\",\"reason\":\"set-incomplete\",\"to\":\"fallback\",\"unit\":4}],\"switches_total\":1,\"transferred\":13607,\"uncounted\":2,\"units\":5},\"class\":\"reconstruct-session\",\"issued_at\":\"2026-09-27T12:00:00Z\",\"kind\":\"claim\",\"parent_receipt_hash\":null,\"seq\":0,\"sig\":\"2871039f189db43685c214c860ac86567712af1e35d3254c371e7faaf8582734b5216c7ba4015383ad9013aac4c34ba1aebf410a56615d5bf2f5d73622c1410e\",\"signer_id\":\"did:example:sink\",\"signer_pubkey\":\"d759793bbc13a2819a827c76adb6fba8a49aee007f49f2d0992d99b825ad2c48\",\"subject\":\"64c0713cb176874607bf8670295242184b7868a9ff7c55554a5ae08de2c301c1\",\"subject_type\":\"object\"}", + "context": { + "outputs": [ + { + "unit": 0, + "layers": 1, + "decoder": 0, + "out_digest": "55f7e628ca707e2ca3159709eeb68b9000813f2916a299acd33a23e6fe012584" + }, + { + "unit": 1, + "layers": 1, + "decoder": 0, + "out_digest": "a3ee8a4b96eceb663f3d94417957d02f897fc166dc96ebe9bf447c4a36a36264" + }, + { + "unit": 2, + "layers": 1, + "decoder": 0, + "out_digest": "00576d2c4d09ef5d7aa807f9b3b1587e200dea6f6694b4da062b41aa2a5ab8af" + }, + { + "unit": 3, + "layers": 1, + "decoder": 0, + "out_digest": "26cd9b2805b604b26e08d9a461db599c4e249bfd4df41a3befb202bc6d0e0700" + }, + { + "unit": 4, + "layers": 1, + "decoder": 1, + "out_digest": "1cd1984bc553c43ee5a48fe7e182a77e60d8ef3c2b0f959ef1a0efd3813b411f" + }, + { + "unit": 0, + "layers": 2, + "decoder": 2, + "out_digest": "cedffc10c0d2e777c954459c198af496e316170b3a8c35276a3f473edf438a0e" + }, + { + "unit": 1, + "layers": 2, + "decoder": 2, + "out_digest": "f0348794b5be95fd5c4e8f268957b6d188c35f76146f4479c960124a4392841d" + }, + { + "unit": 2, + "layers": 2, + "decoder": 2, + "out_digest": "446c9941549464ba1b15c36c6e738380f8918f4a63a47ebbbdd67058a1975a80" + }, + { + "unit": 0, + "layers": 3, + "decoder": 2, + "out_digest": "a80c01cb3ded2f965b69ec4a5b3f1dcb6996e05454d9963e0b05455f9f27bc2f" + } + ], + "redecoded": [ + { + "index": 4, + "out_digest": "d72f3091ac8d0a2c06e2884c1afc5b87d55fa2fa912da194245f303c4ee8b6b7" + } + ] + }, + "expected": { + "outcome": "accept", + "link_hash": "cc336d348fd5b500a1a37f5e6a2f6c72ab4cfe83b76cc508ed4f0aae6eeeb741" + } + }, + { + "name": "session_counted_mismatch", + "about": "an object received counted one byte short of the session's sum", + "procedure": "claim", + "receipt": "{\"body\":{\"classical_declared\":700,\"classical_source\":\"wai2-table\",\"counted_discarded\":1904,\"counted_fallback\":0,\"counted_primary\":5607,\"deadline_us\":40000,\"decoders\":[{\"capability\":\"wai.video.int_hyper\",\"decoder\":\"builtin:wai@0.4.0\",\"leaves\":4,\"module_status\":null,\"path\":\"primary\",\"pin\":\"7b4371854df0aa1645ac6525b373387c0617b873d5a57748932ee0f386ea164b\",\"rendition\":0,\"tier\":\"decode-equivalence\",\"variant\":null},{\"capability\":\"wai.video.av1\",\"decoder\":\"builtin:wai@0.4.0\",\"leaves\":1,\"module_status\":null,\"path\":\"fallback\",\"pin\":null,\"rendition\":null,\"tier\":null,\"variant\":null},{\"capability\":\"wai.video.int_refine\",\"decoder\":\"builtin:wai@0.4.0\",\"leaves\":4,\"module_status\":null,\"path\":\"primary\",\"pin\":null,\"rendition\":null,\"tier\":null,\"variant\":null}],\"energy\":null,\"fallback_units\":1,\"framing\":\"registered\",\"host\":{\"build\":{\"profile\":\"release\",\"target\":\"aarch64-unknown-linux-gnu\",\"toolchain\":\"rustc 1.95.0\"},\"profile\":\"native-ffi\",\"target\":\"aarch64-unknown-linux-gnu\",\"threads\":4},\"leaf_count\":9,\"media\":\"video\",\"missed\":1,\"missed_units\":[{\"late_us\":1200,\"layers\":1,\"unit\":4}],\"output_root\":\"3cb2c68a7fe160511bd3fbbbd6945b5d54fac6b499e33769b1ea6828f04bb312\",\"primary_units\":4,\"receipt_bytes\":640,\"session_nonce\":\"57c5462dfdabd1b7bdd204d34ba33649c057eb535349f29f45eb8f8c7d4a7e7f\",\"stage_sets\":[{\"claim\":\"b636e8894207d2fe59add1e1cacf3b52ea760fccb4dc3f0abce79be90e871640\",\"first_unit\":0}],\"switches\":[{\"from\":\"primary\",\"reason\":\"set-incomplete\",\"to\":\"fallback\",\"unit\":4}],\"switches_total\":1,\"transferred\":13607,\"uncounted\":2,\"units\":5},\"class\":\"reconstruct-session\",\"issued_at\":\"2026-09-27T12:00:00Z\",\"kind\":\"claim\",\"parent_receipt_hash\":null,\"seq\":0,\"sig\":\"2871039f189db43685c214c860ac86567712af1e35d3254c371e7faaf8582734b5216c7ba4015383ad9013aac4c34ba1aebf410a56615d5bf2f5d73622c1410e\",\"signer_id\":\"did:example:sink\",\"signer_pubkey\":\"d759793bbc13a2819a827c76adb6fba8a49aee007f49f2d0992d99b825ad2c48\",\"subject\":\"64c0713cb176874607bf8670295242184b7868a9ff7c55554a5ae08de2c301c1\",\"subject_type\":\"object\"}", + "context": { + "objects": [ + { + "content_hash": "64c0713cb176874607bf8670295242184b7868a9ff7c55554a5ae08de2c301c1", + "path": "primary", + "counted": null, + "transferred": 5000, + "presented": true + }, + { + "content_hash": "47a2c23727d2eb9d2beef0931c3e9b2675408d372660420cce427dc27fd21fe1", + "path": "primary", + "counted": 899, + "transferred": 900, + "presented": true + }, + { + "content_hash": "6b74be11e64461c7d972fc5cb6ba15e98427e9d6e60622b0a753222138de28cf", + "path": "primary", + "counted": 901, + "transferred": 901, + "presented": true + }, + { + "content_hash": "5e7a38ca5c04442cbe00b040d58e4494f5aa36fb81e8bbe0d304fd2d1ce722b2", + "path": "primary", + "counted": 902, + "transferred": 902, + "presented": true + }, + { + "content_hash": "792a12990c5207ca83a86b7420815f1f2d34918553a0130a4f9570a11354f2ca", + "path": "primary", + "counted": 903, + "transferred": 903, + "presented": false + }, + { + "content_hash": "be5055af8e32359265852c512667b10ab6a07455e5ab06603e278763f6633a85", + "path": "primary", + "counted": 1000, + "transferred": 1000, + "presented": true + }, + { + "content_hash": "1c6eae0ed41ed7fc1b2f00b46ea1de98f21a6d6cbf62bf6b22cf76a664a49376", + "path": "primary", + "counted": 1001, + "transferred": 1001, + "presented": false + }, + { + "content_hash": "13b04249eca2b1a9061dba8ca2846169d3f5fa3548d9e138a0cf2cb553798cf4", + "path": "fallback", + "counted": null, + "transferred": 3000, + "presented": true + } + ] + }, + "expected": { + "outcome": "reject", + "step": 6, + "reason": "session_counted_mismatch" + } + }, + { + "name": "session_uncounted_mismatch", + "about": "the fallback envelope given as countable: one object fewer is uncounted", + "procedure": "claim", + "receipt": "{\"body\":{\"classical_declared\":700,\"classical_source\":\"wai2-table\",\"counted_discarded\":1904,\"counted_fallback\":0,\"counted_primary\":5607,\"deadline_us\":40000,\"decoders\":[{\"capability\":\"wai.video.int_hyper\",\"decoder\":\"builtin:wai@0.4.0\",\"leaves\":4,\"module_status\":null,\"path\":\"primary\",\"pin\":\"7b4371854df0aa1645ac6525b373387c0617b873d5a57748932ee0f386ea164b\",\"rendition\":0,\"tier\":\"decode-equivalence\",\"variant\":null},{\"capability\":\"wai.video.av1\",\"decoder\":\"builtin:wai@0.4.0\",\"leaves\":1,\"module_status\":null,\"path\":\"fallback\",\"pin\":null,\"rendition\":null,\"tier\":null,\"variant\":null},{\"capability\":\"wai.video.int_refine\",\"decoder\":\"builtin:wai@0.4.0\",\"leaves\":4,\"module_status\":null,\"path\":\"primary\",\"pin\":null,\"rendition\":null,\"tier\":null,\"variant\":null}],\"energy\":null,\"fallback_units\":1,\"framing\":\"registered\",\"host\":{\"build\":{\"profile\":\"release\",\"target\":\"aarch64-unknown-linux-gnu\",\"toolchain\":\"rustc 1.95.0\"},\"profile\":\"native-ffi\",\"target\":\"aarch64-unknown-linux-gnu\",\"threads\":4},\"leaf_count\":9,\"media\":\"video\",\"missed\":1,\"missed_units\":[{\"late_us\":1200,\"layers\":1,\"unit\":4}],\"output_root\":\"3cb2c68a7fe160511bd3fbbbd6945b5d54fac6b499e33769b1ea6828f04bb312\",\"primary_units\":4,\"receipt_bytes\":640,\"session_nonce\":\"57c5462dfdabd1b7bdd204d34ba33649c057eb535349f29f45eb8f8c7d4a7e7f\",\"stage_sets\":[{\"claim\":\"b636e8894207d2fe59add1e1cacf3b52ea760fccb4dc3f0abce79be90e871640\",\"first_unit\":0}],\"switches\":[{\"from\":\"primary\",\"reason\":\"set-incomplete\",\"to\":\"fallback\",\"unit\":4}],\"switches_total\":1,\"transferred\":13607,\"uncounted\":2,\"units\":5},\"class\":\"reconstruct-session\",\"issued_at\":\"2026-09-27T12:00:00Z\",\"kind\":\"claim\",\"parent_receipt_hash\":null,\"seq\":0,\"sig\":\"2871039f189db43685c214c860ac86567712af1e35d3254c371e7faaf8582734b5216c7ba4015383ad9013aac4c34ba1aebf410a56615d5bf2f5d73622c1410e\",\"signer_id\":\"did:example:sink\",\"signer_pubkey\":\"d759793bbc13a2819a827c76adb6fba8a49aee007f49f2d0992d99b825ad2c48\",\"subject\":\"64c0713cb176874607bf8670295242184b7868a9ff7c55554a5ae08de2c301c1\",\"subject_type\":\"object\"}", + "context": { + "objects": [ + { + "content_hash": "64c0713cb176874607bf8670295242184b7868a9ff7c55554a5ae08de2c301c1", + "path": "primary", + "counted": null, + "transferred": 5000, + "presented": true + }, + { + "content_hash": "47a2c23727d2eb9d2beef0931c3e9b2675408d372660420cce427dc27fd21fe1", + "path": "primary", + "counted": 900, + "transferred": 900, + "presented": true + }, + { + "content_hash": "6b74be11e64461c7d972fc5cb6ba15e98427e9d6e60622b0a753222138de28cf", + "path": "primary", + "counted": 901, + "transferred": 901, + "presented": true + }, + { + "content_hash": "5e7a38ca5c04442cbe00b040d58e4494f5aa36fb81e8bbe0d304fd2d1ce722b2", + "path": "primary", + "counted": 902, + "transferred": 902, + "presented": true + }, + { + "content_hash": "792a12990c5207ca83a86b7420815f1f2d34918553a0130a4f9570a11354f2ca", + "path": "primary", + "counted": 903, + "transferred": 903, + "presented": false + }, + { + "content_hash": "be5055af8e32359265852c512667b10ab6a07455e5ab06603e278763f6633a85", + "path": "primary", + "counted": 1000, + "transferred": 1000, + "presented": true + }, + { + "content_hash": "1c6eae0ed41ed7fc1b2f00b46ea1de98f21a6d6cbf62bf6b22cf76a664a49376", + "path": "primary", + "counted": 1001, + "transferred": 1001, + "presented": false + }, + { + "content_hash": "13b04249eca2b1a9061dba8ca2846169d3f5fa3548d9e138a0cf2cb553798cf4", + "path": "fallback", + "counted": 3000, + "transferred": 3000, + "presented": true + } + ] + }, + "expected": { + "outcome": "reject", + "step": 6, + "reason": "session_counted_mismatch" + } + }, + { + "name": "session_discarded_mismatch", + "about": "a late layer object given as presented: fewer bytes discarded", + "procedure": "claim", + "receipt": "{\"body\":{\"classical_declared\":700,\"classical_source\":\"wai2-table\",\"counted_discarded\":1904,\"counted_fallback\":0,\"counted_primary\":5607,\"deadline_us\":40000,\"decoders\":[{\"capability\":\"wai.video.int_hyper\",\"decoder\":\"builtin:wai@0.4.0\",\"leaves\":4,\"module_status\":null,\"path\":\"primary\",\"pin\":\"7b4371854df0aa1645ac6525b373387c0617b873d5a57748932ee0f386ea164b\",\"rendition\":0,\"tier\":\"decode-equivalence\",\"variant\":null},{\"capability\":\"wai.video.av1\",\"decoder\":\"builtin:wai@0.4.0\",\"leaves\":1,\"module_status\":null,\"path\":\"fallback\",\"pin\":null,\"rendition\":null,\"tier\":null,\"variant\":null},{\"capability\":\"wai.video.int_refine\",\"decoder\":\"builtin:wai@0.4.0\",\"leaves\":4,\"module_status\":null,\"path\":\"primary\",\"pin\":null,\"rendition\":null,\"tier\":null,\"variant\":null}],\"energy\":null,\"fallback_units\":1,\"framing\":\"registered\",\"host\":{\"build\":{\"profile\":\"release\",\"target\":\"aarch64-unknown-linux-gnu\",\"toolchain\":\"rustc 1.95.0\"},\"profile\":\"native-ffi\",\"target\":\"aarch64-unknown-linux-gnu\",\"threads\":4},\"leaf_count\":9,\"media\":\"video\",\"missed\":1,\"missed_units\":[{\"late_us\":1200,\"layers\":1,\"unit\":4}],\"output_root\":\"3cb2c68a7fe160511bd3fbbbd6945b5d54fac6b499e33769b1ea6828f04bb312\",\"primary_units\":4,\"receipt_bytes\":640,\"session_nonce\":\"57c5462dfdabd1b7bdd204d34ba33649c057eb535349f29f45eb8f8c7d4a7e7f\",\"stage_sets\":[{\"claim\":\"b636e8894207d2fe59add1e1cacf3b52ea760fccb4dc3f0abce79be90e871640\",\"first_unit\":0}],\"switches\":[{\"from\":\"primary\",\"reason\":\"set-incomplete\",\"to\":\"fallback\",\"unit\":4}],\"switches_total\":1,\"transferred\":13607,\"uncounted\":2,\"units\":5},\"class\":\"reconstruct-session\",\"issued_at\":\"2026-09-27T12:00:00Z\",\"kind\":\"claim\",\"parent_receipt_hash\":null,\"seq\":0,\"sig\":\"2871039f189db43685c214c860ac86567712af1e35d3254c371e7faaf8582734b5216c7ba4015383ad9013aac4c34ba1aebf410a56615d5bf2f5d73622c1410e\",\"signer_id\":\"did:example:sink\",\"signer_pubkey\":\"d759793bbc13a2819a827c76adb6fba8a49aee007f49f2d0992d99b825ad2c48\",\"subject\":\"64c0713cb176874607bf8670295242184b7868a9ff7c55554a5ae08de2c301c1\",\"subject_type\":\"object\"}", + "context": { + "objects": [ + { + "content_hash": "64c0713cb176874607bf8670295242184b7868a9ff7c55554a5ae08de2c301c1", + "path": "primary", + "counted": null, + "transferred": 5000, + "presented": true + }, + { + "content_hash": "47a2c23727d2eb9d2beef0931c3e9b2675408d372660420cce427dc27fd21fe1", + "path": "primary", + "counted": 900, + "transferred": 900, + "presented": true + }, + { + "content_hash": "6b74be11e64461c7d972fc5cb6ba15e98427e9d6e60622b0a753222138de28cf", + "path": "primary", + "counted": 901, + "transferred": 901, + "presented": true + }, + { + "content_hash": "5e7a38ca5c04442cbe00b040d58e4494f5aa36fb81e8bbe0d304fd2d1ce722b2", + "path": "primary", + "counted": 902, + "transferred": 902, + "presented": true + }, + { + "content_hash": "792a12990c5207ca83a86b7420815f1f2d34918553a0130a4f9570a11354f2ca", + "path": "primary", + "counted": 903, + "transferred": 903, + "presented": true + }, + { + "content_hash": "be5055af8e32359265852c512667b10ab6a07455e5ab06603e278763f6633a85", + "path": "primary", + "counted": 1000, + "transferred": 1000, + "presented": true + }, + { + "content_hash": "1c6eae0ed41ed7fc1b2f00b46ea1de98f21a6d6cbf62bf6b22cf76a664a49376", + "path": "primary", + "counted": 1001, + "transferred": 1001, + "presented": false + }, + { + "content_hash": "13b04249eca2b1a9061dba8ca2846169d3f5fa3548d9e138a0cf2cb553798cf4", + "path": "fallback", + "counted": null, + "transferred": 3000, + "presented": true + } + ] + }, + "expected": { + "outcome": "reject", + "step": 6, + "reason": "session_counted_mismatch" + } + }, + { + "name": "session_classical_decoded", + "about": "the rendition named is the one the session decoded", + "procedure": "claim", + "receipt": "{\"body\":{\"classical_declared\":700,\"classical_source\":\"wai2-table\",\"counted_discarded\":1904,\"counted_fallback\":0,\"counted_primary\":5607,\"deadline_us\":40000,\"decoders\":[{\"capability\":\"wai.video.int_hyper\",\"decoder\":\"builtin:wai@0.4.0\",\"leaves\":4,\"module_status\":null,\"path\":\"primary\",\"pin\":\"7b4371854df0aa1645ac6525b373387c0617b873d5a57748932ee0f386ea164b\",\"rendition\":0,\"tier\":\"decode-equivalence\",\"variant\":null},{\"capability\":\"wai.video.av1\",\"decoder\":\"builtin:wai@0.4.0\",\"leaves\":1,\"module_status\":null,\"path\":\"fallback\",\"pin\":null,\"rendition\":null,\"tier\":null,\"variant\":null},{\"capability\":\"wai.video.int_refine\",\"decoder\":\"builtin:wai@0.4.0\",\"leaves\":4,\"module_status\":null,\"path\":\"primary\",\"pin\":null,\"rendition\":null,\"tier\":null,\"variant\":null}],\"energy\":null,\"fallback_units\":1,\"framing\":\"registered\",\"host\":{\"build\":{\"profile\":\"release\",\"target\":\"aarch64-unknown-linux-gnu\",\"toolchain\":\"rustc 1.95.0\"},\"profile\":\"native-ffi\",\"target\":\"aarch64-unknown-linux-gnu\",\"threads\":4},\"leaf_count\":9,\"media\":\"video\",\"missed\":1,\"missed_units\":[{\"late_us\":1200,\"layers\":1,\"unit\":4}],\"output_root\":\"3cb2c68a7fe160511bd3fbbbd6945b5d54fac6b499e33769b1ea6828f04bb312\",\"primary_units\":4,\"receipt_bytes\":640,\"session_nonce\":\"57c5462dfdabd1b7bdd204d34ba33649c057eb535349f29f45eb8f8c7d4a7e7f\",\"stage_sets\":[{\"claim\":\"b636e8894207d2fe59add1e1cacf3b52ea760fccb4dc3f0abce79be90e871640\",\"first_unit\":0}],\"switches\":[{\"from\":\"primary\",\"reason\":\"set-incomplete\",\"to\":\"fallback\",\"unit\":4}],\"switches_total\":1,\"transferred\":13607,\"uncounted\":2,\"units\":5},\"class\":\"reconstruct-session\",\"issued_at\":\"2026-09-27T12:00:00Z\",\"kind\":\"claim\",\"parent_receipt_hash\":null,\"seq\":0,\"sig\":\"2871039f189db43685c214c860ac86567712af1e35d3254c371e7faaf8582734b5216c7ba4015383ad9013aac4c34ba1aebf410a56615d5bf2f5d73622c1410e\",\"signer_id\":\"did:example:sink\",\"signer_pubkey\":\"d759793bbc13a2819a827c76adb6fba8a49aee007f49f2d0992d99b825ad2c48\",\"subject\":\"64c0713cb176874607bf8670295242184b7868a9ff7c55554a5ae08de2c301c1\",\"subject_type\":\"object\"}", + "context": { + "envelopes": [ + { + "envelope": "57414932b30000007b22776169223a22312e31222c226d65646961223a22766964656f222c22696e74656e74223a227265706c6963617465222c2272656e646974696f6e73223a5b7b226361706162696c697479223a227761692e766964656f2e696e745f6879706572222c226b696e64223a22696e745f6879706572227d2c7b226361706162696c697479223a227761692e766964656f2e617663222c226b696e64223a22617663227d5d2c22746172676574223a6e756c6c7d020000000000c8000000c8000000bc020000111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111122222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222", + "rendition": 0 + } + ] + }, + "expected": { + "outcome": "reject", + "step": 6, + "reason": "session_classical_mismatch" + } + }, + { + "name": "session_classical_length", + "about": "a classical length one byte more than the rendition table gives", + "procedure": "claim", + "receipt": "{\"body\":{\"classical_declared\":701,\"classical_source\":\"wai2-table\",\"counted_discarded\":1904,\"counted_fallback\":0,\"counted_primary\":5607,\"deadline_us\":40000,\"decoders\":[{\"capability\":\"wai.video.int_hyper\",\"decoder\":\"builtin:wai@0.4.0\",\"leaves\":4,\"module_status\":null,\"path\":\"primary\",\"pin\":\"7b4371854df0aa1645ac6525b373387c0617b873d5a57748932ee0f386ea164b\",\"rendition\":0,\"tier\":\"decode-equivalence\",\"variant\":null},{\"capability\":\"wai.video.av1\",\"decoder\":\"builtin:wai@0.4.0\",\"leaves\":1,\"module_status\":null,\"path\":\"fallback\",\"pin\":null,\"rendition\":null,\"tier\":null,\"variant\":null},{\"capability\":\"wai.video.int_refine\",\"decoder\":\"builtin:wai@0.4.0\",\"leaves\":4,\"module_status\":null,\"path\":\"primary\",\"pin\":null,\"rendition\":null,\"tier\":null,\"variant\":null}],\"energy\":null,\"fallback_units\":1,\"framing\":\"registered\",\"host\":{\"build\":{\"profile\":\"release\",\"target\":\"aarch64-unknown-linux-gnu\",\"toolchain\":\"rustc 1.95.0\"},\"profile\":\"native-ffi\",\"target\":\"aarch64-unknown-linux-gnu\",\"threads\":4},\"leaf_count\":9,\"media\":\"video\",\"missed\":1,\"missed_units\":[{\"late_us\":1200,\"layers\":1,\"unit\":4}],\"output_root\":\"3cb2c68a7fe160511bd3fbbbd6945b5d54fac6b499e33769b1ea6828f04bb312\",\"primary_units\":4,\"receipt_bytes\":640,\"session_nonce\":\"57c5462dfdabd1b7bdd204d34ba33649c057eb535349f29f45eb8f8c7d4a7e7f\",\"stage_sets\":[{\"claim\":\"b636e8894207d2fe59add1e1cacf3b52ea760fccb4dc3f0abce79be90e871640\",\"first_unit\":0}],\"switches\":[{\"from\":\"primary\",\"reason\":\"set-incomplete\",\"to\":\"fallback\",\"unit\":4}],\"switches_total\":1,\"transferred\":13607,\"uncounted\":2,\"units\":5},\"class\":\"reconstruct-session\",\"issued_at\":\"2026-09-27T12:00:00Z\",\"kind\":\"claim\",\"parent_receipt_hash\":null,\"seq\":0,\"sig\":\"038072fb14c13b474efa3999b4d4775bb485e3ae9e049f6e323860e5c1717bd249f247e45dbc578c00ff0a9ae09ea1df1442cfb1752f88b4d01b709eb0a4b601\",\"signer_id\":\"did:example:sink\",\"signer_pubkey\":\"d759793bbc13a2819a827c76adb6fba8a49aee007f49f2d0992d99b825ad2c48\",\"subject\":\"64c0713cb176874607bf8670295242184b7868a9ff7c55554a5ae08de2c301c1\",\"subject_type\":\"object\"}", + "context": { + "envelopes": [ + { + "envelope": "57414932b30000007b22776169223a22312e31222c226d65646961223a22766964656f222c22696e74656e74223a227265706c6963617465222c2272656e646974696f6e73223a5b7b226361706162696c697479223a227761692e766964656f2e696e745f6879706572222c226b696e64223a22696e745f6879706572227d2c7b226361706162696c697479223a227761692e766964656f2e617663222c226b696e64223a22617663227d5d2c22746172676574223a6e756c6c7d020000000000c8000000c8000000bc020000111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111122222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222", + "rendition": 1 + } + ] + }, + "expected": { + "outcome": "reject", + "step": 6, + "reason": "session_classical_mismatch" + } + }, + { + "name": "session_classical_no_envelope", + "about": "a classical length with no envelope that carries one", + "procedure": "claim", + "receipt": "{\"body\":{\"classical_declared\":700,\"classical_source\":\"wai2-table\",\"counted_discarded\":1904,\"counted_fallback\":0,\"counted_primary\":5607,\"deadline_us\":40000,\"decoders\":[{\"capability\":\"wai.video.int_hyper\",\"decoder\":\"builtin:wai@0.4.0\",\"leaves\":4,\"module_status\":null,\"path\":\"primary\",\"pin\":\"7b4371854df0aa1645ac6525b373387c0617b873d5a57748932ee0f386ea164b\",\"rendition\":0,\"tier\":\"decode-equivalence\",\"variant\":null},{\"capability\":\"wai.video.av1\",\"decoder\":\"builtin:wai@0.4.0\",\"leaves\":1,\"module_status\":null,\"path\":\"fallback\",\"pin\":null,\"rendition\":null,\"tier\":null,\"variant\":null},{\"capability\":\"wai.video.int_refine\",\"decoder\":\"builtin:wai@0.4.0\",\"leaves\":4,\"module_status\":null,\"path\":\"primary\",\"pin\":null,\"rendition\":null,\"tier\":null,\"variant\":null}],\"energy\":null,\"fallback_units\":1,\"framing\":\"registered\",\"host\":{\"build\":{\"profile\":\"release\",\"target\":\"aarch64-unknown-linux-gnu\",\"toolchain\":\"rustc 1.95.0\"},\"profile\":\"native-ffi\",\"target\":\"aarch64-unknown-linux-gnu\",\"threads\":4},\"leaf_count\":9,\"media\":\"video\",\"missed\":1,\"missed_units\":[{\"late_us\":1200,\"layers\":1,\"unit\":4}],\"output_root\":\"3cb2c68a7fe160511bd3fbbbd6945b5d54fac6b499e33769b1ea6828f04bb312\",\"primary_units\":4,\"receipt_bytes\":640,\"session_nonce\":\"57c5462dfdabd1b7bdd204d34ba33649c057eb535349f29f45eb8f8c7d4a7e7f\",\"stage_sets\":[{\"claim\":\"b636e8894207d2fe59add1e1cacf3b52ea760fccb4dc3f0abce79be90e871640\",\"first_unit\":0}],\"switches\":[{\"from\":\"primary\",\"reason\":\"set-incomplete\",\"to\":\"fallback\",\"unit\":4}],\"switches_total\":1,\"transferred\":13607,\"uncounted\":2,\"units\":5},\"class\":\"reconstruct-session\",\"issued_at\":\"2026-09-27T12:00:00Z\",\"kind\":\"claim\",\"parent_receipt_hash\":null,\"seq\":0,\"sig\":\"2871039f189db43685c214c860ac86567712af1e35d3254c371e7faaf8582734b5216c7ba4015383ad9013aac4c34ba1aebf410a56615d5bf2f5d73622c1410e\",\"signer_id\":\"did:example:sink\",\"signer_pubkey\":\"d759793bbc13a2819a827c76adb6fba8a49aee007f49f2d0992d99b825ad2c48\",\"subject\":\"64c0713cb176874607bf8670295242184b7868a9ff7c55554a5ae08de2c301c1\",\"subject_type\":\"object\"}", + "context": { + "envelopes": [] + }, + "expected": { + "outcome": "reject", + "step": 6, + "reason": "session_classical_mismatch" + } + }, + { + "name": "session_classical_index_past_table", + "about": "a rendition index past the envelope's table", + "procedure": "claim", + "receipt": "{\"body\":{\"classical_declared\":700,\"classical_source\":\"wai2-table\",\"counted_discarded\":1904,\"counted_fallback\":0,\"counted_primary\":5607,\"deadline_us\":40000,\"decoders\":[{\"capability\":\"wai.video.int_hyper\",\"decoder\":\"builtin:wai@0.4.0\",\"leaves\":4,\"module_status\":null,\"path\":\"primary\",\"pin\":\"7b4371854df0aa1645ac6525b373387c0617b873d5a57748932ee0f386ea164b\",\"rendition\":0,\"tier\":\"decode-equivalence\",\"variant\":null},{\"capability\":\"wai.video.av1\",\"decoder\":\"builtin:wai@0.4.0\",\"leaves\":1,\"module_status\":null,\"path\":\"fallback\",\"pin\":null,\"rendition\":null,\"tier\":null,\"variant\":null},{\"capability\":\"wai.video.int_refine\",\"decoder\":\"builtin:wai@0.4.0\",\"leaves\":4,\"module_status\":null,\"path\":\"primary\",\"pin\":null,\"rendition\":null,\"tier\":null,\"variant\":null}],\"energy\":null,\"fallback_units\":1,\"framing\":\"registered\",\"host\":{\"build\":{\"profile\":\"release\",\"target\":\"aarch64-unknown-linux-gnu\",\"toolchain\":\"rustc 1.95.0\"},\"profile\":\"native-ffi\",\"target\":\"aarch64-unknown-linux-gnu\",\"threads\":4},\"leaf_count\":9,\"media\":\"video\",\"missed\":1,\"missed_units\":[{\"late_us\":1200,\"layers\":1,\"unit\":4}],\"output_root\":\"3cb2c68a7fe160511bd3fbbbd6945b5d54fac6b499e33769b1ea6828f04bb312\",\"primary_units\":4,\"receipt_bytes\":640,\"session_nonce\":\"57c5462dfdabd1b7bdd204d34ba33649c057eb535349f29f45eb8f8c7d4a7e7f\",\"stage_sets\":[{\"claim\":\"b636e8894207d2fe59add1e1cacf3b52ea760fccb4dc3f0abce79be90e871640\",\"first_unit\":0}],\"switches\":[{\"from\":\"primary\",\"reason\":\"set-incomplete\",\"to\":\"fallback\",\"unit\":4}],\"switches_total\":1,\"transferred\":13607,\"uncounted\":2,\"units\":5},\"class\":\"reconstruct-session\",\"issued_at\":\"2026-09-27T12:00:00Z\",\"kind\":\"claim\",\"parent_receipt_hash\":null,\"seq\":0,\"sig\":\"2871039f189db43685c214c860ac86567712af1e35d3254c371e7faaf8582734b5216c7ba4015383ad9013aac4c34ba1aebf410a56615d5bf2f5d73622c1410e\",\"signer_id\":\"did:example:sink\",\"signer_pubkey\":\"d759793bbc13a2819a827c76adb6fba8a49aee007f49f2d0992d99b825ad2c48\",\"subject\":\"64c0713cb176874607bf8670295242184b7868a9ff7c55554a5ae08de2c301c1\",\"subject_type\":\"object\"}", + "context": { + "envelopes": [ + { + "envelope": "57414932b30000007b22776169223a22312e31222c226d65646961223a22766964656f222c22696e74656e74223a227265706c6963617465222c2272656e646974696f6e73223a5b7b226361706162696c697479223a227761692e766964656f2e696e745f6879706572222c226b696e64223a22696e745f6879706572227d2c7b226361706162696c697479223a227761692e766964656f2e617663222c226b696e64223a22617663227d5d2c22746172676574223a6e756c6c7d020000000000c8000000c8000000bc020000111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111122222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222", + "rendition": 2 + } + ] + }, + "expected": { + "outcome": "reject", + "step": 6, + "reason": "session_classical_mismatch" + } + }, + { + "name": "session_classical_not_wai2", + "about": "a WAI1 envelope given as the entry envelope", + "procedure": "claim", + "receipt": "{\"body\":{\"classical_declared\":700,\"classical_source\":\"wai2-table\",\"counted_discarded\":1904,\"counted_fallback\":0,\"counted_primary\":5607,\"deadline_us\":40000,\"decoders\":[{\"capability\":\"wai.video.int_hyper\",\"decoder\":\"builtin:wai@0.4.0\",\"leaves\":4,\"module_status\":null,\"path\":\"primary\",\"pin\":\"7b4371854df0aa1645ac6525b373387c0617b873d5a57748932ee0f386ea164b\",\"rendition\":0,\"tier\":\"decode-equivalence\",\"variant\":null},{\"capability\":\"wai.video.av1\",\"decoder\":\"builtin:wai@0.4.0\",\"leaves\":1,\"module_status\":null,\"path\":\"fallback\",\"pin\":null,\"rendition\":null,\"tier\":null,\"variant\":null},{\"capability\":\"wai.video.int_refine\",\"decoder\":\"builtin:wai@0.4.0\",\"leaves\":4,\"module_status\":null,\"path\":\"primary\",\"pin\":null,\"rendition\":null,\"tier\":null,\"variant\":null}],\"energy\":null,\"fallback_units\":1,\"framing\":\"registered\",\"host\":{\"build\":{\"profile\":\"release\",\"target\":\"aarch64-unknown-linux-gnu\",\"toolchain\":\"rustc 1.95.0\"},\"profile\":\"native-ffi\",\"target\":\"aarch64-unknown-linux-gnu\",\"threads\":4},\"leaf_count\":9,\"media\":\"video\",\"missed\":1,\"missed_units\":[{\"late_us\":1200,\"layers\":1,\"unit\":4}],\"output_root\":\"3cb2c68a7fe160511bd3fbbbd6945b5d54fac6b499e33769b1ea6828f04bb312\",\"primary_units\":4,\"receipt_bytes\":640,\"session_nonce\":\"57c5462dfdabd1b7bdd204d34ba33649c057eb535349f29f45eb8f8c7d4a7e7f\",\"stage_sets\":[{\"claim\":\"b636e8894207d2fe59add1e1cacf3b52ea760fccb4dc3f0abce79be90e871640\",\"first_unit\":0}],\"switches\":[{\"from\":\"primary\",\"reason\":\"set-incomplete\",\"to\":\"fallback\",\"unit\":4}],\"switches_total\":1,\"transferred\":13607,\"uncounted\":2,\"units\":5},\"class\":\"reconstruct-session\",\"issued_at\":\"2026-09-27T12:00:00Z\",\"kind\":\"claim\",\"parent_receipt_hash\":null,\"seq\":0,\"sig\":\"2871039f189db43685c214c860ac86567712af1e35d3254c371e7faaf8582734b5216c7ba4015383ad9013aac4c34ba1aebf410a56615d5bf2f5d73622c1410e\",\"signer_id\":\"did:example:sink\",\"signer_pubkey\":\"d759793bbc13a2819a827c76adb6fba8a49aee007f49f2d0992d99b825ad2c48\",\"subject\":\"64c0713cb176874607bf8670295242184b7868a9ff7c55554a5ae08de2c301c1\",\"subject_type\":\"object\"}", + "context": { + "envelopes": [ + { + "envelope": "57414931020000007b7d00000000", + "rendition": 0 + } + ] + }, + "expected": { + "outcome": "reject", + "step": 6, + "reason": "session_classical_mismatch" + } + }, + { + "name": "session_no_classical_accept", + "about": "a session with no classical rendition, checked against no envelope", + "procedure": "claim", + "receipt": "{\"body\":{\"classical_declared\":null,\"classical_source\":null,\"counted_discarded\":1904,\"counted_fallback\":0,\"counted_primary\":5607,\"deadline_us\":40000,\"decoders\":[{\"capability\":\"wai.video.int_hyper\",\"decoder\":\"builtin:wai@0.4.0\",\"leaves\":4,\"module_status\":null,\"path\":\"primary\",\"pin\":\"7b4371854df0aa1645ac6525b373387c0617b873d5a57748932ee0f386ea164b\",\"rendition\":0,\"tier\":\"decode-equivalence\",\"variant\":null},{\"capability\":\"wai.video.av1\",\"decoder\":\"builtin:wai@0.4.0\",\"leaves\":1,\"module_status\":null,\"path\":\"fallback\",\"pin\":null,\"rendition\":null,\"tier\":null,\"variant\":null},{\"capability\":\"wai.video.int_refine\",\"decoder\":\"builtin:wai@0.4.0\",\"leaves\":4,\"module_status\":null,\"path\":\"primary\",\"pin\":null,\"rendition\":null,\"tier\":null,\"variant\":null}],\"energy\":null,\"fallback_units\":1,\"framing\":\"registered\",\"host\":{\"build\":{\"profile\":\"release\",\"target\":\"aarch64-unknown-linux-gnu\",\"toolchain\":\"rustc 1.95.0\"},\"profile\":\"native-ffi\",\"target\":\"aarch64-unknown-linux-gnu\",\"threads\":4},\"leaf_count\":9,\"media\":\"video\",\"missed\":1,\"missed_units\":[{\"late_us\":1200,\"layers\":1,\"unit\":4}],\"output_root\":\"3cb2c68a7fe160511bd3fbbbd6945b5d54fac6b499e33769b1ea6828f04bb312\",\"primary_units\":4,\"receipt_bytes\":640,\"session_nonce\":\"57c5462dfdabd1b7bdd204d34ba33649c057eb535349f29f45eb8f8c7d4a7e7f\",\"stage_sets\":[{\"claim\":\"b636e8894207d2fe59add1e1cacf3b52ea760fccb4dc3f0abce79be90e871640\",\"first_unit\":0}],\"switches\":[{\"from\":\"primary\",\"reason\":\"set-incomplete\",\"to\":\"fallback\",\"unit\":4}],\"switches_total\":1,\"transferred\":13607,\"uncounted\":2,\"units\":5},\"class\":\"reconstruct-session\",\"issued_at\":\"2026-09-27T12:00:00Z\",\"kind\":\"claim\",\"parent_receipt_hash\":null,\"seq\":0,\"sig\":\"1cf2fb5a961bffa7755c939aea26c10ca39d9dac416426f6bb442968fcb96d7a03b1a5b0726ad0e95581d790cc69dc18e131cf1f5666e2e1de0f5d94e97a2300\",\"signer_id\":\"did:example:sink\",\"signer_pubkey\":\"d759793bbc13a2819a827c76adb6fba8a49aee007f49f2d0992d99b825ad2c48\",\"subject\":\"64c0713cb176874607bf8670295242184b7868a9ff7c55554a5ae08de2c301c1\",\"subject_type\":\"object\"}", + "context": { + "envelopes": [] + }, + "expected": { + "outcome": "accept", + "link_hash": "71ed19030c3daa0a6068721effb303b6202fe2d67cc72cb8f5f50cbc1dc6a8a6" + } + }, + { + "name": "session_stage_claim_invalid", + "about": "the stage claim the session names, with its signature broken", + "procedure": "claim", + "receipt": "{\"body\":{\"classical_declared\":700,\"classical_source\":\"wai2-table\",\"counted_discarded\":1904,\"counted_fallback\":0,\"counted_primary\":5607,\"deadline_us\":40000,\"decoders\":[{\"capability\":\"wai.video.int_hyper\",\"decoder\":\"builtin:wai@0.4.0\",\"leaves\":4,\"module_status\":null,\"path\":\"primary\",\"pin\":\"7b4371854df0aa1645ac6525b373387c0617b873d5a57748932ee0f386ea164b\",\"rendition\":0,\"tier\":\"decode-equivalence\",\"variant\":null},{\"capability\":\"wai.video.av1\",\"decoder\":\"builtin:wai@0.4.0\",\"leaves\":1,\"module_status\":null,\"path\":\"fallback\",\"pin\":null,\"rendition\":null,\"tier\":null,\"variant\":null},{\"capability\":\"wai.video.int_refine\",\"decoder\":\"builtin:wai@0.4.0\",\"leaves\":4,\"module_status\":null,\"path\":\"primary\",\"pin\":null,\"rendition\":null,\"tier\":null,\"variant\":null}],\"energy\":null,\"fallback_units\":1,\"framing\":\"registered\",\"host\":{\"build\":{\"profile\":\"release\",\"target\":\"aarch64-unknown-linux-gnu\",\"toolchain\":\"rustc 1.95.0\"},\"profile\":\"native-ffi\",\"target\":\"aarch64-unknown-linux-gnu\",\"threads\":4},\"leaf_count\":9,\"media\":\"video\",\"missed\":1,\"missed_units\":[{\"late_us\":1200,\"layers\":1,\"unit\":4}],\"output_root\":\"3cb2c68a7fe160511bd3fbbbd6945b5d54fac6b499e33769b1ea6828f04bb312\",\"primary_units\":4,\"receipt_bytes\":640,\"session_nonce\":\"57c5462dfdabd1b7bdd204d34ba33649c057eb535349f29f45eb8f8c7d4a7e7f\",\"stage_sets\":[{\"claim\":\"b636e8894207d2fe59add1e1cacf3b52ea760fccb4dc3f0abce79be90e871640\",\"first_unit\":0}],\"switches\":[{\"from\":\"primary\",\"reason\":\"set-incomplete\",\"to\":\"fallback\",\"unit\":4}],\"switches_total\":1,\"transferred\":13607,\"uncounted\":2,\"units\":5},\"class\":\"reconstruct-session\",\"issued_at\":\"2026-09-27T12:00:00Z\",\"kind\":\"claim\",\"parent_receipt_hash\":null,\"seq\":0,\"sig\":\"2871039f189db43685c214c860ac86567712af1e35d3254c371e7faaf8582734b5216c7ba4015383ad9013aac4c34ba1aebf410a56615d5bf2f5d73622c1410e\",\"signer_id\":\"did:example:sink\",\"signer_pubkey\":\"d759793bbc13a2819a827c76adb6fba8a49aee007f49f2d0992d99b825ad2c48\",\"subject\":\"64c0713cb176874607bf8670295242184b7868a9ff7c55554a5ae08de2c301c1\",\"subject_type\":\"object\"}", + "context": { + "outputs": [ + { + "unit": 0, + "layers": 1, + "decoder": 0, + "out_digest": "55f7e628ca707e2ca3159709eeb68b9000813f2916a299acd33a23e6fe012584" + }, + { + "unit": 1, + "layers": 1, + "decoder": 0, + "out_digest": "a3ee8a4b96eceb663f3d94417957d02f897fc166dc96ebe9bf447c4a36a36264" + }, + { + "unit": 2, + "layers": 1, + "decoder": 0, + "out_digest": "00576d2c4d09ef5d7aa807f9b3b1587e200dea6f6694b4da062b41aa2a5ab8af" + }, + { + "unit": 3, + "layers": 1, + "decoder": 0, + "out_digest": "26cd9b2805b604b26e08d9a461db599c4e249bfd4df41a3befb202bc6d0e0700" + }, + { + "unit": 4, + "layers": 1, + "decoder": 1, + "out_digest": "1cd1984bc553c43ee5a48fe7e182a77e60d8ef3c2b0f959ef1a0efd3813b411f" + }, + { + "unit": 0, + "layers": 2, + "decoder": 2, + "out_digest": "cedffc10c0d2e777c954459c198af496e316170b3a8c35276a3f473edf438a0e" + }, + { + "unit": 1, + "layers": 2, + "decoder": 2, + "out_digest": "f0348794b5be95fd5c4e8f268957b6d188c35f76146f4479c960124a4392841d" + }, + { + "unit": 2, + "layers": 2, + "decoder": 2, + "out_digest": "446c9941549464ba1b15c36c6e738380f8918f4a63a47ebbbdd67058a1975a80" + }, + { + "unit": 0, + "layers": 3, + "decoder": 2, + "out_digest": "a80c01cb3ded2f965b69ec4a5b3f1dcb6996e05454d9963e0b05455f9f27bc2f" + } + ], + "stage_claims": [ + "{\"body\":{\"bytes_envelopes\":10607,\"conflicts\":0,\"deadline_misses\":2,\"objects\":[{\"bytes\":900,\"evidence\":\"none\",\"layer\":1,\"object\":\"47a2c23727d2eb9d2beef0931c3e9b2675408d372660420cce427dc27fd21fe1\",\"reason\":null,\"status\":\"applied\",\"units\":{\"count\":1,\"from\":0}},{\"bytes\":901,\"evidence\":\"none\",\"layer\":1,\"object\":\"6b74be11e64461c7d972fc5cb6ba15e98427e9d6e60622b0a753222138de28cf\",\"reason\":null,\"status\":\"applied\",\"units\":{\"count\":1,\"from\":1}},{\"bytes\":902,\"evidence\":\"none\",\"layer\":1,\"object\":\"5e7a38ca5c04442cbe00b040d58e4494f5aa36fb81e8bbe0d304fd2d1ce722b2\",\"reason\":null,\"status\":\"applied\",\"units\":{\"count\":1,\"from\":2}},{\"bytes\":903,\"evidence\":\"none\",\"layer\":1,\"object\":\"792a12990c5207ca83a86b7420815f1f2d34918553a0130a4f9570a11354f2ca\",\"reason\":null,\"status\":\"late\",\"units\":{\"count\":1,\"from\":3}},{\"bytes\":1000,\"evidence\":\"none\",\"layer\":2,\"object\":\"be5055af8e32359265852c512667b10ab6a07455e5ab06603e278763f6633a85\",\"reason\":null,\"status\":\"applied\",\"units\":{\"count\":1,\"from\":0}},{\"bytes\":1001,\"evidence\":\"none\",\"layer\":2,\"object\":\"1c6eae0ed41ed7fc1b2f00b46ea1de98f21a6d6cbf62bf6b22cf76a664a49376\",\"reason\":null,\"status\":\"late\",\"units\":{\"count\":1,\"from\":1}}],\"op_committed\":null,\"op_delivered\":null,\"op_requested\":null,\"presented\":{\"wai-stage:layers\":0},\"stage_hash\":null,\"tier\":\"none\",\"units_by_stage\":[1,2,1],\"vocabulary\":\"urn:wai:staged-delivery:1\"},\"class\":\"stage\",\"issued_at\":\"2026-09-27T12:00:00Z\",\"kind\":\"claim\",\"parent_receipt_hash\":null,\"seq\":0,\"sig\":\"97eb16ba17662e0981fcaf390e1172cefae5c4b2ca5fcf1df3ea10b5176fb0225169a07938ffcb0362d8c35472dab6d39711c331765ebc083bb3b6a55b20da02\",\"signer_id\":\"did:example:sink\",\"signer_pubkey\":\"d759793bbc13a2819a827c76adb6fba8a49aee007f49f2d0992d99b825ad2c48\",\"subject\":\"3844a5152c86c7892dc6c942553da2496c949edd7e32dbbc1a013c4c5d41f54f\",\"subject_type\":\"object\"}" + ] + }, + "expected": { + "outcome": "reject", + "step": 6, + "reason": "context_invalid" + } + }, + { + "name": "session_stage_claim_other_signer", + "about": "a stage claim signed by another key, named by the session", + "procedure": "claim", + "receipt": "{\"body\":{\"classical_declared\":700,\"classical_source\":\"wai2-table\",\"counted_discarded\":1904,\"counted_fallback\":0,\"counted_primary\":5607,\"deadline_us\":40000,\"decoders\":[{\"capability\":\"wai.video.int_hyper\",\"decoder\":\"builtin:wai@0.4.0\",\"leaves\":4,\"module_status\":null,\"path\":\"primary\",\"pin\":\"7b4371854df0aa1645ac6525b373387c0617b873d5a57748932ee0f386ea164b\",\"rendition\":0,\"tier\":\"decode-equivalence\",\"variant\":null},{\"capability\":\"wai.video.av1\",\"decoder\":\"builtin:wai@0.4.0\",\"leaves\":1,\"module_status\":null,\"path\":\"fallback\",\"pin\":null,\"rendition\":null,\"tier\":null,\"variant\":null},{\"capability\":\"wai.video.int_refine\",\"decoder\":\"builtin:wai@0.4.0\",\"leaves\":4,\"module_status\":null,\"path\":\"primary\",\"pin\":null,\"rendition\":null,\"tier\":null,\"variant\":null}],\"energy\":null,\"fallback_units\":1,\"framing\":\"registered\",\"host\":{\"build\":{\"profile\":\"release\",\"target\":\"aarch64-unknown-linux-gnu\",\"toolchain\":\"rustc 1.95.0\"},\"profile\":\"native-ffi\",\"target\":\"aarch64-unknown-linux-gnu\",\"threads\":4},\"leaf_count\":9,\"media\":\"video\",\"missed\":1,\"missed_units\":[{\"late_us\":1200,\"layers\":1,\"unit\":4}],\"output_root\":\"3cb2c68a7fe160511bd3fbbbd6945b5d54fac6b499e33769b1ea6828f04bb312\",\"primary_units\":4,\"receipt_bytes\":640,\"session_nonce\":\"57c5462dfdabd1b7bdd204d34ba33649c057eb535349f29f45eb8f8c7d4a7e7f\",\"stage_sets\":[{\"claim\":\"2ff7a3fb9017dd175c276d2e434ec3ee0814a0f98b8f4187f4ed4008ba62556f\",\"first_unit\":0}],\"switches\":[{\"from\":\"primary\",\"reason\":\"set-incomplete\",\"to\":\"fallback\",\"unit\":4}],\"switches_total\":1,\"transferred\":13607,\"uncounted\":2,\"units\":5},\"class\":\"reconstruct-session\",\"issued_at\":\"2026-09-27T12:00:00Z\",\"kind\":\"claim\",\"parent_receipt_hash\":null,\"seq\":0,\"sig\":\"f983c8be1c0a6e5eae0eb144683fa5e3b7ed156f31c4c53aec413946dbc862fc28fdba280396406743ea5e5796432905db0d9d7147b161dbc05ce372d7a41608\",\"signer_id\":\"did:example:sink\",\"signer_pubkey\":\"d759793bbc13a2819a827c76adb6fba8a49aee007f49f2d0992d99b825ad2c48\",\"subject\":\"64c0713cb176874607bf8670295242184b7868a9ff7c55554a5ae08de2c301c1\",\"subject_type\":\"object\"}", + "context": { + "outputs": [ + { + "unit": 0, + "layers": 1, + "decoder": 0, + "out_digest": "55f7e628ca707e2ca3159709eeb68b9000813f2916a299acd33a23e6fe012584" + }, + { + "unit": 1, + "layers": 1, + "decoder": 0, + "out_digest": "a3ee8a4b96eceb663f3d94417957d02f897fc166dc96ebe9bf447c4a36a36264" + }, + { + "unit": 2, + "layers": 1, + "decoder": 0, + "out_digest": "00576d2c4d09ef5d7aa807f9b3b1587e200dea6f6694b4da062b41aa2a5ab8af" + }, + { + "unit": 3, + "layers": 1, + "decoder": 0, + "out_digest": "26cd9b2805b604b26e08d9a461db599c4e249bfd4df41a3befb202bc6d0e0700" + }, + { + "unit": 4, + "layers": 1, + "decoder": 1, + "out_digest": "1cd1984bc553c43ee5a48fe7e182a77e60d8ef3c2b0f959ef1a0efd3813b411f" + }, + { + "unit": 0, + "layers": 2, + "decoder": 2, + "out_digest": "cedffc10c0d2e777c954459c198af496e316170b3a8c35276a3f473edf438a0e" + }, + { + "unit": 1, + "layers": 2, + "decoder": 2, + "out_digest": "f0348794b5be95fd5c4e8f268957b6d188c35f76146f4479c960124a4392841d" + }, + { + "unit": 2, + "layers": 2, + "decoder": 2, + "out_digest": "446c9941549464ba1b15c36c6e738380f8918f4a63a47ebbbdd67058a1975a80" + }, + { + "unit": 0, + "layers": 3, + "decoder": 2, + "out_digest": "a80c01cb3ded2f965b69ec4a5b3f1dcb6996e05454d9963e0b05455f9f27bc2f" + } + ], + "stage_claims": [ + "{\"body\":{\"bytes_envelopes\":10607,\"conflicts\":0,\"deadline_misses\":2,\"objects\":[{\"bytes\":900,\"evidence\":\"none\",\"layer\":1,\"object\":\"47a2c23727d2eb9d2beef0931c3e9b2675408d372660420cce427dc27fd21fe1\",\"reason\":null,\"status\":\"applied\",\"units\":{\"count\":1,\"from\":0}},{\"bytes\":901,\"evidence\":\"none\",\"layer\":1,\"object\":\"6b74be11e64461c7d972fc5cb6ba15e98427e9d6e60622b0a753222138de28cf\",\"reason\":null,\"status\":\"applied\",\"units\":{\"count\":1,\"from\":1}},{\"bytes\":902,\"evidence\":\"none\",\"layer\":1,\"object\":\"5e7a38ca5c04442cbe00b040d58e4494f5aa36fb81e8bbe0d304fd2d1ce722b2\",\"reason\":null,\"status\":\"applied\",\"units\":{\"count\":1,\"from\":2}},{\"bytes\":903,\"evidence\":\"none\",\"layer\":1,\"object\":\"792a12990c5207ca83a86b7420815f1f2d34918553a0130a4f9570a11354f2ca\",\"reason\":null,\"status\":\"late\",\"units\":{\"count\":1,\"from\":3}},{\"bytes\":1000,\"evidence\":\"none\",\"layer\":2,\"object\":\"be5055af8e32359265852c512667b10ab6a07455e5ab06603e278763f6633a85\",\"reason\":null,\"status\":\"applied\",\"units\":{\"count\":1,\"from\":0}},{\"bytes\":1001,\"evidence\":\"none\",\"layer\":2,\"object\":\"1c6eae0ed41ed7fc1b2f00b46ea1de98f21a6d6cbf62bf6b22cf76a664a49376\",\"reason\":null,\"status\":\"late\",\"units\":{\"count\":1,\"from\":1}}],\"op_committed\":null,\"op_delivered\":null,\"op_requested\":null,\"presented\":{\"wai-stage:layers\":0},\"stage_hash\":null,\"tier\":\"none\",\"units_by_stage\":[1,2,1],\"vocabulary\":\"urn:wai:staged-delivery:1\"},\"class\":\"stage\",\"issued_at\":\"2026-09-27T12:00:00Z\",\"kind\":\"claim\",\"parent_receipt_hash\":null,\"seq\":0,\"sig\":\"05e71bdb8bfabe4669a76eff890fb1abe382b87fb64761273071cc00379812d954b7d9a53cf56554fad2fde0a7cd0bc1b434de0aa4741518d83f5b1c20efa60e\",\"signer_id\":\"did:example:relay\",\"signer_pubkey\":\"34b4d9043156cb6dcf0beb0a2949b7559c940d2bcb6dbe8c53a9b30278e3a746\",\"subject\":\"3844a5152c86c7892dc6c942553da2496c949edd7e32dbbc1a013c4c5d41f54f\",\"subject_type\":\"object\"}" + ] + }, + "expected": { + "outcome": "reject", + "step": 6, + "reason": "context_mismatch" + } + }, + { + "name": "session_stage_claim_not_named", + "about": "a stage claim the session does not name", + "procedure": "claim", + "receipt": "{\"body\":{\"classical_declared\":700,\"classical_source\":\"wai2-table\",\"counted_discarded\":1904,\"counted_fallback\":0,\"counted_primary\":5607,\"deadline_us\":40000,\"decoders\":[{\"capability\":\"wai.video.int_hyper\",\"decoder\":\"builtin:wai@0.4.0\",\"leaves\":4,\"module_status\":null,\"path\":\"primary\",\"pin\":\"7b4371854df0aa1645ac6525b373387c0617b873d5a57748932ee0f386ea164b\",\"rendition\":0,\"tier\":\"decode-equivalence\",\"variant\":null},{\"capability\":\"wai.video.av1\",\"decoder\":\"builtin:wai@0.4.0\",\"leaves\":1,\"module_status\":null,\"path\":\"fallback\",\"pin\":null,\"rendition\":null,\"tier\":null,\"variant\":null},{\"capability\":\"wai.video.int_refine\",\"decoder\":\"builtin:wai@0.4.0\",\"leaves\":4,\"module_status\":null,\"path\":\"primary\",\"pin\":null,\"rendition\":null,\"tier\":null,\"variant\":null}],\"energy\":null,\"fallback_units\":1,\"framing\":\"registered\",\"host\":{\"build\":{\"profile\":\"release\",\"target\":\"aarch64-unknown-linux-gnu\",\"toolchain\":\"rustc 1.95.0\"},\"profile\":\"native-ffi\",\"target\":\"aarch64-unknown-linux-gnu\",\"threads\":4},\"leaf_count\":9,\"media\":\"video\",\"missed\":1,\"missed_units\":[{\"late_us\":1200,\"layers\":1,\"unit\":4}],\"output_root\":\"3cb2c68a7fe160511bd3fbbbd6945b5d54fac6b499e33769b1ea6828f04bb312\",\"primary_units\":4,\"receipt_bytes\":640,\"session_nonce\":\"57c5462dfdabd1b7bdd204d34ba33649c057eb535349f29f45eb8f8c7d4a7e7f\",\"stage_sets\":[{\"claim\":\"b636e8894207d2fe59add1e1cacf3b52ea760fccb4dc3f0abce79be90e871640\",\"first_unit\":0}],\"switches\":[{\"from\":\"primary\",\"reason\":\"set-incomplete\",\"to\":\"fallback\",\"unit\":4}],\"switches_total\":1,\"transferred\":13607,\"uncounted\":2,\"units\":5},\"class\":\"reconstruct-session\",\"issued_at\":\"2026-09-27T12:00:00Z\",\"kind\":\"claim\",\"parent_receipt_hash\":null,\"seq\":0,\"sig\":\"2871039f189db43685c214c860ac86567712af1e35d3254c371e7faaf8582734b5216c7ba4015383ad9013aac4c34ba1aebf410a56615d5bf2f5d73622c1410e\",\"signer_id\":\"did:example:sink\",\"signer_pubkey\":\"d759793bbc13a2819a827c76adb6fba8a49aee007f49f2d0992d99b825ad2c48\",\"subject\":\"64c0713cb176874607bf8670295242184b7868a9ff7c55554a5ae08de2c301c1\",\"subject_type\":\"object\"}", + "context": { + "outputs": [ + { + "unit": 0, + "layers": 1, + "decoder": 0, + "out_digest": "55f7e628ca707e2ca3159709eeb68b9000813f2916a299acd33a23e6fe012584" + }, + { + "unit": 1, + "layers": 1, + "decoder": 0, + "out_digest": "a3ee8a4b96eceb663f3d94417957d02f897fc166dc96ebe9bf447c4a36a36264" + }, + { + "unit": 2, + "layers": 1, + "decoder": 0, + "out_digest": "00576d2c4d09ef5d7aa807f9b3b1587e200dea6f6694b4da062b41aa2a5ab8af" + }, + { + "unit": 3, + "layers": 1, + "decoder": 0, + "out_digest": "26cd9b2805b604b26e08d9a461db599c4e249bfd4df41a3befb202bc6d0e0700" + }, + { + "unit": 4, + "layers": 1, + "decoder": 1, + "out_digest": "1cd1984bc553c43ee5a48fe7e182a77e60d8ef3c2b0f959ef1a0efd3813b411f" + }, + { + "unit": 0, + "layers": 2, + "decoder": 2, + "out_digest": "cedffc10c0d2e777c954459c198af496e316170b3a8c35276a3f473edf438a0e" + }, + { + "unit": 1, + "layers": 2, + "decoder": 2, + "out_digest": "f0348794b5be95fd5c4e8f268957b6d188c35f76146f4479c960124a4392841d" + }, + { + "unit": 2, + "layers": 2, + "decoder": 2, + "out_digest": "446c9941549464ba1b15c36c6e738380f8918f4a63a47ebbbdd67058a1975a80" + }, + { + "unit": 0, + "layers": 3, + "decoder": 2, + "out_digest": "a80c01cb3ded2f965b69ec4a5b3f1dcb6996e05454d9963e0b05455f9f27bc2f" + } + ], + "stage_claims": [ + "{\"body\":{\"bytes_envelopes\":10607,\"conflicts\":0,\"deadline_misses\":2,\"objects\":[{\"bytes\":900,\"evidence\":\"none\",\"layer\":1,\"object\":\"47a2c23727d2eb9d2beef0931c3e9b2675408d372660420cce427dc27fd21fe1\",\"reason\":null,\"status\":\"applied\",\"units\":{\"count\":1,\"from\":0}},{\"bytes\":901,\"evidence\":\"none\",\"layer\":1,\"object\":\"6b74be11e64461c7d972fc5cb6ba15e98427e9d6e60622b0a753222138de28cf\",\"reason\":null,\"status\":\"applied\",\"units\":{\"count\":1,\"from\":1}},{\"bytes\":902,\"evidence\":\"none\",\"layer\":1,\"object\":\"5e7a38ca5c04442cbe00b040d58e4494f5aa36fb81e8bbe0d304fd2d1ce722b2\",\"reason\":null,\"status\":\"applied\",\"units\":{\"count\":1,\"from\":2}},{\"bytes\":903,\"evidence\":\"none\",\"layer\":1,\"object\":\"792a12990c5207ca83a86b7420815f1f2d34918553a0130a4f9570a11354f2ca\",\"reason\":null,\"status\":\"late\",\"units\":{\"count\":1,\"from\":3}},{\"bytes\":1000,\"evidence\":\"none\",\"layer\":2,\"object\":\"be5055af8e32359265852c512667b10ab6a07455e5ab06603e278763f6633a85\",\"reason\":null,\"status\":\"applied\",\"units\":{\"count\":1,\"from\":0}},{\"bytes\":1001,\"evidence\":\"none\",\"layer\":2,\"object\":\"1c6eae0ed41ed7fc1b2f00b46ea1de98f21a6d6cbf62bf6b22cf76a664a49376\",\"reason\":null,\"status\":\"late\",\"units\":{\"count\":1,\"from\":1}}],\"op_committed\":null,\"op_delivered\":null,\"op_requested\":null,\"presented\":{\"wai-stage:layers\":0},\"stage_hash\":null,\"tier\":\"none\",\"units_by_stage\":[1,2,1],\"vocabulary\":\"urn:wai:staged-delivery:1\"},\"class\":\"stage\",\"issued_at\":\"2026-09-27T12:00:00Z\",\"kind\":\"claim\",\"parent_receipt_hash\":null,\"seq\":0,\"sig\":\"283377cdc8d8796dbf727f9415bee1ac13497020a5d8443d4c29c56030c64d79bfa03c3e80904537e62cb64b42105871fc95cc47d92578d44e9275d5fe968207\",\"signer_id\":\"did:example:sink\",\"signer_pubkey\":\"d759793bbc13a2819a827c76adb6fba8a49aee007f49f2d0992d99b825ad2c48\",\"subject\":\"7d947c110518a60a86e7548523a6b542a18ab64807447e0d33598dd51203dc98\",\"subject_type\":\"object\"}" + ] + }, + "expected": { + "outcome": "reject", + "step": 6, + "reason": "context_mismatch" + } + }, + { + "name": "session_stage_disagrees", + "about": "a stage claim with two units at stage 2 where the session presented one unit at three layers", + "procedure": "claim", + "receipt": "{\"body\":{\"classical_declared\":700,\"classical_source\":\"wai2-table\",\"counted_discarded\":1904,\"counted_fallback\":0,\"counted_primary\":5607,\"deadline_us\":40000,\"decoders\":[{\"capability\":\"wai.video.int_hyper\",\"decoder\":\"builtin:wai@0.4.0\",\"leaves\":4,\"module_status\":null,\"path\":\"primary\",\"pin\":\"7b4371854df0aa1645ac6525b373387c0617b873d5a57748932ee0f386ea164b\",\"rendition\":0,\"tier\":\"decode-equivalence\",\"variant\":null},{\"capability\":\"wai.video.av1\",\"decoder\":\"builtin:wai@0.4.0\",\"leaves\":1,\"module_status\":null,\"path\":\"fallback\",\"pin\":null,\"rendition\":null,\"tier\":null,\"variant\":null},{\"capability\":\"wai.video.int_refine\",\"decoder\":\"builtin:wai@0.4.0\",\"leaves\":4,\"module_status\":null,\"path\":\"primary\",\"pin\":null,\"rendition\":null,\"tier\":null,\"variant\":null}],\"energy\":null,\"fallback_units\":1,\"framing\":\"registered\",\"host\":{\"build\":{\"profile\":\"release\",\"target\":\"aarch64-unknown-linux-gnu\",\"toolchain\":\"rustc 1.95.0\"},\"profile\":\"native-ffi\",\"target\":\"aarch64-unknown-linux-gnu\",\"threads\":4},\"leaf_count\":9,\"media\":\"video\",\"missed\":1,\"missed_units\":[{\"late_us\":1200,\"layers\":1,\"unit\":4}],\"output_root\":\"3cb2c68a7fe160511bd3fbbbd6945b5d54fac6b499e33769b1ea6828f04bb312\",\"primary_units\":4,\"receipt_bytes\":640,\"session_nonce\":\"57c5462dfdabd1b7bdd204d34ba33649c057eb535349f29f45eb8f8c7d4a7e7f\",\"stage_sets\":[{\"claim\":\"5d141d903553ba57805fd040ce320298256a0077d26eb6bfaf82378fed9c8fe2\",\"first_unit\":0}],\"switches\":[{\"from\":\"primary\",\"reason\":\"set-incomplete\",\"to\":\"fallback\",\"unit\":4}],\"switches_total\":1,\"transferred\":13607,\"uncounted\":2,\"units\":5},\"class\":\"reconstruct-session\",\"issued_at\":\"2026-09-27T12:00:00Z\",\"kind\":\"claim\",\"parent_receipt_hash\":null,\"seq\":0,\"sig\":\"177e6828641484add22e33169a5215da9d16d448559847182d15352034f17702903e06de31b372c6f890baff85ef7e87b1821a106408200f6f20cc2f85b9ce0e\",\"signer_id\":\"did:example:sink\",\"signer_pubkey\":\"d759793bbc13a2819a827c76adb6fba8a49aee007f49f2d0992d99b825ad2c48\",\"subject\":\"64c0713cb176874607bf8670295242184b7868a9ff7c55554a5ae08de2c301c1\",\"subject_type\":\"object\"}", + "context": { + "outputs": [ + { + "unit": 0, + "layers": 1, + "decoder": 0, + "out_digest": "55f7e628ca707e2ca3159709eeb68b9000813f2916a299acd33a23e6fe012584" + }, + { + "unit": 1, + "layers": 1, + "decoder": 0, + "out_digest": "a3ee8a4b96eceb663f3d94417957d02f897fc166dc96ebe9bf447c4a36a36264" + }, + { + "unit": 2, + "layers": 1, + "decoder": 0, + "out_digest": "00576d2c4d09ef5d7aa807f9b3b1587e200dea6f6694b4da062b41aa2a5ab8af" + }, + { + "unit": 3, + "layers": 1, + "decoder": 0, + "out_digest": "26cd9b2805b604b26e08d9a461db599c4e249bfd4df41a3befb202bc6d0e0700" + }, + { + "unit": 4, + "layers": 1, + "decoder": 1, + "out_digest": "1cd1984bc553c43ee5a48fe7e182a77e60d8ef3c2b0f959ef1a0efd3813b411f" + }, + { + "unit": 0, + "layers": 2, + "decoder": 2, + "out_digest": "cedffc10c0d2e777c954459c198af496e316170b3a8c35276a3f473edf438a0e" + }, + { + "unit": 1, + "layers": 2, + "decoder": 2, + "out_digest": "f0348794b5be95fd5c4e8f268957b6d188c35f76146f4479c960124a4392841d" + }, + { + "unit": 2, + "layers": 2, + "decoder": 2, + "out_digest": "446c9941549464ba1b15c36c6e738380f8918f4a63a47ebbbdd67058a1975a80" + }, + { + "unit": 0, + "layers": 3, + "decoder": 2, + "out_digest": "a80c01cb3ded2f965b69ec4a5b3f1dcb6996e05454d9963e0b05455f9f27bc2f" + } + ], + "stage_claims": [ + "{\"body\":{\"bytes_envelopes\":10607,\"conflicts\":0,\"deadline_misses\":1,\"objects\":[{\"bytes\":900,\"evidence\":\"none\",\"layer\":1,\"object\":\"47a2c23727d2eb9d2beef0931c3e9b2675408d372660420cce427dc27fd21fe1\",\"reason\":null,\"status\":\"applied\",\"units\":{\"count\":1,\"from\":0}},{\"bytes\":901,\"evidence\":\"none\",\"layer\":1,\"object\":\"6b74be11e64461c7d972fc5cb6ba15e98427e9d6e60622b0a753222138de28cf\",\"reason\":null,\"status\":\"applied\",\"units\":{\"count\":1,\"from\":1}},{\"bytes\":902,\"evidence\":\"none\",\"layer\":1,\"object\":\"5e7a38ca5c04442cbe00b040d58e4494f5aa36fb81e8bbe0d304fd2d1ce722b2\",\"reason\":null,\"status\":\"applied\",\"units\":{\"count\":1,\"from\":2}},{\"bytes\":903,\"evidence\":\"none\",\"layer\":1,\"object\":\"792a12990c5207ca83a86b7420815f1f2d34918553a0130a4f9570a11354f2ca\",\"reason\":null,\"status\":\"late\",\"units\":{\"count\":1,\"from\":3}},{\"bytes\":1000,\"evidence\":\"none\",\"layer\":2,\"object\":\"be5055af8e32359265852c512667b10ab6a07455e5ab06603e278763f6633a85\",\"reason\":null,\"status\":\"applied\",\"units\":{\"count\":1,\"from\":0}},{\"bytes\":1001,\"evidence\":\"none\",\"layer\":2,\"object\":\"1c6eae0ed41ed7fc1b2f00b46ea1de98f21a6d6cbf62bf6b22cf76a664a49376\",\"reason\":null,\"status\":\"applied\",\"units\":{\"count\":1,\"from\":1}}],\"op_committed\":null,\"op_delivered\":null,\"op_requested\":null,\"presented\":{\"wai-stage:layers\":0},\"stage_hash\":null,\"tier\":\"none\",\"units_by_stage\":[1,1,2],\"vocabulary\":\"urn:wai:staged-delivery:1\"},\"class\":\"stage\",\"issued_at\":\"2026-09-27T12:00:00Z\",\"kind\":\"claim\",\"parent_receipt_hash\":null,\"seq\":0,\"sig\":\"02a772ff1f99616c1e729ff39e822210e291a4cdb5fe24f6abec43eae69ea7802d75fe2d3251e3c4906ecd6a45b3b24b2e85af096f6cef3462b1d8297fcc6c02\",\"signer_id\":\"did:example:sink\",\"signer_pubkey\":\"d759793bbc13a2819a827c76adb6fba8a49aee007f49f2d0992d99b825ad2c48\",\"subject\":\"3844a5152c86c7892dc6c942553da2496c949edd7e32dbbc1a013c4c5d41f54f\",\"subject_type\":\"object\"}" + ] + }, + "expected": { + "outcome": "reject", + "step": 6, + "reason": "session_stage_disagrees" + } + }, + { + "name": "session_stage_unit_not_presented", + "about": "the stage set placed at unit 2, so its last unit is a unit the session never presented", + "procedure": "claim", + "receipt": "{\"body\":{\"classical_declared\":700,\"classical_source\":\"wai2-table\",\"counted_discarded\":1904,\"counted_fallback\":0,\"counted_primary\":5607,\"deadline_us\":40000,\"decoders\":[{\"capability\":\"wai.video.int_hyper\",\"decoder\":\"builtin:wai@0.4.0\",\"leaves\":4,\"module_status\":null,\"path\":\"primary\",\"pin\":\"7b4371854df0aa1645ac6525b373387c0617b873d5a57748932ee0f386ea164b\",\"rendition\":0,\"tier\":\"decode-equivalence\",\"variant\":null},{\"capability\":\"wai.video.av1\",\"decoder\":\"builtin:wai@0.4.0\",\"leaves\":1,\"module_status\":null,\"path\":\"fallback\",\"pin\":null,\"rendition\":null,\"tier\":null,\"variant\":null},{\"capability\":\"wai.video.int_refine\",\"decoder\":\"builtin:wai@0.4.0\",\"leaves\":4,\"module_status\":null,\"path\":\"primary\",\"pin\":null,\"rendition\":null,\"tier\":null,\"variant\":null}],\"energy\":null,\"fallback_units\":1,\"framing\":\"registered\",\"host\":{\"build\":{\"profile\":\"release\",\"target\":\"aarch64-unknown-linux-gnu\",\"toolchain\":\"rustc 1.95.0\"},\"profile\":\"native-ffi\",\"target\":\"aarch64-unknown-linux-gnu\",\"threads\":4},\"leaf_count\":9,\"media\":\"video\",\"missed\":1,\"missed_units\":[{\"late_us\":1200,\"layers\":1,\"unit\":4}],\"output_root\":\"3cb2c68a7fe160511bd3fbbbd6945b5d54fac6b499e33769b1ea6828f04bb312\",\"primary_units\":4,\"receipt_bytes\":640,\"session_nonce\":\"57c5462dfdabd1b7bdd204d34ba33649c057eb535349f29f45eb8f8c7d4a7e7f\",\"stage_sets\":[{\"claim\":\"b636e8894207d2fe59add1e1cacf3b52ea760fccb4dc3f0abce79be90e871640\",\"first_unit\":2}],\"switches\":[{\"from\":\"primary\",\"reason\":\"set-incomplete\",\"to\":\"fallback\",\"unit\":4}],\"switches_total\":1,\"transferred\":13607,\"uncounted\":2,\"units\":5},\"class\":\"reconstruct-session\",\"issued_at\":\"2026-09-27T12:00:00Z\",\"kind\":\"claim\",\"parent_receipt_hash\":null,\"seq\":0,\"sig\":\"8e19d027ceb1f22182f5d0d19024b6aeaf718b9837b75368a3e3b8f6c595297b9dd65e1228d1af281f93b6d10432bbe5ef731275b0ec1cf005e0820ad1ccf901\",\"signer_id\":\"did:example:sink\",\"signer_pubkey\":\"d759793bbc13a2819a827c76adb6fba8a49aee007f49f2d0992d99b825ad2c48\",\"subject\":\"64c0713cb176874607bf8670295242184b7868a9ff7c55554a5ae08de2c301c1\",\"subject_type\":\"object\"}", + "context": { + "outputs": [ + { + "unit": 0, + "layers": 1, + "decoder": 0, + "out_digest": "55f7e628ca707e2ca3159709eeb68b9000813f2916a299acd33a23e6fe012584" + }, + { + "unit": 1, + "layers": 1, + "decoder": 0, + "out_digest": "a3ee8a4b96eceb663f3d94417957d02f897fc166dc96ebe9bf447c4a36a36264" + }, + { + "unit": 2, + "layers": 1, + "decoder": 0, + "out_digest": "00576d2c4d09ef5d7aa807f9b3b1587e200dea6f6694b4da062b41aa2a5ab8af" + }, + { + "unit": 3, + "layers": 1, + "decoder": 0, + "out_digest": "26cd9b2805b604b26e08d9a461db599c4e249bfd4df41a3befb202bc6d0e0700" + }, + { + "unit": 4, + "layers": 1, + "decoder": 1, + "out_digest": "1cd1984bc553c43ee5a48fe7e182a77e60d8ef3c2b0f959ef1a0efd3813b411f" + }, + { + "unit": 0, + "layers": 2, + "decoder": 2, + "out_digest": "cedffc10c0d2e777c954459c198af496e316170b3a8c35276a3f473edf438a0e" + }, + { + "unit": 1, + "layers": 2, + "decoder": 2, + "out_digest": "f0348794b5be95fd5c4e8f268957b6d188c35f76146f4479c960124a4392841d" + }, + { + "unit": 2, + "layers": 2, + "decoder": 2, + "out_digest": "446c9941549464ba1b15c36c6e738380f8918f4a63a47ebbbdd67058a1975a80" + }, + { + "unit": 0, + "layers": 3, + "decoder": 2, + "out_digest": "a80c01cb3ded2f965b69ec4a5b3f1dcb6996e05454d9963e0b05455f9f27bc2f" + } + ], + "stage_claims": [ + "{\"body\":{\"bytes_envelopes\":10607,\"conflicts\":0,\"deadline_misses\":2,\"objects\":[{\"bytes\":900,\"evidence\":\"none\",\"layer\":1,\"object\":\"47a2c23727d2eb9d2beef0931c3e9b2675408d372660420cce427dc27fd21fe1\",\"reason\":null,\"status\":\"applied\",\"units\":{\"count\":1,\"from\":0}},{\"bytes\":901,\"evidence\":\"none\",\"layer\":1,\"object\":\"6b74be11e64461c7d972fc5cb6ba15e98427e9d6e60622b0a753222138de28cf\",\"reason\":null,\"status\":\"applied\",\"units\":{\"count\":1,\"from\":1}},{\"bytes\":902,\"evidence\":\"none\",\"layer\":1,\"object\":\"5e7a38ca5c04442cbe00b040d58e4494f5aa36fb81e8bbe0d304fd2d1ce722b2\",\"reason\":null,\"status\":\"applied\",\"units\":{\"count\":1,\"from\":2}},{\"bytes\":903,\"evidence\":\"none\",\"layer\":1,\"object\":\"792a12990c5207ca83a86b7420815f1f2d34918553a0130a4f9570a11354f2ca\",\"reason\":null,\"status\":\"late\",\"units\":{\"count\":1,\"from\":3}},{\"bytes\":1000,\"evidence\":\"none\",\"layer\":2,\"object\":\"be5055af8e32359265852c512667b10ab6a07455e5ab06603e278763f6633a85\",\"reason\":null,\"status\":\"applied\",\"units\":{\"count\":1,\"from\":0}},{\"bytes\":1001,\"evidence\":\"none\",\"layer\":2,\"object\":\"1c6eae0ed41ed7fc1b2f00b46ea1de98f21a6d6cbf62bf6b22cf76a664a49376\",\"reason\":null,\"status\":\"late\",\"units\":{\"count\":1,\"from\":1}}],\"op_committed\":null,\"op_delivered\":null,\"op_requested\":null,\"presented\":{\"wai-stage:layers\":0},\"stage_hash\":null,\"tier\":\"none\",\"units_by_stage\":[1,2,1],\"vocabulary\":\"urn:wai:staged-delivery:1\"},\"class\":\"stage\",\"issued_at\":\"2026-09-27T12:00:00Z\",\"kind\":\"claim\",\"parent_receipt_hash\":null,\"seq\":0,\"sig\":\"96eb16ba17662e0981fcaf390e1172cefae5c4b2ca5fcf1df3ea10b5176fb0225169a07938ffcb0362d8c35472dab6d39711c331765ebc083bb3b6a55b20da02\",\"signer_id\":\"did:example:sink\",\"signer_pubkey\":\"d759793bbc13a2819a827c76adb6fba8a49aee007f49f2d0992d99b825ad2c48\",\"subject\":\"3844a5152c86c7892dc6c942553da2496c949edd7e32dbbc1a013c4c5d41f54f\",\"subject_type\":\"object\"}" + ] + }, + "expected": { + "outcome": "reject", + "step": 6, + "reason": "session_stage_disagrees" + } + }, + { + "name": "session_context_on_another_class", + "about": "presentations given as the context of a stage claim", + "procedure": "claim", + "receipt": "{\"body\":{\"bytes_envelopes\":10607,\"conflicts\":0,\"deadline_misses\":2,\"objects\":[{\"bytes\":900,\"evidence\":\"none\",\"layer\":1,\"object\":\"47a2c23727d2eb9d2beef0931c3e9b2675408d372660420cce427dc27fd21fe1\",\"reason\":null,\"status\":\"applied\",\"units\":{\"count\":1,\"from\":0}},{\"bytes\":901,\"evidence\":\"none\",\"layer\":1,\"object\":\"6b74be11e64461c7d972fc5cb6ba15e98427e9d6e60622b0a753222138de28cf\",\"reason\":null,\"status\":\"applied\",\"units\":{\"count\":1,\"from\":1}},{\"bytes\":902,\"evidence\":\"none\",\"layer\":1,\"object\":\"5e7a38ca5c04442cbe00b040d58e4494f5aa36fb81e8bbe0d304fd2d1ce722b2\",\"reason\":null,\"status\":\"applied\",\"units\":{\"count\":1,\"from\":2}},{\"bytes\":903,\"evidence\":\"none\",\"layer\":1,\"object\":\"792a12990c5207ca83a86b7420815f1f2d34918553a0130a4f9570a11354f2ca\",\"reason\":null,\"status\":\"late\",\"units\":{\"count\":1,\"from\":3}},{\"bytes\":1000,\"evidence\":\"none\",\"layer\":2,\"object\":\"be5055af8e32359265852c512667b10ab6a07455e5ab06603e278763f6633a85\",\"reason\":null,\"status\":\"applied\",\"units\":{\"count\":1,\"from\":0}},{\"bytes\":1001,\"evidence\":\"none\",\"layer\":2,\"object\":\"1c6eae0ed41ed7fc1b2f00b46ea1de98f21a6d6cbf62bf6b22cf76a664a49376\",\"reason\":null,\"status\":\"late\",\"units\":{\"count\":1,\"from\":1}}],\"op_committed\":null,\"op_delivered\":null,\"op_requested\":null,\"presented\":{\"wai-stage:layers\":0},\"stage_hash\":null,\"tier\":\"none\",\"units_by_stage\":[1,2,1],\"vocabulary\":\"urn:wai:staged-delivery:1\"},\"class\":\"stage\",\"issued_at\":\"2026-09-27T12:00:00Z\",\"kind\":\"claim\",\"parent_receipt_hash\":null,\"seq\":0,\"sig\":\"96eb16ba17662e0981fcaf390e1172cefae5c4b2ca5fcf1df3ea10b5176fb0225169a07938ffcb0362d8c35472dab6d39711c331765ebc083bb3b6a55b20da02\",\"signer_id\":\"did:example:sink\",\"signer_pubkey\":\"d759793bbc13a2819a827c76adb6fba8a49aee007f49f2d0992d99b825ad2c48\",\"subject\":\"3844a5152c86c7892dc6c942553da2496c949edd7e32dbbc1a013c4c5d41f54f\",\"subject_type\":\"object\"}", + "context": { + "outputs": [ + { + "unit": 0, + "layers": 1, + "decoder": 0, + "out_digest": "55f7e628ca707e2ca3159709eeb68b9000813f2916a299acd33a23e6fe012584" + }, + { + "unit": 1, + "layers": 1, + "decoder": 0, + "out_digest": "a3ee8a4b96eceb663f3d94417957d02f897fc166dc96ebe9bf447c4a36a36264" + }, + { + "unit": 2, + "layers": 1, + "decoder": 0, + "out_digest": "00576d2c4d09ef5d7aa807f9b3b1587e200dea6f6694b4da062b41aa2a5ab8af" + }, + { + "unit": 3, + "layers": 1, + "decoder": 0, + "out_digest": "26cd9b2805b604b26e08d9a461db599c4e249bfd4df41a3befb202bc6d0e0700" + }, + { + "unit": 4, + "layers": 1, + "decoder": 1, + "out_digest": "1cd1984bc553c43ee5a48fe7e182a77e60d8ef3c2b0f959ef1a0efd3813b411f" + }, + { + "unit": 0, + "layers": 2, + "decoder": 2, + "out_digest": "cedffc10c0d2e777c954459c198af496e316170b3a8c35276a3f473edf438a0e" + }, + { + "unit": 1, + "layers": 2, + "decoder": 2, + "out_digest": "f0348794b5be95fd5c4e8f268957b6d188c35f76146f4479c960124a4392841d" + }, + { + "unit": 2, + "layers": 2, + "decoder": 2, + "out_digest": "446c9941549464ba1b15c36c6e738380f8918f4a63a47ebbbdd67058a1975a80" + }, + { + "unit": 0, + "layers": 3, + "decoder": 2, + "out_digest": "a80c01cb3ded2f965b69ec4a5b3f1dcb6996e05454d9963e0b05455f9f27bc2f" + } + ] + }, + "expected": { + "outcome": "reject", + "step": 6, + "reason": "context_mismatch" + } + }, + { + "name": "session_figure_report_accept", + "about": "a measurement claim on a metered session's figure, by the session's key", + "procedure": "claim", + "receipt": "{\"body\":{\"bracket\":null,\"build\":{\"profile\":\"release\",\"target\":null,\"toolchain\":null},\"energy_calibration_ref\":null,\"energy_counter_filtering\":\"Unknown\",\"energy_provenance\":\"OnChipCounter\",\"energy_uncertainty\":{\"relative_ppm\":20000,\"window_us\":1000000},\"figure_index\":null,\"figure_profile\":\"moq-jwp:claim-link\",\"group\":null,\"joules_micro\":250000,\"power_reader\":\"a counter reader\"},\"class\":\"measurement\",\"issued_at\":\"2026-09-27T12:00:00Z\",\"kind\":\"claim\",\"parent_receipt_hash\":null,\"seq\":1,\"sig\":\"0d9432b07525d9805a468cde0e1cabc7b8c478e6d3854b090c9704115bc9abc84c066e438ef9e5654cba5040904ecaf18b429a0996aec00a6c12eee4f3c67e03\",\"signer_id\":\"did:example:sink\",\"signer_pubkey\":\"d759793bbc13a2819a827c76adb6fba8a49aee007f49f2d0992d99b825ad2c48\",\"subject\":\"93d7ea35e77a906d4a1a7933fbe81145d1d4be3e0144a8cb2087e7950d07db06\",\"subject_type\":\"receipt\"}", + "context": { + "figure": { + "claim": "{\"body\":{\"classical_declared\":700,\"classical_source\":\"wai2-table\",\"counted_discarded\":1904,\"counted_fallback\":0,\"counted_primary\":5607,\"deadline_us\":40000,\"decoders\":[{\"capability\":\"wai.video.int_hyper\",\"decoder\":\"builtin:wai@0.4.0\",\"leaves\":4,\"module_status\":null,\"path\":\"primary\",\"pin\":\"7b4371854df0aa1645ac6525b373387c0617b873d5a57748932ee0f386ea164b\",\"rendition\":0,\"tier\":\"decode-equivalence\",\"variant\":null},{\"capability\":\"wai.video.av1\",\"decoder\":\"builtin:wai@0.4.0\",\"leaves\":1,\"module_status\":null,\"path\":\"fallback\",\"pin\":null,\"rendition\":null,\"tier\":null,\"variant\":null},{\"capability\":\"wai.video.int_refine\",\"decoder\":\"builtin:wai@0.4.0\",\"leaves\":4,\"module_status\":null,\"path\":\"primary\",\"pin\":null,\"rendition\":null,\"tier\":null,\"variant\":null}],\"energy\":{\"energy_calibration_ref\":null,\"energy_counter_filtering\":\"Unknown\",\"energy_provenance\":\"OnChipCounter\",\"energy_uncertainty\":{\"relative_ppm\":20000,\"window_us\":1000000},\"joules_micro\":250000},\"fallback_units\":1,\"framing\":\"registered\",\"host\":{\"build\":{\"profile\":\"release\",\"target\":\"aarch64-unknown-linux-gnu\",\"toolchain\":\"rustc 1.95.0\"},\"profile\":\"native-ffi\",\"target\":\"aarch64-unknown-linux-gnu\",\"threads\":4},\"leaf_count\":9,\"media\":\"video\",\"missed\":1,\"missed_units\":[{\"late_us\":1200,\"layers\":1,\"unit\":4}],\"output_root\":\"3cb2c68a7fe160511bd3fbbbd6945b5d54fac6b499e33769b1ea6828f04bb312\",\"primary_units\":4,\"receipt_bytes\":640,\"session_nonce\":\"57c5462dfdabd1b7bdd204d34ba33649c057eb535349f29f45eb8f8c7d4a7e7f\",\"stage_sets\":[{\"claim\":\"b636e8894207d2fe59add1e1cacf3b52ea760fccb4dc3f0abce79be90e871640\",\"first_unit\":0}],\"switches\":[{\"from\":\"primary\",\"reason\":\"set-incomplete\",\"to\":\"fallback\",\"unit\":4}],\"switches_total\":1,\"transferred\":13607,\"uncounted\":2,\"units\":5},\"class\":\"reconstruct-session\",\"issued_at\":\"2026-09-27T12:00:00Z\",\"kind\":\"claim\",\"parent_receipt_hash\":null,\"seq\":0,\"sig\":\"756af8a7612a6238db2bbbc819d72b5fe002e981b618197e1661af71956e72023973f13c2a57cee989ae30edfc828285a63d8b79af4c486a5eab3c2de9e6760f\",\"signer_id\":\"did:example:sink\",\"signer_pubkey\":\"d759793bbc13a2819a827c76adb6fba8a49aee007f49f2d0992d99b825ad2c48\",\"subject\":\"64c0713cb176874607bf8670295242184b7868a9ff7c55554a5ae08de2c301c1\",\"subject_type\":\"object\"}" + } + }, + "expected": { + "outcome": "accept", + "link_hash": "d9c362bf2b568e30a23d1584b67ddacb3878014d10818cb04424da92dd9677e7" + } + }, + { + "name": "session_figure_report_unmetered", + "about": "a measurement claim on an unmetered session, which carries no figure", + "procedure": "claim", + "receipt": "{\"body\":{\"bracket\":null,\"build\":{\"profile\":\"release\",\"target\":null,\"toolchain\":null},\"energy_calibration_ref\":null,\"energy_counter_filtering\":\"Unknown\",\"energy_provenance\":\"OnChipCounter\",\"energy_uncertainty\":{\"relative_ppm\":20000,\"window_us\":1000000},\"figure_index\":null,\"figure_profile\":\"moq-jwp:claim-link\",\"group\":null,\"joules_micro\":250000,\"power_reader\":\"a counter reader\"},\"class\":\"measurement\",\"issued_at\":\"2026-09-27T12:00:00Z\",\"kind\":\"claim\",\"parent_receipt_hash\":null,\"seq\":1,\"sig\":\"6712ccdbc1b537be9a563db6c0f1ac409d36aa240683675acad17b074a96fe603f76c58af8cacf4db71098d947ec1b0cba6ff623ffd460c5b3b1fb5c7d5a100b\",\"signer_id\":\"did:example:sink\",\"signer_pubkey\":\"d759793bbc13a2819a827c76adb6fba8a49aee007f49f2d0992d99b825ad2c48\",\"subject\":\"cc336d348fd5b500a1a37f5e6a2f6c72ab4cfe83b76cc508ed4f0aae6eeeb741\",\"subject_type\":\"receipt\"}", + "context": { + "figure": { + "claim": "{\"body\":{\"classical_declared\":700,\"classical_source\":\"wai2-table\",\"counted_discarded\":1904,\"counted_fallback\":0,\"counted_primary\":5607,\"deadline_us\":40000,\"decoders\":[{\"capability\":\"wai.video.int_hyper\",\"decoder\":\"builtin:wai@0.4.0\",\"leaves\":4,\"module_status\":null,\"path\":\"primary\",\"pin\":\"7b4371854df0aa1645ac6525b373387c0617b873d5a57748932ee0f386ea164b\",\"rendition\":0,\"tier\":\"decode-equivalence\",\"variant\":null},{\"capability\":\"wai.video.av1\",\"decoder\":\"builtin:wai@0.4.0\",\"leaves\":1,\"module_status\":null,\"path\":\"fallback\",\"pin\":null,\"rendition\":null,\"tier\":null,\"variant\":null},{\"capability\":\"wai.video.int_refine\",\"decoder\":\"builtin:wai@0.4.0\",\"leaves\":4,\"module_status\":null,\"path\":\"primary\",\"pin\":null,\"rendition\":null,\"tier\":null,\"variant\":null}],\"energy\":null,\"fallback_units\":1,\"framing\":\"registered\",\"host\":{\"build\":{\"profile\":\"release\",\"target\":\"aarch64-unknown-linux-gnu\",\"toolchain\":\"rustc 1.95.0\"},\"profile\":\"native-ffi\",\"target\":\"aarch64-unknown-linux-gnu\",\"threads\":4},\"leaf_count\":9,\"media\":\"video\",\"missed\":1,\"missed_units\":[{\"late_us\":1200,\"layers\":1,\"unit\":4}],\"output_root\":\"3cb2c68a7fe160511bd3fbbbd6945b5d54fac6b499e33769b1ea6828f04bb312\",\"primary_units\":4,\"receipt_bytes\":640,\"session_nonce\":\"57c5462dfdabd1b7bdd204d34ba33649c057eb535349f29f45eb8f8c7d4a7e7f\",\"stage_sets\":[{\"claim\":\"b636e8894207d2fe59add1e1cacf3b52ea760fccb4dc3f0abce79be90e871640\",\"first_unit\":0}],\"switches\":[{\"from\":\"primary\",\"reason\":\"set-incomplete\",\"to\":\"fallback\",\"unit\":4}],\"switches_total\":1,\"transferred\":13607,\"uncounted\":2,\"units\":5},\"class\":\"reconstruct-session\",\"issued_at\":\"2026-09-27T12:00:00Z\",\"kind\":\"claim\",\"parent_receipt_hash\":null,\"seq\":0,\"sig\":\"2871039f189db43685c214c860ac86567712af1e35d3254c371e7faaf8582734b5216c7ba4015383ad9013aac4c34ba1aebf410a56615d5bf2f5d73622c1410e\",\"signer_id\":\"did:example:sink\",\"signer_pubkey\":\"d759793bbc13a2819a827c76adb6fba8a49aee007f49f2d0992d99b825ad2c48\",\"subject\":\"64c0713cb176874607bf8670295242184b7868a9ff7c55554a5ae08de2c301c1\",\"subject_type\":\"object\"}" + } + }, + "expected": { + "outcome": "reject", + "step": 6, + "reason": "context_mismatch" + } + }, + { + "name": "session_tree_01", + "about": "an output tree of 1 leaves, half on a byte-exact decoder whose re-decode matches and half checked for membership only, whose re-decode does not and is not checked", + "procedure": "claim", + "receipt": "{\"body\":{\"classical_declared\":700,\"classical_source\":\"wai2-table\",\"counted_discarded\":1904,\"counted_fallback\":0,\"counted_primary\":5607,\"deadline_us\":null,\"decoders\":[{\"capability\":\"wai.video.int_hyper\",\"decoder\":\"builtin:wai@0.4.0\",\"leaves\":1,\"module_status\":null,\"path\":\"primary\",\"pin\":\"7b4371854df0aa1645ac6525b373387c0617b873d5a57748932ee0f386ea164b\",\"rendition\":0,\"tier\":\"decode-equivalence\",\"variant\":null}],\"energy\":null,\"fallback_units\":0,\"framing\":\"registered\",\"host\":{\"build\":{\"profile\":\"release\",\"target\":\"aarch64-unknown-linux-gnu\",\"toolchain\":\"rustc 1.95.0\"},\"profile\":\"native-ffi\",\"target\":\"aarch64-unknown-linux-gnu\",\"threads\":4},\"leaf_count\":1,\"media\":\"video\",\"missed\":0,\"missed_units\":[],\"output_root\":\"9bbb2c453e90eab8c5e9ca19a9b9f355103fa5d112ba9b50f23f277b3849e7e7\",\"primary_units\":1,\"receipt_bytes\":640,\"session_nonce\":\"57c5462dfdabd1b7bdd204d34ba33649c057eb535349f29f45eb8f8c7d4a7e7f\",\"stage_sets\":[],\"switches\":[],\"switches_total\":0,\"transferred\":13607,\"uncounted\":2,\"units\":1},\"class\":\"reconstruct-session\",\"issued_at\":\"2026-09-27T12:00:00Z\",\"kind\":\"claim\",\"parent_receipt_hash\":null,\"seq\":0,\"sig\":\"b51115d5435a94b9d7d3d881bee5d24dd93a424693e20f95927f6bec1c55b0fc4904d9d1a3f8eca960fb80908af482086fba39e4cc17641f852e0058ea501e0c\",\"signer_id\":\"did:example:sink\",\"signer_pubkey\":\"d759793bbc13a2819a827c76adb6fba8a49aee007f49f2d0992d99b825ad2c48\",\"subject\":\"64c0713cb176874607bf8670295242184b7868a9ff7c55554a5ae08de2c301c1\",\"subject_type\":\"object\"}", + "context": { + "outputs": [ + { + "unit": 0, + "layers": 1, + "decoder": 0, + "out_digest": "55f7e628ca707e2ca3159709eeb68b9000813f2916a299acd33a23e6fe012584" + } + ], + "redecoded": [ + { + "index": 0, + "out_digest": "55f7e628ca707e2ca3159709eeb68b9000813f2916a299acd33a23e6fe012584" + } + ] + }, + "expected": { + "outcome": "accept", + "link_hash": "10233cc60a08d77aa2d788560acb6f9ae3ef0fc0b9b73464962c6026913539a7" + } + }, + { + "name": "session_tree_02", + "about": "an output tree of 2 leaves, half on a byte-exact decoder whose re-decode matches and half checked for membership only, whose re-decode does not and is not checked", + "procedure": "claim", + "receipt": "{\"body\":{\"classical_declared\":700,\"classical_source\":\"wai2-table\",\"counted_discarded\":1904,\"counted_fallback\":0,\"counted_primary\":5607,\"deadline_us\":null,\"decoders\":[{\"capability\":\"wai.video.int_hyper\",\"decoder\":\"builtin:wai@0.4.0\",\"leaves\":1,\"module_status\":null,\"path\":\"primary\",\"pin\":\"7b4371854df0aa1645ac6525b373387c0617b873d5a57748932ee0f386ea164b\",\"rendition\":0,\"tier\":\"decode-equivalence\",\"variant\":null},{\"capability\":\"wai.video.av1\",\"decoder\":\"builtin:wai@0.4.0\",\"leaves\":1,\"module_status\":null,\"path\":\"fallback\",\"pin\":null,\"rendition\":null,\"tier\":null,\"variant\":null}],\"energy\":null,\"fallback_units\":1,\"framing\":\"registered\",\"host\":{\"build\":{\"profile\":\"release\",\"target\":\"aarch64-unknown-linux-gnu\",\"toolchain\":\"rustc 1.95.0\"},\"profile\":\"native-ffi\",\"target\":\"aarch64-unknown-linux-gnu\",\"threads\":4},\"leaf_count\":2,\"media\":\"video\",\"missed\":0,\"missed_units\":[],\"output_root\":\"edede5b8e2369aa378253e97eea8a58f22a5842c32b39e6ce6737f3a7fdc95e4\",\"primary_units\":1,\"receipt_bytes\":640,\"session_nonce\":\"57c5462dfdabd1b7bdd204d34ba33649c057eb535349f29f45eb8f8c7d4a7e7f\",\"stage_sets\":[],\"switches\":[],\"switches_total\":0,\"transferred\":13607,\"uncounted\":2,\"units\":2},\"class\":\"reconstruct-session\",\"issued_at\":\"2026-09-27T12:00:00Z\",\"kind\":\"claim\",\"parent_receipt_hash\":null,\"seq\":0,\"sig\":\"9ef03188562da2d80c1899ddd9d4256294504fe6c1d60698e14da09804ba7503d61cda4c0a2cab07c8d76928fe2bcf55f80507856010442de69d33490d96b408\",\"signer_id\":\"did:example:sink\",\"signer_pubkey\":\"d759793bbc13a2819a827c76adb6fba8a49aee007f49f2d0992d99b825ad2c48\",\"subject\":\"64c0713cb176874607bf8670295242184b7868a9ff7c55554a5ae08de2c301c1\",\"subject_type\":\"object\"}", + "context": { + "outputs": [ + { + "unit": 0, + "layers": 1, + "decoder": 0, + "out_digest": "55f7e628ca707e2ca3159709eeb68b9000813f2916a299acd33a23e6fe012584" + }, + { + "unit": 1, + "layers": 1, + "decoder": 1, + "out_digest": "a3ee8a4b96eceb663f3d94417957d02f897fc166dc96ebe9bf447c4a36a36264" + } + ], + "redecoded": [ + { + "index": 0, + "out_digest": "55f7e628ca707e2ca3159709eeb68b9000813f2916a299acd33a23e6fe012584" + }, + { + "index": 1, + "out_digest": "9df7f2652febf9fe462ff426af1ee3ec158bf203c59392654482b80775804556" + } + ] + }, + "expected": { + "outcome": "accept", + "link_hash": "d6fbe017a519c77e835a20ebe0f32d399599a41481b0604f7c7bc082098d3a37" + } + }, + { + "name": "session_tree_03", + "about": "an output tree of 3 leaves, half on a byte-exact decoder whose re-decode matches and half checked for membership only, whose re-decode does not and is not checked", + "procedure": "claim", + "receipt": "{\"body\":{\"classical_declared\":700,\"classical_source\":\"wai2-table\",\"counted_discarded\":1904,\"counted_fallback\":0,\"counted_primary\":5607,\"deadline_us\":null,\"decoders\":[{\"capability\":\"wai.video.int_hyper\",\"decoder\":\"builtin:wai@0.4.0\",\"leaves\":2,\"module_status\":null,\"path\":\"primary\",\"pin\":\"7b4371854df0aa1645ac6525b373387c0617b873d5a57748932ee0f386ea164b\",\"rendition\":0,\"tier\":\"decode-equivalence\",\"variant\":null},{\"capability\":\"wai.video.av1\",\"decoder\":\"builtin:wai@0.4.0\",\"leaves\":1,\"module_status\":null,\"path\":\"fallback\",\"pin\":null,\"rendition\":null,\"tier\":null,\"variant\":null}],\"energy\":null,\"fallback_units\":1,\"framing\":\"registered\",\"host\":{\"build\":{\"profile\":\"release\",\"target\":\"aarch64-unknown-linux-gnu\",\"toolchain\":\"rustc 1.95.0\"},\"profile\":\"native-ffi\",\"target\":\"aarch64-unknown-linux-gnu\",\"threads\":4},\"leaf_count\":3,\"media\":\"video\",\"missed\":0,\"missed_units\":[],\"output_root\":\"36d9bc31e2f1709e278a45d7d91b4a25a6a8535ac30e4316090b89694d118d9b\",\"primary_units\":2,\"receipt_bytes\":640,\"session_nonce\":\"57c5462dfdabd1b7bdd204d34ba33649c057eb535349f29f45eb8f8c7d4a7e7f\",\"stage_sets\":[],\"switches\":[],\"switches_total\":0,\"transferred\":13607,\"uncounted\":2,\"units\":3},\"class\":\"reconstruct-session\",\"issued_at\":\"2026-09-27T12:00:00Z\",\"kind\":\"claim\",\"parent_receipt_hash\":null,\"seq\":0,\"sig\":\"c213d6e8b6574d2a0788882653bb5a8c63545b07c59c8f15a6ee34a2f5f98d7cce7f9b1545f6ca3e2f50a1d6e8a6d66051bd457b7f9d93ca435323051580bc02\",\"signer_id\":\"did:example:sink\",\"signer_pubkey\":\"d759793bbc13a2819a827c76adb6fba8a49aee007f49f2d0992d99b825ad2c48\",\"subject\":\"64c0713cb176874607bf8670295242184b7868a9ff7c55554a5ae08de2c301c1\",\"subject_type\":\"object\"}", + "context": { + "outputs": [ + { + "unit": 0, + "layers": 1, + "decoder": 0, + "out_digest": "55f7e628ca707e2ca3159709eeb68b9000813f2916a299acd33a23e6fe012584" + }, + { + "unit": 1, + "layers": 1, + "decoder": 1, + "out_digest": "a3ee8a4b96eceb663f3d94417957d02f897fc166dc96ebe9bf447c4a36a36264" + }, + { + "unit": 2, + "layers": 1, + "decoder": 0, + "out_digest": "00576d2c4d09ef5d7aa807f9b3b1587e200dea6f6694b4da062b41aa2a5ab8af" + } + ], + "redecoded": [ + { + "index": 0, + "out_digest": "55f7e628ca707e2ca3159709eeb68b9000813f2916a299acd33a23e6fe012584" + }, + { + "index": 1, + "out_digest": "9df7f2652febf9fe462ff426af1ee3ec158bf203c59392654482b80775804556" + }, + { + "index": 2, + "out_digest": "00576d2c4d09ef5d7aa807f9b3b1587e200dea6f6694b4da062b41aa2a5ab8af" + } + ] + }, + "expected": { + "outcome": "accept", + "link_hash": "619d13f0485de1a205f1ec3f74b436f7fd281ffa629d64c8a7db5b596cd191b9" + } + }, + { + "name": "session_tree_04", + "about": "an output tree of 4 leaves, half on a byte-exact decoder whose re-decode matches and half checked for membership only, whose re-decode does not and is not checked", + "procedure": "claim", + "receipt": "{\"body\":{\"classical_declared\":700,\"classical_source\":\"wai2-table\",\"counted_discarded\":1904,\"counted_fallback\":0,\"counted_primary\":5607,\"deadline_us\":null,\"decoders\":[{\"capability\":\"wai.video.int_hyper\",\"decoder\":\"builtin:wai@0.4.0\",\"leaves\":2,\"module_status\":null,\"path\":\"primary\",\"pin\":\"7b4371854df0aa1645ac6525b373387c0617b873d5a57748932ee0f386ea164b\",\"rendition\":0,\"tier\":\"decode-equivalence\",\"variant\":null},{\"capability\":\"wai.video.av1\",\"decoder\":\"builtin:wai@0.4.0\",\"leaves\":2,\"module_status\":null,\"path\":\"fallback\",\"pin\":null,\"rendition\":null,\"tier\":null,\"variant\":null}],\"energy\":null,\"fallback_units\":2,\"framing\":\"registered\",\"host\":{\"build\":{\"profile\":\"release\",\"target\":\"aarch64-unknown-linux-gnu\",\"toolchain\":\"rustc 1.95.0\"},\"profile\":\"native-ffi\",\"target\":\"aarch64-unknown-linux-gnu\",\"threads\":4},\"leaf_count\":4,\"media\":\"video\",\"missed\":0,\"missed_units\":[],\"output_root\":\"e1e21838f409b14b26055e52eee94f6e34a771c1de2094fd669fa85b0999a08d\",\"primary_units\":2,\"receipt_bytes\":640,\"session_nonce\":\"57c5462dfdabd1b7bdd204d34ba33649c057eb535349f29f45eb8f8c7d4a7e7f\",\"stage_sets\":[],\"switches\":[],\"switches_total\":0,\"transferred\":13607,\"uncounted\":2,\"units\":4},\"class\":\"reconstruct-session\",\"issued_at\":\"2026-09-27T12:00:00Z\",\"kind\":\"claim\",\"parent_receipt_hash\":null,\"seq\":0,\"sig\":\"a2b5fdf714dc70f99bb233e44bbf16fb942ba2267004aebd1b40f16c73044860be34e9239d8c19e2201faf3b60b53eeb6d3d64953a8fdbc30ed9272db10da403\",\"signer_id\":\"did:example:sink\",\"signer_pubkey\":\"d759793bbc13a2819a827c76adb6fba8a49aee007f49f2d0992d99b825ad2c48\",\"subject\":\"64c0713cb176874607bf8670295242184b7868a9ff7c55554a5ae08de2c301c1\",\"subject_type\":\"object\"}", + "context": { + "outputs": [ + { + "unit": 0, + "layers": 1, + "decoder": 0, + "out_digest": "55f7e628ca707e2ca3159709eeb68b9000813f2916a299acd33a23e6fe012584" + }, + { + "unit": 1, + "layers": 1, + "decoder": 1, + "out_digest": "a3ee8a4b96eceb663f3d94417957d02f897fc166dc96ebe9bf447c4a36a36264" + }, + { + "unit": 2, + "layers": 1, + "decoder": 0, + "out_digest": "00576d2c4d09ef5d7aa807f9b3b1587e200dea6f6694b4da062b41aa2a5ab8af" + }, + { + "unit": 3, + "layers": 1, + "decoder": 1, + "out_digest": "26cd9b2805b604b26e08d9a461db599c4e249bfd4df41a3befb202bc6d0e0700" + } + ], + "redecoded": [ + { + "index": 0, + "out_digest": "55f7e628ca707e2ca3159709eeb68b9000813f2916a299acd33a23e6fe012584" + }, + { + "index": 1, + "out_digest": "9df7f2652febf9fe462ff426af1ee3ec158bf203c59392654482b80775804556" + }, + { + "index": 2, + "out_digest": "00576d2c4d09ef5d7aa807f9b3b1587e200dea6f6694b4da062b41aa2a5ab8af" + }, + { + "index": 3, + "out_digest": "5541d29e4f230e7683ad45c081f4f325fa6216f308b1682f621b3ed279fc39f8" + } + ] + }, + "expected": { + "outcome": "accept", + "link_hash": "a2e62a1db3cf6f91203c9662b7b76e054277c09173375d1a55c8816942efe1b2" + } + }, + { + "name": "session_tree_05", + "about": "an output tree of 5 leaves, half on a byte-exact decoder whose re-decode matches and half checked for membership only, whose re-decode does not and is not checked", + "procedure": "claim", + "receipt": "{\"body\":{\"classical_declared\":700,\"classical_source\":\"wai2-table\",\"counted_discarded\":1904,\"counted_fallback\":0,\"counted_primary\":5607,\"deadline_us\":null,\"decoders\":[{\"capability\":\"wai.video.int_hyper\",\"decoder\":\"builtin:wai@0.4.0\",\"leaves\":3,\"module_status\":null,\"path\":\"primary\",\"pin\":\"7b4371854df0aa1645ac6525b373387c0617b873d5a57748932ee0f386ea164b\",\"rendition\":0,\"tier\":\"decode-equivalence\",\"variant\":null},{\"capability\":\"wai.video.av1\",\"decoder\":\"builtin:wai@0.4.0\",\"leaves\":2,\"module_status\":null,\"path\":\"fallback\",\"pin\":null,\"rendition\":null,\"tier\":null,\"variant\":null}],\"energy\":null,\"fallback_units\":2,\"framing\":\"registered\",\"host\":{\"build\":{\"profile\":\"release\",\"target\":\"aarch64-unknown-linux-gnu\",\"toolchain\":\"rustc 1.95.0\"},\"profile\":\"native-ffi\",\"target\":\"aarch64-unknown-linux-gnu\",\"threads\":4},\"leaf_count\":5,\"media\":\"video\",\"missed\":0,\"missed_units\":[],\"output_root\":\"af31725e4b35075a8dbc2fad6026446f710ab15f6d93d6a9a9743ade4ce6675c\",\"primary_units\":3,\"receipt_bytes\":640,\"session_nonce\":\"57c5462dfdabd1b7bdd204d34ba33649c057eb535349f29f45eb8f8c7d4a7e7f\",\"stage_sets\":[],\"switches\":[],\"switches_total\":0,\"transferred\":13607,\"uncounted\":2,\"units\":5},\"class\":\"reconstruct-session\",\"issued_at\":\"2026-09-27T12:00:00Z\",\"kind\":\"claim\",\"parent_receipt_hash\":null,\"seq\":0,\"sig\":\"0f4d7e28d9ad4177017eb191271a7ccb76327fc527e189fcdf4c0c24ba098208185e76688f013ea0d413ea0c28838e9923569da3ef4db142e2323ba1ef36f00b\",\"signer_id\":\"did:example:sink\",\"signer_pubkey\":\"d759793bbc13a2819a827c76adb6fba8a49aee007f49f2d0992d99b825ad2c48\",\"subject\":\"64c0713cb176874607bf8670295242184b7868a9ff7c55554a5ae08de2c301c1\",\"subject_type\":\"object\"}", + "context": { + "outputs": [ + { + "unit": 0, + "layers": 1, + "decoder": 0, + "out_digest": "55f7e628ca707e2ca3159709eeb68b9000813f2916a299acd33a23e6fe012584" + }, + { + "unit": 1, + "layers": 1, + "decoder": 1, + "out_digest": "a3ee8a4b96eceb663f3d94417957d02f897fc166dc96ebe9bf447c4a36a36264" + }, + { + "unit": 2, + "layers": 1, + "decoder": 0, + "out_digest": "00576d2c4d09ef5d7aa807f9b3b1587e200dea6f6694b4da062b41aa2a5ab8af" + }, + { + "unit": 3, + "layers": 1, + "decoder": 1, + "out_digest": "26cd9b2805b604b26e08d9a461db599c4e249bfd4df41a3befb202bc6d0e0700" + }, + { + "unit": 4, + "layers": 1, + "decoder": 0, + "out_digest": "1cd1984bc553c43ee5a48fe7e182a77e60d8ef3c2b0f959ef1a0efd3813b411f" + } + ], + "redecoded": [ + { + "index": 0, + "out_digest": "55f7e628ca707e2ca3159709eeb68b9000813f2916a299acd33a23e6fe012584" + }, + { + "index": 1, + "out_digest": "9df7f2652febf9fe462ff426af1ee3ec158bf203c59392654482b80775804556" + }, + { + "index": 2, + "out_digest": "00576d2c4d09ef5d7aa807f9b3b1587e200dea6f6694b4da062b41aa2a5ab8af" + }, + { + "index": 3, + "out_digest": "5541d29e4f230e7683ad45c081f4f325fa6216f308b1682f621b3ed279fc39f8" + }, + { + "index": 4, + "out_digest": "1cd1984bc553c43ee5a48fe7e182a77e60d8ef3c2b0f959ef1a0efd3813b411f" + } + ] + }, + "expected": { + "outcome": "accept", + "link_hash": "79b403dd5d1540b004cd6de5bb1b7f69c245fa4dd65fd957c2ce0be478025c17" + } + }, + { + "name": "session_tree_06", + "about": "an output tree of 6 leaves, half on a byte-exact decoder whose re-decode matches and half checked for membership only, whose re-decode does not and is not checked", + "procedure": "claim", + "receipt": "{\"body\":{\"classical_declared\":700,\"classical_source\":\"wai2-table\",\"counted_discarded\":1904,\"counted_fallback\":0,\"counted_primary\":5607,\"deadline_us\":null,\"decoders\":[{\"capability\":\"wai.video.int_hyper\",\"decoder\":\"builtin:wai@0.4.0\",\"leaves\":3,\"module_status\":null,\"path\":\"primary\",\"pin\":\"7b4371854df0aa1645ac6525b373387c0617b873d5a57748932ee0f386ea164b\",\"rendition\":0,\"tier\":\"decode-equivalence\",\"variant\":null},{\"capability\":\"wai.video.av1\",\"decoder\":\"builtin:wai@0.4.0\",\"leaves\":3,\"module_status\":null,\"path\":\"fallback\",\"pin\":null,\"rendition\":null,\"tier\":null,\"variant\":null}],\"energy\":null,\"fallback_units\":3,\"framing\":\"registered\",\"host\":{\"build\":{\"profile\":\"release\",\"target\":\"aarch64-unknown-linux-gnu\",\"toolchain\":\"rustc 1.95.0\"},\"profile\":\"native-ffi\",\"target\":\"aarch64-unknown-linux-gnu\",\"threads\":4},\"leaf_count\":6,\"media\":\"video\",\"missed\":0,\"missed_units\":[],\"output_root\":\"e80808b9eab897bf811a82da19e20154bd3e7bdb49d912b639bc4a2d3abb2be4\",\"primary_units\":3,\"receipt_bytes\":640,\"session_nonce\":\"57c5462dfdabd1b7bdd204d34ba33649c057eb535349f29f45eb8f8c7d4a7e7f\",\"stage_sets\":[],\"switches\":[],\"switches_total\":0,\"transferred\":13607,\"uncounted\":2,\"units\":6},\"class\":\"reconstruct-session\",\"issued_at\":\"2026-09-27T12:00:00Z\",\"kind\":\"claim\",\"parent_receipt_hash\":null,\"seq\":0,\"sig\":\"1175e1c485d566aee252db48e099632ae405a53f9fc0f3523bd131f452324191d393d8cc283fa64f21f7a5276e5b588896a03765b367f4c2a1723922516d540d\",\"signer_id\":\"did:example:sink\",\"signer_pubkey\":\"d759793bbc13a2819a827c76adb6fba8a49aee007f49f2d0992d99b825ad2c48\",\"subject\":\"64c0713cb176874607bf8670295242184b7868a9ff7c55554a5ae08de2c301c1\",\"subject_type\":\"object\"}", + "context": { + "outputs": [ + { + "unit": 0, + "layers": 1, + "decoder": 0, + "out_digest": "55f7e628ca707e2ca3159709eeb68b9000813f2916a299acd33a23e6fe012584" + }, + { + "unit": 1, + "layers": 1, + "decoder": 1, + "out_digest": "a3ee8a4b96eceb663f3d94417957d02f897fc166dc96ebe9bf447c4a36a36264" + }, + { + "unit": 2, + "layers": 1, + "decoder": 0, + "out_digest": "00576d2c4d09ef5d7aa807f9b3b1587e200dea6f6694b4da062b41aa2a5ab8af" + }, + { + "unit": 3, + "layers": 1, + "decoder": 1, + "out_digest": "26cd9b2805b604b26e08d9a461db599c4e249bfd4df41a3befb202bc6d0e0700" + }, + { + "unit": 4, + "layers": 1, + "decoder": 0, + "out_digest": "1cd1984bc553c43ee5a48fe7e182a77e60d8ef3c2b0f959ef1a0efd3813b411f" + }, + { + "unit": 5, + "layers": 1, + "decoder": 1, + "out_digest": "e4c4344155dc2c789a1df265f8064b9ae56f3e0932d85c5ceb38782c135749fc" + } + ], + "redecoded": [ + { + "index": 0, + "out_digest": "55f7e628ca707e2ca3159709eeb68b9000813f2916a299acd33a23e6fe012584" + }, + { + "index": 1, + "out_digest": "9df7f2652febf9fe462ff426af1ee3ec158bf203c59392654482b80775804556" + }, + { + "index": 2, + "out_digest": "00576d2c4d09ef5d7aa807f9b3b1587e200dea6f6694b4da062b41aa2a5ab8af" + }, + { + "index": 3, + "out_digest": "5541d29e4f230e7683ad45c081f4f325fa6216f308b1682f621b3ed279fc39f8" + }, + { + "index": 4, + "out_digest": "1cd1984bc553c43ee5a48fe7e182a77e60d8ef3c2b0f959ef1a0efd3813b411f" + }, + { + "index": 5, + "out_digest": "67754c573f1f7605becf03e65bffa704359b96917b5bc203901eb10e32182cf1" + } + ] + }, + "expected": { + "outcome": "accept", + "link_hash": "d5013711d65644d67734a1a9adb32fb7f9d193f0be912e4ae30de5578d985845" + } + }, + { + "name": "session_tree_07", + "about": "an output tree of 7 leaves, half on a byte-exact decoder whose re-decode matches and half checked for membership only, whose re-decode does not and is not checked", + "procedure": "claim", + "receipt": "{\"body\":{\"classical_declared\":700,\"classical_source\":\"wai2-table\",\"counted_discarded\":1904,\"counted_fallback\":0,\"counted_primary\":5607,\"deadline_us\":null,\"decoders\":[{\"capability\":\"wai.video.int_hyper\",\"decoder\":\"builtin:wai@0.4.0\",\"leaves\":4,\"module_status\":null,\"path\":\"primary\",\"pin\":\"7b4371854df0aa1645ac6525b373387c0617b873d5a57748932ee0f386ea164b\",\"rendition\":0,\"tier\":\"decode-equivalence\",\"variant\":null},{\"capability\":\"wai.video.av1\",\"decoder\":\"builtin:wai@0.4.0\",\"leaves\":3,\"module_status\":null,\"path\":\"fallback\",\"pin\":null,\"rendition\":null,\"tier\":null,\"variant\":null}],\"energy\":null,\"fallback_units\":3,\"framing\":\"registered\",\"host\":{\"build\":{\"profile\":\"release\",\"target\":\"aarch64-unknown-linux-gnu\",\"toolchain\":\"rustc 1.95.0\"},\"profile\":\"native-ffi\",\"target\":\"aarch64-unknown-linux-gnu\",\"threads\":4},\"leaf_count\":7,\"media\":\"video\",\"missed\":0,\"missed_units\":[],\"output_root\":\"c7b5f28385542cd8cffb5681ec7a5d9597dacc12d0f1517f4d986822132074bc\",\"primary_units\":4,\"receipt_bytes\":640,\"session_nonce\":\"57c5462dfdabd1b7bdd204d34ba33649c057eb535349f29f45eb8f8c7d4a7e7f\",\"stage_sets\":[],\"switches\":[],\"switches_total\":0,\"transferred\":13607,\"uncounted\":2,\"units\":7},\"class\":\"reconstruct-session\",\"issued_at\":\"2026-09-27T12:00:00Z\",\"kind\":\"claim\",\"parent_receipt_hash\":null,\"seq\":0,\"sig\":\"d11c4d972310333b59bc20c86989a658c707c68f379defcff53a87b0af8ec5fe664aa3ef98e90d8c9d0b5e56cfbb0077a84c842ca6935501ad682c27461d9c0e\",\"signer_id\":\"did:example:sink\",\"signer_pubkey\":\"d759793bbc13a2819a827c76adb6fba8a49aee007f49f2d0992d99b825ad2c48\",\"subject\":\"64c0713cb176874607bf8670295242184b7868a9ff7c55554a5ae08de2c301c1\",\"subject_type\":\"object\"}", + "context": { + "outputs": [ + { + "unit": 0, + "layers": 1, + "decoder": 0, + "out_digest": "55f7e628ca707e2ca3159709eeb68b9000813f2916a299acd33a23e6fe012584" + }, + { + "unit": 1, + "layers": 1, + "decoder": 1, + "out_digest": "a3ee8a4b96eceb663f3d94417957d02f897fc166dc96ebe9bf447c4a36a36264" + }, + { + "unit": 2, + "layers": 1, + "decoder": 0, + "out_digest": "00576d2c4d09ef5d7aa807f9b3b1587e200dea6f6694b4da062b41aa2a5ab8af" + }, + { + "unit": 3, + "layers": 1, + "decoder": 1, + "out_digest": "26cd9b2805b604b26e08d9a461db599c4e249bfd4df41a3befb202bc6d0e0700" + }, + { + "unit": 4, + "layers": 1, + "decoder": 0, + "out_digest": "1cd1984bc553c43ee5a48fe7e182a77e60d8ef3c2b0f959ef1a0efd3813b411f" + }, + { + "unit": 5, + "layers": 1, + "decoder": 1, + "out_digest": "e4c4344155dc2c789a1df265f8064b9ae56f3e0932d85c5ceb38782c135749fc" + }, + { + "unit": 6, + "layers": 1, + "decoder": 0, + "out_digest": "95542e01dfb7d7c52f2d526bf932ee49cf081ee2bc330c42dd0715cca7deff8b" + } + ], + "redecoded": [ + { + "index": 0, + "out_digest": "55f7e628ca707e2ca3159709eeb68b9000813f2916a299acd33a23e6fe012584" + }, + { + "index": 1, + "out_digest": "9df7f2652febf9fe462ff426af1ee3ec158bf203c59392654482b80775804556" + }, + { + "index": 2, + "out_digest": "00576d2c4d09ef5d7aa807f9b3b1587e200dea6f6694b4da062b41aa2a5ab8af" + }, + { + "index": 3, + "out_digest": "5541d29e4f230e7683ad45c081f4f325fa6216f308b1682f621b3ed279fc39f8" + }, + { + "index": 4, + "out_digest": "1cd1984bc553c43ee5a48fe7e182a77e60d8ef3c2b0f959ef1a0efd3813b411f" + }, + { + "index": 5, + "out_digest": "67754c573f1f7605becf03e65bffa704359b96917b5bc203901eb10e32182cf1" + }, + { + "index": 6, + "out_digest": "95542e01dfb7d7c52f2d526bf932ee49cf081ee2bc330c42dd0715cca7deff8b" + } + ] + }, + "expected": { + "outcome": "accept", + "link_hash": "91792ab40d3ffc4cc0a0971abc92e783c062d86840cdbb85068fdf2b3c997fea" + } + }, + { + "name": "session_tree_08", + "about": "an output tree of 8 leaves, half on a byte-exact decoder whose re-decode matches and half checked for membership only, whose re-decode does not and is not checked", + "procedure": "claim", + "receipt": "{\"body\":{\"classical_declared\":700,\"classical_source\":\"wai2-table\",\"counted_discarded\":1904,\"counted_fallback\":0,\"counted_primary\":5607,\"deadline_us\":null,\"decoders\":[{\"capability\":\"wai.video.int_hyper\",\"decoder\":\"builtin:wai@0.4.0\",\"leaves\":4,\"module_status\":null,\"path\":\"primary\",\"pin\":\"7b4371854df0aa1645ac6525b373387c0617b873d5a57748932ee0f386ea164b\",\"rendition\":0,\"tier\":\"decode-equivalence\",\"variant\":null},{\"capability\":\"wai.video.av1\",\"decoder\":\"builtin:wai@0.4.0\",\"leaves\":4,\"module_status\":null,\"path\":\"fallback\",\"pin\":null,\"rendition\":null,\"tier\":null,\"variant\":null}],\"energy\":null,\"fallback_units\":4,\"framing\":\"registered\",\"host\":{\"build\":{\"profile\":\"release\",\"target\":\"aarch64-unknown-linux-gnu\",\"toolchain\":\"rustc 1.95.0\"},\"profile\":\"native-ffi\",\"target\":\"aarch64-unknown-linux-gnu\",\"threads\":4},\"leaf_count\":8,\"media\":\"video\",\"missed\":0,\"missed_units\":[],\"output_root\":\"3dbe0bb16993427061d7a28dda6d96bacee45d5e0048d6667be35c14ec63b1cc\",\"primary_units\":4,\"receipt_bytes\":640,\"session_nonce\":\"57c5462dfdabd1b7bdd204d34ba33649c057eb535349f29f45eb8f8c7d4a7e7f\",\"stage_sets\":[],\"switches\":[],\"switches_total\":0,\"transferred\":13607,\"uncounted\":2,\"units\":8},\"class\":\"reconstruct-session\",\"issued_at\":\"2026-09-27T12:00:00Z\",\"kind\":\"claim\",\"parent_receipt_hash\":null,\"seq\":0,\"sig\":\"bbc65a17d02f00692b3b9c203280efeefc1e361bfdcfc5771001a6ed52fcab91cc0bec181eee1753642756fc2a3b0370d231ab1136af3d74da7c2d892a686709\",\"signer_id\":\"did:example:sink\",\"signer_pubkey\":\"d759793bbc13a2819a827c76adb6fba8a49aee007f49f2d0992d99b825ad2c48\",\"subject\":\"64c0713cb176874607bf8670295242184b7868a9ff7c55554a5ae08de2c301c1\",\"subject_type\":\"object\"}", + "context": { + "outputs": [ + { + "unit": 0, + "layers": 1, + "decoder": 0, + "out_digest": "55f7e628ca707e2ca3159709eeb68b9000813f2916a299acd33a23e6fe012584" + }, + { + "unit": 1, + "layers": 1, + "decoder": 1, + "out_digest": "a3ee8a4b96eceb663f3d94417957d02f897fc166dc96ebe9bf447c4a36a36264" + }, + { + "unit": 2, + "layers": 1, + "decoder": 0, + "out_digest": "00576d2c4d09ef5d7aa807f9b3b1587e200dea6f6694b4da062b41aa2a5ab8af" + }, + { + "unit": 3, + "layers": 1, + "decoder": 1, + "out_digest": "26cd9b2805b604b26e08d9a461db599c4e249bfd4df41a3befb202bc6d0e0700" + }, + { + "unit": 4, + "layers": 1, + "decoder": 0, + "out_digest": "1cd1984bc553c43ee5a48fe7e182a77e60d8ef3c2b0f959ef1a0efd3813b411f" + }, + { + "unit": 5, + "layers": 1, + "decoder": 1, + "out_digest": "e4c4344155dc2c789a1df265f8064b9ae56f3e0932d85c5ceb38782c135749fc" + }, + { + "unit": 6, + "layers": 1, + "decoder": 0, + "out_digest": "95542e01dfb7d7c52f2d526bf932ee49cf081ee2bc330c42dd0715cca7deff8b" + }, + { + "unit": 7, + "layers": 1, + "decoder": 1, + "out_digest": "cf1c65a8bc3fabc40710f610dcfa9ac2604f45a6fa68f74ee2b464421647da4c" + } + ], + "redecoded": [ + { + "index": 0, + "out_digest": "55f7e628ca707e2ca3159709eeb68b9000813f2916a299acd33a23e6fe012584" + }, + { + "index": 1, + "out_digest": "9df7f2652febf9fe462ff426af1ee3ec158bf203c59392654482b80775804556" + }, + { + "index": 2, + "out_digest": "00576d2c4d09ef5d7aa807f9b3b1587e200dea6f6694b4da062b41aa2a5ab8af" + }, + { + "index": 3, + "out_digest": "5541d29e4f230e7683ad45c081f4f325fa6216f308b1682f621b3ed279fc39f8" + }, + { + "index": 4, + "out_digest": "1cd1984bc553c43ee5a48fe7e182a77e60d8ef3c2b0f959ef1a0efd3813b411f" + }, + { + "index": 5, + "out_digest": "67754c573f1f7605becf03e65bffa704359b96917b5bc203901eb10e32182cf1" + }, + { + "index": 6, + "out_digest": "95542e01dfb7d7c52f2d526bf932ee49cf081ee2bc330c42dd0715cca7deff8b" + }, + { + "index": 7, + "out_digest": "e7f6d40664240de8fe0eea2384891d0f040db6f05dca8450533a725410bfd31f" + } + ] + }, + "expected": { + "outcome": "accept", + "link_hash": "cd82180882e7509e1f661dfeb134b31d9b0a39e1fe290450f1c33a46b57e360f" + } + }, + { + "name": "session_tree_09", + "about": "an output tree of 9 leaves, half on a byte-exact decoder whose re-decode matches and half checked for membership only, whose re-decode does not and is not checked", + "procedure": "claim", + "receipt": "{\"body\":{\"classical_declared\":700,\"classical_source\":\"wai2-table\",\"counted_discarded\":1904,\"counted_fallback\":0,\"counted_primary\":5607,\"deadline_us\":null,\"decoders\":[{\"capability\":\"wai.video.int_hyper\",\"decoder\":\"builtin:wai@0.4.0\",\"leaves\":5,\"module_status\":null,\"path\":\"primary\",\"pin\":\"7b4371854df0aa1645ac6525b373387c0617b873d5a57748932ee0f386ea164b\",\"rendition\":0,\"tier\":\"decode-equivalence\",\"variant\":null},{\"capability\":\"wai.video.av1\",\"decoder\":\"builtin:wai@0.4.0\",\"leaves\":4,\"module_status\":null,\"path\":\"fallback\",\"pin\":null,\"rendition\":null,\"tier\":null,\"variant\":null}],\"energy\":null,\"fallback_units\":4,\"framing\":\"registered\",\"host\":{\"build\":{\"profile\":\"release\",\"target\":\"aarch64-unknown-linux-gnu\",\"toolchain\":\"rustc 1.95.0\"},\"profile\":\"native-ffi\",\"target\":\"aarch64-unknown-linux-gnu\",\"threads\":4},\"leaf_count\":9,\"media\":\"video\",\"missed\":0,\"missed_units\":[],\"output_root\":\"c9e6f19c7b803c8b77c0d8399f25111bfa47bbe9a33946789f308309f52a520e\",\"primary_units\":5,\"receipt_bytes\":640,\"session_nonce\":\"57c5462dfdabd1b7bdd204d34ba33649c057eb535349f29f45eb8f8c7d4a7e7f\",\"stage_sets\":[],\"switches\":[],\"switches_total\":0,\"transferred\":13607,\"uncounted\":2,\"units\":9},\"class\":\"reconstruct-session\",\"issued_at\":\"2026-09-27T12:00:00Z\",\"kind\":\"claim\",\"parent_receipt_hash\":null,\"seq\":0,\"sig\":\"9fcdccfca96242b0b834e9c397fb0c1adbb4f0441a40d122b3394a364f283858badcfb714f0e663b904e4a69982a7da8fcb4ffc3b0892101eb7e05552859300c\",\"signer_id\":\"did:example:sink\",\"signer_pubkey\":\"d759793bbc13a2819a827c76adb6fba8a49aee007f49f2d0992d99b825ad2c48\",\"subject\":\"64c0713cb176874607bf8670295242184b7868a9ff7c55554a5ae08de2c301c1\",\"subject_type\":\"object\"}", + "context": { + "outputs": [ + { + "unit": 0, + "layers": 1, + "decoder": 0, + "out_digest": "55f7e628ca707e2ca3159709eeb68b9000813f2916a299acd33a23e6fe012584" + }, + { + "unit": 1, + "layers": 1, + "decoder": 1, + "out_digest": "a3ee8a4b96eceb663f3d94417957d02f897fc166dc96ebe9bf447c4a36a36264" + }, + { + "unit": 2, + "layers": 1, + "decoder": 0, + "out_digest": "00576d2c4d09ef5d7aa807f9b3b1587e200dea6f6694b4da062b41aa2a5ab8af" + }, + { + "unit": 3, + "layers": 1, + "decoder": 1, + "out_digest": "26cd9b2805b604b26e08d9a461db599c4e249bfd4df41a3befb202bc6d0e0700" + }, + { + "unit": 4, + "layers": 1, + "decoder": 0, + "out_digest": "1cd1984bc553c43ee5a48fe7e182a77e60d8ef3c2b0f959ef1a0efd3813b411f" + }, + { + "unit": 5, + "layers": 1, + "decoder": 1, + "out_digest": "e4c4344155dc2c789a1df265f8064b9ae56f3e0932d85c5ceb38782c135749fc" + }, + { + "unit": 6, + "layers": 1, + "decoder": 0, + "out_digest": "95542e01dfb7d7c52f2d526bf932ee49cf081ee2bc330c42dd0715cca7deff8b" + }, + { + "unit": 7, + "layers": 1, + "decoder": 1, + "out_digest": "cf1c65a8bc3fabc40710f610dcfa9ac2604f45a6fa68f74ee2b464421647da4c" + }, + { + "unit": 8, + "layers": 1, + "decoder": 0, + "out_digest": "5c01f526973ca7dbcde1513bc7d25333954bc4164811a5f21399b6e48d89079d" + } + ], + "redecoded": [ + { + "index": 0, + "out_digest": "55f7e628ca707e2ca3159709eeb68b9000813f2916a299acd33a23e6fe012584" + }, + { + "index": 1, + "out_digest": "9df7f2652febf9fe462ff426af1ee3ec158bf203c59392654482b80775804556" + }, + { + "index": 2, + "out_digest": "00576d2c4d09ef5d7aa807f9b3b1587e200dea6f6694b4da062b41aa2a5ab8af" + }, + { + "index": 3, + "out_digest": "5541d29e4f230e7683ad45c081f4f325fa6216f308b1682f621b3ed279fc39f8" + }, + { + "index": 4, + "out_digest": "1cd1984bc553c43ee5a48fe7e182a77e60d8ef3c2b0f959ef1a0efd3813b411f" + }, + { + "index": 5, + "out_digest": "67754c573f1f7605becf03e65bffa704359b96917b5bc203901eb10e32182cf1" + }, + { + "index": 6, + "out_digest": "95542e01dfb7d7c52f2d526bf932ee49cf081ee2bc330c42dd0715cca7deff8b" + }, + { + "index": 7, + "out_digest": "e7f6d40664240de8fe0eea2384891d0f040db6f05dca8450533a725410bfd31f" + }, + { + "index": 8, + "out_digest": "5c01f526973ca7dbcde1513bc7d25333954bc4164811a5f21399b6e48d89079d" + } + ] + }, + "expected": { + "outcome": "accept", + "link_hash": "bf0459092ec1bc4b21323349e9c86bc05ba29c35aa52af83a05def870dcf1079" + } + }, + { + "name": "session_tree_10", + "about": "an output tree of 10 leaves, half on a byte-exact decoder whose re-decode matches and half checked for membership only, whose re-decode does not and is not checked", + "procedure": "claim", + "receipt": "{\"body\":{\"classical_declared\":700,\"classical_source\":\"wai2-table\",\"counted_discarded\":1904,\"counted_fallback\":0,\"counted_primary\":5607,\"deadline_us\":null,\"decoders\":[{\"capability\":\"wai.video.int_hyper\",\"decoder\":\"builtin:wai@0.4.0\",\"leaves\":5,\"module_status\":null,\"path\":\"primary\",\"pin\":\"7b4371854df0aa1645ac6525b373387c0617b873d5a57748932ee0f386ea164b\",\"rendition\":0,\"tier\":\"decode-equivalence\",\"variant\":null},{\"capability\":\"wai.video.av1\",\"decoder\":\"builtin:wai@0.4.0\",\"leaves\":5,\"module_status\":null,\"path\":\"fallback\",\"pin\":null,\"rendition\":null,\"tier\":null,\"variant\":null}],\"energy\":null,\"fallback_units\":5,\"framing\":\"registered\",\"host\":{\"build\":{\"profile\":\"release\",\"target\":\"aarch64-unknown-linux-gnu\",\"toolchain\":\"rustc 1.95.0\"},\"profile\":\"native-ffi\",\"target\":\"aarch64-unknown-linux-gnu\",\"threads\":4},\"leaf_count\":10,\"media\":\"video\",\"missed\":0,\"missed_units\":[],\"output_root\":\"5d273e52eccde53e9a7d287fcb05c66b71bf05b3b00209adb6096f511f5c13b5\",\"primary_units\":5,\"receipt_bytes\":640,\"session_nonce\":\"57c5462dfdabd1b7bdd204d34ba33649c057eb535349f29f45eb8f8c7d4a7e7f\",\"stage_sets\":[],\"switches\":[],\"switches_total\":0,\"transferred\":13607,\"uncounted\":2,\"units\":10},\"class\":\"reconstruct-session\",\"issued_at\":\"2026-09-27T12:00:00Z\",\"kind\":\"claim\",\"parent_receipt_hash\":null,\"seq\":0,\"sig\":\"12fdf9959cf52273789921ebc3755fe57f8b4dd5d2ea77ed373e55f6abdc2b2231a4f86e1d07e0f5eeafea785dd4cfe09afaa3cf57c98be33c793d4bb9ff0901\",\"signer_id\":\"did:example:sink\",\"signer_pubkey\":\"d759793bbc13a2819a827c76adb6fba8a49aee007f49f2d0992d99b825ad2c48\",\"subject\":\"64c0713cb176874607bf8670295242184b7868a9ff7c55554a5ae08de2c301c1\",\"subject_type\":\"object\"}", + "context": { + "outputs": [ + { + "unit": 0, + "layers": 1, + "decoder": 0, + "out_digest": "55f7e628ca707e2ca3159709eeb68b9000813f2916a299acd33a23e6fe012584" + }, + { + "unit": 1, + "layers": 1, + "decoder": 1, + "out_digest": "a3ee8a4b96eceb663f3d94417957d02f897fc166dc96ebe9bf447c4a36a36264" + }, + { + "unit": 2, + "layers": 1, + "decoder": 0, + "out_digest": "00576d2c4d09ef5d7aa807f9b3b1587e200dea6f6694b4da062b41aa2a5ab8af" + }, + { + "unit": 3, + "layers": 1, + "decoder": 1, + "out_digest": "26cd9b2805b604b26e08d9a461db599c4e249bfd4df41a3befb202bc6d0e0700" + }, + { + "unit": 4, + "layers": 1, + "decoder": 0, + "out_digest": "1cd1984bc553c43ee5a48fe7e182a77e60d8ef3c2b0f959ef1a0efd3813b411f" + }, + { + "unit": 5, + "layers": 1, + "decoder": 1, + "out_digest": "e4c4344155dc2c789a1df265f8064b9ae56f3e0932d85c5ceb38782c135749fc" + }, + { + "unit": 6, + "layers": 1, + "decoder": 0, + "out_digest": "95542e01dfb7d7c52f2d526bf932ee49cf081ee2bc330c42dd0715cca7deff8b" + }, + { + "unit": 7, + "layers": 1, + "decoder": 1, + "out_digest": "cf1c65a8bc3fabc40710f610dcfa9ac2604f45a6fa68f74ee2b464421647da4c" + }, + { + "unit": 8, + "layers": 1, + "decoder": 0, + "out_digest": "5c01f526973ca7dbcde1513bc7d25333954bc4164811a5f21399b6e48d89079d" + }, + { + "unit": 9, + "layers": 1, + "decoder": 1, + "out_digest": "686ff0277613c58687a493af12da86b393bcee283c6758845a2505a93d135905" + } + ], + "redecoded": [ + { + "index": 0, + "out_digest": "55f7e628ca707e2ca3159709eeb68b9000813f2916a299acd33a23e6fe012584" + }, + { + "index": 1, + "out_digest": "9df7f2652febf9fe462ff426af1ee3ec158bf203c59392654482b80775804556" + }, + { + "index": 2, + "out_digest": "00576d2c4d09ef5d7aa807f9b3b1587e200dea6f6694b4da062b41aa2a5ab8af" + }, + { + "index": 3, + "out_digest": "5541d29e4f230e7683ad45c081f4f325fa6216f308b1682f621b3ed279fc39f8" + }, + { + "index": 4, + "out_digest": "1cd1984bc553c43ee5a48fe7e182a77e60d8ef3c2b0f959ef1a0efd3813b411f" + }, + { + "index": 5, + "out_digest": "67754c573f1f7605becf03e65bffa704359b96917b5bc203901eb10e32182cf1" + }, + { + "index": 6, + "out_digest": "95542e01dfb7d7c52f2d526bf932ee49cf081ee2bc330c42dd0715cca7deff8b" + }, + { + "index": 7, + "out_digest": "e7f6d40664240de8fe0eea2384891d0f040db6f05dca8450533a725410bfd31f" + }, + { + "index": 8, + "out_digest": "5c01f526973ca7dbcde1513bc7d25333954bc4164811a5f21399b6e48d89079d" + }, + { + "index": 9, + "out_digest": "f3ff8b3d08e7010fb0d5f7c836dc8b5969bcc95a73ae76813443a2b70929b6bb" + } + ] + }, + "expected": { + "outcome": "accept", + "link_hash": "8d9a055fc59a19c2271231538475a3e1ac7249315314f40c2cf8ecc1ed26152e" + } + }, + { + "name": "session_tree_11", + "about": "an output tree of 11 leaves, half on a byte-exact decoder whose re-decode matches and half checked for membership only, whose re-decode does not and is not checked", + "procedure": "claim", + "receipt": "{\"body\":{\"classical_declared\":700,\"classical_source\":\"wai2-table\",\"counted_discarded\":1904,\"counted_fallback\":0,\"counted_primary\":5607,\"deadline_us\":null,\"decoders\":[{\"capability\":\"wai.video.int_hyper\",\"decoder\":\"builtin:wai@0.4.0\",\"leaves\":6,\"module_status\":null,\"path\":\"primary\",\"pin\":\"7b4371854df0aa1645ac6525b373387c0617b873d5a57748932ee0f386ea164b\",\"rendition\":0,\"tier\":\"decode-equivalence\",\"variant\":null},{\"capability\":\"wai.video.av1\",\"decoder\":\"builtin:wai@0.4.0\",\"leaves\":5,\"module_status\":null,\"path\":\"fallback\",\"pin\":null,\"rendition\":null,\"tier\":null,\"variant\":null}],\"energy\":null,\"fallback_units\":5,\"framing\":\"registered\",\"host\":{\"build\":{\"profile\":\"release\",\"target\":\"aarch64-unknown-linux-gnu\",\"toolchain\":\"rustc 1.95.0\"},\"profile\":\"native-ffi\",\"target\":\"aarch64-unknown-linux-gnu\",\"threads\":4},\"leaf_count\":11,\"media\":\"video\",\"missed\":0,\"missed_units\":[],\"output_root\":\"95150e54cbea1f7024015ea20e2ed826b2abb942b98c6e7c98b768b2dcd2d138\",\"primary_units\":6,\"receipt_bytes\":640,\"session_nonce\":\"57c5462dfdabd1b7bdd204d34ba33649c057eb535349f29f45eb8f8c7d4a7e7f\",\"stage_sets\":[],\"switches\":[],\"switches_total\":0,\"transferred\":13607,\"uncounted\":2,\"units\":11},\"class\":\"reconstruct-session\",\"issued_at\":\"2026-09-27T12:00:00Z\",\"kind\":\"claim\",\"parent_receipt_hash\":null,\"seq\":0,\"sig\":\"e4bee105bd21ac8b3fb0f5d16bbe9038bd1c9aaf977f887ebec7d6d3ede8870a661c96d13a41eb89bf3f414edf14157eb65f041b24a8f9dd55e8a9ac06299807\",\"signer_id\":\"did:example:sink\",\"signer_pubkey\":\"d759793bbc13a2819a827c76adb6fba8a49aee007f49f2d0992d99b825ad2c48\",\"subject\":\"64c0713cb176874607bf8670295242184b7868a9ff7c55554a5ae08de2c301c1\",\"subject_type\":\"object\"}", + "context": { + "outputs": [ + { + "unit": 0, + "layers": 1, + "decoder": 0, + "out_digest": "55f7e628ca707e2ca3159709eeb68b9000813f2916a299acd33a23e6fe012584" + }, + { + "unit": 1, + "layers": 1, + "decoder": 1, + "out_digest": "a3ee8a4b96eceb663f3d94417957d02f897fc166dc96ebe9bf447c4a36a36264" + }, + { + "unit": 2, + "layers": 1, + "decoder": 0, + "out_digest": "00576d2c4d09ef5d7aa807f9b3b1587e200dea6f6694b4da062b41aa2a5ab8af" + }, + { + "unit": 3, + "layers": 1, + "decoder": 1, + "out_digest": "26cd9b2805b604b26e08d9a461db599c4e249bfd4df41a3befb202bc6d0e0700" + }, + { + "unit": 4, + "layers": 1, + "decoder": 0, + "out_digest": "1cd1984bc553c43ee5a48fe7e182a77e60d8ef3c2b0f959ef1a0efd3813b411f" + }, + { + "unit": 5, + "layers": 1, + "decoder": 1, + "out_digest": "e4c4344155dc2c789a1df265f8064b9ae56f3e0932d85c5ceb38782c135749fc" + }, + { + "unit": 6, + "layers": 1, + "decoder": 0, + "out_digest": "95542e01dfb7d7c52f2d526bf932ee49cf081ee2bc330c42dd0715cca7deff8b" + }, + { + "unit": 7, + "layers": 1, + "decoder": 1, + "out_digest": "cf1c65a8bc3fabc40710f610dcfa9ac2604f45a6fa68f74ee2b464421647da4c" + }, + { + "unit": 8, + "layers": 1, + "decoder": 0, + "out_digest": "5c01f526973ca7dbcde1513bc7d25333954bc4164811a5f21399b6e48d89079d" + }, + { + "unit": 9, + "layers": 1, + "decoder": 1, + "out_digest": "686ff0277613c58687a493af12da86b393bcee283c6758845a2505a93d135905" + }, + { + "unit": 10, + "layers": 1, + "decoder": 0, + "out_digest": "23851d2c5e0cc5365e329fbd9c01238313ac71fd4edb4730fa7d58cc74e74823" + } + ], + "redecoded": [ + { + "index": 0, + "out_digest": "55f7e628ca707e2ca3159709eeb68b9000813f2916a299acd33a23e6fe012584" + }, + { + "index": 1, + "out_digest": "9df7f2652febf9fe462ff426af1ee3ec158bf203c59392654482b80775804556" + }, + { + "index": 2, + "out_digest": "00576d2c4d09ef5d7aa807f9b3b1587e200dea6f6694b4da062b41aa2a5ab8af" + }, + { + "index": 3, + "out_digest": "5541d29e4f230e7683ad45c081f4f325fa6216f308b1682f621b3ed279fc39f8" + }, + { + "index": 4, + "out_digest": "1cd1984bc553c43ee5a48fe7e182a77e60d8ef3c2b0f959ef1a0efd3813b411f" + }, + { + "index": 5, + "out_digest": "67754c573f1f7605becf03e65bffa704359b96917b5bc203901eb10e32182cf1" + }, + { + "index": 6, + "out_digest": "95542e01dfb7d7c52f2d526bf932ee49cf081ee2bc330c42dd0715cca7deff8b" + }, + { + "index": 7, + "out_digest": "e7f6d40664240de8fe0eea2384891d0f040db6f05dca8450533a725410bfd31f" + }, + { + "index": 8, + "out_digest": "5c01f526973ca7dbcde1513bc7d25333954bc4164811a5f21399b6e48d89079d" + }, + { + "index": 9, + "out_digest": "f3ff8b3d08e7010fb0d5f7c836dc8b5969bcc95a73ae76813443a2b70929b6bb" + }, + { + "index": 10, + "out_digest": "23851d2c5e0cc5365e329fbd9c01238313ac71fd4edb4730fa7d58cc74e74823" + } + ] + }, + "expected": { + "outcome": "accept", + "link_hash": "9644066f31e07fdea3df83af7f1142790564b62107b5a8c1c3eaf2ad91ae2f2c" + } + }, + { + "name": "session_tree_12", + "about": "an output tree of 12 leaves, half on a byte-exact decoder whose re-decode matches and half checked for membership only, whose re-decode does not and is not checked", + "procedure": "claim", + "receipt": "{\"body\":{\"classical_declared\":700,\"classical_source\":\"wai2-table\",\"counted_discarded\":1904,\"counted_fallback\":0,\"counted_primary\":5607,\"deadline_us\":null,\"decoders\":[{\"capability\":\"wai.video.int_hyper\",\"decoder\":\"builtin:wai@0.4.0\",\"leaves\":6,\"module_status\":null,\"path\":\"primary\",\"pin\":\"7b4371854df0aa1645ac6525b373387c0617b873d5a57748932ee0f386ea164b\",\"rendition\":0,\"tier\":\"decode-equivalence\",\"variant\":null},{\"capability\":\"wai.video.av1\",\"decoder\":\"builtin:wai@0.4.0\",\"leaves\":6,\"module_status\":null,\"path\":\"fallback\",\"pin\":null,\"rendition\":null,\"tier\":null,\"variant\":null}],\"energy\":null,\"fallback_units\":6,\"framing\":\"registered\",\"host\":{\"build\":{\"profile\":\"release\",\"target\":\"aarch64-unknown-linux-gnu\",\"toolchain\":\"rustc 1.95.0\"},\"profile\":\"native-ffi\",\"target\":\"aarch64-unknown-linux-gnu\",\"threads\":4},\"leaf_count\":12,\"media\":\"video\",\"missed\":0,\"missed_units\":[],\"output_root\":\"e7c5251b2715d0d250df47e8d335d9626b27492fa6d99023b7c733ce2f5e5baa\",\"primary_units\":6,\"receipt_bytes\":640,\"session_nonce\":\"57c5462dfdabd1b7bdd204d34ba33649c057eb535349f29f45eb8f8c7d4a7e7f\",\"stage_sets\":[],\"switches\":[],\"switches_total\":0,\"transferred\":13607,\"uncounted\":2,\"units\":12},\"class\":\"reconstruct-session\",\"issued_at\":\"2026-09-27T12:00:00Z\",\"kind\":\"claim\",\"parent_receipt_hash\":null,\"seq\":0,\"sig\":\"4f5b86420d26498ecd90f778c88d08373e3cc2e1a554d6a6eb9486a8363c661e73826735729530757241e56fca373849d0a984352f877dce980d8a7c7b612f00\",\"signer_id\":\"did:example:sink\",\"signer_pubkey\":\"d759793bbc13a2819a827c76adb6fba8a49aee007f49f2d0992d99b825ad2c48\",\"subject\":\"64c0713cb176874607bf8670295242184b7868a9ff7c55554a5ae08de2c301c1\",\"subject_type\":\"object\"}", + "context": { + "outputs": [ + { + "unit": 0, + "layers": 1, + "decoder": 0, + "out_digest": "55f7e628ca707e2ca3159709eeb68b9000813f2916a299acd33a23e6fe012584" + }, + { + "unit": 1, + "layers": 1, + "decoder": 1, + "out_digest": "a3ee8a4b96eceb663f3d94417957d02f897fc166dc96ebe9bf447c4a36a36264" + }, + { + "unit": 2, + "layers": 1, + "decoder": 0, + "out_digest": "00576d2c4d09ef5d7aa807f9b3b1587e200dea6f6694b4da062b41aa2a5ab8af" + }, + { + "unit": 3, + "layers": 1, + "decoder": 1, + "out_digest": "26cd9b2805b604b26e08d9a461db599c4e249bfd4df41a3befb202bc6d0e0700" + }, + { + "unit": 4, + "layers": 1, + "decoder": 0, + "out_digest": "1cd1984bc553c43ee5a48fe7e182a77e60d8ef3c2b0f959ef1a0efd3813b411f" + }, + { + "unit": 5, + "layers": 1, + "decoder": 1, + "out_digest": "e4c4344155dc2c789a1df265f8064b9ae56f3e0932d85c5ceb38782c135749fc" + }, + { + "unit": 6, + "layers": 1, + "decoder": 0, + "out_digest": "95542e01dfb7d7c52f2d526bf932ee49cf081ee2bc330c42dd0715cca7deff8b" + }, + { + "unit": 7, + "layers": 1, + "decoder": 1, + "out_digest": "cf1c65a8bc3fabc40710f610dcfa9ac2604f45a6fa68f74ee2b464421647da4c" + }, + { + "unit": 8, + "layers": 1, + "decoder": 0, + "out_digest": "5c01f526973ca7dbcde1513bc7d25333954bc4164811a5f21399b6e48d89079d" + }, + { + "unit": 9, + "layers": 1, + "decoder": 1, + "out_digest": "686ff0277613c58687a493af12da86b393bcee283c6758845a2505a93d135905" + }, + { + "unit": 10, + "layers": 1, + "decoder": 0, + "out_digest": "23851d2c5e0cc5365e329fbd9c01238313ac71fd4edb4730fa7d58cc74e74823" + }, + { + "unit": 11, + "layers": 1, + "decoder": 1, + "out_digest": "66270813e69c6cffbacb67f95a9c182b2f04ce8c3b2ee4829c257227a5f4a17a" + } + ], + "redecoded": [ + { + "index": 0, + "out_digest": "55f7e628ca707e2ca3159709eeb68b9000813f2916a299acd33a23e6fe012584" + }, + { + "index": 1, + "out_digest": "9df7f2652febf9fe462ff426af1ee3ec158bf203c59392654482b80775804556" + }, + { + "index": 2, + "out_digest": "00576d2c4d09ef5d7aa807f9b3b1587e200dea6f6694b4da062b41aa2a5ab8af" + }, + { + "index": 3, + "out_digest": "5541d29e4f230e7683ad45c081f4f325fa6216f308b1682f621b3ed279fc39f8" + }, + { + "index": 4, + "out_digest": "1cd1984bc553c43ee5a48fe7e182a77e60d8ef3c2b0f959ef1a0efd3813b411f" + }, + { + "index": 5, + "out_digest": "67754c573f1f7605becf03e65bffa704359b96917b5bc203901eb10e32182cf1" + }, + { + "index": 6, + "out_digest": "95542e01dfb7d7c52f2d526bf932ee49cf081ee2bc330c42dd0715cca7deff8b" + }, + { + "index": 7, + "out_digest": "e7f6d40664240de8fe0eea2384891d0f040db6f05dca8450533a725410bfd31f" + }, + { + "index": 8, + "out_digest": "5c01f526973ca7dbcde1513bc7d25333954bc4164811a5f21399b6e48d89079d" + }, + { + "index": 9, + "out_digest": "f3ff8b3d08e7010fb0d5f7c836dc8b5969bcc95a73ae76813443a2b70929b6bb" + }, + { + "index": 10, + "out_digest": "23851d2c5e0cc5365e329fbd9c01238313ac71fd4edb4730fa7d58cc74e74823" + }, + { + "index": 11, + "out_digest": "9469cdcb42fe46fe46e0e0bb0e10f3397dc5048a60b81467183939f1e4548f74" + } + ] + }, + "expected": { + "outcome": "accept", + "link_hash": "671c71d964465eb770c834698abbb3d062e3ee70837d335fa3e71827f17c027b" + } + }, + { + "name": "session_tree_13", + "about": "an output tree of 13 leaves, half on a byte-exact decoder whose re-decode matches and half checked for membership only, whose re-decode does not and is not checked", + "procedure": "claim", + "receipt": "{\"body\":{\"classical_declared\":700,\"classical_source\":\"wai2-table\",\"counted_discarded\":1904,\"counted_fallback\":0,\"counted_primary\":5607,\"deadline_us\":null,\"decoders\":[{\"capability\":\"wai.video.int_hyper\",\"decoder\":\"builtin:wai@0.4.0\",\"leaves\":7,\"module_status\":null,\"path\":\"primary\",\"pin\":\"7b4371854df0aa1645ac6525b373387c0617b873d5a57748932ee0f386ea164b\",\"rendition\":0,\"tier\":\"decode-equivalence\",\"variant\":null},{\"capability\":\"wai.video.av1\",\"decoder\":\"builtin:wai@0.4.0\",\"leaves\":6,\"module_status\":null,\"path\":\"fallback\",\"pin\":null,\"rendition\":null,\"tier\":null,\"variant\":null}],\"energy\":null,\"fallback_units\":6,\"framing\":\"registered\",\"host\":{\"build\":{\"profile\":\"release\",\"target\":\"aarch64-unknown-linux-gnu\",\"toolchain\":\"rustc 1.95.0\"},\"profile\":\"native-ffi\",\"target\":\"aarch64-unknown-linux-gnu\",\"threads\":4},\"leaf_count\":13,\"media\":\"video\",\"missed\":0,\"missed_units\":[],\"output_root\":\"db1298ad9fb8b1a2d6a411d52505d21c55bba463db8a48f72a6c87b2463daf54\",\"primary_units\":7,\"receipt_bytes\":640,\"session_nonce\":\"57c5462dfdabd1b7bdd204d34ba33649c057eb535349f29f45eb8f8c7d4a7e7f\",\"stage_sets\":[],\"switches\":[],\"switches_total\":0,\"transferred\":13607,\"uncounted\":2,\"units\":13},\"class\":\"reconstruct-session\",\"issued_at\":\"2026-09-27T12:00:00Z\",\"kind\":\"claim\",\"parent_receipt_hash\":null,\"seq\":0,\"sig\":\"ac8b1f2ada314a240a5480e3d25b5fca609f4460f12cdcb4b92048ce578604dd5a703348aa13d2e3c003fb0d021b2ee159db2e5690e45ac877e7113f09319c02\",\"signer_id\":\"did:example:sink\",\"signer_pubkey\":\"d759793bbc13a2819a827c76adb6fba8a49aee007f49f2d0992d99b825ad2c48\",\"subject\":\"64c0713cb176874607bf8670295242184b7868a9ff7c55554a5ae08de2c301c1\",\"subject_type\":\"object\"}", + "context": { + "outputs": [ + { + "unit": 0, + "layers": 1, + "decoder": 0, + "out_digest": "55f7e628ca707e2ca3159709eeb68b9000813f2916a299acd33a23e6fe012584" + }, + { + "unit": 1, + "layers": 1, + "decoder": 1, + "out_digest": "a3ee8a4b96eceb663f3d94417957d02f897fc166dc96ebe9bf447c4a36a36264" + }, + { + "unit": 2, + "layers": 1, + "decoder": 0, + "out_digest": "00576d2c4d09ef5d7aa807f9b3b1587e200dea6f6694b4da062b41aa2a5ab8af" + }, + { + "unit": 3, + "layers": 1, + "decoder": 1, + "out_digest": "26cd9b2805b604b26e08d9a461db599c4e249bfd4df41a3befb202bc6d0e0700" + }, + { + "unit": 4, + "layers": 1, + "decoder": 0, + "out_digest": "1cd1984bc553c43ee5a48fe7e182a77e60d8ef3c2b0f959ef1a0efd3813b411f" + }, + { + "unit": 5, + "layers": 1, + "decoder": 1, + "out_digest": "e4c4344155dc2c789a1df265f8064b9ae56f3e0932d85c5ceb38782c135749fc" + }, + { + "unit": 6, + "layers": 1, + "decoder": 0, + "out_digest": "95542e01dfb7d7c52f2d526bf932ee49cf081ee2bc330c42dd0715cca7deff8b" + }, + { + "unit": 7, + "layers": 1, + "decoder": 1, + "out_digest": "cf1c65a8bc3fabc40710f610dcfa9ac2604f45a6fa68f74ee2b464421647da4c" + }, + { + "unit": 8, + "layers": 1, + "decoder": 0, + "out_digest": "5c01f526973ca7dbcde1513bc7d25333954bc4164811a5f21399b6e48d89079d" + }, + { + "unit": 9, + "layers": 1, + "decoder": 1, + "out_digest": "686ff0277613c58687a493af12da86b393bcee283c6758845a2505a93d135905" + }, + { + "unit": 10, + "layers": 1, + "decoder": 0, + "out_digest": "23851d2c5e0cc5365e329fbd9c01238313ac71fd4edb4730fa7d58cc74e74823" + }, + { + "unit": 11, + "layers": 1, + "decoder": 1, + "out_digest": "66270813e69c6cffbacb67f95a9c182b2f04ce8c3b2ee4829c257227a5f4a17a" + }, + { + "unit": 12, + "layers": 1, + "decoder": 0, + "out_digest": "47c089823c210a1989895087dc4d44dc5ed8ee0453d7f2517ccce83cb686c824" + } + ], + "redecoded": [ + { + "index": 0, + "out_digest": "55f7e628ca707e2ca3159709eeb68b9000813f2916a299acd33a23e6fe012584" + }, + { + "index": 1, + "out_digest": "9df7f2652febf9fe462ff426af1ee3ec158bf203c59392654482b80775804556" + }, + { + "index": 2, + "out_digest": "00576d2c4d09ef5d7aa807f9b3b1587e200dea6f6694b4da062b41aa2a5ab8af" + }, + { + "index": 3, + "out_digest": "5541d29e4f230e7683ad45c081f4f325fa6216f308b1682f621b3ed279fc39f8" + }, + { + "index": 4, + "out_digest": "1cd1984bc553c43ee5a48fe7e182a77e60d8ef3c2b0f959ef1a0efd3813b411f" + }, + { + "index": 5, + "out_digest": "67754c573f1f7605becf03e65bffa704359b96917b5bc203901eb10e32182cf1" + }, + { + "index": 6, + "out_digest": "95542e01dfb7d7c52f2d526bf932ee49cf081ee2bc330c42dd0715cca7deff8b" + }, + { + "index": 7, + "out_digest": "e7f6d40664240de8fe0eea2384891d0f040db6f05dca8450533a725410bfd31f" + }, + { + "index": 8, + "out_digest": "5c01f526973ca7dbcde1513bc7d25333954bc4164811a5f21399b6e48d89079d" + }, + { + "index": 9, + "out_digest": "f3ff8b3d08e7010fb0d5f7c836dc8b5969bcc95a73ae76813443a2b70929b6bb" + }, + { + "index": 10, + "out_digest": "23851d2c5e0cc5365e329fbd9c01238313ac71fd4edb4730fa7d58cc74e74823" + }, + { + "index": 11, + "out_digest": "9469cdcb42fe46fe46e0e0bb0e10f3397dc5048a60b81467183939f1e4548f74" + }, + { + "index": 12, + "out_digest": "47c089823c210a1989895087dc4d44dc5ed8ee0453d7f2517ccce83cb686c824" + } + ] + }, + "expected": { + "outcome": "accept", + "link_hash": "1d3d195c46f14c5203799905e5f3f3b8cced5b28dcbe184cf63951b97c437691" + } + }, + { + "name": "session_tree_14", + "about": "an output tree of 14 leaves, half on a byte-exact decoder whose re-decode matches and half checked for membership only, whose re-decode does not and is not checked", + "procedure": "claim", + "receipt": "{\"body\":{\"classical_declared\":700,\"classical_source\":\"wai2-table\",\"counted_discarded\":1904,\"counted_fallback\":0,\"counted_primary\":5607,\"deadline_us\":null,\"decoders\":[{\"capability\":\"wai.video.int_hyper\",\"decoder\":\"builtin:wai@0.4.0\",\"leaves\":7,\"module_status\":null,\"path\":\"primary\",\"pin\":\"7b4371854df0aa1645ac6525b373387c0617b873d5a57748932ee0f386ea164b\",\"rendition\":0,\"tier\":\"decode-equivalence\",\"variant\":null},{\"capability\":\"wai.video.av1\",\"decoder\":\"builtin:wai@0.4.0\",\"leaves\":7,\"module_status\":null,\"path\":\"fallback\",\"pin\":null,\"rendition\":null,\"tier\":null,\"variant\":null}],\"energy\":null,\"fallback_units\":7,\"framing\":\"registered\",\"host\":{\"build\":{\"profile\":\"release\",\"target\":\"aarch64-unknown-linux-gnu\",\"toolchain\":\"rustc 1.95.0\"},\"profile\":\"native-ffi\",\"target\":\"aarch64-unknown-linux-gnu\",\"threads\":4},\"leaf_count\":14,\"media\":\"video\",\"missed\":0,\"missed_units\":[],\"output_root\":\"7c2a5e64a1682dc7f6ec092fa6cb459be15a16f6abbae9a455ed8590d3677b58\",\"primary_units\":7,\"receipt_bytes\":640,\"session_nonce\":\"57c5462dfdabd1b7bdd204d34ba33649c057eb535349f29f45eb8f8c7d4a7e7f\",\"stage_sets\":[],\"switches\":[],\"switches_total\":0,\"transferred\":13607,\"uncounted\":2,\"units\":14},\"class\":\"reconstruct-session\",\"issued_at\":\"2026-09-27T12:00:00Z\",\"kind\":\"claim\",\"parent_receipt_hash\":null,\"seq\":0,\"sig\":\"cd15d5bd84e19c6935c1c502b974e8fdb64b601bdc20875d411a6e5a565a239a668a8d6206ce612d36ad938292df18fe4168c81ca10c0be6f4e9e7a17057e50f\",\"signer_id\":\"did:example:sink\",\"signer_pubkey\":\"d759793bbc13a2819a827c76adb6fba8a49aee007f49f2d0992d99b825ad2c48\",\"subject\":\"64c0713cb176874607bf8670295242184b7868a9ff7c55554a5ae08de2c301c1\",\"subject_type\":\"object\"}", + "context": { + "outputs": [ + { + "unit": 0, + "layers": 1, + "decoder": 0, + "out_digest": "55f7e628ca707e2ca3159709eeb68b9000813f2916a299acd33a23e6fe012584" + }, + { + "unit": 1, + "layers": 1, + "decoder": 1, + "out_digest": "a3ee8a4b96eceb663f3d94417957d02f897fc166dc96ebe9bf447c4a36a36264" + }, + { + "unit": 2, + "layers": 1, + "decoder": 0, + "out_digest": "00576d2c4d09ef5d7aa807f9b3b1587e200dea6f6694b4da062b41aa2a5ab8af" + }, + { + "unit": 3, + "layers": 1, + "decoder": 1, + "out_digest": "26cd9b2805b604b26e08d9a461db599c4e249bfd4df41a3befb202bc6d0e0700" + }, + { + "unit": 4, + "layers": 1, + "decoder": 0, + "out_digest": "1cd1984bc553c43ee5a48fe7e182a77e60d8ef3c2b0f959ef1a0efd3813b411f" + }, + { + "unit": 5, + "layers": 1, + "decoder": 1, + "out_digest": "e4c4344155dc2c789a1df265f8064b9ae56f3e0932d85c5ceb38782c135749fc" + }, + { + "unit": 6, + "layers": 1, + "decoder": 0, + "out_digest": "95542e01dfb7d7c52f2d526bf932ee49cf081ee2bc330c42dd0715cca7deff8b" + }, + { + "unit": 7, + "layers": 1, + "decoder": 1, + "out_digest": "cf1c65a8bc3fabc40710f610dcfa9ac2604f45a6fa68f74ee2b464421647da4c" + }, + { + "unit": 8, + "layers": 1, + "decoder": 0, + "out_digest": "5c01f526973ca7dbcde1513bc7d25333954bc4164811a5f21399b6e48d89079d" + }, + { + "unit": 9, + "layers": 1, + "decoder": 1, + "out_digest": "686ff0277613c58687a493af12da86b393bcee283c6758845a2505a93d135905" + }, + { + "unit": 10, + "layers": 1, + "decoder": 0, + "out_digest": "23851d2c5e0cc5365e329fbd9c01238313ac71fd4edb4730fa7d58cc74e74823" + }, + { + "unit": 11, + "layers": 1, + "decoder": 1, + "out_digest": "66270813e69c6cffbacb67f95a9c182b2f04ce8c3b2ee4829c257227a5f4a17a" + }, + { + "unit": 12, + "layers": 1, + "decoder": 0, + "out_digest": "47c089823c210a1989895087dc4d44dc5ed8ee0453d7f2517ccce83cb686c824" + }, + { + "unit": 13, + "layers": 1, + "decoder": 1, + "out_digest": "3a1e42600a46cf28926fc9f03946a3186264cef938e207b9e159591c179fa7ed" + } + ], + "redecoded": [ + { + "index": 0, + "out_digest": "55f7e628ca707e2ca3159709eeb68b9000813f2916a299acd33a23e6fe012584" + }, + { + "index": 1, + "out_digest": "9df7f2652febf9fe462ff426af1ee3ec158bf203c59392654482b80775804556" + }, + { + "index": 2, + "out_digest": "00576d2c4d09ef5d7aa807f9b3b1587e200dea6f6694b4da062b41aa2a5ab8af" + }, + { + "index": 3, + "out_digest": "5541d29e4f230e7683ad45c081f4f325fa6216f308b1682f621b3ed279fc39f8" + }, + { + "index": 4, + "out_digest": "1cd1984bc553c43ee5a48fe7e182a77e60d8ef3c2b0f959ef1a0efd3813b411f" + }, + { + "index": 5, + "out_digest": "67754c573f1f7605becf03e65bffa704359b96917b5bc203901eb10e32182cf1" + }, + { + "index": 6, + "out_digest": "95542e01dfb7d7c52f2d526bf932ee49cf081ee2bc330c42dd0715cca7deff8b" + }, + { + "index": 7, + "out_digest": "e7f6d40664240de8fe0eea2384891d0f040db6f05dca8450533a725410bfd31f" + }, + { + "index": 8, + "out_digest": "5c01f526973ca7dbcde1513bc7d25333954bc4164811a5f21399b6e48d89079d" + }, + { + "index": 9, + "out_digest": "f3ff8b3d08e7010fb0d5f7c836dc8b5969bcc95a73ae76813443a2b70929b6bb" + }, + { + "index": 10, + "out_digest": "23851d2c5e0cc5365e329fbd9c01238313ac71fd4edb4730fa7d58cc74e74823" + }, + { + "index": 11, + "out_digest": "9469cdcb42fe46fe46e0e0bb0e10f3397dc5048a60b81467183939f1e4548f74" + }, + { + "index": 12, + "out_digest": "47c089823c210a1989895087dc4d44dc5ed8ee0453d7f2517ccce83cb686c824" + }, + { + "index": 13, + "out_digest": "eca166a3ea198bf0271543d5428c3e0323063de0d3352fbde485399d4476a92b" + } + ] + }, + "expected": { + "outcome": "accept", + "link_hash": "0227cfddb55d12762f0220686f6dae5b30208bc169f11d1fe5ad4eb18a786e00" + } + }, + { + "name": "session_tree_15", + "about": "an output tree of 15 leaves, half on a byte-exact decoder whose re-decode matches and half checked for membership only, whose re-decode does not and is not checked", + "procedure": "claim", + "receipt": "{\"body\":{\"classical_declared\":700,\"classical_source\":\"wai2-table\",\"counted_discarded\":1904,\"counted_fallback\":0,\"counted_primary\":5607,\"deadline_us\":null,\"decoders\":[{\"capability\":\"wai.video.int_hyper\",\"decoder\":\"builtin:wai@0.4.0\",\"leaves\":8,\"module_status\":null,\"path\":\"primary\",\"pin\":\"7b4371854df0aa1645ac6525b373387c0617b873d5a57748932ee0f386ea164b\",\"rendition\":0,\"tier\":\"decode-equivalence\",\"variant\":null},{\"capability\":\"wai.video.av1\",\"decoder\":\"builtin:wai@0.4.0\",\"leaves\":7,\"module_status\":null,\"path\":\"fallback\",\"pin\":null,\"rendition\":null,\"tier\":null,\"variant\":null}],\"energy\":null,\"fallback_units\":7,\"framing\":\"registered\",\"host\":{\"build\":{\"profile\":\"release\",\"target\":\"aarch64-unknown-linux-gnu\",\"toolchain\":\"rustc 1.95.0\"},\"profile\":\"native-ffi\",\"target\":\"aarch64-unknown-linux-gnu\",\"threads\":4},\"leaf_count\":15,\"media\":\"video\",\"missed\":0,\"missed_units\":[],\"output_root\":\"8a468c91a9c76ae0a3a19d27cb142af71b4017386ea4ca68c5154d6959ca2e76\",\"primary_units\":8,\"receipt_bytes\":640,\"session_nonce\":\"57c5462dfdabd1b7bdd204d34ba33649c057eb535349f29f45eb8f8c7d4a7e7f\",\"stage_sets\":[],\"switches\":[],\"switches_total\":0,\"transferred\":13607,\"uncounted\":2,\"units\":15},\"class\":\"reconstruct-session\",\"issued_at\":\"2026-09-27T12:00:00Z\",\"kind\":\"claim\",\"parent_receipt_hash\":null,\"seq\":0,\"sig\":\"ae445671f359807ac4cf739c372e41238e02fd12211d851cba4b069f6eb86bf271d8f95bd36e5b05bdf71932836301c6076547384ee4c95196a5603dc1e9df07\",\"signer_id\":\"did:example:sink\",\"signer_pubkey\":\"d759793bbc13a2819a827c76adb6fba8a49aee007f49f2d0992d99b825ad2c48\",\"subject\":\"64c0713cb176874607bf8670295242184b7868a9ff7c55554a5ae08de2c301c1\",\"subject_type\":\"object\"}", + "context": { + "outputs": [ + { + "unit": 0, + "layers": 1, + "decoder": 0, + "out_digest": "55f7e628ca707e2ca3159709eeb68b9000813f2916a299acd33a23e6fe012584" + }, + { + "unit": 1, + "layers": 1, + "decoder": 1, + "out_digest": "a3ee8a4b96eceb663f3d94417957d02f897fc166dc96ebe9bf447c4a36a36264" + }, + { + "unit": 2, + "layers": 1, + "decoder": 0, + "out_digest": "00576d2c4d09ef5d7aa807f9b3b1587e200dea6f6694b4da062b41aa2a5ab8af" + }, + { + "unit": 3, + "layers": 1, + "decoder": 1, + "out_digest": "26cd9b2805b604b26e08d9a461db599c4e249bfd4df41a3befb202bc6d0e0700" + }, + { + "unit": 4, + "layers": 1, + "decoder": 0, + "out_digest": "1cd1984bc553c43ee5a48fe7e182a77e60d8ef3c2b0f959ef1a0efd3813b411f" + }, + { + "unit": 5, + "layers": 1, + "decoder": 1, + "out_digest": "e4c4344155dc2c789a1df265f8064b9ae56f3e0932d85c5ceb38782c135749fc" + }, + { + "unit": 6, + "layers": 1, + "decoder": 0, + "out_digest": "95542e01dfb7d7c52f2d526bf932ee49cf081ee2bc330c42dd0715cca7deff8b" + }, + { + "unit": 7, + "layers": 1, + "decoder": 1, + "out_digest": "cf1c65a8bc3fabc40710f610dcfa9ac2604f45a6fa68f74ee2b464421647da4c" + }, + { + "unit": 8, + "layers": 1, + "decoder": 0, + "out_digest": "5c01f526973ca7dbcde1513bc7d25333954bc4164811a5f21399b6e48d89079d" + }, + { + "unit": 9, + "layers": 1, + "decoder": 1, + "out_digest": "686ff0277613c58687a493af12da86b393bcee283c6758845a2505a93d135905" + }, + { + "unit": 10, + "layers": 1, + "decoder": 0, + "out_digest": "23851d2c5e0cc5365e329fbd9c01238313ac71fd4edb4730fa7d58cc74e74823" + }, + { + "unit": 11, + "layers": 1, + "decoder": 1, + "out_digest": "66270813e69c6cffbacb67f95a9c182b2f04ce8c3b2ee4829c257227a5f4a17a" + }, + { + "unit": 12, + "layers": 1, + "decoder": 0, + "out_digest": "47c089823c210a1989895087dc4d44dc5ed8ee0453d7f2517ccce83cb686c824" + }, + { + "unit": 13, + "layers": 1, + "decoder": 1, + "out_digest": "3a1e42600a46cf28926fc9f03946a3186264cef938e207b9e159591c179fa7ed" + }, + { + "unit": 14, + "layers": 1, + "decoder": 0, + "out_digest": "49eac1e814988d0a60db8a709e70f4a1989819a57e26b92bdd0239c338675c58" + } + ], + "redecoded": [ + { + "index": 0, + "out_digest": "55f7e628ca707e2ca3159709eeb68b9000813f2916a299acd33a23e6fe012584" + }, + { + "index": 1, + "out_digest": "9df7f2652febf9fe462ff426af1ee3ec158bf203c59392654482b80775804556" + }, + { + "index": 2, + "out_digest": "00576d2c4d09ef5d7aa807f9b3b1587e200dea6f6694b4da062b41aa2a5ab8af" + }, + { + "index": 3, + "out_digest": "5541d29e4f230e7683ad45c081f4f325fa6216f308b1682f621b3ed279fc39f8" + }, + { + "index": 4, + "out_digest": "1cd1984bc553c43ee5a48fe7e182a77e60d8ef3c2b0f959ef1a0efd3813b411f" + }, + { + "index": 5, + "out_digest": "67754c573f1f7605becf03e65bffa704359b96917b5bc203901eb10e32182cf1" + }, + { + "index": 6, + "out_digest": "95542e01dfb7d7c52f2d526bf932ee49cf081ee2bc330c42dd0715cca7deff8b" + }, + { + "index": 7, + "out_digest": "e7f6d40664240de8fe0eea2384891d0f040db6f05dca8450533a725410bfd31f" + }, + { + "index": 8, + "out_digest": "5c01f526973ca7dbcde1513bc7d25333954bc4164811a5f21399b6e48d89079d" + }, + { + "index": 9, + "out_digest": "f3ff8b3d08e7010fb0d5f7c836dc8b5969bcc95a73ae76813443a2b70929b6bb" + }, + { + "index": 10, + "out_digest": "23851d2c5e0cc5365e329fbd9c01238313ac71fd4edb4730fa7d58cc74e74823" + }, + { + "index": 11, + "out_digest": "9469cdcb42fe46fe46e0e0bb0e10f3397dc5048a60b81467183939f1e4548f74" + }, + { + "index": 12, + "out_digest": "47c089823c210a1989895087dc4d44dc5ed8ee0453d7f2517ccce83cb686c824" + }, + { + "index": 13, + "out_digest": "eca166a3ea198bf0271543d5428c3e0323063de0d3352fbde485399d4476a92b" + }, + { + "index": 14, + "out_digest": "49eac1e814988d0a60db8a709e70f4a1989819a57e26b92bdd0239c338675c58" + } + ] + }, + "expected": { + "outcome": "accept", + "link_hash": "3028493fbd69a7cb2f7ab94f3ccd83d82062b11f70d10fd1dd96fe867b57f2ae" + } + }, + { + "name": "session_tree_16", + "about": "an output tree of 16 leaves, half on a byte-exact decoder whose re-decode matches and half checked for membership only, whose re-decode does not and is not checked", + "procedure": "claim", + "receipt": "{\"body\":{\"classical_declared\":700,\"classical_source\":\"wai2-table\",\"counted_discarded\":1904,\"counted_fallback\":0,\"counted_primary\":5607,\"deadline_us\":null,\"decoders\":[{\"capability\":\"wai.video.int_hyper\",\"decoder\":\"builtin:wai@0.4.0\",\"leaves\":8,\"module_status\":null,\"path\":\"primary\",\"pin\":\"7b4371854df0aa1645ac6525b373387c0617b873d5a57748932ee0f386ea164b\",\"rendition\":0,\"tier\":\"decode-equivalence\",\"variant\":null},{\"capability\":\"wai.video.av1\",\"decoder\":\"builtin:wai@0.4.0\",\"leaves\":8,\"module_status\":null,\"path\":\"fallback\",\"pin\":null,\"rendition\":null,\"tier\":null,\"variant\":null}],\"energy\":null,\"fallback_units\":8,\"framing\":\"registered\",\"host\":{\"build\":{\"profile\":\"release\",\"target\":\"aarch64-unknown-linux-gnu\",\"toolchain\":\"rustc 1.95.0\"},\"profile\":\"native-ffi\",\"target\":\"aarch64-unknown-linux-gnu\",\"threads\":4},\"leaf_count\":16,\"media\":\"video\",\"missed\":0,\"missed_units\":[],\"output_root\":\"52350be50c241f090a8f21ff34d785997262a2f5929229fe09c9d67eb544cb31\",\"primary_units\":8,\"receipt_bytes\":640,\"session_nonce\":\"57c5462dfdabd1b7bdd204d34ba33649c057eb535349f29f45eb8f8c7d4a7e7f\",\"stage_sets\":[],\"switches\":[],\"switches_total\":0,\"transferred\":13607,\"uncounted\":2,\"units\":16},\"class\":\"reconstruct-session\",\"issued_at\":\"2026-09-27T12:00:00Z\",\"kind\":\"claim\",\"parent_receipt_hash\":null,\"seq\":0,\"sig\":\"59230c4fd4a855447be2c3e81e389ea26a2ea91628cbd63eae24c29ed1e156ac49864864f1e5e6e60dc146dcbbad6bc264d4c88066d08f1776b827b5ee52550b\",\"signer_id\":\"did:example:sink\",\"signer_pubkey\":\"d759793bbc13a2819a827c76adb6fba8a49aee007f49f2d0992d99b825ad2c48\",\"subject\":\"64c0713cb176874607bf8670295242184b7868a9ff7c55554a5ae08de2c301c1\",\"subject_type\":\"object\"}", + "context": { + "outputs": [ + { + "unit": 0, + "layers": 1, + "decoder": 0, + "out_digest": "55f7e628ca707e2ca3159709eeb68b9000813f2916a299acd33a23e6fe012584" + }, + { + "unit": 1, + "layers": 1, + "decoder": 1, + "out_digest": "a3ee8a4b96eceb663f3d94417957d02f897fc166dc96ebe9bf447c4a36a36264" + }, + { + "unit": 2, + "layers": 1, + "decoder": 0, + "out_digest": "00576d2c4d09ef5d7aa807f9b3b1587e200dea6f6694b4da062b41aa2a5ab8af" + }, + { + "unit": 3, + "layers": 1, + "decoder": 1, + "out_digest": "26cd9b2805b604b26e08d9a461db599c4e249bfd4df41a3befb202bc6d0e0700" + }, + { + "unit": 4, + "layers": 1, + "decoder": 0, + "out_digest": "1cd1984bc553c43ee5a48fe7e182a77e60d8ef3c2b0f959ef1a0efd3813b411f" + }, + { + "unit": 5, + "layers": 1, + "decoder": 1, + "out_digest": "e4c4344155dc2c789a1df265f8064b9ae56f3e0932d85c5ceb38782c135749fc" + }, + { + "unit": 6, + "layers": 1, + "decoder": 0, + "out_digest": "95542e01dfb7d7c52f2d526bf932ee49cf081ee2bc330c42dd0715cca7deff8b" + }, + { + "unit": 7, + "layers": 1, + "decoder": 1, + "out_digest": "cf1c65a8bc3fabc40710f610dcfa9ac2604f45a6fa68f74ee2b464421647da4c" + }, + { + "unit": 8, + "layers": 1, + "decoder": 0, + "out_digest": "5c01f526973ca7dbcde1513bc7d25333954bc4164811a5f21399b6e48d89079d" + }, + { + "unit": 9, + "layers": 1, + "decoder": 1, + "out_digest": "686ff0277613c58687a493af12da86b393bcee283c6758845a2505a93d135905" + }, + { + "unit": 10, + "layers": 1, + "decoder": 0, + "out_digest": "23851d2c5e0cc5365e329fbd9c01238313ac71fd4edb4730fa7d58cc74e74823" + }, + { + "unit": 11, + "layers": 1, + "decoder": 1, + "out_digest": "66270813e69c6cffbacb67f95a9c182b2f04ce8c3b2ee4829c257227a5f4a17a" + }, + { + "unit": 12, + "layers": 1, + "decoder": 0, + "out_digest": "47c089823c210a1989895087dc4d44dc5ed8ee0453d7f2517ccce83cb686c824" + }, + { + "unit": 13, + "layers": 1, + "decoder": 1, + "out_digest": "3a1e42600a46cf28926fc9f03946a3186264cef938e207b9e159591c179fa7ed" + }, + { + "unit": 14, + "layers": 1, + "decoder": 0, + "out_digest": "49eac1e814988d0a60db8a709e70f4a1989819a57e26b92bdd0239c338675c58" + }, + { + "unit": 15, + "layers": 1, + "decoder": 1, + "out_digest": "cd3ac56e7dc49f235a245024c0c560cc19ba73fcc0dfb1d38ff9f58bb180d5db" + } + ], + "redecoded": [ + { + "index": 0, + "out_digest": "55f7e628ca707e2ca3159709eeb68b9000813f2916a299acd33a23e6fe012584" + }, + { + "index": 1, + "out_digest": "9df7f2652febf9fe462ff426af1ee3ec158bf203c59392654482b80775804556" + }, + { + "index": 2, + "out_digest": "00576d2c4d09ef5d7aa807f9b3b1587e200dea6f6694b4da062b41aa2a5ab8af" + }, + { + "index": 3, + "out_digest": "5541d29e4f230e7683ad45c081f4f325fa6216f308b1682f621b3ed279fc39f8" + }, + { + "index": 4, + "out_digest": "1cd1984bc553c43ee5a48fe7e182a77e60d8ef3c2b0f959ef1a0efd3813b411f" + }, + { + "index": 5, + "out_digest": "67754c573f1f7605becf03e65bffa704359b96917b5bc203901eb10e32182cf1" + }, + { + "index": 6, + "out_digest": "95542e01dfb7d7c52f2d526bf932ee49cf081ee2bc330c42dd0715cca7deff8b" + }, + { + "index": 7, + "out_digest": "e7f6d40664240de8fe0eea2384891d0f040db6f05dca8450533a725410bfd31f" + }, + { + "index": 8, + "out_digest": "5c01f526973ca7dbcde1513bc7d25333954bc4164811a5f21399b6e48d89079d" + }, + { + "index": 9, + "out_digest": "f3ff8b3d08e7010fb0d5f7c836dc8b5969bcc95a73ae76813443a2b70929b6bb" + }, + { + "index": 10, + "out_digest": "23851d2c5e0cc5365e329fbd9c01238313ac71fd4edb4730fa7d58cc74e74823" + }, + { + "index": 11, + "out_digest": "9469cdcb42fe46fe46e0e0bb0e10f3397dc5048a60b81467183939f1e4548f74" + }, + { + "index": 12, + "out_digest": "47c089823c210a1989895087dc4d44dc5ed8ee0453d7f2517ccce83cb686c824" + }, + { + "index": 13, + "out_digest": "eca166a3ea198bf0271543d5428c3e0323063de0d3352fbde485399d4476a92b" + }, + { + "index": 14, + "out_digest": "49eac1e814988d0a60db8a709e70f4a1989819a57e26b92bdd0239c338675c58" + }, + { + "index": 15, + "out_digest": "fd7ac5bfaf32d59c57faba74ff87b0a09aae703323a147fef03adf7b2761cb1d" + } + ] + }, + "expected": { + "outcome": "accept", + "link_hash": "c38db8c20998af5ca0084b83df1a2ad4432d69f07931f52473b2be7bb8038fc9" + } + }, + { + "name": "session_tree_17", + "about": "an output tree of 17 leaves, half on a byte-exact decoder whose re-decode matches and half checked for membership only, whose re-decode does not and is not checked", + "procedure": "claim", + "receipt": "{\"body\":{\"classical_declared\":700,\"classical_source\":\"wai2-table\",\"counted_discarded\":1904,\"counted_fallback\":0,\"counted_primary\":5607,\"deadline_us\":null,\"decoders\":[{\"capability\":\"wai.video.int_hyper\",\"decoder\":\"builtin:wai@0.4.0\",\"leaves\":9,\"module_status\":null,\"path\":\"primary\",\"pin\":\"7b4371854df0aa1645ac6525b373387c0617b873d5a57748932ee0f386ea164b\",\"rendition\":0,\"tier\":\"decode-equivalence\",\"variant\":null},{\"capability\":\"wai.video.av1\",\"decoder\":\"builtin:wai@0.4.0\",\"leaves\":8,\"module_status\":null,\"path\":\"fallback\",\"pin\":null,\"rendition\":null,\"tier\":null,\"variant\":null}],\"energy\":null,\"fallback_units\":8,\"framing\":\"registered\",\"host\":{\"build\":{\"profile\":\"release\",\"target\":\"aarch64-unknown-linux-gnu\",\"toolchain\":\"rustc 1.95.0\"},\"profile\":\"native-ffi\",\"target\":\"aarch64-unknown-linux-gnu\",\"threads\":4},\"leaf_count\":17,\"media\":\"video\",\"missed\":0,\"missed_units\":[],\"output_root\":\"9213172e08365dda05da08832c707b5e91945fb31e4897d224c92c4f0cf0df48\",\"primary_units\":9,\"receipt_bytes\":640,\"session_nonce\":\"57c5462dfdabd1b7bdd204d34ba33649c057eb535349f29f45eb8f8c7d4a7e7f\",\"stage_sets\":[],\"switches\":[],\"switches_total\":0,\"transferred\":13607,\"uncounted\":2,\"units\":17},\"class\":\"reconstruct-session\",\"issued_at\":\"2026-09-27T12:00:00Z\",\"kind\":\"claim\",\"parent_receipt_hash\":null,\"seq\":0,\"sig\":\"3cdfaa05eb36472f188926c0a2186e70e5ec002816bf3496e59c61c2bb543d3c4c674fd02ad717cc221788d92d5e4b6964b21c249bb3f6a3a52e9c081309cc09\",\"signer_id\":\"did:example:sink\",\"signer_pubkey\":\"d759793bbc13a2819a827c76adb6fba8a49aee007f49f2d0992d99b825ad2c48\",\"subject\":\"64c0713cb176874607bf8670295242184b7868a9ff7c55554a5ae08de2c301c1\",\"subject_type\":\"object\"}", + "context": { + "outputs": [ + { + "unit": 0, + "layers": 1, + "decoder": 0, + "out_digest": "55f7e628ca707e2ca3159709eeb68b9000813f2916a299acd33a23e6fe012584" + }, + { + "unit": 1, + "layers": 1, + "decoder": 1, + "out_digest": "a3ee8a4b96eceb663f3d94417957d02f897fc166dc96ebe9bf447c4a36a36264" + }, + { + "unit": 2, + "layers": 1, + "decoder": 0, + "out_digest": "00576d2c4d09ef5d7aa807f9b3b1587e200dea6f6694b4da062b41aa2a5ab8af" + }, + { + "unit": 3, + "layers": 1, + "decoder": 1, + "out_digest": "26cd9b2805b604b26e08d9a461db599c4e249bfd4df41a3befb202bc6d0e0700" + }, + { + "unit": 4, + "layers": 1, + "decoder": 0, + "out_digest": "1cd1984bc553c43ee5a48fe7e182a77e60d8ef3c2b0f959ef1a0efd3813b411f" + }, + { + "unit": 5, + "layers": 1, + "decoder": 1, + "out_digest": "e4c4344155dc2c789a1df265f8064b9ae56f3e0932d85c5ceb38782c135749fc" + }, + { + "unit": 6, + "layers": 1, + "decoder": 0, + "out_digest": "95542e01dfb7d7c52f2d526bf932ee49cf081ee2bc330c42dd0715cca7deff8b" + }, + { + "unit": 7, + "layers": 1, + "decoder": 1, + "out_digest": "cf1c65a8bc3fabc40710f610dcfa9ac2604f45a6fa68f74ee2b464421647da4c" + }, + { + "unit": 8, + "layers": 1, + "decoder": 0, + "out_digest": "5c01f526973ca7dbcde1513bc7d25333954bc4164811a5f21399b6e48d89079d" + }, + { + "unit": 9, + "layers": 1, + "decoder": 1, + "out_digest": "686ff0277613c58687a493af12da86b393bcee283c6758845a2505a93d135905" + }, + { + "unit": 10, + "layers": 1, + "decoder": 0, + "out_digest": "23851d2c5e0cc5365e329fbd9c01238313ac71fd4edb4730fa7d58cc74e74823" + }, + { + "unit": 11, + "layers": 1, + "decoder": 1, + "out_digest": "66270813e69c6cffbacb67f95a9c182b2f04ce8c3b2ee4829c257227a5f4a17a" + }, + { + "unit": 12, + "layers": 1, + "decoder": 0, + "out_digest": "47c089823c210a1989895087dc4d44dc5ed8ee0453d7f2517ccce83cb686c824" + }, + { + "unit": 13, + "layers": 1, + "decoder": 1, + "out_digest": "3a1e42600a46cf28926fc9f03946a3186264cef938e207b9e159591c179fa7ed" + }, + { + "unit": 14, + "layers": 1, + "decoder": 0, + "out_digest": "49eac1e814988d0a60db8a709e70f4a1989819a57e26b92bdd0239c338675c58" + }, + { + "unit": 15, + "layers": 1, + "decoder": 1, + "out_digest": "cd3ac56e7dc49f235a245024c0c560cc19ba73fcc0dfb1d38ff9f58bb180d5db" + }, + { + "unit": 16, + "layers": 1, + "decoder": 0, + "out_digest": "b3c7f2ac61734e3390450d0f34c70f733b20db0c29d8ea634c0fc0a8638f2258" + } + ], + "redecoded": [ + { + "index": 0, + "out_digest": "55f7e628ca707e2ca3159709eeb68b9000813f2916a299acd33a23e6fe012584" + }, + { + "index": 1, + "out_digest": "9df7f2652febf9fe462ff426af1ee3ec158bf203c59392654482b80775804556" + }, + { + "index": 2, + "out_digest": "00576d2c4d09ef5d7aa807f9b3b1587e200dea6f6694b4da062b41aa2a5ab8af" + }, + { + "index": 3, + "out_digest": "5541d29e4f230e7683ad45c081f4f325fa6216f308b1682f621b3ed279fc39f8" + }, + { + "index": 4, + "out_digest": "1cd1984bc553c43ee5a48fe7e182a77e60d8ef3c2b0f959ef1a0efd3813b411f" + }, + { + "index": 5, + "out_digest": "67754c573f1f7605becf03e65bffa704359b96917b5bc203901eb10e32182cf1" + }, + { + "index": 6, + "out_digest": "95542e01dfb7d7c52f2d526bf932ee49cf081ee2bc330c42dd0715cca7deff8b" + }, + { + "index": 7, + "out_digest": "e7f6d40664240de8fe0eea2384891d0f040db6f05dca8450533a725410bfd31f" + }, + { + "index": 8, + "out_digest": "5c01f526973ca7dbcde1513bc7d25333954bc4164811a5f21399b6e48d89079d" + }, + { + "index": 9, + "out_digest": "f3ff8b3d08e7010fb0d5f7c836dc8b5969bcc95a73ae76813443a2b70929b6bb" + }, + { + "index": 10, + "out_digest": "23851d2c5e0cc5365e329fbd9c01238313ac71fd4edb4730fa7d58cc74e74823" + }, + { + "index": 11, + "out_digest": "9469cdcb42fe46fe46e0e0bb0e10f3397dc5048a60b81467183939f1e4548f74" + }, + { + "index": 12, + "out_digest": "47c089823c210a1989895087dc4d44dc5ed8ee0453d7f2517ccce83cb686c824" + }, + { + "index": 13, + "out_digest": "eca166a3ea198bf0271543d5428c3e0323063de0d3352fbde485399d4476a92b" + }, + { + "index": 14, + "out_digest": "49eac1e814988d0a60db8a709e70f4a1989819a57e26b92bdd0239c338675c58" + }, + { + "index": 15, + "out_digest": "fd7ac5bfaf32d59c57faba74ff87b0a09aae703323a147fef03adf7b2761cb1d" + }, + { + "index": 16, + "out_digest": "b3c7f2ac61734e3390450d0f34c70f733b20db0c29d8ea634c0fc0a8638f2258" + } + ] + }, + "expected": { + "outcome": "accept", + "link_hash": "47577834d335a177d66012abafa365cd8657fca35484f5a369c4c20683b75421" + } + }, + { + "name": "session_tree_18", + "about": "an output tree of 18 leaves, half on a byte-exact decoder whose re-decode matches and half checked for membership only, whose re-decode does not and is not checked", + "procedure": "claim", + "receipt": "{\"body\":{\"classical_declared\":700,\"classical_source\":\"wai2-table\",\"counted_discarded\":1904,\"counted_fallback\":0,\"counted_primary\":5607,\"deadline_us\":null,\"decoders\":[{\"capability\":\"wai.video.int_hyper\",\"decoder\":\"builtin:wai@0.4.0\",\"leaves\":9,\"module_status\":null,\"path\":\"primary\",\"pin\":\"7b4371854df0aa1645ac6525b373387c0617b873d5a57748932ee0f386ea164b\",\"rendition\":0,\"tier\":\"decode-equivalence\",\"variant\":null},{\"capability\":\"wai.video.av1\",\"decoder\":\"builtin:wai@0.4.0\",\"leaves\":9,\"module_status\":null,\"path\":\"fallback\",\"pin\":null,\"rendition\":null,\"tier\":null,\"variant\":null}],\"energy\":null,\"fallback_units\":9,\"framing\":\"registered\",\"host\":{\"build\":{\"profile\":\"release\",\"target\":\"aarch64-unknown-linux-gnu\",\"toolchain\":\"rustc 1.95.0\"},\"profile\":\"native-ffi\",\"target\":\"aarch64-unknown-linux-gnu\",\"threads\":4},\"leaf_count\":18,\"media\":\"video\",\"missed\":0,\"missed_units\":[],\"output_root\":\"6d2512f3fd0a2858a8bcd10eee659d4203ec9ba40354664f27a1d53f78436937\",\"primary_units\":9,\"receipt_bytes\":640,\"session_nonce\":\"57c5462dfdabd1b7bdd204d34ba33649c057eb535349f29f45eb8f8c7d4a7e7f\",\"stage_sets\":[],\"switches\":[],\"switches_total\":0,\"transferred\":13607,\"uncounted\":2,\"units\":18},\"class\":\"reconstruct-session\",\"issued_at\":\"2026-09-27T12:00:00Z\",\"kind\":\"claim\",\"parent_receipt_hash\":null,\"seq\":0,\"sig\":\"d0d5fe214377948c7eab24067fa17dd3e0e6e6e73fc74a2c884a0785129238bc0cfc68eab9b77cbb42faf52ccad4e8119a960365b85af31331fc2020cf5d5300\",\"signer_id\":\"did:example:sink\",\"signer_pubkey\":\"d759793bbc13a2819a827c76adb6fba8a49aee007f49f2d0992d99b825ad2c48\",\"subject\":\"64c0713cb176874607bf8670295242184b7868a9ff7c55554a5ae08de2c301c1\",\"subject_type\":\"object\"}", + "context": { + "outputs": [ + { + "unit": 0, + "layers": 1, + "decoder": 0, + "out_digest": "55f7e628ca707e2ca3159709eeb68b9000813f2916a299acd33a23e6fe012584" + }, + { + "unit": 1, + "layers": 1, + "decoder": 1, + "out_digest": "a3ee8a4b96eceb663f3d94417957d02f897fc166dc96ebe9bf447c4a36a36264" + }, + { + "unit": 2, + "layers": 1, + "decoder": 0, + "out_digest": "00576d2c4d09ef5d7aa807f9b3b1587e200dea6f6694b4da062b41aa2a5ab8af" + }, + { + "unit": 3, + "layers": 1, + "decoder": 1, + "out_digest": "26cd9b2805b604b26e08d9a461db599c4e249bfd4df41a3befb202bc6d0e0700" + }, + { + "unit": 4, + "layers": 1, + "decoder": 0, + "out_digest": "1cd1984bc553c43ee5a48fe7e182a77e60d8ef3c2b0f959ef1a0efd3813b411f" + }, + { + "unit": 5, + "layers": 1, + "decoder": 1, + "out_digest": "e4c4344155dc2c789a1df265f8064b9ae56f3e0932d85c5ceb38782c135749fc" + }, + { + "unit": 6, + "layers": 1, + "decoder": 0, + "out_digest": "95542e01dfb7d7c52f2d526bf932ee49cf081ee2bc330c42dd0715cca7deff8b" + }, + { + "unit": 7, + "layers": 1, + "decoder": 1, + "out_digest": "cf1c65a8bc3fabc40710f610dcfa9ac2604f45a6fa68f74ee2b464421647da4c" + }, + { + "unit": 8, + "layers": 1, + "decoder": 0, + "out_digest": "5c01f526973ca7dbcde1513bc7d25333954bc4164811a5f21399b6e48d89079d" + }, + { + "unit": 9, + "layers": 1, + "decoder": 1, + "out_digest": "686ff0277613c58687a493af12da86b393bcee283c6758845a2505a93d135905" + }, + { + "unit": 10, + "layers": 1, + "decoder": 0, + "out_digest": "23851d2c5e0cc5365e329fbd9c01238313ac71fd4edb4730fa7d58cc74e74823" + }, + { + "unit": 11, + "layers": 1, + "decoder": 1, + "out_digest": "66270813e69c6cffbacb67f95a9c182b2f04ce8c3b2ee4829c257227a5f4a17a" + }, + { + "unit": 12, + "layers": 1, + "decoder": 0, + "out_digest": "47c089823c210a1989895087dc4d44dc5ed8ee0453d7f2517ccce83cb686c824" + }, + { + "unit": 13, + "layers": 1, + "decoder": 1, + "out_digest": "3a1e42600a46cf28926fc9f03946a3186264cef938e207b9e159591c179fa7ed" + }, + { + "unit": 14, + "layers": 1, + "decoder": 0, + "out_digest": "49eac1e814988d0a60db8a709e70f4a1989819a57e26b92bdd0239c338675c58" + }, + { + "unit": 15, + "layers": 1, + "decoder": 1, + "out_digest": "cd3ac56e7dc49f235a245024c0c560cc19ba73fcc0dfb1d38ff9f58bb180d5db" + }, + { + "unit": 16, + "layers": 1, + "decoder": 0, + "out_digest": "b3c7f2ac61734e3390450d0f34c70f733b20db0c29d8ea634c0fc0a8638f2258" + }, + { + "unit": 17, + "layers": 1, + "decoder": 1, + "out_digest": "64b919c5441af6df04b8563a34fe9fe57b84e802b1856a98e1edafc328e809d6" + } + ], + "redecoded": [ + { + "index": 0, + "out_digest": "55f7e628ca707e2ca3159709eeb68b9000813f2916a299acd33a23e6fe012584" + }, + { + "index": 1, + "out_digest": "9df7f2652febf9fe462ff426af1ee3ec158bf203c59392654482b80775804556" + }, + { + "index": 2, + "out_digest": "00576d2c4d09ef5d7aa807f9b3b1587e200dea6f6694b4da062b41aa2a5ab8af" + }, + { + "index": 3, + "out_digest": "5541d29e4f230e7683ad45c081f4f325fa6216f308b1682f621b3ed279fc39f8" + }, + { + "index": 4, + "out_digest": "1cd1984bc553c43ee5a48fe7e182a77e60d8ef3c2b0f959ef1a0efd3813b411f" + }, + { + "index": 5, + "out_digest": "67754c573f1f7605becf03e65bffa704359b96917b5bc203901eb10e32182cf1" + }, + { + "index": 6, + "out_digest": "95542e01dfb7d7c52f2d526bf932ee49cf081ee2bc330c42dd0715cca7deff8b" + }, + { + "index": 7, + "out_digest": "e7f6d40664240de8fe0eea2384891d0f040db6f05dca8450533a725410bfd31f" + }, + { + "index": 8, + "out_digest": "5c01f526973ca7dbcde1513bc7d25333954bc4164811a5f21399b6e48d89079d" + }, + { + "index": 9, + "out_digest": "f3ff8b3d08e7010fb0d5f7c836dc8b5969bcc95a73ae76813443a2b70929b6bb" + }, + { + "index": 10, + "out_digest": "23851d2c5e0cc5365e329fbd9c01238313ac71fd4edb4730fa7d58cc74e74823" + }, + { + "index": 11, + "out_digest": "9469cdcb42fe46fe46e0e0bb0e10f3397dc5048a60b81467183939f1e4548f74" + }, + { + "index": 12, + "out_digest": "47c089823c210a1989895087dc4d44dc5ed8ee0453d7f2517ccce83cb686c824" + }, + { + "index": 13, + "out_digest": "eca166a3ea198bf0271543d5428c3e0323063de0d3352fbde485399d4476a92b" + }, + { + "index": 14, + "out_digest": "49eac1e814988d0a60db8a709e70f4a1989819a57e26b92bdd0239c338675c58" + }, + { + "index": 15, + "out_digest": "fd7ac5bfaf32d59c57faba74ff87b0a09aae703323a147fef03adf7b2761cb1d" + }, + { + "index": 16, + "out_digest": "b3c7f2ac61734e3390450d0f34c70f733b20db0c29d8ea634c0fc0a8638f2258" + }, + { + "index": 17, + "out_digest": "b7988f6a6e8844ff5ec686f9290b0b4ab0c5c3c028b5e9be116e12821b851534" + } + ] + }, + "expected": { + "outcome": "accept", + "link_hash": "1fe712bcf0e69a335864ad159e2108a0b54d1d2b425b4042c0a992b739de409a" + } + }, + { + "name": "session_tree_19", + "about": "an output tree of 19 leaves, half on a byte-exact decoder whose re-decode matches and half checked for membership only, whose re-decode does not and is not checked", + "procedure": "claim", + "receipt": "{\"body\":{\"classical_declared\":700,\"classical_source\":\"wai2-table\",\"counted_discarded\":1904,\"counted_fallback\":0,\"counted_primary\":5607,\"deadline_us\":null,\"decoders\":[{\"capability\":\"wai.video.int_hyper\",\"decoder\":\"builtin:wai@0.4.0\",\"leaves\":10,\"module_status\":null,\"path\":\"primary\",\"pin\":\"7b4371854df0aa1645ac6525b373387c0617b873d5a57748932ee0f386ea164b\",\"rendition\":0,\"tier\":\"decode-equivalence\",\"variant\":null},{\"capability\":\"wai.video.av1\",\"decoder\":\"builtin:wai@0.4.0\",\"leaves\":9,\"module_status\":null,\"path\":\"fallback\",\"pin\":null,\"rendition\":null,\"tier\":null,\"variant\":null}],\"energy\":null,\"fallback_units\":9,\"framing\":\"registered\",\"host\":{\"build\":{\"profile\":\"release\",\"target\":\"aarch64-unknown-linux-gnu\",\"toolchain\":\"rustc 1.95.0\"},\"profile\":\"native-ffi\",\"target\":\"aarch64-unknown-linux-gnu\",\"threads\":4},\"leaf_count\":19,\"media\":\"video\",\"missed\":0,\"missed_units\":[],\"output_root\":\"e2e4a4d505c8728811bb94c9120e92e0f71c60e8c9e37d923a3d8ea47acdbc6f\",\"primary_units\":10,\"receipt_bytes\":640,\"session_nonce\":\"57c5462dfdabd1b7bdd204d34ba33649c057eb535349f29f45eb8f8c7d4a7e7f\",\"stage_sets\":[],\"switches\":[],\"switches_total\":0,\"transferred\":13607,\"uncounted\":2,\"units\":19},\"class\":\"reconstruct-session\",\"issued_at\":\"2026-09-27T12:00:00Z\",\"kind\":\"claim\",\"parent_receipt_hash\":null,\"seq\":0,\"sig\":\"a6aaac3b1f43463440fc472a5937507901d53409e8a8e04b1c83b2be4bd9567833118034ee3a85c0bad3e1a3e7d27714107bd8c0fcaa27d5d90e67f2f1cc7906\",\"signer_id\":\"did:example:sink\",\"signer_pubkey\":\"d759793bbc13a2819a827c76adb6fba8a49aee007f49f2d0992d99b825ad2c48\",\"subject\":\"64c0713cb176874607bf8670295242184b7868a9ff7c55554a5ae08de2c301c1\",\"subject_type\":\"object\"}", + "context": { + "outputs": [ + { + "unit": 0, + "layers": 1, + "decoder": 0, + "out_digest": "55f7e628ca707e2ca3159709eeb68b9000813f2916a299acd33a23e6fe012584" + }, + { + "unit": 1, + "layers": 1, + "decoder": 1, + "out_digest": "a3ee8a4b96eceb663f3d94417957d02f897fc166dc96ebe9bf447c4a36a36264" + }, + { + "unit": 2, + "layers": 1, + "decoder": 0, + "out_digest": "00576d2c4d09ef5d7aa807f9b3b1587e200dea6f6694b4da062b41aa2a5ab8af" + }, + { + "unit": 3, + "layers": 1, + "decoder": 1, + "out_digest": "26cd9b2805b604b26e08d9a461db599c4e249bfd4df41a3befb202bc6d0e0700" + }, + { + "unit": 4, + "layers": 1, + "decoder": 0, + "out_digest": "1cd1984bc553c43ee5a48fe7e182a77e60d8ef3c2b0f959ef1a0efd3813b411f" + }, + { + "unit": 5, + "layers": 1, + "decoder": 1, + "out_digest": "e4c4344155dc2c789a1df265f8064b9ae56f3e0932d85c5ceb38782c135749fc" + }, + { + "unit": 6, + "layers": 1, + "decoder": 0, + "out_digest": "95542e01dfb7d7c52f2d526bf932ee49cf081ee2bc330c42dd0715cca7deff8b" + }, + { + "unit": 7, + "layers": 1, + "decoder": 1, + "out_digest": "cf1c65a8bc3fabc40710f610dcfa9ac2604f45a6fa68f74ee2b464421647da4c" + }, + { + "unit": 8, + "layers": 1, + "decoder": 0, + "out_digest": "5c01f526973ca7dbcde1513bc7d25333954bc4164811a5f21399b6e48d89079d" + }, + { + "unit": 9, + "layers": 1, + "decoder": 1, + "out_digest": "686ff0277613c58687a493af12da86b393bcee283c6758845a2505a93d135905" + }, + { + "unit": 10, + "layers": 1, + "decoder": 0, + "out_digest": "23851d2c5e0cc5365e329fbd9c01238313ac71fd4edb4730fa7d58cc74e74823" + }, + { + "unit": 11, + "layers": 1, + "decoder": 1, + "out_digest": "66270813e69c6cffbacb67f95a9c182b2f04ce8c3b2ee4829c257227a5f4a17a" + }, + { + "unit": 12, + "layers": 1, + "decoder": 0, + "out_digest": "47c089823c210a1989895087dc4d44dc5ed8ee0453d7f2517ccce83cb686c824" + }, + { + "unit": 13, + "layers": 1, + "decoder": 1, + "out_digest": "3a1e42600a46cf28926fc9f03946a3186264cef938e207b9e159591c179fa7ed" + }, + { + "unit": 14, + "layers": 1, + "decoder": 0, + "out_digest": "49eac1e814988d0a60db8a709e70f4a1989819a57e26b92bdd0239c338675c58" + }, + { + "unit": 15, + "layers": 1, + "decoder": 1, + "out_digest": "cd3ac56e7dc49f235a245024c0c560cc19ba73fcc0dfb1d38ff9f58bb180d5db" + }, + { + "unit": 16, + "layers": 1, + "decoder": 0, + "out_digest": "b3c7f2ac61734e3390450d0f34c70f733b20db0c29d8ea634c0fc0a8638f2258" + }, + { + "unit": 17, + "layers": 1, + "decoder": 1, + "out_digest": "64b919c5441af6df04b8563a34fe9fe57b84e802b1856a98e1edafc328e809d6" + }, + { + "unit": 18, + "layers": 1, + "decoder": 0, + "out_digest": "e120f02a7fffc970d4a82e4afa8c7d29a00b06a10a7d9fcbf49edacff256ed1d" + } + ], + "redecoded": [ + { + "index": 0, + "out_digest": "55f7e628ca707e2ca3159709eeb68b9000813f2916a299acd33a23e6fe012584" + }, + { + "index": 1, + "out_digest": "9df7f2652febf9fe462ff426af1ee3ec158bf203c59392654482b80775804556" + }, + { + "index": 2, + "out_digest": "00576d2c4d09ef5d7aa807f9b3b1587e200dea6f6694b4da062b41aa2a5ab8af" + }, + { + "index": 3, + "out_digest": "5541d29e4f230e7683ad45c081f4f325fa6216f308b1682f621b3ed279fc39f8" + }, + { + "index": 4, + "out_digest": "1cd1984bc553c43ee5a48fe7e182a77e60d8ef3c2b0f959ef1a0efd3813b411f" + }, + { + "index": 5, + "out_digest": "67754c573f1f7605becf03e65bffa704359b96917b5bc203901eb10e32182cf1" + }, + { + "index": 6, + "out_digest": "95542e01dfb7d7c52f2d526bf932ee49cf081ee2bc330c42dd0715cca7deff8b" + }, + { + "index": 7, + "out_digest": "e7f6d40664240de8fe0eea2384891d0f040db6f05dca8450533a725410bfd31f" + }, + { + "index": 8, + "out_digest": "5c01f526973ca7dbcde1513bc7d25333954bc4164811a5f21399b6e48d89079d" + }, + { + "index": 9, + "out_digest": "f3ff8b3d08e7010fb0d5f7c836dc8b5969bcc95a73ae76813443a2b70929b6bb" + }, + { + "index": 10, + "out_digest": "23851d2c5e0cc5365e329fbd9c01238313ac71fd4edb4730fa7d58cc74e74823" + }, + { + "index": 11, + "out_digest": "9469cdcb42fe46fe46e0e0bb0e10f3397dc5048a60b81467183939f1e4548f74" + }, + { + "index": 12, + "out_digest": "47c089823c210a1989895087dc4d44dc5ed8ee0453d7f2517ccce83cb686c824" + }, + { + "index": 13, + "out_digest": "eca166a3ea198bf0271543d5428c3e0323063de0d3352fbde485399d4476a92b" + }, + { + "index": 14, + "out_digest": "49eac1e814988d0a60db8a709e70f4a1989819a57e26b92bdd0239c338675c58" + }, + { + "index": 15, + "out_digest": "fd7ac5bfaf32d59c57faba74ff87b0a09aae703323a147fef03adf7b2761cb1d" + }, + { + "index": 16, + "out_digest": "b3c7f2ac61734e3390450d0f34c70f733b20db0c29d8ea634c0fc0a8638f2258" + }, + { + "index": 17, + "out_digest": "b7988f6a6e8844ff5ec686f9290b0b4ab0c5c3c028b5e9be116e12821b851534" + }, + { + "index": 18, + "out_digest": "e120f02a7fffc970d4a82e4afa8c7d29a00b06a10a7d9fcbf49edacff256ed1d" + } + ] + }, + "expected": { + "outcome": "accept", + "link_hash": "8a8428fb5e40f06d3d4363ce398650651c50ea877d066c810186944fb5f584b2" + } + }, + { + "name": "session_tree_20", + "about": "an output tree of 20 leaves, half on a byte-exact decoder whose re-decode matches and half checked for membership only, whose re-decode does not and is not checked", + "procedure": "claim", + "receipt": "{\"body\":{\"classical_declared\":700,\"classical_source\":\"wai2-table\",\"counted_discarded\":1904,\"counted_fallback\":0,\"counted_primary\":5607,\"deadline_us\":null,\"decoders\":[{\"capability\":\"wai.video.int_hyper\",\"decoder\":\"builtin:wai@0.4.0\",\"leaves\":10,\"module_status\":null,\"path\":\"primary\",\"pin\":\"7b4371854df0aa1645ac6525b373387c0617b873d5a57748932ee0f386ea164b\",\"rendition\":0,\"tier\":\"decode-equivalence\",\"variant\":null},{\"capability\":\"wai.video.av1\",\"decoder\":\"builtin:wai@0.4.0\",\"leaves\":10,\"module_status\":null,\"path\":\"fallback\",\"pin\":null,\"rendition\":null,\"tier\":null,\"variant\":null}],\"energy\":null,\"fallback_units\":10,\"framing\":\"registered\",\"host\":{\"build\":{\"profile\":\"release\",\"target\":\"aarch64-unknown-linux-gnu\",\"toolchain\":\"rustc 1.95.0\"},\"profile\":\"native-ffi\",\"target\":\"aarch64-unknown-linux-gnu\",\"threads\":4},\"leaf_count\":20,\"media\":\"video\",\"missed\":0,\"missed_units\":[],\"output_root\":\"8e92fb6453752cb53e20b99a81d7b314f0e54b9f9fc5dae9903a8186f68f28ca\",\"primary_units\":10,\"receipt_bytes\":640,\"session_nonce\":\"57c5462dfdabd1b7bdd204d34ba33649c057eb535349f29f45eb8f8c7d4a7e7f\",\"stage_sets\":[],\"switches\":[],\"switches_total\":0,\"transferred\":13607,\"uncounted\":2,\"units\":20},\"class\":\"reconstruct-session\",\"issued_at\":\"2026-09-27T12:00:00Z\",\"kind\":\"claim\",\"parent_receipt_hash\":null,\"seq\":0,\"sig\":\"db39d8dbd2bf1f71e49bcb84bf8e86617fe2351da6238b127639a5014fe7ba5896d789dd178cf5cf8a2855d2c06b7d9800036cf6648c7e7031929a8a555fc002\",\"signer_id\":\"did:example:sink\",\"signer_pubkey\":\"d759793bbc13a2819a827c76adb6fba8a49aee007f49f2d0992d99b825ad2c48\",\"subject\":\"64c0713cb176874607bf8670295242184b7868a9ff7c55554a5ae08de2c301c1\",\"subject_type\":\"object\"}", + "context": { + "outputs": [ + { + "unit": 0, + "layers": 1, + "decoder": 0, + "out_digest": "55f7e628ca707e2ca3159709eeb68b9000813f2916a299acd33a23e6fe012584" + }, + { + "unit": 1, + "layers": 1, + "decoder": 1, + "out_digest": "a3ee8a4b96eceb663f3d94417957d02f897fc166dc96ebe9bf447c4a36a36264" + }, + { + "unit": 2, + "layers": 1, + "decoder": 0, + "out_digest": "00576d2c4d09ef5d7aa807f9b3b1587e200dea6f6694b4da062b41aa2a5ab8af" + }, + { + "unit": 3, + "layers": 1, + "decoder": 1, + "out_digest": "26cd9b2805b604b26e08d9a461db599c4e249bfd4df41a3befb202bc6d0e0700" + }, + { + "unit": 4, + "layers": 1, + "decoder": 0, + "out_digest": "1cd1984bc553c43ee5a48fe7e182a77e60d8ef3c2b0f959ef1a0efd3813b411f" + }, + { + "unit": 5, + "layers": 1, + "decoder": 1, + "out_digest": "e4c4344155dc2c789a1df265f8064b9ae56f3e0932d85c5ceb38782c135749fc" + }, + { + "unit": 6, + "layers": 1, + "decoder": 0, + "out_digest": "95542e01dfb7d7c52f2d526bf932ee49cf081ee2bc330c42dd0715cca7deff8b" + }, + { + "unit": 7, + "layers": 1, + "decoder": 1, + "out_digest": "cf1c65a8bc3fabc40710f610dcfa9ac2604f45a6fa68f74ee2b464421647da4c" + }, + { + "unit": 8, + "layers": 1, + "decoder": 0, + "out_digest": "5c01f526973ca7dbcde1513bc7d25333954bc4164811a5f21399b6e48d89079d" + }, + { + "unit": 9, + "layers": 1, + "decoder": 1, + "out_digest": "686ff0277613c58687a493af12da86b393bcee283c6758845a2505a93d135905" + }, + { + "unit": 10, + "layers": 1, + "decoder": 0, + "out_digest": "23851d2c5e0cc5365e329fbd9c01238313ac71fd4edb4730fa7d58cc74e74823" + }, + { + "unit": 11, + "layers": 1, + "decoder": 1, + "out_digest": "66270813e69c6cffbacb67f95a9c182b2f04ce8c3b2ee4829c257227a5f4a17a" + }, + { + "unit": 12, + "layers": 1, + "decoder": 0, + "out_digest": "47c089823c210a1989895087dc4d44dc5ed8ee0453d7f2517ccce83cb686c824" + }, + { + "unit": 13, + "layers": 1, + "decoder": 1, + "out_digest": "3a1e42600a46cf28926fc9f03946a3186264cef938e207b9e159591c179fa7ed" + }, + { + "unit": 14, + "layers": 1, + "decoder": 0, + "out_digest": "49eac1e814988d0a60db8a709e70f4a1989819a57e26b92bdd0239c338675c58" + }, + { + "unit": 15, + "layers": 1, + "decoder": 1, + "out_digest": "cd3ac56e7dc49f235a245024c0c560cc19ba73fcc0dfb1d38ff9f58bb180d5db" + }, + { + "unit": 16, + "layers": 1, + "decoder": 0, + "out_digest": "b3c7f2ac61734e3390450d0f34c70f733b20db0c29d8ea634c0fc0a8638f2258" + }, + { + "unit": 17, + "layers": 1, + "decoder": 1, + "out_digest": "64b919c5441af6df04b8563a34fe9fe57b84e802b1856a98e1edafc328e809d6" + }, + { + "unit": 18, + "layers": 1, + "decoder": 0, + "out_digest": "e120f02a7fffc970d4a82e4afa8c7d29a00b06a10a7d9fcbf49edacff256ed1d" + }, + { + "unit": 19, + "layers": 1, + "decoder": 1, + "out_digest": "68aee1cd87a8224bc389c297e3b001e9e842f5f416eaeda4b1aafa365e042d46" + } + ], + "redecoded": [ + { + "index": 0, + "out_digest": "55f7e628ca707e2ca3159709eeb68b9000813f2916a299acd33a23e6fe012584" + }, + { + "index": 1, + "out_digest": "9df7f2652febf9fe462ff426af1ee3ec158bf203c59392654482b80775804556" + }, + { + "index": 2, + "out_digest": "00576d2c4d09ef5d7aa807f9b3b1587e200dea6f6694b4da062b41aa2a5ab8af" + }, + { + "index": 3, + "out_digest": "5541d29e4f230e7683ad45c081f4f325fa6216f308b1682f621b3ed279fc39f8" + }, + { + "index": 4, + "out_digest": "1cd1984bc553c43ee5a48fe7e182a77e60d8ef3c2b0f959ef1a0efd3813b411f" + }, + { + "index": 5, + "out_digest": "67754c573f1f7605becf03e65bffa704359b96917b5bc203901eb10e32182cf1" + }, + { + "index": 6, + "out_digest": "95542e01dfb7d7c52f2d526bf932ee49cf081ee2bc330c42dd0715cca7deff8b" + }, + { + "index": 7, + "out_digest": "e7f6d40664240de8fe0eea2384891d0f040db6f05dca8450533a725410bfd31f" + }, + { + "index": 8, + "out_digest": "5c01f526973ca7dbcde1513bc7d25333954bc4164811a5f21399b6e48d89079d" + }, + { + "index": 9, + "out_digest": "f3ff8b3d08e7010fb0d5f7c836dc8b5969bcc95a73ae76813443a2b70929b6bb" + }, + { + "index": 10, + "out_digest": "23851d2c5e0cc5365e329fbd9c01238313ac71fd4edb4730fa7d58cc74e74823" + }, + { + "index": 11, + "out_digest": "9469cdcb42fe46fe46e0e0bb0e10f3397dc5048a60b81467183939f1e4548f74" + }, + { + "index": 12, + "out_digest": "47c089823c210a1989895087dc4d44dc5ed8ee0453d7f2517ccce83cb686c824" + }, + { + "index": 13, + "out_digest": "eca166a3ea198bf0271543d5428c3e0323063de0d3352fbde485399d4476a92b" + }, + { + "index": 14, + "out_digest": "49eac1e814988d0a60db8a709e70f4a1989819a57e26b92bdd0239c338675c58" + }, + { + "index": 15, + "out_digest": "fd7ac5bfaf32d59c57faba74ff87b0a09aae703323a147fef03adf7b2761cb1d" + }, + { + "index": 16, + "out_digest": "b3c7f2ac61734e3390450d0f34c70f733b20db0c29d8ea634c0fc0a8638f2258" + }, + { + "index": 17, + "out_digest": "b7988f6a6e8844ff5ec686f9290b0b4ab0c5c3c028b5e9be116e12821b851534" + }, + { + "index": 18, + "out_digest": "e120f02a7fffc970d4a82e4afa8c7d29a00b06a10a7d9fcbf49edacff256ed1d" + }, + { + "index": 19, + "out_digest": "9436e6edd6411835af7500432df9c51a17b590217e97e642f20820df0323387a" + } + ] + }, + "expected": { + "outcome": "accept", + "link_hash": "e2afb382ab36cd695becc80f9795caa72e437395c19f20052eb91758fba81129" + } + }, + { + "name": "session_tree_21", + "about": "an output tree of 21 leaves, half on a byte-exact decoder whose re-decode matches and half checked for membership only, whose re-decode does not and is not checked", + "procedure": "claim", + "receipt": "{\"body\":{\"classical_declared\":700,\"classical_source\":\"wai2-table\",\"counted_discarded\":1904,\"counted_fallback\":0,\"counted_primary\":5607,\"deadline_us\":null,\"decoders\":[{\"capability\":\"wai.video.int_hyper\",\"decoder\":\"builtin:wai@0.4.0\",\"leaves\":11,\"module_status\":null,\"path\":\"primary\",\"pin\":\"7b4371854df0aa1645ac6525b373387c0617b873d5a57748932ee0f386ea164b\",\"rendition\":0,\"tier\":\"decode-equivalence\",\"variant\":null},{\"capability\":\"wai.video.av1\",\"decoder\":\"builtin:wai@0.4.0\",\"leaves\":10,\"module_status\":null,\"path\":\"fallback\",\"pin\":null,\"rendition\":null,\"tier\":null,\"variant\":null}],\"energy\":null,\"fallback_units\":10,\"framing\":\"registered\",\"host\":{\"build\":{\"profile\":\"release\",\"target\":\"aarch64-unknown-linux-gnu\",\"toolchain\":\"rustc 1.95.0\"},\"profile\":\"native-ffi\",\"target\":\"aarch64-unknown-linux-gnu\",\"threads\":4},\"leaf_count\":21,\"media\":\"video\",\"missed\":0,\"missed_units\":[],\"output_root\":\"0c6c96faed98dfe4ba1cae73ef330d2a757c6f4cb6e6db5cf57acaf3f6556a22\",\"primary_units\":11,\"receipt_bytes\":640,\"session_nonce\":\"57c5462dfdabd1b7bdd204d34ba33649c057eb535349f29f45eb8f8c7d4a7e7f\",\"stage_sets\":[],\"switches\":[],\"switches_total\":0,\"transferred\":13607,\"uncounted\":2,\"units\":21},\"class\":\"reconstruct-session\",\"issued_at\":\"2026-09-27T12:00:00Z\",\"kind\":\"claim\",\"parent_receipt_hash\":null,\"seq\":0,\"sig\":\"d8c5b037466ded3ec55b92a0a975bca1a50d885897a63c2b94575d54380d9a7a48923ec9283bb0d79c01ec617e0c3b1156d09935218f86c1d42a2c4b8111ff0d\",\"signer_id\":\"did:example:sink\",\"signer_pubkey\":\"d759793bbc13a2819a827c76adb6fba8a49aee007f49f2d0992d99b825ad2c48\",\"subject\":\"64c0713cb176874607bf8670295242184b7868a9ff7c55554a5ae08de2c301c1\",\"subject_type\":\"object\"}", + "context": { + "outputs": [ + { + "unit": 0, + "layers": 1, + "decoder": 0, + "out_digest": "55f7e628ca707e2ca3159709eeb68b9000813f2916a299acd33a23e6fe012584" + }, + { + "unit": 1, + "layers": 1, + "decoder": 1, + "out_digest": "a3ee8a4b96eceb663f3d94417957d02f897fc166dc96ebe9bf447c4a36a36264" + }, + { + "unit": 2, + "layers": 1, + "decoder": 0, + "out_digest": "00576d2c4d09ef5d7aa807f9b3b1587e200dea6f6694b4da062b41aa2a5ab8af" + }, + { + "unit": 3, + "layers": 1, + "decoder": 1, + "out_digest": "26cd9b2805b604b26e08d9a461db599c4e249bfd4df41a3befb202bc6d0e0700" + }, + { + "unit": 4, + "layers": 1, + "decoder": 0, + "out_digest": "1cd1984bc553c43ee5a48fe7e182a77e60d8ef3c2b0f959ef1a0efd3813b411f" + }, + { + "unit": 5, + "layers": 1, + "decoder": 1, + "out_digest": "e4c4344155dc2c789a1df265f8064b9ae56f3e0932d85c5ceb38782c135749fc" + }, + { + "unit": 6, + "layers": 1, + "decoder": 0, + "out_digest": "95542e01dfb7d7c52f2d526bf932ee49cf081ee2bc330c42dd0715cca7deff8b" + }, + { + "unit": 7, + "layers": 1, + "decoder": 1, + "out_digest": "cf1c65a8bc3fabc40710f610dcfa9ac2604f45a6fa68f74ee2b464421647da4c" + }, + { + "unit": 8, + "layers": 1, + "decoder": 0, + "out_digest": "5c01f526973ca7dbcde1513bc7d25333954bc4164811a5f21399b6e48d89079d" + }, + { + "unit": 9, + "layers": 1, + "decoder": 1, + "out_digest": "686ff0277613c58687a493af12da86b393bcee283c6758845a2505a93d135905" + }, + { + "unit": 10, + "layers": 1, + "decoder": 0, + "out_digest": "23851d2c5e0cc5365e329fbd9c01238313ac71fd4edb4730fa7d58cc74e74823" + }, + { + "unit": 11, + "layers": 1, + "decoder": 1, + "out_digest": "66270813e69c6cffbacb67f95a9c182b2f04ce8c3b2ee4829c257227a5f4a17a" + }, + { + "unit": 12, + "layers": 1, + "decoder": 0, + "out_digest": "47c089823c210a1989895087dc4d44dc5ed8ee0453d7f2517ccce83cb686c824" + }, + { + "unit": 13, + "layers": 1, + "decoder": 1, + "out_digest": "3a1e42600a46cf28926fc9f03946a3186264cef938e207b9e159591c179fa7ed" + }, + { + "unit": 14, + "layers": 1, + "decoder": 0, + "out_digest": "49eac1e814988d0a60db8a709e70f4a1989819a57e26b92bdd0239c338675c58" + }, + { + "unit": 15, + "layers": 1, + "decoder": 1, + "out_digest": "cd3ac56e7dc49f235a245024c0c560cc19ba73fcc0dfb1d38ff9f58bb180d5db" + }, + { + "unit": 16, + "layers": 1, + "decoder": 0, + "out_digest": "b3c7f2ac61734e3390450d0f34c70f733b20db0c29d8ea634c0fc0a8638f2258" + }, + { + "unit": 17, + "layers": 1, + "decoder": 1, + "out_digest": "64b919c5441af6df04b8563a34fe9fe57b84e802b1856a98e1edafc328e809d6" + }, + { + "unit": 18, + "layers": 1, + "decoder": 0, + "out_digest": "e120f02a7fffc970d4a82e4afa8c7d29a00b06a10a7d9fcbf49edacff256ed1d" + }, + { + "unit": 19, + "layers": 1, + "decoder": 1, + "out_digest": "68aee1cd87a8224bc389c297e3b001e9e842f5f416eaeda4b1aafa365e042d46" + }, + { + "unit": 20, + "layers": 1, + "decoder": 0, + "out_digest": "01d364fffad3148204e1cebc263ab9c8818eab8969da5fcbc5794392d170ad6c" + } + ], + "redecoded": [ + { + "index": 0, + "out_digest": "55f7e628ca707e2ca3159709eeb68b9000813f2916a299acd33a23e6fe012584" + }, + { + "index": 1, + "out_digest": "9df7f2652febf9fe462ff426af1ee3ec158bf203c59392654482b80775804556" + }, + { + "index": 2, + "out_digest": "00576d2c4d09ef5d7aa807f9b3b1587e200dea6f6694b4da062b41aa2a5ab8af" + }, + { + "index": 3, + "out_digest": "5541d29e4f230e7683ad45c081f4f325fa6216f308b1682f621b3ed279fc39f8" + }, + { + "index": 4, + "out_digest": "1cd1984bc553c43ee5a48fe7e182a77e60d8ef3c2b0f959ef1a0efd3813b411f" + }, + { + "index": 5, + "out_digest": "67754c573f1f7605becf03e65bffa704359b96917b5bc203901eb10e32182cf1" + }, + { + "index": 6, + "out_digest": "95542e01dfb7d7c52f2d526bf932ee49cf081ee2bc330c42dd0715cca7deff8b" + }, + { + "index": 7, + "out_digest": "e7f6d40664240de8fe0eea2384891d0f040db6f05dca8450533a725410bfd31f" + }, + { + "index": 8, + "out_digest": "5c01f526973ca7dbcde1513bc7d25333954bc4164811a5f21399b6e48d89079d" + }, + { + "index": 9, + "out_digest": "f3ff8b3d08e7010fb0d5f7c836dc8b5969bcc95a73ae76813443a2b70929b6bb" + }, + { + "index": 10, + "out_digest": "23851d2c5e0cc5365e329fbd9c01238313ac71fd4edb4730fa7d58cc74e74823" + }, + { + "index": 11, + "out_digest": "9469cdcb42fe46fe46e0e0bb0e10f3397dc5048a60b81467183939f1e4548f74" + }, + { + "index": 12, + "out_digest": "47c089823c210a1989895087dc4d44dc5ed8ee0453d7f2517ccce83cb686c824" + }, + { + "index": 13, + "out_digest": "eca166a3ea198bf0271543d5428c3e0323063de0d3352fbde485399d4476a92b" + }, + { + "index": 14, + "out_digest": "49eac1e814988d0a60db8a709e70f4a1989819a57e26b92bdd0239c338675c58" + }, + { + "index": 15, + "out_digest": "fd7ac5bfaf32d59c57faba74ff87b0a09aae703323a147fef03adf7b2761cb1d" + }, + { + "index": 16, + "out_digest": "b3c7f2ac61734e3390450d0f34c70f733b20db0c29d8ea634c0fc0a8638f2258" + }, + { + "index": 17, + "out_digest": "b7988f6a6e8844ff5ec686f9290b0b4ab0c5c3c028b5e9be116e12821b851534" + }, + { + "index": 18, + "out_digest": "e120f02a7fffc970d4a82e4afa8c7d29a00b06a10a7d9fcbf49edacff256ed1d" + }, + { + "index": 19, + "out_digest": "9436e6edd6411835af7500432df9c51a17b590217e97e642f20820df0323387a" + }, + { + "index": 20, + "out_digest": "01d364fffad3148204e1cebc263ab9c8818eab8969da5fcbc5794392d170ad6c" + } + ] + }, + "expected": { + "outcome": "accept", + "link_hash": "89ffa6c8a93d7c0f78a57a98688fb424660756b6490250d40c7d54efbb761643" + } + }, + { + "name": "session_tree_22", + "about": "an output tree of 22 leaves, half on a byte-exact decoder whose re-decode matches and half checked for membership only, whose re-decode does not and is not checked", + "procedure": "claim", + "receipt": "{\"body\":{\"classical_declared\":700,\"classical_source\":\"wai2-table\",\"counted_discarded\":1904,\"counted_fallback\":0,\"counted_primary\":5607,\"deadline_us\":null,\"decoders\":[{\"capability\":\"wai.video.int_hyper\",\"decoder\":\"builtin:wai@0.4.0\",\"leaves\":11,\"module_status\":null,\"path\":\"primary\",\"pin\":\"7b4371854df0aa1645ac6525b373387c0617b873d5a57748932ee0f386ea164b\",\"rendition\":0,\"tier\":\"decode-equivalence\",\"variant\":null},{\"capability\":\"wai.video.av1\",\"decoder\":\"builtin:wai@0.4.0\",\"leaves\":11,\"module_status\":null,\"path\":\"fallback\",\"pin\":null,\"rendition\":null,\"tier\":null,\"variant\":null}],\"energy\":null,\"fallback_units\":11,\"framing\":\"registered\",\"host\":{\"build\":{\"profile\":\"release\",\"target\":\"aarch64-unknown-linux-gnu\",\"toolchain\":\"rustc 1.95.0\"},\"profile\":\"native-ffi\",\"target\":\"aarch64-unknown-linux-gnu\",\"threads\":4},\"leaf_count\":22,\"media\":\"video\",\"missed\":0,\"missed_units\":[],\"output_root\":\"e2c1d24acc4802ad8f7ed12795c6ff83981ab85bf35a35cc95fce22d6483e3ed\",\"primary_units\":11,\"receipt_bytes\":640,\"session_nonce\":\"57c5462dfdabd1b7bdd204d34ba33649c057eb535349f29f45eb8f8c7d4a7e7f\",\"stage_sets\":[],\"switches\":[],\"switches_total\":0,\"transferred\":13607,\"uncounted\":2,\"units\":22},\"class\":\"reconstruct-session\",\"issued_at\":\"2026-09-27T12:00:00Z\",\"kind\":\"claim\",\"parent_receipt_hash\":null,\"seq\":0,\"sig\":\"2214d8fefc3a61e6008b9d919807afd5d2a504f08ced1c887b769684086984405b21e9e0befb58746120a5bb3974d822b0a8657790ac88654e723ff914e34201\",\"signer_id\":\"did:example:sink\",\"signer_pubkey\":\"d759793bbc13a2819a827c76adb6fba8a49aee007f49f2d0992d99b825ad2c48\",\"subject\":\"64c0713cb176874607bf8670295242184b7868a9ff7c55554a5ae08de2c301c1\",\"subject_type\":\"object\"}", + "context": { + "outputs": [ + { + "unit": 0, + "layers": 1, + "decoder": 0, + "out_digest": "55f7e628ca707e2ca3159709eeb68b9000813f2916a299acd33a23e6fe012584" + }, + { + "unit": 1, + "layers": 1, + "decoder": 1, + "out_digest": "a3ee8a4b96eceb663f3d94417957d02f897fc166dc96ebe9bf447c4a36a36264" + }, + { + "unit": 2, + "layers": 1, + "decoder": 0, + "out_digest": "00576d2c4d09ef5d7aa807f9b3b1587e200dea6f6694b4da062b41aa2a5ab8af" + }, + { + "unit": 3, + "layers": 1, + "decoder": 1, + "out_digest": "26cd9b2805b604b26e08d9a461db599c4e249bfd4df41a3befb202bc6d0e0700" + }, + { + "unit": 4, + "layers": 1, + "decoder": 0, + "out_digest": "1cd1984bc553c43ee5a48fe7e182a77e60d8ef3c2b0f959ef1a0efd3813b411f" + }, + { + "unit": 5, + "layers": 1, + "decoder": 1, + "out_digest": "e4c4344155dc2c789a1df265f8064b9ae56f3e0932d85c5ceb38782c135749fc" + }, + { + "unit": 6, + "layers": 1, + "decoder": 0, + "out_digest": "95542e01dfb7d7c52f2d526bf932ee49cf081ee2bc330c42dd0715cca7deff8b" + }, + { + "unit": 7, + "layers": 1, + "decoder": 1, + "out_digest": "cf1c65a8bc3fabc40710f610dcfa9ac2604f45a6fa68f74ee2b464421647da4c" + }, + { + "unit": 8, + "layers": 1, + "decoder": 0, + "out_digest": "5c01f526973ca7dbcde1513bc7d25333954bc4164811a5f21399b6e48d89079d" + }, + { + "unit": 9, + "layers": 1, + "decoder": 1, + "out_digest": "686ff0277613c58687a493af12da86b393bcee283c6758845a2505a93d135905" + }, + { + "unit": 10, + "layers": 1, + "decoder": 0, + "out_digest": "23851d2c5e0cc5365e329fbd9c01238313ac71fd4edb4730fa7d58cc74e74823" + }, + { + "unit": 11, + "layers": 1, + "decoder": 1, + "out_digest": "66270813e69c6cffbacb67f95a9c182b2f04ce8c3b2ee4829c257227a5f4a17a" + }, + { + "unit": 12, + "layers": 1, + "decoder": 0, + "out_digest": "47c089823c210a1989895087dc4d44dc5ed8ee0453d7f2517ccce83cb686c824" + }, + { + "unit": 13, + "layers": 1, + "decoder": 1, + "out_digest": "3a1e42600a46cf28926fc9f03946a3186264cef938e207b9e159591c179fa7ed" + }, + { + "unit": 14, + "layers": 1, + "decoder": 0, + "out_digest": "49eac1e814988d0a60db8a709e70f4a1989819a57e26b92bdd0239c338675c58" + }, + { + "unit": 15, + "layers": 1, + "decoder": 1, + "out_digest": "cd3ac56e7dc49f235a245024c0c560cc19ba73fcc0dfb1d38ff9f58bb180d5db" + }, + { + "unit": 16, + "layers": 1, + "decoder": 0, + "out_digest": "b3c7f2ac61734e3390450d0f34c70f733b20db0c29d8ea634c0fc0a8638f2258" + }, + { + "unit": 17, + "layers": 1, + "decoder": 1, + "out_digest": "64b919c5441af6df04b8563a34fe9fe57b84e802b1856a98e1edafc328e809d6" + }, + { + "unit": 18, + "layers": 1, + "decoder": 0, + "out_digest": "e120f02a7fffc970d4a82e4afa8c7d29a00b06a10a7d9fcbf49edacff256ed1d" + }, + { + "unit": 19, + "layers": 1, + "decoder": 1, + "out_digest": "68aee1cd87a8224bc389c297e3b001e9e842f5f416eaeda4b1aafa365e042d46" + }, + { + "unit": 20, + "layers": 1, + "decoder": 0, + "out_digest": "01d364fffad3148204e1cebc263ab9c8818eab8969da5fcbc5794392d170ad6c" + }, + { + "unit": 21, + "layers": 1, + "decoder": 1, + "out_digest": "7c587829be53d8fd83fa843e9b2d1ae7567637256ffa2b00dc5a12b6b3d2bfbd" + } + ], + "redecoded": [ + { + "index": 0, + "out_digest": "55f7e628ca707e2ca3159709eeb68b9000813f2916a299acd33a23e6fe012584" + }, + { + "index": 1, + "out_digest": "9df7f2652febf9fe462ff426af1ee3ec158bf203c59392654482b80775804556" + }, + { + "index": 2, + "out_digest": "00576d2c4d09ef5d7aa807f9b3b1587e200dea6f6694b4da062b41aa2a5ab8af" + }, + { + "index": 3, + "out_digest": "5541d29e4f230e7683ad45c081f4f325fa6216f308b1682f621b3ed279fc39f8" + }, + { + "index": 4, + "out_digest": "1cd1984bc553c43ee5a48fe7e182a77e60d8ef3c2b0f959ef1a0efd3813b411f" + }, + { + "index": 5, + "out_digest": "67754c573f1f7605becf03e65bffa704359b96917b5bc203901eb10e32182cf1" + }, + { + "index": 6, + "out_digest": "95542e01dfb7d7c52f2d526bf932ee49cf081ee2bc330c42dd0715cca7deff8b" + }, + { + "index": 7, + "out_digest": "e7f6d40664240de8fe0eea2384891d0f040db6f05dca8450533a725410bfd31f" + }, + { + "index": 8, + "out_digest": "5c01f526973ca7dbcde1513bc7d25333954bc4164811a5f21399b6e48d89079d" + }, + { + "index": 9, + "out_digest": "f3ff8b3d08e7010fb0d5f7c836dc8b5969bcc95a73ae76813443a2b70929b6bb" + }, + { + "index": 10, + "out_digest": "23851d2c5e0cc5365e329fbd9c01238313ac71fd4edb4730fa7d58cc74e74823" + }, + { + "index": 11, + "out_digest": "9469cdcb42fe46fe46e0e0bb0e10f3397dc5048a60b81467183939f1e4548f74" + }, + { + "index": 12, + "out_digest": "47c089823c210a1989895087dc4d44dc5ed8ee0453d7f2517ccce83cb686c824" + }, + { + "index": 13, + "out_digest": "eca166a3ea198bf0271543d5428c3e0323063de0d3352fbde485399d4476a92b" + }, + { + "index": 14, + "out_digest": "49eac1e814988d0a60db8a709e70f4a1989819a57e26b92bdd0239c338675c58" + }, + { + "index": 15, + "out_digest": "fd7ac5bfaf32d59c57faba74ff87b0a09aae703323a147fef03adf7b2761cb1d" + }, + { + "index": 16, + "out_digest": "b3c7f2ac61734e3390450d0f34c70f733b20db0c29d8ea634c0fc0a8638f2258" + }, + { + "index": 17, + "out_digest": "b7988f6a6e8844ff5ec686f9290b0b4ab0c5c3c028b5e9be116e12821b851534" + }, + { + "index": 18, + "out_digest": "e120f02a7fffc970d4a82e4afa8c7d29a00b06a10a7d9fcbf49edacff256ed1d" + }, + { + "index": 19, + "out_digest": "9436e6edd6411835af7500432df9c51a17b590217e97e642f20820df0323387a" + }, + { + "index": 20, + "out_digest": "01d364fffad3148204e1cebc263ab9c8818eab8969da5fcbc5794392d170ad6c" + }, + { + "index": 21, + "out_digest": "68c5337faac08354c20caec0d0e7221de83055c34f8427195a1ecd9fa2f067ba" + } + ] + }, + "expected": { + "outcome": "accept", + "link_hash": "448a0e599e701dc7cec9393d3806063c833002281bd39ab2e22521d817b5aa08" + } + }, + { + "name": "session_tree_23", + "about": "an output tree of 23 leaves, half on a byte-exact decoder whose re-decode matches and half checked for membership only, whose re-decode does not and is not checked", + "procedure": "claim", + "receipt": "{\"body\":{\"classical_declared\":700,\"classical_source\":\"wai2-table\",\"counted_discarded\":1904,\"counted_fallback\":0,\"counted_primary\":5607,\"deadline_us\":null,\"decoders\":[{\"capability\":\"wai.video.int_hyper\",\"decoder\":\"builtin:wai@0.4.0\",\"leaves\":12,\"module_status\":null,\"path\":\"primary\",\"pin\":\"7b4371854df0aa1645ac6525b373387c0617b873d5a57748932ee0f386ea164b\",\"rendition\":0,\"tier\":\"decode-equivalence\",\"variant\":null},{\"capability\":\"wai.video.av1\",\"decoder\":\"builtin:wai@0.4.0\",\"leaves\":11,\"module_status\":null,\"path\":\"fallback\",\"pin\":null,\"rendition\":null,\"tier\":null,\"variant\":null}],\"energy\":null,\"fallback_units\":11,\"framing\":\"registered\",\"host\":{\"build\":{\"profile\":\"release\",\"target\":\"aarch64-unknown-linux-gnu\",\"toolchain\":\"rustc 1.95.0\"},\"profile\":\"native-ffi\",\"target\":\"aarch64-unknown-linux-gnu\",\"threads\":4},\"leaf_count\":23,\"media\":\"video\",\"missed\":0,\"missed_units\":[],\"output_root\":\"c1706ad43988ea927531a1945fc0eceba01aa1f951a42c25322f751680c970c3\",\"primary_units\":12,\"receipt_bytes\":640,\"session_nonce\":\"57c5462dfdabd1b7bdd204d34ba33649c057eb535349f29f45eb8f8c7d4a7e7f\",\"stage_sets\":[],\"switches\":[],\"switches_total\":0,\"transferred\":13607,\"uncounted\":2,\"units\":23},\"class\":\"reconstruct-session\",\"issued_at\":\"2026-09-27T12:00:00Z\",\"kind\":\"claim\",\"parent_receipt_hash\":null,\"seq\":0,\"sig\":\"3577d8909c348a2acc0512f47af5889373b9964e19e936662fb3aa5d157056820a886eec69cf59c13034f9e53415deee5859dfbd923826128c64bed5322f6702\",\"signer_id\":\"did:example:sink\",\"signer_pubkey\":\"d759793bbc13a2819a827c76adb6fba8a49aee007f49f2d0992d99b825ad2c48\",\"subject\":\"64c0713cb176874607bf8670295242184b7868a9ff7c55554a5ae08de2c301c1\",\"subject_type\":\"object\"}", + "context": { + "outputs": [ + { + "unit": 0, + "layers": 1, + "decoder": 0, + "out_digest": "55f7e628ca707e2ca3159709eeb68b9000813f2916a299acd33a23e6fe012584" + }, + { + "unit": 1, + "layers": 1, + "decoder": 1, + "out_digest": "a3ee8a4b96eceb663f3d94417957d02f897fc166dc96ebe9bf447c4a36a36264" + }, + { + "unit": 2, + "layers": 1, + "decoder": 0, + "out_digest": "00576d2c4d09ef5d7aa807f9b3b1587e200dea6f6694b4da062b41aa2a5ab8af" + }, + { + "unit": 3, + "layers": 1, + "decoder": 1, + "out_digest": "26cd9b2805b604b26e08d9a461db599c4e249bfd4df41a3befb202bc6d0e0700" + }, + { + "unit": 4, + "layers": 1, + "decoder": 0, + "out_digest": "1cd1984bc553c43ee5a48fe7e182a77e60d8ef3c2b0f959ef1a0efd3813b411f" + }, + { + "unit": 5, + "layers": 1, + "decoder": 1, + "out_digest": "e4c4344155dc2c789a1df265f8064b9ae56f3e0932d85c5ceb38782c135749fc" + }, + { + "unit": 6, + "layers": 1, + "decoder": 0, + "out_digest": "95542e01dfb7d7c52f2d526bf932ee49cf081ee2bc330c42dd0715cca7deff8b" + }, + { + "unit": 7, + "layers": 1, + "decoder": 1, + "out_digest": "cf1c65a8bc3fabc40710f610dcfa9ac2604f45a6fa68f74ee2b464421647da4c" + }, + { + "unit": 8, + "layers": 1, + "decoder": 0, + "out_digest": "5c01f526973ca7dbcde1513bc7d25333954bc4164811a5f21399b6e48d89079d" + }, + { + "unit": 9, + "layers": 1, + "decoder": 1, + "out_digest": "686ff0277613c58687a493af12da86b393bcee283c6758845a2505a93d135905" + }, + { + "unit": 10, + "layers": 1, + "decoder": 0, + "out_digest": "23851d2c5e0cc5365e329fbd9c01238313ac71fd4edb4730fa7d58cc74e74823" + }, + { + "unit": 11, + "layers": 1, + "decoder": 1, + "out_digest": "66270813e69c6cffbacb67f95a9c182b2f04ce8c3b2ee4829c257227a5f4a17a" + }, + { + "unit": 12, + "layers": 1, + "decoder": 0, + "out_digest": "47c089823c210a1989895087dc4d44dc5ed8ee0453d7f2517ccce83cb686c824" + }, + { + "unit": 13, + "layers": 1, + "decoder": 1, + "out_digest": "3a1e42600a46cf28926fc9f03946a3186264cef938e207b9e159591c179fa7ed" + }, + { + "unit": 14, + "layers": 1, + "decoder": 0, + "out_digest": "49eac1e814988d0a60db8a709e70f4a1989819a57e26b92bdd0239c338675c58" + }, + { + "unit": 15, + "layers": 1, + "decoder": 1, + "out_digest": "cd3ac56e7dc49f235a245024c0c560cc19ba73fcc0dfb1d38ff9f58bb180d5db" + }, + { + "unit": 16, + "layers": 1, + "decoder": 0, + "out_digest": "b3c7f2ac61734e3390450d0f34c70f733b20db0c29d8ea634c0fc0a8638f2258" + }, + { + "unit": 17, + "layers": 1, + "decoder": 1, + "out_digest": "64b919c5441af6df04b8563a34fe9fe57b84e802b1856a98e1edafc328e809d6" + }, + { + "unit": 18, + "layers": 1, + "decoder": 0, + "out_digest": "e120f02a7fffc970d4a82e4afa8c7d29a00b06a10a7d9fcbf49edacff256ed1d" + }, + { + "unit": 19, + "layers": 1, + "decoder": 1, + "out_digest": "68aee1cd87a8224bc389c297e3b001e9e842f5f416eaeda4b1aafa365e042d46" + }, + { + "unit": 20, + "layers": 1, + "decoder": 0, + "out_digest": "01d364fffad3148204e1cebc263ab9c8818eab8969da5fcbc5794392d170ad6c" + }, + { + "unit": 21, + "layers": 1, + "decoder": 1, + "out_digest": "7c587829be53d8fd83fa843e9b2d1ae7567637256ffa2b00dc5a12b6b3d2bfbd" + }, + { + "unit": 22, + "layers": 1, + "decoder": 0, + "out_digest": "8bf65e08db2dc14a138df5c114940e28396ffe2279278732321dda8d2e377061" + } + ], + "redecoded": [ + { + "index": 0, + "out_digest": "55f7e628ca707e2ca3159709eeb68b9000813f2916a299acd33a23e6fe012584" + }, + { + "index": 1, + "out_digest": "9df7f2652febf9fe462ff426af1ee3ec158bf203c59392654482b80775804556" + }, + { + "index": 2, + "out_digest": "00576d2c4d09ef5d7aa807f9b3b1587e200dea6f6694b4da062b41aa2a5ab8af" + }, + { + "index": 3, + "out_digest": "5541d29e4f230e7683ad45c081f4f325fa6216f308b1682f621b3ed279fc39f8" + }, + { + "index": 4, + "out_digest": "1cd1984bc553c43ee5a48fe7e182a77e60d8ef3c2b0f959ef1a0efd3813b411f" + }, + { + "index": 5, + "out_digest": "67754c573f1f7605becf03e65bffa704359b96917b5bc203901eb10e32182cf1" + }, + { + "index": 6, + "out_digest": "95542e01dfb7d7c52f2d526bf932ee49cf081ee2bc330c42dd0715cca7deff8b" + }, + { + "index": 7, + "out_digest": "e7f6d40664240de8fe0eea2384891d0f040db6f05dca8450533a725410bfd31f" + }, + { + "index": 8, + "out_digest": "5c01f526973ca7dbcde1513bc7d25333954bc4164811a5f21399b6e48d89079d" + }, + { + "index": 9, + "out_digest": "f3ff8b3d08e7010fb0d5f7c836dc8b5969bcc95a73ae76813443a2b70929b6bb" + }, + { + "index": 10, + "out_digest": "23851d2c5e0cc5365e329fbd9c01238313ac71fd4edb4730fa7d58cc74e74823" + }, + { + "index": 11, + "out_digest": "9469cdcb42fe46fe46e0e0bb0e10f3397dc5048a60b81467183939f1e4548f74" + }, + { + "index": 12, + "out_digest": "47c089823c210a1989895087dc4d44dc5ed8ee0453d7f2517ccce83cb686c824" + }, + { + "index": 13, + "out_digest": "eca166a3ea198bf0271543d5428c3e0323063de0d3352fbde485399d4476a92b" + }, + { + "index": 14, + "out_digest": "49eac1e814988d0a60db8a709e70f4a1989819a57e26b92bdd0239c338675c58" + }, + { + "index": 15, + "out_digest": "fd7ac5bfaf32d59c57faba74ff87b0a09aae703323a147fef03adf7b2761cb1d" + }, + { + "index": 16, + "out_digest": "b3c7f2ac61734e3390450d0f34c70f733b20db0c29d8ea634c0fc0a8638f2258" + }, + { + "index": 17, + "out_digest": "b7988f6a6e8844ff5ec686f9290b0b4ab0c5c3c028b5e9be116e12821b851534" + }, + { + "index": 18, + "out_digest": "e120f02a7fffc970d4a82e4afa8c7d29a00b06a10a7d9fcbf49edacff256ed1d" + }, + { + "index": 19, + "out_digest": "9436e6edd6411835af7500432df9c51a17b590217e97e642f20820df0323387a" + }, + { + "index": 20, + "out_digest": "01d364fffad3148204e1cebc263ab9c8818eab8969da5fcbc5794392d170ad6c" + }, + { + "index": 21, + "out_digest": "68c5337faac08354c20caec0d0e7221de83055c34f8427195a1ecd9fa2f067ba" + }, + { + "index": 22, + "out_digest": "8bf65e08db2dc14a138df5c114940e28396ffe2279278732321dda8d2e377061" + } + ] + }, + "expected": { + "outcome": "accept", + "link_hash": "c53a86d3b1573d360d43affb34bd05ee1817ab3f9a37498270b21e0ad9d338a4" + } + }, + { + "name": "session_tree_24", + "about": "an output tree of 24 leaves, half on a byte-exact decoder whose re-decode matches and half checked for membership only, whose re-decode does not and is not checked", + "procedure": "claim", + "receipt": "{\"body\":{\"classical_declared\":700,\"classical_source\":\"wai2-table\",\"counted_discarded\":1904,\"counted_fallback\":0,\"counted_primary\":5607,\"deadline_us\":null,\"decoders\":[{\"capability\":\"wai.video.int_hyper\",\"decoder\":\"builtin:wai@0.4.0\",\"leaves\":12,\"module_status\":null,\"path\":\"primary\",\"pin\":\"7b4371854df0aa1645ac6525b373387c0617b873d5a57748932ee0f386ea164b\",\"rendition\":0,\"tier\":\"decode-equivalence\",\"variant\":null},{\"capability\":\"wai.video.av1\",\"decoder\":\"builtin:wai@0.4.0\",\"leaves\":12,\"module_status\":null,\"path\":\"fallback\",\"pin\":null,\"rendition\":null,\"tier\":null,\"variant\":null}],\"energy\":null,\"fallback_units\":12,\"framing\":\"registered\",\"host\":{\"build\":{\"profile\":\"release\",\"target\":\"aarch64-unknown-linux-gnu\",\"toolchain\":\"rustc 1.95.0\"},\"profile\":\"native-ffi\",\"target\":\"aarch64-unknown-linux-gnu\",\"threads\":4},\"leaf_count\":24,\"media\":\"video\",\"missed\":0,\"missed_units\":[],\"output_root\":\"df43658f2f1e835d5edef15ec526c37f356fbc8b042ea53d3d67b1d5f872ac21\",\"primary_units\":12,\"receipt_bytes\":640,\"session_nonce\":\"57c5462dfdabd1b7bdd204d34ba33649c057eb535349f29f45eb8f8c7d4a7e7f\",\"stage_sets\":[],\"switches\":[],\"switches_total\":0,\"transferred\":13607,\"uncounted\":2,\"units\":24},\"class\":\"reconstruct-session\",\"issued_at\":\"2026-09-27T12:00:00Z\",\"kind\":\"claim\",\"parent_receipt_hash\":null,\"seq\":0,\"sig\":\"f8d42d2f2312666ed30e36d10966fe1b7c3c4896ab399dd38eaa8e891006503c198aaa7cb92c728b1569e9fe0880186916c3db809b7c76a56095c36ec932df00\",\"signer_id\":\"did:example:sink\",\"signer_pubkey\":\"d759793bbc13a2819a827c76adb6fba8a49aee007f49f2d0992d99b825ad2c48\",\"subject\":\"64c0713cb176874607bf8670295242184b7868a9ff7c55554a5ae08de2c301c1\",\"subject_type\":\"object\"}", + "context": { + "outputs": [ + { + "unit": 0, + "layers": 1, + "decoder": 0, + "out_digest": "55f7e628ca707e2ca3159709eeb68b9000813f2916a299acd33a23e6fe012584" + }, + { + "unit": 1, + "layers": 1, + "decoder": 1, + "out_digest": "a3ee8a4b96eceb663f3d94417957d02f897fc166dc96ebe9bf447c4a36a36264" + }, + { + "unit": 2, + "layers": 1, + "decoder": 0, + "out_digest": "00576d2c4d09ef5d7aa807f9b3b1587e200dea6f6694b4da062b41aa2a5ab8af" + }, + { + "unit": 3, + "layers": 1, + "decoder": 1, + "out_digest": "26cd9b2805b604b26e08d9a461db599c4e249bfd4df41a3befb202bc6d0e0700" + }, + { + "unit": 4, + "layers": 1, + "decoder": 0, + "out_digest": "1cd1984bc553c43ee5a48fe7e182a77e60d8ef3c2b0f959ef1a0efd3813b411f" + }, + { + "unit": 5, + "layers": 1, + "decoder": 1, + "out_digest": "e4c4344155dc2c789a1df265f8064b9ae56f3e0932d85c5ceb38782c135749fc" + }, + { + "unit": 6, + "layers": 1, + "decoder": 0, + "out_digest": "95542e01dfb7d7c52f2d526bf932ee49cf081ee2bc330c42dd0715cca7deff8b" + }, + { + "unit": 7, + "layers": 1, + "decoder": 1, + "out_digest": "cf1c65a8bc3fabc40710f610dcfa9ac2604f45a6fa68f74ee2b464421647da4c" + }, + { + "unit": 8, + "layers": 1, + "decoder": 0, + "out_digest": "5c01f526973ca7dbcde1513bc7d25333954bc4164811a5f21399b6e48d89079d" + }, + { + "unit": 9, + "layers": 1, + "decoder": 1, + "out_digest": "686ff0277613c58687a493af12da86b393bcee283c6758845a2505a93d135905" + }, + { + "unit": 10, + "layers": 1, + "decoder": 0, + "out_digest": "23851d2c5e0cc5365e329fbd9c01238313ac71fd4edb4730fa7d58cc74e74823" + }, + { + "unit": 11, + "layers": 1, + "decoder": 1, + "out_digest": "66270813e69c6cffbacb67f95a9c182b2f04ce8c3b2ee4829c257227a5f4a17a" + }, + { + "unit": 12, + "layers": 1, + "decoder": 0, + "out_digest": "47c089823c210a1989895087dc4d44dc5ed8ee0453d7f2517ccce83cb686c824" + }, + { + "unit": 13, + "layers": 1, + "decoder": 1, + "out_digest": "3a1e42600a46cf28926fc9f03946a3186264cef938e207b9e159591c179fa7ed" + }, + { + "unit": 14, + "layers": 1, + "decoder": 0, + "out_digest": "49eac1e814988d0a60db8a709e70f4a1989819a57e26b92bdd0239c338675c58" + }, + { + "unit": 15, + "layers": 1, + "decoder": 1, + "out_digest": "cd3ac56e7dc49f235a245024c0c560cc19ba73fcc0dfb1d38ff9f58bb180d5db" + }, + { + "unit": 16, + "layers": 1, + "decoder": 0, + "out_digest": "b3c7f2ac61734e3390450d0f34c70f733b20db0c29d8ea634c0fc0a8638f2258" + }, + { + "unit": 17, + "layers": 1, + "decoder": 1, + "out_digest": "64b919c5441af6df04b8563a34fe9fe57b84e802b1856a98e1edafc328e809d6" + }, + { + "unit": 18, + "layers": 1, + "decoder": 0, + "out_digest": "e120f02a7fffc970d4a82e4afa8c7d29a00b06a10a7d9fcbf49edacff256ed1d" + }, + { + "unit": 19, + "layers": 1, + "decoder": 1, + "out_digest": "68aee1cd87a8224bc389c297e3b001e9e842f5f416eaeda4b1aafa365e042d46" + }, + { + "unit": 20, + "layers": 1, + "decoder": 0, + "out_digest": "01d364fffad3148204e1cebc263ab9c8818eab8969da5fcbc5794392d170ad6c" + }, + { + "unit": 21, + "layers": 1, + "decoder": 1, + "out_digest": "7c587829be53d8fd83fa843e9b2d1ae7567637256ffa2b00dc5a12b6b3d2bfbd" + }, + { + "unit": 22, + "layers": 1, + "decoder": 0, + "out_digest": "8bf65e08db2dc14a138df5c114940e28396ffe2279278732321dda8d2e377061" + }, + { + "unit": 23, + "layers": 1, + "decoder": 1, + "out_digest": "da305639e012f936cb52ac1b9d044a1ca6a808036325d4a951e5b06382822efe" + } + ], + "redecoded": [ + { + "index": 0, + "out_digest": "55f7e628ca707e2ca3159709eeb68b9000813f2916a299acd33a23e6fe012584" + }, + { + "index": 1, + "out_digest": "9df7f2652febf9fe462ff426af1ee3ec158bf203c59392654482b80775804556" + }, + { + "index": 2, + "out_digest": "00576d2c4d09ef5d7aa807f9b3b1587e200dea6f6694b4da062b41aa2a5ab8af" + }, + { + "index": 3, + "out_digest": "5541d29e4f230e7683ad45c081f4f325fa6216f308b1682f621b3ed279fc39f8" + }, + { + "index": 4, + "out_digest": "1cd1984bc553c43ee5a48fe7e182a77e60d8ef3c2b0f959ef1a0efd3813b411f" + }, + { + "index": 5, + "out_digest": "67754c573f1f7605becf03e65bffa704359b96917b5bc203901eb10e32182cf1" + }, + { + "index": 6, + "out_digest": "95542e01dfb7d7c52f2d526bf932ee49cf081ee2bc330c42dd0715cca7deff8b" + }, + { + "index": 7, + "out_digest": "e7f6d40664240de8fe0eea2384891d0f040db6f05dca8450533a725410bfd31f" + }, + { + "index": 8, + "out_digest": "5c01f526973ca7dbcde1513bc7d25333954bc4164811a5f21399b6e48d89079d" + }, + { + "index": 9, + "out_digest": "f3ff8b3d08e7010fb0d5f7c836dc8b5969bcc95a73ae76813443a2b70929b6bb" + }, + { + "index": 10, + "out_digest": "23851d2c5e0cc5365e329fbd9c01238313ac71fd4edb4730fa7d58cc74e74823" + }, + { + "index": 11, + "out_digest": "9469cdcb42fe46fe46e0e0bb0e10f3397dc5048a60b81467183939f1e4548f74" + }, + { + "index": 12, + "out_digest": "47c089823c210a1989895087dc4d44dc5ed8ee0453d7f2517ccce83cb686c824" + }, + { + "index": 13, + "out_digest": "eca166a3ea198bf0271543d5428c3e0323063de0d3352fbde485399d4476a92b" + }, + { + "index": 14, + "out_digest": "49eac1e814988d0a60db8a709e70f4a1989819a57e26b92bdd0239c338675c58" + }, + { + "index": 15, + "out_digest": "fd7ac5bfaf32d59c57faba74ff87b0a09aae703323a147fef03adf7b2761cb1d" + }, + { + "index": 16, + "out_digest": "b3c7f2ac61734e3390450d0f34c70f733b20db0c29d8ea634c0fc0a8638f2258" + }, + { + "index": 17, + "out_digest": "b7988f6a6e8844ff5ec686f9290b0b4ab0c5c3c028b5e9be116e12821b851534" + }, + { + "index": 18, + "out_digest": "e120f02a7fffc970d4a82e4afa8c7d29a00b06a10a7d9fcbf49edacff256ed1d" + }, + { + "index": 19, + "out_digest": "9436e6edd6411835af7500432df9c51a17b590217e97e642f20820df0323387a" + }, + { + "index": 20, + "out_digest": "01d364fffad3148204e1cebc263ab9c8818eab8969da5fcbc5794392d170ad6c" + }, + { + "index": 21, + "out_digest": "68c5337faac08354c20caec0d0e7221de83055c34f8427195a1ecd9fa2f067ba" + }, + { + "index": 22, + "out_digest": "8bf65e08db2dc14a138df5c114940e28396ffe2279278732321dda8d2e377061" + }, + { + "index": 23, + "out_digest": "8d57033cf933cd97f91d56fb405ed39c23193b39c0ad84a9facb60bd7e74db5f" + } + ] + }, + "expected": { + "outcome": "accept", + "link_hash": "bf3a214788f4e54508b6c4b741b7005a406dbb30e4fd32aded888366ee1812be" + } + }, + { + "name": "session_tree_25", + "about": "an output tree of 25 leaves, half on a byte-exact decoder whose re-decode matches and half checked for membership only, whose re-decode does not and is not checked", + "procedure": "claim", + "receipt": "{\"body\":{\"classical_declared\":700,\"classical_source\":\"wai2-table\",\"counted_discarded\":1904,\"counted_fallback\":0,\"counted_primary\":5607,\"deadline_us\":null,\"decoders\":[{\"capability\":\"wai.video.int_hyper\",\"decoder\":\"builtin:wai@0.4.0\",\"leaves\":13,\"module_status\":null,\"path\":\"primary\",\"pin\":\"7b4371854df0aa1645ac6525b373387c0617b873d5a57748932ee0f386ea164b\",\"rendition\":0,\"tier\":\"decode-equivalence\",\"variant\":null},{\"capability\":\"wai.video.av1\",\"decoder\":\"builtin:wai@0.4.0\",\"leaves\":12,\"module_status\":null,\"path\":\"fallback\",\"pin\":null,\"rendition\":null,\"tier\":null,\"variant\":null}],\"energy\":null,\"fallback_units\":12,\"framing\":\"registered\",\"host\":{\"build\":{\"profile\":\"release\",\"target\":\"aarch64-unknown-linux-gnu\",\"toolchain\":\"rustc 1.95.0\"},\"profile\":\"native-ffi\",\"target\":\"aarch64-unknown-linux-gnu\",\"threads\":4},\"leaf_count\":25,\"media\":\"video\",\"missed\":0,\"missed_units\":[],\"output_root\":\"6a319e4ce53ced0062c395e423842bc9af41bd7d68f95898b03e26a5e75f4255\",\"primary_units\":13,\"receipt_bytes\":640,\"session_nonce\":\"57c5462dfdabd1b7bdd204d34ba33649c057eb535349f29f45eb8f8c7d4a7e7f\",\"stage_sets\":[],\"switches\":[],\"switches_total\":0,\"transferred\":13607,\"uncounted\":2,\"units\":25},\"class\":\"reconstruct-session\",\"issued_at\":\"2026-09-27T12:00:00Z\",\"kind\":\"claim\",\"parent_receipt_hash\":null,\"seq\":0,\"sig\":\"74cd16defa80844792ddba56c2270d2e8ed149ddf62abd84832c2f2fc093d2e84fed9289cdd2afccfdf02f94c36d8e16defcd06cf8411c46f53a1585c9cc5b06\",\"signer_id\":\"did:example:sink\",\"signer_pubkey\":\"d759793bbc13a2819a827c76adb6fba8a49aee007f49f2d0992d99b825ad2c48\",\"subject\":\"64c0713cb176874607bf8670295242184b7868a9ff7c55554a5ae08de2c301c1\",\"subject_type\":\"object\"}", + "context": { + "outputs": [ + { + "unit": 0, + "layers": 1, + "decoder": 0, + "out_digest": "55f7e628ca707e2ca3159709eeb68b9000813f2916a299acd33a23e6fe012584" + }, + { + "unit": 1, + "layers": 1, + "decoder": 1, + "out_digest": "a3ee8a4b96eceb663f3d94417957d02f897fc166dc96ebe9bf447c4a36a36264" + }, + { + "unit": 2, + "layers": 1, + "decoder": 0, + "out_digest": "00576d2c4d09ef5d7aa807f9b3b1587e200dea6f6694b4da062b41aa2a5ab8af" + }, + { + "unit": 3, + "layers": 1, + "decoder": 1, + "out_digest": "26cd9b2805b604b26e08d9a461db599c4e249bfd4df41a3befb202bc6d0e0700" + }, + { + "unit": 4, + "layers": 1, + "decoder": 0, + "out_digest": "1cd1984bc553c43ee5a48fe7e182a77e60d8ef3c2b0f959ef1a0efd3813b411f" + }, + { + "unit": 5, + "layers": 1, + "decoder": 1, + "out_digest": "e4c4344155dc2c789a1df265f8064b9ae56f3e0932d85c5ceb38782c135749fc" + }, + { + "unit": 6, + "layers": 1, + "decoder": 0, + "out_digest": "95542e01dfb7d7c52f2d526bf932ee49cf081ee2bc330c42dd0715cca7deff8b" + }, + { + "unit": 7, + "layers": 1, + "decoder": 1, + "out_digest": "cf1c65a8bc3fabc40710f610dcfa9ac2604f45a6fa68f74ee2b464421647da4c" + }, + { + "unit": 8, + "layers": 1, + "decoder": 0, + "out_digest": "5c01f526973ca7dbcde1513bc7d25333954bc4164811a5f21399b6e48d89079d" + }, + { + "unit": 9, + "layers": 1, + "decoder": 1, + "out_digest": "686ff0277613c58687a493af12da86b393bcee283c6758845a2505a93d135905" + }, + { + "unit": 10, + "layers": 1, + "decoder": 0, + "out_digest": "23851d2c5e0cc5365e329fbd9c01238313ac71fd4edb4730fa7d58cc74e74823" + }, + { + "unit": 11, + "layers": 1, + "decoder": 1, + "out_digest": "66270813e69c6cffbacb67f95a9c182b2f04ce8c3b2ee4829c257227a5f4a17a" + }, + { + "unit": 12, + "layers": 1, + "decoder": 0, + "out_digest": "47c089823c210a1989895087dc4d44dc5ed8ee0453d7f2517ccce83cb686c824" + }, + { + "unit": 13, + "layers": 1, + "decoder": 1, + "out_digest": "3a1e42600a46cf28926fc9f03946a3186264cef938e207b9e159591c179fa7ed" + }, + { + "unit": 14, + "layers": 1, + "decoder": 0, + "out_digest": "49eac1e814988d0a60db8a709e70f4a1989819a57e26b92bdd0239c338675c58" + }, + { + "unit": 15, + "layers": 1, + "decoder": 1, + "out_digest": "cd3ac56e7dc49f235a245024c0c560cc19ba73fcc0dfb1d38ff9f58bb180d5db" + }, + { + "unit": 16, + "layers": 1, + "decoder": 0, + "out_digest": "b3c7f2ac61734e3390450d0f34c70f733b20db0c29d8ea634c0fc0a8638f2258" + }, + { + "unit": 17, + "layers": 1, + "decoder": 1, + "out_digest": "64b919c5441af6df04b8563a34fe9fe57b84e802b1856a98e1edafc328e809d6" + }, + { + "unit": 18, + "layers": 1, + "decoder": 0, + "out_digest": "e120f02a7fffc970d4a82e4afa8c7d29a00b06a10a7d9fcbf49edacff256ed1d" + }, + { + "unit": 19, + "layers": 1, + "decoder": 1, + "out_digest": "68aee1cd87a8224bc389c297e3b001e9e842f5f416eaeda4b1aafa365e042d46" + }, + { + "unit": 20, + "layers": 1, + "decoder": 0, + "out_digest": "01d364fffad3148204e1cebc263ab9c8818eab8969da5fcbc5794392d170ad6c" + }, + { + "unit": 21, + "layers": 1, + "decoder": 1, + "out_digest": "7c587829be53d8fd83fa843e9b2d1ae7567637256ffa2b00dc5a12b6b3d2bfbd" + }, + { + "unit": 22, + "layers": 1, + "decoder": 0, + "out_digest": "8bf65e08db2dc14a138df5c114940e28396ffe2279278732321dda8d2e377061" + }, + { + "unit": 23, + "layers": 1, + "decoder": 1, + "out_digest": "da305639e012f936cb52ac1b9d044a1ca6a808036325d4a951e5b06382822efe" + }, + { + "unit": 24, + "layers": 1, + "decoder": 0, + "out_digest": "223468b0ac64c3b09969e414a560b3aa8f880064facff95098e12adb723bbfdc" + } + ], + "redecoded": [ + { + "index": 0, + "out_digest": "55f7e628ca707e2ca3159709eeb68b9000813f2916a299acd33a23e6fe012584" + }, + { + "index": 1, + "out_digest": "9df7f2652febf9fe462ff426af1ee3ec158bf203c59392654482b80775804556" + }, + { + "index": 2, + "out_digest": "00576d2c4d09ef5d7aa807f9b3b1587e200dea6f6694b4da062b41aa2a5ab8af" + }, + { + "index": 3, + "out_digest": "5541d29e4f230e7683ad45c081f4f325fa6216f308b1682f621b3ed279fc39f8" + }, + { + "index": 4, + "out_digest": "1cd1984bc553c43ee5a48fe7e182a77e60d8ef3c2b0f959ef1a0efd3813b411f" + }, + { + "index": 5, + "out_digest": "67754c573f1f7605becf03e65bffa704359b96917b5bc203901eb10e32182cf1" + }, + { + "index": 6, + "out_digest": "95542e01dfb7d7c52f2d526bf932ee49cf081ee2bc330c42dd0715cca7deff8b" + }, + { + "index": 7, + "out_digest": "e7f6d40664240de8fe0eea2384891d0f040db6f05dca8450533a725410bfd31f" + }, + { + "index": 8, + "out_digest": "5c01f526973ca7dbcde1513bc7d25333954bc4164811a5f21399b6e48d89079d" + }, + { + "index": 9, + "out_digest": "f3ff8b3d08e7010fb0d5f7c836dc8b5969bcc95a73ae76813443a2b70929b6bb" + }, + { + "index": 10, + "out_digest": "23851d2c5e0cc5365e329fbd9c01238313ac71fd4edb4730fa7d58cc74e74823" + }, + { + "index": 11, + "out_digest": "9469cdcb42fe46fe46e0e0bb0e10f3397dc5048a60b81467183939f1e4548f74" + }, + { + "index": 12, + "out_digest": "47c089823c210a1989895087dc4d44dc5ed8ee0453d7f2517ccce83cb686c824" + }, + { + "index": 13, + "out_digest": "eca166a3ea198bf0271543d5428c3e0323063de0d3352fbde485399d4476a92b" + }, + { + "index": 14, + "out_digest": "49eac1e814988d0a60db8a709e70f4a1989819a57e26b92bdd0239c338675c58" + }, + { + "index": 15, + "out_digest": "fd7ac5bfaf32d59c57faba74ff87b0a09aae703323a147fef03adf7b2761cb1d" + }, + { + "index": 16, + "out_digest": "b3c7f2ac61734e3390450d0f34c70f733b20db0c29d8ea634c0fc0a8638f2258" + }, + { + "index": 17, + "out_digest": "b7988f6a6e8844ff5ec686f9290b0b4ab0c5c3c028b5e9be116e12821b851534" + }, + { + "index": 18, + "out_digest": "e120f02a7fffc970d4a82e4afa8c7d29a00b06a10a7d9fcbf49edacff256ed1d" + }, + { + "index": 19, + "out_digest": "9436e6edd6411835af7500432df9c51a17b590217e97e642f20820df0323387a" + }, + { + "index": 20, + "out_digest": "01d364fffad3148204e1cebc263ab9c8818eab8969da5fcbc5794392d170ad6c" + }, + { + "index": 21, + "out_digest": "68c5337faac08354c20caec0d0e7221de83055c34f8427195a1ecd9fa2f067ba" + }, + { + "index": 22, + "out_digest": "8bf65e08db2dc14a138df5c114940e28396ffe2279278732321dda8d2e377061" + }, + { + "index": 23, + "out_digest": "8d57033cf933cd97f91d56fb405ed39c23193b39c0ad84a9facb60bd7e74db5f" + }, + { + "index": 24, + "out_digest": "223468b0ac64c3b09969e414a560b3aa8f880064facff95098e12adb723bbfdc" + } + ] + }, + "expected": { + "outcome": "accept", + "link_hash": "2faf4f5f962fc7a31841ce4e6598c1b7525cb1fe01381ddf08de4ceece16c202" + } + }, + { + "name": "session_tree_26", + "about": "an output tree of 26 leaves, half on a byte-exact decoder whose re-decode matches and half checked for membership only, whose re-decode does not and is not checked", + "procedure": "claim", + "receipt": "{\"body\":{\"classical_declared\":700,\"classical_source\":\"wai2-table\",\"counted_discarded\":1904,\"counted_fallback\":0,\"counted_primary\":5607,\"deadline_us\":null,\"decoders\":[{\"capability\":\"wai.video.int_hyper\",\"decoder\":\"builtin:wai@0.4.0\",\"leaves\":13,\"module_status\":null,\"path\":\"primary\",\"pin\":\"7b4371854df0aa1645ac6525b373387c0617b873d5a57748932ee0f386ea164b\",\"rendition\":0,\"tier\":\"decode-equivalence\",\"variant\":null},{\"capability\":\"wai.video.av1\",\"decoder\":\"builtin:wai@0.4.0\",\"leaves\":13,\"module_status\":null,\"path\":\"fallback\",\"pin\":null,\"rendition\":null,\"tier\":null,\"variant\":null}],\"energy\":null,\"fallback_units\":13,\"framing\":\"registered\",\"host\":{\"build\":{\"profile\":\"release\",\"target\":\"aarch64-unknown-linux-gnu\",\"toolchain\":\"rustc 1.95.0\"},\"profile\":\"native-ffi\",\"target\":\"aarch64-unknown-linux-gnu\",\"threads\":4},\"leaf_count\":26,\"media\":\"video\",\"missed\":0,\"missed_units\":[],\"output_root\":\"331b342dee8be26cbe3849aea25a508d9586027ca277621c82d5ee07556a0395\",\"primary_units\":13,\"receipt_bytes\":640,\"session_nonce\":\"57c5462dfdabd1b7bdd204d34ba33649c057eb535349f29f45eb8f8c7d4a7e7f\",\"stage_sets\":[],\"switches\":[],\"switches_total\":0,\"transferred\":13607,\"uncounted\":2,\"units\":26},\"class\":\"reconstruct-session\",\"issued_at\":\"2026-09-27T12:00:00Z\",\"kind\":\"claim\",\"parent_receipt_hash\":null,\"seq\":0,\"sig\":\"7c25fce7d7f9be52e9f6ed5cbe5adb7b5686030bd1c4d7f9c328ca35a5885658480535abee73b84d65e4379d613cabbbd8e85c828525e4479189156640fb1f08\",\"signer_id\":\"did:example:sink\",\"signer_pubkey\":\"d759793bbc13a2819a827c76adb6fba8a49aee007f49f2d0992d99b825ad2c48\",\"subject\":\"64c0713cb176874607bf8670295242184b7868a9ff7c55554a5ae08de2c301c1\",\"subject_type\":\"object\"}", + "context": { + "outputs": [ + { + "unit": 0, + "layers": 1, + "decoder": 0, + "out_digest": "55f7e628ca707e2ca3159709eeb68b9000813f2916a299acd33a23e6fe012584" + }, + { + "unit": 1, + "layers": 1, + "decoder": 1, + "out_digest": "a3ee8a4b96eceb663f3d94417957d02f897fc166dc96ebe9bf447c4a36a36264" + }, + { + "unit": 2, + "layers": 1, + "decoder": 0, + "out_digest": "00576d2c4d09ef5d7aa807f9b3b1587e200dea6f6694b4da062b41aa2a5ab8af" + }, + { + "unit": 3, + "layers": 1, + "decoder": 1, + "out_digest": "26cd9b2805b604b26e08d9a461db599c4e249bfd4df41a3befb202bc6d0e0700" + }, + { + "unit": 4, + "layers": 1, + "decoder": 0, + "out_digest": "1cd1984bc553c43ee5a48fe7e182a77e60d8ef3c2b0f959ef1a0efd3813b411f" + }, + { + "unit": 5, + "layers": 1, + "decoder": 1, + "out_digest": "e4c4344155dc2c789a1df265f8064b9ae56f3e0932d85c5ceb38782c135749fc" + }, + { + "unit": 6, + "layers": 1, + "decoder": 0, + "out_digest": "95542e01dfb7d7c52f2d526bf932ee49cf081ee2bc330c42dd0715cca7deff8b" + }, + { + "unit": 7, + "layers": 1, + "decoder": 1, + "out_digest": "cf1c65a8bc3fabc40710f610dcfa9ac2604f45a6fa68f74ee2b464421647da4c" + }, + { + "unit": 8, + "layers": 1, + "decoder": 0, + "out_digest": "5c01f526973ca7dbcde1513bc7d25333954bc4164811a5f21399b6e48d89079d" + }, + { + "unit": 9, + "layers": 1, + "decoder": 1, + "out_digest": "686ff0277613c58687a493af12da86b393bcee283c6758845a2505a93d135905" + }, + { + "unit": 10, + "layers": 1, + "decoder": 0, + "out_digest": "23851d2c5e0cc5365e329fbd9c01238313ac71fd4edb4730fa7d58cc74e74823" + }, + { + "unit": 11, + "layers": 1, + "decoder": 1, + "out_digest": "66270813e69c6cffbacb67f95a9c182b2f04ce8c3b2ee4829c257227a5f4a17a" + }, + { + "unit": 12, + "layers": 1, + "decoder": 0, + "out_digest": "47c089823c210a1989895087dc4d44dc5ed8ee0453d7f2517ccce83cb686c824" + }, + { + "unit": 13, + "layers": 1, + "decoder": 1, + "out_digest": "3a1e42600a46cf28926fc9f03946a3186264cef938e207b9e159591c179fa7ed" + }, + { + "unit": 14, + "layers": 1, + "decoder": 0, + "out_digest": "49eac1e814988d0a60db8a709e70f4a1989819a57e26b92bdd0239c338675c58" + }, + { + "unit": 15, + "layers": 1, + "decoder": 1, + "out_digest": "cd3ac56e7dc49f235a245024c0c560cc19ba73fcc0dfb1d38ff9f58bb180d5db" + }, + { + "unit": 16, + "layers": 1, + "decoder": 0, + "out_digest": "b3c7f2ac61734e3390450d0f34c70f733b20db0c29d8ea634c0fc0a8638f2258" + }, + { + "unit": 17, + "layers": 1, + "decoder": 1, + "out_digest": "64b919c5441af6df04b8563a34fe9fe57b84e802b1856a98e1edafc328e809d6" + }, + { + "unit": 18, + "layers": 1, + "decoder": 0, + "out_digest": "e120f02a7fffc970d4a82e4afa8c7d29a00b06a10a7d9fcbf49edacff256ed1d" + }, + { + "unit": 19, + "layers": 1, + "decoder": 1, + "out_digest": "68aee1cd87a8224bc389c297e3b001e9e842f5f416eaeda4b1aafa365e042d46" + }, + { + "unit": 20, + "layers": 1, + "decoder": 0, + "out_digest": "01d364fffad3148204e1cebc263ab9c8818eab8969da5fcbc5794392d170ad6c" + }, + { + "unit": 21, + "layers": 1, + "decoder": 1, + "out_digest": "7c587829be53d8fd83fa843e9b2d1ae7567637256ffa2b00dc5a12b6b3d2bfbd" + }, + { + "unit": 22, + "layers": 1, + "decoder": 0, + "out_digest": "8bf65e08db2dc14a138df5c114940e28396ffe2279278732321dda8d2e377061" + }, + { + "unit": 23, + "layers": 1, + "decoder": 1, + "out_digest": "da305639e012f936cb52ac1b9d044a1ca6a808036325d4a951e5b06382822efe" + }, + { + "unit": 24, + "layers": 1, + "decoder": 0, + "out_digest": "223468b0ac64c3b09969e414a560b3aa8f880064facff95098e12adb723bbfdc" + }, + { + "unit": 25, + "layers": 1, + "decoder": 1, + "out_digest": "2729200cc60d2fced7b6111aa8579fe341910e7cc3e656ac58be6506be7edd09" + } + ], + "redecoded": [ + { + "index": 0, + "out_digest": "55f7e628ca707e2ca3159709eeb68b9000813f2916a299acd33a23e6fe012584" + }, + { + "index": 1, + "out_digest": "9df7f2652febf9fe462ff426af1ee3ec158bf203c59392654482b80775804556" + }, + { + "index": 2, + "out_digest": "00576d2c4d09ef5d7aa807f9b3b1587e200dea6f6694b4da062b41aa2a5ab8af" + }, + { + "index": 3, + "out_digest": "5541d29e4f230e7683ad45c081f4f325fa6216f308b1682f621b3ed279fc39f8" + }, + { + "index": 4, + "out_digest": "1cd1984bc553c43ee5a48fe7e182a77e60d8ef3c2b0f959ef1a0efd3813b411f" + }, + { + "index": 5, + "out_digest": "67754c573f1f7605becf03e65bffa704359b96917b5bc203901eb10e32182cf1" + }, + { + "index": 6, + "out_digest": "95542e01dfb7d7c52f2d526bf932ee49cf081ee2bc330c42dd0715cca7deff8b" + }, + { + "index": 7, + "out_digest": "e7f6d40664240de8fe0eea2384891d0f040db6f05dca8450533a725410bfd31f" + }, + { + "index": 8, + "out_digest": "5c01f526973ca7dbcde1513bc7d25333954bc4164811a5f21399b6e48d89079d" + }, + { + "index": 9, + "out_digest": "f3ff8b3d08e7010fb0d5f7c836dc8b5969bcc95a73ae76813443a2b70929b6bb" + }, + { + "index": 10, + "out_digest": "23851d2c5e0cc5365e329fbd9c01238313ac71fd4edb4730fa7d58cc74e74823" + }, + { + "index": 11, + "out_digest": "9469cdcb42fe46fe46e0e0bb0e10f3397dc5048a60b81467183939f1e4548f74" + }, + { + "index": 12, + "out_digest": "47c089823c210a1989895087dc4d44dc5ed8ee0453d7f2517ccce83cb686c824" + }, + { + "index": 13, + "out_digest": "eca166a3ea198bf0271543d5428c3e0323063de0d3352fbde485399d4476a92b" + }, + { + "index": 14, + "out_digest": "49eac1e814988d0a60db8a709e70f4a1989819a57e26b92bdd0239c338675c58" + }, + { + "index": 15, + "out_digest": "fd7ac5bfaf32d59c57faba74ff87b0a09aae703323a147fef03adf7b2761cb1d" + }, + { + "index": 16, + "out_digest": "b3c7f2ac61734e3390450d0f34c70f733b20db0c29d8ea634c0fc0a8638f2258" + }, + { + "index": 17, + "out_digest": "b7988f6a6e8844ff5ec686f9290b0b4ab0c5c3c028b5e9be116e12821b851534" + }, + { + "index": 18, + "out_digest": "e120f02a7fffc970d4a82e4afa8c7d29a00b06a10a7d9fcbf49edacff256ed1d" + }, + { + "index": 19, + "out_digest": "9436e6edd6411835af7500432df9c51a17b590217e97e642f20820df0323387a" + }, + { + "index": 20, + "out_digest": "01d364fffad3148204e1cebc263ab9c8818eab8969da5fcbc5794392d170ad6c" + }, + { + "index": 21, + "out_digest": "68c5337faac08354c20caec0d0e7221de83055c34f8427195a1ecd9fa2f067ba" + }, + { + "index": 22, + "out_digest": "8bf65e08db2dc14a138df5c114940e28396ffe2279278732321dda8d2e377061" + }, + { + "index": 23, + "out_digest": "8d57033cf933cd97f91d56fb405ed39c23193b39c0ad84a9facb60bd7e74db5f" + }, + { + "index": 24, + "out_digest": "223468b0ac64c3b09969e414a560b3aa8f880064facff95098e12adb723bbfdc" + }, + { + "index": 25, + "out_digest": "1ba9767da05df2f37c42c86f246b933f82b600c0af4f8375cfa7f61b671d1569" + } + ] + }, + "expected": { + "outcome": "accept", + "link_hash": "f00243712254220a22b74e106a3bf6edb9dc8087fae513e26790833a7cf777a4" + } + }, + { + "name": "session_tree_27", + "about": "an output tree of 27 leaves, half on a byte-exact decoder whose re-decode matches and half checked for membership only, whose re-decode does not and is not checked", + "procedure": "claim", + "receipt": "{\"body\":{\"classical_declared\":700,\"classical_source\":\"wai2-table\",\"counted_discarded\":1904,\"counted_fallback\":0,\"counted_primary\":5607,\"deadline_us\":null,\"decoders\":[{\"capability\":\"wai.video.int_hyper\",\"decoder\":\"builtin:wai@0.4.0\",\"leaves\":14,\"module_status\":null,\"path\":\"primary\",\"pin\":\"7b4371854df0aa1645ac6525b373387c0617b873d5a57748932ee0f386ea164b\",\"rendition\":0,\"tier\":\"decode-equivalence\",\"variant\":null},{\"capability\":\"wai.video.av1\",\"decoder\":\"builtin:wai@0.4.0\",\"leaves\":13,\"module_status\":null,\"path\":\"fallback\",\"pin\":null,\"rendition\":null,\"tier\":null,\"variant\":null}],\"energy\":null,\"fallback_units\":13,\"framing\":\"registered\",\"host\":{\"build\":{\"profile\":\"release\",\"target\":\"aarch64-unknown-linux-gnu\",\"toolchain\":\"rustc 1.95.0\"},\"profile\":\"native-ffi\",\"target\":\"aarch64-unknown-linux-gnu\",\"threads\":4},\"leaf_count\":27,\"media\":\"video\",\"missed\":0,\"missed_units\":[],\"output_root\":\"c1bf47037d75653268c19bbc5db2ecad9687ca692052410bc841d75a4df69ed8\",\"primary_units\":14,\"receipt_bytes\":640,\"session_nonce\":\"57c5462dfdabd1b7bdd204d34ba33649c057eb535349f29f45eb8f8c7d4a7e7f\",\"stage_sets\":[],\"switches\":[],\"switches_total\":0,\"transferred\":13607,\"uncounted\":2,\"units\":27},\"class\":\"reconstruct-session\",\"issued_at\":\"2026-09-27T12:00:00Z\",\"kind\":\"claim\",\"parent_receipt_hash\":null,\"seq\":0,\"sig\":\"5dcc7689de7e4c0d5b0fed8b6a5ebd8ccfc7113aca0bcbc37cb9825547c06804ff18b969381154c107fe1a1451eb605f2f8c5cd99de85fbb01c7a2b2d29ae60c\",\"signer_id\":\"did:example:sink\",\"signer_pubkey\":\"d759793bbc13a2819a827c76adb6fba8a49aee007f49f2d0992d99b825ad2c48\",\"subject\":\"64c0713cb176874607bf8670295242184b7868a9ff7c55554a5ae08de2c301c1\",\"subject_type\":\"object\"}", + "context": { + "outputs": [ + { + "unit": 0, + "layers": 1, + "decoder": 0, + "out_digest": "55f7e628ca707e2ca3159709eeb68b9000813f2916a299acd33a23e6fe012584" + }, + { + "unit": 1, + "layers": 1, + "decoder": 1, + "out_digest": "a3ee8a4b96eceb663f3d94417957d02f897fc166dc96ebe9bf447c4a36a36264" + }, + { + "unit": 2, + "layers": 1, + "decoder": 0, + "out_digest": "00576d2c4d09ef5d7aa807f9b3b1587e200dea6f6694b4da062b41aa2a5ab8af" + }, + { + "unit": 3, + "layers": 1, + "decoder": 1, + "out_digest": "26cd9b2805b604b26e08d9a461db599c4e249bfd4df41a3befb202bc6d0e0700" + }, + { + "unit": 4, + "layers": 1, + "decoder": 0, + "out_digest": "1cd1984bc553c43ee5a48fe7e182a77e60d8ef3c2b0f959ef1a0efd3813b411f" + }, + { + "unit": 5, + "layers": 1, + "decoder": 1, + "out_digest": "e4c4344155dc2c789a1df265f8064b9ae56f3e0932d85c5ceb38782c135749fc" + }, + { + "unit": 6, + "layers": 1, + "decoder": 0, + "out_digest": "95542e01dfb7d7c52f2d526bf932ee49cf081ee2bc330c42dd0715cca7deff8b" + }, + { + "unit": 7, + "layers": 1, + "decoder": 1, + "out_digest": "cf1c65a8bc3fabc40710f610dcfa9ac2604f45a6fa68f74ee2b464421647da4c" + }, + { + "unit": 8, + "layers": 1, + "decoder": 0, + "out_digest": "5c01f526973ca7dbcde1513bc7d25333954bc4164811a5f21399b6e48d89079d" + }, + { + "unit": 9, + "layers": 1, + "decoder": 1, + "out_digest": "686ff0277613c58687a493af12da86b393bcee283c6758845a2505a93d135905" + }, + { + "unit": 10, + "layers": 1, + "decoder": 0, + "out_digest": "23851d2c5e0cc5365e329fbd9c01238313ac71fd4edb4730fa7d58cc74e74823" + }, + { + "unit": 11, + "layers": 1, + "decoder": 1, + "out_digest": "66270813e69c6cffbacb67f95a9c182b2f04ce8c3b2ee4829c257227a5f4a17a" + }, + { + "unit": 12, + "layers": 1, + "decoder": 0, + "out_digest": "47c089823c210a1989895087dc4d44dc5ed8ee0453d7f2517ccce83cb686c824" + }, + { + "unit": 13, + "layers": 1, + "decoder": 1, + "out_digest": "3a1e42600a46cf28926fc9f03946a3186264cef938e207b9e159591c179fa7ed" + }, + { + "unit": 14, + "layers": 1, + "decoder": 0, + "out_digest": "49eac1e814988d0a60db8a709e70f4a1989819a57e26b92bdd0239c338675c58" + }, + { + "unit": 15, + "layers": 1, + "decoder": 1, + "out_digest": "cd3ac56e7dc49f235a245024c0c560cc19ba73fcc0dfb1d38ff9f58bb180d5db" + }, + { + "unit": 16, + "layers": 1, + "decoder": 0, + "out_digest": "b3c7f2ac61734e3390450d0f34c70f733b20db0c29d8ea634c0fc0a8638f2258" + }, + { + "unit": 17, + "layers": 1, + "decoder": 1, + "out_digest": "64b919c5441af6df04b8563a34fe9fe57b84e802b1856a98e1edafc328e809d6" + }, + { + "unit": 18, + "layers": 1, + "decoder": 0, + "out_digest": "e120f02a7fffc970d4a82e4afa8c7d29a00b06a10a7d9fcbf49edacff256ed1d" + }, + { + "unit": 19, + "layers": 1, + "decoder": 1, + "out_digest": "68aee1cd87a8224bc389c297e3b001e9e842f5f416eaeda4b1aafa365e042d46" + }, + { + "unit": 20, + "layers": 1, + "decoder": 0, + "out_digest": "01d364fffad3148204e1cebc263ab9c8818eab8969da5fcbc5794392d170ad6c" + }, + { + "unit": 21, + "layers": 1, + "decoder": 1, + "out_digest": "7c587829be53d8fd83fa843e9b2d1ae7567637256ffa2b00dc5a12b6b3d2bfbd" + }, + { + "unit": 22, + "layers": 1, + "decoder": 0, + "out_digest": "8bf65e08db2dc14a138df5c114940e28396ffe2279278732321dda8d2e377061" + }, + { + "unit": 23, + "layers": 1, + "decoder": 1, + "out_digest": "da305639e012f936cb52ac1b9d044a1ca6a808036325d4a951e5b06382822efe" + }, + { + "unit": 24, + "layers": 1, + "decoder": 0, + "out_digest": "223468b0ac64c3b09969e414a560b3aa8f880064facff95098e12adb723bbfdc" + }, + { + "unit": 25, + "layers": 1, + "decoder": 1, + "out_digest": "2729200cc60d2fced7b6111aa8579fe341910e7cc3e656ac58be6506be7edd09" + }, + { + "unit": 26, + "layers": 1, + "decoder": 0, + "out_digest": "3bbb7b537ed2dacc3ccb2880227a23bab4b6137c3c12e1cdda8b0a11a808ca5b" + } + ], + "redecoded": [ + { + "index": 0, + "out_digest": "55f7e628ca707e2ca3159709eeb68b9000813f2916a299acd33a23e6fe012584" + }, + { + "index": 1, + "out_digest": "9df7f2652febf9fe462ff426af1ee3ec158bf203c59392654482b80775804556" + }, + { + "index": 2, + "out_digest": "00576d2c4d09ef5d7aa807f9b3b1587e200dea6f6694b4da062b41aa2a5ab8af" + }, + { + "index": 3, + "out_digest": "5541d29e4f230e7683ad45c081f4f325fa6216f308b1682f621b3ed279fc39f8" + }, + { + "index": 4, + "out_digest": "1cd1984bc553c43ee5a48fe7e182a77e60d8ef3c2b0f959ef1a0efd3813b411f" + }, + { + "index": 5, + "out_digest": "67754c573f1f7605becf03e65bffa704359b96917b5bc203901eb10e32182cf1" + }, + { + "index": 6, + "out_digest": "95542e01dfb7d7c52f2d526bf932ee49cf081ee2bc330c42dd0715cca7deff8b" + }, + { + "index": 7, + "out_digest": "e7f6d40664240de8fe0eea2384891d0f040db6f05dca8450533a725410bfd31f" + }, + { + "index": 8, + "out_digest": "5c01f526973ca7dbcde1513bc7d25333954bc4164811a5f21399b6e48d89079d" + }, + { + "index": 9, + "out_digest": "f3ff8b3d08e7010fb0d5f7c836dc8b5969bcc95a73ae76813443a2b70929b6bb" + }, + { + "index": 10, + "out_digest": "23851d2c5e0cc5365e329fbd9c01238313ac71fd4edb4730fa7d58cc74e74823" + }, + { + "index": 11, + "out_digest": "9469cdcb42fe46fe46e0e0bb0e10f3397dc5048a60b81467183939f1e4548f74" + }, + { + "index": 12, + "out_digest": "47c089823c210a1989895087dc4d44dc5ed8ee0453d7f2517ccce83cb686c824" + }, + { + "index": 13, + "out_digest": "eca166a3ea198bf0271543d5428c3e0323063de0d3352fbde485399d4476a92b" + }, + { + "index": 14, + "out_digest": "49eac1e814988d0a60db8a709e70f4a1989819a57e26b92bdd0239c338675c58" + }, + { + "index": 15, + "out_digest": "fd7ac5bfaf32d59c57faba74ff87b0a09aae703323a147fef03adf7b2761cb1d" + }, + { + "index": 16, + "out_digest": "b3c7f2ac61734e3390450d0f34c70f733b20db0c29d8ea634c0fc0a8638f2258" + }, + { + "index": 17, + "out_digest": "b7988f6a6e8844ff5ec686f9290b0b4ab0c5c3c028b5e9be116e12821b851534" + }, + { + "index": 18, + "out_digest": "e120f02a7fffc970d4a82e4afa8c7d29a00b06a10a7d9fcbf49edacff256ed1d" + }, + { + "index": 19, + "out_digest": "9436e6edd6411835af7500432df9c51a17b590217e97e642f20820df0323387a" + }, + { + "index": 20, + "out_digest": "01d364fffad3148204e1cebc263ab9c8818eab8969da5fcbc5794392d170ad6c" + }, + { + "index": 21, + "out_digest": "68c5337faac08354c20caec0d0e7221de83055c34f8427195a1ecd9fa2f067ba" + }, + { + "index": 22, + "out_digest": "8bf65e08db2dc14a138df5c114940e28396ffe2279278732321dda8d2e377061" + }, + { + "index": 23, + "out_digest": "8d57033cf933cd97f91d56fb405ed39c23193b39c0ad84a9facb60bd7e74db5f" + }, + { + "index": 24, + "out_digest": "223468b0ac64c3b09969e414a560b3aa8f880064facff95098e12adb723bbfdc" + }, + { + "index": 25, + "out_digest": "1ba9767da05df2f37c42c86f246b933f82b600c0af4f8375cfa7f61b671d1569" + }, + { + "index": 26, + "out_digest": "3bbb7b537ed2dacc3ccb2880227a23bab4b6137c3c12e1cdda8b0a11a808ca5b" + } + ] + }, + "expected": { + "outcome": "accept", + "link_hash": "e31387a0a0434033a54cdfc68098e8ddbc4e6ee8cc70b33f258b8f49ce553f2a" + } + }, + { + "name": "session_tree_28", + "about": "an output tree of 28 leaves, half on a byte-exact decoder whose re-decode matches and half checked for membership only, whose re-decode does not and is not checked", + "procedure": "claim", + "receipt": "{\"body\":{\"classical_declared\":700,\"classical_source\":\"wai2-table\",\"counted_discarded\":1904,\"counted_fallback\":0,\"counted_primary\":5607,\"deadline_us\":null,\"decoders\":[{\"capability\":\"wai.video.int_hyper\",\"decoder\":\"builtin:wai@0.4.0\",\"leaves\":14,\"module_status\":null,\"path\":\"primary\",\"pin\":\"7b4371854df0aa1645ac6525b373387c0617b873d5a57748932ee0f386ea164b\",\"rendition\":0,\"tier\":\"decode-equivalence\",\"variant\":null},{\"capability\":\"wai.video.av1\",\"decoder\":\"builtin:wai@0.4.0\",\"leaves\":14,\"module_status\":null,\"path\":\"fallback\",\"pin\":null,\"rendition\":null,\"tier\":null,\"variant\":null}],\"energy\":null,\"fallback_units\":14,\"framing\":\"registered\",\"host\":{\"build\":{\"profile\":\"release\",\"target\":\"aarch64-unknown-linux-gnu\",\"toolchain\":\"rustc 1.95.0\"},\"profile\":\"native-ffi\",\"target\":\"aarch64-unknown-linux-gnu\",\"threads\":4},\"leaf_count\":28,\"media\":\"video\",\"missed\":0,\"missed_units\":[],\"output_root\":\"e320934292bf4e59bce2231b174ef6f7c535e350808d70c0f26fa4bc095930cc\",\"primary_units\":14,\"receipt_bytes\":640,\"session_nonce\":\"57c5462dfdabd1b7bdd204d34ba33649c057eb535349f29f45eb8f8c7d4a7e7f\",\"stage_sets\":[],\"switches\":[],\"switches_total\":0,\"transferred\":13607,\"uncounted\":2,\"units\":28},\"class\":\"reconstruct-session\",\"issued_at\":\"2026-09-27T12:00:00Z\",\"kind\":\"claim\",\"parent_receipt_hash\":null,\"seq\":0,\"sig\":\"393089b8ea80ecfcc33a27b324cef5c0b4b47cb0a48cb5ac5a68b0c9fc1948b1d7bb374ba4608112015214ec11f4d05345346a9bbc19e7609fac72ddd5f90e02\",\"signer_id\":\"did:example:sink\",\"signer_pubkey\":\"d759793bbc13a2819a827c76adb6fba8a49aee007f49f2d0992d99b825ad2c48\",\"subject\":\"64c0713cb176874607bf8670295242184b7868a9ff7c55554a5ae08de2c301c1\",\"subject_type\":\"object\"}", + "context": { + "outputs": [ + { + "unit": 0, + "layers": 1, + "decoder": 0, + "out_digest": "55f7e628ca707e2ca3159709eeb68b9000813f2916a299acd33a23e6fe012584" + }, + { + "unit": 1, + "layers": 1, + "decoder": 1, + "out_digest": "a3ee8a4b96eceb663f3d94417957d02f897fc166dc96ebe9bf447c4a36a36264" + }, + { + "unit": 2, + "layers": 1, + "decoder": 0, + "out_digest": "00576d2c4d09ef5d7aa807f9b3b1587e200dea6f6694b4da062b41aa2a5ab8af" + }, + { + "unit": 3, + "layers": 1, + "decoder": 1, + "out_digest": "26cd9b2805b604b26e08d9a461db599c4e249bfd4df41a3befb202bc6d0e0700" + }, + { + "unit": 4, + "layers": 1, + "decoder": 0, + "out_digest": "1cd1984bc553c43ee5a48fe7e182a77e60d8ef3c2b0f959ef1a0efd3813b411f" + }, + { + "unit": 5, + "layers": 1, + "decoder": 1, + "out_digest": "e4c4344155dc2c789a1df265f8064b9ae56f3e0932d85c5ceb38782c135749fc" + }, + { + "unit": 6, + "layers": 1, + "decoder": 0, + "out_digest": "95542e01dfb7d7c52f2d526bf932ee49cf081ee2bc330c42dd0715cca7deff8b" + }, + { + "unit": 7, + "layers": 1, + "decoder": 1, + "out_digest": "cf1c65a8bc3fabc40710f610dcfa9ac2604f45a6fa68f74ee2b464421647da4c" + }, + { + "unit": 8, + "layers": 1, + "decoder": 0, + "out_digest": "5c01f526973ca7dbcde1513bc7d25333954bc4164811a5f21399b6e48d89079d" + }, + { + "unit": 9, + "layers": 1, + "decoder": 1, + "out_digest": "686ff0277613c58687a493af12da86b393bcee283c6758845a2505a93d135905" + }, + { + "unit": 10, + "layers": 1, + "decoder": 0, + "out_digest": "23851d2c5e0cc5365e329fbd9c01238313ac71fd4edb4730fa7d58cc74e74823" + }, + { + "unit": 11, + "layers": 1, + "decoder": 1, + "out_digest": "66270813e69c6cffbacb67f95a9c182b2f04ce8c3b2ee4829c257227a5f4a17a" + }, + { + "unit": 12, + "layers": 1, + "decoder": 0, + "out_digest": "47c089823c210a1989895087dc4d44dc5ed8ee0453d7f2517ccce83cb686c824" + }, + { + "unit": 13, + "layers": 1, + "decoder": 1, + "out_digest": "3a1e42600a46cf28926fc9f03946a3186264cef938e207b9e159591c179fa7ed" + }, + { + "unit": 14, + "layers": 1, + "decoder": 0, + "out_digest": "49eac1e814988d0a60db8a709e70f4a1989819a57e26b92bdd0239c338675c58" + }, + { + "unit": 15, + "layers": 1, + "decoder": 1, + "out_digest": "cd3ac56e7dc49f235a245024c0c560cc19ba73fcc0dfb1d38ff9f58bb180d5db" + }, + { + "unit": 16, + "layers": 1, + "decoder": 0, + "out_digest": "b3c7f2ac61734e3390450d0f34c70f733b20db0c29d8ea634c0fc0a8638f2258" + }, + { + "unit": 17, + "layers": 1, + "decoder": 1, + "out_digest": "64b919c5441af6df04b8563a34fe9fe57b84e802b1856a98e1edafc328e809d6" + }, + { + "unit": 18, + "layers": 1, + "decoder": 0, + "out_digest": "e120f02a7fffc970d4a82e4afa8c7d29a00b06a10a7d9fcbf49edacff256ed1d" + }, + { + "unit": 19, + "layers": 1, + "decoder": 1, + "out_digest": "68aee1cd87a8224bc389c297e3b001e9e842f5f416eaeda4b1aafa365e042d46" + }, + { + "unit": 20, + "layers": 1, + "decoder": 0, + "out_digest": "01d364fffad3148204e1cebc263ab9c8818eab8969da5fcbc5794392d170ad6c" + }, + { + "unit": 21, + "layers": 1, + "decoder": 1, + "out_digest": "7c587829be53d8fd83fa843e9b2d1ae7567637256ffa2b00dc5a12b6b3d2bfbd" + }, + { + "unit": 22, + "layers": 1, + "decoder": 0, + "out_digest": "8bf65e08db2dc14a138df5c114940e28396ffe2279278732321dda8d2e377061" + }, + { + "unit": 23, + "layers": 1, + "decoder": 1, + "out_digest": "da305639e012f936cb52ac1b9d044a1ca6a808036325d4a951e5b06382822efe" + }, + { + "unit": 24, + "layers": 1, + "decoder": 0, + "out_digest": "223468b0ac64c3b09969e414a560b3aa8f880064facff95098e12adb723bbfdc" + }, + { + "unit": 25, + "layers": 1, + "decoder": 1, + "out_digest": "2729200cc60d2fced7b6111aa8579fe341910e7cc3e656ac58be6506be7edd09" + }, + { + "unit": 26, + "layers": 1, + "decoder": 0, + "out_digest": "3bbb7b537ed2dacc3ccb2880227a23bab4b6137c3c12e1cdda8b0a11a808ca5b" + }, + { + "unit": 27, + "layers": 1, + "decoder": 1, + "out_digest": "846311931ccdc46a5ecd34a50468fb769bc2e64b33749f05f54aa4f4f33ac998" + } + ], + "redecoded": [ + { + "index": 0, + "out_digest": "55f7e628ca707e2ca3159709eeb68b9000813f2916a299acd33a23e6fe012584" + }, + { + "index": 1, + "out_digest": "9df7f2652febf9fe462ff426af1ee3ec158bf203c59392654482b80775804556" + }, + { + "index": 2, + "out_digest": "00576d2c4d09ef5d7aa807f9b3b1587e200dea6f6694b4da062b41aa2a5ab8af" + }, + { + "index": 3, + "out_digest": "5541d29e4f230e7683ad45c081f4f325fa6216f308b1682f621b3ed279fc39f8" + }, + { + "index": 4, + "out_digest": "1cd1984bc553c43ee5a48fe7e182a77e60d8ef3c2b0f959ef1a0efd3813b411f" + }, + { + "index": 5, + "out_digest": "67754c573f1f7605becf03e65bffa704359b96917b5bc203901eb10e32182cf1" + }, + { + "index": 6, + "out_digest": "95542e01dfb7d7c52f2d526bf932ee49cf081ee2bc330c42dd0715cca7deff8b" + }, + { + "index": 7, + "out_digest": "e7f6d40664240de8fe0eea2384891d0f040db6f05dca8450533a725410bfd31f" + }, + { + "index": 8, + "out_digest": "5c01f526973ca7dbcde1513bc7d25333954bc4164811a5f21399b6e48d89079d" + }, + { + "index": 9, + "out_digest": "f3ff8b3d08e7010fb0d5f7c836dc8b5969bcc95a73ae76813443a2b70929b6bb" + }, + { + "index": 10, + "out_digest": "23851d2c5e0cc5365e329fbd9c01238313ac71fd4edb4730fa7d58cc74e74823" + }, + { + "index": 11, + "out_digest": "9469cdcb42fe46fe46e0e0bb0e10f3397dc5048a60b81467183939f1e4548f74" + }, + { + "index": 12, + "out_digest": "47c089823c210a1989895087dc4d44dc5ed8ee0453d7f2517ccce83cb686c824" + }, + { + "index": 13, + "out_digest": "eca166a3ea198bf0271543d5428c3e0323063de0d3352fbde485399d4476a92b" + }, + { + "index": 14, + "out_digest": "49eac1e814988d0a60db8a709e70f4a1989819a57e26b92bdd0239c338675c58" + }, + { + "index": 15, + "out_digest": "fd7ac5bfaf32d59c57faba74ff87b0a09aae703323a147fef03adf7b2761cb1d" + }, + { + "index": 16, + "out_digest": "b3c7f2ac61734e3390450d0f34c70f733b20db0c29d8ea634c0fc0a8638f2258" + }, + { + "index": 17, + "out_digest": "b7988f6a6e8844ff5ec686f9290b0b4ab0c5c3c028b5e9be116e12821b851534" + }, + { + "index": 18, + "out_digest": "e120f02a7fffc970d4a82e4afa8c7d29a00b06a10a7d9fcbf49edacff256ed1d" + }, + { + "index": 19, + "out_digest": "9436e6edd6411835af7500432df9c51a17b590217e97e642f20820df0323387a" + }, + { + "index": 20, + "out_digest": "01d364fffad3148204e1cebc263ab9c8818eab8969da5fcbc5794392d170ad6c" + }, + { + "index": 21, + "out_digest": "68c5337faac08354c20caec0d0e7221de83055c34f8427195a1ecd9fa2f067ba" + }, + { + "index": 22, + "out_digest": "8bf65e08db2dc14a138df5c114940e28396ffe2279278732321dda8d2e377061" + }, + { + "index": 23, + "out_digest": "8d57033cf933cd97f91d56fb405ed39c23193b39c0ad84a9facb60bd7e74db5f" + }, + { + "index": 24, + "out_digest": "223468b0ac64c3b09969e414a560b3aa8f880064facff95098e12adb723bbfdc" + }, + { + "index": 25, + "out_digest": "1ba9767da05df2f37c42c86f246b933f82b600c0af4f8375cfa7f61b671d1569" + }, + { + "index": 26, + "out_digest": "3bbb7b537ed2dacc3ccb2880227a23bab4b6137c3c12e1cdda8b0a11a808ca5b" + }, + { + "index": 27, + "out_digest": "bffb13a73decf062e6756f5bc3bd8178cbc1f306ece9cd63fb92d2808228c784" + } + ] + }, + "expected": { + "outcome": "accept", + "link_hash": "20bf9026fa65f0adcfc796bd9c380658824690f4de24b486dc6b0fd100be94b8" + } + }, + { + "name": "session_tree_29", + "about": "an output tree of 29 leaves, half on a byte-exact decoder whose re-decode matches and half checked for membership only, whose re-decode does not and is not checked", + "procedure": "claim", + "receipt": "{\"body\":{\"classical_declared\":700,\"classical_source\":\"wai2-table\",\"counted_discarded\":1904,\"counted_fallback\":0,\"counted_primary\":5607,\"deadline_us\":null,\"decoders\":[{\"capability\":\"wai.video.int_hyper\",\"decoder\":\"builtin:wai@0.4.0\",\"leaves\":15,\"module_status\":null,\"path\":\"primary\",\"pin\":\"7b4371854df0aa1645ac6525b373387c0617b873d5a57748932ee0f386ea164b\",\"rendition\":0,\"tier\":\"decode-equivalence\",\"variant\":null},{\"capability\":\"wai.video.av1\",\"decoder\":\"builtin:wai@0.4.0\",\"leaves\":14,\"module_status\":null,\"path\":\"fallback\",\"pin\":null,\"rendition\":null,\"tier\":null,\"variant\":null}],\"energy\":null,\"fallback_units\":14,\"framing\":\"registered\",\"host\":{\"build\":{\"profile\":\"release\",\"target\":\"aarch64-unknown-linux-gnu\",\"toolchain\":\"rustc 1.95.0\"},\"profile\":\"native-ffi\",\"target\":\"aarch64-unknown-linux-gnu\",\"threads\":4},\"leaf_count\":29,\"media\":\"video\",\"missed\":0,\"missed_units\":[],\"output_root\":\"0142316a46b8018f4cd2852a88b6b6cb3d4aa1e367e8cda03f2757b2c35fdcac\",\"primary_units\":15,\"receipt_bytes\":640,\"session_nonce\":\"57c5462dfdabd1b7bdd204d34ba33649c057eb535349f29f45eb8f8c7d4a7e7f\",\"stage_sets\":[],\"switches\":[],\"switches_total\":0,\"transferred\":13607,\"uncounted\":2,\"units\":29},\"class\":\"reconstruct-session\",\"issued_at\":\"2026-09-27T12:00:00Z\",\"kind\":\"claim\",\"parent_receipt_hash\":null,\"seq\":0,\"sig\":\"e917f0373cda96f0a11f74421a2429d94407eca6d4c8ab09cbb36d8216d0dea7a386b2bbb93af8bf13721af68715344256f08c6859b145181199d8022f8d0d02\",\"signer_id\":\"did:example:sink\",\"signer_pubkey\":\"d759793bbc13a2819a827c76adb6fba8a49aee007f49f2d0992d99b825ad2c48\",\"subject\":\"64c0713cb176874607bf8670295242184b7868a9ff7c55554a5ae08de2c301c1\",\"subject_type\":\"object\"}", + "context": { + "outputs": [ + { + "unit": 0, + "layers": 1, + "decoder": 0, + "out_digest": "55f7e628ca707e2ca3159709eeb68b9000813f2916a299acd33a23e6fe012584" + }, + { + "unit": 1, + "layers": 1, + "decoder": 1, + "out_digest": "a3ee8a4b96eceb663f3d94417957d02f897fc166dc96ebe9bf447c4a36a36264" + }, + { + "unit": 2, + "layers": 1, + "decoder": 0, + "out_digest": "00576d2c4d09ef5d7aa807f9b3b1587e200dea6f6694b4da062b41aa2a5ab8af" + }, + { + "unit": 3, + "layers": 1, + "decoder": 1, + "out_digest": "26cd9b2805b604b26e08d9a461db599c4e249bfd4df41a3befb202bc6d0e0700" + }, + { + "unit": 4, + "layers": 1, + "decoder": 0, + "out_digest": "1cd1984bc553c43ee5a48fe7e182a77e60d8ef3c2b0f959ef1a0efd3813b411f" + }, + { + "unit": 5, + "layers": 1, + "decoder": 1, + "out_digest": "e4c4344155dc2c789a1df265f8064b9ae56f3e0932d85c5ceb38782c135749fc" + }, + { + "unit": 6, + "layers": 1, + "decoder": 0, + "out_digest": "95542e01dfb7d7c52f2d526bf932ee49cf081ee2bc330c42dd0715cca7deff8b" + }, + { + "unit": 7, + "layers": 1, + "decoder": 1, + "out_digest": "cf1c65a8bc3fabc40710f610dcfa9ac2604f45a6fa68f74ee2b464421647da4c" + }, + { + "unit": 8, + "layers": 1, + "decoder": 0, + "out_digest": "5c01f526973ca7dbcde1513bc7d25333954bc4164811a5f21399b6e48d89079d" + }, + { + "unit": 9, + "layers": 1, + "decoder": 1, + "out_digest": "686ff0277613c58687a493af12da86b393bcee283c6758845a2505a93d135905" + }, + { + "unit": 10, + "layers": 1, + "decoder": 0, + "out_digest": "23851d2c5e0cc5365e329fbd9c01238313ac71fd4edb4730fa7d58cc74e74823" + }, + { + "unit": 11, + "layers": 1, + "decoder": 1, + "out_digest": "66270813e69c6cffbacb67f95a9c182b2f04ce8c3b2ee4829c257227a5f4a17a" + }, + { + "unit": 12, + "layers": 1, + "decoder": 0, + "out_digest": "47c089823c210a1989895087dc4d44dc5ed8ee0453d7f2517ccce83cb686c824" + }, + { + "unit": 13, + "layers": 1, + "decoder": 1, + "out_digest": "3a1e42600a46cf28926fc9f03946a3186264cef938e207b9e159591c179fa7ed" + }, + { + "unit": 14, + "layers": 1, + "decoder": 0, + "out_digest": "49eac1e814988d0a60db8a709e70f4a1989819a57e26b92bdd0239c338675c58" + }, + { + "unit": 15, + "layers": 1, + "decoder": 1, + "out_digest": "cd3ac56e7dc49f235a245024c0c560cc19ba73fcc0dfb1d38ff9f58bb180d5db" + }, + { + "unit": 16, + "layers": 1, + "decoder": 0, + "out_digest": "b3c7f2ac61734e3390450d0f34c70f733b20db0c29d8ea634c0fc0a8638f2258" + }, + { + "unit": 17, + "layers": 1, + "decoder": 1, + "out_digest": "64b919c5441af6df04b8563a34fe9fe57b84e802b1856a98e1edafc328e809d6" + }, + { + "unit": 18, + "layers": 1, + "decoder": 0, + "out_digest": "e120f02a7fffc970d4a82e4afa8c7d29a00b06a10a7d9fcbf49edacff256ed1d" + }, + { + "unit": 19, + "layers": 1, + "decoder": 1, + "out_digest": "68aee1cd87a8224bc389c297e3b001e9e842f5f416eaeda4b1aafa365e042d46" + }, + { + "unit": 20, + "layers": 1, + "decoder": 0, + "out_digest": "01d364fffad3148204e1cebc263ab9c8818eab8969da5fcbc5794392d170ad6c" + }, + { + "unit": 21, + "layers": 1, + "decoder": 1, + "out_digest": "7c587829be53d8fd83fa843e9b2d1ae7567637256ffa2b00dc5a12b6b3d2bfbd" + }, + { + "unit": 22, + "layers": 1, + "decoder": 0, + "out_digest": "8bf65e08db2dc14a138df5c114940e28396ffe2279278732321dda8d2e377061" + }, + { + "unit": 23, + "layers": 1, + "decoder": 1, + "out_digest": "da305639e012f936cb52ac1b9d044a1ca6a808036325d4a951e5b06382822efe" + }, + { + "unit": 24, + "layers": 1, + "decoder": 0, + "out_digest": "223468b0ac64c3b09969e414a560b3aa8f880064facff95098e12adb723bbfdc" + }, + { + "unit": 25, + "layers": 1, + "decoder": 1, + "out_digest": "2729200cc60d2fced7b6111aa8579fe341910e7cc3e656ac58be6506be7edd09" + }, + { + "unit": 26, + "layers": 1, + "decoder": 0, + "out_digest": "3bbb7b537ed2dacc3ccb2880227a23bab4b6137c3c12e1cdda8b0a11a808ca5b" + }, + { + "unit": 27, + "layers": 1, + "decoder": 1, + "out_digest": "846311931ccdc46a5ecd34a50468fb769bc2e64b33749f05f54aa4f4f33ac998" + }, + { + "unit": 28, + "layers": 1, + "decoder": 0, + "out_digest": "9ecfcc6181471c99e6cf19ba1872f8986898f3a99e412d3bb467678fec8e3863" + } + ], + "redecoded": [ + { + "index": 0, + "out_digest": "55f7e628ca707e2ca3159709eeb68b9000813f2916a299acd33a23e6fe012584" + }, + { + "index": 1, + "out_digest": "9df7f2652febf9fe462ff426af1ee3ec158bf203c59392654482b80775804556" + }, + { + "index": 2, + "out_digest": "00576d2c4d09ef5d7aa807f9b3b1587e200dea6f6694b4da062b41aa2a5ab8af" + }, + { + "index": 3, + "out_digest": "5541d29e4f230e7683ad45c081f4f325fa6216f308b1682f621b3ed279fc39f8" + }, + { + "index": 4, + "out_digest": "1cd1984bc553c43ee5a48fe7e182a77e60d8ef3c2b0f959ef1a0efd3813b411f" + }, + { + "index": 5, + "out_digest": "67754c573f1f7605becf03e65bffa704359b96917b5bc203901eb10e32182cf1" + }, + { + "index": 6, + "out_digest": "95542e01dfb7d7c52f2d526bf932ee49cf081ee2bc330c42dd0715cca7deff8b" + }, + { + "index": 7, + "out_digest": "e7f6d40664240de8fe0eea2384891d0f040db6f05dca8450533a725410bfd31f" + }, + { + "index": 8, + "out_digest": "5c01f526973ca7dbcde1513bc7d25333954bc4164811a5f21399b6e48d89079d" + }, + { + "index": 9, + "out_digest": "f3ff8b3d08e7010fb0d5f7c836dc8b5969bcc95a73ae76813443a2b70929b6bb" + }, + { + "index": 10, + "out_digest": "23851d2c5e0cc5365e329fbd9c01238313ac71fd4edb4730fa7d58cc74e74823" + }, + { + "index": 11, + "out_digest": "9469cdcb42fe46fe46e0e0bb0e10f3397dc5048a60b81467183939f1e4548f74" + }, + { + "index": 12, + "out_digest": "47c089823c210a1989895087dc4d44dc5ed8ee0453d7f2517ccce83cb686c824" + }, + { + "index": 13, + "out_digest": "eca166a3ea198bf0271543d5428c3e0323063de0d3352fbde485399d4476a92b" + }, + { + "index": 14, + "out_digest": "49eac1e814988d0a60db8a709e70f4a1989819a57e26b92bdd0239c338675c58" + }, + { + "index": 15, + "out_digest": "fd7ac5bfaf32d59c57faba74ff87b0a09aae703323a147fef03adf7b2761cb1d" + }, + { + "index": 16, + "out_digest": "b3c7f2ac61734e3390450d0f34c70f733b20db0c29d8ea634c0fc0a8638f2258" + }, + { + "index": 17, + "out_digest": "b7988f6a6e8844ff5ec686f9290b0b4ab0c5c3c028b5e9be116e12821b851534" + }, + { + "index": 18, + "out_digest": "e120f02a7fffc970d4a82e4afa8c7d29a00b06a10a7d9fcbf49edacff256ed1d" + }, + { + "index": 19, + "out_digest": "9436e6edd6411835af7500432df9c51a17b590217e97e642f20820df0323387a" + }, + { + "index": 20, + "out_digest": "01d364fffad3148204e1cebc263ab9c8818eab8969da5fcbc5794392d170ad6c" + }, + { + "index": 21, + "out_digest": "68c5337faac08354c20caec0d0e7221de83055c34f8427195a1ecd9fa2f067ba" + }, + { + "index": 22, + "out_digest": "8bf65e08db2dc14a138df5c114940e28396ffe2279278732321dda8d2e377061" + }, + { + "index": 23, + "out_digest": "8d57033cf933cd97f91d56fb405ed39c23193b39c0ad84a9facb60bd7e74db5f" + }, + { + "index": 24, + "out_digest": "223468b0ac64c3b09969e414a560b3aa8f880064facff95098e12adb723bbfdc" + }, + { + "index": 25, + "out_digest": "1ba9767da05df2f37c42c86f246b933f82b600c0af4f8375cfa7f61b671d1569" + }, + { + "index": 26, + "out_digest": "3bbb7b537ed2dacc3ccb2880227a23bab4b6137c3c12e1cdda8b0a11a808ca5b" + }, + { + "index": 27, + "out_digest": "bffb13a73decf062e6756f5bc3bd8178cbc1f306ece9cd63fb92d2808228c784" + }, + { + "index": 28, + "out_digest": "9ecfcc6181471c99e6cf19ba1872f8986898f3a99e412d3bb467678fec8e3863" + } + ] + }, + "expected": { + "outcome": "accept", + "link_hash": "c406de5af0466e6048b5eeae9d6641261b1886e25b75b8402a0de84b5ad9dd52" + } + }, + { + "name": "session_tree_30", + "about": "an output tree of 30 leaves, half on a byte-exact decoder whose re-decode matches and half checked for membership only, whose re-decode does not and is not checked", + "procedure": "claim", + "receipt": "{\"body\":{\"classical_declared\":700,\"classical_source\":\"wai2-table\",\"counted_discarded\":1904,\"counted_fallback\":0,\"counted_primary\":5607,\"deadline_us\":null,\"decoders\":[{\"capability\":\"wai.video.int_hyper\",\"decoder\":\"builtin:wai@0.4.0\",\"leaves\":15,\"module_status\":null,\"path\":\"primary\",\"pin\":\"7b4371854df0aa1645ac6525b373387c0617b873d5a57748932ee0f386ea164b\",\"rendition\":0,\"tier\":\"decode-equivalence\",\"variant\":null},{\"capability\":\"wai.video.av1\",\"decoder\":\"builtin:wai@0.4.0\",\"leaves\":15,\"module_status\":null,\"path\":\"fallback\",\"pin\":null,\"rendition\":null,\"tier\":null,\"variant\":null}],\"energy\":null,\"fallback_units\":15,\"framing\":\"registered\",\"host\":{\"build\":{\"profile\":\"release\",\"target\":\"aarch64-unknown-linux-gnu\",\"toolchain\":\"rustc 1.95.0\"},\"profile\":\"native-ffi\",\"target\":\"aarch64-unknown-linux-gnu\",\"threads\":4},\"leaf_count\":30,\"media\":\"video\",\"missed\":0,\"missed_units\":[],\"output_root\":\"8ff1929ac5ac4f41d42855c3ae620ff1d929e910e27df6bc290e874488df3f00\",\"primary_units\":15,\"receipt_bytes\":640,\"session_nonce\":\"57c5462dfdabd1b7bdd204d34ba33649c057eb535349f29f45eb8f8c7d4a7e7f\",\"stage_sets\":[],\"switches\":[],\"switches_total\":0,\"transferred\":13607,\"uncounted\":2,\"units\":30},\"class\":\"reconstruct-session\",\"issued_at\":\"2026-09-27T12:00:00Z\",\"kind\":\"claim\",\"parent_receipt_hash\":null,\"seq\":0,\"sig\":\"a6332b085948cb1a4207c70b517532565e9864e5df1a967d1c761ad72256ae94e483d441661fb35fed04f31f9c97142e24acae9031ccb69c743a7fe52579fa0b\",\"signer_id\":\"did:example:sink\",\"signer_pubkey\":\"d759793bbc13a2819a827c76adb6fba8a49aee007f49f2d0992d99b825ad2c48\",\"subject\":\"64c0713cb176874607bf8670295242184b7868a9ff7c55554a5ae08de2c301c1\",\"subject_type\":\"object\"}", + "context": { + "outputs": [ + { + "unit": 0, + "layers": 1, + "decoder": 0, + "out_digest": "55f7e628ca707e2ca3159709eeb68b9000813f2916a299acd33a23e6fe012584" + }, + { + "unit": 1, + "layers": 1, + "decoder": 1, + "out_digest": "a3ee8a4b96eceb663f3d94417957d02f897fc166dc96ebe9bf447c4a36a36264" + }, + { + "unit": 2, + "layers": 1, + "decoder": 0, + "out_digest": "00576d2c4d09ef5d7aa807f9b3b1587e200dea6f6694b4da062b41aa2a5ab8af" + }, + { + "unit": 3, + "layers": 1, + "decoder": 1, + "out_digest": "26cd9b2805b604b26e08d9a461db599c4e249bfd4df41a3befb202bc6d0e0700" + }, + { + "unit": 4, + "layers": 1, + "decoder": 0, + "out_digest": "1cd1984bc553c43ee5a48fe7e182a77e60d8ef3c2b0f959ef1a0efd3813b411f" + }, + { + "unit": 5, + "layers": 1, + "decoder": 1, + "out_digest": "e4c4344155dc2c789a1df265f8064b9ae56f3e0932d85c5ceb38782c135749fc" + }, + { + "unit": 6, + "layers": 1, + "decoder": 0, + "out_digest": "95542e01dfb7d7c52f2d526bf932ee49cf081ee2bc330c42dd0715cca7deff8b" + }, + { + "unit": 7, + "layers": 1, + "decoder": 1, + "out_digest": "cf1c65a8bc3fabc40710f610dcfa9ac2604f45a6fa68f74ee2b464421647da4c" + }, + { + "unit": 8, + "layers": 1, + "decoder": 0, + "out_digest": "5c01f526973ca7dbcde1513bc7d25333954bc4164811a5f21399b6e48d89079d" + }, + { + "unit": 9, + "layers": 1, + "decoder": 1, + "out_digest": "686ff0277613c58687a493af12da86b393bcee283c6758845a2505a93d135905" + }, + { + "unit": 10, + "layers": 1, + "decoder": 0, + "out_digest": "23851d2c5e0cc5365e329fbd9c01238313ac71fd4edb4730fa7d58cc74e74823" + }, + { + "unit": 11, + "layers": 1, + "decoder": 1, + "out_digest": "66270813e69c6cffbacb67f95a9c182b2f04ce8c3b2ee4829c257227a5f4a17a" + }, + { + "unit": 12, + "layers": 1, + "decoder": 0, + "out_digest": "47c089823c210a1989895087dc4d44dc5ed8ee0453d7f2517ccce83cb686c824" + }, + { + "unit": 13, + "layers": 1, + "decoder": 1, + "out_digest": "3a1e42600a46cf28926fc9f03946a3186264cef938e207b9e159591c179fa7ed" + }, + { + "unit": 14, + "layers": 1, + "decoder": 0, + "out_digest": "49eac1e814988d0a60db8a709e70f4a1989819a57e26b92bdd0239c338675c58" + }, + { + "unit": 15, + "layers": 1, + "decoder": 1, + "out_digest": "cd3ac56e7dc49f235a245024c0c560cc19ba73fcc0dfb1d38ff9f58bb180d5db" + }, + { + "unit": 16, + "layers": 1, + "decoder": 0, + "out_digest": "b3c7f2ac61734e3390450d0f34c70f733b20db0c29d8ea634c0fc0a8638f2258" + }, + { + "unit": 17, + "layers": 1, + "decoder": 1, + "out_digest": "64b919c5441af6df04b8563a34fe9fe57b84e802b1856a98e1edafc328e809d6" + }, + { + "unit": 18, + "layers": 1, + "decoder": 0, + "out_digest": "e120f02a7fffc970d4a82e4afa8c7d29a00b06a10a7d9fcbf49edacff256ed1d" + }, + { + "unit": 19, + "layers": 1, + "decoder": 1, + "out_digest": "68aee1cd87a8224bc389c297e3b001e9e842f5f416eaeda4b1aafa365e042d46" + }, + { + "unit": 20, + "layers": 1, + "decoder": 0, + "out_digest": "01d364fffad3148204e1cebc263ab9c8818eab8969da5fcbc5794392d170ad6c" + }, + { + "unit": 21, + "layers": 1, + "decoder": 1, + "out_digest": "7c587829be53d8fd83fa843e9b2d1ae7567637256ffa2b00dc5a12b6b3d2bfbd" + }, + { + "unit": 22, + "layers": 1, + "decoder": 0, + "out_digest": "8bf65e08db2dc14a138df5c114940e28396ffe2279278732321dda8d2e377061" + }, + { + "unit": 23, + "layers": 1, + "decoder": 1, + "out_digest": "da305639e012f936cb52ac1b9d044a1ca6a808036325d4a951e5b06382822efe" + }, + { + "unit": 24, + "layers": 1, + "decoder": 0, + "out_digest": "223468b0ac64c3b09969e414a560b3aa8f880064facff95098e12adb723bbfdc" + }, + { + "unit": 25, + "layers": 1, + "decoder": 1, + "out_digest": "2729200cc60d2fced7b6111aa8579fe341910e7cc3e656ac58be6506be7edd09" + }, + { + "unit": 26, + "layers": 1, + "decoder": 0, + "out_digest": "3bbb7b537ed2dacc3ccb2880227a23bab4b6137c3c12e1cdda8b0a11a808ca5b" + }, + { + "unit": 27, + "layers": 1, + "decoder": 1, + "out_digest": "846311931ccdc46a5ecd34a50468fb769bc2e64b33749f05f54aa4f4f33ac998" + }, + { + "unit": 28, + "layers": 1, + "decoder": 0, + "out_digest": "9ecfcc6181471c99e6cf19ba1872f8986898f3a99e412d3bb467678fec8e3863" + }, + { + "unit": 29, + "layers": 1, + "decoder": 1, + "out_digest": "391f049a7aa1c57d89e770ff717c28d5d394245d57ca8f5e396e4dba414879d8" + } + ], + "redecoded": [ + { + "index": 0, + "out_digest": "55f7e628ca707e2ca3159709eeb68b9000813f2916a299acd33a23e6fe012584" + }, + { + "index": 1, + "out_digest": "9df7f2652febf9fe462ff426af1ee3ec158bf203c59392654482b80775804556" + }, + { + "index": 2, + "out_digest": "00576d2c4d09ef5d7aa807f9b3b1587e200dea6f6694b4da062b41aa2a5ab8af" + }, + { + "index": 3, + "out_digest": "5541d29e4f230e7683ad45c081f4f325fa6216f308b1682f621b3ed279fc39f8" + }, + { + "index": 4, + "out_digest": "1cd1984bc553c43ee5a48fe7e182a77e60d8ef3c2b0f959ef1a0efd3813b411f" + }, + { + "index": 5, + "out_digest": "67754c573f1f7605becf03e65bffa704359b96917b5bc203901eb10e32182cf1" + }, + { + "index": 6, + "out_digest": "95542e01dfb7d7c52f2d526bf932ee49cf081ee2bc330c42dd0715cca7deff8b" + }, + { + "index": 7, + "out_digest": "e7f6d40664240de8fe0eea2384891d0f040db6f05dca8450533a725410bfd31f" + }, + { + "index": 8, + "out_digest": "5c01f526973ca7dbcde1513bc7d25333954bc4164811a5f21399b6e48d89079d" + }, + { + "index": 9, + "out_digest": "f3ff8b3d08e7010fb0d5f7c836dc8b5969bcc95a73ae76813443a2b70929b6bb" + }, + { + "index": 10, + "out_digest": "23851d2c5e0cc5365e329fbd9c01238313ac71fd4edb4730fa7d58cc74e74823" + }, + { + "index": 11, + "out_digest": "9469cdcb42fe46fe46e0e0bb0e10f3397dc5048a60b81467183939f1e4548f74" + }, + { + "index": 12, + "out_digest": "47c089823c210a1989895087dc4d44dc5ed8ee0453d7f2517ccce83cb686c824" + }, + { + "index": 13, + "out_digest": "eca166a3ea198bf0271543d5428c3e0323063de0d3352fbde485399d4476a92b" + }, + { + "index": 14, + "out_digest": "49eac1e814988d0a60db8a709e70f4a1989819a57e26b92bdd0239c338675c58" + }, + { + "index": 15, + "out_digest": "fd7ac5bfaf32d59c57faba74ff87b0a09aae703323a147fef03adf7b2761cb1d" + }, + { + "index": 16, + "out_digest": "b3c7f2ac61734e3390450d0f34c70f733b20db0c29d8ea634c0fc0a8638f2258" + }, + { + "index": 17, + "out_digest": "b7988f6a6e8844ff5ec686f9290b0b4ab0c5c3c028b5e9be116e12821b851534" + }, + { + "index": 18, + "out_digest": "e120f02a7fffc970d4a82e4afa8c7d29a00b06a10a7d9fcbf49edacff256ed1d" + }, + { + "index": 19, + "out_digest": "9436e6edd6411835af7500432df9c51a17b590217e97e642f20820df0323387a" + }, + { + "index": 20, + "out_digest": "01d364fffad3148204e1cebc263ab9c8818eab8969da5fcbc5794392d170ad6c" + }, + { + "index": 21, + "out_digest": "68c5337faac08354c20caec0d0e7221de83055c34f8427195a1ecd9fa2f067ba" + }, + { + "index": 22, + "out_digest": "8bf65e08db2dc14a138df5c114940e28396ffe2279278732321dda8d2e377061" + }, + { + "index": 23, + "out_digest": "8d57033cf933cd97f91d56fb405ed39c23193b39c0ad84a9facb60bd7e74db5f" + }, + { + "index": 24, + "out_digest": "223468b0ac64c3b09969e414a560b3aa8f880064facff95098e12adb723bbfdc" + }, + { + "index": 25, + "out_digest": "1ba9767da05df2f37c42c86f246b933f82b600c0af4f8375cfa7f61b671d1569" + }, + { + "index": 26, + "out_digest": "3bbb7b537ed2dacc3ccb2880227a23bab4b6137c3c12e1cdda8b0a11a808ca5b" + }, + { + "index": 27, + "out_digest": "bffb13a73decf062e6756f5bc3bd8178cbc1f306ece9cd63fb92d2808228c784" + }, + { + "index": 28, + "out_digest": "9ecfcc6181471c99e6cf19ba1872f8986898f3a99e412d3bb467678fec8e3863" + }, + { + "index": 29, + "out_digest": "853afa70587615f00c515748754b34f74dc12c5c43a9284a373fa68837d7421c" + } + ] + }, + "expected": { + "outcome": "accept", + "link_hash": "6434c6175b72fe27bec00e5aca999af7c3bcb231553ffeec84ecd83a7a48670a" + } + }, + { + "name": "session_tree_31", + "about": "an output tree of 31 leaves, half on a byte-exact decoder whose re-decode matches and half checked for membership only, whose re-decode does not and is not checked", + "procedure": "claim", + "receipt": "{\"body\":{\"classical_declared\":700,\"classical_source\":\"wai2-table\",\"counted_discarded\":1904,\"counted_fallback\":0,\"counted_primary\":5607,\"deadline_us\":null,\"decoders\":[{\"capability\":\"wai.video.int_hyper\",\"decoder\":\"builtin:wai@0.4.0\",\"leaves\":16,\"module_status\":null,\"path\":\"primary\",\"pin\":\"7b4371854df0aa1645ac6525b373387c0617b873d5a57748932ee0f386ea164b\",\"rendition\":0,\"tier\":\"decode-equivalence\",\"variant\":null},{\"capability\":\"wai.video.av1\",\"decoder\":\"builtin:wai@0.4.0\",\"leaves\":15,\"module_status\":null,\"path\":\"fallback\",\"pin\":null,\"rendition\":null,\"tier\":null,\"variant\":null}],\"energy\":null,\"fallback_units\":15,\"framing\":\"registered\",\"host\":{\"build\":{\"profile\":\"release\",\"target\":\"aarch64-unknown-linux-gnu\",\"toolchain\":\"rustc 1.95.0\"},\"profile\":\"native-ffi\",\"target\":\"aarch64-unknown-linux-gnu\",\"threads\":4},\"leaf_count\":31,\"media\":\"video\",\"missed\":0,\"missed_units\":[],\"output_root\":\"7023712a5337d037350fb6033f0adb98a9cb0b87d53ba952a020bad604b123b7\",\"primary_units\":16,\"receipt_bytes\":640,\"session_nonce\":\"57c5462dfdabd1b7bdd204d34ba33649c057eb535349f29f45eb8f8c7d4a7e7f\",\"stage_sets\":[],\"switches\":[],\"switches_total\":0,\"transferred\":13607,\"uncounted\":2,\"units\":31},\"class\":\"reconstruct-session\",\"issued_at\":\"2026-09-27T12:00:00Z\",\"kind\":\"claim\",\"parent_receipt_hash\":null,\"seq\":0,\"sig\":\"e728360e5e4571b26fb3182e88d0af25b5e4b6f4831ffb66da9329dcc94aa95002b025f98f51dadb304f120c9b0531c8e6d2a22e0af489a9c4a654412ef5680a\",\"signer_id\":\"did:example:sink\",\"signer_pubkey\":\"d759793bbc13a2819a827c76adb6fba8a49aee007f49f2d0992d99b825ad2c48\",\"subject\":\"64c0713cb176874607bf8670295242184b7868a9ff7c55554a5ae08de2c301c1\",\"subject_type\":\"object\"}", + "context": { + "outputs": [ + { + "unit": 0, + "layers": 1, + "decoder": 0, + "out_digest": "55f7e628ca707e2ca3159709eeb68b9000813f2916a299acd33a23e6fe012584" + }, + { + "unit": 1, + "layers": 1, + "decoder": 1, + "out_digest": "a3ee8a4b96eceb663f3d94417957d02f897fc166dc96ebe9bf447c4a36a36264" + }, + { + "unit": 2, + "layers": 1, + "decoder": 0, + "out_digest": "00576d2c4d09ef5d7aa807f9b3b1587e200dea6f6694b4da062b41aa2a5ab8af" + }, + { + "unit": 3, + "layers": 1, + "decoder": 1, + "out_digest": "26cd9b2805b604b26e08d9a461db599c4e249bfd4df41a3befb202bc6d0e0700" + }, + { + "unit": 4, + "layers": 1, + "decoder": 0, + "out_digest": "1cd1984bc553c43ee5a48fe7e182a77e60d8ef3c2b0f959ef1a0efd3813b411f" + }, + { + "unit": 5, + "layers": 1, + "decoder": 1, + "out_digest": "e4c4344155dc2c789a1df265f8064b9ae56f3e0932d85c5ceb38782c135749fc" + }, + { + "unit": 6, + "layers": 1, + "decoder": 0, + "out_digest": "95542e01dfb7d7c52f2d526bf932ee49cf081ee2bc330c42dd0715cca7deff8b" + }, + { + "unit": 7, + "layers": 1, + "decoder": 1, + "out_digest": "cf1c65a8bc3fabc40710f610dcfa9ac2604f45a6fa68f74ee2b464421647da4c" + }, + { + "unit": 8, + "layers": 1, + "decoder": 0, + "out_digest": "5c01f526973ca7dbcde1513bc7d25333954bc4164811a5f21399b6e48d89079d" + }, + { + "unit": 9, + "layers": 1, + "decoder": 1, + "out_digest": "686ff0277613c58687a493af12da86b393bcee283c6758845a2505a93d135905" + }, + { + "unit": 10, + "layers": 1, + "decoder": 0, + "out_digest": "23851d2c5e0cc5365e329fbd9c01238313ac71fd4edb4730fa7d58cc74e74823" + }, + { + "unit": 11, + "layers": 1, + "decoder": 1, + "out_digest": "66270813e69c6cffbacb67f95a9c182b2f04ce8c3b2ee4829c257227a5f4a17a" + }, + { + "unit": 12, + "layers": 1, + "decoder": 0, + "out_digest": "47c089823c210a1989895087dc4d44dc5ed8ee0453d7f2517ccce83cb686c824" + }, + { + "unit": 13, + "layers": 1, + "decoder": 1, + "out_digest": "3a1e42600a46cf28926fc9f03946a3186264cef938e207b9e159591c179fa7ed" + }, + { + "unit": 14, + "layers": 1, + "decoder": 0, + "out_digest": "49eac1e814988d0a60db8a709e70f4a1989819a57e26b92bdd0239c338675c58" + }, + { + "unit": 15, + "layers": 1, + "decoder": 1, + "out_digest": "cd3ac56e7dc49f235a245024c0c560cc19ba73fcc0dfb1d38ff9f58bb180d5db" + }, + { + "unit": 16, + "layers": 1, + "decoder": 0, + "out_digest": "b3c7f2ac61734e3390450d0f34c70f733b20db0c29d8ea634c0fc0a8638f2258" + }, + { + "unit": 17, + "layers": 1, + "decoder": 1, + "out_digest": "64b919c5441af6df04b8563a34fe9fe57b84e802b1856a98e1edafc328e809d6" + }, + { + "unit": 18, + "layers": 1, + "decoder": 0, + "out_digest": "e120f02a7fffc970d4a82e4afa8c7d29a00b06a10a7d9fcbf49edacff256ed1d" + }, + { + "unit": 19, + "layers": 1, + "decoder": 1, + "out_digest": "68aee1cd87a8224bc389c297e3b001e9e842f5f416eaeda4b1aafa365e042d46" + }, + { + "unit": 20, + "layers": 1, + "decoder": 0, + "out_digest": "01d364fffad3148204e1cebc263ab9c8818eab8969da5fcbc5794392d170ad6c" + }, + { + "unit": 21, + "layers": 1, + "decoder": 1, + "out_digest": "7c587829be53d8fd83fa843e9b2d1ae7567637256ffa2b00dc5a12b6b3d2bfbd" + }, + { + "unit": 22, + "layers": 1, + "decoder": 0, + "out_digest": "8bf65e08db2dc14a138df5c114940e28396ffe2279278732321dda8d2e377061" + }, + { + "unit": 23, + "layers": 1, + "decoder": 1, + "out_digest": "da305639e012f936cb52ac1b9d044a1ca6a808036325d4a951e5b06382822efe" + }, + { + "unit": 24, + "layers": 1, + "decoder": 0, + "out_digest": "223468b0ac64c3b09969e414a560b3aa8f880064facff95098e12adb723bbfdc" + }, + { + "unit": 25, + "layers": 1, + "decoder": 1, + "out_digest": "2729200cc60d2fced7b6111aa8579fe341910e7cc3e656ac58be6506be7edd09" + }, + { + "unit": 26, + "layers": 1, + "decoder": 0, + "out_digest": "3bbb7b537ed2dacc3ccb2880227a23bab4b6137c3c12e1cdda8b0a11a808ca5b" + }, + { + "unit": 27, + "layers": 1, + "decoder": 1, + "out_digest": "846311931ccdc46a5ecd34a50468fb769bc2e64b33749f05f54aa4f4f33ac998" + }, + { + "unit": 28, + "layers": 1, + "decoder": 0, + "out_digest": "9ecfcc6181471c99e6cf19ba1872f8986898f3a99e412d3bb467678fec8e3863" + }, + { + "unit": 29, + "layers": 1, + "decoder": 1, + "out_digest": "391f049a7aa1c57d89e770ff717c28d5d394245d57ca8f5e396e4dba414879d8" + }, + { + "unit": 30, + "layers": 1, + "decoder": 0, + "out_digest": "e44c1218b9d73306a15434d4328c2df004bd1edcb645441e250a61a7b151759d" + } + ], + "redecoded": [ + { + "index": 0, + "out_digest": "55f7e628ca707e2ca3159709eeb68b9000813f2916a299acd33a23e6fe012584" + }, + { + "index": 1, + "out_digest": "9df7f2652febf9fe462ff426af1ee3ec158bf203c59392654482b80775804556" + }, + { + "index": 2, + "out_digest": "00576d2c4d09ef5d7aa807f9b3b1587e200dea6f6694b4da062b41aa2a5ab8af" + }, + { + "index": 3, + "out_digest": "5541d29e4f230e7683ad45c081f4f325fa6216f308b1682f621b3ed279fc39f8" + }, + { + "index": 4, + "out_digest": "1cd1984bc553c43ee5a48fe7e182a77e60d8ef3c2b0f959ef1a0efd3813b411f" + }, + { + "index": 5, + "out_digest": "67754c573f1f7605becf03e65bffa704359b96917b5bc203901eb10e32182cf1" + }, + { + "index": 6, + "out_digest": "95542e01dfb7d7c52f2d526bf932ee49cf081ee2bc330c42dd0715cca7deff8b" + }, + { + "index": 7, + "out_digest": "e7f6d40664240de8fe0eea2384891d0f040db6f05dca8450533a725410bfd31f" + }, + { + "index": 8, + "out_digest": "5c01f526973ca7dbcde1513bc7d25333954bc4164811a5f21399b6e48d89079d" + }, + { + "index": 9, + "out_digest": "f3ff8b3d08e7010fb0d5f7c836dc8b5969bcc95a73ae76813443a2b70929b6bb" + }, + { + "index": 10, + "out_digest": "23851d2c5e0cc5365e329fbd9c01238313ac71fd4edb4730fa7d58cc74e74823" + }, + { + "index": 11, + "out_digest": "9469cdcb42fe46fe46e0e0bb0e10f3397dc5048a60b81467183939f1e4548f74" + }, + { + "index": 12, + "out_digest": "47c089823c210a1989895087dc4d44dc5ed8ee0453d7f2517ccce83cb686c824" + }, + { + "index": 13, + "out_digest": "eca166a3ea198bf0271543d5428c3e0323063de0d3352fbde485399d4476a92b" + }, + { + "index": 14, + "out_digest": "49eac1e814988d0a60db8a709e70f4a1989819a57e26b92bdd0239c338675c58" + }, + { + "index": 15, + "out_digest": "fd7ac5bfaf32d59c57faba74ff87b0a09aae703323a147fef03adf7b2761cb1d" + }, + { + "index": 16, + "out_digest": "b3c7f2ac61734e3390450d0f34c70f733b20db0c29d8ea634c0fc0a8638f2258" + }, + { + "index": 17, + "out_digest": "b7988f6a6e8844ff5ec686f9290b0b4ab0c5c3c028b5e9be116e12821b851534" + }, + { + "index": 18, + "out_digest": "e120f02a7fffc970d4a82e4afa8c7d29a00b06a10a7d9fcbf49edacff256ed1d" + }, + { + "index": 19, + "out_digest": "9436e6edd6411835af7500432df9c51a17b590217e97e642f20820df0323387a" + }, + { + "index": 20, + "out_digest": "01d364fffad3148204e1cebc263ab9c8818eab8969da5fcbc5794392d170ad6c" + }, + { + "index": 21, + "out_digest": "68c5337faac08354c20caec0d0e7221de83055c34f8427195a1ecd9fa2f067ba" + }, + { + "index": 22, + "out_digest": "8bf65e08db2dc14a138df5c114940e28396ffe2279278732321dda8d2e377061" + }, + { + "index": 23, + "out_digest": "8d57033cf933cd97f91d56fb405ed39c23193b39c0ad84a9facb60bd7e74db5f" + }, + { + "index": 24, + "out_digest": "223468b0ac64c3b09969e414a560b3aa8f880064facff95098e12adb723bbfdc" + }, + { + "index": 25, + "out_digest": "1ba9767da05df2f37c42c86f246b933f82b600c0af4f8375cfa7f61b671d1569" + }, + { + "index": 26, + "out_digest": "3bbb7b537ed2dacc3ccb2880227a23bab4b6137c3c12e1cdda8b0a11a808ca5b" + }, + { + "index": 27, + "out_digest": "bffb13a73decf062e6756f5bc3bd8178cbc1f306ece9cd63fb92d2808228c784" + }, + { + "index": 28, + "out_digest": "9ecfcc6181471c99e6cf19ba1872f8986898f3a99e412d3bb467678fec8e3863" + }, + { + "index": 29, + "out_digest": "853afa70587615f00c515748754b34f74dc12c5c43a9284a373fa68837d7421c" + }, + { + "index": 30, + "out_digest": "e44c1218b9d73306a15434d4328c2df004bd1edcb645441e250a61a7b151759d" + } + ] + }, + "expected": { + "outcome": "accept", + "link_hash": "ddc9845fd41ccf4f46cef26d8ded00df2630313bc7f81ce755601f29ee0afa4c" + } + }, + { + "name": "session_tree_32", + "about": "an output tree of 32 leaves, half on a byte-exact decoder whose re-decode matches and half checked for membership only, whose re-decode does not and is not checked", + "procedure": "claim", + "receipt": "{\"body\":{\"classical_declared\":700,\"classical_source\":\"wai2-table\",\"counted_discarded\":1904,\"counted_fallback\":0,\"counted_primary\":5607,\"deadline_us\":null,\"decoders\":[{\"capability\":\"wai.video.int_hyper\",\"decoder\":\"builtin:wai@0.4.0\",\"leaves\":16,\"module_status\":null,\"path\":\"primary\",\"pin\":\"7b4371854df0aa1645ac6525b373387c0617b873d5a57748932ee0f386ea164b\",\"rendition\":0,\"tier\":\"decode-equivalence\",\"variant\":null},{\"capability\":\"wai.video.av1\",\"decoder\":\"builtin:wai@0.4.0\",\"leaves\":16,\"module_status\":null,\"path\":\"fallback\",\"pin\":null,\"rendition\":null,\"tier\":null,\"variant\":null}],\"energy\":null,\"fallback_units\":16,\"framing\":\"registered\",\"host\":{\"build\":{\"profile\":\"release\",\"target\":\"aarch64-unknown-linux-gnu\",\"toolchain\":\"rustc 1.95.0\"},\"profile\":\"native-ffi\",\"target\":\"aarch64-unknown-linux-gnu\",\"threads\":4},\"leaf_count\":32,\"media\":\"video\",\"missed\":0,\"missed_units\":[],\"output_root\":\"1b90590a181bc187058842cbd1a0bb40257d3ecd33847f6c51bb9fef678668e8\",\"primary_units\":16,\"receipt_bytes\":640,\"session_nonce\":\"57c5462dfdabd1b7bdd204d34ba33649c057eb535349f29f45eb8f8c7d4a7e7f\",\"stage_sets\":[],\"switches\":[],\"switches_total\":0,\"transferred\":13607,\"uncounted\":2,\"units\":32},\"class\":\"reconstruct-session\",\"issued_at\":\"2026-09-27T12:00:00Z\",\"kind\":\"claim\",\"parent_receipt_hash\":null,\"seq\":0,\"sig\":\"75dc7b67cfbc57228882b6640947281b5fef93aef4dcd46492b977fce188c8742016152d9df125fc903e399162d5716770e5842e9e7e8b8776411728c5280701\",\"signer_id\":\"did:example:sink\",\"signer_pubkey\":\"d759793bbc13a2819a827c76adb6fba8a49aee007f49f2d0992d99b825ad2c48\",\"subject\":\"64c0713cb176874607bf8670295242184b7868a9ff7c55554a5ae08de2c301c1\",\"subject_type\":\"object\"}", + "context": { + "outputs": [ + { + "unit": 0, + "layers": 1, + "decoder": 0, + "out_digest": "55f7e628ca707e2ca3159709eeb68b9000813f2916a299acd33a23e6fe012584" + }, + { + "unit": 1, + "layers": 1, + "decoder": 1, + "out_digest": "a3ee8a4b96eceb663f3d94417957d02f897fc166dc96ebe9bf447c4a36a36264" + }, + { + "unit": 2, + "layers": 1, + "decoder": 0, + "out_digest": "00576d2c4d09ef5d7aa807f9b3b1587e200dea6f6694b4da062b41aa2a5ab8af" + }, + { + "unit": 3, + "layers": 1, + "decoder": 1, + "out_digest": "26cd9b2805b604b26e08d9a461db599c4e249bfd4df41a3befb202bc6d0e0700" + }, + { + "unit": 4, + "layers": 1, + "decoder": 0, + "out_digest": "1cd1984bc553c43ee5a48fe7e182a77e60d8ef3c2b0f959ef1a0efd3813b411f" + }, + { + "unit": 5, + "layers": 1, + "decoder": 1, + "out_digest": "e4c4344155dc2c789a1df265f8064b9ae56f3e0932d85c5ceb38782c135749fc" + }, + { + "unit": 6, + "layers": 1, + "decoder": 0, + "out_digest": "95542e01dfb7d7c52f2d526bf932ee49cf081ee2bc330c42dd0715cca7deff8b" + }, + { + "unit": 7, + "layers": 1, + "decoder": 1, + "out_digest": "cf1c65a8bc3fabc40710f610dcfa9ac2604f45a6fa68f74ee2b464421647da4c" + }, + { + "unit": 8, + "layers": 1, + "decoder": 0, + "out_digest": "5c01f526973ca7dbcde1513bc7d25333954bc4164811a5f21399b6e48d89079d" + }, + { + "unit": 9, + "layers": 1, + "decoder": 1, + "out_digest": "686ff0277613c58687a493af12da86b393bcee283c6758845a2505a93d135905" + }, + { + "unit": 10, + "layers": 1, + "decoder": 0, + "out_digest": "23851d2c5e0cc5365e329fbd9c01238313ac71fd4edb4730fa7d58cc74e74823" + }, + { + "unit": 11, + "layers": 1, + "decoder": 1, + "out_digest": "66270813e69c6cffbacb67f95a9c182b2f04ce8c3b2ee4829c257227a5f4a17a" + }, + { + "unit": 12, + "layers": 1, + "decoder": 0, + "out_digest": "47c089823c210a1989895087dc4d44dc5ed8ee0453d7f2517ccce83cb686c824" + }, + { + "unit": 13, + "layers": 1, + "decoder": 1, + "out_digest": "3a1e42600a46cf28926fc9f03946a3186264cef938e207b9e159591c179fa7ed" + }, + { + "unit": 14, + "layers": 1, + "decoder": 0, + "out_digest": "49eac1e814988d0a60db8a709e70f4a1989819a57e26b92bdd0239c338675c58" + }, + { + "unit": 15, + "layers": 1, + "decoder": 1, + "out_digest": "cd3ac56e7dc49f235a245024c0c560cc19ba73fcc0dfb1d38ff9f58bb180d5db" + }, + { + "unit": 16, + "layers": 1, + "decoder": 0, + "out_digest": "b3c7f2ac61734e3390450d0f34c70f733b20db0c29d8ea634c0fc0a8638f2258" + }, + { + "unit": 17, + "layers": 1, + "decoder": 1, + "out_digest": "64b919c5441af6df04b8563a34fe9fe57b84e802b1856a98e1edafc328e809d6" + }, + { + "unit": 18, + "layers": 1, + "decoder": 0, + "out_digest": "e120f02a7fffc970d4a82e4afa8c7d29a00b06a10a7d9fcbf49edacff256ed1d" + }, + { + "unit": 19, + "layers": 1, + "decoder": 1, + "out_digest": "68aee1cd87a8224bc389c297e3b001e9e842f5f416eaeda4b1aafa365e042d46" + }, + { + "unit": 20, + "layers": 1, + "decoder": 0, + "out_digest": "01d364fffad3148204e1cebc263ab9c8818eab8969da5fcbc5794392d170ad6c" + }, + { + "unit": 21, + "layers": 1, + "decoder": 1, + "out_digest": "7c587829be53d8fd83fa843e9b2d1ae7567637256ffa2b00dc5a12b6b3d2bfbd" + }, + { + "unit": 22, + "layers": 1, + "decoder": 0, + "out_digest": "8bf65e08db2dc14a138df5c114940e28396ffe2279278732321dda8d2e377061" + }, + { + "unit": 23, + "layers": 1, + "decoder": 1, + "out_digest": "da305639e012f936cb52ac1b9d044a1ca6a808036325d4a951e5b06382822efe" + }, + { + "unit": 24, + "layers": 1, + "decoder": 0, + "out_digest": "223468b0ac64c3b09969e414a560b3aa8f880064facff95098e12adb723bbfdc" + }, + { + "unit": 25, + "layers": 1, + "decoder": 1, + "out_digest": "2729200cc60d2fced7b6111aa8579fe341910e7cc3e656ac58be6506be7edd09" + }, + { + "unit": 26, + "layers": 1, + "decoder": 0, + "out_digest": "3bbb7b537ed2dacc3ccb2880227a23bab4b6137c3c12e1cdda8b0a11a808ca5b" + }, + { + "unit": 27, + "layers": 1, + "decoder": 1, + "out_digest": "846311931ccdc46a5ecd34a50468fb769bc2e64b33749f05f54aa4f4f33ac998" + }, + { + "unit": 28, + "layers": 1, + "decoder": 0, + "out_digest": "9ecfcc6181471c99e6cf19ba1872f8986898f3a99e412d3bb467678fec8e3863" + }, + { + "unit": 29, + "layers": 1, + "decoder": 1, + "out_digest": "391f049a7aa1c57d89e770ff717c28d5d394245d57ca8f5e396e4dba414879d8" + }, + { + "unit": 30, + "layers": 1, + "decoder": 0, + "out_digest": "e44c1218b9d73306a15434d4328c2df004bd1edcb645441e250a61a7b151759d" + }, + { + "unit": 31, + "layers": 1, + "decoder": 1, + "out_digest": "f3dbcb2ac88184d978eb8467cef4d7ca5b44301d8a1f9609e95ac8c44e19b5e0" + } + ], + "redecoded": [ + { + "index": 0, + "out_digest": "55f7e628ca707e2ca3159709eeb68b9000813f2916a299acd33a23e6fe012584" + }, + { + "index": 1, + "out_digest": "9df7f2652febf9fe462ff426af1ee3ec158bf203c59392654482b80775804556" + }, + { + "index": 2, + "out_digest": "00576d2c4d09ef5d7aa807f9b3b1587e200dea6f6694b4da062b41aa2a5ab8af" + }, + { + "index": 3, + "out_digest": "5541d29e4f230e7683ad45c081f4f325fa6216f308b1682f621b3ed279fc39f8" + }, + { + "index": 4, + "out_digest": "1cd1984bc553c43ee5a48fe7e182a77e60d8ef3c2b0f959ef1a0efd3813b411f" + }, + { + "index": 5, + "out_digest": "67754c573f1f7605becf03e65bffa704359b96917b5bc203901eb10e32182cf1" + }, + { + "index": 6, + "out_digest": "95542e01dfb7d7c52f2d526bf932ee49cf081ee2bc330c42dd0715cca7deff8b" + }, + { + "index": 7, + "out_digest": "e7f6d40664240de8fe0eea2384891d0f040db6f05dca8450533a725410bfd31f" + }, + { + "index": 8, + "out_digest": "5c01f526973ca7dbcde1513bc7d25333954bc4164811a5f21399b6e48d89079d" + }, + { + "index": 9, + "out_digest": "f3ff8b3d08e7010fb0d5f7c836dc8b5969bcc95a73ae76813443a2b70929b6bb" + }, + { + "index": 10, + "out_digest": "23851d2c5e0cc5365e329fbd9c01238313ac71fd4edb4730fa7d58cc74e74823" + }, + { + "index": 11, + "out_digest": "9469cdcb42fe46fe46e0e0bb0e10f3397dc5048a60b81467183939f1e4548f74" + }, + { + "index": 12, + "out_digest": "47c089823c210a1989895087dc4d44dc5ed8ee0453d7f2517ccce83cb686c824" + }, + { + "index": 13, + "out_digest": "eca166a3ea198bf0271543d5428c3e0323063de0d3352fbde485399d4476a92b" + }, + { + "index": 14, + "out_digest": "49eac1e814988d0a60db8a709e70f4a1989819a57e26b92bdd0239c338675c58" + }, + { + "index": 15, + "out_digest": "fd7ac5bfaf32d59c57faba74ff87b0a09aae703323a147fef03adf7b2761cb1d" + }, + { + "index": 16, + "out_digest": "b3c7f2ac61734e3390450d0f34c70f733b20db0c29d8ea634c0fc0a8638f2258" + }, + { + "index": 17, + "out_digest": "b7988f6a6e8844ff5ec686f9290b0b4ab0c5c3c028b5e9be116e12821b851534" + }, + { + "index": 18, + "out_digest": "e120f02a7fffc970d4a82e4afa8c7d29a00b06a10a7d9fcbf49edacff256ed1d" + }, + { + "index": 19, + "out_digest": "9436e6edd6411835af7500432df9c51a17b590217e97e642f20820df0323387a" + }, + { + "index": 20, + "out_digest": "01d364fffad3148204e1cebc263ab9c8818eab8969da5fcbc5794392d170ad6c" + }, + { + "index": 21, + "out_digest": "68c5337faac08354c20caec0d0e7221de83055c34f8427195a1ecd9fa2f067ba" + }, + { + "index": 22, + "out_digest": "8bf65e08db2dc14a138df5c114940e28396ffe2279278732321dda8d2e377061" + }, + { + "index": 23, + "out_digest": "8d57033cf933cd97f91d56fb405ed39c23193b39c0ad84a9facb60bd7e74db5f" + }, + { + "index": 24, + "out_digest": "223468b0ac64c3b09969e414a560b3aa8f880064facff95098e12adb723bbfdc" + }, + { + "index": 25, + "out_digest": "1ba9767da05df2f37c42c86f246b933f82b600c0af4f8375cfa7f61b671d1569" + }, + { + "index": 26, + "out_digest": "3bbb7b537ed2dacc3ccb2880227a23bab4b6137c3c12e1cdda8b0a11a808ca5b" + }, + { + "index": 27, + "out_digest": "bffb13a73decf062e6756f5bc3bd8178cbc1f306ece9cd63fb92d2808228c784" + }, + { + "index": 28, + "out_digest": "9ecfcc6181471c99e6cf19ba1872f8986898f3a99e412d3bb467678fec8e3863" + }, + { + "index": 29, + "out_digest": "853afa70587615f00c515748754b34f74dc12c5c43a9284a373fa68837d7421c" + }, + { + "index": 30, + "out_digest": "e44c1218b9d73306a15434d4328c2df004bd1edcb645441e250a61a7b151759d" + }, + { + "index": 31, + "out_digest": "43073ca7183c0ad5093bb7eb5045b4ff63a3007c96396852a9891a6f5e4014e2" + } + ] + }, + "expected": { + "outcome": "accept", + "link_hash": "cc979797a17618608e4a449231dafa8ec2edb0e5563b7ba6f3c71da104d13bfc" + } + }, + { + "name": "session_tree_33", + "about": "an output tree of 33 leaves, half on a byte-exact decoder whose re-decode matches and half checked for membership only, whose re-decode does not and is not checked", + "procedure": "claim", + "receipt": "{\"body\":{\"classical_declared\":700,\"classical_source\":\"wai2-table\",\"counted_discarded\":1904,\"counted_fallback\":0,\"counted_primary\":5607,\"deadline_us\":null,\"decoders\":[{\"capability\":\"wai.video.int_hyper\",\"decoder\":\"builtin:wai@0.4.0\",\"leaves\":17,\"module_status\":null,\"path\":\"primary\",\"pin\":\"7b4371854df0aa1645ac6525b373387c0617b873d5a57748932ee0f386ea164b\",\"rendition\":0,\"tier\":\"decode-equivalence\",\"variant\":null},{\"capability\":\"wai.video.av1\",\"decoder\":\"builtin:wai@0.4.0\",\"leaves\":16,\"module_status\":null,\"path\":\"fallback\",\"pin\":null,\"rendition\":null,\"tier\":null,\"variant\":null}],\"energy\":null,\"fallback_units\":16,\"framing\":\"registered\",\"host\":{\"build\":{\"profile\":\"release\",\"target\":\"aarch64-unknown-linux-gnu\",\"toolchain\":\"rustc 1.95.0\"},\"profile\":\"native-ffi\",\"target\":\"aarch64-unknown-linux-gnu\",\"threads\":4},\"leaf_count\":33,\"media\":\"video\",\"missed\":0,\"missed_units\":[],\"output_root\":\"0135af1be9acfa21689c2af62f95b658fbd74467b5f154c75650477c21a02be5\",\"primary_units\":17,\"receipt_bytes\":640,\"session_nonce\":\"57c5462dfdabd1b7bdd204d34ba33649c057eb535349f29f45eb8f8c7d4a7e7f\",\"stage_sets\":[],\"switches\":[],\"switches_total\":0,\"transferred\":13607,\"uncounted\":2,\"units\":33},\"class\":\"reconstruct-session\",\"issued_at\":\"2026-09-27T12:00:00Z\",\"kind\":\"claim\",\"parent_receipt_hash\":null,\"seq\":0,\"sig\":\"1d095d772fc21d72245973b852a8faa4e3f17726d6c1c233392e73a9e889b26d9a3c9a37a5de32c608ab194d495d50d25cde1636e368bca4d43e24b74eeddb06\",\"signer_id\":\"did:example:sink\",\"signer_pubkey\":\"d759793bbc13a2819a827c76adb6fba8a49aee007f49f2d0992d99b825ad2c48\",\"subject\":\"64c0713cb176874607bf8670295242184b7868a9ff7c55554a5ae08de2c301c1\",\"subject_type\":\"object\"}", + "context": { + "outputs": [ + { + "unit": 0, + "layers": 1, + "decoder": 0, + "out_digest": "55f7e628ca707e2ca3159709eeb68b9000813f2916a299acd33a23e6fe012584" + }, + { + "unit": 1, + "layers": 1, + "decoder": 1, + "out_digest": "a3ee8a4b96eceb663f3d94417957d02f897fc166dc96ebe9bf447c4a36a36264" + }, + { + "unit": 2, + "layers": 1, + "decoder": 0, + "out_digest": "00576d2c4d09ef5d7aa807f9b3b1587e200dea6f6694b4da062b41aa2a5ab8af" + }, + { + "unit": 3, + "layers": 1, + "decoder": 1, + "out_digest": "26cd9b2805b604b26e08d9a461db599c4e249bfd4df41a3befb202bc6d0e0700" + }, + { + "unit": 4, + "layers": 1, + "decoder": 0, + "out_digest": "1cd1984bc553c43ee5a48fe7e182a77e60d8ef3c2b0f959ef1a0efd3813b411f" + }, + { + "unit": 5, + "layers": 1, + "decoder": 1, + "out_digest": "e4c4344155dc2c789a1df265f8064b9ae56f3e0932d85c5ceb38782c135749fc" + }, + { + "unit": 6, + "layers": 1, + "decoder": 0, + "out_digest": "95542e01dfb7d7c52f2d526bf932ee49cf081ee2bc330c42dd0715cca7deff8b" + }, + { + "unit": 7, + "layers": 1, + "decoder": 1, + "out_digest": "cf1c65a8bc3fabc40710f610dcfa9ac2604f45a6fa68f74ee2b464421647da4c" + }, + { + "unit": 8, + "layers": 1, + "decoder": 0, + "out_digest": "5c01f526973ca7dbcde1513bc7d25333954bc4164811a5f21399b6e48d89079d" + }, + { + "unit": 9, + "layers": 1, + "decoder": 1, + "out_digest": "686ff0277613c58687a493af12da86b393bcee283c6758845a2505a93d135905" + }, + { + "unit": 10, + "layers": 1, + "decoder": 0, + "out_digest": "23851d2c5e0cc5365e329fbd9c01238313ac71fd4edb4730fa7d58cc74e74823" + }, + { + "unit": 11, + "layers": 1, + "decoder": 1, + "out_digest": "66270813e69c6cffbacb67f95a9c182b2f04ce8c3b2ee4829c257227a5f4a17a" + }, + { + "unit": 12, + "layers": 1, + "decoder": 0, + "out_digest": "47c089823c210a1989895087dc4d44dc5ed8ee0453d7f2517ccce83cb686c824" + }, + { + "unit": 13, + "layers": 1, + "decoder": 1, + "out_digest": "3a1e42600a46cf28926fc9f03946a3186264cef938e207b9e159591c179fa7ed" + }, + { + "unit": 14, + "layers": 1, + "decoder": 0, + "out_digest": "49eac1e814988d0a60db8a709e70f4a1989819a57e26b92bdd0239c338675c58" + }, + { + "unit": 15, + "layers": 1, + "decoder": 1, + "out_digest": "cd3ac56e7dc49f235a245024c0c560cc19ba73fcc0dfb1d38ff9f58bb180d5db" + }, + { + "unit": 16, + "layers": 1, + "decoder": 0, + "out_digest": "b3c7f2ac61734e3390450d0f34c70f733b20db0c29d8ea634c0fc0a8638f2258" + }, + { + "unit": 17, + "layers": 1, + "decoder": 1, + "out_digest": "64b919c5441af6df04b8563a34fe9fe57b84e802b1856a98e1edafc328e809d6" + }, + { + "unit": 18, + "layers": 1, + "decoder": 0, + "out_digest": "e120f02a7fffc970d4a82e4afa8c7d29a00b06a10a7d9fcbf49edacff256ed1d" + }, + { + "unit": 19, + "layers": 1, + "decoder": 1, + "out_digest": "68aee1cd87a8224bc389c297e3b001e9e842f5f416eaeda4b1aafa365e042d46" + }, + { + "unit": 20, + "layers": 1, + "decoder": 0, + "out_digest": "01d364fffad3148204e1cebc263ab9c8818eab8969da5fcbc5794392d170ad6c" + }, + { + "unit": 21, + "layers": 1, + "decoder": 1, + "out_digest": "7c587829be53d8fd83fa843e9b2d1ae7567637256ffa2b00dc5a12b6b3d2bfbd" + }, + { + "unit": 22, + "layers": 1, + "decoder": 0, + "out_digest": "8bf65e08db2dc14a138df5c114940e28396ffe2279278732321dda8d2e377061" + }, + { + "unit": 23, + "layers": 1, + "decoder": 1, + "out_digest": "da305639e012f936cb52ac1b9d044a1ca6a808036325d4a951e5b06382822efe" + }, + { + "unit": 24, + "layers": 1, + "decoder": 0, + "out_digest": "223468b0ac64c3b09969e414a560b3aa8f880064facff95098e12adb723bbfdc" + }, + { + "unit": 25, + "layers": 1, + "decoder": 1, + "out_digest": "2729200cc60d2fced7b6111aa8579fe341910e7cc3e656ac58be6506be7edd09" + }, + { + "unit": 26, + "layers": 1, + "decoder": 0, + "out_digest": "3bbb7b537ed2dacc3ccb2880227a23bab4b6137c3c12e1cdda8b0a11a808ca5b" + }, + { + "unit": 27, + "layers": 1, + "decoder": 1, + "out_digest": "846311931ccdc46a5ecd34a50468fb769bc2e64b33749f05f54aa4f4f33ac998" + }, + { + "unit": 28, + "layers": 1, + "decoder": 0, + "out_digest": "9ecfcc6181471c99e6cf19ba1872f8986898f3a99e412d3bb467678fec8e3863" + }, + { + "unit": 29, + "layers": 1, + "decoder": 1, + "out_digest": "391f049a7aa1c57d89e770ff717c28d5d394245d57ca8f5e396e4dba414879d8" + }, + { + "unit": 30, + "layers": 1, + "decoder": 0, + "out_digest": "e44c1218b9d73306a15434d4328c2df004bd1edcb645441e250a61a7b151759d" + }, + { + "unit": 31, + "layers": 1, + "decoder": 1, + "out_digest": "f3dbcb2ac88184d978eb8467cef4d7ca5b44301d8a1f9609e95ac8c44e19b5e0" + }, + { + "unit": 32, + "layers": 1, + "decoder": 0, + "out_digest": "82ee63367d6fb67eb5687bd5c96b78e24acc397a3ae8a0506a6734a4de3ce20c" + } + ], + "redecoded": [ + { + "index": 0, + "out_digest": "55f7e628ca707e2ca3159709eeb68b9000813f2916a299acd33a23e6fe012584" + }, + { + "index": 1, + "out_digest": "9df7f2652febf9fe462ff426af1ee3ec158bf203c59392654482b80775804556" + }, + { + "index": 2, + "out_digest": "00576d2c4d09ef5d7aa807f9b3b1587e200dea6f6694b4da062b41aa2a5ab8af" + }, + { + "index": 3, + "out_digest": "5541d29e4f230e7683ad45c081f4f325fa6216f308b1682f621b3ed279fc39f8" + }, + { + "index": 4, + "out_digest": "1cd1984bc553c43ee5a48fe7e182a77e60d8ef3c2b0f959ef1a0efd3813b411f" + }, + { + "index": 5, + "out_digest": "67754c573f1f7605becf03e65bffa704359b96917b5bc203901eb10e32182cf1" + }, + { + "index": 6, + "out_digest": "95542e01dfb7d7c52f2d526bf932ee49cf081ee2bc330c42dd0715cca7deff8b" + }, + { + "index": 7, + "out_digest": "e7f6d40664240de8fe0eea2384891d0f040db6f05dca8450533a725410bfd31f" + }, + { + "index": 8, + "out_digest": "5c01f526973ca7dbcde1513bc7d25333954bc4164811a5f21399b6e48d89079d" + }, + { + "index": 9, + "out_digest": "f3ff8b3d08e7010fb0d5f7c836dc8b5969bcc95a73ae76813443a2b70929b6bb" + }, + { + "index": 10, + "out_digest": "23851d2c5e0cc5365e329fbd9c01238313ac71fd4edb4730fa7d58cc74e74823" + }, + { + "index": 11, + "out_digest": "9469cdcb42fe46fe46e0e0bb0e10f3397dc5048a60b81467183939f1e4548f74" + }, + { + "index": 12, + "out_digest": "47c089823c210a1989895087dc4d44dc5ed8ee0453d7f2517ccce83cb686c824" + }, + { + "index": 13, + "out_digest": "eca166a3ea198bf0271543d5428c3e0323063de0d3352fbde485399d4476a92b" + }, + { + "index": 14, + "out_digest": "49eac1e814988d0a60db8a709e70f4a1989819a57e26b92bdd0239c338675c58" + }, + { + "index": 15, + "out_digest": "fd7ac5bfaf32d59c57faba74ff87b0a09aae703323a147fef03adf7b2761cb1d" + }, + { + "index": 16, + "out_digest": "b3c7f2ac61734e3390450d0f34c70f733b20db0c29d8ea634c0fc0a8638f2258" + }, + { + "index": 17, + "out_digest": "b7988f6a6e8844ff5ec686f9290b0b4ab0c5c3c028b5e9be116e12821b851534" + }, + { + "index": 18, + "out_digest": "e120f02a7fffc970d4a82e4afa8c7d29a00b06a10a7d9fcbf49edacff256ed1d" + }, + { + "index": 19, + "out_digest": "9436e6edd6411835af7500432df9c51a17b590217e97e642f20820df0323387a" + }, + { + "index": 20, + "out_digest": "01d364fffad3148204e1cebc263ab9c8818eab8969da5fcbc5794392d170ad6c" + }, + { + "index": 21, + "out_digest": "68c5337faac08354c20caec0d0e7221de83055c34f8427195a1ecd9fa2f067ba" + }, + { + "index": 22, + "out_digest": "8bf65e08db2dc14a138df5c114940e28396ffe2279278732321dda8d2e377061" + }, + { + "index": 23, + "out_digest": "8d57033cf933cd97f91d56fb405ed39c23193b39c0ad84a9facb60bd7e74db5f" + }, + { + "index": 24, + "out_digest": "223468b0ac64c3b09969e414a560b3aa8f880064facff95098e12adb723bbfdc" + }, + { + "index": 25, + "out_digest": "1ba9767da05df2f37c42c86f246b933f82b600c0af4f8375cfa7f61b671d1569" + }, + { + "index": 26, + "out_digest": "3bbb7b537ed2dacc3ccb2880227a23bab4b6137c3c12e1cdda8b0a11a808ca5b" + }, + { + "index": 27, + "out_digest": "bffb13a73decf062e6756f5bc3bd8178cbc1f306ece9cd63fb92d2808228c784" + }, + { + "index": 28, + "out_digest": "9ecfcc6181471c99e6cf19ba1872f8986898f3a99e412d3bb467678fec8e3863" + }, + { + "index": 29, + "out_digest": "853afa70587615f00c515748754b34f74dc12c5c43a9284a373fa68837d7421c" + }, + { + "index": 30, + "out_digest": "e44c1218b9d73306a15434d4328c2df004bd1edcb645441e250a61a7b151759d" + }, + { + "index": 31, + "out_digest": "43073ca7183c0ad5093bb7eb5045b4ff63a3007c96396852a9891a6f5e4014e2" + }, + { + "index": 32, + "out_digest": "82ee63367d6fb67eb5687bd5c96b78e24acc397a3ae8a0506a6734a4de3ce20c" + } + ] + }, + "expected": { + "outcome": "accept", + "link_hash": "2de6ef267a0ea1e6c3a8e407468bdc279d96f8ac8cb65268c4ca4df5f53666dd" + } } ] } diff --git a/wai/wai-rs/Cargo.toml b/wai/wai-rs/Cargo.toml index 3411f5624..bf2087587 100644 --- a/wai/wai-rs/Cargo.toml +++ b/wai/wai-rs/Cargo.toml @@ -205,7 +205,9 @@ telemetry = [] # for the coverage vocabulary and `oer` for the evidential grades and the OER receipt # an energy claim may name, which it reads and verifies through `crate::oer`. Its one # direct dependency, curve25519-dalek, is already in the graph under ed25519-dalek. -receipt_claims = ["provenance", "oer", "jwp_hash", "dep:curve25519-dalek"] +# `telemetry` (no dependency) gives a session claim's switch reasons, delivery-telemetry +# §5's one list (jwp-receipts §2.4.12). +receipt_claims = ["provenance", "oer", "jwp_hash", "telemetry", "dep:curve25519-dalek"] # Key discovery and signing authority (extensions/jwp-receipts.md §7): the origin key # log a `did:web` signer_id names, anchoring, the confirmation reported beside a receipt's # or claim's verdict, and the authorisation and revocation of decoder and reconstruct diff --git a/wai/wai-rs/include/wai.h b/wai/wai-rs/include/wai.h index 988c60e4e..024e56bbc 100644 --- a/wai/wai-rs/include/wai.h +++ b/wai/wai-rs/include/wai.h @@ -333,13 +333,6 @@ */ #define CHAIN_HELD_LINKS 65536 -/** - * How many parents one chain keeps as requested (§3 step 3, §6.1): the parents named by - * groups it refused `parent_not_held`. A group whose link hash is one of them fills a - * gap, and is exempt from the freshness bound. Past it, the oldest request is dropped. - */ -#define CHAIN_REQUESTED_LINKS 64 - /** * `CausalOp::mutation_kind` for an action input (move/look/buttons + free payload). */ diff --git a/wai/wai-rs/src/claim_receipt.rs b/wai/wai-rs/src/claim_receipt.rs index f885c36bb..1c672250f 100644 --- a/wai/wai-rs/src/claim_receipt.rs +++ b/wai/wai-rs/src/claim_receipt.rs @@ -34,7 +34,11 @@ //! hash of what was presented, and every layer object with its status and the evidence //! of its delivery receipt; //! - `delivery-gap` — a relay's statement that it did not forward an object, and why -//! (jwp-receipts §4.2). +//! (jwp-receipts §4.2); +//! - `reconstruct-session` — what a sink reconstructed in one session ([`session`]): its +//! decoders and host, paths and switches, late presentations, the output tree, its +//! counted and transferred bytes, the classical rendition it did not need, the `stage` +//! claims it signed, and its decode energy where metered. //! //! A `measurement` or `operating-point` claim names the receipt that seals its figure //! by a figure profile ([`crate::energy_figure`], energy-measurement §6.1) and that @@ -123,6 +127,11 @@ pub const DOMAIN_CLAIM_LINK: &[u8] = b"moq-jwp:claim-link\x01"; // names here so every existing caller of this module's API stays valid. pub use crate::jwp_hash::{content_hash as object_content_hash, DOMAIN_OBJECT}; +pub mod session; +pub use session::{ + DecoderEntry, Missed, ObjectSeen, SessionClaim, SessionEnergy, SessionHost, SessionPath, StageSetRef, Switch, +}; + /// The largest integer a claim may carry: I-JSON's (RFC 7493) exact-integer bound, /// the canonical form's (`crate::jcs::MAX_INTEGER`). pub(crate) const MAX_INTEGER: u64 = crate::jcs::MAX_INTEGER; @@ -299,6 +308,48 @@ pub enum Reason { /// A `delivery-gap` claim whose subject is not the content hash of the object receipt /// at its coordinates. GapSubjectMismatch, + /// A session whose primary and fallback units do not sum to its units. + SessionPathSum, + /// A session whose entries' leaves are not its leaf count, whose leaf count is below + /// its units, or one of whose units and leaf count is 0 and the other not. + SessionLeafSum, + /// A session with an output root and no leaf, or leaves and no root. + SessionRootPresence, + /// A session whose host's thread count is not a power of two. + SessionHostMalformed, + /// A decoder entry not of its table: the decoder's grammar, a rendition past 65535, a + /// tier without a pin or a pin without a tier or an unknown tier, a module status + /// that does not fit its decoder, no leaf; or two entries that differ only in leaves. + SessionDecoderMalformed, + /// A decoder entry whose tier exceeds its capability's class tier. + SessionTierExceedsClass, + /// A switch between equal paths or for an unlisted reason, switches out of order, + /// more than 1024 written or more than their total. + SessionSwitchInvalid, + /// Missed presentations above the leaves or without a deadline, or a list of them + /// that is too long, out of order or holds an impossible entry. + SessionMissedInvalid, + /// Stage sets out of order, or one listed twice. + SessionStageSetsInvalid, + /// More discarded bytes than were counted. + SessionCountedInvalid, + /// A classical source without a classical length or the converse, or an unknown + /// source. + SessionClassicalInvalid, + /// The presentations do not give the session's output root over its leaf count. + SessionOutputMismatch, + /// The presentations give other units, leaves, first-use order or paths than the + /// session states, or name an entry it does not have. + SessionOutputInconsistent, + /// A byte-exact presentation decoded again gives another digest. + SessionOutputIrreproducible, + /// The objects received give other counted, uncounted or transferred bytes. + SessionCountedMismatch, + /// The entry envelopes do not give the session's classical rendition and length. + SessionClassicalMismatch, + /// A `stage` claim the session names counts units the session's outputs do not hold + /// at its stages. + SessionStageDisagrees, } impl Reason { @@ -376,6 +427,23 @@ impl Reason { Reason::StageUnitsUnsupported => "stage_units_unsupported", Reason::StageDeliveredDisagrees => "stage_delivered_disagrees", Reason::GapSubjectMismatch => "gap_subject_mismatch", + Reason::SessionPathSum => "session_path_sum", + Reason::SessionLeafSum => "session_leaf_sum", + Reason::SessionRootPresence => "session_root_presence", + Reason::SessionHostMalformed => "session_host_malformed", + Reason::SessionDecoderMalformed => "session_decoder_malformed", + Reason::SessionTierExceedsClass => "session_tier_exceeds_class", + Reason::SessionSwitchInvalid => "session_switch_invalid", + Reason::SessionMissedInvalid => "session_missed_invalid", + Reason::SessionStageSetsInvalid => "session_stage_sets_invalid", + Reason::SessionCountedInvalid => "session_counted_invalid", + Reason::SessionClassicalInvalid => "session_classical_invalid", + Reason::SessionOutputMismatch => "session_output_mismatch", + Reason::SessionOutputInconsistent => "session_output_inconsistent", + Reason::SessionOutputIrreproducible => "session_output_irreproducible", + Reason::SessionCountedMismatch => "session_counted_mismatch", + Reason::SessionClassicalMismatch => "session_classical_mismatch", + Reason::SessionStageDisagrees => "session_stage_disagrees", } } } @@ -445,6 +513,7 @@ pub enum ClaimClass { OperatingPoint, Stage, DeliveryGap, + ReconstructSession, } /// The class of `group` and `object` receipts. A claim naming it is rejected. @@ -462,6 +531,7 @@ impl ClaimClass { ClaimClass::OperatingPoint => "operating-point", ClaimClass::Stage => "stage", ClaimClass::DeliveryGap => "delivery-gap", + ClaimClass::ReconstructSession => "reconstruct-session", } } @@ -476,6 +546,7 @@ impl ClaimClass { "operating-point" => Some(ClaimClass::OperatingPoint), "stage" => Some(ClaimClass::Stage), "delivery-gap" => Some(ClaimClass::DeliveryGap), + "reconstruct-session" => Some(ClaimClass::ReconstructSession), _ => None, } } @@ -485,7 +556,8 @@ impl ClaimClass { /// everything a group receipt covers; a report about a figure takes the subject type /// its figure profile fixes (checked at step 4); every other class is about one /// object — a `stage` claim about the stage set's base, a `delivery-gap` claim about - /// the object not forwarded. + /// the object not forwarded, a `reconstruct-session` claim about the session's entry + /// object. pub fn admits(self, t: SubjectType) -> bool { match self { ClaimClass::LogInclusion => t == SubjectType::Receipt, @@ -494,7 +566,8 @@ impl ClaimClass { | ClaimClass::SoftBinding | ClaimClass::BindingRecovery | ClaimClass::Stage - | ClaimClass::DeliveryGap => t == SubjectType::Object, + | ClaimClass::DeliveryGap + | ClaimClass::ReconstructSession => t == SubjectType::Object, } } } @@ -1455,6 +1528,7 @@ pub enum ClaimBody { OperatingPoint(OperatingPointClaim), Stage(StageClaim), DeliveryGap(DeliveryGapClaim), + ReconstructSession(SessionClaim), } /// The energy body's members, in the order step 2 reads them. @@ -1547,6 +1621,7 @@ impl ClaimBody { ClaimBody::OperatingPoint(_) => ClaimClass::OperatingPoint, ClaimBody::Stage(_) => ClaimClass::Stage, ClaimBody::DeliveryGap(_) => ClaimClass::DeliveryGap, + ClaimBody::ReconstructSession(_) => ClaimClass::ReconstructSession, } } @@ -1702,6 +1777,7 @@ impl ClaimBody { m.insert("reason".into(), g.reason.label().into()); m.insert("observed_at".into(), g.observed_at.clone().into()); } + ClaimBody::ReconstructSession(c) => return c.to_value(), } Value::Object(m) } @@ -1924,6 +2000,7 @@ impl ClaimBody { } ClaimBody::DeliveryGap(DeliveryGapClaim { track_alias, group_id, object_id, reason, observed_at }) } + ClaimClass::ReconstructSession => ClaimBody::ReconstructSession(SessionClaim::read(m)?), ClaimClass::BindingRecovery => { members(m, RECOVERY_MEMBERS)?; ClaimBody::BindingRecovery(BindingRecoveryClaim { @@ -2056,6 +2133,7 @@ impl ClaimBody { } Ok(()) } + ClaimBody::ReconstructSession(c) => c.check_values(), } } @@ -2153,6 +2231,7 @@ impl ClaimBody { // A gap has no rule of its own beyond its types; its subject is checked // against the object receipt at its coordinates at step 6. ClaimBody::DeliveryGap(_) => Ok(()), + ClaimBody::ReconstructSession(c) => c.rules(), } } } @@ -3378,7 +3457,7 @@ pub(crate) fn rfc3339(s: &str) -> bool { /// fails instead of passing on nothing. (A function rather than a public constant so /// cbindgen does not export it into the C header.) pub fn corpus_vector_count() -> usize { - 302 + 415 } /// The conformance corpus (`claim-conformance/vectors.json`), regenerated. Ed25519 @@ -3416,6 +3495,8 @@ mod corpus { use curve25519_dalek::{edwards::CompressedEdwardsY, EdwardsPoint, Scalar}; use serde_json::json; + mod session; + const T0: &str = "2026-09-27T12:00:00Z"; const WM_ALG: &str = "org.example.watermark.1"; const FP_ALG: &str = "org.example.fingerprint.1"; @@ -4612,6 +4693,8 @@ mod corpus { ]); v.extend(report_vectors()); v.extend(stage_vectors()); + // §2.4.12, appended: the vectors above are an unchanged prefix. + v.extend(session::vectors()); v } @@ -5341,7 +5424,7 @@ mod corpus { let mut doc = Map::new(); doc.insert( "about".into(), - "jwp-receipts section 2.4.3-2.4.11, 2.6 and 3.1-3.2: typed claim receipts and the soft \ + "jwp-receipts section 2.4.3-2.4.12, 2.6 and 3.1-3.2: typed claim receipts and the soft \ binding class. Every vector is synthetic: keys are Ed25519 from fixed 32-byte seeds \ (0x11 publisher, 0x22 meter, 0x33 operator, 0x44 sink, 0x55 resolver, 0x66 relay) \ and attest nothing; figures are invented; algorithm names, endpoints, logs and registries use \ @@ -5462,6 +5545,38 @@ mod corpus { return Ok(Err(e)); } } + // §2.4.12: a session against its outputs, the objects it received, its entry + // envelopes and the stage claims it names, in that order. + let outputs = c.get("outputs").map(presentations_of).transpose()?; + if let Some(ps) = &outputs { + let found = redecoded_of(c.get("redecoded"))?; + if let Err(e) = r.check_session_outputs(ps, &|i| found.get(&i).copied()) { + return Ok(Err(e)); + } + } + if let Some(o) = c.get("objects") + && let Err(e) = r.check_session_objects(&objects_of(o)?) + { + return Ok(Err(e)); + } + if let Some(e) = c.get("envelopes") { + let envs = envelopes_of(e)?; + let refs: Vec<(&[u8], u64)> = envs.iter().map(|(b, i)| (b.as_slice(), *i)).collect(); + if let Err(e) = r.check_session_envelopes(&refs) { + return Ok(Err(e)); + } + } + if let Some(w) = c.get("stage_claims") { + let wires = w + .as_array() + .ok_or("stage_claims must be an array")? + .iter() + .map(|x| x.as_str().ok_or("a stage claim is given as its wire form")) + .collect::, _>>()?; + if let Err(e) = r.check_session_stage_claims(&wires, outputs.as_deref()) { + return Ok(Err(e)); + } + } if let Some(w) = ctx_wire("declaration")? { // §2.6.3: the declaration is context only together with the publisher // key; a corpus that supplies one without the other is malformed, not @@ -5491,6 +5606,70 @@ mod corpus { } } + /// An `outputs` context: the presentations a session commits to. + fn presentations_of(v: &Value) -> Result, String> { + v.as_array() + .ok_or("outputs must be an array")? + .iter() + .map(|p| { + let n = |k: &str| p.get(k).and_then(Value::as_u64).ok_or(format!("bad output {k}")); + Ok(crate::output_tree::Presentation { + unit: n("unit")?, + layers: u16::try_from(n("layers")?).map_err(|_| "bad output layers")?, + decoder: u16::try_from(n("decoder")?).map_err(|_| "bad output decoder")?, + out_digest: hash_of(p.get("out_digest"), "output out_digest")?, + }) + }) + .collect() + } + + /// A `redecoded` context: what a verifier found when it decoded the presentations at + /// these indices of `outputs` again. + fn redecoded_of(v: Option<&Value>) -> Result, String> { + let Some(v) = v else { return Ok(BTreeMap::new()) }; + v.as_array() + .ok_or("redecoded must be an array")? + .iter() + .map(|x| { + let i = x.get("index").and_then(Value::as_u64).ok_or("bad redecoded index")?; + Ok((usize::try_from(i).map_err(|_| "bad redecoded index")?, hash_of(x.get("out_digest"), "redecoded out_digest")?)) + }) + .collect() + } + + /// An `objects` context: each object a session received. + fn objects_of(v: &Value) -> Result, String> { + v.as_array() + .ok_or("objects must be an array")? + .iter() + .map(|o| { + Ok(ObjectSeen { + content_hash: hash_of(o.get("content_hash"), "object content_hash")?, + path: o.get("path").and_then(Value::as_str).and_then(SessionPath::from_label).ok_or("bad object path")?, + counted: match o.get("counted") { + Some(Value::Null) => None, + c => Some(c.and_then(Value::as_u64).ok_or("bad object counted")?), + }, + transferred: o.get("transferred").and_then(Value::as_u64).ok_or("bad object transferred")?, + presented: o.get("presented").and_then(Value::as_bool).ok_or("bad object presented")?, + }) + }) + .collect() + } + + /// An `envelopes` context: each entry envelope's bytes and its classical rendition's + /// index. + fn envelopes_of(v: &Value) -> Result, u64)>, String> { + v.as_array() + .ok_or("envelopes must be an array")? + .iter() + .map(|e| { + let bytes = e.get("envelope").and_then(Value::as_str).and_then(unhex).ok_or("bad envelope")?; + Ok((bytes, e.get("rendition").and_then(Value::as_u64).ok_or("bad envelope rendition")?)) + }) + .collect() + } + /// A `figure` context: the receipt that carries the figure a report names — an /// `energy` claim's wire form (`claim`), viewed as `crate::energy_figure` views it, or /// a receipt the verifier has verified, given as its view (`view`): `{profile, @@ -6252,6 +6431,77 @@ mod tests { assert_eq!(hex(digest.as_bytes()), "55d483624eca626b710c93ea954f854df57fd16029aaf6d6fa78edc1771b484c"); } + /// The vectors the corpus held before the `reconstruct-session` class was added, + /// pinned as the tests above pin theirs. The digest was computed from the corpus as + /// it stood before the class was added and must never be edited to make the test pass. + #[test] + fn the_vectors_before_the_session_are_unchanged() { + let doc: Value = crate::oer::load(conformance_vectors().as_bytes()).unwrap(); + let vs = doc["vectors"].as_array().unwrap(); + let first = Value::Array(vs[..302].to_vec()); + let digest = blake3::hash(serde_json::to_string(&first).unwrap().as_bytes()); + assert_eq!(hex(digest.as_bytes()), "41465e7b57ca795b8ee4b998f11553a3a2b720fe994e6f0d53866af73f281ba1"); + } + + /// A session claim's grammars (§2.4.12): `media`, a decoder identifier, and the + /// rounding of its worker count. + #[test] + fn session_grammars() { + use super::session::{decoder_ok, media_ok}; + for ok in ["builtin:wai@0.4.0", "builtin:a@1", "builtin:wai_rs-x@1.2.3-rc.1+build", &format!("module:sha256:{}", "ab".repeat(32))] { + assert!(decoder_ok(ok), "{ok}"); + } + for bad in [ + "builtin:wai", + "builtin:@1", + "builtin:wai@", + "builtin:wai@v1", + "builtin:Wai@1", + "builtin:wai@1@2", + "builtin:wai@1 ", + "module:sha256:", + &format!("module:sha256:{}", "AB".repeat(32)), + &format!("module:sha256:{}", "ab".repeat(33)), + &format!("builtin:{}@1", "a".repeat(65)), + &format!("builtin:a@1{}", "0".repeat(64)), + "wai@0.4.0", + ] { + assert!(!decoder_ok(bad), "{bad}"); + } + assert!(media_ok("video") && media_ok("a") && media_ok(&"a".repeat(32)) && media_ok("x-1")); + assert!(!media_ok("") && !media_ok(&"a".repeat(33)) && !media_ok("Video") && !media_ok("a b") && !media_ok("a.b")); + let r = SessionHost::rounded_threads; + assert_eq!([r(0), r(1), r(2), r(3), r(4), r(7), r(8), r(1023), r(u64::MAX)], [1, 1, 2, 2, 4, 4, 8, 512, 1 << 63]); + } + + /// A session claim round-trips through its wire form, its figure is viewed under the + /// claim-link profile only where it was metered, and its figure is a second item for + /// confirmation, needing the session's authority and the class's. + #[test] + fn a_session_round_trips_and_its_figure_is_its_own_item() { + use crate::energy_figure::EnergyFigures; + let doc: Value = crate::oer::load(conformance_vectors().as_bytes()).unwrap(); + let wire = |name: &str| { + doc["vectors"].as_array().unwrap().iter().find(|v| v["name"] == name).unwrap()["receipt"].as_str().unwrap().to_owned() + }; + let unmetered = verify_claim_json(&wire("session_accept")).unwrap(); + let metered = verify_claim_json(&wire("session_metered_accept")).unwrap(); + for c in [&unmetered, &metered] { + assert_eq!(c.class(), ClaimClass::ReconstructSession); + assert_eq!(ClaimReceipt::from_json(&c.to_json()).unwrap(), *c); + assert_eq!(c.authorities(), vec!["reconstruct-session".to_owned()]); + } + assert_eq!(unmetered.figure_authorities(), None); + assert_eq!(metered.figure_authorities(), Some(vec!["reconstruct-session".to_owned(), "energy/OnChipCounter".to_owned()])); + let v = unmetered.figure_view().unwrap(); + assert_eq!((v.profile.as_str(), v.identity, v.figures.len()), ("moq-jwp:claim-link", unmetered.link_hash(), 0)); + let v = metered.figure_view().unwrap(); + assert_eq!((v.profile.as_str(), v.identity, v.signer), ("moq-jwp:claim-link", metered.link_hash(), Some(metered.signer_pubkey))); + let f = v.figure(None).unwrap(); + assert_eq!(f.joules_micro, 250_000); + assert_eq!(f.class.as_ref().map(|c| c.label()), Some("OnChipCounter")); + } + /// §2.4.10's rules, each refused at step 4 by `seal` as a verifier refuses it; the /// delivered stage a reader derives from the objects; rule 5 not applied when no /// stage is stated as delivered; and whether a commitment was met, derived. diff --git a/wai/wai-rs/src/claim_receipt/corpus/session.rs b/wai/wai-rs/src/claim_receipt/corpus/session.rs new file mode 100644 index 000000000..4b0145492 --- /dev/null +++ b/wai/wai-rs/src/claim_receipt/corpus/session.rs @@ -0,0 +1,887 @@ +//! The `reconstruct-session` vectors of `claim-conformance/` (jwp-receipts §2.4.12, §5.11). +//! +//! One session is the model the others edit: a title of five units, four of them a stage +//! set over a pinned base, decoded on the primary path and refined to up to three +//! layers, the fifth decoded on the fallback path after a switch and presented late, and +//! an entry envelope whose classical rendition the sink did not need. Every context a +//! verifier can hold is given beside it: the presentations, the objects received, the +//! entry envelope and the `stage` claim the session names. + +use super::*; +use crate::container::{Rendition, WaiMulti}; +use crate::output_tree::Presentation; + +const SINK_ID: &str = "did:example:sink"; + +fn leak(s: String) -> &'static str { + Box::leak(s.into_boxed_str()) +} + +/// The digest of a presentation's output: synthetic, one per (unit, layers). +fn digest(unit: u64, layers: u16) -> [u8; 32] { + crate::pin::sha256(format!("claim-conformance: the output of unit {unit} at {layers} layers").as_bytes()) +} + +fn pres(unit: u64, layers: u16, decoder: u16) -> Presentation { + Presentation { unit, layers, decoder, out_digest: digest(unit, layers) } +} + +/// The pin the base's decode verified. +fn pin() -> [u8; 32] { + crate::pin::sha256(b"claim-conformance: a parameter set") +} + +/// The entry envelope: a `WAI2` whose first rendition the session decodes and whose +/// second, a classical rendition, it did not need. +fn entry_envelope() -> Vec { + WaiMulti::new( + "video", + "replicate", + Value::Null, + vec![ + Rendition::media("wai.video.int_hyper", "int_hyper", vec![0x11; 200]), + Rendition::media("wai.video.avc", "avc", vec![0x22; 700]), + ], + ) + .to_bytes() + .expect("a WAI2 envelope") +} + +/// The session's entry object: the entry envelope's content hash. +fn entry() -> [u8; 32] { + object_content_hash(&entry_envelope()) +} + +fn entry_decoder(capability: &str, path: SessionPath, pinned: bool, rendition: Option, leaves: u64) -> DecoderEntry { + DecoderEntry { + capability: capability.into(), + rendition, + path, + decoder: "builtin:wai@0.4.0".into(), + variant: None, + pin: pinned.then(pin), + tier: pinned.then(|| "decode-equivalence".into()), + module_status: None, + leaves, + } +} + +/// The presentations of the model session: units 0–3 at layer 1 through the base, unit 4 +/// at layer 1 through the fallback, units 0–2 at layer 2 and unit 0 at layer 3 through +/// the refinement. +fn model_presentations() -> Vec { + let mut ps: Vec = (0..4).map(|u| pres(u, 1, 0)).collect(); + ps.push(pres(4, 1, 1)); + ps.extend((0..3).map(|u| pres(u, 2, 2))); + ps.push(pres(0, 3, 2)); + ps +} + +/// The stage claim the model session names: the set of units 0–3 as the sink observed it. +/// Units 0, 1 and 2 reached stage 1 on time, unit 3's first layer arrived late; unit 0 +/// reached stage 2, unit 1's second layer arrived late. +fn model_stage(units: &[u64], second_layer_applied_to_unit_1: bool) -> ClaimReceipt { + let mut objects: Vec = (0..3).map(|i| st_obj(1, &format!("s1.{i}"), i, 1, 900 + i, StageStatus::Applied, StageEvidence::None, None)).collect(); + objects.push(st_obj(1, "s1.3", 3, 1, 903, StageStatus::Late, StageEvidence::None, None)); + objects.push(st_obj(2, "s2.0", 0, 1, 1000, StageStatus::Applied, StageEvidence::None, None)); + let unit1 = if second_layer_applied_to_unit_1 { StageStatus::Applied } else { StageStatus::Late }; + objects.push(st_obj(2, "s2.1", 1, 1, 1001, unit1, StageEvidence::None, None)); + let misses = if second_layer_applied_to_unit_1 { 1 } else { 2 }; + seal(&viewer(), SINK_ID, SubjectType::Object, stage_base(), 0, ClaimBody::Stage(stage_body(None, None, None, 0, units, "none", objects, 0, misses)), None) +} + +fn model_stage_ok() -> ClaimReceipt { + model_stage(&[1, 2, 1], false) +} + +/// The objects the model session received: the entry envelope (not countable: its +/// classical rendition's format is not checked), the six layer objects of its stage set +/// (two arrived late and were never presented), and the fallback envelope (not +/// countable). +fn model_objects() -> Vec { + let layer = |name: &str, bytes: u64, presented: bool| ObjectSeen { + content_hash: layer_hash(name), + path: SessionPath::Primary, + counted: Some(bytes), + transferred: bytes, + presented, + }; + vec![ + ObjectSeen { content_hash: entry(), path: SessionPath::Primary, counted: None, transferred: 5_000, presented: true }, + layer("s1.0", 900, true), + layer("s1.1", 901, true), + layer("s1.2", 902, true), + layer("s1.3", 903, false), + layer("s2.0", 1000, true), + layer("s2.1", 1001, false), + ObjectSeen { + content_hash: object_content_hash(b"WAI1 claim-conformance: the fallback rendition"), + path: SessionPath::Fallback, + counted: None, + transferred: 3_000, + presented: true, + }, + ] +} + +fn model() -> SessionClaim { + let ps = model_presentations(); + SessionClaim { + session_nonce: crate::pin::sha256(b"claim-conformance: a session nonce"), + media: "video".into(), + host: SessionHost { + profile: "native-ffi".into(), + target: Some("aarch64-unknown-linux-gnu".into()), + build: BuildRecord { profile: BuildProfile::Release, toolchain: Some("rustc 1.95.0".into()), target: Some("aarch64-unknown-linux-gnu".into()) }, + threads: 4, + }, + decoders: vec![ + entry_decoder("wai.video.int_hyper", SessionPath::Primary, true, Some(0), 4), + entry_decoder("wai.video.av1", SessionPath::Fallback, false, None, 1), + entry_decoder("wai.video.int_refine", SessionPath::Primary, false, None, 4), + ], + units: 5, + leaf_count: 9, + output_root: crate::output_tree::root(&ps).expect("distinct presentations"), + primary_units: 4, + fallback_units: 1, + switches: vec![Switch { unit: 4, from: SessionPath::Primary, to: SessionPath::Fallback, reason: "set-incomplete".into() }], + switches_total: 1, + deadline_us: Some(40_000), + missed: 1, + missed_units: vec![Missed { unit: 4, layers: 1, late_us: 1_200 }], + stage_sets: vec![StageSetRef { first_unit: 0, claim: model_stage_ok().link_hash() }], + framing: "registered".into(), + counted_primary: 5_607, + counted_fallback: 0, + counted_discarded: 1_904, + uncounted: 2, + transferred: 13_607, + receipt_bytes: 640, + classical_declared: Some(700), + classical_source: Some("wai2-table".into()), + energy: None, + } +} + +fn metered() -> SessionClaim { + SessionClaim { + energy: Some(SessionEnergy { + joules_micro: 250_000, + energy_provenance: "OnChipCounter".into(), + energy_uncertainty: Some(DeclaredUncertainty { relative_ppm: 20_000, window_us: 1_000_000 }), + energy_counter_filtering: Some("Unknown".into()), + energy_calibration_ref: None, + }), + ..model() + } +} + +fn sealed(s: SessionClaim) -> ClaimReceipt { + seal(&viewer(), SINK_ID, SubjectType::Object, entry(), 0, ClaimBody::ReconstructSession(s), None) +} + +fn bad(s: SessionClaim) -> String { + seal_bad(&viewer(), SINK_ID, SubjectType::Object, entry(), 0, ClaimBody::ReconstructSession(s)) +} + +/// A session with its tree and its leaf count recomputed from `ps`, so the tree holds and +/// only what the edit changed is wrong. +fn over(mut s: SessionClaim, ps: &[Presentation]) -> SessionClaim { + s.output_root = crate::output_tree::root(ps).expect("distinct presentations"); + s.leaf_count = ps.len() as u64; + s +} + +fn outputs_value(ps: &[Presentation]) -> Value { + Value::Array( + ps.iter() + .map(|p| json!({ "unit": p.unit, "layers": p.layers, "decoder": p.decoder, "out_digest": hex(&p.out_digest) })) + .collect(), + ) +} + +fn objects_value(os: &[ObjectSeen]) -> Value { + Value::Array( + os.iter() + .map(|o| { + json!({ "content_hash": hex(&o.content_hash), "path": o.path.label(), "counted": o.counted, + "transferred": o.transferred, "presented": o.presented }) + }) + .collect(), + ) +} + +fn envelopes_value(es: &[(Vec, u64)]) -> Value { + Value::Array(es.iter().map(|(e, r)| json!({ "envelope": hex(e), "rendition": r })).collect()) +} + +/// What a verifier that decoded the presentations at these indices again found. +fn redecoded_value(found: &[(usize, [u8; 32])]) -> Value { + Value::Array(found.iter().map(|(i, d)| json!({ "index": i, "out_digest": hex(d) })).collect()) +} + +/// Every context of the model session, as a verifier holding all of them has them. +fn all(v: V, ps: &[Presentation], objects: &[ObjectSeen], stage: &[&ClaimReceipt]) -> V { + let v = with(v, "outputs", outputs_value(ps)); + let v = with(v, "redecoded", redecoded_value(&[(0, ps[0].out_digest)])); + let v = with(v, "objects", objects_value(objects)); + let v = with(v, "envelopes", envelopes_value(&[(entry_envelope(), 1)])); + with(v, "stage_claims", Value::Array(stage.iter().map(|c| Value::String(c.to_json())).collect())) +} + +fn with_model_contexts(v: V) -> V { + all(v, &model_presentations(), &model_objects(), &[&model_stage_ok()]) +} + +/// A session of `n` units, each presented once: the even ones on the primary path +/// through a decoder whose replicate class makes it byte-exact, the odd ones on the +/// fallback path through one checked for membership only. The re-decodes a verifier made +/// give the digest for the first and another digest for the second, which it does not +/// check. +fn tree_vector(n: u64) -> V { + let ps: Vec = (0..n).map(|u| pres(u, 1, (u % 2) as u16)).collect(); + let fallback = n / 2; + let mut decoders = vec![entry_decoder("wai.video.int_hyper", SessionPath::Primary, true, Some(0), n - fallback)]; + if fallback > 0 { + decoders.push(entry_decoder("wai.video.av1", SessionPath::Fallback, false, None, fallback)); + } + let s = SessionClaim { + decoders, + units: n, + primary_units: n - fallback, + fallback_units: fallback, + switches: vec![], + switches_total: 0, + deadline_us: None, + missed: 0, + missed_units: vec![], + stage_sets: vec![], + ..over(model(), &ps) + }; + let found: Vec<(usize, [u8; 32])> = + ps.iter().enumerate().map(|(i, p)| (i, if p.decoder == 0 { p.out_digest } else { digest(p.unit, 9) })).collect(); + let name = leak(format!("session_tree_{n:02}")); + let about = leak(format!( + "an output tree of {n} leaves, half on a byte-exact decoder whose re-decode matches and half checked for membership only, whose re-decode does not and is not checked" + )); + let v = claim(name, about, sealed(s).to_json(), Ok(())); + let v = with(v, "outputs", outputs_value(&ps)); + with(v, "redecoded", redecoded_value(&found)) +} + +pub(super) fn vectors() -> Vec { + let ps = model_presentations(); + let objects = model_objects(); + let stage = model_stage_ok(); + let mut v = vec![ + with_model_contexts(claim( + "session_accept", + "an unmetered session: five units, a stage set refined to three layers, a switch to the fallback, one late presentation and a classical rendition not needed; every context held", + sealed(model()).to_json(), + Ok(()), + )), + with_model_contexts(claim( + "session_metered_accept", + "the same session metered under OnChipCounter with its declared uncertainty and filtering state", + sealed(metered()).to_json(), + Ok(()), + )), + claim("session_no_context_accept", "the model session checked with no context: steps 1-5 only", sealed(model()).to_json(), Ok(())), + with( + claim( + "session_stage_claim_without_outputs_accept", + "the stage claim the session names, held without the outputs: only its identity is checked", + sealed(model()).to_json(), + Ok(()), + ), + "stage_claims", + json!([stage.to_json()]), + ), + ]; + + // ── step 4 ── + let r4 = |name: &'static str, about: &'static str, s: SessionClaim, reason: Reason| reject(name, about, bad(s), 4, reason); + let m = model; + v.push(r4("session_path_sum", "primary_units counts one unit more than were presented", SessionClaim { primary_units: 5, ..m() }, Reason::SessionPathSum)); + v.push(r4( + "session_leaf_sum", + "the entries' leaves sum to one more than leaf_count", + { let mut s = m(); s.decoders[2].leaves = 5; s }, + Reason::SessionLeafSum, + )); + v.push(r4( + "session_leaf_count_below_units", + "fewer leaves than units: a unit counted as presented with no presentation", + { let mut s = m(); s.units = 10; s.primary_units = 9; s }, + Reason::SessionLeafSum, + )); + v.push(r4( + "session_no_units_with_leaves", + "leaves with no unit presented", + SessionClaim { + units: 0, + primary_units: 0, + fallback_units: 0, + ..m() + }, + Reason::SessionLeafSum, + )); + v.push(r4("session_root_absent", "presentations and no output root", SessionClaim { output_root: None, ..m() }, Reason::SessionRootPresence)); + v.push(r4( + "session_root_without_leaves", + "an output root over no presentation", + SessionClaim { + decoders: vec![], + units: 0, + leaf_count: 0, + primary_units: 0, + fallback_units: 0, + missed: 0, + missed_units: vec![], + ..m() + }, + Reason::SessionRootPresence, + )); + v.push(r4( + "session_threads_not_power_of_two", + "three decode workers, written as they are rather than rounded down to two", + { let mut s = m(); s.host.threads = 3; s }, + Reason::SessionHostMalformed, + )); + let entry_edit = |edit: &dyn Fn(&mut DecoderEntry)| { + let mut s = m(); + edit(&mut s.decoders[1]); + s + }; + v.push(r4("session_decoder_no_version", "a builtin decoder with no version", entry_edit(&|d| d.decoder = "builtin:wai".into()), Reason::SessionDecoderMalformed)); + v.push(r4( + "session_decoder_version_not_a_digit", + "a builtin decoder whose version begins with a letter", + entry_edit(&|d| d.decoder = "builtin:wai@v0.4.0".into()), + Reason::SessionDecoderMalformed, + )); + v.push(r4( + "session_decoder_module_short_digest", + "a module decoder whose digest is 63 digits", + entry_edit(&|d| { + d.decoder = format!("module:sha256:{}", &hex(&pin())[..63]); + d.module_status = Some("pinned".into()); + }), + Reason::SessionDecoderMalformed, + )); + v.push(r4( + "session_decoder_tier_without_pin", + "a tier with no pin verified", + entry_edit(&|d| d.tier = Some("none".into())), + Reason::SessionDecoderMalformed, + )); + v.push(r4( + "session_decoder_unknown_tier", + "a pin whose tier is not a tier of SPEC 3.1", + { let mut s = m(); s.decoders[0].tier = Some("bit-exact".into()); s }, + Reason::SessionDecoderMalformed, + )); + v.push(r4( + "session_decoder_builtin_with_module_status", + "a module status on a builtin decoder", + entry_edit(&|d| d.module_status = Some("fetched".into())), + Reason::SessionDecoderMalformed, + )); + v.push(r4( + "session_decoder_module_without_status", + "a module decoder with no module status", + entry_edit(&|d| d.decoder = format!("module:sha256:{}", hex(&pin()))), + Reason::SessionDecoderMalformed, + )); + v.push(r4( + "session_decoder_rendition_past_u16", + "a rendition index past 65535", + { let mut s = m(); s.decoders[0].rendition = Some(65_536); s }, + Reason::SessionDecoderMalformed, + )); + v.push(r4( + "session_decoder_twice", + "two entries that differ only in their leaves", + { + let mut s = m(); + let mut d = s.decoders[2].clone(); + d.leaves = 1; + s.decoders[2].leaves = 3; + s.decoders.push(d); + s + }, + Reason::SessionDecoderMalformed, + )); + v.push(r4( + "session_decoder_no_leaves", + "an entry through which nothing was presented", + { + let mut s = m(); + let mut d = s.decoders[1].clone(); + d.capability = "wai.video.avc".into(); + d.leaves = 0; + s.decoders.push(d); + s + }, + Reason::SessionDecoderMalformed, + )); + v.push(r4( + "session_tier_exceeds_class", + "a refinement capability's entry pinned at decode-equivalence, above its class's tier", + { + let mut s = m(); + s.decoders[2].pin = Some(pin()); + s.decoders[2].tier = Some("decode-equivalence".into()); + s + }, + Reason::SessionTierExceedsClass, + )); + v.push(r4( + "session_switch_to_same_path", + "a switch from the primary path to the primary path", + { let mut s = m(); s.switches[0].to = SessionPath::Primary; s }, + Reason::SessionSwitchInvalid, + )); + v.push(r4( + "session_switch_unknown_reason", + "a switch for a reason delivery-telemetry section 5 does not list", + { let mut s = m(); s.switches[0].reason = "too-slow".into(); s }, + Reason::SessionSwitchInvalid, + )); + v.push(r4( + "session_switch_out_of_order", + "two switches in decreasing order of unit", + { + let mut s = m(); + s.switches.insert(0, Switch { unit: 5, from: SessionPath::Fallback, to: SessionPath::Primary, reason: "recovered".into() }); + s.switches_total = 2; + s + }, + Reason::SessionSwitchInvalid, + )); + v.push(r4( + "session_switches_above_total", + "one switch written and switches_total 0", + SessionClaim { switches_total: 0, ..m() }, + Reason::SessionSwitchInvalid, + )); + v.push(r4( + "session_missed_without_deadline", + "a presentation counted as missed with no deadline to miss", + SessionClaim { deadline_us: None, ..m() }, + Reason::SessionMissedInvalid, + )); + v.push(r4( + "session_missed_above_leaves", + "more presentations missed than presented", + SessionClaim { missed: 10, ..m() }, + Reason::SessionMissedInvalid, + )); + v.push(r4( + "session_missed_units_above_missed", + "two missed presentations written and missed 1", + { let mut s = m(); s.missed_units.insert(0, Missed { unit: 3, layers: 1, late_us: 10 }); s }, + Reason::SessionMissedInvalid, + )); + v.push(r4( + "session_missed_not_late", + "a missed presentation zero microseconds late", + { let mut s = m(); s.missed_units[0].late_us = 0; s }, + Reason::SessionMissedInvalid, + )); + v.push(r4( + "session_missed_out_of_order", + "missed presentations out of order", + { + let mut s = m(); + s.missed = 2; + s.missed_units = vec![Missed { unit: 4, layers: 1, late_us: 1_200 }, Missed { unit: 3, layers: 1, late_us: 10 }]; + s + }, + Reason::SessionMissedInvalid, + )); + v.push(r4( + "session_stage_set_twice", + "one stage set listed twice", + { let mut s = m(); let e = s.stage_sets[0]; s.stage_sets.push(e); s }, + Reason::SessionStageSetsInvalid, + )); + v.push(r4( + "session_discarded_above_counted", + "more bytes discarded than were counted", + SessionClaim { counted_discarded: 5_608, ..m() }, + Reason::SessionCountedInvalid, + )); + v.push(r4( + "session_classical_without_source", + "a classical length with no source", + SessionClaim { classical_source: None, ..m() }, + Reason::SessionClassicalInvalid, + )); + v.push(r4( + "session_classical_source_unregistered", + "a classical source no extension registers", + SessionClaim { classical_source: Some("referenced".into()), ..m() }, + Reason::SessionClassicalInvalid, + )); + let energy_edit = |edit: &dyn Fn(&mut SessionEnergy)| { + let mut s = metered(); + edit(s.energy.as_mut().expect("metered")); + s + }; + v.push(r4("session_energy_zero", "a decode figure of zero: the unmetered session is energy null", energy_edit(&|e| e.joules_micro = 0), Reason::EnergyZeroFigure)); + v.push(r4( + "session_energy_unknown_acquisition", + "a class energy-measurement section 2 does not name", + energy_edit(&|e| e.energy_provenance = "Measured".into()), + Reason::EnergyUnknownAcquisition, + )); + v.push(r4( + "session_energy_legacy_acquisition", + "the legacy HwShunt", + energy_edit(&|e| e.energy_provenance = "HwShunt".into()), + Reason::EnergyLegacyAcquisition, + )); + v.push(r4( + "session_energy_no_uncertainty", + "an OnChipCounter figure with no declared uncertainty", + energy_edit(&|e| e.energy_uncertainty = None), + Reason::EnergyAcquisitionEvidence, + )); + v.push(r4( + "session_energy_below_resolution", + "a 1 microjoule OnChipCounter figure declared below the resolution floor", + energy_edit(&|e| { + e.joules_micro = 1; + e.energy_uncertainty = Some(DeclaredUncertainty { relative_ppm: 288_675, window_us: 1_000_000 }); + }), + Reason::EnergyAcquisitionEvidence, + )); + + // ── steps 1 and 2 ── + let edit = |f: &dyn Fn(&mut Map)| resigned(&sealed(model()), &viewer(), |m| f(body_of(m))); + let nested = |m: &mut Map, k: &str| -> Map { m[k].as_object().expect("object").clone() }; + v.push(reject( + "session_about_a_receipt", + "a session whose subject is a receipt", + seal_bad(&viewer(), SINK_ID, SubjectType::Receipt, entry(), 0, ClaimBody::ReconstructSession(model())), + 1, + Reason::SubjectTypeNotAdmitted, + )); + v.push(reject("session_missing_member", "a session with no uncounted member", edit(&|b| { b.remove("uncounted"); }), 2, Reason::MissingRequiredField)); + v.push(reject("session_unknown_member", "a session with a member the class does not define", edit(&|b| { b.insert("refinements_missing".into(), 0.into()); }), 2, Reason::UnknownMember)); + v.push(reject("session_media_uppercase", "media with an uppercase letter", edit(&|b| { b.insert("media".into(), "Video".into()); }), 2, Reason::FieldType)); + v.push(reject("session_framing_unknown", "a framing label this revision does not define", edit(&|b| { b.insert("framing".into(), "wai-measure/0".into()); }), 2, Reason::FieldType)); + v.push(reject( + "session_host_profile_unknown", + "a host profile outside its enumeration", + edit(&|b| { let mut h = nested(b, "host"); h.insert("profile".into(), "native".into()); b.insert("host".into(), Value::Object(h)); }), + 2, + Reason::FieldType, + )); + v.push(reject( + "session_decoder_path_unknown", + "a decoder entry on a path that is neither primary nor fallback", + edit(&|b| { let mut d = b["decoders"].as_array().expect("decoders").clone(); d[0]["path"] = "secondary".into(); b.insert("decoders".into(), Value::Array(d)); }), + 2, + Reason::FieldType, + )); + v.push(reject( + "session_decoder_entry_unknown_member", + "a decoder entry with a component member, which the entry does not define", + edit(&|b| { let mut d = b["decoders"].as_array().expect("decoders").clone(); d[0]["component"] = "c0".into(); b.insert("decoders".into(), Value::Array(d)); }), + 2, + Reason::UnknownMember, + )); + v.push(reject( + "session_count_as_string", + "units written as a string", + edit(&|b| { b.insert("units".into(), "5".into()); }), + 2, + Reason::FieldType, + )); + v.push(reject( + "session_host_read_before_decoders", + "a host profile outside its enumeration and a decoder entry with no leaves member: the host is read first", + edit(&|b| { + let mut h = nested(b, "host"); + h.insert("profile".into(), "native".into()); + b.insert("host".into(), Value::Object(h)); + let mut d = b["decoders"].as_array().expect("decoders").clone(); + d[0].as_object_mut().expect("entry").remove("leaves"); + b.insert("decoders".into(), Value::Array(d)); + }), + 2, + Reason::FieldType, + )); + v.push(reject( + "session_energy_member_missing", + "an energy object with no calibration reference member", + resigned(&sealed(metered()), &viewer(), |m| { + let b = body_of(m); + let mut e = nested(b, "energy"); + e.remove("energy_calibration_ref"); + b.insert("energy".into(), Value::Object(e)); + }), + 2, + Reason::MissingRequiredField, + )); + v.push(reject( + "session_energy_rewritten", + "an unmetered session given a figure after signing", + tamper(&sealed(model()).to_json(), "\"energy\":null", "\"energy\":{\"energy_calibration_ref\":null,\"energy_counter_filtering\":null,\"energy_provenance\":\"ModelBased\",\"energy_uncertainty\":null,\"joules_micro\":9}"), + 3, + Reason::SignatureVerifyFailed, + )); + + // ── step 6: the outputs ── + let r6 = |name: &'static str, about: &'static str, s: SessionClaim, reason: Reason| reject(name, about, sealed_or_bad(s), 6, reason); + let mut other = ps.clone(); + other[3].out_digest = digest(3, 7); + v.push(with( + r6("session_output_mismatch", "a presentation's output differs from the one the tree commits to", m(), Reason::SessionOutputMismatch), + "outputs", + outputs_value(&other), + )); + v.push(with( + r6("session_output_one_short", "a list one presentation short of leaf_count", m(), Reason::SessionOutputMismatch), + "outputs", + outputs_value(&ps[..8]), + )); + let mut twice = ps.clone(); + twice[8] = pres(0, 2, 2); + v.push(with( + r6("session_output_repeated", "a (unit, layers) presented twice", m(), Reason::SessionOutputMismatch), + "outputs", + outputs_value(&twice), + )); + let moved = { + let mut s = m(); + s.decoders[0].leaves = 3; + s.decoders[2].leaves = 5; + s + }; + v.push(with( + r6("session_output_leaves_moved", "a leaf moved from the base's entry to the refinement's: the sums still agree", moved, Reason::SessionOutputInconsistent), + "outputs", + outputs_value(&ps), + )); + let mut no_entry = ps.clone(); + no_entry[4].decoder = 3; + v.push(with( + r6("session_output_no_such_entry", "a presentation naming a fourth entry of three", over(m(), &no_entry), Reason::SessionOutputInconsistent), + "outputs", + outputs_value(&no_entry), + )); + let mut swapped = ps.clone(); + for p in &mut swapped { + p.decoder = match p.decoder { + 1 => 2, + 2 => 1, + d => d, + }; + } + let reordered = { + let mut s = over(m(), &swapped); + s.decoders.swap(1, 2); + s + }; + v.push(with( + r6( + "session_output_not_first_use_order", + "the refinement's entry listed before the fallback's, which is first named earlier taking the presentations by layers and unit", + reordered, + Reason::SessionOutputInconsistent, + ), + "outputs", + outputs_value(&swapped), + )); + v.push(with( + r6( + "session_output_paths_disagree", + "three units counted on the primary path and two on the fallback, where the presentations give four and one: the sum still agrees", + SessionClaim { primary_units: 3, fallback_units: 2, ..m() }, + Reason::SessionOutputInconsistent, + ), + "outputs", + outputs_value(&ps), + )); + v.push(with( + r6("session_output_units_disagree", "six units stated over five presented", SessionClaim { units: 6, primary_units: 5, ..m() }, Reason::SessionOutputInconsistent), + "outputs", + outputs_value(&ps), + )); + v.push(with( + r6( + "session_output_missed_not_presented", + "a missed presentation of unit 4 at two layers, which was never presented", + { let mut s = m(); s.missed_units[0].layers = 2; s }, + Reason::SessionOutputInconsistent, + ), + "outputs", + outputs_value(&ps), + )); + v.push(with( + with( + r6("session_output_irreproducible", "the base's first presentation decoded again gives another digest", m(), Reason::SessionOutputIrreproducible), + "outputs", + outputs_value(&ps), + ), + "redecoded", + redecoded_value(&[(0, digest(0, 9))]), + )); + v.push(with( + with( + claim( + "session_output_membership_only_accept", + "the fallback's presentation, through a decoder checked for membership only, decoded again with another digest: not checked", + sealed(model()).to_json(), + Ok(()), + ), + "outputs", + outputs_value(&ps), + ), + "redecoded", + redecoded_value(&[(4, digest(4, 9))]), + )); + + // ── step 6: the objects and the envelopes ── + let mut fewer = objects.clone(); + fewer[1].counted = Some(899); + v.push(with(r6("session_counted_mismatch", "an object received counted one byte short of the session's sum", m(), Reason::SessionCountedMismatch), "objects", objects_value(&fewer))); + let mut countable = objects.clone(); + countable[7].counted = Some(3_000); + v.push(with( + r6("session_uncounted_mismatch", "the fallback envelope given as countable: one object fewer is uncounted", m(), Reason::SessionCountedMismatch), + "objects", + objects_value(&countable), + )); + let mut presented = objects.clone(); + presented[4].presented = true; + v.push(with( + r6("session_discarded_mismatch", "a late layer object given as presented: fewer bytes discarded", m(), Reason::SessionCountedMismatch), + "objects", + objects_value(&presented), + )); + v.push(with( + r6("session_classical_decoded", "the rendition named is the one the session decoded", m(), Reason::SessionClassicalMismatch), + "envelopes", + envelopes_value(&[(entry_envelope(), 0)]), + )); + v.push(with( + r6("session_classical_length", "a classical length one byte more than the rendition table gives", SessionClaim { classical_declared: Some(701), ..m() }, Reason::SessionClassicalMismatch), + "envelopes", + envelopes_value(&[(entry_envelope(), 1)]), + )); + v.push(with( + r6("session_classical_no_envelope", "a classical length with no envelope that carries one", m(), Reason::SessionClassicalMismatch), + "envelopes", + json!([]), + )); + v.push(with( + r6("session_classical_index_past_table", "a rendition index past the envelope's table", m(), Reason::SessionClassicalMismatch), + "envelopes", + envelopes_value(&[(entry_envelope(), 2)]), + )); + // A `WAI1` envelope: magic, an empty manifest, an empty payload. + let wai1 = b"WAI1\x02\x00\x00\x00{}\x00\x00\x00\x00".to_vec(); + v.push(with( + r6("session_classical_not_wai2", "a WAI1 envelope given as the entry envelope", m(), Reason::SessionClassicalMismatch), + "envelopes", + envelopes_value(&[(wai1, 0)]), + )); + v.push(with( + claim("session_no_classical_accept", "a session with no classical rendition, checked against no envelope", sealed(SessionClaim { classical_declared: None, classical_source: None, ..m() }).to_json(), Ok(())), + "envelopes", + json!([]), + )); + + // ── step 6: the stage claims ── + let r_stage = |name: &'static str, about: &'static str, s: SessionClaim, claims: Vec, reason: Reason| { + let v = with(r6(name, about, s, reason), "outputs", outputs_value(&ps)); + with(v, "stage_claims", Value::Array(claims.into_iter().map(Value::String).collect())) + }; + let forged = flip_sig(&stage); + v.push(r_stage("session_stage_claim_invalid", "the stage claim the session names, with its signature broken", m(), vec![forged], Reason::ContextInvalid)); + let by_relay = seal(&relay(), "did:example:relay", SubjectType::Object, stage_base(), 0, stage.body.clone(), None); + v.push(r_stage( + "session_stage_claim_other_signer", + "a stage claim signed by another key, named by the session", + SessionClaim { stage_sets: vec![StageSetRef { first_unit: 0, claim: by_relay.link_hash() }], ..m() }, + vec![by_relay.to_json()], + Reason::ContextMismatch, + )); + let unnamed = model_stage(&[1, 2, 1], false); + let unnamed = seal(&viewer(), SINK_ID, SubjectType::Object, layer_hash("another base"), 0, unnamed.body.clone(), None); + v.push(r_stage("session_stage_claim_not_named", "a stage claim the session does not name", m(), vec![unnamed.to_json()], Reason::ContextMismatch)); + let too_far = model_stage(&[1, 1, 2], true); + v.push(r_stage( + "session_stage_disagrees", + "a stage claim with two units at stage 2 where the session presented one unit at three layers", + SessionClaim { stage_sets: vec![StageSetRef { first_unit: 0, claim: too_far.link_hash() }], ..m() }, + vec![too_far.to_json()], + Reason::SessionStageDisagrees, + )); + v.push(r_stage( + "session_stage_unit_not_presented", + "the stage set placed at unit 2, so its last unit is a unit the session never presented", + SessionClaim { stage_sets: vec![StageSetRef { first_unit: 2, claim: stage.link_hash() }], ..m() }, + vec![stage.to_json()], + Reason::SessionStageDisagrees, + )); + v.push(with( + reject( + "session_context_on_another_class", + "presentations given as the context of a stage claim", + stage.to_json(), + 6, + Reason::ContextMismatch, + ), + "outputs", + outputs_value(&ps), + )); + + // ── the figure profile (energy-measurement §6.1): a report on a session's figure ── + let e = sealed(metered()); + let report = |s: &ClaimReceipt| { + let view = crate::energy_figure::EnergyFigures::figure_view(s); + let class = crate::energy_class::EnergyProvenance::OnChipCounter { + uncertainty: crate::energy_class::Uncertainty::new(20_000, 1_000_000).expect("an uncertainty"), + filtering: crate::energy_class::CounterFiltering::Unknown, + }; + let joules = view.as_ref().and_then(|v| v.figure(None)).map_or(250_000, |f| f.joules_micro); + let body = ClaimBody::Measurement(MeasurementClaim { + figure: FigureHeader::new("moq-jwp:claim-link", None, None, joules, &class), + bracket: None, + build: BuildRecord { profile: BuildProfile::Release, toolchain: None, target: None }, + power_reader: Some("a counter reader".into()), + }); + seal(&viewer(), SINK_ID, SubjectType::Receipt, s.link_hash(), 1, body, None) + }; + v.push(with( + claim("session_figure_report_accept", "a measurement claim on a metered session's figure, by the session's key", report(&e).to_json(), Ok(())), + "figure", + claim_ctx(&e), + )); + let unmetered = sealed(model()); + v.push(with( + reject("session_figure_report_unmetered", "a measurement claim on an unmetered session, which carries no figure", report(&unmetered).to_json(), 6, Reason::ContextMismatch), + "figure", + claim_ctx(&unmetered), + )); + + for n in 1..=33 { + v.push(tree_vector(n)); + } + v +} + +/// A session that passes steps 1–4 is sealed as an honest sink would; one that does not +/// is sealed unchecked, for a step-6 vector whose step-4 rules still hold. +fn sealed_or_bad(s: SessionClaim) -> String { + match ClaimReceipt::seal(&viewer(), SINK_ID, SubjectType::Object, entry(), 0, T0, ClaimBody::ReconstructSession(s.clone()), None) { + Ok(r) => r.to_json(), + Err(e) => panic!("a step-6 vector's session must pass steps 1-4: {e}"), + } +} diff --git a/wai/wai-rs/src/claim_receipt/session.rs b/wai/wai-rs/src/claim_receipt/session.rs new file mode 100644 index 000000000..c1c9f5a7e --- /dev/null +++ b/wai/wai-rs/src/claim_receipt/session.rs @@ -0,0 +1,932 @@ +//! `reconstruct-session` (jwp-receipts §2.4.12): what a sink reconstructed in one session. +//! +//! A session claim records the decoders a sink used, on which host and against which +//! parameter sets; the path each unit took and why it switched; the presentations it made +//! after their deadline; a commitment to every output it presented (the output tree of +//! staged-measurement Appendix C, [`crate::output_tree`]); the bytes it counted and +//! received; the declared length of the classical rendition it did not need; the `stage` +//! claims it signed about the stage sets it observed; and, where metered, the decode's +//! energy with its acquisition class. +//! +//! It restates nothing a `stage` claim (§2.4.10) states. A `stage` claim is about one +//! stage set — its layer objects, the units at each stage on time, its delivered stage and +//! bytes — and the session names it by link hash ([`StageSetRef`]); a unit's highest stage +//! is read from the session's outputs. [`ClaimReceipt::check_session_stage_claims`] checks +//! the two against each other. +//! +//! The members are checked at §3.1 step 2 by [`SessionClaim::read`] in the table's order, +//! the class rules at step 4 by [`SessionClaim::rules`], and what a verifier holds — the +//! presentations, the objects, the entry envelopes, the `stage` claims — at step 6 by the +//! `check_session_*` methods of [`ClaimReceipt`]. + +use super::*; +use crate::output_tree::{self, Presentation}; + +/// The framing labels a session's counted members may carry (staged-measurement §3.3). +pub const SESSION_FRAMINGS: &[&str] = &["registered"]; +/// The host profiles of §2.4.12, until an extension of sink profiles registers the set. +pub const SESSION_HOST_PROFILES: &[&str] = &["native-ffi", "browser-baseline", "browser-gpu", "edge-wasi"]; +/// Where `classical_declared` comes from (§2.4.12). +pub const SESSION_CLASSICAL_SOURCES: &[&str] = &["wai2-table"]; +/// The anchors a `module:` decoder's grant can be confirmed under (§7.9). +pub const SESSION_MODULE_STATUSES: &[&str] = &["pinned", "fetched"]; +/// A decoder entry's `builtin:` prefix. +pub const BUILTIN_DECODER: &str = "builtin:"; +/// A decoder entry's `module:` prefix: a module's SHA-256 follows. +pub const MODULE_DECODER: &str = "module:sha256:"; + +/// The most switches a claim writes. Private, so the C header does not gain it. +const MAX_SWITCHES: usize = 1024; +/// The most missed presentations a claim writes. +const MAX_MISSED: usize = 256; +/// The largest `WAI2` rendition index, and the largest layer count a leaf holds. +const MAX_U16: u64 = 65_535; + +/// The members of a session body, in the order §3.1 step 2 reads them. +const SESSION_MEMBERS: &[&str] = &[ + "session_nonce", + "media", + "host", + "decoders", + "units", + "leaf_count", + "output_root", + "primary_units", + "fallback_units", + "switches", + "switches_total", + "deadline_us", + "missed", + "missed_units", + "stage_sets", + "framing", + "counted_primary", + "counted_fallback", + "counted_discarded", + "uncounted", + "transferred", + "receipt_bytes", + "classical_declared", + "classical_source", + "energy", +]; +const HOST_MEMBERS: &[&str] = &["profile", "target", "build", "threads"]; +const DECODER_MEMBERS: &[&str] = + &["capability", "rendition", "path", "decoder", "variant", "pin", "tier", "module_status", "leaves"]; +const SWITCH_MEMBERS: &[&str] = &["unit", "from", "to", "reason"]; +const MISSED_MEMBERS: &[&str] = &["unit", "layers", "late_us"]; +const STAGE_SET_MEMBERS: &[&str] = &["first_unit", "claim"]; +const SESSION_ENERGY_MEMBERS: &[&str] = + &["joules_micro", "energy_provenance", "energy_uncertainty", "energy_counter_filtering", "energy_calibration_ref"]; + +/// The path a decoder entry, a switch or an object is on. +#[derive(Clone, Copy, Debug, PartialEq, Eq, PartialOrd, Ord, Hash)] +pub enum SessionPath { + Primary, + Fallback, +} + +impl SessionPath { + pub fn label(self) -> &'static str { + match self { + SessionPath::Primary => "primary", + SessionPath::Fallback => "fallback", + } + } + pub fn from_label(s: &str) -> Option { + [SessionPath::Primary, SessionPath::Fallback].into_iter().find(|p| p.label() == s) + } +} + +/// The decoder host (§2.4.12). +#[derive(Clone, Debug, PartialEq, Eq)] +pub struct SessionHost { + /// One of [`SESSION_HOST_PROFILES`]. + pub profile: String, + /// The platform the host ran on, a term. + pub target: Option, + /// The build of its decoders, as a `measurement` claim writes a build (§2.4.8). + pub build: BuildRecord, + /// Its decode workers, as the largest power of two not above their number. + pub threads: u64, +} + +impl SessionHost { + /// `threads` written as §2.4.12 writes it: the largest power of two not above `n`, + /// and 1 for 0 workers. + pub fn rounded_threads(n: u64) -> u64 { + if n <= 1 { 1 } else { 1u64 << (63 - n.leading_zeros()) } + } +} + +/// One decoder entry (§2.4.12). +#[derive(Clone, Debug, PartialEq, Eq)] +pub struct DecoderEntry { + pub capability: String, + /// Its `WAI2` rendition index; `None` for a `WAI1` envelope. + pub rendition: Option, + pub path: SessionPath, + /// `builtin:@` or `module:sha256:`. + pub decoder: String, + pub variant: Option, + /// The SHA-256 of the pin the sink verified. + pub pin: Option<[u8; 32]>, + /// That pin's declared tier, as SPEC §3.1 reads it. + pub tier: Option, + /// For a `module:` decoder, the anchor its grant was confirmed under. + pub module_status: Option, + pub leaves: u64, +} + +impl DecoderEntry { + /// Everything but `leaves`: two entries with one key are one entry. + fn key(&self) -> (&str, Option, SessionPath, &str, Option<&str>, Option<[u8; 32]>, Option<&str>, Option<&str>) { + ( + &self.capability, + self.rendition, + self.path, + &self.decoder, + self.variant.as_deref(), + self.pin, + self.tier.as_deref(), + self.module_status.as_deref(), + ) + } +} + +/// A path switch. +#[derive(Clone, Debug, PartialEq, Eq)] +pub struct Switch { + pub unit: u64, + pub from: SessionPath, + pub to: SessionPath, + /// A delivery-telemetry §5 term. + pub reason: String, +} + +/// A presentation made after its unit's deadline. +#[derive(Clone, Copy, Debug, PartialEq, Eq)] +pub struct Missed { + pub unit: u64, + pub layers: u64, + pub late_us: u64, +} + +/// A stage set the sink signed a `stage` claim about: the title's unit that is the set's +/// unit 0, and that claim's link hash. +#[derive(Clone, Copy, Debug, PartialEq, Eq, PartialOrd, Ord)] +pub struct StageSetRef { + pub first_unit: u64, + pub claim: [u8; 32], +} + +/// A session's decode figure with its acquisition class, written as §2.4.5 writes one. +/// The scope (decode, one completion of the presentations committed to) and the figure +/// profile (`moq-jwp:claim-link`, no index) are fixed by the class. +#[derive(Clone, Debug, PartialEq, Eq)] +pub struct SessionEnergy { + pub joules_micro: u64, + pub energy_provenance: String, + pub energy_uncertainty: Option, + pub energy_counter_filtering: Option, + pub energy_calibration_ref: Option, +} + +impl SessionEnergy { + /// The figure `joules_micro` of class `class`, its evidence written where §2.4.5 + /// carries it. + pub fn new(joules_micro: u64, class: &EnergyProvenance) -> SessionEnergy { + let (energy_uncertainty, energy_counter_filtering, energy_calibration_ref) = evidence_of(class); + SessionEnergy { + joules_micro, + energy_provenance: class.label().to_owned(), + energy_uncertainty, + energy_counter_filtering, + energy_calibration_ref, + } + } + + /// The class, admitted as §2.4.5 rule 2 admits one. + pub fn acquisition_class(&self) -> Result { + admit_class( + self.joules_micro, + &self.energy_provenance, + self.energy_uncertainty, + self.energy_counter_filtering.as_deref(), + self.energy_calibration_ref.as_deref(), + ) + } +} + +/// `reconstruct-session` (§2.4.12). The subject is the session's entry object. +#[derive(Clone, Debug, PartialEq, Eq)] +pub struct SessionClaim { + pub session_nonce: [u8; 32], + pub media: String, + pub host: SessionHost, + /// In first-use order: taking the presentations by (layers, unit), each entry is + /// first named after the one before it. + pub decoders: Vec, + pub units: u64, + pub leaf_count: u64, + pub output_root: Option<[u8; 32]>, + pub primary_units: u64, + pub fallback_units: u64, + pub switches: Vec, + pub switches_total: u64, + pub deadline_us: Option, + pub missed: u64, + pub missed_units: Vec, + pub stage_sets: Vec, + pub framing: String, + pub counted_primary: u64, + pub counted_fallback: u64, + pub counted_discarded: u64, + pub uncounted: u64, + pub transferred: u64, + pub receipt_bytes: u64, + pub classical_declared: Option, + pub classical_source: Option, + pub energy: Option, +} + +/// One object a sink received, as the step-6 check against the objects reads it. +#[derive(Clone, Debug, PartialEq, Eq)] +pub struct ObjectSeen { + pub content_hash: [u8; 32], + pub path: SessionPath, + /// Its counted bytes (staged-measurement §3); `None` for an object not countable. + pub counted: Option, + /// Its bytes as received, whole or as byte ranges. + pub transferred: u64, + /// Whether any of its outputs was presented. + pub presented: bool, +} + +/// `media` as §2.4.12 writes it: 1 to 32 of `a`–`z`, `0`–`9` and `-`. +pub fn media_ok(s: &str) -> bool { + (1..=32).contains(&s.len()) && s.bytes().all(|b| b.is_ascii_lowercase() || b.is_ascii_digit() || b == b'-') +} + +/// A decoder identifier of §2.4.12's grammar: `builtin:@` or +/// `module:sha256:<64 lowercase hex>`. +pub fn decoder_ok(s: &str) -> bool { + if let Some(h) = s.strip_prefix(MODULE_DECODER) { + return h.len() == 64 && is_lower_hex(h); + } + let Some(rest) = s.strip_prefix(BUILTIN_DECODER) else { return false }; + let Some((krate, version)) = rest.split_once('@') else { return false }; + let crate_ok = (1..=64).contains(&krate.len()) + && krate.bytes().all(|b| b.is_ascii_lowercase() || b.is_ascii_digit() || b == b'_' || b == b'-'); + let version_ok = (1..=64).contains(&version.len()) + && version.as_bytes()[0].is_ascii_digit() + && version.bytes().all(|b| b.is_ascii_alphanumeric() || b == b'.' || b == b'+' || b == b'-'); + crate_ok && version_ok +} + +fn opt_str_value(s: &Option) -> Value { + s.clone().map(Value::String).unwrap_or(Value::Null) +} + +fn build_value(b: &BuildRecord) -> Value { + let mut m = Map::new(); + m.insert("profile".into(), b.profile.label().into()); + m.insert("toolchain".into(), opt_str_value(&b.toolchain)); + m.insert("target".into(), opt_str_value(&b.target)); + Value::Object(m) +} + +/// A build (§2.4.8): its members, then `profile` from its enumeration, `toolchain`, and +/// `target` a term. +fn get_build(v: &Value) -> Result { + let bm = v.as_object().ok_or(Reason::FieldType)?; + members(bm, BUILD_MEMBERS)?; + let profile = BuildProfile::from_label(&get_str(bm, "profile")?).ok_or(Reason::FieldType)?; + let toolchain = get_opt_str(bm, "toolchain")?; + let target = get_opt_str(bm, "target")?; + if let Some(t) = &target { + term_ok(t)?; + } + Ok(BuildRecord { profile, toolchain, target }) +} + +fn get_path(m: &Map, k: &str) -> Result { + SessionPath::from_label(&get_str(m, k)?).ok_or(Reason::FieldType) +} + +fn get_opt_term(m: &Map, k: &str) -> Result, Reason> { + let s = get_opt_str(m, k)?; + if let Some(t) = &s { + term_ok(t)?; + } + Ok(s) +} + +fn array<'a>(m: &'a Map, k: &str) -> Result<&'a Vec, Reason> { + m[k].as_array().ok_or(Reason::FieldType) +} + +fn object<'a>(v: &'a Value, required: &[&str]) -> Result<&'a Map, Reason> { + let o = v.as_object().ok_or(Reason::FieldType)?; + members(o, required)?; + Ok(o) +} + +impl SessionClaim { + pub(super) fn to_value(&self) -> Value { + let mut m = Map::new(); + m.insert("session_nonce".into(), hex(&self.session_nonce).into()); + m.insert("media".into(), self.media.clone().into()); + let mut h = Map::new(); + h.insert("profile".into(), self.host.profile.clone().into()); + h.insert("target".into(), opt_str_value(&self.host.target)); + h.insert("build".into(), build_value(&self.host.build)); + h.insert("threads".into(), self.host.threads.into()); + m.insert("host".into(), Value::Object(h)); + let decoders = self + .decoders + .iter() + .map(|d| { + let mut o = Map::new(); + o.insert("capability".into(), d.capability.clone().into()); + o.insert("rendition".into(), d.rendition.map_or(Value::Null, Value::from)); + o.insert("path".into(), d.path.label().into()); + o.insert("decoder".into(), d.decoder.clone().into()); + o.insert("variant".into(), opt_str_value(&d.variant)); + o.insert("pin".into(), opt_hex(&d.pin)); + o.insert("tier".into(), opt_str_value(&d.tier)); + o.insert("module_status".into(), opt_str_value(&d.module_status)); + o.insert("leaves".into(), d.leaves.into()); + Value::Object(o) + }) + .collect(); + m.insert("decoders".into(), Value::Array(decoders)); + m.insert("units".into(), self.units.into()); + m.insert("leaf_count".into(), self.leaf_count.into()); + m.insert("output_root".into(), opt_hex(&self.output_root)); + m.insert("primary_units".into(), self.primary_units.into()); + m.insert("fallback_units".into(), self.fallback_units.into()); + let switches = self + .switches + .iter() + .map(|s| { + let mut o = Map::new(); + o.insert("unit".into(), s.unit.into()); + o.insert("from".into(), s.from.label().into()); + o.insert("to".into(), s.to.label().into()); + o.insert("reason".into(), s.reason.clone().into()); + Value::Object(o) + }) + .collect(); + m.insert("switches".into(), Value::Array(switches)); + m.insert("switches_total".into(), self.switches_total.into()); + m.insert("deadline_us".into(), self.deadline_us.map_or(Value::Null, Value::from)); + m.insert("missed".into(), self.missed.into()); + let missed = self + .missed_units + .iter() + .map(|x| { + let mut o = Map::new(); + o.insert("unit".into(), x.unit.into()); + o.insert("layers".into(), x.layers.into()); + o.insert("late_us".into(), x.late_us.into()); + Value::Object(o) + }) + .collect(); + m.insert("missed_units".into(), Value::Array(missed)); + let sets = self + .stage_sets + .iter() + .map(|s| { + let mut o = Map::new(); + o.insert("first_unit".into(), s.first_unit.into()); + o.insert("claim".into(), hex(&s.claim).into()); + Value::Object(o) + }) + .collect(); + m.insert("stage_sets".into(), Value::Array(sets)); + m.insert("framing".into(), self.framing.clone().into()); + m.insert("counted_primary".into(), self.counted_primary.into()); + m.insert("counted_fallback".into(), self.counted_fallback.into()); + m.insert("counted_discarded".into(), self.counted_discarded.into()); + m.insert("uncounted".into(), self.uncounted.into()); + m.insert("transferred".into(), self.transferred.into()); + m.insert("receipt_bytes".into(), self.receipt_bytes.into()); + m.insert("classical_declared".into(), self.classical_declared.map_or(Value::Null, Value::from)); + m.insert("classical_source".into(), opt_str_value(&self.classical_source)); + m.insert( + "energy".into(), + self.energy.as_ref().map_or(Value::Null, |e| { + let mut o = Map::new(); + o.insert("joules_micro".into(), e.joules_micro.into()); + o.insert("energy_provenance".into(), e.energy_provenance.clone().into()); + o.insert("energy_uncertainty".into(), uncertainty_value(e.energy_uncertainty)); + o.insert("energy_counter_filtering".into(), opt_str_value(&e.energy_counter_filtering)); + o.insert("energy_calibration_ref".into(), opt_str_value(&e.energy_calibration_ref)); + Value::Object(o) + }), + ); + Value::Object(m) + } + + /// Step 2: the members — missing, then unknown — and then each member's type and + /// encoding together, in the table's order, a nested object's members checked where + /// the table reaches it and an array's entries in the array's order. Every failure + /// but a missing or unknown member is `field_type`. + pub(super) fn read(m: &Map) -> Result { + members(m, SESSION_MEMBERS)?; + let session_nonce = get_hash(m, "session_nonce")?; + let media = get_str(m, "media")?; + if !media_ok(&media) { + return Err(Reason::FieldType); + } + let h = object(&m["host"], HOST_MEMBERS)?; + let profile = get_str(h, "profile")?; + if !SESSION_HOST_PROFILES.contains(&profile.as_str()) { + return Err(Reason::FieldType); + } + let target = get_opt_term(h, "target")?; + let build = get_build(&h["build"])?; + let host = SessionHost { profile, target, build, threads: get_int(h, "threads")? }; + let decoders = array(m, "decoders")? + .iter() + .map(|v| { + let o = object(v, DECODER_MEMBERS)?; + let capability = get_str(o, "capability")?; + term_ok(&capability)?; + Ok(DecoderEntry { + capability, + rendition: get_opt_int(o, "rendition")?, + path: get_path(o, "path")?, + decoder: get_str(o, "decoder")?, + variant: get_opt_term(o, "variant")?, + pin: get_opt_hash(o, "pin")?, + tier: get_opt_str(o, "tier")?, + module_status: get_opt_str(o, "module_status")?, + leaves: get_int(o, "leaves")?, + }) + }) + .collect::, Reason>>()?; + let units = get_int(m, "units")?; + let leaf_count = get_int(m, "leaf_count")?; + let output_root = get_opt_hash(m, "output_root")?; + let primary_units = get_int(m, "primary_units")?; + let fallback_units = get_int(m, "fallback_units")?; + let switches = array(m, "switches")? + .iter() + .map(|v| { + let o = object(v, SWITCH_MEMBERS)?; + Ok(Switch { unit: get_int(o, "unit")?, from: get_path(o, "from")?, to: get_path(o, "to")?, reason: get_str(o, "reason")? }) + }) + .collect::, Reason>>()?; + let switches_total = get_int(m, "switches_total")?; + let deadline_us = get_opt_int(m, "deadline_us")?; + let missed = get_int(m, "missed")?; + let missed_units = array(m, "missed_units")? + .iter() + .map(|v| { + let o = object(v, MISSED_MEMBERS)?; + Ok(Missed { unit: get_int(o, "unit")?, layers: get_int(o, "layers")?, late_us: get_int(o, "late_us")? }) + }) + .collect::, Reason>>()?; + let stage_sets = array(m, "stage_sets")? + .iter() + .map(|v| { + let o = object(v, STAGE_SET_MEMBERS)?; + Ok(StageSetRef { first_unit: get_int(o, "first_unit")?, claim: get_hash(o, "claim")? }) + }) + .collect::, Reason>>()?; + let framing = get_str(m, "framing")?; + if !SESSION_FRAMINGS.contains(&framing.as_str()) { + return Err(Reason::FieldType); + } + let counted_primary = get_int(m, "counted_primary")?; + let counted_fallback = get_int(m, "counted_fallback")?; + let counted_discarded = get_int(m, "counted_discarded")?; + let uncounted = get_int(m, "uncounted")?; + let transferred = get_int(m, "transferred")?; + let receipt_bytes = get_int(m, "receipt_bytes")?; + let classical_declared = get_opt_int(m, "classical_declared")?; + let classical_source = get_opt_term(m, "classical_source")?; + let energy = match &m["energy"] { + Value::Null => None, + v => { + let o = object(v, SESSION_ENERGY_MEMBERS)?; + Some(SessionEnergy { + joules_micro: get_int(o, "joules_micro")?, + energy_provenance: get_str(o, "energy_provenance")?, + energy_uncertainty: get_uncertainty(o)?, + energy_counter_filtering: get_opt_str(o, "energy_counter_filtering")?, + energy_calibration_ref: get_opt_str(o, "energy_calibration_ref")?, + }) + } + }; + Ok(SessionClaim { + session_nonce, + media, + host, + decoders, + units, + leaf_count, + output_root, + primary_units, + fallback_units, + switches, + switches_total, + deadline_us, + missed, + missed_units, + stage_sets, + framing, + counted_primary, + counted_fallback, + counted_discarded, + uncounted, + transferred, + receipt_bytes, + classical_declared, + classical_source, + energy, + }) + } + + /// The encodings and enumerations step 2 checks, for a body built field by field. + pub(super) fn check_values(&self) -> Result<(), Reason> { + let ft = Reason::FieldType; + if !media_ok(&self.media) || !SESSION_HOST_PROFILES.contains(&self.host.profile.as_str()) { + return Err(ft); + } + for t in [&self.host.target, &self.host.build.target].into_iter().flatten() { + term_ok(t)?; + } + int_ok(self.host.threads)?; + for d in &self.decoders { + term_ok(&d.capability)?; + if let Some(v) = &d.variant { + term_ok(v)?; + } + if let Some(r) = d.rendition { + int_ok(r)?; + } + int_ok(d.leaves)?; + } + for n in [self.units, self.leaf_count, self.primary_units, self.fallback_units, self.switches_total, self.missed] { + int_ok(n)?; + } + for s in &self.switches { + int_ok(s.unit)?; + } + if let Some(d) = self.deadline_us { + int_ok(d)?; + } + for x in &self.missed_units { + for n in [x.unit, x.layers, x.late_us] { + int_ok(n)?; + } + } + for s in &self.stage_sets { + int_ok(s.first_unit)?; + } + if !SESSION_FRAMINGS.contains(&self.framing.as_str()) { + return Err(ft); + } + for n in [ + self.counted_primary, + self.counted_fallback, + self.counted_discarded, + self.uncounted, + self.transferred, + self.receipt_bytes, + ] { + int_ok(n)?; + } + if let Some(c) = self.classical_declared { + int_ok(c)?; + } + if let Some(s) = &self.classical_source { + term_ok(s)?; + } + if let Some(e) = &self.energy { + int_ok(e.joules_micro)?; + if let Some(u) = e.energy_uncertainty { + int_ok(u.relative_ppm)?; + int_ok(u.window_us)?; + } + } + Ok(()) + } + + /// The class rules (§2.4.12), checked at §3.1 step 4 in this order. + pub(super) fn rules(&self) -> Result<(), Reason> { + // Rule 1: every unit took one path, by its last presentation. + if u128::from(self.primary_units) + u128::from(self.fallback_units) != u128::from(self.units) { + return Err(Reason::SessionPathSum); + } + // Rule 2: the leaves are the presentations, and a unit is presented at least once. + let leaves: u128 = self.decoders.iter().map(|d| u128::from(d.leaves)).sum(); + if leaves != u128::from(self.leaf_count) || self.leaf_count < self.units || (self.units == 0) != (self.leaf_count == 0) { + return Err(Reason::SessionLeafSum); + } + // Rule 3: a root exactly when there is a leaf. + if self.output_root.is_some() != (self.leaf_count > 0) { + return Err(Reason::SessionRootPresence); + } + // Rule 4: the workers, rounded so they do not single out a machine. + if !self.host.threads.is_power_of_two() { + return Err(Reason::SessionHostMalformed); + } + // Rule 5: each entry as its table says, and no entry twice. + let malformed = Reason::SessionDecoderMalformed; + for d in &self.decoders { + let builtin = d.decoder.starts_with(BUILTIN_DECODER); + let tier_ok = match (&d.pin, &d.tier) { + (None, None) => true, + (Some(_), Some(t)) => crate::codecs::DeclaredTier::from_token(t).is_some(), + _ => false, + }; + let status_ok = match &d.module_status { + None => builtin, + Some(s) => !builtin && SESSION_MODULE_STATUSES.contains(&s.as_str()), + }; + if !decoder_ok(&d.decoder) || d.rendition.is_some_and(|r| r > MAX_U16) || !tier_ok || !status_ok || d.leaves == 0 { + return Err(malformed); + } + } + let mut keys: Vec<_> = self.decoders.iter().map(DecoderEntry::key).collect(); + keys.sort(); + if keys.windows(2).any(|w| w[0] == w[1]) { + return Err(malformed); + } + // Rule 6: no pin's tier above its capability's class. + for d in &self.decoders { + let Some(t) = d.tier.as_deref().and_then(crate::codecs::DeclaredTier::from_token) else { continue }; + if crate::codecs::class_tier(&d.capability).is_some_and(|class| t > class) { + return Err(Reason::SessionTierExceedsClass); + } + } + // Rule 7: the switches. + let reasons = crate::telemetry::observation::SWITCH_REASONS; + if self.switches.len() > MAX_SWITCHES + || self.switches.len() as u64 > self.switches_total + || self.switches.iter().any(|s| s.from == s.to || !reasons.contains(&s.reason.as_str())) + || self.switches.windows(2).any(|w| w[0].unit > w[1].unit) + { + return Err(Reason::SessionSwitchInvalid); + } + // Rule 8: the missed presentations. + let key = |x: &Missed| (x.unit, x.layers); + if self.missed > self.leaf_count + || (self.deadline_us.is_none() && self.missed != 0) + || self.missed_units.len() > MAX_MISSED + || self.missed_units.len() as u64 > self.missed + || self.missed_units.iter().any(|x| x.layers == 0 || x.layers > MAX_U16 || x.late_us == 0) + || self.missed_units.windows(2).any(|w| key(&w[0]) >= key(&w[1])) + { + return Err(Reason::SessionMissedInvalid); + } + // Rule 9: the stage sets, each once and in order. + if self.stage_sets.windows(2).any(|w| w[0] >= w[1]) { + return Err(Reason::SessionStageSetsInvalid); + } + // Rule 10: discarded bytes are bytes received. + if u128::from(self.counted_discarded) > u128::from(self.counted_primary) + u128::from(self.counted_fallback) { + return Err(Reason::SessionCountedInvalid); + } + // Rule 11: a classical length with its source. + match (&self.classical_declared, &self.classical_source) { + (None, None) => {} + (Some(_), Some(s)) if SESSION_CLASSICAL_SOURCES.contains(&s.as_str()) => {} + _ => return Err(Reason::SessionClassicalInvalid), + } + // Rule 12: a figure is never 0, and its class is admitted as §2.4.5 rule 2 admits one. + if let Some(e) = &self.energy { + if e.joules_micro == 0 { + return Err(Reason::EnergyZeroFigure); + } + e.acquisition_class()?; + } + Ok(()) + } + + /// The units presented, each with its presentation at its largest layer count: + /// `(unit, layers, decoder)`, by unit. + fn finals(ps: &[Presentation]) -> Vec<(u64, u16, u16)> { + let mut by_unit: BTreeMap = BTreeMap::new(); + for p in ps { + let e = by_unit.entry(p.unit).or_insert((p.layers, p.decoder)); + if p.layers > e.0 { + *e = (p.layers, p.decoder); + } + } + by_unit.into_iter().map(|(u, (l, d))| (u, l, d)).collect() + } +} + +/// Whether a re-decode of a presentation through this capability is checked against its +/// digest: its replicate class makes it byte-exact (`neural-int-exact`, +/// `standard-defined`). +pub fn redecode_checked(capability: &str) -> bool { + use crate::codecs::ReplicateClass; + matches!( + crate::codecs::capability_replicate_class(capability), + Some(ReplicateClass::NeuralIntegerExact | ReplicateClass::StandardDefined) + ) +} + +impl ClaimReceipt { + fn session(&self) -> Result<&SessionClaim, Rejection> { + match &self.body { + ClaimBody::ReconstructSession(s) => Ok(s), + _ => Err(Rejection::at(6, Reason::ContextMismatch)), + } + } + + /// Step 6 (§2.4.12), against the outputs: the presentations the claim commits to, in + /// any order, and `redecode`, which gives what the verifier found when it decoded the + /// presentation at an index of `ps` again, or `None` where it did not. It is asked + /// only about presentations whose decoder is byte-exact by its replicate class; every + /// other presentation is checked for membership only. In order: the tree + /// (`session_output_mismatch`), the members the presentations give + /// (`session_output_inconsistent`), then each re-decode + /// (`session_output_irreproducible`). + pub fn check_session_outputs(&self, ps: &[Presentation], redecode: &dyn Fn(usize) -> Option<[u8; 32]>) -> Result<(), Rejection> { + let s = self.session()?; + let at = |r| Rejection::at(6, r); + // 1. The tree. + let mismatch = at(Reason::SessionOutputMismatch); + if ps.len() as u64 != s.leaf_count { + return Err(mismatch); + } + let root = output_tree::root(ps).map_err(|_| mismatch)?; + if root != s.output_root { + return Err(mismatch); + } + // 2. What the presentations give. + let inconsistent = at(Reason::SessionOutputInconsistent); + if ps.iter().any(|p| usize::from(p.decoder) >= s.decoders.len() || p.layers == 0) { + return Err(inconsistent); + } + let finals = SessionClaim::finals(ps); + if finals.len() as u64 != s.units { + return Err(inconsistent); + } + let mut leaves = vec![0u64; s.decoders.len()]; + for p in ps { + leaves[usize::from(p.decoder)] += 1; + } + if s.decoders.iter().zip(&leaves).any(|(d, n)| d.leaves != *n) { + return Err(inconsistent); + } + // First-use order: by (layers, unit), the entries are first named in their order. + let mut by_use: Vec<&Presentation> = ps.iter().collect(); + by_use.sort_by_key(|p| (p.layers, p.unit)); + let mut next = 0usize; + for p in by_use { + let d = usize::from(p.decoder); + if d > next { + return Err(inconsistent); + } + if d == next { + next += 1; + } + } + let primary = finals.iter().filter(|(_, _, d)| s.decoders[usize::from(*d)].path == SessionPath::Primary).count() as u64; + if primary != s.primary_units || finals.len() as u64 - primary != s.fallback_units { + return Err(inconsistent); + } + let presented: std::collections::BTreeSet<(u64, u64)> = ps.iter().map(|p| (p.unit, u64::from(p.layers))).collect(); + if s.missed_units.iter().any(|x| !presented.contains(&(x.unit, x.layers))) { + return Err(inconsistent); + } + // 3. A byte-exact decode reproduces its output. + for (i, p) in ps.iter().enumerate() { + if !redecode_checked(&s.decoders[usize::from(p.decoder)].capability) { + continue; + } + if let Some(d) = redecode(i) + && d != p.out_digest + { + return Err(at(Reason::SessionOutputIrreproducible)); + } + } + Ok(()) + } + + /// Step 6 (§2.4.12), against the objects received: the counted sums per path and over + /// the objects not presented, the count of objects not countable, and the transferred + /// bytes (`session_counted_mismatch`). + pub fn check_session_objects(&self, objects: &[ObjectSeen]) -> Result<(), Rejection> { + let s = self.session()?; + let (mut primary, mut fallback, mut discarded, mut uncounted, mut transferred) = (0u128, 0u128, 0u128, 0u64, 0u128); + for o in objects { + transferred += u128::from(o.transferred); + match o.counted { + None => uncounted += 1, + Some(c) => { + match o.path { + SessionPath::Primary => primary += u128::from(c), + SessionPath::Fallback => fallback += u128::from(c), + } + if !o.presented { + discarded += u128::from(c); + } + } + } + } + let want = ( + u128::from(s.counted_primary), + u128::from(s.counted_fallback), + u128::from(s.counted_discarded), + s.uncounted, + u128::from(s.transferred), + ); + if (primary, fallback, discarded, uncounted, transferred) != want { + return Err(Rejection::at(6, Reason::SessionCountedMismatch)); + } + Ok(()) + } + + /// Step 6 (§2.4.12), against the entry envelopes that carry a classical rendition: + /// each envelope's bytes and that rendition's index. Each is a `WAI2` envelope whose + /// entry at the index is selectable, of a standard replicate class, and the capability + /// of no decoder entry; and their rendition-table lengths sum to `classical_declared`, + /// which is `null` exactly when there is none (`session_classical_mismatch`). + pub fn check_session_envelopes(&self, envelopes: &[(&[u8], u64)]) -> Result<(), Rejection> { + use crate::codecs::ReplicateClass; + let s = self.session()?; + let mismatch = Rejection::at(6, Reason::SessionClassicalMismatch); + let mut sum = 0u128; + for (bytes, index) in envelopes { + let w = crate::container::WaiMulti::from_bytes(bytes).map_err(|_| mismatch)?; + let i = usize::try_from(*index).map_err(|_| mismatch)?; + let (Some(meta), Some(payload)) = (w.manifest.renditions.get(i), w.renditions.get(i)) else { + return Err(mismatch); + }; + let standard = matches!( + crate::codecs::capability_replicate_class(&meta.capability), + Some(ReplicateClass::StandardDefined | ReplicateClass::StandardTolerance | ReplicateClass::StandardUnclassified) + ); + if !meta.is_selectable() || !standard || s.decoders.iter().any(|d| d.capability == meta.capability) { + return Err(mismatch); + } + sum += payload.len() as u128; + } + let got = (!envelopes.is_empty()).then_some(sum); + if got != s.classical_declared.map(u128::from) { + return Err(mismatch); + } + Ok(()) + } + + /// Step 6 (§2.4.12), against the `stage` claims the verifier holds of those + /// `stage_sets` names, as wire forms, and the presentations where it holds them too. + /// In order, for each claim: it passes §3.1 steps 1–4 (`context_invalid`); it is a + /// `stage` claim, signed by this claim's key, named by an entry of `stage_sets` + /// (`context_mismatch`); and, with the presentations, every unit of its set is + /// presented and, for each stage `s` from 1 up, the units of the set presented at more + /// than `s` layers are no fewer than it counts at `s` or above + /// (`session_stage_disagrees`). + pub fn check_session_stage_claims(&self, wires: &[&str], outputs: Option<&[Presentation]>) -> Result<(), Rejection> { + let s = self.session()?; + let finals = outputs.map(SessionClaim::finals); + for w in wires { + let c = verify_claim_json(w).map_err(|_| Rejection::at(6, Reason::ContextInvalid))?; + let link = c.link_hash(); + let ClaimBody::Stage(st) = &c.body else { + return Err(Rejection::at(6, Reason::ContextMismatch)); + }; + let named: Vec = s.stage_sets.iter().filter(|e| e.claim == link).map(|e| e.first_unit).collect(); + if c.signer_pubkey != self.signer_pubkey || named.is_empty() { + return Err(Rejection::at(6, Reason::ContextMismatch)); + } + let Some(finals) = &finals else { continue }; + let disagrees = Rejection::at(6, Reason::SessionStageDisagrees); + let n = st.unit_count().ok_or(disagrees)?; + for f in named { + let end = u128::from(f) + u128::from(n); + let in_set: Vec = + finals.iter().filter(|(u, _, _)| u128::from(*u) >= u128::from(f) && u128::from(*u) < end).map(|(_, l, _)| *l).collect(); + if in_set.len() as u128 != u128::from(n) { + return Err(disagrees); + } + for stage in 1..st.units_by_stage.len() { + let at_or_above: u128 = st.units_by_stage[stage..].iter().map(|x| u128::from(*x)).sum(); + let reached = in_set.iter().filter(|l| usize::from(**l) > stage).count() as u128; + if reached < at_or_above { + return Err(disagrees); + } + } + } + } + Ok(()) + } + + /// The authorities the energy figure of a `reconstruct-session` claim needs, as an + /// item of its own (§7.5): `reconstruct-session` and `energy/`. `None` for a + /// claim of another class, or a session whose `energy` is `null`. + pub fn figure_authorities(&self) -> Option> { + let ClaimBody::ReconstructSession(s) = &self.body else { return None }; + let e = s.energy.as_ref()?; + Some(vec![ClaimClass::ReconstructSession.label().to_owned(), format!("energy/{}", e.energy_provenance)]) + } +} diff --git a/wai/wai-rs/src/energy_figure.rs b/wai/wai-rs/src/energy_figure.rs index 439edb6a0..340123fe4 100644 --- a/wai/wai-rs/src/energy_figure.rs +++ b/wai/wai-rs/src/energy_figure.rs @@ -137,10 +137,18 @@ pub trait EnergyFigures { } /// An `energy` claim (`moq-jwp:claim-link`): its figure and class, identified by its -/// link hash. A claim of another class carries no figure. +/// link hash; and a `reconstruct-session` claim whose `energy` is not `null`: the +/// session's decode figure and its class (jwp-receipts §2.4.12). A claim of another class, +/// and a session that was not metered, carry no figure. impl EnergyFigures for ClaimReceipt { fn figure_view(&self) -> Option { self.verify().ok()?; + if let ClaimBody::ReconstructSession(s) = &self.body + && let Some(e) = &s.energy + { + let class = e.acquisition_class().ok()?; + return Some(FigureView::single("moq-jwp:claim-link", self.link_hash(), e.joules_micro, Some(class), self.signer_pubkey)); + } let ClaimBody::Energy(e) = &self.body else { return Some(FigureView { profile: "moq-jwp:claim-link".into(), diff --git a/wai/wai-rs/src/lib.rs b/wai/wai-rs/src/lib.rs index 2fae3496b..dc78e65c4 100644 --- a/wai/wai-rs/src/lib.rs +++ b/wai/wai-rs/src/lib.rs @@ -338,8 +338,9 @@ pub mod http_binding; // Staged-delivery measurement (extensions/staged-measurement.md): the output tree // (Appendix C), the counted bytes of an envelope (§3), and the evaluation of a staged -// title (§3–§6, §9) through the staged sink. -#[cfg(feature = "stage_measure")] +// title (§3–§6, §9) through the staged sink. The output tree is also what a session +// claim commits to (jwp-receipts §2.4.12), so `receipt_claims` builds it too. +#[cfg(any(feature = "stage_measure", feature = "receipt_claims"))] pub mod output_tree; #[cfg(feature = "stage_measure")] pub mod measure_framing; -- 2.54.0 (Apple Git-157) From 3b370522ff8bce50a38657536e311c88156c2358 Mon Sep 17 00:00:00 2001 From: Transaction Science Date: Tue, 6 Oct 2026 09:17:57 -0400 Subject: [PATCH 03/27] claim-conformance: claim_verify.py and differential.py read reconstruct-session MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit claim_verify.py checks a session as jwp-receipts §2.4.12 states it, written from the text: step 2 in the table's order, the twelve rules, an independent output tree (SHA-256, RFC 6962), first-use order, the counted sums, a WAI2 reading of the entry envelope with the registry's replicate classes, and the stage claims a session names. Every vector reports its declared outcome. differential.py builds sessions from random presentation lists, as an honest sink states them, gives them a defect or two, and requires both verifiers to agree; the README describes the vectors and the family. Co-Authored-By: Claude Opus 5.5 --- wai/claim-conformance/README.md | 74 ++++- wai/claim-conformance/claim_verify.py | 408 +++++++++++++++++++++++++- wai/claim-conformance/differential.py | 208 ++++++++++++- 3 files changed, 680 insertions(+), 10 deletions(-) diff --git a/wai/claim-conformance/README.md b/wai/claim-conformance/README.md index afca9eec6..25b65ae7a 100644 --- a/wai/claim-conformance/README.md +++ b/wai/claim-conformance/README.md @@ -1,10 +1,10 @@ # claim-conformance Conformance for [typed receipt classes and the soft binding class](../extensions/jwp-receipts.md) -(§2.4.3–§2.4.11, §2.6, §3.1–§3.2): `claim` receipts of class `energy`, +(§2.4.3–§2.4.12, §2.6, §3.1–§3.2): `claim` receipts of class `energy`, `lawful-basis`, `log-inclusion`, `soft-binding`, `binding-recovery`, `measurement`, -`operating-point`, `stage` and `delivery-gap`, and recovery through a soft binding under -the ancestor rule. +`operating-point`, `stage`, `delivery-gap` and `reconstruct-session`, and recovery +through a soft binding under the ancestor rule. Each vector declares **one outcome**: `accept` — with the claim's `link_hash`, which pins the canonical form, or for a recovery the ancestor it attests — or `reject` at a @@ -30,7 +30,14 @@ a vector that gives a recovery record one without the other is malformed), and corpus's matcher is byte equality), and `figure` (the receipt that carries the figure a `measurement` or `operating-point` claim names), and `gap_object` (the object receipt at a `delivery-gap` claim's coordinates, as the verifier holds it once verified, by -inclusion at least: `{track_alias, group_id, object_id, content_hash}`). An `object` context may also carry the +inclusion at least: `{track_alias, group_id, object_id, content_hash}`), and, for a +`reconstruct-session` claim, `outputs` (its presentations, `{unit, layers, decoder, +out_digest}`), `redecoded` (what a verifier that decoded presentations again found, +`{index, out_digest}`, the index into `outputs`), `objects` (each object received, +`{content_hash, path, counted, transferred, presented}`, `counted` `null` for an object +not countable), `envelopes` (each entry envelope carrying a classical rendition, its bytes +in hex and the rendition's index) and `stage_claims` (the wire forms of the `stage` +claims it names). An `object` context may also carry the class its leaf is labelled with (jwp-receipts §2.2), in energy-measurement §2.7's JSON members, read as that section reads them. A `figure` context is one of two forms: `claim`, an `energy` claim's wire form, viewed under the `moq-jwp:claim-link` profile; @@ -44,7 +51,8 @@ object in hand's `observed_hash` (or `null`). Both procedures report defect, in a recovery performed and in one recorded. Everything is synthetic. Keys are Ed25519 from fixed seeds (0x11 publisher, 0x22 meter, -0x33 operator, 0x44 sink, 0x55 resolver, 0x66 relay) and attest nothing; figures, uncertainties and +0x33 operator, 0x44 sink, 0x55 resolver, 0x66 relay) and attest nothing; outputs, +parameter sets and envelope payloads are synthetic bytes; figures, uncertainties and calibration references are invented; algorithm identifiers, registries, endpoints, logs and calibration certificates use reserved example domains; vocabulary terms are illustrative and no verifier here checks them against a vocabulary. @@ -165,6 +173,53 @@ The vectors cover: given to a claim that is not a gap (`context_mismatch`), for a reason outside its enumeration, a date that does not exist, or a subject that is a receipt. +## What a sink reconstructed: `reconstruct-session` + +A `reconstruct-session` claim (§2.4.12) is signed by a sink (key 0x44) about the entry +object of one session. Most vectors edit one model session: five units, four of them a +stage set over a pinned base refined to up to three layers, the fifth decoded on the +fallback path after a switch and presented late, two late layer objects never presented, +and an entry envelope — a `WAI2` built by `wai-rs`'s container module — whose classical +rendition the sink did not need. The vectors cover: + +- **Accepted:** the model unmetered and metered under `OnChipCounter`, each against every + context: its presentations, a re-decode of a byte-exact presentation that matches, the + objects received, the entry envelope and the `stage` claim it names; the model with no + context, and with its `stage` claim but no presentations; a session with no classical + rendition against no envelope; output trees of 1 to 33 leaves, half through a decoder + whose replicate class makes it byte-exact and half through one checked for membership + only, each re-decoded (the second with another digest, which is not checked); and a + `measurement` claim on a metered session's figure, under `moq-jwp:claim-link`, by the + session's key. +- **Rejected at step 4,** each rule with its reason: units, leaves and paths that do not + add up, a root without leaves or leaves without a root, three workers, a decoder + identifier of the wrong grammar, a tier without a pin or one SPEC §3.1 does not define, + module statuses that do not fit, a rendition past 65535, an entry twice or with no + leaves, a refinement entry pinned above its class's tier, switches between one path and + itself, for an unlisted reason, out of order or above their total, missed presentations + with no deadline, above the leaves, above `missed`, zero microseconds late or out of + order, a stage set listed twice, more bytes discarded than counted, a classical length + without its source or with an unregistered one, and a figure of zero or of every + acquisition-class defect. +- **Rejected at steps 1–3:** a subject that is a receipt; a missing and an unknown member; + `media`, `framing`, a host profile and a decoder path outside their grammar or + enumeration; a count written as a string; the host read before the decoders; an energy + object missing a member; and a figure written into an unmetered session after signing. +- **Rejected at step 6:** a presentation whose output differs, a list one short, a + (unit, layers) twice (`session_output_mismatch`); leaves moved between entries, a + presentation naming an entry that does not exist, entries out of first-use order, paths + and units that the presentations do not give, a missed presentation never made + (`session_output_inconsistent`); a byte-exact re-decode that differs + (`session_output_irreproducible`); objects whose counted, uncounted or discarded bytes + differ (`session_counted_mismatch`); the decoded rendition named as the classical one, + a length one byte off, no envelope, an index past the table, a `WAI1` envelope + (`session_classical_mismatch`); a `stage` claim whose signature is broken + (`context_invalid`), signed by another key, or not named (`context_mismatch`); a `stage` + claim counting more units at stage 2 than the session presented there, and a set + placed so that one of its units was never presented (`session_stage_disagrees`); a + session context given to a `stage` claim; and a `measurement` claim on an unmetered + session, which carries no figure. + ## Steps 1 and 2: types, and the order a body is read in §3.1 step 2 checks exactly the type a member table gives, member by member in the @@ -275,7 +330,14 @@ that do not themselves verify, bodies of every class with one defect from a fixe and with every pair of those at two different positions (a member, or a member of a nested object), where the order §3.1 step 2 reads a body in decides the reason, and, with `--random N`, a seeded random sample of dates, endpoints, figures, sums and class -combinations. Separately, each value that makes a whole file unreadable under +combinations, and of sessions: each built from a random presentation list as an honest +sink states it, then given a defect or two in the body or in a context (units, leaves and +paths off by one, switches and missed presentations past their caps, a `null` deadline +with misses, presences that disagree, decoder indices out of range, leaves moved between +entries, entries out of first-use order, outputs dropped or changed, re-decodes that match +and that do not, objects counted otherwise, every acquisition class), checked against its +presentations, objects, entry envelope and a `stage` claim that reaches its stages or +misses them. Separately, each value that makes a whole file unreadable under oer-receipts §4 — a number beyond the double range, `NaN`, an unpaired surrogate escape, a repeated member name, nesting past 64 levels — goes in a file of its own beside readable twins, and the two verifiers must both refuse the file or give it the same diff --git a/wai/claim-conformance/claim_verify.py b/wai/claim-conformance/claim_verify.py index 3df1eec59..732c636a9 100644 --- a/wai/claim-conformance/claim_verify.py +++ b/wai/claim-conformance/claim_verify.py @@ -1,6 +1,6 @@ #!/usr/bin/env python3 """Second verifier for claim-conformance/ — typed claim receipts, the soft binding class, -and recovery under the ancestor rule (extensions/jwp-receipts.md §2.4.3-§2.4.11, §2.6, +and recovery under the ancestor rule (extensions/jwp-receipts.md §2.4.3-§2.4.12, §2.6, §3.1-§3.2), and the arithmetic of a measurement report (energy-measurement.md §3.1, §6.2), computed with Python's integers. @@ -30,7 +30,7 @@ has no verdicts, and `verdicts` exits 1 with no output. No integer in a claim is from more than twenty digits, so no verdict depends on an interpreter's limit on integer digits. """ -import json, os, re, sys, unicodedata +import hashlib, json, os, re, struct, sys, unicodedata from decimal import localcontext HERE = os.path.dirname(os.path.abspath(__file__)) @@ -218,7 +218,7 @@ ENVELOPE = ["kind", "class", "subject_type", "subject", "seq", "issued_at", "bod ADMITS = {"energy": {"object"}, "lawful-basis": {"object", "receipt"}, "log-inclusion": {"receipt"}, "soft-binding": {"object"}, "binding-recovery": {"object"}, "measurement": {"object", "receipt"}, "operating-point": {"object", "receipt"}, - "stage": {"object"}, "delivery-gap": {"object"}} + "stage": {"object"}, "delivery-gap": {"object"}, "reconstruct-session": {"object"}} FIGURE = ["figure_profile", "figure_index", "group", "joules_micro", "energy_provenance", "energy_uncertainty", "energy_counter_filtering", "energy_calibration_ref"] BODY = { @@ -232,6 +232,11 @@ BODY = { "stage": ["vocabulary", "op_requested", "op_committed", "op_delivered", "presented", "units_by_stage", "tier", "stage_hash", "objects", "conflicts", "deadline_misses", "bytes_envelopes"], "delivery-gap": ["track_alias", "group_id", "object_id", "reason", "observed_at"], + "reconstruct-session": ["session_nonce", "media", "host", "decoders", "units", "leaf_count", "output_root", + "primary_units", "fallback_units", "switches", "switches_total", "deadline_us", "missed", + "missed_units", "stage_sets", "framing", "counted_primary", "counted_fallback", + "counted_discarded", "uncounted", "transferred", "receipt_bytes", "classical_declared", + "classical_source", "energy"], } # §2.4.10: one reported layer object, its units, the enumerations this extension defines # for it, the tiers of staged-delivery §5, and the reasons of staged-delivery §4.2. @@ -280,6 +285,31 @@ WHITE_SPACE = ("\t\n\x0b\x0c\r \x85\xa0\u1680\u2000\u2001\u2002\u2003\u2004\u200 COVERAGE = {"Whole", "Partial"} GRADES = OER.GRADES +# §2.4.12: a session's host, decoder entries, switches, missed presentations, stage sets +# and energy, the enumerations it defines, and delivery-telemetry.md §5's switch reasons. +SESSION_HOST = ["profile", "target", "build", "threads"] +SESSION_DECODER = ["capability", "rendition", "path", "decoder", "variant", "pin", "tier", "module_status", "leaves"] +SESSION_SWITCH = ["unit", "from", "to", "reason"] +SESSION_MISSED = ["unit", "layers", "late_us"] +SESSION_STAGE_SET = ["first_unit", "claim"] +SESSION_ENERGY = ["joules_micro", "energy_provenance", "energy_uncertainty", "energy_counter_filtering", + "energy_calibration_ref"] +HOST_PROFILES = ("native-ffi", "browser-baseline", "browser-gpu", "edge-wasi") +PATHS = ("primary", "fallback") +FRAMINGS = ("registered",) +CLASSICAL_SOURCES = ("wai2-table",) +MODULE_STATUSES = ("pinned", "fetched") +TIER_RANK = {"none": 0, "entropy-consistency": 1, "decode-equivalence": 2} # SPEC §3.1 +SWITCH_REASONS = ("pin-malformed", "form-not-registered", "form-unreadable", "form-required", "prior-revoked", + "prior-not-authorised", "prior-not-held", "digest-superseded", "set-malformed", "part-mismatch", + "set-incomplete", "missing-capability", "module-unverified", "module-revoked", "trap", + "fuel-exhausted", "memory-exhausted", "deadline-threshold", "unit-hash-mismatch", + "budget-exhausted", "recovered") +# The capability registry (../registry/capabilities.json): each capability's kind, status +# and replicate class, for a session's tiers, re-decodes and classical rendition. +with open(os.path.join(HERE, "..", "registry", "capabilities.json"), encoding="utf-8") as _f: + REGISTRY = {c["capability"]: c for c in json.load(_f)["capabilities"]} + class Reject(Exception): def __init__(self, step, reason): @@ -398,6 +428,9 @@ def check_body(cls, b): raise Reject(2, "field_type") return members(b, BODY[cls], 2) + if cls == "reconstruct-session": + check_session_body(b) + return if cls == "stage": # In the member table's order: `vocabulary` before the objects, whose members are # checked where the table reaches them. @@ -498,6 +531,353 @@ def check_body(cls, b): need(is_token(b["alg"]) and is_uri(b["resolution_endpoint"]), 2) +def nested(v, required): + """A nested object a table fixes: an object, then its members, missing then unknown.""" + need(isinstance(v, dict), 2) + members(v, required, 2) + return v + + +def check_session_body(b): + """§2.4.12, at §3.1 step 2: each member's type and encoding in the table's order, the + members of the host, of each decoder entry, switch, missed presentation and stage set, + and of `energy`, where the table reaches them.""" + need(is_hex(b["session_nonce"], 32), 2) + need(isinstance(b["media"], str) and re.fullmatch(r"[a-z0-9-]{1,32}", b["media"]) is not None, 2) + h = nested(b["host"], SESSION_HOST) + need(h["profile"] in HOST_PROFILES, 2) + need(h["target"] is None or is_token(h["target"]), 2) + bd = nested(h["build"], BUILD) + need(bd["profile"] in ("release", "debug"), 2) + need(bd["toolchain"] is None or isinstance(bd["toolchain"], str), 2) + need(bd["target"] is None or is_token(bd["target"]), 2) + need(is_int(h["threads"]), 2) + need(isinstance(b["decoders"], list), 2) + for d in b["decoders"]: + nested(d, SESSION_DECODER) + need(is_token(d["capability"]), 2) + need(d["rendition"] is None or is_int(d["rendition"]), 2) + need(d["path"] in PATHS, 2) + need(isinstance(d["decoder"], str), 2) + need(d["variant"] is None or is_token(d["variant"]), 2) + need(d["pin"] is None or is_hex(d["pin"], 32), 2) + need(d["tier"] is None or isinstance(d["tier"], str), 2) + need(d["module_status"] is None or isinstance(d["module_status"], str), 2) + need(is_int(d["leaves"]), 2) + need(all(is_int(b[k]) for k in ("units", "leaf_count")), 2) + need(b["output_root"] is None or is_hex(b["output_root"], 32), 2) + need(all(is_int(b[k]) for k in ("primary_units", "fallback_units")), 2) + need(isinstance(b["switches"], list), 2) + for w in b["switches"]: + nested(w, SESSION_SWITCH) + need(is_int(w["unit"]) and w["from"] in PATHS and w["to"] in PATHS and isinstance(w["reason"], str), 2) + need(is_int(b["switches_total"]), 2) + need(b["deadline_us"] is None or is_int(b["deadline_us"]), 2) + need(is_int(b["missed"]), 2) + need(isinstance(b["missed_units"], list), 2) + for x in b["missed_units"]: + nested(x, SESSION_MISSED) + need(all(is_int(x[k]) for k in SESSION_MISSED), 2) + need(isinstance(b["stage_sets"], list), 2) + for x in b["stage_sets"]: + nested(x, SESSION_STAGE_SET) + need(is_int(x["first_unit"]) and is_hex(x["claim"], 32), 2) + need(b["framing"] in FRAMINGS, 2) + need(all(is_int(b[k]) for k in ("counted_primary", "counted_fallback", "counted_discarded", "uncounted", + "transferred", "receipt_bytes")), 2) + need(b["classical_declared"] is None or is_int(b["classical_declared"]), 2) + need(b["classical_source"] is None or is_token(b["classical_source"]), 2) + e = b["energy"] + if e is not None: + nested(e, SESSION_ENERGY) + need(is_int(e["joules_micro"]), 2) + need(isinstance(e["energy_provenance"], str), 2) + u = e["energy_uncertainty"] + if u is not None: + nested(u, UNCERTAINTY) + need(is_int(u["relative_ppm"]) and is_int(u["window_us"]), 2) + need(e["energy_counter_filtering"] is None or isinstance(e["energy_counter_filtering"], str), 2) + need(e["energy_calibration_ref"] is None or isinstance(e["energy_calibration_ref"], str), 2) + + +def decoder_ok(s): + """A decoder identifier of §2.4.12: builtin:@ or module:sha256:.""" + if s.startswith("module:sha256:"): + return re.fullmatch(r"[0-9a-f]{64}", s[len("module:sha256:"):]) is not None + if not s.startswith("builtin:") or "@" not in s: + return False + krate, version = s[len("builtin:"):].split("@", 1) + return (re.fullmatch(r"[a-z0-9_-]{1,64}", krate) is not None + and re.fullmatch(r"[0-9][0-9A-Za-z.+-]{0,63}", version) is not None) + + +def replicate(cap): + """A capability's replicate class as the registry states it, None for one it does not + register or classify.""" + c = REGISTRY.get(cap) + return c["replicate"] if c else None + + +def class_tier(cap): + """SPEC §3.1 *Tier*: the tier a capability's class gives — decode-equivalence for an + integer-exact neural decode, entropy-consistency for an entropy-exact one, none for + every other class — or None for a capability with no class.""" + r = replicate(cap) + if r is None: + return None + return {"neural-int-exact": "decode-equivalence", "neural-entropy-exact": "entropy-consistency"}.get(r, "none") + + +def selectable(entry): + """SPEC §7.1: not a companion or a refinement, and a capability a sink may dispatch — + one the registry does not list, or a payload that is not a candidate.""" + if entry.get("role") in ("companion", "refinement"): + return False + c = REGISTRY.get(entry["capability"]) + return c is None or (c["kind"] == "payload" and c["status"] != "candidate") + + +def session_rules(b): + """§2.4.12's rules, at §3.1 step 4, in order.""" + ds = b["decoders"] + need(b["primary_units"] + b["fallback_units"] == b["units"], 4, "session_path_sum") + need(sum(d["leaves"] for d in ds) == b["leaf_count"] and b["leaf_count"] >= b["units"] + and (b["units"] == 0) == (b["leaf_count"] == 0), 4, "session_leaf_sum") + need((b["output_root"] is not None) == (b["leaf_count"] > 0), 4, "session_root_presence") + t = b["host"]["threads"] + need(t > 0 and t & (t - 1) == 0, 4, "session_host_malformed") + for d in ds: + builtin = d["decoder"].startswith("builtin:") + tier_ok = (d["pin"] is None and d["tier"] is None) or ( + d["pin"] is not None and d["tier"] is not None and d["tier"] in TIER_RANK) + status_ok = builtin if d["module_status"] is None else (not builtin and d["module_status"] in MODULE_STATUSES) + need(decoder_ok(d["decoder"]) and (d["rendition"] is None or d["rendition"] <= 65535) and tier_ok + and status_ok and d["leaves"] != 0, 4, "session_decoder_malformed") + keys = [tuple(d[k] for k in SESSION_DECODER if k != "leaves") for d in ds] + need(len(set(keys)) == len(keys), 4, "session_decoder_malformed") + for d in ds: + ct = class_tier(d["capability"]) + need(d["tier"] is None or ct is None or TIER_RANK[d["tier"]] <= TIER_RANK[ct], 4, "session_tier_exceeds_class") + sw = b["switches"] + need(len(sw) <= 1024 and len(sw) <= b["switches_total"] + and all(w["from"] != w["to"] and w["reason"] in SWITCH_REASONS for w in sw) + and all(sw[i]["unit"] <= sw[i + 1]["unit"] for i in range(len(sw) - 1)), 4, "session_switch_invalid") + mu = b["missed_units"] + need(b["missed"] <= b["leaf_count"] and (b["deadline_us"] is not None or b["missed"] == 0) + and len(mu) <= 256 and len(mu) <= b["missed"] + and all(1 <= x["layers"] <= 65535 and x["late_us"] >= 1 for x in mu) + and all((mu[i]["unit"], mu[i]["layers"]) < (mu[i + 1]["unit"], mu[i + 1]["layers"]) for i in range(len(mu) - 1)), + 4, "session_missed_invalid") + ss = b["stage_sets"] + need(all((ss[i]["first_unit"], ss[i]["claim"]) < (ss[i + 1]["first_unit"], ss[i + 1]["claim"]) + for i in range(len(ss) - 1)), 4, "session_stage_sets_invalid") + need(b["counted_discarded"] <= b["counted_primary"] + b["counted_fallback"], 4, "session_counted_invalid") + cd, cs = b["classical_declared"], b["classical_source"] + need((cd is None and cs is None) or (cd is not None and cs in CLASSICAL_SOURCES), 4, "session_classical_invalid") + e = b["energy"] + if e is not None: + need(e["joules_micro"] != 0, 4, "energy_zero_figure") + acquisition(e) + + +# ------------------------------------------- §2.4.12 step 6: what a session is checked against + +def out_leaf(p): + """staged-measurement Appendix C: a presentation's leaf.""" + return hashlib.sha256(b"wai:out-leaf\x01" + p["unit"].to_bytes(8, "big") + p["layers"].to_bytes(2, "big") + + p["decoder"].to_bytes(2, "big") + bytes.fromhex(p["out_digest"])).digest() + + +def out_mth(leaves): + """RFC 6962's Merkle tree hash, under the output tree's node domain.""" + if len(leaves) == 1: + return leaves[0] + k = 1 + while k * 2 < len(leaves): + k *= 2 + return hashlib.sha256(b"wai:out-node\x01" + out_mth(leaves[:k]) + out_mth(leaves[k:])).digest() + + +def ctx_int(v, bits=64): + if not (isinstance(v, int) and not isinstance(v, bool) and 0 <= v < 2 ** bits): + raise ValueError("bad integer in a session context") + return v + + +def ctx_hash(v): + if not is_hex(v, 32): + raise ValueError("bad hash in a session context") + return v + + +def presentations(v): + if not isinstance(v, list): + raise ValueError("outputs must be an array") + return [{"unit": ctx_int(p["unit"]), "layers": ctx_int(p["layers"], 16), "decoder": ctx_int(p["decoder"], 16), + "out_digest": ctx_hash(p["out_digest"])} for p in v] + + +def finals(ps): + """Each unit presented, with its presentation at its largest layer count.""" + out = {} + for p in ps: + if p["unit"] not in out or p["layers"] > out[p["unit"]]["layers"]: + out[p["unit"]] = p + return out + + +def check_session_outputs(c, ps, redecoded): + b = c["body"] + need(c["class"] == "reconstruct-session", 6, "context_mismatch") + keys = [(p["unit"], p["layers"]) for p in ps] + need(len(ps) == b["leaf_count"] and len(set(keys)) == len(keys), 6, "session_output_mismatch") + if ps: + ordered = sorted(ps, key=lambda p: (p["unit"], p["layers"])) + need(out_mth([out_leaf(p) for p in ordered]).hex() == b["output_root"], 6, "session_output_mismatch") + else: + need(b["output_root"] is None, 6, "session_output_mismatch") + ds = b["decoders"] + bad = "session_output_inconsistent" + need(all(p["decoder"] < len(ds) and p["layers"] >= 1 for p in ps), 6, bad) + fin = finals(ps) + need(len(fin) == b["units"], 6, bad) + need(all(d["leaves"] == sum(1 for p in ps if p["decoder"] == i) for i, d in enumerate(ds)), 6, bad) + nxt = 0 + for p in sorted(ps, key=lambda p: (p["layers"], p["unit"])): + need(p["decoder"] <= nxt, 6, bad) + if p["decoder"] == nxt: + nxt += 1 + primary = sum(1 for p in fin.values() if ds[p["decoder"]]["path"] == "primary") + need(primary == b["primary_units"] and len(fin) - primary == b["fallback_units"], 6, bad) + need(all((x["unit"], x["layers"]) in set(keys) for x in b["missed_units"]), 6, bad) + for i, p in enumerate(ps): + if replicate(ds[p["decoder"]]["capability"]) in ("neural-int-exact", "standard-defined") and i in redecoded: + need(redecoded[i] == p["out_digest"], 6, "session_output_irreproducible") + + +def objects_seen(v): + if not isinstance(v, list): + raise ValueError("objects must be an array") + out = [] + for o in v: + ctx_hash(o["content_hash"]) + if o["path"] not in PATHS or not isinstance(o["presented"], bool): + raise ValueError("bad object") + out.append({"path": o["path"], "counted": None if o["counted"] is None else ctx_int(o["counted"]), + "transferred": ctx_int(o["transferred"]), "presented": o["presented"]}) + return out + + +def check_session_objects(c, objs): + b = c["body"] + need(c["class"] == "reconstruct-session", 6, "context_mismatch") + sums = {"primary": 0, "fallback": 0} + discarded = uncounted = transferred = 0 + for o in objs: + n = o["counted"] + transferred += o["transferred"] + if n is None: + uncounted += 1 + else: + sums[o["path"]] += n + if not o["presented"]: + discarded += n + need((sums["primary"], sums["fallback"], discarded, uncounted, transferred) + == (b["counted_primary"], b["counted_fallback"], b["counted_discarded"], b["uncounted"], b["transferred"]), + 6, "session_counted_mismatch") + + +def wai2_renditions(data): + """SPEC §7.1: a WAI2 envelope's manifest entries and each payload's length, or None for + bytes that are not one.""" + if len(data) < 8 or data[:4] != b"WAI2": + return None + ml = struct.unpack_from(" len(data): + return None + try: + m = parse_strict(data[8:8 + ml].decode("utf-8")) + except (ValueError, UnicodeDecodeError): + return None + if not (isinstance(m, dict) and all(isinstance(m.get(k), str) for k in ("wai", "media", "intent")) + and isinstance(m.get("renditions"), list)): + return None + rs = m["renditions"] + for r in rs: + if not (isinstance(r, dict) and isinstance(r.get("capability"), str) and isinstance(r.get("kind"), str) + and (r.get("role") is None or isinstance(r.get("role"), str))): + return None + o = 8 + ml + if o + 2 > len(data) or struct.unpack_from(" len(data): + return None + lengths, expected = [], 0 + for i in range(len(rs)): + off, ln = struct.unpack_from(" len(data): + return None + return list(zip(rs, lengths)) + + +def envelopes(v): + if not isinstance(v, list): + raise ValueError("envelopes must be an array") + out = [] + for e in v: + if not is_hex(e["envelope"]): + raise ValueError("bad envelope") + out.append((bytes.fromhex(e["envelope"]), ctx_int(e["rendition"]))) + return out + + +def check_session_envelopes(c, envs): + b = c["body"] + need(c["class"] == "reconstruct-session", 6, "context_mismatch") + bad = "session_classical_mismatch" + total = 0 + decoded = {d["capability"] for d in b["decoders"]} + for data, i in envs: + rs = wai2_renditions(data) + need(rs is not None and i < len(rs), 6, bad) + entry, ln = rs[i] + need(selectable(entry) + and replicate(entry["capability"]) in ("standard-defined", "standard-tolerance", "standard-unclassified") + and entry["capability"] not in decoded, 6, bad) + total += ln + need((total if envs else None) == b["classical_declared"], 6, bad) + + +def check_session_stage_claims(c, wires, ps): + if not isinstance(wires, list) or not all(isinstance(w, str) for w in wires): + raise ValueError("stage_claims must be an array of wire forms") + b = c["body"] + need(c["class"] == "reconstruct-session", 6, "context_mismatch") + fin = finals(ps) if ps is not None else None + for w in wires: + try: + s = verify_claim(w) + except Reject: + raise Reject(6, "context_invalid") + link = link_hash(s) + named = [x["first_unit"] for x in b["stage_sets"] if x["claim"] == link] + need(s["class"] == "stage" and s["signer_pubkey"] == c["signer_pubkey"] and named, 6, "context_mismatch") + if fin is None: + continue + ubs = s["body"]["units_by_stage"] + n = sum(ubs) + for f in named: + in_set = [p["layers"] for u, p in fin.items() if f <= u < f + n] + need(len(in_set) == n, 6, "session_stage_disagrees") + for st in range(1, len(ubs)): + need(sum(1 for l in in_set if l > st) >= sum(ubs[st:]), 6, "session_stage_disagrees") + + def check_figure_header(b): """§2.4.8's header at step 2, in its table's order: `figure_profile` a term, as it is read; the index an integer or null; the group a hash or null; then the figure and the @@ -655,6 +1035,8 @@ def class_rules(c): need(dlv is not None or b["prediction"] is not None, 4, "operating_point_empty") elif cls == "stage": stage_rules(b) + elif cls == "reconstruct-session": + session_rules(b) elif cls == "log-inclusion": need(b["log_receipt"] != "", 4, "log_inclusion_no_evidence") elif cls in ("soft-binding", "binding-recovery"): @@ -917,6 +1299,23 @@ def check_context(c, ctx): need(c["class"] == "delivery-gap", 6, "context_mismatch") need(all(g[k] == b[k] for k in ("track_alias", "group_id", "object_id")), 6, "context_mismatch") need(g["content_hash"] == c["subject"], 6, "gap_subject_mismatch") + # §2.4.12: a session against its outputs, the objects it received, its entry envelopes + # and the stage claims it names, in that order. + ps = presentations(ctx["outputs"]) if "outputs" in ctx else None + if ps is not None: + red = ctx.get("redecoded", []) + if not isinstance(red, list): + raise ValueError("redecoded must be an array") + found = {} + for x in red: + found[ctx_int(x["index"])] = ctx_hash(x["out_digest"]) + check_session_outputs(c, ps, found) + if "objects" in ctx: + check_session_objects(c, objects_seen(ctx["objects"])) + if "envelopes" in ctx: + check_session_envelopes(c, envelopes(ctx["envelopes"])) + if "stage_claims" in ctx: + check_session_stage_claims(c, ctx["stage_claims"], ps) if "declaration" in ctx: # In §3.1 step 6's order: the claim must be one that names a declaration; the # declaration must itself pass steps 1-4 (context_invalid) — its signer_pubkey is @@ -993,6 +1392,9 @@ def figure_view(f): figs = {} if e["class"] == "energy": figs[None] = (e["body"]["joules_micro"], class_of_body(e["body"])) + elif e["class"] == "reconstruct-session" and e["body"]["energy"] is not None: + # energy-measurement §6.1: a session's figure is its `energy`, with its class. + figs[None] = (e["body"]["energy"]["joules_micro"], class_of_json(e["body"]["energy"])) return ("moq-jwp:claim-link", link_hash(e), None, figs, e["signer_pubkey"]) v = f["view"] figs = {x["index"]: (x["joules_micro"], class_of_json(x)) for x in v["figures"]} diff --git a/wai/claim-conformance/differential.py b/wai/claim-conformance/differential.py index 98c859321..28021c7ef 100644 --- a/wai/claim-conformance/differential.py +++ b/wai/claim-conformance/differential.py @@ -19,7 +19,13 @@ presence combination of their points and prediction; reports checked against fig that agree and disagree in each member; energy claims against labelled objects; stage claims around every rule of §2.4.10 — points, the stage hash, the units, the objects' order, statuses, evidence, reasons and bytes, and the delivered stage they give — and -delivery-gap claims against object receipts at their coordinates and elsewhere — +delivery-gap claims against object receipts at their coordinates and elsewhere; and +reconstruct-session claims built from random presentation lists, around every rule of +§2.4.12 — units, leaves and paths off by one, switches and missed presentations at and past +their caps, a null deadline with misses, presences that disagree, decoder indices out of +range, leaves moved between entries, entries out of first-use order, every acquisition +class — with their outputs, re-decodes, objects, entry envelopes and stage claims that +reach their stages or miss them — writes them in the corpus's format with no declared outcome, runs both verifiers' `verdicts` mode, and reports every input on which they differ. @@ -528,6 +534,205 @@ def stages(ins, rng, n): {"gap_object": {"track_alias": 8, "group_id": 3, "object_id": 0, "content_hash": g["subject"]}}) +SESSION_CAPS = [("wai.video.int_hyper", "primary", True), ("wai.video.av1", "fallback", False), + ("wai.video.int_refine", "primary", False), ("wai.image.png", "fallback", False), + ("wai.neural.int_hyper", "primary", True), ("wai.image.int_refine", "primary", False)] +SESSION_ENERGY = [ + None, + {"joules_micro": 250000, "energy_provenance": "OnChipCounter", + "energy_uncertainty": {"relative_ppm": 20000, "window_us": 1000000}, "energy_counter_filtering": "Unknown", + "energy_calibration_ref": None}, + {"joules_micro": 1, "energy_provenance": "OnChipCounter", "energy_uncertainty": {"relative_ppm": 288676, "window_us": 1}, + "energy_counter_filtering": "Off", "energy_calibration_ref": None}, + {"joules_micro": 1, "energy_provenance": "OnChipCounter", "energy_uncertainty": {"relative_ppm": 288675, "window_us": 1}, + "energy_counter_filtering": "On", "energy_calibration_ref": None}, + {"joules_micro": 250000, "energy_provenance": "OnChipCounter", + "energy_uncertainty": {"relative_ppm": 20000, "window_us": 1000000}, "energy_counter_filtering": None, + "energy_calibration_ref": None}, + {"joules_micro": 9000, "energy_provenance": "CalibratedInstrument", + "energy_uncertainty": {"relative_ppm": 5000, "window_us": 1000000}, "energy_counter_filtering": None, + "energy_calibration_ref": "\u3000"}, + {"joules_micro": 9000, "energy_provenance": "CalibratedInstrument", + "energy_uncertainty": {"relative_ppm": 5000, "window_us": 1000000}, "energy_counter_filtering": None, + "energy_calibration_ref": "urn:example:certificate"}, + {"joules_micro": 9000, "energy_provenance": "ModelBased", "energy_uncertainty": None, + "energy_counter_filtering": None, "energy_calibration_ref": None}, + {"joules_micro": 9000, "energy_provenance": "ModelBased", "energy_uncertainty": {"relative_ppm": 1, "window_us": 1}, + "energy_counter_filtering": None, "energy_calibration_ref": None}, + {"joules_micro": 9000, "energy_provenance": "Estimator", "energy_uncertainty": None, + "energy_counter_filtering": None, "energy_calibration_ref": None}, + {"joules_micro": 9000, "energy_provenance": "HwShunt", "energy_uncertainty": None, + "energy_counter_filtering": None, "energy_calibration_ref": None}, + {"joules_micro": 0, "energy_provenance": "ModelBased", "energy_uncertainty": None, + "energy_counter_filtering": None, "energy_calibration_ref": None}, + {"joules_micro": 9000, "energy_provenance": "onchipcounter", "energy_uncertainty": None, + "energy_counter_filtering": None, "energy_calibration_ref": None}, +] + + +def session_stage_claim(rng, n_set, at_stage_1, signer, subject): + """A stage claim (§2.4.10) that passes its own rules: `n_set` units, `at_stage_1` of + them at stage 1 through one applied first layer, the rest at stage 0.""" + ubs = [n_set - at_stage_1, at_stage_1] if at_stage_1 else [n_set] + objects = [] if not at_stage_1 else [{ + "layer": 1, "object": CV.blake3(b"differential: a stage layer").hex(), "units": {"from": 0, "count": at_stage_1}, + "bytes": 700, "status": "applied", "evidence": "none", "reason": None}] + body = {"vocabulary": CV.STAGE_VOCABULARY, "op_requested": None, "op_committed": None, "op_delivered": None, + "presented": {"wai-stage:layers": 0 if ubs[0] else 1}, "units_by_stage": ubs, "tier": "none", + "stage_hash": None, "objects": objects, "conflicts": 0, "deadline_misses": 0, "bytes_envelopes": 5700} + c = {"kind": "claim", "class": "stage", "subject_type": "object", "subject": subject, "seq": 0, + "issued_at": "2026-09-27T12:00:00Z", "body": body, "signer_id": "did:example:sink", "parent_receipt_hash": None} + return CV.jcs(sign(c, signer)) + + +def sessions(ins, rng, n): + """§2.4.12 around its rules: a random presentation list — units with gaps, one to three + layers each, through one to four decoder entries — and the session it gives, then a + defect or two in the body or the contexts, signed by the sink.""" + base = ins.receipt("session_accept") + ctx0 = ins.by_name["session_accept"]["context"] + envelope = ctx0["envelopes"][0]["envelope"] + reasons = list(CV.SWITCH_REASONS) + for i in range(n): + pool = rng.sample(SESSION_CAPS, rng.randint(1, 4)) + ps = [] + for u in range(rng.randint(1, 12)): + if rng.random() < 0.1: + continue + for layers in range(1, rng.randint(1, 3) + 1): + if layers == 1 or rng.random() < 0.9: + ps.append({"unit": u, "layers": layers, "decoder": rng.randrange(len(pool)), + "out_digest": CV.blake3(b"differential: output %d %d %d" % (i, u, layers)).hex()}) + # Entries in first-use order, as an honest sink lists them. + order = [] + for p in sorted(ps, key=lambda p: (p["layers"], p["unit"])): + if p["decoder"] not in order: + order.append(p["decoder"]) + for p in ps: + p["decoder"] = order.index(p["decoder"]) + decoders = [] + for j, old in enumerate(order): + cap, path, pinned = pool[old] + decoders.append({"capability": cap, "rendition": rng.choice([None, 0]), "path": path, + "decoder": "builtin:wai@0.4.0", "variant": None, + "pin": CV.blake3(b"differential: a pin").hex() if pinned else None, + "tier": "decode-equivalence" if pinned else None, "module_status": None, + "leaves": sum(1 for p in ps if p["decoder"] == j)}) + fin = CV.finals(ps) + primary = sum(1 for p in fin.values() if decoders[p["decoder"]]["path"] == "primary") + ordered = sorted(ps, key=lambda p: (p["unit"], p["layers"])) + root = CV.out_mth([CV.out_leaf(p) for p in ordered]).hex() if ps else None + deadline = rng.choice([None, 40000]) + late = rng.sample(ordered, min(len(ordered), rng.randint(0, 3))) if deadline else [] + late = sorted(({"unit": p["unit"], "layers": p["layers"], "late_us": rng.randint(1, 5000)} for p in late), + key=lambda x: (x["unit"], x["layers"])) + switches = sorted(({"unit": rng.randint(0, 12), "from": "primary", "to": "fallback", "reason": rng.choice(reasons)} + for _ in range(rng.randint(0, 3))), key=lambda w: w["unit"]) + objects = [{"content_hash": CV.blake3(b"differential: object %d %d" % (i, k)).hex(), + "path": rng.choice(["primary", "primary", "fallback"]), + "counted": rng.choice([None, 700, 1200, 0]), "transferred": rng.choice([700, 1200, 3000]), + "presented": rng.random() < 0.8} for k in range(rng.randint(0, 5))] + counted = lambda path: sum(o["counted"] for o in objects if o["counted"] is not None and o["path"] == path) + stage_wires, stage_sets = [], [] + if fin and rng.random() < 0.5: + units = sorted(fin) + f = rng.choice(units) + n_set = rng.randint(1, 3) + reached = sum(1 for u, p in fin.items() if f <= u < f + n_set and p["layers"] > 1) + at1 = min(n_set, max(0, reached + rng.choice([0, 0, 1, -1]))) + signer = VIEWER if rng.random() < 0.9 else RELAY + w = session_stage_claim(rng, n_set, at1, signer, CV.blake3(b"differential: a base %d" % i).hex()) + if rng.random() < 0.05: + w = w.replace('"tier":"none"', '"tier":"nonе"') + stage_wires.append(w) + stage_sets.append({"first_unit": f, "claim": CV.link_hash(json.loads(w)) if rng.random() < 0.95 else "00" * 32}) + body = dict(base["body"], decoders=decoders, units=len(fin), leaf_count=len(ps), output_root=root, + primary_units=primary, fallback_units=len(fin) - primary, switches=switches, + switches_total=len(switches) + rng.choice([0, 0, 2]), deadline_us=deadline, + missed=len(late) + rng.choice([0, 0, 1]) if deadline else 0, missed_units=late, + stage_sets=stage_sets, counted_primary=counted("primary"), counted_fallback=counted("fallback"), + counted_discarded=sum(o["counted"] for o in objects if o["counted"] is not None and not o["presented"]), + uncounted=sum(1 for o in objects if o["counted"] is None), + transferred=sum(o["transferred"] for o in objects), + energy=copy.deepcopy(rng.choice(SESSION_ENERGY))) + if rng.random() < 0.5: + body["classical_declared"], body["classical_source"] = None, None + ctx = {"outputs": copy.deepcopy(ps), "objects": objects} + # One or two defects, in the body or in a context. + for _ in range(rng.choice([0, 1, 1, 2])): + k = rng.randrange(26) + ds = body["decoders"] + if k == 0: + body["primary_units"] += rng.choice([1, -1]) if body["primary_units"] else 1 + elif k == 1: + body["units"] += 1 + elif k == 2 and len(ds) > 1 and ds[0]["leaves"] > 1: + ds[0]["leaves"] -= 1 + ds[1]["leaves"] += 1 + elif k == 3: + body["leaf_count"] += rng.choice([1, -1]) if body["leaf_count"] else 1 + elif k == 4: + body["output_root"] = rng.choice([None, CV.blake3(b"differential: another root").hex()]) + elif k == 5 and late: + late[0]["layers"] += 3 + elif k == 6: + body["switches_total"] = max(0, len(switches) - 1) + elif k == 7: + body["switches"] = [{"unit": u, "from": "primary", "to": "fallback", "reason": "recovered"} for u in range(1025)] + body["switches_total"] = 1025 + elif k == 8 and ps: + body["deadline_us"], body["missed"] = 40000, 257 + body["missed_units"] = [{"unit": u, "layers": 1, "late_us": 1} for u in range(257)] + elif k == 9: + body["deadline_us"], body["missed"] = None, max(1, body["missed"]) + elif k == 10: + body["classical_declared"], body["classical_source"] = rng.choice([(700, None), (None, "wai2-table"), (700, "referenced")]) + elif k == 11 and ctx["outputs"]: + ctx["outputs"][rng.randrange(len(ctx["outputs"]))]["decoder"] = len(ds) + rng.choice([0, 1]) + elif k == 12 and len(ds) > 1: + ds[0], ds[1] = ds[1], ds[0] + elif k == 13: + body["counted_discarded"] += 1 + elif k == 14 and ctx["objects"]: + o = ctx["objects"][0] + o["counted"] = None if o["counted"] is not None else 5 + elif k == 15: + body["host"] = dict(body["host"], threads=rng.choice([0, 3, 6, 2 ** 52])) + elif k == 16 and ds: + ds[-1]["decoder"] = rng.choice(["builtin:wai", "builtin:wai@x", "module:sha256:" + "a" * 64, "builtin:Wai@1"]) + elif k == 17 and ds: + ds[-1]["pin"] = rng.choice([ds[-1]["pin"], CV.blake3(b"differential: a pin").hex()]) + ds[-1]["tier"] = rng.choice(["none", "decode-equivalence", "entropy-consistency", "bit-exact", None]) + elif k == 18 and ds: + ds.append(dict(ds[0])) + elif k == 19 and ctx["outputs"]: + ctx["outputs"].pop(rng.randrange(len(ctx["outputs"]))) + elif k == 20 and ctx["outputs"]: + ctx["outputs"][0]["out_digest"] = CV.blake3(b"differential: not this output").hex() + elif k == 21 and stage_sets: + stage_sets.append(dict(stage_sets[0])) + elif k == 22: + body["framing"] = rng.choice(["registered", "wai-measure/0"]) + elif k == 23 and ds: + ds[0]["module_status"] = rng.choice(["pinned", "fetched", "cached"]) + elif k == 24: + body["counted_primary"] += rng.choice([1, -1]) if body["counted_primary"] else 1 + elif k == 25 and switches: + body["switches"] = [dict(switches[0], to="primary")] + switches[1:] + if rng.random() < 0.5: + ctx["redecoded"] = [{"index": j, "out_digest": rng.choice([p["out_digest"], CV.blake3(b"differential: redecoded").hex()])} + for j, p in enumerate(ps) if rng.random() < 0.3] + if rng.random() < 0.4: + ctx["envelopes"] = rng.choice([[], [{"envelope": envelope, "rendition": rng.choice([0, 1, 2])}]]) + if ctx["envelopes"]: + body["classical_declared"], body["classical_source"] = rng.choice([(700, "wai2-table"), (701, "wai2-table"), (None, None)]) + if stage_wires: + ctx["stage_claims"] = stage_wires + if rng.random() < 0.1: + del ctx["outputs"] + ins.add(f"session_random_{i}", CV.jcs(sign(dict(base, body=body), VIEWER)), ctx) + + def figures(ins, rng, n): oer_t = ins.by_name["energy_matches_oer_accept"]["context"]["oer"]["receipt"] claim_t = ins.receipt("energy_matches_oer_accept") @@ -1007,6 +1212,7 @@ def main(argv): bodies(ins) reports(ins, random.Random(f"reports {a.seed}"), a.random) # its own stream, as classes() stages(ins, random.Random(f"stages {a.seed}"), a.random) # its own stream, as classes() + sessions(ins, random.Random(f"sessions {a.seed}"), a.random) # its own stream, as classes() doc = text_of({"about": "differential inputs; no outcome is declared", "vectors": ins.out}) with tempfile.NamedTemporaryFile("w", suffix=".json", delete=False, encoding="utf-8") as f: f.write(doc) -- 2.54.0 (Apple Git-157) From 6aeb9f2eaa093051130f3b59049bbaf7cebd0385 Mon Sep 17 00:00:00 2001 From: Transaction Science Date: Tue, 6 Oct 2026 09:20:59 -0400 Subject: [PATCH 04/27] wai: a session's energy figure is an item of its own for confirmation MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit key_log::Item::figure_of_claim gives the energy figure of a metered reconstruct-session claim as a second item (jwp-receipts §7.5): it needs reconstruct-session and energy/, every one of them, as confirm already requires of an item's authorities. A verifier reports the session's confirmation and its figure's side by side. signer-conformance gains the cases: a key holding reconstruct-session but not energy/OnChipCounter confirms the session and has its figure refused; a key holding both, under a fetched anchor, leaves the figure unconfirmed; under a pinned one, both are confirmed; a did:key leaves both unconfirmed. signer_verify.py gives every verdict; the earlier vectors are an unchanged prefix. Co-Authored-By: Claude Opus 5.5 --- wai/signer-conformance/README.md | 10 +- wai/signer-conformance/signer_verify.py | 18 ++- wai/signer-conformance/vectors.json | 138 ++++++++++++++++++++++ wai/wai-rs/src/key_log.rs | 15 +++ wai/wai-rs/src/key_log/corpus.rs | 148 ++++++++++++++++++++++-- wai/wai-rs/src/key_log/tests.rs | 30 ++++- 6 files changed, 344 insertions(+), 15 deletions(-) diff --git a/wai/signer-conformance/README.md b/wai/signer-conformance/README.md index 048ea9cd2..4628dfa67 100644 --- a/wai/signer-conformance/README.md +++ b/wai/signer-conformance/README.md @@ -21,7 +21,10 @@ reason, head or anchor path — does not conform. **`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. The item is either +`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= reason=