Files
awoooi/docs/awooop/inventory/INV-9-global-singleton-catalog.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

236 lines
8.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-9: Global Singleton Catalog
**版本**v1.0 初稿
**日期**2026-05-03台北
**來源**`apps/api/src/` grep `_instance = None` / `get_*()` factory functions
**用途**ADR-124 Global Singleton Decomposition 的執行基礎
---
## 概覽
| 統計 | 數量 |
|------|------|
| 確認全域單例 | 13 |
| 需要分解per-project| 9 |
| 可保持 platform-level | 4 |
---
## 完整清單
### 1. TrustEngine
| 屬性 | 值 |
|------|----|
| 位置 | `apps/api/src/core/trust_engine.py:189` |
| Factory | `get_trust_engine()` at line 393 |
| 單例模式 | module-level `_trust_engine` variable |
| 目前狀態 | 全域,所有 tenant 共用 |
| 影響 | trust_records無 project_idtrust score 跨 tenant 混算 |
| 分解策略 | per-project trust engine instance從 project contract 讀 trust_policy |
| Phase | Phase 2repository 加 project_id filter 後)|
| 風險 | 高TrustEngine 是飛輪核心,分解需仔細 regression test|
---
### 2. ProviderRegistryMCP
| 屬性 | 值 |
|------|----|
| 位置 | `apps/api/src/plugins/mcp/registry.py:74` |
| Factory | module-level `get_registry()` at line 80 / `_registry` at line 209 |
| 目前狀態 | 全域,所有 tenant 共用 MCP provider 清單 |
| 影響 | Phase 5 MCP Gateway不同 tenant 應有不同可用 tool 清單 |
| 分解策略 | platform-level registrytool 清單)+ per-project grants誰可用什麼Registry 本身可保持 platform-level |
| Phase | Phase 5MCP Gateway 建立時)|
| 風險 | 中Registry 改為 read-only platform resourcegrants 移到 DB|
---
### 3. AnomalyCounter
| 屬性 | 值 |
|------|----|
| 位置 | `apps/api/src/services/anomaly_counter.py:85` |
| Factory | `_anomaly_counter = AnomalyCounter(get_redis())` at line 800 |
| 目前狀態 | 全域6 個 Redis prefix 無 tenant 隔離 |
| 影響 | P1-17多 tenant 計數混算 |
| 分解策略 | per-project 工廠:`get_anomaly_counter(project_id)` 注入 `project_prefix` |
| Phase | Phase 2PR-11|
| 風險 | 中6 個 prefix 全部要改)|
---
### 4. AIRouter
| 屬性 | 值 |
|------|----|
| 位置 | `apps/api/src/services/ai_router.py:194` |
| Factory | `_router = AIRouter()` at line 1324 |
| 依賴 | AIProviderRegistry923、AIRouterExecutor975|
| 目前狀態 | 全域,所有 tenant 共用 provider routing 決策 |
| 影響 | EwoooC 可能使用 AWOOOI 的 model routing policy |
| 分解策略 | AIRouter 接受 EffectivePolicy 參數per-project policy 已在 Phase 4 設計Router 邏輯保持 platform-levelpolicy 來源改為 per-project |
| Phase | Phase 4EffectivePolicy 設計完成後)|
| 風險 | 中ADR-052 AIRouter 已有 protocol 設計,改 policy 注入點)|
---
### 5. IntentClassifier
| 屬性 | 值 |
|------|----|
| 位置 | `apps/api/src/services/intent_classifier.py:357` |
| Factory | `_classifier = IntentClassifier()` at line 744 |
| 目前狀態 | 全域 |
| 影響 | 不同 tenant 可能需要不同 intent classification domain |
| 分解策略 | 短期保持 platform-levelintent schema 共用);長期 per-project intent domain config |
| Phase | Phase 6EwoooC 需要不同 intent domain 時才分解)|
| 風險 | 低intent classification 不帶 tenant 資料)|
---
### 6. TelegramGateway
| 屬性 | 值 |
|------|----|
| 位置 | `apps/api/src/services/telegram_gateway.py:1324` |
| Factory | `_gateway = TelegramGateway()` at line 6375 |
| 目前狀態 | 全域,持有 polling leader lock |
| 影響 | `telegram:polling:leader` 是 platform_resource但 gateway 本身可以 per-project |
| 分解策略 | polling leader 保持 platform_resourcegateway 處理邏輯改為 per-project不同 tenant 有不同 Telegram bot|
| Phase | Phase 7Communication Hub 建立時)|
| 風險 | 高TelegramGateway 是最大的 service約 6000+ 行)|
---
### 7. DecisionManager
| 屬性 | 值 |
|------|----|
| 位置 | `apps/api/src/services/decision_manager.py:1402` |
| Factory | `_decision_manager = DecisionManager()` at line 3529 |
| 目前狀態 | 全域,硬碼 silence keyP1-24 已在 PR-02 修補)|
| 影響 | 決策邏輯跨 tenant 共用(不同 tenant 決策規則不同)|
| 分解策略 | DecisionManager 接受 project_id 參數;規則從 project policy contract 讀 |
| Phase | Phase 4EffectivePolicy 設計完成後)|
| 風險 | 極高DecisionManager 是 Tier 3 核心,修改需 ADR 和架構審查)|
---
### 8. ConsensusEngine
| 屬性 | 值 |
|------|----|
| 位置 | `apps/api/src/services/consensus_engine.py:344` |
| Factory | `_consensus_engine = ConsensusEngine()` at line 716 |
| 目前狀態 | 全域,`CONSENSUS_PREFIX="consensus:"` 無 project |
| 影響 | P0-12多 tenant consensus 結果混合 |
| 分解策略 | ConsensusEngine 接受 project_idCONSENSUS_PREFIX 改為 `{project_id}:consensus:` |
| Phase | Phase 2PR-06|
| 風險 | 中(需 Redis 雙寫 Phase A 先完成)|
---
### 9. DecisionFusionAdapter
| 屬性 | 值 |
|------|----|
| 位置 | `apps/api/src/services/decision_fusion_adapter.py:538` |
| 單例模式 | `_adapter_instance = None` |
| 目前狀態 | 全域 |
| 影響 | 決策融合結果跨 tenant |
| 分解策略 | 同 DecisionManager依賴它Phase 4 一起改 |
| Phase | Phase 4 |
| 風險 | 中 |
---
### 10. FailoverAlerter
| 屬性 | 值 |
|------|----|
| 位置 | `apps/api/src/services/failover_alerter.py:395` |
| 單例模式 | `_alerter_instance = None` |
| 目前狀態 | 全域 |
| 影響 | failover 告警沒有 tenant 隔離GCP Ollama failover 是 platform_resource|
| 分解策略 | failover 告警本身是 `platform_resource`(保持全域),但告警發送目的地改為 per-project channel |
| Phase | Phase 7Communication Hub 建立後)|
| 風險 | 低 |
---
### 11. HostRepairAgent
| 屬性 | 值 |
|------|----|
| 位置 | `apps/api/src/services/host_repair_agent.py:204` |
| 單例模式 | `cls._instance = None` |
| 目前狀態 | 全域 |
| 影響 | 主機修復操作無 tenant scope主機屬於 platform|
| 分解策略 | 保持 `platform_internal`(主機修復是 platform 操作,不是 tenant 操作)|
| Phase | N/A不需分解|
| 風險 | 低 |
---
### 12. AIProviderRegistry
| 屬性 | 值 |
|------|----|
| 位置 | `apps/api/src/services/ai_router.py:923` |
| 目前狀態 | AIRouter 的內部 registry全域 |
| 影響 | provider 清單是 platform resourceGCP Ollama/Gemini/etc 所有 tenant 共用)|
| 分解策略 | 保持 platform-level registryper-project policy 控制各 tenant 的可用 provider |
| Phase | Phase 4EffectivePolicy 設計)|
| 風險 | 低 |
---
### 13. AIRouterExecutor
| 屬性 | 值 |
|------|----|
| 位置 | `apps/api/src/services/ai_router.py:975` |
| 目前狀態 | AIRouter 的執行器,全域 |
| 影響 | 執行邏輯共用,但 policy 會 per-project |
| 分解策略 | 同 AIRouterPhase 4|
| Phase | Phase 4 |
| 風險 | 中 |
---
## 分解優先序ADR-124 執行計畫)
| Phase | 要分解的單例 | 策略 |
|-------|-----------|------|
| Phase 2 | AnomalyCounterPR-11、ConsensusEnginePR-06| 注入 project_id 參數 |
| Phase 4 | AIRouter、AIProviderRegistry、AIRouterExecutor、DecisionFusionAdapter | EffectivePolicy 注入 |
| Phase 5 | ProviderRegistry | per-project grants 移到 DBregistry 保持 platform-level |
| Phase 6 | IntentClassifier | EwoooC 需要不同 intent domain 時 |
| Phase 7 | TelegramGateway、FailoverAlerter | Communication Hub 建立 |
| **特別謹慎** | **TrustEngine**、**DecisionManager** | Tier 3需額外 ADR 和架構審查 |
> **TrustEngine 和 DecisionManager 分解需要統帥批准Tier 3 核心RED_ZONES.md**
---
## 不需分解的單例platform_resource
| 單例 | 理由 |
|------|------|
| HostRepairAgent | 主機修復 = platform 操作,不屬於任何 tenant |
| AIProviderRegistry | provider 清單 = platform resource |
| TelegramGateway 的 polling leader | platform_resource全域唯一|
---
## 驗收標準
- [ ] 13 個單例全部分類完成per-project / platform-level / platform_resource
- [ ] TrustEngine 和 DecisionManager 的分解計畫需獨立 ADRTier 3 審查)
- [ ] Phase 2 前AnomalyCounter + ConsensusEngine 分解完成
*最後更新2026-05-03台北*