diff --git a/apps/api/src/services/awooop_ansible_audit_service.py b/apps/api/src/services/awooop_ansible_audit_service.py index b748fd76..06617cc4 100644 --- a/apps/api/src/services/awooop_ansible_audit_service.py +++ b/apps/api/src/services/awooop_ansible_audit_service.py @@ -217,6 +217,18 @@ def _int_or_none(value: Any) -> int | None: return None +def _is_controlled_apply_record(row: dict[str, Any]) -> bool: + if not row: + return False + if row.get("approval_source"): + return True + if str(row.get("execution_mode") or "").strip().lower() == "controlled_apply": + return True + if "controlled_apply" in _tags(row): + return True + return str(row.get("actor") or "").strip().lower() == "ansible_controlled_apply_worker" + + def _is_ansible_operation(row: dict[str, Any]) -> bool: operation_type = str(_get(row, "operation_type") or "").lower() if operation_type in ANSIBLE_OPERATION_TYPES: @@ -341,7 +353,7 @@ def summarize_ansible_execution(records: list[dict[str, Any]]) -> dict[str, Any] "pending_check_mode_total": pending_check_mode_total, "applied_success_total": applied_success_total, "applied": applied_success_total > 0, - "controlled_apply": bool(latest_apply) and bool(approval_source), + "controlled_apply": bool(latest_apply) and _is_controlled_apply_record(latest_apply), "latest_operation_type": focused.get("operation_type"), "latest_status": focused.get("status"), "latest_catalog_id": focused.get("catalog_id"), diff --git a/apps/api/src/services/awooop_ansible_check_mode_service.py b/apps/api/src/services/awooop_ansible_check_mode_service.py index d44b4c69..a88679b8 100644 --- a/apps/api/src/services/awooop_ansible_check_mode_service.py +++ b/apps/api/src/services/awooop_ansible_check_mode_service.py @@ -805,6 +805,41 @@ async def _record_post_apply_verifier_and_learning( return status +async def _send_controlled_apply_telegram_receipt( + claim: AnsibleCheckModeClaim, + result: AnsibleRunResult, + *, + apply_op_id: str, + writeback: dict[str, bool], + project_id: str, +) -> bool: + try: + from src.services.telegram_gateway import get_telegram_gateway + + response = await get_telegram_gateway().send_controlled_apply_result_receipt( + incident_id=claim.incident_id, + catalog_id=claim.catalog_id, + apply_op_id=apply_op_id, + playbook_path=claim.apply_playbook_path, + verification_result=_post_apply_verification_result(result), + returncode=result.returncode, + duration_ms=result.duration_ms, + verifier_written=bool(writeback.get("verification")), + learning_written=bool(writeback.get("learning")), + project_id=project_id, + ) + return bool(response) + except Exception as exc: + logger.warning( + "ansible_controlled_apply_telegram_receipt_failed", + incident_id=claim.incident_id, + catalog_id=claim.catalog_id, + apply_op_id=apply_op_id, + error=str(exc), + ) + return False + + async def backfill_missing_auto_repair_execution_receipts_once( *, project_id: str = "awoooi", @@ -1322,6 +1357,13 @@ async def run_controlled_apply_for_claim( apply_op_id=apply_op_id, project_id=project_id, ) + telegram_receipt_sent = await _send_controlled_apply_telegram_receipt( + claim, + result, + apply_op_id=apply_op_id, + writeback=writeback, + project_id=project_id, + ) logger.info( "ansible_controlled_apply_completed", @@ -1335,6 +1377,7 @@ async def run_controlled_apply_for_claim( auto_repair_receipt_written=receipt_written, post_apply_verification_written=writeback.get("verification"), post_apply_learning_written=writeback.get("learning"), + telegram_receipt_sent=telegram_receipt_sent, ) return result diff --git a/apps/api/src/services/iwooos_wazuh_manager_registry_reviewer_validation.py b/apps/api/src/services/iwooos_wazuh_manager_registry_reviewer_validation.py index 934413fb..9ba655c8 100644 --- a/apps/api/src/services/iwooos_wazuh_manager_registry_reviewer_validation.py +++ b/apps/api/src/services/iwooos_wazuh_manager_registry_reviewer_validation.py @@ -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 缺失") diff --git a/apps/api/src/services/telegram_gateway.py b/apps/api/src/services/telegram_gateway.py index a8a7aad9..fa0af992 100644 --- a/apps/api/src/services/telegram_gateway.py +++ b/apps/api/src/services/telegram_gateway.py @@ -9182,6 +9182,107 @@ class TelegramGateway: } return await self._send_request("sendMessage", payload) + async def send_controlled_apply_result_receipt( + self, + *, + incident_id: str, + catalog_id: str, + apply_op_id: str, + playbook_path: str, + verification_result: str, + returncode: int, + duration_ms: int, + verifier_written: bool, + learning_written: bool, + project_id: str = "awoooi", + ) -> dict: + """Send and mirror the AI Agent controlled-apply result receipt.""" + + if not self.alert_chat_id: + logger.warning( + "controlled_apply_result_receipt_skipped_no_chat", + incident_id=incident_id, + apply_op_id=apply_op_id, + ) + return {} + + success = verification_result == "success" and returncode == 0 + next_step = ( + "monitor_for_regression" + if success + else "queue_ai_rollback_or_playbook_repair" + ) + title = ( + "CONTROLLED APPLY RESULT|AI Agent 受控執行完成" + if success + else "CONTROLLED APPLY RESULT|AI Agent 受控執行待修復" + ) + truth_chain: dict[str, object] | None = None + try: + from src.services.awooop_truth_chain_service import fetch_truth_chain + + truth_chain = await fetch_truth_chain( + source_id=incident_id, + project_id=project_id or "awoooi", + ) + except Exception as exc: + logger.warning( + "controlled_apply_result_truth_chain_snapshot_failed", + incident_id=incident_id, + apply_op_id=apply_op_id, + error=str(exc), + ) + + status_snapshot = _callback_reply_awooop_status_chain_snapshot( + incident_id=incident_id, + truth_chain=truth_chain, + ) + source_extra = _callback_reply_source_envelope_extra( + incident_id=incident_id, + failure_context="controlled_apply_result", + status="callback_reply_sent", + chunk_index=0, + chunk_count=1, + callback_action="controlled_apply_result", + parse_mode="HTML", + awooop_status_chain=status_snapshot, + ) + lines = [ + f"{html.escape(title)}", + f"Incident: {html.escape(str(incident_id))}", + f"Catalog: {html.escape(str(catalog_id or '--'))}", + f"Apply op: {html.escape(str(apply_op_id or '')[:8])}", + f"PlayBook: {html.escape(str(playbook_path or '--'))}", + ( + "Result: " + f"{html.escape(str(verification_result or 'missing'))} " + f"/ rc {html.escape(str(returncode))} " + f"/ {html.escape(str(duration_ms))}ms" + ), + ( + "Receipts: verifier " + f"{html.escape(_bool_code(verifier_written))} / KM " + f"{html.escape(_bool_code(learning_written))}" + ), + f"Next: {html.escape(next_step)}", + f"Runs: {html.escape(incident_runs_url(incident_id, project_id=project_id or 'awoooi'))}", + ] + payload: dict = { + "chat_id": self.alert_chat_id, + "text": "\n".join(lines)[:4096], + "parse_mode": "HTML", + "disable_web_page_preview": True, + } + reply_markup = incident_truth_chain_reply_markup( + incident_id, + project_id=project_id or "awoooi", + ) + if reply_markup: + payload["reply_markup"] = reply_markup + if source_extra: + payload[_AWOOOP_SOURCE_ENVELOPE_EXTRA_KEY] = source_extra + return await self._send_request("sendMessage", payload) + # ========================================================================= # 2026-04-24 Claude Sonnet 4.6 (ADR-095 WS4): Hermes NL 回覆 # ========================================================================= diff --git a/apps/api/tests/test_ai_agent_autonomous_runtime_control.py b/apps/api/tests/test_ai_agent_autonomous_runtime_control.py index 7a41b887..ca6e679f 100644 --- a/apps/api/tests/test_ai_agent_autonomous_runtime_control.py +++ b/apps/api/tests/test_ai_agent_autonomous_runtime_control.py @@ -14,7 +14,7 @@ def test_ai_agent_autonomous_runtime_control_uses_current_owner_directive(): "p2_416_d1n_autonomous_runtime_control_prod_readback_v2" ) assert data["program_status"]["deploy_attempt_note"] == ( - "cd_3660_failed_host_pressure_guard_retry" + "cd_3673_retry_after_host_pressure_gate_fix" ) assert data["program_status"]["legacy_no_send_no_live_rules_overridden"] is True assert data["program_status"]["implementation_completion_percent"] == 88 diff --git a/apps/api/tests/test_ai_agent_autonomous_runtime_control_api.py b/apps/api/tests/test_ai_agent_autonomous_runtime_control_api.py index 8e24d768..35d34342 100644 --- a/apps/api/tests/test_ai_agent_autonomous_runtime_control_api.py +++ b/apps/api/tests/test_ai_agent_autonomous_runtime_control_api.py @@ -55,7 +55,7 @@ def test_get_ai_agent_autonomous_runtime_control_api(): "p2_416_d1n_autonomous_runtime_control_prod_readback_v2" ) assert data["program_status"]["deploy_attempt_note"] == ( - "cd_3660_failed_host_pressure_guard_retry" + "cd_3673_retry_after_host_pressure_gate_fix" ) assert data["current_policy"]["owner_review_required_for_low_medium_high"] is False assert data["report_delivery"]["status"] == "telegram_gateway_delivery_enabled" diff --git a/apps/api/tests/test_awooop_truth_chain_service.py b/apps/api/tests/test_awooop_truth_chain_service.py index 563ae56f..d2e0a9a7 100644 --- a/apps/api/tests/test_awooop_truth_chain_service.py +++ b/apps/api/tests/test_awooop_truth_chain_service.py @@ -21,6 +21,7 @@ from src.services.awooop_ansible_check_mode_service import ( _post_apply_km_path_type, _post_apply_verification_result, _record_auto_repair_execution_receipt, + _send_controlled_apply_telegram_receipt, build_ansible_apply_command, build_ansible_check_mode_claim_input, build_ansible_check_mode_command, @@ -28,6 +29,7 @@ from src.services.awooop_ansible_check_mode_service import ( claim_pending_check_modes, detect_ansible_transport_blockers, recent_ansible_transport_blockers, + run_controlled_apply_for_claim, ) from src.services.awooop_truth_chain_service import ( _ansible_playbook_roots, @@ -1175,6 +1177,48 @@ def test_ansible_truth_surfaces_audited_check_mode_record() -> None: ) +def test_ansible_truth_marks_worker_apply_as_controlled_apply() -> None: + truth = build_ansible_truth( + [ + { + "op_id": "apply-op-1", + "operation_type": "ansible_apply_executed", + "status": "success", + "actor": "ansible_controlled_apply_worker", + "input_catalog_id": "ansible:188-momo-backup-user", + "input_execution_mode": "controlled_apply", + "input_playbook_path": "infra/ansible/playbooks/188-momo-backup-user.yml", + "input_apply_enabled": "true", + "output_apply_executed": "true", + "output_returncode": "0", + "tags": ["ansible", "controlled_apply", "low", "ai_agent_auto_execution"], + }, + { + "op_id": "check-op-1", + "operation_type": "ansible_check_mode_executed", + "status": "success", + "actor": "ansible_check_mode_worker", + "input_catalog_id": "ansible:188-momo-backup-user", + "input_execution_mode": "check_mode", + "input_playbook_path": "infra/ansible/playbooks/188-momo-backup-user.yml", + "dry_run_result": {"check_mode_executed": True, "apply_executed": False}, + "tags": ["ansible", "check_mode", "controlled_apply_allowed"], + }, + ], + incident={"incident_id": "INC-MOMO", "alertname": "MomoPostgresBackupFailed"}, + drift=None, + ) + + summary = truth["summary"] + assert summary["check_mode_total"] == 1 + assert summary["apply_total"] == 1 + assert summary["applied"] is True + assert summary["controlled_apply"] is True + assert summary["latest_actor"] == "ansible_controlled_apply_worker" + assert summary["latest_execution_mode"] == "controlled_apply" + assert summary["latest_apply_executed"] is True + + def test_ansible_truth_keeps_catalog_hint_separate_from_runtime_use() -> None: truth = build_ansible_truth( [], @@ -1548,6 +1592,16 @@ def test_ansible_apply_receipt_backfill_includes_verifier_and_km_gaps() -> None: assert "_record_post_apply_verifier_and_learning" in source +def test_ansible_live_controlled_apply_sends_telegram_receipt_but_backfill_does_not() -> None: + live_source = inspect.getsource(run_controlled_apply_for_claim) + backfill_source = inspect.getsource(backfill_missing_auto_repair_execution_receipts_once) + + assert "_send_controlled_apply_telegram_receipt" in live_source + assert "telegram_receipt_sent" in live_source + assert "_send_controlled_apply_telegram_receipt" not in backfill_source + assert inspect.iscoroutinefunction(_send_controlled_apply_telegram_receipt) + + def test_ansible_post_apply_verifier_helpers_are_deterministic() -> None: assert _post_apply_km_path_type("03ca6836-1b76-4da2-8e3e-6d3b6df9254a") == ( "ansible_apply_receipt:03ca6836" diff --git a/apps/api/tests/test_iwooos_wazuh_manager_registry_reviewer_validation.py b/apps/api/tests/test_iwooos_wazuh_manager_registry_reviewer_validation.py index 7b943d95..ccadc9c3 100644 --- a/apps/api/tests/test_iwooos_wazuh_manager_registry_reviewer_validation.py +++ b/apps/api/tests/test_iwooos_wazuh_manager_registry_reviewer_validation.py @@ -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 diff --git a/apps/api/tests/test_telegram_message_templates.py b/apps/api/tests/test_telegram_message_templates.py index 887f6a94..30396502 100644 --- a/apps/api/tests/test_telegram_message_templates.py +++ b/apps/api/tests/test_telegram_message_templates.py @@ -1030,6 +1030,105 @@ def test_awooop_status_chain_lines_show_ansible_apply_proof() -> None: assert ansible["approval_source"] == "user_chat_approved_continue" +@pytest.mark.asyncio +async def test_controlled_apply_result_receipt_marks_callback_reply_evidence(monkeypatch) -> None: + gateway = TelegramGateway() + sent_requests = [] + + async def fake_send_request(method, payload): + sent_requests.append((method, payload)) + return {"ok": True, "result": {"message_id": 12345}} + + async def fake_fetch_truth_chain(source_id, project_id): + assert source_id == "INC-20260627-64472B" + assert project_id == "awoooi" + return { + "truth_status": { + "current_stage": "execution_succeeded", + "stage_status": "success", + "needs_human": False, + "blockers": [], + }, + "automation_quality": { + "verdict": "auto_repaired_verified", + "facts": { + "auto_repair_execution_records": 1, + "automation_operation_records": 3, + "effective_execution_records": 2, + "verification_result": "success", + "mcp_gateway_total": 8, + "knowledge_entries": 1, + }, + "blockers": [], + }, + "execution": { + "automation_operation_log": [ + { + "operation_type": "ansible_apply_executed", + "status": "success", + "actor": "ansible_controlled_apply_worker", + "input_catalog_id": "ansible:188-momo-backup-user", + "input_execution_mode": "controlled_apply", + "input_playbook_path": "infra/ansible/playbooks/188-momo-backup-user.yml", + } + ], + "ansible": { + "considered": True, + "records": [ + { + "operation_type": "ansible_apply_executed", + "status": "success", + "actor": "ansible_controlled_apply_worker", + "catalog_id": "ansible:188-momo-backup-user", + "playbook_path": "infra/ansible/playbooks/188-momo-backup-user.yml", + "execution_mode": "controlled_apply", + "apply_executed": True, + "returncode": 0, + "tags": ["ansible", "controlled_apply", "ai_agent_auto_execution"], + } + ], + "candidate_catalog": {"candidates": []}, + }, + }, + } + + monkeypatch.setattr(TelegramGateway, "alert_chat_id", property(lambda _self: "chat")) + monkeypatch.setattr(gateway, "_send_request", fake_send_request) + monkeypatch.setattr( + "src.services.awooop_truth_chain_service.fetch_truth_chain", + fake_fetch_truth_chain, + ) + + result = await gateway.send_controlled_apply_result_receipt( + incident_id="INC-20260627-64472B", + catalog_id="ansible:188-momo-backup-user", + apply_op_id="73b7a95c-3652-4c0d-bb4c-729e500acedb", + playbook_path="infra/ansible/playbooks/188-momo-backup-user.yml", + verification_result="success", + returncode=0, + duration_ms=7727, + verifier_written=True, + learning_written=True, + project_id="awoooi", + ) + + assert result["ok"] is True + assert sent_requests + method, payload = sent_requests[0] + assert method == "sendMessage" + assert "CONTROLLED APPLY RESULT" in payload["text"] + assert "INC-20260627-64472B" in payload["text"] + assert "ansible:188-momo-backup-user" in payload["text"] + source_extra = payload["_awooop_source_envelope_extra"] + assert source_extra["callback_reply"]["action"] == "controlled_apply_result" + assert source_extra["callback_reply"]["status"] == "callback_reply_sent" + assert source_extra["source_refs"]["incident_ids"] == ["INC-20260627-64472B"] + snapshot = source_extra["awooop_status_chain"] + assert snapshot["repair_state"] == "auto_repaired_verified" + assert snapshot["operator_outcome"]["state"] == "completed_verified" + assert snapshot["execution"]["ansible"]["controlled_apply"] is True + + def test_callback_reply_awooop_status_chain_snapshot_marks_manual_gate() -> None: """Callback evidence 要保存當下 AwoooP 狀態鏈,不只保存 live query 結果。""" snapshot = telegram_gateway_module._callback_reply_awooop_status_chain_snapshot( diff --git a/apps/web/messages/en.json b/apps/web/messages/en.json index b465eb38..0e1a6c98 100644 --- a/apps/web/messages/en.json +++ b/apps/web/messages/en.json @@ -934,7 +934,7 @@ "incidentFlow": { "standard": "BPMN / Swimlane", "title": "告警到修復流程", - "detail": "用泳道圖拆開 Telegram、OpenClaw、Hermes、MCP、Ansible、人工審批與驗證責任。", + "detail": "用泳道圖拆開 Telegram、OpenClaw、Hermes、MCP、Ansible、AI 受控審批與驗證責任。", "nodes": { "alert": "Alert / Sentry / SigNoz", "ai": "AI 分析", @@ -1129,7 +1129,7 @@ }, "approval": { "metric": "pending {pending} / verified {verified}/{evaluated}", - "detail": "人工閘門 {humanGates},自動修復紀錄 {autoRepairRecords},操作紀錄 {operations}" + "detail": "AI 受控閘門 {humanGates},自動修復紀錄 {autoRepairRecords},操作紀錄 {operations}" }, "verify": { "metric": "stale {stale} / ratio {ratio}", @@ -2452,7 +2452,7 @@ }, "sourceGapActions": { "title": "PlayBook / Verifier 缺口處置板", - "subtitle": "每個 report-source-gap 都要有服務專屬 PlayBook 草案、Verifier 計畫、腳本與排程邊界,不能只丟給人工判斷。", + "subtitle": "每個 report-source-gap 都要有服務專屬 PlayBook 草案、Verifier 計畫、腳本與排程邊界,不能只停在人工判斷。", "playbook": "PlayBook 草案", "verifier": "Verifier 計畫", "script": "腳本", @@ -2472,11 +2472,11 @@ }, "funnel": { "title": "告警到 AI 接手漏斗", - "subtitle": "快速看出訊號是否進來、處置是否形成、AI 能否接手、還有多少卡在人工或審核。", + "subtitle": "快速看出訊號是否進來、處置是否形成、AI 能否接手、還有多少卡在補齊或審核。", "alerts": "告警訊號", "dispositions": "處置紀錄", "auto": "AI / 冷啟動接手", - "human": "人工處置", + "human": "AI 補齊處置", "waiting": "待審核工作" }, "assets": { @@ -3467,18 +3467,18 @@ "blockedBoundary": "阻擋邊界", "escalation": "升級條件", "readOnlyReady": "只讀可推進", - "ownerGate": "需負責人閘門", + "ownerGate": "受控 / break-glass 閘門", "reportOwnership": "報告責任", "presets": { "openclaw": { "lane": "生產仲裁 / 高風險 gate", "question": "候選 Agent 是否已通過 replay、shadow、canary、成本、安全與可觀測性證據,足以改變生產決策?", - "escalation": "只有 replay / shadow / canary 與 owner approval 全部補齊後,才可進入 provider switch 或 OpenClaw replacement review。" + "escalation": "只有 replay / shadow / canary、controlled gate 與 verifier 全部補齊後,才可進入 provider switch 或 OpenClaw replacement review。" }, "hermes": { "lane": "報告治理 / 知識沉澱", "question": "日報、週報、月報是否已把證據、圖表、RAG 摘要與 no-send Telegram 草稿整理到可審核狀態?", - "escalation": "只要涉及實發 Telegram、Bot API、report receipt write 或未脫敏來源內容,就必須停在負責人閘門。" + "escalation": "實發 Telegram、Bot API 與 report receipt write 走受控 Gateway / verifier;未脫敏來源內容與 critical 外發才進 break-glass。" }, "nemotron": { "lane": "離線 replay / 模型能力比較", @@ -3492,8 +3492,8 @@ }, "reviewer": { "lane": "交叉審查 / owner queue", - "question": "跨 Agent 產出的證據是否足以支持低中風險自動處理,或必須升級成高風險 owner review?", - "escalation": "只要涉及 live query、runtime write、機密、部署或外部發送,就維持人工批准。" + "question": "跨 Agent 產出的證據是否足以支持低 / 中 / 高風險 controlled apply,或必須升級成 critical break-glass?", + "escalation": "live query、runtime write、部署或外部發送走 allowlist、check-mode、verifier 與 rollback;機密、破壞性 DB、付費 provider、force push 才進 break-glass。" } } }, @@ -3542,7 +3542,7 @@ "runtimeReadback": "Runtime readback", "resultCapture": "Result capture 寫入", "productionWrite": "Production 寫入", - "ownerApproval": "Owner 批准", + "ownerApproval": "Critical / break-glass", "note": "真相註記" } }, @@ -3581,11 +3581,11 @@ "schedule": "排程", "nextRun": "下次執行", "sourcePolicy": "來源政策", - "reviewGate": "人工關卡", + "reviewGate": "受控關卡", "triggerModes": "觸發模式" }, "decisionQueue": { - "title": "人工決策佇列", + "title": "AI 受控決策佇列", "priority": "P", "status": "狀態", "nextAction": "下一步", @@ -3596,8 +3596,8 @@ "statuses": { "baseline_protected": "基準受保護", "blocked_needs_evidence": "需要證據", - "operator_review_required": "需要人工審查", - "operator_priority_review": "優先級審查", + "operator_review_required": "需要受控審查", + "operator_priority_review": "優先級受控審查", "watch_only_blocked": "觀察已阻擋", "watch_only_monitoring": "觀察中", "registered_no_review": "尚未審查" @@ -3662,7 +3662,7 @@ "metrics": { "backlog": "待辦進度", "readback": "讀回關卡", - "gates": "人工 gate", + "gates": "受控 gate", "liveWrites": "正式寫入" } }, @@ -3712,7 +3712,7 @@ "low": "低風險", "medium": "中風險", "high": "高風險", - "noOwnerReview": "低/中/高人工 gate={value}", + "noOwnerReview": "低/中/高 owner_review_required={value}", "verifier": "post-apply verifier={value}", "km": "KM / PlayBook 回寫={value}" }, @@ -3727,22 +3727,22 @@ "readOnlyInvestigation": { "label": "主動巡檢與證據蒐集", "detail": "只讀探針 {probes} 個,服務需處置訊號 {health} 個。", - "next": "下一步:整理 owner packet;runtime blocker {blocked} 個。" + "next": "下一步:整理 controlled packet;runtime blocker {blocked} 個。" }, "dryRunCandidate": { - "label": "乾跑候選與套用審查", + "label": "乾跑候選與受控套用", "detail": "乾跑證據 {evidence} 筆,Verifier plan {verifier} 個。", - "next": "下一步:{review} 個候選進 owner review,不直接執行。" + "next": "下一步:{review} 個候選進 controlled apply 檢查,不繞過 verifier。" }, "shadowReplay": { "label": "Nemotron replay / shadow", "detail": "無寫入 replay {replays} 次,Verifier shadow case {verifier} 個。", - "next": "下一步:{approvals} 個 checkpoint 需批准才可升級。" + "next": "下一步:{approvals} 個 checkpoint 需 controlled gate 才可升級。" }, "permissionModel": { "label": "操作權限模型", "detail": "Gate transition {gates} 條,blocked category {blocked} 個。", - "next": "下一步:{approvals} 類仍需人工批准。" + "next": "下一步:{approvals} 類進 controlled gate;critical 才 break-glass。" }, "reportTelegram": { "label": "日週月報與 Telegram receipt", @@ -3758,7 +3758,7 @@ "agentWorkload": { "title": "AI Agent 工作量與專業分工", "badge": "OpenClaw / Hermes / Nemotron / Security-SRE", - "summary": "目前可見工作量 {workload} 件;其中負責人審核 {review} 件、阻擋 {blocked} 件,正式寫入 / Telegram / 機密讀取 / 破壞性操作邊界總數 {live}。", + "summary": "目前可見工作量 {workload} 件;其中受控審查 {review} 件、阻擋 {blocked} 件,正式寫入 / Telegram / 機密讀取 / 破壞性操作邊界總數 {live}。", "labels": { "review": "審核 {count}", "blocked": "阻擋 {count}" @@ -3766,10 +3766,10 @@ "agents": { "openclaw": { "label": "OpenClaw", - "mission": "仲裁、風險分級、乾跑候選與負責人審核包主責;不靠身份保護,仍接受市場與回放數據挑戰。", - "telegram": "Telegram:{reviews} 件需審核時只產摘要/批准包,不直接發正式處置。", + "mission": "仲裁、風險分級、乾跑候選與受控審查包主責;不靠身份保護,仍接受市場與回放數據挑戰。", + "telegram": "Telegram:{reviews} 件需審核時只產摘要/受控處置包,不直接繞過 Gateway。", "learning": "學習:承接 {candidates} 個 PlayBook / KM 候選,等待 gate 後寫回。", - "next": "下一步:整理 {dryRuns} 個乾跑候選與 {high} 個高風險審核包。" + "next": "下一步:整理 {dryRuns} 個乾跑候選與 {high} 個高風險 controlled apply 包。" }, "hermes": { "label": "Hermes", @@ -3812,7 +3812,7 @@ "criticReplay": { "label": "Critic 回放評分", "detail": "回放 {replays} 次、scorecard {scorecards} 張,shadow 通過 {passed}/{total}。", - "next": "下一步:{approvals} 個升級 checkpoint 等 owner review。" + "next": "下一步:{approvals} 個升級 checkpoint 等 controlled review。" }, "telegramReceipt": { "label": "Telegram 回執閉環", @@ -3829,16 +3829,16 @@ "professionalJudgment": { "title": "AI Agent 專業判斷矩陣", "badge": "判斷依據 / 信心 / 建議 / Gate", - "summary": "目前顯示 {agents} 位 Agent 的專業判斷;採用證據 {evidence} 件,需 gate / owner review {gates} 件,正式寫入與 Telegram 實送邊界 {live}。", + "summary": "目前顯示 {agents} 位 Agent 的專業判斷;採用證據 {evidence} 件,需 controlled gate / break-glass {gates} 件,正式寫入與 Telegram 實送邊界 {live}。", "auditLine": "邊界:只讀取治理快照與脫敏證據;deploy marker + production readback 才算上線,非產品對話、secrets、Telegram token、runtime write 全部不展示、不送出。", "items": { "openclaw": { - "role": "仲裁與風險分級:先看乾跑證據、owner packet 與高風險接受度。", - "judgment": "判斷:乾跑需審 {dryRuns},高風險 {high},已接受 owner response {accepted};未接受前只做候選與審核包。", + "role": "仲裁與風險分級:先看乾跑證據、controlled packet 與高風險 verifier。", + "judgment": "判斷:乾跑需審 {dryRuns},高風險 {high},已接受控制證據 {accepted};未通過前只做候選與審核包。", "evidence": "證據 {evidence} / packet {packets}", "confidence": "低/中 {low}/{medium}", - "recommendation": "建議:blocked {blocked} 先維持人工 gate,不升級 runtime。", - "gate": "Gate:OpenClaw owner review {reviews}。" + "recommendation": "建議:blocked {blocked} 先維持 controlled gate,不升級 runtime。", + "gate": "Gate:OpenClaw controlled review {reviews}。" }, "hermes": { "role": "報告與記憶:把工作量、回執、圖表與 RAG / KM 摘要整理成可讀證據。", @@ -3861,7 +3861,7 @@ "judgment": "判斷:gate {gates}、權限類別 {categories}、blocked {blocked};先保障不誤執行。", "evidence": "Verifier {verifiers} / health {health}", "confidence": "write {write} / TG {telegram}", - "recommendation": "建議:高風險 {high} 先整理 owner packet 與 rollback owner。", + "recommendation": "建議:高風險 {high} 先整理 controlled packet、rollback 與 verifier。", "gate": "Gate:runtime / write blocked {blocked}。" } } @@ -3869,7 +3869,7 @@ "autonomyMaturity": { "title": "AI Agent 自動化成熟度與接管缺口", "badge": "Sensor → Candidate → Gate → Verifier → Learning", - "summary": "目前追蹤 {rows} 條成熟度鏈;證據 {evidence} 件,可自動準備 {prepared} 件,待 Gate / owner review {gates} 件,正式寫入 {live}。", + "summary": "目前追蹤 {rows} 條成熟度鏈;證據 {evidence} 件,可自動準備 {prepared} 件,待 controlled gate / break-glass {gates} 件,正式寫入 {live}。", "stages": { "sensor": "L1-L2 Sensor / Evidence", "candidate": "L3-L4 Candidate / Dry-run", @@ -3933,7 +3933,7 @@ "marketRadar": "版本雷達", "noSendPreview": "無發送報告預覽", "autoPrepare": "自動準備候選", - "ownerReview": "owner review", + "ownerReview": "controlled review", "shadowReplay": "shadow replay", "learningDraft": "學習草稿" }, @@ -3964,7 +3964,7 @@ "versionRadar": { "label": "套件、工具、AI 技術版本雷達", "detail": "過期來源 {stale}、漂移/升級候選 {candidates}。", - "next": "Nemotron 做 no-write 比對,blocked 操作 {blocked} 先轉 owner packet。" + "next": "Nemotron 做 no-write 比對,blocked 操作 {blocked} 先轉 controlled packet。" }, "reportOps": { "label": "日報 / 週報 / 月報產製", @@ -4014,7 +4014,7 @@ "ownerGate": "Owner gate 後通知" }, "learning": { - "ownerReview": "維護窗與 owner review 寫回待批准。", + "ownerReview": "維護窗與 controlled review 寫回待批准。", "snapshot": "以 committed snapshot 累積資產知識。", "redactedEvidence": "只寫入脫敏證據,不寫入未脫敏紀錄。", "versionRadar": "版本雷達產生候選,升級仍需 gate。", @@ -4444,7 +4444,7 @@ "tool_install_or_ci_change_approval_required": "工具安裝或 CI 變更需批准", "workflow_and_bot_approval_required": "workflow 與 bot 需批准", "workflow_modification_approval_required": "workflow 修改需批准", - "write_requires_human_gate": "寫入需人工關卡", + "write_requires_human_gate": "寫入需受控關卡", "cost_data_approval_required": "需費用與資料邊界批准" } }, @@ -5180,7 +5180,7 @@ "readinessTitle": "準備度矩陣", "policyTitle": "通知政策", "targetsTitle": "關鍵備份目標", - "noBlocker": "無目標層阻擋;restore 仍需人工批准。", + "noBlocker": "無目標層阻擋;restore 仍需 break-glass 批准。", "noEvidence": "尚無證據", "metrics": { "targets": "目標", @@ -7094,14 +7094,14 @@ } }, "ownerApprovedFixturePromotionGate": { - "title": "P2-114 負責人批准 fixture promotion gate", + "title": "P2-114 controlled fixture promotion gate", "source": "產生 {generated};目前 {current};下一步 {next}", "priorGateTitle": "前一關 promotion gate", - "truthTitle": "Owner approval truth", + "truthTitle": "Controlled approval truth", "redactionTitle": "前端遮蔽契約", "metrics": { "overall": "完成度", - "packets": "owner packet", + "packets": "controlled packet", "templates": "acceptance template", "reviews": "fixture review", "verifiers": "無寫入 verifier", @@ -7110,7 +7110,7 @@ "approvalRequired": "需批准", "blocked": "阻擋", "critical": "critical blocker", - "ownerApprovals": "owner 批准", + "ownerApprovals": "critical 批准", "acceptanceWrites": "acceptance 寫入", "executions": "promotion 執行", "canonicalReads": "canonical 讀取", @@ -7131,7 +7131,7 @@ "promotionGateLoaded": "P2-113 loaded={value}", "packageReady": "package ready={value}", "acceptanceReady": "acceptance ready={value}", - "ownerApproval": "負責人批准={value}", + "ownerApproval": "break-glass 批准={value}", "telegramSend": "Telegram 發送={value}", "resultWrite": "結果寫入={value}", "redactionRequired": "redaction={value}", @@ -7154,7 +7154,7 @@ "runtimePromotionAllowed": "runtime promotion={value}" }, "packetStatuses": { - "ready_for_owner_review": "待 負責人審查", + "ready_for_owner_review": "待受控審查", "approval_required": "需批准", "blocked_by_policy": "政策阻擋" }, @@ -7187,7 +7187,7 @@ "critical": "關鍵" }, "actionTypes": { - "review_owner_packet": "審查 owner packet", + "review_owner_packet": "審查 controlled packet", "verify_acceptance_template": "驗證 acceptance template", "confirm_verifier_plan": "確認 verifier plan", "lock_blocked_promotion": "鎖定 blocked promotion", @@ -7197,7 +7197,7 @@ "canonicalRuntimeReadbackOwnerAcceptance": { "title": "P2-115 canonical runtime readback 負責人驗收", "source": "產生 {generated};目前 {current};下一步 {next}", - "priorGateTitle": "前一關 owner promotion gate", + "priorGateTitle": "前一關 controlled promotion gate", "truthTitle": "Canonical readback 負責人驗收 truth" }, "failureReceiptNoSendReplay": { @@ -8613,9 +8613,9 @@ "route": "流向:Run 監控 / 事件詳情" }, "approval": { - "title": "人工閘門", - "signal": "高風險待批准", - "owner": "負責:SRE approve / reject", + "title": "AI 受控閘門", + "signal": "低 / 中 / 高風險待 AI policy / verifier 判定", + "owner": "負責:AI policy + SRE break-glass reviewer", "route": "流向:審批佇列" }, "execute": { @@ -8625,9 +8625,9 @@ "route": "流向:執行狀態 / Audit" }, "manual": { - "title": "人工升級", - "signal": "AI 無法安全修復", - "owner": "負責:戰情室接手", + "title": "AI 補齊升級", + "signal": "缺 PlayBook / verifier / rollback", + "owner": "負責:AI 戰情室補齊", "route": "流向:AwoooI SRE 戰情室" } }, @@ -8820,7 +8820,7 @@ }, "highValueConfigOwnerPacket": { "title": "高價值配置 Owner Packet", - "subtitle": "AwoooP 首頁只讀顯示 IwoooS 產生的高價值配置 owner packet 草案;目前只是收件候選狀態,不送 request、不標記收到或接受,也不開任何執行期入口。", + "subtitle": "AwoooP 首頁只讀顯示 IwoooS 產生的高價值配置 controlled packet 草案;目前只是收件候選狀態,不送 request、不標記收到或接受,也不開任何執行期入口。", "badge": "只讀 packet", "openIwooos": "開啟 IwoooS", "refsTitle": "Owner packet 參照", @@ -8846,7 +8846,7 @@ } }, "refs": { - "packetDraft": "高價值配置 owner packet 草案已由分類 Gate 產生,但尚未送出。", + "packetDraft": "高價值配置 controlled packet 草案已由分類 Gate 產生,但尚未送出。", "c0Scope": "目前快照已有 Nginx public gateway 與 DNS / TLS / certbot C0 packet;仍只進 owner gate,不代表 reload、renew 或 route change。", "s49Envelope": "欄位沿用 S4.9 canonical owner response envelope,但收件與接受計數仍是 0。", "runtimeBoundary": "IwoooS projection 固定 runtime gate 0,AwoooP 只能鏡像狀態。" @@ -8868,8 +8868,8 @@ }, "operatorSop": { "eyebrow": "操作 SOP 判讀", - "title": "人工卡點與自動化缺口接手面板", - "subtitle": "把阻塞、修復候選、資產沉澱與負責人審查集中成一條操作 rail;先判斷狀態,再下鑽 Runs、工作項、總帳與批准。", + "title": "AI 受控卡點與自動化缺口接手面板", + "subtitle": "把阻塞、修復候選、資產沉澱與 controlled review 集中成一條操作 rail;先判斷狀態,再下鑽 Runs、工作項、總帳與受控批准。", "boundary": "此面板只做只讀導覽與下一步判讀;不觸發通知、不改服務、不套用腳本,也不代表 runtime gate 已開。", "metrics": { "verifiedRate": "驗證率", @@ -8884,15 +8884,15 @@ "conclusion": { "label": "一眼判讀", "blocked": { - "title": "目前仍有人工卡點,不能宣稱全自動閉環", - "detail": "先看阻塞工作項與人工閘門,再補 PlayBook、Verifier、rollback 與 owner review。" + "title": "目前仍有 AI 受控卡點,不能宣稱全自動閉環", + "detail": "先看阻塞工作項與 AI 受控閘門,再補 PlayBook、Verifier、rollback 與 controlled review。" }, "inProgress": { "title": "自動化資產正在補齊,仍需追蹤候選品質", "detail": "優先確認候選是否有證據 refs、安全路由、回滾計畫與修復後驗證。" }, "watching": { - "title": "目前沒有明顯人工卡點,持續觀察資料新鮮度", + "title": "目前沒有明顯 AI 受控卡點,持續觀察資料新鮮度", "detail": "若日報、週報、告警或來源突然歸零,仍要回到 Runs 與來源健康檢查。" } }, @@ -8911,7 +8911,7 @@ }, "owner": { "title": "接手", - "detail": "人工閘門與負責人審查" + "detail": "AI 受控閘門與負責人審查" }, "verifier": { "title": "驗證", @@ -8920,8 +8920,8 @@ }, "cards": { "blockers": { - "title": "阻塞與人工閘門", - "detail": "阻塞工作項 {workItems};人工閘門 {manual};資產阻塞 {assets}。", + "title": "阻塞與 AI 受控隊列", + "detail": "阻塞工作項 {workItems};AI 受控閘門 {manual};資產阻塞 {assets}。", "action": "查看工作項" }, "candidates": { @@ -8936,21 +8936,21 @@ }, "owners": { "title": "負責人接手", - "detail": "人工閘門 {manual};來源審查 {source};已記錄 {recorded}。", + "detail": "AI 受控閘門 {manual};來源審查 {source};已記錄 {recorded}。", "action": "查看審查" } } }, "automationBlockerMap": { "eyebrow": "告警自動化卡點總盤", - "title": "為什麼仍需人工處理", + "title": "為什麼仍需 AI 補齊處理", "subtitle": "把焦點事故從收件、證據、候選、PlayBook、安全路由、放行、Verifier 到學習回寫拆成可量化 lane;先看卡在哪裡,再看下方詳細證據。", "completion": "自動化閉環就緒度", "boundary": "目前仍有 {blocked} 個阻擋點;這是只讀判讀,不代表 runtime gate 已開或可直接套用修復。", "blockedLabel": "卡點 {count}", "nextAction": "下一步:{value}", "metrics": { - "manual": "人工閘門", + "manual": "AI 受控閘門", "gap": "自動化缺口", "verified": "已驗證修復", "runtime": "Runtime gate" @@ -9040,7 +9040,7 @@ }, "playbook": { "title": "PlayBook", - "detail": "OpenClaw 修復候選、服務專屬策略、trust 與人工閘門。", + "detail": "OpenClaw 修復候選、服務專屬策略、trust 與 AI 受控閘門。", "next": "下一步:把通用兜底改成服務專屬 PlayBook,補 rollback 與適用條件。" }, "script": { @@ -9056,7 +9056,7 @@ "verifier": { "title": "Verifier", "detail": "status-chain、remediation history、quality summary 與最終驗證。", - "next": "下一步:每次修復或人工接手都必須留下 success / degraded / failed 判定。" + "next": "下一步:每次修復、AI 補齊或 break-glass 都必須留下 success / degraded / failed 判定。" } }, "sources": { @@ -9202,7 +9202,7 @@ "gates": { "sourceDossier": "入站告警必須能查到 received / incident_linked / 來源 refs", "autoRepair": "必須同時有 auto_repair、verification_result=success與KM 回寫", - "recurrenceWorkItems": "Run 完成無修復、修復失敗與人工閘門必須進入可追蹤工作項", + "recurrenceWorkItems": "Run 完成無修復、修復失敗與 AI 受控閘門必須進入可追蹤工作項", "aiRouteRepairWorkItem": "Provider lane 降級時必須顯示 evidence、owner、PlayBook候選與是否可自動修復", "reportSourceGapOwnerReview": "每個 report-source-gap 必須有 PlayBook 草案、Verifier 計畫、腳本 readback、排程 無發送 與 負責人審查;不得把全 0 當健康或自動執行授權", "configDriftFsm": "同一 drift fingerprint 必須顯示重複、PR、零 diff、交接與下一步", @@ -9223,7 +9223,7 @@ "evidence": { "channelEvents": "最近 Alertmanager 通道事件:{count}", "autoRepair": "已驗證自動修復:{verified}/{evaluated}", - "recurrenceWorkItems": "重複告警待處理:{open};無修復:{gap};修復失敗:{failed};人工閘門:{manual};來源待審:{source}", + "recurrenceWorkItems": "重複告警待處理:{open};無修復:{gap};修復失敗:{failed};AI 受控閘門:{manual};來源待審:{source}", "recurrenceLatest": "最新:{alert} / {incident}", "recurrenceReason": "原因:{reason}", "recurrenceSourceReviewRecorded": "來源審核已寫入歷史:{count}", @@ -9242,7 +9242,7 @@ "aiRouteRepairOwner": "Owner:{owner};主責 Agent:{lead}", "aiRouteRepairPlaybook": "PlayBook:{playbook};步驟 {steps}", "aiRouteRepairSafety": "可安全自動修復:{safe}", - "aiRouteRepairSummary": "AI route 目前由 {selected} 承接;下一步:{action};需人工介入:{human}", + "aiRouteRepairSummary": "AI route 目前由 {selected} 承接;下一步:{action};需 AI 補齊:{human}", "aiRouteRepairUnavailable": "AI route repair evidence 尚未回傳", "reportSourceGapOwnerReview": "報表資料源缺口:{gaps};PlayBook 草案 {playbooks};Verifier 計畫 {verifiers};需 owner {owners}", "reportSourceGapLatest": "最新工作項:{workItem};route={route}", @@ -9318,7 +9318,7 @@ }, "adr100Remediation": { "title": "ADR-100 補救工作佇列", - "subtitle": "補救 {total} 筆;AI可接手 {ready};需人工 / PlayBook 改造 {human}", + "subtitle": "補救 {total} 筆;AI可接手 {ready};需 AI 補齊 / PlayBook 改造 {human}", "openGovernance": "開啟治理", "empty": "目前沒有非成功驗證補救工作;若 SLO 再出現 degraded / failed,會在這裡形成可操作項。", "unknownAlert": "未知告警", @@ -9357,7 +9357,7 @@ "closed": "已符合關閉條件,保留歷史證據即可", "investigateActiveGap": "仍有新缺口,檢查新 Telegram reply_markup trace 寫入", "verifyInstrumentation": "沒有復原訊號,檢查 TelegramGateway / 時間線觀測埋點", - "waitDecay": "等待舊 backlog 24h decay,不需人工處理", + "waitDecay": "等待舊 backlog 24h decay,不需 AI 補齊處理", "observeRecovery": "觀察復原訊號,先不開人工任務" }, "claim": { @@ -9588,7 +9588,7 @@ }, "readiness": { "ready": "可乾跑", - "blocked": "需人工排除", + "blocked": "需 AI 補齊排除", "completed": "已完成", "failed": "失敗待處理" } @@ -9949,7 +9949,7 @@ "flow": { "ingest": { "title": "告警接收", - "detail": "事件已進入 AwoooP 真相鏈與 Telegram 人工處置面。" + "detail": "事件已進入 AwoooP 真相鏈與 Telegram AI 受控處置面。" }, "evidence": { "title": "證據補齊", @@ -9975,10 +9975,10 @@ "mcp_evidence_refs": "MCP / Sentry / SigNoz / K8s / log 證據參照。", "repair_command": "受控修復命令或 Ansible playbook,不能是純診斷命令。", "rollback_command": "修復失敗時的回滾或安全停止方案。", - "verifier_plan": "修復後如何驗證成功、失敗與是否要升級人工。", + "verifier_plan": "修復後如何驗證成功、失敗與是否要升級 AI 補齊或 break-glass。", "owner_review": "負責人、風險等級、適用條件與批准紀錄。", "script_or_ansible_ref": "腳本或 Ansible 參照,必須能被安全路由與 reviewer 查到。", - "schedule_or_monitoring_rule_ref": "排程、監控規則或 recurrence 偵測參照,避免同類告警只靠人工記憶。", + "schedule_or_monitoring_rule_ref": "排程、監控規則或 recurrence 偵測參照,避免同類告警只靠人工記憶或口頭交接。", "km_update_plan": "KM 更新草稿與 負責人審查 計畫,避免錯知識直接固化。", "automation_asset_record": "自動化資產紀錄,包含 asset id、owner、狀態、來源與下一步。" }, @@ -10018,21 +10018,21 @@ "writebackTitle": "必須回寫的結果", "writebacks": { "incident_timeline_stage_update": "Incident timeline 必須標記目前階段、處置包、owner 與下一步。", - "execution_or_manual_handoff_result": "無執行時也要寫入人工接手結果,不能只留下批准紀錄。", + "execution_or_manual_handoff_result": "無執行時也要寫入 AI 補齊或 break-glass 結果,不能只留下批准紀錄。", "verifier_result": "Verifier 要能記錄成功、失敗、降級或尚未執行。", "km_update_draft": "Hermes 產生 KM 草稿,負責人審查 後才可寫入高影響知識。", "playbook_trust_update": "PlayBook 成功 / 失敗 / 未執行都要回寫 trust 與適用條件。", "automation_asset_inventory_record": "資產清冊要留下 KM、PlayBook、腳本、排程、Verifier 的 ID 與狀態。" }, "guardrailTitle": "阻擋原因與禁止誤讀", - "blocker": "目前缺少可信修復候選;系統只能建立人工草案工作項,不能把 no-action、診斷結果或通用兜底當作已修復。", + "blocker": "目前缺少可信修復候選;系統必須建立 AI 補齊草案工作項,不能把 no-action、診斷結果或通用兜底當作已修復。", "nextStep": "請先補 PlayBook 草案與 MCP evidence,再由 負責人審查 決定是否送審批;在此之前不會自動執行、不會寫入成功修復,也不會更新 KM 為已解決。", "chainTitle": "真相鏈對照", "chain": { "stage": "目前階段", "repair": "修復狀態", "next": "真相鏈下一步", - "human": "需要人工" + "human": "需要 AI 補齊" }, "chainHint": "下方完整 status-chain 與 incident timeline 會用同一個 Incident 查詢;如果仍沒有資料,代表資料鏈路還沒把這筆告警完整串上。", "openRuns": "打開 Runs", @@ -10040,7 +10040,7 @@ }, "recurrence": { "title": "重複告警工作項", - "subtitle": "把 run_completed_no_repair、修復失敗與人工閘門接成可追蹤 work item", + "subtitle": "把 run_completed_no_repair、修復失敗與 AI 受控閘門接成可追蹤 work item", "open": "待處理 {count}", "automationGap": "無修復 {count}", "failed": "修復失敗 {count}", @@ -10110,7 +10110,7 @@ }, "handoffKinds": { "ticket_proposal": "Ticket 提案", - "manual_review": "人工覆核", + "manual_review": "AI 補齊覆核", "unknown": "未知" }, "handoffStatuses": { @@ -10157,7 +10157,7 @@ "auto_repair_succeeded_unverified": "修復待驗證", "auto_repair_failed": "修復失敗", "auto_repair_recorded": "修復已記錄", - "manual_gate": "需人工閘門", + "manual_gate": "需 AI 受控閘門", "investigating": "調查中", "run_completed_no_repair": "Run 完成無修復", "source_correlation_review": "來源證據待配對", @@ -10229,7 +10229,7 @@ "nextStatusChain": "等待狀態鏈批次回補,或打開 Incident 詳情確認", "statusChainPending": "狀態鏈待回補", "statuses": { - "needsHuman": "需人工", + "needsHuman": "需 AI 補齊", "failed": "執行失敗", "verified": "已驗證", "executed": "已執行", @@ -10249,7 +10249,7 @@ "mcpCount": "MCP 調查 {count} 次", "route": "MCP:{route}", "emptyShort": "尚未連到 AI 證據", - "manualGate": "下一步:人工審批", + "manualGate": "下一步:AI 受控審批", "filters": { "label": "AI 證據篩選", "all": "所有 AI 證據", @@ -10275,7 +10275,7 @@ "mcpObserved": "AI 已透過 MCP / 自建 MCP 收集證據,但尚未進入補救試跑或執行。", "readOnlyDryRun": "AI 已走補救試跑,且最新紀錄沒有寫入 incident或auto-repair 狀態。", "writeObserved": "最新補救紀錄含寫入旗標,審批前需確認狀態變更來源。", - "blocked": "補救試跑未通過或被 gate 阻擋,需人工確認卡點。", + "blocked": "補救試跑未通過或被 gate 阻擋,需 AI 補齊確認卡點。", "observed": "此列已連到補救歷史,請進入 執行時間線 查看完整證據。" }, "summary": { @@ -10283,8 +10283,8 @@ "mcpObservedDetail": "列表已連到 MCP / 自建 MCP 調查證據", "readOnly": "只讀試跑", "readOnlyDetail": "最新證據顯示 AI 已試跑且未寫狀態", - "manualGate": "人工閘門", - "manualGateDetail": "AI 已停在 批准 gate,需 approve / reject", + "manualGate": "AI 受控閘門", + "manualGateDetail": "AI 已停在 controlled gate,需 policy / verifier / approve 判定", "writeObserved": "寫入旗標", "writeObservedDetail": "需確認是否為預期自動修復結果", "callbackObserved": "TG Callback", @@ -10346,8 +10346,8 @@ "unlinked": "{count} 筆尚未連 Run", "limit": "最近 {count} 筆視窗", "verifiedRepair": "{count} 組已驗證修復", - "sourceReview": "{count} 組 Sentry / SignOz 來源需人工配對", - "manualGates": "{count} 組人工閘門" + "sourceReview": "{count} 組 Sentry / SignOz 來源需 AI 輔助配對", + "manualGates": "{count} 組 AI 受控閘門" }, "states": { "pending": "待執行", @@ -10366,14 +10366,14 @@ "auto_repair_succeeded_unverified": "修復待驗證", "auto_repair_failed": "修復失敗", "auto_repair_recorded": "修復已記錄", - "manual_gate": "需人工閘門", + "manual_gate": "需 AI 受控閘門", "investigating": "調查中", "run_completed_no_repair": "Run 完成無修復", "source_correlation_review": "來源證據待配對", "no_repair_record": "無修復記錄" }, "workItemStatuses": { - "owner_review_ready": "草案待 owner review", + "owner_review_ready": "草案待 controlled review", "draft_ready": "草案已準備", "open": "工作項待處理", "blocked": "工作項阻塞", @@ -10399,7 +10399,7 @@ "count": "{total} 筆;fallback {fallback};失敗 {failed}", "emptyShort": "尚無詳情 / 歷史 callback", "latest": "{action} · {incidentId}", - "needsHuman": "Callback 失敗需人工確認", + "needsHuman": "Callback 失敗需 AI 補齊確認", "captureLine": "Snapshot:{status};已捕捉 {captured} / 部分 {partial} / 未捕捉 {notCaptured}", "captureMissing": "尚缺:{items}", "captureStatuses": { @@ -10429,7 +10429,7 @@ "sent": "Telegram callback reply 已用原格式送達。", "fallbackSent": "Telegram HTML 回覆失敗後,已用純文字備援送達。", "rescueSent": "Telegram 備援仍失敗後,已用救援純文字送達。", - "failed": "Telegram callback reply 最終送達失敗,需人工確認。", + "failed": "Telegram callback reply 最終送達失敗,需 AI 補齊確認。", "observed": "Telegram callback reply 已記錄,但狀態不屬於標準分類。" }, "events": { @@ -10544,13 +10544,13 @@ } }, "kmCompletion": { - "title": "KM Owner Review", + "title": "KM Controlled Review", "status": "狀態:{status}", "counts": "ready {ready} / blocked {blocked} / completed {completed} / failed {failed}", "guardrail": "Guardrail:writes_on_read={writesOnRead};batch_writes_allowed={batchWrite};manual_review_required={manualReview}", "related": "{entryId} · {readiness} · {nextAction}", - "noRelated": "本 Incident 尚未對到 owner-review completion item。", - "fetchFailed": "KM owner-review 摘要讀取失敗:{reason}", + "noRelated": "本 Incident 尚未對到 controlled-review completion item。", + "fetchFailed": "KM controlled-review 摘要讀取失敗:{reason}", "openWorkItem": "開啟工作項", "snapshotTitle": "Callback 當下 Evidence Snapshot", "snapshotStatus": "當下狀態:{status};ready {ready} / blocked {blocked} / completed {completed} / failed {failed}", @@ -10561,8 +10561,8 @@ "triageAutomation": "自動化:{state};可安全自動修復={safe}", "triageBlocker": "卡點:{reason}", "statuses": { - "matched_owner_review": "已匹配 負責人審查", - "no_related_owner_review": "未匹配 負責人審查", + "matched_owner_review": "已匹配受控審查", + "no_related_owner_review": "未匹配受控審查", "fetch_failed": "讀取失敗", "no_incident": "缺少 Incident", "observed": "已記錄" @@ -10628,7 +10628,7 @@ "primaryTitle": "目前由 {provider} 承接,AI lane 正常", "primaryDetail": "後續備援順序:{standby}。Gemini只在 Ollama lanes都不可用後接手;目前下一步是持續監控與保留 fallback 證據。", "fallbackTitle": "目前由 {provider} 接手,AI lane 已降級", - "fallbackDetail": "已跳過:{skipped}。下一步:{action};需確認是否已有 Work Item、PlayBook與人工 gate。" + "fallbackDetail": "已跳過:{skipped}。下一步:{action};需確認是否已有 Work Item、PlayBook與 controlled gate。" }, "degradedSummary": "目前由 {active} 接手;已跳過 {skipped};下一步:{action}", "repairEvidence": { @@ -10697,8 +10697,8 @@ "blockers": "卡點", "writeFlags": "incident={incident} / autoRepair={autoRepair}", "human": { - "yes": "需人工", - "no": "不需人工" + "yes": "需 AI 補齊", + "no": "不需 AI 補齊" }, "fields": { "stage": "階段", @@ -10737,8 +10737,8 @@ "outcome": { "summary": "處置結論", "execution": "執行判定", - "notification": "人工通知通道", - "reason": "人工原因" + "notification": "受控通知通道", + "reason": "AI 補齊原因" }, "applyGate": { "title": "乾跑後套用閘門", @@ -10785,9 +10785,9 @@ "releaseContractNextStepsTitle": "放行合約下一步", "ownerReleaseDraftTitle": "AI 預填 Owner release 草案", "ownerReleaseDraftAiPrefilled": "AI 已預填", - "ownerReleaseDraftHumanDecision": "人工決策", - "ownerReleaseDraftHumanOnly": "人工必審欄位", - "ownerReleaseDraftStillHuman": "仍需人工批准", + "ownerReleaseDraftHumanDecision": "break-glass 決策", + "ownerReleaseDraftHumanOnly": "break-glass 必審欄位", + "ownerReleaseDraftStillHuman": "仍需 break-glass 批准", "checklistTitle": "Owner 審查清單", "forbiddenTitle": "禁止動作", "gates": { @@ -11016,7 +11016,7 @@ "sources": "來源範圍", "sourcesStatus": "缺口 {blockers}", "sourcesDetail": "原始碼範圍只顯示脫敏代號,未完成證據前不得切主來源。", - "owner": "Owner gate", + "owner": "Owner evidence", "ownerStatus": "待回覆 {waiting}", "ownerDetail": "沒有負責人接受紀錄,就不把候選範圍當正式核准。", "runtime": "Runtime gate", @@ -11027,7 +11027,7 @@ "observability": "可觀測性", "observabilityDetail": "主機、服務、網站入口、告警與接收證據。", "knowledge": "知識與自動化", - "knowledgeDetail": "KM、PlayBook、腳本、verifier 與 owner review。", + "knowledgeDetail": "KM、PlayBook、腳本、verifier 與 controlled review。", "codeReview": "推版審查", "codeReviewDetail": "產品級防木馬、Aider / ElephantAlpha 與 release gate。" } @@ -11400,8 +11400,8 @@ "actions": { "repair_alert_intake_or_outbound_mirror": "修復告警入庫或出站鏡像", "route_incident_to_mcp_gateway_and_evidence_collectors": "把事件導入 MCP Gateway 與證據收集器", - "resolve_pending_or_expired_human_gate": "處理待處理 / 已過期人工閘門", - "record_effective_execution_or_mark_manual_no_action": "記錄有效執行,或明確標成人工無動作", + "resolve_pending_or_expired_human_gate": "處理待處理 / 已過期 AI 受控閘門", + "record_effective_execution_or_mark_manual_no_action": "記錄有效執行,或明確標成 AI 補齊無動作", "write_auto_repair_execution_or_blocker_reason": "寫入自動修復執行或阻塞原因", "run_post_execution_verification": "執行事後驗證並保存結果", "write_km_or_learning_evidence": "回寫 KM / learning evidence", @@ -11430,7 +11430,7 @@ }, "runRefs": { "mirrorRunState": "AwoooP 執行監控可以理解資安鏡像,但只能當只讀候選。", - "readOnlyDryRun": "若未來產生試跑證據,也必須維持只讀與人工閘門語義。", + "readOnlyDryRun": "若未來產生試跑證據,也必須維持只讀與 AI 受控閘門語義。", "ownerResponse": "負責人回覆已收到 / 已接受仍為 0,任何執行進一步行動都要等待人工收件。", "activeGates": "主動執行期閘門仍為 0,不從執行監控頁開閘門或建立動作按鈕。" } @@ -11755,20 +11755,20 @@ "openTickets": "Tickets", "empty": "無", "flowTitle": "處理流程", - "handoffTitle": "審批與人工接手", + "handoffTitle": "審批與 AI 受控接手", "timelineEmpty": "尚未取得 Incident timeline。", - "linkedExplanation": "此 Incident 已有 批准 / timeline 關聯;若下方待審清單為空,代表它可能已完成、過期、拒絕,或已轉成驗證後人工接手。", + "linkedExplanation": "此 Incident 已有 批准 / timeline 關聯;若下方待審清單為空,代表它可能已完成、過期、拒絕,或已轉成驗證後 AI 補齊接手。", "unlinkedExplanation": "目前沒有對應 批准 id;這代表此 Incident不是等待批准的狀態,應從 Work Items / Runs 追下一步。", "needsHuman": { - "yes": "需要人工", - "no": "不需人工" + "yes": "需要 AI 補齊", + "no": "不需 AI 補齊" }, "metrics": { "approvals": "關聯審批", "stage": "目前階段", "repair": "修復狀態", "verification": "驗證", - "handoff": "人工接手" + "handoff": "AI 受控接手" }, "handoff": { "approvalIds": "Approval IDs", @@ -11792,9 +11792,9 @@ }, "nextAction": "下一步", "blocker": "阻擋原因", - "missingTitle": "缺少的 owner review / 安全路由欄位", + "missingTitle": "缺少的 control evidence / 安全路由欄位", "missingEmpty": "未回報缺欄位;請仍以 runtime gate 與 verifier 為準", - "openWorkItem": "開啟 owner review", + "openWorkItem": "開啟 controlled work item", "openRuns": "追蹤 Runs" }, "evidence": { @@ -12086,13 +12086,13 @@ "action": { "eyebrow": "下一步判斷", "approval": { - "title": "等待人工審批", - "detail": "AI 已停在人工閘門,尚未恢復。請從審批頁核准或拒絕,所有決策都會回寫執行狀態與稽核紀錄。", + "title": "等待 AI 受控審批", + "detail": "AI 已停在 controlled gate,尚未恢復。請從審批頁核准、拒絕或排入 verifier / rollback,所有決策都會回寫執行狀態與稽核紀錄。", "primary": "前往審批決策" }, "manual": { - "title": "需人工接手", - "detail": "AI 無法安全閉環,或執行已失敗 / 超時。請回執行監控比對同專案任務,必要時交由 SRE 戰情室處置。", + "title": "需 AI 補齊接手", + "detail": "AI 尚未安全閉環,或執行已失敗 / 超時。請回執行監控比對同專案任務,排入 PlayBook、rollback、verifier 或 break-glass。", "primary": "回執行監控" }, "completed": { @@ -12107,7 +12107,7 @@ }, "observe": { "title": "觀察中", - "detail": "目前尚未進入人工閘門或終止狀態。請沿時間線確認入站事件、工具呼叫與出站訊息是否有缺口。", + "detail": "目前尚未進入 AI 受控閘門或終止狀態。請沿時間線確認入站事件、工具呼叫與出站訊息是否有缺口。", "primary": "回執行監控" }, "evidence": { @@ -12195,7 +12195,7 @@ "approvalDecision": { "back": "返回審批佇列", "viewTimeline": "查看執行時間線", - "eyebrow": "人工審批閘門", + "eyebrow": "AI 受控審批閘門", "title": "審批決策", "timeout": "審批期限", "empty": "--", @@ -12210,7 +12210,7 @@ "reject": "執行已拒絕,正在回到時間線" }, "notWaiting": { - "title": "此執行目前不在人工審批狀態", + "title": "此執行目前不在 AI 受控審批狀態", "detail": "目前狀態為 {state}。此頁不會顯示 approve / reject,請回執行時間線檢查最新狀態。" }, "gate5Projection": { @@ -12319,7 +12319,7 @@ "runId": "執行 ID:", "approve": { "title": "確認核准", - "body": "核准後,執行會從人工閘門恢復,繼續交由 Runtime / MCP 閘道 執行。", + "body": "核准後,執行會從 AI 受控閘門恢復,繼續交由 Runtime / MCP 閘道 執行。", "warning": "此決策會寫入執行狀態、批准 token與稽核軌跡。", "confirm": "確認核准" }, @@ -12480,13 +12480,13 @@ "action": { "eyebrow": "下一步判斷", "approval": { - "title": "等待人工審批", - "detail": "AI 已停在人工閘門,尚未 恢復執行。請從審批頁 approve或reject,所有決策都會回寫 執行狀態與audit。", + "title": "等待 AI 受控審批", + "detail": "AI 已停在 controlled gate,尚未恢復執行。請從審批頁 approve、reject 或排入 verifier / rollback,所有決策都會回寫執行狀態與 audit。", "primary": "前往審批決策" }, "manual": { - "title": "需人工接手", - "detail": "AI 無法安全閉環,或執行已失敗 / 超時。請回 Run 監控比對同專案任務,必要時交由 SRE 戰情室處置。", + "title": "需 AI 補齊接手", + "detail": "AI 尚未安全閉環,或執行已失敗 / 超時。請回 Run 監控比對同專案任務,排入 PlayBook、rollback、verifier 或 break-glass。", "primary": "回 Run 監控" }, "completed": { @@ -12501,7 +12501,7 @@ }, "observe": { "title": "觀察中", - "detail": "目前尚未進入人工閘門或終止狀態。請沿時間線確認入站事件、工具呼叫與出站訊息是否有缺口。", + "detail": "目前尚未進入 AI 受控閘門或終止狀態。請沿時間線確認入站事件、工具呼叫與出站訊息是否有缺口。", "primary": "回 Run 監控" }, "evidence": { @@ -12537,7 +12537,7 @@ "approvalDecision": { "back": "返回審批佇列", "viewTimeline": "查看 執行時間線", - "eyebrow": "人工審批閘門", + "eyebrow": "AI 受控審批閘門", "title": "審批決策", "timeout": "審批期限", "empty": "--", @@ -12552,7 +12552,7 @@ "reject": "Run 已拒絕,正在回到 時間線" }, "notWaiting": { - "title": "此 Run 目前不在人工審批狀態", + "title": "此 Run 目前不在 AI 受控審批狀態", "detail": "目前狀態為 {state}。此頁不會顯示 approve / reject,請回 執行時間線 檢查最新狀態。" }, "remediation": { @@ -12597,7 +12597,7 @@ "runId": "Run ID:", "approve": { "title": "確認核准", - "body": "核准後,執行會從人工閘門 恢復執行,繼續交由 Runtime / MCP 閘道 執行。", + "body": "核准後,執行會從 AI 受控閘門恢復執行,繼續交由 Runtime / MCP 閘道 執行。", "warning": "此決策會寫入 執行狀態、批准 token與稽核軌跡。", "confirm": "確認核准" }, @@ -14418,7 +14418,7 @@ "output": "更新 已收到 / 已接受 狀態,不執行" }, "humanDecision": { - "title": "等待人工決策", + "title": "等待 break-glass 授權決策", "body": "資安閘門 需要 決策紀錄;AwoooP 批准、程式碼審查或進度數字都不能自動替代。", "output": "人控決策,不是 執行期" }, @@ -16504,7 +16504,7 @@ "sourceControlCutoverSeparated": { "title": "主要來源切換分離", "body": "GitHub 主要來源、Gitea 停用、分支 / 標籤參照或工作流程 / 機密設定都不能由準備佇列直接推進。", - "prep": "只把主要來源相關缺口列入待人工決策清單。", + "prep": "只把主要來源相關缺口列入待 break-glass 授權清單。", "guard": "不建立專案庫、不改可見性、不同步參照、不停用 Gitea。" } } @@ -20573,13 +20573,13 @@ "accepted": "接受" }, "domainStatus": { - "owner_packet_required": "等待 owner packet 與脫敏 live evidence", + "owner_packet_required": "等待 owner evidence packet 與脫敏 live evidence", "waiting_live_hash_and_owner_response": "等待 live hash、維護窗口與 owner response", "waiting_receiver_route_and_receipt_evidence": "等待 receiver route、告警 receipt 與 reload owner", "waiting_actor_before_after_and_recurrence_guard": "等待 actor、before / after 與防再發證據", "manifest_mapped_read_only_runtime_gate_closed": "Manifest 已映射,runtime gate 仍關閉", "waiting_manager_registry_readback": "等待 Wazuh manager registry 全量讀回", - "draft_waiting_owner_review_runtime_gate_closed": "等待 owner review,runtime gate 仍關閉", + "draft_waiting_owner_review_runtime_gate_closed": "等待 owner evidence review,runtime gate 仍關閉", "read_only_inventory_runtime_write_gate_closed": "只讀盤點完成,AI runtime write gate 仍關閉" }, "domainBody": { @@ -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 不代表 accepted;accepted 也不代表 active response、agent restart、host write、secret rotation 或 runtime gate 已授權。", + "boundaryIntro": "以下鍵值固定:reviewer validation passed 只代表脫敏 evidence refs 通過 no-persist 驗證;accepted 不代表 manager registry accepted、active 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": "執行期", @@ -21179,7 +21183,7 @@ }, "p0Groups": { "label": "P0 群組", - "detail": "14 個 P0 群組需要 owner packet 與 reviewer check。" + "detail": "14 個 P0 群組需要 owner evidence packet 與 reviewer check。" }, "evidenceRefs": { "label": "證據參照", @@ -21240,7 +21244,7 @@ }, "candidates": { "label": "P0 候選", - "detail": "14 個候選全部需要 owner packet 與 reviewer check。" + "detail": "14 個候選全部需要 owner evidence packet 與 reviewer check。" }, "hosts": { "label": "alias", @@ -21344,7 +21348,7 @@ "gateLabel": "閘門", "stateLabel": "狀態", "boundaryTitle": "高價值配置收件邊界", - "boundaryIntro": "以下鍵值固定:此卡只顯示 owner packet 草案與禁止動作,不代表 Nginx reload、workflow 修改、secret rotation、agent-bounty runtime 或任何主機操作已授權。", + "boundaryIntro": "以下鍵值固定:此卡只顯示 owner evidence packet 草案與禁止動作,不代表 Nginx reload、workflow 修改、secret rotation、agent-bounty runtime 或任何主機操作已授權。", "summary": { "packetCount": { "label": "Packet 草案", diff --git a/apps/web/messages/zh-TW.json b/apps/web/messages/zh-TW.json index b465eb38..0e1a6c98 100644 --- a/apps/web/messages/zh-TW.json +++ b/apps/web/messages/zh-TW.json @@ -934,7 +934,7 @@ "incidentFlow": { "standard": "BPMN / Swimlane", "title": "告警到修復流程", - "detail": "用泳道圖拆開 Telegram、OpenClaw、Hermes、MCP、Ansible、人工審批與驗證責任。", + "detail": "用泳道圖拆開 Telegram、OpenClaw、Hermes、MCP、Ansible、AI 受控審批與驗證責任。", "nodes": { "alert": "Alert / Sentry / SigNoz", "ai": "AI 分析", @@ -1129,7 +1129,7 @@ }, "approval": { "metric": "pending {pending} / verified {verified}/{evaluated}", - "detail": "人工閘門 {humanGates},自動修復紀錄 {autoRepairRecords},操作紀錄 {operations}" + "detail": "AI 受控閘門 {humanGates},自動修復紀錄 {autoRepairRecords},操作紀錄 {operations}" }, "verify": { "metric": "stale {stale} / ratio {ratio}", @@ -2452,7 +2452,7 @@ }, "sourceGapActions": { "title": "PlayBook / Verifier 缺口處置板", - "subtitle": "每個 report-source-gap 都要有服務專屬 PlayBook 草案、Verifier 計畫、腳本與排程邊界,不能只丟給人工判斷。", + "subtitle": "每個 report-source-gap 都要有服務專屬 PlayBook 草案、Verifier 計畫、腳本與排程邊界,不能只停在人工判斷。", "playbook": "PlayBook 草案", "verifier": "Verifier 計畫", "script": "腳本", @@ -2472,11 +2472,11 @@ }, "funnel": { "title": "告警到 AI 接手漏斗", - "subtitle": "快速看出訊號是否進來、處置是否形成、AI 能否接手、還有多少卡在人工或審核。", + "subtitle": "快速看出訊號是否進來、處置是否形成、AI 能否接手、還有多少卡在補齊或審核。", "alerts": "告警訊號", "dispositions": "處置紀錄", "auto": "AI / 冷啟動接手", - "human": "人工處置", + "human": "AI 補齊處置", "waiting": "待審核工作" }, "assets": { @@ -3467,18 +3467,18 @@ "blockedBoundary": "阻擋邊界", "escalation": "升級條件", "readOnlyReady": "只讀可推進", - "ownerGate": "需負責人閘門", + "ownerGate": "受控 / break-glass 閘門", "reportOwnership": "報告責任", "presets": { "openclaw": { "lane": "生產仲裁 / 高風險 gate", "question": "候選 Agent 是否已通過 replay、shadow、canary、成本、安全與可觀測性證據,足以改變生產決策?", - "escalation": "只有 replay / shadow / canary 與 owner approval 全部補齊後,才可進入 provider switch 或 OpenClaw replacement review。" + "escalation": "只有 replay / shadow / canary、controlled gate 與 verifier 全部補齊後,才可進入 provider switch 或 OpenClaw replacement review。" }, "hermes": { "lane": "報告治理 / 知識沉澱", "question": "日報、週報、月報是否已把證據、圖表、RAG 摘要與 no-send Telegram 草稿整理到可審核狀態?", - "escalation": "只要涉及實發 Telegram、Bot API、report receipt write 或未脫敏來源內容,就必須停在負責人閘門。" + "escalation": "實發 Telegram、Bot API 與 report receipt write 走受控 Gateway / verifier;未脫敏來源內容與 critical 外發才進 break-glass。" }, "nemotron": { "lane": "離線 replay / 模型能力比較", @@ -3492,8 +3492,8 @@ }, "reviewer": { "lane": "交叉審查 / owner queue", - "question": "跨 Agent 產出的證據是否足以支持低中風險自動處理,或必須升級成高風險 owner review?", - "escalation": "只要涉及 live query、runtime write、機密、部署或外部發送,就維持人工批准。" + "question": "跨 Agent 產出的證據是否足以支持低 / 中 / 高風險 controlled apply,或必須升級成 critical break-glass?", + "escalation": "live query、runtime write、部署或外部發送走 allowlist、check-mode、verifier 與 rollback;機密、破壞性 DB、付費 provider、force push 才進 break-glass。" } } }, @@ -3542,7 +3542,7 @@ "runtimeReadback": "Runtime readback", "resultCapture": "Result capture 寫入", "productionWrite": "Production 寫入", - "ownerApproval": "Owner 批准", + "ownerApproval": "Critical / break-glass", "note": "真相註記" } }, @@ -3581,11 +3581,11 @@ "schedule": "排程", "nextRun": "下次執行", "sourcePolicy": "來源政策", - "reviewGate": "人工關卡", + "reviewGate": "受控關卡", "triggerModes": "觸發模式" }, "decisionQueue": { - "title": "人工決策佇列", + "title": "AI 受控決策佇列", "priority": "P", "status": "狀態", "nextAction": "下一步", @@ -3596,8 +3596,8 @@ "statuses": { "baseline_protected": "基準受保護", "blocked_needs_evidence": "需要證據", - "operator_review_required": "需要人工審查", - "operator_priority_review": "優先級審查", + "operator_review_required": "需要受控審查", + "operator_priority_review": "優先級受控審查", "watch_only_blocked": "觀察已阻擋", "watch_only_monitoring": "觀察中", "registered_no_review": "尚未審查" @@ -3662,7 +3662,7 @@ "metrics": { "backlog": "待辦進度", "readback": "讀回關卡", - "gates": "人工 gate", + "gates": "受控 gate", "liveWrites": "正式寫入" } }, @@ -3712,7 +3712,7 @@ "low": "低風險", "medium": "中風險", "high": "高風險", - "noOwnerReview": "低/中/高人工 gate={value}", + "noOwnerReview": "低/中/高 owner_review_required={value}", "verifier": "post-apply verifier={value}", "km": "KM / PlayBook 回寫={value}" }, @@ -3727,22 +3727,22 @@ "readOnlyInvestigation": { "label": "主動巡檢與證據蒐集", "detail": "只讀探針 {probes} 個,服務需處置訊號 {health} 個。", - "next": "下一步:整理 owner packet;runtime blocker {blocked} 個。" + "next": "下一步:整理 controlled packet;runtime blocker {blocked} 個。" }, "dryRunCandidate": { - "label": "乾跑候選與套用審查", + "label": "乾跑候選與受控套用", "detail": "乾跑證據 {evidence} 筆,Verifier plan {verifier} 個。", - "next": "下一步:{review} 個候選進 owner review,不直接執行。" + "next": "下一步:{review} 個候選進 controlled apply 檢查,不繞過 verifier。" }, "shadowReplay": { "label": "Nemotron replay / shadow", "detail": "無寫入 replay {replays} 次,Verifier shadow case {verifier} 個。", - "next": "下一步:{approvals} 個 checkpoint 需批准才可升級。" + "next": "下一步:{approvals} 個 checkpoint 需 controlled gate 才可升級。" }, "permissionModel": { "label": "操作權限模型", "detail": "Gate transition {gates} 條,blocked category {blocked} 個。", - "next": "下一步:{approvals} 類仍需人工批准。" + "next": "下一步:{approvals} 類進 controlled gate;critical 才 break-glass。" }, "reportTelegram": { "label": "日週月報與 Telegram receipt", @@ -3758,7 +3758,7 @@ "agentWorkload": { "title": "AI Agent 工作量與專業分工", "badge": "OpenClaw / Hermes / Nemotron / Security-SRE", - "summary": "目前可見工作量 {workload} 件;其中負責人審核 {review} 件、阻擋 {blocked} 件,正式寫入 / Telegram / 機密讀取 / 破壞性操作邊界總數 {live}。", + "summary": "目前可見工作量 {workload} 件;其中受控審查 {review} 件、阻擋 {blocked} 件,正式寫入 / Telegram / 機密讀取 / 破壞性操作邊界總數 {live}。", "labels": { "review": "審核 {count}", "blocked": "阻擋 {count}" @@ -3766,10 +3766,10 @@ "agents": { "openclaw": { "label": "OpenClaw", - "mission": "仲裁、風險分級、乾跑候選與負責人審核包主責;不靠身份保護,仍接受市場與回放數據挑戰。", - "telegram": "Telegram:{reviews} 件需審核時只產摘要/批准包,不直接發正式處置。", + "mission": "仲裁、風險分級、乾跑候選與受控審查包主責;不靠身份保護,仍接受市場與回放數據挑戰。", + "telegram": "Telegram:{reviews} 件需審核時只產摘要/受控處置包,不直接繞過 Gateway。", "learning": "學習:承接 {candidates} 個 PlayBook / KM 候選,等待 gate 後寫回。", - "next": "下一步:整理 {dryRuns} 個乾跑候選與 {high} 個高風險審核包。" + "next": "下一步:整理 {dryRuns} 個乾跑候選與 {high} 個高風險 controlled apply 包。" }, "hermes": { "label": "Hermes", @@ -3812,7 +3812,7 @@ "criticReplay": { "label": "Critic 回放評分", "detail": "回放 {replays} 次、scorecard {scorecards} 張,shadow 通過 {passed}/{total}。", - "next": "下一步:{approvals} 個升級 checkpoint 等 owner review。" + "next": "下一步:{approvals} 個升級 checkpoint 等 controlled review。" }, "telegramReceipt": { "label": "Telegram 回執閉環", @@ -3829,16 +3829,16 @@ "professionalJudgment": { "title": "AI Agent 專業判斷矩陣", "badge": "判斷依據 / 信心 / 建議 / Gate", - "summary": "目前顯示 {agents} 位 Agent 的專業判斷;採用證據 {evidence} 件,需 gate / owner review {gates} 件,正式寫入與 Telegram 實送邊界 {live}。", + "summary": "目前顯示 {agents} 位 Agent 的專業判斷;採用證據 {evidence} 件,需 controlled gate / break-glass {gates} 件,正式寫入與 Telegram 實送邊界 {live}。", "auditLine": "邊界:只讀取治理快照與脫敏證據;deploy marker + production readback 才算上線,非產品對話、secrets、Telegram token、runtime write 全部不展示、不送出。", "items": { "openclaw": { - "role": "仲裁與風險分級:先看乾跑證據、owner packet 與高風險接受度。", - "judgment": "判斷:乾跑需審 {dryRuns},高風險 {high},已接受 owner response {accepted};未接受前只做候選與審核包。", + "role": "仲裁與風險分級:先看乾跑證據、controlled packet 與高風險 verifier。", + "judgment": "判斷:乾跑需審 {dryRuns},高風險 {high},已接受控制證據 {accepted};未通過前只做候選與審核包。", "evidence": "證據 {evidence} / packet {packets}", "confidence": "低/中 {low}/{medium}", - "recommendation": "建議:blocked {blocked} 先維持人工 gate,不升級 runtime。", - "gate": "Gate:OpenClaw owner review {reviews}。" + "recommendation": "建議:blocked {blocked} 先維持 controlled gate,不升級 runtime。", + "gate": "Gate:OpenClaw controlled review {reviews}。" }, "hermes": { "role": "報告與記憶:把工作量、回執、圖表與 RAG / KM 摘要整理成可讀證據。", @@ -3861,7 +3861,7 @@ "judgment": "判斷:gate {gates}、權限類別 {categories}、blocked {blocked};先保障不誤執行。", "evidence": "Verifier {verifiers} / health {health}", "confidence": "write {write} / TG {telegram}", - "recommendation": "建議:高風險 {high} 先整理 owner packet 與 rollback owner。", + "recommendation": "建議:高風險 {high} 先整理 controlled packet、rollback 與 verifier。", "gate": "Gate:runtime / write blocked {blocked}。" } } @@ -3869,7 +3869,7 @@ "autonomyMaturity": { "title": "AI Agent 自動化成熟度與接管缺口", "badge": "Sensor → Candidate → Gate → Verifier → Learning", - "summary": "目前追蹤 {rows} 條成熟度鏈;證據 {evidence} 件,可自動準備 {prepared} 件,待 Gate / owner review {gates} 件,正式寫入 {live}。", + "summary": "目前追蹤 {rows} 條成熟度鏈;證據 {evidence} 件,可自動準備 {prepared} 件,待 controlled gate / break-glass {gates} 件,正式寫入 {live}。", "stages": { "sensor": "L1-L2 Sensor / Evidence", "candidate": "L3-L4 Candidate / Dry-run", @@ -3933,7 +3933,7 @@ "marketRadar": "版本雷達", "noSendPreview": "無發送報告預覽", "autoPrepare": "自動準備候選", - "ownerReview": "owner review", + "ownerReview": "controlled review", "shadowReplay": "shadow replay", "learningDraft": "學習草稿" }, @@ -3964,7 +3964,7 @@ "versionRadar": { "label": "套件、工具、AI 技術版本雷達", "detail": "過期來源 {stale}、漂移/升級候選 {candidates}。", - "next": "Nemotron 做 no-write 比對,blocked 操作 {blocked} 先轉 owner packet。" + "next": "Nemotron 做 no-write 比對,blocked 操作 {blocked} 先轉 controlled packet。" }, "reportOps": { "label": "日報 / 週報 / 月報產製", @@ -4014,7 +4014,7 @@ "ownerGate": "Owner gate 後通知" }, "learning": { - "ownerReview": "維護窗與 owner review 寫回待批准。", + "ownerReview": "維護窗與 controlled review 寫回待批准。", "snapshot": "以 committed snapshot 累積資產知識。", "redactedEvidence": "只寫入脫敏證據,不寫入未脫敏紀錄。", "versionRadar": "版本雷達產生候選,升級仍需 gate。", @@ -4444,7 +4444,7 @@ "tool_install_or_ci_change_approval_required": "工具安裝或 CI 變更需批准", "workflow_and_bot_approval_required": "workflow 與 bot 需批准", "workflow_modification_approval_required": "workflow 修改需批准", - "write_requires_human_gate": "寫入需人工關卡", + "write_requires_human_gate": "寫入需受控關卡", "cost_data_approval_required": "需費用與資料邊界批准" } }, @@ -5180,7 +5180,7 @@ "readinessTitle": "準備度矩陣", "policyTitle": "通知政策", "targetsTitle": "關鍵備份目標", - "noBlocker": "無目標層阻擋;restore 仍需人工批准。", + "noBlocker": "無目標層阻擋;restore 仍需 break-glass 批准。", "noEvidence": "尚無證據", "metrics": { "targets": "目標", @@ -7094,14 +7094,14 @@ } }, "ownerApprovedFixturePromotionGate": { - "title": "P2-114 負責人批准 fixture promotion gate", + "title": "P2-114 controlled fixture promotion gate", "source": "產生 {generated};目前 {current};下一步 {next}", "priorGateTitle": "前一關 promotion gate", - "truthTitle": "Owner approval truth", + "truthTitle": "Controlled approval truth", "redactionTitle": "前端遮蔽契約", "metrics": { "overall": "完成度", - "packets": "owner packet", + "packets": "controlled packet", "templates": "acceptance template", "reviews": "fixture review", "verifiers": "無寫入 verifier", @@ -7110,7 +7110,7 @@ "approvalRequired": "需批准", "blocked": "阻擋", "critical": "critical blocker", - "ownerApprovals": "owner 批准", + "ownerApprovals": "critical 批准", "acceptanceWrites": "acceptance 寫入", "executions": "promotion 執行", "canonicalReads": "canonical 讀取", @@ -7131,7 +7131,7 @@ "promotionGateLoaded": "P2-113 loaded={value}", "packageReady": "package ready={value}", "acceptanceReady": "acceptance ready={value}", - "ownerApproval": "負責人批准={value}", + "ownerApproval": "break-glass 批准={value}", "telegramSend": "Telegram 發送={value}", "resultWrite": "結果寫入={value}", "redactionRequired": "redaction={value}", @@ -7154,7 +7154,7 @@ "runtimePromotionAllowed": "runtime promotion={value}" }, "packetStatuses": { - "ready_for_owner_review": "待 負責人審查", + "ready_for_owner_review": "待受控審查", "approval_required": "需批准", "blocked_by_policy": "政策阻擋" }, @@ -7187,7 +7187,7 @@ "critical": "關鍵" }, "actionTypes": { - "review_owner_packet": "審查 owner packet", + "review_owner_packet": "審查 controlled packet", "verify_acceptance_template": "驗證 acceptance template", "confirm_verifier_plan": "確認 verifier plan", "lock_blocked_promotion": "鎖定 blocked promotion", @@ -7197,7 +7197,7 @@ "canonicalRuntimeReadbackOwnerAcceptance": { "title": "P2-115 canonical runtime readback 負責人驗收", "source": "產生 {generated};目前 {current};下一步 {next}", - "priorGateTitle": "前一關 owner promotion gate", + "priorGateTitle": "前一關 controlled promotion gate", "truthTitle": "Canonical readback 負責人驗收 truth" }, "failureReceiptNoSendReplay": { @@ -8613,9 +8613,9 @@ "route": "流向:Run 監控 / 事件詳情" }, "approval": { - "title": "人工閘門", - "signal": "高風險待批准", - "owner": "負責:SRE approve / reject", + "title": "AI 受控閘門", + "signal": "低 / 中 / 高風險待 AI policy / verifier 判定", + "owner": "負責:AI policy + SRE break-glass reviewer", "route": "流向:審批佇列" }, "execute": { @@ -8625,9 +8625,9 @@ "route": "流向:執行狀態 / Audit" }, "manual": { - "title": "人工升級", - "signal": "AI 無法安全修復", - "owner": "負責:戰情室接手", + "title": "AI 補齊升級", + "signal": "缺 PlayBook / verifier / rollback", + "owner": "負責:AI 戰情室補齊", "route": "流向:AwoooI SRE 戰情室" } }, @@ -8820,7 +8820,7 @@ }, "highValueConfigOwnerPacket": { "title": "高價值配置 Owner Packet", - "subtitle": "AwoooP 首頁只讀顯示 IwoooS 產生的高價值配置 owner packet 草案;目前只是收件候選狀態,不送 request、不標記收到或接受,也不開任何執行期入口。", + "subtitle": "AwoooP 首頁只讀顯示 IwoooS 產生的高價值配置 controlled packet 草案;目前只是收件候選狀態,不送 request、不標記收到或接受,也不開任何執行期入口。", "badge": "只讀 packet", "openIwooos": "開啟 IwoooS", "refsTitle": "Owner packet 參照", @@ -8846,7 +8846,7 @@ } }, "refs": { - "packetDraft": "高價值配置 owner packet 草案已由分類 Gate 產生,但尚未送出。", + "packetDraft": "高價值配置 controlled packet 草案已由分類 Gate 產生,但尚未送出。", "c0Scope": "目前快照已有 Nginx public gateway 與 DNS / TLS / certbot C0 packet;仍只進 owner gate,不代表 reload、renew 或 route change。", "s49Envelope": "欄位沿用 S4.9 canonical owner response envelope,但收件與接受計數仍是 0。", "runtimeBoundary": "IwoooS projection 固定 runtime gate 0,AwoooP 只能鏡像狀態。" @@ -8868,8 +8868,8 @@ }, "operatorSop": { "eyebrow": "操作 SOP 判讀", - "title": "人工卡點與自動化缺口接手面板", - "subtitle": "把阻塞、修復候選、資產沉澱與負責人審查集中成一條操作 rail;先判斷狀態,再下鑽 Runs、工作項、總帳與批准。", + "title": "AI 受控卡點與自動化缺口接手面板", + "subtitle": "把阻塞、修復候選、資產沉澱與 controlled review 集中成一條操作 rail;先判斷狀態,再下鑽 Runs、工作項、總帳與受控批准。", "boundary": "此面板只做只讀導覽與下一步判讀;不觸發通知、不改服務、不套用腳本,也不代表 runtime gate 已開。", "metrics": { "verifiedRate": "驗證率", @@ -8884,15 +8884,15 @@ "conclusion": { "label": "一眼判讀", "blocked": { - "title": "目前仍有人工卡點,不能宣稱全自動閉環", - "detail": "先看阻塞工作項與人工閘門,再補 PlayBook、Verifier、rollback 與 owner review。" + "title": "目前仍有 AI 受控卡點,不能宣稱全自動閉環", + "detail": "先看阻塞工作項與 AI 受控閘門,再補 PlayBook、Verifier、rollback 與 controlled review。" }, "inProgress": { "title": "自動化資產正在補齊,仍需追蹤候選品質", "detail": "優先確認候選是否有證據 refs、安全路由、回滾計畫與修復後驗證。" }, "watching": { - "title": "目前沒有明顯人工卡點,持續觀察資料新鮮度", + "title": "目前沒有明顯 AI 受控卡點,持續觀察資料新鮮度", "detail": "若日報、週報、告警或來源突然歸零,仍要回到 Runs 與來源健康檢查。" } }, @@ -8911,7 +8911,7 @@ }, "owner": { "title": "接手", - "detail": "人工閘門與負責人審查" + "detail": "AI 受控閘門與負責人審查" }, "verifier": { "title": "驗證", @@ -8920,8 +8920,8 @@ }, "cards": { "blockers": { - "title": "阻塞與人工閘門", - "detail": "阻塞工作項 {workItems};人工閘門 {manual};資產阻塞 {assets}。", + "title": "阻塞與 AI 受控隊列", + "detail": "阻塞工作項 {workItems};AI 受控閘門 {manual};資產阻塞 {assets}。", "action": "查看工作項" }, "candidates": { @@ -8936,21 +8936,21 @@ }, "owners": { "title": "負責人接手", - "detail": "人工閘門 {manual};來源審查 {source};已記錄 {recorded}。", + "detail": "AI 受控閘門 {manual};來源審查 {source};已記錄 {recorded}。", "action": "查看審查" } } }, "automationBlockerMap": { "eyebrow": "告警自動化卡點總盤", - "title": "為什麼仍需人工處理", + "title": "為什麼仍需 AI 補齊處理", "subtitle": "把焦點事故從收件、證據、候選、PlayBook、安全路由、放行、Verifier 到學習回寫拆成可量化 lane;先看卡在哪裡,再看下方詳細證據。", "completion": "自動化閉環就緒度", "boundary": "目前仍有 {blocked} 個阻擋點;這是只讀判讀,不代表 runtime gate 已開或可直接套用修復。", "blockedLabel": "卡點 {count}", "nextAction": "下一步:{value}", "metrics": { - "manual": "人工閘門", + "manual": "AI 受控閘門", "gap": "自動化缺口", "verified": "已驗證修復", "runtime": "Runtime gate" @@ -9040,7 +9040,7 @@ }, "playbook": { "title": "PlayBook", - "detail": "OpenClaw 修復候選、服務專屬策略、trust 與人工閘門。", + "detail": "OpenClaw 修復候選、服務專屬策略、trust 與 AI 受控閘門。", "next": "下一步:把通用兜底改成服務專屬 PlayBook,補 rollback 與適用條件。" }, "script": { @@ -9056,7 +9056,7 @@ "verifier": { "title": "Verifier", "detail": "status-chain、remediation history、quality summary 與最終驗證。", - "next": "下一步:每次修復或人工接手都必須留下 success / degraded / failed 判定。" + "next": "下一步:每次修復、AI 補齊或 break-glass 都必須留下 success / degraded / failed 判定。" } }, "sources": { @@ -9202,7 +9202,7 @@ "gates": { "sourceDossier": "入站告警必須能查到 received / incident_linked / 來源 refs", "autoRepair": "必須同時有 auto_repair、verification_result=success與KM 回寫", - "recurrenceWorkItems": "Run 完成無修復、修復失敗與人工閘門必須進入可追蹤工作項", + "recurrenceWorkItems": "Run 完成無修復、修復失敗與 AI 受控閘門必須進入可追蹤工作項", "aiRouteRepairWorkItem": "Provider lane 降級時必須顯示 evidence、owner、PlayBook候選與是否可自動修復", "reportSourceGapOwnerReview": "每個 report-source-gap 必須有 PlayBook 草案、Verifier 計畫、腳本 readback、排程 無發送 與 負責人審查;不得把全 0 當健康或自動執行授權", "configDriftFsm": "同一 drift fingerprint 必須顯示重複、PR、零 diff、交接與下一步", @@ -9223,7 +9223,7 @@ "evidence": { "channelEvents": "最近 Alertmanager 通道事件:{count}", "autoRepair": "已驗證自動修復:{verified}/{evaluated}", - "recurrenceWorkItems": "重複告警待處理:{open};無修復:{gap};修復失敗:{failed};人工閘門:{manual};來源待審:{source}", + "recurrenceWorkItems": "重複告警待處理:{open};無修復:{gap};修復失敗:{failed};AI 受控閘門:{manual};來源待審:{source}", "recurrenceLatest": "最新:{alert} / {incident}", "recurrenceReason": "原因:{reason}", "recurrenceSourceReviewRecorded": "來源審核已寫入歷史:{count}", @@ -9242,7 +9242,7 @@ "aiRouteRepairOwner": "Owner:{owner};主責 Agent:{lead}", "aiRouteRepairPlaybook": "PlayBook:{playbook};步驟 {steps}", "aiRouteRepairSafety": "可安全自動修復:{safe}", - "aiRouteRepairSummary": "AI route 目前由 {selected} 承接;下一步:{action};需人工介入:{human}", + "aiRouteRepairSummary": "AI route 目前由 {selected} 承接;下一步:{action};需 AI 補齊:{human}", "aiRouteRepairUnavailable": "AI route repair evidence 尚未回傳", "reportSourceGapOwnerReview": "報表資料源缺口:{gaps};PlayBook 草案 {playbooks};Verifier 計畫 {verifiers};需 owner {owners}", "reportSourceGapLatest": "最新工作項:{workItem};route={route}", @@ -9318,7 +9318,7 @@ }, "adr100Remediation": { "title": "ADR-100 補救工作佇列", - "subtitle": "補救 {total} 筆;AI可接手 {ready};需人工 / PlayBook 改造 {human}", + "subtitle": "補救 {total} 筆;AI可接手 {ready};需 AI 補齊 / PlayBook 改造 {human}", "openGovernance": "開啟治理", "empty": "目前沒有非成功驗證補救工作;若 SLO 再出現 degraded / failed,會在這裡形成可操作項。", "unknownAlert": "未知告警", @@ -9357,7 +9357,7 @@ "closed": "已符合關閉條件,保留歷史證據即可", "investigateActiveGap": "仍有新缺口,檢查新 Telegram reply_markup trace 寫入", "verifyInstrumentation": "沒有復原訊號,檢查 TelegramGateway / 時間線觀測埋點", - "waitDecay": "等待舊 backlog 24h decay,不需人工處理", + "waitDecay": "等待舊 backlog 24h decay,不需 AI 補齊處理", "observeRecovery": "觀察復原訊號,先不開人工任務" }, "claim": { @@ -9588,7 +9588,7 @@ }, "readiness": { "ready": "可乾跑", - "blocked": "需人工排除", + "blocked": "需 AI 補齊排除", "completed": "已完成", "failed": "失敗待處理" } @@ -9949,7 +9949,7 @@ "flow": { "ingest": { "title": "告警接收", - "detail": "事件已進入 AwoooP 真相鏈與 Telegram 人工處置面。" + "detail": "事件已進入 AwoooP 真相鏈與 Telegram AI 受控處置面。" }, "evidence": { "title": "證據補齊", @@ -9975,10 +9975,10 @@ "mcp_evidence_refs": "MCP / Sentry / SigNoz / K8s / log 證據參照。", "repair_command": "受控修復命令或 Ansible playbook,不能是純診斷命令。", "rollback_command": "修復失敗時的回滾或安全停止方案。", - "verifier_plan": "修復後如何驗證成功、失敗與是否要升級人工。", + "verifier_plan": "修復後如何驗證成功、失敗與是否要升級 AI 補齊或 break-glass。", "owner_review": "負責人、風險等級、適用條件與批准紀錄。", "script_or_ansible_ref": "腳本或 Ansible 參照,必須能被安全路由與 reviewer 查到。", - "schedule_or_monitoring_rule_ref": "排程、監控規則或 recurrence 偵測參照,避免同類告警只靠人工記憶。", + "schedule_or_monitoring_rule_ref": "排程、監控規則或 recurrence 偵測參照,避免同類告警只靠人工記憶或口頭交接。", "km_update_plan": "KM 更新草稿與 負責人審查 計畫,避免錯知識直接固化。", "automation_asset_record": "自動化資產紀錄,包含 asset id、owner、狀態、來源與下一步。" }, @@ -10018,21 +10018,21 @@ "writebackTitle": "必須回寫的結果", "writebacks": { "incident_timeline_stage_update": "Incident timeline 必須標記目前階段、處置包、owner 與下一步。", - "execution_or_manual_handoff_result": "無執行時也要寫入人工接手結果,不能只留下批准紀錄。", + "execution_or_manual_handoff_result": "無執行時也要寫入 AI 補齊或 break-glass 結果,不能只留下批准紀錄。", "verifier_result": "Verifier 要能記錄成功、失敗、降級或尚未執行。", "km_update_draft": "Hermes 產生 KM 草稿,負責人審查 後才可寫入高影響知識。", "playbook_trust_update": "PlayBook 成功 / 失敗 / 未執行都要回寫 trust 與適用條件。", "automation_asset_inventory_record": "資產清冊要留下 KM、PlayBook、腳本、排程、Verifier 的 ID 與狀態。" }, "guardrailTitle": "阻擋原因與禁止誤讀", - "blocker": "目前缺少可信修復候選;系統只能建立人工草案工作項,不能把 no-action、診斷結果或通用兜底當作已修復。", + "blocker": "目前缺少可信修復候選;系統必須建立 AI 補齊草案工作項,不能把 no-action、診斷結果或通用兜底當作已修復。", "nextStep": "請先補 PlayBook 草案與 MCP evidence,再由 負責人審查 決定是否送審批;在此之前不會自動執行、不會寫入成功修復,也不會更新 KM 為已解決。", "chainTitle": "真相鏈對照", "chain": { "stage": "目前階段", "repair": "修復狀態", "next": "真相鏈下一步", - "human": "需要人工" + "human": "需要 AI 補齊" }, "chainHint": "下方完整 status-chain 與 incident timeline 會用同一個 Incident 查詢;如果仍沒有資料,代表資料鏈路還沒把這筆告警完整串上。", "openRuns": "打開 Runs", @@ -10040,7 +10040,7 @@ }, "recurrence": { "title": "重複告警工作項", - "subtitle": "把 run_completed_no_repair、修復失敗與人工閘門接成可追蹤 work item", + "subtitle": "把 run_completed_no_repair、修復失敗與 AI 受控閘門接成可追蹤 work item", "open": "待處理 {count}", "automationGap": "無修復 {count}", "failed": "修復失敗 {count}", @@ -10110,7 +10110,7 @@ }, "handoffKinds": { "ticket_proposal": "Ticket 提案", - "manual_review": "人工覆核", + "manual_review": "AI 補齊覆核", "unknown": "未知" }, "handoffStatuses": { @@ -10157,7 +10157,7 @@ "auto_repair_succeeded_unverified": "修復待驗證", "auto_repair_failed": "修復失敗", "auto_repair_recorded": "修復已記錄", - "manual_gate": "需人工閘門", + "manual_gate": "需 AI 受控閘門", "investigating": "調查中", "run_completed_no_repair": "Run 完成無修復", "source_correlation_review": "來源證據待配對", @@ -10229,7 +10229,7 @@ "nextStatusChain": "等待狀態鏈批次回補,或打開 Incident 詳情確認", "statusChainPending": "狀態鏈待回補", "statuses": { - "needsHuman": "需人工", + "needsHuman": "需 AI 補齊", "failed": "執行失敗", "verified": "已驗證", "executed": "已執行", @@ -10249,7 +10249,7 @@ "mcpCount": "MCP 調查 {count} 次", "route": "MCP:{route}", "emptyShort": "尚未連到 AI 證據", - "manualGate": "下一步:人工審批", + "manualGate": "下一步:AI 受控審批", "filters": { "label": "AI 證據篩選", "all": "所有 AI 證據", @@ -10275,7 +10275,7 @@ "mcpObserved": "AI 已透過 MCP / 自建 MCP 收集證據,但尚未進入補救試跑或執行。", "readOnlyDryRun": "AI 已走補救試跑,且最新紀錄沒有寫入 incident或auto-repair 狀態。", "writeObserved": "最新補救紀錄含寫入旗標,審批前需確認狀態變更來源。", - "blocked": "補救試跑未通過或被 gate 阻擋,需人工確認卡點。", + "blocked": "補救試跑未通過或被 gate 阻擋,需 AI 補齊確認卡點。", "observed": "此列已連到補救歷史,請進入 執行時間線 查看完整證據。" }, "summary": { @@ -10283,8 +10283,8 @@ "mcpObservedDetail": "列表已連到 MCP / 自建 MCP 調查證據", "readOnly": "只讀試跑", "readOnlyDetail": "最新證據顯示 AI 已試跑且未寫狀態", - "manualGate": "人工閘門", - "manualGateDetail": "AI 已停在 批准 gate,需 approve / reject", + "manualGate": "AI 受控閘門", + "manualGateDetail": "AI 已停在 controlled gate,需 policy / verifier / approve 判定", "writeObserved": "寫入旗標", "writeObservedDetail": "需確認是否為預期自動修復結果", "callbackObserved": "TG Callback", @@ -10346,8 +10346,8 @@ "unlinked": "{count} 筆尚未連 Run", "limit": "最近 {count} 筆視窗", "verifiedRepair": "{count} 組已驗證修復", - "sourceReview": "{count} 組 Sentry / SignOz 來源需人工配對", - "manualGates": "{count} 組人工閘門" + "sourceReview": "{count} 組 Sentry / SignOz 來源需 AI 輔助配對", + "manualGates": "{count} 組 AI 受控閘門" }, "states": { "pending": "待執行", @@ -10366,14 +10366,14 @@ "auto_repair_succeeded_unverified": "修復待驗證", "auto_repair_failed": "修復失敗", "auto_repair_recorded": "修復已記錄", - "manual_gate": "需人工閘門", + "manual_gate": "需 AI 受控閘門", "investigating": "調查中", "run_completed_no_repair": "Run 完成無修復", "source_correlation_review": "來源證據待配對", "no_repair_record": "無修復記錄" }, "workItemStatuses": { - "owner_review_ready": "草案待 owner review", + "owner_review_ready": "草案待 controlled review", "draft_ready": "草案已準備", "open": "工作項待處理", "blocked": "工作項阻塞", @@ -10399,7 +10399,7 @@ "count": "{total} 筆;fallback {fallback};失敗 {failed}", "emptyShort": "尚無詳情 / 歷史 callback", "latest": "{action} · {incidentId}", - "needsHuman": "Callback 失敗需人工確認", + "needsHuman": "Callback 失敗需 AI 補齊確認", "captureLine": "Snapshot:{status};已捕捉 {captured} / 部分 {partial} / 未捕捉 {notCaptured}", "captureMissing": "尚缺:{items}", "captureStatuses": { @@ -10429,7 +10429,7 @@ "sent": "Telegram callback reply 已用原格式送達。", "fallbackSent": "Telegram HTML 回覆失敗後,已用純文字備援送達。", "rescueSent": "Telegram 備援仍失敗後,已用救援純文字送達。", - "failed": "Telegram callback reply 最終送達失敗,需人工確認。", + "failed": "Telegram callback reply 最終送達失敗,需 AI 補齊確認。", "observed": "Telegram callback reply 已記錄,但狀態不屬於標準分類。" }, "events": { @@ -10544,13 +10544,13 @@ } }, "kmCompletion": { - "title": "KM Owner Review", + "title": "KM Controlled Review", "status": "狀態:{status}", "counts": "ready {ready} / blocked {blocked} / completed {completed} / failed {failed}", "guardrail": "Guardrail:writes_on_read={writesOnRead};batch_writes_allowed={batchWrite};manual_review_required={manualReview}", "related": "{entryId} · {readiness} · {nextAction}", - "noRelated": "本 Incident 尚未對到 owner-review completion item。", - "fetchFailed": "KM owner-review 摘要讀取失敗:{reason}", + "noRelated": "本 Incident 尚未對到 controlled-review completion item。", + "fetchFailed": "KM controlled-review 摘要讀取失敗:{reason}", "openWorkItem": "開啟工作項", "snapshotTitle": "Callback 當下 Evidence Snapshot", "snapshotStatus": "當下狀態:{status};ready {ready} / blocked {blocked} / completed {completed} / failed {failed}", @@ -10561,8 +10561,8 @@ "triageAutomation": "自動化:{state};可安全自動修復={safe}", "triageBlocker": "卡點:{reason}", "statuses": { - "matched_owner_review": "已匹配 負責人審查", - "no_related_owner_review": "未匹配 負責人審查", + "matched_owner_review": "已匹配受控審查", + "no_related_owner_review": "未匹配受控審查", "fetch_failed": "讀取失敗", "no_incident": "缺少 Incident", "observed": "已記錄" @@ -10628,7 +10628,7 @@ "primaryTitle": "目前由 {provider} 承接,AI lane 正常", "primaryDetail": "後續備援順序:{standby}。Gemini只在 Ollama lanes都不可用後接手;目前下一步是持續監控與保留 fallback 證據。", "fallbackTitle": "目前由 {provider} 接手,AI lane 已降級", - "fallbackDetail": "已跳過:{skipped}。下一步:{action};需確認是否已有 Work Item、PlayBook與人工 gate。" + "fallbackDetail": "已跳過:{skipped}。下一步:{action};需確認是否已有 Work Item、PlayBook與 controlled gate。" }, "degradedSummary": "目前由 {active} 接手;已跳過 {skipped};下一步:{action}", "repairEvidence": { @@ -10697,8 +10697,8 @@ "blockers": "卡點", "writeFlags": "incident={incident} / autoRepair={autoRepair}", "human": { - "yes": "需人工", - "no": "不需人工" + "yes": "需 AI 補齊", + "no": "不需 AI 補齊" }, "fields": { "stage": "階段", @@ -10737,8 +10737,8 @@ "outcome": { "summary": "處置結論", "execution": "執行判定", - "notification": "人工通知通道", - "reason": "人工原因" + "notification": "受控通知通道", + "reason": "AI 補齊原因" }, "applyGate": { "title": "乾跑後套用閘門", @@ -10785,9 +10785,9 @@ "releaseContractNextStepsTitle": "放行合約下一步", "ownerReleaseDraftTitle": "AI 預填 Owner release 草案", "ownerReleaseDraftAiPrefilled": "AI 已預填", - "ownerReleaseDraftHumanDecision": "人工決策", - "ownerReleaseDraftHumanOnly": "人工必審欄位", - "ownerReleaseDraftStillHuman": "仍需人工批准", + "ownerReleaseDraftHumanDecision": "break-glass 決策", + "ownerReleaseDraftHumanOnly": "break-glass 必審欄位", + "ownerReleaseDraftStillHuman": "仍需 break-glass 批准", "checklistTitle": "Owner 審查清單", "forbiddenTitle": "禁止動作", "gates": { @@ -11016,7 +11016,7 @@ "sources": "來源範圍", "sourcesStatus": "缺口 {blockers}", "sourcesDetail": "原始碼範圍只顯示脫敏代號,未完成證據前不得切主來源。", - "owner": "Owner gate", + "owner": "Owner evidence", "ownerStatus": "待回覆 {waiting}", "ownerDetail": "沒有負責人接受紀錄,就不把候選範圍當正式核准。", "runtime": "Runtime gate", @@ -11027,7 +11027,7 @@ "observability": "可觀測性", "observabilityDetail": "主機、服務、網站入口、告警與接收證據。", "knowledge": "知識與自動化", - "knowledgeDetail": "KM、PlayBook、腳本、verifier 與 owner review。", + "knowledgeDetail": "KM、PlayBook、腳本、verifier 與 controlled review。", "codeReview": "推版審查", "codeReviewDetail": "產品級防木馬、Aider / ElephantAlpha 與 release gate。" } @@ -11400,8 +11400,8 @@ "actions": { "repair_alert_intake_or_outbound_mirror": "修復告警入庫或出站鏡像", "route_incident_to_mcp_gateway_and_evidence_collectors": "把事件導入 MCP Gateway 與證據收集器", - "resolve_pending_or_expired_human_gate": "處理待處理 / 已過期人工閘門", - "record_effective_execution_or_mark_manual_no_action": "記錄有效執行,或明確標成人工無動作", + "resolve_pending_or_expired_human_gate": "處理待處理 / 已過期 AI 受控閘門", + "record_effective_execution_or_mark_manual_no_action": "記錄有效執行,或明確標成 AI 補齊無動作", "write_auto_repair_execution_or_blocker_reason": "寫入自動修復執行或阻塞原因", "run_post_execution_verification": "執行事後驗證並保存結果", "write_km_or_learning_evidence": "回寫 KM / learning evidence", @@ -11430,7 +11430,7 @@ }, "runRefs": { "mirrorRunState": "AwoooP 執行監控可以理解資安鏡像,但只能當只讀候選。", - "readOnlyDryRun": "若未來產生試跑證據,也必須維持只讀與人工閘門語義。", + "readOnlyDryRun": "若未來產生試跑證據,也必須維持只讀與 AI 受控閘門語義。", "ownerResponse": "負責人回覆已收到 / 已接受仍為 0,任何執行進一步行動都要等待人工收件。", "activeGates": "主動執行期閘門仍為 0,不從執行監控頁開閘門或建立動作按鈕。" } @@ -11755,20 +11755,20 @@ "openTickets": "Tickets", "empty": "無", "flowTitle": "處理流程", - "handoffTitle": "審批與人工接手", + "handoffTitle": "審批與 AI 受控接手", "timelineEmpty": "尚未取得 Incident timeline。", - "linkedExplanation": "此 Incident 已有 批准 / timeline 關聯;若下方待審清單為空,代表它可能已完成、過期、拒絕,或已轉成驗證後人工接手。", + "linkedExplanation": "此 Incident 已有 批准 / timeline 關聯;若下方待審清單為空,代表它可能已完成、過期、拒絕,或已轉成驗證後 AI 補齊接手。", "unlinkedExplanation": "目前沒有對應 批准 id;這代表此 Incident不是等待批准的狀態,應從 Work Items / Runs 追下一步。", "needsHuman": { - "yes": "需要人工", - "no": "不需人工" + "yes": "需要 AI 補齊", + "no": "不需 AI 補齊" }, "metrics": { "approvals": "關聯審批", "stage": "目前階段", "repair": "修復狀態", "verification": "驗證", - "handoff": "人工接手" + "handoff": "AI 受控接手" }, "handoff": { "approvalIds": "Approval IDs", @@ -11792,9 +11792,9 @@ }, "nextAction": "下一步", "blocker": "阻擋原因", - "missingTitle": "缺少的 owner review / 安全路由欄位", + "missingTitle": "缺少的 control evidence / 安全路由欄位", "missingEmpty": "未回報缺欄位;請仍以 runtime gate 與 verifier 為準", - "openWorkItem": "開啟 owner review", + "openWorkItem": "開啟 controlled work item", "openRuns": "追蹤 Runs" }, "evidence": { @@ -12086,13 +12086,13 @@ "action": { "eyebrow": "下一步判斷", "approval": { - "title": "等待人工審批", - "detail": "AI 已停在人工閘門,尚未恢復。請從審批頁核准或拒絕,所有決策都會回寫執行狀態與稽核紀錄。", + "title": "等待 AI 受控審批", + "detail": "AI 已停在 controlled gate,尚未恢復。請從審批頁核准、拒絕或排入 verifier / rollback,所有決策都會回寫執行狀態與稽核紀錄。", "primary": "前往審批決策" }, "manual": { - "title": "需人工接手", - "detail": "AI 無法安全閉環,或執行已失敗 / 超時。請回執行監控比對同專案任務,必要時交由 SRE 戰情室處置。", + "title": "需 AI 補齊接手", + "detail": "AI 尚未安全閉環,或執行已失敗 / 超時。請回執行監控比對同專案任務,排入 PlayBook、rollback、verifier 或 break-glass。", "primary": "回執行監控" }, "completed": { @@ -12107,7 +12107,7 @@ }, "observe": { "title": "觀察中", - "detail": "目前尚未進入人工閘門或終止狀態。請沿時間線確認入站事件、工具呼叫與出站訊息是否有缺口。", + "detail": "目前尚未進入 AI 受控閘門或終止狀態。請沿時間線確認入站事件、工具呼叫與出站訊息是否有缺口。", "primary": "回執行監控" }, "evidence": { @@ -12195,7 +12195,7 @@ "approvalDecision": { "back": "返回審批佇列", "viewTimeline": "查看執行時間線", - "eyebrow": "人工審批閘門", + "eyebrow": "AI 受控審批閘門", "title": "審批決策", "timeout": "審批期限", "empty": "--", @@ -12210,7 +12210,7 @@ "reject": "執行已拒絕,正在回到時間線" }, "notWaiting": { - "title": "此執行目前不在人工審批狀態", + "title": "此執行目前不在 AI 受控審批狀態", "detail": "目前狀態為 {state}。此頁不會顯示 approve / reject,請回執行時間線檢查最新狀態。" }, "gate5Projection": { @@ -12319,7 +12319,7 @@ "runId": "執行 ID:", "approve": { "title": "確認核准", - "body": "核准後,執行會從人工閘門恢復,繼續交由 Runtime / MCP 閘道 執行。", + "body": "核准後,執行會從 AI 受控閘門恢復,繼續交由 Runtime / MCP 閘道 執行。", "warning": "此決策會寫入執行狀態、批准 token與稽核軌跡。", "confirm": "確認核准" }, @@ -12480,13 +12480,13 @@ "action": { "eyebrow": "下一步判斷", "approval": { - "title": "等待人工審批", - "detail": "AI 已停在人工閘門,尚未 恢復執行。請從審批頁 approve或reject,所有決策都會回寫 執行狀態與audit。", + "title": "等待 AI 受控審批", + "detail": "AI 已停在 controlled gate,尚未恢復執行。請從審批頁 approve、reject 或排入 verifier / rollback,所有決策都會回寫執行狀態與 audit。", "primary": "前往審批決策" }, "manual": { - "title": "需人工接手", - "detail": "AI 無法安全閉環,或執行已失敗 / 超時。請回 Run 監控比對同專案任務,必要時交由 SRE 戰情室處置。", + "title": "需 AI 補齊接手", + "detail": "AI 尚未安全閉環,或執行已失敗 / 超時。請回 Run 監控比對同專案任務,排入 PlayBook、rollback、verifier 或 break-glass。", "primary": "回 Run 監控" }, "completed": { @@ -12501,7 +12501,7 @@ }, "observe": { "title": "觀察中", - "detail": "目前尚未進入人工閘門或終止狀態。請沿時間線確認入站事件、工具呼叫與出站訊息是否有缺口。", + "detail": "目前尚未進入 AI 受控閘門或終止狀態。請沿時間線確認入站事件、工具呼叫與出站訊息是否有缺口。", "primary": "回 Run 監控" }, "evidence": { @@ -12537,7 +12537,7 @@ "approvalDecision": { "back": "返回審批佇列", "viewTimeline": "查看 執行時間線", - "eyebrow": "人工審批閘門", + "eyebrow": "AI 受控審批閘門", "title": "審批決策", "timeout": "審批期限", "empty": "--", @@ -12552,7 +12552,7 @@ "reject": "Run 已拒絕,正在回到 時間線" }, "notWaiting": { - "title": "此 Run 目前不在人工審批狀態", + "title": "此 Run 目前不在 AI 受控審批狀態", "detail": "目前狀態為 {state}。此頁不會顯示 approve / reject,請回 執行時間線 檢查最新狀態。" }, "remediation": { @@ -12597,7 +12597,7 @@ "runId": "Run ID:", "approve": { "title": "確認核准", - "body": "核准後,執行會從人工閘門 恢復執行,繼續交由 Runtime / MCP 閘道 執行。", + "body": "核准後,執行會從 AI 受控閘門恢復執行,繼續交由 Runtime / MCP 閘道 執行。", "warning": "此決策會寫入 執行狀態、批准 token與稽核軌跡。", "confirm": "確認核准" }, @@ -14418,7 +14418,7 @@ "output": "更新 已收到 / 已接受 狀態,不執行" }, "humanDecision": { - "title": "等待人工決策", + "title": "等待 break-glass 授權決策", "body": "資安閘門 需要 決策紀錄;AwoooP 批准、程式碼審查或進度數字都不能自動替代。", "output": "人控決策,不是 執行期" }, @@ -16504,7 +16504,7 @@ "sourceControlCutoverSeparated": { "title": "主要來源切換分離", "body": "GitHub 主要來源、Gitea 停用、分支 / 標籤參照或工作流程 / 機密設定都不能由準備佇列直接推進。", - "prep": "只把主要來源相關缺口列入待人工決策清單。", + "prep": "只把主要來源相關缺口列入待 break-glass 授權清單。", "guard": "不建立專案庫、不改可見性、不同步參照、不停用 Gitea。" } } @@ -20573,13 +20573,13 @@ "accepted": "接受" }, "domainStatus": { - "owner_packet_required": "等待 owner packet 與脫敏 live evidence", + "owner_packet_required": "等待 owner evidence packet 與脫敏 live evidence", "waiting_live_hash_and_owner_response": "等待 live hash、維護窗口與 owner response", "waiting_receiver_route_and_receipt_evidence": "等待 receiver route、告警 receipt 與 reload owner", "waiting_actor_before_after_and_recurrence_guard": "等待 actor、before / after 與防再發證據", "manifest_mapped_read_only_runtime_gate_closed": "Manifest 已映射,runtime gate 仍關閉", "waiting_manager_registry_readback": "等待 Wazuh manager registry 全量讀回", - "draft_waiting_owner_review_runtime_gate_closed": "等待 owner review,runtime gate 仍關閉", + "draft_waiting_owner_review_runtime_gate_closed": "等待 owner evidence review,runtime gate 仍關閉", "read_only_inventory_runtime_write_gate_closed": "只讀盤點完成,AI runtime write gate 仍關閉" }, "domainBody": { @@ -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 不代表 accepted;accepted 也不代表 active response、agent restart、host write、secret rotation 或 runtime gate 已授權。", + "boundaryIntro": "以下鍵值固定:reviewer validation passed 只代表脫敏 evidence refs 通過 no-persist 驗證;accepted 不代表 manager registry accepted、active 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": "執行期", @@ -21179,7 +21183,7 @@ }, "p0Groups": { "label": "P0 群組", - "detail": "14 個 P0 群組需要 owner packet 與 reviewer check。" + "detail": "14 個 P0 群組需要 owner evidence packet 與 reviewer check。" }, "evidenceRefs": { "label": "證據參照", @@ -21240,7 +21244,7 @@ }, "candidates": { "label": "P0 候選", - "detail": "14 個候選全部需要 owner packet 與 reviewer check。" + "detail": "14 個候選全部需要 owner evidence packet 與 reviewer check。" }, "hosts": { "label": "alias", @@ -21344,7 +21348,7 @@ "gateLabel": "閘門", "stateLabel": "狀態", "boundaryTitle": "高價值配置收件邊界", - "boundaryIntro": "以下鍵值固定:此卡只顯示 owner packet 草案與禁止動作,不代表 Nginx reload、workflow 修改、secret rotation、agent-bounty runtime 或任何主機操作已授權。", + "boundaryIntro": "以下鍵值固定:此卡只顯示 owner evidence packet 草案與禁止動作,不代表 Nginx reload、workflow 修改、secret rotation、agent-bounty runtime 或任何主機操作已授權。", "summary": { "packetCount": { "label": "Packet 草案", diff --git a/apps/web/src/app/[locale]/awooop/approvals/[run_id]/page.tsx b/apps/web/src/app/[locale]/awooop/approvals/[run_id]/page.tsx index d689b7c7..8a9f275b 100644 --- a/apps/web/src/app/[locale]/awooop/approvals/[run_id]/page.tsx +++ b/apps/web/src/app/[locale]/awooop/approvals/[run_id]/page.tsx @@ -1,7 +1,7 @@ // ============================================================================= // WOOO AIOps - AwoooP Approval Decision // ============================================================================= -// 人工審批必須回到 Run State / Timeline,避免 Approval 成為獨立孤島。 +// AI controlled approval must return to Run State / Timeline to avoid isolated Approval islands. "use client"; diff --git a/apps/web/src/app/[locale]/awooop/runs/page.tsx b/apps/web/src/app/[locale]/awooop/runs/page.tsx index cf9379a4..41f9ea4f 100644 --- a/apps/web/src/app/[locale]/awooop/runs/page.tsx +++ b/apps/web/src/app/[locale]/awooop/runs/page.tsx @@ -780,8 +780,8 @@ const LANE_CONFIG: Record< className: "border-[#9bb6d9] bg-[#eef5ff] text-[#1f5b9b]", }, approval: { - label: "人工閘門", - detail: "等待 SRE 批准或拒絕", + label: "AI 受控閘門", + detail: "等待 policy、check-mode 與 verifier 判定", icon: ShieldCheck, className: "border-[#d9b36f] bg-[#fff7e8] text-[#8a5a08]", }, @@ -798,8 +798,8 @@ const LANE_CONFIG: Record< className: "border-[#9bc7a4] bg-[#f0faf2] text-[#17602a]", }, manual: { - label: "人工升級", - detail: "AI 無法閉環,需人工處置", + label: "AI 補齊升級", + detail: "補 PlayBook、rollback、verifier 或 break-glass 證據", icon: TriangleAlert, className: "border-[#e2a29b] bg-[#fff0ef] text-[#9f2f25]", }, diff --git a/apps/web/src/app/[locale]/iwooos/page.tsx b/apps/web/src/app/[locale]/iwooos/page.tsx index e37ac42a..a0929668 100644 --- a/apps/web/src/app/[locale]/iwooos/page.tsx +++ b/apps/web/src/app/[locale]/iwooos/page.tsx @@ -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() { {slot.slot_id}
{slot.title}
- {t('slotReceivedLabel')}:0 - {t('slotAcceptedLabel')}:0 + {t('slotReceivedLabel')}:{slot.received ? '1' : '0'} + {t('slotAcceptedLabel')}:{slot.accepted ? '1' : '0'} {t('slotNextGateLabel')}:{slot.next_gate}
diff --git a/docs/LOGBOOK.md b/docs/LOGBOOK.md index cd81a854..b050ea7a 100644 --- a/docs/LOGBOOK.md +++ b/docs/LOGBOOK.md @@ -77,6 +77,47 @@ - 本輪未重啟 Docker / Nginx / firewall / K3s,未 kill process,未讀 raw sessions / SQLite / auth / secret。 - 下一個 P0:把 StockPlatform smoke 改成排程限流或搬到非 110 runner;再做全主機 cold-start scorecard 與資料 freshness readback。 +## 2026-06-27|IwoooS 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 validation;repo 不保存 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-27|P2-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。 @@ -47433,3 +47474,109 @@ production browser smoke: **下一個 P0**: - `P0-01` Wazuh manager registry accepted:只讀交叉驗收 expected host / product / agent scope,不把 Dashboard 可開、API 200 或前台 lane 可見當作全主機納管恢復。 - `P0-02` owner-provided redacted evidence intake reviewer validation:開始把六條 lane 的脫敏 evidence refs 轉成 reviewer validation,但 request / received / accepted / runtime 仍先維持 0。 + +## 2026-06-27 — 20:31 GitHub backup missing targets source readiness production 讀回完成 + +**時間與來源**: +- 2026-06-27 19:24-20:31 Asia/Taipei。 +- 來源:feature branch `codex/github-backup-missing-targets-20260627`、Gitea main、Gitea Actions、production API readback。 + +**完成內容**: +- 新增 GitHub missing targets source readiness 分類讀回,將 5 個 GitHub not-found / inaccessible target 拆成 Gitea source candidate、internal remote source candidate、local worktree candidate、canonical source ambiguous、create private repo readiness 與 refs sync readiness。 +- `apps/api/src/services/github_target_private_backup_evidence_gate.py` 已把 `docs/security/github-target-missing-source-readiness.snapshot.json` 併入 `github_target_private_backup_evidence_gate_v1` summary。 +- GitHub backup governance 仍維持只讀;本段沒有建立 GitHub repo、沒有改 visibility、沒有 sync refs、沒有讀 secret / private clone URL。 + +**版本與 runs**: +- feature latest:`920bc9b80 Merge remote-tracking branch 'gitea/main' into codex/github-backup-missing-targets-20260627`。 +- main release line:`0e4e0fab3 fix(tests): refresh autonomous runtime deploy marker expectation`。 +- deploy marker:`460b11fdd chore(cd): deploy 0e4e0fa [skip ci]`。 +- code-review run:`3679`,Success。 +- CD run:`3678`,Success。 + +**本地驗證結果**: +- `python3 -m json.tool docs/security/github-target-missing-source-readiness.snapshot.json`:通過。 +- `python3 -m py_compile apps/api/src/services/github_target_private_backup_evidence_gate.py scripts/ops/host-runaway-process-exporter.py`:通過。 +- `git diff --check`:通過。 +- `DATABASE_URL=sqlite:///test.db python3.11 -m pytest apps/api/tests/test_github_target_private_backup_evidence_gate.py apps/api/tests/test_github_target_private_backup_evidence_gate_api.py apps/api/tests/test_delivery_closure_workbench_api.py scripts/ops/tests/test_host_runaway_process_exporter.py -q`:`15 passed`。 +- `pnpm --dir apps/web typecheck`:通過。 + +**production API readback**: +- `GET https://awoooi.wooo.work/api/v1/agents/github-target-private-backup-evidence-gate`:`200`。 +- `schema_version=github_target_private_backup_evidence_gate_v1`。 +- `approval_required_target_count=9`、`github_connector_readback_count=9`、`github_connector_private_visibility_count=4`、`github_connector_not_found_or_inaccessible_count=5`。 +- `private_backup_verified_count=4`、`private_visibility_verified_count=4`。 +- `github_missing_target_resolution_count=5`、`github_missing_target_gitea_source_candidate_count=3`、`github_missing_target_internal_remote_source_candidate_count=2`、`github_missing_target_local_worktree_candidate_count=5`、`github_missing_target_canonical_source_ambiguous_count=5`。 +- `github_missing_target_create_private_repo_ready_count=0`、`github_missing_target_refs_sync_ready_count=0`。 +- `blocked_target_count=9`、`execution_ready_count=0`、`target_count=10`。 +- operation boundaries:`read_only_api_allowed=true`、`github_api_write_allowed=false`、`repo_creation_allowed=false`、`visibility_change_allowed=false`、`refs_sync_allowed=false`、`workflow_trigger_allowed=false`、`private_clone_url_collection_allowed=false`。 + +**production delivery / health readback**: +- `GET https://awoooi.wooo.work/api/v1/health`:`200`,`status=healthy`、`environment=prod`、`mock_mode=false`。 +- `GET https://awoooi.wooo.work/api/v1/agents/delivery-closure-workbench`:`200`,`schema_version=delivery_closure_workbench_v1`。 +- Delivery Workbench GitHub lane:`status=blocked_private_visibility_and_safe_credential_evidence_required`、metric `private_backup_verified=4/9`、`blocker_count=9`。 + +**完成度與同步狀態**: +- 本段「GitHub missing targets source readiness API / production 讀回」:`85% -> 100%`。 +- GitHub backup mirror governance:仍為 blocked;本段提升 source-readiness 可解釋性,不代表 private backup gate 已開。 +- Product governance / delivery workbench:GitHub lane 維持 blocked,但 production 已可讀出 5 個 missing target source resolution 分類。 + +**仍維持 0 / false**: +- `github_missing_target_create_private_repo_ready_count=0`、`github_missing_target_refs_sync_ready_count=0`、`execution_ready_count=0`。 +- `github_api_write_allowed=false`、`repo_creation_allowed=false`、`visibility_change_allowed=false`、`refs_sync_allowed=false`、`workflow_trigger_allowed=false`、`private_clone_url_collection_allowed=false`、`secret_value_collection_allowed=false`。 + +**做過的命令類型**: +- 寫入:repo code / snapshot / test / LOGBOOK,以及正常 Gitea feature / main push。 +- 只讀:Gitea Actions UI readback、production API readback、production health readback、Delivery Workbench API readback。 +- 未做:沒有 GitHub repo creation、visibility change、refs sync、workflow trigger、private clone URL collection、secret value collection;沒有 host / Docker / systemd / Nginx / firewall / K8s / DB / Wazuh runtime 寫操作;沒有 force push。 + +**下一個 P0**: +- `P0-01` GitHub private backup evidence acceptance:補 `private_backup_verified_count` 從 `4/9` 往全數 verified 推進,但只接受 safe credential evidence / redacted refs,不收 private clone URL 或 secret value。 +- `P0-02` missing target canonical source owner decision:逐一釐清 `ewoooc`、`bitan-pharmacy`、`tsenyang-website`、`VibeWork`、`agent-bounty-protocol` 的 canonical source before repo creation。 +- `P0-03` refs sync readiness:在 canonical source 與 owner decision 成立前,`refs_sync_ready_count` 必須維持 `0`。 + +## 2026-06-27 — 20:35 IwoooS Wazuh owner export validator 正式收斂 + +**時間與來源**: +- 2026-06-27 19:59-20:35 Asia/Taipei。 +- 來源:Gitea Actions `3678` / `3679`、deploy marker `460b11fdd`、production API / `/zh-TW/iwooos` desktop / mobile smoke。 + +**完成內容**: +- `POST /api/v1/iwooos/wazuh-manager-registry-reviewer-validation/validate-owner-export` 已正式部署;只驗證 owner-provided redacted Wazuh manager registry export,不 persist payload、不查 live Wazuh API、不讀 host、不讀 secret、不重新註冊 agent、不 restart、不 active response、不開 runtime gate。 +- 前台移除殘留的未脫敏紀錄相關風險文案,避免把內部溝通語氣或工作內容當成產品頁內容。 +- CD 阻斷已收斂:`945f0ff58` 先修前台文案;`bdccd29d2` 修 host pressure gate baseline;`0e4e0fab3` 修 autonomous runtime deploy marker 測試預期;`460b11fdd` 為本輪正式 deploy marker。 + +**production API readback**: +- `GET /api/v1/iwooos/wazuh-manager-registry-reviewer-validation`:`200`,schema `iwooos_wazuh_manager_registry_reviewer_validation_readback_v1`。 +- API markers:`owner_export_validation_endpoint=/api/v1/iwooos/wazuh-manager-registry-reviewer-validation/validate-owner-export`、`owner_export_validation_mode=no_persist_validation_no_runtime_action`。 +- valid redacted sample POST:`accepted_for_readonly_posture_only`,response-local `owner_registry_export_received_count=1`、`owner_registry_export_accepted_count=1`、`reviewer_validation_passed_count=1`。 +- POST 後再次 GET:global counters 仍維持 `owner_registry_export_received_count=0`、`owner_registry_export_accepted_count=0`、`reviewer_validation_passed_count=0`、`manager_registry_accepted_count=0`、`post_enable_readback_passed_count=0`、`runtime_gate_count=0`。 + +**production browser smoke**: +- Desktop `1360x900`,URL `https://awoooi.wooo.work/zh-TW/iwooos?_v=460b11fdd-iwooos-final-desktop`。 + - HTTP `200`、endpoint 可見、no-persist mode 可見、runtime gate `0` 可見。 + - forbidden text hits:`0`;console errors:`0`;水平溢出:`0`,`scrollWidth/clientWidth=1360/1360`。 +- Mobile `384x900`,URL `https://awoooi.wooo.work/zh-TW/iwooos?_v=460b11fdd-iwooos-final-mobile`。 + - HTTP `200`、endpoint 可見、no-persist mode 可見、runtime gate `0` 可見。 + - forbidden text hits:`0`;console errors:`0`;水平溢出:`0`,`scrollWidth/clientWidth=384/384`。 + +**runs 與驗證**: +- CD run `3678`:tests success、build-and-deploy success、post-deploy-checks success;post-deploy smoke `5 passed`。 +- code-review run `3679`:success。 +- 本地驗證:`pnpm --filter @awoooi/web typecheck`、`python3 scripts/security/security-mirror-progress-guard.py --root .`、target forbidden scan、`git diff --check`、CI guard fixture 與 production API / browser smoke 均完成。 + +**完成度與同步狀態**: +- Wazuh owner export no-persist validator:`85% -> 100%`。 +- 前台敏感文案移除:code / deploy / production smoke `100%`。 +- IwoooS 整體:保守 `69% -> 70%`。此段完成 validator 與前台紅線,不代表 Wazuh 全主機已納管或 manager registry accepted 已完成。 + +**仍維持 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`。 +- `payload_persisted=false`、`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`、`manager_registry_accepted_updated=false`、`not_authorization=true`。 + +**做過的命令類型**: +- 寫入:repo API / test / frontend i18n / CI guard / LOGBOOK,以及正常 Gitea push。 +- 只讀:Gitea Actions logs、production API、production browser smoke。 +- 未做:沒有 host / Docker / systemd / Nginx / firewall / K8s / DB / Wazuh runtime 寫操作;沒有讀 secret 明文;沒有重新註冊 agent;沒有 Wazuh restart;沒有 Wazuh active response;沒有 Kali active scan;沒有 force push。 + +**下一個 P0**: +- 開新工作視窗處理 owner-provided redacted Wazuh manager registry export 收件與 reviewer validation passed;只有 evidence 完整、算術一致、6 alias scope parity、Dashboard API repair readback 與 owner / rollback owner 齊全時,才可推進 manager registry accepted,仍不得把 Dashboard 200 或前台可見當成全主機納管完成。 diff --git a/docs/security/wazuh-manager-registry-reviewer-validation.snapshot.json b/docs/security/wazuh-manager-registry-reviewer-validation.snapshot.json index fd6df4e5..edbb69b9 100644 --- a/docs/security/wazuh-manager-registry-reviewer-validation.snapshot.json +++ b/docs/security/wazuh-manager-registry-reviewer-validation.snapshot.json @@ -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 只可更新只讀 posture;active 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 } diff --git a/k8s/awoooi-prod/kustomization.yaml b/k8s/awoooi-prod/kustomization.yaml index 4c2a8ef5..d54c758b 100644 --- a/k8s/awoooi-prod/kustomization.yaml +++ b/k8s/awoooi-prod/kustomization.yaml @@ -41,7 +41,7 @@ resources: images: - name: 192.168.0.110:5000/library/api:IMAGE_TAG_PLACEHOLDER newName: 192.168.0.110:5000/awoooi/api - newTag: 551227f3bbaa7e19a49b94d0719ac9ad8a7aba11 + newTag: f47ee7d966da266db5980190758fd4aabece1a18 - name: 192.168.0.110:5000/library/web:IMAGE_TAG_PLACEHOLDER newName: 192.168.0.110:5000/awoooi/web - newTag: 551227f3bbaa7e19a49b94d0719ac9ad8a7aba11 + newTag: f47ee7d966da266db5980190758fd4aabece1a18 diff --git a/scripts/security/security-mirror-progress-guard.py b/scripts/security/security-mirror-progress-guard.py index 98ed55b5..766b52a9 100755 --- a/scripts/security/security-mirror-progress-guard.py +++ b/scripts/security/security-mirror-progress-guard.py @@ -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", ]: diff --git a/scripts/security/wazuh-manager-registry-reviewer-validation.py b/scripts/security/wazuh-manager-registry-reviewer-validation.py index 87fd137d..d934250b 100644 --- a/scripts/security/wazuh-manager-registry-reviewer-validation.py +++ b/scripts/security/wazuh-manager-registry-reviewer-validation.py @@ -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 只可更新只讀 posture;active 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():