Skip to content

Win 提权助手收尾 + 规则资源(随包geo/可达性/UI) + 应用分流(catalog多选/默认注入/联动)#13

Closed
Sway-Chan wants to merge 12 commits into
mainfrom
feat/win-helper
Closed

Win 提权助手收尾 + 规则资源(随包geo/可达性/UI) + 应用分流(catalog多选/默认注入/联动)#13
Sway-Chan wants to merge 12 commits into
mainfrom
feat/win-helper

Conversation

@Sway-Chan

Copy link
Copy Markdown
Owner

概述

本分支收尾 Windows 提权助手,并落地规则资源与应用分流两块改进。

win-helper(Windows 零授权)

  • helper / winproc / 服务管理(WindowsServiceHelper) / 自卸载(selfuninstall) 修复与测试 + installer.nsh
  • 测速服务(SpeedTestService)重构 + 并发/进度单测;helper-handlers 引导门控

规则资源

  • 内置随包 geo 扩展(预设 geo 本地化)+ 远程 rule_set 生成期可达性预检/剔除,防单个坏标签 404 致 initialize rule-set FATAL(含 reachability / prune / scheduler-throttle 单测)
  • 资源库对话框:present 改按磁盘 fileExists 判定,外置「未下载」不再误标「文件缺失」;抽纯函数 resolveCatalogItemState + 回归单测
  • 已下载资源页:badge 基类 whitespace-nowrap;标题与「全部/内置/外置」tab 下沉整宽自适应;引用列徽章改 muted 文本 + 定宽

应用分流

  • 自定义 app 的 geosite/geoip 改 catalog 受限多选,从源头消灭「手打无效分类 → remote rule_set 404 FATAL」footgun;抽纯函数 geoCategoryOptions / localGeoTagSet + 单测
  • 移除 apple/bilibili 预设并删随包 srs;为内置预设默认注入 appRule(代理·跟全局) + loadConfig 一次性迁移(appRulesSeeded 守卫,幂等、不回灌)→ 卡片启动即可首次切节点热切换;抽纯函数 defaultAppRules / seedDefaultAppRules + 单测
  • 自定义 app 添加时同注入默认 appRule(与内置一致,消除首切再重启);所选 geo 联动下载进规则资源,generateRouteConfig 对 app geo 本地优先(localResPath)、缺失回落远程
  • 策略卡标签「手动选择策略组」→「代理策略」+ 提权字号 + 右上 chevron 可点击 affordance

验证

  • eslint / tsc(main + renderer) / jest(全量,含新增纯函数单测)全绿
  • 功能已真机验证

Sway-Chan and others added 12 commits June 14, 2026 12:54
…ge token化

- HIGH-1: buildWindowsUacLaunchCommand 的 watchdogArgs 值 token 去前导横线('-Bypass'→'Bypass'/'-Hidden'→'Hidden'),修 Windows TUN 看护脚本因 ExecutionPolicy/WindowStyle 未生效被拦/窗口闪现(真机验证 UAC 一次起核+TUN 通过)
- 9090: resolveClashApiPortConflict 的 probe 串行化(Promise.all→串行 await),修 bind 探测临时 listener 被并行 connect 探测自连 → 空闲端口误判 listening=true 锁死代理启动(Windows 真机 30/30→0/30)
- windowsHide: sing-box 提权 spawn 加 windowsHide:true,消除 TUN 启动外层 powershell 黑色控制台窗闪现
- MED-1: 提取 prunedSelectorDefault 单一真值,rule-sel 目标节点被启动前 gate 剔除时回落 proxy-selector(跟全局)而非任意存活节点;接入内联 detour 与 pruneTagsClosure 两处剔除点 + 单测
- MED-2: forceKillElevated 加 reportCancelled 形参,spawn 失败兜底不误报 STOP_AUTH_CANCELLED
- LOW-3: helper-handlers 裸 'app:uninstall-all' 改引 IPC_CHANNELS.APP_UNINSTALL_ALL
- T12: 分类/协议/资源 badge 裸 tailwind 色阶 → --badge-<hue> CSS token(明暗双块),协议 badge 加 variant=outline 消 hover 主色闪现

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
PR dododook#58/dododook#59-dododook#64 误带入仓库根的开发期草稿,非源码、无引用(jest.config/tsconfig 均不引用),清除。

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
- P1 watcher 引用计数:连接页 mount→watch/unmount→unwatch,connectionsWatchers>0 才 trimConnection+推送;漏 unwatch 退化为原行为(fail-safe);0→1 与 start 对齐 tick 即推首帧
- P2 窗口可见性门控:isWindowVisible 谓词,无可见窗口整轮跳过 fetch/parse/trim/广播(含首页 stats),重置 last 防恢复后失真速率
- P3 连接表行级 memo:ConnectionRow/DurationCell memo + 共享秒 tick 订阅自刷新 + ZERO_SPEED 稳定引用,整表每 2s 全量 reconcile→仅变化行
- P4:trim 移进 divider 分支消半浪费;activeConnections 取廉价 length 与列表门控解耦
- 经独立审计两轮收敛(无 HIGH/MED)

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
- N-1 导航: App.tsx routeMap 补 appPolicy, 与 sidebar mainNavItems 全集对齐
- N-2 性能健壮: StatsService.resetConnectionsWatchers + did-start-loading 挂钩,
  渲染端reload/崩溃重建时归零watcher引用计数,防漏发UNWATCH致计数泄漏(fail-safe已兜底)
