Files
awoooi/scripts/security/high-value-config-control-coverage.py
Your Name 8294a05456
All checks were successful
Code Review / ai-code-review (push) Successful in 22s
CD Pipeline / tests (push) Successful in 1m35s
CD Pipeline / build-and-deploy (push) Successful in 3m53s
CD Pipeline / post-deploy-checks (push) Successful in 1m26s
feat(iwooos): 新增主機服務變更證據驗收 gate
2026-06-15 18:16:34 +08:00

490 lines
28 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": "change_evidence_acceptance_ready_needs_gitops_owner_evidence",
"coverage_percent": 64,
"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",
"k8s/awoooi-prod",
"k8s/argocd",
],
"current_gap": "已固定 owner response acceptance 與 GitOps 變更證據驗收只讀帳本proposed commit、rendered manifest diff、ArgoCD app / sync revision、health before / after、rollout、route smoke、metrics / alert、rollback、maintenance window 與 post-check evidence 仍全部為 0。",
"next_owner_action": "補 GitOps owner 回覆、proposed commit ref、rendered manifest diff ref、ArgoCD app / sync revision ref、health before / after、rollout、route smoke、metrics / alert、blast radius、rollback revision、maintenance window 與 post-check owner。",
},
"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": "change_evidence_acceptance_ready_needs_host_service_owner_evidence",
"coverage_percent": 62,
"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/DEV-HOSTS-112-111-168-OBSERVE-ONLY-MAPPING.md",
],
"current_gap": "已固定 9 份 Docker / systemd / host service owner response acceptance candidate並新增 host service change evidence acceptance重啟 actor、before / after state、Docker daemon、compose / systemd state、failed unit、port binding、dependency、cold-start、route recovery、operator notice、cross-project sync 與 no-false-green 皆已納入只讀帳本;仍缺 owner response、live hash、change evidence、maintenance / restart window、rollback owner、post-check plan、disable switch 與 no-secret-value evidence。",
"next_owner_action": "補 owner-provided live hash / disposition、change / incident ref、actor role / team、before / after state、Docker daemon state、compose / systemd state、failed unit review、port binding、服務依賴圖、cold-start sequence、route recovery、operator notification、cross-project sync、rollback owner、post-check plan、disable switch 與 no-secret-value evidence。",
},
"ssh_firewall_network_access": {
"coverage_status": "incident_change_evidence_acceptance_ready_needs_network_owner_evidence",
"coverage_percent": 62,
"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",
],
"current_gap": "owner response acceptance 帳本已固定 16 個 SSH / network acceptance candidate端口 / 防火牆事故型變更證據驗收帳本已固定 14 個 change evidence candidate仍缺 owner-provided change / incident evidence、actor、before / after state、service health impact、operator notification、cross-project sync、maintenance window、rollback owner 與 post-check evidence。",
"next_owner_action": "補端口 / 防火牆變更的 change / incident ref、actor role / team、affected scope、before / after state、service dependency、customer impact、service health impact、operator notification、cross-project sync、rollback owner 與 post-check 指標。",
},
"ai_provider_model_routing": {
"coverage_status": "policy_ready_needs_dry_run_pack",
"coverage_percent": 60,
"evidence_refs": [
"docs/HARD_RULES.md",
"docs/ai",
],
"current_gap": "模型 / provider / Ollama proxy 切換需 dry-run、benchmark、成本與 privacy review目前不切 production。",
"next_owner_action": "補 provider owner、fallback order、cost review、privacy review、benchmark 與 rollback owner。",
},
"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",
"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",
"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",
}
]
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",
"monitoring_alerting_observability",
"ssh_firewall_network_access",
"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())