Files
patbond-doc/docs/development/development-plan.md
T
lixi 18746ce6fc docs: 增加 ADR-008 将 PostgreSQL 版本基线定为 18
- 零数据窗口期定版:与本机开发库 18.6 对齐,Testcontainers/编排/交付统一 postgres:18
- 切换当日 37 测试于 postgres:18 全绿,Flyway V1 兼容
- 同步开发计划 5.1/M0/CI 门禁与进展看板的版本表述
- 门禁:mkdocs build --strict 通过
2026-09-04 11:33:58 +08:00

18 KiB
Raw Blame History

Patbond 开发实施文档

状态:Draft 1.0
更新日期:2026-09-03
适用仓库:patbond-apipatbond-docpatbond-flutter

1. 文档目标

本文档用于把现有 Flutter 静态 Demo、本地 PostgreSQL 数据库和 Java 登录原型组织成可持续开发的产品。它定义当前基线、目标边界、接口约定、迭代顺序、质量门禁和验收标准。

文档按类型分目录管理,避免产品、接口、数据库和运维内容混杂:

docs/
  index.md
  development/   # 开发计划、编码规范和协作流程
  api/           # OpenAPI、接口约定和调用示例
  architecture/  # 系统设计、ADR 和模块边界
  database/      # 数据模型、迁移说明和 SQL
  testing/       # 测试策略、用例和质量报告
  operations/    # 部署、配置、监控和故障处理

目录在出现对应文档时创建,不放无内容的占位文件。新增文档后必须同步更新 mkdocs.yml 导航。

当前尚无独立 PRD 和 OpenAPI 契约。出现冲突时,按以下顺序处理:

  1. 团队已确认的产品需求和 API 契约。
  2. patbond-doc/docs/database/patbond_postgresql.sql 中的数据约束。
  3. Flutter Demo 所表达的页面流程和交互意图。
  4. 当前 Java 原型代码。

Demo 中的示例文案、模拟延迟、图片地址和展示型字段不视为正式业务契约。

2. 当前基线

仓库 已有能力 主要缺口
patbond-flutter 首页、AI 创作、宠物档案、本地服务、个人中心五个 Tab;点赞、收藏、评论、宠物及疫苗编辑等本地交互 无登录页、网络层、鉴权状态和真实业务接口;AI 与预约为模拟流程
patbond-api Maven 多模块;authusercommon;注册、登录、用户创建/查询/密码校验共 6 个接口 用户仅存内存;token 不可验证;未连接 PostgreSQL;无其余业务域接口
patbond-doc PostgreSQL 16+ 目标模型,包含 7 个 schema、36 张表、开发数据、约束和参考查询 SQL 是一次性 bootstrap,不是 Flyway 迁移;MkDocs 首页和工程文档尚不完整

当前三仓没有形成真实端到端链路。现阶段应定义为:可交互产品 Demo + 身份服务原型 + 已导入本地数据库的目标数据模型

3. 产品范围与主流程

Patbond 面向宠物主人,围绕一个核心闭环开发:

注册/登录
  -> 建立宠物档案
  -> 记录体重、疫苗和健康事件
  -> 浏览社区或使用 AI 创作
  -> 发布、点赞、收藏和评论
  -> 查找附近服务并预约
  -> 将完成的服务回写健康档案

目标业务域如下:

业务域 主要能力 数据 schema
身份 用户、凭证、会话、地址、偏好 identity
媒体 头像、宠物照片、帖子媒体、健康附件、AI 输入输出 media
宠物健康 宠物、共同照护人、体重、疫苗、健康事件、提醒 pet_health
社区 动态、评论、点赞、收藏、关注、话题、Feed community
AI 创作 模型、风格、异步任务、重试、生成结果 creation
本地服务 服务商、服务项目、可预约资源、预约状态流转 marketplace
平台能力 地区、通知、事务 Outbox platform

4. MVP 架构原则

4.1 后端形态

MVP 阶段沿用当前 Maven 多模块仓库和 Spring 服务框架,但不一次性拆出七个独立微服务。

  • 保留 patbond-auth:面向客户端的认证入口。
  • 保留 patbond-user:身份、凭证和用户资料的唯一数据所有者。
  • 保留 patbond-common:仅放稳定的跨模块契约和基础类型,不承载业务逻辑,也不应让所有服务被动引入 RabbitMQ、Feign 等依赖。
  • 按迭代增加宠物健康、社区、AI 创作和本地服务模块;模块边界与数据库 schema 对齐。
  • MVP 可共享一个 PostgreSQL 实例,但每个业务模块只直接读写自己拥有的 schema。
  • 跨域写入通过应用服务完成;异步通知使用事务 Outbox。不要依靠客户端同时调用多个服务维持一致性。

