Files
Jyotisha/docs/tasks/TASK-api-not-configured-mislabel-20260904.md
T

4.8 KiB
Raw Blame History

TASK · 部署/数据库瞬断被报成「服务尚未配置」(2026-09-04)

  • 基线:origin/staging @ a75929c1
  • 分支:codex/api-not-configured-mislabel-20260904
  • 执行方:coding agent;验收:Claude
  • BUG 编号起点:BUG-542(若 TASK-rectification-quality-probe-dedupe-20260904.md 尚未开工则从 BUG-540 起;开工时 grep -o "BUG-5[0-9][0-9]" docs/BUG_HISTORY.md | sort -u | tail -1 复核)

1. 事故实证

2026-09-04 约 22:00UTC+8)用户在 staging 校正面点选答案,POST /api/rectification/agentGET /api/rectification/cases/<id>?sessionId=… 均返回 503 {"error":"服务尚未配置"}。同一时刻 GET /api/health

字段 当时 数分钟后
deployment.gitCommit a75929c1(刚落地) a75929c1
status blocked ok
database.latestMigration null 20260904010000_read_report_candidate_range.sql
database.requiredMigrationsPresent false true
checks.rectificationMigrations degraded / "Error" ok
checks.modelCatalog blocked / database_model_catalog_unavailable ok

即:数据库在部署切换窗口内短暂不可用,随后自愈;环境变量从未缺失。

2. 根因

16 处路由用同一段兜底(示例 frontend/src/app/api/rectification/cases/[caseId]/route.ts L3845、frontend/src/app/api/rectification/agent/route.ts L143153):

try { supabase = await createServerSupabaseClient(); accounting = createAdminSupabaseClient(); }
catch { return 503 {"error":"服务尚未配置"} }

createServerSupabaseClient() 在自托管分支里会先读身份会话(readIdentitySession → 数据库查询),任何数据库连接错误都从这里抛出,被 catch 一律翻译成"尚未配置"。文案本来只对应 SupabaseConfigurationErrorfrontend/src/lib/supabase/config.tscode = "DATABASE_NOT_CONFIGURED",缺环境变量时抛出)。

全部 16 处:api/rectification/{agent, cases/open, cases/entry-summary, cases/[caseId], cases/[caseId]/{close, adopt-skill, upgrade-skill, candidates/accept, turns/[turnId]/regenerate}}api/consult/{route, status, cancel}api/modelsapi/birth-time-journeyapi/birth-time-guidelib/onboarding-post.ts

3. 决策记录

  1. 只有 isSupabaseConfigurationError(error) 为真时才允许返回"服务尚未配置";其它异常一律 503 {"error":"服务暂时不可用,请稍后重试","code":"service_unavailable"},并 console.error 带路由名与 error.name(不打印堆栈里的连接串)。
  2. 不新增重试、不改部署顺序、不动 health 判定;部署窗口内的短暂 503 是可接受的,这里只修说法,让用户与验收方不再误以为环境变量丢了。
  3. 16 处收敛为一个共享 helper(放 frontend/src/lib/api/ 或既有的 route 工具目录,位置由执行方按现有惯例选),不得复制 16 份新文案。

4. 硬红线

  • 不得改 createServerSupabaseClient / createAdminSupabaseClient 的抛错语义与调用顺序。
  • 未登录仍是 401,与本任务无关的路径不得顺带改动。
  • 不得在错误响应里回显任何环境变量名之外的信息;配置错误响应保留现有 "服务尚未配置" 文案(既有测试引用)。

5. 任务分解

5.1 共享 helper + 16 处替换

  • 验收:grep -rn "服务尚未配置" frontend/src 只命中 helper 一处;tsc --noEmitnpm run lint 0 error。

5.2 回归测试

  • 新增 frontend/tests/api-service-unavailable-20260904.test.ts:模拟 createServerSupabaseClient 抛 (a) SupabaseConfigurationError → 503 服务尚未配置(b) 普通 Error("connection refused") → 503 code=service_unavailable,文案不含"尚未配置"。至少覆盖 rectification/agentcases/[caseId] 两条路由(Node 22 module mock 契约见 docs/BUG_HISTORY.mdtest(reports): document Node 22 mock contract 相关条目)。
  • 既有引用"服务尚未配置"的测试若断言的是非配置类异常,改断言并写"原值 / 新值 / 原因"。

5.3 记录

  • docs/BUG_HISTORY.md 新增一条(现象、触发条件=部署切换窗口、根因=兜底翻译、修复、验证);CHANGELOG.md 一条;docs/tasks/PROGRESS-api-not-configured-mislabel-20260904.md

6. 让步顺序

5.1 > 5.2 > 5.3。若某条路由的测试 harness 不支持 mock,只覆盖两条主路由并把其余写进进度记录。

7. 开工前置命令

git fetch origin --prune
git worktree add -b codex/api-not-configured-mislabel-20260904 .worktrees/api-not-configured-mislabel-20260904 origin/staging
cd .worktrees/api-not-configured-mislabel-20260904
ln -s /workspace/Jyotisha/frontend/node_modules frontend/node_modules
grep -rn "服务尚未配置" frontend/src frontend/tests | wc -l