# df-relay + df-tunnel + df-project + df-types + df-execute 代码走查报告 > 走查日期: 2026-08-02 > 范围: df-relay(5 文件, 30KB) + df-tunnel(3 文件, 32KB) + df-project(2 文件, 21KB) + df-types(3 文件, 42KB) + df-execute(2 文件, 34KB) --- ## 一、df-relay 云中继 ### 问题汇总 | # | 等级 | 文件 | 类型 | 简述 | |---|---|---|---|---| | 1 | 🟡 P1 | relay.rs | risk | token 鉴权用 `env DF_RELAY_TOKEN` 全局常量,生产级应有独立 token 每 device | | 2 | 🟡 P1 | relay.rs | risk | 注册表 `tokio::sync::Mutex` 锁粒度粗,高并发连接时瓶颈 | | 3 | 🟢 P2 | conn.rs | smell | `ConnRegistry::route` 中 `BroadcastMessage` 字段 `kind`/`from`/`handle.kind` 三因子匹配,可读性差 | | 4 | 🟢 P2 | broadcast.rs | smell | `ControlMessage` 定义了但 `handle_inbound_text` 中只处理 `ping`,其余控制消息未实现 | ### 正面评价 1. **架构清晰**: Event/Command/Control 三方向路由,语义明确 2. **Hello 握手**: 双因子校验(kind + token),超时 10s,error 帧回显 3. **心跳处理**: 小程序 ping → relay pong 本地响应,不经过 device 4. **BroadcastMessage 全字段**: device_id/kind/source/from/payload/ts,路由信息完整 --- ## 二、df-tunnel 隧道客户端 ### 问题汇总 | # | 等级 | 文件 | 类型 | 简述 | |---|---|---|---|---| | 1 | 🟡 P1 | tunnel.rs | risk | 重连退避逻辑写了 `backoff_delay` 函数但未实现自动后台重连,需手动 connect | | 2 | 🟡 P1 | tunnel.rs | risk | `cleanup_conn` 中 `select!` 500ms 超时后 abort task,可能丢最后一帧 | | 3 | 🟢 P2 | tunnel.rs | smell | `WsTunnelClient` 持 3 个 `Mutex>`(server_url/device_id/token),可合并为单 struct | | 4 | 🟢 P2 | tunnel.rs | smell | `connect` 方法 130 行,逻辑过重,可拆为 `do_connect` + `handshake` + `start_loop` | ### 正面评价 1. **协议对齐**: 与 df-relay 的 Hello 握手协议一致 2. **connect_timeout**: 15s 超时防 TCP SYN 无响应时永久挂 3. **HANDSHAKE_PROBE**: 3s 窗口探测 relay 是否拒绝,防静默失败 4. **心跳间隔**: 25s 应用层 Ping,防 NAT 连接表超时回收 5. **CommandHandler**: `BoxFuture` 回调,不阻塞收发循环 6. **send_raw_event**: AiChatEvent 全 19 变体透传,不依赖强类型 --- ## 三、df-project 项目管理 ### 问题汇总 | # | 等级 | 文件 | 类型 | 简述 | |---|---|---|---|---| | 1 | 🟢 P2 | manager.rs | smell | `ProjectManager::create` 纯领域层工厂,但 `Project` 实体与 `ProjectRecord` 模型不同源 | | 2 | 🟢 P2 | scan_helpers.rs | smell | 图片收集 `is_badge_image` 依赖域名+关键词列表,`is_pure_badge_line` 行级扫描逻辑复杂 | ### 正面评价 1. **状态机完整**: `can_transition` 矩阵清晰,`transition` 返回 `TerminalState`/`IllegalTransition` 区分 2. **scan_helpers 纯函数**: 无 IO 依赖,`strip_readme_noise` 处理 frontmatter/HTML注释/TOC/徽章 3. **否定前缀处理**: 单字(不/无/非/未/没/勿)+两字(没有/并非/毫无等)否定前缀,设计精细 4. **测试覆盖**: manager.rs 7 个测试,scan_helpers.rs 10 个测试 --- ## 四、df-types 类型定义 ### 问题汇总 | # | 等级 | 文件 | 类型 | 简述 | |---|---|---|---|---| | 1 | 🟢 P2 | augmentation.rs | smell | 21KB 单文件,MentionRef/Augmentation/ResolveError 三个模块混在一起 | | 2 | 🟢 P2 | types.rs | smell | `ExecutionId`/`ToolCallType` newtype 大量 `From`/`PartialEq` 样板,可取 derive_more | ### 正面评价 1. **SanitizedPath newtype**: 脱敏路径强制类型化,防裸 String 误用 2. **MentionRef/Augmentation 双结构**: resolve 前/后分离,职责清晰 3. **serde tag=kind**: 四种变体统一 json 结构,前端可共用 chip 渲染 4. **TaskStatus 双源一致性**: `as_str()` const fn + `valid_values()` 测试锁定 5. **WorkflowEvent 兼容**: `#[serde(default)]` 向后兼容老事件 --- ## 五、df-execute 命令执行 ### 问题汇总 | # | 等级 | 文件 | 类型 | 简述 | |---|---|---|---|---| | 1 | 🟡 P1 | shell.rs | risk | `build_command` 中 `ShellType::default()` 依赖 `PWSH_CACHE` 异步填充,首次 `execute` 可能读到未初始化 | | 2 | 🟡 P1 | env_snapshot.rs | risk | `probe_version` 内 `std::process::Command::output()` 无 timeout,Windows Store alias 卡死(已修复 5s timeout) | | 3 | 🟢 P2 | shell.rs | smell | `execute_streaming` 的 `on_output` 回调在 `select!` 中调用,`FnMut` 不可重入 | ### 正面评价 1. **PWSH_CACHE 单源**: 异步 probe + 同步读取,死缓存已修复 2. **execute_streaming**: mpsc 通道解耦 + 逐行回调 + read_to_end 兜底 3. **kill_on_drop**: 超时后子进程不残留 4. **CREATE_NO_WINDOW**: Windows 后台静默执行不弹黑窗 5. **env_snapshot 超时兜底**: 5s timeout + spawn_blocking 防永久卡 6. **extract_version_token**: 鲁棒版本号提取,"2.41.0.windows.1" → "2.41.0" 7. **测试覆盖**: shell.rs 探测缓存测试,env_snapshot 7 个测试