Files
felhom.eu/scripts/test_iso_bootstrap_gate.py
T
admin 9d39faabf8 R-502: the ISO first-boot harness is a gate, full runs only, "not checked" without docker
iso_bootstrap_gate.py runs scripts/iso/test/bootstrap-modes.sh in felhom-iso-assistant:trixie
(staged copy, read-only mount, --network none), registered fast=False in repo_gates.py so the
pre-push hook and CI (both --fast) never run it (decision 147). No docker / no image / docker
error -> exit 2 NOT CHECKED. Every green run is followed by a built-in decoy: the harness must
FAIL a bootstrap whose pairing banner never paints (R-496 shape), or the gate convicts the
instrument as blind. Docker-free decoys in test_iso_bootstrap_gate.py (fake docker on a
one-directory PATH), run from test_gate_decoys.py (COVERS).

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_0159rPz1ZhFKsS53msqPYxtS
2026-10-06 11:29:17 +02:00

148 lines
6.1 KiB
Python

#!/usr/bin/env python3
# -*- coding: utf-8 -*-
"""Decoys for scripts/iso_bootstrap_gate.py (R-502). DOCKER-FREE — runs on the CI runner (BusyBox +
python3 + git) and on DooPlex alike, and never reaches the real docker.
HOW. The gate finds docker with shutil.which, so every case runs the REAL gate as a subprocess with
PATH set to ONE temp directory: empty (no docker), or holding a FAKE `docker` written in python with
an absolute shebang (so it needs nothing else on PATH — /usr/bin, where the real docker lives on
DooPlex, is never on it). The fake answers `image inspect` and `run` per FAKE_DOCKER_MODE, and for
`run` reads the STAGED felhom-bootstrap.sh from the `-v <dir>:/src:ro` mount, so it can tell the
genuine run from the gate's built-in banner decoy.
What the fake cannot do is run the harness — that needs root and the image. The harness's power to
see a broken banner is proven by the gate itself, in the real container, on every full run (its
built-in decoy). This file proves the gate's verdicts: that a blind harness, a failing harness, a
harness that checked nothing, and an unrun harness can never read as green.
Run: python3 scripts/test_iso_bootstrap_gate.py
"""
import os
import shutil
import subprocess
import sys
import tempfile
import unittest
HERE = os.path.dirname(os.path.abspath(__file__))
ROOT = os.path.dirname(HERE)
GATE = os.path.join(HERE, "iso_bootstrap_gate.py")
sys.path.insert(0, HERE)
import iso_bootstrap_gate as g # noqa: E402
import repo_gates # noqa: E402
FAKE = r'''#!%(py)s
import os, re, sys
mode = os.environ.get("FAKE_DOCKER_MODE", "genuine")
a = sys.argv[1:]
log = os.environ.get("FAKE_DOCKER_LOG")
if log:
open(log, "a").write(" ".join(a) + "\n")
if a[:2] == ["image", "inspect"]:
sys.exit(1 if mode == "no-image" else 0)
if a[:1] == ["rm"]:
sys.exit(0)
if a[:1] != ["run"]:
sys.exit(3)
if mode == "daemon-error":
print("docker: Error response from daemon: something broke."); sys.exit(125)
src = [x for x in a if x.endswith(":/src:ro")][0][:-len(":/src:ro")]
mutant = "R-502 planted decoy" in open(os.path.join(src, "felhom-bootstrap.sh"), encoding="utf-8").read()
oks = "".join(" ok: check %%d\n" %% i for i in range(60))
if mode == "fails" or (mutant and mode != "blind"):
print(oks + " FAIL: R-496: banner painted to the console seam\nSOME TESTS FAILED"); sys.exit(1)
if mode == "hollow":
print("ALL BOOTSTRAP-MODE TESTS PASSED"); sys.exit(0)
print(oks + "ALL BOOTSTRAP-MODE TESTS PASSED"); sys.exit(0)
'''
def run_gate(mode=None):
"""Run the real gate. mode None = no docker on PATH at all."""
d = tempfile.mkdtemp(prefix="iso-gate-test-")
try:
log = os.path.join(d, "calls.log")
if mode is not None:
p = os.path.join(d, "docker")
with open(p, "w") as f:
f.write(FAKE % {"py": sys.executable})
os.chmod(p, 0o755)
env = {"PATH": d, "FAKE_DOCKER_MODE": mode or "", "FAKE_DOCKER_LOG": log,
"HOME": d, "PYTHONDONTWRITEBYTECODE": "1"}
r = subprocess.run([sys.executable, GATE], cwd=ROOT, env=env,
stdout=subprocess.PIPE, stderr=subprocess.STDOUT)
calls = ""
if os.path.exists(log):
with open(log) as f:
calls = f.read()
return r.returncode, r.stdout.decode("utf-8", "replace"), calls
finally:
shutil.rmtree(d, ignore_errors=True)
class IsoBootstrapGateTest(unittest.TestCase):
def test_genuine_passes_and_runs_the_decoy_too(self):
rc, out, calls = run_gate("genuine")
self.assertEqual(rc, 0, out)
self.assertIn("built-in decoy convicted", out)
self.assertEqual(calls.count("run "), 2, "want the genuine run AND the decoy run:\n" + calls)
self.assertIn("--network none", calls)
def test_blind_harness_convicts(self):
# The harness passes a bootstrap whose banner never paints: the R-496 shape. Must be 1.
rc, out, _ = run_gate("blind")
self.assertEqual(rc, 1, out)
self.assertIn("instrument is blind", out)
def test_failing_harness_convicts(self):
rc, out, calls = run_gate("fails")
self.assertEqual(rc, 1, out)
self.assertIn("FAIL: R-496: banner painted", out)
self.assertEqual(calls.count("run "), 1)
def test_pass_line_without_checks_convicts(self):
rc, out, _ = run_gate("hollow")
self.assertEqual(rc, 1, out)
self.assertIn("proved nothing", out)
def test_no_docker_is_not_checked(self):
rc, out, _ = run_gate(None)
self.assertEqual(rc, 2, out)
self.assertIn("NOT CHECKED", out)
def test_no_image_is_not_checked(self):
rc, out, calls = run_gate("no-image")
self.assertEqual(rc, 2, out)
self.assertIn("NOT CHECKED", out)
self.assertNotIn("run ", calls)
def test_docker_error_is_not_checked(self):
rc, out, _ = run_gate("daemon-error")
self.assertEqual(rc, 2, out)
def test_decoy_plants_on_the_real_bootstrap(self):
# The built-in decoy's anchor must exist ONCE in the real script, and the plant must apply.
d = tempfile.mkdtemp()
try:
self.assertIsNone(g.stage(d, mutate=True))
with open(os.path.join(d, "felhom-bootstrap.sh"), encoding="utf-8") as f:
text = f.read()
self.assertIn("R-502 planted decoy", text)
for _src, rel in g.INPUTS:
self.assertTrue(os.path.exists(os.path.join(d, rel)), rel)
finally:
shutil.rmtree(d, ignore_errors=True)
def test_registered_full_runs_only(self):
# Decision 147: never in --fast (pre-push hook and CI both run --fast; CI has no docker).
rows = [r for r in repo_gates.GATES if r[0] == "iso-bootstrap"]
self.assertEqual(len(rows), 1, "iso-bootstrap must be registered once in repo_gates.GATES")
self.assertTrue(rows[0][1].endswith("iso_bootstrap_gate.py"))
self.assertIs(rows[0][3], False, "iso-bootstrap must be fast=False (full runs only)")
self.assertIs(rows[0][4], False, "iso-bootstrap must not be exemptible")
if __name__ == "__main__":
unittest.main(verbosity=2)