feat: 新增管理后台前端项目及安全加固
Some checks failed
CI / Lint & TypeCheck (push) Has been cancelled
CI / Unit Tests (push) Has been cancelled
CI / Build Frontend (push) Has been cancelled
CI / Rust Check (push) Has been cancelled
CI / Security Scan (push) Has been cancelled
CI / E2E Tests (push) Has been cancelled

refactor(saas): 重构认证中间件与限流策略
- 登录限流调整为5次/分钟/IP
- 注册限流调整为3次/小时/IP
- GET请求不计入限流

fix(saas): 修复调度器时间戳处理
- 使用NOW()替代文本时间戳
- 兼容TEXT和TIMESTAMPTZ列类型

feat(saas): 实现环境变量插值
- 支持${ENV_VAR}语法解析
- 数据库密码支持环境变量注入

chore: 新增前端管理界面
- 基于React+Ant Design Pro
- 包含路由守卫/错误边界
- 对接58个API端点

docs: 更新安全加固文档
- 新增密钥管理规范
- 记录P0安全项审计结果
- 补充TLS终止说明

test: 完善配置解析单元测试
- 新增环境变量插值测试用例
This commit is contained in:
iven
2026-03-31 00:11:33 +08:00
parent 6821df5f44
commit eb956d0dce
129 changed files with 11913 additions and 863 deletions

309
docs/audit-2026-03-30.md Normal file
View File

