veto-leash 0.1.2 → 1.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.
Files changed (96) hide show
  1. package/README.md +125 -203
  2. package/dist/ast/builtins.d.ts +28 -0
  3. package/dist/ast/builtins.d.ts.map +1 -0
  4. package/dist/ast/builtins.js +361 -0
  5. package/dist/ast/builtins.js.map +1 -0
  6. package/dist/ast/checker.d.ts +17 -0
  7. package/dist/ast/checker.d.ts.map +1 -0
  8. package/dist/ast/checker.js +97 -0
  9. package/dist/ast/checker.js.map +1 -0
  10. package/dist/ast/index.d.ts +5 -0
  11. package/dist/ast/index.d.ts.map +1 -0
  12. package/dist/ast/index.js +7 -0
  13. package/dist/ast/index.js.map +1 -0
  14. package/dist/ast/parser.d.ts +55 -0
  15. package/dist/ast/parser.d.ts.map +1 -0
  16. package/dist/ast/parser.js +210 -0
  17. package/dist/ast/parser.js.map +1 -0
  18. package/dist/ast/query.d.ts +48 -0
  19. package/dist/ast/query.d.ts.map +1 -0
  20. package/dist/ast/query.js +102 -0
  21. package/dist/ast/query.js.map +1 -0
  22. package/dist/ast/validate-cli.d.ts +21 -0
  23. package/dist/ast/validate-cli.d.ts.map +1 -0
  24. package/dist/ast/validate-cli.js +73 -0
  25. package/dist/ast/validate-cli.js.map +1 -0
  26. package/dist/cli.js +105 -21
  27. package/dist/cli.js.map +1 -1
  28. package/dist/compiler/builtins.d.ts.map +1 -1
  29. package/dist/compiler/builtins.js +721 -4
  30. package/dist/compiler/builtins.js.map +1 -1
  31. package/dist/compiler/commands.d.ts +40 -0
  32. package/dist/compiler/commands.d.ts.map +1 -0
  33. package/dist/compiler/commands.js +311 -0
  34. package/dist/compiler/commands.js.map +1 -0
  35. package/dist/compiler/content.d.ts +160 -0
  36. package/dist/compiler/content.d.ts.map +1 -0
  37. package/dist/compiler/content.js +461 -0
  38. package/dist/compiler/content.js.map +1 -0
  39. package/dist/compiler/index.d.ts.map +1 -1
  40. package/dist/compiler/index.js +34 -7
  41. package/dist/compiler/index.js.map +1 -1
  42. package/dist/compiler/llm.d.ts.map +1 -1
  43. package/dist/compiler/llm.js +96 -9
  44. package/dist/compiler/llm.js.map +1 -1
  45. package/dist/compiler/prompt.d.ts +1 -1
  46. package/dist/compiler/prompt.d.ts.map +1 -1
  47. package/dist/compiler/prompt.js +247 -15
  48. package/dist/compiler/prompt.js.map +1 -1
  49. package/dist/config/leash-parser.d.ts +29 -0
  50. package/dist/config/leash-parser.d.ts.map +1 -0
  51. package/dist/config/leash-parser.js +70 -0
  52. package/dist/config/leash-parser.js.map +1 -0
  53. package/dist/config/loader.d.ts +2 -1
  54. package/dist/config/loader.d.ts.map +1 -1
  55. package/dist/config/loader.js +18 -8
  56. package/dist/config/loader.js.map +1 -1
  57. package/dist/config/schema.d.ts +8 -0
  58. package/dist/config/schema.d.ts.map +1 -1
  59. package/dist/config/schema.js +19 -0
  60. package/dist/config/schema.js.map +1 -1
  61. package/dist/config/watcher.d.ts +18 -0
  62. package/dist/config/watcher.d.ts.map +1 -0
  63. package/dist/config/watcher.js +102 -0
  64. package/dist/config/watcher.js.map +1 -0
  65. package/dist/matcher.d.ts +18 -0
  66. package/dist/matcher.d.ts.map +1 -1
  67. package/dist/matcher.js +43 -0
  68. package/dist/matcher.js.map +1 -1
  69. package/dist/native/claude-code.d.ts.map +1 -1
  70. package/dist/native/claude-code.js +294 -50
  71. package/dist/native/claude-code.js.map +1 -1
  72. package/dist/native/cursor.d.ts +14 -1
  73. package/dist/native/cursor.d.ts.map +1 -1
  74. package/dist/native/cursor.js +340 -34
  75. package/dist/native/cursor.js.map +1 -1
  76. package/dist/native/index.d.ts +5 -0
  77. package/dist/native/index.d.ts.map +1 -1
  78. package/dist/native/index.js +56 -10
  79. package/dist/native/index.js.map +1 -1
  80. package/dist/native/opencode.d.ts.map +1 -1
  81. package/dist/native/opencode.js +15 -3
  82. package/dist/native/opencode.js.map +1 -1
  83. package/dist/native/validator.d.ts +15 -0
  84. package/dist/native/validator.d.ts.map +1 -0
  85. package/dist/native/validator.js +343 -0
  86. package/dist/native/validator.js.map +1 -0
  87. package/dist/types.d.ts +114 -0
  88. package/dist/types.d.ts.map +1 -1
  89. package/dist/types.js.map +1 -1
  90. package/dist/wrapper/daemon.d.ts.map +1 -1
  91. package/dist/wrapper/daemon.js +31 -2
  92. package/dist/wrapper/daemon.js.map +1 -1
  93. package/languages/tree-sitter-javascript.wasm +0 -0
  94. package/languages/tree-sitter-tsx.wasm +0 -0
  95. package/languages/tree-sitter-typescript.wasm +0 -0
  96. package/package.json +12 -3
