# ZCLAW SaaS + Tauri 系统性功能审计报告 V10 > 审计日期: 2026-03-31 > 审计范围: SaaS 后端 (68 路由/22 表) + Tauri 桌面端 (107 命令/13 Store) + admin-v2 管理后台 (14 服务/11 页面) > 审计方法: 静态代码分析 + 数据流追踪 + 交叉索引 > 修复状态: P0 已修复, P1 已处理, P2 已处理 --- ## 1. 执行摘要 ### 1.1 整体完成度 | 层级 | 总数 | 活跃 | 未使用 | 利用率 | |------|------|------|--------|-------| | SaaS 路由 | 92 | 84 | 8 | **91.3%** | | Tauri 命令 | 107 | 79 | 28 | **73.8%** | | Zustand Store | 13 | 13 | 0 | **100%** | | admin-v2 服务 | 14 | 14 | 0 | **100%** | ### 1.2 问题统计 | 严重级别 | 数量 | 描述 | |---------|------|------| | **P0 (阻塞)** | 1 | trigger_update 参数不匹配导致所有 Trigger 更新失效 | | **P1 (严重)** | 3 | sessionStore 无 Kernel 适配器、定时任务执行器为 stub、配置同步未传播到 kernel | | **P2 (高)** | 5 | 8 个孤立路由、2 个写而不读 DB 表、Workflow→Pipeline 元数据丢失、Role 管理无 admin 页面、8+ 个 saas-admin 方法无消费者 | | **P3 (中)** | 6 | CleanupRateLimitWorker stub、CacheKey 死代码、pipeline-client 缺少 probe 检测、GET 请求无速率限制、SSRF DNS 失败不阻断、connectionStore 客户端切换未重新注入 | | **P4 (低)** | 4 | 7 个 @deprecated TS 标记、a2a feature-gated 代码、ScheduledTaskRow 部分字段、director.rs 休眠代码 | --- ## 2. 功能交叉索引 ### 2.1 SaaS 路由 ↔ 前端消费者映射 #### 路由状态分布 | 状态 | 数量 | 说明 | |------|------|------| | CONNECTED (两端消费) | 27 | SaaS 路由同时被 desktop 和 admin-v2 调用 | | DESKTOP_ONLY | 31 | 仅桌面端消费(含 auth、role、device 等) | | ADMIN_ONLY | 16 | 仅 admin-v2 消费(含 key 管理、prompt 写操作等) | | ORPHANED | 8 | 无前端消费者 | | INTERNAL | 1 | health 端点 | #### 8 个孤立路由(无前端消费者) | 路由 | 模块 | 建议 | |------|------|------| | `GET /api/v1/providers/:id/models` | model_config | 可通过 `GET /api/v1/models?provider_id=X` 替代,考虑移除 | | `GET /api/v1/config/items/:id` | migration | 无单条配置查询需求,考虑移除 | | `DELETE /api/v1/config/items/:id` | migration | 无删除配置 UI,考虑移除或添加到 admin-v2 | | `GET /api/v1/config/analysis` | migration | 配置分析功能未接入,添加到 admin-v2 或移除 | | `POST /api/v1/config/seed` | migration | 配置种子引导未接入,内部工具保留 | | `GET /api/v1/config/sync-logs` | migration | 同步日志查询无 UI,添加到 admin-v2 Config 页面 | | `GET /api/v1/roles/:id/permissions` | role | 角色权限查询无消费者,整合到角色管理 UI | | `GET /api/scheduler/tasks/:id` | scheduled_task | 单条任务查询无消费者 | #### 按模块路由覆盖度 | 模块 | 路由数 | Connected | Desktop Only | Admin Only | Orphaned | |------|-------|-----------|-------------|------------|----------| | auth | 9 | 3 | 5 | 1 | 0 | | account | 12 | 5 | 6 | 0 | 0 | | model_config | 14 | 9 | 3 | 0 | 1 | | relay | 9 | 2 | 3 | 4 | 0 | | migration | 11 | 1 | 5 | 0 | 4 | | role | 11 | 0 | 10 | 0 | 1 | | prompt | 10 | 3 | 1 | 5 | 0 | | agent_template | 7 | 1 | 1 | 4 | 0 | | scheduled_task | 5 | 0 | 4 | 0 | 1 | | telemetry | 4 | 0 | 2 | 2 | 0 | | health | 1 | - | - | - | 1 (internal) | ### 2.2 Tauri 命令 ↔ 前端调用映射 #### 28 个未使用命令 | 分类 | 命令 | 原因 | |------|------|------| | **遗留 Gateway (11)** | zclaw_status/start/stop/restart/local_auth/prepare_for_tauri/approve_device_pairing/doctor/process_list/process_logs/version + zclaw_health_check + zclaw_ping | Gateway 已被 Kernel 替代,全部遗留代码 | | **LLM 内部 (3)** | llm_complete, embedding_create, embedding_providers | 后端内部使用,非前端直接调用 | | **Agent 导出导入 (2)** | agent_export, agent_import | 后端已实现,前端 UI 未接入 | | **Kernel 管理 (1)** | kernel_shutdown | 无关闭路径 | | **Hand (1)** | hand_run_cancel | 取消单次运行未接入 UI | | **定时任务 (2)** | scheduled_task_create, scheduled_task_list | 整个模块未使用 | | **Pipeline (1)** | pipeline_templates | 模板列表未接入 | | **Viking (2)** | viking_add_with_metadata, viking_store_with_summaries | 高级存储功能未接入 | | **Memory (2)** | memory_configure_embedding, memory_is_embedding_configured | 已有 viking 命令替代 | | **Context (1)** | estimate_content_tokens | 已有 compactor 命令替代 | --- ## 3. 核心数据流追踪 ### 3.1 聊天流 + 记忆提取 (BREAK-02 验证) **结论: PARTIALLY WORKING — 前端正常,后端缺失** | 层级 | 记忆提取 | 状态 | |------|---------|------| | 前端 (chatStore.ts:509) | `onComplete` 回调调用 `getMemoryExtractor().extractFromConversation()` | **WORKING** | | Rust (intelligence_hooks.rs:50-108) | 仅调用 `reflect()`,不调用 `extract_and_store_memories()` | **NO extraction** | | Rust Tauri 命令 (lib.rs:204-205) | 仅注册为手动命令 | **Manual only** | **影响**: 桌面用户通过前端回调正常工作。但任何绕过前端直接调用 Tauri 命令的路径(如 headless/gateway relay)将缺失记忆提取。 **建议**: 在 `post_conversation_hook` 中添加可选的 `extract_and_store_memories` 调用,或在文档中明确说明设计意图。 ### 3.2 Hand 触发 + 审批 (BREAK-03 验证) **结论: CONFIRMED WORKING** kernel.rs:1118-1193 的 `respond_to_approval` 实现: - 状态更新为 "approved" - `tokio::spawn` 创建后台任务 - 调用 `hands.execute(&hand_id, &context, input).await` 执行 Hand - 更新 HandRun 结果和 approval 状态为 "completed"/"failed" BREAK-03 **不是问题**,审批后自动执行机制完整。 ### 3.3 Agent CRUD 一致性 **结论: INTENTIONAL GAP — 设计意图** | 路径 | Create | Read | Update | Delete | Export/Import | |------|--------|------|--------|--------|--------------| | Kernel (Tauri) | ✅ | ✅ | ✅ | ✅ | ✅ | | Gateway (REST) | ✅ | ✅ | ✅ | ✅ | ❌ | | SaaS | 仅 template | 仅 template | 仅 template | 仅 template | ❌ | SaaS 仅存储 agent 模板(蓝图),运行时 Agent 是本地状态,由 Kernel/Gateway 管理。这是正确的架构决策。 ### 3.4 配置同步流 **结论: PARTIALLY WORKING** | 方向 | 路径 | 状态 | |------|------|------| | SaaS → localStorage | `pullConfig()` → `localStorage.setItem()` | ✅ WORKING | | localStorage → SaaS | `syncConfig()` + dirty tracking | ✅ WORKING | | localStorage → Kernel | 无传播机制 | ❌ **GAP** | **影响**: SaaS 同步的配置仅影响前端 UI 设置(如主题),不会传播到运行中的 Rust kernel。kernel 从磁盘 TOML 读取配置,与 localStorage 无关。 --- ## 4. 差距模式分析 ### 4.1 "写了没接" — 代码存在但未接入 | ID | 项目 | 文件 | 严重性 | |----|------|------|--------| | WNC-01 | CleanupRateLimitWorker (空 stub) | `crates/zclaw-saas/src/workers/cleanup_rate_limit.rs` | P3 | | WNC-02 | 定时任务执行器 (仅状态管理,无实际执行) | `crates/zclaw-saas/src/scheduler.rs:134-192` | P1 | | WNC-03 | Role 管理 (无 admin-v2 页面) | `admin-v2/src/` 无 roles 服务/页面 | P2 | | WNC-04 | Agent export/import (前端未接入) | `desktop/src-tauri/src/kernel_commands/agent.rs:213-235` | P4 | | WNC-05 | pipeline_templates 命令 (无调用) | `desktop/src-tauri/src/pipeline_commands/presentation.rs` | P4 | ### 4.2 "接了没传" — 接口不匹配 | ID | 项目 | 文件 | 严重性 | 详情 | |----|------|------|--------|------| | **MSH-01** | **trigger_update 参数不匹配** | `trigger.rs:183` vs `kernel-triggers.ts:92` | **P0** | **前端发 `{id, updates: {name, enabled, handId}}` 嵌套结构,Rust 期望 `{id, name, enabled, hand_id}` 扁平参数。所有 trigger 更新实际为 no-op** | | MSH-02 | Workflow→Pipeline 元数据丢失 | `workflowStore.ts:379-502` | P2 | 丢失 category/industry/tags/icon/version/author 等字段 | ### 4.3 "传了没存" — 数据接收但未持久化 | ID | 项目 | 文件 | 严重性 | |----|------|------|--------| | PTS-01 | 定时任务执行结果 | `scheduler.rs:134-192` | P1 | ### 4.4 "存了没用" — 写入但无读路径 | ID | 表 | 写入位置 | 读路径 | 严重性 | |----|-----|---------|--------|--------| | SUN-01 | `prompt_sync_status` | `prompt/service.rs:272` | **无** | P2 | | SUN-02 | `config_sync_log` | `migration/service.rs:425` | 有 handler 但 handler 本身孤立 | P2 | ### 4.5 "双系统不同步" — SaaS vs Tauri 功能差异 | 领域 | Gateway | Kernel | SaaS | 差距性质 | |------|---------|--------|------|---------| | Agent CRUD | REST | invoke | 仅 template | **INTENTIONAL** | | Session | REST | ❌ 无命令 | ❌ 无路由 | sessionStore 无 Kernel 适配器 | | Trigger | REST | invoke | ❌ 无路由 | 仅本地,不同步 | | Browser | ❌ | invoke | ❌ 无路由 | Tauri-only 特性 | | Pipeline | ❌ | invoke | ❌ 无路由 | Tauri-only 特性 | | Role 管理 | ❌ | ❌ | REST | 仅 desktop 消费,无 admin UI | --- ## 5. 安全审计 ### 5.1 安全控制验证(全部 PASS) | 控制项 | 状态 | 证据 | |--------|------|------| | JWT secret 管理 | ✅ | debug 模式 fallback,release 模式强制要求环境变量 (`config.rs:236-248`) | | SSRF 防护 | ✅ | 多层验证:主机名黑名单、DNS 解析检查、私有 IP 段、混淆防护 (`relay/service.rs:452-565`) | | 速率限制 | ✅ | 公开端点分级限流 (login 5/min, register 3/hour)、认证端点 RPM 限制 (`middleware.rs:56-162`) | | Relay 认证 | ✅ | `relay:use` 权限检查 (`relay/handlers.rs:24`)、key pool 隔离 | | 请求体大小限制 | ✅ | MAX_BODY_BYTES = 1MB (`relay/handlers.rs:47-50`) | | IP 提取安全 | ✅ | 不信任 X-Forwarded-For,仅从 TCP 层获取 (`middleware.rs:133-138`) | ### 5.2 安全注意事项 | 项 | 严重性 | 说明 | |----|--------|------| | GET 请求无速率限制 | P3 | GET 免于限流 (middleware.rs:62),可被利用但 GET 无副作用 | | SSRF DNS 失败不阻断 | P3 | DNS 解析失败时不阻断请求 (service.rs:530-533),存在窄 TOCTOU 窗口 | | sessionStore 类型不安全转换 | P3 | `setSessionStoreClient` 无条件 cast 为 GatewayClient (sessionStore.ts:225-228) | --- ## 6. Store 适配器一致性 | Store | Gateway 适配器 | Kernel 适配器 | SaaS 适配器 | 问题 | |-------|---------------|-------------|------------|------| | connectionStore | ✅ | ✅ | ✅ | P3: 客户端切换后未重新注入其他 store | | chatStore | ✅ (via conn) | ✅ (via conn) | ✅ (relay) | 无 | | agentStore | ✅ | ✅ | ❌ | 无 | | handStore | ✅ | ✅ | ❌ | P3: fallback 为 stub client | | workflowStore | ✅ | ✅ | ❌ | P2: Pipeline→Workflow 元数据丢失 | | configStore | ✅ | ✅ | ✅ | 无 | | securityStore | ✅ | ✅ | ❌ | 无 | | **sessionStore** | ✅ | **❌** | ❌ | **P1: 无 Kernel 适配器,Tauri 模式下 session 失效** | | saasStore | ❌ | ❌ | ✅ | 无 (SaaS 专用) | | memoryGraphStore | ❌ | ✅ (invoke) | ❌ | 无 | | browserHandStore | ❌ | ✅ (invoke) | ❌ | P3: Tauri-only 特性 | | offlineStore | ✅ (via conn) | ✅ (via conn) | ❌ | 无 | | workflowBuilderStore | ❌ | ❌ | ❌ | 纯本地存储 | --- ## 7. 死代码审计 ### 7.1 已验证的假阳性(AUDIT_TRACKER V9 纠正) | ID | 项目 | 实际状态 | |----|------|---------| | DEAD-01 | PromptInjector | **活跃** — 在 zclaw-runtime/growth.rs 和 viking_commands.rs 中使用 | | DEAD-02 | MemoryRetriever | **活跃** — 在 zclaw-runtime/growth.rs 和 create_growth_system() 中使用 | | DEAD-03 | GrowthTracker | **活跃** — 在 zclaw-runtime/growth.rs 和 create_growth_system() 中使用 | | DEAD-04 | director.rs (897 行) | **Feature-gated** — multi-agent 特性,默认不编译 | | DEAD-05 | saas-admin.ts Role 方法 | **确认死代码** — 8+ 个方法无前端消费者 | ### 7.2 真正的死代码 | 项目 | 文件 | 说明 | |------|------|------| | 11 个 Gateway 命令 | `desktop/src-tauri/src/gateway/commands.rs` | Gateway 已被 Kernel 替代 | | 8+ Role/Permission 方法 | `desktop/src/lib/saas-admin.ts:183-220` | 完整实现但无调用者 | | CacheKey 结构体 | `crates/zclaw-growth/src/retrieval/cache.rs:22` | 整个结构体从未使用 | | CleanupRateLimitWorker | `crates/zclaw-saas/src/workers/cleanup_rate_limit.rs` | 空 stub | --- ## 8. 优先修复清单 ### P0 — 阻塞(已修复 ✅) | ID | 问题 | 文件 | 修复方案 | 状态 | |----|------|------|---------|------| | MSH-01 | trigger_update 参数不匹配 | `trigger.rs:183` / `kernel-triggers.ts:92` | Rust 端改为接受 `{ id, updates: {...} }` 结构体,匹配前端格式 | ✅ 已修复 | ### P1 — 严重(已处理 ✅) | ID | 问题 | 文件 | 修复方案 | 状态 | |----|------|------|---------|------| | WNC-02 | 定时任务执行器为 stub | `scheduler.rs:134-192` | 添加 TODO(STUB) 标注 + 运行时 warn 日志 | ✅ 已标注 | | GAP-01 | sessionStore 无 Kernel 适配器 | `sessionStore.ts:225-228` | 添加类型检测,KernelClient 使用 stub 适配器 | ✅ 已修复 | | GAP-02 | 配置同步未传播到 kernel | `saasStore.ts:528-531` | 评估为设计意图:SaaS 配置为 UI-only,`llm_routing` 通过 account data 已传播 | ✅ 确认设计意图 | ### P2 — 高(下个迭代) | ID | 问题 | 修复方案 | |----|------|---------| | ORPHAN | 8 个孤立路由 | 评估移除或添加 admin-v2 UI | | SUN-01 | prompt_sync_status 写而不读 | 添加 admin 读路径或移除表 | | SUN-02 | config_sync_log 写而不读 | 添加 admin-v2 Config 页面 tab | | MSH-02 | Pipeline→Workflow 元数据丢失 | 扩展 Workflow 类型或标注忽略字段 | | ADMIN-01 | Role 管理无 admin 页面 | 添加 admin-v2 角色管理页面 | | DEAD-05 | 8+ saas-admin 方法无消费者 | 接入 UI 或移除 | ### P3 — 中(后续迭代) | ID | 问题 | 修复方案 | |----|------|---------| | STUB-01 | CleanupRateLimitWorker 空实现 | 移除或实现 | | DEAD-06 | CacheKey 死结构体 | 移除 | | GAP-03 | pipeline-client 缺少 probe 检测 | 复用 kernel-client 的 probeTauriAvailability | | GAP-04 | connectionStore 切换后未重新注入 store | 在 connect() 后重新调用 initializeStores() | | SEC-01 | GET 请求无速率限制 | 监控 GET 量,必要时添加 | | SEC-02 | SSRF DNS 失败不阻断 | 考虑 DNS 失败时阻断请求 | ### P4 — 低(维护时处理) | ID | 问题 | |----|------| | CLEANUP-01 | 11 个遗留 Gateway 命令移除 | | CLEANUP-02 | 7 个 @deprecated TS 标记清理 | | CLEANUP-03 | 4 个 CANDIDATE 级 dead_code 评估 | | FEATURE-01 | Agent export/import 前端接入 | | FEATURE-02 | multi-agent (director.rs) 激活准备 | --- ## 9. 验证命令 ```bash # 编译验证 cargo build -p zclaw-saas # TypeScript 类型检查 cd desktop && pnpm tsc --noEmit # admin-v2 类型检查 cd admin-v2 && pnpm tsc --noEmit # Rust 测试 cargo test -p zclaw-saas # 搜索 trigger_update 不匹配 (P0 验证) grep -n "trigger_update" desktop/src-tauri/src/kernel_commands/trigger.rs desktop/src/lib/kernel-triggers.ts # 搜索孤立路由 (P2 验证) grep -rn "config/analysis\|config/seed\|config/sync-logs" desktop/src/ admin-v2/src/ # 搜索写而不读表 (P2 验证) grep -rn "prompt_sync_status" crates/zclaw-saas/src/ --include="*.rs" ``` --- ## 10. 审计方法总结 本次审计使用了以下技术: 1. **交叉索引** — 92 条 SaaS 路由 × 107 个 Tauri 命令 × 14 个 admin 服务 全量匹配 2. **数据流追踪** — 4 条核心业务流端到端追踪(聊天、Agent CRUD、Hand 审批、配置同步) 3. **差距模式扫描** — 5 种已知差距模式逐一验证 4. **安全面审计** — JWT/SSRF/rate-limit/auth 中间件逐项检查 5. **死代码检测** — `#[allow(dead_code)]` + `#[deprecated]` + 无引用代码全量扫描 6. **接口一致性** — Tauri 命令签名 vs 前端 invoke 参数逐个比对 总审计代码量:~150,000 行 Rust + ~45,000 行 TypeScript + ~8,000 行 SQL