| Filename | Latest commit message | Latest commit date |
|---|---|---|
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]> |
||
| .. | ||
| README.md | ||
| vectors.json | ||
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'sbytes;outcomeisread, with itsdigest, itscellsand itschunklength, orrefuseand itsreason.tasks(§5.3) are a TaskConfiguration (task) and acatalogue;outcomeisaccept, with thetask_idand theretention_s, orrefuse.task_files(§5.4) are a file'sbytes, therevisionsand theanchorsheld, by fixture name;outcomeisaccept, with the file'sdigest, thetask_idand theconfirmationas jwp-receipts §7.4 reports it, orrefuse.contributions(§6.2) name atask_fileand arecord, and give the session'sclaims(the last is the one judged), theregion,at_msand thepool; every manifest and creative offixturesis held, and the task file is accepted underreceiver.outcomeisreport, with thecell,creative,column,quartile,time, the reportid(freshwithout attestation) and the pool idsdiscarded, orno_reportwith itsreason.flows(§6–§7) are end to end:reportslists each report, a presentation with itsrecord,claim,region,at_msand its contribution's cell, or a report written to fail with theerrorand the WAIreasonit meets;stepsare, in order, each upload (theWIU1file, the leader'sresponseas DAP UploadErrors and itserrors, and for a relay's merge itssourcesand each source'ssharesof the response), the aggregation job (its request, response and each report'soutcomeandreason), and each collection atnow_s(processing, a DAP problem type, orcompletedwith every message, theresultand the signedreceipt). Theflightflow'slatereport is uploaded after its batch's collection, and itsreplaystep sends the helper again, byid, a report it committed: theinit_reqand the helper'sresp, refusing itreport_replayed. The helper's statement does not count it (telemetry-aggregation §6.1).uploads(§6.4) are a file'sbytes;outcomeisread, with thetask_idand theids, orrefuse.plans(§6.5) are thestoredreports, the instantt_msand thebudget, under the open task file;outcomegivessend(each id and its class),defer,dropand thefile.settles(§6.6) are the filesentand theresponse;outcomegives whether itsettles, and the ids todeleteand tokeep.receipts(§8.1) are areceipt, acatalogueand the batch'sreports(ornull);outcomeisaccept, with telemetry-aggregation §8.2's fields,rejected(theleader's and thehelper's, eachnullfor a statement of version 1) andreports_checked, orrefusewith itsreasonand where (at).tables(§8.2) are acatalogue, ataskandreceipts, each with its reports ornull;outcomegives each receipt'sdigestandverdict, a standing one's batch, instants, count,rejectedandrows, and thetotals, with each aggregator'srejectedsummed; orrefuseand itsreason.
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.