产品在测试机上发现工作台发了两个 workload 请求、clinicId 不一样。 查下去不只是"多发一个",是**那一发真的取回了别家的数据**。 ── 服务端(真问题)────────────────────────────────────────── `/plans/assignments/agents`、`/plans/assignments/workload`、`/plans/matrix` 三个读接口拿着查询串里的 clinicId 直接查,不校验是否在 scope 内。 实测:北京朝阳公园的主管(clinicIds=[66701845…])带杭州大厦的 id 请求, 拿到 200 + 那家 26 位客服的**姓名与在手负载**;矩阵同样能拿到完整患者量分布。⚠ ️ 写路径一直是拦的(create 里那句 includes 判断),所以分不走别家的人 —— 但名册是员工姓名、矩阵是患者量分布,读一样不能敞。 闸抽成 common/decorators/resolve-clinic-id:不传取第一个诊所,传了必须在范围内, 范围外抛 Forbidden(10107)并列出真实 id ——⛔ 不能"当成这个诊所没人"返回 0, 0 是合法答案,静默返回会让助手拿着 0 去解释"为什么这批人是空的"(违 T14)。 集团级(clinicIds 为空)原样放行,⛔ 别把空数组当成没权限。 MCP 里原来抄了一份一模一样的实现 —— 抄一份的直接后果就是补的时候只补了一边。 现在两边共用一份。 ── 前端(触发源)──────────────────────────────────────────── 第一帧 user.clinicIds 还是 undefined(JWT 里没有这一项,只能等 /auth/session), visibleClinics 回落到"字典里的全部诊所" → 锁了第一个「杭州大厦」→ 发出那一发。 session 回来后自己纠正成朝阳公园,所以肉眼只看见"发了两个请求"。 新增 clinicScopeReady():undefined=还没加载 / []=集团级,两者必须分开 ——⛔ 别改 visibleClinics 的回落语义去顺手修,那会让集团级用户的筛选器空掉。 实测改后:进工作台只发 1 个 workload,clinicId 正确。⚠ ️ 前端等待与服务端闸是**两层**,缺一不可:查询串是用户可改的。 测试:回归从"grep MCP 源码"改成锁**闸只有一份实现** + **每个收 clinicId 的 REST 读接口都过闸**(按 @Query('clinicId') 出现次数比对),这正是漏掉的那一类。 Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
| Name |
Last commit
|
Last update |
|---|---|---|
| .. | ||
| ai-invocations | Loading commit data... | |
| assistant | Loading commit data... | |
| host-admin | Loading commit data... | |
| pet | Loading commit data... | |
| plan-detail | Loading commit data... | |
| plans | Loading commit data... | |
| realtime-coach | Loading commit data... | |
| recall-debug | Loading commit data... | |
| supervisor | Loading commit data... | |
| ui | Loading commit data... | |
| auth-gate.tsx | Loading commit data... | |
| can.tsx | Loading commit data... | |
| identity-cluster.tsx | Loading commit data... | |
| mock-login-dialog.tsx | Loading commit data... | |
| priority-hover.tsx | Loading commit data... | |
| session-expired.tsx | Loading commit data... |