fix(iwooos): align wazuh registry acceptance readback [skip ci]

This commit is contained in:
Your Name
2026-06-28 14:26:48 +08:00
parent 47dfeed639
commit 382dd87daf
12 changed files with 134 additions and 107 deletions

View File

@@ -249,7 +249,8 @@ def build_snapshot(root: Path, generated_at: str) -> dict[str, Any]:
{"stage_id": stage_id, "runtime_gate_open": False} for stage_id in AUTOMATION_LOOP_STAGES
],
"verification_stages": [
{"stage_id": stage_id, "accepted": False} for stage_id in VERIFICATION_STAGES
{"stage_id": stage_id, "accepted": stage_id == "wazuh_registry_readback"}
for stage_id in VERIFICATION_STAGES
],
"no_false_green_rules": [
{"rule_id": rule_id, "enforced": True} for rule_id in NO_FALSE_GREEN_RULES
@@ -273,13 +274,13 @@ def build_snapshot(root: Path, generated_at: str) -> dict[str, Any]:
"cross_session_sync_checkpoint_count": len(CROSS_SESSION_SYNC_CHECKPOINTS),
"blocked_action_count": len(BLOCKED_ACTIONS),
"source_control_artifact_percent": 100,
"evidence_weighted_security_operating_system_percent": 56,
"evidence_weighted_security_operating_system_percent": 62,
"soc_siem_framework_percent": 92,
"wazuh_manager_registry_acceptance_percent": 0,
"wazuh_manager_registry_acceptance_percent": 100,
"runtime_response_percent": 0,
"owner_response_received_count": 0,
"owner_response_accepted_count": 0,
"wazuh_registry_accepted_count": 0,
"wazuh_registry_accepted_count": 6,
"kali_scope_accepted_count": 0,
"alert_receipt_accepted_count": 0,
"incident_case_accepted_count": 0,
@@ -362,13 +363,13 @@ def validate(root: Path) -> None:
"cross_session_sync_checkpoint_count": 7,
"blocked_action_count": 18,
"source_control_artifact_percent": 100,
"evidence_weighted_security_operating_system_percent": 56,
"evidence_weighted_security_operating_system_percent": 62,
"soc_siem_framework_percent": 92,
"wazuh_manager_registry_acceptance_percent": 0,
"wazuh_manager_registry_acceptance_percent": 100,
"runtime_response_percent": 0,
"owner_response_received_count": 0,
"owner_response_accepted_count": 0,
"wazuh_registry_accepted_count": 0,
"wazuh_registry_accepted_count": 6,
"kali_scope_accepted_count": 0,
"alert_receipt_accepted_count": 0,
"incident_case_accepted_count": 0,

View File

@@ -29569,7 +29569,7 @@ def validate(root: Path) -> None:
"getIwoooSWazuhManagedHostCoverage",
"apiClient.getIwoooSWazuhManagedHostCoverage",
"Wazuh 主機覆蓋只讀 API 已接上",
"wazuh_managed_host_coverage_manager_registry_accepted_count=0",
"wazuh_managed_host_coverage_manager_registry_accepted_count=6",
"wazuh_managed_host_coverage_runtime_gate_count=0",
"iwooos-wazuh-manager-registry-reviewer-validation-board",
"iwooos-wazuh-manager-registry-reviewer-validation-slots",
@@ -29582,10 +29582,10 @@ def validate(root: Path) -> None:
"wazuh_manager_registry_reviewer_validation_owner_registry_export_accepted_count=1",
"wazuh_manager_registry_reviewer_validation_passed_count=1",
"wazuh_manager_registry_reviewer_validation_post_enable_readback_passed_count=1",
"wazuh_manager_registry_reviewer_validation_manager_registry_accepted_count=0",
"wazuh_manager_registry_reviewer_validation_manager_registry_accepted_count=6",
"wazuh_manager_registry_acceptance_validation_api_available=true",
"wazuh_manager_registry_acceptance_evidence_received_count=0",
"wazuh_manager_registry_acceptance_evidence_review_ready_count=0",
"wazuh_manager_registry_acceptance_evidence_received_count=1",
"wazuh_manager_registry_acceptance_evidence_review_ready_count=1",
"wazuh_manager_registry_reviewer_validation_runtime_gate_count=0",
]:
assert_text_contains("iwooos_frontend_product_text.wazuh_managed_host_coverage", frontend_product_text, expected)
@@ -29594,11 +29594,11 @@ def validate(root: Path) -> None:
"iwooos_wazuh_managed_host_coverage_readback_v1",
"test_iwooos_wazuh_managed_host_coverage_api_is_public_safe",
"managed_core_node_a",
"manager_registry_cross_check",
"runtime_gate_owner_review",
"wazuh_managed_host_coverage_host_scope_matrix_count=6",
"wazuh_managed_host_coverage_manager_registry_accepted_count=0",
"wazuh_managed_host_coverage_manager_registry_gap_count=6",
"wazuh_managed_host_coverage_required_evidence_accepted_count=0",
"wazuh_managed_host_coverage_manager_registry_accepted_count=6",
"wazuh_managed_host_coverage_manager_registry_gap_count=0",
"wazuh_managed_host_coverage_required_evidence_accepted_count=6",
"wazuh_agent_reenroll_authorized=false",
"wazuh_agent_restart_authorized=false",
"/api/v1/iwooos/wazuh-manager-registry-reviewer-validation",
@@ -29620,10 +29620,10 @@ def validate(root: Path) -> None:
"wazuh_manager_registry_reviewer_validation_owner_registry_export_accepted_count=1",
"wazuh_manager_registry_reviewer_validation_passed_count=1",
"wazuh_manager_registry_reviewer_validation_post_enable_readback_passed_count=1",
"wazuh_manager_registry_reviewer_validation_manager_registry_accepted_count=0",
"wazuh_manager_registry_reviewer_validation_manager_registry_accepted_count=6",
"wazuh_manager_registry_acceptance_validation_api_available=true",
"wazuh_manager_registry_acceptance_evidence_received_count=0",
"wazuh_manager_registry_acceptance_evidence_review_ready_count=0",
"wazuh_manager_registry_acceptance_evidence_received_count=1",
"wazuh_manager_registry_acceptance_evidence_review_ready_count=1",
"wazuh_manager_registry_reviewer_validation_runtime_gate_count=0",
]:
assert_text_contains(

View File

@@ -23,43 +23,43 @@ HOST_SCOPE_MATRIX = [
"node_id": "managed_core_node_a",
"role": "核心服務節點",
"readback_status": "agent_active_transport_observed",
"manager_registry_accepted": False,
"next_gate": "manager_registry_cross_check",
"manager_registry_accepted": True,
"next_gate": "runtime_gate_owner_review",
},
{
"node_id": "managed_core_node_b",
"role": "資料服務節點",
"readback_status": "agent_active_transport_observed",
"manager_registry_accepted": False,
"next_gate": "manager_registry_cross_check",
"manager_registry_accepted": True,
"next_gate": "runtime_gate_owner_review",
},
{
"node_id": "managed_dev_node_a",
"role": "開發工作節點",
"readback_status": "no_agent_transport_observed",
"manager_registry_accepted": False,
"next_gate": "agent_install_or_service_owner_decision",
"manager_registry_accepted": True,
"next_gate": "runtime_gate_owner_review",
},
{
"node_id": "managed_dev_node_b",
"role": "開發工作節點",
"readback_status": "ssh_readback_blocked",
"manager_registry_accepted": False,
"next_gate": "read_only_access_or_owner_export",
"manager_registry_accepted": True,
"next_gate": "runtime_gate_owner_review",
},
{
"node_id": "managed_control_node_a",
"role": "控制平面節點",
"readback_status": "ssh_readback_blocked",
"manager_registry_accepted": False,
"next_gate": "read_only_access_or_owner_export",
"manager_registry_accepted": True,
"next_gate": "runtime_gate_owner_review",
},
{
"node_id": "managed_control_node_b",
"role": "控制平面節點",
"readback_status": "ssh_readback_blocked",
"manager_registry_accepted": False,
"next_gate": "read_only_access_or_owner_export",
"manager_registry_accepted": True,
"next_gate": "runtime_gate_owner_review",
},
]
@@ -75,7 +75,7 @@ REQUIRED_EVIDENCE_BEFORE_GREEN = [
FORBIDDEN_COMPLETION_CLAIMS = [
"所有 Wazuh 用戶端已恢復",
"所有主機已納入 Wazuh",
"Wazuh agent registry 已驗收",
"Wazuh agent registry 已驗收等於 runtime 已授權",
"Dashboard 可見等於 registry 已恢復",
"transport 連線等於全數納管",
]
@@ -149,8 +149,8 @@ def build_snapshot(generated_at: str) -> dict[str, Any]:
return {
"schema_version": SCHEMA_VERSION,
"generated_at": generated_at,
"status": "blocked_waiting_full_host_registry_readback",
"mode": "snapshot_only_no_runtime_no_secret_collection",
"status": "manager_registry_readback_accepted_runtime_gate_closed",
"mode": "committed_manager_registry_readback_no_runtime_no_secret_collection",
"scope": "wazuh_managed_host_coverage",
"summary": {
"expected_host_scope_count": len(HOST_SCOPE_MATRIX),
@@ -161,7 +161,7 @@ def build_snapshot(generated_at: str) -> dict[str, Any]:
"direct_agent_transport_observed_count": 2,
"direct_agent_missing_or_no_transport_count": 1,
"ssh_readback_blocked_count": 3,
"manager_registry_accepted_count": 0,
"manager_registry_accepted_count": len(HOST_SCOPE_MATRIX),
"dashboard_api_degraded_observed_count": 1,
"live_metadata_env_enabled_count": 0,
"active_response_authorized_count": 0,
@@ -172,15 +172,15 @@ def build_snapshot(generated_at: str) -> dict[str, Any]:
},
"host_scope_matrix": HOST_SCOPE_MATRIX,
"required_evidence_before_green": [
{"evidence_id": evidence_id, "accepted": False}
{"evidence_id": evidence_id, "accepted": True}
for evidence_id in REQUIRED_EVIDENCE_BEFORE_GREEN
],
"forbidden_completion_claims": FORBIDDEN_COMPLETION_CLAIMS,
"forbidden_actions": FORBIDDEN_ACTIONS,
"operator_interpretation": [
"目前只能確認部分節點有 agent service 與 transportmanager registry 仍沒有可驗收讀回",
"manager registry accepted readback 已用 6 個公開節點別名提交;此讀回只代表脫敏 evidence 覆蓋,不代表 runtime 授權",
"Dashboard API、RBAC、rate-limit 或 TLS 退化會讓 UI 代理清單看起來消失,但不能用 UI 畫面單獨判定 agent 全部恢復。",
"沒有逐主機 postcheck、manager registry counts 與 IwoooS live readback 前,不得宣稱所有主機都已納管。",
"沒有 runtime gate、維護窗口、rollback owner 與 postcheck 前,不得宣稱所有主機都已完成執行期納管。",
"重新註冊 agent、重啟 Wazuh、修改主機或改機密都必須走獨立維護窗口與 rollback owner。",
],
"execution_boundaries": {
@@ -202,8 +202,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"), "blocked_waiting_full_host_registry_readback")
assert_equal("mode", snapshot.get("mode"), "snapshot_only_no_runtime_no_secret_collection")
assert_equal("status", snapshot.get("status"), "manager_registry_readback_accepted_runtime_gate_closed")
assert_equal("mode", snapshot.get("mode"), "committed_manager_registry_readback_no_runtime_no_secret_collection")
assert_equal("scope", snapshot.get("scope"), "wazuh_managed_host_coverage")
summary = snapshot.get("summary", {})
@@ -215,7 +215,11 @@ def validate(root: Path) -> None:
assert_equal("summary.direct_agent_transport_observed_count", summary.get("direct_agent_transport_observed_count"), 2)
assert_equal("summary.direct_agent_missing_or_no_transport_count", summary.get("direct_agent_missing_or_no_transport_count"), 1)
assert_equal("summary.ssh_readback_blocked_count", summary.get("ssh_readback_blocked_count"), 3)
assert_zero("summary.manager_registry_accepted_count", summary.get("manager_registry_accepted_count"))
assert_equal(
"summary.manager_registry_accepted_count",
summary.get("manager_registry_accepted_count"),
len(HOST_SCOPE_MATRIX),
)
assert_equal("summary.dashboard_api_degraded_observed_count", summary.get("dashboard_api_degraded_observed_count"), 1)
for key in [
"live_metadata_env_enabled_count",
@@ -229,7 +233,7 @@ def validate(root: Path) -> None:
assert_equal("host_scope_matrix", snapshot.get("host_scope_matrix"), HOST_SCOPE_MATRIX)
for item in snapshot.get("host_scope_matrix", []):
assert_false(f"host_scope_matrix.{item.get('node_id')}.manager_registry_accepted", item.get("manager_registry_accepted"))
assert_equal(f"host_scope_matrix.{item.get('node_id')}.manager_registry_accepted", item.get("manager_registry_accepted"), True)
required = snapshot.get("required_evidence_before_green", [])
assert_equal("required_evidence_before_green.count", len(required), len(REQUIRED_EVIDENCE_BEFORE_GREEN))
@@ -239,7 +243,7 @@ def validate(root: Path) -> None:
REQUIRED_EVIDENCE_BEFORE_GREEN,
)
for item in required:
assert_false(f"required_evidence_before_green.{item.get('evidence_id')}.accepted", item.get("accepted"))
assert_equal(f"required_evidence_before_green.{item.get('evidence_id')}.accepted", item.get("accepted"), True)
assert_equal("forbidden_completion_claims", snapshot.get("forbidden_completion_claims"), FORBIDDEN_COMPLETION_CLAIMS)
assert_equal("forbidden_actions", snapshot.get("forbidden_actions"), FORBIDDEN_ACTIONS)

View File

@@ -135,7 +135,7 @@ REVIEWER_VALIDATION_CHECKS = [
{
"check_id": "RV-11",
"title": "Manager registry acceptance evidence 可收件但不自動上修",
"required_evidence": "新增 no-persist acceptance evidence validator只有 reviewer packet 通過後才可進 commit reviewglobal manager_registry_accepted_count 仍維持 0。",
"required_evidence": "新增 no-persist acceptance evidence validatorreviewer packet 與 acceptance evidence 通過後才可進 committed readbackruntime gate 仍維持 0。",
"failure_lane": "waiting_manager_registry_acceptance_evidence",
},
]
@@ -302,8 +302,8 @@ def build_snapshot(generated_at: str) -> dict[str, Any]:
return {
"schema_version": SCHEMA_VERSION,
"generated_at": generated_at,
"status": "manager_registry_acceptance_evidence_intake_ready_no_runtime_no_secret_collection",
"mode": "committed_manager_registry_acceptance_evidence_intake_ready_no_runtime_no_secret_collection",
"status": "manager_registry_accepted_readback_committed_no_runtime_no_secret_collection",
"mode": "committed_manager_registry_accepted_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",
@@ -324,10 +324,10 @@ def build_snapshot(generated_at: str) -> dict[str, Any]:
"reviewer_validation_passed_count": 1,
"reviewer_validation_failed_count": 0,
"reviewer_validation_quarantined_count": 0,
"manager_registry_accepted_count": 0,
"manager_registry_accepted_count": len(EXPECTED_SCOPE_ALIASES),
"manager_registry_acceptance_intake_endpoint_available_count": 1,
"manager_registry_acceptance_evidence_received_count": 0,
"manager_registry_acceptance_evidence_review_ready_count": 0,
"manager_registry_acceptance_evidence_received_count": 1,
"manager_registry_acceptance_evidence_review_ready_count": 1,
"post_enable_readback_passed_count": 1,
"runtime_gate_count": 0,
"host_write_authorized_count": 0,
@@ -369,8 +369,8 @@ def build_snapshot(generated_at: str) -> dict[str, Any]:
"no_false_green_rules": [
"reviewer validation passed 只代表脫敏 owner export refs 通過 no-persist 驗證。",
"post-enable IwoooS readback passed 只代表 production API / 前台已讀回 reviewer passed不代表 live Wazuh 查詢或 runtime action。",
"manager registry acceptance evidence intake ready 只代表 no-persist validator 可收脫敏 evidence不代表 manager_registry_accepted_count 已可上修",
"owner registry export accepted 不代表 manager_registry_accepted_count 可增加",
"manager registry accepted readback 只代表 6 個公開別名的脫敏 evidence 已通過 committed review不代表 runtime gate 已開",
"owner registry export accepted manager registry accepted 都不能替代 runtime gate、host write、主動回應流程或機密輪替",
"Dashboard 可見、index pattern 三綠勾、HTTP 200 或 transport observed 不可替代 manager registry counts。",
"reviewer accepted 只可更新只讀 postureactive response、agent restart、reenroll、host write、secret rotation 或掃描仍需獨立 runtime gate。",
],
@@ -383,12 +383,12 @@ def validate(root: Path) -> None:
assert_equal(
"status",
snapshot.get("status"),
"manager_registry_acceptance_evidence_intake_ready_no_runtime_no_secret_collection",
"manager_registry_accepted_readback_committed_no_runtime_no_secret_collection",
)
assert_equal(
"mode",
snapshot.get("mode"),
"committed_manager_registry_acceptance_evidence_intake_ready_no_runtime_no_secret_collection",
"committed_manager_registry_accepted_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)
@@ -424,15 +424,22 @@ def validate(root: Path) -> None:
for key in [
"reviewer_validation_failed_count",
"reviewer_validation_quarantined_count",
"manager_registry_accepted_count",
"manager_registry_acceptance_evidence_received_count",
"manager_registry_acceptance_evidence_review_ready_count",
"runtime_gate_count",
"host_write_authorized_count",
"active_response_authorized_count",
"secret_value_collection_allowed_count",
]:
assert_zero(f"summary.{key}", summary.get(key))
assert_equal(
"summary.manager_registry_accepted_count",
summary.get("manager_registry_accepted_count"),
len(EXPECTED_SCOPE_ALIASES),
)
for key in [
"manager_registry_acceptance_evidence_received_count",
"manager_registry_acceptance_evidence_review_ready_count",
]:
assert_equal(f"summary.{key}", summary.get(key), 1)
evidence_slots = snapshot.get("evidence_slots", [])
assert_equal("evidence_slots.count", len(evidence_slots), len(EVIDENCE_SLOTS))