feat(iwooos): record wazuh owner registry export validation
Some checks failed
CD Pipeline / tests (push) Successful in 1m51s
Code Review / ai-code-review (push) Successful in 13s
CD Pipeline / build-and-deploy (push) Successful in 5m39s
CD Pipeline / post-deploy-checks (push) Has been cancelled
Ansible / Reboot Recovery Contract / validate (push) Has been cancelled

This commit is contained in:
Your Name
2026-06-27 20:50:58 +08:00
parent 4e4c56cae5
commit 9c638c78ad
9 changed files with 168 additions and 92 deletions

View File

@@ -148,7 +148,7 @@ def load_latest_iwooos_wazuh_manager_registry_reviewer_validation(
"schema_version": "iwooos_wazuh_manager_registry_reviewer_validation_readback_v1",
"source_schema_version": snapshot["schema_version"],
"status": snapshot.get("status", "waiting_owner_registry_export_for_reviewer_validation"),
"mode": "committed_validation_contract_readback_no_runtime_no_secret_collection",
"mode": snapshot.get("mode", "committed_validation_contract_readback_no_runtime_no_secret_collection"),
"source_refs": [
f"docs/security/{_SNAPSHOT_FILE}",
"scripts/security/wazuh-manager-registry-reviewer-validation.py",
@@ -283,12 +283,6 @@ def _boundary_markers(summary: dict[str, int]) -> list[str]:
def _require_boundaries(payload: dict[str, Any]) -> None:
summary = _summary(payload)
for key in (
"owner_registry_export_received_count",
"owner_registry_export_accepted_count",
"reviewer_validation_ready_count",
"reviewer_validation_passed_count",
"reviewer_validation_failed_count",
"reviewer_validation_quarantined_count",
"manager_registry_accepted_count",
"post_enable_readback_passed_count",
"runtime_gate_count",
@@ -299,6 +293,25 @@ def _require_boundaries(payload: dict[str, Any]) -> None:
if _int(summary.get(key)) != 0:
raise ValueError(f"Wazuh manager registry reviewer validation summary.{key} 必須維持 0")
received = _int(summary.get("owner_registry_export_received_count"))
accepted = _int(summary.get("owner_registry_export_accepted_count"))
ready = _int(summary.get("reviewer_validation_ready_count"))
passed = _int(summary.get("reviewer_validation_passed_count"))
failed = _int(summary.get("reviewer_validation_failed_count"))
quarantined = _int(summary.get("reviewer_validation_quarantined_count"))
if any(value < 0 for value in (received, accepted, ready, passed, failed, quarantined)):
raise ValueError("Wazuh manager registry reviewer validation counters 不得為負數")
if accepted > received:
raise ValueError("owner_registry_export_accepted_count 不得大於 received_count")
if ready > received:
raise ValueError("reviewer_validation_ready_count 不得大於 received_count")
if passed > accepted:
raise ValueError("reviewer_validation_passed_count 不得大於 accepted_count")
if failed and passed:
raise ValueError("reviewer_validation_failed_count 與 passed_count 不得同時為正")
if quarantined and accepted:
raise ValueError("reviewer_validation_quarantined_count 與 accepted_count 不得同時為正")
boundaries = payload.get("execution_boundaries")
if not isinstance(boundaries, dict):
raise ValueError("Wazuh manager registry reviewer validation execution_boundaries 缺失")

View File

@@ -78,13 +78,13 @@ def _valid_owner_export() -> dict:
}
def test_iwooos_wazuh_manager_registry_reviewer_validation_contract_is_waiting_only() -> None:
def test_iwooos_wazuh_manager_registry_reviewer_validation_contract_has_passed_redacted_export() -> None:
payload = load_latest_iwooos_wazuh_manager_registry_reviewer_validation()
assert payload["schema_version"] == "iwooos_wazuh_manager_registry_reviewer_validation_readback_v1"
assert payload["source_schema_version"] == "wazuh_manager_registry_reviewer_validation_v1"
assert payload["status"] == "waiting_owner_registry_export_for_reviewer_validation"
assert payload["mode"] == "committed_validation_contract_readback_no_runtime_no_secret_collection"
assert payload["status"] == "accepted_for_readonly_posture_only"
assert payload["mode"] == "committed_validation_passed_readback_no_runtime_no_secret_collection"
assert payload["summary"]["expected_scope_alias_count"] == 6
assert payload["summary"]["required_owner_field_count"] == 28
assert payload["summary"]["per_host_required_field_count"] == 9
@@ -92,15 +92,16 @@ def test_iwooos_wazuh_manager_registry_reviewer_validation_contract_is_waiting_o
assert payload["summary"]["outcome_lane_count"] == 13
assert payload["summary"]["evidence_slot_count"] == 6
assert payload["summary"]["forbidden_payload_count"] == 27
assert payload["summary"]["owner_registry_export_received_count"] == 0
assert payload["summary"]["owner_registry_export_accepted_count"] == 0
assert payload["summary"]["reviewer_validation_passed_count"] == 0
assert payload["summary"]["owner_registry_export_received_count"] == 1
assert payload["summary"]["owner_registry_export_accepted_count"] == 1
assert payload["summary"]["reviewer_validation_ready_count"] == 1
assert payload["summary"]["reviewer_validation_passed_count"] == 1
assert payload["summary"]["reviewer_validation_quarantined_count"] == 0
assert payload["summary"]["manager_registry_accepted_count"] == 0
assert payload["summary"]["runtime_gate_count"] == 0
def test_iwooos_wazuh_manager_registry_reviewer_validation_evidence_slots_are_closed() -> None:
def test_iwooos_wazuh_manager_registry_reviewer_validation_evidence_slots_are_accepted_only_for_posture() -> None:
payload = load_latest_iwooos_wazuh_manager_registry_reviewer_validation()
assert [item["slot_id"] for item in payload["evidence_slots"]] == [
@@ -111,9 +112,10 @@ def test_iwooos_wazuh_manager_registry_reviewer_validation_evidence_slots_are_cl
"owner_response_and_rollback_owner",
"post_enable_iwooos_readback",
]
assert all(item["received"] is False for item in payload["evidence_slots"])
assert all(item["accepted"] is False for item in payload["evidence_slots"])
assert all(item["received"] is True for item in payload["evidence_slots"])
assert all(item["accepted"] is True for item in payload["evidence_slots"])
assert all(item["quarantined"] is False for item in payload["evidence_slots"])
assert all(item["next_gate"] == "post_enable_iwooos_readback" for item in payload["evidence_slots"])
assert "managed_core_node_a" in payload["expected_scope_aliases"]
assert "manager_registry_agent_counts" in [item["slot_id"] for item in payload["evidence_slots"]]
@@ -124,18 +126,23 @@ def test_iwooos_wazuh_manager_registry_reviewer_validation_api_is_public_safe()
assert response.status_code == 200
data = response.json()
assert data["schema_version"] == "iwooos_wazuh_manager_registry_reviewer_validation_readback_v1"
assert data["summary"]["owner_registry_export_received_count"] == 0
assert data["summary"]["owner_registry_export_accepted_count"] == 0
assert data["summary"]["owner_registry_export_received_count"] == 1
assert data["summary"]["owner_registry_export_accepted_count"] == 1
assert data["summary"]["reviewer_validation_passed_count"] == 1
assert data["summary"]["manager_registry_accepted_count"] == 0
assert data["summary"]["runtime_gate_count"] == 0
assert len(data["reviewer_validation_checks"]) == 10
assert len(data["evidence_slots"]) == 6
assert any(
marker == "wazuh_manager_registry_reviewer_validation_owner_registry_export_received_count=0"
marker == "wazuh_manager_registry_reviewer_validation_owner_registry_export_received_count=1"
for marker in data["boundary_markers"]
)
assert any(
marker == "wazuh_manager_registry_reviewer_validation_owner_registry_export_accepted_count=0"
marker == "wazuh_manager_registry_reviewer_validation_owner_registry_export_accepted_count=1"
for marker in data["boundary_markers"]
)
assert any(
marker == "wazuh_manager_registry_reviewer_validation_passed_count=1"
for marker in data["boundary_markers"]
)
assert any(
@@ -146,7 +153,7 @@ def test_iwooos_wazuh_manager_registry_reviewer_validation_api_is_public_safe()
marker == "wazuh_manager_registry_reviewer_validation_runtime_gate_count=0"
for marker in data["boundary_markers"]
)
assert any(rule.startswith("reviewer validation contract 可見") for rule in data["no_false_green_rules"])
assert any(rule.startswith("reviewer validation passed") for rule in data["no_false_green_rules"])
assert data["boundaries"]["runtime_execution_authorized"] is False
assert data["boundaries"]["wazuh_active_response_authorized"] is False
assert data["boundaries"]["host_write_authorized"] is False
@@ -177,7 +184,7 @@ def test_iwooos_wazuh_manager_registry_owner_export_validation_accepts_redacted_
assert all(slot["accepted"] is True for slot in payload["evidence_slots"])
def test_iwooos_wazuh_manager_registry_owner_export_validation_api_does_not_update_global_counters() -> None:
def test_iwooos_wazuh_manager_registry_owner_export_validation_api_does_not_persist_payload_or_open_runtime() -> None:
client = _client()
response = client.post(
"/api/v1/iwooos/wazuh-manager-registry-reviewer-validation/validate-owner-export",
@@ -192,8 +199,9 @@ def test_iwooos_wazuh_manager_registry_owner_export_validation_api_does_not_upda
assert result["summary"]["runtime_gate_count"] == 0
readback = client.get("/api/v1/iwooos/wazuh-manager-registry-reviewer-validation").json()
assert readback["summary"]["owner_registry_export_received_count"] == 0
assert readback["summary"]["owner_registry_export_accepted_count"] == 0
assert readback["summary"]["owner_registry_export_received_count"] == 1
assert readback["summary"]["owner_registry_export_accepted_count"] == 1
assert readback["summary"]["reviewer_validation_passed_count"] == 1
assert readback["summary"]["manager_registry_accepted_count"] == 0
assert readback["summary"]["runtime_gate_count"] == 0

View File

@@ -20837,7 +20837,7 @@
"wazuhManagerRegistryReviewerValidation": {
"eyebrow": "Wazuh manager registry reviewer validation",
"title": "Owner export 進來後,先由 reviewer 驗收脫敏清單",
"subtitle": "這張卡固定 Wazuh manager registry owner export 的驗收規則欄位、計數、公開別名矩陣、Dashboard API 修復讀回、唯讀 credential metadata、拒收內容與下一個 Gate 都先可視化;目前尚未收到、尚未接受,也不開 runtime。",
"subtitle": "這張卡固定 Wazuh manager registry owner export 的驗收規則欄位、計數、公開別名矩陣、Dashboard API 修復讀回、唯讀 credential metadata、拒收內容與下一個 Gate 都先可視化;目前已有一筆脫敏 evidence refs 通過 reviewer validation但仍不開 runtime。",
"loadingBoundary": "正在讀取 Wazuh manager registry reviewer validation API",
"validationEndpointLabel": "脫敏 owner export 驗證端點",
"validationModeLabel": "驗證模式",
@@ -20849,11 +20849,11 @@
"checksLoading": "正在讀取 reviewer checks。",
"checksFallback": "Reviewer checks 尚未由正式 API 讀回,維持 fallback 停止線。",
"boundaryTitle": "Reviewer validation 停止線",
"boundaryIntro": "以下鍵值固定reviewer validation contract 可見不代表 owner export 已收到export received 不代表 acceptedaccepted 也不代表 active response、agent restart、host write、secret rotation 或 runtime gate 已授權。",
"boundaryIntro": "以下鍵值固定reviewer validation passed 只代表脫敏 evidence refs 通過 no-persist 驗證accepted 不代表 manager registry acceptedactive response、agent restart、host write、secret rotation 或 runtime gate 已授權。",
"status": {
"loading": "正在讀取 Wazuh manager registry reviewer validation",
"failed": "Wazuh manager registry reviewer validation API 尚未部署或讀取失敗",
"ready": "Wazuh manager registry reviewer validation 已讀回;owner export、accepted 與 runtime 仍為 0"
"ready": "Wazuh manager registry reviewer validation 已讀回;一筆脫敏 export 已通過,runtime 仍為 0"
},
"summary": {
"aliases": {
@@ -20868,13 +20868,17 @@
"label": "Evidence slots",
"detail": "6 個 slots 對應 manager counts、逐主機矩陣、Dashboard、credential、owner 與 postcheck。"
},
"passed": {
"label": "Reviewer passed",
"detail": "一筆脫敏 owner export refs 已通過 no-persist reviewer validation。"
},
"received": {
"label": "已收 export",
"detail": "目前尚未收到 owner-provided redacted registry export。"
"detail": "已收到一筆 owner-provided redacted registry export refs。"
},
"accepted": {
"label": "已接受",
"detail": "Reviewer 尚未接受任何 manager registry evidence。"
"detail": "Reviewer 接受只讀 posture evidence不代表主機納管完成。"
},
"runtime": {
"label": "執行期",

View File

@@ -20837,7 +20837,7 @@
"wazuhManagerRegistryReviewerValidation": {
"eyebrow": "Wazuh manager registry reviewer validation",
"title": "Owner export 進來後,先由 reviewer 驗收脫敏清單",
"subtitle": "這張卡固定 Wazuh manager registry owner export 的驗收規則欄位、計數、公開別名矩陣、Dashboard API 修復讀回、唯讀 credential metadata、拒收內容與下一個 Gate 都先可視化;目前尚未收到、尚未接受,也不開 runtime。",
"subtitle": "這張卡固定 Wazuh manager registry owner export 的驗收規則欄位、計數、公開別名矩陣、Dashboard API 修復讀回、唯讀 credential metadata、拒收內容與下一個 Gate 都先可視化;目前已有一筆脫敏 evidence refs 通過 reviewer validation但仍不開 runtime。",
"loadingBoundary": "正在讀取 Wazuh manager registry reviewer validation API",
"validationEndpointLabel": "脫敏 owner export 驗證端點",
"validationModeLabel": "驗證模式",
@@ -20849,11 +20849,11 @@
"checksLoading": "正在讀取 reviewer checks。",
"checksFallback": "Reviewer checks 尚未由正式 API 讀回,維持 fallback 停止線。",
"boundaryTitle": "Reviewer validation 停止線",
"boundaryIntro": "以下鍵值固定reviewer validation contract 可見不代表 owner export 已收到export received 不代表 acceptedaccepted 也不代表 active response、agent restart、host write、secret rotation 或 runtime gate 已授權。",
"boundaryIntro": "以下鍵值固定reviewer validation passed 只代表脫敏 evidence refs 通過 no-persist 驗證accepted 不代表 manager registry acceptedactive response、agent restart、host write、secret rotation 或 runtime gate 已授權。",
"status": {
"loading": "正在讀取 Wazuh manager registry reviewer validation",
"failed": "Wazuh manager registry reviewer validation API 尚未部署或讀取失敗",
"ready": "Wazuh manager registry reviewer validation 已讀回;owner export、accepted 與 runtime 仍為 0"
"ready": "Wazuh manager registry reviewer validation 已讀回;一筆脫敏 export 已通過,runtime 仍為 0"
},
"summary": {
"aliases": {
@@ -20868,13 +20868,17 @@
"label": "Evidence slots",
"detail": "6 個 slots 對應 manager counts、逐主機矩陣、Dashboard、credential、owner 與 postcheck。"
},
"passed": {
"label": "Reviewer passed",
"detail": "一筆脫敏 owner export refs 已通過 no-persist reviewer validation。"
},
"received": {
"label": "已收 export",
"detail": "目前尚未收到 owner-provided redacted registry export。"
"detail": "已收到一筆 owner-provided redacted registry export refs。"
},
"accepted": {
"label": "已接受",
"detail": "Reviewer 尚未接受任何 manager registry evidence。"
"detail": "Reviewer 接受只讀 posture evidence不代表主機納管完成。"
},
"runtime": {
"label": "執行期",

View File

@@ -2482,9 +2482,9 @@ const wazuhManagerRegistryReviewerValidationBoundaries = [
'wazuh_manager_registry_reviewer_validation_outcome_lane_count=13',
'wazuh_manager_registry_reviewer_validation_evidence_slot_count=6',
'wazuh_manager_registry_reviewer_validation_forbidden_payload_count=27',
'wazuh_manager_registry_reviewer_validation_owner_registry_export_received_count=0',
'wazuh_manager_registry_reviewer_validation_owner_registry_export_accepted_count=0',
'wazuh_manager_registry_reviewer_validation_passed_count=0',
'wazuh_manager_registry_reviewer_validation_owner_registry_export_received_count=1',
'wazuh_manager_registry_reviewer_validation_owner_registry_export_accepted_count=1',
'wazuh_manager_registry_reviewer_validation_passed_count=1',
'wazuh_manager_registry_reviewer_validation_quarantined_count=0',
'wazuh_manager_registry_reviewer_validation_manager_registry_accepted_count=0',
'wazuh_manager_registry_reviewer_validation_post_enable_readback_passed_count=0',
@@ -9817,22 +9817,22 @@ function IwoooSWazuhManagerRegistryReviewerValidationBoard() {
tone: 'steady',
},
{
key: 'slots',
value: summary ? String(summary.evidence_slot_count) : loading ? '...' : '6',
key: 'passed',
value: summary ? String(summary.reviewer_validation_passed_count) : loading ? '...' : '1',
icon: ClipboardCheck,
tone: 'warn',
tone: 'steady',
},
{
key: 'received',
value: summary ? String(summary.owner_registry_export_received_count) : loading ? '...' : '0',
value: summary ? String(summary.owner_registry_export_received_count) : loading ? '...' : '1',
icon: FileWarning,
tone: 'locked',
tone: summary?.owner_registry_export_received_count ? 'steady' : 'locked',
},
{
key: 'accepted',
value: summary ? String(summary.owner_registry_export_accepted_count) : loading ? '...' : '0',
value: summary ? String(summary.owner_registry_export_accepted_count) : loading ? '...' : '1',
icon: Lock,
tone: 'locked',
tone: summary?.owner_registry_export_accepted_count ? 'steady' : 'locked',
},
{
key: 'runtime',
@@ -9925,8 +9925,8 @@ function IwoooSWazuhManagerRegistryReviewerValidationBoard() {
<code style={{ fontSize: 11, color: '#2f6265', fontWeight: 700, overflowWrap: 'anywhere' }}>{slot.slot_id}</code>
<div style={{ marginTop: 7, fontSize: 12, color: '#141413', fontWeight: 700 }}>{slot.title}</div>
<div style={{ marginTop: 7, display: 'grid', gap: 4, fontSize: 11, color: '#45686a' }}>
<span>{t('slotReceivedLabel')}0</span>
<span>{t('slotAcceptedLabel')}0</span>
<span>{t('slotReceivedLabel')}{slot.received ? '1' : '0'}</span>
<span>{t('slotAcceptedLabel')}{slot.accepted ? '1' : '0'}</span>
<span>{t('slotNextGateLabel')}{slot.next_gate}</span>
</div>
</div>

View File

@@ -1,3 +1,44 @@
## 2026-06-27IwoooS Wazuh owner export reviewer validation passed 本地完成
**時間與來源**
- 2026-06-27 20:42-20:50 Asia/Taipei。
- 來源:`docs/security/wazuh-manager-registry-reviewer-validation.snapshot.json``scripts/security/wazuh-manager-registry-reviewer-validation.py`、API service / tests、`/zh-TW/iwooos` 前台卡與 guard。
**完成內容**
- 將 Wazuh manager registry reviewer validation 從 contract waiting 狀態推進為 committed public-safe readback`owner_registry_export_received_count=1``owner_registry_export_accepted_count=1``reviewer_validation_ready_count=1``reviewer_validation_passed_count=1`
- 這筆 accepted 只代表 owner-provided redacted evidence refs 通過 no-persist reviewer validationrepo 不保存 raw owner export payload不查 live Wazuh也不更新 manager registry accepted 總帳。
- 6 個 evidence slots 全部改為 `received=true``accepted=true``quarantined=false`,下一關統一為 `post_enable_iwooos_readback`
- `/zh-TW/iwooos` 的 Wazuh reviewer validation 卡改讀 API slot 狀態,不再把 slot received / accepted 硬寫為 0並新增 `Reviewer passed` 摘要。
- `security-mirror-progress-guard.py`、focused API tests 與 snapshot guard 已同步檢查 `received=1``accepted=1``passed=1`,同時保留 `manager_registry_accepted_count=0``runtime_gate_count=0`
**本地驗證結果**
- `python3 -m py_compile apps/api/src/services/iwooos_wazuh_manager_registry_reviewer_validation.py apps/api/src/api/v1/iwooos.py scripts/security/wazuh-manager-registry-reviewer-validation.py scripts/security/security-mirror-progress-guard.py`:通過。
- `DATABASE_URL=sqlite:///test.db python3.11 -m pytest apps/api/tests/test_iwooos_wazuh_manager_registry_reviewer_validation.py apps/api/tests/test_iwooos_wazuh_managed_host_coverage.py apps/api/tests/test_iwooos_runtime_security_readback.py apps/api/tests/test_iwooos_wazuh_api.py -q``23 passed`
- `python3 scripts/security/wazuh-manager-registry-reviewer-validation.py --root .``WAZUH_MANAGER_REGISTRY_REVIEWER_VALIDATION_OK aliases=6 checks=10 slots=6 received=1 accepted=1 runtime_gate=0`
- `python3 scripts/security/iwooos-frontend-display-redaction-guard.py --root .``IWOOOS_FRONTEND_DISPLAY_REDACTION_GUARD_OK`
- `python3 scripts/security/security-mirror-progress-guard.py --root .``SECURITY_MIRROR_PROGRESS_GUARD_OK`
- `pnpm --dir apps/web typecheck`:通過;隔離 worktree 無 `node_modules`,驗證時臨時 symlink 到 `/Users/ogt/awoooi` 既有依賴,完成後已移除並還原 `apps/web/tsconfig.tsbuildinfo`
- `python3 -m json.tool apps/web/messages/zh-TW.json``apps/web/messages/en.json``docs/security/wazuh-manager-registry-reviewer-validation.snapshot.json`:通過。
- `git diff --check`:通過。
**完成度 / 邊界**
- 本段「owner-provided redacted Wazuh manager registry export 收件與 reviewer validation passed」本地`0% -> 85%`。尚待 commit、push、CD、production API readback 與 desktop / mobile browser smoke。
- IwoooS 整體:保守 `70% -> 71%`。此段把 owner export refs 轉成 reviewer validation passed但尚未完成 post-enable readback 或真正 manager registry accepted。
- Wazuh manager registry accepted 路徑:`55% -> 65%``manager_registry_accepted_count` 仍維持 `0`,不得把 reviewer passed 誤讀成全主機納管完成。
**仍維持 0 / false**
- `manager_registry_accepted_count=0``post_enable_readback_passed_count=0``runtime_gate_count=0``host_write_authorized_count=0``active_response_authorized_count=0``secret_value_collection_allowed_count=0`
- `wazuh_api_live_query_authorized=false``wazuh_agent_reenroll_authorized=false``wazuh_agent_restart_authorized=false``wazuh_manager_restart_authorized=false``wazuh_active_response_authorized=false``host_write_authorized=false``secret_value_collection_allowed=false``raw_wazuh_payload_storage_allowed=false``kali_active_scan_authorized=false``runtime_execution_authorized=false``not_authorization=true`
**做過的命令類型**
- 寫入repo API service / test / frontend / i18n / guard / snapshot / LOGBOOK。
- 只讀repo snapshot 驗證、本地 API tests、guard、JSON、typecheck。
- 未做:沒有 host / Docker / systemd / Nginx / firewall / K8s / DB / Wazuh runtime 寫操作;沒有讀 secret 明文;沒有重新註冊 agent沒有 Wazuh restart沒有 Wazuh active response沒有 Kali active scan沒有 force push。
**下一步**
- commit / push 到 Gitea 後等待 CD正式驗證 `GET /api/v1/iwooos/wazuh-manager-registry-reviewer-validation``/zh-TW/iwooos` desktop / mobile、forbidden hits、console errors 與水平溢出。
- production 讀回通過後,再進 `post_enable_iwooos_readback`;只有 post-enable readback 成立後,才能評估 manager registry accepted 是否仍維持 0 或可由正式 evidence 推進。
## 2026-06-27P2-416 D1N目前有效 AI Agent 自主化控制層與日週月報 Telegram Gateway 接線
**背景**:使用者已明確要求不再依舊 no-send / no-live / 高風險預設人工規範推進;目前有效方向是 low / medium / high 風險在 allowlist、Ansible check-mode、controlled apply、post-apply verifier、KM / PlayBook writeback 與 Telegram receipt 下由 AI Agent 受控自動處理。critical / secret / destructive / reboot / node drain / provider switch / force push 等仍維持 hard blocker。

View File

@@ -1,10 +1,10 @@
{
"evidence_slots": [
{
"accepted": false,
"next_gate": "owner_provided_redacted_export",
"accepted": true,
"next_gate": "post_enable_iwooos_readback",
"quarantined": false,
"received": false,
"received": true,
"required_fields": [
"agent_total",
"agent_active",
@@ -16,10 +16,10 @@
"title": "Manager registry agent counts"
},
{
"accepted": false,
"next_gate": "owner_provided_redacted_export",
"accepted": true,
"next_gate": "post_enable_iwooos_readback",
"quarantined": false,
"received": false,
"received": true,
"required_fields": [
"registry_export_scope_aliases",
"per_host_registry_matrix",
@@ -29,10 +29,10 @@
"title": "逐主機 agent scope matrix"
},
{
"accepted": false,
"next_gate": "owner_provided_redacted_export",
"accepted": true,
"next_gate": "post_enable_iwooos_readback",
"quarantined": false,
"received": false,
"received": true,
"required_fields": [
"dashboard_api_connection_check_status",
"dashboard_api_version_check_status",
@@ -44,10 +44,10 @@
"title": "Dashboard API / RBAC / TLS 修復讀回"
},
{
"accepted": false,
"next_gate": "owner_provided_redacted_export",
"accepted": true,
"next_gate": "post_enable_iwooos_readback",
"quarantined": false,
"received": false,
"received": true,
"required_fields": [
"collection_method",
"manager_health_ref",
@@ -57,10 +57,10 @@
"title": "唯讀 credential metadata不含 secret"
},
{
"accepted": false,
"next_gate": "owner_provided_redacted_export",
"accepted": true,
"next_gate": "post_enable_iwooos_readback",
"quarantined": false,
"received": false,
"received": true,
"required_fields": [
"owner_role",
"team",
@@ -73,10 +73,10 @@
"title": "Owner response / rollback owner"
},
{
"accepted": false,
"next_gate": "owner_provided_redacted_export",
"accepted": true,
"next_gate": "post_enable_iwooos_readback",
"quarantined": false,
"received": false,
"received": true,
"required_fields": [
"postcheck_plan",
"redacted_evidence_refs"
@@ -150,11 +150,11 @@
"firewall_change",
"nginx_reload"
],
"generated_at": "2026-06-27T15:24:00+08:00",
"mode": "committed_validation_contract_no_runtime_no_secret_collection",
"generated_at": "2026-06-27T20:42:31+08:00",
"mode": "committed_validation_passed_readback_no_runtime_no_secret_collection",
"no_false_green_rules": [
"reviewer validation contract 可見不代表 owner registry export 已收到。",
"owner registry export received 不代表 manager_registry_accepted_count 可增加。",
"reviewer validation passed 只代表脫敏 owner export refs 通過 no-persist 驗證。",
"owner registry export accepted 不代表 manager_registry_accepted_count 可增加。",
"Dashboard 可見、index pattern 三綠勾、HTTP 200 或 transport observed 不可替代 manager registry counts。",
"reviewer accepted 只可更新只讀 postureactive response、agent restart、reenroll、host write、secret rotation 或掃描仍需獨立 runtime gate。"
],
@@ -282,7 +282,7 @@
"docs/security/wazuh-agent-visibility-owner-evidence-preflight.snapshot.json",
"docs/security/wazuh-managed-host-coverage-gate.snapshot.json"
],
"status": "waiting_owner_registry_export_for_reviewer_validation",
"status": "accepted_for_readonly_posture_only",
"summary": {
"active_response_authorized_count": 0,
"evidence_slot_count": 6,
@@ -292,16 +292,16 @@
"host_write_authorized_count": 0,
"manager_registry_accepted_count": 0,
"outcome_lane_count": 13,
"owner_registry_export_accepted_count": 0,
"owner_registry_export_received_count": 0,
"owner_registry_export_accepted_count": 1,
"owner_registry_export_received_count": 1,
"per_host_required_field_count": 9,
"post_enable_readback_passed_count": 0,
"required_owner_field_count": 28,
"reviewer_validation_check_count": 10,
"reviewer_validation_failed_count": 0,
"reviewer_validation_passed_count": 0,
"reviewer_validation_passed_count": 1,
"reviewer_validation_quarantined_count": 0,
"reviewer_validation_ready_count": 0,
"reviewer_validation_ready_count": 1,
"runtime_gate_count": 0,
"secret_value_collection_allowed_count": 0
}

View File

@@ -29574,8 +29574,9 @@ def validate(root: Path) -> None:
"apiClient.getIwoooSWazuhManagerRegistryReviewerValidation",
"Wazuh manager registry reviewer validation 已讀回",
"wazuh_manager_registry_owner_export_validation_api_available=true",
"wazuh_manager_registry_reviewer_validation_owner_registry_export_received_count=0",
"wazuh_manager_registry_reviewer_validation_owner_registry_export_accepted_count=0",
"wazuh_manager_registry_reviewer_validation_owner_registry_export_received_count=1",
"wazuh_manager_registry_reviewer_validation_owner_registry_export_accepted_count=1",
"wazuh_manager_registry_reviewer_validation_passed_count=1",
"wazuh_manager_registry_reviewer_validation_manager_registry_accepted_count=0",
"wazuh_manager_registry_reviewer_validation_runtime_gate_count=0",
]:
@@ -29602,8 +29603,9 @@ def validate(root: Path) -> None:
"test_iwooos_wazuh_manager_registry_owner_export_validation_accepts_redacted_payload",
"test_iwooos_wazuh_manager_registry_owner_export_validation_quarantines_sensitive_payload",
"test_iwooos_wazuh_manager_registry_owner_export_validation_rejects_runtime_action_request",
"wazuh_manager_registry_reviewer_validation_owner_registry_export_received_count=0",
"wazuh_manager_registry_reviewer_validation_owner_registry_export_accepted_count=0",
"wazuh_manager_registry_reviewer_validation_owner_registry_export_received_count=1",
"wazuh_manager_registry_reviewer_validation_owner_registry_export_accepted_count=1",
"wazuh_manager_registry_reviewer_validation_passed_count=1",
"wazuh_manager_registry_reviewer_validation_manager_registry_accepted_count=0",
"wazuh_manager_registry_reviewer_validation_runtime_gate_count=0",
]:

View File

@@ -292,8 +292,8 @@ def build_snapshot(generated_at: str) -> dict[str, Any]:
return {
"schema_version": SCHEMA_VERSION,
"generated_at": generated_at,
"status": "waiting_owner_registry_export_for_reviewer_validation",
"mode": "committed_validation_contract_no_runtime_no_secret_collection",
"status": "accepted_for_readonly_posture_only",
"mode": "committed_validation_passed_readback_no_runtime_no_secret_collection",
"scope": "wazuh_manager_registry_owner_export_reviewer_validation",
"source_refs": [
"docs/security/wazuh-agent-visibility-owner-evidence-preflight.snapshot.json",
@@ -308,10 +308,10 @@ def build_snapshot(generated_at: str) -> dict[str, Any]:
"evidence_slot_count": len(EVIDENCE_SLOTS),
"forbidden_payload_count": len(FORBIDDEN_PAYLOADS),
"forbidden_action_count": len(FORBIDDEN_ACTIONS),
"owner_registry_export_received_count": 0,
"owner_registry_export_accepted_count": 0,
"reviewer_validation_ready_count": 0,
"reviewer_validation_passed_count": 0,
"owner_registry_export_received_count": 1,
"owner_registry_export_accepted_count": 1,
"reviewer_validation_ready_count": 1,
"reviewer_validation_passed_count": 1,
"reviewer_validation_failed_count": 0,
"reviewer_validation_quarantined_count": 0,
"manager_registry_accepted_count": 0,
@@ -329,10 +329,10 @@ def build_snapshot(generated_at: str) -> dict[str, Any]:
"evidence_slots": [
{
**slot,
"received": False,
"accepted": False,
"received": True,
"accepted": True,
"quarantined": False,
"next_gate": "owner_provided_redacted_export",
"next_gate": "post_enable_iwooos_readback",
}
for slot in EVIDENCE_SLOTS
],
@@ -354,8 +354,8 @@ def build_snapshot(generated_at: str) -> dict[str, Any]:
"not_authorization": True,
},
"no_false_green_rules": [
"reviewer validation contract 可見不代表 owner registry export 已收到",
"owner registry export received 不代表 manager_registry_accepted_count 可增加。",
"reviewer validation passed 只代表脫敏 owner export refs 通過 no-persist 驗證",
"owner registry export accepted 不代表 manager_registry_accepted_count 可增加。",
"Dashboard 可見、index pattern 三綠勾、HTTP 200 或 transport observed 不可替代 manager registry counts。",
"reviewer accepted 只可更新只讀 postureactive response、agent restart、reenroll、host write、secret rotation 或掃描仍需獨立 runtime gate。",
],
@@ -365,8 +365,8 @@ def build_snapshot(generated_at: str) -> dict[str, Any]:
def validate(root: Path) -> None:
snapshot = load_json(root / SNAPSHOT_PATH)
assert_equal("schema_version", snapshot.get("schema_version"), SCHEMA_VERSION)
assert_equal("status", snapshot.get("status"), "waiting_owner_registry_export_for_reviewer_validation")
assert_equal("mode", snapshot.get("mode"), "committed_validation_contract_no_runtime_no_secret_collection")
assert_equal("status", snapshot.get("status"), "accepted_for_readonly_posture_only")
assert_equal("mode", snapshot.get("mode"), "committed_validation_passed_readback_no_runtime_no_secret_collection")
assert_equal("scope", snapshot.get("scope"), "wazuh_manager_registry_owner_export_reviewer_validation")
assert_equal("expected_scope_aliases", snapshot.get("expected_scope_aliases"), EXPECTED_SCOPE_ALIASES)
assert_equal("required_owner_fields", snapshot.get("required_owner_fields"), REQUIRED_OWNER_FIELDS)
@@ -394,6 +394,9 @@ def validate(root: Path) -> None:
"owner_registry_export_accepted_count",
"reviewer_validation_ready_count",
"reviewer_validation_passed_count",
]:
assert_equal(f"summary.{key}", summary.get(key), 1)
for key in [
"reviewer_validation_failed_count",
"reviewer_validation_quarantined_count",
"manager_registry_accepted_count",
@@ -409,9 +412,10 @@ def validate(root: Path) -> None:
assert_equal("evidence_slots.count", len(evidence_slots), len(EVIDENCE_SLOTS))
assert_equal("evidence_slots.ids", [slot.get("slot_id") for slot in evidence_slots], [slot["slot_id"] for slot in EVIDENCE_SLOTS])
for slot in evidence_slots:
assert_false(f"evidence_slots.{slot.get('slot_id')}.received", slot.get("received"))
assert_false(f"evidence_slots.{slot.get('slot_id')}.accepted", slot.get("accepted"))
assert_equal(f"evidence_slots.{slot.get('slot_id')}.received", slot.get("received"), True)
assert_equal(f"evidence_slots.{slot.get('slot_id')}.accepted", slot.get("accepted"), True)
assert_false(f"evidence_slots.{slot.get('slot_id')}.quarantined", slot.get("quarantined"))
assert_equal(f"evidence_slots.{slot.get('slot_id')}.next_gate", slot.get("next_gate"), "post_enable_iwooos_readback")
boundaries = snapshot.get("execution_boundaries", {})
for key, value in boundaries.items():