@node9/proxy 0.2.1 → 1.0.1

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.
Files changed (6) hide show
  1. package/README.md +66 -319
  2. package/dist/cli.js +1417 -608
  3. package/dist/cli.mjs +1417 -608
  4. package/dist/index.js +722 -261
  5. package/dist/index.mjs +722 -261
  6. package/package.json +44 -8
package/README.md CHANGED
@@ -5,385 +5,132 @@
5
5
  [![NPM Version](https://img.shields.io/npm/v/@node9/proxy.svg)](https://www.npmjs.com/package/@node9/proxy)
6
6
  [![License: MIT](https://img.shields.io/badge/License-MIT-blue.svg)](https://opensource.org/licenses/MIT)
7
7
 
8
- **Node9** is the execution security layer for the Agentic Era. It intercepts AI agent actions — via native hooks (Claude Code, Gemini CLI, Cursor) or a JSON-RPC proxy (MCP servers, shell commands) before they reach your production environment.
8
+ **Node9** is the execution security layer for the Agentic Era. It encases autonomous AI Agents (Claude Code, Gemini CLI, Cursor, MCP Servers) in a deterministic security wrapper, intercepting dangerous shell commands and tool calls before they execute.
9
9
 
10
- While others try to _guess_ if a prompt is malicious (Semantic Security), Node9 _intercepts_ the actual action (Execution Security).
10
+ While others try to _guess_ if a prompt is malicious (Semantic Security), Node9 _governs_ the actual action (Execution Security).
11
11
 
12
- ## 🗺️ Architecture
13
-
14
- Node9 has two protection modes. The right one depends on your agent:
15
-
16
- | Agent | Mode | How |
17
- | -------------- | --------- | -------------------------------------------------------- |
18
- | Claude Code | **Hook** | `node9 addto claude` — hooks fire before every tool call |
19
- | Gemini CLI | **Hook** | `node9 addto gemini` — hooks fire before every tool call |
20
- | Cursor | **Hook** | `node9 addto cursor` — hooks fire before every tool call |
21
- | MCP Servers | **Proxy** | `node9 "npx <server>"` — JSON-RPC interceptor |
22
- | Shell commands | **Proxy** | `node9 "rm -rf ./data"` — evaluates before running |
23
-
24
- > ⚠️ **`node9 gemini` and `node9 claude` do NOT work** — interactive CLIs need a real TTY and communicate via their own hook system, not JSON-RPC. Use `node9 addto` for one-time setup, then run the agent normally.
25
-
26
- ### Hook Mode (Claude Code, Gemini CLI, Cursor)
27
-
28
- ```mermaid
29
- sequenceDiagram
30
- participant LLM as AI Model
31
- participant Agent as Agent CLI
32
- participant Hook as node9 check (PreToolUse hook)
33
- participant OS as Local System/Shell
34
-
35
- LLM->>Agent: "Delete the tmp folder"
36
- Agent->>Hook: PreToolUse fires: Bash { command: "rm -rf ./tmp" }
37
-
38
- Note over Hook: 🧠 Semantic Parser analyzes AST
39
- Note over Hook: 🛡️ Policy Engine checks rules
40
-
41
- alt is dangerous & not allowed
42
- Hook-->>Agent: ❌ exit 1 — action blocked
43
- Agent-->>LLM: "Action blocked by security policy"
44
- else is safe OR approved by user
45
- Hook-->>Agent: ✅ exit 0 — proceed
46
- Agent->>OS: Execute: rm -rf ./tmp
47
- OS-->>Agent: Success
48
- Agent-->>LLM: "Folder deleted"
49
- end
50
- ```
12
+ ---
51
13
 
52
- ### Proxy Mode (MCP Servers & shell commands)
14
+ ## Key Architectural Upgrades
53
15
 
54
- ```mermaid
55
- sequenceDiagram
56
- participant Agent as Agent / Caller
57
- participant Node9 as Node9 Proxy
58
- participant MCP as MCP Server / Shell
16
+ ### 🏁 The Multi-Channel Race Engine
59
17
 
60
- Agent->>Node9: JSON-RPC tools/call { command: "rm -rf ./tmp" }
18
+ Node9 initiates a **Concurrent Race** across all enabled channels. The first channel to receive a human signature wins and instantly cancels the others:
61
19
 
62
- Note over Node9: 🧠 Semantic Parser analyzes AST
63
- Note over Node9: 🛡️ Policy Engine checks rules
20
+ - **Native Popup:** OS-level dialog (Mac/Win/Linux) for sub-second keyboard dismissal.
21
+ - **Browser Dashboard:** Local web UI for deep inspection of large payloads (SQL/Code).
22
+ - **Cloud (Slack):** Remote asynchronous approval for team governance.
23
+ - **Terminal:** Classic `[Y/n]` prompt for manual proxy usage and SSH sessions.
64
24
 
65
- alt is dangerous & not allowed
66
- Node9-->>Agent: ❌ BLOCK: error response
67
- else is safe OR approved by user
68
- Node9->>MCP: Forward original request
69
- MCP-->>Node9: Result
70
- Node9-->>Agent: Tool Result: Success
71
- end
72
- ```
25
+ ### 🧠 AI Negotiation Loop
73
26
 
74
- ---
27
+ Node9 doesn't just "cut the wire." When a command is blocked, it injects a **Structured Negotiation Prompt** back into the AI’s context window. This teaches the AI why it was stopped and instructs it to pivot to a safer alternative or apologize to the human.
75
28
 
76
- ## 🛑 The Problem: Agent Liability
29
+ ### 🌊 The Resolution Waterfall
77
30
 
78
- In 2026, AI agents have "Write Access" to everything (GitHub, AWS, Stripe, Databases).
31
+ Security posture is resolved using a strict 5-tier waterfall:
79
32
 
80
- - **The Risk:** An agent hallucinating a `DROP DATABASE` or an unauthorized `aws.delete_instance`.
81
- - **The Solution:** Node9 intercepts high-risk tool calls and pauses execution until a human provides a signature.
82
-
83
- ## 🚀 Key Features
84
-
85
- - **Deterministic "Sudo" Mode:** Intercepts dangerous tool calls based on hardcoded policies.
86
- - **Human-in-the-Loop (HITL):** Requires explicit approval via the **Terminal** (Local) or **Slack** (Cloud).
87
- - **One-Command Setup:** `node9 addto claude` wires up full protection in seconds — no manual config editing.
88
- - **MCP Native:** Deep-packet inspection of JSON-RPC traffic. Protects any Model Context Protocol server.
89
- - **Hook Native:** Plugs into Claude Code, Gemini CLI, and Cursor's native hook systems to intercept built-in tools (Bash, Write, Edit) — not just MCP calls.
90
- - **Global Config:** Store your security posture in a `node9.config.json` file in your project root.
33
+ 1. **Env Vars:** Session-level overrides (e.g., `NODE9_PAUSED=1`).
34
+ 2. **Cloud (SaaS):** Global organization "Locks" that cannot be bypassed locally.
35
+ 3. **Project Config:** Repository-specific rules (`node9.config.json`).
36
+ 4. **Global Config:** Personal UI preferences (`~/.node9/config.json`).
37
+ 5. **Defaults:** The built-in safety net.
91
38
 
92
39
  ---
93
40
 
94
- ## 📦 Installation
41
+ ## 🚀 Quick Start
95
42
 
96
43
  ```bash
97
44
  npm install -g @node9/proxy
98
- ```
99
45
 
100
- ---
101
-
102
- ## ⚡ Quick Start
103
-
104
- Node9 provides two layers of protection depending on the agent you use:
105
-
106
- ### 1. Hook-Based Protection (For Interactive Agents)
107
-
108
- Interactive CLIs like **Gemini**, **Claude Code**, and **Cursor** require a real terminal. Use the `addto` command to wire up Node9's native hooks:
109
-
110
- ```bash
111
- # One-time setup
112
- node9 addto gemini
46
+ # 1. Setup protection for your favorite agent
113
47
  node9 addto claude
114
- node9 addto cursor
115
-
116
- # Then run your agent normally! Node9 protection is now automatic.
117
- gemini
118
- claude
119
- ```
120
-
121
- ### 2. Proxy-Based Protection (For MCP & Shell)
122
-
123
- For standalone MCP servers or one-off shell commands, use the **Smart Runner** prefix:
124
-
125
- ```bash
126
- # Intercepts 'rm -rf /' before starting
127
- node9 "rm -rf /"
128
-
129
- # Wraps an MCP server with a security proxy
130
- node9 "npx @modelcontextprotocol/server-github"
131
- ```
132
-
133
- _Note: Always wrap the target command in quotes._
134
-
135
- ---
136
-
137
- ## 🛠 Usage
138
-
139
- ### 1. Connect to Node9 Cloud (Optional)
140
-
141
- To route approvals to **Slack** when you are away from your terminal, login once with your API key:
48
+ node9 addto gemini
142
49
 
143
- ```bash
50
+ # 2. (Optional) Connect to Slack for remote approvals
144
51
  node9 login <your_api_key>
145
- ```
146
-
147
- _Your credentials are stored in `~/.node9/credentials.json` with `0o600` permissions (owner read/write only)._
148
-
149
- ### 2. One-Command Agent Setup
150
-
151
- `node9 addto <target>` wires up Node9 to your AI agent automatically:
152
-
153
- | Target | MCP Servers | Built-in Tools (Bash, Write, Edit...) | Audit Log |
154
- | -------- | :---------: | :-----------------------------------: | :-------: |
155
- | `claude` | ✅ | ✅ via `PreToolUse` hook | ✅ |
156
- | `gemini` | ✅ | ✅ via `BeforeTool` hook | ✅ |
157
- | `cursor` | ✅ | ✅ via `preToolUse` hook | ✅ |
158
-
159
- **What it does under the hood:**
160
-
161
- - Wraps your existing MCP servers with `node9 proxy` (asks for confirmation first)
162
- - Adds a pre-execution hook → `node9 check` runs before every tool call
163
- - Adds a post-execution hook → `node9 log` writes every executed action to `~/.node9/audit.log`
164
-
165
- ### 3. Local Approval Daemon (Browser UI)
166
-
167
- For hook-based integrations, Node9 can auto-start a local browser UI to approve or deny dangerous actions without needing a Slack account.
168
-
169
- ```bash
170
- # Start manually and keep it running in the background
171
- node9 daemon --background
172
-
173
- # Check status / stop
174
- node9 daemon status
175
- node9 daemon stop
176
- ```
177
-
178
- **How it works:**
179
-
180
- - When a dangerous tool call arrives and the daemon is running, Node9 routes it to `http://127.0.0.1:7391` and opens your browser.
181
- - If the daemon is **not** running, Node9 auto-starts it and opens the browser automatically (default behaviour).
182
- - If you **close the browser tab** without approving or denying, Node9 waits 2 seconds (to allow for an accidental refresh), then abandons the request and falls back to a terminal prompt.
183
- - After a browser-close abandonment, the daemon shuts down automatically so the next command goes back to the same auto-start flow.
184
-
185
- **Settings (in the browser UI ⚙️):**
186
-
187
- | Setting | Default | Effect |
188
- | ----------------- | ------- | ----------------------------------------------------------------------------------- |
189
- | Auto-start daemon | **On** | Start the daemon + open browser automatically when no approval mechanism is running |
190
-
191
- Turn "Auto-start daemon" **off** if you prefer to always be asked in the terminal, or if you want to control the daemon lifecycle manually.
192
-
193
- You can also disable auto-start permanently via `~/.node9/config.json`:
194
-
195
- ```json
196
- {
197
- "settings": {
198
- "mode": "standard",
199
- "autoStartDaemon": false
200
- }
201
- }
202
- ```
203
-
204
- ### 4. Manual Command & MCP Protection
205
52
 
206
- To protect any command or MCP server manually:
207
-
208
- **Protecting a direct command:**
209
-
210
- ```bash
211
- node9 "rm -rf ./data"
212
- ```
213
-
214
- **Protecting GitHub MCP Server:**
215
-
216
- ```bash
217
- node9 "npx @modelcontextprotocol/server-github"
53
+ # 3. Check your status
54
+ node9 status
218
55
  ```
219
56
 
220
- **Note:** Direct proxying (e.g. `node9 gemini`) is not supported for interactive agents. Use `node9 addto` instead.
221
-
222
- ### 4. SDK — Protect Functions in Your Own Code
223
-
224
- Wrap any async function with `protect()` to require human approval before it runs:
225
-
226
- ```typescript
227
- import { protect } from '@node9/proxy';
57
+ ---
228
58
 
229
- const deleteDatabase = protect('aws.rds.delete_database', async (name: string) => {
230
- // ... actual deletion logic
231
- });
59
+ ## 🛠 Protection Modes
232
60
 
233
- // Node9 intercepts this and prompts for approval before running
234
- await deleteDatabase('production-db-v1');
235
- ```
61
+ | Mode | Target | How it works |
62
+ | :-------------- | :--------------------- | :------------------------------------------------------ |
63
+ | **Hook Mode** | Claude, Gemini, Cursor | `node9 addto <agent>` wires native pre-execution hooks. |
64
+ | **Proxy Mode** | MCP Servers, Shell | `node9 "npx <server>"` intercepts JSON-RPC traffic. |
65
+ | **Manual Mode** | You | `node9 rm -rf /` protects you from your own typos. |
236
66
 
237
67
  ---
238
68
 
239
69
  ## ⚙️ Configuration (`node9.config.json`)
240
70
 
241
- Add a `node9.config.json` to your project root or `~/.node9/config.json` for global use.
71
+ Rules are **merged additive**—you cannot "un-danger" a word locally if it was defined as dangerous by a higher authority (like the Cloud).
242
72
 
243
73
  ```json
244
74
  {
245
75
  "settings": {
246
- "mode": "standard"
76
+ "mode": "standard",
77
+ "enableUndo": true,
78
+ "approvers": {
79
+ "native": true,
80
+ "browser": true,
81
+ "cloud": true,
82
+ "terminal": true
83
+ }
247
84
  },
248
85
  "policy": {
249
- "dangerousWords": ["delete", "drop", "terminate", "rm", "rmdir"],
86
+ "sandboxPaths": ["/tmp/**", "**/test-results/**"],
87
+ "dangerousWords": ["drop", "destroy", "purge", "push --force"],
250
88
  "ignoredTools": ["list_*", "get_*", "read_*"],
251
89
  "toolInspection": {
252
90
  "bash": "command",
253
- "shell": "command",
254
- "run_shell_command": "command"
255
- },
256
- "rules": [
257
- {
258
- "action": "rm",
259
- "allowPaths": ["**/node_modules/**", "dist/**", "build/**"]
260
- }
261
- ]
262
- },
263
- "environments": {
264
- "production": {
265
- "requireApproval": true,
266
- "slackChannel": "#alerts-prod-security"
267
- },
268
- "development": {
269
- "requireApproval": false
91
+ "postgres:query": "sql"
270
92
  }
271
93
  }
272
94
  }
273
95
  ```
274
96
 
275
- **Modes:**
276
-
277
- - `standard`: Allows everything except tools containing `dangerousWords`.
278
- - `strict`: Blocks **everything** except tools listed in `ignoredTools`.
279
-
280
- **Environment overrides** (keyed by `NODE_ENV`):
281
-
282
- - `requireApproval: false` — auto-allow all actions in that environment (useful for local dev).
283
- - `slackChannel` — route cloud approvals to a specific Slack channel for that environment.
284
-
285
- ### 🔌 Universal Tool Inspection (The "Universal Adapter")
286
-
287
- Node9 can protect **any** tool, even if it's not Claude or Gemini. You can tell Node9 where to find the "dangerous" payload in any tool call.
288
-
289
- Example: Protecting a custom "Stripe" MCP server:
290
-
291
- ```json
292
- "toolInspection": {
293
- "stripe.send_refund": "amount",
294
- "github.delete*": "params.repo_name"
295
- }
296
- ```
297
-
298
- Now, whenever your agent calls `stripe.send_refund`, Node9 will extract the `amount` and check it against your global security policy.
299
-
300
97
  ---
301
98
 
302
- ## 🛡️ How it Works
303
-
304
- Node9 is **deterministic**. It doesn't use AI to check AI.
99
+ ## Phase 2: The "Undo" Engine (Coming Soon)
305
100
 
306
- ### Hook Mode (via `node9 addto`)
307
-
308
- ```
309
- Claude wants to run Bash("rm -rf /data")
310
-
311
- PreToolUse hook fires
312
- → node9 check
313
-
314
- ┌────┴─────┐
315
- │ BLOCKED │ → Claude is told the action was denied
316
- └──────────┘
317
- OR
318
- ┌──────────┐
319
- │ APPROVED │ → Claude runs the command
320
- └──────────┘
321
-
322
- PostToolUse hook fires
323
- → node9 log → appended to ~/.node9/audit.log
324
- ```
325
-
326
- ### Proxy Mode (via `node9 "<command>"`)
327
-
328
- ```
329
- 1. Intercept — catches the JSON-RPC tools/call request mid-flight
330
- 2. Evaluate — checks against your local node9.config.json
331
- 3. Suspend — execution is frozen in a PENDING state
332
- 4. Authorize — Local: prompt in terminal / Cloud: button in Slack
333
- 5. Release — command forwarded to the target only after approval
334
- ```
101
+ Node9 is currently building **Shadow Git Snapshots**. When enabled, Node9 takes a silent, lightweight Git snapshot right before an AI agent is allowed to edit or delete files. If the AI hallucinates, you can revert the entire session with one click: `node9 undo`.
335
102
 
336
103
  ---
337
104
 
338
105
  ## 🔧 Troubleshooting
339
106
 
340
- **`node9 check` exits immediately / Claude Code is never blocked**
107
+ **`node9 check` exits immediately / Claude is never blocked**
108
+ Node9 fails open by design to prevent breaking your agent. Check debug logs: `NODE9_DEBUG=1 claude`.
341
109
 
342
- Node9 fails open by design if it can't parse the hook payload it exits 0 rather than blocking your agent. Enable debug logging to see what's happening:
110
+ **Terminal prompt never appears during Claude/Gemini sessions**
111
+ Interactive agents run hooks in a "Headless" subprocess. You **must** enable `native: true` or `browser: true` in your config to see approval prompts.
343
112
 
344
- ```bash
345
- NODE9_DEBUG=1 claude # logs every hook payload to ~/.node9/hook-debug.log
346
- ```
347
-
348
- **Browser opens on every single tool call**
349
-
350
- The daemon opens the browser only when no tab is already connected. If your browser keeps opening, check that the previous tab is still open. If you'd prefer the terminal prompt instead, disable auto-start in the daemon UI (⚙️ Settings → Auto-start daemon: Off).
351
-
352
- **`node9 daemon stop` says "Not running" even though I see the process**
353
-
354
- The daemon PID file may be stale. Run `rm ~/.node9/daemon.pid` and try again.
355
-
356
- **Terminal prompt never appears — action is just blocked**
357
-
358
- The terminal prompt only shows when `process.stdout` is a TTY (i.e. you're running directly in a terminal, not through a pipe). If you're using the hook system (`node9 check`), it runs headless. Start the daemon to get a browser prompt instead:
359
-
360
- ```bash
361
- node9 daemon --background
362
- ```
363
-
364
- **"Always Allow" / "Always Deny" not taking effect after restart**
365
-
366
- Persistent decisions are stored in `~/.node9/decisions.json`. If a project `node9.config.json` overrides the `ignoredTools` list in a way that covers the tool, it may be allowed before the decisions file is checked. Look at the config precedence: project config → global config → defaults.
113
+ **"Blocked by Organization (SaaS)"**
114
+ A corporate policy has locked this action. You must click the "Approve" button in your company's Slack channel to proceed.
367
115
 
368
116
  ---
369
117
 
370
- ## 📈 Roadmap
118
+ ## 🗺️ Roadmap
371
119
 
372
- - [x] Local Terminal "Sudo" (OSS)
373
- - [x] MCP JSON-RPC Interceptor
374
- - [x] Slack Remote Approvals (Pro)
375
- - [x] One-command setup (`node9 addto claude/gemini/cursor`)
376
- - [x] Hook-native integration (PreToolUse / BeforeTool / preToolUse)
377
- - [x] Audit log (`~/.node9/audit.log`)
378
- - [ ] **Multi-Admin Quorum** (Approve only if 2 admins click)
379
- - [ ] **SOC2 Tamper-proof Audit Logs** (Enterprise)
120
+ - [x] **Multi-Channel Race Engine** (Simultaneous Native/Browser/Cloud/Terminal)
121
+ - [x] **AI Negotiation Loop** (Instructional feedback loop to guide LLM behavior)
122
+ - [x] **Resolution Waterfall** (Cascading configuration: Env > Cloud > Project > Global)
123
+ - [x] **Native OS Dialogs** (Sub-second approval via Mac/Win/Linux system windows)
124
+ - [x] **One-command Agent Setup** (`node9 addto claude | gemini | cursor`)
125
+ - [x] **Identity-Aware Execution** (Differentiates between Human vs. AI risk levels)
126
+ - [ ] **Shadow Git Snapshots** (1-click Undo for AI hallucinations)
127
+ - [ ] **Execution Sandboxing** (Simulate dangerous commands in a virtual FS before applying)
128
+ - [ ] **Multi-Admin Quorum** (Require 2+ human signatures for high-stakes production actions)
129
+ - [ ] **SOC2 Tamper-proof Audit Trail** (Cryptographically signed, cloud-managed logs)
380
130
 
381
131
  ---
382
132
 
383
- ## 🏢 Enterprise & Commercial Use
384
-
385
- The local proxy is free forever for individual developers. For teams requiring **Slack Integration**, **VPC Deployment**, and **Tamper-proof Audit Logs**, visit [node9.ai](https://node9.ai) or contact `support@node9.ai`.
386
-
387
- ---
133
+ ## 🏢 Enterprise & Compliance
388
134
 
389
- **Safe Agentic Automations Start with Node9.** 🛡️🚀
135
+ Node9 Pro provides **Governance Locking**, **SAML/SSO**, and **VPC Deployment**.
136
+ Visit [node9.ai](https://node9.ai