# 11 · 接口与契约总册 > 全系统的边界接口清单 + 规范业务对象契约 + TypeScript↔Python 跨语言契约策略。 > 各篇的 YAML 片段是示意,本篇是接口的**权威索引**;字段级定义在代码仓 `packages/domain` 中。 ## 1. 接口清单(按边界分类) ### 1.1 平面间端口(进程内 / 内部服务,TS interface) 借用同行评审(brainstorming.md §6)的端口风格——每个端口是一条信任边界的收口: ```ts // 认知平面 → 可信执行链:唯一提交入口 interface ProposalSubmissionPort { submit(proposal: Proposal): Promise<{ caseId: CaseId; lifecycleRunId: RunId }> } // 可信执行链内部依赖(确定性服务,不暴露给 LLM) interface PolicyEnginePort { check(proposal: Proposal, pack: PolicyPackRef): Promise } interface SimulationPort { simulate(proposal: Proposal): Promise } interface EnvelopePort { match(proposal: Proposal): Promise // 包络命中与边界检查 } // 授权环节:现势复核 + 许可签发(03 篇 §2.2,I4) interface AuthorityPort { authorize(p: Proposal, approvals: Approval[]): Promise revoke(permitId: PermitId, reason: string): Promise } // 网关:只认 (Proposal, Permit) 对 interface GatewayPort { dispatch(p: Proposal, permit: ExecutionPermit): Promise } // 共享账本与证据 interface LedgerPort { read(scope: LedgerScope): Promise // 带版本号(乐观并发) append(update: PositionUpdate): Promise } interface EvidencePort { record(evt: DomainEvent): Promise // 事件溯源写入口 } // 运营工单台(02 篇 §5) interface CaseDeskPort { open(kind: CaseKind, input: CaseInput): Promise read(caseId: CaseId): Promise apply(cmd: CaseCommand): Promise // 审批、叉分情景、关单… watch(caseId: CaseId): AsyncIterable } ``` ### 1.2 服务间接口(跨进程 / 跨语言) | 接口 | 双方 | 协议 | 契约来源 | |---|---|---|---| | Skill 调用 | TS Runtime → Python Skill 服务 | HTTP/JSON(FastAPI) | domain 导出的 JSON Schema(见 §3) | | 审批/工单 API | 前端/工单台 → Runtime | HTTP/JSON | 同上 | | 决策案 API(外部系统) | 外部系统 → 平台 | HTTP/JSON,`start/act/observe` 三操作(同行方案 A) | 二期再开放,一期仅内部 | | 联邦网关 | 省级平台 ↔ 他省 | 签名工件交换(10 篇) | FlexibilityEnvelope 等工件 schema | | 外部适配器 | 平台 ↔ 交易平台/调度/计量 | 对方规定(文件/WebService/消息) | 防腐层内转换(06 篇),原始报文留痕 | | 边缘控制链路 | 执行引擎 ↔ 边缘终端 | 国网标准协议栈(IEC 104 / MQTT + 国密等,按现场定) | **不属于** JSON 契约域;计划/包络的语义仍来自 domain 对象 | ### 1.3 事件契约 事件总线上的每类事件 = 一个 domain 对象 + 信封: ```ts interface EventEnvelope { eventType: string; schemaVersion: string // 语义化版本 occurredAt: string // ISO8601 UTC causationId: string; correlationId: string // 因果链(复盘/审计遍历用) payload: T } ``` ## 2. 规范业务对象总表 合并本文档集与同行评审 §12 的清单,去重后的权威列表(★ = 已在各篇定义): | 对象 | 篇 | 权威存储 | 说明 | |---|---|---|---| | Resource / ResourceProfile ★ | 02 | 关系库(复用既有档案/设备中心主数据) | 画像含可靠性评分 | | FlexibilityEnvelope ★ | 04/10 | 关系库 | 能力向上;省间交换同 schema | | PositionLedger / PositionUpdate ★ | 00/04 | 关系库(账本服务) | 约束级联载体 | | Commitment | 10 | 关系库 | 用户承诺与省间承诺共用基型 | | ForecastBundle | 05 | 时序库 + 快照 | 预测曲线 + 分位区间 + 模型版本 | | SituationReport ★ | 02 | 事件日志 + 快照 | | | Proposal ★(含 digest) | 03 | 关系库 + 事件日志 | 状态机见 03 | | ConstraintSet | 03/05 | 随 Proposal 快照 | 优化器输入的约束集合 | | ValidationResult / SimulationResult | 03 | 快照 | 血缘组成部分 | | Approval ★ / ExecutionPermit ★ | 03 | 关系库 | 绑定 digest | | DispatchOrder | 04 | 关系库 | 许可放行后的分解指令 | | ExecutionReceipt / ExecutionReport ★ | 04 | 事件日志 | 幂等回执(I5) | | Settlement | 06 | 关系库 | 结算事实 | | DecisionCase ★ | 02 | 关系库 | 工单聚合(引用,不复制) | | PolicyPack ★ | 05 | 版本库(随代码仓管理) | 可执行规则 + 测试 | | Envelope ★(授权包络) | 03 | 关系库 | 与 FlexibilityEnvelope 严格区分 | | ReviewFinding ★ | 02 | 语义记忆库 | | ## 3. TypeScript ↔ Python 契约策略 ### 3.1 单一事实来源 + 双向生成 ``` packages/domain (zod schemas, TS) ← 唯一手写处 │ 构建时导出 ▼ contracts/*.schema.json (JSON Schema) ← 提交入库的中立工件(版本化) │ datamodel-code-generator ▼ skills-py/.../models.py (pydantic) ← 生成物,禁止手改 ``` - **为什么 zod 为源**:对象的产生地与主要校验点在 TS Runtime(工作流步骤 IO、 结构化输出、事件信封都用 zod);JSON Schema 作为中立层,Python 侧不依赖 TS 工具链; - **双端校验**:TS 侧 `registerSkill` 出站校验(05/09 篇),Python FastAPI 用生成的 pydantic 模型入站校验——同一 schema,两端执行; - **备选方案**(记录备查):JSON Schema 手写为源、两侧都生成——对 Python 团队更中立, 但失去 zod 的 TS 类型推导与重构联动;除非武大/电科院团队明确要求共管 schema 源文件, 维持 zod 为源。 ### 3.2 契约测试(CI 强制) - `contracts/fixtures/` 存每类对象的**黄金样例**(含边界值与历史真实脱敏样本); - TS CI 与 Python CI 各自加载全部样例做校验——两端对同一样例结论不一致即构建失败; - schema 变更走**兼容性检查**:对比上一版 JSON Schema,破坏性变更(删字段、改类型、 收紧约束)必须升主版本并附迁移说明;事件消费者按 `schemaVersion` 路由新旧处理器。 ### 3.3 数据表示纪律(跨语言最容易翻车处) | 项 | 约定 | |---|---| | 金额 / 电价 / 电量 | **字符串表示的定点小数**(`"123.45"`),禁止 JSON 浮点直传金额(TS number 与 Python float 的精度差异会在结算对账时爆炸);两侧分别用 decimal 库处理 | | 单位 | 编进字段名:`power_mw`、`energy_mwh`、`price_yuan_per_mwh`——消灭「这个数是 kW 还是 MW」类事故 | | 时间戳 | ISO8601 UTC 存储与传输;市场时段语义(96 点、申报截止)统一按 `Asia/Shanghai` 解释,时段用 `{date, interval_index}` 而非裸时间戳 | | 曲线 | `{interval_minutes: 15, start: ..., values: [...]}` 定长数组,不用稀疏 map | | 标识 | 全部字符串 ID(防 JS 大整数精度损失);主数据 ID 引用既有档案中心编码 | | 枚举 | 全大写字符串字面量,两侧生成为枚举类型 | ### 3.4 为什么不用 gRPC / protobuf 当前调用量级(申报级频次,非遥测流)下 HTTP/JSON 足够,且: 血缘快照人类可读(审计员直接看)、合作方接入门槛低、与 FastAPI/OpenAPI 生态顺滑。 遥测流是另一个协议域(边缘侧,国网标准协议栈),本就不在 JSON 契约范围内。 二期若省间联邦工件量大再评估签名 + 二进制序列化。 ## 4. 一期落实清单 1. `packages/domain` 建仓:先落 07 篇场景所需对象(Proposal / Approval / Permit / PositionLedger / ForecastBundle / SituationReport / DecisionCase); 2. JSON Schema 导出与 pydantic 生成接入构建脚本;`contracts/` 目录 + 黄金样例; 3. 双端契约测试进 CI(M1 里程碑的一部分——数据先行包括契约先行); 4. 与武大/电科院约定:Skill 服务只依赖 `contracts/`(JSON Schema + 生成的 pydantic), 不依赖 TS 仓的任何内部代码——组织边界与代码边界对齐。