open-standards/wai/extensions/synthesis.md
Transaction Science 03117478c4 wai.media.synthesis: origin claims for every kind of media, two marking layers, reviews and labels
extensions/synthesis.md: the origin claim of an object, a group or a track (captured,
reconstructed, assistive, synthesized; the class rises along a chain of derivations and
never falls), its IPTC digital source type and C2PA statement as functions of the claim,
two pinned integer derivations whose recomputation proves an assistive claim, the marking
and detection records of the second layer and their agreement with the first, AI
participants' tracks, reviews a player presents only on a decode path of the review's
tier, and a player's signed label log with the EU icons pinned by digest. The wai-rs
module (feature `synthesis`), its vectors generator and the corpus.

Co-Authored-By: Claude Opus 5.5 <[email protected]>
2026-10-21 05:17:43 -04:00

47 KiB
Raw Permalink Blame History

WAI Extension: Synthesis Provenance

Status: Draft. Registers the record wai.media.synthesis: what a piece of media is, for every kind of media WAI carries. An origin claim says of one object, one group or one track that it is captured, reconstructed (a codec, neural or not, rebuilding what was captured), assistive (an edit that does not substantially alter its input, such as an upscale or a denoise) or synthesized (generated). The claim names each input by the link hash of the input's own claim, and its class is the greater of the class its own step gives and its inputs' classes, so the class rises along every chain of derivations and never falls. The claim restates the content's IPTC digital source type, which is a function of the claim, and so is its C2PA statement: the actions and the c2pa.ai-disclosure assertions a manifest carries. An assistive claim carries evidence: where its step is one of the two integer derivations this extension pins, a verifier holding the input's decoded samples recomputes the output and compares it, so the claim that the edit is assistive is checked, not trusted. The signed claim is the first of two marking layers; the second is a watermark whose payload is a function of the claim, and a verifier refuses a detection that disagrees with it. The watermark algorithm itself is a slot this revision leaves to a later one. An AI participant of a room is marked in its grant, and its messages, captions and tracks carry its machine origin. A review is a signed verdict over one exact reconstruction, which a player presents only for a presentation whose decode path holds the review's tier, so one review holds for every viewer of that output. A label policy says when a label must be shown, and a player's signed log shows whether it was. No new transport. The reference implementation is the synthesis module of wai-rs (feature synthesis); the corpus is live-conformance/synthesis/, and its second implementation is live-conformance/synthesis_verify.py. Keywords MUST, MUST NOT, SHOULD, MAY are RFC 2119/8174.

Texts read for this revision, each pinned to the version named: the Code of Practice on Transparency of AI-Generated Content, final text of 10 June 2026, Section 1 Measures 1.1 to 1.3 and Section 2 Measures 1.1 and 1.2 and its Annex 1; the EU icons the Commission publishes for that Annex, as fetched on 21 October 2026 from the page it last updated on 13 October 2026 (§10.2); Regulation (EU) 2024/1689, Article 50, paragraphs 2, 4 and 5 as that Code reproduces them, and the last sentence of paragraph 2 in a reproduction of the Official Journal text (the Official Journal itself could not be fetched for this revision); the C2PA Technical Specification, version 2.4, §6.4, §18.15.2, §18.15.4.5 and §18.28; and the IPTC Digital Source Type vocabulary, whose most recent concept change is dated 2024-10-23. A section number of one of those texts in this extension is that version's.

1. Scope

In scope: the records and their encodings (§2); the classes, the steps and the origin claim (§3); the two pinned integer derivations and the evidence that makes an assistive claim checkable (§4); the digital source type (§5) and the C2PA statement (§6) a claim gives; the two marking layers, their records and their agreement (§7); AI participants of rooms (§8); the review and when a player presents it (§9); when a label is shown, the EU icons pinned by digest, and a player's log (§10); verification (§11).

Out of scope: a transport; how a generator, a codec or an editor works; the watermark algorithm of the second marking layer and its detector, which a later revision registers in the slot of §7.4; how a manifest is assembled, embedded and signed, which is C2PA's and provenance's; key discovery for the signers of these records, which a verifier takes from jwp-receipts §7 as it does for any other key; and the rendering of a label, beyond the asset it shows and the instants it shows it at.

Relationship to the core spec: wai.media.synthesis is a record (SPEC §5): a signed record a WAI tool emits and verifies. It names no payload format and is not dispatchable.

Relationship to timed-text and live-events: a caption's origin (live-events §4.10), and a chat's or a reaction's (§4.4, §4.5 there), is this extension's class for a text event, with no record of its own: origin 1 is a person's text, class captured with source digitalCreation; origin 2 a machine's, class synthesized generated with oversight fully_autonomous; origin 3 a machine's reviewed by a person, class synthesized with oversight human_validated. Timed-text §10.3's export is then §5's and §6's for such a step.

Relationship to energy-binding §6.1: a decode, and any codec, reconstructs; it does not create, and a neural codec does not make its output AI-generated. This extension keeps that: a codec is a convert step (§3.2), which names no model, asserts no source of its own and keeps its input's class, and its C2PA statement is c2pa.opened and c2pa.converted with no digital source type (§6).

