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

247 lines
9.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.

# 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()`L506`inbox.lock()`L519后者在 `tokio::time::timeout` 内跨 `rx.recv().await` 持有L521-536。两个并发调用可互相阻塞。另有一条死信通道 `_response_tx/_response_rx`L490从未连接——sender 存入 pending_requests 但 receiver 无人读取。
**验证**: 修复后需添加并发 `send_to_agent()` 测试验证死锁消除。
**修复方案**: 用 `oneshot` channel 重构响应接收模式:
- 每次 `send_to_agent()` 创建 `oneshot::channel`
- sender 存入 `pending_requests`receiver 配合 `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.tsx`527 行安全关键组件)。
**修复**: 删除排除项运行 `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:21` `tracing::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`
```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 | KernelGrowth 隐式依赖显式化 | <30min |
| 23 | noUncheckedIndexedAccess 添加 | 2-4h |
| 24 | handStore/configStore duck-typingdiscriminator | <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)
5. tsconfig 修复#6
6. LlmConfig Debug 遮蔽#7
7. 关键 unwrap 修复#8
8. 静默吞错修复 关键集群#9
9. 缺失索引迁移#10
10. Config 验证#11
11. 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 配置验证