open-standards/wai/live-conformance/fleet/README.md
Transaction Science be42dd3b1f wai.delivery.fleet: an organisation's nodes enrolled by their keys, their records verified, and a report signed for a period
extensions/fleet.md: the enrolment (WFE1), the records a node contributes as it
signs them (a relay's session summaries, per-hop records with their ledgers, the
room descriptors that place them), placement in time and one thing once, the
fleet report (WFR1) with node and room lines, energy per scope and class with
unmetered figures counted as unmetered, citations, the bundle and its
verification, and the reasons.

wai-rs: the fleet module (feature fleet), its corpus generator
(wai_fleet_vectors), tests/fleet.rs; live-conformance/fleet/ (63 vectors) and
fleet_verify.py, the second implementation.

Co-Authored-By: Claude Opus 5.5 <[email protected]>
2026-10-27 15:22:20 -04:00

67 lines
4.4 KiB
Markdown

# live-conformance/fleet — the fleet
The corpus of [`extensions/fleet.md`](../../extensions/fleet.md) §11, in one file,
`vectors.json`:
- `vectors`: bundles (§7.1), each a `report`, its `enrolments` and its `records` in their
carriage (§4.1), with the `outcome` §7.3 gives it;
- `keys`: the organisation's and the nodes' public keys, and those of another organisation and
of a relay of no fleet, which the controls use.
**Fleet equivalence.** For each vector, a conforming verifier given its bundle reaches the outcome
the vector states:
- `refuse`: the `reason` and where, `at`: `["bundle"]`, `["report"]`, `["enrolment", i]`,
`["record", i]`, `["report", "nodes", j]` or `["report", "rooms", j]` for a line of the report,
or `["report", "totals"]`;
- `accept`: the report's `digest`, its `organisation`, `start` and `end`, the number of
`records`; each enrolment (its `node`, `role`, `label`, `from`, `until`, `digest`, the
`records` it signed and whether it is `silent`); each node line (its `node`, `label`, `role`,
`sessions`, `links`, `bytes_in`, `bytes_out`, `link_bytes_in`, `link_bytes_out`, `hops`,
`hop_bytes_in`, `hop_bytes_out`); each room line (its `room`, `t0`, `hops`, `sessions`,
`subscriber_us`, `bytes_in`, `bytes_out`); the `totals`; for each line and the totals, the
`energy` of each scope, `sessions` and `hops`: its rows (`class`, `figures`, `joules_micro`,
`max_ppm`), its `unmetered` figures and its `coverage`; and each line's `cites`, each
`[kind, identity]`.
The accepted vectors:
- `a_week`: a week of a fleet of two relays cascading (the edge relay's upstream link to the home
relay is one session at each end), a compositor and an ingest gateway, with a room service
enrolled and silent. Every session's figure is the unmetered marker, so the sessions are
`unmetered`; the lesson room's hops are of three classes, one row each, `whole`; the relay
room's only hop is the reference relay's recorded record, the unmetered marker; and the fleet's
hops are `partial`.
- `measured_only`: a day of a relay and a compositor, both OnChipCounter readings: one row of two
figures with the larger declared uncertainty, `whole`.
- `unmetered_only`: a day of two relays with summaries alone: sessions `unmetered`, hops `none`.
- `enrolled_and_silent`: two relays enrolled, no record: no line, both nodes silent.
Every other vector is refused, a control of one defect: each reason of §10 and each code it reuses,
among them a report that drops an unmetered figure, one that states it as a metered figure of zero
joules, and totals that would state partial hops whole.
**Provenance.** Generated here: `wai_fleet_vectors gen` writes `vectors.json`. The per-hop records,
their ledgers and the room descriptors are taken unchanged from [`metering/`](../metering/): the
lesson room's descriptor and the per-hop records of its relay (OnChipCounter), its compositor
(OnChipCounter in `lesson`, ModelBased in `mixed_classes`) and its ingest gateway (Estimator), and
the relay room's descriptor with `relay-record.wmh`, which the reference relay signed in its own
test and which states the unmetered marker. Their joule figures are those that corpus states. The
home relay here is the relay that signed those records, under the same key. The session summaries
are written by the generator in the reference relay's form, `joule-moq-relay/session-summary/2`,
from sessions authored in code: their counts were measured by nothing, their remote addresses are
documentation addresses (RFC 5737), and every relay states the unmetered marker for a session, as
the reference relay does. `wai-fleet`'s tests read every summary of the accepted vectors with the
reference relay's own types, require its text re-serialised by them to be the line's byte for
byte, and verify its signature with the relay's own check. The organisation's and the other keys
are SHA-256 of a fixed label; every time is a constant; Ed25519 signing is deterministic (RFC 8032);
so the file is the same bytes on every machine. When the metering corpus is regenerated, so is
this one.
Regenerate and check:
cd wai/wai-rs
cargo run --no-default-features --features fleet --bin wai_fleet_vectors -- gen ../live-conformance/fleet
cargo run --no-default-features --features fleet --bin wai_fleet_vectors -- verify ../live-conformance/fleet
cargo test --no-default-features --features fleet --test fleet
python3 -I ../live-conformance/fleet_verify.py ../live-conformance/fleet