open-standards/wai/extensions/ai-usage.md
Transaction Science a7157f691e
Some checks failed
joule-moq-room room service / joule-moq-room · does this change touch it (pull_request) Successful in 6s
joule-moq-web browser client / joule-moq-web · does this change touch it (pull_request) Successful in 6s
wai-web reach builds / wai-web reach · does this change touch it (pull_request) Successful in 6s
wai-web reach builds / wai-web reach builds · the package of record, every output as recorded (pull_request) Successful in 2m46s
wai-web reach builds / wai-web reach builds · this tree's wai-web, every rung on its engine line (pull_request) Successful in 4m46s
standards workspaces build + test / which workspaces this change touches (pull_request) Successful in 14s
WAI conformance / does this change touch it (pull_request) Successful in 13s
WAI energy receipts / does this change touch it (pull_request) Successful in 9s
WAI HTTP delivery / WAI HTTP · does this change touch it (pull_request) Successful in 12s
WAI neural sink gates / does this change touch it (pull_request) Successful in 14s
wai-pack / wai-pack · does this change touch it (pull_request) Successful in 11s
repository checks / lockfiles, tests in CI, workflow hygiene, spec and section references, public text (pull_request) Successful in 1m37s
wai-quantum studio and desktop / does this change touch it (pull_request) Successful in 20s
wai-web wasm32 / does this change touch it (pull_request) Successful in 22s
WAI conformance / quantum core and corpus under wasm32-wasip2 (wasmtime) (pull_request) Successful in 3m0s
WAI conformance / cross-arch byte-equality · linux (pull_request) Successful in 30s
WAI energy receipts / energy receipts · linux (pull_request) Successful in 10m5s
WAI neural sink gates / model-free refusals of the neural sink (pull_request) Successful in 1m31s
WAI conformance / cargo-class corpora · linux (pull_request) Successful in 18m15s
wai-pack / wai-pack · linux (pull_request) Successful in 1m47s
wai-quantum studio and desktop / studio · browser (pull_request) Successful in 2m38s
wai-web wasm32 / wai-web wasm32 build · corpus, menu and writers (pull_request) Successful in 4m13s
wai-quantum studio and desktop / desktop app · macos (pull_request) Has been cancelled
wai-pack / wai-pack · linux-arm64 (pull_request) Has been cancelled
wai-pack / wai-pack · macos (pull_request) Has been cancelled
wai-pack / wai-pack · independent verifier (Python) (pull_request) Has been cancelled
wai-pack / wai-pack · the floor through a media prober (pull_request) Has been cancelled
wai-pack / wai-pack · dependency licences (pull_request) Has been cancelled
WAI HTTP delivery / HTTP corpus · falsify mutations 0/3 (pull_request) Has been cancelled
WAI HTTP delivery / HTTP corpus · falsify mutations 1/3 (pull_request) Has been cancelled
WAI HTTP delivery / HTTP corpus · falsify mutations 2/3 (pull_request) Has been cancelled
WAI HTTP delivery / HTTP corpus · falsify patches 0/3 (pull_request) Has been cancelled
WAI HTTP delivery / HTTP corpus · falsify patches 1/3 (pull_request) Has been cancelled
WAI HTTP delivery / HTTP corpus · falsify patches 2/3 (pull_request) Has been cancelled
WAI HTTP delivery / HTTP corpus · every patch and mutation in exactly one shard (pull_request) Has been cancelled
WAI HTTP delivery / HTTP corpus · verified both ways, and the differential (pull_request) Has been cancelled
WAI HTTP delivery / cache rules · controls and labelled caches (pull_request) Has been cancelled
WAI energy receipts / energy receipts · linux-arm64 (pull_request) Has been cancelled
WAI energy receipts / energy receipts · macos (pull_request) Has been cancelled
WAI conformance / cargo-class corpora · linux-arm64 (pull_request) Has been cancelled
WAI conformance / cargo-class corpora · macos (pull_request) Has been cancelled
WAI conformance / v2 vocabulary · manifests validate as stated (pull_request) Has been cancelled
WAI conformance / independent verifiers · claims, JWP, key discovery and integer payloads (Python) (pull_request) Has been cancelled
WAI conformance / delivery telemetry · CMCD and CMSD against an independent library (pull_request) Has been cancelled
WAI conformance / cross-arch byte-equality · linux-arm64 (pull_request) Has been cancelled
WAI conformance / cross-arch byte-equality · macos (pull_request) Has been cancelled
WAI conformance / codec wrappers · fuzz smoke, text decode limits, C entry points, provenance, the semantic path (pull_request) Has been cancelled
WAI conformance / C2PA manifest emission · signed, read back, validated (pull_request) Has been cancelled
standards workspaces build + test / macOS energy backends (pull_request) Has been cancelled
standards workspaces build + test / joule-code-rs (joule-code/joule-code-rs, joule-code-rs, linux-arm64, true) (pull_request) Has been cancelled
joule-moq-web browser client / joule-moq-web · browser end-to-end (macos) (pull_request) Has been cancelled
joule-moq-room room service / joule-moq-room, every target (pull_request) Has been cancelled
ai-usage §4.1: a manifest that does not read holds no statement that can be read
Co-Authored-By: Claude Opus 5.5 <[email protected]>
2026-10-21 05:43:49 -04:00

