From 59057420805e51d8edc886f0a95fc96f88d69b26 Mon Sep 17 00:00:00 2001 From: iven Date: Wed, 13 May 2026 13:33:49 +0800 Subject: [PATCH] =?UTF-8?q?docs:=20=E5=BC=80=E5=8F=91=E6=B5=81=E7=A8=8B?= =?UTF-8?q?=E9=98=B6=E6=AE=B5=E6=80=BB=E7=BB=93=E4=B8=8E=E4=BC=98=E5=8C=96?= =?UTF-8?q?=20=E2=80=94=20=E5=A4=9A=E4=B8=93=E5=AE=B6=E7=BB=84=E5=8F=91?= =?UTF-8?q?=E6=95=A3=E5=BC=8F=E8=AE=A8=E8=AE=BA?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 8 类开发问题归纳(175 次 fix 分析)、3 个连锁效应案例、 6 位专家流程改进建议、Feature DoD 清单、P0/P1/P2 行动方案。 Co-Authored-By: Claude Opus 4.7 --- ...05-13-development-process-retrospective.md | 536 ++++++++++++++++++ 1 file changed, 536 insertions(+) create mode 100644 docs/discussions/2026-05-13-development-process-retrospective.md diff --git a/docs/discussions/2026-05-13-development-process-retrospective.md b/docs/discussions/2026-05-13-development-process-retrospective.md new file mode 100644 index 0000000..b15100e --- /dev/null +++ b/docs/discussions/2026-05-13-development-process-retrospective.md @@ -0,0 +1,536 @@ +# HMS 开发流程阶段总结与优化 — 多专家组发散式讨论 + +> 日期: 2026-05-13 | 参与者: iven, Claude(六位虚拟专家) +> 数据基准: 770 次提交 / 175 次 fix(22.7%)/ 近月 24% fix 率 +> 关联: [质量系统性预防方案](../docs/discussions/2026-05-08-quality-systemic-prevention.md) | [六维度分析](../docs/superpowers/specs/2026-05-11-system-comprehensive-analysis-design.md) + +--- + +## 1. 背景与数据概览 + +HMS 项目自 2026-04-10 首次提交以来,历经 33 天密集开发,累计 770 次提交。系统已从 MVP 成长为包含 17 个 Rust crate、297 个前端文件、66 个小程序页面的中型医疗 SaaS 平台。 + +但开发过程中暴露了一个不可忽视的信号:**近 1/4 的提交在修 bug**。 + +### 1.1 核心数据 + +| 指标 | 值 | 含义 | +|------|-----|------| +| 总提交 | 770 次 | 33 天,日均 23 次 | +| fix 类型提交 | 175 次(22.7%) | 近 1/4 的提交在修 bug | +| 近月 fix 率 | 151/630 = 24.0% | 趋势未改善 | +| 单次批量 fix 最高 | 16 个问题 | 角色测试 V3 一轮发现 16 个 | +| 角色测试总发现 | 27 个独立问题(4 轮) | 测试→发现→修复周期长 +| V1→V2 审计 | 新增 21 个问题 | 新代码持续引入新 bug | + +### 1.2 fix 提交类别分布(全部 175 次) + +| 类别 | 次数 | 占比 | 典型模式 | +|------|------|------|---------| +| 前后端接口不一致 | ~35 | 20% | 字段名/路径/类型不匹配 | +| 权限/菜单/路由 | ~25 | 14% | 权限码散落、菜单不可见 | +| 安全(租户隔离/PII) | ~25 | 14% | SQL 注入、越权、CORS | +| 小程序特有问题 | ~28 | 16% | 登录态、平台限制、Storage | +| 后端开发了前端未集成 | ~10 | 6% | 硬编码假数据、缺失对接 | +| 数据库/迁移 | ~15 | 9% | 表名错误、SQL 方言、幂等性 | +| 状态管理/竞态 | ~15 | 9% | 事件链断裂、CAS、并发 | +| 其他(编译/UX/AI) | ~22 | 13% | 类型错误、AI 模型适配 | + +### 1.3 时间线上的问题密度 + +``` +4 月 10-15 日 ██████ 基础设施搭建 + 首批权限问题(fix 15 次) +4 月 16-22 日 ████████ 核心医疗模块 + 安全首次审计(fix 28 次) +4 月 23-28 日 ██████████ 内容管理+AI+透析扩展(fix 35 次,高峰) +4 月 29-5 月 4 ██████████ V1 审计 + 质量加固(fix 30 次) +5 月 5-8 日 ████████████ 角色测试 4 轮迭代(fix 45 次,最高峰) +5 月 9-13 日 ████████ 媒体库+轮播图+Copilot(fix 22 次) +``` + +**观察:fix 密度在 5 月 5-8 日达到最高峰**,原因是 4 轮角色测试集中发现了 27 个问题。这表明大量 bug 在引入后数天甚至数周才被发现,而非在开发时就被拦截。 + +--- + +## 2. 问题目录 — 八类问题的具体案例与根因 + +### 2.1 前后端接口不一致(~35 次 fix,占比最高) + +这是出现频率最高的问题类型,贯穿整个项目周期。 + +**问题 A:字段名不匹配** +- 后端 DTO 用 `consultation_type`,前端写 `type` → 请求 422 +- 后端 DTO 用 `planned_date`,前端写 `due_date` → 数据丢失 +- 后端返回 `unread_count_patient`,前端读 `unread_count` → 显示 NaN +- commit: `c53f562` fix(web,miniprogram): 端到端测试修复 + 33 接口字段对齐 + +**问题 B:请求体结构不匹配** +- 后端 `CreateFollowUpRecordReq` 要求 `{task_id, result, patient_condition}`,前端传 `{task_id, content:{text}}` → 422 +- commit: `8316281` fix(miniprogram): 修复 API 接口字段对齐 -- 33 接口端到端验证 +- commit: `fbb28e6` fix(miniprogram): submitRecord 补充 task_id 字段 + +**问题 C:返回数据格式不匹配** +- 后端 `Vec<(NaiveDate, f64)>` 序列化为数组 `[[date, value]]`,前端期望对象 `[{date, value}]` → 趋势图不显示 +- commit: `1f8fd04` fix(health): 趋势图数据不显示 -- 后端 DTO 元组转结构体 + +**问题 D:遗漏字段** +- 后端文章列表 API 缺少 `version` 字段,前端更新时无法做乐观锁 → 更新覆盖 +- commit: `96b952c` fix(health): 文章列表 API 补充 version 字段 + +**根因**:后端 Rust DTO 和前端 TypeScript 接口各自维护,没有任何自动同步机制。后端改了字段名,前端不知道。 + +--- + +### 2.2 权限/菜单/路由问题(~25 次 fix,持续时间最长) + +从 4 月 11 日到 5 月 10 日,权限相关 fix 持续出现 29 天,是最顽固的问题类别。 + +**问题 A:权限码格式不统一** +- seed 迁移用冒号分隔 `health:patient:list`,handler 检查用点号 `health.patient.list` → **所有权限检查返回 403** +- commit: `0d7d3af` fix(auth): 权限编码冒号改点号 + 补充缺失权限 + +**问题 B:菜单三重配置遗漏** +- 媒体库菜单不可见,排查发现三个独立问题: + 1. parent_id 查找条件错误(指向不存在的父菜单) + 2. menu INSERT 缺少 permission 字段 + 3. 缺少 menu_roles 角色关联 +- commit: `edb4b65` fix(health): 修复媒体库和轮播图菜单不可见 -- 三重修复 + +**问题 C:路由注册方式导致中间件泄漏** +- Axum `.merge()` 导致 middleware 泄漏到整个路由树,公开端点被加了认证中间件 +- 改用 `.nest()` 隔离后才修复 +- commit: `84b671d` fix(server+health): 修复路由 middleware 泄漏 + +**问题 D:权限码缺 .list 导致 403** +- 每个实体需要 `.list` + `.manage` 两个权限码,漏掉 `.list` 列表页直接 403 +- 这个问题在 CLAUDE.md 反模式中已有警告,但仍反复出现 + +**根因**:权限系统涉及 4 层同步(handler 权限码 → seed 迁移 → 前端路由 meta → 菜单可见性),每加一个功能需手动同步 4 处,遗漏率几乎 100%。 + +--- + +### 2.3 安全问题(~25 次 fix,4 轮审计才收敛) + +**问题 A:SQL 注入** +- `action_inbox_service.rs` 用 `format!` 拼接 `patient_id`/`user_id` 到 SQL → 注入向量 +- commit: `2b90db4` fix(health): P0 安全修复 + +**问题 B:FHIR 越权** +- `allowed_patient_ids` 已声明但未在查询层强制执行 → 第三方可访问非授权患者数据 +- commit: `2b90db4` + `4828713` fix(health): FHIR 子查询添加 tenant_id 过滤 + +**问题 C:开发配置泄漏到生产** +- JWT Secret 硬编码 `"dev-secret-key"` 作为 fallback +- CORS 通配符 `*` 在生产环境生效 +- commit: `f7bf5a8` fix(server): CORS 生产环境拒绝通配符 + +**问题 D:默认放行模式** +- OAuth 端点无权限检查、限流默认放行、Redis 不可达时直接放行 +- 每次安全审计都发现同类问题:**开发便利优先,生产安全靠人工事后加固** +- commit: `080d2cb` fix(security): 限流 fail-closed + 多租户安全加固 + +**根因**:缺乏"安全默认"原则。所有新端点默认放行,需要开发者主动加限制 → 必然遗漏。 + +--- + +### 2.4 小程序特有问题(~28 次 fix) + +**问题 A:登录态管理混乱** +- 退出登录后刷新仍保持登录态(Storage 未清理) +- useDidShow 生命周期中认证恢复失败 +- 页面间用 Storage 传递数据,刷新后丢失 +- commit: `3c828bf` + `6632985` + `f75bc19` + +**问题 B:微信平台限制未适配** +- `` 不支持 HTTP URL(轮播图 404) +- 域名白名单未配置 +- commit: `4788e19` fix(health,miniprogram): 轮播图改用相对路径 + +**问题 C:关怀模式(老年适配)** +- 非线性放大计算错误,页面尺寸异常 +- 20px 字号低于适老阈值 22px +- commit: `4335f7e` + `257ca94` + +**根因**:小程序 124 文件 0 测试,质量保障完全真空。所有问题靠手动发现。 + +--- + +### 2.5 后端开发了但前端未集成(~10 次 fix) + +**问题 A:前端仍用硬编码假数据** +- 运营仪表盘、统计页、系统信息页在 API 就绪后仍显示假数据 +- commit: `2e4d98c` fix(web): 统计页空列表接入真实 API + 运营待办去硬编码 + +**问题 B:新端点已开发但未对接** +- `GET /health/vital-signs/today` 后端已开发,前端未调用 +- commit: `d26a847` fix(health): 对接今日体征摘要新端点 + +**问题 C:后端返回关联数据但前端仍显示原始 ID** +- 告警详情显示原始 patient_id / rule_id,未做关联展示 +- commit: `0acf901` fix(web): 告警详情显示患者名和规则标题替代原始 ID + +**根因**:前后端开发节奏不同步,后端先完成但无机制追踪前端是否已集成。 + +--- + +### 2.6 数据库/迁移问题(~15 次 fix) + +**问题 A:表名单复数混用** +- Entity 定义用 `tenant`(单数),迁移 SQL 写 `tenants`(复数)→ 外键引用失败 +- commit: `a174f88` fix(migration): 修复表名 tenants 改为 tenant + +**问题 B:SQL 方言不兼容** +- PostgreSQL `DELETE` 不支持 `LIMIT`,迁移脚本写成了 MySQL 语法 +- commit: `d5c9654` fix(db): 修复 SQL 语法 + RLS 动态表名查询 + +**问题 C:迁移非幂等** +- 多次执行同一迁移会报唯一约束冲突 +- commit: `99dad17` fix(server+health): 修复迁移幂等性 + +**根因**:迁移脚本缺乏在 fresh database 上的自动验证。 + +--- + +### 2.7 状态管理/竞态条件(~15 次 fix) + +**问题 A:Token 刷新并发竞态** +- 同一 refresh token 并发使用两次,先查后改非原子操作 → token 失效 +- commit: `3e1413a` fix(auth): 修复 Token 刷新并发竞态条件 + +**问题 B:事件链断裂** +- `consultation.new_message` 和 `lab_report.reviewed` 事件已发布但消费者未注册 → 功能静默失败 +- commit: `ef0b784` fix(health): 修复两条断裂事件链 + +**问题 C:CAS 条件过严** +- 预约 CAS 精确匹配排班时段,时区偏移导致匹配失败 +- commit: `9b8c2ff` fix(health): 预约 CAS 从精确匹配改为范围匹配 + +**根因**:事件消费者注册无启动时检查,CAS 操作缺乏统一封装。 + +--- + +### 2.8 编译/UX/AI 等其他问题(~22 次 fix) + +**编译/类型错误** — 10 处 TypeScript 编译错误(`fb809f1`)、Rust 类型不匹配(`7ab89f5`) +**AI 模型适配** — qwen3 thinking 模式导致输出为空(`b1a96ac`)、分析结果 JSON 嵌套(`1f91dcc`) +**UX 微调** — 文章预览尺寸(`6269815`)、仪表盘浮点精度(`0721733`) + +这类问题量小且影响有限,不作为流程优化重点。 + +--- + +## 3. 连锁效应分析 — "修一个,冒两个" + +开发过程中最让人沮丧的不是单个 bug,而是修了 A 之后发现 B 也坏了。以下是三个典型案例。 + +### 3.1 媒体库五连修(5 月 10 日,5 次连续 fix) + +``` +step 1: 实现媒体库 + 轮播图(feat 提交 ×5) +step 2: fix — 图片不显示,缺 /uploads Vite 代理 +step 3: fix — 修完路径后图片 401,需要 JWT token +step 4: fix — Web 修好了,小程序轮播图又 404(HTTP 限制) +step 5: fix — 图片修好了,菜单看不到(三重配置遗漏) +step 6: fix — 迁移外键引用表名错误 +``` + +**一个功能,5 次 fix,每次只发现一类问题。** 如果有功能完成检查清单(DoD),第一步就能发现所有 5 类问题。 + +### 3.2 权限系统贯穿全周期(4 月 11 日 → 5 月 10 日,29 天未收敛) + +``` +4/11 fix: 权限编码冒号→点号 + 补充缺失权限 +4/16 fix: 移除权限 fallback(必须显式分配) +4/24 fix: 修复路由 middleware 泄漏 +4/25 fix: 权限同步 + 迁移幂等性 +5/05 fix: 权限同步修复(又发现遗漏) +5/06 fix: 权限守卫、权限配置问题 +5/07 fix: 权限越权(角色测试发现) +5/10 fix: 菜单不可见(媒体库,又是权限问题) +``` + +**29 天内持续出现,每次修了"一处"但"其他处"仍然不一致。** 根本原因是权限定义散落在 4 处,没有单一真相源。 + +### 3.3 角色测试四轮迭代(5 月 5-8 日,10 次批量 fix) + +``` +第 1 轮: 发现 5 个共性问题 → fix +第 2 轮: 发现 8 个问题 → fix +第 3 轮: 发现 4 个共性问题 → fix +第 4 轮: 发现 7 个问题 → fix + 小程序多角色找茬: 16 个问题 → fix + 小程序 V2: 11 个问题 → fix + 小程序 V3: 8 个问题 → fix + 业务链路测试: 3 类问题 → fix +``` + +**10 次批量 fix 才收敛。** 如果每个功能在开发时就有基本的端到端验证,这些问题在第一次角色测试前就应该被拦截。 + +### 3.4 连锁效应的根本原因 + +| 根本原因 | 表现 | 涉及的 fix 次数 | +|---------|------|----------------| +| **缺少功能完成检查清单** | 每次只修一类问题,不全面验证 | ~60 次 | +| **同步点散落在多处** | 修了一处忘了另一处 | ~40 次 | +| **验证滞后** | 开发时不验证,测试/审计时集中发现 | ~50 次 | + +--- + +## 4. 六位专家发散讨论 + +基于以上问题目录,召集六位虚拟专家从不同视角讨论流程改进方案。 + +### 专家 1:流程架构师 — "为什么同样的问题反复出现?" + +**核心论点:24% fix 率不是代码质量问题,是流程缺失问题。** + +1. **缺少 Feature DoD(功能完成定义)** + - 现状:代码写完 → 提交 → 下一个功能。没有统一的完成标准。 + - 媒体库 5 次 fix 说明:每次只验证了一类问题,没有"全量验证"步骤。 + - 建议:建立 Feature DoD 清单,写入 CLAUDE.md,每个功能标记"完成"前必须逐项检查。 + +2. **反馈周期太长** + - bug 在引入后数天甚至数周才被发现(角色测试时),修复成本指数级增长。 + - 角色测试 4 轮才收敛(27 → 11 → 8 → 3),而不是一轮完成。 + - 建议:每个功能完成时立即做 5-10 分钟的端到端手动验证。 + +3. **没有"破坏性变更"意识** + - 新增迁移/路由/权限时不检查是否影响已有功能。 + - V1→V2 审计发现 21 个新问题,说明新代码持续引入回归。 + - 建议:CI 增加基于 diff 的定向回归测试。 + +**"如果只能改一件事":** 建立 Feature DoD 清单并强制执行。 + +--- + +### 专家 2:质量工程专家 — "测试是写代码前的契约,不是写完后的补救" + +**核心论点:测试金字塔倒挂严重,前端几乎无自动化保障。** + +1. **后端测试量大但结构性缺陷** + - 999 个测试函数,但异步测试仅 184 个(18.4%)。 + - 并发预约、事件消费、多租户隔离等核心路径缺异步集成测试。 + - 预约并发 bug 只在角色测试时被发现,单元测试无法捕获。 + +2. **前端测试覆盖率严重不足** + - Web:297 文件 / 62 测试文件(1:4.8) + - 小程序:124 文件 / **0 测试** — 质量保障真空 + - 小程序 31 次 fix 中大部分是状态管理和 API 对接问题,自动化测试完全可以预防。 + +3. **缺少"错误预算"概念** + - fix 率 24% 没有目标、没有趋势监控。 + - 建议:设定 fix 率目标 < 15%,每周跟踪趋势。 + +**"如果只能改一件事":** 给小程序补 service 层测试。124 文件 0 测试是最大质量真空。 + +--- + +### 专家 3:安全审计专家 — "安全靠设计时预防,不靠事后发现" + +**核心论点:25 次安全 fix 中 80% 可以通过安全 lint 在提交前拦截。** + +1. **安全修复模式高度重复** + - 每次都是同一个模式:默认放行 → 发现问题 → 收紧。 + - CORS 通配符、OAuth 无权限、FHIR 越权、限流放行 — 本质都是"默认放行"。 + - 建议:建立"安全默认"原则 — 所有新端点默认拒绝,必须显式声明权限。 + +2. **租户隔离反复遗漏** + - 从 4 月 11 日到 5 月 5 日,24 天内租户隔离问题出现 5 次。 + - 每次审计都发现新的遗漏点。 + - 建议:租户过滤统一中间件,禁止手写 tenant_id 过滤。 + +**"如果只能改一件事":** 在 CLAUDE.md 增加"新增端点安全检查清单"。 + +--- + +### 专家 4:DevOps/自动化专家 — "人能记住的事,不应该靠人记住" + +**核心论点:24% fix 率的本质是手动同步成本。** + +1. **权限码 4 处手动同步是最大系统性 bug 源** + - handler / seed / 路由 meta / 菜单 — 每加一个功能同步 4 处,遗漏率 100%。 + - 12+ 次权限相关 fix,每次都是"忘了同步第 N 处"。 + - 建议:`permissions.yaml` 单一真相源 + 构建时自动生成。 + +2. **缺少 CI 质量门禁** + - 当前只有 `cargo check` + `cargo test`,没有权限完整性检查、路径一致性检查、安全 lint。 + - 建议:CI 增加 4 个门禁(权限/路径/安全/覆盖率)。 + +3. **OpenAPI 注解 33%,前端完全不用 spec** + - 后端生成 spec,前端手写路径,两边必然分叉。 + - 建议:openapi-typescript 自动生成前端 API 客户端。 + +**"如果只能改一件事":** 实施 `permissions.yaml` 单一真相源。消除 12+ 次 fix 的根因。 + +--- + +### 专家 5:产品/需求管理专家 — "功能冻结≠冻结完成,而是冻结了技术债" + +**核心论点:需求推进速度 > 质量保障速度。** + +1. **6 个冻结模块是隐性成本** + - 护理计划 44 分、班次 41 分 — 完成度极低但持续占用编译体积和认知负担。 + - 建议:冻结超时策略 — 冻结 > 2 周自动触发决策(完成或移除)。 + +2. **缺少质量红线** + - 770 次提交中 24% 是 fix,说明需求推进速度远超质量保障速度。 + - 建议:fix 率 > 20% 时新功能需额外审批。 + +3. **缺少"最小可验证增量"** + - 媒体库一次提交 5+ 个 crate 的改动,验证只能事后进行。 + - 建议:拆分为更小的可验证增量,每步有明确验证标准。 + +**"如果只能改一件事":** 设定质量红线 — fix 率 > 20% 时优先偿还技术债。 + +--- + +### 专家 6:技术债务分析师 — "债务不可怕,可怕的是不可见" + +**核心论点:技术债缺乏可视化管理。** + +1. **已完成的技术债偿还** + - event.rs 2871 行 → 已拆分为 13 个领域文件 + - module.rs 1595 行 → 已拆分为 13 个子模块 + +2. **未处理的技术债** + - erp-health 仍为巨石(189 文件,12 子域) + - utoipa 注解 33% + - 小程序 0 测试 + - 6 个冻结模块 + +3. **建议:建立技术债看板** + - 量化每项债务的"利息"(修复频率 × 修复成本) + - 每个迭代 20% 时间用于偿还 + +**"如果只能改一件事":** 建立技术债看板,让债务利息可视化。 + +--- + +## 5. 共识与行动方案 + +### 5.1 六位专家的共识 + +| # | 共识 | 专家一致性 | +|---|------|-----------| +| C1 | 24% fix 率是系统性流程问题,非个别代码质量问题 | 6/6 | +| C2 | 权限码 4 处手动同步是最高优先级的自动化目标 | 6/6 | +| C3 | 小程序 0 测试是最大质量真空 | 5/6 | +| C4 | 缺少 Feature DoD 是 fix 反复出现的直接原因 | 6/6 | +| C5 | 前后端接口不一致的根因是缺少契约自动同步 | 6/6 | +| C6 | 新需求推进速度 > 质量保障速度 | 6/6 | + +### 5.2 分歧与权衡 + +| 议题 | 观点 A | 观点 B | 建议 | +|------|--------|--------|------| +| 新功能 vs 技术债 | 设质量红线,fix > 20% 停新功能 | 过于刚性,影响交付 | **软红线**:fix > 20% 时新功能需额外审批 | +| 权限注册表方案 | YAML 单一真相源 + 自动生成 | 改造成本高,先用 lint | **分两步**:先 lint 拦截,再迁移 YAML | +| 小程序测试策略 | 先补 service 层接口测试 | 先补关键页面 E2E | **service 层优先**(投入产出比更高) | +| 冻结模块处理 | 立即决定:完成或移除 | 等有资源时处理 | **冻结超时**:> 2 周自动触发决策 | + +### 5.3 行动方案(按优先级排序) + +#### P0 — 立即实施(1-2 天见效) + +| # | 行动 | 投入 | 消除的 fix 类别 | +|---|------|------|----------------| +| P0-1 | **建立 Feature DoD 清单**,写入 CLAUDE.md | 2h | 权限遗漏、菜单不可见、安全默认、前后端不一致 | +| P0-2 | **新增端点安全检查清单**,写入 CLAUDE.md | 1h | CORS/OAuth/限流/脱敏遗漏 | +| P0-3 | **CLAUDE.md 增加前后端同步检查项** | 1h | 字段名/路径/类型不匹配 | + +#### P1 — 本周实施(3-5 天见效) + +| # | 行动 | 投入 | 消除的 fix 类别 | +|---|------|------|----------------| +| P1-1 | **权限注册完整性 CI 检查**:handler 权限码 vs seed 一致性 | 4h | 权限码不一致 | +| P1-2 | **API 路径一致性 CI 检查**:前端 API 路径 vs 后端 OpenAPI spec | 1d | 前后端路径分叉 | +| P1-3 | **小程序 service 层测试**(29 个文件) | 2d | 小程序 API 对接问题 | +| P1-4 | **`createProtectedRoute()` wrapper** — 不声明权限码则无法创建路由 | 0.5d | 路由守卫遗漏 | + +#### P2 — 下阶段实施(持续改进) + +| # | 行动 | 投入 | 效果 | +|---|------|------|------| +| P2-1 | `permissions.yaml` 单一真相源 + 自动生成 | 3-5d | 根除权限同步问题 | +| P2-2 | openapi-typescript 自动生成前端 API 客户端 | 2-3d | 根除路径分叉 | +| P2-3 | 冻结模块策略(完成/移除/超时) | 1d | 减少隐性技术债 | +| P2-4 | 技术债看板建立 | 1d | 债务可视化 | +| P2-5 | fix 率趋势监控(每周跟踪) | 0.5d | 质量趋势感知 | + +### 5.4 度量体系 + +| 指标 | 当前值 | 目标值 | 测量方式 | +|------|--------|--------|---------| +| fix 率 | 24% | < 15% | fix 提交数 / 总提交数 | +| 权限同步遗漏 | 12+ 次/月 | 0 次 | CI 检查结果 | +| 前端测试文件 | 62/297 | 120/297 | 文件计数 | +| 小程序测试 | 0 文件 | 29 service 全覆盖 | 文件计数 | +| 单次批量 fix | 16 个 | < 5 个 | 单次提交修复数 | + +### 5.5 质量红线 + +| 红线 | 触发条件 | 行动 | +|------|---------|------| +| fix 率 > 20% | 连续 2 周 | 新功能需额外审批 | +| 单次批量 fix > 10 | 单次提交 | 回溯 DoD 是否执行 | +| 安全 CRITICAL | 审计发现 | 立即修复,暂停其他 | + +--- + +## 附录 A:Feature DoD 清单(建议版本) + +每个功能标记"完成"前,必须通过以下检查清单: + +```markdown +## Feature DoD — 功能完成检查清单 + +### 后端 +- [ ] Entity 包含所有标准字段(id/tenant_id/created_at/updated_at/deleted_at/version) +- [ ] Handler 添加 require_permission 权限守卫 +- [ ] 权限码已写入 seed 迁移(.list + .manage) +- [ ] utoipa 注解已添加(OpenAPI 文档可见) +- [ ] Service 层核心路径有单元/集成测试 +- [ ] 多租户隔离正确(tenant_id 过滤) +- [ ] 输入验证完整(必填字段 + 格式校验) +- [ ] 错误处理统一(AppError,不 panic) +- [ ] 关键操作有 tracing 日志 + +### 前端(Web) +- [ ] API 路径与后端 OpenAPI spec 一致 +- [ ] 路由使用 createProtectedRoute 并声明权限码 +- [ ] 菜单配置已更新(可见性 + 权限关联) +- [ ] 错误状态有用户友好提示 +- [ ] 不使用 any 类型 + +### 前端(小程序) +- [ ] Service 层接口契约与后端 DTO 一致 +- [ ] 登录态处理正确(useDidShow 恢复) +- [ ] 长者模式适配完成 +- [ ] 无硬编码路径 + +### 安全 +- [ ] 新增端点有权限声明(非默认放行) +- [ ] 敏感数据有脱敏/加密处理 +- [ ] 用户输入已验证和消毒 +- [ ] 无 CORS 通配符 + +### 验证 +- [ ] cargo check 全 workspace 通过 +- [ ] cargo test 全部通过 +- [ ] 浏览器中手动验证功能正常 +- [ ] 相关路由权限按角色测试通过 +``` + +--- + +## 结论 + +**核心洞察:24% fix 率的根因不是"代码写得不好",而是"流程让好代码也容易出错"。** + +权限散落 4 处、前后端类型各自维护、缺少完成检查清单、验证滞后 — 这些是系统性问题,需要系统性解决。 + +**最有效的三件事:** +1. **Feature DoD**(2h 投入)— 让每次提交都经过全量检查 +2. **权限/路径 CI 一致性检查**(1-2d 投入)— 让不一致无法通过 CI +3. **小程序 service 层测试**(2d 投入)— 填补最大质量真空 + +这三件事做完,预计 fix 率可从 24% 降至 15% 以下。