- N-3 风格统一: real-time-logs/app-rules-card/backup-restore 裸语义色阶 → success/warning/info/destructive token
- CoreUpdateService: replaceManualCore 加 skipBackup(重置出厂跳备份/验证闩,改走recordSuccessfulVersion+pruneBackup)
- sidebar + i18n(zh/en) 收口
- 单测: core-swap-gate.test (+167) 覆盖门控置/清位

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
…L2b)

装一次 → Windows TUN 启停免每次 UAC,对齐 macOS helper 的零授权体验。经平台门控 + 接口抽象隔离,macOS/Linux 路径零改动。

- L0 接口抽象:抽 IPrivilegedHelper,HelperManager implements(纯类型,mac 零行为变更),
  ProxyManager/helper-handlers 形参拓宽到接口
- L1 helper-win/ Go 二进制:命名管道(SDDL: SYSTEM+IU, token 为主鉴权边界) + 行协议(逐行镜像
  helper.go) + CTRL_BREAK 优雅停 + GetExtendedTcpTable freeport + 轮询 GUI PID 父死看护 + SCM 服务;
  独立 go.mod + vendor(go-winio/x-sys) 离线可构建
- L2a WindowsServiceHelper 客户端(实现接口) + 6 单测;ResourceManager.getWinHelperPath
- L2b ProxyManager 启动路由短路(win helper 就绪→零提权起核,否则回退每次 UAC) + teardownForQuit win 分支
- 构建:build-helper.sh 加 Windows 交叉编译 target → resources/win/com.flowz.helper.exe(构建产物不入库)