如果未来采用“每服务独立数据库”,应先移除跨 schema 外键并设计事件一致性,不能直接把当前 SQL 按 schema 拆库。

4.2 客户端形态

Flutter 保留现有页面作为交互参考,逐页替换本地数据:

Page/Widget -> Feature Controller -> Repository -> API Client
                                      -> Local Cache
  • AppState 不再直接承担所有业务状态和持久化职责。
  • authpetscommunitycreationmarketplace 拆分 feature 状态。
  • access token 仅保存在安全存储中;不得写入普通 SharedPreferences
  • SharedPreferences 仅保留主题、引导状态等非敏感轻量配置。
  • 服务端数据是事实来源;本地缓存需要定义失效、刷新和冲突策略。

4.3 数据库演进

现有 patbond_postgresql.sql 作为已评审目标模型和本地开发基线,不再直接修改为日常发布脚本。

  • 把结构、开发种子数据和校验脚本拆开。
  • 后端接入 Flyway,每次结构变更新增版本化迁移,不修改已发布迁移。
  • 已导入的本地库应先备份;接入 Flyway 时优先重建开发库,或在核对 schema checksum 后建立 baseline,禁止直接重复执行 bootstrap。
  • 正式环境不得导入开发账号、示例帖子或演示预约。
  • ID 统一使用 UUID;应用层优先生成 UUIDv7,数据库的 gen_random_uuid() 作为兜底。
  • 所有时间以 timestamptz 保存并通过 ISO 8601 传输;客户端按本地时区显示。
  • 金额使用整数分;距离、年龄、疫苗进度和相对时间均由事实字段计算,不持久化展示字符串。

5. 本地开发基线

5.1 环境要求

  • JDK 17。不要使用更高版本 JDK 代替团队基线进行发布构建。
  • Maven 3.9+M0 完成后改用仓库内 Maven Wrapper。
  • PostgreSQL 18(版本基线见 ADR-008),现有本地库作为开发数据源。
  • Nacos,供当前 patbond-auth 发现 patbond-user
  • Flutter/Dart 版本需满足 patbond-flutter/pubspec.yamlM0 完成后通过版本管理工具锁定。

不要在仓库中提交数据库密码、token、对象存储密钥或第三方服务密钥。

5.2 当前原型启动

后端配置目前只有 .sample 文件。首次启动时应在本机复制为被 Git 忽略的 application.yml,并确认 Nacos 地址:

cp patbond-user/src/main/resources/application.yml.sample \
  patbond-user/src/main/resources/application.yml
cp patbond-auth/src/main/resources/application.yml.sample \
  patbond-auth/src/main/resources/application.yml

mvn -pl patbond-common -am install
mvn -f patbond-user/pom.xml spring-boot:run
mvn -f patbond-auth/pom.xml spring-boot:run

两个服务需分别在终端中运行。默认端口是 8082user)和 8081(auth)。当前版本不读取 PostgreSQL;只有 M1 的数据源和 Repository 完成后,本地数据库才会进入运行链路。

Flutter 启动:

flutter pub get
flutter run

5.3 数据库接入目标

M1 应通过环境变量注入以下配置,变量名在实现时统一:

PATBOND_DB_URL=jdbc:postgresql://127.0.0.1:5432/patbond
PATBOND_DB_USERNAME=<local-user>
PATBOND_DB_PASSWORD=<local-password>
NACOS_SERVER_ADDR=127.0.0.1:8848

连接前至少验证 identitymediapet_healthcommunitycreationmarketplaceplatform 七个 schema 均存在。应用账号应使用最小权限,不使用 PostgreSQL 超级用户运行服务。

6. API 契约规范

正式开发前先建立 OpenAPI 文档。建议统一使用 /api/v1 前缀,内部服务接口使用独立的 /internal 前缀且必须具备服务间认证。

6.1 通用规则

  • JSON 字段统一使用 camelCase
  • 资源 ID 对外表示为 UUID 字符串。
  • 成功响应可沿用 { "code": 0, "message": "success", "data": ... }
  • 错误必须同时返回正确 HTTP 状态码和稳定业务错误码,禁止只返回异常文本。
  • 列表采用 cursor 分页;动态 Feed 禁止深度 OFFSET
  • 创建帖子、生成任务和预约等写接口必须支持 Idempotency-Key
  • 更新宠物、帖子、预约等聚合时使用 version 做乐观锁。
  • 日志不得记录密码、token、手机号全文或上传签名。

6.2 第一批接口

