@clawdreyhepburn/carapace 0.2.0 → 0.3.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
@@ -10,6 +10,7 @@
10
10
  <a href="#installation">Installation</a> •
11
11
  <a href="#quick-start">Quick Start</a> •
12
12
  <a href="#how-it-works">How It Works</a> •
13
+ <a href="docs/RECOMMENDED-POLICIES.md">Recommended Policies</a> •
13
14
  <a href="#gui">Control GUI</a> •
14
15
  <a href="#security">Security</a> •
15
16
  <a href="#attribution">Attribution</a>
@@ -37,19 +38,22 @@ The progression:
37
38
  ## Architecture
38
39
 
39
40
  ```
40
- +-------------+ +----------------------------+ +-----------------+
41
- | | | Carapace | | MCP Server A |
42
- | OpenClaw |---->| |---->| (filesystem) |
43
- | Agent | | +----------------------+ | +-----------------+
44
- | | | | Cedarling WASM | | | MCP Server B |
45
- | mcp_call |---->| | (Cedar 4.4.2) | |---->| (GitHub) |
46
- | | | +----------------------+ | +-----------------+
47
- | carapace | | | +-----------------+
48
- | _exec --|---->| Cedar: exec_command |---->| Shell (local) |
49
- | | | | +-----------------+
50
- | carapace | | | +-----------------+
51
- | _fetch --|---->| Cedar: call_api |---->| HTTP (remote) |
52
- | | | +----------------------+ | +-----------------+
41
+ +----------------------------+
42
+ | Carapace |
43
+ +-------------+ | | +------------------+
44
+ | | | +----------------------+ | | Anthropic / |
45
+ | OpenClaw |---->| | LLM Proxy | |---->| OpenAI API |
46
+ | Agent | | | (intercepts tool_use)| | +------------------+
47
+ | | | +----------------------+ |
48
+ | | | | | +-----------------+
49
+ | | | Cedar evaluates | | MCP Server A |
50
+ | | | every tool call |---->| (filesystem) |
51
+ | | | | | +-----------------+
52
+ | | | +----------------------+ | | MCP Server B |
53
+ | | | | Cedarling WASM | |---->| (GitHub) |
54
+ | | | | (Cedar 4.4.2) | | +-----------------+
55
+ | | | +----------------------+ |
56
+ | | | +----------------------+ |
53
57
  | | | | Local Control GUI | |
54
58
  +-------------+ | +----------------------+ |
55
59
  +--------------+--------------+
@@ -60,7 +64,11 @@ The progression:
60
64
  +-------------+
61
65
  ```
62
66
 
63
- **Every operation flows through Cedar evaluation.** MCP tool calls, shell commands, and outbound API requests are all authorized by Cedar policies before execution. If the policy says deny, the operation never happens. The agent gets a clear denial message with the reason.
67
+ ### Two enforcement modes
68
+
69
+ **LLM Proxy (recommended):** Carapace holds the real API key and proxies all LLM traffic. When the LLM suggests a tool call, Carapace evaluates it against Cedar *before returning the response to OpenClaw*. Denied tool calls are stripped from the response — OpenClaw never sees them and can't execute them. **This is un-bypassable.** The agent can't call tools that Cedar denies because it literally never receives the tool call instruction.
70
+
71
+ **Tool-level gating:** Carapace registers Cedar-gated agent tools (`carapace_exec`, `carapace_fetch`, `mcp_call`) that authorize each operation before executing it. This requires denying built-in tools via `openclaw carapace setup` to prevent bypass. Use this mode when you can't or don't want to proxy LLM traffic.
64
72
 
65
73
  ## Screenshots
66
74
 
@@ -154,18 +162,70 @@ In your OpenClaw config, add the servers you want Carapace to manage:
154
162
  }
