fips205-slhdsa-verified/verification/check-selftest.sh

399 lines
23 KiB
Bash
Raw Permalink Normal View History

post-flip drill over the chain certificate: HELD; audit gates now self-tested The window under audit claimed the campaign's first certificate, so this drill was maximally adversarial. Everything of substance HELD: - three-way model fidelity EXACT: extracted chain_free_loop.body == chainFoldN step == the Rust origin, operation-for-operation including address threading - button green fresh; axiom sweep over ALL 8 declarations minimal (pure lemmas = kernel-3; oracle-touching = kernel-3 + oracle.f only) - non-vacuity PROVEN: the concrete 1-step consequence (one address-set + one hash call) derives from the certificate by rfl - commit body of cfd50bb intact (the one flagged fragment was a bad drill grep pattern, not an artifact); worktree clean; heads synced NEW, from the drill (R3-5 tradition): verification/check-selftest.sh - permanent adversarial self-test of the check.sh gates. Attack 1 (dead Proofs file) and attack 2 (certificate with a smuggled axiom) must both make check.sh fail; both verified rejected, selftest green, self-cleaning. An audit that cannot fail is theater; this one demonstrably can. Two notes for the record: (a) bind_congr is the generic Bind-class congruence from core/Mathlib, not Aeneas.Std.Primitives (memory corrected); (b) the certificate covers chain_free_loop - the thin chain_free wrapper (bound computation + massert + clone) gets its trivial composition lemma in the wots layer, where it is consumed. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-23 12:34:42 +00:00
#!/usr/bin/env bash
review round 2: in-Lean exact-cone audit + reproducibility + doc honesty Addresses the round-2 reviewer punch-list. No theorem statement, proof term, or fold definition changed; the eleven cones are unchanged (independent collectAxioms dump in verification/RECORDED-RUN.md). AUDIT GATE (both reviewers, the critical one) - Retire the bash #print-axioms text parser (fail-open on empty/truncated reports, and only a SUBSET check). Replace with verification/Proofs/Audit.lean: reads each certificate's cone from the kernel via collectAxioms and asserts EXACT set equality against its expected boundary. Extra axiom, dropped oracle, renamed/deleted cert, or an axiom/opaque sham each throw -> non-zero Lean exit. No text to misparse; nothing fails open. check.sh Phase 3 now just compiles it (and still requires the explicit PASSED line). - check-selftest.sh rewritten to attack the new gate: dead-file, smuggled extra axiom (named), dropped-oracle (subset would pass, exact must not), and a vanished certificate (the collectAxioms-returns-[] trap). All four rejected. REPRODUCIBILITY (GPT B1.4 / B1.5) - extract.sh refuses a wrong-commit or dirty source tree (fail-closed), takes an optional source-path arg, and pins the source commit. - verification/PROVENANCE.json: single machine-readable pin set (source + charon + aeneas commits/channel + lean + ocaml) with generated-file sha256. - Re-running extract.sh reproduces gen/SlhVerify/{Types,Funs}.lean byte-identically (companion fips205-source commit adds Cargo.lock + rust-toolchain.toml; verified not to perturb the model). DOC HONESTY (both reviewers) - README: fix the self-contradiction (apex "not yet proven" trailer vs the proven apex), the false "oracles kept OUTSIDE every cone" (they are INSIDE, by design), "deployed monomorphic path" and "semantics-identical for every parameter set" overclaims, "only two lines changed", stale snapshot head; retitle the stale future-tense "what will be claimed" section. - TRUSTED-BASE: drop "nothing proven yet"; add base_2b-inner and deployment- bridge non-claims explicitly; current pin. - ChainSpec header: "deployed monomorphic path" -> private verify_mono facade (comment only). Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-07-24 17:13:55 +00:00
# Adversarial self-test of the check.sh gates (the R3-5 tradition: an audit that
review round 5: bind the policy, the specification bodies, and the harness The third reviewer demonstrated that the round-4 gate was closed at the EXPLOITS, not the MECHANISMS: it bound the manifest rows while the things he moved sat outside the binding. Three fail-opens, each executed end-to-end with the button printing ALL GREEN. No theorem, proof, fold, or model body changed. NEW-1 — the policy constant was unbound. `manifestFingerprint` covered `manifest` but never `allowedBoundary`, the sole predicate the enumeration tests against; adding one name re-opened the False-proof with the committed fingerprint BYTE-IDENTICAL. NEW-2 — the specification bodies were unbound. The statement fingerprint pinned each certificate's TYPE, which names its reference fold; redefining that fold to *be* the extracted loop left cone and type-hash identical while the certificate degenerated to `loop = loop`. 100% of the fidelity content lives in those defs. NEW-3 — the harness was unbound. Stubbing verification/lean-guard alone, without touching check.sh or the proofs, gave ALL GREEN in 3.6s over destroyed proofs. FIX — one mechanism rather than three patches. Audit.lean now emits a canonical AUDIT-MANIFEST block and check.sh binds to its SHA-256. The block covers the POLICY constants, every certificate's fully-elaborated statement, and every specification constant transitively reachable from those statements with its fully-elaborated BODY (41 constants; the closure is computed, so a new fold cannot appear without moving the digest; Prop-valued constants contribute their statement, by proof irrelevance). This also retires the 32-bit Expr.hash as the binding (NEW-5) — it survives only as a per-certificate diagnostic. Enumeration now covers EVERY declaration kind (a `def : False` passed before) in the eight certificate modules AND in Audit.lean itself — the auditor is no longer exempt (round-5 R1). A bare `axiom` in audited scope is now an error. Phase 0 purges stale .olean (the verdict must depend on committed bytes, not .gitignored build state — NEW-4), forbids any .lean outside gen/ and Proofs/, and sha256-pins the four model files AND lean-guard. lean-guard is KEPT rather than removed (the reviewer's portability advice is declined by operator decision): it is the memory cap and machine-wide lock that protect the build machine after a 12.2GB OOM took the host down. That trade-off is documented. check.sh's "Certificates proven:" line now comes from the audited manifest; the hand-kept CERTS array — the one authoritative claim string nothing bound — is deleted. check-selftest.sh: 14 attacks, all rejected, plus a check that the hashed block literally carries the twelve fold bodies. Attacks 9-14 are the reviewers' and an independent drill's own exploits, turned into regression tests. DOCS. TRUSTED-BASE gains item 11 (the REAL trusted computing base — lean-guard pinned; check.sh, the toolchain env, $AENEAS_HOME, python3 and Lean still trusted) and item 12 (the apex does not compose the ten). README: the audit description rewritten; the XMSS sibling-order claim downgraded from "pins" to "makes visible", with a new blanket non-claim covering all ten loop certificates; the de-plumbing file claim corrected (round 1 touched only verify_mono.rs, round 2 only helpers.rs — which is ON the deployed verify AND sign paths, now disclosed; wots.rs was never patched). RECORDED-RUN: three lines that stood inside a fence were a hand-written summary, not console output — fabricated evidence in the file whose purpose is machine evidence. They are removed and the fabrication is named in place, together with the correction that the "INDEPENDENT RUN" block predates this gate. New rule: nothing goes in a fence unless captured with tee/cat, and every block states its date, pin, and who ran it. The transcripts added here follow it. Also disclosed rather than buried: three bugs in my own test harness this round (an olean-purge build-order break, an attack rejected by the wrong rule, and a coverage assertion looking on the wrong line) — each would have let an attack pass or fail for an unrelated reason. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-07-27 20:57:46 +00:00
# cannot fail is theater). Every attack MUST make check.sh fail, via the gate it
# targets — each assertion names a SPECIFIC diagnostic, so a rejection for an
# unrelated reason fails the test too.
post-flip drill over the chain certificate: HELD; audit gates now self-tested The window under audit claimed the campaign's first certificate, so this drill was maximally adversarial. Everything of substance HELD: - three-way model fidelity EXACT: extracted chain_free_loop.body == chainFoldN step == the Rust origin, operation-for-operation including address threading - button green fresh; axiom sweep over ALL 8 declarations minimal (pure lemmas = kernel-3; oracle-touching = kernel-3 + oracle.f only) - non-vacuity PROVEN: the concrete 1-step consequence (one address-set + one hash call) derives from the certificate by rfl - commit body of cfd50bb intact (the one flagged fragment was a bad drill grep pattern, not an artifact); worktree clean; heads synced NEW, from the drill (R3-5 tradition): verification/check-selftest.sh - permanent adversarial self-test of the check.sh gates. Attack 1 (dead Proofs file) and attack 2 (certificate with a smuggled axiom) must both make check.sh fail; both verified rejected, selftest green, self-cleaning. An audit that cannot fail is theater; this one demonstrably can. Two notes for the record: (a) bind_congr is the generic Bind-class congruence from core/Mathlib, not Aeneas.Std.Primitives (memory corrected); (b) the certificate covers chain_free_loop - the thin chain_free wrapper (bound computation + massert + clone) gets its trivial composition lemma in the wots layer, where it is consumed. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-23 12:34:42 +00:00
#
review round 5: bind the policy, the specification bodies, and the harness The third reviewer demonstrated that the round-4 gate was closed at the EXPLOITS, not the MECHANISMS: it bound the manifest rows while the things he moved sat outside the binding. Three fail-opens, each executed end-to-end with the button printing ALL GREEN. No theorem, proof, fold, or model body changed. NEW-1 — the policy constant was unbound. `manifestFingerprint` covered `manifest` but never `allowedBoundary`, the sole predicate the enumeration tests against; adding one name re-opened the False-proof with the committed fingerprint BYTE-IDENTICAL. NEW-2 — the specification bodies were unbound. The statement fingerprint pinned each certificate's TYPE, which names its reference fold; redefining that fold to *be* the extracted loop left cone and type-hash identical while the certificate degenerated to `loop = loop`. 100% of the fidelity content lives in those defs. NEW-3 — the harness was unbound. Stubbing verification/lean-guard alone, without touching check.sh or the proofs, gave ALL GREEN in 3.6s over destroyed proofs. FIX — one mechanism rather than three patches. Audit.lean now emits a canonical AUDIT-MANIFEST block and check.sh binds to its SHA-256. The block covers the POLICY constants, every certificate's fully-elaborated statement, and every specification constant transitively reachable from those statements with its fully-elaborated BODY (41 constants; the closure is computed, so a new fold cannot appear without moving the digest; Prop-valued constants contribute their statement, by proof irrelevance). This also retires the 32-bit Expr.hash as the binding (NEW-5) — it survives only as a per-certificate diagnostic. Enumeration now covers EVERY declaration kind (a `def : False` passed before) in the eight certificate modules AND in Audit.lean itself — the auditor is no longer exempt (round-5 R1). A bare `axiom` in audited scope is now an error. Phase 0 purges stale .olean (the verdict must depend on committed bytes, not .gitignored build state — NEW-4), forbids any .lean outside gen/ and Proofs/, and sha256-pins the four model files AND lean-guard. lean-guard is KEPT rather than removed (the reviewer's portability advice is declined by operator decision): it is the memory cap and machine-wide lock that protect the build machine after a 12.2GB OOM took the host down. That trade-off is documented. check.sh's "Certificates proven:" line now comes from the audited manifest; the hand-kept CERTS array — the one authoritative claim string nothing bound — is deleted. check-selftest.sh: 14 attacks, all rejected, plus a check that the hashed block literally carries the twelve fold bodies. Attacks 9-14 are the reviewers' and an independent drill's own exploits, turned into regression tests. DOCS. TRUSTED-BASE gains item 11 (the REAL trusted computing base — lean-guard pinned; check.sh, the toolchain env, $AENEAS_HOME, python3 and Lean still trusted) and item 12 (the apex does not compose the ten). README: the audit description rewritten; the XMSS sibling-order claim downgraded from "pins" to "makes visible", with a new blanket non-claim covering all ten loop certificates; the de-plumbing file claim corrected (round 1 touched only verify_mono.rs, round 2 only helpers.rs — which is ON the deployed verify AND sign paths, now disclosed; wots.rs was never patched). RECORDED-RUN: three lines that stood inside a fence were a hand-written summary, not console output — fabricated evidence in the file whose purpose is machine evidence. They are removed and the fabrication is named in place, together with the correction that the "INDEPENDENT RUN" block predates this gate. New rule: nothing goes in a fence unless captured with tee/cat, and every block states its date, pin, and who ran it. The transcripts added here follow it. Also disclosed rather than buried: three bugs in my own test harness this round (an olean-purge build-order break, an attack rejected by the wrong rule, and a coverage assertion looking on the wrong line) — each would have let an attack pass or fail for an unrelated reason. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-07-27 20:57:46 +00:00
# Attacks 1-8 are the round-3/4 set. Attacks 9-14 were authored by external
# reviewers and an independent drill, each having DEMONSTRATED the corresponding
# fail-open against an earlier gate — they are the reason this round exists:
post-flip drill over the chain certificate: HELD; audit gates now self-tested The window under audit claimed the campaign's first certificate, so this drill was maximally adversarial. Everything of substance HELD: - three-way model fidelity EXACT: extracted chain_free_loop.body == chainFoldN step == the Rust origin, operation-for-operation including address threading - button green fresh; axiom sweep over ALL 8 declarations minimal (pure lemmas = kernel-3; oracle-touching = kernel-3 + oracle.f only) - non-vacuity PROVEN: the concrete 1-step consequence (one address-set + one hash call) derives from the certificate by rfl - commit body of cfd50bb intact (the one flagged fragment was a bad drill grep pattern, not an artifact); worktree clean; heads synced NEW, from the drill (R3-5 tradition): verification/check-selftest.sh - permanent adversarial self-test of the check.sh gates. Attack 1 (dead Proofs file) and attack 2 (certificate with a smuggled axiom) must both make check.sh fail; both verified rejected, selftest green, self-cleaning. An audit that cannot fail is theater; this one demonstrably can. Two notes for the record: (a) bind_congr is the generic Bind-class congruence from core/Mathlib, not Aeneas.Std.Primitives (memory corrected); (b) the certificate covers chain_free_loop - the thin chain_free wrapper (bound computation + massert + clone) gets its trivial composition lemma in the wots layer, where it is consumed. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-23 12:34:42 +00:00
#
review round 5: bind the policy, the specification bodies, and the harness The third reviewer demonstrated that the round-4 gate was closed at the EXPLOITS, not the MECHANISMS: it bound the manifest rows while the things he moved sat outside the binding. Three fail-opens, each executed end-to-end with the button printing ALL GREEN. No theorem, proof, fold, or model body changed. NEW-1 — the policy constant was unbound. `manifestFingerprint` covered `manifest` but never `allowedBoundary`, the sole predicate the enumeration tests against; adding one name re-opened the False-proof with the committed fingerprint BYTE-IDENTICAL. NEW-2 — the specification bodies were unbound. The statement fingerprint pinned each certificate's TYPE, which names its reference fold; redefining that fold to *be* the extracted loop left cone and type-hash identical while the certificate degenerated to `loop = loop`. 100% of the fidelity content lives in those defs. NEW-3 — the harness was unbound. Stubbing verification/lean-guard alone, without touching check.sh or the proofs, gave ALL GREEN in 3.6s over destroyed proofs. FIX — one mechanism rather than three patches. Audit.lean now emits a canonical AUDIT-MANIFEST block and check.sh binds to its SHA-256. The block covers the POLICY constants, every certificate's fully-elaborated statement, and every specification constant transitively reachable from those statements with its fully-elaborated BODY (41 constants; the closure is computed, so a new fold cannot appear without moving the digest; Prop-valued constants contribute their statement, by proof irrelevance). This also retires the 32-bit Expr.hash as the binding (NEW-5) — it survives only as a per-certificate diagnostic. Enumeration now covers EVERY declaration kind (a `def : False` passed before) in the eight certificate modules AND in Audit.lean itself — the auditor is no longer exempt (round-5 R1). A bare `axiom` in audited scope is now an error. Phase 0 purges stale .olean (the verdict must depend on committed bytes, not .gitignored build state — NEW-4), forbids any .lean outside gen/ and Proofs/, and sha256-pins the four model files AND lean-guard. lean-guard is KEPT rather than removed (the reviewer's portability advice is declined by operator decision): it is the memory cap and machine-wide lock that protect the build machine after a 12.2GB OOM took the host down. That trade-off is documented. check.sh's "Certificates proven:" line now comes from the audited manifest; the hand-kept CERTS array — the one authoritative claim string nothing bound — is deleted. check-selftest.sh: 14 attacks, all rejected, plus a check that the hashed block literally carries the twelve fold bodies. Attacks 9-14 are the reviewers' and an independent drill's own exploits, turned into regression tests. DOCS. TRUSTED-BASE gains item 11 (the REAL trusted computing base — lean-guard pinned; check.sh, the toolchain env, $AENEAS_HOME, python3 and Lean still trusted) and item 12 (the apex does not compose the ten). README: the audit description rewritten; the XMSS sibling-order claim downgraded from "pins" to "makes visible", with a new blanket non-claim covering all ten loop certificates; the de-plumbing file claim corrected (round 1 touched only verify_mono.rs, round 2 only helpers.rs — which is ON the deployed verify AND sign paths, now disclosed; wots.rs was never patched). RECORDED-RUN: three lines that stood inside a fence were a hand-written summary, not console output — fabricated evidence in the file whose purpose is machine evidence. They are removed and the fabrication is named in place, together with the correction that the "INDEPENDENT RUN" block predates this gate. New rule: nothing goes in a fence unless captured with tee/cat, and every block states its date, pin, and who ran it. The transcripts added here follow it. Also disclosed rather than buried: three bugs in my own test harness this round (an olean-purge build-order break, an attack rejected by the wrong rule, and a coverage assertion looking on the wrong line) — each would have let an attack pass or fail for an unrelated reason. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-07-27 20:57:46 +00:00
# 9 widen `allowedBoundary` by one name + a False-proof (round-5 NEW-1:
# previously ALL GREEN with the fingerprint BYTE-IDENTICAL)
# 10 redefine a reference fold to BE the extracted loop (round-5 NEW-2:
# previously ALL GREEN — the certificate degenerates to `loop = loop`)
# 11 `def : False` instead of `theorem : False` (drill: the round-4
# enumeration matched `.thmInfo` only, so this passed)
# 12 a False-proof inside Audit.lean itself (round-5 R1: the
# auditor was exempt from its own enumeration)
# 13 stub `lean-guard` (round-5 NEW-3:
# previously ALL GREEN in 3.6s over destroyed proofs)
# 14 a stray .lean beside check.sh (round-5 NEW-4:
# LEAN_PATH includes $PWD, so it can join the environment ungated)
review round 6: pin the auditor, purge every olean, pin gen/ as a set Round 6 confirmed the digest redesign closed NEW-1/NEW-2/NEW-5 at the mechanism ("the first time in three rounds I have not been able to gut a certificate"), then demonstrated two more ways to reach ALL GREEN with the committed digest BYTE-IDENTICAL over a repository proving False. Both are fixed. NEW-7 — the digest bound the audit's DATA, never its LOGIC. Flipping the two fail-closed guards in Proofs/Audit.lean to `unless true` disabled every in-Lean check; the block's inputs genuinely had not changed, so the digest still matched. Total attacker diff: 2 files, 6 insertions. Worse, TRUSTED-BASE item 11 listed the trusted-unbound set and did NOT mention Audit.lean, so a reviewer using it as a map of what to read by hand would have skipped the file that computes the number it is judged by. FIX: Proofs/Audit.lean is now sha256-pinned in harness_integrity_sha256, symmetric with lean-guard, and item 11 says so — including the honest residue: an author who edits the logic AND rotates its pin is caught only by reading the diff at the pin. NEW-8 — Phase 0's purge covered gen/ and Proofs/ while the stray check greped only *.lean, so an ORPHAN verification/Evil.olean whose source had been DELETED fell between them, satisfied an import, and was invisible to git status (*.olean is gitignored). FIX: purge every .olean under verification/, and forbid stray .lean AND .olean. NEW-9 (partial) — gen/ was pinned by four NAMES, not as a SET, so a new file there was neither hashed nor forbidden while LEAN_PATH contains $PWD/gen. FIX: Phase 0 asserts the gen/*.lean file set equals the pin map exactly. This found a real gap on its first run: Aeneas emits *_Template.lean scaffolding into gen/ on every extraction — untracked byproducts (a fresh clone has only the four pinned files) that nothing imports but that sat on LEAN_PATH unpinned. They are now purged as byproducts before the set assertion. Also, from the reviewer's §3 suggestion: the canonical block is now COMMITTED as verification/AUDIT-MANIFEST.txt, so a digest mismatch prints a real diff instead of writing an observed file with nothing to compare against; check.sh also fails if the committed copy drifts from what Lean emits. check-selftest.sh: 16 attacks, all rejected, plus the coverage check. Attacks 16 and 17 are the reviewer's two demonstrations. Attacks that mutate the audit's DATA now re-pin Audit.lean first, so they still test the digest/enumeration rather than being stopped by the byte pin; attack 17 deliberately does not re-pin, because the pin is what it tests. Housekeeping: PROVENANCE.json trailing newline restored (NEW-12). Disclosed rather than buried: two more of my own assertion bugs this round — attack 16 asserted the hygiene message when the correct rejection is the purge plus a failed import, and the earlier gen/ set check surfaced the template files only because it was written strictly. Both are the wrong-diagnostic class. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-07-28 07:22:12 +00:00
# 16 an ORPHAN .olean whose source was deleted (round-6 NEW-8:
# fell between the purge and the stray check; ALL GREEN, digest identical)
# 17 the audit's fail-closed guards switched off (round-6 NEW-7:
# the digest binds the audit's DATA, never its LOGIC; two characters in
# Audit.lean defeated every gate with the digest BYTE-IDENTICAL)
round 7: assert pin-map completeness (NEW-13), correct the count to 137, fix the regeneration-scope contradiction The third reviewer demonstrated NEW-13: PROVENANCE.json is a tracked file that nothing pins, and Phase 0's only completeness test was 'is the map non-empty'. Deleting the harness_integrity_sha256 key therefore silently un-pinned BOTH lean-guard and Proofs/Audit.lean with no diagnostic, after which the round-6 logic mutation ran to ALL GREEN over a repository proving False with the digest byte-identical. Reproduced here before fixing. The required pin NAMES now live hardcoded in check.sh — policy in the root of trust, values in the map — so a shortened map is a build failure naming the missing entries. Self-test attack 18 performs the deletion. GPT reviewer, independently: the documented '131 assertion points' was wrong. Recounted from the code, the defensible figure is 137 mono-path evaluated cases (9 retained original + 108 randomized + 10 NIST internal + 10 NIST external-pure); 131 had folded in 3 deployed-only prehash cases while omitting the retained test, and TRUSTED-BASE then decomposed it as 20 + 108 = 128, contradicting itself. Item 9 now carries the full table, states that 127 of the 137 compare mono against deployed, keeps the 3 prehash cases explicitly outside the total, and records that only two SHA2-512 and one SHAKE-256 vector are executable there — so this is not NIST coverage of all four supported prehash variants. Also from GPT: PROVENANCE.json contradicted itself, saying extraction 'reproduces all four model files byte-identically' while its own _comment correctly said the two *External files are hand-maintained. Extraction regenerates two files; the other two are byte-pinned. Corrected. TRUSTED-BASE item 11 now discloses that PROVENANCE.json is itself load-bearing and unpinned, and item 7's stale snapshot head is fixed. README states the lean-guard graceful fallback and that the empirical bridge runs on stable Rust without any Lean toolchain (round-7 NEW-16), which is the first load-bearing part of this work a third party can reproduce with cargo alone. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-07-28 11:03:35 +00:00
# 18 the pin map shortened by one JSON key (round-7 NEW-13:
# deleting harness_integrity_sha256 silently un-pinned BOTH lean-guard and
# Audit.lean with no diagnostic, re-opening 17 with the digest identical)
review round 5: bind the policy, the specification bodies, and the harness The third reviewer demonstrated that the round-4 gate was closed at the EXPLOITS, not the MECHANISMS: it bound the manifest rows while the things he moved sat outside the binding. Three fail-opens, each executed end-to-end with the button printing ALL GREEN. No theorem, proof, fold, or model body changed. NEW-1 — the policy constant was unbound. `manifestFingerprint` covered `manifest` but never `allowedBoundary`, the sole predicate the enumeration tests against; adding one name re-opened the False-proof with the committed fingerprint BYTE-IDENTICAL. NEW-2 — the specification bodies were unbound. The statement fingerprint pinned each certificate's TYPE, which names its reference fold; redefining that fold to *be* the extracted loop left cone and type-hash identical while the certificate degenerated to `loop = loop`. 100% of the fidelity content lives in those defs. NEW-3 — the harness was unbound. Stubbing verification/lean-guard alone, without touching check.sh or the proofs, gave ALL GREEN in 3.6s over destroyed proofs. FIX — one mechanism rather than three patches. Audit.lean now emits a canonical AUDIT-MANIFEST block and check.sh binds to its SHA-256. The block covers the POLICY constants, every certificate's fully-elaborated statement, and every specification constant transitively reachable from those statements with its fully-elaborated BODY (41 constants; the closure is computed, so a new fold cannot appear without moving the digest; Prop-valued constants contribute their statement, by proof irrelevance). This also retires the 32-bit Expr.hash as the binding (NEW-5) — it survives only as a per-certificate diagnostic. Enumeration now covers EVERY declaration kind (a `def : False` passed before) in the eight certificate modules AND in Audit.lean itself — the auditor is no longer exempt (round-5 R1). A bare `axiom` in audited scope is now an error. Phase 0 purges stale .olean (the verdict must depend on committed bytes, not .gitignored build state — NEW-4), forbids any .lean outside gen/ and Proofs/, and sha256-pins the four model files AND lean-guard. lean-guard is KEPT rather than removed (the reviewer's portability advice is declined by operator decision): it is the memory cap and machine-wide lock that protect the build machine after a 12.2GB OOM took the host down. That trade-off is documented. check.sh's "Certificates proven:" line now comes from the audited manifest; the hand-kept CERTS array — the one authoritative claim string nothing bound — is deleted. check-selftest.sh: 14 attacks, all rejected, plus a check that the hashed block literally carries the twelve fold bodies. Attacks 9-14 are the reviewers' and an independent drill's own exploits, turned into regression tests. DOCS. TRUSTED-BASE gains item 11 (the REAL trusted computing base — lean-guard pinned; check.sh, the toolchain env, $AENEAS_HOME, python3 and Lean still trusted) and item 12 (the apex does not compose the ten). README: the audit description rewritten; the XMSS sibling-order claim downgraded from "pins" to "makes visible", with a new blanket non-claim covering all ten loop certificates; the de-plumbing file claim corrected (round 1 touched only verify_mono.rs, round 2 only helpers.rs — which is ON the deployed verify AND sign paths, now disclosed; wots.rs was never patched). RECORDED-RUN: three lines that stood inside a fence were a hand-written summary, not console output — fabricated evidence in the file whose purpose is machine evidence. They are removed and the fabrication is named in place, together with the correction that the "INDEPENDENT RUN" block predates this gate. New rule: nothing goes in a fence unless captured with tee/cat, and every block states its date, pin, and who ran it. The transcripts added here follow it. Also disclosed rather than buried: three bugs in my own test harness this round (an olean-purge build-order break, an attack rejected by the wrong rule, and a coverage assertion looking on the wrong line) — each would have let an attack pass or fail for an unrelated reason. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-07-27 20:57:46 +00:00
#
# Self-cleaning: every mutated file is backed up and restored, and an EXIT trap
# restores even on failure. Run from a clean tree.
review round 4: bind the cert set, statements, and model bytes (F1/F2/F3) The third reviewer demonstrated that the round-2 in-Lean exact-cone audit, though sound for LISTED certs, left three fail-opens OUTSIDE the cone check — and made check.sh print ALL GREEN over a repo proving False. All closed; no theorem, proof, or fold changed (the 11 cones are unchanged). F1 — the audited SET was unbound. Audit.lean now (a) enumerates EVERY theorem defined in the eight certificate modules and requires each cone ⊆ boundary, so an un-manifested `theorem _ : False := cheat _` fails regardless of naming (this is the exact exploit the reviewer used); and (b) prints a MANIFEST fingerprint over the whole committed manifest, which check.sh binds to — so deleting/swapping a cert row fails outside Lean too. F2 — only cones were bound, not statements. Each cert now also carries the structural fingerprint (Expr.hash) of its elaborated type; a statement gutted to a tautology of the same cone changes the fingerprint and fails. F3 — the gen/ model bytes were unbound. New check.sh Phase 0 sha256-pins all four gen/SlhVerify/*.lean (incl. the two hand-maintained *External files, now hashed in PROVENANCE.json) BEFORE compiling; a hand-edited model fails first. F4/F5 — docs. README cone diagram now roots honestly at slh_verify_internal and states the pure/prehash domain-separator byte, the ctx>255 check, M' assembly, and deserialization are ABOVE the root and uncovered (new TRUSTED-BASE item 10). The false "rules out a wrong ADRS field" claim is corrected in README + ChainSpec (a transliteration makes the field visible, not excluded). check-selftest.sh: eight attacks, all rejected (dead file; extra axiom; dropped oracle; vanished cert; un-manifested False theorem; gutted statement; hand-edited model; deleted manifest row). Full transcript + green check.sh in verification/RECORDED-RUN.md. Standing limit unchanged and disclosed: an audit cannot defend against an author who edits the manifest AND check.sh AND the proofs together; the consumer defense is the pinned commit reviewed at the pin. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-07-27 17:47:39 +00:00
set -uo pipefail
post-flip drill over the chain certificate: HELD; audit gates now self-tested The window under audit claimed the campaign's first certificate, so this drill was maximally adversarial. Everything of substance HELD: - three-way model fidelity EXACT: extracted chain_free_loop.body == chainFoldN step == the Rust origin, operation-for-operation including address threading - button green fresh; axiom sweep over ALL 8 declarations minimal (pure lemmas = kernel-3; oracle-touching = kernel-3 + oracle.f only) - non-vacuity PROVEN: the concrete 1-step consequence (one address-set + one hash call) derives from the certificate by rfl - commit body of cfd50bb intact (the one flagged fragment was a bad drill grep pattern, not an artifact); worktree clean; heads synced NEW, from the drill (R3-5 tradition): verification/check-selftest.sh - permanent adversarial self-test of the check.sh gates. Attack 1 (dead Proofs file) and attack 2 (certificate with a smuggled axiom) must both make check.sh fail; both verified rejected, selftest green, self-cleaning. An audit that cannot fail is theater; this one demonstrably can. Two notes for the record: (a) bind_congr is the generic Bind-class congruence from core/Mathlib, not Aeneas.Std.Primitives (memory corrected); (b) the certificate covers chain_free_loop - the thin chain_free wrapper (bound computation + massert + clone) gets its trivial composition lemma in the wots layer, where it is consumed. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-23 12:34:42 +00:00
HERE="$(cd "$(dirname "$0")" && pwd)"
cd "$HERE"
review round 5: bind the policy, the specification bodies, and the harness The third reviewer demonstrated that the round-4 gate was closed at the EXPLOITS, not the MECHANISMS: it bound the manifest rows while the things he moved sat outside the binding. Three fail-opens, each executed end-to-end with the button printing ALL GREEN. No theorem, proof, fold, or model body changed. NEW-1 — the policy constant was unbound. `manifestFingerprint` covered `manifest` but never `allowedBoundary`, the sole predicate the enumeration tests against; adding one name re-opened the False-proof with the committed fingerprint BYTE-IDENTICAL. NEW-2 — the specification bodies were unbound. The statement fingerprint pinned each certificate's TYPE, which names its reference fold; redefining that fold to *be* the extracted loop left cone and type-hash identical while the certificate degenerated to `loop = loop`. 100% of the fidelity content lives in those defs. NEW-3 — the harness was unbound. Stubbing verification/lean-guard alone, without touching check.sh or the proofs, gave ALL GREEN in 3.6s over destroyed proofs. FIX — one mechanism rather than three patches. Audit.lean now emits a canonical AUDIT-MANIFEST block and check.sh binds to its SHA-256. The block covers the POLICY constants, every certificate's fully-elaborated statement, and every specification constant transitively reachable from those statements with its fully-elaborated BODY (41 constants; the closure is computed, so a new fold cannot appear without moving the digest; Prop-valued constants contribute their statement, by proof irrelevance). This also retires the 32-bit Expr.hash as the binding (NEW-5) — it survives only as a per-certificate diagnostic. Enumeration now covers EVERY declaration kind (a `def : False` passed before) in the eight certificate modules AND in Audit.lean itself — the auditor is no longer exempt (round-5 R1). A bare `axiom` in audited scope is now an error. Phase 0 purges stale .olean (the verdict must depend on committed bytes, not .gitignored build state — NEW-4), forbids any .lean outside gen/ and Proofs/, and sha256-pins the four model files AND lean-guard. lean-guard is KEPT rather than removed (the reviewer's portability advice is declined by operator decision): it is the memory cap and machine-wide lock that protect the build machine after a 12.2GB OOM took the host down. That trade-off is documented. check.sh's "Certificates proven:" line now comes from the audited manifest; the hand-kept CERTS array — the one authoritative claim string nothing bound — is deleted. check-selftest.sh: 14 attacks, all rejected, plus a check that the hashed block literally carries the twelve fold bodies. Attacks 9-14 are the reviewers' and an independent drill's own exploits, turned into regression tests. DOCS. TRUSTED-BASE gains item 11 (the REAL trusted computing base — lean-guard pinned; check.sh, the toolchain env, $AENEAS_HOME, python3 and Lean still trusted) and item 12 (the apex does not compose the ten). README: the audit description rewritten; the XMSS sibling-order claim downgraded from "pins" to "makes visible", with a new blanket non-claim covering all ten loop certificates; the de-plumbing file claim corrected (round 1 touched only verify_mono.rs, round 2 only helpers.rs — which is ON the deployed verify AND sign paths, now disclosed; wots.rs was never patched). RECORDED-RUN: three lines that stood inside a fence were a hand-written summary, not console output — fabricated evidence in the file whose purpose is machine evidence. They are removed and the fabrication is named in place, together with the correction that the "INDEPENDENT RUN" block predates this gate. New rule: nothing goes in a fence unless captured with tee/cat, and every block states its date, pin, and who ran it. The transcripts added here follow it. Also disclosed rather than buried: three bugs in my own test harness this round (an olean-purge build-order break, an attack rejected by the wrong rule, and a coverage assertion looking on the wrong line) — each would have let an attack pass or fail for an unrelated reason. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-07-27 20:57:46 +00:00
source ~/aeneas-toolchain/env.sh
post-flip drill over the chain certificate: HELD; audit gates now self-tested The window under audit claimed the campaign's first certificate, so this drill was maximally adversarial. Everything of substance HELD: - three-way model fidelity EXACT: extracted chain_free_loop.body == chainFoldN step == the Rust origin, operation-for-operation including address threading - button green fresh; axiom sweep over ALL 8 declarations minimal (pure lemmas = kernel-3; oracle-touching = kernel-3 + oracle.f only) - non-vacuity PROVEN: the concrete 1-step consequence (one address-set + one hash call) derives from the certificate by rfl - commit body of cfd50bb intact (the one flagged fragment was a bad drill grep pattern, not an artifact); worktree clean; heads synced NEW, from the drill (R3-5 tradition): verification/check-selftest.sh - permanent adversarial self-test of the check.sh gates. Attack 1 (dead Proofs file) and attack 2 (certificate with a smuggled axiom) must both make check.sh fail; both verified rejected, selftest green, self-cleaning. An audit that cannot fail is theater; this one demonstrably can. Two notes for the record: (a) bind_congr is the generic Bind-class congruence from core/Mathlib, not Aeneas.Std.Primitives (memory corrected); (b) the certificate covers chain_free_loop - the thin chain_free wrapper (bound computation + massert + clone) gets its trivial composition lemma in the wots layer, where it is consumed. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-23 12:34:42 +00:00
round 8: self-deriving harness pins, honest extraction guarantees, attestation basis Third reviewer returned ATTEST-with-conditions at 1bc4f39. Its conditions are committed verbatim as ATTESTATION-BASIS.md so the limits travel with the artifact instead of living in a review document a consumer never sees. Condition 9 — that extract.sh's byte-identical regeneration has never been observed by any party but the author — is the campaign's last open item, and the file records that both reviewers are now blocked on it for different environmental reasons. HARNESS PINS ARE NOW SELF-DERIVING. My round-7 fix hardcoded the required pin names, which the reviewer correctly called a second thing to keep in sync, and it supplied the boundary the harness does have: the executable bit. check.sh now requires every executable file in verification/ to be pinned (itself excluded — it cannot pin itself), plus Proofs/Audit.lean. A new harness script therefore fails closed until pinned. Consequence, and the reviewer argued for it: check-selftest.sh, drill.sh and extract.sh are now pinned too — the self-test is the only artifact demonstrating the gates work, and its assertions have been defective in four consecutive rounds, so weakening it should be a reviewable rotation rather than an unnoticed edit. THE EXTRACTION SCRIPT'S GUARANTEES ARE NOW STATED HONESTLY. The reviewer found a tautological assert in it — comparing a dict against the comprehension that had just built it — in the script written to fix a provenance-honesty defect. My first repair (comparing kept[k] against t[k]) was tautological for the same reason, which I confirmed by negative test. No check inside a transformer can detect a corrupted input, because the transformer defines the output from that input; that lesson is now recorded in the code. Both fake checks are gone and the header and provenance text name what actually protects the result — the pinned SOURCE_SHA256, the sk-must-be-present check, the group and test counts, and verify mode — each of which I negative-tested. Also: the self-test keeps its backups outside verification/ (cp -p preserves the executable bit, so an in-tree backup would have looked like an unpinned harness file and failed a run for an unrelated reason); the Phase-0 banner no longer says a file 'differs' when an entry is simply absent; and attack 18's assertion follows the renamed diagnostic and now requires both missing pins to be named. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-07-28 12:40:39 +00:00
# Backups live OUTSIDE verification/. Round-8 added a self-deriving harness rule:
# every executable file in this directory must be pinned. `cp -p` preserves the
# executable bit, so an in-tree `check.sh.sfbak` would look like an unpinned
# harness file and fail the run for a reason unrelated to the attack — the
# defect class this suite exists to catch.
SFBAK="$(mktemp -d)"
review round 5: bind the policy, the specification bodies, and the harness The third reviewer demonstrated that the round-4 gate was closed at the EXPLOITS, not the MECHANISMS: it bound the manifest rows while the things he moved sat outside the binding. Three fail-opens, each executed end-to-end with the button printing ALL GREEN. No theorem, proof, fold, or model body changed. NEW-1 — the policy constant was unbound. `manifestFingerprint` covered `manifest` but never `allowedBoundary`, the sole predicate the enumeration tests against; adding one name re-opened the False-proof with the committed fingerprint BYTE-IDENTICAL. NEW-2 — the specification bodies were unbound. The statement fingerprint pinned each certificate's TYPE, which names its reference fold; redefining that fold to *be* the extracted loop left cone and type-hash identical while the certificate degenerated to `loop = loop`. 100% of the fidelity content lives in those defs. NEW-3 — the harness was unbound. Stubbing verification/lean-guard alone, without touching check.sh or the proofs, gave ALL GREEN in 3.6s over destroyed proofs. FIX — one mechanism rather than three patches. Audit.lean now emits a canonical AUDIT-MANIFEST block and check.sh binds to its SHA-256. The block covers the POLICY constants, every certificate's fully-elaborated statement, and every specification constant transitively reachable from those statements with its fully-elaborated BODY (41 constants; the closure is computed, so a new fold cannot appear without moving the digest; Prop-valued constants contribute their statement, by proof irrelevance). This also retires the 32-bit Expr.hash as the binding (NEW-5) — it survives only as a per-certificate diagnostic. Enumeration now covers EVERY declaration kind (a `def : False` passed before) in the eight certificate modules AND in Audit.lean itself — the auditor is no longer exempt (round-5 R1). A bare `axiom` in audited scope is now an error. Phase 0 purges stale .olean (the verdict must depend on committed bytes, not .gitignored build state — NEW-4), forbids any .lean outside gen/ and Proofs/, and sha256-pins the four model files AND lean-guard. lean-guard is KEPT rather than removed (the reviewer's portability advice is declined by operator decision): it is the memory cap and machine-wide lock that protect the build machine after a 12.2GB OOM took the host down. That trade-off is documented. check.sh's "Certificates proven:" line now comes from the audited manifest; the hand-kept CERTS array — the one authoritative claim string nothing bound — is deleted. check-selftest.sh: 14 attacks, all rejected, plus a check that the hashed block literally carries the twelve fold bodies. Attacks 9-14 are the reviewers' and an independent drill's own exploits, turned into regression tests. DOCS. TRUSTED-BASE gains item 11 (the REAL trusted computing base — lean-guard pinned; check.sh, the toolchain env, $AENEAS_HOME, python3 and Lean still trusted) and item 12 (the apex does not compose the ten). README: the audit description rewritten; the XMSS sibling-order claim downgraded from "pins" to "makes visible", with a new blanket non-claim covering all ten loop certificates; the de-plumbing file claim corrected (round 1 touched only verify_mono.rs, round 2 only helpers.rs — which is ON the deployed verify AND sign paths, now disclosed; wots.rs was never patched). RECORDED-RUN: three lines that stood inside a fence were a hand-written summary, not console output — fabricated evidence in the file whose purpose is machine evidence. They are removed and the fabrication is named in place, together with the correction that the "INDEPENDENT RUN" block predates this gate. New rule: nothing goes in a fence unless captured with tee/cat, and every block states its date, pin, and who ran it. The transcripts added here follow it. Also disclosed rather than buried: three bugs in my own test harness this round (an olean-purge build-order break, an attack rejected by the wrong rule, and a coverage assertion looking on the wrong line) — each would have let an attack pass or fail for an unrelated reason. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-07-27 20:57:46 +00:00
BAKS=()
round 8: self-deriving harness pins, honest extraction guarantees, attestation basis Third reviewer returned ATTEST-with-conditions at 1bc4f39. Its conditions are committed verbatim as ATTESTATION-BASIS.md so the limits travel with the artifact instead of living in a review document a consumer never sees. Condition 9 — that extract.sh's byte-identical regeneration has never been observed by any party but the author — is the campaign's last open item, and the file records that both reviewers are now blocked on it for different environmental reasons. HARNESS PINS ARE NOW SELF-DERIVING. My round-7 fix hardcoded the required pin names, which the reviewer correctly called a second thing to keep in sync, and it supplied the boundary the harness does have: the executable bit. check.sh now requires every executable file in verification/ to be pinned (itself excluded — it cannot pin itself), plus Proofs/Audit.lean. A new harness script therefore fails closed until pinned. Consequence, and the reviewer argued for it: check-selftest.sh, drill.sh and extract.sh are now pinned too — the self-test is the only artifact demonstrating the gates work, and its assertions have been defective in four consecutive rounds, so weakening it should be a reviewable rotation rather than an unnoticed edit. THE EXTRACTION SCRIPT'S GUARANTEES ARE NOW STATED HONESTLY. The reviewer found a tautological assert in it — comparing a dict against the comprehension that had just built it — in the script written to fix a provenance-honesty defect. My first repair (comparing kept[k] against t[k]) was tautological for the same reason, which I confirmed by negative test. No check inside a transformer can detect a corrupted input, because the transformer defines the output from that input; that lesson is now recorded in the code. Both fake checks are gone and the header and provenance text name what actually protects the result — the pinned SOURCE_SHA256, the sk-must-be-present check, the group and test counts, and verify mode — each of which I negative-tested. Also: the self-test keeps its backups outside verification/ (cp -p preserves the executable bit, so an in-tree backup would have looked like an unpinned harness file and failed a run for an unrelated reason); the Phase-0 banner no longer says a file 'differs' when an entry is simply absent; and attack 18's assertion follows the renamed diagnostic and now requires both missing pins to be named. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-07-28 12:40:39 +00:00
save() { cp -p "$1" "$SFBAK/$(printf %s "$1" | tr / _)"; BAKS+=("$1"); }
restore() { for f in "${BAKS[@]:-}"; do
b="$SFBAK/$(printf %s "$f" | tr / _)"
[ -f "$b" ] && cp -p "$b" "$f" && rm -f "$b"
done; BAKS=(); }
review round 6: pin the auditor, purge every olean, pin gen/ as a set Round 6 confirmed the digest redesign closed NEW-1/NEW-2/NEW-5 at the mechanism ("the first time in three rounds I have not been able to gut a certificate"), then demonstrated two more ways to reach ALL GREEN with the committed digest BYTE-IDENTICAL over a repository proving False. Both are fixed. NEW-7 — the digest bound the audit's DATA, never its LOGIC. Flipping the two fail-closed guards in Proofs/Audit.lean to `unless true` disabled every in-Lean check; the block's inputs genuinely had not changed, so the digest still matched. Total attacker diff: 2 files, 6 insertions. Worse, TRUSTED-BASE item 11 listed the trusted-unbound set and did NOT mention Audit.lean, so a reviewer using it as a map of what to read by hand would have skipped the file that computes the number it is judged by. FIX: Proofs/Audit.lean is now sha256-pinned in harness_integrity_sha256, symmetric with lean-guard, and item 11 says so — including the honest residue: an author who edits the logic AND rotates its pin is caught only by reading the diff at the pin. NEW-8 — Phase 0's purge covered gen/ and Proofs/ while the stray check greped only *.lean, so an ORPHAN verification/Evil.olean whose source had been DELETED fell between them, satisfied an import, and was invisible to git status (*.olean is gitignored). FIX: purge every .olean under verification/, and forbid stray .lean AND .olean. NEW-9 (partial) — gen/ was pinned by four NAMES, not as a SET, so a new file there was neither hashed nor forbidden while LEAN_PATH contains $PWD/gen. FIX: Phase 0 asserts the gen/*.lean file set equals the pin map exactly. This found a real gap on its first run: Aeneas emits *_Template.lean scaffolding into gen/ on every extraction — untracked byproducts (a fresh clone has only the four pinned files) that nothing imports but that sat on LEAN_PATH unpinned. They are now purged as byproducts before the set assertion. Also, from the reviewer's §3 suggestion: the canonical block is now COMMITTED as verification/AUDIT-MANIFEST.txt, so a digest mismatch prints a real diff instead of writing an observed file with nothing to compare against; check.sh also fails if the committed copy drifts from what Lean emits. check-selftest.sh: 16 attacks, all rejected, plus the coverage check. Attacks 16 and 17 are the reviewer's two demonstrations. Attacks that mutate the audit's DATA now re-pin Audit.lean first, so they still test the digest/enumeration rather than being stopped by the byte pin; attack 17 deliberately does not re-pin, because the pin is what it tests. Housekeeping: PROVENANCE.json trailing newline restored (NEW-12). Disclosed rather than buried: two more of my own assertion bugs this round — attack 16 asserted the hygiene message when the correct rejection is the purge plus a failed import, and the earlier gen/ set check surfaced the template files only because it was written strictly. Both are the wrong-diagnostic class. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-07-28 07:22:12 +00:00
# Proofs/Audit.lean is sha256-pinned by Phase 0 since round 6 (NEW-7). An attack
# that mutates the audit's DATA must therefore ALSO rotate that pin, otherwise it
# is stopped by the byte pin and never reaches the mechanism it means to test —
# the "rejected for an unrelated reason" defect class. `repin_audit` simulates an
# author who edits and dutifully re-pins; the digest/enumeration must still bite.
# Attack 17 deliberately does NOT re-pin: it is the test of the pin itself.
repin_audit() {
python3 - <<'PY'
import json, hashlib
p = "PROVENANCE.json"; d = json.load(open(p))
d["harness_integrity_sha256"]["Proofs/Audit.lean"] = hashlib.sha256(
open("Proofs/Audit.lean","rb").read()).hexdigest()
json.dump(d, open(p,"w"), indent=2); open(p,"a").write("\n")
PY
}
review round 2: in-Lean exact-cone audit + reproducibility + doc honesty Addresses the round-2 reviewer punch-list. No theorem statement, proof term, or fold definition changed; the eleven cones are unchanged (independent collectAxioms dump in verification/RECORDED-RUN.md). AUDIT GATE (both reviewers, the critical one) - Retire the bash #print-axioms text parser (fail-open on empty/truncated reports, and only a SUBSET check). Replace with verification/Proofs/Audit.lean: reads each certificate's cone from the kernel via collectAxioms and asserts EXACT set equality against its expected boundary. Extra axiom, dropped oracle, renamed/deleted cert, or an axiom/opaque sham each throw -> non-zero Lean exit. No text to misparse; nothing fails open. check.sh Phase 3 now just compiles it (and still requires the explicit PASSED line). - check-selftest.sh rewritten to attack the new gate: dead-file, smuggled extra axiom (named), dropped-oracle (subset would pass, exact must not), and a vanished certificate (the collectAxioms-returns-[] trap). All four rejected. REPRODUCIBILITY (GPT B1.4 / B1.5) - extract.sh refuses a wrong-commit or dirty source tree (fail-closed), takes an optional source-path arg, and pins the source commit. - verification/PROVENANCE.json: single machine-readable pin set (source + charon + aeneas commits/channel + lean + ocaml) with generated-file sha256. - Re-running extract.sh reproduces gen/SlhVerify/{Types,Funs}.lean byte-identically (companion fips205-source commit adds Cargo.lock + rust-toolchain.toml; verified not to perturb the model). DOC HONESTY (both reviewers) - README: fix the self-contradiction (apex "not yet proven" trailer vs the proven apex), the false "oracles kept OUTSIDE every cone" (they are INSIDE, by design), "deployed monomorphic path" and "semantics-identical for every parameter set" overclaims, "only two lines changed", stale snapshot head; retitle the stale future-tense "what will be claimed" section. - TRUSTED-BASE: drop "nothing proven yet"; add base_2b-inner and deployment- bridge non-claims explicitly; current pin. - ChainSpec header: "deployed monomorphic path" -> private verify_mono facade (comment only). Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-07-24 17:13:55 +00:00
cleanup() {
restore
round 8: self-deriving harness pins, honest extraction guarantees, attestation basis Third reviewer returned ATTEST-with-conditions at 1bc4f39. Its conditions are committed verbatim as ATTESTATION-BASIS.md so the limits travel with the artifact instead of living in a review document a consumer never sees. Condition 9 — that extract.sh's byte-identical regeneration has never been observed by any party but the author — is the campaign's last open item, and the file records that both reviewers are now blocked on it for different environmental reasons. HARNESS PINS ARE NOW SELF-DERIVING. My round-7 fix hardcoded the required pin names, which the reviewer correctly called a second thing to keep in sync, and it supplied the boundary the harness does have: the executable bit. check.sh now requires every executable file in verification/ to be pinned (itself excluded — it cannot pin itself), plus Proofs/Audit.lean. A new harness script therefore fails closed until pinned. Consequence, and the reviewer argued for it: check-selftest.sh, drill.sh and extract.sh are now pinned too — the self-test is the only artifact demonstrating the gates work, and its assertions have been defective in four consecutive rounds, so weakening it should be a reviewable rotation rather than an unnoticed edit. THE EXTRACTION SCRIPT'S GUARANTEES ARE NOW STATED HONESTLY. The reviewer found a tautological assert in it — comparing a dict against the comprehension that had just built it — in the script written to fix a provenance-honesty defect. My first repair (comparing kept[k] against t[k]) was tautological for the same reason, which I confirmed by negative test. No check inside a transformer can detect a corrupted input, because the transformer defines the output from that input; that lesson is now recorded in the code. Both fake checks are gone and the header and provenance text name what actually protects the result — the pinned SOURCE_SHA256, the sk-must-be-present check, the group and test counts, and verify mode — each of which I negative-tested. Also: the self-test keeps its backups outside verification/ (cp -p preserves the executable bit, so an in-tree backup would have looked like an unpinned harness file and failed a run for an unrelated reason); the Phase-0 banner no longer says a file 'differs' when an entry is simply absent; and attack 18's assertion follows the renamed diagnostic and now requires both missing pins to be named. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-07-28 12:40:39 +00:00
rm -rf "$SFBAK" 2>/dev/null
review round 6: pin the auditor, purge every olean, pin gen/ as a set Round 6 confirmed the digest redesign closed NEW-1/NEW-2/NEW-5 at the mechanism ("the first time in three rounds I have not been able to gut a certificate"), then demonstrated two more ways to reach ALL GREEN with the committed digest BYTE-IDENTICAL over a repository proving False. Both are fixed. NEW-7 — the digest bound the audit's DATA, never its LOGIC. Flipping the two fail-closed guards in Proofs/Audit.lean to `unless true` disabled every in-Lean check; the block's inputs genuinely had not changed, so the digest still matched. Total attacker diff: 2 files, 6 insertions. Worse, TRUSTED-BASE item 11 listed the trusted-unbound set and did NOT mention Audit.lean, so a reviewer using it as a map of what to read by hand would have skipped the file that computes the number it is judged by. FIX: Proofs/Audit.lean is now sha256-pinned in harness_integrity_sha256, symmetric with lean-guard, and item 11 says so — including the honest residue: an author who edits the logic AND rotates its pin is caught only by reading the diff at the pin. NEW-8 — Phase 0's purge covered gen/ and Proofs/ while the stray check greped only *.lean, so an ORPHAN verification/Evil.olean whose source had been DELETED fell between them, satisfied an import, and was invisible to git status (*.olean is gitignored). FIX: purge every .olean under verification/, and forbid stray .lean AND .olean. NEW-9 (partial) — gen/ was pinned by four NAMES, not as a SET, so a new file there was neither hashed nor forbidden while LEAN_PATH contains $PWD/gen. FIX: Phase 0 asserts the gen/*.lean file set equals the pin map exactly. This found a real gap on its first run: Aeneas emits *_Template.lean scaffolding into gen/ on every extraction — untracked byproducts (a fresh clone has only the four pinned files) that nothing imports but that sat on LEAN_PATH unpinned. They are now purged as byproducts before the set assertion. Also, from the reviewer's §3 suggestion: the canonical block is now COMMITTED as verification/AUDIT-MANIFEST.txt, so a digest mismatch prints a real diff instead of writing an observed file with nothing to compare against; check.sh also fails if the committed copy drifts from what Lean emits. check-selftest.sh: 16 attacks, all rejected, plus the coverage check. Attacks 16 and 17 are the reviewer's two demonstrations. Attacks that mutate the audit's DATA now re-pin Audit.lean first, so they still test the digest/enumeration rather than being stopped by the byte pin; attack 17 deliberately does not re-pin, because the pin is what it tests. Housekeeping: PROVENANCE.json trailing newline restored (NEW-12). Disclosed rather than buried: two more of my own assertion bugs this round — attack 16 asserted the hygiene message when the correct rejection is the purge plus a failed import, and the earlier gen/ set check surfaced the template files only because it was written strictly. Both are the wrong-diagnostic class. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-07-28 07:22:12 +00:00
rm -f Proofs/Stray.lean Proofs/EvilSpec.lean Evil.lean Evil.olean \
Proofs/*.olean gen/SlhVerify/*.olean *.olean .audit-manifest.observed 2>/dev/null
review round 5: bind the policy, the specification bodies, and the harness The third reviewer demonstrated that the round-4 gate was closed at the EXPLOITS, not the MECHANISMS: it bound the manifest rows while the things he moved sat outside the binding. Three fail-opens, each executed end-to-end with the button printing ALL GREEN. No theorem, proof, fold, or model body changed. NEW-1 — the policy constant was unbound. `manifestFingerprint` covered `manifest` but never `allowedBoundary`, the sole predicate the enumeration tests against; adding one name re-opened the False-proof with the committed fingerprint BYTE-IDENTICAL. NEW-2 — the specification bodies were unbound. The statement fingerprint pinned each certificate's TYPE, which names its reference fold; redefining that fold to *be* the extracted loop left cone and type-hash identical while the certificate degenerated to `loop = loop`. 100% of the fidelity content lives in those defs. NEW-3 — the harness was unbound. Stubbing verification/lean-guard alone, without touching check.sh or the proofs, gave ALL GREEN in 3.6s over destroyed proofs. FIX — one mechanism rather than three patches. Audit.lean now emits a canonical AUDIT-MANIFEST block and check.sh binds to its SHA-256. The block covers the POLICY constants, every certificate's fully-elaborated statement, and every specification constant transitively reachable from those statements with its fully-elaborated BODY (41 constants; the closure is computed, so a new fold cannot appear without moving the digest; Prop-valued constants contribute their statement, by proof irrelevance). This also retires the 32-bit Expr.hash as the binding (NEW-5) — it survives only as a per-certificate diagnostic. Enumeration now covers EVERY declaration kind (a `def : False` passed before) in the eight certificate modules AND in Audit.lean itself — the auditor is no longer exempt (round-5 R1). A bare `axiom` in audited scope is now an error. Phase 0 purges stale .olean (the verdict must depend on committed bytes, not .gitignored build state — NEW-4), forbids any .lean outside gen/ and Proofs/, and sha256-pins the four model files AND lean-guard. lean-guard is KEPT rather than removed (the reviewer's portability advice is declined by operator decision): it is the memory cap and machine-wide lock that protect the build machine after a 12.2GB OOM took the host down. That trade-off is documented. check.sh's "Certificates proven:" line now comes from the audited manifest; the hand-kept CERTS array — the one authoritative claim string nothing bound — is deleted. check-selftest.sh: 14 attacks, all rejected, plus a check that the hashed block literally carries the twelve fold bodies. Attacks 9-14 are the reviewers' and an independent drill's own exploits, turned into regression tests. DOCS. TRUSTED-BASE gains item 11 (the REAL trusted computing base — lean-guard pinned; check.sh, the toolchain env, $AENEAS_HOME, python3 and Lean still trusted) and item 12 (the apex does not compose the ten). README: the audit description rewritten; the XMSS sibling-order claim downgraded from "pins" to "makes visible", with a new blanket non-claim covering all ten loop certificates; the de-plumbing file claim corrected (round 1 touched only verify_mono.rs, round 2 only helpers.rs — which is ON the deployed verify AND sign paths, now disclosed; wots.rs was never patched). RECORDED-RUN: three lines that stood inside a fence were a hand-written summary, not console output — fabricated evidence in the file whose purpose is machine evidence. They are removed and the fabrication is named in place, together with the correction that the "INDEPENDENT RUN" block predates this gate. New rule: nothing goes in a fence unless captured with tee/cat, and every block states its date, pin, and who ran it. The transcripts added here follow it. Also disclosed rather than buried: three bugs in my own test harness this round (an olean-purge build-order break, an attack rejected by the wrong rule, and a coverage assertion looking on the wrong line) — each would have let an attack pass or fail for an unrelated reason. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-07-27 20:57:46 +00:00
return 0
review round 2: in-Lean exact-cone audit + reproducibility + doc honesty Addresses the round-2 reviewer punch-list. No theorem statement, proof term, or fold definition changed; the eleven cones are unchanged (independent collectAxioms dump in verification/RECORDED-RUN.md). AUDIT GATE (both reviewers, the critical one) - Retire the bash #print-axioms text parser (fail-open on empty/truncated reports, and only a SUBSET check). Replace with verification/Proofs/Audit.lean: reads each certificate's cone from the kernel via collectAxioms and asserts EXACT set equality against its expected boundary. Extra axiom, dropped oracle, renamed/deleted cert, or an axiom/opaque sham each throw -> non-zero Lean exit. No text to misparse; nothing fails open. check.sh Phase 3 now just compiles it (and still requires the explicit PASSED line). - check-selftest.sh rewritten to attack the new gate: dead-file, smuggled extra axiom (named), dropped-oracle (subset would pass, exact must not), and a vanished certificate (the collectAxioms-returns-[] trap). All four rejected. REPRODUCIBILITY (GPT B1.4 / B1.5) - extract.sh refuses a wrong-commit or dirty source tree (fail-closed), takes an optional source-path arg, and pins the source commit. - verification/PROVENANCE.json: single machine-readable pin set (source + charon + aeneas commits/channel + lean + ocaml) with generated-file sha256. - Re-running extract.sh reproduces gen/SlhVerify/{Types,Funs}.lean byte-identically (companion fips205-source commit adds Cargo.lock + rust-toolchain.toml; verified not to perturb the model). DOC HONESTY (both reviewers) - README: fix the self-contradiction (apex "not yet proven" trailer vs the proven apex), the false "oracles kept OUTSIDE every cone" (they are INSIDE, by design), "deployed monomorphic path" and "semantics-identical for every parameter set" overclaims, "only two lines changed", stale snapshot head; retitle the stale future-tense "what will be claimed" section. - TRUSTED-BASE: drop "nothing proven yet"; add base_2b-inner and deployment- bridge non-claims explicitly; current pin. - ChainSpec header: "deployed monomorphic path" -> private verify_mono facade (comment only). Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-07-24 17:13:55 +00:00
}
post-flip drill over the chain certificate: HELD; audit gates now self-tested The window under audit claimed the campaign's first certificate, so this drill was maximally adversarial. Everything of substance HELD: - three-way model fidelity EXACT: extracted chain_free_loop.body == chainFoldN step == the Rust origin, operation-for-operation including address threading - button green fresh; axiom sweep over ALL 8 declarations minimal (pure lemmas = kernel-3; oracle-touching = kernel-3 + oracle.f only) - non-vacuity PROVEN: the concrete 1-step consequence (one address-set + one hash call) derives from the certificate by rfl - commit body of cfd50bb intact (the one flagged fragment was a bad drill grep pattern, not an artifact); worktree clean; heads synced NEW, from the drill (R3-5 tradition): verification/check-selftest.sh - permanent adversarial self-test of the check.sh gates. Attack 1 (dead Proofs file) and attack 2 (certificate with a smuggled axiom) must both make check.sh fail; both verified rejected, selftest green, self-cleaning. An audit that cannot fail is theater; this one demonstrably can. Two notes for the record: (a) bind_congr is the generic Bind-class congruence from core/Mathlib, not Aeneas.Std.Primitives (memory corrected); (b) the certificate covers chain_free_loop - the thin chain_free wrapper (bound computation + massert + clone) gets its trivial composition lemma in the wots layer, where it is consumed. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-23 12:34:42 +00:00
trap cleanup EXIT
review round 5: bind the policy, the specification bodies, and the harness The third reviewer demonstrated that the round-4 gate was closed at the EXPLOITS, not the MECHANISMS: it bound the manifest rows while the things he moved sat outside the binding. Three fail-opens, each executed end-to-end with the button printing ALL GREEN. No theorem, proof, fold, or model body changed. NEW-1 — the policy constant was unbound. `manifestFingerprint` covered `manifest` but never `allowedBoundary`, the sole predicate the enumeration tests against; adding one name re-opened the False-proof with the committed fingerprint BYTE-IDENTICAL. NEW-2 — the specification bodies were unbound. The statement fingerprint pinned each certificate's TYPE, which names its reference fold; redefining that fold to *be* the extracted loop left cone and type-hash identical while the certificate degenerated to `loop = loop`. 100% of the fidelity content lives in those defs. NEW-3 — the harness was unbound. Stubbing verification/lean-guard alone, without touching check.sh or the proofs, gave ALL GREEN in 3.6s over destroyed proofs. FIX — one mechanism rather than three patches. Audit.lean now emits a canonical AUDIT-MANIFEST block and check.sh binds to its SHA-256. The block covers the POLICY constants, every certificate's fully-elaborated statement, and every specification constant transitively reachable from those statements with its fully-elaborated BODY (41 constants; the closure is computed, so a new fold cannot appear without moving the digest; Prop-valued constants contribute their statement, by proof irrelevance). This also retires the 32-bit Expr.hash as the binding (NEW-5) — it survives only as a per-certificate diagnostic. Enumeration now covers EVERY declaration kind (a `def : False` passed before) in the eight certificate modules AND in Audit.lean itself — the auditor is no longer exempt (round-5 R1). A bare `axiom` in audited scope is now an error. Phase 0 purges stale .olean (the verdict must depend on committed bytes, not .gitignored build state — NEW-4), forbids any .lean outside gen/ and Proofs/, and sha256-pins the four model files AND lean-guard. lean-guard is KEPT rather than removed (the reviewer's portability advice is declined by operator decision): it is the memory cap and machine-wide lock that protect the build machine after a 12.2GB OOM took the host down. That trade-off is documented. check.sh's "Certificates proven:" line now comes from the audited manifest; the hand-kept CERTS array — the one authoritative claim string nothing bound — is deleted. check-selftest.sh: 14 attacks, all rejected, plus a check that the hashed block literally carries the twelve fold bodies. Attacks 9-14 are the reviewers' and an independent drill's own exploits, turned into regression tests. DOCS. TRUSTED-BASE gains item 11 (the REAL trusted computing base — lean-guard pinned; check.sh, the toolchain env, $AENEAS_HOME, python3 and Lean still trusted) and item 12 (the apex does not compose the ten). README: the audit description rewritten; the XMSS sibling-order claim downgraded from "pins" to "makes visible", with a new blanket non-claim covering all ten loop certificates; the de-plumbing file claim corrected (round 1 touched only verify_mono.rs, round 2 only helpers.rs — which is ON the deployed verify AND sign paths, now disclosed; wots.rs was never patched). RECORDED-RUN: three lines that stood inside a fence were a hand-written summary, not console output — fabricated evidence in the file whose purpose is machine evidence. They are removed and the fabrication is named in place, together with the correction that the "INDEPENDENT RUN" block predates this gate. New rule: nothing goes in a fence unless captured with tee/cat, and every block states its date, pin, and who ran it. The transcripts added here follow it. Also disclosed rather than buried: three bugs in my own test harness this round (an olean-purge build-order break, an attack rejected by the wrong rule, and a coverage assertion looking on the wrong line) — each would have let an attack pass or fail for an unrelated reason. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-07-27 20:57:46 +00:00
fail() { echo "$1"; shift; [ $# -gt 0 ] && sed 's/^/ /' "$1"; exit 1; }
post-flip drill over the chain certificate: HELD; audit gates now self-tested The window under audit claimed the campaign's first certificate, so this drill was maximally adversarial. Everything of substance HELD: - three-way model fidelity EXACT: extracted chain_free_loop.body == chainFoldN step == the Rust origin, operation-for-operation including address threading - button green fresh; axiom sweep over ALL 8 declarations minimal (pure lemmas = kernel-3; oracle-touching = kernel-3 + oracle.f only) - non-vacuity PROVEN: the concrete 1-step consequence (one address-set + one hash call) derives from the certificate by rfl - commit body of cfd50bb intact (the one flagged fragment was a bad drill grep pattern, not an artifact); worktree clean; heads synced NEW, from the drill (R3-5 tradition): verification/check-selftest.sh - permanent adversarial self-test of the check.sh gates. Attack 1 (dead Proofs file) and attack 2 (certificate with a smuggled axiom) must both make check.sh fail; both verified rejected, selftest green, self-cleaning. An audit that cannot fail is theater; this one demonstrably can. Two notes for the record: (a) bind_congr is the generic Bind-class congruence from core/Mathlib, not Aeneas.Std.Primitives (memory corrected); (b) the certificate covers chain_free_loop - the thin chain_free wrapper (bound computation + massert + clone) gets its trivial composition lemma in the wots layer, where it is consumed. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-23 12:34:42 +00:00
echo "check-selftest: attacking the gates"
echo "===================================="
review round 5: bind the policy, the specification bodies, and the harness The third reviewer demonstrated that the round-4 gate was closed at the EXPLOITS, not the MECHANISMS: it bound the manifest rows while the things he moved sat outside the binding. Three fail-opens, each executed end-to-end with the button printing ALL GREEN. No theorem, proof, fold, or model body changed. NEW-1 — the policy constant was unbound. `manifestFingerprint` covered `manifest` but never `allowedBoundary`, the sole predicate the enumeration tests against; adding one name re-opened the False-proof with the committed fingerprint BYTE-IDENTICAL. NEW-2 — the specification bodies were unbound. The statement fingerprint pinned each certificate's TYPE, which names its reference fold; redefining that fold to *be* the extracted loop left cone and type-hash identical while the certificate degenerated to `loop = loop`. 100% of the fidelity content lives in those defs. NEW-3 — the harness was unbound. Stubbing verification/lean-guard alone, without touching check.sh or the proofs, gave ALL GREEN in 3.6s over destroyed proofs. FIX — one mechanism rather than three patches. Audit.lean now emits a canonical AUDIT-MANIFEST block and check.sh binds to its SHA-256. The block covers the POLICY constants, every certificate's fully-elaborated statement, and every specification constant transitively reachable from those statements with its fully-elaborated BODY (41 constants; the closure is computed, so a new fold cannot appear without moving the digest; Prop-valued constants contribute their statement, by proof irrelevance). This also retires the 32-bit Expr.hash as the binding (NEW-5) — it survives only as a per-certificate diagnostic. Enumeration now covers EVERY declaration kind (a `def : False` passed before) in the eight certificate modules AND in Audit.lean itself — the auditor is no longer exempt (round-5 R1). A bare `axiom` in audited scope is now an error. Phase 0 purges stale .olean (the verdict must depend on committed bytes, not .gitignored build state — NEW-4), forbids any .lean outside gen/ and Proofs/, and sha256-pins the four model files AND lean-guard. lean-guard is KEPT rather than removed (the reviewer's portability advice is declined by operator decision): it is the memory cap and machine-wide lock that protect the build machine after a 12.2GB OOM took the host down. That trade-off is documented. check.sh's "Certificates proven:" line now comes from the audited manifest; the hand-kept CERTS array — the one authoritative claim string nothing bound — is deleted. check-selftest.sh: 14 attacks, all rejected, plus a check that the hashed block literally carries the twelve fold bodies. Attacks 9-14 are the reviewers' and an independent drill's own exploits, turned into regression tests. DOCS. TRUSTED-BASE gains item 11 (the REAL trusted computing base — lean-guard pinned; check.sh, the toolchain env, $AENEAS_HOME, python3 and Lean still trusted) and item 12 (the apex does not compose the ten). README: the audit description rewritten; the XMSS sibling-order claim downgraded from "pins" to "makes visible", with a new blanket non-claim covering all ten loop certificates; the de-plumbing file claim corrected (round 1 touched only verify_mono.rs, round 2 only helpers.rs — which is ON the deployed verify AND sign paths, now disclosed; wots.rs was never patched). RECORDED-RUN: three lines that stood inside a fence were a hand-written summary, not console output — fabricated evidence in the file whose purpose is machine evidence. They are removed and the fabrication is named in place, together with the correction that the "INDEPENDENT RUN" block predates this gate. New rule: nothing goes in a fence unless captured with tee/cat, and every block states its date, pin, and who ran it. The transcripts added here follow it. Also disclosed rather than buried: three bugs in my own test harness this round (an olean-purge build-order break, an attack rejected by the wrong rule, and a coverage assertion looking on the wrong line) — each would have let an attack pass or fail for an unrelated reason. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-07-27 20:57:46 +00:00
# ── 1: dead file ────────────────────────────────────────────────────────────
post-flip drill over the chain certificate: HELD; audit gates now self-tested The window under audit claimed the campaign's first certificate, so this drill was maximally adversarial. Everything of substance HELD: - three-way model fidelity EXACT: extracted chain_free_loop.body == chainFoldN step == the Rust origin, operation-for-operation including address threading - button green fresh; axiom sweep over ALL 8 declarations minimal (pure lemmas = kernel-3; oracle-touching = kernel-3 + oracle.f only) - non-vacuity PROVEN: the concrete 1-step consequence (one address-set + one hash call) derives from the certificate by rfl - commit body of cfd50bb intact (the one flagged fragment was a bad drill grep pattern, not an artifact); worktree clean; heads synced NEW, from the drill (R3-5 tradition): verification/check-selftest.sh - permanent adversarial self-test of the check.sh gates. Attack 1 (dead Proofs file) and attack 2 (certificate with a smuggled axiom) must both make check.sh fail; both verified rejected, selftest green, self-cleaning. An audit that cannot fail is theater; this one demonstrably can. Two notes for the record: (a) bind_congr is the generic Bind-class congruence from core/Mathlib, not Aeneas.Std.Primitives (memory corrected); (b) the certificate covers chain_free_loop - the thin chain_free wrapper (bound computation + massert + clone) gets its trivial composition lemma in the wots layer, where it is consumed. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-23 12:34:42 +00:00
echo "-- stray" > Proofs/Stray.lean
review round 5: bind the policy, the specification bodies, and the harness The third reviewer demonstrated that the round-4 gate was closed at the EXPLOITS, not the MECHANISMS: it bound the manifest rows while the things he moved sat outside the binding. Three fail-opens, each executed end-to-end with the button printing ALL GREEN. No theorem, proof, fold, or model body changed. NEW-1 — the policy constant was unbound. `manifestFingerprint` covered `manifest` but never `allowedBoundary`, the sole predicate the enumeration tests against; adding one name re-opened the False-proof with the committed fingerprint BYTE-IDENTICAL. NEW-2 — the specification bodies were unbound. The statement fingerprint pinned each certificate's TYPE, which names its reference fold; redefining that fold to *be* the extracted loop left cone and type-hash identical while the certificate degenerated to `loop = loop`. 100% of the fidelity content lives in those defs. NEW-3 — the harness was unbound. Stubbing verification/lean-guard alone, without touching check.sh or the proofs, gave ALL GREEN in 3.6s over destroyed proofs. FIX — one mechanism rather than three patches. Audit.lean now emits a canonical AUDIT-MANIFEST block and check.sh binds to its SHA-256. The block covers the POLICY constants, every certificate's fully-elaborated statement, and every specification constant transitively reachable from those statements with its fully-elaborated BODY (41 constants; the closure is computed, so a new fold cannot appear without moving the digest; Prop-valued constants contribute their statement, by proof irrelevance). This also retires the 32-bit Expr.hash as the binding (NEW-5) — it survives only as a per-certificate diagnostic. Enumeration now covers EVERY declaration kind (a `def : False` passed before) in the eight certificate modules AND in Audit.lean itself — the auditor is no longer exempt (round-5 R1). A bare `axiom` in audited scope is now an error. Phase 0 purges stale .olean (the verdict must depend on committed bytes, not .gitignored build state — NEW-4), forbids any .lean outside gen/ and Proofs/, and sha256-pins the four model files AND lean-guard. lean-guard is KEPT rather than removed (the reviewer's portability advice is declined by operator decision): it is the memory cap and machine-wide lock that protect the build machine after a 12.2GB OOM took the host down. That trade-off is documented. check.sh's "Certificates proven:" line now comes from the audited manifest; the hand-kept CERTS array — the one authoritative claim string nothing bound — is deleted. check-selftest.sh: 14 attacks, all rejected, plus a check that the hashed block literally carries the twelve fold bodies. Attacks 9-14 are the reviewers' and an independent drill's own exploits, turned into regression tests. DOCS. TRUSTED-BASE gains item 11 (the REAL trusted computing base — lean-guard pinned; check.sh, the toolchain env, $AENEAS_HOME, python3 and Lean still trusted) and item 12 (the apex does not compose the ten). README: the audit description rewritten; the XMSS sibling-order claim downgraded from "pins" to "makes visible", with a new blanket non-claim covering all ten loop certificates; the de-plumbing file claim corrected (round 1 touched only verify_mono.rs, round 2 only helpers.rs — which is ON the deployed verify AND sign paths, now disclosed; wots.rs was never patched). RECORDED-RUN: three lines that stood inside a fence were a hand-written summary, not console output — fabricated evidence in the file whose purpose is machine evidence. They are removed and the fabrication is named in place, together with the correction that the "INDEPENDENT RUN" block predates this gate. New rule: nothing goes in a fence unless captured with tee/cat, and every block states its date, pin, and who ran it. The transcripts added here follow it. Also disclosed rather than buried: three bugs in my own test harness this round (an olean-purge build-order break, an attack rejected by the wrong rule, and a coverage assertion looking on the wrong line) — each would have let an attack pass or fail for an unrelated reason. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-07-27 20:57:46 +00:00
./check.sh > /tmp/sf1.out 2>&1 && fail "ATTACK 1 SUCCEEDED (dead file stayed green)" /tmp/sf1.out
grep -q "DEAD FILE" /tmp/sf1.out || fail "ATTACK 1: failed, not via the dead-file gate" /tmp/sf1.out
rm -f Proofs/Stray.lean
review round 4: bind the cert set, statements, and model bytes (F1/F2/F3) The third reviewer demonstrated that the round-2 in-Lean exact-cone audit, though sound for LISTED certs, left three fail-opens OUTSIDE the cone check — and made check.sh print ALL GREEN over a repo proving False. All closed; no theorem, proof, or fold changed (the 11 cones are unchanged). F1 — the audited SET was unbound. Audit.lean now (a) enumerates EVERY theorem defined in the eight certificate modules and requires each cone ⊆ boundary, so an un-manifested `theorem _ : False := cheat _` fails regardless of naming (this is the exact exploit the reviewer used); and (b) prints a MANIFEST fingerprint over the whole committed manifest, which check.sh binds to — so deleting/swapping a cert row fails outside Lean too. F2 — only cones were bound, not statements. Each cert now also carries the structural fingerprint (Expr.hash) of its elaborated type; a statement gutted to a tautology of the same cone changes the fingerprint and fails. F3 — the gen/ model bytes were unbound. New check.sh Phase 0 sha256-pins all four gen/SlhVerify/*.lean (incl. the two hand-maintained *External files, now hashed in PROVENANCE.json) BEFORE compiling; a hand-edited model fails first. F4/F5 — docs. README cone diagram now roots honestly at slh_verify_internal and states the pure/prehash domain-separator byte, the ctx>255 check, M' assembly, and deserialization are ABOVE the root and uncovered (new TRUSTED-BASE item 10). The false "rules out a wrong ADRS field" claim is corrected in README + ChainSpec (a transliteration makes the field visible, not excluded). check-selftest.sh: eight attacks, all rejected (dead file; extra axiom; dropped oracle; vanished cert; un-manifested False theorem; gutted statement; hand-edited model; deleted manifest row). Full transcript + green check.sh in verification/RECORDED-RUN.md. Standing limit unchanged and disclosed: an audit cannot defend against an author who edits the manifest AND check.sh AND the proofs together; the consumer defense is the pinned commit reviewed at the pin. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-07-27 17:47:39 +00:00
echo "✓ attack 1 rejected (dead-file gate)"
post-flip drill over the chain certificate: HELD; audit gates now self-tested The window under audit claimed the campaign's first certificate, so this drill was maximally adversarial. Everything of substance HELD: - three-way model fidelity EXACT: extracted chain_free_loop.body == chainFoldN step == the Rust origin, operation-for-operation including address threading - button green fresh; axiom sweep over ALL 8 declarations minimal (pure lemmas = kernel-3; oracle-touching = kernel-3 + oracle.f only) - non-vacuity PROVEN: the concrete 1-step consequence (one address-set + one hash call) derives from the certificate by rfl - commit body of cfd50bb intact (the one flagged fragment was a bad drill grep pattern, not an artifact); worktree clean; heads synced NEW, from the drill (R3-5 tradition): verification/check-selftest.sh - permanent adversarial self-test of the check.sh gates. Attack 1 (dead Proofs file) and attack 2 (certificate with a smuggled axiom) must both make check.sh fail; both verified rejected, selftest green, self-cleaning. An audit that cannot fail is theater; this one demonstrably can. Two notes for the record: (a) bind_congr is the generic Bind-class congruence from core/Mathlib, not Aeneas.Std.Primitives (memory corrected); (b) the certificate covers chain_free_loop - the thin chain_free wrapper (bound computation + massert + clone) gets its trivial composition lemma in the wots layer, where it is consumed. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-23 12:34:42 +00:00
review round 5: bind the policy, the specification bodies, and the harness The third reviewer demonstrated that the round-4 gate was closed at the EXPLOITS, not the MECHANISMS: it bound the manifest rows while the things he moved sat outside the binding. Three fail-opens, each executed end-to-end with the button printing ALL GREEN. No theorem, proof, fold, or model body changed. NEW-1 — the policy constant was unbound. `manifestFingerprint` covered `manifest` but never `allowedBoundary`, the sole predicate the enumeration tests against; adding one name re-opened the False-proof with the committed fingerprint BYTE-IDENTICAL. NEW-2 — the specification bodies were unbound. The statement fingerprint pinned each certificate's TYPE, which names its reference fold; redefining that fold to *be* the extracted loop left cone and type-hash identical while the certificate degenerated to `loop = loop`. 100% of the fidelity content lives in those defs. NEW-3 — the harness was unbound. Stubbing verification/lean-guard alone, without touching check.sh or the proofs, gave ALL GREEN in 3.6s over destroyed proofs. FIX — one mechanism rather than three patches. Audit.lean now emits a canonical AUDIT-MANIFEST block and check.sh binds to its SHA-256. The block covers the POLICY constants, every certificate's fully-elaborated statement, and every specification constant transitively reachable from those statements with its fully-elaborated BODY (41 constants; the closure is computed, so a new fold cannot appear without moving the digest; Prop-valued constants contribute their statement, by proof irrelevance). This also retires the 32-bit Expr.hash as the binding (NEW-5) — it survives only as a per-certificate diagnostic. Enumeration now covers EVERY declaration kind (a `def : False` passed before) in the eight certificate modules AND in Audit.lean itself — the auditor is no longer exempt (round-5 R1). A bare `axiom` in audited scope is now an error. Phase 0 purges stale .olean (the verdict must depend on committed bytes, not .gitignored build state — NEW-4), forbids any .lean outside gen/ and Proofs/, and sha256-pins the four model files AND lean-guard. lean-guard is KEPT rather than removed (the reviewer's portability advice is declined by operator decision): it is the memory cap and machine-wide lock that protect the build machine after a 12.2GB OOM took the host down. That trade-off is documented. check.sh's "Certificates proven:" line now comes from the audited manifest; the hand-kept CERTS array — the one authoritative claim string nothing bound — is deleted. check-selftest.sh: 14 attacks, all rejected, plus a check that the hashed block literally carries the twelve fold bodies. Attacks 9-14 are the reviewers' and an independent drill's own exploits, turned into regression tests. DOCS. TRUSTED-BASE gains item 11 (the REAL trusted computing base — lean-guard pinned; check.sh, the toolchain env, $AENEAS_HOME, python3 and Lean still trusted) and item 12 (the apex does not compose the ten). README: the audit description rewritten; the XMSS sibling-order claim downgraded from "pins" to "makes visible", with a new blanket non-claim covering all ten loop certificates; the de-plumbing file claim corrected (round 1 touched only verify_mono.rs, round 2 only helpers.rs — which is ON the deployed verify AND sign paths, now disclosed; wots.rs was never patched). RECORDED-RUN: three lines that stood inside a fence were a hand-written summary, not console output — fabricated evidence in the file whose purpose is machine evidence. They are removed and the fabrication is named in place, together with the correction that the "INDEPENDENT RUN" block predates this gate. New rule: nothing goes in a fence unless captured with tee/cat, and every block states its date, pin, and who ran it. The transcripts added here follow it. Also disclosed rather than buried: three bugs in my own test harness this round (an olean-purge build-order break, an attack rejected by the wrong rule, and a coverage assertion looking on the wrong line) — each would have let an attack pass or fail for an unrelated reason. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-07-27 20:57:46 +00:00
# ── 2: smuggled disallowed axiom in a real cone ─────────────────────────────
review round 6: pin the auditor, purge every olean, pin gen/ as a set Round 6 confirmed the digest redesign closed NEW-1/NEW-2/NEW-5 at the mechanism ("the first time in three rounds I have not been able to gut a certificate"), then demonstrated two more ways to reach ALL GREEN with the committed digest BYTE-IDENTICAL over a repository proving False. Both are fixed. NEW-7 — the digest bound the audit's DATA, never its LOGIC. Flipping the two fail-closed guards in Proofs/Audit.lean to `unless true` disabled every in-Lean check; the block's inputs genuinely had not changed, so the digest still matched. Total attacker diff: 2 files, 6 insertions. Worse, TRUSTED-BASE item 11 listed the trusted-unbound set and did NOT mention Audit.lean, so a reviewer using it as a map of what to read by hand would have skipped the file that computes the number it is judged by. FIX: Proofs/Audit.lean is now sha256-pinned in harness_integrity_sha256, symmetric with lean-guard, and item 11 says so — including the honest residue: an author who edits the logic AND rotates its pin is caught only by reading the diff at the pin. NEW-8 — Phase 0's purge covered gen/ and Proofs/ while the stray check greped only *.lean, so an ORPHAN verification/Evil.olean whose source had been DELETED fell between them, satisfied an import, and was invisible to git status (*.olean is gitignored). FIX: purge every .olean under verification/, and forbid stray .lean AND .olean. NEW-9 (partial) — gen/ was pinned by four NAMES, not as a SET, so a new file there was neither hashed nor forbidden while LEAN_PATH contains $PWD/gen. FIX: Phase 0 asserts the gen/*.lean file set equals the pin map exactly. This found a real gap on its first run: Aeneas emits *_Template.lean scaffolding into gen/ on every extraction — untracked byproducts (a fresh clone has only the four pinned files) that nothing imports but that sat on LEAN_PATH unpinned. They are now purged as byproducts before the set assertion. Also, from the reviewer's §3 suggestion: the canonical block is now COMMITTED as verification/AUDIT-MANIFEST.txt, so a digest mismatch prints a real diff instead of writing an observed file with nothing to compare against; check.sh also fails if the committed copy drifts from what Lean emits. check-selftest.sh: 16 attacks, all rejected, plus the coverage check. Attacks 16 and 17 are the reviewer's two demonstrations. Attacks that mutate the audit's DATA now re-pin Audit.lean first, so they still test the digest/enumeration rather than being stopped by the byte pin; attack 17 deliberately does not re-pin, because the pin is what it tests. Housekeeping: PROVENANCE.json trailing newline restored (NEW-12). Disclosed rather than buried: two more of my own assertion bugs this round — attack 16 asserted the hygiene message when the correct rejection is the purge plus a failed import, and the earlier gen/ set check surfaced the template files only because it was written strictly. Both are the wrong-diagnostic class. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-07-28 07:22:12 +00:00
save check.sh; save Proofs/Audit.lean; save PROVENANCE.json
review round 5: bind the policy, the specification bodies, and the harness The third reviewer demonstrated that the round-4 gate was closed at the EXPLOITS, not the MECHANISMS: it bound the manifest rows while the things he moved sat outside the binding. Three fail-opens, each executed end-to-end with the button printing ALL GREEN. No theorem, proof, fold, or model body changed. NEW-1 — the policy constant was unbound. `manifestFingerprint` covered `manifest` but never `allowedBoundary`, the sole predicate the enumeration tests against; adding one name re-opened the False-proof with the committed fingerprint BYTE-IDENTICAL. NEW-2 — the specification bodies were unbound. The statement fingerprint pinned each certificate's TYPE, which names its reference fold; redefining that fold to *be* the extracted loop left cone and type-hash identical while the certificate degenerated to `loop = loop`. 100% of the fidelity content lives in those defs. NEW-3 — the harness was unbound. Stubbing verification/lean-guard alone, without touching check.sh or the proofs, gave ALL GREEN in 3.6s over destroyed proofs. FIX — one mechanism rather than three patches. Audit.lean now emits a canonical AUDIT-MANIFEST block and check.sh binds to its SHA-256. The block covers the POLICY constants, every certificate's fully-elaborated statement, and every specification constant transitively reachable from those statements with its fully-elaborated BODY (41 constants; the closure is computed, so a new fold cannot appear without moving the digest; Prop-valued constants contribute their statement, by proof irrelevance). This also retires the 32-bit Expr.hash as the binding (NEW-5) — it survives only as a per-certificate diagnostic. Enumeration now covers EVERY declaration kind (a `def : False` passed before) in the eight certificate modules AND in Audit.lean itself — the auditor is no longer exempt (round-5 R1). A bare `axiom` in audited scope is now an error. Phase 0 purges stale .olean (the verdict must depend on committed bytes, not .gitignored build state — NEW-4), forbids any .lean outside gen/ and Proofs/, and sha256-pins the four model files AND lean-guard. lean-guard is KEPT rather than removed (the reviewer's portability advice is declined by operator decision): it is the memory cap and machine-wide lock that protect the build machine after a 12.2GB OOM took the host down. That trade-off is documented. check.sh's "Certificates proven:" line now comes from the audited manifest; the hand-kept CERTS array — the one authoritative claim string nothing bound — is deleted. check-selftest.sh: 14 attacks, all rejected, plus a check that the hashed block literally carries the twelve fold bodies. Attacks 9-14 are the reviewers' and an independent drill's own exploits, turned into regression tests. DOCS. TRUSTED-BASE gains item 11 (the REAL trusted computing base — lean-guard pinned; check.sh, the toolchain env, $AENEAS_HOME, python3 and Lean still trusted) and item 12 (the apex does not compose the ten). README: the audit description rewritten; the XMSS sibling-order claim downgraded from "pins" to "makes visible", with a new blanket non-claim covering all ten loop certificates; the de-plumbing file claim corrected (round 1 touched only verify_mono.rs, round 2 only helpers.rs — which is ON the deployed verify AND sign paths, now disclosed; wots.rs was never patched). RECORDED-RUN: three lines that stood inside a fence were a hand-written summary, not console output — fabricated evidence in the file whose purpose is machine evidence. They are removed and the fabrication is named in place, together with the correction that the "INDEPENDENT RUN" block predates this gate. New rule: nothing goes in a fence unless captured with tee/cat, and every block states its date, pin, and who ran it. The transcripts added here follow it. Also disclosed rather than buried: three bugs in my own test harness this round (an olean-purge build-order break, an attack rejected by the wrong rule, and a coverage assertion looking on the wrong line) — each would have let an attack pass or fail for an unrelated reason. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-07-27 20:57:46 +00:00
# NB: no imports — Phase 0 now purges every .olean, so a module injected at the
# head of the build order cannot import one that has not been compiled yet.
post-flip drill over the chain certificate: HELD; audit gates now self-tested The window under audit claimed the campaign's first certificate, so this drill was maximally adversarial. Everything of substance HELD: - three-way model fidelity EXACT: extracted chain_free_loop.body == chainFoldN step == the Rust origin, operation-for-operation including address threading - button green fresh; axiom sweep over ALL 8 declarations minimal (pure lemmas = kernel-3; oracle-touching = kernel-3 + oracle.f only) - non-vacuity PROVEN: the concrete 1-step consequence (one address-set + one hash call) derives from the certificate by rfl - commit body of cfd50bb intact (the one flagged fragment was a bad drill grep pattern, not an artifact); worktree clean; heads synced NEW, from the drill (R3-5 tradition): verification/check-selftest.sh - permanent adversarial self-test of the check.sh gates. Attack 1 (dead Proofs file) and attack 2 (certificate with a smuggled axiom) must both make check.sh fail; both verified rejected, selftest green, self-cleaning. An audit that cannot fail is theater; this one demonstrably can. Two notes for the record: (a) bind_congr is the generic Bind-class congruence from core/Mathlib, not Aeneas.Std.Primitives (memory corrected); (b) the certificate covers chain_free_loop - the thin chain_free wrapper (bound computation + massert + clone) gets its trivial composition lemma in the wots layer, where it is consumed. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-23 12:34:42 +00:00
cat > Proofs/EvilSpec.lean <<'EOF'
axiom evil_ax : True
theorem evil_thm : True := evil_ax
EOF
python3 - <<'PY'
s = open("check.sh").read()
review round 5: bind the policy, the specification bodies, and the harness The third reviewer demonstrated that the round-4 gate was closed at the EXPLOITS, not the MECHANISMS: it bound the manifest rows while the things he moved sat outside the binding. Three fail-opens, each executed end-to-end with the button printing ALL GREEN. No theorem, proof, fold, or model body changed. NEW-1 — the policy constant was unbound. `manifestFingerprint` covered `manifest` but never `allowedBoundary`, the sole predicate the enumeration tests against; adding one name re-opened the False-proof with the committed fingerprint BYTE-IDENTICAL. NEW-2 — the specification bodies were unbound. The statement fingerprint pinned each certificate's TYPE, which names its reference fold; redefining that fold to *be* the extracted loop left cone and type-hash identical while the certificate degenerated to `loop = loop`. 100% of the fidelity content lives in those defs. NEW-3 — the harness was unbound. Stubbing verification/lean-guard alone, without touching check.sh or the proofs, gave ALL GREEN in 3.6s over destroyed proofs. FIX — one mechanism rather than three patches. Audit.lean now emits a canonical AUDIT-MANIFEST block and check.sh binds to its SHA-256. The block covers the POLICY constants, every certificate's fully-elaborated statement, and every specification constant transitively reachable from those statements with its fully-elaborated BODY (41 constants; the closure is computed, so a new fold cannot appear without moving the digest; Prop-valued constants contribute their statement, by proof irrelevance). This also retires the 32-bit Expr.hash as the binding (NEW-5) — it survives only as a per-certificate diagnostic. Enumeration now covers EVERY declaration kind (a `def : False` passed before) in the eight certificate modules AND in Audit.lean itself — the auditor is no longer exempt (round-5 R1). A bare `axiom` in audited scope is now an error. Phase 0 purges stale .olean (the verdict must depend on committed bytes, not .gitignored build state — NEW-4), forbids any .lean outside gen/ and Proofs/, and sha256-pins the four model files AND lean-guard. lean-guard is KEPT rather than removed (the reviewer's portability advice is declined by operator decision): it is the memory cap and machine-wide lock that protect the build machine after a 12.2GB OOM took the host down. That trade-off is documented. check.sh's "Certificates proven:" line now comes from the audited manifest; the hand-kept CERTS array — the one authoritative claim string nothing bound — is deleted. check-selftest.sh: 14 attacks, all rejected, plus a check that the hashed block literally carries the twelve fold bodies. Attacks 9-14 are the reviewers' and an independent drill's own exploits, turned into regression tests. DOCS. TRUSTED-BASE gains item 11 (the REAL trusted computing base — lean-guard pinned; check.sh, the toolchain env, $AENEAS_HOME, python3 and Lean still trusted) and item 12 (the apex does not compose the ten). README: the audit description rewritten; the XMSS sibling-order claim downgraded from "pins" to "makes visible", with a new blanket non-claim covering all ten loop certificates; the de-plumbing file claim corrected (round 1 touched only verify_mono.rs, round 2 only helpers.rs — which is ON the deployed verify AND sign paths, now disclosed; wots.rs was never patched). RECORDED-RUN: three lines that stood inside a fence were a hand-written summary, not console output — fabricated evidence in the file whose purpose is machine evidence. They are removed and the fabrication is named in place, together with the correction that the "INDEPENDENT RUN" block predates this gate. New rule: nothing goes in a fence unless captured with tee/cat, and every block states its date, pin, and who ran it. The transcripts added here follow it. Also disclosed rather than buried: three bugs in my own test harness this round (an olean-purge build-order break, an attack rejected by the wrong rule, and a coverage assertion looking on the wrong line) — each would have let an attack pass or fail for an unrelated reason. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-07-27 20:57:46 +00:00
assert 'PROOFS=(\n' in s, "check.sh PROOFS shape changed"
review round 4: bind the cert set, statements, and model bytes (F1/F2/F3) The third reviewer demonstrated that the round-2 in-Lean exact-cone audit, though sound for LISTED certs, left three fail-opens OUTSIDE the cone check — and made check.sh print ALL GREEN over a repo proving False. All closed; no theorem, proof, or fold changed (the 11 cones are unchanged). F1 — the audited SET was unbound. Audit.lean now (a) enumerates EVERY theorem defined in the eight certificate modules and requires each cone ⊆ boundary, so an un-manifested `theorem _ : False := cheat _` fails regardless of naming (this is the exact exploit the reviewer used); and (b) prints a MANIFEST fingerprint over the whole committed manifest, which check.sh binds to — so deleting/swapping a cert row fails outside Lean too. F2 — only cones were bound, not statements. Each cert now also carries the structural fingerprint (Expr.hash) of its elaborated type; a statement gutted to a tautology of the same cone changes the fingerprint and fails. F3 — the gen/ model bytes were unbound. New check.sh Phase 0 sha256-pins all four gen/SlhVerify/*.lean (incl. the two hand-maintained *External files, now hashed in PROVENANCE.json) BEFORE compiling; a hand-edited model fails first. F4/F5 — docs. README cone diagram now roots honestly at slh_verify_internal and states the pure/prehash domain-separator byte, the ctx>255 check, M' assembly, and deserialization are ABOVE the root and uncovered (new TRUSTED-BASE item 10). The false "rules out a wrong ADRS field" claim is corrected in README + ChainSpec (a transliteration makes the field visible, not excluded). check-selftest.sh: eight attacks, all rejected (dead file; extra axiom; dropped oracle; vanished cert; un-manifested False theorem; gutted statement; hand-edited model; deleted manifest row). Full transcript + green check.sh in verification/RECORDED-RUN.md. Standing limit unchanged and disclosed: an audit cannot defend against an author who edits the manifest AND check.sh AND the proofs together; the consumer defense is the pinned commit reviewed at the pin. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-07-27 17:47:39 +00:00
open("check.sh","w").write(s.replace('PROOFS=(\n', 'PROOFS=(\n "EvilSpec"\n', 1))
review round 2: in-Lean exact-cone audit + reproducibility + doc honesty Addresses the round-2 reviewer punch-list. No theorem statement, proof term, or fold definition changed; the eleven cones are unchanged (independent collectAxioms dump in verification/RECORDED-RUN.md). AUDIT GATE (both reviewers, the critical one) - Retire the bash #print-axioms text parser (fail-open on empty/truncated reports, and only a SUBSET check). Replace with verification/Proofs/Audit.lean: reads each certificate's cone from the kernel via collectAxioms and asserts EXACT set equality against its expected boundary. Extra axiom, dropped oracle, renamed/deleted cert, or an axiom/opaque sham each throw -> non-zero Lean exit. No text to misparse; nothing fails open. check.sh Phase 3 now just compiles it (and still requires the explicit PASSED line). - check-selftest.sh rewritten to attack the new gate: dead-file, smuggled extra axiom (named), dropped-oracle (subset would pass, exact must not), and a vanished certificate (the collectAxioms-returns-[] trap). All four rejected. REPRODUCIBILITY (GPT B1.4 / B1.5) - extract.sh refuses a wrong-commit or dirty source tree (fail-closed), takes an optional source-path arg, and pins the source commit. - verification/PROVENANCE.json: single machine-readable pin set (source + charon + aeneas commits/channel + lean + ocaml) with generated-file sha256. - Re-running extract.sh reproduces gen/SlhVerify/{Types,Funs}.lean byte-identically (companion fips205-source commit adds Cargo.lock + rust-toolchain.toml; verified not to perturb the model). DOC HONESTY (both reviewers) - README: fix the self-contradiction (apex "not yet proven" trailer vs the proven apex), the false "oracles kept OUTSIDE every cone" (they are INSIDE, by design), "deployed monomorphic path" and "semantics-identical for every parameter set" overclaims, "only two lines changed", stale snapshot head; retitle the stale future-tense "what will be claimed" section. - TRUSTED-BASE: drop "nothing proven yet"; add base_2b-inner and deployment- bridge non-claims explicitly; current pin. - ChainSpec header: "deployed monomorphic path" -> private verify_mono facade (comment only). Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-07-24 17:13:55 +00:00
a = open("Proofs/Audit.lean").read()
review round 5: bind the policy, the specification bodies, and the harness The third reviewer demonstrated that the round-4 gate was closed at the EXPLOITS, not the MECHANISMS: it bound the manifest rows while the things he moved sat outside the binding. Three fail-opens, each executed end-to-end with the button printing ALL GREEN. No theorem, proof, fold, or model body changed. NEW-1 — the policy constant was unbound. `manifestFingerprint` covered `manifest` but never `allowedBoundary`, the sole predicate the enumeration tests against; adding one name re-opened the False-proof with the committed fingerprint BYTE-IDENTICAL. NEW-2 — the specification bodies were unbound. The statement fingerprint pinned each certificate's TYPE, which names its reference fold; redefining that fold to *be* the extracted loop left cone and type-hash identical while the certificate degenerated to `loop = loop`. 100% of the fidelity content lives in those defs. NEW-3 — the harness was unbound. Stubbing verification/lean-guard alone, without touching check.sh or the proofs, gave ALL GREEN in 3.6s over destroyed proofs. FIX — one mechanism rather than three patches. Audit.lean now emits a canonical AUDIT-MANIFEST block and check.sh binds to its SHA-256. The block covers the POLICY constants, every certificate's fully-elaborated statement, and every specification constant transitively reachable from those statements with its fully-elaborated BODY (41 constants; the closure is computed, so a new fold cannot appear without moving the digest; Prop-valued constants contribute their statement, by proof irrelevance). This also retires the 32-bit Expr.hash as the binding (NEW-5) — it survives only as a per-certificate diagnostic. Enumeration now covers EVERY declaration kind (a `def : False` passed before) in the eight certificate modules AND in Audit.lean itself — the auditor is no longer exempt (round-5 R1). A bare `axiom` in audited scope is now an error. Phase 0 purges stale .olean (the verdict must depend on committed bytes, not .gitignored build state — NEW-4), forbids any .lean outside gen/ and Proofs/, and sha256-pins the four model files AND lean-guard. lean-guard is KEPT rather than removed (the reviewer's portability advice is declined by operator decision): it is the memory cap and machine-wide lock that protect the build machine after a 12.2GB OOM took the host down. That trade-off is documented. check.sh's "Certificates proven:" line now comes from the audited manifest; the hand-kept CERTS array — the one authoritative claim string nothing bound — is deleted. check-selftest.sh: 14 attacks, all rejected, plus a check that the hashed block literally carries the twelve fold bodies. Attacks 9-14 are the reviewers' and an independent drill's own exploits, turned into regression tests. DOCS. TRUSTED-BASE gains item 11 (the REAL trusted computing base — lean-guard pinned; check.sh, the toolchain env, $AENEAS_HOME, python3 and Lean still trusted) and item 12 (the apex does not compose the ten). README: the audit description rewritten; the XMSS sibling-order claim downgraded from "pins" to "makes visible", with a new blanket non-claim covering all ten loop certificates; the de-plumbing file claim corrected (round 1 touched only verify_mono.rs, round 2 only helpers.rs — which is ON the deployed verify AND sign paths, now disclosed; wots.rs was never patched). RECORDED-RUN: three lines that stood inside a fence were a hand-written summary, not console output — fabricated evidence in the file whose purpose is machine evidence. They are removed and the fabrication is named in place, together with the correction that the "INDEPENDENT RUN" block predates this gate. New rule: nothing goes in a fence unless captured with tee/cat, and every block states its date, pin, and who ran it. The transcripts added here follow it. Also disclosed rather than buried: three bugs in my own test harness this round (an olean-purge build-order break, an attack rejected by the wrong rule, and a coverage assertion looking on the wrong line) — each would have let an attack pass or fail for an unrelated reason. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-07-27 20:57:46 +00:00
assert 'import Proofs.ApexSpec' in a and ' [ (`fips205.chain_free_loop_eq' in a, "Audit.lean shape changed"
review round 2: in-Lean exact-cone audit + reproducibility + doc honesty Addresses the round-2 reviewer punch-list. No theorem statement, proof term, or fold definition changed; the eleven cones are unchanged (independent collectAxioms dump in verification/RECORDED-RUN.md). AUDIT GATE (both reviewers, the critical one) - Retire the bash #print-axioms text parser (fail-open on empty/truncated reports, and only a SUBSET check). Replace with verification/Proofs/Audit.lean: reads each certificate's cone from the kernel via collectAxioms and asserts EXACT set equality against its expected boundary. Extra axiom, dropped oracle, renamed/deleted cert, or an axiom/opaque sham each throw -> non-zero Lean exit. No text to misparse; nothing fails open. check.sh Phase 3 now just compiles it (and still requires the explicit PASSED line). - check-selftest.sh rewritten to attack the new gate: dead-file, smuggled extra axiom (named), dropped-oracle (subset would pass, exact must not), and a vanished certificate (the collectAxioms-returns-[] trap). All four rejected. REPRODUCIBILITY (GPT B1.4 / B1.5) - extract.sh refuses a wrong-commit or dirty source tree (fail-closed), takes an optional source-path arg, and pins the source commit. - verification/PROVENANCE.json: single machine-readable pin set (source + charon + aeneas commits/channel + lean + ocaml) with generated-file sha256. - Re-running extract.sh reproduces gen/SlhVerify/{Types,Funs}.lean byte-identically (companion fips205-source commit adds Cargo.lock + rust-toolchain.toml; verified not to perturb the model). DOC HONESTY (both reviewers) - README: fix the self-contradiction (apex "not yet proven" trailer vs the proven apex), the false "oracles kept OUTSIDE every cone" (they are INSIDE, by design), "deployed monomorphic path" and "semantics-identical for every parameter set" overclaims, "only two lines changed", stale snapshot head; retitle the stale future-tense "what will be claimed" section. - TRUSTED-BASE: drop "nothing proven yet"; add base_2b-inner and deployment- bridge non-claims explicitly; current pin. - ChainSpec header: "deployed monomorphic path" -> private verify_mono facade (comment only). Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-07-24 17:13:55 +00:00
a = a.replace('import Proofs.ApexSpec', 'import Proofs.ApexSpec\nimport Proofs.EvilSpec', 1)
review round 5: bind the policy, the specification bodies, and the harness The third reviewer demonstrated that the round-4 gate was closed at the EXPLOITS, not the MECHANISMS: it bound the manifest rows while the things he moved sat outside the binding. Three fail-opens, each executed end-to-end with the button printing ALL GREEN. No theorem, proof, fold, or model body changed. NEW-1 — the policy constant was unbound. `manifestFingerprint` covered `manifest` but never `allowedBoundary`, the sole predicate the enumeration tests against; adding one name re-opened the False-proof with the committed fingerprint BYTE-IDENTICAL. NEW-2 — the specification bodies were unbound. The statement fingerprint pinned each certificate's TYPE, which names its reference fold; redefining that fold to *be* the extracted loop left cone and type-hash identical while the certificate degenerated to `loop = loop`. 100% of the fidelity content lives in those defs. NEW-3 — the harness was unbound. Stubbing verification/lean-guard alone, without touching check.sh or the proofs, gave ALL GREEN in 3.6s over destroyed proofs. FIX — one mechanism rather than three patches. Audit.lean now emits a canonical AUDIT-MANIFEST block and check.sh binds to its SHA-256. The block covers the POLICY constants, every certificate's fully-elaborated statement, and every specification constant transitively reachable from those statements with its fully-elaborated BODY (41 constants; the closure is computed, so a new fold cannot appear without moving the digest; Prop-valued constants contribute their statement, by proof irrelevance). This also retires the 32-bit Expr.hash as the binding (NEW-5) — it survives only as a per-certificate diagnostic. Enumeration now covers EVERY declaration kind (a `def : False` passed before) in the eight certificate modules AND in Audit.lean itself — the auditor is no longer exempt (round-5 R1). A bare `axiom` in audited scope is now an error. Phase 0 purges stale .olean (the verdict must depend on committed bytes, not .gitignored build state — NEW-4), forbids any .lean outside gen/ and Proofs/, and sha256-pins the four model files AND lean-guard. lean-guard is KEPT rather than removed (the reviewer's portability advice is declined by operator decision): it is the memory cap and machine-wide lock that protect the build machine after a 12.2GB OOM took the host down. That trade-off is documented. check.sh's "Certificates proven:" line now comes from the audited manifest; the hand-kept CERTS array — the one authoritative claim string nothing bound — is deleted. check-selftest.sh: 14 attacks, all rejected, plus a check that the hashed block literally carries the twelve fold bodies. Attacks 9-14 are the reviewers' and an independent drill's own exploits, turned into regression tests. DOCS. TRUSTED-BASE gains item 11 (the REAL trusted computing base — lean-guard pinned; check.sh, the toolchain env, $AENEAS_HOME, python3 and Lean still trusted) and item 12 (the apex does not compose the ten). README: the audit description rewritten; the XMSS sibling-order claim downgraded from "pins" to "makes visible", with a new blanket non-claim covering all ten loop certificates; the de-plumbing file claim corrected (round 1 touched only verify_mono.rs, round 2 only helpers.rs — which is ON the deployed verify AND sign paths, now disclosed; wots.rs was never patched). RECORDED-RUN: three lines that stood inside a fence were a hand-written summary, not console output — fabricated evidence in the file whose purpose is machine evidence. They are removed and the fabrication is named in place, together with the correction that the "INDEPENDENT RUN" block predates this gate. New rule: nothing goes in a fence unless captured with tee/cat, and every block states its date, pin, and who ran it. The transcripts added here follow it. Also disclosed rather than buried: three bugs in my own test harness this round (an olean-purge build-order break, an attack rejected by the wrong rule, and a coverage assertion looking on the wrong line) — each would have let an attack pass or fail for an unrelated reason. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-07-27 20:57:46 +00:00
a = a.replace(' [ (`fips205.chain_free_loop_eq', ' [ (`evil_thm, kernel3, 0),\n (`fips205.chain_free_loop_eq', 1)
review round 2: in-Lean exact-cone audit + reproducibility + doc honesty Addresses the round-2 reviewer punch-list. No theorem statement, proof term, or fold definition changed; the eleven cones are unchanged (independent collectAxioms dump in verification/RECORDED-RUN.md). AUDIT GATE (both reviewers, the critical one) - Retire the bash #print-axioms text parser (fail-open on empty/truncated reports, and only a SUBSET check). Replace with verification/Proofs/Audit.lean: reads each certificate's cone from the kernel via collectAxioms and asserts EXACT set equality against its expected boundary. Extra axiom, dropped oracle, renamed/deleted cert, or an axiom/opaque sham each throw -> non-zero Lean exit. No text to misparse; nothing fails open. check.sh Phase 3 now just compiles it (and still requires the explicit PASSED line). - check-selftest.sh rewritten to attack the new gate: dead-file, smuggled extra axiom (named), dropped-oracle (subset would pass, exact must not), and a vanished certificate (the collectAxioms-returns-[] trap). All four rejected. REPRODUCIBILITY (GPT B1.4 / B1.5) - extract.sh refuses a wrong-commit or dirty source tree (fail-closed), takes an optional source-path arg, and pins the source commit. - verification/PROVENANCE.json: single machine-readable pin set (source + charon + aeneas commits/channel + lean + ocaml) with generated-file sha256. - Re-running extract.sh reproduces gen/SlhVerify/{Types,Funs}.lean byte-identically (companion fips205-source commit adds Cargo.lock + rust-toolchain.toml; verified not to perturb the model). DOC HONESTY (both reviewers) - README: fix the self-contradiction (apex "not yet proven" trailer vs the proven apex), the false "oracles kept OUTSIDE every cone" (they are INSIDE, by design), "deployed monomorphic path" and "semantics-identical for every parameter set" overclaims, "only two lines changed", stale snapshot head; retitle the stale future-tense "what will be claimed" section. - TRUSTED-BASE: drop "nothing proven yet"; add base_2b-inner and deployment- bridge non-claims explicitly; current pin. - ChainSpec header: "deployed monomorphic path" -> private verify_mono facade (comment only). Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-07-24 17:13:55 +00:00
open("Proofs/Audit.lean","w").write(a)
post-flip drill over the chain certificate: HELD; audit gates now self-tested The window under audit claimed the campaign's first certificate, so this drill was maximally adversarial. Everything of substance HELD: - three-way model fidelity EXACT: extracted chain_free_loop.body == chainFoldN step == the Rust origin, operation-for-operation including address threading - button green fresh; axiom sweep over ALL 8 declarations minimal (pure lemmas = kernel-3; oracle-touching = kernel-3 + oracle.f only) - non-vacuity PROVEN: the concrete 1-step consequence (one address-set + one hash call) derives from the certificate by rfl - commit body of cfd50bb intact (the one flagged fragment was a bad drill grep pattern, not an artifact); worktree clean; heads synced NEW, from the drill (R3-5 tradition): verification/check-selftest.sh - permanent adversarial self-test of the check.sh gates. Attack 1 (dead Proofs file) and attack 2 (certificate with a smuggled axiom) must both make check.sh fail; both verified rejected, selftest green, self-cleaning. An audit that cannot fail is theater; this one demonstrably can. Two notes for the record: (a) bind_congr is the generic Bind-class congruence from core/Mathlib, not Aeneas.Std.Primitives (memory corrected); (b) the certificate covers chain_free_loop - the thin chain_free wrapper (bound computation + massert + clone) gets its trivial composition lemma in the wots layer, where it is consumed. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-23 12:34:42 +00:00
PY
review round 6: pin the auditor, purge every olean, pin gen/ as a set Round 6 confirmed the digest redesign closed NEW-1/NEW-2/NEW-5 at the mechanism ("the first time in three rounds I have not been able to gut a certificate"), then demonstrated two more ways to reach ALL GREEN with the committed digest BYTE-IDENTICAL over a repository proving False. Both are fixed. NEW-7 — the digest bound the audit's DATA, never its LOGIC. Flipping the two fail-closed guards in Proofs/Audit.lean to `unless true` disabled every in-Lean check; the block's inputs genuinely had not changed, so the digest still matched. Total attacker diff: 2 files, 6 insertions. Worse, TRUSTED-BASE item 11 listed the trusted-unbound set and did NOT mention Audit.lean, so a reviewer using it as a map of what to read by hand would have skipped the file that computes the number it is judged by. FIX: Proofs/Audit.lean is now sha256-pinned in harness_integrity_sha256, symmetric with lean-guard, and item 11 says so — including the honest residue: an author who edits the logic AND rotates its pin is caught only by reading the diff at the pin. NEW-8 — Phase 0's purge covered gen/ and Proofs/ while the stray check greped only *.lean, so an ORPHAN verification/Evil.olean whose source had been DELETED fell between them, satisfied an import, and was invisible to git status (*.olean is gitignored). FIX: purge every .olean under verification/, and forbid stray .lean AND .olean. NEW-9 (partial) — gen/ was pinned by four NAMES, not as a SET, so a new file there was neither hashed nor forbidden while LEAN_PATH contains $PWD/gen. FIX: Phase 0 asserts the gen/*.lean file set equals the pin map exactly. This found a real gap on its first run: Aeneas emits *_Template.lean scaffolding into gen/ on every extraction — untracked byproducts (a fresh clone has only the four pinned files) that nothing imports but that sat on LEAN_PATH unpinned. They are now purged as byproducts before the set assertion. Also, from the reviewer's §3 suggestion: the canonical block is now COMMITTED as verification/AUDIT-MANIFEST.txt, so a digest mismatch prints a real diff instead of writing an observed file with nothing to compare against; check.sh also fails if the committed copy drifts from what Lean emits. check-selftest.sh: 16 attacks, all rejected, plus the coverage check. Attacks 16 and 17 are the reviewer's two demonstrations. Attacks that mutate the audit's DATA now re-pin Audit.lean first, so they still test the digest/enumeration rather than being stopped by the byte pin; attack 17 deliberately does not re-pin, because the pin is what it tests. Housekeeping: PROVENANCE.json trailing newline restored (NEW-12). Disclosed rather than buried: two more of my own assertion bugs this round — attack 16 asserted the hygiene message when the correct rejection is the purge plus a failed import, and the earlier gen/ set check surfaced the template files only because it was written strictly. Both are the wrong-diagnostic class. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-07-28 07:22:12 +00:00
repin_audit
review round 5: bind the policy, the specification bodies, and the harness The third reviewer demonstrated that the round-4 gate was closed at the EXPLOITS, not the MECHANISMS: it bound the manifest rows while the things he moved sat outside the binding. Three fail-opens, each executed end-to-end with the button printing ALL GREEN. No theorem, proof, fold, or model body changed. NEW-1 — the policy constant was unbound. `manifestFingerprint` covered `manifest` but never `allowedBoundary`, the sole predicate the enumeration tests against; adding one name re-opened the False-proof with the committed fingerprint BYTE-IDENTICAL. NEW-2 — the specification bodies were unbound. The statement fingerprint pinned each certificate's TYPE, which names its reference fold; redefining that fold to *be* the extracted loop left cone and type-hash identical while the certificate degenerated to `loop = loop`. 100% of the fidelity content lives in those defs. NEW-3 — the harness was unbound. Stubbing verification/lean-guard alone, without touching check.sh or the proofs, gave ALL GREEN in 3.6s over destroyed proofs. FIX — one mechanism rather than three patches. Audit.lean now emits a canonical AUDIT-MANIFEST block and check.sh binds to its SHA-256. The block covers the POLICY constants, every certificate's fully-elaborated statement, and every specification constant transitively reachable from those statements with its fully-elaborated BODY (41 constants; the closure is computed, so a new fold cannot appear without moving the digest; Prop-valued constants contribute their statement, by proof irrelevance). This also retires the 32-bit Expr.hash as the binding (NEW-5) — it survives only as a per-certificate diagnostic. Enumeration now covers EVERY declaration kind (a `def : False` passed before) in the eight certificate modules AND in Audit.lean itself — the auditor is no longer exempt (round-5 R1). A bare `axiom` in audited scope is now an error. Phase 0 purges stale .olean (the verdict must depend on committed bytes, not .gitignored build state — NEW-4), forbids any .lean outside gen/ and Proofs/, and sha256-pins the four model files AND lean-guard. lean-guard is KEPT rather than removed (the reviewer's portability advice is declined by operator decision): it is the memory cap and machine-wide lock that protect the build machine after a 12.2GB OOM took the host down. That trade-off is documented. check.sh's "Certificates proven:" line now comes from the audited manifest; the hand-kept CERTS array — the one authoritative claim string nothing bound — is deleted. check-selftest.sh: 14 attacks, all rejected, plus a check that the hashed block literally carries the twelve fold bodies. Attacks 9-14 are the reviewers' and an independent drill's own exploits, turned into regression tests. DOCS. TRUSTED-BASE gains item 11 (the REAL trusted computing base — lean-guard pinned; check.sh, the toolchain env, $AENEAS_HOME, python3 and Lean still trusted) and item 12 (the apex does not compose the ten). README: the audit description rewritten; the XMSS sibling-order claim downgraded from "pins" to "makes visible", with a new blanket non-claim covering all ten loop certificates; the de-plumbing file claim corrected (round 1 touched only verify_mono.rs, round 2 only helpers.rs — which is ON the deployed verify AND sign paths, now disclosed; wots.rs was never patched). RECORDED-RUN: three lines that stood inside a fence were a hand-written summary, not console output — fabricated evidence in the file whose purpose is machine evidence. They are removed and the fabrication is named in place, together with the correction that the "INDEPENDENT RUN" block predates this gate. New rule: nothing goes in a fence unless captured with tee/cat, and every block states its date, pin, and who ran it. The transcripts added here follow it. Also disclosed rather than buried: three bugs in my own test harness this round (an olean-purge build-order break, an attack rejected by the wrong rule, and a coverage assertion looking on the wrong line) — each would have let an attack pass or fail for an unrelated reason. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-07-27 20:57:46 +00:00
./check.sh > /tmp/sf2.out 2>&1 && fail "ATTACK 2 SUCCEEDED (smuggled axiom)" /tmp/sf2.out
grep -q "evil_ax" /tmp/sf2.out || fail "ATTACK 2: rejected but evil_ax not named" /tmp/sf2.out
restore; rm -f Proofs/EvilSpec.lean
review round 4: bind the cert set, statements, and model bytes (F1/F2/F3) The third reviewer demonstrated that the round-2 in-Lean exact-cone audit, though sound for LISTED certs, left three fail-opens OUTSIDE the cone check — and made check.sh print ALL GREEN over a repo proving False. All closed; no theorem, proof, or fold changed (the 11 cones are unchanged). F1 — the audited SET was unbound. Audit.lean now (a) enumerates EVERY theorem defined in the eight certificate modules and requires each cone ⊆ boundary, so an un-manifested `theorem _ : False := cheat _` fails regardless of naming (this is the exact exploit the reviewer used); and (b) prints a MANIFEST fingerprint over the whole committed manifest, which check.sh binds to — so deleting/swapping a cert row fails outside Lean too. F2 — only cones were bound, not statements. Each cert now also carries the structural fingerprint (Expr.hash) of its elaborated type; a statement gutted to a tautology of the same cone changes the fingerprint and fails. F3 — the gen/ model bytes were unbound. New check.sh Phase 0 sha256-pins all four gen/SlhVerify/*.lean (incl. the two hand-maintained *External files, now hashed in PROVENANCE.json) BEFORE compiling; a hand-edited model fails first. F4/F5 — docs. README cone diagram now roots honestly at slh_verify_internal and states the pure/prehash domain-separator byte, the ctx>255 check, M' assembly, and deserialization are ABOVE the root and uncovered (new TRUSTED-BASE item 10). The false "rules out a wrong ADRS field" claim is corrected in README + ChainSpec (a transliteration makes the field visible, not excluded). check-selftest.sh: eight attacks, all rejected (dead file; extra axiom; dropped oracle; vanished cert; un-manifested False theorem; gutted statement; hand-edited model; deleted manifest row). Full transcript + green check.sh in verification/RECORDED-RUN.md. Standing limit unchanged and disclosed: an audit cannot defend against an author who edits the manifest AND check.sh AND the proofs together; the consumer defense is the pinned commit reviewed at the pin. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-07-27 17:47:39 +00:00
echo "✓ attack 2 rejected (extra-axiom detection — evil_ax named)"
post-flip drill over the chain certificate: HELD; audit gates now self-tested The window under audit claimed the campaign's first certificate, so this drill was maximally adversarial. Everything of substance HELD: - three-way model fidelity EXACT: extracted chain_free_loop.body == chainFoldN step == the Rust origin, operation-for-operation including address threading - button green fresh; axiom sweep over ALL 8 declarations minimal (pure lemmas = kernel-3; oracle-touching = kernel-3 + oracle.f only) - non-vacuity PROVEN: the concrete 1-step consequence (one address-set + one hash call) derives from the certificate by rfl - commit body of cfd50bb intact (the one flagged fragment was a bad drill grep pattern, not an artifact); worktree clean; heads synced NEW, from the drill (R3-5 tradition): verification/check-selftest.sh - permanent adversarial self-test of the check.sh gates. Attack 1 (dead Proofs file) and attack 2 (certificate with a smuggled axiom) must both make check.sh fail; both verified rejected, selftest green, self-cleaning. An audit that cannot fail is theater; this one demonstrably can. Two notes for the record: (a) bind_congr is the generic Bind-class congruence from core/Mathlib, not Aeneas.Std.Primitives (memory corrected); (b) the certificate covers chain_free_loop - the thin chain_free wrapper (bound computation + massert + clone) gets its trivial composition lemma in the wots layer, where it is consumed. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-23 12:34:42 +00:00
review round 5: bind the policy, the specification bodies, and the harness The third reviewer demonstrated that the round-4 gate was closed at the EXPLOITS, not the MECHANISMS: it bound the manifest rows while the things he moved sat outside the binding. Three fail-opens, each executed end-to-end with the button printing ALL GREEN. No theorem, proof, fold, or model body changed. NEW-1 — the policy constant was unbound. `manifestFingerprint` covered `manifest` but never `allowedBoundary`, the sole predicate the enumeration tests against; adding one name re-opened the False-proof with the committed fingerprint BYTE-IDENTICAL. NEW-2 — the specification bodies were unbound. The statement fingerprint pinned each certificate's TYPE, which names its reference fold; redefining that fold to *be* the extracted loop left cone and type-hash identical while the certificate degenerated to `loop = loop`. 100% of the fidelity content lives in those defs. NEW-3 — the harness was unbound. Stubbing verification/lean-guard alone, without touching check.sh or the proofs, gave ALL GREEN in 3.6s over destroyed proofs. FIX — one mechanism rather than three patches. Audit.lean now emits a canonical AUDIT-MANIFEST block and check.sh binds to its SHA-256. The block covers the POLICY constants, every certificate's fully-elaborated statement, and every specification constant transitively reachable from those statements with its fully-elaborated BODY (41 constants; the closure is computed, so a new fold cannot appear without moving the digest; Prop-valued constants contribute their statement, by proof irrelevance). This also retires the 32-bit Expr.hash as the binding (NEW-5) — it survives only as a per-certificate diagnostic. Enumeration now covers EVERY declaration kind (a `def : False` passed before) in the eight certificate modules AND in Audit.lean itself — the auditor is no longer exempt (round-5 R1). A bare `axiom` in audited scope is now an error. Phase 0 purges stale .olean (the verdict must depend on committed bytes, not .gitignored build state — NEW-4), forbids any .lean outside gen/ and Proofs/, and sha256-pins the four model files AND lean-guard. lean-guard is KEPT rather than removed (the reviewer's portability advice is declined by operator decision): it is the memory cap and machine-wide lock that protect the build machine after a 12.2GB OOM took the host down. That trade-off is documented. check.sh's "Certificates proven:" line now comes from the audited manifest; the hand-kept CERTS array — the one authoritative claim string nothing bound — is deleted. check-selftest.sh: 14 attacks, all rejected, plus a check that the hashed block literally carries the twelve fold bodies. Attacks 9-14 are the reviewers' and an independent drill's own exploits, turned into regression tests. DOCS. TRUSTED-BASE gains item 11 (the REAL trusted computing base — lean-guard pinned; check.sh, the toolchain env, $AENEAS_HOME, python3 and Lean still trusted) and item 12 (the apex does not compose the ten). README: the audit description rewritten; the XMSS sibling-order claim downgraded from "pins" to "makes visible", with a new blanket non-claim covering all ten loop certificates; the de-plumbing file claim corrected (round 1 touched only verify_mono.rs, round 2 only helpers.rs — which is ON the deployed verify AND sign paths, now disclosed; wots.rs was never patched). RECORDED-RUN: three lines that stood inside a fence were a hand-written summary, not console output — fabricated evidence in the file whose purpose is machine evidence. They are removed and the fabrication is named in place, together with the correction that the "INDEPENDENT RUN" block predates this gate. New rule: nothing goes in a fence unless captured with tee/cat, and every block states its date, pin, and who ran it. The transcripts added here follow it. Also disclosed rather than buried: three bugs in my own test harness this round (an olean-purge build-order break, an attack rejected by the wrong rule, and a coverage assertion looking on the wrong line) — each would have let an attack pass or fail for an unrelated reason. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-07-27 20:57:46 +00:00
# ── 3: dropped oracle (a subset check would pass; exact must not) ────────────
review round 6: pin the auditor, purge every olean, pin gen/ as a set Round 6 confirmed the digest redesign closed NEW-1/NEW-2/NEW-5 at the mechanism ("the first time in three rounds I have not been able to gut a certificate"), then demonstrated two more ways to reach ALL GREEN with the committed digest BYTE-IDENTICAL over a repository proving False. Both are fixed. NEW-7 — the digest bound the audit's DATA, never its LOGIC. Flipping the two fail-closed guards in Proofs/Audit.lean to `unless true` disabled every in-Lean check; the block's inputs genuinely had not changed, so the digest still matched. Total attacker diff: 2 files, 6 insertions. Worse, TRUSTED-BASE item 11 listed the trusted-unbound set and did NOT mention Audit.lean, so a reviewer using it as a map of what to read by hand would have skipped the file that computes the number it is judged by. FIX: Proofs/Audit.lean is now sha256-pinned in harness_integrity_sha256, symmetric with lean-guard, and item 11 says so — including the honest residue: an author who edits the logic AND rotates its pin is caught only by reading the diff at the pin. NEW-8 — Phase 0's purge covered gen/ and Proofs/ while the stray check greped only *.lean, so an ORPHAN verification/Evil.olean whose source had been DELETED fell between them, satisfied an import, and was invisible to git status (*.olean is gitignored). FIX: purge every .olean under verification/, and forbid stray .lean AND .olean. NEW-9 (partial) — gen/ was pinned by four NAMES, not as a SET, so a new file there was neither hashed nor forbidden while LEAN_PATH contains $PWD/gen. FIX: Phase 0 asserts the gen/*.lean file set equals the pin map exactly. This found a real gap on its first run: Aeneas emits *_Template.lean scaffolding into gen/ on every extraction — untracked byproducts (a fresh clone has only the four pinned files) that nothing imports but that sat on LEAN_PATH unpinned. They are now purged as byproducts before the set assertion. Also, from the reviewer's §3 suggestion: the canonical block is now COMMITTED as verification/AUDIT-MANIFEST.txt, so a digest mismatch prints a real diff instead of writing an observed file with nothing to compare against; check.sh also fails if the committed copy drifts from what Lean emits. check-selftest.sh: 16 attacks, all rejected, plus the coverage check. Attacks 16 and 17 are the reviewer's two demonstrations. Attacks that mutate the audit's DATA now re-pin Audit.lean first, so they still test the digest/enumeration rather than being stopped by the byte pin; attack 17 deliberately does not re-pin, because the pin is what it tests. Housekeeping: PROVENANCE.json trailing newline restored (NEW-12). Disclosed rather than buried: two more of my own assertion bugs this round — attack 16 asserted the hygiene message when the correct rejection is the purge plus a failed import, and the earlier gen/ set check surfaced the template files only because it was written strictly. Both are the wrong-diagnostic class. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-07-28 07:22:12 +00:00
save Proofs/Audit.lean; save PROVENANCE.json
review round 1: fix the fail-open audit gate + remove the overclaimed framing External review (both standing reviewers, 2026-07-24) returned DO NOT ATTEST. The eleven Lean theorems compile with genuinely clean cones (both reviewers independently reconstructed them), but two real defects were found and are fixed here. FIX 1 — the axiom audit was FAIL-OPEN (the critical blocker). check.sh Phase 3 grepped a single physical line of each `#print axioms` report; Lean WRAPS long cones across lines, so for ht/fors_outer/APEX the audit checked only `[propext,` and silently ignored the continuation lines — a disallowed axiom on line 2+ passed (the GPT reviewer demonstrated `review_evil_ax` passing). Since check.sh is the sole source of the word "proven", this is unacceptable. - New parser: FLATTEN the whole report (join newlines) BEFORE parsing, then extract each certificate's complete bracketed cone with a literal-string (regex-safe) scan and subset-check every axiom. Missing/empty report => FAIL CLOSED. The audit now prints the count of axioms actually audited per cert (apex: 8, previously 1). - check-selftest.sh gains ATTACK 3: a smuggled axiom bundled with the apex so its cone WRAPS with the evil axiom on a continuation line — the exact exploit. Verified: all three attacks now rejected, attack 3 via the axiom gate naming the continuation-line axiom. (Also fixed attack 2's leftover EvilSpec.lean tripping attack 3's dead-file gate.) FIX 2 — remove the overclaimed framing (refuted by both reviewers). Corrected in README, the ApexSpec header + apex docstring, and (separately) the control MANIFEST: - "composes all ten loop-fidelity certificates" — FALSE. The apex proof is a STRUCTURAL FACTORIZATION; it references NONE of the ten (grep: 0) and would remain provable if one were deleted. They are independent local-fidelity lemmas, not links in the apex proof. - "every loop is individually fidelity-certified" — FALSE. base_2b's inner accumulation loop is threaded opaquely and uncertified — and it determines the FORS indices / WOTS digits, so a defect there could change the recomputed root while all eleven theorems still hold. - "the deployed verifier" — the proved subject is verify_mono, a private #![allow(dead_code)] monomorphic facade NOT called by the public API; the bridge to the deployed generic verifier is the finite differential test, not a machine-checked refinement. - "verify-path pyramid complete" — replaced with "intermediate verification layer"; the apex is an ACCEPTANCE CHARACTERIZATION, not closed-form FIPS-205 correctness. Also: FunsExternal header noted the Take axiom "remains" (stale — deleted in de-plumbing round 2); corrected. check.sh green over all eleven certificates under the fixed fail-closed parser (exit 0, 8 axioms audited for the apex). Nothing about the theorems changed — they were and are sound; only the audit tool and the claims about them are fixed. NOT DONE (remaining reviewer blockers, tracked): reproducible extract tuple (pin commits, de-hard-code extract.sh) + Cargo.lock / toolchain pin. Attestation remains gated behind review round 2 + the operator halt + the appeal. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-24 14:55:10 +00:00
python3 - <<'PY'
review round 2: in-Lean exact-cone audit + reproducibility + doc honesty Addresses the round-2 reviewer punch-list. No theorem statement, proof term, or fold definition changed; the eleven cones are unchanged (independent collectAxioms dump in verification/RECORDED-RUN.md). AUDIT GATE (both reviewers, the critical one) - Retire the bash #print-axioms text parser (fail-open on empty/truncated reports, and only a SUBSET check). Replace with verification/Proofs/Audit.lean: reads each certificate's cone from the kernel via collectAxioms and asserts EXACT set equality against its expected boundary. Extra axiom, dropped oracle, renamed/deleted cert, or an axiom/opaque sham each throw -> non-zero Lean exit. No text to misparse; nothing fails open. check.sh Phase 3 now just compiles it (and still requires the explicit PASSED line). - check-selftest.sh rewritten to attack the new gate: dead-file, smuggled extra axiom (named), dropped-oracle (subset would pass, exact must not), and a vanished certificate (the collectAxioms-returns-[] trap). All four rejected. REPRODUCIBILITY (GPT B1.4 / B1.5) - extract.sh refuses a wrong-commit or dirty source tree (fail-closed), takes an optional source-path arg, and pins the source commit. - verification/PROVENANCE.json: single machine-readable pin set (source + charon + aeneas commits/channel + lean + ocaml) with generated-file sha256. - Re-running extract.sh reproduces gen/SlhVerify/{Types,Funs}.lean byte-identically (companion fips205-source commit adds Cargo.lock + rust-toolchain.toml; verified not to perturb the model). DOC HONESTY (both reviewers) - README: fix the self-contradiction (apex "not yet proven" trailer vs the proven apex), the false "oracles kept OUTSIDE every cone" (they are INSIDE, by design), "deployed monomorphic path" and "semantics-identical for every parameter set" overclaims, "only two lines changed", stale snapshot head; retitle the stale future-tense "what will be claimed" section. - TRUSTED-BASE: drop "nothing proven yet"; add base_2b-inner and deployment- bridge non-claims explicitly; current pin. - ChainSpec header: "deployed monomorphic path" -> private verify_mono facade (comment only). Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-07-24 17:13:55 +00:00
import re
a = open("Proofs/Audit.lean").read()
review round 5: bind the policy, the specification bodies, and the harness The third reviewer demonstrated that the round-4 gate was closed at the EXPLOITS, not the MECHANISMS: it bound the manifest rows while the things he moved sat outside the binding. Three fail-opens, each executed end-to-end with the button printing ALL GREEN. No theorem, proof, fold, or model body changed. NEW-1 — the policy constant was unbound. `manifestFingerprint` covered `manifest` but never `allowedBoundary`, the sole predicate the enumeration tests against; adding one name re-opened the False-proof with the committed fingerprint BYTE-IDENTICAL. NEW-2 — the specification bodies were unbound. The statement fingerprint pinned each certificate's TYPE, which names its reference fold; redefining that fold to *be* the extracted loop left cone and type-hash identical while the certificate degenerated to `loop = loop`. 100% of the fidelity content lives in those defs. NEW-3 — the harness was unbound. Stubbing verification/lean-guard alone, without touching check.sh or the proofs, gave ALL GREEN in 3.6s over destroyed proofs. FIX — one mechanism rather than three patches. Audit.lean now emits a canonical AUDIT-MANIFEST block and check.sh binds to its SHA-256. The block covers the POLICY constants, every certificate's fully-elaborated statement, and every specification constant transitively reachable from those statements with its fully-elaborated BODY (41 constants; the closure is computed, so a new fold cannot appear without moving the digest; Prop-valued constants contribute their statement, by proof irrelevance). This also retires the 32-bit Expr.hash as the binding (NEW-5) — it survives only as a per-certificate diagnostic. Enumeration now covers EVERY declaration kind (a `def : False` passed before) in the eight certificate modules AND in Audit.lean itself — the auditor is no longer exempt (round-5 R1). A bare `axiom` in audited scope is now an error. Phase 0 purges stale .olean (the verdict must depend on committed bytes, not .gitignored build state — NEW-4), forbids any .lean outside gen/ and Proofs/, and sha256-pins the four model files AND lean-guard. lean-guard is KEPT rather than removed (the reviewer's portability advice is declined by operator decision): it is the memory cap and machine-wide lock that protect the build machine after a 12.2GB OOM took the host down. That trade-off is documented. check.sh's "Certificates proven:" line now comes from the audited manifest; the hand-kept CERTS array — the one authoritative claim string nothing bound — is deleted. check-selftest.sh: 14 attacks, all rejected, plus a check that the hashed block literally carries the twelve fold bodies. Attacks 9-14 are the reviewers' and an independent drill's own exploits, turned into regression tests. DOCS. TRUSTED-BASE gains item 11 (the REAL trusted computing base — lean-guard pinned; check.sh, the toolchain env, $AENEAS_HOME, python3 and Lean still trusted) and item 12 (the apex does not compose the ten). README: the audit description rewritten; the XMSS sibling-order claim downgraded from "pins" to "makes visible", with a new blanket non-claim covering all ten loop certificates; the de-plumbing file claim corrected (round 1 touched only verify_mono.rs, round 2 only helpers.rs — which is ON the deployed verify AND sign paths, now disclosed; wots.rs was never patched). RECORDED-RUN: three lines that stood inside a fence were a hand-written summary, not console output — fabricated evidence in the file whose purpose is machine evidence. They are removed and the fabrication is named in place, together with the correction that the "INDEPENDENT RUN" block predates this gate. New rule: nothing goes in a fence unless captured with tee/cat, and every block states its date, pin, and who ran it. The transcripts added here follow it. Also disclosed rather than buried: three bugs in my own test harness this round (an olean-purge build-order break, an attack rejected by the wrong rule, and a coverage assertion looking on the wrong line) — each would have let an attack pass or fail for an unrelated reason. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-07-27 20:57:46 +00:00
new, n = re.subn(r'(`fips205\.to_int_loop_eq,\s*)kernel3,', r'\1kernel3 ++ [oracleF],', a)
assert n == 1, f"expected 1 to_int row, patched {n}"
review round 2: in-Lean exact-cone audit + reproducibility + doc honesty Addresses the round-2 reviewer punch-list. No theorem statement, proof term, or fold definition changed; the eleven cones are unchanged (independent collectAxioms dump in verification/RECORDED-RUN.md). AUDIT GATE (both reviewers, the critical one) - Retire the bash #print-axioms text parser (fail-open on empty/truncated reports, and only a SUBSET check). Replace with verification/Proofs/Audit.lean: reads each certificate's cone from the kernel via collectAxioms and asserts EXACT set equality against its expected boundary. Extra axiom, dropped oracle, renamed/deleted cert, or an axiom/opaque sham each throw -> non-zero Lean exit. No text to misparse; nothing fails open. check.sh Phase 3 now just compiles it (and still requires the explicit PASSED line). - check-selftest.sh rewritten to attack the new gate: dead-file, smuggled extra axiom (named), dropped-oracle (subset would pass, exact must not), and a vanished certificate (the collectAxioms-returns-[] trap). All four rejected. REPRODUCIBILITY (GPT B1.4 / B1.5) - extract.sh refuses a wrong-commit or dirty source tree (fail-closed), takes an optional source-path arg, and pins the source commit. - verification/PROVENANCE.json: single machine-readable pin set (source + charon + aeneas commits/channel + lean + ocaml) with generated-file sha256. - Re-running extract.sh reproduces gen/SlhVerify/{Types,Funs}.lean byte-identically (companion fips205-source commit adds Cargo.lock + rust-toolchain.toml; verified not to perturb the model). DOC HONESTY (both reviewers) - README: fix the self-contradiction (apex "not yet proven" trailer vs the proven apex), the false "oracles kept OUTSIDE every cone" (they are INSIDE, by design), "deployed monomorphic path" and "semantics-identical for every parameter set" overclaims, "only two lines changed", stale snapshot head; retitle the stale future-tense "what will be claimed" section. - TRUSTED-BASE: drop "nothing proven yet"; add base_2b-inner and deployment- bridge non-claims explicitly; current pin. - ChainSpec header: "deployed monomorphic path" -> private verify_mono facade (comment only). Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-07-24 17:13:55 +00:00
open("Proofs/Audit.lean","w").write(new)
PY
review round 6: pin the auditor, purge every olean, pin gen/ as a set Round 6 confirmed the digest redesign closed NEW-1/NEW-2/NEW-5 at the mechanism ("the first time in three rounds I have not been able to gut a certificate"), then demonstrated two more ways to reach ALL GREEN with the committed digest BYTE-IDENTICAL over a repository proving False. Both are fixed. NEW-7 — the digest bound the audit's DATA, never its LOGIC. Flipping the two fail-closed guards in Proofs/Audit.lean to `unless true` disabled every in-Lean check; the block's inputs genuinely had not changed, so the digest still matched. Total attacker diff: 2 files, 6 insertions. Worse, TRUSTED-BASE item 11 listed the trusted-unbound set and did NOT mention Audit.lean, so a reviewer using it as a map of what to read by hand would have skipped the file that computes the number it is judged by. FIX: Proofs/Audit.lean is now sha256-pinned in harness_integrity_sha256, symmetric with lean-guard, and item 11 says so — including the honest residue: an author who edits the logic AND rotates its pin is caught only by reading the diff at the pin. NEW-8 — Phase 0's purge covered gen/ and Proofs/ while the stray check greped only *.lean, so an ORPHAN verification/Evil.olean whose source had been DELETED fell between them, satisfied an import, and was invisible to git status (*.olean is gitignored). FIX: purge every .olean under verification/, and forbid stray .lean AND .olean. NEW-9 (partial) — gen/ was pinned by four NAMES, not as a SET, so a new file there was neither hashed nor forbidden while LEAN_PATH contains $PWD/gen. FIX: Phase 0 asserts the gen/*.lean file set equals the pin map exactly. This found a real gap on its first run: Aeneas emits *_Template.lean scaffolding into gen/ on every extraction — untracked byproducts (a fresh clone has only the four pinned files) that nothing imports but that sat on LEAN_PATH unpinned. They are now purged as byproducts before the set assertion. Also, from the reviewer's §3 suggestion: the canonical block is now COMMITTED as verification/AUDIT-MANIFEST.txt, so a digest mismatch prints a real diff instead of writing an observed file with nothing to compare against; check.sh also fails if the committed copy drifts from what Lean emits. check-selftest.sh: 16 attacks, all rejected, plus the coverage check. Attacks 16 and 17 are the reviewer's two demonstrations. Attacks that mutate the audit's DATA now re-pin Audit.lean first, so they still test the digest/enumeration rather than being stopped by the byte pin; attack 17 deliberately does not re-pin, because the pin is what it tests. Housekeeping: PROVENANCE.json trailing newline restored (NEW-12). Disclosed rather than buried: two more of my own assertion bugs this round — attack 16 asserted the hygiene message when the correct rejection is the purge plus a failed import, and the earlier gen/ set check surfaced the template files only because it was written strictly. Both are the wrong-diagnostic class. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-07-28 07:22:12 +00:00
repin_audit
review round 5: bind the policy, the specification bodies, and the harness The third reviewer demonstrated that the round-4 gate was closed at the EXPLOITS, not the MECHANISMS: it bound the manifest rows while the things he moved sat outside the binding. Three fail-opens, each executed end-to-end with the button printing ALL GREEN. No theorem, proof, fold, or model body changed. NEW-1 — the policy constant was unbound. `manifestFingerprint` covered `manifest` but never `allowedBoundary`, the sole predicate the enumeration tests against; adding one name re-opened the False-proof with the committed fingerprint BYTE-IDENTICAL. NEW-2 — the specification bodies were unbound. The statement fingerprint pinned each certificate's TYPE, which names its reference fold; redefining that fold to *be* the extracted loop left cone and type-hash identical while the certificate degenerated to `loop = loop`. 100% of the fidelity content lives in those defs. NEW-3 — the harness was unbound. Stubbing verification/lean-guard alone, without touching check.sh or the proofs, gave ALL GREEN in 3.6s over destroyed proofs. FIX — one mechanism rather than three patches. Audit.lean now emits a canonical AUDIT-MANIFEST block and check.sh binds to its SHA-256. The block covers the POLICY constants, every certificate's fully-elaborated statement, and every specification constant transitively reachable from those statements with its fully-elaborated BODY (41 constants; the closure is computed, so a new fold cannot appear without moving the digest; Prop-valued constants contribute their statement, by proof irrelevance). This also retires the 32-bit Expr.hash as the binding (NEW-5) — it survives only as a per-certificate diagnostic. Enumeration now covers EVERY declaration kind (a `def : False` passed before) in the eight certificate modules AND in Audit.lean itself — the auditor is no longer exempt (round-5 R1). A bare `axiom` in audited scope is now an error. Phase 0 purges stale .olean (the verdict must depend on committed bytes, not .gitignored build state — NEW-4), forbids any .lean outside gen/ and Proofs/, and sha256-pins the four model files AND lean-guard. lean-guard is KEPT rather than removed (the reviewer's portability advice is declined by operator decision): it is the memory cap and machine-wide lock that protect the build machine after a 12.2GB OOM took the host down. That trade-off is documented. check.sh's "Certificates proven:" line now comes from the audited manifest; the hand-kept CERTS array — the one authoritative claim string nothing bound — is deleted. check-selftest.sh: 14 attacks, all rejected, plus a check that the hashed block literally carries the twelve fold bodies. Attacks 9-14 are the reviewers' and an independent drill's own exploits, turned into regression tests. DOCS. TRUSTED-BASE gains item 11 (the REAL trusted computing base — lean-guard pinned; check.sh, the toolchain env, $AENEAS_HOME, python3 and Lean still trusted) and item 12 (the apex does not compose the ten). README: the audit description rewritten; the XMSS sibling-order claim downgraded from "pins" to "makes visible", with a new blanket non-claim covering all ten loop certificates; the de-plumbing file claim corrected (round 1 touched only verify_mono.rs, round 2 only helpers.rs — which is ON the deployed verify AND sign paths, now disclosed; wots.rs was never patched). RECORDED-RUN: three lines that stood inside a fence were a hand-written summary, not console output — fabricated evidence in the file whose purpose is machine evidence. They are removed and the fabrication is named in place, together with the correction that the "INDEPENDENT RUN" block predates this gate. New rule: nothing goes in a fence unless captured with tee/cat, and every block states its date, pin, and who ran it. The transcripts added here follow it. Also disclosed rather than buried: three bugs in my own test harness this round (an olean-purge build-order break, an attack rejected by the wrong rule, and a coverage assertion looking on the wrong line) — each would have let an attack pass or fail for an unrelated reason. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-07-27 20:57:46 +00:00
./check.sh > /tmp/sf3.out 2>&1 && fail "ATTACK 3 SUCCEEDED (dropped oracle — subset hole)" /tmp/sf3.out
grep -q "missing=\[verify_mono.oracle.f\]" /tmp/sf3.out || fail "ATTACK 3: rejected but missing oracle not named" /tmp/sf3.out
restore
review round 4: bind the cert set, statements, and model bytes (F1/F2/F3) The third reviewer demonstrated that the round-2 in-Lean exact-cone audit, though sound for LISTED certs, left three fail-opens OUTSIDE the cone check — and made check.sh print ALL GREEN over a repo proving False. All closed; no theorem, proof, or fold changed (the 11 cones are unchanged). F1 — the audited SET was unbound. Audit.lean now (a) enumerates EVERY theorem defined in the eight certificate modules and requires each cone ⊆ boundary, so an un-manifested `theorem _ : False := cheat _` fails regardless of naming (this is the exact exploit the reviewer used); and (b) prints a MANIFEST fingerprint over the whole committed manifest, which check.sh binds to — so deleting/swapping a cert row fails outside Lean too. F2 — only cones were bound, not statements. Each cert now also carries the structural fingerprint (Expr.hash) of its elaborated type; a statement gutted to a tautology of the same cone changes the fingerprint and fails. F3 — the gen/ model bytes were unbound. New check.sh Phase 0 sha256-pins all four gen/SlhVerify/*.lean (incl. the two hand-maintained *External files, now hashed in PROVENANCE.json) BEFORE compiling; a hand-edited model fails first. F4/F5 — docs. README cone diagram now roots honestly at slh_verify_internal and states the pure/prehash domain-separator byte, the ctx>255 check, M' assembly, and deserialization are ABOVE the root and uncovered (new TRUSTED-BASE item 10). The false "rules out a wrong ADRS field" claim is corrected in README + ChainSpec (a transliteration makes the field visible, not excluded). check-selftest.sh: eight attacks, all rejected (dead file; extra axiom; dropped oracle; vanished cert; un-manifested False theorem; gutted statement; hand-edited model; deleted manifest row). Full transcript + green check.sh in verification/RECORDED-RUN.md. Standing limit unchanged and disclosed: an audit cannot defend against an author who edits the manifest AND check.sh AND the proofs together; the consumer defense is the pinned commit reviewed at the pin. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-07-27 17:47:39 +00:00
echo "✓ attack 3 rejected (missing-oracle detection — exact cone, not subset)"
review round 2: in-Lean exact-cone audit + reproducibility + doc honesty Addresses the round-2 reviewer punch-list. No theorem statement, proof term, or fold definition changed; the eleven cones are unchanged (independent collectAxioms dump in verification/RECORDED-RUN.md). AUDIT GATE (both reviewers, the critical one) - Retire the bash #print-axioms text parser (fail-open on empty/truncated reports, and only a SUBSET check). Replace with verification/Proofs/Audit.lean: reads each certificate's cone from the kernel via collectAxioms and asserts EXACT set equality against its expected boundary. Extra axiom, dropped oracle, renamed/deleted cert, or an axiom/opaque sham each throw -> non-zero Lean exit. No text to misparse; nothing fails open. check.sh Phase 3 now just compiles it (and still requires the explicit PASSED line). - check-selftest.sh rewritten to attack the new gate: dead-file, smuggled extra axiom (named), dropped-oracle (subset would pass, exact must not), and a vanished certificate (the collectAxioms-returns-[] trap). All four rejected. REPRODUCIBILITY (GPT B1.4 / B1.5) - extract.sh refuses a wrong-commit or dirty source tree (fail-closed), takes an optional source-path arg, and pins the source commit. - verification/PROVENANCE.json: single machine-readable pin set (source + charon + aeneas commits/channel + lean + ocaml) with generated-file sha256. - Re-running extract.sh reproduces gen/SlhVerify/{Types,Funs}.lean byte-identically (companion fips205-source commit adds Cargo.lock + rust-toolchain.toml; verified not to perturb the model). DOC HONESTY (both reviewers) - README: fix the self-contradiction (apex "not yet proven" trailer vs the proven apex), the false "oracles kept OUTSIDE every cone" (they are INSIDE, by design), "deployed monomorphic path" and "semantics-identical for every parameter set" overclaims, "only two lines changed", stale snapshot head; retitle the stale future-tense "what will be claimed" section. - TRUSTED-BASE: drop "nothing proven yet"; add base_2b-inner and deployment- bridge non-claims explicitly; current pin. - ChainSpec header: "deployed monomorphic path" -> private verify_mono facade (comment only). Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-07-24 17:13:55 +00:00
review round 5: bind the policy, the specification bodies, and the harness The third reviewer demonstrated that the round-4 gate was closed at the EXPLOITS, not the MECHANISMS: it bound the manifest rows while the things he moved sat outside the binding. Three fail-opens, each executed end-to-end with the button printing ALL GREEN. No theorem, proof, fold, or model body changed. NEW-1 — the policy constant was unbound. `manifestFingerprint` covered `manifest` but never `allowedBoundary`, the sole predicate the enumeration tests against; adding one name re-opened the False-proof with the committed fingerprint BYTE-IDENTICAL. NEW-2 — the specification bodies were unbound. The statement fingerprint pinned each certificate's TYPE, which names its reference fold; redefining that fold to *be* the extracted loop left cone and type-hash identical while the certificate degenerated to `loop = loop`. 100% of the fidelity content lives in those defs. NEW-3 — the harness was unbound. Stubbing verification/lean-guard alone, without touching check.sh or the proofs, gave ALL GREEN in 3.6s over destroyed proofs. FIX — one mechanism rather than three patches. Audit.lean now emits a canonical AUDIT-MANIFEST block and check.sh binds to its SHA-256. The block covers the POLICY constants, every certificate's fully-elaborated statement, and every specification constant transitively reachable from those statements with its fully-elaborated BODY (41 constants; the closure is computed, so a new fold cannot appear without moving the digest; Prop-valued constants contribute their statement, by proof irrelevance). This also retires the 32-bit Expr.hash as the binding (NEW-5) — it survives only as a per-certificate diagnostic. Enumeration now covers EVERY declaration kind (a `def : False` passed before) in the eight certificate modules AND in Audit.lean itself — the auditor is no longer exempt (round-5 R1). A bare `axiom` in audited scope is now an error. Phase 0 purges stale .olean (the verdict must depend on committed bytes, not .gitignored build state — NEW-4), forbids any .lean outside gen/ and Proofs/, and sha256-pins the four model files AND lean-guard. lean-guard is KEPT rather than removed (the reviewer's portability advice is declined by operator decision): it is the memory cap and machine-wide lock that protect the build machine after a 12.2GB OOM took the host down. That trade-off is documented. check.sh's "Certificates proven:" line now comes from the audited manifest; the hand-kept CERTS array — the one authoritative claim string nothing bound — is deleted. check-selftest.sh: 14 attacks, all rejected, plus a check that the hashed block literally carries the twelve fold bodies. Attacks 9-14 are the reviewers' and an independent drill's own exploits, turned into regression tests. DOCS. TRUSTED-BASE gains item 11 (the REAL trusted computing base — lean-guard pinned; check.sh, the toolchain env, $AENEAS_HOME, python3 and Lean still trusted) and item 12 (the apex does not compose the ten). README: the audit description rewritten; the XMSS sibling-order claim downgraded from "pins" to "makes visible", with a new blanket non-claim covering all ten loop certificates; the de-plumbing file claim corrected (round 1 touched only verify_mono.rs, round 2 only helpers.rs — which is ON the deployed verify AND sign paths, now disclosed; wots.rs was never patched). RECORDED-RUN: three lines that stood inside a fence were a hand-written summary, not console output — fabricated evidence in the file whose purpose is machine evidence. They are removed and the fabrication is named in place, together with the correction that the "INDEPENDENT RUN" block predates this gate. New rule: nothing goes in a fence unless captured with tee/cat, and every block states its date, pin, and who ran it. The transcripts added here follow it. Also disclosed rather than buried: three bugs in my own test harness this round (an olean-purge build-order break, an attack rejected by the wrong rule, and a coverage assertion looking on the wrong line) — each would have let an attack pass or fail for an unrelated reason. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-07-27 20:57:46 +00:00
# ── 4: vanished certificate ─────────────────────────────────────────────────
review round 6: pin the auditor, purge every olean, pin gen/ as a set Round 6 confirmed the digest redesign closed NEW-1/NEW-2/NEW-5 at the mechanism ("the first time in three rounds I have not been able to gut a certificate"), then demonstrated two more ways to reach ALL GREEN with the committed digest BYTE-IDENTICAL over a repository proving False. Both are fixed. NEW-7 — the digest bound the audit's DATA, never its LOGIC. Flipping the two fail-closed guards in Proofs/Audit.lean to `unless true` disabled every in-Lean check; the block's inputs genuinely had not changed, so the digest still matched. Total attacker diff: 2 files, 6 insertions. Worse, TRUSTED-BASE item 11 listed the trusted-unbound set and did NOT mention Audit.lean, so a reviewer using it as a map of what to read by hand would have skipped the file that computes the number it is judged by. FIX: Proofs/Audit.lean is now sha256-pinned in harness_integrity_sha256, symmetric with lean-guard, and item 11 says so — including the honest residue: an author who edits the logic AND rotates its pin is caught only by reading the diff at the pin. NEW-8 — Phase 0's purge covered gen/ and Proofs/ while the stray check greped only *.lean, so an ORPHAN verification/Evil.olean whose source had been DELETED fell between them, satisfied an import, and was invisible to git status (*.olean is gitignored). FIX: purge every .olean under verification/, and forbid stray .lean AND .olean. NEW-9 (partial) — gen/ was pinned by four NAMES, not as a SET, so a new file there was neither hashed nor forbidden while LEAN_PATH contains $PWD/gen. FIX: Phase 0 asserts the gen/*.lean file set equals the pin map exactly. This found a real gap on its first run: Aeneas emits *_Template.lean scaffolding into gen/ on every extraction — untracked byproducts (a fresh clone has only the four pinned files) that nothing imports but that sat on LEAN_PATH unpinned. They are now purged as byproducts before the set assertion. Also, from the reviewer's §3 suggestion: the canonical block is now COMMITTED as verification/AUDIT-MANIFEST.txt, so a digest mismatch prints a real diff instead of writing an observed file with nothing to compare against; check.sh also fails if the committed copy drifts from what Lean emits. check-selftest.sh: 16 attacks, all rejected, plus the coverage check. Attacks 16 and 17 are the reviewer's two demonstrations. Attacks that mutate the audit's DATA now re-pin Audit.lean first, so they still test the digest/enumeration rather than being stopped by the byte pin; attack 17 deliberately does not re-pin, because the pin is what it tests. Housekeeping: PROVENANCE.json trailing newline restored (NEW-12). Disclosed rather than buried: two more of my own assertion bugs this round — attack 16 asserted the hygiene message when the correct rejection is the purge plus a failed import, and the earlier gen/ set check surfaced the template files only because it was written strictly. Both are the wrong-diagnostic class. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-07-28 07:22:12 +00:00
save Proofs/Audit.lean; save PROVENANCE.json
review round 2: in-Lean exact-cone audit + reproducibility + doc honesty Addresses the round-2 reviewer punch-list. No theorem statement, proof term, or fold definition changed; the eleven cones are unchanged (independent collectAxioms dump in verification/RECORDED-RUN.md). AUDIT GATE (both reviewers, the critical one) - Retire the bash #print-axioms text parser (fail-open on empty/truncated reports, and only a SUBSET check). Replace with verification/Proofs/Audit.lean: reads each certificate's cone from the kernel via collectAxioms and asserts EXACT set equality against its expected boundary. Extra axiom, dropped oracle, renamed/deleted cert, or an axiom/opaque sham each throw -> non-zero Lean exit. No text to misparse; nothing fails open. check.sh Phase 3 now just compiles it (and still requires the explicit PASSED line). - check-selftest.sh rewritten to attack the new gate: dead-file, smuggled extra axiom (named), dropped-oracle (subset would pass, exact must not), and a vanished certificate (the collectAxioms-returns-[] trap). All four rejected. REPRODUCIBILITY (GPT B1.4 / B1.5) - extract.sh refuses a wrong-commit or dirty source tree (fail-closed), takes an optional source-path arg, and pins the source commit. - verification/PROVENANCE.json: single machine-readable pin set (source + charon + aeneas commits/channel + lean + ocaml) with generated-file sha256. - Re-running extract.sh reproduces gen/SlhVerify/{Types,Funs}.lean byte-identically (companion fips205-source commit adds Cargo.lock + rust-toolchain.toml; verified not to perturb the model). DOC HONESTY (both reviewers) - README: fix the self-contradiction (apex "not yet proven" trailer vs the proven apex), the false "oracles kept OUTSIDE every cone" (they are INSIDE, by design), "deployed monomorphic path" and "semantics-identical for every parameter set" overclaims, "only two lines changed", stale snapshot head; retitle the stale future-tense "what will be claimed" section. - TRUSTED-BASE: drop "nothing proven yet"; add base_2b-inner and deployment- bridge non-claims explicitly; current pin. - ChainSpec header: "deployed monomorphic path" -> private verify_mono facade (comment only). Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-07-24 17:13:55 +00:00
python3 - <<'PY'
a = open("Proofs/Audit.lean").read()
review round 5: bind the policy, the specification bodies, and the harness The third reviewer demonstrated that the round-4 gate was closed at the EXPLOITS, not the MECHANISMS: it bound the manifest rows while the things he moved sat outside the binding. Three fail-opens, each executed end-to-end with the button printing ALL GREEN. No theorem, proof, fold, or model body changed. NEW-1 — the policy constant was unbound. `manifestFingerprint` covered `manifest` but never `allowedBoundary`, the sole predicate the enumeration tests against; adding one name re-opened the False-proof with the committed fingerprint BYTE-IDENTICAL. NEW-2 — the specification bodies were unbound. The statement fingerprint pinned each certificate's TYPE, which names its reference fold; redefining that fold to *be* the extracted loop left cone and type-hash identical while the certificate degenerated to `loop = loop`. 100% of the fidelity content lives in those defs. NEW-3 — the harness was unbound. Stubbing verification/lean-guard alone, without touching check.sh or the proofs, gave ALL GREEN in 3.6s over destroyed proofs. FIX — one mechanism rather than three patches. Audit.lean now emits a canonical AUDIT-MANIFEST block and check.sh binds to its SHA-256. The block covers the POLICY constants, every certificate's fully-elaborated statement, and every specification constant transitively reachable from those statements with its fully-elaborated BODY (41 constants; the closure is computed, so a new fold cannot appear without moving the digest; Prop-valued constants contribute their statement, by proof irrelevance). This also retires the 32-bit Expr.hash as the binding (NEW-5) — it survives only as a per-certificate diagnostic. Enumeration now covers EVERY declaration kind (a `def : False` passed before) in the eight certificate modules AND in Audit.lean itself — the auditor is no longer exempt (round-5 R1). A bare `axiom` in audited scope is now an error. Phase 0 purges stale .olean (the verdict must depend on committed bytes, not .gitignored build state — NEW-4), forbids any .lean outside gen/ and Proofs/, and sha256-pins the four model files AND lean-guard. lean-guard is KEPT rather than removed (the reviewer's portability advice is declined by operator decision): it is the memory cap and machine-wide lock that protect the build machine after a 12.2GB OOM took the host down. That trade-off is documented. check.sh's "Certificates proven:" line now comes from the audited manifest; the hand-kept CERTS array — the one authoritative claim string nothing bound — is deleted. check-selftest.sh: 14 attacks, all rejected, plus a check that the hashed block literally carries the twelve fold bodies. Attacks 9-14 are the reviewers' and an independent drill's own exploits, turned into regression tests. DOCS. TRUSTED-BASE gains item 11 (the REAL trusted computing base — lean-guard pinned; check.sh, the toolchain env, $AENEAS_HOME, python3 and Lean still trusted) and item 12 (the apex does not compose the ten). README: the audit description rewritten; the XMSS sibling-order claim downgraded from "pins" to "makes visible", with a new blanket non-claim covering all ten loop certificates; the de-plumbing file claim corrected (round 1 touched only verify_mono.rs, round 2 only helpers.rs — which is ON the deployed verify AND sign paths, now disclosed; wots.rs was never patched). RECORDED-RUN: three lines that stood inside a fence were a hand-written summary, not console output — fabricated evidence in the file whose purpose is machine evidence. They are removed and the fabrication is named in place, together with the correction that the "INDEPENDENT RUN" block predates this gate. New rule: nothing goes in a fence unless captured with tee/cat, and every block states its date, pin, and who ran it. The transcripts added here follow it. Also disclosed rather than buried: three bugs in my own test harness this round (an olean-purge build-order break, an attack rejected by the wrong rule, and a coverage assertion looking on the wrong line) — each would have let an attack pass or fail for an unrelated reason. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-07-27 20:57:46 +00:00
assert a.count('`fips205.chain_free_loop_eq,') >= 1
review round 4: bind the cert set, statements, and model bytes (F1/F2/F3) The third reviewer demonstrated that the round-2 in-Lean exact-cone audit, though sound for LISTED certs, left three fail-opens OUTSIDE the cone check — and made check.sh print ALL GREEN over a repo proving False. All closed; no theorem, proof, or fold changed (the 11 cones are unchanged). F1 — the audited SET was unbound. Audit.lean now (a) enumerates EVERY theorem defined in the eight certificate modules and requires each cone ⊆ boundary, so an un-manifested `theorem _ : False := cheat _` fails regardless of naming (this is the exact exploit the reviewer used); and (b) prints a MANIFEST fingerprint over the whole committed manifest, which check.sh binds to — so deleting/swapping a cert row fails outside Lean too. F2 — only cones were bound, not statements. Each cert now also carries the structural fingerprint (Expr.hash) of its elaborated type; a statement gutted to a tautology of the same cone changes the fingerprint and fails. F3 — the gen/ model bytes were unbound. New check.sh Phase 0 sha256-pins all four gen/SlhVerify/*.lean (incl. the two hand-maintained *External files, now hashed in PROVENANCE.json) BEFORE compiling; a hand-edited model fails first. F4/F5 — docs. README cone diagram now roots honestly at slh_verify_internal and states the pure/prehash domain-separator byte, the ctx>255 check, M' assembly, and deserialization are ABOVE the root and uncovered (new TRUSTED-BASE item 10). The false "rules out a wrong ADRS field" claim is corrected in README + ChainSpec (a transliteration makes the field visible, not excluded). check-selftest.sh: eight attacks, all rejected (dead file; extra axiom; dropped oracle; vanished cert; un-manifested False theorem; gutted statement; hand-edited model; deleted manifest row). Full transcript + green check.sh in verification/RECORDED-RUN.md. Standing limit unchanged and disclosed: an audit cannot defend against an author who edits the manifest AND check.sh AND the proofs together; the consumer defense is the pinned commit reviewed at the pin. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-07-27 17:47:39 +00:00
open("Proofs/Audit.lean","w").write(a.replace('`fips205.chain_free_loop_eq,', '`fips205.chain_free_loop_eq_VANISHED,', 1))
PY
review round 6: pin the auditor, purge every olean, pin gen/ as a set Round 6 confirmed the digest redesign closed NEW-1/NEW-2/NEW-5 at the mechanism ("the first time in three rounds I have not been able to gut a certificate"), then demonstrated two more ways to reach ALL GREEN with the committed digest BYTE-IDENTICAL over a repository proving False. Both are fixed. NEW-7 — the digest bound the audit's DATA, never its LOGIC. Flipping the two fail-closed guards in Proofs/Audit.lean to `unless true` disabled every in-Lean check; the block's inputs genuinely had not changed, so the digest still matched. Total attacker diff: 2 files, 6 insertions. Worse, TRUSTED-BASE item 11 listed the trusted-unbound set and did NOT mention Audit.lean, so a reviewer using it as a map of what to read by hand would have skipped the file that computes the number it is judged by. FIX: Proofs/Audit.lean is now sha256-pinned in harness_integrity_sha256, symmetric with lean-guard, and item 11 says so — including the honest residue: an author who edits the logic AND rotates its pin is caught only by reading the diff at the pin. NEW-8 — Phase 0's purge covered gen/ and Proofs/ while the stray check greped only *.lean, so an ORPHAN verification/Evil.olean whose source had been DELETED fell between them, satisfied an import, and was invisible to git status (*.olean is gitignored). FIX: purge every .olean under verification/, and forbid stray .lean AND .olean. NEW-9 (partial) — gen/ was pinned by four NAMES, not as a SET, so a new file there was neither hashed nor forbidden while LEAN_PATH contains $PWD/gen. FIX: Phase 0 asserts the gen/*.lean file set equals the pin map exactly. This found a real gap on its first run: Aeneas emits *_Template.lean scaffolding into gen/ on every extraction — untracked byproducts (a fresh clone has only the four pinned files) that nothing imports but that sat on LEAN_PATH unpinned. They are now purged as byproducts before the set assertion. Also, from the reviewer's §3 suggestion: the canonical block is now COMMITTED as verification/AUDIT-MANIFEST.txt, so a digest mismatch prints a real diff instead of writing an observed file with nothing to compare against; check.sh also fails if the committed copy drifts from what Lean emits. check-selftest.sh: 16 attacks, all rejected, plus the coverage check. Attacks 16 and 17 are the reviewer's two demonstrations. Attacks that mutate the audit's DATA now re-pin Audit.lean first, so they still test the digest/enumeration rather than being stopped by the byte pin; attack 17 deliberately does not re-pin, because the pin is what it tests. Housekeeping: PROVENANCE.json trailing newline restored (NEW-12). Disclosed rather than buried: two more of my own assertion bugs this round — attack 16 asserted the hygiene message when the correct rejection is the purge plus a failed import, and the earlier gen/ set check surfaced the template files only because it was written strictly. Both are the wrong-diagnostic class. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-07-28 07:22:12 +00:00
repin_audit
review round 5: bind the policy, the specification bodies, and the harness The third reviewer demonstrated that the round-4 gate was closed at the EXPLOITS, not the MECHANISMS: it bound the manifest rows while the things he moved sat outside the binding. Three fail-opens, each executed end-to-end with the button printing ALL GREEN. No theorem, proof, fold, or model body changed. NEW-1 — the policy constant was unbound. `manifestFingerprint` covered `manifest` but never `allowedBoundary`, the sole predicate the enumeration tests against; adding one name re-opened the False-proof with the committed fingerprint BYTE-IDENTICAL. NEW-2 — the specification bodies were unbound. The statement fingerprint pinned each certificate's TYPE, which names its reference fold; redefining that fold to *be* the extracted loop left cone and type-hash identical while the certificate degenerated to `loop = loop`. 100% of the fidelity content lives in those defs. NEW-3 — the harness was unbound. Stubbing verification/lean-guard alone, without touching check.sh or the proofs, gave ALL GREEN in 3.6s over destroyed proofs. FIX — one mechanism rather than three patches. Audit.lean now emits a canonical AUDIT-MANIFEST block and check.sh binds to its SHA-256. The block covers the POLICY constants, every certificate's fully-elaborated statement, and every specification constant transitively reachable from those statements with its fully-elaborated BODY (41 constants; the closure is computed, so a new fold cannot appear without moving the digest; Prop-valued constants contribute their statement, by proof irrelevance). This also retires the 32-bit Expr.hash as the binding (NEW-5) — it survives only as a per-certificate diagnostic. Enumeration now covers EVERY declaration kind (a `def : False` passed before) in the eight certificate modules AND in Audit.lean itself — the auditor is no longer exempt (round-5 R1). A bare `axiom` in audited scope is now an error. Phase 0 purges stale .olean (the verdict must depend on committed bytes, not .gitignored build state — NEW-4), forbids any .lean outside gen/ and Proofs/, and sha256-pins the four model files AND lean-guard. lean-guard is KEPT rather than removed (the reviewer's portability advice is declined by operator decision): it is the memory cap and machine-wide lock that protect the build machine after a 12.2GB OOM took the host down. That trade-off is documented. check.sh's "Certificates proven:" line now comes from the audited manifest; the hand-kept CERTS array — the one authoritative claim string nothing bound — is deleted. check-selftest.sh: 14 attacks, all rejected, plus a check that the hashed block literally carries the twelve fold bodies. Attacks 9-14 are the reviewers' and an independent drill's own exploits, turned into regression tests. DOCS. TRUSTED-BASE gains item 11 (the REAL trusted computing base — lean-guard pinned; check.sh, the toolchain env, $AENEAS_HOME, python3 and Lean still trusted) and item 12 (the apex does not compose the ten). README: the audit description rewritten; the XMSS sibling-order claim downgraded from "pins" to "makes visible", with a new blanket non-claim covering all ten loop certificates; the de-plumbing file claim corrected (round 1 touched only verify_mono.rs, round 2 only helpers.rs — which is ON the deployed verify AND sign paths, now disclosed; wots.rs was never patched). RECORDED-RUN: three lines that stood inside a fence were a hand-written summary, not console output — fabricated evidence in the file whose purpose is machine evidence. They are removed and the fabrication is named in place, together with the correction that the "INDEPENDENT RUN" block predates this gate. New rule: nothing goes in a fence unless captured with tee/cat, and every block states its date, pin, and who ran it. The transcripts added here follow it. Also disclosed rather than buried: three bugs in my own test harness this round (an olean-purge build-order break, an attack rejected by the wrong rule, and a coverage assertion looking on the wrong line) — each would have let an attack pass or fail for an unrelated reason. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-07-27 20:57:46 +00:00
./check.sh > /tmp/sf4.out 2>&1 && fail "ATTACK 4 SUCCEEDED (vanished cert)" /tmp/sf4.out
grep -q "NOT FOUND" /tmp/sf4.out || fail "ATTACK 4: rejected but not via the existence check" /tmp/sf4.out
restore
echo "✓ attack 4 rejected (existence check — a vanished cert cannot pass as 0-axiom)"
review round 4: bind the cert set, statements, and model bytes (F1/F2/F3) The third reviewer demonstrated that the round-2 in-Lean exact-cone audit, though sound for LISTED certs, left three fail-opens OUTSIDE the cone check — and made check.sh print ALL GREEN over a repo proving False. All closed; no theorem, proof, or fold changed (the 11 cones are unchanged). F1 — the audited SET was unbound. Audit.lean now (a) enumerates EVERY theorem defined in the eight certificate modules and requires each cone ⊆ boundary, so an un-manifested `theorem _ : False := cheat _` fails regardless of naming (this is the exact exploit the reviewer used); and (b) prints a MANIFEST fingerprint over the whole committed manifest, which check.sh binds to — so deleting/swapping a cert row fails outside Lean too. F2 — only cones were bound, not statements. Each cert now also carries the structural fingerprint (Expr.hash) of its elaborated type; a statement gutted to a tautology of the same cone changes the fingerprint and fails. F3 — the gen/ model bytes were unbound. New check.sh Phase 0 sha256-pins all four gen/SlhVerify/*.lean (incl. the two hand-maintained *External files, now hashed in PROVENANCE.json) BEFORE compiling; a hand-edited model fails first. F4/F5 — docs. README cone diagram now roots honestly at slh_verify_internal and states the pure/prehash domain-separator byte, the ctx>255 check, M' assembly, and deserialization are ABOVE the root and uncovered (new TRUSTED-BASE item 10). The false "rules out a wrong ADRS field" claim is corrected in README + ChainSpec (a transliteration makes the field visible, not excluded). check-selftest.sh: eight attacks, all rejected (dead file; extra axiom; dropped oracle; vanished cert; un-manifested False theorem; gutted statement; hand-edited model; deleted manifest row). Full transcript + green check.sh in verification/RECORDED-RUN.md. Standing limit unchanged and disclosed: an audit cannot defend against an author who edits the manifest AND check.sh AND the proofs together; the consumer defense is the pinned commit reviewed at the pin. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-07-27 17:47:39 +00:00
review round 5: bind the policy, the specification bodies, and the harness The third reviewer demonstrated that the round-4 gate was closed at the EXPLOITS, not the MECHANISMS: it bound the manifest rows while the things he moved sat outside the binding. Three fail-opens, each executed end-to-end with the button printing ALL GREEN. No theorem, proof, fold, or model body changed. NEW-1 — the policy constant was unbound. `manifestFingerprint` covered `manifest` but never `allowedBoundary`, the sole predicate the enumeration tests against; adding one name re-opened the False-proof with the committed fingerprint BYTE-IDENTICAL. NEW-2 — the specification bodies were unbound. The statement fingerprint pinned each certificate's TYPE, which names its reference fold; redefining that fold to *be* the extracted loop left cone and type-hash identical while the certificate degenerated to `loop = loop`. 100% of the fidelity content lives in those defs. NEW-3 — the harness was unbound. Stubbing verification/lean-guard alone, without touching check.sh or the proofs, gave ALL GREEN in 3.6s over destroyed proofs. FIX — one mechanism rather than three patches. Audit.lean now emits a canonical AUDIT-MANIFEST block and check.sh binds to its SHA-256. The block covers the POLICY constants, every certificate's fully-elaborated statement, and every specification constant transitively reachable from those statements with its fully-elaborated BODY (41 constants; the closure is computed, so a new fold cannot appear without moving the digest; Prop-valued constants contribute their statement, by proof irrelevance). This also retires the 32-bit Expr.hash as the binding (NEW-5) — it survives only as a per-certificate diagnostic. Enumeration now covers EVERY declaration kind (a `def : False` passed before) in the eight certificate modules AND in Audit.lean itself — the auditor is no longer exempt (round-5 R1). A bare `axiom` in audited scope is now an error. Phase 0 purges stale .olean (the verdict must depend on committed bytes, not .gitignored build state — NEW-4), forbids any .lean outside gen/ and Proofs/, and sha256-pins the four model files AND lean-guard. lean-guard is KEPT rather than removed (the reviewer's portability advice is declined by operator decision): it is the memory cap and machine-wide lock that protect the build machine after a 12.2GB OOM took the host down. That trade-off is documented. check.sh's "Certificates proven:" line now comes from the audited manifest; the hand-kept CERTS array — the one authoritative claim string nothing bound — is deleted. check-selftest.sh: 14 attacks, all rejected, plus a check that the hashed block literally carries the twelve fold bodies. Attacks 9-14 are the reviewers' and an independent drill's own exploits, turned into regression tests. DOCS. TRUSTED-BASE gains item 11 (the REAL trusted computing base — lean-guard pinned; check.sh, the toolchain env, $AENEAS_HOME, python3 and Lean still trusted) and item 12 (the apex does not compose the ten). README: the audit description rewritten; the XMSS sibling-order claim downgraded from "pins" to "makes visible", with a new blanket non-claim covering all ten loop certificates; the de-plumbing file claim corrected (round 1 touched only verify_mono.rs, round 2 only helpers.rs — which is ON the deployed verify AND sign paths, now disclosed; wots.rs was never patched). RECORDED-RUN: three lines that stood inside a fence were a hand-written summary, not console output — fabricated evidence in the file whose purpose is machine evidence. They are removed and the fabrication is named in place, together with the correction that the "INDEPENDENT RUN" block predates this gate. New rule: nothing goes in a fence unless captured with tee/cat, and every block states its date, pin, and who ran it. The transcripts added here follow it. Also disclosed rather than buried: three bugs in my own test harness this round (an olean-purge build-order break, an attack rejected by the wrong rule, and a coverage assertion looking on the wrong line) — each would have let an attack pass or fail for an unrelated reason. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-07-27 20:57:46 +00:00
# ── 5: un-manifested THEOREM proving False (round-4 F1) ─────────────────────
review round 4: bind the cert set, statements, and model bytes (F1/F2/F3) The third reviewer demonstrated that the round-2 in-Lean exact-cone audit, though sound for LISTED certs, left three fail-opens OUTSIDE the cone check — and made check.sh print ALL GREEN over a repo proving False. All closed; no theorem, proof, or fold changed (the 11 cones are unchanged). F1 — the audited SET was unbound. Audit.lean now (a) enumerates EVERY theorem defined in the eight certificate modules and requires each cone ⊆ boundary, so an un-manifested `theorem _ : False := cheat _` fails regardless of naming (this is the exact exploit the reviewer used); and (b) prints a MANIFEST fingerprint over the whole committed manifest, which check.sh binds to — so deleting/swapping a cert row fails outside Lean too. F2 — only cones were bound, not statements. Each cert now also carries the structural fingerprint (Expr.hash) of its elaborated type; a statement gutted to a tautology of the same cone changes the fingerprint and fails. F3 — the gen/ model bytes were unbound. New check.sh Phase 0 sha256-pins all four gen/SlhVerify/*.lean (incl. the two hand-maintained *External files, now hashed in PROVENANCE.json) BEFORE compiling; a hand-edited model fails first. F4/F5 — docs. README cone diagram now roots honestly at slh_verify_internal and states the pure/prehash domain-separator byte, the ctx>255 check, M' assembly, and deserialization are ABOVE the root and uncovered (new TRUSTED-BASE item 10). The false "rules out a wrong ADRS field" claim is corrected in README + ChainSpec (a transliteration makes the field visible, not excluded). check-selftest.sh: eight attacks, all rejected (dead file; extra axiom; dropped oracle; vanished cert; un-manifested False theorem; gutted statement; hand-edited model; deleted manifest row). Full transcript + green check.sh in verification/RECORDED-RUN.md. Standing limit unchanged and disclosed: an audit cannot defend against an author who edits the manifest AND check.sh AND the proofs together; the consumer defense is the pinned commit reviewed at the pin. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-07-27 17:47:39 +00:00
save Proofs/ChainSpec.lean
review round 5: bind the policy, the specification bodies, and the harness The third reviewer demonstrated that the round-4 gate was closed at the EXPLOITS, not the MECHANISMS: it bound the manifest rows while the things he moved sat outside the binding. Three fail-opens, each executed end-to-end with the button printing ALL GREEN. No theorem, proof, fold, or model body changed. NEW-1 — the policy constant was unbound. `manifestFingerprint` covered `manifest` but never `allowedBoundary`, the sole predicate the enumeration tests against; adding one name re-opened the False-proof with the committed fingerprint BYTE-IDENTICAL. NEW-2 — the specification bodies were unbound. The statement fingerprint pinned each certificate's TYPE, which names its reference fold; redefining that fold to *be* the extracted loop left cone and type-hash identical while the certificate degenerated to `loop = loop`. 100% of the fidelity content lives in those defs. NEW-3 — the harness was unbound. Stubbing verification/lean-guard alone, without touching check.sh or the proofs, gave ALL GREEN in 3.6s over destroyed proofs. FIX — one mechanism rather than three patches. Audit.lean now emits a canonical AUDIT-MANIFEST block and check.sh binds to its SHA-256. The block covers the POLICY constants, every certificate's fully-elaborated statement, and every specification constant transitively reachable from those statements with its fully-elaborated BODY (41 constants; the closure is computed, so a new fold cannot appear without moving the digest; Prop-valued constants contribute their statement, by proof irrelevance). This also retires the 32-bit Expr.hash as the binding (NEW-5) — it survives only as a per-certificate diagnostic. Enumeration now covers EVERY declaration kind (a `def : False` passed before) in the eight certificate modules AND in Audit.lean itself — the auditor is no longer exempt (round-5 R1). A bare `axiom` in audited scope is now an error. Phase 0 purges stale .olean (the verdict must depend on committed bytes, not .gitignored build state — NEW-4), forbids any .lean outside gen/ and Proofs/, and sha256-pins the four model files AND lean-guard. lean-guard is KEPT rather than removed (the reviewer's portability advice is declined by operator decision): it is the memory cap and machine-wide lock that protect the build machine after a 12.2GB OOM took the host down. That trade-off is documented. check.sh's "Certificates proven:" line now comes from the audited manifest; the hand-kept CERTS array — the one authoritative claim string nothing bound — is deleted. check-selftest.sh: 14 attacks, all rejected, plus a check that the hashed block literally carries the twelve fold bodies. Attacks 9-14 are the reviewers' and an independent drill's own exploits, turned into regression tests. DOCS. TRUSTED-BASE gains item 11 (the REAL trusted computing base — lean-guard pinned; check.sh, the toolchain env, $AENEAS_HOME, python3 and Lean still trusted) and item 12 (the apex does not compose the ten). README: the audit description rewritten; the XMSS sibling-order claim downgraded from "pins" to "makes visible", with a new blanket non-claim covering all ten loop certificates; the de-plumbing file claim corrected (round 1 touched only verify_mono.rs, round 2 only helpers.rs — which is ON the deployed verify AND sign paths, now disclosed; wots.rs was never patched). RECORDED-RUN: three lines that stood inside a fence were a hand-written summary, not console output — fabricated evidence in the file whose purpose is machine evidence. They are removed and the fabrication is named in place, together with the correction that the "INDEPENDENT RUN" block predates this gate. New rule: nothing goes in a fence unless captured with tee/cat, and every block states its date, pin, and who ran it. The transcripts added here follow it. Also disclosed rather than buried: three bugs in my own test harness this round (an olean-purge build-order break, an attack rejected by the wrong rule, and a coverage assertion looking on the wrong line) — each would have let an attack pass or fail for an unrelated reason. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-07-27 20:57:46 +00:00
printf '\n-- SELFTEST ATTACK 5\naxiom cheat5 : ∀ (P : Prop), P\ntheorem repo_proves_false : False := cheat5 _\n' >> Proofs/ChainSpec.lean
./check.sh > /tmp/sf5.out 2>&1 && fail "ATTACK 5 SUCCEEDED: check.sh GREEN over a repo proving False!" /tmp/sf5.out
grep -qE "repo_proves_false|AXIOM DECLARED" /tmp/sf5.out || fail "ATTACK 5: rejected but not via the enumeration" /tmp/sf5.out
restore
echo "✓ attack 5 rejected (enumeration — an un-manifested False theorem cannot pass)"
# ── 6: gutted STATEMENT, cone preserved (round-4 F2) ────────────────────────
review round 4: bind the cert set, statements, and model bytes (F1/F2/F3) The third reviewer demonstrated that the round-2 in-Lean exact-cone audit, though sound for LISTED certs, left three fail-opens OUTSIDE the cone check — and made check.sh print ALL GREEN over a repo proving False. All closed; no theorem, proof, or fold changed (the 11 cones are unchanged). F1 — the audited SET was unbound. Audit.lean now (a) enumerates EVERY theorem defined in the eight certificate modules and requires each cone ⊆ boundary, so an un-manifested `theorem _ : False := cheat _` fails regardless of naming (this is the exact exploit the reviewer used); and (b) prints a MANIFEST fingerprint over the whole committed manifest, which check.sh binds to — so deleting/swapping a cert row fails outside Lean too. F2 — only cones were bound, not statements. Each cert now also carries the structural fingerprint (Expr.hash) of its elaborated type; a statement gutted to a tautology of the same cone changes the fingerprint and fails. F3 — the gen/ model bytes were unbound. New check.sh Phase 0 sha256-pins all four gen/SlhVerify/*.lean (incl. the two hand-maintained *External files, now hashed in PROVENANCE.json) BEFORE compiling; a hand-edited model fails first. F4/F5 — docs. README cone diagram now roots honestly at slh_verify_internal and states the pure/prehash domain-separator byte, the ctx>255 check, M' assembly, and deserialization are ABOVE the root and uncovered (new TRUSTED-BASE item 10). The false "rules out a wrong ADRS field" claim is corrected in README + ChainSpec (a transliteration makes the field visible, not excluded). check-selftest.sh: eight attacks, all rejected (dead file; extra axiom; dropped oracle; vanished cert; un-manifested False theorem; gutted statement; hand-edited model; deleted manifest row). Full transcript + green check.sh in verification/RECORDED-RUN.md. Standing limit unchanged and disclosed: an audit cannot defend against an author who edits the manifest AND check.sh AND the proofs together; the consumer defense is the pinned commit reviewed at the pin. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-07-27 17:47:39 +00:00
save Proofs/InputPrepSpec.lean
python3 - <<'PY'
s = open("Proofs/InputPrepSpec.lean").read()
review round 5: bind the policy, the specification bodies, and the harness The third reviewer demonstrated that the round-4 gate was closed at the EXPLOITS, not the MECHANISMS: it bound the manifest rows while the things he moved sat outside the binding. Three fail-opens, each executed end-to-end with the button printing ALL GREEN. No theorem, proof, fold, or model body changed. NEW-1 — the policy constant was unbound. `manifestFingerprint` covered `manifest` but never `allowedBoundary`, the sole predicate the enumeration tests against; adding one name re-opened the False-proof with the committed fingerprint BYTE-IDENTICAL. NEW-2 — the specification bodies were unbound. The statement fingerprint pinned each certificate's TYPE, which names its reference fold; redefining that fold to *be* the extracted loop left cone and type-hash identical while the certificate degenerated to `loop = loop`. 100% of the fidelity content lives in those defs. NEW-3 — the harness was unbound. Stubbing verification/lean-guard alone, without touching check.sh or the proofs, gave ALL GREEN in 3.6s over destroyed proofs. FIX — one mechanism rather than three patches. Audit.lean now emits a canonical AUDIT-MANIFEST block and check.sh binds to its SHA-256. The block covers the POLICY constants, every certificate's fully-elaborated statement, and every specification constant transitively reachable from those statements with its fully-elaborated BODY (41 constants; the closure is computed, so a new fold cannot appear without moving the digest; Prop-valued constants contribute their statement, by proof irrelevance). This also retires the 32-bit Expr.hash as the binding (NEW-5) — it survives only as a per-certificate diagnostic. Enumeration now covers EVERY declaration kind (a `def : False` passed before) in the eight certificate modules AND in Audit.lean itself — the auditor is no longer exempt (round-5 R1). A bare `axiom` in audited scope is now an error. Phase 0 purges stale .olean (the verdict must depend on committed bytes, not .gitignored build state — NEW-4), forbids any .lean outside gen/ and Proofs/, and sha256-pins the four model files AND lean-guard. lean-guard is KEPT rather than removed (the reviewer's portability advice is declined by operator decision): it is the memory cap and machine-wide lock that protect the build machine after a 12.2GB OOM took the host down. That trade-off is documented. check.sh's "Certificates proven:" line now comes from the audited manifest; the hand-kept CERTS array — the one authoritative claim string nothing bound — is deleted. check-selftest.sh: 14 attacks, all rejected, plus a check that the hashed block literally carries the twelve fold bodies. Attacks 9-14 are the reviewers' and an independent drill's own exploits, turned into regression tests. DOCS. TRUSTED-BASE gains item 11 (the REAL trusted computing base — lean-guard pinned; check.sh, the toolchain env, $AENEAS_HOME, python3 and Lean still trusted) and item 12 (the apex does not compose the ten). README: the audit description rewritten; the XMSS sibling-order claim downgraded from "pins" to "makes visible", with a new blanket non-claim covering all ten loop certificates; the de-plumbing file claim corrected (round 1 touched only verify_mono.rs, round 2 only helpers.rs — which is ON the deployed verify AND sign paths, now disclosed; wots.rs was never patched). RECORDED-RUN: three lines that stood inside a fence were a hand-written summary, not console output — fabricated evidence in the file whose purpose is machine evidence. They are removed and the fabrication is named in place, together with the correction that the "INDEPENDENT RUN" block predates this gate. New rule: nothing goes in a fence unless captured with tee/cat, and every block states its date, pin, and who ran it. The transcripts added here follow it. Also disclosed rather than buried: three bugs in my own test harness this round (an olean-purge build-order break, an attack rejected by the wrong rule, and a coverage assertion looking on the wrong line) — each would have let an attack pass or fail for an unrelated reason. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-07-27 20:57:46 +00:00
i = s.index("theorem to_byte_loop_eq (n : Std.U32) (k : Nat) :") # a LEAF cert
j = s.index("theorem hbody_cs", i) # next declaration
open("Proofs/InputPrepSpec.lean","w").write(
s[:i] + "theorem to_byte_loop_eq : (∀ p : Prop, p ¬p) := Classical.em\n\n" + s[j:])
review round 4: bind the cert set, statements, and model bytes (F1/F2/F3) The third reviewer demonstrated that the round-2 in-Lean exact-cone audit, though sound for LISTED certs, left three fail-opens OUTSIDE the cone check — and made check.sh print ALL GREEN over a repo proving False. All closed; no theorem, proof, or fold changed (the 11 cones are unchanged). F1 — the audited SET was unbound. Audit.lean now (a) enumerates EVERY theorem defined in the eight certificate modules and requires each cone ⊆ boundary, so an un-manifested `theorem _ : False := cheat _` fails regardless of naming (this is the exact exploit the reviewer used); and (b) prints a MANIFEST fingerprint over the whole committed manifest, which check.sh binds to — so deleting/swapping a cert row fails outside Lean too. F2 — only cones were bound, not statements. Each cert now also carries the structural fingerprint (Expr.hash) of its elaborated type; a statement gutted to a tautology of the same cone changes the fingerprint and fails. F3 — the gen/ model bytes were unbound. New check.sh Phase 0 sha256-pins all four gen/SlhVerify/*.lean (incl. the two hand-maintained *External files, now hashed in PROVENANCE.json) BEFORE compiling; a hand-edited model fails first. F4/F5 — docs. README cone diagram now roots honestly at slh_verify_internal and states the pure/prehash domain-separator byte, the ctx>255 check, M' assembly, and deserialization are ABOVE the root and uncovered (new TRUSTED-BASE item 10). The false "rules out a wrong ADRS field" claim is corrected in README + ChainSpec (a transliteration makes the field visible, not excluded). check-selftest.sh: eight attacks, all rejected (dead file; extra axiom; dropped oracle; vanished cert; un-manifested False theorem; gutted statement; hand-edited model; deleted manifest row). Full transcript + green check.sh in verification/RECORDED-RUN.md. Standing limit unchanged and disclosed: an audit cannot defend against an author who edits the manifest AND check.sh AND the proofs together; the consumer defense is the pinned commit reviewed at the pin. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-07-27 17:47:39 +00:00
PY
review round 5: bind the policy, the specification bodies, and the harness The third reviewer demonstrated that the round-4 gate was closed at the EXPLOITS, not the MECHANISMS: it bound the manifest rows while the things he moved sat outside the binding. Three fail-opens, each executed end-to-end with the button printing ALL GREEN. No theorem, proof, fold, or model body changed. NEW-1 — the policy constant was unbound. `manifestFingerprint` covered `manifest` but never `allowedBoundary`, the sole predicate the enumeration tests against; adding one name re-opened the False-proof with the committed fingerprint BYTE-IDENTICAL. NEW-2 — the specification bodies were unbound. The statement fingerprint pinned each certificate's TYPE, which names its reference fold; redefining that fold to *be* the extracted loop left cone and type-hash identical while the certificate degenerated to `loop = loop`. 100% of the fidelity content lives in those defs. NEW-3 — the harness was unbound. Stubbing verification/lean-guard alone, without touching check.sh or the proofs, gave ALL GREEN in 3.6s over destroyed proofs. FIX — one mechanism rather than three patches. Audit.lean now emits a canonical AUDIT-MANIFEST block and check.sh binds to its SHA-256. The block covers the POLICY constants, every certificate's fully-elaborated statement, and every specification constant transitively reachable from those statements with its fully-elaborated BODY (41 constants; the closure is computed, so a new fold cannot appear without moving the digest; Prop-valued constants contribute their statement, by proof irrelevance). This also retires the 32-bit Expr.hash as the binding (NEW-5) — it survives only as a per-certificate diagnostic. Enumeration now covers EVERY declaration kind (a `def : False` passed before) in the eight certificate modules AND in Audit.lean itself — the auditor is no longer exempt (round-5 R1). A bare `axiom` in audited scope is now an error. Phase 0 purges stale .olean (the verdict must depend on committed bytes, not .gitignored build state — NEW-4), forbids any .lean outside gen/ and Proofs/, and sha256-pins the four model files AND lean-guard. lean-guard is KEPT rather than removed (the reviewer's portability advice is declined by operator decision): it is the memory cap and machine-wide lock that protect the build machine after a 12.2GB OOM took the host down. That trade-off is documented. check.sh's "Certificates proven:" line now comes from the audited manifest; the hand-kept CERTS array — the one authoritative claim string nothing bound — is deleted. check-selftest.sh: 14 attacks, all rejected, plus a check that the hashed block literally carries the twelve fold bodies. Attacks 9-14 are the reviewers' and an independent drill's own exploits, turned into regression tests. DOCS. TRUSTED-BASE gains item 11 (the REAL trusted computing base — lean-guard pinned; check.sh, the toolchain env, $AENEAS_HOME, python3 and Lean still trusted) and item 12 (the apex does not compose the ten). README: the audit description rewritten; the XMSS sibling-order claim downgraded from "pins" to "makes visible", with a new blanket non-claim covering all ten loop certificates; the de-plumbing file claim corrected (round 1 touched only verify_mono.rs, round 2 only helpers.rs — which is ON the deployed verify AND sign paths, now disclosed; wots.rs was never patched). RECORDED-RUN: three lines that stood inside a fence were a hand-written summary, not console output — fabricated evidence in the file whose purpose is machine evidence. They are removed and the fabrication is named in place, together with the correction that the "INDEPENDENT RUN" block predates this gate. New rule: nothing goes in a fence unless captured with tee/cat, and every block states its date, pin, and who ran it. The transcripts added here follow it. Also disclosed rather than buried: three bugs in my own test harness this round (an olean-purge build-order break, an attack rejected by the wrong rule, and a coverage assertion looking on the wrong line) — each would have let an attack pass or fail for an unrelated reason. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-07-27 20:57:46 +00:00
./check.sh > /tmp/sf6.out 2>&1 && fail "ATTACK 6 SUCCEEDED (gutted statement, cone preserved)" /tmp/sf6.out
grep -q "STATEMENT fingerprint" /tmp/sf6.out || fail "ATTACK 6: rejected but not via the statement check" /tmp/sf6.out
restore
echo "✓ attack 6 rejected (statement check — a gutted statement of the same cone cannot pass)"
review round 4: bind the cert set, statements, and model bytes (F1/F2/F3) The third reviewer demonstrated that the round-2 in-Lean exact-cone audit, though sound for LISTED certs, left three fail-opens OUTSIDE the cone check — and made check.sh print ALL GREEN over a repo proving False. All closed; no theorem, proof, or fold changed (the 11 cones are unchanged). F1 — the audited SET was unbound. Audit.lean now (a) enumerates EVERY theorem defined in the eight certificate modules and requires each cone ⊆ boundary, so an un-manifested `theorem _ : False := cheat _` fails regardless of naming (this is the exact exploit the reviewer used); and (b) prints a MANIFEST fingerprint over the whole committed manifest, which check.sh binds to — so deleting/swapping a cert row fails outside Lean too. F2 — only cones were bound, not statements. Each cert now also carries the structural fingerprint (Expr.hash) of its elaborated type; a statement gutted to a tautology of the same cone changes the fingerprint and fails. F3 — the gen/ model bytes were unbound. New check.sh Phase 0 sha256-pins all four gen/SlhVerify/*.lean (incl. the two hand-maintained *External files, now hashed in PROVENANCE.json) BEFORE compiling; a hand-edited model fails first. F4/F5 — docs. README cone diagram now roots honestly at slh_verify_internal and states the pure/prehash domain-separator byte, the ctx>255 check, M' assembly, and deserialization are ABOVE the root and uncovered (new TRUSTED-BASE item 10). The false "rules out a wrong ADRS field" claim is corrected in README + ChainSpec (a transliteration makes the field visible, not excluded). check-selftest.sh: eight attacks, all rejected (dead file; extra axiom; dropped oracle; vanished cert; un-manifested False theorem; gutted statement; hand-edited model; deleted manifest row). Full transcript + green check.sh in verification/RECORDED-RUN.md. Standing limit unchanged and disclosed: an audit cannot defend against an author who edits the manifest AND check.sh AND the proofs together; the consumer defense is the pinned commit reviewed at the pin. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-07-27 17:47:39 +00:00
review round 5: bind the policy, the specification bodies, and the harness The third reviewer demonstrated that the round-4 gate was closed at the EXPLOITS, not the MECHANISMS: it bound the manifest rows while the things he moved sat outside the binding. Three fail-opens, each executed end-to-end with the button printing ALL GREEN. No theorem, proof, fold, or model body changed. NEW-1 — the policy constant was unbound. `manifestFingerprint` covered `manifest` but never `allowedBoundary`, the sole predicate the enumeration tests against; adding one name re-opened the False-proof with the committed fingerprint BYTE-IDENTICAL. NEW-2 — the specification bodies were unbound. The statement fingerprint pinned each certificate's TYPE, which names its reference fold; redefining that fold to *be* the extracted loop left cone and type-hash identical while the certificate degenerated to `loop = loop`. 100% of the fidelity content lives in those defs. NEW-3 — the harness was unbound. Stubbing verification/lean-guard alone, without touching check.sh or the proofs, gave ALL GREEN in 3.6s over destroyed proofs. FIX — one mechanism rather than three patches. Audit.lean now emits a canonical AUDIT-MANIFEST block and check.sh binds to its SHA-256. The block covers the POLICY constants, every certificate's fully-elaborated statement, and every specification constant transitively reachable from those statements with its fully-elaborated BODY (41 constants; the closure is computed, so a new fold cannot appear without moving the digest; Prop-valued constants contribute their statement, by proof irrelevance). This also retires the 32-bit Expr.hash as the binding (NEW-5) — it survives only as a per-certificate diagnostic. Enumeration now covers EVERY declaration kind (a `def : False` passed before) in the eight certificate modules AND in Audit.lean itself — the auditor is no longer exempt (round-5 R1). A bare `axiom` in audited scope is now an error. Phase 0 purges stale .olean (the verdict must depend on committed bytes, not .gitignored build state — NEW-4), forbids any .lean outside gen/ and Proofs/, and sha256-pins the four model files AND lean-guard. lean-guard is KEPT rather than removed (the reviewer's portability advice is declined by operator decision): it is the memory cap and machine-wide lock that protect the build machine after a 12.2GB OOM took the host down. That trade-off is documented. check.sh's "Certificates proven:" line now comes from the audited manifest; the hand-kept CERTS array — the one authoritative claim string nothing bound — is deleted. check-selftest.sh: 14 attacks, all rejected, plus a check that the hashed block literally carries the twelve fold bodies. Attacks 9-14 are the reviewers' and an independent drill's own exploits, turned into regression tests. DOCS. TRUSTED-BASE gains item 11 (the REAL trusted computing base — lean-guard pinned; check.sh, the toolchain env, $AENEAS_HOME, python3 and Lean still trusted) and item 12 (the apex does not compose the ten). README: the audit description rewritten; the XMSS sibling-order claim downgraded from "pins" to "makes visible", with a new blanket non-claim covering all ten loop certificates; the de-plumbing file claim corrected (round 1 touched only verify_mono.rs, round 2 only helpers.rs — which is ON the deployed verify AND sign paths, now disclosed; wots.rs was never patched). RECORDED-RUN: three lines that stood inside a fence were a hand-written summary, not console output — fabricated evidence in the file whose purpose is machine evidence. They are removed and the fabrication is named in place, together with the correction that the "INDEPENDENT RUN" block predates this gate. New rule: nothing goes in a fence unless captured with tee/cat, and every block states its date, pin, and who ran it. The transcripts added here follow it. Also disclosed rather than buried: three bugs in my own test harness this round (an olean-purge build-order break, an attack rejected by the wrong rule, and a coverage assertion looking on the wrong line) — each would have let an attack pass or fail for an unrelated reason. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-07-27 20:57:46 +00:00
# ── 7: hand-edited model file (round-4 F3) ──────────────────────────────────
review round 4: bind the cert set, statements, and model bytes (F1/F2/F3) The third reviewer demonstrated that the round-2 in-Lean exact-cone audit, though sound for LISTED certs, left three fail-opens OUTSIDE the cone check — and made check.sh print ALL GREEN over a repo proving False. All closed; no theorem, proof, or fold changed (the 11 cones are unchanged). F1 — the audited SET was unbound. Audit.lean now (a) enumerates EVERY theorem defined in the eight certificate modules and requires each cone ⊆ boundary, so an un-manifested `theorem _ : False := cheat _` fails regardless of naming (this is the exact exploit the reviewer used); and (b) prints a MANIFEST fingerprint over the whole committed manifest, which check.sh binds to — so deleting/swapping a cert row fails outside Lean too. F2 — only cones were bound, not statements. Each cert now also carries the structural fingerprint (Expr.hash) of its elaborated type; a statement gutted to a tautology of the same cone changes the fingerprint and fails. F3 — the gen/ model bytes were unbound. New check.sh Phase 0 sha256-pins all four gen/SlhVerify/*.lean (incl. the two hand-maintained *External files, now hashed in PROVENANCE.json) BEFORE compiling; a hand-edited model fails first. F4/F5 — docs. README cone diagram now roots honestly at slh_verify_internal and states the pure/prehash domain-separator byte, the ctx>255 check, M' assembly, and deserialization are ABOVE the root and uncovered (new TRUSTED-BASE item 10). The false "rules out a wrong ADRS field" claim is corrected in README + ChainSpec (a transliteration makes the field visible, not excluded). check-selftest.sh: eight attacks, all rejected (dead file; extra axiom; dropped oracle; vanished cert; un-manifested False theorem; gutted statement; hand-edited model; deleted manifest row). Full transcript + green check.sh in verification/RECORDED-RUN.md. Standing limit unchanged and disclosed: an audit cannot defend against an author who edits the manifest AND check.sh AND the proofs together; the consumer defense is the pinned commit reviewed at the pin. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-07-27 17:47:39 +00:00
save gen/SlhVerify/Funs.lean
review round 5: bind the policy, the specification bodies, and the harness The third reviewer demonstrated that the round-4 gate was closed at the EXPLOITS, not the MECHANISMS: it bound the manifest rows while the things he moved sat outside the binding. Three fail-opens, each executed end-to-end with the button printing ALL GREEN. No theorem, proof, fold, or model body changed. NEW-1 — the policy constant was unbound. `manifestFingerprint` covered `manifest` but never `allowedBoundary`, the sole predicate the enumeration tests against; adding one name re-opened the False-proof with the committed fingerprint BYTE-IDENTICAL. NEW-2 — the specification bodies were unbound. The statement fingerprint pinned each certificate's TYPE, which names its reference fold; redefining that fold to *be* the extracted loop left cone and type-hash identical while the certificate degenerated to `loop = loop`. 100% of the fidelity content lives in those defs. NEW-3 — the harness was unbound. Stubbing verification/lean-guard alone, without touching check.sh or the proofs, gave ALL GREEN in 3.6s over destroyed proofs. FIX — one mechanism rather than three patches. Audit.lean now emits a canonical AUDIT-MANIFEST block and check.sh binds to its SHA-256. The block covers the POLICY constants, every certificate's fully-elaborated statement, and every specification constant transitively reachable from those statements with its fully-elaborated BODY (41 constants; the closure is computed, so a new fold cannot appear without moving the digest; Prop-valued constants contribute their statement, by proof irrelevance). This also retires the 32-bit Expr.hash as the binding (NEW-5) — it survives only as a per-certificate diagnostic. Enumeration now covers EVERY declaration kind (a `def : False` passed before) in the eight certificate modules AND in Audit.lean itself — the auditor is no longer exempt (round-5 R1). A bare `axiom` in audited scope is now an error. Phase 0 purges stale .olean (the verdict must depend on committed bytes, not .gitignored build state — NEW-4), forbids any .lean outside gen/ and Proofs/, and sha256-pins the four model files AND lean-guard. lean-guard is KEPT rather than removed (the reviewer's portability advice is declined by operator decision): it is the memory cap and machine-wide lock that protect the build machine after a 12.2GB OOM took the host down. That trade-off is documented. check.sh's "Certificates proven:" line now comes from the audited manifest; the hand-kept CERTS array — the one authoritative claim string nothing bound — is deleted. check-selftest.sh: 14 attacks, all rejected, plus a check that the hashed block literally carries the twelve fold bodies. Attacks 9-14 are the reviewers' and an independent drill's own exploits, turned into regression tests. DOCS. TRUSTED-BASE gains item 11 (the REAL trusted computing base — lean-guard pinned; check.sh, the toolchain env, $AENEAS_HOME, python3 and Lean still trusted) and item 12 (the apex does not compose the ten). README: the audit description rewritten; the XMSS sibling-order claim downgraded from "pins" to "makes visible", with a new blanket non-claim covering all ten loop certificates; the de-plumbing file claim corrected (round 1 touched only verify_mono.rs, round 2 only helpers.rs — which is ON the deployed verify AND sign paths, now disclosed; wots.rs was never patched). RECORDED-RUN: three lines that stood inside a fence were a hand-written summary, not console output — fabricated evidence in the file whose purpose is machine evidence. They are removed and the fabrication is named in place, together with the correction that the "INDEPENDENT RUN" block predates this gate. New rule: nothing goes in a fence unless captured with tee/cat, and every block states its date, pin, and who ran it. The transcripts added here follow it. Also disclosed rather than buried: three bugs in my own test harness this round (an olean-purge build-order break, an attack rejected by the wrong rule, and a coverage assertion looking on the wrong line) — each would have let an attack pass or fail for an unrelated reason. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-07-27 20:57:46 +00:00
printf '\n-- SELFTEST ATTACK 7\n' >> gen/SlhVerify/Funs.lean
./check.sh > /tmp/sf7.out 2>&1 && fail "ATTACK 7 SUCCEEDED (hand-edited model passed)" /tmp/sf7.out
grep -q "INTEGRITY FAILED" /tmp/sf7.out || fail "ATTACK 7: rejected but not via Phase 0" /tmp/sf7.out
review round 4: bind the cert set, statements, and model bytes (F1/F2/F3) The third reviewer demonstrated that the round-2 in-Lean exact-cone audit, though sound for LISTED certs, left three fail-opens OUTSIDE the cone check — and made check.sh print ALL GREEN over a repo proving False. All closed; no theorem, proof, or fold changed (the 11 cones are unchanged). F1 — the audited SET was unbound. Audit.lean now (a) enumerates EVERY theorem defined in the eight certificate modules and requires each cone ⊆ boundary, so an un-manifested `theorem _ : False := cheat _` fails regardless of naming (this is the exact exploit the reviewer used); and (b) prints a MANIFEST fingerprint over the whole committed manifest, which check.sh binds to — so deleting/swapping a cert row fails outside Lean too. F2 — only cones were bound, not statements. Each cert now also carries the structural fingerprint (Expr.hash) of its elaborated type; a statement gutted to a tautology of the same cone changes the fingerprint and fails. F3 — the gen/ model bytes were unbound. New check.sh Phase 0 sha256-pins all four gen/SlhVerify/*.lean (incl. the two hand-maintained *External files, now hashed in PROVENANCE.json) BEFORE compiling; a hand-edited model fails first. F4/F5 — docs. README cone diagram now roots honestly at slh_verify_internal and states the pure/prehash domain-separator byte, the ctx>255 check, M' assembly, and deserialization are ABOVE the root and uncovered (new TRUSTED-BASE item 10). The false "rules out a wrong ADRS field" claim is corrected in README + ChainSpec (a transliteration makes the field visible, not excluded). check-selftest.sh: eight attacks, all rejected (dead file; extra axiom; dropped oracle; vanished cert; un-manifested False theorem; gutted statement; hand-edited model; deleted manifest row). Full transcript + green check.sh in verification/RECORDED-RUN.md. Standing limit unchanged and disclosed: an audit cannot defend against an author who edits the manifest AND check.sh AND the proofs together; the consumer defense is the pinned commit reviewed at the pin. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-07-27 17:47:39 +00:00
restore
review round 5: bind the policy, the specification bodies, and the harness The third reviewer demonstrated that the round-4 gate was closed at the EXPLOITS, not the MECHANISMS: it bound the manifest rows while the things he moved sat outside the binding. Three fail-opens, each executed end-to-end with the button printing ALL GREEN. No theorem, proof, fold, or model body changed. NEW-1 — the policy constant was unbound. `manifestFingerprint` covered `manifest` but never `allowedBoundary`, the sole predicate the enumeration tests against; adding one name re-opened the False-proof with the committed fingerprint BYTE-IDENTICAL. NEW-2 — the specification bodies were unbound. The statement fingerprint pinned each certificate's TYPE, which names its reference fold; redefining that fold to *be* the extracted loop left cone and type-hash identical while the certificate degenerated to `loop = loop`. 100% of the fidelity content lives in those defs. NEW-3 — the harness was unbound. Stubbing verification/lean-guard alone, without touching check.sh or the proofs, gave ALL GREEN in 3.6s over destroyed proofs. FIX — one mechanism rather than three patches. Audit.lean now emits a canonical AUDIT-MANIFEST block and check.sh binds to its SHA-256. The block covers the POLICY constants, every certificate's fully-elaborated statement, and every specification constant transitively reachable from those statements with its fully-elaborated BODY (41 constants; the closure is computed, so a new fold cannot appear without moving the digest; Prop-valued constants contribute their statement, by proof irrelevance). This also retires the 32-bit Expr.hash as the binding (NEW-5) — it survives only as a per-certificate diagnostic. Enumeration now covers EVERY declaration kind (a `def : False` passed before) in the eight certificate modules AND in Audit.lean itself — the auditor is no longer exempt (round-5 R1). A bare `axiom` in audited scope is now an error. Phase 0 purges stale .olean (the verdict must depend on committed bytes, not .gitignored build state — NEW-4), forbids any .lean outside gen/ and Proofs/, and sha256-pins the four model files AND lean-guard. lean-guard is KEPT rather than removed (the reviewer's portability advice is declined by operator decision): it is the memory cap and machine-wide lock that protect the build machine after a 12.2GB OOM took the host down. That trade-off is documented. check.sh's "Certificates proven:" line now comes from the audited manifest; the hand-kept CERTS array — the one authoritative claim string nothing bound — is deleted. check-selftest.sh: 14 attacks, all rejected, plus a check that the hashed block literally carries the twelve fold bodies. Attacks 9-14 are the reviewers' and an independent drill's own exploits, turned into regression tests. DOCS. TRUSTED-BASE gains item 11 (the REAL trusted computing base — lean-guard pinned; check.sh, the toolchain env, $AENEAS_HOME, python3 and Lean still trusted) and item 12 (the apex does not compose the ten). README: the audit description rewritten; the XMSS sibling-order claim downgraded from "pins" to "makes visible", with a new blanket non-claim covering all ten loop certificates; the de-plumbing file claim corrected (round 1 touched only verify_mono.rs, round 2 only helpers.rs — which is ON the deployed verify AND sign paths, now disclosed; wots.rs was never patched). RECORDED-RUN: three lines that stood inside a fence were a hand-written summary, not console output — fabricated evidence in the file whose purpose is machine evidence. They are removed and the fabrication is named in place, together with the correction that the "INDEPENDENT RUN" block predates this gate. New rule: nothing goes in a fence unless captured with tee/cat, and every block states its date, pin, and who ran it. The transcripts added here follow it. Also disclosed rather than buried: three bugs in my own test harness this round (an olean-purge build-order break, an attack rejected by the wrong rule, and a coverage assertion looking on the wrong line) — each would have let an attack pass or fail for an unrelated reason. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-07-27 20:57:46 +00:00
echo "✓ attack 7 rejected (Phase 0 model-byte integrity)"
review round 4: bind the cert set, statements, and model bytes (F1/F2/F3) The third reviewer demonstrated that the round-2 in-Lean exact-cone audit, though sound for LISTED certs, left three fail-opens OUTSIDE the cone check — and made check.sh print ALL GREEN over a repo proving False. All closed; no theorem, proof, or fold changed (the 11 cones are unchanged). F1 — the audited SET was unbound. Audit.lean now (a) enumerates EVERY theorem defined in the eight certificate modules and requires each cone ⊆ boundary, so an un-manifested `theorem _ : False := cheat _` fails regardless of naming (this is the exact exploit the reviewer used); and (b) prints a MANIFEST fingerprint over the whole committed manifest, which check.sh binds to — so deleting/swapping a cert row fails outside Lean too. F2 — only cones were bound, not statements. Each cert now also carries the structural fingerprint (Expr.hash) of its elaborated type; a statement gutted to a tautology of the same cone changes the fingerprint and fails. F3 — the gen/ model bytes were unbound. New check.sh Phase 0 sha256-pins all four gen/SlhVerify/*.lean (incl. the two hand-maintained *External files, now hashed in PROVENANCE.json) BEFORE compiling; a hand-edited model fails first. F4/F5 — docs. README cone diagram now roots honestly at slh_verify_internal and states the pure/prehash domain-separator byte, the ctx>255 check, M' assembly, and deserialization are ABOVE the root and uncovered (new TRUSTED-BASE item 10). The false "rules out a wrong ADRS field" claim is corrected in README + ChainSpec (a transliteration makes the field visible, not excluded). check-selftest.sh: eight attacks, all rejected (dead file; extra axiom; dropped oracle; vanished cert; un-manifested False theorem; gutted statement; hand-edited model; deleted manifest row). Full transcript + green check.sh in verification/RECORDED-RUN.md. Standing limit unchanged and disclosed: an audit cannot defend against an author who edits the manifest AND check.sh AND the proofs together; the consumer defense is the pinned commit reviewed at the pin. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-07-27 17:47:39 +00:00
review round 5: bind the policy, the specification bodies, and the harness The third reviewer demonstrated that the round-4 gate was closed at the EXPLOITS, not the MECHANISMS: it bound the manifest rows while the things he moved sat outside the binding. Three fail-opens, each executed end-to-end with the button printing ALL GREEN. No theorem, proof, fold, or model body changed. NEW-1 — the policy constant was unbound. `manifestFingerprint` covered `manifest` but never `allowedBoundary`, the sole predicate the enumeration tests against; adding one name re-opened the False-proof with the committed fingerprint BYTE-IDENTICAL. NEW-2 — the specification bodies were unbound. The statement fingerprint pinned each certificate's TYPE, which names its reference fold; redefining that fold to *be* the extracted loop left cone and type-hash identical while the certificate degenerated to `loop = loop`. 100% of the fidelity content lives in those defs. NEW-3 — the harness was unbound. Stubbing verification/lean-guard alone, without touching check.sh or the proofs, gave ALL GREEN in 3.6s over destroyed proofs. FIX — one mechanism rather than three patches. Audit.lean now emits a canonical AUDIT-MANIFEST block and check.sh binds to its SHA-256. The block covers the POLICY constants, every certificate's fully-elaborated statement, and every specification constant transitively reachable from those statements with its fully-elaborated BODY (41 constants; the closure is computed, so a new fold cannot appear without moving the digest; Prop-valued constants contribute their statement, by proof irrelevance). This also retires the 32-bit Expr.hash as the binding (NEW-5) — it survives only as a per-certificate diagnostic. Enumeration now covers EVERY declaration kind (a `def : False` passed before) in the eight certificate modules AND in Audit.lean itself — the auditor is no longer exempt (round-5 R1). A bare `axiom` in audited scope is now an error. Phase 0 purges stale .olean (the verdict must depend on committed bytes, not .gitignored build state — NEW-4), forbids any .lean outside gen/ and Proofs/, and sha256-pins the four model files AND lean-guard. lean-guard is KEPT rather than removed (the reviewer's portability advice is declined by operator decision): it is the memory cap and machine-wide lock that protect the build machine after a 12.2GB OOM took the host down. That trade-off is documented. check.sh's "Certificates proven:" line now comes from the audited manifest; the hand-kept CERTS array — the one authoritative claim string nothing bound — is deleted. check-selftest.sh: 14 attacks, all rejected, plus a check that the hashed block literally carries the twelve fold bodies. Attacks 9-14 are the reviewers' and an independent drill's own exploits, turned into regression tests. DOCS. TRUSTED-BASE gains item 11 (the REAL trusted computing base — lean-guard pinned; check.sh, the toolchain env, $AENEAS_HOME, python3 and Lean still trusted) and item 12 (the apex does not compose the ten). README: the audit description rewritten; the XMSS sibling-order claim downgraded from "pins" to "makes visible", with a new blanket non-claim covering all ten loop certificates; the de-plumbing file claim corrected (round 1 touched only verify_mono.rs, round 2 only helpers.rs — which is ON the deployed verify AND sign paths, now disclosed; wots.rs was never patched). RECORDED-RUN: three lines that stood inside a fence were a hand-written summary, not console output — fabricated evidence in the file whose purpose is machine evidence. They are removed and the fabrication is named in place, together with the correction that the "INDEPENDENT RUN" block predates this gate. New rule: nothing goes in a fence unless captured with tee/cat, and every block states its date, pin, and who ran it. The transcripts added here follow it. Also disclosed rather than buried: three bugs in my own test harness this round (an olean-purge build-order break, an attack rejected by the wrong rule, and a coverage assertion looking on the wrong line) — each would have let an attack pass or fail for an unrelated reason. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-07-27 20:57:46 +00:00
# ── 8: deleted manifest row (round-4 F1, set half) ──────────────────────────
review round 6: pin the auditor, purge every olean, pin gen/ as a set Round 6 confirmed the digest redesign closed NEW-1/NEW-2/NEW-5 at the mechanism ("the first time in three rounds I have not been able to gut a certificate"), then demonstrated two more ways to reach ALL GREEN with the committed digest BYTE-IDENTICAL over a repository proving False. Both are fixed. NEW-7 — the digest bound the audit's DATA, never its LOGIC. Flipping the two fail-closed guards in Proofs/Audit.lean to `unless true` disabled every in-Lean check; the block's inputs genuinely had not changed, so the digest still matched. Total attacker diff: 2 files, 6 insertions. Worse, TRUSTED-BASE item 11 listed the trusted-unbound set and did NOT mention Audit.lean, so a reviewer using it as a map of what to read by hand would have skipped the file that computes the number it is judged by. FIX: Proofs/Audit.lean is now sha256-pinned in harness_integrity_sha256, symmetric with lean-guard, and item 11 says so — including the honest residue: an author who edits the logic AND rotates its pin is caught only by reading the diff at the pin. NEW-8 — Phase 0's purge covered gen/ and Proofs/ while the stray check greped only *.lean, so an ORPHAN verification/Evil.olean whose source had been DELETED fell between them, satisfied an import, and was invisible to git status (*.olean is gitignored). FIX: purge every .olean under verification/, and forbid stray .lean AND .olean. NEW-9 (partial) — gen/ was pinned by four NAMES, not as a SET, so a new file there was neither hashed nor forbidden while LEAN_PATH contains $PWD/gen. FIX: Phase 0 asserts the gen/*.lean file set equals the pin map exactly. This found a real gap on its first run: Aeneas emits *_Template.lean scaffolding into gen/ on every extraction — untracked byproducts (a fresh clone has only the four pinned files) that nothing imports but that sat on LEAN_PATH unpinned. They are now purged as byproducts before the set assertion. Also, from the reviewer's §3 suggestion: the canonical block is now COMMITTED as verification/AUDIT-MANIFEST.txt, so a digest mismatch prints a real diff instead of writing an observed file with nothing to compare against; check.sh also fails if the committed copy drifts from what Lean emits. check-selftest.sh: 16 attacks, all rejected, plus the coverage check. Attacks 16 and 17 are the reviewer's two demonstrations. Attacks that mutate the audit's DATA now re-pin Audit.lean first, so they still test the digest/enumeration rather than being stopped by the byte pin; attack 17 deliberately does not re-pin, because the pin is what it tests. Housekeeping: PROVENANCE.json trailing newline restored (NEW-12). Disclosed rather than buried: two more of my own assertion bugs this round — attack 16 asserted the hygiene message when the correct rejection is the purge plus a failed import, and the earlier gen/ set check surfaced the template files only because it was written strictly. Both are the wrong-diagnostic class. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-07-28 07:22:12 +00:00
save Proofs/Audit.lean; save PROVENANCE.json
review round 4: bind the cert set, statements, and model bytes (F1/F2/F3) The third reviewer demonstrated that the round-2 in-Lean exact-cone audit, though sound for LISTED certs, left three fail-opens OUTSIDE the cone check — and made check.sh print ALL GREEN over a repo proving False. All closed; no theorem, proof, or fold changed (the 11 cones are unchanged). F1 — the audited SET was unbound. Audit.lean now (a) enumerates EVERY theorem defined in the eight certificate modules and requires each cone ⊆ boundary, so an un-manifested `theorem _ : False := cheat _` fails regardless of naming (this is the exact exploit the reviewer used); and (b) prints a MANIFEST fingerprint over the whole committed manifest, which check.sh binds to — so deleting/swapping a cert row fails outside Lean too. F2 — only cones were bound, not statements. Each cert now also carries the structural fingerprint (Expr.hash) of its elaborated type; a statement gutted to a tautology of the same cone changes the fingerprint and fails. F3 — the gen/ model bytes were unbound. New check.sh Phase 0 sha256-pins all four gen/SlhVerify/*.lean (incl. the two hand-maintained *External files, now hashed in PROVENANCE.json) BEFORE compiling; a hand-edited model fails first. F4/F5 — docs. README cone diagram now roots honestly at slh_verify_internal and states the pure/prehash domain-separator byte, the ctx>255 check, M' assembly, and deserialization are ABOVE the root and uncovered (new TRUSTED-BASE item 10). The false "rules out a wrong ADRS field" claim is corrected in README + ChainSpec (a transliteration makes the field visible, not excluded). check-selftest.sh: eight attacks, all rejected (dead file; extra axiom; dropped oracle; vanished cert; un-manifested False theorem; gutted statement; hand-edited model; deleted manifest row). Full transcript + green check.sh in verification/RECORDED-RUN.md. Standing limit unchanged and disclosed: an audit cannot defend against an author who edits the manifest AND check.sh AND the proofs together; the consumer defense is the pinned commit reviewed at the pin. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-07-27 17:47:39 +00:00
python3 - <<'PY'
import re
a = open("Proofs/Audit.lean").read()
review round 5: bind the policy, the specification bodies, and the harness The third reviewer demonstrated that the round-4 gate was closed at the EXPLOITS, not the MECHANISMS: it bound the manifest rows while the things he moved sat outside the binding. Three fail-opens, each executed end-to-end with the button printing ALL GREEN. No theorem, proof, fold, or model body changed. NEW-1 — the policy constant was unbound. `manifestFingerprint` covered `manifest` but never `allowedBoundary`, the sole predicate the enumeration tests against; adding one name re-opened the False-proof with the committed fingerprint BYTE-IDENTICAL. NEW-2 — the specification bodies were unbound. The statement fingerprint pinned each certificate's TYPE, which names its reference fold; redefining that fold to *be* the extracted loop left cone and type-hash identical while the certificate degenerated to `loop = loop`. 100% of the fidelity content lives in those defs. NEW-3 — the harness was unbound. Stubbing verification/lean-guard alone, without touching check.sh or the proofs, gave ALL GREEN in 3.6s over destroyed proofs. FIX — one mechanism rather than three patches. Audit.lean now emits a canonical AUDIT-MANIFEST block and check.sh binds to its SHA-256. The block covers the POLICY constants, every certificate's fully-elaborated statement, and every specification constant transitively reachable from those statements with its fully-elaborated BODY (41 constants; the closure is computed, so a new fold cannot appear without moving the digest; Prop-valued constants contribute their statement, by proof irrelevance). This also retires the 32-bit Expr.hash as the binding (NEW-5) — it survives only as a per-certificate diagnostic. Enumeration now covers EVERY declaration kind (a `def : False` passed before) in the eight certificate modules AND in Audit.lean itself — the auditor is no longer exempt (round-5 R1). A bare `axiom` in audited scope is now an error. Phase 0 purges stale .olean (the verdict must depend on committed bytes, not .gitignored build state — NEW-4), forbids any .lean outside gen/ and Proofs/, and sha256-pins the four model files AND lean-guard. lean-guard is KEPT rather than removed (the reviewer's portability advice is declined by operator decision): it is the memory cap and machine-wide lock that protect the build machine after a 12.2GB OOM took the host down. That trade-off is documented. check.sh's "Certificates proven:" line now comes from the audited manifest; the hand-kept CERTS array — the one authoritative claim string nothing bound — is deleted. check-selftest.sh: 14 attacks, all rejected, plus a check that the hashed block literally carries the twelve fold bodies. Attacks 9-14 are the reviewers' and an independent drill's own exploits, turned into regression tests. DOCS. TRUSTED-BASE gains item 11 (the REAL trusted computing base — lean-guard pinned; check.sh, the toolchain env, $AENEAS_HOME, python3 and Lean still trusted) and item 12 (the apex does not compose the ten). README: the audit description rewritten; the XMSS sibling-order claim downgraded from "pins" to "makes visible", with a new blanket non-claim covering all ten loop certificates; the de-plumbing file claim corrected (round 1 touched only verify_mono.rs, round 2 only helpers.rs — which is ON the deployed verify AND sign paths, now disclosed; wots.rs was never patched). RECORDED-RUN: three lines that stood inside a fence were a hand-written summary, not console output — fabricated evidence in the file whose purpose is machine evidence. They are removed and the fabrication is named in place, together with the correction that the "INDEPENDENT RUN" block predates this gate. New rule: nothing goes in a fence unless captured with tee/cat, and every block states its date, pin, and who ran it. The transcripts added here follow it. Also disclosed rather than buried: three bugs in my own test harness this round (an olean-purge build-order break, an attack rejected by the wrong rule, and a coverage assertion looking on the wrong line) — each would have let an attack pass or fail for an unrelated reason. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-07-27 20:57:46 +00:00
new, n = re.subn(r'\n\s*\(`fips205\.to_int_loop_eq,.*?\),', '', a)
assert n == 1, f"expected 1 row, removed {n}"
review round 4: bind the cert set, statements, and model bytes (F1/F2/F3) The third reviewer demonstrated that the round-2 in-Lean exact-cone audit, though sound for LISTED certs, left three fail-opens OUTSIDE the cone check — and made check.sh print ALL GREEN over a repo proving False. All closed; no theorem, proof, or fold changed (the 11 cones are unchanged). F1 — the audited SET was unbound. Audit.lean now (a) enumerates EVERY theorem defined in the eight certificate modules and requires each cone ⊆ boundary, so an un-manifested `theorem _ : False := cheat _` fails regardless of naming (this is the exact exploit the reviewer used); and (b) prints a MANIFEST fingerprint over the whole committed manifest, which check.sh binds to — so deleting/swapping a cert row fails outside Lean too. F2 — only cones were bound, not statements. Each cert now also carries the structural fingerprint (Expr.hash) of its elaborated type; a statement gutted to a tautology of the same cone changes the fingerprint and fails. F3 — the gen/ model bytes were unbound. New check.sh Phase 0 sha256-pins all four gen/SlhVerify/*.lean (incl. the two hand-maintained *External files, now hashed in PROVENANCE.json) BEFORE compiling; a hand-edited model fails first. F4/F5 — docs. README cone diagram now roots honestly at slh_verify_internal and states the pure/prehash domain-separator byte, the ctx>255 check, M' assembly, and deserialization are ABOVE the root and uncovered (new TRUSTED-BASE item 10). The false "rules out a wrong ADRS field" claim is corrected in README + ChainSpec (a transliteration makes the field visible, not excluded). check-selftest.sh: eight attacks, all rejected (dead file; extra axiom; dropped oracle; vanished cert; un-manifested False theorem; gutted statement; hand-edited model; deleted manifest row). Full transcript + green check.sh in verification/RECORDED-RUN.md. Standing limit unchanged and disclosed: an audit cannot defend against an author who edits the manifest AND check.sh AND the proofs together; the consumer defense is the pinned commit reviewed at the pin. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-07-27 17:47:39 +00:00
open("Proofs/Audit.lean","w").write(new)
review round 1: fix the fail-open audit gate + remove the overclaimed framing External review (both standing reviewers, 2026-07-24) returned DO NOT ATTEST. The eleven Lean theorems compile with genuinely clean cones (both reviewers independently reconstructed them), but two real defects were found and are fixed here. FIX 1 — the axiom audit was FAIL-OPEN (the critical blocker). check.sh Phase 3 grepped a single physical line of each `#print axioms` report; Lean WRAPS long cones across lines, so for ht/fors_outer/APEX the audit checked only `[propext,` and silently ignored the continuation lines — a disallowed axiom on line 2+ passed (the GPT reviewer demonstrated `review_evil_ax` passing). Since check.sh is the sole source of the word "proven", this is unacceptable. - New parser: FLATTEN the whole report (join newlines) BEFORE parsing, then extract each certificate's complete bracketed cone with a literal-string (regex-safe) scan and subset-check every axiom. Missing/empty report => FAIL CLOSED. The audit now prints the count of axioms actually audited per cert (apex: 8, previously 1). - check-selftest.sh gains ATTACK 3: a smuggled axiom bundled with the apex so its cone WRAPS with the evil axiom on a continuation line — the exact exploit. Verified: all three attacks now rejected, attack 3 via the axiom gate naming the continuation-line axiom. (Also fixed attack 2's leftover EvilSpec.lean tripping attack 3's dead-file gate.) FIX 2 — remove the overclaimed framing (refuted by both reviewers). Corrected in README, the ApexSpec header + apex docstring, and (separately) the control MANIFEST: - "composes all ten loop-fidelity certificates" — FALSE. The apex proof is a STRUCTURAL FACTORIZATION; it references NONE of the ten (grep: 0) and would remain provable if one were deleted. They are independent local-fidelity lemmas, not links in the apex proof. - "every loop is individually fidelity-certified" — FALSE. base_2b's inner accumulation loop is threaded opaquely and uncertified — and it determines the FORS indices / WOTS digits, so a defect there could change the recomputed root while all eleven theorems still hold. - "the deployed verifier" — the proved subject is verify_mono, a private #![allow(dead_code)] monomorphic facade NOT called by the public API; the bridge to the deployed generic verifier is the finite differential test, not a machine-checked refinement. - "verify-path pyramid complete" — replaced with "intermediate verification layer"; the apex is an ACCEPTANCE CHARACTERIZATION, not closed-form FIPS-205 correctness. Also: FunsExternal header noted the Take axiom "remains" (stale — deleted in de-plumbing round 2); corrected. check.sh green over all eleven certificates under the fixed fail-closed parser (exit 0, 8 axioms audited for the apex). Nothing about the theorems changed — they were and are sound; only the audit tool and the claims about them are fixed. NOT DONE (remaining reviewer blockers, tracked): reproducible extract tuple (pin commits, de-hard-code extract.sh) + Cargo.lock / toolchain pin. Attestation remains gated behind review round 2 + the operator halt + the appeal. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-24 14:55:10 +00:00
PY
review round 6: pin the auditor, purge every olean, pin gen/ as a set Round 6 confirmed the digest redesign closed NEW-1/NEW-2/NEW-5 at the mechanism ("the first time in three rounds I have not been able to gut a certificate"), then demonstrated two more ways to reach ALL GREEN with the committed digest BYTE-IDENTICAL over a repository proving False. Both are fixed. NEW-7 — the digest bound the audit's DATA, never its LOGIC. Flipping the two fail-closed guards in Proofs/Audit.lean to `unless true` disabled every in-Lean check; the block's inputs genuinely had not changed, so the digest still matched. Total attacker diff: 2 files, 6 insertions. Worse, TRUSTED-BASE item 11 listed the trusted-unbound set and did NOT mention Audit.lean, so a reviewer using it as a map of what to read by hand would have skipped the file that computes the number it is judged by. FIX: Proofs/Audit.lean is now sha256-pinned in harness_integrity_sha256, symmetric with lean-guard, and item 11 says so — including the honest residue: an author who edits the logic AND rotates its pin is caught only by reading the diff at the pin. NEW-8 — Phase 0's purge covered gen/ and Proofs/ while the stray check greped only *.lean, so an ORPHAN verification/Evil.olean whose source had been DELETED fell between them, satisfied an import, and was invisible to git status (*.olean is gitignored). FIX: purge every .olean under verification/, and forbid stray .lean AND .olean. NEW-9 (partial) — gen/ was pinned by four NAMES, not as a SET, so a new file there was neither hashed nor forbidden while LEAN_PATH contains $PWD/gen. FIX: Phase 0 asserts the gen/*.lean file set equals the pin map exactly. This found a real gap on its first run: Aeneas emits *_Template.lean scaffolding into gen/ on every extraction — untracked byproducts (a fresh clone has only the four pinned files) that nothing imports but that sat on LEAN_PATH unpinned. They are now purged as byproducts before the set assertion. Also, from the reviewer's §3 suggestion: the canonical block is now COMMITTED as verification/AUDIT-MANIFEST.txt, so a digest mismatch prints a real diff instead of writing an observed file with nothing to compare against; check.sh also fails if the committed copy drifts from what Lean emits. check-selftest.sh: 16 attacks, all rejected, plus the coverage check. Attacks 16 and 17 are the reviewer's two demonstrations. Attacks that mutate the audit's DATA now re-pin Audit.lean first, so they still test the digest/enumeration rather than being stopped by the byte pin; attack 17 deliberately does not re-pin, because the pin is what it tests. Housekeeping: PROVENANCE.json trailing newline restored (NEW-12). Disclosed rather than buried: two more of my own assertion bugs this round — attack 16 asserted the hygiene message when the correct rejection is the purge plus a failed import, and the earlier gen/ set check surfaced the template files only because it was written strictly. Both are the wrong-diagnostic class. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-07-28 07:22:12 +00:00
repin_audit
review round 5: bind the policy, the specification bodies, and the harness The third reviewer demonstrated that the round-4 gate was closed at the EXPLOITS, not the MECHANISMS: it bound the manifest rows while the things he moved sat outside the binding. Three fail-opens, each executed end-to-end with the button printing ALL GREEN. No theorem, proof, fold, or model body changed. NEW-1 — the policy constant was unbound. `manifestFingerprint` covered `manifest` but never `allowedBoundary`, the sole predicate the enumeration tests against; adding one name re-opened the False-proof with the committed fingerprint BYTE-IDENTICAL. NEW-2 — the specification bodies were unbound. The statement fingerprint pinned each certificate's TYPE, which names its reference fold; redefining that fold to *be* the extracted loop left cone and type-hash identical while the certificate degenerated to `loop = loop`. 100% of the fidelity content lives in those defs. NEW-3 — the harness was unbound. Stubbing verification/lean-guard alone, without touching check.sh or the proofs, gave ALL GREEN in 3.6s over destroyed proofs. FIX — one mechanism rather than three patches. Audit.lean now emits a canonical AUDIT-MANIFEST block and check.sh binds to its SHA-256. The block covers the POLICY constants, every certificate's fully-elaborated statement, and every specification constant transitively reachable from those statements with its fully-elaborated BODY (41 constants; the closure is computed, so a new fold cannot appear without moving the digest; Prop-valued constants contribute their statement, by proof irrelevance). This also retires the 32-bit Expr.hash as the binding (NEW-5) — it survives only as a per-certificate diagnostic. Enumeration now covers EVERY declaration kind (a `def : False` passed before) in the eight certificate modules AND in Audit.lean itself — the auditor is no longer exempt (round-5 R1). A bare `axiom` in audited scope is now an error. Phase 0 purges stale .olean (the verdict must depend on committed bytes, not .gitignored build state — NEW-4), forbids any .lean outside gen/ and Proofs/, and sha256-pins the four model files AND lean-guard. lean-guard is KEPT rather than removed (the reviewer's portability advice is declined by operator decision): it is the memory cap and machine-wide lock that protect the build machine after a 12.2GB OOM took the host down. That trade-off is documented. check.sh's "Certificates proven:" line now comes from the audited manifest; the hand-kept CERTS array — the one authoritative claim string nothing bound — is deleted. check-selftest.sh: 14 attacks, all rejected, plus a check that the hashed block literally carries the twelve fold bodies. Attacks 9-14 are the reviewers' and an independent drill's own exploits, turned into regression tests. DOCS. TRUSTED-BASE gains item 11 (the REAL trusted computing base — lean-guard pinned; check.sh, the toolchain env, $AENEAS_HOME, python3 and Lean still trusted) and item 12 (the apex does not compose the ten). README: the audit description rewritten; the XMSS sibling-order claim downgraded from "pins" to "makes visible", with a new blanket non-claim covering all ten loop certificates; the de-plumbing file claim corrected (round 1 touched only verify_mono.rs, round 2 only helpers.rs — which is ON the deployed verify AND sign paths, now disclosed; wots.rs was never patched). RECORDED-RUN: three lines that stood inside a fence were a hand-written summary, not console output — fabricated evidence in the file whose purpose is machine evidence. They are removed and the fabrication is named in place, together with the correction that the "INDEPENDENT RUN" block predates this gate. New rule: nothing goes in a fence unless captured with tee/cat, and every block states its date, pin, and who ran it. The transcripts added here follow it. Also disclosed rather than buried: three bugs in my own test harness this round (an olean-purge build-order break, an attack rejected by the wrong rule, and a coverage assertion looking on the wrong line) — each would have let an attack pass or fail for an unrelated reason. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-07-27 20:57:46 +00:00
./check.sh > /tmp/sf8.out 2>&1 && fail "ATTACK 8 SUCCEEDED (a dropped cert row passed)" /tmp/sf8.out
grep -q "digest mismatch" /tmp/sf8.out || fail "ATTACK 8: rejected but not via the digest binding" /tmp/sf8.out
restore
echo "✓ attack 8 rejected (audit-manifest digest — a silently-dropped cert cannot pass)"
# ── 9: WIDEN THE POLICY (round-5 NEW-1) ─────────────────────────────────────
# Previously ALL GREEN with the committed fingerprint byte-identical: the
# fingerprint covered `manifest` but never `allowedBoundary`, the very predicate
# the enumeration tests against.
# Widen the policy ALONE — no axiom is declared anywhere, so the enumeration
# (which now also rejects a bare `axiom` in an audited module) cannot fire and
# the DIGEST must be what bites. `sorryAx` is used as the smuggled name because
# admitting it would silently legalise every `sorry` in the repository.
review round 6: pin the auditor, purge every olean, pin gen/ as a set Round 6 confirmed the digest redesign closed NEW-1/NEW-2/NEW-5 at the mechanism ("the first time in three rounds I have not been able to gut a certificate"), then demonstrated two more ways to reach ALL GREEN with the committed digest BYTE-IDENTICAL over a repository proving False. Both are fixed. NEW-7 — the digest bound the audit's DATA, never its LOGIC. Flipping the two fail-closed guards in Proofs/Audit.lean to `unless true` disabled every in-Lean check; the block's inputs genuinely had not changed, so the digest still matched. Total attacker diff: 2 files, 6 insertions. Worse, TRUSTED-BASE item 11 listed the trusted-unbound set and did NOT mention Audit.lean, so a reviewer using it as a map of what to read by hand would have skipped the file that computes the number it is judged by. FIX: Proofs/Audit.lean is now sha256-pinned in harness_integrity_sha256, symmetric with lean-guard, and item 11 says so — including the honest residue: an author who edits the logic AND rotates its pin is caught only by reading the diff at the pin. NEW-8 — Phase 0's purge covered gen/ and Proofs/ while the stray check greped only *.lean, so an ORPHAN verification/Evil.olean whose source had been DELETED fell between them, satisfied an import, and was invisible to git status (*.olean is gitignored). FIX: purge every .olean under verification/, and forbid stray .lean AND .olean. NEW-9 (partial) — gen/ was pinned by four NAMES, not as a SET, so a new file there was neither hashed nor forbidden while LEAN_PATH contains $PWD/gen. FIX: Phase 0 asserts the gen/*.lean file set equals the pin map exactly. This found a real gap on its first run: Aeneas emits *_Template.lean scaffolding into gen/ on every extraction — untracked byproducts (a fresh clone has only the four pinned files) that nothing imports but that sat on LEAN_PATH unpinned. They are now purged as byproducts before the set assertion. Also, from the reviewer's §3 suggestion: the canonical block is now COMMITTED as verification/AUDIT-MANIFEST.txt, so a digest mismatch prints a real diff instead of writing an observed file with nothing to compare against; check.sh also fails if the committed copy drifts from what Lean emits. check-selftest.sh: 16 attacks, all rejected, plus the coverage check. Attacks 16 and 17 are the reviewer's two demonstrations. Attacks that mutate the audit's DATA now re-pin Audit.lean first, so they still test the digest/enumeration rather than being stopped by the byte pin; attack 17 deliberately does not re-pin, because the pin is what it tests. Housekeeping: PROVENANCE.json trailing newline restored (NEW-12). Disclosed rather than buried: two more of my own assertion bugs this round — attack 16 asserted the hygiene message when the correct rejection is the purge plus a failed import, and the earlier gen/ set check surfaced the template files only because it was written strictly. Both are the wrong-diagnostic class. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-07-28 07:22:12 +00:00
save Proofs/Audit.lean; save PROVENANCE.json
review round 5: bind the policy, the specification bodies, and the harness The third reviewer demonstrated that the round-4 gate was closed at the EXPLOITS, not the MECHANISMS: it bound the manifest rows while the things he moved sat outside the binding. Three fail-opens, each executed end-to-end with the button printing ALL GREEN. No theorem, proof, fold, or model body changed. NEW-1 — the policy constant was unbound. `manifestFingerprint` covered `manifest` but never `allowedBoundary`, the sole predicate the enumeration tests against; adding one name re-opened the False-proof with the committed fingerprint BYTE-IDENTICAL. NEW-2 — the specification bodies were unbound. The statement fingerprint pinned each certificate's TYPE, which names its reference fold; redefining that fold to *be* the extracted loop left cone and type-hash identical while the certificate degenerated to `loop = loop`. 100% of the fidelity content lives in those defs. NEW-3 — the harness was unbound. Stubbing verification/lean-guard alone, without touching check.sh or the proofs, gave ALL GREEN in 3.6s over destroyed proofs. FIX — one mechanism rather than three patches. Audit.lean now emits a canonical AUDIT-MANIFEST block and check.sh binds to its SHA-256. The block covers the POLICY constants, every certificate's fully-elaborated statement, and every specification constant transitively reachable from those statements with its fully-elaborated BODY (41 constants; the closure is computed, so a new fold cannot appear without moving the digest; Prop-valued constants contribute their statement, by proof irrelevance). This also retires the 32-bit Expr.hash as the binding (NEW-5) — it survives only as a per-certificate diagnostic. Enumeration now covers EVERY declaration kind (a `def : False` passed before) in the eight certificate modules AND in Audit.lean itself — the auditor is no longer exempt (round-5 R1). A bare `axiom` in audited scope is now an error. Phase 0 purges stale .olean (the verdict must depend on committed bytes, not .gitignored build state — NEW-4), forbids any .lean outside gen/ and Proofs/, and sha256-pins the four model files AND lean-guard. lean-guard is KEPT rather than removed (the reviewer's portability advice is declined by operator decision): it is the memory cap and machine-wide lock that protect the build machine after a 12.2GB OOM took the host down. That trade-off is documented. check.sh's "Certificates proven:" line now comes from the audited manifest; the hand-kept CERTS array — the one authoritative claim string nothing bound — is deleted. check-selftest.sh: 14 attacks, all rejected, plus a check that the hashed block literally carries the twelve fold bodies. Attacks 9-14 are the reviewers' and an independent drill's own exploits, turned into regression tests. DOCS. TRUSTED-BASE gains item 11 (the REAL trusted computing base — lean-guard pinned; check.sh, the toolchain env, $AENEAS_HOME, python3 and Lean still trusted) and item 12 (the apex does not compose the ten). README: the audit description rewritten; the XMSS sibling-order claim downgraded from "pins" to "makes visible", with a new blanket non-claim covering all ten loop certificates; the de-plumbing file claim corrected (round 1 touched only verify_mono.rs, round 2 only helpers.rs — which is ON the deployed verify AND sign paths, now disclosed; wots.rs was never patched). RECORDED-RUN: three lines that stood inside a fence were a hand-written summary, not console output — fabricated evidence in the file whose purpose is machine evidence. They are removed and the fabrication is named in place, together with the correction that the "INDEPENDENT RUN" block predates this gate. New rule: nothing goes in a fence unless captured with tee/cat, and every block states its date, pin, and who ran it. The transcripts added here follow it. Also disclosed rather than buried: three bugs in my own test harness this round (an olean-purge build-order break, an attack rejected by the wrong rule, and a coverage assertion looking on the wrong line) — each would have let an attack pass or fail for an unrelated reason. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-07-27 20:57:46 +00:00
python3 - <<'PY'
a = open("Proofs/Audit.lean").read()
old = " kernel3 ++ [oracleF, oracleH, oracleTL, oracleTLen, oracleHMsg]\n"
assert a.count(old) == 1, "allowedBoundary shape changed"
open("Proofs/Audit.lean","w").write(a.replace(old, old.rstrip("\n") + " ++ [`sorryAx]\n", 1))
PY
review round 6: pin the auditor, purge every olean, pin gen/ as a set Round 6 confirmed the digest redesign closed NEW-1/NEW-2/NEW-5 at the mechanism ("the first time in three rounds I have not been able to gut a certificate"), then demonstrated two more ways to reach ALL GREEN with the committed digest BYTE-IDENTICAL over a repository proving False. Both are fixed. NEW-7 — the digest bound the audit's DATA, never its LOGIC. Flipping the two fail-closed guards in Proofs/Audit.lean to `unless true` disabled every in-Lean check; the block's inputs genuinely had not changed, so the digest still matched. Total attacker diff: 2 files, 6 insertions. Worse, TRUSTED-BASE item 11 listed the trusted-unbound set and did NOT mention Audit.lean, so a reviewer using it as a map of what to read by hand would have skipped the file that computes the number it is judged by. FIX: Proofs/Audit.lean is now sha256-pinned in harness_integrity_sha256, symmetric with lean-guard, and item 11 says so — including the honest residue: an author who edits the logic AND rotates its pin is caught only by reading the diff at the pin. NEW-8 — Phase 0's purge covered gen/ and Proofs/ while the stray check greped only *.lean, so an ORPHAN verification/Evil.olean whose source had been DELETED fell between them, satisfied an import, and was invisible to git status (*.olean is gitignored). FIX: purge every .olean under verification/, and forbid stray .lean AND .olean. NEW-9 (partial) — gen/ was pinned by four NAMES, not as a SET, so a new file there was neither hashed nor forbidden while LEAN_PATH contains $PWD/gen. FIX: Phase 0 asserts the gen/*.lean file set equals the pin map exactly. This found a real gap on its first run: Aeneas emits *_Template.lean scaffolding into gen/ on every extraction — untracked byproducts (a fresh clone has only the four pinned files) that nothing imports but that sat on LEAN_PATH unpinned. They are now purged as byproducts before the set assertion. Also, from the reviewer's §3 suggestion: the canonical block is now COMMITTED as verification/AUDIT-MANIFEST.txt, so a digest mismatch prints a real diff instead of writing an observed file with nothing to compare against; check.sh also fails if the committed copy drifts from what Lean emits. check-selftest.sh: 16 attacks, all rejected, plus the coverage check. Attacks 16 and 17 are the reviewer's two demonstrations. Attacks that mutate the audit's DATA now re-pin Audit.lean first, so they still test the digest/enumeration rather than being stopped by the byte pin; attack 17 deliberately does not re-pin, because the pin is what it tests. Housekeeping: PROVENANCE.json trailing newline restored (NEW-12). Disclosed rather than buried: two more of my own assertion bugs this round — attack 16 asserted the hygiene message when the correct rejection is the purge plus a failed import, and the earlier gen/ set check surfaced the template files only because it was written strictly. Both are the wrong-diagnostic class. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-07-28 07:22:12 +00:00
repin_audit
review round 5: bind the policy, the specification bodies, and the harness The third reviewer demonstrated that the round-4 gate was closed at the EXPLOITS, not the MECHANISMS: it bound the manifest rows while the things he moved sat outside the binding. Three fail-opens, each executed end-to-end with the button printing ALL GREEN. No theorem, proof, fold, or model body changed. NEW-1 — the policy constant was unbound. `manifestFingerprint` covered `manifest` but never `allowedBoundary`, the sole predicate the enumeration tests against; adding one name re-opened the False-proof with the committed fingerprint BYTE-IDENTICAL. NEW-2 — the specification bodies were unbound. The statement fingerprint pinned each certificate's TYPE, which names its reference fold; redefining that fold to *be* the extracted loop left cone and type-hash identical while the certificate degenerated to `loop = loop`. 100% of the fidelity content lives in those defs. NEW-3 — the harness was unbound. Stubbing verification/lean-guard alone, without touching check.sh or the proofs, gave ALL GREEN in 3.6s over destroyed proofs. FIX — one mechanism rather than three patches. Audit.lean now emits a canonical AUDIT-MANIFEST block and check.sh binds to its SHA-256. The block covers the POLICY constants, every certificate's fully-elaborated statement, and every specification constant transitively reachable from those statements with its fully-elaborated BODY (41 constants; the closure is computed, so a new fold cannot appear without moving the digest; Prop-valued constants contribute their statement, by proof irrelevance). This also retires the 32-bit Expr.hash as the binding (NEW-5) — it survives only as a per-certificate diagnostic. Enumeration now covers EVERY declaration kind (a `def : False` passed before) in the eight certificate modules AND in Audit.lean itself — the auditor is no longer exempt (round-5 R1). A bare `axiom` in audited scope is now an error. Phase 0 purges stale .olean (the verdict must depend on committed bytes, not .gitignored build state — NEW-4), forbids any .lean outside gen/ and Proofs/, and sha256-pins the four model files AND lean-guard. lean-guard is KEPT rather than removed (the reviewer's portability advice is declined by operator decision): it is the memory cap and machine-wide lock that protect the build machine after a 12.2GB OOM took the host down. That trade-off is documented. check.sh's "Certificates proven:" line now comes from the audited manifest; the hand-kept CERTS array — the one authoritative claim string nothing bound — is deleted. check-selftest.sh: 14 attacks, all rejected, plus a check that the hashed block literally carries the twelve fold bodies. Attacks 9-14 are the reviewers' and an independent drill's own exploits, turned into regression tests. DOCS. TRUSTED-BASE gains item 11 (the REAL trusted computing base — lean-guard pinned; check.sh, the toolchain env, $AENEAS_HOME, python3 and Lean still trusted) and item 12 (the apex does not compose the ten). README: the audit description rewritten; the XMSS sibling-order claim downgraded from "pins" to "makes visible", with a new blanket non-claim covering all ten loop certificates; the de-plumbing file claim corrected (round 1 touched only verify_mono.rs, round 2 only helpers.rs — which is ON the deployed verify AND sign paths, now disclosed; wots.rs was never patched). RECORDED-RUN: three lines that stood inside a fence were a hand-written summary, not console output — fabricated evidence in the file whose purpose is machine evidence. They are removed and the fabrication is named in place, together with the correction that the "INDEPENDENT RUN" block predates this gate. New rule: nothing goes in a fence unless captured with tee/cat, and every block states its date, pin, and who ran it. The transcripts added here follow it. Also disclosed rather than buried: three bugs in my own test harness this round (an olean-purge build-order break, an attack rejected by the wrong rule, and a coverage assertion looking on the wrong line) — each would have let an attack pass or fail for an unrelated reason. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-07-27 20:57:46 +00:00
./check.sh > /tmp/sf9.out 2>&1 && fail "ATTACK 9 SUCCEEDED: the axiom policy was widened and the button stayed GREEN!" /tmp/sf9.out
grep -q "digest mismatch" /tmp/sf9.out || fail "ATTACK 9: rejected but not via the policy-covering digest" /tmp/sf9.out
restore
echo "✓ attack 9 rejected (digest covers allowedBoundary — the policy cannot be widened silently)"
# ── 10: REDEFINE A SPEC FOLD TO BE THE LOOP (round-5 NEW-2) ─────────────────
# The certificate keeps its exact statement, cone and type-hash, but becomes
# `loop = loop` — vacuous. Previously ALL GREEN.
save Proofs/ChainSpec.lean
python3 - <<'PY'
s = open("Proofs/ChainSpec.lean").read()
i = s.index("noncomputable def chainFoldN")
j = s.index("/-- One full loop step", i)
gut = """noncomputable def chainFoldN {N : Std.Usize} (pk_seed : Slice Std.U8) :
types.Adrs → Array Std.U8 N → Std.U32 → Nat → Result (Array Std.U8 N) :=
fun adrs tmp start s =>
verify_mono.chain_free_loop
{ start := start,
«end» := Std.U32.ofNatCore ((start.val + s) % 2 ^ 32) (Nat.mod_lt _ (by norm_num)) }
pk_seed adrs tmp
"""
open("Proofs/ChainSpec.lean","w").write(s[:i] + gut + s[j:])
PY
./check.sh > /tmp/sf10.out 2>&1 && fail "ATTACK 10 SUCCEEDED: the spec fold IS the loop, certificate is vacuous, still GREEN!" /tmp/sf10.out
# Two layers stand here, and either is a valid rejection: the existing proof no
# longer matches the redefined fold (Phase 2), and — if an attacker repairs the
# proof, as the round-5 reviewer did — the digest covers specification BODIES,
# so it moves. Attack 9 is the pure test that the digest binding fires; that the
# digest's input contains the fold bodies is verified directly (see below).
grep -qE "digest mismatch|FAIL: Proofs/ChainSpec" /tmp/sf10.out \
|| fail "ATTACK 10: rejected, but neither via the digest nor a proof break" /tmp/sf10.out
restore
echo "✓ attack 10 rejected (a specification fold cannot be silently redefined to the loop)"
# ── 11: `def : False` rather than `theorem : False` (drill finding) ─────────
save Proofs/WotsSpec.lean
printf '\n-- SELFTEST ATTACK 11\naxiom cheat11 : ∀ (P : Prop), P\ndef attack11_false : False := cheat11 _\n' >> Proofs/WotsSpec.lean
./check.sh > /tmp/sf11.out 2>&1 && fail "ATTACK 11 SUCCEEDED: a def proving False passed!" /tmp/sf11.out
grep -qE "attack11_false|AXIOM DECLARED" /tmp/sf11.out || fail "ATTACK 11: rejected but not via the all-kinds enumeration" /tmp/sf11.out
restore
echo "✓ attack 11 rejected (enumeration covers every declaration kind, not just theorems)"
# ── 12: a False-proof inside the AUDITOR itself (round-5 R1) ────────────────
review round 6: pin the auditor, purge every olean, pin gen/ as a set Round 6 confirmed the digest redesign closed NEW-1/NEW-2/NEW-5 at the mechanism ("the first time in three rounds I have not been able to gut a certificate"), then demonstrated two more ways to reach ALL GREEN with the committed digest BYTE-IDENTICAL over a repository proving False. Both are fixed. NEW-7 — the digest bound the audit's DATA, never its LOGIC. Flipping the two fail-closed guards in Proofs/Audit.lean to `unless true` disabled every in-Lean check; the block's inputs genuinely had not changed, so the digest still matched. Total attacker diff: 2 files, 6 insertions. Worse, TRUSTED-BASE item 11 listed the trusted-unbound set and did NOT mention Audit.lean, so a reviewer using it as a map of what to read by hand would have skipped the file that computes the number it is judged by. FIX: Proofs/Audit.lean is now sha256-pinned in harness_integrity_sha256, symmetric with lean-guard, and item 11 says so — including the honest residue: an author who edits the logic AND rotates its pin is caught only by reading the diff at the pin. NEW-8 — Phase 0's purge covered gen/ and Proofs/ while the stray check greped only *.lean, so an ORPHAN verification/Evil.olean whose source had been DELETED fell between them, satisfied an import, and was invisible to git status (*.olean is gitignored). FIX: purge every .olean under verification/, and forbid stray .lean AND .olean. NEW-9 (partial) — gen/ was pinned by four NAMES, not as a SET, so a new file there was neither hashed nor forbidden while LEAN_PATH contains $PWD/gen. FIX: Phase 0 asserts the gen/*.lean file set equals the pin map exactly. This found a real gap on its first run: Aeneas emits *_Template.lean scaffolding into gen/ on every extraction — untracked byproducts (a fresh clone has only the four pinned files) that nothing imports but that sat on LEAN_PATH unpinned. They are now purged as byproducts before the set assertion. Also, from the reviewer's §3 suggestion: the canonical block is now COMMITTED as verification/AUDIT-MANIFEST.txt, so a digest mismatch prints a real diff instead of writing an observed file with nothing to compare against; check.sh also fails if the committed copy drifts from what Lean emits. check-selftest.sh: 16 attacks, all rejected, plus the coverage check. Attacks 16 and 17 are the reviewer's two demonstrations. Attacks that mutate the audit's DATA now re-pin Audit.lean first, so they still test the digest/enumeration rather than being stopped by the byte pin; attack 17 deliberately does not re-pin, because the pin is what it tests. Housekeeping: PROVENANCE.json trailing newline restored (NEW-12). Disclosed rather than buried: two more of my own assertion bugs this round — attack 16 asserted the hygiene message when the correct rejection is the purge plus a failed import, and the earlier gen/ set check surfaced the template files only because it was written strictly. Both are the wrong-diagnostic class. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-07-28 07:22:12 +00:00
save Proofs/Audit.lean; save PROVENANCE.json
review round 5: bind the policy, the specification bodies, and the harness The third reviewer demonstrated that the round-4 gate was closed at the EXPLOITS, not the MECHANISMS: it bound the manifest rows while the things he moved sat outside the binding. Three fail-opens, each executed end-to-end with the button printing ALL GREEN. No theorem, proof, fold, or model body changed. NEW-1 — the policy constant was unbound. `manifestFingerprint` covered `manifest` but never `allowedBoundary`, the sole predicate the enumeration tests against; adding one name re-opened the False-proof with the committed fingerprint BYTE-IDENTICAL. NEW-2 — the specification bodies were unbound. The statement fingerprint pinned each certificate's TYPE, which names its reference fold; redefining that fold to *be* the extracted loop left cone and type-hash identical while the certificate degenerated to `loop = loop`. 100% of the fidelity content lives in those defs. NEW-3 — the harness was unbound. Stubbing verification/lean-guard alone, without touching check.sh or the proofs, gave ALL GREEN in 3.6s over destroyed proofs. FIX — one mechanism rather than three patches. Audit.lean now emits a canonical AUDIT-MANIFEST block and check.sh binds to its SHA-256. The block covers the POLICY constants, every certificate's fully-elaborated statement, and every specification constant transitively reachable from those statements with its fully-elaborated BODY (41 constants; the closure is computed, so a new fold cannot appear without moving the digest; Prop-valued constants contribute their statement, by proof irrelevance). This also retires the 32-bit Expr.hash as the binding (NEW-5) — it survives only as a per-certificate diagnostic. Enumeration now covers EVERY declaration kind (a `def : False` passed before) in the eight certificate modules AND in Audit.lean itself — the auditor is no longer exempt (round-5 R1). A bare `axiom` in audited scope is now an error. Phase 0 purges stale .olean (the verdict must depend on committed bytes, not .gitignored build state — NEW-4), forbids any .lean outside gen/ and Proofs/, and sha256-pins the four model files AND lean-guard. lean-guard is KEPT rather than removed (the reviewer's portability advice is declined by operator decision): it is the memory cap and machine-wide lock that protect the build machine after a 12.2GB OOM took the host down. That trade-off is documented. check.sh's "Certificates proven:" line now comes from the audited manifest; the hand-kept CERTS array — the one authoritative claim string nothing bound — is deleted. check-selftest.sh: 14 attacks, all rejected, plus a check that the hashed block literally carries the twelve fold bodies. Attacks 9-14 are the reviewers' and an independent drill's own exploits, turned into regression tests. DOCS. TRUSTED-BASE gains item 11 (the REAL trusted computing base — lean-guard pinned; check.sh, the toolchain env, $AENEAS_HOME, python3 and Lean still trusted) and item 12 (the apex does not compose the ten). README: the audit description rewritten; the XMSS sibling-order claim downgraded from "pins" to "makes visible", with a new blanket non-claim covering all ten loop certificates; the de-plumbing file claim corrected (round 1 touched only verify_mono.rs, round 2 only helpers.rs — which is ON the deployed verify AND sign paths, now disclosed; wots.rs was never patched). RECORDED-RUN: three lines that stood inside a fence were a hand-written summary, not console output — fabricated evidence in the file whose purpose is machine evidence. They are removed and the fabrication is named in place, together with the correction that the "INDEPENDENT RUN" block predates this gate. New rule: nothing goes in a fence unless captured with tee/cat, and every block states its date, pin, and who ran it. The transcripts added here follow it. Also disclosed rather than buried: three bugs in my own test harness this round (an olean-purge build-order break, an attack rejected by the wrong rule, and a coverage assertion looking on the wrong line) — each would have let an attack pass or fail for an unrelated reason. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-07-27 20:57:46 +00:00
python3 - <<'PY'
a = open("Proofs/Audit.lean").read()
i = a.index("elab \"auditCones\"")
open("Proofs/Audit.lean","w").write(
a[:i] + "axiom cheat12 : ∀ (P : Prop), P\ntheorem audit_proves_false : False := cheat12 _\n\n" + a[i:])
PY
review round 6: pin the auditor, purge every olean, pin gen/ as a set Round 6 confirmed the digest redesign closed NEW-1/NEW-2/NEW-5 at the mechanism ("the first time in three rounds I have not been able to gut a certificate"), then demonstrated two more ways to reach ALL GREEN with the committed digest BYTE-IDENTICAL over a repository proving False. Both are fixed. NEW-7 — the digest bound the audit's DATA, never its LOGIC. Flipping the two fail-closed guards in Proofs/Audit.lean to `unless true` disabled every in-Lean check; the block's inputs genuinely had not changed, so the digest still matched. Total attacker diff: 2 files, 6 insertions. Worse, TRUSTED-BASE item 11 listed the trusted-unbound set and did NOT mention Audit.lean, so a reviewer using it as a map of what to read by hand would have skipped the file that computes the number it is judged by. FIX: Proofs/Audit.lean is now sha256-pinned in harness_integrity_sha256, symmetric with lean-guard, and item 11 says so — including the honest residue: an author who edits the logic AND rotates its pin is caught only by reading the diff at the pin. NEW-8 — Phase 0's purge covered gen/ and Proofs/ while the stray check greped only *.lean, so an ORPHAN verification/Evil.olean whose source had been DELETED fell between them, satisfied an import, and was invisible to git status (*.olean is gitignored). FIX: purge every .olean under verification/, and forbid stray .lean AND .olean. NEW-9 (partial) — gen/ was pinned by four NAMES, not as a SET, so a new file there was neither hashed nor forbidden while LEAN_PATH contains $PWD/gen. FIX: Phase 0 asserts the gen/*.lean file set equals the pin map exactly. This found a real gap on its first run: Aeneas emits *_Template.lean scaffolding into gen/ on every extraction — untracked byproducts (a fresh clone has only the four pinned files) that nothing imports but that sat on LEAN_PATH unpinned. They are now purged as byproducts before the set assertion. Also, from the reviewer's §3 suggestion: the canonical block is now COMMITTED as verification/AUDIT-MANIFEST.txt, so a digest mismatch prints a real diff instead of writing an observed file with nothing to compare against; check.sh also fails if the committed copy drifts from what Lean emits. check-selftest.sh: 16 attacks, all rejected, plus the coverage check. Attacks 16 and 17 are the reviewer's two demonstrations. Attacks that mutate the audit's DATA now re-pin Audit.lean first, so they still test the digest/enumeration rather than being stopped by the byte pin; attack 17 deliberately does not re-pin, because the pin is what it tests. Housekeeping: PROVENANCE.json trailing newline restored (NEW-12). Disclosed rather than buried: two more of my own assertion bugs this round — attack 16 asserted the hygiene message when the correct rejection is the purge plus a failed import, and the earlier gen/ set check surfaced the template files only because it was written strictly. Both are the wrong-diagnostic class. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-07-28 07:22:12 +00:00
repin_audit
review round 5: bind the policy, the specification bodies, and the harness The third reviewer demonstrated that the round-4 gate was closed at the EXPLOITS, not the MECHANISMS: it bound the manifest rows while the things he moved sat outside the binding. Three fail-opens, each executed end-to-end with the button printing ALL GREEN. No theorem, proof, fold, or model body changed. NEW-1 — the policy constant was unbound. `manifestFingerprint` covered `manifest` but never `allowedBoundary`, the sole predicate the enumeration tests against; adding one name re-opened the False-proof with the committed fingerprint BYTE-IDENTICAL. NEW-2 — the specification bodies were unbound. The statement fingerprint pinned each certificate's TYPE, which names its reference fold; redefining that fold to *be* the extracted loop left cone and type-hash identical while the certificate degenerated to `loop = loop`. 100% of the fidelity content lives in those defs. NEW-3 — the harness was unbound. Stubbing verification/lean-guard alone, without touching check.sh or the proofs, gave ALL GREEN in 3.6s over destroyed proofs. FIX — one mechanism rather than three patches. Audit.lean now emits a canonical AUDIT-MANIFEST block and check.sh binds to its SHA-256. The block covers the POLICY constants, every certificate's fully-elaborated statement, and every specification constant transitively reachable from those statements with its fully-elaborated BODY (41 constants; the closure is computed, so a new fold cannot appear without moving the digest; Prop-valued constants contribute their statement, by proof irrelevance). This also retires the 32-bit Expr.hash as the binding (NEW-5) — it survives only as a per-certificate diagnostic. Enumeration now covers EVERY declaration kind (a `def : False` passed before) in the eight certificate modules AND in Audit.lean itself — the auditor is no longer exempt (round-5 R1). A bare `axiom` in audited scope is now an error. Phase 0 purges stale .olean (the verdict must depend on committed bytes, not .gitignored build state — NEW-4), forbids any .lean outside gen/ and Proofs/, and sha256-pins the four model files AND lean-guard. lean-guard is KEPT rather than removed (the reviewer's portability advice is declined by operator decision): it is the memory cap and machine-wide lock that protect the build machine after a 12.2GB OOM took the host down. That trade-off is documented. check.sh's "Certificates proven:" line now comes from the audited manifest; the hand-kept CERTS array — the one authoritative claim string nothing bound — is deleted. check-selftest.sh: 14 attacks, all rejected, plus a check that the hashed block literally carries the twelve fold bodies. Attacks 9-14 are the reviewers' and an independent drill's own exploits, turned into regression tests. DOCS. TRUSTED-BASE gains item 11 (the REAL trusted computing base — lean-guard pinned; check.sh, the toolchain env, $AENEAS_HOME, python3 and Lean still trusted) and item 12 (the apex does not compose the ten). README: the audit description rewritten; the XMSS sibling-order claim downgraded from "pins" to "makes visible", with a new blanket non-claim covering all ten loop certificates; the de-plumbing file claim corrected (round 1 touched only verify_mono.rs, round 2 only helpers.rs — which is ON the deployed verify AND sign paths, now disclosed; wots.rs was never patched). RECORDED-RUN: three lines that stood inside a fence were a hand-written summary, not console output — fabricated evidence in the file whose purpose is machine evidence. They are removed and the fabrication is named in place, together with the correction that the "INDEPENDENT RUN" block predates this gate. New rule: nothing goes in a fence unless captured with tee/cat, and every block states its date, pin, and who ran it. The transcripts added here follow it. Also disclosed rather than buried: three bugs in my own test harness this round (an olean-purge build-order break, an attack rejected by the wrong rule, and a coverage assertion looking on the wrong line) — each would have let an attack pass or fail for an unrelated reason. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-07-27 20:57:46 +00:00
./check.sh > /tmp/sf12.out 2>&1 && fail "ATTACK 12 SUCCEEDED: the auditor itself proves False, still GREEN!" /tmp/sf12.out
grep -qE "audit_proves_false|AXIOM DECLARED" /tmp/sf12.out || fail "ATTACK 12: rejected but not via self-enumeration" /tmp/sf12.out
restore
echo "✓ attack 12 rejected (the auditor audits itself — no exemption)"
# ── 13: stub the compiler harness (round-5 NEW-3) ──────────────────────────
# Previously: ALL GREEN in 3.6s with the proofs destroyed. lean-guard is KEPT
# (it is this machine's memory cap) and sha256-pinned instead.
save lean-guard
cat > lean-guard <<'EOF'
#!/usr/bin/env bash
echo "exact-cone audit PASSED"
exit 0
EOF
chmod +x lean-guard
./check.sh > /tmp/sf13.out 2>&1 && fail "ATTACK 13 SUCCEEDED: a stubbed harness passed!" /tmp/sf13.out
grep -q "INTEGRITY FAILED" /tmp/sf13.out || fail "ATTACK 13: rejected but not via the harness pin" /tmp/sf13.out
restore
echo "✓ attack 13 rejected (Phase 0 pins lean-guard — the harness is in the TCB and bound)"
# ── 14: stray .lean beside check.sh (round-5 NEW-4) ────────────────────────
cat > Evil.lean <<'EOF'
axiom cheat14 : ∀ (P : Prop), P
theorem evil14 : False := cheat14 _
EOF
./check.sh > /tmp/sf14.out 2>&1 && fail "ATTACK 14 SUCCEEDED: a stray Lean module passed!" /tmp/sf14.out
grep -q "BUILD HYGIENE FAILED" /tmp/sf14.out || fail "ATTACK 14: rejected but not via the hygiene gate" /tmp/sf14.out
rm -f Evil.lean
echo "✓ attack 14 rejected (no .lean may sit outside gen/ and Proofs/)"
review round 6: pin the auditor, purge every olean, pin gen/ as a set Round 6 confirmed the digest redesign closed NEW-1/NEW-2/NEW-5 at the mechanism ("the first time in three rounds I have not been able to gut a certificate"), then demonstrated two more ways to reach ALL GREEN with the committed digest BYTE-IDENTICAL over a repository proving False. Both are fixed. NEW-7 — the digest bound the audit's DATA, never its LOGIC. Flipping the two fail-closed guards in Proofs/Audit.lean to `unless true` disabled every in-Lean check; the block's inputs genuinely had not changed, so the digest still matched. Total attacker diff: 2 files, 6 insertions. Worse, TRUSTED-BASE item 11 listed the trusted-unbound set and did NOT mention Audit.lean, so a reviewer using it as a map of what to read by hand would have skipped the file that computes the number it is judged by. FIX: Proofs/Audit.lean is now sha256-pinned in harness_integrity_sha256, symmetric with lean-guard, and item 11 says so — including the honest residue: an author who edits the logic AND rotates its pin is caught only by reading the diff at the pin. NEW-8 — Phase 0's purge covered gen/ and Proofs/ while the stray check greped only *.lean, so an ORPHAN verification/Evil.olean whose source had been DELETED fell between them, satisfied an import, and was invisible to git status (*.olean is gitignored). FIX: purge every .olean under verification/, and forbid stray .lean AND .olean. NEW-9 (partial) — gen/ was pinned by four NAMES, not as a SET, so a new file there was neither hashed nor forbidden while LEAN_PATH contains $PWD/gen. FIX: Phase 0 asserts the gen/*.lean file set equals the pin map exactly. This found a real gap on its first run: Aeneas emits *_Template.lean scaffolding into gen/ on every extraction — untracked byproducts (a fresh clone has only the four pinned files) that nothing imports but that sat on LEAN_PATH unpinned. They are now purged as byproducts before the set assertion. Also, from the reviewer's §3 suggestion: the canonical block is now COMMITTED as verification/AUDIT-MANIFEST.txt, so a digest mismatch prints a real diff instead of writing an observed file with nothing to compare against; check.sh also fails if the committed copy drifts from what Lean emits. check-selftest.sh: 16 attacks, all rejected, plus the coverage check. Attacks 16 and 17 are the reviewer's two demonstrations. Attacks that mutate the audit's DATA now re-pin Audit.lean first, so they still test the digest/enumeration rather than being stopped by the byte pin; attack 17 deliberately does not re-pin, because the pin is what it tests. Housekeeping: PROVENANCE.json trailing newline restored (NEW-12). Disclosed rather than buried: two more of my own assertion bugs this round — attack 16 asserted the hygiene message when the correct rejection is the purge plus a failed import, and the earlier gen/ set check surfaced the template files only because it was written strictly. Both are the wrong-diagnostic class. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-07-28 07:22:12 +00:00
# ── 16: ORPHAN .olean WITH NO SOURCE (round-6 NEW-8) ───────────────────────
# Previously ALL GREEN, digest byte-identical, repo proving False: the round-5
# purge covered gen/ and Proofs/ while the stray check greped only *.lean, so a
# compiled module with its source DELETED fell between the two — and *.olean is
# .gitignored, so `git status` showed only the one-line import.
save Proofs/ChainSpec.lean
cat > Evil.lean <<'EOF'
axiom cheat16 : ∀ (P : Prop), P
theorem attack16_false : False := cheat16 _
EOF
( cd "$AENEAS_HOME/backends/lean" && lake env bash -c \
"cd '$HERE' && export LEAN_PATH=\"\$LEAN_PATH:\$PWD/gen:\$PWD\" && lean -o '$HERE/Evil.olean' '$HERE/Evil.lean'" ) >/dev/null 2>&1
rm -f Evil.lean # the SOURCE is gone; only the .olean remains
printf '\nimport Evil\n' >> Proofs/ChainSpec.lean
if [ ! -f Evil.olean ]; then
round 7: assert pin-map completeness (NEW-13), correct the count to 137, fix the regeneration-scope contradiction The third reviewer demonstrated NEW-13: PROVENANCE.json is a tracked file that nothing pins, and Phase 0's only completeness test was 'is the map non-empty'. Deleting the harness_integrity_sha256 key therefore silently un-pinned BOTH lean-guard and Proofs/Audit.lean with no diagnostic, after which the round-6 logic mutation ran to ALL GREEN over a repository proving False with the digest byte-identical. Reproduced here before fixing. The required pin NAMES now live hardcoded in check.sh — policy in the root of trust, values in the map — so a shortened map is a build failure naming the missing entries. Self-test attack 18 performs the deletion. GPT reviewer, independently: the documented '131 assertion points' was wrong. Recounted from the code, the defensible figure is 137 mono-path evaluated cases (9 retained original + 108 randomized + 10 NIST internal + 10 NIST external-pure); 131 had folded in 3 deployed-only prehash cases while omitting the retained test, and TRUSTED-BASE then decomposed it as 20 + 108 = 128, contradicting itself. Item 9 now carries the full table, states that 127 of the 137 compare mono against deployed, keeps the 3 prehash cases explicitly outside the total, and records that only two SHA2-512 and one SHAKE-256 vector are executable there — so this is not NIST coverage of all four supported prehash variants. Also from GPT: PROVENANCE.json contradicted itself, saying extraction 'reproduces all four model files byte-identically' while its own _comment correctly said the two *External files are hand-maintained. Extraction regenerates two files; the other two are byte-pinned. Corrected. TRUSTED-BASE item 11 now discloses that PROVENANCE.json is itself load-bearing and unpinned, and item 7's stale snapshot head is fixed. README states the lean-guard graceful fallback and that the empirical bridge runs on stable Rust without any Lean toolchain (round-7 NEW-16), which is the first load-bearing part of this work a third party can reproduce with cargo alone. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-07-28 11:03:35 +00:00
# An attack that could not be staged must FAIL the suite, never pass quietly:
# round-7 review found this branch printed a note and fell through to the
# unconditional "16 attacks rejected" line, so the suite could claim a
# rejection that never happened.
rm -f Evil.olean
fail "ATTACK 16 could not be staged (Evil.olean did not build) — the suite must not report green on an attack it did not run"
review round 6: pin the auditor, purge every olean, pin gen/ as a set Round 6 confirmed the digest redesign closed NEW-1/NEW-2/NEW-5 at the mechanism ("the first time in three rounds I have not been able to gut a certificate"), then demonstrated two more ways to reach ALL GREEN with the committed digest BYTE-IDENTICAL over a repository proving False. Both are fixed. NEW-7 — the digest bound the audit's DATA, never its LOGIC. Flipping the two fail-closed guards in Proofs/Audit.lean to `unless true` disabled every in-Lean check; the block's inputs genuinely had not changed, so the digest still matched. Total attacker diff: 2 files, 6 insertions. Worse, TRUSTED-BASE item 11 listed the trusted-unbound set and did NOT mention Audit.lean, so a reviewer using it as a map of what to read by hand would have skipped the file that computes the number it is judged by. FIX: Proofs/Audit.lean is now sha256-pinned in harness_integrity_sha256, symmetric with lean-guard, and item 11 says so — including the honest residue: an author who edits the logic AND rotates its pin is caught only by reading the diff at the pin. NEW-8 — Phase 0's purge covered gen/ and Proofs/ while the stray check greped only *.lean, so an ORPHAN verification/Evil.olean whose source had been DELETED fell between them, satisfied an import, and was invisible to git status (*.olean is gitignored). FIX: purge every .olean under verification/, and forbid stray .lean AND .olean. NEW-9 (partial) — gen/ was pinned by four NAMES, not as a SET, so a new file there was neither hashed nor forbidden while LEAN_PATH contains $PWD/gen. FIX: Phase 0 asserts the gen/*.lean file set equals the pin map exactly. This found a real gap on its first run: Aeneas emits *_Template.lean scaffolding into gen/ on every extraction — untracked byproducts (a fresh clone has only the four pinned files) that nothing imports but that sat on LEAN_PATH unpinned. They are now purged as byproducts before the set assertion. Also, from the reviewer's §3 suggestion: the canonical block is now COMMITTED as verification/AUDIT-MANIFEST.txt, so a digest mismatch prints a real diff instead of writing an observed file with nothing to compare against; check.sh also fails if the committed copy drifts from what Lean emits. check-selftest.sh: 16 attacks, all rejected, plus the coverage check. Attacks 16 and 17 are the reviewer's two demonstrations. Attacks that mutate the audit's DATA now re-pin Audit.lean first, so they still test the digest/enumeration rather than being stopped by the byte pin; attack 17 deliberately does not re-pin, because the pin is what it tests. Housekeeping: PROVENANCE.json trailing newline restored (NEW-12). Disclosed rather than buried: two more of my own assertion bugs this round — attack 16 asserted the hygiene message when the correct rejection is the purge plus a failed import, and the earlier gen/ set check surfaced the template files only because it was written strictly. Both are the wrong-diagnostic class. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-07-28 07:22:12 +00:00
else
./check.sh > /tmp/sf16.out 2>&1 && fail "ATTACK 16 SUCCEEDED: an orphan .olean injected False and stayed GREEN!" /tmp/sf16.out
# The defense is Phase 0's purge, which now covers ALL of verification/ and so
# deletes the orphan BEFORE the stray check ever sees it; `import Evil` then has
# nothing to resolve and Phase 2 fails closed. Assert that chain precisely —
# the rejection must be the import failure AND the .olean must be gone. (An
# earlier revision asserted the hygiene message and failed while the gate was
# working correctly: the same wrong-diagnostic defect this suite exists to catch.)
grep -q "FAIL: Proofs/ChainSpec" /tmp/sf16.out \
|| fail "ATTACK 16: rejected, but not by the purge+import chain" /tmp/sf16.out
[ ! -f Evil.olean ] \
|| fail "ATTACK 16: check.sh failed but the orphan .olean survived Phase 0" /tmp/sf16.out
echo "✓ attack 16 rejected (Phase 0 purges every .olean under verification/, so an"
echo " orphan compiled module with no source cannot satisfy an import)"
fi
restore; rm -f Evil.olean Evil.lean
# ── 17: TAMPER THE AUDIT'S LOGIC, NOT ITS DATA (round-6 NEW-7) ─────────────
# Switching the two fail-closed guards to `unless true` disables every in-Lean
# check while leaving the digest BYTE-IDENTICAL — the digest binds the audit's
# data, never the code that reads it. Note this attack does NOT re-pin
# Audit.lean: the sha256 pin is the only thing standing here, and that is
# exactly what is being tested.
save Proofs/Audit.lean; save Proofs/ChainSpec.lean
python3 - <<'PY'
a = open("Proofs/Audit.lean").read()
n = a.count(" unless errs.isEmpty do")
assert n >= 1, "Audit.lean fail-closed guard shape changed"
open("Proofs/Audit.lean","w").write(a.replace(" unless errs.isEmpty do", " unless true do"))
PY
printf '\n-- SELFTEST ATTACK 17\naxiom cheat17 : ∀ (P : Prop), P\ntheorem attack17_false : False := cheat17 _\n' >> Proofs/ChainSpec.lean
./check.sh > /tmp/sf17.out 2>&1 && fail "ATTACK 17 SUCCEEDED: the audit's guards were disabled and it stayed GREEN!" /tmp/sf17.out
grep -q "INTEGRITY FAILED" /tmp/sf17.out || fail "ATTACK 17: rejected but not via the Audit.lean harness pin" /tmp/sf17.out
restore
echo "✓ attack 17 rejected (Phase 0 pins Audit.lean — its LOGIC cannot be silently switched off)"
round 7: assert pin-map completeness (NEW-13), correct the count to 137, fix the regeneration-scope contradiction The third reviewer demonstrated NEW-13: PROVENANCE.json is a tracked file that nothing pins, and Phase 0's only completeness test was 'is the map non-empty'. Deleting the harness_integrity_sha256 key therefore silently un-pinned BOTH lean-guard and Proofs/Audit.lean with no diagnostic, after which the round-6 logic mutation ran to ALL GREEN over a repository proving False with the digest byte-identical. Reproduced here before fixing. The required pin NAMES now live hardcoded in check.sh — policy in the root of trust, values in the map — so a shortened map is a build failure naming the missing entries. Self-test attack 18 performs the deletion. GPT reviewer, independently: the documented '131 assertion points' was wrong. Recounted from the code, the defensible figure is 137 mono-path evaluated cases (9 retained original + 108 randomized + 10 NIST internal + 10 NIST external-pure); 131 had folded in 3 deployed-only prehash cases while omitting the retained test, and TRUSTED-BASE then decomposed it as 20 + 108 = 128, contradicting itself. Item 9 now carries the full table, states that 127 of the 137 compare mono against deployed, keeps the 3 prehash cases explicitly outside the total, and records that only two SHA2-512 and one SHAKE-256 vector are executable there — so this is not NIST coverage of all four supported prehash variants. Also from GPT: PROVENANCE.json contradicted itself, saying extraction 'reproduces all four model files byte-identically' while its own _comment correctly said the two *External files are hand-maintained. Extraction regenerates two files; the other two are byte-pinned. Corrected. TRUSTED-BASE item 11 now discloses that PROVENANCE.json is itself load-bearing and unpinned, and item 7's stale snapshot head is fixed. README states the lean-guard graceful fallback and that the empirical bridge runs on stable Rust without any Lean toolchain (round-7 NEW-16), which is the first load-bearing part of this work a third party can reproduce with cargo alone. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-07-28 11:03:35 +00:00
# ── 18: SHORTEN THE PIN MAP (round-7 NEW-13) ───────────────────────────────
# Previously ALL GREEN: PROVENANCE.json is a tracked file that nothing pins, and
# the only completeness test was "is the map non-empty", so deleting the whole
# harness_integrity_sha256 key silently un-pinned BOTH lean-guard and
# Proofs/Audit.lean with no diagnostic — after which the attack-17 logic
# mutation ran green over a repository proving False, digest byte-identical.
# The required pin NAMES now live hardcoded in check.sh (the root of trust),
# so a shortened map is a build failure.
save PROVENANCE.json
python3 - <<'PY'
import json
p = "PROVENANCE.json"; d = json.load(open(p))
del d["harness_integrity_sha256"]
json.dump(d, open(p, "w"), indent=2); open(p, "a").write("\n")
PY
./check.sh > /tmp/sf18.out 2>&1 && fail "ATTACK 18 SUCCEEDED: the harness pins were deleted and the button stayed GREEN!" /tmp/sf18.out
round 8: self-deriving harness pins, honest extraction guarantees, attestation basis Third reviewer returned ATTEST-with-conditions at 1bc4f39. Its conditions are committed verbatim as ATTESTATION-BASIS.md so the limits travel with the artifact instead of living in a review document a consumer never sees. Condition 9 — that extract.sh's byte-identical regeneration has never been observed by any party but the author — is the campaign's last open item, and the file records that both reviewers are now blocked on it for different environmental reasons. HARNESS PINS ARE NOW SELF-DERIVING. My round-7 fix hardcoded the required pin names, which the reviewer correctly called a second thing to keep in sync, and it supplied the boundary the harness does have: the executable bit. check.sh now requires every executable file in verification/ to be pinned (itself excluded — it cannot pin itself), plus Proofs/Audit.lean. A new harness script therefore fails closed until pinned. Consequence, and the reviewer argued for it: check-selftest.sh, drill.sh and extract.sh are now pinned too — the self-test is the only artifact demonstrating the gates work, and its assertions have been defective in four consecutive rounds, so weakening it should be a reviewable rotation rather than an unnoticed edit. THE EXTRACTION SCRIPT'S GUARANTEES ARE NOW STATED HONESTLY. The reviewer found a tautological assert in it — comparing a dict against the comprehension that had just built it — in the script written to fix a provenance-honesty defect. My first repair (comparing kept[k] against t[k]) was tautological for the same reason, which I confirmed by negative test. No check inside a transformer can detect a corrupted input, because the transformer defines the output from that input; that lesson is now recorded in the code. Both fake checks are gone and the header and provenance text name what actually protects the result — the pinned SOURCE_SHA256, the sk-must-be-present check, the group and test counts, and verify mode — each of which I negative-tested. Also: the self-test keeps its backups outside verification/ (cp -p preserves the executable bit, so an in-tree backup would have looked like an unpinned harness file and failed a run for an unrelated reason); the Phase-0 banner no longer says a file 'differs' when an entry is simply absent; and attack 18's assertion follows the renamed diagnostic and now requires both missing pins to be named. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-07-28 12:40:39 +00:00
# The diagnostic is "UNPINNED harness file" since round 8, when the required set
# became self-deriving from the executable bit: deleting the map now reports ALL
# five harness entries as unpinned, not just the two that used to be hardcoded.
grep -q "UNPINNED harness file" /tmp/sf18.out || fail "ATTACK 18: rejected but not via the pin-map completeness check" /tmp/sf18.out
grep -q "Proofs/Audit.lean" /tmp/sf18.out || fail "ATTACK 18: rejected but did not name the audit driver" /tmp/sf18.out
grep -q "lean-guard" /tmp/sf18.out || fail "ATTACK 18: rejected but did not name lean-guard" /tmp/sf18.out
round 7: assert pin-map completeness (NEW-13), correct the count to 137, fix the regeneration-scope contradiction The third reviewer demonstrated NEW-13: PROVENANCE.json is a tracked file that nothing pins, and Phase 0's only completeness test was 'is the map non-empty'. Deleting the harness_integrity_sha256 key therefore silently un-pinned BOTH lean-guard and Proofs/Audit.lean with no diagnostic, after which the round-6 logic mutation ran to ALL GREEN over a repository proving False with the digest byte-identical. Reproduced here before fixing. The required pin NAMES now live hardcoded in check.sh — policy in the root of trust, values in the map — so a shortened map is a build failure naming the missing entries. Self-test attack 18 performs the deletion. GPT reviewer, independently: the documented '131 assertion points' was wrong. Recounted from the code, the defensible figure is 137 mono-path evaluated cases (9 retained original + 108 randomized + 10 NIST internal + 10 NIST external-pure); 131 had folded in 3 deployed-only prehash cases while omitting the retained test, and TRUSTED-BASE then decomposed it as 20 + 108 = 128, contradicting itself. Item 9 now carries the full table, states that 127 of the 137 compare mono against deployed, keeps the 3 prehash cases explicitly outside the total, and records that only two SHA2-512 and one SHAKE-256 vector are executable there — so this is not NIST coverage of all four supported prehash variants. Also from GPT: PROVENANCE.json contradicted itself, saying extraction 'reproduces all four model files byte-identically' while its own _comment correctly said the two *External files are hand-maintained. Extraction regenerates two files; the other two are byte-pinned. Corrected. TRUSTED-BASE item 11 now discloses that PROVENANCE.json is itself load-bearing and unpinned, and item 7's stale snapshot head is fixed. README states the lean-guard graceful fallback and that the empirical bridge runs on stable Rust without any Lean toolchain (round-7 NEW-16), which is the first load-bearing part of this work a third party can reproduce with cargo alone. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-07-28 11:03:35 +00:00
restore
echo "✓ attack 18 rejected (the pin map cannot be silently shortened — required names are in check.sh)"
review round 5: bind the policy, the specification bodies, and the harness The third reviewer demonstrated that the round-4 gate was closed at the EXPLOITS, not the MECHANISMS: it bound the manifest rows while the things he moved sat outside the binding. Three fail-opens, each executed end-to-end with the button printing ALL GREEN. No theorem, proof, fold, or model body changed. NEW-1 — the policy constant was unbound. `manifestFingerprint` covered `manifest` but never `allowedBoundary`, the sole predicate the enumeration tests against; adding one name re-opened the False-proof with the committed fingerprint BYTE-IDENTICAL. NEW-2 — the specification bodies were unbound. The statement fingerprint pinned each certificate's TYPE, which names its reference fold; redefining that fold to *be* the extracted loop left cone and type-hash identical while the certificate degenerated to `loop = loop`. 100% of the fidelity content lives in those defs. NEW-3 — the harness was unbound. Stubbing verification/lean-guard alone, without touching check.sh or the proofs, gave ALL GREEN in 3.6s over destroyed proofs. FIX — one mechanism rather than three patches. Audit.lean now emits a canonical AUDIT-MANIFEST block and check.sh binds to its SHA-256. The block covers the POLICY constants, every certificate's fully-elaborated statement, and every specification constant transitively reachable from those statements with its fully-elaborated BODY (41 constants; the closure is computed, so a new fold cannot appear without moving the digest; Prop-valued constants contribute their statement, by proof irrelevance). This also retires the 32-bit Expr.hash as the binding (NEW-5) — it survives only as a per-certificate diagnostic. Enumeration now covers EVERY declaration kind (a `def : False` passed before) in the eight certificate modules AND in Audit.lean itself — the auditor is no longer exempt (round-5 R1). A bare `axiom` in audited scope is now an error. Phase 0 purges stale .olean (the verdict must depend on committed bytes, not .gitignored build state — NEW-4), forbids any .lean outside gen/ and Proofs/, and sha256-pins the four model files AND lean-guard. lean-guard is KEPT rather than removed (the reviewer's portability advice is declined by operator decision): it is the memory cap and machine-wide lock that protect the build machine after a 12.2GB OOM took the host down. That trade-off is documented. check.sh's "Certificates proven:" line now comes from the audited manifest; the hand-kept CERTS array — the one authoritative claim string nothing bound — is deleted. check-selftest.sh: 14 attacks, all rejected, plus a check that the hashed block literally carries the twelve fold bodies. Attacks 9-14 are the reviewers' and an independent drill's own exploits, turned into regression tests. DOCS. TRUSTED-BASE gains item 11 (the REAL trusted computing base — lean-guard pinned; check.sh, the toolchain env, $AENEAS_HOME, python3 and Lean still trusted) and item 12 (the apex does not compose the ten). README: the audit description rewritten; the XMSS sibling-order claim downgraded from "pins" to "makes visible", with a new blanket non-claim covering all ten loop certificates; the de-plumbing file claim corrected (round 1 touched only verify_mono.rs, round 2 only helpers.rs — which is ON the deployed verify AND sign paths, now disclosed; wots.rs was never patched). RECORDED-RUN: three lines that stood inside a fence were a hand-written summary, not console output — fabricated evidence in the file whose purpose is machine evidence. They are removed and the fabrication is named in place, together with the correction that the "INDEPENDENT RUN" block predates this gate. New rule: nothing goes in a fence unless captured with tee/cat, and every block states its date, pin, and who ran it. The transcripts added here follow it. Also disclosed rather than buried: three bugs in my own test harness this round (an olean-purge build-order break, an attack rejected by the wrong rule, and a coverage assertion looking on the wrong line) — each would have let an attack pass or fail for an unrelated reason. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-07-27 20:57:46 +00:00
# ── 15: COVERAGE OF THE DIGEST INPUT (direct, not an attack) ───────────────
# Attack 9 proves the digest binding fires. This proves WHAT it covers: the
# hashed block must literally contain each reference fold's definition BODY, so
# that any change to one necessarily moves the SHA-256 (round-5 NEW-2).
./check.sh > /tmp/sf15.out 2>&1 || fail "ATTACK 15 setup: clean tree is not green" /tmp/sf15.out
lake_out=$(cd "$AENEAS_HOME/backends/lean" 2>/dev/null && lake env bash -c \
"cd '$HERE' && export LEAN_PATH=\"\$LEAN_PATH:\$PWD/gen:\$PWD\" && '$HERE/lean-guard' 'Proofs/Audit.lean'" 2>&1)
BLOCK=$(awk '/AUDIT-MANIFEST-BEGIN/{f=1;next} /AUDIT-MANIFEST-END/{f=0} f' <<<"$lake_out")
[ -n "$BLOCK" ] || { echo "✗ ATTACK 15: no audit block"; exit 1; }
for fold in chainFoldN wotsChainFold xmssFoldN htFoldN forsInnerFold forsOuterFold \
toIntFold toByteFold wotsCsumFold base2bOuterFold slhVerifyRoot htVerifyRoot; do
grep -q "spec|fips205.$fold|def|value=" <<<"$BLOCK" \
|| { echo "✗ CHECK 15: the digest input does NOT carry the body of $fold"; exit 1; }
done
# Lean's equation compiler splits a recursive definition: `chainFoldN` is a thin
# wrapper and the actual recursion lives in `chainFoldN._f`. BOTH are reached by
# the closure and printed, so assert the SEMANTIC content specifically — the
# extracted primitives a fold must call — rather than assuming which line holds
# it. (An earlier revision of this check asserted the body text was on the
# wrapper's line and failed while coverage was in fact correct.)
for probe in "fips205.chainFoldN._f|def|value=.*set_hash_address" \
"fips205.xmssFoldN._f|def|value=.*verify_mono.oracle.h" \
"fips205.slhVerifyRoot|def|value=.*verify_mono.oracle.h_msg"; do
grep -qE "spec\|$probe" <<<"$BLOCK" \
|| { echo "✗ CHECK 15: the digest input is missing expected body content: $probe"; exit 1; }
done
echo "✓ check 15 passed (the hashed block carries all 12 reference-fold bodies,"
echo ' including the recursive _f companions and their extracted-primitive calls)'
review round 1: fix the fail-open audit gate + remove the overclaimed framing External review (both standing reviewers, 2026-07-24) returned DO NOT ATTEST. The eleven Lean theorems compile with genuinely clean cones (both reviewers independently reconstructed them), but two real defects were found and are fixed here. FIX 1 — the axiom audit was FAIL-OPEN (the critical blocker). check.sh Phase 3 grepped a single physical line of each `#print axioms` report; Lean WRAPS long cones across lines, so for ht/fors_outer/APEX the audit checked only `[propext,` and silently ignored the continuation lines — a disallowed axiom on line 2+ passed (the GPT reviewer demonstrated `review_evil_ax` passing). Since check.sh is the sole source of the word "proven", this is unacceptable. - New parser: FLATTEN the whole report (join newlines) BEFORE parsing, then extract each certificate's complete bracketed cone with a literal-string (regex-safe) scan and subset-check every axiom. Missing/empty report => FAIL CLOSED. The audit now prints the count of axioms actually audited per cert (apex: 8, previously 1). - check-selftest.sh gains ATTACK 3: a smuggled axiom bundled with the apex so its cone WRAPS with the evil axiom on a continuation line — the exact exploit. Verified: all three attacks now rejected, attack 3 via the axiom gate naming the continuation-line axiom. (Also fixed attack 2's leftover EvilSpec.lean tripping attack 3's dead-file gate.) FIX 2 — remove the overclaimed framing (refuted by both reviewers). Corrected in README, the ApexSpec header + apex docstring, and (separately) the control MANIFEST: - "composes all ten loop-fidelity certificates" — FALSE. The apex proof is a STRUCTURAL FACTORIZATION; it references NONE of the ten (grep: 0) and would remain provable if one were deleted. They are independent local-fidelity lemmas, not links in the apex proof. - "every loop is individually fidelity-certified" — FALSE. base_2b's inner accumulation loop is threaded opaquely and uncertified — and it determines the FORS indices / WOTS digits, so a defect there could change the recomputed root while all eleven theorems still hold. - "the deployed verifier" — the proved subject is verify_mono, a private #![allow(dead_code)] monomorphic facade NOT called by the public API; the bridge to the deployed generic verifier is the finite differential test, not a machine-checked refinement. - "verify-path pyramid complete" — replaced with "intermediate verification layer"; the apex is an ACCEPTANCE CHARACTERIZATION, not closed-form FIPS-205 correctness. Also: FunsExternal header noted the Take axiom "remains" (stale — deleted in de-plumbing round 2); corrected. check.sh green over all eleven certificates under the fixed fail-closed parser (exit 0, 8 axioms audited for the apex). Nothing about the theorems changed — they were and are sound; only the audit tool and the claims about them are fixed. NOT DONE (remaining reviewer blockers, tracked): reproducible extract tuple (pin commits, de-hard-code extract.sh) + Cargo.lock / toolchain pin. Attestation remains gated behind review round 2 + the operator halt + the appeal. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-24 14:55:10 +00:00
post-flip drill over the chain certificate: HELD; audit gates now self-tested The window under audit claimed the campaign's first certificate, so this drill was maximally adversarial. Everything of substance HELD: - three-way model fidelity EXACT: extracted chain_free_loop.body == chainFoldN step == the Rust origin, operation-for-operation including address threading - button green fresh; axiom sweep over ALL 8 declarations minimal (pure lemmas = kernel-3; oracle-touching = kernel-3 + oracle.f only) - non-vacuity PROVEN: the concrete 1-step consequence (one address-set + one hash call) derives from the certificate by rfl - commit body of cfd50bb intact (the one flagged fragment was a bad drill grep pattern, not an artifact); worktree clean; heads synced NEW, from the drill (R3-5 tradition): verification/check-selftest.sh - permanent adversarial self-test of the check.sh gates. Attack 1 (dead Proofs file) and attack 2 (certificate with a smuggled axiom) must both make check.sh fail; both verified rejected, selftest green, self-cleaning. An audit that cannot fail is theater; this one demonstrably can. Two notes for the record: (a) bind_congr is the generic Bind-class congruence from core/Mathlib, not Aeneas.Std.Primitives (memory corrected); (b) the certificate covers chain_free_loop - the thin chain_free wrapper (bound computation + massert + clone) gets its trivial composition lemma in the wots layer, where it is consumed. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-23 12:34:42 +00:00
echo
round 7: assert pin-map completeness (NEW-13), correct the count to 137, fix the regeneration-scope contradiction The third reviewer demonstrated NEW-13: PROVENANCE.json is a tracked file that nothing pins, and Phase 0's only completeness test was 'is the map non-empty'. Deleting the harness_integrity_sha256 key therefore silently un-pinned BOTH lean-guard and Proofs/Audit.lean with no diagnostic, after which the round-6 logic mutation ran to ALL GREEN over a repository proving False with the digest byte-identical. Reproduced here before fixing. The required pin NAMES now live hardcoded in check.sh — policy in the root of trust, values in the map — so a shortened map is a build failure naming the missing entries. Self-test attack 18 performs the deletion. GPT reviewer, independently: the documented '131 assertion points' was wrong. Recounted from the code, the defensible figure is 137 mono-path evaluated cases (9 retained original + 108 randomized + 10 NIST internal + 10 NIST external-pure); 131 had folded in 3 deployed-only prehash cases while omitting the retained test, and TRUSTED-BASE then decomposed it as 20 + 108 = 128, contradicting itself. Item 9 now carries the full table, states that 127 of the 137 compare mono against deployed, keeps the 3 prehash cases explicitly outside the total, and records that only two SHA2-512 and one SHAKE-256 vector are executable there — so this is not NIST coverage of all four supported prehash variants. Also from GPT: PROVENANCE.json contradicted itself, saying extraction 'reproduces all four model files byte-identically' while its own _comment correctly said the two *External files are hand-maintained. Extraction regenerates two files; the other two are byte-pinned. Corrected. TRUSTED-BASE item 11 now discloses that PROVENANCE.json is itself load-bearing and unpinned, and item 7's stale snapshot head is fixed. README states the lean-guard graceful fallback and that the empirical bridge runs on stable Rust without any Lean toolchain (round-7 NEW-16), which is the first load-bearing part of this work a third party can reproduce with cargo alone. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-07-28 11:03:35 +00:00
echo "SELFTEST GREEN: 17 attacks rejected + digest-coverage check — dead files, extra axioms, dropped"
review round 5: bind the policy, the specification bodies, and the harness The third reviewer demonstrated that the round-4 gate was closed at the EXPLOITS, not the MECHANISMS: it bound the manifest rows while the things he moved sat outside the binding. Three fail-opens, each executed end-to-end with the button printing ALL GREEN. No theorem, proof, fold, or model body changed. NEW-1 — the policy constant was unbound. `manifestFingerprint` covered `manifest` but never `allowedBoundary`, the sole predicate the enumeration tests against; adding one name re-opened the False-proof with the committed fingerprint BYTE-IDENTICAL. NEW-2 — the specification bodies were unbound. The statement fingerprint pinned each certificate's TYPE, which names its reference fold; redefining that fold to *be* the extracted loop left cone and type-hash identical while the certificate degenerated to `loop = loop`. 100% of the fidelity content lives in those defs. NEW-3 — the harness was unbound. Stubbing verification/lean-guard alone, without touching check.sh or the proofs, gave ALL GREEN in 3.6s over destroyed proofs. FIX — one mechanism rather than three patches. Audit.lean now emits a canonical AUDIT-MANIFEST block and check.sh binds to its SHA-256. The block covers the POLICY constants, every certificate's fully-elaborated statement, and every specification constant transitively reachable from those statements with its fully-elaborated BODY (41 constants; the closure is computed, so a new fold cannot appear without moving the digest; Prop-valued constants contribute their statement, by proof irrelevance). This also retires the 32-bit Expr.hash as the binding (NEW-5) — it survives only as a per-certificate diagnostic. Enumeration now covers EVERY declaration kind (a `def : False` passed before) in the eight certificate modules AND in Audit.lean itself — the auditor is no longer exempt (round-5 R1). A bare `axiom` in audited scope is now an error. Phase 0 purges stale .olean (the verdict must depend on committed bytes, not .gitignored build state — NEW-4), forbids any .lean outside gen/ and Proofs/, and sha256-pins the four model files AND lean-guard. lean-guard is KEPT rather than removed (the reviewer's portability advice is declined by operator decision): it is the memory cap and machine-wide lock that protect the build machine after a 12.2GB OOM took the host down. That trade-off is documented. check.sh's "Certificates proven:" line now comes from the audited manifest; the hand-kept CERTS array — the one authoritative claim string nothing bound — is deleted. check-selftest.sh: 14 attacks, all rejected, plus a check that the hashed block literally carries the twelve fold bodies. Attacks 9-14 are the reviewers' and an independent drill's own exploits, turned into regression tests. DOCS. TRUSTED-BASE gains item 11 (the REAL trusted computing base — lean-guard pinned; check.sh, the toolchain env, $AENEAS_HOME, python3 and Lean still trusted) and item 12 (the apex does not compose the ten). README: the audit description rewritten; the XMSS sibling-order claim downgraded from "pins" to "makes visible", with a new blanket non-claim covering all ten loop certificates; the de-plumbing file claim corrected (round 1 touched only verify_mono.rs, round 2 only helpers.rs — which is ON the deployed verify AND sign paths, now disclosed; wots.rs was never patched). RECORDED-RUN: three lines that stood inside a fence were a hand-written summary, not console output — fabricated evidence in the file whose purpose is machine evidence. They are removed and the fabrication is named in place, together with the correction that the "INDEPENDENT RUN" block predates this gate. New rule: nothing goes in a fence unless captured with tee/cat, and every block states its date, pin, and who ran it. The transcripts added here follow it. Also disclosed rather than buried: three bugs in my own test harness this round (an olean-purge build-order break, an attack rejected by the wrong rule, and a coverage assertion looking on the wrong line) — each would have let an attack pass or fail for an unrelated reason. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-07-27 20:57:46 +00:00
echo "oracles, vanished certs, un-manifested False theorems AND defs, gutted"
echo "statements, hand-edited models, dropped manifest rows, widened policy,"
echo "specification folds redefined to the loop, a False-proof in the auditor,"
round 7: assert pin-map completeness (NEW-13), correct the count to 137, fix the regeneration-scope contradiction The third reviewer demonstrated NEW-13: PROVENANCE.json is a tracked file that nothing pins, and Phase 0's only completeness test was 'is the map non-empty'. Deleting the harness_integrity_sha256 key therefore silently un-pinned BOTH lean-guard and Proofs/Audit.lean with no diagnostic, after which the round-6 logic mutation ran to ALL GREEN over a repository proving False with the digest byte-identical. Reproduced here before fixing. The required pin NAMES now live hardcoded in check.sh — policy in the root of trust, values in the map — so a shortened map is a build failure naming the missing entries. Self-test attack 18 performs the deletion. GPT reviewer, independently: the documented '131 assertion points' was wrong. Recounted from the code, the defensible figure is 137 mono-path evaluated cases (9 retained original + 108 randomized + 10 NIST internal + 10 NIST external-pure); 131 had folded in 3 deployed-only prehash cases while omitting the retained test, and TRUSTED-BASE then decomposed it as 20 + 108 = 128, contradicting itself. Item 9 now carries the full table, states that 127 of the 137 compare mono against deployed, keeps the 3 prehash cases explicitly outside the total, and records that only two SHA2-512 and one SHAKE-256 vector are executable there — so this is not NIST coverage of all four supported prehash variants. Also from GPT: PROVENANCE.json contradicted itself, saying extraction 'reproduces all four model files byte-identically' while its own _comment correctly said the two *External files are hand-maintained. Extraction regenerates two files; the other two are byte-pinned. Corrected. TRUSTED-BASE item 11 now discloses that PROVENANCE.json is itself load-bearing and unpinned, and item 7's stale snapshot head is fixed. README states the lean-guard graceful fallback and that the empirical bridge runs on stable Rust without any Lean toolchain (round-7 NEW-16), which is the first load-bearing part of this work a third party can reproduce with cargo alone. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-07-28 11:03:35 +00:00
echo "a stubbed harness, stray modules, and a shortened pin map."