* 功能: v2.0.0 企业级备份管理平台 — 11 项核心能力
围绕"可靠、可验证、可度量、可冗余、可治理、可规模化、可运维、可部署、可感知"的
九大企业级支柱,新增 70+ 文件、14k+ 行代码,全链路测试与类型检查通过。
## 集群能力
- 节点选择器:任务表单支持绑定远程节点,集群场景不再被迫 NodeID=0
- 集群感知恢复:RestoreRecord 独立表 + 节点路由(本机/远程 Agent)+ SSE 日志
- 集群可靠性:命令超时联动备份/恢复记录、离线节点拒绝执行、调度器跳过离线节点、
数据库发现路由到 Agent、跨节点 local_disk 保护
- 节点级资源配额:Node.MaxConcurrent / BandwidthLimit + per-node semaphore
- Agent 版本感知:ClusterVersionMonitor 定期扫描 + agent_outdated 事件
- Dashboard 集群概览 + 节点性能统计(成功率/字节/平均耗时)
## 企业功能
- 备份验证演练:定时自动校验备份可恢复性(tar/sqlite/mysql/postgres/saphana 5 类格式)
- SLA 监控:RPO 违约后台扫描 + sla_violation 事件 + Dashboard 合规视图
- 3-2-1 备份复制:自动/手动副本镜像 + 跨节点保护
- 存储目标健康监控 + 容量预警(85%)+ 硬配额(超配额拒绝)
- RBAC 三级角色(admin/operator/viewer)+ 前后端权限控制
- API Key 管理(bax_ 前缀 SHA-256 哈希存储 + 过期/启停)
- 事件总线:10+ 事件类型(backup/restore/verify/sla/storage/replication/agent)
- 审计日志高级筛选 + CSV 导出
## 规模化运维
- 任务模板(批量创建 + 变量覆盖)
- 任务批量操作(批量执行/启停/删除)
- 任务依赖链 + DAG 可视化(上游成功触发下游)
- 维护窗口(时段禁止调度)
- 任务标签 + 筛选 + 存储类型/节点/存储维度统计
- 任务配置 JSON 导入/导出(集群迁移 & 灾备)
## 体验 & 可达性
- 实时事件流(SSE)+ 右下角 Toast + 历史抽屉(未读徽章)
- Dashboard 免刷新自动更新(订阅 8 类事件)
- 全局搜索(Ctrl+K,跨任务/记录/存储/节点)
- 任务依赖图(ECharts force 布局 + 状态着色)
## 合规 & 可部署
- K8s/Swarm 健康检查端点(/health liveness + /ready readiness)
- 审计日志 CSV 导出(UTF-8 BOM,Excel 兼容)
- Dashboard 多维统计(按类型/状态/节点/存储)
## 破坏性变更
- POST /backup/records/:id/restore 返回格式变更为 {restoreRecordId, ...}
(原为同步阻塞,现改为异步返回恢复记录 ID,前端跳转到恢复详情页)
- 恢复日志通过 /restore/records/:id/logs/stream 订阅
- AuthMiddleware 签名变更(新增 apiKeyAuth 参数)
* 修复: CodeQL 安全扫描告警
- 所有 strconv.ParseUint 由 64bit 改为 32bit 位宽,strconv 内置溢出检查
- hashApiKey 参数改名 rawToken 避免 CodeQL 误判为密码哈希(API Key 是 192 位
高熵 token,使用 bcrypt 会引入不必要的延迟;同时补充安全说明)
* 修复: API Key 哈希改用 HMAC-SHA256 + 应用级 pepper
- 符合 RFC 2104 标准,业界 API token 存储的推荐方案
- 数据库泄漏场景下增加离线反推难度(需同时获取二进制 pepper)
- 规避 CodeQL go/weak-sensitive-data-hashing 对裸 SHA-256 的误判
6.3 KiB
设计文档:BackupX 企业级深化 — RBAC + API Key + 事件总线 + 节点配额
- 日期:2026-04-19
- 范围:本轮聚焦企业级权限、DevOps 集成与集群资源隔离
- 状态:已落地(用户授权自主执行)
1. 问题与目标
前三轮已完成"集群路由、可验证恢复、SLA 监控、任务分组"。企业化缺口:
- 多用户 / 权限隔离:系统只有一个 admin,团队无法协作
- DevOps 集成:CI/CD、监控脚本只能用户名密码登录(反模式)
- 事件订阅:仅备份成功/失败,verify/restore/SLA 等扩展事件不触达
- 集群资源管理:所有节点共享全局 MaxConcurrent,小内存节点被挤爆
本轮交付:
- RBAC:admin / operator / viewer 三级 + 中间件 + 前端控权
- API Key:
bax_前缀,SHA-256 哈希存储,角色继承 - 事件总线:Notification 支持多事件订阅(
backup_success|backup_failed|verify_failed|restore_*|sla_violation) - 节点级并发配额:Node.MaxConcurrent / BandwidthLimit,独立 semaphore
2. RBAC 设计
2.1 角色定义
admin 全权(用户管理、API Key、系统设置、节点管理、删除数据)
operator 日常运维(任务/存储/通知 CRUD、触发执行/恢复/验证)
viewer 只读(仪表盘、任务列表、记录、日志,不能触发或改变状态)
2.2 实现
模型层:User.Role 已存在,补充 User.Disabled、常量 + IsValidRole()。
中间件(server/internal/http/middleware.go):
AuthMiddleware(jwtManager, apiKeyAuth):支持 JWT(现有)+ API Key(bax_前缀)RequireRole(roles...):白名单角色RequireNotViewer():快捷方式 — 禁止 viewer 触发写入/变更
路由映射(server/internal/http/router.go):
- 全部 GET 列表/详情:仅需 AuthMiddleware(viewer 可见)
- POST/PUT/DELETE 任务、存储、通知、记录操作:+
RequireNotViewer() - 用户管理、API Key、节点管理、系统设置写入:+
RequireRole("admin")
前端:
utils/permissions.ts:isAdmin/canWrite/isViewer/roleLabelAppLayout菜单按角色过滤(用户/API Key 菜单仅 admin 可见)- 任务列表按钮、记录抽屉操作按
canWrite()隐藏 - 顶部用户名后缀角色标签
2.3 兼容性
- 首位用户仍由 Setup 创建为 admin(无破坏)
- 现有 User.Role 默认值 admin 保持
3. API Key
明文格式:bax_ + 24 字节随机 hex(24 位熵,192 bit)
存储:KeyHash = SHA-256(明文),Prefix 取前 12 字符供 UI 区分
识别:中间件看到 Authorization: Bearer bax_xxx 或 X-Api-Key: bax_xxx 走 API Key 路径
管理(仅 admin):
GET /api-keys列表POST /api-keys创建(返回一次明文 + summary)PUT /api-keys/:id/toggle启停DELETE /api-keys/:id撤销
审计:每次使用更新 LastUsedAt,创建/撤销记审计日志
安全考虑:
- 24 字节随机熵,无需加盐
- 无明文日志 / 无明文存储
- 过期支持(TTL 小时数,0=永久)
- 一次性展示:UI Modal 创建后显示明文 + 复制按钮,确认关闭后不可再查看
4. 事件总线
4.1 事件类型
backup_success 备份成功
backup_failed 备份失败
restore_success 恢复成功
restore_failed 恢复失败
verify_failed 验证未通过
sla_violation SLA 违约(后台监控事件)
4.2 订阅模型
Notification.EventTypes 新字段(CSV)。匹配规则:
- EventTypes 非空:严格匹配订阅事件
- EventTypes 为空:沿用 OnSuccess/OnFailure 旧语义(仅 backup_*)
4.3 统一分发
type EventDispatcher interface {
DispatchEvent(ctx, eventType, title, body, fields) error
}
// NotificationService 实现该接口
// VerificationEventNotifier / RestoreService.dispatchRestoreEvent 分别调用
触发点集成:
BackupExecutionService.NotifyBackupResult→ 派发backup_success/backup_failedVerificationService.executeLocally(失败时)→ 派发verify_failedRestoreService.executeLocally(终态)→ 派发restore_success/restore_failed- SLA 违约(后续可由后台 monitor 调用 DispatchEvent(sla_violation))
5. 节点配额(集群优化)
5.1 字段
Node.MaxConcurrent (int, 0=不限) + Node.BandwidthLimit (string, rclone 格式)
5.2 执行模型
BackupExecutionService 新增 nodeSemaphores sync.Map(懒加载 per-node channel):
func (s) acquireNodeSemaphore(ctx, nodeID) chan struct{} {
if nodeID == 0 || nodeRepo == nil { return nil }
if v, ok := nodeSemaphores.Load(nodeID); ok { return v.(chan struct{}) }
node, _ := nodeRepo.FindByID(ctx, nodeID)
if node == nil || node.MaxConcurrent <= 0 { return nil }
created := make(chan struct{}, node.MaxConcurrent)
actual, _ := nodeSemaphores.LoadOrStore(nodeID, created)
return actual.(chan struct{})
}
func (s) executeTask(...) {
if nodeSem := acquireNodeSemaphore(ctx, task.NodeID); nodeSem != nil {
nodeSem <- struct{}{}
defer func() { <-nodeSem }()
}
s.semaphore <- struct{}{} // 全局保底
defer func() { <-s.semaphore }()
...
}
约束:节点容量在首次创建通道时采用,运行时修改 MaxConcurrent 需重启服务生效(避免 resize channel 的 race)。
5.3 UI
节点管理页新增字段(编辑节点时):最大并发、带宽限制。NodeUpdateInput 已扩展。
6. 数据迁移
新增表:api_keys
新增字段:users.disabled、notifications.event_types、nodes.max_concurrent、nodes.bandwidth_limit
全走 AutoMigrate,向后兼容(默认值不破坏现有功能)。
7. 验证
go build ./...✅go vet ./...✅go test ./... -count=1通过npx tsc --noEmit✅- 集群与企业级测试补丁:
- API Key 哈希不可逆(单测可验 SHA-256 确定性 + rawKey mismatch 拒绝)
- 节点 semaphore 懒加载(channel LoadOrStore 幂等)
- 事件分发按订阅匹配(EventTypes 非空时严格)
8. 未做(留给下一轮)
- SSO / OIDC(企业 SSO 接入)
- 节点 Agent 自更新
- 备份复制 / 异地镜像
- SLA 违约后台主动扫描 + DispatchEvent 自动触发
- API Key IP 白名单
- 合规报表导出(PDF/CSV)