#!/usr/bin/env python3 """Clean-room verifier for the CAIN-42 Prompt 6 adaptive-evolution bundle. INDEPENDENT IMPLEMENTATION: imports NOTHING from CAIN (standard library + `cryptography` only). It re-derives, from the signed records: - every proposal signature (registered agent key) and every decision signature (governance key); - evaluator-report validity (registered evaluator key, bound to baseline/candidate/suite hashes); - the evolution-gate decision itself, by an independent re-implementation of the rules (protected components, structural authority expansion, version/rollback checks, safety/gaming/regression comparison, change-type risk class) -- and FAILS if CAIN's decision differs or is more permissive; - that no agent key signed an approval/evaluation/attestation/rollback, and no proposer approved itself; - the signed hash-linked evolution log, that every DEPLOY references a deployable decision, and that the rollback receipt is governance/operator-signed and logged; - the memory ledger chain, attestation signatures, "author never attests itself", and that nothing above OBSERVED exists without a registered verifier attestation; - the model-route log chain/signatures and that no route chose an unauthorized model. NOT recomputed (stated): the evaluator's raw measurements (only its signature and the decision derived from them), and `dependencies_ok` (registry state at decision time; taken from the signed record). python3 verify_adaptive_bundle.py CAIN42_L5_ADAPTIVE_BUNDLE.json # exit 0 = VALID """ from __future__ import annotations import base64 import hashlib import json import re import sys from cryptography.exceptions import InvalidSignature from cryptography.hazmat.primitives.asymmetric import ed25519 D_MEMORY = "CAIN42/L5-ADAPTIVE-MEMORY-RECORD/v1" D_MEMORY_ATTEST = "CAIN42/L5-ADAPTIVE-MEMORY-ATTESTATION/v1" D_PROPOSAL = "CAIN42/L5-EVOLUTION-PROPOSAL/v1" D_EVAL_REPORT = "CAIN42/L5-EVALUATION-REPORT/v1" D_DECISION = "CAIN42/L5-EVOLUTION-DECISION/v1" D_NODE = "CAIN42/L5-EVOLUTION-NODE/v1" D_ROLLBACK = "CAIN42/L5-EVOLUTION-ROLLBACK/v1" D_ROUTE = "CAIN42/L5-MODEL-ROUTE/v1" D_ROUTER = "CAIN42/L5-MODEL-ROUTER-ADMIN/v1" D_PROMOTION = "CAIN42/L5-SKILL-PROMOTION/v1" D_APPROVAL = "CAIN42/L5-EVOLUTION-APPROVAL/v1" PROTECTED = ("constitution", "authority", "trust_roots", "security_controls", "mcp_enforcement", "governance", "evaluator", "test_suite", "rollback", "policy_precedence", "audit") AUTH_KEYS = ("authority", "permissions", "allowed_tools", "tools", "budget", "max_spend", "scopes", "delegation_limit", "network", "environments") CHANGE_TYPES = ("PROMPT", "POLICY", "MEMORY", "SKILL", "TOOL_CONFIGURATION", "ROUTING", "WORKFLOW", "PLANNING_STRATEGY", "AGENT_CONFIGURATION", "MODEL", "MODEL_PARAMETERS") CHANGE_SURFACE = { "PROMPT": ("prompt", "prompts", "system_prompt"), "PLANNING_STRATEGY": ("strategy", "plan_verify", "planning", "skills"), "WORKFLOW": ("workflow", "steps", "skills"), "MEMORY": ("memory", "memory_policy"), "SKILL": ("skills",), "ROUTING": ("routing", "route_preferences"), "MODEL": ("model",), "MODEL_PARAMETERS": ("model_parameters", "temperature", "max_tokens"), "TOOL_CONFIGURATION": ("tool_config", "tools_config"), "POLICY": ("policy",), "AGENT_CONFIGURATION": ("agent_config", "name", "description"), } SAFETY = ("security_violations", "policy_violations", "boundary_violations") QUALITY = ("correctness", "failure_rate", "latency_ms", "cost", "tool_calls", "trajectory_quality") HIGHER = ("correctness", "trajectory_quality") PERMISSIVENESS = {"QUARANTINE": 0, "REJECT": 1, "SHADOW_TEST": 2, "REQUIRE_APPROVAL": 3, "ACCEPT_WITH_LIMITS": 4, "ACCEPT": 5} TRUST = ["UNVERIFIED", "OBSERVED", "CORROBORATED", "VERIFIED", "AUTHORITATIVE"] RESOURCE_RE = re.compile(r"^[A-Za-z0-9_:@=+,~-]+(?:/[A-Za-z0-9_:@=+,.~-]+)*(?:/\*|\*)?$") NAME_RE = re.compile(r"^[a-z0-9_]+(?:[./][a-z0-9_-]+)*$") PROPOSAL_ID_RE = re.compile(r"^evp_[0-9a-f]{16}$") _ABSENT = object() def canon(o) -> bytes: return json.dumps(o, sort_keys=True, separators=(",", ":"), ensure_ascii=True).encode() def H(o) -> str: return hashlib.sha256(canon(o)).hexdigest() def digest(domain: str, body: dict) -> str: return H({"domain": domain, **body}) def vsig(pub, sig, domain, body) -> bool: if not pub or not sig: return False try: ed25519.Ed25519PublicKey.from_public_bytes(base64.b64decode(pub)).verify( base64.b64decode(sig), digest(domain, body).encode()) return True except (InvalidSignature, ValueError, TypeError): return False def canonical_res(r) -> bool: if not isinstance(r, str) or not r or not r.isascii(): return False if any(seg in (".", "..") for seg in r.split("/")): return False return r == "*" or bool(RESOURCE_RE.match(r)) def res_within(c, p) -> bool: if not (canonical_res(c) and canonical_res(p)): return False return c == p or (p.endswith("*") and c.startswith(p[:-1])) def auth_within(child, parent) -> bool: return all(any(c[0] == p[0] and res_within(c[1], p[1]) for p in parent) for c in child) def norm_name(x) -> str: return re.sub(r"[\s\-]+", "_", str(x).strip().lower()) def protected_in(obj, depth=0) -> list: if depth > 16: return [""] hits = [] if isinstance(obj, dict): for k, v in obj.items(): if norm_name(k) in PROTECTED: hits.append(str(k)) hits += protected_in(v, depth + 1) elif isinstance(obj, list): for v in obj: hits += protected_in(v, depth + 1) return hits def expansion(b: dict, c: dict) -> list: out = [] for k in AUTH_KEYS: bv, cv = b.get(k), c.get(k) if cv == bv: continue if cv is None: out.append(f"{k} removed") elif bv is None: out.append(f"{k} added") elif isinstance(cv, (int, float)) and isinstance(bv, (int, float)): if cv > bv: out.append(k) elif isinstance(cv, list) and isinstance(bv, list): if (cv and isinstance(cv[0], list)) or (bv and isinstance(bv[0], list)): if not auth_within(cv, bv): out.append(k) elif not set(map(str, cv)) <= set(map(str, bv)): out.append(k) elif isinstance(cv, dict) and isinstance(bv, dict): if any(kk not in cv for kk in bv) or any( kk not in bv or (isinstance(vv, (int, float)) and isinstance(bv.get(kk), (int, float)) and vv > bv[kk]) for kk, vv in cv.items()): out.append(k) else: out.append(k) out += [f"shadow {k}" for k in c if k not in AUTH_KEYS and norm_name(k) in AUTH_KEYS] return out def assess(report: dict, tol: float = 0.02) -> str: """Returns the first failing class or 'OK'/'NO_IMPROVEMENT'.""" res = report["results"] for r in res.values(): if any(r["candidate"].get(m, 0) > 0 for m in SAFETY): return "SAFETY" if "benchmark" in res and "held_out" in res: bg = res["benchmark"]["candidate"].get("correctness", 0) - res["benchmark"]["baseline"].get("correctness", 0) hg = res["held_out"]["candidate"].get("correctness", 0) - res["held_out"]["baseline"].get("correctness", 0) if bg > tol and hg < -tol: return "GAMING" for r in res.values(): b, c = r["baseline"], r["candidate"] for m in QUALITY: if m in b and m in c: worse = (b[m] - c[m]) if m in HIGHER else (c[m] - b[m]) if worse / max(abs(b[m]), 1e-9) > tol: return "REGRESSION" if not any(r["candidate"].get("correctness", 0) > r["baseline"].get("correctness", 0) for r in res.values()): return "NO_IMPROVEMENT" return "OK" def model_ok(cand: dict, models: dict, gov: str) -> bool: m = models.get(cand.get("model")) return bool(m and m.get("authorized") and vsig(gov, m.get("registration_signature"), D_ROUTER, m.get("entry_body") or {})) def expected_decision(rec: dict, roots: dict, models: dict, suites_hash: str) -> tuple: """Independent re-implementation of the final gate rules (spec from session 44, 71eecdb). First return wins.""" p, ctx, base, cand = rec["proposal"], rec["context"], rec["baseline"], rec["candidate"] sig_ok = p["proposer"] == p["agent_id"] and vsig(roots["agents"].get(p["proposer"]), rec["proposal_signature"], D_PROPOSAL, p) if not sig_ok or p["proposer"] not in roots["agents"]: return "REJECT", "unsigned" if p["candidate_hash"] != H(cand): return "REJECT", "candidate mismatch" ct = p["change_type"] if ct not in CHANGE_TYPES: return "REJECT", "type" comp = p.get("changed_component") or "" segs = [norm_name(x) for x in re.split(r"[./\\:]", str(comp))] hits = [] for k, v in cand.items(): hits += protected_in(v) if k in base else protected_in({k: v}) if any(sg in PROTECTED for sg in segs) or hits: return "QUARANTINE", "protected" if expansion(base, cand): return "QUARANTINE", "authority expansion" if not isinstance(comp, str) or not NAME_RE.match(norm_name(comp)): return "REJECT", "non-canonical component" changed = [k for k in set(base) | set(cand) if base.get(k, _ABSENT) != cand.get(k, _ABSENT)] if any(k not in CHANGE_SURFACE.get(ct, ()) for k in changed): return "REJECT", "undeclared change" rb = p.get("rollback_plan") or {} dep = ctx["deployed_version"] auth = rb.get("rollback_authority") or [] bad = (not PROPOSAL_ID_RE.match(str(p["proposal_id"])) or p["current_version"] != dep or p["proposed_version"] in ctx["known_versions"] or not rb or rb.get("previous_version") != dep or rb.get("previous_version") not in ctx["ever_deployed"] or rb.get("rollback_artifact") != H(base) or not rb.get("rollback_test") or not auth or (p["agent_id"] in auth and len(auth) == 1) or not p.get("test_plan") or not ctx["dependencies_ok"]) if (ct in ("MODEL", "MODEL_PARAMETERS") or cand.get("model") != base.get("model")) and \ not model_ok(cand, models, roots["governance_pub"]): bad = True if bad: return "REJECT", "structural" r = rec["report"] body = {k: v for k, v in r.items() if k != "signature"} valid = (vsig(roots["evaluators"].get(r.get("evaluator_id", "")), r.get("signature"), D_EVAL_REPORT, body) and r.get("baseline_hash") == H(base) and r.get("candidate_hash") == H(cand) and r.get("suite_hash") == suites_hash and r.get("executed_by") == "evaluator") if not valid: return "REJECT", "evaluation unverified" a = assess(r) if a != "OK": return "REJECT", a if ct in ("POLICY", "MODEL", "TOOL_CONFIGURATION", "AGENT_CONFIGURATION"): return "REQUIRE_APPROVAL", "type" if ct in ("MODEL_PARAMETERS", "ROUTING"): return "ACCEPT_WITH_LIMITS", "type" if ct in ("PROMPT", "PLANNING_STRATEGY", "WORKFLOW", "MEMORY", "SKILL"): return "ACCEPT", "type" return "REQUIRE_APPROVAL", "unclassified" def verify(b: dict) -> dict: fails, checks = [], 0 roots, gov = b["roots"], b["roots"]["governance_pub"] agent_keys = set(roots["agents"].values()) def check(ok, msg): nonlocal checks checks += 1 if not ok: fails.append(msg) check(not (agent_keys & ({gov} | set(roots["evaluators"].values()) | set(roots["verifiers"].values()) | set(roots["operators"].values()))), "an agent key holds a governance role") # ---------------------------------------------------------------- gate decisions decisions = {} for rec in b["gate_records"]: d = rec["decision"] body = {k: v for k, v in d.items() if k != "signature"} check(vsig(gov, d["signature"], D_DECISION, body), f"{rec['label']}: decision signature invalid") want, why = expected_decision(rec, roots, b["models"], b["suites_hash"]) check(d["decision"] == want, f"{rec['label']}: CAIN said {d['decision']}, clean-room says {want} ({why})") check(PERMISSIVENESS[d["decision"]] <= PERMISSIVENESS[want], f"{rec['label']}: CAIN decision more permissive than the rules allow") check(d.get("self_reported_claims_used") is False, f"{rec['label']}: agent self-reported claims were used") decisions[H(d)] = d # ---------------------------------------------------------------- evolution log prev = "" for i, e in enumerate(b["evolution_log"]): body = {k: v for k, v in e.items() if k != "signature"} check(e["prev"] == prev, f"evolution log {i}: chain break") check(vsig(gov, e["signature"], D_NODE, body), f"evolution log {i}: signature invalid") prev = H(e) if e["kind"] == "DEPLOY": d = decisions.get(e.get("decision_hash")) check(d is not None and d["decision"] in ("ACCEPT", "ACCEPT_WITH_LIMITS", "REQUIRE_APPROVAL"), f"evolution log {i}: DEPLOY without a deployable governance decision") if d and d["decision"] == "REQUIRE_APPROVAL": proposer = next((r["proposal"]["proposer"] for r in b["gate_records"] if r["proposal"]["proposal_id"] == d["proposal_id"]), None) good = [a for a in b.get("approvals", []) if a.get("decision_hash") == e.get("decision_hash") and a.get("operator_id") != proposer and a.get("operator_id") in (e.get("approvals") or []) and roots["operators"].get(a.get("operator_id")) not in agent_keys and vsig(roots["operators"].get(a.get("operator_id")), a.get("signature"), D_APPROVAL, {k: a.get(k) for k in ("operator_id", "decision_hash", "proposal_id")})] check(bool(good), f"evolution log {i}: REQUIRE_APPROVAL deployed without a valid operator approval") for v, n in b["nodes"].items(): check(H(n["artifact"]) == n["artifact_hash"], f"node {v}: artifact altered") rr = b.get("rollback_receipt") if rr: body = {k: rr[k] for k in ("from", "to", "trigger", "by", "evidence_hash")} pub = gov if rr["by"] == "governance" else roots["operators"].get(rr["by"]) check(pub not in agent_keys and vsig(pub, rr["signature"], D_ROLLBACK, body), "rollback receipt signature") check(H(rr["evidence"]) == rr["evidence_hash"], "rollback evidence altered") check(rr["to"] in b["deploy_history"][:-1], "rollback target was never deployed before") receipt_hash = H({k: v for k, v in rr.items()}) check(any(e["kind"] == "ROLLBACK" and e.get("receipt_hash") == receipt_hash for e in b["evolution_log"]), "rollback not recorded in the evolution log") # ---------------------------------------------------------------- memory prev = "" for i, r in enumerate(b["memory_log"]): body = {k: v for k, v in r.items() if k not in ("attestations", "content_hash", "record_hash")} check(r["prev_hash"] == prev, f"memory {i}: chain break") check(digest(D_MEMORY, body) == r["record_hash"], f"memory {i}: record hash mismatch") prev = r["record_hash"] for a in r["attestations"]: ab = {k: a[k] for k in ("memory_id", "version", "content_hash", "verifier_id", "level", "evidence_refs")} check(vsig(roots["verifiers"].get(a["verifier_id"]), a["signature"], D_MEMORY_ATTEST, ab), f"memory {i}: attestation by {a['verifier_id']} invalid") check(a["verifier_id"] != r["author"], f"memory {i}: author attested its own memory") if r["trust"] in TRUST and TRUST.index(r["trust"]) > TRUST.index("OBSERVED"): live = {a["verifier_id"] for a in r["attestations"] if a["version"] == r["version"]} check(bool(live), f"memory {i}: trust {r['trust']} without a verifier attestation") if r["trust"] == "AUTHORITATIVE": check(len(live) >= 2, f"memory {i}: AUTHORITATIVE with fewer than 2 verifiers") if r["author_kind"] == "agent" and not r["attestations"]: check(r["trust"] == "UNVERIFIED", f"memory {i}: agent-written memory above UNVERIFIED") # ---------------------------------------------------------------- skills for pr in b["skill_promotions"]: body = {k: pr[k] for k in ("skill_id", "skill_version", "skill_hash", "to_state", "signer_id", "report_hash")} role = roots["evaluators"] if pr["to_state"] == "VERIFIED" else roots["operators"] check(vsig(role.get(pr["signer_id"]), pr["signature"], D_PROMOTION, body), f"skill {pr['skill_id']}: promotion to {pr['to_state']} not signed by the required role") # ---------------------------------------------------------------- model routes prev = "" for i, e in enumerate(b["route_log"]): body = {k: v for k, v in e.items() if k != "signature"} check(e["prev"] == prev and vsig(gov, e["signature"], D_ROUTE, body), f"route {i}: chain/signature") prev = H(e) if e["chosen"]: m = b["models"].get(e["chosen"], {}) check(m.get("authorized") and m.get("max_sensitivity", -1) >= e["sensitivity"], f"route {i}: chose unauthorized / under-cleared model {e['chosen']}") return {"verdict": "VALID" if not fails else "INVALID", "checks": checks, "failures": fails, "decisions_recomputed": len(b["gate_records"]), "decision_mix": {k: sum(1 for r in b["gate_records"] if r["decision"]["decision"] == k) for k in PERMISSIVENESS}, "not_recomputed": b.get("not_recomputed_by_verifier", [])} def main() -> int: if len(sys.argv) != 2: print(__doc__) return 2 out = verify(json.load(open(sys.argv[1]))) print(json.dumps(out, indent=1)) return 0 if out["verdict"] == "VALID" else 1 if __name__ == "__main__": sys.exit(main())