## 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>
5.2 KiB
5.2 KiB
INV-5: Migration Compatibility Matrix
版本:v1.0 初稿
日期:2026-05-03(台北)
範圍:apps/api/pyproject.toml 實際版本 + AwoooP Phase 1 migration 需求
用途:Phase 1 schema migration 前確認版本相容性,避免 breaking change 踩雷
1. 當前依賴版本(從 pyproject.toml 實際讀取)
| 套件 | 當前約束 | 對 AwoooP Phase 1 的影響 |
|---|---|---|
| Python | >=3.11 | ✅ 足夠;asyncio.TaskGroup(3.11)可用 |
| FastAPI | >=0.115.0 | ✅ 0.115 已支援 lifespan context manager |
| SQLAlchemy | >=2.0.0 ✅ 已是 2.x | ✅ mapped_column、DeclarativeBase、async session 均可用 |
| Pydantic | >=2.5.0 ✅ 已是 v2 | ✅ model_validator、field_validator v2 語法可直接用 |
| pydantic-settings | >=2.1.0 | ✅ |
| asyncpg | >=0.29.0 | ✅ 支援 PostgreSQL 15/16 |
| redis | >=5.0.0 | ✅ redis-py 5.x 支援 cluster mode + NX |
| Alembic | 未列出(透過 SQLAlchemy 間接) | ⚠️ 需確認版本;建議鎖定 >=1.13.0 |
| Langfuse | >=2.0.0,<3.0.0(鎖定) | ✅ 無 AwoooP 影響,保持不變 |
| opentelemetry | >=1.20.0 | ✅ GenAI semantic conventions 需要 >=1.25.0(ADR-121) |
| claude-agent-sdk | >=0.1.50 | ✅ 已使用 |
2. 重要發現
✅ SQLAlchemy 已是 2.x:MASTER-WORKPLAN 中「ORM 1.x vs 2.x」問題已不存在。
mapped_column、relationship、async session 均可正常用- 但仍需確認:AwoooP 新 model 使用正確的 2.x 寫法(
DeclarativeBase而非舊declarative_base())
✅ Pydantic 已是 v2:六合約 Pydantic models 可直接用 v2 語法。
⚠️ Alembic 版本未鎖定:
apps/api/migrations/有大量.sql手寫 migration(非 Alembic auto-generate)- AwoooP Phase 1 要決定:繼續手寫 SQL migration,還是引入 Alembic autogenerate?
- 建議:保持手寫 SQL(現有慣例),每個 migration 強制有 down migration
⚠️ OTel 版本需升級(ADR-121):
- GenAI Semantic Conventions 需要
opentelemetry-semantic-conventions>=0.46b0(含gen_ai.*namespace) - 當前
>=1.20.0可能不夠,需要>=1.25.0 - 升級風險:低(向後相容);需要加入
opentelemetry-semantic-conventions依賴
3. AwoooP Phase 1 新依賴需求
| 套件 | 版本 | 用途 | 是否需要新增 |
|---|---|---|---|
pg_partman(PostgreSQL extension) |
>=4.7.0 | 高流量表 partition 自動管理 | ⚠️ 需在 DB 層安裝,非 Python 套件 |
opentelemetry-semantic-conventions |
>=0.46b0 | OTel GenAI attribute(ADR-121) | ✅ 需新增到 pyproject.toml |
PgBouncer |
>=1.21.0 | Connection pool(tool-expert 需求) | ⚠️ Infrastructure,非 Python 套件 |
4. Migration SQL 版本相容性
| Migration 問題 | 當前狀態 | 修補方式 |
|---|---|---|
adr105_mcp_audit_snapshots.sql 建表 mcp_audit_snapshots,但 models.py 用 mcp_audit_log |
⚠️ 衝突 | 確認是否已 rollback;若 mcp_audit_log 是現行表,則 mcp_audit_snapshots 已廢棄 |
| 部分 migration 無 rollback SQL | ⚠️ MASTER-WORKPLAN P0-02 | Phase 1 新 migration 強制加 down migration |
ARRAY 型別在部分 migration 用 TEXT[],在其他用 JSONB |
🟠 不一致 | AwoooP 新表一律用 JSONB(fix_playbooks_array_to_jsonb.sql 已示範) |
5. SQLAlchemy 2.x 正確寫法確認清單(Phase 1 新 model 必須遵守)
# ✅ 正確(SQLAlchemy 2.x)
from sqlalchemy.orm import DeclarativeBase, mapped_column, Mapped
from sqlalchemy import String, DateTime, func
from typing import Optional
class Base(DeclarativeBase):
pass
class AwooopProject(Base):
__tablename__ = "awooop_projects"
project_id: Mapped[str] = mapped_column(String(64), primary_key=True)
display_name: Mapped[str] = mapped_column(String(128), nullable=False)
created_at: Mapped[datetime] = mapped_column(
DateTime(timezone=True), server_default=func.now()
)
migration_mode: Mapped[str] = mapped_column(
String(32), nullable=False, default="legacy_awoooi_default"
)
# ❌ 舊寫法(SQLAlchemy 1.x,不要用)
# from sqlalchemy.ext.declarative import declarative_base
# Base = declarative_base()
# project_id = Column(String(64), primary_key=True)
6. 版本兼容風險清單
| 風險 | 嚴重度 | 緩解方式 |
|---|---|---|
| pg_partman 未安裝,partition 手動建立出錯 | 中 | Phase 1 先不建 partition,只規劃;Phase 4 前安裝 pg_partman |
| OTel semantic conventions 版本不足 | 低 | Phase 4 前升級(非 Phase 1 阻擋項) |
| PgBouncer 未安裝,AwoooP worker 壓力測試可能爆連接 | 中 | Phase 4(platform shell)前安裝 |
| Alembic 未鎖定,CI 環境版本飄移 | 低 | 鎖定 alembic>=1.13.0 加入 pyproject.toml |
7. 驗收標準
- Phase 1 所有新 migration 使用 SQLAlchemy 2.x
mapped_column語法 - 所有新 migration 有 down migration SQL
mcp_audit_snapshotsvsmcp_audit_log衝突已解決(確認哪個是現行表)pg_partman安裝計畫已寫入 runbook
最後更新:2026-05-03(台北)