# df-storage + df-relay + df-tunnel + df-project + df-types 代码走查报告

> 走查日期: 2026-08-02
> 范围: df-storage(7 文件, 150KB) + df-relay(5 文件, 30KB) + df-tunnel(3 文件, 28KB) + df-project(3 文件, 21KB) + df-types(3 文件, 42KB)

---

## 问题汇总

| # | 等级 | 文件 | 类型 | 简述 |
|---|---|---|---|---|
| 1 | 🔴 P0 | migrations.rs(89KB) | smell | 单文件 1914 行，37 个迁移函数 + V1 建表 SQL，文件过大 |
| 2 | 🔴 P0 | models.rs(25KB) | smell | 所有数据模型定义在单文件，20+ 结构体，已超合理阈值 |
| 3 | 🟡 P1 | secret.rs | risk | keyring 迁移失败时保留明文在 SQLite 文件，无加密保护 |
| 4 | 🟡 P1 | db.rs | risk | `Arc<Mutex<Connection>>` 单连接 Mutex，高并发时是瓶颈 |
| 5 | 🟡 P1 | crud/idea_repo.rs(65KB) | smell | IdeaRepo 单文件 65KB，含 KnowledgeRepo + 向量工具 |
| 6 | 🟡 P1 | crud/task_repo.rs(42KB) | smell | TaskRepo 42KB，含 advance_status_atomic 等复杂逻辑 |
| 7 | 🟡 P1 | relay.rs | risk | 单 token 鉴权（env `DF_RELAY_TOKEN`），生产级需独立 token/device |
| 8 | 🟡 P1 | tunnel.rs | risk | 仅支持手动重连，无自动后台重连 supervisor |
| 9 | 🟢 P2 | crud/mod.rs | smell | impl_repo! 宏 + 14 个子模块，但 advance_status_atomic 等特殊方法不在宏内 |
| 10 | 🟢 P2 | relay.rs | risk | 心跳 ping-pong 仅 miniapp 端触发，device 端无主动心跳 |
| 11 | 🟢 P2 | tunnel.rs | smell | `parse_payload_from_broadcast` 用匿名结构体仅提取 payload，不够健壮 |
| 12 | 🟢 P2 | scan_helpers.rs | smell | `is_pure_badge_line` 字符串解析逻辑复杂，无 regex 纯手写 |
| 13 | 🟢 P2 | types.rs | smell | 9 个 ID 别名 + 4 个状态枚举 + ExecutionId 新类型 + ToolCallType 新类型 |
| 14 | 🟢 P2 | augmentation.rs | smell | MentionRef/Augmentation 都带 tag = "kind"，但未共用反序列化代码 |

---

## 🔴 P0 问题详述

### #1 migrations.rs 89KB 单文件

**文件**: `migrations.rs` (1914 行)
**问题**: 37 个迁移函数 + V1 建表 SQL 字符串 + 步骤列表全在一个文件。V1_SQL 本身占数百行。

**建议**: 拆为 `migrations/v1.rs` ~ `migrations/v37.rs`，`migrations/mod.rs` 只保留 `run()` 和步骤列表。

### #2 models.rs 25KB 单文件

**文件**: `models.rs` (558 行)
**问题**: 20+ 结构体（IdeaRecord / ProjectRecord / TaskRecord / AiProviderRecord / AiConversationRecord / AiMessageRecord / KnowledgeRecord / ...）全在单文件。

**建议**: 拆为 `models/idea.rs` / `models/project.rs` / `models/task.rs` / `models/ai.rs` / `models/knowledge.rs`。

---

## 🟡 P1 问题详述

### #3 keyring 迁移失败保留明文

**文件**: `secret.rs:130-140`
**风险**: keyring 迁移失败时，api_key 明文保留在 SQLite 文件（无加密），用户可能不知情。

**建议**: 在迁移失败告警中提供更明确的指引，或支持 AES 加密 fallback。

### #4 db.rs 单连接 Mutex

**文件**: `db.rs:30-45`
**风险**: 全库单 `Connection` + `Mutex`，所有 CRUD 操作串行化。MCP server + GUI 并发读写时虽 WAL 模式允许写并发，但 Mutex 仍限制为单线程。

**建议**: 考虑 r2d2 连接池（注释中已标注 TODO）。

### #5 idea_repo.rs 65KB

**文件**: `crud/idea_repo.rs` (65KB)
**内含**: IdeaRepo + KnowledgeRepo + KnowledgeEventsRepo + 向量工具（embedding 搜索）。

**建议**: 拆为 3 个独立 repo 文件。

---

## 正面评价

1. **impl_repo! 宏**: 消除 14 个 Repo 的重复样板，统一 insert/get_by_id/list_all/query/update_field/delete/update_full
2. **secret.rs 设计**: OS keyring 优先 + DB 明文 fallback + 迁移失败计数 + 失败阈值告警
3. **db.rs 已开 WAL**: `PRAGMA journal_mode=WAL` + `PRAGMA foreign_keys=ON`
4. **relay 配对路由**: 按 device_id 配对，非全局广播，设计合理
5. **relay 心跳**: miniapp ping → relay pong 本地响应，不经过 device 透传
6. **tunnel 握手探测**: HANDSHAKE_PROBE 窗口 + 15s CONNECT_TIMEOUT，防死连
7. **tunnel 收发循环**: 独立 tokio::spawn + mpsc 解耦，不阻塞调用方
8. **scan_helpers 轻量**: 无 regex 依赖，纯手写字符串解析
9. **ProjectManager 状态机**: 独立领域层，不依赖 storage
10. **Augmentation 脱敏路径**: SanitizedPath newtype 防裸 String 误用