"""The Run Certificate — a design and its complete justification, addressable. WHY THIS EXISTS --------------- The compiler already emits a design record (compiler.design_record), and it is good: deterministic, plain text, states what it does NOT establish. But it is one tool's record, it has no identity, and nothing can check it. A reviewer handed that text has to take it on trust that it describes the run it claims to describe. A certificate fixes three things the record cannot: 1. IDENTITY. It is content-addressed. The id IS the hash of the content, so "certificate 8f2a…" names exactly one document and nothing else. Two runs that produced the same answer produce the same id; a run that differed anywhere produces a different one. You cannot rename a result into agreeing with you. 2. TAMPER EVIDENCE. Anyone can recompute the hash from the content. There is no signing key to trust and none to lose — the document verifies itself. 3. COMPLETENESS THAT IS PART OF THE RECORD. What was NOT established is a first-class section, hashed with everything else. You cannot quietly drop the caveats and keep the id. DETERMINISM IS THE WHOLE MECHANISM ---------------------------------- If the same inputs produced two different certificates, the hash would be noise and every property above would collapse. So the canonical form: * sorts every key, at every depth; * contains NO clock and NO random source. A timestamp would give the same run two ids, which is precisely the failure to avoid. Time is metadata the caller attaches OUTSIDE the hashed payload; * normalises floats through repr-stable rounding, because 0.1+0.2 must not fork a certificate; * refuses values it cannot canonicalise, rather than coercing them to a string and hashing something that looks fine and means nothing. WHAT A CERTIFICATE IS NOT ------------------------- It is not a claim that the design is correct, or safe, or novel. It says: this input, through this code at this version, produced this output, and here is what nobody checked. A reviewer still has to do the science. The certificate only guarantees they are reviewing what they think they are reviewing. Pure logic: no network, no database, no I/O. Same discipline as compiler.py. """ from __future__ import annotations import hashlib import json from typing import Any, Dict, List, Optional, Tuple __all__ = [ "CERT_VERSION", "CanonicalError", "canonical", "content_hash", "build", "verify", "render_text", ] # Bumped only when the canonical form changes in a way that would alter hashes # for unchanged inputs. It is part of the hashed payload, so old certificates # stay verifiable against the rules they were minted under. CERT_VERSION = "1" _FLOAT_PLACES = 10 class CanonicalError(ValueError): """A value that cannot be canonicalised. Raised rather than coerced.""" def canonical(value: Any) -> Any: """Reduce a value to its canonical form, or refuse. Refusing is the point. Coercing an unknown object with str() would produce a hash that looks authoritative and means nothing — worse than an error, because it fails silently and only at the moment somebody relies on it. """ if value is None or isinstance(value, (str, bool)): return value if isinstance(value, int) and not isinstance(value, bool): return value if isinstance(value, float): if value != value or value in (float("inf"), float("-inf")): raise CanonicalError( "NaN and infinity have no canonical form; a certificate " "containing one could never be reproduced.") # Round before hashing so 0.30000000000000004 and 0.3 agree. Integral # floats normalise to int so 1.0 and 1 cannot fork a certificate. r = round(value, _FLOAT_PLACES) return int(r) if r == int(r) else r if isinstance(value, (list, tuple)): return [canonical(v) for v in value] if isinstance(value, dict): out = {} for k in sorted(value): if not isinstance(k, str): raise CanonicalError( f"certificate keys must be strings; got {type(k).__name__}") out[k] = canonical(value[k]) return out raise CanonicalError( f"{type(value).__name__} has no canonical form. Convert it " "explicitly rather than letting the hash cover a repr.") def _serialise(payload: Dict[str, Any]) -> str: return json.dumps(canonical(payload), sort_keys=True, separators=(",", ":"), ensure_ascii=False) def content_hash(payload: Dict[str, Any]) -> str: """sha256 of the canonical serialisation, truncated to 16 hex chars. Truncated because this is an identifier a human reads aloud and types into a search box, not a cryptographic commitment against an adversary with unlimited attempts. 64 bits still makes an accidental collision inconceivable at any volume this will ever see. """ return hashlib.sha256(_serialise(payload).encode("utf-8")).hexdigest()[:16] def build(*, kind: str, inputs: Dict[str, Any], outputs: Dict[str, Any], passes: Optional[List[Dict[str, Any]]] = None, not_established: Optional[List[str]] = None, versions: Optional[Dict[str, str]] = None, scope: Optional[Dict[str, str]] = None) -> Dict[str, Any]: """Assemble a certificate. Deterministic: same arguments, same id. `not_established` is required to be explicit even when empty. An empty list is a CLAIM — "we checked everything relevant" — and it should have to be made deliberately rather than arrived at by forgetting the argument. """ payload = { "cert_version": CERT_VERSION, "kind": str(kind), "inputs": inputs or {}, "outputs": outputs or {}, "passes": passes or [], # Sorted so two runs that established the same gaps in a different # order are the same certificate. "not_established": sorted(str(x) for x in (not_established or [])), "versions": versions or {}, "scope": scope or {}, } cert = dict(payload) cert["id"] = content_hash(payload) return cert def verify(cert: Dict[str, Any]) -> Tuple[bool, str]: """Recompute the id from the content. Returns (ok, explanation). No key, no authority, no service to be up: the document checks itself. Anyone holding it can run this, including someone who does not trust us — which is the only kind of verification worth putting in a methods section. """ if not isinstance(cert, dict): return False, "not a certificate object" claimed = cert.get("id") if not claimed: return False, "no id — nothing to check the content against" payload = {k: v for k, v in cert.items() if k != "id"} if payload.get("cert_version") != CERT_VERSION: # Not a failure. An older certificate is valid under the rules it was # minted with; saying "invalid" would be a lie about tampering. return False, (f"minted under cert_version " f"{payload.get('cert_version')!r}, this build canonicalises " f"{CERT_VERSION!r} — verify with that version's rules") try: actual = content_hash(payload) except CanonicalError as exc: return False, f"content cannot be canonicalised: {exc}" if actual != claimed: return False, (f"content does not match its id (claimed {claimed}, " f"content hashes to {actual}) — it has been altered " "since it was issued") return True, f"content matches its id ({claimed})" def render_text(cert: Dict[str, Any]) -> str: """Plain text, because it diffs, pastes into an email, survives every tool in the chain, and cannot silently re-render differently later.""" L: List[str] = [] add = L.append add("TURINGDNA RUN CERTIFICATE") add(f"id {cert.get('id', '(unissued)')}") add(f"kind {cert.get('kind', '')}") add(f"cert-version {cert.get('cert_version', '')}") add("=" * 72) add("") ok, why = verify(cert) add(f"SELF-CHECK {'PASS' if ok else 'FAIL'} — {why}") add(" Recompute it yourself: sha256 of the canonical JSON of every field") add(" except `id`, first 16 hex characters. No key required.") add("") for title, key in (("INPUTS", "inputs"), ("OUTPUTS", "outputs"), ("VERSIONS", "versions"), ("SCOPE", "scope")): section = cert.get(key) or {} if not section: continue add(title) for k in sorted(section): add(f" {k:<22} {section[k]}") add("") passes = cert.get("passes") or [] if passes: add("PASSES") for p in passes: add(f" [{str(p.get('status', '')):<11}] {p.get('title', p.get('name', ''))}") if p.get("detail"): for line in _wrap(str(p["detail"]), 66): add(f" {line}") add("") gaps = cert.get("not_established") or [] add("NOT ESTABLISHED BY THIS CERTIFICATE") if gaps: for g in gaps: add(f" - {g}") else: add(" Nothing was recorded as unestablished. That is a CLAIM, not an") add(" absence of information — read it as one.") add("") add("-" * 72) add("This certificate attests that these inputs, through this code at these") add("versions, produced these outputs. It is not a claim that the design is") add("correct, safe, or novel, and it does not replace the review.") return "\n".join(L) def _wrap(text: str, width: int) -> List[str]: words, line, out = str(text).split(), "", [] for w in words: if line and len(line) + 1 + len(w) > width: out.append(line) line = w else: line = f"{line} {w}".strip() if line: out.append(line) return out