From 9a4a65a2414f04b2fa772ec4ddabe21cc65f5801 Mon Sep 17 00:00:00 2001 From: iven Date: Wed, 13 May 2026 13:36:57 +0800 Subject: [PATCH] =?UTF-8?q?docs:=20P0=20=E6=B5=81=E7=A8=8B=E6=94=B9?= =?UTF-8?q?=E8=BF=9B=20=E2=80=94=20Feature=20DoD=20+=20=E5=AE=89=E5=85=A8?= =?UTF-8?q?=E6=A3=80=E6=9F=A5=20+=20=E5=89=8D=E5=90=8E=E7=AB=AF=E5=90=8C?= =?UTF-8?q?=E6=AD=A5=E6=A3=80=E6=9F=A5?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 基于 175 次 fix 分析的三个最高优先级行动项: - §2.6 Feature DoD 清单(后端/Web/小程序/安全/验证 5 维度) - §3.3 新增 API 端点安全检查(默认拒绝原则) - §3.3 前后端接口同步检查(DTO 变更 6 项同步确认) - §6 反模式增加 3 条教训(DoD/安全默认/前后端同步) 关联: docs/discussions/2026-05-13-development-process-retrospective.md Co-Authored-By: Claude Opus 4.7 --- CLAUDE.md | 76 +++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 76 insertions(+) diff --git a/CLAUDE.md b/CLAUDE.md index 75d7e71..4ee0ec0 100644 --- a/CLAUDE.md +++ b/CLAUDE.md @@ -126,6 +126,54 @@ - **步骤 4 功能验证必须实际操作** — 只看编译通过不算验证,必须启动服务、在浏览器中确认功能正常。 - **步骤 7 推送是强制环节**,不推送就等于没完成。不允许"等一下再推"。 +### 2.6 Feature DoD — 功能完成定义(强制) + +> 历史数据显示 24% 的提交是 fix,根因是缺少统一的完成标准。 +> 每个功能标记"完成"前,**必须**逐项检查以下清单,不允许跳过。 + +#### 后端 + +- [ ] Entity 包含所有标准字段(`id`/`tenant_id`/`created_at`/`updated_at`/`created_by`/`updated_by`/`deleted_at`/`version`) +- [ ] Handler 添加 `require_permission` 权限守卫 +- [ ] 权限码已写入 seed 迁移(每个实体 `.list` + `.manage`,权限码前缀与实体名一致) +- [ ] utoipa 注解已添加(`#[derive(utoipa::OpenApi)]` + path/response schema) +- [ ] Service 层核心路径有单元/集成测试 +- [ ] 多租户隔离正确(所有查询含 `tenant_id` 过滤,无手写 SQL 拼接) +- [ ] 输入验证完整(必填字段 + 格式校验 + 长度限制) +- [ ] 错误处理统一(`AppError`,不 panic,不 unwrap 生产代码) +- [ ] 关键操作有 `tracing` 日志(info/warn/error 级别合理) + +#### 前端(Web) + +- [ ] API 路径与后端 OpenAPI spec 一致(不手写路径,从 `api/health/` 模块调用) +- [ ] 路由声明权限码(`permissions: [...]`),与后端 handler 一致 +- [ ] 菜单配置已更新(`parent_id` 正确 + `permission` 字段 + `menu_roles` 关联) +- [ ] 错误状态有用户友好提示(不显示原始 error message) +- [ ] 不使用 `any` 类型(用 `unknown` + 类型守卫) + +#### 前端(小程序) + +- [ ] Service 层接口契约与后端 DTO 一致(字段名/类型/结构体) +- [ ] 登录态处理正确(`useDidShow` 恢复认证、退出清理 Storage) +- [ ] 页面间数据通过 API 获取,不用 Storage 传递 +- [ ] 长者模式适配完成(字号 ≥ 22px) +- [ ] 图片使用合法 URL(HTTPS 或相对路径,不用 HTTP) + +#### 安全 + +- [ ] 新增端点有权限声明(默认拒绝,不是默认放行) +- [ ] 敏感数据有脱敏/加密处理(PII 字段走 AES-256-GCM) +- [ ] 用户输入已验证和消毒(防 SQL 注入、XSS) +- [ ] 无 CORS 通配符、无硬编码密钥 + +#### 端到端验证 + +- [ ] `cargo check` 全 workspace 通过 +- [ ] `cargo test` 全部通过 +- [ ] 浏览器中手动验证功能正常(列表/创建/编辑/删除/权限拦截) +- [ ] 小程序中验证(涉及小程序页面时) +- [ ] 相关路由权限按角色测试通过(至少 admin + 只读角色) + --- ## 3. 实现规则 @@ -152,6 +200,31 @@ - utoipa 自动生成 OpenAPI 文档 - 租户 ID 从 JWT 中间件注入,**不在** API 路径中传递(管理员接口除外) +#### 新增 API 端点安全检查(强制) + +> 历史数据:25 次安全 fix 中 80% 源于默认放行模式。 +> 新增端点时**必须**逐项确认: + +- [ ] 端点已添加 `require_permission` 权限守卫(非公开端点) +- [ ] 公开端点已显式标记为 `public`(不继承认证中间件) +- [ ] 路由使用 `.nest()` 注册带中间件的子路由(禁止 `.merge()` 防止中间件泄漏) +- [ ] 敏感操作有速率限制 +- [ ] 无 `format!` 拼接 SQL — 所有查询使用 SeaORM 参数化 +- [ ] FHIR/第三方端点有 `tenant_id` 和 `allowed_patient_ids` 范围过滤 +- [ ] 无硬编码密钥或 fallback 默认值 + +#### 前后端接口同步检查(强制) + +> 历史数据:35 次 fix 源于前后端接口不一致。 +> 后端 DTO 变更时**必须**同步检查前端: + +- [ ] DTO 字段名变更 → 前端 TypeScript 接口同步更新 +- [ ] DTO 新增必填字段 → 前端表单和请求体同步更新 +- [ ] API 路径变更 → 前端 `api/` 模块路径同步更新 +- [ ] 返回数据结构变更(数组/对象/嵌套)→ 前端解析逻辑同步更新 +- [ ] 枚举值变更 → 前端类型定义和 UI 映射同步更新 +- [ ] 后端新增端点 → 前端 API 模块同步添加调用函数,不允许留空 + ### 3.4 事件总线 - 模块间通信**只能**通过 `EventBus` @@ -301,6 +374,9 @@ chore(docker): 添加 PostgreSQL 健康检查 - ❌ **不要**忘记更新文档 — 涉及架构、接口、模块变化时必须同步更新相关文档 - ❌ **不要**一次性输出长文档 — 超过 200 行的文档必须分步编写(先大纲 → 逐章 → 整合),否则会因上下文过长卡死 - ❌ **不要**忽略讨论记录 — 每次发散式讨论结束后必须建立文档到 `docs/discussions/`,不要口头确认后就忘 +- ❌ **不要**跳过 Feature DoD — 每个功能标记"完成"前必须通过 §2.6 检查清单,不全面验证就提交 = 后续 5 次 fix(媒体库教训) +- ❌ **不要**新增端点时默认放行 — 所有端点默认拒绝访问,必须显式声明权限(安全教训:25 次 fix 源于默认放行) +- ❌ **不要**后端 DTO 变更不同步前端 — 字段名/路径/类型变更时必须同步更新前端 TypeScript 接口(35 次 fix 教训) ### 场景化指令