Files
zclaw_openfang/docs/superpowers/specs/2026-04-18-release-readiness-audit-design.md
iven fa5ab4e161
Some checks failed
CI / Lint & TypeCheck (push) Has been cancelled
CI / Unit Tests (push) Has been cancelled
CI / Build Frontend (push) Has been cancelled
CI / Rust Check (push) Has been cancelled
CI / Security Scan (push) Has been cancelled
CI / E2E Tests (push) Has been cancelled
refactor(middleware): 移除数据脱敏中间件及相关代码
移除不再使用的数据脱敏功能,包括:
1. 删除data_masking模块
2. 清理loop_runner中的unmask逻辑
3. 移除前端saas-relay-client.ts中的mask/unmask实现
4. 更新中间件层数从15层降为14层
5. 同步更新相关文档(CLAUDE.md、TRUTH.md、wiki等)

此次变更简化了系统架构,移除了不再需要的敏感数据处理逻辑。所有相关测试证据和截图已归档。
2026-04-22 19:19:07 +08:00

9.8 KiB
Raw Blame History

ZCLAW 发布前审计设计文档

日期: 2026-04-18 目标: 全维度审计系统问题,为首次用户发布做准备 方法: 4 专家组并行分析 + 交叉评审

背景

ZCLAW 已完成稳定化基线,进入发布准备阶段。在发布前组织了一次多维度深度审计,通过 4 个专家代理(后端稳定性、前端质量、安全与数据、工程卫生)并行分析,发现并验证了 24 个问题点。经交叉评审后纠正了 4 项原始审计误判。

审计纠正(原始误判)

原始声称 实际情况
Cargo.lock 缺失 已提交并跟踪,git ls-files Cargo.lock 确认
无 CI/CD .github/workflows/ci.yml + release.yml 完整存在
src-tauri LOC 偏差 3x 实际 61,257 行,与 TRUTH.md ~61,400 基本一致
Token INTEGER 溢出 每行存单次请求 token 不溢出SUM() 已返回 BIGINT

第一层:发布阻塞项(必须修复)

1. Director 死锁风险 — P0 CRITICAL

文件: crates/zclaw-kernel/src/director.rs:506-536

问题: send_to_agent() 顺序获取 pending_requests.lock()L506inbox.lock()L519后者在 tokio::time::timeout 内跨 rx.recv().await 持有L521-536。两个并发调用可互相阻塞。另有一条死信通道 _response_tx/_response_rxL490从未连接——sender 存入 pending_requests 但 receiver 无人读取。

验证: 修复后需添加并发 send_to_agent() 测试验证死锁消除。

修复方案: 用 oneshot channel 重构响应接收模式:

  • 每次 send_to_agent() 创建 oneshot::channel
  • sender 存入 pending_requestsreceiver 配合 tokio::time::timeout 等待
  • 新增独立的 inbox 消费任务分发响应到对应 oneshot sender
  • 变更 pending_requests 类型为 HashMap<String, oneshot::Sender<A2aEnvelope>>

工时: 2-4h重构 + 测试更新)

2. Pipeline Executor 内存泄漏 — P0 HIGH

文件: crates/zclaw-pipeline/src/executor.rs

问题: runs: RwLock<HashMap<String, PipelineRun>>cancellations: RwLock<HashMap<String, bool>> 无限增长,无清理路径。

