Files
patbond-doc/docs/development/iterations/iteration-3/19-contract-sync-report.md
T
lixi a611acb358
CI / docs-build (push) Successful in 32s
docs: M3 第二波收口——报告 15~20 入档挂导航
- 15~17 社区后端纵切三单(帖子/Feed 作者链路/评论互动关注,226→310)
- 18 契约冻结 v1.3.0(31 路径/43 操作,26 项修正照单全收)
- 19 快照同步与全仓契约矩阵(173 格零漂移,修 allOf 校验盲区,→325)
- 20 收口总表:定型语义汇总(第三波接入依据)与质量事件记录

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-09-09 11:38:42 +08:00

7.9 KiB
Raw Blame History

M3 契约同步报告(api 侧:v1.3.0 字节级快照同步 + community/media 契约矩阵入场)

作者:Senior Developer(后端) 日期:2026-09-09 工单:契约冻结 v1.3.0 的 api 侧收尾(18 号冻结报告 §5-2 注明的硬依赖工单) 输入:doc 仓 docs/api/openapi.yaml v1.3.0main@f84847631 路径 / 43 操作 / 72 schemas);patbond-api dev@7f1dd33310 测试基线) 结论先行:正典 v1.3.0 已字节级复制为四个模块的 openapi-v1.3.0.yaml 快照(md5 与正典逐一比对一致),pet/auth 守卫期望同步升版;community 域 17 操作 64 单元格、media 域 2 操作 8 单元格的契约一致性测试全响应矩阵入场,均零豁免;实现与冻结契约零漂移(64+8 格无一漂移报告);发现并修复框架级校验盲区一处(ContractValidator 不支持 v1.3.0 引入的 nullable + allOf: [$ref] 模式,会静默跳过 coverImage/replyToUser 内部校验);mutation 自证两轮通过(普通路径 + allOf 定向路径注毒均红、还原即绿);全套 325 测试全绿(310 + 15),check-secrets.sh --all 通过。


1. 快照同步(字节级)

位置 处置
patbond-pet/src/test/resources/contract/ openapi-v1.2.0.yaml openapi-v1.3.0.yaml 替换(删旧)
patbond-auth/src/test/resources/contract/ openapi-v1.2.0.yaml openapi-v1.3.0.yaml 替换(删旧)
patbond-community/src/test/resources/contract/ —(新建) openapi-v1.3.0.yaml 新增
patbond-user/src/test/resources/contract/ —(新建) openapi-v1.3.0.yaml 新增
  • 四份快照 md5 与 doc 仓正典(main@f848476)逐一比对一致(5b550fabf8e94b715ac1161798cb2738),满足「字节级复制」纪律。
  • 旧 v1.2.0 快照删除而非保留:每个模块的 OpenApiContract.RESOURCE 常量只认一份快照文件,守卫测试锁 info.version,保留旧文件只是死重——历史版本由 git 历史与 doc 仓承载。
  • pet/auth 守卫期望同步升版:1.2.0/18 路径/24 操作/45 schemas1.3.0/31/43/72;各域 operationsTagged 断言不变仍绿(pets 域 18 操作、auth 域 6 操作在 v1.3.0 中零变化,即 v1.2.0 冻结面未被 1.3.0 触碰的实证)。
  • 契约框架(OpenApiContract + ContractValidator)按既有的模块内复制纪律扩为四份同构副本(pet/auth/community/user),同步纪律注释已改为「四模块各复制一份、各自更新期望」。

2. 覆盖矩阵规模(本单新增 19 操作 / 72 单元格,零豁免)

模块 测试类 操作 (操作, 状态码) 单元格 豁免
communityposts/feed/comments/interactions/follows patbond-community CommunityContractConformanceTest 17 64 0
media(两步上传,属 user 模块) patbond-user MediaContractConformanceTest 2 8 0
pets/dictionaries/health-records(既有) patbond-pet ContractConformanceTest 18 82 1(沿用)
auth/user/analytics(既有) patbond-auth AuthContractConformanceTest 6 19 0
合计(v1.3.0 全部 43 操作) 4 模块 4 类 43 173 1
  • 机制与 pet 侧 T2-09 完全同构:真实起服务发请求(community 走 MockMvc + postgres:18 Testcontainer 全迁移链;media 走真实 MinIO Testcontainer,直传为真实 HTTP PUT)→ 严格校验器逐字段比对(未声明字段即报漂移)→ 末位全矩阵门禁断言每个声明单元格都被真实响应触发过。
  • community 域覆盖要点:错误码全谱 40000/40101/40301/40401/40403/40404/40405/40406/40902/40905/42203/42204 各至少一格实证;双业务码单元格(POST /posts 404 的 40401/40405、POST comments 404 的 40403/40406)两种业务码分别触发;分页信封 hasMore/nextCursor 两态、coverImage 与 replyToUser 的 null/非空两分支、防枚举合并语义(幽灵 id 与他人 draft 同响应)均在矩阵内。
  • media 域覆盖要点:201 凭据形态、直传后 complete 200(含幂等重复确认)、400mime 白名单外 + 畸形 assetId)、401、404 防枚举合并(他人 asset 与幽灵 asset 同答 40405)、422/42205(直传前确认)。

