# IwoooS Public Gateway / Nginx 事故後回讀計畫

| 項目 | 內容 |
|------|------|
| 日期 | 2026-06-15 |
| 狀態 | `post_incident_readback_plan_ready_no_runtime_action` |
| 工具 | `scripts/security/public-gateway-post-incident-readback-plan.py` |
| 輸入 | `docs/security/public-gateway-rendered-diff-acceptance.snapshot.json` |
| Snapshot | `docs/security/public-gateway-post-incident-readback-plan.snapshot.json` |
| runtime gate | `0` |

## 1. 目的

Nginx public gateway 是公開網站、API、Webhook、WebSocket、TLS、ACME 與 AI provider proxy 的共同入口。若 live Nginx conf 被手動或緊急變更，IwoooS 不能只看 route `200`、Nginx active、dashboard up、CD success 或 UI 可見就判定事故已驗收。

本文件補上事故後回讀計畫：未來若發生 gateway / Nginx 變更或事故，必須用脫敏 evidence ref 回填 actor、時間窗、變更意圖或 break-glass、改前改後 route 狀態、source-to-live diff、`nginx -t` readback、reload / no-reload 判定、route smoke、TLS / ACME、WebSocket、upstream、AI provider、monitoring、跨專案同步、回滾、防再發與 no-false-green attestation。

這個計畫不是 live conf received、不是 rendered diff accepted、不是 `nginx -t` 授權、不是 Nginx reload、不是 route smoke、不是 DNS / TLS probe、不是 certbot renew、不是 host write，也不是 production write 或 runtime gate。

## 2. 摘要

| 指標 | 值 | 說明 |
|------|----|------|
| readback candidate count | `3` | 對應三份 public gateway config |
| C0 readback candidate count | `2` | 188 all sites、188 internal tools HTTPS |
| C1 readback candidate count | `1` | 110 Ollama proxy |
| readback field count | `36` | 每份事故後回讀欄位 |
| required readback field count | `30` | 未來 owner evidence 必填欄位 |
| reviewer check count | `28` | 補件、隔離、拒收、review 與 no-false-green 檢查 |
| outcome lane count | `10` | 從等待回讀包到等待 runtime gate |
| blocked action count | `41` | 不可直接執行或不可誤讀的動作 |
| post-incident readback received / accepted | `0 / 0` | 尚未收到 / 驗收 |
| nginx test / reload / route smoke authorized | `0 / 0 / 0` | 尚未授權且未執行 |
| runtime gate / action button | `0 / 0` | 未開啟 |
| coverage after readback plan | `92%` | 只代表只讀控管成熟度，不代表可 reload |

## 3. Readback 欄位

| 欄位 | 內容規則 |
|------|----------|
| `gateway_incident_or_change_ref` | incident、change、ticket 或 maintenance ref |
| `actor_attribution_ref` | actor role / team，不接受匿名操作 |
| `change_time_window_ref` | 變更 / 事故時間窗 |
| `change_intent_or_break_glass_ref` | change intent 或 break-glass reason；break-glass 不等於事前批准 |
| `before_route_state_ref` | 改前 route / upstream / TLS / WebSocket 摘要 ref |
| `after_route_state_ref` | 改後 route / upstream / TLS / WebSocket 摘要 ref |
| `source_live_diff_state_ref` | source-to-live diff 狀態 ref，不保存 raw conf 或完整 diff |
| `nginx_test_readback_ref` | owner-provided `nginx -t` readback ref；本工具不得執行 |
| `nginx_reload_or_no_reload_ref` | 是否 reload 與原因 ref |
| `route_smoke_readback_ref` | affected routes、status、TLS、WebSocket、ACME 或不適用原因 |
| `tls_acme_readback_ref` | TLS / ACME impact ref |
| `websocket_readback_ref` | WebSocket / streaming route impact ref |
| `upstream_health_ref` | upstream health、port、dependency impact ref |
| `public_admin_api_route_impact_ref` | public / admin / API / callback / webhook 影響 ref |
| `ai_provider_impact_ref` | Ollama、AI provider、model route 或 proxy 影響 ref |
| `monitoring_alert_ref` | monitoring、alert、incident 或 dashboard ref |
| `operator_notification_ref` | 已通知受影響產品 / owner / Session 的脫敏 ref |
| `cross_project_sync_ref` | 跨專案同步 ref |
| `rollback_validation_ref` | rollback owner 與回滾後驗證 ref |
| `post_change_monitoring_ref` | post-change monitoring window ref |
| `recovery_or_still_degraded_ref` | 已恢復或仍 degraded 的狀態 ref |
| `postcheck_readback_ref` | 獨立 post-check readback ref |
| `recurrence_guard_ref` | 防再發 guard、change freeze、owner review 或 automation block |
| `maintenance_window` | 後續 runtime action 的維護窗口或明確禁止窗口 |
| `rollback_owner` | rollback owner / team |
| `followup_owner` | 補件或下一階段 owner |
| `not_approval` | 必須為 `true` |

## 4. Reviewer Checks

