protect-mcp 0.6.2 → 0.7.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/dist/cli.mjs CHANGED
@@ -3,20 +3,26 @@ import {
3
3
  formatSimulation,
4
4
  parseLogFile,
5
5
  simulate
6
- } from "./chunk-S4ICHNSP.mjs";
6
+ } from "./chunk-ZBKJANP7.mjs";
7
7
  import {
8
8
  ProtectGateway,
9
9
  validateCredentials
10
- } from "./chunk-PLKRTBDR.mjs";
10
+ } from "./chunk-OHUTUFTC.mjs";
11
11
  import {
12
+ evaluateCedar,
12
13
  initSigning,
13
14
  isCedarAvailable,
14
15
  loadCedarPolicies,
15
- loadPolicy
16
- } from "./chunk-UV53U6D4.mjs";
16
+ loadPolicy,
17
+ policySetFromSource,
18
+ runEvaluatorSelfTest,
19
+ signDecision
20
+ } from "./chunk-546U3A7R.mjs";
17
21
  import "./chunk-PQJP2ZCI.mjs";
18
22
 
19
23
  // src/cli.ts
24
+ import { readFileSync as readFileSyncCli, existsSync as existsSyncCli, appendFileSync as appendFileSyncCli, mkdirSync as mkdirSyncCli } from "fs";
25
+ import { basename as basenameCli, join as joinCli } from "path";
20
26
  function printHelp() {
21
27
  process.stderr.write(`
22
28
  protect-mcp \u2014 Enterprise security gateway for MCP servers & Claude Code hooks
@@ -49,6 +55,8 @@ Options:
49
55
 
50
56
  Commands:
51
57
  serve Start HTTP hook server for Claude Code integration (port 9377)
58
+ evaluate Evaluate one tool call against a Cedar policy (PreToolUse gate; exit 2 = deny, fail-closed)
59
+ sign Sign one tool call into a receipt (PostToolUse)
52
60
  init-hooks Generate Claude Code hook config + skill + sample Cedar policy
53
61
  quickstart Zero-config onboarding: init + demo + show receipts in one command
54
62
  connect Create a ScopeBlind sandbox dashboard and configure receipt upload
@@ -1273,6 +1281,88 @@ async function sendInstallTelemetry() {
1273
1281
  } catch {
1274
1282
  }
1275
1283
  }
1284
+ function flagValue(argv, name) {
1285
+ const i = argv.indexOf(name);
1286
+ return i >= 0 && argv[i + 1] ? argv[i + 1] : void 0;
1287
+ }
1288
+ function loadPolicyArg(argv) {
1289
+ const cedarDir = flagValue(argv, "--cedar");
1290
+ const policyFile = flagValue(argv, "--policy");
1291
+ try {
1292
+ if (cedarDir) return loadCedarPolicies(cedarDir);
1293
+ if (policyFile && existsSyncCli(policyFile)) {
1294
+ return policySetFromSource(readFileSyncCli(policyFile, "utf-8"), basenameCli(policyFile));
1295
+ }
1296
+ } catch {
1297
+ }
1298
+ return null;
1299
+ }
1300
+ async function handleEvaluate(argv) {
1301
+ const tool = flagValue(argv, "--tool") || "";
1302
+ const inputRaw = flagValue(argv, "--input") || "{}";
1303
+ const contextRaw = flagValue(argv, "--context");
1304
+ const failOnMissing = flagValue(argv, "--fail-on-missing-policy") !== "false";
1305
+ const policySet = loadPolicyArg(argv);
1306
+ if (!policySet) {
1307
+ if (failOnMissing) {
1308
+ process.stderr.write("protect-mcp evaluate: policy not found; denying (fail-closed). Pass --fail-on-missing-policy false to allow.\n");
1309
+ process.exit(2);
1310
+ }
1311
+ process.stdout.write(JSON.stringify({ allowed: true, reason: "no_policy_configured" }) + "\n");
1312
+ process.exit(0);
1313
+ }
1314
+ let input = {};
1315
+ try {
1316
+ input = JSON.parse(inputRaw);
1317
+ } catch {
1318
+ }
1319
+ let extra = {};
1320
+ if (contextRaw) {
1321
+ try {
1322
+ extra = JSON.parse(contextRaw);
1323
+ } catch {
1324
+ }
1325
+ }
1326
+ const context = { ...input, ...extra };
1327
+ if (typeof input.command === "string" && context.command_pattern === void 0) {
1328
+ context.command_pattern = input.command;
1329
+ }
1330
+ const decision = await evaluateCedar(policySet, { tool, tier: "unknown", context }, void 0, { failClosed: true });
1331
+ process.stdout.write(JSON.stringify({ allowed: decision.allowed, reason: decision.reason, policy_digest: policySet.digest }) + "\n");
1332
+ process.exit(decision.allowed ? 0 : 2);
1333
+ }
1334
+ async function handleSign(argv) {
1335
+ const tool = flagValue(argv, "--tool") || "";
1336
+ const receiptsDir = flagValue(argv, "--receipts") || "./receipts/";
1337
+ const keyPath = flagValue(argv, "--key");
1338
+ if (keyPath && existsSyncCli(keyPath)) {
1339
+ try {
1340
+ await initSigning({ enabled: true, key_path: keyPath });
1341
+ } catch {
1342
+ }
1343
+ }
1344
+ const requestId = `tu-${Date.now()}-${Math.random().toString(36).slice(2, 6)}`;
1345
+ const signed = signDecision({
1346
+ tool,
1347
+ decision: "allow",
1348
+ reason_code: "post_execution_receipt",
1349
+ policy_digest: "none",
1350
+ request_id: requestId,
1351
+ mode: "enforce",
1352
+ timestamp: Date.now()
1353
+ });
1354
+ try {
1355
+ mkdirSyncCli(receiptsDir, { recursive: true });
1356
+ } catch {
1357
+ }
1358
+ const line = signed.signed ?? JSON.stringify({ tool, request_id: requestId, signed: false, note: signed.warning || "no signer configured" });
1359
+ try {
1360
+ appendFileSyncCli(joinCli(receiptsDir, "receipts.jsonl"), line + "\n");
1361
+ } catch {
1362
+ }
1363
+ process.stdout.write(JSON.stringify({ signed: Boolean(signed.signed), artifact_type: signed.artifact_type, request_id: requestId }) + "\n");
1364
+ process.exit(0);
1365
+ }
1276
1366
  async function main() {
1277
1367
  sendInstallTelemetry().catch(() => {
1278
1368
  });
@@ -1281,6 +1371,14 @@ async function main() {
1281
1371
  printHelp();
1282
1372
  process.exit(0);
1283
1373
  }
1374
+ if (args[0] === "evaluate") {
1375
+ await handleEvaluate(args.slice(1));
1376
+ return;
1377
+ }
1378
+ if (args[0] === "sign") {
1379
+ await handleSign(args.slice(1));
1380
+ return;
1381
+ }
1284
1382
  if (args[0] === "serve") {
1285
1383
  const { startHookServer } = await import("./hook-server.mjs");
1286
1384
  const portIdx = args.indexOf("--port");
@@ -1289,13 +1387,22 @@ async function main() {
1289
1387
  const policyPath2 = policyIdx >= 0 && args[policyIdx + 1] ? args[policyIdx + 1] : void 0;
1290
1388
  const cedarIdx = args.indexOf("--cedar");
1291
1389
  const cedarDir2 = cedarIdx >= 0 && args[cedarIdx + 1] ? args[cedarIdx + 1] : void 0;
1292
- await startHookServer({
1293
- port,
1294
- policyPath: policyPath2,
1295
- cedarDir: cedarDir2,
1296
- enforce: args.includes("--enforce"),
1297
- verbose: args.includes("--verbose") || args.includes("-v")
1298
- });
1390
+ const enforce2 = args.includes("--enforce");
1391
+ const verbose2 = args.includes("--verbose") || args.includes("-v");
1392
+ if (enforce2) {
1393
+ const selfTest = await runEvaluatorSelfTest();
1394
+ if (!selfTest.passed) {
1395
+ process.stderr.write("protect-mcp serve --enforce: the policy-engine restraint self-test FAILED. Refusing to arm the gate.\n");
1396
+ for (const c of selfTest.cases.filter((c2) => !c2.pass)) {
1397
+ process.stderr.write(` [FAIL] ${c.name}: expected ${c.expected}, got ${c.actual}
1398
+ `);
1399
+ }
1400
+ process.exit(1);
1401
+ }
1402
+ if (verbose2) process.stderr.write(`protect-mcp: restraint self-test passed (${selfTest.cases.length} vectors). Arming gate.
1403
+ `);
1404
+ }
1405
+ await startHookServer({ port, policyPath: policyPath2, cedarDir: cedarDir2, enforce: enforce2, verbose: verbose2 });
1299
1406
  return;
1300
1407
  }
1301
1408
  if (args[0] === "init-hooks") {
@@ -1442,7 +1549,7 @@ async function main() {
1442
1549
  if (useHttp) {
1443
1550
  const portIdx = args.indexOf("--port");
1444
1551
  const httpPort = portIdx >= 0 && args[portIdx + 1] ? parseInt(args[portIdx + 1]) : 3e3;
1445
- const { startHttpTransport } = await import("./http-transport-MO32ESHZ.mjs");
1552
+ const { startHttpTransport } = await import("./http-transport-R5AO7X6D.mjs");
1446
1553
  startHttpTransport({ port: httpPort, config, serverCommand: childCommand });
1447
1554
  return;
1448
1555
  }
@@ -1605,6 +1712,24 @@ async function handleDoctor() {
1605
1712
  } catch {
1606
1713
  process.stdout.write(dim2(" ScopeBlind API not reachable \u2014 offline mode (receipts stored locally)\n"));
1607
1714
  }
1715
+ process.stdout.write("\nRestraint self-test:\n");
1716
+ try {
1717
+ const st = await runEvaluatorSelfTest();
1718
+ if (!st.wasmAvailable) {
1719
+ process.stdout.write(dim2(" Cedar WASM not installed; the gate fails closed (denies) until it is.\n"));
1720
+ }
1721
+ for (const c of st.cases) {
1722
+ process.stdout.write(c.pass ? green2(` ${c.name}
1723
+ `) : `\x1B[31m FAIL: ${c.name} (expected ${c.expected}, got ${c.actual})
1724
+ \x1B[0m`);
1725
+ }
1726
+ if (!st.passed) issues++;
1727
+ else process.stdout.write(green2(" the gate denies what it should and allows what it should\n"));
1728
+ } catch (err) {
1729
+ process.stdout.write(yellow2(` self-test could not run: ${err instanceof Error ? err.message : "unknown"}
1730
+ `));
1731
+ issues++;
1732
+ }
1608
1733
  process.stdout.write("\n");
1609
1734
  if (issues === 0) {
1610
1735
  process.stdout.write("\x1B[32m\x1B[1mAll checks passed.\x1B[0m Ready to wrap MCP servers.\n");
@@ -89,14 +89,18 @@ function buildEntities(req) {
89
89
  }
90
90
  ];
91
91
  }
92
- async function evaluateCedar(policySet, req, schema) {
92
+ function onEvalError(reason, failClosed, extra) {
93
+ return {
94
+ allowed: !failClosed,
95
+ reason: failClosed ? reason : `${reason} (observe mode; would DENY under enforcement)`,
96
+ metadata: { error: true, fail_closed: failClosed, would_deny: true, ...extra || {} }
97
+ };
98
+ }
99
+ async function evaluateCedar(policySet, req, schema, options) {
100
+ const failClosed = options?.failClosed ?? true;
93
101
  const available = await ensureCedarWasm();
94
102
  if (!available) {
95
- return {
96
- allowed: true,
97
- reason: "cedar_wasm_not_available",
98
- metadata: { fallback: true }
99
- };
103
+ return onEvalError("cedar_wasm_not_available", failClosed, { fallback: true });
100
104
  }
101
105
  try {
102
106
  const agentId = req.agentId || req.tier;
@@ -118,7 +122,7 @@ async function evaluateCedar(policySet, req, schema) {
118
122
  let result;
119
123
  if (typeof cedarWasm.isAuthorized === "function") {
120
124
  result = cedarWasm.isAuthorized({
121
- policies: policySet.source,
125
+ policies: { staticPolicies: policySet.source },
122
126
  entities,
123
127
  principal: authRequest.principal,
124
128
  action: authRequest.action,
@@ -136,7 +140,7 @@ async function evaluateCedar(policySet, req, schema) {
136
140
  const cedarEngine = cedarWasm.default || cedarWasm;
137
141
  if (typeof cedarEngine.isAuthorized === "function") {
138
142
  result = cedarEngine.isAuthorized({
139
- policies: policySet.source,
143
+ policies: { staticPolicies: policySet.source },
140
144
  entities,
141
145
  principal: authRequest.principal,
142
146
  action: authRequest.action,
@@ -145,57 +149,56 @@ async function evaluateCedar(policySet, req, schema) {
145
149
  schema: cedarSchema
146
150
  });
147
151
  } else {
148
- return {
149
- allowed: true,
150
- reason: "cedar_wasm_api_unsupported",
151
- metadata: { fallback: true, exports: Object.keys(cedarWasm) }
152
- };
152
+ return onEvalError("cedar_wasm_api_unsupported", failClosed, { exports: Object.keys(cedarWasm) });
153
153
  }
154
154
  }
155
- const decision = parseWasmResult(result);
155
+ const parsed = parseWasmResult(result);
156
+ const policyErrors = extractPolicyErrors(result);
157
+ if (parsed.kind === "error") {
158
+ return onEvalError(`cedar_unparseable_result: ${parsed.diagnostics}`, failClosed);
159
+ }
160
+ if (policyErrors.length > 0) {
161
+ return onEvalError(
162
+ `cedar_policy_errored: ${policyErrors.length} policy error(s); decision is unsound`,
163
+ failClosed,
164
+ { policy_errors: policyErrors.slice(0, 5), policy_digest: policySet.digest }
165
+ );
166
+ }
156
167
  return {
157
- allowed: decision.allowed,
158
- reason: decision.allowed ? void 0 : `cedar_deny${decision.diagnostics ? ": " + decision.diagnostics : ""}`,
168
+ allowed: parsed.kind === "allow",
169
+ reason: parsed.kind === "allow" ? void 0 : `cedar_deny${parsed.diagnostics ? ": " + parsed.diagnostics : ""}`,
159
170
  metadata: {
160
171
  policy_digest: policySet.digest,
161
- ...decision.matchedPolicies ? { matched_policies: decision.matchedPolicies } : {}
172
+ ...parsed.matchedPolicies ? { matched_policies: parsed.matchedPolicies } : {}
162
173
  }
163
174
  };
164
175
  } catch (err) {
165
- return {
166
- allowed: true,
167
- reason: `cedar_eval_error: ${err instanceof Error ? err.message : "unknown"}`,
168
- metadata: { fallback: true, error: true }
169
- };
176
+ return onEvalError(`cedar_eval_error: ${err instanceof Error ? err.message : "unknown"}`, failClosed);
170
177
  }
171
178
  }
172
179
  function parseWasmResult(result) {
173
- if (!result) {
174
- return { allowed: true, diagnostics: "null result from Cedar WASM" };
175
- }
176
- if (result.type === "allow" || result.type === "Allow") {
177
- return { allowed: true };
178
- }
179
- if (result.type === "deny" || result.type === "Deny") {
180
- return {
181
- allowed: false,
182
- diagnostics: result.diagnostics ? JSON.stringify(result.diagnostics) : void 0,
183
- matchedPolicies: result.diagnostics?.reasons
184
- };
185
- }
186
- if (result.decision === "Allow") {
187
- return { allowed: true };
188
- }
189
- if (result.decision === "Deny") {
190
- return {
191
- allowed: false,
192
- diagnostics: result.diagnostics ? JSON.stringify(result.diagnostics) : void 0
193
- };
194
- }
195
- if (typeof result === "boolean") {
196
- return { allowed: result };
180
+ if (!result) return { kind: "error", diagnostics: "null result from Cedar WASM" };
181
+ if (result.type === "failure") {
182
+ return { kind: "error", diagnostics: `cedar failure: ${JSON.stringify(result.errors ?? [])}` };
183
+ }
184
+ if (result.type === "success" && result.response) {
185
+ const dec = result.response.decision;
186
+ const reasons = result.response.diagnostics?.reason;
187
+ if (dec === "allow" || dec === "Allow") return { kind: "allow", matchedPolicies: reasons };
188
+ if (dec === "deny" || dec === "Deny") {
189
+ return { kind: "deny", diagnostics: result.response.diagnostics ? JSON.stringify(result.response.diagnostics) : void 0, matchedPolicies: reasons };
190
+ }
197
191
  }
198
- return { allowed: true, diagnostics: `unknown result format: ${JSON.stringify(result)}` };
192
+ if (result.type === "allow" || result.decision === "Allow") return { kind: "allow" };
193
+ if (result.type === "deny" || result.decision === "Deny") return { kind: "deny" };
194
+ if (typeof result === "boolean") return result ? { kind: "allow" } : { kind: "deny" };
195
+ return { kind: "error", diagnostics: `unknown result format: ${JSON.stringify(result)}` };
196
+ }
197
+ function extractPolicyErrors(result) {
198
+ if (!result || typeof result !== "object") return [];
199
+ const raw = result.errors ?? result.response?.diagnostics?.errors ?? result.diagnostics?.errors ?? [];
200
+ if (!Array.isArray(raw)) return [];
201
+ return raw.map((e) => typeof e === "string" ? e : e?.message ?? e?.error ?? JSON.stringify(e)).filter(Boolean);
199
202
  }
200
203
  async function isCedarAvailable() {
201
204
  return ensureCedarWasm();
@@ -1,7 +1,7 @@
1
1
  import {
2
2
  startHookServer
3
- } from "./chunk-3YCKR72H.mjs";
4
- import "./chunk-UV53U6D4.mjs";
3
+ } from "./chunk-X63ELMU4.mjs";
4
+ import "./chunk-546U3A7R.mjs";
5
5
  import "./chunk-PQJP2ZCI.mjs";
6
6
  export {
7
7
  startHookServer
@@ -1,7 +1,7 @@
1
1
  import {
2
2
  ProtectGateway
3
- } from "./chunk-PLKRTBDR.mjs";
4
- import "./chunk-UV53U6D4.mjs";
3
+ } from "./chunk-OHUTUFTC.mjs";
4
+ import "./chunk-546U3A7R.mjs";
5
5
  import "./chunk-PQJP2ZCI.mjs";
6
6
 
7
7
  // src/http-transport.ts
package/dist/index.d.mts CHANGED
@@ -595,19 +595,52 @@ interface CedarSchema {
595
595
  * Throws if the directory doesn't exist or contains no .cedar files.
596
596
  */
597
597
  declare function loadCedarPolicies(dirPath: string): CedarPolicySet;
598
+ interface CedarEvalOptions {
599
+ /**
600
+ * Default true (0.7.0+). When true, ANY evaluation error, engine
601
+ * unavailability, malformed result, or per-policy error DENIES. When false
602
+ * (explicit observe/shadow use only), those paths ALLOW but are flagged
603
+ * would_deny:true in the decision metadata so the failure is never silent.
604
+ */
605
+ failClosed?: boolean;
606
+ }
598
607
  /**
599
608
  * Evaluate a Cedar policy set against a tool call.
600
609
  *
601
- * Returns a standard ExternalDecision compatible with the gateway's
602
- * decision pipeline. If Cedar WASM is not available, returns a
603
- * fallback allow decision (fail-open, logged).
610
+ * FAIL-CLOSED by default (0.7.0+): if Cedar is unavailable, the engine API is
611
+ * unsupported, evaluation throws, the result is malformed, or ANY policy errored
612
+ * during evaluation (which Cedar otherwise silently discards, leaving a residual
613
+ * permit standing), this returns DENY. The allow-on-error behavior is reachable
614
+ * only by explicitly passing { failClosed: false }, and even then it is flagged.
604
615
  */
605
- declare function evaluateCedar(policySet: CedarPolicySet, req: CedarEvalRequest, schema?: CedarSchema): Promise<ExternalDecision>;
616
+ declare function evaluateCedar(policySet: CedarPolicySet, req: CedarEvalRequest, schema?: CedarSchema, options?: CedarEvalOptions): Promise<ExternalDecision>;
606
617
  /**
607
618
  * Validate that Cedar WASM is available.
608
619
  * Useful for CLI startup diagnostics.
609
620
  */
610
621
  declare function isCedarAvailable(): Promise<boolean>;
622
+ /** Build a CedarPolicySet from inline source (for the self-test). */
623
+ declare function policySetFromSource(source: string, name?: string): CedarPolicySet;
624
+ interface SelfTestCase {
625
+ name: string;
626
+ expected: 'ALLOW' | 'DENY';
627
+ actual: 'ALLOW' | 'DENY';
628
+ pass: boolean;
629
+ reason?: string;
630
+ }
631
+ interface SelfTestReport {
632
+ wasmAvailable: boolean;
633
+ passed: boolean;
634
+ cases: SelfTestCase[];
635
+ }
636
+ /**
637
+ * Run known deny/allow vectors through the LIVE evaluator before the gate is
638
+ * trusted. Always proves the fail-closed invariant (the engine being unable to
639
+ * decide must DENY). When Cedar WASM is present it also proves a real forbid
640
+ * denies, a permit allows, and a policy using the silently-discarded
641
+ * `in`-on-String pattern DENIES rather than permit-all (the 0.6.x regression).
642
+ */
643
+ declare function runEvaluatorSelfTest(): Promise<SelfTestReport>;
611
644
 
612
645
  /**
613
646
  * MCP tool-calling gateway that intercepts JSON-RPC requests,
@@ -2982,4 +3015,4 @@ declare function getScopeBlindBridge(): ScopeBlindBridge;
2982
3015
  /** Convenience: forward a signed receipt without instantiating yourself. */
2983
3016
  declare function forwardReceipt(signedReceipt: any): void;
2984
3017
 
2985
- export { type ActionReceipt, type AdmissionResult, type AgentId, type AgentManifest, type ApprovalAssertion, type ApprovalChallenge, type ApprovalNotification, type ApprovalResult, type ArenaPayload, type ArenaReceipt, type AttestationDocument, type AttestationPayload, type AttestationProvider, type AttestationReceipt, type AttestationResult, type AuditBundle, type AuditBundleOptions, type BenchmarkPayload, type BenchmarkReceipt, type BuilderId, type C2PAAssertion, type C2PAIngredient, type C2PAManifest, type C2PAOptions, type CCRConnectorConfig, type CCRSessionContext, type CalibrationScore, type CedarEvalRequest, type CedarPolicySet, type CedarSchema, type CedarSchemaResult, type CommittedFieldOpening, type CommittedSignResult, type ComplianceReport, ConfidentialGate, type ConfidentialGateConfig, type ConfidentialInferenceConfig, type CredentialConfig, type DecisionContext, type DecisionLog, type DelegationReceipt, type DisclosureMode, type Ed25519PublicKey, type EvidenceAttestation, type EvidenceAttestationInput, type EvidenceIssuer, type EvidenceReceipt, type EvidenceReceiptBase, type EvidenceSummary, type EvidenceSummaryEntry, type EvidenceType, type ExternalDecision, type ExternalPDPConfig, type HFDatasetMetadata, type HFReceiptRow, type HookEventName, type HookInput, type HookResponse, type IssuerType, type JsonRpcRequest, type JsonRpcResponse, type LeaseCompatibility, type ManifestBuilder, type ManifestCapabilities, type ManifestConfig, type ManifestIdentity, type ManifestPresentation, type ManifestSignature, type ManifestStatus, type McpToolDescription, type MinimalDisclosure, type NotificationConfig, type PassportTokenClaims, type PayloadDigest, type PlanReceipt, type PolicyEngineMode, type PredictionReceipt, type PredictionResolution, type PropagatorConfig, type ProtectConfig, ProtectGateway, type ProtectPolicy, type RateLimit, ReceiptPropagator, type RedactedResult, type RedactionSalt, type RekorAnchor, type RekorVerification, type RestraintPayload, type RestraintReceipt, type SHA256Hash, type SafetyTranscript, type Sandbox, type SandboxConfig, type SandboxReceipt, type SandboxResult, type SandboxToolCall, type SchemaGeneratorConfig, ScopeBlindBridge, type SigningConfig, type SimulationResult, type SimulationSummary, type SwarmContext, type TierOverrides, type TimingMetrics, type ToolPolicy, type TrustTier, type WorkPayload, type WorkReceipt, anchorToRekor, buildDecisionContext, checkRateLimit, collectSignedReceipts, computeCalibration, confidentialInference, createApprovalChallenge, createApprovalReceiptPayload, createAttestationField, createAuditBundle, createC2PAManifest, createDisclosurePackage, createEvidenceAttestation, createLogAnchorField, createReceiptChannel, createSandbox, destroySandbox, discloseField, ed25519ToDIDKey, evaluateCedar, evaluateTier, exportC2PAManifestJSON, exportJSONL, formatReportMarkdown, formatSimulation, forwardReceipt, generateC2PACommand, generateCedarSchema, generateDatasetCard, generateHFMetadata, generateReport, generateSafetyTranscript, generateSchemaStub, getScopeBlindBridge, getSignerInfo, getToolPolicy, hashReceipt, hashResponseBody, initSigning, isAgentId, isCedarAvailable, isDisclosureMode, isEvidenceType, isManifestStatus, isSigningEnabled, listCredentialLabels, loadCedarPolicies, loadPolicy, manifestToVC, meetsMinTier, parseLogFile, parseNotificationConfigFromEnv, parseRateLimit, queryExternalPDP, receiptToVP, receiptsToHFRows, redactFields, resolveCredential, revealField, runInSandbox, sendApprovalNotification, signCommittedDecision, signDecision, simulate, toCredentialRequestOptions, toManifoldFormat, toMetaculusFormat, validateCredentials, validateEvidenceReceipt, validateManifest, verifyActaC2PAAssertions, verifyAllCommitments, verifyApprovalAssertion, verifyCommitment, verifyEvidenceAttestation, verifyRekorAnchor };
3018
+ export { type ActionReceipt, type AdmissionResult, type AgentId, type AgentManifest, type ApprovalAssertion, type ApprovalChallenge, type ApprovalNotification, type ApprovalResult, type ArenaPayload, type ArenaReceipt, type AttestationDocument, type AttestationPayload, type AttestationProvider, type AttestationReceipt, type AttestationResult, type AuditBundle, type AuditBundleOptions, type BenchmarkPayload, type BenchmarkReceipt, type BuilderId, type C2PAAssertion, type C2PAIngredient, type C2PAManifest, type C2PAOptions, type CCRConnectorConfig, type CCRSessionContext, type CalibrationScore, type CedarEvalOptions, type CedarEvalRequest, type CedarPolicySet, type CedarSchema, type CedarSchemaResult, type CommittedFieldOpening, type CommittedSignResult, type ComplianceReport, ConfidentialGate, type ConfidentialGateConfig, type ConfidentialInferenceConfig, type CredentialConfig, type DecisionContext, type DecisionLog, type DelegationReceipt, type DisclosureMode, type Ed25519PublicKey, type EvidenceAttestation, type EvidenceAttestationInput, type EvidenceIssuer, type EvidenceReceipt, type EvidenceReceiptBase, type EvidenceSummary, type EvidenceSummaryEntry, type EvidenceType, type ExternalDecision, type ExternalPDPConfig, type HFDatasetMetadata, type HFReceiptRow, type HookEventName, type HookInput, type HookResponse, type IssuerType, type JsonRpcRequest, type JsonRpcResponse, type LeaseCompatibility, type ManifestBuilder, type ManifestCapabilities, type ManifestConfig, type ManifestIdentity, type ManifestPresentation, type ManifestSignature, type ManifestStatus, type McpToolDescription, type MinimalDisclosure, type NotificationConfig, type PassportTokenClaims, type PayloadDigest, type PlanReceipt, type PolicyEngineMode, type PredictionReceipt, type PredictionResolution, type PropagatorConfig, type ProtectConfig, ProtectGateway, type ProtectPolicy, type RateLimit, ReceiptPropagator, type RedactedResult, type RedactionSalt, type RekorAnchor, type RekorVerification, type RestraintPayload, type RestraintReceipt, type SHA256Hash, type SafetyTranscript, type Sandbox, type SandboxConfig, type SandboxReceipt, type SandboxResult, type SandboxToolCall, type SchemaGeneratorConfig, ScopeBlindBridge, type SelfTestCase, type SelfTestReport, type SigningConfig, type SimulationResult, type SimulationSummary, type SwarmContext, type TierOverrides, type TimingMetrics, type ToolPolicy, type TrustTier, type WorkPayload, type WorkReceipt, anchorToRekor, buildDecisionContext, checkRateLimit, collectSignedReceipts, computeCalibration, confidentialInference, createApprovalChallenge, createApprovalReceiptPayload, createAttestationField, createAuditBundle, createC2PAManifest, createDisclosurePackage, createEvidenceAttestation, createLogAnchorField, createReceiptChannel, createSandbox, destroySandbox, discloseField, ed25519ToDIDKey, evaluateCedar, evaluateTier, exportC2PAManifestJSON, exportJSONL, formatReportMarkdown, formatSimulation, forwardReceipt, generateC2PACommand, generateCedarSchema, generateDatasetCard, generateHFMetadata, generateReport, generateSafetyTranscript, generateSchemaStub, getScopeBlindBridge, getSignerInfo, getToolPolicy, hashReceipt, hashResponseBody, initSigning, isAgentId, isCedarAvailable, isDisclosureMode, isEvidenceType, isManifestStatus, isSigningEnabled, listCredentialLabels, loadCedarPolicies, loadPolicy, manifestToVC, meetsMinTier, parseLogFile, parseNotificationConfigFromEnv, parseRateLimit, policySetFromSource, queryExternalPDP, receiptToVP, receiptsToHFRows, redactFields, resolveCredential, revealField, runEvaluatorSelfTest, runInSandbox, sendApprovalNotification, signCommittedDecision, signDecision, simulate, toCredentialRequestOptions, toManifoldFormat, toMetaculusFormat, validateCredentials, validateEvidenceReceipt, validateManifest, verifyActaC2PAAssertions, verifyAllCommitments, verifyApprovalAssertion, verifyCommitment, verifyEvidenceAttestation, verifyRekorAnchor };
package/dist/index.d.ts CHANGED
@@ -595,19 +595,52 @@ interface CedarSchema {
595
595
  * Throws if the directory doesn't exist or contains no .cedar files.
596
596
  */
597
597
  declare function loadCedarPolicies(dirPath: string): CedarPolicySet;
598
+ interface CedarEvalOptions {
599
+ /**
600
+ * Default true (0.7.0+). When true, ANY evaluation error, engine
601
+ * unavailability, malformed result, or per-policy error DENIES. When false
602
+ * (explicit observe/shadow use only), those paths ALLOW but are flagged
603
+ * would_deny:true in the decision metadata so the failure is never silent.
604
+ */
605
+ failClosed?: boolean;
606
+ }
598
607
  /**
599
608
  * Evaluate a Cedar policy set against a tool call.
600
609
  *
601
- * Returns a standard ExternalDecision compatible with the gateway's
602
- * decision pipeline. If Cedar WASM is not available, returns a
603
- * fallback allow decision (fail-open, logged).
610
+ * FAIL-CLOSED by default (0.7.0+): if Cedar is unavailable, the engine API is
611
+ * unsupported, evaluation throws, the result is malformed, or ANY policy errored
612
+ * during evaluation (which Cedar otherwise silently discards, leaving a residual
613
+ * permit standing), this returns DENY. The allow-on-error behavior is reachable
614
+ * only by explicitly passing { failClosed: false }, and even then it is flagged.
604
615
  */
605
- declare function evaluateCedar(policySet: CedarPolicySet, req: CedarEvalRequest, schema?: CedarSchema): Promise<ExternalDecision>;
616
+ declare function evaluateCedar(policySet: CedarPolicySet, req: CedarEvalRequest, schema?: CedarSchema, options?: CedarEvalOptions): Promise<ExternalDecision>;
606
617
  /**
607
618
  * Validate that Cedar WASM is available.
608
619
  * Useful for CLI startup diagnostics.
609
620
  */
610
621
  declare function isCedarAvailable(): Promise<boolean>;
622
+ /** Build a CedarPolicySet from inline source (for the self-test). */
623
+ declare function policySetFromSource(source: string, name?: string): CedarPolicySet;
624
+ interface SelfTestCase {
625
+ name: string;
626
+ expected: 'ALLOW' | 'DENY';
627
+ actual: 'ALLOW' | 'DENY';
628
+ pass: boolean;
629
+ reason?: string;
630
+ }
631
+ interface SelfTestReport {
632
+ wasmAvailable: boolean;
633
+ passed: boolean;
634
+ cases: SelfTestCase[];
635
+ }
636
+ /**
637
+ * Run known deny/allow vectors through the LIVE evaluator before the gate is
638
+ * trusted. Always proves the fail-closed invariant (the engine being unable to
639
+ * decide must DENY). When Cedar WASM is present it also proves a real forbid
640
+ * denies, a permit allows, and a policy using the silently-discarded
641
+ * `in`-on-String pattern DENIES rather than permit-all (the 0.6.x regression).
642
+ */
643
+ declare function runEvaluatorSelfTest(): Promise<SelfTestReport>;
611
644
 
612
645
  /**
613
646
  * MCP tool-calling gateway that intercepts JSON-RPC requests,
@@ -2982,4 +3015,4 @@ declare function getScopeBlindBridge(): ScopeBlindBridge;
2982
3015
  /** Convenience: forward a signed receipt without instantiating yourself. */
2983
3016
  declare function forwardReceipt(signedReceipt: any): void;
2984
3017
 
2985
- export { type ActionReceipt, type AdmissionResult, type AgentId, type AgentManifest, type ApprovalAssertion, type ApprovalChallenge, type ApprovalNotification, type ApprovalResult, type ArenaPayload, type ArenaReceipt, type AttestationDocument, type AttestationPayload, type AttestationProvider, type AttestationReceipt, type AttestationResult, type AuditBundle, type AuditBundleOptions, type BenchmarkPayload, type BenchmarkReceipt, type BuilderId, type C2PAAssertion, type C2PAIngredient, type C2PAManifest, type C2PAOptions, type CCRConnectorConfig, type CCRSessionContext, type CalibrationScore, type CedarEvalRequest, type CedarPolicySet, type CedarSchema, type CedarSchemaResult, type CommittedFieldOpening, type CommittedSignResult, type ComplianceReport, ConfidentialGate, type ConfidentialGateConfig, type ConfidentialInferenceConfig, type CredentialConfig, type DecisionContext, type DecisionLog, type DelegationReceipt, type DisclosureMode, type Ed25519PublicKey, type EvidenceAttestation, type EvidenceAttestationInput, type EvidenceIssuer, type EvidenceReceipt, type EvidenceReceiptBase, type EvidenceSummary, type EvidenceSummaryEntry, type EvidenceType, type ExternalDecision, type ExternalPDPConfig, type HFDatasetMetadata, type HFReceiptRow, type HookEventName, type HookInput, type HookResponse, type IssuerType, type JsonRpcRequest, type JsonRpcResponse, type LeaseCompatibility, type ManifestBuilder, type ManifestCapabilities, type ManifestConfig, type ManifestIdentity, type ManifestPresentation, type ManifestSignature, type ManifestStatus, type McpToolDescription, type MinimalDisclosure, type NotificationConfig, type PassportTokenClaims, type PayloadDigest, type PlanReceipt, type PolicyEngineMode, type PredictionReceipt, type PredictionResolution, type PropagatorConfig, type ProtectConfig, ProtectGateway, type ProtectPolicy, type RateLimit, ReceiptPropagator, type RedactedResult, type RedactionSalt, type RekorAnchor, type RekorVerification, type RestraintPayload, type RestraintReceipt, type SHA256Hash, type SafetyTranscript, type Sandbox, type SandboxConfig, type SandboxReceipt, type SandboxResult, type SandboxToolCall, type SchemaGeneratorConfig, ScopeBlindBridge, type SigningConfig, type SimulationResult, type SimulationSummary, type SwarmContext, type TierOverrides, type TimingMetrics, type ToolPolicy, type TrustTier, type WorkPayload, type WorkReceipt, anchorToRekor, buildDecisionContext, checkRateLimit, collectSignedReceipts, computeCalibration, confidentialInference, createApprovalChallenge, createApprovalReceiptPayload, createAttestationField, createAuditBundle, createC2PAManifest, createDisclosurePackage, createEvidenceAttestation, createLogAnchorField, createReceiptChannel, createSandbox, destroySandbox, discloseField, ed25519ToDIDKey, evaluateCedar, evaluateTier, exportC2PAManifestJSON, exportJSONL, formatReportMarkdown, formatSimulation, forwardReceipt, generateC2PACommand, generateCedarSchema, generateDatasetCard, generateHFMetadata, generateReport, generateSafetyTranscript, generateSchemaStub, getScopeBlindBridge, getSignerInfo, getToolPolicy, hashReceipt, hashResponseBody, initSigning, isAgentId, isCedarAvailable, isDisclosureMode, isEvidenceType, isManifestStatus, isSigningEnabled, listCredentialLabels, loadCedarPolicies, loadPolicy, manifestToVC, meetsMinTier, parseLogFile, parseNotificationConfigFromEnv, parseRateLimit, queryExternalPDP, receiptToVP, receiptsToHFRows, redactFields, resolveCredential, revealField, runInSandbox, sendApprovalNotification, signCommittedDecision, signDecision, simulate, toCredentialRequestOptions, toManifoldFormat, toMetaculusFormat, validateCredentials, validateEvidenceReceipt, validateManifest, verifyActaC2PAAssertions, verifyAllCommitments, verifyApprovalAssertion, verifyCommitment, verifyEvidenceAttestation, verifyRekorAnchor };
3018
+ export { type ActionReceipt, type AdmissionResult, type AgentId, type AgentManifest, type ApprovalAssertion, type ApprovalChallenge, type ApprovalNotification, type ApprovalResult, type ArenaPayload, type ArenaReceipt, type AttestationDocument, type AttestationPayload, type AttestationProvider, type AttestationReceipt, type AttestationResult, type AuditBundle, type AuditBundleOptions, type BenchmarkPayload, type BenchmarkReceipt, type BuilderId, type C2PAAssertion, type C2PAIngredient, type C2PAManifest, type C2PAOptions, type CCRConnectorConfig, type CCRSessionContext, type CalibrationScore, type CedarEvalOptions, type CedarEvalRequest, type CedarPolicySet, type CedarSchema, type CedarSchemaResult, type CommittedFieldOpening, type CommittedSignResult, type ComplianceReport, ConfidentialGate, type ConfidentialGateConfig, type ConfidentialInferenceConfig, type CredentialConfig, type DecisionContext, type DecisionLog, type DelegationReceipt, type DisclosureMode, type Ed25519PublicKey, type EvidenceAttestation, type EvidenceAttestationInput, type EvidenceIssuer, type EvidenceReceipt, type EvidenceReceiptBase, type EvidenceSummary, type EvidenceSummaryEntry, type EvidenceType, type ExternalDecision, type ExternalPDPConfig, type HFDatasetMetadata, type HFReceiptRow, type HookEventName, type HookInput, type HookResponse, type IssuerType, type JsonRpcRequest, type JsonRpcResponse, type LeaseCompatibility, type ManifestBuilder, type ManifestCapabilities, type ManifestConfig, type ManifestIdentity, type ManifestPresentation, type ManifestSignature, type ManifestStatus, type McpToolDescription, type MinimalDisclosure, type NotificationConfig, type PassportTokenClaims, type PayloadDigest, type PlanReceipt, type PolicyEngineMode, type PredictionReceipt, type PredictionResolution, type PropagatorConfig, type ProtectConfig, ProtectGateway, type ProtectPolicy, type RateLimit, ReceiptPropagator, type RedactedResult, type RedactionSalt, type RekorAnchor, type RekorVerification, type RestraintPayload, type RestraintReceipt, type SHA256Hash, type SafetyTranscript, type Sandbox, type SandboxConfig, type SandboxReceipt, type SandboxResult, type SandboxToolCall, type SchemaGeneratorConfig, ScopeBlindBridge, type SelfTestCase, type SelfTestReport, type SigningConfig, type SimulationResult, type SimulationSummary, type SwarmContext, type TierOverrides, type TimingMetrics, type ToolPolicy, type TrustTier, type WorkPayload, type WorkReceipt, anchorToRekor, buildDecisionContext, checkRateLimit, collectSignedReceipts, computeCalibration, confidentialInference, createApprovalChallenge, createApprovalReceiptPayload, createAttestationField, createAuditBundle, createC2PAManifest, createDisclosurePackage, createEvidenceAttestation, createLogAnchorField, createReceiptChannel, createSandbox, destroySandbox, discloseField, ed25519ToDIDKey, evaluateCedar, evaluateTier, exportC2PAManifestJSON, exportJSONL, formatReportMarkdown, formatSimulation, forwardReceipt, generateC2PACommand, generateCedarSchema, generateDatasetCard, generateHFMetadata, generateReport, generateSafetyTranscript, generateSchemaStub, getScopeBlindBridge, getSignerInfo, getToolPolicy, hashReceipt, hashResponseBody, initSigning, isAgentId, isCedarAvailable, isDisclosureMode, isEvidenceType, isManifestStatus, isSigningEnabled, listCredentialLabels, loadCedarPolicies, loadPolicy, manifestToVC, meetsMinTier, parseLogFile, parseNotificationConfigFromEnv, parseRateLimit, policySetFromSource, queryExternalPDP, receiptToVP, receiptsToHFRows, redactFields, resolveCredential, revealField, runEvaluatorSelfTest, runInSandbox, sendApprovalNotification, signCommittedDecision, signDecision, simulate, toCredentialRequestOptions, toManifoldFormat, toMetaculusFormat, validateCredentials, validateEvidenceReceipt, validateManifest, verifyActaC2PAAssertions, verifyAllCommitments, verifyApprovalAssertion, verifyCommitment, verifyEvidenceAttestation, verifyRekorAnchor };