Files
zclaw_openfang/plans/shimmying-singing-sloth.md
iven f4efc823e2 refactor(types): comprehensive TypeScript type system improvements
Major type system refactoring and error fixes across the codebase:

**Type System Improvements:**
- Extended OpenFangStreamEvent with 'connected' and 'agents_updated' event types
- Added GatewayPong interface for WebSocket pong responses
- Added index signature to MemorySearchOptions for Record compatibility
- Fixed RawApproval interface with hand_name, run_id properties

**Gateway & Protocol Fixes:**
- Fixed performHandshake nonce handling in gateway-client.ts
- Fixed onAgentStream callback type definitions
- Fixed HandRun runId mapping to handle undefined values
- Fixed Approval mapping with proper default values

**Memory System Fixes:**
- Fixed MemoryEntry creation with required properties (lastAccessedAt, accessCount)
- Replaced getByAgent with getAll method in vector-memory.ts
- Fixed MemorySearchOptions type compatibility

**Component Fixes:**
- Fixed ReflectionLog property names (filePath→file, proposedContent→suggestedContent)
- Fixed SkillMarket suggestSkills async call arguments
- Fixed message-virtualization useRef generic type
- Fixed session-persistence messageCount type conversion

**Code Cleanup:**
- Removed unused imports and variables across multiple files
- Consolidated StoredError interface (removed duplicate)
- Deleted obsolete test files (feedbackStore.test.ts, memory-index.test.ts)

**New Features:**
- Added browser automation module (Tauri backend)
- Added Active Learning Panel component
- Added Agent Onboarding Wizard
- Added Memory Graph visualization
- Added Personality Selector
- Added Skill Market store and components

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-17 08:05:07 +08:00

12 KiB
Raw Permalink Blame History

ZCLAW 代码质量与安全全面检查计划

类型: 代码审查 / 安全审计 优先级: P0 (阻塞发布) 预计工时: 25 人天 创建日期: 2026-03-16

一、背景与目标

1.1 问题背景

ZCLAW 项目在进行代码审查时发现多个安全漏洞和代码质量问题,需要系统性修复以确保:

  1. 安全性: 敏感数据存储、通信加密、输入验证
  2. 代码质量: 文件大小、类型安全、错误处理
  3. 测试覆盖: 当前约 40-50%,目标 80%

1.2 预期成果

  • 所有关键安全漏洞修复
  • 代码文件符合 800 行限制
  • TypeScript 严格模式通过
  • 测试覆盖率达到 80%

二、发现的问题摘要

2.1 安全问题 (按严重性)

严重性 问题 文件位置
HIGH Ed25519 私钥 localStorage 明文存储 secure-storage.ts:270-278
MEDIUM 正则表达式 ReDoS 风险 CreateTriggerModal.tsx:149
MEDIUM API 错误详情泄露敏感信息 llm-service.ts:189-192
MEDIUM 堆栈跟踪存储在错误对象中 error-types.ts:356-358
MEDIUM 默认使用 ws:// 非加密协议 gateway-client.ts:51
LOW Token 部分字符记录到控制台 connectionStore.ts:249

2.2 代码质量问题

优先级 问题 影响范围
P0 2 个超大文件 (>800行) gateway-client.ts (~1850行), gatewayStore.ts (~1670行)
P0 32 处 any 类型 主要在 gateway-client.ts
P0 21 处静默错误吞噬 多个文件
P0 测试覆盖率不足 估计 40-50%
P1 30+ 未类型化 catch 多个文件
P1 缺少 UI 组件测试 *.tsx 文件
P1 错误提取逻辑重复 30+ 处相同模式
P2 130+ console.log 需要结构化日志

2.3 架构问题

  • gatewayStore.ts 未完全拆分
  • 类型定义分散在多个 store 文件
  • tsconfig.json 排除 7 个有类型错误的文件
  • uuid 包使用但未声明依赖

三、实施计划

Phase 1: P0 关键修复 (预计 12.5 天)

1.1 安全存储加密 [2天]

文件: desktop/src/lib/secure-storage.ts

修改内容:

// 当 keyring 不可用时,加密私钥后再存储
function encryptPrivateKey(key: string, passphrase: string): string {
  // 使用 PBKDF2 派生密钥 + AES-GCM 加密
}

// 添加安全状态组件显示警告
export function SecurityStatusBanner(): JSX.Element {
  // 当使用 localStorage 回退时显示警告
}

验证:

  • 单元测试: 验证加密后再存储
  • 手动测试: 禁用 keyring验证 localStorage 中数据已加密

1.2 拆分 gateway-client.ts [3天]

当前: 1 个 1850 行文件

目标结构:

lib/gateway/
├── client.ts          (~300 行 - 核心 GatewayClient 类)
├── websocket.ts       (~200 行 - WebSocket 处理)
├── rest-api.ts        (~400 行 - REST API 方法)
├── auth.ts            (~150 行 - 认证逻辑)
├── types.ts           (~100 行 - 类型定义)
└── config.ts          (~50 行 - 配置常量)

