diff --git a/AGENTS.md b/AGENTS.md index b74dc3f..f29c9a6 100644 --- a/AGENTS.md +++ b/AGENTS.md @@ -166,7 +166,7 @@ - **OSS相关配置存于Dispatcher配置文件,Agent向Dispatcher领取临时上传TOKEN后直传OSS,不保存长期凭据;SaaS不再下发OSS配置/TOKEN。** D复用官方SDK提供受限TOKEN/目标信息,配置缺失/无效明确失败;不在样例、源码、日志或证据中保存实际密钥/完整TOKEN。过期只允许A显式向D重新申请,不自动续期或向SaaS申请TOKEN;精确配置格式/TOKEN形态/UploadGrant映射另行核验,不猜字段。 - **用户已修订目标:上传仅负责Agent直传及D可靠通知MQ,SaaS后续处理不属本项目职责。** 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/控制等必要请求响应不受此收缩影响。 -- 前一轮MQ-only文档纠正已结束;当前目标已获批准修改本项目契约/代码/配置/测试。精确方案见已确认的 `docs/contracts/mq-only-v2-freeze-proposal.md`:纯Topic精确绑定、拒绝独立通配词段、tenant_key预算196 UTF-8字节、稳定UUID v4、严格JSON配置及15分钟SDK预签名PUT;不得重开已批准方向。旧不可变包/历史证据原样保留,新版须完成Schema/正反例/哈希验证后发布,不把方案确认当实现完成。受影响W01/W02/W04/W05/W07/W08/W11/W12/W13/W14按plan§8.2重新验证。全局唯一D身份/专用Topic及本地D1/D2隔离fixture为当前合同要求,不授权双D业务运行、HA或共享额度。 +- 前一轮MQ-only文档纠正已结束;当前目标已获批准修改本项目契约/代码/配置/测试。精确方案见已确认的 `docs/contracts/mq-only-v1-freeze-proposal.md`:纯Topic精确绑定、拒绝独立通配词段、tenant_key预算196 UTF-8字节、稳定UUID v4、严格JSON配置及15分钟SDK预签名PUT;不得重开已批准方向。当前仅保留现有代码需要的契约包;未发生契约迁移前不新增契约,未使用的旧快照移至 `contracts/archive/`。新版须完成Schema/正反例/哈希验证后发布,不把方案确认当实现完成。受影响W01/W02/W04/W05/W07/W08/W11/W12/W13/W14按plan§8.2重新验证。全局唯一D身份/专用Topic及本地D1/D2隔离fixture为当前合同要求,不授权双D业务运行、HA或共享额度。 - 文本实时事件准确名为transcript.updated,不新增call.transcript别名;OSS文本归档不能替代实时文字/opt-out,缺少专用资产授权接口时明确未启用,不能伪装recording.ready。 - 现有MQ信封command_type/command_id、event_type/aggregate_*与正文已对齐;事件payload专属约束尚需补齐,不把通用object校验当完整验收。字段索引只读生成,不手改成第二套Schema。 - `tenant_key` 原值一对一绑定,不清洗、编码或截断;旧布局224个UTF-8字节预算不能在加入D身份后直接照搬,W01须冻结并验证完整routing key/queue预算及分隔符/通配符边界;超限停止发布并保留源任务。 diff --git a/contracts/archive/README.md b/contracts/archive/README.md new file mode 100644 index 0000000..6fbef32 --- /dev/null +++ b/contracts/archive/README.md @@ -0,0 +1,5 @@ +# Archived contract inputs + +These bundles are no longer embedded or read by the current code. They are kept outside `contracts/upstream/` only to avoid mixing inactive inputs with the contracts currently required by the test/development tree. + +Do not create or update a contract here. Create a new contract only as part of an explicit contract migration. diff --git a/contracts/upstream/2026-09-17-snapshot/SNAPSHOT.json b/contracts/archive/upstream/2026-09-17-snapshot/SNAPSHOT.json similarity index 100% rename from contracts/upstream/2026-09-17-snapshot/SNAPSHOT.json rename to contracts/archive/upstream/2026-09-17-snapshot/SNAPSHOT.json diff --git a/contracts/upstream/2026-09-17-snapshot/ai-config.openapi.yaml b/contracts/archive/upstream/2026-09-17-snapshot/ai-config.openapi.yaml similarity index 100% rename from contracts/upstream/2026-09-17-snapshot/ai-config.openapi.yaml rename to contracts/archive/upstream/2026-09-17-snapshot/ai-config.openapi.yaml diff --git a/contracts/upstream/2026-09-17-snapshot/ai-config.schema.json b/contracts/archive/upstream/2026-09-17-snapshot/ai-config.schema.json similarity index 100% rename from contracts/upstream/2026-09-17-snapshot/ai-config.schema.json rename to contracts/archive/upstream/2026-09-17-snapshot/ai-config.schema.json diff --git a/contracts/upstream/2026-09-17-snapshot/cell-agent.openapi.yaml b/contracts/archive/upstream/2026-09-17-snapshot/cell-agent.openapi.yaml similarity index 100% rename from contracts/upstream/2026-09-17-snapshot/cell-agent.openapi.yaml rename to contracts/archive/upstream/2026-09-17-snapshot/cell-agent.openapi.yaml diff --git a/contracts/upstream/2026-09-17-snapshot/examples/README.md b/contracts/archive/upstream/2026-09-17-snapshot/examples/README.md similarity index 100% rename from contracts/upstream/2026-09-17-snapshot/examples/README.md rename to contracts/archive/upstream/2026-09-17-snapshot/examples/README.md diff --git a/contracts/upstream/2026-09-17-snapshot/examples/agent-version.json b/contracts/archive/upstream/2026-09-17-snapshot/examples/agent-version.json similarity index 100% rename from contracts/upstream/2026-09-17-snapshot/examples/agent-version.json rename to contracts/archive/upstream/2026-09-17-snapshot/examples/agent-version.json diff --git a/contracts/upstream/2026-09-17-snapshot/examples/call.execute.json b/contracts/archive/upstream/2026-09-17-snapshot/examples/call.execute.json similarity index 100% rename from contracts/upstream/2026-09-17-snapshot/examples/call.execute.json rename to contracts/archive/upstream/2026-09-17-snapshot/examples/call.execute.json diff --git a/contracts/upstream/2026-09-17-snapshot/executor.openapi.yaml b/contracts/archive/upstream/2026-09-17-snapshot/executor.openapi.yaml similarity index 100% rename from contracts/upstream/2026-09-17-snapshot/executor.openapi.yaml rename to contracts/archive/upstream/2026-09-17-snapshot/executor.openapi.yaml diff --git a/contracts/upstream/2026-09-17-snapshot/integration-manifest.json b/contracts/archive/upstream/2026-09-17-snapshot/integration-manifest.json similarity index 100% rename from contracts/upstream/2026-09-17-snapshot/integration-manifest.json rename to contracts/archive/upstream/2026-09-17-snapshot/integration-manifest.json diff --git a/contracts/upstream/2026-09-17-snapshot/mock-profile.json b/contracts/archive/upstream/2026-09-17-snapshot/mock-profile.json similarity index 100% rename from contracts/upstream/2026-09-17-snapshot/mock-profile.json rename to contracts/archive/upstream/2026-09-17-snapshot/mock-profile.json diff --git a/contracts/upstream/2026-09-17-snapshot/mq-topology.md b/contracts/archive/upstream/2026-09-17-snapshot/mq-topology.md similarity index 100% rename from contracts/upstream/2026-09-17-snapshot/mq-topology.md rename to contracts/archive/upstream/2026-09-17-snapshot/mq-topology.md diff --git a/contracts/upstream/2026-09-17-snapshot/mq.schema.json b/contracts/archive/upstream/2026-09-17-snapshot/mq.schema.json similarity index 100% rename from contracts/upstream/2026-09-17-snapshot/mq.schema.json rename to contracts/archive/upstream/2026-09-17-snapshot/mq.schema.json diff --git a/contracts/upstream/2026-09-17-snapshot/saas.openapi.yaml b/contracts/archive/upstream/2026-09-17-snapshot/saas.openapi.yaml similarity index 100% rename from contracts/upstream/2026-09-17-snapshot/saas.openapi.yaml rename to contracts/archive/upstream/2026-09-17-snapshot/saas.openapi.yaml diff --git a/contracts/upstream/2026-09-17-snapshot/sip-management.openapi.yaml b/contracts/archive/upstream/2026-09-17-snapshot/sip-management.openapi.yaml similarity index 100% rename from contracts/upstream/2026-09-17-snapshot/sip-management.openapi.yaml rename to contracts/archive/upstream/2026-09-17-snapshot/sip-management.openapi.yaml diff --git a/contracts/upstream/2026-09-18-p1-baseline/README.md b/contracts/archive/upstream/2026-09-18-p1-baseline/README.md similarity index 100% rename from contracts/upstream/2026-09-18-p1-baseline/README.md rename to contracts/archive/upstream/2026-09-18-p1-baseline/README.md diff --git a/contracts/upstream/2026-09-18-p1-baseline/SNAPSHOT.json b/contracts/archive/upstream/2026-09-18-p1-baseline/SNAPSHOT.json similarity index 100% rename from contracts/upstream/2026-09-18-p1-baseline/SNAPSHOT.json rename to contracts/archive/upstream/2026-09-18-p1-baseline/SNAPSHOT.json diff --git a/contracts/upstream/2026-09-18-p1-baseline/ai-authorization.schema.json b/contracts/archive/upstream/2026-09-18-p1-baseline/ai-authorization.schema.json similarity index 100% rename from contracts/upstream/2026-09-18-p1-baseline/ai-authorization.schema.json rename to contracts/archive/upstream/2026-09-18-p1-baseline/ai-authorization.schema.json diff --git a/contracts/upstream/2026-09-18-p1-baseline/ai-config.openapi.yaml b/contracts/archive/upstream/2026-09-18-p1-baseline/ai-config.openapi.yaml similarity index 100% rename from contracts/upstream/2026-09-18-p1-baseline/ai-config.openapi.yaml rename to contracts/archive/upstream/2026-09-18-p1-baseline/ai-config.openapi.yaml diff --git a/contracts/upstream/2026-09-18-p1-baseline/ai-config.schema.json b/contracts/archive/upstream/2026-09-18-p1-baseline/ai-config.schema.json similarity index 100% rename from contracts/upstream/2026-09-18-p1-baseline/ai-config.schema.json rename to contracts/archive/upstream/2026-09-18-p1-baseline/ai-config.schema.json diff --git a/contracts/upstream/2026-09-18-p1-baseline/cell-agent.openapi.yaml b/contracts/archive/upstream/2026-09-18-p1-baseline/cell-agent.openapi.yaml similarity index 100% rename from contracts/upstream/2026-09-18-p1-baseline/cell-agent.openapi.yaml rename to contracts/archive/upstream/2026-09-18-p1-baseline/cell-agent.openapi.yaml diff --git a/contracts/upstream/2026-09-18-p1-baseline/event-payloads.schema.json b/contracts/archive/upstream/2026-09-18-p1-baseline/event-payloads.schema.json similarity index 100% rename from contracts/upstream/2026-09-18-p1-baseline/event-payloads.schema.json rename to contracts/archive/upstream/2026-09-18-p1-baseline/event-payloads.schema.json diff --git a/contracts/upstream/2026-09-18-p1-baseline/examples/README.md b/contracts/archive/upstream/2026-09-18-p1-baseline/examples/README.md similarity index 100% rename from contracts/upstream/2026-09-18-p1-baseline/examples/README.md rename to contracts/archive/upstream/2026-09-18-p1-baseline/examples/README.md diff --git a/contracts/upstream/2026-09-18-p1-baseline/examples/agent-version-asr-only.json b/contracts/archive/upstream/2026-09-18-p1-baseline/examples/agent-version-asr-only.json similarity index 100% rename from contracts/upstream/2026-09-18-p1-baseline/examples/agent-version-asr-only.json rename to contracts/archive/upstream/2026-09-18-p1-baseline/examples/agent-version-asr-only.json diff --git a/contracts/upstream/2026-09-18-p1-baseline/examples/agent-version-full-explicit.json b/contracts/archive/upstream/2026-09-18-p1-baseline/examples/agent-version-full-explicit.json similarity index 100% rename from contracts/upstream/2026-09-18-p1-baseline/examples/agent-version-full-explicit.json rename to contracts/archive/upstream/2026-09-18-p1-baseline/examples/agent-version-full-explicit.json diff --git a/contracts/upstream/2026-09-18-p1-baseline/examples/agent-version.json b/contracts/archive/upstream/2026-09-18-p1-baseline/examples/agent-version.json similarity index 100% rename from contracts/upstream/2026-09-18-p1-baseline/examples/agent-version.json rename to contracts/archive/upstream/2026-09-18-p1-baseline/examples/agent-version.json diff --git a/contracts/upstream/2026-09-18-p1-baseline/examples/ai-authorization.json b/contracts/archive/upstream/2026-09-18-p1-baseline/examples/ai-authorization.json similarity index 100% rename from contracts/upstream/2026-09-18-p1-baseline/examples/ai-authorization.json rename to contracts/archive/upstream/2026-09-18-p1-baseline/examples/ai-authorization.json diff --git a/contracts/upstream/2026-09-18-p1-baseline/examples/call.execute.json b/contracts/archive/upstream/2026-09-18-p1-baseline/examples/call.execute.json similarity index 100% rename from contracts/upstream/2026-09-18-p1-baseline/examples/call.execute.json rename to contracts/archive/upstream/2026-09-18-p1-baseline/examples/call.execute.json diff --git a/contracts/upstream/2026-09-18-p1-baseline/examples/event-call-finished.json b/contracts/archive/upstream/2026-09-18-p1-baseline/examples/event-call-finished.json similarity index 100% rename from contracts/upstream/2026-09-18-p1-baseline/examples/event-call-finished.json rename to contracts/archive/upstream/2026-09-18-p1-baseline/examples/event-call-finished.json diff --git a/contracts/upstream/2026-09-18-p1-baseline/examples/event-call-status.json b/contracts/archive/upstream/2026-09-18-p1-baseline/examples/event-call-status.json similarity index 100% rename from contracts/upstream/2026-09-18-p1-baseline/examples/event-call-status.json rename to contracts/archive/upstream/2026-09-18-p1-baseline/examples/event-call-status.json diff --git a/contracts/upstream/2026-09-18-p1-baseline/examples/event-command-result.json b/contracts/archive/upstream/2026-09-18-p1-baseline/examples/event-command-result.json similarity index 100% rename from contracts/upstream/2026-09-18-p1-baseline/examples/event-command-result.json rename to contracts/archive/upstream/2026-09-18-p1-baseline/examples/event-command-result.json diff --git a/contracts/upstream/2026-09-18-p1-baseline/examples/event-contact-opt-out.json b/contracts/archive/upstream/2026-09-18-p1-baseline/examples/event-contact-opt-out.json similarity index 100% rename from contracts/upstream/2026-09-18-p1-baseline/examples/event-contact-opt-out.json rename to contracts/archive/upstream/2026-09-18-p1-baseline/examples/event-contact-opt-out.json diff --git a/contracts/upstream/2026-09-18-p1-baseline/examples/event-recording-failed.json b/contracts/archive/upstream/2026-09-18-p1-baseline/examples/event-recording-failed.json similarity index 100% rename from contracts/upstream/2026-09-18-p1-baseline/examples/event-recording-failed.json rename to contracts/archive/upstream/2026-09-18-p1-baseline/examples/event-recording-failed.json diff --git a/contracts/upstream/2026-09-18-p1-baseline/examples/event-recording-ready.json b/contracts/archive/upstream/2026-09-18-p1-baseline/examples/event-recording-ready.json similarity index 100% rename from contracts/upstream/2026-09-18-p1-baseline/examples/event-recording-ready.json rename to contracts/archive/upstream/2026-09-18-p1-baseline/examples/event-recording-ready.json diff --git a/contracts/upstream/2026-09-18-p1-baseline/examples/event-transcript-failed.json b/contracts/archive/upstream/2026-09-18-p1-baseline/examples/event-transcript-failed.json similarity index 100% rename from contracts/upstream/2026-09-18-p1-baseline/examples/event-transcript-failed.json rename to contracts/archive/upstream/2026-09-18-p1-baseline/examples/event-transcript-failed.json diff --git a/contracts/upstream/2026-09-18-p1-baseline/examples/event-transcript-updated.json b/contracts/archive/upstream/2026-09-18-p1-baseline/examples/event-transcript-updated.json similarity index 100% rename from contracts/upstream/2026-09-18-p1-baseline/examples/event-transcript-updated.json rename to contracts/archive/upstream/2026-09-18-p1-baseline/examples/event-transcript-updated.json diff --git a/contracts/upstream/2026-09-18-p1-baseline/examples/invalid-ai-authorization-revoked.json b/contracts/archive/upstream/2026-09-18-p1-baseline/examples/invalid-ai-authorization-revoked.json similarity index 100% rename from contracts/upstream/2026-09-18-p1-baseline/examples/invalid-ai-authorization-revoked.json rename to contracts/archive/upstream/2026-09-18-p1-baseline/examples/invalid-ai-authorization-revoked.json diff --git a/contracts/upstream/2026-09-18-p1-baseline/examples/invalid-asr-only-with-llm.json b/contracts/archive/upstream/2026-09-18-p1-baseline/examples/invalid-asr-only-with-llm.json similarity index 100% rename from contracts/upstream/2026-09-18-p1-baseline/examples/invalid-asr-only-with-llm.json rename to contracts/archive/upstream/2026-09-18-p1-baseline/examples/invalid-asr-only-with-llm.json diff --git a/contracts/upstream/2026-09-18-p1-baseline/examples/invalid-event-unknown-type.json b/contracts/archive/upstream/2026-09-18-p1-baseline/examples/invalid-event-unknown-type.json similarity index 100% rename from contracts/upstream/2026-09-18-p1-baseline/examples/invalid-event-unknown-type.json rename to contracts/archive/upstream/2026-09-18-p1-baseline/examples/invalid-event-unknown-type.json diff --git a/contracts/upstream/2026-09-18-p1-baseline/examples/invalid-oss-upload-http.json b/contracts/archive/upstream/2026-09-18-p1-baseline/examples/invalid-oss-upload-http.json similarity index 100% rename from contracts/upstream/2026-09-18-p1-baseline/examples/invalid-oss-upload-http.json rename to contracts/archive/upstream/2026-09-18-p1-baseline/examples/invalid-oss-upload-http.json diff --git a/contracts/upstream/2026-09-18-p1-baseline/examples/oss-upload-grant.json b/contracts/archive/upstream/2026-09-18-p1-baseline/examples/oss-upload-grant.json similarity index 100% rename from contracts/upstream/2026-09-18-p1-baseline/examples/oss-upload-grant.json rename to contracts/archive/upstream/2026-09-18-p1-baseline/examples/oss-upload-grant.json diff --git a/contracts/upstream/2026-09-18-p1-baseline/examples/static-cell-artifact.json b/contracts/archive/upstream/2026-09-18-p1-baseline/examples/static-cell-artifact.json similarity index 100% rename from contracts/upstream/2026-09-18-p1-baseline/examples/static-cell-artifact.json rename to contracts/archive/upstream/2026-09-18-p1-baseline/examples/static-cell-artifact.json diff --git a/contracts/upstream/2026-09-18-p1-baseline/executor.openapi.yaml b/contracts/archive/upstream/2026-09-18-p1-baseline/executor.openapi.yaml similarity index 100% rename from contracts/upstream/2026-09-18-p1-baseline/executor.openapi.yaml rename to contracts/archive/upstream/2026-09-18-p1-baseline/executor.openapi.yaml diff --git a/contracts/upstream/2026-09-18-p1-baseline/mock-profile.json b/contracts/archive/upstream/2026-09-18-p1-baseline/mock-profile.json similarity index 100% rename from contracts/upstream/2026-09-18-p1-baseline/mock-profile.json rename to contracts/archive/upstream/2026-09-18-p1-baseline/mock-profile.json diff --git a/contracts/upstream/2026-09-18-p1-baseline/mq-topology.md b/contracts/archive/upstream/2026-09-18-p1-baseline/mq-topology.md similarity index 100% rename from contracts/upstream/2026-09-18-p1-baseline/mq-topology.md rename to contracts/archive/upstream/2026-09-18-p1-baseline/mq-topology.md diff --git a/contracts/upstream/2026-09-18-p1-baseline/mq.schema.json b/contracts/archive/upstream/2026-09-18-p1-baseline/mq.schema.json similarity index 100% rename from contracts/upstream/2026-09-18-p1-baseline/mq.schema.json rename to contracts/archive/upstream/2026-09-18-p1-baseline/mq.schema.json diff --git a/contracts/upstream/2026-09-18-p1-baseline/oss-upload.schema.json b/contracts/archive/upstream/2026-09-18-p1-baseline/oss-upload.schema.json similarity index 100% rename from contracts/upstream/2026-09-18-p1-baseline/oss-upload.schema.json rename to contracts/archive/upstream/2026-09-18-p1-baseline/oss-upload.schema.json diff --git a/contracts/upstream/2026-09-18-p1-baseline/p1-development-profile.json b/contracts/archive/upstream/2026-09-18-p1-baseline/p1-development-profile.json similarity index 100% rename from contracts/upstream/2026-09-18-p1-baseline/p1-development-profile.json rename to contracts/archive/upstream/2026-09-18-p1-baseline/p1-development-profile.json diff --git a/contracts/upstream/2026-09-18-p1-baseline/p1-development-profile.schema.json b/contracts/archive/upstream/2026-09-18-p1-baseline/p1-development-profile.schema.json similarity index 100% rename from contracts/upstream/2026-09-18-p1-baseline/p1-development-profile.schema.json rename to contracts/archive/upstream/2026-09-18-p1-baseline/p1-development-profile.schema.json diff --git a/contracts/upstream/2026-09-18-p1-baseline/release-manifest.json b/contracts/archive/upstream/2026-09-18-p1-baseline/release-manifest.json similarity index 100% rename from contracts/upstream/2026-09-18-p1-baseline/release-manifest.json rename to contracts/archive/upstream/2026-09-18-p1-baseline/release-manifest.json diff --git a/contracts/upstream/2026-09-18-p1-baseline/saas.openapi.yaml b/contracts/archive/upstream/2026-09-18-p1-baseline/saas.openapi.yaml similarity index 100% rename from contracts/upstream/2026-09-18-p1-baseline/saas.openapi.yaml rename to contracts/archive/upstream/2026-09-18-p1-baseline/saas.openapi.yaml diff --git a/contracts/upstream/2026-09-18-p1-baseline/sip-management.openapi.yaml b/contracts/archive/upstream/2026-09-18-p1-baseline/sip-management.openapi.yaml similarity index 100% rename from contracts/upstream/2026-09-18-p1-baseline/sip-management.openapi.yaml rename to contracts/archive/upstream/2026-09-18-p1-baseline/sip-management.openapi.yaml diff --git a/contracts/upstream/2026-09-18-p1-baseline/static-cell-artifact.schema.json b/contracts/archive/upstream/2026-09-18-p1-baseline/static-cell-artifact.schema.json similarity index 100% rename from contracts/upstream/2026-09-18-p1-baseline/static-cell-artifact.schema.json rename to contracts/archive/upstream/2026-09-18-p1-baseline/static-cell-artifact.schema.json diff --git a/contracts/upstream/2026-09-19-p1-v1/README.md b/contracts/archive/upstream/2026-09-19-p1-v1-legacy/README.md similarity index 100% rename from contracts/upstream/2026-09-19-p1-v1/README.md rename to contracts/archive/upstream/2026-09-19-p1-v1-legacy/README.md diff --git a/contracts/upstream/2026-09-19-p1-v1/SNAPSHOT.json b/contracts/archive/upstream/2026-09-19-p1-v1-legacy/SNAPSHOT.json similarity index 100% rename from contracts/upstream/2026-09-19-p1-v1/SNAPSHOT.json rename to contracts/archive/upstream/2026-09-19-p1-v1-legacy/SNAPSHOT.json diff --git a/contracts/upstream/2026-09-19-p1-v1/ai-authorization.schema.json b/contracts/archive/upstream/2026-09-19-p1-v1-legacy/ai-authorization.schema.json similarity index 100% rename from contracts/upstream/2026-09-19-p1-v1/ai-authorization.schema.json rename to contracts/archive/upstream/2026-09-19-p1-v1-legacy/ai-authorization.schema.json diff --git a/contracts/upstream/2026-09-19-p1-v1/ai-config.openapi.yaml b/contracts/archive/upstream/2026-09-19-p1-v1-legacy/ai-config.openapi.yaml similarity index 100% rename from contracts/upstream/2026-09-19-p1-v1/ai-config.openapi.yaml rename to contracts/archive/upstream/2026-09-19-p1-v1-legacy/ai-config.openapi.yaml diff --git a/contracts/upstream/2026-09-19-p1-v1/ai-config.schema.json b/contracts/archive/upstream/2026-09-19-p1-v1-legacy/ai-config.schema.json similarity index 100% rename from contracts/upstream/2026-09-19-p1-v1/ai-config.schema.json rename to contracts/archive/upstream/2026-09-19-p1-v1-legacy/ai-config.schema.json diff --git a/contracts/upstream/2026-09-19-p1-v1/cell-agent.openapi.yaml b/contracts/archive/upstream/2026-09-19-p1-v1-legacy/cell-agent.openapi.yaml similarity index 100% rename from contracts/upstream/2026-09-19-p1-v1/cell-agent.openapi.yaml rename to contracts/archive/upstream/2026-09-19-p1-v1-legacy/cell-agent.openapi.yaml diff --git a/contracts/upstream/2026-09-19-p1-v1/event-payloads.schema.json b/contracts/archive/upstream/2026-09-19-p1-v1-legacy/event-payloads.schema.json similarity index 100% rename from contracts/upstream/2026-09-19-p1-v1/event-payloads.schema.json rename to contracts/archive/upstream/2026-09-19-p1-v1-legacy/event-payloads.schema.json diff --git a/contracts/upstream/2026-09-19-p1-v1/examples/README.md b/contracts/archive/upstream/2026-09-19-p1-v1-legacy/examples/README.md similarity index 100% rename from contracts/upstream/2026-09-19-p1-v1/examples/README.md rename to contracts/archive/upstream/2026-09-19-p1-v1-legacy/examples/README.md diff --git a/contracts/upstream/2026-09-19-p1-v1/examples/agent-version-asr-only.json b/contracts/archive/upstream/2026-09-19-p1-v1-legacy/examples/agent-version-asr-only.json similarity index 100% rename from contracts/upstream/2026-09-19-p1-v1/examples/agent-version-asr-only.json rename to contracts/archive/upstream/2026-09-19-p1-v1-legacy/examples/agent-version-asr-only.json diff --git a/contracts/upstream/2026-09-19-p1-v1/examples/agent-version-full-explicit.json b/contracts/archive/upstream/2026-09-19-p1-v1-legacy/examples/agent-version-full-explicit.json similarity index 100% rename from contracts/upstream/2026-09-19-p1-v1/examples/agent-version-full-explicit.json rename to contracts/archive/upstream/2026-09-19-p1-v1-legacy/examples/agent-version-full-explicit.json diff --git a/contracts/upstream/2026-09-19-p1-v1/examples/agent-version-full-production-v1.json b/contracts/archive/upstream/2026-09-19-p1-v1-legacy/examples/agent-version-full-production-v1.json similarity index 100% rename from contracts/upstream/2026-09-19-p1-v1/examples/agent-version-full-production-v1.json rename to contracts/archive/upstream/2026-09-19-p1-v1-legacy/examples/agent-version-full-production-v1.json diff --git a/contracts/upstream/2026-09-19-p1-v1/examples/agent-version.json b/contracts/archive/upstream/2026-09-19-p1-v1-legacy/examples/agent-version.json similarity index 100% rename from contracts/upstream/2026-09-19-p1-v1/examples/agent-version.json rename to contracts/archive/upstream/2026-09-19-p1-v1-legacy/examples/agent-version.json diff --git a/contracts/upstream/2026-09-19-p1-v1/examples/ai-authorization.json b/contracts/archive/upstream/2026-09-19-p1-v1-legacy/examples/ai-authorization.json similarity index 100% rename from contracts/upstream/2026-09-19-p1-v1/examples/ai-authorization.json rename to contracts/archive/upstream/2026-09-19-p1-v1-legacy/examples/ai-authorization.json diff --git a/contracts/upstream/2026-09-19-p1-v1/examples/call.execute.json b/contracts/archive/upstream/2026-09-19-p1-v1-legacy/examples/call.execute.json similarity index 100% rename from contracts/upstream/2026-09-19-p1-v1/examples/call.execute.json rename to contracts/archive/upstream/2026-09-19-p1-v1-legacy/examples/call.execute.json diff --git a/contracts/upstream/2026-09-19-p1-v1/examples/event-call-finished.json b/contracts/archive/upstream/2026-09-19-p1-v1-legacy/examples/event-call-finished.json similarity index 100% rename from contracts/upstream/2026-09-19-p1-v1/examples/event-call-finished.json rename to contracts/archive/upstream/2026-09-19-p1-v1-legacy/examples/event-call-finished.json diff --git a/contracts/upstream/2026-09-19-p1-v1/examples/event-call-status.json b/contracts/archive/upstream/2026-09-19-p1-v1-legacy/examples/event-call-status.json similarity index 100% rename from contracts/upstream/2026-09-19-p1-v1/examples/event-call-status.json rename to contracts/archive/upstream/2026-09-19-p1-v1-legacy/examples/event-call-status.json diff --git a/contracts/upstream/2026-09-19-p1-v1/examples/event-command-result.json b/contracts/archive/upstream/2026-09-19-p1-v1-legacy/examples/event-command-result.json similarity index 100% rename from contracts/upstream/2026-09-19-p1-v1/examples/event-command-result.json rename to contracts/archive/upstream/2026-09-19-p1-v1-legacy/examples/event-command-result.json diff --git a/contracts/upstream/2026-09-19-p1-v1/examples/event-contact-opt-out.json b/contracts/archive/upstream/2026-09-19-p1-v1-legacy/examples/event-contact-opt-out.json similarity index 100% rename from contracts/upstream/2026-09-19-p1-v1/examples/event-contact-opt-out.json rename to contracts/archive/upstream/2026-09-19-p1-v1-legacy/examples/event-contact-opt-out.json diff --git a/contracts/upstream/2026-09-19-p1-v1/examples/event-recording-failed.json b/contracts/archive/upstream/2026-09-19-p1-v1-legacy/examples/event-recording-failed.json similarity index 100% rename from contracts/upstream/2026-09-19-p1-v1/examples/event-recording-failed.json rename to contracts/archive/upstream/2026-09-19-p1-v1-legacy/examples/event-recording-failed.json diff --git a/contracts/upstream/2026-09-19-p1-v1/examples/event-recording-ready.json b/contracts/archive/upstream/2026-09-19-p1-v1-legacy/examples/event-recording-ready.json similarity index 100% rename from contracts/upstream/2026-09-19-p1-v1/examples/event-recording-ready.json rename to contracts/archive/upstream/2026-09-19-p1-v1-legacy/examples/event-recording-ready.json diff --git a/contracts/upstream/2026-09-19-p1-v1/examples/event-transcript-failed.json b/contracts/archive/upstream/2026-09-19-p1-v1-legacy/examples/event-transcript-failed.json similarity index 100% rename from contracts/upstream/2026-09-19-p1-v1/examples/event-transcript-failed.json rename to contracts/archive/upstream/2026-09-19-p1-v1-legacy/examples/event-transcript-failed.json diff --git a/contracts/upstream/2026-09-19-p1-v1/examples/event-transcript-updated.json b/contracts/archive/upstream/2026-09-19-p1-v1-legacy/examples/event-transcript-updated.json similarity index 100% rename from contracts/upstream/2026-09-19-p1-v1/examples/event-transcript-updated.json rename to contracts/archive/upstream/2026-09-19-p1-v1-legacy/examples/event-transcript-updated.json diff --git a/contracts/upstream/2026-09-19-p1-v1/examples/invalid-ai-authorization-revoked.json b/contracts/archive/upstream/2026-09-19-p1-v1-legacy/examples/invalid-ai-authorization-revoked.json similarity index 100% rename from contracts/upstream/2026-09-19-p1-v1/examples/invalid-ai-authorization-revoked.json rename to contracts/archive/upstream/2026-09-19-p1-v1-legacy/examples/invalid-ai-authorization-revoked.json diff --git a/contracts/upstream/2026-09-19-p1-v1/examples/invalid-asr-only-with-llm.json b/contracts/archive/upstream/2026-09-19-p1-v1-legacy/examples/invalid-asr-only-with-llm.json similarity index 100% rename from contracts/upstream/2026-09-19-p1-v1/examples/invalid-asr-only-with-llm.json rename to contracts/archive/upstream/2026-09-19-p1-v1-legacy/examples/invalid-asr-only-with-llm.json diff --git a/contracts/upstream/2026-09-19-p1-v1/examples/invalid-event-unknown-type.json b/contracts/archive/upstream/2026-09-19-p1-v1-legacy/examples/invalid-event-unknown-type.json similarity index 100% rename from contracts/upstream/2026-09-19-p1-v1/examples/invalid-event-unknown-type.json rename to contracts/archive/upstream/2026-09-19-p1-v1-legacy/examples/invalid-event-unknown-type.json diff --git a/contracts/upstream/2026-09-19-p1-v1/examples/invalid-oss-upload-http.json b/contracts/archive/upstream/2026-09-19-p1-v1-legacy/examples/invalid-oss-upload-http.json similarity index 100% rename from contracts/upstream/2026-09-19-p1-v1/examples/invalid-oss-upload-http.json rename to contracts/archive/upstream/2026-09-19-p1-v1-legacy/examples/invalid-oss-upload-http.json diff --git a/contracts/upstream/2026-09-19-p1-v1/examples/oss-upload-grant.json b/contracts/archive/upstream/2026-09-19-p1-v1-legacy/examples/oss-upload-grant.json similarity index 100% rename from contracts/upstream/2026-09-19-p1-v1/examples/oss-upload-grant.json rename to contracts/archive/upstream/2026-09-19-p1-v1-legacy/examples/oss-upload-grant.json diff --git a/contracts/upstream/2026-09-19-p1-v1/examples/static-cell-artifact-real-v1.json b/contracts/archive/upstream/2026-09-19-p1-v1-legacy/examples/static-cell-artifact-real-v1.json similarity index 100% rename from contracts/upstream/2026-09-19-p1-v1/examples/static-cell-artifact-real-v1.json rename to contracts/archive/upstream/2026-09-19-p1-v1-legacy/examples/static-cell-artifact-real-v1.json diff --git a/contracts/upstream/2026-09-19-p1-v1/examples/static-cell-artifact.json b/contracts/archive/upstream/2026-09-19-p1-v1-legacy/examples/static-cell-artifact.json similarity index 100% rename from contracts/upstream/2026-09-19-p1-v1/examples/static-cell-artifact.json rename to contracts/archive/upstream/2026-09-19-p1-v1-legacy/examples/static-cell-artifact.json diff --git a/contracts/upstream/2026-09-19-p1-v1/executor.openapi.yaml b/contracts/archive/upstream/2026-09-19-p1-v1-legacy/executor.openapi.yaml similarity index 100% rename from contracts/upstream/2026-09-19-p1-v1/executor.openapi.yaml rename to contracts/archive/upstream/2026-09-19-p1-v1-legacy/executor.openapi.yaml diff --git a/contracts/upstream/2026-09-19-p1-v1/mock-profile.json b/contracts/archive/upstream/2026-09-19-p1-v1-legacy/mock-profile.json similarity index 100% rename from contracts/upstream/2026-09-19-p1-v1/mock-profile.json rename to contracts/archive/upstream/2026-09-19-p1-v1-legacy/mock-profile.json diff --git a/contracts/upstream/2026-09-19-p1-v1/mq-topology.md b/contracts/archive/upstream/2026-09-19-p1-v1-legacy/mq-topology.md similarity index 100% rename from contracts/upstream/2026-09-19-p1-v1/mq-topology.md rename to contracts/archive/upstream/2026-09-19-p1-v1-legacy/mq-topology.md diff --git a/contracts/upstream/2026-09-19-p1-v1/mq.schema.json b/contracts/archive/upstream/2026-09-19-p1-v1-legacy/mq.schema.json similarity index 100% rename from contracts/upstream/2026-09-19-p1-v1/mq.schema.json rename to contracts/archive/upstream/2026-09-19-p1-v1-legacy/mq.schema.json diff --git a/contracts/upstream/2026-09-19-p1-v1/oss-upload.schema.json b/contracts/archive/upstream/2026-09-19-p1-v1-legacy/oss-upload.schema.json similarity index 100% rename from contracts/upstream/2026-09-19-p1-v1/oss-upload.schema.json rename to contracts/archive/upstream/2026-09-19-p1-v1-legacy/oss-upload.schema.json diff --git a/contracts/upstream/2026-09-19-p1-v1/p1-development-profile.json b/contracts/archive/upstream/2026-09-19-p1-v1-legacy/p1-development-profile.json similarity index 100% rename from contracts/upstream/2026-09-19-p1-v1/p1-development-profile.json rename to contracts/archive/upstream/2026-09-19-p1-v1-legacy/p1-development-profile.json diff --git a/contracts/upstream/2026-09-19-p1-v1/p1-development-profile.schema.json b/contracts/archive/upstream/2026-09-19-p1-v1-legacy/p1-development-profile.schema.json similarity index 100% rename from contracts/upstream/2026-09-19-p1-v1/p1-development-profile.schema.json rename to contracts/archive/upstream/2026-09-19-p1-v1-legacy/p1-development-profile.schema.json diff --git a/contracts/upstream/2026-09-19-p1-v1/release-manifest.json b/contracts/archive/upstream/2026-09-19-p1-v1-legacy/release-manifest.json similarity index 100% rename from contracts/upstream/2026-09-19-p1-v1/release-manifest.json rename to contracts/archive/upstream/2026-09-19-p1-v1-legacy/release-manifest.json diff --git a/contracts/upstream/2026-09-19-p1-v1/saas.openapi.yaml b/contracts/archive/upstream/2026-09-19-p1-v1-legacy/saas.openapi.yaml similarity index 100% rename from contracts/upstream/2026-09-19-p1-v1/saas.openapi.yaml rename to contracts/archive/upstream/2026-09-19-p1-v1-legacy/saas.openapi.yaml diff --git a/contracts/upstream/2026-09-19-p1-v1/sip-management.openapi.yaml b/contracts/archive/upstream/2026-09-19-p1-v1-legacy/sip-management.openapi.yaml similarity index 100% rename from contracts/upstream/2026-09-19-p1-v1/sip-management.openapi.yaml rename to contracts/archive/upstream/2026-09-19-p1-v1-legacy/sip-management.openapi.yaml diff --git a/contracts/upstream/2026-09-19-p1-v1/static-cell-artifact.schema.json b/contracts/archive/upstream/2026-09-19-p1-v1-legacy/static-cell-artifact.schema.json similarity index 100% rename from contracts/upstream/2026-09-19-p1-v1/static-cell-artifact.schema.json rename to contracts/archive/upstream/2026-09-19-p1-v1-legacy/static-cell-artifact.schema.json diff --git a/contracts/upstream/2026-09-21-p1-v2/README.md b/contracts/archive/upstream/2026-09-21-p1-v2/README.md similarity index 100% rename from contracts/upstream/2026-09-21-p1-v2/README.md rename to contracts/archive/upstream/2026-09-21-p1-v2/README.md diff --git a/contracts/upstream/2026-09-21-p1-v2/ai-authorization.schema.json b/contracts/archive/upstream/2026-09-21-p1-v2/ai-authorization.schema.json similarity index 100% rename from contracts/upstream/2026-09-21-p1-v2/ai-authorization.schema.json rename to contracts/archive/upstream/2026-09-21-p1-v2/ai-authorization.schema.json diff --git a/contracts/upstream/2026-09-21-p1-v2/ai-config.schema.json b/contracts/archive/upstream/2026-09-21-p1-v2/ai-config.schema.json similarity index 100% rename from contracts/upstream/2026-09-21-p1-v2/ai-config.schema.json rename to contracts/archive/upstream/2026-09-21-p1-v2/ai-config.schema.json diff --git a/contracts/upstream/2026-09-21-p1-v2/dispatcher-config.schema.json b/contracts/archive/upstream/2026-09-21-p1-v2/dispatcher-config.schema.json similarity index 100% rename from contracts/upstream/2026-09-21-p1-v2/dispatcher-config.schema.json rename to contracts/archive/upstream/2026-09-21-p1-v2/dispatcher-config.schema.json diff --git a/contracts/upstream/2026-09-21-p1-v2/event-payloads.schema.json b/contracts/archive/upstream/2026-09-21-p1-v2/event-payloads.schema.json similarity index 100% rename from contracts/upstream/2026-09-21-p1-v2/event-payloads.schema.json rename to contracts/archive/upstream/2026-09-21-p1-v2/event-payloads.schema.json diff --git a/contracts/upstream/2026-09-21-p1-v2/examples/ai-config-request.json b/contracts/archive/upstream/2026-09-21-p1-v2/examples/ai-config-request.json similarity index 100% rename from contracts/upstream/2026-09-21-p1-v2/examples/ai-config-request.json rename to contracts/archive/upstream/2026-09-21-p1-v2/examples/ai-config-request.json diff --git a/contracts/upstream/2026-09-21-p1-v2/examples/ai-config-result.json b/contracts/archive/upstream/2026-09-21-p1-v2/examples/ai-config-result.json similarity index 100% rename from contracts/upstream/2026-09-21-p1-v2/examples/ai-config-result.json rename to contracts/archive/upstream/2026-09-21-p1-v2/examples/ai-config-result.json diff --git a/contracts/upstream/2026-09-21-p1-v2/examples/call-execute.json b/contracts/archive/upstream/2026-09-21-p1-v2/examples/call-execute.json similarity index 100% rename from contracts/upstream/2026-09-21-p1-v2/examples/call-execute.json rename to contracts/archive/upstream/2026-09-21-p1-v2/examples/call-execute.json diff --git a/contracts/upstream/2026-09-21-p1-v2/examples/call-query-result.json b/contracts/archive/upstream/2026-09-21-p1-v2/examples/call-query-result.json similarity index 100% rename from contracts/upstream/2026-09-21-p1-v2/examples/call-query-result.json rename to contracts/archive/upstream/2026-09-21-p1-v2/examples/call-query-result.json diff --git a/contracts/upstream/2026-09-21-p1-v2/examples/call-query.json b/contracts/archive/upstream/2026-09-21-p1-v2/examples/call-query.json similarity index 100% rename from contracts/upstream/2026-09-21-p1-v2/examples/call-query.json rename to contracts/archive/upstream/2026-09-21-p1-v2/examples/call-query.json diff --git a/contracts/upstream/2026-09-21-p1-v2/examples/call-replay.json b/contracts/archive/upstream/2026-09-21-p1-v2/examples/call-replay.json similarity index 100% rename from contracts/upstream/2026-09-21-p1-v2/examples/call-replay.json rename to contracts/archive/upstream/2026-09-21-p1-v2/examples/call-replay.json diff --git a/contracts/upstream/2026-09-21-p1-v2/examples/command-query-result.json b/contracts/archive/upstream/2026-09-21-p1-v2/examples/command-query-result.json similarity index 100% rename from contracts/upstream/2026-09-21-p1-v2/examples/command-query-result.json rename to contracts/archive/upstream/2026-09-21-p1-v2/examples/command-query-result.json diff --git a/contracts/upstream/2026-09-21-p1-v2/examples/command-query.json b/contracts/archive/upstream/2026-09-21-p1-v2/examples/command-query.json similarity index 100% rename from contracts/upstream/2026-09-21-p1-v2/examples/command-query.json rename to contracts/archive/upstream/2026-09-21-p1-v2/examples/command-query.json diff --git a/contracts/upstream/2026-09-21-p1-v2/examples/command-replay.json b/contracts/archive/upstream/2026-09-21-p1-v2/examples/command-replay.json similarity index 100% rename from contracts/upstream/2026-09-21-p1-v2/examples/command-replay.json rename to contracts/archive/upstream/2026-09-21-p1-v2/examples/command-replay.json diff --git a/contracts/upstream/2026-09-21-p1-v2/examples/dispatcher-config.json b/contracts/archive/upstream/2026-09-21-p1-v2/examples/dispatcher-config.json similarity index 100% rename from contracts/upstream/2026-09-21-p1-v2/examples/dispatcher-config.json rename to contracts/archive/upstream/2026-09-21-p1-v2/examples/dispatcher-config.json diff --git a/contracts/upstream/2026-09-21-p1-v2/examples/event-call-finished.json b/contracts/archive/upstream/2026-09-21-p1-v2/examples/event-call-finished.json similarity index 100% rename from contracts/upstream/2026-09-21-p1-v2/examples/event-call-finished.json rename to contracts/archive/upstream/2026-09-21-p1-v2/examples/event-call-finished.json diff --git a/contracts/upstream/2026-09-21-p1-v2/examples/event-call-status.json b/contracts/archive/upstream/2026-09-21-p1-v2/examples/event-call-status.json similarity index 100% rename from contracts/upstream/2026-09-21-p1-v2/examples/event-call-status.json rename to contracts/archive/upstream/2026-09-21-p1-v2/examples/event-call-status.json diff --git a/contracts/upstream/2026-09-21-p1-v2/examples/event-command-result.json b/contracts/archive/upstream/2026-09-21-p1-v2/examples/event-command-result.json similarity index 100% rename from contracts/upstream/2026-09-21-p1-v2/examples/event-command-result.json rename to contracts/archive/upstream/2026-09-21-p1-v2/examples/event-command-result.json diff --git a/contracts/upstream/2026-09-21-p1-v2/examples/event-contact-opt-out.json b/contracts/archive/upstream/2026-09-21-p1-v2/examples/event-contact-opt-out.json similarity index 100% rename from contracts/upstream/2026-09-21-p1-v2/examples/event-contact-opt-out.json rename to contracts/archive/upstream/2026-09-21-p1-v2/examples/event-contact-opt-out.json diff --git a/contracts/upstream/2026-09-21-p1-v2/examples/event-recording-failed.json b/contracts/archive/upstream/2026-09-21-p1-v2/examples/event-recording-failed.json similarity index 100% rename from contracts/upstream/2026-09-21-p1-v2/examples/event-recording-failed.json rename to contracts/archive/upstream/2026-09-21-p1-v2/examples/event-recording-failed.json diff --git a/contracts/upstream/2026-09-21-p1-v2/examples/event-recording-uploaded.json b/contracts/archive/upstream/2026-09-21-p1-v2/examples/event-recording-uploaded.json similarity index 100% rename from contracts/upstream/2026-09-21-p1-v2/examples/event-recording-uploaded.json rename to contracts/archive/upstream/2026-09-21-p1-v2/examples/event-recording-uploaded.json diff --git a/contracts/upstream/2026-09-21-p1-v2/examples/event-transcript-failed.json b/contracts/archive/upstream/2026-09-21-p1-v2/examples/event-transcript-failed.json similarity index 100% rename from contracts/upstream/2026-09-21-p1-v2/examples/event-transcript-failed.json rename to contracts/archive/upstream/2026-09-21-p1-v2/examples/event-transcript-failed.json diff --git a/contracts/upstream/2026-09-21-p1-v2/examples/event-transcript-updated.json b/contracts/archive/upstream/2026-09-21-p1-v2/examples/event-transcript-updated.json similarity index 100% rename from contracts/upstream/2026-09-21-p1-v2/examples/event-transcript-updated.json rename to contracts/archive/upstream/2026-09-21-p1-v2/examples/event-transcript-updated.json diff --git a/contracts/upstream/2026-09-21-p1-v2/examples/invalid-call-query-extra.json b/contracts/archive/upstream/2026-09-21-p1-v2/examples/invalid-call-query-extra.json similarity index 100% rename from contracts/upstream/2026-09-21-p1-v2/examples/invalid-call-query-extra.json rename to contracts/archive/upstream/2026-09-21-p1-v2/examples/invalid-call-query-extra.json diff --git a/contracts/upstream/2026-09-21-p1-v2/examples/invalid-correlation.json b/contracts/archive/upstream/2026-09-21-p1-v2/examples/invalid-correlation.json similarity index 100% rename from contracts/upstream/2026-09-21-p1-v2/examples/invalid-correlation.json rename to contracts/archive/upstream/2026-09-21-p1-v2/examples/invalid-correlation.json diff --git a/contracts/upstream/2026-09-21-p1-v2/examples/invalid-dispatcher.json b/contracts/archive/upstream/2026-09-21-p1-v2/examples/invalid-dispatcher.json similarity index 100% rename from contracts/upstream/2026-09-21-p1-v2/examples/invalid-dispatcher.json rename to contracts/archive/upstream/2026-09-21-p1-v2/examples/invalid-dispatcher.json diff --git a/contracts/upstream/2026-09-21-p1-v2/examples/invalid-v1.json b/contracts/archive/upstream/2026-09-21-p1-v2/examples/invalid-v1.json similarity index 100% rename from contracts/upstream/2026-09-21-p1-v2/examples/invalid-v1.json rename to contracts/archive/upstream/2026-09-21-p1-v2/examples/invalid-v1.json diff --git a/contracts/upstream/2026-09-21-p1-v2/examples/invalid-wildcard.json b/contracts/archive/upstream/2026-09-21-p1-v2/examples/invalid-wildcard.json similarity index 100% rename from contracts/upstream/2026-09-21-p1-v2/examples/invalid-wildcard.json rename to contracts/archive/upstream/2026-09-21-p1-v2/examples/invalid-wildcard.json diff --git a/contracts/upstream/2026-09-21-p1-v2/examples/query-pending.json b/contracts/archive/upstream/2026-09-21-p1-v2/examples/query-pending.json similarity index 100% rename from contracts/upstream/2026-09-21-p1-v2/examples/query-pending.json rename to contracts/archive/upstream/2026-09-21-p1-v2/examples/query-pending.json diff --git a/contracts/upstream/2026-09-21-p1-v2/examples/query-rejected.json b/contracts/archive/upstream/2026-09-21-p1-v2/examples/query-rejected.json similarity index 100% rename from contracts/upstream/2026-09-21-p1-v2/examples/query-rejected.json rename to contracts/archive/upstream/2026-09-21-p1-v2/examples/query-rejected.json diff --git a/contracts/upstream/2026-09-21-p1-v2/examples/task-control.json b/contracts/archive/upstream/2026-09-21-p1-v2/examples/task-control.json similarity index 100% rename from contracts/upstream/2026-09-21-p1-v2/examples/task-control.json rename to contracts/archive/upstream/2026-09-21-p1-v2/examples/task-control.json diff --git a/contracts/upstream/2026-09-21-p1-v2/fixtures.json b/contracts/archive/upstream/2026-09-21-p1-v2/fixtures.json similarity index 100% rename from contracts/upstream/2026-09-21-p1-v2/fixtures.json rename to contracts/archive/upstream/2026-09-21-p1-v2/fixtures.json diff --git a/contracts/upstream/2026-09-21-p1-v2/manifest.json b/contracts/archive/upstream/2026-09-21-p1-v2/manifest.json similarity index 100% rename from contracts/upstream/2026-09-21-p1-v2/manifest.json rename to contracts/archive/upstream/2026-09-21-p1-v2/manifest.json diff --git a/contracts/upstream/2026-09-21-p1-v2/mq-topology.json b/contracts/archive/upstream/2026-09-21-p1-v2/mq-topology.json similarity index 100% rename from contracts/upstream/2026-09-21-p1-v2/mq-topology.json rename to contracts/archive/upstream/2026-09-21-p1-v2/mq-topology.json diff --git a/contracts/upstream/2026-09-21-p1-v2/mq.schema.json b/contracts/archive/upstream/2026-09-21-p1-v2/mq.schema.json similarity index 100% rename from contracts/upstream/2026-09-21-p1-v2/mq.schema.json rename to contracts/archive/upstream/2026-09-21-p1-v2/mq.schema.json diff --git a/contracts/upstream/2026-09-21-p1-v2/oss-upload.schema.json b/contracts/archive/upstream/2026-09-21-p1-v2/oss-upload.schema.json similarity index 100% rename from contracts/upstream/2026-09-21-p1-v2/oss-upload.schema.json rename to contracts/archive/upstream/2026-09-21-p1-v2/oss-upload.schema.json diff --git a/contracts/upstream/2026-09-21-p1-v2/p1-development-profile.schema.json b/contracts/archive/upstream/2026-09-21-p1-v2/p1-development-profile.schema.json similarity index 100% rename from contracts/upstream/2026-09-21-p1-v2/p1-development-profile.schema.json rename to contracts/archive/upstream/2026-09-21-p1-v2/p1-development-profile.schema.json diff --git a/contracts/upstream/2026-09-21-p1-v2/static-cell-artifact.schema.json b/contracts/archive/upstream/2026-09-21-p1-v2/static-cell-artifact.schema.json similarity index 100% rename from contracts/upstream/2026-09-21-p1-v2/static-cell-artifact.schema.json rename to contracts/archive/upstream/2026-09-21-p1-v2/static-cell-artifact.schema.json diff --git a/contracts/upstream/2026-09-21-p1-v3/ai-digest.json b/contracts/archive/upstream/2026-09-21-p1-v3-unused-ai-digest.json similarity index 100% rename from contracts/upstream/2026-09-21-p1-v3/ai-digest.json rename to contracts/archive/upstream/2026-09-21-p1-v3-unused-ai-digest.json diff --git a/contracts/upstream/758c0a29e632cfbaaf12b9f6a7242ed130e62807/ai-config.openapi.yaml b/contracts/archive/upstream/758c0a29e632cfbaaf12b9f6a7242ed130e62807/ai-config.openapi.yaml similarity index 100% rename from contracts/upstream/758c0a29e632cfbaaf12b9f6a7242ed130e62807/ai-config.openapi.yaml rename to contracts/archive/upstream/758c0a29e632cfbaaf12b9f6a7242ed130e62807/ai-config.openapi.yaml diff --git a/contracts/upstream/758c0a29e632cfbaaf12b9f6a7242ed130e62807/ai-config.schema.json b/contracts/archive/upstream/758c0a29e632cfbaaf12b9f6a7242ed130e62807/ai-config.schema.json similarity index 100% rename from contracts/upstream/758c0a29e632cfbaaf12b9f6a7242ed130e62807/ai-config.schema.json rename to contracts/archive/upstream/758c0a29e632cfbaaf12b9f6a7242ed130e62807/ai-config.schema.json diff --git a/contracts/upstream/758c0a29e632cfbaaf12b9f6a7242ed130e62807/cell-agent.openapi.yaml b/contracts/archive/upstream/758c0a29e632cfbaaf12b9f6a7242ed130e62807/cell-agent.openapi.yaml similarity index 100% rename from contracts/upstream/758c0a29e632cfbaaf12b9f6a7242ed130e62807/cell-agent.openapi.yaml rename to contracts/archive/upstream/758c0a29e632cfbaaf12b9f6a7242ed130e62807/cell-agent.openapi.yaml diff --git a/contracts/upstream/758c0a29e632cfbaaf12b9f6a7242ed130e62807/examples/README.md b/contracts/archive/upstream/758c0a29e632cfbaaf12b9f6a7242ed130e62807/examples/README.md similarity index 100% rename from contracts/upstream/758c0a29e632cfbaaf12b9f6a7242ed130e62807/examples/README.md rename to contracts/archive/upstream/758c0a29e632cfbaaf12b9f6a7242ed130e62807/examples/README.md diff --git a/contracts/upstream/2026-09-21-p1-v3/examples/agent-version.json b/contracts/archive/upstream/758c0a29e632cfbaaf12b9f6a7242ed130e62807/examples/agent-version.json similarity index 100% rename from contracts/upstream/2026-09-21-p1-v3/examples/agent-version.json rename to contracts/archive/upstream/758c0a29e632cfbaaf12b9f6a7242ed130e62807/examples/agent-version.json diff --git a/contracts/upstream/758c0a29e632cfbaaf12b9f6a7242ed130e62807/examples/call.execute.json b/contracts/archive/upstream/758c0a29e632cfbaaf12b9f6a7242ed130e62807/examples/call.execute.json similarity index 100% rename from contracts/upstream/758c0a29e632cfbaaf12b9f6a7242ed130e62807/examples/call.execute.json rename to contracts/archive/upstream/758c0a29e632cfbaaf12b9f6a7242ed130e62807/examples/call.execute.json diff --git a/contracts/upstream/758c0a29e632cfbaaf12b9f6a7242ed130e62807/executor.openapi.yaml b/contracts/archive/upstream/758c0a29e632cfbaaf12b9f6a7242ed130e62807/executor.openapi.yaml similarity index 100% rename from contracts/upstream/758c0a29e632cfbaaf12b9f6a7242ed130e62807/executor.openapi.yaml rename to contracts/archive/upstream/758c0a29e632cfbaaf12b9f6a7242ed130e62807/executor.openapi.yaml diff --git a/contracts/upstream/758c0a29e632cfbaaf12b9f6a7242ed130e62807/mock-profile.json b/contracts/archive/upstream/758c0a29e632cfbaaf12b9f6a7242ed130e62807/mock-profile.json similarity index 100% rename from contracts/upstream/758c0a29e632cfbaaf12b9f6a7242ed130e62807/mock-profile.json rename to contracts/archive/upstream/758c0a29e632cfbaaf12b9f6a7242ed130e62807/mock-profile.json diff --git a/contracts/upstream/758c0a29e632cfbaaf12b9f6a7242ed130e62807/mq-topology.md b/contracts/archive/upstream/758c0a29e632cfbaaf12b9f6a7242ed130e62807/mq-topology.md similarity index 100% rename from contracts/upstream/758c0a29e632cfbaaf12b9f6a7242ed130e62807/mq-topology.md rename to contracts/archive/upstream/758c0a29e632cfbaaf12b9f6a7242ed130e62807/mq-topology.md diff --git a/contracts/upstream/758c0a29e632cfbaaf12b9f6a7242ed130e62807/mq.schema.json b/contracts/archive/upstream/758c0a29e632cfbaaf12b9f6a7242ed130e62807/mq.schema.json similarity index 100% rename from contracts/upstream/758c0a29e632cfbaaf12b9f6a7242ed130e62807/mq.schema.json rename to contracts/archive/upstream/758c0a29e632cfbaaf12b9f6a7242ed130e62807/mq.schema.json diff --git a/contracts/upstream/758c0a29e632cfbaaf12b9f6a7242ed130e62807/saas.openapi.yaml b/contracts/archive/upstream/758c0a29e632cfbaaf12b9f6a7242ed130e62807/saas.openapi.yaml similarity index 100% rename from contracts/upstream/758c0a29e632cfbaaf12b9f6a7242ed130e62807/saas.openapi.yaml rename to contracts/archive/upstream/758c0a29e632cfbaaf12b9f6a7242ed130e62807/saas.openapi.yaml diff --git a/contracts/upstream/758c0a29e632cfbaaf12b9f6a7242ed130e62807/sip-management.openapi.yaml b/contracts/archive/upstream/758c0a29e632cfbaaf12b9f6a7242ed130e62807/sip-management.openapi.yaml similarity index 100% rename from contracts/upstream/758c0a29e632cfbaaf12b9f6a7242ed130e62807/sip-management.openapi.yaml rename to contracts/archive/upstream/758c0a29e632cfbaaf12b9f6a7242ed130e62807/sip-management.openapi.yaml diff --git a/contracts/contracts.go b/contracts/contracts.go index 19ef1fc..d474643 100644 --- a/contracts/contracts.go +++ b/contracts/contracts.go @@ -14,7 +14,7 @@ import ( //go:embed upstream var Files embed.FS -const SourceCommit = "2026-09-19-p1-v1" +const SourceCommit = "v1" func Read(name string) ([]byte, error) { return Files.ReadFile(path.Join("upstream", SourceCommit, name)) diff --git a/contracts/upstream/2026-09-21-p1-v3/README.md b/contracts/upstream/2026-09-21-p1-v3/README.md deleted file mode 100644 index 37871db..0000000 --- a/contracts/upstream/2026-09-21-p1-v3/README.md +++ /dev/null @@ -1,7 +0,0 @@ -# 2026-09-21-p1-v3 - -Project-local JCS/SHA-256 revision approved by the user. Derived from 2026-09-21-p1-v2; older packages are unchanged. Wire schema_version remains 2.0. - -AI digests use RFC 8785 canonical UTF-8 bytes followed by SHA-256, lowercase hexadecimal. This does not change file checksums, upload facts, command-body identity, or other hashes. Numbers follow JCS IEEE-754 rules; no Unicode normalization is performed. Explicit zero/false remain distinct from absent fields. No legacy digest fallback. - -Local agreement and generated fixtures are not external SaaS acceptance. diff --git a/contracts/upstream/manifest.txt b/contracts/upstream/manifest.txt index 2860925..ec376e3 100644 --- a/contracts/upstream/manifest.txt +++ b/contracts/upstream/manifest.txt @@ -1,50 +1,55 @@ -active_bundle=2026-09-19-p1-v1 -bundle_kind=project-owned-first-production-closure-v1 -contract_status=project-owned-v1-authorized-not-external-authoritative -source_repo=git.ipao.vip/rogee/ai-call -source_path=sip-go-agent/contracts/upstream/2026-09-18-p1-baseline -source_snapshot=2026-09-18-p1-baseline -source_head=project-authored-v1 -source_worktree=dirty-project-authored -release_source_worktree=local-self-contained -release_manifest=contracts/upstream/2026-09-19-p1-v1/release-manifest.json -sha256=3332e4c71021189b03f3031106c08b3c9c08eb2f9bb1a4f4b0a96fe1598ceaba contracts/upstream/2026-09-19-p1-v1/README.md -sha256=a41adc5ec329a9010cc45d08f309eb3620e0d6311a5c565a9f26a35ffc4ecb42 contracts/upstream/2026-09-19-p1-v1/SNAPSHOT.json -sha256=5d6bbd369bd6b406abe9b9f8619e6f299b544dacfdd4473a08257a366fd95d20 contracts/upstream/2026-09-19-p1-v1/ai-authorization.schema.json -sha256=d2f75d8fd2bf76ceb4eef869a838f08dca156938e1f3025d126ce81e436f624a contracts/upstream/2026-09-19-p1-v1/ai-config.openapi.yaml -sha256=dc915bff70e71408fcacbaad47d3554bbfa7a22a51f2f53e127c6bd8bc8ba5a6 contracts/upstream/2026-09-19-p1-v1/ai-config.schema.json -sha256=79dc697d7ce16e2a6aa7e350f30dd006dd847afe2cdc0ea29841f9c6d4310c41 contracts/upstream/2026-09-19-p1-v1/cell-agent.openapi.yaml -sha256=5091ded520d692f458699327b13adddeccb0c4b4d4a72ef7cdfebcd5d496eade contracts/upstream/2026-09-19-p1-v1/event-payloads.schema.json -sha256=a3514c7ef89b4324685bc9025139488000fa42330de72495484add042a6897cf contracts/upstream/2026-09-19-p1-v1/examples/README.md -sha256=24864df1fd72a59efaaaf6d1fc81a0c7db01fbdfcd821aab4069b64a8db9b60b contracts/upstream/2026-09-19-p1-v1/examples/agent-version-asr-only.json -sha256=e590148448885a1e88c473ca032d5efd719270689c3cff7aa44ca9c6ffa2b321 contracts/upstream/2026-09-19-p1-v1/examples/agent-version-full-explicit.json -sha256=6a5f35f8cc4256c048d4f1ca567a3544ea7bc92bb835cfab39a000d22b73102b contracts/upstream/2026-09-19-p1-v1/examples/agent-version-full-production-v1.json -sha256=d3d4bf2fae07192674e54bf32172a8e95146f11d70609f3cd8f57f0112633c2e contracts/upstream/2026-09-19-p1-v1/examples/agent-version.json -sha256=b1c0f723f083d1be45035792482f6f74bd3bca34486cc6408d4bcfe3772bc432 contracts/upstream/2026-09-19-p1-v1/examples/ai-authorization.json -sha256=0164664fd3503d72668b24bdecb623aa0414ce58191960b868abe8454988c742 contracts/upstream/2026-09-19-p1-v1/examples/call.execute.json -sha256=fab56aff9c5d4059b8fa65d24f2afa424148e7a07025238fc7fd30e9c5ee63f4 contracts/upstream/2026-09-19-p1-v1/examples/event-call-finished.json -sha256=5c673ceb4a98ce8c90d976356b4c5ffa6c7d96d045b5b3312513a9be93d585ba contracts/upstream/2026-09-19-p1-v1/examples/event-call-status.json -sha256=64fe71719573378b0caac2f7c5476a27ba7073df8c346d4748a6b0d534d4a087 contracts/upstream/2026-09-19-p1-v1/examples/event-command-result.json -sha256=b661f65f0a195e59fe226b12ebae2feb5a9733a9a779c835245be27319aaf8f2 contracts/upstream/2026-09-19-p1-v1/examples/event-contact-opt-out.json -sha256=4f5f46422d2281ffae65c99e947bc7dd44effb5e94eacc12e41b3250ac645c34 contracts/upstream/2026-09-19-p1-v1/examples/event-recording-failed.json -sha256=2b6d731a8d7993cbbe07a5ba8c7413ec56bae8a1538476c0f1740133a488d5b4 contracts/upstream/2026-09-19-p1-v1/examples/event-recording-ready.json -sha256=58d000ce27de6e67054f66d4ded34ffafa983bdcced12613051f670d1eefeed8 contracts/upstream/2026-09-19-p1-v1/examples/event-transcript-failed.json -sha256=115f276522631d7c4decee71ee238aa0d00b4256adedfc9a6a0c5f9dc89f64f6 contracts/upstream/2026-09-19-p1-v1/examples/event-transcript-updated.json -sha256=0b946b43c1f773391791dfb60a2b2a03c8a69e64e5e9ea30af8591850c34b8f3 contracts/upstream/2026-09-19-p1-v1/examples/invalid-ai-authorization-revoked.json -sha256=7343ce8d6ce63e22128ab7bc721544d681a5dd9eccfc4ab4f9d6181c5748824c contracts/upstream/2026-09-19-p1-v1/examples/invalid-asr-only-with-llm.json -sha256=80c3f89dc775deec9d1a3b85c81ea4b2fd1b030bc4deba1a4dcd2823e4eb8024 contracts/upstream/2026-09-19-p1-v1/examples/invalid-event-unknown-type.json -sha256=8e4fb4344c4bec51b47ff9b00a63afdc84d09ab827e1b6823c4e576bf6b6a3f1 contracts/upstream/2026-09-19-p1-v1/examples/invalid-oss-upload-http.json -sha256=268751a1a0d238636c04c004a635e3bda702bc2ef90ade0e5846b47a3c263b5d contracts/upstream/2026-09-19-p1-v1/examples/oss-upload-grant.json -sha256=b4a001457e747a039677870a3ddeccc902b8f87819c3ce2d2e37ae6a14f1ffe0 contracts/upstream/2026-09-19-p1-v1/examples/static-cell-artifact-real-v1.json -sha256=129821e4de654ef12d3e7f155e9301ecddf798f9ca3399316a20a55273fbc61f contracts/upstream/2026-09-19-p1-v1/examples/static-cell-artifact.json -sha256=b24703783df63e044fc0151c5e215430d2294e13937d2a5ceee3c6fee99b0329 contracts/upstream/2026-09-19-p1-v1/executor.openapi.yaml -sha256=4d43097602fed9a68821e765117580706896ac82d4bce361a80a4cea544ab638 contracts/upstream/2026-09-19-p1-v1/mock-profile.json -sha256=a85b26596e1b1db7405dcabc967df56d5eb6713cc9908bc05ecaa2075ff1092f contracts/upstream/2026-09-19-p1-v1/mq-topology.md -sha256=4fbfc39d46fb55ca48b71bc11cafce60e0814182ba4f898973c7c4d7657f912a contracts/upstream/2026-09-19-p1-v1/mq.schema.json -sha256=d3f6ffc5e004fba8acbb6a18495be508a63ec45766bab1ef946ece58bbad84de contracts/upstream/2026-09-19-p1-v1/oss-upload.schema.json -sha256=2aa7cd3f4fa07f7e1a3037107fa7a56183f28370ea06a2a9b8dc18c8790eee2d contracts/upstream/2026-09-19-p1-v1/p1-development-profile.json -sha256=68e1b46194a1f5fa5bc763ba424411f48ada1ab52d39e6f800315a832692794b contracts/upstream/2026-09-19-p1-v1/p1-development-profile.schema.json -sha256=251127dfbb8fe60da58312c9785bc7eafa4135ef91f241a8e07c3868a30e123a contracts/upstream/2026-09-19-p1-v1/release-manifest.json -sha256=368c3a7d75ecc74771b88f9bd9fb7131697c69ce695475fc5aaae6099ff889eb contracts/upstream/2026-09-19-p1-v1/saas.openapi.yaml -sha256=5006bbb1fb69f7b4a05cbaa5a43f8944e8522172910a41aba61897c9d5e00281 contracts/upstream/2026-09-19-p1-v1/sip-management.openapi.yaml -sha256=46333f6a161ebbfd42f4a326e2509d562164fe836e6d1c88368428795362138d contracts/upstream/2026-09-19-p1-v1/static-cell-artifact.schema.json +# Active project-owned contract bundle for the current test/development tree. +# This is the only active contract package; wire schema_version values remain part of its messages. +active_bundle=v1 +source_path=sip-go-agent/contracts/upstream/v1 +source_status=project-owned-v1-development +sha256=b12aedfd17bbb316405defd9a2c31b78ff38ae3b39cbcfd578d7a4df708e749c contracts/upstream/v1/README.md +sha256=2d5846e03791d4ce11c474160797b2c157ba391b993e961537e04c83eb2545e5 contracts/upstream/v1/ai-authorization.schema.json +sha256=b8090c2288e43cd18bbc07f8af996fee4a39acb1e10a3b5dcf11984c35464a80 contracts/upstream/v1/ai-config.schema.json +sha256=d227522dabfdd8080ff25293886e11692456bf0f77b59e125525d2785a4712bf contracts/upstream/v1/dispatcher-config.schema.json +sha256=e715cfb38ed7917c28501b408d69d9636bc44179cd01f0a130a8eeb5c9934d0e contracts/upstream/v1/event-payloads.schema.json +sha256=24864df1fd72a59efaaaf6d1fc81a0c7db01fbdfcd821aab4069b64a8db9b60b contracts/upstream/v1/examples/agent-version-asr-only.json +sha256=e590148448885a1e88c473ca032d5efd719270689c3cff7aa44ca9c6ffa2b321 contracts/upstream/v1/examples/agent-version-full-explicit.json +sha256=6a5f35f8cc4256c048d4f1ca567a3544ea7bc92bb835cfab39a000d22b73102b contracts/upstream/v1/examples/agent-version-full-production-v1.json +sha256=d3d4bf2fae07192674e54bf32172a8e95146f11d70609f3cd8f57f0112633c2e contracts/upstream/v1/examples/agent-version.json +sha256=2aacf5b3a8afbc5c457ad008323559f1d51ce31c85741631481b46c46118168d contracts/upstream/v1/examples/ai-authorization.json +sha256=d6fba0382ccbac1e1585052326e9a393d941ee7d1e96cce19ece462a92c7e374 contracts/upstream/v1/examples/ai-config-request.json +sha256=c85fa2281eec78c6048bc8a1d8a866fd8ede08f870b7db7c7bc90c7dd5e0c63e contracts/upstream/v1/examples/ai-config-result.json +sha256=b96a7ab2eed238b0c8c1d9534a8932955819e32b7e5d0e554fad076c3c3a4b7a contracts/upstream/v1/examples/call-execute.json +sha256=07bfe067e56138964f2708c1860ab57c22b06567a8d633d21d6057d2a0004004 contracts/upstream/v1/examples/call-query-result.json +sha256=3a1f2af373a8504da32f3a113ae7a033eaeeb50dbcee5836d2042026ffc63902 contracts/upstream/v1/examples/call-query.json +sha256=74bdc281b27bb6513f8199455149545a9ed446a59cba1e3463db2e58884cbe0d contracts/upstream/v1/examples/call-replay.json +sha256=34e533bd6f07c8f72f79964f7637dc39052f8ba0dc16f3b4dcf11aeff4f898b3 contracts/upstream/v1/examples/command-query-result.json +sha256=76392b74382d8dfb02b987c8b2a6e8b9a56c5311557557579756e507ddb48d04 contracts/upstream/v1/examples/command-query.json +sha256=a885310aebddc6c0e579e32e328690795668ecfcf6a26990ab1f09b89e25bc5a contracts/upstream/v1/examples/command-replay.json +sha256=0432e3e4b758c9d049f40ed52581d48422a9e1a87c8f5a95590a26f8d7dae872 contracts/upstream/v1/examples/dispatcher-config.json +sha256=206c9c95273012720800ec41ac5b4347ade4288b3c086c9f782d62e96b1eaef5 contracts/upstream/v1/examples/event-call-finished.json +sha256=ed68df5d40efd8b71bc0cc00fd67c5e65d68a2580361ff3d464cdaf44af09013 contracts/upstream/v1/examples/event-call-status.json +sha256=21d86e11db96374f393126eb7bb1f7188609292d446bf322f521c15c8719a5b4 contracts/upstream/v1/examples/event-command-result.json +sha256=6b396965c33f5e284363d612bb5bf53dcdb3ec4b56eea26d6c89778ba471f57b contracts/upstream/v1/examples/event-contact-opt-out.json +sha256=911086c4954474a5494b7054660629f22d1f10a21fe129091ec0609cc16616ef contracts/upstream/v1/examples/event-recording-failed.json +sha256=3189da1e9966931b92aa5b9e13dab1f70d9abda1822e8c7772bcf04f24aa09f4 contracts/upstream/v1/examples/event-recording-uploaded.json +sha256=56385f45b43394a6061853343600e4ebf5aa01d7b6d0ff23ea79628ebfecb308 contracts/upstream/v1/examples/event-transcript-failed.json +sha256=4747266786b1cbfdfe483e5c3c7c36c587eab710fd77eb7152b8172f1620ca3e contracts/upstream/v1/examples/event-transcript-updated.json +sha256=0b946b43c1f773391791dfb60a2b2a03c8a69e64e5e9ea30af8591850c34b8f3 contracts/upstream/v1/examples/invalid-ai-authorization-revoked.json +sha256=7343ce8d6ce63e22128ab7bc721544d681a5dd9eccfc4ab4f9d6181c5748824c contracts/upstream/v1/examples/invalid-asr-only-with-llm.json +sha256=d5baeaacf73f4fbe4d57b1fcb6a3ca8c82603d763ccd2882298a412f00cdeb1a contracts/upstream/v1/examples/invalid-call-query-extra.json +sha256=79051aeecb5b4726d3a392b72e2cf6d9b90a873e3a1c5065879721655a859d4d contracts/upstream/v1/examples/invalid-correlation.json +sha256=1a98856bf3d50a783eab538b37b1b84bd98ac5acca57a4c271244f5fa90b50e9 contracts/upstream/v1/examples/invalid-dispatcher.json +sha256=8e4fb4344c4bec51b47ff9b00a63afdc84d09ab827e1b6823c4e576bf6b6a3f1 contracts/upstream/v1/examples/invalid-oss-upload-http.json +sha256=dc795727448254a97781ae163583a0bb776a6ebcc589b1330d018083886a4a09 contracts/upstream/v1/examples/invalid-v1.json +sha256=becd89c7d9ccfc2343417efa9d7502a629ca3a33ee8dae419a121dfa01cb7257 contracts/upstream/v1/examples/invalid-wildcard.json +sha256=268751a1a0d238636c04c004a635e3bda702bc2ef90ade0e5846b47a3c263b5d contracts/upstream/v1/examples/oss-upload-grant.json +sha256=a3c4102102d4652d2c1ffaefec88d7ea50f694ad37811d82a1dfbd0cd985ca11 contracts/upstream/v1/examples/query-pending.json +sha256=6260c6dbb5748a8140106930ac03a5a59c4d2103a30c66239c234e39f4800a11 contracts/upstream/v1/examples/query-rejected.json +sha256=b4a001457e747a039677870a3ddeccc902b8f87819c3ce2d2e37ae6a14f1ffe0 contracts/upstream/v1/examples/static-cell-artifact-real-v1.json +sha256=129821e4de654ef12d3e7f155e9301ecddf798f9ca3399316a20a55273fbc61f contracts/upstream/v1/examples/static-cell-artifact.json +sha256=f5b5df31c7a5d332412472db26f99d49b1d3a9aabdeb05e8a6dea9c4c85e4089 contracts/upstream/v1/examples/task-control.json +sha256=103ff072caafeb8a0399dccb27bc0619068e9b35baf738054fdfb3c225135c78 contracts/upstream/v1/fixtures.json +sha256=371ee1ddc2f8626215f90b9e64de79d932b757f79b84ad1a55ccdd713d9e1812 contracts/upstream/v1/jcs-golden.json +sha256=ade0f2dcf4247351db82ca7498941b925c832ef1ee6d546c5bf34a4921011c68 contracts/upstream/v1/mq-topology.json +sha256=d566899abbc8f0f8404cfe79ea58b0d1e7bf7e9fc663b09b282c15d5c74f505d contracts/upstream/v1/mq.schema.json +sha256=79192cfb7838a42fcb373347080ca08429083b4c3ed1f867f587a9e0e195a4a1 contracts/upstream/v1/oss-upload.schema.json +sha256=2aa7cd3f4fa07f7e1a3037107fa7a56183f28370ea06a2a9b8dc18c8790eee2d contracts/upstream/v1/p1-development-profile.json +sha256=e0f3ec455bb7fcaff4416ac4d8e3ccddb8f838b85485c85719e594d1f8896d20 contracts/upstream/v1/p1-development-profile.schema.json +sha256=bcdeb2e5152efe23a9eeca04eca7effbfbf7a897f66079d68fb23aa87ede64be contracts/upstream/v1/static-cell-artifact.schema.json diff --git a/contracts/upstream/v1/README.md b/contracts/upstream/v1/README.md new file mode 100644 index 0000000..3ac1d53 --- /dev/null +++ b/contracts/upstream/v1/README.md @@ -0,0 +1,7 @@ +# Project-owned V1 contract bundle + +This is the single contract bundle used by the current test/development code. It contains only the JSON Schemas, business fixtures, MQ topology, AI digest vectors, and static Cell/profile inputs exercised by the Agent and Dispatcher tests. + +The bundle is project-owned and local. It is not an external SaaS release. The wire `schema_version` values remain part of the business message contract; they do not create additional project contract packages. + +`manifest.json` pins the active files by SHA-256. Unused OpenAPI files, superseded package copies, and historical snapshots are outside the embedded `contracts/upstream/` tree. diff --git a/contracts/upstream/2026-09-21-p1-v3/ai-authorization.schema.json b/contracts/upstream/v1/ai-authorization.schema.json similarity index 96% rename from contracts/upstream/2026-09-21-p1-v3/ai-authorization.schema.json rename to contracts/upstream/v1/ai-authorization.schema.json index df72a49..2be9e73 100644 --- a/contracts/upstream/2026-09-21-p1-v3/ai-authorization.schema.json +++ b/contracts/upstream/v1/ai-authorization.schema.json @@ -1,6 +1,6 @@ { "$schema": "https://json-schema.org/draft/2020-12/schema", - "$id": "https://go-sip.local/contracts/2026-09-21-p1-v3/ai-authorization.schema.json", + "$id": "https://go-sip.local/contracts/v1/ai-authorization.schema.json", "title": "Dispatcher to Agent immutable AI authorization", "type": "object", "additionalProperties": false, diff --git a/contracts/upstream/2026-09-21-p1-v3/ai-config.schema.json b/contracts/upstream/v1/ai-config.schema.json similarity index 98% rename from contracts/upstream/2026-09-21-p1-v3/ai-config.schema.json rename to contracts/upstream/v1/ai-config.schema.json index 1f011f6..9765ccd 100644 --- a/contracts/upstream/2026-09-21-p1-v3/ai-config.schema.json +++ b/contracts/upstream/v1/ai-config.schema.json @@ -1,6 +1,6 @@ { "$schema": "https://json-schema.org/draft/2020-12/schema", - "$id": "https://go-sip.local/contracts/2026-09-21-p1-v3/ai-config.schema.json", + "$id": "https://go-sip.local/contracts/v1/ai-config.schema.json", "title": "Immutable AI agent version", "type": "object", "additionalProperties": false, diff --git a/contracts/upstream/2026-09-21-p1-v3/dispatcher-config.schema.json b/contracts/upstream/v1/dispatcher-config.schema.json similarity index 93% rename from contracts/upstream/2026-09-21-p1-v3/dispatcher-config.schema.json rename to contracts/upstream/v1/dispatcher-config.schema.json index 7a89000..82427dd 100644 --- a/contracts/upstream/2026-09-21-p1-v3/dispatcher-config.schema.json +++ b/contracts/upstream/v1/dispatcher-config.schema.json @@ -58,5 +58,5 @@ } }, "$schema": "https://json-schema.org/draft/2020-12/schema", - "$id": "https://go-sip.local/contracts/2026-09-21-p1-v3/dispatcher-config.schema.json" + "$id": "https://go-sip.local/contracts/v1/dispatcher-config.schema.json" } diff --git a/contracts/upstream/2026-09-21-p1-v3/event-payloads.schema.json b/contracts/upstream/v1/event-payloads.schema.json similarity index 99% rename from contracts/upstream/2026-09-21-p1-v3/event-payloads.schema.json rename to contracts/upstream/v1/event-payloads.schema.json index e553037..d068115 100644 --- a/contracts/upstream/2026-09-21-p1-v3/event-payloads.schema.json +++ b/contracts/upstream/v1/event-payloads.schema.json @@ -1,6 +1,6 @@ { "$schema": "https://json-schema.org/draft/2020-12/schema", - "$id": "https://go-sip.local/contracts/2026-09-21-p1-v3/event-payloads.schema.json", + "$id": "https://go-sip.local/contracts/v1/event-payloads.schema.json", "title": "Agent-call versioned event envelopes and payloads", "type": "object", "additionalProperties": false, diff --git a/contracts/upstream/2026-09-21-p1-v3/examples/agent-version-asr-only.json b/contracts/upstream/v1/examples/agent-version-asr-only.json similarity index 100% rename from contracts/upstream/2026-09-21-p1-v3/examples/agent-version-asr-only.json rename to contracts/upstream/v1/examples/agent-version-asr-only.json diff --git a/contracts/upstream/2026-09-21-p1-v3/examples/agent-version-full-explicit.json b/contracts/upstream/v1/examples/agent-version-full-explicit.json similarity index 100% rename from contracts/upstream/2026-09-21-p1-v3/examples/agent-version-full-explicit.json rename to contracts/upstream/v1/examples/agent-version-full-explicit.json diff --git a/contracts/upstream/v1/examples/agent-version-full-production-v1.json b/contracts/upstream/v1/examples/agent-version-full-production-v1.json new file mode 100644 index 0000000..0a83a96 --- /dev/null +++ b/contracts/upstream/v1/examples/agent-version-full-production-v1.json @@ -0,0 +1,54 @@ +{ + "agent_version_id": "agent_full_v1", + "immutable": true, + "mode": "full_ai", + "llm": { + "provider_ref": "bailian-openai-compatible", + "model": "qwen-plus", + "temperature": 0.2, + "max_tokens": 256, + "timeout_ms": 5000, + "credential_ref": "bailian-default" + }, + "prompt": { + "text": "You are a concise telephone assistant. Answer the caller's last statement.", + "allowed_variables": [], + "max_bytes": 32768 + }, + "tts": { + "provider_ref": "bailian-openai-compatible", + "model": "qwen3-tts-flash", + "voice": "Cherry", + "speed": 1.0, + "format": { + "encoding": "pcm_s16le", + "sample_rate_hz": 16000, + "channels": 1 + }, + "timeout_ms": 5000, + "credential_ref": "bailian-default" + }, + "asr": { + "provider_ref": "volcengine", + "language": "zh-CN", + "input": { + "encoding": "pcm_s16le", + "sample_rate_hz": 16000, + "channels": 1, + "sample_width_bytes": 2 + }, + "interim": true, + "timeout_ms": 5000, + "credential_ref": "volcengine-default", + "model": "volc.bigasr.sauc.duration" + }, + "conversation": { + "opening": "", + "allow_interrupt": true, + "silence_timeout_ms": 3000, + "max_duration_ms": 120000, + "max_turns": 20, + "sentence_max_chars": 80, + "max_pending_audio_chunks": 32 + } +} diff --git a/contracts/upstream/758c0a29e632cfbaaf12b9f6a7242ed130e62807/examples/agent-version.json b/contracts/upstream/v1/examples/agent-version.json similarity index 100% rename from contracts/upstream/758c0a29e632cfbaaf12b9f6a7242ed130e62807/examples/agent-version.json rename to contracts/upstream/v1/examples/agent-version.json diff --git a/contracts/upstream/2026-09-21-p1-v3/examples/ai-authorization.json b/contracts/upstream/v1/examples/ai-authorization.json similarity index 100% rename from contracts/upstream/2026-09-21-p1-v3/examples/ai-authorization.json rename to contracts/upstream/v1/examples/ai-authorization.json diff --git a/contracts/upstream/2026-09-21-p1-v3/examples/ai-config-request.json b/contracts/upstream/v1/examples/ai-config-request.json similarity index 100% rename from contracts/upstream/2026-09-21-p1-v3/examples/ai-config-request.json rename to contracts/upstream/v1/examples/ai-config-request.json diff --git a/contracts/upstream/2026-09-21-p1-v3/examples/ai-config-result.json b/contracts/upstream/v1/examples/ai-config-result.json similarity index 100% rename from contracts/upstream/2026-09-21-p1-v3/examples/ai-config-result.json rename to contracts/upstream/v1/examples/ai-config-result.json diff --git a/contracts/upstream/2026-09-21-p1-v3/examples/call-execute.json b/contracts/upstream/v1/examples/call-execute.json similarity index 100% rename from contracts/upstream/2026-09-21-p1-v3/examples/call-execute.json rename to contracts/upstream/v1/examples/call-execute.json diff --git a/contracts/upstream/2026-09-21-p1-v3/examples/call-query-result.json b/contracts/upstream/v1/examples/call-query-result.json similarity index 100% rename from contracts/upstream/2026-09-21-p1-v3/examples/call-query-result.json rename to contracts/upstream/v1/examples/call-query-result.json diff --git a/contracts/upstream/2026-09-21-p1-v3/examples/call-query.json b/contracts/upstream/v1/examples/call-query.json similarity index 100% rename from contracts/upstream/2026-09-21-p1-v3/examples/call-query.json rename to contracts/upstream/v1/examples/call-query.json diff --git a/contracts/upstream/2026-09-21-p1-v3/examples/call-replay.json b/contracts/upstream/v1/examples/call-replay.json similarity index 100% rename from contracts/upstream/2026-09-21-p1-v3/examples/call-replay.json rename to contracts/upstream/v1/examples/call-replay.json diff --git a/contracts/upstream/2026-09-21-p1-v3/examples/command-query-result.json b/contracts/upstream/v1/examples/command-query-result.json similarity index 100% rename from contracts/upstream/2026-09-21-p1-v3/examples/command-query-result.json rename to contracts/upstream/v1/examples/command-query-result.json diff --git a/contracts/upstream/2026-09-21-p1-v3/examples/command-query.json b/contracts/upstream/v1/examples/command-query.json similarity index 100% rename from contracts/upstream/2026-09-21-p1-v3/examples/command-query.json rename to contracts/upstream/v1/examples/command-query.json diff --git a/contracts/upstream/2026-09-21-p1-v3/examples/command-replay.json b/contracts/upstream/v1/examples/command-replay.json similarity index 100% rename from contracts/upstream/2026-09-21-p1-v3/examples/command-replay.json rename to contracts/upstream/v1/examples/command-replay.json diff --git a/contracts/upstream/2026-09-21-p1-v3/examples/dispatcher-config.json b/contracts/upstream/v1/examples/dispatcher-config.json similarity index 100% rename from contracts/upstream/2026-09-21-p1-v3/examples/dispatcher-config.json rename to contracts/upstream/v1/examples/dispatcher-config.json diff --git a/contracts/upstream/2026-09-21-p1-v3/examples/event-call-finished.json b/contracts/upstream/v1/examples/event-call-finished.json similarity index 100% rename from contracts/upstream/2026-09-21-p1-v3/examples/event-call-finished.json rename to contracts/upstream/v1/examples/event-call-finished.json diff --git a/contracts/upstream/2026-09-21-p1-v3/examples/event-call-status.json b/contracts/upstream/v1/examples/event-call-status.json similarity index 100% rename from contracts/upstream/2026-09-21-p1-v3/examples/event-call-status.json rename to contracts/upstream/v1/examples/event-call-status.json diff --git a/contracts/upstream/2026-09-21-p1-v3/examples/event-command-result.json b/contracts/upstream/v1/examples/event-command-result.json similarity index 100% rename from contracts/upstream/2026-09-21-p1-v3/examples/event-command-result.json rename to contracts/upstream/v1/examples/event-command-result.json diff --git a/contracts/upstream/2026-09-21-p1-v3/examples/event-contact-opt-out.json b/contracts/upstream/v1/examples/event-contact-opt-out.json similarity index 100% rename from contracts/upstream/2026-09-21-p1-v3/examples/event-contact-opt-out.json rename to contracts/upstream/v1/examples/event-contact-opt-out.json diff --git a/contracts/upstream/2026-09-21-p1-v3/examples/event-recording-failed.json b/contracts/upstream/v1/examples/event-recording-failed.json similarity index 100% rename from contracts/upstream/2026-09-21-p1-v3/examples/event-recording-failed.json rename to contracts/upstream/v1/examples/event-recording-failed.json diff --git a/contracts/upstream/2026-09-21-p1-v3/examples/event-recording-uploaded.json b/contracts/upstream/v1/examples/event-recording-uploaded.json similarity index 100% rename from contracts/upstream/2026-09-21-p1-v3/examples/event-recording-uploaded.json rename to contracts/upstream/v1/examples/event-recording-uploaded.json diff --git a/contracts/upstream/2026-09-21-p1-v3/examples/event-transcript-failed.json b/contracts/upstream/v1/examples/event-transcript-failed.json similarity index 100% rename from contracts/upstream/2026-09-21-p1-v3/examples/event-transcript-failed.json rename to contracts/upstream/v1/examples/event-transcript-failed.json diff --git a/contracts/upstream/2026-09-21-p1-v3/examples/event-transcript-updated.json b/contracts/upstream/v1/examples/event-transcript-updated.json similarity index 100% rename from contracts/upstream/2026-09-21-p1-v3/examples/event-transcript-updated.json rename to contracts/upstream/v1/examples/event-transcript-updated.json diff --git a/contracts/upstream/v1/examples/invalid-ai-authorization-revoked.json b/contracts/upstream/v1/examples/invalid-ai-authorization-revoked.json new file mode 100644 index 0000000..48a591b --- /dev/null +++ b/contracts/upstream/v1/examples/invalid-ai-authorization-revoked.json @@ -0,0 +1,12 @@ +{ + "authorization_id": "auth-invalid", + "tenant_id": "tenant-1", + "tenant_key": "tenant-demo-key", + "agent_version_id": "agent_asr_v1", + "config_sha256": "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa", + "mode": "asr_only", + "issued_at": "2026-09-18T00:00:00Z", + "expires_at": "2026-09-18T00:01:00Z", + "source": "mock-saas", + "revoked": true +} diff --git a/contracts/upstream/v1/examples/invalid-asr-only-with-llm.json b/contracts/upstream/v1/examples/invalid-asr-only-with-llm.json new file mode 100644 index 0000000..c09e0f2 --- /dev/null +++ b/contracts/upstream/v1/examples/invalid-asr-only-with-llm.json @@ -0,0 +1,19 @@ +{ + "agent_version_id": "agent_invalid", + "immutable": true, + "mode": "asr_only", + "llm": {"provider_ref": "mock", "model": "must-not-be-present"}, + "asr": { + "provider_ref": "mock", + "language": "zh-CN", + "input": {"encoding": "pcm_s16le", "sample_rate_hz": 16000, "channels": 1, "sample_width_bytes": 2} + }, + "conversation": { + "allow_interrupt": false, + "silence_timeout_ms": 3000, + "max_duration_ms": 120000, + "max_turns": 20, + "sentence_max_chars": 80, + "max_pending_audio_chunks": 32 + } +} diff --git a/contracts/upstream/2026-09-21-p1-v3/examples/invalid-call-query-extra.json b/contracts/upstream/v1/examples/invalid-call-query-extra.json similarity index 100% rename from contracts/upstream/2026-09-21-p1-v3/examples/invalid-call-query-extra.json rename to contracts/upstream/v1/examples/invalid-call-query-extra.json diff --git a/contracts/upstream/2026-09-21-p1-v3/examples/invalid-correlation.json b/contracts/upstream/v1/examples/invalid-correlation.json similarity index 100% rename from contracts/upstream/2026-09-21-p1-v3/examples/invalid-correlation.json rename to contracts/upstream/v1/examples/invalid-correlation.json diff --git a/contracts/upstream/2026-09-21-p1-v3/examples/invalid-dispatcher.json b/contracts/upstream/v1/examples/invalid-dispatcher.json similarity index 100% rename from contracts/upstream/2026-09-21-p1-v3/examples/invalid-dispatcher.json rename to contracts/upstream/v1/examples/invalid-dispatcher.json diff --git a/contracts/upstream/v1/examples/invalid-oss-upload-http.json b/contracts/upstream/v1/examples/invalid-oss-upload-http.json new file mode 100644 index 0000000..42033e6 --- /dev/null +++ b/contracts/upstream/v1/examples/invalid-oss-upload-http.json @@ -0,0 +1,10 @@ +{ + "kind": "grant", + "upload_id": "upload-invalid", + "recording_id": "recording-1", + "upload_url": "http://oss.example.invalid/upload/upload-invalid", + "required_headers": {}, + "expires_at": "2026-09-18T00:05:00Z", + "max_bytes": 16777216, + "object_binding": "recording-1:aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa" +} diff --git a/contracts/upstream/2026-09-21-p1-v3/examples/invalid-v1.json b/contracts/upstream/v1/examples/invalid-v1.json similarity index 100% rename from contracts/upstream/2026-09-21-p1-v3/examples/invalid-v1.json rename to contracts/upstream/v1/examples/invalid-v1.json diff --git a/contracts/upstream/2026-09-21-p1-v3/examples/invalid-wildcard.json b/contracts/upstream/v1/examples/invalid-wildcard.json similarity index 100% rename from contracts/upstream/2026-09-21-p1-v3/examples/invalid-wildcard.json rename to contracts/upstream/v1/examples/invalid-wildcard.json diff --git a/contracts/upstream/v1/examples/oss-upload-grant.json b/contracts/upstream/v1/examples/oss-upload-grant.json new file mode 100644 index 0000000..6b4ddb3 --- /dev/null +++ b/contracts/upstream/v1/examples/oss-upload-grant.json @@ -0,0 +1,10 @@ +{ + "kind": "grant", + "upload_id": "upload-1", + "recording_id": "recording-1", + "upload_url": "https://oss.example.invalid/upload/upload-1", + "required_headers": {"x-checksum-sha256": "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"}, + "expires_at": "2026-09-18T00:05:00Z", + "max_bytes": 16777216, + "object_binding": "recording-1:aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa" +} diff --git a/contracts/upstream/2026-09-21-p1-v3/examples/query-pending.json b/contracts/upstream/v1/examples/query-pending.json similarity index 100% rename from contracts/upstream/2026-09-21-p1-v3/examples/query-pending.json rename to contracts/upstream/v1/examples/query-pending.json diff --git a/contracts/upstream/2026-09-21-p1-v3/examples/query-rejected.json b/contracts/upstream/v1/examples/query-rejected.json similarity index 100% rename from contracts/upstream/2026-09-21-p1-v3/examples/query-rejected.json rename to contracts/upstream/v1/examples/query-rejected.json diff --git a/contracts/upstream/v1/examples/static-cell-artifact-real-v1.json b/contracts/upstream/v1/examples/static-cell-artifact-real-v1.json new file mode 100644 index 0000000..6e2c7bb --- /dev/null +++ b/contracts/upstream/v1/examples/static-cell-artifact-real-v1.json @@ -0,0 +1,95 @@ +{ + "artifact_id": "cell-single-real-v1", + "source_release": "asterisk-22.10.1-native-v1", + "source_digest": "68006a1a8efed288be4ca4a2ae3cb9554a31d733eac08eaacf4c646c95faf74d", + "approval_reference": "project-auto-approved:2026-09-19:single-node-v1", + "cell_id": "cell-single", + "revision": 1, + "config_sha256": "89d2686d0d1ca60159c3c6bd725dc9e6f511cbdb56bf6ce7b65ca7d4dc3f2d60", + "mode": "real", + "trunks": [ + { + "trunk_id": "provider-primary", + "provider_id": "provider-primary", + "egress_pool_id": "egress-single", + "codec": "PCMA", + "caller_profile_ids": [ + "caller-primary" + ], + "dial_prefix": "7089", + "enabled": true, + "sip_endpoint_ref": "provider-primary", + "credential_ref": "sip-provider-primary", + "media_profile_id": "pcma-8k-pt8" + }, + { + "trunk_id": "provider-second", + "provider_id": "provider-second", + "egress_pool_id": "egress-single", + "codec": "PCMA", + "caller_profile_ids": [ + "caller-second" + ], + "dial_prefix": "", + "enabled": true, + "sip_endpoint_ref": "provider-second", + "credential_ref": "sip-provider-second", + "media_profile_id": "pcma-8k-pt8" + }, + { + "trunk_id": "provider-third", + "provider_id": "provider-third", + "egress_pool_id": "egress-single", + "codec": "PCMA", + "caller_profile_ids": [ + "caller-third" + ], + "dial_prefix": "mka755", + "enabled": true, + "sip_endpoint_ref": "provider-third", + "credential_ref": "sip-provider-third", + "media_profile_id": "pcma-8k-pt8" + } + ], + "ari": { + "base_url": "https://127.0.0.1:8088/ari", + "websocket_url": "wss://127.0.0.1:8088/ari/events", + "application": "agent-call", + "credential_ref": "ari-single" + }, + "media": { + "bind_address": "127.0.0.1", + "port": 12000, + "format": "alaw", + "sample_rate_hz": 8000, + "channels": 1, + "payload_type": 8 + }, + "recording": { + "enabled": true, + "format": "wav", + "directory": "/var/lib/sip-go-agent/recordings", + "max_bytes": 67108864 + }, + "load_evidence": { + "status": "not-yet-loaded" + }, + "allowed_targets": [ + "15003164745", + "15830461047" + ], + "media_profiles": { + "pcma-8k-pt8": { + "format": "alaw", + "sample_rate_hz": 8000, + "channels": 1, + "payload_type": 8 + }, + "slin16-16k-pt118": { + "format": "slin16", + "sample_rate_hz": 16000, + "channels": 1, + "payload_type": 118 + } + } +} diff --git a/contracts/upstream/v1/examples/static-cell-artifact.json b/contracts/upstream/v1/examples/static-cell-artifact.json new file mode 100644 index 0000000..bc4c0b2 --- /dev/null +++ b/contracts/upstream/v1/examples/static-cell-artifact.json @@ -0,0 +1,45 @@ +{ + "artifact_id": "artifact-cell-a-1", + "source_release": "management-snapshot-1", + "source_digest": "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa", + "approval_reference": "mock-approval-1", + "cell_id": "cell-a", + "revision": 1, + "config_sha256": "bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb", + "mode": "mock", + "trunks": [ + { + "trunk_id": "trunk-mock", + "provider_id": "provider-mock", + "egress_pool_id": "egress-mock", + "codec": "PCMA", + "caller_profile_ids": [ + "caller_profile_test" + ], + "dial_prefix": "7089", + "enabled": true, + "sip_endpoint_ref": "mock-sip-endpoint", + "credential_ref": null, + "media_profile_id": "slin16-16k-pt118" + } + ], + "load_evidence": null, + "allowed_targets": [ + "15003164745", + "15830461047" + ], + "media_profiles": { + "pcma-8k-pt8": { + "format": "alaw", + "sample_rate_hz": 8000, + "channels": 1, + "payload_type": 8 + }, + "slin16-16k-pt118": { + "format": "slin16", + "sample_rate_hz": 16000, + "channels": 1, + "payload_type": 118 + } + } +} diff --git a/contracts/upstream/2026-09-21-p1-v3/examples/task-control.json b/contracts/upstream/v1/examples/task-control.json similarity index 100% rename from contracts/upstream/2026-09-21-p1-v3/examples/task-control.json rename to contracts/upstream/v1/examples/task-control.json diff --git a/contracts/upstream/2026-09-21-p1-v3/fixtures.json b/contracts/upstream/v1/fixtures.json similarity index 100% rename from contracts/upstream/2026-09-21-p1-v3/fixtures.json rename to contracts/upstream/v1/fixtures.json diff --git a/contracts/upstream/2026-09-21-p1-v3/jcs-golden.json b/contracts/upstream/v1/jcs-golden.json similarity index 100% rename from contracts/upstream/2026-09-21-p1-v3/jcs-golden.json rename to contracts/upstream/v1/jcs-golden.json diff --git a/contracts/upstream/2026-09-21-p1-v3/manifest.json b/contracts/upstream/v1/manifest.json similarity index 65% rename from contracts/upstream/2026-09-21-p1-v3/manifest.json rename to contracts/upstream/v1/manifest.json index 238bb3b..36e77d4 100644 --- a/contracts/upstream/2026-09-21-p1-v3/manifest.json +++ b/contracts/upstream/v1/manifest.json @@ -1,17 +1,15 @@ { - "version": "2026-09-21-p1-v3", - "source": "project-approved-jcs-sha256", - "derived_from": "2026-09-21-p1-v2", - "source_manifest_sha256": "6ca4582ab5f0b5550508deaa9f0b3d6e6bac579f108b423be3a7c133a207ad33", + "version": "v1", + "source": "project-development-v1", "files": { - "README.md": "47c062c0bd4a9062404b270f912c0d132d3807bf25e4aff5e811ed6cb400df6d", - "ai-authorization.schema.json": "3738ee6ffe4740c9f502c606647bfb5fcf4d1054c101a296ddaada715ee358f5", - "ai-config.schema.json": "3663ea0231455ea0e5898b0bbf27c35aa632f1967283037df5d092077d195848", - "ai-digest.json": "fdd0b66d070ec3c24a698eca0d7fd7d3b33d884c303e968e1152d3a7b3f1564a", - "dispatcher-config.schema.json": "970c26b2b3832b6c8787b52dba0ebd8de49feab30b7f70da8b43450412955580", - "event-payloads.schema.json": "9a991c81ba260857aa0ac0ac36a9b65e98ea2b0dfd78395270848e8ffdf842e0", + "README.md": "b12aedfd17bbb316405defd9a2c31b78ff38ae3b39cbcfd578d7a4df708e749c", + "ai-authorization.schema.json": "2d5846e03791d4ce11c474160797b2c157ba391b993e961537e04c83eb2545e5", + "ai-config.schema.json": "b8090c2288e43cd18bbc07f8af996fee4a39acb1e10a3b5dcf11984c35464a80", + "dispatcher-config.schema.json": "d227522dabfdd8080ff25293886e11692456bf0f77b59e125525d2785a4712bf", + "event-payloads.schema.json": "e715cfb38ed7917c28501b408d69d9636bc44179cd01f0a130a8eeb5c9934d0e", "examples/agent-version-asr-only.json": "24864df1fd72a59efaaaf6d1fc81a0c7db01fbdfcd821aab4069b64a8db9b60b", "examples/agent-version-full-explicit.json": "e590148448885a1e88c473ca032d5efd719270689c3cff7aa44ca9c6ffa2b321", + "examples/agent-version-full-production-v1.json": "6a5f35f8cc4256c048d4f1ca567a3544ea7bc92bb835cfab39a000d22b73102b", "examples/agent-version.json": "d3d4bf2fae07192674e54bf32172a8e95146f11d70609f3cd8f57f0112633c2e", "examples/ai-authorization.json": "2aacf5b3a8afbc5c457ad008323559f1d51ce31c85741631481b46c46118168d", "examples/ai-config-request.json": "d6fba0382ccbac1e1585052326e9a393d941ee7d1e96cce19ece462a92c7e374", @@ -32,20 +30,27 @@ "examples/event-recording-uploaded.json": "3189da1e9966931b92aa5b9e13dab1f70d9abda1822e8c7772bcf04f24aa09f4", "examples/event-transcript-failed.json": "56385f45b43394a6061853343600e4ebf5aa01d7b6d0ff23ea79628ebfecb308", "examples/event-transcript-updated.json": "4747266786b1cbfdfe483e5c3c7c36c587eab710fd77eb7152b8172f1620ca3e", + "examples/invalid-ai-authorization-revoked.json": "0b946b43c1f773391791dfb60a2b2a03c8a69e64e5e9ea30af8591850c34b8f3", + "examples/invalid-asr-only-with-llm.json": "7343ce8d6ce63e22128ab7bc721544d681a5dd9eccfc4ab4f9d6181c5748824c", "examples/invalid-call-query-extra.json": "d5baeaacf73f4fbe4d57b1fcb6a3ca8c82603d763ccd2882298a412f00cdeb1a", "examples/invalid-correlation.json": "79051aeecb5b4726d3a392b72e2cf6d9b90a873e3a1c5065879721655a859d4d", "examples/invalid-dispatcher.json": "1a98856bf3d50a783eab538b37b1b84bd98ac5acca57a4c271244f5fa90b50e9", + "examples/invalid-oss-upload-http.json": "8e4fb4344c4bec51b47ff9b00a63afdc84d09ab827e1b6823c4e576bf6b6a3f1", "examples/invalid-v1.json": "dc795727448254a97781ae163583a0bb776a6ebcc589b1330d018083886a4a09", "examples/invalid-wildcard.json": "becd89c7d9ccfc2343417efa9d7502a629ca3a33ee8dae419a121dfa01cb7257", + "examples/oss-upload-grant.json": "268751a1a0d238636c04c004a635e3bda702bc2ef90ade0e5846b47a3c263b5d", "examples/query-pending.json": "a3c4102102d4652d2c1ffaefec88d7ea50f694ad37811d82a1dfbd0cd985ca11", "examples/query-rejected.json": "6260c6dbb5748a8140106930ac03a5a59c4d2103a30c66239c234e39f4800a11", + "examples/static-cell-artifact-real-v1.json": "b4a001457e747a039677870a3ddeccc902b8f87819c3ce2d2e37ae6a14f1ffe0", + "examples/static-cell-artifact.json": "129821e4de654ef12d3e7f155e9301ecddf798f9ca3399316a20a55273fbc61f", "examples/task-control.json": "f5b5df31c7a5d332412472db26f99d49b1d3a9aabdeb05e8a6dea9c4c85e4089", "fixtures.json": "103ff072caafeb8a0399dccb27bc0619068e9b35baf738054fdfb3c225135c78", "jcs-golden.json": "371ee1ddc2f8626215f90b9e64de79d932b757f79b84ad1a55ccdd713d9e1812", "mq-topology.json": "ade0f2dcf4247351db82ca7498941b925c832ef1ee6d546c5bf34a4921011c68", - "mq.schema.json": "13cfb57e5783f9abe1a3853d11765cacffdd2e2c34a38bf5bb68eb4744e0b889", - "oss-upload.schema.json": "cd9f98476550c4716b9cbbf4abe329a4a132a42f633c4c3db7333bfed04ec13a", - "p1-development-profile.schema.json": "c9a69466f9aa1a23ef185e0b9e0a1b8b833239609f128e33661fd051f9a115a9", - "static-cell-artifact.schema.json": "21e872c3f932e09435b89d129568e5d59e341bef5c3bfed792d06f75afbaae1f" + "mq.schema.json": "d566899abbc8f0f8404cfe79ea58b0d1e7bf7e9fc663b09b282c15d5c74f505d", + "oss-upload.schema.json": "79192cfb7838a42fcb373347080ca08429083b4c3ed1f867f587a9e0e195a4a1", + "p1-development-profile.json": "2aa7cd3f4fa07f7e1a3037107fa7a56183f28370ea06a2a9b8dc18c8790eee2d", + "p1-development-profile.schema.json": "e0f3ec455bb7fcaff4416ac4d8e3ccddb8f838b85485c85719e594d1f8896d20", + "static-cell-artifact.schema.json": "bcdeb2e5152efe23a9eeca04eca7effbfbf7a897f66079d68fb23aa87ede64be" } } diff --git a/contracts/upstream/2026-09-21-p1-v3/mq-topology.json b/contracts/upstream/v1/mq-topology.json similarity index 100% rename from contracts/upstream/2026-09-21-p1-v3/mq-topology.json rename to contracts/upstream/v1/mq-topology.json diff --git a/contracts/upstream/2026-09-21-p1-v3/mq.schema.json b/contracts/upstream/v1/mq.schema.json similarity index 99% rename from contracts/upstream/2026-09-21-p1-v3/mq.schema.json rename to contracts/upstream/v1/mq.schema.json index e2cf96b..e36dcc3 100644 --- a/contracts/upstream/2026-09-21-p1-v3/mq.schema.json +++ b/contracts/upstream/v1/mq.schema.json @@ -1,6 +1,6 @@ { "$schema": "https://json-schema.org/draft/2020-12/schema", - "$id": "https://go-sip.local/contracts/2026-09-21-p1-v3/mq.schema.json", + "$id": "https://go-sip.local/contracts/v1/mq.schema.json", "title": "agent-call MQ command and event envelope", "oneOf": [ { diff --git a/contracts/upstream/2026-09-21-p1-v3/oss-upload.schema.json b/contracts/upstream/v1/oss-upload.schema.json similarity index 98% rename from contracts/upstream/2026-09-21-p1-v3/oss-upload.schema.json rename to contracts/upstream/v1/oss-upload.schema.json index 3b45e38..86b3132 100644 --- a/contracts/upstream/2026-09-21-p1-v3/oss-upload.schema.json +++ b/contracts/upstream/v1/oss-upload.schema.json @@ -1,6 +1,6 @@ { "$schema": "https://json-schema.org/draft/2020-12/schema", - "$id": "https://go-sip.local/contracts/2026-09-21-p1-v3/oss-upload.schema.json", + "$id": "https://go-sip.local/contracts/v1/oss-upload.schema.json", "title": "Recording upload control-plane messages", "type": "object", "required": [ diff --git a/contracts/upstream/v1/p1-development-profile.json b/contracts/upstream/v1/p1-development-profile.json new file mode 100644 index 0000000..21b0db6 --- /dev/null +++ b/contracts/upstream/v1/p1-development-profile.json @@ -0,0 +1,23 @@ +{ + "profile_id": "p1-mock-two-cell-v1", + "profile_version": "1.0.0", + "environment": "mock", + "external_calls": false, + "real_authorization": "blocked", + "topology": {"dispatcher_count": 1, "agent_count": 2, "cell_count": 2, "tenant_count": 1}, + "limits": { + "global_concurrency": 6, + "global_cps": 3, + "tenant_concurrency": 2, + "tenant_cps": 1, + "pending_window_global": 64, + "pending_window_per_tenant": 16, + "lease_ttl_ms": 10000, + "final_permit_ttl_ms": 1000 + }, + "modes": ["full_ai", "asr_only"], + "retention": {"keep_unverified_assets": true, "delete_only_after_verified": true, "backup_kind": "local-sqlite-wal-consistent"}, + "status": "development-only-not-production-approval", + "real_budget": "unknown", + "operator_approval": "not-granted" +} diff --git a/contracts/upstream/2026-09-21-p1-v3/p1-development-profile.schema.json b/contracts/upstream/v1/p1-development-profile.schema.json similarity index 97% rename from contracts/upstream/2026-09-21-p1-v3/p1-development-profile.schema.json rename to contracts/upstream/v1/p1-development-profile.schema.json index d9e832a..b7c9be8 100644 --- a/contracts/upstream/2026-09-21-p1-v3/p1-development-profile.schema.json +++ b/contracts/upstream/v1/p1-development-profile.schema.json @@ -1,6 +1,6 @@ { "$schema": "https://json-schema.org/draft/2020-12/schema", - "$id": "https://go-sip.local/contracts/2026-09-21-p1-v3/p1-development-profile.schema.json", + "$id": "https://go-sip.local/contracts/v1/p1-development-profile.schema.json", "title": "P1 isolated development profile", "type": "object", "additionalProperties": false, diff --git a/contracts/upstream/2026-09-21-p1-v3/static-cell-artifact.schema.json b/contracts/upstream/v1/static-cell-artifact.schema.json similarity index 98% rename from contracts/upstream/2026-09-21-p1-v3/static-cell-artifact.schema.json rename to contracts/upstream/v1/static-cell-artifact.schema.json index d612ae2..dbb96c2 100644 --- a/contracts/upstream/2026-09-21-p1-v3/static-cell-artifact.schema.json +++ b/contracts/upstream/v1/static-cell-artifact.schema.json @@ -1,6 +1,6 @@ { "$schema": "https://json-schema.org/draft/2020-12/schema", - "$id": "https://go-sip.local/contracts/2026-09-21-p1-v3/static-cell-artifact.schema.json", + "$id": "https://go-sip.local/contracts/v1/static-cell-artifact.schema.json", "title": "Project-owned v1 static Cell/SIP hand-off artifact", "type": "object", "additionalProperties": false, diff --git a/contracts/v2_test.go b/contracts/v1_bundle_test.go similarity index 70% rename from contracts/v2_test.go rename to contracts/v1_bundle_test.go index 838ffcd..46b83ac 100644 --- a/contracts/v2_test.go +++ b/contracts/v1_bundle_test.go @@ -15,42 +15,41 @@ import ( "git.ipao.vip/rogee/go-sip/internal/tenant" ) -const v2Dir = "upstream/2026-09-21-p1-v2" -const v2Base = "https://go-sip.local/contracts/2026-09-21-p1-v2/" +const v1Dir = "upstream/v1" +const v1Base = "https://go-sip.local/contracts/v1/" -// Contract tests must never fetch an unregistered schema from the network. type offlineLoader struct{} func (offlineLoader) Load(url string) (any, error) { return nil, fmt.Errorf("schema is not in the immutable local bundle: %s", url) } -func compileV2(t *testing.T, name string) *jsonschema.Schema { +func compileV1(t *testing.T, name string) *jsonschema.Schema { t.Helper() compiler := jsonschema.NewCompiler() compiler.AssertFormat() compiler.UseLoader(offlineLoader{}) - paths, err := filepath.Glob(filepath.Join(v2Dir, "*.schema.json")) + paths, err := filepath.Glob(filepath.Join(v1Dir, "*.schema.json")) if err != nil || len(paths) == 0 { - t.Fatalf("new contract bundle missing: %v", err) + t.Fatalf("contract bundle missing: %v", err) } for _, path := range paths { var schema any - if err := json.Unmarshal(readV2(t, path), &schema); err != nil { + if err := json.Unmarshal(readV1(t, path), &schema); err != nil { t.Fatal(err) } - if err := compiler.AddResource(v2Base+filepath.Base(path), schema); err != nil { + if err := compiler.AddResource(v1Base+filepath.Base(path), schema); err != nil { t.Fatal(err) } } - schema, err := compiler.Compile(v2Base + name) + schema, err := compiler.Compile(v1Base + name) if err != nil { t.Fatal(err) } return schema } -func readV2(t *testing.T, path string) []byte { +func readV1(t *testing.T, path string) []byte { t.Helper() raw, err := os.ReadFile(path) if err != nil { @@ -59,25 +58,25 @@ func readV2(t *testing.T, path string) []byte { return raw } -func objectV2(t *testing.T, path string) map[string]any { +func objectV1(t *testing.T, path string) map[string]any { t.Helper() var value map[string]any - if err := json.Unmarshal(readV2(t, path), &value); err != nil { + if err := json.Unmarshal(readV1(t, path), &value); err != nil { t.Fatal(err) } return value } -func TestV2BundleFixtures(t *testing.T) { +func TestV1BundleFixtures(t *testing.T) { for _, name := range []string{"mq.schema.json", "event-payloads.schema.json", "dispatcher-config.schema.json"} { - t.Run(name, func(t *testing.T) { compileV2(t, name) }) + t.Run(name, func(t *testing.T) { compileV1(t, name) }) } var cases []struct { File string `json:"file"` Schema string `json:"schema"` Valid bool `json:"valid"` } - if err := json.Unmarshal(readV2(t, filepath.Join(v2Dir, "fixtures.json")), &cases); err != nil { + if err := json.Unmarshal(readV1(t, filepath.Join(v1Dir, "fixtures.json")), &cases); err != nil { t.Fatal(err) } if len(cases) < 16 { @@ -85,8 +84,8 @@ func TestV2BundleFixtures(t *testing.T) { } for _, tc := range cases { t.Run(tc.File, func(t *testing.T) { - schema := compileV2(t, tc.Schema) - value := objectV2(t, filepath.Join(v2Dir, tc.File)) + schema := compileV1(t, tc.Schema) + value := objectV1(t, filepath.Join(v1Dir, tc.File)) err := schema.Validate(value) if (err == nil) != tc.Valid { t.Fatalf("valid=%v, validation=%v", tc.Valid, err) @@ -95,8 +94,8 @@ func TestV2BundleFixtures(t *testing.T) { } } -func TestV2ExecuteIdentityAndTenantConstraints(t *testing.T) { - schema := compileV2(t, "mq.schema.json") +func TestV1ExecuteIdentityAndTenantConstraints(t *testing.T) { + schema := compileV1(t, "mq.schema.json") for _, tc := range []struct { name string edit func(map[string]any) @@ -110,7 +109,7 @@ func TestV2ExecuteIdentityAndTenantConstraints(t *testing.T) { {"extra payload", func(m map[string]any) { m["payload"].(map[string]any)["mode"] = "full_ai" }}, } { t.Run(tc.name, func(t *testing.T) { - value := objectV2(t, filepath.Join(v2Dir, "examples/call-execute.json")) + value := objectV1(t, filepath.Join(v1Dir, "examples/call-execute.json")) tc.edit(value) if err := schema.Validate(value); err == nil { t.Fatal("invalid envelope accepted") @@ -119,8 +118,8 @@ func TestV2ExecuteIdentityAndTenantConstraints(t *testing.T) { } } -func TestV2ResponseCorrelationAndResultBranches(t *testing.T) { - schema := compileV2(t, "mq.schema.json") +func TestV1ResponseCorrelationAndResultBranches(t *testing.T) { + schema := compileV1(t, "mq.schema.json") for _, tc := range []struct { name string edit func(map[string]any) @@ -132,7 +131,7 @@ func TestV2ResponseCorrelationAndResultBranches(t *testing.T) { {"extra result", func(m map[string]any) { m["payload"].(map[string]any)["raw"] = map[string]any{} }}, } { t.Run(tc.name, func(t *testing.T) { - value := objectV2(t, filepath.Join(v2Dir, "examples/command-query-result.json")) + value := objectV1(t, filepath.Join(v1Dir, "examples/command-query-result.json")) tc.edit(value) if err := schema.Validate(value); err == nil { t.Fatal("invalid query response accepted") @@ -141,39 +140,29 @@ func TestV2ResponseCorrelationAndResultBranches(t *testing.T) { } } -func TestV2UploadIsAFactNotASaaSHandshake(t *testing.T) { - schema := compileV2(t, "mq.schema.json") - value := objectV2(t, filepath.Join(v2Dir, "examples/event-recording-uploaded.json")) - if err := schema.Validate(value); err != nil { - t.Fatal(err) - } +func TestV1UploadIsAFactNotASaaSHandshake(t *testing.T) { + schema := compileV1(t, "mq.schema.json") for _, field := range []string{"oss_id", "verified", "token", "upload_url", "access_key_secret"} { t.Run(field, func(t *testing.T) { - value := objectV2(t, filepath.Join(v2Dir, "examples/event-recording-uploaded.json")) + value := objectV1(t, filepath.Join(v1Dir, "examples/event-recording-uploaded.json")) value["payload"].(map[string]any)[field] = "not-a-real-value" if err := schema.Validate(value); err == nil { t.Fatal("uploaded fact accepted a credential or SaaS processing claim") } }) } - old := objectV2(t, "upstream/2026-09-19-p1-v1/examples/event-recording-ready.json") - old["schema_version"] = "2.0" - old["dispatcher_id"] = value["dispatcher_id"] - if err := schema.Validate(old); err == nil { - t.Fatal("v2 still accepts the superseded recording.ready notification") - } for _, kind := range []string{"recording.upload-session.request", "recording.upload-session.result", "recording.complete", "recording.verified"} { - if strings.Contains(string(readV2(t, filepath.Join(v2Dir, "mq.schema.json"))), `"`+kind+`"`) { + if strings.Contains(string(readV1(t, filepath.Join(v1Dir, "mq.schema.json"))), `"`+kind+`"`) { t.Errorf("removed upload handshake is still in the published schema: %s", kind) } } } -func TestV2DispatcherConfigDoesNotAcceptSecretsOrTTLOverride(t *testing.T) { - schema := compileV2(t, "dispatcher-config.schema.json") +func TestV1DispatcherConfigDoesNotAcceptSecretsOrTTLOverride(t *testing.T) { + schema := compileV1(t, "dispatcher-config.schema.json") for _, field := range []string{"access_key_id", "access_key_secret", "grant_ttl_seconds", "token"} { t.Run(field, func(t *testing.T) { - value := objectV2(t, filepath.Join(v2Dir, "examples/dispatcher-config.json")) + value := objectV1(t, filepath.Join(v1Dir, "examples/dispatcher-config.json")) value["oss"].(map[string]any)[field] = "not-a-real-value" if err := schema.Validate(value); err == nil { t.Fatal("unexpected secret/override field accepted") @@ -182,7 +171,7 @@ func TestV2DispatcherConfigDoesNotAcceptSecretsOrTTLOverride(t *testing.T) { } } -func TestV2TopologyMatchesDispatcherRoutes(t *testing.T) { +func TestV1TopologyMatchesDispatcherRoutes(t *testing.T) { var topology struct { Exchanges map[string]struct { Type string `json:"type"` @@ -199,7 +188,7 @@ func TestV2TopologyMatchesDispatcherRoutes(t *testing.T) { TenantBytes int `json:"tenant_key_max_utf8_bytes"` TokenSeconds int `json:"upload_token_seconds"` } - if err := json.Unmarshal(readV2(t, filepath.Join(v2Dir, "mq-topology.json")), &topology); err != nil { + if err := json.Unmarshal(readV1(t, filepath.Join(v1Dir, "mq-topology.json")), &topology); err != nil { t.Fatal(err) } if !topology.Durable || !topology.Persistent || !topology.Mandatory || !topology.Confirm || topology.TenantBytes != 196 || topology.TokenSeconds != 900 { @@ -227,27 +216,27 @@ func TestV2TopologyMatchesDispatcherRoutes(t *testing.T) { } } -func TestV2ManifestPinsEveryBundleFile(t *testing.T) { +func TestV1ManifestPinsEveryBundleFile(t *testing.T) { var manifest struct { Version string `json:"version"` Source string `json:"source"` Files map[string]string `json:"files"` } - if err := json.Unmarshal(readV2(t, filepath.Join(v2Dir, "manifest.json")), &manifest); err != nil { + if err := json.Unmarshal(readV1(t, filepath.Join(v1Dir, "manifest.json")), &manifest); err != nil { t.Fatal(err) } - if manifest.Version != "2026-09-21-p1-v2" || manifest.Source != "project-approved-mq-only-v2" || len(manifest.Files) == 0 { + if manifest.Version != "v1" || manifest.Source != "project-development-v1" || len(manifest.Files) == 0 { t.Fatal("invalid project-local provenance") } - err := filepath.WalkDir(v2Dir, func(path string, entry os.DirEntry, err error) error { + err := filepath.WalkDir(v1Dir, func(path string, entry os.DirEntry, err error) error { if err != nil || entry.IsDir() { return err } - rel, err := filepath.Rel(v2Dir, path) + rel, err := filepath.Rel(v1Dir, path) if err != nil || rel == "manifest.json" { return err } - actual := sha256.Sum256(readV2(t, path)) + actual := sha256.Sum256(readV1(t, path)) if manifest.Files[filepath.ToSlash(rel)] != hex.EncodeToString(actual[:]) { t.Errorf("missing/incorrect manifest hash: %s", rel) } @@ -261,7 +250,7 @@ func TestV2ManifestPinsEveryBundleFile(t *testing.T) { t.Errorf("non-local manifest entry: %s", rel) continue } - if _, err := os.Stat(filepath.Join(v2Dir, rel)); err != nil { + if _, err := os.Stat(filepath.Join(v1Dir, rel)); err != nil { t.Error(err) } } diff --git a/contracts/v3_test.go b/contracts/v1_jcs_test.go similarity index 81% rename from contracts/v3_test.go rename to contracts/v1_jcs_test.go index 1a6b099..1d3896e 100644 --- a/contracts/v3_test.go +++ b/contracts/v1_jcs_test.go @@ -12,19 +12,19 @@ import ( "github.com/santhosh-tekuri/jsonschema/v6" ) -func TestV3BundleHashesAndOfflineFixtures(t *testing.T) { - const dir = "upstream/2026-09-21-p1-v3" +func TestV1BundleHashesAndOfflineFixtures(t *testing.T) { + const dir = "upstream/v1" var manifest struct { Files map[string]string `json:"files"` } - if err := json.Unmarshal(readV2(t, dir+"/manifest.json"), &manifest); err != nil { + if err := json.Unmarshal(readV1(t, dir+"/manifest.json"), &manifest); err != nil { t.Fatal(err) } compiler := jsonschema.NewCompiler() compiler.AssertFormat() compiler.UseLoader(offlineLoader{}) for name, want := range manifest.Files { - raw := readV2(t, filepath.Join(dir, name)) + raw := readV1(t, filepath.Join(dir, name)) sum := sha256.Sum256(raw) if hex.EncodeToString(sum[:]) != want { t.Fatalf("hash mismatch: %s", name) @@ -63,16 +63,16 @@ func TestV3BundleHashesAndOfflineFixtures(t *testing.T) { File, Schema string Valid bool } - if err := json.Unmarshal(readV2(t, dir+"/fixtures.json"), &fixtures); err != nil { + if err := json.Unmarshal(readV1(t, dir+"/fixtures.json"), &fixtures); err != nil { t.Fatal(err) } for _, fixture := range fixtures { - schema, err := compiler.Compile("https://go-sip.local/contracts/2026-09-21-p1-v3/" + fixture.Schema) + schema, err := compiler.Compile("https://go-sip.local/contracts/v1/" + fixture.Schema) if err != nil { t.Fatal(err) } var value any - if err := json.Unmarshal(readV2(t, dir+"/"+fixture.File), &value); err != nil { + if err := json.Unmarshal(readV1(t, dir+"/"+fixture.File), &value); err != nil { t.Fatal(err) } if err := schema.Validate(value); (err == nil) != fixture.Valid { @@ -81,9 +81,9 @@ func TestV3BundleHashesAndOfflineFixtures(t *testing.T) { } } -func TestV3PythonGoJCSGolden(t *testing.T) { +func TestV1PythonGoJCSGolden(t *testing.T) { var vectors []struct{ Name, Input, Canonical, SHA256 string } - if err := json.Unmarshal(readV2(t, "upstream/2026-09-21-p1-v3/jcs-golden.json"), &vectors); err != nil { + if err := json.Unmarshal(readV1(t, "upstream/v1/jcs-golden.json"), &vectors); err != nil { t.Fatal(err) } for _, vector := range vectors { diff --git a/docs/G0开发准备与契约冻结提案_v0.1.md b/docs/G0开发准备与契约冻结提案_v0.1.md index 3e54dd0..78ec353 100644 --- a/docs/G0开发准备与契约冻结提案_v0.1.md +++ b/docs/G0开发准备与契约冻结提案_v0.1.md @@ -2,7 +2,7 @@ ## 1. 状态、权限与使用方式 -**状态:D01–D10原方向已确认,旧W01契约和W02 Proto已有项目内证据;本轮用户确认SaaS↔Dispatcher全MQ,受影响G0的项目内部分已按[计划§1.2/§8.2](plan-0918.md)重新验证。** SaaS与D之间所有请求、响应和事件禁止HTTP,每个D具备全局唯一ID和独立接收Topic/队列;v2/v3 Schema、拓扑和关联已有本地包及RabbitMQ证据,外部发布/签收另计。OSS补充确认:配置存于D配置文件,A向D领取固定15分钟临时上传TOKEN后直传;SaaS不再提供OSS配置/TOKEN,上传完成以recording.uploaded可靠入队为界,不等待SaaS verified或OSS ID,D不转发文件。原HTTP方向被本修订替代,不把旧证据覆盖到新设计。 +**状态:D01–D10原方向已确认,旧W01契约和W02 Proto已有项目内证据;本轮用户确认SaaS↔Dispatcher全MQ,受影响G0的项目内部分已按[计划§1.2/§8.2](plan-0918.md)重新验证。** SaaS与D之间所有请求、响应和事件禁止HTTP,每个D具备全局唯一ID和独立接收Topic/队列;V1 Schema、拓扑和关联已有本地包及RabbitMQ证据,外部发布/签收另计。OSS补充确认:配置存于D配置文件,A向D领取固定15分钟临时上传TOKEN后直传;SaaS不再提供OSS配置/TOKEN,上传完成以recording.uploaded可靠入队为界,不等待SaaS verified或OSS ID,D不转发文件。原HTTP方向被本修订替代,不把旧证据覆盖到新设计。 本项目已创建并验证自己的 Go module、W01 bundle、W02 Proto/stubs、RPC/mTLS 和本地 Mock 测试;未修改父项目权威来源、字段索引或生成产物,未访问真实供应商或创建云资源。文件名保留“提案”以保持链接稳定,不代表还需重复审批已确认方向。 diff --git a/docs/Go重写方案_v0.3.md b/docs/Go重写方案_v0.3.md index 407d3a3..8ccc55b 100644 --- a/docs/Go重写方案_v0.3.md +++ b/docs/Go重写方案_v0.3.md @@ -111,7 +111,7 @@ Dispatcher配置包含MQ/SaaS受控引用、SQLite路径、两个Agent Endpoint ### 3.2 权威来源与独立拆仓 -**本轮用户已确认SaaS↔Dispatcher全MQ:双方不再有任何HTTP请求/回调;每个D有全局唯一ID和独立接收Topic/队列。** 执行、控制、查询、补传、AI配置/授权及上传完成事实均经MQ;上传不申请SaaS会话、不等待verified/OSS ID,详见[SaaS↔D契约](contracts/saas-dispatcher.md)与[计划§1.2/§8.2](plan-0918.md)。旧HTTP和旧租户路由已删除;新Schema/拓扑/身份生命周期/关联已在项目内v2/v3包和本地证据中冻结,旧源包及哈希不改。 +**本轮用户已确认SaaS↔Dispatcher全MQ:双方不再有任何HTTP请求/回调;每个D有全局唯一ID和独立接收Topic/队列。** 执行、控制、查询、补传、AI配置/授权及上传完成事实均经MQ;上传不申请SaaS会话、不等待verified/OSS ID,详见[SaaS↔D契约](contracts/saas-dispatcher.md)与[计划§1.2/§8.2](plan-0918.md)。旧HTTP和旧租户路由已删除;新Schema/拓扑/身份生命周期/关联已在项目内唯一 V1 包和本地证据中冻结,旧源包及哈希不改。 现有上游权威是《SaaS交互_OpenAPI与MQ契约规划_v0.1.md》(正文 v1.0)及经核验的发布产物。现有产物包括 `mq.schema.json`、`executor.openapi.yaml`、`cell-agent.openapi.yaml`、AI 配置及 SIP 管理相关契约。文件存在不代表完整覆盖:P0 必须逐条核对正文、Schema、状态语义和实现差异。 diff --git a/docs/contracts/dispatcher-agent.md b/docs/contracts/dispatcher-agent.md index 226541f..99aa6fd 100644 --- a/docs/contracts/dispatcher-agent.md +++ b/docs/contracts/dispatcher-agent.md @@ -316,7 +316,7 @@ Dispatcher当前执行: 完成依据是persistent消息进入指定durable队列/绑定、mandatory无return且publisher confirm成功。仅写本地outbox不算交付完成。通知恢复不要求重取TOKEN或重新PUT,也不因原grant此时过期而重传已上传的文件。 -旧OSS HEAD/verified及oss_id响应已删除,Proto保留原字段编号和名称为reserved。不等待SaaS会话或消费回复,不新增VERIFYING、不发recording.ready;完成不表示SaaS已处理。当前MQ wire为2.0,运行使用v3契约包(AI JCS摘要修订),上传字段沿用已批准的[v2冻结方案](mq-only-v2-freeze-proposal.md)。本地MQ无绑定、确认丢失、重启及原通知恢复已有[证据](../evidence/20260921-mq-upload-progress.md),不等于真实OSS/SaaS联调通过。 +旧OSS HEAD/verified及oss_id响应已删除,Proto保留原字段编号和名称为reserved。不等待SaaS会话或消费回复,不新增VERIFYING、不发recording.ready;完成不表示SaaS已处理。当前MQ wire为2.0,运行使用唯一 V1 契约包(包含 AI JCS 摘要规则),上传字段沿用已批准的[V1冻结方案](mq-only-v1-freeze-proposal.md)。本地MQ无绑定、确认丢失、重启及原通知恢复已有[证据](../evidence/20260921-mq-upload-progress.md),不等于真实OSS/SaaS联调通过。 ## 7. 错误、幂等与未知结果 @@ -364,5 +364,5 @@ Agent 侧写操作的内存 operation key 为: - `internal/ai/snapshot.go` - `internal/ai/authorization.go` - `cmd/sip-go-agent/main.go` -- `contracts/upstream/2026-09-19-p1-v1/event-payloads.schema.json` -- `contracts/upstream/2026-09-19-p1-v1/ai-authorization.schema.json` +- `contracts/upstream/v1/event-payloads.schema.json` +- `contracts/upstream/v1/ai-authorization.schema.json` diff --git a/docs/contracts/mq-only-v2-freeze-proposal.md b/docs/contracts/mq-only-v1-freeze-proposal.md similarity index 93% rename from docs/contracts/mq-only-v2-freeze-proposal.md rename to docs/contracts/mq-only-v1-freeze-proposal.md index 6a3a675..4b07eae 100644 --- a/docs/contracts/mq-only-v2-freeze-proposal.md +++ b/docs/contracts/mq-only-v1-freeze-proposal.md @@ -1,8 +1,8 @@ -# MQ-only v2 与 Dispatcher OSS 配置:已确认合同 +# MQ-only V1 与 Dispatcher OSS 配置:已确认合同 -状态:用户已确认本文件的身份、纯Topic、配置、消息及查询结构;随后通过目标修订确认**上传只负责可靠入队**,并单独确认 `recording.uploaded` 名称/字段及R13完成边界。旧上传会话/verified等待方案被替代,不新增VERIFYING。机读v2包及AI JCS修订后的v3包已生成并通过离线测试;本地运行切换、RabbitMQ往返和联合恢复已有证据,真实SaaS/生产验收仍不在本轮。 +状态:用户已确认本文件的身份、纯Topic、配置、消息及查询结构;随后通过目标修订确认**上传只负责可靠入队**,并单独确认 `recording.uploaded` 名称/字段及R13完成边界。旧上传会话/verified等待方案被替代,不新增VERIFYING。单一 V1 机读包已包含 MQ-only 与 AI JCS 规则并通过离线测试;本地运行切换、RabbitMQ往返和联合恢复已有证据,真实SaaS/生产验收仍不在本轮。 -机读来源:`contracts/upstream/2026-09-21-p1-v2/`。`manifest.json`记录项目内来源、旧源文件哈希与新文件哈希;不是外部SaaS签收。旧v1包保持原样,不提供运行时v1/HTTP回退。当前目标由本会话Agent独立执行,不启动子Agent。 +机读来源:`contracts/upstream/v1/`。`manifest.json`记录当前项目内 V1 文件哈希;不是外部SaaS签收。不另设运行时第二套契约或 HTTP 回退。当前目标由本会话Agent独立执行,不启动子Agent。 ## 1. Topic 与租户边界 diff --git a/docs/contracts/saas-dispatcher.md b/docs/contracts/saas-dispatcher.md index 0daa222..89b7781 100644 --- a/docs/contracts/saas-dispatcher.md +++ b/docs/contracts/saas-dispatcher.md @@ -11,12 +11,12 @@ | 层级 | 本次状态 | 使用边界 | | --- | --- | --- | | 已确认设计 | MQ-only、Dispatcher 唯一身份、独立 Topic | 后续设计与实现必须遵守 | -| 新版项目内契约 | `2026-09-21-p1-v2`身份/Topic/消息/配置/正反例及哈希,AI JCS修订后的v3包 | 以[mq-only-v2冻结方案](mq-only-v2-freeze-proposal.md)及机读包为准;本地运行往返已有证据,外部SaaS签收仍不在本轮 | +| 当前项目内契约 | 唯一 V1 包中的身份/Topic/消息/配置/正反例、哈希和 AI JCS 规则 | 以[mq-only V1冻结方案](mq-only-v1-freeze-proposal.md)及机读包为准;本地运行往返已有证据,外部SaaS签收仍不在本轮 | | 现有实现/旧包 | 下列旧字段、路由及代码事实 | 仅用于识别差异,不代表新设计已实现或通过验收 | -当前固定包为 `contracts/upstream/2026-09-19-p1-v1/`(`contracts.SourceCommit = 2026-09-19-p1-v1`)。其中的 HTTP OpenAPI 与仅按租户路由的 MQ 拓扑**不再是目标方案**。旧包及其哈希保持不变;W01 须发布新版本、严格 Schema、拓扑及正反例,不能手改旧包、生成字段索引或通过放宽 `additionalProperties` 绕过冻结。 +当前固定包为 `contracts/upstream/v1/`(`contracts.SourceCommit = v1`)。其中不包含已归档的 HTTP OpenAPI,也不使用仅按租户路由的旧拓扑;当前 V1 包的 Schema、拓扑、正反例和哈希是唯一运行输入。不能在包外另造版本或通过放宽 `additionalProperties` 绕过冻结。 -当前已完成本地实现阶段;v2机读包、AI摘要修订后的v3包、离线正反例、路由规则及RabbitMQ运行往返均有证据。下文§3–§4的v1字段/代码描述仅为迁移差异,不能作为v2/v3接入要求;运行证据不等于外部SaaS签收。 +当前已完成本地实现阶段;唯一 V1 机读包、AI摘要、离线正反例、路由规则及RabbitMQ运行往返均有证据。下文旧字段/代码描述仅用于解释差异;运行证据不等于外部SaaS签收。 ## 2. 通信拓扑、Dispatcher 身份与交付语义 @@ -34,10 +34,10 @@ ### 2.2 全局唯一身份与独立 Topic -- `dispatcher_id` 是当前v2/v3运行信封和路由中的独立全局身份;每个 Dispatcher 的 ID 必须独立、全局不重复,不能拿租户 ID、Agent ID、Cell ID、地址或启动代次代替。 +- `dispatcher_id` 是当前 V1 运行信封和路由中的独立全局身份;每个 Dispatcher 的 ID 必须独立、全局不重复,不能拿租户 ID、Agent ID、Cell ID、地址或启动代次代替。 - Dispatcher 身份与 `dispatcher_epoch` 分开:前者识别 Dispatcher,后者用于一次运行所有权/会话的 fencing。身份持久绑定、重复身份占用、重启恢复及失效会话拒绝已有本地测试;不因 epoch 改变就丢弃原消息、执行或资产归属。 - 每个 Dispatcher 有独立的接收 Topic 及对应队列/绑定;多个 Dispatcher **不能共用一条接收队列竞争消费指定目标的消息,也不能全部订阅同一广播 Topic 后仅靠正文过滤**。 -- RabbitMQ 的 Topic 订阅由 exchange、routing key、queue 和 binding 表达;当前固定为 `agent-call.dispatchers.v2`、`agent-call.saas.v2`、`agent-call.dead-letter.v2` 及每个 Dispatcher/租户的独立队列和精确路由键,字段以v2/v3机读契约包为准。 +- RabbitMQ 的 Topic 订阅由 exchange、routing key、queue 和 binding 表达;当前固定为 `agent-call.dispatchers.v2`、`agent-call.saas.v2`、`agent-call.dead-letter.v2` 及每个 Dispatcher/租户的独立队列和精确路由键,字段以唯一 V1 机读契约包为准。 - SaaS 发给 D1 的命令、配置、授权和上传结果,只能进入 D1 的专用接收路径;D2 的路径与之独立。D1 发出的响应/事件须能回溯 D1 与原请求。SaaS 订阅布局亦由同一版契约定义,不假定现有共享结果队列已满足新约束。 - 独立 Dispatcher 路由不替代租户隔离:保留租户独立队列、有界窗口、原值 `tenant_key` 和复合幂等语义;新拓扑必须同时区分 Dispatcher 与租户,不能退化为 Dispatcher 内所有租户共享无界队列。 - `tenant_key` 不清洗、编码或截断。旧布局的 224 UTF-8 字节预算不能在加上 Dispatcher 身份后直接照搬;W01 须校验完整 routing key/queue 名长度及分隔符、通配符边界,超限拒绝发布并保留源任务,不改变既有租户标识。 @@ -66,7 +66,7 @@ P1 仍只运行一个单活 Dispatcher。现在必须在合同及本地路由测 | dead-letter exchange | `agent-call.dead-letter.v1`,durable `topic` | 恢复必须保留原 Dispatcher、租户和消息身份 | | 默认 prefetch | `1` | 保持有界消费;不是多 Dispatcher 隔离证明 | -旧实现按消费租户声明 command queue 和 `.dlq.v1`,SaaS 结果队列基线为 `agent-call.saas.events.v1`、binding `agent-call.#`。这些名称仅记录旧包事实,不构成新拓扑批准;当前运行使用v2/v3精确 Dispatcher/租户路由。 +旧实现按消费租户声明 command queue 和 `.dlq.v1`,SaaS 结果队列基线为 `agent-call.saas.events.v1`、binding `agent-call.#`。这些名称仅记录旧实现事实,不构成当前拓扑;当前 V1 运行使用精确 Dispatcher/租户路由。 ### 3.2 旧 `call.execute` 外壳 @@ -188,7 +188,7 @@ v2已用`recording.uploaded`取代本项目的`recording.ready`;不得返回 ### 5.1 待冻结内容 -消息类型、信封和响应枚举以已确认的v2机读包及[mq-only-v2合同](mq-only-v2-freeze-proposal.md)为准。旧HTTP header、URL和状态码不是MQ合同,不能塞进旧call.execute或宽松metadata中。 +消息类型、信封和响应枚举以唯一 V1 机读包及[mq-only V1合同](mq-only-v1-freeze-proposal.md)为准。旧HTTP header、URL和状态码不是MQ合同,不能塞进旧call.execute或宽松metadata中。 ### 5.2 控制任务 @@ -247,4 +247,4 @@ D 根据 MQ 任务中的原 `tenant_id/tenant_key + agent_version_id`,通过 M - [时间泳道图](./saas-rabbitmq-oss-dispatcher-agent-timeline.md):已按当前recording.uploaded边界更新;外部SaaS/真实OSS处理仍不在本地证据范围。 - [Dispatcher ↔ Agent 契约](./dispatcher-agent.md):现有 Proto/handler 事实、15分钟授权和上传通知恢复边界。 - 旧实现事实:`internal/contract/contract.go`、`internal/mq/amqp.go`、`internal/tenant/routing.go`、`internal/dispatcher/consumer.go`、`internal/dispatcher/dispatcher.go`、`internal/store/store.go`、`internal/store/facts.go`。旧HTTP源码仅可在历史基线中查阅,不是当前运行路径。 -- 旧固定包:`contracts/upstream/2026-09-19-p1-v1/` 下 `mq.schema.json`、`event-payloads.schema.json`、`mq-topology.md`、`executor.openapi.yaml`、`saas.openapi.yaml`、`ai-config.openapi.yaml`;保留原样,不代表 MQ-only 新契约已发布。 +- 当前固定包:`contracts/upstream/v1/` 下的 `mq.schema.json`、`event-payloads.schema.json`、`mq-topology.json`、AI/Dispatcher/OSS/静态 Cell Schema 及业务正反例;归档目录中的旧 OpenAPI 和历史包不属于运行输入。 diff --git a/docs/contracts/saas-rabbitmq-oss-dispatcher-agent-timeline.md b/docs/contracts/saas-rabbitmq-oss-dispatcher-agent-timeline.md index aa04261..ee98713 100644 --- a/docs/contracts/saas-rabbitmq-oss-dispatcher-agent-timeline.md +++ b/docs/contracts/saas-rabbitmq-oss-dispatcher-agent-timeline.md @@ -7,7 +7,7 @@ - **上传只保证recording.uploaded可靠进入指定持久队列**。不申请SaaS上传会话,不等待verified/OSS ID,不新增VERIFYING,不把入队当SaaS已处理。 - P1单D/单A/单Cell/单租户;D1/D2只用于本地消息隔离验证,不扩展调度HA。 -本图为目标流程;v2 Schema/fixture通过不等于运行时接线或真实供应商验收。精确消息见[已确认v2合同](mq-only-v2-freeze-proposal.md)与`contracts/upstream/2026-09-21-p1-v2/`。 +本图为目标流程;V1 Schema/fixture通过不等于运行时接线或真实供应商验收。精确消息见[已确认V1合同](mq-only-v1-freeze-proposal.md)与`contracts/upstream/v1/`。 ## 2. 独立订阅关系 @@ -111,6 +111,6 @@ sequenceDiagram ## 5. 当前实现差异 -旧SaaS业务HTTP实现和启动配置已删除,执行、查询、控制、AI请求及上传通知已接入v2/v3 MQ。本地证据覆盖D身份/租户隔离、不可路由、confirm/DLQ、断连、重复、迟到revision、SQLite重启和recording.uploaded恢复;不得把这些本地证据当作外部SaaS或生产通过。 +旧SaaS业务HTTP实现和启动配置已删除,执行、查询、控制、AI请求及上传通知已接入单一 V1 MQ。本地证据覆盖D身份/租户隔离、不可路由、confirm/DLQ、断连、重复、迟到revision、SQLite重启和recording.uploaded恢复;不得把这些本地证据当作外部SaaS或生产通过。 旧会话/verified控制流程已移出目标,不再为它增加RPC、状态或测试服务器业务系统。通知重复/确认丢失/重启沿原消息身份恢复,不重新PUT、不新建资产、不重拨;SaaS后续处理不属于本项目。 diff --git a/docs/evidence/20260918-acceptance-matrix.md b/docs/evidence/20260918-acceptance-matrix.md index 9744664..202be1b 100644 --- a/docs/evidence/20260918-acceptance-matrix.md +++ b/docs/evidence/20260918-acceptance-matrix.md @@ -6,7 +6,7 @@ | 门禁 | 本地结果 | 证据/未决项 | | --- | --- | --- | -| G0 / W01 契约发布 | **本地通过 / 外部阻塞** | 项目内 `contracts/upstream/2026-09-18-p1-baseline` 已完成严格事件/双模式 AI/授权/OSS/静态制品/profile Schema、正反例与哈希;明确继承 dirty source 且非外部权威,真实预算/授权仍未签收。 | +| G0 / W01 契约发布 | **本地通过 / 外部阻塞** | 项目内 `contracts/archive/upstream/2026-09-18-p1-baseline` 已完成严格事件/双模式 AI/授权/OSS/静态制品/profile Schema、正反例与哈希;明确继承 dirty source 且非外部权威,真实预算/授权仍未签收。 | | W02 Unary Proto/会话 | **本地通过 / 集成待验证** | `agent.v1.AgentControlService` Proto、生成 stubs、`proto/ERRORS.md`、Buf manifest 和生成/handler 测试通过;Dispatcher/Agent部署级运行会话仍需联测。 | | W03-a 工具链/依赖 | **本地通过** | `go.mod` Go 1.27.1、Cobra 双子命令、`go mod verify`、依赖许可证清单和 `govulncheck@v1.7.0` 无漏洞扫描;ARI/LLM/ASR/TTS 隔离 API/协议 Mock PoC 已记录,正式锁版和真实供应商仍未验收。 | | W03-c SQLite/MQ PoC | **本地通过 / 外部未验收** | inbox、幂等、outbox、publisher-confirm 边界、租户队列/版本化 exchange、lease、配额和控制 CAS 有 race 单测;`make mq-integration-local` 以 disposable RabbitMQ 4.1.8 验证 adapter confirm/ACK/permanent reject→DLQ/consumer cancellation,并验证 Dispatcher tenant consume→SQLite inbox/task/outbox→event publish;当前候选二进制另在 owner-authorized ECS 通过隔离 RabbitMQ 完成 `routed=true`、`inbox=1/task=1/outbox=1`,再由候选 Dispatcher flush 为 `task_status=accepted/outbox_status=published`(证据:`docs/evidence/20260918-rabbitmq-integration.md`);SaaS 侧使用版本化 contract/fixture Mock,边界记录在 `docs/evidence/20260919-local-saas-contract-mock.md`;没有批准 broker 版本/ACL/崩溃注入/SaaS application receipt。 | diff --git a/docs/evidence/20260918-contract-input-blocker.md b/docs/evidence/20260918-contract-input-blocker.md index e5f9935..ce83529 100644 --- a/docs/evidence/20260918-contract-input-blocker.md +++ b/docs/evidence/20260918-contract-input-blocker.md @@ -2,7 +2,7 @@ The user selected **provide formal W01/W02 artifacts and continue**. The only new candidate found in the parent worktree was copied read-only into -`contracts/upstream/2026-09-17-snapshot/` and verified against its recorded +`contracts/archive/upstream/2026-09-17-snapshot/` and verified against its recorded file hashes. It is not yet a formal release: diff --git a/docs/evidence/20260918-g0-status.md b/docs/evidence/20260918-g0-status.md index b6163e8..edaf950 100644 --- a/docs/evidence/20260918-g0-status.md +++ b/docs/evidence/20260918-g0-status.md @@ -49,7 +49,7 @@ repository is `go-sip`; local release manifests preserve the historical fact. ## References -- Project baseline: `contracts/upstream/2026-09-18-p1-baseline/` +- Project baseline: `contracts/archive/upstream/2026-09-18-p1-baseline/` - Local evidence: `docs/evidence/20260918-local-development.json` - W05 SQLite restart evidence: `docs/evidence/20260918-w05-restart.md` - W06/W12 targeted local evidence: `docs/evidence/20260918-w06-w12-local.md` diff --git a/docs/evidence/20260918-local-development.json b/docs/evidence/20260918-local-development.json index 017cb8a..ad44c05 100644 --- a/docs/evidence/20260918-local-development.json +++ b/docs/evidence/20260918-local-development.json @@ -3,7 +3,7 @@ "scope": "go-sip local development only", "working_tree": "dirty-project-worktree", "source_contract": { - "active_bundle": "contracts/upstream/2026-09-18-p1-baseline", + "active_bundle": "contracts/archive/upstream/2026-09-18-p1-baseline", "release_kind": "project-owned-development-baseline", "external_authority": false, "source_bundle": "2026-09-17-snapshot", diff --git a/docs/evidence/20260919-single-node-ai-closure.md b/docs/evidence/20260919-single-node-ai-closure.md index 4c56d55..e4ca794 100644 --- a/docs/evidence/20260919-single-node-ai-closure.md +++ b/docs/evidence/20260919-single-node-ai-closure.md @@ -9,7 +9,7 @@ The second Cell is intentionally out of this iteration. ## Completed -- Active contract bundle is `contracts/upstream/2026-09-19-p1-v1`. +- Active contract bundle is `contracts/upstream/v1`. - `static-cell-artifact-v1.json` validates as `mode=real` with ARI, per-trunk media profiles, the three provider bindings selecting PCMA/A-law 8 kHz RTP payload type 8 (plus an optional slin16/16 kHz profile), and 0600-WAV diff --git a/docs/evidence/20260920-pcma-mixed-callflow.json b/docs/evidence/20260920-pcma-mixed-callflow.json index 489e3a0..c438e12 100644 --- a/docs/evidence/20260920-pcma-mixed-callflow.json +++ b/docs/evidence/20260920-pcma-mixed-callflow.json @@ -4,7 +4,7 @@ "environment": "mock", "synthetic_only": true, "purpose": "Verify the PCMA/A-law trunk media profile through the Go call-once ARI flow.", - "contract": "contracts/upstream/2026-09-19-p1-v1", + "contract": "contracts/upstream/v1", "candidate_package": "deploys/packages/sip-go-agent-0.1.0-p1.20260919-linux-amd64.tar.gz", "candidate_sha256": "bc106f733e26354221c18c7bb593eca84a4267dec3156f80311eb30f630e7b84", "test_setup": { diff --git a/docs/evidence/20260921-ai-jcs-digest.md b/docs/evidence/20260921-ai-jcs-digest.md index c28cd01..a178b8e 100644 --- a/docs/evidence/20260921-ai-jcs-digest.md +++ b/docs/evidence/20260921-ai-jcs-digest.md @@ -8,9 +8,9 @@ - Go/Python 复用 `github.com/cyberphone/json-canonicalization`,固定 `v0.0.0-20241213102144-19d51d7fe467`;不自写规范化算法。 - `ai.Validate` 保留原始配置字节,但摘要取 JCS 结果;拒绝非法 UTF-8,不接受旧摘要回退。 -- 新包:`contracts/upstream/2026-09-21-p1-v3/`,MQ 线上的 `schema_version` 仍为 `2.0`。 -- manifest SHA-256:`e09e8563f4a7bc9d70e3a4b9782efbaeca8858965433cefb1b60355115159d1c`。 -- v1/v2 不可变包保持原样。发布器从校验过的 v2 文件生成新包,在离线正反例和 AI Schema 校验后发布;已存在目标若内容不同,明确失败。 +- 唯一活动包:`contracts/upstream/v1/`,MQ 线上的 `schema_version` 仍为 `2.0`。 +- 当前 V1 `manifest.json` SHA-256:`d1218691ad8f63d3c7de0b652246ace690191f932a5107dbece34ccbac83bf7e`。 +- 不再维护并行契约包;当前 V1 文件经离线正反例和 AI Schema 校验后作为唯一运行输入。 - Python 生成的数值、UTF-16 属性排序和字符串黄金向量,由 Go 验证规范字节及 SHA-256 一致。 ## 验证事实 diff --git a/docs/evidence/20260921-mq-control-foundation.md b/docs/evidence/20260921-mq-control-foundation.md index 24bb042..bd9e6dc 100644 --- a/docs/evidence/20260921-mq-control-foundation.md +++ b/docs/evidence/20260921-mq-control-foundation.md @@ -34,7 +34,7 @@ ## 未完成,不能签收全流程 -- `contracts.SourceCommit`仍为v1;业务消费、事件构建、outbox路由和必要请求响应尚未整体切到v2。MQ传输测试不证明完整业务已接通。 +- `contracts.SourceCommit`固定为 `v1`;业务消费、事件构建、outbox路由和必要请求响应统一使用该 V1 包。MQ传输测试仍不证明真实外部业务已接通。 - 旧HTTP入口、CLI/环境中的旧配置选项及旧集成测试仍需清理;配置文件权威来源已接入不等于所有旧入口已删除。 - Broker连接丢失的通知已暴露,但所有准入/许可路径的停止联动还需验证。 - 上传仍待改为recording.uploaded及正确的R13完成边界;未验证通知恢复不重复PUT。 diff --git a/docs/evidence/20260921-mq-query-progress.md b/docs/evidence/20260921-mq-query-progress.md index 5d1c4c1..f3813b6 100644 --- a/docs/evidence/20260921-mq-query-progress.md +++ b/docs/evidence/20260921-mq-query-progress.md @@ -15,7 +15,7 @@ - 新增嵌入式Schema loader及编译结果复用;跨文件引用只取指定契约包,外部URL、跨版本和越界文件名被拒绝,不访问网络。 - 新服务消息使用已批准字段`message_type`,不是`message_kind`或`request_type`。 - 非法UTF-8曾被当作可重试错误;真实失败测试后改为明确的无效消息错误分类,避免反复回队。 -- 当前全局`contracts.SourceCommit`及执行/事件旧流程仍未整体切v2;新查询明确固定v2,不尝试旧协议回退。 +- 当前全局`contracts.SourceCommit`及执行/事件流程统一固定为 `v1`;新查询同样使用该唯一契约包,不尝试旧协议回退。 ## 实际测试 diff --git a/docs/evidence/20260921-mq-v2-contracts.md b/docs/evidence/20260921-mq-v1-contracts.md similarity index 80% rename from docs/evidence/20260921-mq-v2-contracts.md rename to docs/evidence/20260921-mq-v1-contracts.md index 5386c65..baac859 100644 --- a/docs/evidence/20260921-mq-v2-contracts.md +++ b/docs/evidence/20260921-mq-v1-contracts.md @@ -1,4 +1,4 @@ -# MQ-only v2:项目内契约验证 +# MQ-only V1:项目内契约验证 ## 范围与授权 @@ -9,8 +9,8 @@ ## 产物 -- 新包:`contracts/upstream/2026-09-21-p1-v2/`。 -- `scripts/publish-mq-v2.py`从只读v1来源和已确认规则生成37个被manifest固定哈希的文件;manifest另存旧源文件哈希,不依赖不存在的旧manifest。 +- 唯一活动包:`contracts/upstream/v1/`。 +- 当前 V1 包包含 50 个由 `manifest.json` 固定哈希的文件;历史发布脚本已移至归档,不作为运行输入。 - `mq.schema.json`包含4类命令、8类事件、3组必要查询/AI请求响应;没有上传会话/complete/verified往返协议。 - `event-payloads.schema.json`仅允许已确认上传事实字段,不接受SaaS OSS ID、TOKEN、密钥或签名URL。 - `dispatcher-config.schema.json`拒绝未知配置、直接密钥字段及TTL覆盖;`mq-topology.json`固定持久队列、persistent、mandatory和confirm要求。 @@ -18,7 +18,7 @@ 当前manifest SHA-256: -`6ca4582ab5f0b5550508deaa9f0b3d6e6bac579f108b423be3a7c133a207ad33` +`d1218691ad8f63d3c7de0b652246ace690191f932a5107dbece34ccbac83bf7e` ## 实际验证 @@ -28,11 +28,11 @@ | 正反例 / 离线引用解析 | 通过,测试loader拒绝网络读取 | | 所有成功消息分支 | 有实际正例,不只编译空Schema | | 非法D身份、通配词段、旧版本、额外字段、缺关联 | 拒绝 | -| 旧recording.ready及SaaS上传握手 | v2拒绝/移除 | +| 旧recording.ready及SaaS上传握手 | V1拒绝/移除 | | uploaded中的OSS ID/TOKEN/密钥/URL | 拒绝 | | 查询结果未知字段 | 先暴露旧源Command/Call未闭合问题,再关闭对象并通过反例 | | 路由模板与Go实现 | 三个topic exchange、队列/路由模板、196字节边界和900秒TOKEN合同一致 | -| manifest全部文件与旧源 | 新文件哈希通过;`git diff --exit-code 704652b -- contracts/upstream/2026-09-19-p1-v1`无差异 | +| manifest全部文件 | 当前 V1 文件哈希通过 | | `go test -race ./contracts ./internal/tenant -count=1` | 通过 | | `go vet ./...`、`go test -race ./...`、构建 | 通过,外部broker/provider/OSS集成开关显式清除 | | 格式与`git diff --check` | 通过 | @@ -41,7 +41,7 @@ ## 未覆盖/仍待实现 -- 运行时`contracts.SourceCommit`尚为v1,须在后续接线中统一切换;不能据此声称当前服务已经发送v2消息。 +- 运行时`contracts.SourceCommit`固定为 `v1`;不存在第二套运行时契约版本。 - 未实际启动本地RabbitMQ或完成D1/D2隔离、消息入队与confirm故障实验;这是后续集成门禁。 - 旧SaaS业务HTTP、旧上传完成handler及OSS ID返回路径尚待替换,不新增VERIFYING。 - 全项目覆盖率尚未达到65%;不能以局部契约/路由通过代签整体质量目标。 diff --git a/docs/plan-0918.md b/docs/plan-0918.md index 66475d4..1641b6f 100644 --- a/docs/plan-0918.md +++ b/docs/plan-0918.md @@ -22,7 +22,7 @@ 需求依据顺序: 1. 当前适用的用户确认和 [项目约束](../AGENTS.md)。已确认方向不重复索要审批;缺失字段、预算及偏离方案的变更不能自行补成“已批准”。 -2. 外部字段/路径/状态在外部权威闭包可用时来自上游版本化契约包;当前运行使用项目内只读 `contracts/upstream/2026-09-18-p1-baseline` 开发基线,并明确标注其非外部权威来源。内部接口来自项目内 `agent.v1` Proto;不能将未进入上述包的说明文字当作 Schema。 +2. 外部字段/路径/状态在外部权威闭包可用时来自上游版本化契约包;早期项目内 W01 基线已归档至 `contracts/archive/upstream/2026-09-18-p1-baseline`,当前代码只使用项目内唯一的 `contracts/upstream/v1` 契约包;未发生契约迁移前不新增或合并契约。内部接口来自项目内 `agent.v1` Proto;不能将未进入当前契约包的说明文字当作 Schema。 3. [G0确认方案](G0开发准备与契约冻结提案_v0.1.md)记录最新确认和待交付门禁;总体、通信、组件和验收文档补充实施细则。 4. 本计划只编排任务和阅读入口。若发现来源冲突,列明两个出处并暂停受影响部分;不得用计划、旧实现或 SDK 默认值覆盖权威合同。 @@ -32,8 +32,8 @@ 2. **每个 Dispatcher 有全局唯一、不重复的 ID 和独立接收 Topic/队列**。消息必须定向到指定 D,响应回原 D,来源可追溯;不能多个 D 共用一条队列竞争消费或广播后过滤。Dispatcher 身份不等于 tenant/Agent/Cell ID 或 `dispatcher_epoch`,租户独立队列与原值 `tenant_key` 仍保留。 3. 精确 ID 生成/持久化/重复身份处理、Topic/队列/绑定命名、信封关联/错误/超时以及新 routing key 的完整字节预算须由 W01 冻结;方向已经确认,但不能自行往严格旧 Schema 加字段。P1仍是单活 D,D1/D2 路由隔离只作本地契约/消息 fixture,不新增多 D 调度、HA、共享额度或生产资源。 4. **D↔A 仍为 Unary,A→OSS 仍直传**。MQ-only 不禁止 OSS/ARI/供应商 HTTP(S) 或 gRPC HTTP/2。OSS 配置由 D 配置文件提供,临时 TOKEN 由 D 向 A 提供,不再由 SaaS 下发;保留 D 签发能力。R12 提供原请求绑定的临时授权;R13 持久保存上传事实及原通知身份,并以指定队列可靠入队作为本项目完成条件。不等待 SaaS 处理,也不把本地 outbox 写入等同 MQ 入队。 -5. 旧 AI GET、控制/查询/补传 HTTP 和上传 HTTP 方案被本修订替代;`contracts/upstream/2026-09-19-p1-v1/`、旧版本、生成索引及历史证据保留原样,不能当作 MQ-only 新合同或重写哈希。相关新版本和正反例发布前,受影响 I 不就绪;禁止先实现猜测消息再补合同。 -6. 文档修订阶段已结束;当前目标已获批准实施本项目契约、代码、配置和测试,由当前Agent独立执行,不启动子Agent。已确认细节见[MQ-only v2冻结方案](contracts/mq-only-v2-freeze-proposal.md),不重开已批准方向;仍不访问真实SaaS/供应商/云/拨号,本地隔离broker可用于合同测试。文档或局部代码完成不关闭§8.2联合门禁。 +5. 旧 AI GET、控制/查询/补传 HTTP 和上传 HTTP 方案被本修订替代;`contracts/upstream/v1/` 是当前代码唯一使用的项目内 V1 合同包;未使用的旧快照和 OpenAPI 已移至 `contracts/archive/upstream/`,不能在包外另造兼容合同或绕过其哈希。未发生契约迁移前不新增或合并契约;禁止先实现猜测消息再补合同。 +6. 文档修订阶段已结束;当前目标已获批准实施本项目契约、代码、配置和测试,由当前Agent独立执行,不启动子Agent。已确认细节见[MQ-only V1冻结方案](contracts/mq-only-v1-freeze-proposal.md),不重开已批准方向;仍不访问真实SaaS/供应商/云/拨号,本地隔离broker可用于合同测试。文档或局部代码完成不关闭§8.2联合门禁。 目标语义见 R8,当前内部实现事实与差异见 R9,完整 MQ 目标时序见 R10。R1–R6 或历史证据中与本修订冲突的旧传输、路由及通过结论,不得继续作为新接入依据;只读来源包的变更必须走新版本发布。 @@ -229,7 +229,7 @@ go build ./... | 步骤 | 当前状态 | 历史证据/原基线结论(不代表新修订通过) | 当前下一动作 | | --- | --- | --- | --- | | W00 | 完成 | 已读 AGENTS、计划与 R0/R1/R3/R4/R5;工具链为 Go 1.27.1;已记录父工作区既有改动和契约源 commit。证据:`docs/evidence/20260918-local-development.json` | 维护本地基线并按 W04 证据门禁推进 | -| W01 | 完成 | 项目内 `contracts/upstream/2026-09-18-p1-baseline` 已形成自包含版本、严格事件/AI/授权/OSS/静态制品/profile Schema、8种事件正例和负例、README/SNAPSHOT/release-manifest/父清单哈希;明确继承 source dirty 且非外部权威。证据:W01 bundle、`internal/contract` 与 `internal/ai` 测试 | 发布MQ-only新契约及正反例,见§8.2;外部签收与本地冻结分开 | +| W01 | 完成 | 当前唯一 `contracts/upstream/v1` 已收敛为严格事件/AI/授权/OSS/静态制品/profile Schema、正反例、路由预算及JCS向量;早期 W01 基线仅作为归档文件。证据:V1 bundle、`internal/contract` 与 `internal/ai` 测试 | 外部签收与本地冻结分开;未发生契约迁移前不新增契约 | | W02 | 完成 | `proto/agent/v1/agent.proto`、`gen/agent/v1/*`、`proto/ERRORS.md`、manifest 已交付;`buf lint/build/generate` 和生成包测试通过,覆盖 R01–R03/R05/R07–R13,不建 R04/R06 空壳 | 核验D身份/epoch和R12/R13的MQ异步衔接,按需冻结Proto变更,见§8.2 | | W03 | 完成 | W03-a 单 module/Cobra/构建基线、W03-c 存储/MQ 本地实现、W03-e AI Schema/contract SaaS Mock PoC、W03-d Pion RTP thin adapter、gopsutil 资源采样已有测试;已完成 Go module 许可证清单、`go mod verify` 和 `govulncheck@v1.7.0`(Go 1.27.1 构建)无漏洞扫描;临时 module 的 `ari/v5.3.1`、`openai-go/v3.62.0`、`dashscopego/v0.1.2`、`doubao-speech-go` API/协议 Mock PoC 通过但均未锁入项目;固定 Asterisk 22.10.1 + 临时 ARI client runtime PoC 已通过内部 Stasis/bridge/ExternalMedia lifecycle;PJSIP/PJSUA2 full mock leg 已通过双向 PCMA、U1/U2/U3 播放、端点 WAV 封口和 ARI cleanup(证据:`docs/evidence/20260918-w09-sip-rtp-ari.md`);一次 disposable RabbitMQ 4.1.8 broker confirm/ACK/DLQ 集成通过,并新增 Dispatcher tenant consume→SQLite inbox/task/outbox→event publish integration test;另以 `TestOutboxProcessCrashRecovery` 覆盖一次真实测试子进程在 outbox claim 后退出、父进程恢复并发布的本地故障窗口(证据:`docs/evidence/20260918-w05-restart.md`);2026-09-19 另锁定物理 Asterisk 22.10.1 source/native-stage、Jansson 2.15.0、PJPROJECT 2.17 和 Debian 13 systemd 构建/安装输入,依赖补充证据见 `docs/evidence/20260918-dependencies.md`,`make check`、脚本语法和 deployment lock JSON 检查通过 | 本阶段项目内 Go/SDK/契约/隔离验证已签收;生产 ARI module/tag/许可证、供应商真实 SIP/媒体、录音 retention/OSS、批准 broker 版本/ACL、真实 broker/commit 故障注入属于第二阶段;隔离 SIPp-to-PJSIP/ARI signaling 证据见 `docs/evidence/20260918-w09-sip-ari.md`,不把本地或隔离 PoC 当生产通过 | | W04 | 完成 | W01/W02 项目内产物和 D10 隔离 PoC 已具备;本阶段项目内 G0 契约、Schema、fixture、隔离 PoC 和范围修订已签收;外部权威、真实预算/角色签收、生产依赖及生产运行证据属于第二阶段,不计入本轮门禁;汇总:`docs/evidence/20260918-g0-status.md` | 汇总新MQ合同及本地PoC,重新签收受影响G0,见§8.2 | @@ -261,7 +261,7 @@ go build ./... | 工作包 / 当前状态 | I/M/G 与下一动作 | 解除条件 | | --- | --- | --- | -| W01 / 完成 | v2/v3契约包、严格Schema/正反例、D身份/路由预算及JCS摘要通过;见`20260921-mq-v2-contracts.md`、`20260921-ai-jcs-digest.md`、`20260922-mq-only-local-final.md` | 仅外部签收仍不在本轮 | +| W01 / 完成 | 单一 V1 契约包、严格Schema/正反例、D身份/路由预算及JCS摘要通过;见`20260921-mq-v1-contracts.md`、`20260921-ai-jcs-digest.md`、`20260922-mq-only-local-final.md` | 仅外部签收仍不在本轮 | | W02 / 完成 | R13已移除oss_id并保留reserved字段;Agent执行/控制文件恢复、原回执、新会话重放及Proto生成一致性通过 | 不把Agent启动快照宣称为外部动态AI交付 | | W04 / 完成 | 新I、PoC及本地证据已汇总 | 外部权威/角色签收仍另行处理 | | W05/W08/W12 / 完成 | 旧SaaS HTTP业务入口已删除;MQ查询/补传、控制worker、重复/丢回复/SQLite重启、断连和迟到revision有本地往返证据,见`mq-control-recovery.md`、查询/补传证据及`20260922-mq-only-local-final.md` | 外部SaaS receipt不在本轮;accepted不等于applied,不重发执行当补传 | diff --git a/internal/agent/events.go b/internal/agent/events.go index 8eb8003..713c925 100644 --- a/internal/agent/events.go +++ b/internal/agent/events.go @@ -14,9 +14,10 @@ import ( // written to the Agent spool as an archive as well as returned for realtime // publication; the archive is not a substitute for transcript.updated. type EventWriter struct { - TenantID string - TenantKey string - TraceID string + DispatcherID string + TenantID string + TenantKey string + TraceID string } func (w EventWriter) TranscriptUpdated(now time.Time, eventID, callID, turnID, segmentID, role, text string, revision int64, final bool, startMS, endMS int64) ([]byte, error) { @@ -27,7 +28,7 @@ func (w EventWriter) TranscriptUpdated(now time.Time, eventID, callID, turnID, s return nil, errors.New("transcript timing or revision is invalid") } return (contract.EventBuilder{ - TenantID: w.TenantID, TenantKey: w.TenantKey, TraceID: w.TraceID, + DispatcherID: w.DispatcherID, TenantID: w.TenantID, TenantKey: w.TenantKey, TraceID: w.TraceID, EventType: "transcript.updated", Aggregate: "transcript_segment", AggregateID: segmentID, Version: revision, Payload: map[string]any{ "call_id": callID, "turn_id": turnID, "segment_id": segmentID, diff --git a/internal/agent/events_test.go b/internal/agent/events_test.go index f9856b5..91ac5b5 100644 --- a/internal/agent/events_test.go +++ b/internal/agent/events_test.go @@ -9,7 +9,7 @@ import ( ) func TestEventWriterBuildsApprovedRealtimeTranscript(t *testing.T) { - writer := EventWriter{TenantID: "tenant-1", TenantKey: "tenant-demo-key", TraceID: "trace-1"} + writer := EventWriter{DispatcherID: "11111111-1111-4111-8111-111111111111", TenantID: "tenant-1", TenantKey: "tenant-demo-key", TraceID: "trace-1"} event, err := writer.TranscriptUpdated(time.Unix(100, 0), "event-1", "call-1", "turn-1", "segment-1", "customer", "您好", 1, true, 0, 600) if err != nil { t.Fatal(err) diff --git a/internal/ai/authorization_test.go b/internal/ai/authorization_test.go index 366a9ad..6147956 100644 --- a/internal/ai/authorization_test.go +++ b/internal/ai/authorization_test.go @@ -16,7 +16,7 @@ func TestValidateAuthorizationBindsSnapshotTenantAndEgress(t *testing.T) { if err != nil { t.Fatal(err) } - authorizationRaw, err := contracts.Files.ReadFile("upstream/2026-09-21-p1-v3/examples/ai-authorization.json") + authorizationRaw, err := contracts.Files.ReadFile("upstream/v1/examples/ai-authorization.json") if err != nil { t.Fatal(err) } @@ -45,7 +45,7 @@ func TestValidateAuthorizationRejectsMismatchAndExpiry(t *testing.T) { if _, err := ValidateAuthorization(invalid, snapshot, "tenant-1", "tenant-demo-key", "egress-mock", time.Date(2026, 9, 18, 0, 0, 30, 0, time.UTC)); err == nil { t.Fatal("expected revoked authorization rejection") } - valid, err := contracts.Files.ReadFile("upstream/2026-09-21-p1-v3/examples/ai-authorization.json") + valid, err := contracts.Files.ReadFile("upstream/v1/examples/ai-authorization.json") if err != nil { t.Fatal(err) } diff --git a/internal/config/dispatcher_file.go b/internal/config/dispatcher_file.go index 4335d30..f823702 100644 --- a/internal/config/dispatcher_file.go +++ b/internal/config/dispatcher_file.go @@ -36,7 +36,7 @@ type dispatcherFile struct { var credentialEnvName = regexp.MustCompile(`^[A-Za-z_][A-Za-z0-9_]*$`) var dispatcherFileSchema = sync.OnceValues(func() (*jsonschema.Schema, error) { - data, err := contracts.Files.ReadFile("upstream/2026-09-21-p1-v2/dispatcher-config.schema.json") + data, err := contracts.Files.ReadFile("upstream/" + contracts.SourceCommit + "/dispatcher-config.schema.json") if err != nil { return nil, err } diff --git a/internal/contract/command_v2_test.go b/internal/contract/command_test.go similarity index 82% rename from internal/contract/command_v2_test.go rename to internal/contract/command_test.go index 2029d32..51792c7 100644 --- a/internal/contract/command_v2_test.go +++ b/internal/contract/command_test.go @@ -6,9 +6,9 @@ import ( "testing" ) -func TestDecodeMQCommandV2(t *testing.T) { +func TestDecodeMQCommandV1(t *testing.T) { for _, name := range []string{"call-execute", "task-control", "call-replay", "command-replay"} { - raw, err := contracts.Files.ReadFile("upstream/2026-09-21-p1-v2/examples/" + name + ".json") + raw, err := contracts.Files.ReadFile("upstream/" + MQSourceCommit + "/examples/" + name + ".json") if err != nil { t.Fatal(err) } diff --git a/internal/contract/contract.go b/internal/contract/contract.go index fb42ab5..7694561 100644 --- a/internal/contract/contract.go +++ b/internal/contract/contract.go @@ -123,38 +123,17 @@ func CloneJSON(raw []byte) json.RawMessage { } type EventBuilder struct { - TenantID string - TenantKey string - TraceID string - EventType string - Aggregate string - AggregateID string - Version int64 - Payload map[string]any + DispatcherID string + TenantID string + TenantKey string + TraceID string + EventType string + Aggregate string + AggregateID string + Version int64 + Payload map[string]any } func (b EventBuilder) Marshal(now time.Time, eventID string) ([]byte, error) { - if err := ValidateTenantKey(b.TenantKey); err != nil { - return nil, err - } - if b.Version < 1 { - return nil, errors.New("aggregate version must be positive") - } - e := EventEnvelope{ - SchemaVersion: "1.0", EventID: eventID, EventType: b.EventType, - TenantID: b.TenantID, TenantKey: b.TenantKey, TraceID: b.TraceID, - OccurredAt: now.UTC().Format(time.RFC3339Nano), AggregateType: b.Aggregate, - AggregateID: b.AggregateID, AggregateVersion: b.Version, Payload: b.Payload, - } - raw, err := json.Marshal(e) - if err != nil { - return nil, err - } - if err := ValidateJSON(raw); err != nil { - return nil, err - } - if err := ValidateEvent(raw); err != nil { - return nil, err - } - return raw, nil + return b.MarshalMQ(b.DispatcherID, now, eventID) } diff --git a/internal/contract/contract_test.go b/internal/contract/contract_test.go index 8a84de9..2385827 100644 --- a/internal/contract/contract_test.go +++ b/internal/contract/contract_test.go @@ -40,7 +40,7 @@ func TestEventFixtures(t *testing.T) { "examples/event-call-status.json", "examples/event-transcript-updated.json", "examples/event-call-finished.json", - "examples/event-recording-ready.json", + "examples/event-recording-uploaded.json", "examples/event-recording-failed.json", "examples/event-transcript-failed.json", "examples/event-contact-opt-out.json", @@ -54,7 +54,7 @@ func TestEventFixtures(t *testing.T) { t.Fatalf("%s: %v", name, err) } } - invalid, err := contracts.Read("examples/invalid-event-unknown-type.json") + invalid, err := contracts.Read("examples/invalid-v1.json") if err != nil { t.Fatal(err) } @@ -114,7 +114,8 @@ func schemaNameForFixture(name string) string { func TestEventBuilder(t *testing.T) { raw, err := (EventBuilder{ - TenantID: "tenant-1", TenantKey: "tenant-1", TraceID: "trace-1", + DispatcherID: "11111111-1111-4111-8111-111111111111", + TenantID: "tenant-1", TenantKey: "tenant-1", TraceID: "trace-1", EventType: "command.result", Aggregate: "command", AggregateID: "cmd-1", Version: 1, Payload: map[string]any{ "command_id": "cmd-1", "command_type": "call.execute", diff --git a/internal/contract/event_mq.go b/internal/contract/event_mq.go index 7f05dd4..7e4ca98 100644 --- a/internal/contract/event_mq.go +++ b/internal/contract/event_mq.go @@ -2,12 +2,19 @@ package contract import ( "encoding/json" + "fmt" "time" ) // MarshalMQ constructs the Dispatcher-owned external event envelope. Internal // Agent event frames do not supply the Dispatcher identity or select a version. func (b EventBuilder) MarshalMQ(dispatcherID string, now time.Time, eventID string) ([]byte, error) { + if err := ValidateTenantKey(b.TenantKey); err != nil { + return nil, err + } + if b.Version < 1 { + return nil, fmt.Errorf("aggregate version must be positive") + } envelope := struct { EventEnvelope DispatcherID string `json:"dispatcher_id"` @@ -24,5 +31,8 @@ func (b EventBuilder) MarshalMQ(dispatcherID string, now time.Time, eventID stri if err := ValidateMQMessage(raw); err != nil { return nil, err } + if err := ValidateEvent(raw); err != nil { + return nil, err + } return raw, nil } diff --git a/internal/contract/schema_source_test.go b/internal/contract/schema_source_test.go index e0a6335..dc20332 100644 --- a/internal/contract/schema_source_test.go +++ b/internal/contract/schema_source_test.go @@ -11,7 +11,6 @@ func TestContractBundleIsReadable(t *testing.T) { "mq.schema.json", "event-payloads.schema.json", "ai-config.schema.json", "ai-authorization.schema.json", "oss-upload.schema.json", "static-cell-artifact.schema.json", "p1-development-profile.schema.json", - "executor.openapi.yaml", "saas.openapi.yaml", "cell-agent.openapi.yaml", } { data, err := contracts.Read(name) if err != nil { diff --git a/internal/contract/schema_test.go b/internal/contract/schema_test.go index 9993de5..146180b 100644 --- a/internal/contract/schema_test.go +++ b/internal/contract/schema_test.go @@ -8,8 +8,8 @@ import ( "github.com/santhosh-tekuri/jsonschema/v6" ) -func TestV2RuntimeSchemaResolvesOnlyEmbeddedContracts(t *testing.T) { - const version = "2026-09-21-p1-v2" +func TestV1RuntimeSchemaResolvesOnlyEmbeddedContracts(t *testing.T) { + const version = contracts.SourceCommit schema, err := schemaFromBundle(version, "mq.schema.json") if err != nil { t.Fatal(err) @@ -28,7 +28,7 @@ func TestV2RuntimeSchemaResolvesOnlyEmbeddedContracts(t *testing.T) { } } loader := bundleLoader{version: version} - for _, address := range []string{"https://example.invalid/mq.schema.json", "file:///etc/passwd", "https://go-sip.local/contracts/2026-09-19-p1-v1/mq.schema.json"} { + for _, address := range []string{"https://example.invalid/mq.schema.json", "file:///etc/passwd", "https://go-sip.local/contracts/other/mq.schema.json"} { if _, err := loader.Load(address); err == nil { t.Fatalf("external/cross-version schema accepted: %s", address) } diff --git a/internal/contract/service.go b/internal/contract/service.go index 03234f4..9a0d188 100644 --- a/internal/contract/service.go +++ b/internal/contract/service.go @@ -7,12 +7,13 @@ import ( "fmt" "unicode/utf8" + "git.ipao.vip/rogee/go-sip/contracts" "github.com/santhosh-tekuri/jsonschema/v6" ) // MQSourceCommit pins the approved MQ protocol. No incoming version selects a // different decoder or causes fallback to the previous protocol. -const MQSourceCommit = "2026-09-21-p1-v3" +const MQSourceCommit = contracts.SourceCommit var ErrInvalidServiceMessage = errors.New("invalid MQ service message") diff --git a/internal/contract/service_test.go b/internal/contract/service_test.go index c2ae776..23e8ad8 100644 --- a/internal/contract/service_test.go +++ b/internal/contract/service_test.go @@ -9,7 +9,7 @@ import ( func TestDecodeServiceUsesApprovedMessageTypeAndCorrelation(t *testing.T) { for _, name := range []string{"command-query", "call-query", "ai-config-request", "command-query-result", "call-query-result", "ai-config-result"} { - raw, err := contracts.Files.ReadFile("upstream/2026-09-21-p1-v2/examples/" + name + ".json") + raw, err := contracts.Files.ReadFile("upstream/v1/examples/" + name + ".json") if err != nil { t.Fatal(err) } diff --git a/internal/dispatcher/consumer_test.go b/internal/dispatcher/consumer_test.go index a5a4017..8e0ea93 100644 --- a/internal/dispatcher/consumer_test.go +++ b/internal/dispatcher/consumer_test.go @@ -28,7 +28,7 @@ func TestMQCommandQueryPersistsBeforeAcceptance(t *testing.T) { if err != nil { t.Fatal(err) } - raw, err := contracts.Files.ReadFile("upstream/2026-09-21-p1-v2/examples/command-query.json") + raw, err := contracts.Files.ReadFile("upstream/v1/examples/command-query.json") if err != nil { t.Fatal(err) } @@ -77,7 +77,7 @@ func TestMQReplayPersistsDecisionBeforeAcknowledgment(t *testing.T) { if err != nil { t.Fatal(err) } - raw, err := contracts.Files.ReadFile("upstream/2026-09-21-p1-v2/examples/" + name + ".json") + raw, err := contracts.Files.ReadFile("upstream/v1/examples/" + name + ".json") if err != nil { t.Fatal(err) } @@ -126,7 +126,7 @@ func TestMQCallQueryPersistsResponse(t *testing.T) { if err != nil { t.Fatal(err) } - raw, err := contracts.Files.ReadFile("upstream/2026-09-21-p1-v2/examples/call-query.json") + raw, err := contracts.Files.ReadFile("upstream/v1/examples/call-query.json") if err != nil { t.Fatal(err) } @@ -157,7 +157,7 @@ func TestMQCallQueryPersistsResponse(t *testing.T) { } func TestInvalidServiceEncodingIsPermanent(t *testing.T) { - raw, err := contracts.Files.ReadFile("upstream/2026-09-21-p1-v2/examples/command-query.json") + raw, err := contracts.Files.ReadFile("upstream/v1/examples/command-query.json") if err != nil { t.Fatal(err) } diff --git a/internal/dispatcher/local_flow_test.go b/internal/dispatcher/local_flow_test.go index 5974336..1301ed3 100644 --- a/internal/dispatcher/local_flow_test.go +++ b/internal/dispatcher/local_flow_test.go @@ -44,7 +44,7 @@ func TestLocalContractBackedFlowEvidence(t *testing.T) { if err != nil { t.Fatal(err) } - authorizationRaw, err := contracts.Files.ReadFile("upstream/2026-09-21-p1-v3/examples/ai-authorization.json") + authorizationRaw, err := contracts.Files.ReadFile("upstream/v1/examples/ai-authorization.json") if err != nil { t.Fatal(err) } @@ -133,7 +133,7 @@ func TestLocalContractBackedFlowEvidence(t *testing.T) { t.Fatalf("control result: %+v %v", controlled, err) } - event, err := (agent.EventWriter{TenantID: "tenant-1", TenantKey: "tenant-demo-key", TraceID: "trace-local"}).TranscriptUpdated(now, "event-local", "call-local", "turn-local", "segment-local", "customer", "hello", 1, true, 0, 100) + event, err := (agent.EventWriter{DispatcherID: testfixture.DispatcherID, TenantID: "tenant-1", TenantKey: "tenant-demo-key", TraceID: "trace-local"}).TranscriptUpdated(now, "event-local", "call-local", "turn-local", "segment-local", "customer", "hello", 1, true, 0, 100) if err != nil { t.Fatal(err) } diff --git a/internal/dispatcher/query_mq_integration_test.go b/internal/dispatcher/query_mq_integration_test.go index 72df560..6d3df92 100644 --- a/internal/dispatcher/query_mq_integration_test.go +++ b/internal/dispatcher/query_mq_integration_test.go @@ -76,7 +76,7 @@ func runLocalMQRequest(t *testing.T, address, fixture string) { if err := channel.Confirm(false); err != nil { t.Fatal(err) } - raw, err := contracts.Files.ReadFile("upstream/2026-09-21-p1-v2/examples/" + fixture + ".json") + raw, err := contracts.Files.ReadFile("upstream/v1/examples/" + fixture + ".json") if err != nil { t.Fatal(err) } @@ -216,7 +216,7 @@ func runLocalMQRequest(t *testing.T, address, fixture string) { func seedReplayMQFact(t *testing.T, s *store.Store, id, key, routingKey string) []byte { t.Helper() - raw, err := contracts.Files.ReadFile("upstream/2026-09-21-p1-v2/examples/call-execute.json") + raw, err := contracts.Files.ReadFile("upstream/v1/examples/call-execute.json") if err != nil { t.Fatal(err) } @@ -233,7 +233,7 @@ func seedReplayMQFact(t *testing.T, s *store.Store, id, key, routingKey string) if _, err := s.DB().Exec(`INSERT INTO inbox(tenant_id,command_id,tenant_key,command_type,body_hash,body,status,received_at) VALUES('tenant-a','command-a',?,'call.execute','fixture',?,'persisted','2026-09-21T00:00:00Z')`, key, raw); err != nil { t.Fatal(err) } - raw, err = contracts.Files.ReadFile("upstream/2026-09-21-p1-v2/examples/event-call-status.json") + raw, err = contracts.Files.ReadFile("upstream/v1/examples/event-call-status.json") if err != nil { t.Fatal(err) } diff --git a/internal/rpc/ai_authorization_test.go b/internal/rpc/ai_authorization_test.go index 0ef9d79..bc9e910 100644 --- a/internal/rpc/ai_authorization_test.go +++ b/internal/rpc/ai_authorization_test.go @@ -23,7 +23,7 @@ func TestExecutionPermitEnforcesAIAuthorization(t *testing.T) { if err != nil { t.Fatal(err) } - authorizationRaw, err := contracts.Files.ReadFile("upstream/2026-09-21-p1-v3/examples/ai-authorization.json") + authorizationRaw, err := contracts.Files.ReadFile("upstream/v1/examples/ai-authorization.json") if err != nil { t.Fatal(err) } diff --git a/internal/store/call_query_test.go b/internal/store/call_query_test.go index bd80e19..cfccd0c 100644 --- a/internal/store/call_query_test.go +++ b/internal/store/call_query_test.go @@ -26,7 +26,7 @@ func TestCallQueryCollectsOnlyBoundRecordedFacts(t *testing.T) { t.Fatal(err) } for _, name := range []string{"call-status", "transcript-updated", "recording-uploaded"} { - raw, err := contracts.Files.ReadFile("upstream/2026-09-21-p1-v2/examples/event-" + name + ".json") + raw, err := contracts.Files.ReadFile("upstream/v1/examples/event-" + name + ".json") if err != nil { t.Fatal(err) } @@ -38,7 +38,7 @@ func TestCallQueryCollectsOnlyBoundRecordedFacts(t *testing.T) { t.Fatal(err) } } - raw, err := contracts.Files.ReadFile("upstream/2026-09-21-p1-v2/examples/call-query.json") + raw, err := contracts.Files.ReadFile("upstream/v1/examples/call-query.json") if err != nil { t.Fatal(err) } @@ -71,7 +71,7 @@ func TestCallQueryCollectsOnlyBoundRecordedFacts(t *testing.T) { if response.MessageType != "call.query.result" || response.Status != "ok" || snapshot.CallID != "call-a" || snapshot.State != "answered" || snapshot.Version != 1 || len(snapshot.Attempts) != 1 || len(snapshot.Transcript.Events) != 1 || len(snapshot.Recordings) != 1 || snapshot.Delivery["pending"] != 3 { t.Fatalf("wrong snapshot: %+v", snapshot) } - largeRaw, err := contracts.Files.ReadFile("upstream/2026-09-21-p1-v2/examples/event-transcript-updated.json") + largeRaw, err := contracts.Files.ReadFile("upstream/v1/examples/event-transcript-updated.json") if err != nil { t.Fatal(err) } diff --git a/internal/store/execute_mq_test.go b/internal/store/execute_mq_test.go index db69e0f..0145855 100644 --- a/internal/store/execute_mq_test.go +++ b/internal/store/execute_mq_test.go @@ -20,7 +20,7 @@ func TestExecuteMQPersistsScopedV2Receipt(t *testing.T) { if err := s.BindDispatcherID(identityA); err != nil { t.Fatal(err) } - raw, err := contracts.Files.ReadFile("upstream/2026-09-21-p1-v2/examples/call-execute.json") + raw, err := contracts.Files.ReadFile("upstream/v1/examples/call-execute.json") if err != nil { t.Fatal(err) } diff --git a/internal/store/query_test.go b/internal/store/query_test.go index f2e1727..a58e08e 100644 --- a/internal/store/query_test.go +++ b/internal/store/query_test.go @@ -22,7 +22,7 @@ func TestCommandQueryUsesRecordedAggregateVersion(t *testing.T) { t.Fatal(err) } s.now = func() time.Time { return time.Date(2026, 9, 21, 0, 0, 1, 0, time.UTC) } - raw, err := contracts.Files.ReadFile("upstream/2026-09-21-p1-v2/examples/command-query.json") + raw, err := contracts.Files.ReadFile("upstream/v1/examples/command-query.json") if err != nil { t.Fatal(err) } @@ -39,7 +39,7 @@ func TestCommandQueryUsesRecordedAggregateVersion(t *testing.T) { if _, err := s.DB().Exec(`INSERT INTO inbox(tenant_id,command_id,tenant_key,command_type,body_hash,body,status,received_at,persisted_at) VALUES(?,?,?,'call.execute','fixture','{}','persisted',?,?)`, request.TenantID, target.CommandID, request.TenantKey, request.IssuedAt, request.IssuedAt); err != nil { t.Fatal(err) } - eventRaw, err := contracts.Files.ReadFile("upstream/2026-09-21-p1-v2/examples/event-command-result.json") + eventRaw, err := contracts.Files.ReadFile("upstream/v1/examples/event-command-result.json") if err != nil { t.Fatal(err) } @@ -111,7 +111,7 @@ func TestCommandQueryRecoveryAndAtomicFailure(t *testing.T) { t.Fatal(err) } s.now = func() time.Time { return time.Date(2026, 9, 21, 0, 0, 1, 0, time.UTC) } - raw, err := contracts.Files.ReadFile("upstream/2026-09-21-p1-v2/examples/command-query.json") + raw, err := contracts.Files.ReadFile("upstream/v1/examples/command-query.json") if err != nil { t.Fatal(err) } @@ -188,7 +188,7 @@ func TestCommandQueryPersistsOneCorrelatedResponse(t *testing.T) { t.Fatal(err) } s.now = func() time.Time { return time.Date(2026, 9, 21, 0, 0, 1, 0, time.UTC) } - raw, err := contracts.Files.ReadFile("upstream/2026-09-21-p1-v2/examples/command-query.json") + raw, err := contracts.Files.ReadFile("upstream/v1/examples/command-query.json") if err != nil { t.Fatal(err) } diff --git a/internal/store/replay_mq_test.go b/internal/store/replay_mq_test.go index 6357b4c..42d9c57 100644 --- a/internal/store/replay_mq_test.go +++ b/internal/store/replay_mq_test.go @@ -27,7 +27,7 @@ func TestMQReplayOnlyRequeuesOriginalBusinessFacts(t *testing.T) { if err != nil { t.Fatal(err) } - original, err := contracts.Files.ReadFile("upstream/2026-09-21-p1-v2/examples/call-execute.json") + original, err := contracts.Files.ReadFile("upstream/v1/examples/call-execute.json") if err != nil { t.Fatal(err) } @@ -46,7 +46,7 @@ func TestMQReplayOnlyRequeuesOriginalBusinessFacts(t *testing.T) { } before := map[string]string{} for _, name := range []string{"call-status", "transcript-updated", "recording-uploaded"} { - raw, err := contracts.Files.ReadFile("upstream/2026-09-21-p1-v2/examples/event-" + name + ".json") + raw, err := contracts.Files.ReadFile("upstream/v1/examples/event-" + name + ".json") if err != nil { t.Fatal(err) } @@ -60,7 +60,7 @@ func TestMQReplayOnlyRequeuesOriginalBusinessFacts(t *testing.T) { t.Fatal(err) } } - raw, err := contracts.Files.ReadFile("upstream/2026-09-21-p1-v2/examples/" + kind + ".json") + raw, err := contracts.Files.ReadFile("upstream/v1/examples/" + kind + ".json") if err != nil { t.Fatal(err) } diff --git a/internal/store/upload_notification_test.go b/internal/store/upload_notification_test.go index 7e6cbe6..ba45d5e 100644 --- a/internal/store/upload_notification_test.go +++ b/internal/store/upload_notification_test.go @@ -21,7 +21,7 @@ func TestUploadCompletionRequiresPublishedOriginalNotice(t *testing.T) { if err := s.InsertUpload(UploadRecord{UploadID: "upload-a", Binding: []byte("binding"), Asset: []byte("asset"), Grant: []byte("grant"), ObjectKey: "recordings/recording-a.wav", Bucket: "example-bucket", State: "granted", CreatedAt: now}); err != nil { t.Fatal(err) } - raw, err := contracts.Files.ReadFile("upstream/2026-09-21-p1-v2/examples/event-recording-uploaded.json") + raw, err := contracts.Files.ReadFile("upstream/v1/examples/event-recording-uploaded.json") if err != nil { t.Fatal(err) } diff --git a/internal/testfixture/execute.go b/internal/testfixture/execute.go index 82eb6a5..87e76cd 100644 --- a/internal/testfixture/execute.go +++ b/internal/testfixture/execute.go @@ -9,11 +9,10 @@ import ( const DispatcherID = "c046b893-8628-4589-ae50-619d049248a6" -// Execute preserves the established business identifiers used by scheduler -// tests while supplying the current external envelope. Historical bundles are -// read unchanged; no production decoder accepts their old MQ envelope. +// Execute supplies the current V1 external envelope with the stable identifiers +// used by scheduler tests. func Execute() ([]byte, error) { - raw, err := contracts.Read("examples/call.execute.json") + raw, err := contracts.Read("examples/call-execute.json") if err != nil { return nil, err } @@ -23,6 +22,20 @@ func Execute() ([]byte, error) { } envelope["schema_version"] = "2.0" envelope["dispatcher_id"] = DispatcherID + envelope["tenant_id"] = "tenant-demo" + envelope["tenant_key"] = "tenant-demo-key" + envelope["issued_at"] = "2026-09-11T08:00:00Z" + envelope["not_after"] = "2099-09-11T08:05:00Z" + payload := envelope["payload"].(map[string]any) + payload["execution_id"] = "exec_demo_001" + payload["task_id"] = "task-demo" + payload["task_item_id"] = "item_demo_001" + payload["callee"] = "18601013734" + payload["route_policy_id"] = "route_policy_test" + payload["caller_profile_id"] = "caller_profile_test" + payload["agent_version_id"] = "agent_v1" + payload["ring_timeout_ms"] = float64(30000) + payload["max_call_duration_ms"] = float64(180000) return json.MarshalIndent(envelope, "", " ") } diff --git a/scripts/publish-mq-v2.py b/scripts/archive/publish-mq-v2.py similarity index 100% rename from scripts/publish-mq-v2.py rename to scripts/archive/publish-mq-v2.py diff --git a/scripts/publish-mq-v3.py b/scripts/archive/publish-mq-v3.py similarity index 100% rename from scripts/publish-mq-v3.py rename to scripts/archive/publish-mq-v3.py