Skip to main content

WAI Extension: Co-performance

Mirrored from the canonical text at commit b1681667 ().

Status: Draft. Registers the record wai.live.coperformance: people and AI participants performing together in a room, and an audience joining in. A participant publishes an intent: the material it means to play next, ahead of the instant it plays, by the digest of an object or as a symbolic form (notes, a text line, a camera move), so the others can see what it is about to do. When the material plays, a verifier compares what played with what was announced, under a pinned rule, and a room key signs a fidelity statement: per participant, how many intents it announced and how many it kept, which anyone holding the room recomputes. A turn schedule says who holds the floor and for how long, in microseconds or in bars at a stated tempo, as solo turns or call-and-response pairs, and a handover passes the floor within a turn; an object a performer publishes outside its turn is refused by the relay or marked by the room clock, as the schedule states, and an object that arrives later than its grant’s latency budget is marked, never mixed unmarked. An audience member whose grant carries the audience-input power submits signed inputs (a prompt, a sketch or a movement sample by digest, a vote) to a selection window; the room clock commits to the inputs once the window closes, a declared rule (a plurality vote, the top inputs by reactions, or a draw from a seed committed before the window opened) selects from what was committed, and every selected input is credited to the member who sent it. All of it rides in the room’s events, as meta payloads that the room’s authors sign, under one room-level co-performance policy, WPP1, that the room authority signs. No new transport. The reference implementation is the co_performance module of wai-rs (feature co_performance); the corpus is live-conformance/coperformance/, and its second implementation is live-conformance/co_performance_verify.py. Keywords MUST, MUST NOT, SHOULD, MAY are RFC 2119/8174.

Texts read for this revision: the live family this extension builds on, as merged (live-events, live-rooms, live-compose, live-metering, live-moderation, synthesis §8 and ai-usage); RFC 8032 and FIPS 180-4. No outside text is pinned: the rules of this extension are WAI’s own.

1. Scope

In scope: the co-performance policy, its signature and the policy in effect at each instant (§3); how this extension’s statements ride in a room’s events, who may sign each, and the grant attributes it reads (§4); intents, the forms they plan, what played, the pinned rules that compare the two, and the fidelity statement (§5); turn schedules, handovers, the floor, refusal and marking, latency budgets and marks (§6); audience inputs, their windows, the commitment, the selection rules, the selection and its credits (§7); where each rule is enforced (§8); and verification (§9).

Out of scope: a transport; how a participant decides what to play, and how a model produces it; how a performer transcribes what it played into a symbolic form (§5.4 compares the forms it is given); how a sink renders an intent, a schedule or a mark; the contribution record that credits a work’s makers sample by sample, which is a separate extension, wai.media.contribution, whose slot §7.8 names; and the review of what an audience submits, which is live-moderation’s (§7.4).

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

Relationship to live-events: this extension changes nothing in it. Its statements are payloads of the meta kind (§4.2 there), which live-events leaves to applications, as live-moderation’s statement is, so every statement is signed by its author, chained, stamped with the room clock and rate-bounded by its author’s policy (live-events §5, §6). An audience member’s reaction to an input is a reaction event (§4.5 there) whose target is the input’s digest; a moderator’s verdict on an input is a decision event (§4.11 there).

Relationship to live-rooms: the room descriptor’s and the grant’s layouts are unchanged. A room states its co-performance policy in a record of its own, WPP1 (§3), chained like the review policy of live-moderation §3.4 and the room usage record of ai-usage §4.2. The audience-input power and the latency budget are grant attributes (§4.4), which live-rooms §4.4 signs with the grant and leaves to the extensions that read them; a new power bit would be refused by every room verifier of the current revision (live-rooms §3.4: no power above bit 4). The direct power (live-rooms §3.3, bit 1) is the power to sign a schedule, a handover or a window.

Relationship to synthesis §8 and live-rooms §4.4: an AI participant is marked in its grant, its chat, reactions and captions state their machine origin, and its tracks are synthesized media. Its intents are meta events and carry no origin of their own: the grant in effect at their t says whose they are.

2. Terms

Integers are little-endian; a signed integer is two’s complement. A digest is SHA-256 (FIPS 180-4), 32 bytes. Ed25519 is RFC 8032’s, verified strictly (SPEC §7 Signatures): a key that fails step 1 or 2 is bad_key, and a signature that fails a later step is bad_signature. µs is microseconds of room clock.

3. The co-performance policy

3.1 Layout