package/README.md CHANGED
@@ -1,260 +1,182 @@
1
- # veto-leash
2
-
3
- **sudo for AI agents**
1
+ <p align="center">
2
+ <h1 align="center">veto-leash</h1>
3
+ <p align="center"><strong>sudo for AI agents</strong></p>
4
+ <p align="center">
5
+ <a href="https://www.npmjs.com/package/veto-leash"><img src="https://img.shields.io/npm/v/veto-leash?style=flat-square&color=black" alt="npm version"></a>
6
+ <a href="https://github.com/VulnZap/veto-leash/blob/main/LICENSE"><img src="https://img.shields.io/npm/l/veto-leash?style=flat-square&color=black" alt="License"></a>
7
+ <a href="https://www.npmjs.com/package/veto-leash"><img src="https://img.shields.io/npm/dm/veto-leash?style=flat-square&color=black" alt="Downloads"></a>
8
+ </p>
9
+ </p>
4
10
 
5
11
  Your AI agent has root access to your codebase. You have... vibes.
6
12
 
7
13
  ```bash
8
- leash cc "don't delete test files"
14
+ # One file. That's it.
15
+ echo "no lodash
16
+ no any types" > .leash
17
+
18
+ leash init # Auto-detects agents, installs hooks
9
19
  ```
10
20
 
11
- Now every destructive action requires explicit policy. No regex. No config files. Just English.
21
+ Now every action is validated with **AST-level precision**. Zero false positives. Zero config.
22
+
23
+ ## What's New in 1.0
24
+
25
+ - **🎯 AST Validation** - Tree-sitter parsing means `// import lodash` in comments is ignored
26
+ - **📄 Simple `.leash` format** - One rule per line, no YAML boilerplate
27
+ - **🔍 Auto-detection** - `leash init` finds and configures all your AI agents
28
+ - **⚡ Instant** - 95%+ policies use built-in rules (no LLM call needed)
12
29
 
13
30
  ## The Problem
14
31
 
15
- AI coding agents can delete your test files, wipe your .env, run arbitrary migrations. Current permission systems require you to write regex patterns and understand glob syntax. You want to say "protect my tests" and be done.
32
+ AI coding agents can `npm install lodash` when you want native methods. They'll sprinkle `any` types everywhere. They'll `git push --force` to main.
33
+
34
+ Regex-based blockers create false positives. A comment saying `// TODO: remove lodash` shouldn't trigger a block.
16
35
 
