diff --git a/apps/web/messages/en.json b/apps/web/messages/en.json index 462fe4a13..e6da4568f 100644 --- a/apps/web/messages/en.json +++ b/apps/web/messages/en.json @@ -17772,8 +17772,8 @@ }, "items": { "nginxGateway": { - "title": "Nginx public gateway", - "body": "最優先控管公開入口、upstream、admin route、WebSocket、ACME 與 TLS;目前只有 repo-only preflight,live conf、rendered diff、nginx -t、route smoke、maintenance window 與 rollback owner 仍為 0。" + "title": "Nginx 公開入口", + "body": "最優先控管公開入口、上游服務、管理路由、WebSocket、ACME 與 TLS;手動或緊急變更回補已要求變更意圖、事前批准或緊急破窗理由、路由健康影響、回滾驗證與變更後監控窗口,但 live conf、rendered diff、nginx -t、route smoke、維護窗口與回滾負責人仍為 0。" }, "dnsTls": { "title": "DNS / TLS / certbot", @@ -17868,7 +17868,7 @@ }, "coverage": { "label": "平均成熟度", - "detail": "owner response acceptance 帳本推進後平均控管成熟度為 68%。" + "detail": "owner response acceptance 帳本推進後平均控管成熟度為 69%。" }, "runtimeGate": { "label": "執行期", diff --git a/apps/web/messages/zh-TW.json b/apps/web/messages/zh-TW.json index 462fe4a13..e6da4568f 100644 --- a/apps/web/messages/zh-TW.json +++ b/apps/web/messages/zh-TW.json @@ -17772,8 +17772,8 @@ }, "items": { "nginxGateway": { - "title": "Nginx public gateway", - "body": "最優先控管公開入口、upstream、admin route、WebSocket、ACME 與 TLS;目前只有 repo-only preflight,live conf、rendered diff、nginx -t、route smoke、maintenance window 與 rollback owner 仍為 0。" + "title": "Nginx 公開入口", + "body": "最優先控管公開入口、上游服務、管理路由、WebSocket、ACME 與 TLS;手動或緊急變更回補已要求變更意圖、事前批准或緊急破窗理由、路由健康影響、回滾驗證與變更後監控窗口,但 live conf、rendered diff、nginx -t、route smoke、維護窗口與回滾負責人仍為 0。" }, "dnsTls": { "title": "DNS / TLS / certbot", @@ -17868,7 +17868,7 @@ }, "coverage": { "label": "平均成熟度", - "detail": "owner response acceptance 帳本推進後平均控管成熟度為 68%。" + "detail": "owner response acceptance 帳本推進後平均控管成熟度為 69%。" }, "runtimeGate": { "label": "執行期", diff --git a/apps/web/src/app/[locale]/iwooos/page.tsx b/apps/web/src/app/[locale]/iwooos/page.tsx index a0553149f..6f8561498 100644 --- a/apps/web/src/app/[locale]/iwooos/page.tsx +++ b/apps/web/src/app/[locale]/iwooos/page.tsx @@ -2087,7 +2087,7 @@ const highValueConfigOwnerPacketSummary = [ const highValueConfigControlCoverageSummary = [ { key: 'categories', value: '14', icon: ListChecks, tone: 'steady' }, { key: 'c0', value: '8', icon: AlertTriangle, tone: 'warn' }, - { key: 'coverage', value: '68%', icon: ShieldCheck, tone: 'warn' }, + { key: 'coverage', value: '69%', icon: ShieldCheck, tone: 'warn' }, { key: 'runtimeGate', value: '0', icon: Lock, tone: 'locked' }, ] as const @@ -2104,14 +2104,18 @@ const highValueConfigControlCoverageBoundaries = [ 'high_value_config_control_coverage_category_count=14', 'high_value_config_control_coverage_c0_category_count=8', 'high_value_config_control_coverage_c1_category_count=4', - 'high_value_config_control_coverage_average_percent=68', + 'high_value_config_control_coverage_average_percent=69', 'high_value_config_control_coverage_needs_live_evidence_count=9', 'high_value_config_control_coverage_owner_response_required_count=14', 'high_value_config_control_coverage_owner_response_received_count=0', 'high_value_config_control_coverage_owner_response_accepted_count=0', 'high_value_config_control_coverage_runtime_gate_count=0', 'high_value_config_control_coverage_action_button_count=0', - 'nginx_public_gateway_coverage_percent=88', + 'nginx_public_gateway_coverage_percent=90', + 'public_gateway_owner_response_acceptance_required_owner_response_field_count=22', + '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', 'secret_metadata_coverage_percent=68', 'gitea_workflow_runner_source_control_coverage_percent=72', @@ -2341,7 +2345,7 @@ const criticalConfigPrioritySummary = [ ] as const const criticalConfigPriorityItems: CriticalConfigPriorityItem[] = [ - { key: 'nginxGateway', rank: 'P0-1', state: '88% / live 0', icon: Server, tone: 'warn' }, + { 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: 'workflowSecret', rank: 'P0-4', state: '68% / 72%', icon: GitBranch, tone: 'warn' }, diff --git a/docs/security/HIGH-VALUE-CONFIG-CONTROL-COVERAGE.md b/docs/security/HIGH-VALUE-CONFIG-CONTROL-COVERAGE.md index 280bea66d..795d9659a 100644 --- a/docs/security/HIGH-VALUE-CONFIG-CONTROL-COVERAGE.md +++ b/docs/security/HIGH-VALUE-CONFIG-CONTROL-COVERAGE.md @@ -62,7 +62,7 @@ 已新增 `docs/security/PUBLIC-GATEWAY-OWNER-RESPONSE-ACCEPTANCE.md` 與 `docs/security/public-gateway-owner-response-acceptance.snapshot.json`,將 Public Gateway live conf 匯出請求、redacted export 收件預檢與 rendered diff / `nginx -t` gate 草稿串成 owner response acceptance 只讀帳本。 -固定數字為 `acceptance_candidate_count=3`、`c0_acceptance_candidate_count=2`、`c1_acceptance_candidate_count=1`、`acceptance_field_count=27`、`required_owner_response_field_count=16`、`reviewer_check_count=16`、`outcome_lane_count=7`、`blocked_action_count=22`、`owner_response_received_count=0`、`owner_response_accepted_count=0`、`runtime_gate_count=0`。2026-06-15 已補手動 / 緊急 gateway 變更 metadata gate,要求 change actor/source、change time window、cross-project impact 與 communication sync 四欄脫敏 ref;此更新維持 `nginx_public_gateway=88%`,因為 live conf、rendered diff、`nginx -t`、reload、route smoke、DNS / TLS probe、certbot renew、maintenance window、rollback owner、runtime gate 與 action button 仍全部為 `0 / false`。 +固定數字為 `acceptance_candidate_count=3`、`c0_acceptance_candidate_count=2`、`c1_acceptance_candidate_count=1`、`acceptance_field_count=33`、`required_owner_response_field_count=22`、`reviewer_check_count=22`、`outcome_lane_count=8`、`blocked_action_count=28`、`owner_response_received_count=0`、`owner_response_accepted_count=0`、`runtime_gate_count=0`。2026-06-15 已補手動 / 緊急 gateway 變更 metadata gate,要求 change actor/source、change time window、cross-project impact、communication sync、change intent / ticket、pre-change approval 或 break-glass reason、route health impact、rollback validation 與 post-change monitoring window 的脫敏 ref;此更新讓 `nginx_public_gateway` 從 `88%` 推進到 `90%`,因為亂改 Nginx 後不再只看 owner 口頭回覆,而會要求事前意圖或事後 break-glass、健康影響、回滾驗證與監控窗口。不過 live conf、rendered diff、`nginx -t`、reload、route smoke、DNS / TLS probe、certbot renew、maintenance window、rollback owner、runtime gate 與 action button 仍全部為 `0 / false`。 2026-06-14 再新增 `docs/security/PUBLIC-GATEWAY-RENDERED-DIFF-ACCEPTANCE.md` 與 `docs/security/public-gateway-rendered-diff-acceptance.snapshot.json`,把 owner response acceptance 後的 rendered diff evidence、owner-provided `nginx -t` readback、route smoke evidence、TLS / ACME impact、maintenance window、rollback owner 與 post-check evidence 轉成只讀驗收帳本。 @@ -290,7 +290,7 @@ python3 scripts/security/iwooos-config-control-guard.py --root . `public_gateway_preflight_inventory_v1` 已把 Nginx public gateway reload / route change 前置 Gate 固定成只讀清冊,共 `3` 份 source config、`14` 個 route impact、`14` 個 unique upstream、`12` 個 preflight gate,其中 `2` 個 gate 只代表 repo-only ready,`10` 個 gate 仍需 owner acceptance。此更新讓 `nginx_public_gateway` 從 `78%` 推進到 `84%`;owner response、owner-provided live conf、rendered diff、`nginx -t` evidence、route smoke、maintenance window、rollback owner、runtime gate 與 action button 仍全部為 `0`。 -2026-06-14 再新增 `public_gateway_owner_response_acceptance_v1`,把 3 份 public gateway config 轉成 owner response acceptance 只讀帳本;2026-06-15 已強化手動 / 緊急 gateway 變更 metadata gate,固定 `acceptance_candidate_count=3`、`c0_acceptance_candidate_count=2`、`required_owner_response_field_count=16`、`reviewer_check_count=16`、`outcome_lane_count=7`、`blocked_action_count=22`。此更新要求 change actor/source、change time window、cross-project impact 與 communication sync 四欄脫敏 ref;`nginx_public_gateway` 仍維持 `88%`,因為 owner response received / accepted、redacted export received / accepted、rendered diff ready、`nginx -t`、reload、route smoke、DNS / TLS probe、certbot renew、runtime gate 與 action button 仍全部為 `0`。 +2026-06-14 再新增 `public_gateway_owner_response_acceptance_v1`,把 3 份 public gateway config 轉成 owner response acceptance 只讀帳本;2026-06-15 已強化手動 / 緊急 gateway 變更 metadata gate,固定 `acceptance_candidate_count=3`、`c0_acceptance_candidate_count=2`、`required_owner_response_field_count=22`、`reviewer_check_count=22`、`outcome_lane_count=8`、`blocked_action_count=28`。此更新要求 change actor/source、change time window、cross-project impact、communication sync、change intent / ticket、pre-change approval 或 break-glass reason、route health impact、rollback validation 與 post-change monitoring window 的脫敏 ref;`nginx_public_gateway` 從 `88%` 推進到 `90%`,因為亂改 Nginx 後不再只看 owner 口頭回覆,而會要求事前意圖或事後 break-glass、健康影響、回滾驗證與監控窗口。不過 owner response received / accepted、redacted export received / accepted、rendered diff ready、`nginx -t`、reload、route smoke、DNS / TLS probe、certbot renew、runtime gate 與 action button 仍全部為 `0`。 2026-06-14 再新增 `public_gateway_rendered_diff_acceptance_v1`,把 3 份 public gateway config 轉成 `diff_acceptance_candidate_count=3`、`c0_diff_acceptance_candidate_count=2`、`required_evidence_field_count=14`、`reviewer_check_count=15`、`outcome_lane_count=8`、`blocked_action_count=22` 的 rendered diff evidence acceptance 只讀帳本。此更新只讓 `nginx_public_gateway` 從 `86%` 推進到 `88%`;owner response accepted、rendered diff accepted、owner-provided `nginx -t` evidence accepted、route smoke evidence accepted、reload、DNS / TLS probe、certbot renew、runtime gate 與 action button 仍全部為 `0`。 diff --git a/docs/security/IWOOOS-CONFIG-CONTROL-INVENTORY.md b/docs/security/IWOOOS-CONFIG-CONTROL-INVENTORY.md index 21f605d8b..25d9cf0a1 100644 --- a/docs/security/IWOOOS-CONFIG-CONTROL-INVENTORY.md +++ b/docs/security/IWOOOS-CONFIG-CONTROL-INVENTORY.md @@ -105,7 +105,7 @@ 此更新仍不是 live gateway truth:owner response、owner-provided live conf、rendered diff、`nginx -t` evidence、route smoke、maintenance window、rollback owner 與 runtime gate 全部仍為 `0`,也不得 SSH、讀 live conf、執行 `nginx -t`、reload Nginx、改 public route、改 admin route、改 WebSocket / API route、改 ACME、做 DNS / TLS probe、執行 certbot renew 或寫入主機。 -2026-06-14 已新增 `public_gateway_owner_response_acceptance_v1`,把 3 份 Public Gateway config 轉成 owner response acceptance 只讀帳本。2026-06-15 已強化手動 / 緊急 gateway 變更 metadata gate,固定 `candidates=3`、`c0=2`、`owner_fields=16`、`reviewer_checks=16`、`outcome_lanes=7`、`blocked_actions=22`。此更新要求 owner response 必須能提供 change actor/source、change time window、cross-project impact 與 communication sync 四欄脫敏 ref;Nginx public gateway 類別成熟度仍維持 `88%`,因為 owner response received / accepted、redacted export、rendered diff、`nginx -t`、reload、route smoke、DNS / TLS probe、certbot renew、host write、runtime gate 仍全部為 `0 / false`。 +2026-06-14 已新增 `public_gateway_owner_response_acceptance_v1`,把 3 份 Public Gateway config 轉成 owner response acceptance 只讀帳本。2026-06-15 已強化手動 / 緊急 gateway 變更 metadata gate,固定 `candidates=3`、`c0=2`、`owner_fields=22`、`reviewer_checks=22`、`outcome_lanes=8`、`blocked_actions=28`。此更新要求 owner response 必須能提供 change actor/source、change time window、cross-project impact、communication sync、change intent / ticket、pre-change approval 或 break-glass reason、route health impact、rollback validation 與 post-change monitoring window 的脫敏 ref;Nginx public gateway 類別成熟度從 `88%` 推進到 `90%`,因為亂改 Nginx 後不再只看 owner 口頭回覆,而會要求事前意圖或事後 break-glass、健康影響、回滾驗證與監控窗口。不過 owner response received / accepted、redacted export、rendered diff、`nginx -t`、reload、route smoke、DNS / TLS probe、certbot renew、host write、runtime gate 仍全部為 `0 / false`。 2026-06-14 再新增 `public_gateway_rendered_diff_acceptance_v1`,把 3 份 Public Gateway config 轉成 rendered diff evidence acceptance 只讀帳本。固定 `candidates=3`、`c0=2`、`required_evidence_fields=14`、`reviewer_checks=15`、`outcome_lanes=8`、`blocked_actions=22`,讓 Nginx public gateway 類別成熟度從 `86%` 推進到 `88%`。此更新只表示未來 owner-provided rendered diff、`nginx -t` readback、route smoke evidence、TLS / ACME impact、maintenance window、rollback owner 與 post-check evidence 有收件驗收規則;owner response accepted、rendered diff accepted、nginx test evidence accepted、route smoke evidence accepted、reload、DNS / TLS probe、certbot renew、host write、runtime gate 仍全部為 `0 / false`。 diff --git a/docs/security/PUBLIC-GATEWAY-OWNER-RESPONSE-ACCEPTANCE.md b/docs/security/PUBLIC-GATEWAY-OWNER-RESPONSE-ACCEPTANCE.md index 5025f4929..036457dd8 100644 --- a/docs/security/PUBLIC-GATEWAY-OWNER-RESPONSE-ACCEPTANCE.md +++ b/docs/security/PUBLIC-GATEWAY-OWNER-RESPONSE-ACCEPTANCE.md @@ -15,7 +15,7 @@ 本階段不讀 live Nginx conf、不 SSH、不執行 `nginx -t`、不 reload Nginx、不做 route smoke、不做 DNS / TLS probe、不 renew certbot、不改 Nginx / DNS / TLS 設定、不寫 production host、不開 action button。 -2026-06-15 起,本帳本也負責處理手動或緊急 Public Gateway 變更的最小可追溯 metadata。任何疑似未授權 Nginx / route / upstream / port / proxy 變更,都必須先補脫敏 change actor/source ref、change time window、cross-project impact ref 與 communication sync ref;這些欄位只用於責任、影響與回復追蹤,不代表允許讀 live conf、reload 或改 route。 +2026-06-15 起,本帳本也負責處理手動或緊急 Public Gateway 變更的最小可追溯 metadata。任何疑似未授權 Nginx / route / upstream / port / proxy 變更,都必須先補脫敏 change actor/source ref、change time window、cross-project impact ref、communication sync ref、change intent / ticket ref、pre-change approval 或 break-glass reason ref、route health impact ref、rollback validation ref 與 post-change monitoring window;這些欄位只用於責任、影響與回復追蹤,不代表允許讀 live conf、reload 或改 route。 ## 2. 摘要 @@ -26,11 +26,11 @@ | source diff gate candidate | `3` | 來自 rendered diff gate 草稿 | | acceptance candidate | `3` | 對應三份 public gateway config | | C0 / C1 acceptance candidate | `2 / 1` | 188 公開入口兩份為 C0,110 Ollama proxy 為 C1 | -| acceptance field | `27` | 每份 acceptance candidate 固定欄位數 | -| required owner response field | `16` | owner 必須提供的最小欄位 | -| reviewer check | `16` | reviewer 收件前必檢項 | -| outcome lane | `7` | 等待、隔離、拒收、補件、review、只讀更新、等待 runtime gate | -| blocked action | `22` | 驗收前全部禁止 | +| acceptance field | `33` | 每份 acceptance candidate 固定欄位數 | +| required owner response field | `22` | owner 必須提供的最小欄位 | +| reviewer check | `22` | reviewer 收件前必檢項 | +| outcome lane | `8` | 等待、隔離、拒收、補件、review、只讀更新、緊急變更補件、等待 runtime gate | +| blocked action | `28` | 驗收前全部禁止 | | owner response received / accepted | `0 / 0` | 不得假性拉高 | | rendered diff / `nginx -t` / reload / route smoke | `0` | 未授權且未執行 | | runtime gate / action button | `0 / 0` | 不開任何執行入口 | @@ -54,6 +54,12 @@ | `change_time_window` | 變更或事故時間窗,讓 route smoke、告警與跨專案影響能對齊 | | `cross_project_impact_ref` | 跨產品 / 跨專案影響 ref,避免只修單一路由卻造成其他服務中斷 | | `communication_sync_ref` | 通知或協調 ref,證明相關專案 owner 已收到影響與回復狀態 | +| `change_intent_or_ticket_ref` | 變更意圖、維護單、事故單或 ticket ref;不得只用聊天口頭同意 | +| `pre_change_approval_ref` | 正常變更的事前批准 ref;緊急變更不得用此欄偽造批准 | +| `break_glass_reason_ref` | 緊急變更的 break-glass 事由 ref;只代表事後補件,不代表已批准 | +| `route_health_impact_ref` | route health / service health impact ref,需能對齊 affected routes | +| `rollback_validation_ref` | rollback validation ref,需能追溯 rollback owner 與回滾後驗證方式 | +| `post_change_monitoring_window` | 事後觀察窗口,讓告警、route smoke 與跨專案回復狀態能對齊 | | `followup_owner` | 補件、隔離、拒收或下一步 review owner | ## 4. Reviewer Checks @@ -75,6 +81,12 @@ | `change_time_window_present` | 必須提供變更或事故時間窗 | | `cross_project_impact_review_present` | 必須提供跨產品 / 跨專案影響 ref | | `communication_sync_ref_present` | 必須提供通知或協調 ref | +| `change_intent_or_ticket_ref_present` | 每次 Public Gateway / Nginx 變更都必須有 change intent、ticket、incident 或 maintenance ref | +| `pre_change_approval_or_break_glass_present` | 正常變更需有 pre-change approval ref;緊急變更需有 break-glass reason ref,且不得把 break-glass 當成事前批准 | +| `route_health_impact_present` | 必須提供 route health / service health impact ref,確認受影響 domain、upstream、WebSocket、ACME 與 API 是否恢復 | +| `rollback_validation_present` | 必須提供 rollback validation ref,證明回滾路徑、回滾 owner 與回滾後驗證方式可追溯 | +| `post_change_monitoring_window_present` | 必須提供 post-change monitoring window | +| `manual_change_not_silent` | 任何手動或緊急 gateway 變更不得靜默收件;缺 actor、意圖、影響、通知或回滾驗證就必須補件或拒收 | | `counts_transition_safe` | 只有 reviewer record 可更新 received / accepted / rejected;不得同時開 runtime gate | ## 5. Outcome Lanes @@ -87,6 +99,7 @@ | `request_supplement` | 欄位不足、scope 不清或 evidence ref 不可追溯時要求補件 | | `ready_for_rendered_diff_review` | metadata 合格後,只能進 rendered diff reviewer review | | `owner_review_only_update` | 只允許更新只讀 owner review ledger | +| `emergency_change_backfill_required` | 手動或緊急 gateway 變更只能進事後補件,不得因 break-glass 而自動接受或開 runtime gate | | `waiting_runtime_gate` | 即使 owner response accepted,runtime gate 仍等待獨立人工批准 | ## 6. Blocked Actions @@ -112,6 +125,12 @@ accept_unknown_change_actor accept_missing_change_time_window skip_cross_project_impact_review skip_incident_communication_sync +accept_silent_manual_nginx_change +treat_break_glass_as_approval +mark_gateway_change_resolved_without_route_health +skip_rollback_validation +skip_post_change_monitoring +hide_cross_project_route_impact open_runtime_gate add_action_button ``` @@ -124,7 +143,7 @@ add_action_button python3 scripts/security/public-gateway-owner-response-acceptance.py \ --root . \ --output docs/security/public-gateway-owner-response-acceptance.snapshot.json \ - --generated-at 2026-06-15T08:18:00+08:00 + --generated-at 2026-06-15T14:10:00+08:00 ``` 只讀 guard: @@ -139,7 +158,7 @@ python3 scripts/security/source-control-owner-response-guard.py --root . | 工作 | 完成度 | 說明 | |------|--------|------| | owner response acceptance ledger artifact | `100%` | 3 份 public gateway config 已有只讀收件判定帳本 | -| 手動 / 緊急 gateway 變更 metadata gate | `100%` | 已要求 actor/source、time window、cross-project impact、communication sync 四欄 metadata;不收 raw payload | +| 手動 / 緊急 gateway 變更 metadata gate | `100%` | 已要求 actor/source、time window、cross-project impact、communication sync、change intent、approval / break-glass、route health impact、rollback validation 與 post-change monitoring;不收 raw payload | | owner response received / accepted | `0%` | 尚未收到或接受任何 owner response | | rendered diff / `nginx -t` / reload / route smoke | `0%` | 未授權且未執行 | | DNS / TLS / certbot | `0%` | 未授權且未執行 | diff --git a/docs/security/SECURITY-SUPPLY-CHAIN-PROGRESS.md b/docs/security/SECURITY-SUPPLY-CHAIN-PROGRESS.md index d2f1e57a2..109f9c4ef 100644 --- a/docs/security/SECURITY-SUPPLY-CHAIN-PROGRESS.md +++ b/docs/security/SECURITY-SUPPLY-CHAIN-PROGRESS.md @@ -7,7 +7,7 @@ | 本階段完成 | 資安供應鏈 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=12 / checks=12 / lanes=7 / blocked=18 / accepted=0 / runtime=0`;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、內部狀態碼與內部協作內容外洩列為拒收 / 隔離;Backup / Restore / Escrow owner response acceptance 只讀帳本已新增 `candidates=38 / write_capable=27 / fields=14 / checks=13 / lanes=7 / blocked=22 / 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`;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、內部狀態碼與內部協作內容外洩列為拒收 / 隔離;Backup / Restore / Escrow owner response acceptance 只讀帳本已新增 `candidates=38 / write_capable=27 / fields=14 / checks=13 / lanes=7 / blocked=22 / 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`;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 / reviewer_checks=13 / lanes=7 / blocked=22 / 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=30 / owner_fields=14 / reviewer_checks=15 / lanes=7 / blocked=28 / accepted=0 / runtime=0`;上述全部仍是人工送件前草稿或只讀 acceptance 帳本,不是 owner response、live evidence、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、不部署 | diff --git a/docs/security/high-value-config-control-coverage.snapshot.json b/docs/security/high-value-config-control-coverage.snapshot.json index b31e7370d..fcdacb4ed 100644 --- a/docs/security/high-value-config-control-coverage.snapshot.json +++ b/docs/security/high-value-config-control-coverage.snapshot.json @@ -4,9 +4,9 @@ "action_buttons_allowed": false, "category_id": "nginx_public_gateway", "control_tier": "C0", - "coverage_percent": 88, - "coverage_status": "rendered_diff_acceptance_ledger_ready_needs_owner_live_diff", - "current_gap": "已固定 owner response acceptance 與 rendered diff evidence acceptance 只讀帳本;owner response、live conf、rendered diff evidence、nginx -t evidence、route smoke evidence、maintenance window 與 rollback owner 仍全部為 0。", + "coverage_percent": 90, + "coverage_status": "emergency_change_backfill_ready_needs_owner_live_diff", + "current_gap": "已固定 owner response acceptance、手動 / 緊急 gateway 變更回補欄位與 rendered diff evidence acceptance 只讀帳本;owner response、live conf、rendered diff evidence、nginx -t evidence、route smoke evidence、maintenance window 與 rollback owner 仍全部為 0。", "evidence_refs": [ "docs/security/NGINX-CONFIG-DRIFT-DETECTOR.md", "docs/security/nginx-config-drift-repo.snapshot.json", @@ -20,7 +20,7 @@ "docs/schemas/public_gateway_preflight_inventory_v1.schema.json" ], "label": "Nginx / reverse proxy / public route", - "next_owner_action": "補 public gateway owner 回覆、owner-provided live conf、source-to-live rendered diff ref、nginx -t evidence ref、route smoke evidence ref、maintenance window 與 rollback owner。", + "next_owner_action": "補 public gateway owner 回覆、owner-provided live conf、source-to-live rendered diff ref、nginx -t evidence ref、route smoke evidence ref、change intent / break-glass、route health impact、rollback validation、maintenance window 與 rollback owner。", "owner_response_accepted": false, "owner_response_received": false, "owner_response_required": true, @@ -634,8 +634,8 @@ "websocket_route_change_authorized": false, "workflow_modification_authorized": false }, - "generated_at": "2026-06-15T10:08:00+08:00", - "git_commit": "952c9288", + "generated_at": "2026-06-15T14:12:00+08:00", + "git_commit": "ed8c1905", "lowest_coverage_categories": [ { "category_id": "docker_compose_systemd_host_config", diff --git a/docs/security/public-gateway-owner-response-acceptance.snapshot.json b/docs/security/public-gateway-owner-response-acceptance.snapshot.json index 4407c7827..70f8cb7c8 100644 --- a/docs/security/public-gateway-owner-response-acceptance.snapshot.json +++ b/docs/security/public-gateway-owner-response-acceptance.snapshot.json @@ -27,6 +27,12 @@ "change_time_window", "cross_project_impact_ref", "communication_sync_ref", + "change_intent_or_ticket_ref", + "pre_change_approval_ref", + "break_glass_reason_ref", + "route_health_impact_ref", + "rollback_validation_ref", + "post_change_monitoring_window", "reviewer_outcome", "followup_owner", "not_approval" @@ -55,11 +61,19 @@ "accept_missing_change_time_window", "skip_cross_project_impact_review", "skip_incident_communication_sync", + "accept_silent_manual_nginx_change", + "treat_break_glass_as_approval", + "mark_gateway_change_resolved_without_route_health", + "skip_rollback_validation", + "skip_post_change_monitoring", + "hide_cross_project_route_impact", "open_runtime_gate", "add_action_button" ], + "break_glass_reason_ref": null, "certbot_renew_authorized": false, "change_actor_or_source_ref": null, + "change_intent_or_ticket_ref": null, "change_time_window": "pending_owner_response", "communication_sync_ref": null, "config_id": "host188_all_sites", @@ -89,6 +103,7 @@ "request_supplement", "ready_for_rendered_diff_review", "owner_review_only_update", + "emergency_change_backfill_required", "waiting_runtime_gate" ], "owner_response_accepted": false, @@ -97,7 +112,9 @@ "owner_response_ref": null, "owner_response_rejected": false, "owner_role_or_team": "pending_owner_response", + "post_change_monitoring_window": "pending_owner_response", "postcheck_plan": "pending_owner_response", + "pre_change_approval_ref": null, "production_write_authorized": false, "recipient_confirmed": false, "redacted_export_received": false, @@ -121,6 +138,12 @@ "change_time_window", "cross_project_impact_ref", "communication_sync_ref", + "change_intent_or_ticket_ref", + "pre_change_approval_ref", + "break_glass_reason_ref", + "route_health_impact_ref", + "rollback_validation_ref", + "post_change_monitoring_window", "followup_owner" ], "reviewer_checks": [ @@ -139,11 +162,19 @@ "change_time_window_present", "cross_project_impact_review_present", "communication_sync_ref_present", + "change_intent_or_ticket_ref_present", + "pre_change_approval_or_break_glass_present", + "route_health_impact_present", + "rollback_validation_present", + "post_change_monitoring_window_present", + "manual_change_not_silent", "counts_transition_safe" ], "reviewer_outcome": "waiting_owner_response", "rollback_owner": "pending_owner_response", "rollback_owner_accepted": false, + "rollback_validation_ref": null, + "route_health_impact_ref": null, "route_smoke_authorized": false, "route_smoke_executed": false, "route_smoke_plan_ref": null, @@ -179,6 +210,12 @@ "change_time_window", "cross_project_impact_ref", "communication_sync_ref", + "change_intent_or_ticket_ref", + "pre_change_approval_ref", + "break_glass_reason_ref", + "route_health_impact_ref", + "rollback_validation_ref", + "post_change_monitoring_window", "reviewer_outcome", "followup_owner", "not_approval" @@ -207,11 +244,19 @@ "accept_missing_change_time_window", "skip_cross_project_impact_review", "skip_incident_communication_sync", + "accept_silent_manual_nginx_change", + "treat_break_glass_as_approval", + "mark_gateway_change_resolved_without_route_health", + "skip_rollback_validation", + "skip_post_change_monitoring", + "hide_cross_project_route_impact", "open_runtime_gate", "add_action_button" ], + "break_glass_reason_ref": null, "certbot_renew_authorized": false, "change_actor_or_source_ref": null, + "change_intent_or_ticket_ref": null, "change_time_window": "pending_owner_response", "communication_sync_ref": null, "config_id": "host188_internal_tools_https", @@ -241,6 +286,7 @@ "request_supplement", "ready_for_rendered_diff_review", "owner_review_only_update", + "emergency_change_backfill_required", "waiting_runtime_gate" ], "owner_response_accepted": false, @@ -249,7 +295,9 @@ "owner_response_ref": null, "owner_response_rejected": false, "owner_role_or_team": "pending_owner_response", + "post_change_monitoring_window": "pending_owner_response", "postcheck_plan": "pending_owner_response", + "pre_change_approval_ref": null, "production_write_authorized": false, "recipient_confirmed": false, "redacted_export_received": false, @@ -273,6 +321,12 @@ "change_time_window", "cross_project_impact_ref", "communication_sync_ref", + "change_intent_or_ticket_ref", + "pre_change_approval_ref", + "break_glass_reason_ref", + "route_health_impact_ref", + "rollback_validation_ref", + "post_change_monitoring_window", "followup_owner" ], "reviewer_checks": [ @@ -291,11 +345,19 @@ "change_time_window_present", "cross_project_impact_review_present", "communication_sync_ref_present", + "change_intent_or_ticket_ref_present", + "pre_change_approval_or_break_glass_present", + "route_health_impact_present", + "rollback_validation_present", + "post_change_monitoring_window_present", + "manual_change_not_silent", "counts_transition_safe" ], "reviewer_outcome": "waiting_owner_response", "rollback_owner": "pending_owner_response", "rollback_owner_accepted": false, + "rollback_validation_ref": null, + "route_health_impact_ref": null, "route_smoke_authorized": false, "route_smoke_executed": false, "route_smoke_plan_ref": null, @@ -331,6 +393,12 @@ "change_time_window", "cross_project_impact_ref", "communication_sync_ref", + "change_intent_or_ticket_ref", + "pre_change_approval_ref", + "break_glass_reason_ref", + "route_health_impact_ref", + "rollback_validation_ref", + "post_change_monitoring_window", "reviewer_outcome", "followup_owner", "not_approval" @@ -359,11 +427,19 @@ "accept_missing_change_time_window", "skip_cross_project_impact_review", "skip_incident_communication_sync", + "accept_silent_manual_nginx_change", + "treat_break_glass_as_approval", + "mark_gateway_change_resolved_without_route_health", + "skip_rollback_validation", + "skip_post_change_monitoring", + "hide_cross_project_route_impact", "open_runtime_gate", "add_action_button" ], + "break_glass_reason_ref": null, "certbot_renew_authorized": false, "change_actor_or_source_ref": null, + "change_intent_or_ticket_ref": null, "change_time_window": "pending_owner_response", "communication_sync_ref": null, "config_id": "host110_ollama_proxy", @@ -393,6 +469,7 @@ "request_supplement", "ready_for_rendered_diff_review", "owner_review_only_update", + "emergency_change_backfill_required", "waiting_runtime_gate" ], "owner_response_accepted": false, @@ -401,7 +478,9 @@ "owner_response_ref": null, "owner_response_rejected": false, "owner_role_or_team": "pending_owner_response", + "post_change_monitoring_window": "pending_owner_response", "postcheck_plan": "pending_owner_response", + "pre_change_approval_ref": null, "production_write_authorized": false, "recipient_confirmed": false, "redacted_export_received": false, @@ -425,6 +504,12 @@ "change_time_window", "cross_project_impact_ref", "communication_sync_ref", + "change_intent_or_ticket_ref", + "pre_change_approval_ref", + "break_glass_reason_ref", + "route_health_impact_ref", + "rollback_validation_ref", + "post_change_monitoring_window", "followup_owner" ], "reviewer_checks": [ @@ -443,11 +528,19 @@ "change_time_window_present", "cross_project_impact_review_present", "communication_sync_ref_present", + "change_intent_or_ticket_ref_present", + "pre_change_approval_or_break_glass_present", + "route_health_impact_present", + "rollback_validation_present", + "post_change_monitoring_window_present", + "manual_change_not_silent", "counts_transition_safe" ], "reviewer_outcome": "waiting_owner_response", "rollback_owner": "pending_owner_response", "rollback_owner_accepted": false, + "rollback_validation_ref": null, + "route_health_impact_ref": null, "route_smoke_authorized": false, "route_smoke_executed": false, "route_smoke_plan_ref": null, @@ -482,6 +575,12 @@ "change_time_window", "cross_project_impact_ref", "communication_sync_ref", + "change_intent_or_ticket_ref", + "pre_change_approval_ref", + "break_glass_reason_ref", + "route_health_impact_ref", + "rollback_validation_ref", + "post_change_monitoring_window", "reviewer_outcome", "followup_owner", "not_approval" @@ -507,6 +606,12 @@ "accept_missing_change_time_window", "skip_cross_project_impact_review", "skip_incident_communication_sync", + "accept_silent_manual_nginx_change", + "treat_break_glass_as_approval", + "mark_gateway_change_resolved_without_route_health", + "skip_rollback_validation", + "skip_post_change_monitoring", + "hide_cross_project_route_impact", "open_runtime_gate", "add_action_button" ], @@ -530,13 +635,13 @@ "runtime_execution_authorized": false, "secret_value_collection_allowed": false }, - "generated_at": "2026-06-15T08:18:00+08:00", - "git_commit": "04728d36", + "generated_at": "2026-06-15T14:10:00+08:00", + "git_commit": "ed8c1905", "next_steps": [ "等待 owner response;未收到前不得更新 accepted count。", "收到回覆後先走 raw payload / secret / scope / evidence ref 檢查,不合格即隔離、拒收或補件。", "metadata 合格也只能進 rendered diff reviewer review;`nginx -t`、reload、route smoke 與 production write 仍需獨立人工批准。", - "若涉及手動或緊急 gateway 變更,必須先補 change actor/source、time window、cross-project impact 與 communication sync refs。" + "若涉及手動或緊急 gateway 變更,必須先補 change actor/source、time window、cross-project impact、communication sync、change intent、break-glass reason、route health impact、rollback validation 與 post-change monitoring refs。" ], "outcome_lanes": [ { @@ -563,6 +668,10 @@ "lane_id": "owner_review_only_update", "meaning": "只允許更新只讀 owner review ledger,不得修改 Nginx、DNS、TLS 或 workflow。" }, + { + "lane_id": "emergency_change_backfill_required", + "meaning": "手動或緊急 gateway 變更只能進事後補件,不得因 break-glass 而自動接受或開 runtime gate。" + }, { "lane_id": "waiting_runtime_gate", "meaning": "即使 owner response accepted,runtime gate 仍等待獨立人工批准。" @@ -584,6 +693,12 @@ "change_time_window", "cross_project_impact_ref", "communication_sync_ref", + "change_intent_or_ticket_ref", + "pre_change_approval_ref", + "break_glass_reason_ref", + "route_health_impact_ref", + "rollback_validation_ref", + "post_change_monitoring_window", "followup_owner" ], "reviewer_checks": [ @@ -647,6 +762,30 @@ "check_id": "communication_sync_ref_present", "instruction": "必須提供通知或協調 ref,證明相關專案 owner 已收到影響與回復狀態。" }, + { + "check_id": "change_intent_or_ticket_ref_present", + "instruction": "每次 Public Gateway / Nginx 變更都必須有 change intent、ticket、incident 或 maintenance ref,不接受口頭或聊天截圖當唯一依據。" + }, + { + "check_id": "pre_change_approval_or_break_glass_present", + "instruction": "正常變更需有 pre-change approval ref;緊急變更需有 break-glass reason ref,且不得把 break-glass 當成事前批准。" + }, + { + "check_id": "route_health_impact_present", + "instruction": "必須提供 route health / service health impact ref,確認受影響 domain、upstream、WebSocket、ACME 與 API 是否恢復。" + }, + { + "check_id": "rollback_validation_present", + "instruction": "必須提供 rollback validation ref,證明回滾路徑、回滾 owner 與回滾後驗證方式可追溯。" + }, + { + "check_id": "post_change_monitoring_window_present", + "instruction": "必須提供 post-change monitoring window,讓告警、route smoke 與跨專案回復狀態能對齊。" + }, + { + "check_id": "manual_change_not_silent", + "instruction": "任何手動或緊急 gateway 變更不得靜默收件;若缺 actor、意圖、影響、通知或回滾驗證,必須走補件或拒收。" + }, { "check_id": "counts_transition_safe", "instruction": "只有 reviewer record 可更新 received / accepted / rejected;不得同時開 runtime gate。" @@ -662,14 +801,16 @@ "status": "owner_response_acceptance_ledger_ready_no_runtime_action", "summary": { "acceptance_candidate_count": 3, - "acceptance_field_count": 27, + "acceptance_field_count": 33, "accepted_redacted_export_count": 0, "action_button_count": 0, - "blocked_action_count": 22, + "blocked_action_count": 28, + "break_glass_reason_accepted_count": 0, "c0_acceptance_candidate_count": 2, "c1_acceptance_candidate_count": 1, "certbot_renew_authorized_count": 0, "change_actor_identified_count": 0, + "change_intent_accepted_count": 0, "change_time_window_accepted_count": 0, "communication_sync_accepted_count": 0, "cross_project_impact_accepted_count": 0, @@ -679,19 +820,23 @@ "nginx_reload_executed_count": 0, "nginx_test_authorized_count": 0, "nginx_test_executed_count": 0, - "outcome_lane_count": 7, + "outcome_lane_count": 8, "owner_response_accepted_count": 0, "owner_response_quarantined_count": 0, "owner_response_received_count": 0, "owner_response_rejected_count": 0, + "post_change_monitoring_window_accepted_count": 0, + "pre_change_approval_accepted_count": 0, "recipient_confirmed_count": 0, "redacted_export_received_count": 0, "rendered_diff_candidate_count": 0, "rendered_diff_ready_count": 0, "request_sent_count": 0, - "required_owner_response_field_count": 16, - "reviewer_check_count": 16, + "required_owner_response_field_count": 22, + "reviewer_check_count": 22, "rollback_owner_accepted_count": 0, + "rollback_validation_accepted_count": 0, + "route_health_impact_accepted_count": 0, "route_smoke_authorized_count": 0, "route_smoke_executed_count": 0, "runtime_gate_count": 0, diff --git a/scripts/security/high-value-config-control-coverage.py b/scripts/security/high-value-config-control-coverage.py index 98c556b80..1df41f6d2 100644 --- a/scripts/security/high-value-config-control-coverage.py +++ b/scripts/security/high-value-config-control-coverage.py @@ -24,8 +24,8 @@ TAIPEI = timezone(timedelta(hours=8)) CONTROL_STATUS_BY_CATEGORY = { "nginx_public_gateway": { - "coverage_status": "rendered_diff_acceptance_ledger_ready_needs_owner_live_diff", - "coverage_percent": 88, + "coverage_status": "emergency_change_backfill_ready_needs_owner_live_diff", + "coverage_percent": 90, "evidence_refs": [ "docs/security/NGINX-CONFIG-DRIFT-DETECTOR.md", "docs/security/nginx-config-drift-repo.snapshot.json", @@ -38,8 +38,8 @@ CONTROL_STATUS_BY_CATEGORY = { "docs/security/public-gateway-rendered-diff-acceptance.snapshot.json", "docs/schemas/public_gateway_preflight_inventory_v1.schema.json", ], - "current_gap": "已固定 owner response acceptance 與 rendered diff evidence acceptance 只讀帳本;owner response、live conf、rendered diff evidence、nginx -t evidence、route smoke evidence、maintenance window 與 rollback owner 仍全部為 0。", - "next_owner_action": "補 public gateway owner 回覆、owner-provided live conf、source-to-live rendered diff ref、nginx -t evidence ref、route smoke evidence ref、maintenance window 與 rollback owner。", + "current_gap": "已固定 owner response acceptance、手動 / 緊急 gateway 變更回補欄位與 rendered diff evidence acceptance 只讀帳本;owner response、live conf、rendered diff evidence、nginx -t evidence、route smoke evidence、maintenance window 與 rollback owner 仍全部為 0。", + "next_owner_action": "補 public gateway owner 回覆、owner-provided live conf、source-to-live rendered diff ref、nginx -t evidence ref、route smoke evidence ref、change intent / break-glass、route health impact、rollback validation、maintenance window 與 rollback owner。", }, "dns_tls_certbot": { "coverage_status": "owner_response_acceptance_ledger_ready_needs_certificate_owner_evidence", @@ -370,6 +370,7 @@ def build_report(root: Path, generated_at: str | None) -> dict[str, Any]: "repo_only_preflight_contract_ready_needs_owner_live_diff", "owner_response_acceptance_ledger_ready_needs_owner_live_diff", "rendered_diff_acceptance_ledger_ready_needs_owner_live_diff", + "emergency_change_backfill_ready_needs_owner_live_diff", "owner_response_acceptance_ledger_ready_needs_runtime_evidence", "change_evidence_acceptance_ready_needs_gitops_owner_evidence", "secret_injection_change_evidence_acceptance_ready_needs_owner_evidence", diff --git a/scripts/security/iwooos-config-control-guard.py b/scripts/security/iwooos-config-control-guard.py index 16ff25450..107387f64 100644 --- a/scripts/security/iwooos-config-control-guard.py +++ b/scripts/security/iwooos-config-control-guard.py @@ -17,7 +17,7 @@ from typing import Any EXPECTED_CATEGORIES = { - "nginx_public_gateway": 88, + "nginx_public_gateway": 90, "dns_tls_certbot": 78, "k8s_production_gitops": 64, "secret_metadata": 68, @@ -112,10 +112,10 @@ ARTIFACT_SPECS = [ "status": "owner_response_acceptance_ledger_ready_no_runtime_action", "list_counts": { "acceptance_candidates": 3, - "blocked_actions": 22, - "reviewer_checks": 16, - "outcome_lanes": 7, - "required_owner_response_fields": 16, + "blocked_actions": 28, + "reviewer_checks": 22, + "outcome_lanes": 8, + "required_owner_response_fields": 22, }, "summary_counts": { "acceptance_candidate_count": 3, diff --git a/scripts/security/public-gateway-owner-response-acceptance.py b/scripts/security/public-gateway-owner-response-acceptance.py index da4738008..1530ab673 100644 --- a/scripts/security/public-gateway-owner-response-acceptance.py +++ b/scripts/security/public-gateway-owner-response-acceptance.py @@ -46,6 +46,12 @@ ACCEPTANCE_FIELDS = [ "change_time_window", "cross_project_impact_ref", "communication_sync_ref", + "change_intent_or_ticket_ref", + "pre_change_approval_ref", + "break_glass_reason_ref", + "route_health_impact_ref", + "rollback_validation_ref", + "post_change_monitoring_window", "reviewer_outcome", "followup_owner", "not_approval", @@ -67,6 +73,12 @@ REQUIRED_OWNER_RESPONSE_FIELDS = [ "change_time_window", "cross_project_impact_ref", "communication_sync_ref", + "change_intent_or_ticket_ref", + "pre_change_approval_ref", + "break_glass_reason_ref", + "route_health_impact_ref", + "rollback_validation_ref", + "post_change_monitoring_window", "followup_owner", ] @@ -131,6 +143,30 @@ REVIEWER_CHECKS = [ "check_id": "communication_sync_ref_present", "instruction": "必須提供通知或協調 ref,證明相關專案 owner 已收到影響與回復狀態。", }, + { + "check_id": "change_intent_or_ticket_ref_present", + "instruction": "每次 Public Gateway / Nginx 變更都必須有 change intent、ticket、incident 或 maintenance ref,不接受口頭或聊天截圖當唯一依據。", + }, + { + "check_id": "pre_change_approval_or_break_glass_present", + "instruction": "正常變更需有 pre-change approval ref;緊急變更需有 break-glass reason ref,且不得把 break-glass 當成事前批准。", + }, + { + "check_id": "route_health_impact_present", + "instruction": "必須提供 route health / service health impact ref,確認受影響 domain、upstream、WebSocket、ACME 與 API 是否恢復。", + }, + { + "check_id": "rollback_validation_present", + "instruction": "必須提供 rollback validation ref,證明回滾路徑、回滾 owner 與回滾後驗證方式可追溯。", + }, + { + "check_id": "post_change_monitoring_window_present", + "instruction": "必須提供 post-change monitoring window,讓告警、route smoke 與跨專案回復狀態能對齊。", + }, + { + "check_id": "manual_change_not_silent", + "instruction": "任何手動或緊急 gateway 變更不得靜默收件;若缺 actor、意圖、影響、通知或回滾驗證,必須走補件或拒收。", + }, { "check_id": "counts_transition_safe", "instruction": "只有 reviewer record 可更新 received / accepted / rejected;不得同時開 runtime gate。", @@ -162,6 +198,10 @@ OUTCOME_LANES = [ "lane_id": "owner_review_only_update", "meaning": "只允許更新只讀 owner review ledger,不得修改 Nginx、DNS、TLS 或 workflow。", }, + { + "lane_id": "emergency_change_backfill_required", + "meaning": "手動或緊急 gateway 變更只能進事後補件,不得因 break-glass 而自動接受或開 runtime gate。", + }, { "lane_id": "waiting_runtime_gate", "meaning": "即使 owner response accepted,runtime gate 仍等待獨立人工批准。", @@ -189,6 +229,12 @@ BLOCKED_ACTIONS = [ "accept_missing_change_time_window", "skip_cross_project_impact_review", "skip_incident_communication_sync", + "accept_silent_manual_nginx_change", + "treat_break_glass_as_approval", + "mark_gateway_change_resolved_without_route_health", + "skip_rollback_validation", + "skip_post_change_monitoring", + "hide_cross_project_route_impact", "open_runtime_gate", "add_action_button", ] @@ -240,6 +286,12 @@ def acceptance_candidate(diff_gate: dict[str, Any]) -> dict[str, Any]: "change_time_window": "pending_owner_response", "cross_project_impact_ref": None, "communication_sync_ref": None, + "change_intent_or_ticket_ref": None, + "pre_change_approval_ref": None, + "break_glass_reason_ref": None, + "route_health_impact_ref": None, + "rollback_validation_ref": None, + "post_change_monitoring_window": "pending_owner_response", "reviewer_outcome": "waiting_owner_response", "followup_owner": "pending_owner_response", "acceptance_fields": ACCEPTANCE_FIELDS, @@ -336,6 +388,12 @@ def build_report( "change_time_window_accepted_count": 0, "cross_project_impact_accepted_count": 0, "communication_sync_accepted_count": 0, + "change_intent_accepted_count": 0, + "pre_change_approval_accepted_count": 0, + "break_glass_reason_accepted_count": 0, + "route_health_impact_accepted_count": 0, + "rollback_validation_accepted_count": 0, + "post_change_monitoring_window_accepted_count": 0, "runtime_gate_count": 0, "action_button_count": 0, }, @@ -369,7 +427,7 @@ def build_report( "等待 owner response;未收到前不得更新 accepted count。", "收到回覆後先走 raw payload / secret / scope / evidence ref 檢查,不合格即隔離、拒收或補件。", "metadata 合格也只能進 rendered diff reviewer review;`nginx -t`、reload、route smoke 與 production write 仍需獨立人工批准。", - "若涉及手動或緊急 gateway 變更,必須先補 change actor/source、time window、cross-project impact 與 communication sync refs。", + "若涉及手動或緊急 gateway 變更,必須先補 change actor/source、time window、cross-project impact、communication sync、change intent、break-glass reason、route health impact、rollback validation 與 post-change monitoring refs。", ], } diff --git a/scripts/security/security-mirror-progress-guard.py b/scripts/security/security-mirror-progress-guard.py index 1e20fe934..d35b411fb 100755 --- a/scripts/security/security-mirror-progress-guard.py +++ b/scripts/security/security-mirror-progress-guard.py @@ -2988,12 +2988,12 @@ def validate(root: Path) -> None: assert_equal( "high_value_config_coverage.coverage_categories.nginx.coverage_percent", nginx_gateway_category["coverage_percent"], - 88, + 90, ) assert_equal( "high_value_config_coverage.coverage_categories.nginx.coverage_status", nginx_gateway_category["coverage_status"], - "rendered_diff_acceptance_ledger_ready_needs_owner_live_diff", + "emergency_change_backfill_ready_needs_owner_live_diff", ) for evidence_ref in [ "docs/security/PUBLIC-GATEWAY-PREFLIGHT-INVENTORY.md", @@ -5862,11 +5862,11 @@ def validate(root: Path) -> None: "acceptance_candidate_count": 3, "c0_acceptance_candidate_count": 2, "c1_acceptance_candidate_count": 1, - "acceptance_field_count": 27, - "required_owner_response_field_count": 16, - "reviewer_check_count": 16, - "outcome_lane_count": 7, - "blocked_action_count": 22, + "acceptance_field_count": 33, + "required_owner_response_field_count": 22, + "reviewer_check_count": 22, + "outcome_lane_count": 8, + "blocked_action_count": 28, "request_sent_count": 0, "recipient_confirmed_count": 0, "owner_response_received_count": 0, @@ -5892,6 +5892,12 @@ def validate(root: Path) -> None: "change_time_window_accepted_count": 0, "cross_project_impact_accepted_count": 0, "communication_sync_accepted_count": 0, + "change_intent_accepted_count": 0, + "pre_change_approval_accepted_count": 0, + "break_glass_reason_accepted_count": 0, + "route_health_impact_accepted_count": 0, + "rollback_validation_accepted_count": 0, + "post_change_monitoring_window_accepted_count": 0, "runtime_gate_count": 0, "action_button_count": 0, } @@ -5935,6 +5941,12 @@ def validate(root: Path) -> None: "change_time_window_present", "cross_project_impact_review_present", "communication_sync_ref_present", + "change_intent_or_ticket_ref_present", + "pre_change_approval_or_break_glass_present", + "route_health_impact_present", + "rollback_validation_present", + "post_change_monitoring_window_present", + "manual_change_not_silent", "counts_transition_safe", ] assert_equal( @@ -5949,6 +5961,7 @@ def validate(root: Path) -> None: "request_supplement", "ready_for_rendered_diff_review", "owner_review_only_update", + "emergency_change_backfill_required", "waiting_runtime_gate", ] assert_equal( @@ -5977,6 +5990,12 @@ def validate(root: Path) -> None: "accept_missing_change_time_window", "skip_cross_project_impact_review", "skip_incident_communication_sync", + "accept_silent_manual_nginx_change", + "treat_break_glass_as_approval", + "mark_gateway_change_resolved_without_route_health", + "skip_rollback_validation", + "skip_post_change_monitoring", + "hide_cross_project_route_impact", "open_runtime_gate", "add_action_button", ] @@ -5989,27 +6008,27 @@ def validate(root: Path) -> None: assert_equal( f"public_gateway_owner_response_acceptance.{item['acceptance_candidate_id']}.field_count", len(item["acceptance_fields"]), - 27, + 33, ) assert_equal( f"public_gateway_owner_response_acceptance.{item['acceptance_candidate_id']}.required_owner_response_fields", len(item["required_owner_response_fields"]), - 16, + 22, ) assert_equal( f"public_gateway_owner_response_acceptance.{item['acceptance_candidate_id']}.reviewer_checks", len(item["reviewer_checks"]), - 16, + 22, ) assert_equal( f"public_gateway_owner_response_acceptance.{item['acceptance_candidate_id']}.outcome_lanes", len(item["outcome_lanes"]), - 7, + 8, ) assert_equal( f"public_gateway_owner_response_acceptance.{item['acceptance_candidate_id']}.blocked_actions", len(item["blocked_actions"]), - 22, + 28, ) assert_true( f"public_gateway_owner_response_acceptance.{item['acceptance_candidate_id']}.not_approval", @@ -16222,14 +16241,18 @@ def validate(root: Path) -> None: "high_value_config_control_coverage_category_count=14", "high_value_config_control_coverage_c0_category_count=8", "high_value_config_control_coverage_c1_category_count=4", - "high_value_config_control_coverage_average_percent=68", + "high_value_config_control_coverage_average_percent=69", "high_value_config_control_coverage_needs_live_evidence_count=9", "high_value_config_control_coverage_owner_response_required_count=14", "high_value_config_control_coverage_owner_response_received_count=0", "high_value_config_control_coverage_owner_response_accepted_count=0", "high_value_config_control_coverage_runtime_gate_count=0", "high_value_config_control_coverage_action_button_count=0", - "nginx_public_gateway_coverage_percent=88", + "nginx_public_gateway_coverage_percent=90", + "public_gateway_owner_response_acceptance_required_owner_response_field_count=22", + "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", "secret_metadata_coverage_percent=68", "gitea_workflow_runner_source_control_coverage_percent=72", @@ -16461,7 +16484,7 @@ def validate(root: Path) -> None: assert_text_contains( "iwooos_page.critical_config_priority_nginx_percent", iwooos_projection_page, - "{ key: 'nginxGateway', rank: 'P0-1', state: '88% / live 0'", + "{ key: 'nginxGateway', rank: 'P0-1', state: '90% / live 0'", ) assert_text_contains( "iwooos_page.critical_config_priority_dns_percent",