建议接口 用途
Auth POST /api/v1/auth/register 注册并创建会话
Auth POST /api/v1/auth/login 登录
Auth POST /api/v1/auth/refresh 轮换 refresh token
Auth POST /api/v1/auth/logout 撤销当前会话
User GET /api/v1/me 当前用户资料
User PATCH /api/v1/me 修改资料与偏好
Media POST /api/v1/media/uploads 获取上传凭据/创建媒体记录
Pets GET/POST /api/v1/pets 查询、新建宠物
Pets GET/PATCH /api/v1/pets/{petId} 宠物详情与更新
Pets GET/POST /api/v1/pets/{petId}/weights 体重记录
Pets GET/POST/PATCH /api/v1/pets/{petId}/vaccinations 疫苗记录
Pets GET/POST /api/v1/pets/{petId}/health-events 健康时间线

后续接口按社区、AI 创作、本地服务的迭代顺序补充,先写 OpenAPI 和契约测试,再实现客户端调用。

7. 分阶段开发计划

M0:工程基线与契约冻结

目标:让所有开发者能用一致方式启动、测试和联调。

  • 确认 Java 17、Flutter SDK、PostgreSQL 18 的固定版本。
  • 增加 Maven Wrapper 和 Flutter 版本固定方案。
  • 提供可提交的 application.yml 默认配置,敏感值全部由环境变量注入。
  • 增加本地基础设施编排:PostgreSQL、NacosRabbitMQ 在异步任务阶段启用。
  • 将 bootstrap SQL 转为 Flyway baseline,并分离开发种子数据。
  • 确定 UUID、时间、金额、错误响应、分页和幂等规范。
  • 建立 OpenAPI、CI 和基本代码检查。

验收标准:新机器仅依据仓库文档即可启动后端、连接本地数据库并运行自动化检查。

M1:身份与媒体纵向闭环

