Files
go-sip/docs/evidence/saas-queue-refresh-20261009.md
T

51 lines
6.0 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# SaaS 队列驱动配置刷新(2026-10-09)
## 根因与改动
固定环境的 Dispatcher 在启动时拒绝任务 3:`revision 2 changed content`。来源任务修订号未变,状态由 paused 改为 running;旧逻辑把当前任务配置误当作不可修改的历史执行快照。
使用者确认保留 revision 字段与现行 Schema,但不以 SaaS 修订号增减、相等或同号内容变化阻止更新。共享规范文字提交为 `ff74afe396eb811745a20cd88d167585d6593132`;未改 Schema。
- 启动列表之后读取的任务详情为当前配置;详情状态变化不再导致版本冲突。
- 任务刷新、发现、edit 及租户额度采用当次完整读取;最新额度同时更新同租户的未来任务绑定。
- 已持久暂停/停止不被 HTTP running 清除。停止后的 edit、归属、时段、幂等与未知占用规则保留。
- 选线到占用之间按真实任务配置摘要核验,不以 task_revision/status 元数据判断变化;内部 SIP 加载代次及 Agent/Asterisk 实际加载核验不变。
- 历史已接纳执行的冻结快照不被当前配置或额度更新改写。
## 本地验证
`make check`、`make release-check-local`、`make coverage` 通过;业务语句覆盖率 70.8%。包括同修订状态/内容变化、降低任务/额度来源修订号、MQ 暂停保留、同修订选线期间业务变化拒绝、来源元数据单独变化不拒绝、跨任务额度更新,以及冻结执行/未知占用保留的回归测试。RabbitMQ/HTTPS/mTLS 隔离端到端运行通过,不代表真实通话验收。
## 真实环境与测试边界
本地 Chrome 已分别登录租户与隔离管理员会话。隐藏标签页会使页面交互停滞;确认此现象后激活标签页,新建任务对话框可正常打开但未提交。不同标签页共享 browser-harness 的当前会话选择,必须串行操作,不能并行切换后发送点击。
源码 `cd762b5` 已合入 main、推送并按固定入口无重置部署。实际运行二进制 SHA-256 为 `adcd9c1687ce62c8d152ea3afd530e5f5e95a7a8136765b5ea5736c41d79404b`。最初部署报告的 `saas_pending/business_ready=false` 不作为业务就绪签收;随后直接核对 SQLite,`discovery_ready=1`、内部 SIP 加载代次 26、pending 0。四个任务仍保留 `control_state=paused`,任务 3 的 HTTP running 未自动解除暂停。
平台任务 3 显示“开启中”,包含 981 个号码且没有关闭按钮。使用者明确改用号码 0、并发 1 的空任务 4,只验证控制消息和反馈,不导入号码或外呼;任务 3 不作页面操作。恢复部署时任务 3 当日获准呼出时段已结束,并核对持久暂停仍在。管理员页面仅查看线路,未修改。
## 空任务 4:消息与真实失败反馈
通过租户页面确认开启任务 4,页面变成“开启中”。Dispatcher 日志证实实际收到控制队列消息,但 `mq validation failed at /`,随后服务失败关闭并重启;没有生成控制 outbox,任务 4 的持久控制状态仍为 paused。**只能证明格式校验失败,不能由根路径错误推断具体缺失字段或声称业务开启成功。**
使用者要求读取留证并验证反馈,随后明确批准发送真实 `rejected` 而非伪造成功。零活动通道检查后临时停止 Dispatcher;不停止 Agent/Asterisk。用已有 AMQP SDK 被动核验控制队列与任务 4 队列,两者均 `ready=0/consumers=0`,没有原消息可读。不创建、绑定、删除或 purge 队列;诊断读取不 ACK 消息,任何暂存未确认交付随通道关闭返回原队列。
从正常已登录页面 `/prod-api/call/task/4` 的实际响应核对:任务 4、租户 1005,仍等待事件 `b6686633-a8f5-4ae6-a92a-2fd92775f796`,`lastControlAt=2026-10-09 19:52:25`。这只找回待反馈身份,**没有找回被拒绝 MQ 原文**。另从只读 SQLite 核对归属和 paused 状态。
经授权仅发送一次人工失败回执,严格通过现行 Schema:`event_type=task.control`,沿用上述原 `event_id`、登记 D UUID、租户 1005,`payload={"status":"rejected"}`。发布至现行 result exchange 和登记 D 的出站路由,mandatory、无 return、publisher confirm 通过。**这是操作者按已发生的拒绝事实发出的回执,不是正常 Dispatcher 业务处理/outbox 完成,也不是 SaaS 应用收到的证明。** 未发送 applied/成功,不猜新事件身份,不盲重发;首次本机证据路径误写在发布前被明确拒绝,随后核对正确目录和不存在任何已准备回执才执行唯一实际发布。
页面重新加载后任务 4 **仍为“开启中”**,因此没有证明 SaaS 收到、处理或解除等待。需 SaaS 开发按上述事件编号核对结果队列消费及状态映射;不能用 broker confirm 代替应用反馈,也不能为此改写项目任务状态。MQ 原文丢失,具体格式错误需 SaaS 提供原文或先停止消费者、留证后再重发控制消息。
## 私有证据与结束状态
测试机证据目录:`~/.local/share/go-sip/evidence/20261009T121108Z-task4-feedback/`,目录 0700、文件 0600;原凭据不打印、不 source,不存明文副本。
| 证据 | SHA-256 |
| --- | --- |
| 队列核验日志 | `e1846492271a343b649c938c0952eb7c1027483aae261fb2f893b59e1e88c26f` |
| 准备的人工拒绝回执 | `063c8c0183d66afba60d1b834fe74f096faca72cc40d7c585103cca24e78ec05` |
| 发布确认日志 | `2369d93c01fce87c69e2218be678bb86814974e051154d64006ca419e6c63518` |
| 最终服务/数据/原生通道状态 | `9c146cda72d4a71e909b91bc013d7998ccbcc53b55c745b570914cbe5de75646` |
读取完成后已恢复 Dispatcher;最终 Agent/Dispatcher/Asterisk active+running、NRestarts=0,D discovery_ready=1、SIP 26/pending 0,四个任务控制状态 paused,inbox/outbox 均 0,原生 Asterisk 零活动通道/通话。未提交新任务、导入号码、外呼、请求 AI/OSS、重置数据库、清理业务队列、改线路地址/主叫/鉴权或重启 Asterisk。平台白名单、管理员线路热加载、真实通话和 SaaS 实际反馈仍未验证。