diff --git a/docs/development/development-plan.md b/docs/development/development-plan.md new file mode 100644 index 0000000..5f95b97 --- /dev/null +++ b/docs/development/development-plan.md @@ -0,0 +1,370 @@ +# Patbond 开发实施文档 + +> 状态:Draft 1.0 +> 更新日期:2026-09-03 +> 适用仓库:`patbond-api`、`patbond-doc`、`patbond-flutter` + +## 1. 文档目标 + +本文档用于把现有 Flutter 静态 Demo、本地 PostgreSQL 数据库和 Java 登录原型组织成可持续开发的产品。它定义当前基线、目标边界、接口约定、迭代顺序、质量门禁和验收标准。 + +文档按类型分目录管理,避免产品、接口、数据库和运维内容混杂: + +```text +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 多模块;`auth`、`user`、`common`;注册、登录、用户创建/查询/密码校验共 6 个接口 | 用户仅存内存;token 不可验证;未连接 PostgreSQL;无其余业务域接口 | +| `patbond-doc` | PostgreSQL 16+ 目标模型,包含 7 个 schema、36 张表、开发数据、约束和参考查询 | SQL 是一次性 bootstrap,不是 Flyway 迁移;MkDocs 首页和工程文档尚不完整 | + +当前三仓没有形成真实端到端链路。现阶段应定义为:**可交互产品 Demo + 身份服务原型 + 已导入本地数据库的目标数据模型**。 + +## 3. 产品范围与主流程 + +Patbond 面向宠物主人,围绕一个核心闭环开发: + +```text +注册/登录 + -> 建立宠物档案 + -> 记录体重、疫苗和健康事件 + -> 浏览社区或使用 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 保留现有页面作为交互参考,逐页替换本地数据: + +```text +Page/Widget -> Feature Controller -> Repository -> API Client + -> Local Cache +``` + +- `AppState` 不再直接承担所有业务状态和持久化职责。 +- 按 `auth`、`pets`、`community`、`creation`、`marketplace` 拆分 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 16+,现有本地库作为开发数据源。 +- Nacos,供当前 `patbond-auth` 发现 `patbond-user`。 +- Flutter/Dart 版本需满足 `patbond-flutter/pubspec.yaml`,M0 完成后通过版本管理工具锁定。 + +不要在仓库中提交数据库密码、token、对象存储密钥或第三方服务密钥。 + +### 5.2 当前原型启动 + +后端配置目前只有 `.sample` 文件。首次启动时应在本机复制为被 Git 忽略的 `application.yml`,并确认 Nacos 地址: + +```bash +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 +``` + +两个服务需分别在终端中运行。默认端口是 `8082`(user)和 `8081`(auth)。当前版本不读取 PostgreSQL;只有 M1 的数据源和 Repository 完成后,本地数据库才会进入运行链路。 + +Flutter 启动: + +```bash +flutter pub get +flutter run +``` + +### 5.3 数据库接入目标 + +M1 应通过环境变量注入以下配置,变量名在实现时统一: + +```text +PATBOND_DB_URL=jdbc:postgresql://127.0.0.1:5432/patbond +PATBOND_DB_USERNAME= +PATBOND_DB_PASSWORD= +NACOS_SERVER_ADDR=127.0.0.1:8848 +``` + +连接前至少验证 `identity`、`media`、`pet_health`、`community`、`creation`、`marketplace`、`platform` 七个 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 16 的固定版本。 +- 增加 Maven Wrapper 和 Flutter 版本固定方案。 +- 提供可提交的 `application.yml` 默认配置,敏感值全部由环境变量注入。 +- 增加本地基础设施编排:PostgreSQL、Nacos;RabbitMQ 在异步任务阶段启用。 +- 将 bootstrap SQL 转为 Flyway baseline,并分离开发种子数据。 +- 确定 UUID、时间、金额、错误响应、分页和幂等规范。 +- 建立 OpenAPI、CI 和基本代码检查。 + +验收标准:新机器仅依据仓库文档即可启动后端、连接本地数据库并运行自动化检查。 + +### M1:身份与媒体纵向闭环 + +目标:用户能够在 Flutter 完成真实注册、登录和会话恢复。 + +- API 将内存用户迁移到 `identity.users`、`identity.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。 + +### M4:AI 创作 + +目标:替换上传和生成延时模拟。 + +- 实现模型/风格目录、生成任务创建、查询和取消。 +- 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 最低门禁 + +```bash +# Java +mvn clean test + +# Flutter +dart format --output=none --set-exit-if-changed lib test +flutter analyze +flutter test + +# 文档 +mkdocs build --strict +``` + +数据库迁移还需在全新 PostgreSQL 16 实例执行一次,并对升级路径执行一次。 + +### 可观测性与产品验证 + +- 技术指标至少包含请求量、错误率、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 和身份持久化,但不应并行扩展所有业务模块。 diff --git a/docs/index.md b/docs/index.md index 000ea34..9b334fb 100644 --- a/docs/index.md +++ b/docs/index.md @@ -1,17 +1,14 @@ -# Welcome to MkDocs +# Patbond 项目文档 -For full documentation visit [mkdocs.org](https://www.mkdocs.org). +Patbond 是面向宠物主人的社区、健康管理、AI 内容创作与本地服务平台。 -## Commands +当前项目由三个仓库组成: -* `mkdocs new [dir-name]` - Create a new project. -* `mkdocs serve` - Start the live-reloading docs server. -* `mkdocs build` - Build the documentation site. -* `mkdocs -h` - Print help message and exit. +- `patbond-flutter`:产品界面与本地交互 Demo。 +- `patbond-api`:Java/Spring Cloud 后端,当前实现身份注册和登录原型。 +- `patbond-doc`:项目文档与 PostgreSQL 数据模型。 -## Project layout +## 开发入口 - mkdocs.yml # The configuration file. - docs/ - index.md # The documentation homepage. - ... # Other markdown pages, images and other files. +- [开发实施文档](development/development-plan.md):当前基线、架构原则、接口约定、迭代计划和验收标准。 +- [PostgreSQL 数据库脚本](database/patbond_postgresql.sql):本地开发数据库的目标结构及示例数据。 diff --git a/mkdocs.yml b/mkdocs.yml index 5c97ab5..01084d2 100644 --- a/mkdocs.yml +++ b/mkdocs.yml @@ -1,3 +1,7 @@ site_name: Patbond Docs theme: - name: readthedocs \ No newline at end of file + name: readthedocs +nav: + - 首页: index.md + - 开发文档: + - 开发实施计划: development/development-plan.md