155
163
  ```
156
164
 
157
- ### 2. Open the control GUI
165
+ ### 2. Enable the LLM Proxy (recommended)
166
+
167
+ The LLM Proxy is the strongest enforcement mode. Carapace holds the real API key and intercepts tool calls before OpenClaw can execute them.
168
+
169
+ ```json5
170
+ {
171
+ plugins: {
172
+ entries: {
173
+ carapace: {
174
+ enabled: true,
175
+ config: {
176
+ proxy: {
177
+ enabled: true,
178
+ port: 19821,
179
+ upstream: {
180
+ anthropic: { apiKey: "sk-ant-your-real-key-here" }
181
+ }
182
+ }
183
+ }
184
+ }
185
+ }
186
+ },
187
+ // Point OpenClaw at the proxy instead of the real API
188
+ providers: {
189
+ anthropic: {
190
+ apiKey: "carapace-proxy", // dummy — proxy holds the real key
191
+ baseUrl: "http://127.0.0.1:19821"
192
+ }
193
+ }
194
+ }
195
+ ```
196
+
197
+ Now every tool call the LLM suggests goes through Cedar. If Cedar denies it, the tool call is stripped from the response before OpenClaw ever sees it.
198
+
199
+ ### 3. (Alternative) Close the bypass gap without the proxy
200
+
201
+ By default, agents can still use OpenClaw's built-in `exec` and `web_fetch` tools, which bypass Cedar entirely. Run setup to close this:
202
+
203
+ ```bash
204
+ openclaw carapace setup
205
+ ```
206
+
207
+ This adds `exec`, `web_fetch`, and `web_search` to `tools.deny` in your OpenClaw config, forcing agents to use `carapace_exec` and `carapace_fetch` instead — which go through Cedar.
208
+
209
+ You can check for bypasses anytime:
210
+
211
+ ```bash
212
+ openclaw carapace check
213
+ ```
214
+
215
+ > ⚠️ **Without this step, Carapace policies are advisory, not enforced.** The agent can simply choose to use the built-in tools instead. Always run `carapace setup` for real security.
216
+
217
+ ### 4. Open the control GUI
158
218
 
159
219
  Navigate to [http://localhost:19820](http://localhost:19820) in your browser. You'll see all discovered tools from all connected servers.
160
220
 
161
- ### 3. Enable tools
221
+ ### 5. Enable tools
162
222
 
163
223
  Toggle individual tools on/off. Each toggle writes a Cedar policy:
164
224
 
165
225
  - **Toggle ON** → creates a `permit` policy for that tool
166
226
  - **Toggle OFF** → creates a `forbid` policy for that tool
167
227
 
168
- ### 4. Create custom policies
228
+ ### 6. Create custom policies
169
229
 
170
230
  Click **"+ New Policy"** to open the visual builder, or edit policies directly in the Policies tab. Examples:
171
231
 
@@ -218,7 +278,9 @@ permit(
218
278
  );
219
279
  ```
220
280
 
221
- ### 5. Verify policies
281
+ > 📖 **Want more?** See [Recommended Policies](docs/RECOMMENDED-POLICIES.md) for real-world policies covering destructive commands, credential theft, data exfiltration, email deletion, and complete starter configurations.
282
+
283
+ ### 7. Verify policies
222
284
 
223
285
  Click **⚡ Verify** to validate that all policies are syntactically correct and consistent.
224
286
 
