diff --git a/apps/api/src/api/v1/platform/__init__.py b/apps/api/src/api/v1/platform/__init__.py index 065a8c38..a9ff3e19 100644 --- a/apps/api/src/api/v1/platform/__init__.py +++ b/apps/api/src/api/v1/platform/__init__.py @@ -14,9 +14,12 @@ from src.api.v1.platform.runs import router as runs_router from src.api.v1.platform.tenants import router as tenants_router router = APIRouter() +# 2026-05-06 Codex: FastAPI 依註冊順序比對路由。Operator Console 的 +# `/runs/list` 必須排在 `/runs/{run_id}` 前面,否則 `list` 會被當成 +# run_id,造成前端 Run 監控頁 HTTP 422。 +router.include_router(operator_runs_router) router.include_router(runs_router) router.include_router(tenants_router) router.include_router(contracts_router) -router.include_router(operator_runs_router) __all__ = ["router"] diff --git a/apps/api/tests/test_platform_router_order.py b/apps/api/tests/test_platform_router_order.py new file mode 100644 index 00000000..815fbf5e --- /dev/null +++ b/apps/api/tests/test_platform_router_order.py @@ -0,0 +1,15 @@ +from __future__ import annotations + +from src.api.v1.platform import router + + +def test_runs_list_route_is_registered_before_dynamic_run_id() -> None: + paths = [ + route.path + for route in router.routes + if "GET" in getattr(route, "methods", set()) + ] + + assert "/runs/list" in paths + assert "/runs/{run_id}" in paths + assert paths.index("/runs/list") < paths.index("/runs/{run_id}") diff --git a/docs/LOGBOOK.md b/docs/LOGBOOK.md index 9887a117..b1087c83 100644 --- a/docs/LOGBOOK.md +++ b/docs/LOGBOOK.md @@ -1,3 +1,16 @@ +## 2026-05-06 | AwoooP Run 監控頁 422 修正 + +**背景**:Playwright 驗證 `/zh-TW/awooop` 時未再看到 client-side exception,但 `/zh-TW/awooop/runs` 會顯示「無法載入 Run 資料 HTTP 422」。後端 log 顯示 `GET /api/v1/platform/runs/list?page=1&per_page=50` 被回 422。 + +**根因**: +- FastAPI 依註冊順序比對路由。 +- `platform/__init__.py` 先註冊 `/runs/{run_id}`,再註冊 Operator Console 的 `/runs/list`。 +- 因此 `list` 被動態路由當成 `run_id`,再因缺少 `project_id` 或 UUID 格式錯誤回 422。 + +**本次修補**: +- 將 `operator_runs_router` 註冊順序提前到 `runs_router` 之前。 +- 新增 router order 回歸測試,鎖定 `/runs/list` 必須早於 `/runs/{run_id}`。 + ## 2026-05-06 | MCP legacy provider 路徑補上飛輪稽核脈絡 **背景**:AwoooP MCP Gateway 已有五閘門與 gateway audit,但 production 仍有多條 legacy caller 直接走 ProviderRegistry 或 provider wrapper。硬切 Gateway 會因 contract/grant 尚未覆蓋所有路徑而造成修復鏈中斷,因此本輪先做「不改語義的稽核包裝」。