{ "schema_version": "runtime_surface_inventory_v1", "generated_at": "2026-06-05T09:47:25+08:00", "program_status": { "overall_completion_percent": 100, "current_priority": "P1", "current_task_id": "P1-001", "next_task_id": "P1-002", "read_only_mode": true }, "source_refs": [ "docs/schemas/runtime_surface_inventory_v1.schema.json", "k8s/awoooi-prod/kustomization.yaml", "k8s/awoooi-prod/05-deployment-web.yaml", "k8s/awoooi-prod/06-deployment-api.yaml", "k8s/awoooi-prod/08-deployment-worker.yaml", "k8s/awoooi-prod/10-deployment-auto-repair-canary.yaml", "k8s/awoooi-prod/13-cronjob-k3s-report.yaml", "k8s/awoooi-prod/14-cronjob-weekly-report.yaml", "k8s/awoooi-prod/15-cronjob-km-vectorize.yaml", "k8s/awoooi-prod/12-cronjob-drift-scanner.yaml", "k8s/awoooi-prod/03-secrets.example.yaml", "k8s/awoooi-prod/04-repair-ssh-key-template.yaml", "k8s/awoooi-prod/04-repair-known-hosts-template.yaml", "k8s/awoooi-prod/04-ssh-mcp-secret.example.yaml", "k8s/awoooi-prod/07-rbac.yaml", "k8s/awoooi-prod/09-pdb.yaml", "k8s/awoooi-prod/11-vpa.yaml", "k8s/awoooi-prod/12-hpa.yaml", "k8s/awoooi-prod/02-network-policy.yaml", ".gitea/workflows/cd.yaml" ], "rollups": { "total_surfaces": 22, "by_kind": { "deployment": 4, "service": 2, "ingress": 1, "cronjob": 4, "configmap": 2, "secret": 4, "rbac": 1, "policy": 2, "autoscaler": 1, "availability": 1 }, "by_status": { "manifest_mapped": 16, "action_required": 6 }, "by_evidence_level": { "committed_manifest": 17, "live_check_required": 4, "missing_manifest": 1 }, "action_required_surface_ids": [ "external_nginx_gateway_route", "awoooi_secrets", "awoooi_repair_ssh_key_secret", "awoooi_repair_known_hosts_secret", "ssh_mcp_key_secret", "hpa_vpa_autoscaler_contract" ], "secret_surface_ids": [ "awoooi_secrets", "awoooi_repair_ssh_key_secret", "awoooi_repair_known_hosts_secret", "ssh_mcp_key_secret" ], "live_check_missing_surface_ids": [ "external_nginx_gateway_route", "awoooi_secrets", "awoooi_repair_ssh_key_secret", "awoooi_repair_known_hosts_secret", "ssh_mcp_key_secret", "hpa_vpa_autoscaler_contract" ], "total_source_components": 9, "source_components_with_runtime_binding": 9 }, "runtime_surfaces": [ { "surface_id": "awoooi_api_deployment", "display_name": "AWOOOI API Deployment", "kind": "deployment", "manifest_ref": "k8s/awoooi-prod/06-deployment-api.yaml", "status": "manifest_mapped", "risk_level": "high", "evidence_level": "committed_manifest", "runtime_binding": "Deployment/awoooi-api replicas=2 image=192.168.0.110:5000/library/api:IMAGE_TAG_PLACEHOLDER via kustomization images", "health_contract": "liveness /api/v1/health/live;readiness /api/v1/health/ready;public health 由 CD 使用 https://awoooi.wooo.work/api/v1/health 驗證", "secret_exposure": "none", "live_check_status": "not_run", "evidence_refs": [ "k8s/awoooi-prod/06-deployment-api.yaml", "k8s/awoooi-prod/kustomization.yaml", ".gitea/workflows/cd.yaml" ], "next_action": "P1-002 盤點 runner / rollout evidence 時,只能讀取 rollout status 與健康證據,不得 restart、scale 或 patch。" }, { "surface_id": "awoooi_web_deployment", "display_name": "AWOOOI Web Deployment", "kind": "deployment", "manifest_ref": "k8s/awoooi-prod/05-deployment-web.yaml", "status": "manifest_mapped", "risk_level": "medium", "evidence_level": "committed_manifest", "runtime_binding": "Deployment/awoooi-web replicas=2 image=192.168.0.110:5000/library/web:IMAGE_TAG_PLACEHOLDER via kustomization images", "health_contract": "liveness /api/health;readiness /api/health;NEXT_PUBLIC_API_URL 必須為 https://awoooi.wooo.work", "secret_exposure": "none", "live_check_status": "not_run", "evidence_refs": [ "k8s/awoooi-prod/05-deployment-web.yaml", "apps/web/src/app/api/health/route.ts", "docs/HARD_RULES.md" ], "next_action": "前端 runtime 只允許讀取健康與 UI 證據;不得把 NodePort / internal IP 寫回 NEXT_PUBLIC bundle。" }, { "surface_id": "awoooi_worker_deployment", "display_name": "AWOOOI Signal Worker Deployment", "kind": "deployment", "manifest_ref": "k8s/awoooi-prod/08-deployment-worker.yaml", "status": "manifest_mapped", "risk_level": "high", "evidence_level": "committed_manifest", "runtime_binding": "Deployment/awoooi-worker replicas=1 command=python -m src.workers.signal_worker", "health_contract": "liveness 檢查 /tmp/worker-healthy mtime;readiness /tmp/worker-ready;Redis Streams consumer group awoooi-workers", "secret_exposure": "none", "live_check_status": "not_run", "evidence_refs": [ "k8s/awoooi-prod/08-deployment-worker.yaml", "apps/api/src/workers/signal_worker.py", "apps/api/tests/test_runtime_bootstrap_guards.py" ], "next_action": "P1-002 / P1-003 只讀盤點 worker heartbeat 與 queue health,不得手動刪 Pod 或 rollout restart。" }, { "surface_id": "auto_repair_canary_deployment", "display_name": "Auto Repair Canary Deployment", "kind": "deployment", "manifest_ref": "k8s/awoooi-prod/10-deployment-auto-repair-canary.yaml", "status": "manifest_mapped", "risk_level": "medium", "evidence_level": "committed_manifest", "runtime_binding": "Deployment/awoooi-auto-repair-canary replicas=1;不承接流量、不掛 Secret、不暴露 Service", "health_contract": "sleep loop 作為 live-fire target;只有批准後的低風險驗證可使用,不屬於本任務執行範圍", "secret_exposure": "none", "live_check_status": "not_run", "evidence_refs": [ "k8s/awoooi-prod/10-deployment-auto-repair-canary.yaml" ], "next_action": "維持只讀標記;任何 canary 操作仍需明確批准。" }, { "surface_id": "awoooi_api_service", "display_name": "AWOOOI API Service", "kind": "service", "manifest_ref": "k8s/awoooi-prod/06-deployment-api.yaml", "status": "manifest_mapped", "risk_level": "high", "evidence_level": "committed_manifest", "runtime_binding": "Service/awoooi-api-svc NodePort 32334 targetPort 8000 selector app=awoooi-api", "health_contract": "內部 CronJob 使用 http://awoooi-api-svc.awoooi-prod.svc.cluster.local:8000;外部 health 走正式域名", "secret_exposure": "none", "live_check_status": "not_run", "evidence_refs": [ "k8s/awoooi-prod/06-deployment-api.yaml", "k8s/awoooi-prod/15-cronjob-km-vectorize.yaml", "k8s/awoooi-prod/12-cronjob-drift-scanner.yaml" ], "next_action": "只讀比對 Service selector / endpoint / public health,不得 patch Service 或改 NodePort。" }, { "surface_id": "awoooi_web_service", "display_name": "AWOOOI Web Service", "kind": "service", "manifest_ref": "k8s/awoooi-prod/05-deployment-web.yaml", "status": "manifest_mapped", "risk_level": "medium", "evidence_level": "committed_manifest", "runtime_binding": "Service/awoooi-web-svc NodePort 32335 targetPort 3000 selector app=awoooi-web", "health_contract": "public route /zh-TW/governance?tab=automation-inventory;web container health /api/health", "secret_exposure": "none", "live_check_status": "not_run", "evidence_refs": [ "k8s/awoooi-prod/05-deployment-web.yaml", "apps/web/src/app/api/health/route.ts", ".gitea/workflows/cd.yaml" ], "next_action": "只讀確認 public route 與 UI smoke;不得修改 Service 或 public routing。" }, { "surface_id": "external_nginx_gateway_route", "display_name": "External Nginx / Domain Route", "kind": "ingress", "manifest_ref": "缺 Kubernetes Ingress manifest;由外部 gateway / public domain 與 NodePort health 證據承接", "status": "action_required", "risk_level": "high", "evidence_level": "missing_manifest", "runtime_binding": "https://awoooi.wooo.work -> external gateway -> NodePort 32334/32335;K8s repo 目前沒有 Ingress resource", "health_contract": "CD 使用 public API health 與 production Playwright smoke;Ingress / gateway 設定仍需只讀外部路由盤點", "secret_exposure": "none", "live_check_status": "required", "evidence_refs": [ ".gitea/workflows/cd.yaml", "docs/HARD_RULES.md", "k8s/awoooi-prod/05-deployment-web.yaml", "k8s/awoooi-prod/06-deployment-api.yaml" ], "next_action": "P1-002 只讀補 gateway / runner / DNS evidence;不得直接新增 Ingress 或改 Nginx。" }, { "surface_id": "k3s_status_report_cronjob", "display_name": "K3s Status Report CronJob", "kind": "cronjob", "manifest_ref": "k8s/awoooi-prod/13-cronjob-k3s-report.yaml", "status": "manifest_mapped", "risk_level": "medium", "evidence_level": "committed_manifest", "runtime_binding": "CronJob/k3s-status-report schedule=0 1 * * * timeZone=Asia/Taipei command=python -m src.services.k3s_monitor_service", "health_contract": "Telegram daily K3s status;成功不得即時洗版,失敗才需 action-required", "secret_exposure": "none", "live_check_status": "not_run", "evidence_refs": [ "k8s/awoooi-prod/13-cronjob-k3s-report.yaml", "apps/api/src/services/k3s_monitor_service.py" ], "next_action": "P1-002 讀取 CronJob last schedule / failure evidence;不得 create job 手動觸發。" }, { "surface_id": "weekly_report_cronjob", "display_name": "Weekly Report CronJob", "kind": "cronjob", "manifest_ref": "k8s/awoooi-prod/14-cronjob-weekly-report.yaml", "status": "manifest_mapped", "risk_level": "medium", "evidence_level": "committed_manifest", "runtime_binding": "CronJob/weekly-report schedule=0 10 * * 5 timeZone=Asia/Taipei command=python -m src.services.weekly_report_service", "health_contract": "每週報告;Telegram success noise suppression 必須保留", "secret_exposure": "none", "live_check_status": "not_run", "evidence_refs": [ "k8s/awoooi-prod/14-cronjob-weekly-report.yaml", "apps/api/src/services/weekly_report_service.py" ], "next_action": "只讀補 last run / failure-only notification evidence。" }, { "surface_id": "km_vectorize_cronjob", "display_name": "KM Vectorize CronJob", "kind": "cronjob", "manifest_ref": "k8s/awoooi-prod/15-cronjob-km-vectorize.yaml", "status": "manifest_mapped", "risk_level": "medium", "evidence_level": "committed_manifest", "runtime_binding": "CronJob/km-vectorize schedule=0 19 * * * timeZone=Asia/Taipei command=python /app/scripts/cron_km_vectorize.py", "health_contract": "呼叫 in-cluster API Service;failedJobsHistoryLimit=0,失敗證據應進 AwoooP/KM governance", "secret_exposure": "none", "live_check_status": "not_run", "evidence_refs": [ "k8s/awoooi-prod/15-cronjob-km-vectorize.yaml", "scripts/cron_km_vectorize.py" ], "next_action": "只讀確認 last schedule 與 failed row evidence,不得手動 vectorize 或重跑 job。" }, { "surface_id": "drift_scanner_cronjob", "display_name": "Config Drift Scanner CronJob", "kind": "cronjob", "manifest_ref": "k8s/awoooi-prod/12-cronjob-drift-scanner.yaml", "status": "manifest_mapped", "risk_level": "high", "evidence_level": "committed_manifest", "runtime_binding": "CronJob/drift-scanner schedule=0 * * * * command posts /api/v1/drift/internal/scan", "health_contract": "只掃描 awoooi-prod;不得把 drift scan 當 active remediation 或自動 patch", "secret_exposure": "none", "live_check_status": "not_run", "evidence_refs": [ "k8s/awoooi-prod/12-cronjob-drift-scanner.yaml", "apps/api/src/api/v1/drift.py" ], "next_action": "P1-003 盤點 drift scanner last run / alert mapping;不得修改 alert rule 或 workflow。" }, { "surface_id": "awoooi_config_configmap", "display_name": "AWOOOI ConfigMap", "kind": "configmap", "manifest_ref": "k8s/awoooi-prod/04-configmap.yaml", "status": "manifest_mapped", "risk_level": "high", "evidence_level": "committed_manifest", "runtime_binding": "ConfigMap/awoooi-config mounted via envFrom in API / Web / Worker / CronJob", "health_contract": "承載非機密 endpoint / feature flags;任何 provider order 或 internal IP 曝露需獨立審查", "secret_exposure": "none", "live_check_status": "not_run", "evidence_refs": [ "k8s/awoooi-prod/04-configmap.yaml", "k8s/awoooi-prod/06-deployment-api.yaml", "k8s/awoooi-prod/05-deployment-web.yaml" ], "next_action": "P1-004 / P2 配置優化只能產 proposal;不得在本任務改 ConfigMap。" }, { "surface_id": "service_registry_configmap", "display_name": "Service Registry ConfigMap", "kind": "configmap", "manifest_ref": "k8s/awoooi-prod/15-service-registry-configmap.yaml", "status": "manifest_mapped", "risk_level": "high", "evidence_level": "committed_manifest", "runtime_binding": "ConfigMap/service-registry mounted at /app/ops/config/service-registry.yaml in API pod;CD 直接 apply", "health_contract": "stateful_level BLOCK / CRITICAL_HITL / STANDARD_HITL / AUTO 是自動修復爆炸半徑守門依據", "secret_exposure": "none", "live_check_status": "not_run", "evidence_refs": [ "k8s/awoooi-prod/15-service-registry-configmap.yaml", ".gitea/workflows/cd.yaml" ], "next_action": "只讀顯示服務分級;不得自動接受或修改 service stateful level。" }, { "surface_id": "awoooi_secrets", "display_name": "AWOOOI Secrets", "kind": "secret", "manifest_ref": "k8s/awoooi-prod/03-secrets.example.yaml + .gitea/workflows/cd.yaml Secret injection", "status": "action_required", "risk_level": "critical", "evidence_level": "live_check_required", "runtime_binding": "Secret/awoooi-secrets referenced by API / Web / Worker / CronJob envFrom;payload 永遠不得進 snapshot", "health_contract": "只允許 metadata / key existence / redacted policy;禁止讀取 secret 明文、base64 decode 或 log echo", "secret_exposure": "template_only", "live_check_status": "required", "evidence_refs": [ "k8s/awoooi-prod/03-secrets.example.yaml", ".gitea/workflows/cd.yaml", "docs/HARD_RULES.md" ], "next_action": "P1-002 只能補 Secret metadata existence / age evidence;不得讀 payload。" }, { "surface_id": "awoooi_repair_ssh_key_secret", "display_name": "Repair SSH Key Secret", "kind": "secret", "manifest_ref": "k8s/awoooi-prod/04-repair-ssh-key-template.yaml", "status": "action_required", "risk_level": "critical", "evidence_level": "live_check_required", "runtime_binding": "Secret/awoooi-repair-ssh-key mounted read-only into API pod /etc/repair-ssh", "health_contract": "command= forced repair bot;只允許 template / metadata visibility;不得讀私鑰內容", "secret_exposure": "template_only", "live_check_status": "required", "evidence_refs": [ "k8s/awoooi-prod/04-repair-ssh-key-template.yaml", "k8s/awoooi-prod/06-deployment-api.yaml" ], "next_action": "只讀確認 Secret 是否存在與 mount 是否健康;不得 ssh-keyscan、patch 或讀 key。" }, { "surface_id": "awoooi_repair_known_hosts_secret", "display_name": "Repair known_hosts Secret", "kind": "secret", "manifest_ref": "k8s/awoooi-prod/04-repair-known-hosts-template.yaml + .gitea/workflows/cd.yaml", "status": "action_required", "risk_level": "high", "evidence_level": "live_check_required", "runtime_binding": "Secret/awoooi-repair-known-hosts mounted read-only into API pod /etc/repair-known-hosts", "health_contract": "CD 需四台主機指紋完整才 patch;本任務不執行 ssh-keyscan、不更新 Secret", "secret_exposure": "template_only", "live_check_status": "required", "evidence_refs": [ "k8s/awoooi-prod/04-repair-known-hosts-template.yaml", ".gitea/workflows/cd.yaml" ], "next_action": "P1-002 只讀讀取 Secret metadata 與 CD evidence;不得重掃或 patch known_hosts。" }, { "surface_id": "ssh_mcp_key_secret", "display_name": "SSH MCP Key Secret", "kind": "secret", "manifest_ref": "k8s/awoooi-prod/04-ssh-mcp-secret.example.yaml", "status": "action_required", "risk_level": "critical", "evidence_level": "live_check_required", "runtime_binding": "Secret/ssh-mcp-key mounted read-only into API pod /run/secrets/ssh_mcp_key 與 /etc/ssh-mcp/known_hosts", "health_contract": "MCP SSH 診斷需 redaction / audit;本任務不得讀 key、不得建立 SSH session、不得修復主機", "secret_exposure": "template_only", "live_check_status": "required", "evidence_refs": [ "k8s/awoooi-prod/04-ssh-mcp-secret.example.yaml", "k8s/awoooi-prod/06-deployment-api.yaml" ], "next_action": "只讀確認 metadata 與 mount path;任何 MCP SSH 執行仍需批准與 audit。" }, { "surface_id": "executor_rbac", "display_name": "Executor RBAC", "kind": "rbac", "manifest_ref": "k8s/awoooi-prod/07-rbac.yaml", "status": "manifest_mapped", "risk_level": "critical", "evidence_level": "committed_manifest", "runtime_binding": "ServiceAccount/awoooi-executor + ClusterRole/awoooi-executor-role + ClusterRoleBinding", "health_contract": "允許讀取多類 K8s 資源;寫入權限限 pods delete、deployments patch、scale 等高風險操作,必須由 approval gate 阻擋", "secret_exposure": "none", "live_check_status": "not_run", "evidence_refs": [ "k8s/awoooi-prod/07-rbac.yaml", "apps/api/src/services/executor.py" ], "next_action": "P2 安全執行關卡前只做只讀 RBAC diff;不得修改 ClusterRole。" }, { "surface_id": "namespace_quota_limits", "display_name": "Namespace Quota / LimitRange", "kind": "policy", "manifest_ref": "k8s/awoooi-prod/01-namespace-quota.yaml", "status": "manifest_mapped", "risk_level": "medium", "evidence_level": "committed_manifest", "runtime_binding": "Namespace/awoooi-prod + ResourceQuota/awoooi-prod-quota + LimitRange/awoooi-prod-limits", "health_contract": "保護 namespace resource blast radius;任何 limit 調整屬 P2 proposal,不在本任務執行", "secret_exposure": "none", "live_check_status": "not_run", "evidence_refs": [ "k8s/awoooi-prod/01-namespace-quota.yaml" ], "next_action": "只讀對齊 quota usage / HPA 建議;不得 patch quota。" }, { "surface_id": "network_policy_contract", "display_name": "NetworkPolicy Contract", "kind": "policy", "manifest_ref": "k8s/awoooi-prod/02-network-policy.yaml", "status": "manifest_mapped", "risk_level": "critical", "evidence_level": "committed_manifest", "runtime_binding": "NetworkPolicy/default-deny-all + allow-nginx-ingress + allow-required-egress;kustomization 註記由 CD 單獨 apply", "health_contract": "預設拒絕;允許 Nginx gateway、K3s NodePort、Ollama proxy、monitoring、K8s API 與必要服務 egress", "secret_exposure": "none", "live_check_status": "not_run", "evidence_refs": [ "k8s/awoooi-prod/02-network-policy.yaml", "k8s/awoooi-prod/kustomization.yaml", "docs/HARD_RULES.md" ], "next_action": "P1-003 / P2 只讀盤點 egress / alert chain evidence;不得 patch NetworkPolicy。" }, { "surface_id": "hpa_vpa_autoscaler_contract", "display_name": "HPA / VPA Autoscaler Contract", "kind": "autoscaler", "manifest_ref": "k8s/awoooi-prod/12-hpa.yaml + k8s/awoooi-prod/11-vpa.yaml", "status": "action_required", "risk_level": "high", "evidence_level": "committed_manifest", "runtime_binding": "HPA api/web/worker 與 VPA api/web/worker manifests 存在,但 kustomization resources 未列入;需只讀確認實際 apply 路徑與 runtime 狀態", "health_contract": "HPA/VPA 只能提供建議或已批准擴縮容;不得自動提升 runtime gate", "secret_exposure": "none", "live_check_status": "required", "evidence_refs": [ "k8s/awoooi-prod/12-hpa.yaml", "k8s/awoooi-prod/11-vpa.yaml", "k8s/awoooi-prod/kustomization.yaml" ], "next_action": "P2 配置優化前只讀確認 HPA/VPA 是否實際存在;不得 apply 或 patch autoscaler。" }, { "surface_id": "pod_disruption_budget", "display_name": "PodDisruptionBudget", "kind": "availability", "manifest_ref": "k8s/awoooi-prod/09-pdb.yaml", "status": "manifest_mapped", "risk_level": "medium", "evidence_level": "committed_manifest", "runtime_binding": "PDB/api minAvailable=1;PDB/web minAvailable=1;PDB/worker maxUnavailable=1", "health_contract": "節點維護與 rollout availability guard;不得在本任務變更 maxUnavailable / minAvailable", "secret_exposure": "none", "live_check_status": "not_run", "evidence_refs": [ "k8s/awoooi-prod/09-pdb.yaml", "k8s/awoooi-prod/kustomization.yaml" ], "next_action": "只讀確認 PDB health 與 rollout evidence;不得修改可用性策略。" } ], "source_runtime_components": [ { "component_id": "api_fastapi_app", "display_name": "FastAPI app", "source_ref": "apps/api/src/main.py", "component_kind": "api_process", "runtime_binding": "Deployment/awoooi-api container api", "status": "bound", "next_action": "只讀 health / route inventory。" }, { "component_id": "api_health_routes", "display_name": "API health routes", "source_ref": "apps/api/src/routes/health.py", "component_kind": "health_endpoint", "runtime_binding": "Deployment/awoooi-api probes /api/v1/health/live and /api/v1/health/ready", "status": "bound", "next_action": "只讀確認 probe 與 public health 契約。" }, { "component_id": "web_next_app", "display_name": "Next.js app", "source_ref": "apps/web/src/app/", "component_kind": "web_process", "runtime_binding": "Deployment/awoooi-web container web", "status": "bound", "next_action": "只讀 UI smoke;不得改 public API route。" }, { "component_id": "web_health_route", "display_name": "Web health route", "source_ref": "apps/web/src/app/api/health/route.ts", "component_kind": "health_endpoint", "runtime_binding": "Deployment/awoooi-web probes /api/health", "status": "bound", "next_action": "只讀確認 web health。" }, { "component_id": "signal_worker", "display_name": "Signal Worker", "source_ref": "apps/api/src/workers/signal_worker.py", "component_kind": "worker_process", "runtime_binding": "Deployment/awoooi-worker command python -m src.workers.signal_worker", "status": "bound", "next_action": "只讀 queue / heartbeat evidence。" }, { "component_id": "k3s_monitor_service", "display_name": "K3s monitor service", "source_ref": "apps/api/src/services/k3s_monitor_service.py", "component_kind": "scheduled_report", "runtime_binding": "CronJob/k3s-status-report", "status": "bound", "next_action": "只讀 last schedule / failure evidence。" }, { "component_id": "weekly_report_service", "display_name": "Weekly report service", "source_ref": "apps/api/src/services/weekly_report_service.py", "component_kind": "scheduled_report", "runtime_binding": "CronJob/weekly-report", "status": "bound", "next_action": "保留 success-noise suppression。" }, { "component_id": "km_vectorize_script", "display_name": "KM vectorize script", "source_ref": "scripts/cron_km_vectorize.py", "component_kind": "scheduled_job", "runtime_binding": "CronJob/km-vectorize", "status": "bound", "next_action": "只讀確認 vectorize report;不得手動重跑。" }, { "component_id": "drift_internal_scan", "display_name": "Drift internal scan endpoint", "source_ref": "apps/api/src/api/v1/drift.py", "component_kind": "internal_endpoint", "runtime_binding": "CronJob/drift-scanner POST /api/v1/drift/internal/scan", "status": "bound", "next_action": "只讀盤點 drift evidence;不得自動 remediation。" } ], "evidence_gaps": [ { "gap_id": "external_gateway_manifest_gap", "severity": "high", "status": "action_required", "summary": "正式域名健康證據存在,但 repo 內沒有 Kubernetes Ingress manifest;外部 Nginx / gateway 路由仍需只讀盤點。", "evidence_refs": [ ".gitea/workflows/cd.yaml", "k8s/awoooi-prod/05-deployment-web.yaml", "k8s/awoooi-prod/06-deployment-api.yaml" ], "next_action": "P1-002 盤點 gateway / runner / DNS evidence,不直接改 Nginx 或 Ingress。" }, { "gap_id": "secret_metadata_live_check_gap", "severity": "critical", "status": "action_required", "summary": "四個 Secret surface 只能以 template / metadata 顯示;仍缺只讀 metadata existence / age evidence,禁止讀 payload。", "evidence_refs": [ "k8s/awoooi-prod/03-secrets.example.yaml", "k8s/awoooi-prod/04-repair-ssh-key-template.yaml", "k8s/awoooi-prod/04-repair-known-hosts-template.yaml", "k8s/awoooi-prod/04-ssh-mcp-secret.example.yaml" ], "next_action": "P1-002 只讀補 Secret metadata,不 base64 decode、不輸出明文。" }, { "gap_id": "autoscaler_apply_path_gap", "severity": "medium", "status": "action_required", "summary": "HPA / VPA manifest 存在,但未列入 kustomization resources;需只讀確認實際 apply path 與 runtime 狀態。", "evidence_refs": [ "k8s/awoooi-prod/12-hpa.yaml", "k8s/awoooi-prod/11-vpa.yaml", "k8s/awoooi-prod/kustomization.yaml" ], "next_action": "P2 配置優化前只讀確認,不在本任務 apply 或 patch。" } ], "operator_contract": { "display_mode": "read_only_runtime_surface", "must_not_interpret_as": [ "runtime 執行批准", "rollout / restart / scale 批准", "Secret payload 可讀批准", "生產路由變更批准", "HPA / VPA apply 批准", "active scan 或 auto remediation 批准", "runtime 執行授權", "rollout / restart / scale / delete 批准", "Secret 已驗證或可讀取", "Ingress / DNS 可修改" ], "secret_display_policy": "只顯示 template、metadata、引用路徑與 redacted policy;禁止 Secret 明文、base64 decode、token、key、password 或私鑰內容進入 snapshot/API/UI/log。" }, "operation_boundaries": { "read_only_api_allowed": true, "live_k8s_query_allowed": false, "kubectl_allowed": false, "rollout_allowed": false, "restart_allowed": false, "scale_allowed": false, "delete_allowed": false, "secret_read_allowed": false, "secret_plaintext_allowed": false, "active_scan_allowed": false, "production_route_change_allowed": false }, "approval_boundaries": { "runtime_execution_authorized": false, "action_buttons_allowed": false, "secret_value_collection_allowed": false, "host_change_authorized": false, "workflow_modification_authorized": false, "production_routing_authorized": false, "destructive_operation_allowed": false } }