@node9/proxy 2.3.1 → 2.4.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 +41 -25
  2. package/dist/cli.mjs +202 -186
  3. package/package.json +1 -1
package/dist/cli.js CHANGED
@@ -18303,7 +18303,7 @@ var init_ship = __esm({
18303
18303
  });
18304
18304
 
18305
18305
  // src/policy-snapshot/build.ts
18306
- function buildPolicySnapshot(config, activeShields, overrides, mcpTools = {}, statusEntries = [], syncHealth) {
18306
+ function buildPolicySnapshot(config, activeShields, overrides, mcpTools = {}, statusEntries = [], syncHealth, identity) {
18307
18307
  const p = config.policy;
18308
18308
  const statusByKey = /* @__PURE__ */ new Map();
18309
18309
  for (const s of statusEntries) {
@@ -18372,7 +18372,9 @@ function buildPolicySnapshot(config, activeShields, overrides, mcpTools = {}, st
18372
18372
  lastError: syncHealth.lastError,
18373
18373
  consecutiveFailures: syncHealth.consecutiveFailures
18374
18374
  }
18375
- }
18375
+ },
18376
+ // Machine identity — heals legacy machineId-less keys on the SaaS side.
18377
+ ...identity && { machineId: identity.machineId, platform: identity.platform }
18376
18378
  };
18377
18379
  }
18378
18380
  var MAX_RULES, MAX_EGRESS, MAX_MCP_SERVERS, MAX_MCP_TOOLS;
@@ -18748,6 +18750,34 @@ var init_ship2 = __esm({
18748
18750
  }
18749
18751
  });
18750
18752
 
18753
+ // src/machine-id.ts
18754
+ function getMachineId(homeDir2 = os34.homedir()) {
18755
+ const file = path37.join(homeDir2, ".node9", "machine-id");
18756
+ try {
18757
+ const existing = fs38.readFileSync(file, "utf-8").trim();
18758
+ if (UUID_RE.test(existing)) return existing;
18759
+ } catch {
18760
+ }
18761
+ const id = crypto5.randomUUID();
18762
+ try {
18763
+ fs38.mkdirSync(path37.dirname(file), { recursive: true });
18764
+ fs38.writeFileSync(file, id + "\n", { mode: 384 });
18765
+ } catch {
18766
+ }
18767
+ return id;
18768
+ }
18769
+ var crypto5, fs38, os34, path37, UUID_RE;
18770
+ var init_machine_id = __esm({
18771
+ "src/machine-id.ts"() {
18772
+ "use strict";
18773
+ crypto5 = __toESM(require("crypto"));
18774
+ fs38 = __toESM(require("fs"));
18775
+ os34 = __toESM(require("os"));
18776
+ path37 = __toESM(require("path"));
18777
+ UUID_RE = /^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/;
18778
+ }
18779
+ });
18780
+
18751
18781
  // src/daemon/sync.ts
