diff --git a/docs/LOGBOOK.md b/docs/LOGBOOK.md index 016f09eed..e52bfd03a 100644 --- a/docs/LOGBOOK.md +++ b/docs/LOGBOOK.md @@ -1,3 +1,36 @@ +## 2026-06-15|Public Gateway 手動 / 緊急變更 Metadata Gate 強化 + +**背景**:使用者再次指出 Nginx / gateway 類配置常被手動變動,且端口或路由異常會直接影響 Ollama、ArgoCD、registry、stock 等服務。既有 Public Gateway owner response acceptance 已要求 owner、decision、live conf ref、rendered diff、`nginx -t` plan、route smoke、maintenance window、rollback owner 與 post-check,但尚未把「誰動了、何時動、影響哪些專案、是否同步通知」列為必填 metadata。這會讓事故收斂只看技術 diff,缺少責任、時窗與跨專案同步。 + +**完成項目**: +- `scripts/security/public-gateway-owner-response-acceptance.py` 新增 4 個 owner response 必填 metadata 欄位:`change_actor_or_source_ref`、`change_time_window`、`cross_project_impact_ref`、`communication_sync_ref`。 +- Public Gateway owner response reviewer checks 從 `12` 增至 `16`,新增手動 / 緊急變更來源、時間窗、跨專案影響與通知同步檢查。 +- Public Gateway blocked actions 從 `18` 增至 `22`,禁止 unknown actor、missing change window、跳過跨專案影響 review、跳過事故同步。 +- 重新產生 `docs/security/public-gateway-owner-response-acceptance.snapshot.json`,固定 `acceptance_field_count=27`、`required_owner_response_field_count=16`、`reviewer_check_count=16`、`blocked_action_count=22`,所有 received / accepted / runtime gate 維持 `0`。 +- 更新 `PUBLIC-GATEWAY-OWNER-RESPONSE-ACCEPTANCE.md`、`HIGH-VALUE-CONFIG-CONTROL-COVERAGE.md`、`IWOOOS-CONFIG-CONTROL-INVENTORY.md`、`iwooos-config-control-guard.py` 與 `security-mirror-progress-guard.py`,讓主 guard 鎖住新欄位數。 + +**本地驗證**: +- `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` → `PUBLIC_GATEWAY_OWNER_RESPONSE_ACCEPTANCE_OK candidates=3 c0=2 checks=16 lanes=7 accepted=0 runtime_gate=0`。 +- `python3 -m py_compile scripts/security/public-gateway-owner-response-acceptance.py scripts/security/iwooos-config-control-guard.py scripts/security/security-mirror-progress-guard.py` 通過。 +- `python3 -m json.tool docs/security/public-gateway-owner-response-acceptance.snapshot.json` 通過。 +- `python3 scripts/security/iwooos-config-control-guard.py --root .` → `IWOOOS_CONFIG_CONTROL_GUARD_OK`。 +- `python3 scripts/security/security-mirror-progress-guard.py --root .` → `SECURITY_MIRROR_PROGRESS_GUARD_OK`。 +- `python3 scripts/security/iwooos-owner-gate-guard.py --root .` → `IWOOOS_OWNER_GATE_GUARD_OK`。 +- `python3 scripts/security/package-supply-chain-owner-policy-guard.py --root .` → `PACKAGE_SUPPLY_CHAIN_OWNER_POLICY_GUARD_OK`。 +- `python3 scripts/ops/doc-secrets-sanity-check.py docs .gitea` → `DOC_SECRET_SANITY_OK scanned_files=865`。 +- `git diff --check` 通過。 + +**Production / Browser 驗證判斷**: +- 本輪只修改 repo-only 文件、snapshot 與 guard 腳本,未改前端、API、Nginx、K8s 或 runtime,因此不新增正式部署,也不需要 Browser smoke。 +- 若後續把新 metadata 欄位顯示到 AwoooP / IwoooS 前台,必須再做 production desktop / mobile sensitive scan,確認不顯示個人識別、raw conf、raw payload、內部狀態碼或內部協作文字。 + +**完成度與邊界**: +- Public Gateway 手動 / 緊急變更 metadata gate:`0% -> 100%`。 +- Public Gateway owner response acceptance ledger:`86% -> 88%` 的既有成熟度不再上調;本輪只補事故 metadata 欄位,不代表 live evidence 已收到。 +- 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`。 +- IwoooS headline 維持 `64%`;active runtime gate 維持 `0`。 +- 本輪未 SSH、未讀 live conf、未改主機、未重啟 Docker / Nginx、未修改 firewall / iptables、未收 secrets 明文、未執行 active scan、未切 GitHub primary、未 force push,也沒有把內部協作內容放到前端頁面。 + ## 2026-06-15|S4.9 Owner Response Gate 基準收斂與防過期 Guard 更新 **背景**:AwoooP 高可見頁敏感識別已完成正式脫敏與 production 驗證,但 S4.9 owner response gate 的缺口稽核、snapshot 產生器與 guard 仍鎖在較早的 deploy marker。這會讓後續 Session 以舊基準判斷 S4.9 狀態,進而誤把 UI / LOGBOOK / AwoooP 可見性當成 owner response 或資安接受。 diff --git a/docs/security/HIGH-VALUE-CONFIG-CONTROL-COVERAGE.md b/docs/security/HIGH-VALUE-CONFIG-CONTROL-COVERAGE.md index f47243c71..ddb700098 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=23`、`required_owner_response_field_count=12`、`reviewer_check_count=12`、`outcome_lane_count=7`、`blocked_action_count=18`、`owner_response_received_count=0`、`owner_response_accepted_count=0`、`runtime_gate_count=0`。此更新只讓 `nginx_public_gateway` 從 `84%` 推進到 `86%`,代表收件驗收帳本更完整;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=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`。 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 轉成只讀驗收帳本。 @@ -288,7 +288,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 轉成 `acceptance_candidate_count=3`、`c0_acceptance_candidate_count=2`、`required_owner_response_field_count=12`、`reviewer_check_count=12`、`outcome_lane_count=7`、`blocked_action_count=18` 的 owner response acceptance 只讀帳本。此更新只讓 `nginx_public_gateway` 從 `84%` 推進到 `86%`;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=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_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 c4e040942..e5f5fcd3d 100644 --- a/docs/security/IWOOOS-CONFIG-CONTROL-INVENTORY.md +++ b/docs/security/IWOOOS-CONFIG-CONTROL-INVENTORY.md @@ -103,7 +103,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 只讀帳本。固定 `candidates=3`、`c0=2`、`owner_fields=12`、`reviewer_checks=12`、`outcome_lanes=7`、`blocked_actions=18`,讓 Nginx public gateway 類別成熟度從 `84%` 推進到 `86%`。此更新只表示未來 owner 回覆可安全收件、補件、隔離或拒收;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=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_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 bbe54f8e8..5025f4929 100644 --- a/docs/security/PUBLIC-GATEWAY-OWNER-RESPONSE-ACCEPTANCE.md +++ b/docs/security/PUBLIC-GATEWAY-OWNER-RESPONSE-ACCEPTANCE.md @@ -2,7 +2,7 @@ | 項目 | 內容 | |------|------| -| 日期 | 2026-06-14 | +| 日期 | 2026-06-15 | | 狀態 | `owner_response_acceptance_ledger_ready_no_runtime_action` | | 工具 | `scripts/security/public-gateway-owner-response-acceptance.py` | | Snapshot | `docs/security/public-gateway-owner-response-acceptance.snapshot.json` | @@ -15,6 +15,8 @@ 本階段不讀 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。 + ## 2. 摘要 | 指標 | 目前值 | 說明 | @@ -24,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 | `23` | 每份 acceptance candidate 固定欄位數 | -| required owner response field | `12` | owner 必須提供的最小欄位 | -| reviewer check | `12` | reviewer 收件前必檢項 | +| acceptance field | `27` | 每份 acceptance candidate 固定欄位數 | +| required owner response field | `16` | owner 必須提供的最小欄位 | +| reviewer check | `16` | reviewer 收件前必檢項 | | outcome lane | `7` | 等待、隔離、拒收、補件、review、只讀更新、等待 runtime gate | -| blocked action | `18` | 驗收前全部禁止 | +| blocked action | `22` | 驗收前全部禁止 | | owner response received / accepted | `0 / 0` | 不得假性拉高 | | rendered diff / `nginx -t` / reload / route smoke | `0` | 未授權且未執行 | | runtime gate / action button | `0 / 0` | 不開任何執行入口 | @@ -48,6 +50,10 @@ | `maintenance_window` | 維護窗口或禁止窗口 | | `rollback_owner` | rollback 負責人與 rollback ref | | `postcheck_plan` | reload / route smoke 後的 post-check plan | +| `change_actor_or_source_ref` | 若有手動或緊急變更,提供脫敏 actor / source ref,不得貼帳密或 raw shell history | +| `change_time_window` | 變更或事故時間窗,讓 route smoke、告警與跨專案影響能對齊 | +| `cross_project_impact_ref` | 跨產品 / 跨專案影響 ref,避免只修單一路由卻造成其他服務中斷 | +| `communication_sync_ref` | 通知或協調 ref,證明相關專案 owner 已收到影響與回復狀態 | | `followup_owner` | 補件、隔離、拒收或下一步 review owner | ## 4. Reviewer Checks @@ -65,6 +71,10 @@ | `route_smoke_plan_present` | route smoke plan 必須列 affected routes、預期 status、TLS / WebSocket / ACME checks | | `maintenance_window_present` | 必須有維護窗口或明確禁止窗口 | | `rollback_owner_present` | rollback owner 與 rollback ref 必須存在 | +| `change_actor_or_source_ref_present` | 手動或緊急變更必須有脫敏 actor / source ref | +| `change_time_window_present` | 必須提供變更或事故時間窗 | +| `cross_project_impact_review_present` | 必須提供跨產品 / 跨專案影響 ref | +| `communication_sync_ref_present` | 必須提供通知或協調 ref | | `counts_transition_safe` | 只有 reviewer record 可更新 received / accepted / rejected;不得同時開 runtime gate | ## 5. Outcome Lanes @@ -98,6 +108,10 @@ modify_nginx_conf modify_dns_tls_config change_public_route write_production_host +accept_unknown_change_actor +accept_missing_change_time_window +skip_cross_project_impact_review +skip_incident_communication_sync open_runtime_gate add_action_button ``` @@ -110,7 +124,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-14T23:58:00+08:00 + --generated-at 2026-06-15T08:18:00+08:00 ``` 只讀 guard: @@ -125,6 +139,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 | | owner response received / accepted | `0%` | 尚未收到或接受任何 owner response | | rendered diff / `nginx -t` / reload / route smoke | `0%` | 未授權且未執行 | | DNS / TLS / certbot | `0%` | 未授權且未執行 | diff --git a/docs/security/public-gateway-owner-response-acceptance.snapshot.json b/docs/security/public-gateway-owner-response-acceptance.snapshot.json index 67e3a44a5..4407c7827 100644 --- a/docs/security/public-gateway-owner-response-acceptance.snapshot.json +++ b/docs/security/public-gateway-owner-response-acceptance.snapshot.json @@ -23,6 +23,10 @@ "maintenance_window", "rollback_owner", "postcheck_plan", + "change_actor_or_source_ref", + "change_time_window", + "cross_project_impact_ref", + "communication_sync_ref", "reviewer_outcome", "followup_owner", "not_approval" @@ -47,12 +51,20 @@ "modify_dns_tls_config", "change_public_route", "write_production_host", + "accept_unknown_change_actor", + "accept_missing_change_time_window", + "skip_cross_project_impact_review", + "skip_incident_communication_sync", "open_runtime_gate", "add_action_button" ], "certbot_renew_authorized": false, + "change_actor_or_source_ref": null, + "change_time_window": "pending_owner_response", + "communication_sync_ref": null, "config_id": "host188_all_sites", "control_tier": "C0", + "cross_project_impact_ref": null, "decision": "pending_owner_response", "decision_reason": "pending_owner_response", "diff_gate_id": "public_gateway_rendered_diff_gate:host188_all_sites", @@ -105,6 +117,10 @@ "maintenance_window", "rollback_owner", "postcheck_plan", + "change_actor_or_source_ref", + "change_time_window", + "cross_project_impact_ref", + "communication_sync_ref", "followup_owner" ], "reviewer_checks": [ @@ -119,6 +135,10 @@ "route_smoke_plan_present", "maintenance_window_present", "rollback_owner_present", + "change_actor_or_source_ref_present", + "change_time_window_present", + "cross_project_impact_review_present", + "communication_sync_ref_present", "counts_transition_safe" ], "reviewer_outcome": "waiting_owner_response", @@ -155,6 +175,10 @@ "maintenance_window", "rollback_owner", "postcheck_plan", + "change_actor_or_source_ref", + "change_time_window", + "cross_project_impact_ref", + "communication_sync_ref", "reviewer_outcome", "followup_owner", "not_approval" @@ -179,12 +203,20 @@ "modify_dns_tls_config", "change_public_route", "write_production_host", + "accept_unknown_change_actor", + "accept_missing_change_time_window", + "skip_cross_project_impact_review", + "skip_incident_communication_sync", "open_runtime_gate", "add_action_button" ], "certbot_renew_authorized": false, + "change_actor_or_source_ref": null, + "change_time_window": "pending_owner_response", + "communication_sync_ref": null, "config_id": "host188_internal_tools_https", "control_tier": "C0", + "cross_project_impact_ref": null, "decision": "pending_owner_response", "decision_reason": "pending_owner_response", "diff_gate_id": "public_gateway_rendered_diff_gate:host188_internal_tools_https", @@ -237,6 +269,10 @@ "maintenance_window", "rollback_owner", "postcheck_plan", + "change_actor_or_source_ref", + "change_time_window", + "cross_project_impact_ref", + "communication_sync_ref", "followup_owner" ], "reviewer_checks": [ @@ -251,6 +287,10 @@ "route_smoke_plan_present", "maintenance_window_present", "rollback_owner_present", + "change_actor_or_source_ref_present", + "change_time_window_present", + "cross_project_impact_review_present", + "communication_sync_ref_present", "counts_transition_safe" ], "reviewer_outcome": "waiting_owner_response", @@ -287,6 +327,10 @@ "maintenance_window", "rollback_owner", "postcheck_plan", + "change_actor_or_source_ref", + "change_time_window", + "cross_project_impact_ref", + "communication_sync_ref", "reviewer_outcome", "followup_owner", "not_approval" @@ -311,12 +355,20 @@ "modify_dns_tls_config", "change_public_route", "write_production_host", + "accept_unknown_change_actor", + "accept_missing_change_time_window", + "skip_cross_project_impact_review", + "skip_incident_communication_sync", "open_runtime_gate", "add_action_button" ], "certbot_renew_authorized": false, + "change_actor_or_source_ref": null, + "change_time_window": "pending_owner_response", + "communication_sync_ref": null, "config_id": "host110_ollama_proxy", "control_tier": "C1", + "cross_project_impact_ref": null, "decision": "pending_owner_response", "decision_reason": "pending_owner_response", "diff_gate_id": "public_gateway_rendered_diff_gate:host110_ollama_proxy", @@ -369,6 +421,10 @@ "maintenance_window", "rollback_owner", "postcheck_plan", + "change_actor_or_source_ref", + "change_time_window", + "cross_project_impact_ref", + "communication_sync_ref", "followup_owner" ], "reviewer_checks": [ @@ -383,6 +439,10 @@ "route_smoke_plan_present", "maintenance_window_present", "rollback_owner_present", + "change_actor_or_source_ref_present", + "change_time_window_present", + "cross_project_impact_review_present", + "communication_sync_ref_present", "counts_transition_safe" ], "reviewer_outcome": "waiting_owner_response", @@ -418,6 +478,10 @@ "maintenance_window", "rollback_owner", "postcheck_plan", + "change_actor_or_source_ref", + "change_time_window", + "cross_project_impact_ref", + "communication_sync_ref", "reviewer_outcome", "followup_owner", "not_approval" @@ -439,6 +503,10 @@ "modify_dns_tls_config", "change_public_route", "write_production_host", + "accept_unknown_change_actor", + "accept_missing_change_time_window", + "skip_cross_project_impact_review", + "skip_incident_communication_sync", "open_runtime_gate", "add_action_button" ], @@ -462,12 +530,13 @@ "runtime_execution_authorized": false, "secret_value_collection_allowed": false }, - "generated_at": "2026-06-14T23:58:00+08:00", - "git_commit": "233ee934", + "generated_at": "2026-06-15T08:18:00+08:00", + "git_commit": "04728d36", "next_steps": [ "等待 owner response;未收到前不得更新 accepted count。", "收到回覆後先走 raw payload / secret / scope / evidence ref 檢查,不合格即隔離、拒收或補件。", - "metadata 合格也只能進 rendered diff reviewer review;`nginx -t`、reload、route smoke 與 production write 仍需獨立人工批准。" + "metadata 合格也只能進 rendered diff reviewer review;`nginx -t`、reload、route smoke 與 production write 仍需獨立人工批准。", + "若涉及手動或緊急 gateway 變更,必須先補 change actor/source、time window、cross-project impact 與 communication sync refs。" ], "outcome_lanes": [ { @@ -511,6 +580,10 @@ "maintenance_window", "rollback_owner", "postcheck_plan", + "change_actor_or_source_ref", + "change_time_window", + "cross_project_impact_ref", + "communication_sync_ref", "followup_owner" ], "reviewer_checks": [ @@ -558,6 +631,22 @@ "check_id": "rollback_owner_present", "instruction": "rollback owner 與 rollback ref 必須存在,且不可指向 raw secret。" }, + { + "check_id": "change_actor_or_source_ref_present", + "instruction": "若曾有手動或緊急變更,必須提供脫敏 actor / source ref;不得要求個人帳密或 raw shell history。" + }, + { + "check_id": "change_time_window_present", + "instruction": "必須提供變更或事故時間窗,讓 route smoke、告警與跨專案影響可對齊。" + }, + { + "check_id": "cross_project_impact_review_present", + "instruction": "必須提供跨產品 / 跨專案影響 ref,避免只修單一路由卻讓其他服務斷線。" + }, + { + "check_id": "communication_sync_ref_present", + "instruction": "必須提供通知或協調 ref,證明相關專案 owner 已收到影響與回復狀態。" + }, { "check_id": "counts_transition_safe", "instruction": "只有 reviewer record 可更新 received / accepted / rejected;不得同時開 runtime gate。" @@ -573,13 +662,17 @@ "status": "owner_response_acceptance_ledger_ready_no_runtime_action", "summary": { "acceptance_candidate_count": 3, - "acceptance_field_count": 23, + "acceptance_field_count": 27, "accepted_redacted_export_count": 0, "action_button_count": 0, - "blocked_action_count": 18, + "blocked_action_count": 22, "c0_acceptance_candidate_count": 2, "c1_acceptance_candidate_count": 1, "certbot_renew_authorized_count": 0, + "change_actor_identified_count": 0, + "change_time_window_accepted_count": 0, + "communication_sync_accepted_count": 0, + "cross_project_impact_accepted_count": 0, "dns_tls_probe_authorized_count": 0, "maintenance_window_accepted_count": 0, "nginx_reload_authorized_count": 0, @@ -596,8 +689,8 @@ "rendered_diff_candidate_count": 0, "rendered_diff_ready_count": 0, "request_sent_count": 0, - "required_owner_response_field_count": 12, - "reviewer_check_count": 12, + "required_owner_response_field_count": 16, + "reviewer_check_count": 16, "rollback_owner_accepted_count": 0, "route_smoke_authorized_count": 0, "route_smoke_executed_count": 0, diff --git a/scripts/security/iwooos-config-control-guard.py b/scripts/security/iwooos-config-control-guard.py index b5594e6c0..3daedcb12 100644 --- a/scripts/security/iwooos-config-control-guard.py +++ b/scripts/security/iwooos-config-control-guard.py @@ -112,10 +112,10 @@ ARTIFACT_SPECS = [ "status": "owner_response_acceptance_ledger_ready_no_runtime_action", "list_counts": { "acceptance_candidates": 3, - "blocked_actions": 18, - "reviewer_checks": 12, + "blocked_actions": 22, + "reviewer_checks": 16, "outcome_lanes": 7, - "required_owner_response_fields": 12, + "required_owner_response_fields": 16, }, "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 f401bf5bd..da4738008 100644 --- a/scripts/security/public-gateway-owner-response-acceptance.py +++ b/scripts/security/public-gateway-owner-response-acceptance.py @@ -42,6 +42,10 @@ ACCEPTANCE_FIELDS = [ "maintenance_window", "rollback_owner", "postcheck_plan", + "change_actor_or_source_ref", + "change_time_window", + "cross_project_impact_ref", + "communication_sync_ref", "reviewer_outcome", "followup_owner", "not_approval", @@ -59,6 +63,10 @@ REQUIRED_OWNER_RESPONSE_FIELDS = [ "maintenance_window", "rollback_owner", "postcheck_plan", + "change_actor_or_source_ref", + "change_time_window", + "cross_project_impact_ref", + "communication_sync_ref", "followup_owner", ] @@ -107,6 +115,22 @@ REVIEWER_CHECKS = [ "check_id": "rollback_owner_present", "instruction": "rollback owner 與 rollback ref 必須存在,且不可指向 raw secret。", }, + { + "check_id": "change_actor_or_source_ref_present", + "instruction": "若曾有手動或緊急變更,必須提供脫敏 actor / source ref;不得要求個人帳密或 raw shell history。", + }, + { + "check_id": "change_time_window_present", + "instruction": "必須提供變更或事故時間窗,讓 route smoke、告警與跨專案影響可對齊。", + }, + { + "check_id": "cross_project_impact_review_present", + "instruction": "必須提供跨產品 / 跨專案影響 ref,避免只修單一路由卻讓其他服務斷線。", + }, + { + "check_id": "communication_sync_ref_present", + "instruction": "必須提供通知或協調 ref,證明相關專案 owner 已收到影響與回復狀態。", + }, { "check_id": "counts_transition_safe", "instruction": "只有 reviewer record 可更新 received / accepted / rejected;不得同時開 runtime gate。", @@ -161,6 +185,10 @@ BLOCKED_ACTIONS = [ "modify_dns_tls_config", "change_public_route", "write_production_host", + "accept_unknown_change_actor", + "accept_missing_change_time_window", + "skip_cross_project_impact_review", + "skip_incident_communication_sync", "open_runtime_gate", "add_action_button", ] @@ -208,6 +236,10 @@ def acceptance_candidate(diff_gate: dict[str, Any]) -> dict[str, Any]: "maintenance_window": "pending_owner_response", "rollback_owner": "pending_owner_response", "postcheck_plan": "pending_owner_response", + "change_actor_or_source_ref": None, + "change_time_window": "pending_owner_response", + "cross_project_impact_ref": None, + "communication_sync_ref": None, "reviewer_outcome": "waiting_owner_response", "followup_owner": "pending_owner_response", "acceptance_fields": ACCEPTANCE_FIELDS, @@ -300,6 +332,10 @@ def build_report( "certbot_renew_authorized_count": 0, "maintenance_window_accepted_count": 0, "rollback_owner_accepted_count": 0, + "change_actor_identified_count": 0, + "change_time_window_accepted_count": 0, + "cross_project_impact_accepted_count": 0, + "communication_sync_accepted_count": 0, "runtime_gate_count": 0, "action_button_count": 0, }, @@ -333,6 +369,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。", ], } diff --git a/scripts/security/security-mirror-progress-guard.py b/scripts/security/security-mirror-progress-guard.py index d362d7a74..2652064ae 100755 --- a/scripts/security/security-mirror-progress-guard.py +++ b/scripts/security/security-mirror-progress-guard.py @@ -5574,11 +5574,11 @@ def validate(root: Path) -> None: "acceptance_candidate_count": 3, "c0_acceptance_candidate_count": 2, "c1_acceptance_candidate_count": 1, - "acceptance_field_count": 23, - "required_owner_response_field_count": 12, - "reviewer_check_count": 12, + "acceptance_field_count": 27, + "required_owner_response_field_count": 16, + "reviewer_check_count": 16, "outcome_lane_count": 7, - "blocked_action_count": 18, + "blocked_action_count": 22, "request_sent_count": 0, "recipient_confirmed_count": 0, "owner_response_received_count": 0, @@ -5600,6 +5600,10 @@ def validate(root: Path) -> None: "certbot_renew_authorized_count": 0, "maintenance_window_accepted_count": 0, "rollback_owner_accepted_count": 0, + "change_actor_identified_count": 0, + "change_time_window_accepted_count": 0, + "cross_project_impact_accepted_count": 0, + "communication_sync_accepted_count": 0, "runtime_gate_count": 0, "action_button_count": 0, } @@ -5639,6 +5643,10 @@ def validate(root: Path) -> None: "route_smoke_plan_present", "maintenance_window_present", "rollback_owner_present", + "change_actor_or_source_ref_present", + "change_time_window_present", + "cross_project_impact_review_present", + "communication_sync_ref_present", "counts_transition_safe", ] assert_equal( @@ -5677,6 +5685,10 @@ def validate(root: Path) -> None: "modify_dns_tls_config", "change_public_route", "write_production_host", + "accept_unknown_change_actor", + "accept_missing_change_time_window", + "skip_cross_project_impact_review", + "skip_incident_communication_sync", "open_runtime_gate", "add_action_button", ] @@ -5689,17 +5701,17 @@ def validate(root: Path) -> None: assert_equal( f"public_gateway_owner_response_acceptance.{item['acceptance_candidate_id']}.field_count", len(item["acceptance_fields"]), - 23, + 27, ) assert_equal( f"public_gateway_owner_response_acceptance.{item['acceptance_candidate_id']}.required_owner_response_fields", len(item["required_owner_response_fields"]), - 12, + 16, ) assert_equal( f"public_gateway_owner_response_acceptance.{item['acceptance_candidate_id']}.reviewer_checks", len(item["reviewer_checks"]), - 12, + 16, ) assert_equal( f"public_gateway_owner_response_acceptance.{item['acceptance_candidate_id']}.outcome_lanes", @@ -5709,7 +5721,7 @@ def validate(root: Path) -> None: assert_equal( f"public_gateway_owner_response_acceptance.{item['acceptance_candidate_id']}.blocked_actions", len(item["blocked_actions"]), - 18, + 22, ) assert_true( f"public_gateway_owner_response_acceptance.{item['acceptance_candidate_id']}.not_approval",