@@ -0,0 +1,519 @@
1
+ # Recommended Policies
2
+
3
+ Real-world Cedar policies for common "oh no" scenarios. These are starting points — adapt them to your agent's actual needs.
4
+
5
+ ## Before You Write Policies: Close the Bypass Gap
6
+
7
+ **This is the most important step.** If you skip it, every policy in this document is advisory — the agent can just use OpenClaw's built-in `exec` tool instead of `carapace_exec` and bypass Cedar entirely.
8
+
9
+ ```bash
10
+ openclaw carapace setup
11
+ openclaw gateway restart
12
+ ```
13
+
14
+ This denies the built-in `exec`, `web_fetch`, and `web_search` tools, forcing agents to use the Cedar-gated `carapace_exec` and `carapace_fetch` instead. Verify with:
15
+
16
+ ```bash
17
+ openclaw carapace check
18
+ # Should show: ✅ No bypass vulnerabilities found.
19
+ ```
20
+
21
+ **Without this, an agent can:**
22
+ - Call `exec` directly with `rm -rf /` — Carapace never sees it
23
+ - Call `web_fetch` to exfiltrate data — Carapace never sees it
24
+ - Call `exec` with `curl` to hit any API — Carapace never sees it
25
+
26
+ Run setup first. Then write policies.
27
+
28
+ ## The Basics
29
+
30
+ Carapace defaults to **allow-all** so installing it never breaks anything. The recommended path:
31
+
32
+ 1. **Run `carapace setup`** → close the bypass gap
33
+ 2. **Add forbids** → block the scary stuff (this doc)
34
+ 3. **Switch to deny-all** → explicitly permit only what's needed (advanced)
35
+
36
+ Most people should start with step 2 and stay there until they're comfortable.
37
+
38
+ ---
39
+
40
+ ## Shell Policies
41
+
42
+ ### Block destructive file operations
43
+
44
+ The classics. An agent with shell access can `rm -rf /` before you blink.
45
+
46
+ ```cedar
47
+ // Block rm entirely — use trash instead
48
+ forbid(
49
+ principal,
50
+ action == Jans::Action::"exec_command",
51
+ resource == Jans::Shell::"rm"
52
+ );
53
+
54
+ // Block destructive disk tools
55
+ forbid(
56
+ principal,
57
+ action == Jans::Action::"exec_command",
58
+ resource == Jans::Shell::"rmdir"
59
+ );
60
+
61
+ forbid(
62
+ principal,
63
+ action == Jans::Action::"exec_command",
64
+ resource == Jans::Shell::"mkfs"
65
+ );
66
+
67
+ forbid(
68
+ principal,
69
+ action == Jans::Action::"exec_command",
70
+ resource == Jans::Shell::"dd"
71
+ );
72
+
73
+ // Block format/partition tools
74
+ forbid(
75
+ principal,
76
+ action == Jans::Action::"exec_command",
77
+ resource == Jans::Shell::"diskutil"
78
+ );
79
+ ```
80
+
81
+ **Why:** An agent that can delete files can delete *all* files. `rm` is the single most dangerous command you can give an agent. Use `trash` (recoverable) instead and permit that.
82
+
83
+ ### Block credential and secret access
84
+
85
+ Agents don't need to read your SSH keys or browser passwords.
86
+
87
+ ```cedar
88
+ // Block direct credential access tools
89
+ forbid(
90
+ principal,
91
+ action == Jans::Action::"exec_command",
92
+ resource == Jans::Shell::"security"
93
+ );
94
+
95
+ forbid(
96
+ principal,
97
+ action == Jans::Action::"exec_command",
98
+ resource == Jans::Shell::"ssh-keygen"
99
+ );
100
+
101
+ forbid(
102
+ principal,
103
+ action == Jans::Action::"exec_command",
104
+ resource == Jans::Shell::"gpg"
105
+ );
106
+
107
+ // Block password managers
108
+ forbid(
109
+ principal,
110
+ action == Jans::Action::"exec_command",
111
+ resource == Jans::Shell::"op"
112
+ );
113
+
114
+ forbid(
115
+ principal,
116
+ action == Jans::Action::"exec_command",
117
+ resource == Jans::Shell::"pass"
118
+ );
119
+ ```
120
+
121
+ **Why:** `security` (macOS Keychain CLI) can dump stored passwords. `ssh-keygen` can overwrite your keys. An agent doesn't need either of these to do useful work.
122
+
123
+ ### Block system administration
124
+
125
+ Unless your agent is explicitly managing infrastructure, it shouldn't touch system config.
126
+
127
+ ```cedar
128
+ forbid(
129
+ principal,
130
+ action == Jans::Action::"exec_command",
131
+ resource == Jans::Shell::"sudo"
132
+ );
133
+
134
+ forbid(
135
+ principal,
136
+ action == Jans::Action::"exec_command",
137
+ resource == Jans::Shell::"su"
138
+ );
139
+
140
+ forbid(
141
+ principal,
142
+ action == Jans::Action::"exec_command",
143
+ resource == Jans::Shell::"chmod"
144
+ );
145
+
146
+ forbid(
147
+ principal,
148
+ action == Jans::Action::"exec_command",
149
+ resource == Jans::Shell::"chown"
150
+ );
151
+
152
+ forbid(
153
+ principal,
154
+ action == Jans::Action::"exec_command",
155
+ resource == Jans::Shell::"launchctl"
156
+ );
157
+
158
+ forbid(
159
+ principal,
160
+ action == Jans::Action::"exec_command",
161
+ resource == Jans::Shell::"systemctl"
162
+ );
163
+ ```
164
+
165
+ **Why:** Privilege escalation is the nightmare scenario. If your agent can `sudo`, it can do *anything*. Even `chmod` can weaken file permissions enough to enable other attacks.
166
+
167
+ ### Block network reconnaissance
168
+
169
+ Agents don't need to scan your network.
170
+
171
+ ```cedar
172
+ forbid(
173
+ principal,
174
+ action == Jans::Action::"exec_command",
175
+ resource == Jans::Shell::"nmap"
176
+ );
177
+
178
+ forbid(
179
+ principal,
180
+ action == Jans::Action::"exec_command",
181
+ resource == Jans::Shell::"tcpdump"
182
+ );
183
+
184
+ forbid(
185
+ principal,
186
+ action == Jans::Action::"exec_command",
187
+ resource == Jans::Shell::"netcat"
188
+ );
189
+
190
+ forbid(
191
+ principal,
192
+ action == Jans::Action::"exec_command",
193
+ resource == Jans::Shell::"nc"
194
+ );
195
+ ```
196
+
197
+ ### Allow a safe set of dev tools
198
+
199
+ If your agent does development work, permit the tools it actually needs:
200
+
201
+ ```cedar
202
+ // Version control
203
+ permit(
204
+ principal is Jans::Workload,
205
+ action == Jans::Action::"exec_command",
206
+ resource == Jans::Shell::"git"
207
+ );
208
+
209
+ // Package managers
210
+ permit(
211
+ principal is Jans::Workload,
212
+ action == Jans::Action::"exec_command",
213
+ resource == Jans::Shell::"npm"
214
+ );
215
+
216
+ permit(
217
+ principal is Jans::Workload,
218
+ action == Jans::Action::"exec_command",
219
+ resource == Jans::Shell::"npx"
220
+ );
221
+
222
+ // Safe file operations
223
+ permit(
224
+ principal is Jans::Workload,
225
+ action == Jans::Action::"exec_command",
226
+ resource == Jans::Shell::"cat"
227
+ );
228
+
229
+ permit(
230
+ principal is Jans::Workload,
231
+ action == Jans::Action::"exec_command",
232
+ resource == Jans::Shell::"ls"
233
+ );
234
+
235
+ permit(
236
+ principal is Jans::Workload,
237
+ action == Jans::Action::"exec_command",
238
+ resource == Jans::Shell::"grep"
239
+ );
240
+
241
+ permit(
242
+ principal is Jans::Workload,
243
+ action == Jans::Action::"exec_command",
244
+ resource == Jans::Shell::"find"
245
+ );
246
+
247
+ permit(
248
+ principal is Jans::Workload,
249
+ action == Jans::Action::"exec_command",
250
+ resource == Jans::Shell::"trash"
251
+ );
252
+ ```
253
+
254
+ ---
255
+
256
+ ## API Policies
257
+
258
+ ### Block data exfiltration
259
+
260
+ An agent that can POST to any URL can send your files, credentials, and chat history anywhere.
261
+
262
+ ```cedar
263
+ // Block known paste/upload services
264
+ forbid(
265
+ principal,
266
+ action == Jans::Action::"call_api",
267
+ resource == Jans::API::"pastebin.com"
268
+ );
269
+
270
+ forbid(
271
+ principal,
272
+ action == Jans::Action::"call_api",
273
+ resource == Jans::API::"hastebin.com"
274
+ );
275
+
276
+ forbid(
277
+ principal,
278
+ action == Jans::Action::"call_api",
279
+ resource == Jans::API::"transfer.sh"
280
+ );
281
+
282
+ forbid(
283
+ principal,
284
+ action == Jans::Action::"call_api",
285
+ resource == Jans::API::"file.io"
286
+ );
287
+
288
+ forbid(
289
+ principal,
290
+ action == Jans::Action::"call_api",
291
+ resource == Jans::API::"webhook.site"
292
+ );
293
+
294
+ forbid(
295
+ principal,
296
+ action == Jans::Action::"call_api",
297
+ resource == Jans::API::"requestbin.com"
298
+ );
299
+ ```
300
+
301
+ **Why:** Prompt injection attacks can instruct an agent to exfiltrate data by posting it to an attacker-controlled URL. Blocking common exfil endpoints is a basic hygiene measure.
302
+
303
+ ### Allow specific APIs your agent needs
304
+
305
+ Better than blocking bad domains: only allow the domains your agent actually uses.
306
+
307
+ ```cedar
308
+ // GitHub API
309
+ permit(
310
+ principal is Jans::Workload,
311
+ action == Jans::Action::"call_api",
312
+ resource == Jans::API::"api.github.com"
313
+ );
314
+
315
+ // npm registry
316
+ permit(
317
+ principal is Jans::Workload,
318
+ action == Jans::Action::"call_api",
319
+ resource == Jans::API::"registry.npmjs.org"
320
+ );
321
+
322
+ // Your own services
323
+ permit(
324
+ principal is Jans::Workload,
325
+ action == Jans::Action::"call_api",
326
+ resource == Jans::API::"api.yourcompany.com"
327
+ );
328
+ ```
329
+
330
+ ### Block social media posting
331
+
332
+ If your agent has social media access, you might want to prevent it from posting without oversight, or block it from leaking info to random accounts.
333
+
334
+ ```cedar
335
+ // Block direct API access to social platforms
336
+ forbid(
337
+ principal,
338
+ action == Jans::Action::"call_api",
339
+ resource == Jans::API::"api.twitter.com"
340
+ );
341
+
342
+ forbid(
343
+ principal,
344
+ action == Jans::Action::"call_api",
345
+ resource == Jans::API::"api.x.com"
346
+ );
347
+
348
+ forbid(
349
+ principal,
350
+ action == Jans::Action::"call_api",
351
+ resource == Jans::API::"graph.facebook.com"
352
+ );
353
+
354
+ forbid(
355
+ principal,
356
+ action == Jans::Action::"call_api",
357
+ resource == Jans::API::"api.linkedin.com"
358
+ );
359
+ ```
360
+
361
+ **Why:** An agent that can post to social media can damage your reputation in seconds. Even if your agent "should" post, you probably want that gated through an MCP tool with its own policy rather than raw API access.
362
+
363
+ ---
364
+
365
+ ## MCP Tool Policies
366
+
367
+ ### Block destructive MCP tools
368
+
369
+ If you're using the filesystem MCP server, the write tools are the dangerous ones:
370
+
371
+ ```cedar
372
+ forbid(
373
+ principal,
374
+ action == Jans::Action::"call_tool",
375
+ resource == Jans::Tool::"filesystem/write_file"
376
+ );
377
+
378
+ forbid(
379
+ principal,
380
+ action == Jans::Action::"call_tool",
381
+ resource == Jans::Tool::"filesystem/move_file"
382
+ );
383
+ ```
384
+
385
+ ### Block email mass operations
386
+
387
+ If your agent has email access via MCP:
388
+
389
+ ```cedar
390
+ // Prevent bulk deletion
391
+ forbid(
392
+ principal,
393
+ action == Jans::Action::"call_tool",
394
+ resource == Jans::Tool::"email/delete_all"
395
+ );
396
+
397
+ forbid(
398
+ principal,
399
+ action == Jans::Action::"call_tool",
400
+ resource == Jans::Tool::"email/empty_trash"
401
+ );
402
+
403
+ // Prevent mass sending (spam)
404
+ forbid(
405
+ principal,
406
+ action == Jans::Action::"call_tool",
407
+ resource == Jans::Tool::"email/send_bulk"
408
+ );
409
+ ```
410
+
411
+ **Why:** An agent that can delete emails can delete your *entire inbox*. An agent that can send emails can spam your contacts. These are catastrophic, irreversible actions.
412
+
413
+ ### Block database mutations
414
+
415
+ If your agent has database access:
416
+
417
+ ```cedar
418
+ forbid(
419
+ principal,
420
+ action == Jans::Action::"call_tool",
421
+ resource == Jans::Tool::"database/execute_sql"
422
+ );
423
+
424
+ // Allow reads only
425
+ permit(
426
+ principal is Jans::Workload,
427
+ action == Jans::Action::"call_tool",
428
+ resource == Jans::Tool::"database/query"
429
+ );
430
+ ```
431
+
432
+ ---
433
+
434
+ ## Complete Starter Policies
435
+
436
+ ### "Cautious developer" — safe for a coding agent
437
+
438
+ ```cedar
439
+ // Shell: allow common dev tools, block everything dangerous
440
+ permit(principal is Jans::Workload, action == Jans::Action::"exec_command", resource == Jans::Shell::"git");
441
+ permit(principal is Jans::Workload, action == Jans::Action::"exec_command", resource == Jans::Shell::"npm");
442
+ permit(principal is Jans::Workload, action == Jans::Action::"exec_command", resource == Jans::Shell::"npx");
443
+ permit(principal is Jans::Workload, action == Jans::Action::"exec_command", resource == Jans::Shell::"node");
444
+ permit(principal is Jans::Workload, action == Jans::Action::"exec_command", resource == Jans::Shell::"cat");
445
+ permit(principal is Jans::Workload, action == Jans::Action::"exec_command", resource == Jans::Shell::"ls");
446
+ permit(principal is Jans::Workload, action == Jans::Action::"exec_command", resource == Jans::Shell::"grep");
447
+ permit(principal is Jans::Workload, action == Jans::Action::"exec_command", resource == Jans::Shell::"find");
448
+ permit(principal is Jans::Workload, action == Jans::Action::"exec_command", resource == Jans::Shell::"trash");
449
+ permit(principal is Jans::Workload, action == Jans::Action::"exec_command", resource == Jans::Shell::"mkdir");
450
+ permit(principal is Jans::Workload, action == Jans::Action::"exec_command", resource == Jans::Shell::"cp");
451
+ permit(principal is Jans::Workload, action == Jans::Action::"exec_command", resource == Jans::Shell::"mv");
452
+
453
+ forbid(principal, action == Jans::Action::"exec_command", resource == Jans::Shell::"rm");
454
+ forbid(principal, action == Jans::Action::"exec_command", resource == Jans::Shell::"sudo");
455
+ forbid(principal, action == Jans::Action::"exec_command", resource == Jans::Shell::"security");
456
+
457
+ // API: allow GitHub and npm, block exfil
458
+ permit(principal is Jans::Workload, action == Jans::Action::"call_api", resource == Jans::API::"api.github.com");
459
+ permit(principal is Jans::Workload, action == Jans::Action::"call_api", resource == Jans::API::"registry.npmjs.org");
460
+ forbid(principal, action == Jans::Action::"call_api", resource == Jans::API::"pastebin.com");
461
+ forbid(principal, action == Jans::Action::"call_api", resource == Jans::API::"webhook.site");
462
+
463
+ // MCP: allow all tools (rely on shell/API policies for safety)
464
+ permit(principal is Jans::Workload, action == Jans::Action::"call_tool", resource);
465
+ ```
466
+
467
+ ### "Paranoid lockdown" — least privilege, deny-all baseline
468
+
469
+ Set `defaultPolicy: "deny-all"` in config, then only add permits:
470
+
471
+ ```cedar
472
+ // Only the exact tools this agent needs
473
+ permit(principal is Jans::Workload, action == Jans::Action::"call_tool", resource == Jans::Tool::"filesystem/read_file");
474
+ permit(principal is Jans::Workload, action == Jans::Action::"call_tool", resource == Jans::Tool::"filesystem/list_directory");
475
+
476
+ // Only git
477
+ permit(principal is Jans::Workload, action == Jans::Action::"exec_command", resource == Jans::Shell::"git");
478
+
479
+ // No API access at all (omit all call_api permits)
480
+ ```
481
+
482
+ Everything not explicitly permitted is denied. This is the most secure posture but requires you to know exactly what your agent needs.
483
+
484
+ ---
485
+
486
+ ## Policy Design Principles
487
+
488
+ 1. **Forbid the catastrophic, then iterate.** Start by blocking `rm`, `sudo`, and data exfil domains. You can always add more forbids later.
489
+
490
+ 2. **Forbid always wins.** In Cedar, a `forbid` policy overrides any `permit`. This means you can write broad permits and surgical forbids without worrying about order or precedence.
491
+
492
+ 3. **Binary name is the gate, not the arguments.** `Shell::"git"` permits *all* git commands including `git push --force`. If you need argument-level control, use Cedar `when` conditions on `context.args`:
493
+
494
+ ```cedar
495
+ forbid(
496
+ principal,
497
+ action == Jans::Action::"exec_command",
498
+ resource == Jans::Shell::"git"
499
+ ) when {
500
+ context.args like "*--force*"
501
+ };
502
+ ```
503
+
504
+ 4. **Domain name is the gate, not the path.** `API::"api.github.com"` permits all endpoints on that domain. If you need path-level control, use `when` conditions on `context.url`.
505
+
506
+ 5. **Deny-all is aspirational.** Most people should start with allow-all + surgical forbids. Switch to deny-all only when you understand your agent's full tool surface.
507
+
508
+ 6. **Review regularly.** Your agent's needs change. Policies that made sense last month might be too loose or too tight today. The GUI makes this easy — open it, look at what's enabled, adjust.
509
+
510
+ ---
511
+
512
+ ## Further Reading
513
+
514
+ - [Cedar for AI Agents: Why Your AI Agent Needs a Policy Language](https://clawdrey.com/blog/cedar-for-ai-agents-part-1-why-your-ai-agent-needs-a-policy-language.html)
515
+ - [Cedar for AI Agents: Writing Your First Agent Policy](https://clawdrey.com/blog/cedar-for-ai-agents-part-2-writing-your-first-agent-policy.html)
516
+ - [Cedar for AI Agents: When Forbid Meets Permit](https://clawdrey.com/blog/cedar-for-ai-agents-part-3-when-forbid-meets-permit.html)
517
+ - [Cedar for AI Agents: Proving It — SMT Solvers and Why I Trust Math More Than Tests](https://clawdrey.com/blog/proving-it-smt-solvers-and-why-i-trust-math-more-than-tests.html)
518
+ - [Cedar Language Reference](https://docs.cedarpolicy.com/)
519
+ - [Carapace README](../README.md)
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@clawdreyhepburn/carapace",
3
- "version": "0.2.0",
3
+ "version": "0.3.0",
4
4
  "description": "Immutable policy boundaries for MCP tool access. Powered by Cedar + Cedarling WASM.",
5
5
  "license": "Apache-2.0",
6
6
  "type": "module",
@@ -576,6 +576,11 @@ export class CedarlingEngine {
576
576
  name: "String",
577
577
  required: false,
578
578
  },
579
+ workdir: {
580
+ type: "EntityOrCommon",
581
+ name: "String",
582
+ required: false,
583
+ },
579
584
  },
580
585
  },
581
586
  },
@@ -587,6 +592,16 @@ export class CedarlingEngine {
587
592
  context: {
588
593
  type: "Record",
589
594
  attributes: {
595
+ url: {
596
+ type: "EntityOrCommon",
597
+ name: "String",
598
+ required: false,
599
+ },
600
+ method: {
601
+ type: "EntityOrCommon",
602
+ name: "String",
603
+ required: false,
604
+ },
590
605
  body: {
591
606
  type: "EntityOrCommon",
592
607
  name: "String",