open-standards/wai/live-conformance/impressions
Repository files (latest commit first)
Filename Latest commit message Latest commit date
Transaction Science 61320c8641 A report an aggregator committed and was sent again is not rejected, and a reader takes one statement of no count
telemetry-aggregation §6.1's rule that `rejected` counts no report the aggregator aggregated had no
test, and impression_aggregate_verify.py did not apply it. The flight flow now sends the helper a
report it committed, and the Python flow filters as the Rust does. impression-aggregates §7.3 says
what a reader does with a statement of version 1 beside one of version 2, and the corpus adds a
receipt and a table of each.

The ledger's corpus takes these receipts, so it is regenerated by the commit after this one.

Co-Authored-By: Claude Opus 5.5 <[email protected]>
2026-11-07 08:35:01 -05:00
..
README.md A report an aggregator committed and was sent again is not rejected, and a reader takes one statement of no count 2026-11-07 08:35:01 -05:00
vectors.json A report an aggregator committed and was sent again is not rejected, and a reader takes one statement of no count 2026-11-07 08:35:01 -05:00

live-conformance/impressions — ad presentations counted over a bearer with no return path

The corpus of extensions/impression-aggregates.md §11, in one file, vectors.json.

Provenance. Generated here by wai_impression_aggregate_vectors gen (wai-rs, feature impression_aggregate), from Ed25519 keys, salts, report ids, Prio3 randomness, HPKE ephemeral seeds and token nonces and salts that are SHA-256 of a fixed label and a name; constant instants; and manifests, records and claims written by the generator. The issuer key is RFC 9578 Appendix A.2's first test vector, as the presentation corpora use it, and every token is signed with it by RSASSA-PSS over a salt from a seed. The reference aggregators of wai-rs run every flow. No media and no input from outside this repository.

flight gives the flight's first hour (first_hour, in time_precision units), its length and its start in milliseconds. keys names every key by its role, in hexadecimal: the task origin's keys t1 and t2 (aggregate/task) and d1 (delivery alone), a stranger origin's s1, the stitcher and a stranger stitcher, the three statement keys and a stranger's, each aggregator's and the collector's HPKE configuration and private key, the verification keys' seed, and the issuer. fixtures holds what cases name: the creatives A, B and C; the manifests as text (mpd, mpd_short without the first two events, playlist); the pod-input records with what each is; the catalogues flight, open and bound (the flight's with a hold of 3,599 s); the tasks; the key logs (rev0, rev1, which revokes t2 and arrives on the bearer, and stranger); the anchor records (pinned at rev0, fetched); receiver, the revisions and anchors a receiver holds; and the task files flight, open and twin.

  • catalogues (§4.3) are each a catalogue's bytes; outcome is read, with its digest, its cells and its chunk length, or refuse and its reason.
  • tasks (§5.3) are a TaskConfiguration (task) and a catalogue; outcome is accept, with the task_id and the retention_s, or refuse.
  • task_files (§5.4) are a file's bytes, the revisions and the anchors held, by fixture name; outcome is accept, with the file's digest, the task_id and the confirmation as jwp-receipts §7.4 reports it, or refuse.
  • contributions (§6.2) name a task_file and a record, and give the session's claims (the last is the one judged), the region, at_ms and the pool; every manifest and creative of fixtures is held, and the task file is accepted under receiver. outcome is report, with the cell, creative, column, quartile, time, the report id (fresh without attestation) and the pool ids discarded, or no_report with its reason.
  • flows (§6–§7) are end to end: reports lists each report, a presentation with its record, claim, region, at_ms and its contribution's cell, or a report written to fail with the error and the WAI reason it meets; steps are, in order, each upload (the WIU1 file, the leader's response as DAP UploadErrors and its errors, and for a relay's merge its sources and each source's shares of the response), the aggregation job (its request, response and each report's outcome and reason), and each collection at now_s (processing, a DAP problem type, or completed with every message, the result and the signed receipt). The flight flow's late report is uploaded after its batch's collection, and its replay step sends the helper again, by id, a report it committed: the init_req and the helper's resp, refusing it report_replayed. The helper's statement does not count it (telemetry-aggregation §6.1).
  • uploads (§6.4) are a file's bytes; outcome is read, with the task_id and the ids, or refuse.
  • plans (§6.5) are the stored reports, the instant t_ms and the budget, under the open task file; outcome gives send (each id and its class), defer, drop and the file.
  • settles (§6.6) are the file sent and the response; outcome gives whether it settles, and the ids to delete and to keep.
  • receipts (§8.1) are a receipt, a catalogue and the batch's reports (or null); outcome is accept, with telemetry-aggregation §8.2's fields, rejected (the leader's and the helper's, each null for a statement of version 1) and reports_checked, or refuse with its reason and where (at).
  • tables (§8.2) are a catalogue, a task and receipts, each with its reports or null; outcome gives each receipt's digest and verdict, a standing one's batch, instants, count, rejected and rows, and the totals, with each aggregator's rejected summed; or refuse and its reason.

Everything is synthetic: keys attest nothing, the key logs are test logs, origins are reserved example domains, and regions are ISO 3166-1's user-assigned codes and subdivisions of them. Each case states the outcome it was written to have, declared in the generator, never copied from a verifier. The size bounds of §5.4 and §6.4 are carried by no vector; both implementations check each at its edge: a file of exactly the bound that reads in every other respect is read, and the same file one byte longer is refused. §4.3's bound decides no outcome, so neither checks it.

wai_impression_aggregate_vectors verify and tests/impression_aggregate.rs check that the file regenerates byte for byte and that wai-rs reaches every stated outcome; the test also checks the equivalence the extension's §11 describes, which is not stored. ../impression_aggregate_verify.py is the second implementation, written from the extension's text, which also mutates copies of the corpus and drops each of its own checks in turn and requires each to be caught.