#!/usr/bin/env python3 # SPDX-License-Identifier: GPL-3.0-or-later """Host guardrails for the blocked Phase-0.9C feasibility closure.""" 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 require_invalid(errors: list[str], scenario: str) -> None: require(bool(errors), f"unsafe Phase-0.9C mutation passed: {scenario}") 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( "phase09c_validator", root / "tools/validate_phase09c_feasibility.py" ) manifest = validator.load_json( root / "manifests/runtime/phase-0.9c-feasibility.json" ) schema = validator.load_json( root / "manifests/runtime/phase-0.9c-feasibility.schema.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("complete offline validator") def _() -> None: require(validator.collect_errors(root) == [], "current audit does not validate") @case("manifest and schema") def _() -> None: require(validator.validate_manifest(manifest) == [], "manifest invalid") require( validator.validate_schema_instance(schema, manifest) == [], "schema rejected manifest", ) @case("authorization remains false") def _() -> None: for field in validator.AUTHORIZATION_FIELDS: changed = copy.deepcopy(manifest) changed["authorization"][field] = True require_invalid(validator.validate_manifest(changed), field) @case("positive classification rejected") def _() -> None: changed = copy.deepcopy(manifest) changed["status"] = "READY" changed["classification"] = ( "FEASIBILITY_CONTRACT_PROVEN_NO_TARGET_IMPLEMENTATION" ) changed["final_decision"]["positive_classification_allowed"] = True changed["final_decision"]["classification"] = changed["classification"] require_invalid(validator.validate_manifest(changed), "positive decision") @case("startup and cleanup promotion rejected") def _() -> None: for field in ( "normal_sdk_kernelwrite_free", "freestanding_dependency_closure_proven", "safe_return_proven", "safe_process_exit_proven", "error_exit_proven", "timeout_safe_exit_proven", "complete_cleanup_proven", ): changed = copy.deepcopy(manifest) changed["startup_exit"][field] = True require_invalid(validator.validate_manifest(changed), field) @case("fabricated firmware source rejected") def _() -> None: changed = copy.deepcopy(manifest) changed["firmware"]["source_two"]["identity"] = "invented" changed["firmware"]["source_two"]["status"] = "PROVEN" changed["firmware"]["agreement_proven"] = True require_invalid(validator.validate_manifest(changed), "firmware source two") @case("output implementation promotion rejected") def _() -> None: changed = copy.deepcopy(manifest) changed["output_architectures"][0]["current_implementation"] = True changed["host_protocol"]["target_implemented"] = True require_invalid(validator.validate_manifest(changed), "output implementation") @case("capability implementation and execution rejected") def _() -> None: changed = copy.deepcopy(manifest) changed["capability_closure"][0]["implementation_allowed"] = True changed["capability_closure"][0]["execution_allowed"] = True changed["capability_closure"][0]["target_evidence"] = "PROVEN" require_invalid(validator.validate_manifest(changed), "capability promotion") @case("artifact and package rejected") def _() -> None: changed = copy.deepcopy(manifest) changed["artifact"] = { "present": True, "path": "phase09c-observer.elf", "sha256": "1" * 64, "size": 1, "execution_eligible": False, "execution_authorized": False, } changed["implementation"]["target_elf_present"] = True require_invalid(validator.validate_manifest(changed), "artifact") for path in ( "samples/phase09c_observer/main.c", "outputs/phase09c-observer.elf", "outputs/phase-0.9c-observer.map", "packaging/phase09c/install.zip", "packaging/phase09c/lifecycle.pkg", "packaging/phase09c/autoload.json", ): require(validator.forbidden_repository_path(path), path) @case("host files remain permitted") def _() -> None: for path in ( "docs/runtime/phase-0.9c-static-audit.md", "tests/phase09c_feasibility_model.py", "tests/test_phase09c_protocol.py", "tools/validate_phase09c_feasibility.py", "packaging/phase09c/SHA256SUMS.txt", ): require(not validator.forbidden_repository_path(path), path) @case("side-effect false promotion rejected") def _() -> None: for field in ( "no_persistent_content_write_is_side_effect_free", "read_only_flag_is_side_effect_free", "all_planned_observations_proven_side_effect_free", ): changed = copy.deepcopy(manifest) changed["side_effect_model"][field] = True require_invalid(validator.validate_manifest(changed), field) @case("permanent denylist and immutable evidence") def _() -> None: require( validator.validate_immutable_evidence(root) == [], "immutable evidence changed", ) denylist = validator.load_json(root / "manifests/artifact-denylist.json") entry = denylist["entries"][0] require(entry["sha256"] == validator.BLOCKED_HASH, "denylist hash changed") require(entry["permanent"] is True, "denylist is not permanent") require( entry["execution_eligible"] is False, "denylisted artifact became eligible", ) for name, function in cases: try: function() except Exception as error: raise RuntimeError( f"Phase-0.9C feasibility case failed: {name}: {error}" ) from error print(f"Phase-0.9C feasibility host tests: {len(cases)}/{len(cases)} PASS") return 0 if __name__ == "__main__": raise SystemExit(main())