33 KiB
Raw Permalink Blame History

WAI Extension: AI Usage Preferences and Consumption Claims

Status: Draft. Registers the record wai.ai.usage: AI usage preferences for media, bound to the bytes they govern, and the signed statement of an agent that consumed media. A usage statement carries, verbatim, the preferences of three published vocabularies: the AI usage preference vocabulary of draft-ietf-aipref-vocab-08, in its exemplary Structured Field form; the TDM Reservation Protocol's tdm-reservation and tdm-policy (Final Community Group Report CG-FINAL-tdmrep-20240510); and the entries of the cawg.training-mining assertion (Training and Data Mining Assertion, version 1.1). WAI adds no category to any of them. The statement rides in an envelope's manifest, where the object's receipt signs it with the content, so it cannot be removed without the object failing its receipt; in a room usage record, WAU1, that the room authority signs; and in a room grant, as the terms one principal is granted. An HTTP origin writes the Content-Usage field of draft-ietf-aipref-attach-05 and the TDMRep fields from the signed statement, and a MoQ catalog states it for a track before a sink subscribes. One precedence rule decides a use: a grant's terms, then every signed statement, the most restrictive governing, then unsigned statements where nothing is signed. An agent that consumed objects signs a consumption claim, the jwp-receipts claim class consumption, naming the objects by content hash, the term it acted under in each vocabulary, its key as a did:key, the statements it saw and the grant it held; a publisher verifies it against the objects, and a relay or gateway MAY require one before it serves an agent. No new transport. The reference implementation is the ai_usage module of wai-rs (feature ai_usage), with the class's body in claim_receipt; the corpus is live-conformance/usage/, and its second implementation is live-conformance/ai_usage_verify.py. Keywords MUST, MUST NOT, SHOULD, MAY are RFC 2119/8174.

Texts read for this revision, each pinned to the version named: draft-ietf-aipref-vocab-08 (14 September 2026) and draft-ietf-aipref-attach-05 (19 August 2026), Internet-Drafts of the IETF AI Preferences Working Group, both Working Group documents intended for Proposed Standard and neither yet submitted to the IESG; the vocabulary marks its §3 and §4 as not yet having the group's consensus. RFC 9651 (Structured Field Values for HTTP). The TDM Reservation Protocol, Final Community Group Report of 10 May 2024, the report's latest. The Creator Assertions Working Group's Training and Data Mining Assertion, version 1.1, ratified 16 May 2025, the current version. A section number of one of these texts is that version's.

1. Scope

In scope: the usage statement, its three vocabularies, how each is read and what each says about a use (§3); where a statement is carried: an envelope, a room, a grant, an HTTP response and a MoQ catalog (§4); the precedence rule and what a conflict means (§5); the consumption claim (§6); the gate a relay or gateway applies before serving an agent (§7); and verification (§8).

Out of scope: whether a preference is followed, which the vocabulary leaves to its recipient (draft-ietf-aipref-vocab-08 §3.2), and which this extension makes evidence of, not a duty; the legal effect of a preference or of a claim; how a crawler or an agent is recognised as one (§7.1); a profile of the agent protocols that fetch media, which this revision does not define; and the robots.txt rule of draft-ietf-aipref-attach-05 §3, which is the origin's and binds no object (§4.4).

