评审报告: workbuddy 2026-06-14 消息相关更新
评审日期: 2026-06-14
评审人: Claude (claude-opus-4-8)
评审范围: workbuddy 6-13/6-14 推送 + 版本更新说明文档 + 实际代码 diff
状态: P0 全部已修(本地代码);P1/P2 待 workbuddy 跟进
一、评审范围(8 个文件 + 1 文档)
| 文件 |
类型 |
评审点 |
backend/app/models/message.py |
改动 |
status, recallable_until 字段 |
backend/app/api/messages.py |
新增 5 端点 |
recall / delete / mark-read / image / file |
backend/app/services/ws_manager.py |
声称改动 |
"消息状态广播"(实际未实现) |
backend/app/dependencies.py |
改动 |
get_shared_ai_handler(AIHandler 修复) |
backend/app/api/h5.py |
改动 |
邀请功能 3 端点 + participants |
backend/app/api/agents.py |
改动 |
OTP 双因素(otp-bind/otp-verify/otp-unbind) |
frontend-h5/src/api/conversation.ts |
改动 |
mapMessage 字段映射(id→message_id) |
docker-compose.yml |
改动 |
healthcheck 配置(backend 用 curl 已知坑) |
docs/IT智能服务台-版本更新说明-20250614.md |
文档 |
v1.1.0 发布说明 |
二、文档 vs 代码 vs 记忆 三方不一致 ⭐ 关键发现
| 项 |
版本文档 |
代码 |
workbuddy 6-14 记忆 |
| 消息撤回/删除/状态 |
✅ 文档说已做 |
✅ 实际做了 |
❌ 记忆未提 |
| 标记已读 |
✅ |
✅ |
❌ |
| 图片/文件上传 |
✅ |
✅ (路径在容器本地) |
❌ |
| Health Check 已配置 |
✅ |
⚠️ 配了但 backend 用 curl 永远 unhealthy |
❌ |
| ws_manager 状态广播 |
✅ 文档说做了 |
❌ 代码里没有 |
❌ |
| AI Gateway 预留 |
✅ 文档说做了 |
❌ 未看到 |
❌ |
| OTP 双因素 |
✅ |
✅ |
✅ |
| 数据库 id 字段 UUID→VARCHAR(36) |
❌ 文档未提 |
✅ |
✅ |
结论:
- 文档描述的"本次更新"远多于 workbuddy 实际 push 的内容
- 文档与代码有 5 处不一致(ws_manager 状态广播未做、AI Gateway 未做、healthcheck 配错、upload 路径不持久、SQL 迁移未走 Alembic)
- 文档 "审核状态: 待审核" → 本次评审填补了审核空缺
三、13 项发现(按严重度)
🔴 P0 安全(6 项,全部已修)
| # |
位置 |
问题 |
修复 |
| P0-1 |
h5.py:1107 |
participants 端点仅校验"已登录",未校验"是否属于本会话" |
加 is_creator/is_participant 校验 |
| P0-2 |
messages.py:293 |
recall_message 无任何鉴权,任意 HTTP 客户端可改任意消息 |
加 Depends(get_current_agent) + sender_id 校验 |
| P0-3 |
messages.py:336 |
delete_message 同上,可删任意消息 |
同上 |
| P0-4 |
messages.py:368 |
mark_read 任意人可改任意会话已读状态 |
加 agent 鉴权 + assigned/collaborator 校验 |
| P0-5 |
messages.py:400 |
upload_image 无鉴权,可任意上传占用磁盘 |
加 Depends(get_current_agent) |
| P0-6 |
messages.py:458 |
upload_message_file 同上 |
同上 |
🟡 P1 重要(4 项,待 workbuddy 跟进)
| # |
位置 |
问题 |
| P1-1 |
messages.py:434,487 |
upload 保存到 media/images/,media/files/(容器本地),容器重建即丢失 |
| P1-2 |
alembic/versions/ |
模型有 status/recallable_until,但未见对应迁移脚本;文档教用户手动 ALTER(反模式) |
| P1-3 |
docker-compose.yml:118 |
backend healthcheck 用 curl,容器无 curl → 永远 unhealthy(关联 backend-healthcheck-curl-pitfall) |
| P1-4 |
ws_manager.py |
文档承诺"添加消息状态广播",代码里没看到对应方法(ConnectionManager 仅有 send_to_agent/broadcast/send_to_employee/broadcast_to_employees) |
🟢 P2 次要(3 项)
| # |
位置 |
问题 |
状态 |
| P2-1 |
messages.py:388 |
where(Message.is_read == False) 在 SQLAlchemy 里不报错但实际未生效 |
P0-4 修复时一并修:is_(False) |
| P2-2 |
messages.py:440,494 |
upload 写文件非原子,中途崩溃留半文件 |
待 workbuddy 修 |
| P2-3 |
messages.py:501 |
upload 返回原始 original_name,可能含中文/特殊字符 |
待 workbuddy 修 |
四、文档本身的 4 处错误(评审发现)
| # |
位置 |
错误 |
建议 |
| 1 |
部署步骤 6 |
SQL ALTER TABLE ... DEFAULT 'sent' 引号未转义,shell 执行会语法错 |
改用 alembic 迁移脚本,不手动 ALTER |
| 2 |
部署步骤 5 |
docker compose -p root up -d 正是用户 6-14 生产事故的根因 |
删除 -p root 标志,从 /opt/wecom-it-desk/ 跑即可 |
| 3 |
2.1 ws_manager |
声称"添加消息状态广播",代码里没有 |
文档状态改为 "未实现,后续迭代" |
| 4 |
2.1 docker-compose |
"healthcheck 已配置" 不准确 |
注明 "backend healthcheck 有 curl 坑,待修" |
五、对比之前 workbuddy 评审
| 旧 P0 (5 项) |
本次 P0 (6 项) |
备注 |
| #1 WECOM_SECRET 明文 |
(不变) |
等 P0 安全止血阶段 |
| #2 SSL 私钥在 docs/ |
(不变) |
阶段 8-A 前置解决 |
| #3 Mock login bypass |
(已修复) |
— |
| #4 WS token 在 URL/日志 |
(不变) |
等 P0 安全止血 |
| #5 坐席登录无 password |
(不变) |
等 P0 安全止血 |
| — |
P0-1 H5 participants 鉴权 |
本次新发现 |
| — |
P0-2~P0-6 messages.py 5 端点鉴权 |
本次新发现 |
安全态势:本次 workbuddy 推送 反而引入了 6 个 P0 鉴权漏洞。workbuddy 后续推送需 强制走评审流程(本次评审堵住了批量漏洞)。
六、修复与待办
已完成(2026-06-14 本地代码)
待 workbuddy 跟进
待文档/流程
七、风险跟踪表更新
新增 6 项 P0(本次评审),3 项 P1,3 项 P2(详见 docs/风险跟踪表.md)。
评审结论: workbuddy 6-14 推送 P0 比例过高(6/13 = 46%),强烈建议加评审环节。本次评审发现的 6 个 P0 全部已修代码,待 workbuddy 跟进 P1/P2。