docs: V1 发布策略头脑风暴 + 六维度发布就绪度分析文档

This commit is contained in:
iven
2026-05-20 17:53:10 +08:00
parent 65cf96f119
commit 853a0ca2b4
2 changed files with 708 additions and 0 deletions

View File

@@ -0,0 +1,421 @@
# V1 发布策略多专家组辩论 — 会议记录
> 日期: 2026-05-20 | 参与者: 安全工程师、SRE、产品经理、架构师、测试工程师、前端专家
> 主持人: Claude (AI 顾问) | 基于: 六维度全面均衡分析 (6.8/10 B)
---
## 背景
系统经过 862 次提交、17 个 crate、652 个 Rust 源文件、307 个前端文件的开发V1 全面端到端测试已完成。原 2 CRITICAL + 7 HIGH 全部解决,综合评分 6.2/10 B-,当前在 `feat/media-library-banner` 分支。
六维度分析显示:架构 8.5、安全 7.5、前端 7.2、产品 8.0 表现良好;测试 5.5、DevOps 3.8 是短板。本次会议目标:确定 V1 发布的 GO/NO-GO 标准和行动清单。
---
## 议题 1: V1 发布范围 — 大而稳 vs 小而快
### 安全工程师(正方:先修完安全问题再发布)
> "医疗数据泄漏的法律后果是毁灭性的。我们目前的隐患:
> 1. Analytics 端点缺权限校验 — 任何认证用户都能访问全租户分析数据
> 2. 缺 HSTS 和 CSP — 中间人攻击可以注入恶意脚本
> 3. 日志中 PII 脱敏不完整 — 开发日志可能泄漏患者姓名、身份证号
> 4. 没有生产环境 TLS — 所有数据在网络上明文传输
>
> 这些问题修起来都不难1-2 天总量),但不修就发布等于知道有洞还跳。医疗行业合规要求我们至少做到传输加密和访问控制。"
### SRE正方先建立运维基础设施再发布
> "我同意安全问题要修,但我想强调运维视角:没有监控、没有告警、没有备份策略就上线,等于盲飞。
>
> 具体风险:
> 1. 数据库没有加密备份和异地副本 — 医疗法规要求 7 年数据保留,磁盘坏了数据就没了
> 2. 没有 Prometheus/Grafana — 我们不知道 API 响应时间、错误率、资源使用情况
> 3. 迁移在启动时自动执行 — 156 个迁移,任何一个失败就起不来
> 4. 没有 CD 流水线 — 手动部署意味着每次发布都是冒险
>
> 建议监控和备份可以跟安全修复并行做3-5 天搞定。"
### 产品经理(反方:核心功能验证通过即可发布)
> "我理解安全和运维的顾虑,但请注意几个事实:
>
> 1. **发布不等于面向公众开放** — V1 是给首批试点客户1-2 家体检中心)使用的,内网环境部署
> 2. **核心功能已经过充分验证** — E2E 覆盖 157 个端点5 角色测试通过率 86.5%,小程序多角色 96.2%
> 3. **冻结 6 个模块不影响核心流程** — 患者管理、预约、随访、咨询、健康数据这 5 个核心流程都是完整的
> 4. **竞争对手不会等我们** — 每 delay 一周,就可能失去试点窗口
>
> 我的提案:把安全问题分两类 — 阻塞性的Analytics 权限、TLSV1 必修非阻塞性的日志脱敏、CSP可以 V1.1。运维同理 — 备份策略必修CD 可以 V1.1。"
### 架构师(关注架构债务)
> "从架构角度,我比较关心两个问题:
>
> 1. **事件消费者幂等性不统一** — 如果同一个 `patient.created` 事件被投递两次,有的消费者会创建重复数据。这在启动时 outbox replay 的场景下一定会发生。但好消息是:我们有 dead-letter 存储,而且启动 replay 频率很低。
>
> 2. **缓存层薄弱** — 没有 Redis每次请求都打数据库。在试点阶段几十个用户不是问题但要注意。
>
> 我的判断:架构层面没有阻塞性问题。事件幂等性是 P1 级别V1 阶段靠 dead-letter 兜底即可。缓存层 V1.1 再加。"
### 辩论交锋
**安全工程师**: "内网环境不代表没有风险。内部员工越权访问分析数据、开发人员电脑被入侵通过日志获取 PII — 这些都是实际威胁。"
**产品经理**: "我同意 Analytics 权限必须修1 小时的工作量不应该成为阻塞项。但 TLS 在内网部署场景下实际上是反向代理层Nginx做的不是应用层的责任。"
**SRE**: "Nginx 做 TLS 终止是标准做法,但我需要确保我们提供配置模板和文档。另外,备份策略真的不能拖 — 医疗数据的合规要求不是'建议'。"
**架构师**: "折中方案 — V1 发布附带一份'部署检查清单',列出 TLS、备份等运维要求。应用层修 Analytics 权限和安全头HSTS/CSP基础设施层由部署文档覆盖。"
### 议题 1 共识
**结论:有条件 GO — "核心安全必修,基础设施文档化"**
| 项目 | 决定 | 理由 |
|------|------|------|
| Analytics 权限校验 | V1 必修 | 1 小时工作量,风险高 |
| HSTS + CSP 安全头 | V1 必修 | 2 小时工作量,标准化做法 |
| TLS 终止 | V1 通过部署文档覆盖 | 内网由 Nginx 处理,不是应用层责任 |
| 日志 PII 脱敏 | V1.1 | 不阻塞试点,但 V1.1 必修 |
| 备份加密+异地 | V1 必修 | 医疗合规硬要求 |
| Prometheus+Grafana | V1.1 | 试点阶段可人工巡检V1.1 正式监控 |
| CD 流水线 | V1.1 | 手动部署在试点阶段可接受 |
| 事件幂等性 | V1.1 | Dead-letter 兜底,非阻塞 |
| 缓存层 | V1.1+ | 试点用户量不需要 |
---
## 议题 2: 测试策略 — 广度优先 vs 深度优先
### 测试工程师正方Handler 测试优先)
> "当前测试数据943 个后端测试,但 Handler 层 0% 覆盖。这意味着:
>
> 1. API 参数校验完全没有自动化验证
> 2. 错误响应格式、HTTP 状态码没有测试
> 3. 权限守卫是否生效没有测试
> 4. 分页、排序、过滤逻辑没有测试
>
> 我们有 47 个 Handler如果每个核心 Handler 只测 CRUD + 权限校验5 个用例),就是 235 个测试。这比小程序测试(影响面小)优先级更高。
>
> 但我也要诚实2.5 天写 235 个测试不现实。务实方案是只覆盖高风险 Handler — health 模块的核心实体(患者、预约、咨询、健康数据)约 10 个 Handler50 个测试。"
### 安全工程师(正方:安全中间件测试优先)
> "我不同意。安全中间件 0% 测试覆盖意味着:
>
> 1. 多租户隔离可能被绕过 — 我们没有测试跨租户访问
> 2. 权限守卫可能失效 — 我们没有测试 require_permission 的拒绝路径
> 3. JWT 过期/刷新逻辑没有测试 — 生产环境 token 异常无法预测
>
> 安全中间件是所有 Handler 的前提。如果中间件有漏洞,所有 Handler 的权限检查都形同虚设。而且中间件测试数量少(约 15-20 个1.5 天足够。"
### 前端专家(正方:小程序测试优先)
> "小程序 60 个页面0 个单元测试。而且小程序已经经历了至少 15 个 bug fix
>
> - 长轮询 CPU 飙升
> - 并发请求阻塞 30s
> - 页栈超 10 层导航失败
> - 登录卡死
> - DevTools 卡死
>
> 这些都是运行时才发现的问题。如果有单元测试,至少并发控制和导航逻辑可以在 CI 中捕获。小程序是患者直接使用的入口,它的稳定性直接影响用户信任。
>
> 但我承认60 个页面全部写测试不现实。核心层测试request.ts、navigate.ts、auth 相关)约 20-30 个测试2 天可以完成。"
### 产品经理(按用户影响排序)
> "三方都有道理但资源有限V1 只有 5-7 天),我们需要按实际影响排序:
>
> 1. **安全中间件测试** — 影响:全系统。如果多租户隔离有问题,所有数据都暴露。优先级最高。
> 2. **核心 Handler 测试** — 影响:核心业务流程。患者 CRUD + 预约 CRUD 是最高频操作。
> 3. **小程序核心层测试** — 影响:患者端用户体验。但小程序已经有 96.2% 的角色测试通过率。
>
> 测试投入顺序:中间件(1.5d) > 核心Handler(1.5d,精简版) > 小程序核心(1d最精简版)。"
### 辩论交锋
**测试工程师**: "产品经理的排序合理,但我想补充一点 — Handler 测试不只要测 happy path还要测 unhappy path。权限拒绝、参数校验失败、并发冲突 — 这些 unhappy path 是 bug 高发区。"
**安全工程师**: "同意。中间件测试也以 unhappy path 为主 — 跨租户访问、过期 token、无权限访问。这些才是安全测试的价值。"
**前端专家**: "小程序测试我接受精简到 1 天。request.ts 的并发控制和重试逻辑是最高优先 — 这是我们修了 3 次 bug 的地方。"
### 议题 2 共识
**结论:分层递进 — "中间件 → 核心Handler → 小程序核心"**
| 层级 | 测试范围 | 预估时间 | 优先级 |
|------|---------|---------|--------|
| 安全中间件 | 多租户隔离、权限拒绝、JWT 异常(~15 个 unhappy path 测试) | 1.5 天 | V1 必须 |
| 核心 Handler | 患者CRUD + 预约CRUD + 咨询CRUD + 健康数据查询(~40 个测试happy+unhappy | 1.5 天 | V1 必须 |
| 小程序核心层 | request.ts 并发控制 + navigate.ts 安全导航 + auth 存储管理(~15 个测试) | 1 天 | V1.1 |
| E2E CI 集成 | 现有 17 个 E2E spec 接入 CI | 0.5 天 | V1.1 |
---
## 议题 3: DevOps 优先级 — 备份 vs 监控 vs CD
### SRE正方备份加密优先
> "医疗数据备份不是'nice to have',是法律要求。《医疗机构管理条例》和等保三级都要求:
>
> 1. 数据至少 3 份副本(生产 + 本地备份 + 异地备份)
> 2. 备份必须加密存储
> 3. 定期恢复演练
>
> 当前状态pg_dump 手动执行,无加密,无异地。磁盘坏了 = 数据没了。
>
> 工作量:写一个备份脚本 + cron job + 加密配置3 天足够。这是 V1 的硬门槛。"
### 安全工程师正方TLS 终止优先)
> "在议题 1 中我们达成了 TLS 由 Nginx 处理的共识,但我要强调 — 如果部署时没人配置 TLS所有数据在网络上是明文的。
>
> 我同意这不是应用层的代码问题,但 V1 发布包必须包含:
> 1. Nginx TLS 配置模板
> 2. 自签名证书生成脚本(开发/测试用)
> 3. 部署文档中明确标注 TLS 为必配项
>
> 这不是代码工作是文档工作。1-2 小时。"
### 架构师(正方:监控优先)
> "我理解备份和 TLS 的重要性,但从运维实践看,没有监控的系统上线后:
>
> 1. 你不知道它慢 — API 响应从 50ms 退化到 500ms用户先感受到你才知道
> 2. 你不知道它挂了 — 直到用户投诉
> 3. 你不知道资源耗尽 — 直到 OOM 崩溃
>
> Prometheus + Grafana 的最小配置 3 天可以搞定。但考虑到试点阶段(内网、几十用户、专人值守),监控可以降级到 '人工巡检 + 日志告警'。
>
> 折中V1 先用简单的 health check + 日志级别告警V1.1 上 Prometheus。"
### 产品经理(用户体验视角)
> "从用户(体检中心)角度看,他们最关心的是:
> 1. 系统能不能用 — 功能完整性(已满足)
> 2. 数据丢不丢 — 备份(合规+信任)
> 3. 出了问题能不能恢复 — 迁移回滚策略
>
> 监控是'我们的问题',不是'用户的问题'。备份是'用户的问题'。
>
> 我的排序:备份(3d) > 部署文档+TLS模板(0.5d) > 迁移策略(1d) > 监控(V1.1)。"
### 议题 3 共识
**结论:备份+部署文档必修,监控 V1.1**
| 项目 | 决定 | 工作量 | 理由 |
|------|------|--------|------|
| 数据库加密备份+异地脚本 | V1 必修 | 3 天 | 医疗合规硬要求 |
| Nginx TLS 配置模板 | V1 必修 | 0.5 天 | 部署必需 |
| 生产迁移策略(回滚方案) | V1 必修 | 1 天 | 防止迁移失败导致不可恢复 |
| Prometheus+Grafana | V1.1 | 3 天 | 试点阶段人工巡检替代 |
| CD 流水线 | V1.1 | 2 天 | 手动部署试点阶段可接受 |
---
## 议题 4: 技术债务取舍 — 哪些可以接受
### 架构师(事件消费者幂等性)
> "当前 12 个消费者模块中,部分消费者(约 4-5 个)没有幂等检查。风险场景:
>
> 1. Outbox replay 时重复投递 — 概率:每次重启都会发生
> 2. 消费者处理成功但确认失败 — 概率:网络抖动时
>
> 影响评估:
> - 重复创建通知消息 → 用户收到重复通知LOW
> - 重复创建随访任务 → 可能创建重复任务MEDIUM
> - 重复更新统计数据 → 幂等(无影响)
>
> V1 结论:可接受。理由:(1) dead-letter 会捕获异常 (2) 试点阶段重启频率低 (3) 最坏情况是重复通知不是数据损坏。V1.1 统一修复。"
### 前端专家i18n 硬编码中文)
> "当前前端所有文案都硬编码中文i18n key 一个没用。但现实是:
>
> 1. 目标用户 100% 中文 — 体检中心在中国
> 2. 短期内没有国际化需求
> 3. i18n 改造工作量巨大 — 307 个 TS/TSX 文件
>
> V1 完全可以接受硬编码。但有两个前提:
> 1. 不能用中文字符串做逻辑判断(比如 `if (status === '已完成')`
> 2. V1.1 要启动 i18n 改造,至少覆盖公共组件和导航
>
> 结论V1 接受V1.1 启动渐进式改造。"
### 测试工程师CI 不覆盖 E2E
> "17 个 E2E spec但 CI 不跑。这意味着:
>
> 1. 每次 push 只跑单元测试
> 2. 回归问题只能在手动测试时发现
> 3. 小程序 E2E 依赖 MCP 连接,更难自动化
>
> 但接入 CI 有实际困难:
> - E2E 需要 PostgreSQL 实例 — 可以用 GitHub Actions service container
> - 需要 Rust 编译 — 编译时间 10-15 分钟
> - 小程序 E2E 需要微信开发者工具 — 无法在 CI 中运行
>
> V1 折中:只接 Web E2E13 个 spec跑在 CI 上。小程序 E2E 继续手动。V1.1 再优化。
>
> 等等,我重新考虑 — V1 时间紧张CI 接入可以 V1.1。试点阶段开发人员手动跑 E2E 是可控的。"
### SRE迁移自动执行
> "156 个迁移在启动时自动执行。风险:
>
> 1. 迁移失败 = 服务启动失败
> 2. 迁移冲突 = 数据库锁死
> 3. 大表迁移 = 启动耗时数分钟
>
> 但实际上:
> 1. 所有迁移都经过本地验证 — cargo test 覆盖
> 2. 启动时只执行新迁移 — 已执行的会跳过
> 3. 试点阶段数据量小 — 迁移速度不是问题
>
> V1 可接受。但 V1.1 需要改进:
> 1. 生产环境迁移改为手动执行 + pre-check
> 2. 添加迁移回滚策略"
### 议题 4 共识
**结论V1 技术债务全面可接受,但需文档化风险**
| 债务 | V1 决定 | V1.1 计划 | 风险等级 |
|------|---------|----------|---------|
| 事件消费者非幂等 | 接受dead-letter 兜底 | 统一幂等修复 | LOW |
| i18n 硬编码中文 | 接受,目标用户全中文 | 渐进式改造,公共组件优先 | NONE |
| CI 不覆盖 E2E | 接受,手动 E2E | Web E2E 接入 CI | MEDIUM |
| 迁移自动执行 | 接受,试点可控 | 手动迁移+pre-check+回滚 | LOW |
| 缓存层缺失 | 接受,试点用户量小 | Redis 热点查询缓存 | LOW |
| main.rs 未拆分 | 接受 | 模块化重构 | NONE |
---
## 修订后的 V1 行动清单
> 基于 4 个议题的辩论共识V1 工作量总计约 **8.5 天**。
### P0 — V1 发布阻塞项(必修,约 4 天)
| # | 项目 | 工作量 | 负责 | 验收标准 |
|---|------|--------|------|---------|
| V1-1 | Analytics 端点权限校验 | 1h | 安全工程师 | 无权限返回 403有权限返回数据 |
| V1-2 | HSTS + CSP + X-Frame-Options 安全头 | 2h | 安全工程师 | 响应头包含安全策略 |
| V1-3 | 数据库加密备份脚本 + 异地同步 cron | 3d | SRE | 每日自动备份 + AES-256 加密 + 异地 rsync |
| V1-4 | Nginx TLS 终止配置模板 + 部署文档 | 0.5d | SRE | 提供可用的 Nginx 配置 + 自签名证书脚本 |
| V1-5 | 生产迁移策略pre-check + 回滚方案) | 1d | SRE + 架构师 | 迁移前检查 + 失败回滚步骤文档化 |
### P1 — V1 发布质量提升(强烈建议,约 3 天)
| # | 项目 | 工作量 | 负责 | 验收标准 |
|---|------|--------|------|---------|
| V1-6 | 安全中间件 unhappy path 测试 | 1.5d | 测试工程师 + 安全工程师 | ~15 个测试多租户隔离、权限拒绝、JWT 异常 |
| V1-7 | 核心 Handler 测试(患者/预约/咨询/健康数据) | 1.5d | 测试工程师 | ~40 个测试CRUD happy + unhappy path |
### V1 可选优化(时间允许时做)
| # | 项目 | 工作量 | 负责 |
|---|------|--------|------|
| V1-8 | 部署检查清单文档(安全+运维+迁移) | 0.5d | SRE |
| V1-9 | 健康检查端点增强(数据库连接+迁移状态) | 0.5d | SRE |
---
## V1.1 行动清单(发布后 2 周内)
| # | 项目 | 工作量 | 优先级 |
|---|------|--------|--------|
| V1.1-1 | Prometheus + Grafana 最小可观测性 | 3d | P0 |
| V1.1-2 | 小程序核心层单元测试request/navigate/auth | 1d | P0 |
| V1.1-3 | Web E2E 接入 CI | 0.5d | P0 |
| V1.1-4 | 日志 PII 脱敏 | 4h | P0 |
| V1.1-5 | 事件消费者幂等统一修复 | 2d | P1 |
| V1.1-6 | CD 流水线GitHub Actions | 2d | P1 |
| V1.1-7 | i18n 渐进式改造(公共组件+导航) | 3d | P1 |
| V1.1-8 | Redis 热点查询缓存 | 2d | P1 |
| V1.1-9 | main.rs 拆分重构 | 2d | P2 |
| V1.1-10 | OpenAPI 自动生成 TS 类型 | 3d | P2 |
| V1.1-11 | 生产迁移改为手动执行 + pre-check | 1d | P1 |
| V1.1-12 | Handler 测试扩展到全部 47 个 | 2d | P1 |
---
## 最终 GO/NO-GO 判定标准
### GO 条件(全部满足才可发布)
| # | 检查项 | 验证方式 | 负责人 |
|---|--------|---------|--------|
| G1 | `cargo check` 全 workspace 通过 | CI 自动 | 开发 |
| G2 | `cargo test --workspace` 全部通过 | CI 自动 | 开发 |
| G3 | Analytics 端点有权限守卫 | 手动验证:无权限用户返回 403 | 安全工程师 |
| G4 | 安全头 (HSTS/CSP/X-Frame-Options) 存在 | `curl -I` 检查响应头 | 安全工程师 |
| G5 | 数据库备份脚本可运行 | 执行备份脚本,验证加密文件生成 | SRE |
| G6 | Nginx TLS 配置模板可用 | `nginx -t` 验证配置正确 | SRE |
| G7 | 迁移 pre-check 和回滚方案已文档化 | 评审文档 | SRE + 架构师 |
| G8 | 安全中间件 unhappy path 测试通过 | CI 自动(~15 个测试) | 测试工程师 |
| G9 | 核心 Handler 测试通过(患者/预约/咨询/健康数据) | CI 自动(~40 个测试) | 测试工程师 |
| G10 | 浏览器手动验证核心流程患者CRUD + 预约 + 随访) | 手动测试 | 产品经理 |
| G11 | 小程序手动验证核心流程(登录 + 健康数据 + 咨询) | 手动测试 | 产品经理 |
| G12 | 部署文档完整TLS/备份/迁移/检查清单) | 评审文档 | SRE |
### NO-GO 触发条件(任一即阻塞)
| # | 条件 | 理由 |
|---|------|------|
| N1 | 多租户数据隔离被突破 | 安全底线 |
| N2 | 核心业务流程(患者/预约/咨询)无法完成 | 产品底线 |
| N3 | 数据库备份无法执行或无法恢复 | 合规底线 |
| N4 | P0 安全漏洞未修复Analytics 越权) | 安全底线 |
| N5 | 迁移在目标环境执行失败且无回滚方案 | 运维底线 |
### 条件说明
- **GO**: 全部 G1-G12 满足 → V1 可发布到试点环境
- **CONDITIONAL GO**: G1-G7 + G10-G12 满足G8-G9 部分完成 → V1 可发布,但需在 V1.1 首批补全测试
- **NO-GO**: 任一 N1-N5 触发 → 回到开发,修复后重新评估
### 预计时间线
| 阶段 | 时间 | 内容 |
|------|------|------|
| P0 修复 | Day 1-4 | V1-1 到 V1-5安全+运维+迁移) |
| P1 测试 | Day 3-6 | V1-6 到 V1-7与 P0 并行启动) |
| 验收 | Day 7 | G1-G12 全项检查 |
| 发布 | Day 8 | 部署到试点环境 |
| V1.1 启动 | Day 15 | 监控 + 小程序测试 + 日志脱敏 |
---
## 附录:专家组成员与立场总结
| 专家 | 核心立场 | 最大让步 |
|------|---------|---------|
| 安全工程师 | 安全问题必须全部修复才发布 | 日志脱敏和 CSP 可 V1.1,但 Analytics 权限和 TLS 不可妥协 |
| SRE | 备份+监控缺一不可 | 监控可降级为人工巡检,但备份不可妥协 |
| 产品经理 | 核心功能通过即可发布 | 安全硬伤必须修,但非阻塞性问题可推迟 |
| 架构师 | 架构债务可管理即可 | 幂等性和缓存可推迟,但 dead-letter 兜底必须有 |
| 测试工程师 | Handler 测试覆盖是底线 | 可精简到 10 个核心 Handler但中间件测试不可妥协 |
| 前端专家 | 小程序测试是定时炸弹 | 核心层测试可推迟到 V1.1,但需文档化风险 |
---
## 结论
> **最终判定: CONDITIONAL GO**
>
> V1 发布到试点环境是可行的,但需要满足 P0 阻塞项(安全+备份+迁移策略。P1 测试(中间件+核心Handler建议在发布前完成但如果时间紧张可以 CONDITIONAL GO — 在 V1.1 首批补全。
>
> 关键共识:
> 1. 发布不等于公开上线 — 试点环境内网部署,风险可控
> 2. 安全底线不可妥协 — Analytics 权限 + TLS + 备份必须到位
> 3. 测试是信心问题不是功能问题 — 中间件 unhappy path 测试是最低要求
> 4. 运维文档与代码同等重要 — 部署检查清单是 V1 的一部分
>
> 总工作量P0 约 4 天 + P1 约 3 天 = **7 天可达 GO8-9 天可达充分 GO**。

View File

@@ -0,0 +1,287 @@
# HMS V1 发布就绪度 — 六维度全面均衡分析
> 日期: 2026-05-20 | 分支: feat/media-library-banner | 分析方法: 4 并行探索 + 6 专家组深度分析
## 综合评分: 6.3/10 (B-)
| 维度 | 评分 | 评级 | 趋势 | 核心发现 |
|------|------|------|------|---------|
| 架构 | **8.0** | A- | ↑ | 模块边界 9/10事件消费者幂等不统一缓存层薄弱 |
| 安全 | **7.5** | B+ | → | PII 加密企业级 9/10analytics 缺权限(HIGH),缺 HSTS/CSP |
| 前端 | **7.2** | B | ↑ | 64 页面全 lazy长者模式 100%,小程序零测试 |
| 产品 | **~7.0** | B | → | 核心流程完整6 模块冻结2 个 TODO 空实现 |
| 测试 | **5.5** | C+ | → | 990 测试但 Handler 0%,小程序 0中间件 0 |
| DevOps | **3.8** | D+ | ↑ | CD 缺失,备份不合规,无监控告警 |
---
## 一、架构维度 (8.0/10)
### 1.1 模块边界 — 优秀 (9/10)
- erp-core (L1) 零业务依赖,所有 L2 模块彼此零依赖erp-server (L3) 唯一组装点
- 8 个模块全部实现 ErpModule traitModuleRegistry 按拓扑排序启动
- 天然支持微服务拆分:只需将 EventBus 从进程内 broadcast 替换为消息队列
### 1.2 SQL 拼接风险 — 安全但有代码气味 (7/10)
| 位置 | 类型 | 风险 |
|------|------|------|
| `erp-plugin/src/host.rs:368` | advisory lock | NONE (纯数值) |
| `erp-plugin/src/host.rs:336-398` | 动态表名 | LOW (sanitize_identifier) |
| `erp-health/src/service/action_inbox_service.rs:240-353` | 硬编码条件 | NONE (编译时字面量) |
`sanitize_identifier()` 实现正确但缺长度限制PostgreSQL 63 字节标识符上限)。
### 1.3 事件系统 — 良好 (7.5/10)
- 31 事件类型 / 82 发布点 / 12 消费者模块 / Outbox + LISTEN/NOTIFY
- `consume_with_retry()` 提供幂等保证但实际未被消费者调用
- broadcast channel 容量 1024高并发下可能 lag30s 兜底轮询补偿)
### 1.4 缓存层 — 薄弱 (6.5/10)
- 仅有 Moka (权限缓存) + Redis (限流/session),无业务数据缓存
- 高频查询(菜单树、字典项、仪表盘统计)每次请求命中数据库
- 10x 用户增长时数据库连接池将成为瓶颈
### 1.5 架构 TOP 5 风险
1. **事件消费者未统一走 consume_with_retry** (MEDIUM) — 幂等保护不完整3-5d
2. **broadcast channel 容量有限** (MEDIUM) — 高并发丢事件2d
3. **缓存层薄弱** (MEDIUM) — 10x 扩展瓶颈5-8d
4. **action_inbox_service SQL 拼接** (LOW) — 代码气味0.5d
5. **迁移文件过多(156个)** (LOW) — 维护成本3d
---
## 二、安全维度 (7.5/10)
### 2.1 认证与授权 — 优秀 (8.5/10)
- JWT: HS256 + 15min access / 7d refresh + SHA-256 存储 refresh token
- 原子性刷新: `validate_and_revoke_atomic()` 防止 TOCTOU 竞态
- 密码: Argon2 + 随机 salt
- 权限守卫: 444 处 `require_permission()` 调用64 个 handler 文件
- 多租户: 双层隔离(应用层 tenant_id + PostgreSQL RLS
### 2.2 PII 加密 — 优秀 (9/10)
- KEK/DEK 分层 + AES-256-GCM + 盲索引 (HMAC-SHA256)
- 生产环境强制 KEK 配置(`debug_assertions` 下 dev_default 会 panic
- 支持租户级密钥轮换 API
### 2.3 API 安全 — 优秀 (9/10)
- 5 层 rate limiting: IP登录(5/min) + IP刷新(30/min) + 用户API(300/min) + 网关(60/min) + 账户锁定(5次/15min)
- 文件上传: 白名单 + Magic bytes + 大小限制 + UUID 文件名 + 租户隔离
- CORS: 生产环境拒绝通配符
### 2.4 安全 TOP 5 风险
1. **Analytics batch 端点缺权限校验** (HIGH) — CVSS 5.31h
2. **日志 PII 脱敏不完整** (MEDIUM) — secret_len 泄漏 + service 层未脱敏4h
3. **缺少 HSTS + CSP 安全头** (MEDIUM) — CVSS 3.12h
4. **插件 sanitize_identifier 缺长度限制** (MEDIUM) — 8h
5. **SSE token 通过 URL query parameter** (LOW) — 日志泄漏风险4h
---
## 三、前端维度 (7.2/10)
### 3.1 Web 前端 — 良好 (7.5/10)
- 316 TS/TSX 文件54 API 模块5 Zustand stores76 权限码
- **64 个路由页面全部 React.lazy()** — 最佳实践
- 6 个 manualChunks 分包sourcemap 生产关闭
- 10 处生产 `any`7 处在 points.ts 可修复)
- 最大文件 AdminDashboard.tsx 730 行(无超 800 行)
- 62 个测试文件,以 API 契约测试为主
### 3.2 小程序 — 良好但零测试 (7.0/10)
- 59 页面12 主包 + 47 子包34 组件38 service 文件
- 并发安全架构完善: ConcurrencyLimiter(12) + safeNavigateTo + requestUnlimited
- Design Token: 40+ CSS 变量93 SCSS 文件全量接入
- 长者模式: 58/58 页面 100% 覆盖
- **零单元测试** — MCP 自动化审计 96.2% 通过率但只覆盖可达性
### 3.3 前端 TOP 5 风险
1. **小程序零单元测试** (CRITICAL) — 161 文件无测试2-3d
2. **i18n 未实际使用** (HIGH) — 2,298 处硬编码中文3-5d
3. **生产 any 10 处** (MEDIUM) — points.ts 7 处可修复0.5d
4. **a11y 基本缺失** (MEDIUM) — 仅 9 处 aria-/role2-3d
5. **BLE 模块 any 密集** (LOW) — 14 处1d
---
## 四、测试维度 (5.5/10)
### 4.1 测试分布
| 层级 | 测试数 | 覆盖率 |
|------|--------|--------|
| 后端单元 | 802 | Service/DTO 覆盖较好 |
| 后端集成 | 188 | 24 个测试文件 |
| **Handler** | **~2** | **2.8% (2/72 文件)** |
| **安全中间件** | **1** | **20% (1/5)** |
| Web 前端 | 61 文件 | 页面覆盖率 20.8% |
| 小程序 | **0** | **0%** |
| E2E | 17 Web + 4 MP | 核心流程 |
### 4.2 测试密度(测试/1K行代码
| Crate | 密度 | 评价 |
|-------|------|------|
| erp-core | 28.1 | 优秀 |
| erp-message | 20.2 | 优秀 |
| erp-config | 15.3 | 良好 |
| erp-health | **4.9** | 不足 |
| erp-server | **0.7** | 严重不足 |
### 4.3 测试 TOP 5 风险
1. **Handler 层 0% 覆盖** (CRITICAL) — 72 个文件无测试2-3d
2. **小程序 0 测试** (CRITICAL) — 161 文件无测试2d
3. **安全中间件 0 测试** (HIGH) — rate_limit/tenant_rls/frozen_module1.5d
4. **erp-health 28/57 service 无测试** (HIGH) — 核心业务模块3-4d
5. **CI 不覆盖 E2E/小程序** (MEDIUM) — 1.5d
---
## 五、DevOps 维度 (3.8/10)
### 5.1 CI — 良好 (7/10)
- 双平台 CI: GitHub Actions (5 阶段后端 + 4 阶段前端) + Gitea CI (4 jobs)
- Rust 缓存 (Swatinem/rust-cache) + pnpm 缓存
- Clippy 0 警告强制 + cargo audit
### 5.2 CD — 缺失 (0/10)
- 无自动化部署流程
- 无 Docker 镜像版本 tag 策略
- 无蓝绿/金丝雀部署
### 5.3 监控 — 仅 exporter (4/10)
- Prometheus 指标: http_requests_total, http_request_duration, db_pool, eventbus_pending
- 3 级健康检查: /health, /health/live, /health/ready
- **无 Prometheus Server / Grafana / 告警 / 日志聚合 / 分布式追踪**
### 5.4 备份 — 不合规 (3/10)
- 每日 pg_dump + 7 天保留
- **无加密、无异地存储、无 PITR、无恢复测试**
- 医疗数据合规要求: RPO < 1h, 保留 >= 5 年
### 5.5 DevOps TOP 5 风险
1. **无 CD 能力** (CRITICAL) — 发布完全手动3-5d
2. **备份不满足医疗合规** (CRITICAL) — 无加密/异地/PITR5-8d
3. **无监控告警** (HIGH) — 生产盲飞3-5d
4. **迁移在启动时自动执行** (HIGH) — 破坏性 DDL 风险3-5d
5. **安全审计不阻止合并** (MEDIUM) — continue-on-error: true2-3d
---
## 六、产品维度 (~7.0/10)
### 6.1 功能完整性
- 核心流程完整: 患者建档 → 健康数据 → 预约 → 随访 → AI 分析
- 管理员流程完整: 用户管理 → 角色权限 → 数据字典 → 系统配置
- 6 个冻结模块: care-plans, shifts, family-proxy, medications, dialysis, dialysis-prescriptions, schedules
- 2 个 TODO 空实现: ActionDetailDrawer、PendingTasks
### 6.2 wiki 数据校准
| 指标 | wiki | 实际 | 差距 |
|------|------|------|------|
| Rust 源文件 | 652 | 694 | +42 |
| 后端路由 | 260+ | 376 | +116 |
| 权限码 | 132 | 140 | +8 |
| Git 提交 | 862 | 927+ | +65 |
| Web TS/TSX | 307 | 316 | +9 |
| 小程序 TS/TSX | 161 | 167 | +6 |
| API 服务文件 | 28 | 54 | +26 |
| utoipa 注解 | 89 | 94 | +5 |
| "待修复"条目 | 4 | 0 (全已修复) | 需标记 |
---
## 七、V1 发布策略(多专家组辩论共识)
### P0 阻塞项4 天)— 不完成不发布
| # | 行动项 | 维度 | 工作量 |
|---|--------|------|--------|
| A1 | Analytics batch 添加权限校验 | 安全 | 1h |
| A2 | HSTS + CSP + Permissions-Policy 安全头 | 安全 | 2h |
| A3 | 数据库备份加密 + 异地存储 | DevOps | 3d |
| A4 | Nginx TLS 配置模板 | DevOps | 0.5d |
| A5 | 迁移回滚策略文档 + 脚本 | DevOps | 1d |
### P1 测试加固3 天)— 强烈建议
| # | 行动项 | 维度 | 工作量 |
|---|--------|------|--------|
| A6 | 安全中间件 unhappy path 测试 (~15个) | 测试 | 1.5d |
| A7 | 核心 Handler 测试 (~40个) | 测试 | 1.5d |
### P2 V1.1 推迟项(~30 天)
| # | 行动项 | 维度 | 工作量 |
|---|--------|------|--------|
| B1 | Prometheus + Grafana 监控 + 告警 | DevOps | 3d |
| B2 | CD Pipeline (GitHub Actions) | DevOps | 5d |
| B3 | 小程序最小测试套件 | 测试 | 2d |
| B4 | 事件消费者统一 consume_with_retry | 架构 | 5d |
| B5 | 日志 PII 脱敏审查 | 安全 | 4h |
| B6 | 生产迁移策略(独立步骤) | DevOps | 2d |
| B7 | CI 安全审计阻止合并 | DevOps | 0.5d |
| B8 | 菜单树/字典项缓存 | 架构 | 3d |
| B9 | Web a11y 基础合规 | 前端 | 2-3d |
| B10 | points.ts any 类型修复 | 前端 | 2h |
### GO/NO-GO 硬底线
以下任一条件不满足即 NO-GO
1. 多租户数据隔离验证通过(无跨租户泄漏)
2. 核心用户流程端到端可用(建档→录入→预约→随访)
3. 数据库备份可成功恢复(至少一次恢复测试)
4. Analytics 越权已修复
5. 迁移失败有回滚方案
---
## 八、关键数字校准表wiki 更新用)
| 指标 | 当前 wiki | 应更新为 |
|------|-----------|---------|
| Rust 源文件 | 652 | 694 |
| 后端路由 | 260+ | 376+ |
| 权限码 | 132 | 140 |
| Git 提交 | 862 | 927+ |
| Web TS/TSX | 307 | 316 |
| 小程序 TS/TSX | 161 | 167 |
| Web API 服务文件 | 28 | 54 |
| 小程序组件 | 10 | 34 |
| 小程序 Service 文件 | 10+ | 38 |
| utoipa 注解文件 | 89 | 94 |
| Web 冻结路由 | 5 | 6 |
| 后端测试函数 | 943 | 990+ |
| 系统评分 | 6.8/10 (B) | 6.3/10 (B-) |
| 症状导航待修复 | 4 项 | 0 项(全已修复) |
---
## 附录: 分析方法论
- **阶段 1**: 4 个并行探索 Agent后端架构 / 前端+小程序 / 数据库+安全 / V1 就绪度)
- **阶段 2**: 6 个专家组深度分析(架构师 / 安全工程师 / 测试工程师 / 前端专家 / SRE / 产品经理)
- **阶段 3**: 多专家组辩论会议4 个议题:发布范围 / 测试策略 / DevOps 优先级 / 技术债务取舍)
- **总工具调用**: 400+ 次Grep/Glob/Read/Bash 跨 10 个 Agent
- **总分析时长**: ~15 分钟(并行执行)