Files
awoooi/scripts/security/high-value-config-control-coverage.py
Your Name 45c2b8ebe6
All checks were successful
Code Review / ai-code-review (push) Successful in 12s
CD Pipeline / tests (push) Successful in 1m48s
CD Pipeline / build-and-deploy (push) Successful in 6m0s
CD Pipeline / post-deploy-checks (push) Successful in 2m19s
feat(iwooos): 新增 K8s ArgoCD 事故回讀 gate
2026-06-15 20:42:12 +08:00

502 lines
30 KiB
Python
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
#!/usr/bin/env python3
"""
IwoooS 高價值配置控管覆蓋矩陣。
本工具讀取 high-value-config-change-gate.py 的 CATEGORIES 定義,產生一份
全域配置控管覆蓋 snapshot。它只整理 source-of-truth、owner gate、
evidence refs、缺口與 0/false 邊界,不讀 live host、不連外、不執行
Nginx / DNS / K8s / workflow / agent runtime 動作。
"""
from __future__ import annotations
import argparse
import json
import runpy
import subprocess
import sys
from datetime import datetime, timedelta, timezone
from pathlib import Path
from typing import Any
TAIPEI = timezone(timedelta(hours=8))
CONTROL_STATUS_BY_CATEGORY = {
"nginx_public_gateway": {
"coverage_status": "emergency_change_backfill_ready_needs_owner_live_diff",
"coverage_percent": 90,
"evidence_refs": [
"docs/security/NGINX-CONFIG-DRIFT-DETECTOR.md",
"docs/security/nginx-config-drift-repo.snapshot.json",
"docs/security/DOMAIN-TLS-CERTBOT-INVENTORY.md",
"docs/security/PUBLIC-GATEWAY-PREFLIGHT-INVENTORY.md",
"docs/security/public-gateway-preflight-inventory.snapshot.json",
"docs/security/PUBLIC-GATEWAY-OWNER-RESPONSE-ACCEPTANCE.md",
"docs/security/public-gateway-owner-response-acceptance.snapshot.json",
"docs/security/PUBLIC-GATEWAY-RENDERED-DIFF-ACCEPTANCE.md",
"docs/security/public-gateway-rendered-diff-acceptance.snapshot.json",
"docs/schemas/public_gateway_preflight_inventory_v1.schema.json",
],
"current_gap": "已固定 owner response acceptance、手動 / 緊急 gateway 變更回補欄位與 rendered diff evidence acceptance 只讀帳本owner response、live conf、rendered diff evidence、nginx -t evidence、route smoke evidence、maintenance window 與 rollback owner 仍全部為 0。",
"next_owner_action": "補 public gateway owner 回覆、owner-provided live conf、source-to-live rendered diff ref、nginx -t evidence ref、route smoke evidence ref、change intent / break-glass、route health impact、rollback validation、maintenance window 與 rollback owner。",
},
"dns_tls_certbot": {
"coverage_status": "owner_response_acceptance_ledger_ready_needs_certificate_owner_evidence",
"coverage_percent": 78,
"evidence_refs": [
"docs/security/DOMAIN-TLS-CERTBOT-INVENTORY.md",
"docs/security/domain-tls-certbot-inventory.snapshot.json",
"docs/security/DOMAIN-TLS-CERTBOT-OWNER-CONFIRMATION-REQUEST.md",
"docs/security/domain-tls-certbot-owner-confirmation-request.snapshot.json",
"docs/security/DOMAIN-TLS-CERTBOT-OWNER-RESPONSE-ACCEPTANCE.md",
"docs/security/domain-tls-certbot-owner-response-acceptance.snapshot.json",
],
"current_gap": "已固定 4 份 DNS / TLS / certbot owner response acceptance candidate仍缺 owner response、certificate coverage metadata ref、expiry metadata ref、renewal owner、ACME route owner、maintenance window、rollback owner 與 validation plan。",
"next_owner_action": "補 SAN / wildcard / 共用憑證覆蓋依據 ref、到期 metadata ref、renewal owner、ACME route owner、維護窗口、rollback owner 與 validation plan。",
},
"k8s_production_gitops": {
"coverage_status": "post_incident_readback_plan_ready_needs_gitops_owner_evidence",
"coverage_percent": 66,
"evidence_refs": [
"docs/security/HIGH-VALUE-CONFIG-CHANGE-GATE.md",
"docs/security/K8S-ARGOCD-MANIFEST-INVENTORY.md",
"docs/security/k8s-argocd-manifest-inventory.snapshot.json",
"docs/security/K8S-ARGOCD-OWNER-RESPONSE-ACCEPTANCE.md",
"docs/security/k8s-argocd-owner-response-acceptance.snapshot.json",
"docs/security/K8S-ARGOCD-CHANGE-EVIDENCE-ACCEPTANCE.md",
"docs/security/k8s-argocd-change-evidence-acceptance.snapshot.json",
"docs/security/K8S-ARGOCD-POST-INCIDENT-READBACK-PLAN.md",
"docs/security/k8s-argocd-post-incident-readback-plan.snapshot.json",
"k8s/awoooi-prod",
"k8s/argocd",
],
"current_gap": "已固定 owner response acceptance、GitOps 變更證據驗收與事故後回讀計畫只讀帳本ArgoCD sync / health / degraded、Pending workload、image pull / scheduling、rollout before-after、event / metrics / alert、drift scanner、CronJob schedule、NetworkPolicy / RBAC、route / AI provider / monitoring 影響、防再發與 no-false-green 已納入;仍缺 owner response、事故回讀包、rendered manifest diff、ArgoCD revision、maintenance window、rollback revision、post-check owner 與 no-secret-value evidence。",
"next_owner_action": "補 GitOps / K8s 事故回讀包incident / change ref、actor role / team、ArgoCD sync / health / revision、degraded / Pending / image pull / scheduling 摘要、rollout before-after、event summary、metrics / alert、drift scanner、CronJob schedule、NetworkPolicy / Service / RBAC 影響、public/admin route、AI provider、monitoring、operator notification、cross-project sync、recovery 或 still-degraded ref、recurrence guard、maintenance window、rollback revision、rollback owner、post-check owner 與 no-secret-value evidence。",
},
"secret_metadata": {
"coverage_status": "secret_injection_change_evidence_acceptance_ready_needs_owner_evidence",
"coverage_percent": 68,
"evidence_refs": [
"docs/security/SOURCE-CONTROL-WORKFLOW-SECRET-NAME-INVENTORY.md",
"docs/security/source-control-workflow-secret-name-inventory.snapshot.json",
"docs/security/SOURCE-CONTROL-WORKFLOW-SECRET-NAME-OWNER-RESPONSE.md",
"docs/security/source-control-workflow-secret-name-owner-response.snapshot.json",
"docs/security/CD-RUNNER-SECRET-INJECTION-CHANGE-EVIDENCE-ACCEPTANCE.md",
"docs/security/cd-runner-secret-injection-change-evidence-acceptance.snapshot.json",
"docs/security/SECRETS_REFERENCE.md",
],
"current_gap": "已固定 secret name / injection owner 變更證據驗收帳本secret value、hash、partial token、secret store read、secret rotation、repo secret change 與 injection path change 仍全部為 0。",
"next_owner_action": "補 secret name parity ref、injection route owner、rotation owner、guard result ref、rollback owner、post-check evidence 與 redacted evidence refs。",
},
"gitea_workflow_runner_source_control": {
"coverage_status": "cd_runner_secret_injection_change_evidence_acceptance_ready_needs_owner_evidence",
"coverage_percent": 72,
"evidence_refs": [
"docs/security/SOURCE-CONTROL-WORKFLOW-SECRET-NAME-INVENTORY.md",
"docs/security/SOURCE-CONTROL-WORKFLOW-SECRET-NAME-OWNER-RESPONSE.md",
"docs/security/CD-RUNNER-SECRET-INJECTION-CHANGE-EVIDENCE-ACCEPTANCE.md",
"docs/security/cd-runner-secret-injection-change-evidence-acceptance.snapshot.json",
"docs/security/SOURCE-CONTROL-PRIMARY-READINESS-GATE.md",
],
"current_gap": "已固定 CD / runner / secret injection 變更證據驗收帳本workflow diff、runner attestation、secret parity、guard result、deploy marker readback、rollback owner 與 post-check evidence 仍全部為 0。",
"next_owner_action": "補 workflow diff ref、runner owner attestation、secret name parity ref、Gitea run readback、guard result、maintenance window、rollback owner 與 post-check evidence。",
},
"public_admin_api_runtime_config": {
"coverage_status": "frontend_sensitive_surface_guard_ready_needs_runtime_config_owner_evidence",
"coverage_percent": 66,
"evidence_refs": [
"docs/HARD_RULES.md",
"docs/security/IWOOOS-CONFIG-CONTROL-INVENTORY.md",
"docs/security/PUBLIC-RUNTIME-CONFIG-CHANGE-EVIDENCE-ACCEPTANCE.md",
"docs/security/public-runtime-config-change-evidence-acceptance.snapshot.json",
"docs/security/public-frontend-sensitive-surface-guard.snapshot.json",
],
"current_gap": "已固定 Public / Admin / API runtime config 變更證據驗收只讀帳本,並新增前台 source / messages 敏感資訊防洩漏 guardaffected route、admin/auth boundary、API readback、CORS diff、frontend env diff、i18n redaction、webhook owner、desktop/mobile production smoke、bundle scan、rollback 與 post-check evidence 仍全部為 0。",
"next_owner_action": "補 affected route refs、admin/auth boundary、API contract readback、CORS origin diff、frontend env diff、i18n redaction review、webhook/callback owner、desktop/mobile production smoke、bundle sensitive scan、rollback owner 與 post-check evidence。",
},
"backup_restore_credential": {
"coverage_status": "restore_recovery_backfill_ready_needs_owner_live_evidence",
"coverage_percent": 64,
"evidence_refs": [
"docs/security/IWOOOS-CONFIG-CONTROL-INVENTORY.md",
"docs/security/BACKUP-RESTORE-ESCROW-INVENTORY.md",
"docs/security/backup-restore-escrow-inventory.snapshot.json",
"docs/security/BACKUP-RESTORE-OWNER-RESPONSE-ACCEPTANCE.md",
"docs/security/backup-restore-owner-response-acceptance.snapshot.json",
"docs/schemas/backup_restore_escrow_inventory_v1.schema.json",
],
"current_gap": "已固定 owner response acceptance、restore recovery backfill、remote delete guard、retention runway、credential recovery metadata-only 與 backup health no-false-green 只讀帳本restore drill、offsite sync、credential escrow、retention change、live evidence 與 owner response 仍全部為 0。",
"next_owner_action": "補 restore drill approval package、freshness SLO、隔離 restore target、依賴圖、資料分級、offsite remote delete guard、credential recovery non-secret proof、retention runway、observer / stop condition、rollback owner、validation plan 與 no-secret-value evidence。",
},
"agent_bounty_protocol_runtime": {
"coverage_status": "owner_request_draft_ready_needs_runtime_owner",
"coverage_percent": 68,
"evidence_refs": [
"docs/security/AGENT-BOUNTY-IWOOOS-ONBOARDING-HANDOFF.md",
"docs/security/agent-bounty-iwooos-onboarding-handoff.snapshot.json",
"docs/security/AGENT-BOUNTY-OWNER-REQUEST-DRAFT.md",
"docs/security/agent-bounty-owner-request-draft.snapshot.json",
"docs/security/GITHUB-TARGET-OWNER-DECISION-RESPONSE.md",
],
"current_gap": "owner request draft 已固定 11 份草稿;尚未收到 runtime / MCP / A2A / treasury / payout owner responseruntime gate 必須維持 0。",
"next_owner_action": "補 repo owner、external agent owner、treasury owner、runtime gate owner、maintenance window、rollback owner 與 validation plan。",
},
"monitoring_alerting_observability": {
"coverage_status": "alert_chain_no_false_green_backfill_ready_needs_live_evidence_receipt",
"coverage_percent": 68,
"evidence_refs": [
"docs/security/IWOOOS-CONFIG-CONTROL-INVENTORY.md",
"docs/security/MONITORING-ALERTING-OBSERVABILITY-INVENTORY.md",
"docs/security/monitoring-alerting-observability-inventory.snapshot.json",
"docs/security/MONITORING-OWNER-REQUEST-DRAFT.md",
"docs/security/monitoring-owner-request-draft.snapshot.json",
"docs/security/MONITORING-OWNER-RESPONSE-ACCEPTANCE.md",
"docs/security/monitoring-owner-response-acceptance.snapshot.json",
"docs/schemas/monitoring_alerting_observability_inventory_v1.schema.json",
],
"current_gap": "已固定 60 份 monitoring / alerting / observability owner response acceptance candidate並新增告警鏈路 no-false-green 回補欄位;仍缺 owner response、live config hash、rule diff、receiver diff、receipt proof、stale / silence review、post-reload readback、noise budget owner 與 maintenance window。",
"next_owner_action": "補 Prometheus / Alertmanager / Grafana / SigNoz / Sentry / Langfuse / Telegram owner、live drift evidence、reload window、receiver owner、receipt proof、stale alert review、silence / dedup review、route smoke plan、noise budget、rollback owner 與 no-secret-value evidence。",
},
"docker_compose_systemd_host_config": {
"coverage_status": "post_incident_readback_plan_ready_needs_host_service_owner_evidence",
"coverage_percent": 64,
"evidence_refs": [
"docs/security/IWOOOS-CONFIG-CONTROL-INVENTORY.md",
"docs/security/HOST-SERVICE-CONFIG-INVENTORY.md",
"docs/security/host-service-config-inventory.snapshot.json",
"docs/security/HOST-SERVICE-OWNER-REQUEST-DRAFT.md",
"docs/security/host-service-owner-request-draft.snapshot.json",
"docs/security/HOST-SERVICE-OWNER-RESPONSE-ACCEPTANCE.md",
"docs/security/host-service-owner-response-acceptance.snapshot.json",
"docs/security/HOST-SERVICE-CHANGE-EVIDENCE-ACCEPTANCE.md",
"docs/security/host-service-change-evidence-acceptance.snapshot.json",
"docs/security/HOST-SERVICE-POST-INCIDENT-READBACK-PLAN.md",
"docs/security/host-service-post-incident-readback-plan.snapshot.json",
"docs/security/DEV-HOSTS-112-111-168-OBSERVE-ONLY-MAPPING.md",
],
"current_gap": "已固定 9 份 Docker / systemd / host service owner response acceptance candidate、change evidence acceptance 與 post-incident readback plan重啟 actor、boot / recovery window、before / after state、Docker daemon、compose / systemd state、failed unit、port binding、dependency、public/admin route recovery、AI provider health、monitoring alert、operator notice、cross-project sync、restoration、recurrence guard 與 no-false-green 皆已納入只讀帳本;仍缺 owner response、live hash、事故回讀包、maintenance / restart window、rollback owner、post-check plan、disable switch 與 no-secret-value evidence。",
"next_owner_action": "補 host service 事故回讀包owner-provided live hash / disposition、change / incident ref、actor role / team、boot time、restart / recovery window、before / after state、Docker daemon state、compose / systemd state、failed unit review、port binding、服務依賴圖、public/admin route recovery、AI provider health、monitoring alert、operator notification、cross-project sync、restoration evidence、recurrence guard、rollback owner、post-check plan 與 no-secret-value evidence。",
},
"ssh_firewall_network_access": {
"coverage_status": "post_incident_readback_plan_ready_needs_network_owner_evidence",
"coverage_percent": 64,
"evidence_refs": [
"docs/HARD_RULES.md",
"docs/security/IWOOOS-CONFIG-CONTROL-INVENTORY.md",
"docs/security/SSH-NETWORK-ACCESS-INVENTORY.md",
"docs/security/ssh-network-access-inventory.snapshot.json",
"docs/security/SSH-NETWORK-OWNER-REQUEST-DRAFT.md",
"docs/security/ssh-network-owner-request-draft.snapshot.json",
"docs/security/SSH-NETWORK-OWNER-RESPONSE-ACCEPTANCE.md",
"docs/security/ssh-network-owner-response-acceptance.snapshot.json",
"docs/security/PORT-FIREWALL-CHANGE-EVIDENCE-ACCEPTANCE.md",
"docs/security/port-firewall-change-evidence-acceptance.snapshot.json",
"docs/security/SSH-NETWORK-POST-INCIDENT-READBACK-PLAN.md",
"docs/security/ssh-network-post-incident-readback-plan.snapshot.json",
],
"current_gap": "owner response acceptance、端口 / 防火牆事故型變更證據驗收與 post-incident readback plan 都已固定;仍缺 owner-provided change / incident evidence、actor、before / after state、service / AI provider / monitoring impact、operator notification、cross-project sync、restoration evidence、recurrence guard、maintenance window、rollback owner 與 post-check evidence。",
"next_owner_action": "補端口 / 防火牆事故回讀包change / incident ref、actor role / team、affected scope、before / after state、service dependency、public route impact、AI provider impact、monitoring alert impact、operator notification、cross-project sync、restoration evidence、recurrence guard、rollback owner 與 post-check 指標。",
},
"ai_provider_model_routing": {
"coverage_status": "owner_response_acceptance_ready_needs_provider_owner_evidence",
"coverage_percent": 64,
"evidence_refs": [
"docs/HARD_RULES.md",
"docs/ai",
"docs/security/AI-PROVIDER-OWNER-RESPONSE-ACCEPTANCE.md",
"docs/security/ai-provider-owner-response-acceptance.snapshot.json",
],
"current_gap": "已固定 AI provider / model routing owner response acceptance 帳本provider owner、fallback order、dry-run、benchmark、成本、privacy、data classification、prompt redaction、rollback 與 post-check evidence 仍全部為 0目前不切 production。",
"next_owner_action": "補 provider owner、fallback order、dry-run result、benchmark result、cost review、privacy review、data classification、prompt redaction、quota budget、quality gate、rollback owner 與 post-check evidence。",
},
"product_surface_runtime_routes": {
"coverage_status": "scope_inventory_ready",
"coverage_percent": 72,
"evidence_refs": [
"docs/security/IWOOOS-CONFIG-CONTROL-INVENTORY.md",
"docs/security/VIBEWORK-IWOOOS-ONBOARDING-HANDOFF.md",
"docs/security/AGENT-BOUNTY-IWOOOS-ONBOARDING-HANDOFF.md",
"docs/security/AGENT-BOUNTY-OWNER-REQUEST-DRAFT.md",
],
"current_gap": "跨產品 owner response 尚未 accepted產品 route / admin / webhook 仍需逐產品補證。",
"next_owner_action": "補 AWOOOI、AwoooP、IwoooS、VibeWork、agent-bounty-protocol 與公開網站 owner response。",
},
"security_evidence_tooling": {
"coverage_status": "guard_ready",
"coverage_percent": 86,
"evidence_refs": [
"scripts/security/security-mirror-progress-guard.py",
"scripts/security/high-value-config-change-gate.py",
"scripts/security/high-value-config-owner-packet.py",
"docs/security/high-value-config-change-gate.snapshot.json",
],
"current_gap": "guard 已可重跑,但尚未接 blocking CI本階段刻意維持低摩擦。",
"next_owner_action": "維持 guard / doc secret sanity若要 CI blocking 需另開人工批准與 rollout plan。",
},
}
FALSE_BOUNDARIES = {
"runtime_execution_authorized": False,
"host_write_authorized": False,
"host_live_conf_read_authorized": False,
"nginx_test_authorized": False,
"public_gateway_reload_authorized": False,
"public_route_change_authorized": False,
"admin_route_change_authorized": False,
"websocket_route_change_authorized": False,
"acme_challenge_change_authorized": False,
"route_smoke_authorized": False,
"rollback_executed": False,
"nginx_reload_authorized": False,
"dns_tls_change_authorized": False,
"certbot_renew_authorized": False,
"argocd_api_read_authorized": False,
"argocd_sync_authorized": False,
"kubectl_action_authorized": False,
"helm_upgrade_authorized": False,
"network_policy_apply_authorized": False,
"nodeport_change_authorized": False,
"rbac_change_authorized": False,
"backup_run_authorized": False,
"restore_run_authorized": False,
"restore_drill_authorized": False,
"offsite_sync_authorized": False,
"offsite_remote_delete_authorized": False,
"credential_escrow_marker_write_authorized": False,
"retention_change_authorized": False,
"restic_prune_authorized": False,
"rclone_config_authorized": False,
"velero_restore_authorized": False,
"workflow_modification_authorized": False,
"runner_change_authorized": False,
"refs_sync_authorized": False,
"force_push_authorized": False,
"prometheus_reload_authorized": False,
"alertmanager_reload_authorized": False,
"grafana_dashboard_apply_authorized": False,
"signoz_rule_apply_authorized": False,
"sentry_deploy_authorized": False,
"langfuse_config_change_authorized": False,
"otel_collector_reload_authorized": False,
"receiver_route_change_authorized": False,
"silence_policy_change_authorized": False,
"telegram_send_authorized": False,
"notification_route_change_authorized": False,
"webhook_receiver_change_authorized": False,
"remote_write_change_authorized": False,
"exporter_deploy_authorized": False,
"live_alert_fire_authorized": False,
"alert_chain_smoke_authorized": False,
"runtime_config_change_authorized": False,
"api_route_change_authorized": False,
"cors_change_authorized": False,
"frontend_env_change_authorized": False,
"middleware_auth_change_authorized": False,
"callback_url_change_authorized": False,
"webhook_secret_change_authorized": False,
"security_header_change_authorized": False,
"cookie_policy_change_authorized": False,
"csrf_disable_authorized": False,
"rate_limit_disable_authorized": False,
"api_contract_change_authorized": False,
"i18n_public_text_internal_identity_allowed": False,
"internal_ip_exposure_allowed": False,
"repo_namespace_exposure_allowed": False,
"owner_namespace_exposure_allowed": False,
"internal_status_code_exposure_allowed": False,
"internal_transcript_exposure_allowed": False,
"raw_payload_storage_allowed": False,
"desktop_mobile_smoke_authorized": False,
"database_migration_authorized": False,
"secret_value_collection_allowed": False,
"active_scan_authorized": False,
"agent_bounty_runtime_authorized": False,
"payout_or_withdrawal_authorized": False,
"action_buttons_allowed": False,
}
def git_short_sha(root: Path) -> str:
try:
result = subprocess.run(
["git", "rev-parse", "--short", "HEAD"],
cwd=root,
check=True,
capture_output=True,
text=True,
)
return result.stdout.strip()
except Exception:
return "unknown"
def load_gate_categories(root: Path) -> list[Any]:
gate_path = root / "scripts" / "security" / "high-value-config-change-gate.py"
namespace = runpy.run_path(str(gate_path))
return list(namespace["CATEGORIES"])
def category_to_dict(category: Any) -> dict[str, Any]:
status = CONTROL_STATUS_BY_CATEGORY[category.category_id]
return {
"category_id": category.category_id,
"label": category.label,
"priority": category.priority,
"control_tier": category.control_tier,
"required_gate": category.required_gate,
"coverage_status": status["coverage_status"],
"coverage_percent": status["coverage_percent"],
"patterns": list(category.patterns),
"required_validation": list(category.required_validation),
"evidence_refs": status["evidence_refs"],
"current_gap": status["current_gap"],
"next_owner_action": status["next_owner_action"],
"owner_response_required": True,
"owner_response_received": False,
"owner_response_accepted": False,
"runtime_gate_open": False,
"action_buttons_allowed": False,
}
def count_by(items: list[dict[str, Any]], key: str, value: Any) -> int:
return sum(1 for item in items if item[key] == value)
def build_report(root: Path, generated_at: str | None) -> dict[str, Any]:
report_time = generated_at or datetime.now(TAIPEI).isoformat(timespec="seconds")
categories = [category_to_dict(category) for category in load_gate_categories(root)]
c0_categories = [item for item in categories if item["control_tier"] == "C0"]
c1_categories = [item for item in categories if item["control_tier"] == "C1"]
needs_live_evidence = [
item
for item in categories
if item["coverage_status"]
in {
"gate_defined_needs_runtime_evidence",
"policy_defined_needs_restore_drill_owner",
"repo_only_inventory_ready_needs_restore_drill_owner",
"repo_only_inventory_ready_needs_live_route_evidence",
"repo_only_preflight_contract_ready_needs_owner_live_diff",
"owner_response_acceptance_ledger_ready_needs_owner_live_diff",
"rendered_diff_acceptance_ledger_ready_needs_owner_live_diff",
"emergency_change_backfill_ready_needs_owner_live_diff",
"owner_response_acceptance_ledger_ready_needs_runtime_evidence",
"change_evidence_acceptance_ready_needs_gitops_owner_evidence",
"post_incident_readback_plan_ready_needs_gitops_owner_evidence",
"secret_injection_change_evidence_acceptance_ready_needs_owner_evidence",
"cd_runner_secret_injection_change_evidence_acceptance_ready_needs_owner_evidence",
"change_evidence_acceptance_ready_needs_runtime_config_owner_evidence",
"frontend_sensitive_surface_guard_ready_needs_runtime_config_owner_evidence",
"owner_response_acceptance_ledger_ready_needs_restore_drill_owner",
"restore_recovery_backfill_ready_needs_owner_live_evidence",
"owner_response_acceptance_ledger_ready_needs_network_owner",
"owner_response_acceptance_ledger_ready_needs_live_route_evidence",
"alert_chain_no_false_green_backfill_ready_needs_live_evidence_receipt",
"change_evidence_acceptance_ready_needs_network_owner_evidence",
"incident_change_evidence_acceptance_ready_needs_network_owner_evidence",
"post_incident_readback_plan_ready_needs_network_owner_evidence",
"policy_ready_needs_drift_evidence",
"inventory_needed",
"repo_only_inventory_ready_needs_live_owner_evidence",
"incident_recovery_backfill_ready_needs_live_owner_evidence",
"change_evidence_acceptance_ready_needs_host_service_owner_evidence",
"policy_ready_needs_network_matrix",
"policy_ready_needs_dry_run_pack",
"owner_response_acceptance_ready_needs_provider_owner_evidence",
}
]
average_coverage = round(sum(item["coverage_percent"] for item in categories) / len(categories))
lowest_categories = sorted(categories, key=lambda item: item["coverage_percent"])[:4]
return {
"schema_version": "high_value_config_control_coverage_v1",
"generated_at": report_time,
"git_commit": git_short_sha(root),
"source_category_definition": "scripts/security/high-value-config-change-gate.py",
"status": "coverage_matrix_ready",
"summary": {
"category_count": len(categories),
"c0_category_count": len(c0_categories),
"c1_category_count": len(c1_categories),
"c2_category_count": count_by(categories, "control_tier", "C2"),
"c3_category_count": count_by(categories, "control_tier", "C3"),
"registered_control_count": len(categories),
"owner_response_required_count": len(categories),
"owner_response_received_count": 0,
"owner_response_accepted_count": 0,
"runtime_gate_count": 0,
"action_button_count": 0,
"average_coverage_percent": average_coverage,
"needs_live_evidence_count": len(needs_live_evidence),
"lowest_coverage_category_count": len(lowest_categories),
},
"execution_boundaries": FALSE_BOUNDARIES,
"coverage_categories": categories,
"lowest_coverage_categories": [
{
"category_id": item["category_id"],
"label": item["label"],
"coverage_percent": item["coverage_percent"],
"current_gap": item["current_gap"],
"next_owner_action": item["next_owner_action"],
}
for item in lowest_categories
],
"next_collection_order": [
"nginx_public_gateway",
"dns_tls_certbot",
"k8s_production_gitops",
"secret_metadata",
"gitea_workflow_runner_source_control",
"public_admin_api_runtime_config",
"agent_bounty_protocol_runtime",
"docker_compose_systemd_host_config",
"ssh_firewall_network_access",
"ai_provider_model_routing",
"monitoring_alerting_observability",
"backup_restore_credential",
],
"operator_interpretation": [
"這是全域配置控管覆蓋矩陣,不是單次 git diff 變更分類。",
"所有 category 都已有高價值配置 Gate 註冊與 owner response 欄位,但 owner response received / accepted 仍為 0。",
"C0 / C1 coverage percent 只代表只讀框架成熟度,不代表 runtime 可執行。",
"缺 live evidence 的項目只能收 owner-provided redacted evidence不得主動 SSH、reload、scan 或讀 secret value。",
],
}
def main() -> int:
parser = argparse.ArgumentParser(description="IwoooS 高價值配置控管覆蓋矩陣")
parser.add_argument("--root", default=".", help="repo root")
parser.add_argument("--output", help="寫出 JSON 報告")
parser.add_argument("--generated-at", help="固定報告時間,供 committed snapshot 使用")
args = parser.parse_args()
root = Path(args.root).resolve()
report = build_report(root, args.generated_at)
payload = json.dumps(report, ensure_ascii=False, indent=2, sort_keys=True)
if args.output:
output = Path(args.output)
output.parent.mkdir(parents=True, exist_ok=True)
output.write_text(payload + "\n", encoding="utf-8")
else:
print(payload)
summary = report["summary"]
print(
"HIGH_VALUE_CONFIG_CONTROL_COVERAGE_OK "
f"categories={summary['category_count']} "
f"c0={summary['c0_category_count']} "
f"avg={summary['average_coverage_percent']} "
f"runtime_gate={summary['runtime_gate_count']}",
file=sys.stderr,
)
return 0
if __name__ == "__main__":
sys.exit(main())