docs(report): add list-500 task brief — JSON-path select rejected on staging PostgREST

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_016P5RoqzmUQEbeC2qjAkeGr
This commit is contained in:
Jesse_Chen
2026-09-07 02:30:41 +00:00
parent 5e7574d153
commit 480050d655
+55
View File
@@ -0,0 +1,55 @@
# 任务书 · 报告列表 500 修复:PostgREST JSON 路径列在 staging 不可用(2026-09-07
基线:`origin/staging` @ `5c644f92`(开工 `git fetch` 后以 HEAD 为准)。
## 事故实证(委托方已用真实会话对照实测)
- `GET /api/reports` 稳定 500`{"error":"报告列表暂时无法读取","code":"report_generation_failed"}`(部署 `0a1076d6`,含 MD 页 `cfcd369d`)。
- 同一会话 `GET /api/reports/<旧报告id>` **200**——鉴权、DB 连接、`personal_reports` 表读取都正常。
- 该列表路由(含 failed 报告的 `personal_report_sections` 聚合查询)在 09-04/05 的旧部署上**成功返回过完整列表**。`cfcd369d` 对列表查询的唯一改动是新增 select 列:
```ts
"card_summary:report_document->executiveSummary->>summary"
```
- 结论:这个 PostgREST JSON 路径别名 select 在 staging 自托管 Postgres/PostgREST 上被拒,supabase 返回 error → `if (error) throw error` → catch-all 500。列表路由错误日志只记 `error.name`PostgrestError 非 Error 实例 → `UnknownError`),线上日志无法直接看到 PostgREST 错误码——本轮顺带修观测。
- 消费点唯一:`frontend/src/app/api/reports/route.ts`:48 select、:80-81 映射)。
## 根因教训(防复发,写进红线)
执行方单测用 stub supabase clientselect 字符串**从未经过真实 PostgREST 解析**——与 gaps2"虚构盘骗过覆盖表"同款模式。凡新增 PostgREST 查询语法特性(JSON 路径、嵌套 embed、别名),必须有 `test:db` 层真实查询覆盖,或列入部署后 smoke 清单。
## 硬红线
1. 修复不得再依赖未经真实验证的 PostgREST 语法变体(比如换成带引号的 path 再赌一次);本轮修复必须以 `test:db` 真实查询或本地 Postgres+PostgREST 验证过的形态为准。
2. 列表接口对**没有摘要**的行为必须优雅(无 `cardSummary` 字段即可,前端已是可选消费)。
3. 其余既有红线延续(迁移规范、不改 `.gitea/workflows/**`、不提升 main、`./node_modules/.bin/tsc`)。
## 任务
### 任务 1(P0)· 止血:列表恢复可用
`REPORT_LIST_COLUMNS` 移除 JSON 路径列,恢复 09-06 前的列集合;`cardSummary` 暂缺省。目标:`GET /api/reports` 立即恢复 200。可单独先推一次。
### 任务 2(P1)· 卡片摘要走专用列
迁移给 `personal_reports``card_summary text`(可空,≤500 字符 check),MD 生成成功时由 worker 从 MD「摘要」段写入(与现有写 `executiveSummary.summary` 的截取逻辑同源);列表 select 该普通列。旧报告不回填(产品已放弃兼容)。迁移照既有红线,`test:db` 覆盖:列可空、authenticated 只读、worker(service_role) 可写、超长被拒。
### 任务 3P1)· 观测修正
列表 catch 里对 PostgrestError 记 `code`/`hint` 级别信息(非 Error 实例时取其 `code` 字段;不记行数据),避免再出现 `UnknownError` 无从下手。
### 任务 4P0 收尾)· 部署后 smoke
部署对齐后用真实会话验证:列表 200;创建一份新报告端到端(这同时是 MD 页任务 5 一直欠着的收官验收:~30s ready、详情页 TOC/宽表、导出 .md、计费 0 用量结算、新报告卡片摘要显示)。把「列表 GET + 详情 GET + 创建 POST」固化进部署后 smoke 清单文档。
## 收尾
`docs/tasks/PROGRESS-report-list-500-20260907.md``docs/BUG_HISTORY.md` 条目(编号对远端;关联 cfcd369d);不提升 main。
## 交付物清单
1. 止血 diff + 列表恢复 200 证据
2. `card_summary` 迁移 + worker 写入 + `test:db` 四断言
3. 观测修正 + 测试
4. 部署后 smoke 记录(含 MD 页端到端收官全项)