Fixture format handoff-v0-fixture/1 (SPEC-v0.r81a §15). One JSON file per case. The base set has 256 cases (verify 141, canon 87, digest 7, text 3, render 5, ed25519 13); the profile extension (§15A, last part of the table below) adds 14 cases that are counted apart. Every key in these files is a TEST-ONLY key, published deliberately (TEST-KEYS.json); never use one for a real record.
Conformance (§15): a verifier MUST reproduce everything listed in the conformance paragraph of §15: for verify fixtures expect.result; expect.code among its findings of the matching level; no code in expect.absent_codes; and expect.time_bounds, expect.detect_classes, expect.required_codes, expect.finding_text and expect.error_text when present; for render fixtures the expect members present (result, cli_exit, banned_matches, time_bounds_form). reject_codes, detect_codes and error_codes list everything the reference reports; other_codes are warnings, info and status (informative). The reference runner compares those arrays exactly and in order, as a self-check of the reference; a verifier that differs there can still conform. server = REFUSE where a server must refuse the write. Three exports (V53-1, V53-3, V53-4) are given as generator rules (inputs.export_gen, §15) instead of literal bytes.
| Vector | Fixture | Kind | File | Expected | Code | Spec § | Server | Case |
|---|---|---|---|---|---|---|---|---|
| V01 | V01-1 | verify | verify/V01-1.json | ACCEPT | §10, §11.2 | Base record (COMMIT, CONFIRM, DELIVER, ACCEPT; all in head 1), unchanged | ||
| V02 | V02-1 | verify | verify/V02-1.json | REJECT | SIG_W_INVALID | §4.8, §10.6-7 | Base with one hex digit of DELIVER.body.evidence[0].value changed; signatures unchanged (S_w fails at seq 2, prev_hash b | |
| V03 | V03-1 | verify | verify/V03-1.json | REJECT | SIG_W_INVALID | §4.8, §10.6 | As V02, and ACCEPT.prev_hash recomputed over the changed DELIVER; signatures unchanged | |
| V04 | V04-1 | verify | verify/V04-1.json | ACCEPT | §9.4, §10.11 | Insider rewrite: a second history with different DELIVER evidence, re-signed by K_w; no held head (ACCEPT is inherent) | ||
| V04 | V04-2 | verify | verify/V04-2.json | DETECT | HEAD_EQUIVOCATION | §9.4, §10.11 | Insider rewrite verified against heads 0-1 held earlier (--known-heads): same n, different roots | |
| V05 | V05-1 | verify | verify/V05-1.json | REJECT | R1_SEQ | §4.6, §5.2-5.3 | Base with DELIVER and ACCEPT swapped (seq numbers no longer match positions) | |
| V05 | V05-2 | verify | verify/V05-2.json | REJECT | PROOF_INCLUSION | §4.6, §5.2-5.3 | Swapped and renumbered, both re-signed by K_w (prev_hash chain breaks) | |
| V05 | V05-3 | verify | verify/V05-3.json | REJECT | PROOF_INCLUSION | §4.6, §5.2-5.3 | Swapped, renumbered, prev_hash recomputed and re-signed (the G1 table refuses ACCEPT before DELIVER) | |
| V06 | V06-1 | verify | verify/V06-1.json | REJECT | R1_SEQ | §4.6, §10.7 | Base with the DELIVER event dropped | |
| V06 | V06-2 | verify | verify/V06-2.json | REJECT | PROOF_INCLUSION | §4.6, §10.7 | DELIVER dropped and ACCEPT renumbered to seq 2 and re-signed (ACCEPT.prev_hash != H(CONFIRM)) | |
| V07 | V07-1 | verify | verify/V07-1.json | REJECT | R1_SEQ | §4.6, §5.2 | REFUSE | Base with an identical copy of ACCEPT appended |
| V08 | V08-1 | verify | verify/V08-1.json | REJECT | R6_ILLEGAL | §5.3 | REFUSE | Base plus a second ACCEPT for the same DELIVER, correctly chained and signed (forced past the server's refusal) |
| V09 | V09-1 | verify | verify/V09-1.json | REJECT | PROOF_INCLUSION | §4.4, §4.6 | R2's DELIVER (chained and signed for R2) spliced into R1 after R1's CONFIRM; identical COMMIT bodies | |
| V10 | V10-1 | verify | verify/V10-1.json | DETECT | TIP_AHEAD_TRUNCATED | §6.5, §10.10 | Base truncated after DELIVER (ACCEPT removed); the latest head's tip commits seq 3 | |
| V11 | V11-1 | verify | verify/V11-1.json | ACCEPT | §10.10-11 | Earlier export of a record (COMMIT, CONFIRM, DELIVER, REJECT) anchored in head 0 | ||
| V11 | V11-2 | verify | verify/V11-2.json | ACCEPT | §10.10-11 | Later export of the same record (plus DELIVER, ACCEPT; head 1), checked against the known heads saved from V11-1 | ||
| V12 | V12-1 | verify | verify/V12-1.json | REJECT | SIG_W_UNKNOWN_KEY | §7.6, §10.6 | Base with ACCEPT re-signed by an unknown key K_x and server_key_id set to K_x | |
| V12 | V12-2 | verify | verify/V12-2.json | REJECT | HEAD_UNKNOWN_KEY | §7.6, §10.6 | Base with head 1 signed only by the unknown key K_x | |
| V13 | V13-1 | verify | verify/V13-1.json | REJECT | SIG_W_INVALID | §4.8 | Base with ACCEPT carrying DELIVER's S_w (a valid K_w signature over other bytes) | |
| V14 | V14-1 | verify | verify/V14-1.json | REJECT | SIG_W_INVALID | §2.2 | Base with ACCEPT's S_w malleated: S replaced by S + L | |
| V14 | V14-2 | verify | verify/V14-2.json | REJECT | SIG_W_INVALID | §2.2 | Base with ACCEPT's S_w R replaced by a non-canonical encoding (y = p) | |
| V15 | V15-1 | verify | verify/V15-1.json | REJECT | COMMIT_BAD_AGENT_KEY | §2.2, §5.2.6 | REFUSE | COMMIT whose party P agent_key is the identity point (small order), forced past the server's refusal |
| V16 | V16-1 | verify | verify/V16-1.json | REJECT | R4_SIG_A_MISSING | §5.2.7 | REFUSE | ed25519-confirmed ACCEPT with no S_a |
| V16 | V16-2 | verify | verify/V16-2.json | REJECT | R4_SIG_A_INVALID | §5.2.7 | REFUSE | ed25519-confirmed ACCEPT whose S_a is by a key other than the agent_key C committed |
| V17 | V17-1 | verify | verify/V17-1.json | REJECT | R4_SIG_A_INVALID | §5.2.7 | Base (email_token) with an extra invalid S_a appended to ACCEPT's sigs | |
| V18 | V18-1 | verify | verify/V18-1.json | REJECT | SIG_W_INVALID | §4.2, §4.9 | Base with ACCEPT's auth flipped from email_token to ed25519 after signing (party_digest removed) | |
| V19 | V19-1 | verify | verify/V19-1.json | ACCEPT | §7.3, §10.9 | Planned rotation: head 2 announces K1, heads 3-4 dual-signed, K0 retired after head 4 (positive control) | ||
| V19 | V19-2 | verify | verify/V19-2.json | REJECT | EVENT_KEY_WINDOW | §7.3, §10.9 | After the rotation, a DISPUTE signed by the retired K0 and first included in head 5 | |
| V20 | V20-1 | verify | verify/V20-1.json | REJECT | R4_NONCE_REUSED | §5.2.7 | REFUSE | DELIVER reusing COMMIT's token nonce (forced past the server's refusal) |
| V21 | V21-1 | verify | verify/V21-1.json | REJECT | R4_PARTY_DIGEST | §5.2.7 | REFUSE | ACCEPT whose party_digest is another address's digest (forced past the server's refusal) |
| V22 | V22-1 | verify | verify/V22-1.json | REJECT | RECORD_ID_MISMATCH | §4.4 | REFUSE | DELIVER whose record_id names another record, appended to this record's chain |
| V23 | V23-1 | verify | verify/V23-1.json | REJECT | R4_TOKEN_EXPIRED | §5.2.7 | REFUSE | CONFIRM made after its token_expires (forced past the server's refusal) |
| V24 | V24-1 | verify | verify/V24-1.json | REJECT | R3_ERASED_ACTOR | §5.2.4, §5.7 | REFUSE | ACCEPT by C via email token after C's ERASE (forced past the server's refusal) |
| V26 | V26-1 | verify | verify/V26-1.json | REJECT | AUTH_METHOD | §4.2 | Base with ACCEPT's auth.method set to share_token | |
| V26 | V26-2 | verify | verify/V26-2.json | REJECT | FIELD_UNKNOWN | §4.2 | Base with an extra auth.share_token member on ACCEPT | |
| V28 | V28-1 | verify | verify/V28-1.json | ACCEPT | §10.11 | Base checked against --known-heads holding heads 0 and 1 | ||
| V29 | V29-1 | verify | verify/V29-1.json | DETECT | HEAD_ROLLBACK | §9.4b, §10.11 | Rollback: the export ends at head 1 while --known-heads holds head 2 | |
| V30 | V30-1 | verify | verify/V30-1.json | DETECT | HEAD_EQUIVOCATION | §9.4a, §10.11 | Split view: --known-heads holds a K_w-signed head 1 with the same n and a different root | |
| V31 | V31-1 | verify | verify/V31-1.json | REJECT | HEAD_CONSISTENCY_UNPROVEN | §6.4, §9.4c, §10.5 | Export whose head 2 carries a corrupted consistency proof from head 1 | |
| V31 | V31-2 | verify | verify/V31-2.json | DETECT | HEAD_FORK_SAME_SIZE | §6.4, §9.4c, §10.5 | Export to head 1; the mirror holds a validly signed head 2 over a forked log | |
| V32 | V32-1 | verify | verify/V32-1.json | ACCEPT | §6.3, §8.2, §10.6 | Export whose inclusion proofs are against head 2 (positive control) | ||
| V32 | V32-2 | verify | verify/V32-2.json | REJECT | PROOF_INCLUSION | §6.3, §8.2, §10.6 | CONFIRM's inclusion proof (valid for head 2) relabelled as being for head 1 | |
| V33 | V33-1 | verify | verify/V33-1.json | DETECT | HEAD_UNANCHORED | §9.4e, §10.11 | --require-anchored with a mirror that holds head 0 only (the anchoring head 1 is unpublished) | |
| V33 | V33-2 | verify | verify/V33-2.json | ACCEPT | §9.4e, §10.11 | --require-anchored with a mirror that holds heads 0 and 1 (positive control) | ||
| V34 | V34-1 | verify | verify/V34-1.json | REJECT | HEAD_SIG_INVALID | §6.8, §9.4d, §10.5 | Base with head 1's signature altered in its last byte | |
| V34 | V34-2 | verify | verify/V34-2.json | DETECT | HEAD_SIZE_DECREASE | §6.8, §9.4d, §10.5 | Export to head 1; the mirror holds a signed head 2 with a smaller tree_size | |
| V35 | V35-1 | verify | verify/V35-1.json | REJECT | PROOF_TOO_LONG | §3.5, §6.3 | COMMIT's inclusion path replaced by 65 nodes | |
| V35 | V35-2 | verify | verify/V35-2.json | REJECT | PROOF_MALFORMED | §3.5, §6.3 | COMMIT's inclusion path with a malformed node ("zz") | |
| V36 | V36-d1 | digest | digest/V36-d1.json | matches=0 | §5.8 | After erasure of both parties (k_rec deleted): no candidate address, including the true ones, matches any 64-hex string | ||
| V36 | V36-d2 | digest | digest/V36-d2.json | matches=2 | §15 | counting rule: distinct digest values found in 64-hex windows (overlapping, lowercase only); Alice inside a longer run, | ||
| V37 | V37-d1 | digest | digest/V37-d1.json | digest | §5.8 | Before erasure: base record party P's address with P's k_rec gives the digest committed in COMMIT.body.parties.p | ||
| V37 | V37-d2 | digest | digest/V37-d2.json | digest | §5.8 | Before erasure: base record party C's address with C's k_rec gives the digest committed in COMMIT.body.parties.c | ||
| V37 | V37-d3 | digest | digest/V37-d3.json | digest | §5.8 | Normalisation: C's address with surrounding spaces and mixed case (NFC, strip, lowercase) gives the same digest as V37-2 | ||
| V38 | V38-d1 | digest | digest/V38-d1.json | digest | §5.8 | The same address as party P of record r1 (Sim v38) | ||
| V38 | V38-d2 | digest | digest/V38-d2.json | digest | §5.8 | The same address as party P of record r2 (Sim v38): a different k_rec gives a different digest than V38-1 | ||
| V39 | V39-1 | verify | verify/V39-1.json | ACCEPT | §5.7, §10.13 | Export after both parties' ERASE events, anchored in head 2 | ||
| V39 | V39-2 | verify | verify/V39-2.json | REJECT | PLAINTEXT_AFTER_ERASE | §5.7, §10.13 | Erased export that still carries party C's plaintext | |
| V41 | V41-1 | verify | verify/V41-1.json | REJECT | TIME_AFTER_HEAD | §10.9, §11.2 | CONFIRM whose at is after the published_at of its first including head | |
| V42 | V42-1 | verify | verify/V42-1.json | REJECT | R5_TIME_ORDER | §5.2.5 | REFUSE | CONFIRM whose at is earlier than COMMIT's at (forced past the server's refusal) |
| V43 | V43-1 | verify | verify/V43-1.json | ACCEPT | §11.2 | Backdated record: events at 2026-09-01, first included in a head published 2026-10-02 | ||
| V44 | V44-t1 | text | text/V44-t1.json | banned_matches=0 | §11.3 | LITERAL REGEX-UNIT CHECK on stored strings (not the candidate's output; see V44-r1). CLI output for the base record (party P named "Acme Example") must not present at as proven or overclaim strength: no | ||
| V44 | V44-r1 | render | render/V44-r1.json | ACCEPT, exit 0, banned_matches=0 | §11.3, §13 | CLI output (text and --json) of the candidate's own CLI for the base record: no banned wording (render twin of V44-t1) | ||
| V45 | V45-1 | verify | verify/V45-1.json | REJECT | REVERSE_NO_ACCEPT | §5.3 | REFUSE | REVERSE with no prior ACCEPT (forced past the server's refusal) |
| V46 | V46-1 | verify | verify/V46-1.json | REJECT | G1_TERMINAL | §5.3 | REFUSE | AMEND after WITHDRAW (forced past the server's refusal) |
| V47 | V47-1 | verify | verify/V47-1.json | REJECT | G1_WRONG_ROLE | §5.3 | REFUSE | DELIVER by C (wrong role; forced past the server's refusal) |
| V47 | V47-2 | verify | verify/V47-2.json | REJECT | G1_WRONG_ROLE | §5.3 | REFUSE | ACCEPT by P (self-acceptance; forced past the server's refusal) |
| V48 | V48-1 | verify | verify/V48-1.json | REJECT | FIELD_FORM | §4.1, §5.2 | REFUSE | WITHDRAW whose actor is X (neither party) |
| V48 | V48-2 | verify | verify/V48-2.json | REJECT | R2_ACTOR | §4.1, §5.2 | REFUSE | WITHDRAW by W with method server (forced past the server's refusal) |
| V49 | V49-1 | verify | verify/V49-1.json | REJECT | G1_NOT_AGREED | §5.3, §5.4 | REFUSE | DELIVER before C confirmed the COMMIT (forced past the server's refusal) |
| V50 | V50-1 | verify | verify/V50-1.json | REJECT | COMMIT_SELF_DEALING | §5.3, §5.8 | REFUSE | COMMIT where P's and C's digests are equal (k_rec reused across roles; forced past the server's refusal) |
| V51 | V51-1 | verify | verify/V51-1.json | REJECT | LIMIT_SIZE | §3.5, §4.1 | REFUSE | DELIVER whose canonical form exceeds 16 KiB (16 links of ~2 KB), forced past the server's refusal |
| V51 | V51-2 | verify | verify/V51-2.json | REJECT | LIMIT_STRING | §3.5, §4.1 | REFUSE | Base with one string (evidence kind) of 5,000 bytes |
| V51 | V51-c1 | canon | canon/V51-c1.json | OK | §3.5, §4.1 | A string of exactly 4,096 UTF-8 bytes (2,048 x U+00E9): accepted | ||
| V51 | V51-c2 | canon | canon/V51-c2.json | ERROR | LIMIT_STRING | §3.5, §4.1 | A string of 4,097 UTF-8 bytes (2,048 x U+00E9 + x): refused | |
| V52 | V52-1 | verify | verify/V52-1.json | REJECT | LIMIT_DEPTH | §3.2, §3.5 | Base with a plaintext member nested 10,000 arrays deep | |
| V52 | V52-2 | verify | verify/V52-2.json | REJECT | LIMIT_DEPTH | §3.2, §3.5 | Base with DELIVER evidence value nested 5 arrays deep (event depth > 8) | |
| V52 | V52-c1 | canon | canon/V52-c1.json | OK | §3.2, §3.5 | Nesting depth 8 (8 nested objects): the event limit, accepted | ||
| V52 | V52-c2 | canon | canon/V52-c2.json | ERROR | LIMIT_DEPTH | §3.2, §3.5 | Nesting depth 9: refused | |
| V53 | V53-1 | verify | verify/V53-1.json | REJECT | LIMIT_ITEMS | §3.5, §4.8 | Base with its events repeated 251 times (1,004 events) | |
| V53 | V53-2 | verify | verify/V53-2.json | REJECT | LIMIT_SIGS | §3.5, §4.8 | Base with ACCEPT's signature list repeated 3 times (3 S_w) | |
| V53 | V53-3 | verify | verify/V53-3.json | REJECT | LIMIT_ITEMS | §3.5, §4.8 | Base with ACCEPT carrying 50,001 copies of its S_w (array above the 1,000-item limit) | |
| V53 | V53-4 | verify | verify/V53-4.json | REJECT | LIMIT_SIZE | §3.5, §4.8 | An export of 16 MiB + 1 bytes (spaces only): refused before parsing | |
| V53 | V53-c1 | canon | canon/V53-c1.json | OK | §3.5, §4.8 | An object with 64 members: accepted | ||
| V53 | V53-c2 | canon | canon/V53-c2.json | ERROR | LIMIT_MEMBERS | §3.5, §4.8 | An object with 65 members: refused | |
| V53 | V53-c3 | canon | canon/V53-c3.json | OK | §3.5, §4.8 | An array with 64 items: accepted | ||
| V53 | V53-c4 | canon | canon/V53-c4.json | ERROR | LIMIT_ITEMS | §3.5, §4.8 | An array with 65 items: refused | |
| V54 | V54-1 | verify | verify/V54-1.json | ACCEPT | §10.13 | Base with party P named with a Cyrillic A in "Acme" (mixed script; display warning) | ||
| V55 | V55-1 | verify | verify/V55-1.json | REJECT | STR_BANNED_CHAR | §3.6 | REFUSE | Base with party P's name holding an escaped U+202E (RTL override) |
| V55 | V55-2 | verify | verify/V55-2.json | REJECT | STR_BANNED_CHAR | §3.6 | REFUSE | Base with party P's name holding an escaped U+0000 |
| V55 | V55-c1 | canon | canon/V55-c1.json | ERROR | STR_BANNED_CHAR | §3.6 | U+202E (RTL override) in a string | |
| V55 | V55-c2 | canon | canon/V55-c2.json | ERROR | STR_BANNED_CHAR | §3.6 | U+200B (zero width space) in a string | |
| V55 | V55-c3 | canon | canon/V55-c3.json | ERROR | STR_BANNED_CHAR | §3.6 | Escaped U+0000 in a string | |
| V56 | V56-1 | verify | verify/V56-1.json | ACCEPT | §3.6 | Base with party P named "Caf\u00e9" in NFC (positive control) | ||
| V56 | V56-2 | verify | verify/V56-2.json | REJECT | STR_NOT_NFC | §3.6 | Base with party P's name rewritten in NFD (e + U+0301) | |
| V56 | V56-c1 | canon | canon/V56-c1.json | ERROR | STR_NOT_NFC | §3.6 | String in NFD (e + U+0301): strings must be NFC | |
| V56 | V56-c2 | canon | canon/V56-c2.json | OK | §3.6 | Control: the same string in NFC | ||
| V57 | V57-1 | verify | verify/V57-1.json | REJECT | FIELD_UNKNOWN | §4.3 | DELIVER with a plaintext note member in its body (unknown field) | |
| V58 | V58-1 | verify | verify/V58-1.json | ACCEPT | §3.3 | Base re-serialised with indentation and reversed key order | ||
| V58 | V58-c1 | canon | canon/V58-c1.json | OK | §3.3 | Whitespace and key order: the same object with extra whitespace and members out of order | ||
| V59 | V59-1 | verify | verify/V59-1.json | REJECT | JSON_DUP_KEY | §3.2 | Base with a duplicate "type" key in ACCEPT | |
| V59 | V59-c1 | canon | canon/V59-c1.json | ERROR | JSON_DUP_KEY | §3.2 | Duplicate keys in one object | |
| V60 | V60-1 | verify | verify/V60-1.json | REJECT | NUM_NOT_INTEGER | §3.2 | Base with COMMIT seq written as 1.0 | |
| V60 | V60-2 | verify | verify/V60-2.json | REJECT | NUM_NOT_INTEGER | §3.2 | Base with COMMIT seq written as 1e2 | |
| V60 | V60-3 | verify | verify/V60-3.json | REJECT | NUM_NEG_ZERO | §3.2 | Base with COMMIT seq written as -0 | |
| V60 | V60-c1 | canon | canon/V60-c1.json | ERROR | NUM_NOT_INTEGER | §3.2 | Number 1.0 (fraction): the profile allows integers only | |
| V60 | V60-c2 | canon | canon/V60-c2.json | ERROR | NUM_NOT_INTEGER | §3.2 | Number 1e2 (exponent): the profile allows integers only | |
| V60 | V60-c3 | canon | canon/V60-c3.json | ERROR | NUM_NEG_ZERO | §3.2 | Number -0 | |
| V60 | V60-c4 | canon | canon/V60-c4.json | OK | §3.2 | Control: the integers 100 and 0 are accepted | ||
| V61 | V61-1 | verify | verify/V61-1.json | REJECT | NUM_RANGE | §3.2 | Base with COMMIT seq written as 9007199254740993 | |
| V61 | V61-c1 | canon | canon/V61-c1.json | ERROR | NUM_RANGE | §3.2 | Integer 9007199254740993 (above 2^53 - 1) | |
| V61 | V61-c2 | canon | canon/V61-c2.json | OK | §3.2 | Integer 9007199254740991 (2^53 - 1, the largest allowed) | ||
| V61 | V61-c3 | canon | canon/V61-c3.json | OK | §3.2 | Integer -9007199254740991 (the smallest allowed) | ||
| V61 | V61-c4 | canon | canon/V61-c4.json | ERROR | NUM_RANGE | §3.2 | Integer 9007199254740992 (2^53, just outside the range) | |
| V62 | V62-1 | verify | verify/V62-1.json | REJECT | JSON_NAN_INF | §3.2 | Base with COMMIT seq written as NaN | |
| V62 | V62-2 | verify | verify/V62-2.json | REJECT | JSON_NAN_INF | §3.2 | Base with COMMIT seq written as Infinity | |
| V62 | V62-3 | verify | verify/V62-3.json | REJECT | JSON_NAN_INF | §3.2 | Base with COMMIT seq written as -Infinity | |
| V62 | V62-c1 | canon | canon/V62-c1.json | ERROR | JSON_NAN_INF | §3.2 | NaN literal | |
| V62 | V62-c2 | canon | canon/V62-c2.json | ERROR | JSON_NAN_INF | §3.2 | Infinity literal | |
| V62 | V62-c3 | canon | canon/V62-c3.json | ERROR | JSON_NAN_INF | §3.2 | -Infinity literal | |
| V63 | V63-1 | verify | verify/V63-1.json | ACCEPT | §3.2-3.3 | Base with party P's name "Caf\u00e9" written with a \u00e9 escape | ||
| V63 | V63-c1 | canon | canon/V63-c1.json | OK | §3.2-3.3 | String with an escaped \u00e9: canonical form is the literal UTF-8 character | ||
| V63 | V63-c2 | canon | canon/V63-c2.json | OK | §3.2-3.3 | String with a literal é (UTF-8 C3 A9): same canonical bytes as the escaped form | ||
| V64 | V64-1 | verify | verify/V64-1.json | REJECT | STR_BANNED_CHAR | §3.6 | Base with party P's name holding an escaped U+001F | |
| V64 | V64-c1 | canon | canon/V64-c1.json | ERROR | STR_BANNED_CHAR | §3.6 | Escaped control character U+001F in a string (banned in the profile) | |
| V64 | V64-c2 | canon | canon/V64-c2.json | ERROR | JSON_CONTROL_CHAR | §3.6 | Raw control byte 0x1F inside a string (not JSON) | |
| V65 | V65-1 | verify | verify/V65-1.json | ACCEPT | §3.3 | Base with an evidence link written with \/ escapes | ||
| V65 | V65-c1 | canon | canon/V65-c1.json | OK | §3.3 | Escaped solidus \/ : canonical form writes a plain / | ||
| V66 | V66-1 | verify | verify/V66-1.json | REJECT | KEY_FORM | §3.2-3.3 | Base with the first "terms_digest" key renamed to a non-ASCII key | |
| V66 | V66-c1 | canon | canon/V66-c1.json | ERROR | KEY_FORM | §3.2-3.3 | Non-ASCII key "é" (keys are [a-z][a-z0-9_]{0,31}) | |
| V66 | V66-c2 | canon | canon/V66-c2.json | ERROR | KEY_FORM | §3.2-3.3 | Uppercase key "A" | |
| V67 | V67-1 | verify | verify/V67-1.json | REJECT | STR_LONE_SURROGATE | §3.2 | Base with party P's name holding a lone \ud800 | |
| V67 | V67-c1 | canon | canon/V67-c1.json | ERROR | STR_LONE_SURROGATE | §3.2 | Lone high surrogate \ud800 | |
| V67 | V67-c2 | canon | canon/V67-c2.json | ERROR | STR_LONE_SURROGATE | §3.2 | Lone low surrogate \udc00 | |
| V68 | V68-1 | verify | verify/V68-1.json | REJECT | JSON_BAD_UTF8 | §3.1 | Base with invalid UTF-8 bytes (FF FE) in party P's name | |
| V68 | V68-2 | verify | verify/V68-2.json | REJECT | JSON_BOM | §3.1 | Base preceded by a UTF-8 BOM | |
| V68 | V68-c1 | canon | canon/V68-c1.json | ERROR | JSON_BAD_UTF8 | §3.1 | Invalid UTF-8 bytes FF FE inside a string | |
| V68 | V68-c2 | canon | canon/V68-c2.json | ERROR | JSON_BOM | §3.1 | A UTF-8 BOM before the JSON text | |
| V69 | V69-1 | verify | verify/V69-1.json | REJECT | NUM_NOT_INTEGER | §3.2 | Base with COMMIT seq written as 0.30000000000000004 | |
| V69 | V69-c1 | canon | canon/V69-c1.json | ERROR | NUM_NOT_INTEGER | §3.2 | Float 0.30000000000000004 | |
| V70 | V70-c1 | canon | canon/V70-c1.json | ERROR | JSON_NULL | §3.3 | r6: a literal null as a member value (absent != null; the profile has no null) | |
| V70 | V70-c2 | canon | canon/V70-c2.json | ERROR | JSON_NULL | §3.3 | r6: a literal null inside an array | |
| V70 | V70-c3 | canon | canon/V70-c3.json | ERROR | JSON_NULL | §3.3 | r6: a top-level null | |
| V70 | V70-c4 | canon | canon/V70-c4.json | ERROR | JSON_SYNTAX | §3.3 | Trailing data after the JSON value | |
| V70 | V70-c5 | canon | canon/V70-c5.json | ERROR | KEY_FORM | §3.3 | A 33-character key (keys are at most 32 characters) | |
| V70 | V70-c6 | canon | canon/V70-c6.json | OK | §3.3 | A 32-character key: accepted | ||
| V70 | V70-c7 | canon | canon/V70-c7.json | OK | §3.3 | A non-BMP character (U+1F600) written as an escaped surrogate pair: canonical form is the literal 4-byte UTF-8 | ||
| V70 | V70-c8 | canon | canon/V70-c8.json | OK | §3.3 | Key sorting: keys a, a_, a0, b given as b, a_, a0, a (UTF-16 order equals ASCII order here: a < a0 < a_ < b) | ||
| V70 | V70-c9 | canon | canon/V70-c9.json | OK | §3.3 | Literals true and false; an empty object and an empty array | ||
| V70 | V70-c10 | canon | canon/V70-c10.json | OK | §3.3 | Random profile-valid object 1 of 40 (seed 20261015): random whitespace, key order and escaping; expected = canonical byt | ||
| V70 | V70-c11 | canon | canon/V70-c11.json | OK | §3.3 | Random profile-valid object 2 of 40 (seed 20261015): random whitespace, key order and escaping; expected = canonical byt | ||
| V70 | V70-c12 | canon | canon/V70-c12.json | OK | §3.3 | Random profile-valid object 3 of 40 (seed 20261015): random whitespace, key order and escaping; expected = canonical byt | ||
| V70 | V70-c13 | canon | canon/V70-c13.json | OK | §3.3 | Random profile-valid object 4 of 40 (seed 20261015): random whitespace, key order and escaping; expected = canonical byt | ||
| V70 | V70-c14 | canon | canon/V70-c14.json | OK | §3.3 | Random profile-valid object 5 of 40 (seed 20261015): random whitespace, key order and escaping; expected = canonical byt | ||
| V70 | V70-c15 | canon | canon/V70-c15.json | OK | §3.3 | Random profile-valid object 6 of 40 (seed 20261015): random whitespace, key order and escaping; expected = canonical byt | ||
| V70 | V70-c16 | canon | canon/V70-c16.json | OK | §3.3 | Random profile-valid object 7 of 40 (seed 20261015): random whitespace, key order and escaping; expected = canonical byt | ||
| V70 | V70-c17 | canon | canon/V70-c17.json | OK | §3.3 | Random profile-valid object 8 of 40 (seed 20261015): random whitespace, key order and escaping; expected = canonical byt | ||
| V70 | V70-c18 | canon | canon/V70-c18.json | OK | §3.3 | Random profile-valid object 9 of 40 (seed 20261015): random whitespace, key order and escaping; expected = canonical byt | ||
| V70 | V70-c19 | canon | canon/V70-c19.json | OK | §3.3 | Random profile-valid object 10 of 40 (seed 20261015): random whitespace, key order and escaping; expected = canonical by | ||
| V70 | V70-c20 | canon | canon/V70-c20.json | OK | §3.3 | Random profile-valid object 11 of 40 (seed 20261015): random whitespace, key order and escaping; expected = canonical by | ||
| V70 | V70-c21 | canon | canon/V70-c21.json | OK | §3.3 | Random profile-valid object 12 of 40 (seed 20261015): random whitespace, key order and escaping; expected = canonical by | ||
| V70 | V70-c22 | canon | canon/V70-c22.json | OK | §3.3 | Random profile-valid object 13 of 40 (seed 20261015): random whitespace, key order and escaping; expected = canonical by | ||
| V70 | V70-c23 | canon | canon/V70-c23.json | OK | §3.3 | Random profile-valid object 14 of 40 (seed 20261015): random whitespace, key order and escaping; expected = canonical by | ||
| V70 | V70-c24 | canon | canon/V70-c24.json | OK | §3.3 | Random profile-valid object 15 of 40 (seed 20261015): random whitespace, key order and escaping; expected = canonical by | ||
| V70 | V70-c25 | canon | canon/V70-c25.json | OK | §3.3 | Random profile-valid object 16 of 40 (seed 20261015): random whitespace, key order and escaping; expected = canonical by | ||
| V70 | V70-c26 | canon | canon/V70-c26.json | OK | §3.3 | Random profile-valid object 17 of 40 (seed 20261015): random whitespace, key order and escaping; expected = canonical by | ||
| V70 | V70-c27 | canon | canon/V70-c27.json | OK | §3.3 | Random profile-valid object 18 of 40 (seed 20261015): random whitespace, key order and escaping; expected = canonical by | ||
| V70 | V70-c28 | canon | canon/V70-c28.json | OK | §3.3 | Random profile-valid object 19 of 40 (seed 20261015): random whitespace, key order and escaping; expected = canonical by | ||
| V70 | V70-c29 | canon | canon/V70-c29.json | OK | §3.3 | Random profile-valid object 20 of 40 (seed 20261015): random whitespace, key order and escaping; expected = canonical by | ||
| V70 | V70-c30 | canon | canon/V70-c30.json | OK | §3.3 | Random profile-valid object 21 of 40 (seed 20261015): random whitespace, key order and escaping; expected = canonical by | ||
| V70 | V70-c31 | canon | canon/V70-c31.json | OK | §3.3 | Random profile-valid object 22 of 40 (seed 20261015): random whitespace, key order and escaping; expected = canonical by | ||
| V70 | V70-c32 | canon | canon/V70-c32.json | OK | §3.3 | Random profile-valid object 23 of 40 (seed 20261015): random whitespace, key order and escaping; expected = canonical by | ||
| V70 | V70-c33 | canon | canon/V70-c33.json | OK | §3.3 | Random profile-valid object 24 of 40 (seed 20261015): random whitespace, key order and escaping; expected = canonical by | ||
| V70 | V70-c34 | canon | canon/V70-c34.json | OK | §3.3 | Random profile-valid object 25 of 40 (seed 20261015): random whitespace, key order and escaping; expected = canonical by | ||
| V70 | V70-c35 | canon | canon/V70-c35.json | OK | §3.3 | Random profile-valid object 26 of 40 (seed 20261015): random whitespace, key order and escaping; expected = canonical by | ||
| V70 | V70-c36 | canon | canon/V70-c36.json | OK | §3.3 | Random profile-valid object 27 of 40 (seed 20261015): random whitespace, key order and escaping; expected = canonical by | ||
| V70 | V70-c37 | canon | canon/V70-c37.json | OK | §3.3 | Random profile-valid object 28 of 40 (seed 20261015): random whitespace, key order and escaping; expected = canonical by | ||
| V70 | V70-c38 | canon | canon/V70-c38.json | OK | §3.3 | Random profile-valid object 29 of 40 (seed 20261015): random whitespace, key order and escaping; expected = canonical by | ||
| V70 | V70-c39 | canon | canon/V70-c39.json | OK | §3.3 | Random profile-valid object 30 of 40 (seed 20261015): random whitespace, key order and escaping; expected = canonical by | ||
| V70 | V70-c40 | canon | canon/V70-c40.json | OK | §3.3 | Random profile-valid object 31 of 40 (seed 20261015): random whitespace, key order and escaping; expected = canonical by | ||
| V70 | V70-c41 | canon | canon/V70-c41.json | OK | §3.3 | Random profile-valid object 32 of 40 (seed 20261015): random whitespace, key order and escaping; expected = canonical by | ||
| V70 | V70-c42 | canon | canon/V70-c42.json | OK | §3.3 | Random profile-valid object 33 of 40 (seed 20261015): random whitespace, key order and escaping; expected = canonical by | ||
| V70 | V70-c43 | canon | canon/V70-c43.json | OK | §3.3 | Random profile-valid object 34 of 40 (seed 20261015): random whitespace, key order and escaping; expected = canonical by | ||
| V70 | V70-c44 | canon | canon/V70-c44.json | OK | §3.3 | Random profile-valid object 35 of 40 (seed 20261015): random whitespace, key order and escaping; expected = canonical by | ||
| V70 | V70-c45 | canon | canon/V70-c45.json | OK | §3.3 | Random profile-valid object 36 of 40 (seed 20261015): random whitespace, key order and escaping; expected = canonical by | ||
| V70 | V70-c46 | canon | canon/V70-c46.json | OK | §3.3 | Random profile-valid object 37 of 40 (seed 20261015): random whitespace, key order and escaping; expected = canonical by | ||
| V70 | V70-c47 | canon | canon/V70-c47.json | OK | §3.3 | Random profile-valid object 38 of 40 (seed 20261015): random whitespace, key order and escaping; expected = canonical by | ||
| V70 | V70-c48 | canon | canon/V70-c48.json | OK | §3.3 | Random profile-valid object 39 of 40 (seed 20261015): random whitespace, key order and escaping; expected = canonical by | ||
| V70 | V70-c49 | canon | canon/V70-c49.json | OK | §3.3 | Random profile-valid object 40 of 40 (seed 20261015): random whitespace, key order and escaping; expected = canonical by | ||
| V71 | V71-1 | verify | verify/V71-1.json | REJECT | CONFIRM_WHILE_DELIVERED | §5.3, §5.4 | REFUSE | CONFIRM of an AMEND while DELIVERED (A1; forced past the server's refusal) |
| V72 | V72-1 | verify | verify/V72-1.json | REJECT | CONFIRM_SELF | §5.3, §5.4 | REFUSE | CONFIRM of the COMMIT by its own proposer P (A2; forced past the server's refusal) |
| V73 | V73-1 | verify | verify/V73-1.json | REJECT | CONFIRM_TERMS | §5.3, §5.4 | REFUSE | CONFIRM whose terms_digest differs from the proposal's (A3; forced past the server's refusal) |
| V74 | V74-1 | verify | verify/V74-1.json | REJECT | DISPUTE_NO_DELIVER | §5.3 | REFUSE | DISPUTE in WITHDRAWN with no prior DELIVER (A4; forced past the server's refusal) |
| V74 | V74-2 | verify | verify/V74-2.json | ACCEPT | §5.3 | Positive control: DISPUTE after WITHDRAW when a DELIVER exists (legal) | ||
| V75 | V75-1 | verify | verify/V75-1.json | REJECT | CONFIRM_REF | §5.3, §5.4 | REFUSE | CONFIRM naming an AMEND superseded by a later AMEND (A5; forced past the server's refusal) |
| XC2 | XC2-1 | verify | verify/XC2-1.json | ERROR | KEYS_ENDORSEMENT | §7.2, §7.3 | key history in which the retired key K0 endorses the introduction of a new key K2 | |
| XC2 | XC2-2 | verify | verify/XC2-2.json | DETECT | KEY_COMPROMISED_UNWITNESSED | §7.2, §7.3, §7.5 | key history in which the retired key K0 endorses the revocation of K1 from head 100 | |
| XC2 | XC2-3 | verify | verify/XC2-3.json | ACCEPT | §7.4 | control: the same export and the unmodified rotation history | ||
| XE10 | XE10-1 | verify | verify/XE10-1.json | DETECT | HEAD_ROLLBACK | §9.1, §10 | XF1-2's known head 2 with its tip proof carrying one extra member: the tip is not exactly {index, leaf, path}, so it is | |
| XE10 | XE10-2 | verify | verify/XE10-2.json | DETECT | HEAD_ROLLBACK | §9.1, §10 | XF1-2's known head 2 with the tip index written as JSON false (the true index is 0): not an int >= 0, so the tip is igno | |
| XERASE | XERASE-1 | verify | verify/XERASE-1.json | REJECT | R2_ACTOR | §4.3, §5.2, §5.7 | ERASE written with auth.method email_token (must be server) | |
| XF1 | XF1-1 | verify | verify/XF1-1.json | DETECT | TIP_AHEAD_TRUNCATED | §6.5, §9.4, §10, §11.1 | export of V10's base with the ACCEPT entry removed by a recipient; honest head 1 and its tip membership proof kept: the | |
| XF1 | XF1-2 | verify | verify/XF1-2.json | DETECT | HEAD_ROLLBACK | §9.4, §10 | older export (seq 0-1, anchored in head 1) with a known head 2 whose tip proof for this record is seq 3 | |
| XF1 | XF1-3 | verify | verify/XF1-3.json | DETECT | HEAD_FORK_SAME_SIZE | §9.4, §10 | control: known head 2 (same tree_size as head 1, different tip map) commits another event hash at seq 3 with a verified | |
| XF3 | XF3-1 | verify | verify/XF3-1.json | ERROR | LOCAL_CAP | §3.5, §10, §14 | 2,003-byte array of 1,001 zeros (above the 1,000-item protocol limit) with a declared local cap of 1,024 bytes: the byte | |
| XF3 | XF3-2 | verify | verify/XF3-2.json | REJECT | LIMIT_ITEMS | §3.2, §3.5 | control: the same 2,003 bytes with a local cap of 4,096 (not exceeded): the item limit is reached by the parser | |
| XF3 | XF3-3 | verify | verify/XF3-3.json | ERROR | LOCAL_CAP | §3.5, §10, §14 | V01-1's valid 6282-byte export with a declared local cap of 1000 bytes: ERROR LOCAL_CAP whose message says the content w | |
| XF5 | XF5-1 | verify | verify/XF5-1.json | ACCEPT | §7.4, §9.3, §10 | suffix export (heads 3 and 4, first inclusion at head 4) of a history that introduces K1 at head 3; the only supplied he | ||
| XF5 | XF5-2 | verify | verify/XF5-2.json | ACCEPT | §7.4, §9.3, §10 | control: the same suffix export; known head 2 carries next_key announcing K1 (byte-identical to the introducing entry) | ||
| XF5 | XF5-3 | verify | verify/XF5-3.json | ACCEPT | §6.8, §7.4, §9.3 | suffix export; the supplied head 2 carries a next_key that is not the introducing entry (valid_from 5, endorsement not m | ||
| XF5 | XF5-4 | verify | verify/XF5-4.json | ACCEPT | §7.4 | no head 2 supplied at all (suffix export only): the announcement is unseen | ||
| XG1 | XG1-1 | verify | verify/XG1-1.json | REJECT | TIP_FORM | §6.5, §8.3 | export tip member index -1 | |
| XG2 | XG2-1 | verify | verify/XG2-1.json | ERROR | USAGE | §13, §15 | --require-anchored with no --mirror | |
| XG5 | XG5-1 | verify | verify/XG5-1.json | ACCEPT | §10, §11.2 | CONFIRM declared one second before the publisher-declared published_at of its first head | ||
| XG6 | XG6-1 | verify | verify/XG6-1.json | REJECT | TIME_FORM | §6.6, §6.8 | export head 1 with a malformed published_at, a 65-node consistency path and (so) an invalid signature | |
| XG6 | XG6-2 | verify | verify/XG6-2.json | REJECT | PROOF_MALFORMED | §6.8 | export head 1 with a malformed consistency node and an invalid signature | |
| XG6 | XG6-3 | verify | verify/XG6-3.json | REJECT | HEAD_FORM | §6.8 | export head 1 whose first signature is by an unknown key and whose second is malformed | |
| XN1 | XN1-1 | verify | verify/XN1-1.json | REJECT | COMMIT_BAD_AGENT_KEY | §2.2, §5.2 | COMMIT whose party P agent_key is mixed order (aB + T, T of order 2); every S_a has an even challenge, so both Ed25519 e | |
| XN1 | XN1-2 | verify | verify/XN1-2.json | REJECT | SIG_W_INVALID | §2.2, §10 | ACCEPT's S_w with a mixed-order R (rB + T, order 2): the cofactored equation holds, the cofactorless one does not | |
| XN1 | XN1-3 | verify | verify/XN1-3.json | REJECT | HEAD_SIG_INVALID | §2.2, §6.8 | head 1 signed with a mixed-order R (cofactored equation holds) | |
| XN1 | XN1-4 | verify | verify/XN1-4.json | ERROR | KEYS_BAD_KEY | §2.2, §7.3, §10 | key history whose only K_w is mixed order (aB + T, T of order 8); every endorsement, S_w and head signature has k = 0 mo | |
| XN1 | XN1-e1 | ed25519 | ed25519/XN1-e1.json | OK | §2.2 | positive control: standard key and signature | ||
| XN1 | XN1-e2 | ed25519 | ed25519/XN1-e2.json | FAIL | ED_TORSION_A | §2.2 | A = aB + T (T of order 2), challenge k odd: only the cofactored equation holds | |
| XN1 | XN1-e3 | ed25519 | ed25519/XN1-e3.json | FAIL | ED_TORSION_A | §2.2 | A = aB + T (order 2), k even: BOTH equations hold; only the subgroup check refuses | |
| XN1 | XN1-e4 | ed25519 | ed25519/XN1-e4.json | FAIL | ED_TORSION_A | §2.2 | A = aB + T (order 8), k = 0 mod 8: both equations hold; subgroup check refuses | |
| XN1 | XN1-e5 | ed25519 | ed25519/XN1-e5.json | FAIL | ED_TORSION_A | §2.2 | A = aB + T (order 8), k = 3 mod 8: only the cofactored equation holds | |
| XN1 | XN1-e6 | ed25519 | ed25519/XN1-e6.json | FAIL | ED_TORSION_R | §2.2 | R = rB + T (order 2), prime-order A: only the cofactored equation holds | |
| XN1 | XN1-e7 | ed25519 | ed25519/XN1-e7.json | FAIL | ED_TORSION_R | §2.2 | R = rB + T (order 4), prime-order A: only the cofactored equation holds | |
| XN1 | XN1-e8 | ed25519 | ed25519/XN1-e8.json | FAIL | ED_SMALL_ORDER_A | §2.2 | A = the identity: small order is checked before the subgroup check | |
| XN1 | XN1-e9 | ed25519 | ed25519/XN1-e9.json | FAIL | ED_SMALL_ORDER_A | §2.2 | A = a point of order 8 (pure torsion): ED_SMALL_ORDER_A | |
| XN1 | XN1-e10 | ed25519 | ed25519/XN1-e10.json | FAIL | ED_TORSION_A | §2.2 | mixed-order A and a non-canonical R: A's checks come first | |
| XN1 | XN1-e11 | ed25519 | ed25519/XN1-e11.json | FAIL | ED_S_NOT_REDUCED | §2.2 | S + L (not reduced) | |
| XN1 | XN1-e12 | ed25519 | ed25519/XN1-e12.json | FAIL | ED_BAD_SIGNATURE | §2.2 | valid signature over another message: the equation fails | |
| XN1 | XN1-e13 | ed25519 | ed25519/XN1-e13.json | FAIL | ED_SMALL_ORDER_R | §2.2 | R = the identity with a prime-order A: ED_SMALL_ORDER_R | |
| XN2 | XN2-t1 | text | text/XN2-t1.json | banned_matches=0 | §5.7, §11.2, §11.3 | LITERAL REGEX-UNIT CHECK on stored strings (not the candidate's output; see XN2-r1). CLI output for an export after both parties' ERASE: no claim that deletion or unlinkability is proven | ||
| XN2 | XN2-r1 | render | render/XN2-r1.json | ACCEPT, exit 0, banned_matches=0 | §5.7, §11.3, §13 | CLI output (text and --json) of the candidate's own CLI after both parties' ERASE: no claim that deletion or unlinkabili | ||
| XN3 | XN3-t1 | text | text/XN3-t1.json | banned_matches=0 | §5.7, §11.2, §11.3 | LITERAL REGEX-UNIT CHECK on stored strings (not the candidate's output; see XN3-r1). CLI output for a backdated record: inclusion is stated, time only as publisher-declared | ||
| XN3 | XN3-r1 | render | render/XN3-r1.json | ACCEPT, exit 0, banned_matches=0 | §11.2, §11.3, §13 | CLI output (text and --json) of the candidate's own CLI for a backdated record: inclusion is stated, time only as publis | ||
| XN3 | XN3-r2 | render | render/XN3-r2.json | ACCEPT, exit 0, banned_matches=0, time_bounds_form | §11.2, §13 | --json time_bounds of the candidate's own CLI for the backdated record with its head also supplied as a known head: ever | ||
| XN3 | XN3-r3 | render | render/XN3-r3.json | ACCEPT, exit 0, banned_matches=0, time_bounds_form | §11.2, §10, §13 | --json time_bounds of the candidate's own CLI for an export with no heads: each event gets the §11.2 unanchored entry {s | ||
| XN4 | XN4-1 | verify | verify/XN4-1.json | ACCEPT | §6.5, §10, §17 | head 2's signed tip map dishonestly keeps the record's tip at seq 0 although seq 1 (CONFIRM) is in head 2's log; an expo | ||
| XN4 | XN4-2 | verify | verify/XN4-2.json | REJECT | TIP_BEHIND | §6.5, §10 | same dishonest head 2; an export holding seq 1 with its inclusion proof in head 2 | |
| XN5 | XN5-1 | verify | verify/XN5-1.json | ERROR | LOCAL_CAP | §3.5, §14 | base export within every protocol limit, verifier declares a local cap of 4,096 export bytes | |
| XN5 | XN5-2 | verify | verify/XN5-2.json | REJECT | LIMIT_SIZE | §3.5, §14 | export of 16 MiB + 1 bytes with a local cap of 1 MiB: the protocol limit is checked first | |
| XN6 | XN6-1 | verify | verify/XN6-1.json | REJECT | HEAD_CONSISTENCY_UNPROVEN | §8.5, §10 | two genuinely consistent signed export heads with the consistency proof omitted | |
| XN6 | XN6-2 | verify | verify/XN6-2.json | REJECT | PROOF_INCLUSION | §6.5, §10 | export tip leaf tampered (last_seq 9): its membership proof fails; a valid known tip for the same head exists | |
| XN6 | XN6-3 | verify | verify/XN6-3.json | ACCEPT | §9.1, §10 | known-heads tip with a tampered leaf: ignored with a warning, no TIP_* finding | ||
| XN6 | XN6-4 | verify | verify/XN6-4.json | ERROR | WITNESS_UNPROVEN | §9.2, §10 | mirror holds heads 0 and 1, head 1's file without its consistency proof | |
| XN6 | XN6-5 | verify | verify/XN6-5.json | REJECT | HEAD_CHAIN_GAP | §8.5, §10 | export head chain 0, 2 (head 1 left out); inclusion proofs against head 2 | |
| XN6 | XN6-6 | verify | verify/XN6-6.json | REJECT | PLAINTEXT_MISSING | §8.4, §10 | plaintext claims party P but carries no p member | |
| XN7 | XN7-1 | verify | verify/XN7-1.json | DETECT | HEAD_FORK_SAME_SIZE | §9.4, §10 | N7: known head W (n 1, size 1, root A) vs export heads H2 (n 2, size 1, root B) and H3 (n 3, size 2); dates and | |
| XN7 | XN7-2 | verify | verify/XN7-2.json | DETECT | HEAD_FORK_SAME_SIZE | §9.2, §9.4, §10 | as XN7-1 with W supplied as the only mirror head file | |
| XN7 | XN7-3 | verify | verify/XN7-3.json | DETECT | HEAD_FORK_SAME_SIZE | §6.5, §9.4, §10 | known head 2 has the same tree_size and log_root as export head 1 but a different tip_root | |
| XN7 | XN7-4 | verify | verify/XN7-4.json | ACCEPT | §9.4, §10 | control: known head 2 with no new events has the same tree_size, log_root and tip map as export head 1 | ||
| XNULL | XNULL-1 | verify | verify/XNULL-1.json | REJECT | JSON_NULL | §3.4 | absent != null: export member keys written as null | |
| XNULL | XNULL-2 | verify | verify/XNULL-2.json | REJECT | JSON_NULL | §3.4 | absent != null: auth.agent_key_id written as null in a signed event | |
| XSTATE | XSTATE-1 | verify | verify/XSTATE-1.json | ACCEPT | §11.1 | record in state REJECTED verifies: verifier ACCEPT (VERIFIED != ACCEPTED) |
#Profile extension weio-ed25519-only/1 (SPEC §15A; not part of unqualified r8, r8.1 or r8.1a conformance)
14 cases, each with the member "profile": "weio-ed25519-only/1" (verify P1-1 to P1-11, digest P1-d1 to P1-d3; ids and keys in TEST-KEYS.json, section profile). They run like any verify or digest fixture, and the runner counts them apart from the base set. The verifier half of each case is r8: a verifier cannot see the profile (§15A.0), so a conforming verifier reproduces expect.result, expect.code and the rest as for any other case. The server half is the profile's: server = REFUSE with server_code (a profile code from §15A.7, or r8's R3_ERASED_ACTOR for P1-6) and server_refused_seq (the seq of the first event the server refuses). Server expectations are not executed by the fixture runner. Salts in these fixtures are derived from a seed (TEST-ONLY); a real server draws them from a CSPRNG (§15A.2).
| Group | Fixture | Kind | File | Expected | Code | Spec § | Server | Case |
|---|---|---|---|---|---|---|---|---|
| P1 | P1-1 | verify | verify/P1-1.json | ACCEPT | §4.2, §4.3, §5.2, §5.8, §15A, §8.4, §10 | Profile weio-ed25519-only/1, full record COMMIT, CONFIRM, DELIVER, ACCEPT: both parties ed25519, no email, each party digest is the §5.8 HMAC over its exact identifier; the export carries the plaintext, whose email is the identifier | ||
| P1 | P1-2 | verify | verify/P1-2.json | ACCEPT | §4.2, §4.3, §5.2, §5.8, §15A, §8.4, §10 | Profile weio-ed25519-only/1, the same record as P1-1 exported without plaintext (the default profile export): the verifier reports PLAINTEXT_UNAVAILABLE for each role | ||
| P1 | P1-3 | verify | verify/P1-3.json | ACCEPT | §4.2, §4.3, §5.2, §5.8, §15A, §5.3, §5.4 | Profile weio-ed25519-only/1: COMMIT, CONFIRM, AMEND (P), CONFIRM (C), DELIVER, ACCEPT, every event ed25519 | ||
| P1 | P1-4 | verify | verify/P1-4.json | ACCEPT | §4.2, §4.3, §5.2, §5.8, §15A, §5.3, §5.6 | Profile weio-ed25519-only/1: COMMIT, CONFIRM, DELIVER, ACCEPT, REVERSE (P), CONFIRM (C): the record ends REVERSED, every event ed25519 | ||
| P1 | P1-5 | verify | verify/P1-5.json | ACCEPT | §4.2, §4.3, §5.2, §5.8, §15A, §5.7, §10 | Profile weio-ed25519-only/1: ACCEPTed record, then ERASE of C (server event), then P writes a DISPUTE: the erased role is reported, the other role's later event stands; the export carries P's plaintext (the identifier) and none for C | ||
| P1 | P1-6 | verify | verify/P1-6.json | REJECT | R3_ERASED_ACTOR | §4.2, §4.3, §5.2, §5.8, §15A, §5.7 | REFUSE R3_ERASED_ACTOR (seq 5) | Profile weio-ed25519-only/1: ERASE of C, then a DISPUTE written by C (ed25519, signed by C's committed key): REJECT R3_ERASED_ACTOR; a server refuses the write |
| P1 | P1-7 | verify | verify/P1-7.json | REJECT | PLAINTEXT_AFTER_ERASE | §4.2, §4.3, §5.2, §5.8, §15A, §5.7, §8.4, §10 | Profile weio-ed25519-only/1: the P1-5 export with C's plaintext (identifier and k_rec, a copy taken before the ERASE) put back in: REJECT PLAINTEXT_AFTER_ERASE | |
| P1 | P1-8 | verify | verify/P1-8.json | ACCEPT | §4.2, §4.3, §5.2, §5.8, §15A, §15A.3 | REFUSE PROFILE_KEY_UNPROVEN (seq 0) | Profile weio-ed25519-only/1, refusal example: P commits a key that P itself holds as C's agent_key, then writes C's CONFIRM and ACCEPT with it. The verifier ACCEPTs; a profile server REFUSEs the COMMIT (C never proved that key) | |
| P1 | P1-9 | verify | verify/P1-9.json | ACCEPT | §4.2, §4.3, §5.2, §5.8, §15A, §5.3, §15A.2 | REFUSE PROFILE_ID_EQUAL (seq 0) | Profile weio-ed25519-only/1, refusal example: P and C commit the same agent_key, so both identifiers are equal; the two salts differ, so the two digests differ. The verifier ACCEPTs; a profile server REFUSEs the COMMIT before it computes any digest | |
| P1 | P1-10 | verify | verify/P1-10.json | ACCEPT | §4.2, §4.3, §5.2, §5.8, §15A, §4.2, §12, §15A.4 | REFUSE PROFILE_EMAIL_TOKEN (seq 1) | Profile weio-ed25519-only/1, refusal example: C's CONFIRM is written with auth.method email_token (party_digest = C's digest). The verifier ACCEPTs it; a profile server REFUSEs any email_token event | |
| P1 | P1-11 | verify | verify/P1-11.json | REJECT | PLAINTEXT_MISSING | §4.2, §4.3, §5.2, §5.8, §15A, §5.7, §8.4, §10, §15A.6 | Profile weio-ed25519-only/1: the P1-1 record, C not erased, exported with plaintext {claimed: ["C"]} and no plaintext.c (C's plaintext is claimed and missing): REJECT PLAINTEXT_MISSING | |
| P1 | P1-d1 | digest | digest/P1-d1.json | digest | §5.8, §15A.1, §15A.2 | Profile weio-ed25519-only/1: the party P digest of record P1-1 is the §5.8 HMAC over the identifier k-<key_id of P's agent_key>@registry.weio.invalid | ||
| P1 | P1-d2 | digest | digest/P1-d2.json | digest | §5.8, §15A.2 | Profile weio-ed25519-only/1: the identifier of record P1-9 under the P salt; P1-d2 and P1-d3 give two different digests for one identifier | ||
| P1 | P1-d3 | digest | digest/P1-d3.json | digest | §5.8, §15A.2 | Profile weio-ed25519-only/1: the identifier of record P1-9 under the C salt; P1-d2 and P1-d3 give two different digests for one identifier |
#Vectors the spec cannot make testable as fixtures
| Vector | Reason |
|---|---|
| V25 | A write authorised only by the share token is refused by the server (§12); no wire field carries a share token as authority. V26 covers the export side. |
| V27 | Referrer-Policy: no-referrer and hashed share-token logs are web-server behaviour (§12). |
| V40 | Deletion from backups and stores after ERASE is an operations duty (§12). A verifier cannot observe it (§5.7, r7 N2); V37-d* show that a copy exported before the ERASE still links. |
| V57 (server half) | Refusing secret-like note patterns is server-side; the wire half is V57-1. |
| V44 (package-text half) | Scanning an implementation's own source is not wire data. The CLI-output half is render/V44-r1 (the candidate's own CLI) and text/V44-t1 (a literal regex-unit check). |
| V36 (scale) | The vector names 10^6 candidates; V36-d1 uses 50. V36-d2 fixes the counting rule (§15). |
| N4 (stronger completeness) | Proving that a signed tip map was derived from every log leaf needs a full-log audit, which v0 does not define (§6.5); XN4-1 documents the limit. |