# IwoooS Wazuh 只讀 API Release Handoff

> 狀態：source-side 修補、feature branch、正式主線、deploy marker 與 production route readback 已完成；仍等待 Wazuh live metadata owner gate、manager registry 驗收與 Dashboard stored API / RBAC / TLS 修復。
> 本文件不包含 secret、token、內網 Wazuh URL、raw log、raw Wazuh payload 或工作視窗逐字稿。

## 目前分層狀態

- feature branch：`codex/iwooos-wazuh-boundary-guard-20260624` 已推送到 Gitea；精確 HEAD 請用 `git ls-remote` 讀回，不在本文件硬寫避免文件 commit 後自我漂移。
- formal main release：`100%`，Wazuh 只讀 route / no-false-green patch 已進正式主線。
- production deploy：`100%`，正式 API 已讀回 `200 disabled_waiting_iwooos_wazuh_owner_gate`。
- Wazuh live metadata env enable：`0%`，尚未收到正式負責人回覆、機密來源中繼資料、唯讀帳號範圍與 post-enable readback。
- Wazuh manager agent registry accepted：`0%`，尚未取得可驗收的 manager registry 只讀讀回。
- active response / host write / Kali active scan：`0%`，必須維持關閉。

## 根因判定

正式釋出前，`https://awoooi.wooo.work/api/iwooos/wazuh` 曾回 `404 {"detail":"Not Found"}`，同時 `https://awoooi.wooo.work/zh-TW/iwooos` 回 `200`。

判定根因：

- production `/api` 目前落到 FastAPI 後端。
- 既有 `apps/web/src/app/api/iwooos/wazuh/route.ts` 是 Next.js route，沒有被 public gateway 暴露到這條 production path。
- FastAPI 後端原本沒有 `/api/iwooos/wazuh` 相容 route，因此回 404。
- 這個 404 不能被解讀成 Wazuh manager 一定故障，也不能被解讀成 Wazuh 已未安裝。
- 正式釋出後，production route 已讀回 `200 disabled_waiting_iwooos_wazuh_owner_gate`；這只代表 IwoooS route 已部署，不代表 Wazuh manager registry 已恢復或所有 agent 已納管。

## Source-Side 修補

本地 commit：

- `codex/iwooos-wazuh-boundary-guard-20260624` Wazuh API commit 會在每次 rebase 或文件同步後改變；請在 release 前用 `git log --oneline gitea/main..HEAD` 與 `git ls-remote` 讀回，不硬寫在本文件內。
- `codex/iwooos-wazuh-boundary-guard-20260624` feature branch 已推送；但 feature branch push 不等於 formal main release、production deploy 或 Wazuh live metadata 授權。
- Release patch set 需在最終 docs commit 後以 `git format-patch gitea/main..HEAD` 重新產生，再用 `shasum -a 256` 讀回；不得沿用 rebase 前或文件修正前的舊 patch SHA。

變更範圍：

- `apps/api/src/api/v1/iwooos.py`
- `apps/api/src/services/iwooos_wazuh_readonly_status.py`
- `apps/api/src/services/iwooos_runtime_security_readback.py`
- `apps/api/src/main.py`
- `apps/api/tests/test_iwooos_wazuh_api.py`
- `apps/api/tests/test_iwooos_runtime_security_readback.py`
- `scripts/security/wazuh-readonly-route-boundary-guard.py`
- `scripts/security/wazuh-readonly-production-readback.py`
- `scripts/security/wazuh-readonly-release-gate.py`
- `scripts/security/wazuh-readonly-release-lane-preflight.py`
- `scripts/security/wazuh-readonly-release-owner-request.py`
- `scripts/security/wazuh-readonly-release-owner-response-acceptance.py`
- `scripts/security/wazuh-readonly-live-metadata-env-gate.py`
- `scripts/security/security-mirror-progress-guard.py`
- `docs/security/wazuh-readonly-release-gate.snapshot.json`
- `docs/security/wazuh-readonly-release-lane-preflight.snapshot.json`
- `docs/security/wazuh-readonly-release-owner-request.snapshot.json`
- `docs/security/wazuh-readonly-release-owner-response-acceptance.snapshot.json`
- `docs/security/wazuh-readonly-live-metadata-env-gate.snapshot.json`
- `apps/web/src/app/[locale]/iwooos/page.tsx`
- `apps/web/messages/zh-TW.json`
- `apps/web/messages/en.json`
- `docs/LOGBOOK.md`