目标:用户能够在 Flutter 完成真实注册、登录和会话恢复。

  • API 将内存用户迁移到 identity.usersidentity.user_credentials
  • Long 用户 ID 改为 UUID。
  • 实现可验证的 access token、refresh token 轮换、退出和会话撤销。
  • 保护 /internal/**,增加登录失败限制和安全日志。
  • 实现媒体元数据与对象存储上传流程。
  • Flutter 增加登录/注册、API Client、Repository、鉴权拦截和安全存储。

验收标准:注册后重启服务数据不丢失;token 过期可刷新;退出后 refresh token 不可再次使用;客户端可恢复登录态。

M2:宠物健康

目标:替换 Flutter 档案页的本地宠物和疫苗数据。

  • 实现宠物、照护权限、体重、疫苗、健康事件和提醒接口。
  • 校验当前用户对宠物的 owner/caregiver/viewer 权限。
  • Flutter 接入真实列表、详情、编辑、加载、空态和错误态。
  • 体重、疫苗进度、下次接种和月度花费从事实表聚合生成。

验收标准:数据可跨设备读取;无权限用户不能访问宠物;并发更新返回明确冲突;关键流程具备 API 集成测试和 Flutter 组件测试。

M3:社区

目标:完成真实动态发布和互动闭环。

  • 实现 Feed、帖子详情、草稿/发布、媒体、评论、点赞、收藏、关注和话题。
  • Feed 使用游标分页;点赞、收藏使用幂等写入。
  • Flutter 替换本地帖子,并实现刷新、分页、失败重试和乐观更新回滚。

验收标准:发布后可在另一客户端看到;重复点赞不重复计数;分页不丢失、不重复;删除或隐藏内容不可继续出现在公共 Feed。

M4AI 创作

目标:替换上传和生成延时模拟。

  • 实现模型/风格目录、生成任务创建、查询和取消。
  • Worker 通过队列消费任务,使用租约、重试和幂等键防止重复生成。
  • 输出写入媒体表,成功后可一键创建社区草稿。
  • Flutter 展示排队、生成进度、失败重试和取消状态。

验收标准:任务状态流转合法;Worker 重启不丢任务;相同幂等请求不重复扣费或生成;失败原因可追踪。

M5:本地服务与预约

目标:完成附近搜索、服务选择和真实预约。

  • 实现地区、服务商、服务项目、资源和预约接口。
  • 附近搜索先用经纬度边界框,再计算精确距离。
  • 实现预约 hold、确认、服务中、完成、取消和过期状态机。
  • 后台任务释放过期 hold;数据库排斥约束防止资源时段重叠。
  • Flutter 增加时间、宠物、服务项、地址选择及订单列表。

验收标准:并发预约同一资源时段最多一个成功;非法状态迁移被拒绝;过期占位自动释放;完成服务可关联健康事件。

M6:交付加固

  • 通知、事务 Outbox 发布器和失败重试。
  • 限流、审计、结构化日志、指标、Trace 和告警。
  • 容器镜像、环境配置、数据库备份恢复和回滚方案。
  • Flutter 包名、签名、图标、启动页、隐私声明和商店配置。
  • 完成安全、性能、可访问性、弱网和多尺寸测试。

8. 第一迭代建议任务

第一迭代只做“真实登录纵切”,避免同时铺开全部业务域:

  1. 从 bootstrap SQL 提取 identity/media 的 Flyway baseline。
  2. patbond-user 增加 PostgreSQL Repository,实现 UUID 用户持久化。
  3. 实现统一异常响应及用户名、手机号的数据库一致校验。
  4. 将随机 token 替换为可校验 access token,并实现 refresh session。
  5. 增加注册、登录、刷新、退出和鉴权集成测试。
  6. 建立 OpenAPI,并据此生成或手写 Flutter API Client。
  7. Flutter 增加登录页、安全 token 存储和登录态恢复。
  8. 建立一条端到端用例:注册 → 登录 → 获取当前用户 → 退出。

第一迭代暂不开发 AI Worker、社区 Feed 或预约,先验证数据库、认证、客户端和测试链路能够贯通。

9. 测试与质量门禁

后端

  • 单元测试:校验、状态转换、权限和领域规则。
  • 集成测试:使用真实 PostgreSQL/Testcontainers 验证 Repository、迁移、事务和约束。
  • 契约测试:验证 OpenAPI 与实际响应一致。
  • 安全测试:密码不泄露、token 撤销有效、越权访问失败、内部接口受保护。
  • 每个业务模块至少覆盖成功、参数错误、资源不存在、无权限、并发冲突和幂等重试。

Flutter

  • 单元测试:DTO 映射、Repository、缓存和状态转换。
  • Widget 测试:登录、宠物编辑、动态互动、生成状态、预约状态。
  • Golden/响应式测试:手机、平板和桌面宽度,以及 200% 文字缩放。
  • Integration/E2E:注册登录、宠物档案、发帖和预约主路径。
  • 所有网络页面必须覆盖 loading、empty、error、retry 和离线状态。

CI 最低门禁

# Java
mvn clean test

# Flutter
dart format --output=none --set-exit-if-changed lib test
flutter analyze
flutter test

# 文档
mkdocs build --strict

数据库迁移还需在全新 PostgreSQL 18 实例执行一次,并对升级路径执行一次。

可观测性与产品验证

  • 技术指标至少包含请求量、错误率、P95 延迟、数据库连接池、队列积压和 Worker 失败率。
  • 首批产品漏斗事件建议覆盖注册完成、登录成功、宠物创建、动态发布、AI 任务成功和预约确认。
  • 埋点携带事件版本、用户/会话标识和服务端时间,但不得包含密码、token 或非必要个人信息。
  • A/B 实验必须使用稳定分流和独立曝光事件;在基础埋点、指标口径和样本量规则完成前不启动产品实验。

10. 完成定义(Definition of Done

一个功能只有同时满足以下条件才算完成:

  • 需求和异常路径已明确。
  • OpenAPI、数据库迁移和代码实现保持一致。
  • 不依赖 Demo 常量或只在当前进程存在的数据。
  • 权限、输入校验、幂等性和并发行为已处理。
  • API 单元/集成测试及对应 Flutter 测试通过。
  • 页面具有加载、空、错误和重试状态。
  • 日志和指标能定位失败原因,且不泄露敏感数据。
  • 文档已更新,代码通过 CI,可在干净环境复现。

11. 当前已知风险

  1. API 使用 Long,数据库使用 UUID;必须在新增业务前统一。
  2. 当前 token 是随机字符串,无法验证、刷新或撤销。
  3. /internal/users/** 尚无服务间访问控制。
  4. Flutter 没有网络层,模型中仍有相对时间、距离等展示字符串。
  5. application.yml 只有 sample,干净检出无法按 README 直接启动服务。
  6. API 没有自动化测试;Flutter 仅有一个导航冒烟测试。
  7. PostgreSQL bootstrap 含开发数据,不可直接作为生产迁移。
  8. Spring Boot 2.7/Spring Cloud 2021 已进入旧技术代际,需要决定先交付 MVP 还是先升级 Boot 3。
  9. 数据库使用大量跨 schema 外键,与严格的独立数据库微服务模式存在冲突。
  10. AI 提供方、对象存储、天气/地图供应商和通知渠道尚未确定。

12. 开工前待确认事项

  • 第一版是否以“注册登录 + 宠物档案”为 MVP,还是必须包含社区发布。
  • 后端继续多服务部署,还是先采用模块化单体以降低早期运维成本。
  • access/refresh token 有效期及多设备登录策略。
  • 对象存储、AI 模型、天气和地图服务供应商。
  • 是否支持手机号登录、短信验证码和第三方登录。
  • 预约首版是否包含支付、退款和服务商后台;当前数据库只覆盖预约,不包含支付域。
  • 首发平台是 Android/iOS,还是同时支持 Web/桌面。

上述事项未确认前,可以完成 M0 和身份持久化,但不应并行扩展所有业务模块。