@node9/proxy 1.46.0 → 1.48.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 +27 -8
- package/dist/cli.mjs +27 -8
- package/dist/dashboard.mjs +5 -0
- package/dist/index.js +11 -1
- package/dist/index.mjs +11 -1
- package/package.json +1 -1
package/dist/cli.js
CHANGED
|
@@ -337,6 +337,11 @@ var init_config_schema = __esm({
|
|
|
337
337
|
// must run them from the CLI. node9's threat model is the agent itself.
|
|
338
338
|
mcpAllowWeakening: import_zod.z.boolean().optional(),
|
|
339
339
|
cloudSyncIntervalHours: import_zod.z.number().positive().optional(),
|
|
340
|
+
// Seconds-granular override for the cloud policy sync cadence. Wins over
|
|
341
|
+
// cloudSyncIntervalHours when set. Lets you opt into fast apply (e.g. 20)
|
|
342
|
+
// for an incident; clamped to a 15s floor so it can't hammer the API.
|
|
343
|
+
// Unset → falls back to hours, then the 5h default.
|
|
344
|
+
cloudSyncIntervalSeconds: import_zod.z.number().positive().optional(),
|
|
340
345
|
// Outbox shipper (audit.log → SaaS batch ingest). enabled defaults
|
|
341
346
|
// to true; set false to fall back to local-only auditing.
|
|
342
347
|
shipper: import_zod.z.object({
|
|
@@ -4410,6 +4415,7 @@ function getConfig(cwd) {
|
|
|
4410
4415
|
};
|
|
4411
4416
|
applyLayer(globalConfig);
|
|
4412
4417
|
applyLayer(projectConfig);
|
|
4418
|
+
let cloudManagedShields = [];
|
|
4413
4419
|
{
|
|
4414
4420
|
const cacheFile = import_path3.default.join(import_os3.default.homedir(), ".node9", "rules-cache.json");
|
|
4415
4421
|
try {
|
|
@@ -4417,6 +4423,9 @@ function getConfig(cwd) {
|
|
|
4417
4423
|
if (Array.isArray(raw.rules) && raw.rules.length > 0) {
|
|
4418
4424
|
applyLayer({ policy: { smartRules: raw.rules } });
|
|
4419
4425
|
}
|
|
4426
|
+
if (Array.isArray(raw.shields)) {
|
|
4427
|
+
cloudManagedShields = raw.shields.filter((s) => typeof s === "string");
|
|
4428
|
+
}
|
|
4420
4429
|
if (raw.panicMode === true) {
|
|
4421
4430
|
mergedSettings.panicMode = true;
|
|
4422
4431
|
}
|
|
@@ -4427,7 +4436,8 @@ function getConfig(cwd) {
|
|
|
4427
4436
|
}
|
|
4428
4437
|
}
|
|
4429
4438
|
const shieldOverrides = readShieldOverrides();
|
|
4430
|
-
|
|
4439
|
+
const activeShieldNames = [.../* @__PURE__ */ new Set([...readActiveShields(), ...cloudManagedShields])];
|
|
4440
|
+
for (const shieldName of activeShieldNames) {
|
|
4431
4441
|
const shield = getShield(shieldName);
|
|
4432
4442
|
if (!shield) continue;
|
|
4433
4443
|
const existingRuleNames = new Set(mergedPolicy.smartRules.map((r) => r.name));
|
|
@@ -16777,6 +16787,11 @@ function buildSessionDeltas(findings, toolCallsBySession) {
|
|
|
16777
16787
|
signals
|
|
16778
16788
|
}));
|
|
16779
16789
|
}
|
|
16790
|
+
function resolveSyncIntervalMs(settings) {
|
|
16791
|
+
const rawSeconds = settings.cloudSyncIntervalSeconds ?? (settings.cloudSyncIntervalHours ?? DEFAULT_INTERVAL_HOURS) * 3600;
|
|
16792
|
+
const clamped = Math.min(Math.max(rawSeconds, MIN_INTERVAL_SECONDS), MAX_INTERVAL_SECONDS);
|
|
16793
|
+
return clamped * 1e3;
|
|
16794
|
+
}
|
|
16780
16795
|
function readCredentials() {
|
|
16781
16796
|
if (process.env.NODE9_API_KEY) {
|
|
16782
16797
|
return {
|
|
@@ -16872,6 +16887,9 @@ function extractRules(body) {
|
|
|
16872
16887
|
if (Array.isArray(body.rules)) return body.rules;
|
|
16873
16888
|
return [];
|
|
16874
16889
|
}
|
|
16890
|
+
function extractShields(body) {
|
|
16891
|
+
return Array.isArray(body.shields) ? body.shields.filter((s) => typeof s === "string") : [];
|
|
16892
|
+
}
|
|
16875
16893
|
function writeCache2(cache) {
|
|
16876
16894
|
const dir = import_path31.default.dirname(rulesCacheFile());
|
|
16877
16895
|
if (!import_fs32.default.existsSync(dir)) import_fs32.default.mkdirSync(dir, { recursive: true });
|
|
@@ -16891,7 +16909,8 @@ async function syncOnce() {
|
|
|
16891
16909
|
panicMode: result.body.panicMode,
|
|
16892
16910
|
shadowMode: result.body.shadowMode,
|
|
16893
16911
|
syncIntervalHours: result.body.syncIntervalHours,
|
|
16894
|
-
workspaceId: result.body.workspaceId
|
|
16912
|
+
workspaceId: result.body.workspaceId,
|
|
16913
|
+
shields: extractShields(result.body)
|
|
16895
16914
|
};
|
|
16896
16915
|
writeCache2(cache);
|
|
16897
16916
|
}
|
|
@@ -17063,7 +17082,8 @@ async function runCloudSync() {
|
|
|
17063
17082
|
panicMode: result.body.panicMode,
|
|
17064
17083
|
shadowMode: result.body.shadowMode,
|
|
17065
17084
|
syncIntervalHours: result.body.syncIntervalHours,
|
|
17066
|
-
workspaceId: result.body.workspaceId
|
|
17085
|
+
workspaceId: result.body.workspaceId,
|
|
17086
|
+
shields: extractShields(result.body)
|
|
17067
17087
|
};
|
|
17068
17088
|
writeCache2(cache);
|
|
17069
17089
|
maybePushBlast();
|
|
@@ -17099,9 +17119,7 @@ function getCloudRules() {
|
|
|
17099
17119
|
}
|
|
17100
17120
|
}
|
|
17101
17121
|
function startCloudSync() {
|
|
17102
|
-
const
|
|
17103
|
-
const intervalHours = Math.max(rawHours, MIN_INTERVAL_HOURS);
|
|
17104
|
-
const intervalMs = intervalHours * 60 * 60 * 1e3;
|
|
17122
|
+
const intervalMs = resolveSyncIntervalMs(getConfig().settings);
|
|
17105
17123
|
const initial = setTimeout(() => void syncOnce(), 3e4);
|
|
17106
17124
|
initial.unref();
|
|
17107
17125
|
const recurring = setInterval(() => void syncOnce(), intervalMs);
|
|
@@ -17126,7 +17144,7 @@ function startForensicBroadcast() {
|
|
|
17126
17144
|
const recurring = setInterval(() => void tick(), FORENSIC_BROADCAST_INTERVAL_MS);
|
|
17127
17145
|
recurring.unref();
|
|
17128
17146
|
}
|
|
17129
|
-
var import_fs32, import_https4, import_os29, import_path31, FINDING_TO_SIGNAL3, rulesCacheFile, DEFAULT_API_URL, DEFAULT_INTERVAL_HOURS,
|
|
17147
|
+
var import_fs32, import_https4, import_os29, import_path31, FINDING_TO_SIGNAL3, rulesCacheFile, DEFAULT_API_URL, DEFAULT_INTERVAL_HOURS, MIN_INTERVAL_SECONDS, MAX_INTERVAL_SECONDS, FORENSIC_BROADCAST_INTERVAL_MS, FORENSIC_INITIAL_DELAY_MS, forensicBroadcastOffsets;
|
|
17130
17148
|
var init_sync = __esm({
|
|
17131
17149
|
"src/daemon/sync.ts"() {
|
|
17132
17150
|
"use strict";
|
|
@@ -17160,7 +17178,8 @@ var init_sync = __esm({
|
|
|
17160
17178
|
rulesCacheFile = () => import_path31.default.join(import_os29.default.homedir(), ".node9", "rules-cache.json");
|
|
17161
17179
|
DEFAULT_API_URL = "https://api.node9.ai/api/v1/intercept/policies/sync";
|
|
17162
17180
|
DEFAULT_INTERVAL_HOURS = 5;
|
|
17163
|
-
|
|
17181
|
+
MIN_INTERVAL_SECONDS = 15;
|
|
17182
|
+
MAX_INTERVAL_SECONDS = 24 * 60 * 60;
|
|
17164
17183
|
FORENSIC_BROADCAST_INTERVAL_MS = 3e4;
|
|
17165
17184
|
FORENSIC_INITIAL_DELAY_MS = 5e3;
|
|
17166
17185
|
forensicBroadcastOffsets = /* @__PURE__ */ new Map();
|
package/dist/cli.mjs
CHANGED
|
@@ -315,6 +315,11 @@ var init_config_schema = __esm({
|
|
|
315
315
|
// must run them from the CLI. node9's threat model is the agent itself.
|
|
316
316
|
mcpAllowWeakening: z.boolean().optional(),
|
|
317
317
|
cloudSyncIntervalHours: z.number().positive().optional(),
|
|
318
|
+
// Seconds-granular override for the cloud policy sync cadence. Wins over
|
|
319
|
+
// cloudSyncIntervalHours when set. Lets you opt into fast apply (e.g. 20)
|
|
320
|
+
// for an incident; clamped to a 15s floor so it can't hammer the API.
|
|
321
|
+
// Unset → falls back to hours, then the 5h default.
|
|
322
|
+
cloudSyncIntervalSeconds: z.number().positive().optional(),
|
|
318
323
|
// Outbox shipper (audit.log → SaaS batch ingest). enabled defaults
|
|
319
324
|
// to true; set false to fall back to local-only auditing.
|
|
320
325
|
shipper: z.object({
|
|
@@ -4391,6 +4396,7 @@ function getConfig(cwd) {
|
|
|
4391
4396
|
};
|
|
4392
4397
|
applyLayer(globalConfig);
|
|
4393
4398
|
applyLayer(projectConfig);
|
|
4399
|
+
let cloudManagedShields = [];
|
|
4394
4400
|
{
|
|
4395
4401
|
const cacheFile = path3.join(os3.homedir(), ".node9", "rules-cache.json");
|
|
4396
4402
|
try {
|
|
@@ -4398,6 +4404,9 @@ function getConfig(cwd) {
|
|
|
4398
4404
|
if (Array.isArray(raw.rules) && raw.rules.length > 0) {
|
|
4399
4405
|
applyLayer({ policy: { smartRules: raw.rules } });
|
|
4400
4406
|
}
|
|
4407
|
+
if (Array.isArray(raw.shields)) {
|
|
4408
|
+
cloudManagedShields = raw.shields.filter((s) => typeof s === "string");
|
|
4409
|
+
}
|
|
4401
4410
|
if (raw.panicMode === true) {
|
|
4402
4411
|
mergedSettings.panicMode = true;
|
|
4403
4412
|
}
|
|
@@ -4408,7 +4417,8 @@ function getConfig(cwd) {
|
|
|
4408
4417
|
}
|
|
4409
4418
|
}
|
|
4410
4419
|
const shieldOverrides = readShieldOverrides();
|
|
4411
|
-
|
|
4420
|
+
const activeShieldNames = [.../* @__PURE__ */ new Set([...readActiveShields(), ...cloudManagedShields])];
|
|
4421
|
+
for (const shieldName of activeShieldNames) {
|
|
4412
4422
|
const shield = getShield(shieldName);
|
|
4413
4423
|
if (!shield) continue;
|
|
4414
4424
|
const existingRuleNames = new Set(mergedPolicy.smartRules.map((r) => r.name));
|
|
@@ -16751,6 +16761,11 @@ function buildSessionDeltas(findings, toolCallsBySession) {
|
|
|
16751
16761
|
signals
|
|
16752
16762
|
}));
|
|
16753
16763
|
}
|
|
16764
|
+
function resolveSyncIntervalMs(settings) {
|
|
16765
|
+
const rawSeconds = settings.cloudSyncIntervalSeconds ?? (settings.cloudSyncIntervalHours ?? DEFAULT_INTERVAL_HOURS) * 3600;
|
|
16766
|
+
const clamped = Math.min(Math.max(rawSeconds, MIN_INTERVAL_SECONDS), MAX_INTERVAL_SECONDS);
|
|
16767
|
+
return clamped * 1e3;
|
|
16768
|
+
}
|
|
16754
16769
|
function readCredentials() {
|
|
16755
16770
|
if (process.env.NODE9_API_KEY) {
|
|
16756
16771
|
return {
|
|
@@ -16846,6 +16861,9 @@ function extractRules(body) {
|
|
|
16846
16861
|
if (Array.isArray(body.rules)) return body.rules;
|
|
16847
16862
|
return [];
|
|
16848
16863
|
}
|
|
16864
|
+
function extractShields(body) {
|
|
16865
|
+
return Array.isArray(body.shields) ? body.shields.filter((s) => typeof s === "string") : [];
|
|
16866
|
+
}
|
|
16849
16867
|
function writeCache2(cache) {
|
|
16850
16868
|
const dir = path31.dirname(rulesCacheFile());
|
|
16851
16869
|
if (!fs32.existsSync(dir)) fs32.mkdirSync(dir, { recursive: true });
|
|
@@ -16865,7 +16883,8 @@ async function syncOnce() {
|
|
|
16865
16883
|
panicMode: result.body.panicMode,
|
|
16866
16884
|
shadowMode: result.body.shadowMode,
|
|
16867
16885
|
syncIntervalHours: result.body.syncIntervalHours,
|
|
16868
|
-
workspaceId: result.body.workspaceId
|
|
16886
|
+
workspaceId: result.body.workspaceId,
|
|
16887
|
+
shields: extractShields(result.body)
|
|
16869
16888
|
};
|
|
16870
16889
|
writeCache2(cache);
|
|
16871
16890
|
}
|
|
@@ -17037,7 +17056,8 @@ async function runCloudSync() {
|
|
|
17037
17056
|
panicMode: result.body.panicMode,
|
|
17038
17057
|
shadowMode: result.body.shadowMode,
|
|
17039
17058
|
syncIntervalHours: result.body.syncIntervalHours,
|
|
17040
|
-
workspaceId: result.body.workspaceId
|
|
17059
|
+
workspaceId: result.body.workspaceId,
|
|
17060
|
+
shields: extractShields(result.body)
|
|
17041
17061
|
};
|
|
17042
17062
|
writeCache2(cache);
|
|
17043
17063
|
maybePushBlast();
|
|
@@ -17073,9 +17093,7 @@ function getCloudRules() {
|
|
|
17073
17093
|
}
|
|
17074
17094
|
}
|
|
17075
17095
|
function startCloudSync() {
|
|
17076
|
-
const
|
|
17077
|
-
const intervalHours = Math.max(rawHours, MIN_INTERVAL_HOURS);
|
|
17078
|
-
const intervalMs = intervalHours * 60 * 60 * 1e3;
|
|
17096
|
+
const intervalMs = resolveSyncIntervalMs(getConfig().settings);
|
|
17079
17097
|
const initial = setTimeout(() => void syncOnce(), 3e4);
|
|
17080
17098
|
initial.unref();
|
|
17081
17099
|
const recurring = setInterval(() => void syncOnce(), intervalMs);
|
|
@@ -17100,7 +17118,7 @@ function startForensicBroadcast() {
|
|
|
17100
17118
|
const recurring = setInterval(() => void tick(), FORENSIC_BROADCAST_INTERVAL_MS);
|
|
17101
17119
|
recurring.unref();
|
|
17102
17120
|
}
|
|
17103
|
-
var FINDING_TO_SIGNAL3, rulesCacheFile, DEFAULT_API_URL, DEFAULT_INTERVAL_HOURS,
|
|
17121
|
+
var FINDING_TO_SIGNAL3, rulesCacheFile, DEFAULT_API_URL, DEFAULT_INTERVAL_HOURS, MIN_INTERVAL_SECONDS, MAX_INTERVAL_SECONDS, FORENSIC_BROADCAST_INTERVAL_MS, FORENSIC_INITIAL_DELAY_MS, forensicBroadcastOffsets;
|
|
17104
17122
|
var init_sync = __esm({
|
|
17105
17123
|
"src/daemon/sync.ts"() {
|
|
17106
17124
|
"use strict";
|
|
@@ -17130,7 +17148,8 @@ var init_sync = __esm({
|
|
|
17130
17148
|
rulesCacheFile = () => path31.join(os29.homedir(), ".node9", "rules-cache.json");
|
|
17131
17149
|
DEFAULT_API_URL = "https://api.node9.ai/api/v1/intercept/policies/sync";
|
|
17132
17150
|
DEFAULT_INTERVAL_HOURS = 5;
|
|
17133
|
-
|
|
17151
|
+
MIN_INTERVAL_SECONDS = 15;
|
|
17152
|
+
MAX_INTERVAL_SECONDS = 24 * 60 * 60;
|
|
17134
17153
|
FORENSIC_BROADCAST_INTERVAL_MS = 3e4;
|
|
17135
17154
|
FORENSIC_INITIAL_DELAY_MS = 5e3;
|
|
17136
17155
|
forensicBroadcastOffsets = /* @__PURE__ */ new Map();
|
package/dist/dashboard.mjs
CHANGED
|
@@ -2280,6 +2280,11 @@ var init_config_schema = __esm({
|
|
|
2280
2280
|
// must run them from the CLI. node9's threat model is the agent itself.
|
|
2281
2281
|
mcpAllowWeakening: z.boolean().optional(),
|
|
2282
2282
|
cloudSyncIntervalHours: z.number().positive().optional(),
|
|
2283
|
+
// Seconds-granular override for the cloud policy sync cadence. Wins over
|
|
2284
|
+
// cloudSyncIntervalHours when set. Lets you opt into fast apply (e.g. 20)
|
|
2285
|
+
// for an incident; clamped to a 15s floor so it can't hammer the API.
|
|
2286
|
+
// Unset → falls back to hours, then the 5h default.
|
|
2287
|
+
cloudSyncIntervalSeconds: z.number().positive().optional(),
|
|
2283
2288
|
// Outbox shipper (audit.log → SaaS batch ingest). enabled defaults
|
|
2284
2289
|
// to true; set false to fall back to local-only auditing.
|
|
2285
2290
|
shipper: z.object({
|
package/dist/index.js
CHANGED
|
@@ -322,6 +322,11 @@ var ConfigFileSchema = import_zod.z.object({
|
|
|
322
322
|
// must run them from the CLI. node9's threat model is the agent itself.
|
|
323
323
|
mcpAllowWeakening: import_zod.z.boolean().optional(),
|
|
324
324
|
cloudSyncIntervalHours: import_zod.z.number().positive().optional(),
|
|
325
|
+
// Seconds-granular override for the cloud policy sync cadence. Wins over
|
|
326
|
+
// cloudSyncIntervalHours when set. Lets you opt into fast apply (e.g. 20)
|
|
327
|
+
// for an incident; clamped to a 15s floor so it can't hammer the API.
|
|
328
|
+
// Unset → falls back to hours, then the 5h default.
|
|
329
|
+
cloudSyncIntervalSeconds: import_zod.z.number().positive().optional(),
|
|
325
330
|
// Outbox shipper (audit.log → SaaS batch ingest). enabled defaults
|
|
326
331
|
// to true; set false to fall back to local-only auditing.
|
|
327
332
|
shipper: import_zod.z.object({
|
|
@@ -3942,6 +3947,7 @@ function getConfig(cwd) {
|
|
|
3942
3947
|
};
|
|
3943
3948
|
applyLayer(globalConfig);
|
|
3944
3949
|
applyLayer(projectConfig);
|
|
3950
|
+
let cloudManagedShields = [];
|
|
3945
3951
|
{
|
|
3946
3952
|
const cacheFile = import_path3.default.join(import_os3.default.homedir(), ".node9", "rules-cache.json");
|
|
3947
3953
|
try {
|
|
@@ -3949,6 +3955,9 @@ function getConfig(cwd) {
|
|
|
3949
3955
|
if (Array.isArray(raw.rules) && raw.rules.length > 0) {
|
|
3950
3956
|
applyLayer({ policy: { smartRules: raw.rules } });
|
|
3951
3957
|
}
|
|
3958
|
+
if (Array.isArray(raw.shields)) {
|
|
3959
|
+
cloudManagedShields = raw.shields.filter((s) => typeof s === "string");
|
|
3960
|
+
}
|
|
3952
3961
|
if (raw.panicMode === true) {
|
|
3953
3962
|
mergedSettings.panicMode = true;
|
|
3954
3963
|
}
|
|
@@ -3959,7 +3968,8 @@ function getConfig(cwd) {
|
|
|
3959
3968
|
}
|
|
3960
3969
|
}
|
|
3961
3970
|
const shieldOverrides = readShieldOverrides();
|
|
3962
|
-
|
|
3971
|
+
const activeShieldNames = [.../* @__PURE__ */ new Set([...readActiveShields(), ...cloudManagedShields])];
|
|
3972
|
+
for (const shieldName of activeShieldNames) {
|
|
3963
3973
|
const shield = getShield(shieldName);
|
|
3964
3974
|
if (!shield) continue;
|
|
3965
3975
|
const existingRuleNames = new Set(mergedPolicy.smartRules.map((r) => r.name));
|
package/dist/index.mjs
CHANGED
|
@@ -292,6 +292,11 @@ var ConfigFileSchema = z.object({
|
|
|
292
292
|
// must run them from the CLI. node9's threat model is the agent itself.
|
|
293
293
|
mcpAllowWeakening: z.boolean().optional(),
|
|
294
294
|
cloudSyncIntervalHours: z.number().positive().optional(),
|
|
295
|
+
// Seconds-granular override for the cloud policy sync cadence. Wins over
|
|
296
|
+
// cloudSyncIntervalHours when set. Lets you opt into fast apply (e.g. 20)
|
|
297
|
+
// for an incident; clamped to a 15s floor so it can't hammer the API.
|
|
298
|
+
// Unset → falls back to hours, then the 5h default.
|
|
299
|
+
cloudSyncIntervalSeconds: z.number().positive().optional(),
|
|
295
300
|
// Outbox shipper (audit.log → SaaS batch ingest). enabled defaults
|
|
296
301
|
// to true; set false to fall back to local-only auditing.
|
|
297
302
|
shipper: z.object({
|
|
@@ -3912,6 +3917,7 @@ function getConfig(cwd) {
|
|
|
3912
3917
|
};
|
|
3913
3918
|
applyLayer(globalConfig);
|
|
3914
3919
|
applyLayer(projectConfig);
|
|
3920
|
+
let cloudManagedShields = [];
|
|
3915
3921
|
{
|
|
3916
3922
|
const cacheFile = path3.join(os3.homedir(), ".node9", "rules-cache.json");
|
|
3917
3923
|
try {
|
|
@@ -3919,6 +3925,9 @@ function getConfig(cwd) {
|
|
|
3919
3925
|
if (Array.isArray(raw.rules) && raw.rules.length > 0) {
|
|
3920
3926
|
applyLayer({ policy: { smartRules: raw.rules } });
|
|
3921
3927
|
}
|
|
3928
|
+
if (Array.isArray(raw.shields)) {
|
|
3929
|
+
cloudManagedShields = raw.shields.filter((s) => typeof s === "string");
|
|
3930
|
+
}
|
|
3922
3931
|
if (raw.panicMode === true) {
|
|
3923
3932
|
mergedSettings.panicMode = true;
|
|
3924
3933
|
}
|
|
@@ -3929,7 +3938,8 @@ function getConfig(cwd) {
|
|
|
3929
3938
|
}
|
|
3930
3939
|
}
|
|
3931
3940
|
const shieldOverrides = readShieldOverrides();
|
|
3932
|
-
|
|
3941
|
+
const activeShieldNames = [.../* @__PURE__ */ new Set([...readActiveShields(), ...cloudManagedShields])];
|
|
3942
|
+
for (const shieldName of activeShieldNames) {
|
|
3933
3943
|
const shield = getShield(shieldName);
|
|
3934
3944
|
if (!shield) continue;
|
|
3935
3945
|
const existingRuleNames = new Set(mergedPolicy.smartRules.map((r) => r.name));
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@node9/proxy",
|
|
3
|
-
"version": "1.
|
|
3
|
+
"version": "1.48.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",
|