open-standards/wai/extensions/influence.md

740 lines
47 KiB
Markdown
Raw Permalink Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

# WAI Extension: Influence Attribution
> Status: Draft. Registers the record `wai.media.influence`: who conditioned an output, by
> how much, and what each owner is owed for its deliveries. An owner, any party with a key,
> publishes a work (a style or reference image, a voice model, an adapter or another prior, a
> taste prior, or a **catalogue**, a signed set of works) with signed **terms**: the uses it
> allows, as a `wai.ai.usage` statement and as the acts of generation it allows, a per-use price
> or a revenue share, and the evidence it requires of a use. A tool that conditions a
> generation, a set of candidates or an inpainting of a [contribution](contribution.md)
> session on works signs a **conditioning** record beside the step, naming every work by digest
> with its owner's terms in force, its weight and its use; a use the terms disallow is refused
> (`usage_disallowed`). The pinned conditioned generator, `wai-influence:spectral-blend`, reads
> every reference image and adapter it names, so a verifier regenerates the step and a reference
> omitted, added or reweighted fails (`conditioning_mismatch`). Re-executing the steps gives every
> sample of the output the steps that made it, and a declared rule, `wai-influence:share/1`,
> divides the output's samples, in integer units, among the people who made samples, the owners
> of the works that conditioned the model that made them and of the model itself, and buckets
> that pay no one: works with no owner, `unknown` and `undisclosed`, never zero and never given
> to the tool or a payer. The tool signs an **attribution** whose shares a verifier recomputes; an estimated
> training-time share is stated beside them with its estimator's class, never added. A
> settlement statement ([settlement](settlement.md) §7.8) pays each owner an **attribution
> line** recomputed from the acknowledged deliveries of the output, the shares and the owner's
> tariff, and a **transparency report** tells one owner which outputs its works conditioned, how
> they were delivered and what it was paid, without the other owners' figures. No new
> transport, no payment rail and no money. The reference implementation is the `influence`
> module of `wai-rs` (feature `influence`); the corpus is
> [`live-conformance/influence/`](../live-conformance/influence/), and its second
> implementation is `live-conformance/influence_verify.py`.
> Keywords **MUST**, **MUST NOT**, **SHOULD**, **MAY** are RFC 2119/8174.
>
> Texts read for this revision: the WAI texts this one cites; the abstracts of arXiv 2510.08062
> (*Attribution-by-design: Ensuring Inference-Time Provenance in Generative Music Systems*,
> 9 October 2025) and arXiv 2607.00641 (*What's a Credit Worth? A Market Framework for
> Attribution-Aware Compensation in Generative Music*, 1 July 2026); and the published summaries
> of *Re|Shaping Policies for Creativity*, the fourth edition (February 2026) of the global
> report that monitors the 2005 Convention on the Protection and Promotion of the Diversity of
> Cultural Expressions, and of the resolution P10_TA(2026)0066 of 10 March 2026 on copyright and
> generative AI (procedure 2025/2058(INI)). The bodies of the report, the resolution and the
> papers were not read; §1.1 says what follows from them.
## 1. Scope
### 1.1 Why
The fourth edition of *Re|Shaping Policies for Creativity* (February 2026) projects that the
revenues of music and audiovisual creators fall by about a fifth to a quarter by 2028 through
the outputs of generative AI. The resolution P10_TA(2026)0066 (procedure 2025/2058(INI)), a
non-legislative resolution of 10 March 2026, is concerned with generative systems that use
protected content without authorisation or compensation, and calls for rights holders to control
its use at training, at inference and in retrieval, with transparency and documentation of
sources. arXiv
2510.08062 proposes building attribution into a generative system at inference: a catalogue that
actively shapes an output is credited, and its owner is paid each time it is used, with the
royalty flow traceable. arXiv 2607.00641 sets payment by a training-time attribution score, and
finds that the noisier the score, the more the optimal contract moves from a royalty toward a
fixed fee.
Conditioning at inference is often explicit: a tool loads a reference image, an adapter, a
voice or a taste prior, and knows which. WAI's generator is exact (SPEC §5, *Payload of
`wai.generate.spectral`*), and a contribution session already re-executes to its output sample
by sample ([contribution](contribution.md) §7). This extension adds what conditioned each
generation, by digest, and makes the attribution and the payment that follow recomputable. A
training-time estimate stays an estimate: it is carried with its class beside the exact shares,
as contribution §6 carries one, and is never part of them.
### 1.2 In scope and out of scope
In scope: the records (§2); works, terms, catalogues and a prior its owner publishes (§3); the
conditioning record, the steps it names, the pinned conditioned generator, and the check of each
reference's terms and use (§4); the step map, the rule, the attribution record, its comparison
and the tier of a use (§5); the basis a settlement pays from, and a statement with attribution
lines (§6); the transparency report (§7); verification (§8).
Out of scope:
- **Legal questions.** WAI decides none. It states uses, shares and amounts under declared
rules; whether a use needed a licence, whether a share is fair, and what an owner is entitled
to are decided elsewhere, by others, under their own rules.
- **Money, a payment rail, an invoice, and contacting anyone.** A statement's amounts are the
figures a payment would rest on ([settlement](settlement.md) §13).
- **Training-time attribution as a payment basis.** An estimate is reported with its class and
pays no one here (§5.6); a deployment that pays on estimates does so outside the statement.
- **Remuneration of a session's own parties.** The samples a person makes in a session are that
person's share (§5.2), stated and paid by no attribution line in this revision.
- **Conditioned derivations.** A conditioning record names a `generate`, `candidates` or
`inpaint` step (§4.3). A style transfer is an inpainting over the whole picture; a transform
carries no conditioning, since contribution §7.2 gives an attested transform's samples
`unknown` and a pinned one introduces none.
- **Audio and video.** Contribution's sessions are still images in this revision
(contribution §3.1); a voice model is a kind of work now (§3.1), so that its terms can be
published, and is used by the generators a later revision maps.
Relationship to the core spec: `wai.media.influence` is a **record** ([SPEC](../SPEC.md) §5):
signed records a WAI tool emits and verifies. It names no payload format and is not
dispatchable.
Relationship to [contribution](contribution.md): every step this extension reads is a
contribution step, verified by contribution §10 first; the session, the steps, the record and
the map are unchanged. Relationship to [settlement](settlement.md): an attribution line is that
extension's line kind 2 (settlement §7.2, §7.8), recomputed there from a basis this extension
verifies (§6). Relationship to [ai-usage](ai-usage.md): the owner's terms carry a usage
statement (ai-usage §3), and a reference states its use in ai-usage §6.1's form.
## 2. Records
Every record of this extension is a JSON object under contribution §2's encodings: strict JSON
with no member named twice, at most 32 levels of nesting, byte strings in lowercase hexadecimal,
unsigned integers at most 2^53 − 1 and no other number, no boolean, and the **terms** and
**date-times** of [jwp-receipts](jwp-receipts.md) §2.4.3. Each record has exactly the members
its section lists, at every level, and a `kind` naming it; a record that does not, or a member
outside the values or ranges its section gives, is `record_malformed`. A signed record carries
`signer_pubkey` (32 bytes, Ed25519, RFC 8032) and `sig` (64 bytes):
```
sig = Ed25519(signer_key, "wai:influence\x01" || JCS(record without "sig"))
link_hash = BLAKE3("wai:influence-link\x01" || JCS(record))
```
JCS is RFC 8785. The signature is verified strictly ([SPEC](../SPEC.md) §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. A **digest** is SHA-256 (FIPS 180-4). An **amount** is in
millionths of a minor unit of a currency (ISO 4217), as settlement §7.3 has one.
## 3. Works and their owners
### 3.1 Works
A **work** is what can condition a generation. It has a kind and is named by a digest:
| kind | the work | its digest |
|---|---|---|
| `image` | a style or reference image: an `RGB8` state (contribution §2) | the samples digest: SHA-256 over the buffer |
| `voice` | a voice model | the SHA-256 of its parameter set, as a pin's `sha256` (SPEC §3.1) |
| `adapter` | a parameter set a generator reads beside its model | as for `voice` |
| `prior` | a model or another parameter set: a style model, the model a session's model party names | as for `voice` |
| `taste` | a taste prior, an owned ranking model (`wai.media.exploration`) | as for `voice`: the SHA-256 of its file |
| `catalogue` | a signed set of works (§3.3) | its link hash |
The digest is the work's identity, as a pin's digest is a parameter set's (SPEC §3.1): nothing
else selects it.
### 3.2 Terms
An owner publishes a work's **terms** in a record `kind` `"wai-terms"`, signed by the owner:
| member | type | meaning |
|---|---|---|
| `kind` | string | `"wai-terms"` |
| `owner` | 32 B hex | the owner's key |
| `work` | object | `{"kind", "digest", "id"}`: the work's kind and digest (§3.1), and `id`, a name for people, 1 to 256 bytes, which selects nothing |
| `usage` | object or `null` | the owner's usage statement ([ai-usage](ai-usage.md) §3), read by ai-usage §3.6 |
| `acts` | array | 1 to 3 of `candidates`, `generate` and `inpaint`, in that order, none twice: the acts the owner allows its work to condition |
| `tariff` | object | `{"currency", "per_use", "share_ppm"}` (below) |
| `attribution` | string | `stated`, `checked` or `recomputed`: the lowest tier at which a use of the work stands (§5.5) |
| `valid_from` | date-time | when the terms come into force |
| `valid_until` | date-time or `null` | when they end, excluded; `null` for no end |
| `issued_at`, `signer_pubkey`, `sig` | | §2 |
`tariff`: `currency` is three capitals `A`–`Z` (ISO 4217) or `null`; `per_use` is an amount, 0
to 2^53 − 1, owed for each acknowledged delivery of an output the work's bucket has units in
(§6.1); `share_ppm`, 0 to 1 000 000, is the owner's share, in parts per million, of the revenue
attributable to its units (settlement §7.8). With `currency` `null`, `per_use` and `share_ppm`
are 0. Terms whose `valid_until` is not after `valid_from`, or whose `usage` does not read, are
`record_malformed`.
Terms are their owner's: a terms record **MUST** be signed by `owner`, and one signed by any
other key is `not_signed_by_owner`, whatever its signature. Terms are **in force** at an instant
*t* when `valid_from` ≤ *t* and, where `valid_until` is not `null`, *t* < `valid_until`, the
date-times compared as the instants they denote. An owner changes its terms by publishing new
ones; a use is held to the terms its reference names, in force at the step's `issued_at`.
### 3.3 Catalogues
A **catalogue** is a record `kind` `"wai-catalogue"`, signed by its owner:
| member | type | meaning |
|---|---|---|
| `kind` | string | `"wai-catalogue"` |
| `owner` | 32 B hex | the owner's key |
| `works` | array | 1 to 1024 digests of works, in strictly ascending order |
| `issued_at`, `signer_pubkey`, `sig` | | §2 |
A catalogue not signed by its owner is `not_signed_by_owner`. Terms whose `work` is a catalogue
(`kind` `catalogue`, `digest` its link hash) govern every work it lists: a label, a collective
or one person publishes terms once for a body of work, and a reference to one of its works names
the catalogue (§4.1).
### 3.4 A prior its owner publishes
A style model, a voice model, an adapter or a taste prior is a parameter set in SPEC §3.1's
sense. Its owner publishes it unchanged, pinned by its SHA-256, with terms naming that digest:
the bytes a sink resolves a pin against are not altered by being owned, and a prior that travels
in a WAI envelope carries the owner's usage statement in its manifest as any object does
(ai-usage §4.1). An owner is a key: a person, a collective or a label each signs with one, and
this extension names none of them otherwise.
This extension sets no consent requirement for a service's own mechanics: conditioning a
generation on the works a person chose, computing the shares, settling the lines and writing the
reports. Using a distributor's WAI service is the person's agreement to how that service works.
The terms are the owner's preferences and prices, read as this section reads them. Where a regime
asks the operator to state the lawful basis on which it processes what a record reveals, the
operator states it as a `lawful-basis` declaration ([jwp-receipts](jwp-receipts.md) §2.4.6).
## 4. Conditioning
### 4.1 The conditioning record
A step a work conditioned is named, with every work that conditioned it, in a record `kind`
`"wai-conditioning"`, signed by the key that signed the step (the tool's, for a model's step:
contribution §4.1):
| member | type | meaning |
|---|---|---|
| `kind` | string | `"wai-conditioning"` |
| `session` | 32 B hex | the link hash of the session record |
| `step` | integer | the step's `seq` |
| `link` | 32 B hex | the step's link hash (contribution §2) |
| `references` | array | 1 to 16 references, no work named twice |
| `issued_at`, `signer_pubkey`, `sig` | | §2 |
A **reference** has exactly these members:
| member | type | meaning |
|---|---|---|
| `kind` | string | the work's kind (§3.1) |
| `work` | 32 B hex | its digest |
| `size` | object or `null` | for an `image`, `{"width", "height"}`, each at least 1, the buffer at most 2^26 bytes; `null` for any other kind |
| `catalogue` | 32 B hex or `null` | the link hash of a catalogue that lists the work and whose terms govern it; `null` for none, and always `null` for a `catalogue` |
| `terms` | 32 B hex or `null` | the link hash of the owner's terms in force; `null` for a work with no owner, whose share pays no one (§5.2) |
| `weight` | integer or `null` | 1 to 1 000 000, the part of the step's samples the work conditioned, in parts per million |
| `usage` | array | 0 to 3 entries `{"vocabulary", "term"}`, the use made of the work, in [ai-usage](ai-usage.md) §6.1's form, in strictly ascending order of `vocabulary` |
Every reference of a record has a `weight` or none has; the weights sum to at most 1 000 000.
A `usage` entry's `vocabulary` is `aipref`, `cawg` or `tdmrep`, and its `term` a term of that
vocabulary (ai-usage §6.2 rule 4) or `null` for a use outside it. Anything else is
`record_malformed`. Conditioning is a use at inference; this extension maps it onto no term of
any vocabulary, and the reference states the term the tool acted under, as a consumption claim
does, and is held to the owner's statement (§4.5).
### 4.2 Why a record beside the step
Contribution §2 reads every record with exactly the members its section lists, and refuses any
other member (`record_malformed`). A step with a member naming its conditioning would be refused
by every verifier of contribution, and the session behind it could not be verified for anything.
So this extension adds a record beside the step, and every step stays byte for byte what
contribution reads:
| | a member of the step | a record beside it (this extension) |
|---|---|---|
| a contribution verifier | refuses the step, and the session | verifies the session, and ignores the record |
| the binding to the step | the step's signature | the step's link hash, which the step's signature and the contribution record's root fix (contribution §5) |
| what commits to the set of records | the root | the attribution record, which lists every record it reads (§5.3) |
| a step no work conditioned | carries an empty member | has no record |
| the exact generator's steps | regenerated by contribution | regenerated by contribution; a record naming a work for one is refused (§4.4) |
### 4.3 The steps a record names
A conditioning record names a step whose act is `generate`, `candidates` or `inpaint`, the acts
by which a model introduces samples (contribution §4.2): a record that names any other step, or
a second record naming a step an earlier one named, is `conditioning_invalid`. A record whose
`link` is not the link hash of the step its `step` names is `conditioning_unbound`. A record
whose step the verifier does not hold is not checked against it, and its step's samples are
`undisclosed` (§5.1).
### 4.4 The conditioned generator `wai-influence:spectral-blend`
The generator `wai.generate.spectral` reads its model file and its prompt, nothing else (SPEC
§5). A conditioning record that names a step of that generator names works the step did not
read, and is `conditioning_mismatch`.
This extension pins a conditioned generator, `wai-influence:spectral-blend`. Contribution §4.4
gives a step of any generator but `wai.generate.spectral` the check `attest`, so a contribution
verifier does not regenerate it; this extension does. A step of
`wai-influence:spectral-blend`:
- has a conditioning record (`conditioning_missing` otherwise), each of whose references is an
`image` or an `adapter` with a `weight` (`conditioning_invalid` otherwise);
- has the parameters contribution §4.4 gives a `replicate` step of `wai.generate.spectral`: a
`seed` (each of its `seeds`) from 0 to 2^32 − 1, `steps` from 1 to 64, and an output whose
sides are each at most 4096 with `width` · `height` at most 2^23 (`params_invalid`).
Its picture of `width` *w* and `height` *h* for a seed σ is computed byte by byte. The **base**
*B* is `generate(model, prompt, σ, steps, h, w)` of `wai.generate.spectral` with the performer's
model file and the opened prompt's text (the empty string where `prompt` is `null`), as
contribution §4.5 runs it. Each reference *i*, in the record's order, gives a picture *P*ᵢ of the
same size:
- an `image` of size *W*ᵢ × *H*ᵢ: *P*ᵢ(*x*, *y*) is the reference's pixel (*x* mod *W*ᵢ,
*y* mod *H*ᵢ), the reference tiled across the picture;
- an `adapter`: `generate(adapter, prompt, σ, steps, h, w)`, with the adapter's file, a model
file of `wai.generate.spectral`, in place of the performer's.
With *w*ᵢ the weights and *W* their sum, each byte of the picture is
```
⌊(B × (1 000 000 − W) + Σ wᵢ × Pᵢ + 500 000) / 1 000 000⌋
```
the same byte of *B* and of each *P*ᵢ. A `generate` step's output is the picture with its
`seed`; the member at position *k* of a `candidates` step's set is the picture with `seeds`[*k*];
an `inpaint` step's output is the picture at the input's size inside the region and the input
outside it (which contribution checks).
A verifier that holds the step, the performer's model file, the prompt's opening where `prompt`
is not `null`, the samples of every reference image of its stated size and the file of every
adapter computes each picture and compares it with the step's output: a state whose samples
digest differs, or a pixel inside an inpainting's region that differs, is
`conditioning_mismatch`. So a record that omits a work the step read, names one it did not, or
states another weight fails. Where any of these is not held, the step is not regenerated.
### 4.5 Each reference's terms and use
For each reference whose `terms` is not `null`, in order:
1. The terms are given, and so is the catalogue where `catalogue` is not `null`
(`record_missing`).
2. The terms' `work` is the reference's work: with `catalogue` `null`, its `kind` and `digest`
are the reference's `kind` and `work`; with a catalogue, its `kind` is `catalogue` and its
`digest` the catalogue's link hash, and the catalogue's `owner` is the terms' (otherwise
`terms_mismatch`); and the catalogue lists the reference's `work` (`not_in_catalogue`).
3. Where the verifier holds the step, the terms are in force at the step's `issued_at` (§3.2,
`terms_not_in_force`).
4. For each vocabulary the terms' usage statement carries, the reference's `usage` has an entry
(`usage_unanswered`); for each entry whose `term` is not `null`, the statement's preference
for it (ai-usage §3.2, §3.4, §3.5) is not disallow (`usage_disallowed`).
5. Where the verifier holds the step, its act is one of the terms' `acts` (`usage_disallowed`).
A use the terms disallow is refused whatever is paid for it: an attribution that rests on one is
refused, and so is a statement that pays from that attribution (§6.2). The two codes are
ai-usage §9's, raised here for the owner's terms as ai-usage raises them for a consumption claim.
A reference whose `terms` is `null` is checked against nothing: its work has no owner this record
names, and its share is `unowned`.
## 5. Attribution
### 5.1 The step map
Every sample of the output has a **step set**, `made_in`: the steps whose act produced its value.
It is computed as contribution §7.2 computes `made_by`, with each step in place of its performer,
so the performers of a sample's `made_in` are its `made_by`:
| act of step *s* | `made_in` of each sample of its output |
|---|---|
| `author`, `generate`; each member of `candidates` | {*s*} |
| `edit`, `inpaint` | inside the region {*s*}; outside it, the input's at the same pixel |
| `select` | the input's at the same pixel |
| `transform`, `replicate` | the union of the `made_in` of the input pixels its sample mapping reads (contribution §4.5) |
| `compose`, `replicate` | at a pixel an input covers, that input pixel's; at a canvas pixel no input covers, {*s*} |
| `transform` or `compose`, `attest` | {`unknown`} |
A state whose step the verifier does not hold gives every sample {`undisclosed`}; a `replicate`
`transform` or `compose` over an input whose size the verifier does not know gives
{`undisclosed`}. The markers are contribution §7.1's: never a step, and never credited.
### 5.2 The rule `wai-influence:share/1`
Each sample of the output is 1 000 000 **units**, and the **whole** is the number of samples
times 1 000 000. The rule divides the whole, in integers, and the shares always sum to it:
1. **Makers.** A sample's **makers** are its `made_in`: its steps in ascending `seq`, then
`unknown`, then `undisclosed`. Of *m* makers each takes ⌊1 000 000 / *m*⌋ of the sample's
units, and the first also takes the remainder. *U*(*x*) is what a maker *x* takes over all the
samples.
2. **Steps.** For each step *s* with *U*(*s*) above 0:
- performed by a human or an audience party: its **party** bucket takes *U*(*s*);
- performed by a model, with a conditioning record of *n* references: with weights, reference
*i* takes ⌊*U*(*s*) × *w*ᵢ / 1 000 000⌋; with none, each reference takes
⌊*U*(*s*) / (*n* + 1)⌋; the model takes what is left of *U*(*s*);
- performed by a model with no conditioning record: the model takes *U*(*s*).
3. **Buckets.** What a reference takes goes to the **owner** bucket of its terms (one bucket per
terms record, holding its owner's key), or, with `terms` `null`, to the **unowned** bucket of
its work. What a model takes goes to the owner bucket of the terms the attribution names for
that model party (§5.3), or to the unowned bucket of the model's digest. *U*(`unknown`) and
*U*(`undisclosed`) are buckets of their own.
So human-made samples go to the people who made them; a model's samples go, by the declared
weights, to the owners of what conditioned it, and the rest to the model's owner; a sample no
pinned rule fixes is `unknown`; and nothing goes to a party the rule does not name. With no
weights the rule's split is equal, the model counted as one share: the weights were not
declared, and the outcome says so (§8.3). A bucket with no units is not listed. An owner bucket
lists the works whose references gave it units.
### 5.3 The attribution record
The tool signs one **attribution** of an output, `kind` `"wai-attribution"`:
| member | type | meaning |
|---|---|---|
| `kind` | string | `"wai-attribution"` |
| `session` | 32 B hex | the link hash of the session record |
| `record` | 32 B hex | the link hash of the contribution record |
| `output` | 32 B hex | the content hash of the output's object: the record's `output.content_hash` |
| `samples` | integer | the output's samples, `width` × `height` |
| `rule` | term | `wai-influence:share/1` |
| `conditioning` | array | 0 to 256 link hashes of the conditioning records it reads, in strictly ascending order |
| `models` | array | 0 to 64 entries `{"party", "terms", "usage"}`: a model party, the link hash of the terms of the work that party names, and its use in §4.1's form; in strictly ascending order of `party` |
| `shares` | array | the buckets (below), in their order |
| `estimates` | array | 0 to 16 training-time estimates (§5.6) |
| `issued_at`, `signer_pubkey`, `sig` | | §2: the tool's key |
A bucket is one of:
- `{"bucket": "owner", "owner", "terms", "works", "units"}`: an owner's key, the link hash of its
terms, the digests of the works that gave it units in strictly ascending order, and its units;
- `{"bucket": "party", "party", "units"}`: a keyed party of the session, by position;
- `{"bucket": "unowned", "work", "units"}`: a work or a model with no owner named, by digest;
- `{"bucket": "unknown", "units"}` and `{"bucket": "undisclosed", "units"}`.
Each bucket's `units` is at least 1. The buckets are in this order: owner buckets by (`owner`,
`terms`), party buckets by `party`, unowned buckets by `work`, then `unknown`, then
`undisclosed`; no bucket twice. A record that breaks any of this is `record_malformed`. Its
shares sum to the whole, `samples` × 1 000 000 (`shares_not_whole`): a share is never given out
of nothing, and none is lost.
The rule is declared by name. This revision defines one rule, and a record naming another is
`rule_unknown`: a verifier recomputes shares only under a rule it holds.
### 5.4 Comparing the shares
The verifier computes the shares by §5.2 from the steps it holds and compares them with the
record's, bucket by bucket, when its computed shares hold no `undisclosed` units:
1. a computed `unknown` or `undisclosed` bucket with more units than the record's is
`unknown_attributed`: units no pinned rule fixes, credited to someone (contribution §7.1);
2. an owner bucket whose stated units exceed its computed units (0 where it has none) by exactly
the units of one or more of the record's estimates for that owner, an estimate of *p* parts
per million being *p* × `samples` units, is `estimate_mixed`;
3. any other difference, a bucket missing, added, of other units or of other works, is
`shares_mismatch`.
Where the computed shares hold `undisclosed` units, the record's shares are its signer's
statement: they are checked to sum to the whole and are not compared, because the split of the
undisclosed samples among makers is not fixed by what is disclosed. The tier of every bucket is
then `stated` (§5.5).
### 5.5 The tier of a use
Each held step has a tier:
- a step of `wai-influence:spectral-blend`: `recomputed` where this extension regenerated it
(§4.4), `checked` otherwise;
- any other step: `recomputed` where contribution reports it `checked` (for a generation of
`wai.generate.spectral`, regenerated), `checked` where it reports it `not-checked`, and
`stated` where it reports it `attested` (a generator or an operation the tool attests).
An owner bucket's **tier** is the lowest tier of the steps that gave it units, or `stated` where
the shares were not compared (§5.4). An owner's terms state the lowest tier at which a use of its
work stands (§3.2): an owner bucket below its terms' `attribution` is `attribution_not_met`. An
owner that requires `recomputed` is paid only for uses a verifier regenerated, works and weights
included; one that requires `stated` accepts the tool's statement.
The **tier of the outcome** is contribution §10.3's, with each step of
`wai-influence:spectral-blend` counted `checked` there when this extension regenerated it:
`recomputed` when every step behind the output is held and checked, `stated` when none is held,
`checked` otherwise. A policy's lowest tier (§8.1) is held to it (`tier_not_met`).
### 5.6 Training-time estimates
An **estimate** is `{"estimator", "class", "owner", "share_ppm"}`: a term naming the method, a
term naming its class (the family of methods it belongs to, such as an influence-function or a
leave-one-out estimate), an owner's key, and the share it estimates in parts per million, at most
1 000 000. It is the tool's statement with its class, as contribution §6's estimate and an
energy figure are: a verifier reports it as stated, beside the shares and never in them, and no
attribution line is computed from it. An owner bucket holding an estimate's units is
`estimate_mixed` (§5.4).
## 6. Payment
### 6.1 The basis
An accepted attribution is a **basis** for settlement's attribution lines (settlement §7.8),
named by its link hash. It gives: the output's content hash; the whole; and, for each owner
bucket, the owner's key, the bucket's units, and the terms' `per_use` and `share_ppm`. Party,
unowned, `unknown` and `undisclosed` buckets pay no one: a party's samples are its own share and
are paid outside this revision, a work with no owner has no payee, and units no rule fixes are
never paid to anyone. So every amount an attribution line states goes to an owner whose terms the
verifier checked, for units the rule gave it.
An owner is owed, per object class of the deliveries, `per_use` for each acknowledged delivery of
the output and `share_ppm` of the revenue of the output's paid bytes, in proportion to its units
over the whole: an owner whose terms set a per-use price is paid per use, and one whose terms set
a share is paid in proportion to its share of the output. The arithmetic, its rounding and its
remainder are settlement §7.8's.
### 6.2 A statement with attribution lines
A verifier of a statement ([settlement](settlement.md) §7) whose lines include attribution lines
is given the statement and settlement §8.1's inputs, and a list of influence cases (§8.1), the
**given attributions**. It runs these steps and stops at the first refusal:
1. It reads the statement (settlement §7.5), at `statement`.
2. **The bases.** For each payer of an attribution line, in the order the lines first name it, at
`basis` and its index *k*: a given attribution whose record's link hash is the payer is given
(`record_missing`); §8 accepts it (its refusal, at `basis`, *k*, then its own place); and each
owner bucket's terms name no currency or the statement's (`currency_mismatch`).
3. **The statement**: settlement §8.2 with those bases, with its reasons and places.
4. **What it leaves out.** Each other given attribution, in order, at `given` and its index:
§8 accepts it (its refusal, at `given`, its index, then its own place); and where it has an
owner bucket and its output is the content hash of an item of an acknowledgement the statement
settles, the statement names it in no line: `attribution_unsettled`.
So a statement cannot pay an owner from an attribution the verifier refuses: a disallowed use,
a share that does not recompute, and an owner whose required tier is not met each refuse it. Step
4 lets a party that holds an output's attribution check that a statement settling the output's
deliveries pays its owners; a statement settles the bases it names, and a verifier finds an
omitted one only where it holds it.
## 7. The transparency report
### 7.1 The record
For one owner and one statement, the statement's party signs a **report**, `kind`
`"wai-influence-report"`:
| member | type | meaning |
|---|---|---|
| `kind` | string | `"wai-influence-report"` |
| `owner` | 32 B hex | the owner reported to |
| `party` | 32 B hex | the statement's party, which signs it |
| `statement` | 32 B hex | the statement's digest (settlement §7.4) |
| `start`, `end` | integer | the statement's period |
| `outputs` | array | 0 to 1024 outputs, in strictly ascending order of `basis` |
| `amount` | integer | the sum of every line's `amount` |
| `issued_at`, `signer_pubkey`, `sig` | | §2: the party's key |
An output is `{"basis", "output", "whole", "buckets", "lines"}`: the basis's link hash, its
output's content hash and whole; the owner's buckets in it, 1 to 16 `{"terms", "works",
"units"}` in strictly ascending order of `terms`; and its lines, 1 to 4 `{"class", "deliveries",
"bytes", "revenue", "amount"}` in strictly ascending order of `class` (1 to 4): for the object
class, the deliveries and bytes of the owner's attribution line, the revenue *R* of settlement
§7.8, and the line's amount.
A report answers *was my work used, and what was I paid*: the outputs its works had units in, the
works, the units over the whole, the deliveries and the amounts. It names no other owner and no
other owner's units, terms or amounts, and no object but the outputs it lists.
### 7.2 Verifying a report
A report is verified in one of two ways, each stopping at the first refusal:
- **By the owner**, given the report and its own terms: the report reads and its signature
verifies (`record_malformed`, `bad_key`, `bad_signature`, at `report`), and its signer is its
`party` (`signer_mismatch`, at `report`); the terms read as §8.2 step 2 reads them, at `terms`
and its index; each bucket's terms are given (`record_missing`) and are the owner's
(`terms_mismatch`), at `report`, `output` and the output's index; and each line's `amount` is the sum over the buckets of `per_use` ×
`deliveries` + ⌊`revenue` × `share_ppm` × `units` / (1 000 000 × `whole`)⌋, and `amount` the sum
of the lines' (`report_mismatch`). The owner recomputes what it was paid from its own terms and
the report's figures.
- **By an auditor**, given also the statement with its inputs and its given attributions: after
the owner's checks, the statement passes §6.2 (its refusal at `statement`, then its place);
the report's `party`, `statement`, `start` and `end` are the statement's party, digest and
period (`report_mismatch`, at `report`); and the report's
outputs are exactly the statement's attribution lines whose payee is `owner`, grouped by basis,
with each basis's figures for the owner: a basis or a line missing is `report_incomplete`, and
any other difference `report_mismatch`, at `report`.
So the party cannot tell an owner it was paid for fewer deliveries, or not used, while settling
otherwise: an auditor holding the statement finds the difference.
## 8. Verification
### 8.1 Inputs
An influence **case** is: a contribution case (contribution §10.1), whose policy this extension
holds instead (below); the conditioning records it holds, the terms and the catalogues, each in a
list; and the attribution record. The reference images are among the contribution case's states,
named by their samples digests, and the adapter files among its model files, named by their
SHA-256. A **policy** has one member, `tier` (`stated`, `checked` or `recomputed`; default
`stated`), the lowest tier of the outcome it accepts.
### 8.2 Steps
The verifier runs these steps and stops at the first refusal, which it reports with its reason
and its place:
1. **Contribution.** Contribution §10.2 accepts the contribution case under a policy of `stated`:
otherwise its refusal, at `contribution` and then contribution's place.
2. **Reading** (§2, §3, §4.1, §5.3): each terms record, at `terms` and its index, each catalogue,
at `catalogue` and its index, each conditioning record, at `conditioning` and its index, and
the attribution, at `attribution`, read and their signatures verify (`record_malformed`,
`bad_key`, `bad_signature`); each terms record and catalogue is signed by its owner
(`not_signed_by_owner`).
3. **The attribution** (§5.3), at `attribution`: its `session` is the session's link hash
(`session_mismatch`); its signer is the tool (`signer_mismatch`); its `record` is the
contribution record's link hash, its `output` that record's `content_hash` (not `null`), and
its `samples` that record's `width` × `height` (`output_mismatch`); its `rule` is
`wai-influence:share/1` (`rule_unknown`); its shares sum to the whole (`shares_not_whole`); each
conditioning record it names is given (`record_missing`); and each `models` entry, at
`attribution`, `model` and its index, names a model party (`party_unknown`) and terms that are
given (`record_missing`).
4. **Each conditioning record** the attribution names, in its order, at `conditioning` and the
record's index: its `session` is the session's (`session_mismatch`) and its signer the tool
(`signer_mismatch`); where the verifier holds its step, §4.3 (`conditioning_unbound`,
`conditioning_invalid`) and, for the step's generator, §4.4's structure
(`conditioning_mismatch` for `wai.generate.spectral`; `conditioning_invalid`,
`params_invalid` for `wai-influence:spectral-blend`); each reference, at `reference` and its
index, §4.5 (`record_missing`, `terms_mismatch`, `not_in_catalogue`, `terms_not_in_force`,
`usage_unanswered`, `usage_disallowed`); and, where it holds what §4.4 reads, the
regeneration (`conditioning_mismatch`).
5. **Steps with no record**: each held step of `wai-influence:spectral-blend` has a record the
attribution names (`conditioning_missing`, at `step` and the step's index among the
contribution case's steps).
6. **Each `models` entry**, at `attribution`, `model` and its index: the terms' `work` is of kind
`prior` with the party's digest (`terms_mismatch`); §4.5 step 4 with the entry's `usage`
(`usage_unanswered`, `usage_disallowed`); and for each held `generate`, `candidates` or
`inpaint` step of that party, §4.5 steps 3 and 5 (`terms_not_in_force`, `usage_disallowed`).
7. **The shares** (§5.2, §5.4), at `shares`: `unknown_attributed`, `estimate_mixed`,
`shares_mismatch`.
8. **The owners' buckets**, each at `shares` and its index among the record's shares: its terms
are given (`record_missing`) and name its owner (`terms_mismatch`), and its tier meets their
`attribution` (§5.5, `attribution_not_met`). Where the shares were compared, the first two hold
by step 4.
9. **Policy**: an outcome below the policy's tier is `tier_not_met`, at `policy`.
### 8.3 What an accepted case states
- `tier` (§5.5), and `record` and `attribution`: the link hashes of the contribution record and
of the attribution (the basis);
- `conditioning`: for each record the attribution names, in its order, the step's `seq`; its
`status`: `recomputed` where §4.4 regenerated it, `checked` for a step of a pinned generator
not regenerated, `stated` for any other generator, `committed` where the step is not held; its
`weights`, `declared` or `equal`; and each reference's `work`, its owner's key or `null`, and
for each of its `usage` entries the preference of the owner's statement: `allow`, `unknown`,
`outside` for a `null` term, or `absent` where the statement does not carry the vocabulary or
the work has no terms;
- `shares`: the `computed` and the `stated` buckets, as §5.3 writes them, and `compared`, whether
§5.4 compared them;
- `owners`: for each owner bucket of the record, in its order, its `owner`, its `terms` and its
`tier` (§5.5);
- `estimates`: the record's, as stated.
A statement with attribution lines states, accepted, settlement §8.3's figures, its attribution
lines among them, and the link hashes of its bases, `bases`, in the order the lines first name
them. A report states, accepted, its `owner`, its `amount` and, for each output, its `basis` and
its `amount`.
## 9. Reasons
The codes this extension adds, each with where it is raised:
| reason | raised at |
|---|---|
| `not_signed_by_owner` | §3.2, §3.3, §8.2 step 2 |
| `rule_unknown` | §5.3, §8.2 step 3 |
| `shares_not_whole` | §5.3, §8.2 step 3 |
| `conditioning_unbound` | §4.3, §8.2 step 4 |
| `conditioning_invalid` | §4.3, §4.4, §8.2 step 4 |
| `conditioning_missing` | §4.4, §8.2 step 5 |
| `conditioning_mismatch` | §4.4, §8.2 step 4 |
| `terms_mismatch` | §4.5, §7.2, §8.2 steps 4, 6 and 8 |
| `not_in_catalogue` | §4.5, §8.2 step 4 |
| `terms_not_in_force` | §3.2, §4.5, §8.2 steps 4 and 6 |
| `estimate_mixed` | §5.4, §5.6, §8.2 step 7 |
| `shares_mismatch` | §5.4, §8.2 step 7 |
| `attribution_not_met` | §5.5, §8.2 step 8 |
| `currency_mismatch` | §6.2 step 2 |
| `attribution_unsettled` | §6.2 step 4 |
| `report_mismatch` | §7.2 |
| `report_incomplete` | §7.2 |
A verifier of this extension also raises contribution §11's `record_malformed`, `bad_key`,
`bad_signature`, `session_mismatch`, `signer_mismatch`, `output_mismatch`, `party_unknown`,
`params_invalid`, `unknown_attributed` and `tier_not_met` at the places above; ai-usage §9's
`usage_unanswered` and `usage_disallowed` for the owner's terms (§4.5); live-metering §9's
`record_missing` for an input not given; every code of contribution §11 at `contribution`; and,
for a statement, every code settlement §11 raises and reuses, at settlement's places.
## 10. Conformance
[`live-conformance/influence/`](../live-conformance/influence/) holds the corpus, in one file,
`vectors.json`, written from fixed seeds by `wai_influence_vectors gen`. It holds the model files
its sessions generate with (the model file of `wai.generate.spectral`'s conformance vector, and a
second model file written from it that is an owner's style model and adapter), and:
- **cases**, each an influence case and the outcome §8.3 gives it. **Accepted**: a generation
conditioned on an owner's reference image, regenerated, then a person's brush edit, the shares
divided between the person, the image's owner and the model; candidates conditioned on an
owner's adapter and on a work of another owner's catalogue, each regenerated with its seed,
one selected by an audience member and colour-graded; a drawing composed with a layer an
owner's style model generated, the model's samples paid to its owner and the canvas fill to the
arranger; an inpainting by an attested model conditioned on a taste prior and on an image with
no owner, with no weights, the split equal and stated; a conditioned generation behind an
attested scaling, whose samples are `unknown`; the same inpainting with the drawing's step
undisclosed, the shares stated; and an attribution with a training-time estimate beside its
shares. **Refused**: each reason of §9 and each code it reuses, each a control of one defect,
among them a conditioning reference omitted where the regeneration needs it, a reference named
for a generation of the exact generator, a use the owner's terms disallow, shares that do not
sum to the whole, an estimate mixed into an owner's share, the `unknown` samples given to the
tool's own terms, a share that does not recompute, and an owner's required tier not met.
- **statements**, each a settlement statement with its inputs and given attributions and the
outcome of §6.2: **accepted**, a publisher's statement with its delivery lines and an
attribution line for each owner of two outputs; **refused**, an attribution line whose amount
does not recompute, one that states more deliveries than were acknowledged, an owner's line
left out, a basis not given, a basis whose use the owner's terms disallow (a disallowed use
paid), a tariff in another currency, and an output's deliveries settled with no line for its
owners.
- **reports**, each verified by the owner or by an auditor: **accepted**, an owner's report of
two outputs, verified both ways; **refused**, a report that leaves an output out, one whose
amount does not recompute, and one signed by another key.
A conforming verifier gives every case, statement and report the outcome, the reason, the place
and the statements the corpus states. `wai_influence_vectors verify` and the test
`tests/influence.rs` check that the file regenerates byte for byte, that `wai-rs` gives every
vector its outcome, that every reason of §9 and every code it reuses refuses a vector, and that
§9 lists exactly the reference's codes. `live-conformance/influence_verify.py` is the second
implementation, written from this text: it shares no code with `wai-rs`; it verifies the
contribution case with the contribution corpus's second implementation
(`contribution_verify.py`), runs the generator of §4.4 with that implementation's arithmetic,
reads usage statements with `ai_usage_verify.py` and statements with `settlement_verify.py`,
verifies every signature with WAI's strict rule (`claim-conformance/_ed25519.py`) and every link
hash with `claim-conformance/_blake3.py`, computes every share, line and report itself, mutates
copies of the corpus and requires every copy to fail, and drops each of its own checks in turn
and requires the corpus to catch the weakened verifier.
## 11. Security and privacy considerations
- **What is exact and what is stated.** A reference is exact where the generator is pinned: the
step regenerates only from the works it names, at the weights it states. For any other
generator the record is the tool's statement of what it loaded, signed and bound to the step by
its link hash, and the tier of the use says so. An owner chooses the tier it requires (§5.5).
- **Omission.** A tool that leaves a work out of a step of the pinned generator fails the
regeneration. For another generator, leaving a work out is a false statement the record keeps:
the step is fixed by the root, the attribution names the records it reads, and the use is
`stated`. A statement can leave a basis out; an auditor holding the attribution finds it
(§6.2 step 4).
- **Unknown is never paid.** Units a rule cannot fix are `unknown` or `undisclosed`, and the
comparison refuses them credited to a bucket, the tool's own among them (§5.4). Work with no
owner is `unowned`, by digest: anyone who owns that work can see its units, and publish terms.
- **Estimates.** A training-time estimate is noisy, and its class says of what kind. It is
reported, never added to a share and never paid here.
- **Owners are keys.** Terms and catalogues bind a work to a key by that key's signature only, so
no tool can present terms as an owner's that the owner did not sign. Two keys may sign terms for
one work; this extension states which terms a reference named and decides nothing between them.
- **What a report reveals.** An owner's report gives its own buckets, the whole, and the output's
deliveries, bytes and revenue, and names no other owner. An auditor holding the statement and
its bases learns every owner's shares and amounts of those outputs, as settlement §13 says of a
party verifying a statement. A session names its parties by keys and digests, and prompts stay
salted commitments (contribution §8.1).
- **Not a judgment.** A share is a count of samples under a declared rule, and an amount is that
count at a tariff; neither says what a work is worth or whether a use was lawful.