Files
gochat/review-h30.md
T
Rogeeandrogee c922460649 H-97: fix Shangwutong conversation routing (#16)
* H-60: harden Captain migration rollback and concurrency

* chore(agent): baseline — uncommitted work from the local directory

* fix: route Shangwutong events by display id

---------

Co-authored-by: Rogee <rogee@ipao.vip>
2026-08-14 14:35:12 +08:00

3.8 KiB
Raw Blame History

审查结论:阻断,不建议父问题进入 review。Stage 3 两个子问题虽然已标记完成且 PR #5/#6 据交接记录已 squash 合并,但 H-17 的 CID 相关阻断仍未全部关闭。

阻断项(按严重性)

  1. P0kind=52 CID 链路仍不可达。channels/shangwutong/internal/delivery/mapping.go:170-171 只设置 ContactCID,没有设置 RequiresContact/RawOnly;因此 inbound.go:106-108 直接 complete,永远不会执行 ensureResources 的 metadata 写入。结果 contact_inboxes.channel_metadata.cid 不会被持久化,昵称 durable job 无法命中 CID。最小修复:让 kind=52 进入仅更新 ContactInbox metadata 的路径,且把 CID 纳入写入条件;补真实 worker/HTTP 调用链回归测试。

  2. P1:公共 Widget 仍可注入内部 CID。backend/internal/handler/widget/widget_handler.go:1394-1429backend/internal/service/widget_service.go:821-845 接受并保存 channel_metadata.cidHMAC 非 mandatory 时,知道 source_id 的公共调用方可写任意 CID,可能把客服改名投递到错误商务通客户。最小修复:从公共 request DTO、绑定和 service 写入中删除 CID;仅保留受信 Connector 内部路径。

  3. P1:已有 source 的 CID 更新仍只改内存。backend/internal/service/widget_service.go:769-784 的 PublicCreateContact existing 分支调用 setContactInboxChannelMetadata 后没有 contactInboxRepo.Update,所以 Connector 走已有 source 的 POST 分支时 CID 静默丢失。最小修复:metadata 变化时持久化,并覆盖已有 source 测试。

  4. P2migration down 仍丢失 rename operation。channels/shangwutong/db/migrations/002_add_rename_operation.down.sql:17-19 只复制 operation = 'end_conversation',随后删除原表;任何 change_contact_name 的 pending/delivered/uncertain/failed 记录都会被静默删除。最小修复:存在该类记录时明确拒绝 down,或完整无损迁移后再收紧约束。用 sqlite 重现确认 down 后只剩 end_conversation。

  5. P1:昵称事件入队错误被吞掉。backend/internal/handler/api/v1/contact_handler.go:293-297 忽略 channelDispatcher.Dispatch 错误;若 durable job 入队因数据库/worker 故障失败,联系人更新仍返回 200 且没有补偿事件,反写任务永久丢失。最小修复:让该错误进入明确的可重试失败响应,或把事件入队纳入同一可靠事务/outbox。

AI 接管退出部分无阻断:message_service.go 用行锁和 takeover version 防止人工消息与迟到 AI 竞态;显式退出和人工发送均发布既有 conversation.updatedWS payload 含最新 ai_takeover_active,前端消费后立即合并状态。

验证通过:

  • cd backend && go test ./internal/service -run 'TestConversationServiceAITakeoverStartExitAndRestart|TestMessageServiceHumanOutgoingExitsAITakeoverAtomically|TestCaptainConversationResponseRechecksTakeoverBeforeCreate|TestCaptainConversationResponseRejectsStaleJobAfterReentry' -count=1
  • cd backend && go test ./internal/wsevent -run TestOnEvent_ConversationUpdatedPublishesInactiveTakeover_Cov3 -count=1
  • cd backend && go test ./internal/handler/api/v1 ./internal/handler/widget ./internal/service -run 'Test(Shangwutong|WidgetHandler_PublicContactIgnoresCID|ContactUpdate|Captain|MessageServiceHumanOutgoing|ConversationServiceAITakeover)' -count=1
  • cd channels/shangwutong && go test ./... -count=1 && go vet ./...
  • cd frontend && pnpm exec vitest run app/javascript/dashboard/helper/specs/actionCable.spec.js app/javascript/dashboard/store/modules/specs/conversations/mutations.spec.js83 passed
  • cd frontend && pnpm build

PR 状态:H-28/H-29 交接记录称 #5/#6 已合并;当前 Multica issue PR link 查询为空(squash 后关联未保留)。无需新 PR;请退回 H-28 修复上述 CID/回滚/入队问题后再复审。