Relationship to determinism-tiers: a pinned derivation of §4 is integer throughout, so its output is a pure function of its input's samples, and a claim over it is checked by recomputation, at the tier replicate promises. A review (§9) is presented only where the presentation holds the review's tier, under the rule of determinism-tiers §2 (What a tier covers): a tier covers what the sink emits.

Duties this extension supports: the two machine-readable marking layers of the Code of Practice (Section 1, Measure 1.1: Sub-measure 1.1.1, signed and time-stamped metadata; Sub-measure 1.1.2, an imperceptible watermark) and its richer provenance information (Measure 1.3: the model, the timestamp, the type of operations); the disclosure of AI systems that interact with people (Article 50(1)); and the placement of a label at first exposure, after interruptions and at regular intervals (Section 2, Sub-measures 1.2.1 to 1.2.3). WAI states what its records carry and what a verifier checks. It makes no statement about any regime, and a deployment confirms what a regime asks of it against that regime's text.

2. Records

Every record of this extension is a JSON object (RFC 8259) under the encodings of jwp-receipts §2.4.3: byte strings in lowercase hexadecimal; integers unsigned, at most 2^53 − 1, in plain decimal; no other number; no boolean; a term and a date-time as defined there. A record is read as jwp-receipts §3.1 step 1 reads a claim: RFC 8259's grammar, no member named twice in one object, at most 32 levels of nesting. Each record has exactly the members its section lists, no member missing and none added, at any level, and a kind naming it; one that does not is record_malformed.

Every record carries signer_pubkey (32 bytes, the Ed25519 key of RFC 8032 that signs it) and sig (64 bytes):

sig       = Ed25519(signer_key, "wai:synthesis\x01" || JCS(record without "sig"))
link_hash = BLAKE3("wai:synthesis-link\x01" || JCS(record))

JCS is RFC 8785, which on these values reduces to what jwp-receipts §2.4.3 states. The signature is verified strictly (SPEC §7 Signatures): a key that fails step 1 or 2 is bad_key, and a signature that fails a later step bad_signature. A record is named by its link hash wherever another names it. A record whose members carry issued_at holds a date-time there, the instant its signer signed it: the time stamp the Code of Practice's Sub-measure 1.1.1 asks for, self-asserted.

A digest of samples is SHA-256 (FIPS 180-4) over a canonical buffer: for an image, the RGB8 buffer of reconstruction-binding §2 (row-major, three bytes a pixel, no row padding); for another medium, the canonical buffer its capability's *-equivalence names (determinism-tiers §2). An object's content hash is jwp-receipts §2.1's.

3. Classes and the origin claim

3.1 The origin claim

An origin claim, kind "wai-origin", has these members:

member type meaning
kind string "wai-origin"
subject object what it is about: {"type": "object", "content_hash"}, an object by its content hash; {"type": "group", "receipt"}, a group by its group receipt's link hash (jwp-receipts §3 step 3); or {"type": "track", "track", "from_group"}, a track by its digest (live-rooms §6.2: SHA-256 over the rendering of its namespace, one zero byte and its name) from the group from_group on
media string audio, video, image or text
class string captured, reconstructed, assistive or synthesized (§3.2)
step string capture, convert, assist or generate (§3.2)
operation term what ran: a capability or derivation string, or a term naming the type of operation (upscale, inpainting, speech-synthesis)
record 32 B hex or null the identity of a record that derived the subject, where its deriver signs one; null otherwise
source string the subject's digital source type (§5)
models array the models the step ran, at most 16, each {"digest", "type"}: a prior's digest (SPEC §3.1) and trained (a model derived from sampled content) or algorithmic (one that is not); no digest twice
oversight string or null for generate: fully_autonomous, prompt_guided or human_validated (C2PA 2.4 §18.28.4); otherwise null
inputs array the objects the step read, at most 16, each {"content_hash", "origin", "class", "source"}: its content hash, the link hash of its own origin claim or null where it has none, and that claim's class and source, restated; no content hash twice
evidence object or null for assist: §4.3; otherwise null
issued_at date-time when the signer signed it
signer_pubkey, sig §2

media, class, step, oversight, a model's type and an input's class hold only the values the table names, and source and an input's source only the codes of §5. Otherwise record_malformed.

Who signs: the party that performed the step: the capturing device or its operator, the encoder, the editor, the generator's provider. A claim carries its signer's authority and no more; which signers a verifier trusts is its policy.

A verifier is given at most one origin claim for one subject; a second for a subject an earlier claim names is claim_conflict.

3.2 Steps and the class lattice

The classes are ordered: captured < reconstructed < assistive < synthesized. Each step gives a class, and constrains the claim:

step class it gives inputs models oversight evidence
capture captured none none null null
convert reconstructed at least one none null null
assist assistive exactly one any null an object
generate synthesized any at least one not null null

A capture states as its source one of digitalCapture, computationalCapture, screenCapture or digitalCreation: a recording of the world, or a person's work made without a generative model. A claim that breaks the table is record_malformed.

  • capture records the world, or a person's authorship: a camera, a microphone, a screen recording, a person typing or drawing.
  • convert rebuilds or rearranges its inputs without generating or enhancing anything: an encode, a decode, a transcode, a re-package, a decoder's reconstruction (neural or not), and a derivation that copies samples or composes them (crop, rotation, grid or overlay composition, derived-tracks). A codec names no model: its parameter set is pinned in its envelope, and it reconstructs what its input holds.
  • assist edits one input without substantially altering it: an upscale, a denoise, a colour correction. It is the step whose claim needs evidence (§4).
  • generate produces content by a model: a generated picture, voice or video, an inpainting, a voice clone, a talking head, a frame generated between two others, an avatar a model drives.