fieldsizemeaning
magic4WPP1 (ASCII)
version11 in this revision
room32the room id (live-rooms §3.2)
prev32the digest of the policy this one replaces (§3.4); 32 zero bytes for the first
effective8u64: the room-clock instant from which this policy applies; 0 for the first
horizon_ms4u32: how far ahead of its own t an intent may reach (§5.3), above 0
window_ms4u32: the match window (§5.4): how far from its planned instant material may play and still be the intent’s, above 0
time_tol_us4u32: the timing tolerance of the notes rule (§5.5)
angle_tol_mdeg4u32: the angle tolerance of the camera rule (§5.5), in thousandths of a degree
modes1the turn modes a schedule may state (§6.5): bit 0 refuse, bit 1 mark; at least one, no other bit
sig64§3.2

3.2 Digest and signature

The digest of a policy is SHA-256 over its record from magic through modes. The signature is Ed25519 by the room descriptor’s authority over the 26 bytes wai:co-performance-policy (ASCII) and 0x01, followed by the bytes the digest covers.

3.3 Reading and rules

A reader reads exactly the bytes it is given as one policy, in the order of §3.1, and refuses at the first of these that holds:

  1. Fewer than 4 bytes: truncated. A magic other than WPP1: malformed. No byte after the magic: truncated. A version other than 1: unknown_version.
  2. The bytes end before a field the layout requires: truncated.
  3. Bytes after sig: malformed.

It then holds the policy to these rules, and refuses one that breaks any of them as co_policy_malformed: horizon_ms and window_ms are above 0, and modes is 1, 2 or 3. Then its room is the room id (wrong_room), its signature verifies (bad_key, bad_signature), and its link holds (§3.4, co_policy_unlinked).

3.4 The policy in effect

A verifier is given a room’s policies in a list. The first has prev zero and effective 0. Each later one has as prev the digest of the one before it in the list, and an effective above that one’s. A policy that breaks this is refused co_policy_unlinked. The policy in effect at room-clock instant t is the last of the list whose effective is at or below t.

A policy is replaced, never amended. A statement is read under the policy in effect at its event’s t, and an intent is compared (§5.4) under the policy it was announced under. A statement of this extension at an instant with no policy in effect is refused co_no_policy.

4. Statements

4.1 Carriage

magicstatementsectionwho signs it
WPI1intent§5.1any principal of the room
WPF1fidelity statement§5.6a room key
WPT1turn schedule§6.1a room key, or a principal whose grant in effect has the direct power
WPH1handover§6.3the holder of the turn, a principal with the direct power, or a room key
WPM1mark§6.7a room key
WPW1selection window§7.2a room key, or a principal with the direct power
WPA1audience input§7.3an audience member
WPK1commitment§7.5a room key
WPS1selection§7.7a room key

Each statement is the payload of a meta event: its magic, a version byte of 1, and the fields its section lists. A meta payload whose first four bytes are none of these magics is not this extension’s, and a sink that does not implement it shows none of them: they are timed metadata for its application (live-events §4.2). Every statement is bounded by its author’s policy (live-events §5, max_payload), 1024 bytes for a room key, which bounds the counts each section allows.

4.2 Reading

A statement that ends before a field, that holds bytes after its last field, whose version is not 1, or whose field holds a value its section does not allow, is co_statement_malformed. A text field that is not UTF-8 is co_statement_malformed.

4.3 Who signs

A statement whose author is not one the table of §4.1 allows is co_not_permitted, but for a handover, whose author §6.3 checks once it has found the turn (handover_not_holder), and an audience input (input_not_permitted, §7.3). The direct power is that of the author’s grant in effect at its event’s t (live-rooms §9.2 step 4); a room key holds every power. Since a statement is a meta event, the room verifier has already held it to its author’s grant: a principal whose policy does not permit meta cannot send one (live-rooms §9.2 step 4, kind_not_permitted).

4.4 Attributes

This extension reads two grant attributes (live-rooms §4.4):

keyvaluemeaning
audience_inputa decimal integer from 1 to 255the audience-input power: the principal may submit inputs (§7.3), at most this many to one window
latency_budget_msa decimal integer from 1 to 600 000the principal’s latency budget (§6.6)

A decimal integer is 1 to 6 of the digits 0–9, the first not 0. A grant whose attribute of either key is not of its row is refused co_attr_malformed. A grant without audience_input gives no audience-input power; one without latency_budget_ms gives no budget. The authority states a budget per role by giving every grant of the role the same value; an AI participant’s role is where it matters most, since its output is computed and may be late.

5. Intents

5.1 The intent

