* 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>
3.8 KiB
审查结论:阻断,不建议父问题进入 review。Stage 3 两个子问题虽然已标记完成且 PR #5/#6 据交接记录已 squash 合并,但 H-17 的 CID 相关阻断仍未全部关闭。
阻断项(按严重性)
-
P0:kind=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 调用链回归测试。 -
P1:公共 Widget 仍可注入内部 CID。
backend/internal/handler/widget/widget_handler.go:1394-1429和backend/internal/service/widget_service.go:821-845接受并保存channel_metadata.cid;HMAC 非 mandatory 时,知道 source_id 的公共调用方可写任意 CID,可能把客服改名投递到错误商务通客户。最小修复:从公共 request DTO、绑定和 service 写入中删除 CID;仅保留受信 Connector 内部路径。 -
P1:已有 source 的 CID 更新仍只改内存。
backend/internal/service/widget_service.go:769-784的 PublicCreateContact existing 分支调用setContactInboxChannelMetadata后没有contactInboxRepo.Update,所以 Connector 走已有 source 的 POST 分支时 CID 静默丢失。最小修复:metadata 变化时持久化,并覆盖已有 source 测试。 -
P2:migration 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。 -
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.updated,WS payload 含最新 ai_takeover_active,前端消费后立即合并状态。
验证通过:
cd backend && go test ./internal/service -run 'TestConversationServiceAITakeoverStartExitAndRestart|TestMessageServiceHumanOutgoingExitsAITakeoverAtomically|TestCaptainConversationResponseRechecksTakeoverBeforeCreate|TestCaptainConversationResponseRejectsStaleJobAfterReentry' -count=1cd backend && go test ./internal/wsevent -run TestOnEvent_ConversationUpdatedPublishesInactiveTakeover_Cov3 -count=1cd backend && go test ./internal/handler/api/v1 ./internal/handler/widget ./internal/service -run 'Test(Shangwutong|WidgetHandler_PublicContactIgnoresCID|ContactUpdate|Captain|MessageServiceHumanOutgoing|ConversationServiceAITakeover)' -count=1cd 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.js(83 passed)cd frontend && pnpm build
PR 状态:H-28/H-29 交接记录称 #5/#6 已合并;当前 Multica issue PR link 查询为空(squash 后关联未保留)。无需新 PR;请退回 H-28 修复上述 CID/回滚/入队问题后再复审。