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

8.2 KiB
Raw Blame History

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 建立
特別謹慎 TrustEngineDecisionManager 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台北