The class of a claim is the greatest of its step's class and its inputs' stated classes. A claim whose class is another is class_mismatch. So a conversion of a synthesized input is synthesized, and a transcode, a clip or a re-package can never lower what its input was.

3.3 Checks against what a verifier holds

  • Inputs. For each input whose origin names a claim the verifier holds: that claim's subject is the object of the input's content_hash, and its class and source are the input's. Otherwise input_mismatch. An input whose claim is not held is taken as stated.
  • The subject's own envelope. Where the subject is an object and the verifier holds its envelope (SPEC §2): an envelope whose capability's registry class is GenerativeDeterministic or Behavioral (SPEC §7), or whose manifest's intent is create, is generated by every sink that presents it, and its claim's step is generate. A claim of another step over such an envelope is class_understated.

3.4 Through every derivation

A party that derives an object from others and publishes it signs an origin claim for it whose inputs name the inputs' claims; where it signs a record of the derivation too, the claim's record names that record. A relay forwards claims as jwp-receipts §4.1 has it forward any receipt, byte for byte, and alters none. So each object a sink receives has a claim, and the chain of claims behind it reaches the capture or generation it came from:

derivation the output's claim
a relay forwards an object none: the object is the same, and its claim holds for it
an object re-packaged, or a WAI2 component exploded (SPEC §7.1) the same object for every rule that names objects by content hash; its claim holds
an encode, a transcode, a rung of a ladder, a decoder's reconstruction convert of the input
a crop, a rotation, a composition of several inputs convert of the inputs
an upscale, a denoise, a sink-side enhancement assist of the input, with evidence (§4)
a frame generated between two others, a talking head from a picture and a voice, an inpainting generate over the inputs
a clip of a recording, a segment of a track the claim of each group or object it holds, unchanged

A track or group claim covers each object of the track or group; an object claim, where one is given, is the object's.

4. Assistive evidence

4.1 wai-synthesis:upscale2

The derivation wai-synthesis:upscale2, with no parameters ({}), maps a w × h RGB8 buffer in to a 2w × 2h buffer out. For each pixel (x, y) of in and each of its three bytes, with x₁ = min(x + 1, w − 1), y₁ = min(y + 1, h − 1), a = in(x, y), b = in(x₁, y), c = in(x, y₁) and d = in(x₁, y₁):

  • out(2x, 2y) = a;
  • out(2x + 1, 2y) = (a + b + 1) >> 1;
  • out(2x, 2y + 1) = (a + c + 1) >> 1;
  • out(2x + 1, 2y + 1) = (a + b + c + d + 2) >> 2.

This is the half-sample interpolation wai.video.int_motion predicts with (SPEC §5), in the same integer arithmetic.

4.2 wai-synthesis:denoise3

The derivation wai-synthesis:denoise3, with no parameters ({}), maps a w × h RGB8 buffer in to a w × h buffer out: for each pixel (x, y) and each of its three bytes,

out(x, y) = (8 + Σ k(i, j) · in(clamp(x + i), clamp(y + j))) >> 4,

the sum over i, j ∈ {−1, 0, 1}, with k = 4 at (0, 0), 2 where exactly one of i, j is 0, and 1 at the four corners; clamp keeps a coordinate within 0 to w − 1 (or h − 1).

4.3 The evidence

An assist claim's evidence is an object of exactly these members:

member type meaning
tier string replicate: the step is a pinned derivation, checkable by recomputation; attest: it is not, and the claim asserts that the edit is assistive
derivation term the derivation run
params object its parameters
width, height integer the input's size, each at least 1
input_samples 32 B hex the digest of the input's samples (§2)
output_samples 32 B hex the digest of the output's samples

tier and the sizes outside these values are record_malformed. replicate evidence names wai-synthesis:upscale2 or wai-synthesis:denoise3, with params {}, and an output of at most 2^26 bytes (4 · width · height · 3 for the upscale, width · height · 3 for the denoise); otherwise evidence_invalid. A derivation evaluated in float, or by any operation this revision does not pin, states attest: the edit may well be assistive, but its claim can only assert it.

A model-driven derivation joins the pinned set when a capability registers it in integer arithmetic at decode-equivalence, with its parameter set pinned (SPEC §3.1); its evidence then names it and its pin, and is checked the same way. This revision registers none.

4.4 Checking the evidence

A verifier is given the decoded samples of the objects it holds (§11.1). For an assist claim, in this order:

  1. replicate evidence that §4.3 does not admit: evidence_invalid.
  2. With replicate evidence and the input's decoded samples held: they are width · height · 3 bytes and their digest is input_samples (input_samples_mismatch); the derivation is run over them, and the digest of its output is output_samples (assistive_recompute_mismatch). The claim is then proved. Without the input's samples it is not recomputed; attest evidence is asserted.
  3. With the subject's decoded samples held (an object subject): their digest is output_samples (samples_mismatch).
  4. Under a policy that requires proof (§11.1), a claim that is not proved: assistive_not_proved.

