Files
hms/docs/superpowers/plans/2026-04-26-security-defense-in-depth.md
iven b410fa9f78
Some checks failed
CI / rust-check (push) Has been cancelled
CI / rust-test (push) Has been cancelled
CI / frontend-build (push) Has been cancelled
CI / security-audit (push) Has been cancelled
docs: 5 份实施计划 — 性能/安全/事件/前端/可观测性
对应 5 份设计规格,共 75 个 Task:

1. 性能优化 (12 Task) — 批量INSERT/N+1内联name/合并COUNT/按需重绘/chunk拆分
2. 安全纵深防御 (8 Task) — RLS/行级数据范围/Redis session_key/审计哈希链
3. 事件驱动架构 (10 Task) — 11个缺失事件补发/LISTEN+NOTIFY/schema版本化
4. 前端工程化 (10 Task) — hook统一/组件拆分/Bundle优化
5. 可观测性运维 (10 Task) — 深度健康检查/Prometheus/OTel/生产Docker/告警
2026-04-27 08:00:50 +08:00

90 lines
4.7 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# 安全纵深防御实施计划
> 设计规格: `docs/superpowers/specs/2026-04-26-security-defense-in-depth-design.md`
> 日期: 2026-04-26 | 状态: draft | 总周期: 2-3 周
---
## Phase 1: PostgreSQL RLS 安全网Week 1
### Task 1: 创建 RLS 策略迁移
**涉及文件**: `crates/erp-server/migration/src/m000073_enable_rls_all_tables.rs`(新增), `lib.rs`
**步骤**: 对所有含 tenant_id 的表30 基础 + 34 健康)执行 `ALTER TABLE ENABLE ROW LEVEL SECURITY` + `CREATE POLICY tenant_isolation USING (tenant_id = current_setting('app.current_tenant_id')::uuid)` + `CREATE POLICY tenant_bypass USING (current_user IN ('erp_admin', 'erp_migration'))`。创建 `erp_app` 数据库角色。down 方法完整回退。
**验收**: 迁移执行成功;以 erp_app 角色未设置 tenant_id 时查询返回空;现有应用行为不变。
### Task 2: Axum middleware 设置当前连接的 tenant_id
**涉及文件**: `crates/erp-server/src/middleware/tenant.rs`
**步骤**: tenant 中间件从 JWT 解析 tenant_id 后执行 `SET LOCAL app.current_tenant_id = '<id>'`。确认在事务内执行SeaORM 显式事务包装或 session 级 SET + RESET。添加 tracing 日志记录注入状态。SET LOCAL 失败时 warn 但不阻断请求。
**验收**: 注入后以 erp_app 角色查询自动按 tenant_id 过滤;`cargo test --workspace` 通过。
### Task 3: 验证现有测试不受影响
**涉及文件**: 可能修改测试辅助代码
**步骤**: 运行 `cargo test --workspace` 检查 RLS 导致的测试失败。分析失败原因(测试未设置 tenant_id → 查询返回空),在 TestDb/TestApp 初始化时注入 tenant_id。不修改任何业务逻辑代码。
**验收**: `cargo test --workspace` 全部通过。
---
## Phase 2: 行级数据范围 + session_key RedisWeek 2
### Task 4: require_permission 增加 data_scope 过滤逻辑
**涉及文件**: `erp-core/src/types.rs`(TenantContext 增加 permission_data_scopes), `erp-core/src/rbac.rs`(apply_data_scope 函数), JWT 中间件, `erp-health/src/handler/mod.rs`
**步骤**: TenantContext 新增 `permission_data_scopes: HashMap<String, DataScope>`(枚举 All/Self/Department/DepartmentTree。JWT 中间件查询 `role_permissions.data_scope` 填充。实现 `apply_data_scope(query, ctx, permission, owner_column, dept_column)` 按变体追加 filter。各 health handler 列表查询调用此函数。
**验收**: data_scope = Department 时查询自动追加部门过滤;未配置时默认 All 向后兼容。
### Task 5: 微信 session_key 从 HashMap 迁移到 Redis
**涉及文件**: `crates/erp-auth/src/service/wechat_service.rs`, `erp-server/src/app_state.rs`
**步骤**: 替换 `LazyLock<Mutex<HashMap>>` 为 Redis `SET wechat:session:{openid} {key} EX 300` / `GET + DEL`。Redis 连接池通过 AuthState 传入。添加 fallbackRedis 不可用时降级内存 HashMap 并 warn 日志。
**验收**: 小程序登录端到端通过;`cargo test -p erp-auth` 通过。
### Task 6: 小程序 openid 加密存储
**涉及文件**: `apps/miniprogram/src/utils/secure-storage.ts`(新增), `stores/auth.ts`
**步骤**: 创建 AES 加密存储工具setSecure/getSecure。后端登录接口响应新增 `storage_key` 字段。auth.ts 中 openid 存储改用 `setSecure('openid', openid)`
**验收**: `Taro.getStorageSync('openid')` 返回密文;小程序登录端到端通过。
---
## Phase 3: 健康检查增强 + 审计日志Week 2-3
### Task 7: /health/ready 增加 DB ping + Redis ping
**涉及文件**: `crates/erp-server/src/handlers/health.rs`
**步骤**: 添加 `sqlx::query("SELECT 1")` DB 检查 + `redis PING` 检查,使用 `tokio::join!` 并行。响应扩展 status(ok/degraded) + database + redis 字段。
**验收**: DB 不可用时返回 `status: "degraded"` + `database: "unreachable"`
### Task 8: audit_logs 表增加 prev_hash 字段实现哈希链
**涉及文件**: `migration/src/m000074_audit_logs_hash_chain.rs`(新增), `erp-core/src/audit.rs`
**步骤**: 迁移添加 `prev_hash TEXT` + `record_hash TEXT` 列。写入时查询最新 record_hash 作为 prev_hash计算 `SHA256(id + action + resource_type + resource_id + created_at + prev_hash)` 作为 record_hash。添加完整性验证函数检测篡改。内存缓存最近 1000 条 record_hash 优化性能。
**验收**: 新审计日志含哈希链字段;修改记录后验证函数检测到链断裂;`cargo test` 通过。
---
## 执行原则
1. **每 Task 完成后立即提交** — 不积压
2. **Phase 1 最高优先** — RLS 是医疗数据合规红线
3. **RLS 迁移必须可回退** — down 方法完整恢复
4. **渐进式启用 data_scope** — 未配置默认 All不破坏现有行为