历史 · ADR-028:Contracts First 与 Core 准入纵切
重构前档案,仅供追溯,不作为新版本执行指令
历史档案 · 2026-09-11 重构前快照。 本文中的“当前”“已冻结”和实施顺序属于旧基线。新版本以现行总览和实施计划为准。
| 属性 | 内容 |
|---|---|
| 状态 | 已采用,首个实现基线已通过独立 CI 验收 |
| 决策日期 | 2026-09-03 |
| 适用范围 | oceanway-contracts、oceanway-core 以及随后接入的 API Edge、Surface 与 Gateway |
| 前置决策 | OW-ADR-006、011–015、019、022–027 |
背景
十四仓边界建立后,最大的风险不是仓库数量,而是各产品并行开发出不同的身份、模型、Run、资产和钱包语义。如果先迁页面、再补共享契约,Studio、Console、API Edge、Drama 和 Commerce 会各自形成临时事实源;后续即使 UI 看起来统一,调度、计费和追溯仍无法闭环。
因此下一阶段不以“先完成某个页面”为目标,而以一条可执行、可回滚、可诊断的最小业务纵切作为系统骨架。
决策
1. Contracts 必须先于运行仓发布
oceanway-contracts 是跨仓 wire contract 的唯一来源。运行仓只能依赖固定 Release 版本,不允许使用 Git 分支、本地相对路径、复制 TypeScript 文件或跨仓源码导入。
首发基线至少包含:
- opaque/branded 稳定 ID;
- Request Context、Tenant Context 和 Developer Access Context;
- credits、entitlement 与真实 ISO money 的判别联合;
- Asset Version 引用;
- Model Offering 公共投影与 Model Execution Target 内部投影;
- Agent Revision 与 MCP Grant 引用;
- Run Admission、Execution Manifest 和 Run 事件;
- Text/Media Gateway 的提交、观测、不可变
ProviderUsageEvidence/ProviderCostEvidence引用与安全错误; - Canonical Event Envelope;
- 由运行时 Schema 自动生成的 JSON Schema 制品。
所有 wire object 首版采用严格字段校验。因此给既有对象增加字段也按不兼容变更处理;兼容性扩展优先新增独立 Schema 或新的事件版本。不能一边拒绝未知字段,一边把“新增可选字段”声明为 minor 兼容。
1.1 Contracts 依赖必须绑定私有 Registry 与同一发布制品
- GitHub Packages 中的 Contracts 包只向明确授权的消费仓开放;
oceanway-core的 GitHub Actions 获得 Read 权限。 - Core 的首个历史基线使用 pnpm 的
gh:registry-qualified dependency 锁定@oceanway-ai/contracts@0.1.0;后续受控 API 准入验收固定使用@oceanway-ai/contracts@0.2.0。任何阶段都不能因 Registry 配置异常解析到同名公共包。 - pnpm 的
minimumReleaseAge例外只允许当前明确固定的 Contracts 精确版本,不对整个组织 Scope 或浮动版本放宽供应链门禁;0.1.0 是首个历史例外,0.2.0 是当前受控准入制品。 - Contracts Release Workflow 先生成唯一 tgz,再用同一个文件发布 GitHub Package 和 GitHub Release;不得分别重建两个制品。
- Contracts 新增制品比对 Workflow,按版本下载 Registry 与 Release tgz、校验摘要并递归比较解包内容。该 Workflow 是发布验收门禁;
0.2.0已由 Verify Run33756418040正式通过,不能据此倒推所有历史制品都已自动验证。
2. 模型公开面在导入边界隔离
web、api、internal 是发布目标,unpublished 是发布状态而不是第四个 Surface。公共 Model Offering 与内部 Model Execution Target 使用不同导出入口:
- Site、Developer Center、Console 和产品 UI 只能导入公共模型目录契约;
- Core 与 Gateway 可以导入内部执行目标契约;
codex-auto-review、规划模型、自动评测模型和 Provider 绑定没有对应公开 Offering 时,无法进入网页或公共 API 目录。
这项限制必须由包导出和 CI 验证,不能只依赖页面过滤。
3. Core 保持模块化单体
首期 Core 在一个仓库和一个 PostgreSQL 事务边界内实现以下模块:Identity、Tenancy、Authorization、Developer Access、Resource Registry、Asset、Execution、Metering、Billing、Agent、MCP、Model Control、Operations 与 Audit。
模块拥有各自的聚合、Repository、表和事件。Agent 只拥有 Agent Definition、Revision 与 Deployment;Run、Step、Attempt、Execution Manifest 和 Output 只由 Execution 拥有。Provider Credential Version、物理 Channel/Supply 和 Provider Task 保持 Gateway 私有。
Canvas Runtime 延后到 Phase 4;当前 Contracts/Core 基线不提前冻结 Canvas 节点协议。
4. 首个纵切采用 Run Admission
首个可执行纵切固定为 API Surface 的 Run Admission:
上述动作、幂等结果与 Outbox 必须在一个 PostgreSQL 事务中提交。projectId 可选,billingAccountId 必填并由服务端验证;首版只接受 credits,不能把积分伪装成货币,也不能把 credits、entitlement 和 money 相加。
Run 级 Execution Manifest 冻结创建时的 Actor、Execution Principal、租户、付款账户、认证上下文、授权决策、Offering Revision、initial Execution Target、Routing Policy Revision、Reservation、pricingSnapshotId、关联 ID 和数据分类。本文将它的语义角色称为 RunAdmissionManifest;已发布 Contracts 的 ExecutionManifest 已是 Run-level 基线,不能误塞 runStepId、executionAttemptId 或具体 Gateway 路由。Developer Access 链由准入事务校验,不在 Manifest 中复制另一份可变资源投影。Manifest 创建后不可修改;执行变化通过 Run/Step/Attempt、每次 Attempt 的独立 AttemptExecutionManifest 和事件表达。
Canonical Event Envelope 固定使用 aggregateId 与正整数 aggregateRevision,并携带 eventId、eventType、schemaVersion、occurredAt、producer、actorPrincipalId、Organization、Workspace、可选 Project、correlationId、可选 operationId、causationId、traceId 和 payload;其中 causationId 与 traceId 按事实可选。不得恢复含义模糊的 subjectId 或缩写 orgId。
5. 本纵切明确不执行外部副作用
当前基线只完成准入与预占,不调用 Text/Media Gateway、Provider、Agent、MCP 或 Asset 写入,也不开放客户写 API。这样可以先验证租户、授权、模型发布面、账务与幂等不变量,而不制造未知提交或重复生成。
实施快照
@oceanway-ai/contracts@0.1.0已作为首个固定版本发布;包根只暴露公共安全契约,公共模型目录使用public/model-catalog,执行、模型控制和网关契约使用internal/*子路径。oceanway-core已在 Commit77f336a形成 PostgreSQL Run Admission 功能基线,包含模块所有权清单、数据库迁移、单事务准入、数据库不变量与真实 PostgreSQL 集成测试;本地已通过 5 项单元测试、14 项专用 PostgreSQL 集成测试、类型检查、构建、依赖审计以及/livez、/readyz启动验证。- Core 随后的
4d66b6c已锁定私有 Contracts 依赖,并由 独立 CI Run 33745852471 通过格式、类型、单元测试、构建、专用 PostgreSQL 集成测试和生产依赖审计。 - 上述
0.1.0与 Core Commit 是 2026-09-03 的首个历史验收基线。后续受控 API 准入已固定到@oceanway-ai/contracts@0.2.0(Commitce323954;CI33756169615;Release33756329273;Verify33756418040;tgz SHA-256731b9a54d846a7fb8714ba651d41d466abfa2b2b98a4f1466eedb0287e0a23c4)、Coref9e55b6(CI33777925718)和 API Edgef97cf5f(CI33774539995)。 - Infrastructure
e72e5f3已收录 Gate9cc3c9c产生的正式跨服务证据controlled-admission-e2e-9cc3c9c49b16-f9e55b6e56e4-f97cf5f27027.json。该证据验证真实 Release tgz、HTTPS JWKS、RS256 Workload JWT、Edge/Core Socket HTTP 与隔离 PostgreSQL 下的默认关闭和受控准入链路。 - 首个 Contracts-first/Core Run Admission 与后续 API Edge 受控接入据此均已验收;这不代表生产部署或公网开放,也不包含 Gateway 执行与输出、Outbox 发布、Metering 或 Settlement。
上述已发布 ExecutionManifest 与准入证据是 Organization-backed 的 Run 级历史基线,不能因目标文档引入 tenantKind / tenantId、modelRoutingPolicyRevisionId、Attempt Manifest 或 Route Binding 而被追溯改写。目标字段必须进入新的固定 Contracts 版本并通过 Producer/Consumer 兼容门禁;Personal Space API Admission 在 tenant-aware Manifest、Run Event、Wallet Event 与授权门禁共同发布前保持禁用。
Writer 与迁移规则
在某类命令切换前,oceanway-vozeb 仍可以是旧事实 Owner。接入新 Core 时只允许两种模式:
- 旧入口代理到 Core,Core 是唯一 Writer;
- 旧实现继续写,Core 只做不产生事实和费用的 Shadow Read/校验。
禁止旧、新实现同时创建 Run、Reservation、Ledger Entry、Asset 或 Provider Task。回滚只改变后续新命令的路由;已经受理的 Operation 由原 Owner 处理到终态或进入 Reconciliation。
准入事务基线验证门禁
本决策的准入事务基线需要同时通过:
- Contracts 的运行时校验、TypeScript Node/Web 消费测试、JSON Schema 漂移检查、打包检查和依赖审计;
- 公共模型导出无法导入内部 Execution Target 的负向测试;
- Core 模块聚合唯一所有权测试;
- 专用
_testPostgreSQL 上的真实事务测试,且关闭文件级并行; - 并发同幂等键只产生一个 Run 和一份 Reservation;
- 相同幂等键不同语义被拒绝;
- 跨租户、无授权、余额不足或中途约束失败时没有部分写入;
- Manifest 数据库级不可修改;
- Run 读取受 Organization、Workspace 和可选 Project 限制;
- Outbox 与业务事实在同一事务创建,并携带所需 Operation/Correlation/Trace 关联;Outbox Publisher 的外部发布、消费回执和运维读模型属于下一阶段;
- 包、Tag、Changelog、Commit 和 CI 结果可追溯。
上述准入基线现已由 Contracts、Core、API Edge 独立 CI 和 Infrastructure 受控跨服务证据完成验收。完整 Request Attempt、Error Occurrence、事件发布与消费链路不由本 ADR 的已完成状态代替,当前由 Outbox Publisher 与 Ops Explorer 阶段继续实现。
后续顺序
本纵切完成后按下列顺序推进,不同时展开全部产品迁移:
- API Edge 适配(受控门禁已完成):终止 DeveloperCredential,构造受信 Request Context,调用 Core;API Edge 不保存第二份 Run、余额或模型事实。运行时仍默认禁用 Admission,尚未开放公网。
- Outbox Publisher 与 Ops Explorer(当前阶段):依照 ADR-030 以 PostgreSQL-first Dispatcher 可靠投递事务事件,建立 Operation/Run/Reservation 查询投影,为 Admin 的只读 Run Explorer 提供第一条真实数据链;当前仅完成文档基线,代码与验收待实施。
- Metering 与结算:令 Gateway 只追加不可变
ProviderUsageEvidence/ProviderCostEvidence与 source ref,由 Metering 唯一创建规范MeterEvent/ProviderCostFact、处理幂等/更正/对账;Billing 按版本化 Eligibility 和合格 MeterEvent 计算目标净额,只有BillingFinalizationDecision封闭完整 Attempt×Charge Dimension 集合后才结算或释放,未知/冲突进入对账,ProviderCostFact 不单独触发客户账务;Operational Observation 不能驱动结算。 - Text Gateway canary:使用固定 Gateway Contract 接通一条文本执行链;Media 按同级接口随后接入,不做同 Attempt 双投。
- Asset Output:将成功结果登记为 Asset Version 并保留 Run/Attempt/Blob lineage。
- Surface 迁移:先迁 Console
/ai的一个最小调用链,再迁 Studio;旧实现逐命令切换 Writer,始终禁止业务双写。
Canvas Runtime、完整 Agent/MCP 组合、Drama、Commerce 和 FDE 私有交付在上述链路通过后进入各自阶段。
影响
收益是所有平台从第一条调用开始就共享同一租户、付款方、模型发布面、Run 和追踪语义,且 Admin 能基于真实事件建设诊断能力。代价是首个可见页面功能会稍晚,但可以避免后续为多套钱包、模型目录和任务表做高风险合并。