A proved claim says that this output is that pinned derivation of that input, and nothing else: a fact any verifier holding the input's samples checks, at the tier replicate promises.

5. The digital source type

A claim's source is a code of the IPTC Digital Source Type vocabulary, whose terms are http://cv.iptc.org/newscodes/digitalsourcetype/ followed by the code. It is a function of the claim:

step inputs source
capture none as stated: digitalCapture, computationalCapture, screenCapture or digitalCreation
convert one the input's source
convert several compositeSynthetic when an input's class is synthesized; else compositeCapture when every input's source is digitalCapture or computationalCapture; else composite
assist one the input's source when its class is synthesized; else algorithmicallyEnhanced
generate any the generated source: algorithmicMedia when no model is trained; else compositeWithTrainedAlgorithmicMedia when oversight is human_validated or an input's class is not synthesized; else trainedAlgorithmicMedia

A claim whose source is another is source_mismatch. The codes are the vocabulary's own definitions: algorithmicallyEnhanced is an algorithmic modification that leaves the main content unchanged; trainedAlgorithmicMedia media created by a model trained on captured content; compositeWithTrainedAlgorithmicMedia an edit made with such a model, and, by C2PA 2.4 §18.28.3's pairing, generated content a person reviewed and approved; algorithmicMedia media created purely by an algorithm with no sampled training data. A reconstructed claim keeps its input's code: a codec makes no claim about what it reconstructed.

6. The C2PA statement

A claim gives one statement, the JSON object {"actions": A, "assertions": D} written in JCS (RFC 8785):

  • A, the actions of the manifest's first actions assertion (C2PA 2.4 §18.15.2):
    • a claim with no input or with several: [{"action": "c2pa.created", "digitalSourceType": U}], U the IPTC term of the claim's source;
    • a convert of one input: [{"action": "c2pa.opened"}, {"action": "c2pa.converted"}], with no digital source type, as energy-binding §6.1 has it for a decode: the input is the parent ingredient, and its own manifest states its source;
    • an assist of one input: [{"action": "c2pa.opened"}, {"action": "c2pa.edited", "digitalSourceType": U}], U the term of algorithmicallyEnhanced;
    • a generate of one input: the same, U the term of the generated source (§5).
  • D, one c2pa.ai-disclosure assertion (C2PA 2.4 §18.28) for each model whose type is trained, in the claim's order, labelled c2pa.ai-disclosure, c2pa.ai-disclosure__1, … (C2PA 2.4 §6.4): {"label": L, "data": {"modelType": "c2pa.types.model", "modelIdentifier": "tag:transaction.science,2026:wai/model/" ‖ the digest in lowercase hexadecimal}}, and, for a generate, "contentProfile": {"humanOversightLevel": O} in data, O the claim's oversight. A model of type algorithmic has none: C2PA 2.4 §18.28.3 attaches the assertion only where a trained model was invoked. The model is named by digest, as timed-text §10.3 names a caption's.

Embedding the statement in a manifest, and signing that, is C2PA's and provenance's. A rendition of a playlist whose objects include one of class synthesized SHOULD carry the public.machine-generated characteristic (draft-pantos-hls-rfc8216bis-22 §4.4.6.1), as timed-text §10.2 has it for captions.

7. Two marking layers

7.1 The layers

