docs: 5 份实施计划 — 性能/安全/事件/前端/可观测性
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

对应 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/告警
This commit is contained in:
iven
2026-04-27 08:00:50 +08:00
parent 215fb35e0e
commit b410fa9f78
5 changed files with 809 additions and 0 deletions

View File

@@ -0,0 +1,89 @@
# 安全纵深防御实施计划
> 设计规格: `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不破坏现有行为