Some checks failed
joule-moq-agent AI participants / joule-moq-agent · does this change touch it (push) Successful in 1m20s
joule-moq-http live HTTP egress / joule-moq-http · does this change touch it (push) Successful in 1m12s
joule-moq-room room service / joule-moq-room · does this change touch it (push) Successful in 1m26s
wai-app and Create / wai-app · does this change touch it (push) Successful in 1m7s
joule-moq-remote host agent / joule-moq-remote · does this change touch it (push) Successful in 3m30s
wai-audit collector and player integration / does this change touch it (push) Successful in 1m55s
joule-moq-web browser client / joule-moq-web · does this change touch it (push) Successful in 3m44s
wai-ledger service / does this change touch it (push) Failing after 59s
wai-ledger service / service · linux (push) Has been skipped
wai-ledger service / service · macos (push) Has been skipped
wai-quantum studio and desktop / does this change touch it (push) Failing after 5s
wai-sink-android native sink library / does this change touch it (push) Failing after 6s
wai-pack / wai-pack · does this change touch it (push) Failing after 50s
wai-quantum studio and desktop / studio · browser (push) Has been skipped
wai-quantum studio and desktop / desktop app · macos (push) Has been skipped
wai-quantum studio and desktop / desktop app · linux (push) Has been skipped
wai-quantum studio and desktop / desktop app · windows (push) Has been skipped
wai-sink-swift native sink package / does this change touch it (push) Failing after 5s
wai-sink-android native sink library / the JNI layer and the platform-free half on the host JVM · linux-arm64 (push) Has been skipped
wai-sink-android native sink library / every ABI, the AAR, and the instrumented tests in a headless emulator · macos (push) Has been skipped
wai-sink-swift native sink package / libwai slices, desktop tests, simulator tests · macos (push) Has been skipped
WAI operation catalogue / does this change touch it (push) Successful in 2m40s
wai-pack / wai-pack · linux (push) Has been skipped
wai-quantum for JavaScript / does this change touch it (push) Successful in 1m30s
wai-pack / wai-pack · linux-arm64 (push) Has been skipped
wai-pack / wai-pack · macos (push) Has been skipped
wai-pack / wai-pack · independent verifier (Python) (push) Has been skipped
wai-pack / wai-pack · the floor through a media prober (push) Has been skipped
wai-fleet service / does this change touch it (push) Successful in 2m27s
wai-pack / wai-pack · dependency licences (push) Has been skipped
WAI Studio / does this change touch it (push) Failing after 8s
WAI Studio / the catalogue's actions, the unit tests and the core · linux (push) Has been skipped
WAI Studio / Studio in Chromium and Firefox · macos (push) Has been skipped
WAI Studio / Studio in WebKit · linux (push) Has been skipped
joule-code conformance gate / Build + round-trip C1-C4 vectors (push) Successful in 4m6s
WAI breaking changes and the conformance runner / WAI breaking · does this change touch WAI (push) Successful in 8s
WAI examples / WAI examples · does this change touch them (push) Successful in 11s
wai web player plugins / the browser run's room compiles · linux (push) Successful in 58s
wai-app and Create / wai-app · tests, clippy, the line language's verifier (linux) (push) Successful in 32s
wai tv web application / the tv application, built to its baseline and checked · linux (push) Successful in 5m12s
wai web player plugins / the plugins' core under Node · linux (push) Successful in 6m56s
wai-audit collector and player integration / collector · linux (push) Successful in 3m3s
wai-fleet service / service · linux (push) Successful in 2m22s
wai-quantum for JavaScript / javascript · linux (push) Successful in 6m54s
WAI operation catalogue / the catalogue and every door · linux (push) Successful in 16m49s
WAI breaking changes and the conformance runner / WAI breaking · wire, record and API against main · linux (push) Successful in 2m25s
WAI breaking changes and the conformance runner / WAI breaking and conform · their tests, and the independent verifiers through wai conform · linux (push) Successful in 8m44s
joule-code conformance gate / joule-moq-ingest, every target (push) Failing after 6m56s
joule-code conformance gate / joule-moq-relay, every target (push) Failing after 7m31s
WAI examples / WAI examples · portable · linux (push) Successful in 24m14s
joule-moq-agent AI participants / joule-moq-agent, every target (push) Successful in 5m45s
joule-moq-http live HTTP egress / joule-moq-http, every target (push) Successful in 6m55s
joule-moq-remote host agent / joule-moq-remote, every target (linux-arm64) (push) Successful in 5m28s
repository checks / lockfiles, advisories, tests in CI, workflow hygiene, spec and section references, public text (push) Failing after 16m10s
joule-moq-room room service / joule-moq-room, every target (push) Failing after 15m19s
joule-code conformance gate / joule-moq-relay, its own energy on a counter (macos) (push) Successful in 51s
joule-moq-remote host agent / joule-moq-remote, every target (macos) (push) Successful in 52s
wai-audit collector and player integration / collector, player integration and the browser end to end · macos (push) Successful in 2m39s
wai-app and Create / wai-app · Create, browser end-to-end (macos) (push) Successful in 8m47s
joule-moq-web browser client / joule-moq-web · browser end-to-end (macos) (push) Failing after 16m25s
wai-fleet service / service · macos (push) Successful in 1m25s
WAI examples / WAI examples · android-app · linux-arm64 (push) Successful in 20m13s
wai tv web application / the tv application in Chromium, Firefox and WebKit · macos (push) Successful in 21m9s
joule-moq-http in browsers / the egress and the protected room in Chromium, Firefox and WebKit · macos (push) Successful in 50m56s
WAI examples / WAI examples · the archive, the readiness check, the browser and Apple · macos (push) Successful in 20m9s
wai web player plugins / the three players in Chromium, Firefox and WebKit · macos (push) Failing after 34m1s
waiTransport's wt §50.2 and §50.4. An egress signs a per-hop record of role 4 (live-metering §3.12): what it received at the relay and what it answered 200 over HTTP, no subscriber time, no DVR window, its ledger by the grant each request carried; key-log authority live/egress. A room-session receipt of version 2 counts its bytes out beside the relays', so receipt-ledger tariff version 4 bills them at the room's price for bytes out: no new source kind and no new tariff version. Its session at a relay is a subscriber session under its grant, not a hop link. energy-methods places its figure in delivery_relay. The gateway signs its record (Gateway::hop_record), held to its own trace in its test. Metering corpus: room lesson_egress, vector `egress` and seven planted faults; live_metering_verify.py checks them and each of its five egress checks, dropped, is caught. Co-Authored-By: Claude Opus 5.5 <[email protected]>
157 lines
11 KiB
Markdown
157 lines
11 KiB
Markdown
# live-conformance/metering — live metering
|
|
|
|
The corpus of [`extensions/live-metering.md`](../../extensions/live-metering.md) §10: rooms,
|
|
and vectors, each a room-session receipt (`WMR1`, of version 1, or of version 2 stating and
|
|
pricing its hops' bytes out) with what it names (the per-hop session
|
|
records, `WMH1`, of version 1 or of version 2 with a hop's DVR figures, each with its ledger; the composition descriptors and receipts, `WCD1` and
|
|
`WCR1`; the take manifests, `WTM1`; and the logs document of QoE observations), and the
|
|
outcome a verifier gives it.
|
|
|
|
**Metering equivalence.** For each vector, a conforming receipt verifier given its room (by
|
|
name, from `rooms`: the descriptor, the grants, the key-log head and the chains, each
|
|
hexadecimal), its `receipt`, `hops` (each `record` and `ledger`), `descriptors`,
|
|
`compositions`, `takes` and `logs` (the document's text, or `null`) reaches the outcome the
|
|
vector states (§5.4):
|
|
|
|
- `refuse`: the `reason` and where, `at`: `["room"]` or `["room", …]` with the room
|
|
verifier's own place (live-rooms §9.1), `["receipt"]`, `["hop", i]` for the receipt's hop
|
|
entry `i`, `["take", i]`, `["compose"]` for the list of composition receipts or
|
|
`["compose", i]` for the receipt `i` in ascending order of digest, `["qoe"]`, `["units"]`,
|
|
`["energy"]` or `["ceilings"]`;
|
|
- `accept`: the receipt's `digest`; the number of media tracks the room published in the
|
|
session (`media_tracks`, the *M* of §3.7); each hop record's `digest`, `size`, size
|
|
`bound` (B(*M*) for version 1, B₂(*M*) for version 2) and `version`, and for a version 2
|
|
record its six DVR figures by their §3.9 names (`dvr_objects_out`, `dvr_bytes_out`,
|
|
`dvr_objects_stored`, `dvr_bytes_stored`, `dvr_byte_s`, `dvr_dropped`); the `units` (with
|
|
`bytes_out` for a receipt of version 2); the `unmetered` hop entries; the `totals`, one per class; the
|
|
`coverage`, `whole` or `partial`; each grant's `consumption` entry (its ceilings, its units,
|
|
its attributed joules by class, whether its share is `unmetered`, its `funds`, its two
|
|
verdicts and its `leaf`, and for a receipt of version 2 its `bytes_out`); the `consumption_root`; the grants `past` a ceiling with their
|
|
flags; and the `qoe_cell`.
|
|
|
|
A verifier that reaches another outcome, reason, place or fact does not conform.
|
|
|
|
**Provenance.** Generated here: `wai_live_metering_vectors gen` writes `vectors.json` from
|
|
sessions authored in code, from fixed seeds, by capture binding's corpus rules: each key is
|
|
SHA-256 of that corpus's fixed label and the principal's index (the principals it shares with
|
|
that corpus and with live recording's are the same principals), every time is a constant
|
|
(the lesson room's `t0` is 2026-10-16T00:00:00Z), every chunk's bytes are SHA-256 output under
|
|
a fixed label, and Ed25519 signing is deterministic (RFC 8032), so the file is the same bytes
|
|
on every machine. The lesson's per-hop records are aggregated from sessions written in code
|
|
by the rules a hop counts by (§3), and stand for what a relay, a compositor and an ingest
|
|
gateway would count; their joule figures are constants and were measured by nothing. The
|
|
`dvr_relay` vector's DVR figures are counted, by §3.9's rules, from a DVR window written in
|
|
code (the composite's 23 frames of 20 000 bytes, each written as it arrives a third of a
|
|
second into its second and held ten seconds or to the span's end, one dropped a second after
|
|
it arrived, a viewer joining at 20 s filled from the window): measured by nothing either. The
|
|
key-log heads are sealed by the reference's key log under a fixed root; the origin is an
|
|
`.example` name (RFC 2606). The generator asserts that each vector reaches the outcome it was
|
|
written to have before it writes it.
|
|
|
|
**Recorded data, one record.** `relay-record.wmh` and its ledger `relay-ledger.wml` were signed
|
|
by `joule-moq-relay` itself, in its test `tests/room_metering.rs` (two publishers and three
|
|
subscribers of the `relay` room over native QUIC and WebTransport, one subscriber slow, each
|
|
reading its streams concurrently), run once on 2026-10-18 with `WAI_METERING_FIXTURE_DIR`
|
|
set; the relay's key is the room's clock key, under the same label. Its counts, its span
|
|
(3.196 s of room clock from 11:45:35.966 UTC)
|
|
and its subscriber time are what that run measured on loopback, so a second run gives other
|
|
bytes: the pair is committed as recorded and read by the generator, which writes the `relay`
|
|
room's lifecycle around the record's span. The relay meters no energy, and the record says so
|
|
with the unmetered marker. The `relay` room's grants run thirteen days from its `t0`, so a
|
|
pair recorded after 2026-10-31 would fall outside them.
|
|
|
|
## Layout
|
|
|
|
One file, `vectors.json`, beside the recorded pair:
|
|
|
|
- `principals`: the keys, by name (informative).
|
|
- `rooms`: `lesson`, a lesson room (a director with the record power, a performer's device and
|
|
an accompanist's capturing two takes, a compositor laying the room out at one frame a
|
|
second, three viewers, a key log listing the room authority, the store, the relay, the
|
|
compositor, an ingest gateway and a metering key, and a revoked metering key and relay key);
|
|
`lesson_ceilings`, the same with the second viewer's joule ceiling at 1 000 µJ and the third
|
|
viewer's funds ceiling at 0; `lesson_gap`, the clock's `join` of the third viewer not
|
|
delivered; `lesson_bad_chat`, the viewer's chat carrying a bad signature; `relay`, the
|
|
reference relay's test room, with no origin; and `lesson_egress`, the lesson with a key log
|
|
that also lists an egress, with the authority `live/egress` (§3.12, §5.2).
|
|
- `vectors`: each with `name`, `about`, `room`, `receipt`, `hops`, `descriptors`,
|
|
`compositions`, `takes`, `logs`, `outcome`, and as above `reason` and `at`, or the facts.
|
|
|
|
The vectors:
|
|
|
|
- accepted: `lesson` (a relay and a compositor read from an on-chip counter, two takes, ten
|
|
composition receipts, three viewers' logs and a suppressed QoE cell, under a tariff in
|
|
euros; signed by the metering key), `signed_by_authority`, `mixed_classes` (a relay's counter
|
|
reading, a compositor's model and an ingest gateway's estimate, one total per class),
|
|
`ceilings_past` (the second viewer past its joule ceiling, the third past its funds
|
|
ceiling), `large_audience` (ten thousand more subscriber sessions with no grant: the relay's
|
|
record is the lesson's size; sixty logs publish the QoE cell), `relay_recorded` (the
|
|
reference relay's record, unmetered, so the energy is partial) and `dvr_relay` (the lesson's
|
|
relay keeping a ten-second DVR window of the composite: a version 2 record, 48 bytes longer
|
|
than the lesson relay's under a bound 48 bytes higher, stating the frames it stored, the
|
|
byte-seconds it held them, one dropped for not verifying against its receipt, and the ten
|
|
it filled a late viewer with; every other record of the corpus is version 1);
|
|
`bytes_out_priced` (the lesson's receipt of version 2: the bytes its hops sent the session's
|
|
sessions, summed from their ledgers, by grant too, and priced per 10^9 bytes in its tariff
|
|
and in each grant's funds); `egress` (the same session with an egress serving it over HTTP,
|
|
in `lesson_egress`: its record of role 4 with no subscriber time and its ledger by the grant
|
|
each request carried, the receipt of version 2 counting its bytes out beside the relay's;
|
|
every other receipt of the corpus is version 1);
|
|
- refused, one defect each: the receipt (`receipt_bad_signature`, `receipt_truncated`,
|
|
`receipt_wrong_room`, `session_invalid`, `signer_not_authorised`, `signer_revoked`,
|
|
`total_of_no_class`, and for version 2 `bytes_out_mismatch`, a byte more than the ledgers
|
|
(`unit_mismatch`), `bytes_out_left_out_of_the_consumption`, the grants' entries without
|
|
their bytes (`ceiling_mismatch`), `bytes_priced_with_no_tariff` (`session_invalid`), and
|
|
`receipt_unknown_version`, the lesson's receipt with its fifth byte 3 and signed again
|
|
(`unknown_version`)); the hop records (`record_missing`, `record_too_large`,
|
|
`record_invalid`, `energy_invalid`, `record_wrong_room`, `record_bad_signature`,
|
|
`entry_restated_wrong`, `hop_not_authorised`, `hop_class_not_authorised`, `hop_revoked`,
|
|
`span_outside_session`, `track_unknown`, `ledger_invalid`, `ledger_ceiling_mismatch`,
|
|
`ledger_root_mismatch`, `hop_units_mismatch`, and for version 2 `dvr_out_exceeds` and
|
|
`dvr_stored_exceeds`, its bytes sent from its store above its out entries' and its objects
|
|
stored above its in entries' (`record_invalid`), `record_unknown_version`, the DVR relay's
|
|
record with its fifth byte 3 and signed again (`unknown_version`), and
|
|
`dvr_record_too_large`, past B₂(*M*) by less than one entry (`record_too_large`)); an
|
|
egress's (§3.12: `egress_states_sessions`, `egress_states_a_dvr_window` and
|
|
`egress_states_drops_out`, `record_invalid`; `egress_ledger_sessions` and
|
|
`egress_ledger_bytes_in`, `ledger_mismatch`; `egress_not_authorised`, a record of role 4 signed
|
|
by the relay's key, `hop_not_authorised`; and `egress_bytes_left_out`, a receipt whose bytes
|
|
out leave the egress's out, `unit_mismatch`); the takes, compositions and logs
|
|
(`take_missing`, `take_unknown`, `composition_missing`, `composition_refused`,
|
|
`composition_outside_session`, `logs_missing`, `qoe_invalid`, `qoe_not_suppressed`); the
|
|
units, energy and ceilings (`units_mismatch`, `recorded_mismatch`, `classes_summed`,
|
|
`total_mismatch`, `ceiling_mismatch`, `consumption_root_mismatch`); and the room
|
|
(`room_refused`, `lifecycle_incomplete`).
|
|
|
|
## Running
|
|
|
|
```
|
|
cd ../../wai-rs
|
|
cargo run --no-default-features --features live_metering --bin wai_live_metering_vectors -- verify ../live-conformance/metering
|
|
cargo run --no-default-features --features live_metering --bin wai_live_metering_vectors -- gen ../live-conformance/metering # regenerate
|
|
cargo test --no-default-features --features live_metering --test live_metering
|
|
cd ../live-conformance
|
|
python3 live_metering_verify.py metering
|
|
```
|
|
|
|
`wai_live_metering_vectors verify` and `tests/live_metering.rs` require the file to regenerate
|
|
byte for byte and `wai-rs` to give every vector its outcome; the test also requires every
|
|
reason of §9 to refuse a vector, the accepted vectors to be the ones above, the large
|
|
audience's relay record to be the lesson's size within the same bound, the DVR relay's record
|
|
to be version 2 with every figure above 0 and every other accepted record version 1, and §9
|
|
to list exactly the reasons the reference reports. `live_metering_verify.py` is the second implementation,
|
|
written from the extension's text and sharing no code with `wai-rs`: it verifies each room
|
|
with `live_rooms_verify.py`, each take with `capture_take_verify.py` and each composition
|
|
receipt with `live_compose_verify.py`, recomputes every unit, every total, every grant's
|
|
consumption and the QoE cell itself, gives every vector the same outcome, requires the same
|
|
coverage, then mutates copies of the corpus, one defect each, each of which must fail, and
|
|
drops each of its checks of §3.12 in turn, each of which the corpus must catch.
|
|
Pass = an exit status of 0 from each.
|
|
|
|
To record the relay's pair again (it changes the corpus), run the relay's test with
|
|
`WAI_METERING_FIXTURE_DIR` set to this directory, then `gen`:
|
|
|
|
```
|
|
cd ../../../joule-code/joule-code-rs
|
|
WAI_METERING_FIXTURE_DIR=$PWD/../../wai/live-conformance/metering cargo test -p joule-moq-relay --test room_metering
|
|
```
|