18752
18782
  function emptySignals3() {
18753
18783
  return {
@@ -19199,7 +19229,10 @@ async function pushPolicySnapshot(creds) {
19199
19229
  resolveMcpStatus(),
19200
19230
  // fleet-ship Step 2: ship this machine's sync health so the dashboard can
19201
19231
  // show "sync failing" badges. readSyncHealth is local (same module, no circular).
19202
- readSyncHealth()
19232
+ readSyncHealth(),
19233
+ // Machine identity — heals legacy machineId-less keys on the SaaS side
19234
+ // (login-v2 duplicate-key fix). getMachineId mints on first need.
19235
+ { machineId: getMachineId(), platform: process.platform }
19203
19236
  );
19204
19237
  await shipPolicySnapshot(body, creds);
19205
19238
  } catch {
@@ -19223,7 +19256,8 @@ async function runPolicyPush() {
19223
19256
  // resolve ${VAR} placeholders — so this push reflects THIS process's env
19224
19257
  // (daemon here, user shell in runPolicyPush); see the P2 design's two-env note.
19225
19258
  resolveMcpStatus(),
19226
- readSyncHealth()
19259
+ readSyncHealth(),
19260
+ { machineId: getMachineId(), platform: process.platform }
19227
19261
  );
19228
19262
  const sent = await shipPolicySnapshot(body, creds);
19229
19263
  return sent ? { ok: true } : { ok: false, reason: "Push failed (network or server error)" };
@@ -19408,6 +19442,7 @@ var init_sync = __esm({
19408
19442
  init_scan_watermark();
19409
19443
  init_state2();
19410
19444
  init_audit();
19445
+ init_machine_id();
19411
19446
  FINDING_TO_SIGNAL3 = {
19412
19447
  dlp: "dlpFindings",
19413
19448
  pii: "piiFindings",
@@ -48382,27 +48417,8 @@ function resolveCloudEndpoint(pathSuffix, override) {
48382
48417
  return PROD_BASE + pathSuffix;
48383
48418
  }
48384
48419
 
48385
- // src/machine-id.ts
48386
- var crypto7 = __toESM(require("crypto"));
48387
- var fs47 = __toESM(require("fs"));
48388
- var os42 = __toESM(require("os"));
48389
- var path45 = __toESM(require("path"));
48390
- var UUID_RE = /^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/;
48391
- function getMachineId(homeDir2 = os42.homedir()) {
48392
- const file = path45.join(homeDir2, ".node9", "machine-id");
48393
- try {
48394
- const existing = fs47.readFileSync(file, "utf-8").trim();
48395
- if (UUID_RE.test(existing)) return existing;
48396
- } catch {
48397
- }
48398
- const id = crypto7.randomUUID();
48399
- try {
48400
- fs47.mkdirSync(path45.dirname(file), { recursive: true });
48401
- fs47.writeFileSync(file, id + "\n", { mode: 384 });
48402
- } catch {
48403
- }
48404
- return id;
48405
- }
48420
+ // src/auth/device-login.ts
48421
+ init_machine_id();
48406
48422
 
48407
48423
  // src/utils/open-browser.ts
48408
48424
  var import_child_process6 = require("child_process");
package/dist/cli.mjs CHANGED
@@ -18300,7 +18300,7 @@ var init_ship = __esm({
18300
18300
  });
18301
18301
 
18302
18302
  // src/policy-snapshot/build.ts
18303
- function buildPolicySnapshot(config, activeShields, overrides, mcpTools = {}, statusEntries = [], syncHealth) {
18303
+ function buildPolicySnapshot(config, activeShields, overrides, mcpTools = {}, statusEntries = [], syncHealth, identity) {
18304
18304
  const p = config.policy;
18305
18305
  const statusByKey = /* @__PURE__ */ new Map();
18306
18306
  for (const s of statusEntries) {
@@ -18369,7 +18369,9 @@ function buildPolicySnapshot(config, activeShields, overrides, mcpTools = {}, st
18369
18369
  lastError: syncHealth.lastError,
18370
18370
  consecutiveFailures: syncHealth.consecutiveFailures
18371
18371
  }
18372
- }
18372
+ },
18373
+ // Machine identity — heals legacy machineId-less keys on the SaaS side.
18374
+ ...identity && { machineId: identity.machineId, platform: identity.platform }
18373
18375
  };
18374
18376
  }
18375
18377
  var MAX_RULES, MAX_EGRESS, MAX_MCP_SERVERS, MAX_MCP_TOOLS;
@@ -18742,11 +18744,39 @@ var init_ship2 = __esm({
18742
18744
  }
18743
18745
  });
18744
18746
 
18747
+ // src/machine-id.ts
18748
+ import * as crypto5 from "crypto";
18749
+ import * as fs38 from "fs";
18750
+ import * as os34 from "os";
18751
+ import * as path37 from "path";
18752
+ function getMachineId(homeDir2 = os34.homedir()) {
18753
+ const file = path37.join(homeDir2, ".node9", "machine-id");
18754
+ try {
18755
+ const existing = fs38.readFileSync(file, "utf-8").trim();
18756
+ if (UUID_RE.test(existing)) return existing;
18757
+ } catch {
18758
+ }
18759
+ const id = crypto5.randomUUID();
18760
+ try {
18761
+ fs38.mkdirSync(path37.dirname(file), { recursive: true });
18762
+ fs38.writeFileSync(file, id + "\n", { mode: 384 });
18763
+ } catch {
18764
+ }
18765
+ return id;
18766
+ }
18767
+ var UUID_RE;
18768
+ var init_machine_id = __esm({
18769
+ "src/machine-id.ts"() {
18770
+ "use strict";
18771
+ UUID_RE = /^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/;
18772
+ }
18773
+ });
18774
+
18745
18775
  // src/daemon/sync.ts
18746
- import fs38 from "fs";
18776
+ import fs39 from "fs";
18747
18777
  import https4 from "https";
18748
- import os34 from "os";
18749
- import path37 from "path";
18778
+ import os35 from "os";
18779
+ import path38 from "path";
18750
18780
  function emptySignals3() {
18751
18781
  return {
18752
18782
  dlpFindings: 0,
@@ -18791,8 +18821,8 @@ function readCredentials() {
18791
18821
  };
18792
18822
  }
18793
18823
  try {
18794
- const credPath = path37.join(os34.homedir(), ".node9", "credentials.json");
18795
- const creds = JSON.parse(fs38.readFileSync(credPath, "utf-8"));
18824
+ const credPath = path38.join(os35.homedir(), ".node9", "credentials.json");
18825
+ const creds = JSON.parse(fs39.readFileSync(credPath, "utf-8"));
18796
18826
  const profileName = process.env.NODE9_PROFILE ?? "default";
18797
18827
  const profile = creds[profileName];
18798
18828
  if (typeof profile?.apiKey === "string" && profile.apiKey.length > 0) {
@@ -18818,7 +18848,7 @@ function readCredentials() {
18818
18848
  }
18819
18849
  function readCachedEtag() {
18820
18850
  try {
18821
- const raw = JSON.parse(fs38.readFileSync(rulesCacheFile(), "utf-8"));
18851
+ const raw = JSON.parse(fs39.readFileSync(rulesCacheFile(), "utf-8"));
18822
18852
  return typeof raw.etag === "string" ? raw.etag : void 0;
18823
18853
  } catch {
18824
18854
  return void 0;
@@ -18826,7 +18856,7 @@ function readCachedEtag() {
18826
18856
  }
18827
18857
  function readCachedSyncIntervalHours() {
18828
18858
  try {
18829
- const raw = JSON.parse(fs38.readFileSync(rulesCacheFile(), "utf-8"));
18859
+ const raw = JSON.parse(fs39.readFileSync(rulesCacheFile(), "utf-8"));
18830
18860
  return typeof raw.syncIntervalHours === "number" ? raw.syncIntervalHours : void 0;
18831
18861
  } catch {
18832
18862
  return void 0;
@@ -18843,7 +18873,7 @@ function effectiveSyncIntervalMs() {
18843
18873
  }
18844
18874
  function readSyncHealth() {
18845
18875
  try {
18846
- const raw = JSON.parse(fs38.readFileSync(syncHealthFile(), "utf-8"));
18876
+ const raw = JSON.parse(fs39.readFileSync(syncHealthFile(), "utf-8"));
18847
18877
  return {
18848
18878
  lastCheckedAt: typeof raw.lastCheckedAt === "string" ? raw.lastCheckedAt : void 0,
18849
18879
  lastChangedAt: typeof raw.lastChangedAt === "string" ? raw.lastChangedAt : void 0,
@@ -18858,17 +18888,17 @@ function readSyncHealth() {
18858
18888
  function writeSyncHealth(h) {
18859
18889
  try {
18860
18890
  const file = syncHealthFile();
18861
- const dir = path37.dirname(file);
18862
- if (!fs38.existsSync(dir)) fs38.mkdirSync(dir, { recursive: true });
18891
+ const dir = path38.dirname(file);
18892
+ if (!fs39.existsSync(dir)) fs39.mkdirSync(dir, { recursive: true });
18863
18893
  const tmp = `${file}.${process.pid}.tmp`;
18864
- fs38.writeFileSync(tmp, JSON.stringify(h, null, 2) + "\n", "utf-8");
18865
- fs38.renameSync(tmp, file);
18894
+ fs39.writeFileSync(tmp, JSON.stringify(h, null, 2) + "\n", "utf-8");
18895
+ fs39.renameSync(tmp, file);
18866
18896
  } catch {
18867
18897
  }
18868
18898
  }
18869
18899
  function readCacheFetchedAt() {
18870
18900
  try {
18871
- const raw = JSON.parse(fs38.readFileSync(rulesCacheFile(), "utf-8"));
18901
+ const raw = JSON.parse(fs39.readFileSync(rulesCacheFile(), "utf-8"));
18872
18902
  return typeof raw.fetchedAt === "string" ? raw.fetchedAt : void 0;
18873
18903
  } catch {
18874
18904
  return void 0;
@@ -19070,13 +19100,13 @@ function extractManagedConfig(body) {
19070
19100
  }
19071
19101
  function sweepStaleTmp(target) {
19072
19102
  try {
19073
- const dir = path37.dirname(target);
19074
- const prefix = `${path37.basename(target)}.`;
19075
- for (const name of fs38.readdirSync(dir)) {
19103
+ const dir = path38.dirname(target);
19104
+ const prefix = `${path38.basename(target)}.`;
19105
+ for (const name of fs39.readdirSync(dir)) {
19076
19106
  if (!name.startsWith(prefix) || !name.endsWith(".tmp")) continue;
19077
- const full = path37.join(dir, name);
19107
+ const full = path38.join(dir, name);
19078
19108
  try {
19079
- if (Date.now() - fs38.statSync(full).mtimeMs > 5 * 60 * 1e3) fs38.unlinkSync(full);
19109
+ if (Date.now() - fs39.statSync(full).mtimeMs > 5 * 60 * 1e3) fs39.unlinkSync(full);
19080
19110
  } catch {
19081
19111
  }
19082
19112
  }
@@ -19178,7 +19208,7 @@ async function pushBlastSnapshot(creds) {
19178
19208
  }
19179
19209
  async function pushPostureSnapshot(creds) {
19180
19210
  try {
19181
- const home = os34.homedir();
19211
+ const home = os35.homedir();
19182
19212
  const result = await runPosture({ home, cwd: home });
19183
19213
  await shipPosture(result, creds);
19184
19214
  } catch {
@@ -19197,7 +19227,10 @@ async function pushPolicySnapshot(creds) {
19197
19227
  resolveMcpStatus(),
19198
19228
  // fleet-ship Step 2: ship this machine's sync health so the dashboard can
19199
19229
  // show "sync failing" badges. readSyncHealth is local (same module, no circular).
19200
- readSyncHealth()
19230
+ readSyncHealth(),
19231
+ // Machine identity — heals legacy machineId-less keys on the SaaS side
19232
+ // (login-v2 duplicate-key fix). getMachineId mints on first need.
19233
+ { machineId: getMachineId(), platform: process.platform }
19201
19234
  );
19202
19235
  await shipPolicySnapshot(body, creds);
19203
19236
  } catch {
@@ -19221,7 +19254,8 @@ async function runPolicyPush() {
19221
19254
  // resolve ${VAR} placeholders — so this push reflects THIS process's env
19222
19255
  // (daemon here, user shell in runPolicyPush); see the P2 design's two-env note.
19223
19256
  resolveMcpStatus(),
19224
- readSyncHealth()
19257
+ readSyncHealth(),
19258
+ { machineId: getMachineId(), platform: process.platform }
19225
19259
  );
19226
19260
  const sent = await shipPolicySnapshot(body, creds);
19227
19261
  return sent ? { ok: true } : { ok: false, reason: "Push failed (network or server error)" };
@@ -19332,7 +19366,7 @@ async function runCloudSync() {
19332
19366
  }
19333
19367
  function getCloudSyncStatus() {
19334
19368
  try {
19335
- const raw = JSON.parse(fs38.readFileSync(rulesCacheFile(), "utf-8"));
19369
+ const raw = JSON.parse(fs39.readFileSync(rulesCacheFile(), "utf-8"));
19336
19370
  if (!Array.isArray(raw.rules) || typeof raw.fetchedAt !== "string") return { cached: false };
19337
19371
  return {
19338
19372
  cached: true,
@@ -19349,7 +19383,7 @@ function getCloudSyncStatus() {
19349
19383
  }
19350
19384
  function getCloudRules() {
19351
19385
  try {
19352
- const raw = JSON.parse(fs38.readFileSync(rulesCacheFile(), "utf-8"));
19386
+ const raw = JSON.parse(fs39.readFileSync(rulesCacheFile(), "utf-8"));
19353
19387
  return Array.isArray(raw.rules) ? raw.rules : null;
19354
19388
  } catch {
19355
19389
  return null;
@@ -19402,6 +19436,7 @@ var init_sync = __esm({
19402
19436
  init_scan_watermark();
19403
19437
  init_state2();
19404
19438
  init_audit();
19439
+ init_machine_id();
19405
19440
  FINDING_TO_SIGNAL3 = {
19406
19441
  dlp: "dlpFindings",
19407
19442
  pii: "piiFindings",
@@ -19414,13 +19449,13 @@ var init_sync = __esm({
19414
19449
  loop: "loops",
19415
19450
  "long-output-redacted": "longOutputRedactions"
19416
19451
  };
19417
- rulesCacheFile = () => path37.join(os34.homedir(), ".node9", "rules-cache.json");
19418
- rulesCacheBackupFile = () => path37.join(os34.homedir(), ".node9", "rules-cache.last-good.json");
19452
+ rulesCacheFile = () => path38.join(os35.homedir(), ".node9", "rules-cache.json");
19453
+ rulesCacheBackupFile = () => path38.join(os35.homedir(), ".node9", "rules-cache.last-good.json");
19419
19454
  DEFAULT_API_URL2 = "https://api.node9.ai/api/v1/intercept/policies/sync";
19420
19455
  DEFAULT_INTERVAL_HOURS = 5;
19421
19456
  MIN_INTERVAL_SECONDS = 15;
19422
19457
  MAX_INTERVAL_SECONDS = 24 * 60 * 60;
19423
- syncHealthFile = () => path37.join(os34.homedir(), ".node9", "sync-health.json");
19458
+ syncHealthFile = () => path38.join(os35.homedir(), ".node9", "sync-health.json");
19424
19459
  STALE_MIN_MS = 3 * 60 * 60 * 1e3;
19425
19460
  STALE_MAX_MS = 24 * 60 * 60 * 1e3;
19426
19461
  STALE_FACTOR = 3;
@@ -19443,26 +19478,26 @@ __export(audit_shipper_exports, {
19443
19478
  startAuditShipper: () => startAuditShipper,
19444
19479
  writeWatermark: () => writeWatermark
19445
19480
  });
19446
- import fs39 from "fs";
19447
- import path38 from "path";
19448
- import os35 from "os";
19449
- import crypto5 from "crypto";
19481
+ import fs40 from "fs";
19482
+ import path39 from "path";
19483
+ import os36 from "os";
19484
+ import crypto6 from "crypto";
19450
19485
  function fileSignature(filePath) {
19451
- const fd = fs39.openSync(filePath, "r");
19486
+ const fd = fs40.openSync(filePath, "r");
19452
19487
  try {
19453
19488
  const buf = Buffer.alloc(512);
19454
- const read2 = fs39.readSync(fd, buf, 0, 512, 0);
19489
+ const read2 = fs40.readSync(fd, buf, 0, 512, 0);
19455
19490
  const slice = buf.subarray(0, read2);
19456
19491
  const nl = slice.indexOf(10);
19457
19492
  const firstLine = nl === -1 ? slice : slice.subarray(0, nl);
19458
- return crypto5.createHash("sha256").update(firstLine).digest("hex").slice(0, 16);
19493
+ return crypto6.createHash("sha256").update(firstLine).digest("hex").slice(0, 16);
19459
19494
  } finally {
19460
- fs39.closeSync(fd);
19495
+ fs40.closeSync(fd);
19461
19496
  }
19462
19497
  }
19463
19498
  function readWatermark(watermarkPath) {
19464
19499
  try {
19465
- const raw = JSON.parse(fs39.readFileSync(watermarkPath, "utf-8"));
19500
+ const raw = JSON.parse(fs40.readFileSync(watermarkPath, "utf-8"));
19466
19501
  if (typeof raw.fileSig === "string" && typeof raw.offset === "number" && raw.offset >= 0)
19467
19502
  return raw;
19468
19503
  } catch {
@@ -19471,8 +19506,8 @@ function readWatermark(watermarkPath) {
19471
19506
  }
19472
19507
  function writeWatermark(watermarkPath, wm) {
19473
19508
  const tmp = `${watermarkPath}.tmp`;
19474
- fs39.writeFileSync(tmp, JSON.stringify(wm));
19475
- fs39.renameSync(tmp, watermarkPath);
19509
+ fs40.writeFileSync(tmp, JSON.stringify(wm));
19510
+ fs40.renameSync(tmp, watermarkPath);
19476
19511
  }
19477
19512
  function buildWireRows(chunk2) {
19478
19513
  const lastNl = chunk2.lastIndexOf(10);
@@ -19550,11 +19585,11 @@ async function shipOnce(deps = {}) {
19550
19585
  if (!creds?.apiKey) return { status: "no-creds", shipped: 0 };
19551
19586
  const endpoint = buildBatchEndpoint(creds.apiUrl);
19552
19587
  if (!endpoint) return { status: "no-creds", shipped: 0 };
19553
- if (!fs39.existsSync(auditLogPath)) return { status: "idle", shipped: 0 };
19588
+ if (!fs40.existsSync(auditLogPath)) return { status: "idle", shipped: 0 };
19554
19589
  let shipped = 0;
19555
19590
  try {
19556
19591
  for (let chunkN = 0; chunkN < MAX_CHUNKS_PER_TICK; chunkN++) {
19557
- const size = fs39.statSync(auditLogPath).size;
19592
+ const size = fs40.statSync(auditLogPath).size;
19558
19593
  if (size === 0) break;
19559
19594
  const sig = fileSignature(auditLogPath);
19560
19595
  const wm = readWatermark(watermarkPath);
@@ -19562,12 +19597,12 @@ async function shipOnce(deps = {}) {
19562
19597
  if (offset >= size) break;
19563
19598
  const toRead = Math.min(size - offset, MAX_CHUNK_BYTES);
19564
19599
  const buf = Buffer.alloc(toRead);
19565
- const fd = fs39.openSync(auditLogPath, "r");
19600
+ const fd = fs40.openSync(auditLogPath, "r");
19566
19601
  let read2;
19567
19602
  try {
19568
- read2 = fs39.readSync(fd, buf, 0, toRead, offset);
19603
+ read2 = fs40.readSync(fd, buf, 0, toRead, offset);
19569
19604
  } finally {
19570
- fs39.closeSync(fd);
19605
+ fs40.closeSync(fd);
19571
19606
  }
19572
19607
  const { rows, consumed } = buildWireRows(buf.subarray(0, read2));
19573
19608
  if (consumed === 0) break;
@@ -19614,8 +19649,8 @@ async function shipOnce(deps = {}) {
19614
19649
  }
19615
19650
  function shipLagBytes(auditLogPath = LOCAL_AUDIT_LOG, watermarkPath = AUDIT_SHIP_WATERMARK) {
19616
19651
  try {
19617
- if (!fs39.existsSync(auditLogPath)) return 0;
19618
- const size = fs39.statSync(auditLogPath).size;
19652
+ if (!fs40.existsSync(auditLogPath)) return 0;
19653
+ const size = fs40.statSync(auditLogPath).size;
19619
19654
  const wm = readWatermark(watermarkPath);
19620
19655
  if (!wm) return size;
19621
19656
  if (wm.fileSig !== fileSignature(auditLogPath)) return size;
@@ -19646,7 +19681,7 @@ var init_audit_shipper = __esm({
19646
19681
  init_config();
19647
19682
  init_sync();
19648
19683
  init_cloud();
19649
- AUDIT_SHIP_WATERMARK = path38.join(os35.homedir(), ".node9", "audit-ship.json");
19684
+ AUDIT_SHIP_WATERMARK = path39.join(os36.homedir(), ".node9", "audit-ship.json");
19650
19685
  DEFAULT_INTERVAL_MS = 2e4;
19651
19686
  MAX_BATCH = 500;
19652
19687
  MAX_CHUNK_BYTES = 4 * 1024 * 1024;
@@ -19716,12 +19751,12 @@ var init_decision = __esm({
19716
19751
  });
19717
19752
 
19718
19753
  // src/daemon/dlp-scanner.ts
19719
- import fs40 from "fs";
19720
- import path39 from "path";
19721
- import os36 from "os";
19754
+ import fs41 from "fs";
19755
+ import path40 from "path";
19756
+ import os37 from "os";
19722
19757
  function loadIndex() {
19723
19758
  try {
19724
- const raw = JSON.parse(fs40.readFileSync(INDEX_FILE, "utf-8"));
19759
+ const raw = JSON.parse(fs41.readFileSync(INDEX_FILE, "utf-8"));
19725
19760
  if (raw && typeof raw === "object" && !Array.isArray(raw)) {
19726
19761
  const r = raw;
19727
19762
  if (r.offsets && typeof r.offsets === "object") return r.offsets;
@@ -19733,63 +19768,63 @@ function loadIndex() {
19733
19768
  }
19734
19769
  function saveIndex(index) {
19735
19770
  try {
19736
- fs40.writeFileSync(INDEX_FILE, JSON.stringify(index), { encoding: "utf-8", mode: 384 });
19771
+ fs41.writeFileSync(INDEX_FILE, JSON.stringify(index), { encoding: "utf-8", mode: 384 });
19737
19772
  } catch {
19738
19773
  }
19739
19774
  }
19740
19775
  function appendAuditEntry(entry) {
19741
19776
  try {
19742
- fs40.appendFileSync(AUDIT_LOG_FILE, JSON.stringify(entry) + "\n");
19777
+ fs41.appendFileSync(AUDIT_LOG_FILE, JSON.stringify(entry) + "\n");
19743
19778
  } catch {
19744
19779
  }
19745
19780
  }
19746
19781
  function runDlpScan() {
19747
- if (!fs40.existsSync(PROJECTS_DIR2)) return;
19782
+ if (!fs41.existsSync(PROJECTS_DIR2)) return;
19748
19783
  const index = loadIndex();
19749
19784
  const seenThisPass = /* @__PURE__ */ new Set();
19750
19785
  const newFindings = [];
19751
19786
  let updated = false;
19752
19787
  let projDirs;
19753
19788
  try {
19754
- projDirs = fs40.readdirSync(PROJECTS_DIR2);
19789
+ projDirs = fs41.readdirSync(PROJECTS_DIR2);
19755
19790
  } catch {
19756
19791
  return;
19757
19792
  }
19758
19793
  for (const proj of projDirs) {
19759
- const projPath = path39.join(PROJECTS_DIR2, proj);
19794
+ const projPath = path40.join(PROJECTS_DIR2, proj);
19760
19795
  try {
19761
- if (!fs40.lstatSync(projPath).isDirectory()) continue;
19762
- const real = fs40.realpathSync(projPath);
19763
- if (!real.startsWith(PROJECTS_DIR2 + path39.sep) && real !== PROJECTS_DIR2) continue;
19796
+ if (!fs41.lstatSync(projPath).isDirectory()) continue;
19797
+ const real = fs41.realpathSync(projPath);
19798
+ if (!real.startsWith(PROJECTS_DIR2 + path40.sep) && real !== PROJECTS_DIR2) continue;
19764
19799
  } catch {
19765
19800
  continue;
19766
19801
  }
19767
19802
  let files;
19768
19803
  try {
19769
- files = fs40.readdirSync(projPath).filter((f) => f.endsWith(".jsonl") && !f.startsWith("agent-"));
19804
+ files = fs41.readdirSync(projPath).filter((f) => f.endsWith(".jsonl") && !f.startsWith("agent-"));
19770
19805
  } catch {
19771
19806
  continue;
19772
19807
  }
19773
19808
  for (const file of files) {
19774
- const filePath = path39.join(projPath, file);
19809
+ const filePath = path40.join(projPath, file);
19775
19810
  const lastOffset = index[filePath] ?? 0;
19776
19811
  let size;
19777
19812
  try {
19778
- size = fs40.statSync(filePath).size;
19813
+ size = fs41.statSync(filePath).size;
19779
19814
  } catch {
19780
19815
  continue;
19781
19816
  }
19782
19817
  if (size <= lastOffset) continue;
19783
19818
  let fd;
19784
19819
  try {
19785
- fd = fs40.openSync(filePath, "r");
19820
+ fd = fs41.openSync(filePath, "r");
19786
19821
  } catch {
19787
19822
  continue;
19788
19823
  }
19789
19824
  try {
19790
19825
  const chunkSize = size - lastOffset;
19791
19826
  const buf = Buffer.alloc(chunkSize);
19792
- fs40.readSync(fd, buf, 0, chunkSize, lastOffset);
19827
+ fs41.readSync(fd, buf, 0, chunkSize, lastOffset);
19793
19828
  const chunk2 = buf.toString("utf-8");
19794
19829
  for (const line of chunk2.split("\n")) {
19795
19830
  if (!line.trim()) continue;
@@ -19809,7 +19844,7 @@ function runDlpScan() {
19809
19844
  if (typeof text !== "string") continue;
19810
19845
  const match = scanText(text);
19811
19846
  if (!match) continue;
19812
- const projLabel = decodeURIComponent(proj).replace(os36.homedir(), "~").slice(0, 40);
19847
+ const projLabel = decodeURIComponent(proj).replace(os37.homedir(), "~").slice(0, 40);
19813
19848
  const ts = entry.timestamp ?? (/* @__PURE__ */ new Date()).toISOString();
19814
19849
  appendAuditEntry({
19815
19850
  ts,
@@ -19836,7 +19871,7 @@ function runDlpScan() {
19836
19871
  updated = true;
19837
19872
  } finally {
19838
19873
  try {
19839
- fs40.closeSync(fd);
19874
+ fs41.closeSync(fd);
19840
19875
  } catch {
19841
19876
  }
19842
19877
  }
@@ -19884,23 +19919,23 @@ var init_dlp_scanner = __esm({
19884
19919
  init_dlp();
19885
19920
  init_native();
19886
19921
  init_state2();
19887
- INDEX_FILE = path39.join(os36.homedir(), ".node9", "dlp-index.json");
19888
- PROJECTS_DIR2 = path39.join(os36.homedir(), ".claude", "projects");
19922
+ INDEX_FILE = path40.join(os37.homedir(), ".node9", "dlp-index.json");
19923
+ PROJECTS_DIR2 = path40.join(os37.homedir(), ".claude", "projects");
19889
19924
  }
19890
19925
  });
19891
19926
 
19892
19927
  // src/daemon/mcp-reconciler.ts
19893
- import fs41 from "fs";
19894
- import path40 from "path";
19895
- import os37 from "os";
19896
- import crypto6 from "crypto";
19928
+ import fs42 from "fs";
19929
+ import path41 from "path";
19930
+ import os38 from "os";
19931
+ import crypto7 from "crypto";
19897
19932
  function idKey(e) {
19898
- const cmdHash = crypto6.createHash("sha256").update(`${e.command} ${e.args.join(" ")}`).digest("hex").slice(0, 16);
19933
+ const cmdHash = crypto7.createHash("sha256").update(`${e.command} ${e.args.join(" ")}`).digest("hex").slice(0, 16);
19899
19934
  return `${e.agent}:${e.name}:${cmdHash}`;
19900
19935
  }
19901
19936
  function loadBaseline() {
19902
19937
  try {
19903
- const raw = JSON.parse(fs41.readFileSync(BASELINE_FILE2, "utf-8"));
19938
+ const raw = JSON.parse(fs42.readFileSync(BASELINE_FILE2, "utf-8"));
19904
19939
  return new Set(Array.isArray(raw) ? raw : []);
19905
19940
  } catch {
19906
19941
  return /* @__PURE__ */ new Set();
@@ -19908,7 +19943,7 @@ function loadBaseline() {
19908
19943
  }
19909
19944
  function saveBaseline(keys) {
19910
19945
  try {
19911
- fs41.writeFileSync(BASELINE_FILE2, JSON.stringify([...keys].slice(-BASELINE_CAP)), {
19946
+ fs42.writeFileSync(BASELINE_FILE2, JSON.stringify([...keys].slice(-BASELINE_CAP)), {
19912
19947
  mode: 384
19913
19948
  });
19914
19949
  } catch {
@@ -20096,7 +20131,7 @@ var init_mcp_reconciler = __esm({
20096
20131
  init_cloud();
20097
20132
  init_audit();
20098
20133
  init_mcp_pin();
20099
- BASELINE_FILE2 = path40.join(os37.homedir(), ".node9", "mcp-baseline.json");
20134
+ BASELINE_FILE2 = path41.join(os38.homedir(), ".node9", "mcp-baseline.json");
20100
20135
  BASELINE_CAP = 500;
20101
20136
  DEFAULT_INTERVAL_MIN = 60;
20102
20137
  DEFAULT_STALE_DAYS = 7;
@@ -20171,22 +20206,22 @@ var init_hook_heal = __esm({
20171
20206
  });
20172
20207
 
20173
20208
  // src/daemon/startup-log.ts
20174
- import fs42 from "fs";
20175
- import path41 from "path";
20176
- import os38 from "os";
20209
+ import fs43 from "fs";
20210
+ import path42 from "path";
20211
+ import os39 from "os";
20177
20212
  function capStartupLog(file) {
20178
20213
  try {
20179
- if (fs42.statSync(file).size > MAX_STARTUP_LOG_BYTES) fs42.truncateSync(file);
20214
+ if (fs43.statSync(file).size > MAX_STARTUP_LOG_BYTES) fs43.truncateSync(file);
20180
20215
  } catch {
20181
20216
  }
20182
20217
  }
20183
20218
  function openStartupLogFd() {
20184
20219
  try {
20185
20220
  const file = DAEMON_STARTUP_LOG();
20186
- const dir = path41.dirname(file);
20187
- if (!fs42.existsSync(dir)) fs42.mkdirSync(dir, { recursive: true });
20221
+ const dir = path42.dirname(file);
20222
+ if (!fs43.existsSync(dir)) fs43.mkdirSync(dir, { recursive: true });
20188
20223
  capStartupLog(file);
20189
- return fs42.openSync(file, "a");
20224
+ return fs43.openSync(file, "a");
20190
20225
  } catch {
20191
20226
  return void 0;
20192
20227
  }
@@ -20202,18 +20237,18 @@ function recordStartupState(outcome, kind, detail) {
20202
20237
  }
20203
20238
  }
20204
20239
  const file = DAEMON_STARTUP_STATE();
20205
- const dir = path41.dirname(file);
20206
- if (!fs42.existsSync(dir)) fs42.mkdirSync(dir, { recursive: true });
20240
+ const dir = path42.dirname(file);
20241
+ if (!fs43.existsSync(dir)) fs43.mkdirSync(dir, { recursive: true });
20207
20242
  const state = { outcome, at: (/* @__PURE__ */ new Date()).toISOString() };
20208
20243
  if (kind) state.kind = kind;
20209
20244
  if (detail) state.detail = detail.slice(0, MAX_DETAIL);
20210
20245
  const tmp = `${file}.${process.pid}.tmp`;
20211
20246
  try {
20212
- fs42.writeFileSync(tmp, JSON.stringify(state), "utf-8");
20213
- fs42.renameSync(tmp, file);
20247
+ fs43.writeFileSync(tmp, JSON.stringify(state), "utf-8");
20248
+ fs43.renameSync(tmp, file);
20214
20249
  } catch (err2) {
20215
20250
  try {
20216
- fs42.unlinkSync(tmp);
20251
+ fs43.unlinkSync(tmp);
20217
20252
  } catch {
20218
20253
  }
20219
20254
  throw err2;
@@ -20223,7 +20258,7 @@ function recordStartupState(outcome, kind, detail) {
20223
20258
  }
20224
20259
  function readStartupState() {
20225
20260
  try {
20226
- const raw = fs42.readFileSync(DAEMON_STARTUP_STATE(), "utf-8");
20261
+ const raw = fs43.readFileSync(DAEMON_STARTUP_STATE(), "utf-8");
20227
20262
  const s = JSON.parse(raw);
20228
20263
  if (!s || typeof s.outcome !== "string" || typeof s.at !== "string") return null;
20229
20264
  return s;
@@ -20258,11 +20293,11 @@ function readStartupCause(maxAgeMs = 24 * 60 * 60 * 1e3) {
20258
20293
  function logDaemonStartup(kind, detail) {
20259
20294
  try {
20260
20295
  const file = DAEMON_STARTUP_LOG();
20261
- const dir = path41.dirname(file);
20262
- if (!fs42.existsSync(dir)) fs42.mkdirSync(dir, { recursive: true });
20296
+ const dir = path42.dirname(file);
20297
+ if (!fs43.existsSync(dir)) fs43.mkdirSync(dir, { recursive: true });
20263
20298
  const line = `[${(/* @__PURE__ */ new Date()).toISOString()}] daemon-startup:${kind}${detail ? ` ${detail}` : ""}
20264
20299
  `;
20265
- fs42.appendFileSync(file, line, "utf-8");
20300
+ fs43.appendFileSync(file, line, "utf-8");
20266
20301
  } catch {
20267
20302
  }
20268
20303
  }
@@ -20270,9 +20305,9 @@ var DAEMON_STARTUP_LOG, MAX_STARTUP_LOG_BYTES, DAEMON_STARTUP_STATE, MAX_DETAIL,
20270
20305
  var init_startup_log = __esm({
20271
20306
  "src/daemon/startup-log.ts"() {
20272
20307
  "use strict";
20273
- DAEMON_STARTUP_LOG = () => path41.join(os38.homedir(), ".node9", "daemon-startup.log");
20308
+ DAEMON_STARTUP_LOG = () => path42.join(os39.homedir(), ".node9", "daemon-startup.log");
20274
20309
  MAX_STARTUP_LOG_BYTES = 256 * 1024;
20275
- DAEMON_STARTUP_STATE = () => path41.join(os38.homedir(), ".node9", "daemon-startup-state.json");
20310
+ DAEMON_STARTUP_STATE = () => path42.join(os39.homedir(), ".node9", "daemon-startup-state.json");
20276
20311
  MAX_DETAIL = 200;
20277
20312
  STARTING_GRACE_MS = 90 * 1e3;
20278
20313
  }
@@ -20280,10 +20315,10 @@ var init_startup_log = __esm({
20280
20315
 
20281
20316
  // src/daemon/server.ts
20282
20317
  import http3 from "http";
20283
- import fs43 from "fs";
20284
- import path42 from "path";
20285
- import os39 from "os";
20286
- import { randomUUID as randomUUID4 } from "crypto";
20318
+ import fs44 from "fs";
20319
+ import path43 from "path";
20320
+ import os40 from "os";
20321
+ import { randomUUID as randomUUID5 } from "crypto";
20287
20322
  import { spawnSync } from "child_process";
20288
20323
  import chalk6 from "chalk";
20289
20324
  function buildDaemonReport(allEntries, period, now) {
@@ -20373,7 +20408,7 @@ function startDaemon() {
20373
20408
  recordStartupState("failed", "startup-throw", err2 instanceof Error ? err2.message : String(err2));
20374
20409
  process.exit(1);
20375
20410
  }
20376
- const internalToken = randomUUID4();
20411
+ const internalToken = randomUUID5();
20377
20412
  const validToken = (req) => req.headers["x-node9-internal"] === internalToken || req.headers["x-node9-token"] === internalToken;
20378
20413
  const startedAt = (/* @__PURE__ */ new Date()).toISOString();
20379
20414
  const IDLE_TIMEOUT_MS = 12 * 60 * 60 * 1e3;
@@ -20385,7 +20420,7 @@ function startDaemon() {
20385
20420
  idleTimer = setTimeout(() => {
20386
20421
  if (autoStarted) {
20387
20422
  try {
20388
- fs43.unlinkSync(DAEMON_PID_FILE);
20423
+ fs44.unlinkSync(DAEMON_PID_FILE);
20389
20424
  } catch {
20390
20425
  }
20391
20426
  }
@@ -20486,7 +20521,7 @@ data: ${JSON.stringify(item.data)}
20486
20521
  cwd,
20487
20522
  localSmartRuleMatched = false
20488
20523
  } = JSON.parse(body);
20489
- const id = fromCLI && typeof activityId === "string" && activityId || randomUUID4();
20524
+ const id = fromCLI && typeof activityId === "string" && activityId || randomUUID5();
20490
20525
  const entry = {
20491
20526
  id,
20492
20527
  toolName,
@@ -20530,7 +20565,7 @@ data: ${JSON.stringify(item.data)}
20530
20565
  mcpServer: entry.mcpServer
20531
20566
  });
20532
20567
  }
20533
- const projectCwd = typeof cwd === "string" && path42.isAbsolute(cwd) ? cwd : void 0;
20568
+ const projectCwd = typeof cwd === "string" && path43.isAbsolute(cwd) ? cwd : void 0;
20534
20569
  const projectConfig = getConfig(projectCwd);
20535
20570
  const browserEnabled = projectConfig.settings.approvers?.browser !== false;
20536
20571
  const terminalEnabled = projectConfig.settings.approvers?.terminal !== false;
@@ -20854,8 +20889,8 @@ data: ${JSON.stringify(item.data)}
20854
20889
  if (!validToken(req)) return res.writeHead(403).end();
20855
20890
  const periodParam = reqUrl.searchParams.get("period") || "7d";
20856
20891
  const period = ["today", "7d", "30d", "month"].includes(periodParam) ? periodParam : "7d";
20857
- const logPath = path42.join(os39.homedir(), ".node9", "audit.log");
20858
- if (!fs43.existsSync(logPath)) {
20892
+ const logPath = path43.join(os40.homedir(), ".node9", "audit.log");
20893
+ if (!fs44.existsSync(logPath)) {
20859
20894
  res.writeHead(200, { "Content-Type": "application/json" });
20860
20895
  return res.end(
20861
20896
  JSON.stringify({
@@ -20868,7 +20903,7 @@ data: ${JSON.stringify(item.data)}
20868
20903
  );
20869
20904
  }
20870
20905
  try {
20871
- const raw = fs43.readFileSync(logPath, "utf-8");
20906
+ const raw = fs44.readFileSync(logPath, "utf-8");
20872
20907
  const allEntries = raw.split("\n").flatMap((line) => {
20873
20908
  if (!line.trim()) return [];
20874
20909
  try {
@@ -21096,7 +21131,7 @@ data: ${JSON.stringify(item.data)}
21096
21131
  args: { toolCount: tools.length, status },
21097
21132
  decision: "mcp-discovered"
21098
21133
  });
21099
- const id = randomUUID4();
21134
+ const id = randomUUID5();
21100
21135
  const entry = {
21101
21136
  id,
21102
21137
  type: "mcp-discovery",
@@ -21275,8 +21310,8 @@ data: ${JSON.stringify(item.data)}
21275
21310
  server.on("error", (e) => {
21276
21311
  if (e.code === "EADDRINUSE") {
21277
21312
  try {
21278
- if (fs43.existsSync(DAEMON_PID_FILE)) {
21279
- const parsed = JSON.parse(fs43.readFileSync(DAEMON_PID_FILE, "utf-8"));
21313
+ if (fs44.existsSync(DAEMON_PID_FILE)) {
21314
+ const parsed = JSON.parse(fs44.readFileSync(DAEMON_PID_FILE, "utf-8"));
21280
21315
  const pid = parsed.pid;
21281
21316
  if (typeof pid !== "number" || !Number.isInteger(pid) || pid <= 0 || pid > 4194304) {
21282
21317
  throw new Error("invalid pid in daemon.pid");
@@ -21290,7 +21325,7 @@ data: ${JSON.stringify(item.data)}
21290
21325
  }
21291
21326
  } catch {
21292
21327
  try {
21293
- fs43.unlinkSync(DAEMON_PID_FILE);
21328
+ fs44.unlinkSync(DAEMON_PID_FILE);
21294
21329
  } catch {
21295
21330
  }
21296
21331
  retryListen();
@@ -21420,15 +21455,15 @@ var init_server = __esm({
21420
21455
  });
21421
21456
 
21422
21457
  // src/daemon/service.ts
21423
- import fs44 from "fs";
21424
- import path43 from "path";
21425
- import os40 from "os";
21458
+ import fs45 from "fs";
21459
+ import path44 from "path";
21460
+ import os41 from "os";
21426
21461
  import { spawnSync as spawnSync2, execFileSync } from "child_process";
21427
21462
  function resolveNode9Binary() {
21428
21463
  try {
21429
21464
  const script = process.argv[1];
21430
- if (typeof script === "string" && path43.isAbsolute(script) && fs44.existsSync(script)) {
21431
- return fs44.realpathSync(script);
21465
+ if (typeof script === "string" && path44.isAbsolute(script) && fs45.existsSync(script)) {
21466
+ return fs45.realpathSync(script);
21432
21467
  }
21433
21468
  } catch {
21434
21469
  }
@@ -21446,11 +21481,11 @@ function xmlEscape(s) {
21446
21481
  return s.replace(/&/g, "&amp;").replace(/</g, "&lt;").replace(/>/g, "&gt;").replace(/"/g, "&quot;");
21447
21482
  }
21448
21483
  function launchdPlist(binaryPath) {
21449
- const logDir = path43.join(os40.homedir(), ".node9");
21484
+ const logDir = path44.join(os41.homedir(), ".node9");
21450
21485
  const nodePath = xmlEscape(process.execPath);
21451
21486
  const scriptPath = xmlEscape(binaryPath);
21452
- const outLog = xmlEscape(path43.join(logDir, "daemon.log"));
21453
- const errLog = xmlEscape(path43.join(logDir, "daemon-error.log"));
21487
+ const outLog = xmlEscape(path44.join(logDir, "daemon.log"));
21488
+ const errLog = xmlEscape(path44.join(logDir, "daemon-error.log"));
21454
21489
  return `<?xml version="1.0" encoding="UTF-8"?>
21455
21490
  <!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
21456
21491
  <plist version="1.0">
@@ -21483,9 +21518,9 @@ function launchdPlist(binaryPath) {
21483
21518
  `;
21484
21519
  }
21485
21520
  function installLaunchd(binaryPath) {
21486
- const dir = path43.dirname(LAUNCHD_PLIST);
21487
- if (!fs44.existsSync(dir)) fs44.mkdirSync(dir, { recursive: true });
21488
- fs44.writeFileSync(LAUNCHD_PLIST, launchdPlist(binaryPath), "utf-8");
21521
+ const dir = path44.dirname(LAUNCHD_PLIST);
21522
+ if (!fs45.existsSync(dir)) fs45.mkdirSync(dir, { recursive: true });
21523
+ fs45.writeFileSync(LAUNCHD_PLIST, launchdPlist(binaryPath), "utf-8");
21489
21524
  spawnSync2("launchctl", ["unload", LAUNCHD_PLIST], { encoding: "utf8" });
21490
21525
  const r = spawnSync2("launchctl", ["load", "-w", LAUNCHD_PLIST], {
21491
21526
  encoding: "utf8",
@@ -21496,13 +21531,13 @@ function installLaunchd(binaryPath) {
21496
21531
  }
21497
21532
  }
21498
21533
  function uninstallLaunchd() {
21499
- if (fs44.existsSync(LAUNCHD_PLIST)) {
21534
+ if (fs45.existsSync(LAUNCHD_PLIST)) {
21500
21535
  spawnSync2("launchctl", ["unload", "-w", LAUNCHD_PLIST], { encoding: "utf8", timeout: 5e3 });
21501
- fs44.unlinkSync(LAUNCHD_PLIST);
21536
+ fs45.unlinkSync(LAUNCHD_PLIST);
21502
21537
  }
21503
21538
  }
21504
21539
  function isLaunchdInstalled() {
21505
- return fs44.existsSync(LAUNCHD_PLIST);
21540
+ return fs45.existsSync(LAUNCHD_PLIST);
21506
21541
  }
21507
21542
  function systemdUnit(binaryPath) {
21508
21543
  return `[Unit]
@@ -21521,12 +21556,12 @@ WantedBy=default.target
21521
21556
  `;
21522
21557
  }
21523
21558
  function installSystemd(binaryPath) {
21524
- if (!fs44.existsSync(SYSTEMD_UNIT_DIR)) {
21525
- fs44.mkdirSync(SYSTEMD_UNIT_DIR, { recursive: true });
21559
+ if (!fs45.existsSync(SYSTEMD_UNIT_DIR)) {
21560
+ fs45.mkdirSync(SYSTEMD_UNIT_DIR, { recursive: true });
21526
21561
  }
21527
- fs44.writeFileSync(SYSTEMD_UNIT, systemdUnit(binaryPath), "utf-8");
21562
+ fs45.writeFileSync(SYSTEMD_UNIT, systemdUnit(binaryPath), "utf-8");
21528
21563
  try {
21529
- execFileSync("loginctl", ["enable-linger", os40.userInfo().username], { timeout: 3e3 });
21564
+ execFileSync("loginctl", ["enable-linger", os41.userInfo().username], { timeout: 3e3 });
21530
21565
  } catch {
21531
21566
  }
21532
21567
  const reload = spawnSync2("systemctl", ["--user", "daemon-reload"], {
@@ -21546,21 +21581,21 @@ function installSystemd(binaryPath) {
21546
21581
  }
21547
21582
  }
21548
21583
  function uninstallSystemd() {
21549
- if (fs44.existsSync(SYSTEMD_UNIT)) {
21584
+ if (fs45.existsSync(SYSTEMD_UNIT)) {
21550
21585
  spawnSync2("systemctl", ["--user", "disable", "--now", "node9-daemon"], {
21551
21586
  encoding: "utf8",
21552
21587
  timeout: 5e3
21553
21588
  });
21554
21589
  spawnSync2("systemctl", ["--user", "daemon-reload"], { encoding: "utf8", timeout: 5e3 });
21555
- fs44.unlinkSync(SYSTEMD_UNIT);
21590
+ fs45.unlinkSync(SYSTEMD_UNIT);
21556
21591
  }
21557
21592
  }
21558
21593
  function isSystemdInstalled() {
21559
- return fs44.existsSync(SYSTEMD_UNIT);
21594
+ return fs45.existsSync(SYSTEMD_UNIT);
21560
21595
  }
21561
- function windowsStartupDir(homeDir2 = os40.homedir()) {
21562
- const appData = process.env.APPDATA || path43.join(homeDir2, "AppData", "Roaming");
21563
- return path43.join(appData, "Microsoft", "Windows", "Start Menu", "Programs", "Startup");
21596
+ function windowsStartupDir(homeDir2 = os41.homedir()) {
21597
+ const appData = process.env.APPDATA || path44.join(homeDir2, "AppData", "Roaming");
21598
+ return path44.join(appData, "Microsoft", "Windows", "Start Menu", "Programs", "Startup");
21564
21599
  }
21565
21600
  function windowsLauncherVbs(nodePath, scriptPath) {
21566
21601
  for (const p of [nodePath, scriptPath]) {
@@ -21577,23 +21612,23 @@ function windowsLauncherVbs(nodePath, scriptPath) {
21577
21612
  }
21578
21613
  function installWindowsStartup(binaryPath) {
21579
21614
  const target = WIN_LAUNCHER();
21580
- const dir = path43.dirname(target);
21581
- if (!fs44.existsSync(dir)) fs44.mkdirSync(dir, { recursive: true });
21582
- fs44.writeFileSync(target, windowsLauncherVbs(process.execPath, binaryPath), "utf-8");
21615
+ const dir = path44.dirname(target);
21616
+ if (!fs45.existsSync(dir)) fs45.mkdirSync(dir, { recursive: true });
21617
+ fs45.writeFileSync(target, windowsLauncherVbs(process.execPath, binaryPath), "utf-8");
21583
21618
  spawnSync2("wscript.exe", ["//B", target], { encoding: "utf8", timeout: 1e4 });
21584
21619
  }
21585
21620
  function uninstallWindowsStartup() {
21586
21621
  const target = WIN_LAUNCHER();
21587
- if (fs44.existsSync(target)) fs44.unlinkSync(target);
21622
+ if (fs45.existsSync(target)) fs45.unlinkSync(target);
21588
21623
  }
21589
21624
  function isWindowsStartupInstalled() {
21590
- return fs44.existsSync(WIN_LAUNCHER());
21625
+ return fs45.existsSync(WIN_LAUNCHER());
21591
21626
  }
21592
21627
  function stopRunningDaemon() {
21593
- const pidFile = path43.join(os40.homedir(), ".node9", "daemon.pid");
21594
- if (!fs44.existsSync(pidFile)) return;
21628
+ const pidFile = path44.join(os41.homedir(), ".node9", "daemon.pid");
21629
+ if (!fs45.existsSync(pidFile)) return;
21595
21630
  try {
21596
- const data = JSON.parse(fs44.readFileSync(pidFile, "utf-8"));
21631
+ const data = JSON.parse(fs45.readFileSync(pidFile, "utf-8"));
21597
21632
  const pid = data.pid;
21598
21633
  const MAX_PID2 = 4194304;
21599
21634
  if (typeof pid === "number" && Number.isInteger(pid) && pid > 0 && pid <= MAX_PID2) {
@@ -21613,7 +21648,7 @@ function stopRunningDaemon() {
21613
21648
  }
21614
21649
  }
21615
21650
  try {
21616
- fs44.unlinkSync(pidFile);
21651
+ fs45.unlinkSync(pidFile);
21617
21652
  } catch {
21618
21653
  }
21619
21654
  } catch {
@@ -21778,21 +21813,21 @@ var init_service = __esm({
21778
21813
  "src/daemon/service.ts"() {
21779
21814
  "use strict";
21780
21815
  LAUNCHD_LABEL = "ai.node9.daemon";
21781
- LAUNCHD_PLIST = path43.join(os40.homedir(), "Library", "LaunchAgents", `${LAUNCHD_LABEL}.plist`);
21782
- SYSTEMD_UNIT_DIR = path43.join(os40.homedir(), ".config", "systemd", "user");
21783
- SYSTEMD_UNIT = path43.join(SYSTEMD_UNIT_DIR, "node9-daemon.service");
21816
+ LAUNCHD_PLIST = path44.join(os41.homedir(), "Library", "LaunchAgents", `${LAUNCHD_LABEL}.plist`);
21817
+ SYSTEMD_UNIT_DIR = path44.join(os41.homedir(), ".config", "systemd", "user");
21818
+ SYSTEMD_UNIT = path44.join(SYSTEMD_UNIT_DIR, "node9-daemon.service");
21784
21819
  STARTUP_FILE = "node9-daemon.vbs";
21785
- WIN_LAUNCHER = () => path43.join(windowsStartupDir(), STARTUP_FILE);
21820
+ WIN_LAUNCHER = () => path44.join(windowsStartupDir(), STARTUP_FILE);
21786
21821
  }
21787
21822
  });
21788
21823
 
21789
21824
  // src/daemon/index.ts
21790
- import fs45 from "fs";
21825
+ import fs46 from "fs";
21791
21826
  import chalk7 from "chalk";
21792
21827
  function stopDaemon() {
21793
- if (!fs45.existsSync(DAEMON_PID_FILE)) return console.log(chalk7.yellow("Not running."));
21828
+ if (!fs46.existsSync(DAEMON_PID_FILE)) return console.log(chalk7.yellow("Not running."));
21794
21829
  try {
21795
- const data = JSON.parse(fs45.readFileSync(DAEMON_PID_FILE, "utf-8"));
21830
+ const data = JSON.parse(fs46.readFileSync(DAEMON_PID_FILE, "utf-8"));
21796
21831
  const pid = data.pid;
21797
21832
  if (typeof pid !== "number" || !Number.isInteger(pid) || pid <= 0 || pid > MAX_PID) {
21798
21833
  console.log(chalk7.gray("Cleaned up invalid PID file."));
@@ -21804,7 +21839,7 @@ function stopDaemon() {
21804
21839
  console.log(chalk7.gray("Cleaned up stale PID file."));
21805
21840
  } finally {
21806
21841
  try {
21807
- fs45.unlinkSync(DAEMON_PID_FILE);
21842
+ fs46.unlinkSync(DAEMON_PID_FILE);
21808
21843
  } catch {
21809
21844
  }
21810
21845
  }
@@ -21813,9 +21848,9 @@ function daemonStatus() {
21813
21848
  const serviceInstalled = isDaemonServiceInstalled();
21814
21849
  const serviceLabel = serviceInstalled ? chalk7.green("installed (starts on login)") : chalk7.yellow("not installed \u2014 run: node9 daemon install");
21815
21850
  let processStatus;
21816
- if (fs45.existsSync(DAEMON_PID_FILE)) {
21851
+ if (fs46.existsSync(DAEMON_PID_FILE)) {
21817
21852
  try {
21818
- const data = JSON.parse(fs45.readFileSync(DAEMON_PID_FILE, "utf-8"));
21853
+ const data = JSON.parse(fs46.readFileSync(DAEMON_PID_FILE, "utf-8"));
21819
21854
  const pid = data.pid;
21820
21855
  const port = data.port;
21821
21856
  if (typeof pid !== "number" || !Number.isInteger(pid) || pid <= 0 || pid > MAX_PID) {
@@ -48192,26 +48227,26 @@ async function runProxy(targetCommand) {
48192
48227
  init_daemon();
48193
48228
  init_startup_log();
48194
48229
  import { spawn as spawn3 } from "child_process";
48195
- import path44 from "path";
48196
- import fs46 from "fs";
48197
- import os41 from "os";
48230
+ import path45 from "path";
48231
+ import fs47 from "fs";
48232
+ import os42 from "os";
48198
48233
  function isTestingMode() {
48199
48234
  return /^(1|true|yes)$/i.test(process.env.NODE9_TESTING ?? "");
48200
48235
  }
48201
- var SKIP_STAMP = () => path44.join(os41.homedir(), ".node9", ".autostart-skip-stamp");
48236
+ var SKIP_STAMP = () => path45.join(os42.homedir(), ".node9", ".autostart-skip-stamp");
48202
48237
  var SKIP_THROTTLE_MS = 60 * 60 * 1e3;
48203
48238
  function logAutostartSkipThrottled(reason) {
48204
48239
  try {
48205
48240
  const stamp = SKIP_STAMP();
48206
48241
  try {
48207
- if (Date.now() - fs46.statSync(stamp).mtimeMs < SKIP_THROTTLE_MS) return;
48242
+ if (Date.now() - fs47.statSync(stamp).mtimeMs < SKIP_THROTTLE_MS) return;
48208
48243
  } catch {
48209
48244
  }
48210
- const dir = path44.join(os41.homedir(), ".node9");
48211
- if (!fs46.existsSync(dir)) fs46.mkdirSync(dir, { recursive: true });
48212
- fs46.writeFileSync(stamp, "", "utf-8");
48213
- fs46.appendFileSync(
48214
- path44.join(dir, "hook-debug.log"),
48245
+ const dir = path45.join(os42.homedir(), ".node9");
48246
+ if (!fs47.existsSync(dir)) fs47.mkdirSync(dir, { recursive: true });
48247
+ fs47.writeFileSync(stamp, "", "utf-8");
48248
+ fs47.appendFileSync(
48249
+ path45.join(dir, "hook-debug.log"),
48215
48250
  `[${(/* @__PURE__ */ new Date()).toISOString()}] daemon-autostart-skip: ${reason}
48216
48251
  `,
48217
48252
  "utf-8"
@@ -48230,10 +48265,10 @@ async function autoStartDaemonAndWait() {
48230
48265
  return true;
48231
48266
  }
48232
48267
  if (isTestingMode()) return false;
48233
- if (!path44.isAbsolute(process.argv[1])) return false;
48268
+ if (!path45.isAbsolute(process.argv[1])) return false;
48234
48269
  let resolvedArgv1;
48235
48270
  try {
48236
- resolvedArgv1 = fs46.realpathSync(process.argv[1]);
48271
+ resolvedArgv1 = fs47.realpathSync(process.argv[1]);
48237
48272
  } catch {
48238
48273
  return false;
48239
48274
  }
@@ -48271,7 +48306,7 @@ async function autoStartDaemonAndWait() {
48271
48306
  } finally {
48272
48307
  if (startupFd !== void 0) {
48273
48308
  try {
48274
- fs46.closeSync(startupFd);
48309
+ fs47.closeSync(startupFd);
48275
48310
  } catch {
48276
48311
  }
48277
48312
  }
@@ -48375,27 +48410,8 @@ function resolveCloudEndpoint(pathSuffix, override) {
48375
48410
  return PROD_BASE + pathSuffix;
48376
48411
  }
48377
48412
 
48378
- // src/machine-id.ts
48379
- import * as crypto7 from "crypto";
48380
- import * as fs47 from "fs";
48381
- import * as os42 from "os";
48382
- import * as path45 from "path";
48383
- var UUID_RE = /^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/;
48384
- function getMachineId(homeDir2 = os42.homedir()) {
48385
- const file = path45.join(homeDir2, ".node9", "machine-id");
48386
- try {
48387
- const existing = fs47.readFileSync(file, "utf-8").trim();
48388
- if (UUID_RE.test(existing)) return existing;
48389
- } catch {
48390
- }
48391
- const id = crypto7.randomUUID();
48392
- try {
48393
- fs47.mkdirSync(path45.dirname(file), { recursive: true });
48394
- fs47.writeFileSync(file, id + "\n", { mode: 384 });
48395
- } catch {
48396
- }
48397
- return id;
48398
- }
48413
+ // src/auth/device-login.ts
48414
+ init_machine_id();
48399
48415
 
48400
48416
  // src/utils/open-browser.ts
48401
48417
  import { spawn as spawn4 } from "child_process";
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@node9/proxy",
3
- "version": "2.3.1",
3
+ "version": "2.4.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",