### `wai.telemetry.aggregate`: quality of experience the service receives only as sums

- **Measures, aggregated under DAP** ([telemetry-aggregation](extensions/telemetry-aggregation.md)
  §3 to §5): a sink casts each session's metrics (delivery-telemetry §7.2) as four measures, the
  start outcomes and the durations (Prio3SumVec), the stalls (Prio3Sum) and the video start time
  (Prio3Histogram), and reports each through the Distributed Aggregation Protocol of
  `draft-ietf-ppm-dap-20`: secret-shared between a leader and a helper aggregator, each share
  encrypted to its aggregator with HPKE. The aggregators check each measurement's range proof
  (`draft-irtf-cfrg-vdaf-22`) without either seeing it, refuse an out-of-range one
  (`vdaf_verify_error`), and neither learns a measurement as long as one of them follows the
  protocol. Leader and helper are roles any party can run.
- **The task binds who aggregates.** A task's `task_info` names its measure, its scope (zero, or a
  room id), a salt and the keys of the two aggregators and the collector; it enters the
  authenticated data of every input share, so a report is bound at upload. The task id is SHA-256
  over the configuration. A task's minimum batch size is at least fifty, delivery-telemetry §8.4's
  floor, and each aggregator refuses to release a share of a smaller batch (`invalidBatchSize`):
  the floor is enforced by the aggregators, not by the service's restraint.
- **Signed aggregates.** Each aggregator signs a statement of its aggregate share with the batch's
  task, collection, interval, report count and checksum (`WQS1`), sealed to the collector; the
  collector's aggregate receipt (`WQA1`) carries the task, both statements and the result. A reader
  recomputes the result from the two shares and refuses a receipt with one aggregator, a batch below
  the minimum, statements that disagree, or a batch whose reports were uploaded to another task
  (§6 to §8; the reasons are §11's).
- **Where aggregation replaces suppression** (§9): for a figure a measure aggregates, the published
  figure is the receipt's; delivery-telemetry §8.4 still applies to Request-mode reports, to
  Event-mode reports consumed as they arrive, and to figures no measure aggregates. A room's
  quality-of-experience cell ([live-metering](extensions/live-metering.md) §4.7, §6.5) is computed
  from its `outcomes`, `stalls` and `durations` receipts, and equals the cell its logs give.
- **Key classes** ([delivery-telemetry](extensions/delivery-telemetry.md) §3.4, §4.3): every CMCD key
  the mapping writes is `delivery` (what the serving host needs to serve the request) or
  `measurement` (what is only aggregated afterwards), each with what it reveals and to whom; a
  delivery-only Request mode carries the delivery class alone, and a reader refuses a
  delivery-only report with any other key (`measurement_key_in_delivery`). §8.1 now states facts
  and sets no consent requirement for the service's own mechanics; a lawful basis, where a regime
  asks for one, is a `lawful-basis` claim (jwp-receipts §2.4.6).
- **Reference implementation** (`wai-rs`, feature `telemetry_aggregate`): Prio3Count, Prio3Sum,
  Prio3SumVec and Prio3Histogram written from the VDAF draft (the fields, TurboSHAKE128 and its XOF,
  the FLP in the Lagrange basis) and passing the draft's published test vectors, vendored under
  `live-conformance/aggregate/vdaf-22/`; HPKE base mode (RFC 9180 A.1.1); DAP-20's messages and a
  reference client, leader, helper and collector; the receipt verifier and the cell. New
  dependencies, behind the feature: `keccak`, `aes-gcm`, `hkdf` (RustCrypto).
- **Corpus** `live-conformance/aggregate/` (`wai_telemetry_aggregate_vectors gen`), with an
  independent verifier, `telemetry_aggregate_verify.py`, that evaluates Prio3, HPKE and DAP itself
  and re-runs every flow from its reports byte for byte.

