blockintel-gate-sdk 0.3.6 → 0.3.8
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/README.md +24 -0
- package/dist/index.cjs +397 -145
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +107 -3
- package/dist/index.d.ts +107 -3
- package/dist/index.js +395 -145
- package/dist/index.js.map +1 -1
- package/package.json +3 -7
package/dist/index.cjs
CHANGED
|
@@ -2,18 +2,12 @@
|
|
|
2
2
|
|
|
3
3
|
Object.defineProperty(exports, '__esModule', { value: true });
|
|
4
4
|
|
|
5
|
+
var crypto = require('crypto');
|
|
5
6
|
var uuid = require('uuid');
|
|
6
7
|
var clientKms = require('@aws-sdk/client-kms');
|
|
7
|
-
var crypto$1 = require('crypto');
|
|
8
8
|
|
|
9
9
|
var __defProp = Object.defineProperty;
|
|
10
10
|
var __getOwnPropNames = Object.getOwnPropertyNames;
|
|
11
|
-
var __require = /* @__PURE__ */ ((x) => typeof require !== "undefined" ? require : typeof Proxy !== "undefined" ? new Proxy(x, {
|
|
12
|
-
get: (a, b) => (typeof require !== "undefined" ? require : a)[b]
|
|
13
|
-
}) : x)(function(x) {
|
|
14
|
-
if (typeof require !== "undefined") return require.apply(this, arguments);
|
|
15
|
-
throw Error('Dynamic require of "' + x + '" is not supported');
|
|
16
|
-
});
|
|
17
11
|
var __esm = (fn, res) => function __init() {
|
|
18
12
|
return fn && (res = (0, fn[__getOwnPropNames(fn)[0]])(fn = 0)), res;
|
|
19
13
|
};
|
|
@@ -50,56 +44,73 @@ function canonicalizeJson(obj) {
|
|
|
50
44
|
return JSON.stringify(sorted);
|
|
51
45
|
}
|
|
52
46
|
async function sha256Hex(input) {
|
|
53
|
-
|
|
54
|
-
const encoder = new TextEncoder();
|
|
55
|
-
const data = encoder.encode(input);
|
|
56
|
-
const hashBuffer = await crypto.subtle.digest("SHA-256", data);
|
|
57
|
-
const hashArray = Array.from(new Uint8Array(hashBuffer));
|
|
58
|
-
return hashArray.map((b) => b.toString(16).padStart(2, "0")).join("");
|
|
59
|
-
}
|
|
60
|
-
if (typeof __require !== "undefined") {
|
|
61
|
-
const crypto2 = __require("crypto");
|
|
62
|
-
return crypto2.createHash("sha256").update(input, "utf8").digest("hex");
|
|
63
|
-
}
|
|
64
|
-
throw new Error("SHA-256 not available in this environment");
|
|
47
|
+
return crypto.createHash("sha256").update(input, "utf8").digest("hex");
|
|
65
48
|
}
|
|
66
49
|
var init_canonicalJson = __esm({
|
|
67
50
|
"src/utils/canonicalJson.ts"() {
|
|
68
51
|
}
|
|
69
52
|
});
|
|
70
53
|
|
|
71
|
-
// src/utils/
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
signaturePreview: signatureHex.substring(0, 16) + "..."
|
|
84
|
-
}, null, 2));
|
|
85
|
-
return signatureHex;
|
|
86
|
-
}
|
|
87
|
-
if (typeof crypto !== "undefined" && crypto.subtle) {
|
|
88
|
-
const encoder = new TextEncoder();
|
|
89
|
-
const keyData = encoder.encode(secret);
|
|
90
|
-
const messageData = encoder.encode(message);
|
|
91
|
-
const key = await crypto.subtle.importKey(
|
|
92
|
-
"raw",
|
|
93
|
-
keyData,
|
|
94
|
-
{ name: "HMAC", hash: "SHA-256" },
|
|
95
|
-
false,
|
|
96
|
-
["sign"]
|
|
54
|
+
// src/utils/decisionTokenVerify.ts
|
|
55
|
+
var decisionTokenVerify_exports = {};
|
|
56
|
+
__export(decisionTokenVerify_exports, {
|
|
57
|
+
decodeJwtUnsafe: () => decodeJwtUnsafe,
|
|
58
|
+
verifyDecisionTokenRs256: () => verifyDecisionTokenRs256
|
|
59
|
+
});
|
|
60
|
+
function decodeJwtUnsafe(token) {
|
|
61
|
+
try {
|
|
62
|
+
const parts = token.split(".");
|
|
63
|
+
if (parts.length !== 3) return null;
|
|
64
|
+
const header = JSON.parse(
|
|
65
|
+
Buffer.from(parts[0], "base64url").toString("utf8")
|
|
97
66
|
);
|
|
98
|
-
const
|
|
99
|
-
|
|
100
|
-
|
|
67
|
+
const payload = JSON.parse(
|
|
68
|
+
Buffer.from(parts[1], "base64url").toString("utf8")
|
|
69
|
+
);
|
|
70
|
+
return { header, payload };
|
|
71
|
+
} catch {
|
|
72
|
+
return null;
|
|
73
|
+
}
|
|
74
|
+
}
|
|
75
|
+
function verifyDecisionTokenRs256(token, publicKeyPem) {
|
|
76
|
+
const decoded = decodeJwtUnsafe(token);
|
|
77
|
+
if (!decoded || (decoded.header.alg || "").toUpperCase() !== "RS256") return null;
|
|
78
|
+
const { payload } = decoded;
|
|
79
|
+
const now = Math.floor(Date.now() / 1e3);
|
|
80
|
+
if (payload.iss !== ISS || payload.aud !== AUD) return null;
|
|
81
|
+
if (payload.exp != null && payload.exp < now - 5) return null;
|
|
82
|
+
try {
|
|
83
|
+
const parts = token.split(".");
|
|
84
|
+
const signingInput = `${parts[0]}.${parts[1]}`;
|
|
85
|
+
const signature = Buffer.from(parts[2], "base64url");
|
|
86
|
+
const verify = crypto.createVerify("RSA-SHA256");
|
|
87
|
+
verify.update(signingInput);
|
|
88
|
+
verify.end();
|
|
89
|
+
const ok = verify.verify(publicKeyPem, signature);
|
|
90
|
+
return ok ? payload : null;
|
|
91
|
+
} catch {
|
|
92
|
+
return null;
|
|
101
93
|
}
|
|
102
|
-
|
|
94
|
+
}
|
|
95
|
+
var ISS, AUD;
|
|
96
|
+
var init_decisionTokenVerify = __esm({
|
|
97
|
+
"src/utils/decisionTokenVerify.ts"() {
|
|
98
|
+
ISS = "blockintel-gate";
|
|
99
|
+
AUD = "gate-decision";
|
|
100
|
+
}
|
|
101
|
+
});
|
|
102
|
+
async function hmacSha256(secret, message) {
|
|
103
|
+
const hmac = crypto.createHmac("sha256", secret);
|
|
104
|
+
hmac.update(message, "utf8");
|
|
105
|
+
const signatureHex = hmac.digest("hex");
|
|
106
|
+
console.error("[HMAC CRYPTO DEBUG] Signature computation:", JSON.stringify({
|
|
107
|
+
secretLength: secret.length,
|
|
108
|
+
messageLength: message.length,
|
|
109
|
+
messagePreview: message.substring(0, 200) + "...",
|
|
110
|
+
signatureLength: signatureHex.length,
|
|
111
|
+
signaturePreview: signatureHex.substring(0, 16) + "..."
|
|
112
|
+
}, null, 2));
|
|
113
|
+
return signatureHex;
|
|
103
114
|
}
|
|
104
115
|
|
|
105
116
|
// src/auth/HmacSigner.ts
|
|
@@ -132,26 +143,7 @@ var HmacSigner = class {
|
|
|
132
143
|
// Used as nonce in canonical string
|
|
133
144
|
bodyHash
|
|
134
145
|
].join("\n");
|
|
135
|
-
console.error("[HMAC SIGNER DEBUG] Canonical request string:", JSON.stringify({
|
|
136
|
-
method: method.toUpperCase(),
|
|
137
|
-
path,
|
|
138
|
-
tenantId,
|
|
139
|
-
keyId: this.keyId,
|
|
140
|
-
timestampMs: String(timestampMs),
|
|
141
|
-
requestId,
|
|
142
|
-
bodyHash,
|
|
143
|
-
signingStringLength: signingString.length,
|
|
144
|
-
signingStringPreview: signingString.substring(0, 200) + "...",
|
|
145
|
-
bodyJsonLength: bodyJson.length,
|
|
146
|
-
bodyJsonPreview: bodyJson.substring(0, 200) + "..."
|
|
147
|
-
}, null, 2));
|
|
148
146
|
const signature = await hmacSha256(this.secret, signingString);
|
|
149
|
-
console.error("[HMAC SIGNER DEBUG] Signature computed:", JSON.stringify({
|
|
150
|
-
signatureLength: signature.length,
|
|
151
|
-
signaturePreview: signature.substring(0, 16) + "...",
|
|
152
|
-
secretLength: this.secret.length,
|
|
153
|
-
secretPreview: this.secret.substring(0, 4) + "..." + this.secret.substring(this.secret.length - 4)
|
|
154
|
-
}, null, 2));
|
|
155
147
|
return {
|
|
156
148
|
"X-GATE-TENANT-ID": tenantId,
|
|
157
149
|
"X-GATE-KEY-ID": this.keyId,
|
|
@@ -350,6 +342,10 @@ async function retryWithBackoff(fn, options = {}) {
|
|
|
350
342
|
if (!isRetryable) {
|
|
351
343
|
throw error;
|
|
352
344
|
}
|
|
345
|
+
const status = error instanceof Response && error.status || error && typeof error === "object" && "status" in error && error.status || error && typeof error === "object" && "statusCode" in error && error.statusCode;
|
|
346
|
+
const errName = error instanceof Error ? error.name : error && typeof error === "object" && "code" in error ? error.code : "Unknown";
|
|
347
|
+
const extra = ` attempt=${attempt}/${opts.maxAttempts} status=${status ?? "n/a"} err=${errName}`;
|
|
348
|
+
console.warn("[GATE SDK] X-BlockIntel-Degraded: true (reason=retry)" + extra);
|
|
353
349
|
const delay = calculateBackoffDelay(attempt, opts);
|
|
354
350
|
await new Promise((resolve) => setTimeout(resolve, delay));
|
|
355
351
|
}
|
|
@@ -357,17 +353,73 @@ async function retryWithBackoff(fn, options = {}) {
|
|
|
357
353
|
throw lastError;
|
|
358
354
|
}
|
|
359
355
|
|
|
356
|
+
// src/utils/sanitize.ts
|
|
357
|
+
var SENSITIVE_HEADER_NAMES = /* @__PURE__ */ new Set([
|
|
358
|
+
"authorization",
|
|
359
|
+
"x-api-key",
|
|
360
|
+
"x-gate-heartbeat-key",
|
|
361
|
+
"x-gate-signature",
|
|
362
|
+
"cookie"
|
|
363
|
+
]);
|
|
364
|
+
var MAX_STRING_LENGTH = 80;
|
|
365
|
+
function sanitizeHeaders(headers) {
|
|
366
|
+
const out = {};
|
|
367
|
+
for (const [key, value] of Object.entries(headers)) {
|
|
368
|
+
const lower = key.toLowerCase();
|
|
369
|
+
if (SENSITIVE_HEADER_NAMES.has(lower) || lower.includes("signature") || lower.includes("secret") || lower.includes("token")) {
|
|
370
|
+
out[key] = value ? "[REDACTED]" : "[empty]";
|
|
371
|
+
} else {
|
|
372
|
+
out[key] = truncate(String(value), MAX_STRING_LENGTH);
|
|
373
|
+
}
|
|
374
|
+
}
|
|
375
|
+
return out;
|
|
376
|
+
}
|
|
377
|
+
function sanitizeBodyShape(body) {
|
|
378
|
+
if (body === null || body === void 0) {
|
|
379
|
+
return {};
|
|
380
|
+
}
|
|
381
|
+
if (typeof body !== "object") {
|
|
382
|
+
return { _: typeof body };
|
|
383
|
+
}
|
|
384
|
+
if (Array.isArray(body)) {
|
|
385
|
+
return { _: "array", length: String(body.length) };
|
|
386
|
+
}
|
|
387
|
+
const out = {};
|
|
388
|
+
for (const key of Object.keys(body).sort()) {
|
|
389
|
+
const val = body[key];
|
|
390
|
+
if (val !== null && typeof val === "object" && !Array.isArray(val)) {
|
|
391
|
+
out[key] = "object";
|
|
392
|
+
} else if (Array.isArray(val)) {
|
|
393
|
+
out[key] = "array";
|
|
394
|
+
} else {
|
|
395
|
+
out[key] = typeof val;
|
|
396
|
+
}
|
|
397
|
+
}
|
|
398
|
+
return out;
|
|
399
|
+
}
|
|
400
|
+
function truncate(s, max) {
|
|
401
|
+
if (s.length <= max) return s;
|
|
402
|
+
return s.slice(0, max) + "...";
|
|
403
|
+
}
|
|
404
|
+
function isDebugEnabled(debugOption) {
|
|
405
|
+
if (debugOption === true) return true;
|
|
406
|
+
if (typeof process !== "undefined" && process.env.GATE_SDK_DEBUG === "1") return true;
|
|
407
|
+
return false;
|
|
408
|
+
}
|
|
409
|
+
|
|
360
410
|
// src/http/HttpClient.ts
|
|
361
411
|
var HttpClient = class {
|
|
362
412
|
baseUrl;
|
|
363
413
|
timeoutMs;
|
|
364
414
|
userAgent;
|
|
365
415
|
retryOptions;
|
|
416
|
+
debug;
|
|
366
417
|
constructor(config) {
|
|
367
418
|
this.baseUrl = config.baseUrl.replace(/\/$/, "");
|
|
368
419
|
this.timeoutMs = config.timeoutMs ?? 15e3;
|
|
369
420
|
this.userAgent = config.userAgent ?? "blockintel-gate-sdk/0.1.0";
|
|
370
421
|
this.retryOptions = config.retryOptions;
|
|
422
|
+
this.debug = isDebugEnabled(config.debug);
|
|
371
423
|
if (!this.baseUrl) {
|
|
372
424
|
throw new Error("baseUrl is required");
|
|
373
425
|
}
|
|
@@ -386,7 +438,6 @@ var HttpClient = class {
|
|
|
386
438
|
const controller = new AbortController();
|
|
387
439
|
const timeoutId = setTimeout(() => controller.abort(), this.timeoutMs);
|
|
388
440
|
let requestDetailsForLogging = null;
|
|
389
|
-
let requestDetailsSet = false;
|
|
390
441
|
try {
|
|
391
442
|
const response = await retryWithBackoff(
|
|
392
443
|
async () => {
|
|
@@ -409,31 +460,22 @@ var HttpClient = class {
|
|
|
409
460
|
fetchOptions.body = JSON.stringify(body);
|
|
410
461
|
}
|
|
411
462
|
}
|
|
412
|
-
const logHeaders = {};
|
|
413
|
-
if (fetchOptions.headers) {
|
|
414
|
-
Object.entries(fetchOptions.headers).forEach(([key, value]) => {
|
|
415
|
-
if (key.toLowerCase().includes("signature") || key.toLowerCase().includes("secret")) {
|
|
416
|
-
logHeaders[key] = String(value).substring(0, 8) + "...";
|
|
417
|
-
} else {
|
|
418
|
-
logHeaders[key] = String(value);
|
|
419
|
-
}
|
|
420
|
-
});
|
|
421
|
-
}
|
|
422
463
|
const bodyStr = typeof fetchOptions.body === "string" ? fetchOptions.body : null;
|
|
423
|
-
|
|
424
|
-
headers:
|
|
425
|
-
bodyLength: bodyStr ? bodyStr.length : 0
|
|
426
|
-
bodyPreview: bodyStr ? bodyStr.substring(0, 300) : null
|
|
464
|
+
requestDetailsForLogging = {
|
|
465
|
+
headers: this.debug ? sanitizeHeaders(requestHeaders) : {},
|
|
466
|
+
bodyLength: bodyStr ? bodyStr.length : 0
|
|
427
467
|
};
|
|
428
|
-
|
|
429
|
-
|
|
430
|
-
|
|
431
|
-
|
|
432
|
-
|
|
433
|
-
|
|
434
|
-
|
|
435
|
-
|
|
436
|
-
|
|
468
|
+
if (this.debug) {
|
|
469
|
+
const bodyShape = body && typeof body === "object" ? sanitizeBodyShape(body) : {};
|
|
470
|
+
console.error("[GATE SDK] Request:", JSON.stringify({
|
|
471
|
+
url,
|
|
472
|
+
method,
|
|
473
|
+
headerNames: Object.keys(requestHeaders),
|
|
474
|
+
headersRedacted: requestDetailsForLogging.headers,
|
|
475
|
+
bodyLength: requestDetailsForLogging.bodyLength,
|
|
476
|
+
bodyKeysAndTypes: bodyShape
|
|
477
|
+
}, null, 2));
|
|
478
|
+
}
|
|
437
479
|
const res = await fetch(url, fetchOptions);
|
|
438
480
|
if (!res.ok && isRetryableStatus(res.status)) {
|
|
439
481
|
throw res;
|
|
@@ -451,26 +493,24 @@ var HttpClient = class {
|
|
|
451
493
|
clearTimeout(timeoutId);
|
|
452
494
|
let data;
|
|
453
495
|
const contentType = response.headers.get("content-type");
|
|
454
|
-
|
|
455
|
-
|
|
456
|
-
|
|
457
|
-
|
|
458
|
-
|
|
459
|
-
|
|
460
|
-
}
|
|
496
|
+
if (this.debug) {
|
|
497
|
+
console.error("[GATE SDK] Response:", JSON.stringify({
|
|
498
|
+
status: response.status,
|
|
499
|
+
ok: response.ok,
|
|
500
|
+
url: response.url
|
|
501
|
+
}, null, 2));
|
|
502
|
+
}
|
|
461
503
|
if (contentType && contentType.includes("application/json")) {
|
|
462
504
|
try {
|
|
463
505
|
const jsonText = await response.text();
|
|
464
|
-
console.error("[HTTP CLIENT DEBUG] Response body (first 500 chars):", jsonText.substring(0, 500));
|
|
465
506
|
data = JSON.parse(jsonText);
|
|
466
|
-
|
|
467
|
-
|
|
468
|
-
|
|
469
|
-
hasData: typeof data?.data !== "undefined",
|
|
470
|
-
hasError: typeof data?.error !== "undefined"
|
|
471
|
-
}, null, 2));
|
|
507
|
+
if (this.debug && data && typeof data === "object") {
|
|
508
|
+
console.error("[GATE SDK] Response keys:", Object.keys(data));
|
|
509
|
+
}
|
|
472
510
|
} catch (parseError) {
|
|
473
|
-
|
|
511
|
+
if (this.debug) {
|
|
512
|
+
console.error("[GATE SDK] JSON parse error:", parseError instanceof Error ? parseError.message : String(parseError));
|
|
513
|
+
}
|
|
474
514
|
throw new GateError(
|
|
475
515
|
"INVALID_RESPONSE" /* INVALID_RESPONSE */,
|
|
476
516
|
"Failed to parse JSON response",
|
|
@@ -498,26 +538,12 @@ var HttpClient = class {
|
|
|
498
538
|
response.headers.forEach((value, key) => {
|
|
499
539
|
responseHeaders[key] = value;
|
|
500
540
|
});
|
|
501
|
-
if (
|
|
502
|
-
console.error("[
|
|
541
|
+
if (this.debug) {
|
|
542
|
+
console.error("[GATE SDK] Error response:", JSON.stringify({
|
|
503
543
|
status: response.status,
|
|
504
|
-
statusText: response.statusText,
|
|
505
544
|
url: response.url,
|
|
506
|
-
requestMethod: method,
|
|
507
545
|
requestPath: path,
|
|
508
|
-
|
|
509
|
-
responseHeaders,
|
|
510
|
-
responseData: data,
|
|
511
|
-
bodyLength: requestDetailsForLogging ? requestDetailsForLogging.bodyLength : 0,
|
|
512
|
-
bodyPreview: requestDetailsForLogging ? requestDetailsForLogging.bodyPreview : null
|
|
513
|
-
}, null, 2));
|
|
514
|
-
} else {
|
|
515
|
-
console.error("[HTTP CLIENT DEBUG] Response not OK:", JSON.stringify({
|
|
516
|
-
status: response.status,
|
|
517
|
-
statusText: response.statusText,
|
|
518
|
-
url: response.url,
|
|
519
|
-
headers: responseHeaders,
|
|
520
|
-
data
|
|
546
|
+
responseKeys: data && typeof data === "object" ? Object.keys(data) : []
|
|
521
547
|
}, null, 2));
|
|
522
548
|
}
|
|
523
549
|
const errorCode = this.statusToErrorCode(response.status);
|
|
@@ -529,7 +555,6 @@ var HttpClient = class {
|
|
|
529
555
|
details: data
|
|
530
556
|
});
|
|
531
557
|
}
|
|
532
|
-
console.error("[HTTP CLIENT DEBUG] Response OK, returning data");
|
|
533
558
|
return data;
|
|
534
559
|
} catch (error) {
|
|
535
560
|
clearTimeout(timeoutId);
|
|
@@ -946,6 +971,75 @@ var MetricsCollector = class {
|
|
|
946
971
|
this.latencyMs = [];
|
|
947
972
|
}
|
|
948
973
|
};
|
|
974
|
+
function canonicalJsonBinding(obj) {
|
|
975
|
+
if (obj === null || obj === void 0) return "null";
|
|
976
|
+
if (typeof obj === "string") return JSON.stringify(obj);
|
|
977
|
+
if (typeof obj === "number") return obj.toString();
|
|
978
|
+
if (typeof obj === "boolean") return obj ? "true" : "false";
|
|
979
|
+
if (Array.isArray(obj)) {
|
|
980
|
+
const items = obj.map((item) => canonicalJsonBinding(item));
|
|
981
|
+
return "[" + items.join(",") + "]";
|
|
982
|
+
}
|
|
983
|
+
if (typeof obj === "object") {
|
|
984
|
+
const keys = Object.keys(obj).sort();
|
|
985
|
+
const pairs = [];
|
|
986
|
+
for (const key of keys) {
|
|
987
|
+
const value = obj[key];
|
|
988
|
+
if (value !== void 0) {
|
|
989
|
+
pairs.push(JSON.stringify(key) + ":" + canonicalJsonBinding(value));
|
|
990
|
+
}
|
|
991
|
+
}
|
|
992
|
+
return "{" + pairs.join(",") + "}";
|
|
993
|
+
}
|
|
994
|
+
return JSON.stringify(obj);
|
|
995
|
+
}
|
|
996
|
+
function normalizeAddress(addr) {
|
|
997
|
+
if (addr == null || addr === "") return "";
|
|
998
|
+
const s = String(addr).trim();
|
|
999
|
+
if (s.startsWith("0x")) return s.toLowerCase();
|
|
1000
|
+
return "0x" + s.toLowerCase();
|
|
1001
|
+
}
|
|
1002
|
+
function normalizeData(data) {
|
|
1003
|
+
if (data == null || data === "") return "";
|
|
1004
|
+
const s = String(data).trim().toLowerCase();
|
|
1005
|
+
return s.startsWith("0x") ? s : "0x" + s;
|
|
1006
|
+
}
|
|
1007
|
+
function buildTxBindingObject(txIntent, signerId, decodedRecipient, decodedFields, fromAddress) {
|
|
1008
|
+
const toAddr = txIntent.toAddress ?? txIntent.to ?? "";
|
|
1009
|
+
const value = (txIntent.valueAtomic ?? txIntent.valueDecimal ?? txIntent.value ?? "0").toString();
|
|
1010
|
+
const data = normalizeData(
|
|
1011
|
+
txIntent.data ?? txIntent.payloadHash ?? txIntent.dataHash ?? ""
|
|
1012
|
+
);
|
|
1013
|
+
const chainId = (txIntent.chainId ?? txIntent.chain ?? "").toString();
|
|
1014
|
+
const toAddress = normalizeAddress(toAddr);
|
|
1015
|
+
const nonce = txIntent.nonce != null ? String(txIntent.nonce) : "";
|
|
1016
|
+
const decoded = {};
|
|
1017
|
+
if (decodedFields && typeof decodedFields === "object") {
|
|
1018
|
+
for (const [k, v] of Object.entries(decodedFields)) {
|
|
1019
|
+
if (v !== void 0) decoded[k] = v;
|
|
1020
|
+
}
|
|
1021
|
+
}
|
|
1022
|
+
const out = {
|
|
1023
|
+
chainId,
|
|
1024
|
+
toAddress,
|
|
1025
|
+
value,
|
|
1026
|
+
data,
|
|
1027
|
+
nonce
|
|
1028
|
+
};
|
|
1029
|
+
if (fromAddress) out.fromAddress = normalizeAddress(fromAddress);
|
|
1030
|
+
if (decodedRecipient != null)
|
|
1031
|
+
out.decodedRecipient = decodedRecipient ? normalizeAddress(decodedRecipient) : null;
|
|
1032
|
+
if (Object.keys(decoded).length > 0) out.decoded = decoded;
|
|
1033
|
+
if (signerId) out.signerId = signerId;
|
|
1034
|
+
if (txIntent.networkFamily) out.networkFamily = txIntent.networkFamily;
|
|
1035
|
+
return out;
|
|
1036
|
+
}
|
|
1037
|
+
function computeTxDigest(binding) {
|
|
1038
|
+
const canonical = canonicalJsonBinding(binding);
|
|
1039
|
+
return crypto.createHash("sha256").update(canonical, "utf8").digest("hex");
|
|
1040
|
+
}
|
|
1041
|
+
|
|
1042
|
+
// src/kms/wrapAwsSdkV3KmsClient.ts
|
|
949
1043
|
function wrapKmsClient(kmsClient, gateClient, options = {}) {
|
|
950
1044
|
const defaultOptions = {
|
|
951
1045
|
mode: options.mode || "enforce",
|
|
@@ -982,7 +1076,7 @@ function defaultExtractTxIntent(command) {
|
|
|
982
1076
|
throw new Error("SignCommand missing required Message property");
|
|
983
1077
|
}
|
|
984
1078
|
const messageBuffer = message instanceof Buffer ? message : Buffer.from(message);
|
|
985
|
-
const messageHash = crypto
|
|
1079
|
+
const messageHash = crypto.createHash("sha256").update(messageBuffer).digest("hex");
|
|
986
1080
|
return {
|
|
987
1081
|
networkFamily: "OTHER",
|
|
988
1082
|
toAddress: void 0,
|
|
@@ -1021,6 +1115,34 @@ async function handleSignCommand(command, originalClient, gateClient, options) {
|
|
|
1021
1115
|
// Type assertion - txIntent may have extra fields
|
|
1022
1116
|
signingContext
|
|
1023
1117
|
});
|
|
1118
|
+
if (decision.decision === "ALLOW" && gateClient.getRequireDecisionToken() && decision.txDigest != null) {
|
|
1119
|
+
const binding = buildTxBindingObject(
|
|
1120
|
+
txIntent,
|
|
1121
|
+
signerId,
|
|
1122
|
+
void 0,
|
|
1123
|
+
void 0,
|
|
1124
|
+
signingContext.actorPrincipal
|
|
1125
|
+
);
|
|
1126
|
+
const computedDigest = computeTxDigest(binding);
|
|
1127
|
+
if (computedDigest !== decision.txDigest) {
|
|
1128
|
+
options.onDecision("BLOCK", {
|
|
1129
|
+
error: new BlockIntelBlockedError(
|
|
1130
|
+
"DECISION_TOKEN_TX_MISMATCH",
|
|
1131
|
+
decision.decisionId,
|
|
1132
|
+
decision.correlationId,
|
|
1133
|
+
void 0
|
|
1134
|
+
),
|
|
1135
|
+
signerId,
|
|
1136
|
+
command
|
|
1137
|
+
});
|
|
1138
|
+
throw new BlockIntelBlockedError(
|
|
1139
|
+
"DECISION_TOKEN_TX_MISMATCH",
|
|
1140
|
+
decision.decisionId,
|
|
1141
|
+
decision.correlationId,
|
|
1142
|
+
void 0
|
|
1143
|
+
);
|
|
1144
|
+
}
|
|
1145
|
+
}
|
|
1024
1146
|
options.onDecision("ALLOW", { decision, signerId, command });
|
|
1025
1147
|
if (options.mode === "dry-run") {
|
|
1026
1148
|
return await originalClient.send(new clientKms.SignCommand(command));
|
|
@@ -1088,6 +1210,8 @@ var HeartbeatManager = class {
|
|
|
1088
1210
|
// Unique per process
|
|
1089
1211
|
sdkVersion;
|
|
1090
1212
|
// SDK version for tracking
|
|
1213
|
+
apiKey;
|
|
1214
|
+
// x-gate-heartbeat-key for Control Plane auth
|
|
1091
1215
|
currentToken = null;
|
|
1092
1216
|
refreshTimer = null;
|
|
1093
1217
|
started = false;
|
|
@@ -1100,19 +1224,22 @@ var HeartbeatManager = class {
|
|
|
1100
1224
|
this.signerId = options.signerId;
|
|
1101
1225
|
this.environment = options.environment ?? "prod";
|
|
1102
1226
|
this.baseRefreshIntervalSeconds = options.refreshIntervalSeconds ?? 10;
|
|
1227
|
+
this.apiKey = options.apiKey;
|
|
1103
1228
|
this.clientInstanceId = options.clientInstanceId || uuid.v4();
|
|
1104
1229
|
this.sdkVersion = options.sdkVersion || "1.0.0";
|
|
1230
|
+
this.apiKey = options.apiKey;
|
|
1105
1231
|
}
|
|
1106
1232
|
/**
|
|
1107
|
-
* Start background heartbeat refresher
|
|
1233
|
+
* Start background heartbeat refresher.
|
|
1234
|
+
* Optionally wait for initial token (first evaluate() will otherwise wait up to 2s for token).
|
|
1108
1235
|
*/
|
|
1109
|
-
start() {
|
|
1236
|
+
start(options) {
|
|
1110
1237
|
if (this.started) {
|
|
1111
1238
|
return;
|
|
1112
1239
|
}
|
|
1113
1240
|
this.started = true;
|
|
1114
1241
|
this.acquireHeartbeat().catch((error) => {
|
|
1115
|
-
console.error("[HEARTBEAT] Failed to acquire initial heartbeat:", error);
|
|
1242
|
+
console.error("[HEARTBEAT] Failed to acquire initial heartbeat:", error instanceof Error ? error.message : error);
|
|
1116
1243
|
});
|
|
1117
1244
|
this.scheduleNextRefresh();
|
|
1118
1245
|
}
|
|
@@ -1195,12 +1322,23 @@ var HeartbeatManager = class {
|
|
|
1195
1322
|
/**
|
|
1196
1323
|
* Acquire a new heartbeat token from Control Plane
|
|
1197
1324
|
* NEVER logs token value (security)
|
|
1325
|
+
* Requires x-gate-heartbeat-key header (apiKey) for authentication.
|
|
1198
1326
|
*/
|
|
1199
1327
|
async acquireHeartbeat() {
|
|
1328
|
+
if (!this.apiKey || this.apiKey.length === 0) {
|
|
1329
|
+
throw new GateError(
|
|
1330
|
+
"UNAUTHORIZED" /* UNAUTHORIZED */,
|
|
1331
|
+
"Heartbeat API key is required. Set GATE_HEARTBEAT_KEY in environment or pass heartbeatApiKey in GateClientConfig.",
|
|
1332
|
+
{}
|
|
1333
|
+
);
|
|
1334
|
+
}
|
|
1200
1335
|
try {
|
|
1201
1336
|
const response = await this.httpClient.request({
|
|
1202
1337
|
method: "POST",
|
|
1203
1338
|
path: "/api/v1/gate/heartbeat",
|
|
1339
|
+
headers: {
|
|
1340
|
+
"x-gate-heartbeat-key": this.apiKey
|
|
1341
|
+
},
|
|
1204
1342
|
body: {
|
|
1205
1343
|
tenantId: this.tenantId,
|
|
1206
1344
|
signerId: this.signerId,
|
|
@@ -1528,7 +1666,8 @@ var GateClient = class {
|
|
|
1528
1666
|
this.httpClient = new HttpClient({
|
|
1529
1667
|
baseUrl: config.baseUrl,
|
|
1530
1668
|
timeoutMs: config.timeoutMs,
|
|
1531
|
-
userAgent: config.userAgent
|
|
1669
|
+
userAgent: config.userAgent,
|
|
1670
|
+
debug: config.debug
|
|
1532
1671
|
});
|
|
1533
1672
|
if (config.enableStepUp) {
|
|
1534
1673
|
this.stepUpPoller = new StepUpPoller({
|
|
@@ -1549,6 +1688,12 @@ var GateClient = class {
|
|
|
1549
1688
|
console.warn("[GATE CLIENT] LOCAL MODE ENABLED - Auth, heartbeat, and break-glass are disabled");
|
|
1550
1689
|
this.heartbeatManager = null;
|
|
1551
1690
|
} else {
|
|
1691
|
+
const heartbeatApiKey = config.heartbeatApiKey ?? (typeof process !== "undefined" ? process.env.GATE_HEARTBEAT_KEY : void 0);
|
|
1692
|
+
if (!heartbeatApiKey || heartbeatApiKey.length === 0) {
|
|
1693
|
+
throw new Error(
|
|
1694
|
+
"GATE_HEARTBEAT_KEY environment variable or heartbeatApiKey in config is required for heartbeat authentication. Set GATE_HEARTBEAT_KEY in your environment or pass heartbeatApiKey in GateClientConfig."
|
|
1695
|
+
);
|
|
1696
|
+
}
|
|
1552
1697
|
let controlPlaneUrl = config.baseUrl;
|
|
1553
1698
|
if (controlPlaneUrl.includes("/defense")) {
|
|
1554
1699
|
controlPlaneUrl = controlPlaneUrl.split("/defense")[0];
|
|
@@ -1568,7 +1713,8 @@ var GateClient = class {
|
|
|
1568
1713
|
tenantId: config.tenantId,
|
|
1569
1714
|
signerId: initialSignerId,
|
|
1570
1715
|
environment: config.environment ?? "prod",
|
|
1571
|
-
refreshIntervalSeconds: config.heartbeatRefreshIntervalSeconds ?? 10
|
|
1716
|
+
refreshIntervalSeconds: config.heartbeatRefreshIntervalSeconds ?? 10,
|
|
1717
|
+
apiKey: heartbeatApiKey
|
|
1572
1718
|
});
|
|
1573
1719
|
this.heartbeatManager.start();
|
|
1574
1720
|
}
|
|
@@ -1593,6 +1739,16 @@ var GateClient = class {
|
|
|
1593
1739
|
});
|
|
1594
1740
|
}
|
|
1595
1741
|
}
|
|
1742
|
+
/**
|
|
1743
|
+
* Whether the SDK requires a decision token for ALLOW before sign (ENFORCE/HARD).
|
|
1744
|
+
* Env GATE_REQUIRE_DECISION_TOKEN overrides config.
|
|
1745
|
+
*/
|
|
1746
|
+
getRequireDecisionToken() {
|
|
1747
|
+
if (typeof process !== "undefined" && process.env.GATE_REQUIRE_DECISION_TOKEN !== void 0) {
|
|
1748
|
+
return process.env.GATE_REQUIRE_DECISION_TOKEN === "true" || process.env.GATE_REQUIRE_DECISION_TOKEN === "1";
|
|
1749
|
+
}
|
|
1750
|
+
return this.config.requireDecisionToken ?? (this.mode === "ENFORCE" || this.config.enforcementMode === "HARD");
|
|
1751
|
+
}
|
|
1596
1752
|
/**
|
|
1597
1753
|
* Perform async IAM permission risk check (non-blocking)
|
|
1598
1754
|
*
|
|
@@ -1623,6 +1779,7 @@ var GateClient = class {
|
|
|
1623
1779
|
const startTime = Date.now();
|
|
1624
1780
|
const failSafeMode = this.config.failSafeMode ?? "ALLOW_ON_TIMEOUT";
|
|
1625
1781
|
const requestMode = req.mode || this.mode;
|
|
1782
|
+
const requireToken = this.getRequireDecisionToken();
|
|
1626
1783
|
const executeRequest = async () => {
|
|
1627
1784
|
if (!this.config.local && this.heartbeatManager && req.signingContext?.signerId) {
|
|
1628
1785
|
this.heartbeatManager.updateSignerId(req.signingContext.signerId);
|
|
@@ -1657,7 +1814,9 @@ var GateClient = class {
|
|
|
1657
1814
|
delete txIntent.from;
|
|
1658
1815
|
}
|
|
1659
1816
|
const signingContext = {
|
|
1660
|
-
...req.signingContext
|
|
1817
|
+
...req.signingContext,
|
|
1818
|
+
actorPrincipal: req.signingContext?.actorPrincipal ?? req.signingContext?.signerId ?? "gate-sdk-client",
|
|
1819
|
+
signerId: req.signingContext?.signerId ?? req.signingContext?.actorPrincipal ?? "gate-sdk-client"
|
|
1661
1820
|
};
|
|
1662
1821
|
if (heartbeatToken) {
|
|
1663
1822
|
signingContext.heartbeatToken = heartbeatToken;
|
|
@@ -1673,17 +1832,16 @@ var GateClient = class {
|
|
|
1673
1832
|
};
|
|
1674
1833
|
}
|
|
1675
1834
|
let body = {
|
|
1835
|
+
tenantId: this.config.tenantId,
|
|
1676
1836
|
requestId,
|
|
1677
1837
|
timestampMs,
|
|
1678
1838
|
txIntent,
|
|
1679
1839
|
signingContext,
|
|
1680
1840
|
// Add SDK info (required by Hot Path validation)
|
|
1681
|
-
// Note: Must match Python SDK name for consistent canonical JSON
|
|
1682
1841
|
sdk: {
|
|
1683
1842
|
name: "gate-sdk",
|
|
1684
1843
|
version: "0.1.0"
|
|
1685
1844
|
},
|
|
1686
|
-
// Add mode and connection failure strategy
|
|
1687
1845
|
mode: requestMode,
|
|
1688
1846
|
onConnectionFailure: this.onConnectionFailure
|
|
1689
1847
|
};
|
|
@@ -1713,15 +1871,6 @@ var GateClient = class {
|
|
|
1713
1871
|
});
|
|
1714
1872
|
headers = { ...hmacHeaders };
|
|
1715
1873
|
body.__canonicalJson = canonicalBodyJson;
|
|
1716
|
-
const debugHeaders = {};
|
|
1717
|
-
Object.entries(headers).forEach(([key, value]) => {
|
|
1718
|
-
if (key.toLowerCase().includes("signature")) {
|
|
1719
|
-
debugHeaders[key] = value.substring(0, 8) + "...";
|
|
1720
|
-
} else {
|
|
1721
|
-
debugHeaders[key] = value;
|
|
1722
|
-
}
|
|
1723
|
-
});
|
|
1724
|
-
console.error("[GATE CLIENT DEBUG] HMAC headers prepared:", JSON.stringify(debugHeaders, null, 2));
|
|
1725
1874
|
} else if (this.apiKeyAuth) {
|
|
1726
1875
|
const apiKeyHeaders = this.apiKeyAuth.createHeaders({
|
|
1727
1876
|
tenantId: this.config.tenantId,
|
|
@@ -1729,7 +1878,6 @@ var GateClient = class {
|
|
|
1729
1878
|
requestId
|
|
1730
1879
|
});
|
|
1731
1880
|
headers = { ...apiKeyHeaders };
|
|
1732
|
-
console.error("[GATE CLIENT DEBUG] API key headers prepared:", JSON.stringify(headers, null, 2));
|
|
1733
1881
|
} else {
|
|
1734
1882
|
throw new Error("No authentication configured");
|
|
1735
1883
|
}
|
|
@@ -1774,6 +1922,10 @@ var GateClient = class {
|
|
|
1774
1922
|
reasonCodes: responseData.reason_codes ?? responseData.reasonCodes ?? [],
|
|
1775
1923
|
policyVersion: responseData.policy_version ?? responseData.policyVersion,
|
|
1776
1924
|
correlationId: responseData.correlation_id ?? responseData.correlationId,
|
|
1925
|
+
decisionId: responseData.decision_id ?? responseData.decisionId,
|
|
1926
|
+
decisionToken: responseData.decision_token ?? responseData.decisionToken,
|
|
1927
|
+
expiresAt: responseData.expires_at ?? responseData.expiresAt,
|
|
1928
|
+
txDigest: responseData.tx_digest ?? responseData.txDigest,
|
|
1777
1929
|
stepUp: responseData.step_up ? {
|
|
1778
1930
|
requestId: responseData.step_up.request_id ?? (responseData.stepUp?.requestId ?? ""),
|
|
1779
1931
|
ttlSeconds: responseData.step_up.ttl_seconds ?? responseData.stepUp?.ttlSeconds
|
|
@@ -1789,9 +1941,100 @@ var GateClient = class {
|
|
|
1789
1941
|
errorReason: simulationData.errorReason ?? simulationData.error_reason
|
|
1790
1942
|
},
|
|
1791
1943
|
simulationLatencyMs: metadata.simulationLatencyMs ?? metadata.simulation_latency_ms
|
|
1792
|
-
} : {}
|
|
1944
|
+
} : {},
|
|
1945
|
+
metadata: {
|
|
1946
|
+
evaluationLatencyMs: metadata.evaluationLatencyMs ?? metadata.evaluation_latency_ms,
|
|
1947
|
+
policyHash: metadata.policyHash ?? metadata.policy_hash,
|
|
1948
|
+
snapshotVersion: metadata.snapshotVersion ?? metadata.snapshot_version
|
|
1949
|
+
}
|
|
1793
1950
|
};
|
|
1794
1951
|
const latencyMs = Date.now() - startTime;
|
|
1952
|
+
const expectedPolicyHash = this.config.expectedPolicyHash;
|
|
1953
|
+
const expectedSnapshotVersion = this.config.expectedSnapshotVersion;
|
|
1954
|
+
if (expectedPolicyHash != null && result.metadata?.policyHash !== expectedPolicyHash) {
|
|
1955
|
+
if (this.config.debug) {
|
|
1956
|
+
console.warn("[GATE SDK] Policy hash mismatch (pinning)", {
|
|
1957
|
+
expected: expectedPolicyHash,
|
|
1958
|
+
received: result.metadata?.policyHash,
|
|
1959
|
+
requestId
|
|
1960
|
+
});
|
|
1961
|
+
}
|
|
1962
|
+
this.metrics.recordRequest("BLOCK", latencyMs);
|
|
1963
|
+
throw new BlockIntelBlockedError(
|
|
1964
|
+
"POLICY_HASH_MISMATCH",
|
|
1965
|
+
result.decisionId ?? requestId,
|
|
1966
|
+
result.correlationId,
|
|
1967
|
+
requestId
|
|
1968
|
+
);
|
|
1969
|
+
}
|
|
1970
|
+
if (expectedSnapshotVersion != null && result.metadata?.snapshotVersion !== void 0 && result.metadata.snapshotVersion !== expectedSnapshotVersion) {
|
|
1971
|
+
if (this.config.debug) {
|
|
1972
|
+
console.warn("[GATE SDK] Snapshot version mismatch (pinning)", {
|
|
1973
|
+
expected: expectedSnapshotVersion,
|
|
1974
|
+
received: result.metadata?.snapshotVersion,
|
|
1975
|
+
requestId
|
|
1976
|
+
});
|
|
1977
|
+
}
|
|
1978
|
+
this.metrics.recordRequest("BLOCK", latencyMs);
|
|
1979
|
+
throw new BlockIntelBlockedError(
|
|
1980
|
+
"SNAPSHOT_VERSION_MISMATCH",
|
|
1981
|
+
result.decisionId ?? requestId,
|
|
1982
|
+
result.correlationId,
|
|
1983
|
+
requestId
|
|
1984
|
+
);
|
|
1985
|
+
}
|
|
1986
|
+
if (requireToken && requestMode === "ENFORCE" && result.decision === "ALLOW" && !this.config.local) {
|
|
1987
|
+
if (!result.decisionToken || !result.txDigest) {
|
|
1988
|
+
this.metrics.recordRequest("BLOCK", latencyMs);
|
|
1989
|
+
throw new BlockIntelBlockedError(
|
|
1990
|
+
"DECISION_TOKEN_MISSING",
|
|
1991
|
+
result.decisionId ?? requestId,
|
|
1992
|
+
result.correlationId,
|
|
1993
|
+
requestId
|
|
1994
|
+
);
|
|
1995
|
+
}
|
|
1996
|
+
const nowSec = Math.floor(Date.now() / 1e3);
|
|
1997
|
+
if (result.expiresAt != null && result.expiresAt < nowSec - 5) {
|
|
1998
|
+
this.metrics.recordRequest("BLOCK", latencyMs);
|
|
1999
|
+
throw new BlockIntelBlockedError(
|
|
2000
|
+
"DECISION_TOKEN_EXPIRED",
|
|
2001
|
+
result.decisionId ?? requestId,
|
|
2002
|
+
result.correlationId,
|
|
2003
|
+
requestId
|
|
2004
|
+
);
|
|
2005
|
+
}
|
|
2006
|
+
const publicKeyPem = this.config.decisionTokenPublicKey;
|
|
2007
|
+
if (publicKeyPem && result.decisionToken) {
|
|
2008
|
+
const { decodeJwtUnsafe: decodeJwtUnsafe2, verifyDecisionTokenRs256: verifyDecisionTokenRs2562 } = await Promise.resolve().then(() => (init_decisionTokenVerify(), decisionTokenVerify_exports));
|
|
2009
|
+
const decoded = decodeJwtUnsafe2(result.decisionToken);
|
|
2010
|
+
if (decoded && (decoded.header.alg || "").toUpperCase() === "RS256") {
|
|
2011
|
+
const resolvedPem = publicKeyPem.startsWith("-----") ? publicKeyPem : Buffer.from(publicKeyPem, "base64").toString("utf8");
|
|
2012
|
+
const verified = verifyDecisionTokenRs2562(result.decisionToken, resolvedPem);
|
|
2013
|
+
if (verified === null) {
|
|
2014
|
+
this.metrics.recordRequest("BLOCK", latencyMs);
|
|
2015
|
+
throw new BlockIntelBlockedError(
|
|
2016
|
+
"DECISION_TOKEN_INVALID",
|
|
2017
|
+
result.decisionId ?? requestId,
|
|
2018
|
+
result.correlationId,
|
|
2019
|
+
requestId
|
|
2020
|
+
);
|
|
2021
|
+
}
|
|
2022
|
+
}
|
|
2023
|
+
}
|
|
2024
|
+
const signerId = signingContext?.signerId ?? req.signingContext?.signerId;
|
|
2025
|
+
const fromAddress = txIntent.fromAddress ?? txIntent.from;
|
|
2026
|
+
const binding = buildTxBindingObject(txIntent, signerId, void 0, void 0, fromAddress);
|
|
2027
|
+
const computedDigest = computeTxDigest(binding);
|
|
2028
|
+
if (computedDigest !== result.txDigest) {
|
|
2029
|
+
this.metrics.recordRequest("BLOCK", latencyMs);
|
|
2030
|
+
throw new BlockIntelBlockedError(
|
|
2031
|
+
"DECISION_TOKEN_DIGEST_MISMATCH",
|
|
2032
|
+
result.decisionId ?? requestId,
|
|
2033
|
+
result.correlationId,
|
|
2034
|
+
requestId
|
|
2035
|
+
);
|
|
2036
|
+
}
|
|
2037
|
+
}
|
|
1795
2038
|
if (result.decision === "BLOCK") {
|
|
1796
2039
|
if (requestMode === "SHADOW") {
|
|
1797
2040
|
console.warn("[GATE SHADOW MODE] Would have blocked transaction", {
|
|
@@ -1863,6 +2106,7 @@ var GateClient = class {
|
|
|
1863
2106
|
tenantId: this.config.tenantId,
|
|
1864
2107
|
mode: requestMode
|
|
1865
2108
|
});
|
|
2109
|
+
console.warn("[GATE SDK] X-BlockIntel-Degraded: true (reason: fail_open)");
|
|
1866
2110
|
this.metrics.recordRequest("FAIL_OPEN", Date.now() - startTime);
|
|
1867
2111
|
return {
|
|
1868
2112
|
decision: "ALLOW",
|
|
@@ -1894,6 +2138,10 @@ var GateClient = class {
|
|
|
1894
2138
|
}
|
|
1895
2139
|
throw error;
|
|
1896
2140
|
}
|
|
2141
|
+
if (error instanceof GateError && error.code === "RATE_LIMITED" /* RATE_LIMITED */) {
|
|
2142
|
+
console.warn("[GATE SDK] X-BlockIntel-Degraded: true (reason: 429)");
|
|
2143
|
+
throw error;
|
|
2144
|
+
}
|
|
1897
2145
|
if (error instanceof BlockIntelBlockedError || error instanceof BlockIntelStepUpRequiredError) {
|
|
1898
2146
|
throw error;
|
|
1899
2147
|
}
|
|
@@ -1906,6 +2154,7 @@ var GateClient = class {
|
|
|
1906
2154
|
*/
|
|
1907
2155
|
handleFailSafe(mode, error, requestId) {
|
|
1908
2156
|
if (mode === "ALLOW_ON_TIMEOUT") {
|
|
2157
|
+
console.warn("[GATE SDK] X-BlockIntel-Degraded: true (reason: fail_safe_allow)");
|
|
1909
2158
|
return {
|
|
1910
2159
|
decision: "ALLOW",
|
|
1911
2160
|
reasonCodes: ["FAIL_SAFE_ALLOW"],
|
|
@@ -1916,6 +2165,7 @@ var GateClient = class {
|
|
|
1916
2165
|
return null;
|
|
1917
2166
|
}
|
|
1918
2167
|
if (mode === "BLOCK_ON_ANOMALY") {
|
|
2168
|
+
console.warn("[GATE SDK] X-BlockIntel-Degraded: true (reason: fail_safe_allow)");
|
|
1919
2169
|
return {
|
|
1920
2170
|
decision: "ALLOW",
|
|
1921
2171
|
reasonCodes: ["FAIL_SAFE_ALLOW"],
|
|
@@ -2016,6 +2266,8 @@ exports.GateErrorCode = GateErrorCode;
|
|
|
2016
2266
|
exports.HeartbeatManager = HeartbeatManager;
|
|
2017
2267
|
exports.ProvenanceProvider = ProvenanceProvider;
|
|
2018
2268
|
exports.StepUpNotConfiguredError = StepUpNotConfiguredError;
|
|
2269
|
+
exports.buildTxBindingObject = buildTxBindingObject;
|
|
2270
|
+
exports.computeTxDigest = computeTxDigest;
|
|
2019
2271
|
exports.createGateClient = createGateClient;
|
|
2020
2272
|
exports.default = GateClient;
|
|
2021
2273
|
exports.wrapKmsClient = wrapKmsClient;
|