@node9/proxy 1.5.2 → 1.5.4

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
@@ -409,13 +409,66 @@ Smart Rules match on **raw tool arguments** using structured conditions:
409
409
 
410
410
  **Smart Rule fields:**
411
411
 
412
- | Field | Description |
413
- | :-------------- | :----------------------------------------------------------------------------------- |
414
- | `tool` | Tool name or glob (`"bash"`, `"mcp__postgres__*"`, `"*"`) |
415
- | `conditions` | Array of conditions evaluated against the raw args object |
416
- | `conditionMode` | `"all"` (AND, default) or `"any"` (OR) |
417
- | `verdict` | `"review"` (approval prompt) \| `"block"` (hard deny) \| `"allow"` (skip all checks) |
418
- | `reason` | Human-readable explanation shown in the approval prompt and audit log |
412
+ | Field | Description |
413
+ | :---------------- | :--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
414
+ | `tool` | Tool name or glob (`"bash"`, `"mcp__postgres__*"`, `"*"`) |
415
+ | `conditions` | Array of conditions evaluated against the raw args object |
416
+ | `conditionMode` | `"all"` (AND, default) or `"any"` (OR) |
417
+ | `verdict` | `"review"` (approval prompt) \| `"block"` (hard deny) \| `"allow"` (skip all checks) |
418
+ | `reason` | Human-readable explanation shown in the approval prompt and audit log |
419
+ | `dependsOnState` | _(optional)_ Array of state predicates — block only fires when **all** are true. If any predicate is false or the daemon is unreachable the rule is downgraded to review (fail-open). See [Stateful Rules](#stateful-smart-rules) below. |
420
+ | `recoveryCommand` | _(optional)_ Shell command to suggest when the rule blocks — shown on terminal as `💡 Run: npm test` and sent to the AI as a negotiation hint. |
421
+
422
+ ### Stateful Smart Rules
423
+
424
+ Stateful rules let you block actions based on **what the AI has done earlier in the session**, not just what it's doing now. The canonical use case: block deployment unless a test has passed since the last file edit.
425
+
426
+ ```json
427
+ {
428
+ "policy": {
429
+ "smartRules": [
430
+ {
431
+ "name": "require-tests-before-deploy",
432
+ "tool": "Bash",
433
+ "conditions": [
434
+ {
435
+ "field": "command",
436
+ "op": "matches",
437
+ "value": "./deploy.sh|kubectl apply|npm run deploy"
438
+ }
439
+ ],
440
+ "verdict": "block",
441
+ "reason": "Run tests before deploying",
442
+ "dependsOnState": ["no_test_passed_since_last_edit"],
443
+ "recoveryCommand": "npm test"
444
+ }
445
+ ]
446
+ }
447
+ }
448
+ ```
449
+
450
+ **How it works:**
451
+
452
+ 1. The AI attempts a deploy command.
453
+ 2. Node9 checks the daemon: _"Has a test passed since the last file edit?"_
454
+ 3. **If no** → routes to the race engine. Terminal shows the STATE GUARD card with `[1] Allow / [2] Redirect AI to run tests / [3] Deny`. The AI receives a negotiation hint to run `npm test` first if the human redirects.
455
+ 4. **If yes** → the rule is skipped, normal approval flow continues.
456
+ 5. **Daemon unreachable** → fail-open, rule is skipped.
457
+
458
+ > **⚠️ Security note — fail-open behaviour:** When the daemon is unreachable, stateful block rules are silently downgraded to review. This is intentional (availability over lockout), but it means a network disruption can temporarily weaken these rules. A per-rule `failMode: 'closed'` option is planned. If you need a hard guarantee, use a plain block rule (no `dependsOnState`) instead.
459
+
460
+ **State is tracked automatically** — no config required beyond the rule itself:
461
+
462
+ - File edits are detected from `Edit`, `Write`, `MultiEdit` tool calls.
463
+ - Test results are detected from the PostToolUse hook reading command output. Supported runners: `vitest`, `jest`, `mocha`, `pytest`, `cargo test`, `go test`, `rspec`, `phpunit`, `dotnet test`.
464
+
465
+ **Available predicates:**
466
+
467
+ | Predicate | True when |
468
+ | :------------------------------- | :------------------------------------------------------------ |
469
+ | `no_test_passed_since_last_edit` | A file was edited and no passing test has been recorded since |
470
+
471
+ > **Requires the node9 daemon** (`node9 daemon start`). Without the daemon the predicate is always unknown → fail-open.
419
472
 
420
473
  **Condition operators:**
421
474
 
@@ -454,19 +507,60 @@ Use `node9 explain <tool> <args>` to dry-run any tool call and see exactly which
454
507
  }
