- 13~18 后端纵切六单报告(T2-03~08,测试 95→182) - 14 + openapi-pets-draft.yaml 契约起草档案 - 19 契约冻结报告(v1.2.0,22 项草案修正对照) - 20 契约一致性测试(快照机制 + 1 漂移修复) - 21 第二波收口总表(定型语义汇总,第三波接入依据) - mkdocs build --strict 通过 Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
This commit is contained in:
@@ -0,0 +1,117 @@
|
||||
# 19 · T2-09 契约冻结报告:pets 域 12 路径合入正典(v1.2.0)
|
||||
|
||||
- **日期**:2026-09-08
|
||||
- **工单**:T2-09(M2 第二波,契约冻结)
|
||||
- **仓库**:patbond-doc,main 分支
|
||||
- **角色**:API 契约工程师
|
||||
- **结论先行**:`docs/api/openapi.yaml` 由 1.1.0(6 路径)升至 **1.2.0(18 路径 / 24 操作 / 45 schema)**,pets 域 12 路径按 13/16/17/18 号定型表修正草案后合入;新增错误码 8 个(40300/40401/40402/40902/40903/40904/42201/42202,其中 40903/40904/42201/42202 为 M2 新引入,42200 不引入);校验通过(YAML 解析、$ref 全解析、`mkdocs build --strict`)。**自本报告起 pets 域契约冻结。**
|
||||
|
||||
---
|
||||
|
||||
## 1. 冻结端点总表(12 路径 / 18 操作)
|
||||
|
||||
| # | 端点 | 操作 | 权限档 | 成功 | 分页/排序 | 幂等 | 定型依据 |
|
||||
| --- | --- | --- | --- | --- | --- | --- | --- |
|
||||
| 1 | `/api/v1/pets` | GET | 隐式(按 pet_owners 过滤) | 200 数组 | 不分页,created_at DESC | — | 13 §2.1 |
|
||||
| 2 | `/api/v1/pets` | POST | 任何登录用户 | **201** | — | 无键(唯一约束兜底) | 13 §2.1/§2.4 |
|
||||
| 3 | `/api/v1/pets/{petId}` | GET | READ | 200(含 myRole) | — | — | 13 §2.1 |
|
||||
| 4 | `/api/v1/pets/{petId}` | PATCH | MANAGE(仅 owner) | 200 | — | 乐观锁 version | 13 §2.1/§2.3 |
|
||||
| 5 | `/api/v1/breeds` | GET | 仅 Bearer(字典) | 200 数组 | 不分页,sort_order | — | 13 §2.1 |
|
||||
| 6 | `/api/v1/pets/{petId}/weights` | GET | READ | 200 分页信封 | cursor,measured_at DESC, id DESC | — | 16 §1 |
|
||||
| 7 | `/api/v1/pets/{petId}/weights` | POST | WRITE | **201** | — | 可选 Idempotency-Key | 16 §1/§3 |
|
||||
| 8 | `/api/v1/vaccine-catalog` | GET | 仅 Bearer(字典) | 200 数组 | 不分页,species, name | — | 16 §1 |
|
||||
| 9 | `/api/v1/pets/{petId}/vaccinations` | GET | READ | 200 数组 | **不分页**,series_key, dose_no, created_at, id | — | 16 §1(偏差 #6) |
|
||||
| 10 | `/api/v1/pets/{petId}/vaccinations` | POST | WRITE | **201** | — | 可选 Idempotency-Key | 16 §1/§3 |
|
||||
| 11 | `/api/v1/vaccinations/{vaccinationId}` | PATCH | WRITE | 200 | 顶层短路径 | 乐观锁 version | 16 §1(14 号裁量 #1 照采) |
|
||||
| 12 | `/api/v1/pets/{petId}/health-events` | GET | READ | 200 分页信封 | cursor,occurred_at DESC, id DESC | — | 17 §1 |
|
||||
| 13 | `/api/v1/pets/{petId}/health-events` | POST | WRITE | **201** | — | 可选 Idempotency-Key | 17 §1 |
|
||||
| 14 | `/api/v1/health-events/{eventId}` | PATCH | WRITE | 200 | 顶层短路径 | 乐观锁 version | 17 §1 |
|
||||
| 15 | `/api/v1/pets/{petId}/care-reminders` | GET | READ | 200 数组 | **不分页**,due_at ASC, id;`?status=` 过滤 | — | 17 §1(偏差 #4) |
|
||||
| 16 | `/api/v1/pets/{petId}/care-reminders` | POST | WRITE | **201** | — | 可选 Idempotency-Key | 17 §1(偏差 #5,拍板 B) |
|
||||
| 17 | `/api/v1/care-reminders/{reminderId}` | PATCH | WRITE | 200 | 顶层短路径 | 状态守卫(无 version 列) | 17 §1/§2.2(偏差 #6) |
|
||||
| 18 | `/api/v1/pets/{petId}/summary` | GET | READ | 200 | `?tz=` IANA,缺省 UTC | — | 18 §1/§2/§3 |
|
||||
|
||||
**软删除端点 `DELETE /api/v1/pets/{petId}` 不进 M2 契约**(拍板 B;D2-7 首版仅归档,13 §1 明确不在单)。
|
||||
|
||||
### 汇总数
|
||||
|
||||
| 维度 | 1.1.0 | 1.2.0 |
|
||||
| --- | --- | --- |
|
||||
| 路径 | 6 | **18**(+12) |
|
||||
| 操作 | 6 | **24**(+18) |
|
||||
| schema | 15 | **45**(+30) |
|
||||
| 错误码(业务码,不含 0) | 10 | **18**(+8:40300/40401/40402/40902/40903/40904/42201/42202) |
|
||||
| 复用组件 | — | 新增 responses 4(PetNotFound/RecordNotFound/PetWriteDenied/VersionConflict)、parameters 4(PetIdParam/PageLimitParam/PageCursorParam/IdempotencyKeyHeader) |
|
||||
|
||||
## 2. 草案 → 冻结的全部修正项对照(22 项)
|
||||
|
||||
草案 = `openapi-pets-draft.yaml` + 14 号起草报告;修正一律以实现定型表为准(实现定型表 > 草案)。
|
||||
|
||||
### 2.1 错误码(拍板 A1)
|
||||
|
||||
| # | 草案 | 冻结定案 | 依据 |
|
||||
| --- | --- | --- | --- |
|
||||
| 1 | 剂次重复用 40903 | **40904 VACCINATION_DOSE_EXISTS**(40903 已被 T2-03 的 MICROCHIP_EXISTS 占用,按「不复用不改号」顺延) | 16 §4、偏差 #1 |
|
||||
| 2 | 42200 BREED_CONSTRAINT_VIOLATION(品种互斥 422) | **不引入**;品种双填/双空/物种错配/品种不存在或停用一律 400/40000 | 13 §2.4、16 偏差 #2 |
|
||||
| 3 | 42201 疫苗状态机(草案提议) | **照采**,语义定为疫苗专属 VACCINATION_RULE_VIOLATION | 16 §4 |
|
||||
| 4 | 提醒 422 复用 42201 | **42202 REMINDER_RULE_VIOLATION(新增)**,跨资源不复用错误码 | 17 §4、偏差 #1 |
|
||||
| 5 | 草案无 40903 芯片号语义 | **40903 MICROCHIP_EXISTS 新增**(POST/PATCH pets 的 409 分支) | 13 §2.4 |
|
||||
|
||||
### 2.2 响应形态与命名(拍板 A2)
|
||||
|
||||
| # | 草案 | 冻结定案 | 依据 |
|
||||
| --- | --- | --- | --- |
|
||||
| 6 | 资源主键用类型化名(petId/weightId/vaccinationId/eventId/reminderId,14 号裁量 #7) | **裸 `id`**,关联字段保留类型名(petId/vaccineId 等);路径参数名不变 | 16 偏差 #3、17 偏差 #2 |
|
||||
| 7 | Vaccination 无疫苗名称 | 响应**增加 `vaccineName`**(同 breedDisplayName 先例) | 16 偏差 #4 |
|
||||
| 8 | Pet 无 breedDisplayName;列表 Pet 不带 myRole(14 号裁量 #8) | **增加 `breedDisplayName`**;**myRole 进全部宠物响应**(列表/详情/创建/更新统一 Pet schema,PetDetail 撤销) | 13 §2.2 |
|
||||
| 9 | Pet 含 avatarAssetId(只读回显)、status 枚举含 deleted | **avatarAssetId 移除**(ADR-010 整体不出现);响应 status 枚举去 deleted(软删宠物一律 404/40401,永不返回) | 13 §2.2/§2.4 |
|
||||
| 10 | 创建 201、分页信封 `{items, nextCursor, hasMore}`(草案形态) | **照采并升格为全 API 分页正典**,写入 info 通用约定 | 拍板 A2、16 §1.1 |
|
||||
|
||||
### 2.3 分页与列表(拍板 A3)
|
||||
|
||||
| # | 草案 | 冻结定案 | 依据 |
|
||||
| --- | --- | --- | --- |
|
||||
| 11 | 疫苗列表分页待定(TODO-FREEZE #5) | **不分页**,`series_key, dose_no, created_at, id` 排序定死;列表不过滤 status | 16 偏差 #6 |
|
||||
| 12 | 提醒列表分页/待办过滤待定(TODO-FREEZE #8) | **不分页** + `?status=` 白名单过滤,`due_at ASC, id` 排序 | 17 偏差 #4 |
|
||||
| 13 | GET /pets 是否分页待定(TODO-FREEZE #2) | **不分页**,created_at DESC | 13 §2.1 |
|
||||
| 14 | 列表 GET 无 400 分支 | 补 400/40000(limit 越界、cursor 无效、status/species 非法参数) | 13 §2.4、16 §4、17 §4 |
|
||||
|
||||
### 2.4 PATCH 语义与请求体(拍板 A4/B)
|
||||
|
||||
| # | 草案 | 冻结定案 | 依据 |
|
||||
| --- | --- | --- | --- |
|
||||
| 15 | Update 请求字段标 nullable(暗示可清空) | **缺席=不变,不支持清空回 null**,三个 Update schema 全部去 nullable;宠物品种对为唯一例外(整体替换) | 13 §2.3、16 偏差 #7、17 偏差 #3 |
|
||||
| 16 | UpdatePetRequest 权限待定(TODO-FREEZE #4) | MANAGE 仅 owner;species 不可改;status=deleted 经 PATCH 一律 400/40000 | 13 §2.1/§2.3 |
|
||||
| 17 | CreateVaccinationRequest.status 含 cancelled | 创建仅 **scheduled/completed**(创建即取消 400/40000) | 16 偏差 #5 |
|
||||
| 18 | UpdateVaccinationRequest 可改 vaccineId/seriesKey/doseNo?(草案未禁) | **不可改**(不在请求体),修正路径 cancel 后重建;completed/cancelled 均为终态 | 16 §1.2/§2 |
|
||||
| 19 | care-reminders PATCH 无 409 | **补 409/40902**(无 version 列,当前状态条件更新守卫落空) | 17 偏差 #6、§2.2 |
|
||||
| 20 | 顶层短路径待拍板(TODO-FREEZE #11) | **照采**;40402 定型为记录级防枚举(记录不存在与所属宠物不可见响应完全一致);40401 定型为宠物级防枚举(不存在/软删/无关系一致) | 拍板 A4、13 §2.4、16 §4 |
|
||||
|
||||
### 2.5 PetSummary 与其它(拍板 A5/B)
|
||||
|
||||
| # | 草案 | 冻结定案 | 依据 |
|
||||
| --- | --- | --- | --- |
|
||||
| 21 | PetSummary 全 schema 占位(TODO-FREEZE #9/#10) | 按 18 §2 全量替换:`nextVaccination` 用 `dueOn`+`source(planned|nextDue)` 替代单一 plannedOn,增加 vaccinationId/vaccineId/doseNo/doseLabel;`monthlyExpense` 恒非 null、增 timezone 回显、month 定 ISO year-month;进度分母 = 已登记剂次;无记录 null 语义(progress null ≠ 0/0);四项聚合口径**逐字**进 schema 描述;新增 `tz` 查询参数(IANA,缺省 UTC,非法 40000) | 18 §2/§3 |
|
||||
| 22 | 实现侧收紧补进契约描述 | 疫苗须存在/enabled/物种匹配(40000);doseNo ≤32767;health-event notes ≤2000;amountCents 拒绝小数(40000,不静默截断);title btrim 空白 40000;创建提醒不收 status;createdByUserId 取自 token 不收请求体;Idempotency-Key 语义细则(≤255、调用者×宠物×资源隔离、不比对请求体、无 TTL) | 16 §5 末段、17 §4/§6 末段 |
|
||||
|
||||
## 3. 定型表间矛盾核查
|
||||
|
||||
逐项交叉核对 13/16/17/18 号定型表:**未发现互相矛盾处**(40902 在提醒流转守卫上的复用为 17 号显式定型,非撞号;42201/42202 分立与「不复用不改号」原则自洽;防枚举语义 13→16→17 单点继承一致;18 号聚合口径与 16 号「聚合侧自行排除 cancelled」的移交一致)。
|
||||
|
||||
**一处拍板措辞与定型表的出入(已按定型表执行,非仲裁)**:拍板 B 组表述为「Idempotency-Key 为可选头(weights/health-events/care-reminders 三个 POST)」,未列 vaccinations POST;而 16 号定型表明确 `POST .../vaccinations` 支持可选 Idempotency-Key 且有测试锁定(同键两次 201 同 id、落库 1 行),草案亦本已声明该头(14 号裁量 #6,三个 POST 含 vaccinations)。判断拍板枚举的是「本次需拍板的三处」(care-reminders 为 17 号新增偏差 #5,weights/health-events 为可选性确认),vaccinations 属草案既有、无争议项。冻结契约按实现收录**四个** POST 的可选 Idempotency-Key。若此判断与拍板本意不符,请显著上报——收窄为三个属于从契约中移除已实现并已测试的行为,需两端同步。
|
||||
|
||||
## 4. 冻结纪律声明
|
||||
|
||||
自 v1.2.0 起,pets 域 12 路径与全部 schema/错误码**冻结**:
|
||||
|
||||
1. **任何字段变更(增、删、改名、改类型、改必填性、改枚举、改口径)须显著上报**,经评审后走契约变更流程,**两端(后端 patbond-api、客户端 patbond-flutter)同步**,禁止任一侧单方面偏离。
|
||||
2. 纯增量扩展(新增可选响应字段、新增端点、新增错误码)允许在次版本内追加,但同样先改契约再改实现(契约先行,docs/api/index.md 约定)。
|
||||
3. 错误码永不复用、永不改号、永不改义(40903=MICROCHIP_EXISTS、40904=VACCINATION_DOSE_EXISTS、42201=疫苗专属、42202=提醒专属,已在错误码表定死)。
|
||||
4. 已知的未来破坏性调整须走上报流程的存量项:① totalDoses 分母若引入「系列应打总针数」(18 §6);② 幂等键无 TTL 若改为 idempotency 表 + TTL(16 §7);③ ADR-010 裁剪字段(avatar/certificate/provider/booking)M5 按纯增量补入(非破坏性,但须契约先行)。
|
||||
5. 提醒的 title/dueAt 编辑与删除端点、宠物软删除端点均**不在** M2 契约;M2 内改期路径为 dismiss 后重建(17 §7),归档经 `PATCH status=archived`。
|
||||
|
||||
## 5. 校验与提交
|
||||
|
||||
- `python3 yaml.safe_load` 解析通过;158 个 `$ref` 全部可解析;18 路径 / 24 操作 / 45 schema / 错误码表 19 行计数核对一致。
|
||||
- `mkdocs build --strict` 通过。
|
||||
- 提交:`docs/api/openapi.yaml` + `docs/api/index.md` 独立提交并推送 main(提交 `511617b`);本报告与草案文件(14 号、openapi-pets-draft.yaml)按波末统一入档,暂不提交;mkdocs.yml 未动。
|
||||
Reference in New Issue
Block a user