Files
zclaw_openfang/docs/features/COMPREHENSIVE_AUDIT_V8.md
iven 5fdf96c3f5 chore: 提交所有工作进度 — SaaS 后端增强、Admin UI、桌面端集成
包含大量 SaaS 平台改进、Admin 管理后台更新、桌面端集成完善、
文档同步、测试文件重构等内容。为 QA 测试准备干净工作树。
2026-03-29 10:46:41 +08:00

340 lines
15 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+Tauri 系统性功能审计报告 V8
> **审计日期**: 2026-03-29
> **审计范围**: 全量三端审计 — SaaS 后端 + Tauri 桌面端 + Admin 管理后台
> **审计方法**: 五步审计流程 + 十项通用清单 + 五种差距模式 + 安全专项
> **前次审计**: V7 (2026-03-28, 已归档)
---
## 一、执行摘要
| 指标 | 数值 |
|------|------|
| **SaaS API 端点** | 76+ (9 模块, 22+ 数据表) |
| **Tauri 命令** | 150+ (73 个 invoke 调用) |
| **Admin 页面** | 12 (含 login) |
| **文档-代码对齐率** | ~95% |
| **数据流连通率** | 60% (3/5 完整连通, 1 部分连通, 1 断裂) |
| **Dead Code** | 28+ `#[allow(dead_code)]`, 35+ 未调用 API 方法 |
| **安全漏洞** | 1 CRITICAL + 2 HIGH + 2 MEDIUM |
| **差距模式发现** | 12 个 (P0×1, P1×4, P2×4, P3×3) |
| **整体完成度** | **~82%** (核心功能可用,集成链路存在断裂) |
---
## 二、功能清单与完成度矩阵
### 2.1 架构层
| 功能 | 设计目标 | SaaS | Tauri | Admin | 完成度 | 关键差距 |
|------|---------|------|-------|-------|--------|---------|
| 通信层 | 三模式连接 (Kernel/Gateway/SaaS) | N/A | ✅ | N/A | 85% | hand_run 桩命令 |
| 状态管理 | 18 Zustand Store | N/A | N/A | N/A | 80% | 消息不持久化 |
| 安全认证 | Ed25519+JWT+TOTP | ✅ | ✅ | ✅ | 80% | 生物识别/FIDO2 未实现 |
### 2.2 核心功能
| 功能 | 设计目标 | SaaS | Tauri | Admin | 完成度 | 关键差距 |
|------|---------|------|-------|-------|--------|---------|
| 聊天界面 | 流式响应+多模型 | ✅ Relay | ✅ Stream | N/A | 92% | 超长消息卡顿 |
| Agent 分身 | CRUD+模板+切换 | ✅ Template | ✅ Agent | ✅ Template | 85% | 导入/导出未实现 |
| Hands 系统 | 9+ 自主能力 | N/A | ✅ 9 Hands | N/A | 70% | Predictor/Lead 无代码 |
### 2.3 智能层
| 功能 | 设计目标 | SaaS | Tauri | Admin | 完成度 | 关键差距 |
|------|---------|------|-------|-------|--------|---------|
| Agent 记忆 | 跨会话+语义搜索 | N/A | ✅ Viking | N/A | 90% | 大量记忆检索变慢 |
| 身份演化 | SOUL.md+自动改进 | N/A | ✅ | N/A | 70% | Tauri 模式内存存储重启丢失 |
| 反思引擎 | 自动分析+建议 | N/A | ✅ | N/A | 65% | 建议具体性待改进 |
| 心跳巡检 | 定期巡检+主动提醒 | ✅ 设备心跳 | ✅ | N/A | 70% | 持久化调度缺失 |
| 自主授权 | 三级授权+审批 | N/A | ✅ | N/A | 75% | 批量审批未实现 |
| 上下文压缩 | 智能摘要 | N/A | ✅ | N/A | 75% | LLM 增强摘要未使用 |
### 2.4 平台层
| 功能 | 设计目标 | SaaS | Tauri | Admin | 完成度 | 关键差距 |
|------|---------|------|-------|-------|--------|---------|
| 技能系统 | 69 SKILL.md | N/A | ✅ | N/A | 80% | WASM/Native 未实现 |
| 智能路由 | 语义匹配 | N/A | ❌ | N/A | 50% | SemanticSkillRouter 核心未实现 |
| Pipeline DSL | YAML 工作流 | N/A | ✅ | N/A | 90% | 无重大差距 |
| SaaS 平台 | 云端能力 | ✅ | ✅ | ✅ | 88% | SQL 注入+配置单向同步+遥测空转 |
---
## 三、五步审计结果
### 3.1 Step 1: 文档对齐
| 检查项 | 结果 |
|--------|------|
| SaaS API 路由 vs 文档 | ✅ 76+ 端点全部对齐 |
| Tauri 命令 vs 文档 | ✅ 150+ 命令已注册 |
| Admin 页面 vs 文档 | ✅ 12 页面全部存在 |
| 功能文档声称 vs 实际 | ⚠️ 部分功能声称高于实际 (智能路由 50% 声称 Phase 1 完成) |
**对齐率: ~95%**
### 3.2 Step 2: 数据流追踪
| # | 数据流 | 状态 | 断点 |
|---|--------|------|------|
| DF1 | 认证 (Desktop→SaaS) | ✅ 完整 | 无 |
| DF2 | 聊天 Relay (Desktop→SaaS→LLM) | ⚠️ 部分 | chatStore SaaS 模式走 WS 而非 HTTP relay |
| DF3 | 配置同步 (Desktop↔SaaS) | ❌ 单向 | Pull✅, Push/Diff❌ (定义但未调用) |
| DF4 | 设备管理 (Desktop→SaaS) | ✅ 完整 | 心跳不传 OS/version |
| DF5 | 遥测上报 (Desktop→SaaS) | ❌ 断裂 | recordLLMUsage/recordAuditEvent 零调用 |
**连通率: 60% (3/5 完整)**
### 3.3 Step 3: Dead Code 识别
#### Rust `#[allow(dead_code)]` — 28 处
| 分类 | 数量 | 说明 |
|------|------|------|
| Intelligence 模块 | 12 | heartbeat/reflection/identity/compactor 预留给未来 Tauri 命令 |
| Memory 模块 | 3 | persistent.rs 遗留迁移代码 |
| Runtime 驱动 | 4 | 反序列化字段未被访问 |
| Kernel/Pipeline | 4 | 预留功能 (export, intent, stage) |
| lib.rs | 2 | HealthStatus 枚举 + legacy 函数 |
| Growth | 2 | 缓存+存储预留 |
#### 未调用的 SaaS API 方法 — 35+ 个
**需要关注的桌面端方法 (应在 desktop 中使用但未使用)**:
- `healthCheck()` — 未被任何 health check 调用使用
- `listDevices()` — 设备列表未在桌面端展示
- `getRelayTask()` — 单个任务查询未使用
- `computeConfigDiff()` — ❌ 零调用,配置差异计算断裂
- `syncConfig()` — ❌ 零调用,配置推送断裂
**Admin 专用方法 (桌面端不使用是正常的)**:
- Provider/Model/Account/Role/Permission CRUD (~30 个)
- 这些方法在 admin/src/ 中通过独立的 api-client.ts 调用
#### Rust TODO/FIXME — 5 处
| 文件 | 行号 | 内容 |
|------|------|------|
| pipeline_commands.rs | 529 | `// TODO: use actual time` |
| pipeline_commands.rs | 869 | `// TODO: add pattern support` |
| kernel/src/registry.rs | 56 | `// TODO: Track this` |
| kernel/src/export/html.rs | 17 | `// TODO: Implement template-based HTML export` |
| pipeline/src/actions/orchestration.rs | 41 | `// TODO: implement graph storage` |
### 3.4 Step 4: 接口一致性
#### TS 类型差异 — 10+ 组
| 类型对 | 主要差异 |
|--------|---------|
| AccountPublic | admin: 联合类型 role/status; desktop: string |
| OperationLog vs OperationLogInfo | id 类型 string vs number; details 类型不同 |
| ConfigItem vs SaaSConfigItem | current_value 类型不同; desktop 多 created_at/updated_at |
| RelayTask vs RelayTaskInfo | status 联合类型 vs string; desktop 多 max_attempts/created_at |
| PromptTemplate vs PromptTemplateInfo | source/status 联合类型 vs string |
| Provider vs ProviderInfo | admin 有 api_key 字段; desktop 无 |
| Model vs ModelInfo | desktop 多 created_at/updated_at |
### 3.5 Step 5: 端到端验证
| 测试流程 | 结果 | 说明 |
|----------|------|------|
| 用户注册→登录→获取信息 | ✅ | 完整链路通畅 |
| 登录→设备注册→心跳 | ✅ | 降级逻辑正常 |
| 配置 Pull | ✅ | 仅拉取方向 |
| 配置 Push/Diff | ❌ | 方法未调用 |
| Relay chat→SSE | ✅ | llm-service.ts 路径完整 |
| Admin 登录→管理→CRUD | ✅ | 全部页面可操作 |
---
## 四、十项通用审计清单
| # | 审计点 | 结果 | 说明 |
|---|--------|------|------|
| 1 | 代码存在性 | ✅ 95% | 所有文档声明功能有对应代码 |
| 2 | 调用链连通 | ⚠️ 70% | 遥测/配置推送/OTA 链路断裂 |
| 3 | 配置传递 | ✅ 90% | saas-config.toml 端到端有效 |
| 4 | 降级策略 | ✅ 85% | 3 次失败→tauri 模式降级正常 |
| 5 | 错误处理 | ⚠️ 75% | Desktop 401 不自动 logout |
| 6 | 安全审计 | ❌ 60% | SQL 注入 + 权限缺失 |
| 7 | 日志记录 | ⚠️ 70% | migration/telemetry 模块缺 operation_logs |
| 8 | 测试覆盖 | ✅ 80% | SaaS 62 个集成测试, 但覆盖率不足 |
| 9 | 类型一致性 | ⚠️ 70% | 10+ 组类型定义不同步 |
| 10 | 前后端接口匹配 | ⚠️ 75% | 大部分匹配, 部分字段差异 |
---
## 五、五种差距模式
### 5.1 "写了没接" — 5 项确认
| # | 项目 | 位置 | 严重级别 |
|---|------|------|---------|
| G-01 | `recordLLMUsage` / `recordAuditEvent` 零外部调用 | telemetry-collector.ts | **P0** |
| G-02 | `startPromptOTASync` 从未调用 | llm-service.ts | **P1** |
| G-05 | `computeConfigDiff` / `syncConfig` push 未接入 | saas-client.ts | **P1** |
| G-10 | `hand_run_status` / `hand_run_list` 后端桩命令 | kernel_commands.rs | **P3** |
| — | `healthCheck()` 未被 health check 流程调用 | saas-client.ts | **P2** |
### 5.2 "接了没传" — 1 项确认
| # | 项目 | 位置 | 严重级别 |
|---|------|------|---------|
| G-04 | 心跳仅传 device_id, 不传 OS/version | saasStore.ts | **P1** |
### 5.3 "传了没存" — 2 项确认
| # | 项目 | 位置 | 严重级别 |
|---|------|------|---------|
| G-06 | telemetry 端点不写 operation_logs | telemetry/handlers.rs | **P2** |
| G-09 | 心跳不写 operation_logs | account/handlers.rs | **P2** |
### 5.4 "存了没用" — 2 项确认
| # | 项目 | 位置 | 严重级别 |
|---|------|------|---------|
| G-03 | `max_queue_size` / `max_concurrent` relay 未消费 | relay/service.rs | **P1** |
| G-07 | `account_api_keys` 被 relay 绕过 (用 provider_key_pool) | model_config/ | **P2** |
### 5.5 "双系统不同步" — 2 项确认
| # | 项目 | 说明 | 严重级别 |
|---|------|------|---------|
| G-08 | Desktop 401 不自动 logout, Admin 会 | 用户体验不一致 | **P2** |
| G-12 | 双端错误类型不统一 (SaaSApiError vs ApiRequestError) | 不可复用 | **P3** |
---
## 六、安全审计专项
### 6.1 CRITICAL: SQL 注入
**文件**: `crates/zclaw-saas/src/agent_template/service.rs`
全文件使用 `format!()` 直接拼接用户输入到 SQL, 依赖手工 `replace('\'', "''")` 转义。这是项目中**唯一未使用 `$N` 参数化查询**的 service 文件。
**受影响的操作**:
- `list_templates()` — WHERE 条件 (category, source, visibility, status)
- `update_template()` — SET 字段 (description, model, system_prompt, tools, capabilities, visibility, status) + WHERE id
**攻击向量示例**:
```sql
-- category 参数: `' OR 1=1 --` → 绕过 WHERE 条件
-- id 参数: `' OR '1'='1` → 更新所有记录
```
**修复方案**: 改用 `$N` 参数化查询, 参照 `account/service.rs``model_config/service.rs` 的实现模式。
### 6.2 HIGH: 部分模块使用 format! 构造 SQL (但有 $N 绑定)
**文件**: `prompt/service.rs`, `telemetry/service.rs`
这些文件在 WHERE 条件拼接时使用 `format!()`, 但值通过 `.replace('\'', "''")` 转义。虽然后续使用 `$N` 绑定值, 但 WHERE 条件本身的构造仍依赖手工转义。
### 6.3 HIGH: 配置同步缺少权限检查
`POST /api/v1/config/sync` (migration/handlers.rs) 端点未验证调用者是否有 admin 权限。任何已认证用户都可以推送配置。
### 6.4 MEDIUM: 配额限制未执行
`RelayConfig` 定义了 `max_queue_size` (默认 1000) 和 `max_concurrent_per_provider` (默认 5), 但 `execute_relay` 中未做队列容量和并发控制检查。
### 6.5 MEDIUM: Desktop 401 处理不完整
Desktop 端 `SaaSClient` 在 401 刷新失败后不自动 logout, 可能导致用户卡在过期会话中。Admin 端会自动跳转到登录页。
---
## 七、问题优先级与修复计划
### P0 — 立即修复 (阻塞功能)
| # | 问题 | 修复方案 | 影响范围 | 预估 |
|---|------|---------|---------|------|
| G-01 | 遥测系统全链路空转 | 在 llm-service.ts 的 chatCompletion 回调和 intelligence-hooks 中调用 recordLLMUsage / recordAuditEvent | telemetry-collector.ts, llm-service.ts, intelligence_hooks.rs | 2h |
| SEC-01 | SQL 注入 (agent_template) | 改用 `$N` 参数化查询 | agent_template/service.rs | 2h |
### P1 — 本周修复 (功能断裂)
| # | 问题 | 修复方案 | 影响范围 | 预估 |
|---|------|---------|---------|------|
| G-02 | Prompt OTA 未启动 | 在 saasStore.restoreSession/login 中调用 startPromptOTASync | llm-service.ts, saasStore.ts | 1h |
| G-03 | Relay 无并发限制 | 在 execute_relay 中加入队列容量和并发检查 | relay/service.rs | 2h |
| G-04 | 心跳不传 OS/version | 在 deviceHeartbeat 中携带 platform/app_version | saas-client.ts, account/handlers.rs | 1h |
| G-05 | 配置只能单向拉取 | 在 saasStore 中接入 computeConfigDiff 和 syncConfig push | saasStore.ts, saas-client.ts | 3h |
### P2 — 两周内修复 (质量提升)
| # | 问题 | 修复方案 | 影响范围 | 预估 |
|---|------|---------|---------|------|
| G-06 | Telemetry 端点缺审计日志 | 添加 log_operation 调用 | telemetry/handlers.rs | 1h |
| G-07 | account_api_keys 未被消费 | 明确用途: 要么让 relay 消费, 要么移除 | model_config/, relay/ | 4h |
| G-08 | Desktop 401 不自动 logout | 在 refresh 失败后调用 saasStore.logout() | saas-client.ts | 1h |
| SEC-02 | 配置同步缺权限检查 | 在 migration handler 中添加 admin 权限校验 | migration/handlers.rs | 1h |
### P3 — 长期优化 (技术债)
| # | 问题 | 修复方案 | 影响范围 | 预估 |
|---|------|---------|---------|------|
| G-10 | hand_run 桩命令 | 实现真实的运行状态追踪 | kernel_commands.rs | 3h |
| G-12 | 双端错误类型不统一 | 抽取共享错误类型到 @zclaw/types | admin+desktop | 4h |
| — | 28 处 dead_code | 评估后移除或保留 | desktop/src-tauri/ | 2h |
| — | 10+ 组类型定义差异 | 统一类型定义, 消除不一致 | admin+desktop types | 4h |
---
## 八、三端完成度评估
### SaaS 后端: **88%**
| 模块 | API 路由 | 完成度 | 主要问题 |
|------|---------|--------|---------|
| Auth | 8 | 95% | refresh 缺审计日志 |
| Account | 12 | 90% | dashboard 7 次串行查询 |
| Model Config | 14 | 90% | account_api_keys 未被消费 |
| Relay | 9 | 85% | 无并发限制, SSRF 需复核 |
| Migration | 9 | 70% | push 缺权限, 5 端点缺审计日志 |
| Role | 7 | 95% | 无重大问题 |
| Prompt OTA | 8 | 90% | 桌面端未启动 OTA |
| Agent Template | 5 | 75% | **SQL 注入** |
| Telemetry | 4 | 80% | 桌面端未调用上报函数 |
### Tauri 桌面端: **78%**
| 子系统 | 命令数 | 完成度 | 主要问题 |
|--------|-------|--------|---------|
| Kernel | 29 | 85% | hand_run 桩, scheduled_task 未实现 |
| Pipeline | 13 | 90% | 时间戳占位符 |
| Viking | 13 | 95% | 无重大问题 |
| LLM | 3 | 95% | 无重大问题 |
| Intelligence | 6 | 80% | 多个预留函数 |
| Browser | 23 | 85% | 需要 Fantoccini 运行时 |
| SaaS 集成 | 30+ 方法 | 65% | 35+ 方法未调用, 遥测断裂 |
### Admin 管理后台: **85%**
| 维度 | 完成度 | 主要问题 |
|------|--------|---------|
| 页面覆盖 | 95% | 12 个页面全覆盖 |
| API 调用 | 90% | 分页未连接 API |
| 认证 | 90% | token 刷新逻辑完善 |
| 类型定义 | 75% | 与桌面端不一致 |
---
## 九、关键决策建议
1. **遥测系统** — 必须在聊天回调和智能层 hook 中接入 recordLLMUsage, 否则 SaaS 端的遥测统计页面展示全零数据
2. **SQL 注入** — agent_template/service.rs 必须立即改为参数化查询, 这是生产安全红线
3. **配置同步** — 建议实现双向同步, 当前只能 SaaS→Desktop 单向拉取
4. **类型共享** — 考虑抽取 @zclaw/types 共享包, 消除 admin/desktop 类型不一致
5. **Prompt OTA** — 桌面端必须在登录后启动 OTA 同步, 否则 prompt 更新无法到达客户端
---
*审计报告结束*