protect-mcp 0.6.3 → 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
@@ -145,8 +153,8 @@ async function handleInit(argv) {
145
153
  let keypair;
146
154
  {
147
155
  const { randomBytes } = await import("crypto");
148
- const { ed25519 } = await import("@noble/curves/ed25519");
149
- const { bytesToHex } = await import("@noble/hashes/utils");
156
+ const { ed25519 } = await import("./ed25519-DZMMNNVE.mjs");
157
+ const { bytesToHex } = await import("./utils-6AYZFE5A.mjs");
150
158
  const privateKey = randomBytes(32);
151
159
  const publicKey = ed25519.getPublicKey(privateKey);
152
160
  keypair = {
@@ -765,8 +773,8 @@ ${bold("protect-mcp quickstart")}
765
773
  const { randomBytes } = await import("crypto");
766
774
  let keypair;
767
775
  try {
768
- const { ed25519 } = await import("@noble/curves/ed25519");
769
- const { bytesToHex } = await import("@noble/hashes/utils");
776
+ const { ed25519 } = await import("./ed25519-DZMMNNVE.mjs");
777
+ const { bytesToHex } = await import("./utils-6AYZFE5A.mjs");
770
778
  const privateKey = randomBytes(32);
771
779
  const publicKey = ed25519.getPublicKey(privateKey);
772
780
  keypair = {
@@ -1111,8 +1119,8 @@ ${bold("protect-mcp init-hooks")}
1111
1119
  if (!existsSync(keysDir)) mkdirSync(keysDir, { recursive: true });
1112
1120
  const { randomBytes: rb } = await import("crypto");
1113
1121
  try {
1114
- const { ed25519 } = await import("@noble/curves/ed25519");
1115
- const { bytesToHex } = await import("@noble/hashes/utils");
1122
+ const { ed25519 } = await import("./ed25519-DZMMNNVE.mjs");
1123
+ const { bytesToHex } = await import("./utils-6AYZFE5A.mjs");
1116
1124
  const privateKey = rb(32);
1117
1125
  const publicKey = ed25519.getPublicKey(privateKey);
1118
1126
  writeFileSync(keyPath, JSON.stringify({
@@ -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");
@@ -0,0 +1,38 @@
1
+ import {
2
+ ED25519_TORSION_SUBGROUP,
3
+ RistrettoPoint,
4
+ ed25519,
5
+ ed25519_hasher,
6
+ ed25519ctx,
7
+ ed25519ph,
8
+ edwardsToMontgomery,
9
+ edwardsToMontgomeryPriv,
10
+ edwardsToMontgomeryPub,
11
+ encodeToCurve,
12
+ hashToCurve,
13
+ hashToRistretto255,
14
+ hash_to_ristretto255,
15
+ ristretto255,
16
+ ristretto255_hasher,
17
+ x25519
18
+ } from "./chunk-LYKNULYU.mjs";
19
+ import "./chunk-D733KAPG.mjs";
20
+ import "./chunk-PQJP2ZCI.mjs";
21
+ export {
22
+ ED25519_TORSION_SUBGROUP,
23
+ RistrettoPoint,
24
+ ed25519,
25
+ ed25519_hasher,
26
+ ed25519ctx,
27
+ ed25519ph,
28
+ edwardsToMontgomery,
29
+ edwardsToMontgomeryPriv,
30
+ edwardsToMontgomeryPub,
31
+ encodeToCurve,
32
+ hashToCurve,
33
+ hashToRistretto255,
34
+ hash_to_ristretto255,
35
+ ristretto255,
36
+ ristretto255_hasher,
37
+ x25519
38
+ };
@@ -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,
@@ -2019,29 +2052,6 @@ interface ApprovalResult {
2019
2052
  contextHash: string;
2020
2053
  /** Timestamp of approval */
2021
2054
  approvedAt: string;
2022
- /** On failure, a machine-readable reason (e.g. 'invalid_signature'). */
2023
- reason?: string;
2024
- }
2025
- /**
2026
- * The registered credential public key, extracted from the COSE_Key at
2027
- * registration. ES256 keys are an uncompressed P-256 point; EdDSA keys are a
2028
- * 32-byte Ed25519 public key.
2029
- */
2030
- interface CredentialPublicKey {
2031
- /** COSE algorithm: -7 = ES256 (P-256 / ECDSA), -8 = EdDSA (Ed25519). */
2032
- alg: -7 | -8;
2033
- /** Public key, hex. ES256: 65-byte uncompressed point (0x04 || x || y). EdDSA: 32-byte key. */
2034
- publicKeyHex: string;
2035
- }
2036
- interface VerifyAssertionOptions {
2037
- /** Allowed origin(s) the assertion must come from, e.g. 'https://app.scopeblind.com'. Defaults to https://<rpId>. */
2038
- expectedOrigin?: string | string[];
2039
- /** Require the UV (user-verified / biometric or PIN) flag. Default true. */
2040
- requireUserVerification?: boolean;
2041
- /** The signCount stored from the previous assertion; a non-increasing counter signals a cloned authenticator. */
2042
- prevSignCount?: number;
2043
- /** Override 'now' (ms) for testing. */
2044
- now?: number;
2045
2055
  }
2046
2056
  /**
2047
2057
  * Create a WebAuthn challenge for approving a tool call.
@@ -2078,22 +2088,17 @@ declare function toCredentialRequestOptions(challenge: ApprovalChallenge, allowC
2078
2088
  };
2079
2089
  };
2080
2090
  /**
2081
- * Verify a WebAuthn assertion: full, fail-closed verification of a passkey or
2082
- * security-key co-sign. This proves a SPECIFIC human authorized a SPECIFIC
2083
- * action with a hardware-held key the host operator cannot exfiltrate. It
2084
- * checks, in order: challenge freshness; clientDataJSON type, challenge, and
2085
- * origin; the rpIdHash; the UP (and, by default, UV) flags; the authenticator
2086
- * signature over authenticatorData || SHA-256(clientDataJSON) using the
2087
- * registered credential public key (ES256 or EdDSA); and signCount monotonicity
2088
- * (clone detection) when a previous count is supplied. Any failure returns
2089
- * valid:false with a reason; nothing is trusted on a partial check.
2091
+ * Verify a WebAuthn assertion from the client.
2092
+ *
2093
+ * This is a simplified verification that checks the structure
2094
+ * and extracts the authenticator data. For production use with
2095
+ * full signature verification, use the @simplewebauthn/server package.
2090
2096
  *
2091
- * @param challenge - the original challenge
2092
- * @param assertion - the assertion from navigator.credentials.get()
2093
- * @param credentialPublicKey - the registered public key for assertion.credentialId
2094
- * @param opts - origin / UV / signCount / clock options
2097
+ * @param challenge - The original challenge
2098
+ * @param assertion - The assertion from navigator.credentials.get()
2099
+ * @returns ApprovalResult with verification details
2095
2100
  */
2096
- declare function verifyApprovalAssertion(challenge: ApprovalChallenge, assertion: ApprovalAssertion, credentialPublicKey?: CredentialPublicKey, opts?: VerifyAssertionOptions): ApprovalResult;
2101
+ declare function verifyApprovalAssertion(challenge: ApprovalChallenge, assertion: ApprovalAssertion): ApprovalResult;
2097
2102
  /**
2098
2103
  * Create the approval receipt payload for embedding in an Acta receipt.
2099
2104
  *
@@ -3010,4 +3015,4 @@ declare function getScopeBlindBridge(): ScopeBlindBridge;
3010
3015
  /** Convenience: forward a signed receipt without instantiating yourself. */
3011
3016
  declare function forwardReceipt(signedReceipt: any): void;
3012
3017
 
3013
- 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 };