@node9/proxy 1.41.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.
package/README.md CHANGED
@@ -141,6 +141,23 @@ node9 shield list # show all shields + status
141
141
  - **Auto-undo** — git snapshot before every AI file edit → `node9 undo` to revert
142
142
  - **Skills pinning** — SHA-256 verification of installed Claude skills / plugins between sessions
143
143
 
144
+ ## Review prompts — approve inline, in your agent
145
+
146
+ When node9 flags an action for **review** (e.g. `git push --force`, a `DROP TABLE`), the approve/deny prompt renders **inline in the agent conversation** — no frozen session, no separate terminal, no hook-timeout race. node9 still runs the full evaluator and makes the decision; only the prompt _surface_ moves to the agent.
147
+
148
+ - **On by default** for **Claude Code** and **GitHub Copilot CLI** — the agents whose hook contract honors a native `ask`. Every other agent (Codex, Gemini, Antigravity, Hermes, Cursor, OpenCode, Pi) uses node9's own approver.
149
+ - **Control it** with `reviewChannel` in `~/.node9/config.json` (or `--no-ask` on the hook):
150
+
151
+ ```jsonc
152
+ {
153
+ "settings": {
154
+ "reviewChannel": "ask", // "ask" = inline agent prompt (default) | "approver" = node9's own approver
155
+ },
156
+ }
157
+ ```
158
+
159
+ - **Team setups:** when a cloud/team approver is configured (`approvers.cloud: true`), reviews route to that approver instead — node9 won't let an inline self-approval bypass routed/second-party approval.
160
+
144
161
  ## Sandbox — run an agent in a jail
145
162
 
146
163
  When watching isn't enough, **`node9 sandbox`** runs the agent inside a disposable container with a **kernel-enforced egress allowlist** and **scoped mounts** — while node9's hooks govern and audit every tool call _inside_ the box. The hard version of protection: the agent can only touch the folder you mount and reach the hosts you allow; everything else is dropped at the kernel.
package/dist/cli.js CHANGED
@@ -23429,6 +23429,38 @@ var TOOLS = [
23429
23429
  required: []
23430
23430
  }
23431
23431
  },