完成內容：

- 新增 FastAPI `GET /api/iwooos/wazuh`。
- 新增 FastAPI `GET /api/v1/iwooos/wazuh`。
- 將 Wazuh 只讀 metadata 邏輯抽成 `iwooos_wazuh_readonly_status.py`，讓正式 route、Runtime 資安讀回與後續告警鏈共用同一份脫敏 aggregate 結果。
- `GET /api/v1/iwooos/runtime-security-readback` 新增 `wazuh_live_route` P0 lane 與 `wazuh_live_*` summary；正式路由 disabled、misconfigured、registry empty、below expected 或 unavailable 都會在 Runtime board 顯示退化，不再只藏在下方卡片。
- 預設回 `disabled_waiting_iwooos_wazuh_owner_gate`，避免 production 繼續用 404 表示未啟用。
- live Wazuh 查詢仍需 `IWOOOS_WAZUH_READONLY_ENABLED=true` 與 server-side env：`WAZUH_API_BASE_URL`、`WAZUH_API_USERNAME`、`WAZUH_API_PASSWORD`。
- 強制 Wazuh base URL 使用 HTTPS。
- 回傳資料只允許 metadata：agent alias、status、OS 類別、last_seen_present 與 aggregate counts。
- 新增 agent registry no-false-green：若 Wazuh manager registry 回 `agent_total=0`，API 必須回 `wazuh_agent_registry_empty`；若低於 server-side `IWOOOS_WAZUH_EXPECTED_MIN_AGENT_COUNT`，API 必須回 `wazuh_agent_registry_below_expected`。
- summary 會回 `expected_min_agent_count`、`agent_registry_empty_count`、`agent_below_expected_minimum_count`、`agent_visibility_no_false_green_count`；這些只描述 aggregate 狀態，不公開 agent 身分或內網位址。
- 不回傳 raw Wazuh payload、agent 原名、內網 IP、token、password 或 secret。
- 新增 source guard，阻擋硬編 Wazuh 內網 URL / port、帳密、關 TLS、假 SOC dashboard、假 CVE、raw payload 與 legacy dashboard component 回流。
- 新增 production readback 腳本，部署後可直接驗證 public API 不再 404、schema / status / boundary 正確，且沒有 raw payload、內網 IP、agent 原名或 secret 洩漏。
- 新增 release gate snapshot 與 guard，固定 source-side、feature branch push、formal main release、production deploy 與 production route readback 已完成；同時保留 Wazuh live metadata / manager registry / active response / host write 仍未授權，避免後續把 route 200 誤判成 Wazuh 納管恢復。
- 新增 release lane preflight snapshot 與 guard，固定正式 release 前必須選擇 `formal_gitea_merge`、`formal_patch_apply` 或 `maintainer_local_push_with_safe_credential` 其中一條合規 lane，且 owner ack / evidence 未到齊前不得推主線、deploy、force push、使用明文 token workaround 或改 runtime。
- 新增 release owner request 草稿與 owner response acceptance 帳本，將 required ack flags、required evidence fields、allowed release methods、blocked actions、forbidden payloads 與 reviewer checks 機器可讀化；目前 request sent、response received / accepted、release ready、runtime gate 全部維持 `0`。
- 新增 live metadata env gate，固定部署後要先通過 production route readback、server-side env owner response、secret source metadata、Wazuh manager health ref、readonly account scope、post-enable readback、rollback 與 no-secret / no-raw-payload attestation；目前 live query authorized 仍為 `0`。
- 新增 IwoooS 前台「Wazuh 即時中繼資料環境閘門」卡片，公開顯示上述 gate 的 `0 / false` 邊界；文案全部為繁體中文治理語，不放工作視窗逐字稿、委派 XML、聊天內容或個人英文名稱。

## 已完成驗證

已在 `/private/tmp/awoooi-iwooos-wazuh-boundary-verify-20260624` 執行：

