cofluxd 0.5.0 → 0.6.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (3) hide show
  1. package/README.md +2 -1
  2. package/cofluxd.mjs +46 -6
  3. package/package.json +1 -1
package/README.md CHANGED
@@ -16,7 +16,8 @@ cofluxd up # 幂等:零参数即可装/起;已装则按当前
16
16
  cofluxd status # 服务器/登记(含"等待授权")/服务/连接状态
17
17
  cofluxd doctor # 中心网络 + gateway/grant/loopback + daemon 状态分层自检
18
18
  cofluxd logs -f # 看 daemon 日志
19
- cofluxd update # 更新本地 supervisor 二进制并重启(worker server 自动热升级)
19
+ cofluxd update # 下载新二进制(不重启;supervisor 有变化时提示用 restart 应用)
20
+ cofluxd restart # 重启 daemon 应用新 supervisor(⚠ 结束本机所有活会话)
20
21
  cofluxd down # 停止
21
22
  cofluxd uninstall [--purge] # 卸载(--purge 连二进制/配置/凭证一并删)
22
23
  ```
package/cofluxd.mjs CHANGED
@@ -115,6 +115,22 @@ function fdaLabel(status) {
115
115
 
116
116
  const sleep = (ms) => new Promise((r) => setTimeout(r, ms));
117
117
 
118
+ function fileSha256(path) {
119
+ try { return crypto.createHash("sha256").update(fs.readFileSync(path)).digest("hex"); } catch { return null; }
120
+ }
121
+
122
+ // macOS:新落盘的二进制带 com.apple.provenance,launchd 顶层 spawn 会被 AMFI 以
123
+ // OS_REASON_CODESIGNING 静默杀死——即使产物是 Developer ID 签名 + 已公证(2026-07-25
124
+ // v0.13.0 实测仍被连杀)。本地 ad-hoc 重签使其成为"本机产物"绕开该检查;签名威胁模型
125
+ // 不受影响(防的是中心被攻破推恶意产物,靠下载后的 sha256+ed25519 验签,与此无关)。
126
+ function resignMacBinaries(paths) {
127
+ if (!IS_MAC) return;
128
+ for (const p of paths) {
129
+ const r = run("codesign", ["--force", "-s", "-", p]);
130
+ if (r.status !== 0) console.warn(`⚠ 本地重签失败: ${p}(daemon 若被系统杀,手动 codesign --force -s - 该文件后 cofluxd restart)`);
131
+ }
132
+ }
133
+
118
134
  async function download(url, dest) {
119
135
  const res = await fetch(url, { redirect: "follow" });
120
136
  if (!res.ok) die(`下载失败 HTTP ${res.status}: ${url}\n(该版本/平台的 release 资产是否已发布?)`);
@@ -145,6 +161,7 @@ async function ensureBinaries({ version, binDir, skipIfPresent }) {
145
161
  fs.copyFileSync(src, join(BIN_DIR, b));
146
162
  fs.chmodSync(join(BIN_DIR, b), 0o755);
147
163
  }
164
+ resignMacBinaries([SUP_BIN, WRK_BIN]);
148
165
  console.log(`✓ 用本地二进制(${binDir})`);
149
166
  return;
150
167
  }
@@ -166,6 +183,7 @@ async function ensureBinaries({ version, binDir, skipIfPresent }) {
166
183
  await download(`${base}/${b}-${t}`, join(BIN_DIR, b));
167
184
  console.log("✓");
168
185
  }
186
+ resignMacBinaries([SUP_BIN, WRK_BIN]);
169
187
  }
170
188
 
171
189
  // 写 settings.json(daemon 直接读)。
@@ -298,20 +316,41 @@ function cmdDown() { stopService(); console.log("✓ 已停止"); }
298
316
  // 只有 supervisor 真正靠这条命令更新——它不自动升级(持 PTY,重启会杀会话,见 plan 017)。
299
317
  // worker 运行中会被 server 自动热升级到最新 stable(无需停服);这里顺带刷新的是 worker 的
300
318
  // "内置兜底二进制"(supervisor 冷启动/热升级缓存皆无时的 fallback),日常可不管。
319
+ //
320
+ // update 与 restart 拆开(2026-07-25 用户拍板):update 只落盘二进制、绝不重启——替换磁盘
321
+ // 文件对运行中的 supervisor/PTY 零影响;supervisor 内容没变就明说不用重启(大多数发版
322
+ // 都不动 supervisor,旧行为等于白丢一次全部会话)。真正的中断收敛到显式的 `cofluxd restart`。
301
323
  async function cmdUpdate(v) {
302
324
  if (!fs.existsSync(SETTINGS)) die("尚未安装,先 cofluxd up");
303
325
  const version = v.version || "latest";
326
+ const before = fileSha256(SUP_BIN);
304
327
  await ensureBinaries({ version, binDir: v["bin-dir"] });
328
+ if (before === fileSha256(SUP_BIN)) {
329
+ console.log("✓ 已更新:supervisor 无变化——不需要重启,活会话不受影响");
330
+ console.log(" worker 由 server 自动热升级;本次刷新的只是兜底 worker 二进制。");
331
+ } else {
332
+ console.log(`✓ 新 supervisor 已就位(${v["bin-dir"] ? "本地产物" : version}),但尚未生效`);
333
+ console.log(" ⚠ 运行 `cofluxd restart` 应用——会重启 daemon 并结束本机所有活会话(PTY 随 supervisor 退出)。");
334
+ }
335
+ }
336
+
337
+ // 唯一会主动中断会话的命令:应用已就位的新 supervisor(或单纯重启 daemon)。
338
+ function cmdRestart() {
339
+ if (!fs.existsSync(SETTINGS)) die("尚未安装,先 cofluxd up");
340
+ console.log("⚠ 正在重启 daemon:本机所有活会话将结束(PTY 随 supervisor 退出)…");
305
341
  restartService();
306
- console.log(`✓ supervisor 已更新到 ${v["bin-dir"] ? "本地产物" : version} 并重启`);
307
- console.log(" worker 由 server 自动热升级,通常无需手动更新;此命令只更新 supervisor(及其兜底 worker 二进制)。");
342
+ console.log("✓ 已重启(cofluxd status 查看状态)");
308
343
  }
309
344
 
310
345
  // launchd(macOS) / systemd --user(Linux) 服务活跃态查询,status 与 doctor 共用。
346
+ // macOS 必须以 launchctl list 输出里的 PID 为准:label 登记 ≠ 进程存活(supervisor 被
347
+ // OS_REASON_CODESIGNING 杀掉时 label 仍在,旧实现会报假"运行中",2026-07-25 实测踩过)。
311
348
  function serviceRunningInfo() {
312
349
  if (IS_MAC) {
313
- const running = run("launchctl", ["list", "com.coflux.daemon"]).status === 0;
314
- return { running, active: running ? "运行中" : "未运行" };
350
+ const out = run("launchctl", ["list", "com.coflux.daemon"]);
351
+ const registered = out.status === 0;
352
+ const running = registered && /"PID"\s*=\s*\d+/.test(out.stdout || "");
353
+ return { running, active: running ? "运行中" : registered ? "已登记但进程不在(看 cofluxd logs;常见于系统拒签杀进程)" : "未运行" };
315
354
  }
316
355
  if (IS_LINUX) {
317
356
  const active = (run("systemctl", ["--user", "is-active", "coflux-daemon.service"]).stdout || "").trim() || "未运行";
@@ -631,7 +670,8 @@ const HELP = `cofluxd —— coflux daemon 管理
631
670
  cofluxd up [flags] 幂等:首次装+起,已装则按当前 settings.json 重装服务并重启
