# 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 必須遵守) ```python # ✅ 正確(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_snapshots` vs `mcp_audit_log` 衝突已解決(確認哪個是現行表) - [ ] `pg_partman` 安裝計畫已寫入 runbook *最後更新:2026-05-03(台北)*