Files
patbond-doc/docs/development/iterations/iteration-1/01-pm-task-breakdown.md
T
lixi 209021e7d2 docs: 迁入第一迭代过程报告并建立进展看板
- 新增 development/iterations/iteration-1/:15 份角色报告 + 进展看板(已完成/未闭环/下一步),作为双人协作的进度事实来源
- 新增 ADR-006:测试与交付容器化策略(Testcontainers / 交付 Docker 包 / 本机库仅个人联调)
- Git 工作流规范补充:敏感信息只进忽略文件或 sample、测试数据不入库、测试代码限标准测试目录
- 门禁:mkdocs build --strict 通过(零警告)
2026-09-04 10:45:05 +08:00

222 lines
16 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# Patbond 第一迭代任务分解(M0 工程基线 + 真实登录纵切)
> 作者:Senior Project Manager
> 日期:2026-09-03
> 依据:`patbond-doc/docs/development/development-plan.md`Draft 1.02026-09-03
> 范围声明:严格限定为第 7 节 M0 与第 8 节「真实登录纵切」8 项任务。社区、AI 创作、预约、宠物健康均不在本迭代范围内(文档第 8 节明确:"第一迭代暂不开发 AI Worker、社区 Feed 或预约")。
## 1. 范围与合并说明
- **M0 目标**(第 7 节):"让所有开发者能用一致方式启动、测试和联调。" 验收标准:"新机器仅依据仓库文档即可启动后端、连接本地数据库并运行自动化检查。"
- **第一迭代目标**(第 8 节):真实登录纵切,端到端验证"数据库、认证、客户端和测试链路能够贯通"。
- **重叠合并**M0 的"将 bootstrap SQL 转为 Flyway baseline,并分离开发种子数据"与第 8 节任务 1"从 bootstrap SQL 提取 identity/media 的 Flyway baseline"是同一件事在本迭代的落地范围。合并为工单 T1,本迭代只做 identity/media 两个 schema 的 baseline,其余 schema 的 Flyway 化随后续迭代进行。
- **媒体范围提示**:第 8 节 8 项任务不含媒体上传实现(那是 M1 后半段),T1 仅按文档字面提取 media 的表结构 baseline,不开发 `POST /api/v1/media/uploads`
预估规模口径:S ≈ 半天内,M ≈ 1-2 天,L ≈ 3-5 天(含测试与文档)。
---
## 2. 工单列表
### A 组:M0 工程基线(6 个工单)
#### T0-1 接入 Maven Wrapper
- **仓库**patbond-api
- **描述**:为多模块 Maven 工程添加 `mvnw`/`mvnw.cmd` 与 wrapper 配置,锁定 Maven 3.9+README 中的构建命令改用 `./mvnw`
- **验收标准**
- 干净检出后不安装本机 Maven`./mvnw -pl patbond-common -am install` 可通过。
- 文档中 Maven 版本与 wrapper 配置一致。
- **依赖**:无。
- **规模**S
#### T0-2 Flutter/Dart 版本锁定
- **仓库**patbond-flutter
- **描述**:提供 Flutter SDK 版本固定方案(如 FVM 或等效工具),版本满足 `pubspec.yaml` 约束,并写入仓库说明。
- **验收标准**
- 仓库内有明确的版本锁定文件与使用说明。
- 新机器按说明可 `flutter pub get && flutter analyze` 通过。
- **依赖**:无。
- **规模**S
#### T0-3 可提交的默认配置与环境变量注入
- **仓库**patbond-api
- **描述**:把 `application.yml.sample` 替换为可直接提交的 `application.yml` 默认配置;数据库、Nacos 等敏感/环境相关值全部通过环境变量注入,采用第 5.3 节变量名(`PATBOND_DB_URL``PATBOND_DB_USERNAME``PATBOND_DB_PASSWORD``NACOS_SERVER_ADDR`)。修复已知风险 5("干净检出无法按 README 直接启动服务")。
- **验收标准**
- 干净检出 + 设置环境变量即可启动 `patbond-user`8082)与 `patbond-auth`8081),无需手工复制 sample。
- 仓库中无任何密码、token、密钥明文(第 5.1 节红线)。
- **依赖**:无(与 T0-4 联调)。
- **规模**M
#### T0-4 本地基础设施编排(PostgreSQL + Nacos
- **仓库**patbond-api(编排文件),patbond-doc(启动文档)
- **描述**:提供本地一键编排(PostgreSQL 16、Nacos);RabbitMQ 按文档"在异步任务阶段启用",本迭代不加入。数据库容器初始化仅建空库,结构由 Flyway 负责(T1)。
- **验收标准**
- 一条命令拉起 PostgreSQL 16 与 Nacos,端口与 T0-3 的默认环境变量匹配。
- 文档说明启动、停止、重置数据的方式。
- **依赖**:无。
- **规模**M
#### T0-5 契约规范冻结文档
- **仓库**patbond-doc
- **描述**:把第 4.3、6.1 节规则固化为规范文档并纳入 `mkdocs.yml` 导航:UUID(应用层 UUIDv7)、`timestamptz` + ISO 8601、金额整数分、统一错误响应(HTTP 状态码 + 稳定业务错误码)、cursor 分页、`Idempotency-Key``version` 乐观锁、日志脱敏。
- **验收标准**
- 规范文档评审通过,`mkdocs build --strict` 通过。
- T3/T4/T6 的实现均引用此文档而非各自发明。
- **依赖**:无;是 T3、T6a 的前置。
- **规模**M
#### T0-6 建立 CI 最低门禁
- **仓库**patbond-api、patbond-flutter、patbond-doc(三条流水线)
- **描述**:按第 9 节 CI 最低门禁配置:API `mvn clean test`Flutter `dart format --set-exit-if-changed` + `flutter analyze` + `flutter test`;文档 `mkdocs build --strict`。加入基本代码检查。数据库迁移在全新 PostgreSQL 16 实例执行一次的校验,在 T1 合入后追加到 API 流水线。
- **验收标准**
- 三仓 PR 均触发对应门禁,当前主干全绿。
- 门禁失败可阻止合入。
- **依赖**T0-1API 用 wrapper 构建)、T0-2Flutter 版本确定)。
- **规模**M
### B 组:登录纵切(9 个工单,对应第 8 节 8 项任务,任务 6 拆为两单)
#### T1 identity/media Flyway baseline 与种子数据分离(第 8 节任务 1)
- **仓库**patbond-api(迁移脚本),patbond-doc(迁移说明)
- **描述**:从 `patbond-doc/docs/database/patbond_postgresql.sql` 提取 `identity``media` 两个 schema 的结构,转为 Flyway 版本化迁移;开发种子数据独立为不进生产的脚本。遵守第 4.3 节:已导入的本地库先备份,优先重建开发库或核对 checksum 后 baseline"禁止直接重复执行 bootstrap"。
- **验收标准**
- 全新 PostgreSQL 16 实例上 Flyway 迁移一次成功,`identity``media` 表结构与 bootstrap SQL 一致。
- 种子数据脚本与结构迁移分离,且不会进入正式环境。
- 本地既有库的接入路径(重建或 baseline)写入文档。
- **依赖**T0-4(本地 PostgreSQL 可用)。
- **规模**M
#### T2 patbond-user 接入 PostgreSQLUUID 用户持久化(第 8 节任务 2)
- **仓库**patbond-api
- **描述**:为 `patbond-user` 增加数据源与 Repository,把内存用户迁移到 `identity.users``identity.user_credentials`;用户 ID 由 `Long` 改为 UUID(应用层 UUIDv7 优先,`gen_random_uuid()` 兜底),消除已知风险 1。数据库账号使用最小权限(第 5.3 节)。
- **验收标准**
- 注册的用户写入 PostgreSQL,重启服务后数据不丢失。
- 对外 API 中用户 ID 为 UUID 字符串。
- 现有注册/登录/查询/密码校验接口在新存储上行为正确。
- **依赖**T1、T0-3。
- **规模**L
#### T3 统一异常响应与数据库一致校验(第 8 节任务 3)
- **仓库**patbond-api
- **描述**:实现统一错误响应(正确 HTTP 状态码 + 稳定业务错误码,禁止只返回异常文本,见 6.1 节);用户名、手机号唯一性校验以数据库约束为准,应用层校验与数据库约束一致,并发重复注册返回明确错误而非 500。
- **验收标准**
- 参数错误、重复用户名/手机号、资源不存在均返回规范错误体。
- 并发重复注册场景有测试覆盖,无脏数据。
- 日志不记录密码、token、手机号全文。
- **依赖**T2、T0-5。
- **规模**M
#### T4 可校验 access token 与 refresh session(第 8 节任务 4
- **仓库**patbond-api
- **描述**:将随机字符串 token 替换为可校验的 access token;实现 refresh token 轮换、退出与会话撤销(会话落 `identity` 相关表);补齐 `POST /api/v1/auth/refresh``POST /api/v1/auth/logout`;消除已知风险 2。`/internal/**` 的服务间访问控制(风险 3)按 M1 范围至少加基础保护。
- **验收标准**
- access token 可离线/在线校验,过期后用 refresh token 可换新。
- refresh token 轮换后旧 token 立即失效;退出后 refresh token 不可再次使用(M1 验收标准)。
- `/internal/users/**` 不可被无凭据外部调用直接访问。
- **依赖**:T2;token 有效期与多设备策略需产品拍板(见决策 D3),未拍板前按建议默认值实现并做成配置项。
- **规模**L
#### T5 认证链路集成测试(第 8 节任务 5)
- **仓库**patbond-api
- **描述**:使用真实 PostgreSQL/Testcontainers 为注册、登录、刷新、退出、鉴权建立集成测试(第 9 节),覆盖成功、参数错误、凭据错误、token 过期、已撤销 token 复用、无权限访问等路径。
- **验收标准**
- 上述场景全部有自动化断言并纳入 `mvn clean test`
- CI(T0-6)中稳定通过,包含迁移在全新实例执行一次的校验。
- **依赖**T2、T3、T4、T0-6。
- **规模**M
#### T6a 建立 OpenAPI 契约(第 8 节任务 6 前半)
- **仓库**patbond-doc(契约文档),patbond-api(保证实现一致)
- **描述**:为第 6.2 节第一批中本迭代涉及的接口编写 OpenAPI:`/api/v1/auth/register``/auth/login``/auth/refresh``/auth/logout``GET /api/v1/me`。统一 `/api/v1` 前缀、camelCase、UUID 字符串、规范错误体;加入契约测试验证实际响应与文档一致。
- **验收标准**
- OpenAPI 文件评审通过并纳入文档站导航。
- 契约测试在 CI 中验证以上接口响应与契约一致。
- **依赖**T0-5;接口最终形态受 T3/T4 影响(可先起草,随实现收敛)。登录方式字段依赖决策 D5。
- **规模**M
#### T6b Flutter API Client(第 8 节任务 6 后半)
- **仓库**patbond-flutter
- **描述**:依据 T6a 的 OpenAPI 生成或手写 API Client 与 DTO,建立第 4.2 节分层(Repository -> API Client),实现统一错误码解析。
- **验收标准**
- Client 覆盖 T6a 全部接口,DTO 映射有单元测试。
- 错误响应能映射为客户端可处理的类型化错误。
- **依赖**T6a。
- **规模**M
#### T7 Flutter 登录页、安全 token 存储与登录态恢复(第 8 节任务 7)
- **仓库**patbond-flutter
- **描述**:新增登录/注册页;access/refresh token 仅存安全存储(不得写入普通 `SharedPreferences`,第 4.2 节);实现鉴权拦截(自动附带 token、401 时刷新重试)与应用启动登录态恢复;`auth` 状态从 `AppState` 拆出独立 feature 状态。
- **验收标准**
- 可完成真实注册与登录;杀进程重开后登录态恢复;token 过期自动刷新。
- 登录页覆盖 loading、error、retry 状态(第 9 节要求)。
- 有登录流程 Widget 测试与 Repository/状态单元测试。
- **依赖**:T6b;端到端联调依赖 T4。
- **规模**L
#### T8 端到端用例:注册 → 登录 → 获取当前用户 → 退出(第 8 节任务 8)
- **仓库**patbond-flutterE2E 用例),patbond-api、patbond-doc(联调环境与文档)
- **描述**:建立一条贯通真实后端与数据库的端到端自动化用例:注册 → 登录 → `GET /api/v1/me` → 退出,退出后受保护接口访问失败。补充"新机器按文档从零跑通该用例"的操作说明,作为 M0 验收的最终证明。
- **验收标准**
- 用例可在本地编排环境(T0-4)下自动执行并通过。
- 新成员仅凭仓库文档可复现(M0 验收标准)。
- **依赖**T4、T5、T7。
- **规模**M
---
## 3. 关键路径与并行分组
### 关键路径(后端主线 → 客户端联调 → E2E)
```text
T0-4 编排 → T1 Flyway baseline → T2 用户持久化(L) → T4 token/会话(L) → T7 Flutter 登录联调(L) → T8 E2E
```
T2、T4、T7 三个 L 工单串在关键路径上,是迭代周期的决定因素。压缩手段:T4 的 token 方案设计、T7 的登录页 UI 与安全存储封装都可在前置工单完成前先行开工(见下)。
### 可并行任务组
| 组 | 工单 | 说明 |
| --- | --- | --- |
| P1 工程基线(迭代第一周全部并行) | T0-1、T0-2、T0-3、T0-4、T0-5 | 互相无依赖,可 3-4 人同时开工;完成后 T0-6 收口 |
| P2 后端主线(串行) | T1 → T2 → T4 | 关键路径,建议由同一名后端主力负责保持连续性 |
| P3 后端旁路 | T3、T5 | T3 与 T4 都只依赖 T2,可两人并行;T5 随 T3/T4 完成滚动补齐 |
| P4 契约与客户端 | T6a → T6b → T7 | T6a 可在 T0-5 后立即起草(与 T2 并行);T7 的 UI/安全存储部分可与后端并行,仅最终联调等 T4 |
| P5 收口 | T8 | 全链路就绪后执行 |
最小人力建议:1 名后端主力(P2)+ 1 名后端(P3 与部分 P1+ 1 名 Flutter(P4)即可维持关键路径不空转。
---
## 4. 开工前待确认决策清单(源自文档第 12 节)
文档明确:"上述事项未确认前,可以完成 M0 和身份持久化,但不应并行扩展所有业务模块。" 即本迭代大部分工单不被阻塞,但 D3、D5 直接影响本迭代实现,需优先拍板。
| # | 决策事项 | 对本迭代的影响 | 建议默认选项 |
| --- | --- | --- | --- |
| D1 | 第一版 MVP 是"注册登录 + 宠物档案"还是必须包含社区发布 | 不阻塞本迭代,决定第二、三迭代排期 | 注册登录 + 宠物档案(M1+M2),社区后置到 M3;与文档迭代顺序一致 |
| D2 | 后端多服务部署 vs 模块化单体 | 影响 T0-3/T0-4 的配置与编排复杂度、是否长期保留 Nacos | 先模块化单体:保留 Maven 模块边界与 schema 所有权,单进程/同机部署降低早期运维成本;当前 auth/user 双服务与 Nacos 维持现状不扩散,待拍板后再收敛 |
| D3 | access/refresh token 有效期与多设备登录策略 | **直接阻塞 T4 定稿**(可按默认值先实现为配置项) | access 15 分钟;refresh 30 天且每次刷新轮换;允许多设备并行会话,退出仅撤销当前会话 |
| D4 | 对象存储、AI 模型、天气、地图供应商 | 本迭代不阻塞(T1 仅建 media 表结构);对象存储需在 M1 媒体上传前确定 | 本迭代不定 AI/天气/地图;对象存储在下迭代开始前选定一家 S3 兼容服务 |
| D5 | 是否支持手机号登录、短信验证码、第三方登录 | **影响 T3 校验字段、T6a 注册/登录契约、T7 登录页表单** | 首版仅账号(用户名/手机号作为标识)+ 密码,不做短信验证码与第三方登录;数据模型预留凭证类型扩展 |
| D6 | 预约首版是否包含支付、退款和服务商后台 | 不阻塞本迭代;影响 M5 范围与数据库是否需补支付域 | 首版不含支付与服务商后台,预约仅到"确认/完成"状态机;文档已注明当前数据库不含支付域 |
| D7 | 首发平台:Android/iOS,还是含 Web/桌面 | 影响 T7/T8 的测试矩阵与后续 Golden 测试宽度 | 首发仅 Android + iOSWeb/桌面不在验收矩阵 |
另提请产品/技术负责人注意文档第 11 节风险 8(Spring Boot 2.7 已进入旧技术代际,是先交付 MVP 还是先升级 Boot 3)——它不在第 12 节清单中,但会影响 T4 选型的依赖库,建议与 D2 一并讨论。PM 建议:先按现有 Boot 2.7 交付本迭代,升级作为独立技术专项排期,避免纵切迭代被大版本升级绑架。
---
## 5. 质量要求(对全部工单生效)
- 遵守文档第 10 节 Definition of Done:不依赖 Demo 常量或仅存于进程内的数据;权限、校验、幂等、并发已处理;文档同步更新;干净环境可复现。
- 不提交任何密码、token、密钥(第 5.1 节)。
- 日志不得记录密码、token、手机号全文(第 6.1 节)。
- 新增文档必须同步更新 `mkdocs.yml` 导航(第 1 节)。
- 本迭代不实现社区、AI、预约、宠物健康的任何接口或页面改造;发现范围外需求一律记入 backlog。
## 6. 工单统计
- 工单总数:**15**(M0 工程基线 6 个 + 登录纵切 9 个)
- 规模分布:S × 2、M × 10、L × 3
- 关键路径长度:6 个工单(T0-4 → T1 → T2 → T4 → T7 → T8),其中 3 个 L