| Check | 規則 |
|-------|------|
| `source_diff_acceptance_current` | 來源 rendered diff acceptance snapshot 必須是目前版本 |
| `incident_or_change_ref_present` | 必須有 incident / change ref |
| `actor_attribution_present` | 必須標示 actor role / team |
| `change_time_window_present` | 必須有變更 / 事故時間窗 |
| `intent_or_break_glass_present` | 必須有 intent 或 break-glass reason |
| `before_after_route_state_present` | 必須有 before / after route state |
| `source_live_diff_state_present` | 必須有 source-to-live diff 狀態 |
| `nginx_test_readback_is_owner_provided` | `nginx -t` 只能是 owner-provided readback |
| `reload_or_no_reload_called_out` | 必須說明是否 reload |
| `route_smoke_readback_present` | 必須列 route smoke 或不適用原因 |
| `tls_acme_readback_present` | TLS / ACME 不可被 route 200 取代 |
| `websocket_readback_present` | WebSocket / streaming route 需獨立回讀 |
| `upstream_health_present` | upstream health / port / dependency 影響必須列 ref |
| `public_admin_api_route_impact_present` | public / admin / API route 影響需列 ref |
| `ai_provider_impact_present` | AI provider / proxy 影響需列 ref |
| `monitoring_alert_present` | 需有 monitoring / alert / incident ref |
| `operator_notification_present` | 需有通知 ref |
| `cross_project_sync_present` | 需有跨專案同步 ref |
| `rollback_validation_present` | 需有 rollback validation ref |
| `post_change_monitoring_present` | 需有變更後監控窗口 |
| `recovery_or_still_degraded_present` | 需說明恢復或仍 degraded |
| `postcheck_independent` | post-check 必須獨立於原操作人與 UI |
| `recurrence_guard_present` | 需有防再發措施 |
| `maintenance_window_present` | 後續 runtime action 需有維護窗口 |
| `no_false_green` | 不得把 route 200、Nginx active、dashboard up、CD success 或 UI 可見當驗收 |
| `raw_payload_absent` | 不得保存 raw conf、完整 diff、private key、憑證內容、cookie、token 或未脫敏截圖 |
| `runtime_stays_zero` | 不得觸發 `nginx -t`、reload、route smoke、DNS / TLS probe、certbot renew 或 host write |
| `counts_transition_safe` | accepted count 只能由 reviewer record 更新，且不得同時開 runtime gate |

## 5. Outcome Lanes

| Lane | 意義 |
|------|------|
| `waiting_post_incident_readback` | 尚未收到事故回讀包 |
| `request_actor_or_time_supplement` | 缺 actor、時間窗、intent 或 break-glass reason |
| `request_route_state_supplement` | 缺 before / after route、upstream、WebSocket、TLS / ACME 或 route smoke |
| `request_diff_test_supplement` | 缺 source-live diff、`nginx -t` readback、reload / no-reload 或 rollback validation |
| `request_dependency_supplement` | 缺 AI provider、monitoring、public/admin/API route 或跨專案影響 |
| `quarantine_raw_payload` | raw conf、完整 diff、secret、憑證、cookie、token 或未脫敏截圖只能隔離 |
| `reject_false_green_claim` | route 200、Nginx active、dashboard up、CD success 或 UI 可見不能當驗收 |
| `ready_for_gateway_post_incident_review` | metadata 合格後進 reviewer review |
| `recurrence_guard_backfill_required` | 需補防再發 guard |
| `waiting_runtime_gate` | 即使 readback accepted，runtime gate 仍需獨立人工批准 |

## 6. Blocked Actions

| Action | 邊界 |
|--------|------|
| `ssh_read_live_nginx_conf` | 未授權不得讀 live Nginx conf |
| `store_raw_live_conf` | 不得保存 raw live conf |
| `store_full_rendered_diff_payload` | 不得保存完整 diff payload |
| `collect_secret_value` | 不得收 secret value |
| `collect_private_key` | 不得收 private key |
| `collect_certificate_body` | 不得收完整憑證內容 |
| `run_nginx_test` | 不得由本計畫執行 `nginx -t` |
| `reload_nginx` / `restart_nginx` | 不得由本計畫執行 |
| `change_public_route` / `change_admin_route` / `change_api_route` | 不得改 route |
| `change_websocket_route` / `change_acme_challenge_route` / `change_upstream` | 不得改路由、ACME 或 upstream |
| `change_dns_record` / `tls_probe` / `dns_probe` / `certbot_renew` | 不得改 DNS / TLS 或 renew cert |
| `route_smoke` / `websocket_smoke` | 不得由本計畫執行 smoke |
| `host_write` / `firewall_change` / `docker_restart` / `systemd_restart` | 不得寫主機或重啟 |
| `accept_route_200_as_all_green` / `accept_nginx_active_as_all_green` | 不得假性驗收 |
| `mark_readback_accepted_without_reviewer_record` | 不得跳過 reviewer record |
| `open_runtime_gate` / `add_action_button` | 不得開執行閘門或按鈕 |

## 7. 指令

產生 committed snapshot：

```bash
python3 scripts/security/public-gateway-post-incident-readback-plan.py \
  --root . \
  --source-report docs/security/public-gateway-rendered-diff-acceptance.snapshot.json \
  --output docs/security/public-gateway-post-incident-readback-plan.snapshot.json \
  --generated-at 2026-06-15T22:10:00+08:00
```

集中驗證 guard：

```bash
python3 scripts/security/security-mirror-progress-guard.py --root .
```

## 8. 完成度

| 工作 | 完成度 | 說明 |
|------|--------|------|
| Public Gateway / Nginx post-incident readback plan | `100%` | 產生器、snapshot 與文件已固定 |
| post-incident readback received / accepted | `0%` | 尚未收到 / 接受 |
| nginx test / reload / route smoke | `0%` | 未授權且未執行 |
| DNS / TLS / certbot | `0%` | 未授權且未執行 |
| runtime reload / host write | `0%` | 未授權且未執行 |