The first layer is the origin claim: signed, time-stamped metadata (the Code of Practice's Sub-measure 1.1.1). The second is an imperceptible watermark embedded in the content (Sub-measure 1.1.2), whose payload is a function of the claim (§7.2). The Code asks for both on the outputs of generative systems and treats fingerprinting or logging as a supplement that is never sufficient alone (Sub-measure 1.1.3); a content-bound commitment, such as a reconstruction binding over decoded pixels, is a supplement of that kind here and not the second layer.

Under a policy that requires both layers (§11.1), an object claim of class synthesized with no marking record naming it (§7.2) is layer_missing.

7.2 The payload and the marking record

A watermark carrying a claim holds an 8-byte payload: the code of the claim's class (0 captured, 1 reconstructed, 2 assistive, 3 synthesized), then the first seven bytes of the claim's link hash. Read from the content alone, with no metadata, it says the class and points at the claim. Seven bytes find a claim; they do not prove one, and the claim's signature does that. The marking record names the scheme that reads it (§7.4); a signpost in the content naming the detection solution, as the Code's Measure 3.4(c)(ii) describes one, is not part of this revision.

The party that embeds the mark signs a marking record, kind "wai-marking":

member type meaning
kind string "wai-marking"
subject 32 B hex the content hash of the marked object
origin 32 B hex the link hash of its origin claim
scheme term the watermark scheme (§7.4)
scheme_digest 32 B hex the SHA-256 of the scheme's definition
payload 8 B hex the payload embedded
issued_at date-time when it signed it
signer_pubkey, sig §2

A verifier holds the claim the marking names (claim_unknown); that claim's subject is the marking's object, and the marking's payload is the claim's (§7.2) (marking_mismatch).

7.3 Detection and agreement

A detector that reads a watermark signs a detection record, kind "wai-detection": the members of a marking but origin, with payload the 8 bytes read, or null where it found no mark. For each detection, in order, with the origin claim whose subject is the detection's object (if the verifier holds one) and the first marking whose subject it is (if it holds one):

  1. With a marking: the detection's scheme and scheme_digest are the marking's (detection_mismatch).
  2. With no payload read: where a marking says the object was marked, watermark_absent, the second layer having been removed; otherwise the object is unmarked.
  3. With a payload read and a claim held: the payload is the claim's (§7.2); otherwise layers_disagree. A content that carries the mark of a synthesized claim while its metadata says captured, or the mark of another claim, is refused here. With no claim held, the detection is not checked.

7.4 The scheme slot

This revision registers no watermark scheme. A scheme is named by a term wai-mark:<name> and the digest of its definition, which a later revision pins with its embedding as an integer derivation appended to a generative one, so that a sink that generates content embeds the mark as part of the reconstruction it is held to, and with its key-free detector. Until then a detection is a signed statement by its detector and nothing more. The conformance corpus names wai-mark:conformance, whose definition is the text wai-mark:conformance names no watermark algorithm (synthesis.md section 7.4) and which names no algorithm: it exercises the records and their agreement, not a watermark.

8. Live rooms

8.1 AI participants and their events

live-rooms §4.4 marks an AI participant: its grant's ai attribute names the model that acts for it. Its chat, reaction and caption events state origin 2 or 3 with that model (live-events §4.4, §4.5, §4.10); a room verifier refuses one that does not, ai_unmarked (live-rooms §9.2 step 6), and a relay does not forward it.

8.2 Its tracks

Every track an AI participant publishes is synthesized media. Its publisher MUST sign, for each layer track it publishes, a track claim (§3.1, subject of type track) of class synthesized, step generate, whose models include the model the grant's ai names; the claim is signed by the participant's key or a room key. A relay MUST NOT forward the objects of such a track while it holds no such claim.

A verifier given a room (§11.1) replays its lifecycle events in the merged order (live-rooms §9.2): each join and grant_exchange sets its subject's grant, each leave clears it, and for each publish and takeover whose subject's grant names a model in ai, each layer track k from 0 to layers − 1, owned by the subject (its key in lowercase hexadecimal) or by the slot (_ and its name), of the published media kind, is named by its digest (live-rooms §6.2). A track with no claim as above is ai_track_unlabelled, at that lifecycle event.

9. Certified synthesis

9.1 The review

A person or an organisation that reviews a synthesized output signs a review, kind "wai-review":

member type meaning
kind string "wai-review"
subject 32 B hex the content hash of the object reviewed
origin 32 B hex the link hash of its origin claim, of class synthesized
tier string the tier at which the reconstruction reviewed is portable: decode-equivalence or generation-equivalence (determinism-tiers §2; SPEC §7 GenerativeDeterministic)
reconstruction 32 B hex the digest of the canonical output the reviewer saw (§2)
decoder term the decoder the reviewer's output came from
variant term or null its decode path, where it has more than one
scope string what was reviewed: accuracy (words, a script), rendering (pixels, a voice, signing), translation
verdict string approved, approved-with-notes or rejected
notes 32 B hex or null the digest of the notes, null exactly for approved
role term or null a role the reviewer holds for this scope, as the reviewer states it
issued_at date-time when it signed it
signer_pubkey, sig §2

A verifier holds the claim a review names (claim_unknown), whose subject is the review's object and whose class is synthesized (review_subject_mismatch).

9.2 Presenting a review

A player proves its tier by stating its decode path and the digest of what it presented, in a present entry of its log (§10.3): the decoder, its variant, the tier the path holds, and the output's digest. The tier a path holds is the weakest along it: the decoder's tier at its pin (SPEC §3.1), and none where any float stage, or any processing after the decode that alters the medium, lies on the path (determinism-tiers §2 What a tier covers: a tier covers what the sink emits). A verifier that holds the object's decoded samples (the output of a decode at the stated tier) checks the stated digest against them: present_output_irreproducible where it differs.

A player MAY present a review, in a review entry of its log, only for an object it has presented, and only where its latest presentation of the object before that entry:

  1. presented the review's object, which the verifier holds the review of (claim_unknown, review_subject_mismatch);
  2. under a review whose verdict is not rejected (review_rejected);
  3. on a path of the review's tier (review_path_not_exact): a path of tier none or entropy-consistency never presents a review made at decode-equivalence;
  4. with the review's reconstruction as its output's digest (review_reconstruction_mismatch).

Where these hold, the viewer received the output the reviewer saw, byte for byte: one review holds for every viewer whose presentation is exact at that tier, and for no other.

10. Label display

10.1 When a label is shown

A label policy, kind "wai-label-policy", signed by the party that presents content to viewers, says which content is labelled and how:

member type meaning
kind string "wai-label-policy"
classes array the classes labelled, 1 to 4 of §3.2's, in its order, none twice
visual 32 B hex the SHA-256 of the visual label shown with visual media
audio 32 B hex or null the SHA-256 of the audible label played with audio-only media; null for none
interval_us integer or null the longest a labelled presentation goes without a label, in microseconds of the log's clock; at least 1 when not null
grace_us integer how long after the instant it is due a label may come
issued_at date-time when it signed it
signer_pubkey, sig §2

A label is due, for each kind (visual for video, image and text, audible for audio):

  • at first exposure: the first presentation of labelled content of that kind in the session (the Code of Practice's Sub-measure 1.2.1(d));
  • after each interruption: the first presentation of labelled content of that kind after the presentation resumed from an ad break or another interruption (Sub-measure 1.2.2(b); live-ads' breaks end on a cue event, live-events §4.3);
  • at intervals: where the policy has one, every presentation of labelled content of that kind that is neither, no longer than the interval after the last label (Sub-measures 1.2.2(b) and 1.2.3).

10.2 The EU icons, pinned

The Code of Practice's Annex 1 publishes three EU icons, for content fully generated by AI (AI GENERATED), for content partially modified by AI (AI MODIFIED), and a basic one (AI), each in four variations. The Commission publishes them as two archives: SVG (https://ec.europa.eu/newsroom/dae/redirection/document/129546, SHA-256 f76707b69b546677b173975c018528e5e549e12afb05550f32c2f46500ffbefd as fetched) and PNG (https://ec.europa.eu/newsroom/dae/redirection/document/129547, SHA-256 aedc51656497a2e8f3e42798e5749a929952f5b262bad368ee3057f58c0f52c7 as fetched). Each file is pinned here by the SHA-256 of its bytes:

file SHA-256
LABEL_AI GENERATED_black transparent.svg 63d28ab55916b4548edff21d5fbcac065a13e5fb936e9b304ff0bada45f2fac1
LABEL_AI GENERATED_black.svg 503af176b05fd725e68b0aa526977d31bcd657d74b15c6103a57ace81384940f
LABEL_AI GENERATED_white transparent.svg d19736f6da9d38af3cffce8ba08f3f7658b573e1794c173fcd8b55a5c200ed44
LABEL_AI GENERATED_white.svg 10125cdef3fc60a351df72fe1266bb00ea046086921bd1bb20135f0f07b5ed36
LABEL_AI MODIFIED_black transparent.svg 9ab09f54c1ccef01799af43794cd93a8af6607ba9ac6b9526fb90a02be8ddf3d
LABEL_AI MODIFIED_black.svg 2e7349e5eca4ee78eeef160dfef4545c31850932245373a07c5401e73e6599c0
LABEL_AI MODIFIED_white transparent.svg 7ccbce41f9f821a574007b32806ddb6d635ee8bbc5d753ccd05f66f5a3165845
LABEL_AI MODIFIED_white.svg 0c72a7d569a1447e2982a843e156bd5f9cb2ab6f201943c6c68f988dc2f1bb6e
LABEL_AI_black transparent.svg f8e20f1dde8c7d95940da08960b1063620812acc9b4ea96eb5ad051f80f67c21
LABEL_AI_black.svg 58ffe859a4d74829d397f534a988081bcefb716849c7d3b84fa7a026dd1d257f
LABEL_AI_white transparent.svg 52d87cb3f6a191dba24796f745e1eeb80d342883acd1a2e6d856342ad853766c
LABEL_AI_white.svg 5b3b94ae67fea55c4f2d013d0b8ed5b876c1533555ed0ed60e688f2f3ccf1a50
LABEL_AI GENERATED_black transparent.png 74c8c4ee720c4a3286c3c1b9f216ac9b918ebf449e8c421dde5a40cd216b27e6
LABEL_AI GENERATED_black.png 8d0af57bc93ba3797042a4b56db757d85f924d9b0200b75b8842da7be5e402a2
LABEL_AI GENERATED_white transparent.png 06c4c7c00738e0e44c35f5927e72842ff7a9dd757e0374335b9cc1ba6bb52199
LABEL_AI GENERATED_white.png f139d8de4b5173f47a777431e7e03d9258d8ea7ee1ee1a062febc7e9fff067fc
LABEL_AI MODIFIED_black transparent.png f48f6c5137834fff87c701eb9a44934ac51c6b5d826b9b5cfead1b88024f8387
LABEL_AI MODIFIED_black.png 0f32e4afbe1459baaf425c78373ea541421ecdb61803438892e2fc07df67da8f
LABEL_AI MODIFIED_white transparent.png 1f3b435b0bf775a168309c4ede49b23c7fa94b759a72623932e6ccb7bdef6203
LABEL_AI MODIFIED_white.png 64241cf4f87eb0837bd234cb63716c7d78f4e9dbbb8866f40464ca4e6bfbfead
LABEL_AI_black transparent.png 24da93847c04a5c86c714c6cd018c45331b47df32936b617b3c8476933d97fa9
LABEL_AI_black.png 0814d5f04533c118f81aed0d353ea75d1df4171c40b962dba1dfa044a3d84779
LABEL_AI_white transparent.png 5b8c743b679a62453a4bc25070b82bb4db33ad9c68f4ef1b6ef7bb562dd3a4e3
LABEL_AI_white.png b9041e416fed455722a3aaa06a5ea0eb376d8a8e11385fdc8e3e8ee6998cdf26

A policy whose visual is one of these digests shows that EU icon; any other digest names an equivalent label, which the Code allows (Section 2, Commitment 1). A player that shows a pinned icon shows exactly those bytes. No audible EU label is published: the Annex says an audio-only icon will be developed, and the Code's audio work begins with a task force. A policy's audio is then the digest of the disclaimer or earcon its signer chooses (Sub-measure 1.2.3), until a revision of this table pins a published one.

10.3 The player's log

A player signs a log of a viewing session, one record per entry, kind "wai-player", under a key of that session (no identity of the viewer or the device):

member type meaning
kind string "wai-player"
session 32 B hex fresh random bytes of the session, the same in every entry
seq integer the entry's position, from 0
prev 32 B hex or null the link hash of the entry before it; null for entry 0
at integer the session clock at the entry, in microseconds; never below the entry before it's
entry object one of the four below
signer_pubkey, sig §2, the same key in every entry

The entries:

  • {"type": "present", "subject", "origin", "class", "media", "tier", "decoder", "variant", "output"}: the player presented an object from at on: its content hash; the link hash of the origin claim it applied, or null; that claim's class as it read it, or null; the media of §3.1; the tier its path holds (decode-equivalence, generation-equivalence, entropy-consistency or none, §9.2); its decoder (a term) and variant (a term or null), as a reconstruct-session claim names them (jwp-receipts §2.4.12); and its output's digest, or null where it states none.
  • {"type": "shown", "label", "asset", "trigger"}: the player showed a label: visual or audio; the SHA-256 of the asset shown; and why, as the player states it: first-exposure, resume or interval.
  • {"type": "resume", "after"}: presentation resumed after an interruption, ad-break or other.
  • {"type": "review", "subject", "review"}: the player presented the review whose link hash is review for the object subject (§9.2).

A log whose seq is not each entry's position, whose prev is not the link hash of the entry before, whose at goes back, or whose session or key changes, is player_chain_broken, at the first entry that breaks it.

10.4 The obligations

Each present entry whose origin names a claim the verifier holds states that claim's class, for that claim's object (present_mismatch). Under a label policy, in this order:

  1. Every shown entry's asset is the policy's visual for a visual label and its audio for an audible one (label_asset_mismatch).

  2. Each present entry whose class is one the policy labels is a labelled presentation at its at, p, of the label kind its media asks for (§10.1). Taking them in the log's order, each kind on its own:

    • the first of its kind is a first exposure: a shown entry of that kind is in the log with at at most p + grace_us;
    • a later one, when a resume entry lies between the labelled presentation of its kind before it and it, is a resume: a shown entry of that kind has at from the latest such resume's at to p + grace_us;
    • any other, under a policy with an interval, is an interval: a shown entry of that kind has at from p − interval_us to p + grace_us.

    One with no such shown entry is label_not_shown, at its present entry. A label not shown at first exposure is caught by the player's own signed log: the log states the presentation and when the label came.

11. Verification

11.1 Inputs

A verifier is given, each in a list: origin claims, marking records, detection records and reviews; a label policy or none; a player's log or none; the envelopes of the objects it holds (each named by its content hash); the decoded samples it holds, each with the content hash of the object decoded; a room or none, as live-rooms §9.1 gives a room verifier its inputs; and a policy of two members:

member values default meaning
dual_layer when-given, required when-given required: §7.1's rule applies (layer_missing)
assistive accept-asserted, require-proof accept-asserted require-proof: §4.4 step 4 applies (assistive_not_proved)

11.2 Steps

The verifier runs these steps and stops at the first refusal, which it reports with the reason and where: a record by its list and index, the label policy, or the room as live-rooms §9.1 states a place in it.

  1. Reading. Each record, list by list (origin claims, markings, detections, reviews, the label policy, the log's entries), each in order, reads (§2, §3.1, §3.2, §4.3, §7.2, §7.3, §9.1, §10.1, §10.3) and its signature verifies: record_malformed, bad_key, bad_signature.
  2. Origin claims, in order, each by these checks in order: a subject named before (claim_conflict); its class (§3.2, class_mismatch); its source (§5, source_mismatch); its inputs and its envelope (§3.3: input_mismatch, class_understated); its evidence (§4.4: evidence_invalid, input_samples_mismatch, assistive_recompute_mismatch, samples_mismatch, assistive_not_proved).
  3. Marking. The markings in order (§7.2: claim_unknown, marking_mismatch); the detections in order (§7.3: detection_mismatch, watermark_absent, layers_disagree); then, under dual_layer required, the origin claims in order (§7.1, layer_missing).
  4. Reviews, in order (§9.1: claim_unknown, review_subject_mismatch).
  5. The room. Live-rooms §9: a refusal there is this verification's, at the room. A gap is not a refusal. Then its AI participants' tracks (§8.2, ai_track_unlabelled).
  6. The log. Its chain (§10.3, player_chain_broken); then each entry in order: a present entry (§10.4, present_mismatch; §9.2, present_output_irreproducible) and a review entry (§9.2: claim_unknown, review_subject_mismatch, review_rejected, review_path_not_exact, review_reconstruction_mismatch); then, under a label policy, §10.4's steps 1 and 2 (label_asset_mismatch, label_not_shown).

11.3 What an accepted case states

  • for each origin claim, in order: its link hash, class and source, its C2PA statement (§6) as written, and for an assist claim whether it is proved, not-recomputed or asserted (§4.4);
  • for each detection, in order: its object and its result, agree, unmarked or not-checked (§7.3);
  • for each AI participant's track, in the order §8.2 reaches them: its digest and the claim that labels it;
  • for each review entry of the log: its index and the review's link hash;
  • for each labelled presentation that had a label due: its index, the trigger (first-exposure, resume or interval) and the index of the first shown entry that met it;
  • the file name of the EU icon the label policy's visual is, where it is one (§10.2);
  • the room's own outcome, accept or gap, where a room was given.

12. Reasons

The codes this extension adds, each with where it is raised:

reason raised at
record_malformed §2, §3.1, §3.2, §4.3, §11.2 step 1
bad_key §2
bad_signature §2
claim_conflict §3.1
class_mismatch §3.2
source_mismatch §5
input_mismatch §3.3
class_understated §3.3
evidence_invalid §4.3, §4.4 step 1
input_samples_mismatch §4.4 step 2
assistive_recompute_mismatch §4.4 step 2
samples_mismatch §4.4 step 3
assistive_not_proved §4.4 step 4
claim_unknown §7.2, §9.1, §9.2
marking_mismatch §7.2
detection_mismatch §7.3
watermark_absent §7.3
layers_disagree §7.3
layer_missing §7.1
ai_track_unlabelled §8.2
player_chain_broken §10.3
present_mismatch §10.4
present_output_irreproducible §9.2
review_subject_mismatch §9.1, §9.2
review_rejected §9.2
review_path_not_exact §9.2
review_reconstruction_mismatch §9.2
label_asset_mismatch §10.4
label_not_shown §10.4

A verifier given a room also raises every code a room verifier raises (live-rooms §11, and the live-events codes it lists), at the room: ai_unmarked among them, for an AI participant's event that does not state its machine origin (live-rooms §9.2 step 6).

13. Conformance

live-conformance/synthesis/ holds the corpus, in one file, vectors.json, written from fixed seeds by wai_synthesis_vectors gen. It lists the EU icons of §10.2 and the vectors: each a case of §11.1, its outcome, and, accepted, everything §11.3 states; refused, its reason and its place. It has:

  • Accepted: a capture, a neural codec's reconstruction of it, and its two pinned derivations, each proved by recomputation from the reconstruction's decoded samples; a float super-resolution step whose attest evidence is asserted; a generated video, an algorithmic audio generation from a wai.generate.spectral envelope, an inpainting a person reviewed, a composite of a capture and the generated video, and a transcode of the video, each synthesized object marked in both layers, a detection that agrees and one that finds the capture unmarked; a room whose AI host states its model in its chat and caption and labels its speech track; and a review of the generated video presented on an exact path, with labels shown at first exposure, after an ad break and within an interval.
  • Refused: each reason of §12 at least once, each a control of one defect: among them a synthesized object labelled captured (class_understated), an assistive claim whose recomputation differs (assistive_recompute_mismatch), the two marking layers disagreeing (layers_disagree), a review presented on a non-exact path (review_path_not_exact), an AI participant's unmarked chat (ai_unmarked, raised by the room) and a track it publishes with no claim (ai_track_unlabelled), and a label not shown at first exposure, after a break, and within the interval (label_not_shown).

A conforming verifier gives every vector the outcome, the reason, the place and the statements the corpus states. wai_synthesis_vectors verify and the test tests/synthesis.rs check that the file regenerates byte for byte, that wai-rs gives every vector its outcome, that §12 lists exactly the reference's codes, and that §10.2's table pins exactly the reference's icons. live-conformance/synthesis_verify.py is the second implementation, written from this text: it shares no code with wai-rs; it reads §10.2's pins and §12's codes from this text, verifies each room with the live-rooms corpus's second implementation (live_rooms_verify.py), every signature with WAI's strict rule (claim-conformance/_ed25519.py) and every link hash with BLAKE3 written from its specification (claim-conformance/_blake3.py); and it mutates copies of the corpus and requires every copy to be refused.

14. Security and privacy considerations

  • A claim carries its signer's authority. A class is a statement; what this extension adds is that a class can only rise along a chain of claims (§3.2), that an assistive claim over a pinned derivation is checked by recomputation (§4), that a generator's own envelope cannot be claimed as anything but generated (§3.3), and that the second layer is checked against the first (§7). A synthesized object whose producer signs no claim at all is caught only by the second layer, and only once a watermark scheme is registered (§7.4).
  • A watermark payload's seven bytes of link hash locate a claim; they are not a commitment, and a mark can be copied into other content. A detection that agrees with a claim says the content carries that claim's mark, not that the content is the claim's subject; the claim's subject is bound by content hash.
  • Evidence states digests of samples, never samples. A verifier that recomputes holds the input's decoded samples, which it decoded itself.
  • A player's log is signed under a key of the session and names objects, claims, labels and instants of the session's clock: no viewer, no device and no account. It shows what that key reports, and is not evidence that a person watched.
  • A review names its reviewer's key and, where given, a role the reviewer states; a role is the reviewer's statement until an authority attests it.
  • A relay can withhold a claim but cannot alter one. A sink that receives an object without the claim its chain should hold sees the gap in the chain of inputs (§3.4).