Relationship to the core spec: wai.ai.usage is a record (SPEC §5): a signed record a WAI tool emits and verifies. It names no payload format and is not dispatchable. The manifest member ai_usage (§4.1) is an OPTIONAL member under SPEC §8's rule for MINOR revisions.

Relationship to jwp-receipts: the envelope's statement is signed by the object's receipt (§2.1 there); the consumption claim is a claim receipt of the class consumption (§2.4.4 there), on that extension's envelope, canonical form, signature and chain, with the body and class rules of §6 here.

Relationship to live-rooms: the room descriptor's layout is unchanged. A room's statement is a record of its own, chained like the review policy of live-moderation §3.4, and a grant states its principal's terms in the attribute ai_usage (live-rooms §4.4).

2. Terms

  • Vocabulary: one of aipref, tdmrep and cawg, the three sources §3 carries.
  • Term: what a use is named by in a vocabulary: an aipref usage category label (train-ai, ai-use or search, draft-ietf-aipref-vocab-08 §6.1); the tdmrep property tdm-reservation, which governs text and data mining as a whole; or a key of a cawg.training-mining assertion's entries.
  • Preference: what a vocabulary says about one term: allow, disallow or unknown (draft-ietf-aipref-vocab-08 §3).
  • Statement: a JSON object of §3 holding one or more vocabularies.
  • Signed statement: one of an envelope whose receipts verify (§4.1), or of a room usage record that verifies (§4.2).
  • Agent: a party that consumes media by automated means, for any use a vocabulary names. An agent principal in a room is one whose grant carries the attribute ai_usage (§4.3).
  • Content hash: an object's jwp-receipts §2.1 content hash, 32 bytes, written as 64 lowercase hexadecimal digits in JSON.

Integers are little-endian. A digest is SHA-256 (FIPS 180-4), 32 bytes. Ed25519 is RFC 8032's, verified strictly (SPEC §7 Signatures). The canonical form of a JSON value is its JCS serialisation (RFC 8785) as jwp-receipts §2.4.3 restricts it: strings, unsigned integers, null, arrays and objects.

3. The usage statement

3.1 Members

A statement is a JSON object with one or more of these members and no other:

member value source
aipref an object: revision, value draft-ietf-aipref-vocab-08
cawg an object: revision, entries Training and Data Mining Assertion
tdmrep an object: revision, tdm-reservation, tdm-policy the TDM Reservation Protocol

Each vocabulary keeps its own terms and its own preferences. A statement maps no term of one onto a term of another, and a WAI tool MUST NOT write a term none of them defines.

3.2 aipref

  • revision: the string draft-ietf-aipref-vocab-08.
  • value: a statement of preference in the vocabulary's exemplary serialisation (draft-ietf-aipref-vocab-08 §6), as the text an HTTP Content-Usage field would carry (draft-ietf-aipref-attach-05 §2): for example train-ai=n, search=y. It is 1 to 1024 characters, each U+0000 to U+007F (§6.3 there: the syntax is ASCII), and it MUST parse as a Dictionary (§3.3).

The preference of a term is read as draft-ietf-aipref-vocab-08 §6.5 has it: the Dictionary's member whose key is the term's label, its parameters disregarded, gives allow when its value is the Token y, disallow when it is the Token n, and unknown otherwise; a label absent is unknown, and a key that is not one of the three labels is ignored (§6.4 there). When a key repeats, the Dictionary keeps its last value (RFC 9651 §4.2.2), so train-ai=n, train-ai=y allows.

3.3 The Dictionary

value parses as RFC 9651 §4.2 parses a field of type Dictionary: its characters are bytes (§4.2 step 1, which fails on a byte above 0x7F); leading spaces are discarded; the Dictionary is parsed by §4.2.2, with its keys (§4.2.3.3), parameters (§4.2.3.2), inner lists (§4.2.1.2) and every bare item: Integer and Decimal (§4.2.4), String (§4.2.5), Token (§4.2.6), Byte Sequence (§4.2.7), Boolean (§4.2.8), Date (§4.2.9) and Display String (§4.2.10); leading spaces are discarded again; and any character left fails. RFC 9651 leaves two checks of a Byte Sequence to the parser (§4.2.7); here the sequence parses when its content, the characters between its colons, is characters of the base64 alphabet (RFC 4648 §4) followed by at most two =, with the alphabet characters numbering other than one more than a multiple of four. Neither padding nor pad bits are checked.

