@node9/proxy 1.67.4 → 2.0.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.
@@ -2376,7 +2376,11 @@ var init_config_schema = __esm({
2376
2376
  settings: z.object({
2377
2377
  mode: z.enum(["standard", "strict", "audit", "observe"]).optional(),
2378
2378
  autoStartDaemon: z.boolean().optional(),
2379
- enableUndo: z.boolean().optional(),
2379
+ // enableUndo / policy.snapshot: removed with the undo feature. The
2380
+ // schema strips undeclared keys silently (plain zod object — no
2381
+ // .strict(), no .passthrough()), so a config still carrying them stays
2382
+ // valid and simply loses them. Keeping the fields would instead make
2383
+ // `node9_config_get` advertise a removed feature as a live knob.
2380
2384
  enableHookLogDebug: z.boolean().optional(),
2381
2385
  approvalTimeoutMs: z.number().nonnegative().optional(),
2382
2386
  approvalTimeoutSeconds: z.number().nonnegative().optional(),
@@ -2428,11 +2432,6 @@ var init_config_schema = __esm({
2428
2432
  ignoredTools: z.array(z.string()).optional(),
2429
2433
  toolInspection: z.record(z.string()).optional(),
2430
2434
  smartRules: z.array(SmartRuleSchema).optional(),
2431
- snapshot: z.object({
2432
- tools: z.array(z.string()).optional(),
2433
- onlyPaths: z.array(z.string()).optional(),
2434
- ignorePaths: z.array(z.string()).optional()
2435
- }).optional(),
2436
2435
  dlp: z.object({
2437
2436
  enabled: z.boolean().optional(),
2438
2437
  scanIgnoredTools: z.boolean().optional(),
@@ -2597,14 +2596,6 @@ var init_config = __esm({
2597
2596
  settings: {
2598
2597
  mode: "standard",
2599
2598
  autoStartDaemon: true,
2600
- // OFF by default. The snapshot store is a per-project bare git repo with
2601
- // no size ceiling, and eviction drops the index row without deleting the
2602
- // objects — on one machine it reached 378G (352G of it orphaned tmp_pack_*
2603
- // from interrupted `git gc`) and filled the disk. A security tool must not
2604
- // be what fills a customer's disk. Re-enable per install with
2605
- // `{"settings":{"enableUndo":true}}`; the default flips back when the
2606
- // bounded copy-store lands (doc/undo-v2-copy-store-design.md).
2607
- enableUndo: false,
2608
2599
  enableHookLogDebug: true,
2609
2600
  approvalTimeoutMs: 12e4,
2610
2601
  // 120-second auto-deny timeout
@@ -2645,25 +2636,6 @@ var init_config = __esm({
2645
2636
  "terminal.execute": "command",
2646
2637
  "postgres:query": "sql"
2647
2638
  },
2648
- snapshot: {
2649
- tools: [
2650
- "str_replace_based_edit_tool",
2651
- "write_file",
2652
- "edit_file",
2653
- "create_file",
2654
- "edit",
2655
- "replace",
2656
- // Claude / canonicalised Hermes — shouldSnapshot lowercases the
2657
- // incoming name before set-membership, so we list the lowercase
2658
- // forms of `Bash`/`Write`/`Edit`/`MultiEdit`. Without these,
2659
- // post-canonicalisation Hermes `patch` / `write_file` (which now
2660
- // arrive as `Edit` / `Write`) silently skipped snapshotting.
2661
- "write",
2662
- "multiedit"
2663
- ],
2664
- onlyPaths: [],
2665
- ignorePaths: ["**/node_modules/**", "dist/**", "build/**", ".next/**", "**/*.log"]
2666
- },
2667
2639
  smartRules: [
2668
2640
  // ── rm safety (critical — always evaluated first) ──────────────────────
2669
2641
  {
@@ -3915,7 +3887,6 @@ var init_provenance = __esm({
3915
3887
  });
3916
3888
 
3917
3889
  // src/policy/index.ts
3918
- import pm2 from "picomatch";
3919
3890
  var init_policy = __esm({
3920
3891
  "src/policy/index.ts"() {
3921
3892
  "use strict";
@@ -5438,17 +5409,6 @@ function subscribeToSse(onEvent, onResolve, onForensic, onError) {
5438
5409
  function toActivityEvent(eventName, data) {
5439
5410
  const payload = data.activity ?? data;
5440
5411
  const ts = normalizeTs(payload.ts);
5441
- if (eventName === "snapshot") {
5442
- const rawSummary = payload.argsSummary ?? payload.tool ?? "snapshot";
5443
- return {
5444
- kind: "snapshot",
5445
- id: payload.id ?? `${ts}-snapshot`,
5446
- ts,
5447
- hash: payload.hash ?? "",
5448
- summary: compactPath(rawSummary),
5449
- fileCount: typeof payload.fileCount === "number" ? payload.fileCount : 0
5450
- };
5451
- }
5452
5412
  if (eventName !== "activity" && eventName !== "add") return null;
5453
5413
  const toolName = payload.tool ?? payload.toolName;
5454
5414
  if (!toolName) return null;
@@ -5839,9 +5799,6 @@ function applyFilter(events, filter) {
5839
5799
  if (!filter) return events;
5840
5800
  const needle = filter.toLowerCase();
5841
5801
  return events.filter((e) => {
5842
- if (e.kind === "snapshot") {
5843
- return e.hash.toLowerCase().includes(needle) || e.summary.toLowerCase().includes(needle);
5844
- }
5845
5802
  if (e.tool.toLowerCase().includes(needle)) return true;
5846
5803
  if (e.agent && e.agent.toLowerCase().includes(needle)) return true;
5847
5804
  if (e.preview.toLowerCase().includes(needle)) return true;
@@ -5852,19 +5809,6 @@ function applyFilter(events, filter) {
5852
5809
  }
5853
5810
  function ActivityRow({ event }) {
5854
5811
  const t = localTimeOf(event.ts);
5855
- if (event.kind === "snapshot") {
5856
- const filesSuffix = event.fileCount > 0 ? ` \xB7 ${event.fileCount} file${event.fileCount === 1 ? "" : "s"}` : "";
5857
- return /* @__PURE__ */ jsxs(Text, { wrap: "truncate-end", children: [
5858
- /* @__PURE__ */ jsxs(Text, { dimColor: true, children: [
5859
- t,
5860
- " "
5861
- ] }),
5862
- /* @__PURE__ */ jsx(Text, { color: COL.agentClaude, children: "\u{1F4F8} snapshot" }),
5863
- /* @__PURE__ */ jsx(Text, { dimColor: true, children: ` ${event.hash} ` }),
5864
- /* @__PURE__ */ jsx(Text, { children: event.summary }),
5865
- /* @__PURE__ */ jsx(Text, { dimColor: true, children: filesSuffix })
5866
- ] });
5867
- }
5868
5812
  const agentLabel = event.agent ? `[${truncate(capitalize(event.agent), 8)}]`.padEnd(10) : " ".repeat(10);
5869
5813
  const isLoop = event.checkedBy === "loop-detected";
5870
5814
  const verdictIcon = isLoop ? "\u{1F501}" : event.verdict === "block" ? "\u{1F6D1}" : event.verdict === "review" ? "\u{1F7E1}" : event.verdict === "allow" ? "\u2713 " : "\u2026 ";
package/dist/index.js CHANGED
@@ -295,7 +295,11 @@ var ConfigFileSchema = import_zod.z.object({
295
295
  settings: import_zod.z.object({
296
296
  mode: import_zod.z.enum(["standard", "strict", "audit", "observe"]).optional(),
297
297
  autoStartDaemon: import_zod.z.boolean().optional(),
298
- enableUndo: import_zod.z.boolean().optional(),
298
+ // enableUndo / policy.snapshot: removed with the undo feature. The
299
+ // schema strips undeclared keys silently (plain zod object — no
300
+ // .strict(), no .passthrough()), so a config still carrying them stays
301
+ // valid and simply loses them. Keeping the fields would instead make
302
+ // `node9_config_get` advertise a removed feature as a live knob.
299
303
  enableHookLogDebug: import_zod.z.boolean().optional(),
300
304
  approvalTimeoutMs: import_zod.z.number().nonnegative().optional(),
301
305
  approvalTimeoutSeconds: import_zod.z.number().nonnegative().optional(),
@@ -347,11 +351,6 @@ var ConfigFileSchema = import_zod.z.object({
347
351
  ignoredTools: import_zod.z.array(import_zod.z.string()).optional(),
348
352
  toolInspection: import_zod.z.record(import_zod.z.string()).optional(),
349
353
  smartRules: import_zod.z.array(SmartRuleSchema).optional(),
350
- snapshot: import_zod.z.object({
351
- tools: import_zod.z.array(import_zod.z.string()).optional(),
352
- onlyPaths: import_zod.z.array(import_zod.z.string()).optional(),
353
- ignorePaths: import_zod.z.array(import_zod.z.string()).optional()
354
- }).optional(),
355
354
  dlp: import_zod.z.object({
356
355
  enabled: import_zod.z.boolean().optional(),
357
356
  scanIgnoredTools: import_zod.z.boolean().optional(),
@@ -4181,14 +4180,6 @@ var DEFAULT_CONFIG = {
4181
4180
  settings: {
4182
4181
  mode: "standard",
4183
4182
  autoStartDaemon: true,
4184
- // OFF by default. The snapshot store is a per-project bare git repo with
4185
- // no size ceiling, and eviction drops the index row without deleting the
4186
- // objects — on one machine it reached 378G (352G of it orphaned tmp_pack_*
4187
- // from interrupted `git gc`) and filled the disk. A security tool must not
4188
- // be what fills a customer's disk. Re-enable per install with
4189
- // `{"settings":{"enableUndo":true}}`; the default flips back when the
4190
- // bounded copy-store lands (doc/undo-v2-copy-store-design.md).
4191
- enableUndo: false,
4192
4183
  enableHookLogDebug: true,
4193
4184
  approvalTimeoutMs: 12e4,
4194
4185
  // 120-second auto-deny timeout
@@ -4229,25 +4220,6 @@ var DEFAULT_CONFIG = {
4229
4220
  "terminal.execute": "command",
4230
4221
  "postgres:query": "sql"
4231
4222
  },
4232
- snapshot: {
4233
- tools: [
4234
- "str_replace_based_edit_tool",
4235
- "write_file",
4236
- "edit_file",
4237
- "create_file",
4238
- "edit",
4239
- "replace",
4240
- // Claude / canonicalised Hermes — shouldSnapshot lowercases the
4241
- // incoming name before set-membership, so we list the lowercase
4242
- // forms of `Bash`/`Write`/`Edit`/`MultiEdit`. Without these,
4243
- // post-canonicalisation Hermes `patch` / `write_file` (which now
4244
- // arrive as `Edit` / `Write`) silently skipped snapshotting.
4245
- "write",
4246
- "multiedit"
4247
- ],
4248
- onlyPaths: [],
4249
- ignorePaths: ["**/node_modules/**", "dist/**", "build/**", ".next/**", "**/*.log"]
4250
- },
4251
4223
  smartRules: [
4252
4224
  // ── rm safety (critical — always evaluated first) ──────────────────────
4253
4225
  {
@@ -4558,11 +4530,6 @@ function getConfig(cwd) {
4558
4530
  ignoredTools: [...DEFAULT_CONFIG.policy.ignoredTools],
4559
4531
  toolInspection: { ...DEFAULT_CONFIG.policy.toolInspection },
4560
4532
  smartRules: [...DEFAULT_CONFIG.policy.smartRules],
4561
- snapshot: {
4562
- tools: [...DEFAULT_CONFIG.policy.snapshot.tools],
4563
- onlyPaths: [...DEFAULT_CONFIG.policy.snapshot.onlyPaths],
4564
- ignorePaths: [...DEFAULT_CONFIG.policy.snapshot.ignorePaths]
4565
- },
4566
4533
  dlp: { ...DEFAULT_CONFIG.policy.dlp },
4567
4534
  egress: {
4568
4535
  ...DEFAULT_CONFIG.policy.egress,
@@ -4597,7 +4564,6 @@ function getConfig(cwd) {
4597
4564
  const p = source.policy || {};
4598
4565
  if (s.mode !== void 0) mergedSettings.mode = s.mode;
4599
4566
  if (s.autoStartDaemon !== void 0) mergedSettings.autoStartDaemon = s.autoStartDaemon;
4600
- if (s.enableUndo !== void 0) mergedSettings.enableUndo = s.enableUndo;
4601
4567
  if (s.enableHookLogDebug !== void 0)
4602
4568
  mergedSettings.enableHookLogDebug = s.enableHookLogDebug;
4603
4569
  if (s.approvers) mergedSettings.approvers = { ...mergedSettings.approvers, ...s.approvers };
@@ -4631,12 +4597,6 @@ function getConfig(cwd) {
4631
4597
  );
4632
4598
  mergedPolicy.smartRules = [...filteredBlocks, ...localRules, ...filteredNonBlocks];
4633
4599
  }
4634
- if (p.snapshot) {
4635
- const s2 = p.snapshot;
4636
- if (s2.tools) mergedPolicy.snapshot.tools.push(...s2.tools);
4637
- if (s2.onlyPaths) mergedPolicy.snapshot.onlyPaths.push(...s2.onlyPaths);
4638
- if (s2.ignorePaths) mergedPolicy.snapshot.ignorePaths.push(...s2.ignorePaths);
4639
- }
4640
4600
  if (p.dlp) {
4641
4601
  const d = p.dlp;
4642
4602
  if (d.enabled !== void 0) mergedPolicy.dlp.enabled = d.enabled;
@@ -4971,9 +4931,6 @@ function getConfig(cwd) {
4971
4931
  mergedPolicy.dangerousWords = [...new Set(mergedPolicy.dangerousWords)];
4972
4932
  mergedPolicy.ignoredTools = [...new Set(mergedPolicy.ignoredTools)];
4973
4933
  mergedPolicy.skillPinning.roots = [...new Set(mergedPolicy.skillPinning.roots)];
4974
- mergedPolicy.snapshot.tools = [...new Set(mergedPolicy.snapshot.tools)];
4975
- mergedPolicy.snapshot.onlyPaths = [...new Set(mergedPolicy.snapshot.onlyPaths)];
4976
- mergedPolicy.snapshot.ignorePaths = [...new Set(mergedPolicy.snapshot.ignorePaths)];
4977
4934
  const result = {
4978
4935
  settings: mergedSettings,
4979
4936
  policy: mergedPolicy,
@@ -5036,9 +4993,6 @@ ${error.replace("Invalid config:\n", "")}
5036
4993
  return sanitized;
5037
4994
  }
5038
4995
 
5039
- // src/policy/index.ts
5040
- var import_picomatch2 = __toESM(require("picomatch"));
5041
-
5042
4996
  // src/dlp.ts
5043
4997
  var import_fs5 = __toESM(require("fs"));
5044
4998
  var import_path5 = __toESM(require("path"));
package/dist/index.mjs CHANGED
@@ -265,7 +265,11 @@ var ConfigFileSchema = z.object({
265
265
  settings: z.object({
266
266
  mode: z.enum(["standard", "strict", "audit", "observe"]).optional(),
267
267
  autoStartDaemon: z.boolean().optional(),
268
- enableUndo: z.boolean().optional(),
268
+ // enableUndo / policy.snapshot: removed with the undo feature. The
269
+ // schema strips undeclared keys silently (plain zod object — no
270
+ // .strict(), no .passthrough()), so a config still carrying them stays
271
+ // valid and simply loses them. Keeping the fields would instead make
272
+ // `node9_config_get` advertise a removed feature as a live knob.
269
273
  enableHookLogDebug: z.boolean().optional(),
270
274
  approvalTimeoutMs: z.number().nonnegative().optional(),
271
275
  approvalTimeoutSeconds: z.number().nonnegative().optional(),
@@ -317,11 +321,6 @@ var ConfigFileSchema = z.object({
317
321
  ignoredTools: z.array(z.string()).optional(),
318
322
  toolInspection: z.record(z.string()).optional(),
319
323
  smartRules: z.array(SmartRuleSchema).optional(),
320
- snapshot: z.object({
321
- tools: z.array(z.string()).optional(),
322
- onlyPaths: z.array(z.string()).optional(),
323
- ignorePaths: z.array(z.string()).optional()
324
- }).optional(),
325
324
  dlp: z.object({
326
325
  enabled: z.boolean().optional(),
327
326
  scanIgnoredTools: z.boolean().optional(),
@@ -4151,14 +4150,6 @@ var DEFAULT_CONFIG = {
4151
4150
  settings: {
4152
4151
  mode: "standard",
4153
4152
  autoStartDaemon: true,
4154
- // OFF by default. The snapshot store is a per-project bare git repo with
4155
- // no size ceiling, and eviction drops the index row without deleting the
4156
- // objects — on one machine it reached 378G (352G of it orphaned tmp_pack_*
4157
- // from interrupted `git gc`) and filled the disk. A security tool must not
4158
- // be what fills a customer's disk. Re-enable per install with
4159
- // `{"settings":{"enableUndo":true}}`; the default flips back when the
4160
- // bounded copy-store lands (doc/undo-v2-copy-store-design.md).
4161
- enableUndo: false,
4162
4153
  enableHookLogDebug: true,
4163
4154
  approvalTimeoutMs: 12e4,
4164
4155
  // 120-second auto-deny timeout
@@ -4199,25 +4190,6 @@ var DEFAULT_CONFIG = {
4199
4190
  "terminal.execute": "command",
4200
4191
  "postgres:query": "sql"
4201
4192
  },
4202
- snapshot: {
4203
- tools: [
4204
- "str_replace_based_edit_tool",
4205
- "write_file",
4206
- "edit_file",
4207
- "create_file",
4208
- "edit",
4209
- "replace",
4210
- // Claude / canonicalised Hermes — shouldSnapshot lowercases the
4211
- // incoming name before set-membership, so we list the lowercase
4212
- // forms of `Bash`/`Write`/`Edit`/`MultiEdit`. Without these,
4213
- // post-canonicalisation Hermes `patch` / `write_file` (which now
4214
- // arrive as `Edit` / `Write`) silently skipped snapshotting.
4215
- "write",
4216
- "multiedit"
4217
- ],
4218
- onlyPaths: [],
4219
- ignorePaths: ["**/node_modules/**", "dist/**", "build/**", ".next/**", "**/*.log"]
4220
- },
4221
4193
  smartRules: [
4222
4194
  // ── rm safety (critical — always evaluated first) ──────────────────────
4223
4195
  {
@@ -4528,11 +4500,6 @@ function getConfig(cwd) {
4528
4500
  ignoredTools: [...DEFAULT_CONFIG.policy.ignoredTools],
4529
4501
  toolInspection: { ...DEFAULT_CONFIG.policy.toolInspection },
4530
4502
  smartRules: [...DEFAULT_CONFIG.policy.smartRules],
4531
- snapshot: {
4532
- tools: [...DEFAULT_CONFIG.policy.snapshot.tools],
4533
- onlyPaths: [...DEFAULT_CONFIG.policy.snapshot.onlyPaths],
4534
- ignorePaths: [...DEFAULT_CONFIG.policy.snapshot.ignorePaths]
4535
- },
4536
4503
  dlp: { ...DEFAULT_CONFIG.policy.dlp },
4537
4504
  egress: {
4538
4505
  ...DEFAULT_CONFIG.policy.egress,
@@ -4567,7 +4534,6 @@ function getConfig(cwd) {
4567
4534
  const p = source.policy || {};
4568
4535
  if (s.mode !== void 0) mergedSettings.mode = s.mode;
4569
4536
  if (s.autoStartDaemon !== void 0) mergedSettings.autoStartDaemon = s.autoStartDaemon;
4570
- if (s.enableUndo !== void 0) mergedSettings.enableUndo = s.enableUndo;
4571
4537
  if (s.enableHookLogDebug !== void 0)
4572
4538
  mergedSettings.enableHookLogDebug = s.enableHookLogDebug;
4573
4539
  if (s.approvers) mergedSettings.approvers = { ...mergedSettings.approvers, ...s.approvers };
@@ -4601,12 +4567,6 @@ function getConfig(cwd) {
4601
4567
  );
4602
4568
  mergedPolicy.smartRules = [...filteredBlocks, ...localRules, ...filteredNonBlocks];
4603
4569
  }
4604
- if (p.snapshot) {
4605
- const s2 = p.snapshot;
4606
- if (s2.tools) mergedPolicy.snapshot.tools.push(...s2.tools);
4607
- if (s2.onlyPaths) mergedPolicy.snapshot.onlyPaths.push(...s2.onlyPaths);
4608
- if (s2.ignorePaths) mergedPolicy.snapshot.ignorePaths.push(...s2.ignorePaths);
4609
- }
4610
4570
  if (p.dlp) {
4611
4571
  const d = p.dlp;
4612
4572
  if (d.enabled !== void 0) mergedPolicy.dlp.enabled = d.enabled;
@@ -4941,9 +4901,6 @@ function getConfig(cwd) {
4941
4901
  mergedPolicy.dangerousWords = [...new Set(mergedPolicy.dangerousWords)];
4942
4902
  mergedPolicy.ignoredTools = [...new Set(mergedPolicy.ignoredTools)];
4943
4903
  mergedPolicy.skillPinning.roots = [...new Set(mergedPolicy.skillPinning.roots)];
4944
- mergedPolicy.snapshot.tools = [...new Set(mergedPolicy.snapshot.tools)];
4945
- mergedPolicy.snapshot.onlyPaths = [...new Set(mergedPolicy.snapshot.onlyPaths)];
4946
- mergedPolicy.snapshot.ignorePaths = [...new Set(mergedPolicy.snapshot.ignorePaths)];
4947
4904
  const result = {
4948
4905
  settings: mergedSettings,
4949
4906
  policy: mergedPolicy,
@@ -5006,9 +4963,6 @@ ${error.replace("Invalid config:\n", "")}
5006
4963
  return sanitized;
5007
4964
  }
5008
4965
 
5009
- // src/policy/index.ts
5010
- import pm2 from "picomatch";
5011
-
5012
4966
  // src/dlp.ts
5013
4967
  import fs5 from "fs";
5014
4968
  import path5 from "path";
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@node9/proxy",
3
- "version": "1.67.4",
3
+ "version": "2.0.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",