protect-mcp 0.9.6 → 0.9.7

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
@@ -57,6 +57,36 @@ The dashboard binds to `127.0.0.1`, reads only local log/receipt files, and does
57
57
  not upload anything. Use `npx protect-mcp connect` only if you explicitly want a
58
58
  hosted ScopeBlind dashboard.
59
59
 
60
+ ## The gate as an MCP server
61
+
62
+ If you would rather call the gate as tools than wire the Claude Code hooks, run
63
+ it as an MCP server:
64
+
65
+ ```bash
66
+ npx protect-mcp mcp
67
+ ```
68
+
69
+ It speaks MCP over stdio and exposes four read-only tools, the whole loop:
70
+
71
+ - **`evaluate_action`**: decide a proposed tool call against an inline Cedar policy, fail-closed (any policy error is DENY). Returns `{ allowed, decision, reason, policy_digest }`.
72
+ - **`sign_decision`**: turn a decision into an Ed25519 signed receipt (a denial signs a `gateway_restraint`, an allow a `decision_receipt`). Returns the receipt and its public key; generates an ephemeral key if you do not supply one.
73
+ - **`verify_receipt`**: verify a signed receipt offline against a public key. Returns `{ valid, error, type, kid, issuer }`.
74
+ - **`self_test`**: prove it, no inputs. A known-forbidden action is denied, then a signed receipt round-trips and a tampered copy fails.
75
+
76
+ Point any MCP host at it, for example Claude Desktop:
77
+
78
+ ```json
79
+ {
80
+ "mcpServers": {
81
+ "protect-mcp": { "command": "npx", "args": ["-y", "protect-mcp", "mcp"] }
82
+ }
83
+ }
84
+ ```
85
+
86
+ Receipts are byte-compatible with the ones the gate signs at runtime, so a
87
+ receipt minted here verifies with [`@veritasacta/verify`](https://www.npmjs.com/package/@veritasacta/verify)
88
+ and the browser verifier just the same.
89
+
60
90
  ### Local Action Dashboard
61
91
 
62
92
  `protect-mcp dashboard` is the operator view for moving from visibility to
@@ -5,17 +5,19 @@ import {
5
5
  ReceiptBuffer,
6
6
  buildActionReadback,
7
7
  checkRateLimit,
8
- evaluateCedar,
9
8
  getSignerInfo,
10
9
  getToolPolicy,
11
10
  initSigning,
12
- isCedarAvailable,
13
11
  isSigningEnabled,
14
- loadCedarPolicies,
15
12
  loadPolicy,
16
13
  parseRateLimit,
17
14
  signDecision
18
- } from "./chunk-XLJUZ4WO.mjs";
15
+ } from "./chunk-G6X763MH.mjs";
16
+ import {
17
+ evaluateCedar,
18
+ isCedarAvailable,
19
+ loadCedarPolicies
20
+ } from "./chunk-MWXDXYWH.mjs";
19
21
 
20
22
  // src/hook-server.ts
21
23
  import { createServer } from "http";
@@ -236,213 +236,10 @@ function isSigningEnabled() {
236
236
  return signingConfigured && signingInitError === null && signerState !== null && artifactsModule !== null;
237
237
  }
238
238
 
239
- // src/cedar-evaluator.ts
240
- import { createHash as createHash2 } from "crypto";
241
- import { readFileSync as readFileSync3, readdirSync, existsSync as existsSync2 } from "fs";
242
- import { join, extname } from "path";
243
- var cedarWasm = null;
244
- var loadAttempted = false;
245
- async function ensureCedarWasm() {
246
- if (cedarWasm) return true;
247
- if (loadAttempted) return false;
248
- loadAttempted = true;
249
- try {
250
- const moduleName = "@cedar-policy/cedar-wasm";
251
- cedarWasm = await import(
252
- /* @vite-ignore */
253
- moduleName
254
- );
255
- return true;
256
- } catch {
257
- return false;
258
- }
259
- }
260
- function loadCedarPolicies(dirPath) {
261
- if (!existsSync2(dirPath)) {
262
- throw new Error(`Cedar policy directory not found: ${dirPath}`);
263
- }
264
- const entries = readdirSync(dirPath).filter((f) => extname(f) === ".cedar").sort();
265
- if (entries.length === 0) {
266
- throw new Error(`No .cedar files found in: ${dirPath}`);
267
- }
268
- const sources = [];
269
- for (const file of entries) {
270
- const content = readFileSync3(join(dirPath, file), "utf-8");
271
- sources.push(content);
272
- }
273
- const concatenated = sources.join("\n\n");
274
- const digest = createHash2("sha256").update(concatenated).digest("hex").slice(0, 16);
275
- return {
276
- source: concatenated,
277
- digest,
278
- fileCount: entries.length,
279
- files: entries
280
- };
281
- }
282
- function buildEntities(req) {
283
- const agentId = req.agentId || req.tier;
284
- return [
285
- {
286
- uid: { type: "Agent", id: agentId },
287
- attrs: {
288
- tier: req.tier,
289
- ...req.agentId ? { agent_id: req.agentId } : {}
290
- },
291
- parents: []
292
- },
293
- {
294
- uid: { type: "Tool", id: req.tool },
295
- attrs: {},
296
- parents: []
297
- }
298
- ];
299
- }
300
- function onEvalError(reason, failClosed, extra) {
301
- return {
302
- allowed: !failClosed,
303
- reason: failClosed ? reason : `${reason} (observe mode; would DENY under enforcement)`,
304
- metadata: { error: true, fail_closed: failClosed, would_deny: true, ...extra || {} }
305
- };
306
- }
307
- async function evaluateCedar(policySet, req, schema, options) {
308
- const failClosed = options?.failClosed ?? true;
309
- const available = await ensureCedarWasm();
310
- if (!available) {
311
- return onEvalError("cedar_wasm_not_available", failClosed, { fallback: true });
312
- }
313
- try {
314
- const agentId = req.agentId || req.tier;
315
- const context = {
316
- tier: req.tier,
317
- ...req.context || {}
318
- };
319
- if (req.toolInput && Object.keys(req.toolInput).length > 0) {
320
- context.input = req.toolInput;
321
- }
322
- const authRequest = {
323
- principal: { type: "Agent", id: agentId },
324
- action: { type: "Action", id: "MCP::Tool::call" },
325
- resource: { type: "Tool", id: req.tool },
326
- context
327
- };
328
- const entities = buildEntities(req);
329
- const cedarSchema = schema?.schemaJson ?? null;
330
- let result;
331
- if (typeof cedarWasm.isAuthorized === "function") {
332
- result = cedarWasm.isAuthorized({
333
- policies: { staticPolicies: policySet.source },
334
- entities,
335
- principal: authRequest.principal,
336
- action: authRequest.action,
337
- resource: authRequest.resource,
338
- context: authRequest.context,
339
- schema: cedarSchema
340
- });
341
- } else if (typeof cedarWasm.checkAuthorization === "function") {
342
- result = cedarWasm.checkAuthorization(
343
- policySet.source,
344
- JSON.stringify(entities),
345
- JSON.stringify(authRequest)
346
- );
347
- } else {
348
- const cedarEngine = cedarWasm.default || cedarWasm;
349
- if (typeof cedarEngine.isAuthorized === "function") {
350
- result = cedarEngine.isAuthorized({
351
- policies: { staticPolicies: policySet.source },
352
- entities,
353
- principal: authRequest.principal,
354
- action: authRequest.action,
355
- resource: authRequest.resource,
356
- context: authRequest.context,
357
- schema: cedarSchema
358
- });
359
- } else {
360
- return onEvalError("cedar_wasm_api_unsupported", failClosed, { exports: Object.keys(cedarWasm) });
361
- }
362
- }
363
- const parsed = parseWasmResult(result);
364
- const policyErrors = extractPolicyErrors(result);
365
- if (parsed.kind === "error") {
366
- return onEvalError(`cedar_unparseable_result: ${parsed.diagnostics}`, failClosed);
367
- }
368
- if (policyErrors.length > 0) {
369
- return onEvalError(
370
- `cedar_policy_errored: ${policyErrors.length} policy error(s); decision is unsound`,
371
- failClosed,
372
- { policy_errors: policyErrors.slice(0, 5), policy_digest: policySet.digest }
373
- );
374
- }
375
- return {
376
- allowed: parsed.kind === "allow",
377
- reason: parsed.kind === "allow" ? void 0 : `cedar_deny${parsed.diagnostics ? ": " + parsed.diagnostics : ""}`,
378
- metadata: {
379
- policy_digest: policySet.digest,
380
- ...parsed.matchedPolicies ? { matched_policies: parsed.matchedPolicies } : {}
381
- }
382
- };
383
- } catch (err) {
384
- return onEvalError(`cedar_eval_error: ${err instanceof Error ? err.message : "unknown"}`, failClosed);
385
- }
386
- }
387
- function parseWasmResult(result) {
388
- if (!result) return { kind: "error", diagnostics: "null result from Cedar WASM" };
389
- if (result.type === "failure") {
390
- return { kind: "error", diagnostics: `cedar failure: ${JSON.stringify(result.errors ?? [])}` };
391
- }
392
- if (result.type === "success" && result.response) {
393
- const dec = result.response.decision;
394
- const reasons = result.response.diagnostics?.reason;
395
- if (dec === "allow" || dec === "Allow") return { kind: "allow", matchedPolicies: reasons };
396
- if (dec === "deny" || dec === "Deny") {
397
- return { kind: "deny", diagnostics: result.response.diagnostics ? JSON.stringify(result.response.diagnostics) : void 0, matchedPolicies: reasons };
398
- }
399
- }
400
- if (result.type === "allow" || result.decision === "Allow") return { kind: "allow" };
401
- if (result.type === "deny" || result.decision === "Deny") return { kind: "deny" };
402
- if (typeof result === "boolean") return result ? { kind: "allow" } : { kind: "deny" };
403
- return { kind: "error", diagnostics: `unknown result format: ${JSON.stringify(result)}` };
404
- }
405
- function extractPolicyErrors(result) {
406
- if (!result || typeof result !== "object") return [];
407
- const raw = result.errors ?? result.response?.diagnostics?.errors ?? result.diagnostics?.errors ?? [];
408
- if (!Array.isArray(raw)) return [];
409
- return raw.map((e) => typeof e === "string" ? e : e?.message ?? e?.error ?? JSON.stringify(e)).filter(Boolean);
410
- }
411
- async function isCedarAvailable() {
412
- return ensureCedarWasm();
413
- }
414
- function policySetFromSource(source, name = "inline") {
415
- const digest = createHash2("sha256").update(source).digest("hex").slice(0, 16);
416
- return { source, digest, fileCount: 1, files: [name] };
417
- }
418
- async function runEvaluatorSelfTest() {
419
- const wasmAvailable = await isCedarAvailable();
420
- const cases = [];
421
- const run = async (name, expected, policy, context) => {
422
- const d = await evaluateCedar(policy, { tool: "Bash", tier: "unknown", context }, void 0, { failClosed: true });
423
- const actual = d.allowed ? "ALLOW" : "DENY";
424
- cases.push({ name, expected, actual, pass: actual === expected, reason: d.reason });
425
- };
426
- if (!wasmAvailable) {
427
- await run("engine unavailable denies", "DENY", policySetFromSource("permit(principal, action, resource);"), {});
428
- return { wasmAvailable, passed: cases.every((c) => c.pass), cases };
429
- }
430
- const correct = policySetFromSource(
431
- 'forbid(principal, action, resource) when { ["rm", "dd", "mkfs"].contains(context.command) };\npermit(principal, action, resource);'
432
- );
433
- await run("forbid denies rm", "DENY", correct, { command: "rm" });
434
- await run("permit allows ls", "ALLOW", correct, { command: "ls" });
435
- const broken = policySetFromSource(
436
- 'forbid(principal, action, resource) when { context.command in ["rm", "dd"] };\npermit(principal, action, resource);'
437
- );
438
- await run("in-on-String forbid does not permit-all", "DENY", broken, { command: "rm" });
439
- return { wasmAvailable, passed: cases.every((c) => c.pass), cases };
440
- }
441
-
442
239
  // src/http-server.ts