draft-ietf-aipref-vocab-08 §6.5.1 reads a value that does not parse as unknown for every term. A statement does not carry one: a signer whose preference would be read as unknown throughout has made a mistake that binding the statement would preserve, so it is refused.

3.4 cawg

  • revision: the string 1.1.
  • entries: an object of 1 to 32 members, the assertion's entries map (Training and Data Mining Assertion 1.1 §3.2), member for member. Each key is 1 to 255 bytes of components separated by single ., a component being one or more of a–z, A–Z, 0–9, _ and -; a key beginning cawg. is one of the four the assertion defines, cawg.data_mining, cawg.ai_inference, cawg.ai_generative_training and cawg.ai_training, since it reserves the prefix (§3.1 there). Each value is an object holding use, one of allowed, notAllowed and constrained, and optionally constraint_info, 1 to 1024 bytes of UTF-8 (the member the assertion's CDDL names; its prose spells it constraints_info).

A term is a key: allowed is allow; notAllowed is disallow; constrained is disallow, since the assertion treats it as notAllowed in the absence of additional information (§3.1 there), which a grant can give (§5.2); a key absent is unknown. The assertion's metadata map is not carried.

3.5 tdmrep

  • revision: the string CG-FINAL-tdmrep-20240510.
  • tdm-reservation: the integer 1, TDM rights are reserved, or 0, they are not (the protocol's §5.1). The protocol treats any other value as unset; a statement carries none.
  • tdm-policy: null, or the URL of the rightsholder's TDM policy (the protocol's §5.2): 8 to 2048 bytes of ! to ~ (0x21–0x7E), beginning https:// or http://.

The one term is tdm-reservation: 1 is disallow and 0 is allow. tdm-policy is carried for whoever seeks a licence and is not evaluated.

3.6 Reading a statement

A statement is read from JSON in which no object names a member twice. It is refused at the first of these that holds:

  1. It is not an object, it has no member, it has a member §3.1 does not list, or a vocabulary's object has a member absent, a member its section does not list, or a member of another type or outside its range: usage_malformed. A revision that is a string is in range here; in aipref, a value that does not parse (§3.3) is not.
  2. A vocabulary's revision is other than the string its section names: usage_revision_unknown.
  3. Its canonical form is longer than 4096 bytes: usage_malformed.

So a statement with a malformed tdmrep and an unknown aipref revision is refused usage_malformed. The digest of a statement is SHA-256 over its canonical form.

4. Carriage

4.1 The envelope: the manifest member ai_usage

A WAI1 or WAI2 manifest (SPEC §3, §7.1) MAY carry, at its top level, the member ai_usage, a statement. It applies to the object: every rendition and companion of a WAI2. A reader of an earlier revision ignores it (SPEC §8); a malformed one leaves the manifest readable, and this extension refuses the statement, not the envelope.

The member is inside the envelope's bytes, and the object's content hash covers them (jwp-receipts §2.1): the group receipt that includes the object signs the statement with the content. An object whose statement is altered, added or removed no longer hashes to the content hash its receipt names, and fails its receipt. A verifier given an envelope and its receipts:

  1. accepts the receipts as jwp-receipts §3 steps 1 to 5 do, the envelope hashing to the object receipt's content_hash excepted; a refusal there is receipt_invalid;
  2. requires the envelope to hash to that content_hash: otherwise usage_unbound;
  3. reads the manifest's ai_usage, where present, by §3.6. A manifest that does not read (SPEC §2) holds no statement that can be read: usage_malformed.

An object that passes all three is held, with its statement signed by the group receipt's signer_pubkey, or with none. A publisher that states a preference for an object writes the member before it receipts the object. An envelope that carries no receipt carries an unsigned statement, which §5.3 reads as it reads an HTTP field.

4.2 A room: the room usage record WAU1

