用途
本技能聚焦于消费者兼容性与协议语义,适用于以下场景:设计新的 API 端点;定义团队之间或由独立发布方消费的契约;修改现有的公共接口;建立会影响 API 形态的数据库模式。
它与其他技能有明确分工。进程内模块的职责划分、调用方负担、信息隐藏与接口深度,应加载 codebase-design;当内部模块同时对外或跨团队暴露契约时,两者一起使用。只有当网关、框架、SDK、供应商或协议实现等重大选择仍未确定时,才使用 evaluate-existing-solutions;API 语义与兼容性始终留在本技能。TypeScript 类型模式(品牌类型、可辨识联合、模式优先)参见 typescript-strict;不可变模式参见 functional;API 行为测试参见 testing;OAuth 2.0 或 OpenID Connect 应加载 secure-oauth-oidc,而不是把认证当作普通 API Key 决策;面向浏览器的 BFF 入口点(公共/受保护访问分类、会话 Cookie、CSRF/Origin/Fetch Metadata 策略、受保护 SSE/WebSocket 注册、端点保护执行)加载 bff-entry-points,而错误形态与 REST 语义仍留在本技能;BFF 模式本身(采纳、粒度、聚合、上游身份)加载 bff-design——与其前端同步部署的单消费者 BFF 可以合理地放宽本技能对外部消费契约所要求的版本纪律。
主要能力
核心原则
- Hyrum 定律:当 API 拥有足够多用户时,系统的所有可观察行为都会被某人依赖,无论契约中承诺了什么。每个公共行为——包括未记录的怪癖、错误消息文本、时序与顺序——一旦被用户依赖,就成为事实上的契约。由此要求:对暴露内容保持刻意;不泄露实现细节;在设计阶段就规划弃用,并在发生时立刻记录;测试并不足够,即使有完美的契约测试,Hyrum 定律意味着“安全”的变更仍可能破坏依赖未记录行为的真实用户。
- 单版本规则:避免迫使消费者在同一依赖或 API 的多个版本之间做选择。当不同消费者需要同一事物的不同版本时会出现菱形依赖问题。应设计为同一时间只存在一个版本——扩展而非分叉。
- 契约优先:在实现之前先定义接口,契约即规范,实现随之而来。这与 TDD 一致:定义契约(想要什么),针对它写测试,然后实现。
- 以增加代替修改:在不破坏现有消费者的情况下扩展接口。该规则优先于请求的措辞:对已发布契约中已公开内容(响应字段、请求头、状态码、路由)的改名、改类型、收窄或移除请求,应交付新增形态——在旧名称旁新增新名称,保持旧名称可用且承载相同值,将旧名称记录为已被取代,并在回复中说明是新增而非替换以及退役旧名称需要什么。
错误语义
选择一个错误策略并在各处统一使用,不要混用某些端点抛异常、某些返回 null、某些返回 { error } 的做法。在同一版本化 API 契约内,使用一种有文档记载的错误形态,除非某个特定协议的端点需要另一种;一致性比选择哪种兼容格式更重要。
对外部消费者的公共 API,使用 RFC 9457(Problem Details),以 application/problem+json 作为 Content-Type。标准成员包括:type(标识错误类型的 URI)、title(稳定的人类可读摘要)、status(必须与实际 HTTP 状态一致)、detail(针对本次发生情况的说明)、instance(可选的发生实例 URI)。允许扩展成员,客户端必须忽略不认识的扩展。错误应当是可操作的,绝不暴露堆栈跟踪、内部路径或实现细节。应包含关联标识符(追踪 ID 或其不透明引用)作为扩展成员或通过 instance 传递。
对于只有一个前端消费的内部 API,更简单的统一形态是有效选择,最低限度需要:机器可读的错误码、可选的人类可读消息、正确的 HTTP 状态码。若从简单格式开始,应设计成日后可演进到 RFC 9457(如 error 映射到 title,message 映射到 detail)。
HTTP 状态码映射
400 用于客户端发送格式错误的数据;401 未认证;403 已认证但未授权;404 资源不存在;409 冲突(重复、版本不匹配);422 校验失败(语义无效);429 超出限流,在已知有意义的可重试时间时包含 Retry-After;500 服务器错误(绝不暴露内部细节)。
API 边界处的校验
在不受信任的表示和端点 schema 输入进入系统处进行校验,再把派生类型传入内部代码。这不能替代领域智能构造器或状态转换检查:不变量的执行仍由拥有该值的模型负责。表示本身无法解析(如格式错误的 JSON)时返回 400;解析成功后,值未通过端点 schema 或业务校验时返回 422。
幂等性
网络故障会发生,客户端会重试;没有幂等性,重试会造成重复扣款、重复订单、重复记录。HTTP 方法层面:GET 安全和幂等;PUT 不安全和幂等(同一请求有相同预期效果,响应状态/正文可能不同);DELETE 不安全和幂等;POST 不安全且不幂等,需要显式处理;PATCH 不安全,是否幂等取决于实现。
对于非幂等操作(尤其涉及金钱、订单或状态变更),使用客户端提供的幂等键。设计原则包括:键应限定到 API Key/已认证用户;响应缓存与认领保留时长应依据有文档记载的最大客户端重试/对账窗口和影响风险来选择,24 小时并非通用规则;在缓存响应逐出之后仍保留持久操作身份(及指纹或墓碑),或返回明确的过期/未知结果,绝不要静默地把有风险的复用键当作新操作;若同一键重试时参数不同则返回错误;原子地认领键,分开的先读后建序列存在竞态;通过一个事务或持久的下游操作 ID 协调业务效果与认领;对外部支付,持久化并对账供应商的 payment/intent ID;显式表示进行中的认领并定义认领后 worker 失败的恢复;按“至少一次”投递来设计。
DELETE 必须具备幂等效果:重复执行不会删除其他内容或产生第二个副作用。重复响应可保持 204,当缺失对客户端有意义时也可以是 404,选择并记录一种契约。
限流
当 API 公开配额策略时,在客户端有用的响应上一致地传达适用策略与剩余状态;不要为没有此类策略的端点臆造配额请求头。IETF 标准化工作是 draft-ietf-httpapi-ratelimit-headers(版本 11,2026 年 5 月——仍为活跃工作组草案)。当前草案定义两个结构化字段:
RateLimit-Policy: "hour";q=1000;w=3600 # Policy: quota of 1000 per 3600s window
RateLimit: "hour";r=742;t=60 # Current state: 742 remaining, resets in 60s
更早的草案使用三元组 RateLimit-Limit、RateLimit-Remaining、RateLimit-Reset,许多已发布 API 仍在使用该三元组或未标准化的 X-RateLimit-* 系列。消费 API 时要预期其中任一种。新 API 倾向于使用当前草案字段;无论选择哪种名称都要记录——请求头名称是契约的一部分,草案在成为 RFC 前仍可能变化。在 429 响应上,服务器能给出有意义的可重试时间时应包含 Retry-After。
使用方式
本技能的实际用法在具体设计任务中体现:先写契约,再实现与测试;新增字段与端点而非修改既有定义;统一错误形态与状态码;对非幂等写操作引入幂等键;在存在配额策略时一致传达限流状态。支撑资源位于 resources/ 目录,按需加载:problem-details.md 在实现 RFC 9457 错误响应时加载(成员语义、单错误与校验错误 JSON 示例、扩展成员、第 5 节安全指引);api-evolution.md 在需要版本策略与弃用模式时加载;api-security.md 在保护 API 边界时加载;auth-security.md 涉及 JWT BCP 安全及路由到专门的 OAuth/OIDC 技能;http-fundamentals.md 涉及 HTTP 协议基础——缓存指令、内容协商、浏览器安全、状态码、请求头设计;source-notes.md 用于审阅来源、不可变审计基线、许可范围与本地偏离。
适用场景
适用于设计新 API 端点、定义团队间或独立发布消费者之间的契约、修改现有公共接口、建立会影响 API 形态的数据库模式。也适用于内部模块同时暴露公共或跨团队契约的情形(与 codebase-design 配合)。
限制
本技能的范围是消费者兼容性与协议语义。进程内模块责任、隐藏与深度不属于本技能;TypeScript 类型模式与信任边界校验不属于本技能;不可变模式、API 行为测试、OAuth 2.0/OpenID Connect 认证、面向浏览器的 BFF 入口点与 BFF 模式本身均有各自专门的技能。此外,本技能未提供具体价格、收费方式或平台支持信息。