fieldsizemeaning
magic, version5WPI1, 1
track32the track the material plays on (§2); 32 zero bytes for a text intent
at8u64: the room-clock instant the material plays from
span4u32: how long it lasts, in µs from at, above 0
form11 object, 2 notes, 3 text, 4 camera
body…by form (§5.2)

An intent’s author is its event’s principal, and its horizon is the stretch from its event’s t to at + span: what it says about the time ahead. The intent track of a participant is its intents in its events track (live-rooms §6.1): every subscriber of the room that subscribes to that track receives each intent when it is sent, before the material it announces plays.

5.2 Forms

track is zero exactly for a text intent. A form outside 1 to 4, a body that does not read as its form says, and a track that breaks the rule, are co_statement_malformed.

The bodies of forms 2 and 4 are also the symbolic payloads a performer publishes: an object whose payload is a notes body (the count and the notes, with no at) or a camera body (12 bytes) states in symbols what it played (§5.4).

5.3 Rules

An intent is announced ahead, and for a short horizon:

  1. at is above its event’s t: otherwise intent_not_ahead.
  2. at + span − t is at most horizon_ms × 1000 of the policy in effect at t: otherwise intent_beyond_horizon.

5.4 What played

The intent’s window is window_ms × 1000 µs of the policy in effect at its event’s t. Its candidates are:

What played is the candidate nearest at, by |due − at| or |t − at|, and of two equally near, the first of the objects given, or the first event in the merged order. With no candidate the intent was missed. Otherwise it was kept when what played matches it under its form’s rule (§5.5), and diverged when it does not.

For forms 2 and 4 the rule reads the played object’s payload, which the verifier is given by its digest (§9.1). A played object whose payload is not given is payload_missing, at the intent: what played cannot be compared.

5.5 The pinned rules

time_tol_us and angle_tol_mdeg are those of the policy in effect at the intent’s t. A payload that does not read as the form is a diverged intent, not a malformed one: the object is media, and it did not play what was announced.

5.6 The fidelity statement

A room key states, per participant, how often it did what it said it would:

fieldsizemeaning
magic, version5WPF1, 1
through8u64: the room-clock instant it is stated through, at or below its event’s t
count1u8: the entries
entries52 × neach: principal (32), announced, kept, diverged, missed (u32 each)

A fidelity statement whose through is above its event’s t, or whose entries are not in strictly ascending order of principal, is co_statement_malformed.

It covers the intents before it whose at plus their window is at or below through, and it reads them as of its own instant: their candidates are the objects whose arrival is at or below its event’s t, and the events before it. Its entries are, in ascending order of principal, every author of a covered intent, with the number it announced and the number of each outcome. A verifier recomputes the entries from the room; a statement whose entries differ, in any principal or any count, is fidelity_mismatch. A participant kept k of a intents: a fraction a sink may show beside it, as two integers.

6. Turns

6.1 The schedule

fieldsizemeaning
magic, version5WPT1, 1
t08u64: the room’s t0 (live-rooms §3.1), for a relay that holds no descriptor (§8)
from8u64: the instant from which this schedule governs
mode11 refuse, 2 mark (§6.5)
beat_us4u32: µs per beat, the tempo; 0 when lengths are in µs
beats_per_bar1u8: 1 to 32 when beat_us is above 0; 0 otherwise
segments1 + …a u8 count (1 to 4), then each segment: start (u64), length (u32), turns (u16, 1 to 1024), pairs (u8, 0 or 1), holders (a u8 count, 1 to 4, then each holder’s key, 32 bytes)

A segment’s turn length L is length µs when beat_us is 0, and length × beats_per_bar × beat_us µs otherwise: length bars at the stated tempo. A schedule is co_statement_malformed when: t0 is not the descriptor’s; mode is not 1 or 2; beat_us and beats_per_bar break their rule; a segment’s L is 0; a segment starts before from, or before the end of the segment before it (its start + turns × L); an end does not fit a u64; two holders of a segment are one key; or a segment with pairs 1 has an odd number of turns or one holder. Then: from is at or after its event’s t, since a schedule never changes the past (schedule_retroactive); and mode is one the policy’s modes allows (mode_not_allowed).

The schedule in effect at instant x is, of the schedules the room holds whose from is at or below x, the last in the merged order. A later schedule replaces an earlier one from its from on.

6.2 Turns and pairs

