90 lines
6 KiB
Markdown
90 lines
6 KiB
Markdown
# live-conformance/presentation — ad presentation
|
|
|
|
The corpus of [`extensions/ad-presentation.md`](../../extensions/ad-presentation.md) §12: rooms
|
|
of [live-ads](../../extensions/live-ads.md) breaks under ad policies of version 2 that require
|
|
presentation claims; each viewer's break-form `wai.video.ssai` receipt, its session derived
|
|
from the viewer's session key; the `WPC1` claims the viewers' players signed, good ones and a
|
|
control of each check; the creatives and the attestation issuer a verifier holds; what a
|
|
verifier states of them; and each accepted room's HLS tags, byte for byte.
|
|
|
|
**Presentation equivalence.** For each vector, a conforming verifier given its `descriptor`,
|
|
`grants`, `key_log`, `chains`, `policy`, `pt0_ms`, `receipts`, `pods` and `claims`, and the
|
|
corpus's `creatives` and `issuers` (§9.1), reaches the outcome the vector states, with
|
|
everything live-ads §9.4 states (see [`../ads/README.md`](../ads/README.md)) and, for an
|
|
accepted room under a policy that requires claims (§9.4):
|
|
|
|
- `receipt_facts`, each receipt's `presented_spend_micros` beside its `spend_micros`, and its
|
|
`impressions`, each `slot`, the index of its own `claim` among the claims or `null`, and its
|
|
`verdict`: `presented` or the reason it does not count;
|
|
- `claim_facts`, each claim in the order given: its `digest` (`null` when it does not read),
|
|
its `verdict`, the `receipt` and `slot` it names (from §9.2 step 3 on), and, for an
|
|
impression's own claim, the `quartile` it reaches, its `run_ms` and its `viewable_ms`;
|
|
- `spend_micros`, the presented spend of every receipt together.
|
|
|
|
`claim_about` says what each claim is, and is not checked. A verifier that reaches another
|
|
outcome, reason, place, verdict, fact, spend or tag byte does not conform.
|
|
|
|
The corpus also carries `rfc9578_a2_vector1`: the `pkI`, TokenChallenge and token of RFC 9578
|
|
Appendix A.2's first test vector, as printed there. A conforming verifier verifies that token under
|
|
that key before it reads any token of the corpus.
|
|
|
|
**Provenance.** Generated here: `wai_ad_presentation_vectors gen` writes every file from rooms
|
|
authored in code, from fixed seeds, as `../ads/` is written. Each session key is SHA-256 of
|
|
`wai:ad-presentation/corpus/player`, a zero byte and its number (`players` lists their public
|
|
keys); each media object's content hash SHA-256 of a fixed label and two numbers; each token's
|
|
nonce SHA-256, and its salt SHA-384, of a fixed label and its number. The issuer's key is the
|
|
test key RFC 9578 Appendix A.2 publishes; the generator signs the tokens with it. Ed25519 and
|
|
RSASSA-PSS over a given salt are deterministic, so every file is the same bytes on every
|
|
machine. The generator asserts that RFC 9578's token verifies, that each vector reaches the
|
|
outcome and each claim the verdict it was written to have, and that the corpus gives every
|
|
reason of §11, before it writes. No recorded data.
|
|
|
|
## Layout
|
|
|
|
- `vectors.json`: `rfc9578_a2_vector1`; `creatives`, each its `objects` (`content_hash`,
|
|
`duration_ms`); `issuers`, each its `name`, `token_type` and `keys` (DER
|
|
SubjectPublicKeyInfo, hexadecimal); `players` (informative); and `vectors`.
|
|
- `NAME.m3u8`: the HLS tags of each accepted room.
|
|
|
|
The rooms, each built as `../ads/`'s are (a producer, a viewer and the decider, whose grant
|
|
carries the ad budget):
|
|
|
|
- `video_rule`: a 30 s mid-roll under the video rule, five viewers each filled with ad-x
|
|
(15 s) and ad-y (15 s). Presented: viewer 1's two (one partly out of view, with 3 s at 60%),
|
|
viewer 3's ad-x, and viewer 7's ad-y measured over the player's area. Controls:
|
|
`claim_not_viewable` (40% of the pixels; two runs of 1.5 s broken by a pause; a television
|
|
assumption the video rule does not admit), `claim_duplicate`, `claim_key_unbound`,
|
|
`claim_asset_mismatch`, `claim_quartile_mismatch`, `bad_signature` (its impression then
|
|
`claim_absent`), `claim_malformed` (a signed claim that skips with no resumption stated, and
|
|
a truncated claim), and `claim_no_decision`.
|
|
- `cross_media_attested`: an out and its in under the cross-media rule, an audible run and an
|
|
attestation of type 0x0002 from `issuer.example`. Presented: viewer 11's ad-x and viewer 14's
|
|
two. Controls: `attestation_absent`, `attestation_invalid` (another impression's token; an
|
|
altered authenticator) and `claim_not_viewable` (muted; 90% of the pixels).
|
|
- `ceiling_counts_presented`: a budget of 1 minor unit and two receipts each billing 600 000
|
|
millionths; one has a claim, so the presented spend is within the ceiling: accepted.
|
|
- `ceiling_exceeded_by_presented`: the same, both with claims: `funds_exceeded`.
|
|
- `policy_attestation_without_claim`: `ad_policy_malformed`.
|
|
|
|
## Running
|
|
|
|
```
|
|
cd ../../wai-rs
|
|
cargo run --no-default-features --features live_ads --bin wai_ad_presentation_vectors -- verify ../live-conformance/presentation
|
|
cargo run --no-default-features --features live_ads --bin wai_ad_presentation_vectors -- gen ../live-conformance/presentation # regenerate
|
|
cargo test --no-default-features --features live_ads --test ad_presentation
|
|
cd ../live-conformance
|
|
python3 -I ad_presentation_verify.py presentation
|
|
```
|
|
|
|
`wai_ad_presentation_vectors verify` and `tests/ad_presentation.rs` require every file to
|
|
regenerate byte for byte, no other file but this one to be there, and `wai-rs` to give every
|
|
case its outcome; the test also requires §11 to list exactly the reasons the reference reports.
|
|
`ad_presentation_verify.py` is the second implementation, written from the extension's text and
|
|
sharing no code with `wai-rs`: it verifies each room, policy and receipt with
|
|
`live_ads_verify.py`, reads and judges every claim itself, verifies RSASSA-PSS with an
|
|
implementation of its own, reads §11 from the extension, requires every reason to appear, then
|
|
mutates copies of the corpus, one defect each, each of which must fail, and drops each of its
|
|
own checks in turn, each weakened verifier of which the corpus must catch. The browser
|
|
client's reference producer (`joule-moq-web/web/ads/presentation.test.mjs`) requires
|
|
`video_rule`'s first claim from an observation sequence. Pass = an exit status of 0 from each.
|