修复方案:

  • 添加 cleanup(max_age: Duration) 方法,清除已完成/失败/取消的旧记录
  • execute_with_id() 完成后自动调用清理
  • 设置 max_completed_runs 上限(如 100超限淘汰最旧记录

工时: <1h

3. Pipeline 步骤超时缺失 + Delay 无上限 — P0 HIGH

文件: crates/zclaw-pipeline/src/executor.rs

问题: ExecuteError::Timeout 已定义但从未触发。每步执行无超时包装。Action::Delay { ms } 接受原始 u64恶意 YAML 可设 ms: u64::MAX

修复方案:

  • tokio::time::timeout 包装每步 execute_action 调用
  • 使用 PipelineSpec.timeout_secs已存在但未使用cap 在 5 分钟
  • Delay ms 上限 60000超出时 warn 并截断
  • parser.rs/parser_v2.rs 添加 YAML 解析时验证

工时: 1-2h

4. TRUTH.md Hands 数量偏差 — P0 (文档完整性)

文件: docs/TRUTH.md, CLAUDE.md

问题: 声称 9 个 Hand 启用,实际 kernel 注册 7 个:

  • 6 个通过 hands/*.HAND.toml 扫描注册Browser/Clip/Collector/Quiz/Researcher/Twitter
  • 1 个通过 kernel/mod.rs:96 编程注册ReminderHand_ 前缀豁免 HAND.toml 扫描,见 trigger_manager.rs:139
  • Whiteboard/Slideshow/Speech 的 HAND.toml 仅存在于 .claude/worktrees/ 开发分支,无 impl Hand for,未合并到主分支

修复方案:

  • TRUTH.md: 更新为 "6 HAND.toml + Reminder 系统内部 = 7 注册"
  • CLAUDE.md §6: 明确标注 Whiteboard/Slideshow/Speech 为"开发中,未合并"
  • 确认桌面 UI 是否展示 9 个 Hand如有则同步更新

工时: <1h

5. rate_limit_events 清理 Worker 是空壳 — P0 (数据膨胀)

文件: crates/zclaw-saas/src/workers/cleanup_rate_limit.rs

问题: Worker body 是 no-op注释说"rate limit entries are in-memory"),但 main.rs 的 batch flush 确实将限流条目写入数据库。注意:内存中的 DashMap 清理每 300 秒运行一次(state.rs:118),但数据库持久化条目无限增长,无任何删除机制。

修复方案: 实现 Worker body执行 DELETE FROM rate_limit_events WHERE created_at < NOW() - INTERVAL '1 hour'。确认调度器已注册此 Workermain.rs:47 已注册)。

工时: <1h


第二层:强烈建议修复

6. TypeScript 编译排除安全关键文件

文件: desktop/tsconfig.json

问题: 排除了 ErrorAlert.tsx(文件已不存在,残留排除项)和 ErrorBoundary.tsx527 行安全关键组件)。

修复: 删除排除项,运行 tsc --noEmit 验证 ErrorBoundary 无类型错误。

工时: <1h

7. LlmConfig api_key Debug 泄露

文件: crates/zclaw-kernel/src/config.rs

问题: #[derive(Debug)] 会在 format!("{:?}", config) 中打印 api_key 明文。虽然当前无代码 Debug-print 此结构,但日志调试时容易触发。

修复: 移除 Debug derive实现自定义 Debug impl 用 "***REDACTED***" 遮蔽 api_key。

工时: <30min

8. 关键 .unwrap() 调用

文件:

  • crates/zclaw-saas/src/billing/handlers.rs:598 — Response builder unwrap
  • desktop/src-tauri/src/classroom_commands/mod.rs:58 — db_path.parent().unwrap()

修复: 替换为 map_err + ? 传播。

工时: <1h

9. 静默吞错关键集群

文件与修复:

  • crates/zclaw-kernel/src/kernel/approvals.rs:88,93,124 — 已有 tracing::warn! 日志但级别应为 error(审批状态丢失是严重事件)
  • crates/zclaw-protocols/src/mcp_transport.rs:429 → 记录僵尸进程风险
  • crates/zclaw-kernel/src/events.rs:21tracing::debug!("Event dropped: {:?}", e)
  • crates/zclaw-runtime/src/tool/builtin/task.rs → 日志记录 subtask 事件丢失
  • crates/zclaw-growth/src/storage/sqlite.rs 迁移 → 匹配 sqlx::Error::Database 检查 SQLite 错误码 1 子错误 "duplicate column name",区分幂等迁移与真实错误

工时: 2-4h

10. 缺失数据库索引

新文件: crates/zclaw-saas/migrations/20260418000001_add_missing_indexes.sql

CREATE INDEX IF NOT EXISTS idx_rle_created_at ON rate_limit_events(created_at);
CREATE INDEX IF NOT EXISTS idx_billing_sub_plan ON billing_subscriptions(plan_id);
CREATE INDEX IF NOT EXISTS idx_ki_created_by ON knowledge_items(created_by);

工时: <1h

11. 配置验证缺失

文件: crates/zclaw-saas/src/config.rs

修复: 在 SaaSConfig::load() 添加:

  • jwt_expiration_hours >= 1
  • max_connections > 0
  • 改善默认 DB URL 连接失败的错误信息

工时: <1h

12. MCP Transport 响应错配

文件: crates/zclaw-protocols/src/mcp_transport.rs

问题: stdin/stdout 分离的 Mutex 可导致并发请求收到错误响应。

修复: 合并 stdin + stdout 为单一 Mutex在 write-then-read 周期内持有锁。

工时: 3-4h


第三层:可延后至首个补丁

# 问题 工时
13 console.log 清理105处→createLogger 2-3h
14 ChatStore 双源真相重构 2-4h
15 33处内联样式→Tailwind <1h
16 SaaS mixin prototype: any 类型约束 <1h
17 serde_yaml 统一到 serde_yaml_bw 1-2h
18 32处 dead_code 审查清理 2-4h
19 webhook 废弃表删除迁移 <30min
20 A2A feature gate 或移除 feature 定义 <30min
21 dependency 内联声明→workspace 引用 1-2h
22 Kernel→Growth 隐式依赖显式化 <30min
23 noUncheckedIndexedAccess 添加 2-4h
24 handStore/configStore duck-typing→discriminator <1h

TRUTH.md 数值校准清单

指标 当前值 应更正为 验证命令
#[test] (crates) 433 425 grep -rn '^\s*#\[test\]\s*$' crates/ --include="*.rs" | wc -l
#[tokio::test] (crates) 368 309 grep -rn '^\s*#\[tokio::test\]' crates/ --include="*.rs" | wc -l
Zustand Store 21 26 (含子目录) find desktop/src/store/ -name "*.ts" | wc -l
Admin V2 页面 15 17 ls admin-v2/src/pages/*.tsx | wc -l
Pipeline YAML 17 18 find pipelines/ -name "*.yaml" | wc -l
Hands 启用 9 7 (6 HAND.toml + Reminder) ls hands/*.HAND.toml | wc -l + kernel registry

实施计划

Batch 1: 发布阻塞修复 (Day 1, 上午 + 下午)

按依赖顺序执行(总工时 ~6-9h建议分上下午

  1. Pipeline 超时 + 内存泄漏 + Delay 上限(#2, #3— 上午
  2. Director 死锁修复(#1— 上午,可并行
  3. rate_limit_events Worker 实现(#5— 下午
  4. TRUTH.md + CLAUDE.md 数值校准(#4— 下午

验证: cargo test --workspace --exclude zclaw-saas + tsc --noEmit

Batch 2: 强烈建议修复 (Day 2)

  1. tsconfig 修复(#6
  2. LlmConfig Debug 遮蔽(#7
  3. 关键 unwrap 修复(#8
  4. 静默吞错修复 — 关键集群(#9
  5. 缺失索引迁移(#10
  6. Config 验证(#11
  7. MCP Transport 锁合并(#12

验证: cargo test --workspace --exclude zclaw-saas + pnpm tsc --noEmit + pnpm vitest run

Batch 3: 补丁迭代 (Day 3+)

按优先级从高到低处理第三层 12 项。


关键文件列表

  • crates/zclaw-kernel/src/director.rs — P0 Director 死锁
  • crates/zclaw-pipeline/src/executor.rs — P0 Pipeline 内存泄漏 + 超时
  • crates/zclaw-saas/src/workers/cleanup_rate_limit.rs — P0 Worker 空壳
  • docs/TRUTH.md — P0 文档校准
  • desktop/tsconfig.json — P1 类型排除
  • crates/zclaw-kernel/src/config.rs — P1 Debug 泄露
  • crates/zclaw-saas/src/billing/handlers.rs — P1 unwrap
  • desktop/src-tauri/src/classroom_commands/mod.rs — P1 unwrap
  • crates/zclaw-protocols/src/mcp_transport.rs — P1 响应错配
  • crates/zclaw-saas/src/config.rs — P1 配置验证