Turn i of a segment, from 0, runs from start + i × L up to, but not including, start + (i + 1) × L, and its scheduled holder is the segment’s holder i mod n, of its n holders. The holders of a segment take turns in order, so two holders trading four-bar phrases at 120 beats a minute are one segment: beat_us 500 000, beats_per_bar 4, length 4, two holders.

In a segment with pairs 1, turn 2j is a call and turn 2j + 1 its response: the next holder answers what the call played. A verifier states each pair. The floor (§6.4) is held the same way in either.

6.3 Handovers

fieldsizemeaning
magic, version5WPH1, 1
at8u64: the instant the floor passes, at or after its event’s t
to32the principal that takes it

A handover passes the turn that holds at, under the schedule in effect at at of those before it, to to, from at to the turn’s end; the schedule’s next turn is unchanged. It is handover_invalid when at is before its event’s t, when no turn of the schedule in effect holds at, or when to is not a holder of that turn’s segment. Its author is the turn’s holder at at (below), a principal with the direct power, or a room key: otherwise handover_not_holder.

The holder of a turn at instant x is the to of the handover into that turn whose at is the latest at or below x (of two at one at, the later in the merged order), or its scheduled holder when there is none.

6.4 The floor

A segment governs its holders while it runs. An object of principal P is out of turn when, at its arrival, the schedule in effect has a segment that is running and whose holders include P, and the turn running then is held, at that instant, by another principal. An object of a principal no running segment names, or that arrives while no segment runs, is not governed: the floor is open. An accompanist that plays under every turn is left out of the holders.

The floor governs the objects of performers’ media tracks. It does not govern events: a principal’s intents and chat stay its own to send.

6.5 Refuse or mark

A schedule’s mode says what happens to an out-of-turn object:

Which to state is the room’s, through its policy’s modes and each schedule’s mode. Refuse fits an exchange where the floor is the point: timed spoken turns, a game’s moves. Mark fits music: a pickup that starts before the bar line, or a phrase that rings past it, is part of the music, and dropping it would cut the performance where the overlap is the performance; the mark keeps the overlap visible and leaves a mixer to decide.

6.6 Latency budgets

An object of principal P is late when its arrival is after its due instant by more than P’s budget: latency_budget_ms × 1000 µs of the grant in effect for P at the object’s arrival (§9.1). The relay, or the room clock acting for the room, MUST mark a late object (§6.7) before it is mixed: a late object is forwarded with its mark, and a mixer that holds the mark decides whether the object is still of use. A compositor (live-compose §7) MUST NOT mix an object it knows to be late without the mark, and a sink that mixes locally takes the same mark. A late object is never mixed unmarked.

6.7 Marks

fieldsizemeaning
magic, version5WPM1, 1
track32the object’s track
group, object8 eachu64: its group and object ID
flags1bit 0: out of turn; bit 1: late; at least one, no other bit

A mark is the room clock’s, signed as it forwards the object. A verifier checks it against the objects it is given (§9.2 step 7): the object it names is one of them, and each flag it sets holds of that object. Otherwise mark_unfounded. A mark can be no accusation the room’s own records do not support.

7. Audience co-creation

7.1 The audience-input power

A principal is an audience member while its grant in effect carries audience_input (§4.4). Its grant’s event policy permits meta, and, to react to inputs, reaction; the policy’s rate windows (live-events §6.3) bound its inputs as they bound every event, and audience_input bounds how many it submits to one window (§7.3).

7.2 Selection windows

fieldsizemeaning
magic, version5WPW1, 1
rule11 plurality, 2 reactions, 3 draw (§7.6)
types1the input types it takes: bit 0 prompt, bit 1 sketch, bit 2 vote, bit 3 movement
options1for rule 1, the number of options, 2 to 32; otherwise 0
k1how many it selects, 1 to 8
close8u64: the instant it closes, above its event’s t
seed_commit32for rule 3: SHA-256 over the 24 bytes wai:co-performance-seed (ASCII) and 0x01 and the 32-byte seed; otherwise 32 zero bytes
questiontextwhat it asks, 0 to 500 bytes

A window of rule 1 takes votes alone (types 4); one of rules 2 and 3 takes any of prompts, sketches and movement samples, and no vote. A window is co_statement_malformed when it breaks these rules, when its rule, options, k, seed_commit or question is outside what the table allows, or when its close is not above its event’s t. A window is named by the digest of its event.

7.3 Inputs

fieldsizemeaning
magic, version5WPA1, 1
window32the window’s digest
type11 prompt, 2 sketch, 3 vote, 4 movement
body…a prompt: a text field of 1 to 500 bytes; a sketch or a movement sample: the digest (32) of the object that holds it; a vote: option (u8)