```bash
pytest apps/api/tests/test_iwooos_wazuh_api.py
python3 scripts/security/wazuh-readonly-route-boundary-guard.py --root .
python3 scripts/security/wazuh-readonly-release-gate.py --root .
python3 scripts/security/wazuh-readonly-release-lane-preflight.py --root .
python3 scripts/security/wazuh-readonly-release-owner-request.py --root .
python3 scripts/security/wazuh-readonly-release-owner-response-acceptance.py --root .
python3 scripts/security/wazuh-readonly-live-metadata-env-gate.py --root .
python3 scripts/security/security-mirror-progress-guard.py --root .
python3 scripts/ops/doc-secrets-sanity-check.py docs apps/api/src/api/v1/iwooos.py apps/api/src/services/iwooos_wazuh_readonly_status.py apps/api/src/services/iwooos_runtime_security_readback.py apps/web/src/app/api/iwooos/wazuh/route.ts scripts/security/wazuh-readonly-route-boundary-guard.py scripts/security/wazuh-readonly-production-readback.py scripts/security/wazuh-readonly-release-gate.py scripts/security/wazuh-readonly-release-lane-preflight.py scripts/security/wazuh-readonly-release-owner-request.py scripts/security/wazuh-readonly-release-owner-response-acceptance.py scripts/security/wazuh-readonly-live-metadata-env-gate.py
python3 -m py_compile apps/api/src/api/v1/iwooos.py apps/api/src/services/iwooos_wazuh_readonly_status.py apps/api/src/services/iwooos_runtime_security_readback.py scripts/security/wazuh-readonly-route-boundary-guard.py scripts/security/wazuh-readonly-production-readback.py scripts/security/wazuh-readonly-release-gate.py scripts/security/wazuh-readonly-release-lane-preflight.py scripts/security/wazuh-readonly-release-owner-request.py scripts/security/wazuh-readonly-release-owner-response-acceptance.py scripts/security/wazuh-readonly-live-metadata-env-gate.py scripts/security/security-mirror-progress-guard.py
git diff --check
node -e "JSON.parse(require('fs').readFileSync('apps/web/messages/zh-TW.json','utf8')); JSON.parse(require('fs').readFileSync('apps/web/messages/en.json','utf8')); console.log('i18n json ok')"
cmp -s apps/web/messages/zh-TW.json apps/web/messages/en.json
pnpm --filter @awoooi/web typecheck
NEXT_PUBLIC_API_URL=https://awoooi.wooo.work NEXT_PRIVATE_BUILD_WORKER_COUNT=1 SENTRY_SUPPRESS_GLOBAL_ERROR_HANDLER_FILE_WARNING=1 pnpm --filter @awoooi/web build
```

驗證結果：

- `pytest apps/api/tests/test_iwooos_wazuh_api.py`：`6 passed`。
- `wazuh-readonly-route-boundary-guard`：`route=3 public_ui_files=1 forbidden=0 runtime_gate=0`。
- `wazuh-readonly-release-gate`：`source=1 push=1 main=1 deploy=1 readback=1 runtime_gate=0`。
- `wazuh-readonly-release-lane-preflight`：`ready=0 acks=0/6 evidence=0/6 runtime_gate=0`。
- `wazuh-readonly-release-owner-request`：`drafts=1 sent=0 accepted=0 runtime_gate=0`。
- `wazuh-readonly-release-owner-response-acceptance`：`received=0 accepted=0 acks=0/6 evidence=0/6 runtime_gate=0`。
- `wazuh-readonly-live-metadata-env-gate`：`route_readback=1 owner=0 secret_meta=0 live_query=0 runtime_gate=0`。
- `security-mirror-progress-guard`：`SECURITY_MIRROR_PROGRESS_GUARD_OK`。
- `doc-secrets-sanity-check`：`DOC_SECRET_SANITY_OK scanned_files=973`。
- `py_compile`：通過。
- `git diff --check`：通過。
- i18n JSON parse：通過。
- `zh-TW` / `en` messages mirror：通過。
- `pnpm --filter @awoooi/web typecheck`：通過。
- Web production build：通過，`92/92` static pages，`/zh-TW/iwooos` route size `61.8 kB`、First Load JS `292 kB`；build env 使用公網 `NEXT_PUBLIC_API_URL=https://awoooi.wooo.work`，未使用內網 IP。
- 本機 preview desktop：`/zh-TW/iwooos` 卡片可見，水平溢出 `false`，沒有工作視窗 / 委派 / 對話字樣，卡片沒有英文流程裸字。
- 本機 preview mobile `390x844`：卡片可見，水平溢出 `false`，同樣沒有工作視窗 / 委派 / 對話字樣。

