predicate-claw 0.1.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 (136) hide show
  1. package/.github/workflows/release.yml +76 -0
  2. package/.github/workflows/tests.yml +34 -0
  3. package/.markdownlint.yaml +5 -0
  4. package/.pre-commit-config.yaml +100 -0
  5. package/README.md +405 -0
  6. package/dist/src/adapter.d.ts +17 -0
  7. package/dist/src/adapter.js +36 -0
  8. package/dist/src/authority-client.d.ts +21 -0
  9. package/dist/src/authority-client.js +22 -0
  10. package/dist/src/circuit-breaker.d.ts +86 -0
  11. package/dist/src/circuit-breaker.js +174 -0
  12. package/dist/src/config.d.ts +8 -0
  13. package/dist/src/config.js +7 -0
  14. package/dist/src/control-plane-sync.d.ts +57 -0
  15. package/dist/src/control-plane-sync.js +99 -0
  16. package/dist/src/errors.d.ts +6 -0
  17. package/dist/src/errors.js +6 -0
  18. package/dist/src/index.d.ts +12 -0
  19. package/dist/src/index.js +12 -0
  20. package/dist/src/non-web-evidence.d.ts +46 -0
  21. package/dist/src/non-web-evidence.js +54 -0
  22. package/dist/src/openclaw-hooks.d.ts +27 -0
  23. package/dist/src/openclaw-hooks.js +54 -0
  24. package/dist/src/openclaw-plugin-api.d.ts +18 -0
  25. package/dist/src/openclaw-plugin-api.js +17 -0
  26. package/dist/src/provider.d.ts +48 -0
  27. package/dist/src/provider.js +154 -0
  28. package/dist/src/runtime-integration.d.ts +20 -0
  29. package/dist/src/runtime-integration.js +43 -0
  30. package/dist/src/web-evidence.d.ts +48 -0
  31. package/dist/src/web-evidence.js +49 -0
  32. package/dist/tests/adapter.test.d.ts +1 -0
  33. package/dist/tests/adapter.test.js +63 -0
  34. package/dist/tests/audit-event-e2e.test.d.ts +1 -0
  35. package/dist/tests/audit-event-e2e.test.js +209 -0
  36. package/dist/tests/authority-client.test.d.ts +1 -0
  37. package/dist/tests/authority-client.test.js +46 -0
  38. package/dist/tests/circuit-breaker.test.d.ts +1 -0
  39. package/dist/tests/circuit-breaker.test.js +200 -0
  40. package/dist/tests/control-plane-sync.test.d.ts +1 -0
  41. package/dist/tests/control-plane-sync.test.js +90 -0
  42. package/dist/tests/hack-vs-fix-demo.test.d.ts +1 -0
  43. package/dist/tests/hack-vs-fix-demo.test.js +36 -0
  44. package/dist/tests/jwks-rotation.test.d.ts +1 -0
  45. package/dist/tests/jwks-rotation.test.js +232 -0
  46. package/dist/tests/load-latency.test.d.ts +1 -0
  47. package/dist/tests/load-latency.test.js +175 -0
  48. package/dist/tests/multi-tenant-isolation.test.d.ts +1 -0
  49. package/dist/tests/multi-tenant-isolation.test.js +146 -0
  50. package/dist/tests/non-web-evidence.test.d.ts +1 -0
  51. package/dist/tests/non-web-evidence.test.js +139 -0
  52. package/dist/tests/openclaw-hooks.test.d.ts +1 -0
  53. package/dist/tests/openclaw-hooks.test.js +38 -0
  54. package/dist/tests/openclaw-plugin-api.test.d.ts +1 -0
  55. package/dist/tests/openclaw-plugin-api.test.js +40 -0
  56. package/dist/tests/provider.test.d.ts +1 -0
  57. package/dist/tests/provider.test.js +190 -0
  58. package/dist/tests/runtime-integration.test.d.ts +1 -0
  59. package/dist/tests/runtime-integration.test.js +57 -0
  60. package/dist/tests/web-evidence.test.d.ts +1 -0
  61. package/dist/tests/web-evidence.test.js +89 -0
  62. package/docs/MIGRATION_GUIDE.md +405 -0
  63. package/docs/OPERATIONAL_RUNBOOK.md +389 -0
  64. package/docs/PRODUCTION_READINESS.md +134 -0
  65. package/docs/SLO_THRESHOLDS.md +193 -0
  66. package/examples/README.md +171 -0
  67. package/examples/docker/Dockerfile.test +16 -0
  68. package/examples/docker/README.md +48 -0
  69. package/examples/docker/docker-compose.test.yml +16 -0
  70. package/examples/non-web-evidence-demo.ts +184 -0
  71. package/examples/openclaw-plugin-smoke/index.ts +30 -0
  72. package/examples/openclaw-plugin-smoke/openclaw.plugin.json +11 -0
  73. package/examples/openclaw-plugin-smoke/package.json +9 -0
  74. package/examples/openclaw_integration_example.py +41 -0
  75. package/examples/policy/README.md +165 -0
  76. package/examples/policy/approved-hosts.yaml +137 -0
  77. package/examples/policy/dev-workflow.yaml +206 -0
  78. package/examples/policy/policy.example.yaml +17 -0
  79. package/examples/policy/production-strict.yaml +97 -0
  80. package/examples/policy/sensitive-paths.yaml +114 -0
  81. package/examples/policy/source-trust.yaml +129 -0
  82. package/examples/policy/workspace-isolation.yaml +51 -0
  83. package/examples/runtime_registry_example.py +75 -0
  84. package/package.json +27 -0
  85. package/pyproject.toml +41 -0
  86. package/src/adapter.ts +45 -0
  87. package/src/authority-client.ts +50 -0
  88. package/src/circuit-breaker.ts +245 -0
  89. package/src/config.ts +15 -0
  90. package/src/control-plane-sync.ts +159 -0
  91. package/src/errors.ts +5 -0
  92. package/src/index.ts +12 -0
  93. package/src/non-web-evidence.ts +116 -0
  94. package/src/openclaw-hooks.ts +76 -0
  95. package/src/openclaw-plugin-api.ts +51 -0
  96. package/src/openclaw_predicate_provider/__init__.py +16 -0
  97. package/src/openclaw_predicate_provider/__main__.py +5 -0
  98. package/src/openclaw_predicate_provider/adapter.py +84 -0
  99. package/src/openclaw_predicate_provider/agentidentity_backend.py +78 -0
  100. package/src/openclaw_predicate_provider/cli.py +160 -0
  101. package/src/openclaw_predicate_provider/config.py +42 -0
  102. package/src/openclaw_predicate_provider/errors.py +13 -0
  103. package/src/openclaw_predicate_provider/integrations/__init__.py +5 -0
  104. package/src/openclaw_predicate_provider/integrations/openclaw_runtime.py +74 -0
  105. package/src/openclaw_predicate_provider/models.py +19 -0
  106. package/src/openclaw_predicate_provider/openclaw_hooks.py +75 -0
  107. package/src/openclaw_predicate_provider/provider.py +69 -0
  108. package/src/openclaw_predicate_provider/py.typed +1 -0
  109. package/src/openclaw_predicate_provider/sidecar.py +59 -0
  110. package/src/provider.ts +220 -0
  111. package/src/runtime-integration.ts +68 -0
  112. package/src/web-evidence.ts +95 -0
  113. package/tests/adapter.test.ts +76 -0
  114. package/tests/audit-event-e2e.test.ts +258 -0
  115. package/tests/authority-client.test.ts +52 -0
  116. package/tests/circuit-breaker.test.ts +266 -0
  117. package/tests/conftest.py +9 -0
  118. package/tests/control-plane-sync.test.ts +114 -0
  119. package/tests/hack-vs-fix-demo.test.ts +44 -0
  120. package/tests/jwks-rotation.test.ts +274 -0
  121. package/tests/load-latency.test.ts +214 -0
  122. package/tests/multi-tenant-isolation.test.ts +183 -0
  123. package/tests/non-web-evidence.test.ts +168 -0
  124. package/tests/openclaw-hooks.test.ts +46 -0
  125. package/tests/openclaw-plugin-api.test.ts +50 -0
  126. package/tests/provider.test.ts +227 -0
  127. package/tests/runtime-integration.test.ts +70 -0
  128. package/tests/test_adapter.py +46 -0
  129. package/tests/test_cli.py +26 -0
  130. package/tests/test_openclaw_hooks.py +53 -0
  131. package/tests/test_provider.py +59 -0
  132. package/tests/test_runtime_integration.py +77 -0
  133. package/tests/test_sidecar_client.py +198 -0
  134. package/tests/web-evidence.test.ts +113 -0
  135. package/tsconfig.json +14 -0
  136. package/vitest.config.ts +7 -0