An input is checked, in this order:

  1. its author is an audience member at its t: otherwise input_not_permitted;
  2. window names a window before it: otherwise window_unknown;
  3. its type is one the window takes, and a vote’s option is below the window’s options: otherwise input_type_mismatch;
  4. counting it, its author has sent at most audience_input inputs naming that window: otherwise input_over_limit.

A relay MUST NOT forward an input these checks refuse, nor one naming a window whose commitment (§7.5) it has forwarded: the commitment fixed the window’s inputs, and an input the room holds before the commitment in the merged order, with a t below close, is one it counts (§7.5, commit_mismatch). A relay holds an input to these rules with the grant its author’s session proved (live-rooms §10.5) and the windows and commitments of the events tracks it forwards, and withholds an input it refuses, as live-moderation §8.1 withholds a record: never replaced, so its author’s chain shows the gap. An input whose t is at or after the window’s close is not refused: it was in flight when the window closed, and it is not eligible (§7.5). A sketch’s or a movement sample’s object is published as any object of the room, under the member’s grant; the input names it, and a performer that uses it fetches it by that name.

7.4 Moderation

Live-moderation applies to inputs as to any meta event: a review policy may hold them for review (its §6.1), and a moderator decides on them (its §4). An input or a reaction is restricted at an instant when, of the decision events the room accepted before that instant whose target is its digest, the last denies or redacts it (live-events §4.11; live-moderation §4.5 keeps that decision the standing one of its line). A restricted input is not eligible, and a restricted reaction is not counted.

7.5 The commitment

Once a window has closed, a room key commits to its inputs, before any rule runs:

fieldsizemeaning
magic, version5WPK1, 1
window32the window’s digest
count4u32: the eligible inputs
root32SHA-256 over the 26 bytes wai:co-performance-commit (ASCII) and 0x01, window, count (u32), and each eligible input’s digest in the merged order

The eligible inputs of a window are the inputs naming it that the room accepted, with a t below close, that are not restricted at the commitment. A commitment is checked: window names a window before it (window_unknown); its t is at or after close (commit_early); the window has no commitment before it (statement_repeated); and its count and root are those of the eligible inputs (commit_mismatch). The commitment fixes the set a rule runs over before the rule runs, so no input can be added or removed after the outcome is known; for a draw, the seed was committed when the window opened, before any input (§7.2).

7.6 The rules

Each rule is a function of the window, the eligible inputs, and the room’s events before the commitment:

A selection holds fewer than k when fewer are eligible (or, for plurality, fewer options were voted for).

7.7 The selection

fieldsizemeaning
magic, version5WPS1, 1
rule1the window’s rule, 1 to 3, so that the selection reads on its own
window32the window’s digest
commit32the digest of the window’s commitment
seed32for a draw, the seed; otherwise 32 zero bytes
picks1 + …a u8 count, then each pick: for plurality, an option (u8); otherwise an input’s digest (32)
credits1 + 69 × ma u8 count, then each credit: step (u8, 1 or 2), party (32), ref (32), count (u32) (§7.8)

A selection is checked, in this order:

  1. window names a window before it (window_unknown); it is the window’s first selection (statement_repeated); and commit is the digest of the window’s commitment, before it (selection_uncommitted).
  2. For a draw, SHA-256 over wai:co-performance-seed, 0x01 and seed is the window’s seed_commit (seed_mismatch); for the other rules seed is zero (co_statement_malformed).
  3. No pick names an input whose t is at or after close: such an input was submitted after the window closed, and a selection that counts it is input_late.
  4. Its rule is the window’s, and its picks are that rule’s selection over the committed inputs (§7.6), in its order: otherwise selection_mismatch.
  5. The credits are one per pick, in the picks’ order (§7.8). A pick with no credit is input_uncredited; a credit that is not the one its pick gives, or one past the last pick, is credit_mismatch.

7.8 Credit and the contribution slot

Every input that reaches the performance is credited, and a selection is where it reaches it:

The contribution slot. A contribution record (wai.media.contribution, a separate extension) credits the makers of a piece of media by party and by step. Each credit here maps onto it: an author credit onto a party of role audience with the member’s key and a step whose act is author, over the material its ref names; a direct credit onto a step whose act is direct, on behalf of the members its party names. This revision writes no contribution record and depends on none; the credit is complete without one, and a record that cites a selection takes its parties from these fields.

8. Where each rule is enforced