The room authority states the room's preference in a room usage record:

field size meaning
magic 4 WAU1 (ASCII)
version 1 1 in this revision
room 32 the room id (live-rooms §3.2)
prev 32 the digest of the record this one replaces; 32 zero bytes for the first
effective 8 u64: the room-clock instant from which it applies; 0 for the first
statement 2 + n a u16 length, then the statement's canonical form, 2 to 4096 bytes
sig 64 Ed25519 by the room descriptor's authority over the 18 bytes wai:ai-usage-room (ASCII) and 0x01, followed by every byte from magic through statement

The record's digest is SHA-256 over the bytes from magic through statement. A reader reads exactly the bytes it is given, in the order above, and refuses at the first of these that holds: fewer than 4 bytes, truncated; a magic other than WAU1, malformed; no byte after the magic, truncated; a version other than 1, unknown_version; the bytes end before a field, truncated; bytes after sig, malformed. It then reads statement as JSON and by §3.6 (usage_malformed, usage_revision_unknown), and refuses bytes that are not the canonical form of what they hold (usage_malformed). Then room is the room id (wrong_room), and the signature verifies under the authority (bad_key, bad_signature).

A verifier is given a room's records in a list. The first has prev zero and effective 0; each later one has as prev the digest of the one before it, and an effective above that one's. A record that breaks this is refused room_usage_unlinked. The record in effect at room-clock instant t is the last whose effective is at or below t. A record is replaced, never amended: as draft-ietf-aipref-attach-05 §3.3 has it for robots.txt, a change applies from its instant on and never to what was published before.

An object is the room's when it is given with the room (§8). It is governed at its manifest's live.t (live-ingest §6), an integer; an object of the room whose manifest has none is governed by every record in the list.

4.3 A grant's terms: the attribute ai_usage

A room grant MAY carry the attribute ai_usage (live-rooms §4.4), whose value is the canonical form of a statement: the terms the authority grants that principal. They are an arrangement in the sense of draft-ietf-aipref-vocab-08 §5.2, which overrides a statement of preference for the uses it names. A grant whose attribute does not read by §3.6, or is not the canonical form of what it holds, is refused grant_usage_malformed, and its principal holds no terms. The attribute is signed with the grant (live-rooms §4.2), and the 1024 bytes the grant's attributes take bound the terms.

4.4 HTTP: fields mapped from the signed statement

An origin that serves an object (http-delivery §5) whose envelope carries a statement SHOULD send, for a GET or HEAD of it:

  • for aipref: Content-Usage: and the statement's value, byte for byte (draft-ietf-aipref-attach-05 §2);
  • for tdmrep: tdm-reservation: and 0 or 1, and, where tdm-policy is not null, tdm-policy: and the URL (the TDM Reservation Protocol §6.2).

cawg has no HTTP field. These fields are unsigned. A client reads them as the response's statement and compares it with the object's signed statement:

  • Content-Usage field lines are combined as RFC 9110 §5.3 combines them, with a comma and a space, and parsed by §3.3. It conflicts when it does not parse, or when it gives any of the three labels a preference other than the signed value gives it. Parameters, unknown keys and spelling (train-ai=n,search=y against train-ai=n, search=y) do not conflict.
  • tdm-reservation conflicts when more than one field line carries it, or when its value, without leading and trailing spaces and tabs, is other than the signed one written in decimal. tdm-policy conflicts when more than one field line carries it, or when its value, trimmed the same way, is other than the signed URL, or the signed one is null. An absent field conflicts with nothing.
  • A field for a vocabulary the signed statement does not carry, or any field for an object with no signed statement, conflicts with nothing: it is an unsigned statement (§5.3).

A response whose fields conflict is refused header_conflicts. Field names compare without regard to case. The robots.txt Content-Usage rule (draft-ietf-aipref-attach-05 §3) states a preference for a path, not for an object, and is unsigned; a WAI origin MAY write one, and this extension reads none.

4.5 MoQ: the catalog field wai_ai_usage

A WAI track's catalog entry MAY carry wai_ai_usage, a statement (moq-streaming-format §4), so that an agent knows the preference before it subscribes. A catalog is unsigned. Its statement MUST be the statement of every object on the track that carries one; a catalog whose statement does not read by §3.6, or whose digest differs from the digest of a held object's statement on the track, is refused catalog_conflicts. A room track's catalog SHOULD state the room record in effect when the catalog is published.