632
671
  cofluxd status 服务器/登记(含"等待授权")/服务/连接状态
633
672
  cofluxd doctor 中心网络 + gateway bind/grant/loopback + daemon 状态分层自检
634
- cofluxd update 更新本地 supervisor 二进制并重启(worker server 自动热升级)
673
+ cofluxd update 下载新二进制(不重启;supervisor 有变化时提示用 restart 应用)
674
+ cofluxd restart 重启 daemon 应用新 supervisor(⚠ 结束本机所有活会话)
635
675
  cofluxd fda [仅 macOS] 引导授予完全磁盘访问权限(避免 PTY 因 TCC 弹窗卡住)
636
676
  cofluxd logs [-f] 看 daemon 日志
637
677
  cofluxd down 停止
@@ -667,7 +707,7 @@ let cmd = positionals[0];
667
707
  if (values.help || cmd === "help") { console.log(HELP); process.exit(0); }
668
708
  if (!cmd) cmd = fs.existsSync(SETTINGS) ? "status" : "up"; // 首次裸跑 → 引导
669
709
 
670
- const handlers = { up: cmdUp, update: cmdUpdate, down: cmdDown, status: cmdStatus, doctor: cmdDoctor, fda: cmdFda, logs: cmdLogs, uninstall: cmdUninstall };
710
+ const handlers = { up: cmdUp, update: cmdUpdate, restart: cmdRestart, down: cmdDown, status: cmdStatus, doctor: cmdDoctor, fda: cmdFda, logs: cmdLogs, uninstall: cmdUninstall };
671
711
  const h = handlers[cmd];
672
712
  if (!h) die(`未知命令: ${cmd}${MIGRATED[cmd] ? `\n${MIGRATED[cmd]}` : ""}\n\n${HELP}`);
673
713
  await h(values);
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "cofluxd",
3
- "version": "0.5.0",
3
+ "version": "0.6.0",
4
4
  "description": "coflux daemon 管理 CLI:装/起/停/升级 Rust daemon(supervisor + worker)",
5
5
  "type": "module",
6
6
  "bin": {