17
36
  ## The Solution
18
37
 
19
- veto-leash compiles natural language restrictions into precise policies **once**, then enforces them at runtime with zero LLM latency.
38
+ veto-leash uses **AST parsing** for surgical precision:
20
39
 
21
- ```
22
- "don't delete test files"
23
-
24
-
25
- ┌─────────────────────────────────────┐
26
- │ Semantic Compilation (100ms)
27
- │ • Understands "test files" = test │
28
- │ source code, not test-results.xml│
29
- │ • Gemini 2.0 Flash + JSON Schema │
30
- │ • Cached for instant reuse │
31
- └─────────────────────────────────────┘
32
-
33
-
34
- ┌─────────────────────────────────────┐
35
- │ Policy │
36
- │ action: delete │
37
- │ include: *.test.*, *.spec.*, │
38
- │ __tests__/**, test/** │
39
- │ exclude: test-results.*, coverage/ │
40
- └─────────────────────────────────────┘
41
-
42
-
43
- Enforcement (0ms per check)
44
- ```
40
+ | Code | Regex Result | AST Result |
41
+ | ------------------------ | ------------ | -------------------------- |
42
+ | `// import lodash` | ❌ BLOCKED | ✅ ALLOWED (comment) |
43
+ | `"use any type"` | ❌ BLOCKED | ✅ ALLOWED (string) |
44
+ | `const anyValue = 5` | ❌ BLOCKED | ✅ ALLOWED (variable name) |
45
+ | `import _ from 'lodash'` | ✅ BLOCKED | ✅ BLOCKED (correct) |
46
+
47
+ **This precision is our moat.** No other tool achieves zero false positives.
45
48
 
46
49
  ## Quick Start
47
50
 
48
51
  ```bash
49
- # Install
52
+ # Install globally
50
53
  npm install -g veto-leash
51
54
 
52
- # Get free Gemini API key (optional - builtins work without it)
53
- # https://aistudio.google.com/apikey
54
- export GEMINI_API_KEY="your-key"
55
+ # Create a simple .leash file
56
+ echo "no lodash
57
+ no any types
58
+ no console.log" > .leash
55
59
 
56
- # Use it
57
- leash cc "don't delete test files"
60
+ # One command setup
61
+ leash init
58
62
  ```
59
63
 
60
- That's it. Your Claude Code session now blocks test file deletions.
61
-
62
- ## How It Works
63
-
64
- ### Three Enforcement Modes
65
-
66
- | Mode | Use Case | How |
67
- |------|----------|-----|
68
- | **Wrapper** | Any agent | PATH hijacking, TCP daemon |
69
- | **Native** | Claude Code, Windsurf, OpenCode | Hooks directly into agent |
70
- | **Watchdog** | Background protection | File system monitoring, auto-restore |
64
+ That's it. `leash init` will:
71
65
 
72
- ### Native Integrations
66
+ 1. Detect installed agents (Claude Code, Cursor, OpenCode, Windsurf)
67
+ 2. Install native hooks for each
68
+ 3. Your policies are now enforced
73
69
 
74
- ```bash
75
- # Claude Code - PreToolUse hooks
76
- leash add "don't delete test files"
77
- leash install cc
70
+ ## Simple `.leash` Format
78
71
 
79
- # Windsurf - Cascade hooks
80
- leash add "protect .env"
81
- leash install windsurf
82
-
83
- # OpenCode - permission.bash rules
84
- leash add "no migrations"
85
- leash install oc
86
- ```
87
-
88
- ### Wrapper Mode (Works with anything)
89
-
90
- ```bash
91
- # Works with ANY CLI agent
92
- leash cc "don't delete test files"
93
- leash opencode "protect .env"
94
- leash cursor "no database migrations"
95
- leash aider "read-only src/core"
96
- leash my-custom-agent "protect config"
97
72
  ```