5. Precedence

5.1 What governs an object

An object's governing statements are its signed statements: the statement of its envelope, when it is held (§4.1); and, when it is a room's, the room record in effect at its live.t, or every record of the room where it has none (§4.2). A principal's terms are those of the grant it acts under (§4.3).

5.2 The rule

The preference of a use, named by a term T of a vocabulary V, for an object and a principal:

  1. Terms. When the principal's terms carry V and give T allow or disallow, that is the preference: an arrangement overrides a statement of preference (draft-ietf-aipref-vocab-08 §5.2).
  2. Signed statements. Otherwise, of the governing statements that carry V: disallow when any gives T disallow; else allow when any gives it allow; else unknown. This is the vocabulary's own rule for combining statements (§5.1 there), the most restrictive applying.
  3. Unsigned statements. When no governing statement carries V, an agent MAY read an unsigned statement for V (an HTTP field, a catalog, an envelope without receipts) by the same rule. It names no declaring party (§3.1 there), and no verifier can check what it said.

A use named in several vocabularies is disallowed when any of them disallows it; allowed when none disallows it and one allows it; unknown otherwise. A use that falls under no term of a vocabulary is outside that vocabulary, which then says nothing about it. What an agent does with an unknown preference is not this extension's: the vocabulary takes no position on a default (§5 there), and a gate MAY (§7.1).

5.3 Conflicts

A signed statement governs over every unsigned one. An unsigned statement that differs from a signed one is not the signer's: a client that finds one ignores it in step 3, reports the response or catalog refused (header_conflicts, catalog_conflicts), and decides by the signed statement. A stricter unsigned statement is the preference of a party nothing identifies; an agent MAY honour it as well, and a consumption claim is checked against the signed statements alone. Two signed statements that differ are not a conflict: rule 2 applies, and the most restrictive governs.

6. The consumption claim

6.1 The body

A consumption claim is a jwp-receipts §2.4.3 claim of class consumption, subject_type object, signed by the agent's key, whose subject is the first of objects. Its signer_id is the did:key of signer_pubkey (jwp-receipts §7.1), the key that traces the agent. Its body has exactly these members, read in this order at jwp-receipts §3.1 step 2:

member type meaning
objects array of 1 to 1024 32 B hex the content hashes of the objects consumed
usage array of 1 to 3 entries the use, in each vocabulary the agent answers
seen array of 0 to 64 32 B hex the digests of the statements that governed the objects (§5.1)
grant 32 B hex or null the digest of the room grant the agent consumed under (live-rooms §4.2)

A usage entry has exactly vocabulary, one of aipref, cawg and tdmrep, and term, a string of 1 to 255 bytes or null, read in that order. A term names the use as that vocabulary names it; null states that the use falls under no term of the vocabulary. An array of another length, a vocabulary outside the three and a term of another length are field_type.

6.2 Class rules

At jwp-receipts §3.1 step 4, in this order:

  1. objects is in strictly ascending order: consumption_objects_unordered.
  2. subject is the first of objects: consumption_subject_mismatch.
  3. usage is in strictly ascending order of vocabulary: consumption_usage_unordered.
  4. Each term that is not null is a term of its vocabulary: for aipref one of train-ai, ai-use and search; for tdmrep, tdm-reservation; for cawg, one of the assertion's four keys or a key of §3.4's form that does not begin cawg.: consumption_term_unknown.
  5. seen is in strictly ascending order: consumption_seen_unordered.
  6. signer_id is the did:key of signer_pubkey: consumption_signer_not_principal.

6.3 Context

