From 45c2b8ebe642422be0dd3e2e438c60e38f97509f Mon Sep 17 00:00:00 2001 From: Your Name Date: Mon, 15 Jun 2026 20:42:12 +0800 Subject: [PATCH] =?UTF-8?q?feat(iwooos):=20=E6=96=B0=E5=A2=9E=20K8s=20Argo?= =?UTF-8?q?CD=20=E4=BA=8B=E6=95=85=E5=9B=9E=E8=AE=80=20gate?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- apps/web/messages/en.json | 8 +- apps/web/messages/zh-TW.json | 8 +- apps/web/src/app/[locale]/iwooos/page.tsx | 38 +- .../iwooos_posture_projection_v1.schema.json | 277 +++- .../HIGH-VALUE-CONFIG-CONTROL-COVERAGE.md | 3 + .../IWOOOS-CONFIG-CONTROL-INVENTORY.md | 11 +- docs/security/IWOOOS-POSTURE-PROJECTION.md | 12 +- .../K8S-ARGOCD-POST-INCIDENT-READBACK-PLAN.md | 155 ++ .../SECURITY-SUPPLY-CHAIN-PROGRESS.md | 10 +- ...alue-config-control-coverage.snapshot.json | 28 +- .../iwooos-posture-projection.snapshot.json | 61 +- ...-post-incident-readback-plan.snapshot.json | 1352 +++++++++++++++++ .../high-value-config-control-coverage.py | 11 +- .../security/iwooos-config-control-guard.py | 82 +- .../k8s-argocd-post-incident-readback-plan.py | 476 ++++++ .../security-mirror-progress-guard.py | 322 +++- 16 files changed, 2811 insertions(+), 43 deletions(-) create mode 100644 docs/security/K8S-ARGOCD-POST-INCIDENT-READBACK-PLAN.md create mode 100644 docs/security/k8s-argocd-post-incident-readback-plan.snapshot.json create mode 100644 scripts/security/k8s-argocd-post-incident-readback-plan.py diff --git a/apps/web/messages/en.json b/apps/web/messages/en.json index 878278ad7..15f8cb1a4 100644 --- a/apps/web/messages/en.json +++ b/apps/web/messages/en.json @@ -17833,7 +17833,7 @@ }, "k8sArgocd": { "title": "K8s / ArgoCD / production manifests", - "body": "production manifests、ConfigMap / Secret metadata、NetworkPolicy、CronJob 與 rollback revision 需被納管;GitOps 變更證據驗收已固定 proposed commit、rendered diff、ArgoCD readback、health before / after、rollout、route smoke、metrics / alert 與 rollback 欄位,目前仍不執行 ArgoCD sync、kubectl、Helm upgrade 或 live patch。" + "body": "production manifests、ConfigMap / Secret metadata、NetworkPolicy、CronJob 與 rollback revision 需被納管;GitOps 變更證據驗收後已新增事故後回讀計畫,固定 4 個範圍、31 個必填欄位、28 個審查檢查項、10 條結果分流與 41 類禁止動作。目前 post-incident readback received / accepted、ArgoCD app health、sync status、Pending / image pull / scheduling、drift、route / AI / monitoring impact、cross-project sync、no-false-green 與 runtime gate 仍全部為 0;不執行 ArgoCD sync、kubectl、Helm upgrade、NetworkPolicy / NodePort / RBAC 變更或 live patch。" }, "workflowSecret": { "title": "工作流程 / 執行器 / 機密中繼資料", @@ -17918,8 +17918,8 @@ "label": "C0 高風險", "detail": "8 類會影響公開入口、secret、部署、備份或 agent runtime。" }, - "coverage": { - "label": "平均成熟度", + "coverage": { + "label": "平均成熟度", "detail": "host service 事故回讀 gate 納入後,平均控管成熟度為 71%。" }, "runtimeGate": { @@ -17946,7 +17946,7 @@ }, "k8sGitops": { "title": "K8s / ArgoCD GitOps", - "body": "manifest 清冊、負責人回覆驗收與 GitOps 變更證據驗收已固定;目前成熟度 64%,仍缺 proposed commit、rendered manifest diff、ArgoCD app / sync revision、健康前後狀態、rollout、route smoke、metrics / alert、回復與後檢負責人。" + "body": "manifest 清冊、負責人回覆驗收、GitOps 變更證據驗收與事故後回讀計畫已固定;目前成熟度 66%。新回讀計畫涵蓋 4 個範圍、31 個必填欄位、28 個審查檢查項、10 條結果分流與 41 類禁止動作;仍缺 actor、ArgoCD app / sync、Degraded / Pending、image pull / scheduling、rollout 前後、event / metrics / alert、drift scanner、CronJob、NetworkPolicy / RBAC / Secret metadata、route / AI / monitoring impact、跨專案同步與 no-false-green 脫敏證據。readback accepted 與 runtime gate 仍全部為 0。" }, "backupRestore": { "title": "備份 / 還原 / 金庫", diff --git a/apps/web/messages/zh-TW.json b/apps/web/messages/zh-TW.json index 878278ad7..15f8cb1a4 100644 --- a/apps/web/messages/zh-TW.json +++ b/apps/web/messages/zh-TW.json @@ -17833,7 +17833,7 @@ }, "k8sArgocd": { "title": "K8s / ArgoCD / production manifests", - "body": "production manifests、ConfigMap / Secret metadata、NetworkPolicy、CronJob 與 rollback revision 需被納管;GitOps 變更證據驗收已固定 proposed commit、rendered diff、ArgoCD readback、health before / after、rollout、route smoke、metrics / alert 與 rollback 欄位,目前仍不執行 ArgoCD sync、kubectl、Helm upgrade 或 live patch。" + "body": "production manifests、ConfigMap / Secret metadata、NetworkPolicy、CronJob 與 rollback revision 需被納管;GitOps 變更證據驗收後已新增事故後回讀計畫,固定 4 個範圍、31 個必填欄位、28 個審查檢查項、10 條結果分流與 41 類禁止動作。目前 post-incident readback received / accepted、ArgoCD app health、sync status、Pending / image pull / scheduling、drift、route / AI / monitoring impact、cross-project sync、no-false-green 與 runtime gate 仍全部為 0;不執行 ArgoCD sync、kubectl、Helm upgrade、NetworkPolicy / NodePort / RBAC 變更或 live patch。" }, "workflowSecret": { "title": "工作流程 / 執行器 / 機密中繼資料", @@ -17918,8 +17918,8 @@ "label": "C0 高風險", "detail": "8 類會影響公開入口、secret、部署、備份或 agent runtime。" }, - "coverage": { - "label": "平均成熟度", + "coverage": { + "label": "平均成熟度", "detail": "host service 事故回讀 gate 納入後,平均控管成熟度為 71%。" }, "runtimeGate": { @@ -17946,7 +17946,7 @@ }, "k8sGitops": { "title": "K8s / ArgoCD GitOps", - "body": "manifest 清冊、負責人回覆驗收與 GitOps 變更證據驗收已固定;目前成熟度 64%,仍缺 proposed commit、rendered manifest diff、ArgoCD app / sync revision、健康前後狀態、rollout、route smoke、metrics / alert、回復與後檢負責人。" + "body": "manifest 清冊、負責人回覆驗收、GitOps 變更證據驗收與事故後回讀計畫已固定;目前成熟度 66%。新回讀計畫涵蓋 4 個範圍、31 個必填欄位、28 個審查檢查項、10 條結果分流與 41 類禁止動作;仍缺 actor、ArgoCD app / sync、Degraded / Pending、image pull / scheduling、rollout 前後、event / metrics / alert、drift scanner、CronJob、NetworkPolicy / RBAC / Secret metadata、route / AI / monitoring impact、跨專案同步與 no-false-green 脫敏證據。readback accepted 與 runtime gate 仍全部為 0。" }, "backupRestore": { "title": "備份 / 還原 / 金庫", diff --git a/apps/web/src/app/[locale]/iwooos/page.tsx b/apps/web/src/app/[locale]/iwooos/page.tsx index 3c28f16aa..743adb310 100644 --- a/apps/web/src/app/[locale]/iwooos/page.tsx +++ b/apps/web/src/app/[locale]/iwooos/page.tsx @@ -2095,7 +2095,7 @@ const highValueConfigControlCoverageItems: HighValueConfigControlCoverageItem[] { key: 'dockerSystemd', rank: 'P1-1', value: '64%', icon: Server, tone: 'warn' }, { key: 'sshNetwork', rank: 'P1-2', value: '64%', icon: Network, tone: 'warn' }, { key: 'aiProvider', rank: 'P1-3', value: '64%', icon: Cloud, tone: 'warn' }, - { key: 'k8sGitops', rank: 'P1-4', value: '64%', icon: Workflow, tone: 'warn' }, + { key: 'k8sGitops', rank: 'P1-4', value: '66%', icon: Workflow, tone: 'warn' }, ] const highValueConfigControlCoverageBoundaries = [ @@ -2116,7 +2116,7 @@ const highValueConfigControlCoverageBoundaries = [ 'public_gateway_owner_response_acceptance_reviewer_check_count=22', 'public_gateway_owner_response_acceptance_outcome_lane_count=8', 'public_gateway_owner_response_acceptance_blocked_action_count=28', - 'k8s_production_gitops_coverage_percent=64', + 'k8s_production_gitops_coverage_percent=66', 'secret_metadata_coverage_percent=68', 'gitea_workflow_runner_source_control_coverage_percent=72', 'public_admin_api_runtime_config_coverage_percent=66', @@ -2199,6 +2199,28 @@ const highValueConfigControlCoverageBoundaries = [ 'k8s_argocd_change_evidence_acceptance_accepted_count=0', 'k8s_argocd_change_evidence_acceptance_runtime_approval_package_ready_count=0', 'k8s_argocd_change_evidence_acceptance_runtime_gate_count=0', + 'k8s_argocd_post_incident_readback_plan_candidate_count=4', + 'k8s_argocd_post_incident_readback_plan_c0_candidate_count=3', + 'k8s_argocd_post_incident_readback_plan_write_capable_candidate_count=4', + 'k8s_argocd_post_incident_readback_plan_required_readback_field_count=31', + 'k8s_argocd_post_incident_readback_plan_reviewer_check_count=28', + 'k8s_argocd_post_incident_readback_plan_outcome_lane_count=10', + 'k8s_argocd_post_incident_readback_plan_blocked_action_count=41', + 'k8s_argocd_post_incident_readback_plan_post_incident_readback_received_count=0', + 'k8s_argocd_post_incident_readback_plan_post_incident_readback_accepted_count=0', + 'k8s_argocd_post_incident_readback_plan_argocd_app_health_accepted_count=0', + 'k8s_argocd_post_incident_readback_plan_argocd_sync_status_accepted_count=0', + 'k8s_argocd_post_incident_readback_plan_degraded_state_accepted_count=0', + 'k8s_argocd_post_incident_readback_plan_pending_workload_accepted_count=0', + 'k8s_argocd_post_incident_readback_plan_image_pull_or_scheduling_accepted_count=0', + 'k8s_argocd_post_incident_readback_plan_metrics_alert_accepted_count=0', + 'k8s_argocd_post_incident_readback_plan_cross_project_sync_accepted_count=0', + 'k8s_argocd_post_incident_readback_plan_no_false_green_accepted_count=0', + 'k8s_argocd_post_incident_readback_plan_argocd_api_read_authorized_count=0', + 'k8s_argocd_post_incident_readback_plan_argocd_sync_authorized_count=0', + 'k8s_argocd_post_incident_readback_plan_kubectl_action_authorized_count=0', + 'k8s_argocd_post_incident_readback_plan_runtime_gate_count=0', + 'k8s_argocd_post_incident_readback_plan_action_button_count=0', 'public_gateway_rendered_diff_acceptance_candidate_count=3', 'public_gateway_rendered_diff_acceptance_reviewer_check_count=15', 'public_gateway_rendered_diff_acceptance_runtime_gate_count=0', @@ -2446,7 +2468,7 @@ const criticalConfigPrioritySummary = [ const criticalConfigPriorityItems: CriticalConfigPriorityItem[] = [ { key: 'nginxGateway', rank: 'P0-1', state: '90% / live 0', icon: Server, tone: 'warn' }, { key: 'dnsTls', rank: 'P0-2', state: '78% / probe 0', icon: Route, tone: 'warn' }, - { key: 'k8sArgocd', rank: 'P0-3', state: '64% / sync 0', icon: Cloud, tone: 'warn' }, + { key: 'k8sArgocd', rank: 'P0-3', state: '66% / readback 0', icon: Cloud, tone: 'warn' }, { key: 'workflowSecret', rank: 'P0-4', state: '68% / 72%', icon: GitBranch, tone: 'warn' }, { key: 'publicRuntime', rank: 'P0-5', state: '64% / route 0', icon: Network, tone: 'warn' }, { key: 'agentBounty', rank: 'P0-6', state: 'runtime 0', icon: Workflow, tone: 'locked' }, @@ -2517,6 +2539,16 @@ const criticalConfigPriorityBoundaries = [ 'k8s_argocd_change_evidence_acceptance_accepted_count=0', 'k8s_argocd_change_evidence_acceptance_runtime_approval_package_ready_count=0', 'k8s_argocd_change_evidence_acceptance_runtime_gate_count=0', + 'k8s_argocd_post_incident_readback_plan_candidate_count=4', + 'k8s_argocd_post_incident_readback_plan_c0_candidate_count=3', + 'k8s_argocd_post_incident_readback_plan_write_capable_candidate_count=4', + 'k8s_argocd_post_incident_readback_plan_required_readback_field_count=31', + 'k8s_argocd_post_incident_readback_plan_reviewer_check_count=28', + 'k8s_argocd_post_incident_readback_plan_outcome_lane_count=10', + 'k8s_argocd_post_incident_readback_plan_blocked_action_count=41', + 'k8s_argocd_post_incident_readback_plan_post_incident_readback_received_count=0', + 'k8s_argocd_post_incident_readback_plan_post_incident_readback_accepted_count=0', + 'k8s_argocd_post_incident_readback_plan_runtime_gate_count=0', 'dns_tls_live_probe_executed=false', 'certbot_renew_authorized=false', 'argocd_api_read_authorized=false', diff --git a/docs/schemas/iwooos_posture_projection_v1.schema.json b/docs/schemas/iwooos_posture_projection_v1.schema.json index 176c4e821..33b948bc9 100644 --- a/docs/schemas/iwooos_posture_projection_v1.schema.json +++ b/docs/schemas/iwooos_posture_projection_v1.schema.json @@ -428,7 +428,62 @@ "host_service_post_incident_readback_plan_runtime_gate_count", "host_service_post_incident_readback_plan_action_button_count", "host_service_post_incident_readback_plan_coverage_percent_after_readback_plan", - "docker_compose_systemd_host_config_coverage_percent" + "docker_compose_systemd_host_config_coverage_percent", + "k8s_argocd_post_incident_readback_plan_first_layer", + "k8s_argocd_post_incident_readback_plan_candidate_count", + "k8s_argocd_post_incident_readback_plan_c0_candidate_count", + "k8s_argocd_post_incident_readback_plan_c1_candidate_count", + "k8s_argocd_post_incident_readback_plan_write_capable_candidate_count", + "k8s_argocd_post_incident_readback_plan_degraded_or_pending_review_required_candidate_count", + "k8s_argocd_post_incident_readback_plan_drift_or_schedule_review_required_candidate_count", + "k8s_argocd_post_incident_readback_plan_route_ai_monitoring_impact_required_candidate_count", + "k8s_argocd_post_incident_readback_plan_cross_project_sync_required_candidate_count", + "k8s_argocd_post_incident_readback_plan_no_false_green_required_candidate_count", + "k8s_argocd_post_incident_readback_plan_readback_field_count", + "k8s_argocd_post_incident_readback_plan_required_readback_field_count", + "k8s_argocd_post_incident_readback_plan_reviewer_check_count", + "k8s_argocd_post_incident_readback_plan_outcome_lane_count", + "k8s_argocd_post_incident_readback_plan_blocked_action_count", + "k8s_argocd_post_incident_readback_plan_post_incident_readback_received_count", + "k8s_argocd_post_incident_readback_plan_post_incident_readback_accepted_count", + "k8s_argocd_post_incident_readback_plan_actor_attribution_accepted_count", + "k8s_argocd_post_incident_readback_plan_argocd_app_health_accepted_count", + "k8s_argocd_post_incident_readback_plan_argocd_sync_status_accepted_count", + "k8s_argocd_post_incident_readback_plan_degraded_state_accepted_count", + "k8s_argocd_post_incident_readback_plan_pending_workload_accepted_count", + "k8s_argocd_post_incident_readback_plan_image_pull_or_scheduling_accepted_count", + "k8s_argocd_post_incident_readback_plan_rollout_before_after_accepted_count", + "k8s_argocd_post_incident_readback_plan_event_summary_accepted_count", + "k8s_argocd_post_incident_readback_plan_metrics_alert_accepted_count", + "k8s_argocd_post_incident_readback_plan_drift_scanner_accepted_count", + "k8s_argocd_post_incident_readback_plan_cronjob_schedule_accepted_count", + "k8s_argocd_post_incident_readback_plan_network_policy_service_impact_accepted_count", + "k8s_argocd_post_incident_readback_plan_rbac_serviceaccount_impact_accepted_count", + "k8s_argocd_post_incident_readback_plan_secret_metadata_parity_accepted_count", + "k8s_argocd_post_incident_readback_plan_public_admin_route_impact_accepted_count", + "k8s_argocd_post_incident_readback_plan_ai_provider_monitoring_impact_accepted_count", + "k8s_argocd_post_incident_readback_plan_backup_restore_impact_accepted_count", + "k8s_argocd_post_incident_readback_plan_operator_notification_accepted_count", + "k8s_argocd_post_incident_readback_plan_cross_project_sync_accepted_count", + "k8s_argocd_post_incident_readback_plan_recovery_or_still_degraded_accepted_count", + "k8s_argocd_post_incident_readback_plan_postcheck_readback_accepted_count", + "k8s_argocd_post_incident_readback_plan_recurrence_guard_accepted_count", + "k8s_argocd_post_incident_readback_plan_no_false_green_accepted_count", + "k8s_argocd_post_incident_readback_plan_argocd_api_read_authorized_count", + "k8s_argocd_post_incident_readback_plan_argocd_sync_authorized_count", + "k8s_argocd_post_incident_readback_plan_live_cluster_read_authorized_count", + "k8s_argocd_post_incident_readback_plan_kubectl_action_authorized_count", + "k8s_argocd_post_incident_readback_plan_helm_action_authorized_count", + "k8s_argocd_post_incident_readback_plan_network_policy_change_authorized_count", + "k8s_argocd_post_incident_readback_plan_nodeport_change_authorized_count", + "k8s_argocd_post_incident_readback_plan_rbac_change_authorized_count", + "k8s_argocd_post_incident_readback_plan_secret_value_collection_allowed_count", + "k8s_argocd_post_incident_readback_plan_route_smoke_authorized_count", + "k8s_argocd_post_incident_readback_plan_production_write_authorized_count", + "k8s_argocd_post_incident_readback_plan_runtime_gate_count", + "k8s_argocd_post_incident_readback_plan_action_button_count", + "k8s_argocd_post_incident_readback_plan_coverage_percent_after_readback_plan", + "k8s_production_gitops_coverage_percent" ], "properties": { "route_path": { @@ -1846,6 +1901,226 @@ "docker_compose_systemd_host_config_coverage_percent": { "type": "integer", "const": 64 + }, + "k8s_argocd_post_incident_readback_plan_first_layer": { + "type": "boolean", + "const": true + }, + "k8s_argocd_post_incident_readback_plan_candidate_count": { + "type": "integer", + "const": 4 + }, + "k8s_argocd_post_incident_readback_plan_c0_candidate_count": { + "type": "integer", + "const": 3 + }, + "k8s_argocd_post_incident_readback_plan_c1_candidate_count": { + "type": "integer", + "const": 1 + }, + "k8s_argocd_post_incident_readback_plan_write_capable_candidate_count": { + "type": "integer", + "const": 4 + }, + "k8s_argocd_post_incident_readback_plan_degraded_or_pending_review_required_candidate_count": { + "type": "integer", + "const": 4 + }, + "k8s_argocd_post_incident_readback_plan_drift_or_schedule_review_required_candidate_count": { + "type": "integer", + "const": 4 + }, + "k8s_argocd_post_incident_readback_plan_route_ai_monitoring_impact_required_candidate_count": { + "type": "integer", + "const": 4 + }, + "k8s_argocd_post_incident_readback_plan_cross_project_sync_required_candidate_count": { + "type": "integer", + "const": 4 + }, + "k8s_argocd_post_incident_readback_plan_no_false_green_required_candidate_count": { + "type": "integer", + "const": 4 + }, + "k8s_argocd_post_incident_readback_plan_readback_field_count": { + "type": "integer", + "const": 36 + }, + "k8s_argocd_post_incident_readback_plan_required_readback_field_count": { + "type": "integer", + "const": 31 + }, + "k8s_argocd_post_incident_readback_plan_reviewer_check_count": { + "type": "integer", + "const": 28 + }, + "k8s_argocd_post_incident_readback_plan_outcome_lane_count": { + "type": "integer", + "const": 10 + }, + "k8s_argocd_post_incident_readback_plan_blocked_action_count": { + "type": "integer", + "const": 41 + }, + "k8s_argocd_post_incident_readback_plan_post_incident_readback_received_count": { + "type": "integer", + "const": 0 + }, + "k8s_argocd_post_incident_readback_plan_post_incident_readback_accepted_count": { + "type": "integer", + "const": 0 + }, + "k8s_argocd_post_incident_readback_plan_actor_attribution_accepted_count": { + "type": "integer", + "const": 0 + }, + "k8s_argocd_post_incident_readback_plan_argocd_app_health_accepted_count": { + "type": "integer", + "const": 0 + }, + "k8s_argocd_post_incident_readback_plan_argocd_sync_status_accepted_count": { + "type": "integer", + "const": 0 + }, + "k8s_argocd_post_incident_readback_plan_degraded_state_accepted_count": { + "type": "integer", + "const": 0 + }, + "k8s_argocd_post_incident_readback_plan_pending_workload_accepted_count": { + "type": "integer", + "const": 0 + }, + "k8s_argocd_post_incident_readback_plan_image_pull_or_scheduling_accepted_count": { + "type": "integer", + "const": 0 + }, + "k8s_argocd_post_incident_readback_plan_rollout_before_after_accepted_count": { + "type": "integer", + "const": 0 + }, + "k8s_argocd_post_incident_readback_plan_event_summary_accepted_count": { + "type": "integer", + "const": 0 + }, + "k8s_argocd_post_incident_readback_plan_metrics_alert_accepted_count": { + "type": "integer", + "const": 0 + }, + "k8s_argocd_post_incident_readback_plan_drift_scanner_accepted_count": { + "type": "integer", + "const": 0 + }, + "k8s_argocd_post_incident_readback_plan_cronjob_schedule_accepted_count": { + "type": "integer", + "const": 0 + }, + "k8s_argocd_post_incident_readback_plan_network_policy_service_impact_accepted_count": { + "type": "integer", + "const": 0 + }, + "k8s_argocd_post_incident_readback_plan_rbac_serviceaccount_impact_accepted_count": { + "type": "integer", + "const": 0 + }, + "k8s_argocd_post_incident_readback_plan_secret_metadata_parity_accepted_count": { + "type": "integer", + "const": 0 + }, + "k8s_argocd_post_incident_readback_plan_public_admin_route_impact_accepted_count": { + "type": "integer", + "const": 0 + }, + "k8s_argocd_post_incident_readback_plan_ai_provider_monitoring_impact_accepted_count": { + "type": "integer", + "const": 0 + }, + "k8s_argocd_post_incident_readback_plan_backup_restore_impact_accepted_count": { + "type": "integer", + "const": 0 + }, + "k8s_argocd_post_incident_readback_plan_operator_notification_accepted_count": { + "type": "integer", + "const": 0 + }, + "k8s_argocd_post_incident_readback_plan_cross_project_sync_accepted_count": { + "type": "integer", + "const": 0 + }, + "k8s_argocd_post_incident_readback_plan_recovery_or_still_degraded_accepted_count": { + "type": "integer", + "const": 0 + }, + "k8s_argocd_post_incident_readback_plan_postcheck_readback_accepted_count": { + "type": "integer", + "const": 0 + }, + "k8s_argocd_post_incident_readback_plan_recurrence_guard_accepted_count": { + "type": "integer", + "const": 0 + }, + "k8s_argocd_post_incident_readback_plan_no_false_green_accepted_count": { + "type": "integer", + "const": 0 + }, + "k8s_argocd_post_incident_readback_plan_argocd_api_read_authorized_count": { + "type": "integer", + "const": 0 + }, + "k8s_argocd_post_incident_readback_plan_argocd_sync_authorized_count": { + "type": "integer", + "const": 0 + }, + "k8s_argocd_post_incident_readback_plan_live_cluster_read_authorized_count": { + "type": "integer", + "const": 0 + }, + "k8s_argocd_post_incident_readback_plan_kubectl_action_authorized_count": { + "type": "integer", + "const": 0 + }, + "k8s_argocd_post_incident_readback_plan_helm_action_authorized_count": { + "type": "integer", + "const": 0 + }, + "k8s_argocd_post_incident_readback_plan_network_policy_change_authorized_count": { + "type": "integer", + "const": 0 + }, + "k8s_argocd_post_incident_readback_plan_nodeport_change_authorized_count": { + "type": "integer", + "const": 0 + }, + "k8s_argocd_post_incident_readback_plan_rbac_change_authorized_count": { + "type": "integer", + "const": 0 + }, + "k8s_argocd_post_incident_readback_plan_secret_value_collection_allowed_count": { + "type": "integer", + "const": 0 + }, + "k8s_argocd_post_incident_readback_plan_route_smoke_authorized_count": { + "type": "integer", + "const": 0 + }, + "k8s_argocd_post_incident_readback_plan_production_write_authorized_count": { + "type": "integer", + "const": 0 + }, + "k8s_argocd_post_incident_readback_plan_runtime_gate_count": { + "type": "integer", + "const": 0 + }, + "k8s_argocd_post_incident_readback_plan_action_button_count": { + "type": "integer", + "const": 0 + }, + "k8s_argocd_post_incident_readback_plan_coverage_percent_after_readback_plan": { + "type": "integer", + "const": 66 + }, + "k8s_production_gitops_coverage_percent": { + "type": "integer", + "const": 66 } }, "additionalProperties": false diff --git a/docs/security/HIGH-VALUE-CONFIG-CONTROL-COVERAGE.md b/docs/security/HIGH-VALUE-CONFIG-CONTROL-COVERAGE.md index c23e68fb2..f0b841256 100644 --- a/docs/security/HIGH-VALUE-CONFIG-CONTROL-COVERAGE.md +++ b/docs/security/HIGH-VALUE-CONFIG-CONTROL-COVERAGE.md @@ -38,6 +38,8 @@ 2026-06-15 再新增 `docs/security/K8S-ARGOCD-CHANGE-EVIDENCE-ACCEPTANCE.md` 與 `docs/security/k8s-argocd-change-evidence-acceptance.snapshot.json`,將四個 K8s / ArgoCD scan group 轉成 GitOps 變更證據驗收只讀帳本。固定 `change_evidence_candidate_count=4`、`c0_change_evidence_candidate_count=3`、`write_capable_candidate_count=4`、`required_evidence_field_count=18`、`reviewer_check_count=18`、`outcome_lane_count=8`、`blocked_action_count=28`,讓 `k8s_production_gitops` 從 `62%` 推進到 `64%`;proposed commit、rendered manifest diff、ArgoCD app / sync revision、health before / after、rollout status、route smoke、metrics / alert、secret metadata parity、blast radius、maintenance window、rollback revision、postcheck owner、runtime approval package、ArgoCD sync、kubectl action、Helm upgrade、NetworkPolicy / NodePort / RBAC 變更、production write 與 runtime gate 仍全部為 `0 / false`。 +2026-06-15 再新增 `docs/security/K8S-ARGOCD-POST-INCIDENT-READBACK-PLAN.md` 與 `docs/security/k8s-argocd-post-incident-readback-plan.snapshot.json`,把同一批 `awoooi_prod`、`argocd`、`velero`、`monitoring` 轉成事故後回讀計畫。固定 `readback_candidate_count=4`、`c0_readback_candidate_count=3`、`c1_readback_candidate_count=1`、`write_capable_readback_candidate_count=4`、`required_readback_field_count=31`、`reviewer_check_count=28`、`outcome_lane_count=10`、`blocked_action_count=41`,讓 `k8s_production_gitops` 從 `64%` 推進到 `66%`,高價值配置平均維持 `71%`,需 live evidence 類別仍為 `9`。此更新只補上 ArgoCD health / sync、Degraded / Pending、image pull / scheduling、rollout 前後、event / metrics / alert、drift scanner、CronJob、NetworkPolicy / RBAC / Secret metadata、public/admin route、AI provider / monitoring、backup / restore、跨專案同步、postcheck、防再發與 no-false-green 的脫敏回讀欄位;post-incident readback received / accepted、ArgoCD API read、ArgoCD sync、live cluster read、kubectl、Helm、NetworkPolicy / NodePort / RBAC 變更、secret value collection、route smoke、production write、runtime gate 與 action button 仍全部為 `0 / false`。 + ## 1.2a 2026-06-15 CD / Runner / Secret 注入變更證據驗收 已新增 `docs/security/CD-RUNNER-SECRET-INJECTION-CHANGE-EVIDENCE-ACCEPTANCE.md` 與 `docs/security/cd-runner-secret-injection-change-evidence-acceptance.snapshot.json`,將 CD pipeline、Code Review、Deploy alerts、Runner attestation 與 Secret parity / injection owner 轉成 metadata-only 變更證據驗收帳本。 @@ -267,6 +269,7 @@ python3 scripts/security/iwooos-config-control-guard.py --root . | AI provider / model routing owner response acceptance | `100%` | 已新增 `ai_provider_owner_response_acceptance_v1`,8 個 candidate、5 個 write-capable、24 個 owner 必填欄位、24 個 reviewer checks、10 條 outcome lanes、38 類 blocked action;AI provider / model routing 成熟度 `60% -> 64%` | | SSH / firewall / network post-incident readback plan | `100%` | 已新增 `ssh_network_post_incident_readback_plan_v1`,14 個事故回讀 candidate、6 個 write-capable、24 個必填欄位、24 個 reviewer checks、10 條 outcome lanes、34 類 blocked action;成熟度 `62% -> 64%`,readback received / accepted、actor、before / after、impact、通知、同步、恢復、防再發與 runtime gate 仍為 `0` | | Docker / systemd / host service post-incident readback plan | `100%` | 已新增 `host_service_post_incident_readback_plan_v1`,9 個事故回讀 candidate、3 個 write-capable、28 個必填欄位、28 個 reviewer checks、10 條 outcome lanes、41 類 blocked action;成熟度 `62% -> 64%`,readback received / accepted、Docker daemon、compose、systemd、failed unit、port binding、public/admin route、AI provider、monitoring、同步、防再發與 runtime gate 仍為 `0` | +| K8s / ArgoCD post-incident readback plan | `100%` | 已新增 `k8s_argocd_post_incident_readback_plan_v1`,4 個事故回讀 candidate、3 個 C0、4 個 write-capable、31 個必填欄位、28 個 reviewer checks、10 條 outcome lanes、41 類 blocked action;成熟度 `64% -> 66%`,readback received / accepted、ArgoCD health / sync、Pending、image pull / scheduling、drift、impact、同步、防再發與 runtime gate 仍為 `0` | | owner response 收件 | `0%` | 尚未收到或接受任何 owner response | | live evidence collection | `0%` | 未 SSH、未 live probe、未 active scan | | runtime gate | `0%` | 未開啟任何執行期閘門 | diff --git a/docs/security/IWOOOS-CONFIG-CONTROL-INVENTORY.md b/docs/security/IWOOOS-CONFIG-CONTROL-INVENTORY.md index bc9936168..c62f7fe03 100644 --- a/docs/security/IWOOOS-CONFIG-CONTROL-INVENTORY.md +++ b/docs/security/IWOOOS-CONFIG-CONTROL-INVENTORY.md @@ -65,13 +65,19 @@ 此更新只表示 proposed commit、rendered manifest diff、ArgoCD app / sync revision、health before / after、rollout status、route smoke、metrics / alert、secret metadata parity、blast radius、maintenance window、rollback revision 與 postcheck owner 已有收件驗收規則;change evidence received / accepted、runtime approval package、ArgoCD API read、ArgoCD sync、kubectl action、Helm upgrade、NetworkPolicy apply、NodePort change、RBAC change、live cluster read、production write、runtime gate 仍全部為 `0 / false`。 -### 0.3b 2026-06-15 CD / Runner / Secret 注入變更證據驗收 +### 0.3b 2026-06-15 K8s / ArgoCD 事故後回讀計畫 + +`k8s_argocd_post_incident_readback_plan_v1` 已把同一批 `awoooi_prod`、`argocd`、`velero`、`monitoring` 四個 scan group 轉成事故後回讀計畫。固定 `readback_candidates=4`、`c0=3`、`c1=1`、`write_capable=4`、`readback_fields=36`、`required_readback_fields=31`、`reviewer_checks=28`、`outcome_lanes=10`、`blocked_actions=41`,讓 K8s / ArgoCD 類別成熟度從 `64%` 推進到 `66%`。 + +此更新只表示 ArgoCD health / sync、Degraded / Pending、image pull / scheduling、rollout 前後、event / metrics / alert、drift scanner、CronJob、NetworkPolicy / RBAC / Secret metadata、public/admin route、AI provider / monitoring、backup / restore、operator notification、cross-project sync、recovery / still degraded、postcheck、recurrence guard 與 no-false-green 已有脫敏回讀欄位與審查分流;post-incident readback received / accepted、ArgoCD API read、ArgoCD sync、live cluster read、kubectl action、Helm action、NetworkPolicy / NodePort / RBAC 變更、secret value collection、route smoke、production write、runtime gate 仍全部為 `0 / false`。 + +### 0.3c 2026-06-15 CD / Runner / Secret 注入變更證據驗收 `cd_runner_secret_injection_change_evidence_acceptance_v1` 已把 CD pipeline、Code Review、Deploy alerts、Runner attestation 與 Repository secret name parity / injection owner 轉成 metadata-only 變更證據驗收只讀帳本。固定 `candidates=5`、`c0=4`、`c1=1`、`write_capable=5`、`workflow_files=33`、`referenced_secret_names=42`、`runner_labels=5`、`required_evidence_fields=19`、`reviewer_checks=19`、`outcome_lanes=8`、`blocked_actions=32`。 此更新讓 `secret_metadata` 類別成熟度從 `66%` 推進到 `68%`,讓 `gitea_workflow_runner_source_control` 類別成熟度從 `70%` 推進到 `72%`。它只表示 workflow diff、runner owner attestation、secret name parity、secret injection route、Gitea run readback、guard result、rollback owner 與 post-check evidence 已有收件驗收規則;workflow 修改、workflow dispatch、runner 啟用 / 重啟、GitHub hosted runner、secret value / hash / partial token 收集、secret store read、secret 建立 / 更新 / rotate / 刪除、webhook 修改、deploy key 修改、branch protection / CODEOWNERS 修改、refs sync、force push、GitHub primary switch、Gitea 停用、production deploy、runtime gate 仍全部為 `0 / false`。 -### 0.3c 2026-06-15 Public / Admin / API runtime config 變更證據驗收 +### 0.3d 2026-06-15 Public / Admin / API runtime config 變更證據驗收 `public_runtime_config_change_evidence_acceptance_v1` 已把公開產品頁、AwoooP 後台、API / CORS、frontend env、Sentry tunnel、webhook / callback 與跨產品 runtime route 轉成 metadata-only 變更證據驗收只讀帳本。固定 `candidates=6`、`c0=5`、`c1=1`、`write_capable=6`、`source_refs=20`、`required_evidence_fields=21`、`reviewer_checks=21`、`outcome_lanes=8`、`blocked_actions=32`。 @@ -286,6 +292,7 @@ Nginx 是目前必須最先資安控管的配置,原因是它同時控制公 | 端口 / 防火牆變更證據驗收 | `100%` | 已新增並強化 `port_firewall_change_evidence_acceptance_v1`,14 個 candidate、6 個 write-capable、21 個 reviewer checks、9 條 outcome lanes、28 類 blocked action;成熟度 `58% -> 62%` | | SSH / firewall / network 事故後回讀計畫 | `100%` | 已新增 `ssh_network_post_incident_readback_plan_v1`,14 個 readback candidate、24 個必填欄位、24 個 reviewer checks、10 條 outcome lanes、34 類 blocked action;成熟度 `62% -> 64%`,readback accepted 與 runtime gate 仍為 `0` | | K8s / ArgoCD GitOps 變更證據驗收 | `100%` | 已新增 `k8s_argocd_change_evidence_acceptance_v1`,4 個 candidate、3 個 C0、4 個 write-capable、18 個 reviewer checks、8 條 outcome lanes、28 類 blocked action;成熟度 `62% -> 64%` | +| K8s / ArgoCD 事故後回讀計畫 | `100%` | 已新增 `k8s_argocd_post_incident_readback_plan_v1`,4 個 readback candidate、31 個必填欄位、28 個 reviewer checks、10 條 outcome lanes、41 類 blocked action;成熟度 `64% -> 66%`,readback accepted 與 runtime gate 仍為 `0` | | Public / Admin / API runtime config 變更證據驗收 | `100%` | 已新增 `public_runtime_config_change_evidence_acceptance_v1` 與 `public_frontend_sensitive_surface_guard_v1`;6 個 candidate、5 個 C0、21 個 reviewer checks、8 條 outcome lanes、32 類 blocked action,另掃 225 個前端檔案、12 類禁字、違規 0;成熟度 `62% -> 66%`;raw namespace / repo slug / 內部狀態碼 / 內部協作內容外洩列為拒收或隔離條件 | | Package / Docker supply-chain repo-only baseline | `100%` | 已新增 `package_supply_chain_baseline_v1`,盤點 `package_json=6`、`pyproject=4`、`requirements=2`、`dockerfiles=2`、`compose=6`、`gaps=5`;不 install、不掃 CVE、不改 image、不部署 | | Package / Docker supply-chain owner policy gate | `100%` | 已新增 `package_supply_chain_owner_policy_gate_v1`,6 個 owner policy request、2 個 C0、8 個 owner 欄位、12 個 reviewer checks、20 類 blocked action;request_sent / received / accepted / runtime / action 仍為 `0 / false` | diff --git a/docs/security/IWOOOS-POSTURE-PROJECTION.md b/docs/security/IWOOOS-POSTURE-PROJECTION.md index c3466caf4..acda81f59 100644 --- a/docs/security/IWOOOS-POSTURE-PROJECTION.md +++ b/docs/security/IWOOOS-POSTURE-PROJECTION.md @@ -2,8 +2,8 @@ | 項目 | 內容 | |------|------| -| 日期 | 2026-06-14 | -| 狀態 | 草案;P0 governance 總帳已建立;高價值配置 Owner Packet count sync 已完成 | +| 日期 | 2026-06-15 | +| 狀態 | 草案;P0 governance 總帳已建立;高價值配置 Owner Packet count sync 與 K8s / ArgoCD 事故後回讀投影已完成 | | Schema | `docs/schemas/iwooos_posture_projection_v1.schema.json` | | Snapshot | `docs/security/iwooos-posture-projection.snapshot.json` | | 模式 | `mirror_only` | @@ -23,6 +23,12 @@ 此同步只代表 committed read-only projection 與前台顯示對齊;`request_sent_count`、`received_response_count`、`accepted_response_count`、`runtime_gate_count` 與 action buttons 仍全部維持 `0`,不代表 Nginx reload、certbot renew、DNS / TLS probe、workflow 修改、secret rotation、host write、active scan、production write 或 runtime gate。 +## 1.2 2026-06-15 K8s / ArgoCD 事故後回讀投影 + +`k8s_argocd_post_incident_readback_plan_v1` 已投影到 `iwooos-posture-projection.snapshot.json` 與前台 marker。固定 `candidate_count=4`、`c0_candidate_count=3`、`write_capable_candidate_count=4`、`required_readback_field_count=31`、`reviewer_check_count=28`、`outcome_lane_count=10`、`blocked_action_count=41`,並讓 `k8s_production_gitops_coverage_percent=66`。 + +此同步只代表前端可以顯示 K8s / ArgoCD 事故後回讀計畫與邊界;`post_incident_readback_received_count`、`post_incident_readback_accepted_count`、`argocd_api_read_authorized_count`、`argocd_sync_authorized_count`、`kubectl_action_authorized_count`、`runtime_gate_count` 與 `action_button_count` 仍全部維持 `0`。不得把 ArgoCD `Synced`、route 200、Pod Running、CD success 或 smoke pass 視為資安驗收。 + ## 2. 來源 IwoooS 首版只讀取或對齊以下已提交 evidence: @@ -33,6 +39,7 @@ IwoooS 首版只讀取或對齊以下已提交 evidence: | `security_rollout_policy_v1` | 7 條 low-friction non-blocking lanes | | `source_control_owner_response_validation_rollup_v1` | owner response 仍為 0、S4.9 下一個收件候選 | | `source_control_primary_readiness_gate_v1` | GitHub primary readiness 仍為 0、候選 repo 與切換前置缺口 | +| `k8s_argocd_post_incident_readback_plan_v1` | K8s / ArgoCD 事故後回讀計畫、66% 子項成熟度、31 個必填欄位、41 類 blocked action、runtime gate 0 | | `kali_integration_status_v1` | Kali 112 observe-only 整合態勢 | | `vibework_iwooos_onboarding_handoff_v1` | VibeWork repo / product / surface / owner / evidence refs / 獨立產品邊界只讀 handoff | | `docs/LOGBOOK.md` | 部署 marker、Gitea run 與 rollout risk 邊界紀錄 | @@ -103,6 +110,7 @@ IwoooS 首版只讀取或對齊以下已提交 evidence: 56. 16 個 SSH / network access repo-only inventory surfaces、owner response acceptance 與端口 / 防火牆變更證據驗收只讀帳本,顯示 SSH target、known_hosts workflow、CI deploy SSH、monitoring SSH、backup SSH capture、sudoers wrapper、NetworkPolicy、NodePort、WireGuard runbook 與 alert SSH action catalog 的第一層清冊;write-capable surface `6`、NetworkPolicy `2`、NodePort `2`、sudoers `1`、WireGuard `1`,acceptance candidate `16`、change evidence candidate `14`、reviewer check `21`、outcome lane `9`、blocked action `28`,讓 SSH / network 類別成熟度從 `58%` 推進到 `62%`;owner response、change evidence、actor、before / after state、service health impact、operator notification、cross-project sync、post-check evidence、maintenance window、rollback owner、runtime gate 與 action button 仍全部為 `0`,不代表 SSH、sudo、firewall、port close / open、NetworkPolicy、NodePort、WireGuard、route smoke 或 known_hosts patch 已授權。 56d. 14 個 SSH / network / firewall post-incident readback 候選,顯示端口關閉、firewall / NetworkPolicy / NodePort / WireGuard policy、deploy SSH、sudo 與 alert action 事故後必須回讀 actor、before / after、service / public route / AI provider / monitoring impact、operator notification、cross-project sync、restoration evidence、post-check、recurrence guard 與 no-false-green attestation;write-capable candidate `6`、policy / exposure candidate `5`、required readback field `24`、reviewer check `24`、outcome lane `10`、blocked action `34`,讓 SSH / network 類別成熟度從 `62%` 推進到 `64%`;readback received / accepted、actor accepted、before / after accepted、impact accepted、notification accepted、sync accepted、restoration accepted、recurrence guard accepted、runtime gate 與 action button 仍全部為 `0`。 56a. 4 個 K8s / ArgoCD GitOps 變更證據驗收候選,顯示 production manifests、ArgoCD app、Velero、monitoring manifests 的 proposed commit、rendered manifest diff、ArgoCD app / sync revision、health before / after、rollout、route smoke、metrics / alert、secret metadata parity、blast radius、maintenance window、rollback revision 與 postcheck owner 收件規則;C0 candidate `3`、write-capable candidate `4`、reviewer check `18`、outcome lane `8`、blocked action `28`,讓 K8s / ArgoCD 類別成熟度從 `62%` 推進到 `64%`;change evidence、runtime approval package、ArgoCD API read、ArgoCD sync、kubectl action、Helm upgrade、NetworkPolicy / NodePort / RBAC change、production write、runtime gate 與 action button 仍全部為 `0`。 +56a.1. 4 個 K8s / ArgoCD post-incident readback 候選,顯示 ArgoCD app health、sync status、Degraded / Pending、image pull / scheduling、rollout before / after、event / metrics / alert、drift scanner、CronJob、NetworkPolicy / RBAC / Secret metadata、public/admin route、AI provider / monitoring、backup / restore、operator notification、cross-project sync、postcheck、recurrence guard 與 no-false-green attestation 的事故後回讀規則;C0 candidate `3`、write-capable candidate `4`、required readback field `31`、reviewer check `28`、outcome lane `10`、blocked action `41`,讓 K8s / ArgoCD 類別成熟度從 `64%` 推進到 `66%`;readback received / accepted、ArgoCD API read、ArgoCD sync、live cluster read、kubectl、Helm、NetworkPolicy / NodePort / RBAC change、route smoke、production write、runtime gate 與 action button 仍全部為 `0`。 56b. 5 個 CD / Runner / Secret 注入變更證據驗收候選,顯示 CD pipeline、程式碼審查、部署通知、執行器證明與 repository secret name parity / injection owner 的 metadata-only 收件規則;C0 candidate `4`、write-capable candidate `5`、local workflow file `33`、referenced secret name `42`、runner label `5`、reviewer check `19`、outcome lane `8`、blocked action `32`,讓 secret metadata 類別成熟度從 `66%` 推進到 `68%`,讓 Gitea workflow / runner 類別成熟度從 `70%` 推進到 `72%`;workflow diff、runner attestation、secret name parity、secret injection route、deploy marker readback、guard result、postcheck evidence、runtime approval package、workflow modification、runner change、repo secret change、secret rotation、Gitea action dispatch、production deploy、runtime gate 與 action button 仍全部為 `0`。 56c. 8 個 AI provider / model routing owner response acceptance 候選,顯示 AI router provider policy、Ollama proxy gateway、fallback order / circuit breaker、cost budget / quota、privacy / data egress、benchmark / dry-run、model card / version inventory 與 agent replacement candidate boundary 的 metadata-only 收件規則;write-capable candidate `5`、paid-provider candidate `5`、data-egress candidate `6`、owner field `24`、reviewer check `24`、outcome lane `10`、blocked action `38`,讓 AI provider / model routing 類別成熟度從 `60%` 推進到 `64%`;owner response、fallback order、dry-run、benchmark、cost review、privacy review、prompt redaction、quality gate、provider switch、external provider call、paid provider call、prompt send、live endpoint probe、secret collection、SDK install、shadow / canary、runtime gate 與 action button 仍全部為 `0`。 57. 38 個 Backup / restore / escrow / retention repo-only inventory surfaces,顯示 backup orchestration、service backup scripts、restic retention、offsite sync、credential escrow、Velero restore drill、backup health alert 與 cold-start / DR runbook 的第一層清冊;write-capable surface `27`、restore drill surface `4`、offsite / escrow surface `8`,owner response、live evidence、restore drill、offsite sync、credential escrow、retention change、runtime gate 與 action button 仍全部為 `0`,不代表 backup、restore、offsite sync、remote delete、restic prune、escrow marker write、rclone config 或 Velero restore 已授權。 diff --git a/docs/security/K8S-ARGOCD-POST-INCIDENT-READBACK-PLAN.md b/docs/security/K8S-ARGOCD-POST-INCIDENT-READBACK-PLAN.md new file mode 100644 index 000000000..fbe863c27 --- /dev/null +++ b/docs/security/K8S-ARGOCD-POST-INCIDENT-READBACK-PLAN.md @@ -0,0 +1,155 @@ +# K8s / ArgoCD 事故後回讀計畫 + +> 狀態:只讀計畫完成,等待 GitOps / K8s owner 提供脫敏事故回讀包。 +> 範圍:K8s production manifests、ArgoCD、Velero、monitoring manifests。 +> 邊界:本文件不是 ArgoCD API read、sync、rollback、`kubectl`、Helm、Kustomize、NetworkPolicy / NodePort / RBAC 變更、route smoke、secret 收集、production write 或 runtime gate。 + +## 1. 為什麼新增這一層 + +`k8s_argocd_change_evidence_acceptance_v1` 已經定義 proposed commit、rendered manifest diff、ArgoCD app / sync revision、health before / after、rollout、route smoke、metrics / alert、secret metadata parity、blast radius、maintenance window、rollback revision 與 post-check owner 的收件規則。 + +本輪再補 `k8s_argocd_post_incident_readback_plan_v1`,原因是事故中可能同時出現: + +- ArgoCD 顯示 `Synced / Degraded`,但服務局部仍未恢復。 +- Pod、Job 或 CronJob 持續 `Pending`,可能卡在 image pull、scheduling、quota、node、PVC 或 RBAC。 +- drift-scanner、備份排程、監控告警與 public / admin route 互相影響。 +- CD success、deploy marker、route 200、Pod Running 或 UI 可見被誤讀成資安驗收完成。 + +因此這一層只建立事故後回讀欄位、reviewer checks、結果分流與禁止動作,讓 owner evidence 可以被低摩擦收件;在 reviewer record 出現前,所有 accepted / runtime count 必須維持 `0`。 + +## 2. 固定摘要 + +| 欄位 | 值 | +|------|----| +| schema | `k8s_argocd_post_incident_readback_plan_v1` | +| 來源 schema | `k8s_argocd_change_evidence_acceptance_v1` | +| readback candidates | `4` | +| C0 candidates | `3` | +| C1 candidates | `1` | +| write-capable candidates | `4` | +| source manifest files | `49` | +| source YAML manifest files | `45` | +| source C0 files | `36` | +| Deployment objects | `5` | +| CronJob objects | `5` | +| Secret objects | `6` | +| NetworkPolicy objects | `6` | +| RBAC objects | `5` | +| ArgoCD Application objects | `1` | +| PrometheusRule objects | `4` | +| readback fields | `36` | +| required readback fields | `31` | +| reviewer checks | `28` | +| outcome lanes | `10` | +| blocked actions | `41` | +| coverage after plan | `66%` | +| post-incident readback received / accepted | `0 / 0` | +| runtime gate | `0` | +| action buttons | `0` | + +## 3. Readback candidates + +| Candidate | Scope | +|-----------|-------| +| `k8s_argocd_post_incident_readback:awoooi_prod` | AWOOOI production manifests、Deployment、Service、NetworkPolicy、Secret metadata、route 與 rollout 影響 | +| `k8s_argocd_post_incident_readback:argocd` | ArgoCD Application、sync / health、revision、degraded 狀態與 rollback evidence | +| `k8s_argocd_post_incident_readback:velero` | Velero、backup / restore、CronJob / schedule、PVC / object storage 與 DR 影響 | +| `k8s_argocd_post_incident_readback:monitoring` | PrometheusRule、monitoring manifests、alert health、drift-scanner 與 receiver route 影響 | + +## 4. 必填事故後回讀欄位 + +1. `k8s_incident_or_change_ref` +2. `actor_attribution_ref` +3. `argocd_app_health_ref` +4. `argocd_sync_status_ref` +5. `degraded_state_ref` +6. `pending_workload_ref` +7. `image_pull_or_scheduling_ref` +8. `rollout_before_ref` +9. `rollout_after_ref` +10. `event_summary_ref` +11. `metrics_alert_ref` +12. `drift_scanner_ref` +13. `cronjob_schedule_ref` +14. `secret_metadata_parity_ref` +15. `network_policy_service_impact_ref` +16. `rbac_serviceaccount_impact_ref` +17. `public_admin_route_impact_ref` +18. `ai_provider_monitoring_impact_ref` +19. `operator_notification_ref` +20. `cross_project_sync_ref` +21. `recovery_or_still_degraded_ref` +22. `postcheck_readback_ref` +23. `recurrence_guard_ref` +24. `maintenance_window` +25. `rollback_revision` +26. `rollback_owner` +27. `followup_owner` +28. `redacted_evidence_refs` +29. `no_secret_value_attestation` +30. `no_raw_manifest_or_kubeconfig_attestation` +31. `no_false_green_attestation` + +## 5. Reviewer checks + +Reviewer 必須確認: + +- incident / change / deploy marker ref 可追溯。 +- actor role / team 可追溯,不能接受匿名 sync、rollback、kubectl、Helm、rollout 或 image 變更。 +- ArgoCD sync status、health status、revision 與 degraded state 有脫敏 ref。 +- Pending workload 已回讀 image pull、scheduling、quota、node、PVC、RBAC 或其他原因摘要。 +- rollout before / after、event summary、metrics / alert、drift-scanner、CronJob schedule 與 route / AI provider / monitoring 影響可讀。 +- Secret 只提供 metadata parity,不含 value、hash、partial token、DSN、cookie 或 kubeconfig。 +- NetworkPolicy、Service、Ingress、NodePort、RBAC、ServiceAccount 影響已列清楚。 +- post-check 獨立於原操作人與 UI 卡片。 +- recurrence guard、maintenance window、rollback revision、rollback owner 與 followup owner 可追溯。 +- 不用 route 200、Pod Running、ArgoCD Synced、CD success、dashboard up 或 UI 可見當作事故驗收。 + +## 6. Outcome lanes + +| Lane | 意義 | +|------|------| +| `waiting_post_incident_readback` | 尚未收到 K8s / ArgoCD 事故回讀包;所有 accepted / runtime count 維持 0 | +| `request_actor_or_revision_supplement` | 缺 actor、deploy marker、ArgoCD revision 或 rollback revision 時要求補件 | +| `request_degraded_pending_supplement` | 缺 Degraded / Pending / image pull / scheduling / rollout before-after 時要求補件 | +| `request_event_metric_supplement` | 缺 event summary、metrics、alert、drift scanner 或 CronJob schedule 時要求補件 | +| `request_route_dependency_supplement` | 缺 route、AI provider、monitoring、backup / restore、network / RBAC 影響時要求補件 | +| `quarantine_raw_payload` | 收到 Secret value、kubeconfig、raw manifest、raw log、raw event 或未脫敏截圖時隔離 | +| `reject_runtime_claim` | 把 CD success、ArgoCD Synced、route 200、Pod Running 或 UI 可見當驗收時拒收 | +| `ready_for_k8s_post_incident_review` | metadata 合格後,只能進 reviewer review | +| `recurrence_guard_backfill_required` | 需補防再發 guard、owner review、change freeze 或 automation block | +| `waiting_runtime_gate` | 即使 readback accepted,runtime gate 仍需獨立人工批准 | + +## 7. 禁止動作 + +本計畫固定 `blocked_actions=41`。其中包含: + +- `argocd_api_read`、`argocd_sync`、`argocd_rollback` +- `live_cluster_read`、`kubectl_get_live`、`kubectl_apply`、`kubectl_patch`、`kubectl_delete`、`kubectl_rollout_restart`、`kubectl_scale` +- `helm_upgrade`、`helm_rollback`、`kustomize_image_set` +- `change_network_policy`、`change_nodeport`、`change_service_type`、`change_ingress_route`、`change_rbac`、`change_serviceaccount` +- `change_configmap_runtime`、`change_secret_metadata` +- `secret_value_collection`、`kubeconfig_collection`、`raw_manifest_storage`、`raw_event_dump_storage`、`raw_pod_log_storage`、`raw_secret_storage` +- `velero_restore`、`restore_backup`、`prometheus_rule_apply`、`alertmanager_reload` +- `route_smoke`、`production_write` +- `accept_synced_as_healthy`、`accept_route_200_as_all_green`、`accept_pod_running_as_all_green`、`accept_cd_success_as_security_acceptance` +- `skip_degraded_pending_review`、`mark_readback_accepted_without_reviewer_record`、`open_runtime_gate`、`add_action_button` + +## 8. 下一步 + +下一步只能收 GitOps / K8s owner 提供的脫敏事故回讀包,欄位至少包含: + +- incident / change / deploy marker 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 / Ingress / NodePort / RBAC / ServiceAccount 影響 +- public / admin route、AI provider、monitoring、backup / restore 影響 +- operator notification 與 cross-project sync ref +- recovery 或 still-degraded ref +- post-check、recurrence guard、maintenance window、rollback revision、rollback owner、followup owner +- no-secret-value、no-raw-manifest-or-kubeconfig、no-false-green attestation + +在 reviewer record 前,`post_incident_readback_received_count=0`、`post_incident_readback_accepted_count=0`、`runtime_gate_count=0`、`action_button_count=0` 必須維持不變。 diff --git a/docs/security/SECURITY-SUPPLY-CHAIN-PROGRESS.md b/docs/security/SECURITY-SUPPLY-CHAIN-PROGRESS.md index d25a84a22..4a9382e75 100644 --- a/docs/security/SECURITY-SUPPLY-CHAIN-PROGRESS.md +++ b/docs/security/SECURITY-SUPPLY-CHAIN-PROGRESS.md @@ -3,17 +3,23 @@ | 項目 | 內容 | |------|------| | 日期 | 2026-06-15 | -| 狀態 | IwoooS 64% 只讀治理推進中;高價值配置集中 guard、Package / Docker 供應鏈 repo-only baseline 與 Package / Docker 供應鏈 owner policy gate 已完成;Frontend public sensitive surface guard、Backup / Restore / Escrow owner response acceptance backfill、Monitoring / Alerting / Observability no-false-green owner response acceptance、Host Service change evidence acceptance、Host Service post-incident readback plan、AI provider / model routing owner response acceptance、CD / Runner / Secret 注入變更證據驗收與 Public / Admin / API runtime config 變更證據驗收只讀帳本已本地完成;端口 / 防火牆變更證據驗收、主機服務事故回補與 K8s / ArgoCD GitOps 變更證據驗收已正式部署驗證;S4.9 owner response gate 仍是第一優先 | +| 狀態 | IwoooS 64% 只讀治理推進中;高價值配置集中 guard、Package / Docker 供應鏈 repo-only baseline 與 Package / Docker 供應鏈 owner policy gate 已完成;Frontend public sensitive surface guard、Backup / Restore / Escrow owner response acceptance backfill、Monitoring / Alerting / Observability no-false-green owner response acceptance、Host Service change evidence acceptance、Host Service post-incident readback plan、AI provider / model routing owner response acceptance、CD / Runner / Secret 注入變更證據驗收、Public / Admin / API runtime config 變更證據驗收與 K8s / ArgoCD post-incident readback plan 已本地完成;端口 / 防火牆變更證據驗收、主機服務事故回補與 K8s / ArgoCD GitOps 變更證據驗收已正式部署驗證;S4.9 owner response gate 仍是第一優先 | | 本階段完成 | 資安供應鏈 contract manifest + Source Control Approval Board + Draft Reconcile Plan + Ref Detail Diff + Ref Truth Classification + Source Control Ref Truth Owner Response 收件包 + GitHub Primary Readiness Gate + GitHub Primary Rollback ADR + GitHub Target Owner Decision Response 收件包 + Gitea 認證清冊匯出請求 + Gitea 認證清冊匯入驗收契約 + Gitea 清冊覆蓋 Owner Attestation + Gitea Owner Attestation Approval Lane 對齊 + Gitea Owner Attestation Response 收件包 + Workflow / Secret Name Inventory + Workflow / Secret Name Local Evidence + Workflow / Secret Name Redacted Export Request + Workflow / Secret Name Owner Response 收件包 + Source Control Owner Response Validation Rollup + Kali 112 live integration status + Security Finding contract + Kali scan scope approval package + Security Approval Queue + S3 人工批准 Gate + S3 人工決策紀錄 + S3 人工審查封包 + S3 人工決策狀態轉移 + S3 後續 runtime gate 準備契約 + 鏡像 readiness index + 鏡像接收計畫 + 鏡像事件信封 + 鏡像路由矩陣 + 鏡像驗收契約 + 鏡像隔離契約 + 鏡像 dry-run 報告契約 + 鏡像狀態彙整契約 + IwoooS 前端態勢入口 + IwoooS posture projection contract + IwoooS 既有前端資安頁面整合 + IwoooS 覆蓋與邊界矩陣 + IwoooS 只讀資安處理旅程 + IwoooS owner evidence readiness board + IwoooS host coverage view + IwoooS host action gate matrix + IwoooS host evidence readiness board + IwoooS host evidence collection order + IwoooS host evidence intake preflight + IwoooS host evidence review outcome lanes + IwoooS host evidence review handoff packets + IwoooS host evidence reviewer checklist + IwoooS host evidence reviewer outcome lanes + IwoooS host owner decision candidate packets + IwoooS host owner decision review checklist + IwoooS host owner decision review outcome lanes + IwoooS host owner decision record draft packets + IwoooS host owner decision record draft review checklist + IwoooS host owner decision record draft review outcome lanes + IwoooS host owner decision record write-up packets + IwoooS host owner decision record write-up review checklist + IwoooS host owner decision record write-up review outcome lanes + IwoooS host owner decision record formal candidate packets + IwoooS host owner decision record formal candidate review checklist + IwoooS host owner decision record formal candidate review outcome lanes + IwoooS host owner decision record formal record queue packets + IwoooS host owner decision record formal record queue review checklist + IwoooS host owner decision record formal record queue review outcome lanes + IwoooS host owner decision record human handoff readiness packets + IwoooS host owner decision record human handoff readiness review checklist + IwoooS host owner decision record human handoff readiness review outcome lanes + IwoooS host owner decision record human record owner review candidate packets + IwoooS host owner decision record human record owner review candidate checklist + IwoooS host owner decision record human record owner review candidate outcome lanes + IwoooS host owner decision record human record owner review preparation packets + IwoooS host owner decision record human record owner review preparation checklist + IwoooS progress acceleration lanes + IwoooS owner response next-action focus + IwoooS S4.9 owner response preflight + IwoooS S4.9 owner response request templates + IwoooS progress hold movement gates + IwoooS AwoooP read-only landing readiness + IwoooS AwoooP cross-session handoff packets + AwoooP 首頁 IwoooS 資安鏡像候選 + AwoooP 工作鏈路 IwoooS 資安鏡像候選 + AwoooP 審批佇列 IwoooS owner response 只讀焦點 | | 本階段追加 | AwoooP 合約儀表板 IwoooS 資安契約只讀候選 + AwoooP 租戶管理 IwoooS 資安租戶範圍只讀候選 + AwoooP 執行監控 IwoooS 執行狀態只讀候選 + 既有安全 / 合規頁面 IwoooS 只讀反向橋接 + 告警 / 錯誤 / 授權 / 治理頁面 IwoooS 只讀反向橋接 + 稽核 / 工程審查頁面 IwoooS 深色只讀反向橋接 + IwoooS 前端資安頁面連接狀態板 + IwoooS GitHub 主要來源就緒度只讀狀態板 + AwoooP 工作鏈路 GitHub 主要來源就緒度只讀工作項 + AwoooP 合約儀表板 GitHub 主要來源就緒度合約只讀候選 + AwoooP 審批佇列 GitHub 主要來源就緒度審批邊界 + AwoooP 首頁 GitHub 主要來源就緒度只讀摘要 + AwoooP 租戶管理 GitHub 主要來源就緒度租戶範圍 + AwoooP 執行監控 GitHub 主要來源就緒度執行邊界 + IwoooS / AwoooP 資安可視區塊繁體中文呈現防護檢查 + AwoooP 執行詳情 / 審批詳情繁體中文呈現防護檢查 + AwoooP 首頁負責人回覆驗收總覽 + AwoooP 工作鏈路負責人回覆驗收只讀工作項 + AwoooP 合約儀表板負責人回覆驗收契約只讀候選 + AwoooP 審批佇列負責人回覆驗收只讀審查邊界 + AwoooP 租戶管理負責人回覆驗收租戶範圍 + AwoooP 執行監控負責人回覆驗收執行邊界 + AwoooP 執行詳情負責人回覆驗收詳情邊界 + AwoooP 審批決策負責人回覆驗收審批邊界 + IwoooS AwoooP 資安入口覆蓋狀態板 + IwoooS 階段式資安收斂節奏圖 + IwoooS 下一步人工收件作戰板 + IwoooS 人工回覆安全驗收閘道 + IwoooS 人工回覆審查結果分流 + IwoooS 人工決策準備佇列 + IwoooS 人工決策紀錄草稿防誤用 + IwoooS 人工決策正式紀錄負責人指派確認準備包 + IwoooS 人工決策正式紀錄負責人指派確認清單 + IwoooS 人工決策正式紀錄負責人指派確認結果分流 + IwoooS 人工決策正式紀錄負責人指派決策準備包 + IwoooS 人工決策正式紀錄負責人指派決策檢查清單 + IwoooS S4.9 負責人回覆封套欄位 + IwoooS S4.9 負責人回覆封套送件前檢查 + IwoooS S4.9 負責人回覆封套送件前結果分流 + IwoooS S4.9 負責人回覆送件請求草稿 + IwoooS S4.9 負責人回覆送件鏈路摘要 + IwoooS 低摩擦分階段收斂主控 + IwoooS 低摩擦下一步行動邊界 + IwoooS 64% 進度移動訊號驗收條 + IwoooS 第一個進度解鎖路徑 + IwoooS 第一解鎖證據包 + IwoooS 第一解鎖證據包預檢分流 + IwoooS 第一解鎖證據包補件路徑 + IwoooS 第一解鎖證據包補件送審前檢查 + IwoooS 第一解鎖證據包補件送審結果分流 + IwoooS 第一解鎖證據包 reviewer 指派準備包 + IwoooS 第一解鎖證據包 reviewer 指派前檢查 + IwoooS 第一解鎖證據包 reviewer 指派前檢查結果分流 + IwoooS 正式只讀 landing 與 Kali 112 只讀證據進度重估 | | 本階段追加補充 | IwoooS 目前具體工作地圖 + IwoooS 目前具體交付清單 + IwoooS 目前阻塞與解除條件 + IwoooS 三軸進度與全產品套用範圍 + IwoooS 全產品分階段套用台帳 + IwoooS 全產品 rollout 波次驗收門檻 + IwoooS 全產品 rollout 驗收結果分流 + IwoooS 全產品證據接線地圖 + IwoooS 全產品證據接線預檢 + IwoooS 全產品證據接線預檢結果分流 + IwoooS 全產品預檢補件回收台帳 + IwoooS 全產品補件重試門檻 + IwoooS 全產品重試結果分流 + IwoooS 全產品人工審查候選準備 + IwoooS 全產品人工審查候選預檢 + IwoooS 全產品人工審查候選預檢結果分流 + IwoooS 全產品人工審查候選預檢補件回收台帳 + IwoooS 全產品人工審查候選預檢補件重試門檻 + IwoooS 全產品只讀套用快照 + P2-145 owner response acceptance gate 正式驗證完成 | -| P0 追加 | IwoooS P0 配置控管優先序前台正式驗證完成;Nginx public gateway、DNS / TLS / certbot、K8s / ArgoCD / production manifests、Workflow / runner / secret metadata、Public / admin / API runtime config、agent-bounty runtime / treasury 六類先列為即時風險配置;高價值配置 Gate 已補上 `k8s/nginx/**`、`scripts/ops/**/*cert*`、`scripts/ops/**/*tls*`,sample 從 `matched=0 / C0=0` 收斂到 `matched=3 / C0=2`;Gate 預設工作樹 preflight 已可讀取 staged / unstaged / untracked,本地 smoke 對臨時 `k8s/nginx/*` 檔命中 C0;Owner Packet snapshot 已同步為 `packets=3 / c0=2`,Coverage snapshot 已同步最新 patterns;IwoooS / AwoooP 前台 Owner Packet 摘要已正式驗證 `packet=3 / c0=2`,feature commit `e999c16b`、deploy marker `16c6b983`、Gitea code-review `2973` / CD `2972` success;IwoooS posture projection snapshot / schema / guard 已同步 `packet=3 / c0=2`,不再保留舊 `1 / 0` 口徑;高價值配置 Owner Packet 收件預檢已新增 `checks=9 / lanes=5 / required_fields=27 / blocked_requests=16`;高價值配置 Owner Request 草稿包已新增 `drafts=3 / handoff_fields=11 / forbidden_payloads=12 / sent=0`;Public Gateway live conf 匯出請求包已新增 `requests=3 / c0=2 / redaction_rules=8 / received=0`;Public Gateway redacted export 收件預檢已新增 `candidates=3 / c0=2 / checks=10 / rejection_guards=12 / received=0 / accepted=0`;Public Gateway rendered diff / nginx gate 草稿已新增 `candidates=3 / c0=2 / stages=7 / blocked=14 / rendered_diff=0 / runtime=0`;Public Gateway owner response acceptance 只讀帳本已新增 `candidates=3 / c0=2 / fields=33 / checks=22 / lanes=8 / blocked=28 / accepted=0 / runtime=0`,並補上手動 / 緊急 gateway 變更的 intent、approval / break-glass、route health、rollback validation 與 post-change monitoring 必填 ref;DNS / TLS / certbot Owner Confirmation Request 已新增 `requests=4 / c0=4 / fields=9 / questions=5 / guards=12 / received=0 / accepted=0`;K8s / ArgoCD manifest repo-only 清冊已新增 `files=49 / c0=36 / yaml=45 / kinds=20 / blocked=13 / runtime=0`;K8s / ArgoCD Owner Request Draft 已新增 `drafts=4 / c0=3 / fields=11 / sent=0 / runtime=0`;K8s / ArgoCD owner response acceptance 只讀帳本已新增 `candidates=4 / c0=3 / fields=11 / checks=12 / lanes=7 / blocked=18 / accepted=0 / runtime=0`;K8s / ArgoCD GitOps 變更證據驗收已新增 `candidates=4 / c0=3 / write_capable=4 / evidence_fields=18 / checks=18 / lanes=8 / blocked=28 / accepted=0 / runtime=0`;CD / Runner / Secret 注入變更證據驗收已新增 `candidates=5 / c0=4 / write_capable=5 / workflow_files=33 / secret_names=42 / runner_labels=5 / evidence_fields=19 / checks=19 / lanes=8 / blocked=32 / accepted=0 / runtime=0`;Public / Admin / API runtime config 變更證據驗收已新增 `candidates=6 / c0=5 / write_capable=6 / source_refs=20 / evidence_fields=21 / checks=21 / lanes=8 / blocked=32 / accepted=0 / runtime=0`,並把 raw namespace、repo slug、內部狀態碼與內部協作內容外洩列為拒收 / 隔離;Frontend public sensitive surface guard 已新增 `files=225 / patterns=12 / allowlisted=2 / violations=0 / runtime=0`,讓 public runtime config 成熟度 `64% -> 66%`、高價值配置平均 `69% -> 70%`;Backup / Restore / Escrow owner response acceptance 只讀帳本已更新為 `candidates=38 / write_capable=27 / fields=33 / owner_fields=23 / reviewer_checks=22 / lanes=9 / blocked=31 / accepted=0 / runtime=0`;SSH / Firewall / Network Access owner response acceptance 只讀帳本已新增 `candidates=16 / write_capable=6 / fields=13 / checks=15 / lanes=7 / blocked=22 / accepted=0 / runtime=0`;端口 / 防火牆變更證據驗收只讀帳本已新增 `candidates=14 / write_capable=6 / policy_or_exposure=5 / evidence_fields=16 / checks=16 / lanes=8 / blocked=24 / accepted=0 / runtime=0`;owner response / live evidence / runtime gate / action buttons 仍全部為 0 | +| P0 追加 | IwoooS P0 配置控管優先序前台正式驗證完成;Nginx public gateway、DNS / TLS / certbot、K8s / ArgoCD / production manifests、Workflow / runner / secret metadata、Public / admin / API runtime config、agent-bounty runtime / treasury 六類先列為即時風險配置;高價值配置 Gate 已補上 `k8s/nginx/**`、`scripts/ops/**/*cert*`、`scripts/ops/**/*tls*`,sample 從 `matched=0 / C0=0` 收斂到 `matched=3 / C0=2`;Gate 預設工作樹 preflight 已可讀取 staged / unstaged / untracked,本地 smoke 對臨時 `k8s/nginx/*` 檔命中 C0;Owner Packet snapshot 已同步為 `packets=3 / c0=2`,Coverage snapshot 已同步最新 patterns;IwoooS / AwoooP 前台 Owner Packet 摘要已正式驗證 `packet=3 / c0=2`,feature commit `e999c16b`、deploy marker `16c6b983`、Gitea code-review `2973` / CD `2972` success;IwoooS posture projection snapshot / schema / guard 已同步 `packet=3 / c0=2`,不再保留舊 `1 / 0` 口徑;高價值配置 Owner Packet 收件預檢已新增 `checks=9 / lanes=5 / required_fields=27 / blocked_requests=16`;高價值配置 Owner Request 草稿包已新增 `drafts=3 / handoff_fields=11 / forbidden_payloads=12 / sent=0`;Public Gateway live conf 匯出請求包已新增 `requests=3 / c0=2 / redaction_rules=8 / received=0`;Public Gateway redacted export 收件預檢已新增 `candidates=3 / c0=2 / checks=10 / rejection_guards=12 / received=0 / accepted=0`;Public Gateway rendered diff / nginx gate 草稿已新增 `candidates=3 / c0=2 / stages=7 / blocked=14 / rendered_diff=0 / runtime=0`;Public Gateway owner response acceptance 只讀帳本已新增 `candidates=3 / c0=2 / fields=33 / checks=22 / lanes=8 / blocked=28 / accepted=0 / runtime=0`,並補上手動 / 緊急 gateway 變更的 intent、approval / break-glass、route health、rollback validation 與 post-change monitoring 必填 ref;DNS / TLS / certbot Owner Confirmation Request 已新增 `requests=4 / c0=4 / fields=9 / questions=5 / guards=12 / received=0 / accepted=0`;K8s / ArgoCD manifest repo-only 清冊已新增 `files=49 / c0=36 / yaml=45 / kinds=20 / blocked=13 / runtime=0`;K8s / ArgoCD Owner Request Draft 已新增 `drafts=4 / c0=3 / fields=11 / sent=0 / runtime=0`;K8s / ArgoCD owner response acceptance 只讀帳本已新增 `candidates=4 / c0=3 / fields=11 / checks=12 / lanes=7 / blocked=18 / accepted=0 / runtime=0`;K8s / ArgoCD GitOps 變更證據驗收已新增 `candidates=4 / c0=3 / write_capable=4 / evidence_fields=18 / checks=18 / lanes=8 / blocked=28 / accepted=0 / runtime=0`;K8s / ArgoCD Post-incident Readback Plan 已新增 `candidates=4 / c0=3 / c1=1 / write_capable=4 / required_fields=31 / reviewer_checks=28 / lanes=10 / blocked=41 / accepted=0 / runtime=0`;CD / Runner / Secret 注入變更證據驗收已新增 `candidates=5 / c0=4 / write_capable=5 / workflow_files=33 / secret_names=42 / runner_labels=5 / evidence_fields=19 / checks=19 / lanes=8 / blocked=32 / accepted=0 / runtime=0`;Public / Admin / API runtime config 變更證據驗收已新增 `candidates=6 / c0=5 / write_capable=6 / source_refs=20 / evidence_fields=21 / checks=21 / lanes=8 / blocked=32 / accepted=0 / runtime=0`,並把 raw namespace、repo slug、內部狀態碼與內部協作內容外洩列為拒收 / 隔離;Frontend public sensitive surface guard 已新增 `files=225 / patterns=12 / allowlisted=2 / violations=0 / runtime=0`,讓 public runtime config 成熟度 `64% -> 66%`、高價值配置平均 `69% -> 70%`;Backup / Restore / Escrow owner response acceptance 只讀帳本已更新為 `candidates=38 / write_capable=27 / fields=33 / owner_fields=23 / reviewer_checks=22 / lanes=9 / blocked=31 / accepted=0 / runtime=0`;SSH / Firewall / Network Access owner response acceptance 只讀帳本已新增 `candidates=16 / write_capable=6 / fields=13 / checks=15 / lanes=7 / blocked=22 / accepted=0 / runtime=0`;端口 / 防火牆變更證據驗收只讀帳本已新增 `candidates=14 / write_capable=6 / policy_or_exposure=5 / evidence_fields=16 / checks=16 / lanes=8 / blocked=24 / accepted=0 / runtime=0`;owner response / live evidence / runtime gate / action buttons 仍全部為 0 | | P0 agent-bounty 追加 | agent-bounty-protocol Owner Request Draft 已新增 `drafts=11 / control=4 / surface=7 / write_capable=8 / treasury=4 / mcp_a2a=5 / fields=22 / forbidden_inputs=25 / blocked=28 / sent=0 / runtime=0`;這是 repo / refs、deployment、data classification、MCP / A2A、cron / daemon、admin / treasury、webhook / traffic 的人工送件前草稿,不是 owner response、repo push、refs sync、workflow 修改、secret 收集、deploy、compose restart、DB migration、claim / submit、payout / withdrawal、cron / daemon、external send、host write 或 runtime gate | | P1 追加 | Docker / systemd / Host Service Owner Request Draft 已新增 `drafts=9 / write_capable=3 / fields=12 / blocked=14 / sent=0 / runtime=0`;Docker / systemd / Host Service Owner Response Acceptance 已更新為 `candidates=9 / write_capable=3 / live_evidence_required=8 / fields=34 / owner_fields=18 / reviewer_checks=21 / lanes=8 / blocked=27 / accepted=0 / runtime=0`;Docker / systemd / Host Service Change Evidence Acceptance 已新增 `candidates=9 / write_capable=3 / live_evidence_required=8 / evidence_fields=45 / required_fields=25 / reviewer_checks=26 / lanes=10 / blocked=39 / accepted=0 / runtime=0`;Docker / systemd / Host Service Post-incident Readback Plan 已新增 `candidates=9 / write_capable=3 / live_evidence_required=8 / readback_fields=36 / required_fields=28 / reviewer_checks=28 / lanes=10 / blocked=41 / accepted=0 / runtime=0`;AI provider / Model Routing Owner Response Acceptance 已新增 `candidates=8 / write_capable=5 / paid_provider=5 / data_egress=6 / fields=37 / owner_fields=24 / reviewer_checks=24 / lanes=10 / blocked=38 / accepted=0 / runtime=0`;SSH / Firewall / Network Access Owner Request Draft 已新增 `drafts=16 / write_capable=6 / fields=13 / blocked=16 / sent=0 / runtime=0`;Backup / Restore / Escrow Owner Request Draft 已新增 `drafts=38 / write_capable=27 / fields=14 / blocked=18 / sent=0 / runtime=0`;Backup / Restore / Escrow Owner Response Acceptance 已更新為 `candidates=38 / write_capable=27 / owner_fields=23 / reviewer_checks=22 / lanes=9 / blocked=31 / accepted=0 / runtime=0`;Monitoring / Alerting / Observability Owner Request Draft 已新增 `drafts=60 / write_capable=11 / fields=14 / blocked=24 / sent=0 / runtime=0`;Monitoring / Alerting / Observability Owner Response Acceptance 已更新為 `candidates=60 / write_capable=11 / live_evidence_required=60 / fields=38 / owner_fields=14 / reviewer_checks=23 / lanes=12 / blocked=34 / accepted=0 / runtime=0`,並補 incident context、receiver receipt、stale alert、silence / dedup、post-reload readback 與 false-green risk review;上述全部仍是人工送件前草稿、只讀 acceptance 帳本或事故後回讀計畫,不是 owner response、change evidence accepted、live evidence、provider switch、外部 provider call、付費呼叫、prompt send、reload、restart、backup、restore、Telegram send、alert smoke、host write 或 runtime gate | | P2 供應鏈追加 | Package / Docker 供應鏈 repo-only baseline 已新增 `package_json=6 / pyproject=4 / requirements=2 / dockerfiles=2 / compose=6 / gaps=5 / runtime=0`;Package / Docker 供應鏈 owner policy gate 已新增 `requests=6 / c0=2 / fields=8 / checks=12 / blocked=20 / sent=0 / accepted=0 / runtime=0`;缺口為 Python lockfile 缺席、requirements 未 pin、Docker base image 未全數 digest pinning、Docker `COPY --from` 外部 image 未 digest pinning、compose image 未 digest pinning,以及 CVE / license / SBOM window 未定;目前尚未列入 36 個正式 AwoooP 消費 contract,後續若要前台消費需同步 manifest / readiness / route / rollup / dry-run / posture projection / guard count;本輪不 install、不 upgrade、不跑 CVE、不 pull / build / push image、不改 tag、不登入 registry、不部署 | | 原則 | 低摩擦分階段;文件、schema、read-only evidence 優先;不做 runtime enforcement、不切 primary | | P0 主控板 | `docs/workplans/2026-06-04-iwooos-security-governance-p0.md` | +## 0.00aaaaaaaaaa 2026-06-15 K8s / ArgoCD post-incident readback plan + +本輪把 K8s / ArgoCD 從 GitOps 變更證據驗收再補一層事故後回讀計畫:`k8s_argocd_post_incident_readback_plan_v1` 固定 `candidates=4`、`c0=3`、`c1=1`、`write_capable=4`、`readback_fields=36`、`required_readback_fields=31`、`reviewer_checks=28`、`outcome_lanes=10`、`blocked_actions=41`,並讓 `k8s_production_gitops` 只讀治理成熟度 `64% -> 66%`,高價值配置平均成熟度維持 `71%`。新增要求包含 actor、ArgoCD app health、sync status、Degraded / Pending、image pull / scheduling、rollout before / after、event / metrics / alert、drift scanner、CronJob schedule、NetworkPolicy / RBAC / Secret metadata、public/admin route、AI provider / monitoring、backup / restore、operator notification、cross-project sync、postcheck、recurrence guard 與 no-false-green attestation。 + +同步邊界:IwoooS headline 維持 `64%`,active runtime gate 維持 `0`;readback received / accepted、ArgoCD health accepted、sync accepted、Pending / image pull accepted、drift accepted、route / AI / monitoring impact accepted、cross-project sync accepted、no-false-green accepted、ArgoCD API read、ArgoCD sync、kubectl、Helm、NetworkPolicy / NodePort / RBAC 變更、route smoke、production write、runtime gate 與 action buttons 全部仍為 `0 / false`。本段只更新文件、snapshot、guard、schema、投影契約與前端 marker,不連 ArgoCD、不跑 `kubectl`、不套用 manifest、不改 Secret、不改 NetworkPolicy / NodePort / RBAC、不碰 cluster live state。 + ## 0.00aaaaaaaa 2026-06-15 Docker / systemd / Host Service post-incident readback plan 本輪把 Docker / systemd / Host Service 從變更證據驗收再補一層事故後回讀計畫:`host_service_post_incident_readback_plan_v1` 固定 `candidates=9`、`write_capable=3`、`live_evidence_required=8`、`readback_fields=36`、`required_readback_fields=28`、`reviewer_checks=28`、`outcome_lanes=10`、`blocked_actions=41`,並讓 `docker_compose_systemd_host_config` 只讀治理成熟度 `62% -> 64%`、高價值配置平均成熟度 `70% -> 71%`。新增要求包含 actor、boot / recovery window、before / after、Docker daemon、compose、systemd、failed unit、port binding、public / admin route、AI provider、monitoring、operator notification、cross-project sync、restoration evidence、post-check、recurrence guard 與 no-false-green attestation。 diff --git a/docs/security/high-value-config-control-coverage.snapshot.json b/docs/security/high-value-config-control-coverage.snapshot.json index 14c60774c..292dbf217 100644 --- a/docs/security/high-value-config-control-coverage.snapshot.json +++ b/docs/security/high-value-config-control-coverage.snapshot.json @@ -91,9 +91,9 @@ "action_buttons_allowed": false, "category_id": "k8s_production_gitops", "control_tier": "C0", - "coverage_percent": 64, - "coverage_status": "change_evidence_acceptance_ready_needs_gitops_owner_evidence", - "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。", + "coverage_percent": 66, + "coverage_status": "post_incident_readback_plan_ready_needs_gitops_owner_evidence", + "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。", "evidence_refs": [ "docs/security/HIGH-VALUE-CONFIG-CHANGE-GATE.md", "docs/security/K8S-ARGOCD-MANIFEST-INVENTORY.md", @@ -102,11 +102,13 @@ "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" ], "label": "K8s / ArgoCD / production manifests", - "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。", + "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。", "owner_response_accepted": false, "owner_response_received": false, "owner_response_required": true, @@ -643,16 +645,9 @@ "websocket_route_change_authorized": false, "workflow_modification_authorized": false }, - "generated_at": "2026-06-15T20:32:00+08:00", - "git_commit": "c641d1b2", + "generated_at": "2026-06-15T20:46:00+08:00", + "git_commit": "18cf5263", "lowest_coverage_categories": [ - { - "category_id": "k8s_production_gitops", - "coverage_percent": 64, - "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。", - "label": "K8s / ArgoCD / production manifests", - "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。" - }, { "category_id": "backup_restore_credential", "coverage_percent": 64, @@ -673,6 +668,13 @@ "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。", "label": "SSH / sudoers / known_hosts / firewall / WireGuard / NodePort", "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 指標。" + }, + { + "category_id": "ai_provider_model_routing", + "coverage_percent": 64, + "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。", + "label": "AI provider / model routing / Ollama proxy / cost and privacy", + "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。" } ], "next_collection_order": [ diff --git a/docs/security/iwooos-posture-projection.snapshot.json b/docs/security/iwooos-posture-projection.snapshot.json index de329c706..f5f5858c8 100644 --- a/docs/security/iwooos-posture-projection.snapshot.json +++ b/docs/security/iwooos-posture-projection.snapshot.json @@ -8430,7 +8430,9 @@ "docs/security/ssh-network-post-incident-readback-plan.snapshot.json", "docs/security/SSH-NETWORK-POST-INCIDENT-READBACK-PLAN.md", "docs/security/host-service-post-incident-readback-plan.snapshot.json", - "docs/security/HOST-SERVICE-POST-INCIDENT-READBACK-PLAN.md" + "docs/security/HOST-SERVICE-POST-INCIDENT-READBACK-PLAN.md", + "docs/security/K8S-ARGOCD-POST-INCIDENT-READBACK-PLAN.md", + "docs/security/k8s-argocd-post-incident-readback-plan.snapshot.json" ], "status": "draft", "summary": { @@ -9127,7 +9129,62 @@ "host_service_post_incident_readback_plan_runtime_gate_count": 0, "host_service_post_incident_readback_plan_action_button_count": 0, "host_service_post_incident_readback_plan_coverage_percent_after_readback_plan": 64, - "docker_compose_systemd_host_config_coverage_percent": 64 + "docker_compose_systemd_host_config_coverage_percent": 64, + "k8s_argocd_post_incident_readback_plan_first_layer": true, + "k8s_argocd_post_incident_readback_plan_candidate_count": 4, + "k8s_argocd_post_incident_readback_plan_c0_candidate_count": 3, + "k8s_argocd_post_incident_readback_plan_c1_candidate_count": 1, + "k8s_argocd_post_incident_readback_plan_write_capable_candidate_count": 4, + "k8s_argocd_post_incident_readback_plan_degraded_or_pending_review_required_candidate_count": 4, + "k8s_argocd_post_incident_readback_plan_drift_or_schedule_review_required_candidate_count": 4, + "k8s_argocd_post_incident_readback_plan_route_ai_monitoring_impact_required_candidate_count": 4, + "k8s_argocd_post_incident_readback_plan_cross_project_sync_required_candidate_count": 4, + "k8s_argocd_post_incident_readback_plan_no_false_green_required_candidate_count": 4, + "k8s_argocd_post_incident_readback_plan_readback_field_count": 36, + "k8s_argocd_post_incident_readback_plan_required_readback_field_count": 31, + "k8s_argocd_post_incident_readback_plan_reviewer_check_count": 28, + "k8s_argocd_post_incident_readback_plan_outcome_lane_count": 10, + "k8s_argocd_post_incident_readback_plan_blocked_action_count": 41, + "k8s_argocd_post_incident_readback_plan_post_incident_readback_received_count": 0, + "k8s_argocd_post_incident_readback_plan_post_incident_readback_accepted_count": 0, + "k8s_argocd_post_incident_readback_plan_actor_attribution_accepted_count": 0, + "k8s_argocd_post_incident_readback_plan_argocd_app_health_accepted_count": 0, + "k8s_argocd_post_incident_readback_plan_argocd_sync_status_accepted_count": 0, + "k8s_argocd_post_incident_readback_plan_degraded_state_accepted_count": 0, + "k8s_argocd_post_incident_readback_plan_pending_workload_accepted_count": 0, + "k8s_argocd_post_incident_readback_plan_image_pull_or_scheduling_accepted_count": 0, + "k8s_argocd_post_incident_readback_plan_rollout_before_after_accepted_count": 0, + "k8s_argocd_post_incident_readback_plan_event_summary_accepted_count": 0, + "k8s_argocd_post_incident_readback_plan_metrics_alert_accepted_count": 0, + "k8s_argocd_post_incident_readback_plan_drift_scanner_accepted_count": 0, + "k8s_argocd_post_incident_readback_plan_cronjob_schedule_accepted_count": 0, + "k8s_argocd_post_incident_readback_plan_network_policy_service_impact_accepted_count": 0, + "k8s_argocd_post_incident_readback_plan_rbac_serviceaccount_impact_accepted_count": 0, + "k8s_argocd_post_incident_readback_plan_secret_metadata_parity_accepted_count": 0, + "k8s_argocd_post_incident_readback_plan_public_admin_route_impact_accepted_count": 0, + "k8s_argocd_post_incident_readback_plan_ai_provider_monitoring_impact_accepted_count": 0, + "k8s_argocd_post_incident_readback_plan_backup_restore_impact_accepted_count": 0, + "k8s_argocd_post_incident_readback_plan_operator_notification_accepted_count": 0, + "k8s_argocd_post_incident_readback_plan_cross_project_sync_accepted_count": 0, + "k8s_argocd_post_incident_readback_plan_recovery_or_still_degraded_accepted_count": 0, + "k8s_argocd_post_incident_readback_plan_postcheck_readback_accepted_count": 0, + "k8s_argocd_post_incident_readback_plan_recurrence_guard_accepted_count": 0, + "k8s_argocd_post_incident_readback_plan_no_false_green_accepted_count": 0, + "k8s_argocd_post_incident_readback_plan_argocd_api_read_authorized_count": 0, + "k8s_argocd_post_incident_readback_plan_argocd_sync_authorized_count": 0, + "k8s_argocd_post_incident_readback_plan_live_cluster_read_authorized_count": 0, + "k8s_argocd_post_incident_readback_plan_kubectl_action_authorized_count": 0, + "k8s_argocd_post_incident_readback_plan_helm_action_authorized_count": 0, + "k8s_argocd_post_incident_readback_plan_network_policy_change_authorized_count": 0, + "k8s_argocd_post_incident_readback_plan_nodeport_change_authorized_count": 0, + "k8s_argocd_post_incident_readback_plan_rbac_change_authorized_count": 0, + "k8s_argocd_post_incident_readback_plan_secret_value_collection_allowed_count": 0, + "k8s_argocd_post_incident_readback_plan_route_smoke_authorized_count": 0, + "k8s_argocd_post_incident_readback_plan_production_write_authorized_count": 0, + "k8s_argocd_post_incident_readback_plan_runtime_gate_count": 0, + "k8s_argocd_post_incident_readback_plan_action_button_count": 0, + "k8s_argocd_post_incident_readback_plan_coverage_percent_after_readback_plan": 66, + "k8s_production_gitops_coverage_percent": 66 }, "topology_atlas_lenses": [ { diff --git a/docs/security/k8s-argocd-post-incident-readback-plan.snapshot.json b/docs/security/k8s-argocd-post-incident-readback-plan.snapshot.json new file mode 100644 index 000000000..8dfcbebda --- /dev/null +++ b/docs/security/k8s-argocd-post-incident-readback-plan.snapshot.json @@ -0,0 +1,1352 @@ +{ + "blocked_actions": [ + "argocd_api_read", + "argocd_sync", + "argocd_rollback", + "live_cluster_read", + "kubectl_get_live", + "kubectl_apply", + "kubectl_patch", + "kubectl_delete", + "kubectl_rollout_restart", + "kubectl_scale", + "helm_upgrade", + "helm_rollback", + "kustomize_image_set", + "change_network_policy", + "change_nodeport", + "change_service_type", + "change_ingress_route", + "change_rbac", + "change_serviceaccount", + "change_configmap_runtime", + "change_secret_metadata", + "secret_value_collection", + "kubeconfig_collection", + "raw_manifest_storage", + "raw_event_dump_storage", + "raw_pod_log_storage", + "raw_secret_storage", + "velero_restore", + "restore_backup", + "prometheus_rule_apply", + "alertmanager_reload", + "route_smoke", + "production_write", + "accept_synced_as_healthy", + "accept_route_200_as_all_green", + "accept_pod_running_as_all_green", + "accept_cd_success_as_security_acceptance", + "skip_degraded_pending_review", + "mark_readback_accepted_without_reviewer_record", + "open_runtime_gate", + "add_action_button" + ], + "boundaries": { + "action_buttons_allowed": false, + "actor_attribution_accepted": false, + "ai_provider_monitoring_impact_accepted": false, + "argocd_api_read_authorized": false, + "argocd_app_health_accepted": false, + "argocd_sync_authorized": false, + "argocd_sync_status_accepted": false, + "backup_restore_impact_accepted": false, + "cronjob_schedule_accepted": false, + "cross_project_sync_accepted": false, + "degraded_state_accepted": false, + "drift_scanner_accepted": false, + "event_summary_accepted": false, + "helm_action_authorized": false, + "image_pull_or_scheduling_accepted": false, + "kubectl_action_authorized": false, + "live_cluster_read_authorized": false, + "metrics_alert_accepted": false, + "network_policy_change_authorized": false, + "network_policy_service_impact_accepted": false, + "no_false_green_accepted": false, + "nodeport_change_authorized": false, + "not_authorization": true, + "operator_notification_accepted": false, + "pending_workload_accepted": false, + "post_incident_readback_accepted": false, + "post_incident_readback_received": false, + "postcheck_readback_accepted": false, + "production_write_authorized": false, + "public_admin_route_impact_accepted": false, + "rbac_change_authorized": false, + "rbac_serviceaccount_impact_accepted": false, + "recovery_or_still_degraded_accepted": false, + "recurrence_guard_accepted": false, + "rollout_before_after_accepted": false, + "route_smoke_authorized": false, + "runtime_execution_authorized": false, + "secret_metadata_parity_accepted": false, + "secret_value_collection_allowed": false + }, + "generated_at": "2026-06-15T20:45:00+08:00", + "git_commit": "18cf5263", + "outcome_lanes": [ + { + "lane_id": "waiting_post_incident_readback", + "meaning": "尚未收到 K8s / ArgoCD 事故回讀包;所有 accepted / runtime count 維持 0。" + }, + { + "lane_id": "request_actor_or_revision_supplement", + "meaning": "缺 actor、deploy marker、ArgoCD revision 或 rollback revision 時要求補件。" + }, + { + "lane_id": "request_degraded_pending_supplement", + "meaning": "缺 Degraded / Pending / image pull / scheduling / rollout before-after 時要求補件。" + }, + { + "lane_id": "request_event_metric_supplement", + "meaning": "缺 event summary、metrics、alert、drift scanner 或 CronJob schedule 時要求補件。" + }, + { + "lane_id": "request_route_dependency_supplement", + "meaning": "缺 public/admin route、AI provider、monitoring、backup / restore、network / RBAC 影響時要求補件。" + }, + { + "lane_id": "quarantine_raw_payload", + "meaning": "收到 Secret value、kubeconfig、raw manifest、raw log、raw event 或未脫敏截圖時只能隔離。" + }, + { + "lane_id": "reject_runtime_claim", + "meaning": "把 CD success、ArgoCD Synced、route 200、Pod Running 或 UI 可見當驗收時拒收。" + }, + { + "lane_id": "ready_for_k8s_post_incident_review", + "meaning": "metadata 合格後,只能進 reviewer review。" + }, + { + "lane_id": "recurrence_guard_backfill_required", + "meaning": "需補防再發 guard、owner review、change freeze 或 automation block。" + }, + { + "lane_id": "waiting_runtime_gate", + "meaning": "即使 readback accepted,runtime gate 仍需獨立人工批准。" + } + ], + "readback_candidates": [ + { + "action_buttons_allowed": false, + "actor_attribution_accepted": false, + "actor_attribution_ref": null, + "ai_provider_monitoring_impact_accepted": false, + "ai_provider_monitoring_impact_ref": null, + "argocd_api_read_authorized": false, + "argocd_app_health_accepted": false, + "argocd_app_health_ref": null, + "argocd_sync_authorized": false, + "argocd_sync_status_accepted": false, + "argocd_sync_status_ref": null, + "backup_restore_impact_accepted": false, + "backup_restore_impact_ref": null, + "blocked_actions": [ + "argocd_api_read", + "argocd_sync", + "argocd_rollback", + "live_cluster_read", + "kubectl_get_live", + "kubectl_apply", + "kubectl_patch", + "kubectl_delete", + "kubectl_rollout_restart", + "kubectl_scale", + "helm_upgrade", + "helm_rollback", + "kustomize_image_set", + "change_network_policy", + "change_nodeport", + "change_service_type", + "change_ingress_route", + "change_rbac", + "change_serviceaccount", + "change_configmap_runtime", + "change_secret_metadata", + "secret_value_collection", + "kubeconfig_collection", + "raw_manifest_storage", + "raw_event_dump_storage", + "raw_pod_log_storage", + "raw_secret_storage", + "velero_restore", + "restore_backup", + "prometheus_rule_apply", + "alertmanager_reload", + "route_smoke", + "production_write", + "accept_synced_as_healthy", + "accept_route_200_as_all_green", + "accept_pod_running_as_all_green", + "accept_cd_success_as_security_acceptance", + "skip_degraded_pending_review", + "mark_readback_accepted_without_reviewer_record", + "open_runtime_gate", + "add_action_button" + ], + "control_tier": "C0", + "cronjob_schedule_accepted": false, + "cronjob_schedule_ref": null, + "cross_project_sync_accepted": false, + "cross_project_sync_ref": null, + "degraded_state_accepted": false, + "degraded_state_ref": null, + "drift_scanner_accepted": false, + "drift_scanner_ref": null, + "event_summary_accepted": false, + "event_summary_ref": null, + "followup_owner": "pending_post_incident_readback", + "gate_tags": [ + "availability_and_scaling", + "backup_restore", + "network_policy", + "rbac", + "secret_metadata", + "supporting_source", + "workload_or_schedule" + ], + "group_id": "awoooi_prod", + "helm_action_authorized": false, + "image_pull_or_scheduling_accepted": false, + "image_pull_or_scheduling_ref": null, + "k8s_incident_or_change_ref": null, + "kubectl_action_authorized": false, + "live_cluster_read_authorized": false, + "maintenance_window": "pending_post_incident_readback", + "metrics_alert_accepted": false, + "metrics_alert_ref": null, + "network_policy_change_authorized": false, + "network_policy_service_impact_accepted": false, + "network_policy_service_impact_ref": null, + "no_false_green_accepted": false, + "nodeport_change_authorized": false, + "not_approval": true, + "operator_notification_accepted": false, + "operator_notification_ref": null, + "outcome_lanes": [ + "waiting_post_incident_readback", + "request_actor_or_revision_supplement", + "request_degraded_pending_supplement", + "request_event_metric_supplement", + "request_route_dependency_supplement", + "quarantine_raw_payload", + "reject_runtime_claim", + "ready_for_k8s_post_incident_review", + "recurrence_guard_backfill_required", + "waiting_runtime_gate" + ], + "pending_workload_accepted": false, + "pending_workload_ref": null, + "post_incident_readback_accepted": false, + "post_incident_readback_candidate_id": "k8s_argocd_post_incident_readback:awoooi_prod", + "post_incident_readback_received": false, + "postcheck_readback_accepted": false, + "postcheck_readback_ref": null, + "production_write_authorized": false, + "public_admin_route_impact_accepted": false, + "public_admin_route_impact_ref": null, + "rbac_change_authorized": false, + "rbac_serviceaccount_impact_accepted": false, + "rbac_serviceaccount_impact_ref": null, + "readback_fields": [ + "post_incident_readback_candidate_id", + "source_change_evidence_candidate_id", + "group_id", + "root", + "control_tier", + "gate_tags", + "k8s_incident_or_change_ref", + "actor_attribution_ref", + "argocd_app_health_ref", + "argocd_sync_status_ref", + "degraded_state_ref", + "pending_workload_ref", + "image_pull_or_scheduling_ref", + "rollout_before_ref", + "rollout_after_ref", + "event_summary_ref", + "metrics_alert_ref", + "drift_scanner_ref", + "cronjob_schedule_ref", + "backup_restore_impact_ref", + "secret_metadata_parity_ref", + "network_policy_service_impact_ref", + "rbac_serviceaccount_impact_ref", + "public_admin_route_impact_ref", + "ai_provider_monitoring_impact_ref", + "operator_notification_ref", + "cross_project_sync_ref", + "recovery_or_still_degraded_ref", + "postcheck_readback_ref", + "recurrence_guard_ref", + "maintenance_window", + "rollback_revision", + "rollback_owner", + "reviewer_outcome", + "followup_owner", + "not_approval" + ], + "recovery_or_still_degraded_accepted": false, + "recovery_or_still_degraded_ref": null, + "recurrence_guard_accepted": false, + "recurrence_guard_ref": null, + "required_readback_fields": [ + "k8s_incident_or_change_ref", + "actor_attribution_ref", + "argocd_app_health_ref", + "argocd_sync_status_ref", + "degraded_state_ref", + "pending_workload_ref", + "image_pull_or_scheduling_ref", + "rollout_before_ref", + "rollout_after_ref", + "event_summary_ref", + "metrics_alert_ref", + "drift_scanner_ref", + "cronjob_schedule_ref", + "secret_metadata_parity_ref", + "network_policy_service_impact_ref", + "rbac_serviceaccount_impact_ref", + "public_admin_route_impact_ref", + "ai_provider_monitoring_impact_ref", + "operator_notification_ref", + "cross_project_sync_ref", + "recovery_or_still_degraded_ref", + "postcheck_readback_ref", + "recurrence_guard_ref", + "maintenance_window", + "rollback_revision", + "rollback_owner", + "followup_owner", + "redacted_evidence_refs", + "no_secret_value_attestation", + "no_raw_manifest_or_kubeconfig_attestation", + "no_false_green_attestation" + ], + "reviewer_checks": [ + "source_change_evidence_current", + "incident_or_change_ref_present", + "actor_attribution_present", + "argocd_sync_and_health_present", + "degraded_state_review_present", + "pending_workload_review_present", + "rollout_before_after_present", + "event_summary_redacted", + "metrics_alert_ref_present", + "drift_scanner_ref_present", + "cronjob_schedule_review_present", + "backup_restore_impact_called_out", + "secret_metadata_only", + "network_policy_service_impact_present", + "rbac_serviceaccount_impact_present", + "public_admin_route_impact_present", + "ai_provider_monitoring_impact_present", + "operator_notification_present", + "cross_project_sync_present", + "recovery_or_still_degraded_present", + "postcheck_independent", + "recurrence_guard_present", + "maintenance_window_present", + "rollback_revision_present", + "no_false_green", + "raw_payload_absent", + "runtime_stays_zero", + "counts_transition_safe" + ], + "reviewer_outcome": "waiting_post_incident_readback", + "rollback_owner": "pending_post_incident_readback", + "rollback_revision": "pending_post_incident_readback", + "rollout_after_ref": null, + "rollout_before_after_accepted": false, + "rollout_before_ref": null, + "root": "k8s/awoooi-prod", + "route_smoke_authorized": false, + "runtime_gate": false, + "secret_metadata_parity_accepted": false, + "secret_metadata_parity_ref": null, + "secret_value_collection_allowed": false, + "source_change_evidence_candidate_id": "k8s_argocd_change_evidence:awoooi_prod", + "status": "waiting_post_incident_readback", + "write_capable": true + }, + { + "action_buttons_allowed": false, + "actor_attribution_accepted": false, + "actor_attribution_ref": null, + "ai_provider_monitoring_impact_accepted": false, + "ai_provider_monitoring_impact_ref": null, + "argocd_api_read_authorized": false, + "argocd_app_health_accepted": false, + "argocd_app_health_ref": null, + "argocd_sync_authorized": false, + "argocd_sync_status_accepted": false, + "argocd_sync_status_ref": null, + "backup_restore_impact_accepted": false, + "backup_restore_impact_ref": null, + "blocked_actions": [ + "argocd_api_read", + "argocd_sync", + "argocd_rollback", + "live_cluster_read", + "kubectl_get_live", + "kubectl_apply", + "kubectl_patch", + "kubectl_delete", + "kubectl_rollout_restart", + "kubectl_scale", + "helm_upgrade", + "helm_rollback", + "kustomize_image_set", + "change_network_policy", + "change_nodeport", + "change_service_type", + "change_ingress_route", + "change_rbac", + "change_serviceaccount", + "change_configmap_runtime", + "change_secret_metadata", + "secret_value_collection", + "kubeconfig_collection", + "raw_manifest_storage", + "raw_event_dump_storage", + "raw_pod_log_storage", + "raw_secret_storage", + "velero_restore", + "restore_backup", + "prometheus_rule_apply", + "alertmanager_reload", + "route_smoke", + "production_write", + "accept_synced_as_healthy", + "accept_route_200_as_all_green", + "accept_pod_running_as_all_green", + "accept_cd_success_as_security_acceptance", + "skip_degraded_pending_review", + "mark_readback_accepted_without_reviewer_record", + "open_runtime_gate", + "add_action_button" + ], + "control_tier": "C0", + "cronjob_schedule_accepted": false, + "cronjob_schedule_ref": null, + "cross_project_sync_accepted": false, + "cross_project_sync_ref": null, + "degraded_state_accepted": false, + "degraded_state_ref": null, + "drift_scanner_accepted": false, + "drift_scanner_ref": null, + "event_summary_accepted": false, + "event_summary_ref": null, + "followup_owner": "pending_post_incident_readback", + "gate_tags": [ + "argocd_application", + "network_policy", + "supporting_source" + ], + "group_id": "argocd", + "helm_action_authorized": false, + "image_pull_or_scheduling_accepted": false, + "image_pull_or_scheduling_ref": null, + "k8s_incident_or_change_ref": null, + "kubectl_action_authorized": false, + "live_cluster_read_authorized": false, + "maintenance_window": "pending_post_incident_readback", + "metrics_alert_accepted": false, + "metrics_alert_ref": null, + "network_policy_change_authorized": false, + "network_policy_service_impact_accepted": false, + "network_policy_service_impact_ref": null, + "no_false_green_accepted": false, + "nodeport_change_authorized": false, + "not_approval": true, + "operator_notification_accepted": false, + "operator_notification_ref": null, + "outcome_lanes": [ + "waiting_post_incident_readback", + "request_actor_or_revision_supplement", + "request_degraded_pending_supplement", + "request_event_metric_supplement", + "request_route_dependency_supplement", + "quarantine_raw_payload", + "reject_runtime_claim", + "ready_for_k8s_post_incident_review", + "recurrence_guard_backfill_required", + "waiting_runtime_gate" + ], + "pending_workload_accepted": false, + "pending_workload_ref": null, + "post_incident_readback_accepted": false, + "post_incident_readback_candidate_id": "k8s_argocd_post_incident_readback:argocd", + "post_incident_readback_received": false, + "postcheck_readback_accepted": false, + "postcheck_readback_ref": null, + "production_write_authorized": false, + "public_admin_route_impact_accepted": false, + "public_admin_route_impact_ref": null, + "rbac_change_authorized": false, + "rbac_serviceaccount_impact_accepted": false, + "rbac_serviceaccount_impact_ref": null, + "readback_fields": [ + "post_incident_readback_candidate_id", + "source_change_evidence_candidate_id", + "group_id", + "root", + "control_tier", + "gate_tags", + "k8s_incident_or_change_ref", + "actor_attribution_ref", + "argocd_app_health_ref", + "argocd_sync_status_ref", + "degraded_state_ref", + "pending_workload_ref", + "image_pull_or_scheduling_ref", + "rollout_before_ref", + "rollout_after_ref", + "event_summary_ref", + "metrics_alert_ref", + "drift_scanner_ref", + "cronjob_schedule_ref", + "backup_restore_impact_ref", + "secret_metadata_parity_ref", + "network_policy_service_impact_ref", + "rbac_serviceaccount_impact_ref", + "public_admin_route_impact_ref", + "ai_provider_monitoring_impact_ref", + "operator_notification_ref", + "cross_project_sync_ref", + "recovery_or_still_degraded_ref", + "postcheck_readback_ref", + "recurrence_guard_ref", + "maintenance_window", + "rollback_revision", + "rollback_owner", + "reviewer_outcome", + "followup_owner", + "not_approval" + ], + "recovery_or_still_degraded_accepted": false, + "recovery_or_still_degraded_ref": null, + "recurrence_guard_accepted": false, + "recurrence_guard_ref": null, + "required_readback_fields": [ + "k8s_incident_or_change_ref", + "actor_attribution_ref", + "argocd_app_health_ref", + "argocd_sync_status_ref", + "degraded_state_ref", + "pending_workload_ref", + "image_pull_or_scheduling_ref", + "rollout_before_ref", + "rollout_after_ref", + "event_summary_ref", + "metrics_alert_ref", + "drift_scanner_ref", + "cronjob_schedule_ref", + "secret_metadata_parity_ref", + "network_policy_service_impact_ref", + "rbac_serviceaccount_impact_ref", + "public_admin_route_impact_ref", + "ai_provider_monitoring_impact_ref", + "operator_notification_ref", + "cross_project_sync_ref", + "recovery_or_still_degraded_ref", + "postcheck_readback_ref", + "recurrence_guard_ref", + "maintenance_window", + "rollback_revision", + "rollback_owner", + "followup_owner", + "redacted_evidence_refs", + "no_secret_value_attestation", + "no_raw_manifest_or_kubeconfig_attestation", + "no_false_green_attestation" + ], + "reviewer_checks": [ + "source_change_evidence_current", + "incident_or_change_ref_present", + "actor_attribution_present", + "argocd_sync_and_health_present", + "degraded_state_review_present", + "pending_workload_review_present", + "rollout_before_after_present", + "event_summary_redacted", + "metrics_alert_ref_present", + "drift_scanner_ref_present", + "cronjob_schedule_review_present", + "backup_restore_impact_called_out", + "secret_metadata_only", + "network_policy_service_impact_present", + "rbac_serviceaccount_impact_present", + "public_admin_route_impact_present", + "ai_provider_monitoring_impact_present", + "operator_notification_present", + "cross_project_sync_present", + "recovery_or_still_degraded_present", + "postcheck_independent", + "recurrence_guard_present", + "maintenance_window_present", + "rollback_revision_present", + "no_false_green", + "raw_payload_absent", + "runtime_stays_zero", + "counts_transition_safe" + ], + "reviewer_outcome": "waiting_post_incident_readback", + "rollback_owner": "pending_post_incident_readback", + "rollback_revision": "pending_post_incident_readback", + "rollout_after_ref": null, + "rollout_before_after_accepted": false, + "rollout_before_ref": null, + "root": "k8s/argocd", + "route_smoke_authorized": false, + "runtime_gate": false, + "secret_metadata_parity_accepted": false, + "secret_metadata_parity_ref": null, + "secret_value_collection_allowed": false, + "source_change_evidence_candidate_id": "k8s_argocd_change_evidence:argocd", + "status": "waiting_post_incident_readback", + "write_capable": true + }, + { + "action_buttons_allowed": false, + "actor_attribution_accepted": false, + "actor_attribution_ref": null, + "ai_provider_monitoring_impact_accepted": false, + "ai_provider_monitoring_impact_ref": null, + "argocd_api_read_authorized": false, + "argocd_app_health_accepted": false, + "argocd_app_health_ref": null, + "argocd_sync_authorized": false, + "argocd_sync_status_accepted": false, + "argocd_sync_status_ref": null, + "backup_restore_impact_accepted": false, + "backup_restore_impact_ref": null, + "blocked_actions": [ + "argocd_api_read", + "argocd_sync", + "argocd_rollback", + "live_cluster_read", + "kubectl_get_live", + "kubectl_apply", + "kubectl_patch", + "kubectl_delete", + "kubectl_rollout_restart", + "kubectl_scale", + "helm_upgrade", + "helm_rollback", + "kustomize_image_set", + "change_network_policy", + "change_nodeport", + "change_service_type", + "change_ingress_route", + "change_rbac", + "change_serviceaccount", + "change_configmap_runtime", + "change_secret_metadata", + "secret_value_collection", + "kubeconfig_collection", + "raw_manifest_storage", + "raw_event_dump_storage", + "raw_pod_log_storage", + "raw_secret_storage", + "velero_restore", + "restore_backup", + "prometheus_rule_apply", + "alertmanager_reload", + "route_smoke", + "production_write", + "accept_synced_as_healthy", + "accept_route_200_as_all_green", + "accept_pod_running_as_all_green", + "accept_cd_success_as_security_acceptance", + "skip_degraded_pending_review", + "mark_readback_accepted_without_reviewer_record", + "open_runtime_gate", + "add_action_button" + ], + "control_tier": "C0", + "cronjob_schedule_accepted": false, + "cronjob_schedule_ref": null, + "cross_project_sync_accepted": false, + "cross_project_sync_ref": null, + "degraded_state_accepted": false, + "degraded_state_ref": null, + "drift_scanner_accepted": false, + "drift_scanner_ref": null, + "event_summary_accepted": false, + "event_summary_ref": null, + "followup_owner": "pending_post_incident_readback", + "gate_tags": [ + "backup_restore", + "rbac", + "secret_metadata", + "workload_or_schedule" + ], + "group_id": "velero", + "helm_action_authorized": false, + "image_pull_or_scheduling_accepted": false, + "image_pull_or_scheduling_ref": null, + "k8s_incident_or_change_ref": null, + "kubectl_action_authorized": false, + "live_cluster_read_authorized": false, + "maintenance_window": "pending_post_incident_readback", + "metrics_alert_accepted": false, + "metrics_alert_ref": null, + "network_policy_change_authorized": false, + "network_policy_service_impact_accepted": false, + "network_policy_service_impact_ref": null, + "no_false_green_accepted": false, + "nodeport_change_authorized": false, + "not_approval": true, + "operator_notification_accepted": false, + "operator_notification_ref": null, + "outcome_lanes": [ + "waiting_post_incident_readback", + "request_actor_or_revision_supplement", + "request_degraded_pending_supplement", + "request_event_metric_supplement", + "request_route_dependency_supplement", + "quarantine_raw_payload", + "reject_runtime_claim", + "ready_for_k8s_post_incident_review", + "recurrence_guard_backfill_required", + "waiting_runtime_gate" + ], + "pending_workload_accepted": false, + "pending_workload_ref": null, + "post_incident_readback_accepted": false, + "post_incident_readback_candidate_id": "k8s_argocd_post_incident_readback:velero", + "post_incident_readback_received": false, + "postcheck_readback_accepted": false, + "postcheck_readback_ref": null, + "production_write_authorized": false, + "public_admin_route_impact_accepted": false, + "public_admin_route_impact_ref": null, + "rbac_change_authorized": false, + "rbac_serviceaccount_impact_accepted": false, + "rbac_serviceaccount_impact_ref": null, + "readback_fields": [ + "post_incident_readback_candidate_id", + "source_change_evidence_candidate_id", + "group_id", + "root", + "control_tier", + "gate_tags", + "k8s_incident_or_change_ref", + "actor_attribution_ref", + "argocd_app_health_ref", + "argocd_sync_status_ref", + "degraded_state_ref", + "pending_workload_ref", + "image_pull_or_scheduling_ref", + "rollout_before_ref", + "rollout_after_ref", + "event_summary_ref", + "metrics_alert_ref", + "drift_scanner_ref", + "cronjob_schedule_ref", + "backup_restore_impact_ref", + "secret_metadata_parity_ref", + "network_policy_service_impact_ref", + "rbac_serviceaccount_impact_ref", + "public_admin_route_impact_ref", + "ai_provider_monitoring_impact_ref", + "operator_notification_ref", + "cross_project_sync_ref", + "recovery_or_still_degraded_ref", + "postcheck_readback_ref", + "recurrence_guard_ref", + "maintenance_window", + "rollback_revision", + "rollback_owner", + "reviewer_outcome", + "followup_owner", + "not_approval" + ], + "recovery_or_still_degraded_accepted": false, + "recovery_or_still_degraded_ref": null, + "recurrence_guard_accepted": false, + "recurrence_guard_ref": null, + "required_readback_fields": [ + "k8s_incident_or_change_ref", + "actor_attribution_ref", + "argocd_app_health_ref", + "argocd_sync_status_ref", + "degraded_state_ref", + "pending_workload_ref", + "image_pull_or_scheduling_ref", + "rollout_before_ref", + "rollout_after_ref", + "event_summary_ref", + "metrics_alert_ref", + "drift_scanner_ref", + "cronjob_schedule_ref", + "secret_metadata_parity_ref", + "network_policy_service_impact_ref", + "rbac_serviceaccount_impact_ref", + "public_admin_route_impact_ref", + "ai_provider_monitoring_impact_ref", + "operator_notification_ref", + "cross_project_sync_ref", + "recovery_or_still_degraded_ref", + "postcheck_readback_ref", + "recurrence_guard_ref", + "maintenance_window", + "rollback_revision", + "rollback_owner", + "followup_owner", + "redacted_evidence_refs", + "no_secret_value_attestation", + "no_raw_manifest_or_kubeconfig_attestation", + "no_false_green_attestation" + ], + "reviewer_checks": [ + "source_change_evidence_current", + "incident_or_change_ref_present", + "actor_attribution_present", + "argocd_sync_and_health_present", + "degraded_state_review_present", + "pending_workload_review_present", + "rollout_before_after_present", + "event_summary_redacted", + "metrics_alert_ref_present", + "drift_scanner_ref_present", + "cronjob_schedule_review_present", + "backup_restore_impact_called_out", + "secret_metadata_only", + "network_policy_service_impact_present", + "rbac_serviceaccount_impact_present", + "public_admin_route_impact_present", + "ai_provider_monitoring_impact_present", + "operator_notification_present", + "cross_project_sync_present", + "recovery_or_still_degraded_present", + "postcheck_independent", + "recurrence_guard_present", + "maintenance_window_present", + "rollback_revision_present", + "no_false_green", + "raw_payload_absent", + "runtime_stays_zero", + "counts_transition_safe" + ], + "reviewer_outcome": "waiting_post_incident_readback", + "rollback_owner": "pending_post_incident_readback", + "rollback_revision": "pending_post_incident_readback", + "rollout_after_ref": null, + "rollout_before_after_accepted": false, + "rollout_before_ref": null, + "root": "k8s/velero", + "route_smoke_authorized": false, + "runtime_gate": false, + "secret_metadata_parity_accepted": false, + "secret_metadata_parity_ref": null, + "secret_value_collection_allowed": false, + "source_change_evidence_candidate_id": "k8s_argocd_change_evidence:velero", + "status": "waiting_post_incident_readback", + "write_capable": true + }, + { + "action_buttons_allowed": false, + "actor_attribution_accepted": false, + "actor_attribution_ref": null, + "ai_provider_monitoring_impact_accepted": false, + "ai_provider_monitoring_impact_ref": null, + "argocd_api_read_authorized": false, + "argocd_app_health_accepted": false, + "argocd_app_health_ref": null, + "argocd_sync_authorized": false, + "argocd_sync_status_accepted": false, + "argocd_sync_status_ref": null, + "backup_restore_impact_accepted": false, + "backup_restore_impact_ref": null, + "blocked_actions": [ + "argocd_api_read", + "argocd_sync", + "argocd_rollback", + "live_cluster_read", + "kubectl_get_live", + "kubectl_apply", + "kubectl_patch", + "kubectl_delete", + "kubectl_rollout_restart", + "kubectl_scale", + "helm_upgrade", + "helm_rollback", + "kustomize_image_set", + "change_network_policy", + "change_nodeport", + "change_service_type", + "change_ingress_route", + "change_rbac", + "change_serviceaccount", + "change_configmap_runtime", + "change_secret_metadata", + "secret_value_collection", + "kubeconfig_collection", + "raw_manifest_storage", + "raw_event_dump_storage", + "raw_pod_log_storage", + "raw_secret_storage", + "velero_restore", + "restore_backup", + "prometheus_rule_apply", + "alertmanager_reload", + "route_smoke", + "production_write", + "accept_synced_as_healthy", + "accept_route_200_as_all_green", + "accept_pod_running_as_all_green", + "accept_cd_success_as_security_acceptance", + "skip_degraded_pending_review", + "mark_readback_accepted_without_reviewer_record", + "open_runtime_gate", + "add_action_button" + ], + "control_tier": "C1", + "cronjob_schedule_accepted": false, + "cronjob_schedule_ref": null, + "cross_project_sync_accepted": false, + "cross_project_sync_ref": null, + "degraded_state_accepted": false, + "degraded_state_ref": null, + "drift_scanner_accepted": false, + "drift_scanner_ref": null, + "event_summary_accepted": false, + "event_summary_ref": null, + "followup_owner": "pending_post_incident_readback", + "gate_tags": [ + "apply_capable_script", + "monitoring_alerting", + "supporting_source" + ], + "group_id": "monitoring", + "helm_action_authorized": false, + "image_pull_or_scheduling_accepted": false, + "image_pull_or_scheduling_ref": null, + "k8s_incident_or_change_ref": null, + "kubectl_action_authorized": false, + "live_cluster_read_authorized": false, + "maintenance_window": "pending_post_incident_readback", + "metrics_alert_accepted": false, + "metrics_alert_ref": null, + "network_policy_change_authorized": false, + "network_policy_service_impact_accepted": false, + "network_policy_service_impact_ref": null, + "no_false_green_accepted": false, + "nodeport_change_authorized": false, + "not_approval": true, + "operator_notification_accepted": false, + "operator_notification_ref": null, + "outcome_lanes": [ + "waiting_post_incident_readback", + "request_actor_or_revision_supplement", + "request_degraded_pending_supplement", + "request_event_metric_supplement", + "request_route_dependency_supplement", + "quarantine_raw_payload", + "reject_runtime_claim", + "ready_for_k8s_post_incident_review", + "recurrence_guard_backfill_required", + "waiting_runtime_gate" + ], + "pending_workload_accepted": false, + "pending_workload_ref": null, + "post_incident_readback_accepted": false, + "post_incident_readback_candidate_id": "k8s_argocd_post_incident_readback:monitoring", + "post_incident_readback_received": false, + "postcheck_readback_accepted": false, + "postcheck_readback_ref": null, + "production_write_authorized": false, + "public_admin_route_impact_accepted": false, + "public_admin_route_impact_ref": null, + "rbac_change_authorized": false, + "rbac_serviceaccount_impact_accepted": false, + "rbac_serviceaccount_impact_ref": null, + "readback_fields": [ + "post_incident_readback_candidate_id", + "source_change_evidence_candidate_id", + "group_id", + "root", + "control_tier", + "gate_tags", + "k8s_incident_or_change_ref", + "actor_attribution_ref", + "argocd_app_health_ref", + "argocd_sync_status_ref", + "degraded_state_ref", + "pending_workload_ref", + "image_pull_or_scheduling_ref", + "rollout_before_ref", + "rollout_after_ref", + "event_summary_ref", + "metrics_alert_ref", + "drift_scanner_ref", + "cronjob_schedule_ref", + "backup_restore_impact_ref", + "secret_metadata_parity_ref", + "network_policy_service_impact_ref", + "rbac_serviceaccount_impact_ref", + "public_admin_route_impact_ref", + "ai_provider_monitoring_impact_ref", + "operator_notification_ref", + "cross_project_sync_ref", + "recovery_or_still_degraded_ref", + "postcheck_readback_ref", + "recurrence_guard_ref", + "maintenance_window", + "rollback_revision", + "rollback_owner", + "reviewer_outcome", + "followup_owner", + "not_approval" + ], + "recovery_or_still_degraded_accepted": false, + "recovery_or_still_degraded_ref": null, + "recurrence_guard_accepted": false, + "recurrence_guard_ref": null, + "required_readback_fields": [ + "k8s_incident_or_change_ref", + "actor_attribution_ref", + "argocd_app_health_ref", + "argocd_sync_status_ref", + "degraded_state_ref", + "pending_workload_ref", + "image_pull_or_scheduling_ref", + "rollout_before_ref", + "rollout_after_ref", + "event_summary_ref", + "metrics_alert_ref", + "drift_scanner_ref", + "cronjob_schedule_ref", + "secret_metadata_parity_ref", + "network_policy_service_impact_ref", + "rbac_serviceaccount_impact_ref", + "public_admin_route_impact_ref", + "ai_provider_monitoring_impact_ref", + "operator_notification_ref", + "cross_project_sync_ref", + "recovery_or_still_degraded_ref", + "postcheck_readback_ref", + "recurrence_guard_ref", + "maintenance_window", + "rollback_revision", + "rollback_owner", + "followup_owner", + "redacted_evidence_refs", + "no_secret_value_attestation", + "no_raw_manifest_or_kubeconfig_attestation", + "no_false_green_attestation" + ], + "reviewer_checks": [ + "source_change_evidence_current", + "incident_or_change_ref_present", + "actor_attribution_present", + "argocd_sync_and_health_present", + "degraded_state_review_present", + "pending_workload_review_present", + "rollout_before_after_present", + "event_summary_redacted", + "metrics_alert_ref_present", + "drift_scanner_ref_present", + "cronjob_schedule_review_present", + "backup_restore_impact_called_out", + "secret_metadata_only", + "network_policy_service_impact_present", + "rbac_serviceaccount_impact_present", + "public_admin_route_impact_present", + "ai_provider_monitoring_impact_present", + "operator_notification_present", + "cross_project_sync_present", + "recovery_or_still_degraded_present", + "postcheck_independent", + "recurrence_guard_present", + "maintenance_window_present", + "rollback_revision_present", + "no_false_green", + "raw_payload_absent", + "runtime_stays_zero", + "counts_transition_safe" + ], + "reviewer_outcome": "waiting_post_incident_readback", + "rollback_owner": "pending_post_incident_readback", + "rollback_revision": "pending_post_incident_readback", + "rollout_after_ref": null, + "rollout_before_after_accepted": false, + "rollout_before_ref": null, + "root": "k8s/monitoring", + "route_smoke_authorized": false, + "runtime_gate": false, + "secret_metadata_parity_accepted": false, + "secret_metadata_parity_ref": null, + "secret_value_collection_allowed": false, + "source_change_evidence_candidate_id": "k8s_argocd_change_evidence:monitoring", + "status": "waiting_post_incident_readback", + "write_capable": true + } + ], + "readback_fields": [ + "post_incident_readback_candidate_id", + "source_change_evidence_candidate_id", + "group_id", + "root", + "control_tier", + "gate_tags", + "k8s_incident_or_change_ref", + "actor_attribution_ref", + "argocd_app_health_ref", + "argocd_sync_status_ref", + "degraded_state_ref", + "pending_workload_ref", + "image_pull_or_scheduling_ref", + "rollout_before_ref", + "rollout_after_ref", + "event_summary_ref", + "metrics_alert_ref", + "drift_scanner_ref", + "cronjob_schedule_ref", + "backup_restore_impact_ref", + "secret_metadata_parity_ref", + "network_policy_service_impact_ref", + "rbac_serviceaccount_impact_ref", + "public_admin_route_impact_ref", + "ai_provider_monitoring_impact_ref", + "operator_notification_ref", + "cross_project_sync_ref", + "recovery_or_still_degraded_ref", + "postcheck_readback_ref", + "recurrence_guard_ref", + "maintenance_window", + "rollback_revision", + "rollback_owner", + "reviewer_outcome", + "followup_owner", + "not_approval" + ], + "required_readback_fields": [ + "k8s_incident_or_change_ref", + "actor_attribution_ref", + "argocd_app_health_ref", + "argocd_sync_status_ref", + "degraded_state_ref", + "pending_workload_ref", + "image_pull_or_scheduling_ref", + "rollout_before_ref", + "rollout_after_ref", + "event_summary_ref", + "metrics_alert_ref", + "drift_scanner_ref", + "cronjob_schedule_ref", + "secret_metadata_parity_ref", + "network_policy_service_impact_ref", + "rbac_serviceaccount_impact_ref", + "public_admin_route_impact_ref", + "ai_provider_monitoring_impact_ref", + "operator_notification_ref", + "cross_project_sync_ref", + "recovery_or_still_degraded_ref", + "postcheck_readback_ref", + "recurrence_guard_ref", + "maintenance_window", + "rollback_revision", + "rollback_owner", + "followup_owner", + "redacted_evidence_refs", + "no_secret_value_attestation", + "no_raw_manifest_or_kubeconfig_attestation", + "no_false_green_attestation" + ], + "reviewer_checks": [ + { + "check_id": "source_change_evidence_current", + "instruction": "來源 GitOps change evidence snapshot 必須是目前版本。" + }, + { + "check_id": "incident_or_change_ref_present", + "instruction": "必須有 incident / change / deploy marker ref,不能只寫服務已恢復。" + }, + { + "check_id": "actor_attribution_present", + "instruction": "必須標示 actor role / team,不接受匿名 ArgoCD sync、kubectl、Helm、rollout 或 image 變更。" + }, + { + "check_id": "argocd_sync_and_health_present", + "instruction": "ArgoCD sync status、health status 與 revision 必須有脫敏 ref。" + }, + { + "check_id": "degraded_state_review_present", + "instruction": "Synced / Degraded、OutOfSync、Progressing、Suspended 或 Unknown 狀態都需說明。" + }, + { + "check_id": "pending_workload_review_present", + "instruction": "Pending Pod / Job / CronJob / Deployment 需列出 image pull、scheduling、quota、node、PVC 或 RBAC 檢查摘要。" + }, + { + "check_id": "rollout_before_after_present", + "instruction": "必須有 rollout before / after ref,不能只用 CD success 或 deploy marker。" + }, + { + "check_id": "event_summary_redacted", + "instruction": "只能收事件摘要 ref,不保存 raw event dump、raw manifest、raw pod log 或 raw kubeconfig。" + }, + { + "check_id": "metrics_alert_ref_present", + "instruction": "需有 metric / alert / dashboard / incident ref,不能只靠人工觀察。" + }, + { + "check_id": "drift_scanner_ref_present", + "instruction": "涉及 drift-scanner、配置漂移或 GitOps parity 時需有 readback ref;不適用也需明確說明。" + }, + { + "check_id": "cronjob_schedule_review_present", + "instruction": "涉及 CronJob / scheduled job / backup schedule 時需確認 schedule、suspend、last run 與 missed run 摘要。" + }, + { + "check_id": "backup_restore_impact_called_out", + "instruction": "涉及 Velero、backup、restore、PVC 或 object storage 時需列 backup / restore 影響。" + }, + { + "check_id": "secret_metadata_only", + "instruction": "Secret 只能收 metadata parity ref,不得收 value、hash、partial token、DSN、cookie 或 kubeconfig。" + }, + { + "check_id": "network_policy_service_impact_present", + "instruction": "涉及 NetworkPolicy、Service、Ingress、NodePort 或 DNS 時需列 route / port 影響。" + }, + { + "check_id": "rbac_serviceaccount_impact_present", + "instruction": "涉及 RBAC / ServiceAccount / RoleBinding 時需列權限與 fallback 影響。" + }, + { + "check_id": "public_admin_route_impact_present", + "instruction": "public / admin / API route 受影響時需有 route recovery ref;無影響也需明確不適用。" + }, + { + "check_id": "ai_provider_monitoring_impact_present", + "instruction": "AI provider、Ollama、monitoring、alert route 或 webhook 受影響時需列 impact ref。" + }, + { + "check_id": "operator_notification_present", + "instruction": "需提供已通知受影響產品、owner 或 Session 的脫敏 ref。" + }, + { + "check_id": "cross_project_sync_present", + "instruction": "若影響 AwoooP、IwoooS、agent-bounty、StockPlatform、公開網站或監控,需有跨專案同步 ref。" + }, + { + "check_id": "recovery_or_still_degraded_present", + "instruction": "已恢復需提供恢復時間與恢復證據;未恢復需提供 still-degraded ref。" + }, + { + "check_id": "postcheck_independent", + "instruction": "post-check 必須獨立於原操作人與 UI 卡片。" + }, + { + "check_id": "recurrence_guard_present", + "instruction": "必須提出防再發 guard、change freeze、owner review 或 automation block。" + }, + { + "check_id": "maintenance_window_present", + "instruction": "後續任何 sync / rollout / rollback / apply 操作都需維護窗口。" + }, + { + "check_id": "rollback_revision_present", + "instruction": "rollback revision 與 rollback owner 必須同時存在。" + }, + { + "check_id": "no_false_green", + "instruction": "不得只用 route 200、Pod Running、ArgoCD Synced、CD success、dashboard up 或 UI 可見當成事故已驗收。" + }, + { + "check_id": "raw_payload_absent", + "instruction": "不得保存 raw manifest、raw kubeconfig、raw event dump、raw pod log、raw Secret 或未脫敏 screenshot。" + }, + { + "check_id": "runtime_stays_zero", + "instruction": "readback plan 不得觸發 ArgoCD API、kubectl、Helm、Kustomize、NetworkPolicy / NodePort / RBAC 變更或 production write。" + }, + { + "check_id": "counts_transition_safe", + "instruction": "只有 reviewer record 能更新 accepted count,且不得同時開 runtime gate。" + } + ], + "schema_version": "k8s_argocd_post_incident_readback_plan_v1", + "source_paths": [ + "docs/security/K8S-ARGOCD-CHANGE-EVIDENCE-ACCEPTANCE.md", + "docs/security/k8s-argocd-change-evidence-acceptance.snapshot.json" + ], + "source_schema_version": "k8s_argocd_change_evidence_acceptance_v1", + "source_status": "change_evidence_acceptance_ledger_ready_no_runtime_action", + "status": "post_incident_readback_plan_ready_no_runtime_action", + "summary": { + "action_button_count": 0, + "actor_attribution_accepted_count": 0, + "ai_provider_monitoring_impact_accepted_count": 0, + "argocd_api_read_authorized_count": 0, + "argocd_app_health_accepted_count": 0, + "argocd_application_count": 1, + "argocd_sync_authorized_count": 0, + "argocd_sync_status_accepted_count": 0, + "backup_restore_impact_accepted_count": 0, + "blocked_action_count": 41, + "c0_readback_candidate_count": 3, + "c1_readback_candidate_count": 1, + "coverage_percent_after_readback_plan": 66, + "cronjob_object_count": 5, + "cronjob_schedule_accepted_count": 0, + "cross_project_sync_accepted_count": 0, + "cross_project_sync_required_candidate_count": 4, + "degraded_or_pending_review_required_candidate_count": 4, + "degraded_state_accepted_count": 0, + "deployment_object_count": 5, + "drift_or_schedule_review_required_candidate_count": 4, + "drift_scanner_accepted_count": 0, + "event_summary_accepted_count": 0, + "helm_action_authorized_count": 0, + "image_pull_or_scheduling_accepted_count": 0, + "kubectl_action_authorized_count": 0, + "live_cluster_read_authorized_count": 0, + "metrics_alert_accepted_count": 0, + "network_policy_change_authorized_count": 0, + "network_policy_object_count": 6, + "network_policy_service_impact_accepted_count": 0, + "no_false_green_accepted_count": 0, + "no_false_green_required_candidate_count": 4, + "nodeport_change_authorized_count": 0, + "operator_notification_accepted_count": 0, + "outcome_lane_count": 10, + "pending_workload_accepted_count": 0, + "post_incident_readback_accepted_count": 0, + "post_incident_readback_received_count": 0, + "postcheck_readback_accepted_count": 0, + "production_write_authorized_count": 0, + "prometheus_rule_count": 4, + "public_admin_route_impact_accepted_count": 0, + "rbac_change_authorized_count": 0, + "rbac_object_count": 5, + "rbac_serviceaccount_impact_accepted_count": 0, + "readback_candidate_count": 4, + "readback_field_count": 36, + "recovery_or_still_degraded_accepted_count": 0, + "recurrence_guard_accepted_count": 0, + "required_readback_field_count": 31, + "reviewer_check_count": 28, + "rollout_before_after_accepted_count": 0, + "route_ai_monitoring_impact_required_candidate_count": 4, + "route_smoke_authorized_count": 0, + "runtime_gate_count": 0, + "secret_metadata_parity_accepted_count": 0, + "secret_object_count": 6, + "secret_value_collection_allowed_count": 0, + "source_c0_change_evidence_candidate_count": 3, + "source_c0_file_count": 36, + "source_c1_change_evidence_candidate_count": 1, + "source_change_evidence_candidate_count": 4, + "source_manifest_file_count": 49, + "source_scan_group_count": 4, + "source_write_capable_candidate_count": 4, + "source_yaml_manifest_file_count": 45, + "write_capable_readback_candidate_count": 4 + } +} diff --git a/scripts/security/high-value-config-control-coverage.py b/scripts/security/high-value-config-control-coverage.py index de592220f..ce3682fa3 100644 --- a/scripts/security/high-value-config-control-coverage.py +++ b/scripts/security/high-value-config-control-coverage.py @@ -56,8 +56,8 @@ CONTROL_STATUS_BY_CATEGORY = { "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, + "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", @@ -66,11 +66,13 @@ CONTROL_STATUS_BY_CATEGORY = { "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 變更證據驗收只讀帳本;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。", + "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", @@ -382,6 +384,7 @@ def build_report(root: Path, generated_at: str | None) -> dict[str, Any]: "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", diff --git a/scripts/security/iwooos-config-control-guard.py b/scripts/security/iwooos-config-control-guard.py index 8f87a4d0c..034a63d26 100644 --- a/scripts/security/iwooos-config-control-guard.py +++ b/scripts/security/iwooos-config-control-guard.py @@ -19,7 +19,7 @@ from typing import Any EXPECTED_CATEGORIES = { "nginx_public_gateway": 90, "dns_tls_certbot": 78, - "k8s_production_gitops": 64, + "k8s_production_gitops": 66, "secret_metadata": 68, "gitea_workflow_runner_source_control": 72, "public_admin_api_runtime_config": 66, @@ -60,6 +60,7 @@ REQUIRED_CONTROL_DOCS = [ "docs/security/BACKUP-RESTORE-OWNER-RESPONSE-ACCEPTANCE.md", "docs/security/K8S-ARGOCD-OWNER-RESPONSE-ACCEPTANCE.md", "docs/security/K8S-ARGOCD-CHANGE-EVIDENCE-ACCEPTANCE.md", + "docs/security/K8S-ARGOCD-POST-INCIDENT-READBACK-PLAN.md", "docs/security/CD-RUNNER-SECRET-INJECTION-CHANGE-EVIDENCE-ACCEPTANCE.md", "docs/security/PUBLIC-RUNTIME-CONFIG-CHANGE-EVIDENCE-ACCEPTANCE.md", "docs/security/MONITORING-OWNER-REQUEST-DRAFT.md", @@ -419,6 +420,85 @@ ARTIFACT_SPECS = [ "runtime_gate_count": 0, }, }, + { + "label": "k8s argocd post incident readback plan", + "path": "docs/security/k8s-argocd-post-incident-readback-plan.snapshot.json", + "schema": "k8s_argocd_post_incident_readback_plan_v1", + "status": "post_incident_readback_plan_ready_no_runtime_action", + "list_counts": { + "readback_candidates": 4, + "blocked_actions": 41, + "reviewer_checks": 28, + "outcome_lanes": 10, + "required_readback_fields": 31, + }, + "summary_counts": { + "source_change_evidence_candidate_count": 4, + "c0_readback_candidate_count": 3, + "c1_readback_candidate_count": 1, + "readback_candidate_count": 4, + "write_capable_readback_candidate_count": 4, + "source_manifest_file_count": 49, + "source_yaml_manifest_file_count": 45, + "source_c0_file_count": 36, + "deployment_object_count": 5, + "cronjob_object_count": 5, + "secret_object_count": 6, + "network_policy_object_count": 6, + "rbac_object_count": 5, + "argocd_application_count": 1, + "prometheus_rule_count": 4, + "degraded_or_pending_review_required_candidate_count": 4, + "drift_or_schedule_review_required_candidate_count": 4, + "route_ai_monitoring_impact_required_candidate_count": 4, + "cross_project_sync_required_candidate_count": 4, + "no_false_green_required_candidate_count": 4, + "readback_field_count": 36, + "required_readback_field_count": 31, + "reviewer_check_count": 28, + "outcome_lane_count": 10, + "blocked_action_count": 41, + "post_incident_readback_received_count": 0, + "post_incident_readback_accepted_count": 0, + "actor_attribution_accepted_count": 0, + "argocd_app_health_accepted_count": 0, + "argocd_sync_status_accepted_count": 0, + "degraded_state_accepted_count": 0, + "pending_workload_accepted_count": 0, + "image_pull_or_scheduling_accepted_count": 0, + "rollout_before_after_accepted_count": 0, + "event_summary_accepted_count": 0, + "metrics_alert_accepted_count": 0, + "drift_scanner_accepted_count": 0, + "cronjob_schedule_accepted_count": 0, + "network_policy_service_impact_accepted_count": 0, + "rbac_serviceaccount_impact_accepted_count": 0, + "secret_metadata_parity_accepted_count": 0, + "public_admin_route_impact_accepted_count": 0, + "ai_provider_monitoring_impact_accepted_count": 0, + "backup_restore_impact_accepted_count": 0, + "operator_notification_accepted_count": 0, + "cross_project_sync_accepted_count": 0, + "recovery_or_still_degraded_accepted_count": 0, + "postcheck_readback_accepted_count": 0, + "recurrence_guard_accepted_count": 0, + "no_false_green_accepted_count": 0, + "argocd_api_read_authorized_count": 0, + "argocd_sync_authorized_count": 0, + "live_cluster_read_authorized_count": 0, + "kubectl_action_authorized_count": 0, + "helm_action_authorized_count": 0, + "network_policy_change_authorized_count": 0, + "nodeport_change_authorized_count": 0, + "rbac_change_authorized_count": 0, + "secret_value_collection_allowed_count": 0, + "route_smoke_authorized_count": 0, + "production_write_authorized_count": 0, + "runtime_gate_count": 0, + "action_button_count": 0, + "coverage_percent_after_readback_plan": 66, + }, + }, { "label": "cd runner secret injection change evidence acceptance", "path": "docs/security/cd-runner-secret-injection-change-evidence-acceptance.snapshot.json", diff --git a/scripts/security/k8s-argocd-post-incident-readback-plan.py b/scripts/security/k8s-argocd-post-incident-readback-plan.py new file mode 100644 index 000000000..d8fdcbfab --- /dev/null +++ b/scripts/security/k8s-argocd-post-incident-readback-plan.py @@ -0,0 +1,476 @@ +#!/usr/bin/env python3 +""" +IwoooS K8s / ArgoCD post-incident readback 只讀計畫產生器。 + +本工具讀取 K8s / ArgoCD GitOps 變更證據驗收 snapshot,建立事故後回讀 +計畫:誰觸發 GitOps / rollout、ArgoCD 是否 Synced / Degraded、Pod 是否 +Pending、是否有 image pull / scheduling / drift scanner / CronJob / route / +AI provider / monitoring 影響,以及如何防止把 UI 可見、route 200 或 CD +success 誤判成 runtime authorization。它不呼叫 ArgoCD API、不讀 live +cluster、不執行 kubectl / helm / kustomize、不改 NetworkPolicy / NodePort / +RBAC、不保存 raw manifest / kubeconfig / Secret value。 +""" + +from __future__ import annotations + +import argparse +import json +import subprocess +import sys +from datetime import datetime, timedelta, timezone +from pathlib import Path +from typing import Any + + +TAIPEI = timezone(timedelta(hours=8)) + +READBACK_FIELDS = [ + "post_incident_readback_candidate_id", + "source_change_evidence_candidate_id", + "group_id", + "root", + "control_tier", + "gate_tags", + "k8s_incident_or_change_ref", + "actor_attribution_ref", + "argocd_app_health_ref", + "argocd_sync_status_ref", + "degraded_state_ref", + "pending_workload_ref", + "image_pull_or_scheduling_ref", + "rollout_before_ref", + "rollout_after_ref", + "event_summary_ref", + "metrics_alert_ref", + "drift_scanner_ref", + "cronjob_schedule_ref", + "backup_restore_impact_ref", + "secret_metadata_parity_ref", + "network_policy_service_impact_ref", + "rbac_serviceaccount_impact_ref", + "public_admin_route_impact_ref", + "ai_provider_monitoring_impact_ref", + "operator_notification_ref", + "cross_project_sync_ref", + "recovery_or_still_degraded_ref", + "postcheck_readback_ref", + "recurrence_guard_ref", + "maintenance_window", + "rollback_revision", + "rollback_owner", + "reviewer_outcome", + "followup_owner", + "not_approval", +] + +REQUIRED_READBACK_FIELDS = [ + "k8s_incident_or_change_ref", + "actor_attribution_ref", + "argocd_app_health_ref", + "argocd_sync_status_ref", + "degraded_state_ref", + "pending_workload_ref", + "image_pull_or_scheduling_ref", + "rollout_before_ref", + "rollout_after_ref", + "event_summary_ref", + "metrics_alert_ref", + "drift_scanner_ref", + "cronjob_schedule_ref", + "secret_metadata_parity_ref", + "network_policy_service_impact_ref", + "rbac_serviceaccount_impact_ref", + "public_admin_route_impact_ref", + "ai_provider_monitoring_impact_ref", + "operator_notification_ref", + "cross_project_sync_ref", + "recovery_or_still_degraded_ref", + "postcheck_readback_ref", + "recurrence_guard_ref", + "maintenance_window", + "rollback_revision", + "rollback_owner", + "followup_owner", + "redacted_evidence_refs", + "no_secret_value_attestation", + "no_raw_manifest_or_kubeconfig_attestation", + "no_false_green_attestation", +] + +REVIEWER_CHECKS = [ + {"check_id": "source_change_evidence_current", "instruction": "來源 GitOps change evidence snapshot 必須是目前版本。"}, + {"check_id": "incident_or_change_ref_present", "instruction": "必須有 incident / change / deploy marker ref,不能只寫服務已恢復。"}, + {"check_id": "actor_attribution_present", "instruction": "必須標示 actor role / team,不接受匿名 ArgoCD sync、kubectl、Helm、rollout 或 image 變更。"}, + {"check_id": "argocd_sync_and_health_present", "instruction": "ArgoCD sync status、health status 與 revision 必須有脫敏 ref。"}, + {"check_id": "degraded_state_review_present", "instruction": "Synced / Degraded、OutOfSync、Progressing、Suspended 或 Unknown 狀態都需說明。"}, + {"check_id": "pending_workload_review_present", "instruction": "Pending Pod / Job / CronJob / Deployment 需列出 image pull、scheduling、quota、node、PVC 或 RBAC 檢查摘要。"}, + {"check_id": "rollout_before_after_present", "instruction": "必須有 rollout before / after ref,不能只用 CD success 或 deploy marker。"}, + {"check_id": "event_summary_redacted", "instruction": "只能收事件摘要 ref,不保存 raw event dump、raw manifest、raw pod log 或 raw kubeconfig。"}, + {"check_id": "metrics_alert_ref_present", "instruction": "需有 metric / alert / dashboard / incident ref,不能只靠人工觀察。"}, + {"check_id": "drift_scanner_ref_present", "instruction": "涉及 drift-scanner、配置漂移或 GitOps parity 時需有 readback ref;不適用也需明確說明。"}, + {"check_id": "cronjob_schedule_review_present", "instruction": "涉及 CronJob / scheduled job / backup schedule 時需確認 schedule、suspend、last run 與 missed run 摘要。"}, + {"check_id": "backup_restore_impact_called_out", "instruction": "涉及 Velero、backup、restore、PVC 或 object storage 時需列 backup / restore 影響。"}, + {"check_id": "secret_metadata_only", "instruction": "Secret 只能收 metadata parity ref,不得收 value、hash、partial token、DSN、cookie 或 kubeconfig。"}, + {"check_id": "network_policy_service_impact_present", "instruction": "涉及 NetworkPolicy、Service、Ingress、NodePort 或 DNS 時需列 route / port 影響。"}, + {"check_id": "rbac_serviceaccount_impact_present", "instruction": "涉及 RBAC / ServiceAccount / RoleBinding 時需列權限與 fallback 影響。"}, + {"check_id": "public_admin_route_impact_present", "instruction": "public / admin / API route 受影響時需有 route recovery ref;無影響也需明確不適用。"}, + {"check_id": "ai_provider_monitoring_impact_present", "instruction": "AI provider、Ollama、monitoring、alert route 或 webhook 受影響時需列 impact ref。"}, + {"check_id": "operator_notification_present", "instruction": "需提供已通知受影響產品、owner 或 Session 的脫敏 ref。"}, + {"check_id": "cross_project_sync_present", "instruction": "若影響 AwoooP、IwoooS、agent-bounty、StockPlatform、公開網站或監控,需有跨專案同步 ref。"}, + {"check_id": "recovery_or_still_degraded_present", "instruction": "已恢復需提供恢復時間與恢復證據;未恢復需提供 still-degraded ref。"}, + {"check_id": "postcheck_independent", "instruction": "post-check 必須獨立於原操作人與 UI 卡片。"}, + {"check_id": "recurrence_guard_present", "instruction": "必須提出防再發 guard、change freeze、owner review 或 automation block。"}, + {"check_id": "maintenance_window_present", "instruction": "後續任何 sync / rollout / rollback / apply 操作都需維護窗口。"}, + {"check_id": "rollback_revision_present", "instruction": "rollback revision 與 rollback owner 必須同時存在。"}, + {"check_id": "no_false_green", "instruction": "不得只用 route 200、Pod Running、ArgoCD Synced、CD success、dashboard up 或 UI 可見當成事故已驗收。"}, + {"check_id": "raw_payload_absent", "instruction": "不得保存 raw manifest、raw kubeconfig、raw event dump、raw pod log、raw Secret 或未脫敏 screenshot。"}, + {"check_id": "runtime_stays_zero", "instruction": "readback plan 不得觸發 ArgoCD API、kubectl、Helm、Kustomize、NetworkPolicy / NodePort / RBAC 變更或 production write。"}, + {"check_id": "counts_transition_safe", "instruction": "只有 reviewer record 能更新 accepted count,且不得同時開 runtime gate。"}, +] + +OUTCOME_LANES = [ + {"lane_id": "waiting_post_incident_readback", "meaning": "尚未收到 K8s / ArgoCD 事故回讀包;所有 accepted / runtime count 維持 0。"}, + {"lane_id": "request_actor_or_revision_supplement", "meaning": "缺 actor、deploy marker、ArgoCD revision 或 rollback revision 時要求補件。"}, + {"lane_id": "request_degraded_pending_supplement", "meaning": "缺 Degraded / Pending / image pull / scheduling / rollout before-after 時要求補件。"}, + {"lane_id": "request_event_metric_supplement", "meaning": "缺 event summary、metrics、alert、drift scanner 或 CronJob schedule 時要求補件。"}, + {"lane_id": "request_route_dependency_supplement", "meaning": "缺 public/admin route、AI provider、monitoring、backup / restore、network / RBAC 影響時要求補件。"}, + {"lane_id": "quarantine_raw_payload", "meaning": "收到 Secret value、kubeconfig、raw manifest、raw log、raw event 或未脫敏截圖時只能隔離。"}, + {"lane_id": "reject_runtime_claim", "meaning": "把 CD success、ArgoCD Synced、route 200、Pod Running 或 UI 可見當驗收時拒收。"}, + {"lane_id": "ready_for_k8s_post_incident_review", "meaning": "metadata 合格後,只能進 reviewer review。"}, + {"lane_id": "recurrence_guard_backfill_required", "meaning": "需補防再發 guard、owner review、change freeze 或 automation block。"}, + {"lane_id": "waiting_runtime_gate", "meaning": "即使 readback accepted,runtime gate 仍需獨立人工批准。"}, +] + +BLOCKED_ACTIONS = [ + "argocd_api_read", + "argocd_sync", + "argocd_rollback", + "live_cluster_read", + "kubectl_get_live", + "kubectl_apply", + "kubectl_patch", + "kubectl_delete", + "kubectl_rollout_restart", + "kubectl_scale", + "helm_upgrade", + "helm_rollback", + "kustomize_image_set", + "change_network_policy", + "change_nodeport", + "change_service_type", + "change_ingress_route", + "change_rbac", + "change_serviceaccount", + "change_configmap_runtime", + "change_secret_metadata", + "secret_value_collection", + "kubeconfig_collection", + "raw_manifest_storage", + "raw_event_dump_storage", + "raw_pod_log_storage", + "raw_secret_storage", + "velero_restore", + "restore_backup", + "prometheus_rule_apply", + "alertmanager_reload", + "route_smoke", + "production_write", + "accept_synced_as_healthy", + "accept_route_200_as_all_green", + "accept_pod_running_as_all_green", + "accept_cd_success_as_security_acceptance", + "skip_degraded_pending_review", + "mark_readback_accepted_without_reviewer_record", + "open_runtime_gate", + "add_action_button", +] + + +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_json(path: Path) -> dict[str, Any]: + return json.loads(path.read_text(encoding="utf-8")) + + +def build_candidate(source: dict[str, Any]) -> dict[str, Any]: + group_id = source["group_id"] + return { + "post_incident_readback_candidate_id": f"k8s_argocd_post_incident_readback:{group_id}", + "status": "waiting_post_incident_readback", + "source_change_evidence_candidate_id": source["change_evidence_candidate_id"], + "group_id": group_id, + "root": source["root"], + "control_tier": source["control_tier"], + "gate_tags": source.get("gate_tags", []), + "write_capable": source.get("write_capable", True), + "k8s_incident_or_change_ref": None, + "actor_attribution_ref": None, + "argocd_app_health_ref": None, + "argocd_sync_status_ref": None, + "degraded_state_ref": None, + "pending_workload_ref": None, + "image_pull_or_scheduling_ref": None, + "rollout_before_ref": None, + "rollout_after_ref": None, + "event_summary_ref": None, + "metrics_alert_ref": None, + "drift_scanner_ref": None, + "cronjob_schedule_ref": None, + "backup_restore_impact_ref": None, + "secret_metadata_parity_ref": None, + "network_policy_service_impact_ref": None, + "rbac_serviceaccount_impact_ref": None, + "public_admin_route_impact_ref": None, + "ai_provider_monitoring_impact_ref": None, + "operator_notification_ref": None, + "cross_project_sync_ref": None, + "recovery_or_still_degraded_ref": None, + "postcheck_readback_ref": None, + "recurrence_guard_ref": None, + "maintenance_window": "pending_post_incident_readback", + "rollback_revision": "pending_post_incident_readback", + "rollback_owner": "pending_post_incident_readback", + "reviewer_outcome": "waiting_post_incident_readback", + "followup_owner": "pending_post_incident_readback", + "readback_fields": READBACK_FIELDS, + "required_readback_fields": REQUIRED_READBACK_FIELDS, + "reviewer_checks": [item["check_id"] for item in REVIEWER_CHECKS], + "outcome_lanes": [item["lane_id"] for item in OUTCOME_LANES], + "blocked_actions": BLOCKED_ACTIONS, + "not_approval": True, + "post_incident_readback_received": False, + "post_incident_readback_accepted": False, + "actor_attribution_accepted": False, + "argocd_app_health_accepted": False, + "argocd_sync_status_accepted": False, + "degraded_state_accepted": False, + "pending_workload_accepted": False, + "image_pull_or_scheduling_accepted": False, + "rollout_before_after_accepted": False, + "event_summary_accepted": False, + "metrics_alert_accepted": False, + "drift_scanner_accepted": False, + "cronjob_schedule_accepted": False, + "backup_restore_impact_accepted": False, + "secret_metadata_parity_accepted": False, + "network_policy_service_impact_accepted": False, + "rbac_serviceaccount_impact_accepted": False, + "public_admin_route_impact_accepted": False, + "ai_provider_monitoring_impact_accepted": False, + "operator_notification_accepted": False, + "cross_project_sync_accepted": False, + "recovery_or_still_degraded_accepted": False, + "postcheck_readback_accepted": False, + "recurrence_guard_accepted": False, + "no_false_green_accepted": False, + "argocd_api_read_authorized": False, + "argocd_sync_authorized": False, + "kubectl_action_authorized": False, + "helm_action_authorized": False, + "live_cluster_read_authorized": False, + "network_policy_change_authorized": False, + "nodeport_change_authorized": False, + "rbac_change_authorized": False, + "secret_value_collection_allowed": False, + "route_smoke_authorized": False, + "production_write_authorized": False, + "runtime_gate": False, + "action_buttons_allowed": False, + } + + +def build_report( + root: Path, + source_report: dict[str, Any], + generated_at: str | None, +) -> dict[str, Any]: + report_time = generated_at or datetime.now(TAIPEI).isoformat(timespec="seconds") + candidates = [build_candidate(item) for item in source_report.get("change_evidence_candidates", [])] + c0_candidates = [item for item in candidates if item["control_tier"] == "C0"] + c1_candidates = [item for item in candidates if item["control_tier"] == "C1"] + write_capable_candidates = [item for item in candidates if item["write_capable"]] + source_summary = source_report.get("summary", {}) + + return { + "schema_version": "k8s_argocd_post_incident_readback_plan_v1", + "generated_at": report_time, + "git_commit": git_short_sha(root), + "source_schema_version": source_report.get("schema_version"), + "source_status": source_report.get("status"), + "status": "post_incident_readback_plan_ready_no_runtime_action", + "summary": { + "source_change_evidence_candidate_count": source_summary.get("change_evidence_candidate_count", 0), + "source_c0_change_evidence_candidate_count": source_summary.get("c0_change_evidence_candidate_count", 0), + "source_c1_change_evidence_candidate_count": source_summary.get("c1_change_evidence_candidate_count", 0), + "source_write_capable_candidate_count": source_summary.get("write_capable_candidate_count", 0), + "source_scan_group_count": source_summary.get("source_scan_group_count", 0), + "source_manifest_file_count": source_summary.get("source_manifest_file_count", 0), + "source_yaml_manifest_file_count": source_summary.get("source_yaml_manifest_file_count", 0), + "source_c0_file_count": source_summary.get("source_c0_file_count", 0), + "deployment_object_count": source_summary.get("deployment_object_count", 0), + "cronjob_object_count": source_summary.get("cronjob_object_count", 0), + "secret_object_count": source_summary.get("secret_object_count", 0), + "network_policy_object_count": source_summary.get("network_policy_object_count", 0), + "rbac_object_count": source_summary.get("rbac_object_count", 0), + "argocd_application_count": source_summary.get("argocd_application_count", 0), + "prometheus_rule_count": source_summary.get("prometheus_rule_count", 0), + "readback_candidate_count": len(candidates), + "c0_readback_candidate_count": len(c0_candidates), + "c1_readback_candidate_count": len(c1_candidates), + "write_capable_readback_candidate_count": len(write_capable_candidates), + "degraded_or_pending_review_required_candidate_count": len(candidates), + "drift_or_schedule_review_required_candidate_count": len(candidates), + "route_ai_monitoring_impact_required_candidate_count": len(candidates), + "cross_project_sync_required_candidate_count": len(candidates), + "no_false_green_required_candidate_count": len(candidates), + "readback_field_count": len(READBACK_FIELDS), + "required_readback_field_count": len(REQUIRED_READBACK_FIELDS), + "reviewer_check_count": len(REVIEWER_CHECKS), + "outcome_lane_count": len(OUTCOME_LANES), + "blocked_action_count": len(BLOCKED_ACTIONS), + "post_incident_readback_received_count": 0, + "post_incident_readback_accepted_count": 0, + "actor_attribution_accepted_count": 0, + "argocd_app_health_accepted_count": 0, + "argocd_sync_status_accepted_count": 0, + "degraded_state_accepted_count": 0, + "pending_workload_accepted_count": 0, + "image_pull_or_scheduling_accepted_count": 0, + "rollout_before_after_accepted_count": 0, + "event_summary_accepted_count": 0, + "metrics_alert_accepted_count": 0, + "drift_scanner_accepted_count": 0, + "cronjob_schedule_accepted_count": 0, + "backup_restore_impact_accepted_count": 0, + "secret_metadata_parity_accepted_count": 0, + "network_policy_service_impact_accepted_count": 0, + "rbac_serviceaccount_impact_accepted_count": 0, + "public_admin_route_impact_accepted_count": 0, + "ai_provider_monitoring_impact_accepted_count": 0, + "operator_notification_accepted_count": 0, + "cross_project_sync_accepted_count": 0, + "recovery_or_still_degraded_accepted_count": 0, + "postcheck_readback_accepted_count": 0, + "recurrence_guard_accepted_count": 0, + "no_false_green_accepted_count": 0, + "argocd_api_read_authorized_count": 0, + "argocd_sync_authorized_count": 0, + "kubectl_action_authorized_count": 0, + "helm_action_authorized_count": 0, + "live_cluster_read_authorized_count": 0, + "network_policy_change_authorized_count": 0, + "nodeport_change_authorized_count": 0, + "rbac_change_authorized_count": 0, + "secret_value_collection_allowed_count": 0, + "route_smoke_authorized_count": 0, + "production_write_authorized_count": 0, + "runtime_gate_count": 0, + "action_button_count": 0, + "coverage_percent_after_readback_plan": 66, + }, + "boundaries": { + "post_incident_readback_received": False, + "post_incident_readback_accepted": False, + "actor_attribution_accepted": False, + "argocd_app_health_accepted": False, + "argocd_sync_status_accepted": False, + "degraded_state_accepted": False, + "pending_workload_accepted": False, + "image_pull_or_scheduling_accepted": False, + "rollout_before_after_accepted": False, + "event_summary_accepted": False, + "metrics_alert_accepted": False, + "drift_scanner_accepted": False, + "cronjob_schedule_accepted": False, + "backup_restore_impact_accepted": False, + "secret_metadata_parity_accepted": False, + "network_policy_service_impact_accepted": False, + "rbac_serviceaccount_impact_accepted": False, + "public_admin_route_impact_accepted": False, + "ai_provider_monitoring_impact_accepted": False, + "operator_notification_accepted": False, + "cross_project_sync_accepted": False, + "recovery_or_still_degraded_accepted": False, + "postcheck_readback_accepted": False, + "recurrence_guard_accepted": False, + "no_false_green_accepted": False, + "argocd_api_read_authorized": False, + "argocd_sync_authorized": False, + "kubectl_action_authorized": False, + "helm_action_authorized": False, + "live_cluster_read_authorized": False, + "network_policy_change_authorized": False, + "nodeport_change_authorized": False, + "rbac_change_authorized": False, + "secret_value_collection_allowed": False, + "route_smoke_authorized": False, + "production_write_authorized": False, + "runtime_execution_authorized": False, + "action_buttons_allowed": False, + "not_authorization": True, + }, + "readback_fields": READBACK_FIELDS, + "required_readback_fields": REQUIRED_READBACK_FIELDS, + "reviewer_checks": REVIEWER_CHECKS, + "outcome_lanes": OUTCOME_LANES, + "blocked_actions": BLOCKED_ACTIONS, + "readback_candidates": candidates, + "source_paths": [ + "docs/security/K8S-ARGOCD-CHANGE-EVIDENCE-ACCEPTANCE.md", + "docs/security/k8s-argocd-change-evidence-acceptance.snapshot.json", + ], + } + + +def main() -> int: + parser = argparse.ArgumentParser(description="IwoooS K8s / ArgoCD 事故後回讀只讀計畫產生器") + parser.add_argument("--root", default=".", help="repo root") + parser.add_argument( + "--source-change-evidence-report", + default="docs/security/k8s-argocd-change-evidence-acceptance.snapshot.json", + help="k8s-argocd-change-evidence-acceptance.py 輸出的 JSON", + ) + parser.add_argument("--output", help="寫出 JSON 報告") + parser.add_argument("--generated-at", help="固定報告時間,供 committed snapshot 使用") + args = parser.parse_args() + + root = Path(args.root).resolve() + source_report = load_json(root / args.source_change_evidence_report) + report = build_report(root, source_report, 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( + "K8S_ARGOCD_POST_INCIDENT_READBACK_PLAN_OK " + f"candidates={summary['readback_candidate_count']} " + f"c0={summary['c0_readback_candidate_count']} " + f"checks={summary['reviewer_check_count']} " + f"lanes={summary['outcome_lane_count']} " + f"accepted={summary['post_incident_readback_accepted_count']} " + f"runtime_gate={summary['runtime_gate_count']}", + file=sys.stderr, + ) + return 0 + + +if __name__ == "__main__": + sys.exit(main()) diff --git a/scripts/security/security-mirror-progress-guard.py b/scripts/security/security-mirror-progress-guard.py index 2db643c85..8b796039b 100755 --- a/scripts/security/security-mirror-progress-guard.py +++ b/scripts/security/security-mirror-progress-guard.py @@ -207,6 +207,9 @@ def validate(root: Path) -> None: k8s_argocd_change_evidence_acceptance = load_json( security_dir / "k8s-argocd-change-evidence-acceptance.snapshot.json" ) + k8s_argocd_post_incident_readback_plan = load_json( + security_dir / "k8s-argocd-post-incident-readback-plan.snapshot.json" + ) cd_runner_secret_injection_change_evidence_acceptance = load_json( security_dir / "cd-runner-secret-injection-change-evidence-acceptance.snapshot.json" ) @@ -3062,12 +3065,12 @@ def validate(root: Path) -> None: assert_equal( "high_value_config_coverage.coverage_categories.k8s.coverage_percent", k8s_gitops_category["coverage_percent"], - 64, + 66, ) assert_equal( "high_value_config_coverage.coverage_categories.k8s.coverage_status", k8s_gitops_category["coverage_status"], - "change_evidence_acceptance_ready_needs_gitops_owner_evidence", + "post_incident_readback_plan_ready_needs_gitops_owner_evidence", ) for evidence_ref in [ "docs/security/HIGH-VALUE-CONFIG-CHANGE-GATE.md", @@ -3077,6 +3080,8 @@ def validate(root: Path) -> None: "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", ]: @@ -7127,6 +7132,8 @@ def validate(root: Path) -> None: "docs/security/K8S-ARGOCD-OWNER-RESPONSE-ACCEPTANCE.md", "docs/security/k8s-argocd-change-evidence-acceptance.snapshot.json", "docs/security/K8S-ARGOCD-CHANGE-EVIDENCE-ACCEPTANCE.md", + "docs/security/k8s-argocd-post-incident-readback-plan.snapshot.json", + "docs/security/K8S-ARGOCD-POST-INCIDENT-READBACK-PLAN.md", "docs/security/host-service-config-inventory.snapshot.json", "docs/security/HOST-SERVICE-CONFIG-INVENTORY.md", "docs/security/host-service-post-incident-readback-plan.snapshot.json", @@ -7188,6 +7195,7 @@ def validate(root: Path) -> None: "public_frontend_sensitive_surface_guard_allowlisted_match_count": 2, "public_frontend_sensitive_surface_guard_violation_count": 0, "public_frontend_sensitive_surface_guard_runtime_gate_count": 0, + "k8s_production_gitops_coverage_percent": 66, "ai_provider_model_routing_coverage_percent": 64, } for key, expected in expected_high_value_config_coverage_summary.items(): @@ -7422,6 +7430,61 @@ def validate(root: Path) -> None: "k8s_argocd_change_evidence_acceptance_runtime_gate_count": 0, "k8s_argocd_change_evidence_acceptance_action_button_count": 0, "k8s_argocd_change_evidence_acceptance_coverage_percent_after_acceptance": 64, + "k8s_argocd_post_incident_readback_plan_first_layer": True, + "k8s_argocd_post_incident_readback_plan_candidate_count": 4, + "k8s_argocd_post_incident_readback_plan_c0_candidate_count": 3, + "k8s_argocd_post_incident_readback_plan_c1_candidate_count": 1, + "k8s_argocd_post_incident_readback_plan_write_capable_candidate_count": 4, + "k8s_argocd_post_incident_readback_plan_degraded_or_pending_review_required_candidate_count": 4, + "k8s_argocd_post_incident_readback_plan_drift_or_schedule_review_required_candidate_count": 4, + "k8s_argocd_post_incident_readback_plan_route_ai_monitoring_impact_required_candidate_count": 4, + "k8s_argocd_post_incident_readback_plan_cross_project_sync_required_candidate_count": 4, + "k8s_argocd_post_incident_readback_plan_no_false_green_required_candidate_count": 4, + "k8s_argocd_post_incident_readback_plan_readback_field_count": 36, + "k8s_argocd_post_incident_readback_plan_required_readback_field_count": 31, + "k8s_argocd_post_incident_readback_plan_reviewer_check_count": 28, + "k8s_argocd_post_incident_readback_plan_outcome_lane_count": 10, + "k8s_argocd_post_incident_readback_plan_blocked_action_count": 41, + "k8s_argocd_post_incident_readback_plan_post_incident_readback_received_count": 0, + "k8s_argocd_post_incident_readback_plan_post_incident_readback_accepted_count": 0, + "k8s_argocd_post_incident_readback_plan_actor_attribution_accepted_count": 0, + "k8s_argocd_post_incident_readback_plan_argocd_app_health_accepted_count": 0, + "k8s_argocd_post_incident_readback_plan_argocd_sync_status_accepted_count": 0, + "k8s_argocd_post_incident_readback_plan_degraded_state_accepted_count": 0, + "k8s_argocd_post_incident_readback_plan_pending_workload_accepted_count": 0, + "k8s_argocd_post_incident_readback_plan_image_pull_or_scheduling_accepted_count": 0, + "k8s_argocd_post_incident_readback_plan_rollout_before_after_accepted_count": 0, + "k8s_argocd_post_incident_readback_plan_event_summary_accepted_count": 0, + "k8s_argocd_post_incident_readback_plan_metrics_alert_accepted_count": 0, + "k8s_argocd_post_incident_readback_plan_drift_scanner_accepted_count": 0, + "k8s_argocd_post_incident_readback_plan_cronjob_schedule_accepted_count": 0, + "k8s_argocd_post_incident_readback_plan_network_policy_service_impact_accepted_count": 0, + "k8s_argocd_post_incident_readback_plan_rbac_serviceaccount_impact_accepted_count": 0, + "k8s_argocd_post_incident_readback_plan_secret_metadata_parity_accepted_count": 0, + "k8s_argocd_post_incident_readback_plan_public_admin_route_impact_accepted_count": 0, + "k8s_argocd_post_incident_readback_plan_ai_provider_monitoring_impact_accepted_count": 0, + "k8s_argocd_post_incident_readback_plan_backup_restore_impact_accepted_count": 0, + "k8s_argocd_post_incident_readback_plan_operator_notification_accepted_count": 0, + "k8s_argocd_post_incident_readback_plan_cross_project_sync_accepted_count": 0, + "k8s_argocd_post_incident_readback_plan_recovery_or_still_degraded_accepted_count": 0, + "k8s_argocd_post_incident_readback_plan_postcheck_readback_accepted_count": 0, + "k8s_argocd_post_incident_readback_plan_recurrence_guard_accepted_count": 0, + "k8s_argocd_post_incident_readback_plan_no_false_green_accepted_count": 0, + "k8s_argocd_post_incident_readback_plan_argocd_api_read_authorized_count": 0, + "k8s_argocd_post_incident_readback_plan_argocd_sync_authorized_count": 0, + "k8s_argocd_post_incident_readback_plan_live_cluster_read_authorized_count": 0, + "k8s_argocd_post_incident_readback_plan_kubectl_action_authorized_count": 0, + "k8s_argocd_post_incident_readback_plan_helm_action_authorized_count": 0, + "k8s_argocd_post_incident_readback_plan_network_policy_change_authorized_count": 0, + "k8s_argocd_post_incident_readback_plan_nodeport_change_authorized_count": 0, + "k8s_argocd_post_incident_readback_plan_rbac_change_authorized_count": 0, + "k8s_argocd_post_incident_readback_plan_secret_value_collection_allowed_count": 0, + "k8s_argocd_post_incident_readback_plan_route_smoke_authorized_count": 0, + "k8s_argocd_post_incident_readback_plan_production_write_authorized_count": 0, + "k8s_argocd_post_incident_readback_plan_runtime_gate_count": 0, + "k8s_argocd_post_incident_readback_plan_action_button_count": 0, + "k8s_argocd_post_incident_readback_plan_coverage_percent_after_readback_plan": 66, + "k8s_production_gitops_coverage_percent": 66, "cd_runner_secret_injection_change_evidence_acceptance_first_layer": True, "cd_runner_secret_injection_change_evidence_acceptance_candidate_count": 5, "cd_runner_secret_injection_change_evidence_acceptance_c0_candidate_count": 4, @@ -17214,7 +17277,7 @@ def validate(root: Path) -> None: assert_text_contains( "iwooos_page.high_value_config_control_coverage_k8s_gitops_percent", iwooos_projection_page, - "{ key: 'k8sGitops', rank: 'P1-4', value: '64%'", + "{ key: 'k8sGitops', rank: 'P1-4', value: '66%'", ) assert_text_before( "iwooos_page.high_value_config_control_coverage_before_owner_packet", @@ -17240,7 +17303,7 @@ def validate(root: Path) -> None: "public_gateway_owner_response_acceptance_reviewer_check_count=22", "public_gateway_owner_response_acceptance_outcome_lane_count=8", "public_gateway_owner_response_acceptance_blocked_action_count=28", - "k8s_production_gitops_coverage_percent=64", + "k8s_production_gitops_coverage_percent=66", "secret_metadata_coverage_percent=68", "gitea_workflow_runner_source_control_coverage_percent=72", "public_admin_api_runtime_config_coverage_percent=66", @@ -17323,6 +17386,28 @@ def validate(root: Path) -> None: "k8s_argocd_change_evidence_acceptance_accepted_count=0", "k8s_argocd_change_evidence_acceptance_runtime_approval_package_ready_count=0", "k8s_argocd_change_evidence_acceptance_runtime_gate_count=0", + "k8s_argocd_post_incident_readback_plan_candidate_count=4", + "k8s_argocd_post_incident_readback_plan_c0_candidate_count=3", + "k8s_argocd_post_incident_readback_plan_write_capable_candidate_count=4", + "k8s_argocd_post_incident_readback_plan_required_readback_field_count=31", + "k8s_argocd_post_incident_readback_plan_reviewer_check_count=28", + "k8s_argocd_post_incident_readback_plan_outcome_lane_count=10", + "k8s_argocd_post_incident_readback_plan_blocked_action_count=41", + "k8s_argocd_post_incident_readback_plan_post_incident_readback_received_count=0", + "k8s_argocd_post_incident_readback_plan_post_incident_readback_accepted_count=0", + "k8s_argocd_post_incident_readback_plan_argocd_app_health_accepted_count=0", + "k8s_argocd_post_incident_readback_plan_argocd_sync_status_accepted_count=0", + "k8s_argocd_post_incident_readback_plan_degraded_state_accepted_count=0", + "k8s_argocd_post_incident_readback_plan_pending_workload_accepted_count=0", + "k8s_argocd_post_incident_readback_plan_image_pull_or_scheduling_accepted_count=0", + "k8s_argocd_post_incident_readback_plan_metrics_alert_accepted_count=0", + "k8s_argocd_post_incident_readback_plan_cross_project_sync_accepted_count=0", + "k8s_argocd_post_incident_readback_plan_no_false_green_accepted_count=0", + "k8s_argocd_post_incident_readback_plan_argocd_api_read_authorized_count=0", + "k8s_argocd_post_incident_readback_plan_argocd_sync_authorized_count=0", + "k8s_argocd_post_incident_readback_plan_kubectl_action_authorized_count=0", + "k8s_argocd_post_incident_readback_plan_runtime_gate_count=0", + "k8s_argocd_post_incident_readback_plan_action_button_count=0", "public_gateway_rendered_diff_acceptance_candidate_count=3", "public_gateway_rendered_diff_acceptance_reviewer_check_count=15", "public_gateway_rendered_diff_acceptance_runtime_gate_count=0", @@ -17579,7 +17664,7 @@ def validate(root: Path) -> None: assert_text_contains( "iwooos_page.critical_config_priority_k8s_percent", iwooos_projection_page, - "{ key: 'k8sArgocd', rank: 'P0-3', state: '64% / sync 0'", + "{ key: 'k8sArgocd', rank: 'P0-3', state: '66% / readback 0'", ) assert_text_contains( "iwooos_page.critical_config_priority_workflow_secret_percent", @@ -17656,6 +17741,16 @@ def validate(root: Path) -> None: "k8s_argocd_change_evidence_acceptance_accepted_count=0", "k8s_argocd_change_evidence_acceptance_runtime_approval_package_ready_count=0", "k8s_argocd_change_evidence_acceptance_runtime_gate_count=0", + "k8s_argocd_post_incident_readback_plan_candidate_count=4", + "k8s_argocd_post_incident_readback_plan_c0_candidate_count=3", + "k8s_argocd_post_incident_readback_plan_write_capable_candidate_count=4", + "k8s_argocd_post_incident_readback_plan_required_readback_field_count=31", + "k8s_argocd_post_incident_readback_plan_reviewer_check_count=28", + "k8s_argocd_post_incident_readback_plan_outcome_lane_count=10", + "k8s_argocd_post_incident_readback_plan_blocked_action_count=41", + "k8s_argocd_post_incident_readback_plan_post_incident_readback_received_count=0", + "k8s_argocd_post_incident_readback_plan_post_incident_readback_accepted_count=0", + "k8s_argocd_post_incident_readback_plan_runtime_gate_count=0", "argocd_api_read_authorized=false", "argocd_sync_authorized=false", "kubectl_action_authorized=false", @@ -19087,6 +19182,223 @@ def validate(root: Path) -> None: f"k8s_argocd_change_evidence_acceptance.{item['change_evidence_candidate_id']}.{false_key}", item[false_key], ) + assert_equal( + "k8s_argocd_post_incident_readback_plan.schema", + k8s_argocd_post_incident_readback_plan["schema_version"], + "k8s_argocd_post_incident_readback_plan_v1", + ) + assert_equal( + "k8s_argocd_post_incident_readback_plan.status", + k8s_argocd_post_incident_readback_plan["status"], + "post_incident_readback_plan_ready_no_runtime_action", + ) + assert_equal( + "k8s_argocd_post_incident_readback_plan.source_schema_version", + k8s_argocd_post_incident_readback_plan["source_schema_version"], + "k8s_argocd_change_evidence_acceptance_v1", + ) + assert_equal( + "k8s_argocd_post_incident_readback_plan.source_status", + k8s_argocd_post_incident_readback_plan["source_status"], + "change_evidence_acceptance_ledger_ready_no_runtime_action", + ) + for source_path in [ + "docs/security/K8S-ARGOCD-CHANGE-EVIDENCE-ACCEPTANCE.md", + "docs/security/k8s-argocd-change-evidence-acceptance.snapshot.json", + ]: + assert_contains( + "k8s_argocd_post_incident_readback_plan.source_paths", + k8s_argocd_post_incident_readback_plan["source_paths"], + source_path, + ) + expected_k8s_post_incident_summary = { + "source_scan_group_count": 4, + "source_change_evidence_candidate_count": 4, + "source_c0_change_evidence_candidate_count": 3, + "source_c1_change_evidence_candidate_count": 1, + "source_write_capable_candidate_count": 4, + "source_manifest_file_count": 49, + "source_yaml_manifest_file_count": 45, + "source_c0_file_count": 36, + "deployment_object_count": 5, + "cronjob_object_count": 5, + "secret_object_count": 6, + "network_policy_object_count": 6, + "rbac_object_count": 5, + "argocd_application_count": 1, + "prometheus_rule_count": 4, + "readback_candidate_count": 4, + "c0_readback_candidate_count": 3, + "c1_readback_candidate_count": 1, + "write_capable_readback_candidate_count": 4, + "degraded_or_pending_review_required_candidate_count": 4, + "drift_or_schedule_review_required_candidate_count": 4, + "route_ai_monitoring_impact_required_candidate_count": 4, + "cross_project_sync_required_candidate_count": 4, + "no_false_green_required_candidate_count": 4, + "readback_field_count": 36, + "required_readback_field_count": 31, + "reviewer_check_count": 28, + "outcome_lane_count": 10, + "blocked_action_count": 41, + "post_incident_readback_received_count": 0, + "post_incident_readback_accepted_count": 0, + "actor_attribution_accepted_count": 0, + "argocd_app_health_accepted_count": 0, + "argocd_sync_status_accepted_count": 0, + "degraded_state_accepted_count": 0, + "pending_workload_accepted_count": 0, + "image_pull_or_scheduling_accepted_count": 0, + "rollout_before_after_accepted_count": 0, + "event_summary_accepted_count": 0, + "metrics_alert_accepted_count": 0, + "drift_scanner_accepted_count": 0, + "cronjob_schedule_accepted_count": 0, + "network_policy_service_impact_accepted_count": 0, + "rbac_serviceaccount_impact_accepted_count": 0, + "secret_metadata_parity_accepted_count": 0, + "public_admin_route_impact_accepted_count": 0, + "ai_provider_monitoring_impact_accepted_count": 0, + "backup_restore_impact_accepted_count": 0, + "operator_notification_accepted_count": 0, + "cross_project_sync_accepted_count": 0, + "recovery_or_still_degraded_accepted_count": 0, + "postcheck_readback_accepted_count": 0, + "recurrence_guard_accepted_count": 0, + "no_false_green_accepted_count": 0, + "argocd_api_read_authorized_count": 0, + "argocd_sync_authorized_count": 0, + "live_cluster_read_authorized_count": 0, + "kubectl_action_authorized_count": 0, + "helm_action_authorized_count": 0, + "network_policy_change_authorized_count": 0, + "nodeport_change_authorized_count": 0, + "rbac_change_authorized_count": 0, + "secret_value_collection_allowed_count": 0, + "route_smoke_authorized_count": 0, + "production_write_authorized_count": 0, + "runtime_gate_count": 0, + "action_button_count": 0, + "coverage_percent_after_readback_plan": 66, + } + for key, expected in expected_k8s_post_incident_summary.items(): + assert_equal( + f"k8s_argocd_post_incident_readback_plan.summary.{key}", + k8s_argocd_post_incident_readback_plan["summary"][key], + expected, + ) + for key, value in k8s_argocd_post_incident_readback_plan["boundaries"].items(): + if key == "not_authorization": + assert_true(f"k8s_argocd_post_incident_readback_plan.boundaries.{key}", value) + else: + assert_false(f"k8s_argocd_post_incident_readback_plan.boundaries.{key}", value) + expected_k8s_post_incident_ids = [ + "k8s_argocd_post_incident_readback:awoooi_prod", + "k8s_argocd_post_incident_readback:argocd", + "k8s_argocd_post_incident_readback:velero", + "k8s_argocd_post_incident_readback:monitoring", + ] + assert_equal( + "k8s_argocd_post_incident_readback_plan.readback_candidate_ids", + [ + item["post_incident_readback_candidate_id"] + for item in k8s_argocd_post_incident_readback_plan["readback_candidates"] + ], + expected_k8s_post_incident_ids, + ) + assert_equal( + "k8s_argocd_post_incident_readback_plan.reviewer_checks.count", + len(k8s_argocd_post_incident_readback_plan["reviewer_checks"]), + 28, + ) + assert_equal( + "k8s_argocd_post_incident_readback_plan.outcome_lanes.count", + len(k8s_argocd_post_incident_readback_plan["outcome_lanes"]), + 10, + ) + assert_equal( + "k8s_argocd_post_incident_readback_plan.blocked_actions.count", + len(k8s_argocd_post_incident_readback_plan["blocked_actions"]), + 41, + ) + for item in k8s_argocd_post_incident_readback_plan["readback_candidates"]: + assert_equal( + f"k8s_argocd_post_incident_readback_plan.{item['post_incident_readback_candidate_id']}.readback_fields", + len(item["readback_fields"]), + 36, + ) + assert_equal( + f"k8s_argocd_post_incident_readback_plan.{item['post_incident_readback_candidate_id']}.required_readback_fields", + len(item["required_readback_fields"]), + 31, + ) + assert_equal( + f"k8s_argocd_post_incident_readback_plan.{item['post_incident_readback_candidate_id']}.reviewer_checks", + len(item["reviewer_checks"]), + 28, + ) + assert_equal( + f"k8s_argocd_post_incident_readback_plan.{item['post_incident_readback_candidate_id']}.outcome_lanes", + len(item["outcome_lanes"]), + 10, + ) + assert_equal( + f"k8s_argocd_post_incident_readback_plan.{item['post_incident_readback_candidate_id']}.blocked_actions", + len(item["blocked_actions"]), + 41, + ) + assert_true( + f"k8s_argocd_post_incident_readback_plan.{item['post_incident_readback_candidate_id']}.not_approval", + item["not_approval"], + ) + assert_true( + f"k8s_argocd_post_incident_readback_plan.{item['post_incident_readback_candidate_id']}.write_capable", + item["write_capable"], + ) + for false_key in [ + "post_incident_readback_received", + "post_incident_readback_accepted", + "actor_attribution_accepted", + "argocd_app_health_accepted", + "argocd_sync_status_accepted", + "degraded_state_accepted", + "pending_workload_accepted", + "image_pull_or_scheduling_accepted", + "rollout_before_after_accepted", + "event_summary_accepted", + "metrics_alert_accepted", + "drift_scanner_accepted", + "cronjob_schedule_accepted", + "network_policy_service_impact_accepted", + "rbac_serviceaccount_impact_accepted", + "secret_metadata_parity_accepted", + "public_admin_route_impact_accepted", + "ai_provider_monitoring_impact_accepted", + "backup_restore_impact_accepted", + "operator_notification_accepted", + "cross_project_sync_accepted", + "recovery_or_still_degraded_accepted", + "postcheck_readback_accepted", + "recurrence_guard_accepted", + "no_false_green_accepted", + "argocd_api_read_authorized", + "argocd_sync_authorized", + "live_cluster_read_authorized", + "kubectl_action_authorized", + "helm_action_authorized", + "network_policy_change_authorized", + "nodeport_change_authorized", + "rbac_change_authorized", + "secret_value_collection_allowed", + "route_smoke_authorized", + "production_write_authorized", + "runtime_gate", + "action_buttons_allowed", + ]: + assert_false( + f"k8s_argocd_post_incident_readback_plan.{item['post_incident_readback_candidate_id']}.{false_key}", + item[false_key], + ) assert_equal( "cd_runner_secret_injection_change_evidence_acceptance.schema", cd_runner_secret_injection_change_evidence_acceptance["schema_version"],