# Handoff v0 SPEC r8.1a fixtures: index 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-@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. |