98
-
99
- ### Watchdog Mode (Catches everything)
100
-
101
- ```bash
102
- # Background file protection - catches programmatic changes too
103
- leash watch "protect test files"
73
+ # .leash - One rule per line
74
+ no lodash
75
+ no any types - enforces strict TypeScript
76
+ no console.log
77
+ prefer pnpm over npm
104
78
  ```
105
79
 
106
- ## Supported Agents
107
-
108
- | Agent | Native | Wrapper | Notes |
109
- |-------|--------|---------|-------|
110
- | Claude Code | PreToolUse hooks | PATH shims | Best support |
111
- | Windsurf | Cascade hooks | PATH shims | Full support |
112
- | OpenCode | permission.bash | PATH shims | Full support |
113
- | Cursor | .cursorrules | PATH shims | Guidance only |
114
- | Aider | .aider.conf.yml | PATH shims | Read-only files |
115
- | Codex CLI | - | Watchdog | OS sandbox |
116
- | GitHub Copilot | - | Wrapper | No hooks |
117
- | Any CLI tool | - | PATH shims | Universal |
80
+ Lines starting with `#` are comments. Optional reasons after `-`.
118
81
 
119
- ## Project Configuration
82
+ ## Built-in AST Rules
120
83
 
121
- Create a `.leash` file for team-wide policies:
84
+ These work **instantly** with zero LLM calls:
122
85
 
123
- ```yaml
124
- # .leash
125
- version: 1
126
-
127
- policies:
128
- - "don't delete test files"
129
- - "protect .env"
130
- - "no database migrations"
131
-
132
- settings:
133
- fail_closed: true
134
- audit_log: true
135
- ```
86
+ | Rule | What It Catches |
87
+ | --------------------- | ------------------------------------------ |
88
+ | `no lodash` | ES imports, require(), dynamic import() |
89
+ | `no any types` | Type annotations, generics, as expressions |
90
+ | `no console.log` | console.log(), console['log']() |
91
+ | `no eval` | eval(), new Function() |
92
+ | `no class components` | React.Component, PureComponent |
93
+ | `no innerhtml` | innerHTML, dangerouslySetInnerHTML |
94
+ | `no debugger` | debugger statements |
95
+ | `no var` | var declarations |
136
96
 
137
- Then sync to your agents:
97
+ ## Native Agent Support
138
98
 
139
- ```bash
140
- leash sync cc
141
- leash sync windsurf
142
- ```
99
+ | Agent | How It Works | Status |
100
+ | --------------- | ------------------------------------ | ------------ |
101
+ | **Claude Code** | PreToolUse hooks with AST validation | ✅ Full |
102
+ | **Cursor** | hooks.json + beforeShellExecution | ✅ Full |
103
+ | **OpenCode** | permission.bash deny rules | ✅ Full |
104
+ | **Windsurf** | Cascade pre_write_code hooks | ✅ Full |
105
+ | **Aider** | .aider.conf.yml read-only | ✅ Partial |
106
+ | **Any CLI** | Wrapper mode (PATH hijacking) | ✅ Universal |
143
107
 
144
108
  ## Commands
145
109
 
146
110
  ```
147
- leash <agent> "<restriction>" Wrap agent with policy
148
- leash watch "<restriction>" Background file protection
149
- leash explain "<restriction>" Preview policy without installing
150
- leash add "<restriction>" Save policy for native install
151
- leash init Create .leash config file
152
- leash sync [agent] Apply .leash policies
153
- leash install <agent> Install native hooks
154
- leash uninstall <agent> Remove native hooks
155
- leash list Show saved policies
156
- leash audit [--tail] [--clear] View audit log
157
- leash login Leash Cloud (coming soon)
111
+ leash init Auto-detect agents, install hooks
112
+ leash sync [agent] Apply .leash policies to agents
113
+ leash add "<rule>" Add a policy
114
+ leash install <agent> Install hooks for specific agent
115
+ leash explain "<rule>" Preview what a rule catches
116
+ leash watch "<rule>" Background file protection
117
+ leash audit [--tail] View enforcement log
158
118
  leash status Show active sessions
159
- leash clear Clear compilation cache
160
119
  ```
