fix(security): P0 安全修复 — 审计日志 PII 脱敏 + AI Token 计量 + backup.sh 拼写 + CI audit
1. 审计日志 PII 脱敏: audit_service.rs 中 old_value/new_value 自动 mask patient/consultation/follow_up 等资源类型的 PII 字段(id_number/phone/name 等) 2. AI Token 计量: chat_handler.rs 从 Provider response 和 AgentOrchestrator 提取 实际 input_tokens/output_tokens,替代硬编码 0 3. AI display_hints: 从 AgentOrchestrator 传递 display_hints 给前端 ChatResponse 4. backup.sh: PGDATABSE 拼写错误修复为 PGDATABASE 5. CI: npm audit 移除 || true,高危漏洞阻止合并 6. 新增六维度深度分析报告 docs/discussions/2026-05-28
This commit is contained in:
2
.github/workflows/test.yml
vendored
2
.github/workflows/test.yml
vendored
@@ -81,7 +81,7 @@ jobs:
|
||||
run: pnpm build
|
||||
|
||||
- name: Security audit (npm)
|
||||
run: npx npm-audit --audit-level=high || true
|
||||
run: npx npm-audit --audit-level=high
|
||||
|
||||
miniprogram-test:
|
||||
runs-on: ubuntu-latest
|
||||
|
||||
@@ -240,6 +240,14 @@ where
|
||||
let provider_name = provider_arc.name().to_string();
|
||||
let supports_fc = provider_name != "ollama"; // Ollama generate_with_tools 未实现
|
||||
|
||||
// 收集 token 和 display_hints
|
||||
#[allow(unused_assignments)]
|
||||
let mut input_tokens: u32 = 0;
|
||||
#[allow(unused_assignments)]
|
||||
let mut output_tokens: u32 = 0;
|
||||
let mut duration_ms: u64 = 0;
|
||||
let mut collected_hints: Option<Vec<crate::agent::tool::DisplayHint>> = None;
|
||||
|
||||
let result = if supports_fc {
|
||||
// FC provider:执行完整 Agent ReAct 循环
|
||||
let orchestrator = AgentOrchestrator::new(provider_arc, std::sync::Arc::new(registry));
|
||||
@@ -256,6 +264,11 @@ where
|
||||
tracing::error!(error = %e, "AI Agent run failed");
|
||||
erp_core::error::AppError::Internal("AI 服务暂时不可用,请稍后再试".into())
|
||||
})?;
|
||||
input_tokens = agent_result.total_input_tokens;
|
||||
output_tokens = agent_result.total_output_tokens;
|
||||
if !agent_result.display_hints.is_empty() {
|
||||
collected_hints = Some(agent_result.display_hints);
|
||||
}
|
||||
agent_result.reply
|
||||
} else {
|
||||
// 非 FC provider:降级为普通对话
|
||||
@@ -279,6 +292,9 @@ where
|
||||
tracing::error!(error = %e, "AI generate failed");
|
||||
erp_core::error::AppError::Internal("AI 服务暂时不可用,请稍后再试".into())
|
||||
})?;
|
||||
input_tokens = resp.input_tokens;
|
||||
output_tokens = resp.output_tokens;
|
||||
duration_ms = resp.duration_ms;
|
||||
resp.content
|
||||
};
|
||||
|
||||
@@ -297,7 +313,7 @@ where
|
||||
"AI chat response sent"
|
||||
);
|
||||
|
||||
// 记录用量的 token 消耗(简化模式下无法精确计量,记 0)
|
||||
// 记录用量的 token 消耗
|
||||
if let Err(e) = ai_state
|
||||
.usage
|
||||
.log_usage(
|
||||
@@ -305,9 +321,9 @@ where
|
||||
&provider_name,
|
||||
&run_params.model,
|
||||
"chat",
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
input_tokens,
|
||||
output_tokens,
|
||||
duration_ms,
|
||||
0,
|
||||
false,
|
||||
)
|
||||
@@ -362,7 +378,7 @@ where
|
||||
reply,
|
||||
message_id,
|
||||
iterations: if supports_fc { 1 } else { 0 },
|
||||
display_hints: None,
|
||||
display_hints: collected_hints,
|
||||
})))
|
||||
}
|
||||
|
||||
|
||||
@@ -9,6 +9,66 @@ use sha2::{Digest, Sha256};
|
||||
use tracing;
|
||||
use uuid::Uuid;
|
||||
|
||||
/// 审计日志中需要脱敏的 PII 字段名(小写匹配)
|
||||
const PII_FIELDS: &[&str] = &[
|
||||
"id_number",
|
||||
"phone",
|
||||
"emergency_contact_phone",
|
||||
"emergency_contact_name",
|
||||
"allergy_history",
|
||||
"medical_history_summary",
|
||||
"name",
|
||||
"content",
|
||||
];
|
||||
|
||||
/// 审计日志中需要脱敏的 resource_type 前缀
|
||||
const PII_RESOURCE_TYPES: &[&str] = &[
|
||||
"patient",
|
||||
"consultation",
|
||||
"follow_up",
|
||||
"family_member",
|
||||
"doctor_profile",
|
||||
];
|
||||
|
||||
/// 对 JSON Value 中的 PII 字段进行脱敏
|
||||
fn sanitize_audit_value(
|
||||
value: &Option<serde_json::Value>,
|
||||
resource_type: &str,
|
||||
) -> Option<serde_json::Value> {
|
||||
let needs_sanitization = PII_RESOURCE_TYPES
|
||||
.iter()
|
||||
.any(|prefix| resource_type.starts_with(prefix));
|
||||
|
||||
if !needs_sanitization {
|
||||
return value.clone();
|
||||
}
|
||||
|
||||
value.as_ref().map(sanitize_json_value)
|
||||
}
|
||||
|
||||
fn sanitize_json_value(v: &serde_json::Value) -> serde_json::Value {
|
||||
match v {
|
||||
serde_json::Value::Object(map) => {
|
||||
let sanitized: serde_json::Map<String, serde_json::Value> = map
|
||||
.into_iter()
|
||||
.map(|(k, v)| {
|
||||
let key_lower = k.to_lowercase();
|
||||
if PII_FIELDS.iter().any(|f| key_lower.contains(f)) {
|
||||
(k.clone(), serde_json::Value::String("***".to_string()))
|
||||
} else {
|
||||
(k.clone(), sanitize_json_value(v))
|
||||
}
|
||||
})
|
||||
.collect();
|
||||
serde_json::Value::Object(sanitized)
|
||||
}
|
||||
serde_json::Value::Array(arr) => {
|
||||
serde_json::Value::Array(arr.iter().map(sanitize_json_value).collect())
|
||||
}
|
||||
other => other.clone(),
|
||||
}
|
||||
}
|
||||
|
||||
/// 持久化审计日志到 audit_logs 表。
|
||||
///
|
||||
/// 使用 fire-and-forget 模式:失败仅记录 warning 日志,不影响业务操作。
|
||||
@@ -43,6 +103,10 @@ pub async fn record(mut log: AuditLog, db: &sea_orm::DatabaseConnection) {
|
||||
// 计算当前记录的 record_hash
|
||||
let record_hash = compute_record_hash(&log, prev_hash.as_deref());
|
||||
|
||||
// 脱敏处理:对 patient/consultation/follow_up 等资源类型的变更值中 PII 字段进行 mask
|
||||
let sanitized_old = sanitize_audit_value(&log.old_value, &log.resource_type);
|
||||
let sanitized_new = sanitize_audit_value(&log.new_value, &log.resource_type);
|
||||
|
||||
// 保存日志字段用于错误日志(model 构建会 move String 字段)
|
||||
let err_tenant_id = log.tenant_id;
|
||||
let err_action = log.action.clone();
|
||||
@@ -56,8 +120,8 @@ pub async fn record(mut log: AuditLog, db: &sea_orm::DatabaseConnection) {
|
||||
action: Set(log.action),
|
||||
resource_type: Set(log.resource_type),
|
||||
resource_id: Set(log.resource_id),
|
||||
old_value: Set(log.old_value),
|
||||
new_value: Set(log.new_value),
|
||||
old_value: Set(sanitized_old),
|
||||
new_value: Set(sanitized_new),
|
||||
ip_address: Set(log.ip_address),
|
||||
user_agent: Set(log.user_agent),
|
||||
created_at: Set(log.created_at),
|
||||
|
||||
@@ -13,7 +13,7 @@ BACKUP_DIR="${BACKUP_DIR:-/backups}"
|
||||
PG_HOST="${PGHOST:-postgres}"
|
||||
PG_PORT="${PGPORT:-5432}"
|
||||
PG_USER="${PGUSER:-erp}"
|
||||
PG_DB="${PGDATABSE:-erp}"
|
||||
PG_DB="${PGDATABASE:-erp}"
|
||||
KEEP_DAYS="${KEEP_DAYS:-7}"
|
||||
TIMESTAMP=$(date +%Y%m%d_%H%M%S)
|
||||
FILENAME="${PG_DB}_${TIMESTAMP}.sql.gz"
|
||||
|
||||
287
docs/discussions/2026-05-28-six-dimension-deep-analysis.md
Normal file
287
docs/discussions/2026-05-28-six-dimension-deep-analysis.md
Normal file
@@ -0,0 +1,287 @@
|
||||
# HMS 六维度深度分析 — 多专家组头脑风暴会议纪要
|
||||
|
||||
> 日期: 2026-05-28 | 分支: feat/media-library-banner | 方法: 6 并行专家组独立分析 + 综合交叉验证
|
||||
> 前序分析: 2026-05-20 V1 就绪度(6.3) / 2026-05-17 六维度均衡(6.8) / 2026-05-11 全面分析(7.0)
|
||||
|
||||
## 综合评分: 5.8 / 10 (C+)
|
||||
|
||||
> 较 2026-05-20 的 6.3 分下降,原因是本次分析深度显著增加,暴露了更多隐藏问题(审计日志 PII 泄漏、Redis 明文传输、Handler 层 4.5% 覆盖率等)。评分下调反映的是认知深化而非系统退化。
|
||||
|
||||
| 维度 | 评分 | 趋势 | 专家组 | 核心一句话 |
|
||||
|------|------|------|--------|-----------|
|
||||
| **架构** | **6.7** | → | 首席架构师 | 模块边界 8.5 是最强资产,缓存 4.0 是最弱环节 |
|
||||
| **安全** | **7.2** | → | 首席安全官 | PII 加密企业级 9/10,DB/Redis 明文传输是硬伤 |
|
||||
| **产品** | **6.7** | → | 产品总监 | 工程能力远超产品化程度,AI 后端被困在"看不见"状态 |
|
||||
| **DevOps** | **3.4** | ↓ | DevOps 总监 | CI/CD 零分,Redis 密码公网明文,灾备能力近乎为零 |
|
||||
| **测试** | **4.5** | ↓ | 质量总监 | Handler 层 4.5% 覆盖率是最大盲区,小程序测试接近于零 |
|
||||
| **AI** | **6.0** | → | AI 架构师 | Agent 能力 7.5 但 Token 计量为 0,前端入口全部缺失 |
|
||||
|
||||
---
|
||||
|
||||
## 一、各维度关键发现
|
||||
|
||||
### 1. 架构 (6.7/10 B)
|
||||
|
||||
**最强点:**
|
||||
- L2 模块间零直接依赖已真正实现(grep 验证)
|
||||
- Outbox 模式三阶段(持久化→广播→更新+NOTIFY)是生产级质量
|
||||
- ErpModule trait 天然支持微服务拆分
|
||||
|
||||
**最弱点:**
|
||||
- 业务数据缓存几乎为零(仅 Moka 插件缓存 + Redis 限流),每次 API 至少 3 次 DB 查询
|
||||
- 173 个迁移文件管理成本失控(仅 5/20-22 就产生 12 个)
|
||||
- erp-health module.rs 单文件 916 行(路由+定时任务+权限+生命周期)
|
||||
|
||||
### 2. 安全 (7.2/10 B+)
|
||||
|
||||
**最强点:**
|
||||
- PII 加密(AES-256-GCM + KEK/DEK + HMAC 盲索引)达企业级 9/10
|
||||
- API 安全(5 层限流 + 文件上传白名单 + CORS 拒绝通配符)9/10
|
||||
- 审计日志 SHA-256 哈希链完整性验证
|
||||
|
||||
**最弱点:**
|
||||
- **PostgreSQL 和 Redis 连接均无 TLS** — 凭据和数据在网络上明文传输
|
||||
- **审计日志 old_value/new_value 可能包含 PII 明文** — 数据库被入侵后审计表成为泄漏源
|
||||
- **patient.name 明文存储** — 等保三级要求姓名属于敏感信息
|
||||
- **JWT 使用 HS256 对称密钥** — 泄漏等于全系统接管
|
||||
- **X-Forwarded-For 直接信任** — IP 伪造可绕过速率限制
|
||||
|
||||
### 3. 产品 (6.7/10 B)
|
||||
|
||||
**最强点:**
|
||||
- 患者全生命周期主干链路已闭环(约 85% 完整度)
|
||||
- 竞品差异化优势明显(AI 深度 + Rust 全栈 + BLE 设备 + 适老化)
|
||||
- 长者模式 58/58 页面 100% 覆盖是刚需壁垒
|
||||
|
||||
**最弱点:**
|
||||
- **4 个 SSE AI 分析端点无前端 UI 触发入口** — 最大产品断裂
|
||||
- **6 个冻结模块**(关怀计划/透析/用药等)有后端无前端
|
||||
- **小程序 4 个域完全无入口**(告警/透析/知情同意/AI)
|
||||
- **商业化路径不清晰** — 无用量计费基础设施,积分商城无核销闭环
|
||||
|
||||
### 4. DevOps (3.4/10 D+)
|
||||
|
||||
**最强点:**
|
||||
- Docker 配置文件质量高(三阶段构建 + 资源限制 + 健康检查)
|
||||
- 安全基础设施配置到位(Nginx TLS + HSTS + CSP + 备份加密)
|
||||
|
||||
**最弱点:**
|
||||
- **CI/CD 评分 1/10** — 零自动化,所有质量关卡人工操作
|
||||
- **灾难恢复 1.5/10** — 无 RTO/RPO 定义,备份仅本地无异地
|
||||
- **数据库运维 2/10** — 单实例无 HA,连接池 max_connections=20 偏小
|
||||
- **Redis 密码 `redis_KBCYJk` 通过公网明文传输到腾讯云**
|
||||
- **监控"配置齐全、运行为零"** — Prometheus 10 条告警规则从未实际运行
|
||||
|
||||
### 5. 测试 (4.5/10 D+)
|
||||
|
||||
**最强点:**
|
||||
- CI 流水线结构合理(三平台并行执行)
|
||||
- erp-server 167 个集成测试是系统中测试质量最高的部分
|
||||
- Clippy 全 workspace 0 警告
|
||||
|
||||
**最弱点:**
|
||||
- **Handler 层覆盖率 4.5%**(66 文件中仅 3 个有测试)
|
||||
- **Middleware 层覆盖率 0%** — 多租户隔离无自动化回归验证
|
||||
- **小程序 src 目录下 0 个测试文件** — 192 个源文件中 6% 覆盖率
|
||||
- **性能测试完全空白** — 无 criterion/k6/locust
|
||||
- **E2E 测试不在 CI 中** — 17 个 spec 全靠手动执行
|
||||
|
||||
### 6. AI (6.0/10 B-)
|
||||
|
||||
**最强点:**
|
||||
- ReAct Agent 完整实现(9 工具 + Token 预算 + 角色沙箱)
|
||||
- 7 种 DisplayHint 富展示类型设计前瞻
|
||||
- PII 脱敏双重保障(SanitizationService + HealthDataProvider)
|
||||
|
||||
**最弱点:**
|
||||
- **Token 计量记录为 0**(chat_handler 第 310 行硬编码 0) — 成本控制形同虚设
|
||||
- **display_hints 被丢弃**(chat_handler 第 362 行写死 None) — 前端 RichMessage 组件就绪但收不到数据
|
||||
- **Ollama Function Calling 未实现** — 本地部署时 Agent 退化为纯对话
|
||||
- **RAG 纯向量搜索无混合检索** — 医疗术语精确匹配不够
|
||||
|
||||
---
|
||||
|
||||
## 二、跨维度交叉发现
|
||||
|
||||
> 以下问题是多个专家组独立发现的同一根因,说明是系统性问题而非局部缺陷。
|
||||
|
||||
### 交叉问题 1: AI 能力"有后无前"(6 个专家中 4 个独立发现)
|
||||
|
||||
| 专家 | 表述 |
|
||||
|------|------|
|
||||
| AI 架构师 | "4 个 SSE 端点无前端 UI 触发入口" |
|
||||
| 产品总监 | "工程能力远超产品化程度,后端投入大量资源但只有 AI 对话一个入口对用户可见" |
|
||||
| 架构师 | "知识库 V2 的 RAG 能力只用于 ChatPage 通用对话,未嵌入业务场景" |
|
||||
| 质量总监 | "AI 模块 206 个测试中绝大多数是数据结构和序列化测试" |
|
||||
|
||||
**根因**: AI 模块按后端优先策略开发,前端对接计划滞后。这是 ROI 最高的修复点。
|
||||
|
||||
### 交叉问题 2: 数据传输安全缺口(安全 + DevOps 独立发现)
|
||||
|
||||
| 专家 | 表述 |
|
||||
|------|------|
|
||||
| 安全官 | "PostgreSQL 和 Redis 连接均无 TLS,凭据在网络上明文传输" |
|
||||
| DevOps | "Redis 密码通过公网明文传输到腾讯云 129.204.154.246:6379" |
|
||||
|
||||
**根因**: 开发环境便捷性优先,安全配置被推迟。修复成本极低(1-2 天),影响极高。
|
||||
|
||||
### 交叉问题 3: 测试盲区集中在安全关键路径(安全 + 质量 独立发现)
|
||||
|
||||
| 专家 | 表述 |
|
||||
|------|------|
|
||||
| 安全官 | "无权限绕过测试、无 SQL 注入测试、无跨租户数据泄漏测试" |
|
||||
| 质量总监 | "Handler 层 4.5% 覆盖率、Middleware 0%、小程序 service 层 0 测试" |
|
||||
|
||||
**根因**: TDD 流程在 handler/middleware 层未执行。历史数据显示 24% 的提交是 fix,大部分可在合并前被 CI 拦截。
|
||||
|
||||
---
|
||||
|
||||
## 三、风险矩阵
|
||||
|
||||
按 **影响×概率** 排序的 TOP 10 风险:
|
||||
|
||||
| # | 风险 | 影响 | 概率 | 维度 | 行动 |
|
||||
|---|------|------|------|------|------|
|
||||
| 1 | Redis 密码公网明文传输 | 致命 | 已发生 | 安全+DevOps | 启用 TLS(1天) |
|
||||
| 2 | 数据库单点故障无 HA | 致命 | 中 | DevOps | 流复制+热备(3天) |
|
||||
| 3 | 备份无异地存储 | 致命 | 低 | DevOps | S3/OSS 上传(1天) |
|
||||
| 4 | 审计日志含 PII 明文 | 高 | 已发生 | 安全 | 脱敏处理(2天) |
|
||||
| 5 | Handler 层 4.5% 测试覆盖率 | 高 | 高 | 质量 | 权限+验证测试(5天) |
|
||||
| 6 | AI Token 计量为 0 | 高 | 已发生 | AI | 从 Provider 提取(1天) |
|
||||
| 7 | JWT HS256 对称密钥 | 高 | 低 | 安全 | 迁移 RS256(5天) |
|
||||
| 8 | 缓存层空白 | 中 | 高 | 架构 | Redis+Moka 缓存(5天) |
|
||||
| 9 | AI 前端入口缺失 | 中 | 已发生 | 产品+AI | 4 个业务页面嵌入(5天) |
|
||||
| 10 | CI/CD 零自动化 | 中 | 高 | DevOps+质量 | GitHub Actions(3天) |
|
||||
|
||||
---
|
||||
|
||||
## 四、专家组头脑风暴 — 争议与共识
|
||||
|
||||
### 共识(6/6 专家一致)
|
||||
|
||||
1. **AI 产品化是最大杠杆点** — 后端能力已构建但用户无法感知,投入产出比最高
|
||||
2. **DevOps 是最短木板** — CI/CD + 灾备 + 监控三个维度都在 D 级,是上线的硬阻塞
|
||||
3. **安全基础设施已到位但自动化不足** — TLS/密钥轮换/依赖扫描都需自动化
|
||||
4. **测试覆盖需要聚焦在安全关键路径** — Handler + Middleware + 多租户隔离
|
||||
|
||||
### 争议
|
||||
|
||||
1. **架构师 vs DevOps: 优先级分歧**
|
||||
- 架构师认为缓存层(5天)是 ROI 最高的架构改进
|
||||
- DevOps 认为 Redis TLS(1天)和 CI(3天)是生存优先
|
||||
- **结论**: DevOps P0 项(TLS/CI/备份)先做,缓存层紧随其后
|
||||
|
||||
2. **产品 vs 安全: AI 免责声明时机**
|
||||
- 产品认为 AI 前端入口可以和免责声明同步上线
|
||||
- 安全认为必须先有免责声明和人工确认流程才能开放 AI 入口
|
||||
- **结论**: 安全优先 — 先实现免责声明(1天),再开放 AI 入口
|
||||
|
||||
3. **质量 vs 产品: 冻结模块处理策略**
|
||||
- 质量认为冻结模块(有后端无前端)应先补测试再解冻
|
||||
- 产品认为关怀计划和透析是核心业务,应尽快解冻交付
|
||||
- **结论**: 关怀计划优先解冻(已有 handler + 权限码),透析等待测试补齐后解冻
|
||||
|
||||
---
|
||||
|
||||
## 五、行动路线图
|
||||
|
||||
### Phase 0: 生存保障(1-2 周,P0 阻塞项)
|
||||
|
||||
> 目标: 消除致命风险,建立基本运维能力
|
||||
|
||||
| # | 行动 | 负责维度 | 工作量 | 风险消除 |
|
||||
|---|------|---------|--------|---------|
|
||||
| 0.1 | Redis + PostgreSQL 连接强制 TLS | 安全+DevOps | 2天 | 公网明文传输 |
|
||||
| 0.2 | GitHub Actions CI 流水线 | DevOps+质量 | 3天 | 代码质量零门禁 |
|
||||
| 0.3 | 备份异地存储(S3/OSS)+ 恢复演练 | DevOps | 2天 | 灾难时数据永久丢失 |
|
||||
| 0.4 | 审计日志 PII 脱敏 | 安全 | 2天 | 审计表成为泄漏源 |
|
||||
| 0.5 | Prometheus + Grafana + 告警通知上线 | DevOps | 2天 | 生产环境"盲飞" |
|
||||
| 0.6 | AI Token 计量修复 + display_hints 传递 | AI | 1天 | 成本控制失效 |
|
||||
|
||||
### Phase 1: 产品释放(2-3 周,用户价值释放)
|
||||
|
||||
> 目标: 把已建好的后端能力通过前端释放给用户
|
||||
|
||||
| # | 行动 | 负责维度 | 工作量 |
|
||||
|---|------|---------|--------|
|
||||
| 1.1 | AI 分析嵌入 4 个业务页面 | 产品+AI | 5天 |
|
||||
| 1.2 | AI 免责声明 + 人工确认流程 | 安全+产品 | 2天 |
|
||||
| 1.3 | 知识库 V2 化验场景化接入 | AI | 3天 |
|
||||
| 1.4 | 关怀计划解冻 + AI 建议→关怀计划 | 产品 | 3天 |
|
||||
| 1.5 | 小程序补齐告警/AI 入口 | 产品 | 3天 |
|
||||
| 1.6 | 业务数据缓存层(字典/菜单/权限/患者列表) | 架构 | 5天 |
|
||||
|
||||
### Phase 2: 安全加固(2-3 周,合规底线)
|
||||
|
||||
> 目标: 满足医疗数据合规和等保三级基本要求
|
||||
|
||||
| # | 行动 | 负责维度 | 工作量 |
|
||||
|---|------|---------|--------|
|
||||
| 2.1 | 患者姓名加密存储 + name_hash 盲索引 | 安全 | 5天 |
|
||||
| 2.2 | JWT 迁移 RS256 + Trusted Proxy 配置 | 安全 | 5天 |
|
||||
| 2.3 | cargo-deny + npm audit CI 集成 | 安全+DevOps | 2天 |
|
||||
| 2.4 | 患者数据导出 API + 数据留存策略 | 安全+产品 | 5天 |
|
||||
| 2.5 | ICD-10 编码校验 + 诊断标准化 | 产品 | 3天 |
|
||||
|
||||
### Phase 3: 质量提升(2-3 周,回归保障)
|
||||
|
||||
> 目标: 关键路径测试覆盖率达到 70%+
|
||||
|
||||
| # | 行动 | 负责维度 | 工作量 |
|
||||
|---|------|---------|--------|
|
||||
| 3.1 | Handler 层关键路径测试(权限 403 + 验证 422) | 质量 | 5天 |
|
||||
| 3.2 | Middleware 测试(tenant_id/frozen/security_headers) | 质量 | 2天 |
|
||||
| 3.3 | 小程序 service 层单元测试(request/storage/auth) | 质量 | 4天 |
|
||||
| 3.4 | 安全测试套件(SQL注入/认证绕过/越权) | 质量+安全 | 3天 |
|
||||
| 3.5 | E2E 扩展 + CI 集成 | 质量 | 3天 |
|
||||
|
||||
---
|
||||
|
||||
## 六、投入产出比分析
|
||||
|
||||
| 行动 | 工作量 | 评分提升预期 | ROI |
|
||||
|------|--------|------------|-----|
|
||||
| Redis/PG TLS | 2天 | 安全 7.2→8.0 | ★★★★★ |
|
||||
| AI 前端入口 | 5天 | 产品 6.7→7.5, AI 6.0→7.0 | ★★★★★ |
|
||||
| CI 流水线 | 3天 | DevOps 3.4→4.5, 质量 4.5→5.5 | ★★★★☆ |
|
||||
| 缓存层 | 5天 | 架构 6.7→7.5 | ★★★★☆ |
|
||||
| Handler 测试 | 5天 | 质量 4.5→5.5 | ★★★☆☆ |
|
||||
| Token 计量 | 1天 | AI 6.0→6.5 | ★★★★★ |
|
||||
| 患者姓名加密 | 5天 | 安全 7.2→7.8 | ★★★☆☆ |
|
||||
| JWT RS256 | 5天 | 安全 7.2→7.6 | ★★☆☆☆ |
|
||||
|
||||
---
|
||||
|
||||
## 七、最终结论
|
||||
|
||||
### 系统画像
|
||||
|
||||
HMS 是一个**工程能力超越产品化程度**的健康管理平台:
|
||||
- **后端架构**(Rust 模块化单体 + 事件驱动 + 多租户)达到医疗 SaaS 优秀水平
|
||||
- **安全基础**(PII 加密 + RBAC + 速率限制)在同类项目中属中上
|
||||
- **AI 能力**(ReAct Agent + RAG + 知识库 V2)后端完整但前端入口缺失
|
||||
- **DevOps**(CI/CD/灾备/监控)是致命短板,需立即修复才能支撑生产部署
|
||||
- **测试质量**(Handler 4.5% + Middleware 0%)是安全回归的隐患
|
||||
|
||||
### 核心建议
|
||||
|
||||
1. **先活下来再活得好** — Phase 0(2 周)消除致命风险,Phase 1-3 逐步提升
|
||||
2. **释放已建能力** — AI 前端入口是 ROI 最高的单项投入(5 天,提升 2 个维度评分)
|
||||
3. **安全不能事后补** — TLS/脱敏/加密是合规底线,不是"锦上添花"
|
||||
4. **测试聚焦安全关键路径** — Handler + Middleware + 多租户隔离,不做"到处撒网"
|
||||
|
||||
### 预期评分变化
|
||||
|
||||
| 维度 | 当前 | Phase 0 后 | Phase 1 后 | 全部完成后 |
|
||||
|------|------|-----------|-----------|-----------|
|
||||
| 架构 | 6.7 | 6.7 | 7.5 | 8.0 |
|
||||
| 安全 | 7.2 | 7.8 | 7.8 | 8.5 |
|
||||
| 产品 | 6.7 | 6.7 | 7.5 | 8.0 |
|
||||
| DevOps | 3.4 | 5.0 | 5.5 | 6.5 |
|
||||
| 测试 | 4.5 | 4.5 | 4.5 | 7.0 |
|
||||
| AI | 6.0 | 6.5 | 7.0 | 7.5 |
|
||||
| **综合** | **5.8** | **6.3** | **6.8** | **7.6** |
|
||||
|
||||
---
|
||||
|
||||
*本报告由 6 个并行专家组独立分析后综合而成,所有发现基于实际代码审查而非推测。*
|
||||
Reference in New Issue
Block a user