@atbash/sdk 0.10.0-dev.0 → 0.10.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
@@ -10,6 +10,9 @@ var __require = /* @__PURE__ */ ((x) => typeof require !== "undefined" ? require
10
10
  if (typeof require !== "undefined") return require.apply(this, arguments);
11
11
  throw Error('Dynamic require of "' + x + '" is not supported');
12
12
  });
13
+ var __esm = (fn, res) => function __init() {
14
+ return fn && (res = (0, fn[__getOwnPropNames(fn)[0]])(fn = 0)), res;
15
+ };
13
16
  var __commonJS = (cb, mod2) => function __require2() {
14
17
  return mod2 || (0, cb[__getOwnPropNames(cb)[0]])((mod2 = { exports: {} }).exports, mod2), mod2.exports;
15
18
  };
@@ -30,10 +33,28 @@ var __toESM = (mod2, isNodeMode, target) => (target = mod2 != null ? __create(__
30
33
  mod2
31
34
  ));
32
35
 
36
+ // <define:__ATBASH_CHROMIA_NODE_URLS__>
37
+ var define_ATBASH_CHROMIA_NODE_URLS_default;
38
+ var init_define_ATBASH_CHROMIA_NODE_URLS = __esm({
39
+ "<define:__ATBASH_CHROMIA_NODE_URLS__>"() {
40
+ define_ATBASH_CHROMIA_NODE_URLS_default = ["https://node0.testnet.chromia.com:7740", "https://node1.testnet.chromia.com:7740"];
41
+ }
42
+ });
43
+
44
+ // <define:__ATBASH_PRIVATE_NODE_URLS__>
45
+ var define_ATBASH_PRIVATE_NODE_URLS_default;
46
+ var init_define_ATBASH_PRIVATE_NODE_URLS = __esm({
47
+ "<define:__ATBASH_PRIVATE_NODE_URLS__>"() {
48
+ define_ATBASH_PRIVATE_NODE_URLS_default = ["https://node0-pvn-testnet.dynamic.chromia.dev:7740", "https://node1-pvn-testnet.dynamic.chromia.dev:7740", "https://node2-pvn-testnet.dynamic.chromia.dev:7740"];
49
+ }
50
+ });
51
+
33
52
  // (disabled):node_modules/buffer/index.js
34
53
  var require_buffer = __commonJS({
35
54
  "(disabled):node_modules/buffer/index.js"() {
36
55
  "use strict";
56
+ init_define_ATBASH_CHROMIA_NODE_URLS();
57
+ init_define_ATBASH_PRIVATE_NODE_URLS();
37
58
  }
38
59
  });
39
60
 