豁免格清单

本单新增矩阵零豁免——community 域的 409 均为幂等键/乐观锁冲突、422 均为业务规则拒绝,media 域 422 为状态机拒绝,单线程 MockMvc 均可确定性触发。全仓唯一豁免格仍为 pet 侧沿用的 PATCH /api/v1/care-reminders/{reminderId} 409(并发条件更新守卫落空,单线程无法确定性构造,行为语义由并发一致性设计文档背书)。

3. 发现并修复的漂移清单

3.1 实现 ↔ 冻结契约:零漂移

新增 72 单元格全部一次通过严格校验,无字段名/类型/必填/nullable/枚举/格式漂移,无需修实现;未发现语义级冲突。这与第二波「先定型表、后冻结照单全收」的流程预期一致——契约本就是按已定型实现冻结的,本单是对「冻结稿与实现零偏差」声明的全矩阵实证。

3.2 框架级校验盲区一处(发现并修复)

  • 问题v1.3.0 为表达「可空的 $ref」引入 nullable: true + allOf: [$ref] 模式(FeedCard.coverImageComment.replyToUser),而既有 ContractValidator 明文只支持无 allOf 子集——遇到该模式会解析出 type=null静默跳过内部校验coverImage/replyToUser 里新增泄漏字段或类型漂移将无法被察觉,属校验盲区而非误报。
  • 修复:四份 ContractValidator 副本同步加入单分支 allOf 展平合并(分支键先入、同级键——如外层 nullable——胜出;冻结契约只用单分支 allOf,浅合并即精确),并以定向 mutation 证明该路径生效(见 §4)。

4. mutation 自证(注毒应红、还原应绿)

轮次 注毒点 预期 实测
1a community 快照 PostMediaItem.required 注入假必填字段 5 测试失败,$.data.media[0].fakeContractField: 契约必填字段缺失
1b user 快照 MediaAsset.required 注入假必填字段 2 测试失败,$.data.fakeContractField: 契约必填字段缺失
2 community 快照 coverImage 的 allOf 同级注入 required: [fakeAllOfField](定向打 allOf 合并路径) GET /api/v1/feed 200 漂移:$.data.items[*].coverImage.fakeAllOfField: 契约必填字段缺失
还原 四快照 cp 回正典并 md5 复核 绿 全套 325 测试全绿

第 2 轮专为 §3.2 的修复自证:假必填字段被报告在 coverImage 内部,证明 allOf 合并后校验器确实下钻到了此前静默跳过的分支。

5. 测试数变化

模块 基线 现在 增量
patbond-common 3 3
patbond-user 96 100 +4MediaContractConformanceTest
patbond-auth 39 39 —(守卫期望升版,数量不变)
patbond-pet 89 89 —(守卫期望升版,数量不变)
patbond-community 83 94 +11CommunityContractConformanceTest
合计 310 325 +15

JAVA_HOME=/usr/lib/jvm/java-17-openjdk ./mvnw clean test 全绿;scripts/check-secrets.sh --all 通过(快照与测试无敏感信息,MinIO 凭据沿用 dummy 占位值先例)。

6. 遗留与交接

  • 契约同步纪律自此为四处复制:doc 仓正典升版 → 四模块同字节复制新快照 + 各守卫期望更新,任一处忘记同步 CI 即红(守卫锁 info.version 与三项计数)。
  • 契约测试框架仍为模块内四份同构副本(与 BearerAuthFilter 同纪律);若第三迭代后副本继续增多,可评估抽入 patbond-common 的 test-jar,此次不动。
  • 本报告(19 号)随波末统一挂导航入档;mkdocs.yml 本次不动;doc 仓 openapi.yaml 本单未触碰。