# df-storage + df-ideas + df-mcp 代码走查报告

> 走查日期: 2026-08-02
> 范围: crates/df-storage/ (7 files, ~142KB) + crates/df-ideas/ (7 files, ~63KB) + crates/df-mcp/ (3 files, ~52KB)

---

## 一、df-storage 存储层

### 文件规模

| 文件 | 行数 | 类型 |
|---|---|---|
| migrations.rs | 89,663 | 迁移脚本(37 个版本) |
| models.rs | 24,880 | 15 个数据模型 |
| secret.rs | 16,523 | 密钥管理(keyring) |
| crud/mod.rs | 14,919 | Repo 宏 + 公共工具 |
| crud/task_repo.rs | 42,011 | 任务 Repo |
| crud/idea_repo.rs | 65,123 | 灵感 Repo |
| crud/conversation_repo.rs | 23,614 | 对话 Repo |
| crud/message_repo.rs | 26,633 | 消息 Repo |
| crud/project_repo.rs | 20,753 | 项目 Repo |
| crud/settings.rs | 11,778 | 列白名单 |

### 问题汇总

| # | 等级 | 文件 | 类型 | 简述 |
|---|---|---|---|---|
| 1 | 🟡 P1 | migrations.rs | smell | 89KB 单文件，37 个迁移函数全在一个文件，V1 建表 SQL 也嵌在里面 |
| 2 | 🟡 P1 | secret.rs | risk | keyring 在 Linux 无 GUI 会话时静默失败，`set_provider_secret` 返回 Err 但上层不处理 |
| 3 | 🟡 P1 | db.rs | risk | 单连接 `Mutex<Connection>`，GUI + MCP server 并发读写时锁竞争 |
| 4 | 🟡 P1 | crud/mod.rs | risk | `impl_repo!` 宏生成的 `update_field` 不校验 entity_type（已知缺陷 B-260801-01） |
| 5 | 🟡 P1 | crud/idea_repo.rs | smell | 65KB 单文件，灵感 Repo 含知识库/向量工具，职责过宽 |
| 6 | 🟡 P1 | crud/task_repo.rs | smell | 42KB 单文件，含 `advance_status_atomic` 状态机收口 |
| 7 | 🟢 P2 | secret.rs | smell | 迁移失败计数 sidecar 文件用 `.devflow-keyring-failcount`，路径依赖 cwd |
| 8 | 🟢 P2 | models.rs | smell | `AiProviderRecord` 的 `Debug` 手动脱敏，新增字段易漏 |
| 9 | 🟢 P2 | migrations.rs | smell | 37 个迁移版本，V1 建表 SQL 内联，V21 消息拆表迁移函数长 |

### 正面评价

1. **胡盾宏 impl_repo!**: 消除 14 个 Repo 的重复样板，from_row/insert/update 三体分离
2. **迁移幂等**: column_exists 探测，新库/老库/坏数据均不崩
3. **WAL 模式**: `PRAGMA journal_mode=WAL` 已启用，GUI + MCP 并发安全
4. **密钥管理**: keyring 迁移 + 失败计数阈值 + 显示告警，设计完整
5. **ensure_resolved_key**: 归一化(trim/剥引号)防粘贴脏 key
6. **列白名单**: `allowed_columns_for` 每表独立白名单，防 SQL 注入
7. **基线测试**: `all_known_tables_have_column_whitelist` 防新增表漏白名单

---

## 二、df-ideas 灵感评估

### 问题汇总

| # | 等级 | 文件 | 类型 | 简述 |
|---|---|---|---|---|
| 1 | 🟡 P1 | adversarial.rs | smell | 296KB 单文件，引擎 + 测试混在一起，测试应拆到独立文件 |
| 2 | 🟡 P1 | adversarial_helpers.rs | risk | 拒绝语义化关键字 `"no"` 过宽，`"no problem"` 等文本可能误判 |
| 3 | 🟢 P2 | scoring.rs | smell | 关键词匹配 `count_any` 否定前缀处理复杂，但只处理单字+两字否定 |
| 4 | 🟢 P2 | scoring_keywords.rs | smell | 关键词硬编码，最佳实践应为 JSON 配置 |
| 5 | 🟢 P2 | adversarial.rs | risk | `evaluate_with_llm` 返回一致性未校验，ARC-260618-01-e 待决策 |

### 正面评价

1. **对抗评估架构**: 启发式/LLM 双轨 + 自动降级，`evaluated_by` 三态标记前端可展示
2. **LLM prompt 设计**: 三角色辩论 + 严格 JSON schema + 截断保护
3. **parse_llm_eval 容错**: 剥离 ```json 围栏 + 正则兜底 + 枚举映射 + 数值 clamp
4. **评分引擎**: 否定前缀处理(不复用反向不计入复用正向分)，设计精细
5. **测试覆盖**: adversarial 7 个启发式 + 1 个 LLM mock 测试，scoring 10 个测试

---

## 三、df-mcp MCP Server

### 问题汇总

| # | 等级 | 文件 | 类型 | 简述 |
|---|---|---|---|---|
| 1 | 🟡 P1 | tools.rs | smell | 31KB 单文件，19 个 handler + 工具定义全在一起 |
| 2 | 🟡 P1 | tools.rs | risk | `Box::leak` 静态化工具定义，但 `all_tools()` 每次调用重新构建 Vec |
| 3 | 🟢 P2 | server.rs | smell | dispatch 中 `high_risk` 兜底拒绝与 `visible` 过滤双重检查，但 `visible` 已过滤 High |
| 4 | 🟢 P2 | protocol.rs | smell | `McpMethod::from_request` 中 `tools/call` 的 arguments 取 `req.params.get("arguments")`，可能为 null |

### 正面评价

1. **安全设计**: High 风险工具默认拒绝，read-only 模式仅 Low，双保险
2. **协议实现**: 完整 JSON-RPC 2.0 + MCP 2025-06-18 协议
3. **测试覆盖**: initialize/list/call/High拒绝/read-only/create-then-list 全路径覆盖
4. **handler 函数指针**: 避免闭包捕获生命周期问题
5. **medium_audit 审计日志**: Medium 风险工具调用有 tracing::warn 审计