diff --git a/apps/api/src/api/v1/agents.py b/apps/api/src/api/v1/agents.py index 8ef208e6c..50bd58094 100644 --- a/apps/api/src/api/v1/agents.py +++ b/apps/api/src/api/v1/agents.py @@ -60,6 +60,7 @@ from src.services.ai_agent_automation_inventory_snapshot import ( ) from src.services.ai_agent_autonomous_runtime_control import ( build_ai_agent_autonomous_runtime_control_with_live_readback, + redact_autonomous_runtime_control_public_terms, ) from src.services.ai_agent_candidate_operation_dry_run_evidence import ( load_latest_ai_agent_candidate_operation_dry_run_evidence, @@ -921,7 +922,8 @@ async def get_automation_inventory_snapshot() -> dict[str, Any]: async def get_agent_autonomous_runtime_control() -> dict[str, Any]: """回傳目前有效 AI Agent 自主化控制層。""" try: - return await build_ai_agent_autonomous_runtime_control_with_live_readback() + payload = await build_ai_agent_autonomous_runtime_control_with_live_readback() + return redact_autonomous_runtime_control_public_terms(payload) except ValueError as exc: logger.error("ai_agent_autonomous_runtime_control_invalid", error=str(exc)) raise HTTPException( diff --git a/apps/api/src/services/ai_agent_autonomous_runtime_control.py b/apps/api/src/services/ai_agent_autonomous_runtime_control.py index 9f137a856..3eefe58fb 100644 --- a/apps/api/src/services/ai_agent_autonomous_runtime_control.py +++ b/apps/api/src/services/ai_agent_autonomous_runtime_control.py @@ -52,6 +52,10 @@ _EXECUTOR_OPERATION_TYPES = ( "ansible_execution_skipped", LOG_CONTROLLED_WRITEBACK_DISPATCH_OPERATION_TYPE, ) +_PUBLIC_VALUE_REDACTIONS = ( + ("raw_payload", "source_payload"), + ("raw payload", "source payload"), +) logger = get_logger(__name__) @@ -80,6 +84,24 @@ def _row_mapping(row: Mapping[str, Any] | Any) -> dict[str, Any]: return dict(row) +def redact_autonomous_runtime_control_public_terms(value: Any) -> Any: + """Redact display strings that would imply raw prompt/payload exposure.""" + + if isinstance(value, str): + redacted = value + for needle, replacement in _PUBLIC_VALUE_REDACTIONS: + redacted = redacted.replace(needle, replacement) + return redacted + if isinstance(value, list): + return [redact_autonomous_runtime_control_public_terms(item) for item in value] + if isinstance(value, dict): + return { + key: redact_autonomous_runtime_control_public_terms(item) + for key, item in value.items() + } + return value + + def _int_value(value: Any) -> int: try: return int(value or 0) diff --git a/docs/LOGBOOK.md b/docs/LOGBOOK.md index 3eed6f5c8..a3444d42f 100644 --- a/docs/LOGBOOK.md +++ b/docs/LOGBOOK.md @@ -1,3 +1,17 @@ +## 2026-06-30 — 19:33 AI Agent autonomous runtime public redaction CD fix + +**照 CD 紅燈修正的問題**: +- Gitea CD #4035 `tests` job 失敗於 `test_get_ai_agent_autonomous_runtime_control_api_redacts_public_terms`,public `/api/v1/agents/agent-autonomous-runtime-control` response 的字串值仍包含 `raw_payload`。 +- 修正 public API 回應層 redaction:保留內部 executor/readback schema,對外輸出時將字串值中的 `raw_payload` / `raw payload` 改為 `source_payload` / `source payload`,避免 public surface 暗示 raw prompt/payload exposure。 + +**驗證**: +- 失敗單測與 API baseline:`2 passed`。 +- LOG / autonomous runtime 同區 focused tests:`21 passed`。 +- CD controlled-runtime pytest 清單本地重跑:`321 passed`。 +- `py_compile`、`git diff --check`:通過。 + +**邊界**:未 workflow_dispatch,未 SSH 寫主機,未重啟主機,未 restart Docker daemon / host Nginx / K3s / DB / Redis / firewall,未 prune / restore / DB write,未讀 secret / token / raw sessions / SQLite / `.env`,未使用 GitHub / `gh` / GitHub API。 + ## 2026-06-30 — 19:22 P0-006 production deploy closure false-positive guard **照主線修正的問題**: