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

473 lines
12 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 代码质量与安全全面检查计划
> **类型**: 代码审查 / 安全审计
> **优先级**: 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`
**修改内容**:
```typescript
// 当 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` (新建)
**关键类型定义**:
```typescript
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天]
**命令**:
```bash
cd desktop && pnpm add uuid && pnpm add -D @types/uuid
```
**验证**:
- [ ] `pnpm install` 无错误
- [ ] `pnpm tsc --noEmit` 通过
#### 1.6 修复静默错误吞噬 [1天]
**修改模式**:
```typescript
// 错误模式
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`
**修改内容**:
```typescript
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`
**修改**:
```typescript
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`
**修改**:
```typescript
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`
**修改**:
```typescript
// 生产环境默认 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 修改**:
```json
{
"compilerOptions": {
"useUnknownInCatchVariables": true
}
}
```
**修复所有 catch 块**:
```typescript
catch (err: unknown) {
const message = err instanceof Error ? err.message : String(err);
}
```
#### 2.6 提取错误处理工具 [1天]
**新建文件**: `desktop/src/lib/error-utils.ts`
```typescript
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`
```typescript
// 修改前
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`
```typescript
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 结构化日志