KB-EEE6

authority_seal_encoder.py

36 min read Revision 1
fix7codexauthority-sealrejected2026-06-11

#!/usr/bin/env python3

============================================================================

FIX7-CANON-V1 AUTHORITY-SEAL ENCODER -- N7 / N8 / P7 byte-exact contract

authority_seal_encoder_id: FIX7-CANON-V1-AUTHORITY-SEAL-ENCODER

authority_seal_schema: FIX7-AUTHORITY-SEAL-V1

REV 2026-06-11 (FAIL-OPEN + PROVENANCE PATCH, Codex final-seal reject closure):

Adds (1) per-field SEMANTIC value grammar (hex256 / id / identity / timestamp

/ positive-int / path / decision-token) that fails closed BEFORE any digest is

produced; (2) report-set validation (no empty / no duplicate doc-id / no

duplicate record / valid id+revision / deterministic sort); (3) an explicit

PROVENANCE class system so REHEARSAL or otherwise non-authority N6 input can

NEVER enter a REAL N7/N8/P7 seal. The rehearsal path (encode_node) is

unchanged byte-for-byte for VALID fixtures (pins preserved), but a REAL seal

must go through encode_real_n7/n8/p7, which are provenance-gated and remain

BLOCKED until a real non-rehearsal N1..N6 chain is supplied (true blocker).

PURPOSE (Codex AS-P1..AS-P4 + FINAL-AS-* closure):

OFFLINE, stdlib-only, deterministic, fail-closed executable contract for the

three authority-seal nodes N7 / N8 / P7. Lets Codex (and a self-Codex dry-run)

author/verify each seal WITHOUT inventing any field name, order, tag, byte

encoding, value grammar, or provenance class.

IT DOES NOT:

- mutate production, KB, PG, Directus, registry, or system_issues;

- recompute the Packet V3 engineering digests (N1..N6 / membership); those are

CONSUMED as inputs exactly as the canonicalizer --produce emits;

- self-seal / self-approve: the OWNER/CODEX authority-input fields are required

and are NOT fabricated here (fixtures are explicitly labelled FIXTURE and are

used only by --selftest to prove determinism + fail-closed behaviour);

- promote a REHEARSAL corpus to real authority evidence (provenance gate).

GRAMMAR (copied byte-for-byte from canonicalizer rev3 SSOT

sha256 49c386a9b9666c09786fc4f89bc79776b6046eaee6f4da6d8537d2c753b734d0):

FORBIDDEN_BYTES = {TAB, LF, CR, NUL, backslash}

rec(*f) = ("\t".join(f) + "\n").encode() (rejects TAB/LF in a field)

digest(tag,recs) = sha256( (tag+"\n").encode() + b"".join(recs) )

=> identical encoding to every other FIX7 seal digest. No new encoding.

AUTHORITY-SEAL DAG (engineering edges N1..N8/N9 copied verbatim from the

canonicalizer SSOT EDGES dict; this layer ADDS only the P7 pin node):

N7 -> N2,N3,N4,N5,N6,N1 (envelope manifest)

N8 -> N2,N5,N6,N7 (detached seal; depends on N7)

P7 -> N2,N7,N8 (authoritative pin; depends on N7 and N8)

=> N7 NEVER binds N8 or P7; N8 NEVER binds P7. Proven acyclic below.

Invocation:

python3 authority_seal_encoder.py --selftest -> exit 0 iff all vectors pass

python3 authority_seal_encoder.py --emit-fixture -> print fixture digests

============================================================================

import hashlib, re, sys

SCHEMA = "FIX7-AUTHORITY-SEAL-V1"

def sha(b: bytes) -> str: return hashlib.sha256(b).hexdigest()

---- grammar (verbatim from canonicalizer rev3) ---------------------------

FORBIDDEN_BYTES = {0x09, 0x0A, 0x0D, 0x00, 0x5C} # TAB LF CR NUL backslash

class Reject(Exception): def init(self, status, detail=""): super().init(f"{status}: {detail}") self.status = status

def _check_field(value): if not isinstance(value, str): raise Reject("SEAL_FIELD_NOT_STRING", repr(value)) b = value.encode("utf-8") if any(byte in FORBIDDEN_BYTES for byte in b): raise Reject("SEAL_FIELD_FORBIDDEN_BYTE", repr(value)) return value

def rec(*f): for x in f: _check_field(x) if "\t" in x or "\n" in x: # canonicalizer-identical guard raise Reject("SEAL_FIELD_RESERVED_TOKEN", "sep in value") return ("\t".join(f) + "\n").encode()

def digest(tag, records): return sha((tag + "\n").encode() + b"".join(records))

---- value grammar (NEW: semantic per-field validation, fail-closed) ------

Each kind has a deterministic, anchored grammar. Any value that does not match

is rejected with an exact status BEFORE a digest can be produced.

