@node9/proxy 1.40.0 → 1.42.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.
@@ -2265,6 +2265,11 @@ var init_config_schema = __esm({
2265
2265
  allowGlobalPause: z.boolean().optional(),
2266
2266
  auditHashArgs: z.boolean().optional(),
2267
2267
  agentPolicy: z.enum(["require_approval", "block_on_rules"]).optional(),
2268
+ // Where a `review` verdict's prompt is rendered: 'ask' = the agent's own
2269
+ // inline approve/deny prompt (Claude Code / GitHub Copilot); 'approver' =
2270
+ // node9's own approver (terminal/native/cloud). Unset → smart default
2271
+ // (ask for ask-capable agents unless a cloud approver is configured).
2272
+ reviewChannel: z.enum(["ask", "approver"]).optional(),
2268
2273
  cloudSyncIntervalHours: z.number().positive().optional(),
2269
2274
  // Outbox shipper (audit.log → SaaS batch ingest). enabled defaults
2270
2275
  // to true; set false to fall back to local-only auditing.
package/dist/index.js CHANGED
@@ -278,6 +278,11 @@ var ConfigFileSchema = import_zod.z.object({
278
278
  allowGlobalPause: import_zod.z.boolean().optional(),
279
279
  auditHashArgs: import_zod.z.boolean().optional(),
280
280
  agentPolicy: import_zod.z.enum(["require_approval", "block_on_rules"]).optional(),
281
+ // Where a `review` verdict's prompt is rendered: 'ask' = the agent's own
282
+ // inline approve/deny prompt (Claude Code / GitHub Copilot); 'approver' =
283
+ // node9's own approver (terminal/native/cloud). Unset → smart default
284
+ // (ask for ask-capable agents unless a cloud approver is configured).
285
+ reviewChannel: import_zod.z.enum(["ask", "approver"]).optional(),
281
286
  cloudSyncIntervalHours: import_zod.z.number().positive().optional(),
282
287
  // Outbox shipper (audit.log → SaaS batch ingest). enabled defaults
283
288
  // to true; set false to fall back to local-only auditing.
@@ -3731,6 +3736,7 @@ function getConfig(cwd) {
3731
3736
  if (s.approvalTimeoutSeconds !== void 0 && s.approvalTimeoutMs === void 0)
3732
3737
  mergedSettings.approvalTimeoutMs = s.approvalTimeoutSeconds * 1e3;
3733
3738
  if (s.environment !== void 0) mergedSettings.environment = s.environment;
3739
+ if (s.reviewChannel !== void 0) mergedSettings.reviewChannel = s.reviewChannel;
3734
3740
  if (s.cloudSyncIntervalHours !== void 0)
3735
3741
  mergedSettings.cloudSyncIntervalHours = s.cloudSyncIntervalHours;
3736
3742
  if (s.hud !== void 0) mergedSettings.hud = { ...mergedSettings.hud, ...s.hud };
@@ -5006,7 +5012,7 @@ async function authorizeHeadless(toolName, args, meta, options) {
5006
5012
  tool: toolName,
5007
5013
  args,
5008
5014
  ts: actTs,
5009
- status: result.approved ? "allow" : result.blockedByLabel?.includes("DLP") ? "dlp" : result.blockedByLabel?.includes("Taint") ? "taint" : "block",
5015
+ status: result.review ? "review" : result.approved ? "allow" : result.blockedByLabel?.includes("DLP") ? "dlp" : result.blockedByLabel?.includes("Taint") ? "taint" : "block",
5010
5016
  label: result.blockedByLabel,
5011
5017
  ruleHit: result.ruleHit,
5012
5018
  observeWouldBlock: result.observeWouldBlock,
@@ -5369,6 +5375,16 @@ async function _authorizeHeadlessCore(toolName, args, metaArg, options) {
5369
5375
  taintWarning
5370
5376
  );
5371
5377
  }
5378
+ const cloudEnforcedForDefer = approvers.cloud && !!creds?.apiKey;
5379
+ if (options?.deferReview && !taintWarning && !cloudEnforcedForDefer) {
5380
+ return {
5381
+ approved: false,
5382
+ review: true,
5383
+ reason: explainableLabel || "Node9 flagged this action for review.",
5384
+ ruleDescription: policyRuleDescription,
5385
+ blockedByLabel: explainableLabel
5386
+ };
5387
+ }
5372
5388
  let cloudRequestId = null;
5373
5389
  const cloudEnforced = approvers.cloud && !!creds?.apiKey;
5374
5390
  const forceReview = localSmartRuleMatched === true || options?.localSmartRuleMatched === true || void 0;
package/dist/index.mjs CHANGED
@@ -248,6 +248,11 @@ var ConfigFileSchema = z.object({
248
248
  allowGlobalPause: z.boolean().optional(),
249
249
  auditHashArgs: z.boolean().optional(),
250
250
  agentPolicy: z.enum(["require_approval", "block_on_rules"]).optional(),
251
+ // Where a `review` verdict's prompt is rendered: 'ask' = the agent's own
252
+ // inline approve/deny prompt (Claude Code / GitHub Copilot); 'approver' =
253
+ // node9's own approver (terminal/native/cloud). Unset → smart default
254
+ // (ask for ask-capable agents unless a cloud approver is configured).
255
+ reviewChannel: z.enum(["ask", "approver"]).optional(),
251
256
  cloudSyncIntervalHours: z.number().positive().optional(),
252
257
  // Outbox shipper (audit.log → SaaS batch ingest). enabled defaults
253
258
  // to true; set false to fall back to local-only auditing.
@@ -3701,6 +3706,7 @@ function getConfig(cwd) {
3701
3706
  if (s.approvalTimeoutSeconds !== void 0 && s.approvalTimeoutMs === void 0)
3702
3707
  mergedSettings.approvalTimeoutMs = s.approvalTimeoutSeconds * 1e3;
3703
3708
  if (s.environment !== void 0) mergedSettings.environment = s.environment;
3709
+ if (s.reviewChannel !== void 0) mergedSettings.reviewChannel = s.reviewChannel;
3704
3710
  if (s.cloudSyncIntervalHours !== void 0)
3705
3711
  mergedSettings.cloudSyncIntervalHours = s.cloudSyncIntervalHours;
3706
3712
  if (s.hud !== void 0) mergedSettings.hud = { ...mergedSettings.hud, ...s.hud };
@@ -4976,7 +4982,7 @@ async function authorizeHeadless(toolName, args, meta, options) {
4976
4982
  tool: toolName,
4977
4983
  args,
4978
4984
  ts: actTs,
4979
- status: result.approved ? "allow" : result.blockedByLabel?.includes("DLP") ? "dlp" : result.blockedByLabel?.includes("Taint") ? "taint" : "block",
4985
+ status: result.review ? "review" : result.approved ? "allow" : result.blockedByLabel?.includes("DLP") ? "dlp" : result.blockedByLabel?.includes("Taint") ? "taint" : "block",
4980
4986
  label: result.blockedByLabel,
4981
4987
  ruleHit: result.ruleHit,
4982
4988
  observeWouldBlock: result.observeWouldBlock,
@@ -5339,6 +5345,16 @@ async function _authorizeHeadlessCore(toolName, args, metaArg, options) {
5339
5345
  taintWarning
5340
5346
  );
5341
5347
  }
5348
+ const cloudEnforcedForDefer = approvers.cloud && !!creds?.apiKey;
5349
+ if (options?.deferReview && !taintWarning && !cloudEnforcedForDefer) {
5350
+ return {
5351
+ approved: false,
5352
+ review: true,
5353
+ reason: explainableLabel || "Node9 flagged this action for review.",
5354
+ ruleDescription: policyRuleDescription,
5355
+ blockedByLabel: explainableLabel
5356
+ };
5357
+ }
5342
5358
  let cloudRequestId = null;
5343
5359
  const cloudEnforced = approvers.cloud && !!creds?.apiKey;
5344
5360
  const forceReview = localSmartRuleMatched === true || options?.localSmartRuleMatched === true || void 0;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@node9/proxy",
3
- "version": "1.40.0",
3
+ "version": "1.42.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",