@atbash/sdk 0.9.2 → 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/LICENSE +202 -28
- package/NOTICE +10 -0
- package/README.md +77 -13
- package/THIRD-PARTY-NOTICES +10256 -0
- package/dist/browser.d.mts +366 -50
- package/dist/browser.mjs +506 -174
- package/dist/index.d.mts +366 -50
- package/dist/index.d.ts +366 -50
- package/dist/index.js +1354 -41569
- package/dist/index.mjs +2773 -43019
- package/index.d.ts +19 -0
- package/index.js +61 -54
- package/package.json +15 -9
package/dist/browser.mjs
CHANGED
|
@@ -40585,7 +40585,7 @@ function requireFailoverStrategies() {
|
|
|
40585
40585
|
exports.createTimeoutPromise = createTimeoutPromise;
|
|
40586
40586
|
const utils_12 = requireUtils$1();
|
|
40587
40587
|
const httpUtil_1 = httpUtil;
|
|
40588
|
-
const
|
|
40588
|
+
const logger3 = __importStar2(logger$3);
|
|
40589
40589
|
const http_utils_1 = httpUtils;
|
|
40590
40590
|
function getUnreachableDuration(statusCode, error4) {
|
|
40591
40591
|
if ((0, http_utils_1.isNetworkError)(error4)) {
|
|
@@ -40686,7 +40686,7 @@ function requireFailoverStrategies() {
|
|
|
40686
40686
|
while (true) {
|
|
40687
40687
|
if (groupedSuccessfulResponses.maxNumberOfEqualResponses() >= bftMajorityThreshold) {
|
|
40688
40688
|
if (groupedSuccessfulResponses.numberOfDistinctResponses() > 1) {
|
|
40689
|
-
|
|
40689
|
+
logger3.warning(`Got disagreeing responses, but could still reach BFT majority`);
|
|
40690
40690
|
}
|
|
40691
40691
|
return groupedSuccessfulResponses.majorityResponse();
|
|
40692
40692
|
}
|
|
@@ -40724,7 +40724,7 @@ function requireFailoverStrategies() {
|
|
|
40724
40724
|
if (!isError4 && !error4) {
|
|
40725
40725
|
return { error: error4, statusCode, rspBody, transactionTimestamp };
|
|
40726
40726
|
}
|
|
40727
|
-
|
|
40727
|
+
logger3.info(`${method} request failed on ${endpoint.url}. Attempt: ${attempt + 1} / ${config2.attemptsPerEndpoint}`);
|
|
40728
40728
|
yield (0, utils_12.sleep)(config2.attemptInterval);
|
|
40729
40729
|
}
|
|
40730
40730
|
return { error: error4, statusCode, rspBody, transactionTimestamp };
|
|
@@ -40760,7 +40760,7 @@ function requireFailoverStrategies() {
|
|
|
40760
40760
|
if (isServerError) {
|
|
40761
40761
|
const duration = getUnreachableDuration(statusCode !== null && statusCode !== void 0 ? statusCode : void 0, response.error);
|
|
40762
40762
|
nodeManager2.makeNodeUnavailable(node2.url, duration);
|
|
40763
|
-
|
|
40763
|
+
logger3.info(`request failed with server error on ${node2.url} trying next node`);
|
|
40764
40764
|
break;
|
|
40765
40765
|
}
|
|
40766
40766
|
if (isClientError) {
|
|
@@ -40768,11 +40768,11 @@ function requireFailoverStrategies() {
|
|
|
40768
40768
|
return { error: error4, statusCode, rspBody, transactionTimestamp };
|
|
40769
40769
|
}
|
|
40770
40770
|
if (!nodeManager2.useStickyNode) {
|
|
40771
|
-
|
|
40771
|
+
logger3.info(`request failed client error on ${node2.url} trying next node`);
|
|
40772
40772
|
break;
|
|
40773
40773
|
}
|
|
40774
40774
|
}
|
|
40775
|
-
|
|
40775
|
+
logger3.info(`${method} request failed on ${node2.url}. Attempt: ${attempt + 1} / ${config2.attemptsPerEndpoint}`);
|
|
40776
40776
|
if (config2.attemptInterval > 0) {
|
|
40777
40777
|
yield (0, utils_12.sleep)(config2.attemptInterval);
|
|
40778
40778
|
}
|
|
@@ -41001,7 +41001,7 @@ function requireUtils$1() {
|
|
|
41001
41001
|
exports.getBlockchainRidFromIid = getBlockchainRidFromIid;
|
|
41002
41002
|
exports.convertToPrintable = convertToPrintable;
|
|
41003
41003
|
const buffer_12 = buffer$3;
|
|
41004
|
-
const
|
|
41004
|
+
const logger3 = __importStar2(logger$3);
|
|
41005
41005
|
const errors_12 = errors;
|
|
41006
41006
|
const gtxTool = __importStar2(gtx$1);
|
|
41007
41007
|
const errors_2 = errors;
|
|
@@ -41084,7 +41084,7 @@ function requireUtils$1() {
|
|
|
41084
41084
|
function validTxRid(txRID) {
|
|
41085
41085
|
if (txRID.length != 32) {
|
|
41086
41086
|
const error4 = new errors_12.InvalidTxRidException(txRID);
|
|
41087
|
-
|
|
41087
|
+
logger3.error(error4.toString());
|
|
41088
41088
|
return false;
|
|
41089
41089
|
}
|
|
41090
41090
|
return true;
|
|
@@ -41487,7 +41487,7 @@ function requireUtils$1() {
|
|
|
41487
41487
|
function handleGetResponse(error4, statusCode, responseObject, callback) {
|
|
41488
41488
|
try {
|
|
41489
41489
|
const responseObjectPrintable = convertToPrintable(responseObject);
|
|
41490
|
-
|
|
41490
|
+
logger3.debug(`error: ${error4}, status code: ${statusCode}, response body: ${responseObjectPrintable}`);
|
|
41491
41491
|
if (error4) {
|
|
41492
41492
|
return callback(error4, null);
|
|
41493
41493
|
}
|
|
@@ -41497,16 +41497,16 @@ function requireUtils$1() {
|
|
|
41497
41497
|
return callback(null, responseObject);
|
|
41498
41498
|
} catch (error5) {
|
|
41499
41499
|
callback(error5, null);
|
|
41500
|
-
|
|
41500
|
+
logger3.error(`client.handleGetResponse(): Failed to call the callback function. ${error5}`);
|
|
41501
41501
|
}
|
|
41502
41502
|
}
|
|
41503
41503
|
function handlePostResponse(error4, statusCode, responseObject, callback) {
|
|
41504
41504
|
var _a2;
|
|
41505
41505
|
const responseObjectPrintable = convertToPrintable(responseObject);
|
|
41506
|
-
|
|
41506
|
+
logger3.debug(`error: ${error4}, status code: ${statusCode}, response body: ${responseObjectPrintable}`);
|
|
41507
41507
|
try {
|
|
41508
41508
|
if (error4) {
|
|
41509
|
-
|
|
41509
|
+
logger3.error(`In client post(). ${error4}`);
|
|
41510
41510
|
callback(error4, null);
|
|
41511
41511
|
} else if (!statusCode || !(0, http_utils_1.isSuccessfulStatusCode)(statusCode)) {
|
|
41512
41512
|
let errorMessage2 = `Unexpected status code from server. Code: ${statusCode}.`;
|
|
@@ -41514,14 +41514,14 @@ function requireUtils$1() {
|
|
|
41514
41514
|
if (responseObjectPrintable) {
|
|
41515
41515
|
errorMessage2 += ` Message: ${responseObjectPrintable}.`;
|
|
41516
41516
|
}
|
|
41517
|
-
|
|
41517
|
+
logger3.error(errorMessage2);
|
|
41518
41518
|
callback(new errors_12.UnexpectedStatusError(statusCode !== null && statusCode !== void 0 ? statusCode : 400, errorMessageInResponseBody || responseObjectPrintable), responseObject);
|
|
41519
41519
|
} else {
|
|
41520
|
-
|
|
41520
|
+
logger3.info(`Calling responseCallback with responseObject: ${responseObjectPrintable}`);
|
|
41521
41521
|
callback(null, responseObject);
|
|
41522
41522
|
}
|
|
41523
41523
|
} catch (error5) {
|
|
41524
|
-
|
|
41524
|
+
logger3.error(`client.handlePostResponse(): Failed to call callback function ${error5}`);
|
|
41525
41525
|
}
|
|
41526
41526
|
}
|
|
41527
41527
|
function getBlockchainRidFromIid(_a2) {
|
|
@@ -42259,7 +42259,7 @@ function requireBlockchainClient() {
|
|
|
42259
42259
|
const crypto_12 = requireCryptoBrowserify();
|
|
42260
42260
|
const cloneDeep_1$1 = __importDefault2(cloneDeep_1);
|
|
42261
42261
|
const IccfProofTxMaterialBuilder_1 = requireIccfProofTxMaterialBuilder();
|
|
42262
|
-
const
|
|
42262
|
+
const logger3 = __importStar2(logger$3);
|
|
42263
42263
|
const formatter_12 = formatter;
|
|
42264
42264
|
const serialization_12 = serialization$2;
|
|
42265
42265
|
const gtxTool = __importStar2(gtx$1);
|
|
@@ -42301,7 +42301,7 @@ function requireBlockchainClient() {
|
|
|
42301
42301
|
},
|
|
42302
42302
|
signTransaction(transaction, signMethod2, callback) {
|
|
42303
42303
|
return __awaiter2(this, void 0, void 0, function* () {
|
|
42304
|
-
|
|
42304
|
+
logger3.debug(`Signing transaction with ${!(0, utils_12.isKeyPair)(signMethod2) ? "signature provider containing " : ""}pubKey: ${(0, formatter_12.toString)(signMethod2.pubKey)}`);
|
|
42305
42305
|
const gtx2 = (0, utils_12.getGTXFromBufferOrTransactionOrOperation)(transaction, config2.blockchainRid);
|
|
42306
42306
|
try {
|
|
42307
42307
|
const signedTx = yield (0, utils_12.isKeyPair)(signMethod2) ? gtxTool.sign(gtx2, signMethod2.privKey, config2.merkleHashVersion, signMethod2.pubKey) : gtxTool.sign(gtx2, signMethod2, config2.merkleHashVersion);
|
|
@@ -42326,7 +42326,7 @@ function requireBlockchainClient() {
|
|
|
42326
42326
|
const promiEvent = new promiEvents_12.Web3PromiEvent((resolve2, reject) => __awaiter2(this, void 0, void 0, function* () {
|
|
42327
42327
|
let error4 = null;
|
|
42328
42328
|
for (let i = 0; i < config2.retryTransactionPolling.count; i++) {
|
|
42329
|
-
|
|
42329
|
+
logger3.info(`sendTransactionWithRetries attempt ${i + 1} of ${config2.retryTransactionPolling.count}`);
|
|
42330
42330
|
const tmpPromiEvent = sendOnce().on(enums_12.TransactionEvent.ClusterAnchoringConfirmation, (receipt) => {
|
|
42331
42331
|
promiEvent.emit(enums_12.TransactionEvent.ClusterAnchoringConfirmation, receipt);
|
|
42332
42332
|
}).on(enums_12.TransactionEvent.SystemAnchoringConfirmation, (receipt) => {
|
|
@@ -42338,7 +42338,7 @@ function requireBlockchainClient() {
|
|
|
42338
42338
|
}).on(enums_12.TransactionEvent.DappConfirmed, (receipt) => {
|
|
42339
42339
|
promiEvent.emit(enums_12.TransactionEvent.DappConfirmed, receipt);
|
|
42340
42340
|
}).catch((tmpError) => {
|
|
42341
|
-
|
|
42341
|
+
logger3.warning(`sendTransactionWithRetries error on attempt ${i + 1} of ${config2.retryTransactionPolling.count}: ${tmpError}`);
|
|
42342
42342
|
promiEvent.emit(enums_12.TransactionEvent.Rejected, tmpError);
|
|
42343
42343
|
error4 = tmpError;
|
|
42344
42344
|
});
|
|
@@ -43073,11 +43073,11 @@ function requireDecodeTransactionToGtx() {
|
|
|
43073
43073
|
Object.defineProperty(decodeTransactionToGtx, "__esModule", { value: true });
|
|
43074
43074
|
decodeTransactionToGtx.decodeTransactionToGtx = decodeTransactionToGtx$1;
|
|
43075
43075
|
const gtxTool = __importStar2(gtx$1);
|
|
43076
|
-
const
|
|
43076
|
+
const logger3 = __importStar2(logger$3);
|
|
43077
43077
|
const dump_1 = requireDump();
|
|
43078
43078
|
function decodeTransactionToGtx$1(encodedTransaction) {
|
|
43079
43079
|
const gtx2 = gtxTool.deserialize(encodedTransaction);
|
|
43080
|
-
|
|
43080
|
+
logger3.debug(`Output from deserializing a raw transaction: ${(0, dump_1.dumpGtv)(gtx2)}`);
|
|
43081
43081
|
return gtx2;
|
|
43082
43082
|
}
|
|
43083
43083
|
return decodeTransactionToGtx;
|
|
@@ -43455,6 +43455,17 @@ var native = {
|
|
|
43455
43455
|
defaultChromiaNodeUrls: () => [...DEFAULT_CHROMIA_NODE_URLS_ARR],
|
|
43456
43456
|
defaultPrivateNodeUrls: () => [...DEFAULT_PRIVATE_NODE_URLS_ARR],
|
|
43457
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"),
|
|
43458
43469
|
classifyMemoryWrite: stub("classifyMemoryWrite"),
|
|
43459
43470
|
classifyMemoryRead: stub("classifyMemoryRead"),
|
|
43460
43471
|
defaultMemoryWriteToolNames: stub("defaultMemoryWriteToolNames"),
|
|
@@ -43531,6 +43542,32 @@ function randomHex(size) {
|
|
|
43531
43542
|
return hex;
|
|
43532
43543
|
}
|
|
43533
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
|
+
|
|
43534
43571
|
// src-ts/chain-config.ts
|
|
43535
43572
|
init_define_ATBASH_CHROMIA_NODE_URLS();
|
|
43536
43573
|
init_define_ATBASH_PRIVATE_NODE_URLS();
|
|
@@ -44588,9 +44625,19 @@ init_define_ATBASH_PRIVATE_NODE_URLS();
|
|
|
44588
44625
|
// src-ts/normalize.ts
|
|
44589
44626
|
init_define_ATBASH_CHROMIA_NODE_URLS();
|
|
44590
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
|
+
}
|
|
44591
44638
|
function normalizeVerdict(raw2) {
|
|
44592
44639
|
if (raw2 === null || raw2 === void 0) return "No verdict";
|
|
44593
|
-
const v =
|
|
44640
|
+
const v = wireText(raw2).trim().toUpperCase();
|
|
44594
44641
|
if (v === "ALLOW" || v === "GREEN") return "ALLOW";
|
|
44595
44642
|
if (v === "HOLD" || v === "YELLOW") return "HOLD";
|
|
44596
44643
|
if (v === "BLOCK" || v === "RED") return "BLOCK";
|
|
@@ -44600,7 +44647,7 @@ function normalizeActionType(raw2) {
|
|
|
44600
44647
|
return typeof raw2 === "string" ? raw2.trim().toLowerCase() : "";
|
|
44601
44648
|
}
|
|
44602
44649
|
function normalizeStatus(raw2) {
|
|
44603
|
-
const s2 =
|
|
44650
|
+
const s2 = wireText(raw2).toLowerCase();
|
|
44604
44651
|
if (s2 === "pending" || s2 === "answered" || s2 === "error") return s2;
|
|
44605
44652
|
return "error";
|
|
44606
44653
|
}
|
|
@@ -44627,17 +44674,58 @@ function allowSignalsPermit(data) {
|
|
|
44627
44674
|
}
|
|
44628
44675
|
return signals.length === 0 || signals.every((value) => value === true);
|
|
44629
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
|
+
}
|
|
44630
44713
|
function wireActionType(data) {
|
|
44631
|
-
|
|
44632
|
-
|
|
44633
|
-
|
|
44714
|
+
for (const source of decisionSources(data)) {
|
|
44715
|
+
const actionType = actionTypeOf(source);
|
|
44716
|
+
if (actionType !== "") return actionType;
|
|
44717
|
+
}
|
|
44718
|
+
return "";
|
|
44634
44719
|
}
|
|
44635
44720
|
function isAuditTier(data) {
|
|
44636
44721
|
const absentVerdict = data.verdict === null || data.verdict === void 0;
|
|
44637
44722
|
return absentVerdict && data.status === "logged";
|
|
44638
44723
|
}
|
|
44724
|
+
function isAuditTierBody(data) {
|
|
44725
|
+
return isAuditTier(data);
|
|
44726
|
+
}
|
|
44639
44727
|
function canonicalAllow(data) {
|
|
44640
|
-
if (
|
|
44728
|
+
if (explicitRefusal(data) !== "") return false;
|
|
44641
44729
|
const actionType = wireActionType(data);
|
|
44642
44730
|
if (actionType && actionType !== "allow") return false;
|
|
44643
44731
|
if (isAuditTier(data)) return true;
|
|
@@ -44646,6 +44734,62 @@ function canonicalAllow(data) {
|
|
|
44646
44734
|
return verdict === "ALLOW" || verdict === "GREEN";
|
|
44647
44735
|
}
|
|
44648
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
|
+
|
|
44649
44793
|
// src-ts/browser/opentel/telemetry.ts
|
|
44650
44794
|
init_define_ATBASH_CHROMIA_NODE_URLS();
|
|
44651
44795
|
init_define_ATBASH_PRIVATE_NODE_URLS();
|
|
@@ -44682,6 +44826,12 @@ function resolve(_key, flagValue) {
|
|
|
44682
44826
|
function forcedChainNetwork(flagValue) {
|
|
44683
44827
|
return flagValue === "public" || flagValue === "private" ? flagValue : void 0;
|
|
44684
44828
|
}
|
|
44829
|
+
function agentKeyFromEnv() {
|
|
44830
|
+
return "";
|
|
44831
|
+
}
|
|
44832
|
+
function strandedAgentKey() {
|
|
44833
|
+
return "";
|
|
44834
|
+
}
|
|
44685
44835
|
|
|
44686
44836
|
// src-ts/client.ts
|
|
44687
44837
|
function generateToolCallId() {
|
|
@@ -44707,6 +44857,13 @@ function resolveConstructorChain(options) {
|
|
|
44707
44857
|
}
|
|
44708
44858
|
return chainForNetwork(options.network ?? forcedChainNetwork() ?? "private");
|
|
44709
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
|
+
}
|
|
44710
44867
|
var Atbash = class _Atbash {
|
|
44711
44868
|
auth;
|
|
44712
44869
|
endpoint;
|
|
@@ -44720,6 +44877,10 @@ var Atbash = class _Atbash {
|
|
|
44720
44877
|
orgEncryptionPubKey;
|
|
44721
44878
|
/** When true (default), `auditToolCall` denies on any error. */
|
|
44722
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;
|
|
44723
44884
|
/** Org key learned from the last agent-exists check, for this agent only. */
|
|
44724
44885
|
_orgKeyFromChain = null;
|
|
44725
44886
|
debug;
|
|
@@ -44761,16 +44922,6 @@ var Atbash = class _Atbash {
|
|
|
44761
44922
|
*/
|
|
44762
44923
|
_agentExistsCache = null;
|
|
44763
44924
|
static AGENT_EXISTS_TTL_MS = 5e3;
|
|
44764
|
-
/**
|
|
44765
|
-
* Cached bearer token for risk-engine / insurance read calls. Built
|
|
44766
|
-
* lazily as a signed `log_tool_call` tx and refreshed every 4 min so
|
|
44767
|
-
* server-side replay protection windows never expire it mid-session.
|
|
44768
|
-
*/
|
|
44769
|
-
// Keyed by blockchainRid so bearers for the public and private chains can
|
|
44770
|
-
// coexist. The dashboard derives `authNetwork` from the BRID inside the
|
|
44771
|
-
// signed envelope, so a bearer signed for chain A cannot authenticate a
|
|
44772
|
-
// request routed to chain B — every chain the client talks to needs its own.
|
|
44773
|
-
_authBearers = /* @__PURE__ */ new Map();
|
|
44774
44925
|
/** Guards `logEnvironmentOnce` — hosts construct several clients. */
|
|
44775
44926
|
static environmentLogged = false;
|
|
44776
44927
|
constructor(privkey, options = {}) {
|
|
@@ -44793,6 +44944,8 @@ var Atbash = class _Atbash {
|
|
|
44793
44944
|
this.verifyPubKey = validated.verifyPubKey ?? void 0;
|
|
44794
44945
|
this.orgEncryptionPubKey = options.orgEncryptionPubKey;
|
|
44795
44946
|
this.failClosed = options.failClosed !== false;
|
|
44947
|
+
this.requireEnforcement = options.requireEnforcement !== false;
|
|
44948
|
+
this.decisionTimeoutMs = options.decisionTimeoutMs ?? DEFAULT_DECISION_TIMEOUT_MS;
|
|
44796
44949
|
this.debug = options.debug === true;
|
|
44797
44950
|
this.logger = options.logger ?? {};
|
|
44798
44951
|
this.http = new HttpClient(this.endpoint, options.timeoutMs ?? 12e4);
|
|
@@ -44856,6 +45009,84 @@ var Atbash = class _Atbash {
|
|
|
44856
45009
|
* validated against the trusted allowlist / self-hosted policy; a
|
|
44857
45010
|
* self-hosted endpoint's `verifyPubKey` becomes the client default.
|
|
44858
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
|
+
}
|
|
44859
45090
|
static fromConfig(options = {}) {
|
|
44860
45091
|
const configuredEndpoint = resolve("judgeEndpoint") || void 0;
|
|
44861
45092
|
const configuredVerifyPubKey = resolve("judgeVerifyPubKey") || void 0;
|
|
@@ -44871,8 +45102,8 @@ var Atbash = class _Atbash {
|
|
|
44871
45102
|
verifyPubKey: configuredVerifyPubKey
|
|
44872
45103
|
} : { endpoint: configuredEndpoint })
|
|
44873
45104
|
);
|
|
44874
|
-
const
|
|
44875
|
-
|
|
45105
|
+
const auth = _Atbash.resolveIdentity(options);
|
|
45106
|
+
_Atbash.warnOnStrandedKey(options.logger);
|
|
44876
45107
|
return new _Atbash(auth.privkey, {
|
|
44877
45108
|
endpoint: validated.url,
|
|
44878
45109
|
chain: options.chain,
|
|
@@ -44883,6 +45114,8 @@ var Atbash = class _Atbash {
|
|
|
44883
45114
|
orgName: options.orgName,
|
|
44884
45115
|
verifyPubKey: validated.verifyPubKey ?? void 0,
|
|
44885
45116
|
failClosed: options.failClosed,
|
|
45117
|
+
requireEnforcement: options.requireEnforcement,
|
|
45118
|
+
decisionTimeoutMs: options.decisionTimeoutMs,
|
|
44886
45119
|
// ATBASH_DEBUG lets an operator turn diagnostics on without editing a
|
|
44887
45120
|
// host's plugin config, which is usually the harder half.
|
|
44888
45121
|
debug: options.debug ?? /^(1|true|yes)$/i.test(resolve("debug")),
|
|
@@ -45081,45 +45314,28 @@ var Atbash = class _Atbash {
|
|
|
45081
45314
|
}
|
|
45082
45315
|
if (!resp.ok) throw await this.httpError(resp);
|
|
45083
45316
|
const bodyBytes = Buffer.from(await resp.arrayBuffer());
|
|
45084
|
-
const verifyPubKey = options.verifyPubKey
|
|
45317
|
+
const verifyPubKey = this.effectiveVerifyKey(options.verifyPubKey);
|
|
45085
45318
|
if (verifyPubKey !== void 0) {
|
|
45086
|
-
|
|
45087
|
-
if (!sig) {
|
|
45088
|
-
throw new SignatureVerificationError(
|
|
45089
|
-
"missing X-Atbash-Signature header"
|
|
45090
|
-
);
|
|
45091
|
-
}
|
|
45092
|
-
let ok;
|
|
45093
|
-
try {
|
|
45094
|
-
ok = native.verifySignature(bodyBytes, sig, verifyPubKey);
|
|
45095
|
-
} catch (err) {
|
|
45096
|
-
throw new SignatureVerificationError(
|
|
45097
|
-
`signature verification threw: ${errorMessage(err)}`
|
|
45098
|
-
);
|
|
45099
|
-
}
|
|
45100
|
-
if (!ok) {
|
|
45101
|
-
throw new SignatureVerificationError(
|
|
45102
|
-
"signature does not verify against configured verifyPubKey"
|
|
45103
|
-
);
|
|
45104
|
-
}
|
|
45319
|
+
verifyResponseSignature(bodyBytes, resp, verifyPubKey);
|
|
45105
45320
|
}
|
|
45106
45321
|
const data = parseJson(bodyBytes);
|
|
45107
45322
|
const rawScore = data.score;
|
|
45108
45323
|
const score = typeof rawScore === "number" && Number.isInteger(rawScore) && rawScore >= 1 && rawScore <= 10 ? rawScore : void 0;
|
|
45109
45324
|
return {
|
|
45110
45325
|
verdict: normalizeVerdict(data.verdict),
|
|
45111
|
-
allow:
|
|
45326
|
+
allow: this.executable(data),
|
|
45112
45327
|
actionType: normalizeActionType(data.action_type),
|
|
45113
|
-
reason:
|
|
45114
|
-
confidence:
|
|
45115
|
-
provider:
|
|
45116
|
-
latencyMs:
|
|
45117
|
-
toolCallId:
|
|
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),
|
|
45118
45333
|
onChain: Boolean(data.on_chain),
|
|
45119
45334
|
enforced: Boolean(data.enforced),
|
|
45120
|
-
enforcementMode:
|
|
45121
|
-
status:
|
|
45122
|
-
score
|
|
45335
|
+
enforcementMode: wireText(data.enforcement_mode),
|
|
45336
|
+
status: wireText(data.status),
|
|
45337
|
+
score,
|
|
45338
|
+
refusal: explicitRefusal(data)
|
|
45123
45339
|
};
|
|
45124
45340
|
}
|
|
45125
45341
|
/* ── audit_tool_call (redact → judge → decision) ───────────────────────── */
|
|
@@ -45152,77 +45368,125 @@ var Atbash = class _Atbash {
|
|
|
45152
45368
|
}
|
|
45153
45369
|
try {
|
|
45154
45370
|
this.logger.info?.("[atbash] judge API called", { tool: toolName });
|
|
45155
|
-
const result = await
|
|
45156
|
-
|
|
45157
|
-
|
|
45158
|
-
|
|
45159
|
-
|
|
45160
|
-
|
|
45161
|
-
|
|
45162
|
-
|
|
45163
|
-
|
|
45164
|
-
|
|
45165
|
-
|
|
45166
|
-
|
|
45167
|
-
|
|
45168
|
-
|
|
45169
|
-
}
|
|
45170
|
-
return {
|
|
45171
|
-
allow: true,
|
|
45172
|
-
verdict: "ALLOW",
|
|
45173
|
-
reason: result.reason || "audit tier \u2014 request logged on-chain, no AI enforcement",
|
|
45174
|
-
toolCallId: result.toolCallId
|
|
45175
|
-
};
|
|
45176
|
-
}
|
|
45177
|
-
const action = result.actionType;
|
|
45178
|
-
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);
|
|
45179
45385
|
return {
|
|
45180
45386
|
allow: false,
|
|
45181
|
-
verdict: "
|
|
45182
|
-
reason:
|
|
45183
|
-
toolCallId: result.toolCallId
|
|
45387
|
+
verdict: "ERROR",
|
|
45388
|
+
reason: `The judge's reply failed its signature check (${errorMessage(err)}), so it was not trusted.`
|
|
45184
45389
|
};
|
|
45185
45390
|
}
|
|
45186
|
-
|
|
45187
|
-
|
|
45188
|
-
|
|
45189
|
-
|
|
45190
|
-
|
|
45191
|
-
|
|
45192
|
-
|
|
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
|
+
);
|
|
45193
45445
|
}
|
|
45194
|
-
if (
|
|
45195
|
-
|
|
45196
|
-
|
|
45197
|
-
|
|
45198
|
-
|
|
45199
|
-
reason: result.reason,
|
|
45200
|
-
toolCallId: result.toolCallId
|
|
45201
|
-
};
|
|
45202
|
-
}
|
|
45203
|
-
if (result.verdict === "BLOCK") {
|
|
45204
|
-
return {
|
|
45205
|
-
allow: false,
|
|
45206
|
-
verdict: "BLOCK",
|
|
45207
|
-
reason: result.reason,
|
|
45208
|
-
toolCallId: result.toolCallId
|
|
45209
|
-
};
|
|
45210
|
-
}
|
|
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
|
+
);
|
|
45211
45451
|
return {
|
|
45212
|
-
allow:
|
|
45213
|
-
verdict: "
|
|
45214
|
-
reason:
|
|
45215
|
-
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
|
|
45216
45456
|
};
|
|
45217
45457
|
}
|
|
45218
|
-
return
|
|
45219
|
-
|
|
45220
|
-
|
|
45221
|
-
|
|
45222
|
-
|
|
45223
|
-
|
|
45224
|
-
|
|
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.");
|
|
45469
|
+
}
|
|
45470
|
+
if (action === "hold_for_user_confirm") {
|
|
45471
|
+
return held;
|
|
45225
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
|
+
);
|
|
45226
45490
|
}
|
|
45227
45491
|
/**
|
|
45228
45492
|
* One exit for every judge failure.
|
|
@@ -45234,18 +45498,30 @@ var Atbash = class _Atbash {
|
|
|
45234
45498
|
*/
|
|
45235
45499
|
failJudge(reason, cause, toolCallId) {
|
|
45236
45500
|
const api2 = cause instanceof AtbashAPIError ? cause : null;
|
|
45501
|
+
const userReason = userFacingReason(reason, api2);
|
|
45237
45502
|
const status = api2 ? ` status=${api2.status || "no-response"}` : "";
|
|
45503
|
+
const detail = this.debug ? ` detail=${truncate(reason, 500)}` : "";
|
|
45238
45504
|
const body = this.debug && api2?.body ? ` body=${truncate(api2.body, 500)}` : "";
|
|
45239
45505
|
this.logger.warn?.(
|
|
45240
|
-
`[atbash] judge API failed \u2014${status} reason=${truncate(
|
|
45506
|
+
`[atbash] judge API failed \u2014${status} reason=${truncate(userReason, 300)}${detail}${body}`,
|
|
45241
45507
|
{
|
|
45242
|
-
reason,
|
|
45243
|
-
...api2 ? { status: api2.status
|
|
45508
|
+
reason: userReason,
|
|
45509
|
+
...api2 ? { status: api2.status } : {},
|
|
45510
|
+
...this.debug && api2 ? { body: api2.body, detail: reason } : {},
|
|
45244
45511
|
endpoint: this.endpoint,
|
|
45245
45512
|
...toolCallId ? { toolCallId } : {}
|
|
45246
45513
|
}
|
|
45247
45514
|
);
|
|
45248
|
-
return this.fail(
|
|
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));
|
|
45249
45525
|
}
|
|
45250
45526
|
fail(reason, toolCallId) {
|
|
45251
45527
|
return { allow: !this.failClosed, verdict: "ERROR", reason, toolCallId };
|
|
@@ -45271,13 +45547,18 @@ var Atbash = class _Atbash {
|
|
|
45271
45547
|
this.authHeaders(brid)
|
|
45272
45548
|
);
|
|
45273
45549
|
await this.raiseIfError(resp);
|
|
45274
|
-
const
|
|
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 : {};
|
|
45275
45556
|
return {
|
|
45276
45557
|
status: normalizeStatus(data.status),
|
|
45277
45558
|
verdict: normalizeVerdict(data.verdict),
|
|
45278
|
-
allow:
|
|
45279
|
-
reason:
|
|
45280
|
-
judgmentId:
|
|
45559
|
+
allow: this.executable(data),
|
|
45560
|
+
reason: wireText(data.reason),
|
|
45561
|
+
judgmentId: wireText(data.judgmentId, judgmentId),
|
|
45281
45562
|
onChain: optBool(data.onChain),
|
|
45282
45563
|
cached: optBool(data.cached),
|
|
45283
45564
|
responseTimeMs: optNumber(data.responseTimeMs)
|
|
@@ -45561,10 +45842,28 @@ var Atbash = class _Atbash {
|
|
|
45561
45842
|
recordCall(name2, void 0, agentPubkey);
|
|
45562
45843
|
try {
|
|
45563
45844
|
const result = await fn();
|
|
45564
|
-
|
|
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
|
+
});
|
|
45565
45854
|
return result;
|
|
45566
45855
|
} catch (err) {
|
|
45567
|
-
|
|
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
|
+
});
|
|
45568
45867
|
throw err;
|
|
45569
45868
|
}
|
|
45570
45869
|
}
|
|
@@ -45602,25 +45901,10 @@ var Atbash = class _Atbash {
|
|
|
45602
45901
|
* trips the server's replay window.
|
|
45603
45902
|
*/
|
|
45604
45903
|
getAuthBearer(brid) {
|
|
45605
|
-
|
|
45606
|
-
const now = Date.now();
|
|
45607
|
-
const cached = this._authBearers.get(chainBrid);
|
|
45608
|
-
if (cached && now - cached.issuedAt < 4 * 60 * 1e3) return cached.hex;
|
|
45609
|
-
const nonce = `auth-${now.toString(36)}-${randomHex(4)}`;
|
|
45610
|
-
const hex = native.signLogToolCall(
|
|
45611
|
-
nonce,
|
|
45612
|
-
`auth:${now}`,
|
|
45613
|
-
"",
|
|
45614
|
-
"auth-bearer",
|
|
45615
|
-
"",
|
|
45616
|
-
this.auth.privkey,
|
|
45617
|
-
chainBrid
|
|
45618
|
-
);
|
|
45619
|
-
this._authBearers.set(chainBrid, { hex, issuedAt: now });
|
|
45620
|
-
return hex;
|
|
45904
|
+
return agentAuthBearer(this.auth, brid ?? this.blockchainRid);
|
|
45621
45905
|
}
|
|
45622
45906
|
authHeaders(brid) {
|
|
45623
|
-
return
|
|
45907
|
+
return agentAuthHeaders(this.auth, brid ?? this.blockchainRid);
|
|
45624
45908
|
}
|
|
45625
45909
|
async riskEngineGet(action, params, brid) {
|
|
45626
45910
|
let resp;
|
|
@@ -45750,6 +46034,66 @@ var Atbash = class _Atbash {
|
|
|
45750
46034
|
return native.containsEvasionCharacters(text);
|
|
45751
46035
|
}
|
|
45752
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
|
+
}
|
|
45753
46097
|
function baseToolCall(raw2) {
|
|
45754
46098
|
return {
|
|
45755
46099
|
toolCallId: String(raw2.tool_call_id ?? ""),
|
|
@@ -45821,10 +46165,12 @@ function isRecord2(v) {
|
|
|
45821
46165
|
}
|
|
45822
46166
|
function optString(v) {
|
|
45823
46167
|
if (v === null || v === void 0) return void 0;
|
|
46168
|
+
if (typeof v === "object" || typeof v === "function") return void 0;
|
|
45824
46169
|
return typeof v === "string" ? v : String(v);
|
|
45825
46170
|
}
|
|
45826
46171
|
function optNumber(v) {
|
|
45827
46172
|
if (v === null || v === void 0) return void 0;
|
|
46173
|
+
if (typeof v === "object" || typeof v === "function") return void 0;
|
|
45828
46174
|
const n = Number(v);
|
|
45829
46175
|
return Number.isFinite(n) ? n : void 0;
|
|
45830
46176
|
}
|
|
@@ -45951,22 +46297,6 @@ function bootSyncFailureLine(cause) {
|
|
|
45951
46297
|
);
|
|
45952
46298
|
}
|
|
45953
46299
|
|
|
45954
|
-
// src-ts/memory/_gtv_bytes.ts
|
|
45955
|
-
init_define_ATBASH_CHROMIA_NODE_URLS();
|
|
45956
|
-
init_define_ATBASH_PRIVATE_NODE_URLS();
|
|
45957
|
-
function gtvToFfiSafe(value) {
|
|
45958
|
-
if (value instanceof Uint8Array) return Buffer.from(value).toString("hex");
|
|
45959
|
-
if (Array.isArray(value)) return value.map(gtvToFfiSafe);
|
|
45960
|
-
if (value !== null && typeof value === "object") {
|
|
45961
|
-
const out = {};
|
|
45962
|
-
for (const [key3, val] of Object.entries(value)) {
|
|
45963
|
-
out[key3] = gtvToFfiSafe(val);
|
|
45964
|
-
}
|
|
45965
|
-
return out;
|
|
45966
|
-
}
|
|
45967
|
-
return value;
|
|
45968
|
-
}
|
|
45969
|
-
|
|
45970
46300
|
// src-ts/memory/index.ts
|
|
45971
46301
|
init_define_ATBASH_CHROMIA_NODE_URLS();
|
|
45972
46302
|
init_define_ATBASH_PRIVATE_NODE_URLS();
|
|
@@ -46309,6 +46639,7 @@ export {
|
|
|
46309
46639
|
classifyMemoryWrite,
|
|
46310
46640
|
columnAad,
|
|
46311
46641
|
commitMemoryVersion,
|
|
46642
|
+
configureEvents,
|
|
46312
46643
|
containsEvasionCharacters2 as containsEvasionCharacters,
|
|
46313
46644
|
containsSecret2 as containsSecret,
|
|
46314
46645
|
createFileLogger,
|
|
@@ -46324,6 +46655,7 @@ export {
|
|
|
46324
46655
|
encryptForOrg,
|
|
46325
46656
|
encryptMemoryContent2 as encryptMemoryContent,
|
|
46326
46657
|
encryptedLength,
|
|
46658
|
+
eventsAreOn,
|
|
46327
46659
|
flushTelemetry,
|
|
46328
46660
|
generateKeypair2 as generateKeypair,
|
|
46329
46661
|
getActiveAgentMemory,
|
|
@@ -46334,7 +46666,6 @@ export {
|
|
|
46334
46666
|
getMemoryHistory,
|
|
46335
46667
|
getRecentAgentMemory,
|
|
46336
46668
|
getRollbackHistory,
|
|
46337
|
-
gtvToFfiSafe,
|
|
46338
46669
|
guardMemoryWrite,
|
|
46339
46670
|
isEnvelope,
|
|
46340
46671
|
isValidPrivateKey2 as isValidPrivateKey,
|
|
@@ -46353,6 +46684,7 @@ export {
|
|
|
46353
46684
|
pubkeyToHex,
|
|
46354
46685
|
recordCall,
|
|
46355
46686
|
recordDuration,
|
|
46687
|
+
recordEvent,
|
|
46356
46688
|
redactJsonStrings,
|
|
46357
46689
|
redactSecrets2 as redactSecrets,
|
|
46358
46690
|
resolve,
|