@@ -0,0 +1,405 @@
1
+ # Migration Guide
2
+
3
+ This guide covers migration paths to Predicate Authority from common existing
4
+ security approaches.
5
+
6
+ ## Table of Contents
7
+
8
+ - [From OpenClaw Sandbox](#from-openclaw-sandbox)
9
+ - [From HITL-Only](#from-hitl-only)
10
+ - [From Custom Guardrails](#from-custom-guardrails)
11
+ - [Gradual Rollout Strategy](#gradual-rollout-strategy)
12
+
13
+ ---
14
+
15
+ ## From OpenClaw Sandbox
16
+
17
+ If you're currently using OpenClaw's built-in sandbox for isolation.
18
+
19
+ ### Current State
20
+
21
+ ```
22
+ ┌─────────────────┐ ┌─────────────────┐
23
+ │ OpenClaw Agent │───▶│ Docker/VM │
24
+ │ │ │ Sandbox │
25
+ │ (all actions) │ │ (isolated) │
26
+ └─────────────────┘ └─────────────────┘
27
+ ```
28
+
29
+ **Pros of sandbox:**
30
+ - Host machine is protected
31
+ - Simple to set up
32
+
33
+ **Cons of sandbox:**
34
+ - Agent can still exfiltrate via network
35
+ - Agent can access sandbox credentials
36
+ - No per-action authorization
37
+ - No audit trail of decisions
38
+
39
+ ### Migration Target
40
+
41
+ ```
42
+ ┌─────────────────┐ ┌─────────────────┐ ┌─────────────────┐
43
+ │ OpenClaw Agent │───▶│ GuardedProvider │───▶│ Sandbox │
44
+ │ │ │ (pre-execution │ │ (defense in │
45
+ │ (all actions) │ │ authorization) │ │ depth) │
46
+ └─────────────────┘ └─────────────────┘ └─────────────────┘
47
+ ```
48
+
49
+ ### Migration Steps
50
+
51
+ #### Step 1: Install Predicate Provider
52
+
53
+ ```bash
54
+ npm install openclaw-predicate-provider
55
+ ```
56
+
57
+ #### Step 2: Start in Audit Mode
58
+
59
+ Run Predicate in audit-only mode first to understand what would be blocked:
60
+
61
+ ```typescript
62
+ const provider = new GuardedProvider({
63
+ principal: "agent:my-agent",
64
+ auditOnly: true, // Log decisions but don't enforce
65
+ });
66
+ ```
67
+
68
+ Review logs to identify:
69
+ - What actions are common
70
+ - What sources requests come from
71
+ - Any false positives from default policy
72
+
73
+ #### Step 3: Build Initial Policy
74
+
75
+ Based on audit data, create a policy that matches your sandbox boundaries:
76
+
77
+ ```yaml
78
+ # Match your existing sandbox allowed paths
79
+ rules:
80
+ - id: allow_sandbox_workspace
81
+ effect: allow
82
+ action: fs.*
83
+ resource: /sandbox/workspace/**
84
+
85
+ - id: allow_sandbox_network
86
+ effect: allow
87
+ action: net.http
88
+ resource:
89
+ - "http://localhost:*"
90
+ - "https://api.internal.example.com/*"
91
+ ```
92
+
93
+ #### Step 4: Enable Enforcement
94
+
95
+ Switch from audit-only to enforcing mode:
96
+
97
+ ```typescript
98
+ const provider = new GuardedProvider({
99
+ principal: "agent:my-agent",
100
+ auditOnly: false, // Now enforcing
101
+ });
102
+ ```
103
+
104
+ #### Step 5: Keep Sandbox as Defense in Depth
105
+
106
+ Don't remove the sandbox - it provides blast-radius reduction if policy has gaps.
107
+
108
+ ---
109
+
110
+ ## From HITL-Only
111
+
112
+ If you're currently using human-in-the-loop approval for all sensitive actions.
113
+
114
+ ### Current State
115
+
116
+ ```
117
+ ┌─────────────────┐ ┌─────────────────┐ ┌─────────────────┐
118
+ │ OpenClaw Agent │───▶│ HITL Queue │───▶│ Execution │
119
+ │ │ │ │ │ │
120
+ │ "run command" │ │ [APPROVE?] │ │ (after human) │
121
+ └─────────────────┘ └─────────────────┘ └─────────────────┘
122
+ ```
123
+
124
+ **Pros of HITL:**
125
+ - Maximum control
126
+ - Human judgment for edge cases
127
+
128
+ **Cons of HITL:**
129
+ - Slow (latency in minutes)
130
+ - Doesn't scale
131
+ - Human fatigue leads to rubber-stamping
132
+ - Blocks agent autonomy
133
+
134
+ ### Migration Target
135
+
136
+ ```
137
+ ┌─────────────────┐
138
+ ┌───▶│ Fast Auto-Allow │ (common patterns)
139
+ │ └─────────────────┘
140
+ ┌─────────────────┐ ┌───┴───────────────┐
141
+ │ OpenClaw Agent │───▶│ GuardedProvider │
142
+ │ │ │ (policy-based) │
143
+ └─────────────────┘ └───┬───────────────┘
144
+ │ ┌─────────────────┐
145
+ └───▶│ HITL for Edge │ (exceptional cases)
146
+ └─────────────────┘
147
+ ```
148
+
149
+ ### Migration Steps
150
+
151
+ #### Step 1: Analyze HITL Logs
152
+
153
+ Export your HITL approval logs and categorize:
154
+
155
+ | Category | Volume | Outcome |
156
+ |----------|--------|---------|
157
+ | Read workspace files | 85% | Always approved |
158
+ | Run git/npm commands | 10% | Always approved |
159
+ | External HTTP | 3% | Sometimes denied |
160
+ | Shell with flags | 2% | Careful review |
161
+
162
+ #### Step 2: Automate the 95%
163
+
164
+ Create policy rules for actions that are always approved:
165
+
166
+ ```yaml
167
+ rules:
168
+ # These were always approved - automate them
169
+ - id: auto_approve_workspace_reads
170
+ effect: allow
171
+ action: fs.read
172
+ resource: ./workspace/**
173
+
174
+ - id: auto_approve_git
175
+ effect: allow
176
+ action: shell.execute
177
+ resource: "git *"
178
+
179
+ - id: auto_approve_npm
180
+ effect: allow
181
+ action: shell.execute
182
+ resource: "npm *"
183
+ ```
184
+
185
+ #### Step 3: Keep HITL for Exceptions
186
+
187
+ Configure escalation for uncertain cases:
188
+
189
+ ```typescript
190
+ const provider = new GuardedProvider({
191
+ principal: "agent:my-agent",
192
+ escalation: {
193
+ onDeny: async (request, reason) => {
194
+ // Route to HITL queue for manual review
195
+ if (reason === "requires_review") {
196
+ return await hitlQueue.enqueue(request);
197
+ }
198
+ throw new ActionDeniedError(reason);
199
+ },
200
+ },
201
+ });
202
+ ```
203
+
204
+ #### Step 4: Measure and Iterate
205
+
206
+ Track metrics:
207
+ - HITL queue reduction (target: 90%+ auto-handled)
208
+ - False positive rate (auto-denied that should have been allowed)
209
+ - False negative rate (auto-allowed that should have been denied)
210
+
211
+ Adjust policy based on data.
212
+
213
+ ---
214
+
215
+ ## From Custom Guardrails
216
+
217
+ If you've built custom authorization logic (regex checks, allowlists, etc.).
218
+
219
+ ### Current State
220
+
221
+ ```typescript
222
+ // Typical custom guardrail code
223
+ async function guardedExecute(command: string) {
224
+ // Check against blocklist
225
+ if (DANGEROUS_PATTERNS.some(p => command.match(p))) {
226
+ throw new Error("Blocked by guardrail");
227
+ }
228
+
229
+ // Check against allowlist
230
+ if (!ALLOWED_COMMANDS.some(c => command.startsWith(c))) {
231
+ throw new Error("Not in allowlist");
232
+ }
233
+
234
+ return execute(command);
235
+ }
236
+ ```
237
+
238
+ **Problems with custom guardrails:**
239
+ - Regex is error-prone (bypasses are common)
240
+ - Hard to audit and maintain
241
+ - No centralized policy management
242
+ - No telemetry or compliance trail
243
+
244
+ ### Migration Steps
245
+
246
+ #### Step 1: Document Existing Rules
247
+
248
+ Extract your custom rules into a structured format:
249
+
250
+ | Rule Type | Pattern | Intent |
251
+ |-----------|---------|--------|
252
+ | Block | `rm -rf` | Prevent destructive ops |
253
+ | Block | `curl.*\|.*bash` | Prevent remote exec |
254
+ | Allow | `git *` | Version control |
255
+ | Allow | `npm *` | Package management |
256
+
257
+ #### Step 2: Convert to Policy YAML
258
+
259
+ ```yaml
260
+ rules:
261
+ # Converted from DANGEROUS_PATTERNS
262
+ - id: deny_rm_rf
263
+ effect: deny
264
+ action: shell.execute
265
+ resource: "rm -rf *"
266
+
267
+ - id: deny_curl_bash
268
+ effect: deny
269
+ action: shell.execute
270
+ resource: "curl * | bash*"
271
+
272
+ # Converted from ALLOWED_COMMANDS
273
+ - id: allow_git
274
+ effect: allow
275
+ action: shell.execute
276
+ resource: "git *"
277
+
278
+ - id: allow_npm
279
+ effect: allow
280
+ action: shell.execute
281
+ resource: "npm *"
282
+ ```
283
+
284
+ #### Step 3: Run Side-by-Side
285
+
286
+ Test Predicate policy against your existing guardrails:
287
+
288
+ ```typescript
289
+ async function validateMigration(request) {
290
+ const customResult = await customGuardrail(request);
291
+ const predicateResult = await provider.authorize(request);
292
+
293
+ if (customResult !== predicateResult) {
294
+ console.warn("Mismatch:", { request, customResult, predicateResult });
295
+ }
296
+ }
297
+ ```
298
+
299
+ Fix any mismatches before switching over.
300
+
301
+ #### Step 4: Switch and Remove Custom Code
302
+
303
+ Once validated, remove custom guardrail code and rely on Predicate.
304
+
305
+ ---
306
+
307
+ ## Gradual Rollout Strategy
308
+
309
+ For production systems, use a phased approach.
310
+
311
+ ### Phase 1: Shadow Mode (Week 1-2)
312
+
313
+ ```typescript
314
+ const provider = new GuardedProvider({
315
+ mode: "shadow", // Log only, no enforcement
316
+ });
317
+ ```
318
+
319
+ - Collect baseline data
320
+ - Identify common patterns
321
+ - Build initial policy
322
+
323
+ ### Phase 2: Soft Enforcement (Week 3-4)
324
+
325
+ ```typescript
326
+ const provider = new GuardedProvider({
327
+ mode: "soft", // Enforce but allow override
328
+ onDeny: async (request) => {
329
+ // Log and allow with warning
330
+ console.warn("Would deny:", request);
331
+ return { allow: true, warning: true };
332
+ },
333
+ });
334
+ ```
335
+
336
+ - Start enforcing but allow overrides
337
+ - Track would-be denials
338
+ - Tune policy to reduce false positives
339
+
340
+ ### Phase 3: Full Enforcement (Week 5+)
341
+
342
+ ```typescript
343
+ const provider = new GuardedProvider({
344
+ mode: "enforce", // Full enforcement
345
+ });
346
+ ```
347
+
348
+ - Full enforcement
349
+ - HITL escalation for edge cases
350
+ - Continuous monitoring
351
+
352
+ ### Rollback Plan
353
+
354
+ Keep ability to disable quickly:
355
+
356
+ ```typescript
357
+ const provider = new GuardedProvider({
358
+ enabled: process.env.PREDICATE_ENABLED !== "false",
359
+ });
360
+ ```
361
+
362
+ ```bash
363
+ # Emergency disable
364
+ export PREDICATE_ENABLED=false
365
+ systemctl restart openclaw-agent
366
+ ```
367
+
368
+ ---
369
+
370
+ ## Common Migration Issues
371
+
372
+ ### Issue: Too Many False Positives
373
+
374
+ **Symptom:** Legitimate actions being blocked
375
+
376
+ **Solution:**
377
+ 1. Check audit logs for deny reasons
378
+ 2. Add allow rules for legitimate patterns
379
+ 3. Consider source-based trust levels
380
+
381
+ ### Issue: Performance Impact
382
+
383
+ **Symptom:** Increased latency on tool calls
384
+
385
+ **Solution:**
386
+ 1. Check sidecar is running locally (not remote)
387
+ 2. Review p50/p95 latency metrics
388
+ 3. Consider increasing timeout if network is slow
389
+
390
+ ### Issue: Missing Context
391
+
392
+ **Symptom:** Decisions made without full context
393
+
394
+ **Solution:**
395
+ 1. Ensure OpenClaw passes source labels
396
+ 2. Add session_id and tenant_id propagation
397
+ 3. Review context extraction in hooks
398
+
399
+ ---
400
+
401
+ ## Getting Help
402
+
403
+ - Check [docs/OPERATIONAL_RUNBOOK.md](OPERATIONAL_RUNBOOK.md) for troubleshooting
404
+ - Review [examples/policy/](../examples/policy/) for policy templates
405
+ - File issues at https://github.com/PredicateSystems/openclaw-predicate-provider