At jwp-receipts §3.1 step 6 a verifier is given the objects it holds, with their receipts (§4.1), and, where the claim names a grant or its objects are a room's, the room: its descriptor, its grants and its usage records. It refuses at the first of these that fails:

  1. Each of objects is the content hash of an object it holds: consumption_object_unknown.
  2. When grant is not null: it is the digest of one of the room's grants that live-rooms §4.3 accepts, whose principal is signer_pubkey, and which is good at the live.t of every object of the room the claim names that has one; and every object the claim names is the room's. Otherwise grant_mismatch. A grant refused grant_usage_malformed holds no terms and is still the principal's.
  3. seen is exactly the digests of the objects' governing statements: preference_mismatch.
  4. usage answers every vocabulary any governing statement carries: usage_unanswered.
  5. For each object in the order of objects, and each entry in the order of usage, the preference of §5.2, with the grant's terms where grant names one, is not disallow: usage_disallowed.

A room whose usage records are refused (§4.2) states no preference: its objects are governed by their own statements alone. A grant the room refuses (live-rooms §4.3) is not one of its grants, and a claim that names it is refused at step 2.

6.4 What an accepted claim states

An accepted claim states, under the agent's key, that the agent consumed those objects for that use, having seen those statements, under that grant. A verifier reports, for each object, the preference §5.2 gives the claimed use: allowed, unknown, or outside when every term is null. A claim refused usage_disallowed is still its signer's statement: its signature and chain hold, and what it records is a use the governing statements disallow. A refusal at step 6 is of the use, never of the signature. The publisher, the agent and any party that holds the objects and the claim reach the same verdict.

7. The gate

7.1 Policy

A relay or a gateway MAY require consumption claims before it serves an agent. Whether it does, and how it recognises an agent outside a room, is its own policy; in a room, an agent principal is one whose grant carries terms (§4.3). The policy has two parameters:

  • window, 0 to 16: how many of the most recent groups the gate served the agent may lack a claim. With 0, every object the agent requests is claimed before it is served, as over HTTP, where the agent names each object by its content hash before it fetches it (http-delivery §5.2). With n ≥ 1, the agent claims what it received after it received it, as over MOQT, where a live object's content hash is known only once it is published.
  • require_allowed: whether a use whose preference is unknown or outside is refused.

7.2 Decision

The gate holds the claims the agent gave it, each verified (§8) and signed by the agent's key (in a room, its grant's principal; elsewhere, the key the gateway authenticates it by): an accepted claim, or one refused usage_disallowed, is held; any other is not. It keeps the groups it served the agent, in order, a group over HTTP being one object. For a request, a group of objects, the objects it checks are the requested ones when window is 0, and otherwise those of every served group but the last window. For each of those objects, in that order, it refuses at the first of these:

  1. No held claim names it: claim_required.
  2. A held claim that names it was refused usage_disallowed: usage_disallowed.
  3. With require_allowed, a held claim that names it gives it a preference other than allowed: usage_not_granted.

Otherwise it serves the request. A gate that refuses tells the agent the reason; over MOQT a relay ends the subscription, and over HTTP a gateway answers 403.

7.3 Over HTTP

An agent gives a gateway a claim with its request: the field WAI-Usage-Claim: and the claim's canonical form in base64url without padding (RFC 4648 §5). The gateway verifies it, holds it as §7.2 says, and decides. WAI-Usage-Claim is proposed for the HTTP Field Name Registry (RFC 9110 §16.3), and is not registered. This revision defines no MOQT carriage for a claim; a relay that gates over MOQT holds the claims its agents gave it over HTTP.

8. Verification

A verifier is given what each check reads, and nothing more:

check inputs outcome
a statement (§3.6) its JSON accepted with its digest and every term's preference, or refused
an object (§4.1) its envelope, object receipt and group receipt held, with its statement or none, or refused
a room (§4.2, §4.3) its descriptor, grants and usage records each record and grant accepted or refused
a response (§4.4) an object and its response fields consistent, or header_conflicts
a catalog (§4.5) a catalog entry and the objects of its track consistent, or refused
a claim (§6) the claim, the claim before it of its signer, its objects, and its room accepted with each object's preference, or refused at a step, with its reason
a gate (§7) the policy, the served groups, the claims given, and a request served, or refused with its reason

A room descriptor or a grant that does not verify is refused as live-rooms §3.4 and §4.3 refuse it; a room with no verified descriptor governs nothing.

9. Reasons

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

