## 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>
8.2 KiB
8.2 KiB
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_id),trust score 跨 tenant 混算 |
| 分解策略 | per-project trust engine instance,從 project contract 讀 trust_policy |
| Phase | Phase 2(repository 加 project_id filter 後) |
| 風險 | 高(TrustEngine 是飛輪核心,分解需仔細 regression test) |
2. ProviderRegistry(MCP)
| 屬性 | 值 |
|---|---|
| 位置 | 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 registry(tool 清單)+ per-project grants(誰可用什麼);Registry 本身可保持 platform-level |
| Phase | Phase 5(MCP Gateway 建立時) |
| 風險 | 中(Registry 改為 read-only platform resource,grants 移到 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 2(PR-11) |
| 風險 | 中(6 個 prefix 全部要改) |
4. AIRouter
| 屬性 | 值 |
|---|---|
| 位置 | apps/api/src/services/ai_router.py:194 |
| Factory | _router = AIRouter() at line 1324 |
| 依賴 | AIProviderRegistry(923)、AIRouterExecutor(975) |
| 目前狀態 | 全域,所有 tenant 共用 provider routing 決策 |
| 影響 | EwoooC 可能使用 AWOOOI 的 model routing policy |
| 分解策略 | AIRouter 接受 EffectivePolicy 參數(per-project policy 已在 Phase 4 設計);Router 邏輯保持 platform-level,policy 來源改為 per-project |
| Phase | Phase 4(EffectivePolicy 設計完成後) |
| 風險 | 中(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-level(intent schema 共用);長期 per-project intent domain config |
| Phase | Phase 6(EwoooC 需要不同 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_resource;gateway 處理邏輯改為 per-project(不同 tenant 有不同 Telegram bot) |
| Phase | Phase 7(Communication Hub 建立時) |
| 風險 | 高(TelegramGateway 是最大的 service,約 6000+ 行) |
7. DecisionManager
| 屬性 | 值 |
|---|---|
| 位置 | apps/api/src/services/decision_manager.py:1402 |
| Factory | _decision_manager = DecisionManager() at line 3529 |
| 目前狀態 | 全域,硬碼 silence key(P1-24 已在 PR-02 修補) |
| 影響 | 決策邏輯跨 tenant 共用(不同 tenant 決策規則不同) |
| 分解策略 | DecisionManager 接受 project_id 參數;規則從 project policy contract 讀 |
| Phase | Phase 4(EffectivePolicy 設計完成後) |
| 風險 | 極高(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_id;CONSENSUS_PREFIX 改為 {project_id}:consensus: |
| Phase | Phase 2(PR-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 7(Communication 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 resource(GCP Ollama/Gemini/etc 所有 tenant 共用) |
| 分解策略 | 保持 platform-level registry;per-project policy 控制各 tenant 的可用 provider |
| Phase | Phase 4(EffectivePolicy 設計) |
| 風險 | 低 |
13. AIRouterExecutor
| 屬性 | 值 |
|---|---|
| 位置 | apps/api/src/services/ai_router.py:975 |
| 目前狀態 | AIRouter 的執行器,全域 |
| 影響 | 執行邏輯共用,但 policy 會 per-project |
| 分解策略 | 同 AIRouter(Phase 4) |
| Phase | Phase 4 |
| 風險 | 中 |
分解優先序(ADR-124 執行計畫)
| Phase | 要分解的單例 | 策略 |
|---|---|---|
| Phase 2 | AnomalyCounter(PR-11)、ConsensusEngine(PR-06) | 注入 project_id 參數 |
| Phase 4 | AIRouter、AIProviderRegistry、AIRouterExecutor、DecisionFusionAdapter | EffectivePolicy 注入 |
| Phase 5 | ProviderRegistry | per-project grants 移到 DB,registry 保持 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 的分解計畫需獨立 ADR(Tier 3 審查)
- Phase 2 前:AnomalyCounter + ConsensusEngine 分解完成
最後更新:2026-05-03(台北)