docs: make approved SaaS dispatcher contract the current project entry
This commit is contained in:
@@ -75,120 +75,41 @@
|
||||
|
||||
开始任务前先定义完成标准。交付前依此验证,发现问题就修好再测,不把未完成的工作交回给使用者。只有确认完成,或遇到真正需要使用者介入的障碍时,才回报。
|
||||
|
||||
## 当前范围
|
||||
## 当前范围与权威入口
|
||||
|
||||
- 后续Agent必须先读 **`docs/plan-dispatcher-state-v0.1.md`** 和 **`docs/thirds/v0.4.md`**;历史 F 工作包索引见 `docs/plan-config-read-v0.1.md`:按 F 工作包/文档索引读取需求与契约,确认 C/L/M 和 I/M/G 前置、授权及写入边界后实施;并行时按该计划§9认领,子Agent只写独占模块/证据,§8本轮总台账、公共文件及合并状态由集成负责人单写。已恢复原内容的 `docs/archive/plan-0918.md` 仅保留旧 W00–W16 历史,不是现行计划入口。本地 Dispatcher v0.4 任务发现、MQ 控制及外呼入站规则另读 `docs/plan-dispatcher-state-v0.1.md`、`docs/thirds/v0.4.md`;`docs/plan-0926.md`、`docs/thirds/v0.3.md` 及 v0.2 状态仅作历史。**v0.4 的 Schema、隔离 Mock 与代码已在项目内实施,真实 SaaS/management 尚未签收或联调;仅显式条件清理已终止任务的任务配置副本,不自动清除现有 SQLite 数据。没有 SaaS 应用收讫的执行、幂等及 outbox 记录继续保留。日志不得记录密钥、完整音频或对话。** 计划不替代权威Schema或验收,不重复审批已确认方向,不自动授权真实云/付费/拨号。
|
||||
- 当前MQ-only/OSS调整目标已获用户明确批准由当前Agent独立执行,**不启动子Agent**,不得再以子Agent模型/fast环境阻塞本目标;此前按任务类型自动分工规则在本目标不适用。若未来另获启动授权,仍遵守下条模型要求。
|
||||
- 用户指定:若启动开发及配套审查子Agent,固定 **gpt-5.6-luna、max思考、fast模式**。启动前查询精确provider/model和runner支持并显式配置(当前工具用模型`:max`后缀及`fast: true`,不继承默认);不可用/不支持/无法核验则报告阻塞,不静默换模型、降思考档、关fast或换CLI。此为后续执行约束,本轮仅修复计划,未启动开发子Agent。
|
||||
- 并行开发须先有获授权的可追溯Git/契约基线、一lane一工作区/测试资源、无交叠写集合及每批合并后回归;当前子项目尚未跟踪的文件不能假定存在于HEAD/worktree。不得自动提交、暂存或清理父项目无关改动;详情见 `docs/plan-config-read-v0.1.md` §9。
|
||||
- 当前已获授权进行本项目开发:W01 项目内契约基线和 W02 Proto/stubs 已建立;仍不能把设计、Mock、Proto或88项测试清单写成真实供应商/生产验收已通过。入口和权威依据仍为 `docs/architecture/Go重写方案_v0.3.md`、`docs/acceptance/验证与切换验收_v0.3.md`、`docs/contracts/通信与事件数据交互_v0.1.md`、`docs/references/OpenAPI与MQ字段索引_v0.1.md`、`docs/dependencies/开源组件选型与复用清单_v0.2.md`。
|
||||
- 开发准备见 `docs/architecture/G0开发准备与契约冻结提案_v0.1.md`:D01–D10的方案方向、双模式/许可/恢复机制及内部PoC初始profile已获用户确认;本项目已自行交付 W01/W02 开发基线,但外部权威发布、真实预算、供应商签收和 G0/PoC 仍需分别验证,不能混写为生产合同。缺失字段细节、实际预算及方案变更另行确认。本轮验收基线收敛为单节点/单 Agent/单 Cell/单租户;双节点、第二 Cell、第二租户及其公平/故障矩阵不在本轮开发或验收范围,跨 Cell/多租户能力保留为后续阶段。
|
||||
- 用户已确认完整 Go Agent、分阶段替换:调度、Cell 执行、ARI/RTP/录音、AI 流及 Cell 配置接收。最终没有 Python 运行依赖;不重写 Asterisk、不实现第二套管理后台。
|
||||
- 本项目已独立拆仓运营,源码、文档、依赖、配置、迁移、测试、部署、发布入口全部留在本目录。普通构建/测试/运行不读取父目录,不使用其它项目内部模块、环境文件或夹具,不共享其业务数据库。
|
||||
- 当前已初始化独立 Git 仓库并绑定公开远程 `git.ipao.vip/rogee/go-sip`;未经授权不要重新 `git init`、改为 submodule、移动历史或更改父仓库跟踪关系。
|
||||
- 当前工作由使用者批准按 P01–P08 实施,K01–K16 已确认,不重复审批;本目标由当前 Agent 独立执行,**不启动子 Agent**。只有未来重新获得授权,才按使用者指定的 `gpt-5.6-luna`、`max` 思考和 `fast: true` 逐项核验并显式配置,不静默换模型、降档或关闭 fast。
|
||||
- 唯一现行 SaaS↔Dispatcher 业务说明是 [`docs/thirds/saas-dispatcher.md`](docs/thirds/saas-dispatcher.md);当前项目内 Schema、拓扑、正反例及来源/hash 在 [`contracts/local/`](contracts/local/);内部 Agent RPC 在 [`proto/agent/agent.proto`](proto/agent/agent.proto)。进度与缺口见 [`docs/plan-saas-dispatcher.md`](docs/plan-saas-dispatcher.md) 和 [`docs/evidence/saas-dispatcher-implementation.md`](docs/evidence/saas-dispatcher-implementation.md)。文档不能代替机器合同或外部签收。
|
||||
- [`docs/plan-saas-dispatcher-v05-v0.1.md`](docs/plan-saas-dispatcher-v05-v0.1.md) 的原路径和原 SHA-256 已由 `contracts/local/manifest.json` 固定,只作**不可变历史来源**;旧 F/W 工作包、v0.1–v0.4 本地提案、旧 MQ-only 合同及 `docs/archive/` 不作为当前运行入口。固定 MQ `v1` 名称、HTTP `/internal/v1/dispatcher/...` 路径和有业务意义的 revision 是通信规则,不是应删除的自有实现代次。不得为历史路径新建兼容层或配置回退。
|
||||
- 当前本地范围仅**单节点、单 Dispatcher、单 Agent、单 Cell、单租户和隔离 Mock**。根命令只接受显式 `agent`/`dispatcher` 业务子命令,mixed/real 启动即拒绝;没有真实 SaaS、management、RabbitMQ、OSS、AI 供应商、Asterisk、SIP 线路、ECS 或生产签收。生产发布包仍为 `production_approval=false`。本机 Mock HTTPS、双向 TLS、RabbitMQ 和哈希通过均不授权真实呼叫。
|
||||
- 开发按 TDD 分批,小步提交;不得覆盖使用者现存修改/未跟踪文件,不自动清理、迁移或覆盖任何现存 SQLite、spool、outbox 和 Agent 恢复文件。旧 `.executions` 及恢复根目录中旧 `.uploads`、`.upload-locks`、逐执行 `state.json` 的发现须只读失败关闭,现存未交付事实由使用者确认处置。真实云账号、EIP、线路、拨号、生产部署和共享数据操作分别需要明确授权。
|
||||
|
||||
## SIP 接入信息
|
||||
## SaaS、Dispatcher 与 Agent 的现行边界
|
||||
|
||||
以下为用户提供的 SIP 参数,服务商名称待补充;已记录不代表已完成真实线路验证。
|
||||
- SaaS→Dispatcher 的**五类只读配置**为 `GET /internal/v1/dispatcher/sip`、`/task/:task_id`、`/tasks`、`/tenant/:tenant_id/quota`、`/ai-providers`;路径前缀固定,均须校验 Dispatcher UUID/资源归属、数字 `tenant_id`、完整快照、来源、有效授权和版本。配置读失败、过期、矛盾或不确定时关新准入;没有旧 MQ 配置回退、通用业务 HTTP、ETag 兜底或偷偷启用旧执行字段。已接纳任务持久绑定原快照。
|
||||
- 呼叫、控制、必要回执和**每通话唯一最终结果**经固定 `v1` RabbitMQ Topic/队列,任务与控制队列由 SaaS 预建,Dispatcher 仅消费、不可自行建/删/绑定;结果进入指定共享 durable 队列。独立 D UUID 和接收队列不能广播后正文过滤;`tenant_key` 原值保留,任务只能由归属 D 执行。入站先校验和持久 inbox 后 ACK,状态/outbox 同事务;persistent、mandatory、无 return、publisher confirm 成功才记交付,confirm **不是** SaaS 应用收讫。失败/确认丢失与重启只重发同身份消息,不重复拨号或捏造结果。
|
||||
- `call.execute` 只带获批 `task_id/callee`,调用线路、主叫、AI 和时限由该任务快照固定;`task.control` 的 pause/resume/stop 无旧 CAS/版本字段,控制回 task/action/status 处理结果,stop 不可恢复。发现分页同快照先全部校验后提交,MQ 控制持久状态高于偶发 HTTP 状态;冲突关准入、resume 须重新核验。历史命令不因消息年龄过期,但实际呼出前仍检查任务/白名单/时段/授权/额度和有效通话上限;任务结束不删未确认结果、恢复、幂等或未知占用。
|
||||
- 独立 Dispatcher 的 SQLite 是任务、额度、inbox/outbox 的权威数据;Agent 无业务数据库,录音、执行与上传恢复只写受控私有文件。额度包含未知占用,新 boot/租约到期不得自动清除未知执行;不实现双活数据库、自动跨机热备、多 D 共享额度或第二租户公平。本轮不借本机 D1/D2 隔离夹具宣称多 D 运行。不得建立旧表/旧消息/旧 HTTP 执行兼容通道。
|
||||
- Dispatcher↔Agent 复用 Unary gRPC 和受控 Endpoint;Agent 预绑定 D UUID 与服务端证书指纹,激活/会话代际、peer mTLS/SAN/SNI 和已签发期限须核对,新 boot 不清未知占用。Agent 不自行向 SaaS 取任务/AI/OSS 授权;Dispatcher 只用已经核验的 Agent `GetLoadedSIP` revision 开执行准入。本机 Mock 的加载回报不证明 Asterisk 已实际加载,SIP 配置的唯一编辑/审批面仍是 management。
|
||||
- AI 使用任务内不可变授权快照:仅经获批准百炼/火山 ASR、OpenAI 兼容 LLM、火山 TTS 能表达的参数进入每通话实例;ASR-only 不启动 LLM/TTS,完整 AI 不借旧语音测试的 LLM/TTS。只有最终用户 ASR 文本的明确字面关键词可触发拒联/挂断;不由 SDK 默认值、环境、CLI、metadata 或宽松 Schema 改写业务参数,不因 SDK 重试产生第二次发起/收费或重播。日志只存脱敏版本/摘要/计数,不存密钥、prompt、完整对话或音频。
|
||||
- Agent 录音经受控双向 TLS 向 D 领取短期 OSS 上传授权,每次尝试只作**一次 HTTPS PUT**;正常上传成功不写录音/结果业务文件。首次明确失败须先完整保存录音与结果两份恢复文件,才从该时刻启动 48 小时重试;按 1、2、4、8、16、32、60 分钟及其后每 60 分钟的固定节奏显式重新申请授权,同一 OSS 目标、同一消息身份。PUT 结果未知不得盲目重传;48 小时届满仍失败时保留文件待人工,**不伪造最终结果或自动清理**。D 不转发文件,已确认结束的通话及时释放执行占用;未知执行仍占用。只有真实终结后才通过唯一 `call.execute.result` 回报录音路径、最终转写和拒联事实;无录音或录音生成失败以空 `recording={}` 和真实结果收口,生成失败须说明原因。不能恢复的录音不声称零丢失,也不伪造 OSS/SaaS 应用回执。凭据/TOKEN/签名 URL 不写入样例、日志、源码或证据。
|
||||
|
||||
| 服务商 | SIP 服务端 | 主叫号码/标识 | 被叫前缀 |
|
||||
## SIP 与真实呼叫限制
|
||||
|
||||
| 线路 | SIP 服务端(历史登记,非已验证线路) | 主叫标识 | 被叫前缀 |
|
||||
| --- | --- | --- | --- |
|
||||
| 数企 | `61.132.228.221:5060` | `BD93205882` | `7089` |
|
||||
| 中鼎 | `60.171.24.90:5060` | `mbkq` | 无 |
|
||||
| 百应 | `160.202.254.79:5060` | `KQ91526` | `mka755` |
|
||||
|
||||
## SIP 全局共用定义:外呼号码白名单
|
||||
- 全线路**只允许原始号码** `15003164745`、`15830461047`,但白名单和上述登记绝非真实拨号授权。已授权的真实/旧路径仅在 Asia/Shanghai 每日 `09:00`(含)至 `20:00`(不含)放行,每条 trunk 对每个原始号码每天最多 3 次,窗口外直接拒绝,不等候/自动延迟/自动重试/静默换线。每次真实试拨仍须使用者明确安排并受现行程序 Mock-only 启动屏障约束;不能拿 Mock 时段测试宣称 real 放行。
|
||||
- 任务按周一至周日多个时段与指定排除日期配置,线路只有每周允许时段(**没有线路排除日期**),Asia/Shanghai 左闭右开、跨日拆分;缺失或不确定 fail-closed,不自动重拨。由 Dispatcher 在持久接纳与实际发出指令前判定,并取任务/获批 AI 较小通话时限;Agent 仅校验会话和签发期限,不重算外呼策略。本地策略 Mock 与固定真实门禁必须分别报告。
|
||||
- `BD` 等主叫原值不得清洗或当作 Digest 用户名;业务原始被叫号码不变,仅被选定数企 trunk 按规则构造 `7089<原号>`(其它线路使用自己的前缀),不重复加前缀。三条 trunk 独立,不能把同地址伪造为备用线路或换线重拨;服务商反馈 PCMA,对应 Asterisk `allow=alaw`,传输/注册/鉴权/并发仍待真实签收。不以 sipgo/diago 另造 Asterisk 替代架构。
|
||||
|
||||
- 外呼号码白名单:`15003164745`、`15830461047`。
|
||||
- 所有 SIP 线路仅允许在此列表范围内发起外呼;不在列表内的号码必须拒绝。该列表仅用于已授权的 Mock/明确安排的测试;不得因写入此处而自动发起真实呼叫,原始号码保持不变。
|
||||
- **现行真实/旧路径运行限制**仍为 Asia/Shanghai 每日 `09:00`(含)至 `20:00`(不含);窗口外 Dispatcher/Agent 必须 fail-closed,禁止等待、自动延迟、重试或换线。下述非生产和真实验证条款中的固定时间仍是**当前真实运行限制**。新增的 V3 执行入口只启用隔离 Mock,mixed/real 启动即拒绝;Mock 测试不能宣称 real 放行。
|
||||
- **F04 项目内 Mock 已实现、外部未签收的后续目标**:仅 Dispatcher 在持久接纳与实际发出呼出指令前判断任务×已选 SIP 线路的允许时段、白名单、命令/授权/租户额度期限及任务/AI 较小通话时限;Agent 只校验会话及 Dispatcher 签发期限,不重算外呼业务策略。任务按周一至周日分别配置多个允许时段,可排除多个指定日期;线路只配置每周允许时段,**没有线路排除日期**。均按 Asia/Shanghai 判断,跨日拆分、左闭右开,任务排除日期全天拒绝;缺失/不确定时段拒绝并持久记录,不等下一窗口、不自动重试或换线。任务和线路时段**尚不能授权真实试拨**;F08 最终结果/额度收口、F09 完整验收及真实合同/部署授权分别未完成,不能据此放开固定真实门禁。
|
||||
- 主叫标识保留原值(包括 `BD`),不能按纯数字手机号清洗,也不能直接当成 Digest 认证用户名;具体 From/PAI 等字段映射仍需确认。
|
||||
- 业务原始被叫号码保持不变;使用该线路时按其规则构造 `7089<被叫号码>`,避免重复添加或把该前缀带到其他供应商线路。
|
||||
- 传输协议、IP/Digest 鉴权、是否注册及并发限制仍需供应商确认;当前供应商已反馈需使用 PCMA,Asterisk 配置以 `allow=alaw` 表示,仍需真实线路验证。
|
||||
- 每条线路目前只提供一个服务端地址,未提供独立备用地址。不能把同一地址重复填写成主备并宣称具备容灾;三条已登记线路应作为独立 trunk 配置,不为凑主备虚构供应商。
|
||||
## 运行环境、诊断与开发门禁
|
||||
|
||||
## ECS 部署环境与 Asterisk 运行约束
|
||||
|
||||
- ECS 部署环境固定优先使用 Debian 13(Trixie)minimal;仅当阿里云北京区域没有可用的 Debian 13 镜像时,才允许使用 Ubuntu 24.04 LTS。不得擅自切换到其他操作系统。
|
||||
- Asterisk 必须直接部署在实际承载它的 ECS 主机上,由 systemd service 统一管理并启用开机自启动;部署验收必须确认 service 已 enabled 且 active,不得以手工前台进程或容器入口替代生产启动方式。
|
||||
|
||||
## 开发与非生产环境强制部署/诊断步骤
|
||||
|
||||
- 开发、Mock、mixed、real 的**非生产环境**必须默认开启环境部署与诊断步骤;这些步骤是必需的,不得因“只是开发”“环境已存在”“时间紧”或调用方参数而跳过、关闭、静默降级或默认禁用。任何显式关闭均视为配置错误,应失败并阻止验收。
|
||||
- 每次新主机、新版本或新 Cell 验证至少执行并留存脱敏事实:ECS/EIP/网络资源只读核验、Debian/架构/磁盘/权限核验、`rogee` SSH 与 SSH 加固核验、发布包及依赖 SHA-256、Asterisk/systemd `enabled+active`、ARI/PJSIP endpoint/contact 状态、媒体 profile/监听端口和运行版本。
|
||||
- 每次非生产 `mixed`/`real` 外呼验证,必须先通过 Asia/Shanghai `09:00`–`20:00`(左闭右开)时间门禁,再在拨号前启动受限 SIP/RTP 抓包和 Asterisk PJSIP logger,并在结束后采集 SIP 响应码、INVITE/180/183/200/4xx/5xx/BYE 或 CANCEL 时间线、SDP codec/媒体地址端口、RTP 包/字节计数、录音与 ASR/LLM/TTS 事实及 SHA-256;无拨号前抓包、状态快照或时间门禁不得宣称验证通过。失败呼叫同样必须保留状态和抓包证据,不能只报告一个 hangup cause。
|
||||
- 抓包、日志、录音和识别文本只写入受限的非生产证据目录,聊天、源码、配置样例、提交和长期证据不得保存密钥、完整用户音频或完整用户对话;交付证据默认保存脱敏摘要、计数、状态码和哈希。若 tcpdump/CAP_NET_RAW、PJSIP logger、ARI/PJSIP 状态采集任一不可用,必须 fail-closed 报告阻塞,不得静默改成无抓包流程。
|
||||
- 上述步骤由统一部署/验收入口自动执行;`mock`、`mixed`、`real` 只替换适配器,不能绕开同一套部署、诊断、状态和证据门禁。生产环境仍须另行授权和通过生产安全屏障,非生产默认强制开启不等于生产放行。
|
||||
|
||||
## 本次上线目标与分期(用户已确认)
|
||||
|
||||
- P1以稳定快速内测上线为目标:1个节点、1个Agent、1套Asterisk、1个单活Dispatcher/SQLite、1个启用租户;本轮不开发、不验收双节点、第二 Cell/第二 Asterisk或第二租户。用户已确认后续多 Dispatcher 目标为每 D 独立 ID/接收队列、独占 Agent/Asterisk 执行资源;同一租户可有多任务,但每个任务只能有一个 D 归属,SaaS 持久绑定租户+任务→D,呼叫/控制不得分发到其它 D,不能暗中迁移。单任务并发可由归属 D 本地判断;跨 D 租户/供应商总上限仍须先冻结有界额度份额,不能各 D 各按全局上限放行。本轮不把 D1/D2 隔离 fixture 冒充多 D 业务运行。
|
||||
- 至少3家独立SIP trunk 的静态配置、路由/主叫/前缀/codec/额度约束和协议 Mock/mixed 覆盖仍需保持;真实供应商外呼和 ECS 仅作为第二阶段联调,不是本轮前置。
|
||||
- ASR-only和ASR+LLM+TTS均按批准的不可变AI配置在本地/隔离链路验收;不擅自加MQ模式字段,不复用旧LLM/TTS。真实供应商未联调时必须明确标记为第二阶段,不能把 Mock 写成真实供应商通过。
|
||||
- P1使用管理平台批准的静态单 Cell 快照和受控维护窗口,不做在线发布/回滚编排;静态配置必须关准入、排空、核验实际加载,旧直写通道不得并行。
|
||||
- P1保留 tenant_key 原值、租户独立队列、复合幂等键、有界窗口及单租户配额/控制边界;不开发或验收双租户公平、第二 Cell 汇总配额和多实例协调。
|
||||
- 本阶段上传按固定15分钟授权、单次PUT、原事实持久化及recording.uploaded可靠入队进行本地隔离验收;不申请SaaS上传会话、不等待complete/verified或OSS ID。RabbitMQ ACL/TLS和application receipt仅按适用版本化契约/隔离测试验证,不将通知入队称为SaaS已处理;真实SaaS/MQ联调延期第二阶段。
|
||||
- 88项验收为跨阶段基线,当前只签收单节点/单 Cell/单租户适用子场景;双节点、第二 Cell、第二租户、真实 ECS/生产联调、容量/N+1及切换均不作为本轮门禁。
|
||||
|
||||
## 语言与工程
|
||||
|
||||
- 工具链基线为 Go 1.27.1。实施时锁定 CI/构建镜像和依赖,并校验实际工具链;不得自动修改其它项目的 Go 基线。
|
||||
- 标准库优先、单Go module/二进制,用Cobra显式提供agent、dispatcher两个业务子命令,无默认双角色启动;同一制品分进程/权限/目录,升级受版本兼容和排空约束,不另造CLI框架。
|
||||
- JSON v2、UUID 和新测试 API 的采用以契约兼容和实测为前提;既有标识、哈希规范不得随 API 更换。实验性 SIMD 不在当前范围。
|
||||
- 用户已确认不接PG:独立Dispatcher持有SQLite权威任务/配额/outbox,Agent无业务DB,文本/录音及执行/上传恢复信息落文件。禁止NFS共享SQLite/两份DB双活发额度,自动跨机热备不在已实现承诺内。
|
||||
- 已确认Unary gRPC,Dispatcher预配置Agent Endpoint;Agent业务只需D Endpoint,证书/监听/ARI/持久目录由部署提供。SDK复用连接,不增内部MQ或双向流,不因RPC超时重拨。
|
||||
- 所有Agent共用mTLS证书,D身份独立;必须通过受控Endpoint主动激活/节点会话授权,不信自报身份/地址。共享私钥泄露影响整组,轮换/撤销和风险要签收,不关闭SAN/SNI校验。
|
||||
- D感知健康/负载/软件协议/能力及供应商applied配置版本;样本过期/缺失为unknown,低CPU不突破租户/供应商/Cell/AI配额,新boot不清旧未知占用。
|
||||
- 实施后至少执行本模块的格式化检查、`go vet ./...`、`go test -race ./...` 和构建;当前代码已有 W01/W02/本地 RPC/AI Mock 入口,真实 DB/MQ、媒体、供应商、容量及切换验收仍分别报告,不能用本地通过记录代签。
|
||||
|
||||
## 开源复用硬约束(用户已确认)
|
||||
|
||||
- SIP 及其它组件有适用开源库/官方 SDK 必须复用,禁止从零手写替代协议栈或客户端。优先标准库、Asterisk 原生能力、现成 SDK;自有代码限业务状态机、事务、权限、配额和薄适配。
|
||||
- 不自写 SIP/ARI、RTP/RTCP 编解包、G.711、WS/AMQP/数据库驱动、OSS 签名、已有 SDK 覆盖的 AI 协议或 Schema 解析。库不满足先选替代、修上游或报告阻塞;例外须用户另行批准。
|
||||
- 采用前核验 module/tag/commit、Go1.27.1、许可证/NOTICE、传递依赖/漏洞及真实协议兼容,留存 PoC;不得将 main README、未归档或可下载等同于生产通过。
|
||||
- SDK 自动重试不得造成二次 originate、旧音频重播或重复收费;不因 SIP 库存在而用 sipgo/diago 替换已选定 Asterisk 架构。
|
||||
|
||||
## AI配置与参数(用户已确认)
|
||||
|
||||
- P1采用百炼/火山ASR、OpenAI兼容LLM、火山TTS;SDK首选及未通过门禁见组件清单§1.3/§4.3。基础栈方向确定不等于精确版本、许可证或参数能力已验收;不为补字段改为自写协议。
|
||||
- **现行合同(尚未切换)**:Dispatcher按MQ任务agent_version_id,经RabbitMQ专用Topic向SaaS取得不可变AI配置/授权,响应回原Dispatcher;校验租户/源Schema/不可变摘要/能力并持久绑定后向Agent交付执行快照。过去已废弃的独立AI版本GET不复活;新获批准的方向是**任务配置只读接口内含智能体**,须另冻合同而非旧GET兼容层。Agent不直连SaaS,不从CLI/env/源码常量或SDK默认覆盖AI业务值,不新增任务MQ模式字段或调参后台。
|
||||
- 已有model/prompt/voice/speed/ASR输入与识别/temperature/max_tokens/timeout及对话控制必须实际传入SDK或控制器;热词/VAD/top_p/音量/阶段时限等所需扩展先在上游补GAP-09,再生成校验。严格additionalProperties不放宽,不借metadata/raw_request透传。
|
||||
- **现行 AI 合同**:SaaS新版本供新任务引用,无需改代码/重启D/A;在途/原排队任务固定快照,同版本异内容拒绝。缓存按租户+版本隔离,断SaaS无有效授权缓存拒新准入;显式0/false与未提供保真,并发通话不得共享可变SDK参数。
|
||||
- **项目内配置与执行(已发布外部 v1 不变)**:项目内 v0.4 任务发现、控制及外呼入站依据 `docs/thirds/v0.4.md`;其它必要边界见 `docs/thirds/第三方对接事件与请求消费顺序_v0.1.md`。拟定 SaaS 只读路径为 `/internal/v1/dispatcher/sip`、`/internal/v1/dispatcher/task/:task_id`、`/internal/v1/dispatcher/tasks` 和 `/internal/v1/dispatcher/tenant/:tenant_id/quota`;均为项目内字段/路径,实际 SaaS 兼容性未验证。D 用 `X-DISPATCHER-id`/`X-DISPATCHER-SECRET-KEY` 按需读取,不在源码、配置样例或日志暴露凭据。SIP 启动先取获批全量并核验 Agent/Asterisk 加载后才准入;任务按租户+任务缓存约 60 秒,到期重新读取完整 200,无 ETag、过期缓存或 MQ 配置回退;已接纳执行固定原快照,暂停/停止控制不等待缓存。项目内 v0.4 `call.execute` 入站只有 `task_id/callee`,调用路由、主叫、AI 和时限绑定已授权任务快照;历史 MQ 命令不因年龄过期,但拨号前门禁不放宽。任务终止仅允许**显式、条件式**清理任务配置副本,不删执行恢复、幂等或 outbox。SIP 改动须关准入、排空及核验实际加载;外部 opt-out 现行 MQ 即时语义不可擅自改称已切换为最终 `call.result`。F01/F07 本地 Schema、正反例、来源/hash 与 Mock C 已通过,外部签收/连通仍未验证。
|
||||
- 凭据/供应商端点来自受控引用且有授权校验;不再定义独立出口池标识或出口池授权名单,Dispatcher 仍校验任务允许线路、全局号码白名单、时段和额度,不能因可调参数绕过安全硬限额或启用不安全重试。OpenAI默认自动重试显式关闭;日志只留脱敏版本/摘要/有效参数,不打印prompt/变量/密钥。
|
||||
- 静态发布只约束SIP/节点制品,不将AI配置硬编码;GAP-08/09及SDK参数PoC为P1门禁,验证入口见验收§5.1(现有E/L项子场景,不新增虚假通过数)。
|
||||
|
||||
## 契约与可靠性
|
||||
|
||||
- 本项目设计/运行/验收文档只在自身 `docs/` 维护。上游共享接口有唯一权威来源;导入带版本、来源和哈希的不可变契约包,再生成类型/校验,不维护重复手写 Schema。
|
||||
- 新内部消息/许可/fencing 协议需先获批;不擅自改变 SaaS 路径、字段、状态、路由或控制语义。
|
||||
- **现行已发布合同(新版本生效前必须遵守)**:SaaS↔Dispatcher的全部交互唯一经RabbitMQ专用Topic订阅,双方无HTTP请求/回调/兼容通道或故障回退,包括执行、控制、查询、整体补传、AI配置/授权及recording.uploaded上传事实通知;上传不申请SaaS会话或等待verified/OSS ID回复。OSS配置/TOKEN不来自SaaS:Agent领取及显式重申请TOKEN只经D↔A Unary;本规则不禁止Agent→OSS、ARI、AI供应商HTTP(S)或gRPC的HTTP/2。
|
||||
- **本轮项目内目标(尚未替换真实外部运行)**:任务(含智能体)、SIP、任务发现和按 tenant_id 的租户额度走四条只读 HTTP;呼叫、控制及其必要回执/单份最终结果走 MQ,取消对外业务查询/补传和分散通话事件。不提供配置HTTP→MQ回退,也不恢复其它业务HTTP通道。SaaS须分发 management 已批准的唯一 SIP 版本,management 仍为唯一编辑/审批面。该本地语义按第三方契约及版本化 Schema/示例/hash 冻结,Mock C 是本地门禁,不等待外部签收;真实切换仍需另行授权。
|
||||
- 新HTTP配置字段项目内 SIP 新版见 `docs/contracts/config-read-fields-v0.3-proposal.md`、`config-read-v0.3.schema.json`/mock示例;AI 授权和静态 Cell 制品的项目内新版见同一提案;旧 v1/v0.2 保留历史,不作为当前运行契约;任务/额度仍参照 v0.1;截图只证实UI含义,英文响应键为项目自定义,绝非SaaS现网接口已确认字段。用户新增任务排除日期、线路时段等未见截图项按项目需求设计;SIP传输/鉴权/注册及额度未知不能猜默认值。Schema/Mock 校验可满足项目内 C,但不代表 SaaS/management 已发布或真实兼容;真实响应、审批来源和 Agent/Asterisk 实际加载仍须单独验证。当前唯一权威运行契约不因草案变化。
|
||||
- **每个Dispatcher必须有独立、全局唯一且不重复的ID及独立接收Topic/队列**;指定D的任务/现行MQ配置结果/上传结果不能由其它D抢收,也不能广播后仅靠正文过滤;新目标只读HTTP配置由该D UUID+SECRETKEY获取且须核对任务归属。身份与tenant/Agent/Cell ID、dispatcher_epoch分开;现行合同保留租户独立队列及原值tenant_key,完整新路由长度预算须重验。具体ID生成/持久化、Topic/绑定、消息字段/关联/错误/期限须随W01新版本冻结,不凭本文给旧严格Schema添加字段。
|
||||
- **v0.4 任务发现与队列所有权硬边界**:SaaS 独占创建、维护、退役每 D 的独立控制队列与每任务任务队列及绑定;Dispatcher 仅消费,不能自行建队、绑定或删除。本地 RabbitMQ 无 `configure` 权限 Mock 已通过,真实兼容性未验证。新加入或重启 D 先 `GET /internal/v1/dispatcher/tasks?mode=snapshot` 逐页取得同一 `snapshot_id`/`watermark` 的完整清单,全部校验后一次 SQLite 事务提交;独立控制队列积压处理完成前不开任务准入。运行期 `GET .../tasks?after=<内存游标>` 仅发现归属变更,每页持久提交后推进内存游标;重启不恢复旧 v0.3 持久事件游标,分页或持久化失败关新准入、停任务消费,MQ 控制及结果恢复照常处理。HTTP 的偶发状态与 MQ 已应用状态冲突则关准入,不让发现页覆盖已持久的 pause/stop;只有 MQ resume 经单任务新鲜状态确认才恢复原积压。stop 挂断、排空后回自身控制回执,未接纳旧外呼静默 ACK、不拨号、不回逐条结果,也不删 SaaS 任务队列。历史 `task.control` 与 `call.execute` 不因消息年龄过期,外呼仍在接纳和拨号前独立检查任务/白名单/时段/授权/额度及通话时限,未来 `issued_at` 不提前接纳。保留原值 tenant_key、租户额度和未知占用;跨 D 份额仍待外部冻结。v0.1–v0.3 发现证据仅作历史,v0.4 本地证据见 `docs/evidence/dispatcher-v04-local-acceptance.md`;不能证明真实 SaaS/management、多 D 或生产可用。
|
||||
- **OSS相关配置存于Dispatcher配置文件,Agent向Dispatcher领取临时上传TOKEN后直传OSS,不保存长期凭据;SaaS不再下发OSS配置/TOKEN。** D复用官方SDK提供受限TOKEN/目标信息,配置缺失/无效明确失败;不在样例、源码、日志或证据中保存实际密钥/完整TOKEN。过期只允许A显式向D重新申请,不自动续期或向SaaS申请TOKEN;精确配置格式/TOKEN形态/UploadGrant映射另行核验,不猜字段。
|
||||
- **本轮项目内目标:上传仅负责 Agent 直传及 D 可靠通知 MQ,SaaS 后续处理不属本项目职责;外部 v2 的现行上传事实不因本地目标自动改变。** D保留签发能力、不转发文件;R13持久保存事实与recording.uploaded outbox,消息为persistent、进入指定durable队列/绑定、mandatory无return且publisher confirm成功后才记交付完成。只写本地outbox不算入队;不申请SaaS会话、不等待verified/OSS ID、不新增VERIFYING、不伪造SaaS结果。
|
||||
- 新版recording.uploaded取代本项目recording.ready,字段为call_id/recording_id/upload_id/bucket/object_key/format/channels/sample_rate_hz/duration_ms/size_bytes/checksum_sha256;不含TOKEN/密钥/签名URL。MQ失败/确认丢失/重启只恢复原消息身份的交付,不重新PUT或新建资产。现行AI/控制等必要请求响应不受此收缩影响;新目标AI改用任务只读HTTP获取,控制仍走MQ。
|
||||
- 前一轮MQ-only文档纠正已结束;以下是**现行 MQ-only v1 合同的历史基线**,不得误当作新只读配置HTTP方案的限制或验收通过:现行机器依据见 `contracts/upstream/v1/mq-topology.json`、`mq.schema.json` 和 `event-payloads.schema.json`,第三方顺序说明见 `docs/thirds/第三方对接事件与请求消费顺序_v0.1.md`:纯Topic精确绑定、拒绝独立通配词段、tenant_key预算196 UTF-8字节、稳定UUID v4、旧版严格JSON配置及15分钟SDK预签名PUT;新目标保留业务MQ及OSS规则,仅替换配置获取,须另发版本化合同,不原地复用旧Schema。当前仅保留现有代码需要的契约包;未发生契约迁移前不新增契约,旧快照不作为当前工作树输入。新版须完成Schema/正反例/哈希验证后发布,不把方案确认当实现完成。历史 W01/W02/W04/W05/W07/W08/W11/W12/W13/W14 范围见归档 `docs/archive/plan-0918.md` §8.2;项目内 v0.4 配置/控制路径以 `docs/plan-dispatcher-state-v0.1.md` 和本地验收证据为当前入口;外部合同另行签收。全局唯一D身份/专用Topic及本地D1/D2隔离fixture为当前合同要求,不授权双D业务运行、HA或共享额度。
|
||||
- **现行已发布合同**中的实时文字事件名为transcript.updated,不新增call.transcript别名;OSS文本归档不能冒充当前实时文字/opt-out,缺少专用资产授权接口时明确未启用,不能伪装recording.ready。
|
||||
- **用户已批准的项目内精简契约目标**见 `docs/plan-config-read-v0.1.md` §3.5/§4 和第三方对接契约:SaaS↔D 移除对外查询/补传命令及分散通话/转写/拒联/录音事件,保留呼叫/控制命令和必要回执;录音仍上传 OSS,D 每通话只回传一份含最终转写、拒联事实与 OSS 路径的 `call.result`。本地实现以 F01/F07 Schema、正反例、来源/hash 和 Mock C 为门禁,无需额外外部/业务签收;本地验收更新后不要求通话前实时文字或拒联。无录音按 `not_created` 收口;预期录音明确失败立即 `unavailable`,未知最迟于 `call.ended_at + 15m` 收口。通话确认终结释放执行资源后释放占用,不等待 OSS 或 MQ confirm;未知仍占用。现行外部 Schema/代码保持原样,真实兼容性未验证。
|
||||
- 现有MQ信封command_type/command_id、event_type/aggregate_*与正文已对齐;事件payload专属约束尚需补齐,不把通用object校验当完整验收。字段索引只读生成,不手改成第二套Schema。
|
||||
- `tenant_key` 原值一对一绑定,不清洗、编码或截断;旧布局224个UTF-8字节预算不能在加入D身份后直接照搬,W01须冻结并验证完整routing key/queue预算及分隔符/通配符边界;超限停止发布并保留源任务。
|
||||
- 持久 inbox 后 ACK;状态与 outbox 同事务;confirm 不等于 SaaS 应用收讫。重复投递、未知执行和恢复不能触发重复拨号。
|
||||
- 配额覆盖所有 Cell/实例及未知占用;租约过期不自动释放不明通话。**现行 v2** 控制 CAS 为 expected_task_revision,pause 与 stop 的 drain/hangup 区分;paused 可按新授权恢复,stopped 不可恢复。现行整体补传仅 call_id/source_command_id;下一版对外查询/补传目标取消但严格合同/代码未改。最后发起许可、权限和屏障须故障注入。
|
||||
- **用户已批准的项目内精简契约目标(不能混写现行 v2;外部签收不阻塞本地 C)**:`call.execute.payload` 仅 `task_id/callee`,外呼信封身份仍用于防止重拨;路由/主叫/智能体版本与 `ring_timeout_ms/max_call_duration_ms` 均从已批准的任务配置取得并持久绑定。`task.control` 的 pause/resume/stop 均不带 `command_id` 或 `expected_task_revision`,不设计控制去重,但 D 必须回 task/action/status 处理结果;乱序、控制重投/回执丢失与 stop 后 resume 的本地判定写入第三方契约并由 Mock 测试;外部签收不是本地阻塞项,不偷偷重引入 CAS/去重掩盖。任务配置新增明确 `caller_profile_id`,按allowed_trunk_ids顺序选首个时段/额度/加载/主叫均匹配的线路,选后固定、不自动换线重拨;有效通话上限取任务与已授权AI两者较小值。旧running配置/发现不得解除已持久的paused/stopped,resume须强制最新任务核验,stopped同ID不可逆。拟定配置响应不再包含 `agent.content_sha256`;录音 checksum 另有用途,不误删;SIP SaaS 响应不再提供 snapshot_sha256 或静态制品。参见 `docs/plan-config-read-v0.1.md` 和 `docs/thirds/第三方对接事件与请求消费顺序_v0.1.md`。
|
||||
- management是SIP配置唯一编辑/审批面。**现行 P1**通过批准的版本化静态制品和受控部署入口交付,D核验目标/准入屏障,Agent加载并报告;不要求在线发布控制面。静态交接合同须批准,旧直接写Agent面不能同时启用;成功必须证明精确快照已被Asterisk加载。
|
||||
- **本轮项目内 SIP 配置读取目标(现行外部运行未切换)**:management 仍是 SIP 唯一编辑/审批方,SaaS 仅经只读 HTTP 提供该 D 资源分区的获批全量快照;新加入/重启 D 先查询、核验所属 Agent/Asterisk 实际加载的 SIP 线路 revision 后才消费执行队列;Agent/Asterisk 的部署配置由受控部署确定,不来自 SaaS。后续约每60秒核对版本,有变化就关执行准入、排空旧活动通话并确认新版已加载;控制MQ照常处理。SaaS/management 分属不同配置系统时须证明SaaS分发的是同一份获批线路配置版本;不引入共享业务DB或MQ配置回退。项目内 SIP 读取及准入链路已用隔离 Mock 验证;真实 Agent/Asterisk 加载与 SaaS/management 切换尚未验证。真实 SaaS/management 兼容性及多 D 资源配额份额仍未验证、不属本轮验收,详见 `docs/architecture/Dispatcher有界接纳与控制通道改造计划_v0.1.md` §3.2。
|
||||
|
||||
## 安全和真实验证
|
||||
|
||||
- mock/mixed/real 明确隔离;Mock 默认隔离真实外网,正式模式拒绝 Mock/测试凭据,不静默回退。
|
||||
- 只允许复用既有 ASR 协议;禁止复用 `voice_test` 的 LLM/TTS。P1必须完成新LLM/TTS规范、SDK适配和本地/协议隔离验收;真实供应商联调延期第二阶段,不能以Mock冒充真实供应商通过,也不能把真实联调延期误写成当前 P1 已实测。
|
||||
- 真实外呼只允许原始号码 `15003164745`、`15830461047`,但白名单和文档不是拨号授权;每次真实验证仍需明确安排,且仅可在 Asia/Shanghai `09:00`–`20:00`(左闭右开)执行。每条 SIP trunk 对每个原始手机号每天最多 3 次;某条线路失败时可在额度内经当前会话确认后改测另一条线路,但不得在窗口外等待、自动延迟、在同一条线路/号码上超额、自动重试或静默换线。
|
||||
- 不把 SIP 白名单出口 IP 当作 SIP 服务端,不虚构备用线路,不逐呼重写共享配置,不自动重拨已接通/未知的执行。
|
||||
- 生产使用多机器、多 EIP 直连;1000 路指完整 ASR/LLM/TTS 已接通通话,N+1 与供应商能力须实测,不采用单 EIP+NAT。
|
||||
- 独立开发和测试不要求云账号。云创建、EIP 改绑、网络放行、供应商消费和测试资源清理必须另获明确授权;不得触碰无关资源。
|
||||
- 不在源码、配置样例、文档、日志或证据中保存密钥、密码、私钥、完整用户音频/对话;注入受控凭据,诊断端点仅管理网可达。
|
||||
- 旧 Python 与新 Go 不得同时写同一资源或各自发放共享额度。没有可验证的所有权/状态回迁方案就暂停切换,不以回滚镜像冒险重拨。
|
||||
- 项目是独立 Go module,工具链 Go **1.27.1**;普通构建、测试、运行不读取父项目业务模块、数据库、env 或夹具。标准库和成熟官方 SDK 优先,Cobra 显式 `agent`/`dispatcher`,单制品分角色/权限/目录。禁止自行重写 SIP/ARI、RTP/RTCP/G.711、WebSocket、AMQP、SQLite 驱动、OSS 签名及 SDK 已覆盖的 AI 协议;核验现有依赖能力后再新增库。生产原生 Asterisk 仍由独立 Cell 的 systemd 统一管理,不声称当前 Mock 已完成真实媒体或 1000 路容量验收。
|
||||
- ECS 优先 Debian 13(Trixie)minimal;只有阿里云北京无可用镜像时允许 Ubuntu 24.04 LTS。Asterisk 直接安装在承载 ECS 主机,由 systemd 启用自启动并核对 `enabled+active`;不得以前台进程或容器入口代替。
|
||||
- 开发、Mock、mixed、real 的**非生产主机**部署与诊断步骤默认强制,不因时间/旧环境/调用方参数跳过或静默降级;显式关闭即失败。每次新主机/版本/Cell 至少留存脱敏 ECS/EIP/网络只读核验、Debian/架构/磁盘/权限、`rogee` SSH 与加固、发布包/依赖 SHA-256、Asterisk/systemd `enabled+active`、ARI/PJSIP endpoint/contact、媒体 profile/端口及运行版本。
|
||||
- 非生产 mixed/real 呼叫必须先通过上述真实时间门禁;**拨号前**启动受限 SIP/RTP 抓包和 Asterisk PJSIP logger,结束后采集 SIP 响应/INVITE–BYE 时间线、SDP codec/媒体地址端口、RTP 包/字节、录音与 ASR/LLM/TTS 事实及 SHA-256。失败通话也保存状态和抓包;tcpdump/CAP_NET_RAW、PJSIP logger 或 ARI/PJSIP 状态任一不可用须失败关闭。原始抓包/日志/录音只写受限证据目录,聊天、提交与长期证据只存脱敏摘要/计数/状态码/hash,不含完整用户音频/对话或凭据。统一入口见 [`deploys/test/nonprod-call-evidence.sh`](deploys/test/nonprod-call-evidence.sh);本地 `make check` 与 `make release-check-local` **不能代签主机诊断或生产门禁**。
|
||||
- 当前完成前至少检查格式、当前合同和 Proto 来源/hash、`go vet ./...`、`go test -race ./...`、构建、确实运行的隔离 RabbitMQ/HTTPS/双向 TLS 端到端测试、业务单元覆盖率 ≥65% 及 A01–A12/K01–K16 对照。真实 SaaS/management/OSS/AI/Asterisk/ECS、第二节点/Cell/租户、多 D 额度、容量/N+1及生产切换必须另有事实与授权,任何本机 Mock 通过不得写成其签收。
|
||||
- 不自动提交/暂存/清理使用者在父项目或本项目的无关修改;并行开发仍须有可追溯 Git/合同基线、一 lane 一工作区/测试资源、无交叠写集合、合并后回归。本目标明确禁用子 Agent,不能以模型、fast 环境或外部服务不可用阻塞本地 Mock 目标。问题根因不明时补可观测性并诚实报告,不能用静默兜底伪装修复。
|
||||
|
||||
@@ -1,92 +1,28 @@
|
||||
# go-sip
|
||||
|
||||
Go SIP 调度与执行项目:同一 module/二进制通过 Cobra 提供 `dispatcher`、`agent` 两个业务子命令,分阶段替换 Python。现行**外部** SaaS↔Dispatcher 合同仍为 MQ-only;本轮**项目内本地 Mock** 目标为四条只读 HTTP GET、v3 MQ 及单份最终结果,其中只有任务发现改按 [`docs/thirds/v0.2.md`](docs/thirds/v0.2.md) §2.5,其他本地 SaaS 协议仍按 v0.1。项目内提案和 Mock 不代表 SaaS/management 已签收或上线。
|
||||
独立 Go SIP 调度与执行项目。单一 Go 1.27.1 module/制品通过 Cobra 显式提供 `dispatcher`、`agent` 两个业务子命令;当前业务启动只允许**隔离 Mock**,mixed/real 直接拒绝。目标是分阶段以 Go 替换 Agent,不重写 Asterisk,也不建立第二套 SaaS 管理后台。项目的源码、文档、依赖、构建、测试、配置和发布入口均在本仓库内。
|
||||
|
||||
> **当前状态:F00–F04、F08、F09 与项目内 Mock C 已完成本地适用验证;F06 的本地制品/拒绝门禁通过,真实部署和切换未执行。** P1 业务模块覆盖率均 ≥65%(MQ 须带 RabbitMQ 集成测试);CLI 和历史包未达线单独列为技术债,不宣称全仓达标。默认 Mock 不生成真实录音,上传成功/失败分支由隔离测试注入合成事实。真实 SaaS/MQ、供应商/ECS、Asterisk 媒体、生产切换及第二 Cell/第二租户仍属未验证或后续阶段;缺少 Asterisk/tcpdump 时部署 preflight 按要求 fail-closed,未冒充 mixed/real 通过。
|
||||
> 本项目已独立拆仓运营;源码、配置、依赖、迁移、测试、部署和文档均在此目录内维护。远程仓库为 `git.ipao.vip/rogee/go-sip`,本地 Git 默认分支为 `main`;真实外呼仍受逐次授权、capture-first、白名单和时间门禁约束。
|
||||
> **范围与进度:** [当前实施与验收入口](docs/plan-saas-dispatcher.md)记录 P01–P06 本地已验证、P07 文档/残留清理进行中、P08 最终 A01–A12/K01–K16 与 ≥65% 业务覆盖率对照待完成。隔离 RabbitMQ、双向 TLS/HTTPS、OSS PUT 与 AI Mock 的通过,不代表真实 SaaS、管理平台、MQ 应用收讫、OSS/AI 供应商、Asterisk/SIP/ECS、真实拨号或生产切换已验证;当前发布清单 `production_approval=false`。真实试拨另需逐次授权,并遵守白名单、Asia/Shanghai `09:00`–`20:00` 及拨号前诊断抓包门禁。
|
||||
|
||||
## 已确认的范围
|
||||
## 唯一当前接口
|
||||
|
||||
- 使用 **Go 1.27.1**、Cobra单项目双命令和同一发布制品;角色分进程、权限/目录分离。
|
||||
- 不接PG:Dispatcher独立SQLite统一任务/配额/outbox;Agent无业务数据库,文本/录音/必要恢复信息落文件。
|
||||
- 内部 **Unary gRPC**;Dispatcher配置Agent Endpoint列表,Agent业务启动只需Dispatcher Endpoint,证书/监听/本地资源通过部署提供。
|
||||
- 所有Agent共用mTLS证书、Dispatcher身份独立;需Endpoint主动激活/受限节点会话,不能把群组证书当单节点身份。
|
||||
- 本次以稳定、快速单节点上线为目标:**1 个 Agent、1 套 Asterisk、1 个单活 Dispatcher、单 Cell、至少 3 家独立 SIP trunk 的契约/协议 fixture、1 个内测商务租户**;双节点、第二 Cell、双租户延期第二阶段。
|
||||
- SIP 使用管理平台批准的不可变静态快照;维护窗口发布、排空和实际加载确认保留,在线动态发布/回滚编排暂缓。**现行真实路径**仍受 Asia/Shanghai 每日 `09:00`(含)至 `20:00`(不含)及白名单门禁约束;任务×线路时段与任务排除日期仅在本地 Mock V3 验证,不放开真实试拨。
|
||||
- 有适用开源库/官方 SDK 时强制复用,不从零手写 SIP/ARI、RTP、MQ、数据库、OSS 或 AI 协议客户端;选库失败先报告阻塞,不静默转自研。
|
||||
- 重写完整 Agent:调度控制面、Cell 外呼执行、ARI/RTP/录音、AI 流式适配、Cell 配置接收。
|
||||
- 分阶段迁移,最终构建、测试和运行不依赖 Python、父仓库目录或其它业务项目内部代码。
|
||||
- Asterisk 继续负责 SIP;独立 SIP 管理平台继续拥有配置管理权,均不纳入重写。
|
||||
- **外部运行基线与本地目标分开**:当前真实 SaaS↔Dispatcher 仍按已发布 MQ-only 合同工作。P1 本地目标按项目内契约采用四条只读 HTTP GET(SIP 全量、单任务含智能体、归属任务清单、按 `tenant_id` 取额度)和 v3 MQ 命令/控制/回执/唯一最终 `call.result`,移除对外 query/replay 及拆分通话事件。F01/F07 Schema、正反例、来源/hash 与 Mock C 已通过,F02–F04/F08/F09 本地验证见下文;外部兼容仍未验证,不扩为多 D 协调/HA。
|
||||
- **OSS配置存于Dispatcher配置文件,Agent向Dispatcher领取临时上传TOKEN后直传OSS,不保存长期凭据。** SaaS不下发OSS配置/TOKEN;D保留SDK签发能力,不转发文件。上传不申请SaaS会话、不等待verified/OSS ID或业务处理回复;D仅在原上传事实可靠进入指定持久MQ队列后记录交付完成。实时文字仍为 `transcript.updated`,归档不能替代实时事件。
|
||||
- 本次必须支持 **ASR-only** 与 **ASR + LLM + TTS** 两种模式;本阶段已完成本地/协议隔离双模式验收。百炼/火山ASR、OpenAI兼容LLM、火山TTS的真实供应商能力和生产参数联调仍标第二阶段/未启用,不能将 Mock 写成真实供应商通过;禁止复用旧LLM/TTS。
|
||||
- **现行 AI 配置**按任务 agent_version_id 经 MQ 向 SaaS 取得并持久绑定;过去独立的 AI GET 已废弃。**新目标**将获授权的智能体配置放入任务只读 HTTP 响应,不复活旧 GET 或保留 MQ 配置回退。 模型、提示词、音色/语速、识别、超时/打断等参数不写死;新版本用于新任务,无需重启,在途通话固定快照。静态SIP发布不代表AI配置静态硬编码。
|
||||
- 本轮验收范围收敛为单节点、单 Agent、单 Cell、单租户;保留 tenant_key 原值、独立队列、复合幂等和有界窗口。双节点、第二 Cell、双租户公平/背压/恢复不在本轮开发或验收范围,作为后续阶段。
|
||||
- 当前外部上传合同仍是 R12 临时授权、Agent 直传、R13 报告及 `recording.uploaded` 可靠入队。P1 本地目标改为每通话一份最终 `call.result`(含 `uploaded/unavailable/not_created`),不再发送拆分录音/实时文字/拒联事件;15 分钟收口、8 MiB 消息体上限及超限 outbox 阻塞已通过本地 Mock 验证,但未完成真实媒体、OSS 或 SaaS 应用签收。
|
||||
- [SaaS↔Dispatcher 通信说明](docs/thirds/saas-dispatcher.md);机器合同为 [`contracts/local/`](contracts/local/) 的 Schema、拓扑、正反例和来源/hash。SaaS 的 SIP、任务、归属任务清单、租户额度和 AI 供应商配置只经五类只读 HTTP;呼叫、控制、必要回执与每通话唯一结果只经固定 `v1` RabbitMQ 通信名。固定 HTTP `/internal/v1/dispatcher/...`、MQ `v1` 及业务 revision 是有效合同,不是旧实现代次。
|
||||
- Dispatcher 独立 UUID/资源归属、SaaS 预建的控制/任务队列、共享持久结果队列及本地 SQLite 权威任务/额度/inbox/outbox;未知通话不释放占用、不重拨、重启继续原消息身份。Agent 与 Dispatcher 通过双向 TLS Unary gRPC 和预绑定身份/会话代际交互,业务恢复落私有文件。内部联系见 [`proto/agent/agent.proto`](proto/agent/agent.proto)。
|
||||
- 任务内不可变获批 AI 参数支持 ASR-only 与 ASR+LLM+TTS;录音经短期授权由 Agent **一次** HTTPS PUT 至 OSS,明确失败才按受控文件恢复,结果未知不自动再传,最终事实进入 MQ。批准 Mock 的 SIP revision 回报不证明 Asterisk 已实际加载。
|
||||
- [`docs/plan-saas-dispatcher-v05-v0.1.md`](docs/plan-saas-dispatcher-v05-v0.1.md) 保持原字节和来源 hash,**只作为当前机器合同的历史来源**,不是另一个运行计划;更早的 F/W/v0.1–v0.4、旧 MQ-only 与部署示例在历史文档或 [`docs/archive/`](docs/archive/) 中追溯,不作为运行回退。
|
||||
|
||||
## 当前本地实现
|
||||
|
||||
旧 MQ-only 基线的身份隔离、配置、回执、控制、AI授权及上传通知有 loopback RabbitMQ 本地证据,见 `docs/evidence/20260922-mq-only-local-final.md`;该证据不代签新目标。本轮项目内结果分别见 [F03 v0.3/F09](docs/evidence/f09-local-acceptance-v0.3.md)、[F04](docs/evidence/f04-local-dial-policy-v0.1.md)、[F08](docs/evidence/f08-local-final-result-v0.1.md) 和 [F06 本地发布阻断](docs/evidence/f06-local-release-gates-v0.3.md);[F03 v0.2](docs/evidence/f03-local-task-discovery-v0.2.md) 只留作历史。部署 preflight 在缺失 Asterisk/tcpdump 时明确失败并保留日志;本地测试不等同真实 SaaS、供应商或生产验收。
|
||||
|
||||
- `contracts/upstream/` 嵌入项目内自包含 W01 基线,记录父源 commit、dirty 继承和 SHA-256;运行时代码读取该包,不读取父目录。
|
||||
- `internal/store/` 提供 SQLite inbox、任务、租户/跨 Cell 配额、控制 CAS、replay 和 outbox 事务。
|
||||
- `internal/agent/` 只使用文件保存执行状态、transcript、录音/资产和崩溃恢复信息;boot 不释放未知占用;录音通过 Dispatcher 授权的短期 Alibaba OSS presigned PUT 直传,上传尝试和通知恢复分别持久记录,失败/过期保留源文件,不自动续期或重新PUT。
|
||||
- `internal/ai/` 对固定 AI Schema 做不可变快照校验,支持项目内显式 `full_ai`/`asr_only` 分支;`mock_pipeline` 只用于隔离协议/取消/参数测试,不宣称真实供应商已启用。
|
||||
- 旧 `internal/control/` HTTP业务实现、启动入口、CLI参数及环境配置已删除,不保留兼容通道。
|
||||
- `internal/rpc/` 提供 `agent.v1` Unary handlers、mTLS TLS1.3 配置、会话世代/fencing、CAS、permit/fact/upload metadata 边界;Agent CLI 可选启动受证书保护的 gRPC listener,并校验静态 Cell 制品与 AI 授权边界。`internal/calllog/` 提供按手机号 HMAC 关联、掩码和 allow-list JSONL 外呼业务日志,不写原始号码、凭据、音频、转写或 prompt。
|
||||
- `internal/health/` 使用 gopsutil 采样主机/进程资源;媒体端口和 AI 配额未接入时明确报告 unknown。`internal/mq/` 默认 bounded prefetch=1、per-tenant DLQ 和 publisher confirm;`make mq-integration-local` 只启动 disposable RabbitMQ。
|
||||
- `make acceptance-local` 校验当前项目内合同、格式、race/vet/build 和受限 RabbitMQ 本地矩阵;不访问真实服务。`make release-check-local` 构建并校验一次性本地制品与归档包、v0.1 业务/v0.3 发现/v3 队列草案和 Proto 的版本/hash,验证已有制品、打包目录、归档及校验文件均不会被覆盖,且 CLI 旧开关不存在、mixed/real 制品在打开资源前拒绝。`make release` 仅允许在 `dist/` 下指定**尚不存在**的目标目录,记录 dirty-source 与版本/hash,始终标记 `production_approval=false`;两者均不部署或拨号。真实 OSS 授权测试仍须另用受控环境显式开启,不能从 Mock 或上述制品检查推定通过。
|
||||
- 直接依赖版本/本地许可证清单见 [`docs/evidence/20260918-dependencies.md`](docs/evidence/20260918-dependencies.md);门禁结论见 [`docs/evidence/20260918-acceptance-matrix.md`](docs/evidence/20260918-acceptance-matrix.md);SIP 注册/认证/From/PAI/前缀/选路对比见 [`docs/evidence/20260919-sip-routing-implementation-comparison.md`](docs/evidence/20260919-sip-routing-implementation-comparison.md),手机号业务日志边界见 [`docs/evidence/20260919-phone-call-business-log.md`](docs/evidence/20260919-phone-call-business-log.md)。
|
||||
|
||||
以上 20260918–20260922 的历史证据只覆盖旧基线;本轮新合同、Mock C 和 F03–F09/F06 的本地证据单独列在前文。两组证据都不等于真实供应商、生产 SaaS/MQ receipt、实际切换或第二阶段拓扑通过。范围和延期项见 [`docs/evidence/20260920-scope-amendment.md`](docs/evidence/20260920-scope-amendment.md)。
|
||||
|
||||
## 显式重新申请上传授权
|
||||
|
||||
仅对已有失败或结果未知的上传使用:
|
||||
## 本地验证(不触碰真实线路)
|
||||
|
||||
```sh
|
||||
sip-go-agent agent upload-retry --spool /path/to/agent-spool \
|
||||
--upload-id '<原上传ID>' --request-id '<新的小写UUID v4>' \
|
||||
--file '/path/to/retained-recording.wav'
|
||||
make check # 格式、Proto、当前合同/历史来源、race、vet、构建、三项实际运行的隔离 MQ 集成测试
|
||||
make release-check-local # 本地制品、hash、当前拓扑、Mock-only/不覆盖既有文件的包检查
|
||||
```
|
||||
|
||||
该命令使用既有Dispatcher端点/mTLS部署配置,不发起呼叫。请求ID必须由调用方显式提供;每个ID最多一次PUT,已成功上传的文件只恢复通知,不能再次PUT。重复旧请求不会获得续期TOKEN。`completed` 只表示指定持久MQ队列已接收原通知,不表示SaaS已处理。使用前仍需满足对应环境的统一部署与诊断要求。
|
||||
结果、重启与故障场景及未验证项见 [`docs/evidence/saas-dispatcher-implementation.md`](docs/evidence/saas-dispatcher-implementation.md)。本地检查不等于非生产主机验收:任何实际新主机/版本/Cell 验证须执行 [`deploys/test/nonprod-call-evidence.sh`](deploys/test/nonprod-call-evidence.sh) 规定的资源、Asterisk/systemd、ARI/PJSIP 与媒体诊断;mixed/real 外呼还须在拨号**之前**启动受限 SIP/RTP 抓包和 PJSIP logger。当前 Mock-only 制品不能启用 mixed/real,更不能因白名单和样例自动发起真实呼叫。
|
||||
|
||||
## 文档
|
||||
## 导航
|
||||
|
||||
文档目录总览见 [`docs/README.md`](docs/README.md)。后续 Agent 先读[本轮配置读取与有界外呼计划](docs/plan-config-read-v0.1.md),按 F 工作包确认 C/L/M 和 I/M/G 前置及权威合同;原 [plan-0918](docs/archive/plan-0918.md) 恢复原文归档,仅供追溯。并行开发按新计划§9登记单写范围、隔离工作区/测试资源和合并回归,由集成负责人统一维护§8总台账;开发子Agent固定使用 **gpt-5.6-luna+max+fast**,不可用时报告阻塞,不静默降级。本轮未启动开发子Agent。
|
||||
- [当前实施与 A01–A12 验收](docs/plan-saas-dispatcher.md) · [当前通信合同](docs/thirds/saas-dispatcher.md) · [当前机器合同](contracts/local/manifest.json) · [可复核本地证据](docs/evidence/saas-dispatcher-implementation.md)
|
||||
- [文档索引](docs/README.md) · [物理部署及独立 Asterisk 约束](deploys/README.md) · [项目开发与安全约束](AGENTS.md)
|
||||
|
||||
| 文档 | 内容 |
|
||||
| --- | --- |
|
||||
| [本轮配置读取与有界外呼计划](docs/plan-config-read-v0.1.md) | 首读入口:F00–F09、C/L/M 与 I/M/G 门禁、单写/验证状态;四条只读 GET 的外部合同仍待签收 |
|
||||
| [任务发现事件游标计划](docs/plan-0926.md) | v0.3 项目内合同、运行与本地 Mock 范围;外部顺序、墓碑容量和切换另行签收 |
|
||||
| [旧 plan-0918 归档原文](docs/archive/plan-0918.md) | W00–W16 历史状态及旧 MQ-only 阶段证据;非本轮执行入口 |
|
||||
| [Go重写方案 v0.3](docs/architecture/Go重写方案_v0.3.md) | 本次单节点/单 Cell/单租户目标、至少3 SIP fixture、双AI模式、P0/P1/第二阶段分期 |
|
||||
| [通信与事件数据交互 v0.1](docs/contracts/通信与事件数据交互_v0.1.md) | 首发Unary、静态SIP与双模式、§6.1–6.3 SaaS配置来源/参数矩阵/安全边界 |
|
||||
| [SaaS↔Dispatcher 第三方对接顺序](docs/thirds/第三方对接事件与请求消费顺序_v0.1.md)、[任务发现 v0.3](docs/thirds/v0.3.md) | 仅任务发现按 v0.3 项目内修订;[v0.2](docs/thirds/v0.2.md) 是历史,其余项目内 SaaS 协议仍用 v0.1;外部合同/取消查询补传仍待签收 |
|
||||
| [现行 MQ 机器契约](contracts/upstream/v1/mq.schema.json)、[Agent Proto](proto/agent/v1/agent.proto) | 现行消息和Unary字段权威;HTTP配置仅有项目提案 |
|
||||
| [OpenAPI与MQ字段索引 v0.1](docs/references/OpenAPI与MQ字段索引_v0.1.md) | 旧源只读提取42个HTTP操作/115个组件及哈希;不代表新MQ-only入口,不手改生成物 |
|
||||
| [deploys:物理机 systemd 发布包](deploys/README.md) | 锁定 Debian 13/Go 1.27.1/发布版本,构建并上传不依赖 Docker 的 Agent/Dispatcher 安装包 |
|
||||
| [验证与切换验收 v0.3](docs/acceptance/验证与切换验收_v0.3.md) | 10个首发汇总门禁、88项基线按阶段适用、P2公平性及独立容量验收 |
|
||||
| [开源组件选型与复用清单 v0.2](docs/dependencies/开源组件选型与复用清单_v0.2.md) | §1.3首发基础库/AI SDK选择,§4.3参数能力及锁版/许可/PoC门禁 |
|
||||
| [G0开发准备与契约冻结方案 v0.1](docs/architecture/G0开发准备与契约冻结提案_v0.1.md) | 原D01–D10方向已确认;MQ-only新增GAP-10及受影响G0须重新验证,真实外部发布/生产联调另行安排 |
|
||||
| [AGENTS.md](AGENTS.md) | 本独立子项目的开发与安全约束 |
|
||||
|
||||
## 独立项目原则
|
||||
|
||||
- 当前设计文档以本目录 `docs/` 为唯一维护位置,不再向父项目另存一份。
|
||||
- 对接协议的现有权威来源仍属于上游;后续在本项目导入带来源、版本和 SHA-256 的不可变契约发布包,不能另写一套同名 Schema。
|
||||
- 后续发行包、CI、数据库和运行配置独立。不能靠 `../agent_call`、`../management`、`../sip_mock_server` 或父项目环境文件运行。
|
||||
- 业务代码范围仅包括 SIP Agent/Dispatcher 与 Asterisk;RabbitMQ、OSS、AI 供应商及 SaaS API 是 SaaS 提供的基础设施,不在本项目生产包中部署。独立集成测试使用自有隔离数据库、RabbitMQ 和契约 fixture;OSS数据面复用官方SDK/标准HTTP,D按自身配置文件提供临时TOKEN,A直传且不持有长期AK/SK;不申请SaaS上传会话,不等待SaaS校验或业务处理;外部 SIP Mock 只能以固定镜像及版本化协议接入,不导入其源码。
|
||||
- 真实外呼、云创建、供应商调用和消费授权均是独立门禁,不能由测试成功或本文档自动授权。
|
||||
|
||||
## 旧阶段基线与本轮入口
|
||||
|
||||
以下为旧阶段的原有分期记录;四条只读 HTTP GET(配置、任务发现、租户额度)、有界消费和时段改造的新依赖、状态与门禁以[本轮计划](docs/plan-config-read-v0.1.md)为准。
|
||||
|
||||
1. **P0:先完成MQ-only新合同(GAP-10)。** 冻结D唯一ID/生命周期、独立Topic/队列/绑定、全部请求响应/关联/错误/期限及Unary异步衔接;旧包原样保留。其余已有基线按受影响范围重新验证,包括8种事件payload、双AI模式(GAP-08)、SaaS任务AI配置读取/调参(GAP-09)、首发Unary职责、单 Cell 静态快照来源/加载回执、D配置文件/临时上传TOKEN及上传通知可靠入队和至少3家SIP trunk的配置/协议 fixture。只核验实际采用的SDK;火山TTS参数覆盖、精确版本/许可证未核验前不宣布锁库,不等待未来动态发布/文本OSS归档合同。
|
||||
2. **P1:本次单节点内测上线。** 完成单 Cell、单租户、双模式、幂等/控制/配额/恢复/录音安全的本地/隔离闭环;真实 ECS、真实外呼、生产 SaaS/MQ 联调不作为本阶段前置。
|
||||
3. **第二阶段:** 真实 SaaS/MQ 对接、RabbitMQ ACL/TLS及适用的业务回执、真实供应商/ECS 联调,以及双节点、第二 Cell、第二租户公平调度。
|
||||
4. **后续另立项:** 在线动态发布、自动跨供应商FALLBACK、多Dispatcher HA/分布式配额、权重借用、文本OSS归档、1000路完整AI/N+1。既有call/command整体补传不是通用回放平台,当前单节点首发仍保留。
|
||||
|
||||
阶段目标详见主方案§1/§10,首发验收见验收方案§1.1–§1.2;文件名保持不变。旧 MQ-only 本地门禁见[归档计划 §8.2](docs/archive/plan-0918.md)和`docs/evidence/20260922-mq-only-local-final.md`;本轮新目标仅按[新计划 §8](docs/plan-config-read-v0.1.md)记状态;真实依赖、供应商、云/拨号、生产receipt、容量和切换仍属第二阶段,归档旧证据见 `docs/archive/evidence/20260920-local-p1-acceptance.md`。
|
||||
现存 SQLite、spool、outbox 与 Agent 恢复文件不自动清空或迁移;发现旧状态拒绝启动并保留原文件,必须先厘清未交付事实。仓库不保存真实密钥、完整用户音频或完整对话。
|
||||
|
||||
@@ -1,5 +1,7 @@
|
||||
# Physical production deployment
|
||||
|
||||
This is the **target host layout**, not an approved deployment of the current binary. The current business commands are isolated Mock-only and reject mixed/real before opening resources; the local release manifest has `production_approval=false`. Neither the steps below nor a local package/check authorize real services or calls. Native Asterisk loading and required non-production diagnostics still need separate evidence.
|
||||
|
||||
Production is a small systemd installation on Debian 13 amd64:
|
||||
|
||||
1. native Asterisk Cell (`asterisk.service`), owned by the approved SIP
|
||||
|
||||
+15
-37
@@ -1,47 +1,25 @@
|
||||
# 文档导航
|
||||
|
||||
`docs/` 是本项目唯一的设计、契约、决策和验证文档目录。
|
||||
`docs/` 是本项目设计、合同、决策和验收事实的维护目录。以下入口以**当前项目内隔离 Mock 合同**为准;真实 SaaS/management、供应商、线路、ECS 和生产切换仍未签收。
|
||||
|
||||
## 首读顺序
|
||||
|
||||
1. [`plan-config-read-v0.1.md`](plan-config-read-v0.1.md):四条只读接口、任务发现、有界消费及外呼时段的 F00–F09/F06 执行入口、C/L/M 和 I/M/G 门禁;任务发现 v0.3 另读 [`plan-0926.md`](plan-0926.md)。原 [`plan-0918.md`](archive/plan-0918.md) 按 HEAD 原文归档,仅作旧 W00–W16 历史。
|
||||
2. [`architecture/Go重写方案_v0.3.md`](architecture/Go重写方案_v0.3.md):单节点、单 Cell、单租户的总体方案与分期。
|
||||
3. [`contracts/`](contracts/):SaaS、Dispatcher、Agent、RabbitMQ 和 OSS 的项目内契约。
|
||||
4. [`acceptance/验证与切换验收_v0.3.md`](acceptance/验证与切换验收_v0.3.md):验收门禁、证据要求和第二阶段边界。
|
||||
5. [`evidence/f09-local-acceptance-v0.3.md`](evidence/f09-local-acceptance-v0.3.md) 和 [`evidence/f06-local-release-gates-v0.3.md`](evidence/f06-local-release-gates-v0.3.md):任务发现当前项目内 Mock 与发布阻断证据;[`20260922-mq-only-local-final.md`](evidence/20260922-mq-only-local-final.md) 仅作旧 MQ-only 本地基线。
|
||||
1. [`plan-saas-dispatcher.md`](plan-saas-dispatcher.md):P01–P08 当前实施进度、A01–A12/K01–K16 验收与未验证边界。
|
||||
2. [`thirds/saas-dispatcher.md`](thirds/saas-dispatcher.md):唯一现行 SaaS↔Dispatcher 项目内通信说明,五类只读 HTTP、固定 `v1` MQ、归属、控制、唯一结果与上传恢复。
|
||||
3. [`../contracts/local/manifest.json`](../contracts/local/manifest.json) 与 [`../contracts/local/`](../contracts/local/):唯一当前机器 Schema、拓扑、正反例和不可变来源/hash;内部 Agent RPC 见 [`../proto/agent/agent.proto`](../proto/agent/agent.proto)。Markdown 不代替机器校验。
|
||||
4. [`evidence/saas-dispatcher-implementation.md`](evidence/saas-dispatcher-implementation.md):本地测试、故障/重启与未验证项的可核查证据。
|
||||
5. [`../AGENTS.md`](../AGENTS.md):本独立项目开发、SIP、部署、真实呼叫与诊断约束。
|
||||
|
||||
## 按职责查找
|
||||
## 其它文档
|
||||
|
||||
### 方案与范围
|
||||
|
||||
- [`architecture/Go重写方案_v0.3.md`](architecture/Go重写方案_v0.3.md):产品范围、运行边界和阶段目标。
|
||||
- [`contracts/通信与事件数据交互_v0.1.md`](contracts/通信与事件数据交互_v0.1.md):通信、事件、AI 配置和上传边界。
|
||||
- [`architecture/G0开发准备与契约冻结提案_v0.1.md`](architecture/G0开发准备与契约冻结提案_v0.1.md):D01–D10 方向及 G0 前置。
|
||||
- [`dependencies/开源组件选型与复用清单_v0.2.md`](dependencies/开源组件选型与复用清单_v0.2.md):组件、SDK、版本和 PoC 门禁。
|
||||
- [`references/OpenAPI与MQ字段索引_v0.1.md`](references/OpenAPI与MQ字段索引_v0.1.md):旧源只读索引,不是当前 MQ-only Schema。
|
||||
- [`references/saas-page-snapshot-analysis.md`](references/saas-page-snapshot-analysis.md):SaaS 页面可见字段盘点;其中旧 MQ 配置建议已被新目标取代,非契约/验收证据。
|
||||
|
||||
### 契约与决策
|
||||
|
||||
- [`thirds/第三方对接事件与请求消费顺序_v0.1.md`](thirds/第三方对接事件与请求消费顺序_v0.1.md):SaaS↔Dispatcher 的项目内配置与 MQ 业务契约;仅其中旧 §2.5 任务发现已由 [`thirds/v0.3.md`](thirds/v0.3.md) 项目内合同替换,[`v0.2`](thirds/v0.2.md) 为历史。取消对外查询/补传及分散事件仍待外部签收。
|
||||
- [`../contracts/upstream/v1/mq.schema.json`](../contracts/upstream/v1/mq.schema.json)、[`event-payloads.schema.json`](../contracts/upstream/v1/event-payloads.schema.json)、[`mq-topology.json`](../contracts/upstream/v1/mq-topology.json):现行 MQ 信封、事件正文、路由的机器契约。
|
||||
- [`contracts/config-read-fields-v0.1-proposal.md`](contracts/config-read-fields-v0.1-proposal.md):两只读接口字段来源、响应结构与项目自拟 Schema/Mock 示例;**不是现网 SaaS JSON 或正式合同**。
|
||||
- [`decisions/`](decisions/):已记录的关键技术决策。
|
||||
|
||||
### 证据
|
||||
|
||||
- [`evidence/README.md`](evidence/README.md):证据与开发文档的职责边界、保留和归档规则。
|
||||
- `evidence/` 保存可复核的运行事实、测试结果和边界说明;历史证据不因当前契约变化而改写。
|
||||
- 旧 MQ-only 本地结论见[归档计划 §8.2](archive/plan-0918.md)和 [`20260922-mq-only-local-final.md`](evidence/20260922-mq-only-local-final.md);**本轮新方向的状态只在[新计划 §8](plan-config-read-v0.1.md)登记**。
|
||||
- 证据中的 `mock`、`mixed`、`real` 必须按原记录理解;本地或隔离通过不等于真实 SaaS、供应商、生产或容量验收通过。
|
||||
|
||||
### 归档
|
||||
|
||||
- [`archive/`](archive/) 保存已被当前基线替代、但仍需保留追溯价值的文档,包括恢复原文的[旧总计划](archive/plan-0918.md),以及无项目归属的旧参考资料。
|
||||
- 归档文件不作为当前实现、契约或验收依据;需要引用历史事实时必须使用归档路径。
|
||||
- [`architecture/`](architecture/) 保存产品方案、边界与阶段背景;[`decisions/`](decisions/) 保存设计决定;[`contracts/`](contracts/) 是原有合同和提案记录,当前机器约束以 `../contracts/local/` 为准;[`acceptance/`](acceptance/) 保存跨阶段验收基线,须按本轮单节点/单 Cell/单租户范围核对。
|
||||
- [`plan-saas-dispatcher-v05-v0.1.md`](plan-saas-dispatcher-v05-v0.1.md) 是**不可变历史来源**:原文件路径和 SHA-256 被当前合同 `manifest.json` 引用,必须保持原字节,不是第二个当前运行计划。旧 [`plan-config-read-v0.1.md`](plan-config-read-v0.1.md)、[`plan-dispatcher-state-v0.1.md`](plan-dispatcher-state-v0.1.md)、[`plan-0926.md`](plan-0926.md)、`thirds/v0.1–v0.4` 和上游 MQ-only v1 只供追溯旧事实,不能覆盖当前项目内合同,也不能作为兼容回退。
|
||||
- [`archive/`](archive/) 保存旧 W/F 工作包、旧部署样例和上一版 AGENTS 原文等历史事实;[`archive/plan-0918.md`](archive/plan-0918.md) 是旧 W00–W16 原文,不是现在的执行入口。归档说明不能代签真实验收。
|
||||
- [`evidence/README.md`](evidence/README.md) 说明历史证据保留规则;旧本地结果仍按当时环境和版本解读,不能据此推断当前合同或真实供应商已通过。
|
||||
- [`../deploys/README.md`](../deploys/README.md) 为 Mock-only 本地发布及物理环境要求,实际新主机/版本/Cell 诊断与拨号前受限抓包见 [`../deploys/test/nonprod-call-evidence.sh`](../deploys/test/nonprod-call-evidence.sh)。本地包检查不替代真实 Asterisk 加载或生产审批。
|
||||
|
||||
## 维护规则
|
||||
|
||||
- 不在 `docs/` 复制上游 Schema;上游契约包、生成物和字段索引保持单一来源。
|
||||
- 不把证据摘要改写成新的通过结论;范围、环境和未执行项必须保持可追溯。
|
||||
- 新增文档先归入方案、契约、决策、证据或归档中的一个明确类别;根目录 `plan-config-read-v0.1.md` 是总执行入口,用户指定的 `plan-0926.md` 仅说明 v0.3 任务发现分项,不另设第二个总台账;不新增无类别根文件。
|
||||
- 不在文档中维护第二套 Schema,不改写已被来源/hash 固定的原文;新增当前字段先更新机器合同及正反例,再更新当前说明与来源记录。
|
||||
- 当前状态只在 `plan-saas-dispatcher.md` 与实施证据中维护;历史文件保留真实来源和阶段,不为消除旧名称而重写归档或受保护的使用者修改。
|
||||
- 报告须区分本地隔离 Mock、真实非生产和生产,注明哪些测试未执行。源码、样例、日志、证据均不得保存真实凭据、完整用户音频或完整用户对话。
|
||||
|
||||
@@ -0,0 +1,194 @@
|
||||
# go-sip:独立项目约束
|
||||
|
||||
## 宪法
|
||||
|
||||
- 任何涉及文件的调研或修改,如果当前是 git 仓库,需要先同步远程提交到本地,避免调研过时问题。
|
||||
- 基于 TDD 进行功能的开发与业务变更,单元测试覆盖率要保证 65% 以上
|
||||
- 任何时候我提出任何需求均需要理解并**结构化复述后与我进行确认,避免理解偏差**。
|
||||
- 不要在代码里藏兜底逻辑来吞掉错误、隐藏问题。出了问题就应该让它爆出来,否则你永远找不到真实问题。
|
||||
- 当一个问题出现时,不要用各种 small fix、针对性补丁来掩盖它。**必须定位真实根因,彻底修复**。在 bug 上糊纸只会让系统积累你不知道的危险暗病。
|
||||
- 即使问题很难定位,也**绝不要偷懒做表面修复**。应该给项目增加充分的日志和可观测性,保证下次问题再现时你有足够信息去定位。问题无法修复时,只需要诚实告诉我信息不足、需新增日志,不要假装修好了。
|
||||
- 始终注意在关键路径上给自己留足排查日志,确保每一个**关键节点都是可追溯**的。
|
||||
- 当项目关键技术栈或产品方向发生变更时,同步更新 agents.md。文档必须随代码一起演进,不能让它变成过时的谎言。
|
||||
- 大规模重构或实验性改动前,必须先切新分支。
|
||||
|
||||
- 不以维护向后兼容性为目标。**对于已经废弃的代码路径,应直接移除**,不再通过兼容层、回退机制或迁移方案予以保留。
|
||||
- 在充分满足当前需求的前提下,采用**尽可能简单的实现方案**。避免引入缺乏实际需求依据的抽象、配置项和间接层。
|
||||
- **采用渐进式、分层的方式构建系统**。首先完成能够端到端运行的最小版本,再基于稳定可用的产品逐步增加功能。不要以尚未成熟的复杂性取代已经可用的产品。
|
||||
- **保持组件的模块化**,并明确划分不同职责与关注点。
|
||||
- 当成熟且维护良好的库能够降低整体复杂度或提高可靠性时,应优先采用。除非有明确理由,不要重复实现通用功能。
|
||||
- 在自行实现功能或新增依赖之前,应优先评估项目现有依赖的能力。应先查阅相关文档和类型定义,不应未经确认就认定某个库不具备所需能力。
|
||||
- 架构决策**应着眼于长期演进**。不要采用仅能解决当前问题、且预期需要在后续替换的权宜方案。
|
||||
- 在设计解决方案之前,**先研究成熟产品如何解决同类问题**。优先采用经过验证的模式和约定,避免从零开始另行设计一套方案。
|
||||
|
||||
## 禁止清单(不主动考虑、不主动提议、不实现,遇到只记入 TODO 技术债列表)
|
||||
|
||||
1. 法律合规:商业库授权、开源协议合规、GDPR/个保、隐私政策(法务负责)。
|
||||
2. 依赖安全:NPM 及第三方包漏洞、安全补丁、依赖升级策略。
|
||||
3. 访问安全:服务只需支持局域网访问(host 绑定 0.0.0.0 即可),不考虑公网暴露、HTTPS、认证/权限体系(登录、RBAC)、限流、防爬、数据加密、审计日志。
|
||||
|
||||
## 红线清单(快速阶段也不能省,现在便宜、以后极贵)
|
||||
|
||||
1. 数据模型/表结构:认真设计,建表慎重——改表成本远高于写代码。
|
||||
2. 目录结构与模块边界:保持简单清晰,不堆一坨代码。
|
||||
3. 基础错误日志:出错时至少能看到发生了什么。
|
||||
4. Git:小步提交,保持历史清晰。
|
||||
5. 基础输入校验:仅防止程序崩溃,不做安全加固。
|
||||
6. 环境差异配置(端口、地址等)与代码分离(.env 或配置项)。
|
||||
|
||||
## 沟通方式
|
||||
|
||||
- 向使用者回报时,使用清楚直白的语言说明做了什么、结果如何。最终回复禁用术语、技术实现细节与工程腔。写法是:对一个聪明但没在看代码的人解释。
|
||||
|
||||
- 实际执行过程(思考、规划、写程序、除错、解决问题)保持完整的技术严谨度,这条规范只适用于对使用者的沟通方式。
|
||||
|
||||
## 回复风格
|
||||
|
||||
- 只写结论、实际改动、原因、验证结果
|
||||
- 不描述推进动作,禁用「我先……再……」等叙述句式
|
||||
- 不使用工程汇报腔(「落地」「落到」「推进」等类似用语)
|
||||
- 直接、专业、去表演化
|
||||
- 回复文字永远使用与对方相同的语系,专有名词维持英文
|
||||
- 不使用口语化表达,说重点,简单明了
|
||||
- 需要时搭配条列式与表格加强输出可读性
|
||||
|
||||
## 决策规则
|
||||
|
||||
- 当方案有多个选项时,列出每个选项的优缺点,并明确指出推荐选项与原因,先问我。
|
||||
- 有多种实现方式时,选最简单能跑通的。
|
||||
- 遇到"禁止清单"中的问题:不展开、不实现,追加到 TODO 技术债列表即可。
|
||||
|
||||
## Sub-Agent 使用时机
|
||||
|
||||
当任务符合以下任一条件时,直接 spawn sub-agent 分工执行,无需询问使用者:
|
||||
|
||||
- 任务可拆分为多个**平行且无依赖**的子任务
|
||||
- 各子任务职责明确分离,合并执行会造成 context 混杂
|
||||
- 大量结构相同的重复性任务(可用 `spawn_agents_on_csv` batch 执行)
|
||||
- 各子任务需要不同的 model 配置或 sandbox 权限,例如:
|
||||
|
||||
- 探索型任务使用轻量 model + `read-only` sandbox
|
||||
- 审查型任务使用高推理 model + `read-only` sandbox
|
||||
- 修改型任务使用执行导向 model + `workspace-write` sandbox
|
||||
|
||||
## 验证标准
|
||||
|
||||
开始任务前先定义完成标准。交付前依此验证,发现问题就修好再测,不把未完成的工作交回给使用者。只有确认完成,或遇到真正需要使用者介入的障碍时,才回报。
|
||||
|
||||
## 当前范围
|
||||
|
||||
- 后续Agent必须先读 **`docs/plan-dispatcher-state-v0.1.md`** 和 **`docs/thirds/v0.4.md`**;历史 F 工作包索引见 `docs/plan-config-read-v0.1.md`:按 F 工作包/文档索引读取需求与契约,确认 C/L/M 和 I/M/G 前置、授权及写入边界后实施;并行时按该计划§9认领,子Agent只写独占模块/证据,§8本轮总台账、公共文件及合并状态由集成负责人单写。已恢复原内容的 `docs/archive/plan-0918.md` 仅保留旧 W00–W16 历史,不是现行计划入口。本地 Dispatcher v0.4 任务发现、MQ 控制及外呼入站规则另读 `docs/plan-dispatcher-state-v0.1.md`、`docs/thirds/v0.4.md`;`docs/plan-0926.md`、`docs/thirds/v0.3.md` 及 v0.2 状态仅作历史。**v0.4 的 Schema、隔离 Mock 与代码已在项目内实施,真实 SaaS/management 尚未签收或联调;仅显式条件清理已终止任务的任务配置副本,不自动清除现有 SQLite 数据。没有 SaaS 应用收讫的执行、幂等及 outbox 记录继续保留。日志不得记录密钥、完整音频或对话。** 计划不替代权威Schema或验收,不重复审批已确认方向,不自动授权真实云/付费/拨号。
|
||||
- 当前MQ-only/OSS调整目标已获用户明确批准由当前Agent独立执行,**不启动子Agent**,不得再以子Agent模型/fast环境阻塞本目标;此前按任务类型自动分工规则在本目标不适用。若未来另获启动授权,仍遵守下条模型要求。
|
||||
- 用户指定:若启动开发及配套审查子Agent,固定 **gpt-5.6-luna、max思考、fast模式**。启动前查询精确provider/model和runner支持并显式配置(当前工具用模型`:max`后缀及`fast: true`,不继承默认);不可用/不支持/无法核验则报告阻塞,不静默换模型、降思考档、关fast或换CLI。此为后续执行约束,本轮仅修复计划,未启动开发子Agent。
|
||||
- 并行开发须先有获授权的可追溯Git/契约基线、一lane一工作区/测试资源、无交叠写集合及每批合并后回归;当前子项目尚未跟踪的文件不能假定存在于HEAD/worktree。不得自动提交、暂存或清理父项目无关改动;详情见 `docs/plan-config-read-v0.1.md` §9。
|
||||
- 当前已获授权进行本项目开发:W01 项目内契约基线和 W02 Proto/stubs 已建立;仍不能把设计、Mock、Proto或88项测试清单写成真实供应商/生产验收已通过。入口和权威依据仍为 `docs/architecture/Go重写方案_v0.3.md`、`docs/acceptance/验证与切换验收_v0.3.md`、`docs/contracts/通信与事件数据交互_v0.1.md`、`docs/references/OpenAPI与MQ字段索引_v0.1.md`、`docs/dependencies/开源组件选型与复用清单_v0.2.md`。
|
||||
- 开发准备见 `docs/architecture/G0开发准备与契约冻结提案_v0.1.md`:D01–D10的方案方向、双模式/许可/恢复机制及内部PoC初始profile已获用户确认;本项目已自行交付 W01/W02 开发基线,但外部权威发布、真实预算、供应商签收和 G0/PoC 仍需分别验证,不能混写为生产合同。缺失字段细节、实际预算及方案变更另行确认。本轮验收基线收敛为单节点/单 Agent/单 Cell/单租户;双节点、第二 Cell、第二租户及其公平/故障矩阵不在本轮开发或验收范围,跨 Cell/多租户能力保留为后续阶段。
|
||||
- 用户已确认完整 Go Agent、分阶段替换:调度、Cell 执行、ARI/RTP/录音、AI 流及 Cell 配置接收。最终没有 Python 运行依赖;不重写 Asterisk、不实现第二套管理后台。
|
||||
- 本项目已独立拆仓运营,源码、文档、依赖、配置、迁移、测试、部署、发布入口全部留在本目录。普通构建/测试/运行不读取父目录,不使用其它项目内部模块、环境文件或夹具,不共享其业务数据库。
|
||||
- 当前已初始化独立 Git 仓库并绑定公开远程 `git.ipao.vip/rogee/go-sip`;未经授权不要重新 `git init`、改为 submodule、移动历史或更改父仓库跟踪关系。
|
||||
|
||||
## SIP 接入信息
|
||||
|
||||
以下为用户提供的 SIP 参数,服务商名称待补充;已记录不代表已完成真实线路验证。
|
||||
|
||||
| 服务商 | SIP 服务端 | 主叫号码/标识 | 被叫前缀 |
|
||||
| --- | --- | --- | --- |
|
||||
| 数企 | `61.132.228.221:5060` | `BD93205882` | `7089` |
|
||||
| 中鼎 | `60.171.24.90:5060` | `mbkq` | 无 |
|
||||
| 百应 | `160.202.254.79:5060` | `KQ91526` | `mka755` |
|
||||
|
||||
## SIP 全局共用定义:外呼号码白名单
|
||||
|
||||
- 外呼号码白名单:`15003164745`、`15830461047`。
|
||||
- 所有 SIP 线路仅允许在此列表范围内发起外呼;不在列表内的号码必须拒绝。该列表仅用于已授权的 Mock/明确安排的测试;不得因写入此处而自动发起真实呼叫,原始号码保持不变。
|
||||
- **现行真实/旧路径运行限制**仍为 Asia/Shanghai 每日 `09:00`(含)至 `20:00`(不含);窗口外 Dispatcher/Agent 必须 fail-closed,禁止等待、自动延迟、重试或换线。下述非生产和真实验证条款中的固定时间仍是**当前真实运行限制**。新增的 V3 执行入口只启用隔离 Mock,mixed/real 启动即拒绝;Mock 测试不能宣称 real 放行。
|
||||
- **F04 项目内 Mock 已实现、外部未签收的后续目标**:仅 Dispatcher 在持久接纳与实际发出呼出指令前判断任务×已选 SIP 线路的允许时段、白名单、命令/授权/租户额度期限及任务/AI 较小通话时限;Agent 只校验会话及 Dispatcher 签发期限,不重算外呼业务策略。任务按周一至周日分别配置多个允许时段,可排除多个指定日期;线路只配置每周允许时段,**没有线路排除日期**。均按 Asia/Shanghai 判断,跨日拆分、左闭右开,任务排除日期全天拒绝;缺失/不确定时段拒绝并持久记录,不等下一窗口、不自动重试或换线。任务和线路时段**尚不能授权真实试拨**;F08 最终结果/额度收口、F09 完整验收及真实合同/部署授权分别未完成,不能据此放开固定真实门禁。
|
||||
- 主叫标识保留原值(包括 `BD`),不能按纯数字手机号清洗,也不能直接当成 Digest 认证用户名;具体 From/PAI 等字段映射仍需确认。
|
||||
- 业务原始被叫号码保持不变;使用该线路时按其规则构造 `7089<被叫号码>`,避免重复添加或把该前缀带到其他供应商线路。
|
||||
- 传输协议、IP/Digest 鉴权、是否注册及并发限制仍需供应商确认;当前供应商已反馈需使用 PCMA,Asterisk 配置以 `allow=alaw` 表示,仍需真实线路验证。
|
||||
- 每条线路目前只提供一个服务端地址,未提供独立备用地址。不能把同一地址重复填写成主备并宣称具备容灾;三条已登记线路应作为独立 trunk 配置,不为凑主备虚构供应商。
|
||||
|
||||
## ECS 部署环境与 Asterisk 运行约束
|
||||
|
||||
- ECS 部署环境固定优先使用 Debian 13(Trixie)minimal;仅当阿里云北京区域没有可用的 Debian 13 镜像时,才允许使用 Ubuntu 24.04 LTS。不得擅自切换到其他操作系统。
|
||||
- Asterisk 必须直接部署在实际承载它的 ECS 主机上,由 systemd service 统一管理并启用开机自启动;部署验收必须确认 service 已 enabled 且 active,不得以手工前台进程或容器入口替代生产启动方式。
|
||||
|
||||
## 开发与非生产环境强制部署/诊断步骤
|
||||
|
||||
- 开发、Mock、mixed、real 的**非生产环境**必须默认开启环境部署与诊断步骤;这些步骤是必需的,不得因“只是开发”“环境已存在”“时间紧”或调用方参数而跳过、关闭、静默降级或默认禁用。任何显式关闭均视为配置错误,应失败并阻止验收。
|
||||
- 每次新主机、新版本或新 Cell 验证至少执行并留存脱敏事实:ECS/EIP/网络资源只读核验、Debian/架构/磁盘/权限核验、`rogee` SSH 与 SSH 加固核验、发布包及依赖 SHA-256、Asterisk/systemd `enabled+active`、ARI/PJSIP endpoint/contact 状态、媒体 profile/监听端口和运行版本。
|
||||
- 每次非生产 `mixed`/`real` 外呼验证,必须先通过 Asia/Shanghai `09:00`–`20:00`(左闭右开)时间门禁,再在拨号前启动受限 SIP/RTP 抓包和 Asterisk PJSIP logger,并在结束后采集 SIP 响应码、INVITE/180/183/200/4xx/5xx/BYE 或 CANCEL 时间线、SDP codec/媒体地址端口、RTP 包/字节计数、录音与 ASR/LLM/TTS 事实及 SHA-256;无拨号前抓包、状态快照或时间门禁不得宣称验证通过。失败呼叫同样必须保留状态和抓包证据,不能只报告一个 hangup cause。
|
||||
- 抓包、日志、录音和识别文本只写入受限的非生产证据目录,聊天、源码、配置样例、提交和长期证据不得保存密钥、完整用户音频或完整用户对话;交付证据默认保存脱敏摘要、计数、状态码和哈希。若 tcpdump/CAP_NET_RAW、PJSIP logger、ARI/PJSIP 状态采集任一不可用,必须 fail-closed 报告阻塞,不得静默改成无抓包流程。
|
||||
- 上述步骤由统一部署/验收入口自动执行;`mock`、`mixed`、`real` 只替换适配器,不能绕开同一套部署、诊断、状态和证据门禁。生产环境仍须另行授权和通过生产安全屏障,非生产默认强制开启不等于生产放行。
|
||||
|
||||
## 本次上线目标与分期(用户已确认)
|
||||
|
||||
- P1以稳定快速内测上线为目标:1个节点、1个Agent、1套Asterisk、1个单活Dispatcher/SQLite、1个启用租户;本轮不开发、不验收双节点、第二 Cell/第二 Asterisk或第二租户。用户已确认后续多 Dispatcher 目标为每 D 独立 ID/接收队列、独占 Agent/Asterisk 执行资源;同一租户可有多任务,但每个任务只能有一个 D 归属,SaaS 持久绑定租户+任务→D,呼叫/控制不得分发到其它 D,不能暗中迁移。单任务并发可由归属 D 本地判断;跨 D 租户/供应商总上限仍须先冻结有界额度份额,不能各 D 各按全局上限放行。本轮不把 D1/D2 隔离 fixture 冒充多 D 业务运行。
|
||||
- 至少3家独立SIP trunk 的静态配置、路由/主叫/前缀/codec/额度约束和协议 Mock/mixed 覆盖仍需保持;真实供应商外呼和 ECS 仅作为第二阶段联调,不是本轮前置。
|
||||
- ASR-only和ASR+LLM+TTS均按批准的不可变AI配置在本地/隔离链路验收;不擅自加MQ模式字段,不复用旧LLM/TTS。真实供应商未联调时必须明确标记为第二阶段,不能把 Mock 写成真实供应商通过。
|
||||
- P1使用管理平台批准的静态单 Cell 快照和受控维护窗口,不做在线发布/回滚编排;静态配置必须关准入、排空、核验实际加载,旧直写通道不得并行。
|
||||
- P1保留 tenant_key 原值、租户独立队列、复合幂等键、有界窗口及单租户配额/控制边界;不开发或验收双租户公平、第二 Cell 汇总配额和多实例协调。
|
||||
- 本阶段上传按固定15分钟授权、单次PUT、原事实持久化及recording.uploaded可靠入队进行本地隔离验收;不申请SaaS上传会话、不等待complete/verified或OSS ID。RabbitMQ ACL/TLS和application receipt仅按适用版本化契约/隔离测试验证,不将通知入队称为SaaS已处理;真实SaaS/MQ联调延期第二阶段。
|
||||
- 88项验收为跨阶段基线,当前只签收单节点/单 Cell/单租户适用子场景;双节点、第二 Cell、第二租户、真实 ECS/生产联调、容量/N+1及切换均不作为本轮门禁。
|
||||
|
||||
## 语言与工程
|
||||
|
||||
- 工具链基线为 Go 1.27.1。实施时锁定 CI/构建镜像和依赖,并校验实际工具链;不得自动修改其它项目的 Go 基线。
|
||||
- 标准库优先、单Go module/二进制,用Cobra显式提供agent、dispatcher两个业务子命令,无默认双角色启动;同一制品分进程/权限/目录,升级受版本兼容和排空约束,不另造CLI框架。
|
||||
- JSON v2、UUID 和新测试 API 的采用以契约兼容和实测为前提;既有标识、哈希规范不得随 API 更换。实验性 SIMD 不在当前范围。
|
||||
- 用户已确认不接PG:独立Dispatcher持有SQLite权威任务/配额/outbox,Agent无业务DB,文本/录音及执行/上传恢复信息落文件。禁止NFS共享SQLite/两份DB双活发额度,自动跨机热备不在已实现承诺内。
|
||||
- 已确认Unary gRPC,Dispatcher预配置Agent Endpoint;Agent业务只需D Endpoint,证书/监听/ARI/持久目录由部署提供。SDK复用连接,不增内部MQ或双向流,不因RPC超时重拨。
|
||||
- 所有Agent共用mTLS证书,D身份独立;必须通过受控Endpoint主动激活/节点会话授权,不信自报身份/地址。共享私钥泄露影响整组,轮换/撤销和风险要签收,不关闭SAN/SNI校验。
|
||||
- D感知健康/负载/软件协议/能力及供应商applied配置版本;样本过期/缺失为unknown,低CPU不突破租户/供应商/Cell/AI配额,新boot不清旧未知占用。
|
||||
- 实施后至少执行本模块的格式化检查、`go vet ./...`、`go test -race ./...` 和构建;当前代码已有 W01/W02/本地 RPC/AI Mock 入口,真实 DB/MQ、媒体、供应商、容量及切换验收仍分别报告,不能用本地通过记录代签。
|
||||
|
||||
## 开源复用硬约束(用户已确认)
|
||||
|
||||
- SIP 及其它组件有适用开源库/官方 SDK 必须复用,禁止从零手写替代协议栈或客户端。优先标准库、Asterisk 原生能力、现成 SDK;自有代码限业务状态机、事务、权限、配额和薄适配。
|
||||
- 不自写 SIP/ARI、RTP/RTCP 编解包、G.711、WS/AMQP/数据库驱动、OSS 签名、已有 SDK 覆盖的 AI 协议或 Schema 解析。库不满足先选替代、修上游或报告阻塞;例外须用户另行批准。
|
||||
- 采用前核验 module/tag/commit、Go1.27.1、许可证/NOTICE、传递依赖/漏洞及真实协议兼容,留存 PoC;不得将 main README、未归档或可下载等同于生产通过。
|
||||
- SDK 自动重试不得造成二次 originate、旧音频重播或重复收费;不因 SIP 库存在而用 sipgo/diago 替换已选定 Asterisk 架构。
|
||||
|
||||
## AI配置与参数(用户已确认)
|
||||
|
||||
- P1采用百炼/火山ASR、OpenAI兼容LLM、火山TTS;SDK首选及未通过门禁见组件清单§1.3/§4.3。基础栈方向确定不等于精确版本、许可证或参数能力已验收;不为补字段改为自写协议。
|
||||
- **现行合同(尚未切换)**:Dispatcher按MQ任务agent_version_id,经RabbitMQ专用Topic向SaaS取得不可变AI配置/授权,响应回原Dispatcher;校验租户/源Schema/不可变摘要/能力并持久绑定后向Agent交付执行快照。过去已废弃的独立AI版本GET不复活;新获批准的方向是**任务配置只读接口内含智能体**,须另冻合同而非旧GET兼容层。Agent不直连SaaS,不从CLI/env/源码常量或SDK默认覆盖AI业务值,不新增任务MQ模式字段或调参后台。
|
||||
- 已有model/prompt/voice/speed/ASR输入与识别/temperature/max_tokens/timeout及对话控制必须实际传入SDK或控制器;热词/VAD/top_p/音量/阶段时限等所需扩展先在上游补GAP-09,再生成校验。严格additionalProperties不放宽,不借metadata/raw_request透传。
|
||||
- **现行 AI 合同**:SaaS新版本供新任务引用,无需改代码/重启D/A;在途/原排队任务固定快照,同版本异内容拒绝。缓存按租户+版本隔离,断SaaS无有效授权缓存拒新准入;显式0/false与未提供保真,并发通话不得共享可变SDK参数。
|
||||
- **项目内配置与执行(已发布外部 v1 不变)**:项目内 v0.4 任务发现、控制及外呼入站依据 `docs/thirds/v0.4.md`;其它必要边界见 `docs/thirds/第三方对接事件与请求消费顺序_v0.1.md`。拟定 SaaS 只读路径为 `/internal/v1/dispatcher/sip`、`/internal/v1/dispatcher/task/:task_id`、`/internal/v1/dispatcher/tasks` 和 `/internal/v1/dispatcher/tenant/:tenant_id/quota`;均为项目内字段/路径,实际 SaaS 兼容性未验证。D 用 `X-DISPATCHER-id`/`X-DISPATCHER-SECRET-KEY` 按需读取,不在源码、配置样例或日志暴露凭据。SIP 启动先取获批全量并核验 Agent/Asterisk 加载后才准入;任务按租户+任务缓存约 60 秒,到期重新读取完整 200,无 ETag、过期缓存或 MQ 配置回退;已接纳执行固定原快照,暂停/停止控制不等待缓存。项目内 v0.4 `call.execute` 入站只有 `task_id/callee`,调用路由、主叫、AI 和时限绑定已授权任务快照;历史 MQ 命令不因年龄过期,但拨号前门禁不放宽。任务终止仅允许**显式、条件式**清理任务配置副本,不删执行恢复、幂等或 outbox。SIP 改动须关准入、排空及核验实际加载;外部 opt-out 现行 MQ 即时语义不可擅自改称已切换为最终 `call.result`。F01/F07 本地 Schema、正反例、来源/hash 与 Mock C 已通过,外部签收/连通仍未验证。
|
||||
- 凭据/供应商端点来自受控引用且有授权校验;不再定义独立出口池标识或出口池授权名单,Dispatcher 仍校验任务允许线路、全局号码白名单、时段和额度,不能因可调参数绕过安全硬限额或启用不安全重试。OpenAI默认自动重试显式关闭;日志只留脱敏版本/摘要/有效参数,不打印prompt/变量/密钥。
|
||||
- 静态发布只约束SIP/节点制品,不将AI配置硬编码;GAP-08/09及SDK参数PoC为P1门禁,验证入口见验收§5.1(现有E/L项子场景,不新增虚假通过数)。
|
||||
|
||||
## 契约与可靠性
|
||||
|
||||
- 本项目设计/运行/验收文档只在自身 `docs/` 维护。上游共享接口有唯一权威来源;导入带版本、来源和哈希的不可变契约包,再生成类型/校验,不维护重复手写 Schema。
|
||||
- 新内部消息/许可/fencing 协议需先获批;不擅自改变 SaaS 路径、字段、状态、路由或控制语义。
|
||||
- **现行已发布合同(新版本生效前必须遵守)**:SaaS↔Dispatcher的全部交互唯一经RabbitMQ专用Topic订阅,双方无HTTP请求/回调/兼容通道或故障回退,包括执行、控制、查询、整体补传、AI配置/授权及recording.uploaded上传事实通知;上传不申请SaaS会话或等待verified/OSS ID回复。OSS配置/TOKEN不来自SaaS:Agent领取及显式重申请TOKEN只经D↔A Unary;本规则不禁止Agent→OSS、ARI、AI供应商HTTP(S)或gRPC的HTTP/2。
|
||||
- **本轮项目内目标(尚未替换真实外部运行)**:任务(含智能体)、SIP、任务发现和按 tenant_id 的租户额度走四条只读 HTTP;呼叫、控制及其必要回执/单份最终结果走 MQ,取消对外业务查询/补传和分散通话事件。不提供配置HTTP→MQ回退,也不恢复其它业务HTTP通道。SaaS须分发 management 已批准的唯一 SIP 版本,management 仍为唯一编辑/审批面。该本地语义按第三方契约及版本化 Schema/示例/hash 冻结,Mock C 是本地门禁,不等待外部签收;真实切换仍需另行授权。
|
||||
- 新HTTP配置字段项目内 SIP 新版见 `docs/contracts/config-read-fields-v0.3-proposal.md`、`config-read-v0.3.schema.json`/mock示例;AI 授权和静态 Cell 制品的项目内新版见同一提案;旧 v1/v0.2 保留历史,不作为当前运行契约;任务/额度仍参照 v0.1;截图只证实UI含义,英文响应键为项目自定义,绝非SaaS现网接口已确认字段。用户新增任务排除日期、线路时段等未见截图项按项目需求设计;SIP传输/鉴权/注册及额度未知不能猜默认值。Schema/Mock 校验可满足项目内 C,但不代表 SaaS/management 已发布或真实兼容;真实响应、审批来源和 Agent/Asterisk 实际加载仍须单独验证。当前唯一权威运行契约不因草案变化。
|
||||
- **每个Dispatcher必须有独立、全局唯一且不重复的ID及独立接收Topic/队列**;指定D的任务/现行MQ配置结果/上传结果不能由其它D抢收,也不能广播后仅靠正文过滤;新目标只读HTTP配置由该D UUID+SECRETKEY获取且须核对任务归属。身份与tenant/Agent/Cell ID、dispatcher_epoch分开;现行合同保留租户独立队列及原值tenant_key,完整新路由长度预算须重验。具体ID生成/持久化、Topic/绑定、消息字段/关联/错误/期限须随W01新版本冻结,不凭本文给旧严格Schema添加字段。
|
||||
- **v0.4 任务发现与队列所有权硬边界**:SaaS 独占创建、维护、退役每 D 的独立控制队列与每任务任务队列及绑定;Dispatcher 仅消费,不能自行建队、绑定或删除。本地 RabbitMQ 无 `configure` 权限 Mock 已通过,真实兼容性未验证。新加入或重启 D 先 `GET /internal/v1/dispatcher/tasks?mode=snapshot` 逐页取得同一 `snapshot_id`/`watermark` 的完整清单,全部校验后一次 SQLite 事务提交;独立控制队列积压处理完成前不开任务准入。运行期 `GET .../tasks?after=<内存游标>` 仅发现归属变更,每页持久提交后推进内存游标;重启不恢复旧 v0.3 持久事件游标,分页或持久化失败关新准入、停任务消费,MQ 控制及结果恢复照常处理。HTTP 的偶发状态与 MQ 已应用状态冲突则关准入,不让发现页覆盖已持久的 pause/stop;只有 MQ resume 经单任务新鲜状态确认才恢复原积压。stop 挂断、排空后回自身控制回执,未接纳旧外呼静默 ACK、不拨号、不回逐条结果,也不删 SaaS 任务队列。历史 `task.control` 与 `call.execute` 不因消息年龄过期,外呼仍在接纳和拨号前独立检查任务/白名单/时段/授权/额度及通话时限,未来 `issued_at` 不提前接纳。保留原值 tenant_key、租户额度和未知占用;跨 D 份额仍待外部冻结。v0.1–v0.3 发现证据仅作历史,v0.4 本地证据见 `docs/evidence/dispatcher-v04-local-acceptance.md`;不能证明真实 SaaS/management、多 D 或生产可用。
|
||||
- **OSS相关配置存于Dispatcher配置文件,Agent向Dispatcher领取临时上传TOKEN后直传OSS,不保存长期凭据;SaaS不再下发OSS配置/TOKEN。** D复用官方SDK提供受限TOKEN/目标信息,配置缺失/无效明确失败;不在样例、源码、日志或证据中保存实际密钥/完整TOKEN。过期只允许A显式向D重新申请,不自动续期或向SaaS申请TOKEN;精确配置格式/TOKEN形态/UploadGrant映射另行核验,不猜字段。
|
||||
- **本轮项目内目标:上传仅负责 Agent 直传及 D 可靠通知 MQ,SaaS 后续处理不属本项目职责;外部 v2 的现行上传事实不因本地目标自动改变。** D保留签发能力、不转发文件;R13持久保存事实与recording.uploaded outbox,消息为persistent、进入指定durable队列/绑定、mandatory无return且publisher confirm成功后才记交付完成。只写本地outbox不算入队;不申请SaaS会话、不等待verified/OSS ID、不新增VERIFYING、不伪造SaaS结果。
|
||||
- 新版recording.uploaded取代本项目recording.ready,字段为call_id/recording_id/upload_id/bucket/object_key/format/channels/sample_rate_hz/duration_ms/size_bytes/checksum_sha256;不含TOKEN/密钥/签名URL。MQ失败/确认丢失/重启只恢复原消息身份的交付,不重新PUT或新建资产。现行AI/控制等必要请求响应不受此收缩影响;新目标AI改用任务只读HTTP获取,控制仍走MQ。
|
||||
- 前一轮MQ-only文档纠正已结束;以下是**现行 MQ-only v1 合同的历史基线**,不得误当作新只读配置HTTP方案的限制或验收通过:现行机器依据见 `contracts/upstream/v1/mq-topology.json`、`mq.schema.json` 和 `event-payloads.schema.json`,第三方顺序说明见 `docs/thirds/第三方对接事件与请求消费顺序_v0.1.md`:纯Topic精确绑定、拒绝独立通配词段、tenant_key预算196 UTF-8字节、稳定UUID v4、旧版严格JSON配置及15分钟SDK预签名PUT;新目标保留业务MQ及OSS规则,仅替换配置获取,须另发版本化合同,不原地复用旧Schema。当前仅保留现有代码需要的契约包;未发生契约迁移前不新增契约,旧快照不作为当前工作树输入。新版须完成Schema/正反例/哈希验证后发布,不把方案确认当实现完成。历史 W01/W02/W04/W05/W07/W08/W11/W12/W13/W14 范围见归档 `docs/archive/plan-0918.md` §8.2;项目内 v0.4 配置/控制路径以 `docs/plan-dispatcher-state-v0.1.md` 和本地验收证据为当前入口;外部合同另行签收。全局唯一D身份/专用Topic及本地D1/D2隔离fixture为当前合同要求,不授权双D业务运行、HA或共享额度。
|
||||
- **现行已发布合同**中的实时文字事件名为transcript.updated,不新增call.transcript别名;OSS文本归档不能冒充当前实时文字/opt-out,缺少专用资产授权接口时明确未启用,不能伪装recording.ready。
|
||||
- **用户已批准的项目内精简契约目标**见 `docs/plan-config-read-v0.1.md` §3.5/§4 和第三方对接契约:SaaS↔D 移除对外查询/补传命令及分散通话/转写/拒联/录音事件,保留呼叫/控制命令和必要回执;录音仍上传 OSS,D 每通话只回传一份含最终转写、拒联事实与 OSS 路径的 `call.result`。本地实现以 F01/F07 Schema、正反例、来源/hash 和 Mock C 为门禁,无需额外外部/业务签收;本地验收更新后不要求通话前实时文字或拒联。无录音按 `not_created` 收口;预期录音明确失败立即 `unavailable`,未知最迟于 `call.ended_at + 15m` 收口。通话确认终结释放执行资源后释放占用,不等待 OSS 或 MQ confirm;未知仍占用。现行外部 Schema/代码保持原样,真实兼容性未验证。
|
||||
- 现有MQ信封command_type/command_id、event_type/aggregate_*与正文已对齐;事件payload专属约束尚需补齐,不把通用object校验当完整验收。字段索引只读生成,不手改成第二套Schema。
|
||||
- `tenant_key` 原值一对一绑定,不清洗、编码或截断;旧布局224个UTF-8字节预算不能在加入D身份后直接照搬,W01须冻结并验证完整routing key/queue预算及分隔符/通配符边界;超限停止发布并保留源任务。
|
||||
- 持久 inbox 后 ACK;状态与 outbox 同事务;confirm 不等于 SaaS 应用收讫。重复投递、未知执行和恢复不能触发重复拨号。
|
||||
- 配额覆盖所有 Cell/实例及未知占用;租约过期不自动释放不明通话。**现行 v2** 控制 CAS 为 expected_task_revision,pause 与 stop 的 drain/hangup 区分;paused 可按新授权恢复,stopped 不可恢复。现行整体补传仅 call_id/source_command_id;下一版对外查询/补传目标取消但严格合同/代码未改。最后发起许可、权限和屏障须故障注入。
|
||||
- **用户已批准的项目内精简契约目标(不能混写现行 v2;外部签收不阻塞本地 C)**:`call.execute.payload` 仅 `task_id/callee`,外呼信封身份仍用于防止重拨;路由/主叫/智能体版本与 `ring_timeout_ms/max_call_duration_ms` 均从已批准的任务配置取得并持久绑定。`task.control` 的 pause/resume/stop 均不带 `command_id` 或 `expected_task_revision`,不设计控制去重,但 D 必须回 task/action/status 处理结果;乱序、控制重投/回执丢失与 stop 后 resume 的本地判定写入第三方契约并由 Mock 测试;外部签收不是本地阻塞项,不偷偷重引入 CAS/去重掩盖。任务配置新增明确 `caller_profile_id`,按allowed_trunk_ids顺序选首个时段/额度/加载/主叫均匹配的线路,选后固定、不自动换线重拨;有效通话上限取任务与已授权AI两者较小值。旧running配置/发现不得解除已持久的paused/stopped,resume须强制最新任务核验,stopped同ID不可逆。拟定配置响应不再包含 `agent.content_sha256`;录音 checksum 另有用途,不误删;SIP SaaS 响应不再提供 snapshot_sha256 或静态制品。参见 `docs/plan-config-read-v0.1.md` 和 `docs/thirds/第三方对接事件与请求消费顺序_v0.1.md`。
|
||||
- management是SIP配置唯一编辑/审批面。**现行 P1**通过批准的版本化静态制品和受控部署入口交付,D核验目标/准入屏障,Agent加载并报告;不要求在线发布控制面。静态交接合同须批准,旧直接写Agent面不能同时启用;成功必须证明精确快照已被Asterisk加载。
|
||||
- **本轮项目内 SIP 配置读取目标(现行外部运行未切换)**:management 仍是 SIP 唯一编辑/审批方,SaaS 仅经只读 HTTP 提供该 D 资源分区的获批全量快照;新加入/重启 D 先查询、核验所属 Agent/Asterisk 实际加载的 SIP 线路 revision 后才消费执行队列;Agent/Asterisk 的部署配置由受控部署确定,不来自 SaaS。后续约每60秒核对版本,有变化就关执行准入、排空旧活动通话并确认新版已加载;控制MQ照常处理。SaaS/management 分属不同配置系统时须证明SaaS分发的是同一份获批线路配置版本;不引入共享业务DB或MQ配置回退。项目内 SIP 读取及准入链路已用隔离 Mock 验证;真实 Agent/Asterisk 加载与 SaaS/management 切换尚未验证。真实 SaaS/management 兼容性及多 D 资源配额份额仍未验证、不属本轮验收,详见 `docs/architecture/Dispatcher有界接纳与控制通道改造计划_v0.1.md` §3.2。
|
||||
|
||||
## 安全和真实验证
|
||||
|
||||
- mock/mixed/real 明确隔离;Mock 默认隔离真实外网,正式模式拒绝 Mock/测试凭据,不静默回退。
|
||||
- 只允许复用既有 ASR 协议;禁止复用 `voice_test` 的 LLM/TTS。P1必须完成新LLM/TTS规范、SDK适配和本地/协议隔离验收;真实供应商联调延期第二阶段,不能以Mock冒充真实供应商通过,也不能把真实联调延期误写成当前 P1 已实测。
|
||||
- 真实外呼只允许原始号码 `15003164745`、`15830461047`,但白名单和文档不是拨号授权;每次真实验证仍需明确安排,且仅可在 Asia/Shanghai `09:00`–`20:00`(左闭右开)执行。每条 SIP trunk 对每个原始手机号每天最多 3 次;某条线路失败时可在额度内经当前会话确认后改测另一条线路,但不得在窗口外等待、自动延迟、在同一条线路/号码上超额、自动重试或静默换线。
|
||||
- 不把 SIP 白名单出口 IP 当作 SIP 服务端,不虚构备用线路,不逐呼重写共享配置,不自动重拨已接通/未知的执行。
|
||||
- 生产使用多机器、多 EIP 直连;1000 路指完整 ASR/LLM/TTS 已接通通话,N+1 与供应商能力须实测,不采用单 EIP+NAT。
|
||||
- 独立开发和测试不要求云账号。云创建、EIP 改绑、网络放行、供应商消费和测试资源清理必须另获明确授权;不得触碰无关资源。
|
||||
- 不在源码、配置样例、文档、日志或证据中保存密钥、密码、私钥、完整用户音频/对话;注入受控凭据,诊断端点仅管理网可达。
|
||||
- 旧 Python 与新 Go 不得同时写同一资源或各自发放共享额度。没有可验证的所有权/状态回迁方案就暂停切换,不以回滚镜像冒险重拨。
|
||||
@@ -138,6 +138,8 @@
|
||||
|
||||
- 历史部署 JSON:部署目录仍放置旧 Dispatcher 文件配置与两份自行编号的静态 Cell 样例,其中审批标记不能证明现行管理平台审批。部署布局测试先复现三份旧样例仍在当前路径,再将原始字节移至 `docs/archive/deployment-examples/`,逐份核验迁移前后 SHA-256 相同并记录于该目录 README;当前 `deploys/config/` 仅保留已由现行 Mock 端点读取测试验证的 Agent 样例。安装包从未包含这三份旧文件,真实 Agent/Asterisk 加载和审批仍未验证。
|
||||
|
||||
- 当前文档单入口:`AGENTS.md`、根 `README.md` 和 `docs/README.md` 不再把旧 MQ-only、F 工作包或 v0.4 发现写作当前执行依据,改指唯一项目内通信说明、机器合同与新的 `docs/plan-saas-dispatcher.md` 状态入口;物理部署说明标明当前制品只支持隔离 Mock、不批准真实安装。原 AGENTS 原字节归档到 `docs/archive/AGENTS-before-current-contract.md`(SHA-256 `8996ce2db909508172f59f39e780bdab2f48b2eba1acc3590dcffc50f8b2f6f0`)。版本化计划 `docs/plan-saas-dispatcher-v05-v0.1.md` 已被当前 `contracts/local/manifest.json` 固定原路径及 SHA-256 `666f39e56ea9f4b55661efcac82edd6f9729848e2d60e5f24cdf5aa3ac97ee87`,因此保留原字节作为合同**历史来源例外**,另建不带代次的当前计划索引,而不伪造来源或另立运行合同。四份当前根文档的相对链接、两份原字节 SHA-256、`go test ./contracts ./internal/config`、`make check`(含 race/vet/build 与三项真实隔离 MQ PASS)及 `make release-check-local` 均已核对通过;当前待办仍有 AI 自有名称及历史夹具残留分类,本批不宣布 P07 完成。真实 SaaS、Asterisk/ECS、OSS、AI 与非生产主机诊断均未运行。
|
||||
|
||||
## 验收台账
|
||||
|
||||
P01–P06 的项目内隔离证据见上;P07 全仓命名与唯一入口尚在清理,A01–A12 和 K01–K16 的最终对照仍待 P08。不得用本地 Mock 冒充外部签收。
|
||||
|
||||
@@ -0,0 +1,31 @@
|
||||
# SaaS↔Dispatcher:当前实施与验收入口
|
||||
|
||||
本项目的**唯一现行业务通信说明**为 [`thirds/saas-dispatcher.md`](thirds/saas-dispatcher.md),唯一项目内机器契约为 [`../contracts/local/`](../contracts/local/) 的 Schema、拓扑、正反例与 `manifest.json`。Agent 内部 RPC 见 [`../proto/agent/agent.proto`](../proto/agent/agent.proto)。本文只记录实施和验收进度,不另立一套字段或队列。
|
||||
|
||||
## 范围和来源
|
||||
|
||||
- 用户已确认 K01–K16,并明确批准实施 P01–P08;已取代原计划 §1.2“仅修订计划”的旧范围,不重复审批。固定 MQ `v1` 通信名、HTTP `/internal/v1/dispatcher/...` 路径和有业务含义的 revision 不属于自有实现代次,保持不变。
|
||||
- [`plan-saas-dispatcher-v05-v0.1.md`](plan-saas-dispatcher-v05-v0.1.md) 是本轮合同的**不可变历史来源**,其原路径及 SHA-256 已写入当前合同 `manifest.json`;为保护来源事实,不改名、不改字节、不作为另一个当前运行入口。其他旧方案、旧 MQ-only 合同与旧验收数字均为历史。
|
||||
- 当前仅验收单节点、单 Dispatcher、单 Agent、单 Cell、单租户的**隔离 Mock**。真实 SaaS/MQ/OSS/AI/Asterisk/SIP/ECS、容量及生产切换没有在本轮验证;样例、Hash 和本机测试均不是拨号或生产授权。
|
||||
- 不迁移、清空或自动处置现存 SQLite、Agent 恢复文件、旧 spool 和 outbox;发现旧执行/上传状态时拒绝启动并保留原文件,按事实另行确认处置。
|
||||
|
||||
## 工作项
|
||||
|
||||
| 阶段 | 本地状态及核验入口 |
|
||||
| --- | --- |
|
||||
| P01 契约 | 已建立当前 HTTP/MQ Schema、拓扑、正反例和来源/hash;见 `contracts/local/manifest.json` 及 [`evidence/saas-dispatcher-implementation.md`](evidence/saas-dispatcher-implementation.md)。 |
|
||||
| P02 单入口与 Proto | 根命令只注册现行 Mock Agent/Dispatcher;八个 Agent RPC 方法、生成物与 `proto/manifest.json` 已验证。 |
|
||||
| P03 五类只读 HTTP | SIP、任务、发现、租户额度及供应商配置只读;租户/任务归属和新鲜度均经隔离测试。 |
|
||||
| P04 MQ/SQLite | SaaS 预建队列、独立 Dispatcher 身份、持久 inbox/outbox、控制屏障及共享结果队列有隔离 MQ 测试。Confirm 不等于 SaaS 已处理。 |
|
||||
| P05 AI/媒体 | 不可变获批 AI 快照,ASR-only、ASR+LLM+TTS、关键词、16 kHz 媒体及失败边界仅经本地 Mock 验证。 |
|
||||
| P06 录音/OSS/结果 | 隔离双向 TLS 录音、一次 HTTPS PUT、失败与未知结果恢复、48 小时边界和唯一最终 MQ 结果经本机测试。 |
|
||||
| P07 唯一当前入口 | 旧执行/配置/MQ/AI/Proto/Schema/脚本路径已分批删除;当前文档和全仓残留例外审计进行中,历史来源及实际数据保留。 |
|
||||
| P08 验收交付 | A01–A12、K01–K16、业务覆盖率 ≥65%、重启/故障矩阵及诊断门禁的最终对照**尚未完成**。不得将前述分批通过写为最终签收。 |
|
||||
|
||||
每批变更、测试命令、正反例和未验证项详见 [`evidence/saas-dispatcher-implementation.md`](evidence/saas-dispatcher-implementation.md)。发布包 `production_approval=false`;`make check`、`make release-check-local` 仅检验本机隔离制品与行为,不运行真实服务。
|
||||
|
||||
## 交付门禁
|
||||
|
||||
- 必须执行格式、当前合同及 Proto 来源/hash 检查,`go vet ./...`、`go test -race ./...`、构建及三项**实际通过**的隔离 RabbitMQ 集成测试;旧测试筛选式匹配零项不得算通过。
|
||||
- 对照原计划 A01–A12 与 K01–K16 逐项记录本地证据和缺口,业务代码单元测试覆盖率须达到 65%;故障、重投、重启和约十分钟 Agent 会话过期边界不可遗漏。
|
||||
- 实际非生产主机验证另须执行 [`../deploys/test/nonprod-call-evidence.sh`](../deploys/test/nonprod-call-evidence.sh) 规定的资源/状态核查和拨号前受限抓包;本地 Mock、打包、证书与哈希均不能替代真实 Agent/Asterisk 加载、SaaS 应用收讫或供应商验收。未经单独安排不进行云操作或真实呼叫。
|
||||
Reference in New Issue
Block a user