reason raised at
usage_malformed §3.6, §4.2
usage_revision_unknown §3.6
receipt_invalid §4.1 step 1
usage_unbound §4.1 step 2
room_usage_unlinked §4.2
grant_usage_malformed §4.3
header_conflicts §4.4
catalog_conflicts §4.5
consumption_objects_unordered §6.2 rule 1
consumption_subject_mismatch §6.2 rule 2
consumption_usage_unordered §6.2 rule 3
consumption_term_unknown §6.2 rule 4
consumption_seen_unordered §6.2 rule 5
consumption_signer_not_principal §6.2 rule 6
consumption_object_unknown §6.3 step 1
grant_mismatch §6.3 step 2
preference_mismatch §6.3 step 3
usage_unanswered §6.3 step 4
usage_disallowed §6.3 step 5, §7.2
claim_required §7.2
usage_not_granted §7.2

A room usage record also raises truncated, malformed, unknown_version, wrong_room, bad_key and bad_signature, as live-rooms §3.4 names them, and a claim every code of jwp-receipts §3.1 steps 1 to 5.

10. Conformance

live-conformance/usage/ holds the corpus, written from fixed seeds by wai_ai_usage_vectors gen as vectors.json. It has:

  • Statements: each vocabulary alone and the three together, with every term's preference; aipref values that exercise the Dictionary: a repeated key, parameters, a value that is not a Token, an inner list, a key that is not a label, and every kind of bare item; and one statement refused for each defect of §3.6, among them a value that does not parse and an upper-case key.
  • Objects: a publication whose envelopes carry statements under one group receipt, among them a WAI2; the same envelope with its statement removed (usage_unbound), and altered (usage_unbound); one under a receipt whose signature fails (receipt_invalid); and one whose statement does not read.
  • Rooms: a room with two chained usage records and the grants of two agent principals, one of whose terms lift a disallow; a record of another room, one whose signature fails, one out of its chain, and one whose statement does not read; a grant whose terms do not read.
  • Responses and catalogs: fields that agree with the signed statement in another spelling, and fields and a catalog that contradict it.
  • Claims: claims accepted with each object's preference — allowed, unknown, outside, and allowed under a grant over a room's disallow — and one refused for each reason of §6.2 and §6.3, among them a use the statement forbids, objects the verifier does not hold, and a signature that fails.
  • Gates: requests served and refused under each policy, for each reason of §7.2.

A conforming verifier gives every case the outcome, the reason, the step and everything else the corpus states. wai_ai_usage_vectors verify and the test tests/ai_usage.rs check that the file regenerates byte for byte, that wai-rs gives every case its outcome, that every reason of §9 appears, and that §9 lists exactly the reference's codes. live-conformance/ai_usage_verify.py is the second implementation, written from this text: it shares no code with wai-rs; it reads rooms with the live-rooms corpus's second implementation (live_rooms_verify.py), checks every signature with WAI's strict rule (claim-conformance/_ed25519.py) and computes BLAKE3 with claim-conformance/_blake3.py, and parses Structured Fields, canonical forms, receipts and claims itself; and it mutates copies of the corpus and requires every copy to fail.

11. Security and privacy considerations

  • A preference is not a security mechanism (draft-ietf-aipref-vocab-08 §8). What this extension adds is evidence: the publisher's statement bound to the bytes, and the agent's statement of what it did, both signed. Neither makes a use happen or stops one.
  • Removing an envelope's statement changes its content hash. An object served without its receipts carries an unsigned statement at most, and an agent that requires receipts sees the difference. A party that strips the statement and receipts the object under its own key becomes that object's publisher, under its own key.
  • An HTTP field and a catalog are written by whoever serves them. A signed statement governs over both (§5.3), so an intermediary that rewrites a field changes nothing a claim is checked against, and a client that compares them sees the rewrite.
  • A consumption claim is signed by the agent's key and names the agent by that key alone (jwp-receipts §7.1). A key-log confirmation, where the agent's origin publishes one, says who holds the key; without one the claim is the key's statement.
  • A claim lists the objects an agent consumed. A publisher that holds it learns what the agent read and for what use, which is its purpose; an agent that claims under a gate discloses that to the gate's operator too.
  • A claim records the use its agent states. A false statement is a signed false statement: a verifier checks it against the objects and the statements, and cannot check what the agent did afterwards.
  • tdm-policy is a URL a statement carries and a verifier never fetches.