#!/usr/bin/env python3 # SPDX-License-Identifier: GPL-3.0-or-later """Validate the fail-closed Phase-0.8 preflight record.""" from __future__ import annotations import argparse import json from pathlib import Path def load(path: Path) -> dict[str, object]: document = json.loads(path.read_text(encoding="utf-8")) if not isinstance(document, dict): raise RuntimeError(f"{path}: expected an object") return document def main() -> int: parser = argparse.ArgumentParser() parser.add_argument("--root", type=Path, required=True) args = parser.parse_args() root = args.root.resolve() audit = load(root / "manifests/runtime/phase-0.8-read-only-preflight.json") profile = load(root / "manifests/runtime/controlled-ps5-runtime-profile.json") locks = load(root / "manifests/upstreams.lock.json") if audit.get("decision") != "READ_ONLY_PREFLIGHT_BLOCKED": raise RuntimeError("Phase-0.8 no longer fails closed") if audit.get("scope") != "offline_admissibility_audit_only": raise RuntimeError("Phase-0.8 scope was widened") if audit.get("on_device_session_started") is not False: raise RuntimeError("Phase-0.8 incorrectly claims an on-device session") if audit.get("dataset_complete") is not False: raise RuntimeError("Phase-0.8 incorrectly claims a complete dataset") if audit.get("open_stop_ro") is not True or audit.get("open_stop_gate") is not True: raise RuntimeError("Phase-0.8 stop state is incomplete") authorization = audit["authorization"] false_authorizations = ( "explicit_read_only_preflight_permission_recorded", "connection_authorized", "installation_authorized", "lifecycle_authorized", "execution_authorized", "automatic_retry", ) if any(authorization[key] is not False for key in false_authorizations): raise RuntimeError("Phase-0.8 records unauthorized authority") if ( authorization["permission_reference"] is not None or authorization["permission_exact_text"] is not None ): raise RuntimeError("Phase-0.8 invents a permission record") if any(audit["ps5_actions"].values()): raise RuntimeError("Phase-0.8 records an on-device action") collector = audit["collector_assessment"] if collector["selected_collector"] is not None: raise RuntimeError("Phase-0.8 selected an inadmissible collector") if collector["can_prove_no_atime_audit_cache_or_metadata_change"] is not False: raise RuntimeError("Phase-0.8 overstates collector side-effect proof") candidates = {item["id"]: item for item in collector["candidates"]} payload_manager = candidates["payload_manager_v0_3_1_http"] if payload_manager["usable"] is not False or payload_manager["result"] != "STOP-RO": raise RuntimeError("stock Payload Manager HTTP was promoted") manager_lock = locks["sources"]["ps5_payload_manager"] if payload_manager["source_commit"] != manager_lock["commit"]: raise RuntimeError("Payload Manager preflight source is not pinned") required_blockers = { "explicit_permission_record_absent": "STOP-RO", "collector_side_effect_freedom_unproven": "STOP-RO", "payload_manager_http_mutates_runtime_state": "STOP-RO", "two_source_firmware_attestation_absent": "STOP-GATE", "current_live_identity_and_topology_absent": "STOP-GATE", "autoload_startup_retry_state_absent": "STOP-GATE", "stock_elfldr_backup_unproven": "STOP-GATE", "stock_payload_manager_backup_unproven": "HARD_STOP-GATE", } blockers = {item["id"]: item["severity"] for item in audit["blockers"]} if blockers != required_blockers: raise RuntimeError("Phase-0.8 blocker set changed") if audit["firmware"]["two_current_sources_agree"] != "UNPROVEN": raise RuntimeError("Phase-0.8 invents a second firmware source") if ( audit["rollback_preconditions"]["stock_payload_manager_backup"]["result"] != "HARD_STOP-GATE" ): raise RuntimeError("Payload Manager rollback hard gate disappeared") if audit["payload_manager_backup_exactly_present"] != "UNPROVEN": raise RuntimeError("Phase-0.8 invents an exact manager backup") if audit["historical_evidence_is_not_current_preflight_evidence"] is not True: raise RuntimeError("historical observations were promoted to current evidence") if profile["deployment"]["installed"] is not False: raise RuntimeError("Phase-0.8 incorrectly marks the hardened runtime installed") if profile["execution_authorized"] is not False: raise RuntimeError("Phase-0.8 widened execution authority") print("Phase-0.8 read-only preflight remains blocked without PS5 contact") return 0 if __name__ == "__main__": raise SystemExit(main())