离线 gate 全绿:tsc / eslint / jest 519 / GOOS=windows build+vet+vendor。
父死看护对齐 macOS watchParent(轮询 GUI PID,非 Job Object)。
Windows 真机必验待跑:UAC/sc 引号/管道连通/硬杀 wintun 残留/非管理员连管道。
剩余 L2c(index 注入 + promptHelperGate win) / L2d(UI 卡)。

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
dododook#65 含 Windows 提权/9090 自竞态/windowsHide 弹窗修复——设计稿中 helper 建于其上的基线。
本分支原基于 main+dododook#66+dododook#67,并入 dododook#65 后 = main + 三个 PR,便于完成后直接作独立 PR。
自动合并零冲突(helper-handlers/ProxyManager 我的改动与 dododook#65 落不同区域)。
复验:main tsc 0 / jest 523 全绿。

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
- L2c: index.ts 按平台装配 helper(macHelper 始终建,供 CoreUpdateService/PlatformPrivilegeService
  的 macOS 专属消费;模块 helperManager = Windows→WindowsServiceHelper / 其余→macHelper);
  promptHelperGate 加 Windows 分支(安装/修复服务,一次 UAC);ProxyManager.maybePromptHelperGate
  放行 win32(gate 对称覆盖 Windows TUN,无 backgroundDisabled)
- L2d: 设置页 helper 卡放开 Windows 显示(复用既有卡——backgroundDisabled/pathMismatch 等 macOS
  专属 UI 在 Windows flag 恒 false 不渲染;「管理员授权框」文案平台通用)

gate 全绿:main tsc 0 / renderer vite build / eslint 0 / jest 523。

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
第 1 轮(3 维度 agent;跨平台零回归审计干净,铁律守住):
- [Go-H2] freeport 空 TCP 表 &table[4] 越界 panic → 加 len<4 / n==0 守卫(IPv4+IPv6)
- [Go-H1] CTRL_BREAK 在 session-0 LocalSystem 服务下结构性失效(无 console 投递不到)→ 加
  Job Object(KILL_ON_JOB_CLOSE) 防孤儿网(helper 死→内核连坐杀 child,补足 watchParent 的
  GUI-死场景)+ terminateChild 5s→2s
- [Go-M1] enableIPForwarding 补 IPv6(netsh ipv6 forwarding);IPEnableRouter 持久副作用加注释
- [TS-H1] sc create binPath= "\"..\"" 在含空格路径(C:\Program Files)下 CommandLineToArgvW
  argv 碎裂、flag 值带字面引号污染 → 改 New-Service 真双引号直达 CreateService

第 2 轮(复核修复 + 抓新问题):
- [TS-MED-1] sc delete 异步「标记删除」vs 固定 300ms → New-Service 撞 1072 →
  轮询等服务消失 + 1072 退避重试
- [TS-MED-2] 提权失败只回退出码 → try/catch 把异常信息写回 app(失败带原因,对齐元规则)
- [TS-H2] Win 核更新 binPath 漂移 / pathMismatch 文档化为已知限制

gate 全绿:GOOS=windows build+vet / tsc 0 / eslint 0 / jest 523。
真机必验项已记录(Job Object 连坐杀、sc 引号实效、1072 命中率、硬杀 wintun 残留、非管理员连管道等)。

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
第 3 轮 review(仅查 round-2 新增 PS 逻辑,无新 HIGH):
- [MED-A] New-Service 1072 退避重试的 catch 吞所有异常、末尾硬编码「1072」文案盖掉非 1072 真因
  (反噬 round-2 自己引入的 MED-2「失败带真因」)→ catch 存 $lastErr,末尾 throw 透出真实异常
- [MED-B] PS5.1 Out-File -Encoding utf8 带 BOM → 回传文案残留零宽字符 → 改 [IO.File]::WriteAllText
  (.NET 默认 UTF-8 无 BOM),读侧回普通 trim
- uninstall 跑在 wrapper Stop 下幂等、临时文件清理、嵌套 try/catch —— 对抗核查均通过

gate:tsc 0 / eslint 0 / jest 6/6(含 1072/Get-Service 断言)。

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
真机暴露 L2b 漏接:只接了 start/teardownForQuit,漏了交互式 stop() 与起前孤儿清理的 Windows helper 路由:
- stop:原走 privilegeService.stopElevated(注入的是 macHelper,Win 上 supported=false)→ 落 RunAs taskkill
  杀 SYSTEM sing-box → 弹 UAC 且慢(先试非提权再升级)。修:stopSingBoxProcess 的 Win 分支先经
  this.helperManager(winHelper).stopCore()(零 UAC),镜像 macOS stopSingBoxWithSudo 的 helper 分支
- 起前 cleanup:killOrphanedProcessesWindows 非提权 taskkill 对 SYSTEM 孤儿 Access denied 清不掉。
  修:killOrphanedSingBoxProcesses 的 Win 先经 winHelper.cleanup()(SYSTEM 清 SYSTEM 孤儿,零 UAC),镜像 macOS

至此 Windows helper 集成对齐 macOS:start/stop/restart/cleanup/freeport 全经 helper 零 UAC。
gate:tsc 0 / eslint 0 / jest 523。

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
- 界面预览:原 9 张无标签外链 CDN webp → 11 张分组 + 中文配文图(7 组覆盖全功能域):
  首页明/暗 · 节点订阅 · 应用分流+路由规则 · 规则资源 · 连接诊断+实时日志 · 设置 + Windows/macOS 提权助手卡。
  截图为 headless 渲染 + 内置 demo 数据(无真实订阅/节点),webp 1280 宽入 docs/screenshots/(合计 360K)。
- 特性表:macOS 零授权链 → 零授权提权链(macOS + Windows),补本 PR 新增的 Windows LocalSystem 服务免每次 UAC。

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
## win-helper(Windows 零授权)
- helper/winproc/服务管理(WindowsServiceHelper)/自卸载(selfuninstall) 修复与测试 + installer.nsh
- 测速服务(SpeedTestService)重构 + 并发/进度单测;helper-handlers 引导门控

## 规则资源
- 内置随包 geo 扩展(APP_GEOSITE/GEOIP 预设 geo 本地化)+ 远程 rule_set 生成期可达性预检/剔除,防单个坏标签 404 致 sing-box initialize rule-set FATAL(+reachability/prune/scheduler-throttle 单测)
- 资源库对话框:present 改按磁盘 fileExists 判定(presentIds),外置「未下载」不再误标「文件缺失」;抽纯函数 resolveCatalogItemState + 回归单测
- 已下载资源页:badge 基类 whitespace-nowrap;标题与「全部/内置/外置」tab 下沉整宽自适应;引用列徽章改 muted 文本 + 定宽

## 应用分流
- 自定义 app 的 geosite/geoip 改 catalog 受限多选(geo-tag-picker),从源头消灭「手打无效分类 → remote rule_set 404 FATAL」footgun;抽纯函数 geoCategoryOptions/localGeoTagSet + 单测
- 移除 apple/bilibili 预设并删随包 srs;为内置预设默认注入 appRule(代理·跟全局) + loadConfig 一次性迁移(appRulesSeeded 守卫,幂等、不回灌) → 卡片启动即可首次切节点热切换;抽纯函数 defaultAppRules/seedDefaultAppRules + 单测
- 自定义 app 添加时同注入默认 appRule(与内置一致,消除首切再重启);所选 geo 联动下载进规则资源,generateRouteConfig 对 app geo 本地优先(localResPath)、缺失回落远程
- 策略卡标签「手动选择策略组」→「代理策略」+ 提权字号 + 右上 chevron 可点击 affordance

验证:eslint / tsc(main+renderer) / jest(全量含新增单测) 全绿;功能已真机验证。
@Sway-Chan

Copy link
Copy Markdown
Owner Author

误提交到个人 fork,已改提到上游 dododook#68,关闭此 PR。

@Sway-Chan Sway-Chan closed this Jun 14, 2026
Sway-Chan added a commit that referenced this pull request Jun 24, 2026
…修 + 3 取舍 + probing 死链清理)