RE_HEX256 = re.compile(r"^[0-9a-f]{64}$") # exactly 64 lowercase hex RE_ID = re.compile(r"^[A-Za-z0-9][A-Za-z0-9.:@+/-]{0,199}$") RE_DECISION = re.compile(r"^[A-Z0-9][A-Z0-9]{0,127}$") # uppercase decision token RE_TS = re.compile(r"^\d{4}-\d{2}-\d{2}T\d{2}:\d{2}:\d{2}(.\d{1,9})?Z$") # RFC3339 UTC RE_PATH = re.compile(r"^[A-Za-z0-9][A-Za-z0-9._/@:+-]{0,399}$") RE_POSINT = re.compile(r"^[1-9][0-9]{0,17}$") # positive integer, no leading 0

def _v_hex(field, v): if not RE_HEX256.match(v): raise Reject("SEAL_FIELD_NOT_HEX", f"{field}={v!r} (need 64 lowercase hex)")

def _v_id(field, v): if not RE_ID.match(v): raise Reject("SEAL_FIELD_BAD_ID", f"{field}={v!r}")

def _v_identity(field, v): # non-empty, printable ASCII (0x20-0x7E), not all-whitespace if not v or not all(0x20 <= ord(c) <= 0x7E for c in v) or not v.strip(): raise Reject("SEAL_FIELD_BAD_IDENTITY", f"{field}={v!r}")

def _v_timestamp(field, v): if not RE_TS.match(v): raise Reject("SEAL_FIELD_BAD_TIMESTAMP", f"{field}={v!r} (need RFC3339 UTC ...Z)")

def v_decision(field, v): if not RE_DECISION.match(v): raise Reject("SEAL_FIELD_BAD_ENUM", f"{field}={v!r} (decision token [A-Z0-9])")

def _v_posint(field, v): if not RE_POSINT.match(v): raise Reject("SEAL_FIELD_BAD_INT", f"{field}={v!r} (need positive integer)")

def _v_path(field, v): if not RE_PATH.match(v): raise Reject("SEAL_FIELD_BAD_PATH", f"{field}={v!r}")

VALIDATORS = { "hex": _v_hex, "id": _v_id, "identity": _v_identity, "timestamp": _v_timestamp, "decision": _v_decision, "posint": _v_posint, "path": _v_path, "const": None, }

field name -> grammar kind (the encoding contract for VALUES)

FIELD_KIND = { "schema_version": "const", "node_id": "const", "approval_scope": "const", "seal_scope": "const", "pin_scope": "const", "membership_sha256": "hex", "canonicalizer_sha256": "hex", "marker_fence_registry_sha256": "hex", "superseded_boundary_sha256": "hex", "guard_set_sha256": "hex", "active_corpus_sha256": "hex", "envelope_manifest_sha256": "hex", "detached_seal_sha256": "hex", "report_documents_digest": "hex", "pinned_canonicalizer_sha256": "hex", "pinned_packet_v3_tree_sha256": "hex", "approval_event_id": "id", "approver_identity": "identity", "sealed_by": "identity", "approval_event_timestamp": "timestamp", "sealed_at": "timestamp", "owner_blueprint_decision": "decision", "pinned_canonicalizer_revision": "posint", "pinned_canonicalizer_utf8_bytes": "posint", "pinned_canonicalizer_document_id": "path", "parent_checkpoint": "path", "codex_report_document": "path", "codex_checkpoint_document": "path", }

def validate_value(field, v): """Semantic grammar gate. const fields are covered by the constant check.""" kind = FIELD_KIND.get(field) if kind is None: raise Reject("SEAL_FIELD_UNKNOWN_KIND", field) if kind == "const": return if v == "": raise Reject("SEAL_FIELD_EMPTY", field) VALIDATORS[kind](field, v)

---- authority-seal DAG (engineering edges verbatim; + P7) -----------------

EDGES = { "N1": [], "N2": [], "N3": [], "N4": [], "N5": [], "N6": ["N1"], "N7": ["N2", "N3", "N4", "N5", "N6", "N1"], "N8": ["N2", "N5", "N6", "N7"], "P7": ["N2", "N7", "N8"], "N9_DIAG": [], }

def has_cycle(e): # verbatim from canonicalizer c = {k: 0 for k in e} def dfs(u): c[u] = 1 for v in e[u]: if c[v] == 1 or (c[v] == 0 and dfs(v)): return True c[u] = 2 return False return any(c[k] == 0 and dfs(k) for k in e)

---- domain tags (N7/N8 reserved in canonicalizer RESERVED_TOKENS) ---------

TAGS = { "N7": "FIX7_ACTIVE_AUTHORITY_ENVELOPE_MANIFEST_V1", "N8": "FIX7_CODEX_DETACHED_SEAL_V1", "P7": "FIX7_AUTHORITY_SEAL_PIN_V1", "REPORTS": "FIX7_CODEX_SEAL_REPORTS_V1", }

---- fixed field rosters (the ENCODING is the order) -----------------------