@@ -0,0 +1,309 @@
# ZCLAW 全面项目审计报告
> **审计日期**: 2026-03-30
> **审计范围**: 系统架构、代码质量、性能、安全、业务功能、用户体验
> **审计基准**: v0.7.0,基于 F16/S2/S4/S8 完成后的代码状态
> **审计方法**: 5 个并行子代理 + 直接代码分析
---
## 一、执行摘要
### 总体评级: **B+ (良好)**
| 维度 | 评级 | 关键发现 |
|------|------|----------|
| 系统架构 | A- | 10 Crate 分层清晰SaaS 独立feature gate 全覆盖 |
| 代码质量 | B | 0 编译警告453 测试但多文件超限53 处 Promise\<any\> |
| 安全性 | B | Cookie 已实现SQL 全参数化,但登出未撤 token无 TLS |
| 性能 | B | 连接池健康检查完备,但 SSE 不响应 shutdown表无自动清理 |
| 业务功能 | A- | 93 API9 Hands66 Skills前后端对齐SaaS 定时任务执行未闭环 |
### 关键数字
| 指标 | 数值 |
|------|------|
| Rust 代码行数 | 54,380 |
| SaaS API 端点 | 93 (10 模块) |
| Tauri 命令 | 106 |
| 测试数量 | 453 (254 unit + 199 async) |
| Hands | 9 |
| Skills | 66 SKILL.md |
| Pipeline YAML | 7 |
| 编译警告 | 0 (项目自有) |
| TypeScript 错误 | 0 |
---
## 二、系统架构审计
### 2.1 Crate 分层 ✅
```
L1: zclaw-types (无 zclaw 依赖) ✅
L1.5: zclaw-growth (仅依赖 types) — 目录在 L5 但依赖在 L1
L2: zclaw-memory (→ types)
L3: zclaw-runtime (→ types, memory, growth)
L4: zclaw-kernel (→ types, memory, runtime, protocols, hands, skills)
L5: zclaw-skills (→ types), zclaw-hands (→ types, runtime), zclaw-protocols (→ types)
zclaw-pipeline (→ types, runtime, kernel, skills, hands)
独立: zclaw-saas (仅依赖 zclaw-types) ✅
```
**架构代理验证结果**:
- ✅ 无循环依赖DAG
- ✅ SaaS 独立于 Kernel
- ✅ workspace members 完整
- ✅ multi-agent feature 传播链正确: desktop → kernel → protocols/a2a
- ✅ wasm feature gate 完整
- ✅ dev-server feature gate 完整
- `zclaw-growth` 目录位置与依赖层级不一致(不影响功能)
- `zclaw-pipeline` 声明了 `zclaw-kernel` 依赖但代码中未直接 import
### 2.2 数据流完整性 ✅
| 链路 | 状态 | 覆盖 |
|------|------|------|
| Desktop UI → Store → Tauri → Kernel → LLM/Hands/Skills | ✅ 完整 | 106 个 Tauri 命令 |
| Admin V2 → Axios → SaaS API → PostgreSQL | ✅ 完整 | 12 个 service 文件 |
| Pipeline YAML → Executor → LLM/Skill/Hand Actions | ✅ 完整 | 三种 Action driver 均已接通 |
---
## 三、代码质量审计
### 3.1 编译状态 ✅
- `cargo check --workspace`: **0 项目警告**
- `admin-v2 tsc --noEmit`: **通过**
- `desktop tsc --noEmit`: **通过**
### 3.2 大文件审计 ⚠️
**Rust 文件(>800 行)**:
| 文件 | 行数 | 建议 |
|------|------|------|
| `kernel_commands.rs` | **2185** | 按功能域拆分 |
| `lib.rs` (desktop) | **1518** | 命令定义独立 |
| `kernel.rs` | **1490** | 拆分 a2a/scheduler 子模块 |
| `pipeline_commands.rs` | **1391** | 按 stage 拆分 |
| `generation.rs` | 1080 | 逻辑连贯,可保持 |
| `quiz.rs` | 1027 | 题目模板导致 |
| `openai.rs` | 912 | 拆分 streaming 子模块 |
| `director.rs` | 912 | 拆分 turn/submission |
| `loop_runner.rs` | 896 | 拆分 tool execution |
| `store.rs` | 804 | 拆分 query builder |
**TypeScript 文件(>800 行)**:
| 文件 | 行数 | 类型安全 |
|------|------|----------|
| `intelligence-client.ts` | 1471 | 低风险 |
| `kernel-client.ts` | 1343 | 低风险 |
| `saas-client.ts` | 1290 | 低风险 |
| **`gateway-client.ts`** | **1227** | **53 处 Promise\<any\>** |
| **`gateway-api.ts`** | **672** | **同上** |
### 3.3 unwrap() 使用 ⚠️
- 68 个 Rust 文件含 unwrap(),生产代码约 108 处
- `store.rs` 独占 75 处(最高风险)
- **P0 风险**: `extraction_adapter.rs:306-310` 链式 unwrapLLM 返回异常格式时 panic
- **P1 风险**: `context_builder.rs` 多处 HashMap `get_mut().unwrap()`
### 3.4 TypeScript 类型安全
- 0 处 `@ts-ignore` / `@ts-nocheck`
- **53 处 `Promise<any>`** 在 gateway-client.ts + gateway-api.ts最大类型安全盲区
- 6 处静默 `catch(() => {})`saasStore.ts 3 处应添加日志)
- 33 处 `#[allow(dead_code)]`(半数标注 "reserved",需定期审视)
### 3.5 测试覆盖
| Crate | 测试数 | 评价 |
|-------|--------|------|
| zclaw-saas | 111 | 良好 |
| zclaw-growth | 75 | 良好 |
| zclaw-pipeline | 59 | 良好 |
| zclaw-types | 57 | 良好 |
| zclaw-runtime | 42 | 中等 |
| zclaw-kernel | 41 | 需提升 |
| zclaw-skills | 22 | 需提升 |
| zclaw-hands | 21 | 需提升 |
| zclaw-memory | 20 | 需提升 |
| zclaw-protocols | **5** | **不足** |
---
## 四、安全审计
### 4.1 安全发现汇总
| 级别 | ID | 问题 | 文件 |
|------|-----|------|------|
| HIGH | SEC-02 | `saas-config.toml` 含明文 DB 密码 | saas-config.toml:16 |
| HIGH | SEC-03 | ShellSkill SKILL.md 命令注入信任模型 | skills/runner.rs:125 |
| HIGH | SEC-04 | 服务端无 TLS 终止 | saas/main.rs:72 |
| HIGH | SEC-05 | JWT debug fallback 密钥硬编码 | saas/config.rs:238 |
| MED | SEC-06 | 登出未撤销服务端 refresh token | saas/auth/handlers.rs:506 |
| MED | SEC-07 | 注册端点无验证码/邀请机制 | saas/auth/handlers.rs:54 |
| MED | SEC-08 | 角色权限缓存无 TTL/失效 | saas/auth/handlers.rs:397 |
| MED | SEC-09 | 登录缺少专门暴力破解保护 | saas/auth/handlers.rs:160 |
| MED | SEC-10 | 生产 CORS 配置含 localhost | saas-config.toml:12 |
| MED | SEC-11 | Cookie Secure 在非 HTTPS 环境失效 | saas/auth/handlers.rs:29 |
| MED | SEC-13 | TOTP 加密密钥从 JWT Secret 派生 | saas/config.rs:285 |
| LOW | SEC-14 | PythonSkill 脚本路径信任模型 | skills/runner.rs:83 |
| LOW | SEC-15 | Rate limit 信任 X-Forwarded-For | saas/middleware.rs:109 |
### 4.2 安全优势
| 项目 | 状态 |
|------|------|
| SQL 注入防护 | ✅ 100% 参数化0 字符串拼接 |
| 密码哈希 | ✅ Argon2id + spawn_blocking |
| Refresh Token Rotation | ✅ 一次性使用 + SHA-256 hash 存储 |
| API Key 加密 | ✅ AES-256-GCM + 随机 nonce |
| 错误信息处理 | ✅ 500 不泄露内部细节 |
| 审计日志 | ✅ 覆盖所有关键操作 + IP |
| TOTP 暴力破解保护 | ✅ 5 次失败锁定 10 分钟 |
| XSS 防护 | ✅ 唯一 innerHTML 用 DOMPurify |
| 账号隔离 | ✅ 所有查询强制 account_id |
| CORS 安全 | ✅ 生产强制白名单 |
---
## 五、性能审计
### 5.1 严重性能问题
| 问题 | 影响 | 文件 |
|------|------|------|
| SSE 流不检查 CancellationToken | graceful shutdown 等待最长 5 分钟 | relay/service.rs |
| 数据表无自动清理 | operation_logs/usage_records/relay_tasks 无限增长 | scheduler.rs |
| 连接池偏小 (max=20) | 高并发 SSE 场景不足 | db.rs:12 |
| Scheduler 循环不监听 shutdown token | 后台 task 不会被取消 | scheduler.rs:55,78,111 |
### 5.2 中等性能问题
| 问题 | 文件 |
|------|------|
| relay_tasks 缺 (account_id, status) 复合索引 | relay/handlers.rs:31 |
| SSE usage 跳过后 task 永久 "processing" | relay/service.rs:302 |
| OTA 提示词 N+1 查询(每模板 2 次) | prompt/service.rs:242 |
| totp_fail_counts 无清理机制 | state.rs:26 |
| `operation_logs` COUNT(*) 无时间范围 | account/handlers.rs:144 |
### 5.3 性能优势
| 项目 | 设计 |
|------|------|
| 连接池健康检查 | 80% 水位 503 + 3s 超时 |
| TCP keepalive | 60s/10s/3次 + SO_LINGER 1s |
| SSE 背压 | bounded channel(128) |
| SSE 并发限制 | Semaphore(16) |
| DashMap 死锁 | RefMut 在 await 前释放 |
| 前端无轮询 | TanStack Query 按需触发 |
---
## 六、业务功能审计
### 6.1 SaaS API 完整度 ✅
| 模块 | 端点数 | CRUD |
|------|--------|------|
| auth (含 TOTP) | 9 | 完整认证流程 |
| account (含 tokens/devices/logs/stats) | 12 | ✅ |
| provider | 6 | ✅ C/R/U/D |
| model | 5 | ✅ C/R/U/D |
| api_keys (含 rotate) | 5 | ✅ |
| relay (含 key pool) | 9 | ✅ |
| config/migration | 12 | ✅ + sync/diff/pull |
| role + permission_template | 11 | ✅ |
| prompt (含 versions/rollback) | 10 | ✅ |
| agent_template | 5 | ✅ |
| scheduled_task | 5 | ✅ |
| telemetry | 4 | ✅ |
| health | 1 | ✅ |
| **总计** | **93** | **完整** |
### 6.2 前后端对齐 ✅
- Admin V2: 12 个 service 文件 → 后端路由全部匹配
- baseURL `/api/v1` + Vite proxy → 无断链
- `withCredentials: true` → Cookie 自动发送
- **后端就绪但无 Admin UI**: Role 管理、TOTP、Prompt 版本、定时任务管理
### 6.3 功能缺口
| 功能 | 后端 | 前端 Admin | 状态 |
|------|------|-----------|------|
| Role CRUD | ✅ 4 端点 | ❌ | 后端就绪 |
| Permission Template | ✅ 4 端点 | ❌ | 后端就绪 |
| TOTP 2FA | ✅ 3 端点 | ❌ | 后端就绪 |
| Prompt 版本管理 | ✅ 4 端点 | ❌ | 后端就绪 |
| 定时任务管理 | ✅ 5 端点 | ❌ | 后端就绪 |
| SaaS 定时任务执行 | ⚠️ 仅状态管理 | — | **未闭环** |
| Kernel 定时任务执行 | ✅ TriggerManager | ✅ | 完整闭环 |
### 6.4 Approval 流程 ✅
完整闭环: 触发 → 检查 → 创建审批 → 前端通知 → 审批/拒绝 → 执行 → 结果通知
---
## 七、待改进项(按优先级)
### P0 — 必须修复
| ID | 问题 | 影响 |
|----|------|------|
| P0-1 | SSE 流不检查 CancellationToken | 停机等待最长 5 分钟 |
| P0-2 | 数据表无自动清理 (logs/usage/relay_tasks) | 磁盘耗尽 + 查询退化 |
| P0-3 | `store.rs` 75 处 unwrap | 数据库异常导致 panic |
| P0-4 | `extraction_adapter.rs` 链式 unwrap | LLM 异常输出导致 panic |
| P0-5 | 登出未撤销服务端 refresh token | XSS 后 token 仍可用 |
### P1 — 应该修复
| ID | 问题 | 影响 |
|----|------|------|
| P1-1 | `kernel_commands.rs` 2185 行 | 可维护性 |
| P1-2 | `gateway-client.ts` 53 处 Promise\<any\> | 类型安全盲区 |
| P1-3 | 连接池 max=20 偏小 | 高并发不足 |
| P1-4 | relay_tasks 缺复合索引 | 查询性能 |
| P1-5 | Scheduler 循环不响应 shutdown | 优雅停机不完整 |
| P1-6 | `saas-config.toml` 含明文密码 | 安全风险 |
| P1-7 | Cookie Secure 在 localhost 失效 | 开发环境认证失败 |
| P1-8 | 登录缺暴力破解保护 | 安全风险 |
| P1-9 | `zclaw-protocols` 仅 5 个测试 | 回归风险 |
### P2 — 可以改进
| ID | 问题 | 影响 |
|----|------|------|
| P2-1 | 多个文件 >800 行 | 代码组织 |
| P2-2 | 角色权限缓存无失效机制 | 降权不即时生效 |
| P2-3 | `sqlx-postgres 0.7.4` 未来兼容性 | 编译噪音 |
| P2-4 | SaaS 定时任务执行未闭环 | 功能不完整 |
| P2-5 | `scheduled_tasks` 路径缺 `/v1` 前缀 | API 一致性 |
| P2-6 | OTA 提示词 N+1 查询 | 性能 |
---
## 八、架构优势
1. **SaaS 独立部署** — 不依赖 Kernel可独立扩展
2. **Feature gate 分离** — multi-agent 功能可选
3. **Cookie + Header 双路径认证** — 向后兼容 + 安全
4. **声明式 Scheduler** — TOML 配置驱动
5. **参数化 SQL 全覆盖** — 零注入风险
6. **连接池健康检查** — 80% 水位自动降级
7. **Argon2id 密码哈希** — 业界最佳实践
8. **审计日志全覆盖** — 所有关键操作 + IP
9. **SSE 背压设计** — bounded channel 防内存溢出
---
*审计完成。5 个并行子代理深度审计,覆盖架构/代码/安全/性能/业务全维度。*