@node9/proxy 1.55.0 → 1.56.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 +3072 -1963
- package/dist/cli.mjs +3058 -1950
- package/dist/dashboard.mjs +70 -41
- package/dist/index.js +326 -101
- package/dist/index.mjs +326 -101
- package/package.json +1 -1
package/dist/dashboard.mjs
CHANGED
|
@@ -547,9 +547,9 @@ function matchesPattern(text, patterns) {
|
|
|
547
547
|
const withoutDotSlash = text.replace(/^\.\//, "");
|
|
548
548
|
return isMatch(withoutDotSlash) || isMatch(`./${withoutDotSlash}`);
|
|
549
549
|
}
|
|
550
|
-
function getNestedValue(obj,
|
|
550
|
+
function getNestedValue(obj, path11) {
|
|
551
551
|
if (!obj || typeof obj !== "object") return null;
|
|
552
|
-
const segments =
|
|
552
|
+
const segments = path11.split(".");
|
|
553
553
|
for (const seg of segments) {
|
|
554
554
|
if (FORBIDDEN_PATH_SEGMENTS.has(seg)) return null;
|
|
555
555
|
}
|
|
@@ -2279,6 +2279,10 @@ var init_config_schema = __esm({
|
|
|
2279
2279
|
// approver_set). Default (unset/false): those tools refuse over MCP — a human
|
|
2280
2280
|
// must run them from the CLI. node9's threat model is the agent itself.
|
|
2281
2281
|
mcpAllowWeakening: z.boolean().optional(),
|
|
2282
|
+
// Auto-wire reconciler (P3 2.6): auto-wrap new ungoverned MCP servers vs
|
|
2283
|
+
// nudge-only (default), and the scan cadence in minutes.
|
|
2284
|
+
mcpAutoWrap: z.boolean().optional(),
|
|
2285
|
+
mcpReconcileIntervalMinutes: z.number().positive().optional(),
|
|
2282
2286
|
cloudSyncIntervalHours: z.number().positive().optional(),
|
|
2283
2287
|
// Seconds-granular override for the cloud policy sync cadence. Wins over
|
|
2284
2288
|
// cloudSyncIntervalHours when set. Lets you opt into fast apply (e.g. 20)
|
|
@@ -2419,6 +2423,20 @@ var init_managed = __esm({
|
|
|
2419
2423
|
}
|
|
2420
2424
|
});
|
|
2421
2425
|
|
|
2426
|
+
// src/shields/build.ts
|
|
2427
|
+
var init_build = __esm({
|
|
2428
|
+
"src/shields/build.ts"() {
|
|
2429
|
+
"use strict";
|
|
2430
|
+
}
|
|
2431
|
+
});
|
|
2432
|
+
|
|
2433
|
+
// src/auth/trusted-hosts.ts
|
|
2434
|
+
var init_trusted_hosts = __esm({
|
|
2435
|
+
"src/auth/trusted-hosts.ts"() {
|
|
2436
|
+
"use strict";
|
|
2437
|
+
}
|
|
2438
|
+
});
|
|
2439
|
+
|
|
2422
2440
|
// src/config/index.ts
|
|
2423
2441
|
var DANGEROUS_WORDS, DEFAULT_CONFIG;
|
|
2424
2442
|
var init_config = __esm({
|
|
@@ -2427,6 +2445,8 @@ var init_config = __esm({
|
|
|
2427
2445
|
init_config_schema();
|
|
2428
2446
|
init_shields();
|
|
2429
2447
|
init_managed();
|
|
2448
|
+
init_build();
|
|
2449
|
+
init_trusted_hosts();
|
|
2430
2450
|
DANGEROUS_WORDS = [
|
|
2431
2451
|
"mkfs",
|
|
2432
2452
|
// formats/wipes a filesystem partition
|
|
@@ -2635,7 +2655,10 @@ var init_config = __esm({
|
|
|
2635
2655
|
egress: { enabled: false, mode: "review", allow: [], deny: [], allowPrivate: true },
|
|
2636
2656
|
loopDetection: { enabled: true, threshold: 5, windowSeconds: 120 },
|
|
2637
2657
|
injectionScan: { enabled: false, minConfidence: "medium", allow: [] },
|
|
2638
|
-
skillPinning: { enabled: false, mode: "warn", roots: [] }
|
|
2658
|
+
skillPinning: { enabled: false, mode: "warn", roots: [] },
|
|
2659
|
+
trustedHosts: [],
|
|
2660
|
+
trustedHostsManaged: false,
|
|
2661
|
+
appPermissions: {}
|
|
2639
2662
|
},
|
|
2640
2663
|
environments: {}
|
|
2641
2664
|
};
|
|
@@ -3624,13 +3647,6 @@ var init_provenance = __esm({
|
|
|
3624
3647
|
}
|
|
3625
3648
|
});
|
|
3626
3649
|
|
|
3627
|
-
// src/auth/trusted-hosts.ts
|
|
3628
|
-
var init_trusted_hosts = __esm({
|
|
3629
|
-
"src/auth/trusted-hosts.ts"() {
|
|
3630
|
-
"use strict";
|
|
3631
|
-
}
|
|
3632
|
-
});
|
|
3633
|
-
|
|
3634
3650
|
// src/policy/index.ts
|
|
3635
3651
|
import pm2 from "picomatch";
|
|
3636
3652
|
var init_policy = __esm({
|
|
@@ -3669,6 +3685,18 @@ var init_mcp_pin = __esm({
|
|
|
3669
3685
|
}
|
|
3670
3686
|
});
|
|
3671
3687
|
|
|
3688
|
+
// src/daemon/hook-baseline.ts
|
|
3689
|
+
import path8 from "path";
|
|
3690
|
+
import os8 from "os";
|
|
3691
|
+
var BASELINE_FILE, NOTIFIED_FILE;
|
|
3692
|
+
var init_hook_baseline = __esm({
|
|
3693
|
+
"src/daemon/hook-baseline.ts"() {
|
|
3694
|
+
"use strict";
|
|
3695
|
+
BASELINE_FILE = path8.join(os8.homedir(), ".node9", "hooks-baseline.json");
|
|
3696
|
+
NOTIFIED_FILE = path8.join(os8.homedir(), ".node9", "hook-heal-notified.json");
|
|
3697
|
+
}
|
|
3698
|
+
});
|
|
3699
|
+
|
|
3672
3700
|
// src/setup-opencode-shim.ts
|
|
3673
3701
|
var init_setup_opencode_shim = __esm({
|
|
3674
3702
|
"src/setup-opencode-shim.ts"() {
|
|
@@ -3692,6 +3720,7 @@ var init_setup = __esm({
|
|
|
3692
3720
|
"src/setup.ts"() {
|
|
3693
3721
|
"use strict";
|
|
3694
3722
|
init_mcp_pin();
|
|
3723
|
+
init_hook_baseline();
|
|
3695
3724
|
init_setup_opencode_shim();
|
|
3696
3725
|
init_setup_pi_shim();
|
|
3697
3726
|
}
|
|
@@ -3724,8 +3753,8 @@ var init_scan_history = __esm({
|
|
|
3724
3753
|
// src/cli/commands/scan.ts
|
|
3725
3754
|
import chalk4 from "chalk";
|
|
3726
3755
|
import fs6 from "fs";
|
|
3727
|
-
import
|
|
3728
|
-
import
|
|
3756
|
+
import path9 from "path";
|
|
3757
|
+
import os9 from "os";
|
|
3729
3758
|
import stringWidth2 from "string-width";
|
|
3730
3759
|
function claudeModelPrice2(model) {
|
|
3731
3760
|
const t = pricingFor(model);
|
|
@@ -3874,7 +3903,7 @@ function processClaudeFile(file, projPath, projLabel, ruleSources, startDate, re
|
|
|
3874
3903
|
const sessionId = file.replace(/\.jsonl$/, "");
|
|
3875
3904
|
let raw;
|
|
3876
3905
|
try {
|
|
3877
|
-
raw = fs6.readFileSync(
|
|
3906
|
+
raw = fs6.readFileSync(path9.join(projPath, file), "utf-8");
|
|
3878
3907
|
} catch {
|
|
3879
3908
|
return;
|
|
3880
3909
|
}
|
|
@@ -3926,7 +3955,7 @@ function processClaudeFile(file, projPath, projLabel, ruleSources, startDate, re
|
|
|
3926
3955
|
if (block.type !== "tool_result") continue;
|
|
3927
3956
|
const filePath = block.tool_use_id ? toolUseFilePaths.get(block.tool_use_id) : void 0;
|
|
3928
3957
|
if (filePath) {
|
|
3929
|
-
const ext =
|
|
3958
|
+
const ext = path9.extname(filePath).toLowerCase();
|
|
3930
3959
|
if (CODE_EXTENSIONS.has(ext)) continue;
|
|
3931
3960
|
}
|
|
3932
3961
|
const resultText = typeof block.content === "string" ? block.content : Array.isArray(block.content) ? block.content.map((c) => c.text ?? "").join("\n") : null;
|
|
@@ -3983,7 +4012,7 @@ function processClaudeFile(file, projPath, projLabel, ruleSources, startDate, re
|
|
|
3983
4012
|
const rawCmd = String(input.command ?? "").trimStart();
|
|
3984
4013
|
if (/^node9\s+(scan|explain|report|tail|dlp|status|sessions|audit)\b/.test(rawCmd)) continue;
|
|
3985
4014
|
const inputFilePath = typeof input.file_path === "string" ? input.file_path : "";
|
|
3986
|
-
const inputFileExt = inputFilePath ?
|
|
4015
|
+
const inputFileExt = inputFilePath ? path9.extname(inputFilePath).toLowerCase() : "";
|
|
3987
4016
|
if (CODE_EXTENSIONS.has(inputFileExt)) continue;
|
|
3988
4017
|
const dlpMatch = scanArgs(input);
|
|
3989
4018
|
if (dlpMatch) {
|
|
@@ -4080,13 +4109,13 @@ function processClaudeFile(file, projPath, projLabel, ruleSources, startDate, re
|
|
|
4080
4109
|
}
|
|
4081
4110
|
}
|
|
4082
4111
|
async function processClaudeProjectAsync(proj, projectsDir, ruleSources, startDate, result, dedup, onProgress, onLine) {
|
|
4083
|
-
const projPath =
|
|
4112
|
+
const projPath = path9.join(projectsDir, proj);
|
|
4084
4113
|
try {
|
|
4085
4114
|
if (!fs6.statSync(projPath).isDirectory()) return;
|
|
4086
4115
|
} catch {
|
|
4087
4116
|
return;
|
|
4088
4117
|
}
|
|
4089
|
-
const projLabel = stripTerminalEscapes(decodeURIComponent(proj).replace(
|
|
4118
|
+
const projLabel = stripTerminalEscapes(decodeURIComponent(proj).replace(os9.homedir(), "~")).slice(
|
|
4090
4119
|
0,
|
|
4091
4120
|
40
|
|
4092
4121
|
);
|
|
@@ -4130,7 +4159,7 @@ function emptyClaudeScan() {
|
|
|
4130
4159
|
};
|
|
4131
4160
|
}
|
|
4132
4161
|
async function scanClaudeHistoryAsync(startDate, onProgress, onLine) {
|
|
4133
|
-
const projectsDir =
|
|
4162
|
+
const projectsDir = path9.join(os9.homedir(), ".claude", "projects");
|
|
4134
4163
|
const result = emptyClaudeScan();
|
|
4135
4164
|
if (!fs6.existsSync(projectsDir)) return result;
|
|
4136
4165
|
let projDirs;
|
|
@@ -4156,7 +4185,7 @@ async function scanClaudeHistoryAsync(startDate, onProgress, onLine) {
|
|
|
4156
4185
|
return result;
|
|
4157
4186
|
}
|
|
4158
4187
|
function scanGeminiHistory(startDate, onProgress, onLine) {
|
|
4159
|
-
const tmpDir =
|
|
4188
|
+
const tmpDir = path9.join(os9.homedir(), ".gemini", "tmp");
|
|
4160
4189
|
const result = {
|
|
4161
4190
|
filesScanned: 0,
|
|
4162
4191
|
sessions: 0,
|
|
@@ -4180,7 +4209,7 @@ function scanGeminiHistory(startDate, onProgress, onLine) {
|
|
|
4180
4209
|
}
|
|
4181
4210
|
const ruleSources = buildRuleSources();
|
|
4182
4211
|
for (const slug of slugDirs) {
|
|
4183
|
-
const slugPath =
|
|
4212
|
+
const slugPath = path9.join(tmpDir, slug);
|
|
4184
4213
|
try {
|
|
4185
4214
|
if (!fs6.statSync(slugPath).isDirectory()) continue;
|
|
4186
4215
|
} catch {
|
|
@@ -4189,11 +4218,11 @@ function scanGeminiHistory(startDate, onProgress, onLine) {
|
|
|
4189
4218
|
let projLabel = stripTerminalEscapes(slug).slice(0, 40);
|
|
4190
4219
|
try {
|
|
4191
4220
|
projLabel = stripTerminalEscapes(
|
|
4192
|
-
fs6.readFileSync(
|
|
4193
|
-
).replace(
|
|
4221
|
+
fs6.readFileSync(path9.join(slugPath, ".project_root"), "utf-8").trim()
|
|
4222
|
+
).replace(os9.homedir(), "~").slice(0, 40);
|
|
4194
4223
|
} catch {
|
|
4195
4224
|
}
|
|
4196
|
-
const chatsDir =
|
|
4225
|
+
const chatsDir = path9.join(slugPath, "chats");
|
|
4197
4226
|
if (!fs6.existsSync(chatsDir)) continue;
|
|
4198
4227
|
let chatFiles;
|
|
4199
4228
|
try {
|
|
@@ -4210,7 +4239,7 @@ function scanGeminiHistory(startDate, onProgress, onLine) {
|
|
|
4210
4239
|
onProgress?.(result.filesScanned);
|
|
4211
4240
|
let raw;
|
|
4212
4241
|
try {
|
|
4213
|
-
raw = fs6.readFileSync(
|
|
4242
|
+
raw = fs6.readFileSync(path9.join(chatsDir, chatFile), "utf-8");
|
|
4214
4243
|
} catch {
|
|
4215
4244
|
continue;
|
|
4216
4245
|
}
|
|
@@ -4383,7 +4412,7 @@ function scanGeminiHistory(startDate, onProgress, onLine) {
|
|
|
4383
4412
|
return result;
|
|
4384
4413
|
}
|
|
4385
4414
|
function scanCodexHistory(startDate, onProgress, onLine) {
|
|
4386
|
-
const sessionsBase =
|
|
4415
|
+
const sessionsBase = path9.join(os9.homedir(), ".codex", "sessions");
|
|
4387
4416
|
const result = {
|
|
4388
4417
|
filesScanned: 0,
|
|
4389
4418
|
sessions: 0,
|
|
@@ -4402,28 +4431,28 @@ function scanCodexHistory(startDate, onProgress, onLine) {
|
|
|
4402
4431
|
const jsonlFiles = [];
|
|
4403
4432
|
try {
|
|
4404
4433
|
for (const year of fs6.readdirSync(sessionsBase)) {
|
|
4405
|
-
const yearPath =
|
|
4434
|
+
const yearPath = path9.join(sessionsBase, year);
|
|
4406
4435
|
try {
|
|
4407
4436
|
if (!fs6.statSync(yearPath).isDirectory()) continue;
|
|
4408
4437
|
} catch {
|
|
4409
4438
|
continue;
|
|
4410
4439
|
}
|
|
4411
4440
|
for (const month of fs6.readdirSync(yearPath)) {
|
|
4412
|
-
const monthPath =
|
|
4441
|
+
const monthPath = path9.join(yearPath, month);
|
|
4413
4442
|
try {
|
|
4414
4443
|
if (!fs6.statSync(monthPath).isDirectory()) continue;
|
|
4415
4444
|
} catch {
|
|
4416
4445
|
continue;
|
|
4417
4446
|
}
|
|
4418
4447
|
for (const day of fs6.readdirSync(monthPath)) {
|
|
4419
|
-
const dayPath =
|
|
4448
|
+
const dayPath = path9.join(monthPath, day);
|
|
4420
4449
|
try {
|
|
4421
4450
|
if (!fs6.statSync(dayPath).isDirectory()) continue;
|
|
4422
4451
|
} catch {
|
|
4423
4452
|
continue;
|
|
4424
4453
|
}
|
|
4425
4454
|
for (const file of fs6.readdirSync(dayPath)) {
|
|
4426
|
-
if (file.endsWith(".jsonl")) jsonlFiles.push(
|
|
4455
|
+
if (file.endsWith(".jsonl")) jsonlFiles.push(path9.join(dayPath, file));
|
|
4427
4456
|
}
|
|
4428
4457
|
}
|
|
4429
4458
|
}
|
|
@@ -4464,7 +4493,7 @@ function scanCodexHistory(startDate, onProgress, onLine) {
|
|
|
4464
4493
|
sessionId = String(payload["id"] ?? filePath);
|
|
4465
4494
|
startTime = String(payload["timestamp"] ?? "");
|
|
4466
4495
|
const cwd = String(payload["cwd"] ?? "");
|
|
4467
|
-
projLabel = stripTerminalEscapes(cwd.replace(
|
|
4496
|
+
projLabel = stripTerminalEscapes(cwd.replace(os9.homedir(), "~")).slice(0, 40);
|
|
4468
4497
|
continue;
|
|
4469
4498
|
}
|
|
4470
4499
|
if (entry.type === "turn_context" && typeof payload["model"] === "string") {
|
|
@@ -4707,11 +4736,11 @@ var init_scan = __esm({
|
|
|
4707
4736
|
|
|
4708
4737
|
// src/tui/dashboard/data.ts
|
|
4709
4738
|
import fs7 from "fs";
|
|
4710
|
-
import
|
|
4711
|
-
import
|
|
4739
|
+
import os10 from "os";
|
|
4740
|
+
import path10 from "path";
|
|
4712
4741
|
import http from "http";
|
|
4713
4742
|
function auditLogPath() {
|
|
4714
|
-
return
|
|
4743
|
+
return path10.join(os10.homedir(), ".node9", "audit.log");
|
|
4715
4744
|
}
|
|
4716
4745
|
function readAuditEntriesAsync(chunkSize = 1e3, customPath) {
|
|
4717
4746
|
return new Promise((resolve) => {
|
|
@@ -4851,13 +4880,13 @@ function loadBlast() {
|
|
|
4851
4880
|
}
|
|
4852
4881
|
}
|
|
4853
4882
|
function shortenPath(p) {
|
|
4854
|
-
const home =
|
|
4883
|
+
const home = os10.homedir();
|
|
4855
4884
|
return p.startsWith(home) ? p.replace(home, "~") : p;
|
|
4856
4885
|
}
|
|
4857
4886
|
async function loadReportAuditAsync(period) {
|
|
4858
|
-
const claudeProjectsDir =
|
|
4859
|
-
const codexSessionsDir =
|
|
4860
|
-
const geminiTmpDir =
|
|
4887
|
+
const claudeProjectsDir = path10.join(os10.homedir(), ".claude", "projects");
|
|
4888
|
+
const codexSessionsDir = path10.join(os10.homedir(), ".codex", "sessions");
|
|
4889
|
+
const geminiTmpDir = path10.join(os10.homedir(), ".gemini", "tmp");
|
|
4861
4890
|
const { start, end } = getDateRange(period, /* @__PURE__ */ new Date());
|
|
4862
4891
|
const entries = await readAuditEntriesAsync();
|
|
4863
4892
|
void ensurePricingLoaded();
|
|
@@ -5963,8 +5992,8 @@ import { Fragment as Fragment3, jsx as jsx4, jsxs as jsxs4 } from "react/jsx-run
|
|
|
5963
5992
|
function TopToolsProjects({ audit }) {
|
|
5964
5993
|
const data = audit?.data;
|
|
5965
5994
|
const tools = data ? [...data.toolMap.entries()].sort(([, a], [, b]) => b.calls - a.calls).slice(0, ROW_LIMIT) : [];
|
|
5966
|
-
const projects = data ? [...data.cost.byProject.entries()].map(([
|
|
5967
|
-
name: basenameOf(
|
|
5995
|
+
const projects = data ? [...data.cost.byProject.entries()].map(([path11, r]) => ({
|
|
5996
|
+
name: basenameOf(path11),
|
|
5968
5997
|
cost: r.cost,
|
|
5969
5998
|
tokens: r.inputTokens + r.outputTokens
|
|
5970
5999
|
})).sort((a, b) => b.cost - a.cost).slice(0, ROW_LIMIT) : [];
|
|
@@ -6401,8 +6430,8 @@ function pickTopLoopFile(loops) {
|
|
|
6401
6430
|
map.set(k, (map.get(k) ?? 0) + (l.count ?? 0));
|
|
6402
6431
|
}
|
|
6403
6432
|
if (map.size === 0) return void 0;
|
|
6404
|
-
const [
|
|
6405
|
-
return { path:
|
|
6433
|
+
const [path11, count] = [...map.entries()].sort((a, b) => b[1] - a[1])[0];
|
|
6434
|
+
return { path: path11, count };
|
|
6406
6435
|
}
|
|
6407
6436
|
var EMPTY_FILTERED_SCAN;
|
|
6408
6437
|
var init_derive = __esm({
|