ROSTERS = { "N7": [ "schema_version", "node_id", "membership_sha256", # N1 doc-set anchor (per-doc N1 bound via N6) "canonicalizer_sha256", # N2 "marker_fence_registry_sha256", # N3 "superseded_boundary_sha256", # N4 "guard_set_sha256", # N5 "active_corpus_sha256", # N6 "approval_event_id", # A1 (Codex) "approver_identity", # A2 (owner + Codex) "approval_event_timestamp", # A3 (Codex) "owner_blueprint_decision", # A5 (owner) "approval_scope", # constant ], "N8": [ "schema_version", "node_id", "canonicalizer_sha256", # N2 "guard_set_sha256", # N5 "active_corpus_sha256", # N6 "envelope_manifest_sha256", # N7 <-- N8 depends on N7 "sealed_by", # Codex signer identity "sealed_at", # Codex timestamp "parent_checkpoint", # checkpoint doc id@rev "report_documents_digest", # FIX7_CODEX_SEAL_REPORTS_V1 sub-digest "seal_scope", # constant ], "P7": [ "schema_version", "node_id", "pinned_canonicalizer_document_id", "pinned_canonicalizer_revision", "pinned_canonicalizer_utf8_bytes", "pinned_canonicalizer_sha256", # == N2 "pinned_packet_v3_tree_sha256", "codex_report_document", # id@rev "codex_checkpoint_document", # id@rev "envelope_manifest_sha256", # N7 "detached_seal_sha256", # N8 <-- P7 depends on N8 "approval_event_id", # A1 "pin_scope", # constant ], }

fields that, if present in a node's input, would create a back-edge (cycle)

CYCLE_FORBIDDEN = { "N7": {"detached_seal_sha256", "authority_seal_pin_sha256", "envelope_manifest_sha256"}, "N8": {"authority_seal_pin_sha256", "detached_seal_sha256"}, "P7": {"authority_seal_pin_sha256"}, }

constant fields whose value is contract-fixed

CONST = { "schema_version": SCHEMA, "N7": {"node_id": "N7", "approval_scope": "BLUEPRINT_SEAL_ONLY_NO_IMPLEMENTATION"}, "N8": {"node_id": "N8", "seal_scope": "BLUEPRINT_SEAL_ONLY_NO_IMPLEMENTATION"}, "P7": {"node_id": "P7", "pin_scope": "CANDIDATE_TO_AUTHORITATIVE_PIN_BLUEPRINT_ONLY"}, }

OUTPUT_FIELD = { "N7": "envelope_manifest_sha256", "N8": "detached_seal_sha256", "P7": "authority_seal_pin_sha256", }

---- provenance class system (NEW: AS-PROVENANCE) -------------------------

Every engineering/authority input carries a provenance class. A REAL seal may

only consume inputs whose class is allowed for real sealing. REHEARSAL (and the

explicit FORBIDDEN sentinel) can NEVER enter a real seal.

PROVENANCE_CLASSES = { "ENGINEERING_VERIFIED_CANDIDATE", # canonicalizer/Packet-V3 candidate, reproduced "REHEARSAL", # fixture / dress-rehearsal value (NOT real) "AUTHORITY_INPUT", # owner/Codex supplied authority value "CODEX_AUTHORED", # Codex signer/seal value "OFFICIAL_PIN", # already-sealed official pin "FORBIDDEN_FOR_REAL_SEAL", # explicit sentinel: never seal }

classes acceptable for the N6/engineering corpus input of a REAL seal

PROVENANCE_ALLOWED_REAL_CORPUS = {"ENGINEERING_VERIFIED_CANDIDATE", "OFFICIAL_PIN"}

classes acceptable for an authority/signer input of a REAL seal

PROVENANCE_ALLOWED_REAL_AUTHORITY = {"AUTHORITY_INPUT", "CODEX_AUTHORED", "OFFICIAL_PIN"}

def assert_provenance(field, prov_class, allowed): if prov_class is None: raise Reject("SEAL_PROVENANCE_MISSING", field) if prov_class not in PROVENANCE_CLASSES: raise Reject("SEAL_PROVENANCE_UNKNOWN_CLASS", f"{field}={prov_class!r}") if prov_class == "REHEARSAL": raise Reject("SEAL_PROVENANCE_REHEARSAL_BLOCKED", f"{field}: REHEARSAL input may not enter a real seal") if prov_class not in allowed: raise Reject("SEAL_PROVENANCE_FORBIDDEN_CLASS", f"{field}={prov_class!r} not in {sorted(allowed)}")

---- the encoder (rehearsal/generic path) ---------------------------------

def encode_node(node_id, pairs, claimed_tag=None): """pairs: ordered list of (field_name, value). Returns the node digest. Fail-closed: every contract violation raises Reject with an exact status. This is the REHEARSAL/generic encoder: it validates STRUCTURE + VALUE GRAMMAR but is provenance-agnostic. A REAL seal must use encode_real_n7/n8/p7.""" if node_id not in ROSTERS: raise Reject("SEAL_UNKNOWN_NODE", node_id) roster = ROSTERS[node_id] tag = TAGS[node_id] if claimed_tag is not None and claimed_tag != tag: raise Reject("SEAL_DOMAIN_TAG_MISMATCH", f"{claimed_tag} != {tag}") names = [n for n, _ in pairs] given = set(names) # 1. cycle guard FIRST (a forbidden descendant field => back-edge) bad = given & CYCLE_FORBIDDEN[node_id] if bad: raise Reject("SEAL_HASH_GRAPH_CYCLE", f"{node_id} may not bind {sorted(bad)}") # 2. missing / extra expected = set(roster) missing = expected - given if missing: raise Reject("SEAL_INPUT_MISSING", f"{sorted(missing)}") extra = given - expected if extra: raise Reject("SEAL_INPUT_EXTRA", f"{sorted(extra)}") # 3. duplicate field names if len(names) != len(given): raise Reject("SEAL_INPUT_DUPLICATE", "duplicate field name") # 4. exact order if names != roster: raise Reject("SEAL_FIELD_ORDER_MISMATCH", f"{names} != {roster}") # 5. constant-field values consts = {"schema_version": CONST["schema_version"], **CONST[node_id]} d = dict(pairs) for k, v in consts.items(): if d[k] != v: raise Reject("SEAL_CONSTANT_FIELD_MISMATCH", f"{k}={d[k]!r} != {v!r}") # 6. forbidden-byte gate FIRST (preserves SEAL_FIELD_FORBIDDEN_BYTE precedence) for n, v in pairs: _check_field(v) # 7. semantic value grammar (NEW): every field must match its kind for n, v in pairs: validate_value(n, v) # 8. encode in fixed roster order records = [rec(n, v) for n, v in pairs] return digest(tag, records)

def report_documents_digest(report_pairs): """Sub-digest binding (document_id, revision) report records. Fail-closed: rejects empty sets, duplicate document ids, duplicate records, invalid document ids, and invalid revisions. Records are deterministically sorted before hashing (input order does not matter, but validity does).""" if not report_pairs: raise Reject("SEAL_REPORT_SET_EMPTY", "report set has zero records") seen_records = set() seen_docs = set() norm = [] for item in report_pairs: if not (isinstance(item, (list, tuple)) and len(item) == 2): raise Reject("SEAL_REPORT_DOC_ID_INVALID", f"record not (doc,rev): {item!r}") doc, revn = item if not isinstance(doc, str) or not RE_PATH.match(doc): raise Reject("SEAL_REPORT_DOC_ID_INVALID", repr(doc)) if not isinstance(revn, str) or not RE_POSINT.match(revn): raise Reject("SEAL_REPORT_REVISION_INVALID", f"{doc} rev={revn!r}") if (doc, revn) in seen_records: raise Reject("SEAL_REPORT_SET_DUPLICATE", f"duplicate record {doc}@{revn}") if doc in seen_docs: raise Reject("SEAL_REPORT_SET_DUPLICATE", f"duplicate document id {doc}") seen_records.add((doc, revn)); seen_docs.add(doc); norm.append((doc, revn)) recs = sorted(rec(doc, revn) for doc, revn in norm) return digest(TAGS["REPORTS"], recs)

def verify_pin(expected_digest, pairs): """Recompute P7 over pairs; True iff it matches expected. Detects any mutation of a pinned field (canonicalizer hash, Packet V3 tree, etc.).""" try: return encode_node("P7", pairs) == expected_digest except Reject: return False

def seal_p7(pairs, prose_only=False): """Author a P7 pin. A prose-only pin (no executable encode) is rejected.""" if prose_only: raise Reject("SEAL_PROSE_ONLY_PIN_REJECTED", "P7 must be a computed digest") dig = encode_node("P7", pairs) if not (isinstance(dig, str) and len(dig) == 64 and all(c in "0123456789abcdef" for c in dig)): raise Reject("SEAL_PROSE_ONLY_PIN_REJECTED", "no 64-hex digest produced") return dig

---- REAL seal path (provenance-gated; BLOCKED until real N6 exists) -------

def encode_real_n7(pairs, provenance=None, real_n6_available=False): """Author a REAL N7 envelope manifest. Unlike encode_node (rehearsal), this REQUIRES a provenance map and refuses REHEARSAL / forbidden / missing classes for the engineering corpus inputs. Even with a correct class, it stays BLOCKED until a real non-rehearsal N1..N6 chain is supplied (real_n6_available=True with first-hand evidence). In this lane no such chain exists => true blocker.""" provenance = provenance or {} # engineering corpus inputs that must carry real (non-rehearsal) provenance for field in ("active_corpus_sha256", "membership_sha256", "canonicalizer_sha256", "marker_fence_registry_sha256", "superseded_boundary_sha256", "guard_set_sha256"): assert_provenance(field, provenance.get(field), PROVENANCE_ALLOWED_REAL_CORPUS) # authority inputs must carry authority/codex provenance for field in ("approval_event_id", "approver_identity", "approval_event_timestamp", "owner_blueprint_decision"): assert_provenance(field, provenance.get(field), PROVENANCE_ALLOWED_REAL_AUTHORITY) if not real_n6_available: raise Reject("SEAL_REAL_N6_NOT_AVAILABLE", "no real non-rehearsal N1..N6 chain exists in this lane") return encode_node("N7", pairs)

def encode_real_n8(pairs, provenance=None, real_upstream=False): provenance = provenance or {} for field in ("sealed_by", "sealed_at", "parent_checkpoint", "report_documents_digest"): assert_provenance(field, provenance.get(field), PROVENANCE_ALLOWED_REAL_AUTHORITY) if not real_upstream: raise Reject("SEAL_REAL_N6_NOT_AVAILABLE", "N8 requires a real (non-rehearsal) N7") return encode_node("N8", pairs)

def encode_real_p7(pairs, provenance=None, real_upstream=False): provenance = provenance or {} for field in ("codex_report_document", "codex_checkpoint_document", "approval_event_id"): assert_provenance(field, provenance.get(field), PROVENANCE_ALLOWED_REAL_AUTHORITY) if not real_upstream: raise Reject("SEAL_REAL_N6_NOT_AVAILABLE", "P7 requires a real (non-rehearsal) N7/N8") return seal_p7(pairs)

===========================================================================

TEST VECTORS (FIXTURE inputs only -- NOT a real seal)

===========================================================================

N2_REV3 = "49c386a9b9666c09786fc4f89bc79776b6046eaee6f4da6d8537d2c753b734d0" MEMBERSHIP = "f2bda8effc7be19b54722828126b82d7d2d48bee5e5e5dc0c8f347ce210fe251" PACKET_V3_TREE = "b95df0a5d2f41f80bea0cef8621c1f8bb0f6b49a40175116418494ed4141ca6d" SSOT_DOC = ("knowledge/dev/reports/architecture/" "t1-fix7-existing-system-refactor-execution-blueprint-2026-06-08/" "canonicalizer-fix7-canon-v1-ssot.md") FX = { "N3": "3" * 64, "N4": "4" * 64, "N5": "5" * 64, "N6": "6" * 64, }

def fixture_n7_pairs(): return [ ("schema_version", SCHEMA), ("node_id", "N7"), ("membership_sha256", MEMBERSHIP), ("canonicalizer_sha256", N2_REV3), ("marker_fence_registry_sha256", FX["N3"]), ("superseded_boundary_sha256", FX["N4"]), ("guard_set_sha256", FX["N5"]), ("active_corpus_sha256", FX["N6"]), ("approval_event_id", "FIXTURE-APPROVAL-EVENT-0001"), ("approver_identity", "FIXTURE-OWNER+FIXTURE-CODEX"), ("approval_event_timestamp", "2026-06-10T00:00:00Z"), ("owner_blueprint_decision", "FIXTURE_OPTION_2_SEAL_ONLY"), ("approval_scope", "BLUEPRINT_SEAL_ONLY_NO_IMPLEMENTATION"), ]

def fixture_n8_pairs(n7): rep = report_documents_digest([ ("knowledge/dev/reports/architecture/codex-fix7-authority-seal-approval-lane-2026-06-10/00-readme-first.md", "1"), ]) return [ ("schema_version", SCHEMA), ("node_id", "N8"), ("canonicalizer_sha256", N2_REV3), ("guard_set_sha256", FX["N5"]), ("active_corpus_sha256", FX["N6"]), ("envelope_manifest_sha256", n7), ("sealed_by", "FIXTURE-CODEX-SIGNER"), ("sealed_at", "2026-06-10T00:00:00Z"), ("parent_checkpoint", "knowledge/.../checkpoint-codex-fix7-authority-seal-approval-lane-2026-06-10.md@1"), ("report_documents_digest", rep), ("seal_scope", "BLUEPRINT_SEAL_ONLY_NO_IMPLEMENTATION"), ]

def fixture_p7_pairs(n7, n8): return [ ("schema_version", SCHEMA), ("node_id", "P7"), ("pinned_canonicalizer_document_id", SSOT_DOC), ("pinned_canonicalizer_revision", "3"), ("pinned_canonicalizer_utf8_bytes", "38756"), ("pinned_canonicalizer_sha256", N2_REV3), ("pinned_packet_v3_tree_sha256", PACKET_V3_TREE), ("codex_report_document", "knowledge/.../codex-fix7-authority-seal-approval-lane-2026-06-10/00-readme-first.md@1"), ("codex_checkpoint_document", "knowledge/.../checkpoint-codex-fix7-authority-seal-approval-lane-2026-06-10.md@1"), ("envelope_manifest_sha256", n7), ("detached_seal_sha256", n8), ("approval_event_id", "FIXTURE-APPROVAL-EVENT-0001"), ("pin_scope", "CANDIDATE_TO_AUTHORITATIVE_PIN_BLUEPRINT_ONLY"), ]

provenance map that WOULD classify the rehearsal corpus -- as REHEARSAL,

proving it can never enter a real seal.

def fixture_rehearsal_provenance(): return {f: "REHEARSAL" for f in ( "active_corpus_sha256", "membership_sha256", "canonicalizer_sha256", "marker_fence_registry_sha256", "superseded_boundary_sha256", "guard_set_sha256", "approval_event_id", "approver_identity", "approval_event_timestamp", "owner_blueprint_decision")}

def _expect_reject(status, fn): try: fn() except Reject as e: if e.status == status: return True, f"OK raised {status}" return False, f"FAIL wrong status {e.status} (wanted {status})" return False, f"FAIL no Reject (wanted {status})"

def selftest(): results = [] def chk(name, ok, note=""): results.append((name, ok, note))

# static DAG acyclicity
chk("DAG acyclic (N7,N8,P7)", not has_cycle(EDGES))
cyc = {k: list(v) for k, v in EDGES.items()}; cyc["N7"] = cyc["N7"] + ["N8"]
chk("injected N7->N8 edge detected as cycle", has_cycle(cyc))

# positive vectors + determinism
n7 = encode_node("N7", fixture_n7_pairs())
n7b = encode_node("N7", fixture_n7_pairs())
chk("N7 encodes to 64-hex", len(n7) == 64 and all(c in "0123456789abcdef" for c in n7), n7)
chk("N7 deterministic", n7 == n7b)
n8 = encode_node("N8", fixture_n8_pairs(n7))
chk("N8 encodes (binds N7) to 64-hex", len(n8) == 64, n8)
chk("N8 deterministic", n8 == encode_node("N8", fixture_n8_pairs(n7)))
p7 = seal_p7(fixture_p7_pairs(n7, n8))
chk("P7 seals (binds N7,N8) to 64-hex", len(p7) == 64, p7)
chk("P7 deterministic", p7 == encode_node("P7", fixture_p7_pairs(n7, n8)))

# negative: missing field
ok, note = _expect_reject("SEAL_INPUT_MISSING",
    lambda: encode_node("N7", fixture_n7_pairs()[:-1]))
chk("missing field -> SEAL_INPUT_MISSING", ok, note)

# negative: extra field
ok, note = _expect_reject("SEAL_INPUT_EXTRA",
    lambda: encode_node("N7", fixture_n7_pairs() + [("rogue_field", "x")]))
chk("extra field -> SEAL_INPUT_EXTRA", ok, note)

# negative: wrong order
swapped = fixture_n7_pairs()
swapped[2], swapped[3] = swapped[3], swapped[2]
ok, note = _expect_reject("SEAL_FIELD_ORDER_MISMATCH",
    lambda: encode_node("N7", swapped))
chk("wrong order -> SEAL_FIELD_ORDER_MISMATCH", ok, note)

# negative: wrong domain tag
ok, note = _expect_reject("SEAL_DOMAIN_TAG_MISMATCH",
    lambda: encode_node("N7", fixture_n7_pairs(), claimed_tag="WRONG_TAG_V1"))
chk("wrong domain tag -> SEAL_DOMAIN_TAG_MISMATCH", ok, note)

# negative: wrong dependency (N3 fed into N8, which does not depend on N3)
n8wrong = fixture_n8_pairs(n7) + [("marker_fence_registry_sha256", FX["N3"])]
ok, note = _expect_reject("SEAL_INPUT_EXTRA",
    lambda: encode_node("N8", n8wrong))
chk("wrong dependency (N3 into N8) -> SEAL_INPUT_EXTRA", ok, note)

# negative: N7 tries to bind N8 -> cycle
n7cyc = fixture_n7_pairs() + [("detached_seal_sha256", n8)]
ok, note = _expect_reject("SEAL_HASH_GRAPH_CYCLE",
    lambda: encode_node("N7", n7cyc))
chk("N7 binds N8 -> SEAL_HASH_GRAPH_CYCLE", ok, note)

# negative: N7 tries to bind P7 -> cycle
n7cyc2 = fixture_n7_pairs() + [("authority_seal_pin_sha256", p7)]
ok, note = _expect_reject("SEAL_HASH_GRAPH_CYCLE",
    lambda: encode_node("N7", n7cyc2))
chk("N7 binds P7 -> SEAL_HASH_GRAPH_CYCLE", ok, note)

# negative: N8 missing N7
n8nomissing = [p for p in fixture_n8_pairs(n7) if p[0] != "envelope_manifest_sha256"]
ok, note = _expect_reject("SEAL_INPUT_MISSING",
    lambda: encode_node("N8", n8nomissing))
chk("N8 missing N7 -> SEAL_INPUT_MISSING", ok, note)

# negative: N8 binds P7 -> cycle
n8cyc = fixture_n8_pairs(n7) + [("authority_seal_pin_sha256", p7)]
ok, note = _expect_reject("SEAL_HASH_GRAPH_CYCLE",
    lambda: encode_node("N8", n8cyc))
chk("N8 binds P7 -> SEAL_HASH_GRAPH_CYCLE", ok, note)

# negative: P7 prose-only pin
ok, note = _expect_reject("SEAL_PROSE_ONLY_PIN_REJECTED",
    lambda: seal_p7(fixture_p7_pairs(n7, n8), prose_only=True))
chk("P7 prose-only -> SEAL_PROSE_ONLY_PIN_REJECTED", ok, note)

# negative: mutated canonicalizer hash -> pin verify fails
mut = fixture_p7_pairs(n7, n8)
mut[5] = ("pinned_canonicalizer_sha256", "0" * 64)
chk("mutated canonicalizer hash -> P7 verify FAIL", not verify_pin(p7, mut))

# negative: mutated Packet V3 tree -> pin verify fails
mut2 = fixture_p7_pairs(n7, n8)
mut2[6] = ("pinned_packet_v3_tree_sha256", "0" * 64)
chk("mutated Packet V3 tree -> P7 verify FAIL", not verify_pin(p7, mut2))

# negative: constant field tampered
bad_const = fixture_n7_pairs()
bad_const[-1] = ("approval_scope", "IMPLEMENTATION_ALLOWED")
ok, note = _expect_reject("SEAL_CONSTANT_FIELD_MISMATCH",
    lambda: encode_node("N7", bad_const))
chk("tampered scope constant -> SEAL_CONSTANT_FIELD_MISMATCH", ok, note)

# negative: forbidden byte (backslash) in a field
bad_byte = fixture_n7_pairs()
bad_byte[8] = ("approval_event_id", "evt\\001")
ok, note = _expect_reject("SEAL_FIELD_FORBIDDEN_BYTE",
    lambda: encode_node("N7", bad_byte))
chk("forbidden byte in field -> SEAL_FIELD_FORBIDDEN_BYTE", ok, note)

# ===== NEW: value grammar negatives (Codex direct probes) =====
grammar_cases = [
    ("N7 canonicalizer not a sha -> NOT_HEX", "SEAL_FIELD_NOT_HEX", "N7",
     lambda p: _set(p, "canonicalizer_sha256", "NOT_A_SHA")),
    ("N7 membership uppercase hex -> NOT_HEX", "SEAL_FIELD_NOT_HEX", "N7",
     lambda p: _set(p, "membership_sha256", "F" * 64)),
    ("N7 canonicalizer 63 hex -> NOT_HEX", "SEAL_FIELD_NOT_HEX", "N7",
     lambda p: _set(p, "canonicalizer_sha256", "a" * 63)),
    ("N7 approval_event_id empty -> EMPTY", "SEAL_FIELD_EMPTY", "N7",
     lambda p: _set(p, "approval_event_id", "")),
    ("N7 approver_identity empty -> EMPTY", "SEAL_FIELD_EMPTY", "N7",
     lambda p: _set(p, "approver_identity", "")),
    ("N7 timestamp bad -> BAD_TIMESTAMP", "SEAL_FIELD_BAD_TIMESTAMP", "N7",
     lambda p: _set(p, "approval_event_timestamp", "not-a-time")),
    ("N7 decision lowercase -> BAD_ENUM", "SEAL_FIELD_BAD_ENUM", "N7",
     lambda p: _set(p, "owner_blueprint_decision", "lower case")),
]
for name, status, node, mut_fn in grammar_cases:
    ok, note = _expect_reject(status, lambda mf=mut_fn, nd=node: encode_node(nd, mf(fixture_n7_pairs())))
    chk(name, ok, note)

# N8 grammar negatives
ok, note = _expect_reject("SEAL_FIELD_EMPTY",
    lambda: encode_node("N8", _set(fixture_n8_pairs(n7), "sealed_by", "")))
chk("N8 sealed_by empty -> SEAL_FIELD_EMPTY", ok, note)
ok, note = _expect_reject("SEAL_FIELD_NOT_HEX",
    lambda: encode_node("N8", _set(fixture_n8_pairs(n7), "report_documents_digest", "NOT_A_SHA")))
chk("N8 report_documents_digest not hex -> SEAL_FIELD_NOT_HEX", ok, note)
ok, note = _expect_reject("SEAL_FIELD_BAD_TIMESTAMP",
    lambda: encode_node("N8", _set(fixture_n8_pairs(n7), "sealed_at", "10/06/2026")))
chk("N8 sealed_at bad format -> SEAL_FIELD_BAD_TIMESTAMP", ok, note)

# P7 grammar negatives
ok, note = _expect_reject("SEAL_FIELD_BAD_INT",
    lambda: encode_node("P7", _set(fixture_p7_pairs(n7, n8), "pinned_canonicalizer_revision", "not-an-int")))
chk("P7 revision not int -> SEAL_FIELD_BAD_INT", ok, note)
ok, note = _expect_reject("SEAL_FIELD_BAD_INT",
    lambda: encode_node("P7", _set(fixture_p7_pairs(n7, n8), "pinned_canonicalizer_utf8_bytes", "-1")))
chk("P7 byte count -1 -> SEAL_FIELD_BAD_INT", ok, note)
ok, note = _expect_reject("SEAL_FIELD_BAD_INT",
    lambda: encode_node("P7", _set(fixture_p7_pairs(n7, n8), "pinned_canonicalizer_utf8_bytes", "0")))
chk("P7 byte count 0 (non-positive) -> SEAL_FIELD_BAD_INT", ok, note)
ok, note = _expect_reject("SEAL_FIELD_EMPTY",
    lambda: encode_node("P7", _set(fixture_p7_pairs(n7, n8), "pinned_canonicalizer_document_id", "")))
chk("P7 empty document id -> SEAL_FIELD_EMPTY", ok, note)

# ===== NEW: report-set negatives =====
ok, note = _expect_reject("SEAL_REPORT_SET_EMPTY", lambda: report_documents_digest([]))
chk("empty report set -> SEAL_REPORT_SET_EMPTY", ok, note)
ok, note = _expect_reject("SEAL_REPORT_SET_DUPLICATE",
    lambda: report_documents_digest([("doc-a.md", "1"), ("doc-a.md", "1")]))
chk("duplicate report record -> SEAL_REPORT_SET_DUPLICATE", ok, note)
ok, note = _expect_reject("SEAL_REPORT_SET_DUPLICATE",
    lambda: report_documents_digest([("doc-a.md", "1"), ("doc-a.md", "2")]))
chk("duplicate report doc id -> SEAL_REPORT_SET_DUPLICATE", ok, note)
ok, note = _expect_reject("SEAL_REPORT_DOC_ID_INVALID",
    lambda: report_documents_digest([("", "1")]))
chk("empty report doc id -> SEAL_REPORT_DOC_ID_INVALID", ok, note)
ok, note = _expect_reject("SEAL_REPORT_REVISION_INVALID",
    lambda: report_documents_digest([("doc-a.md", "x")]))
chk("bad report revision -> SEAL_REPORT_REVISION_INVALID", ok, note)
# report-set determinism: input order does not matter
r1 = report_documents_digest([("doc-a.md", "1"), ("doc-b.md", "2")])
r2 = report_documents_digest([("doc-b.md", "2"), ("doc-a.md", "1")])
chk("report set deterministic (order-independent)", r1 == r2)

# ===== NEW: provenance negatives (REHEARSAL can never become real) =====
ok, note = _expect_reject("SEAL_PROVENANCE_REHEARSAL_BLOCKED",
    lambda: encode_real_n7(fixture_n7_pairs(), fixture_rehearsal_provenance()))
chk("REHEARSAL N6 into real N7 -> SEAL_PROVENANCE_REHEARSAL_BLOCKED", ok, note)
ok, note = _expect_reject("SEAL_PROVENANCE_MISSING",
    lambda: encode_real_n7(fixture_n7_pairs(), {}))
chk("missing provenance into real N7 -> SEAL_PROVENANCE_MISSING", ok, note)
forb = {f: "FORBIDDEN_FOR_REAL_SEAL" for f in fixture_rehearsal_provenance()}
ok, note = _expect_reject("SEAL_PROVENANCE_FORBIDDEN_CLASS",
    lambda: encode_real_n7(fixture_n7_pairs(), forb))
chk("forbidden provenance class into real N7 -> SEAL_PROVENANCE_FORBIDDEN_CLASS", ok, note)
unk = {f: "MADE_UP_CLASS" for f in fixture_rehearsal_provenance()}
ok, note = _expect_reject("SEAL_PROVENANCE_UNKNOWN_CLASS",
    lambda: encode_real_n7(fixture_n7_pairs(), unk))
chk("unknown provenance class into real N7 -> SEAL_PROVENANCE_UNKNOWN_CLASS", ok, note)
# correct classes but no real N6 chain -> still BLOCKED (true blocker)
good = {}
for f in ("active_corpus_sha256", "membership_sha256", "canonicalizer_sha256",
          "marker_fence_registry_sha256", "superseded_boundary_sha256", "guard_set_sha256"):
    good[f] = "ENGINEERING_VERIFIED_CANDIDATE"
for f in ("approval_event_id", "approver_identity", "approval_event_timestamp",
          "owner_blueprint_decision"):
    good[f] = "AUTHORITY_INPUT"
ok, note = _expect_reject("SEAL_REAL_N6_NOT_AVAILABLE",
    lambda: encode_real_n7(fixture_n7_pairs(), good))
chk("valid classes but no real N6 -> SEAL_REAL_N6_NOT_AVAILABLE (true blocker)", ok, note)
# if a real N6 chain WERE supplied, the real path would produce the digest:
chk("real N7 path is live when real_n6_available + valid provenance",
    encode_real_n7(fixture_n7_pairs(), good, real_n6_available=True) == n7)

npass = sum(1 for _, ok, _ in results if ok)
for name, ok, note in results:
    print(f"  [{'PASS' if ok else 'FAIL'}] {name}" + (f"  {note}" if note and not ok else ""))
print(f"AUTHORITY-SEAL-ENCODER SELFTEST: {npass}/{len(results)} PASS")
return all(ok for _, ok, _ in results)

def _set(pairs, field, value): return [(k, value if k == field else v) for k, v in pairs]

def emit_fixture(): n7 = encode_node("N7", fixture_n7_pairs()) n8 = encode_node("N8", fixture_n8_pairs(n7)) p7 = seal_p7(fixture_p7_pairs(n7, n8)) print("FIXTURE seal digests (NOT a real seal; fixture authority inputs):") print(" N7 envelope_manifest_sha256 :", n7) print(" N8 detached_seal_sha256 :", n8) print(" P7 authority_seal_pin_sha256:", p7) print(" DAG acyclic :", not has_cycle(EDGES))

if name == "main": args = sys.argv[1:] if args and args[0] == "--emit-fixture": emit_fixture() elif args and args[0] == "--selftest": sys.exit(0 if selftest() else 1) else: ok = selftest() print() emit_fixture() sys.exit(0 if ok else 1)

Back to Knowledge Hub knowledge/dev/reports/architecture/codex-fix7-n7-n8-p7-authority-seal-authoring-2026-06-11/authority_seal_encoder.py