@node9/proxy 2.2.2 → 2.3.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/dist/cli.js +113 -15
  2. package/dist/cli.mjs +113 -15
  3. package/package.json +1 -1
package/dist/cli.js CHANGED
@@ -21561,6 +21561,75 @@ function uninstallSystemd() {
21561
21561
  function isSystemdInstalled() {
21562
21562
  return import_fs43.default.existsSync(SYSTEMD_UNIT);
21563
21563
  }
21564
+ function windowsLauncherVbs(nodePath, scriptPath) {
21565
+ for (const p of [nodePath, scriptPath]) {
21566
+ if (p.includes('"')) throw new Error(`Illegal quote in path: ${p}`);
21567
+ }
21568
+ return [
21569
+ "' Auto-generated by node9 \u2014 starts the approval daemon with no console window.",
21570
+ "' Recreated on every `node9 daemon install`; safe to delete (uninstall does).",
21571
+ 'Set sh = CreateObject("Wscript.Shell")',
21572
+ 'sh.Environment("PROCESS")("NODE9_AUTO_STARTED") = "1"',
21573
+ `sh.Run """${nodePath}"" ""${scriptPath}"" daemon", 0, False`,
21574
+ ""
21575
+ ].join("\r\n");
21576
+ }
21577
+ function schtasksCreateArgs(launcherPath) {
21578
+ return [
21579
+ "/Create",
21580
+ "/TN",
21581
+ SCHTASKS_TASK,
21582
+ "/TR",
21583
+ `wscript.exe //B "${launcherPath}"`,
21584
+ "/SC",
21585
+ "ONLOGON",
21586
+ "/F"
21587
+ ];
21588
+ }
21589
+ function installSchtasks(binaryPath) {
21590
+ const launcher = WIN_LAUNCHER();
21591
+ const dir = import_path42.default.dirname(launcher);
21592
+ if (!import_fs43.default.existsSync(dir)) import_fs43.default.mkdirSync(dir, { recursive: true });
21593
+ import_fs43.default.writeFileSync(launcher, windowsLauncherVbs(process.execPath, binaryPath), "utf-8");
21594
+ const create = (0, import_child_process3.spawnSync)("schtasks", schtasksCreateArgs(launcher), {
21595
+ encoding: "utf8",
21596
+ timeout: 1e4
21597
+ });
21598
+ if (create.status !== 0) {
21599
+ throw new Error(
21600
+ `schtasks /Create failed: ${create.stderr || create.stdout || "unknown error"}`
21601
+ );
21602
+ }
21603
+ (0, import_child_process3.spawnSync)("schtasks", ["/Run", "/TN", SCHTASKS_TASK], { encoding: "utf8", timeout: 1e4 });
21604
+ }
21605
+ function uninstallSchtasks() {
21606
+ (0, import_child_process3.spawnSync)("schtasks", ["/Delete", "/TN", SCHTASKS_TASK, "/F"], {
21607
+ encoding: "utf8",
21608
+ timeout: 1e4
21609
+ });
21610
+ const launcher = WIN_LAUNCHER();
21611
+ if (import_fs43.default.existsSync(launcher)) {
21612
+ try {
21613
+ import_fs43.default.unlinkSync(launcher);
21614
+ } catch {
21615
+ }
21616
+ }
21617
+ }
21618
+ function isSchtasksInstalled() {
21619
+ const r = (0, import_child_process3.spawnSync)("schtasks", ["/Query", "/TN", SCHTASKS_TASK], {
21620
+ encoding: "utf8",
21621
+ timeout: 5e3
21622
+ });
21623
+ return r.status === 0;
21624
+ }
21625
+ function isSchtasksEnabled() {
21626
+ const r = (0, import_child_process3.spawnSync)("schtasks", ["/Query", "/TN", SCHTASKS_TASK, "/XML"], {
21627
+ encoding: "utf8",
21628
+ timeout: 5e3
21629
+ });
21630
+ if (r.status !== 0) return false;
21631
+ return !/<Enabled>\s*false\s*<\/Enabled>/i.test(r.stdout ?? "");
21632
+ }
21564
21633
  function stopRunningDaemon() {
21565
21634
  const pidFile = import_path42.default.join(import_os39.default.homedir(), ".node9", "daemon.pid");
21566
21635
  if (!import_fs43.default.existsSync(pidFile)) return;
@@ -21572,15 +21641,15 @@ function stopRunningDaemon() {
21572
21641
  try {
21573
21642
  process.kill(pid, "SIGTERM");
21574
21643
  const deadline = Date.now() + 3e3;
21575
- const pollStop = (0, import_child_process3.spawnSync)(
21576
- "sh",
21577
- ["-c", `while kill -0 ${pid} 2>/dev/null; do sleep 0.1; done`],
21578
- {
21579
- timeout: 3100
21644
+ const sleeper = new Int32Array(new SharedArrayBuffer(4));
21645
+ while (Date.now() < deadline) {
21646
+ try {
21647
+ process.kill(pid, 0);
21648
+ } catch {
21649
+ break;
21580
21650
  }
21581
- );
21582
- void pollStop;
21583
- void deadline;
21651
+ Atomics.wait(sleeper, 0, 0, 100);
21652
+ }
21584
21653
  } catch {
21585
21654
  }
21586
21655
  }
@@ -21618,6 +21687,11 @@ function installDaemonService() {
21618
21687
  installSystemd(binary);
21619
21688
  return { ok: true, platform: "systemd", alreadyInstalled };
21620
21689
  }
21690
+ if (process.platform === "win32") {
21691
+ const alreadyInstalled = isSchtasksInstalled();
21692
+ installSchtasks(binary);
21693
+ return { ok: true, platform: "schtasks", alreadyInstalled };
21694
+ }
21621
21695
  return {
21622
21696
  ok: false,
21623
21697
  reason: `Automatic service install is not supported on ${process.platform}. Start the daemon manually with: node9 daemon start`
@@ -21639,6 +21713,10 @@ function uninstallDaemonService() {
21639
21713
  uninstallSystemd();
21640
21714
  return { ok: true, platform: "systemd", alreadyInstalled: false };
21641
21715
  }
21716
+ if (process.platform === "win32") {
21717
+ uninstallSchtasks();
21718
+ return { ok: true, platform: "schtasks", alreadyInstalled: false };
21719
+ }
21642
21720
  return {
21643
21721
  ok: false,
21644
21722
  reason: `Service management not supported on ${process.platform}.`
@@ -21653,11 +21731,14 @@ function uninstallDaemonService() {
21653
21731
  function isDaemonServiceInstalled() {
21654
21732
  if (process.platform === "darwin") return isLaunchdInstalled();
21655
21733
  if (process.platform === "linux") return isSystemdInstalled();
21734
+ if (process.platform === "win32") return isSchtasksInstalled();
21656
21735
  return false;
21657
21736
  }
21658
21737
  function autostartRepairDecision(opts) {
21659
21738
  if (!opts.autoStartDaemon) return "skip";
21660
- if (process.platform !== "linux" && process.platform !== "darwin") return "unsupported";
21739
+ if (process.platform !== "linux" && process.platform !== "darwin" && process.platform !== "win32") {
21740
+ return "unsupported";
21741
+ }
21661
21742
  if (!opts.installed) return "skip";
21662
21743
  return opts.enabled ? "ok" : "repair";
21663
21744
  }
@@ -21670,6 +21751,13 @@ function enableDaemonServiceQuiet() {
21670
21751
  });
21671
21752
  return r.status === 0;
21672
21753
  }
21754
+ if (process.platform === "win32") {
21755
+ const r = (0, import_child_process3.spawnSync)("schtasks", ["/Change", "/TN", SCHTASKS_TASK, "/ENABLE"], {
21756
+ encoding: "utf8",
21757
+ timeout: 5e3
21758
+ });
21759
+ return r.status === 0;
21760
+ }
21673
21761
  return process.platform === "darwin";
21674
21762
  } catch {
21675
21763
  return false;
@@ -21684,10 +21772,13 @@ function ensureAutostartHealthy(autoStartDaemon) {
21684
21772
  if (decision === "repair") return enableDaemonServiceQuiet() ? "repaired" : "skipped";
21685
21773
  return decision === "ok" ? "ok" : decision === "unsupported" ? "unsupported" : "skipped";
21686
21774
  }
21775
+ function autostartInstallHint() {
21776
+ return process.platform === "linux" ? "Run: systemctl --user enable --now node9-daemon (or: node9 daemon install)" : "Run: node9 daemon install";
21777
+ }
21687
21778
  function autostartAdvice(opts) {
21688
- const installable = process.platform === "linux" || process.platform === "darwin";
21779
+ const installable = process.platform === "linux" || process.platform === "darwin" || process.platform === "win32";
21689
21780
  if (!opts.cloudEnabled || !installable) return null;
21690
- const installHint = process.platform === "linux" ? "Run: systemctl --user enable --now node9-daemon (or: node9 daemon install)" : "Run: node9 daemon install";
21781
+ const installHint = autostartInstallHint();
21691
21782
  if (opts.installed && !opts.enabled) {
21692
21783
  return {
21693
21784
  level: "warn",
@@ -21720,11 +21811,14 @@ function isDaemonServiceEnabled() {
21720
21811
  });
21721
21812
  return r.status === 0;
21722
21813
  }
21814
+ if (process.platform === "win32") {
21815
+ return isSchtasksEnabled();
21816
+ }
21723
21817
  } catch {
21724
21818
  }
21725
21819
  return false;
21726
21820
  }
21727
- var import_fs43, import_path42, import_os39, import_child_process3, LAUNCHD_LABEL, LAUNCHD_PLIST, SYSTEMD_UNIT_DIR, SYSTEMD_UNIT;
21821
+ var import_fs43, import_path42, import_os39, import_child_process3, LAUNCHD_LABEL, LAUNCHD_PLIST, SYSTEMD_UNIT_DIR, SYSTEMD_UNIT, SCHTASKS_TASK, WIN_LAUNCHER;
21728
21822
  var init_service = __esm({
21729
21823
  "src/daemon/service.ts"() {
21730
21824
  "use strict";
@@ -21736,6 +21830,8 @@ var init_service = __esm({
21736
21830
  LAUNCHD_PLIST = import_path42.default.join(import_os39.default.homedir(), "Library", "LaunchAgents", `${LAUNCHD_LABEL}.plist`);
21737
21831
  SYSTEMD_UNIT_DIR = import_path42.default.join(import_os39.default.homedir(), ".config", "systemd", "user");
21738
21832
  SYSTEMD_UNIT = import_path42.default.join(SYSTEMD_UNIT_DIR, "node9-daemon.service");
21833
+ SCHTASKS_TASK = "Node9Daemon";
21834
+ WIN_LAUNCHER = () => import_path42.default.join(import_os39.default.homedir(), ".node9", "daemon-launcher.vbs");
21739
21835
  }
21740
21836
  });
21741
21837
 
@@ -48283,7 +48379,7 @@ async function onboardMachine(apiKey, opts = {}) {
48283
48379
  push.ok ? { name: "register", ok: true, detail: "machine visible in the dashboard" } : { name: "register", ok: false, detail: push.reason }
48284
48380
  );
48285
48381
  const healed = ensureAutostartHealthy(!!getConfig().settings.autoStartDaemon);
48286
- const detail = healed === "repaired" ? "autostart re-enabled (survives reboot)" : isDaemonRunning() ? "running" : healed === "unsupported" ? "no background service on this platform: starts on agent activity" : "starts on agent activity";
48382
+ const detail = healed === "repaired" ? "autostart re-enabled (survives reboot)" : isDaemonRunning() ? "running" : healed === "unsupported" ? "no background service on this platform: starts on agent activity" : "starts on agent activity (make it survive reboots: node9 daemon install)";
48287
48383
  steps.push({ name: "daemon", ok: true, detail });
48288
48384
  }
48289
48385
  const required = ["credentials", "policy-sync", "register"];
@@ -50389,7 +50485,9 @@ function registerDoctorCommand(program2, version2) {
50389
50485
  const fails = health.consecutiveFailures > 0 ? ` (${health.consecutiveFailures} consecutive failure${health.consecutiveFailures === 1 ? "" : "s"}${health.lastError ? `: ${health.lastError}` : ""})` : "";
50390
50486
  warn(
50391
50487
  `Cloud policy is STALE \u2014 ${when}${fails}. The cached policy is still enforced, but changes from the dashboard are not reaching this machine.`,
50392
- "Run: node9 policy sync (and ensure the daemon autostarts: systemctl --user enable --now node9-daemon)"
50488
+ // Platform-aware: this hint hardcoded systemctl and told a Windows
50489
+ // founder to run a Linux command (QA 2026-08-28).
50490
+ `Run: node9 policy sync (then keep it fresh across reboots \u2014 ${autostartInstallHint()})`
50393
50491
  );
50394
50492
  } else if (health.lastCheckedAt) {
50395
50493
  pass(`Cloud policy fresh \u2014 last synced ${agoLabel(health.lastCheckedAt)}`);
@@ -52131,7 +52229,7 @@ function registerInitCommand(program2) {
52131
52229
  await setupAgent(agent);
52132
52230
  console.log("");
52133
52231
  }
52134
- if ((process.platform === "darwin" || process.platform === "linux") && process.stdout.isTTY) {
52232
+ if ((process.platform === "darwin" || process.platform === "linux" || process.platform === "win32") && process.stdout.isTTY) {
52135
52233
  const alreadyInstalled = isDaemonServiceInstalled();
52136
52234
  if (!alreadyInstalled) {
52137
52235
  const { confirm: confirm4 } = await import("@inquirer/prompts");
package/dist/cli.mjs CHANGED
@@ -21558,6 +21558,75 @@ function uninstallSystemd() {
21558
21558
  function isSystemdInstalled() {
21559
21559
  return fs44.existsSync(SYSTEMD_UNIT);
21560
21560
  }
21561
+ function windowsLauncherVbs(nodePath, scriptPath) {
21562
+ for (const p of [nodePath, scriptPath]) {
21563
+ if (p.includes('"')) throw new Error(`Illegal quote in path: ${p}`);
21564
+ }
21565
+ return [
21566
+ "' Auto-generated by node9 \u2014 starts the approval daemon with no console window.",
21567
+ "' Recreated on every `node9 daemon install`; safe to delete (uninstall does).",
21568
+ 'Set sh = CreateObject("Wscript.Shell")',
21569
+ 'sh.Environment("PROCESS")("NODE9_AUTO_STARTED") = "1"',
21570
+ `sh.Run """${nodePath}"" ""${scriptPath}"" daemon", 0, False`,
21571
+ ""
21572
+ ].join("\r\n");
21573
+ }
21574
+ function schtasksCreateArgs(launcherPath) {
21575
+ return [
21576
+ "/Create",
21577
+ "/TN",
21578
+ SCHTASKS_TASK,
21579
+ "/TR",
21580
+ `wscript.exe //B "${launcherPath}"`,
21581
+ "/SC",
21582
+ "ONLOGON",
21583
+ "/F"
21584
+ ];
21585
+ }
21586
+ function installSchtasks(binaryPath) {
21587
+ const launcher = WIN_LAUNCHER();
21588
+ const dir = path43.dirname(launcher);
21589
+ if (!fs44.existsSync(dir)) fs44.mkdirSync(dir, { recursive: true });
21590
+ fs44.writeFileSync(launcher, windowsLauncherVbs(process.execPath, binaryPath), "utf-8");
21591
+ const create = spawnSync2("schtasks", schtasksCreateArgs(launcher), {
21592
+ encoding: "utf8",
21593
+ timeout: 1e4
21594
+ });
21595
+ if (create.status !== 0) {
21596
+ throw new Error(
21597
+ `schtasks /Create failed: ${create.stderr || create.stdout || "unknown error"}`
21598
+ );
21599
+ }
21600
+ spawnSync2("schtasks", ["/Run", "/TN", SCHTASKS_TASK], { encoding: "utf8", timeout: 1e4 });
21601
+ }
21602
+ function uninstallSchtasks() {
21603
+ spawnSync2("schtasks", ["/Delete", "/TN", SCHTASKS_TASK, "/F"], {
21604
+ encoding: "utf8",
21605
+ timeout: 1e4
21606
+ });
21607
+ const launcher = WIN_LAUNCHER();
21608
+ if (fs44.existsSync(launcher)) {
21609
+ try {
21610
+ fs44.unlinkSync(launcher);
21611
+ } catch {
21612
+ }
21613
+ }
21614
+ }
21615
+ function isSchtasksInstalled() {
21616
+ const r = spawnSync2("schtasks", ["/Query", "/TN", SCHTASKS_TASK], {
21617
+ encoding: "utf8",
21618
+ timeout: 5e3
21619
+ });
21620
+ return r.status === 0;
21621
+ }
21622
+ function isSchtasksEnabled() {
21623
+ const r = spawnSync2("schtasks", ["/Query", "/TN", SCHTASKS_TASK, "/XML"], {
21624
+ encoding: "utf8",
21625
+ timeout: 5e3
21626
+ });
21627
+ if (r.status !== 0) return false;
21628
+ return !/<Enabled>\s*false\s*<\/Enabled>/i.test(r.stdout ?? "");
21629
+ }
21561
21630
  function stopRunningDaemon() {
21562
21631
  const pidFile = path43.join(os40.homedir(), ".node9", "daemon.pid");
21563
21632
  if (!fs44.existsSync(pidFile)) return;
@@ -21569,15 +21638,15 @@ function stopRunningDaemon() {
21569
21638
  try {
21570
21639
  process.kill(pid, "SIGTERM");
21571
21640
  const deadline = Date.now() + 3e3;
21572
- const pollStop = spawnSync2(
21573
- "sh",
21574
- ["-c", `while kill -0 ${pid} 2>/dev/null; do sleep 0.1; done`],
21575
- {
21576
- timeout: 3100
21641
+ const sleeper = new Int32Array(new SharedArrayBuffer(4));
21642
+ while (Date.now() < deadline) {
21643
+ try {
21644
+ process.kill(pid, 0);
21645
+ } catch {
21646
+ break;
21577
21647
  }
21578
- );
21579
- void pollStop;
21580
- void deadline;
21648
+ Atomics.wait(sleeper, 0, 0, 100);
21649
+ }
21581
21650
  } catch {
21582
21651
  }
21583
21652
  }
@@ -21615,6 +21684,11 @@ function installDaemonService() {
21615
21684
  installSystemd(binary);
21616
21685
  return { ok: true, platform: "systemd", alreadyInstalled };
21617
21686
  }
21687
+ if (process.platform === "win32") {
21688
+ const alreadyInstalled = isSchtasksInstalled();
21689
+ installSchtasks(binary);
21690
+ return { ok: true, platform: "schtasks", alreadyInstalled };
21691
+ }
21618
21692
  return {
21619
21693
  ok: false,
21620
21694
  reason: `Automatic service install is not supported on ${process.platform}. Start the daemon manually with: node9 daemon start`
@@ -21636,6 +21710,10 @@ function uninstallDaemonService() {
21636
21710
  uninstallSystemd();
21637
21711
  return { ok: true, platform: "systemd", alreadyInstalled: false };
21638
21712
  }
21713
+ if (process.platform === "win32") {
21714
+ uninstallSchtasks();
21715
+ return { ok: true, platform: "schtasks", alreadyInstalled: false };
21716
+ }
21639
21717
  return {
21640
21718
  ok: false,
21641
21719
  reason: `Service management not supported on ${process.platform}.`
@@ -21650,11 +21728,14 @@ function uninstallDaemonService() {
21650
21728
  function isDaemonServiceInstalled() {
21651
21729
  if (process.platform === "darwin") return isLaunchdInstalled();
21652
21730
  if (process.platform === "linux") return isSystemdInstalled();
21731
+ if (process.platform === "win32") return isSchtasksInstalled();
21653
21732
  return false;
21654
21733
  }
21655
21734
  function autostartRepairDecision(opts) {
21656
21735
  if (!opts.autoStartDaemon) return "skip";
21657
- if (process.platform !== "linux" && process.platform !== "darwin") return "unsupported";
21736
+ if (process.platform !== "linux" && process.platform !== "darwin" && process.platform !== "win32") {
21737
+ return "unsupported";
21738
+ }
21658
21739
  if (!opts.installed) return "skip";
21659
21740
  return opts.enabled ? "ok" : "repair";
21660
21741
  }
@@ -21667,6 +21748,13 @@ function enableDaemonServiceQuiet() {
21667
21748
  });
21668
21749
  return r.status === 0;
21669
21750
  }
21751
+ if (process.platform === "win32") {
21752
+ const r = spawnSync2("schtasks", ["/Change", "/TN", SCHTASKS_TASK, "/ENABLE"], {
21753
+ encoding: "utf8",
21754
+ timeout: 5e3
21755
+ });
21756
+ return r.status === 0;
21757
+ }
21670
21758
  return process.platform === "darwin";
21671
21759
  } catch {
21672
21760
  return false;
@@ -21681,10 +21769,13 @@ function ensureAutostartHealthy(autoStartDaemon) {
21681
21769
  if (decision === "repair") return enableDaemonServiceQuiet() ? "repaired" : "skipped";
21682
21770
  return decision === "ok" ? "ok" : decision === "unsupported" ? "unsupported" : "skipped";
21683
21771
  }
21772
+ function autostartInstallHint() {
21773
+ return process.platform === "linux" ? "Run: systemctl --user enable --now node9-daemon (or: node9 daemon install)" : "Run: node9 daemon install";
21774
+ }
21684
21775
  function autostartAdvice(opts) {
21685
- const installable = process.platform === "linux" || process.platform === "darwin";
21776
+ const installable = process.platform === "linux" || process.platform === "darwin" || process.platform === "win32";
21686
21777
  if (!opts.cloudEnabled || !installable) return null;
21687
- const installHint = process.platform === "linux" ? "Run: systemctl --user enable --now node9-daemon (or: node9 daemon install)" : "Run: node9 daemon install";
21778
+ const installHint = autostartInstallHint();
21688
21779
  if (opts.installed && !opts.enabled) {
21689
21780
  return {
21690
21781
  level: "warn",
@@ -21717,11 +21808,14 @@ function isDaemonServiceEnabled() {
21717
21808
  });
21718
21809
  return r.status === 0;
21719
21810
  }
21811
+ if (process.platform === "win32") {
21812
+ return isSchtasksEnabled();
21813
+ }
21720
21814
  } catch {
21721
21815
  }
21722
21816
  return false;
21723
21817
  }
21724
- var LAUNCHD_LABEL, LAUNCHD_PLIST, SYSTEMD_UNIT_DIR, SYSTEMD_UNIT;
21818
+ var LAUNCHD_LABEL, LAUNCHD_PLIST, SYSTEMD_UNIT_DIR, SYSTEMD_UNIT, SCHTASKS_TASK, WIN_LAUNCHER;
21725
21819
  var init_service = __esm({
21726
21820
  "src/daemon/service.ts"() {
21727
21821
  "use strict";
@@ -21729,6 +21823,8 @@ var init_service = __esm({
21729
21823
  LAUNCHD_PLIST = path43.join(os40.homedir(), "Library", "LaunchAgents", `${LAUNCHD_LABEL}.plist`);
21730
21824
  SYSTEMD_UNIT_DIR = path43.join(os40.homedir(), ".config", "systemd", "user");
21731
21825
  SYSTEMD_UNIT = path43.join(SYSTEMD_UNIT_DIR, "node9-daemon.service");
21826
+ SCHTASKS_TASK = "Node9Daemon";
21827
+ WIN_LAUNCHER = () => path43.join(os40.homedir(), ".node9", "daemon-launcher.vbs");
21732
21828
  }
21733
21829
  });
21734
21830
 
@@ -48276,7 +48372,7 @@ async function onboardMachine(apiKey, opts = {}) {
48276
48372
  push.ok ? { name: "register", ok: true, detail: "machine visible in the dashboard" } : { name: "register", ok: false, detail: push.reason }
48277
48373
  );
48278
48374
  const healed = ensureAutostartHealthy(!!getConfig().settings.autoStartDaemon);
48279
- const detail = healed === "repaired" ? "autostart re-enabled (survives reboot)" : isDaemonRunning() ? "running" : healed === "unsupported" ? "no background service on this platform: starts on agent activity" : "starts on agent activity";
48375
+ const detail = healed === "repaired" ? "autostart re-enabled (survives reboot)" : isDaemonRunning() ? "running" : healed === "unsupported" ? "no background service on this platform: starts on agent activity" : "starts on agent activity (make it survive reboots: node9 daemon install)";
48280
48376
  steps.push({ name: "daemon", ok: true, detail });
48281
48377
  }
48282
48378
  const required = ["credentials", "policy-sync", "register"];
@@ -50382,7 +50478,9 @@ function registerDoctorCommand(program2, version2) {
50382
50478
  const fails = health.consecutiveFailures > 0 ? ` (${health.consecutiveFailures} consecutive failure${health.consecutiveFailures === 1 ? "" : "s"}${health.lastError ? `: ${health.lastError}` : ""})` : "";
50383
50479
  warn(
50384
50480
  `Cloud policy is STALE \u2014 ${when}${fails}. The cached policy is still enforced, but changes from the dashboard are not reaching this machine.`,
50385
- "Run: node9 policy sync (and ensure the daemon autostarts: systemctl --user enable --now node9-daemon)"
50481
+ // Platform-aware: this hint hardcoded systemctl and told a Windows
50482
+ // founder to run a Linux command (QA 2026-08-28).
50483
+ `Run: node9 policy sync (then keep it fresh across reboots \u2014 ${autostartInstallHint()})`
50386
50484
  );
50387
50485
  } else if (health.lastCheckedAt) {
50388
50486
  pass(`Cloud policy fresh \u2014 last synced ${agoLabel(health.lastCheckedAt)}`);
@@ -52124,7 +52222,7 @@ function registerInitCommand(program2) {
52124
52222
  await setupAgent(agent);
52125
52223
  console.log("");
52126
52224
  }
52127
- if ((process.platform === "darwin" || process.platform === "linux") && process.stdout.isTTY) {
52225
+ if ((process.platform === "darwin" || process.platform === "linux" || process.platform === "win32") && process.stdout.isTTY) {
52128
52226
  const alreadyInstalled = isDaemonServiceInstalled();
52129
52227
  if (!alreadyInstalled) {
52130
52228
  const { confirm: confirm4 } = await import("@inquirer/prompts");
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@node9/proxy",
3
- "version": "2.2.2",
3
+ "version": "2.3.0",
4
4
  "description": "The Sudo Command for AI Agents. Execution Security for Claude Code, Codex, Gemini, Cursor, Opencode, Pi, and any MCP server.",
5
5
  "main": "./dist/index.js",
6
6
  "module": "./dist/index.mjs",