fix(consult): resolve chat subject from server-owned profile binding
This commit is contained in:
@@ -13199,3 +13199,19 @@
|
||||
- 相关记录:BUG-976、BUG-977
|
||||
- 复发自:无
|
||||
- 修复版本:`2503c019`
|
||||
|
||||
## BUG-997 | 切换人物后普通聊天仍用登录用户本人的出生资料
|
||||
|
||||
- 状态:resolved
|
||||
- 首次发现:2026-09-22
|
||||
- 最近更新:2026-09-22
|
||||
- 影响面:普通聊天 `/api/consult` 的排盘对象,以及 `POST/PATCH /api/sessions` 的人物绑定
|
||||
- 用户现象:会话已经记下另一位人物,继续提问时计算和咨询上下文仍使用当前登录用户的 `profiles`。对方资料被删除后,发送还会退回本人。
|
||||
- 触发条件:会话绑定 `chart_profile_role=other` 与某个 `chart_profile_id` 后调用普通咨询;或客户端同时提交另一套出生字段。
|
||||
- 根因:`chart_profile_id/name/role` 只是客户端可写的展示快照。咨询读取会话时不取 `chart_profile_id`,准备阶段无条件 `loadProfile(userId)` 读取登录用户的 `profiles`。客户端出生字段因此可以和实际排盘对象不一致,缺失或越权的 other 资料也会落回本人。
|
||||
- 修复:新增服务端 subject resolver。`self` 与未绑定的旧会话只读当前用户权威 `profiles`;`other` 只读当前用户拥有的 `chart_profiles` 行,并在服务端重新派生姓名与角色。会话展示名、客户端 `name/year/month/day/hour/minute/city/lat/lon/tz` 都不能覆盖该结果。另一用户的 id、随机 id、角色不一致、删除、缺失或不完整资料一律失败,不退回本人,也不扣点、不调用模型。空会话可以由服务端按 id 填上角色和姓名;已有消息的会话拒绝改绑。刷新与深链只使用库里的绑定,不读取全局 `activeChartId`。未改表结构、计费语义或模型选择,也未接到报告、每日星语或生时校正。
|
||||
- 验证:`frontend/tests/consultation-subject-binding.test.ts` 10 pass / 0 fail,覆盖 self/other、越权与随机 id、角色与伪造姓名、删除/缺失/不完整、客户端出生字段冲突、咨询准备拿到 other 资料、失败不扣点且不进入准备、有消息后改绑拒绝、刷新保留绑定、并发删除后发送失败。与 `consultation-route-service`、`application-billing-contract`、`chat-session-write`、`chat-session-authority`、`consultation-workflow-contract`、`consultation-birth-time-mode` 合跑 88 tests、87 pass / 1 fail。单独再跑 `consultation-birth-time-mode` 为 9 pass / 1 fail;失败项是本机无法创建 skill symlink(EPERM),同文件的咨询 route 顺序断言通过。`tsc --noEmit` 通过;`npm run lint` 0 error。未部署。
|
||||
- 防复发:普通咨询在扣点前必须经 subject resolver。other 查询必须同时约束 `id` 与当前 `user_id`,失败不得调用 `loadProfile` 作为退路。客户端出生字段不得进入 `toolInput`。已有消息的会话绑定必须与库存值一致,否则拒绝整次 PATCH。
|
||||
- 相关记录:BUG-001、BUG-010、BUG-011、BUG-018、BUG-073、BUG-076、BUG-188
|
||||
- 复发自:无
|
||||
- 修复版本:本次分支提交(未推送,未部署)
|
||||
|
||||
@@ -0,0 +1,33 @@
|
||||
# 进度 · 普通聊天人物资料服务端真值与会话绑定(2026-09-22)
|
||||
|
||||
基线:`10baeb2fa865743c428806e115ac92ca9d92fb71`(开工时 `origin/staging`)。分支 `codex/consultation-subject-binding-20260922`。未推送,未部署。
|
||||
|
||||
## 做了什么
|
||||
|
||||
- 新增 `frontend/src/lib/consultation-subject-resolver.ts`。`self` 和未绑定旧会话只读当前用户 `profiles`。`other` 只读当前用户拥有的 `chart_profiles`,服务端重新派生姓名和角色。
|
||||
- `prepareConsultationRoute` 在扣点前解析 subject。other 不继承登录用户的校正候选区间。客户端出生字段只被传入后丢弃。
|
||||
- `POST /api/consult` 读取 `chart_profile_id/name/role`,失败时返回固定中文错误,不扣点、不调用模型。
|
||||
- 会话创建与 PATCH 由服务端填写或核对绑定。空会话可以绑定;已有消息则拒绝改绑。刷新和深链只看库存绑定,不看 `activeChartId`。
|
||||
|
||||
## 断言变更
|
||||
|
||||
| 测试 | 原值 | 新值 | 原因 |
|
||||
| --- | --- | --- | --- |
|
||||
| `application-billing-contract.test.ts` 会话 select | `...,title,theme,chart_profile_role,context_summary` | 同一串中在 role 前增加 `chart_profile_id,chart_profile_name` | 普通咨询必须按库存人物 id 解析,不能只看 role |
|
||||
|
||||
其余既有测试名未改。展示名与资料最新姓名不一致时,咨询仍使用资料里的姓名,不因此失败:任务书要求后续聊天用该人物最新资料,展示快照不是排盘真值。伪造姓名不能写入绑定,也不能补全缺姓名的资料;角色不一致则直接失败,且不退回本人。
|
||||
|
||||
## 验证
|
||||
|
||||
- `tsc --noEmit`:通过。
|
||||
- `npm run lint`:0 error(既有 warning 未改)。
|
||||
- `npx tsx --test tests/consultation-subject-binding.test.ts`:10 pass / 0 fail。
|
||||
- 同命令一起跑 `consultation-subject-binding.test.ts`、`consultation-route-service.test.ts`、`application-billing-contract.test.ts`、`chat-session-write.test.ts`、`chat-session-authority.test.ts`、`consultation-birth-time-mode.test.ts`、`consultation-workflow-contract.test.ts`:88 tests,87 pass / 1 fail。
|
||||
- 单独再跑 `consultation-birth-time-mode.test.ts`:9 pass / 1 fail。唯一失败是 `general agent runtime has no Jyotish skill package and no personal chart tool`,本机创建 skill symlink 报 EPERM。同文件里「consult route validates mode before billing」通过。
|
||||
- 未跑全量 `npm test`,未跑 `next build`。
|
||||
|
||||
## 留给下一轮人物选择 UI
|
||||
|
||||
- 不改 `page.tsx`、首屏或聊天顶栏,不做选择器。
|
||||
- 不把 other 接到报告、每日星语或生时校正。
|
||||
- 全局 `activeChartId` 仍只在客户端;服务端不读它。
|
||||
Reference in New Issue
Block a user