161
120
 
162
- ## Built-in Patterns
163
-
164
- These work instantly without an API key:
165
-
166
- | Phrase | What It Protects |
167
- |--------|-----------------|
168
- | `test files` | `*.test.*`, `*.spec.*`, `__tests__/**` |
169
- | `.env` | `.env`, `.env.*`, excluding `.env.example` |
170
- | `migrations` | `**/migrations/**`, `prisma/migrations/**` |
171
- | `config` | `*.config.*`, `tsconfig*`, `.eslintrc*` |
172
- | `lock files` | `package-lock.json`, `yarn.lock`, etc. |
173
-
174
- ## Examples
175
-
176
- ```bash
177
- # Preview what a policy protects
178
- leash explain "don't delete test files"
179
-
180
- # Wrapper mode - intercepts shell commands
181
- leash cc "don't delete test files"
182
-
183
- # Native mode - integrates with agent's permission system
184
- leash add "don't delete test files"
185
- leash add "protect .env"
186
- leash install cc
187
-
188
- # Watchdog mode - file system monitoring
189
- leash watch "protect test files"
121
+ ## How It Works
190
122
 
191
- # Team config
192
- leash init # Creates .leash
193
- leash sync windsurf # Applies to agent
123
+ ```
124
+ User: "no lodash"
125
+
126
+ ┌─────────────────────────────────────────┐
127
+ │ 1. Check builtins (instant, no LLM) │
128
+ │ → Found: "no lodash" builtin │
129
+ └─────────────────────────────────────────┘
130
+
131
+ ┌─────────────────────────────────────────┐
132
+ │ 2. Runtime: Write/Edit intercepted │
133
+ │ → Regex pre-filter: contains │
134
+ │ "lodash"? Yes → continue │
135
+ │ → AST parse (5ms, cached) │
136
+ │ → Query: import_statement with │
137
+ │ source matching "lodash" │
138
+ │ → BLOCKED with line/column │
139
+ └─────────────────────────────────────────┘
194
140
  ```
195
141
 
196
- ## Environment Variables
197
-
198
- | Variable | Description |
199
- |----------|-------------|
200
- | `GEMINI_API_KEY` | Required for custom restrictions (not builtins) |
201
- | `LEASH_CLOUD_URL` | Leash Cloud API endpoint (coming soon) |
202
- | `LEASH_API_KEY` | Leash Cloud API key (coming soon) |
142
+ **Key insight**: Regex pre-filter skips 95%+ of files instantly. AST parsing only runs when needed.
203
143
 
204
- ## Leash Cloud (Coming Soon)
144
+ ## Environment Variables
205
145
 
206
- - Team-wide policy sync
207
- - Centralized audit logs
208
- - LLM credits for compilation
209
- - Policy analytics
146
+ | Variable | Description |
147
+ | ---------------- | ------------------------------------------- |
148
+ | `GEMINI_API_KEY` | Only needed for custom rules (not builtins) |
210
149
 
211
- Join the waitlist: https://leash.cloud
150
+ Get a free API key: https://aistudio.google.com/apikey
212
151
 
213
152
  ## Philosophy
214
153
 
215
- 1. **Semantic over syntactic** - "test files" means test source code, not files with "test" in the name
216
- 2. **Compile once, enforce always** - LLM runs once at startup, enforcement is instant
217
- 3. **Fail closed** - If the daemon is unreachable, commands are blocked
218
- 4. **Defense in depth** - Native hooks + wrapper mode + watchdog = comprehensive protection
219
- 5. **No config tax** - Natural language in, protection out
220
-
221
- ## How veto-leash Protects Files
222
-
223
- When you run `leash cc "don't delete test files"`:
224
-
225
- 1. **Compile**: Natural language → glob patterns (via Gemini 2.0 Flash)
226
- 2. **Start daemon**: TCP server on localhost (random port)
227
- 3. **Create shims**: Shell wrappers for `rm`, `git rm`, etc.
228
- 4. **Launch agent**: With modified PATH
229
- 5. **Intercept**: Every shell command checks daemon first
230
- 6. **Block or allow**: Based on policy
231
-
232
- The agent never knows veto-leash is there - it just sees commands failing with clear error messages.
154
+ 1. **Surgeon-level precision** - AST parsing = zero false positives
155
+ 2. **Invisible until needed** - Auto-detection, background enforcement
156
+ 3. **Steroid, not weight** - Makes AI agents _better_, not slower
157
+ 4. **Natural language policies** - `no lodash` not `{ "rule": "no-import", "pattern": "^lodash" }`
233
158
 
234
- ## Security Model
159
+ ## Test Suite
235
160
 
236
- - Localhost only (`127.0.0.1`)
237
- - Random port each session
238
- - Temp directory cleaned on exit
239
- - No eval - patterns validated with micromatch
240
- - Fail closed by default
241
- - API key from environment only
242
-
243
- ## Platform Support
244
-
245
- - macOS
246
- - Linux
247
- - Windows (PowerShell shims)
248
- - WSL
161
+ ```
162
+ 229 tests passing
163
+ ├── 41 AST validation tests
164
+ ├── 93 content matching tests
165
+ ├── 41 command interception tests
166
+ ├── 17 pattern matcher tests
167
+ ├── 16 builtin rules tests
168
+ ├── 12 parser tests
169
+ └── 9 session tests
170
+ ```
249
171
 
250
172
  ## License
251
173
 
252
- MIT
253
-
254
- ## Credits
255
-
256
- Built by [Plaw, Inc.](https://plaw.io) for the [Veto](https://veto.dev) product line.
174
+ Apache-2.0
257
175
 
258
176
  ---
259
177
 
260
- Ship faster. Sleep better.
178
+ <p align="center">
179
+ Built by <a href="https://plaw.io">Plaw, Inc.</a> for the <a href="https://veto.dev">Veto</a> product line.
180
+ <br><br>
181
+ <strong>Ship faster. Sleep better.</strong>
182
+ </p>
@@ -0,0 +1,28 @@
1
+ import type { ASTRule } from '../types.js';
2
+ /**
3
+ * Pre-compiled AST queries for common restrictions.
4
+ * These replace regex-based content rules with precise structural queries.
5
+ *
6
+ * Key advantages over regex:
7
+ * - Zero false positives (AST ignores comments and strings)
8
+ * - Catches all variants (destructuring, bracket notation, dynamic imports)
9
+ * - Can express structural constraints regex cannot
10
+ *
11
+ * Query syntax: tree-sitter S-expressions
12
+ * - (node_type) matches any node of that type
13
+ * - (node_type field: (child)) matches with specific field
14
+ * - @name captures the node
15
+ * - (#eq? @name "value") exact string match on node text
16
+ * - (#match? @name "regex") regex match on node text
17
+ */
18
+ export declare const AST_BUILTINS: Record<string, ASTRule[]>;
19
+ /**
20
+ * Get all AST rules for a restriction
21
+ * Normalizes common variations (e.g., "no any" vs "no any types")
22
+ */
23
+ export declare function getASTRules(restriction: string): ASTRule[] | null;
24
+ /**
25
+ * List all available AST builtin keys
26
+ */
27
+ export declare function listASTBuiltins(): string[];
28
+ //# sourceMappingURL=builtins.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"builtins.d.ts","sourceRoot":"","sources":["../../src/ast/builtins.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,aAAa,CAAC;AAE3C;;;;;;;;;;;;;;;GAeG;AACH,eAAO,MAAM,YAAY,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,EAAE,CAyUlD,CAAC;AAEF;;;GAGG;AACH,wBAAgB,WAAW,CAAC,WAAW,EAAE,MAAM,GAAG,OAAO,EAAE,GAAG,IAAI,CA0BjE;AAED;;GAEG;AACH,wBAAgB,eAAe,IAAI,MAAM,EAAE,CAE1C"}