- iteration-3 报告 01-08(PM 拆解/后端/Flutter/RC 首个 CERTIFIED/UI/埋点/证据基线/Git) - ADR-016 自托管 MinIO 起步预留迁云(用户确认现无云存储)、ADR-017 patbond-community :8084 + media 归 user + 作者信息跨 schema 只读、ADR-018 范围裁剪(话题剪出/单层评论)、 ADR-019 幂等按域(PUT/DELETE + request_hash)、ADR-020 聚合 feed_viewed/字典 v3/ 北极星不变/队列三项升第一波、ADR-021 Git 修订(main 更正/PR 情形触发/首发布重建 main/ 防泄漏 grep 先行) - mkdocs 挂「第三迭代」导航,build --strict 通过 Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
14 KiB
07 · M3 开工前证据审计与基线快照
角色:Evidence Collector(沿用 iteration-2/07 模式:每条声称附可复现命令与输出,拒绝空口断言) 审计日期:2026-09-08 · 只读审计,未改代码、未 commit、未动 mkdocs.yml 与 Reality Checker 分工:本报告不复跑测试套件与 E2E(运行态归他),只管证据链完整性、档案质量、静态计数与基线快照
1. M2 证据链审计
1.1 报告在档与导航挂载:30/30 + index,完整率 100%
ls docs/development/iterations/iteration-2/ | grep -c '^\([0-9]\|index\)' # → 31(01~30 + index.md)
grep -c "iteration-2/" mkdocs.yml # → 31
逐份核对结果:01-pm-task-breakdown.md ~ 30-device-verification-checklist.md 编号连续无断号,31 个文件与 mkdocs.yml 第 3464 行的 31 条导航一一对应(进展看板 + 0130),无孤儿文件、无空挂导航。另有非报告附件 openapi-pets-draft.yaml(第二波契约草案存档,14 号报告引用,不要求挂导航)。
注意口径:29 号收官总结第 21 行写"29 份入档"——写作当时属实;30 号(真机补验清单)系收官后由 e68b655 追加入档并挂导航,时间线自洽,不算矛盾。
1.2 ADR 断号检查:001~015 连续,终号 015
grep -oE "ADR-[0-9]+" docs/architecture/decisions.md | sort -u
# → ADR-001 ~ ADR-015,15 个,无断号
与 29 号总结"ADR 001~015"声称一致。
1.3 feature-checklist M2 三节(§7~§9)抽核 5 条状态声称
| # | 清单声称 | 实物证据(可复现) | 结论 |
|---|---|---|---|
| 1 | §7 "Flyway V3 pet_health 8 表 + V4 字典种子(28 品种/10 疫苗)" | grep -c "CREATE TABLE" V3__pet_health_baseline.sql → 8(breeds/pets/pet_owners/pet_weight_records/vaccine_catalog/pet_vaccinations/health_events/care_reminders);V4 两条 INSERT 值行数 28(breeds)+ 10(vaccine_catalog) |
✅ 逐字吻合 |
| 2 | §7 "宠物 CRUD + breeds 目录 23 例(六类路径 + 三角色矩阵)" | PetCrudIntegrationTest 14 例 + PetPermissionIntegrationTest 9 例 = 23(@Test 注解计数) |
✅ 吻合 |
| 3 | §7 "契约一致性测试(v1.2.0 字节级快照)" | api 侧快照文件在档且 sha256 与正典逐字节一致(见 §2.2);ContractConformanceTest 11 例在档 |
✅ 吻合 |
| 4 | §8 "pets 数据层……DTO 映射 62 例测试" | 22 号报告原文第 109 行为"本单(dev@7fb9031)126(+62,全绿)"——62 是该工单全量新增测试数(含 DTO 映射、repository、异常类型化等),非纯 DTO 映射例数 | ⚠️ 数字有出处,清单转述口径漂移(见 §6-G4) |
| 5 | §9 "事件字典 v2 白名单(pet 域 3 + health_record 域 7)……api@64c9b72" | EventDictionary.java 实数 pet 域 3 + health_record 域 7,与 06 号 §1.5 键集逐条一致(24 号报告已逐条对照);提交 64c9b72 在 api 历史中定位到 |
✅ 吻合 |
抽核之外顺带实证:§7 各接口测试例数声称(体重 8 / 疫苗 12 / 事件 11 / 提醒 10 / 摘要 12)与对应测试类 @Test 计数全部逐一吻合。
2. 契约档案审计
2.1 openapi.yaml v1.2.0 的 18 路径(逐一列出)
grep -nE "^ /" docs/api/openapi.yaml # 18 行
python3 -c "...yaml.safe_load..." # paths: 18, operations: 24, schemas: 45
| # | 路径 | # | 路径 |
|---|---|---|---|
| 1 | /api/v1/auth/register |
10 | /api/v1/pets/{petId}/weights |
| 2 | /api/v1/auth/login |
11 | /api/v1/vaccine-catalog |
| 3 | /api/v1/auth/refresh |
12 | /api/v1/pets/{petId}/vaccinations |
| 4 | /api/v1/auth/logout |
13 | /api/v1/vaccinations/{vaccinationId} |
| 5 | /api/v1/me |
14 | /api/v1/pets/{petId}/health-events |
| 6 | /api/v1/events |
15 | /api/v1/health-events/{eventId} |
| 7 | /api/v1/pets |
16 | /api/v1/pets/{petId}/care-reminders |
| 8 | /api/v1/pets/{petId} |
17 | /api/v1/care-reminders/{reminderId} |
| 9 | /api/v1/breeds |
18 | /api/v1/pets/{petId}/summary |
info.version: 1.2.0(第 4 行)。29 号声称"18 路径/24 操作/45 schema"三个数字全部复现吻合。
2.2 api 侧快照 sha256 与正典一致(字节级)
sha256sum docs/api/openapi.yaml \
patbond-api/patbond-pet/src/test/resources/contract/openapi-v1.2.0.yaml
# 二者均为 243fe6487bfa19018bddbfdb2cece16d9f81bc9718d3404501574677a4cd689d
✅ 快照存在且与正典逐字节一致,契约测试的"字节级快照锁"有实物支撑。
2.3 Flyway 迁移清单:V1~V4 齐全(单链归 patbond-user)
patbond-user/src/main/resources/db/migration/
├── V1__identity_media_baseline.sql
├── V2__create_platform_product_events.sql
├── V3__pet_health_baseline.sql # pet_health schema 8 表
└── V4__pet_health_dictionary_seed.sql # 28 品种 + 10 疫苗种子
无断号,pet 模块自身无迁移目录,与"迁移链仍归 patbond-user 单链"(清单 §7)一致。
3. 提交完整性
3.1 三仓 status:工作区全干净,与远端零偏差
git -C <repo> status -sb # 三仓均无未跟踪/未提交文件,无 ahead/behind 标记
| 仓库 | 分支 | 状态 |
|---|---|---|
| patbond-doc | main…origin/main | 干净,已同步 |
| patbond-api | dev…origin/dev | 干净,已同步 |
| patbond-flutter | dev…origin/dev | 干净,已同步 |
3.2 29 号收官索引的关键提交逐一定位(git log --oneline -25 + 逐哈希 git log -1)
doc 仓(10/10 定位到):1891d9b(开工 10 报告 + ADR-009~015)→ 2ceab6b(events 契约补录)→ 6025832/b04e93c(第一波收口)→ 511617b(契约冻结 v1.2.0)→ 222990e(第二波收口)→ b81c050(第三波收口)→ 23ce404(T2-19 文档收口)→ fcac68d(M2 收官)→ e68b655(30 号追加,现 HEAD)。
api 仓(11/11 定位到):49299fb(V3/V4)→ 0eae1c9(pet 骨架)→ 58576f8(ADR-013 移除 health_record_action)→ 8fbf444(T2-03)→ 825dde3(T2-04)→ 4c2653c(T2-05)→ d8303bf(T2-06)→ 3b27f9f(T2-07)→ 00f7dbd(T2-08)→ d026f2f(契约测试 T2-09)→ 64c9b72(字典 v2,现 HEAD,= 29 号声称收官 HEAD)。
flutter 仓(8/8 定位到):33b993c(持久化队列)→ 7fb9031(T2-11 数据层)→ 97a1f46(T2-12)→ 5b34fa3/c91f18a(T2-13)→ e186ba3/ba50332(T2-14)→ 720865b(E2E 脚本,现 HEAD,= 29 号声称收官 HEAD)。
E2E 实物:patbond-flutter/test_e2e_m2_manual.dart(777 行)在档,脚本内场景标号 [1/11]~[11/11] 恰 11 个,与 28 号"11/11 场景"声称的场景数吻合(复跑归 Reality Checker)。
4. 静态计数 vs 声称
4.1 后端 @Test:191,与声称一致
grep -rE "@(Test|ParameterizedTest)\b" --include="*.java" patbond-api \
| grep -v target | wc -l # → 191
| 模块 | @Test 数 |
|---|---|
| patbond-common | 3 |
| patbond-user | 68 |
| patbond-auth | 31 |
| patbond-pet | 89 |
| 合计 | 191 ✅ |
pet 模块内分布:CRUD 14 / 权限矩阵 9 / 体重 8 / 疫苗 12 / 事件 11 / 提醒 10 / 摘要 12 / 契约一致性 11 / 健康探针 1 / 骨架 1。
4.2 前端 test/testWidgets:272,与声称一致
grep -rE "^\s*(test|testWidgets)\(" patbond-flutter/test --include="*.dart" | wc -l # → 272
| 目录 | 例数 | 说明 |
|---|---|---|
| test/features/pets/ | 193 | 20 个文件(models 25、repository 22、detail_page 19、health_record_display 16 为大头) |
| test/analytics/ | 34 | 队列/存储/路由观察者/服务/会话 5 文件 |
| test/core/ | 21 | token_refresher 5 + 共享 widget 16 |
| test/features/auth/ | 18 | repository 10 + 登录/注册页各 4 |
| test/widgets/ + 根 | 6 | tag_pill 5 + widget_test 1 |
| 合计 | 272 ✅ |
静态注解计数与运行期用例数吻合,说明无参数化展开偏差;实际运行全绿与否归 Reality Checker 复核。
5. M3 开工基线快照(M3 收官对比基准)
5.1 三仓 HEAD(完整哈希)
| 仓库 | 分支 | HEAD | 末次提交 |
|---|---|---|---|
| patbond-doc | main | e68b6553cadaccb3b29fbbca3d44df04473c506f |
docs: 真机补验独立操作清单(30 号,M2 挂起项) |
| patbond-api | dev | 64c9b72fd19cec916d964e2468330ede5fddfb81 |
feat: 事件字典 v2 白名单扩充 pet/health_record 域 10 事件(T2-17 后端) |
| patbond-flutter | dev | 720865bcb93fca5fe49340b77807fb174d193b91 |
test: M2 E2E 烟囱脚本(T2-18 收官) |
5.2 核心数字
| 维度 | 基线值(静态计数) |
|---|---|
| 后端 @Test | 191(common 3 / user 68 / auth 31 / pet 89) |
| 前端 test/testWidgets | 272(pets 193 / analytics 34 / core 21 / auth 18 / 其他 6) |
| openapi.yaml | v1.2.0,18 路径 / 24 操作 / 45 schema(清单见 §2.1),sha256 243fe648…4cd689d,api 侧快照字节级一致 |
| Flyway | V1~V4(单链归 patbond-user;pet_health 8 表 + 字典种子 28 品种/10 疫苗) |
| ADR 终号 | ADR-015 |
| E2E 资产 | test_e2e_manual.dart(M1)+ test_e2e_m2_manual.dart(M2,11 场景) |
5.3 模块与端口表
| 模块 | 端口 | 说明 |
|---|---|---|
| patbond-auth | :8081(PATBOND_AUTH_PORT) |
application.yml |
| patbond-user | :8082(PATBOND_USER_PORT) |
application.yml;含 analytics 接收端与 Flyway 单链 |
| patbond-pet | :8083(PATBOND_PET_PORT) |
仅 application.yml.sample(本地需从 sample 复制);compose 映射 8083:8083 |
| postgres | 容器内 :5432 | postgres:18,不对宿主机发布端口(compose 注释:调试临时加 15432:5432) |
| patbond-common | — | 共享库,无端口 |
5.4 事件白名单基线(EventDictionary 实数:共 22 事件)
patbond-api/patbond-user/src/main/java/com/patbond/patbond/user/analytics/EventDictionary.java:
- auth 域 11:
auth_register_started/auth_register_succeeded/auth_register_failed/auth_login_succeeded/auth_login_failed/auth_token_refresh_succeeded/auth_token_refresh_failed/auth_logout/auth_session_restore_started/auth_session_restore_succeeded/auth_session_restore_failed - 通用 1:
page_viewed(v2 正稿) - pet 域 3:
pet_create_started/pet_create_succeeded/pet_create_failed - health_record 域 7:
health_record_create_started/health_record_create_succeeded/health_record_create_failed/health_record_viewed/health_record_edit_succeeded/health_record_edit_failed/health_record_deleted - 已废弃(ADR-013,测试锁定拒绝):
health_record_action
客户端实际发射面(grep -rhoE "'(auth_|pet_|health_record_|page_viewed)…'" lib/):15 个——auth 5(register/login 成败 + logout)+ page_viewed + pet 3 + health_record 6。白名单侧多出的 7 个中,auth 6 个为服务端字典预置(token_refresh/session_restore/register_started 客户端未挂),health_record_deleted 留待删除端点(27 号已声明合理留白)。
6. 证据缺口清单
| # | 缺口 | 出处 | 定级 |
|---|---|---|---|
| G1 | "字典 v2 13 事件"口径不可复现:27 号 §"埋点端到端贯通"写"13 个事件(pet 域 3 + health_record 域 6 + page_viewed 正稿)"——括号内实为 10;29 号沿用"13 事件"。从任何实数(白名单总 22 / v2 增量 10 / v2 客户端挂接 10 / 客户端发射面 15)均凑不出 13 | 27 号第 27 行、29 号第 20 行 | 低(数字笔误级,但收官总结是对外口径,M3 引用时应改写为"v2 增量 10、白名单共 22") |
| G2 | CI 状态声称离线不可复核:29 号收官索引 api"CI success"、doc"strict 通过"无法在本机复现(需按 M2 建立的 Gitea commit status API 实查惯例取证);flutter 一栏写"待本提交 CI"且 30 号追加后未回填终态结论——三仓收官 CI 是否全绿目前档内无闭环证据 | 29 号 §5 | 中(M3 开工前建议补一次三仓 HEAD 的 commit status 实查并回填) |
| G3 | feature-checklist 头部哈希滞后:头部"最后更新"写 flutter ba50332,终态 HEAD 为 720865b(E2E 脚本提交)。272 计数在 HEAD 仍成立,非事实错误,但对账时会引起哈希对不上 |
feature-checklist.md 第 5 行 | 低 |
| G4 | "DTO 映射 62 例测试"转述漂移:22 号原文的 +62 是 T2-11 工单全量新增测试数,清单 §8 转述成了"DTO 映射 62 例" | feature-checklist §8 | 低 |
| G5 | 真机两项仍挂起(非新缺口,登记延续):Android 事件落库观察、SessionTracker 30 分钟手测——方案 A 挂起,操作清单已独立成 30 号 | 29 号 §4、30 号 | 中(M3 期间设备到位即补,预计 0.5 天) |
除上述外,M2 档案的可复现声称(报告数、导航、ADR、契约三数字、快照哈希、Flyway、双端测试计数、关键提交链、E2E 场景数)全部实证通过:抽核与全查合计 40+ 条声称,仅 G1/G3/G4 三处口径瑕疵,无一处"声称的实物不存在"。
7. 审计结论
- 证据链完整率:30/30 报告 + index 在档且挂导航(100%);ADR-001~015 无断号;关键提交 29/29 在三仓历史定位。
- 静态计数:后端 191、前端 272,与收官声称逐一吻合;契约 18/24/45 三数字与字节级快照全部复现。
- 基线快照:已建立(§5),M3 收官时以本节为对比基准。
- 缺口:5 项(G1~G5),无阻塞级;建议 M3 开工时顺手处理 G2(CI 实查回填)与 G1(口径改写)。
审计执行:Evidence Collector · 2026-09-08 本报告未挂导航(不动 mkdocs.yml 为本次硬约束,待 M3 文档收口时统一挂载)