455
508
  ```
456
509
 
457
- | Key | Default | Description |
458
- | :------------------- | :-------- | :------------------------------------------------------------------------------ |
459
- | `mode` | `"audit"` | `audit` (log-only) \| `standard` (approve/block) \| `strict` (deny by default) |
460
- | `enableUndo` | `true` | Take git snapshots before every AI file edit |
461
- | `flightRecorder` | `true` | Record tool call activity to the flight recorder ring buffer for the browser UI |
462
- | `approvalTimeoutMs` | `30000` | Auto-deny after N ms if no human responds (`0` = wait forever) |
463
- | `approvers.native` | `true` | OS-native popup |
464
- | `approvers.browser` | `true` | Browser dashboard (`node9 daemon`) |
465
- | `approvers.cloud` | `false` | Slack / SaaS approval — requires `node9 login`; opt-in only |
466
- | `approvers.terminal` | `true` | `[Y/n]` prompt in terminal |
510
+ | Key | Default | Description |
511
+ | :------------------- | :-------- | :-------------------------------------------------------------------------------------------- |
512
+ | `mode` | `"audit"` | `audit` \| `observe` \| `standard` \| `strict` — see [Security Modes](#-security-modes) below |
513
+ | `enableUndo` | `true` | Take git snapshots before every AI file edit |
514
+ | `flightRecorder` | `true` | Record tool call activity to the flight recorder ring buffer for the browser UI |
515
+ | `approvalTimeoutMs` | `30000` | Auto-deny after N ms if no human responds (`0` = wait forever) |
516
+ | `approvers.native` | `true` | OS-native popup |
517
+ | `approvers.browser` | `true` | Browser dashboard (`node9 daemon`) |
518
+ | `approvers.cloud` | `false` | Slack / SaaS approval — requires `node9 login`; opt-in only |
519
+ | `approvers.terminal` | `true` | `[Y/n]` prompt in terminal |
520
+
521
+ ## 🔒 Security Modes
522
+
523
+ | Mode | Blocks? | Runs rules? | Use when |
524
+ | :--------- | :------ | :---------- | :--------------------------------------------------------------------------- |
525
+ | `audit` | Never | No | You want a log of every tool call but never want node9 to interfere |
526
+ | `observe` | Never | Yes | New install — see what _would_ have been blocked before enabling enforcement |
527
+ | `standard` | Yes | Yes | Normal use — dangerous commands need human approval |
528
+ | `strict` | Yes | Yes | High-security — anything not explicitly allowed is denied |
529
+
530
+ **`audit` vs `observe`:** Both never block. The difference is that `audit` skips the policy pipeline entirely (zero overhead, pure logging), while `observe` runs smart rules and DLP in full — recording each `would-block` decision without acting on it. The HUD shows `⚠ N would-block` in observe mode so you can see what enforcement would look like in practice.
531
+
532
+ **Recommended path:** start on `observe` for a few days to build confidence, then switch to `standard`.
533
+
534
+ ---
535
+
536
+ ## 🛡️ Security Statusline (HUD)
537
+
538
+ When Claude Code is detected, `node9 init` automatically adds a **security statusline** to Claude Code's terminal UI. You can also add it manually:
539
+
540
+ ```bash
541
+ node9 setup hud # add to ~/.claude/settings.json
542
+ node9 setup hud --remove
543
+ ```
544
+
545
+ The HUD renders up to three lines below Claude Code's prompt:
546
+
547
+ ```
548
+ 🛡 node9 | standard | ✅ 14 allowed 🛑 1 blocked ⚡ require-tests-before-deploy
549
+ claude-opus-4-5 │ ctx ████████░░ 82% │ 5h ██████░░░░ 61% (43m left)
550
+ 2 CLAUDE.md | 5 rules | 3 MCPs | 2 hooks
551
+ ```
552
+
553
+ | Segment | Source | Notes |
554
+ | :----------------- | :-------------------------- | :------------------------------------------------------- |
555
+ | `standard` | daemon: current mode | changes colour in `strict` (red) and `observe` (magenta) |
556
+ | `✅ N allowed` | daemon: session counters | resets when the daemon restarts |
557
+ | `🛑 N blocked` | daemon: session counters | shown in red when > 0 |
558
+ | `⚠ N would-block` | daemon: session counters | shown instead of blocked/allowed in `observe` mode |
559
+ | `⚡ rule-name` | daemon: last smart rule hit | most recent rule that fired |
560
+ | Context bar | Claude Code stdin | token usage and rate limit windows |
561
+ | Environment counts | local config files | CLAUDE.md / rules / MCPs / hooks active in this project |
467
562
 
468
- > **Tip choosing a mode:**
469
- > Start with the default `audit` to observe what your agent does without blocking anything. Once you understand its behaviour, switch to `standard` (blocks dangerous commands with human approval) or `strict` (denies anything not explicitly allowed) in your `~/.node9/config.json` or project `node9.config.json`.
563
+ When the daemon is not running the HUD shows `🛡 node9 | offline` instead of an error.
470
564
 
471
565
  ---
472
566
 
@@ -476,7 +570,8 @@ Use `node9 explain <tool> <args>` to dry-run any tool call and see exactly which
476
570
  | :----------------------------------- | :------------------------------------------------------------------------------------ |
477
571
  | `node9 setup` | Interactive menu — detects installed agents and wires hooks for you |
478
572
  | `node9 addto <agent>` | Wire hooks for a specific agent (`claude`, `gemini`, `cursor`) |
479
- | `node9 init` | Create default `~/.node9/config.json` |
573
+ | `node9 setup hud` | Add the node9 security statusline to Claude Code (also done automatically by `init`) |
574
+ | `node9 init` | Create default config, wire detected agents, and set up the HUD |
480
575
  | `node9 status` | Show current protection status and active rules |
481
576
  | `node9 doctor` | Health check — verifies binaries, config, credentials, and all agent hooks |
482
577
  | `node9 shield <cmd>` | Manage shields (`enable`, `disable`, `list`, `status`) |