NORAEarly Access

Appendices · Chapter 43

Appendix F — Divergences from the spec {.unnumbered}

Appendix F — Divergences from the spec

Where this list is silent, the spec governs. Every entry states: what the spec requires, what this implementation does instead, and why.

Live divergences

1. Repository naming

Spec: Meridian-Canon (one n). This repo: Meridian-Cannon (two n's) for historical reasons. The inconsistency is unresolved. Why: The textbook preserves both spellings: Meridian-Cannon for the repository, Meridian-Canon for the specification. No change to conformance. ### 2. Embedding model defaults Spec: nomic-embed-text-v1.5 (768-d) on SQLite; bge-large-en-v1.5 (1024-d) on Postgres. This textbook: Chapter 9 introduces BGE-M3 and Nomic v2-MoE as defaults for new builds; spec defaults remain documented for backward compatibility. Why: Per dossier 03, the spec defaults are the 2024 generation; BGE-M3 and Nomic v2-MoE are the 2026 successors. No change to attestation byte-shape. ### 3. Cryptopals-equivalent for canonicalization Spec: No specific lab prescribed. This textbook: Lab 7 — a six-problem set walking from naïve canonicalization to the parser-mismatch attack, identified in dossier 01 as a pedagogical gap. Why: Canonicalization byte-exactness is best learned by attacking it. The lab is supplementary; it is not a Canon conformance requirement. ### 4. Second-language verifier Spec: Implementation-neutral; no second language required. This textbook: Lab 25 requires implementing the verifier in Go (or Rust) and proving byte-for-byte agreement with the Python reference. Why: Re-implementation in a second language is the only reliable way to verify that canonicalization is byte-exact. This is pedagogy, not a Canon conformance requirement. ### 5. EU AI Act compliance overlay Spec: Silent on EU AI Act compliance. This textbook: Appendix C and Chapter 26 treat it as an optional overlay for systems deployed in EU jurisdictions. No effect on R1–R9 conformance. ### 6. Status of FRE 707 Spec: Frames FRE 707 as an open question. This textbook: Explicit that FRE 707 is proposed but not law as of May 2026 (see Chapter 3, Appendix C, dossier 05). The spec is silent on the timeline. ### 7. Key rotation implemented; formal revocation not implemented What diverges. The spec (§ 6.4) describes a key lifecycle that includes revocation: a previously-issued key can be invalidated so that attestations signed under it are no longer considered valid. The meridian-canon rotate-key CLI command (Chapter 23, meridian/canon/keys.py) implements rotation — generating a new Ed25519 keypair, recording the prior public key and rotation timestamp in the audit log, and updating the active key in the Keychain — but it does not implement revocation. Existing attestations signed under the rotated-out key remain verifiable; there is no mechanism to mark them invalid or to publish a revocation list. Why. Revocation requires a distribution channel (a revocation endpoint or a signed revocation list that verifiers can fetch). That infrastructure is out of scope for the current implementation; the textbook does not yet cover deployment of the attestation signing service as a network-accessible component. Implication. In the current implementation a compromised key cannot be actively invalidated. The mitigation is procedural: rotate promptly on suspicion of compromise, record the rotation event in the audit log with a reason field, and disclose the rotation to any relying party that holds attestations signed under the prior key. Chapter 23 notes this limitation explicitly and defers formal revocation to a future Phase C implementation. ### 8. DSSE adoption — breaking change in signature format What changed. Canon v0.2.0 adopts DSSE per the CNCF in-toto specification. Prior to v0.2.0, Canon used bare Ed25519 over JCS bytes — sign(SHA-256(JCS(obj))). v0.2.0 uses sign(PAE(payload_type, JCS(obj))). This is a breaking change in the signature format: a v0.1.x signature over an attestation body is not a valid v0.2.0 DSSE signature over the same body, and vice versa. Implication. Attestations sealed with emit() (v0.1.x) verify via the seven-step legacy path. Attestations sealed with emit_dsse() (v0.2.0) verify via the DSSE three-step path. Both paths are supported by conformant verifiers. The dsse_envelope key is the discriminator. Migration. Existing v0.1.x attestations are not invalidated. No re-sealing is required. For new attestations, emit_dsse() is preferred. emit() is retained for backward compatibility and documented as legacy. ### 9. chain_hash as Canon extension to DSSE What diverges. The DSSE base specification does not include a chain_hash field in the envelope. Canon v0.2.0 adds chain_hash as an extension field containing SHA-256(base64url_decode(payload)). This allows field-level integrity checking without implementing the full PAE verification procedure. Why. The chain_hash field is a convenience for recipients who want to confirm payload integrity quickly (a single SHA-256) before committing to the PAE computation and Ed25519 verification. It is not a substitute for signature verification but provides a fast pre-check. Implication. A verifier that only checks chain_hash is not conformant — it must also verify the Ed25519 signature over the PAE. The chain_hash field is documented as a convenience; the PAE signature is authoritative. ### 10. payload_type version encoding — Canon convention What diverges. DSSE specifies that payload_type is a URI identifying the content type of the payload. It does not require version information in the URI. Canon v0.2.0 encodes the spec version in the payload_type string: application/vnd.nora.canon.attestation+json; version=0.2.0. This is a Canon convention, not a DSSE requirement. Why. Encoding the version in payload_type ensures that the version is part of the signed message (via PAE). A verifier can detect version mismatches from the payload_type alone, without parsing the payload. This makes version detection fast and tamper-evident. Implication. A DSSE verifier that does not understand Canon's version parameter will still verify the signature correctly — the parameter is part of the type string, not a separate field. It is a Canon extension to DSSE naming conventions, not a change to the DSSE protocol. ### 12. Epistemic Neutrality Masking uses a rule-based masker, not a trained classifier What diverges. The spec (§ 5.2, R5 — Epistemic Neutrality) calls for a masking component that suppresses author-identifying signals using a model trained to recognize those signals across diverse text styles. The current implementation in meridian/witness/local_chunker.py and part3_architecture/18_epistemic_masking.md uses a rule-based masker: a configurable list of named-entity patterns, pronoun substitution rules, and stopword filters defined in YAML (see docs/textbook divergence note in EDITORIAL.md). The masker does not learn from data and does not generalize beyond its configured pattern set. Why. A trained classifier requires a labeled corpus of author-attributed text, a training pipeline, and periodic retraining as writing styles shift — infrastructure that is not yet in place. The rule-based approach is deterministic, auditable, and sufficient for the current evidence types (email headers, SMS metadata, structured records) where author signals are largely confined to known fields. Implication. The rule-based masker may fail to suppress subtle stylometric signals in free-text fields (narrative case notes, long-form correspondence). Any consumer of Meridian-Cannon attestations relying on R5 for anonymization should treat the current ENM as a best-effort mitigation, not a guarantee. Chapter 18 documents the pattern set in full and includes a ✻ Try This exercise that demonstrates the attack surface. Replacing the rule-based masker with a trained classifier is listed as a Phase C deliverable. ## Resolved divergences (none yet) ## Open questions - Should the textbook include a Rust reference verifier as a separate published artifact? Decision pending. - Should the textbook ship a Quarto build pipeline by default, or remain Markdown-only? Decision pending; per dossier 06 Quarto is the recommendation. - Should the standalone nora-canon-verifier PyPI package ship from this repository or from a separate one? Decision pending.

Status: living document. Update on every divergence noticed.