## 乾淨套用 Proof

乾淨套用 proof 需從最新 `gitea/main` 建立獨立 worktree：

```bash
git worktree add /private/tmp/awoooi-iwooos-wazuh-release-apply-check-<timestamp> gitea/main
git am /private/tmp/awoooi-iwooos-wazuh-boundary-release-patch-<timestamp>/*.patch
```

此 proof 只證明 patch 可乾淨落在最新主線並通過 guard，不代表已合併主線、已部署或已啟用 Wazuh live metadata。最終 patch SHA 與 apply-check commit 應由 release 執行者在 final docs commit 之後用命令讀回，不寫入會自我漂移的 committed 文件。

乾淨套用 worktree 驗證結果：

- `pytest apps/api/tests/test_iwooos_wazuh_api.py`：`6 passed`。
- `python3 scripts/security/wazuh-readonly-route-boundary-guard.py --root .`：`WAZUH_READONLY_ROUTE_BOUNDARY_GUARD_OK route=3 public_ui_files=1 forbidden=0 runtime_gate=0`。
- `python3 scripts/security/wazuh-readonly-release-gate.py --root .`：`WAZUH_READONLY_RELEASE_GATE_OK source=1 push=1 main=1 deploy=1 readback=1 runtime_gate=0`。
- `python3 scripts/security/wazuh-readonly-release-lane-preflight.py --root .`：`WAZUH_READONLY_RELEASE_LANE_PREFLIGHT_OK ready=0 acks=0/6 evidence=0/6 runtime_gate=0`。
- `python3 scripts/security/security-mirror-progress-guard.py --root .`：`SECURITY_MIRROR_PROGRESS_GUARD_OK`。
- `python3 scripts/ops/doc-secrets-sanity-check.py ...`：`DOC_SECRET_SANITY_OK scanned_files=973`。
- `python3 -m py_compile ...`：通過。
- `git diff --check`：通過。

正式部署後的 production 現況記錄：

```bash
python3 scripts/security/wazuh-readonly-production-readback.py --json
```

預期只可回 IwoooS Wazuh read-only route 的安全邊界狀態；目前尚未啟用 Wazuh live metadata，因此不得顯示綠燈。

目前實測：

```json
{"api_status":"disabled_waiting_iwooos_wazuh_owner_gate","configured":false,"http_status":200,"runtime_gate_count":0,"schema_version":"iwooos_wazuh_production_readback_v1","status":"production_readback_passed"}
```

這個讀回不代表 Wazuh manager registry 已恢復；它只代表 route 部署完成且目前仍正確停在 owner gate。

## Release 前 Gate

下一階段 gate 需確認：

- Wazuh live metadata env gate 目前固定 `owner=0`、`secret_meta=0`、`live_query=0`；不得把一般「批准繼續」當成 server-side env owner response。
- route 已部署完成；下一步不是再修 404，而是建立 Wazuh manager registry 只讀驗收、Dashboard stored API / RBAC / TLS 修復與 post-enable readback。
- 不得複製舊 workspace 的內嵌明文 Gitea token。
- 不得把 Wazuh URL、帳密、token、cookie、private key、runner token 或 webhook secret 寫入 repo。
- 不得為了讓 agent 顯示回來而直接改 Nginx、Docker、K8s、firewall、Wazuh manager、Wazuh rule、Wazuh decoder、stored API、RBAC、TLS 或 Wazuh active response。
- 若要啟用 live metadata query，必須由正式 secrets / env 注入 `IWOOOS_WAZUH_READONLY_ENABLED=true` 與 Wazuh server-side env，且要先有 owner gate。

## Production Readback 預期

部署後、尚未啟用 Wazuh env 時：

```bash
curl -sS https://awoooi.wooo.work/api/iwooos/wazuh
```

預期：

