@node9/proxy 1.19.2 → 1.19.4
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 +200 -112
- package/dist/cli.mjs +168 -80
- package/dist/dashboard.mjs +4651 -0
- package/dist/index.js +21 -23
- package/dist/index.mjs +17 -19
- package/package.json +4 -1
package/dist/cli.js
CHANGED
|
@@ -1708,7 +1708,11 @@ function extractCanonicalFindings(call, ctx) {
|
|
|
1708
1708
|
})
|
|
1709
1709
|
);
|
|
1710
1710
|
}
|
|
1711
|
-
|
|
1711
|
+
const ast = analyzeShellCommand(command);
|
|
1712
|
+
const sudoVariant = ast.actions.includes("sudo") || ast.actions.includes("su");
|
|
1713
|
+
const chmodVariant = ast.actions.includes("chmod") && (ast.allTokens.includes("777") || ast.allTokens.includes("0777") || ast.allTokens.includes("+x"));
|
|
1714
|
+
const chownVariant = ast.actions.includes("chown") && ast.allTokens.includes("root");
|
|
1715
|
+
if (sudoVariant || chmodVariant || chownVariant) {
|
|
1712
1716
|
out.push(
|
|
1713
1717
|
makeFinding({
|
|
1714
1718
|
type: "privilege-escalation",
|
|
@@ -1840,7 +1844,7 @@ function* stringValues(obj, depth = 0) {
|
|
|
1840
1844
|
}
|
|
1841
1845
|
for (const v of Object.values(obj)) yield* stringValues(v, depth + 1);
|
|
1842
1846
|
}
|
|
1843
|
-
var import_safe_regex2, import_mvdan_sh, import_picomatch, import_safe_regex22, import_safe_regex23, import_crypto2, ASSIGNMENT_CONTEXT_RE, DLP_STOPWORDS, DLP_PATTERNS, DLP_PATTERNS_GLOBAL, SENSITIVE_PATH_PATTERNS, MAX_DEPTH, MAX_STRING_BYTES, MAX_JSON_PARSE_BYTES, syntax, sharedParser, MESSAGE_FLAGS, SHELL_INTERPRETERS, DOWNLOAD_CMDS, NORMALIZE_CACHE_MAX, normalizeCache, AST_CACHE_MAX, astCache, PARSE_FAIL, FS_READ_TOOLS, FS_OP_PRESCREEN_RE, HOME_CACHE_ALLOWLIST, SENSITIVE_PATH_RULES, BASH_TOOL_NAMES, AST_FS_REGEX_RULES, FS_OP_CACHE_MAX, fsOpCache, SOURCE_COMMANDS, SINK_COMMANDS, OBFUSCATORS, SENSITIVE_PATTERNS, FLAGS_WITH_VALUES, MAX_REGEX_LENGTH, REGEX_CACHE_MAX, regexCache, FORBIDDEN_PATH_SEGMENTS, SQL_DML_KEYWORDS, aws_default, bash_safe_default, docker_default, filesystem_default, github_default, k8s_default, mongodb_default, postgres_default, project_jail_default, redis_default, BUILTIN_SHIELDS, LOOP_MAX_RECORDS, FINDING_TO_SIGNAL, SCAN_SIGNAL_WEIGHTS, LOOP_THRESHOLD_FOR_WASTE, COST_PER_LOOP_ITER_USD, DESTRUCTIVE_OP_RE,
|
|
1847
|
+
var import_safe_regex2, import_mvdan_sh, import_picomatch, import_safe_regex22, import_safe_regex23, import_crypto2, ASSIGNMENT_CONTEXT_RE, DLP_STOPWORDS, DLP_PATTERNS, DLP_PATTERNS_GLOBAL, SENSITIVE_PATH_PATTERNS, MAX_DEPTH, MAX_STRING_BYTES, MAX_JSON_PARSE_BYTES, syntax, sharedParser, MESSAGE_FLAGS, SHELL_INTERPRETERS, DOWNLOAD_CMDS, NORMALIZE_CACHE_MAX, normalizeCache, AST_CACHE_MAX, astCache, PARSE_FAIL, FS_READ_TOOLS, FS_OP_PRESCREEN_RE, HOME_CACHE_ALLOWLIST, SENSITIVE_PATH_RULES, BASH_TOOL_NAMES, AST_FS_REGEX_RULES, FS_OP_CACHE_MAX, fsOpCache, SOURCE_COMMANDS, SINK_COMMANDS, OBFUSCATORS, SENSITIVE_PATTERNS, FLAGS_WITH_VALUES, MAX_REGEX_LENGTH, REGEX_CACHE_MAX, regexCache, FORBIDDEN_PATH_SEGMENTS, SQL_DML_KEYWORDS, aws_default, bash_safe_default, docker_default, filesystem_default, github_default, k8s_default, mongodb_default, postgres_default, project_jail_default, redis_default, BUILTIN_SHIELDS, LOOP_MAX_RECORDS, FINDING_TO_SIGNAL, SCAN_SIGNAL_WEIGHTS, LOOP_THRESHOLD_FOR_WASTE, COST_PER_LOOP_ITER_USD, DESTRUCTIVE_OP_RE, SENSITIVE_PATH_RE, FILE_TOOLS, PII_EMAIL_RE, PII_SSN_RE, PII_PHONE_RE, PII_CC_RE, LONG_OUTPUT_THRESHOLD_BYTES, CANONICAL_EXTRACTOR_VERSION, DEDUPE_PREVIEW_LEN, TERMINAL_ESCAPE_RE;
|
|
1844
1848
|
var init_dist = __esm({
|
|
1845
1849
|
"packages/policy-engine/dist/index.mjs"() {
|
|
1846
1850
|
"use strict";
|
|
@@ -3246,7 +3250,6 @@ var init_dist = __esm({
|
|
|
3246
3250
|
LOOP_THRESHOLD_FOR_WASTE = 3;
|
|
3247
3251
|
COST_PER_LOOP_ITER_USD = 6e-3;
|
|
3248
3252
|
DESTRUCTIVE_OP_RE = /\brm\s+-[rRf]+\b|\bDROP\s+(TABLE|DATABASE|COLLECTION|SCHEMA)\b|\bTRUNCATE\s+TABLE\b|\bgit\s+push\s+(--force|-f)\b|\bFLUSHALL\b|\bFLUSHDB\b|\bkubectl\s+delete\b|\bhelm\s+uninstall\b/i;
|
|
3249
|
-
PRIVILEGE_ESCALATION_RE = /\b(sudo|su)\b\s+[a-z]|\bchmod\s+(0?777|\+x)\b|\bchown\s+root\b/i;
|
|
3250
3253
|
SENSITIVE_PATH_RE = /\.aws\/(credentials|config)\b|\.ssh\/(id_rsa|id_ed25519|id_ecdsa|id_dsa)\b|\.env(\.|$|\b)|\.config\/gcloud\/credentials\.db\b|\.docker\/config\.json\b|\.netrc\b|\.npmrc\b|\.node9\/credentials\.json\b/i;
|
|
3251
3254
|
FILE_TOOLS = /* @__PURE__ */ new Set([
|
|
3252
3255
|
"read",
|
|
@@ -3266,7 +3269,7 @@ var init_dist = __esm({
|
|
|
3266
3269
|
PII_PHONE_RE = /\b(?:\+?1[-.\s]?)?\(?\d{3}\)?[-.\s]\d{3}[-.\s]\d{4}\b/;
|
|
3267
3270
|
PII_CC_RE = /\b(?:4\d{3}|5[1-5]\d{2}|3[47]\d{2}|6\d{3})[-\s]?\d{4}[-\s]?\d{4}[-\s]?\d{4}\b/;
|
|
3268
3271
|
LONG_OUTPUT_THRESHOLD_BYTES = 100 * 1024;
|
|
3269
|
-
CANONICAL_EXTRACTOR_VERSION = "canonical-
|
|
3272
|
+
CANONICAL_EXTRACTOR_VERSION = "canonical-v4";
|
|
3270
3273
|
DEDUPE_PREVIEW_LEN = 120;
|
|
3271
3274
|
TERMINAL_ESCAPE_RE = // eslint-disable-next-line no-control-regex
|
|
3272
3275
|
/\x1b\[[0-9;?]*[A-Za-z]|\x1b\][^\x07\x1b]*(?:\x07|\x1b\\)|\x1b[@-_]|[\x00-\x08\x0b\x0c\x0e-\x1f\x7f]/g;
|
|
@@ -4739,19 +4742,16 @@ function isDaemonRunning() {
|
|
|
4739
4742
|
}
|
|
4740
4743
|
return false;
|
|
4741
4744
|
}
|
|
4742
|
-
|
|
4743
|
-
encoding: "utf8",
|
|
4744
|
-
timeout: 300
|
|
4745
|
-
});
|
|
4746
|
-
if (r.status === 0 && (r.stdout ?? "").includes(`:${DAEMON_PORT}`)) return true;
|
|
4747
|
-
return false;
|
|
4745
|
+
return true;
|
|
4748
4746
|
}
|
|
4747
|
+
return false;
|
|
4748
|
+
}
|
|
4749
|
+
async function isDaemonReachable(timeoutMs = 500) {
|
|
4749
4750
|
try {
|
|
4750
|
-
const
|
|
4751
|
-
|
|
4752
|
-
timeout: 300
|
|
4751
|
+
const res = await fetch(`http://${DAEMON_HOST}:${DAEMON_PORT}/settings`, {
|
|
4752
|
+
signal: AbortSignal.timeout(timeoutMs)
|
|
4753
4753
|
});
|
|
4754
|
-
return
|
|
4754
|
+
return res.ok;
|
|
4755
4755
|
} catch {
|
|
4756
4756
|
return false;
|
|
4757
4757
|
}
|
|
@@ -4810,7 +4810,7 @@ async function waitForDaemonDecision(id, signal) {
|
|
|
4810
4810
|
if (signal) signal.removeEventListener("abort", onAbort);
|
|
4811
4811
|
}
|
|
4812
4812
|
}
|
|
4813
|
-
async function notifyDaemonViewer(toolName, args, meta, riskMetadata) {
|
|
4813
|
+
async function notifyDaemonViewer(toolName, args, meta, riskMetadata, activityId, socketActivitySent) {
|
|
4814
4814
|
const base = `http://${DAEMON_HOST}:${DAEMON_PORT}`;
|
|
4815
4815
|
const res = await fetch(`${base}/check`, {
|
|
4816
4816
|
method: "POST",
|
|
@@ -4821,7 +4821,12 @@ async function notifyDaemonViewer(toolName, args, meta, riskMetadata) {
|
|
|
4821
4821
|
slackDelegated: true,
|
|
4822
4822
|
agent: meta?.agent,
|
|
4823
4823
|
mcpServer: meta?.mcpServer,
|
|
4824
|
-
...riskMetadata && { riskMetadata }
|
|
4824
|
+
...riskMetadata && { riskMetadata },
|
|
4825
|
+
// fromCLI=true tells the daemon the CLI already sent the activity
|
|
4826
|
+
// event via socket. Same contract as registerDaemonEntry — without
|
|
4827
|
+
// it the daemon double-emits 'activity' for cloud-enforced flows.
|
|
4828
|
+
fromCLI: socketActivitySent !== false,
|
|
4829
|
+
activityId
|
|
4825
4830
|
}),
|
|
4826
4831
|
signal: AbortSignal.timeout(3e3)
|
|
4827
4832
|
});
|
|
@@ -4890,7 +4895,7 @@ async function resolveViaDaemon(id, decision, internalToken, source) {
|
|
|
4890
4895
|
signal: AbortSignal.timeout(3e3)
|
|
4891
4896
|
});
|
|
4892
4897
|
}
|
|
4893
|
-
var import_fs9, import_net, import_path9, import_os8,
|
|
4898
|
+
var import_fs9, import_net, import_path9, import_os8, ACTIVITY_SOCKET_PATH, DAEMON_PORT, DAEMON_HOST;
|
|
4894
4899
|
var init_daemon = __esm({
|
|
4895
4900
|
"src/auth/daemon.ts"() {
|
|
4896
4901
|
"use strict";
|
|
@@ -4898,7 +4903,6 @@ var init_daemon = __esm({
|
|
|
4898
4903
|
import_net = __toESM(require("net"));
|
|
4899
4904
|
import_path9 = __toESM(require("path"));
|
|
4900
4905
|
import_os8 = __toESM(require("os"));
|
|
4901
|
-
import_child_process = require("child_process");
|
|
4902
4906
|
ACTIVITY_SOCKET_PATH = process.platform === "win32" ? "\\\\.\\pipe\\node9-activity" : import_path9.default.join(import_os8.default.tmpdir(), "node9-activity.sock");
|
|
4903
4907
|
DAEMON_PORT = 7391;
|
|
4904
4908
|
DAEMON_HOST = "127.0.0.1";
|
|
@@ -5098,9 +5102,9 @@ function sendDesktopNotification(title, body) {
|
|
|
5098
5102
|
if (process.platform === "darwin") {
|
|
5099
5103
|
const esc = (s) => s.replace(/\\/g, "\\\\").replace(/"/g, '\\"');
|
|
5100
5104
|
const script = `display notification "${esc(body)}" with title "${esc(title)}"`;
|
|
5101
|
-
(0,
|
|
5105
|
+
(0, import_child_process.spawn)("osascript", ["-e", script], { detached: true, stdio: "ignore" }).unref();
|
|
5102
5106
|
} else if (process.platform === "linux") {
|
|
5103
|
-
(0,
|
|
5107
|
+
(0, import_child_process.spawn)("notify-send", [title, body, "--icon=dialog-warning"], {
|
|
5104
5108
|
detached: true,
|
|
5105
5109
|
stdio: "ignore"
|
|
5106
5110
|
}).unref();
|
|
@@ -5195,7 +5199,7 @@ activate
|
|
|
5195
5199
|
display dialog (item 1 of argv) with title (item 2 of argv) ${buttons}
|
|
5196
5200
|
end tell
|
|
5197
5201
|
end run`;
|
|
5198
|
-
childProcess = (0,
|
|
5202
|
+
childProcess = (0, import_child_process.spawn)("osascript", ["-e", script, "--", message, title]);
|
|
5199
5203
|
} else if (process.platform === "linux") {
|
|
5200
5204
|
const pangoMessage = buildPangoMessage(
|
|
5201
5205
|
toolName,
|
|
@@ -5221,12 +5225,12 @@ end run`;
|
|
|
5221
5225
|
argsList.push("--cancel-label", "Block \u238B");
|
|
5222
5226
|
argsList.push("--extra-button", "Always Allow");
|
|
5223
5227
|
}
|
|
5224
|
-
childProcess = (0,
|
|
5228
|
+
childProcess = (0, import_child_process.spawn)("zenity", argsList);
|
|
5225
5229
|
} else if (process.platform === "win32") {
|
|
5226
5230
|
const b64Msg = Buffer.from(message).toString("base64");
|
|
5227
5231
|
const b64Title = Buffer.from(title).toString("base64");
|
|
5228
5232
|
const ps = `Add-Type -AssemblyName PresentationFramework; $msg = [System.Text.Encoding]::UTF8.GetString([System.Convert]::FromBase64String("${b64Msg}")); $title = [System.Text.Encoding]::UTF8.GetString([System.Convert]::FromBase64String("${b64Title}")); $res = [System.Windows.MessageBox]::Show($msg, $title, "${locked ? "OK" : "YesNo"}", "Warning", "Button2", "DefaultDesktopOnly"); if ($res -eq "Yes") { exit 0 } else { exit 1 }`;
|
|
5229
|
-
childProcess = (0,
|
|
5233
|
+
childProcess = (0, import_child_process.spawn)("powershell", ["-Command", ps]);
|
|
5230
5234
|
}
|
|
5231
5235
|
let output = "";
|
|
5232
5236
|
childProcess?.stdout?.on("data", (d) => output += d.toString());
|
|
@@ -5242,11 +5246,11 @@ end run`;
|
|
|
5242
5246
|
}
|
|
5243
5247
|
});
|
|
5244
5248
|
}
|
|
5245
|
-
var
|
|
5249
|
+
var import_child_process, import_path11, isTestEnv;
|
|
5246
5250
|
var init_native = __esm({
|
|
5247
5251
|
"src/ui/native.ts"() {
|
|
5248
5252
|
"use strict";
|
|
5249
|
-
|
|
5253
|
+
import_child_process = require("child_process");
|
|
5250
5254
|
import_path11 = __toESM(require("path"));
|
|
5251
5255
|
init_context_sniper();
|
|
5252
5256
|
isTestEnv = () => {
|
|
@@ -5967,7 +5971,14 @@ async function _authorizeHeadlessCore(toolName, args, meta, options) {
|
|
|
5967
5971
|
let daemonAllowCount = 1;
|
|
5968
5972
|
if (approvers.terminal && isDaemonRunning() && !options?.calledFromDaemon) {
|
|
5969
5973
|
if (cloudEnforced && cloudRequestId) {
|
|
5970
|
-
const viewer = await notifyDaemonViewer(
|
|
5974
|
+
const viewer = await notifyDaemonViewer(
|
|
5975
|
+
toolName,
|
|
5976
|
+
args,
|
|
5977
|
+
meta,
|
|
5978
|
+
riskMetadata,
|
|
5979
|
+
options?.activityId,
|
|
5980
|
+
options?.socketActivitySent
|
|
5981
|
+
).catch(() => null);
|
|
5971
5982
|
viewerId = viewer?.id ?? null;
|
|
5972
5983
|
daemonEntryId = viewerId;
|
|
5973
5984
|
if (viewer) daemonAllowCount = viewer.allowCount;
|
|
@@ -8060,6 +8071,7 @@ __export(scan_watermark_exports, {
|
|
|
8060
8071
|
markUploadComplete: () => markUploadComplete,
|
|
8061
8072
|
saveWatermark: () => saveWatermark,
|
|
8062
8073
|
scanDelta: () => scanDelta,
|
|
8074
|
+
tickForensicBroadcast: () => tickForensicBroadcast,
|
|
8063
8075
|
tickScanWatcher: () => tickScanWatcher
|
|
8064
8076
|
});
|
|
8065
8077
|
function freshWatermark() {
|
|
@@ -8263,6 +8275,25 @@ function extractFindingsFromLine(line, sessionId, lineIndex) {
|
|
|
8263
8275
|
}
|
|
8264
8276
|
return findings;
|
|
8265
8277
|
}
|
|
8278
|
+
async function tickForensicBroadcast(offsets) {
|
|
8279
|
+
const out = [];
|
|
8280
|
+
const files = listJsonlFiles();
|
|
8281
|
+
for (const file of files) {
|
|
8282
|
+
const size = fileSize(file);
|
|
8283
|
+
const offset = offsets.get(file);
|
|
8284
|
+
if (offset === void 0) {
|
|
8285
|
+
offsets.set(file, size);
|
|
8286
|
+
continue;
|
|
8287
|
+
}
|
|
8288
|
+
if (size <= offset) continue;
|
|
8289
|
+
const sessionId = import_path19.default.basename(file, ".jsonl");
|
|
8290
|
+
const newOffset = await scanDelta(file, offset, (obj, lineIndex) => {
|
|
8291
|
+
out.push(...extractFindingsFromLine(obj, sessionId, lineIndex));
|
|
8292
|
+
});
|
|
8293
|
+
offsets.set(file, newOffset);
|
|
8294
|
+
}
|
|
8295
|
+
return out;
|
|
8296
|
+
}
|
|
8266
8297
|
function markUploadComplete() {
|
|
8267
8298
|
const state = loadWatermark();
|
|
8268
8299
|
if (state.status === "schema-future") return;
|
|
@@ -11031,6 +11062,19 @@ data: ${JSON.stringify(data)}
|
|
|
11031
11062
|
}
|
|
11032
11063
|
});
|
|
11033
11064
|
}
|
|
11065
|
+
function broadcastForensic(finding) {
|
|
11066
|
+
const severity = CRITICAL_FORENSIC_CATEGORIES.has(finding.type) ? "critical" : "warning";
|
|
11067
|
+
const event = {
|
|
11068
|
+
type: "forensic",
|
|
11069
|
+
id: `fnd_${(0, import_crypto6.randomUUID)()}`,
|
|
11070
|
+
ts: Date.now(),
|
|
11071
|
+
sessionId: finding.sessionId,
|
|
11072
|
+
category: finding.type,
|
|
11073
|
+
severity
|
|
11074
|
+
};
|
|
11075
|
+
if (finding.patternName !== void 0) event.patternName = finding.patternName;
|
|
11076
|
+
broadcast("forensic", event);
|
|
11077
|
+
}
|
|
11034
11078
|
function abandonPending() {
|
|
11035
11079
|
setAbandonTimer(null);
|
|
11036
11080
|
pending.forEach((entry, id) => {
|
|
@@ -11214,7 +11258,7 @@ function bindActivitySocket() {
|
|
|
11214
11258
|
});
|
|
11215
11259
|
activitySocketServer = unixServer;
|
|
11216
11260
|
}
|
|
11217
|
-
var import_net2, import_fs21, import_path23, import_os19, import_crypto6, homeDir, DAEMON_PID_FILE, DECISIONS_FILE, AUDIT_LOG_FILE, TRUST_FILE2, GLOBAL_CONFIG_FILE, CREDENTIALS_FILE, INSIGHT_COUNTS_FILE, pending, sseClients, suggestionTracker, taintStore, insightCounts, _abandonTimer, _hadBrowserClient, _daemonServer, daemonRejectionHandlerRegistered, AUTO_DENY_MS, TRUST_DURATIONS, autoStarted, ACTIVITY_SOCKET_PATH2, ACTIVITY_RING_SIZE, activityRing, LARGE_RESPONSE_RING_SIZE, largeResponseRing, cachedScanResult, cachedScanTs, SCAN_CACHE_TTL_MS, SECRET_KEY_RE, INPUT_PRICE_PER_1M, OUTPUT_PRICE_PER_1M, BYTES_PER_TOKEN, WRITE_TOOL_NAMES, ACTIVITY_REBIND_MAX_ATTEMPTS, ACTIVITY_REBIND_WINDOW_MS, ACTIVITY_HEALTH_PROBE_MS, activitySocketServer, activityHealthInterval, activityRebindAttempts, activityCircuitTripped;
|
|
11261
|
+
var import_net2, import_fs21, import_path23, import_os19, import_crypto6, homeDir, DAEMON_PID_FILE, DECISIONS_FILE, AUDIT_LOG_FILE, TRUST_FILE2, GLOBAL_CONFIG_FILE, CREDENTIALS_FILE, INSIGHT_COUNTS_FILE, pending, sseClients, suggestionTracker, taintStore, insightCounts, _abandonTimer, _hadBrowserClient, _daemonServer, daemonRejectionHandlerRegistered, AUTO_DENY_MS, TRUST_DURATIONS, autoStarted, ACTIVITY_SOCKET_PATH2, ACTIVITY_RING_SIZE, activityRing, LARGE_RESPONSE_RING_SIZE, largeResponseRing, cachedScanResult, cachedScanTs, SCAN_CACHE_TTL_MS, SECRET_KEY_RE, INPUT_PRICE_PER_1M, OUTPUT_PRICE_PER_1M, BYTES_PER_TOKEN, CRITICAL_FORENSIC_CATEGORIES, WRITE_TOOL_NAMES, ACTIVITY_REBIND_MAX_ATTEMPTS, ACTIVITY_REBIND_WINDOW_MS, ACTIVITY_HEALTH_PROBE_MS, activitySocketServer, activityHealthInterval, activityRebindAttempts, activityCircuitTripped;
|
|
11218
11262
|
var init_state2 = __esm({
|
|
11219
11263
|
"src/daemon/state.ts"() {
|
|
11220
11264
|
"use strict";
|
|
@@ -11264,6 +11308,11 @@ var init_state2 = __esm({
|
|
|
11264
11308
|
INPUT_PRICE_PER_1M = 3;
|
|
11265
11309
|
OUTPUT_PRICE_PER_1M = 15;
|
|
11266
11310
|
BYTES_PER_TOKEN = 4;
|
|
11311
|
+
CRITICAL_FORENSIC_CATEGORIES = /* @__PURE__ */ new Set([
|
|
11312
|
+
"privilege-escalation",
|
|
11313
|
+
"destructive-op",
|
|
11314
|
+
"eval-of-remote"
|
|
11315
|
+
]);
|
|
11267
11316
|
WRITE_TOOL_NAMES = /* @__PURE__ */ new Set([
|
|
11268
11317
|
"write",
|
|
11269
11318
|
"write_file",
|
|
@@ -11604,7 +11653,26 @@ function startCloudSync() {
|
|
|
11604
11653
|
const recurring = setInterval(() => void syncOnce(), intervalMs);
|
|
11605
11654
|
recurring.unref();
|
|
11606
11655
|
}
|
|
11607
|
-
|
|
11656
|
+
function startForensicBroadcast() {
|
|
11657
|
+
const tick = async () => {
|
|
11658
|
+
try {
|
|
11659
|
+
const findings = await tickForensicBroadcast(forensicBroadcastOffsets);
|
|
11660
|
+
for (const f of findings) broadcastForensic(f);
|
|
11661
|
+
} catch (err2) {
|
|
11662
|
+
const msg = err2 instanceof Error ? err2.message : String(err2);
|
|
11663
|
+
appendToLog(HOOK_DEBUG_LOG, {
|
|
11664
|
+
ts: (/* @__PURE__ */ new Date()).toISOString(),
|
|
11665
|
+
kind: "forensic-broadcast-error",
|
|
11666
|
+
error: msg
|
|
11667
|
+
});
|
|
11668
|
+
}
|
|
11669
|
+
};
|
|
11670
|
+
const initial = setTimeout(() => void tick(), FORENSIC_INITIAL_DELAY_MS);
|
|
11671
|
+
initial.unref();
|
|
11672
|
+
const recurring = setInterval(() => void tick(), FORENSIC_BROADCAST_INTERVAL_MS);
|
|
11673
|
+
recurring.unref();
|
|
11674
|
+
}
|
|
11675
|
+
var import_fs22, import_https2, import_os20, import_path24, FINDING_TO_SIGNAL3, rulesCacheFile, DEFAULT_API_URL, DEFAULT_INTERVAL_HOURS, MIN_INTERVAL_HOURS, FORENSIC_BROADCAST_INTERVAL_MS, FORENSIC_INITIAL_DELAY_MS, forensicBroadcastOffsets;
|
|
11608
11676
|
var init_sync = __esm({
|
|
11609
11677
|
"src/daemon/sync.ts"() {
|
|
11610
11678
|
"use strict";
|
|
@@ -11616,6 +11684,8 @@ var init_sync = __esm({
|
|
|
11616
11684
|
init_blast();
|
|
11617
11685
|
init_dist();
|
|
11618
11686
|
init_scan_watermark();
|
|
11687
|
+
init_state2();
|
|
11688
|
+
init_audit();
|
|
11619
11689
|
FINDING_TO_SIGNAL3 = {
|
|
11620
11690
|
dlp: "dlpFindings",
|
|
11621
11691
|
pii: "piiFindings",
|
|
@@ -11632,6 +11702,9 @@ var init_sync = __esm({
|
|
|
11632
11702
|
DEFAULT_API_URL = "https://api.node9.ai/api/v1/intercept/policies/sync";
|
|
11633
11703
|
DEFAULT_INTERVAL_HOURS = 5;
|
|
11634
11704
|
MIN_INTERVAL_HOURS = 1;
|
|
11705
|
+
FORENSIC_BROADCAST_INTERVAL_MS = 3e4;
|
|
11706
|
+
FORENSIC_INITIAL_DELAY_MS = 5e3;
|
|
11707
|
+
forensicBroadcastOffsets = /* @__PURE__ */ new Map();
|
|
11635
11708
|
}
|
|
11636
11709
|
});
|
|
11637
11710
|
|
|
@@ -11859,6 +11932,7 @@ var init_mcp_tools = __esm({
|
|
|
11859
11932
|
function startDaemon() {
|
|
11860
11933
|
startCostSync();
|
|
11861
11934
|
startCloudSync();
|
|
11935
|
+
startForensicBroadcast();
|
|
11862
11936
|
startDlpScanner();
|
|
11863
11937
|
loadInsightCounts();
|
|
11864
11938
|
const internalToken = (0, import_crypto7.randomUUID)();
|
|
@@ -12664,13 +12738,26 @@ data: ${JSON.stringify(item.data)}
|
|
|
12664
12738
|
}).then((res) => {
|
|
12665
12739
|
if (res.ok) {
|
|
12666
12740
|
try {
|
|
12667
|
-
|
|
12741
|
+
let orphanPid = null;
|
|
12742
|
+
const ss = (0, import_child_process2.spawnSync)("ss", ["-Htnp", `sport = :${DAEMON_PORT}`], {
|
|
12668
12743
|
encoding: "utf8",
|
|
12669
12744
|
timeout: 1e3
|
|
12670
12745
|
});
|
|
12671
|
-
|
|
12672
|
-
|
|
12673
|
-
|
|
12746
|
+
if (!ss.error && ss.status === 0) {
|
|
12747
|
+
const m = ss.stdout?.match(/pid=(\d+)/);
|
|
12748
|
+
if (m) orphanPid = parseInt(m[1], 10);
|
|
12749
|
+
} else if (ss.error?.code === "ENOENT" || ss.status === null) {
|
|
12750
|
+
const lsof = (0, import_child_process2.spawnSync)(
|
|
12751
|
+
"lsof",
|
|
12752
|
+
["-nP", `-iTCP:${DAEMON_PORT}`, "-sTCP:LISTEN", "-t"],
|
|
12753
|
+
{ encoding: "utf8", timeout: 1e3 }
|
|
12754
|
+
);
|
|
12755
|
+
if (!lsof.error && lsof.status === 0) {
|
|
12756
|
+
const first = (lsof.stdout ?? "").split("\n")[0].trim();
|
|
12757
|
+
if (/^\d+$/.test(first)) orphanPid = parseInt(first, 10);
|
|
12758
|
+
}
|
|
12759
|
+
}
|
|
12760
|
+
if (orphanPid !== null) {
|
|
12674
12761
|
process.kill(orphanPid, 0);
|
|
12675
12762
|
atomicWriteSync2(
|
|
12676
12763
|
DAEMON_PID_FILE,
|
|
@@ -12705,14 +12792,14 @@ data: ${JSON.stringify(item.data)}
|
|
|
12705
12792
|
JSON.stringify({ pid: process.pid, port: DAEMON_PORT, internalToken, autoStarted }),
|
|
12706
12793
|
{ mode: 384 }
|
|
12707
12794
|
);
|
|
12708
|
-
console.error(import_chalk6.default.green(`\u{1F6E1}\uFE0F Node9 Guard LIVE
|
|
12795
|
+
console.error(import_chalk6.default.green(`\u{1F6E1}\uFE0F Node9 Guard LIVE on 127.0.0.1:${DAEMON_PORT}`));
|
|
12709
12796
|
});
|
|
12710
12797
|
if (watchMode) {
|
|
12711
12798
|
console.error(import_chalk6.default.cyan("\u{1F6F0}\uFE0F Flight Recorder active \u2014 daemon will not idle-timeout"));
|
|
12712
12799
|
}
|
|
12713
12800
|
startActivitySocket();
|
|
12714
12801
|
}
|
|
12715
|
-
var import_http, import_fs25, import_path27, import_os23, import_crypto7,
|
|
12802
|
+
var import_http, import_fs25, import_path27, import_os23, import_crypto7, import_child_process2, import_chalk6;
|
|
12716
12803
|
var init_server = __esm({
|
|
12717
12804
|
"src/daemon/server.ts"() {
|
|
12718
12805
|
"use strict";
|
|
@@ -12721,7 +12808,7 @@ var init_server = __esm({
|
|
|
12721
12808
|
import_path27 = __toESM(require("path"));
|
|
12722
12809
|
import_os23 = __toESM(require("os"));
|
|
12723
12810
|
import_crypto7 = require("crypto");
|
|
12724
|
-
|
|
12811
|
+
import_child_process2 = require("child_process");
|
|
12725
12812
|
import_chalk6 = __toESM(require("chalk"));
|
|
12726
12813
|
init_core();
|
|
12727
12814
|
init_scan();
|
|
@@ -12746,7 +12833,7 @@ function resolveNode9Binary() {
|
|
|
12746
12833
|
}
|
|
12747
12834
|
try {
|
|
12748
12835
|
const cmd = process.platform === "win32" ? "where" : "which";
|
|
12749
|
-
const r = (0,
|
|
12836
|
+
const r = (0, import_child_process3.spawnSync)(cmd, ["node9"], { encoding: "utf8", timeout: 3e3 });
|
|
12750
12837
|
if (r.status === 0 && r.stdout.trim()) {
|
|
12751
12838
|
return r.stdout.trim().split("\n")[0].trim();
|
|
12752
12839
|
}
|
|
@@ -12798,8 +12885,8 @@ function installLaunchd(binaryPath) {
|
|
|
12798
12885
|
const dir = import_path28.default.dirname(LAUNCHD_PLIST);
|
|
12799
12886
|
if (!import_fs26.default.existsSync(dir)) import_fs26.default.mkdirSync(dir, { recursive: true });
|
|
12800
12887
|
import_fs26.default.writeFileSync(LAUNCHD_PLIST, launchdPlist(binaryPath), "utf-8");
|
|
12801
|
-
(0,
|
|
12802
|
-
const r = (0,
|
|
12888
|
+
(0, import_child_process3.spawnSync)("launchctl", ["unload", LAUNCHD_PLIST], { encoding: "utf8" });
|
|
12889
|
+
const r = (0, import_child_process3.spawnSync)("launchctl", ["load", "-w", LAUNCHD_PLIST], {
|
|
12803
12890
|
encoding: "utf8",
|
|
12804
12891
|
timeout: 5e3
|
|
12805
12892
|
});
|
|
@@ -12809,7 +12896,7 @@ function installLaunchd(binaryPath) {
|
|
|
12809
12896
|
}
|
|
12810
12897
|
function uninstallLaunchd() {
|
|
12811
12898
|
if (import_fs26.default.existsSync(LAUNCHD_PLIST)) {
|
|
12812
|
-
(0,
|
|
12899
|
+
(0, import_child_process3.spawnSync)("launchctl", ["unload", "-w", LAUNCHD_PLIST], { encoding: "utf8", timeout: 5e3 });
|
|
12813
12900
|
import_fs26.default.unlinkSync(LAUNCHD_PLIST);
|
|
12814
12901
|
}
|
|
12815
12902
|
}
|
|
@@ -12838,18 +12925,18 @@ function installSystemd(binaryPath) {
|
|
|
12838
12925
|
}
|
|
12839
12926
|
import_fs26.default.writeFileSync(SYSTEMD_UNIT, systemdUnit(binaryPath), "utf-8");
|
|
12840
12927
|
try {
|
|
12841
|
-
(0,
|
|
12928
|
+
(0, import_child_process3.execFileSync)("loginctl", ["enable-linger", import_os24.default.userInfo().username], { timeout: 3e3 });
|
|
12842
12929
|
} catch {
|
|
12843
12930
|
}
|
|
12844
|
-
const reload = (0,
|
|
12931
|
+
const reload = (0, import_child_process3.spawnSync)("systemctl", ["--user", "daemon-reload"], {
|
|
12845
12932
|
encoding: "utf8",
|
|
12846
12933
|
timeout: 5e3
|
|
12847
12934
|
});
|
|
12848
12935
|
if (reload.status !== 0) {
|
|
12849
12936
|
throw new Error(`systemctl daemon-reload failed: ${reload.stderr}`);
|
|
12850
12937
|
}
|
|
12851
|
-
(0,
|
|
12852
|
-
const enable = (0,
|
|
12938
|
+
(0, import_child_process3.spawnSync)("systemctl", ["--user", "stop", "node9-daemon"], { encoding: "utf8", timeout: 3e3 });
|
|
12939
|
+
const enable = (0, import_child_process3.spawnSync)("systemctl", ["--user", "enable", "--now", "node9-daemon"], {
|
|
12853
12940
|
encoding: "utf8",
|
|
12854
12941
|
timeout: 5e3
|
|
12855
12942
|
});
|
|
@@ -12859,11 +12946,11 @@ function installSystemd(binaryPath) {
|
|
|
12859
12946
|
}
|
|
12860
12947
|
function uninstallSystemd() {
|
|
12861
12948
|
if (import_fs26.default.existsSync(SYSTEMD_UNIT)) {
|
|
12862
|
-
(0,
|
|
12949
|
+
(0, import_child_process3.spawnSync)("systemctl", ["--user", "disable", "--now", "node9-daemon"], {
|
|
12863
12950
|
encoding: "utf8",
|
|
12864
12951
|
timeout: 5e3
|
|
12865
12952
|
});
|
|
12866
|
-
(0,
|
|
12953
|
+
(0, import_child_process3.spawnSync)("systemctl", ["--user", "daemon-reload"], { encoding: "utf8", timeout: 5e3 });
|
|
12867
12954
|
import_fs26.default.unlinkSync(SYSTEMD_UNIT);
|
|
12868
12955
|
}
|
|
12869
12956
|
}
|
|
@@ -12881,7 +12968,7 @@ function stopRunningDaemon() {
|
|
|
12881
12968
|
try {
|
|
12882
12969
|
process.kill(pid, "SIGTERM");
|
|
12883
12970
|
const deadline = Date.now() + 3e3;
|
|
12884
|
-
const pollStop = (0,
|
|
12971
|
+
const pollStop = (0, import_child_process3.spawnSync)(
|
|
12885
12972
|
"sh",
|
|
12886
12973
|
["-c", `while kill -0 ${pid} 2>/dev/null; do sleep 0.1; done`],
|
|
12887
12974
|
{
|
|
@@ -12913,7 +13000,7 @@ function installDaemonService() {
|
|
|
12913
13000
|
return { ok: true, platform: "launchd", alreadyInstalled };
|
|
12914
13001
|
}
|
|
12915
13002
|
if (process.platform === "linux") {
|
|
12916
|
-
const check = (0,
|
|
13003
|
+
const check = (0, import_child_process3.spawnSync)("systemctl", ["--user", "--version"], {
|
|
12917
13004
|
encoding: "utf8",
|
|
12918
13005
|
timeout: 2e3
|
|
12919
13006
|
});
|
|
@@ -12964,14 +13051,14 @@ function isDaemonServiceInstalled() {
|
|
|
12964
13051
|
if (process.platform === "linux") return isSystemdInstalled();
|
|
12965
13052
|
return false;
|
|
12966
13053
|
}
|
|
12967
|
-
var import_fs26, import_path28, import_os24,
|
|
13054
|
+
var import_fs26, import_path28, import_os24, import_child_process3, LAUNCHD_LABEL, LAUNCHD_PLIST, SYSTEMD_UNIT_DIR, SYSTEMD_UNIT;
|
|
12968
13055
|
var init_service = __esm({
|
|
12969
13056
|
"src/daemon/service.ts"() {
|
|
12970
13057
|
"use strict";
|
|
12971
13058
|
import_fs26 = __toESM(require("fs"));
|
|
12972
13059
|
import_path28 = __toESM(require("path"));
|
|
12973
13060
|
import_os24 = __toESM(require("os"));
|
|
12974
|
-
|
|
13061
|
+
import_child_process3 = require("child_process");
|
|
12975
13062
|
LAUNCHD_LABEL = "ai.node9.daemon";
|
|
12976
13063
|
LAUNCHD_PLIST = import_path28.default.join(import_os24.default.homedir(), "Library", "LaunchAgents", `${LAUNCHD_LABEL}.plist`);
|
|
12977
13064
|
SYSTEMD_UNIT_DIR = import_path28.default.join(import_os24.default.homedir(), ".config", "systemd", "user");
|
|
@@ -13021,28 +13108,19 @@ function daemonStatus() {
|
|
|
13021
13108
|
processStatus = import_chalk7.default.yellow("not running (stale PID file)");
|
|
13022
13109
|
}
|
|
13023
13110
|
} else {
|
|
13024
|
-
|
|
13025
|
-
encoding: "utf8",
|
|
13026
|
-
timeout: 500
|
|
13027
|
-
});
|
|
13028
|
-
if (r.status === 0 && (r.stdout ?? "").includes(`:${DAEMON_PORT}`)) {
|
|
13029
|
-
processStatus = import_chalk7.default.yellow(`running (orphaned \u2014 no PID file)`);
|
|
13030
|
-
} else {
|
|
13031
|
-
processStatus = import_chalk7.default.yellow("not running");
|
|
13032
|
-
}
|
|
13111
|
+
processStatus = import_chalk7.default.yellow("not running");
|
|
13033
13112
|
}
|
|
13034
13113
|
console.log(`
|
|
13035
13114
|
Process : ${processStatus}`);
|
|
13036
13115
|
console.log(` Service : ${serviceLabel}
|
|
13037
13116
|
`);
|
|
13038
13117
|
}
|
|
13039
|
-
var import_fs27, import_chalk7,
|
|
13118
|
+
var import_fs27, import_chalk7, MAX_PID;
|
|
13040
13119
|
var init_daemon2 = __esm({
|
|
13041
13120
|
"src/daemon/index.ts"() {
|
|
13042
13121
|
"use strict";
|
|
13043
13122
|
import_fs27 = __toESM(require("fs"));
|
|
13044
13123
|
import_chalk7 = __toESM(require("chalk"));
|
|
13045
|
-
import_child_process5 = require("child_process");
|
|
13046
13124
|
init_server();
|
|
13047
13125
|
init_state2();
|
|
13048
13126
|
init_service();
|
|
@@ -13219,7 +13297,7 @@ async function ensureDaemon() {
|
|
|
13219
13297
|
} catch {
|
|
13220
13298
|
}
|
|
13221
13299
|
console.log(import_chalk30.default.dim("\u{1F6E1}\uFE0F Starting Node9 daemon..."));
|
|
13222
|
-
const child = (0,
|
|
13300
|
+
const child = (0, import_child_process13.spawn)(process.execPath, [process.argv[1], "daemon"], {
|
|
13223
13301
|
detached: true,
|
|
13224
13302
|
stdio: "ignore",
|
|
13225
13303
|
env: { ...process.env, NODE9_AUTO_STARTED: "1" }
|
|
@@ -13849,7 +13927,7 @@ async function startTail(options = {}) {
|
|
|
13849
13927
|
process.exit(1);
|
|
13850
13928
|
});
|
|
13851
13929
|
}
|
|
13852
|
-
var import_http2, import_chalk30, import_fs45, import_os41, import_path47, import_readline6,
|
|
13930
|
+
var import_http2, import_chalk30, import_fs45, import_os41, import_path47, import_readline6, import_child_process13, PID_FILE, ICONS, MODEL_CONTEXT_LIMITS, RESET2, BOLD2, RED, YELLOW, CYAN, GRAY, GREEN, HIDE_CURSOR, SHOW_CURSOR, ERASE_DOWN, pendingShownForId, pendingWrappedLines, DIVIDER;
|
|
13853
13931
|
var init_tail = __esm({
|
|
13854
13932
|
"src/tui/tail.ts"() {
|
|
13855
13933
|
"use strict";
|
|
@@ -13859,7 +13937,7 @@ var init_tail = __esm({
|
|
|
13859
13937
|
import_os41 = __toESM(require("os"));
|
|
13860
13938
|
import_path47 = __toESM(require("path"));
|
|
13861
13939
|
import_readline6 = __toESM(require("readline"));
|
|
13862
|
-
|
|
13940
|
+
import_child_process13 = require("child_process");
|
|
13863
13941
|
init_daemon2();
|
|
13864
13942
|
init_daemon();
|
|
13865
13943
|
PID_FILE = import_path47.default.join(import_os41.default.homedir(), ".node9", "daemon.pid");
|
|
@@ -14315,7 +14393,7 @@ function parseDuration(str) {
|
|
|
14315
14393
|
// src/proxy/index.ts
|
|
14316
14394
|
var import_readline2 = __toESM(require("readline"));
|
|
14317
14395
|
var import_chalk8 = __toESM(require("chalk"));
|
|
14318
|
-
var
|
|
14396
|
+
var import_child_process4 = require("child_process");
|
|
14319
14397
|
var import_execa = require("execa");
|
|
14320
14398
|
var import_execa2 = require("execa");
|
|
14321
14399
|
init_orchestrator();
|
|
@@ -14403,11 +14481,11 @@ async function runProxy(targetCommand) {
|
|
|
14403
14481
|
}
|
|
14404
14482
|
console.error(import_chalk8.default.green(`\u{1F680} Node9 Proxy Active: Monitoring [${targetCommand}]`));
|
|
14405
14483
|
const spawnEnv = { ...process.env, FORCE_COLOR: "1" };
|
|
14406
|
-
const child = useShell ? (0,
|
|
14484
|
+
const child = useShell ? (0, import_child_process4.spawn)("/bin/bash", ["-c", targetCommand], {
|
|
14407
14485
|
stdio: ["pipe", "pipe", "inherit"],
|
|
14408
14486
|
shell: false,
|
|
14409
14487
|
env: spawnEnv
|
|
14410
|
-
}) : (0,
|
|
14488
|
+
}) : (0, import_child_process4.spawn)(executable, args, { stdio: ["pipe", "pipe", "inherit"], shell: false, env: spawnEnv });
|
|
14411
14489
|
const agentIn = import_readline2.default.createInterface({ input: process.stdin, terminal: false });
|
|
14412
14490
|
agentIn.on("line", async (line) => {
|
|
14413
14491
|
let message;
|
|
@@ -14471,7 +14549,7 @@ async function runProxy(targetCommand) {
|
|
|
14471
14549
|
}
|
|
14472
14550
|
|
|
14473
14551
|
// src/cli/daemon-starter.ts
|
|
14474
|
-
var
|
|
14552
|
+
var import_child_process5 = require("child_process");
|
|
14475
14553
|
var import_path29 = __toESM(require("path"));
|
|
14476
14554
|
var import_fs28 = __toESM(require("fs"));
|
|
14477
14555
|
init_daemon();
|
|
@@ -14489,7 +14567,7 @@ async function autoStartDaemonAndWait() {
|
|
|
14489
14567
|
}
|
|
14490
14568
|
if (!resolvedArgv1.endsWith(".js")) return false;
|
|
14491
14569
|
try {
|
|
14492
|
-
const child = (0,
|
|
14570
|
+
const child = (0, import_child_process5.spawn)(process.execPath, [resolvedArgv1, "daemon"], {
|
|
14493
14571
|
detached: true,
|
|
14494
14572
|
stdio: "ignore",
|
|
14495
14573
|
env: {
|
|
@@ -14501,13 +14579,7 @@ async function autoStartDaemonAndWait() {
|
|
|
14501
14579
|
for (let i = 0; i < 20; i++) {
|
|
14502
14580
|
await new Promise((r) => setTimeout(r, 250));
|
|
14503
14581
|
if (!isDaemonRunning()) continue;
|
|
14504
|
-
|
|
14505
|
-
const res = await fetch(`http://${DAEMON_HOST}:${DAEMON_PORT}/settings`, {
|
|
14506
|
-
signal: AbortSignal.timeout(500)
|
|
14507
|
-
});
|
|
14508
|
-
if (res.ok) return true;
|
|
14509
|
-
} catch {
|
|
14510
|
-
}
|
|
14582
|
+
if (await isDaemonReachable()) return true;
|
|
14511
14583
|
}
|
|
14512
14584
|
} catch {
|
|
14513
14585
|
}
|
|
@@ -14517,7 +14589,7 @@ async function autoStartDaemonAndWait() {
|
|
|
14517
14589
|
// src/cli/commands/check.ts
|
|
14518
14590
|
var import_chalk9 = __toESM(require("chalk"));
|
|
14519
14591
|
var import_fs31 = __toESM(require("fs"));
|
|
14520
|
-
var
|
|
14592
|
+
var import_child_process7 = require("child_process");
|
|
14521
14593
|
var import_path32 = __toESM(require("path"));
|
|
14522
14594
|
var import_os27 = __toESM(require("os"));
|
|
14523
14595
|
init_orchestrator();
|
|
@@ -14526,7 +14598,7 @@ init_config();
|
|
|
14526
14598
|
init_policy();
|
|
14527
14599
|
|
|
14528
14600
|
// src/undo.ts
|
|
14529
|
-
var
|
|
14601
|
+
var import_child_process6 = require("child_process");
|
|
14530
14602
|
var import_crypto8 = __toESM(require("crypto"));
|
|
14531
14603
|
var import_fs29 = __toESM(require("fs"));
|
|
14532
14604
|
var import_net3 = __toESM(require("net"));
|
|
@@ -14639,7 +14711,7 @@ function ensureShadowRepo(shadowDir, cwd) {
|
|
|
14639
14711
|
cleanOrphanedIndexFiles(shadowDir);
|
|
14640
14712
|
const normalizedCwd = normalizeCwdForHash(cwd);
|
|
14641
14713
|
const shadowEnvBase = { ...process.env, GIT_DIR: shadowDir, GIT_WORK_TREE: cwd };
|
|
14642
|
-
const check = (0,
|
|
14714
|
+
const check = (0, import_child_process6.spawnSync)("git", ["rev-parse", "--git-dir"], {
|
|
14643
14715
|
env: shadowEnvBase,
|
|
14644
14716
|
timeout: 3e3
|
|
14645
14717
|
});
|
|
@@ -14665,17 +14737,17 @@ function ensureShadowRepo(shadowDir, cwd) {
|
|
|
14665
14737
|
import_fs29.default.mkdirSync(shadowDir, { recursive: true });
|
|
14666
14738
|
} catch {
|
|
14667
14739
|
}
|
|
14668
|
-
const init = (0,
|
|
14740
|
+
const init = (0, import_child_process6.spawnSync)("git", ["init", "--bare", shadowDir], { timeout: 5e3 });
|
|
14669
14741
|
if (init.status !== 0 || init.error) {
|
|
14670
14742
|
const reason = init.error ? init.error.message : init.stderr?.toString();
|
|
14671
14743
|
if (process.env.NODE9_DEBUG === "1") console.error("[Node9] git init --bare failed:", reason);
|
|
14672
14744
|
return false;
|
|
14673
14745
|
}
|
|
14674
14746
|
const configFile = import_path30.default.join(shadowDir, "config");
|
|
14675
|
-
(0,
|
|
14747
|
+
(0, import_child_process6.spawnSync)("git", ["config", "--file", configFile, "core.untrackedCache", "true"], {
|
|
14676
14748
|
timeout: 3e3
|
|
14677
14749
|
});
|
|
14678
|
-
(0,
|
|
14750
|
+
(0, import_child_process6.spawnSync)("git", ["config", "--file", configFile, "core.fsmonitor", "true"], {
|
|
14679
14751
|
timeout: 3e3
|
|
14680
14752
|
});
|
|
14681
14753
|
try {
|
|
@@ -14686,14 +14758,17 @@ function ensureShadowRepo(shadowDir, cwd) {
|
|
|
14686
14758
|
}
|
|
14687
14759
|
function buildGitEnv(cwd) {
|
|
14688
14760
|
const shadowDir = getShadowRepoDir(cwd);
|
|
14689
|
-
const check = (0,
|
|
14761
|
+
const check = (0, import_child_process6.spawnSync)("git", ["rev-parse", "--git-dir"], {
|
|
14690
14762
|
env: { ...process.env, GIT_DIR: shadowDir, GIT_WORK_TREE: cwd },
|
|
14691
14763
|
timeout: 2e3
|
|
14692
14764
|
});
|
|
14693
14765
|
if (check.status === 0) {
|
|
14694
14766
|
return { ...process.env, GIT_DIR: shadowDir, GIT_WORK_TREE: cwd };
|
|
14695
14767
|
}
|
|
14696
|
-
|
|
14768
|
+
const env = { ...process.env };
|
|
14769
|
+
delete env.GIT_DIR;
|
|
14770
|
+
delete env.GIT_WORK_TREE;
|
|
14771
|
+
return env;
|
|
14697
14772
|
}
|
|
14698
14773
|
async function createShadowSnapshot(tool = "unknown", args = {}, ignorePaths = []) {
|
|
14699
14774
|
let indexFile = null;
|
|
@@ -14711,11 +14786,11 @@ async function createShadowSnapshot(tool = "unknown", args = {}, ignorePaths = [
|
|
|
14711
14786
|
GIT_WORK_TREE: cwd,
|
|
14712
14787
|
GIT_INDEX_FILE: indexFile
|
|
14713
14788
|
};
|
|
14714
|
-
(0,
|
|
14715
|
-
const treeRes = (0,
|
|
14789
|
+
(0, import_child_process6.spawnSync)("git", ["add", "-A"], { env: shadowEnv, timeout: GIT_TIMEOUT });
|
|
14790
|
+
const treeRes = (0, import_child_process6.spawnSync)("git", ["write-tree"], { env: shadowEnv, timeout: GIT_TIMEOUT });
|
|
14716
14791
|
const treeHash = treeRes.stdout?.toString().trim();
|
|
14717
14792
|
if (!treeHash || treeRes.status !== 0) return null;
|
|
14718
|
-
const commitRes = (0,
|
|
14793
|
+
const commitRes = (0, import_child_process6.spawnSync)(
|
|
14719
14794
|
"git",
|
|
14720
14795
|
["commit-tree", treeHash, "-m", `Node9 AI Snapshot: ${(/* @__PURE__ */ new Date()).toISOString()}`],
|
|
14721
14796
|
{ env: shadowEnv, timeout: GIT_TIMEOUT }
|
|
@@ -14727,7 +14802,7 @@ async function createShadowSnapshot(tool = "unknown", args = {}, ignorePaths = [
|
|
|
14727
14802
|
let capturedFiles = [];
|
|
14728
14803
|
let capturedDiff = null;
|
|
14729
14804
|
if (prevEntry) {
|
|
14730
|
-
const filesRes = (0,
|
|
14805
|
+
const filesRes = (0, import_child_process6.spawnSync)("git", ["diff", "--name-only", prevEntry.hash, commitHash], {
|
|
14731
14806
|
env: shadowEnv,
|
|
14732
14807
|
timeout: GIT_TIMEOUT
|
|
14733
14808
|
});
|
|
@@ -14737,7 +14812,7 @@ async function createShadowSnapshot(tool = "unknown", args = {}, ignorePaths = [
|
|
|
14737
14812
|
if (capturedFiles.length === 0) {
|
|
14738
14813
|
return prevEntry.hash;
|
|
14739
14814
|
}
|
|
14740
|
-
const diffRes = (0,
|
|
14815
|
+
const diffRes = (0, import_child_process6.spawnSync)("git", ["diff", prevEntry.hash, commitHash], {
|
|
14741
14816
|
env: shadowEnv,
|
|
14742
14817
|
timeout: GIT_TIMEOUT
|
|
14743
14818
|
});
|
|
@@ -14745,7 +14820,7 @@ async function createShadowSnapshot(tool = "unknown", args = {}, ignorePaths = [
|
|
|
14745
14820
|
capturedDiff = diffRes.stdout?.toString() || null;
|
|
14746
14821
|
}
|
|
14747
14822
|
} else {
|
|
14748
|
-
const filesRes = (0,
|
|
14823
|
+
const filesRes = (0, import_child_process6.spawnSync)("git", ["ls-tree", "-r", "--name-only", commitHash], {
|
|
14749
14824
|
env: shadowEnv,
|
|
14750
14825
|
timeout: GIT_TIMEOUT
|
|
14751
14826
|
});
|
|
@@ -14778,7 +14853,7 @@ async function createShadowSnapshot(tool = "unknown", args = {}, ignorePaths = [
|
|
|
14778
14853
|
notifySnapshotTaken(commitHash.slice(0, 7), tool, entry.argsSummary, capturedFiles.length);
|
|
14779
14854
|
import_fs29.default.writeFileSync(UNDO_LATEST_PATH, commitHash);
|
|
14780
14855
|
if (shouldGc) {
|
|
14781
|
-
(0,
|
|
14856
|
+
(0, import_child_process6.spawn)("git", ["gc", "--auto"], { env: shadowEnv, detached: true, stdio: "ignore" }).unref();
|
|
14782
14857
|
}
|
|
14783
14858
|
return commitHash;
|
|
14784
14859
|
} catch (err2) {
|
|
@@ -14799,14 +14874,14 @@ function getSnapshotHistory() {
|
|
|
14799
14874
|
function computeUndoDiff(hash, cwd) {
|
|
14800
14875
|
try {
|
|
14801
14876
|
const env = buildGitEnv(cwd);
|
|
14802
|
-
const statRes = (0,
|
|
14877
|
+
const statRes = (0, import_child_process6.spawnSync)("git", ["diff", hash, "--stat", "--", "."], {
|
|
14803
14878
|
cwd,
|
|
14804
14879
|
env,
|
|
14805
14880
|
timeout: GIT_TIMEOUT
|
|
14806
14881
|
});
|
|
14807
14882
|
const stat = statRes.stdout?.toString().trim();
|
|
14808
14883
|
if (!stat || statRes.status !== 0) return null;
|
|
14809
|
-
const diffRes = (0,
|
|
14884
|
+
const diffRes = (0, import_child_process6.spawnSync)("git", ["diff", hash, "--", "."], {
|
|
14810
14885
|
cwd,
|
|
14811
14886
|
env,
|
|
14812
14887
|
timeout: GIT_TIMEOUT
|
|
@@ -14825,7 +14900,7 @@ function applyUndo(hash, cwd) {
|
|
|
14825
14900
|
try {
|
|
14826
14901
|
const dir = cwd ?? process.cwd();
|
|
14827
14902
|
const env = buildGitEnv(dir);
|
|
14828
|
-
const restore = (0,
|
|
14903
|
+
const restore = (0, import_child_process6.spawnSync)("git", ["restore", "--source", hash, "--staged", "--worktree", "."], {
|
|
14829
14904
|
cwd: dir,
|
|
14830
14905
|
env,
|
|
14831
14906
|
timeout: GIT_TIMEOUT
|
|
@@ -14837,7 +14912,7 @@ function applyUndo(hash, cwd) {
|
|
|
14837
14912
|
}
|
|
14838
14913
|
return false;
|
|
14839
14914
|
}
|
|
14840
|
-
const lsTree = (0,
|
|
14915
|
+
const lsTree = (0, import_child_process6.spawnSync)("git", ["ls-tree", "-r", "--name-only", hash], {
|
|
14841
14916
|
cwd: dir,
|
|
14842
14917
|
env,
|
|
14843
14918
|
timeout: GIT_TIMEOUT
|
|
@@ -14856,8 +14931,8 @@ function applyUndo(hash, cwd) {
|
|
|
14856
14931
|
`);
|
|
14857
14932
|
return false;
|
|
14858
14933
|
}
|
|
14859
|
-
const tracked = (0,
|
|
14860
|
-
const untracked = (0,
|
|
14934
|
+
const tracked = (0, import_child_process6.spawnSync)("git", ["ls-files"], { cwd: dir, env, timeout: GIT_TIMEOUT }).stdout?.toString().trim().split("\n").filter(Boolean) ?? [];
|
|
14935
|
+
const untracked = (0, import_child_process6.spawnSync)("git", ["ls-files", "--others", "--exclude-standard"], {
|
|
14861
14936
|
cwd: dir,
|
|
14862
14937
|
env,
|
|
14863
14938
|
timeout: GIT_TIMEOUT
|
|
@@ -15128,7 +15203,7 @@ RAW: ${raw}
|
|
|
15128
15203
|
]) {
|
|
15129
15204
|
delete safeEnv[key];
|
|
15130
15205
|
}
|
|
15131
|
-
const d = (0,
|
|
15206
|
+
const d = (0, import_child_process7.spawn)(process.execPath, [scriptPath, "daemon"], {
|
|
15132
15207
|
detached: true,
|
|
15133
15208
|
stdio: "ignore",
|
|
15134
15209
|
env: { ...safeEnv, NODE9_AUTO_STARTED: "1" }
|
|
@@ -15961,7 +16036,7 @@ var import_chalk11 = __toESM(require("chalk"));
|
|
|
15961
16036
|
var import_fs33 = __toESM(require("fs"));
|
|
15962
16037
|
var import_path34 = __toESM(require("path"));
|
|
15963
16038
|
var import_os29 = __toESM(require("os"));
|
|
15964
|
-
var
|
|
16039
|
+
var import_child_process8 = require("child_process");
|
|
15965
16040
|
init_daemon();
|
|
15966
16041
|
function registerDoctorCommand(program2, version2) {
|
|
15967
16042
|
program2.command("doctor").description("Check that Node9 is installed and configured correctly").action(() => {
|
|
@@ -15987,7 +16062,7 @@ function registerDoctorCommand(program2, version2) {
|
|
|
15987
16062
|
`));
|
|
15988
16063
|
section("Binary");
|
|
15989
16064
|
try {
|
|
15990
|
-
const which = (0,
|
|
16065
|
+
const which = (0, import_child_process8.execSync)("which node9", { encoding: "utf-8", timeout: 3e3 }).trim();
|
|
15991
16066
|
pass(`node9 found at ${which}`);
|
|
15992
16067
|
} catch {
|
|
15993
16068
|
warn(
|
|
@@ -16005,7 +16080,7 @@ function registerDoctorCommand(program2, version2) {
|
|
|
16005
16080
|
);
|
|
16006
16081
|
}
|
|
16007
16082
|
try {
|
|
16008
|
-
const gitVersion = (0,
|
|
16083
|
+
const gitVersion = (0, import_child_process8.execSync)("git --version", { encoding: "utf-8", timeout: 3e3 }).trim();
|
|
16009
16084
|
pass(gitVersion);
|
|
16010
16085
|
} catch {
|
|
16011
16086
|
warn(
|
|
@@ -16106,10 +16181,12 @@ function registerDoctorCommand(program2, version2) {
|
|
|
16106
16181
|
}
|
|
16107
16182
|
section("Daemon (optional)");
|
|
16108
16183
|
if (isDaemonRunning()) {
|
|
16109
|
-
pass(
|
|
16184
|
+
pass(
|
|
16185
|
+
`Daemon running on ${DAEMON_HOST}:${DAEMON_PORT} \u2014 terminal & native approvals enabled`
|
|
16186
|
+
);
|
|
16110
16187
|
} else {
|
|
16111
16188
|
warn(
|
|
16112
|
-
"Daemon not running \u2014
|
|
16189
|
+
"Daemon not running \u2014 terminal & native approvals unavailable",
|
|
16113
16190
|
"Run: node9 daemon --background"
|
|
16114
16191
|
);
|
|
16115
16192
|
}
|
|
@@ -16981,7 +17058,7 @@ function registerReportCommand(program2) {
|
|
|
16981
17058
|
|
|
16982
17059
|
// src/cli/commands/daemon-cmd.ts
|
|
16983
17060
|
var import_chalk14 = __toESM(require("chalk"));
|
|
16984
|
-
var
|
|
17061
|
+
var import_child_process9 = require("child_process");
|
|
16985
17062
|
init_daemon2();
|
|
16986
17063
|
var VALID_ACTIONS = "start | stop | restart | status | install | uninstall";
|
|
16987
17064
|
function registerDaemonCommand(program2) {
|
|
@@ -17020,7 +17097,7 @@ function registerDaemonCommand(program2) {
|
|
|
17020
17097
|
if (cmd === "restart") {
|
|
17021
17098
|
stopDaemon();
|
|
17022
17099
|
await new Promise((r) => setTimeout(r, 500));
|
|
17023
|
-
const child = (0,
|
|
17100
|
+
const child = (0, import_child_process9.spawn)(process.execPath, [process.argv[1], "daemon"], {
|
|
17024
17101
|
detached: true,
|
|
17025
17102
|
stdio: "ignore",
|
|
17026
17103
|
env: { ...process.env, NODE9_AUTO_STARTED: "1" }
|
|
@@ -17050,7 +17127,7 @@ function registerDaemonCommand(program2) {
|
|
|
17050
17127
|
return;
|
|
17051
17128
|
}
|
|
17052
17129
|
if (options.background) {
|
|
17053
|
-
const child = (0,
|
|
17130
|
+
const child = (0, import_child_process9.spawn)(process.execPath, [process.argv[1], "daemon"], {
|
|
17054
17131
|
detached: true,
|
|
17055
17132
|
stdio: "ignore"
|
|
17056
17133
|
});
|
|
@@ -17708,7 +17785,7 @@ function registerUndoCommand(program2) {
|
|
|
17708
17785
|
|
|
17709
17786
|
// src/cli/commands/watch.ts
|
|
17710
17787
|
var import_chalk19 = __toESM(require("chalk"));
|
|
17711
|
-
var
|
|
17788
|
+
var import_child_process10 = require("child_process");
|
|
17712
17789
|
init_daemon();
|
|
17713
17790
|
function registerWatchCommand(program2) {
|
|
17714
17791
|
program2.command("watch").description("Run a command under Node9 watch mode (daemon stays alive for the session)").argument("<command>", "Command to run").argument("[args...]", "Arguments for the command").action(async (cmd, args) => {
|
|
@@ -17725,7 +17802,7 @@ function registerWatchCommand(program2) {
|
|
|
17725
17802
|
}
|
|
17726
17803
|
} catch {
|
|
17727
17804
|
console.error(import_chalk19.default.dim("\u{1F6E1}\uFE0F Starting Node9 daemon (watch mode)..."));
|
|
17728
|
-
const child = (0,
|
|
17805
|
+
const child = (0, import_child_process10.spawn)(process.execPath, [process.argv[1], "daemon"], {
|
|
17729
17806
|
detached: true,
|
|
17730
17807
|
stdio: "ignore",
|
|
17731
17808
|
env: { ...process.env, NODE9_AUTO_STARTED: "1", NODE9_WATCH_MODE: "1" }
|
|
@@ -17755,7 +17832,7 @@ function registerWatchCommand(program2) {
|
|
|
17755
17832
|
"\n Tip: run `node9 tail` in another terminal to review and approve AI actions.\n"
|
|
17756
17833
|
)
|
|
17757
17834
|
);
|
|
17758
|
-
const result = (0,
|
|
17835
|
+
const result = (0, import_child_process10.spawnSync)(cmd, args, {
|
|
17759
17836
|
stdio: "inherit",
|
|
17760
17837
|
env: { ...process.env, NODE9_WATCH_MODE: "1" }
|
|
17761
17838
|
});
|
|
@@ -17770,7 +17847,7 @@ function registerWatchCommand(program2) {
|
|
|
17770
17847
|
// src/mcp-gateway/index.ts
|
|
17771
17848
|
var import_readline4 = __toESM(require("readline"));
|
|
17772
17849
|
var import_chalk20 = __toESM(require("chalk"));
|
|
17773
|
-
var
|
|
17850
|
+
var import_child_process11 = require("child_process");
|
|
17774
17851
|
var import_execa3 = require("execa");
|
|
17775
17852
|
init_orchestrator();
|
|
17776
17853
|
init_provenance();
|
|
@@ -17956,7 +18033,7 @@ async function runMcpGateway(upstreamCommand) {
|
|
|
17956
18033
|
const safeEnv = Object.fromEntries(
|
|
17957
18034
|
Object.entries(process.env).filter(([k]) => !UPSTREAM_INJECTOR_VARS.has(k))
|
|
17958
18035
|
);
|
|
17959
|
-
const child = (0,
|
|
18036
|
+
const child = (0, import_child_process11.spawn)(executable, cmdArgs, {
|
|
17960
18037
|
stdio: ["pipe", "pipe", "inherit"],
|
|
17961
18038
|
// control stdin/stdout; inherit stderr
|
|
17962
18039
|
shell: false,
|
|
@@ -18302,7 +18379,7 @@ var import_readline5 = __toESM(require("readline"));
|
|
|
18302
18379
|
var import_fs39 = __toESM(require("fs"));
|
|
18303
18380
|
var import_os35 = __toESM(require("os"));
|
|
18304
18381
|
var import_path41 = __toESM(require("path"));
|
|
18305
|
-
var
|
|
18382
|
+
var import_child_process12 = require("child_process");
|
|
18306
18383
|
init_core();
|
|
18307
18384
|
init_daemon();
|
|
18308
18385
|
init_shields();
|
|
@@ -18776,7 +18853,7 @@ function handleRuleAdd(args) {
|
|
|
18776
18853
|
return `Rule "${name}" added to ~/.node9/config.json \u2014 verdict: ${verdict} when ${field} matches "${pattern}"`;
|
|
18777
18854
|
}
|
|
18778
18855
|
function runCliCommand(subArgs) {
|
|
18779
|
-
const result = (0,
|
|
18856
|
+
const result = (0, import_child_process12.spawnSync)(process.execPath, [process.argv[1], ...subArgs], {
|
|
18780
18857
|
encoding: "utf-8",
|
|
18781
18858
|
timeout: 6e4,
|
|
18782
18859
|
// Disable colors — stdout is piped (not a TTY), chalk auto-detects, but be explicit
|
|
@@ -20786,6 +20863,17 @@ program.command("tail").description("Stream live agent activity to the terminal"
|
|
|
20786
20863
|
process.exit(1);
|
|
20787
20864
|
}
|
|
20788
20865
|
});
|
|
20866
|
+
program.command("monitor").description("Live interactive dashboard \u2014 activity feed, approvals, security signals").action(async () => {
|
|
20867
|
+
try {
|
|
20868
|
+
const dashboardPath = import_path49.default.join(__dirname, "dashboard.mjs");
|
|
20869
|
+
const dynamicImport = new Function("id", "return import(id)");
|
|
20870
|
+
const mod = await dynamicImport(`file://${dashboardPath}`);
|
|
20871
|
+
await mod.startMonitor();
|
|
20872
|
+
} catch (err2) {
|
|
20873
|
+
console.error(import_chalk31.default.red(`\u274C ${err2 instanceof Error ? err2.message : String(err2)}`));
|
|
20874
|
+
process.exit(1);
|
|
20875
|
+
}
|
|
20876
|
+
});
|
|
20789
20877
|
registerWatchCommand(program);
|
|
20790
20878
|
registerMcpGatewayCommand(program);
|
|
20791
20879
|
registerMcpServerCommand(program);
|