# G0 开发准备与契约冻结提案 v0.1 ## 1. 状态、权限与使用方式 **状态:D01–D10 方案已由用户确认;项目内 W01 契约基线和 W02 Proto 已建立,但外部权威发布、D10 PoC/运行验收和真实预算仍待完成,G0 尚未通过。** 确认依据为用户本轮指令:“除 OSS 上传Agent会直连上传,从Dispatcher拿相关配置;其它按建议更新文档。” OSS 文件由 Agent 从 Dispatcher 获取受限配置后直接上传,Dispatcher 不中转文件内容;其余按已列建议执行。 本项目已创建并验证自己的 Go module、W01 bundle、W02 Proto/stubs、RPC/mTLS 和本地 Mock 测试;未修改父项目权威来源、字段索引或生成产物,未访问真实供应商或创建云资源。文件名保留“提案”以保持链接稳定,不代表还需重复审批已确认方向。 当前结论:可以继续开展 P0 契约补充、隔离 PoC 和项目内实现;不得宣称 G0 通过或把项目内基线冒充外部权威,也不得启动未获授权的真实供应商/云/拨号。架构、首发范围和供应商方向沿用已有决定,不重新选型。 - 外部字段/路径/状态仍以带来源哈希的上游主契约为准。本文件记录已确认的变更方向和验收要求,**不能被代码当 Schema 使用**。后续由上游维护者修改唯一来源并发布,再导入生成;本文件保留为决策历史,不继续手工维护字段副本。 - 内部机制、字段方向及兼容策略已确认,正式 Proto 的类型/编号/错误映射等仍需定稿与校验。本轮不生成 `.proto`,也不以临时 JSON 绕过契约;未提供的字段细节、实际预算和技术验证不能视为一并通过。 - 角色简称:S=SaaS/上游契约维护方,M=管理平台维护方,D/A=Dispatcher/Agent 实现方,O=部署/安全/测试负责人。角色不代表已指定人员或已签收;实际姓名、版本、日期和证据须在批准记录补全。 - 外部交互仍保留现有 7 条 SaaS 业务路径及 8 种 MQ 事件;已有 AI 版本 GET 的部署归属由 §4 确认,不新增 HTTP 拨号/业务结果回调、MQ 模式字段或内部 MQ。 - 依据:[重写方案](Go重写方案_v0.3.md)、[通信设计](通信与事件数据交互_v0.1.md)、[验收方案](验证与切换验收_v0.3.md)、[只读字段索引](OpenAPI与MQ字段索引_v0.1.md)、[组件清单](开源组件选型与复用清单_v0.2.md)。索引不是独立契约包。 ## 2. 方案确认记录与开发边界 D01–D10 的共同状态为 **用户已确认方案/源发布与验证未完成**,D07 明确为 Agent 从 Dispatcher 取配置后直连 OSS 上传。确认人及依据为 §1 的本轮用户指令;实现/安全签收责任人和产物版本仍待实际登记。不得再次把已确认方向标成“待用户审批”,也不得因此关闭 GAP。编号保留用于跟踪交付证据,不增加原 88 项运行验收数量。 | 确认项 | 对应缺口/交付内容 | 提交与签收角色 | 最小退出证据 | 未满足时阻塞 | | --- | --- | --- | --- | --- | | D01 | §3 八种事件的 payload、条件约束与同域版本 | S 提交,D/A 联合验证 | 上游发布版本、Schema、每种事件正反例、跨语言校验/摘要适用规则 | 业务结果序列化与消费闭环冻结;不阻塞只读工具 PoC | | D02 | §4.1 双 AI 模式及旧版本兼容(GAP-08) | S 提交,D/A 签收 | 两分支 Schema、旧完整模式兼容样本、模式资源/行为断言 | 两模式执行配置实现与 P1 双模式签收 | | D03 | §4.2 SaaS 配置授权、参数、受控引用(GAP-09) | S/O 提交,D/A 签收 | 部署归属、租户授权/撤销合同、摘要金样、参数到 SDK 映射 PoC | 配置缓存/下发和对应 AI 参数能力承诺 | | D04 | §5 Unary/最后许可/控制屏障(GAP-04) | D/A 提交,S 确认业务控制语义,O 确认恢复边界 | 已批准协议、状态转移及崩溃矩阵;随后生成 Proto 并做隔离 PoC | 跨 Cell 发起、控制、事实提交和恢复实现冻结 | | D05 | §5.2 共用证书会话与撤销(GAP-05) | O 提交,D/A 签收 | Endpoint/SAN 清单、角色隔离、重放负例、全组轮换方案及风险签收 | 节点准入和敏感配置交付 | | D06 | §6.1 P1 静态制品交接(GAP-03 P1) | M/O 提交,D/A 签收 | 制品来源、授权矩阵、唯一写入口、精确加载证据格式 | SIP 静态集成与真实发布 | | D07 | §6.2 Agent 取配置后直连 OSS 上传(GAP-02 P1) | S/O 提交,D/A 签收 | 受限配置、Agent→OSS 直传及 D 不转发文件证据;既有接口作用域、15分钟token、显式重新申请/完成幂等与 verified 证据 | 录音交接闭环;文本归档仍延后 | | D08 | §6.3 profile、单活恢复、保留(GAP-06/07 P1) | O 提交,D/A 签收 | 明确数值/来源/预算、备份与恢复演练设计、唯一所有权方案 | 对应运行参数冻结与真实验收,不阻塞离线原理 PoC | | D09 | §7 独立契约包和重建链 | S/M 提供版本,D/A 负责导入 | 只读包、清单、可重复生成/校验、项目外隔离构建记录 | 独立可交付构建,不得临时读取父目录运行 | | D10 | §8 依赖和关键 SDK PoC | D/A 提交,O 审核许可/安全 | 精确版本、许可/NOTICE、漏洞处置及对应 PoC 原始记录 | 未验证组件进入正式实现/发布依赖 | ### 2.1 允许先做、不能先做 允许先做:在另行安排开发时,用成熟库开展 SQLite 事务/恢复、AMQP 确认、ARI/媒体、Schema 工具链、SDK 参数映射和 mTLS 原理 PoC;本地资源必须隔离真实外网,不使用生产凭据。PoC 不依赖猜测的业务字段,也不以临时协议投入业务运行。 不能先做:实现者自行给 MQ 补字段、用宽松 object 校验生产事件、凭本地 CLI/env 选择 AI 模式、先写临时许可协议后让上游兼容、把供应商 SDK 示例成功当作参数/取消/收费行为验收。 可按依赖逐项解锁开发,不要求所有真实供应商测试先完成;但完整 G0 须有 P1 合同和本地关键 PoC 签收,P1 交付仍须独立完成真实验证。真实凭据、外呼、云资源或费用均另行授权。 ### 2.2 P1/P2 配额澄清(既有要求,不是新提案) P1 必须实施当前真实租户的限额,并在单活 D 的同一 SQLite 事务域汇总两个 Cell 的租户/全局/供应商/Cell/按模式 AI 并发及 CPS;保留租户复合键、有界窗口、未知占用、停止屏障。不能把“只有一个真实租户”解释为免除租户隔离或额度执行。 P2 增加多个同时活跃租户的等权轮询、额度不足跳过、公平恢复、全链路背压和公平性验收;不是首次实现原子配额。P1 可用两个模拟租户测隔离,但不因此开放第二真实租户。 ## 3. D01:外部事件 Schema 补齐方案(已确认方向) ### 3.1 上游修改方法 由上游将现有 `event_type` 分支与专属 `payload` 约束关联,保留原信封和严格未知字段策略。复用上游已有 Call、Attempt、TranscriptSegment、Recording、CommandResult 等实际组件;组件名称以源发布物为准,不在本项目重复定义。现有字段可复用不等于可以省略事件条件约束。 源发布前须给每种事件补齐必填/可选、类型/枚举、字节限制、可空规则、时间单位和条件组合。下表是**已确认的约束及复用方向**,不是已发布完整字段表;缺少源字段的地方由 S 明确扩展细节,不能凭表生成未经权威源定义的 JSON。 | 事件 | payload 方向与必须冻结的条件 | 最少反例 | | --- | --- | --- | | `command.result` | 复用原命令结果快照;按 command_type/status 限定 execution/call/control revision 及 reason 的适用性;发起前拒绝/超期没有 call_id;executing 不代表已发 SIP,控制 applied 必须有全目标屏障事实 | 无 call 拒绝却造 call_id;仅 accepted 就标控制 applied;CAS 失败返回成功 | | `call.status` | 复用同 call 下的通话/attempt 状态快照,关联租户、原命令/执行及当前 attempt;线路/Cell/出口来自实际获批路由;阶段时间依据观测而非纯本地计时 | answered 无接通事实;换租户/attempt;用整体版本丢掉独立域事件 | | `call.finished` | 复用通话终态和 attempt 结论;开始/接通/结束及持续时间保留原单位与未接通规则;允许录音/文字仍在后处理,不覆盖资产域 | 未接通却生成接通时长;通话结束强行把未交接录音设 ready | | `transcript.updated` | 复用段/轮次/revision/text/final、说话方和真实播放证据;中间稿/最终稿规则与同段 final 同内容幂等、异内容冲突机读化;完整文本不截断 | 迟到中间稿覆盖 final;仅生成 TTS 就标已播放;ASR-only 伪造助手播放 | | `transcript.failed` | 引用原 call 和受影响文字范围、源定义的失败阶段/原因/恢复性;无 segment 时如何表达整流失败由上游明确;不虚构空 final | 无关联对象;失败后静默删除已持久最终稿;用 recording.failed 代替 | | `recording.ready` | 复用原录音快照/OSS ID、文件元信息与上传会话关联;只接受 SaaS complete 已 verified 的事实;不能在 payload 带任意下载 URL/长期凭据 | PUT 2xx 即 ready;大小/摘要不符;verified=false;将文本归档伪装录音 | | `recording.failed` | 复用原录音身份、失败原因与可恢复性;明确上传超时、校验失败和永久丢失的区分;仍保存后续对账/补传所需关联 | 失败产生新 recording_id 逃避幂等;永久丢失报 ready | | `contact.opt_out` | 复用原租户/task/member/call 关联与拒绝时间/证据引用;最小必要信息;ASR-only 同样具备经批准的判定与通知流程 | 未授权模型判定;跨成员关联;等待录音上传才发 opt-out | ### 3.2 顺序、重复与测试 - D 对同一稳定事实和内容摘要幂等;同事实 ID 异内容必须冲突。MQ event_id/aggregate 字段继续由 D 的权威事务生成,不能由 Agent 自报最大版本。 - 版本按源规定的聚合实体和状态域处理,独立文字段/录音不被其它域的大版本覆盖;重放使用原事件身份,publish confirm 不等于 SaaS 应用收讫。 - 每种事件至少保留一个合法样本和一个非法样本;另测缺必填、未知字段、错误事件分支、跨租户/归属、空值、边界尺寸、乱序与重复。Schema 能验证形状,数据库归属、控制屏障和 verified 来源还必须运行时验证。 - 上游发布包含上述样本与预期结果的版本;本项目导入原样例运行 Go 校验,不手写一组与上游互不校验的“同名 Schema”。 ## 4. D02/D03:双模式与 AI 配置方案 ### 4.1 两模式与兼容(用户已确认,待 S 发布) 在**不可变 AI 版本对象**新增 `mode`,枚举为 `asr_only` / `asr_llm_tts`;不放入 `call.execute`。模式随 agent_version_id 固定,不能通过运行时参数覆盖;当前上游 Schema 尚未更新。 | 情况 | 已确认解释与条件 | | --- | --- | | 已有发布版本未带 mode | 仅在符合原完整 AI Schema 时按 `asr_llm_tts` 执行;不回写原对象、不注入默认值后重算原摘要。该兼容规则须进发布版本说明 | | 新发布版本 | 发布入口要求显式 mode;读取旧版本与创建新版本可有不同校验上下文,不能拿兼容读取规则默许新建省略 mode | | `asr_llm_tts` | 保持原 llm/prompt/tts/asr/conversation 条件和完整对话能力,不因模式引入放宽原必填 | | `asr_only` | 要求原身份/不可变标记、asr 和适用的 conversation 控制;llm/prompt/tts 必须缺省而非空对象或 null;不得建立 LLM/TTS 会话或占用其专属额度 | | ASR-only 的 conversation | 仅要求 silence_timeout_ms/max_duration_ms;opening/allow_interrupt/max_turns/sentence_max_chars/max_pending_audio_chunks 禁止提供,避免对无播放/生成场景产生假控制。若业务需识别段数量上限,应另提明确字段,不套用对话轮数 | | 缺必需能力/未知 mode | 拒绝新准入,不自动切换成另一模式,不静默关闭不支持参数 | ASR-only 静音以实际输入活动及获批 VAD 策略判定,最长时限从源契约约定的接通时点起算;静音到期按获批结束策略关闭,不自动播放提示。最终文字、录音、文字失败、opt-out 和控制屏障仍适用。opt-out 判定复用独立批准规则;禁止为此暗中开启 LLM,规则缺失时该能力门禁仍阻塞。 模式分支由上游使用源 Schema 机制生成,保持 additionalProperties 严格策略。当前 Schema 无法表达上述 ASR-only,上游发布前不能提交假的完整配置“先跑起来”。 ### 4.2 读取、授权与快照(方向已确认,待 S/O 补齐部署与合同细节) 1. 明确已有 `GET /internal/v1/ai/agent-versions/{agent_version_id}` 的 **SaaS 部署入口**、服务身份与可信租户绑定;租户不从响应任意覆盖任务归属。无权、找不到、不可用分别处理,不猜测第二个 task-config 路径。 2. 在首次成功准备执行配置时,将 `(原值 tenant_key, agent_version_id, 源 Schema 版本, 原内容摘要)` 与执行绑定并持久化。尚未取得有效配置的排队项不能准入;已有有效绑定的排队/在途项不因“最新版本”改变配置。新任务须显式引用新 agent_version_id。 3. 摘要采用上游已有算法及其精确输入边界,导入跨语言金样:键顺序、Unicode、数值、缺省/null/0/false 均须验证;本项目不另选 canonical 算法。若上游未发布明确算法,保持该项阻塞,不把普通 json.Marshal 字节当权威摘要。 4. 模式/参数归一化结果作为独立有效快照,关联原摘要和适配器版本,不修改原不可变内容。日志仅留版本、摘要及允许的脱敏参数,不留 prompt/variables/密钥。 5. P1 **不凭离线缓存授予新的发起许可**:D 可缓存不可变内容,但最终许可前须有本次执行的有效授权检查;SaaS 不可达且无上游已批准有效期的授权记录则拒新准入。已确认撤销阻止新许可,已发许可按 §5 有界收敛,在途终止仍走批准控制,不擅自挂断;撤销传播时效等源细节仍需冻结。 6. 如需要离线准入,上游须另外发布租户绑定、有效期、撤销传播和缓存可用性规则;未批准前不从本地 TTL 或 ETag 推导业务授权。每次权威检查使用已有读取合同,不新增自造授权接口。 7. provider_ref/credential_ref 由 O 管理的受控注册表解析,包含供应商、允许 Endpoint、API/资源版本、凭据种类、租户作用域及出口/能力限制;AI 业务参数不写入该注册表。Agent 不直连 SaaS,也不接收全局凭据库。 8. D 向被绑定 Agent 交付本执行最小权限配置/凭据;会话元数据、令牌和敏感值不进日志。配置哈希与原 JSON 校验、有效参数映射和权限检查都成功才准入。并发 SDK 客户端不得共享可变的 per-call 参数。 ### 4.3 参数差异表(方向已确认,待进入上游,不是本地 Schema) 现有 model/prompt/voice/speed、ASR 输入/语言/interim、temperature/max_tokens/timeout_ms 和 conversation 字段必须原义传入 SDK/控制器;不能因 SDK 有默认值就省略映射。已有 speed 范围等不在本文件重定义。 | 待源发布的扩展名 | 已确认语义/单位/缺省方向 | 能力与边界要求 | | --- | --- | --- | | `asr.hotwords` | 有界非空词字符串列表;未提供表示不启用用户热词 | S 冻结项数/UTF-8 字节上限和必要的词权重模型;仅适配 SDK 真正支持的表达,不能塞 raw_request | | `asr.vad` | enabled(bool)及获批的语音开始/结束静音阈值(ms);false 与未提供不同 | 明确供应商 VAD 或本地控制器职责,不能双重处理互相截断;阈值范围需供应商证据 | | `llm.top_p` | number,0 < top_p ≤ 1;未提供按版本化能力表明确解释 | 与 temperature 的同时使用/互斥规则逐供应商批准,不擅自丢弃一个参数 | | `tts.volume` | 对外统一 0–1 线性音量;显式 0 表示静音,不是默认音量 | 须验证 SDK 原生单位及转换是否保真;只能离散或无等价语义时先提交变更确认,不能先四舍五入上线 | | 阶段时限 | 分 connect/first_output/idle/total,均整数 ms;与现有 timeout_ms 的优先级须源合同定义 | 网络连接由适配器、流空闲/总时限由控制器共同执行;缺省使用已批准模式 profile 的明确值,不静默沿用 SDK 默认 | 批准参数必须附:必填条件、合法范围、缺省来源、显式零/false 处理、SDK 精确字段/转换、供应商不支持时的拒绝行为和正反例。上表未给齐的供应商范围属于待取证项,不允许本地臆定;metadata 不承担执行参数透传。OpenAI 兼容 SDK 自动重试显式关闭;取消不能触发旧音频重播或二次收费请求。 ## 5. D04/D05:首发 Unary 与最后许可方案 ### 5.1 公共关联和幂等(语义已确认,待正式 Proto 定稿) 保持通信设计 R01–R03/R05/R07–R13 职责,不增加在线发布 R04/R06 空壳。公共字段按已确认方向分层,精确 wire 定义随 Proto 定稿: | 层 | 字段方向/规则 | | --- | --- | | 传输/诊断 | protocol_version、request_id、trace_id;RPC deadline 只限制一次等待,不是业务授权/通话期限;重试可换 request_id,不能换业务幂等键 | | 目标/授权 | dispatcher_epoch、agent_id、cell_id、boot_id、session_generation;节点会话凭据仅安全元数据传输;目标均来自 D 的受控绑定 | | 持久幂等 | operation_id + operation_type + target;内容摘要不可变,同键异内容冲突;业务归属键始终包含原值 tenant_key 与源 execution/call/attempt 标识 | | 配置/控制 | AI 原版本/摘要、SIP applied revision/hash、task_revision、admission_generation 与 resource_reservation_id;缺失/过期/不匹配拒绝 | | 事实提交 | fact_id、fact_digest、observed_at、发生时 boot/source_sequence;当前认证会话与历史事实 boot 分离,D 事务持久接收后才确认 | 错误映射沿用通信设计 §7.1。accepted 仅表示持久接收,applied 需真实屏障/加载/控制证据;NOT_FOUND、超时、CANCELLED、Asterisk 当前通道列表为空均不是“从未拨过”证明。 ### 5.2 共用证书下的激活、代次和撤销 - D 从预配置 Endpoint 列表发 R01 受限探测,校验 TLS SAN/SNI、Agent 群组证书及部署期预期目标,再发 R02 绑定 agent/cell/boot。A 只接受独立 Dispatcher 身份;不能执行 A 自报 URL。 - D 每次取得唯一运行所有权后建立新的 dispatcher_epoch;A 每次启动产生新的 boot_id,旧 boot 的执行许可一律无效,但旧执行/资产占用不清零。generation 在所属 epoch 内单调;epoch 不能按 UUID 大小排序。 - R02 采用持久 activation operation_id:D 先保存 pending 绑定,再由 A 持久接受,D 收到/查询到相同绑定后标 active;回复丢失重查原操作。active 前 A 不获得执行/敏感配置权限。会话令牌用成熟安全随机源,D 仅保存必要校验材料,禁止自研密码协议。 - 激活冲突、旧 epoch、重放、错误 boot、未完成绑定都 fail closed。新 epoch 激活必须在旧 D 已停用/网络隔离/身份撤销可证明后进行;备份恢复不能仅修改一个 generation 数字声称隔离旧进程。 - 共用私钥泄露可能冒充整组 Agent,Endpoint 和会话只能降低误绑定/重放风险,不形成节点级密码学隔离。撤销/轮换针对全组;先关准入、收敛许可并处理在途,再替换证书和会话。不能关闭主机名验证或以风险声明替代演练。 ### 5.3 最后许可的持久顺序(已确认安全边界) 内部阶段为 prepared → permit_granted → dispatching → observed/unknown → terminal;这些不是新增 MQ status。资源预留、文件记录、D 账本和 Asterisk 事实分别承担职责,不宣称跨 SQLite/文件/ARI 原子事务。 1. D 事务建立原执行/attempt 的发起意图及完整资源预留、唯一 Agent/Cell 路由和配置绑定,持久后才 R07。A 校验后先持久执行文件,R07 重复只能返回原决定,不能发起通话。 2. A 准备发起时,以原 attempt 和唯一 permit 请求 R08。D 在一个短 SQLite 事务内校验当前任务控制、准入代次、会话/健康/版本、授权时段/截止、供应商矩阵及全部额度,再记录唯一 permit_id 和有效期;不跨网络持有 SQLite 写事务。 3. 同 permit 操作重试返回原许可/原期限,不延长授权、不另计一份并发。CPS 在最后许可发放时不可重复扣减地记入限速窗口;许可未使用也不在窗口内提前退 CPS。但许可速率不能直接当真实发起速率:不同许可可能因传输/调度延迟集中提交。P1对每个共享资源采用保守窗口,在任意“源CPS统计窗口+最大许可TTL+时钟安全余量”内发放的许可不超过原窗口预算,同时保留原突发上限;不得各Cell自行发满一份。该办法降低可用吞吐,须由O按供应商实际CPS口径批准,并用两Cell延迟/集中提交负例验证,不能擅自缩短窗口换吞吐。并发释放另依实际可证明终态判断,不能将两者混为退款。 4. A 在统一的**本地发起/控制串行区**检查 boot/session、控制/准入代次、实际加载快照和许可期限,持久记录 dispatching 及确定的 ARI 通道关联后,才允许至多一次 originate 提交。R05/R09 关闭准入也进入该串行区;检查与提交之间不能让控制悄悄穿过。 5. 串行区不能无限等 ARI:网络等待有界,超时/进程中断即保留 unknown;已经提交或可能提交的请求不以同 ID 再次 originate。ARI 客户端对该操作禁止透明自动重试;确定通道 ID 用于关联对账,不单独构成 exactly-once 证明。 6. A 用本机单调时钟对一次 R08 请求建立有效期上界:计时从请求发出起,不从响应收到起;同请求重试不重置起点。D 返回剩余有效期不得超过原许可期限/业务截止。绝对授权截止还须检查批准的时钟偏差安全余量;RPC 晚到、时钟异常、失联或本地代次变化拒绝发起。 7. boot 重启不恢复旧单调计时或旧许可;dispatching/unknown 先查本地文件、D 意图和 Asterisk/其它获批证据,不自行重新拨号。prepared 未越过发起点也必须得到 D 对旧许可收敛的明确决定,不能自动续期。 8. R11 提交稳定事实:D 将去重、状态/配额和 MQ outbox 放同一事务,commit 后才成功响应。成功包丢失 A 重报原 fact;A 不得因缺确认删除唯一事实,也不得换 fact_id 制造新结果。 这套顺序选择“宁可保留不确定占用,也不重拨”,不是承诺网络分区下无需对账的 exactly-once。许可控制的本地界线是首次提交 ARI,不是对 Asterisk 发出线上 INVITE 的跨进程原子提交;已经在途的 ARI 请求必须计入未知占用和控制屏障,不能仅等 TTL 就报告无发起可能。许可过期只禁止新的 ARI 提交,不证明过去没有提交,不能自动释放未知占用。CPS还须观测 Asterisk 实际发起时间;若其排队能使供应商实际口径超额,须先用适用的 Asterisk 原生限速/准入能力及成熟 SDK 验证解决,否则阻塞 D04,不以许可窗口通过冒充实际CPS通过。 ### 5.4 pause/stop/维护屏障 D 先 CAS 持久化控制及关闭新许可,再向所有相关 Cell 下发同一控制操作和目标 revision。A 持久关闭门闩、使未使用旧许可失效,报告已提交/可能提交/振铃/接通/未知占用。串行区内抢先提交的发起属于屏障前执行,必须计入控制范围,不能漏掉。 - pause/drain:不新增发起,屏障前已拨出/振铃/接通沿原生命周期继续;暂停后的恢复须新的合法控制/授权,不复活旧许可。 - stop/drain:同样阻止新发起,已提交执行按源 drain 规则结束;stopped 不可恢复。stop/hangup 必须逐项执行获授权挂断并核对终态,超时不当成功。 - 维护/SIP 静态改配:关闭受影响资源,旧许可失效且未知占用完成对账,按维护要求排空后才加载。不能拿任务 pause 的完成条件代替配置安全排空。 - applied 只有在所有必需目标的对应语义均有证据时成立。失联 A/仍可能在途的 ARI 请求保持 applying/reconciling;D 自己等到 TTL 不替代 A 的收敛证据。 ### 5.5 恢复/故障矩阵与内部 PoC 初始 profile | 注入位置 | 必须保留与允许的动作 | 禁止 | | --- | --- | --- | | D commit 前后崩溃、R07 回复丢失 | 原执行/预留/操作恢复并查询原结果 | 改 execution_id 再投;重新发一份额度 | | R08 已提交但回包丢失 | 查/重取原许可和原期限;过期进入收敛 | 新 permit 无限延寿;先退并发再重拨 | | A 写 dispatching 后、ARI 提交前后崩溃 | 按原通道/意图对账;不能证明则 unknown | “通道没找到”即重发 originate | | 控制与最终检查/ARI 提交交错 | 同串行区判定先后,D 等所有目标屏障事实 | 仅 CAS 成功就发 applied | | A 重启/D epoch 更新/时钟跳变 | 废弃旧发起权限,保留旧通话/资产归属 | 新 boot 清空占用;旧事实按旧 boot 丢弃 | | R11 commit 后回复丢失 | 重报同 fact 同摘要,返回原持久结果 | 二次 outbox 事件、跨状态域版本覆盖 | | SQLite 备份恢复、旧 D 仍可能存在 | 隔离旧 D 后受控激活;无证据停止新准入 | 两份 SQLite 并行发许可;NFS 共享文件充当 HA | 以下为**用户已确认、尚未实测的内部隔离 PoC 初始值**,不覆盖验收 §9 的上游基线或真实供应商预算:最终许可 TTL 上限 1000ms、R08 单次 deadline 500ms;一般查询/事实提交单次 deadline 3s;接收控制单次 deadline 1s(不是 applied 完成时限)。重试不得越原业务/许可截止,退避继承已批准 profile;不能证明 TTL/网络/时钟余量时拒绝发起。 每条内部 Unary 编码后上限 512KiB,许可/控制请求上限 64KiB;不传音频/录音字节,不无限批量事实。外部 MQ 256KiB、HTTP JSON 64KiB 等源限制仍独立有效,内部较大上限不能绕过外部上限;超限拒绝/告警而非截断。协议初版仅支持同一批准版本和显式能力集,未知枚举/关键字段拒绝准入;后续兼容范围须有升级测试再扩展,不承诺自动滚动升级。 ## 6. D06–D08:静态交接、录音与运行恢复 ### 6.1 P1 静态制品交接(流程已确认,待正式制品合同) M 是唯一编辑/审批面;制品外层记录 source_release、source_digest、approval_reference、精确 cell/trunk 目标、源 Publication 的 revision/config_sha256 和协议兼容范围。SIP 配置体复用源结构,外层包装不得冒充已有 API 已支持的新字段。 交接顺序:M 批准 → O 核验来源和两个 Cell×至少三供应商授权矩阵 → D 持久关闭资源准入/R05 收敛 → O 经唯一受控入口原子部署/加载 → A/R01 报实际快照与脱敏 Asterisk 加载证据 → D 核验后逐资源开放。审批记录必须证明旧直写入口已关闭。 加载证据至少关联制品版本/哈希、目标、Agent boot、Asterisk 镜像/配置版本、实际加载时间及 SDK/CLI 观测摘要;文件写入成功或 reload 返回 0 不足以证明加载。失败保留关闭准入,人工恢复旧制品同样重新核验;不自动拨电话验证,也不自动启用未获白名单授权的另一出口。 ### 6.2 P1 录音配置与 Agent 直连 OSS 上传(用户已确认) **上传数据面固定为 Agent → OSS;配置/授权控制面为 SaaS → Dispatcher → Agent。Dispatcher 不接收、缓存或代理转发录音文件内容,也不替 Agent 执行 OSS 文件上传。** Agent 从 Dispatcher 取得相关受限配置后,使用官方 OSS SDK/成熟上传客户端直接连接获准 OSS 目标;“Agent 不直连 SaaS”不禁止其直连 OSS。 OSS 配置源仍是 SaaS,D 通过原 recording-uploads/upload_id/complete 流程管理每个录音的上传会话。下发配置包含契约允许的 HTTPS 上传目标、必要 headers/受限上传凭证、有效期及对象/内容绑定;不下发全局长期 AK,不维护 Agent/CLI 的第二套 bucket/AK 配置。S 仍须补齐作用域、size/checksum、续期是否保持原会话及 complete 幂等返回的源细节。 1. A 封口文件并持久元信息,通过 R12 向 D 取得该原录音身份的受限上传配置;D 负责与 SaaS 申请/续期。 2. A 直接把文件内容上传至指定 OSS,不把文件发给 D,也不通过内部 gRPC 传录音字节。D 失联时已有仍有效授权可继续上传;授权过期或缺失则保留原文件,等待 D 恢复后续原会话,不改用本地长期密钥。 3. A 通过 R13 向 D 报告原资产/会话及上传元信息;D 调用 SaaS complete,由 SaaS 独立校验对象。上传成功但 D/complete 不可达时只保留待完成状态,不能发 ready。 4. verified 后 D 事务记录资产状态和 recording.ready outbox,再通过 MQ 回传 OSS ID。PUT/complete 超时分别按原对象/会话幂等对账,恢复不能新建资产或重拨。未定义的续期/查询语义仍阻塞相应恢复分支,不猜测接口。 本地删除条件继承验收 profile:verified、ready 已得到要求的发布确认、无恢复任务且满足保留;MQ confirm 不等于 SaaS 应用收讫,不额外等待不存在的应用 ACK。文本 OSS 归档继续受 GAP-02 延后约束,实时 transcript.updated/opt-out 不等待 OSS。 ### 6.3 运行 profile 与单活恢复登记 审批登记须包含:profile_id/版本/源哈希/覆盖理由、1 D+2 A 的精确资源绑定、租户/供应商/Cell/模式额度、队列与待发起窗口、心跳/许可/时钟余量、磁盘/文件阈值、保留/备份、真实测试号码/线路/费用上限、维护窗口、RPO/RTO 和签收人。 沿用验收 §9/§9.1 的适用基线(例如心跳 2s、租约 10s、失联停新发起、磁盘 70%告警/80%停新准入/60%恢复),拓扑差异只用有批准记录的覆盖;不把 DEV 全局 6 或后续 1000 路当 P1 真实授权。未取得实际预算/供应商上限时填写 blocked,不填虚构数字。 单活采用本机部署监督+成熟 OS 排他锁防止同机双启动,SQLite 保持本地盘,在线备份走成熟驱动/SQLite 支持的备份能力,包含 WAL 一致性;这些不构成跨机隔离。人工迁移/恢复先证明旧 D 停止与发起权限隔离,再恢复库、激活新 epoch、核对两 A 的文件/Asterisk/未决资产和额度,最后开准入。卷丢失时按实际事实损失签收,永久未上传录音不得承诺 RPO=0。 ## 7. D09:独立只读契约包与可重复生成方案 后续进入开发时,在本项目导入一个只读版本目录 `contracts/upstream//`(此目录本轮未创建),完整包含需要的 Schema/OpenAPI/示例及其引用闭包;禁止外部 `$ref` 在构建时联网或越出包目录。本项目自己的批准 Proto 来源单独维护并记录版本,不手写外部业务结构替代源类型。 清单记录:发布 ID、上游仓库/不可变 commit 或发布地址、文件路径与 SHA-256、批准引用、生成器版本/校验参数、源 Schema 方言和许可证。发布方的来源校验与内容哈希都要验证;自报哈希不等于可信来源。 已确认的后续流水线(本轮未执行): 1. 验证来源和全文件哈希,拒绝缺失/额外未声明/路径越界/引用不闭合的文件;导入过程不能覆盖旧已发布版本。 2. 用锁定的成熟生成器从源生成 Go 类型和只读字段索引,并使用锁定的成熟 Schema 校验器显式执行运行时校验;类型生成不等于校验。生成器不支持的关键约束应报阻塞,不手改生成代码绕过。 3. 对上游合法/非法样例执行一致性测试;同输入重建结果必须确定,生成结果差异须在 CI 失败。源升级经过兼容测试而非静默替换。 4. 将项目复制到无父目录、无外部网络依赖的隔离工作区,用已批准依赖缓存完成生成/构建/测试;普通运行不读取父文档目录。维护者导入可以显式取上游发布物,普通构建不可以偷偷读父目录。 5. 字段索引同步由同一源版本生成,本文件提案不进入生成输入。本轮保留现有索引,避免手工改成第二套 Schema。 ## 8. D10:最小 PoC 顺序与证据 复用[组件清单](开源组件选型与复用清单_v0.2.md)现有候选,不新增协议栈。本轮不声称已下载或验证任一精确版本。每个采用项记录 module/tag/commit、源码/依赖哈希、Go 1.27.1 构建、许可证/NOTICE、传递依赖/漏洞处置和适用协议版本。 | 顺序/已有验收域 | 本地最小检查与通过条件 | 失败处理 | | --- | --- | --- | | 1.Schema/生成工具 | 真实上游 3.1/2020-12 特性、严格对象、条件分支、缺省/0/false、引用闭包和中文原值在 Go 中与金样一致;不只编译生成类型 | 换成熟生成/校验工具或修上游;不放宽 Schema | | 2.SQLite+Agent 文件/恢复 | 单 Cell 额度事务、inbox/outbox crash 点、WAL 备份还原;文件使用成熟 FS 原语验证落盘/原子替换/损坏隔离和重启重放 | 驱动不满足先替代;不改成内存字典或 Agent 业务数据库;跨 Cell 额度延期第二阶段 | | 3.Unary/身份/许可 | 成熟 gRPC/mTLS、SAN 错配/重放、R02 丢包、§5 崩溃矩阵、RPC 超时不重拨、同机第二 D 拒绝启动 | D04/D05方案已确认;后续开发时定稿/生成Proto并验证,未通过不得签收 | | 4.ARI/RTP/录音 | 本地固定 digest Asterisk、确定通道关联、ExternalMedia、PCMA/PCM、事件断连与取消清理;故障下注入 originate 响应丢失不得二次提交 | 先换成熟 SDK/修上游;不能手写 ARI/SIP/RTP/G.711 替代 | | 5.ASR/LLM/TTS 参数 | 百炼/火山 ASR、OpenAI 兼容 LLM、火山 TTS 的实际锁定 SDK 对照 §4 记录传参、0/false、取消和重试;Mock 检查边界行为 | SDK 缺能力不走 metadata/raw_request;报阻塞或批准替代 SDK | | 6.MQ/录音交接 | 隔离真实 broker 的 confirm/重投/限流、SQLite outbox、受限上传及 complete 超时恢复;供应商 API 用协议 Mock | 本地通过不替代真实 MQ/OSS/云身份验证 | 每份证据记录环境/mock-mixed-real、版本、输入边界、预期/实际、脱敏日志、失败注入点和残余风险;失败/blocked 不删样本。SDK 本地 Mock 只验证客户端映射,不证明供应商服务端支持、费用或双模式真实可用。真实 SIP/AI/OSS 必须另行授权并分别验收。 ## 9. 确认结果、后续交付与完成判定 D01–D10 的建议已按 §1 用户指令确认,D07 明确为 Agent 取 Dispatcher 配置后直连 OSS 上传。不再重复要求用户审批相同方向。后续优先完成 D02 的上游双模式 Schema 和 D04/D05 的正式 Proto/会话合同,同时由 S 补 D01/D03、M/O 补静态交接、上传会话细节和实际 profile;选型 PoC 与只读包工具验证可以并行准备。 逐项跟踪格式:`确认项 → 用户已确认语义/例外 → 待交付字段/产物 → 上游发布版本/哈希或内部协议版本 → 实施/签收责任人及日期 → PoC/验收证据 → 未决风险`。缺产物/责任人/证据时标为“方案已确认,交付/验证未完成”,不能退回“待用户审批”或冒充“已冻结/通过”;对未给出的字段细节、真实额度/费用以及偏离已确认方案的变更另行确认。 **本轮完成标准:**确认状态、Agent→OSS直传及相关验收要求在文档间一致,父项目权威源未改;不是十项门禁全部通过。后续获得修改上游/创建代码的执行授权再导入发布物、生成 Proto/类型和执行隔离 PoC;本轮不扩大到这些操作。真实云、供应商消费和拨号仍另获明确授权,P1/P2/后续功能分别验收。