@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.
- package/dist/cli.js +41 -25
- package/dist/cli.mjs +202 -186
- 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/
|
|
48386
|
-
|
|
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
|
|
18776
|
+
import fs39 from "fs";
|
|
18747
18777
|
import https4 from "https";
|
|
18748
|
-
import
|
|
18749
|
-
import
|
|
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 =
|
|
18795
|
-
const creds = JSON.parse(
|
|
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(
|
|
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(
|
|
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(
|
|
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 =
|
|
18862
|
-
if (!
|
|
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
|
-
|
|
18865
|
-
|
|
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(
|
|
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 =
|
|
19074
|
-
const prefix = `${
|
|
19075
|
-
for (const name of
|
|
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 =
|
|
19107
|
+
const full = path38.join(dir, name);
|
|
19078
19108
|
try {
|
|
19079
|
-
if (Date.now() -
|
|
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 =
|
|
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(
|
|
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(
|
|
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 = () =>
|
|
19418
|
-
rulesCacheBackupFile = () =>
|
|
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 = () =>
|
|
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
|
|
19447
|
-
import
|
|
19448
|
-
import
|
|
19449
|
-
import
|
|
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 =
|
|
19486
|
+
const fd = fs40.openSync(filePath, "r");
|
|
19452
19487
|
try {
|
|
19453
19488
|
const buf = Buffer.alloc(512);
|
|
19454
|
-
const read2 =
|
|
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
|
|
19493
|
+
return crypto6.createHash("sha256").update(firstLine).digest("hex").slice(0, 16);
|
|
19459
19494
|
} finally {
|
|
19460
|
-
|
|
19495
|
+
fs40.closeSync(fd);
|
|
19461
19496
|
}
|
|
19462
19497
|
}
|
|
19463
19498
|
function readWatermark(watermarkPath) {
|
|
19464
19499
|
try {
|
|
19465
|
-
const raw = JSON.parse(
|
|
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
|
-
|
|
19475
|
-
|
|
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 (!
|
|
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 =
|
|
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 =
|
|
19600
|
+
const fd = fs40.openSync(auditLogPath, "r");
|
|
19566
19601
|
let read2;
|
|
19567
19602
|
try {
|
|
19568
|
-
read2 =
|
|
19603
|
+
read2 = fs40.readSync(fd, buf, 0, toRead, offset);
|
|
19569
19604
|
} finally {
|
|
19570
|
-
|
|
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 (!
|
|
19618
|
-
const 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 =
|
|
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
|
|
19720
|
-
import
|
|
19721
|
-
import
|
|
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(
|
|
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
|
-
|
|
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
|
-
|
|
19777
|
+
fs41.appendFileSync(AUDIT_LOG_FILE, JSON.stringify(entry) + "\n");
|
|
19743
19778
|
} catch {
|
|
19744
19779
|
}
|
|
19745
19780
|
}
|
|
19746
19781
|
function runDlpScan() {
|
|
19747
|
-
if (!
|
|
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 =
|
|
19789
|
+
projDirs = fs41.readdirSync(PROJECTS_DIR2);
|
|
19755
19790
|
} catch {
|
|
19756
19791
|
return;
|
|
19757
19792
|
}
|
|
19758
19793
|
for (const proj of projDirs) {
|
|
19759
|
-
const projPath =
|
|
19794
|
+
const projPath = path40.join(PROJECTS_DIR2, proj);
|
|
19760
19795
|
try {
|
|
19761
|
-
if (!
|
|
19762
|
-
const real =
|
|
19763
|
-
if (!real.startsWith(PROJECTS_DIR2 +
|
|
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 =
|
|
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 =
|
|
19809
|
+
const filePath = path40.join(projPath, file);
|
|
19775
19810
|
const lastOffset = index[filePath] ?? 0;
|
|
19776
19811
|
let size;
|
|
19777
19812
|
try {
|
|
19778
|
-
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 =
|
|
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
|
-
|
|
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(
|
|
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
|
-
|
|
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 =
|
|
19888
|
-
PROJECTS_DIR2 =
|
|
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
|
|
19894
|
-
import
|
|
19895
|
-
import
|
|
19896
|
-
import
|
|
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 =
|
|
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(
|
|
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
|
-
|
|
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 =
|
|
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
|
|
20175
|
-
import
|
|
20176
|
-
import
|
|
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 (
|
|
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 =
|
|
20187
|
-
if (!
|
|
20221
|
+
const dir = path42.dirname(file);
|
|
20222
|
+
if (!fs43.existsSync(dir)) fs43.mkdirSync(dir, { recursive: true });
|
|
20188
20223
|
capStartupLog(file);
|
|
20189
|
-
return
|
|
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 =
|
|
20206
|
-
if (!
|
|
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
|
-
|
|
20213
|
-
|
|
20247
|
+
fs43.writeFileSync(tmp, JSON.stringify(state), "utf-8");
|
|
20248
|
+
fs43.renameSync(tmp, file);
|
|
20214
20249
|
} catch (err2) {
|
|
20215
20250
|
try {
|
|
20216
|
-
|
|
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 =
|
|
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 =
|
|
20262
|
-
if (!
|
|
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
|
-
|
|
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 = () =>
|
|
20308
|
+
DAEMON_STARTUP_LOG = () => path42.join(os39.homedir(), ".node9", "daemon-startup.log");
|
|
20274
20309
|
MAX_STARTUP_LOG_BYTES = 256 * 1024;
|
|
20275
|
-
DAEMON_STARTUP_STATE = () =>
|
|
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
|
|
20284
|
-
import
|
|
20285
|
-
import
|
|
20286
|
-
import { randomUUID as
|
|
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 =
|
|
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
|
-
|
|
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 ||
|
|
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" &&
|
|
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 =
|
|
20858
|
-
if (!
|
|
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 =
|
|
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 =
|
|
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 (
|
|
21279
|
-
const parsed = JSON.parse(
|
|
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
|
-
|
|
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
|
|
21424
|
-
import
|
|
21425
|
-
import
|
|
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" &&
|
|
21431
|
-
return
|
|
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, "&").replace(/</g, "<").replace(/>/g, ">").replace(/"/g, """);
|
|
21447
21482
|
}
|
|
21448
21483
|
function launchdPlist(binaryPath) {
|
|
21449
|
-
const logDir =
|
|
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(
|
|
21453
|
-
const errLog = xmlEscape(
|
|
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 =
|
|
21487
|
-
if (!
|
|
21488
|
-
|
|
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 (
|
|
21534
|
+
if (fs45.existsSync(LAUNCHD_PLIST)) {
|
|
21500
21535
|
spawnSync2("launchctl", ["unload", "-w", LAUNCHD_PLIST], { encoding: "utf8", timeout: 5e3 });
|
|
21501
|
-
|
|
21536
|
+
fs45.unlinkSync(LAUNCHD_PLIST);
|
|
21502
21537
|
}
|
|
21503
21538
|
}
|
|
21504
21539
|
function isLaunchdInstalled() {
|
|
21505
|
-
return
|
|
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 (!
|
|
21525
|
-
|
|
21559
|
+
if (!fs45.existsSync(SYSTEMD_UNIT_DIR)) {
|
|
21560
|
+
fs45.mkdirSync(SYSTEMD_UNIT_DIR, { recursive: true });
|
|
21526
21561
|
}
|
|
21527
|
-
|
|
21562
|
+
fs45.writeFileSync(SYSTEMD_UNIT, systemdUnit(binaryPath), "utf-8");
|
|
21528
21563
|
try {
|
|
21529
|
-
execFileSync("loginctl", ["enable-linger",
|
|
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 (
|
|
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
|
-
|
|
21590
|
+
fs45.unlinkSync(SYSTEMD_UNIT);
|
|
21556
21591
|
}
|
|
21557
21592
|
}
|
|
21558
21593
|
function isSystemdInstalled() {
|
|
21559
|
-
return
|
|
21594
|
+
return fs45.existsSync(SYSTEMD_UNIT);
|
|
21560
21595
|
}
|
|
21561
|
-
function windowsStartupDir(homeDir2 =
|
|
21562
|
-
const appData = process.env.APPDATA ||
|
|
21563
|
-
return
|
|
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 =
|
|
21581
|
-
if (!
|
|
21582
|
-
|
|
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 (
|
|
21622
|
+
if (fs45.existsSync(target)) fs45.unlinkSync(target);
|
|
21588
21623
|
}
|
|
21589
21624
|
function isWindowsStartupInstalled() {
|
|
21590
|
-
return
|
|
21625
|
+
return fs45.existsSync(WIN_LAUNCHER());
|
|
21591
21626
|
}
|
|
21592
21627
|
function stopRunningDaemon() {
|
|
21593
|
-
const pidFile =
|
|
21594
|
-
if (!
|
|
21628
|
+
const pidFile = path44.join(os41.homedir(), ".node9", "daemon.pid");
|
|
21629
|
+
if (!fs45.existsSync(pidFile)) return;
|
|
21595
21630
|
try {
|
|
21596
|
-
const data = JSON.parse(
|
|
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
|
-
|
|
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 =
|
|
21782
|
-
SYSTEMD_UNIT_DIR =
|
|
21783
|
-
SYSTEMD_UNIT =
|
|
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 = () =>
|
|
21820
|
+
WIN_LAUNCHER = () => path44.join(windowsStartupDir(), STARTUP_FILE);
|
|
21786
21821
|
}
|
|
21787
21822
|
});
|
|
21788
21823
|
|
|
21789
21824
|
// src/daemon/index.ts
|
|
21790
|
-
import
|
|
21825
|
+
import fs46 from "fs";
|
|
21791
21826
|
import chalk7 from "chalk";
|
|
21792
21827
|
function stopDaemon() {
|
|
21793
|
-
if (!
|
|
21828
|
+
if (!fs46.existsSync(DAEMON_PID_FILE)) return console.log(chalk7.yellow("Not running."));
|
|
21794
21829
|
try {
|
|
21795
|
-
const data = JSON.parse(
|
|
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
|
-
|
|
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 (
|
|
21851
|
+
if (fs46.existsSync(DAEMON_PID_FILE)) {
|
|
21817
21852
|
try {
|
|
21818
|
-
const data = JSON.parse(
|
|
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
|
|
48196
|
-
import
|
|
48197
|
-
import
|
|
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 = () =>
|
|
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() -
|
|
48242
|
+
if (Date.now() - fs47.statSync(stamp).mtimeMs < SKIP_THROTTLE_MS) return;
|
|
48208
48243
|
} catch {
|
|
48209
48244
|
}
|
|
48210
|
-
const dir =
|
|
48211
|
-
if (!
|
|
48212
|
-
|
|
48213
|
-
|
|
48214
|
-
|
|
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 (!
|
|
48268
|
+
if (!path45.isAbsolute(process.argv[1])) return false;
|
|
48234
48269
|
let resolvedArgv1;
|
|
48235
48270
|
try {
|
|
48236
|
-
resolvedArgv1 =
|
|
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
|
-
|
|
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/
|
|
48379
|
-
|
|
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
|
+
"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",
|