验证:

  • pnpm tsc --noEmit 通过
  • 所有现有测试通过
  • 每个文件 <400 行

1.3 拆分 gatewayStore.ts [4天]

当前: 1 个 1670 行文件

目标结构:

store/
├── connectionStore.ts  (已存在)
├── cloneStore.ts       (新增 - clone 管理)
├── skillStore.ts       (新增 - skill 管理)
├── channelStore.ts     (新增 - channel 管理)
├── triggerStore.ts     (新增 - trigger 管理)
├── workflowStore.ts    (已存在)
├── handStore.ts        (已存在)
├── usageStore.ts       (新增 - 使用统计)
└── configStore.ts      (已存在)

依赖: 应在 1.2 之后执行以避免合并冲突

验证:

  • pnpm tsc --noEmit 通过
  • 所有现有测试通过
  • 每个 store <400 行

1.4 替换 any 类型 [2天]

文件: lib/gateway/types.ts (新建)

关键类型定义:

export interface HealthResponse {
  status: 'ok' | 'degraded' | 'error';
  version: string;
  uptime: number;
}

export interface StatusResponse {
  gateway_version: string;
  agent_count: number;
  active_connections: number;
}

export interface CloneUpdate {
  name?: string;
  model?: string;
  system_prompt?: string;
  temperature?: number;
}

依赖: 应在 1.2 之后执行

验证:

  • noImplicitAny: true 检查通过
  • API 响应有运行时验证

1.5 添加 uuid 依赖 [0.5天]

命令:

cd desktop && pnpm add uuid && pnpm add -D @types/uuid

验证:

  • pnpm install 无错误
  • pnpm tsc --noEmit 通过

1.6 修复静默错误吞噬 [1天]

修改模式:

// 错误模式
catch { }

// 正确模式
catch (err: unknown) {
  if (import.meta.env.DEV) {
    console.warn('[模块名] 操作失败:', err);
  }
  // 预期: 某些场景下 localStorage 可能不可用
}

涉及文件:

  • secure-storage.ts
  • gateway-client.ts
  • connectionStore.ts
  • chatStore.ts
  • RightPanel.tsx
  • App.tsx

验证:

  • 搜索 catch\s*\([^)]*\)\s*\{[\s\n]*\} 返回空

Phase 2: P1 重要修复 (预计 6.5 天)

2.1 ReDoS 防护 [1天]

文件: desktop/src/components/CreateTriggerModal.tsx

修改内容:

const MAX_PATTERN_LENGTH = 200;

function validateRegexPattern(pattern: string): { valid: boolean; error?: string } {
  if (pattern.length > MAX_PATTERN_LENGTH) {
    return { valid: false, error: 'Pattern too long (max 200 chars)' };
  }

  // 检测危险构造
  const dangerousPatterns = [/\(\?[^)]*\+[^)]*\)/, /(.*)\1{3,}/];
  for (const dangerous of dangerousPatterns) {
    if (dangerous.test(pattern)) {
      return { valid: false, error: 'Pattern contains dangerous constructs' };
    }
  }

  // 超时检测
  try {
    const regex = new RegExp(pattern);
    const start = Date.now();
    regex.test('a'.repeat(20) + 'b'.repeat(20));
    if (Date.now() - start > 100) {
      return { valid: false, error: 'Pattern is too complex' };
    }
    return { valid: true };
  } catch {
    return { valid: false, error: 'Invalid regular expression' };
  }
}

2.2 清理 API 错误详情 [0.5天]

文件: desktop/src/lib/llm-service.ts

修改:

if (!response.ok) {
  const errorBody = await response.text();
  if (import.meta.env.DEV) {
    console.error('[OpenAI] API error:', errorBody);
  }
  // 返回清理后的错误
  throw new Error(`[OpenAI] API error: ${response.status} - Request failed`);
}

2.3 限制堆栈跟踪 [0.5天]

文件: desktop/src/lib/error-types.ts

修改:

technicalDetails: error instanceof Error
  ? `${error.name}: ${error.message}`  // 移除 stack
  : String(error),
// 仅开发环境保留原始错误
originalError: import.meta.env.DEV ? error : undefined,

2.4 默认安全 WebSocket [0.5天]

文件: desktop/src/lib/gateway-client.ts

修改:

// 生产环境默认 WSS
const USE_WSS = import.meta.env.VITE_USE_WSS !== 'false' || import.meta.env.PROD;

// 非 localhost 使用 ws:// 时警告
if (!url.startsWith('wss://') && !isLocalhost(url)) {
  console.warn('[Gateway] Connecting to non-localhost with insecure WebSocket');
}

2.5 类型化所有 catch 块 [1天]

tsconfig.json 修改:

{
  "compilerOptions": {
    "useUnknownInCatchVariables": true
  }
}

修复所有 catch 块:

