关键设计决策和原因
概述
本文档深入分析 UCP 的关键设计决策,解释每个决策背后的原因、权衡和依据。这些决策共同构成了 UCP 的核心架构,使其能够解决电商生态系统的互操作性问题。
1. 能力(Capabilities)与扩展(Extensions)分离
决策
将核心功能(Capabilities)与可选增强(Extensions)分离,使用 extends 字段声明扩展依赖。
原因
- 避免能力定义臃肿:如果所有功能都放在基础能力中,Schema 会变得庞大且难以维护
- 支持渐进式增强:商家可以根据需要逐步添加功能,而不必实现所有功能
- 保持核心简洁:核心能力保持简洁,专注于基本功能
- 灵活组合:通过扩展机制实现功能的灵活组合
权衡
优势:
- 模块化设计
- 易于扩展
- 向后兼容
挑战:
- 需要 Schema 组合逻辑
- 扩展依赖管理
- 文档复杂度增加
依据
- JSON Schema 的
allOf组合机制 - 软件工程中的关注点分离原则
- REST API 设计中的资源扩展模式
2. 动态能力发现与协商
决策
商家通过 Profile 声明能力,平台通过请求声明 Profile URI,双方通过算法协商确定共同支持的能力。
原因
- 无许可集成:无需预先注册即可集成,降低集成门槛
- 自动适配:平台可以自动发现和适配商家能力
- 减少集成复杂度:从 O(N×M) 降低到 O(N+M)
- 支持快速迭代:商家可以快速添加新能力,平台自动发现
权衡
优势:
- 降低集成成本
- 支持快速集成
- 灵活的生态系统
挑战:
- Profile 获取开销
- 协商算法复杂度
- 缓存和性能优化需求
依据
- Web 标准中的
.well-known机制 - OAuth 2.0 的发现机制
- 分布式系统中的服务发现模式
3. 反向域名命名空间
决策
使用反向域名格式({reverse-domain}.{service}.{capability})命名能力和服务,将治理权限编码到标识符中。
原因
- 无需中央注册表:通过域名所有权自然建立治理关系
- 避免命名冲突:反向域名确保全局唯一性
- 清晰的治理模型:从名称即可知道谁负责该能力
- 支持供应商扩展:供应商可以使用自己的命名空间定义自定义能力
权衡
优势:
- 去中心化
- 避免单点故障
- 清晰的治理关系
挑战:
- 名称较长
- 需要域名所有权验证
- 供应商需要管理自己的命名空间
依据
- Java 包命名约定
- Android 应用 ID 命名
- DNS 系统的域名所有权模型
4. 传输无关设计
决策
协议设计独立于传输层,支持多种传输协议(REST、MCP、A2A、Embedded)。
原因
- 适应不同基础设施:不同商家和平台有不同的技术栈
- 支持多种用例:AI 代理偏好 MCP,Web 应用偏好 REST
- 未来扩展性:可以添加新的传输协议而不影响核心协议
- 统一操作语义:无论使用哪种传输,操作行为一致
权衡
优势:
- 灵活性
- 广泛的适用性
- 未来扩展性
挑战:
- 需要定义传输绑定
- 实现复杂度增加
- 需要统一的错误处理
依据
- OSI 模型的层次化设计
- HTTP 作为应用层协议的设计
- 抽象与具体实现的分离原则
5. 支付处理器抽象
决策
将支付工具(接受什么)与支付处理器(如何处理)分离,通过 Payment Handler 规范定义处理流程。
原因
- 解决 N-to-N 复杂度:从 O(N×M×P) 降低到 O(N+M+P)
- 解耦支付逻辑:平台不需要了解每个支付提供商的细节
- 支持新支付方式:新支付方式只需定义新的 Handler
- 最小化 PCI 范围:平台不接触原始支付凭证
权衡
优势:
- 大幅降低复杂度
- 灵活的支付方式支持
- 安全优势
挑战:
- Handler 规范定义复杂度
- 需要支付提供商合作
- 实现复杂度增加
依据**
- 设计模式中的策略模式
- 插件架构模式
- 支付行业的令牌化实践
6. 客户端 Schema 解析
决策
平台必须在客户端获取和组合 Schema,而不是服务器端预组合。
原因
- 瘦传输定义:传输定义只引用基础 Schema,保持简洁
- 支持动态扩展:扩展可以独立发布和版本化
- 类型安全:通过 JSON Schema 提供类型验证
- 自描述:Schema 明确声明依赖关系
权衡
优势:
- 模块化 Schema
- 灵活的扩展机制
- 类型安全
挑战:
- 客户端解析开销
- 多次 Schema 获取
- 需要缓存机制
依据
- JSON Schema 的
$ref机制 - 客户端驱动的 API 设计
- 微服务架构中的服务发现模式
7. HTTP Message Signatures
决策
使用 RFC 9421 HTTP Message Signatures 作为主要的身份认证机制。
原因
- 无许可集成:无需预先建立信任关系
- 基于标准:使用成熟的 IETF 标准
- 不可否认性:提供加密签名保证
- 密钥发现:通过 Profile 自动发现公钥
权衡
优势:
- 支持无许可集成
- 强大的安全性
- 基于标准
挑战:
- 实现复杂度
- 性能开销
- 密钥管理需求
依据
- RFC 9421 HTTP Message Signatures
- 公钥基础设施(PKI)模型
- OAuth 2.0 的密钥发现机制
8. 日期格式版本控制
决策
使用日期格式(YYYY-MM-DD)而非语义版本(如 1.2.3)进行版本控制。
原因
- 清晰的顺序:日期格式提供明确的 chronological ordering
- 避免歧义:语义版本号可能产生歧义(如
1.2.3vs1.2.4) - 易于理解:日期格式直观易懂
- 独立组件版本化:支持协议和能力独立版本化
权衡
优势:
- 清晰的版本语义
- 易于版本比较
- 支持独立版本化
挑战:
- 不能表达破坏性更改的程度
- 版本号较长
- 需要明确的兼容性规则
依据
- API 版本控制最佳实践
- 日期格式的清晰性
- 独立组件版本化的需求
9. 服务器选择(Server-Selects)架构
决策
能力协商采用服务器选择架构,商家(服务器)决定激活的能力集合。
原因
- 商家控制:商家对自己的能力有最终决定权
- 简化客户端:平台不需要复杂的协商逻辑
- 安全性:商家可以基于安全策略选择能力
- 性能:协商在服务器端完成,可以利用缓存
权衡
优势:
- 商家控制
- 简化客户端
- 安全性
挑战:
- 平台需要信任商家
- 协商结果可能不符合平台期望
- 需要明确的错误处理
依据
- REST API 设计中的服务器驱动协商
- OAuth 2.0 的服务器选择模式
- 安全最佳实践
10. Profile 缓存策略
决策
要求 Profile 支持公共缓存,最小 TTL 60 秒,不允许 private、no-store 或 no-cache。
原因
- 性能优化:减少 Profile 获取开销
- 稳定性:Profile 代表稳定的身份和能力
- 防止滥用:防止恶意请求导致大量 Profile 获取
- 支持 CDN:允许使用 CDN 缓存 Profile
权衡
优势:
- 性能提升
- 减少服务器负载
- 支持 CDN 缓存
挑战:
- 更新延迟
- 需要版本控制
- 缓存失效策略
依据
- HTTP 缓存标准(RFC 7234)
- Web 性能最佳实践
- CDN 缓存策略
11. 单向凭证流
决策
支付凭证只从平台流向商家,商家不得在响应中回显凭证。
原因
- 最小化 PCI 范围:减少接触支付凭证的系统
- 安全最佳实践:避免凭证在响应中暴露
- 防止重放攻击:单向流减少攻击面
- 合规性:符合 PCI-DSS 要求
权衡
优势:
- 安全性提升
- 合规性优势
- 减少攻击面
挑战:
- 错误处理复杂度
- 需要不透明令牌
- 调试困难
依据
- PCI-DSS 合规要求
- 安全最佳实践
- 支付行业的令牌化实践
12. 扩展的 requires 字段
决策
扩展 Schema 可以声明 requires 字段来指示所需的协议和能力版本。
原因
- 版本依赖管理:明确声明版本依赖关系
- 兼容性验证:在运行时验证版本兼容性
- 防止错误使用:防止在不兼容的版本中使用扩展
- 文档化:Schema 本身文档化版本要求
权衡
优势:
- 明确的版本依赖
- 自动兼容性验证
- 防止错误使用
挑战:
- Schema 复杂度增加
- 需要版本比较逻辑
- 文档维护成本
依据
- 软件包管理的版本依赖模型
- API 版本控制最佳实践
- 类型系统的版本约束
总结
UCP 的关键设计决策共同实现了:
- 模块化:通过能力和扩展分离实现模块化设计
- 灵活性:通过动态发现和传输无关设计实现灵活性
- 安全性:通过 HTTP Message Signatures 和单向凭证流实现安全性
- 可扩展性:通过命名空间和扩展机制实现可扩展性
- 性能:通过缓存策略和客户端解析实现性能优化
这些决策基于:
- 成熟的 Web 标准和最佳实践
- 软件工程的设计原则
- 支付行业的安全要求
- 分布式系统的架构模式
通过仔细权衡各种因素,UCP 实现了一个既灵活又安全、既强大又易用的协议。