2 Commits
Author SHA1 Message Date
Qiu Yuzhou 43ea00cb44 fix(system-proxy): use BundleProgram in daemon plist and refresh stale registration
launchd 对 ProgramArguments[0] 的相对路径按 _PATH_STDPATH(PATH)解析而非
bundle:系统域 daemon 的 job 因此永远 spawn 失败(EX_CONFIG 节流循环,
launchctl print 显示 job state = spawn failed、runs 持续累加),客户端 XPC
调用只能等到超时。agent 之所以正常,是 GUI 域导入时被解析成绝对路径,system
域 submitted job 没有这一步。SMAppService 清单的正确键是 BundleProgram
(bundle 相对,launchd.plist(5)),改用之。

launchd 同时沿用注册提交时的定义快照:app 更新改动 LaunchDaemon 清单后旧
定义不会自动刷新(register() 对已注册服务返回 alreadyRegistered),必须注销
重注。门禁在已批准分支按清单内容 SHA-256 指纹(UserDefaults)检测漂移,漂移
才注销重注——审批与 bundle 签名绑定,重注不重新弹授权;首次注册成功即记指
纹,失败不记(下次启动重试),指纹一致为一次哈希比对的 no-op。
2026-09-30 18:54:19 +08:00
Qiu Yuzhou d2a8d6105c feat(system-proxy): route writes through privileged LaunchDaemon helper
Implements issue #71 with ADR-0020 (supersedes ADR-0019's endpoint-signature
cleanup, startup cleanup, and health-gate cleanup).

- New ShadowsocksX-NG2SystemProxyHelper target: app-bundled root LaunchDaemon
  (SMAppService.daemon, on-demand via MachServices) that mechanically applies
  a closed typed configuration or executes an unconditional clear. Clients are
  accepted by code-signing bundle identifier only; requests run serially on a
  shared queue (last-writer-wins).
- SystemProxyConfiguration is now the closed typed apply payload (Codable over
  JSON XPC): explicit SOCKS/HTTP/HTTPS enable + endpoints, PAC and
  auto-discovery disabled with URL/JS removed, explicit simple-hostname
  exclusion, complete ExceptionsList. Unmodeled Proxies keys are preserved and
  equivalent values skip the commit.
- Cleanup is a side effect of a persisted system-proxy intent on-to-off
  transition only: the switch itself, or the agent-off cascade (persist both
  intents off, clear, then stop listeners; failed cascade persistence records
  no transition and clears nothing). Launch with the switch off, health-gate
  closure, invalid targets, and passive events never clear. Failed clears are
  surfaced without deferred retry.
- Endpoint-signature store, ownership migration, and direct Authorization
  Services writes are removed; old signature files stay inert. Helper
  unavailability or pending approval keeps an enabled intent pending and
  surfaces the Login Items approval path (HomeView button + menu label).
2026-09-30 12:26:40 +08:00