Files
awoooi/docs/awooop/inventory/INV-4-hardcoded-namespace-ip.md
Your Name 8629ac709b
Some checks failed
run-migration / migrate (push) Failing after 59s
Code Review / ai-code-review (push) Successful in 1m8s
Type Sync Check / check-type-sync (push) Successful in 2m27s
feat(awooop): Phase 1-8 完整實作 — AwoooP Agent Platform 六平面架構
## Phase 1-3: Control Plane + Contract System
- awooop_phase1_control_plane_2026-05-04.sql: 12 張核心表 + RLS
- awooop_phase1_batch1_rls_2026-05-04.sql: 全部 FORCE RLS + GRANT
- packages/awooop-contracts/: 六合約 JSON Schema + golden fixtures
- src/models/awooop_contracts.py: Pydantic v2 contract models(extra=forbid)
- src/repositories/contract_repository.py: contract lifecycle(draft→published→active)
- src/services/contract_service.py: HMAC publish sig + Redis multi-sig activate
- src/services/schema_validator.py: LLM output validator(retry×3, E-SCHEMA-001)

## Phase 2: Tenant Isolation
- awooop_phase2_budget_ledger_2026-05-04.sql: budget_ledger + RLS
- src/services/budget_service.py: Token Budget Hard Kill 三層防線
- src/core/context.py: PROJECT_ID ContextVar(31 background loop 自動繼承)
- src/db/base.py + models.py: project_id 欄位 + RLS set_config 注入
- src/hermes/nl_gateway.py: project_id Redis key 前綴(Phase A 雙寫)
- src/services/anomaly_counter.py: per-project 改造(Phase A fallback)

## Phase 4: Platform Shell in Shadow Mode
- awooop_phase4_run_state_2026-05-04.sql: run_state + step_journal + idempotency
- src/services/run_state_machine.py: 8-state FSM + SKIP LOCKED + stale reaper
- src/services/platform_runtime.py: UUID v7 + W3C trace_id + shadow_execute
- src/services/audit_sink.py: PII/secret redaction 9 patterns
- src/api/v1/platform/runs.py: POST/GET /v1/platform/runs(Router→Service 架構)
- src/workers/platform_worker.py: SKIP LOCKED worker + heartbeat + reaper loop
- src/main.py: platform router + lifespan worker start/stop

## Phase 5: MCP Gateway 五閘門
- awooop_phase5_mcp_gateway_2026-05-04.sql: 4 表 + RLS
- src/plugins/mcp/gateway.py: McpGateway(Gate 1~5, E-MCP-GATE-001~009)
- src/plugins/mcp/redaction_middleware.py: 雙層 redaction + 16K 截斷
- src/plugins/mcp/registry.py: __provider name mangling(ADR-116)
- src/plugins/mcp/credential_resolver.py: k8s secret ref 解析
- tests/test_mcp_credential_isolation.py: 10 個迴歸測試(secret leak 防再現)

## Phase 6-8: EwoooC + Channel Hub + Approval Token
- awooop_phase6_ewoooc_onboarding_2026-05-04.sql: ewoooc tenant + 4 read-only MCP tools
- awooop_phase7_channel_hub_2026-05-04.sql: conversation_event + outbound_message
- src/services/provider_proxy.py: ProviderProxy + PlatformEnvelope(ADR-115)
- src/services/channel_hub.py: Telegram inbound mirror + Progressive Feedback(30s)
- src/services/awooop_approval_token.py: HS256 + jti NX replay 防護 + suggest mode

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-04 19:31:53 +08:00

