@atbash/sdk 0.22.0-dev.0 → 0.24.0-dev.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/browser.mjs CHANGED
@@ -33,6 +33,14 @@ var __toESM = (mod2, isNodeMode, target) => (target = mod2 != null ? __create(__
33
33
  mod2
34
34
  ));
35
35
 
36
+ // <define:__ATBASH_DEV_JUDGE_PINS__>
37
+ var define_ATBASH_DEV_JUDGE_PINS_default;
38
+ var init_define_ATBASH_DEV_JUDGE_PINS = __esm({
39
+ "<define:__ATBASH_DEV_JUDGE_PINS__>"() {
40
+ define_ATBASH_DEV_JUDGE_PINS_default = ["03f1632c850eb126edf64923484a21713d3b3931a0755258a2cb6090d4a1859d3a"];
41
+ }
42
+ });
43
+
36
44
  // <define:__ATBASH_PRIVATE_NODE_URLS__>
37
45
  var define_ATBASH_PRIVATE_NODE_URLS_default;
38
46
  var init_define_ATBASH_PRIVATE_NODE_URLS = __esm({
@@ -41,11 +49,21 @@ var init_define_ATBASH_PRIVATE_NODE_URLS = __esm({
41
49
  }
42
50
  });
43
51
 
52
+ // <define:__ATBASH_PROD_JUDGE_PINS__>
53
+ var define_ATBASH_PROD_JUDGE_PINS_default;
54
+ var init_define_ATBASH_PROD_JUDGE_PINS = __esm({
55
+ "<define:__ATBASH_PROD_JUDGE_PINS__>"() {
56
+ define_ATBASH_PROD_JUDGE_PINS_default = ["02818eced310b32f227fada6dba76dbf0f9171265f63ec9860cc5a89a2bdb18bff"];
57
+ }
58
+ });
59
+
44
60
  // (disabled):node_modules/buffer/index.js
45
61
  var require_buffer = __commonJS({
46
62
  "(disabled):node_modules/buffer/index.js"() {
47
63
  "use strict";
64
+ init_define_ATBASH_DEV_JUDGE_PINS();
48
65
  init_define_ATBASH_PRIVATE_NODE_URLS();
66
+ init_define_ATBASH_PROD_JUDGE_PINS();
49
67
  }
50
68
  });
51
69
 
@@ -53,7 +71,9 @@ var require_buffer = __commonJS({
53
71
  var require_bn = __commonJS({
54
72
  "node_modules/bn.js/lib/bn.js"(exports, module) {
55
73
  "use strict";
74
+ init_define_ATBASH_DEV_JUDGE_PINS();
56
75
  init_define_ATBASH_PRIVATE_NODE_URLS();
76
+ init_define_ATBASH_PROD_JUDGE_PINS();
57
77
  (function(module2, exports2) {
58
78
  "use strict";
59
79
  function assert2(val, msg) {
@@ -2872,22 +2892,34 @@ var require_bn = __commonJS({
2872
2892
  });
2873
2893
 
2874
2894
  // src-ts/index.ts
2895
+ init_define_ATBASH_DEV_JUDGE_PINS();
2875
2896
  init_define_ATBASH_PRIVATE_NODE_URLS();
2897
+ init_define_ATBASH_PROD_JUDGE_PINS();
2876
2898
 
2877
2899
  // src-ts/browser/native.ts
2900
+ init_define_ATBASH_DEV_JUDGE_PINS();
2878
2901
  init_define_ATBASH_PRIVATE_NODE_URLS();
2902
+ init_define_ATBASH_PROD_JUDGE_PINS();
2879
2903
 
2880
2904
  // node_modules/@noble/curves/secp256k1.js
2905
+ init_define_ATBASH_DEV_JUDGE_PINS();
2881
2906
  init_define_ATBASH_PRIVATE_NODE_URLS();
2907
+ init_define_ATBASH_PROD_JUDGE_PINS();
2882
2908
 
2883
2909
  // node_modules/@noble/hashes/sha2.js
2910
+ init_define_ATBASH_DEV_JUDGE_PINS();
2884
2911
  init_define_ATBASH_PRIVATE_NODE_URLS();
2912
+ init_define_ATBASH_PROD_JUDGE_PINS();
2885
2913
 
2886
2914
  // node_modules/@noble/hashes/_md.js
2915
+ init_define_ATBASH_DEV_JUDGE_PINS();
2887
2916
  init_define_ATBASH_PRIVATE_NODE_URLS();
2917
+ init_define_ATBASH_PROD_JUDGE_PINS();
2888
2918
 
2889
2919
  // node_modules/@noble/hashes/utils.js
2920
+ init_define_ATBASH_DEV_JUDGE_PINS();
2890
2921
  init_define_ATBASH_PRIVATE_NODE_URLS();
2922
+ init_define_ATBASH_PROD_JUDGE_PINS();
2891
2923
  function isBytes(a) {
2892
2924
  return a instanceof Uint8Array || ArrayBuffer.isView(a) && a.constructor.name === "Uint8Array" && "BYTES_PER_ELEMENT" in a && a.BYTES_PER_ELEMENT === 1;
2893
2925
  }
@@ -3309,10 +3341,14 @@ var sha256 = /* @__PURE__ */ createHasher(
3309
3341
  );
3310
3342
 
3311
3343
  // node_modules/@noble/curves/abstract/curve.js
3344
+ init_define_ATBASH_DEV_JUDGE_PINS();
3312
3345
  init_define_ATBASH_PRIVATE_NODE_URLS();
3346
+ init_define_ATBASH_PROD_JUDGE_PINS();
3313
3347
 
3314
3348
  // node_modules/@noble/curves/utils.js
3349
+ init_define_ATBASH_DEV_JUDGE_PINS();
3315
3350
  init_define_ATBASH_PRIVATE_NODE_URLS();
3351
+ init_define_ATBASH_PROD_JUDGE_PINS();
3316
3352
  var abytes2 = (value, length, title) => abytes(value, length, title);
3317
3353
  var anumber2 = anumber;
3318
3354
  var bytesToHex2 = bytesToHex;
@@ -3465,7 +3501,9 @@ function validateObject(object, fields = {}, optFields = {}) {
3465
3501
  }
3466
3502
 
3467
3503
  // node_modules/@noble/curves/abstract/modular.js
3504
+ init_define_ATBASH_DEV_JUDGE_PINS();
3468
3505
  init_define_ATBASH_PRIVATE_NODE_URLS();
3506
+ init_define_ATBASH_PROD_JUDGE_PINS();
3469
3507
  var _0n2 = /* @__PURE__ */ BigInt(0);
3470
3508
  var _1n2 = /* @__PURE__ */ BigInt(1);
3471
3509
  var _2n = /* @__PURE__ */ BigInt(2);
@@ -4114,10 +4152,14 @@ function createKeygen(randomSecretKey, getPublicKey) {
4114
4152
  }
4115
4153
 
4116
4154
  // node_modules/@noble/curves/abstract/weierstrass.js
4155
+ init_define_ATBASH_DEV_JUDGE_PINS();
4117
4156
  init_define_ATBASH_PRIVATE_NODE_URLS();
4157
+ init_define_ATBASH_PROD_JUDGE_PINS();
4118
4158
 
4119
4159
  // node_modules/@noble/hashes/hmac.js
4160
+ init_define_ATBASH_DEV_JUDGE_PINS();
4120
4161
  init_define_ATBASH_PRIVATE_NODE_URLS();
4162
+ init_define_ATBASH_PROD_JUDGE_PINS();
4121
4163
  var _HMAC = class {
4122
4164
  oHash;
4123
4165
  iHash;
@@ -5149,7 +5191,9 @@ var Pointk1 = /* @__PURE__ */ weierstrass(secp256k1_CURVE, {
5149
5191
  var secp256k1 = /* @__PURE__ */ ecdsa(Pointk1, sha256);
5150
5192
 
5151
5193
  // node_modules/postchain-client/built/esm/index.js
5194
+ init_define_ATBASH_DEV_JUDGE_PINS();
5152
5195
  init_define_ATBASH_PRIVATE_NODE_URLS();
5196
+ init_define_ATBASH_PROD_JUDGE_PINS();
5153
5197
  var import_bn = __toESM(require_bn(), 1);
5154
5198
  var commonjsGlobal = typeof globalThis !== "undefined" ? globalThis : typeof window !== "undefined" ? window : typeof global !== "undefined" ? global : typeof self !== "undefined" ? self : {};
5155
5199
  function getDefaultExportFromCjs(x) {
@@ -43375,6 +43419,17 @@ function verifySignature(body, signatureHex, pubkeyHex) {
43375
43419
  const sigBytes = hexToBytes2(sigClean);
43376
43420
  return secp256k1.verify(sigBytes, digest9, pkBytes, { prehash: false });
43377
43421
  }
43422
+ function pinnedJudgeVerifyKeys(host) {
43423
+ const h = host.trim().toLowerCase();
43424
+ if (h === "atbash.ai" || h === "www.atbash.ai") return [...define_ATBASH_PROD_JUDGE_PINS_default];
43425
+ let devHost = "";
43426
+ try {
43427
+ devHost = "https://chromia-verified-ai-dev-two.vercel.app" ? new URL("https://chromia-verified-ai-dev-two.vercel.app").hostname.toLowerCase() : "";
43428
+ } catch {
43429
+ devHost = "";
43430
+ }
43431
+ return devHost !== "" && h === devHost ? [...define_ATBASH_DEV_JUDGE_PINS_default] : [];
43432
+ }
43378
43433
  var STUB_MSG = "not available in @atbash/sdk browser bundle \u2014 call from Node or handle server-side";
43379
43434
  function redactSecrets(input) {
43380
43435
  return { redacted: input, found: [] };
@@ -43416,6 +43471,7 @@ var native = {
43416
43471
  signLogToolCall,
43417
43472
  signJudgeAction,
43418
43473
  verifySignature,
43474
+ pinnedJudgeVerifyKeys,
43419
43475
  normalizeForMatching,
43420
43476
  containsEvasionCharacters,
43421
43477
  redactSecrets,
@@ -43496,10 +43552,14 @@ var native = {
43496
43552
  };
43497
43553
 
43498
43554
  // src-ts/client.ts
43555
+ init_define_ATBASH_DEV_JUDGE_PINS();
43499
43556
  init_define_ATBASH_PRIVATE_NODE_URLS();
43557
+ init_define_ATBASH_PROD_JUDGE_PINS();
43500
43558
 
43501
43559
  // src-ts/random.ts
43560
+ init_define_ATBASH_DEV_JUDGE_PINS();
43502
43561
  init_define_ATBASH_PRIVATE_NODE_URLS();
43562
+ init_define_ATBASH_PROD_JUDGE_PINS();
43503
43563
  function randomBytes4(size) {
43504
43564
  const buf = new Uint8Array(size);
43505
43565
  globalThis.crypto.getRandomValues(buf);
@@ -43515,7 +43575,9 @@ function randomHex(size) {
43515
43575
  }
43516
43576
 
43517
43577
  // src-ts/auth-bearer.ts
43578
+ init_define_ATBASH_DEV_JUDGE_PINS();
43518
43579
  init_define_ATBASH_PRIVATE_NODE_URLS();
43580
+ init_define_ATBASH_PROD_JUDGE_PINS();
43519
43581
  var BEARER_TTL_MS = 4 * 60 * 1e3;
43520
43582
  var bearers = /* @__PURE__ */ new Map();
43521
43583
  function agentAuthBearer(auth, blockchainRid) {
@@ -43540,7 +43602,9 @@ function agentAuthHeaders(auth, blockchainRid) {
43540
43602
  }
43541
43603
 
43542
43604
  // src-ts/chain-config.ts
43605
+ init_define_ATBASH_DEV_JUDGE_PINS();
43543
43606
  init_define_ATBASH_PRIVATE_NODE_URLS();
43607
+ init_define_ATBASH_PROD_JUDGE_PINS();
43544
43608
  var DEFAULT_PRIVATE_NODE_URLS = Object.freeze(
43545
43609
  native.defaultPrivateNodeUrls()
43546
43610
  );
@@ -43560,17 +43624,25 @@ function chainForNetwork(network) {
43560
43624
  }
43561
43625
 
43562
43626
  // src-ts/constants.ts
43627
+ init_define_ATBASH_DEV_JUDGE_PINS();
43563
43628
  init_define_ATBASH_PRIVATE_NODE_URLS();
43629
+ init_define_ATBASH_PROD_JUDGE_PINS();
43564
43630
  var DEFAULT_ENDPOINT = native.DEFAULT_ENDPOINT;
43565
43631
 
43566
43632
  // src-ts/browser/encrypted-toolcall.ts
43633
+ init_define_ATBASH_DEV_JUDGE_PINS();
43567
43634
  init_define_ATBASH_PRIVATE_NODE_URLS();
43635
+ init_define_ATBASH_PROD_JUDGE_PINS();
43568
43636
 
43569
43637
  // src-ts/browser/crypto-ecies.ts
43638
+ init_define_ATBASH_DEV_JUDGE_PINS();
43570
43639
  init_define_ATBASH_PRIVATE_NODE_URLS();
43640
+ init_define_ATBASH_PROD_JUDGE_PINS();
43571
43641
 
43572
43642
  // node_modules/@noble/hashes/hkdf.js
43643
+ init_define_ATBASH_DEV_JUDGE_PINS();
43573
43644
  init_define_ATBASH_PRIVATE_NODE_URLS();
43645
+ init_define_ATBASH_PROD_JUDGE_PINS();
43574
43646
  function extract(hash3, ikm, salt) {
43575
43647
  ahash(hash3);
43576
43648
  if (salt === void 0)
@@ -43611,13 +43683,19 @@ function expand2(hash3, prk, info2, length = 32) {
43611
43683
  var hkdf = (hash3, ikm, salt, info2, length) => expand2(hash3, extract(hash3, ikm, salt), info2, length);
43612
43684
 
43613
43685
  // node_modules/@noble/ciphers/aes.js
43686
+ init_define_ATBASH_DEV_JUDGE_PINS();
43614
43687
  init_define_ATBASH_PRIVATE_NODE_URLS();
43688
+ init_define_ATBASH_PROD_JUDGE_PINS();
43615
43689
 
43616
43690
  // node_modules/@noble/ciphers/_polyval.js
43691
+ init_define_ATBASH_DEV_JUDGE_PINS();
43617
43692
  init_define_ATBASH_PRIVATE_NODE_URLS();
43693
+ init_define_ATBASH_PROD_JUDGE_PINS();
43618
43694
 
43619
43695
  // node_modules/@noble/ciphers/utils.js
43696
+ init_define_ATBASH_DEV_JUDGE_PINS();
43620
43697
  init_define_ATBASH_PRIVATE_NODE_URLS();
43698
+ init_define_ATBASH_PROD_JUDGE_PINS();
43621
43699
  function isBytes3(a) {
43622
43700
  return a instanceof Uint8Array || ArrayBuffer.isView(a) && a.constructor.name === "Uint8Array" && "BYTES_PER_ELEMENT" in a && a.BYTES_PER_ELEMENT === 1;
43623
43701
  }
@@ -44210,7 +44288,9 @@ function encryptedLength(plaintextByteLength) {
44210
44288
  }
44211
44289
 
44212
44290
  // src-ts/crypto/envelope.ts
44291
+ init_define_ATBASH_DEV_JUDGE_PINS();
44213
44292
  init_define_ATBASH_PRIVATE_NODE_URLS();
44293
+ init_define_ATBASH_PROD_JUDGE_PINS();
44214
44294
  var PREFIX = "atb1";
44215
44295
  var SEPARATOR = ".";
44216
44296
  function toBase64(bytes) {
@@ -44343,7 +44423,9 @@ function signEncryptedToolCall(toolCallId, action, context, toolName, toolArgsJs
44343
44423
  }
44344
44424
 
44345
44425
  // src-ts/endpoint.ts
44426
+ init_define_ATBASH_DEV_JUDGE_PINS();
44346
44427
  init_define_ATBASH_PRIVATE_NODE_URLS();
44428
+ init_define_ATBASH_PROD_JUDGE_PINS();
44347
44429
  function buildAllowedJudgeHosts() {
44348
44430
  return /* @__PURE__ */ new Set([
44349
44431
  "atbash.ai",
@@ -44359,6 +44441,23 @@ function isAllowlistedJudgeHost(endpoint) {
44359
44441
  return false;
44360
44442
  }
44361
44443
  }
44444
+ var LOOPBACK_HOSTS = /* @__PURE__ */ new Set(["localhost", "127.0.0.1", "[::1]", "::1"]);
44445
+ var loopbackJudgePins = [];
44446
+ function setLoopbackJudgePinsForTests(keys2) {
44447
+ loopbackJudgePins = keys2.map((k) => k.trim().toLowerCase());
44448
+ }
44449
+ function judgeVerifyKeys(endpoint, configuredKey) {
44450
+ const host = new URL(endpoint).hostname.toLowerCase();
44451
+ const pins = LOOPBACK_HOSTS.has(host) ? loopbackJudgePins : native.pinnedJudgeVerifyKeys(host);
44452
+ const key3 = configuredKey?.trim().toLowerCase();
44453
+ if (pins.length === 0) return key3 ? [key3] : [];
44454
+ if (key3 && !pins.includes(key3)) {
44455
+ throw new Error(
44456
+ `[atbash] verifyPubKey ${key3} is not the response-signing key pinned for ${host}. Refusing to load \u2014 an Atbash host's replies are checked against the key built into the SDK; remove verifyPubKey, or set it to the pinned key.`
44457
+ );
44458
+ }
44459
+ return pins;
44460
+ }
44362
44461
  function validateJudgeEndpoint(judge) {
44363
44462
  const policy = judge?.policy === "self-hosted" ? "self-hosted" : "default";
44364
44463
  const candidate = judge?.endpoint?.trim() || DEFAULT_ENDPOINT;
@@ -44401,7 +44500,9 @@ function validateJudgeEndpoint(judge) {
44401
44500
  }
44402
44501
 
44403
44502
  // src-ts/errors.ts
44503
+ init_define_ATBASH_DEV_JUDGE_PINS();
44404
44504
  init_define_ATBASH_PRIVATE_NODE_URLS();
44505
+ init_define_ATBASH_PROD_JUDGE_PINS();
44405
44506
  var AtbashAPIError = class extends Error {
44406
44507
  /** HTTP status code (or 0 if the request never completed). */
44407
44508
  status;
@@ -44465,7 +44566,9 @@ function enrich(status, body, statusText, endpoint, path3) {
44465
44566
  }
44466
44567
 
44467
44568
  // src-ts/jail-hold.ts
44569
+ init_define_ATBASH_DEV_JUDGE_PINS();
44468
44570
  init_define_ATBASH_PRIVATE_NODE_URLS();
44571
+ init_define_ATBASH_PROD_JUDGE_PINS();
44469
44572
  var DEFAULTS = { ceilingMs: 3e4, pollMs: 1e3 };
44470
44573
  var holds = /* @__PURE__ */ new Map();
44471
44574
  var blockedAt = /* @__PURE__ */ new Map();
@@ -44475,7 +44578,7 @@ function isJailHeld(pubkey) {
44475
44578
  return holds.has(pubkey);
44476
44579
  }
44477
44580
  function recordBlock(pubkey) {
44478
- const now = Date.now();
44581
+ const now = performance.now();
44479
44582
  for (const [key3, at] of blockedAt) if (now - at > BLOCK_MEMORY_MS) blockedAt.delete(key3);
44480
44583
  blockedAt.set(pubkey, now);
44481
44584
  }
@@ -44521,7 +44624,9 @@ function configureJailHold(next) {
44521
44624
  }
44522
44625
 
44523
44626
  // src-ts/http/client.ts
44627
+ init_define_ATBASH_DEV_JUDGE_PINS();
44524
44628
  init_define_ATBASH_PRIVATE_NODE_URLS();
44629
+ init_define_ATBASH_PROD_JUDGE_PINS();
44525
44630
  var HttpClient = class {
44526
44631
  baseUrl;
44527
44632
  timeoutMs;
@@ -44626,7 +44731,9 @@ function classifyTransportError(err, url, method, timeoutMs) {
44626
44731
  }
44627
44732
 
44628
44733
  // src-ts/browser/keyLoader.ts
44734
+ init_define_ATBASH_DEV_JUDGE_PINS();
44629
44735
  init_define_ATBASH_PRIVATE_NODE_URLS();
44736
+ init_define_ATBASH_PROD_JUDGE_PINS();
44630
44737
  var NOT_AVAILABLE = "keyLoader is not available in the browser bundle \u2014 pass `agentKey` explicitly to Atbash.fromConfig or use `new Atbash(privkey, opts)`.";
44631
44738
  function resolveKeyPath(_input) {
44632
44739
  throw new Error(NOT_AVAILABLE);
@@ -44636,10 +44743,14 @@ function loadAgentFromFile(_keyPath) {
44636
44743
  }
44637
44744
 
44638
44745
  // src-ts/decision.ts
44746
+ init_define_ATBASH_DEV_JUDGE_PINS();
44639
44747
  init_define_ATBASH_PRIVATE_NODE_URLS();
44748
+ init_define_ATBASH_PROD_JUDGE_PINS();
44640
44749
 
44641
44750
  // src-ts/normalize.ts
44751
+ init_define_ATBASH_DEV_JUDGE_PINS();
44642
44752
  init_define_ATBASH_PRIVATE_NODE_URLS();
44753
+ init_define_ATBASH_PROD_JUDGE_PINS();
44643
44754
  function wireText(raw2, fallback = "") {
44644
44755
  if (raw2 === null || raw2 === void 0) return fallback;
44645
44756
  if (typeof raw2 === "object" || typeof raw2 === "function") return fallback;
@@ -44750,7 +44861,9 @@ function canonicalAllow(data) {
44750
44861
  }
44751
44862
 
44752
44863
  // src-ts/opentel/events.ts
44864
+ init_define_ATBASH_DEV_JUDGE_PINS();
44753
44865
  init_define_ATBASH_PRIVATE_NODE_URLS();
44866
+ init_define_ATBASH_PROD_JUDGE_PINS();
44754
44867
  var SLOW_MS = 1500;
44755
44868
  var SUCCESS_SAMPLE_RATE = 10;
44756
44869
  var logger2 = null;
@@ -44805,7 +44918,9 @@ function recordEvent(e) {
44805
44918
  }
44806
44919
 
44807
44920
  // src-ts/browser/opentel/telemetry.ts
44921
+ init_define_ATBASH_DEV_JUDGE_PINS();
44808
44922
  init_define_ATBASH_PRIVATE_NODE_URLS();
44923
+ init_define_ATBASH_PROD_JUDGE_PINS();
44809
44924
  function setupTelemetry(_config) {
44810
44925
  }
44811
44926
  function recordCall(_functionName, _source, _agentPubkey) {
@@ -44818,7 +44933,9 @@ async function shutdownTelemetry() {
44818
44933
  }
44819
44934
 
44820
44935
  // src-ts/browser/userConfig.ts
44936
+ init_define_ATBASH_DEV_JUDGE_PINS();
44821
44937
  init_define_ATBASH_PRIVATE_NODE_URLS();
44938
+ init_define_ATBASH_PROD_JUDGE_PINS();
44822
44939
  var NOT_AVAILABLE2 = "userConfig file I/O is not available in the browser bundle.";
44823
44940
  function getConfigDir() {
44824
44941
  throw new Error(NOT_AVAILABLE2);
@@ -44847,7 +44964,10 @@ function strandedAgentKey() {
44847
44964
 
44848
44965
  // src-ts/client.ts
44849
44966
  var AGENT_NOT_REGISTERED = "Agent not registered. Onboard the agent at the dashboard before submitting actions.";
44967
+ var TOOL_CALL_IDS_FOR_TESTS = /* @__PURE__ */ Symbol.for("@atbash/sdk.toolCallIdsForTests");
44850
44968
  function generateToolCallId() {
44969
+ const fixed = globalThis[TOOL_CALL_IDS_FOR_TESTS];
44970
+ if (fixed && fixed.ids.length > 0) return fixed.ids[fixed.next++ % fixed.ids.length];
44851
44971
  return `tc-${Date.now()}-${randomHex(4)}`;
44852
44972
  }
44853
44973
  function resolveConstructorChain(options) {
@@ -44884,12 +45004,21 @@ var Atbash = class _Atbash {
44884
45004
  orgName;
44885
45005
  /** Default judge response-signing pubkey, if configured (see fromConfig). */
44886
45006
  verifyPubKey;
45007
+ /**
45008
+ * The keys every judge reply must be signed by: the host's pinned keys, or
45009
+ * the configured `verifyPubKey` on a host with none. Empty means unchecked.
45010
+ */
45011
+ verifyKeys;
44887
45012
  /** Default org encryption key — see {@link AtbashOptions.orgEncryptionPubKey}. */
44888
45013
  orgEncryptionPubKey;
44889
45014
  /** When true (default), `auditToolCall` denies on any error. */
44890
45015
  failClosed;
44891
45016
  /** When true (default), an unenforced (audit-tier) answer is refused. */
44892
45017
  requireEnforcement;
45018
+ /** When true, a signed non-enforcing mode never relaxes a verdict. */
45019
+ enforceLocally;
45020
+ /** Results whose enforcement mode came signed and bound to their call. */
45021
+ modeTrusted = /* @__PURE__ */ new WeakSet();
44893
45022
  /** Overall deadline for one auditToolCall decision, in ms. */
44894
45023
  decisionTimeoutMs;
44895
45024
  /** Org key learned from the last agent-exists check, for this agent only. */
@@ -44953,9 +45082,11 @@ var Atbash = class _Atbash {
44953
45082
  this._forcedNetwork = forcedChainNetwork();
44954
45083
  this.orgName = options.orgName;
44955
45084
  this.verifyPubKey = validated.verifyPubKey ?? void 0;
45085
+ this.verifyKeys = judgeVerifyKeys(this.endpoint, this.verifyPubKey);
44956
45086
  this.orgEncryptionPubKey = options.orgEncryptionPubKey;
44957
45087
  this.failClosed = options.failClosed !== false;
44958
45088
  this.requireEnforcement = options.requireEnforcement !== false;
45089
+ this.enforceLocally = options.enforceLocally === true;
44959
45090
  this.decisionTimeoutMs = options.decisionTimeoutMs ?? DEFAULT_DECISION_TIMEOUT_MS;
44960
45091
  this.debug = options.debug === true;
44961
45092
  this.logger = options.logger ?? {};
@@ -44964,7 +45095,7 @@ var Atbash = class _Atbash {
44964
45095
  if (this.endpoint !== DEFAULT_ENDPOINT) {
44965
45096
  this.logger.warn?.("[atbash] running on non-default judge endpoint", {
44966
45097
  endpoint: this.endpoint,
44967
- verifying: this.verifyPubKey ? "with response-signature pubkey configured" : "without signature verification"
45098
+ verifying: this.verifyKeys.length > 0 ? "with response-signature pubkey configured" : "without signature verification"
44968
45099
  });
44969
45100
  }
44970
45101
  if (isAllowlistedJudgeHost(this.endpoint)) {
@@ -45002,12 +45133,12 @@ var Atbash = class _Atbash {
45002
45133
  _Atbash.environmentLogged = true;
45003
45134
  const brief = (rid) => rid ? `${rid.slice(0, 8)}\u2026` : "(unset)";
45004
45135
  this.logger.info?.(
45005
- `[atbash] environment \u2014 judge=${this.endpoint} privateChain=${brief(native.DEFAULT_PRIVATE_BLOCKCHAIN_RID)} activeChain=${brief(this.blockchainRid)} responseSignatureCheck=${this.verifyPubKey ? "on" : "off"}`,
45136
+ `[atbash] environment \u2014 judge=${this.endpoint} privateChain=${brief(native.DEFAULT_PRIVATE_BLOCKCHAIN_RID)} activeChain=${brief(this.blockchainRid)} responseSignatureCheck=${this.verifyKeys.length > 0 ? "on" : "off"}`,
45006
45137
  {
45007
45138
  judgeEndpoint: this.endpoint,
45008
45139
  privateBlockchainRid: native.DEFAULT_PRIVATE_BLOCKCHAIN_RID,
45009
45140
  activeBlockchainRid: this.blockchainRid,
45010
- responseSignatureCheck: Boolean(this.verifyPubKey)
45141
+ responseSignatureCheck: this.verifyKeys.length > 0
45011
45142
  }
45012
45143
  );
45013
45144
  }
@@ -45125,6 +45256,7 @@ config.json still holds an "agentKey" (${identity}), but a settings file no long
45125
45256
  verifyPubKey: validated.verifyPubKey ?? void 0,
45126
45257
  failClosed: options.failClosed,
45127
45258
  requireEnforcement: options.requireEnforcement,
45259
+ enforceLocally: options.enforceLocally,
45128
45260
  decisionTimeoutMs: options.decisionTimeoutMs,
45129
45261
  // ATBASH_DEBUG lets an operator turn diagnostics on without editing a
45130
45262
  // host's plugin config, which is usually the harder half.
@@ -45259,22 +45391,34 @@ config.json still holds an "agentKey" (${identity}), but a settings file no long
45259
45391
  * response bytes via the Rust core's `verifySignature`.
45260
45392
  */
45261
45393
  async judgeAction(action, context = "", options = {}) {
45394
+ return this.judgeTracked(action, context, options, false);
45395
+ }
45396
+ /**
45397
+ * judgeAction, optionally asking the judge for the true verdict and the
45398
+ * organisation's enforcement mode so this client applies the mode itself.
45399
+ *
45400
+ * Only auditToolCall opts in: judgeAction's callers keep the server-side
45401
+ * downgrade they gate on today.
45402
+ *
45403
+ * @param clientEnforces - Send `X-Atbash-Client-Enforcement` when the reply can be trusted.
45404
+ */
45405
+ judgeTracked(action, context, options, clientEnforces) {
45262
45406
  return this.track("judgeAction", this.auth.pubkey, async () => {
45263
45407
  try {
45264
- return await this._judgeAction(action, context, options);
45408
+ return await this._judgeAction(action, context, options, clientEnforces);
45265
45409
  } catch (err) {
45266
45410
  if (!isEncryptionStateMismatch(err)) throw err;
45267
45411
  this._orgKeyFromChain = null;
45268
- return await this._judgeAction(action, context, options);
45412
+ return await this._judgeAction(action, context, options, clientEnforces);
45269
45413
  }
45270
45414
  });
45271
45415
  }
45272
- async _judgeAction(action, context, options) {
45416
+ async _judgeAction(action, context, options, clientEnforces = false) {
45273
45417
  if (!action?.trim()) {
45274
45418
  throw new Error("action is required and cannot be empty.");
45275
45419
  }
45276
45420
  if (isJailHeld(this.auth.pubkey)) return this.localJailBlock();
45277
- const startedAt = Date.now();
45421
+ const startedAt = performance.now();
45278
45422
  let chainOpts = options.chainOpts;
45279
45423
  if (options.orgName && this._explicitChain) {
45280
45424
  chainOpts = options.chainOpts ?? {
@@ -45331,17 +45475,23 @@ config.json still holds an "agentKey" (${identity}), but a settings file no long
45331
45475
  if (options.toolArgsJson) body.tool_args_json = options.toolArgsJson;
45332
45476
  if (options.resolved) body.resolved = options.resolved;
45333
45477
  if (options.mode) body.mode = options.mode;
45478
+ const verifyKeys = this.effectiveVerifyKeys(options.verifyPubKey);
45479
+ const optIn = clientEnforces && (verifyKeys.length > 0 || this.enforceLocally);
45480
+ const optInValue = this.enforceLocally ? "strict" : "1";
45334
45481
  let resp;
45335
45482
  try {
45336
- resp = await this.http.post("/api/v1/judge", body);
45483
+ resp = await this.http.post(
45484
+ "/api/v1/judge",
45485
+ body,
45486
+ optIn ? { "X-Atbash-Client-Enforcement": optInValue } : void 0
45487
+ );
45337
45488
  } catch (err) {
45338
45489
  throw this.transportError(err);
45339
45490
  }
45340
45491
  if (!resp.ok) throw await this.httpError(resp);
45341
45492
  const bodyBytes = Buffer.from(await resp.arrayBuffer());
45342
- const verifyPubKey = this.effectiveVerifyKey(options.verifyPubKey);
45343
- if (verifyPubKey !== void 0) {
45344
- verifyResponseSignature(bodyBytes, resp, verifyPubKey);
45493
+ if (verifyKeys.length > 0) {
45494
+ verifyResponseSignature(bodyBytes, resp, verifyKeys);
45345
45495
  }
45346
45496
  const parsed = tryParseJson(bodyBytes.toString("utf-8"));
45347
45497
  if (!isRecord2(parsed)) {
@@ -45352,6 +45502,12 @@ config.json still holds an "agentKey" (${identity}), but a settings file no long
45352
45502
  const data = parsed;
45353
45503
  const rawScore = data.score;
45354
45504
  const score = typeof rawScore === "number" && Number.isInteger(rawScore) && rawScore >= 1 && rawScore <= 10 ? rawScore : void 0;
45505
+ const statedId = wireText(data.tool_call_id);
45506
+ const statedJudgment = wireText(data.judgment_id);
45507
+ const statedStatus = wireText(data.on_chain_status);
45508
+ const statedJudgeStatus = typeof data.status === "string" ? data.status : "";
45509
+ const boundToCall = (statedId === logResult.toolCallId || statedId === judgmentId) && (!statedJudgment || statedJudgment === judgmentId);
45510
+ const signatureChecked = verifyKeys.length > 0;
45355
45511
  const result = {
45356
45512
  verdict: normalizeVerdict(data.verdict),
45357
45513
  allow: this.executable(data),
@@ -45361,30 +45517,65 @@ config.json still holds an "agentKey" (${identity}), but a settings file no long
45361
45517
  provider: wireText(data.provider),
45362
45518
  latencyMs: wireNumber(data.latency_ms),
45363
45519
  toolCallId: wireText(data.tool_call_id, logResult.toolCallId),
45520
+ ...wireText(data.judgment_id) ? { judgmentId: wireText(data.judgment_id) } : {},
45364
45521
  onChain: Boolean(data.on_chain),
45522
+ // Only a stated boolean is a statement: `onChain` above reads silence as false.
45523
+ ...typeof data.on_chain === "boolean" ? {
45524
+ record: {
45525
+ onChain: data.on_chain,
45526
+ ...statedStatus ? { status: statedStatus } : {},
45527
+ boundToCall,
45528
+ signatureChecked,
45529
+ ...statedJudgeStatus ? { judgeStatus: statedJudgeStatus } : {},
45530
+ // A judge status marks a reply that carries no verdict: a shadow
45531
+ // ack, or an answer that was only logged.
45532
+ verdictRecorded: data.on_chain && boundToCall && signatureChecked && !statedJudgeStatus
45533
+ }
45534
+ } : {},
45365
45535
  enforced: Boolean(data.enforced),
45366
45536
  enforcementMode: wireText(data.enforcement_mode),
45367
45537
  status: wireText(data.status),
45368
45538
  score,
45369
45539
  refusal: explicitRefusal(data)
45370
45540
  };
45371
- return this.applyJailHold(result, startedAt);
45541
+ if (optIn) {
45542
+ const echo = data.client_enforcement;
45543
+ if (echo !== void 0 && echo !== optInValue || echo === void 0 && this.enforceLocally) {
45544
+ throw new SignatureVerificationError(
45545
+ "the reply does not confirm the enforcement this client asked for"
45546
+ );
45547
+ }
45548
+ if (verifyKeys.length > 0) {
45549
+ if (statedId && statedId !== logResult.toolCallId && statedId !== judgmentId || statedJudgment && statedJudgment !== judgmentId) {
45550
+ throw new SignatureVerificationError(
45551
+ `the signed reply is for call ${statedJudgment || statedId}, not this one`
45552
+ );
45553
+ }
45554
+ if (statedId && echo === optInValue) this.modeTrusted.add(result);
45555
+ }
45556
+ }
45557
+ return this.applyJailHold(result, startedAt, statedStatus);
45372
45558
  }
45373
45559
  /**
45374
- * Start a local hold on an enforced, on-chain BLOCK (the verdict that jails).
45375
- * Refuse any other result that lands while the agent is held, or whose
45376
- * request was already in flight when the block arrived: the server judged it
45377
- * on pre-jail state.
45560
+ * Start a local hold on an enforced BLOCK that jails: one already on chain,
45561
+ * or one the judge answered before its chain write landed
45562
+ * (`on_chain_status: "pending"`), which jails once it lands. Refuse any other
45563
+ * result that lands while the agent is held, or whose request was already in
45564
+ * flight when the block arrived: the server judged it on pre-jail state.
45565
+ *
45566
+ * @param onChainStatus - The reply's `on_chain_status`; empty when absent.
45378
45567
  */
45379
- applyJailHold(result, startedAt) {
45568
+ applyJailHold(result, startedAt, onChainStatus = "") {
45380
45569
  const pubkey = this.auth.pubkey;
45381
- if (result.verdict === "BLOCK" && result.enforced && result.onChain) {
45570
+ if (result.verdict === "BLOCK" && result.enforced) {
45382
45571
  recordBlock(pubkey);
45383
- holdJail(
45384
- pubkey,
45385
- () => this.getAgentPolicy(pubkey).then((p) => p.isJailed),
45386
- () => this.logger.warn?.("[atbash] local jail hold released: the chain did not confirm the jail in time")
45387
- );
45572
+ if (result.onChain || onChainStatus === "pending") {
45573
+ holdJail(
45574
+ pubkey,
45575
+ () => this.getAgentPolicy(pubkey).then((p) => p.isJailed),
45576
+ () => this.logger.warn?.("[atbash] local jail hold released: the chain did not confirm the jail in time")
45577
+ );
45578
+ }
45388
45579
  return result;
45389
45580
  }
45390
45581
  return isJailHeld(pubkey) || blockedSince(pubkey, startedAt) ? this.localJailBlock(result.toolCallId) : result;
@@ -45395,7 +45586,7 @@ config.json still holds an "agentKey" (${identity}), but a settings file no long
45395
45586
  verdict: "BLOCK",
45396
45587
  allow: false,
45397
45588
  actionType: "block",
45398
- reason: "Agent is jailed. All actions are blocked until the organization owner unjails this agent.",
45589
+ reason: `Agent is jailed. All actions are blocked until the organization owner unjails this agent at ${this.endpoint.replace(/\/+$/, "")}/risk-engine/agents.`,
45399
45590
  confidence: 1,
45400
45591
  provider: "policy",
45401
45592
  latencyMs: 0,
@@ -45439,13 +45630,18 @@ config.json still holds an "agentKey" (${identity}), but a settings file no long
45439
45630
  try {
45440
45631
  this.logger.info?.("[atbash] judge API called", { tool: toolName });
45441
45632
  const result = await withDeadline(
45442
- this.judgeAction(actionText, contextText, {
45443
- toolName,
45444
- toolArgsJson: argsJson,
45445
- orgName: this.orgName,
45446
- // Passed through unredacted — caller vouches for the contents.
45447
- resolved: input.resolved
45448
- }),
45633
+ this.judgeTracked(
45634
+ actionText,
45635
+ contextText,
45636
+ {
45637
+ toolName,
45638
+ toolArgsJson: argsJson,
45639
+ orgName: this.orgName,
45640
+ // Passed through unredacted — caller vouches for the contents.
45641
+ resolved: input.resolved
45642
+ },
45643
+ true
45644
+ ),
45449
45645
  this.decisionTimeoutMs
45450
45646
  );
45451
45647
  return this.decide(result);
@@ -45455,7 +45651,7 @@ config.json still holds an "agentKey" (${identity}), but a settings file no long
45455
45651
  return {
45456
45652
  allow: false,
45457
45653
  verdict: "ERROR",
45458
- reason: `The judge's reply failed its signature check (${errorMessage(err)}), so it was not trusted.`
45654
+ reason: `The judge's reply was not trusted (${errorMessage(err)}).`
45459
45655
  };
45460
45656
  }
45461
45657
  if (err instanceof JudgeRefusalError || err instanceof AtbashAPIError && isRefusalStatus(err.status)) {
@@ -45465,20 +45661,20 @@ config.json still holds an "agentKey" (${identity}), but a settings file no long
45465
45661
  }
45466
45662
  }
45467
45663
  /**
45468
- * The verify key for one call (R4, governor tier-2 review). A per-call key
45469
- * may only narrow what the client accepts: on a client pinned to a judge
45470
- * key it must be that same key, never a replacement; on an unpinned client
45471
- * it adds the check.
45664
+ * The verify keys for one call (R4, governor tier-2 review). A per-call key
45665
+ * may only narrow what the client accepts: on a client pinned to judge keys
45666
+ * it must be one of them, never a replacement; on an unpinned client it
45667
+ * adds the check.
45472
45668
  */
45473
- effectiveVerifyKey(perCall) {
45474
- if (perCall === void 0) return this.verifyPubKey;
45669
+ effectiveVerifyKeys(perCall) {
45670
+ if (perCall === void 0) return this.verifyKeys;
45475
45671
  const key3 = perCall.trim().toLowerCase();
45476
- if (this.verifyPubKey !== void 0 && key3 !== this.verifyPubKey) {
45672
+ if (this.verifyKeys.length > 0 && !this.verifyKeys.includes(key3)) {
45477
45673
  throw new SignatureVerificationError(
45478
45674
  "a per-call verifyPubKey cannot replace the judge key this client is pinned to"
45479
45675
  );
45480
45676
  }
45481
- return key3;
45677
+ return [key3];
45482
45678
  }
45483
45679
  /**
45484
45680
  * Collapse a judge result into a {@link Decision}. The most restrictive
@@ -45490,7 +45686,12 @@ config.json still holds an "agentKey" (${identity}), but a settings file no long
45490
45686
  * never overrides a refusal.
45491
45687
  */
45492
45688
  decide(result) {
45493
- const inner = this.decideInner(result);
45689
+ const decided = this.applyMode(result);
45690
+ const inner = {
45691
+ ...decided,
45692
+ ...result.judgmentId ? { judgmentId: result.judgmentId } : {},
45693
+ ...result.record ? { record: result.record } : {}
45694
+ };
45494
45695
  if (!result.enforcementMode) return inner;
45495
45696
  return {
45496
45697
  ...inner,
@@ -45498,6 +45699,50 @@ config.json still holds an "agentKey" (${identity}), but a settings file no long
45498
45699
  enforcementMode: result.enforcementMode
45499
45700
  };
45500
45701
  }
45702
+ /**
45703
+ * Apply the organisation's enforcement mode to the judge's true verdict.
45704
+ *
45705
+ * Only a mode that arrived signed and bound to this call counts; a missing,
45706
+ * unsigned or unknown mode, or enforceLocally, means enforce. Under
45707
+ * `shadow`, `monitor` or `off` a BLOCK or HOLD runs, reported in
45708
+ * `wouldVerdict`. An ERROR stays an error: it is not a verdict.
45709
+ */
45710
+ applyMode(result) {
45711
+ const mode = result.enforcementMode;
45712
+ const relaxes = this.modeTrusted.has(result) && (mode === "shadow" || mode === "monitor" || mode === "off");
45713
+ if (result.status === "shadow_recorded" && result.verdict === "No verdict") {
45714
+ if (!relaxes || this.enforceLocally) {
45715
+ return {
45716
+ allow: false,
45717
+ verdict: "ERROR",
45718
+ reason: "Atbash recorded this action without judging it (the organisation is not enforcing), and this client requires a verdict.",
45719
+ toolCallId: result.toolCallId
45720
+ };
45721
+ }
45722
+ this.logger.info?.(`[atbash] recorded in ${mode} mode; not judged yet`, {
45723
+ toolCallId: result.toolCallId
45724
+ });
45725
+ return {
45726
+ allow: true,
45727
+ verdict: "ALLOW",
45728
+ reason: `Recorded in ${mode} mode; the verdict appears in the dashboard.`,
45729
+ toolCallId: result.toolCallId
45730
+ };
45731
+ }
45732
+ const inner = this.decideInner(result);
45733
+ if (!relaxes || this.enforceLocally || inner.allow) return inner;
45734
+ if (inner.verdict !== "BLOCK" && inner.verdict !== "HOLD") return inner;
45735
+ this.logger.warn?.(`[atbash] would ${inner.verdict.toLowerCase()} (${mode} mode): ${inner.reason ?? ""}`, {
45736
+ toolCallId: inner.toolCallId
45737
+ });
45738
+ return {
45739
+ allow: true,
45740
+ verdict: "ALLOW",
45741
+ reason: inner.reason,
45742
+ toolCallId: inner.toolCallId,
45743
+ wouldVerdict: inner.verdict
45744
+ };
45745
+ }
45501
45746
  decideInner(result) {
45502
45747
  const toolCallId = result.toolCallId;
45503
45748
  const deny = (verdict, reason) => ({
@@ -45533,7 +45778,9 @@ config.json still holds an "agentKey" (${identity}), but a settings file no long
45533
45778
  return {
45534
45779
  allow: false,
45535
45780
  verdict: "ERROR",
45536
- reason: "Atbash logged this action but did not check it (audit-tier plan), and this client requires a checked decision. Upgrade the plan, or set requireEnforcement: false for log-only mode.",
45781
+ // The judge's own reason says why it did not check (the plan, a
45782
+ // deactivated agent); a fixed "audit-tier plan" hid which.
45783
+ reason: result.reason ? `Atbash did not check this action, and this client requires a checked decision. The judge said: ${result.reason}` : "Atbash logged this action but did not check it (audit-tier plan), and this client requires a checked decision. Upgrade the plan, or set requireEnforcement: false for log-only mode.",
45537
45784
  toolCallId
45538
45785
  };
45539
45786
  }
@@ -45623,32 +45870,52 @@ config.json still holds an "agentKey" (${identity}), but a settings file no long
45623
45870
  const pk = agentPubkey ?? this.auth.pubkey;
45624
45871
  return this.track("getJudgmentStatus", pk, async () => {
45625
45872
  const brid = await this.callBrid(chainOpts);
45873
+ const optIn = this.verifyKeys.length > 0 || this.enforceLocally;
45874
+ const optInValue = this.enforceLocally ? "strict" : "1";
45626
45875
  const resp = await this.http.get(
45627
45876
  "/api/v1/judge",
45628
45877
  { tool_call_id: judgmentId, agent_pubkey: pk, brid },
45629
- this.authHeaders(brid)
45878
+ {
45879
+ ...this.authHeaders(brid),
45880
+ ...optIn ? { "X-Atbash-Client-Enforcement": optInValue } : {}
45881
+ }
45630
45882
  );
45631
45883
  await this.raiseIfError(resp);
45632
45884
  const bytes = Buffer.from(await resp.arrayBuffer());
45633
- if (this.verifyPubKey !== void 0) {
45634
- verifyResponseSignature(bytes, resp, this.verifyPubKey);
45885
+ if (this.verifyKeys.length > 0) {
45886
+ verifyResponseSignature(bytes, resp, this.verifyKeys);
45635
45887
  }
45636
45888
  const parsed = tryParseJson(bytes.toString("utf-8"));
45637
45889
  const data = isRecord2(parsed) ? parsed : {};
45638
- const rawId = data.tool_call_id ?? data.judgmentId;
45890
+ const rawId = data.tool_call_id;
45639
45891
  const statedId = wireText(rawId);
45640
45892
  const sameCall = rawId === void 0 || rawId === null || statedId === judgmentId;
45641
- return {
45893
+ let modeTrusted = false;
45894
+ if (optIn) {
45895
+ const echo = data.client_enforcement;
45896
+ if (echo !== void 0 && echo !== optInValue || echo === void 0 && this.enforceLocally) {
45897
+ throw new SignatureVerificationError(
45898
+ "the status does not confirm the enforcement this client asked for"
45899
+ );
45900
+ }
45901
+ modeTrusted = this.verifyKeys.length > 0 && echo === optInValue && statedId === judgmentId;
45902
+ }
45903
+ const status = {
45642
45904
  status: normalizeStatus(data.status),
45643
45905
  verdict: normalizeVerdict(data.verdict),
45644
45906
  allow: sameCall && this.executable(data),
45645
45907
  reason: wireText(data.reason),
45646
45908
  judgmentId: statedId || judgmentId,
45647
- onChain: optBool(data.onChain),
45648
- cached: optBool(data.cached),
45649
- // The Dashboard sends response_time_ms; responseTimeMs is the spec name.
45650
- responseTimeMs: optNumber(data.responseTimeMs ?? data.response_time_ms)
45909
+ responseTimeMs: optNumber(data.response_time_ms)
45651
45910
  };
45911
+ const mode = wireText(data.enforcement_mode);
45912
+ if (!modeTrusted || this.enforceLocally || !(mode === "shadow" || mode === "monitor" || mode === "off") || status.verdict !== "BLOCK" && status.verdict !== "HOLD") {
45913
+ return status;
45914
+ }
45915
+ this.logger.warn?.(`[atbash] would ${status.verdict.toLowerCase()} (${mode} mode): ${status.reason}`, {
45916
+ toolCallId: judgmentId
45917
+ });
45918
+ return { ...status, verdict: "ALLOW", allow: true, wouldVerdict: status.verdict };
45652
45919
  });
45653
45920
  }
45654
45921
  /* ── risk-engine queries (action-dispatched GET) ───────────────────────── */
@@ -46150,14 +46417,14 @@ async function withDeadline(p, ms) {
46150
46417
  clearTimeout(timer);
46151
46418
  }
46152
46419
  }
46153
- function verifyResponseSignature(bodyBytes, resp, verifyPubKey) {
46420
+ function verifyResponseSignature(bodyBytes, resp, verifyKeys) {
46154
46421
  const sig = resp.headers.get("X-Atbash-Signature");
46155
46422
  if (!sig) {
46156
46423
  throw new SignatureVerificationError("missing X-Atbash-Signature header");
46157
46424
  }
46158
- let ok;
46425
+ let ok = false;
46159
46426
  try {
46160
- ok = native.verifySignature(bodyBytes, sig, verifyPubKey);
46427
+ ok = verifyKeys.some((key3) => native.verifySignature(bodyBytes, sig, key3));
46161
46428
  } catch (err) {
46162
46429
  throw new SignatureVerificationError(
46163
46430
  `signature verification threw: ${errorMessage(err)}`
@@ -46249,10 +46516,6 @@ function optNumber(v) {
46249
46516
  const n = Number(v);
46250
46517
  return Number.isFinite(n) ? n : void 0;
46251
46518
  }
46252
- function optBool(v) {
46253
- if (v === null || v === void 0) return void 0;
46254
- return Boolean(v);
46255
- }
46256
46519
  function tryParseJson(text) {
46257
46520
  try {
46258
46521
  return JSON.parse(text);
@@ -46298,7 +46561,9 @@ function truncate(text, limit = MAX_ACTION_LEN) {
46298
46561
  }
46299
46562
 
46300
46563
  // src-ts/browser/key-path.ts
46564
+ init_define_ATBASH_DEV_JUDGE_PINS();
46301
46565
  init_define_ATBASH_PRIVATE_NODE_URLS();
46566
+ init_define_ATBASH_PROD_JUDGE_PINS();
46302
46567
  var KEY_FILENAMES = ["guard-client-key", "atbash-client-key"];
46303
46568
  var unavailable = (name2) => {
46304
46569
  throw new Error(`${name2} is not available in the browser bundle`);
@@ -46311,7 +46576,9 @@ function chooseKeyPath(_input, _exists) {
46311
46576
  }
46312
46577
 
46313
46578
  // src-ts/redact.ts
46579
+ init_define_ATBASH_DEV_JUDGE_PINS();
46314
46580
  init_define_ATBASH_PRIVATE_NODE_URLS();
46581
+ init_define_ATBASH_PROD_JUDGE_PINS();
46315
46582
  function redactJsonStrings(value) {
46316
46583
  if (typeof value === "string") {
46317
46584
  return native.redactSecrets(value).redacted;
@@ -46330,7 +46597,9 @@ function redactJsonStrings(value) {
46330
46597
  }
46331
46598
 
46332
46599
  // src-ts/signature.ts
46600
+ init_define_ATBASH_DEV_JUDGE_PINS();
46333
46601
  init_define_ATBASH_PRIVATE_NODE_URLS();
46602
+ init_define_ATBASH_PROD_JUDGE_PINS();
46334
46603
  function verifyJudgeResponseSignature(bodyBytes, signatureHex, pubKeyHex) {
46335
46604
  if (!signatureHex) {
46336
46605
  return { ok: false, reason: "missing X-Atbash-Signature header" };
@@ -46353,7 +46622,9 @@ function verifyJudgeResponseSignature(bodyBytes, signatureHex, pubKeyHex) {
46353
46622
  }
46354
46623
 
46355
46624
  // src-ts/memory/boot-sync-message.ts
46625
+ init_define_ATBASH_DEV_JUDGE_PINS();
46356
46626
  init_define_ATBASH_PRIVATE_NODE_URLS();
46627
+ init_define_ATBASH_PROD_JUDGE_PINS();
46357
46628
  var BOOT_SYNC_HINT = "check the chain endpoint and orgName if the cause above does not explain it";
46358
46629
  function bootSyncFailureLine(cause) {
46359
46630
  const reason = cause instanceof Error ? cause.message : String(cause);
@@ -46365,10 +46636,14 @@ function bootSyncFailureLine(cause) {
46365
46636
  }
46366
46637
 
46367
46638
  // src-ts/memory/index.ts
46639
+ init_define_ATBASH_DEV_JUDGE_PINS();
46368
46640
  init_define_ATBASH_PRIVATE_NODE_URLS();
46641
+ init_define_ATBASH_PROD_JUDGE_PINS();
46369
46642
 
46370
46643
  // src-ts/browser/memory-crypto.ts
46644
+ init_define_ATBASH_DEV_JUDGE_PINS();
46371
46645
  init_define_ATBASH_PRIVATE_NODE_URLS();
46646
+ init_define_ATBASH_PROD_JUDGE_PINS();
46372
46647
  var { Buffer: Buffer4 } = index;
46373
46648
  var HKDF_INFO = new TextEncoder().encode("atbash:memory-encryption");
46374
46649
  var KEY_LEN = 32;
@@ -46443,7 +46718,9 @@ async function decryptMemoryContent2(ciphertext, nonce, key3) {
46443
46718
  }
46444
46719
 
46445
46720
  // src-ts/browser/memory-scan.ts
46721
+ init_define_ATBASH_DEV_JUDGE_PINS();
46446
46722
  init_define_ATBASH_PRIVATE_NODE_URLS();
46723
+ init_define_ATBASH_PROD_JUDGE_PINS();
46447
46724
  var STUB_MSG2 = "not available in @atbash/sdk browser bundle \u2014 scan memory server-side";
46448
46725
  async function scanMemory(_entry, _auth, _opts) {
46449
46726
  throw new Error(`scanMemory ${STUB_MSG2}`);
@@ -46453,7 +46730,9 @@ async function scanMemoryBatch(_entries, _auth, _opts) {
46453
46730
  }
46454
46731
 
46455
46732
  // src-ts/browser/memory-chain.ts
46733
+ init_define_ATBASH_DEV_JUDGE_PINS();
46456
46734
  init_define_ATBASH_PRIVATE_NODE_URLS();
46735
+ init_define_ATBASH_PROD_JUDGE_PINS();
46457
46736
  var STUB_MSG3 = "not available in @atbash/sdk browser bundle \u2014 commit/rollback memory server-side";
46458
46737
  async function commitMemoryVersion(_plaintext, _auth, _opts) {
46459
46738
  throw new Error(`commitMemoryVersion ${STUB_MSG3}`);
@@ -46481,7 +46760,9 @@ async function rollbackMemory(_toId, _reason, _auth, _opts) {
46481
46760
  }
46482
46761
 
46483
46762
  // src-ts/browser/memory-classifier.ts
46763
+ init_define_ATBASH_DEV_JUDGE_PINS();
46484
46764
  init_define_ATBASH_PRIVATE_NODE_URLS();
46765
+ init_define_ATBASH_PROD_JUDGE_PINS();
46485
46766
  var STUB_MSG4 = "not available in @atbash/sdk browser bundle \u2014 classify memory writes server-side";
46486
46767
  var DEFAULT_MEMORY_WRITE_TOOL_NAMES = [
46487
46768
  "write",
@@ -46504,14 +46785,18 @@ function classifyMemoryWrite(_event, _ctx, _opts = {}) {
46504
46785
  }
46505
46786
 
46506
46787
  // src-ts/browser/memory-guard.ts
46788
+ init_define_ATBASH_DEV_JUDGE_PINS();
46507
46789
  init_define_ATBASH_PRIVATE_NODE_URLS();
46790
+ init_define_ATBASH_PROD_JUDGE_PINS();
46508
46791
  var STUB_MSG5 = "not available in @atbash/sdk browser bundle \u2014 guard memory writes agent-side";
46509
46792
  async function guardMemoryWrite(_input) {
46510
46793
  throw new Error(`guardMemoryWrite ${STUB_MSG5}`);
46511
46794
  }
46512
46795
 
46513
46796
  // src-ts/browser/memory-slot.ts
46797
+ init_define_ATBASH_DEV_JUDGE_PINS();
46514
46798
  init_define_ATBASH_PRIVATE_NODE_URLS();
46799
+ init_define_ATBASH_PROD_JUDGE_PINS();
46515
46800
  var unavailable2 = (name2) => {
46516
46801
  throw new Error(`${name2} is not available in the browser bundle`);
46517
46802
  };
@@ -46520,7 +46805,9 @@ function memorySlotOf(_target, _home, _root2, _extraHomes, _p) {
46520
46805
  }
46521
46806
 
46522
46807
  // src-ts/memory/sync.ts
46808
+ init_define_ATBASH_DEV_JUDGE_PINS();
46523
46809
  init_define_ATBASH_PRIVATE_NODE_URLS();
46810
+ init_define_ATBASH_PROD_JUDGE_PINS();
46524
46811
  var MemoryIntegrityError = class extends Error {
46525
46812
  constructor(id, reason) {
46526
46813
  super(`memory integrity check failed on id ${id}: ${reason}`);
@@ -46553,7 +46840,9 @@ async function syncLocalMemory(auth, pointer, opts = {}) {
46553
46840
  }
46554
46841
 
46555
46842
  // src-ts/browser/memory-pointer-store.ts
46843
+ init_define_ATBASH_DEV_JUDGE_PINS();
46556
46844
  init_define_ATBASH_PRIVATE_NODE_URLS();
46845
+ init_define_ATBASH_PROD_JUDGE_PINS();
46557
46846
  var unavailable3 = (name2) => {
46558
46847
  throw new Error(`${name2} is not available in the browser bundle`);
46559
46848
  };
@@ -46572,7 +46861,9 @@ function defaultPointerPath(_workspaceDir) {
46572
46861
  }
46573
46862
 
46574
46863
  // src-ts/browser/memory-file-logger.ts
46864
+ init_define_ATBASH_DEV_JUDGE_PINS();
46575
46865
  init_define_ATBASH_PRIVATE_NODE_URLS();
46866
+ init_define_ATBASH_PROD_JUDGE_PINS();
46576
46867
  var unavailable4 = (name2) => {
46577
46868
  throw new Error(`${name2} is not available in the browser bundle`);
46578
46869
  };
@@ -46584,7 +46875,9 @@ function defaultPluginLogPath(_workspaceDir) {
46584
46875
  }
46585
46876
 
46586
46877
  // src-ts/browser/memory-read-classifier.ts
46878
+ init_define_ATBASH_DEV_JUDGE_PINS();
46587
46879
  init_define_ATBASH_PRIVATE_NODE_URLS();
46880
+ init_define_ATBASH_PROD_JUDGE_PINS();
46588
46881
  var STUB_MSG6 = "not available in @atbash/sdk browser bundle \u2014 classify memory reads server-side";
46589
46882
  var DEFAULT_MEMORY_READ_TOOL_NAMES = [
46590
46883
  "memory_search",
@@ -46595,7 +46888,9 @@ function classifyMemoryRead(_event, _ctx, _opts = {}) {
46595
46888
  }
46596
46889
 
46597
46890
  // src-ts/browser/memory-guard-manager.ts
46891
+ init_define_ATBASH_DEV_JUDGE_PINS();
46598
46892
  init_define_ATBASH_PRIVATE_NODE_URLS();
46893
+ init_define_ATBASH_PROD_JUDGE_PINS();
46599
46894
  var unavailable5 = (name2) => {
46600
46895
  throw new Error(`${name2} is not available in the browser bundle`);
46601
46896
  };
@@ -46734,6 +47029,7 @@ export {
46734
47029
  isEnvelope,
46735
47030
  isJailHeld,
46736
47031
  isValidPrivateKey2 as isValidPrivateKey,
47032
+ judgeVerifyKeys,
46737
47033
  keyFingerprintOf,
46738
47034
  keyPathCandidates,
46739
47035
  loadAgent2 as loadAgent,
@@ -46760,6 +47056,7 @@ export {
46760
47056
  saveUserConfig,
46761
47057
  scanMemory,
46762
47058
  scanMemoryBatch,
47059
+ setLoopbackJudgePinsForTests,
46763
47060
  setupTelemetry,
46764
47061
  shutdownTelemetry,
46765
47062
  signEncryptedToolCall,