Files
zclaw_openfang/docs/features/08-saas-platform/00-saas-overview.md
iven 22b967d2a6
Some checks failed
CI / Rust Check (push) Has been cancelled
CI / Lint & TypeCheck (push) Has been cancelled
CI / Unit Tests (push) Has been cancelled
CI / Build Frontend (push) Has been cancelled
CI / Security Scan (push) Has been cancelled
CI / E2E Tests (push) Has been cancelled
docs(features): v0.10.1/v0.10.2 数字校准 + 行业模板文档更新
- README.md: SKILL 76→75, Tauri 命令 175→171, SaaS API 58→131, Workers 5→7, 数据表 25→34, Admin 11→13 页面
- 00-saas-overview.md: Agent Template 新增 5 个端点文档、种子数据表、端到端数据流图
- roadmap.md: 同步最新数字
- fix(saasStore): toTopRequired → totpRequired 拼写修复
2026-04-03 21:29:44 +08:00

329 lines
17 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.

# ZCLAW SaaS 平台 — 总览
> 最后更新: 2026-04-01 | 实施状态: Phase 1-4 全部完成 + 架构重构完成10 个后端模块 + Worker + Scheduler + Admin V2 (Vite + Ant Design Pro) + 桌面端完整集成
## 架构概述
ZCLAW SaaS 平台为桌面端用户提供云端能力包括模型中转Key 池、账号管理、配置同步、Prompt OTA、Agent 模板和遥测收集。
```text
桌面端 (Tauri/React)
├── Mode A: Tauri Kernel (本地直连 LLM)
├── Mode B: Gateway WebSocket (本地中转)
└── Mode C: SaaS Cloud ──→ Rust/Axum 后端 (端口 8080) ──→ 上游 LLM Provider
├── Admin V2 (Ant Design Pro 纯 SPA)
└── PostgreSQL (数据持久化)
```
## 技术栈
| 层级 | 技术 | 说明 |
|------|------|------|
| 后端 | Rust + Axum + sqlx + PostgreSQL | JWT + API Token 双认证RBAC 权限 |
| Admin V2 | Vite 6 + React 19 + antd v5 + ProComponents | 纯 SPA替代 Next.js消除 SSR/hydration 问题) |
| 桌面端 | React 18 + Zustand + TypeScript | saas-client.ts 30+ API 方法 |
| 安全 | Argon2id + TOTP 2FA (AES-256-GCM) + RBAC | 速率限制 + 操作审计 + SSRF 防护 |
## 数据库
- **引擎**: PostgreSQL (sqlx 异步驱动)
- **Schema 版本**: v6 (TIMESTAMPTZ 时间戳类型)
- **数据表**: 25 张 (accounts, providers, models, relay_tasks, prompt_templates, agent_templates, telemetry_reports 等)
- **种子数据**: 3 个系统角色 (super_admin, admin, user)3 个内置 Prompt 模板
- **迁移系统**: 声明式 SQL 文件 (`crates/zclaw-saas/migrations/`),按文件名排序执行
- **连接池**: 50 max / 5 min 连接10s 获取超时300s 空闲超时1800s 最大生命周期
## 功能模块
| 模块 | 完成度 | API 路由数 | 核心能力 |
|------|--------|-----------|----------|
| 认证 (Auth) | 100% | 8 | JWT + API Token 双认证、注册/登录、密码修改、/me、TOTP 2FA (AES-256-GCM 加密) |
| 账号 (Account) | 100% | 12 | CRUD + 角色管理 + 角色提升防护 + 设备注册/心跳 + 操作日志 + Dashboard 统计 |
| 模型配置 (Model Config) | 100% | 14 | Provider/Model/Key CRUD + Key 轮换 + 用量统计 (按天/按模型聚合) |
| 中转 (Relay) | 100% | 9 | SSE 流式 + JSON 响应 + Key 池管理 + RPM/TPM 限制 + 指数退避重试 + SSRF 防护 |
| 配置迁移 (Migration) | 100% | 9 | 配置 CRUD + 分析 + 种子数据 (21 项默认) + push/merge 同步 + diff 对比 + 增量拉取 |
| 角色 (Role) | 100% | 7 | Role CRUD + 系统角色保护 + 权限模板 + 批量应用 |
| Prompt OTA | 100% | 8 | 模板 + 版本管理 + OTA 批量检查 + 版本回滚 + 不可变版本历史 |
| Agent 模板 | 100% | 5 | 模板 CRUD + tools/capabilities/model 绑定 + 可见性控制 |
| 遥测 (Telemetry) | 100% | 4 | 批量 Token 用量上报 + 模型聚合统计 + 每日统计 + 审计摘要 |
| 定时任务 (Scheduled Task) | 100% | 2 | 用户定时任务 CRUD (创建/列表/更新/删除)30s 轮询执行 |
| **Worker 系统** | 100% | — | 5 个 Worker (log_operation, cleanup_rate_limit, cleanup_refresh_tokens, record_usage, update_last_used)mpsc 异步调度,自动重试 |
| **声明式 Scheduler** | 100% | — | TOML 配置定时任务,灵活间隔 (30s/5m/1h/1d)run_on_start内置 DB 清理 |
| **合计** | — | **58** | — |
## API 端点一览
### 公开端点 (无需认证)
- `POST /api/v1/auth/register` — 注册
- `POST /api/v1/auth/login` — 登录 (支持 TOTP 验证)
- `GET /api/health` — 健康检查
### 认证 (Auth)
- `GET /api/v1/auth/me` — 当前用户信息
- `POST /api/v1/auth/refresh` — 刷新 Token
- `PUT /api/v1/auth/password` — 修改密码
- `POST /api/v1/auth/totp/setup` — 生成 TOTP 密钥,返回 otpauth:// URI
- `POST /api/v1/auth/totp/verify` — 验证 TOTP 码并启用 2FA
- `POST /api/v1/auth/totp/disable` — 禁用 2FA (需密码确认)
### 账号管理 (Account)
- `GET /api/v1/accounts` — 列出账号 (admin分页 + 角色/状态/搜索过滤)
- `GET /api/v1/accounts/:id` — 获取账号
- `PATCH /api/v1/accounts/:id` — 更新账号 (自更新有限字段admin 可设置角色)
- `PATCH /api/v1/accounts/:id/status` — 更新状态 (admin: active/disabled/suspended)
- `GET /api/v1/tokens` — 列出 API Token
- `POST /api/v1/tokens` — 创建 API Token (权限限制为创建者子集)
- `DELETE /api/v1/tokens/:id` — 撤销 Token
- `GET /api/v1/devices` — 列出当前用户设备
- `POST /api/v1/devices/register` — 注册/更新设备 (UPSERT)
- `POST /api/v1/devices/heartbeat` — 设备心跳
- `GET /api/v1/logs/operations` — 操作日志 (admin分页)
- `GET /api/v1/stats/dashboard` — 仪表盘统计 (admin)
### Provider / Model / Key 管理
- `GET/POST /api/v1/providers` — Provider 列表/创建
- `GET/PATCH/DELETE /api/v1/providers/:id` — 单个 Provider
- `GET /api/v1/providers/:id/models` — Provider 下的模型列表
- `GET/POST /api/v1/models` — Model 列表/创建
- `GET/PATCH/DELETE /api/v1/models/:id` — 单个 Model
- `GET/POST /api/v1/keys` — 账号 API Key 列表/创建
- `POST /api/v1/keys/:id/rotate` — 轮换 API Key
- `DELETE /api/v1/keys/:id` — 撤销 API Key
- `GET /api/v1/usage` — 用量统计 (按日期/模型/Provider 过滤)
### 中转 (Relay)
- `GET /api/v1/relay/models` — 可用中转模型
- `POST /api/v1/relay/chat/completions` — OpenAI 兼容聊天中转 (SSE/JSON)
- `GET /api/v1/relay/tasks` — 中转任务列表 (分页 + 状态过滤)
- `GET /api/v1/relay/tasks/:id` — 获取单个任务
- `POST /api/v1/relay/tasks/:id/retry` — 重试失败任务 (admin)
- `GET /api/v1/providers/:provider_id/keys` — Provider Key 池列表 (admin)
- `POST /api/v1/providers/:provider_id/keys` — 添加 Key 到池 (admin)
- `PUT /api/v1/providers/:provider_id/keys/:key_id/toggle` — 切换 Key 启停 (admin)
- `DELETE /api/v1/providers/:provider_id/keys/:key_id` — 删除池中 Key (admin)
### 配置迁移 (Migration)
- `GET /api/v1/config/items` — 列出配置项 (分页 + 分类/来源过滤)
- `GET /api/v1/config/items/:id` — 获取配置项
- `POST /api/v1/config/items` — 创建配置项 (admin)
- `PUT /api/v1/config/items/:id` — 更新配置项 (admin)
- `DELETE /api/v1/config/items/:id` — 删除配置项 (admin)
- `GET /api/v1/config/analysis` — 配置分析 (分类摘要 + 全部项)
- `POST /api/v1/config/seed` — 种子配置 (admin21 项默认含 11 项安全策略)
- `POST /api/v1/config/sync` — 配置同步 (push/merge 模式)
- `POST /api/v1/config/diff` — 配置差异对比 (只读)
- `GET /api/v1/config/sync-logs` — 同步日志 (分页)
- `GET /api/v1/config/pull` — 批量拉取配置 (支持 since 增量)
### 角色 (Role)
- `GET /api/v1/roles` — 列出角色
- `GET/POST /api/v1/roles/:id` — 角色 CRUD (系统角色不可修改/删除)
- `PUT/DELETE /api/v1/roles/:id` — 更新/删除角色 (admin)
- `GET /api/v1/permission-templates` — 权限模板列表
- `POST /api/v1/permission-templates` — 创建模板 (admin)
- `POST /api/v1/permission-templates/:id/apply` — 批量应用模板到账号
### Prompt OTA
- `POST /api/v1/prompts/check` — OTA 批量检查更新 (设备上报版本,返回差量)
- `GET /api/v1/prompts` — 列出模板 (分页 + 分类/来源/状态过滤)
- `POST /api/v1/prompts` — 创建模板 + 初始 v1
- `GET /api/v1/prompts/:name` — 按名称获取模板
- `PUT /api/v1/prompts/:name` — 更新模板元数据
- `DELETE /api/v1/prompts/:name` — 归档模板
- `GET /api/v1/prompts/:name/versions` — 版本历史
- `GET /api/v1/prompts/:name/versions/:version` — 获取特定版本
- `POST /api/v1/prompts/:name/versions` — 发布新版本 (自动递增)
- `POST /api/v1/prompts/:name/rollback/:version` — 回滚到指定版本
### Agent 模板
- `GET /api/v1/agent-templates` — 列出模板 (分页 + 分类/来源/可见性过滤)
- `POST /api/v1/agent-templates` — 创建模板 (输入验证: name 非空+长度限制, temperature 0.0-1.0, max_tokens 0-65535)
- `GET /api/v1/agent-templates/:id` — 获取模板 (含全部 25 列)
- `GET /api/v1/agent-templates/available` — 列出公开可用模板 (轻量级, 仅核心字段)
- `POST /api/v1/agent-templates/:id` — 更新模板
- `DELETE /api/v1/agent-templates/:id` — 归档模板
- `POST /api/v1/agent-templates/:id/create-agent` — 从模板创建 Agent 配置 (tools 合并, model fallback)
- `POST /api/v1/accounts/me/assign-template` — 分配行业模板到当前账户
- `GET /api/v1/accounts/me/assigned-template` — 获取已分配的行业模板
- `DELETE /api/v1/accounts/me/assigned-template` — 取消行业模板分配
#### 行业模板种子数据
6 个内置行业模板 (source='builtin'):
| 模板 | 模型 | 工具 | 温度 |
|------|------|------|------|
| Code Assistant | gpt-4o | file_read, file_write, shell_exec | 0.3 |
| Content Writer | claude-sonnet-4-20250514 | web_fetch, file_write | 0.7 |
| Data Analyst | gemini-2.5-pro | shell_exec, file_read | 0.2 |
| Research Agent | deepseek-chat | web_fetch, file_read | 0.5 |
| Translator | gpt-4o | (none) | 0.3 |
| Medical Assistant | claude-sonnet-4-20250514 | web_fetch, file_read | 0.2 |
#### 端到端数据流
```text
用户选择模板 → assignTemplate(templateId)
→ 后端: accounts.assigned_template_id = templateId
→ 前端 createFromTemplate(template)
→ Step 1: saasClient.createAgentFromTemplate(templateId) — 后端合并 tools+capabilities
→ Step 2: client.createClone(merged config)
→ Step 3: identity.updateFile('soul', soul_content)
→ Step 4: identity.updateFile('system', system_prompt)
→ Step 5: updateClone(temperature, maxTokens, tools, source_template_id, welcomeMessage, quickCommands)
→ Step 6: loadClones() 刷新 store
→ ChatArea: FirstConversationPrompt
→ clone.welcomeMessage || generateWelcomeMessage()
→ clone.quickCommands || 硬编码 QUICK_ACTIONS
```
### 遥测 (Telemetry)
- `POST /api/v1/telemetry/report` — 批量上报 Token 用量 (每次最多 500 条)
- `GET /api/v1/telemetry/stats` — 模型聚合统计 (请求次数/Token/延迟/成功率)
- `GET /api/v1/telemetry/daily` — 每日使用量聚合 (按设备去重)
- `POST /api/v1/telemetry/audit` — 批量审计日志摘要 (仅动作类型和计数)
### 定时任务 (Scheduled Task)
- `POST /api/scheduler/tasks` — 创建定时任务 (支持 cron/interval 两种调度模式)
- `GET /api/scheduler/tasks` — 列出当前用户的定时任务
- `PATCH /api/scheduler/tasks/:id` — 更新定时任务 (名称/调度/启用状态)
- `DELETE /api/scheduler/tasks/:id` — 删除定时任务
## 安全特性
| 特性 | 实现 |
|------|------|
| 密码存储 | Argon2id + 随机盐 |
| TOTP 2FA | AES-256-GCM 加密密钥 + 兼容旧版明文格式 |
| JWT | RS256/HS256支持过期 Token 刷新 |
| API Token | `zclaw_` 前缀SHA-256 哈希存储 |
| RBAC | 三级系统角色 + 自定义角色 + 权限模板 |
| 角色提升防护 | 自更新时禁止修改 role 字段 |
| 速率限制 | 滑动窗口 per-account (可配置 RPM) |
| SSRF 防护 | 私有 IP/回环/元数据端点/十六进制 IP/DNS 解析检查 |
| Key 池安全 | RPM/TPM 限制 + 429 自动冷却 + Retry-After 支持 |
| 审计日志 | 所有写操作记录500 错误不暴露内部细节 |
## 中转 (Relay) 核心流程
```text
客户端请求 → Auth 中间件 → Relay Handler
├── 1. select_best_key() — 选择最优 Key (非冷却 + 未超 RPM/TPM + 优先级)
│ └── Key 池耗尽 → 回退到 Provider 级单 Key
├── 2. execute_relay() — 向上游发送请求
│ ├── User-Agent: claude-code/1.0 — Coding Plan API 兼容
│ ├── SSE 流式: 捕获流事件中的 usage异步记录
│ └── JSON: 从响应提取 usage同步记录
├── 3. 重试策略 — max_attempts (默认 3)
│ ├── 429: 标记 Key 冷却 → 立即切换下一个 Key (不等待)
│ └── 其他错误: 指数退避重试
└── 4. SSRF 防护 — 验证 Provider URL阻断私有网络请求
```
## 桌面端 LLM 路由模式 (llm_routing)
账户级别 `llm_routing` 设置控制桌面端如何调用 LLM
| 模式 | 行为 | 适用场景 |
|------|------|---------|
| `relay` | 桌面端通过 SaaS relay + Key Pool 调用 LLM | 共享 Key 池,无需本地 API Key |
| `local` | 桌面端直连本地 kernel需要本地 API Key | 私有部署,本地模型 |
**路由优先级**: Admin 配置的 `llm_routing` 覆盖桌面端 localStorage 中的 `connectionMode`。登录时 SaaS 后端返回的 `account.llm_routing` 写入 localStorage`connectionStore.connect()` 读取并强制切换。
**数据流**:
```text
llm_routing=relay:
Desktop → connectionStore (llm_routing=relay) → KernelClient
→ baseUrl = saasUrl/api/v1/relay → kernel 追加 /chat/completions
→ apiKey = SaaS JWT token → Bearer 认证
→ Key Pool 选择最优 Key → 上游 Provider
llm_routing=local:
Desktop → connectionStore (llm_routing=local) → KernelClient
→ 本地配置的 apiKey + baseUrl → 直连 Provider
```
## 配置同步模式
| 模式 | 行为 | 使用场景 |
|------|------|---------|
| push | 客户端覆盖 SaaS 值,缺失则创建 | 新设备首次同步 |
| merge | 仅填充 SaaS 空值,冲突时 SaaS 优先 | 多设备合并 |
| diff | 只读对比,返回差异列表 | 同步前预览 |
| pull | 批量拉取,支持 since 增量 | 定期同步 |
## 关键文件索引
### 后端 (crates/zclaw-saas/)
| 文件 | 职责 |
|------|------|
| `src/main.rs` | 服务启动 + 路由注册 + 后台任务 (速率限制清理 + 设备清理) |
| `src/db.rs` | 数据库初始化 + Schema v6 + TIMESTAMPTZ 迁移 + 25 张表 + Admin 引导 |
| `src/state.rs` | AppState (PgPool + Config + JWT Secret + 速率限制 DashMap + WorkerDispatcher) |
| `src/config.rs` | SaaSConfig (Server/Database/Auth/Relay/RateLimit/Scheduler),多环境配置加载 |
| `src/error.rs` | SaasError 16 种变体 + HTTP 状态码映射 |
| `src/middleware.rs` | Request-ID + API-Version + 速率限制中间件 |
| `src/common.rs` | PaginatedResponse<T> + 分页工具函数 |
| `src/auth/` | JWT + API Token 双认证 + TOTP 2FA + 密码管理 |
| `src/account/` | 账号 CRUD + 设备管理 + Dashboard + API Token |
| `src/model_config/` | Provider/Model/AccountKey CRUD + 用量统计 |
| `src/relay/` | SSE/JSON 中转 + Key 池 + 重试 + SSRF 防护 |
| `src/relay/key_pool.rs` | Key 池选择算法 + RPM/TPM 跟踪 + 冷却管理 |
| `src/migration/` | 配置 CRUD + 同步 (push/merge) + diff + 增量 pull |
| `src/role/` | 角色 CRUD + 权限模板 + 批量应用 |
| `src/prompt/` | Prompt 模板 + 版本管理 + OTA 检查 + 回滚 |
| `src/agent_template/` | Agent 模板 CRUD + 可见性控制 |
| `src/telemetry/` | Token 用量上报 + 模型统计 + 每日统计 + 审计摘要 |
| `src/scheduled_task/` | 用户定时任务 CRUD (创建/列表/更新/删除) + 30s 轮询执行 |
| `src/workers/` | Worker 系统 (5 Worker: log_operation, cleanup_rate_limit, cleanup_refresh_tokens, record_usage, update_last_used) |
| `src/scheduler.rs` | 声明式 Scheduler (TOML 定时任务配置 + DB 清理任务) |
| `migrations/` | SQL 迁移文件 (Schema v6, TIMESTAMPTZ) |
### Admin 管理后台 (admin-v2/)
> **迁移说明**: 原有 `admin/`Next.js 14因 SSR/hydration 与 SWR 的根本冲突导致后端连接池耗尽,
> 已用 `admin-v2/`Vite + React + Ant Design Pro 纯 SPA完全替代。
> 详见 [故障排查 13 节](../../knowledge-base/troubleshooting.md)
| 文件 | 职责 |
|------|------|
| `src/services/request.ts` | Axios 实例 + JWT 拦截器 + 401 自动刷新 |
| `src/services/auth.ts` | 认证 API (login/refresh/me) |
| `src/stores/authStore.ts` | Zustand: token + account + permissions |
| `src/types/index.ts` | 全部 TypeScript 类型定义 |
| `src/layouts/AdminLayout.tsx` | ProLayout 侧边栏 + 用户信息 |
| `src/pages/Dashboard.tsx` | 仪表盘 (统计卡片 + 趋势图 + 操作日志) |
| `src/pages/Accounts.tsx` | 账号管理 (CRUD + 角色筛选) |
| `src/pages/Providers.tsx` | 服务商管理 + Key Pool 子表 |
| `src/pages/Models.tsx` | 模型管理 |
| `src/pages/ApiKeys.tsx` | API 密钥管理 |
| `src/pages/Usage.tsx` | 用量统计 (时间范围 + Tab 切换) |
| `src/pages/Relay.tsx` | 中转任务管理 |
| `src/pages/Config.tsx` | 系统配置 (分类 Tab) |
| `src/pages/Prompts.tsx` | 提示词管理 (版本历史 + 回滚) |
| `src/pages/Logs.tsx` | 操作日志 |
| `src/pages/AgentTemplates.tsx` | Agent 模板管理 |
### 桌面端 (desktop/src/)
| 文件 | 职责 |
|------|------|
| `lib/saas-client.ts` | SaaS HTTP 客户端 (30+ API 方法 + 自动重试 + 离线检测) |
| `store/saasStore.ts` | SaaS 状态管理 (登录/设备/心跳/配置同步/遥测) |
| `lib/telemetry-collector.ts` | 遥测数据采集器 |
| `components/SaaS/SaaSStatus.tsx` | 连接状态 + 可用模型 |
| `components/SaaS/SaaSSettings.tsx` | 设置页 (密码/TOTP/迁移) |
| `components/LoginPage.tsx` | 登录/注册 UI |
---
**最后更新**: 2026-04-01