fix(chat): make the server the only writer of session messages
List GET no longer ships transcripts; consult appends questions after reserve and ignores client history so dual-tab last-write-wins cannot erase messages. Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
+22
-1
@@ -1069,4 +1069,25 @@
|
||||
- 建议在数据库 migration 成功后运行独立的环境 readiness 脚本,不放在应用启动期,避免每个实例重复探测或因业务配置缺失阻止无关只读能力启动。
|
||||
- readiness 应枚举当前环境所有已发布模型的 `model_tier`,逐一检查 `rectification`、`chat.standard`、`report.full` 三个 feature 是否存在 `status='published' AND enabled=true` 的定价;任何组合缺失即以脱敏、可行动的运维错误 fail closed。
|
||||
- readiness 只负责验证,不写入或 seed 价格;部署后仍必须通过 admin flow 为实际 tier 发布定价,随后再重跑 readiness。
|
||||
- 本地验证:TypeScript、改动文件 ESLint、rectification `705/705`、consult/report 聚焦 `262/262` 通过;全量 `2368/2369`,唯一失败是默认 `python3` 缺少 PyYAML,改用已安装 PyYAML 的 `/opt/homebrew/bin/python3` 后对应文件 `39/39` 通过。
|
||||
- 本地验证:
|
||||
- `./node_modules/.bin/tsc --noEmit` 通过。
|
||||
- 非数据库前端测试 **2377 通过 / fail=0 / skipped=0**。
|
||||
- `npm run test:db -- --test-concurrency=1`:**34 通过 / fail=0 / skipped=0**(含 `append_consultation_question` 幂等、双 request_id 叠加、`session_full`)。
|
||||
- `npm test` 会并行拉起多个 Postgres fixture,本机 Docker address pool 只能同时容纳 2 个 compose network,并行时会超时,不是本轮断言回归。验收用上面两项拆开跑。
|
||||
- 浅色/深色:加载态 `.session-messages-loading` 使用 `color: var(--color-ink-secondary)`,spinner 的 `currentColor` 跟随该 token(浅色 `#5f5f59`,深色 `#b3afa4`)。`session_full` 走 sonner toast,背景/文字用 `--color-canvas` / `--color-ink`,错误语气由「已写满」命中 `failedNotice`。未登录所以没有做带真实会话的页面点击;主题检查落在 token 与合同测试上。
|
||||
|
||||
## 2026-09-01 - TASK-chat-message-authority:服务端收回 messages 写权
|
||||
|
||||
- 列表 `GET /api/sessions` 不再选择 `messages`;新增 `GET /api/sessions/[id]` 按会话加载完整消息。前端启动只拉列表,切换时拉详情,已加载的会话内存缓存,正在 streaming 的会话不重拉。
|
||||
- `append_consultation_question` 在 reserve 成功后写入用户提问;满员返回 `session_full` 并取消预扣。consult 忽略客户端 `history`,改读库内最近 12 条。
|
||||
- `persistSession` 只 PATCH 元数据。旧全量 `messages` PATCH 返回 200 且不覆盖库。中止/失败部分回答不再落库。
|
||||
- 断言例外(锁住的正是本轮要修的缺陷):
|
||||
- `consultation-recovery.test.ts`:不再要求发问前 `persistSession(userSession)`,也不再要求中止/截断路径持久化部分回答;完成恢复改拉详情而不是整表列表。
|
||||
- `chat-session-write.test.ts`:create schema `messages.max(0)`;update 请求体不含 `messages`;页面不再把 thinkingText 映射进 PATCH。
|
||||
- `application-billing-contract.test.ts` / `rectification-agentic-entry.test.ts`:校正 agent select 去掉未使用的 `messages`;consult select 增加 `messages` 以便服务端读历史。
|
||||
- `consultation-stream-recovery.test.ts` / `consultation-workflow-contract.test.ts`:agentic 函数切片终点从 `parsed.data.history` 改为 `storedHistory`。
|
||||
- `chat-notice-and-scroll-contract.test.ts`:toast 支持一键开新对话的 action。
|
||||
- 实测:
|
||||
- Payload:列表响应列集合为 `id,title,theme,model_id,session_type,rectification_case_id,chart_profile_* ,updated_at`,消息文本只能出现在详情 GET。多会话账户的字节对比取决于该账户存量消息,合同测试锁的是“列表不含消息文本”这一结构,而不是某一个登录态的绝对字节数。
|
||||
- `session_full`:本地 PostgreSQL 把会话填到 200 条后再 append,返回 `error_code=session_full`,行内消息数仍为 200。
|
||||
- 双标签页:同一会话两次 `append_consultation_question`(不同 request_id)后两条用户消息都在;这是改前 last-write-wins 必丢、改后必留的核心形状。
|
||||
|
||||
Reference in New Issue
Block a user