#!/usr/bin/env python3 # SPDX-License-Identifier: GPL-3.0-or-later """Twenty-two host-only guardrails for Phase 0.9E-R.""" from __future__ import annotations import argparse import copy import importlib.util from pathlib import Path import sys from types import ModuleType from typing import Callable def load_module(name: str, path: Path) -> ModuleType: spec = importlib.util.spec_from_file_location(name, path) if spec is None or spec.loader is None: raise RuntimeError(f"could not load {path}") module = importlib.util.module_from_spec(spec) sys.modules[name] = module spec.loader.exec_module(module) return module def require(condition: bool, message: str) -> None: if not condition: raise RuntimeError(message) def main() -> int: parser = argparse.ArgumentParser() parser.add_argument("--root", type=Path, required=True) args = parser.parse_args() root = args.root.resolve() validator = load_module( "phase09er_validator", root / "tools/validate_phase09er_provenance.py" ) manifest = validator.load_json( root / "manifests/runtime/phase-0.9e-r-release-correlation.json" ) port_manifest = validator.load_json( root / "manifests/runtime/phase-0.9e-r-port9020-audit.json" ) cases: list[tuple[str, Callable[[], None]]] = [] def case(name: str) -> Callable[[Callable[[], None]], Callable[[], None]]: def register(function: Callable[[], None]) -> Callable[[], None]: cases.append((name, function)) return function return register @case("01 name match alone is not a byte match") def _() -> None: require( not validator.official_byte_match( official_source=True, local_name="same.zip", local_size=1, local_sha256="a" * 64, asset_name="same.zip", asset_size=2, asset_sha256="b" * 64, ), "name-only candidate became a byte match", ) @case("02 size match alone is not a byte match") def _() -> None: require( not validator.official_byte_match( official_source=True, local_name="local.zip", local_size=10, local_sha256="a" * 64, asset_name="asset.zip", asset_size=10, asset_sha256="b" * 64, ), "size-only candidate became a byte match", ) @case("03 hash match also requires exact byte count") def _() -> None: require( not validator.official_byte_match( official_source=True, local_name="same.zip", local_size=10, local_sha256="a" * 64, asset_name="same.zip", asset_size=11, asset_sha256="a" * 64, ), "hash with a different byte count became a match", ) @case("04 a mirror cannot establish an official byte match") def _() -> None: require( not validator.official_byte_match( official_source=False, local_name="same.zip", local_size=10, local_sha256="a" * 64, asset_name="same.zip", asset_size=10, asset_sha256="a" * 64, ), "non-official mirror established an official match", ) @case("05 release association is not inner-content binding") def _() -> None: require( validator.source_binding( release_associated=True, inner_bytes_matched=False, inner_opaque=True, ) == "SOURCE_ONLY_ASSOCIATION", "release association was promoted to reproducible content", ) @case("06 opaque SIECAF receives no invented provenance") def _() -> None: require( manifest["inner_archive"]["classification"] == "OPAQUE_UNBOUND" and manifest["inner_archive"]["further_reverse_engineering_performed"] is False, "opaque inner archive provenance was overclaimed", ) @case("07 public release commits are exact") def _() -> None: for tag in manifest["tags"]: require( len(tag["commit"]) == 40 and all(character in "0123456789abcdef" for character in tag["commit"]), f"release commit is not exact: {tag['tag']}", ) @case("08 each source archive is hashed") def _() -> None: for tag in manifest["tags"]: require( len(tag["source_archive_sha256"]) == 64, f"source archive hash missing: {tag['tag']}", ) @case("09 upstream worktree must be clean") def _() -> None: changed = copy.deepcopy(manifest) changed["upstream_worktree"]["clean"] = False require( bool(validator.validate_release_manifest(changed)), "dirty upstream worktree passed", ) @case("10 port reference is not an implementation") def _() -> None: require( not validator.port_implementation_sufficient("PORT_9020_REFERENCE_ONLY"), "reference-only text was accepted as implementation", ) @case("11 embedded bytes receive no invented source commit") def _() -> None: changed = copy.deepcopy(port_manifest) changed["port_9021_relation"]["source_commit"] = "0" * 40 require( bool(validator.validate_port_manifest(changed)), "embedded loader bytes accepted an invented source commit", ) @case("12 a sender without receive is not duplex") def _() -> None: require( not validator.sender_duplex(sends=True, receives=False), "one-way sender became duplex", ) @case("13 missing short-send handling is a deficiency") def _() -> None: require( validator.sender_short_send_deficiency( uses_sendall=False, explicit_send_loop=False ), "missing short-send handling was accepted", ) require( not validator.sender_short_send_deficiency( uses_sendall=True, explicit_send_loop=False ), "sendall was incorrectly marked as lacking short-send handling", ) @case("14 operator attestation is not runtime evidence") def _() -> None: require( not validator.attestation_is_runtime_proof( attested=True, hardware_observed=False ), "operator attestation became runtime proof", ) @case("15 empty attestation authorizes nothing") def _() -> None: text = ( root / "docs/approvals/phase-0.9e-r-y2jb-deployed-use-attestation.md" ).read_text(encoding="utf-8") require("attested: false" in text, "template became attested") for field in validator.AUTHORIZATION_FIELDS: require(f"{field}: false" in text, f"template omits false {field}") @case("16 Phase 0.9F blocks without official match") def _() -> None: require( not validator.phase09f_design_allowed( correlation="OFFICIAL_RELEASE_NO_MATCH", release_commit_known=True, upstream_clean=True, port_classification="PORT_9020_IMPLEMENTATION_FOUND", sender_identified=True, attestation_available=True, all_authorizations_false=True, ), "Phase 0.9F passed without an official asset match", ) @case("17 Phase 0.9F blocks without found or partial loader") def _() -> None: require( not validator.phase09f_design_allowed( correlation="OFFICIAL_RELEASE_BYTE_MATCH", release_commit_known=True, upstream_clean=True, port_classification="PORT_9020_REFERENCE_ONLY", sender_identified=True, attestation_available=True, all_authorizations_false=True, ), "Phase 0.9F passed with a reference-only loader", ) @case("18 no target source appears") def _() -> None: errors = validator.phase09er_path_errors( {"docs/runtime/phase-0.9e-r-note.md", "src/backends/ps5/rescue.c"} ) require(any("target" in error for error in errors), "target source guard failed") require( not validator.phase09er_path_errors( {"docs/runtime/phase-0.9e-r-note.md"} ), "documentation was rejected as target source", ) @case("19 no target artifact appears") def _() -> None: require( bool(validator.phase09er_path_errors({"packaging/rescue.elf"})), "target artifact guard failed", ) @case("20 all authorization fields remain false") def _() -> None: changed = copy.deepcopy(manifest) changed["authorization"]["execution_authorized"] = True require( bool(validator.validate_release_manifest(changed)), "true authorization passed", ) @case("21 automatic retry remains false") def _() -> None: require( manifest["authorization"]["automatic_retry"] is False and port_manifest["authorization"]["automatic_retry"] is False and port_manifest["official_remote_js_loader"][ "automatic_retry_authorized" ] is False, "automatic retry was authorized", ) @case("22 no large release asset enters Git") def _() -> None: actions = manifest["actions"] require( actions["large_release_assets_downloaded"] == 0 and actions["large_release_asset_bytes_downloaded"] == 0, "a large official release asset was recorded as downloaded", ) for path in root.rglob("*"): if ( path.is_file() and ".git" not in path.parts and "work" not in path.parts ): require( path.stat().st_size <= 50 * 1024 * 1024, f"large release-like file entered repository: {path}", ) failures: list[str] = [] for name, function in cases: try: function() except Exception as error: # guardrail harness reports all failures failures.append(f"{name}: {error}") if failures: for failure in failures: print(f"FAIL: {failure}") return 1 print(f"Phase-0.9E-R provenance guardrails: {len(cases)}/{len(cases)} PASS") return 0 if __name__ == "__main__": raise SystemExit(main())