23432
+ {
23433
+ name: "node9_posture",
23434
+ description: "Run the node9 security posture scorecard for the agent on this host \u2014 grades how exposed the machine is to a compromised agent across isolation, egress, secrets-on-disk, supply chain, and privilege, with the #1 risk and a concrete fix for each finding. Read-only.",
23435
+ inputSchema: {
23436
+ type: "object",
23437
+ properties: {
23438
+ agent: {
23439
+ type: "string",
23440
+ description: "Optional label / policy scope for the agent being graded."
23441
+ }
23442
+ },
23443
+ required: []
23444
+ }
23445
+ },
23446
+ {
23447
+ name: "node9_explain",
23448
+ description: 'Preview exactly how node9 would evaluate a tool call BEFORE running it \u2014 the full allow / review / block waterfall and step-by-step policy trace. Use this to self-check a command (e.g. "git push --force") and see whether it would be allowed, sent for human review, or blocked, and why. Read-only \u2014 nothing executes.',
23449
+ inputSchema: {
23450
+ type: "object",
23451
+ properties: {
23452
+ tool: {
23453
+ type: "string",
23454
+ description: 'Tool name to evaluate. Defaults to "bash" for plain shell commands.'
23455
+ },
23456
+ args: {
23457
+ type: "string",
23458
+ description: 'Tool arguments as JSON, or a plain shell command string (e.g. "git push --force").'
23459
+ }
23460
+ },
23461
+ required: []
23462
+ }
23463
+ },
23432
23464
  {
23433
23465
  name: "node9_rule_add",
23434
23466
  description: 'Add a new protective smart rule to the global node9 config (~/.node9/config.json). Rules can block or send dangerous commands for human review based on regex conditions. IMPORTANT: only "block" and "review" verdicts are permitted \u2014 "allow" rules are never accepted because they would weaken node9 security. Rules can only be added, never removed.',
@@ -23735,6 +23767,17 @@ function handleSessionMcp(args) {
23735
23767
  if (typeof args.detail === "string" && args.detail) cliArgs.push("--detail", args.detail);
23736
23768
  return runCliCommand(cliArgs);
23737
23769
  }
23770
+ function handlePostureMcp(args) {
23771
+ const cliArgs = ["posture"];
23772
+ if (typeof args.agent === "string" && args.agent) cliArgs.push("--agent", args.agent);
23773
+ return runCliCommand(cliArgs);
23774
+ }
23775
+ function handleExplainMcp(args) {
23776
+ const tool = typeof args.tool === "string" && args.tool ? args.tool : "bash";
23777
+ const cliArgs = ["explain", tool];
23778
+ if (typeof args.args === "string" && args.args) cliArgs.push(args.args);
23779
+ return runCliCommand(cliArgs);
23780
+ }
23738
23781
  function handleUndoList(args) {
23739
23782
  const cwdFilter = typeof args.cwd === "string" && args.cwd ? args.cwd : null;
23740
23783
  let history = getSnapshotHistory();
@@ -23869,6 +23912,10 @@ function runMcpServer() {
23869
23912
  text = handleReportMcp(toolArgs);
23870
23913
  } else if (toolName === "node9_session") {
23871
23914
  text = handleSessionMcp(toolArgs);
23915
+ } else if (toolName === "node9_posture") {
23916
+ text = handlePostureMcp(toolArgs);
23917
+ } else if (toolName === "node9_explain") {
23918
+ text = handleExplainMcp(toolArgs);
23872
23919
  } else {
23873
23920
  process.stdout.write(err(id, -32601, `Unknown tool: ${toolName}`) + "\n");
23874
23921
  return;
package/dist/cli.mjs CHANGED
@@ -23401,6 +23401,38 @@ var TOOLS = [
23401
23401
  required: []
23402
23402
  }
23403
23403
  },
23404
+ {
23405
+ name: "node9_posture",
23406
+ description: "Run the node9 security posture scorecard for the agent on this host \u2014 grades how exposed the machine is to a compromised agent across isolation, egress, secrets-on-disk, supply chain, and privilege, with the #1 risk and a concrete fix for each finding. Read-only.",
23407
+ inputSchema: {
23408
+ type: "object",
23409
+ properties: {
23410
+ agent: {
23411
+ type: "string",
23412
+ description: "Optional label / policy scope for the agent being graded."
23413
+ }
23414
+ },
23415
+ required: []
23416
+ }
23417
+ },
23418
+ {
23419
+ name: "node9_explain",
23420
+ description: 'Preview exactly how node9 would evaluate a tool call BEFORE running it \u2014 the full allow / review / block waterfall and step-by-step policy trace. Use this to self-check a command (e.g. "git push --force") and see whether it would be allowed, sent for human review, or blocked, and why. Read-only \u2014 nothing executes.',
23421
+ inputSchema: {
23422
+ type: "object",
23423
+ properties: {
23424
+ tool: {
23425
+ type: "string",
23426
+ description: 'Tool name to evaluate. Defaults to "bash" for plain shell commands.'
23427
+ },
23428
+ args: {
23429
+ type: "string",
23430
+ description: 'Tool arguments as JSON, or a plain shell command string (e.g. "git push --force").'
23431
+ }
23432
+ },
23433
+ required: []
23434
+ }
23435
+ },
23404
23436
  {
23405
23437
  name: "node9_rule_add",
23406
23438
  description: 'Add a new protective smart rule to the global node9 config (~/.node9/config.json). Rules can block or send dangerous commands for human review based on regex conditions. IMPORTANT: only "block" and "review" verdicts are permitted \u2014 "allow" rules are never accepted because they would weaken node9 security. Rules can only be added, never removed.',
@@ -23707,6 +23739,17 @@ function handleSessionMcp(args) {
23707
23739
  if (typeof args.detail === "string" && args.detail) cliArgs.push("--detail", args.detail);
23708
23740
  return runCliCommand(cliArgs);
23709
23741
  }
23742
+ function handlePostureMcp(args) {
23743
+ const cliArgs = ["posture"];
23744
+ if (typeof args.agent === "string" && args.agent) cliArgs.push("--agent", args.agent);
23745
+ return runCliCommand(cliArgs);
23746
+ }
23747
+ function handleExplainMcp(args) {
23748
+ const tool = typeof args.tool === "string" && args.tool ? args.tool : "bash";
23749
+ const cliArgs = ["explain", tool];
23750
+ if (typeof args.args === "string" && args.args) cliArgs.push(args.args);
23751
+ return runCliCommand(cliArgs);
23752
+ }
23710
23753
  function handleUndoList(args) {
23711
23754
  const cwdFilter = typeof args.cwd === "string" && args.cwd ? args.cwd : null;
23712
23755
  let history = getSnapshotHistory();
@@ -23841,6 +23884,10 @@ function runMcpServer() {
23841
23884
  text = handleReportMcp(toolArgs);
23842
23885
  } else if (toolName === "node9_session") {
23843
23886
  text = handleSessionMcp(toolArgs);
23887
+ } else if (toolName === "node9_posture") {
23888
+ text = handlePostureMcp(toolArgs);
23889
+ } else if (toolName === "node9_explain") {
23890
+ text = handleExplainMcp(toolArgs);
23844
23891
  } else {
23845
23892
  process.stdout.write(err(id, -32601, `Unknown tool: ${toolName}`) + "\n");
23846
23893
  return;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@node9/proxy",
3
- "version": "1.41.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",