Split monolithic kernel_commands.rs (2185 lines) and pipeline_commands.rs (1391 lines) into focused sub-modules under kernel_commands/ and pipeline_commands/ directories. Add gateway module (commands, config, io, runtime), health_check, and 15 new TypeScript client libraries for SaaS relay, auth, admin, telemetry, and kernel sub-systems (a2a, agent, chat, hands, skills, triggers). Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
11 KiB
11 KiB
ZCLAW 系统评估报告
评估日期: 2026-03-31 评估范围: SaaS 后端 (Axum) + Admin V2 (React/Ant Design) + Desktop (Tauri/React/Zustand) 系统定位: LLM Token 池中转管理 + 行业 Agent 模板分发
1. 总览
系统健康度
| 子系统 | 状态 | 端点 | 编译/类型检查 | 评估 |
|---|---|---|---|---|
| SaaS 后端 | 运行中 | localhost:8080 | cargo check 通过 |
良好 |
| Admin V2 | 运行中 | localhost:5173 | tsc --noEmit 通过 |
良好 |
| Desktop | 运行中 | localhost:1420 | 计划文件零错误; 有遗留重构错误 | 基本可用 |
发现汇总
| 严重级别 | SaaS 后端 | Admin V2 | Desktop |
|---|---|---|---|
| Critical | 0 | 0 | 0 |
| High | 1 | 3 | 2 |
| Medium | 5 | 8 | 7 |
| Low | 3 | 8 | 4 |
| 合计 | 9 | 19 | 13 |
2. SaaS 后端评估
2.1 路由覆盖
总计 69 条路由 (5 公开 + 64 受保护)
| 模块 | 路由数 | CRUD 完整性 |
|---|---|---|
| Auth | 8 | 登录/注册/刷新/登出/密码/TOTP |
| Account | 12 | CRUD + 状态管理 + Token + 日志 + Dashboard + 设备 |
| Model Config | 15 | Provider/Model/ApiKey CRUD + 用量统计 |
| Relay | 9 | 中转任务 + Key Pool 管理 |
| Config | 11 | 配置迁移/同步/差异分析 |
| Role | 10 | 角色 CRUD + 权限模板 |
| Prompt | 10 | 提示词 CRUD + 版本管理 |
| Agent Template | 7 | 模板 CRUD + /available + /full |
| Scheduler | 5 | 定时任务 CRUD |
| Telemetry | 4 | 上报 + 统计 |
2.2 安全评估
正面发现:
- 全量参数化查询 (sqlx bind),无 SQL 注入风险
- SSRF 防护:
validate_provider_url()拦截私网 IP、十六进制/八进制混淆 - Argon2id 密码哈希 (spawn_blocking 避免阻塞异步运行时)
- AES-256-GCM 加密 TOTP 密钥和 Provider API Key
- Refresh Token 单次使用 + DB 撤销
- TOTP 暴力破解防护: 5次/10分钟/账户
- Cookie: HttpOnly + SameSite=Strict + Secure (生产环境)
- CORS: 生产环境空白名单直接 panic 拒绝启动
- JWT 密钥: release 编译无
ZCLAW_SAAS_JWT_SECRET拒绝启动 - 请求体限制: 1MB
- TCP keepalive + 短 SO_LINGER 防止 CLOSE_WAIT
发现的问题:
| 级别 | 问题 | 位置 |
|---|---|---|
| High | X-Forwarded-For 头信任 — 攻击者可伪造 IP 绕过限流 |
middleware.rs:138-142 |
| Medium | 内存限流不跨重启持久化,多实例部署时无效 | middleware.rs |
| Medium | format!("SELECT ... FROM {}", table) — 当前安全但模式脆弱 |
db.rs:852,858 |
| Medium | .and_hms_opt(0,0,0).unwrap() 多处 — 理论上安全但不防御 |
model_config/service.rs:441 |
| Medium | scheduler spawn 中 _db 克隆后未使用 |
scheduler.rs:46 |
| Medium | SCHEMA_VERSION=9 但仅 5 个迁移文件 — 可能混淆 | db.rs:7 |
| Low | Demo 种子明文 API Key — 仅限 demo 场景 | db.rs:467-471 |
| Low | #[allow(dead_code)] 标记的保留函数 |
auth/handlers.rs:499 |
| Low | SQL 分割器中 .unwrap() |
db.rs:127 |
2.3 新功能验证
| 功能 | 状态 | 说明 |
|---|---|---|
accounts.llm_routing 列 |
✅ | 迁移 + CRUD + 登录响应全部接入 |
/agent-templates/available |
✅ | 轻量公开列表端点 |
/agent-templates/:id/full |
✅ | 完整模板端点 |
| Agent 模板 9 个扩展字段 | ✅ | soul_content, scenarios, welcome_message 等 |
| Key Pool LRU 排序 | ✅ | ORDER BY priority, total_requests ASC |
| Key Pool 清理定时任务 | ✅ | 24h 周期清理 key_usage_window |
| 6 个行业种子模板 | ✅ | Coder/Writer/Analyst/Researcher/Translator/Medical |
3. Admin V2 前端评估
3.1 页面清单
12 个页面, 使用 React Query 管理服务端状态, Zustand 仅用于 auth store, 其余均为 useState。
3.2 类型安全
- TypeScript 严格模式启用
noUnusedLocals+noUnusedParameters启用- 整个代码库仅 1 处
any(Providers.tsx:69) - 可选字段正确标记
- 前后端类型基本对齐
3.3 发现的问题
| 级别 | 问题 | 位置 |
|---|---|---|
| High | 未使用的 @ant-design/charts 依赖增加包体积 |
package.json:13 |
| High | any 类型在 addKeyMutation |
Providers.tsx:69 |
| High | Token 刷新竞态 — 刷新失败时 pending 请求未 reject | request.ts:96-99 |
| Medium | 6 个表格无搜索/筛选功能 | Accounts/Models/Providers 等 |
| Medium | 服务端分页不同步本地状态 | Accounts/Models/Providers 等 |
| Medium | Agent Template 详情 Modal 缺少扩展字段展示 | AgentTemplates.tsx:189-210 |
| Medium | Config 内联编辑无加载指示器 | Config.tsx:51 |
| Medium | Dashboard 统计卡片加载时布局跳动 | Dashboard.tsx:93 |
| Medium | 网络错误未包装为 ApiRequestError |
request.ts:115 |
| Medium | configService 返回格式不一致 | services/config.ts:6 |
| Medium | Key Pool 变更丢弃错误详情 | Providers.tsx:78,88,98 |
| Low | Model 类型缺少 created_at/updated_at |
types/index.ts:65-77 |
| Low | 所有表格禁用 page size 切换 | 所有 ProTable 页面 |
| Low | Login 页面固定 480px 非响应式 | Login.tsx:79 |
| Low | Config 点击值缺少 hover 视觉反馈 | Config.tsx:62 |
| Low | OperationLog/PromptVersion 类型微小不匹配 | types/index.ts |
| Low | @ant-design/pro-layout 与 pro-components 冗余 |
package.json:17 |
| Low | AgentTemplateAvailable 类型已定义但未消费 |
types/index.ts:243-250 |
3.4 新功能验证
| 功能 | 状态 | 说明 |
|---|---|---|
| Accounts LLM 路由模式列 | ✅ | Tag 组件 + valueEnum |
| Accounts 编辑 Modal 路由下拉 | ✅ | relay/local Select |
| Providers Key Pool CRUD | ✅ | 添加/启用禁用/删除全部可用 |
| Agent Template 扩展字段表单 | ✅ | emoji/personality/soul_content 等 |
| Agent Template 详情 Modal | ⚠️ | 缺少扩展字段展示 |
4. Desktop 前端评估
4.1 Store 架构
14 个 Zustand Store, 模块化拆分完成。核心协调中心为 connectionStore。
4.2 新功能验证
| 功能 | 状态 | 说明 |
|---|---|---|
| saas-types 模板类型 | ✅ | AgentTemplateAvailable + AgentTemplateFull |
| saas-client 模板 API | ✅ | fetchAvailableTemplates + fetchTemplateFull |
| saasStore 模板状态 | ✅ | availableTemplates + fetchAvailableTemplates |
| connectionStore 路由优先级 | ✅ | admin llm_routing 覆盖 localStorage |
| agentStore.createFromTemplate | ✅ | Clone + SOUL.md 持久化 |
| Wizard Step 0 模板选择 | ✅ | Grid 布局 + 空白 Agent 选项 |
4.3 发现的问题
| 级别 | 问题 | 位置 |
|---|---|---|
| High | 模板 Grid 非响应式 — 使用 getState() 而非 React hook |
AgentOnboardingWizard.tsx:387 |
| High | adminRouting 从 localStorage 解析无验证 | connectionStore.ts:358-372 |
| Medium | 8 处 console.log/warn 在生产 store 中 |
agentStore.ts, handStore.ts |
| Medium | sessionStore 假设 GatewayClient 不适配 KernelClient | sessionStore.ts:225 |
| Medium | ChatStore persist partialize 日期序列化 | chatStore.ts:703 |
| Medium | OfflineStore 健康检查 interval 清理风险 | offlineStore.ts:347 |
| Medium | 硬编码中文错误消息 (无 i18n) | saasStore.ts, connectionStore.ts |
| Medium | gateway-api.ts / kernel-hands.ts 有 TS 错误 | 之前重构遗留 |
| Low | gatewayStore facade 订阅所有 store 引起过多渲染 | gatewayStore.ts:67-76 |
| Low | Store 初始化 setTimeout 时序问题 | store/index.ts:89-92 |
| Low | deprecated secureStorageSync 仍导出 |
secure-storage.ts:306-330 |
| Low | SkillInfo 类型微小不匹配 | configStore.ts:638-665 |
4.4 安全评估
- SaaS Token: OS keyring 存储 + 加密 localStorage fallback — 合理
- Legacy 明文 Token 清理逻辑存在
- API Key: secureStorage 存储带格式验证 + 哈希
- Master encryption key 在无 keyring 时存 localStorage — 降级方案
- authToken 始终为 null 在 Zustand state — 仅在 saasClient 内存中持有
5. 架构一致性验证
设计规格 vs 实现
基于 docs/superpowers/specs/2026-03-30-saas-positioning-design.md 逐项核对:
| 设计要求 | 实现状态 | 说明 |
|---|---|---|
| 账号级 LLM 路由 (relay/local) | ✅ 完成 | accounts.llm_routing 列 + CRUD + 登录响应 |
| Admin 配置路由模式 | ✅ 完成 | Accounts 页编辑 Modal 有下拉 |
| Desktop 遵守路由模式 | ✅ 完成 | connectionStore 优先级覆盖 |
| Token Pool 多 Key 轮转 | ✅ 完成 | LRU 排序 + RPM/TPM 限制 |
| Key Pool Admin 管理 | ✅ 完成 | 添加/启用禁用/删除 |
| 行业模板扩展字段 | ✅ 完成 | 9 个新字段 (soul_content 等) |
| /available 端点 | ✅ 完成 | 轻量公开列表 |
| /full 端点 | ✅ 完成 | 完整模板数据 |
| Desktop 模板消费 | ✅ 完成 | fetchAvailableTemplates + fetchTemplateFull |
| Agent 首次创建选模板 | ✅ 完成 | Wizard Step 0 Grid |
| SOUL.md 注入 | ✅ 完成 | createFromTemplate 持久化 |
| 模板不覆盖已成长 Agent | ✅ 完成 | 仅在创建时使用 |
结论: 设计规格 12/12 项全部实现。
6. 优先修复建议
P0 — 立即修复 (安全/稳定性)
- Token 刷新竞态 (
request.ts:96-99): 刷新失败时 reject 所有 pending 请求 - X-Forwarded-For 信任 (
middleware.rs:138-142): 限制仅信任已知代理 IP
P1 — 近期修复 (功能完整性)
- 模板 Grid 响应式 (
AgentOnboardingWizard.tsx:387): 使用useSaaSStore()hook 替代getState() - Agent Template 详情 Modal (
AgentTemplates.tsx): 补充扩展字段展示 - adminRouting 解析验证 (
connectionStore.ts:358): 对 localStorage 解析结果做类型校验 - 清理
@ant-design/charts未使用依赖
P2 — 中期优化 (代码质量)
- 统一分页状态管理 — Admin 多个表格页
- 添加表格搜索/筛选功能 — 至少 Accounts/Models/Providers
- 修复 gateway-api.ts / kernel-hands.ts TS 错误 — 之前重构遗留
- 替换 store 中的 console.log — 使用 createLogger
- Config 页内联编辑加载指示
P3 — 长期改进
- 内存限流 → Redis/PostgreSQL 持久化限流 (多实例部署准备)
- i18n 框架 (当前所有中文硬编码)
- 单元测试 — Admin V2 和 Desktop 目前零测试覆盖
- 统一 SAAS_SCHEMA_VERSION 管理 (减少迁移文件与版本号的不一致困惑)
7. 结论
系统整体评价: 良好 (B+)
优势:
- 后端安全实践优秀: 参数化查询、SSRF 防护、密钥加密、Cookie 安全
- 设计规格 100% 实现,无遗漏
- Admin V2 TypeScript 严格模式,仅 1 处
any - 69 个 API 端点覆盖全面,权限控制细粒度
- Desktop Store 架构清晰,14 个 store 模块化
短板:
- Desktop 有遗留 TS 错误未修复 (gateway-api.ts, kernel-hands.ts)
- Admin V2 缺少搜索/筛选功能影响可用性
- Token 刷新竞态条件需立即修复
- 零测试覆盖 (Admin V2 + Desktop)
- Agent Template 详情展示不完整