Files
zclaw_openfang/wiki/saas.md
iven 5d88d129d1 docs(wiki): Phase B+C完成 — middleware/saas/security/memory 5节模板重构
- middleware.md: 集成契约+3不变量+执行流 (157→136行)
- saas.md: 移除安全重复→引用security.md+Token Pool算法 (231→173行)
- security.md: 吸收saas认证内容成为安全唯一真相源 (158→199行)
- memory.md: 最大压缩363→147行+Hermes洞察提炼+4不变量

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
2026-04-22 21:42:24 +08:00

174 lines
6.8 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.

---
title: SaaS 平台
updated: 2026-04-22
status: active
tags: [module, saas, billing, relay]
---
# SaaS 平台
> 从 [[index]] 导航。关联模块: [[routing]] [[chat]] [[security]]
## 设计决策
**核心定位: SaaS 是 Tauri 桌面端的中枢,不是独立 Web 应用。**
| 决策 | 为什么 |
|------|--------|
| Token Pool 集中管理 | 桌面端不持有 LLM API KeySaaS 维护共享 Key 池做 RPM/TPM 轮换,支持用量追踪和计费 |
| 16 模块目录划分 | 按业务域高内聚auth/relay/billing/knowledge/model_config/account/agent_template/industry/role/prompt/scheduled_task/telemetry/migration/models/tasks/workers |
| 137 routes + 13 路由模块 | main.rs 用 `.merge()` 统一注册,每个模块独立维护路由 |
| 7 后台 Workers | 用量记录/聚合、限流清理、token 清理、embedding 生成等异步任务解耦 |
| 认证与安全 | 详见 [[security]] |
## 关键文件 + 数据流
### SaaS 模块结构
16 个目录 (`crates/zclaw-saas/src/`):
```
account/ agent_template/ auth/ billing/ industry/
knowledge/ migration/ model_config/ models/ prompt/
relay/ role/ scheduled_task/ tasks/ telemetry/ workers/
```
### 核心文件
| 文件 | 职责 |
|------|------|
| `crates/zclaw-saas/src/main.rs` | 路由注册入口 (13 个 .merge()) |
| `crates/zclaw-saas/src/relay/handlers.rs` | 聊天中转 + Token Pool 分配 |
| `crates/zclaw-saas/src/billing/` | 配额递增/订阅/支付回调 |
| `crates/zclaw-saas/src/knowledge/` | 知识库 CRUD + pgvector (最大模块, 24 routes) |
| `crates/zclaw-saas/src/workers/` | 7 个后台 Worker |
| `crates/zclaw-saas/migrations/` | SQL 迁移 (38 文件, 42 CREATE TABLE) |
| `admin-v2/src/pages/` | 17 页管理后台 |
| `desktop/src/lib/saas-client.ts` | 前端 SaaS API 客户端 |
| `desktop/src/store/saasStore.ts` | SaaS 认证状态 |
### 数据流
```
桌面端请求 (ChatPanel)
→ Tauri invoke / HTTP SSE
→ SaaS Relay (POST /api/v1/relay/chat/completions)
→ JWT 验证 → Token Pool 选择 Key → LLM API
→ SSE 流式返回
→ 桌面端 streamStore.onDelta 渲染
```
### 集成契约
| 方向 | 接口 | 说明 |
|------|------|------|
| Called by <-- desktop | Tauri invoke / HTTP SSE | Chat relay, billing, auth |
| Calls --> relay handlers | POST /api/v1/relay/chat/completions | Token Pool RPM/TPM 轮换 |
| Provides --> admin | 137 routes | User/billing/knowledge/model 管理 |
### API 分布
| 模块 | 路由数 | 核心端点 |
|------|--------|---------|
| knowledge | 24 | 分类/条目/搜索/上传/版本/结构化 |
| model_config | 19 | Provider/模型/Key/模型组/用量 |
| billing | 12 | 订阅/用量/支付/mock/回调/invoice |
| account | 12 | CRUD/状态/token/设备/操作日志/dashboard |
| agent_template | 11 | 模板 CRUD + 创建 Agent + 分配 |
| auth | 9 | POST /auth/{register,login,refresh,logout} + TOTP + password |
| industry | 8 | 行业 CRUD + 账户分配 |
| migration | 8 | 配置项 CRUD + 分析/seed/sync/diff |
| prompt | 6 | Prompt CRUD + 版本/回滚 |
| role | 6 | 角色/权限模板 CRUD |
| telemetry | 4 | 上报/统计/日报/审计 |
| relay | 5 | POST /relay/chat/completions + GET /relay/models |
| scheduled_task | 2 | 定时任务 CRUD |
### 数据表 (42 CREATE TABLE)
核心表: users, agents, conversations, messages, billing_*, knowledge_*, model_configs, roles, permissions, scheduled_tasks, telemetry, agent_templates, saas_schema_version, user_profiles, trajectory_records, industries, account_industries
## 代码逻辑
### Token Pool RPM/TPM 轮换算法
```
SaaS Relay 收到请求
→ 验证 JWT → 提取 user_id
→ Token Pool 选择 Key:
1. priority ASC (高优先级优先)
2. last_used_at ASC (最久未用优先)
3. cooldown 检查 (跳过冷却中的 Key)
4. RPM/TPM 滑动窗口检查 (当前窗口是否超限)
→ 转发请求到 LLM API
→ record_usage worker 异步记录
```
### Workers (7 个)
| Worker | 文件 | 职责 |
|--------|------|------|
| record_usage | workers/ | 用量记录 (relay 后异步) |
| aggregate_usage | workers/ | 用量聚合 (日报/月报) |
| generate_embedding | workers/ | 内容分块 (embedding deferred, pgvector 就绪) |
| log_operation | workers/ | 操作日志 |
| cleanup_rate_limit | workers/ | 限流记录清理 |
| cleanup_refresh_tokens | workers/ | 刷新 token 清理 |
| update_last_used | workers/ | 模型最后使用时间更新 |
### 计费流程
```
用户请求 relay → quota_check_middleware 检查月度配额
→ 通过: relay 正常执行
→ record_usage worker 递增 relay_requests + input_tokens
→ aggregate_usage worker 定期聚合
→ 超额: 返回 429 QuotaExceeded
```
## 活跃问题 + 陷阱
| 问题 | 级别 | 说明 |
|------|------|------|
| Admin 用量统计显示 0/0 | P2 Open | Dashboard 17 requests / 6304 tokens但 Usage 页 0/0数据源不一致 |
| 桌面端 Token 统计为 0 | P2 Open | 前端 token 统计未接通后端数据源 |
| Deepseek 中转任务卡 processing | P3 Open | 特定模型 relay 任务状态不更新 |
| Embedding 生成未实现 | 长期 | pgvector 索引就绪generate_embedding worker 逻辑空 |
| AuthGuard 竞态条件 | P1 Deferred | 并发请求时可能绕过认证 |
陷阱:
- SaaS 数据库需要 PostgreSQL (`docker-compose.yml`),不是 SQLite
- Token Pool 的 RPM/TPM 是滑动窗口不是固定窗口,测试时注意时间边界
- `saas-config.toml` 支持 `${ENV_VAR}` 环境变量插值
- knowledge 是最大模块 (24 routes),修改时影响面广
## 变更日志
| 日期 | 变更 | 提交 |
|------|------|------|
| 2026-04-21 | Embedding 接通 + 自学习 A/B 线 | — |
| 2026-04-17 | E2E 测试 129 链路7 Bug 修复 | — |
| 2026-04-15 | Heartbeat 统一健康系统 | — |
| 2026-04-12 | 行业配置 + 管家主动性全栈 5 Phase | — |
| 2026-04-09 | Hermes Intelligence Pipeline 4 Chunk | 684 tests PASS |
### 测试覆盖
| 功能 | 测试文件 |
|------|---------|
| 认证流程 | `crates/zclaw-saas/tests/auth_test.rs` |
| 认证安全 | `crates/zclaw-saas/tests/auth_security_test.rs` |
| 账户 CRUD | `crates/zclaw-saas/tests/account_test.rs` |
| 账户安全 | `crates/zclaw-saas/tests/account_security_test.rs` |
| 计费 | `crates/zclaw-saas/tests/billing_test.rs` |
| 知识库 | `crates/zclaw-saas/tests/knowledge_test.rs` |
| 模型配置 | `crates/zclaw-saas/tests/model_config_test.rs` |
| Prompt | `crates/zclaw-saas/tests/prompt_test.rs` |
| 权限矩阵 | `crates/zclaw-saas/tests/permission_matrix_test.rs` |
| Relay | `crates/zclaw-saas/tests/relay_test.rs` |
| Relay 验证 | `crates/zclaw-saas/tests/relay_validation_test.rs` |
| 角色 | `crates/zclaw-saas/tests/role_test.rs` |
| 定时任务 | `crates/zclaw-saas/tests/scheduled_task_test.rs` |
| Telemetry | `crates/zclaw-saas/tests/telemetry_test.rs` |
| 配置同步 | `crates/zclaw-saas/tests/migration_test.rs` |