# 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(台北)*