dododook#174 引入:
- 缓存污染(#3/#10/dododook#15):state 文件兜底的乐观 loggedIn 用 skipCache 不进登录缓存(缓存只存 STATUS 真值),免 revoked/过期 key 的 state 残留固化误显已连接
- 瞬态登录核 authUrl 清理(#5):空 authUrl 下沉 finalize + loginCompleted 守卫,覆盖取消/崩溃/超时
- 设置弹窗文案(#8):去掉错误的「不自动重启」承诺(TS 设置改保存确会 switchMode 重连)
- EVENT_TAILSCALE_STATE_CLEARED(#4):reconcile 删 root state 后 main 发事件、渲染端清缓存+登录态,免撕裂

已合入 dododook#163dododook#173 回归:
- win-tun 用 powershellPath(#1,PATH 劫持 fail-open→dododook#159 释放门 no-op)
- ProxyManager startInternal 补 win32 换核重解析(#2)
- StatsService OOM eviction 改 LRU 近似(#7,免删健康长连接)
- helper chownTree 加 uid==0 guard(#12);helper upgradeable 跨窗口重发(#14)

probing 死链清理(批3 删自动探针后的全链死代码):probe 字段/setter/检测中 badge/handler 分支/PROBE channel+handler/probeTailscaleLoginStates+killTailscaleStatusProbe+tailscaleStatusProbe+emitTailscaleStatus probe 参数/buildTailscaleStatusProbeConfig+单测。

取舍(核实后不改,有据):#6 删 state 是 v5 非提权恢复手段、#9 tailscaleApiPort 每次新分配临时端口免撞、#13 dododook#168 已知 TS-H2 预存限制。

gate:tsc(main+renderer)+eslint+jest 1838 + go vet 全绿。
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant