#!/usr/bin/env python3 """Validate the active selected-case publication gate.""" from __future__ import annotations import argparse import hashlib import json from pathlib import Path from typing import Any ROOT = Path(__file__).resolve().parents[1] GATE = Path("coverage/release-authorized-gate.report.json") EXPECTED_SCHEMA = "release-authorized-gate.v1" EXPECTED_SCOPE = "selected_case_web_wasm_simulation" def canonical(value: Any) -> str: return json.dumps(value, ensure_ascii=False, sort_keys=True, separators=(",", ":")) def validate(root: Path, gate_path: Path = GATE) -> dict[str, Any]: root = root.resolve() path = gate_path if gate_path.is_absolute() else root / gate_path report = json.loads(path.read_text(encoding="utf-8")) unsigned = {key: value for key, value in report.items() if key != "report_sha256"} expected_hash = hashlib.sha256(canonical(unsigned).encode("utf-8")).hexdigest() errors: list[str] = [] if report.get("schema") != EXPECTED_SCHEMA: errors.append("schema_invalid") if report.get("status") != "authorized": errors.append("gate_not_authorized") if report.get("implementation_status") != "verified": errors.append("implementation_not_verified") if report.get("release_scope") != EXPECTED_SCOPE: errors.append("scope_invalid") if report.get("candidate_eligible") is not True: errors.append("candidate_not_eligible") if report.get("release_action") != "ALLOW_RELEASE": errors.append("release_action_not_allowed") if report.get("remaining_blockers") != []: errors.append("remaining_blockers_present") if report.get("report_sha256") != expected_hash: errors.append("report_hash_invalid") if not all(item.get("hash_match") is True for item in report.get("evidence", [])): errors.append("evidence_hash_invalid") if report.get("risk_boundary", {}).get("technical_evidence_rewritten") is not False: errors.append("technical_evidence_was_rewritten") return {"status": "authorized" if not errors else "blocked", "release_action": "ALLOW_RELEASE" if not errors else "STOP_RELEASE", "scope": report.get("release_scope"), "errors": errors, "report_sha256": report.get("report_sha256")} def main() -> int: parser = argparse.ArgumentParser() parser.add_argument("--repo-root", type=Path, default=ROOT) parser.add_argument("--gate", type=Path, default=GATE) args = parser.parse_args() result = validate(args.repo_root, args.gate) print(json.dumps(result, ensure_ascii=False, sort_keys=True)) return 0 if result["status"] == "authorized" else 1 if __name__ == "__main__": raise SystemExit(main())