#!/usr/bin/env python3 """Validate the mirror-only security progress guardrails. This script is intentionally read-only. It checks committed snapshots only and does not call GitHub, Gitea, Kali, AwoooP, or any runtime API. """ from __future__ import annotations import argparse import json from pathlib import Path from typing import Any def load_json(path: Path) -> dict[str, Any]: return json.loads(path.read_text(encoding="utf-8")) def assert_equal(label: str, actual: Any, expected: Any) -> None: if actual != expected: raise SystemExit(f"BLOCKED {label}: expected {expected!r}, got {actual!r}") def assert_false(label: str, actual: Any) -> None: assert_equal(label, actual, False) def assert_true(label: str, actual: Any) -> None: assert_equal(label, actual, True) def assert_contains(label: str, values: list[Any], expected: Any) -> None: if expected not in values: raise SystemExit(f"BLOCKED {label}: missing {expected!r}") def validate(root: Path) -> None: security_dir = root / "docs" / "security" manifest = load_json(security_dir / "security-supply-chain-contract-manifest.snapshot.json") readiness = load_json(security_dir / "security-mirror-readiness.snapshot.json") rollup = load_json(security_dir / "security-mirror-status-rollup.snapshot.json") acceptance = load_json(security_dir / "security-mirror-acceptance.snapshot.json") dry_run = load_json(security_dir / "security-mirror-dry-run.snapshot.json") owner_rollup = load_json(security_dir / "source-control-owner-response-validation-rollup.snapshot.json") primary_gate = load_json(security_dir / "source-control-primary-readiness-gate.snapshot.json") manifest_count = manifest["contract_count"] readiness_summary = readiness["summary"] rollup_summary = rollup["summary"] assert_equal("manifest.contract_count", manifest_count, 35) assert_equal("readiness.total_contracts", readiness_summary["total_contracts"], manifest_count) assert_equal("rollup.total_contracts", rollup_summary["total_contracts"], manifest_count) assert_equal("rollup.ready_for_mirror_count", rollup_summary["ready_for_mirror_count"], 32) assert_equal("rollup.partial_ready_count", rollup_summary["partial_ready_count"], 2) assert_equal("rollup.contract_only_count", rollup_summary["contract_only_count"], 1) assert_equal("rollup.blocked_count", rollup_summary["blocked_count"], 0) progress = rollup["progress_estimate"] assert_equal("progress.overall_percent", progress["overall_percent"], 58) assert_equal("progress.framework_percent_min", progress["framework_percent_min"], 80) assert_equal("progress.framework_percent_max", progress["framework_percent_max"], 85) assert_equal("progress.runtime_landing_percent_min", progress["runtime_landing_percent_min"], 35) assert_equal("progress.runtime_landing_percent_max", progress["runtime_landing_percent_max"], 40) assert_true("progress.not_authorization", progress["not_authorization"]) assert_false("rollup.runtime_execution_authorized", rollup["runtime_execution_authorized"]) assert_equal("rollup.active_runtime_gate_count", rollup_summary["active_runtime_gate_count"], 0) assert_false("rollup.runtime_actions_executed", rollup_summary["runtime_actions_executed"]) assert_false("rollup.payloads_ingested", rollup_summary["payloads_ingested"]) assert_equal("rollup.github_primary_ready_count", rollup_summary["github_primary_ready_count"], 0) assert_equal("rollup.owner_response_validation_received_count", rollup_summary["owner_response_validation_received_count"], 0) assert_equal("rollup.owner_response_validation_accepted_count", rollup_summary["owner_response_validation_accepted_count"], 0) assert_equal("rollup.workflow_secret_inventory_complete_count", rollup_summary["workflow_secret_inventory_complete_count"], 0) assert_false("rollup.secret_value_collection_allowed", rollup_summary["secret_value_collection_allowed"]) assert_false("rollup.secret_value_detected", rollup_summary["secret_value_detected"]) owner_summary = owner_rollup["summary"] assert_equal("owner_rollup.total_received_response_count", owner_summary["total_received_response_count"], 0) assert_equal("owner_rollup.total_accepted_response_count", owner_summary["total_accepted_response_count"], 0) assert_false("owner_rollup.runtime_execution_authorized", owner_summary["runtime_execution_authorized"]) assert_false("owner_rollup.repo_creation_authorized", owner_summary["repo_creation_authorized"]) assert_false("owner_rollup.refs_sync_authorized", owner_summary["refs_sync_authorized"]) assert_false("owner_rollup.workflow_modification_authorized", owner_summary["workflow_modification_authorized"]) assert_false("owner_rollup.github_primary_switch_authorized", owner_summary["github_primary_switch_authorized"]) assert_false("owner_rollup.action_buttons_allowed", owner_summary["action_buttons_allowed"]) next_candidate = owner_rollup["next_collection_candidate"] assert_equal("owner_rollup.next_collection_candidate.order", next_candidate["order"], 1) assert_equal( "owner_rollup.next_collection_candidate.lane_id", next_candidate["lane_id"], "s4_9_gitea_inventory_owner_attestation_response", ) assert_equal( "owner_rollup.next_collection_candidate.display_status", next_candidate["display_status"], "next_owner_response_required", ) assert_equal( "owner_rollup.next_collection_candidate.required_response_template_count", next_candidate["required_response_template_count"], 5, ) assert_equal("owner_rollup.next_collection_candidate.received_response_count", next_candidate["received_response_count"], 0) assert_equal("owner_rollup.next_collection_candidate.accepted_response_count", next_candidate["accepted_response_count"], 0) assert_equal( "owner_rollup.next_collection_candidate.awooop_display_mode", next_candidate["awooop_display_mode"], "display_next_collection_item_only", ) assert_true("owner_rollup.next_collection_candidate.blocked_until_received", next_candidate["blocked_until_received"]) assert_false("owner_rollup.next_collection_candidate.execution_authorized", next_candidate["execution_authorized"]) assert_true("owner_rollup.next_collection_candidate.not_approval", next_candidate["not_approval"]) owner_local_validation = owner_rollup["latest_local_validation"] assert_equal("owner_rollup.latest_local_validation.status", owner_local_validation["status"], "repo_snapshot_guard_pass") assert_equal("owner_rollup.latest_local_validation.scope", owner_local_validation["scope"], "repo_snapshot_only") assert_equal("owner_rollup.latest_local_validation.result", owner_local_validation["result"], "SOURCE_CONTROL_OWNER_RESPONSE_GUARD_OK") assert_equal("owner_rollup.latest_local_validation.received_response_count", owner_local_validation["received_response_count"], 0) assert_equal("owner_rollup.latest_local_validation.accepted_response_count", owner_local_validation["accepted_response_count"], 0) assert_false("owner_rollup.latest_local_validation.runtime_actions_authorized", owner_local_validation["runtime_actions_authorized"]) assert_false("owner_rollup.latest_local_validation.repo_or_refs_actions_authorized", owner_local_validation["repo_or_refs_actions_authorized"]) assert_false("owner_rollup.latest_local_validation.workflow_or_secret_actions_authorized", owner_local_validation["workflow_or_secret_actions_authorized"]) assert_true("owner_rollup.latest_local_validation.not_authorization", owner_local_validation["not_authorization"]) primary_summary = primary_gate["summary"] assert_equal("primary_gate.primary_ready_count", primary_summary["primary_ready_count"], 0) assert_false("primary_gate.runtime_actions_authorized", primary_summary["runtime_actions_authorized"]) assert_false("primary_gate.github_primary_switch_authorized", primary_summary["github_primary_switch_authorized"]) assert_false("primary_gate.action_buttons_allowed", primary_summary["action_buttons_allowed"]) assert_false("primary_gate.raw_secret_storage_authorized", primary_summary["raw_secret_storage_authorized"]) acceptance_ids = [item["check_id"] for item in acceptance["acceptance_checks"]] assert_contains("acceptance_checks", acceptance_ids, "PROGRESS_ESTIMATE_NOT_AUTHORIZATION") assert_equal("acceptance.summary.acceptance_check_count", acceptance["summary"]["acceptance_check_count"], len(acceptance_ids)) assert_equal( "acceptance.summary.blocking_check_count", acceptance["summary"]["blocking_check_count"], sum(1 for item in acceptance["acceptance_checks"] if item["blocking_if_failed"]), ) assert_false("acceptance.runtime_execution_authorized", acceptance["runtime_execution_authorized"]) dry_run_summary = dry_run["summary"] dry_run_step_ids = [item["step_id"] for item in dry_run["dry_run_steps"]] assert_equal("dry_run.dry_run_status", dry_run["dry_run_status"], "contract_defined_not_executed") assert_equal("dry_run.total_contracts", dry_run_summary["total_contracts"], manifest_count) assert_equal("dry_run.acceptance_check_count", dry_run_summary["acceptance_check_count"], 8) assert_false("dry_run.runtime_execution_authorized", dry_run["runtime_execution_authorized"]) assert_false("dry_run.runtime_actions_executed", dry_run_summary["runtime_actions_executed"]) assert_false("dry_run.payloads_ingested", dry_run_summary["payloads_ingested"]) assert_contains("dry_run_steps", dry_run_step_ids, "CHECK_PROGRESS_GUARD") assert_contains("dry_run_steps", dry_run_step_ids, "CHECK_OWNER_RESPONSE_GUARD") local_validation = dry_run["latest_local_validation"] assert_equal("dry_run.latest_local_validation.status", local_validation["status"], "repo_snapshot_guard_pass") assert_equal("dry_run.latest_local_validation.scope", local_validation["scope"], "repo_snapshot_only") assert_equal( "dry_run.latest_local_validation.result", local_validation["result"], "SECURITY_MIRROR_PROGRESS_GUARD_OK; SOURCE_CONTROL_OWNER_RESPONSE_GUARD_OK", ) assert_contains("dry_run.latest_local_validation.validated_steps", local_validation["validated_steps"], "CHECK_PROGRESS_GUARD") assert_contains( "dry_run.latest_local_validation.validated_steps", local_validation["validated_steps"], "CHECK_OWNER_RESPONSE_GUARD", ) assert_false("dry_run.latest_local_validation.runtime_actions_executed", local_validation["runtime_actions_executed"]) assert_false("dry_run.latest_local_validation.payloads_ingested", local_validation["payloads_ingested"]) assert_false("dry_run.latest_local_validation.production_ingestion_enabled", local_validation["production_ingestion_enabled"]) assert_true("dry_run.latest_local_validation.not_authorization", local_validation["not_authorization"]) forbidden_actions = set(rollup["forbidden_actions"]) | set(acceptance["forbidden_actions"]) for action in [ "start_kali_scan", "call_kali_execute_endpoint", "create_github_repo", "change_repo_visibility", "sync_git_refs", "switch_github_primary", "production_deploy", ]: assert_contains("forbidden_actions", list(forbidden_actions), action) def main() -> None: parser = argparse.ArgumentParser(description=__doc__) parser.add_argument( "--root", default=Path(__file__).resolve().parents[2], type=Path, help="Repository root. Defaults to the current script's repository.", ) args = parser.parse_args() validate(args.root.resolve()) print("SECURITY_MIRROR_PROGRESS_GUARD_OK") if __name__ == "__main__": main()