docs: M2 开工前分析 10 份报告入档 + ADR-009~015 拍板决策
CI / docs-build (push) Successful in 1m3s

- iteration-2 报告 01-08(PM 拆解/后端/Flutter 评估/现实核查/UI 规范/埋点规划/证据基线/Git 规划),04、06 已由正式角色复核定稿
- mkdocs 挂「第二迭代」导航,build --strict 通过
- ADR-009 新建 patbond-pet 模块、ADR-010 照片剪出 M2、ADR-011 dev 主干/master 发布、ADR-012 北极星与 H1-H4、ADR-013 废弃 health_record_action、ADR-014 DEBT-1 随 M2、ADR-015 照护人邀请后置

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
This commit is contained in:
2026-09-07 13:54:35 +08:00
parent 5537f92227
commit 1891d9b7b4
10 changed files with 2007 additions and 0 deletions
@@ -0,0 +1,346 @@
# Patbond 第二迭代任务分解(M2 宠物健康档案)
> 作者:Senior Project Manager
> 日期:2026-09-07
> 依据:`patbond-doc/docs/development/development-plan.md`(第 7 节 M2、第 6.2 节 Pets 接口、第 9/10 节质量门禁与 DoD)、`iterations/iteration-1/20-iteration-1-summary.md`(收官总结与遗留清单)、`docs/architecture/decisions.md`ADR-001~008)、`docs/database/patbond_postgresql.sql``pet_health` schema 8 张表)
> 编号约定:本迭代工单以 `T2-` 前缀编号(T2-01 起),避免与第一迭代 T0-x/T1~T12 冲突。
> 范围声明:严格限定为 M2 宠物健康档案。社区(M3)、AI 创作(M4)、预约(M5)不在本迭代范围;发现范围外需求一律记入 backlog。
---
## 1. 范围界定与依据
### 1.1 开发计划 M2 原文(正典依据)
开发计划第 7 节 M2 定义(引用原文要点):
- 目标:"替换 Flutter 档案页的本地宠物和疫苗数据。"
- "实现宠物、照护权限、体重、疫苗、健康事件和提醒接口。"
- "校验当前用户对宠物的 owner/caregiver/viewer 权限。"
- "Flutter 接入真实列表、详情、编辑、加载、空态和错误态。"
- "体重、疫苗进度、下次接种和月度花费从事实表聚合生成。"
- 验收标准:"数据可跨设备读取;无权限用户不能访问宠物;并发更新返回明确冲突;关键流程具备 API 集成测试和 Flutter 组件测试。"
第 6.2 节第一批接口中属于本迭代的端点:
| 端点 | 用途 |
| --- | --- |
| `GET/POST /api/v1/pets` | 查询、新建宠物 |
| `GET/PATCH /api/v1/pets/{petId}` | 宠物详情与更新 |
| `GET/POST /api/v1/pets/{petId}/weights` | 体重记录 |
| `GET/POST/PATCH /api/v1/pets/{petId}/vaccinations` | 疫苗记录 |
| `GET/POST /api/v1/pets/{petId}/health-events` | 健康时间线 |
数据模型依据:`pet_health` schema 共 8 张表(breeds、pets、pet_owners、pet_weight_records、vaccine_catalog、pet_vaccinations、health_events、health_event_media、care_reminders——含关联表 9 个对象),字段、约束、状态机均已在 bootstrap SQL 定稿评审。
### 1.2 与第一迭代总结口径的差异(须拍板,见 §4)
第一迭代总结把 M2 目标写为"档案 CRUD、照片管理、体重/**体温**记录、疫苗/驱虫提醒",与开发计划 M2 原文存在三处扩张,PM 逐条对照数据模型后的结论:
1. **照片管理**`pets.avatar_asset_id``pet_vaccinations.certificate_asset_id``health_event_media` 均引用 `media.assets`,但媒体上传流程(M1 后半段的 `POST /api/v1/media/uploads`)第一迭代未实现,且**对象存储供应商至今未拍板**(第一迭代决策清单 D4 遗留)。照片管理不是 M2 原文要求,纳入与否见决策 D2-1。
2. **体温记录**`pet_health` schema **没有体温表**。最接近的承载是 `health_events``measurement` 事件类型。是否需要结构化体温数据见决策 D2-4,本拆解默认不建新表。
3. **驱虫提醒**:数据模型已支持(`health_events.event_type='deworming'` + `care_reminders.reminder_type='deworming'`),属 M2 原文"提醒接口"范围内,纳入。
### 1.3 本迭代 MVP 范围(PM 建议口径,待 §4 拍板确认)
- **纳入**:宠物 CRUD(含品种目录)、pet_owners 权限校验框架、体重记录、疫苗记录(含疫苗目录、系列/剂次、scheduled→completed 状态机)、健康事件时间线、照护提醒(app 内列表,无推送)、四项聚合(最新体重、疫苗进度、下次接种、月度花费)、Flutter 档案页全量替换真实数据、两项高优先遗留埋点。
- **默认剪出(待拍板)**:照片/媒体上传、体温专表、共同照护人邀请流程(权限**校验**必须实现,邀请**交互**可后置)、提醒推送通知(通知系统属 M6)。
---
## 2. 工单列表
预估规模口径沿用第一迭代:S ≈ 半天内,M ≈ 1-2 天,L ≈ 3-5 天(含测试与文档)。
### A 组:数据与工程基础(后端)
#### T2-01 Flyway V3pet_health schema baseline 与种子数据分离
- **仓库**patbond-api(迁移脚本),patbond-doc(迁移说明)
- **描述**:从 bootstrap SQL 提取 `pet_health` 全部表结构为 Flyway V3 迁移;breeds、vaccine_catalog 的开发种子数据独立为不进生产的脚本(沿用第一迭代 identity/media 的做法)。
- **关键技术裁剪(必须遵守)**bootstrap SQL 第 1156~1166 行为 `pet_vaccinations`/`health_events``provider_id``booking_id` 增加了指向 `marketplace.providers`/`marketplace.bookings` 的外键。marketplace schema 属 M5,本迭代**不迁移**V3 必须**剥离这四条跨 schema 外键**(字段保留为裸 uuid 可空列),M5 迁移 marketplace 时再以新版本迁移补回。同理 `updated_at` 触发器依赖的公共函数需确认已在 V1 建立或随 V3 建立。
- **验收标准**
- 全新 postgres:18Testcontainers)上 V1→V2→V3 全量迁移一次成功,表结构与 bootstrap SQL 一致(跨 schema 外键除外,差异写入迁移说明)。
- 种子数据脚本与结构迁移分离,不进正式环境。
- `./mvnw clean test` 全绿(既有 82 测试不回归)。
- **依赖**:无(第一波首项)。
- **规模**M
#### T2-02 宠物健康后端模块骨架与鉴权接入
- **仓库**patbond-api
- **描述**:按开发计划 4.1 节"按迭代增加宠物健康模块;模块边界与数据库 schema 对齐",建立宠物健康业务模块(新建 Maven 模块 vs 并入现有服务见决策 D2-2,未拍板前先按 PM 建议方案搭骨架);复用第一迭代 JWT 资源侧校验,实现"当前用户"解析注入;模块只读写 `pet_health` schema。
- **验收标准**
- 模块编译入构建链,`./mvnw clean test` 全绿。
- 携带有效 access token 的请求能解析出当前用户 UUID;无 token / 过期 token 返回 401 + 既有错误码契约(40100 系)。
- Docker Compose 编排同步纳入新模块(若 D2-2 选独立服务)。
- **依赖**:D2-2 拍板(可先按建议方案开工,方案变更成本在骨架期最低)。
- **规模**M
### B 组:后端接口纵切
#### T2-03 宠物 CRUD 与 pet_owners 权限框架
- **仓库**patbond-api
- **描述**:实现 `GET/POST /api/v1/pets``GET/PATCH /api/v1/pets/{petId}` 与品种目录查询(breeds 只读列表,按 species 过滤)。创建宠物时当前用户自动成为 `pet_owners` 的 primary owner;所有 `/pets/**` 请求经统一权限校验(owner/caregiver 可写、viewer 只读、无关系 404/403,语义在契约中定死);`PATCH` 使用 `version` 乐观锁,冲突返回明确错误码;`status` 流转(active/archived 等)按数据库约束实现;软删除语义遵守 `ck_pets_deleted` 约束。
- **验收标准**
- 创建→列表→详情→更新→归档全链路走真实 PostgreSQL,重启不丢数据。
- 无权限用户访问他人宠物被拒绝(错误码与 HTTP 状态码在契约定死并有测试)。
- 并发更新(version 过期)返回明确冲突错误,有集成测试。
- breed_id 与 custom_breed_name 互斥校验(`ck_pets_breed`)应用层与数据库一致。
- **依赖**T2-01、T2-02。
- **规模**L
#### T2-04 体重记录接口
- **仓库**patbond-api
- **描述**`GET/POST /api/v1/pets/{petId}/weights`。列表 cursor 分页(`measured_at DESC, id DESC`,与既有索引对齐);创建校验 `weight_kg` 区间(>0 且 ≤500);写接口支持 `Idempotency-Key`(第 6.1 节要求)。
- **验收标准**
- 分页不丢失不重复;参数越界返回规范错误体。
- 相同 Idempotency-Key 重试不产生重复记录,有测试。
- 权限校验复用 T2-03 框架(viewer 只读)。
- **依赖**T2-03。
- **规模**M
#### T2-05 疫苗目录与疫苗记录接口
- **仓库**patbond-api
- **描述**vaccine_catalog 只读查询(按 species);`GET/POST/PATCH /api/v1/pets/{petId}/vaccinations`series_key + dose_no 唯一性(非 cancelled)、scheduled/completed/cancelled 状态机及日期约束(`ck_vaccination_dates`)、`next_due_on` 维护、`version` 乐观锁。`certificate_asset_id``provider_id``booking_id` 本迭代不开放写入(照片待 D2-1、预约属 M5),字段在契约中不出现或标记只读。
- **验收标准**
- 状态机非法迁移被拒绝并返回稳定错误码;同系列同剂次重复登记返回冲突。
- completed 必须带 administered_on、scheduled 必须带 planned_on(与数据库约束一致,应用层先行校验)。
- 集成测试覆盖成功、参数错误、不存在、无权限、并发冲突、幂等重试六类路径(第 9 节要求)。
- **依赖**T2-03。
- **规模**L
#### T2-06 健康事件时间线接口
- **仓库**patbond-api
- **描述**`GET/POST /api/v1/pets/{petId}/health-events`,建议补 `PATCH /api/v1/health-events/{eventId}`(编辑标题/备注/金额,乐观锁)。六类事件类型(medical/feeding/deworming/grooming/measurement/note);`amount_cents` 整数分(第 4.3 节);`occurred_at DESC` cursor 分页;`created_by_user_id` 记录操作者。`health_event_media` 本迭代不实现(随 D2-1)。
- **验收标准**
- 时间线分页正确;金额只收整数分且非负。
- 事件类型白名单校验与数据库约束一致。
- 六类测试路径覆盖同 T2-05。
- **依赖**T2-03。
- **规模**M
#### T2-07 照护提醒接口
- **仓库**patbond-api
- **描述**care_reminders 的列表/创建/状态流转(pending→completed/dismissedcompleted 必须写 completed_at,与 `ck_care_reminder_completed` 一致)。四类提醒类型(deworming/checkup/medication/other)。**仅 app 内数据接口,不做推送**(通知系统属 M6,见决策 D2-5)。
- **验收标准**
- 提醒可创建、按 due_at 查询待办、标记完成/忽略;状态与 completed_at 一致性有测试。
- 权限校验复用 T2-03 框架。
- **依赖**T2-03。
- **规模**M
#### T2-08 档案聚合摘要接口
- **仓库**patbond-api
- **描述**:实现档案页摘要所需聚合(建议 `GET /api/v1/pets/{petId}/summary`):最新体重、疫苗进度(completed 剂次/总剂次)、下次接种(scheduled 中最近 planned_on 或最近 next_due_on)、当月花费(health_events.amount_cents 按月求和)。全部从事实表实时聚合,**不持久化展示字符串**(第 4.3 节红线);聚合口径逐项写入契约描述。
- **验收标准**
- 各聚合值有集成测试锁定口径(含空数据、跨月边界、cancelled 疫苗不计入)。
- 时间按 `timestamptz` 存储、ISO 8601 传输,月度边界按客户端传入时区或明确定义的服务端口径(写入契约,避免歧义)。
- **依赖**T2-04、T2-05、T2-06。
- **规模**M
### C 组:契约与测试
#### T2-09 OpenAPI 契约扩展与冻结
- **仓库**patbond-doc`docs/api/openapi.yaml`),patbond-api(契约测试保证一致)
- **描述**:在既有 5 端点契约上扩展 pets 域全部端点(宠物、品种、体重、疫苗、目录、事件、提醒、摘要)。沿用既定规范:`/api/v1` 前缀、camelCase、UUID 字符串、统一信封、稳定业务错误码(pets 域新错误码段与 401/403/404/409 语义定死)、cursor 分页参数形态、`Idempotency-Key``version` 字段。**起草与 T2-03~05 并行,冻结须在 T2-03 权限/错误语义与 T2-08 聚合字段定型之后**——冻结是第三波前端联调的放行闸门(沿用第一迭代验证过的模式)。
- **验收标准**
- 契约文件评审通过;契约测试在 CI 中验证实际响应与文档一致。
- `mkdocs build --strict` 通过(契约文件更新不涉及导航变更)。
- 冻结后任何字段变更须显著上报,两端同步修改。
- **依赖**T2-03(错误/权限语义)、T2-08(聚合字段);起草仅依赖 §1.1 端点表。
- **规模**M
#### T2-10 后端集成测试滚动补齐与 CI
- **仓库**patbond-api
- **描述**:随 B 组各工单滚动补齐 Testcontainerspostgres:18)集成测试,交付前每单必须全绿(沿用第一迭代"每波 `./mvnw clean test` 必绿"纪律);V3 迁移在全新实例执行一次的校验并入 CI。本单为横切验收单,不单独排人。
- **验收标准**
- 每个业务接口覆盖成功、参数错误、资源不存在、无权限、并发冲突、幂等重试(第 9 节六类)。
- **caregiver/viewer 权限路径必须有测试覆盖**:邀请流程若按 D2-3 后置,则用测试数据直接写 pet_owners 构造三种角色场景,避免"权限代码存在但从未被验证"。
- Gitea Actions ci.yml 全绿;CI 时长若超 10 分钟记录并评估分层。
- **依赖**:随 T2-03~T2-08 滚动。
- **规模**M(分摊在各单内)
### D 组:Flutter 客户端
#### T2-11 pets feature 状态拆分与 API Client
- **仓库**patbond-flutter
- **描述**:按开发计划 4.2 节把宠物档案状态从 `AppState` 拆出独立 pets featureController → Repository → API Client 分层,对齐第一迭代 auth feature 的既有结构);依据 T2-09 冻结契约实现 DTO 与 Client(宠物、品种、体重、疫苗、事件、提醒、摘要),统一错误码解析复用既有网络层与 token 拦截。
- **验收标准**
- DTO 映射有单元测试;错误响应映射为类型化错误。
- 不再从 `AppState` 读写宠物/疫苗 demo 数据(体重、疫苗进度等展示字符串全部改为由服务端事实字段计算)。
- **依赖**:T2-09 冻结。UI 无关的分层骨架可提前与后端并行。
- **规模**M
#### T2-12 宠物列表、详情与编辑页接入真实数据
- **仓库**patbond-flutter
- **描述**:档案页(`lib/features/pets/pets_page.dart`)替换为真实列表/详情/创建/编辑:品种选择(目录接口 + 自定义品种互斥)、性别/生日/芯片号等字段对齐数据模型;**所有网络页面覆盖 loading、empty、error、retry 四态**(第 9 节硬要求);编辑冲突(409)给出明确的用户提示与刷新路径。头像照片按 D2-1 裁决处理(默认保留本地占位图,不做上传)。
- **验收标准**
- 新用户空态 → 建档 → 列表/详情展示全链路走真实后端。
- 四态齐备并有 widget 测试;乐观锁冲突提示有测试。
- **依赖**:T2-11;UI 稿可在第一波先行出设计(含四态与空态)。
- **规模**L
#### T2-13 体重与疫苗模块接入
- **仓库**patbond-flutter
- **描述**:体重录入与历史列表(分页加载);疫苗登记(选目录、系列/剂次、计划/完成状态)、疫苗进度与"下一针"改从 T2-08 摘要接口取数(替换 demo 的 `vaccines.reminderVaccine` 等本地字符串)。
- **验收标准**
- 体重与疫苗数据在另一登录设备(或清空本地数据重登)可见——对应 M2"跨设备读取"验收。
- 疫苗状态机操作的非法路径(如未填接种日期就标完成)被前端拦截且后端兜底。
- 相关 widget/单元测试补齐。
- **依赖**T2-11、T2-12。
- **规模**L
#### T2-14 健康时间线与提醒页接入
- **仓库**patbond-flutter
- **描述**:健康事件时间线(六类事件、金额录入以元展示/整数分传输、分页);照护提醒列表与完成/忽略操作;档案页"月度花费"改从摘要接口取数。demo 中硬编码的"健康提醒:已经半年没有进行体内外驱虫"改为真实提醒数据驱动。
- **验收标准**
- 时间线与提醒四态齐备;金额展示与传输换算有单元测试。
- 无提醒/无事件时空态正确。
- **依赖**T2-11、T2-12。
- **规模**M
### E 组:遗留项与收口
#### T2-15 遗留埋点:sessionId 生命周期(高优先,第一波插入)
- **仓库**patbond-flutter
- **描述**:第一迭代遗留 §1:引入 `WidgetsBindingObserver` 监听 app 前后台切换,定义会话超时与 sessionId 重建规则,修复"sessionId 只在退出时清空"的缺陷。
- **验收标准**:进后台超时回前台生成新 sessionId;规则有单元测试;不依赖 M2 契约,可与后端第一波并行。
- **依赖**:无。
- **规模**S
#### T2-16 遗留埋点:page_viewed 路由埋点(高优先,第一波插入)
- **仓库**patbond-flutter
- **描述**:第一迭代遗留 §2:接入 `RouteObserver` 挂接 `page_viewed` 事件(事件定义沿用报告 13 规范)。
- **验收标准**:主要页面路由切换产生 page_viewed 事件并能落库(复用既有 /api/v1/events 链路);有测试。
- **依赖**:无。
- **规模**S
#### T2-17 埋点:health_record_action 挂接与 M2 事件
- **仓库**patbond-flutter(挂接),patbond-doc(事件表更新)
- **描述**:第一迭代预留的 `health_record_action` 挂接点在 M2 档案功能落地后接通(建档、体重录入、疫苗登记、事件记录等动作);后端事件白名单同步扩充。埋点不得含健康敏感明文(沿用隐私红线)。
- **验收标准**:关键健康操作产生事件并落库;白名单与文档同步;有测试。
- **依赖**T2-12~T2-14(随页面落地滚动挂接)。
- **规模**S
#### T2-18 E2E 烟囱测试与真机联调收官
- **仓库**patbond-flutter(用例),patbond-apicompose 环境),patbond-doc(证据归档)
- **描述**:沿用第一迭代收官战模式:compose 起后端 → 真实链路烟囱:登录 → 建档 → 记体重 → 登记疫苗 → 记健康事件 → 摘要数值核对 → 第二账号访问该宠物被拒 → 第二设备(或重装态)同账号读到全部数据。收集 HTTP transcript(脱敏)、数据库查询证据、门禁输出。
- **验收标准**:烟囱场景全绿;契约偏差 0 个;M2 四条验收标准(跨设备、无权限拒绝、并发冲突明确、双端测试齐备)逐条有证据。
- **依赖**T2-05、T2-08、T2-13、T2-14。
- **规模**M
#### T2-19 文档与迭代收口
- **仓库**patbond-doc
- **描述**OpenAPI 定稿归档、feature-checklist 增补 M2 条目、迭代报告归档、任务板更新与收官总结。iteration-2 报告目录的 `mkdocs.yml` 导航条目由文档维护者在收口提交时统一添加(本拆解报告本身不改 mkdocs.yml)。
- **验收标准**`mkdocs build --strict` 通过;报告索引完整可还原全貌。
- **依赖**:各波交付。
- **规模**S
---
## 3. 波次划分与关键路径
沿用第一迭代验证过的"波次并行 + 契约冻结先行"模式。
### 第一波(并行开工,无互锁)
| 并行线 | 工单 | 说明 |
| --- | --- | --- |
| 后端数据基础 | T2-01 → T2-02 | 关键路径起点,一人连续负责 |
| 契约起草 | T2-09(起草态) | 按 §1.1 端点表 + 数据模型先出草案,随 T2-03 收敛 |
| 前端遗留埋点 | T2-15、T2-16 | 与 M2 契约零耦合,第一波消化掉两项高优先遗留 |
| UI 设计 | 档案页/四态/空态设计稿(供 T2-12) | 不占关键路径 |
### 第二波(后端纵切,契约收敛)
| 并行线 | 工单 | 说明 |
| --- | --- | --- |
| 后端主线 | T2-03 → T2-04/T2-05/T2-06/T2-0703 后三线可并行)→ T2-08 | T2-03 权限框架是全部业务单的前置 |
| 前端骨架 | T2-11 的分层骨架(不依赖契约的部分) | Repository/状态骨架先行 |
| 测试滚动 | T2-10 | 随各单交付即测即绿即提交 |
**波末闸门:T2-09 契约冻结**(条件:T2-03 权限/错误语义定型 + T2-08 聚合字段定型)。不冻结不放行第三波前端联调,偏差须显著上报。
### 第三波(冻结契约下两端并行)
| 并行线 | 工单 | 说明 |
| --- | --- | --- |
| 前端主线 | T2-11(完成)→ T2-12 → T2-13 / T2-14 | 12 完成后 13、14 可两人并行 |
| 后端旁路 | 契约测试补齐、种子数据完善、性能核对 | 不占关键路径 |
| 埋点 | T2-17 | 随页面落地滚动挂接 |
### 第四波(收官)
T2-18 E2E 烟囱 → T2-19 文档收口 → 任务板更新与验收报告。
### 关键路径
```text
T2-01 → T2-02 → T2-03(L) → T2-05(L) → T2-08 → [T2-09 冻结] → T2-11 → T2-12(L) → T2-13(L) → T2-18
```
四个 L 工单串在关键路径上,是周期决定因素。压缩手段:T2-09 草案与 T2-11 骨架前移(已排入一、二波);T2-04/06/07 走旁路不占主线;T2-12 的 UI 稿第一波先行。
---
## 4. 需要用户拍板的决策清单
以下决策 PM 只给建议,**不替用户拍板**。D2-1~D2-3 直接影响工单定稿,建议开工前优先裁决。
| # | 决策事项 | 影响 | PM 建议(仅供参考) |
| --- | --- | --- | --- |
| D2-1 | **照片/媒体是否纳入 M2**:宠物头像上传、疫苗证书、健康事件附件均依赖媒体上传流程(M1 遗留未做)与对象存储供应商(第一迭代 D4 至今未定) | 阻塞 T2-12 头像、T2-05 证书字段、health_event_media;若纳入需增补媒体上传专项工单(约 +1 L) | M2 首版**不含**照片上传,档案先跑通结构化数据;对象存储选型(建议 S3 兼容,如自建 MinIO 起步)拍板后以独立专项插入 M2 末波或 M3 |
| D2-2 | **后端模块归属**:新建独立宠物健康服务(对齐"模块边界与 schema 对齐"+ 独立部署)vs 作为模块并入 patbond-user 进程(降低双人团队运维面) | 决定 T2-02 骨架形态、compose 编排、CI 构建时长 | 新建 Maven 模块 `patbond-pet`(独立数据所有权),**部署形态倾向与 user 同进程或同 compose 独立容器均可接受**,请结合第一迭代 D2(单体 vs 多服务)一并裁决 |
| D2-3 | **共同照护人邀请流程是否入 M2**pet_owners 支持 owner/caregiver/viewer,但"邀请另一个用户"需要检索用户、发出/接受邀请等交互 | 决定 T2-03 是否扩为含邀请端点(约 +1 M)与前端邀请页 | M2 只做"创建者即 primary owner"+ 完整权限**校验**框架(测试数据覆盖三角色),邀请**交互**后置 M3+;这样 M2 验收标准"无权限用户不能访问"仍可完整验证 |
| D2-4 | **体温记录**:迭代一总结提及,但数据模型无体温表 | 若要结构化体温需新表与新迁移(超出已评审模型) | 用 `health_events``measurement` 类型承载文字化记录,不建新表;若产品明确要体温曲线图,另立数据模型变更提案再排期 |
| D2-5 | **提醒的通知形态**care_reminders 首版是否仅 app 内列表(无系统推送/本地通知) | 推送涉及通知渠道选型(platform.notifications 属 M6 | 首版仅 app 内列表 + 到期排序展示;推送后置 M6 |
| D2-6 | **breeds / vaccine_catalog 目录数据来源**:开发种子够用,但正式目录(犬猫品种表、疫苗名录)内容与量级谁提供、何时定稿 | 不阻塞开发(seed 兜底),影响上线数据质量 | 开发期用 seed(每 species 各 10~20 条常见项);正式目录数据作为独立内容任务由产品侧供稿 |
| D2-7 | **宠物删除语义**:前端提供什么入口——归档(archived)/ 软删除(deleted/ 不提供 | 影响 T2-03 状态流转范围与 T2-12 交互 | 首版仅提供"归档",软删除接口保留但前端不出入口,避免误删争议 |
| D2-8 | **中优先遗留是否纳入 M2**access token 黑名单、/internal 改 mTLS、auth_sessions 清理调优、埋点完善其余项(队列持久化等) | 纳入则挤占 M2 周期 | **不纳入**,维持技术债清单,M3 或加固阶段统一处理(TagPill 设计债同此) |
---
## 5. 遗留项插入位置汇总
| 遗留项(第一迭代总结编号) | 优先级 | 插入位置 |
| --- | --- | --- |
| 埋点 sessionId 生命周期(§1 | 高 | **T2-15,第一波**,独立工单 |
| page_viewed 路由埋点(§2 | 高 | **T2-16,第一波**,独立工单 |
| health_record_action 挂接(§7 之一) | 中(M2 天然落点) | **T2-17,第三波**随页面滚动挂接 |
| access token 黑名单(§4 | 中 | 不入 M2(待 D2-8 确认),技术债清单 |
| /internal 改 mTLS(§5 | 中 | 不入 M2(待 D2-8 确认),需先补 ADR |
| auth_sessions 清理调优(§6) | 中 | 不入 M2,性能阶段处理 |
| 埋点完善其余 4 项(§7) | 中 | 不入 M2;后端事件查询端点若 T2-17 验证需要可顺手做,超出即止 |
| TagPill 对比度设计债(§8) | 低 | 不入 M2,设计系统升级时统一处理 |
---
## 6. 风险清单
| # | 风险 | 影响 | 缓解措施 |
| --- | --- | --- | --- |
| R1 | **未提交/未推送风险**(第一迭代 R3 教训:两天工作量曾只存在于工作区) | 误操作全损;协作与 CI 失效 | 沿用已验证纪律:**每波每单交付即提交即推送**;PM 任务板每波核对三仓 `git status`。开工时基线:三仓工作区干净、与远端同步(2026-09-07 已核实) |
| R2 | **契约偏差风险**:pets 域端点数量约为第一迭代 4 倍,聚合字段口径(月度边界、进度分母)最易两端理解不一 | 联调返工 | 冻结闸门制度不放松;聚合口径在契约中逐字段写清(含时区口径);偏差显著上报,禁止任一端私改 |
| R3 | **V3 迁移照抄 bootstrap SQL 的跨 schema 外键**(第 1156~1166 行引用 marketplace) | 迁移在干净库直接失败,或被迫提前迁移 marketplace | 已写入 T2-01 描述为强制裁剪项;迁移说明记录差异与 M5 补回计划;Testcontainers 全新库验证兜底 |
| R4 | **对象存储未定拖累范围**:若 D2-1 拍板"要照片"而供应商未定 | T2-12/T2-05 范围反复 | 决策清单置顶 D2-1;默认口径按"不含照片"排期,拍板含照片则显式加 1 个 L 工单并顺延 |
| R5 | **权限路径测试盲区**:邀请流程后置时,caregiver/viewer 无自然产生入口 | "权限代码存在但从未验证",M2 验收标准落空 | T2-10 明确要求用测试数据直接构造三角色场景;E2E(T2-18)含第二账号拒绝场景 |
| R6 | **范围膨胀**:迭代一总结口径(照片/体温)比开发计划 M2 原文宽 | 周期失控、返工 | 本报告 §1.2 已逐条对照数据模型澄清;一切扩张走 §4 拍板,未拍板按 PM 建议默认剪出 |
| R7 | **CI 时长增长**:测试数将从 82 大幅增加,Testcontainers 全跑 | CI 反馈变慢、门禁被绕过 | T2-10 记录每波 CI 时长,超 10 分钟评估按模块分层执行;不降低"提交前全绿"标准 |
| R8 | **单接口面过宽的估算风险**:疫苗状态机 + 系列/剂次约束复杂度接近第一迭代 JWT 会话单 | T2-05 拖关键路径 | T2-05 已按 L 估算并置于关键路径显式管理;catalog 只读部分可先行拆出交付 |
| R9 | **文档导航遗漏**iteration-2 目录需入 mkdocs 导航,但本迭代规则限制随手改 mkdocs.yml | `mkdocs build --strict` 门禁或导航缺失 | 归入 T2-19 由文档维护者收口提交时统一处理,收口清单显式含此项 |
---
## 7. 质量要求(对全部工单生效)
- 遵守开发计划第 10 节 DoD:不依赖 Demo 常量;权限、校验、幂等、并发已处理;文档同步更新;干净环境可复现。
- 沿用既定契约规范:camelCase、UUID 字符串、ISO 8601 + timestamptz、金额整数分、统一信封与稳定错误码、cursor 分页、Idempotency-Key、version 乐观锁。
- 不提交任何密码、token、密钥;日志与埋点不含健康敏感明文与手机号全文。
- 自动化测试一律 Testcontainers postgres:18ADR-006/008);每单交付 `./mvnw clean test` / `flutter analyze` + `flutter test` 全绿。
- 所有网络页面四态(loading/empty/error/retry)齐备。
- 本迭代不实现社区、AI、预约的任何接口或页面;范围外需求记 backlog。
## 8. 工单统计
- 工单总数:**19**(数据与工程基础 2 + 后端接口 6 + 契约与测试 2 + Flutter 4 + 遗留与收口 5
- 规模分布:S × 5、M × 10、L × 4
- 关键路径长度:9 个工单(T2-01 → T2-02 → T2-03 → T2-05 → T2-08 → 冻结 → T2-11 → T2-12 → T2-13 → T2-18),其中 L × 4
- 待拍板决策:**8 项**(D2-1~D2-8,前三项建议开工前裁决)