109 lines
5.2 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# INV-4: Hardcoded Namespace & IP Inventory
**版本**v1.0 初稿
**日期**2026-05-03台北
**範圍**`apps/api/src/` 全 codebase + `k8s/`
**用途**Phase 2 多租戶改造 + EwoooC onboarding 前必須清理的硬碼
---
## 1. Hardcoded K8s Namespace
| 位置 | 行號 | 內容 | 影響 | 修補方式 |
|------|------|------|------|---------|
| `apps/api/src/plugins/mcp/providers/k8s_provider.py` | 40-41 | `ALLOWED_NAMESPACES = {"awoooi-prod"}` / `DEFAULT_NAMESPACE = "awoooi-prod"` | 🔴 P0-13EwoooC K8s tool 無法操作自己的 namespace | 改為 config-driven從 EffectivePolicy 或 project contract 讀 allowed namespaces |
| `apps/api/src/plugins/mcp/mcp_bridge.py` | 592, 602, 631, 647, 681 | `namespace = parameters.get("namespace", "awoooi-prod")` | 🔴 P0-135 處預設值都寫死 | 改為 `namespace = parameters.get("namespace", get_project_default_namespace(project_id))` |
| `apps/api/src/plugins/mcp/providers/signoz_provider.py` | 169 | `namespace = parameters.get("namespace", "awoooi-prod")` | 🟠 SignOz query 預設 namespace 錯誤 | 同上 |
| `apps/api/src/main.py` | 175 | `sentry_sdk.set_tag("host", "k8s-awoooi-prod")` | 🔵 Sentry tag 寫死EwoooC 看到錯誤 host tag | 改為 `settings.SENTRY_HOST_TAG` |
| `apps/api/src/core/prompts.py` | 120, 178, 192 | 系統 prompt 中出現 `awoooi-prod` | 🔵 LLM 可能在其他 tenant 錯誤建議 awoooi-prod namespace | 改為 `{tenant_namespace}` template variable |
---
## 2. Hardcoded IP Addresses
### 內網 IP已知用途
| IP | 用途 | 位置 | 改法 |
|----|------|------|------|
| `192.168.0.110` | Gitea / Prometheus / Loki / MinIO | `config.py:226,413,460,813` | 已在 config 以 default 存在OKK8s 覆蓋)|
| `192.168.0.111` | Ollama Local Fallback | `config.py` + `feedback_ollama_111_only.md`(已更新) | ADR-110 已改為第三層 fallbackconfig 需更新 |
| `192.168.0.112` | ArgoCD | `config.py:396` | OKconfig default|
| `192.168.0.120` | K3s API Server | `config.py:531` | OKconfig default|
| `192.168.0.121` | K3s ingress | `config.py:837` | 確認用途 |
| `192.168.0.188` | PostgreSQL / Redis / SigNoz / Grafana / ClickHouse | `config.py` 多處 | OKconfig defaultK8s 以 env 覆蓋)|
### 🔴 問題telemetry.py IP Assertion
| 位置 | 行號 | 內容 | 問題 |
|------|------|------|------|
| `apps/api/src/core/telemetry.py` | 71 | `if "192.168.0.188" not in endpoint: raise` | 🔴 P0-08EwoooC 啟動必失敗EwoooC SigNoz 可能是不同 endpoint|
| 修補方式 | | | 移除硬碼 assert改為 `if endpoint not in settings.ALLOWED_TELEMETRY_ENDPOINTS:` |
### GCP IP新增ADR-1102026-05-03 生效)
| IP | 用途 | 位置 |
|----|------|------|
| `34.143.170.20` | Ollama GCP-A PrimarySSD| `config.py`ADR-110 已加入 `_ALLOWED_PUBLIC_IPS`|
| `34.21.145.224` | Ollama GCP-B SecondarySSD| `config.py`ADR-110 已加入 `_ALLOWED_PUBLIC_IPS`|
**注意**
- K8s NetworkPolicy egress已新增 GCP-A/GCP-B /32 出口規則ADR-110
- INV-4 確認GCP IP 已在 `config.py._ALLOWED_PUBLIC_IPS` 白名單,非新增需求
- telemetry.py:71 assertGCP IP 不影響assert 是針對 OTEL endpoint非 Ollama endpoint
---
## 3. SSH Host Hardcodes
| 位置 | 內容 | 問題 | 修補 |
|------|------|------|------|
| `reference_four_hosts.md` | 110/120/121/188 四主機清單 | 文件不是程式碼OK | 無 |
| `apps/api/src/plugins/mcp/providers/ssh_provider.py`(若有)| SSH 目標主機 | 需 grep 確認是否硬碼 | 改為 config-driven 白名單 |
---
## 4. 其他硬碼字串
| 位置 | 內容 | 問題 | 修補 |
|------|------|------|------|
| `apps/api/src/core/config.py:625` | `default="192.168.0.188=ollama"` | Ollama-to-host mappingADR-110 後需更新 | 改為 `192.168.0.188=ollama_old`(僅 fallback 相關)|
| `apps/api/src/core/config.py:828` | `default="192.168.0.188,192.168.0.110,192.168.0.111"` | 主機清單 | 確認用途,若是 monitoring target 需加 GCP IP |
---
## 5. 改造策略Phase 2
### K8s Namespace優先
```python
# 方案project contract 中定義允許的 K8s namespaces
# awooop_projects.k8s_namespaces: ["awoooi-prod"]AWOOOI/ ["ewoooc-prod"]EwoooC
# k8s_provider.py 從 project contract 讀,而非硬碼
def get_allowed_namespaces(project_id: str) -> set[str]:
contract = get_active_project_contract(project_id)
return set(contract.allowed_k8s_namespaces)
```
### Telemetry Endpoint AssertP0-08PR-01 優先)
```python
# 修改前telemetry.py:71
if "192.168.0.188" not in endpoint:
raise ValueError(f"Forbidden OTEL endpoint: {endpoint}")
# 修改後
allowed_endpoints = settings.ALLOWED_TELEMETRY_ENDPOINTS.split(",")
if not any(allowed in endpoint for allowed in allowed_endpoints):
raise ValueError(f"Forbidden OTEL endpoint: {endpoint}")
```
---
## 6. 驗收標準
- [ ] `grep -r "192.168.0.188" apps/api/src/``telemetry.py` 的 assert 行消失
- [ ] `grep -r '"awoooi-prod"' apps/api/src/` 中的程式碼路徑(非 prompt 文字、非 comment結果為 0
- [ ] k8s_provider.py `ALLOWED_NAMESPACES` 改為 config-driven
- [ ] INV-4 中標記 GCP IP 已確認加入 NetworkPolicyADR-110 完成)
*最後更新2026-05-03台北*