catch (err: unknown) {
  const message = err instanceof Error ? err.message : String(err);
}

2.6 提取错误处理工具 [1天]

新建文件: desktop/src/lib/error-utils.ts

export function getErrorMessage(err: unknown): string {
  if (err instanceof Error) return err.message;
  if (typeof err === 'string') return err;
  return 'Unknown error';
}

export function isError(err: unknown): err is Error {
  return err instanceof Error;
}

2.7 移除 tsconfig 排除项 [2天]

当前排除:

  • src/components/ActiveLearningPanel.tsx
  • src/components/ui/ErrorAlert.tsx
  • src/components/ui/ErrorBoundary.tsx
  • src/store/activeLearningStore.ts
  • src/store/skillMarketStore.ts
  • src/types/active-learning.ts
  • src/types/skill-market.ts

操作: 逐个修复类型错误后从排除列表移除


Phase 3: P2 质量改进 (预计 7.5 天)

3.1 屏蔽控制台 Token [0.5天]

文件: desktop/src/store/connectionStore.ts

// 修改前
console.log('[ConnectionStore] Connecting with token:', effectiveToken ? `${effectiveToken.substring(0, 8)}...` : '(empty)');

// 修改后
console.log('[ConnectionStore] Connecting with token:', effectiveToken ? '[REDACTED]' : '(empty)');

3.2 提升测试覆盖率到 80% [5天]

当前测试:

  • Store 层: ~70%
  • Lib 层: ~50%
  • Component 层: ~10%

新增测试:

tests/desktop/
├── components/
│   ├── CreateTriggerModal.test.tsx
│   ├── ChatArea.test.tsx
│   └── CloneManager.test.tsx
├── lib/
│   ├── gateway-client.test.ts
│   ├── secure-storage.test.ts
│   └── llm-service.test.ts
└── integration/
    ├── websocket-flow.test.ts
    └── auth-flow.test.ts

依赖: 应在 Phase 1 重构后执行

3.3 结构化日志 [2天]

新建文件: desktop/src/lib/logger.ts

type LogLevel = 'debug' | 'info' | 'warn' | 'error';

export const logger = {
  debug: (context: string, message: string, data?: unknown) => { ... },
  info: (context: string, message: string, data?: unknown) => { ... },
  warn: (context: string, message: string, data?: unknown) => { ... },
  error: (context: string, message: string, error?: unknown) => { ... },
};

逐步替换 console.log


四、关键文件清单

文件 问题 修改类型
desktop/src/lib/secure-storage.ts 私钥明文存储 安全加固
desktop/src/lib/gateway-client.ts 1850行, 32处any 拆分+类型化
desktop/src/store/gatewayStore.ts 1670行 拆分
desktop/src/components/CreateTriggerModal.tsx ReDoS风险 输入验证
desktop/src/lib/error-types.ts 堆栈泄露 数据清理
desktop/src/lib/llm-service.ts 错误详情泄露 错误处理
desktop/src/store/connectionStore.ts Token日志 日志清理
desktop/package.json 缺uuid依赖 依赖添加
desktop/tsconfig.json 排除7文件 类型修复

五、验证清单

Phase 1 完成标准

  • pnpm tsc --noEmit 通过
  • pnpm vitest run 通过
  • any 类型 (gateway-client 相关)
  • 无静默 catch 块
  • 所有文件 <800 行

Phase 2 完成标准

  • ReDoS 模式被拒绝
  • API 错误不暴露响应体
  • 堆栈跟踪不在 technicalDetails
  • 生产环境默认 WSS
  • 所有 catch 使用 unknown
  • tsconfig 无自定义排除

Phase 3 完成标准

  • 控制台无敏感数据
  • 测试覆盖率 >= 80%
  • 所有日志使用结构化 logger

六、风险与依赖

6.1 风险

风险 影响 缓解措施
重构引入回归 每步运行测试套件
拆分破坏导入 使用 TypeScript 重构
测试用例失效 先修复代码再写测试

6.2 依赖关系

1.2 (拆分 gateway-client) → 1.3 (拆分 gatewayStore) → 1.4 (替换 any)
                                                  → 3.2 (增加测试)

七、执行顺序建议

  1. 立即执行 (无依赖):

    • 1.5 添加 uuid 依赖
    • 1.6 修复静默错误吞噬
    • 2.1 ReDoS 防护
    • 2.2 清理 API 错误
    • 2.3 限制堆栈跟踪
    • 2.4 默认 WSS
    • 2.5 类型化 catch
    • 2.6 错误处理工具
    • 3.1 屏蔽 Token
  2. 第二批 (有依赖):

    • 1.2 拆分 gateway-client
    • 1.3 拆分 gatewayStore
    • 1.4 替换 any 类型
  3. 最后执行:

    • 1.1 安全存储加密 (需要设计确认)
    • 2.7 移除 tsconfig 排除
    • 3.2 提升测试覆盖率
    • 3.3 结构化日志