@@ -41,6 +62,8 @@ var require_buffer = __commonJS({
41
62
  var require_bn = __commonJS({
42
63
  "node_modules/bn.js/lib/bn.js"(exports, module) {
43
64
  "use strict";
65
+ init_define_ATBASH_CHROMIA_NODE_URLS();
66
+ init_define_ATBASH_PRIVATE_NODE_URLS();
44
67
  (function(module2, exports2) {
45
68
  "use strict";
46
69
  function assert2(val, msg) {
@@ -2858,7 +2881,29 @@ var require_bn = __commonJS({
2858
2881
  }
2859
2882
  });
2860
2883
 
2884
+ // src-ts/index.ts
2885
+ init_define_ATBASH_CHROMIA_NODE_URLS();
2886
+ init_define_ATBASH_PRIVATE_NODE_URLS();
2887
+
2888
+ // src-ts/browser/native.ts
2889
+ init_define_ATBASH_CHROMIA_NODE_URLS();
2890
+ init_define_ATBASH_PRIVATE_NODE_URLS();
2891
+
2892
+ // node_modules/@noble/curves/secp256k1.js
2893
+ init_define_ATBASH_CHROMIA_NODE_URLS();
2894
+ init_define_ATBASH_PRIVATE_NODE_URLS();
2895
+
2896
+ // node_modules/@noble/hashes/sha2.js
2897
+ init_define_ATBASH_CHROMIA_NODE_URLS();
2898
+ init_define_ATBASH_PRIVATE_NODE_URLS();
2899
+
2900
+ // node_modules/@noble/hashes/_md.js
2901
+ init_define_ATBASH_CHROMIA_NODE_URLS();
2902
+ init_define_ATBASH_PRIVATE_NODE_URLS();
2903
+
2861
2904
  // node_modules/@noble/hashes/utils.js
2905
+ init_define_ATBASH_CHROMIA_NODE_URLS();
2906
+ init_define_ATBASH_PRIVATE_NODE_URLS();
2862
2907
  function isBytes(a) {
2863
2908
  return a instanceof Uint8Array || ArrayBuffer.isView(a) && a.constructor.name === "Uint8Array" && "BYTES_PER_ELEMENT" in a && a.BYTES_PER_ELEMENT === 1;
2864
2909
  }
@@ -3279,7 +3324,13 @@ var sha256 = /* @__PURE__ */ createHasher(
3279
3324
  /* @__PURE__ */ oidNist(1)
3280
3325
  );
3281
3326
 
3327
+ // node_modules/@noble/curves/abstract/curve.js
3328
+ init_define_ATBASH_CHROMIA_NODE_URLS();
3329
+ init_define_ATBASH_PRIVATE_NODE_URLS();
3330
+
3282
3331
  // node_modules/@noble/curves/utils.js
3332
+ init_define_ATBASH_CHROMIA_NODE_URLS();
3333
+ init_define_ATBASH_PRIVATE_NODE_URLS();
3283
3334
  var abytes2 = (value, length, title) => abytes(value, length, title);
3284
3335
  var anumber2 = anumber;
3285
3336
  var bytesToHex2 = bytesToHex;
@@ -3432,6 +3483,8 @@ function validateObject(object, fields = {}, optFields = {}) {
3432
3483
  }
3433
3484
 
3434
3485
  // node_modules/@noble/curves/abstract/modular.js
3486
+ init_define_ATBASH_CHROMIA_NODE_URLS();
3487
+ init_define_ATBASH_PRIVATE_NODE_URLS();
3435
3488
  var _0n2 = /* @__PURE__ */ BigInt(0);
3436
3489
  var _1n2 = /* @__PURE__ */ BigInt(1);
3437
3490
  var _2n = /* @__PURE__ */ BigInt(2);
@@ -4079,7 +4132,13 @@ function createKeygen(randomSecretKey, getPublicKey) {
4079
4132
  };
4080
4133
  }
4081
4134
 
4135
+ // node_modules/@noble/curves/abstract/weierstrass.js
4136
+ init_define_ATBASH_CHROMIA_NODE_URLS();
4137
+ init_define_ATBASH_PRIVATE_NODE_URLS();
4138
+
4082
4139
  // node_modules/@noble/hashes/hmac.js
4140
+ init_define_ATBASH_CHROMIA_NODE_URLS();
4141
+ init_define_ATBASH_PRIVATE_NODE_URLS();
4083
4142
  var _HMAC = class {
4084
4143
  oHash;
4085
4144
  iHash;
@@ -5111,6 +5170,8 @@ var Pointk1 = /* @__PURE__ */ weierstrass(secp256k1_CURVE, {
5111
5170
  var secp256k1 = /* @__PURE__ */ ecdsa(Pointk1, sha256);
5112
5171
 
5113
5172
  // node_modules/postchain-client/built/esm/index.js
5173
+ init_define_ATBASH_CHROMIA_NODE_URLS();
5174
+ init_define_ATBASH_PRIVATE_NODE_URLS();
5114
5175
  var import_bn = __toESM(require_bn(), 1);
5115
5176
  var commonjsGlobal = typeof globalThis !== "undefined" ? globalThis : typeof window !== "undefined" ? window : typeof global !== "undefined" ? global : typeof self !== "undefined" ? self : {};
5116
5177
  function getDefaultExportFromCjs(x) {
@@ -40524,7 +40585,7 @@ function requireFailoverStrategies() {
40524
40585
  exports.createTimeoutPromise = createTimeoutPromise;
40525
40586
  const utils_12 = requireUtils$1();
40526
40587
  const httpUtil_1 = httpUtil;
40527
- const logger2 = __importStar2(logger$3);
40588
+ const logger3 = __importStar2(logger$3);
40528
40589
  const http_utils_1 = httpUtils;
40529
40590
  function getUnreachableDuration(statusCode, error4) {
40530
40591
  if ((0, http_utils_1.isNetworkError)(error4)) {
@@ -40625,7 +40686,7 @@ function requireFailoverStrategies() {
40625
40686
  while (true) {
40626
40687
  if (groupedSuccessfulResponses.maxNumberOfEqualResponses() >= bftMajorityThreshold) {
40627
40688
  if (groupedSuccessfulResponses.numberOfDistinctResponses() > 1) {
40628
- logger2.warning(`Got disagreeing responses, but could still reach BFT majority`);
40689
+ logger3.warning(`Got disagreeing responses, but could still reach BFT majority`);
40629
40690
  }
40630
40691
  return groupedSuccessfulResponses.majorityResponse();
40631
40692
  }
@@ -40663,7 +40724,7 @@ function requireFailoverStrategies() {
40663
40724
  if (!isError4 && !error4) {
40664
40725
  return { error: error4, statusCode, rspBody, transactionTimestamp };
40665
40726
  }
40666
- logger2.info(`${method} request failed on ${endpoint.url}. Attempt: ${attempt + 1} / ${config2.attemptsPerEndpoint}`);
40727
+ logger3.info(`${method} request failed on ${endpoint.url}. Attempt: ${attempt + 1} / ${config2.attemptsPerEndpoint}`);
40667
40728
  yield (0, utils_12.sleep)(config2.attemptInterval);
40668
40729
  }
40669
40730
  return { error: error4, statusCode, rspBody, transactionTimestamp };
@@ -40699,7 +40760,7 @@ function requireFailoverStrategies() {
40699
40760
  if (isServerError) {
40700
40761
  const duration = getUnreachableDuration(statusCode !== null && statusCode !== void 0 ? statusCode : void 0, response.error);
40701
40762
  nodeManager2.makeNodeUnavailable(node2.url, duration);
40702
- logger2.info(`request failed with server error on ${node2.url} trying next node`);
40763
+ logger3.info(`request failed with server error on ${node2.url} trying next node`);
40703
40764
  break;
40704
40765
  }
40705
40766
  if (isClientError) {
@@ -40707,11 +40768,11 @@ function requireFailoverStrategies() {
40707
40768
  return { error: error4, statusCode, rspBody, transactionTimestamp };
40708
40769
  }
40709
40770
  if (!nodeManager2.useStickyNode) {
40710
- logger2.info(`request failed client error on ${node2.url} trying next node`);
40771
+ logger3.info(`request failed client error on ${node2.url} trying next node`);
40711
40772
  break;
40712
40773
  }
40713
40774
  }
40714
- logger2.info(`${method} request failed on ${node2.url}. Attempt: ${attempt + 1} / ${config2.attemptsPerEndpoint}`);
40775
+ logger3.info(`${method} request failed on ${node2.url}. Attempt: ${attempt + 1} / ${config2.attemptsPerEndpoint}`);
40715
40776
  if (config2.attemptInterval > 0) {
40716
40777
  yield (0, utils_12.sleep)(config2.attemptInterval);
40717
40778
  }
@@ -40940,7 +41001,7 @@ function requireUtils$1() {
40940
41001
  exports.getBlockchainRidFromIid = getBlockchainRidFromIid;
40941
41002
  exports.convertToPrintable = convertToPrintable;
40942
41003
  const buffer_12 = buffer$3;
40943
- const logger2 = __importStar2(logger$3);
41004
+ const logger3 = __importStar2(logger$3);
40944
41005
  const errors_12 = errors;
40945
41006
  const gtxTool = __importStar2(gtx$1);
40946
41007
  const errors_2 = errors;
@@ -41023,7 +41084,7 @@ function requireUtils$1() {
41023
41084
  function validTxRid(txRID) {
41024
41085
  if (txRID.length != 32) {
41025
41086
  const error4 = new errors_12.InvalidTxRidException(txRID);
41026
- logger2.error(error4.toString());
41087
+ logger3.error(error4.toString());
41027
41088
  return false;
41028
41089
  }
41029
41090
  return true;
@@ -41426,7 +41487,7 @@ function requireUtils$1() {
41426
41487
  function handleGetResponse(error4, statusCode, responseObject, callback) {
41427
41488
  try {
41428
41489
  const responseObjectPrintable = convertToPrintable(responseObject);
41429
- logger2.debug(`error: ${error4}, status code: ${statusCode}, response body: ${responseObjectPrintable}`);
41490
+ logger3.debug(`error: ${error4}, status code: ${statusCode}, response body: ${responseObjectPrintable}`);
41430
41491
  if (error4) {
41431
41492
  return callback(error4, null);
41432
41493
  }
@@ -41436,16 +41497,16 @@ function requireUtils$1() {
41436
41497
  return callback(null, responseObject);
41437
41498
  } catch (error5) {
41438
41499
  callback(error5, null);
41439
- logger2.error(`client.handleGetResponse(): Failed to call the callback function. ${error5}`);
41500
+ logger3.error(`client.handleGetResponse(): Failed to call the callback function. ${error5}`);
41440
41501
  }
41441
41502
  }
41442
41503
  function handlePostResponse(error4, statusCode, responseObject, callback) {
41443
41504
  var _a2;
41444
41505
  const responseObjectPrintable = convertToPrintable(responseObject);
41445
- logger2.debug(`error: ${error4}, status code: ${statusCode}, response body: ${responseObjectPrintable}`);
41506
+ logger3.debug(`error: ${error4}, status code: ${statusCode}, response body: ${responseObjectPrintable}`);
41446
41507
  try {
41447
41508
  if (error4) {
41448
- logger2.error(`In client post(). ${error4}`);
41509
+ logger3.error(`In client post(). ${error4}`);
41449
41510
  callback(error4, null);
41450
41511
  } else if (!statusCode || !(0, http_utils_1.isSuccessfulStatusCode)(statusCode)) {
41451
41512
  let errorMessage2 = `Unexpected status code from server. Code: ${statusCode}.`;
@@ -41453,14 +41514,14 @@ function requireUtils$1() {
41453
41514
  if (responseObjectPrintable) {
41454
41515
  errorMessage2 += ` Message: ${responseObjectPrintable}.`;
41455
41516
  }
41456
- logger2.error(errorMessage2);
41517
+ logger3.error(errorMessage2);
41457
41518
  callback(new errors_12.UnexpectedStatusError(statusCode !== null && statusCode !== void 0 ? statusCode : 400, errorMessageInResponseBody || responseObjectPrintable), responseObject);
41458
41519
  } else {
41459
- logger2.info(`Calling responseCallback with responseObject: ${responseObjectPrintable}`);
41520
+ logger3.info(`Calling responseCallback with responseObject: ${responseObjectPrintable}`);
41460
41521
  callback(null, responseObject);
41461
41522
  }
41462
41523
  } catch (error5) {
41463
- logger2.error(`client.handlePostResponse(): Failed to call callback function ${error5}`);
41524
+ logger3.error(`client.handlePostResponse(): Failed to call callback function ${error5}`);
41464
41525
  }
41465
41526
  }
41466
41527
  function getBlockchainRidFromIid(_a2) {
@@ -42198,7 +42259,7 @@ function requireBlockchainClient() {
42198
42259
  const crypto_12 = requireCryptoBrowserify();
42199
42260
  const cloneDeep_1$1 = __importDefault2(cloneDeep_1);
42200
42261
  const IccfProofTxMaterialBuilder_1 = requireIccfProofTxMaterialBuilder();
42201
- const logger2 = __importStar2(logger$3);
42262
+ const logger3 = __importStar2(logger$3);
42202
42263
  const formatter_12 = formatter;
42203
42264
  const serialization_12 = serialization$2;
42204
42265
  const gtxTool = __importStar2(gtx$1);
@@ -42240,7 +42301,7 @@ function requireBlockchainClient() {
42240
42301
  },
42241
42302
  signTransaction(transaction, signMethod2, callback) {
42242
42303
  return __awaiter2(this, void 0, void 0, function* () {
42243
- logger2.debug(`Signing transaction with ${!(0, utils_12.isKeyPair)(signMethod2) ? "signature provider containing " : ""}pubKey: ${(0, formatter_12.toString)(signMethod2.pubKey)}`);
42304
+ logger3.debug(`Signing transaction with ${!(0, utils_12.isKeyPair)(signMethod2) ? "signature provider containing " : ""}pubKey: ${(0, formatter_12.toString)(signMethod2.pubKey)}`);
42244
42305
  const gtx2 = (0, utils_12.getGTXFromBufferOrTransactionOrOperation)(transaction, config2.blockchainRid);
42245
42306
  try {
42246
42307
  const signedTx = yield (0, utils_12.isKeyPair)(signMethod2) ? gtxTool.sign(gtx2, signMethod2.privKey, config2.merkleHashVersion, signMethod2.pubKey) : gtxTool.sign(gtx2, signMethod2, config2.merkleHashVersion);
@@ -42265,7 +42326,7 @@ function requireBlockchainClient() {
42265
42326
  const promiEvent = new promiEvents_12.Web3PromiEvent((resolve2, reject) => __awaiter2(this, void 0, void 0, function* () {
42266
42327
  let error4 = null;
42267
42328
  for (let i = 0; i < config2.retryTransactionPolling.count; i++) {
42268
- logger2.info(`sendTransactionWithRetries attempt ${i + 1} of ${config2.retryTransactionPolling.count}`);
42329
+ logger3.info(`sendTransactionWithRetries attempt ${i + 1} of ${config2.retryTransactionPolling.count}`);
42269
42330
  const tmpPromiEvent = sendOnce().on(enums_12.TransactionEvent.ClusterAnchoringConfirmation, (receipt) => {
42270
42331
  promiEvent.emit(enums_12.TransactionEvent.ClusterAnchoringConfirmation, receipt);
42271
42332
  }).on(enums_12.TransactionEvent.SystemAnchoringConfirmation, (receipt) => {
@@ -42277,7 +42338,7 @@ function requireBlockchainClient() {
42277
42338
  }).on(enums_12.TransactionEvent.DappConfirmed, (receipt) => {
42278
42339
  promiEvent.emit(enums_12.TransactionEvent.DappConfirmed, receipt);
42279
42340
  }).catch((tmpError) => {
42280
- logger2.warning(`sendTransactionWithRetries error on attempt ${i + 1} of ${config2.retryTransactionPolling.count}: ${tmpError}`);
42341
+ logger3.warning(`sendTransactionWithRetries error on attempt ${i + 1} of ${config2.retryTransactionPolling.count}: ${tmpError}`);
42281
42342
  promiEvent.emit(enums_12.TransactionEvent.Rejected, tmpError);
42282
42343
  error4 = tmpError;
42283
42344
  });
@@ -43012,11 +43073,11 @@ function requireDecodeTransactionToGtx() {
43012
43073
  Object.defineProperty(decodeTransactionToGtx, "__esModule", { value: true });
43013
43074
  decodeTransactionToGtx.decodeTransactionToGtx = decodeTransactionToGtx$1;
43014
43075
  const gtxTool = __importStar2(gtx$1);
43015
- const logger2 = __importStar2(logger$3);
43076
+ const logger3 = __importStar2(logger$3);
43016
43077
  const dump_1 = requireDump();
43017
43078
  function decodeTransactionToGtx$1(encodedTransaction) {
43018
43079
  const gtx2 = gtxTool.deserialize(encodedTransaction);
43019
- logger2.debug(`Output from deserializing a raw transaction: ${(0, dump_1.dumpGtv)(gtx2)}`);
43080
+ logger3.debug(`Output from deserializing a raw transaction: ${(0, dump_1.dumpGtv)(gtx2)}`);
43020
43081
  return gtx2;
43021
43082
  }
43022
43083
  return decodeTransactionToGtx;
@@ -43233,17 +43294,11 @@ var index = /* @__PURE__ */ getDefaultExportFromCjs(builtExports);
43233
43294
 
43234
43295
  // src-ts/browser/native.ts
43235
43296
  var { Buffer: Buffer3, gtx: pcgtx } = index;
43236
- var DEV_ENDPOINT = "https://chromia-verified-ai-dev-two.vercel.app";
43237
- var DEV_BLOCKCHAIN_RID = "02668C5218871F69A93CC0F7032DCFFE06EF0D35EF2F0B07A92A3D83A3F23A7D";
43238
- var DEV_PRIVATE_BLOCKCHAIN_RID = "2603569AE8DC3F254323F719C8D4347BBA964E874E781291F8474236BE8B6493";
43239
- var DEFAULT_CHROMIA_NODE_URLS_ARR = [
43240
- "https://node0.testnet.chromia.com:7740",
43241
- "https://node1.testnet.chromia.com:7740",
43242
- "https://node3.testnet.chromia.com:7740"
43243
- ];
43244
- var DEFAULT_PRIVATE_NODE_URLS_ARR = [
43245
- "https://node0-pvn-testnet.dynamic.chromia.dev"
43246
- ];
43297
+ var ATBASH_ENDPOINT = "https://atbash.ai";
43298
+ var ATBASH_BLOCKCHAIN_RID = "0163241D9AF137638E63E48EFCDE15510F38C2426F7AD5DC726AF60351BF4DFE";
43299
+ var ATBASH_PRIVATE_BLOCKCHAIN_RID = "39FFD3557D0296CB2C57FDC6A3B8C024E95639CF4964DA08141AC20C6344D408";
43300
+ var DEFAULT_CHROMIA_NODE_URLS_ARR = define_ATBASH_CHROMIA_NODE_URLS_default;
43301
+ var DEFAULT_PRIVATE_NODE_URLS_ARR = define_ATBASH_PRIVATE_NODE_URLS_default;
43247
43302
  var MERKLE_HASH_VERSION = 2;
43248
43303
  function stripHex(s2) {
43249
43304
  return s2.trim().replace(/^0x/i, "").toLowerCase();
@@ -43394,15 +43449,23 @@ var native = {
43394
43449
  deriveMemoryKey,
43395
43450
  encryptMemoryContent,
43396
43451
  decryptMemoryContent,
43397
- DEFAULT_BLOCKCHAIN_RID: DEV_BLOCKCHAIN_RID,
43398
- DEFAULT_PRIVATE_BLOCKCHAIN_RID: DEV_PRIVATE_BLOCKCHAIN_RID,
43399
- DEFAULT_ENDPOINT: DEV_ENDPOINT,
43400
- // Browser has no NAPI channel to Rust's HONEYCOMB_KEY — telemetry
43401
- // silently no-ops. `HONEYCOMB_API_KEY` env var still overrides at runtime.
43402
- HONEYCOMB_KEY: "",
43452
+ DEFAULT_BLOCKCHAIN_RID: ATBASH_BLOCKCHAIN_RID,
43453
+ DEFAULT_PRIVATE_BLOCKCHAIN_RID: ATBASH_PRIVATE_BLOCKCHAIN_RID,
43454
+ DEFAULT_ENDPOINT: ATBASH_ENDPOINT,
43403
43455
  defaultChromiaNodeUrls: () => [...DEFAULT_CHROMIA_NODE_URLS_ARR],
43404
43456
  defaultPrivateNodeUrls: () => [...DEFAULT_PRIVATE_NODE_URLS_ARR],
43405
43457
  // Server-only surfaces — throw at runtime, keep types satisfied.
43458
+ // The memory signers are here and not with the other signing shims because
43459
+ // their args are encrypted by `encryptMemoryContent`, which this build does
43460
+ // not have: a browser could sign the transaction but never produce one worth
43461
+ // sending.
43462
+ signAddAgentMemory: stub("signAddAgentMemory"),
43463
+ signRollbackAgentMemory: stub("signRollbackAgentMemory"),
43464
+ extractMemoryEdits: stub("extractMemoryEdits"),
43465
+ applyMemoryEdits: stub("applyMemoryEdits"),
43466
+ memorySlotForPath: stub("memorySlotForPath"),
43467
+ isSafeMemorySlot: stub("isSafeMemorySlot"),
43468
+ defaultAgentHomeDirs: stub("defaultAgentHomeDirs"),
43406
43469
  classifyMemoryWrite: stub("classifyMemoryWrite"),
43407
43470
  classifyMemoryRead: stub("classifyMemoryRead"),
43408
43471
  defaultMemoryWriteToolNames: stub("defaultMemoryWriteToolNames"),
@@ -43426,9 +43489,10 @@ var native = {
43426
43489
  validateMemoryId: stub("validateMemoryId"),
43427
43490
  validateRollbackReason: stub("validateRollbackReason"),
43428
43491
  validateMemoryNonce: stub("validateMemoryNonce"),
43492
+ validateFilePath: stub("validateFilePath"),
43429
43493
  buildGetActiveMemoryIdQuery: stub("buildGetActiveMemoryIdQuery"),
43430
- buildGetAgentMemoryQuery: stub("buildGetAgentMemoryQuery"),
43431
- buildGetAllAgentMemoryQuery: stub("buildGetAllAgentMemoryQuery"),
43494
+ buildGetRecentAgentMemoryQuery: stub("buildGetRecentAgentMemoryQuery"),
43495
+ buildGetActiveAgentMemoryQuery: stub("buildGetActiveAgentMemoryQuery"),
43432
43496
  buildGetAgentMemoryHistoryQuery: stub("buildGetAgentMemoryHistoryQuery"),
43433
43497
  buildGetAgentMemoryRollbackHistoryQuery: stub("buildGetAgentMemoryRollbackHistoryQuery"),
43434
43498
  buildGetAgentMemoryByIdQuery: stub("buildGetAgentMemoryByIdQuery"),
@@ -43447,16 +43511,23 @@ var native = {
43447
43511
  OP_ROLLBACK_AGENT_MEMORY: "rollback_agent_memory",
43448
43512
  OP_LOG_ENCRYPTED_TOOL_CALL: "log_encrypted_tool_call",
43449
43513
  QUERY_GET_ACTIVE_MEMORY_ID: "get_active_memory_id",
43450
- QUERY_GET_AGENT_MEMORY: "get_agent_memory",
43451
- QUERY_GET_ALL_AGENT_MEMORY: "get_all_agent_memory",
43514
+ QUERY_GET_RECENT_AGENT_MEMORY: "get_recent_agent_memory",
43515
+ QUERY_GET_ACTIVE_AGENT_MEMORY: "get_active_agent_memory",
43452
43516
  QUERY_GET_AGENT_MEMORY_HISTORY: "get_agent_memory_history",
43453
43517
  QUERY_GET_AGENT_MEMORY_BY_ID: "get_agent_memory_by_id",
43454
43518
  QUERY_GET_AGENT_MEMORY_ROLLBACK_HISTORY: "get_agent_memory_rollback_history",
43455
43519
  ARG_AGENT_PUBKEY: "agent_pubkey",
43456
- ARG_ID: "id"
43520
+ ARG_ID: "id",
43521
+ ARG_FILE_PATH: "file_path"
43457
43522
  };
43458
43523
 
43524
+ // src-ts/client.ts
43525
+ init_define_ATBASH_CHROMIA_NODE_URLS();
43526
+ init_define_ATBASH_PRIVATE_NODE_URLS();
43527
+
43459
43528
  // src-ts/random.ts
43529
+ init_define_ATBASH_CHROMIA_NODE_URLS();
43530
+ init_define_ATBASH_PRIVATE_NODE_URLS();
43460
43531
  function randomBytes4(size) {
43461
43532
  const buf = new Uint8Array(size);
43462
43533
  globalThis.crypto.getRandomValues(buf);
@@ -43471,7 +43542,39 @@ function randomHex(size) {
43471
43542
  return hex;
43472
43543
  }
43473
43544
 
43545
+ // src-ts/auth-bearer.ts
43546
+ init_define_ATBASH_CHROMIA_NODE_URLS();
43547
+ init_define_ATBASH_PRIVATE_NODE_URLS();
43548
+ var BEARER_TTL_MS = 4 * 60 * 1e3;
43549
+ var bearers = /* @__PURE__ */ new Map();
43550
+ function agentAuthBearer(auth, blockchainRid) {
43551
+ const key3 = `${auth.pubkey}:${blockchainRid}`;
43552
+ const now = Date.now();
43553
+ const cached = bearers.get(key3);
43554
+ if (cached && now - cached.issuedAt < BEARER_TTL_MS) return cached.hex;
43555
+ const hex = native.signLogToolCall(
43556
+ `auth-${now.toString(36)}-${randomHex(4)}`,
43557
+ `auth:${now}`,
43558
+ "",
43559
+ "auth-bearer",
43560
+ "",
43561
+ auth.privkey,
43562
+ blockchainRid
43563
+ );
43564
+ bearers.set(key3, { hex, issuedAt: now });
43565
+ return hex;
43566
+ }
43567
+ function agentAuthHeaders(auth, blockchainRid) {
43568
+ return { Authorization: `Bearer ${agentAuthBearer(auth, blockchainRid)}` };
43569
+ }
43570
+
43571
+ // src-ts/chain-config.ts
43572
+ init_define_ATBASH_CHROMIA_NODE_URLS();
43573
+ init_define_ATBASH_PRIVATE_NODE_URLS();
43574
+
43474
43575
  // src-ts/constants.ts
43576
+ init_define_ATBASH_CHROMIA_NODE_URLS();
43577
+ init_define_ATBASH_PRIVATE_NODE_URLS();
43475
43578
  var DEFAULT_ENDPOINT = native.DEFAULT_ENDPOINT;
43476
43579
  var DEFAULT_CHROMIA_NODE_URLS = Object.freeze(
43477
43580
  native.defaultChromiaNodeUrls()
@@ -43493,8 +43596,21 @@ var PRIVATE_CHAIN = {
43493
43596
  blockchainRid: DEFAULT_PRIVATE_BLOCKCHAIN_RID,
43494
43597
  nodeUrls: DEFAULT_PRIVATE_NODE_URLS
43495
43598
  };
43599
+ function chainForNetwork(network) {
43600
+ return network === "private" ? PRIVATE_CHAIN : PUBLIC_CHAIN;
43601
+ }
43602
+
43603
+ // src-ts/browser/encrypted-toolcall.ts
43604
+ init_define_ATBASH_CHROMIA_NODE_URLS();
43605
+ init_define_ATBASH_PRIVATE_NODE_URLS();
43606
+
43607
+ // src-ts/browser/crypto-ecies.ts
43608
+ init_define_ATBASH_CHROMIA_NODE_URLS();
43609
+ init_define_ATBASH_PRIVATE_NODE_URLS();
43496
43610
 
43497
43611
  // node_modules/@noble/hashes/hkdf.js
43612
+ init_define_ATBASH_CHROMIA_NODE_URLS();
43613
+ init_define_ATBASH_PRIVATE_NODE_URLS();
43498
43614
  function extract(hash3, ikm, salt) {
43499
43615
  ahash(hash3);
43500
43616
  if (salt === void 0)
@@ -43534,7 +43650,17 @@ function expand2(hash3, prk, info2, length = 32) {
43534
43650
  }
43535
43651
  var hkdf = (hash3, ikm, salt, info2, length) => expand2(hash3, extract(hash3, ikm, salt), info2, length);
43536
43652
 
43653
+ // node_modules/@noble/ciphers/aes.js
43654
+ init_define_ATBASH_CHROMIA_NODE_URLS();
43655
+ init_define_ATBASH_PRIVATE_NODE_URLS();
43656
+
43657
+ // node_modules/@noble/ciphers/_polyval.js
43658
+ init_define_ATBASH_CHROMIA_NODE_URLS();
43659
+ init_define_ATBASH_PRIVATE_NODE_URLS();
43660
+
43537
43661
  // node_modules/@noble/ciphers/utils.js
43662
+ init_define_ATBASH_CHROMIA_NODE_URLS();
43663
+ init_define_ATBASH_PRIVATE_NODE_URLS();
43538
43664
  function isBytes3(a) {
43539
43665
  return a instanceof Uint8Array || ArrayBuffer.isView(a) && a.constructor.name === "Uint8Array" && "BYTES_PER_ELEMENT" in a && a.BYTES_PER_ELEMENT === 1;
43540
43666
  }
@@ -44126,6 +44252,46 @@ function encryptedLength(plaintextByteLength) {
44126
44252
  return HEADER_LEN + plaintextByteLength + GCM_TAG_LEN;
44127
44253
  }
44128
44254
 
44255
+ // src-ts/crypto/envelope.ts
44256
+ init_define_ATBASH_CHROMIA_NODE_URLS();
44257
+ init_define_ATBASH_PRIVATE_NODE_URLS();
44258
+ var PREFIX = "atb1";
44259
+ var SEPARATOR = ".";
44260
+ function toBase64(bytes) {
44261
+ let binary = "";
44262
+ for (const b of bytes) binary += String.fromCharCode(b);
44263
+ return btoa(binary);
44264
+ }
44265
+ function fromBase64(text) {
44266
+ const binary = atob(text);
44267
+ const out = new Uint8Array(binary.length);
44268
+ for (let i = 0; i < binary.length; i++) out[i] = binary.charCodeAt(i);
44269
+ return out;
44270
+ }
44271
+ function packEnvelope(payload, keyFingerprint = "", claimHash = "") {
44272
+ return [PREFIX, keyFingerprint, claimHash, toBase64(payload)].join(SEPARATOR);
44273
+ }
44274
+ function fieldWidthOk(value, hexChars) {
44275
+ return value.length === 0 ? true : value.length === hexChars && /^[0-9a-f]+$/.test(value);
44276
+ }
44277
+ function isEnvelope(value) {
44278
+ if (typeof value !== "string" || !value.startsWith(PREFIX + SEPARATOR)) return false;
44279
+ const parts = value.split(SEPARATOR);
44280
+ return parts.length >= 4 && fieldWidthOk(parts[1], 16) && fieldWidthOk(parts[2], 64);
44281
+ }
44282
+ function parseEnvelope(value) {
44283
+ if (!isEnvelope(value)) return null;
44284
+ const [, keyFingerprint, claimHash, ...rest] = value.split(SEPARATOR);
44285
+ try {
44286
+ return { keyFingerprint, claimHash, payload: fromBase64(rest.join(SEPARATOR)) };
44287
+ } catch {
44288
+ return null;
44289
+ }
44290
+ }
44291
+ function keyFingerprintOf(pubKeyHex) {
44292
+ return pubKeyHex.trim().replace(/^0x/i, "").toLowerCase().slice(0, 16);
44293
+ }
44294
+
44129
44295
  // src-ts/browser/encrypted-toolcall.ts
44130
44296
  var { Buffer: PolyBuffer, gtx: pcgtx2 } = index;
44131
44297
  var MERKLE_HASH_VERSION2 = 2;
@@ -44138,6 +44304,9 @@ function claimHashHex(toolName, action, context, toolArgsJson) {
44138
44304
  ]);
44139
44305
  return bytesToHex2(sha256(new TextEncoder().encode(canonical)));
44140
44306
  }
44307
+ function columnAad(toolCallId, column) {
44308
+ return `${toolCallId}:${column}`;
44309
+ }
44141
44310
  function normalizeActionForHash(action) {
44142
44311
  action = action.trim();
44143
44312
  try {
@@ -44183,31 +44352,34 @@ function signOpWithBytes(opName, args, privkeyHex, blockchainRidHex) {
44183
44352
  return pcgtx2.serialize(g).toString("hex");
44184
44353
  }
44185
44354
  function signEncryptedToolCall(toolCallId, action, context, toolName, toolArgsJson, orgEncryptionPubKey, privkeyHex, blockchainRidHex) {
44186
- const plaintext = {
44187
- tool_name: toolName,
44188
- action,
44189
- context,
44190
- tool_args_json: toolArgsJson
44191
- };
44192
- const contentCipher = encryptForOrg(
44193
- JSON.stringify(plaintext),
44194
- orgEncryptionPubKey,
44195
- toolCallId,
44196
- EciesDomain.toolCall
44355
+ const fingerprint = keyFingerprintOf(orgEncryptionPubKey);
44356
+ const seal = (text, column) => text === "" ? "" : packEnvelope(
44357
+ encryptForOrg(
44358
+ text,
44359
+ orgEncryptionPubKey,
44360
+ columnAad(toolCallId, column),
44361
+ EciesDomain.toolCall
44362
+ ),
44363
+ fingerprint
44197
44364
  );
44198
- const actionHash = bytesToHex2(
44199
- sha256(new TextEncoder().encode(normalizeActionForHash(action)))
44365
+ const actionColumn = packEnvelope(
44366
+ encryptForOrg(
44367
+ action,
44368
+ orgEncryptionPubKey,
44369
+ columnAad(toolCallId, "action"),
44370
+ EciesDomain.toolCall
44371
+ ),
44372
+ fingerprint,
44373
+ claimHashHex(toolName, action, context, toolArgsJson)
44200
44374
  );
44201
44375
  return signOpWithBytes(
44202
- "log_encrypted_tool_call",
44376
+ "log_tool_call",
44203
44377
  [
44204
44378
  toolCallId,
44379
+ actionColumn,
44380
+ seal(context, "context"),
44205
44381
  toolName,
44206
- contentCipher,
44207
- actionHash,
44208
- // Empty = "org's current key"; chain resolves it.
44209
- PolyBuffer.from(new Uint8Array(0)),
44210
- claimHashHex(toolName, action, context, toolArgsJson)
44382
+ seal(toolArgsJson, "tool_args")
44211
44383
  ],
44212
44384
  privkeyHex,
44213
44385
  blockchainRidHex
@@ -44215,11 +44387,23 @@ function signEncryptedToolCall(toolCallId, action, context, toolName, toolArgsJs
44215
44387
  }
44216
44388
 
44217
44389
  // src-ts/endpoint.ts
44218
- var ALLOWED_JUDGE_HOSTS = /* @__PURE__ */ new Set([
44219
- "atbash.ai",
44220
- "www.atbash.ai",
44221
- "chromia-verified-ai-dev-two.vercel.app"
44222
- ]);
44390
+ init_define_ATBASH_CHROMIA_NODE_URLS();
44391
+ init_define_ATBASH_PRIVATE_NODE_URLS();
44392
+ function buildAllowedJudgeHosts() {
44393
+ return /* @__PURE__ */ new Set([
44394
+ "atbash.ai",
44395
+ "www.atbash.ai",
44396
+ new URL(DEFAULT_ENDPOINT).hostname.toLowerCase()
44397
+ ]);
44398
+ }
44399
+ var ALLOWED_JUDGE_HOSTS = buildAllowedJudgeHosts();
44400
+ function isAllowlistedJudgeHost(endpoint) {
44401
+ try {
44402
+ return ALLOWED_JUDGE_HOSTS.has(new URL(endpoint).hostname.toLowerCase());
44403
+ } catch {
44404
+ return false;
44405
+ }
44406
+ }
44223
44407
  function validateJudgeEndpoint(judge) {
44224
44408
  const policy = judge?.policy === "self-hosted" ? "self-hosted" : "default";
44225
44409
  const candidate = judge?.endpoint?.trim() || DEFAULT_ENDPOINT;
@@ -44262,16 +44446,30 @@ function validateJudgeEndpoint(judge) {
44262
44446
  }
44263
44447
 
44264
44448
  // src-ts/errors.ts
44449
+ init_define_ATBASH_CHROMIA_NODE_URLS();
44450
+ init_define_ATBASH_PRIVATE_NODE_URLS();
44265
44451
  var AtbashAPIError = class extends Error {
44266
44452
  /** HTTP status code (or 0 if the request never completed). */
44267
44453
  status;
44268
44454
  /** Raw response body text (may be empty). */
44269
44455
  body;
44270
- constructor(status, body, statusText = "", endpoint = DEFAULT_ENDPOINT) {
44271
- super(enrich(status, body, statusText, endpoint));
44456
+ /**
44457
+ * Request path this status came from, e.g. `/api/v1/judge` — absent when the
44458
+ * request never reached a response (transport failures carry status 0).
44459
+ *
44460
+ * A status alone does not say what failed. Several routes answer one call, and
44461
+ * more than one of them can 404: a caller reading only `404` cannot tell "this
44462
+ * agent is not registered" from "the chain-routing lookup did not resolve", and
44463
+ * has to guess from the body's prose — which a 404 raised before any handler
44464
+ * ran does not carry. The path is the fact that settles it.
44465
+ */
44466
+ path;
44467
+ constructor(status, body, statusText = "", endpoint = DEFAULT_ENDPOINT, path3) {
44468
+ super(enrich(status, body, statusText, endpoint, path3));
44272
44469
  this.name = "AtbashAPIError";
44273
44470
  this.status = status;
44274
44471
  this.body = body;
44472
+ this.path = path3;
44275
44473
  }
44276
44474
  };
44277
44475
  var SignatureVerificationError = class extends Error {
@@ -44280,9 +44478,9 @@ var SignatureVerificationError = class extends Error {
44280
44478
  this.name = "SignatureVerificationError";
44281
44479
  }
44282
44480
  };
44283
- function enrich(status, body, statusText, endpoint) {
44481
+ function enrich(status, body, statusText, endpoint, path3) {
44284
44482
  const dashboard = endpoint.replace(/\/+$/, "") || DEFAULT_ENDPOINT;
44285
- let msg = `API error ${status}: ${body || statusText}`;
44483
+ let msg = `API error ${status}${path3 ? ` from ${path3}` : ""}: ${body || statusText}`;
44286
44484
  const lowered = body.toLowerCase();
44287
44485
  if (lowered.includes("agent not registered")) {
44288
44486
  msg += `
@@ -44304,6 +44502,8 @@ function enrich(status, body, statusText, endpoint) {
44304
44502
  }
44305
44503
 
44306
44504
  // src-ts/http/client.ts
44505
+ init_define_ATBASH_CHROMIA_NODE_URLS();
44506
+ init_define_ATBASH_PRIVATE_NODE_URLS();
44307
44507
  var HttpClient = class {
44308
44508
  baseUrl;
44309
44509
  timeoutMs;
@@ -44336,11 +44536,80 @@ var HttpClient = class {
44336
44536
  });
44337
44537
  }
44338
44538
  async fetch(url, init4) {
44339
- return fetch(url, { ...init4, signal: AbortSignal.timeout(this.timeoutMs) });
44539
+ try {
44540
+ return await fetch(url, {
44541
+ ...init4,
44542
+ signal: AbortSignal.timeout(this.timeoutMs)
44543
+ });
44544
+ } catch (err) {
44545
+ throw classifyTransportError(err, url, init4.method ?? "GET", this.timeoutMs);
44546
+ }
44547
+ }
44548
+ };
44549
+ var HttpTransportError = class extends Error {
44550
+ kind;
44551
+ constructor(kind, message, options) {
44552
+ super(message, options);
44553
+ this.name = "HttpTransportError";
44554
+ this.kind = kind;
44340
44555
  }
44341
44556
  };
44557
+ function classifyTransportError(err, url, method, timeoutMs) {
44558
+ const name2 = err instanceof Error ? err.name : "";
44559
+ const cause = err instanceof Error ? err.cause : void 0;
44560
+ const code2 = cause && typeof cause === "object" && "code" in cause ? String(cause.code) : "";
44561
+ if (name2 === "TimeoutError") {
44562
+ return new HttpTransportError(
44563
+ "timeout",
44564
+ `${method} ${url} did not respond within ${timeoutMs} ms \u2014 the judge may be slow to boot or the LLM is under load; retry in a moment`,
44565
+ { cause: err }
44566
+ );
44567
+ }
44568
+ if (name2 === "AbortError") {
44569
+ return new HttpTransportError(
44570
+ "aborted",
44571
+ `${method} ${url} was cancelled by the caller`,
44572
+ { cause: err }
44573
+ );
44574
+ }
44575
+ if (code2 === "UND_ERR_CONNECT_TIMEOUT") {
44576
+ return new HttpTransportError(
44577
+ "timeout",
44578
+ `${method} ${url} could not establish a connection before the transport deadline \u2014 check the endpoint and network`,
44579
+ { cause: err }
44580
+ );
44581
+ }
44582
+ if (code2 === "ENOTFOUND" || code2 === "EAI_AGAIN") {
44583
+ return new HttpTransportError(
44584
+ "dns",
44585
+ `could not resolve the judge hostname (${url}) \u2014 check the endpoint and DNS`,
44586
+ { cause: err }
44587
+ );
44588
+ }
44589
+ if (code2 === "ECONNREFUSED") {
44590
+ return new HttpTransportError(
44591
+ "connect_refused",
44592
+ `judge refused the connection (${url}) \u2014 the service may be down or restarting`,
44593
+ { cause: err }
44594
+ );
44595
+ }
44596
+ if (code2 === "ECONNRESET" || code2 === "EPIPE") {
44597
+ return new HttpTransportError(
44598
+ "connection_reset",
44599
+ `judge dropped the connection mid-request (${url}) \u2014 retry once`,
44600
+ { cause: err }
44601
+ );
44602
+ }
44603
+ return new HttpTransportError(
44604
+ "unknown",
44605
+ `${method} ${url} failed: ${err instanceof Error ? err.message : String(err)}`,
44606
+ { cause: err }
44607
+ );
44608
+ }
44342
44609
 
44343
44610
  // src-ts/browser/keyLoader.ts
44611
+ init_define_ATBASH_CHROMIA_NODE_URLS();
44612
+ init_define_ATBASH_PRIVATE_NODE_URLS();
44344
44613
  var NOT_AVAILABLE = "keyLoader is not available in the browser bundle \u2014 pass `agentKey` explicitly to Atbash.fromConfig or use `new Atbash(privkey, opts)`.";
44345
44614
  function resolveKeyPath(_input) {
44346
44615
  throw new Error(NOT_AVAILABLE);
@@ -44349,17 +44618,36 @@ function loadAgentFromFile(_keyPath) {
44349
44618
  throw new Error(NOT_AVAILABLE);
44350
44619
  }
44351
44620
 
44621
+ // src-ts/decision.ts
44622
+ init_define_ATBASH_CHROMIA_NODE_URLS();
44623
+ init_define_ATBASH_PRIVATE_NODE_URLS();
44624
+
44352
44625
  // src-ts/normalize.ts
44626
+ init_define_ATBASH_CHROMIA_NODE_URLS();
44627
+ init_define_ATBASH_PRIVATE_NODE_URLS();
44628
+ function wireText(raw2, fallback = "") {
44629
+ if (raw2 === null || raw2 === void 0) return fallback;
44630
+ if (typeof raw2 === "object" || typeof raw2 === "function") return fallback;
44631
+ return String(raw2);
44632
+ }
44633
+ function wireNumber(raw2, fallback = 0) {
44634
+ if (raw2 === null || raw2 === void 0) return fallback;
44635
+ if (typeof raw2 === "object" || typeof raw2 === "function") return fallback;
44636
+ return Number(raw2);
44637
+ }
44353
44638
  function normalizeVerdict(raw2) {
44354
44639
  if (raw2 === null || raw2 === void 0) return "No verdict";
44355
- const v = String(raw2).toUpperCase();
44640
+ const v = wireText(raw2).trim().toUpperCase();
44356
44641
  if (v === "ALLOW" || v === "GREEN") return "ALLOW";
44357
44642
  if (v === "HOLD" || v === "YELLOW") return "HOLD";
44358
44643
  if (v === "BLOCK" || v === "RED") return "BLOCK";
44359
44644
  return "HOLD";
44360
44645
  }
44646
+ function normalizeActionType(raw2) {
44647
+ return typeof raw2 === "string" ? raw2.trim().toLowerCase() : "";
44648
+ }
44361
44649
  function normalizeStatus(raw2) {
44362
- const s2 = String(raw2 ?? "").toLowerCase();
44650
+ const s2 = wireText(raw2).toLowerCase();
44363
44651
  if (s2 === "pending" || s2 === "answered" || s2 === "error") return s2;
44364
44652
  return "error";
44365
44653
  }
@@ -44374,7 +44662,137 @@ function pubkeyToHex(val) {
44374
44662
  return "";
44375
44663
  }
44376
44664
 
44665
+ // src-ts/decision.ts
44666
+ function isRecord(value) {
44667
+ return typeof value === "object" && value !== null && !Array.isArray(value);
44668
+ }
44669
+ function allowSignalsPermit(data) {
44670
+ const signals = [];
44671
+ if (Object.hasOwn(data, "allow")) signals.push(data.allow);
44672
+ if (isRecord(data.decision) && Object.hasOwn(data.decision, "allow")) {
44673
+ signals.push(data.decision.allow);
44674
+ }
44675
+ return signals.length === 0 || signals.every((value) => value === true);
44676
+ }
44677
+ function explicitRefusal(data) {
44678
+ let hold = false;
44679
+ for (const source of decisionSources(data)) {
44680
+ const verdict = verdictOf(source);
44681
+ if (verdict === "BLOCK" || verdict === "RED") return "BLOCK";
44682
+ if (verdict === "HOLD" || verdict === "YELLOW") hold = true;
44683
+ const actionType = actionTypeOf(source);
44684
+ if (actionType === "block") return "BLOCK";
44685
+ if (actionType === "hold_for_user_confirm") hold = true;
44686
+ }
44687
+ if (!allowSignalsPermit(data)) return "BLOCK";
44688
+ return hold ? "HOLD" : "";
44689
+ }
44690
+ function decisionSources(data) {
44691
+ return [data, isRecord(data.decision) ? data.decision : {}];
44692
+ }
44693
+ function verdictOf(source) {
44694
+ return typeof source.verdict === "string" ? source.verdict.trim().toUpperCase() : "";
44695
+ }
44696
+ function actionTypeRank(actionType) {
44697
+ if (actionType === "block") return 4;
44698
+ if (actionType === "hold_for_user_confirm") return 3;
44699
+ if (actionType === "") return 1;
44700
+ if (actionType === "allow") return 0;
44701
+ return 2;
44702
+ }
44703
+ function actionTypeOf(source) {
44704
+ let winner = "";
44705
+ for (const key3 of ["action_type", "actionType"]) {
44706
+ const raw2 = source[key3];
44707
+ if (raw2 === void 0 || raw2 === null) continue;
44708
+ const actionType = normalizeActionType(raw2);
44709
+ if (actionTypeRank(actionType) > actionTypeRank(winner)) winner = actionType;
44710
+ }
44711
+ return winner;
44712
+ }
44713
+ function wireActionType(data) {
44714
+ for (const source of decisionSources(data)) {
44715
+ const actionType = actionTypeOf(source);
44716
+ if (actionType !== "") return actionType;
44717
+ }
44718
+ return "";
44719
+ }
44720
+ function isAuditTier(data) {
44721
+ const absentVerdict = data.verdict === null || data.verdict === void 0;
44722
+ return absentVerdict && data.status === "logged";
44723
+ }
44724
+ function isAuditTierBody(data) {
44725
+ return isAuditTier(data);
44726
+ }
44727
+ function canonicalAllow(data) {
44728
+ if (explicitRefusal(data) !== "") return false;
44729
+ const actionType = wireActionType(data);
44730
+ if (actionType && actionType !== "allow") return false;
44731
+ if (isAuditTier(data)) return true;
44732
+ if (typeof data.verdict !== "string") return false;
44733
+ const verdict = data.verdict.trim().toUpperCase();
44734
+ return verdict === "ALLOW" || verdict === "GREEN";
44735
+ }
44736
+
44737
+ // src-ts/opentel/events.ts
44738
+ init_define_ATBASH_CHROMIA_NODE_URLS();
44739
+ init_define_ATBASH_PRIVATE_NODE_URLS();
44740
+ var SLOW_MS = 1500;
44741
+ var SUCCESS_SAMPLE_RATE = 10;
44742
+ var logger2 = null;
44743
+ var eventsEnabled = false;
44744
+ var sdkVersion = "";
44745
+ var eventSource = "sdk";
44746
+ var hashAgentKey = null;
44747
+ function eventsOptedOut() {
44748
+ const flag = process.env.ATBASH_TELEMETRY_EVENTS_DISABLED?.trim().toLowerCase();
44749
+ return Boolean(flag && ["1", "true", "yes", "on"].includes(flag));
44750
+ }
44751
+ var SOURCE_SHAPE = /^(?:sdk|cli|plugin:[a-z0-9][a-z0-9._-]{0,31})$/;
44752
+ function configureEvents(next, opts = {}) {
44753
+ logger2 = next;
44754
+ eventsEnabled = next !== null && !eventsOptedOut();
44755
+ if (opts.version) sdkVersion = opts.version;
44756
+ if (opts.source && SOURCE_SHAPE.test(opts.source)) eventSource = opts.source;
44757
+ hashAgentKey = opts.hashAgentKey ?? null;
44758
+ }
44759
+ function eventsAreOn() {
44760
+ return eventsEnabled && logger2 !== null;
44761
+ }
44762
+ function sampleRateFor(e) {
44763
+ if (e.status === "error") return 1;
44764
+ if (e.durationMs >= SLOW_MS) return 1;
44765
+ return Math.random() < 1 / SUCCESS_SAMPLE_RATE ? SUCCESS_SAMPLE_RATE : 0;
44766
+ }
44767
+ function recordEvent(e) {
44768
+ if (!eventsAreOn()) return;
44769
+ const sampleRate = sampleRateFor(e);
44770
+ if (sampleRate === 0) return;
44771
+ try {
44772
+ const attributes = {
44773
+ "function.name": e.functionName,
44774
+ "duration_ms": Math.round(e.durationMs),
44775
+ status: e.status,
44776
+ source: eventSource,
44777
+ // Honeycomb reweights counts and percentiles by this. It is per-event
44778
+ // because the sampling is biased by outcome and latency.
44779
+ sampleRate
44780
+ };
44781
+ if (sdkVersion) attributes["sdk.version"] = sdkVersion;
44782
+ if (e.agentPubkey && hashAgentKey) attributes["agent.hash"] = hashAgentKey(e.agentPubkey);
44783
+ if (e.chain) attributes["chain"] = e.chain;
44784
+ if (e.errorClass) attributes["error.class"] = e.errorClass;
44785
+ if (e.errorStatus !== void 0) attributes["error.status"] = e.errorStatus;
44786
+ if (e.errorPath) attributes["error.path"] = e.errorPath;
44787
+ if (e.outcome) attributes["outcome"] = e.outcome;
44788
+ logger2.emit({ body: e.functionName, attributes });
44789
+ } catch {
44790
+ }
44791
+ }
44792
+
44377
44793
  // src-ts/browser/opentel/telemetry.ts
44794
+ init_define_ATBASH_CHROMIA_NODE_URLS();
44795
+ init_define_ATBASH_PRIVATE_NODE_URLS();
44378
44796
  function setupTelemetry(_config) {
44379
44797
  }
44380
44798
  function recordCall(_functionName, _source, _agentPubkey) {
@@ -44387,6 +44805,8 @@ async function shutdownTelemetry() {
44387
44805
  }
44388
44806
 
44389
44807
  // src-ts/browser/userConfig.ts
44808
+ init_define_ATBASH_CHROMIA_NODE_URLS();
44809
+ init_define_ATBASH_PRIVATE_NODE_URLS();
44390
44810
  var NOT_AVAILABLE2 = "userConfig file I/O is not available in the browser bundle.";
44391
44811
  function getConfigDir() {
44392
44812
  throw new Error(NOT_AVAILABLE2);
@@ -44403,11 +44823,47 @@ function saveUserConfig(_) {
44403
44823
  function resolve(_key, flagValue) {
44404
44824
  return flagValue ?? "";
44405
44825
  }
44826
+ function forcedChainNetwork(flagValue) {
44827
+ return flagValue === "public" || flagValue === "private" ? flagValue : void 0;
44828
+ }
44829
+ function agentKeyFromEnv() {
44830
+ return "";
44831
+ }
44832
+ function strandedAgentKey() {
44833
+ return "";
44834
+ }
44406
44835
 
44407
44836
  // src-ts/client.ts
44408
44837
  function generateToolCallId() {
44409
44838
  return `tc-${Date.now()}-${randomHex(4)}`;
44410
44839
  }
44840
+ function resolveConstructorChain(options) {
44841
+ if (options.chain) return options.chain;
44842
+ const hasNodeUrls = options.nodeUrls !== void 0;
44843
+ const hasBrid = options.blockchainRid !== void 0;
44844
+ if (hasNodeUrls !== hasBrid) {
44845
+ throw new Error(
44846
+ 'nodeUrls and blockchainRid must be provided together \u2014 passing one without the other 404s every chain request. Prefer `chain: PUBLIC_CHAIN | PRIVATE_CHAIN` or `network: "public" | "private"`.'
44847
+ );
44848
+ }
44849
+ if (hasNodeUrls && hasBrid) {
44850
+ const brid = options.blockchainRid;
44851
+ const derivedNetwork = options.network ?? (brid === PUBLIC_CHAIN.blockchainRid ? "public" : brid === PRIVATE_CHAIN.blockchainRid ? "private" : "private");
44852
+ return {
44853
+ network: derivedNetwork,
44854
+ blockchainRid: brid,
44855
+ nodeUrls: options.nodeUrls
44856
+ };
44857
+ }
44858
+ return chainForNetwork(options.network ?? forcedChainNetwork() ?? "private");
44859
+ }
44860
+ function errorDetail(err) {
44861
+ if (!(err instanceof AtbashAPIError)) return {};
44862
+ return {
44863
+ errorStatus: err.status,
44864
+ ...err.path ? { errorPath: err.path } : {}
44865
+ };
44866
+ }
44411
44867
  var Atbash = class _Atbash {
44412
44868
  auth;
44413
44869
  endpoint;
@@ -44421,6 +44877,13 @@ var Atbash = class _Atbash {
44421
44877
  orgEncryptionPubKey;
44422
44878
  /** When true (default), `auditToolCall` denies on any error. */
44423
44879
  failClosed;
44880
+ /** When true (default), an unenforced (audit-tier) answer is refused. */
44881
+ requireEnforcement;
44882
+ /** Overall deadline for one auditToolCall decision, in ms. */
44883
+ decisionTimeoutMs;
44884
+ /** Org key learned from the last agent-exists check, for this agent only. */
44885
+ _orgKeyFromChain = null;
44886
+ debug;
44424
44887
  logger;
44425
44888
  http;
44426
44889
  /**
@@ -44429,28 +44892,114 @@ var Atbash = class _Atbash {
44429
44892
  */
44430
44893
  _chainCache = /* @__PURE__ */ new Map();
44431
44894
  /**
44432
- * Cached bearer token for risk-engine / insurance read calls. Built
44433
- * lazily as a signed `log_tool_call` tx and refreshed every 4 min so
44434
- * server-side replay protection windows never expire it mid-session.
44895
+ * The chain the constructor settled on. Used only where a lookup returns no
44896
+ * answer — see {@link resolveChainFromMap}.
44897
+ */
44898
+ _defaultChain;
44899
+ /**
44900
+ * True when the caller named a chain outright — `chain`, `network`, or the
44901
+ * paired `blockchainRid` + `nodeUrls`.
44902
+ *
44903
+ * Such a client is never re-pointed: not by the migration switch, and not by
44904
+ * where an org turns out to live. Naming a chain is the caller saying "talk
44905
+ * to this one", and silently routing elsewhere would make the argument a
44906
+ * suggestion. A client that names nothing is the one that follows the org.
44435
44907
  */
44436
- _authBearer = null;
44908
+ _explicitChain;
44909
+ /**
44910
+ * The fleet-wide chain switch, read once at construction. `resolve()` hits
44911
+ * the config file on disk, so re-reading it per call would put a file read
44912
+ * on every judge.
44913
+ */
44914
+ _forcedNetwork;
44915
+ /**
44916
+ * Short-TTL cache for `/api/ai/exists`. The `registered` field is
44917
+ * monotonic (once true, stays true), so most calls in a burst re-fetch
44918
+ * data that hasn't changed. The `org_encryption_pubkey` field CAN change
44919
+ * — an org toggling encryption mid-session — so the TTL is deliberately
44920
+ * short (see `AGENT_EXISTS_TTL_MS`). Keyed by (pubkey, network) so
44921
+ * cross-agent / cross-network calls don't collide.
44922
+ */
44923
+ _agentExistsCache = null;
44924
+ static AGENT_EXISTS_TTL_MS = 5e3;
44925
+ /** Guards `logEnvironmentOnce` — hosts construct several clients. */
44926
+ static environmentLogged = false;
44437
44927
  constructor(privkey, options = {}) {
44438
44928
  this.auth = native.loadAgent(privkey);
44439
- this.endpoint = (options.endpoint ?? DEFAULT_ENDPOINT).replace(/\/+$/, "") || DEFAULT_ENDPOINT;
44440
- this.nodeUrls = options.nodeUrls ? [...options.nodeUrls] : DEFAULT_CHROMIA_NODE_URLS;
44441
- this.blockchainRid = options.blockchainRid ?? native.DEFAULT_BLOCKCHAIN_RID;
44929
+ const validated = validateJudgeEndpoint(
44930
+ options.verifyPubKey ? {
44931
+ policy: "self-hosted",
44932
+ endpoint: options.endpoint ?? DEFAULT_ENDPOINT,
44933
+ verifyPubKey: options.verifyPubKey
44934
+ } : { endpoint: options.endpoint }
44935
+ );
44936
+ this.endpoint = validated.url;
44937
+ const resolvedChain = resolveConstructorChain(options);
44938
+ this.nodeUrls = [...resolvedChain.nodeUrls];
44939
+ this.blockchainRid = resolvedChain.blockchainRid;
44940
+ this._defaultChain = resolvedChain;
44941
+ this._explicitChain = options.chain !== void 0 || options.network !== void 0 || options.blockchainRid !== void 0 && options.nodeUrls !== void 0;
44942
+ this._forcedNetwork = forcedChainNetwork();
44442
44943
  this.orgName = options.orgName;
44443
- this.verifyPubKey = options.verifyPubKey;
44944
+ this.verifyPubKey = validated.verifyPubKey ?? void 0;
44444
44945
  this.orgEncryptionPubKey = options.orgEncryptionPubKey;
44445
44946
  this.failClosed = options.failClosed !== false;
44947
+ this.requireEnforcement = options.requireEnforcement !== false;
44948
+ this.decisionTimeoutMs = options.decisionTimeoutMs ?? DEFAULT_DECISION_TIMEOUT_MS;
44949
+ this.debug = options.debug === true;
44446
44950
  this.logger = options.logger ?? {};
44447
- this.http = new HttpClient(this.endpoint, options.timeoutMs ?? 3e4);
44951
+ this.http = new HttpClient(this.endpoint, options.timeoutMs ?? 12e4);
44952
+ this.logEnvironmentOnce();
44448
44953
  if (this.endpoint !== DEFAULT_ENDPOINT) {
44449
44954
  this.logger.warn?.("[atbash] running on non-default judge endpoint", {
44450
44955
  endpoint: this.endpoint,
44451
44956
  verifying: this.verifyPubKey ? "with response-signature pubkey configured" : "without signature verification"
44452
44957
  });
44453
44958
  }
44959
+ if (isAllowlistedJudgeHost(this.endpoint)) {
44960
+ try {
44961
+ setupTelemetry({
44962
+ enabled: true,
44963
+ endpoint: this.endpoint,
44964
+ getAuthHeaders: () => this.authHeaders()
44965
+ });
44966
+ } catch (err) {
44967
+ this.logger.warn?.(
44968
+ "[atbash] telemetry setup failed \u2014 continuing without metrics",
44969
+ { error: String(err) }
44970
+ );
44971
+ }
44972
+ } else {
44973
+ this.logger.info?.(
44974
+ "[atbash] telemetry disabled \u2014 the agent bearer is only sent to hosts that already receive it, and this judge endpoint is not one",
44975
+ { endpoint: this.endpoint }
44976
+ );
44977
+ }
44978
+ }
44979
+ /**
44980
+ * Say which environment this build talks to, once per process.
44981
+ *
44982
+ * The endpoint and both chain RIDs are compiled in, chosen by the npm tag,
44983
+ * and no configuration repoints a released build. So installing the build
44984
+ * for the wrong environment is invisible: the plugin loads, the hook fires,
44985
+ * and every judge call fails because the agent does not exist on the chain
44986
+ * this build targets. Organisation names are not unique across environments
44987
+ * either, so an org resolving is not evidence the build is right.
44988
+ */
44989
+ logEnvironmentOnce() {
44990
+ if (_Atbash.environmentLogged) return;
44991
+ _Atbash.environmentLogged = true;
44992
+ const brief = (rid) => rid ? `${rid.slice(0, 8)}\u2026` : "(unset)";
44993
+ this.logger.info?.(
44994
+ `[atbash] environment \u2014 judge=${this.endpoint} publicChain=${brief(native.DEFAULT_BLOCKCHAIN_RID)} privateChain=${brief(native.DEFAULT_PRIVATE_BLOCKCHAIN_RID)} activeChain=${brief(this.blockchainRid)} responseSignatureCheck=${this.verifyPubKey ? "on" : "off"}`,
44995
+ {
44996
+ judgeEndpoint: this.endpoint,
44997
+ publicBlockchainRid: native.DEFAULT_BLOCKCHAIN_RID,
44998
+ privateBlockchainRid: native.DEFAULT_PRIVATE_BLOCKCHAIN_RID,
44999
+ activeBlockchainRid: this.blockchainRid,
45000
+ responseSignatureCheck: Boolean(this.verifyPubKey)
45001
+ }
45002
+ );
44454
45003
  }
44455
45004
  /**
44456
45005
  * Construct from resolved config: explicit overrides → env vars → the
@@ -44460,21 +45009,116 @@ var Atbash = class _Atbash {
44460
45009
  * validated against the trusted allowlist / self-hosted policy; a
44461
45010
  * self-hosted endpoint's `verifyPubKey` becomes the client default.
44462
45011
  */
45012
+ /**
45013
+ * Decide which key this client signs as.
45014
+ *
45015
+ * Most specific wins: a key passed in code, then a key file the host named,
45016
+ * then the environment, then the default key file. `config.json` is absent
45017
+ * from that list on purpose — it is a settings file, writable by anything
45018
+ * that can write the user's home and read by every Atbash integration on the
45019
+ * machine, so letting it name the key meant one stray value silently
45020
+ * re-pointed who each of them signed as.
45021
+ *
45022
+ * A named `keyPath` that does not exist throws rather than falling through.
45023
+ * The caller said which file holds its identity; quietly signing as a
45024
+ * different one is the outcome worth refusing.
45025
+ *
45026
+ * @param options - The `fromConfig` options, read for `agentKey` and `keyPath`.
45027
+ * @returns The resolved agent identity.
45028
+ * @throws When a named key file is missing, or no identity can be found.
45029
+ */
45030
+ static resolveIdentity(options) {
45031
+ if (options.agentKey) return native.loadAgent(options.agentKey);
45032
+ if (options.keyPath) return loadAgentFromFile(options.keyPath);
45033
+ const fromEnv = agentKeyFromEnv();
45034
+ if (fromEnv) return native.loadAgent(fromEnv);
45035
+ try {
45036
+ return loadAgentFromFile();
45037
+ } catch (err) {
45038
+ throw _Atbash.explainStrandedKey(err);
45039
+ }
45040
+ }
45041
+ /**
45042
+ * Add the one thing a machine with no key file needs to hear.
45043
+ *
45044
+ * This is the only path where the operator cannot see what happened: no key
45045
+ * file, and the key they are looking for sits in `config.json`, which no
45046
+ * longer selects the identity. A bare "key file not found" sends them hunting
45047
+ * for a key they already have. Only this branch gets the hint — a caller who
45048
+ * named a `keyPath` is told about that path, where a stranded key is noise.
45049
+ *
45050
+ * @param err - The "key file not found" error from the default lookup.
45051
+ * @returns The same error, or one that also names the key in config.json.
45052
+ */
45053
+ static explainStrandedKey(err) {
45054
+ const stranded = strandedAgentKey();
45055
+ if (!stranded) return err;
45056
+ let identity;
45057
+ try {
45058
+ identity = native.derivePublicKey(stranded);
45059
+ } catch {
45060
+ identity = "(unreadable)";
45061
+ }
45062
+ const message = err instanceof Error ? err.message : String(err);
45063
+ return new Error(
45064
+ `${message}
45065
+ config.json still holds an "agentKey" (${identity}), but a settings file no longer chooses the signing key. Move it into one of the key files above, or set ATBASH_AGENT_KEY.`
45066
+ );
45067
+ }
45068
+ /**
45069
+ * Say so when `config.json` still holds an agent key.
45070
+ *
45071
+ * Nothing signs with it any more, and silence would leave an operator
45072
+ * believing one identity is in force while another is. The pubkey is named,
45073
+ * not the key, so the line is safe in a log.
45074
+ *
45075
+ * @param logger - The host logger, when one was supplied.
45076
+ */
45077
+ static warnOnStrandedKey(logger3) {
45078
+ const stranded = strandedAgentKey();
45079
+ if (!stranded) return;
45080
+ let identity;
45081
+ try {
45082
+ identity = native.derivePublicKey(stranded);
45083
+ } catch {
45084
+ identity = "(unreadable)";
45085
+ }
45086
+ logger3?.warn?.(
45087
+ `[atbash] "agentKey" in config.json is ignored \u2014 settings do not choose the signing key. It holds ${identity}; this client signs as the key file or ATBASH_AGENT_KEY instead. Move it into the key file, or delete the field, to silence this.`
45088
+ );
45089
+ }
44463
45090
  static fromConfig(options = {}) {
45091
+ const configuredEndpoint = resolve("judgeEndpoint") || void 0;
45092
+ const configuredVerifyPubKey = resolve("judgeVerifyPubKey") || void 0;
45093
+ if (!options.judge && configuredVerifyPubKey && !configuredEndpoint) {
45094
+ throw new Error(
45095
+ "judgeVerifyPubKey / ATBASH_JUDGE_VERIFY_PUBKEY is set but no judge endpoint is configured: set judgeEndpoint / ATBASH_ENDPOINT to the self-hosted judge"
45096
+ );
45097
+ }
44464
45098
  const validated = validateJudgeEndpoint(
44465
- options.judge ?? { endpoint: resolve("judgeEndpoint") || void 0 }
45099
+ options.judge ?? (configuredVerifyPubKey && configuredEndpoint ? {
45100
+ policy: "self-hosted",
45101
+ endpoint: configuredEndpoint,
45102
+ verifyPubKey: configuredVerifyPubKey
45103
+ } : { endpoint: configuredEndpoint })
44466
45104
  );
44467
- const agentKey = resolve("agentKey", options.agentKey);
44468
- const auth = agentKey ? native.loadAgent(agentKey) : loadAgentFromFile(options.keyPath);
44469
- const blockchainRid = resolve("blockchainRid", options.blockchainRid) || void 0;
45105
+ const auth = _Atbash.resolveIdentity(options);
45106
+ _Atbash.warnOnStrandedKey(options.logger);
44470
45107
  return new _Atbash(auth.privkey, {
44471
45108
  endpoint: validated.url,
44472
- blockchainRid,
45109
+ chain: options.chain,
45110
+ network: options.network,
45111
+ blockchainRid: options.blockchainRid,
44473
45112
  timeoutMs: options.timeoutMs,
44474
45113
  nodeUrls: options.nodeUrls,
44475
45114
  orgName: options.orgName,
44476
45115
  verifyPubKey: validated.verifyPubKey ?? void 0,
44477
45116
  failClosed: options.failClosed,
45117
+ requireEnforcement: options.requireEnforcement,
45118
+ decisionTimeoutMs: options.decisionTimeoutMs,
45119
+ // ATBASH_DEBUG lets an operator turn diagnostics on without editing a
45120
+ // host's plugin config, which is usually the harder half.
45121
+ debug: options.debug ?? /^(1|true|yes)$/i.test(resolve("debug")),
44478
45122
  logger: options.logger
44479
45123
  });
44480
45124
  }
@@ -44495,17 +45139,41 @@ var Atbash = class _Atbash {
44495
45139
  */
44496
45140
  async checkAgentExists(pubkey, opts) {
44497
45141
  const pk = pubkey ?? this.auth.pubkey;
45142
+ const network = opts?.network;
45143
+ const now = Date.now();
45144
+ const cached = this._agentExistsCache;
45145
+ if (cached && cached.pubkey === pk && cached.network === network && cached.expiresAt > now) {
45146
+ if (pk === this.auth.pubkey) {
45147
+ this._orgKeyFromChain = cached.orgKey;
45148
+ }
45149
+ return cached.registered;
45150
+ }
44498
45151
  return this.track("checkAgentExists", pk, async () => {
44499
45152
  const query = { pubkey: pk };
44500
- if (opts?.network) query.network = opts.network;
45153
+ if (network) query.network = network;
45154
+ const brid = network ? this.bridFromChainOpts({ network }) : await this.defaultOrgBrid();
44501
45155
  const resp = await this.http.get(
44502
45156
  "/api/ai/exists",
44503
45157
  query,
44504
- this.authHeaders()
45158
+ this.authHeaders(brid)
44505
45159
  );
44506
45160
  await this.raiseIfError(resp);
44507
45161
  const data = await this.json(resp);
44508
- return Boolean(data?.registered);
45162
+ const registered = Boolean(data?.registered);
45163
+ const orgKey = typeof data?.org_encryption_pubkey === "string" && data.org_encryption_pubkey ? data.org_encryption_pubkey : null;
45164
+ if (registered) {
45165
+ this._agentExistsCache = {
45166
+ pubkey: pk,
45167
+ network,
45168
+ expiresAt: Date.now() + _Atbash.AGENT_EXISTS_TTL_MS,
45169
+ registered,
45170
+ orgKey
45171
+ };
45172
+ }
45173
+ if (pk === this.auth.pubkey) {
45174
+ this._orgKeyFromChain = orgKey;
45175
+ }
45176
+ return registered;
44509
45177
  });
44510
45178
  }
44511
45179
  /* ── log_tool_call (sign-only) ─────────────────────────────────────────── */
@@ -44534,8 +45202,8 @@ var Atbash = class _Atbash {
44534
45202
  };
44535
45203
  }
44536
45204
  const toolCallId = generateToolCallId();
44537
- const brid = this.bridFromChainOpts(options.chainOpts);
44538
- const orgKey = options.orgEncryptionPubKey ?? this.orgEncryptionPubKey;
45205
+ const brid = options.chainOpts?.blockchainRid || options.chainOpts?.network ? this.bridFromChainOpts(options.chainOpts) : await this.defaultOrgBrid() ?? this.blockchainRid;
45206
+ const orgKey = options.orgEncryptionPubKey ?? this.orgEncryptionPubKey ?? this._orgKeyFromChain;
44539
45207
  try {
44540
45208
  const signedHex = orgKey ? signEncryptedToolCall(
44541
45209
  toolCallId,
@@ -44570,24 +45238,42 @@ var Atbash = class _Atbash {
44570
45238
  * response bytes via the Rust core's `verifySignature`.
44571
45239
  */
44572
45240
  async judgeAction(action, context = "", options = {}) {
44573
- return this.track(
44574
- "judgeAction",
44575
- this.auth.pubkey,
44576
- () => this._judgeAction(action, context, options)
44577
- );
45241
+ return this.track("judgeAction", this.auth.pubkey, async () => {
45242
+ try {
45243
+ return await this._judgeAction(action, context, options);
45244
+ } catch (err) {
45245
+ if (!isEncryptionStateMismatch(err)) throw err;
45246
+ this._orgKeyFromChain = null;
45247
+ return await this._judgeAction(action, context, options);
45248
+ }
45249
+ });
44578
45250
  }
44579
45251
  async _judgeAction(action, context, options) {
44580
45252
  if (!action?.trim()) {
44581
45253
  throw new Error("action is required and cannot be empty.");
44582
45254
  }
44583
45255
  let chainOpts = options.chainOpts;
44584
- if (options.orgName) {
44585
- const mapNetwork = await this.getActiveNetworkForOrg(options.orgName);
44586
- if (mapNetwork) {
44587
- chainOpts = { network: mapNetwork };
44588
- } else if (!chainOpts?.blockchainRid) {
44589
- const resolved = await this.resolveChainFromMap(options.orgName, null);
44590
- chainOpts = { ...chainOpts, network: resolved.network };
45256
+ if (options.orgName && this._explicitChain) {
45257
+ chainOpts = options.chainOpts ?? { network: this._defaultChain.network };
45258
+ } else if (options.orgName && this.forcedNetwork()) {
45259
+ chainOpts = { network: this.forcedNetwork() };
45260
+ } else if (options.orgName) {
45261
+ const cached = this._chainCache.get(options.orgName);
45262
+ if (cached) {
45263
+ chainOpts = { network: cached.network };
45264
+ } else {
45265
+ const mapNetwork = await this.getActiveNetworkForOrg(options.orgName);
45266
+ if (mapNetwork) {
45267
+ const chain = mapNetwork === "private" ? PRIVATE_CHAIN : PUBLIC_CHAIN;
45268
+ this._chainCache.set(options.orgName, chain);
45269
+ chainOpts = { network: mapNetwork };
45270
+ } else if (!chainOpts?.blockchainRid) {
45271
+ const resolved = await this.resolveChainFromMap(
45272
+ options.orgName,
45273
+ null
45274
+ );
45275
+ chainOpts = { ...chainOpts, network: resolved.network };
45276
+ }
44591
45277
  }
44592
45278
  }
44593
45279
  const brid = this.bridFromChainOpts(chainOpts);
@@ -44599,18 +45285,15 @@ var Atbash = class _Atbash {
44599
45285
  if (!logResult.success || !logResult.toolCallId || !logResult.signedHex) {
44600
45286
  throw new Error(logResult.error || "Failed to sign log_tool_call");
44601
45287
  }
44602
- let signedJudgeAction;
44603
- if (!options.provider) {
44604
- const judgmentId = generateToolCallId();
44605
- signedJudgeAction = native.signJudgeAction(
44606
- judgmentId,
44607
- action,
44608
- context || "",
44609
- "",
44610
- this.auth.privkey,
44611
- brid
44612
- );
44613
- }
45288
+ const judgmentId = generateToolCallId();
45289
+ const signedJudgeAction = native.signJudgeAction(
45290
+ judgmentId,
45291
+ action,
45292
+ context || "",
45293
+ "",
45294
+ this.auth.privkey,
45295
+ brid
45296
+ );
44614
45297
  const body = {
44615
45298
  tool_call_id: logResult.toolCallId,
44616
45299
  agent_pubkey: this.auth.pubkey,
@@ -44619,9 +45302,8 @@ var Atbash = class _Atbash {
44619
45302
  };
44620
45303
  if (signedJudgeAction) body.signed_judge_action = signedJudgeAction;
44621
45304
  if (context) body.context = context;
44622
- if (options.provider) body.provider = options.provider;
44623
45305
  if (options.toolName) body.tool_name = options.toolName;
44624
- if (options.model) body.model = options.model;
45306
+ if (options.toolArgsJson) body.tool_args_json = options.toolArgsJson;
44625
45307
  if (options.resolved) body.resolved = options.resolved;
44626
45308
  if (options.mode) body.mode = options.mode;
44627
45309
  let resp;
@@ -44632,44 +45314,28 @@ var Atbash = class _Atbash {
44632
45314
  }
44633
45315
  if (!resp.ok) throw await this.httpError(resp);
44634
45316
  const bodyBytes = Buffer.from(await resp.arrayBuffer());
44635
- const verifyPubKey = options.verifyPubKey ?? this.verifyPubKey;
45317
+ const verifyPubKey = this.effectiveVerifyKey(options.verifyPubKey);
44636
45318
  if (verifyPubKey !== void 0) {
44637
- const sig = resp.headers.get("X-Atbash-Signature");
44638
- if (!sig) {
44639
- throw new SignatureVerificationError(
44640
- "missing X-Atbash-Signature header"
44641
- );
44642
- }
44643
- let ok;
44644
- try {
44645
- ok = native.verifySignature(bodyBytes, sig, verifyPubKey);
44646
- } catch (err) {
44647
- throw new SignatureVerificationError(
44648
- `signature verification threw: ${errorMessage(err)}`
44649
- );
44650
- }
44651
- if (!ok) {
44652
- throw new SignatureVerificationError(
44653
- "signature does not verify against configured verifyPubKey"
44654
- );
44655
- }
45319
+ verifyResponseSignature(bodyBytes, resp, verifyPubKey);
44656
45320
  }
44657
45321
  const data = parseJson(bodyBytes);
44658
45322
  const rawScore = data.score;
44659
45323
  const score = typeof rawScore === "number" && Number.isInteger(rawScore) && rawScore >= 1 && rawScore <= 10 ? rawScore : void 0;
44660
45324
  return {
44661
45325
  verdict: normalizeVerdict(data.verdict),
44662
- actionType: String(data.action_type ?? ""),
44663
- reason: String(data.reason ?? ""),
44664
- confidence: Number(data.confidence ?? 0),
44665
- provider: String(data.provider ?? ""),
44666
- latencyMs: Number(data.latency_ms ?? 0),
44667
- toolCallId: String(data.tool_call_id ?? logResult.toolCallId),
45326
+ allow: this.executable(data),
45327
+ actionType: normalizeActionType(data.action_type),
45328
+ reason: wireText(data.reason),
45329
+ confidence: wireNumber(data.confidence),
45330
+ provider: wireText(data.provider),
45331
+ latencyMs: wireNumber(data.latency_ms),
45332
+ toolCallId: wireText(data.tool_call_id, logResult.toolCallId),
44668
45333
  onChain: Boolean(data.on_chain),
44669
45334
  enforced: Boolean(data.enforced),
44670
- enforcementMode: String(data.enforcement_mode ?? ""),
44671
- status: String(data.status ?? ""),
44672
- score
45335
+ enforcementMode: wireText(data.enforcement_mode),
45336
+ status: wireText(data.status),
45337
+ score,
45338
+ refusal: explicitRefusal(data)
44673
45339
  };
44674
45340
  }
44675
45341
  /* ── audit_tool_call (redact → judge → decision) ───────────────────────── */
@@ -44702,97 +45368,197 @@ var Atbash = class _Atbash {
44702
45368
  }
44703
45369
  try {
44704
45370
  this.logger.info?.("[atbash] judge API called", { tool: toolName });
44705
- const result = await this.judgeAction(actionText, contextText, {
44706
- toolName,
44707
- toolArgsJson: argsJson,
44708
- orgName: this.orgName,
44709
- // Passed through unredacted — caller vouches for the contents.
44710
- resolved: input.resolved
44711
- });
44712
- if (result.verdict === "No verdict") {
44713
- if (result.status !== "logged") {
44714
- return this.fail(
44715
- `judge returned no verdict without an audit-tier marker (status: ${result.status || "absent"})`,
44716
- result.toolCallId
44717
- );
44718
- }
44719
- return {
44720
- allow: true,
44721
- verdict: "ALLOW",
44722
- reason: result.reason || "audit tier \u2014 request logged on-chain, no AI enforcement",
44723
- toolCallId: result.toolCallId
44724
- };
44725
- }
44726
- const action = result.actionType;
44727
- if (action === "block") {
45371
+ const result = await withDeadline(
45372
+ this.judgeAction(actionText, contextText, {
45373
+ toolName,
45374
+ toolArgsJson: argsJson,
45375
+ orgName: this.orgName,
45376
+ // Passed through unredacted — caller vouches for the contents.
45377
+ resolved: input.resolved
45378
+ }),
45379
+ this.decisionTimeoutMs
45380
+ );
45381
+ return this.decide(result);
45382
+ } catch (err) {
45383
+ if (err instanceof SignatureVerificationError) {
45384
+ this.failJudge(errorMessage(err), err);
44728
45385
  return {
44729
45386
  allow: false,
44730
- verdict: "BLOCK",
44731
- reason: result.reason,
44732
- toolCallId: result.toolCallId
45387
+ verdict: "ERROR",
45388
+ reason: `The judge's reply failed its signature check (${errorMessage(err)}), so it was not trusted.`
44733
45389
  };
44734
45390
  }
44735
- if (action === "hold_for_user_confirm") {
44736
- return {
44737
- allow: false,
44738
- verdict: "HOLD",
44739
- reason: result.reason || "held for human confirmation",
44740
- toolCallId: result.toolCallId
44741
- };
45391
+ return this.failJudge(errorMessage(err), err);
45392
+ }
45393
+ }
45394
+ /**
45395
+ * The verify key for one call (R4, governor tier-2 review). A per-call key
45396
+ * may only narrow what the client accepts: on a client pinned to a judge
45397
+ * key it must be that same key, never a replacement; on an unpinned client
45398
+ * it adds the check.
45399
+ */
45400
+ effectiveVerifyKey(perCall) {
45401
+ if (perCall === void 0) return this.verifyPubKey;
45402
+ const key3 = perCall.trim().toLowerCase();
45403
+ if (this.verifyPubKey !== void 0 && key3 !== this.verifyPubKey) {
45404
+ throw new SignatureVerificationError(
45405
+ "a per-call verifyPubKey cannot replace the judge key this client is pinned to"
45406
+ );
45407
+ }
45408
+ return key3;
45409
+ }
45410
+ /**
45411
+ * Collapse a judge result into a {@link Decision}. The most restrictive
45412
+ * signal wins (security review 2026-09-30, H1): `action_type`, `verdict`
45413
+ * and the canonical `allow` are each able to deny, and only a result where
45414
+ * all three agree may execute. A present `allow` / `decision.allow` that is
45415
+ * not exactly `true` is the judge declining to grant permission, so it
45416
+ * denies even under `failClosed: false` — that option relaxes *errors*, it
45417
+ * never overrides a refusal.
45418
+ */
45419
+ decide(result) {
45420
+ const toolCallId = result.toolCallId;
45421
+ const deny = (verdict, reason) => ({
45422
+ allow: false,
45423
+ verdict,
45424
+ reason,
45425
+ toolCallId
45426
+ });
45427
+ const notGranted = "the judge response did not grant permission";
45428
+ const held = deny("HOLD", result.reason || "held for human confirmation");
45429
+ const blocked = deny("BLOCK", result.reason || notGranted);
45430
+ if (result.refusal === "BLOCK") return blocked;
45431
+ if (result.verdict === "No verdict") {
45432
+ if (result.actionType === "block") {
45433
+ return blocked;
45434
+ }
45435
+ if (result.actionType === "hold_for_user_confirm") {
45436
+ return held;
45437
+ }
45438
+ if (result.refusal === "HOLD") return held;
45439
+ if (result.status !== "logged") {
45440
+ return this.failJudge(
45441
+ `judge returned no verdict without an audit-tier marker (status: ${result.status || "absent"})`,
45442
+ void 0,
45443
+ toolCallId
45444
+ );
44742
45445
  }
44743
- if (action === "allow") {
44744
- if (result.verdict === "HOLD") {
44745
- return {
44746
- allow: false,
44747
- verdict: "HOLD",
44748
- reason: result.reason,
44749
- toolCallId: result.toolCallId
44750
- };
44751
- }
44752
- if (result.verdict === "BLOCK") {
44753
- return {
44754
- allow: false,
44755
- verdict: "BLOCK",
44756
- reason: result.reason,
44757
- toolCallId: result.toolCallId
44758
- };
44759
- }
45446
+ if (this.requireEnforcement) {
45447
+ this.logger.warn?.(
45448
+ "[atbash] judge did not enforce this action (audit tier) and requireEnforcement is on: denied",
45449
+ { toolCallId }
45450
+ );
44760
45451
  return {
44761
- allow: true,
44762
- verdict: "ALLOW",
44763
- reason: result.reason,
44764
- toolCallId: result.toolCallId
45452
+ allow: false,
45453
+ verdict: "ERROR",
45454
+ 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.",
45455
+ toolCallId
44765
45456
  };
44766
45457
  }
44767
- return this.fail(
44768
- "unrecognized action_type from judge",
44769
- result.toolCallId
44770
- );
44771
- } catch (err) {
44772
- const message = errorMessage(err);
44773
- this.logger.warn?.("[atbash] judge API failed", { reason: message });
44774
- return this.fail(message);
45458
+ if (result.allow !== true) return deny("BLOCK", notGranted);
45459
+ return {
45460
+ allow: true,
45461
+ verdict: "ALLOW",
45462
+ reason: result.reason || "audit tier \u2014 request logged on-chain, no AI enforcement",
45463
+ toolCallId
45464
+ };
45465
+ }
45466
+ const action = result.actionType;
45467
+ if (action === "block") {
45468
+ return deny("BLOCK", result.reason || "Blocked by your organisation's Atbash policy.");
44775
45469
  }
45470
+ if (action === "hold_for_user_confirm") {
45471
+ return held;
45472
+ }
45473
+ if (result.refusal === "HOLD") return held;
45474
+ if (action === "allow") {
45475
+ if (result.verdict === "HOLD") return held;
45476
+ if (result.verdict === "BLOCK") return blocked;
45477
+ if (result.allow !== true) return deny("BLOCK", notGranted);
45478
+ return {
45479
+ allow: true,
45480
+ verdict: "ALLOW",
45481
+ reason: result.reason,
45482
+ toolCallId
45483
+ };
45484
+ }
45485
+ return this.failJudge(
45486
+ "unrecognized action_type from judge",
45487
+ void 0,
45488
+ toolCallId
45489
+ );
45490
+ }
45491
+ /**
45492
+ * One exit for every judge failure.
45493
+ *
45494
+ * Status and reason go in the *message*, not only in the meta object: hosts
45495
+ * print the message and drop the meta, which is why this read as a bare
45496
+ * "judge API failed" while the judge was answering with a precise reason.
45497
+ * The response body follows only under `debug`, since it can echo the action.
45498
+ */
45499
+ failJudge(reason, cause, toolCallId) {
45500
+ const api2 = cause instanceof AtbashAPIError ? cause : null;
45501
+ const userReason = userFacingReason(reason, api2);
45502
+ const status = api2 ? ` status=${api2.status || "no-response"}` : "";
45503
+ const detail = this.debug ? ` detail=${truncate(reason, 500)}` : "";
45504
+ const body = this.debug && api2?.body ? ` body=${truncate(api2.body, 500)}` : "";
45505
+ this.logger.warn?.(
45506
+ `[atbash] judge API failed \u2014${status} reason=${truncate(userReason, 300)}${detail}${body}`,
45507
+ {
45508
+ reason: userReason,
45509
+ ...api2 ? { status: api2.status } : {},
45510
+ ...this.debug && api2 ? { body: api2.body, detail: reason } : {},
45511
+ endpoint: this.endpoint,
45512
+ ...toolCallId ? { toolCallId } : {}
45513
+ }
45514
+ );
45515
+ return this.fail(userReason, toolCallId);
45516
+ }
45517
+ /**
45518
+ * The canonical permission for a response body under this client's
45519
+ * settings: {@link canonicalAllow}, minus the audit tier when
45520
+ * `requireEnforcement` is on. Never more permissive than `auditToolCall`.
45521
+ */
45522
+ executable(data) {
45523
+ if (!canonicalAllow(data)) return false;
45524
+ return !(this.requireEnforcement && isAuditTierBody(data));
44776
45525
  }
44777
45526
  fail(reason, toolCallId) {
44778
45527
  return { allow: !this.failClosed, verdict: "ERROR", reason, toolCallId };
44779
45528
  }
44780
45529
  /* ── judgment status ───────────────────────────────────────────────────── */
44781
- async getJudgmentStatus(judgmentId, agentPubkey) {
45530
+ /**
45531
+ * Return the current status of a previously submitted judgment.
45532
+ *
45533
+ * `chainOpts` names which chain the judgment was signed against. The
45534
+ * server's GET /api/v1/judge routes to that chain when the SDK sends
45535
+ * a `brid` query param; without it, the server falls back to public.
45536
+ * Callers on the private chain must pass a `chainOpts` (or configure
45537
+ * the client on the private chain) — otherwise polling a POSTed
45538
+ * judgment on the private chain 404s at the server.
45539
+ */
45540
+ async getJudgmentStatus(judgmentId, agentPubkey, chainOpts) {
44782
45541
  const pk = agentPubkey ?? this.auth.pubkey;
45542
+ const brid = this.bridFromChainOpts(chainOpts);
44783
45543
  return this.track("getJudgmentStatus", pk, async () => {
44784
45544
  const resp = await this.http.get(
44785
45545
  "/api/v1/judge",
44786
- { tool_call_id: judgmentId, agent_pubkey: pk },
44787
- this.authHeaders()
45546
+ { tool_call_id: judgmentId, agent_pubkey: pk, brid },
45547
+ this.authHeaders(brid)
44788
45548
  );
44789
45549
  await this.raiseIfError(resp);
44790
- const data = await this.json(resp) ?? {};
45550
+ const bytes = Buffer.from(await resp.arrayBuffer());
45551
+ if (this.verifyPubKey !== void 0) {
45552
+ verifyResponseSignature(bytes, resp, this.verifyPubKey);
45553
+ }
45554
+ const parsed = tryParseJson(bytes.toString("utf-8"));
45555
+ const data = isRecord2(parsed) ? parsed : {};
44791
45556
  return {
44792
45557
  status: normalizeStatus(data.status),
44793
45558
  verdict: normalizeVerdict(data.verdict),
44794
- reason: String(data.reason ?? ""),
44795
- judgmentId: String(data.judgmentId ?? judgmentId),
45559
+ allow: this.executable(data),
45560
+ reason: wireText(data.reason),
45561
+ judgmentId: wireText(data.judgmentId, judgmentId),
44796
45562
  onChain: optBool(data.onChain),
44797
45563
  cached: optBool(data.cached),
44798
45564
  responseTimeMs: optNumber(data.responseTimeMs)
@@ -44804,49 +45570,65 @@ var Atbash = class _Atbash {
44804
45570
  return this.track(
44805
45571
  "getToolCalls",
44806
45572
  void 0,
44807
- () => this.riskEngineRecords("tool-calls", { limit: maxCount })
45573
+ async () => this.riskEngineRecords(
45574
+ "tool-calls",
45575
+ { limit: maxCount },
45576
+ await this.defaultOrgBrid()
45577
+ )
44808
45578
  );
44809
45579
  }
44810
- getOrgToolCalls(orgName, maxCount) {
44811
- return this.track(
44812
- "getOrgToolCalls",
44813
- void 0,
44814
- () => this.riskEngineRecords("org-tool-calls", {
44815
- org: orgName,
44816
- limit: maxCount
44817
- })
44818
- );
45580
+ async getOrgToolCalls(orgName, maxCount) {
45581
+ return this.track("getOrgToolCalls", void 0, async () => {
45582
+ const brid = await this.bridForOrg(orgName);
45583
+ return this.riskEngineRecords(
45584
+ "org-tool-calls",
45585
+ { org: orgName, limit: maxCount },
45586
+ brid
45587
+ );
45588
+ });
44819
45589
  }
44820
45590
  getAgentToolCalls(agentPubkey, maxCount) {
44821
45591
  return this.track(
44822
45592
  "getAgentToolCalls",
44823
45593
  agentPubkey,
44824
- () => this.riskEngineRecords("agent-tool-calls", {
44825
- agent: agentPubkey,
44826
- limit: maxCount
44827
- })
45594
+ async () => this.riskEngineRecords(
45595
+ "agent-tool-calls",
45596
+ { agent: agentPubkey, limit: maxCount },
45597
+ await this.defaultOrgBrid()
45598
+ )
44828
45599
  );
44829
45600
  }
44830
45601
  async getToolCallCount() {
44831
45602
  return this.track("getToolCallCount", void 0, async () => {
44832
- const raw2 = await this.riskEngineGet("tool-call-count", {});
45603
+ const raw2 = await this.riskEngineGet(
45604
+ "tool-call-count",
45605
+ {},
45606
+ await this.defaultOrgBrid()
45607
+ );
44833
45608
  const n = Number(raw2);
44834
45609
  return Number.isFinite(n) ? n : 0;
44835
45610
  });
44836
45611
  }
44837
45612
  async getToolCallFull(toolCallId) {
44838
45613
  return this.track("getToolCallFull", void 0, async () => {
44839
- const raw2 = await this.riskEngineGet("tool-call-full", {
44840
- tool_call_id: toolCallId
44841
- });
44842
- if (!isRecord(raw2)) return null;
45614
+ const raw2 = await this.riskEngineGet(
45615
+ "tool-call-full",
45616
+ { tool_call_id: toolCallId },
45617
+ await this.defaultOrgBrid()
45618
+ );
45619
+ if (!isRecord2(raw2)) return null;
44843
45620
  return toToolCallFull(raw2);
44844
45621
  });
44845
45622
  }
44846
45623
  async getOrgTierInfo(orgName) {
44847
45624
  return this.track("getOrgTierInfo", void 0, async () => {
44848
- const raw2 = await this.riskEngineGet("org-tier-info", { org: orgName });
44849
- if (!isRecord(raw2)) return null;
45625
+ const brid = await this.bridForOrg(orgName);
45626
+ const raw2 = await this.riskEngineGet(
45627
+ "org-tier-info",
45628
+ { org: orgName },
45629
+ brid
45630
+ );
45631
+ if (!isRecord2(raw2)) return null;
44850
45632
  return {
44851
45633
  orgName: String(raw2.org_name ?? ""),
44852
45634
  tier: String(raw2.tier ?? ""),
@@ -44857,20 +45639,24 @@ var Atbash = class _Atbash {
44857
45639
  }
44858
45640
  async getPendingHeldActions(orgName, maxCount) {
44859
45641
  return this.track("getPendingHeldActions", void 0, async () => {
44860
- const raw2 = await this.riskEngineGet("pending-held-actions", {
44861
- org: orgName,
44862
- limit: maxCount
44863
- });
45642
+ const brid = await this.bridForOrg(orgName);
45643
+ const raw2 = await this.riskEngineGet(
45644
+ "pending-held-actions",
45645
+ { org: orgName, limit: maxCount },
45646
+ brid
45647
+ );
44864
45648
  if (!Array.isArray(raw2)) return [];
44865
45649
  return raw2.map((item) => toHeldAction(item));
44866
45650
  });
44867
45651
  }
44868
45652
  async getHeldActionReviews(orgName, maxCount) {
44869
45653
  return this.track("getHeldActionReviews", void 0, async () => {
44870
- const raw2 = await this.riskEngineGet("held-action-reviews", {
44871
- org: orgName,
44872
- limit: maxCount
44873
- });
45654
+ const brid = await this.bridForOrg(orgName);
45655
+ const raw2 = await this.riskEngineGet(
45656
+ "held-action-reviews",
45657
+ { org: orgName, limit: maxCount },
45658
+ brid
45659
+ );
44874
45660
  if (!Array.isArray(raw2)) return [];
44875
45661
  return raw2.map(
44876
45662
  (item) => toHeldActionReview(item)
@@ -44878,19 +45664,29 @@ var Atbash = class _Atbash {
44878
45664
  });
44879
45665
  }
44880
45666
  /* ── risk-engine batched (action-dispatched POST) ──────────────────────── */
44881
- getAgentDetail(agentPubkey) {
44882
- return this.track(
44883
- "getAgentDetail",
44884
- agentPubkey,
44885
- () => this.riskEnginePost({ action: "agent-detail-batch", agent: agentPubkey })
44886
- );
45667
+ async getAgentDetail(agentPubkey, options = {}) {
45668
+ return this.track("getAgentDetail", agentPubkey, async () => {
45669
+ const network = await this.resolveAgentLookupNetwork(options);
45670
+ const brid = network ? this.bridFromChainOpts({ network }) : void 0;
45671
+ return this.riskEnginePost(
45672
+ { action: "agent-detail-batch", agent: agentPubkey },
45673
+ network,
45674
+ brid
45675
+ );
45676
+ });
44887
45677
  }
44888
- async getAgentPolicy(agentPubkey) {
45678
+ async getAgentPolicy(agentPubkey, options = {}) {
44889
45679
  return this.track("getAgentPolicy", agentPubkey, async () => {
44890
- const raw2 = await this.riskEnginePost({
44891
- action: "agent-policy-batch",
44892
- agent: agentPubkey
44893
- });
45680
+ const network = await this.resolveAgentLookupNetwork(options);
45681
+ const brid = network ? this.bridFromChainOpts({ network }) : void 0;
45682
+ const raw2 = await this.riskEnginePost(
45683
+ {
45684
+ action: "agent-policy-batch",
45685
+ agent: agentPubkey
45686
+ },
45687
+ network,
45688
+ brid
45689
+ );
44894
45690
  return {
44895
45691
  policy: String(raw2.policy ?? ""),
44896
45692
  isJailed: Boolean(raw2.is_jailed),
@@ -44905,11 +45701,11 @@ var Atbash = class _Atbash {
44905
45701
  const resp = await this.http.get(
44906
45702
  "/api/insurance",
44907
45703
  { action: "safety-stats" },
44908
- this.authHeaders()
45704
+ this.authHeaders(await this.defaultOrgBrid())
44909
45705
  );
44910
45706
  await this.raiseIfError(resp);
44911
45707
  const data = await this.json(resp) ?? {};
44912
- if (isRecord(data.data)) return data.data;
45708
+ if (isRecord2(data.data)) return data.data;
44913
45709
  return data;
44914
45710
  });
44915
45711
  }
@@ -44923,8 +45719,9 @@ var Atbash = class _Atbash {
44923
45719
  return this.track("getOrgSubscription", void 0, async () => {
44924
45720
  const params = { org: orgName };
44925
45721
  if (network) params.network = network;
44926
- const raw2 = await this.riskEngineGet("org-subscription", params);
44927
- if (!isRecord(raw2)) return null;
45722
+ const brid = network ? this.bridFromChainOpts({ network }) : void 0;
45723
+ const raw2 = await this.riskEngineGet("org-subscription", params, brid);
45724
+ if (!isRecord2(raw2)) return null;
44928
45725
  return coerceOrgSubscription(raw2, orgName);
44929
45726
  });
44930
45727
  }
@@ -44936,21 +45733,22 @@ var Atbash = class _Atbash {
44936
45733
  * entry (caller falls back to per-chain subscription resolution).
44937
45734
  */
44938
45735
  async getActiveNetworkForOrg(orgName) {
45736
+ let resp;
44939
45737
  try {
44940
- const resp = await this.http.get(
45738
+ resp = await this.http.get(
44941
45739
  "/api/org-network",
44942
- { org: orgName },
45740
+ { org: orgName.trim() },
44943
45741
  this.authHeaders()
44944
45742
  );
44945
- if (resp.status !== 200) return null;
44946
- const data = await this.json(resp);
44947
- if (data?.network === "public" || data?.network === "private") {
44948
- return data.network;
44949
- }
44950
- return null;
44951
- } catch {
44952
- return null;
45743
+ } catch (err) {
45744
+ throw this.transportError(err);
44953
45745
  }
45746
+ if (resp.status !== 200) throw await this.httpError(resp);
45747
+ const data = await this.json(resp);
45748
+ if (data?.network === "public" || data?.network === "private") {
45749
+ return data.network;
45750
+ }
45751
+ return null;
44954
45752
  }
44955
45753
  /**
44956
45754
  * Resolve which chain an org's actions should run against. Cached
@@ -44959,13 +45757,19 @@ var Atbash = class _Atbash {
44959
45757
  * 2. Per-chain subscription fallback — public + private records
44960
45758
  * are fetched in parallel, with `is_private_blockchain` and
44961
45759
  * `assigned_at` reconciling mixed states.
44962
- * Defaults to the public chain when nothing else resolves.
45760
+ * A lookup that names exactly one chain wins outright. Where it names
45761
+ * neither (a brand-new org) or cannot choose between them, the client's
45762
+ * configured default decides.
44963
45763
  */
44964
45764
  async resolveChainForOrg(orgName) {
44965
- const cached = this._chainCache.get(orgName);
45765
+ const name2 = orgName.trim();
45766
+ if (this._explicitChain) return this._defaultChain;
45767
+ const forced = this.forcedNetwork();
45768
+ if (forced) return chainForNetwork(forced);
45769
+ const cached = this._chainCache.get(name2);
44966
45770
  if (cached) return cached;
44967
- const mapNetwork = await this.getActiveNetworkForOrg(orgName);
44968
- return this.resolveChainFromMap(orgName, mapNetwork);
45771
+ const mapNetwork = await this.getActiveNetworkForOrg(name2);
45772
+ return this.resolveChainFromMap(name2, mapNetwork);
44969
45773
  }
44970
45774
  /**
44971
45775
  * Resolve a chain given an already-fetched `org_networks` map result.
@@ -44981,37 +45785,50 @@ var Atbash = class _Atbash {
44981
45785
  this._chainCache.set(orgName, chain);
44982
45786
  return chain;
44983
45787
  }
44984
- try {
44985
- const [pubSub, privSub] = await Promise.all([
44986
- this.getOrgSubscription(orgName, "public").catch(() => null),
44987
- this.getOrgSubscription(orgName, "private").catch(() => null)
44988
- ]);
44989
- if (pubSub?.is_private_blockchain) {
44990
- this._chainCache.set(orgName, PRIVATE_CHAIN);
44991
- return PRIVATE_CHAIN;
44992
- }
44993
- if (pubSub && privSub) {
44994
- const chain = privSub.assigned_at > pubSub.assigned_at ? PRIVATE_CHAIN : PUBLIC_CHAIN;
44995
- this._chainCache.set(orgName, chain);
44996
- return chain;
44997
- }
44998
- if (pubSub) {
44999
- this._chainCache.set(orgName, PUBLIC_CHAIN);
45000
- return PUBLIC_CHAIN;
45001
- }
45002
- if (privSub?.is_private_blockchain) {
45003
- this._chainCache.set(orgName, PRIVATE_CHAIN);
45004
- return PRIVATE_CHAIN;
45005
- }
45006
- } catch {
45788
+ const [pubRes, privRes] = await Promise.allSettled([
45789
+ this.getOrgSubscription(orgName, "public"),
45790
+ this.getOrgSubscription(orgName, "private")
45791
+ ]);
45792
+ const pubSub = pubRes.status === "fulfilled" ? pubRes.value : null;
45793
+ const privSub = privRes.status === "fulfilled" ? privRes.value : null;
45794
+ const failure = pubRes.status === "rejected" ? pubRes.reason : privRes.status === "rejected" ? privRes.reason : null;
45795
+ if (pubSub?.is_private_blockchain) {
45796
+ this._chainCache.set(orgName, PRIVATE_CHAIN);
45797
+ return PRIVATE_CHAIN;
45798
+ }
45799
+ if (pubSub && privSub) {
45800
+ const chain = privSub.assigned_at === pubSub.assigned_at ? this._defaultChain : privSub.assigned_at > pubSub.assigned_at ? PRIVATE_CHAIN : PUBLIC_CHAIN;
45801
+ this._chainCache.set(orgName, chain);
45802
+ return chain;
45803
+ }
45804
+ if (pubSub) {
45805
+ this._chainCache.set(orgName, PUBLIC_CHAIN);
45806
+ return PUBLIC_CHAIN;
45007
45807
  }
45008
- this._chainCache.set(orgName, PUBLIC_CHAIN);
45009
- return PUBLIC_CHAIN;
45808
+ if (privSub?.is_private_blockchain) {
45809
+ this._chainCache.set(orgName, PRIVATE_CHAIN);
45810
+ return PRIVATE_CHAIN;
45811
+ }
45812
+ if (failure) {
45813
+ const detail = failure instanceof Error ? failure.message : String(failure);
45814
+ throw new AtbashAPIError(
45815
+ failure instanceof AtbashAPIError ? failure.status : 0,
45816
+ `could not resolve the chain for org "${orgName}": ${detail}`,
45817
+ "",
45818
+ this.endpoint
45819
+ );
45820
+ }
45821
+ this._chainCache.set(orgName, this._defaultChain);
45822
+ return this._defaultChain;
45010
45823
  }
45011
45824
  /** Drop any cached chain resolutions. Useful in tests. */
45012
45825
  clearChainCache() {
45013
45826
  this._chainCache.clear();
45014
45827
  }
45828
+ /** Drop the short-TTL `/api/ai/exists` cache. Useful in tests. */
45829
+ clearAgentExistsCache() {
45830
+ this._agentExistsCache = null;
45831
+ }
45015
45832
  /* ── internals ─────────────────────────────────────────────────────────── */
45016
45833
  /**
45017
45834
  * Wrap an SDK method body in telemetry — records the call at start
@@ -45025,10 +45842,28 @@ var Atbash = class _Atbash {
45025
45842
  recordCall(name2, void 0, agentPubkey);
45026
45843
  try {
45027
45844
  const result = await fn();
45028
- recordDuration(name2, performance.now() - start, "success");
45845
+ const durationMs = performance.now() - start;
45846
+ recordDuration(name2, durationMs, "success");
45847
+ recordEvent({
45848
+ functionName: name2,
45849
+ durationMs,
45850
+ status: "success",
45851
+ agentPubkey,
45852
+ chain: this.blockchainRid
45853
+ });
45029
45854
  return result;
45030
45855
  } catch (err) {
45031
- recordDuration(name2, performance.now() - start, "error");
45856
+ const durationMs = performance.now() - start;
45857
+ recordDuration(name2, durationMs, "error");
45858
+ recordEvent({
45859
+ functionName: name2,
45860
+ durationMs,
45861
+ status: "error",
45862
+ agentPubkey,
45863
+ chain: this.blockchainRid,
45864
+ errorClass: err instanceof Error ? err.constructor.name : typeof err,
45865
+ ...errorDetail(err)
45866
+ });
45032
45867
  throw err;
45033
45868
  }
45034
45869
  }
@@ -45043,6 +45878,21 @@ var Atbash = class _Atbash {
45043
45878
  if (chainOpts?.network === "public") return PUBLIC_CHAIN.blockchainRid;
45044
45879
  return this.blockchainRid;
45045
45880
  }
45881
+ /**
45882
+ * Resolve the dashboard chain used by agent metadata/policy reads.
45883
+ * Explicit per-call network overrides win; otherwise use the supplied org
45884
+ * or the client's configured default org. A custom BRID is intentionally
45885
+ * left untouched because it cannot be represented by the dashboard's
45886
+ * public/private query selector.
45887
+ */
45888
+ async resolveAgentLookupNetwork(options) {
45889
+ if (options.chainOpts?.network) return options.chainOpts.network;
45890
+ if (options.chainOpts?.blockchainRid) return void 0;
45891
+ if (this._explicitChain) return this._defaultChain.network;
45892
+ const orgName = options.orgName ?? this.orgName;
45893
+ if (!orgName) return void 0;
45894
+ return (await this.resolveChainForOrg(orgName)).network;
45895
+ }
45046
45896
  /**
45047
45897
  * Get-or-create a Bearer token for dashboard reads. The token is a
45048
45898
  * signed `log_tool_call` op (locally signed, never submitted) — the
@@ -45050,34 +45900,19 @@ var Atbash = class _Atbash {
45050
45900
  * for 4 minutes; refreshed after that so a long-lived client never
45051
45901
  * trips the server's replay window.
45052
45902
  */
45053
- getAuthBearer() {
45054
- const now = Date.now();
45055
- if (this._authBearer && now - this._authBearer.issuedAt < 4 * 60 * 1e3) {
45056
- return this._authBearer.hex;
45057
- }
45058
- const nonce = `auth-${now.toString(36)}-${randomHex(4)}`;
45059
- const hex = native.signLogToolCall(
45060
- nonce,
45061
- `auth:${now}`,
45062
- "",
45063
- "auth-bearer",
45064
- "",
45065
- this.auth.privkey,
45066
- this.blockchainRid
45067
- );
45068
- this._authBearer = { hex, issuedAt: now };
45069
- return hex;
45903
+ getAuthBearer(brid) {
45904
+ return agentAuthBearer(this.auth, brid ?? this.blockchainRid);
45070
45905
  }
45071
- authHeaders() {
45072
- return { Authorization: `Bearer ${this.getAuthBearer()}` };
45906
+ authHeaders(brid) {
45907
+ return agentAuthHeaders(this.auth, brid ?? this.blockchainRid);
45073
45908
  }
45074
- async riskEngineGet(action, params) {
45909
+ async riskEngineGet(action, params, brid) {
45075
45910
  let resp;
45076
45911
  try {
45077
45912
  resp = await this.http.get(
45078
45913
  "/api/risk-engine",
45079
45914
  { action, ...params },
45080
- this.authHeaders()
45915
+ this.authHeaders(brid)
45081
45916
  );
45082
45917
  } catch (err) {
45083
45918
  throw this.transportError(err);
@@ -45085,22 +45920,60 @@ var Atbash = class _Atbash {
45085
45920
  if (resp.status !== 200) throw await this.httpError(resp);
45086
45921
  return this.json(resp);
45087
45922
  }
45088
- async riskEnginePost(body) {
45923
+ async riskEnginePost(body, network, brid) {
45089
45924
  let resp;
45090
45925
  try {
45091
- resp = await this.http.post("/api/risk-engine", body, this.authHeaders());
45926
+ const path3 = network ? `/api/risk-engine?network=${encodeURIComponent(network)}` : "/api/risk-engine";
45927
+ resp = await this.http.post(path3, body, this.authHeaders(brid));
45092
45928
  } catch (err) {
45093
45929
  throw this.transportError(err);
45094
45930
  }
45095
45931
  if (resp.status !== 200) throw await this.httpError(resp);
45096
45932
  const data = await this.json(resp);
45097
- return isRecord(data) ? data : {};
45933
+ return isRecord2(data) ? data : {};
45098
45934
  }
45099
- async riskEngineRecords(action, params) {
45100
- const raw2 = await this.riskEngineGet(action, params);
45935
+ async riskEngineRecords(action, params, brid) {
45936
+ const raw2 = await this.riskEngineGet(action, params, brid);
45101
45937
  if (!Array.isArray(raw2)) return [];
45102
45938
  return raw2.map((item) => toToolCallRecord(item));
45103
45939
  }
45940
+ /**
45941
+ * BRID for an org — one round-trip to the map, honoring the client's chain
45942
+ * cache. A "brand-new org" (nothing anywhere names its chain) is not an
45943
+ * error — `resolveChainForOrg` returns the client default for that case and
45944
+ * this helper returns its BRID. A transport failure or non-200 from
45945
+ * `/api/org-network` IS an error and propagates: the caller cannot fall
45946
+ * back to the default chain on outage, because with multi-chain live that
45947
+ * silently reads from the wrong chain. Matches the Python binding's
45948
+ * `_brid_for_org` semantics.
45949
+ */
45950
+ async bridForOrg(orgName) {
45951
+ return (await this.resolveChainForOrg(orgName)).blockchainRid;
45952
+ }
45953
+ /**
45954
+ * BRID for the client's configured default org, if it has one.
45955
+ *
45956
+ * Calls that carry no `orgName` argument are not chain-less: they still
45957
+ * belong to `this.orgName`, and that org lives on exactly one chain. Routing
45958
+ * them by the constructor's chain instead means a client configured
45959
+ * `network: "private"` reads the private chain for an org that lives on
45960
+ * public, and gets an empty answer rather than an error. So where an org is
45961
+ * known the org decides the chain, and the constructor's chain is what is
45962
+ * left when no org is known at all — the order `resolveAgentLookupNetwork`
45963
+ * already applies to agent metadata reads, and the order the dashboard
45964
+ * applies in `resolveChainForWallet`.
45965
+ *
45966
+ * Undefined when there is no default org, so callers keep falling back to
45967
+ * the client default.
45968
+ */
45969
+ /** The switch's chain, unless this client named one of its own. */
45970
+ forcedNetwork() {
45971
+ return this._explicitChain ? void 0 : this._forcedNetwork;
45972
+ }
45973
+ async defaultOrgBrid() {
45974
+ if (this._explicitChain || !this.orgName) return void 0;
45975
+ return this.bridForOrg(this.orgName);
45976
+ }
45104
45977
  async raiseIfError(resp) {
45105
45978
  if (resp.ok) return;
45106
45979
  throw await this.httpError(resp);
@@ -45111,11 +45984,28 @@ var Atbash = class _Atbash {
45111
45984
  resp.status,
45112
45985
  await safeText(resp),
45113
45986
  resp.statusText,
45114
- this.endpoint
45987
+ this.endpoint,
45988
+ requestPath(resp.url)
45115
45989
  );
45116
45990
  }
45117
- /** Wrap a *transport* failure (fetch threw, no response) as an AtbashAPIError. */
45991
+ /**
45992
+ * Wrap a transport failure (fetch threw, no response) as an AtbashAPIError.
45993
+ *
45994
+ * `HttpTransportError.kind` names the cause; the message is already
45995
+ * human-readable. `debug` echoes the original exception so operators can
45996
+ * cross-reference with node / undici logs when a class doesn't match.
45997
+ */
45118
45998
  transportError(err) {
45999
+ if (err instanceof HttpTransportError) {
46000
+ if (this.debug) {
46001
+ this.logger.warn?.(`[atbash] transport failed \u2014 kind=${err.kind}`, {
46002
+ kind: err.kind,
46003
+ cause: err.cause instanceof Error ? err.cause.message : String(err.cause ?? ""),
46004
+ endpoint: this.endpoint
46005
+ });
46006
+ }
46007
+ return new AtbashAPIError(0, err.message, "", this.endpoint);
46008
+ }
45119
46009
  return new AtbashAPIError(0, errorMessage(err), "", this.endpoint);
45120
46010
  }
45121
46011
  async json(resp) {
@@ -45144,6 +46034,66 @@ var Atbash = class _Atbash {
45144
46034
  return native.containsEvasionCharacters(text);
45145
46035
  }
45146
46036
  };
46037
+ function userFacingReason(reason, api2) {
46038
+ if (api2 && api2.status > 0) {
46039
+ const where = ` (HTTP ${api2.status}${api2.path ? ` from ${api2.path}` : ""})`;
46040
+ const b = api2.body.toLowerCase();
46041
+ if (b.includes("agent not registered")) {
46042
+ return `Agent not registered with Atbash: onboard it in the Atbash dashboard${where}.`;
46043
+ }
46044
+ if (b.includes("jailed")) {
46045
+ return `This agent is jailed; unjail it in the Atbash dashboard${where}.`;
46046
+ }
46047
+ if (b.includes("agent has no policy") || b.includes("no policy configured")) {
46048
+ return `This agent has no policy; attach one in the Atbash dashboard${where}.`;
46049
+ }
46050
+ if (b.includes("audit tier") || b.includes("verdict disabled") || b.includes("verdict not supported")) {
46051
+ return `The organisation's plan does not include checked decisions${where}.`;
46052
+ }
46053
+ return `The Atbash judge answered with an error${where}, so the action was not approved.`;
46054
+ }
46055
+ const text = api2 ? api2.body || reason : reason;
46056
+ return truncate(text.replace(/https?:\/\/[^\s)]+/g, "the judge"), 300);
46057
+ }
46058
+ var DEFAULT_DECISION_TIMEOUT_MS = 6e4;
46059
+ async function withDeadline(p, ms) {
46060
+ let timer;
46061
+ const deadline = new Promise((_, reject) => {
46062
+ timer = setTimeout(
46063
+ () => reject(
46064
+ new Error(
46065
+ `The judge did not give a decision within ${Math.round(ms / 1e3)} s, so the action was not approved. Check the network, or raise decisionTimeoutMs.`
46066
+ )
46067
+ ),
46068
+ ms
46069
+ );
46070
+ });
46071
+ p.catch(() => void 0);
46072
+ try {
46073
+ return await Promise.race([p, deadline]);
46074
+ } finally {
46075
+ clearTimeout(timer);
46076
+ }
46077
+ }
46078
+ function verifyResponseSignature(bodyBytes, resp, verifyPubKey) {
46079
+ const sig = resp.headers.get("X-Atbash-Signature");
46080
+ if (!sig) {
46081
+ throw new SignatureVerificationError("missing X-Atbash-Signature header");
46082
+ }
46083
+ let ok;
46084
+ try {
46085
+ ok = native.verifySignature(bodyBytes, sig, verifyPubKey);
46086
+ } catch (err) {
46087
+ throw new SignatureVerificationError(
46088
+ `signature verification threw: ${errorMessage(err)}`
46089
+ );
46090
+ }
46091
+ if (!ok) {
46092
+ throw new SignatureVerificationError(
46093
+ "signature does not verify against configured verifyPubKey"
46094
+ );
46095
+ }
46096
+ }
45147
46097
  function baseToolCall(raw2) {
45148
46098
  return {
45149
46099
  toolCallId: String(raw2.tool_call_id ?? ""),
@@ -45210,15 +46160,17 @@ function coerceOrgSubscription(raw2, orgName) {
45210
46160
  is_active: Boolean(raw2.is_active)
45211
46161
  };
45212
46162
  }
45213
- function isRecord(v) {
46163
+ function isRecord2(v) {
45214
46164
  return typeof v === "object" && v !== null && !Array.isArray(v);
45215
46165
  }
45216
46166
  function optString(v) {
45217
46167
  if (v === null || v === void 0) return void 0;
46168
+ if (typeof v === "object" || typeof v === "function") return void 0;
45218
46169
  return typeof v === "string" ? v : String(v);
45219
46170
  }
45220
46171
  function optNumber(v) {
45221
46172
  if (v === null || v === void 0) return void 0;
46173
+ if (typeof v === "object" || typeof v === "function") return void 0;
45222
46174
  const n = Number(v);
45223
46175
  return Number.isFinite(n) ? n : void 0;
45224
46176
  }
@@ -45237,6 +46189,14 @@ function parseJson(bytes) {
45237
46189
  const parsed = tryParseJson(bytes.toString("utf-8"));
45238
46190
  return parsed === void 0 ? {} : parsed;
45239
46191
  }
46192
+ function requestPath(url) {
46193
+ if (!url) return void 0;
46194
+ try {
46195
+ return new URL(url).pathname || void 0;
46196
+ } catch {
46197
+ return void 0;
46198
+ }
46199
+ }
45240
46200
  async function safeText(resp) {
45241
46201
  try {
45242
46202
  return await resp.text();
@@ -45247,6 +46207,10 @@ async function safeText(resp) {
45247
46207
  function errorMessage(err) {
45248
46208
  return err instanceof Error ? err.message : String(err);
45249
46209
  }
46210
+ function isEncryptionStateMismatch(err) {
46211
+ const msg = errorMessage(err);
46212
+ return msg.includes("must be a valid encryption envelope") || msg.includes("must be plaintext");
46213
+ }
45250
46214
  function stringifyArgs(args) {
45251
46215
  if (args === null || args === void 0) return "";
45252
46216
  if (typeof args === "string") return args;
@@ -45257,12 +46221,28 @@ function stringifyArgs(args) {
45257
46221
  }
45258
46222
  }
45259
46223
  var MAX_ACTION_LEN = 4e3;
45260
- function truncate(text) {
45261
- if (text.length <= MAX_ACTION_LEN) return text;
45262
- return text.slice(0, MAX_ACTION_LEN) + "\u2026";
46224
+ function truncate(text, limit = MAX_ACTION_LEN) {
46225
+ if (text.length <= limit) return text;
46226
+ return text.slice(0, limit) + "\u2026";
46227
+ }
46228
+
46229
+ // src-ts/browser/key-path.ts
46230
+ init_define_ATBASH_CHROMIA_NODE_URLS();
46231
+ init_define_ATBASH_PRIVATE_NODE_URLS();
46232
+ var KEY_FILENAMES = ["guard-client-key", "atbash-client-key"];
46233
+ var unavailable = (name2) => {
46234
+ throw new Error(`${name2} is not available in the browser bundle`);
46235
+ };
46236
+ function keyPathCandidates() {
46237
+ return unavailable("keyPathCandidates");
46238
+ }
46239
+ function chooseKeyPath(_input, _exists) {
46240
+ return unavailable("chooseKeyPath");
45263
46241
  }
45264
46242
 
45265
46243
  // src-ts/redact.ts
46244
+ init_define_ATBASH_CHROMIA_NODE_URLS();
46245
+ init_define_ATBASH_PRIVATE_NODE_URLS();
45266
46246
  function redactJsonStrings(value) {
45267
46247
  if (typeof value === "string") {
45268
46248
  return native.redactSecrets(value).redacted;
@@ -45281,6 +46261,8 @@ function redactJsonStrings(value) {
45281
46261
  }
45282
46262
 
45283
46263
  // src-ts/signature.ts
46264
+ init_define_ATBASH_CHROMIA_NODE_URLS();
46265
+ init_define_ATBASH_PRIVATE_NODE_URLS();
45284
46266
  function verifyJudgeResponseSignature(bodyBytes, signatureHex, pubKeyHex) {
45285
46267
  if (!signatureHex) {
45286
46268
  return { ok: false, reason: "missing X-Atbash-Signature header" };
@@ -45302,7 +46284,26 @@ function verifyJudgeResponseSignature(bodyBytes, signatureHex, pubKeyHex) {
45302
46284
  };
45303
46285
  }
45304
46286
 
46287
+ // src-ts/memory/boot-sync-message.ts
46288
+ init_define_ATBASH_CHROMIA_NODE_URLS();
46289
+ init_define_ATBASH_PRIVATE_NODE_URLS();
46290
+ var BOOT_SYNC_HINT = "check the chain endpoint and orgName if the cause above does not explain it";
46291
+ function bootSyncFailureLine(cause) {
46292
+ const reason = cause instanceof Error ? cause.message : String(cause);
46293
+ const trimmed = reason.trim();
46294
+ return trimmed ? `[atbash] boot memory sync failed: ${trimmed}` : (
46295
+ // No cause to show: fall back to the advice rather than a bare colon.
46296
+ `[atbash] boot memory sync failed \u2014 ${BOOT_SYNC_HINT}`
46297
+ );
46298
+ }
46299
+
46300
+ // src-ts/memory/index.ts
46301
+ init_define_ATBASH_CHROMIA_NODE_URLS();
46302
+ init_define_ATBASH_PRIVATE_NODE_URLS();
46303
+
45305
46304
  // src-ts/browser/memory-crypto.ts
46305
+ init_define_ATBASH_CHROMIA_NODE_URLS();
46306
+ init_define_ATBASH_PRIVATE_NODE_URLS();
45306
46307
  var { Buffer: Buffer4 } = index;
45307
46308
  var HKDF_INFO = new TextEncoder().encode("atbash:memory-encryption");
45308
46309
  var KEY_LEN = 32;
@@ -45377,6 +46378,8 @@ async function decryptMemoryContent2(ciphertext, nonce, key3) {
45377
46378
  }
45378
46379
 
45379
46380
  // src-ts/browser/memory-scan.ts
46381
+ init_define_ATBASH_CHROMIA_NODE_URLS();
46382
+ init_define_ATBASH_PRIVATE_NODE_URLS();
45380
46383
  var STUB_MSG2 = "not available in @atbash/sdk browser bundle \u2014 scan memory server-side";
45381
46384
  async function scanMemory(_entry, _auth, _opts) {
45382
46385
  throw new Error(`scanMemory ${STUB_MSG2}`);
@@ -45386,6 +46389,8 @@ async function scanMemoryBatch(_entries, _auth, _opts) {
45386
46389
  }
45387
46390
 
45388
46391
  // src-ts/browser/memory-chain.ts
46392
+ init_define_ATBASH_CHROMIA_NODE_URLS();
46393
+ init_define_ATBASH_PRIVATE_NODE_URLS();
45389
46394
  var STUB_MSG3 = "not available in @atbash/sdk browser bundle \u2014 commit/rollback memory server-side";
45390
46395
  async function commitMemoryVersion(_plaintext, _auth, _opts) {
45391
46396
  throw new Error(`commitMemoryVersion ${STUB_MSG3}`);
@@ -45393,11 +46398,11 @@ async function commitMemoryVersion(_plaintext, _auth, _opts) {
45393
46398
  async function getActiveMemoryId(_auth, _chainOpts) {
45394
46399
  throw new Error(`getActiveMemoryId ${STUB_MSG3}`);
45395
46400
  }
45396
- async function getActiveMemory(_auth, _chainOpts) {
45397
- throw new Error(`getActiveMemory ${STUB_MSG3}`);
46401
+ async function getRecentAgentMemory(_auth, _chainOpts) {
46402
+ throw new Error(`getRecentAgentMemory ${STUB_MSG3}`);
45398
46403
  }
45399
- async function getAllAgentMemory(_auth, _chainOpts) {
45400
- throw new Error(`getAllAgentMemory ${STUB_MSG3}`);
46404
+ async function getActiveAgentMemory(_auth, _chainOpts) {
46405
+ throw new Error(`getActiveAgentMemory ${STUB_MSG3}`);
45401
46406
  }
45402
46407
  async function getMemoryHistory(_auth, _chainOpts) {
45403
46408
  throw new Error(`getMemoryHistory ${STUB_MSG3}`);
@@ -45413,6 +46418,8 @@ async function rollbackMemory(_toId, _reason, _auth, _opts) {
45413
46418
  }
45414
46419
 
45415
46420
  // src-ts/browser/memory-classifier.ts
46421
+ init_define_ATBASH_CHROMIA_NODE_URLS();
46422
+ init_define_ATBASH_PRIVATE_NODE_URLS();
45416
46423
  var STUB_MSG4 = "not available in @atbash/sdk browser bundle \u2014 classify memory writes server-side";
45417
46424
  var DEFAULT_MEMORY_WRITE_TOOL_NAMES = [
45418
46425
  "write",
@@ -45434,103 +46441,17 @@ function classifyMemoryWrite(_event, _ctx, _opts = {}) {
45434
46441
  throw new Error(`classifyMemoryWrite ${STUB_MSG4}`);
45435
46442
  }
45436
46443
 
45437
- // src-ts/memory/guard.ts
45438
- function emitDebugProbe(event, ctx, memEntry, logger2) {
45439
- if (!logger2?.info) return;
45440
- const ev = event ?? {};
45441
- const c = ctx ?? {};
45442
- const argsCandidate = ev.params ?? c.params ?? ev.args ?? c.args ?? ev.arguments ?? c.arguments;
45443
- const argsObj = argsCandidate && typeof argsCandidate === "object" ? argsCandidate : {};
45444
- const argsKeys = Object.keys(argsObj).slice(0, 20);
45445
- const pickedPath = typeof argsObj.file_path === "string" && argsObj.file_path || typeof argsObj.path === "string" && argsObj.path || typeof argsObj.filename === "string" && argsObj.filename || null;
45446
- const editsArr = Array.isArray(argsObj.edits) ? argsObj.edits : null;
45447
- const firstEditKeys = editsArr && editsArr[0] && typeof editsArr[0] === "object" ? Object.keys(editsArr[0]).slice(0, 10) : null;
45448
- const tool = ev.toolName ?? c.tool?.name ?? c.toolName ?? c.name ?? "(none)";
45449
- logger2.info("[atbash][probe] before_tool_call", {
45450
- toolName: tool,
45451
- eventKeys: Object.keys(ev).slice(0, 20),
45452
- ctxKeys: Object.keys(c).slice(0, 20),
45453
- argsKeys,
45454
- pickedPath,
45455
- firstEditKeys,
45456
- editsCount: editsArr?.length,
45457
- memoryWrite: !!memEntry,
45458
- memoryPath: memEntry?.key
45459
- });
45460
- }
45461
- async function guardMemoryWrite(input) {
45462
- const {
45463
- event,
45464
- ctx,
45465
- auth,
45466
- endpoint,
45467
- verifyPubKey,
45468
- orgName,
45469
- threshold,
45470
- patterns,
45471
- toolNames,
45472
- enforce = true,
45473
- debug: debug2 = false,
45474
- logger: logger2
45475
- } = input;
45476
- const memEntry = classifyMemoryWrite(event, ctx, { patterns, toolNames });
45477
- if (debug2) emitDebugProbe(event, ctx, memEntry, logger2);
45478
- if (!memEntry) return { handled: false };
45479
- let scanResult;
45480
- try {
45481
- scanResult = await scanMemory(memEntry, auth, {
45482
- endpoint,
45483
- verifyPubKey,
45484
- orgName,
45485
- threshold
45486
- });
45487
- } catch (err) {
45488
- const reason = err instanceof Error ? err.message : String(err);
45489
- logger2?.warn?.("[atbash] memory scan failed", {
45490
- path: memEntry.key,
45491
- reason
45492
- });
45493
- return {
45494
- handled: true,
45495
- decision: enforce ? { allow: false, block: true, reason } : { allow: true }
45496
- };
45497
- }
45498
- if (scanResult.verdict === "red") {
45499
- logger2?.warn?.("[atbash] memory BLOCK", {
45500
- path: memEntry.key,
45501
- reason: scanResult.reason
45502
- });
45503
- return {
45504
- handled: true,
45505
- decision: enforce ? { allow: false, block: true, reason: scanResult.reason } : { allow: true },
45506
- scanResult,
45507
- committed: false
45508
- };
45509
- }
45510
- commitMemoryVersion(memEntry.value, auth, {
45511
- score: scanResult.score,
45512
- orgName,
45513
- endpoint
45514
- }).catch((err) => {
45515
- const reason = err instanceof Error ? err.message : String(err);
45516
- logger2?.warn?.("[atbash] memory commit to chain failed", {
45517
- path: memEntry.key,
45518
- reason
45519
- });
45520
- });
45521
- logger2?.info?.(
45522
- scanResult.verdict === "yellow" ? "[atbash] memory HOLD" : "[atbash] memory ALLOW",
45523
- { path: memEntry.key, score: scanResult.score, reason: scanResult.reason }
45524
- );
45525
- return {
45526
- handled: true,
45527
- decision: { allow: true },
45528
- scanResult,
45529
- committed: true
45530
- };
46444
+ // src-ts/browser/memory-guard.ts
46445
+ init_define_ATBASH_CHROMIA_NODE_URLS();
46446
+ init_define_ATBASH_PRIVATE_NODE_URLS();
46447
+ var STUB_MSG5 = "not available in @atbash/sdk browser bundle \u2014 guard memory writes agent-side";
46448
+ async function guardMemoryWrite(_input) {
46449
+ throw new Error(`guardMemoryWrite ${STUB_MSG5}`);
45531
46450
  }
45532
46451
 
45533
46452
  // src-ts/memory/sync.ts
46453
+ init_define_ATBASH_CHROMIA_NODE_URLS();
46454
+ init_define_ATBASH_PRIVATE_NODE_URLS();
45534
46455
  var MemoryIntegrityError = class extends Error {
45535
46456
  constructor(id, reason) {
45536
46457
  super(`memory integrity check failed on id ${id}: ${reason}`);
@@ -45545,25 +46466,27 @@ async function syncLocalMemory(auth, pointer, opts = {}) {
45545
46466
  const now = Date.now();
45546
46467
  const withinTtl = !opts.force && now - pointer.checkedAt < ttl;
45547
46468
  if (withinTtl) {
45548
- return { drifted: false, pointer };
46469
+ return { drifted: false, checked: false, pointer };
45549
46470
  }
45550
- const currentId = await getActiveMemoryId(auth, opts.chainOpts);
46471
+ const currentId = await getActiveMemoryId(auth, opts.chainOpts, opts.filePath);
45551
46472
  const nextPointer = { activeId: currentId, checkedAt: now };
45552
46473
  if (currentId === pointer.activeId) {
45553
- return { drifted: false, pointer: nextPointer };
46474
+ return { drifted: false, checked: true, pointer: nextPointer };
45554
46475
  }
45555
46476
  if (currentId === null) {
45556
- return { drifted: true, current: null, pointer: nextPointer };
46477
+ return { drifted: true, checked: true, current: null, pointer: nextPointer };
45557
46478
  }
45558
46479
  const row = await getMemoryById(currentId, auth, opts.chainOpts);
45559
46480
  if (row.decryptError) {
45560
46481
  throw new MemoryIntegrityError(currentId, row.decryptError);
45561
46482
  }
45562
- return { drifted: true, current: row, pointer: nextPointer };
46483
+ return { drifted: true, checked: true, current: row, pointer: nextPointer };
45563
46484
  }
45564
46485
 
45565
46486
  // src-ts/browser/memory-pointer-store.ts
45566
- var unavailable = (name2) => {
46487
+ init_define_ATBASH_CHROMIA_NODE_URLS();
46488
+ init_define_ATBASH_PRIVATE_NODE_URLS();
46489
+ var unavailable2 = (name2) => {
45567
46490
  throw new Error(`${name2} is not available in the browser bundle`);
45568
46491
  };
45569
46492
  var PointerStore = class {
@@ -45577,32 +46500,38 @@ var PointerStore = class {
45577
46500
  }
45578
46501
  };
45579
46502
  function defaultPointerPath(_workspaceDir) {
45580
- return unavailable("defaultPointerPath");
46503
+ return unavailable2("defaultPointerPath");
45581
46504
  }
45582
46505
 
45583
46506
  // src-ts/browser/memory-file-logger.ts
45584
- var unavailable2 = (name2) => {
46507
+ init_define_ATBASH_CHROMIA_NODE_URLS();
46508
+ init_define_ATBASH_PRIVATE_NODE_URLS();
46509
+ var unavailable3 = (name2) => {
45585
46510
  throw new Error(`${name2} is not available in the browser bundle`);
45586
46511
  };
45587
46512
  function createFileLogger(_logFilePath, _hostLogger) {
45588
- return unavailable2("createFileLogger");
46513
+ return unavailable3("createFileLogger");
45589
46514
  }
45590
46515
  function defaultPluginLogPath(_workspaceDir) {
45591
- return unavailable2("defaultPluginLogPath");
46516
+ return unavailable3("defaultPluginLogPath");
45592
46517
  }
45593
46518
 
45594
46519
  // src-ts/browser/memory-read-classifier.ts
45595
- var STUB_MSG5 = "not available in @atbash/sdk browser bundle \u2014 classify memory reads server-side";
46520
+ init_define_ATBASH_CHROMIA_NODE_URLS();
46521
+ init_define_ATBASH_PRIVATE_NODE_URLS();
46522
+ var STUB_MSG6 = "not available in @atbash/sdk browser bundle \u2014 classify memory reads server-side";
45596
46523
  var DEFAULT_MEMORY_READ_TOOL_NAMES = [
45597
46524
  "memory_search",
45598
46525
  "memory_get"
45599
46526
  ];
45600
46527
  function classifyMemoryRead(_event, _ctx, _opts = {}) {
45601
- throw new Error(`classifyMemoryRead ${STUB_MSG5}`);
46528
+ throw new Error(`classifyMemoryRead ${STUB_MSG6}`);
45602
46529
  }
45603
46530
 
45604
46531
  // src-ts/browser/memory-guard-manager.ts
45605
- var unavailable3 = (name2) => {
46532
+ init_define_ATBASH_CHROMIA_NODE_URLS();
46533
+ init_define_ATBASH_PRIVATE_NODE_URLS();
46534
+ var unavailable4 = (name2) => {
45606
46535
  throw new Error(`${name2} is not available in the browser bundle`);
45607
46536
  };
45608
46537
  var MemoryGuardManager = class {
@@ -45622,7 +46551,7 @@ var MemoryGuardManager = class {
45622
46551
  }
45623
46552
  };
45624
46553
  function createMemoryGuardManager(_opts) {
45625
- return unavailable3("createMemoryGuardManager");
46554
+ return unavailable4("createMemoryGuardManager");
45626
46555
  }
45627
46556
 
45628
46557
  // src-ts/index.ts
@@ -45683,6 +46612,7 @@ function diffMemorySnapshots2(before, after) {
45683
46612
  export {
45684
46613
  Atbash,
45685
46614
  AtbashAPIError,
46615
+ BOOT_SYNC_HINT,
45686
46616
  DEFAULT_BLOCKCHAIN_RID,
45687
46617
  DEFAULT_CHROMIA_NODE_URLS,
45688
46618
  DEFAULT_ENDPOINT,
@@ -45690,14 +46620,26 @@ export {
45690
46620
  DEFAULT_MEMORY_READ_TOOL_NAMES,
45691
46621
  DEFAULT_MEMORY_WRITE_TOOL_NAMES,
45692
46622
  EciesDomain,
46623
+ HttpClient,
46624
+ HttpTransportError,
46625
+ KEY_FILENAMES,
45693
46626
  MemoryGuardManager,
45694
46627
  MemoryIntegrityError,
46628
+ PRIVATE_CHAIN,
46629
+ PUBLIC_CHAIN,
45695
46630
  PointerStore,
45696
46631
  SignatureVerificationError,
46632
+ bootSyncFailureLine,
46633
+ buildAllowedJudgeHosts,
46634
+ canonicalAllow,
46635
+ chainForNetwork,
46636
+ chooseKeyPath,
45697
46637
  claimHashHex,
45698
46638
  classifyMemoryRead,
45699
46639
  classifyMemoryWrite,
46640
+ columnAad,
45700
46641
  commitMemoryVersion,
46642
+ configureEvents,
45701
46643
  containsEvasionCharacters2 as containsEvasionCharacters,
45702
46644
  containsSecret2 as containsSecret,
45703
46645
  createFileLogger,
@@ -45713,28 +46655,36 @@ export {
45713
46655
  encryptForOrg,
45714
46656
  encryptMemoryContent2 as encryptMemoryContent,
45715
46657
  encryptedLength,
46658
+ eventsAreOn,
45716
46659
  flushTelemetry,
45717
46660
  generateKeypair2 as generateKeypair,
45718
- getActiveMemory,
46661
+ getActiveAgentMemory,
45719
46662
  getActiveMemoryId,
45720
- getAllAgentMemory,
45721
46663
  getConfigDir,
45722
46664
  getConfigPath,
45723
46665
  getMemoryById,
45724
46666
  getMemoryHistory,
46667
+ getRecentAgentMemory,
45725
46668
  getRollbackHistory,
45726
46669
  guardMemoryWrite,
46670
+ isEnvelope,
45727
46671
  isValidPrivateKey2 as isValidPrivateKey,
46672
+ keyFingerprintOf,
46673
+ keyPathCandidates,
45728
46674
  loadAgent2 as loadAgent,
45729
46675
  loadAgentFromFile,
45730
46676
  loadUserConfig,
45731
46677
  normalizeActionForHash,
46678
+ normalizeActionType,
45732
46679
  normalizeForMatching2 as normalizeForMatching,
45733
46680
  normalizeStatus,
45734
46681
  normalizeVerdict,
46682
+ packEnvelope,
46683
+ parseEnvelope,
45735
46684
  pubkeyToHex,
45736
46685
  recordCall,
45737
46686
  recordDuration,
46687
+ recordEvent,
45738
46688
  redactJsonStrings,
45739
46689
  redactSecrets2 as redactSecrets,
45740
46690
  resolve,
@@ -45775,4 +46725,3 @@ postchain-client/built/esm/index.js:
45775
46725
  @noble/ciphers/utils.js:
45776
46726
  (*! noble-ciphers - MIT License (c) 2023 Paul Miller (paulmillr.com) *)
45777
46727
  */
45778
- //# sourceMappingURL=browser.mjs.map