- HTTP `200`。
- `schema_version=iwooos_wazuh_readonly_status_v1`。
- `status=disabled_waiting_iwooos_wazuh_owner_gate`。
- `configured=false`。
- `runtime_gate_count=0`。
- `active_response_authorized=false`。
- `host_write_authorized=false`。
- 不含內網 IP、agent 原名、token、password、raw payload。

正式驗收命令：

```bash
python3 scripts/security/wazuh-readonly-production-readback.py --json
```

正式驗收不接受 404；若仍回 404，代表 FastAPI 相容 route 尚未部署或 gateway 尚未接到新 API。

若 owner gate 與 server-side env 已正式啟用：

- 成功時可回 `readonly_metadata_available`。
- manager registry 為空時必須回 `wazuh_agent_registry_empty`，不得顯示綠燈。
- manager registry 低於 `IWOOOS_WAZUH_EXPECTED_MIN_AGENT_COUNT` 時必須回 `wazuh_agent_registry_below_expected`，不得顯示綠燈。
- Wazuh 不可達時可回 `wazuh_readonly_metadata_unavailable`。
- 任何情況都不得回 raw payload、agent 原名、內網 IP、secret。
- 任何情況都不得因 route 可用而自動打開 active response、host write、Kali active scan 或 SOAR action。

## 完成度

| 項目 | 完成度 | 狀態 |
|---|---:|---|
| Wazuh public API 404 source-side 修補 | `100%` | 已完成本地分支 HEAD |
| Wazuh route boundary source guard | `100%` | 已納入 `security-mirror-progress-guard` |
| Production readback 驗收腳本 | `100%` | 已完成；正式部署後不得接受 404 |
| Wazuh release gate snapshot / guard | `100%` | 已完成；固定 source / feature branch / main / deploy / readback 已完成，live metadata 仍 blocked |
| Wazuh release lane preflight | `100%` | 已完成；owner acks `0/6`、evidence `0/6`、正式 release ready `0` |
| Wazuh release owner request / acceptance | `100%` | 已完成只讀草稿與收件帳本；request sent `0`、response accepted `0` |
| Wazuh live metadata env gate | `100%` | 已完成只讀 gate；route readback `1`，owner / secret metadata / live query 仍 `0` |
| Wazuh agent registry no-false-green | `100%` | source-side 已能區分 registry 空與低於預期；production live registry accepted 仍 `0` |
| IwoooS 前台 Wazuh live metadata env gate 卡片 | `100%` | source-side 與本機桌機 / 手機驗證完成；production route readback 已完成，live metadata 仍 `0` |
| 乾淨套用 proof | `100%` | patch set 可落在最新 `gitea/main` 並通過同組 guard；最終 hash 以 release 前 readback 為準 |
| Gitea feature branch push | `100%` | `codex/iwooos-wazuh-boundary-guard-20260624` 已推送；精確 HEAD 以 release 前讀回為準 |
| Formal main release | `100%` | 已進正式主線 |
| Production deploy / readback | `100%` | 已回 `200 disabled_waiting_iwooos_wazuh_owner_gate` |
| Wazuh server-side env enable | `0%` | 等待 owner gate 與 secrets 注入 |
| Wazuh manager agent registry accepted | `0%` | 尚未取得可驗收 registry truth |
| Wazuh event refs / host forensic refs accepted | `0%` | 尚未收到合格證據 |
| Wazuh active response / host write / Kali active scan | `0%` | 必須維持 false |

## 下一步優先序

1. 依 `wazuh-readonly-live-metadata-env-gate.snapshot.json` 補 server-side env owner response、secret source metadata、Wazuh manager health ref、readonly account scope 與 post-enable readback，才可考慮啟用 Wazuh read-only metadata query。
2. 取得 Wazuh manager agent registry 的脫敏、可驗收只讀讀回：總數、在線、離線、從未連線、最後連線時間窗與 Dashboard API 狀態參照。
3. 修復 Dashboard stored API / RBAC / run_as / rate-limit / TLS trust 退化；修復前不得把 Dashboard 看不到 agent 解讀成 agent 全部消失，也不得把 transport count 解讀成 agent registry 恢復。
4. 收件 Wazuh manager health ref、agent status ref、event refs、host forensic refs 與 containment / recovery proof。
5. 仍禁止 active response、host write、firewall / Nginx / Docker / K8s runtime action、Kali active scan、secret 明文收集。