After the fact, a verifier (§9) checks every one of these against the room: a relay that forwarded an out-of-turn object under refuse, a clock that left one unmarked, or one that marked an object that was neither, is found out.

9. Verification

9.1 Inputs

A co-performance verifier is given what a room verifier is given (live-rooms §9.1: a descriptor, grants, a key-log head or none, and the chains), and:

The grant in effect for a principal at an instant, for an object, is the grant of its last join or grant_exchange at or before that instant, unless a leave of it follows, when it has none (live-rooms §7.2).

9.2 Steps

It runs these steps and stops at the first refusal, which it reports with the reason and where:

  1. The room (live-rooms §9): a refusal, at room with the room verifier’s own place. A gap is not a refusal; the steps go on, and those that recompute from the whole room are not made (below).
  2. The policies, in the list’s order (§3.3, §3.4): at the policy’s index.
  3. The grants’ attributes (§4.4), in the grants’ order: at the grant’s index.
  4. The statements, in the merged order: each meta event the room accepted whose payload begins with a magic of §4.1, by its section: §4.2, then §3.4 (co_no_policy), then §4.3, then the rules of its section, in the order each section gives. A commitment, a selection and a fidelity statement are recomputed at their place in the merged order. At the record.
  5. The intents (§5.4), in the merged order: each one’s outcome, and payload_missing, at the intent’s record.
  6. The objects, in the order given: out of turn under refuse (turn_violated); out of turn under mark without a mark that sets bit 0 (turn_unmarked); late without a mark that sets bit 1 (late_unflagged). At the object’s index.
  7. The marks, in the merged order (§6.7): mark_unfounded, at the record.
  8. The outcome (§9.3).

With a gap, step 4 does not check a commitment’s count and root (commit_mismatch), a selection’s picks and credits (step 3 onward of §7.7), or a fidelity statement’s entries: each depends on events the verifier may not hold. Every other check is made, over what it holds.

9.3 Outcomes and what a verification states

With accept or gap, the verifier states:

10. Reasons

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

reasonraised at
co_policy_malformed§3.3
co_policy_unlinked§3.4
co_no_policy§3.4, §9.2 step 4
co_attr_malformed§4.4, §9.2 step 3
co_statement_malformed§4.2, §5.2, §5.6, §6.1, §7.2, §7.7 step 2
co_not_permitted§4.3
intent_not_ahead§5.3
intent_beyond_horizon§5.3
payload_missing§5.4, §9.2 step 5
fidelity_mismatch§5.6
schedule_retroactive§6.1
mode_not_allowed§6.1
handover_invalid§6.3
handover_not_holder§6.3
turn_violated§6.5, §9.2 step 6
turn_unmarked§6.5, §9.2 step 6
late_unflagged§6.6, §9.2 step 6
mark_unfounded§6.7, §9.2 step 7
input_not_permitted§7.3 step 1
window_unknown§7.3 step 2, §7.5, §7.7 step 1
input_type_mismatch§7.3 step 3
input_over_limit§7.3 step 4
statement_repeated§7.5, §7.7 step 1
commit_early§7.5
commit_mismatch§7.5
selection_uncommitted§7.7 step 1
seed_mismatch§7.7 step 2
input_late§7.7 step 3
selection_mismatch§7.7 step 4
input_uncredited§7.7 step 5
credit_mismatch§7.7 step 5

A co-performance verifier also raises every code a room verifier raises (live-rooms §11 and the live-events codes it lists), at the room; truncated, malformed and unknown_version for a policy that does not read; wrong_room, bad_key and bad_signature for a policy of another room or whose signature fails; and delivery_gap for a gap, which is not a refusal.

11. Conformance

live-conformance/coperformance/ holds the corpus, in one file, vectors.json, written from fixed seeds by wai_co_performance_vectors gen. It has rooms, each a room (descriptor, grants, key-log head or none, chains), its policies, objects and payloads, and the outcome §9.3 gives them with everything it states:

A conforming verifier gives every room the outcome, the reason, the place, and everything else the corpus states. wai_co_performance_vectors verify and the test tests/co_performance.rs check that the file regenerates byte for byte, that wai-rs gives every room its outcome, that every reason of §10 appears, and that §10 lists exactly the reference’s codes. live-conformance/co_performance_verify.py is the second implementation, written from this text: it shares no code with wai-rs; it verifies each room with the live-rooms corpus’s second implementation (live_rooms_verify.py) and every signature with WAI’s strict rule (claim-conformance/_ed25519.py); and it mutates copies of the corpus and requires every copy to fail.

12. Security and privacy considerations