443
240
  import { createServer } from "http";
444
- import { readFileSync as readFileSync4, existsSync as existsSync3 } from "fs";
445
- import { join as join2 } from "path";
241
+ import { readFileSync as readFileSync3, existsSync as existsSync2 } from "fs";
242
+ import { join } from "path";
446
243
  var LOG_FILE = ".protect-mcp-log.jsonl";
447
244
  var MAX_RECEIPTS = 100;
448
245
  var ReceiptBuffer = class {
@@ -535,13 +332,13 @@ function handleHealth(res, startTime, config) {
535
332
  }));
536
333
  }
537
334
  function handleStatus(res, logDir) {
538
- const logPath = join2(logDir, LOG_FILE);
539
- if (!existsSync3(logPath)) {
335
+ const logPath = join(logDir, LOG_FILE);
336
+ if (!existsSync2(logPath)) {
540
337
  res.writeHead(200);
541
338
  res.end(JSON.stringify({ entries: 0, message: "no log file yet" }));
542
339
  return;
543
340
  }
544
- const raw = readFileSync4(logPath, "utf-8");
341
+ const raw = readFileSync3(logPath, "utf-8");
545
342
  const lines = raw.trim().split("\n").filter(Boolean);
546
343
  const entries = [];
547
344
  for (const line of lines) {
@@ -665,7 +462,7 @@ function handleListApprovals(res, approvalStore) {
665
462
  }
666
463
 
667
464
  // src/action-readback.ts
668
- import { createHash as createHash3 } from "crypto";
465
+ import { createHash as createHash2 } from "crypto";
669
466
  var SECRET_KEY_RE = /(api[_-]?key|authorization|bearer|credential|password|secret|session|token|private[_-]?key)/i;
670
467
  var DESTINATION_KEYS = [
671
468
  "path",
@@ -745,7 +542,7 @@ function buildActionReadback(tool, input) {
745
542
  action,
746
543
  destination,
747
544
  payload_preview: payloadPreview,
748
- payload_hash: createHash3("sha256").update(canonical).digest("hex"),
545
+ payload_hash: createHash2("sha256").update(canonical).digest("hex"),
749
546
  payload_bytes: Buffer.byteLength(canonical, "utf-8"),
750
547
  disclosed_fields: [...new Set(disclosedFields)].slice(0, 80),
751
548
  redacted_fields: [...new Set(redactedFields)].slice(0, 80),
@@ -762,11 +559,6 @@ export {
762
559
  signDecision,
763
560
  getSignerInfo,
764
561
  isSigningEnabled,
765
- loadCedarPolicies,
766
- evaluateCedar,
767
- isCedarAvailable,
768
- policySetFromSource,
769
- runEvaluatorSelfTest,
770
562
  ReceiptBuffer,
771
563
  startStatusServer,
772
564
  buildActionReadback
@@ -1,11 +1,11 @@
1
1
  import {
2
2
  meetsMinTier
3
- } from "./chunk-PB3TC7E3.mjs";
3
+ } from "./chunk-YM6SOJBR.mjs";
4
4
  import {
5
5
  checkRateLimit,
6
6
  getToolPolicy,
7
7
  parseRateLimit
8
- } from "./chunk-XLJUZ4WO.mjs";
8
+ } from "./chunk-G6X763MH.mjs";
9
9
 
10
10
  // src/simulate.ts
11
11
  import { readFileSync } from "fs";
@@ -0,0 +1,210 @@
1
+ // src/cedar-evaluator.ts
2
+ import { createHash } from "crypto";
3
+ import { readFileSync, readdirSync, existsSync } from "fs";
4
+ import { join, extname } from "path";
5
+ var cedarWasm = null;
6
+ var loadAttempted = false;
7
+ async function ensureCedarWasm() {
8
+ if (cedarWasm) return true;
9
+ if (loadAttempted) return false;
10
+ loadAttempted = true;
11
+ try {
12
+ const moduleName = "@cedar-policy/cedar-wasm";
13
+ cedarWasm = await import(
14
+ /* @vite-ignore */
15
+ moduleName
16
+ );
17
+ return true;
18
+ } catch {
19
+ return false;
20
+ }
21
+ }
22
+ function loadCedarPolicies(dirPath) {
23
+ if (!existsSync(dirPath)) {
24
+ throw new Error(`Cedar policy directory not found: ${dirPath}`);
25
+ }
26
+ const entries = readdirSync(dirPath).filter((f) => extname(f) === ".cedar").sort();
27
+ if (entries.length === 0) {
28
+ throw new Error(`No .cedar files found in: ${dirPath}`);
29
+ }
30
+ const sources = [];
31
+ for (const file of entries) {
32
+ const content = readFileSync(join(dirPath, file), "utf-8");
33
+ sources.push(content);
34
+ }
35
+ const concatenated = sources.join("\n\n");
36
+ const digest = createHash("sha256").update(concatenated).digest("hex").slice(0, 16);
37
+ return {
38
+ source: concatenated,
39
+ digest,
40
+ fileCount: entries.length,
41
+ files: entries
42
+ };
43
+ }
44
+ function buildEntities(req) {
45
+ const agentId = req.agentId || req.tier;
46
+ return [
47
+ {
48
+ uid: { type: "Agent", id: agentId },
49
+ attrs: {
50
+ tier: req.tier,
51
+ ...req.agentId ? { agent_id: req.agentId } : {}
52
+ },
53
+ parents: []
54
+ },
55
+ {
56
+ uid: { type: "Tool", id: req.tool },
57
+ attrs: {},
58
+ parents: []
59
+ }
60
+ ];
61
+ }
62
+ function onEvalError(reason, failClosed, extra) {
63
+ return {
64
+ allowed: !failClosed,
65
+ reason: failClosed ? reason : `${reason} (observe mode; would DENY under enforcement)`,
66
+ metadata: { error: true, fail_closed: failClosed, would_deny: true, ...extra || {} }
67
+ };
68
+ }
69
+ async function evaluateCedar(policySet, req, schema, options) {
70
+ const failClosed = options?.failClosed ?? true;
71
+ const available = await ensureCedarWasm();
72
+ if (!available) {
73
+ return onEvalError("cedar_wasm_not_available", failClosed, { fallback: true });
74
+ }
75
+ try {
76
+ const agentId = req.agentId || req.tier;
77
+ const context = {
78
+ tier: req.tier,
79
+ ...req.context || {}
80
+ };
81
+ if (req.toolInput && Object.keys(req.toolInput).length > 0) {
82
+ context.input = req.toolInput;
83
+ }
84
+ const authRequest = {
85
+ principal: { type: "Agent", id: agentId },
86
+ action: { type: "Action", id: "MCP::Tool::call" },
87
+ resource: { type: "Tool", id: req.tool },
88
+ context
89
+ };
90
+ const entities = buildEntities(req);
91
+ const cedarSchema = schema?.schemaJson ?? null;
92
+ let result;
93
+ if (typeof cedarWasm.isAuthorized === "function") {
94
+ result = cedarWasm.isAuthorized({
95
+ policies: { staticPolicies: policySet.source },
96
+ entities,
97
+ principal: authRequest.principal,
98
+ action: authRequest.action,
99
+ resource: authRequest.resource,
100
+ context: authRequest.context,
101
+ schema: cedarSchema
102
+ });
103
+ } else if (typeof cedarWasm.checkAuthorization === "function") {
104
+ result = cedarWasm.checkAuthorization(
105
+ policySet.source,
106
+ JSON.stringify(entities),
107
+ JSON.stringify(authRequest)
108
+ );
109
+ } else {
110
+ const cedarEngine = cedarWasm.default || cedarWasm;
111
+ if (typeof cedarEngine.isAuthorized === "function") {
112
+ result = cedarEngine.isAuthorized({
113
+ policies: { staticPolicies: policySet.source },
114
+ entities,
115
+ principal: authRequest.principal,
116
+ action: authRequest.action,
117
+ resource: authRequest.resource,
118
+ context: authRequest.context,
119
+ schema: cedarSchema
120
+ });
121
+ } else {
122
+ return onEvalError("cedar_wasm_api_unsupported", failClosed, { exports: Object.keys(cedarWasm) });
123
+ }
124
+ }
125
+ const parsed = parseWasmResult(result);
126
+ const policyErrors = extractPolicyErrors(result);
127
+ if (parsed.kind === "error") {
128
+ return onEvalError(`cedar_unparseable_result: ${parsed.diagnostics}`, failClosed);
129
+ }
130
+ if (policyErrors.length > 0) {
131
+ return onEvalError(
132
+ `cedar_policy_errored: ${policyErrors.length} policy error(s); decision is unsound`,
133
+ failClosed,
134
+ { policy_errors: policyErrors.slice(0, 5), policy_digest: policySet.digest }
135
+ );
136
+ }
137
+ return {
138
+ allowed: parsed.kind === "allow",
139
+ reason: parsed.kind === "allow" ? void 0 : `cedar_deny${parsed.diagnostics ? ": " + parsed.diagnostics : ""}`,
140
+ metadata: {
141
+ policy_digest: policySet.digest,
142
+ ...parsed.matchedPolicies ? { matched_policies: parsed.matchedPolicies } : {}
143
+ }
144
+ };
145
+ } catch (err) {
146
+ return onEvalError(`cedar_eval_error: ${err instanceof Error ? err.message : "unknown"}`, failClosed);
147
+ }
148
+ }
149
+ function parseWasmResult(result) {
150
+ if (!result) return { kind: "error", diagnostics: "null result from Cedar WASM" };
151
+ if (result.type === "failure") {
152
+ return { kind: "error", diagnostics: `cedar failure: ${JSON.stringify(result.errors ?? [])}` };
153
+ }
154
+ if (result.type === "success" && result.response) {
155
+ const dec = result.response.decision;
156
+ const reasons = result.response.diagnostics?.reason;
157
+ if (dec === "allow" || dec === "Allow") return { kind: "allow", matchedPolicies: reasons };
158
+ if (dec === "deny" || dec === "Deny") {
159
+ return { kind: "deny", diagnostics: result.response.diagnostics ? JSON.stringify(result.response.diagnostics) : void 0, matchedPolicies: reasons };
160
+ }
161
+ }
162
+ if (result.type === "allow" || result.decision === "Allow") return { kind: "allow" };
163
+ if (result.type === "deny" || result.decision === "Deny") return { kind: "deny" };
164
+ if (typeof result === "boolean") return result ? { kind: "allow" } : { kind: "deny" };
165
+ return { kind: "error", diagnostics: `unknown result format: ${JSON.stringify(result)}` };
166
+ }
167
+ function extractPolicyErrors(result) {
168
+ if (!result || typeof result !== "object") return [];
169
+ const raw = result.errors ?? result.response?.diagnostics?.errors ?? result.diagnostics?.errors ?? [];
170
+ if (!Array.isArray(raw)) return [];
171
+ return raw.map((e) => typeof e === "string" ? e : e?.message ?? e?.error ?? JSON.stringify(e)).filter(Boolean);
172
+ }
173
+ async function isCedarAvailable() {
174
+ return ensureCedarWasm();
175
+ }
176
+ function policySetFromSource(source, name = "inline") {
177
+ const digest = createHash("sha256").update(source).digest("hex").slice(0, 16);
178
+ return { source, digest, fileCount: 1, files: [name] };
179
+ }
180
+ async function runEvaluatorSelfTest() {
181
+ const wasmAvailable = await isCedarAvailable();
182
+ const cases = [];
183
+ const run = async (name, expected, policy, context) => {
184
+ const d = await evaluateCedar(policy, { tool: "Bash", tier: "unknown", context }, void 0, { failClosed: true });
185
+ const actual = d.allowed ? "ALLOW" : "DENY";
186
+ cases.push({ name, expected, actual, pass: actual === expected, reason: d.reason });
187
+ };
188
+ if (!wasmAvailable) {
189
+ await run("engine unavailable denies", "DENY", policySetFromSource("permit(principal, action, resource);"), {});
190
+ return { wasmAvailable, passed: cases.every((c) => c.pass), cases };
191
+ }
192
+ const correct = policySetFromSource(
193
+ 'forbid(principal, action, resource) when { ["rm", "dd", "mkfs"].contains(context.command) };\npermit(principal, action, resource);'
194
+ );
195
+ await run("forbid denies rm", "DENY", correct, { command: "rm" });
196
+ await run("permit allows ls", "ALLOW", correct, { command: "ls" });
197
+ const broken = policySetFromSource(
198
+ 'forbid(principal, action, resource) when { context.command in ["rm", "dd"] };\npermit(principal, action, resource);'
199
+ );
200
+ await run("in-on-String forbid does not permit-all", "DENY", broken, { command: "rm" });
201
+ return { wasmAvailable, passed: cases.every((c) => c.pass), cases };
202
+ }
203
+
204
+ export {
205
+ loadCedarPolicies,
206
+ evaluateCedar,
207
+ isCedarAvailable,
208
+ policySetFromSource,
209
+ runEvaluatorSelfTest
210
+ };
@@ -2,13 +2,15 @@ import {
2
2
  ReceiptBuffer,
3
3
  buildActionReadback,
4
4
  checkRateLimit,
5
- evaluateCedar,
6
5
  getToolPolicy,
7
6
  isSigningEnabled,
8
7
  parseRateLimit,
9
8
  signDecision,
10
9
  startStatusServer
11
- } from "./chunk-XLJUZ4WO.mjs";
10
+ } from "./chunk-G6X763MH.mjs";
11
+ import {
12
+ evaluateCedar
13
+ } from "./chunk-MWXDXYWH.mjs";
12
14
 
13
15
  // src/evidence-store.ts
14
16
  import { readFileSync, writeFileSync, existsSync } from "fs";