@astrasyncai/verification-gateway 4.0.0 → 4.1.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/README.md +106 -29
- package/dist/adapter-interface/interface.d.mts +2 -2
- package/dist/adapter-interface/interface.d.ts +2 -2
- package/dist/adapters/express.d.mts +2 -2
- package/dist/adapters/express.d.ts +2 -2
- package/dist/adapters/express.js +398 -15
- package/dist/adapters/express.js.map +1 -1
- package/dist/adapters/express.mjs +398 -15
- package/dist/adapters/express.mjs.map +1 -1
- package/dist/adapters/http-pdlss.d.mts +3 -3
- package/dist/adapters/http-pdlss.d.ts +3 -3
- package/dist/adapters/http-pdlss.js.map +1 -1
- package/dist/adapters/http-pdlss.mjs.map +1 -1
- package/dist/adapters/mcp.d.mts +56 -36
- package/dist/adapters/mcp.d.ts +56 -36
- package/dist/adapters/mcp.js +220 -3
- package/dist/adapters/mcp.js.map +1 -1
- package/dist/adapters/mcp.mjs +220 -3
- package/dist/adapters/mcp.mjs.map +1 -1
- package/dist/adapters/nextjs.d.mts +2 -2
- package/dist/adapters/nextjs.d.ts +2 -2
- package/dist/adapters/nextjs.js +433 -18
- package/dist/adapters/nextjs.js.map +1 -1
- package/dist/adapters/nextjs.mjs +433 -18
- package/dist/adapters/nextjs.mjs.map +1 -1
- package/dist/adapters/sdk.d.mts +2 -2
- package/dist/adapters/sdk.d.ts +2 -2
- package/dist/adapters/sdk.js +2 -2
- package/dist/adapters/sdk.js.map +1 -1
- package/dist/adapters/sdk.mjs +2 -2
- package/dist/adapters/sdk.mjs.map +1 -1
- package/dist/agent/index.d.mts +2 -2
- package/dist/agent/index.d.ts +2 -2
- package/dist/agent/index.js.map +1 -1
- package/dist/agent/index.mjs.map +1 -1
- package/dist/bin/astrasync-claude-hook.js +13 -13
- package/dist/bin/astrasync-codex-hook.js +13 -13
- package/dist/bin/astrasync-guard.js +13 -13
- package/dist/bin/astrasync.js +80 -26
- package/dist/browser/background.js +13 -13
- package/dist/browser/background.js.map +1 -1
- package/dist/browser/background.mjs +13 -13
- package/dist/browser/background.mjs.map +1 -1
- package/dist/browser/browser-adapter.d.mts +2 -2
- package/dist/browser/browser-adapter.d.ts +2 -2
- package/dist/claude-code/claude-code-adapter.d.mts +2 -2
- package/dist/claude-code/claude-code-adapter.d.ts +2 -2
- package/dist/cli/index.d.mts +2 -2
- package/dist/cli/index.d.ts +2 -2
- package/dist/codex/index.d.mts +3 -3
- package/dist/codex/index.d.ts +3 -3
- package/dist/codex/index.js +13 -13
- package/dist/codex/index.js.map +1 -1
- package/dist/codex/index.mjs +13 -13
- package/dist/codex/index.mjs.map +1 -1
- package/dist/cursor/cursor-adapter.d.mts +2 -2
- package/dist/cursor/cursor-adapter.d.ts +2 -2
- package/dist/cursor/extension.d.mts +2 -2
- package/dist/cursor/extension.d.ts +2 -2
- package/dist/cursor/extension.js +13 -13
- package/dist/cursor/extension.js.map +1 -1
- package/dist/cursor/extension.mjs +13 -13
- package/dist/cursor/extension.mjs.map +1 -1
- package/dist/edge-config.d.mts +22 -7
- package/dist/edge-config.d.ts +22 -7
- package/dist/edge-config.js.map +1 -1
- package/dist/edge-config.mjs.map +1 -1
- package/dist/edge-core/index.d.mts +425 -0
- package/dist/edge-core/index.d.ts +425 -0
- package/dist/edge-core/index.js +1482 -0
- package/dist/edge-core/index.js.map +1 -0
- package/dist/edge-core/index.mjs +1437 -0
- package/dist/edge-core/index.mjs.map +1 -0
- package/dist/{express-BZajRs4i.d.mts → express-BVd1_3FE.d.ts} +9 -7
- package/dist/{express-CjCUB1k7.d.ts → express-D_4hTn5Z.d.mts} +9 -7
- package/dist/gateway/gateway.d.mts +2 -2
- package/dist/gateway/gateway.d.ts +2 -2
- package/dist/gateway/gateway.js +13 -13
- package/dist/gateway/gateway.js.map +1 -1
- package/dist/gateway/gateway.mjs +13 -13
- package/dist/gateway/gateway.mjs.map +1 -1
- package/dist/git-trigger/git-hooks.d.mts +2 -2
- package/dist/git-trigger/git-hooks.d.ts +2 -2
- package/dist/{index-adgKhujR.d.ts → index-B0YHu_SP.d.ts} +30 -27
- package/dist/{index-B0cyMZDL.d.mts → index-BPEBlOsE.d.mts} +30 -27
- package/dist/{index-BRYteOqO.d.mts → index-DQb5-_1X.d.mts} +1 -1
- package/dist/{index-BZQdVqNw.d.ts → index-T1aBoUcc.d.ts} +1 -1
- package/dist/index.d.mts +11 -11
- package/dist/index.d.ts +11 -11
- package/dist/index.js +477 -265
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +474 -265
- package/dist/index.mjs.map +1 -1
- package/dist/local-evaluator/evaluator.d.mts +2 -2
- package/dist/local-evaluator/evaluator.d.ts +2 -2
- package/dist/metadata-capture.d.mts +63 -4
- package/dist/metadata-capture.d.ts +63 -4
- package/dist/metadata-capture.js +67 -0
- package/dist/metadata-capture.js.map +1 -1
- package/dist/metadata-capture.mjs +64 -0
- package/dist/metadata-capture.mjs.map +1 -1
- package/dist/{nextjs-DeUTnOBd.d.mts → nextjs-WyeVr2Kp.d.mts} +3 -3
- package/dist/{nextjs-D_iFf5k-.d.ts → nextjs-w7RTbP1P.d.ts} +3 -3
- package/dist/platform-signatures.d.mts +5 -6
- package/dist/platform-signatures.d.ts +5 -6
- package/dist/platform-signatures.js.map +1 -1
- package/dist/platform-signatures.mjs.map +1 -1
- package/dist/registration/index.d.mts +10 -11
- package/dist/registration/index.d.ts +10 -11
- package/dist/registration/index.js.map +1 -1
- package/dist/registration/index.mjs.map +1 -1
- package/dist/{sdk-BM3mwEAq.d.ts → sdk-CbTNIkAa.d.mts} +4 -4
- package/dist/{sdk-_il1Q41f.d.mts → sdk-QeX0Z8Ho.d.ts} +4 -4
- package/dist/transport/index.d.mts +2 -2
- package/dist/transport/index.d.ts +2 -2
- package/dist/transport/index.js.map +1 -1
- package/dist/transport/index.mjs.map +1 -1
- package/dist/{types-CHKCgDFC.d.ts → types-BLUx92FJ.d.ts} +1 -1
- package/dist/{types-DfnP7JiM.d.mts → types-DqfPU5Bl.d.mts} +1 -1
- package/dist/{types-BcDf9Kk0.d.mts → types-r850cOt0.d.mts} +106 -88
- package/dist/{types-fTQD448H.d.ts → types-sMxBT-nM.d.ts} +106 -88
- package/dist/ui/index.d.mts +11 -7
- package/dist/ui/index.d.ts +11 -7
- package/dist/ui/index.js +13 -9
- package/dist/ui/index.js.map +1 -1
- package/dist/ui/index.mjs +10 -8
- package/dist/ui/index.mjs.map +1 -1
- package/dist/verify.d.mts +8 -7
- package/dist/verify.d.ts +8 -7
- package/dist/verify.js +1 -1
- package/dist/verify.js.map +1 -1
- package/dist/verify.mjs +1 -1
- package/dist/verify.mjs.map +1 -1
- package/package.json +8 -2
package/dist/index.js
CHANGED
|
@@ -36,6 +36,7 @@ __export(src_exports, {
|
|
|
36
36
|
AstraSync: () => AstraSync,
|
|
37
37
|
AstraSyncError: () => AstraSyncError,
|
|
38
38
|
AuthenticationError: () => AuthenticationError,
|
|
39
|
+
CAPTURE_SCHEMA_VERSION: () => CAPTURE_SCHEMA_VERSION,
|
|
39
40
|
ChallengeHandler: () => ChallengeHandler,
|
|
40
41
|
DEFAULT_EDGE_CONFIG: () => DEFAULT_EDGE_CONFIG,
|
|
41
42
|
DEFAULT_TRUST_THRESHOLDS: () => DEFAULT_TRUST_THRESHOLDS,
|
|
@@ -54,9 +55,11 @@ __export(src_exports, {
|
|
|
54
55
|
authorizeSettlement: () => authorizeSettlement,
|
|
55
56
|
awaitStepUpApproval: () => awaitStepUpApproval,
|
|
56
57
|
buildGuidance: () => buildGuidance,
|
|
58
|
+
buildSdkObservedMetadata: () => buildSdkObservedMetadata,
|
|
57
59
|
clearCache: () => clearCache,
|
|
58
60
|
createMcpMiddleware: () => createMcpMiddleware,
|
|
59
61
|
degradeToObserve: () => degradeToObserve,
|
|
62
|
+
deriveConnectionFromHeaders: () => deriveConnectionFromHeaders,
|
|
60
63
|
detectPlatformFingerprint: () => detectPlatformFingerprint,
|
|
61
64
|
determineAccessLevel: () => determineAccessLevel,
|
|
62
65
|
express: () => express_exports,
|
|
@@ -214,7 +217,7 @@ function getCapabilities(accessLevel) {
|
|
|
214
217
|
}
|
|
215
218
|
|
|
216
219
|
// src/version.ts
|
|
217
|
-
var SDK_VERSION = "4.
|
|
220
|
+
var SDK_VERSION = "4.1.0";
|
|
218
221
|
|
|
219
222
|
// src/well-known.ts
|
|
220
223
|
var CACHE_TTL_MS = 60 * 60 * 1e3;
|
|
@@ -1212,6 +1215,7 @@ function performCounterpartyPreCheck(routeConfig, astraCreds, purpose) {
|
|
|
1212
1215
|
}
|
|
1213
1216
|
|
|
1214
1217
|
// src/metadata-capture.ts
|
|
1218
|
+
var CAPTURE_SCHEMA_VERSION = 1;
|
|
1215
1219
|
var SECRET_HEADER_NAMES = /* @__PURE__ */ new Set([
|
|
1216
1220
|
"cookie",
|
|
1217
1221
|
"set-cookie",
|
|
@@ -1356,6 +1360,373 @@ function extractPlatformHeaders(sanitized) {
|
|
|
1356
1360
|
}
|
|
1357
1361
|
return out;
|
|
1358
1362
|
}
|
|
1363
|
+
var CONNECTION_HEADER_SOURCES = [
|
|
1364
|
+
["ip", ["cf-connecting-ip", "fastly-client-ip", "true-client-ip", "x-real-ip"]],
|
|
1365
|
+
[
|
|
1366
|
+
"country",
|
|
1367
|
+
["cf-ipcountry", "x-vercel-ip-country", "cloudfront-viewer-country", "fastly-geo-country"]
|
|
1368
|
+
],
|
|
1369
|
+
["region", ["x-vercel-ip-country-region", "cloudfront-viewer-country-region"]],
|
|
1370
|
+
["city", ["x-vercel-ip-city", "cloudfront-viewer-city"]],
|
|
1371
|
+
["asn", ["cloudfront-viewer-asn"]],
|
|
1372
|
+
["tlsVersion", ["cloudfront-viewer-tls"]],
|
|
1373
|
+
["httpVersion", ["cloudfront-viewer-http-version"]],
|
|
1374
|
+
// TLS fingerprints can only be computed where TLS terminates. When a CDN
|
|
1375
|
+
// terminates TLS in front of the merchant, its fingerprint headers ARE the
|
|
1376
|
+
// connection-layer truth — normalising them here is the permanent design.
|
|
1377
|
+
["tlsFingerprint", ["cf-ja3-hash"]],
|
|
1378
|
+
["ja4", ["cf-ja4"]]
|
|
1379
|
+
];
|
|
1380
|
+
function deriveConnectionFromHeaders(headers) {
|
|
1381
|
+
if (!headers) return void 0;
|
|
1382
|
+
const lower = {};
|
|
1383
|
+
for (const name of Object.keys(headers)) {
|
|
1384
|
+
const value = headers[name];
|
|
1385
|
+
if (typeof value === "string" && value.length > 0) lower[name.toLowerCase()] = value;
|
|
1386
|
+
}
|
|
1387
|
+
const connection = {};
|
|
1388
|
+
for (const [key, sources] of CONNECTION_HEADER_SOURCES) {
|
|
1389
|
+
for (const source of sources) {
|
|
1390
|
+
const value = lower[source]?.trim();
|
|
1391
|
+
if (value) {
|
|
1392
|
+
connection[key] = value;
|
|
1393
|
+
break;
|
|
1394
|
+
}
|
|
1395
|
+
}
|
|
1396
|
+
}
|
|
1397
|
+
if (!connection.ip) {
|
|
1398
|
+
const xff = lower["x-forwarded-for"];
|
|
1399
|
+
const client = xff?.split(",")[0]?.trim();
|
|
1400
|
+
if (client) connection.ip = client;
|
|
1401
|
+
}
|
|
1402
|
+
return Object.keys(connection).length > 0 ? connection : void 0;
|
|
1403
|
+
}
|
|
1404
|
+
function buildSdkObservedMetadata(rawHeaders) {
|
|
1405
|
+
const { headers, apiKeyFormat, platformHeaders } = sanitizeHeaders(rawHeaders);
|
|
1406
|
+
const flat = {};
|
|
1407
|
+
if (rawHeaders) {
|
|
1408
|
+
for (const name of Object.keys(rawHeaders)) {
|
|
1409
|
+
const value = rawHeaders[name];
|
|
1410
|
+
if (value === void 0) continue;
|
|
1411
|
+
flat[name.toLowerCase()] = Array.isArray(value) ? value.join(", ") : String(value);
|
|
1412
|
+
}
|
|
1413
|
+
}
|
|
1414
|
+
const connection = deriveConnectionFromHeaders(flat);
|
|
1415
|
+
return {
|
|
1416
|
+
headers,
|
|
1417
|
+
...apiKeyFormat && { apiKeyFormat },
|
|
1418
|
+
...platformHeaders && { platformHeaders },
|
|
1419
|
+
...connection && { connection },
|
|
1420
|
+
schemaVersion: CAPTURE_SCHEMA_VERSION
|
|
1421
|
+
};
|
|
1422
|
+
}
|
|
1423
|
+
|
|
1424
|
+
// src/edge-config.ts
|
|
1425
|
+
var DEFAULT_EDGE_CONFIG = Object.freeze({
|
|
1426
|
+
version: 1,
|
|
1427
|
+
mode: "observe",
|
|
1428
|
+
depth: "classify",
|
|
1429
|
+
pathRules: [],
|
|
1430
|
+
sampling: Object.freeze({ anonymousBeaconRate: 0.1 }),
|
|
1431
|
+
failurePosture: "open"
|
|
1432
|
+
});
|
|
1433
|
+
var EDGE_MODES = ["observe", "enforce"];
|
|
1434
|
+
var EDGE_DEPTHS = ["classify", "authenticate", "authorize"];
|
|
1435
|
+
function isEdgeConfig(value) {
|
|
1436
|
+
if (typeof value !== "object" || value === null) return false;
|
|
1437
|
+
const v = value;
|
|
1438
|
+
if (v.version !== 1) return false;
|
|
1439
|
+
if (!EDGE_MODES.includes(v.mode)) return false;
|
|
1440
|
+
if (!EDGE_DEPTHS.includes(v.depth)) return false;
|
|
1441
|
+
if (!Array.isArray(v.pathRules)) return false;
|
|
1442
|
+
for (const rule of v.pathRules) {
|
|
1443
|
+
if (typeof rule !== "object" || rule === null) return false;
|
|
1444
|
+
const r = rule;
|
|
1445
|
+
if (typeof r.pattern !== "string" || r.pattern.length === 0) return false;
|
|
1446
|
+
if (r.mode !== void 0 && !EDGE_MODES.includes(r.mode)) return false;
|
|
1447
|
+
if (r.depth !== void 0 && !EDGE_DEPTHS.includes(r.depth)) return false;
|
|
1448
|
+
}
|
|
1449
|
+
const sampling = v.sampling;
|
|
1450
|
+
if (typeof sampling !== "object" || sampling === null || typeof sampling.anonymousBeaconRate !== "number" || sampling.anonymousBeaconRate < 0 || sampling.anonymousBeaconRate > 1) {
|
|
1451
|
+
return false;
|
|
1452
|
+
}
|
|
1453
|
+
return v.failurePosture === "open";
|
|
1454
|
+
}
|
|
1455
|
+
async function fetchEdgeConfig(config, counterpartyId, opts) {
|
|
1456
|
+
if (!counterpartyId) return null;
|
|
1457
|
+
const headers = { Accept: "application/json" };
|
|
1458
|
+
if (config.apiKey) {
|
|
1459
|
+
headers["Authorization"] = `Bearer ${config.apiKey}`;
|
|
1460
|
+
headers["X-API-Key"] = config.apiKey;
|
|
1461
|
+
}
|
|
1462
|
+
if (opts?.etag) headers["If-None-Match"] = opts.etag;
|
|
1463
|
+
try {
|
|
1464
|
+
const response = await fetch(
|
|
1465
|
+
`${config.apiBaseUrl}/endpoints/${encodeURIComponent(counterpartyId)}/edge-config`,
|
|
1466
|
+
{ method: "GET", headers, signal: AbortSignal.timeout(opts?.timeoutMs ?? 5e3) }
|
|
1467
|
+
);
|
|
1468
|
+
if (response.status === 304) return { notModified: true };
|
|
1469
|
+
if (!response.ok) return null;
|
|
1470
|
+
const body = await response.json();
|
|
1471
|
+
const edgeConfig = body.data?.edgeConfig;
|
|
1472
|
+
if (!isEdgeConfig(edgeConfig)) return null;
|
|
1473
|
+
return { edgeConfig, etag: response.headers.get("etag") ?? void 0 };
|
|
1474
|
+
} catch {
|
|
1475
|
+
return null;
|
|
1476
|
+
}
|
|
1477
|
+
}
|
|
1478
|
+
var DEFAULT_TTL_MS = 60 * 1e3;
|
|
1479
|
+
var DEFAULT_MAX_STALE_MS = 24 * 60 * 60 * 1e3;
|
|
1480
|
+
var cache2 = /* @__PURE__ */ new Map();
|
|
1481
|
+
var inflight2 = /* @__PURE__ */ new Map();
|
|
1482
|
+
function cacheKey(apiBaseUrl, counterpartyId) {
|
|
1483
|
+
return `${apiBaseUrl}|${counterpartyId}`;
|
|
1484
|
+
}
|
|
1485
|
+
function degradeToObserve(config) {
|
|
1486
|
+
if (config.mode !== "enforce" && !config.pathRules.some((r) => r.mode === "enforce")) {
|
|
1487
|
+
return config;
|
|
1488
|
+
}
|
|
1489
|
+
return {
|
|
1490
|
+
...config,
|
|
1491
|
+
mode: "observe",
|
|
1492
|
+
pathRules: config.pathRules.map((r) => r.mode === "enforce" ? { ...r, mode: "observe" } : r)
|
|
1493
|
+
};
|
|
1494
|
+
}
|
|
1495
|
+
async function revalidate(config, counterpartyId) {
|
|
1496
|
+
const key = cacheKey(config.apiBaseUrl, counterpartyId);
|
|
1497
|
+
const existing = inflight2.get(key);
|
|
1498
|
+
if (existing) return existing;
|
|
1499
|
+
const promise = fetchEdgeConfig(config, counterpartyId, { etag: cache2.get(key)?.etag }).then((result) => {
|
|
1500
|
+
if (result === null) return;
|
|
1501
|
+
const now = Date.now();
|
|
1502
|
+
if ("notModified" in result) {
|
|
1503
|
+
const entry = cache2.get(key);
|
|
1504
|
+
if (entry) entry.lastSuccessAt = now;
|
|
1505
|
+
return;
|
|
1506
|
+
}
|
|
1507
|
+
cache2.set(key, { config: result.edgeConfig, etag: result.etag, lastSuccessAt: now });
|
|
1508
|
+
}).finally(() => {
|
|
1509
|
+
inflight2.delete(key);
|
|
1510
|
+
});
|
|
1511
|
+
inflight2.set(key, promise);
|
|
1512
|
+
return promise;
|
|
1513
|
+
}
|
|
1514
|
+
async function getEdgeConfig(config, counterpartyId, opts) {
|
|
1515
|
+
const ttlMs = opts?.ttlMs ?? DEFAULT_TTL_MS;
|
|
1516
|
+
const maxStaleMs = opts?.maxStaleMs ?? DEFAULT_MAX_STALE_MS;
|
|
1517
|
+
const key = cacheKey(config.apiBaseUrl, counterpartyId);
|
|
1518
|
+
const entry = cache2.get(key);
|
|
1519
|
+
if (entry) {
|
|
1520
|
+
const age = Date.now() - entry.lastSuccessAt;
|
|
1521
|
+
if (age > ttlMs) {
|
|
1522
|
+
revalidate(config, counterpartyId).catch(() => {
|
|
1523
|
+
});
|
|
1524
|
+
}
|
|
1525
|
+
return age > maxStaleMs ? degradeToObserve(entry.config) : entry.config;
|
|
1526
|
+
}
|
|
1527
|
+
await revalidate(config, counterpartyId).catch(() => {
|
|
1528
|
+
});
|
|
1529
|
+
return cache2.get(key)?.config ?? DEFAULT_EDGE_CONFIG;
|
|
1530
|
+
}
|
|
1531
|
+
function matchEdgePathRule(rules, path) {
|
|
1532
|
+
for (const rule of rules) {
|
|
1533
|
+
if (globToRegExp(rule.pattern).test(path)) return rule;
|
|
1534
|
+
}
|
|
1535
|
+
return void 0;
|
|
1536
|
+
}
|
|
1537
|
+
function globToRegExp(pattern) {
|
|
1538
|
+
const escaped = pattern.replace(/[.+?^${}()|[\]\\]/g, "\\$&").replace(/\*/g, ".*");
|
|
1539
|
+
return new RegExp(`^${escaped}$`, "i");
|
|
1540
|
+
}
|
|
1541
|
+
function _resetEdgeConfigCache() {
|
|
1542
|
+
cache2.clear();
|
|
1543
|
+
inflight2.clear();
|
|
1544
|
+
}
|
|
1545
|
+
|
|
1546
|
+
// src/platform-signatures.ts
|
|
1547
|
+
var PLATFORM_AGENT_SIGNATURES = [
|
|
1548
|
+
{
|
|
1549
|
+
vendor: "claude",
|
|
1550
|
+
displayName: "Anthropic Claude",
|
|
1551
|
+
uaPatterns: [/claude/i, /anthropic/i],
|
|
1552
|
+
agentCardPatterns: [/anthropic\.com/i, /claude\.ai/i],
|
|
1553
|
+
apiKeyFormatPatterns: [/^sk-ant/i],
|
|
1554
|
+
headerPatterns: [/^anthropic-version/i, /^anthropic-beta/i, /^x-anthropic-/i]
|
|
1555
|
+
},
|
|
1556
|
+
{
|
|
1557
|
+
vendor: "chatgpt",
|
|
1558
|
+
displayName: "OpenAI ChatGPT",
|
|
1559
|
+
uaPatterns: [/chatgpt/i, /openai/i, /gpt-?\d/i],
|
|
1560
|
+
agentCardPatterns: [/openai\.com/i, /chatgpt\.com/i],
|
|
1561
|
+
apiKeyFormatPatterns: [/^sk-proj/i, /^sk-svcacct/i],
|
|
1562
|
+
headerPatterns: [/^openai-organization/i, /^openai-project/i, /^openai-version/i]
|
|
1563
|
+
},
|
|
1564
|
+
{
|
|
1565
|
+
vendor: "gemini",
|
|
1566
|
+
displayName: "Google Gemini",
|
|
1567
|
+
uaPatterns: [/gemini/i, /google-gemini/i, /bard/i],
|
|
1568
|
+
agentCardPatterns: [/gemini\.google\.com/i, /ai\.google\.dev/i],
|
|
1569
|
+
apiKeyFormatPatterns: [/^aiza/i],
|
|
1570
|
+
headerPatterns: [/^x-goog-user-project/i, /^x-goog-api-client/i]
|
|
1571
|
+
},
|
|
1572
|
+
{
|
|
1573
|
+
vendor: "cursor",
|
|
1574
|
+
displayName: "Cursor",
|
|
1575
|
+
uaPatterns: [/cursor/i],
|
|
1576
|
+
agentCardPatterns: [/cursor\.sh/i, /cursor\.com/i]
|
|
1577
|
+
},
|
|
1578
|
+
{
|
|
1579
|
+
vendor: "goose",
|
|
1580
|
+
displayName: "Block Goose",
|
|
1581
|
+
uaPatterns: [/goose/i, /block-goose/i],
|
|
1582
|
+
agentCardPatterns: [/block\.xyz\/goose/i, /goose\.tools/i]
|
|
1583
|
+
},
|
|
1584
|
+
{
|
|
1585
|
+
vendor: "perplexity",
|
|
1586
|
+
displayName: "Perplexity",
|
|
1587
|
+
uaPatterns: [/perplexity/i],
|
|
1588
|
+
agentCardPatterns: [/perplexity\.ai/i],
|
|
1589
|
+
apiKeyFormatPatterns: [/^pplx-/i]
|
|
1590
|
+
}
|
|
1591
|
+
];
|
|
1592
|
+
function matchPlatformSignature(signatures, input) {
|
|
1593
|
+
const ua = input.userAgent ?? "";
|
|
1594
|
+
const cardUrl = input.agentCardUrl ?? "";
|
|
1595
|
+
const apiKeyFormat = input.apiKeyFormat ?? "";
|
|
1596
|
+
const headerLines = [];
|
|
1597
|
+
if (input.platformHeaders) {
|
|
1598
|
+
for (const [name, value] of Object.entries(input.platformHeaders)) {
|
|
1599
|
+
headerLines.push(name, `${name}: ${value}`);
|
|
1600
|
+
}
|
|
1601
|
+
}
|
|
1602
|
+
for (const sig of signatures) {
|
|
1603
|
+
const uaMatch = sig.uaPatterns?.some((p) => p.test(ua));
|
|
1604
|
+
const cardMatch = sig.agentCardPatterns?.some((p) => p.test(cardUrl));
|
|
1605
|
+
const keyMatch = apiKeyFormat.length > 0 && sig.apiKeyFormatPatterns?.some((p) => p.test(apiKeyFormat));
|
|
1606
|
+
const headerMatch = headerLines.length > 0 && sig.headerPatterns?.some((p) => headerLines.some((line) => p.test(line)));
|
|
1607
|
+
if (uaMatch || cardMatch || keyMatch || headerMatch) {
|
|
1608
|
+
const uaBase = ua.split(/[\s/]/)[0]?.toLowerCase() ?? "";
|
|
1609
|
+
const cardHost = (() => {
|
|
1610
|
+
try {
|
|
1611
|
+
return cardUrl ? new URL(cardUrl).host : "";
|
|
1612
|
+
} catch {
|
|
1613
|
+
return "";
|
|
1614
|
+
}
|
|
1615
|
+
})();
|
|
1616
|
+
const keyBasis = uaBase || cardHost || apiKeyFormat || "unknown";
|
|
1617
|
+
return {
|
|
1618
|
+
vendor: sig.vendor,
|
|
1619
|
+
fingerprintKey: `${sig.vendor}:${keyBasis}`,
|
|
1620
|
+
displayName: sig.displayName
|
|
1621
|
+
};
|
|
1622
|
+
}
|
|
1623
|
+
}
|
|
1624
|
+
return void 0;
|
|
1625
|
+
}
|
|
1626
|
+
function detectPlatformFingerprint(input) {
|
|
1627
|
+
return matchPlatformSignature(PLATFORM_AGENT_SIGNATURES, input);
|
|
1628
|
+
}
|
|
1629
|
+
|
|
1630
|
+
// src/edge-core/classify.ts
|
|
1631
|
+
var STATIC_EXTENSIONS = /\.(css|js|mjs|map|png|jpe?g|gif|webp|avif|svg|ico|woff2?|ttf|otf|eot|mp4|webm|pdf|txt|xml)$/i;
|
|
1632
|
+
var BOT_UA_PATTERN = /curl|wget|python-requests|python-urllib|node-fetch|axios|got|okhttp|go-http-client|libwww|httpie|java\/|ruby|php|scrapy|headless|phantomjs|selenium|playwright|puppeteer|bot|crawler|spider|slurp/i;
|
|
1633
|
+
var BROWSER_UA_PATTERN = /mozilla\/\d/i;
|
|
1634
|
+
var _patterns = { STATIC_EXTENSIONS, BOT_UA_PATTERN, BROWSER_UA_PATTERN };
|
|
1635
|
+
|
|
1636
|
+
// src/edge-core/events.ts
|
|
1637
|
+
function sampled(rate, random = Math.random) {
|
|
1638
|
+
if (rate <= 0) return false;
|
|
1639
|
+
if (rate >= 1) return true;
|
|
1640
|
+
return random() < rate;
|
|
1641
|
+
}
|
|
1642
|
+
|
|
1643
|
+
// src/adapters/anonymous-beacon.ts
|
|
1644
|
+
function readHeader(raw, name) {
|
|
1645
|
+
const value = raw[name];
|
|
1646
|
+
if (typeof value === "string") return value;
|
|
1647
|
+
if (Array.isArray(value)) return value[0];
|
|
1648
|
+
return void 0;
|
|
1649
|
+
}
|
|
1650
|
+
function classifyPassThroughTraffic(path, rawHeaders) {
|
|
1651
|
+
if (_patterns.STATIC_EXTENSIONS.test(path)) return { kind: "never" };
|
|
1652
|
+
const credentials = extractCredentials(rawHeaders, {});
|
|
1653
|
+
if (credentials.astraId || credentials.apiKey || credentials.jwt) {
|
|
1654
|
+
return { kind: "never" };
|
|
1655
|
+
}
|
|
1656
|
+
const userAgent = readHeader(rawHeaders, "user-agent") ?? "";
|
|
1657
|
+
const { apiKeyFormat, platformHeaders } = sanitizeHeaders(rawHeaders);
|
|
1658
|
+
const fingerprint = detectPlatformFingerprint({ userAgent, apiKeyFormat, platformHeaders });
|
|
1659
|
+
if (fingerprint) {
|
|
1660
|
+
return {
|
|
1661
|
+
kind: "platform",
|
|
1662
|
+
protocol: "platform-ua",
|
|
1663
|
+
evidence: { vendor: fingerprint.vendor, userAgent: userAgent || "(none)" }
|
|
1664
|
+
};
|
|
1665
|
+
}
|
|
1666
|
+
if (!userAgent || _patterns.BOT_UA_PATTERN.test(userAgent) || !_patterns.BROWSER_UA_PATTERN.test(userAgent)) {
|
|
1667
|
+
return {
|
|
1668
|
+
kind: "anonymous-bot",
|
|
1669
|
+
protocol: "ua-heuristic",
|
|
1670
|
+
evidence: { userAgent: userAgent || "(none)" }
|
|
1671
|
+
};
|
|
1672
|
+
}
|
|
1673
|
+
if (!readHeader(rawHeaders, "sec-fetch-mode") && !readHeader(rawHeaders, "accept-language")) {
|
|
1674
|
+
return {
|
|
1675
|
+
kind: "anonymous-bot",
|
|
1676
|
+
protocol: "ua-heuristic",
|
|
1677
|
+
evidence: { userAgent, spoofedBrowser: true }
|
|
1678
|
+
};
|
|
1679
|
+
}
|
|
1680
|
+
return { kind: "never" };
|
|
1681
|
+
}
|
|
1682
|
+
function createAnonymousBeacon(config, options) {
|
|
1683
|
+
const counterpartyId = config.counterpartyId;
|
|
1684
|
+
if (!counterpartyId) return () => {
|
|
1685
|
+
};
|
|
1686
|
+
const random = options?.random ?? Math.random;
|
|
1687
|
+
let edgeConfig;
|
|
1688
|
+
let refreshing = false;
|
|
1689
|
+
const refreshConfig = () => {
|
|
1690
|
+
if (refreshing) return;
|
|
1691
|
+
refreshing = true;
|
|
1692
|
+
getEdgeConfig(config, counterpartyId).then((cfg) => {
|
|
1693
|
+
edgeConfig = cfg;
|
|
1694
|
+
}).catch(() => {
|
|
1695
|
+
}).finally(() => {
|
|
1696
|
+
refreshing = false;
|
|
1697
|
+
});
|
|
1698
|
+
};
|
|
1699
|
+
refreshConfig();
|
|
1700
|
+
return (input) => {
|
|
1701
|
+
try {
|
|
1702
|
+
refreshConfig();
|
|
1703
|
+
const cfg = edgeConfig;
|
|
1704
|
+
if (!cfg) return;
|
|
1705
|
+
const traffic = classifyPassThroughTraffic(input.requestPath, input.rawHeaders);
|
|
1706
|
+
if (traffic.kind === "never") return;
|
|
1707
|
+
if (traffic.kind === "anonymous-bot" && !sampled(cfg.sampling.anonymousBeaconRate, random)) {
|
|
1708
|
+
return;
|
|
1709
|
+
}
|
|
1710
|
+
const userAgent = readHeader(input.rawHeaders, "user-agent");
|
|
1711
|
+
const xff = input.rawHeaders["x-forwarded-for"];
|
|
1712
|
+
const xffStr = Array.isArray(xff) ? xff.join(", ") : xff;
|
|
1713
|
+
const sourceIp = input.sourceIp ?? xffStr?.split(",")[0]?.trim();
|
|
1714
|
+
reportUnregisteredAttempt(config, {
|
|
1715
|
+
...input.counterpartyUrl && { counterpartyUrl: input.counterpartyUrl },
|
|
1716
|
+
counterpartyType: options?.counterpartyType ?? config.counterpartyType ?? "api",
|
|
1717
|
+
...sourceIp && { sourceIp },
|
|
1718
|
+
...userAgent && { userAgent },
|
|
1719
|
+
requestPath: input.requestPath,
|
|
1720
|
+
requestMethod: input.requestMethod,
|
|
1721
|
+
...traffic.protocol && { protocol: traffic.protocol },
|
|
1722
|
+
...traffic.evidence && { evidence: traffic.evidence },
|
|
1723
|
+
observedMetadata: buildSdkObservedMetadata(input.rawHeaders)
|
|
1724
|
+
}).catch(() => {
|
|
1725
|
+
});
|
|
1726
|
+
} catch {
|
|
1727
|
+
}
|
|
1728
|
+
};
|
|
1729
|
+
}
|
|
1359
1730
|
|
|
1360
1731
|
// src/adapters/express.ts
|
|
1361
1732
|
function defaultExtractCredentials(req) {
|
|
@@ -1367,7 +1738,7 @@ function defaultExtractCredentials(req) {
|
|
|
1367
1738
|
function extractAstraSyncCredentials(req) {
|
|
1368
1739
|
return extractHttpCredentials(req.headers);
|
|
1369
1740
|
}
|
|
1370
|
-
function
|
|
1741
|
+
function headerValue2(value) {
|
|
1371
1742
|
if (typeof value === "string") return value;
|
|
1372
1743
|
if (Array.isArray(value)) return value[0];
|
|
1373
1744
|
return void 0;
|
|
@@ -1375,9 +1746,9 @@ function headerValue(value) {
|
|
|
1375
1746
|
function resolveRequestPdlss(req, routeConfig, customExtractPurpose, customExtractAction) {
|
|
1376
1747
|
return resolveHttpPdlss({
|
|
1377
1748
|
method: req.method,
|
|
1378
|
-
astraPurpose:
|
|
1379
|
-
astraAction:
|
|
1380
|
-
legacyPurpose:
|
|
1749
|
+
astraPurpose: headerValue2(req.headers["x-astra-purpose"]),
|
|
1750
|
+
astraAction: headerValue2(req.headers["x-astra-action"]),
|
|
1751
|
+
legacyPurpose: headerValue2(req.headers["x-purpose"] ?? req.headers["X-Purpose"]),
|
|
1381
1752
|
queryPurpose: typeof req.query.purpose === "string" ? req.query.purpose : void 0,
|
|
1382
1753
|
routePurpose: routeConfig?.purpose,
|
|
1383
1754
|
routeAction: routeConfig?.action,
|
|
@@ -1460,6 +1831,11 @@ function defaultOnDenied(result, _req, res) {
|
|
|
1460
1831
|
}
|
|
1461
1832
|
var DEFAULT_ROUTES_REFRESH_MS = 5 * 60 * 1e3;
|
|
1462
1833
|
function createMiddleware(options) {
|
|
1834
|
+
if ("routes" in options) {
|
|
1835
|
+
console.warn(
|
|
1836
|
+
"[VerificationGateway] `routes` is dashboard-managed since v2.9.7; this option is ignored \u2014 configure route policy in your AstraSync dashboard."
|
|
1837
|
+
);
|
|
1838
|
+
}
|
|
1463
1839
|
const {
|
|
1464
1840
|
extractCredentials: customExtractCredentials,
|
|
1465
1841
|
extractPurpose: customExtractPurpose,
|
|
@@ -1471,12 +1847,25 @@ function createMiddleware(options) {
|
|
|
1471
1847
|
routesRefreshMs = DEFAULT_ROUTES_REFRESH_MS,
|
|
1472
1848
|
failOnError = "open",
|
|
1473
1849
|
caseInsensitiveRouteMatch = false,
|
|
1850
|
+
anonymousBeacon = true,
|
|
1474
1851
|
...config
|
|
1475
1852
|
} = options;
|
|
1476
1853
|
if (config.apiBaseUrl) {
|
|
1477
1854
|
prefetchWellKnown(config.apiBaseUrl).catch(() => {
|
|
1478
1855
|
});
|
|
1479
1856
|
}
|
|
1857
|
+
const emitAnonymousBeacon = anonymousBeacon ? createAnonymousBeacon(config, { counterpartyType: config.counterpartyType ?? "api" }) : void 0;
|
|
1858
|
+
const beaconPassThrough = emitAnonymousBeacon ? (req) => {
|
|
1859
|
+
const xff = req.headers["x-forwarded-for"];
|
|
1860
|
+
const xffStr = Array.isArray(xff) ? xff.join(", ") : xff;
|
|
1861
|
+
emitAnonymousBeacon({
|
|
1862
|
+
requestPath: req.path,
|
|
1863
|
+
requestMethod: req.method,
|
|
1864
|
+
counterpartyUrl: config.counterpartyUrl || `${req.protocol}://${req.get("host")}`,
|
|
1865
|
+
sourceIp: req.ip ?? (xffStr ? xffStr.split(",")[0].trim() : void 0),
|
|
1866
|
+
rawHeaders: req.headers
|
|
1867
|
+
});
|
|
1868
|
+
} : void 0;
|
|
1480
1869
|
let cachedRoutes = [];
|
|
1481
1870
|
let lastFetchAt = 0;
|
|
1482
1871
|
let refreshing = null;
|
|
@@ -1537,6 +1926,7 @@ function createMiddleware(options) {
|
|
|
1537
1926
|
cachedRoutes.length === 0 ? "no-policy" : "no-match"
|
|
1538
1927
|
);
|
|
1539
1928
|
}
|
|
1929
|
+
beaconPassThrough?.(req);
|
|
1540
1930
|
return next();
|
|
1541
1931
|
}
|
|
1542
1932
|
const wellKnownUrls = config.apiBaseUrl ? await getWellKnownUrls(config.apiBaseUrl).catch(() => void 0) : void 0;
|
|
@@ -1547,6 +1937,7 @@ function createMiddleware(options) {
|
|
|
1547
1937
|
res.setHeader("X-Astra-Gateway-Mode", "unenforced");
|
|
1548
1938
|
res.setHeader("X-Astra-Gateway-Reason", "route-none");
|
|
1549
1939
|
}
|
|
1940
|
+
beaconPassThrough?.(req);
|
|
1550
1941
|
return next();
|
|
1551
1942
|
}
|
|
1552
1943
|
const pdlssPair = resolveRequestPdlss(
|
|
@@ -1639,16 +2030,10 @@ function createMiddleware(options) {
|
|
|
1639
2030
|
forwardedFor: forwardedForStr,
|
|
1640
2031
|
agentCardUrl,
|
|
1641
2032
|
// Workstream D — capture EVERY inbound header (SDK-only merchants
|
|
1642
|
-
// have no edge to do it upstream)
|
|
1643
|
-
// stripped; out of the verify
|
|
1644
|
-
|
|
1645
|
-
|
|
1646
|
-
return {
|
|
1647
|
-
headers,
|
|
1648
|
-
...apiKeyFormat && { apiKeyFormat },
|
|
1649
|
-
...platformHeaders && { platformHeaders }
|
|
1650
|
-
};
|
|
1651
|
-
})()
|
|
2033
|
+
// have no edge to do it upstream) plus the CDN-derived connection
|
|
2034
|
+
// block. Local string work, secrets stripped; out of the verify
|
|
2035
|
+
// cache key so it doesn't defeat caching.
|
|
2036
|
+
observedMetadata: buildSdkObservedMetadata(req.headers)
|
|
1652
2037
|
}
|
|
1653
2038
|
};
|
|
1654
2039
|
let result = await verify(config, verificationRequest);
|
|
@@ -1842,7 +2227,7 @@ function resolveNextPdlss(request, routeConfig) {
|
|
|
1842
2227
|
routeAction: routeConfig?.action
|
|
1843
2228
|
});
|
|
1844
2229
|
}
|
|
1845
|
-
function
|
|
2230
|
+
function generateInterstitialHtml(result, options) {
|
|
1846
2231
|
const title = escapeHtml(options.commerceShield?.title || "AstraSync Agent Verification");
|
|
1847
2232
|
const message = escapeHtml(
|
|
1848
2233
|
options.commerceShield?.message || result.guidance?.message || "This site verifies AI agents before granting access. We noticed you're visiting without AstraSync credentials."
|
|
@@ -1998,13 +2383,31 @@ function generateCommerceShieldHtml(result, options) {
|
|
|
1998
2383
|
}
|
|
1999
2384
|
var DEFAULT_ROUTES_REFRESH_MS2 = 5 * 60 * 1e3;
|
|
2000
2385
|
function createMiddleware2(options) {
|
|
2386
|
+
if ("routes" in options) {
|
|
2387
|
+
console.warn(
|
|
2388
|
+
"[VerificationGateway/Next.js] `routes` is dashboard-managed since v2.9.7; this option is ignored \u2014 configure route policy in your AstraSync dashboard."
|
|
2389
|
+
);
|
|
2390
|
+
}
|
|
2001
2391
|
const {
|
|
2002
2392
|
skipPaths = [],
|
|
2003
|
-
|
|
2393
|
+
showInterstitial,
|
|
2394
|
+
showCommerceShield,
|
|
2004
2395
|
enableRuntimeChallenge = true,
|
|
2005
2396
|
routesRefreshMs = DEFAULT_ROUTES_REFRESH_MS2,
|
|
2397
|
+
anonymousBeacon = true,
|
|
2006
2398
|
...config
|
|
2007
2399
|
} = options;
|
|
2400
|
+
const interstitialEnabled = showInterstitial ?? showCommerceShield ?? true;
|
|
2401
|
+
const emitAnonymousBeacon = anonymousBeacon ? createAnonymousBeacon(config, { counterpartyType: config.counterpartyType ?? "website" }) : void 0;
|
|
2402
|
+
const beaconPassThrough = emitAnonymousBeacon ? (request, pathname) => {
|
|
2403
|
+
emitAnonymousBeacon({
|
|
2404
|
+
requestPath: pathname,
|
|
2405
|
+
requestMethod: request.method,
|
|
2406
|
+
counterpartyUrl: config.counterpartyUrl || request.nextUrl.origin,
|
|
2407
|
+
sourceIp: request.headers.get("x-forwarded-for")?.split(",")[0]?.trim() || void 0,
|
|
2408
|
+
rawHeaders: Object.fromEntries(request.headers.entries())
|
|
2409
|
+
});
|
|
2410
|
+
} : void 0;
|
|
2008
2411
|
let cachedRoutes = [];
|
|
2009
2412
|
let lastFetchAt = 0;
|
|
2010
2413
|
let refreshing = null;
|
|
@@ -2046,9 +2449,11 @@ function createMiddleware2(options) {
|
|
|
2046
2449
|
}
|
|
2047
2450
|
const routeConfig = findRouteConfig2(cachedRoutes, pathname, request.method);
|
|
2048
2451
|
if (!routeConfig) {
|
|
2452
|
+
beaconPassThrough?.(request, pathname);
|
|
2049
2453
|
return NextResponse.next();
|
|
2050
2454
|
}
|
|
2051
2455
|
if (routeConfig.minAccessLevel === "none") {
|
|
2456
|
+
beaconPassThrough?.(request, pathname);
|
|
2052
2457
|
return NextResponse.next();
|
|
2053
2458
|
}
|
|
2054
2459
|
const credentials = extractCredentialsFromNextRequest(request);
|
|
@@ -2100,8 +2505,8 @@ function createMiddleware2(options) {
|
|
|
2100
2505
|
{ status: 403 }
|
|
2101
2506
|
);
|
|
2102
2507
|
}
|
|
2103
|
-
if (
|
|
2104
|
-
return new NextResponse(
|
|
2508
|
+
if (interstitialEnabled) {
|
|
2509
|
+
return new NextResponse(generateInterstitialHtml(preCheckResult, options), {
|
|
2105
2510
|
status: 200,
|
|
2106
2511
|
headers: {
|
|
2107
2512
|
"Content-Type": "text/html",
|
|
@@ -2129,17 +2534,9 @@ function createMiddleware2(options) {
|
|
|
2129
2534
|
host: request.headers.get("host") || void 0,
|
|
2130
2535
|
forwardedFor,
|
|
2131
2536
|
agentCardUrl: request.headers.get("x-astrasync-agent-card") || void 0,
|
|
2132
|
-
// Workstream D — full sanitised header capture
|
|
2133
|
-
|
|
2134
|
-
|
|
2135
|
-
Object.fromEntries(request.headers.entries())
|
|
2136
|
-
);
|
|
2137
|
-
return {
|
|
2138
|
-
headers,
|
|
2139
|
-
...apiKeyFormat && { apiKeyFormat },
|
|
2140
|
-
...platformHeaders && { platformHeaders }
|
|
2141
|
-
};
|
|
2142
|
-
})()
|
|
2537
|
+
// Workstream D — full sanitised header capture + CDN-derived
|
|
2538
|
+
// connection block (Web Headers → plain map).
|
|
2539
|
+
observedMetadata: buildSdkObservedMetadata(Object.fromEntries(request.headers.entries()))
|
|
2143
2540
|
}
|
|
2144
2541
|
};
|
|
2145
2542
|
let result = await verify(config, verificationRequest);
|
|
@@ -2194,8 +2591,8 @@ function createMiddleware2(options) {
|
|
|
2194
2591
|
}
|
|
2195
2592
|
);
|
|
2196
2593
|
}
|
|
2197
|
-
if (
|
|
2198
|
-
return new NextResponse(
|
|
2594
|
+
if (interstitialEnabled) {
|
|
2595
|
+
return new NextResponse(generateInterstitialHtml(result, options), {
|
|
2199
2596
|
status: 200,
|
|
2200
2597
|
headers: {
|
|
2201
2598
|
"Content-Type": "text/html",
|
|
@@ -2283,7 +2680,7 @@ var VerificationGatewayClient = class {
|
|
|
2283
2680
|
/**
|
|
2284
2681
|
* Quick verification — checks credentials and policy in one call.
|
|
2285
2682
|
*
|
|
2286
|
-
*
|
|
2683
|
+
* The return shape mirrors `VerificationResult`'s identity/policy
|
|
2287
2684
|
* split. Map to HTTP status the same way: `!identityVerified` → 401,
|
|
2288
2685
|
* `identityVerified && !policyAllowed` → 403.
|
|
2289
2686
|
*/
|
|
@@ -2713,8 +3110,8 @@ function extractX402TransactionValue(req) {
|
|
|
2713
3110
|
// src/transport/rfc9421.ts
|
|
2714
3111
|
var import_structured_headers = require("structured-headers");
|
|
2715
3112
|
function parseRFC9421(headers) {
|
|
2716
|
-
const sigInput =
|
|
2717
|
-
const sig =
|
|
3113
|
+
const sigInput = readHeader2(headers, "signature-input");
|
|
3114
|
+
const sig = readHeader2(headers, "signature");
|
|
2718
3115
|
if (!sigInput || !sig) return null;
|
|
2719
3116
|
let inputDict;
|
|
2720
3117
|
let sigDict;
|
|
@@ -2758,7 +3155,7 @@ function parseRFC9421(headers) {
|
|
|
2758
3155
|
if (signatures.length === 0) return null;
|
|
2759
3156
|
return { signatures };
|
|
2760
3157
|
}
|
|
2761
|
-
function
|
|
3158
|
+
function readHeader2(headers, name) {
|
|
2762
3159
|
for (const key of Object.keys(headers)) {
|
|
2763
3160
|
if (key.toLowerCase() === name) {
|
|
2764
3161
|
const raw = headers[key];
|
|
@@ -3076,11 +3473,11 @@ function extractACPContext(request) {
|
|
|
3076
3473
|
const purpose = mapACPRequestToPurpose(method, path);
|
|
3077
3474
|
const sessionId = extractSessionId2(path);
|
|
3078
3475
|
const headers = request.headers ?? {};
|
|
3079
|
-
const signatureHeader =
|
|
3080
|
-
const timestampHeader =
|
|
3081
|
-
const idempotencyKey =
|
|
3082
|
-
const apiVersion =
|
|
3083
|
-
const bearer = extractBearer(
|
|
3476
|
+
const signatureHeader = readHeader3(headers, "signature");
|
|
3477
|
+
const timestampHeader = readHeader3(headers, "timestamp");
|
|
3478
|
+
const idempotencyKey = readHeader3(headers, "idempotency-key");
|
|
3479
|
+
const apiVersion = readHeader3(headers, "api-version");
|
|
3480
|
+
const bearer = extractBearer(readHeader3(headers, "authorization"));
|
|
3084
3481
|
const body = request.body ?? {};
|
|
3085
3482
|
const merchantId = coerceString3(body.merchant_id ?? body.merchantId);
|
|
3086
3483
|
const totals = Array.isArray(body.totals) ? body.totals : void 0;
|
|
@@ -3148,7 +3545,7 @@ function extractFulfillmentOption(body) {
|
|
|
3148
3545
|
}
|
|
3149
3546
|
return void 0;
|
|
3150
3547
|
}
|
|
3151
|
-
function
|
|
3548
|
+
function readHeader3(headers, name) {
|
|
3152
3549
|
for (const key of Object.keys(headers)) {
|
|
3153
3550
|
if (key.toLowerCase() === name) {
|
|
3154
3551
|
const raw = headers[key];
|
|
@@ -3942,9 +4339,9 @@ function toBuf(bytes) {
|
|
|
3942
4339
|
new Uint8Array(out).set(bytes);
|
|
3943
4340
|
return out;
|
|
3944
4341
|
}
|
|
3945
|
-
function checkTimestamp(
|
|
3946
|
-
if (!
|
|
3947
|
-
const ts = parseTimestamp(
|
|
4342
|
+
function checkTimestamp(headerValue3, toleranceSec, nowFn) {
|
|
4343
|
+
if (!headerValue3) return { ok: false, error: "missing Timestamp header" };
|
|
4344
|
+
const ts = parseTimestamp(headerValue3);
|
|
3948
4345
|
if (ts === null) return { ok: false, error: "unparseable Timestamp header" };
|
|
3949
4346
|
const now = nowFn ? nowFn() : Math.floor(Date.now() / 1e3);
|
|
3950
4347
|
if (Math.abs(now - ts) > toleranceSec) {
|
|
@@ -3988,7 +4385,7 @@ async function getSubtle() {
|
|
|
3988
4385
|
// src/transport/mpp.ts
|
|
3989
4386
|
var import_mppx = require("mppx");
|
|
3990
4387
|
function extractMPPFromRequest(request) {
|
|
3991
|
-
const auth =
|
|
4388
|
+
const auth = readHeader4(request.headers, "authorization");
|
|
3992
4389
|
if (!auth || !/^\s*Payment\s+/i.test(auth)) return null;
|
|
3993
4390
|
try {
|
|
3994
4391
|
const credential = import_mppx.Credential.deserialize(auth);
|
|
@@ -4016,7 +4413,7 @@ function extractMPPFromResponse(response) {
|
|
|
4016
4413
|
offeredMethods: methods
|
|
4017
4414
|
};
|
|
4018
4415
|
}
|
|
4019
|
-
const receiptHeader =
|
|
4416
|
+
const receiptHeader = readHeader4(response.headers, "payment-receipt");
|
|
4020
4417
|
if (receiptHeader) {
|
|
4021
4418
|
try {
|
|
4022
4419
|
const parsed = import_mppx.Receipt.deserialize(receiptHeader);
|
|
@@ -4036,7 +4433,7 @@ function extractMPPFromResponse(response) {
|
|
|
4036
4433
|
return { kind: "error", error: { type: "invalid-receipt-encoding" } };
|
|
4037
4434
|
}
|
|
4038
4435
|
}
|
|
4039
|
-
const contentType =
|
|
4436
|
+
const contentType = readHeader4(response.headers, "content-type");
|
|
4040
4437
|
if (contentType && /application\/problem\+json/i.test(contentType)) {
|
|
4041
4438
|
const body = typeof response.body === "object" && response.body !== null ? response.body : {};
|
|
4042
4439
|
return {
|
|
@@ -4059,7 +4456,7 @@ function extractMPPContext(message) {
|
|
|
4059
4456
|
return extractMPPFromRequest(message);
|
|
4060
4457
|
}
|
|
4061
4458
|
function collectChallenges(response) {
|
|
4062
|
-
const wwwAuth =
|
|
4459
|
+
const wwwAuth = readHeader4(response.headers, "www-authenticate");
|
|
4063
4460
|
if (!wwwAuth) return [];
|
|
4064
4461
|
const headers = new Headers();
|
|
4065
4462
|
headers.set("www-authenticate", wwwAuth);
|
|
@@ -4087,7 +4484,7 @@ function summarizeChallenge(ch) {
|
|
|
4087
4484
|
opaque: raw.opaque
|
|
4088
4485
|
};
|
|
4089
4486
|
}
|
|
4090
|
-
function
|
|
4487
|
+
function readHeader4(headers, name) {
|
|
4091
4488
|
for (const key of Object.keys(headers)) {
|
|
4092
4489
|
if (key.toLowerCase() === name) {
|
|
4093
4490
|
const raw = headers[key];
|
|
@@ -4176,14 +4573,14 @@ function verifyMPP(input) {
|
|
|
4176
4573
|
var import_schemas = require("@x402/core/schemas");
|
|
4177
4574
|
var import_utils = require("@x402/core/utils");
|
|
4178
4575
|
function extractX402FromRequest(request) {
|
|
4179
|
-
const
|
|
4576
|
+
const headerValue3 = readHeader5(request.headers, "x-payment");
|
|
4180
4577
|
if (request.body && typeof request.body === "object") {
|
|
4181
4578
|
const parsed = tryParsePayload(request.body);
|
|
4182
4579
|
if (parsed) return buildPayloadContext(parsed, "body");
|
|
4183
4580
|
}
|
|
4184
|
-
if (
|
|
4581
|
+
if (headerValue3) {
|
|
4185
4582
|
try {
|
|
4186
|
-
const decoded = (0, import_utils.safeBase64Decode)(
|
|
4583
|
+
const decoded = (0, import_utils.safeBase64Decode)(headerValue3);
|
|
4187
4584
|
if (decoded) {
|
|
4188
4585
|
const json = JSON.parse(decoded);
|
|
4189
4586
|
const parsed = tryParsePayload(json);
|
|
@@ -4206,10 +4603,10 @@ function extractX402FromResponse(response) {
|
|
|
4206
4603
|
const parsed = tryParseRequired(response.body);
|
|
4207
4604
|
if (parsed) return buildRequiredContext(parsed, "body");
|
|
4208
4605
|
}
|
|
4209
|
-
const
|
|
4210
|
-
if (
|
|
4606
|
+
const headerValue3 = readHeader5(response.headers, "x-payment-required");
|
|
4607
|
+
if (headerValue3) {
|
|
4211
4608
|
try {
|
|
4212
|
-
const decoded = (0, import_utils.safeBase64Decode)(
|
|
4609
|
+
const decoded = (0, import_utils.safeBase64Decode)(headerValue3);
|
|
4213
4610
|
if (decoded) {
|
|
4214
4611
|
const json = JSON.parse(decoded);
|
|
4215
4612
|
const parsed = tryParseRequired(json);
|
|
@@ -4306,7 +4703,7 @@ function coerceVersion(v) {
|
|
|
4306
4703
|
if (v === 1 || v === 2) return v;
|
|
4307
4704
|
return null;
|
|
4308
4705
|
}
|
|
4309
|
-
function
|
|
4706
|
+
function readHeader5(headers, name) {
|
|
4310
4707
|
if (!headers) return void 0;
|
|
4311
4708
|
for (const key of Object.keys(headers)) {
|
|
4312
4709
|
if (key.toLowerCase() === name) {
|
|
@@ -5054,8 +5451,11 @@ function mcpToPdlss(parsed, requestPath, headerPurpose, headerAction, toolGate)
|
|
|
5054
5451
|
} else if (parsed.actionFromBody && parsed.actionSourceFromBody) {
|
|
5055
5452
|
action = parsed.actionFromBody;
|
|
5056
5453
|
actionSource = parsed.actionSourceFromBody;
|
|
5454
|
+
} else if (parsed.method === "tools/call") {
|
|
5455
|
+
action = void 0;
|
|
5456
|
+
actionSource = void 0;
|
|
5057
5457
|
} else {
|
|
5058
|
-
action = parsed.toolName ?
|
|
5458
|
+
action = parsed.toolName ? `${parsed.method}:${parsed.toolName}` : parsed.method;
|
|
5059
5459
|
actionSource = "transport_layer";
|
|
5060
5460
|
}
|
|
5061
5461
|
return { purpose, action, resource, purposeSource, actionSource };
|
|
@@ -5170,6 +5570,15 @@ function createMcpMiddleware(options) {
|
|
|
5170
5570
|
prefetchWellKnown(config.apiBaseUrl).catch(() => {
|
|
5171
5571
|
});
|
|
5172
5572
|
}
|
|
5573
|
+
if (toolGates) {
|
|
5574
|
+
for (const [toolName, gate] of Object.entries(toolGates)) {
|
|
5575
|
+
if (typeof gate === "string") {
|
|
5576
|
+
console.warn(
|
|
5577
|
+
`[VerificationGateway/MCP] toolGates['${toolName}'] uses the bare-string shorthand ('${gate}'). Gated tools need a PDLSS purpose (else PDLSS_PURPOSE_REQUIRED 400) and evaluate purpose-only without a declared action. Use the object form instead: { minAccessLevel: '${gate}', purpose: '...', action: '...' }.`
|
|
5578
|
+
);
|
|
5579
|
+
}
|
|
5580
|
+
}
|
|
5581
|
+
}
|
|
5173
5582
|
return async (req, res, next) => {
|
|
5174
5583
|
try {
|
|
5175
5584
|
if (skip) return next();
|
|
@@ -5289,7 +5698,13 @@ function createMcpMiddleware(options) {
|
|
|
5289
5698
|
callerMetadata: {
|
|
5290
5699
|
sourceIp: req.ip,
|
|
5291
5700
|
userAgent: req.headers["user-agent"],
|
|
5292
|
-
host: req.headers.host
|
|
5701
|
+
host: req.headers.host,
|
|
5702
|
+
// Capture EVERY inbound header (parity with the express adapter —
|
|
5703
|
+
// MCP-only merchants have no edge to do it upstream) plus the
|
|
5704
|
+
// CDN-derived connection block. Local string work, secrets
|
|
5705
|
+
// stripped; out of the verify cache key so it doesn't defeat
|
|
5706
|
+
// caching.
|
|
5707
|
+
observedMetadata: buildSdkObservedMetadata(req.headers)
|
|
5293
5708
|
}
|
|
5294
5709
|
};
|
|
5295
5710
|
let result = await verify(config, verificationRequest);
|
|
@@ -6074,212 +6489,6 @@ async function recordDecision2(config, params) {
|
|
|
6074
6489
|
blockchainTxHash: result.blockchainTxHash
|
|
6075
6490
|
};
|
|
6076
6491
|
}
|
|
6077
|
-
|
|
6078
|
-
// src/edge-config.ts
|
|
6079
|
-
var DEFAULT_EDGE_CONFIG = Object.freeze({
|
|
6080
|
-
version: 1,
|
|
6081
|
-
mode: "observe",
|
|
6082
|
-
depth: "classify",
|
|
6083
|
-
pathRules: [],
|
|
6084
|
-
sampling: Object.freeze({ anonymousBeaconRate: 0.1 }),
|
|
6085
|
-
failurePosture: "open"
|
|
6086
|
-
});
|
|
6087
|
-
var EDGE_MODES = ["observe", "enforce"];
|
|
6088
|
-
var EDGE_DEPTHS = ["classify", "authenticate", "authorize"];
|
|
6089
|
-
function isEdgeConfig(value) {
|
|
6090
|
-
if (typeof value !== "object" || value === null) return false;
|
|
6091
|
-
const v = value;
|
|
6092
|
-
if (v.version !== 1) return false;
|
|
6093
|
-
if (!EDGE_MODES.includes(v.mode)) return false;
|
|
6094
|
-
if (!EDGE_DEPTHS.includes(v.depth)) return false;
|
|
6095
|
-
if (!Array.isArray(v.pathRules)) return false;
|
|
6096
|
-
for (const rule of v.pathRules) {
|
|
6097
|
-
if (typeof rule !== "object" || rule === null) return false;
|
|
6098
|
-
const r = rule;
|
|
6099
|
-
if (typeof r.pattern !== "string" || r.pattern.length === 0) return false;
|
|
6100
|
-
if (r.mode !== void 0 && !EDGE_MODES.includes(r.mode)) return false;
|
|
6101
|
-
if (r.depth !== void 0 && !EDGE_DEPTHS.includes(r.depth)) return false;
|
|
6102
|
-
}
|
|
6103
|
-
const sampling = v.sampling;
|
|
6104
|
-
if (typeof sampling !== "object" || sampling === null || typeof sampling.anonymousBeaconRate !== "number" || sampling.anonymousBeaconRate < 0 || sampling.anonymousBeaconRate > 1) {
|
|
6105
|
-
return false;
|
|
6106
|
-
}
|
|
6107
|
-
return v.failurePosture === "open";
|
|
6108
|
-
}
|
|
6109
|
-
async function fetchEdgeConfig(config, counterpartyId, opts) {
|
|
6110
|
-
if (!counterpartyId) return null;
|
|
6111
|
-
const headers = { Accept: "application/json" };
|
|
6112
|
-
if (config.apiKey) {
|
|
6113
|
-
headers["Authorization"] = `Bearer ${config.apiKey}`;
|
|
6114
|
-
headers["X-API-Key"] = config.apiKey;
|
|
6115
|
-
}
|
|
6116
|
-
if (opts?.etag) headers["If-None-Match"] = opts.etag;
|
|
6117
|
-
try {
|
|
6118
|
-
const response = await fetch(
|
|
6119
|
-
`${config.apiBaseUrl}/endpoints/${encodeURIComponent(counterpartyId)}/edge-config`,
|
|
6120
|
-
{ method: "GET", headers, signal: AbortSignal.timeout(opts?.timeoutMs ?? 5e3) }
|
|
6121
|
-
);
|
|
6122
|
-
if (response.status === 304) return { notModified: true };
|
|
6123
|
-
if (!response.ok) return null;
|
|
6124
|
-
const body = await response.json();
|
|
6125
|
-
const edgeConfig = body.data?.edgeConfig;
|
|
6126
|
-
if (!isEdgeConfig(edgeConfig)) return null;
|
|
6127
|
-
return { edgeConfig, etag: response.headers.get("etag") ?? void 0 };
|
|
6128
|
-
} catch {
|
|
6129
|
-
return null;
|
|
6130
|
-
}
|
|
6131
|
-
}
|
|
6132
|
-
var DEFAULT_TTL_MS = 60 * 1e3;
|
|
6133
|
-
var DEFAULT_MAX_STALE_MS = 24 * 60 * 60 * 1e3;
|
|
6134
|
-
var cache2 = /* @__PURE__ */ new Map();
|
|
6135
|
-
var inflight2 = /* @__PURE__ */ new Map();
|
|
6136
|
-
function cacheKey(apiBaseUrl, counterpartyId) {
|
|
6137
|
-
return `${apiBaseUrl}|${counterpartyId}`;
|
|
6138
|
-
}
|
|
6139
|
-
function degradeToObserve(config) {
|
|
6140
|
-
if (config.mode !== "enforce" && !config.pathRules.some((r) => r.mode === "enforce")) {
|
|
6141
|
-
return config;
|
|
6142
|
-
}
|
|
6143
|
-
return {
|
|
6144
|
-
...config,
|
|
6145
|
-
mode: "observe",
|
|
6146
|
-
pathRules: config.pathRules.map((r) => r.mode === "enforce" ? { ...r, mode: "observe" } : r)
|
|
6147
|
-
};
|
|
6148
|
-
}
|
|
6149
|
-
async function revalidate(config, counterpartyId) {
|
|
6150
|
-
const key = cacheKey(config.apiBaseUrl, counterpartyId);
|
|
6151
|
-
const existing = inflight2.get(key);
|
|
6152
|
-
if (existing) return existing;
|
|
6153
|
-
const promise = fetchEdgeConfig(config, counterpartyId, { etag: cache2.get(key)?.etag }).then((result) => {
|
|
6154
|
-
if (result === null) return;
|
|
6155
|
-
const now = Date.now();
|
|
6156
|
-
if ("notModified" in result) {
|
|
6157
|
-
const entry = cache2.get(key);
|
|
6158
|
-
if (entry) entry.lastSuccessAt = now;
|
|
6159
|
-
return;
|
|
6160
|
-
}
|
|
6161
|
-
cache2.set(key, { config: result.edgeConfig, etag: result.etag, lastSuccessAt: now });
|
|
6162
|
-
}).finally(() => {
|
|
6163
|
-
inflight2.delete(key);
|
|
6164
|
-
});
|
|
6165
|
-
inflight2.set(key, promise);
|
|
6166
|
-
return promise;
|
|
6167
|
-
}
|
|
6168
|
-
async function getEdgeConfig(config, counterpartyId, opts) {
|
|
6169
|
-
const ttlMs = opts?.ttlMs ?? DEFAULT_TTL_MS;
|
|
6170
|
-
const maxStaleMs = opts?.maxStaleMs ?? DEFAULT_MAX_STALE_MS;
|
|
6171
|
-
const key = cacheKey(config.apiBaseUrl, counterpartyId);
|
|
6172
|
-
const entry = cache2.get(key);
|
|
6173
|
-
if (entry) {
|
|
6174
|
-
const age = Date.now() - entry.lastSuccessAt;
|
|
6175
|
-
if (age > ttlMs) {
|
|
6176
|
-
revalidate(config, counterpartyId).catch(() => {
|
|
6177
|
-
});
|
|
6178
|
-
}
|
|
6179
|
-
return age > maxStaleMs ? degradeToObserve(entry.config) : entry.config;
|
|
6180
|
-
}
|
|
6181
|
-
await revalidate(config, counterpartyId).catch(() => {
|
|
6182
|
-
});
|
|
6183
|
-
return cache2.get(key)?.config ?? DEFAULT_EDGE_CONFIG;
|
|
6184
|
-
}
|
|
6185
|
-
function matchEdgePathRule(rules, path) {
|
|
6186
|
-
for (const rule of rules) {
|
|
6187
|
-
if (globToRegExp(rule.pattern).test(path)) return rule;
|
|
6188
|
-
}
|
|
6189
|
-
return void 0;
|
|
6190
|
-
}
|
|
6191
|
-
function globToRegExp(pattern) {
|
|
6192
|
-
const escaped = pattern.replace(/[.+?^${}()|[\]\\]/g, "\\$&").replace(/\*/g, ".*");
|
|
6193
|
-
return new RegExp(`^${escaped}$`, "i");
|
|
6194
|
-
}
|
|
6195
|
-
function _resetEdgeConfigCache() {
|
|
6196
|
-
cache2.clear();
|
|
6197
|
-
inflight2.clear();
|
|
6198
|
-
}
|
|
6199
|
-
|
|
6200
|
-
// src/platform-signatures.ts
|
|
6201
|
-
var PLATFORM_AGENT_SIGNATURES = [
|
|
6202
|
-
{
|
|
6203
|
-
vendor: "claude",
|
|
6204
|
-
displayName: "Anthropic Claude",
|
|
6205
|
-
uaPatterns: [/claude/i, /anthropic/i],
|
|
6206
|
-
agentCardPatterns: [/anthropic\.com/i, /claude\.ai/i],
|
|
6207
|
-
apiKeyFormatPatterns: [/^sk-ant/i],
|
|
6208
|
-
headerPatterns: [/^anthropic-version/i, /^anthropic-beta/i, /^x-anthropic-/i]
|
|
6209
|
-
},
|
|
6210
|
-
{
|
|
6211
|
-
vendor: "chatgpt",
|
|
6212
|
-
displayName: "OpenAI ChatGPT",
|
|
6213
|
-
uaPatterns: [/chatgpt/i, /openai/i, /gpt-?\d/i],
|
|
6214
|
-
agentCardPatterns: [/openai\.com/i, /chatgpt\.com/i],
|
|
6215
|
-
apiKeyFormatPatterns: [/^sk-proj/i, /^sk-svcacct/i],
|
|
6216
|
-
headerPatterns: [/^openai-organization/i, /^openai-project/i, /^openai-version/i]
|
|
6217
|
-
},
|
|
6218
|
-
{
|
|
6219
|
-
vendor: "gemini",
|
|
6220
|
-
displayName: "Google Gemini",
|
|
6221
|
-
uaPatterns: [/gemini/i, /google-gemini/i, /bard/i],
|
|
6222
|
-
agentCardPatterns: [/gemini\.google\.com/i, /ai\.google\.dev/i],
|
|
6223
|
-
apiKeyFormatPatterns: [/^aiza/i],
|
|
6224
|
-
headerPatterns: [/^x-goog-user-project/i, /^x-goog-api-client/i]
|
|
6225
|
-
},
|
|
6226
|
-
{
|
|
6227
|
-
vendor: "cursor",
|
|
6228
|
-
displayName: "Cursor",
|
|
6229
|
-
uaPatterns: [/cursor/i],
|
|
6230
|
-
agentCardPatterns: [/cursor\.sh/i, /cursor\.com/i]
|
|
6231
|
-
},
|
|
6232
|
-
{
|
|
6233
|
-
vendor: "goose",
|
|
6234
|
-
displayName: "Block Goose",
|
|
6235
|
-
uaPatterns: [/goose/i, /block-goose/i],
|
|
6236
|
-
agentCardPatterns: [/block\.xyz\/goose/i, /goose\.tools/i]
|
|
6237
|
-
},
|
|
6238
|
-
{
|
|
6239
|
-
vendor: "perplexity",
|
|
6240
|
-
displayName: "Perplexity",
|
|
6241
|
-
uaPatterns: [/perplexity/i],
|
|
6242
|
-
agentCardPatterns: [/perplexity\.ai/i],
|
|
6243
|
-
apiKeyFormatPatterns: [/^pplx-/i]
|
|
6244
|
-
}
|
|
6245
|
-
];
|
|
6246
|
-
function matchPlatformSignature(signatures, input) {
|
|
6247
|
-
const ua = input.userAgent ?? "";
|
|
6248
|
-
const cardUrl = input.agentCardUrl ?? "";
|
|
6249
|
-
const apiKeyFormat = input.apiKeyFormat ?? "";
|
|
6250
|
-
const headerLines = [];
|
|
6251
|
-
if (input.platformHeaders) {
|
|
6252
|
-
for (const [name, value] of Object.entries(input.platformHeaders)) {
|
|
6253
|
-
headerLines.push(name, `${name}: ${value}`);
|
|
6254
|
-
}
|
|
6255
|
-
}
|
|
6256
|
-
for (const sig of signatures) {
|
|
6257
|
-
const uaMatch = sig.uaPatterns?.some((p) => p.test(ua));
|
|
6258
|
-
const cardMatch = sig.agentCardPatterns?.some((p) => p.test(cardUrl));
|
|
6259
|
-
const keyMatch = apiKeyFormat.length > 0 && sig.apiKeyFormatPatterns?.some((p) => p.test(apiKeyFormat));
|
|
6260
|
-
const headerMatch = headerLines.length > 0 && sig.headerPatterns?.some((p) => headerLines.some((line) => p.test(line)));
|
|
6261
|
-
if (uaMatch || cardMatch || keyMatch || headerMatch) {
|
|
6262
|
-
const uaBase = ua.split(/[\s/]/)[0]?.toLowerCase() ?? "";
|
|
6263
|
-
const cardHost = (() => {
|
|
6264
|
-
try {
|
|
6265
|
-
return cardUrl ? new URL(cardUrl).host : "";
|
|
6266
|
-
} catch {
|
|
6267
|
-
return "";
|
|
6268
|
-
}
|
|
6269
|
-
})();
|
|
6270
|
-
const keyBasis = uaBase || cardHost || apiKeyFormat || "unknown";
|
|
6271
|
-
return {
|
|
6272
|
-
vendor: sig.vendor,
|
|
6273
|
-
fingerprintKey: `${sig.vendor}:${keyBasis}`,
|
|
6274
|
-
displayName: sig.displayName
|
|
6275
|
-
};
|
|
6276
|
-
}
|
|
6277
|
-
}
|
|
6278
|
-
return void 0;
|
|
6279
|
-
}
|
|
6280
|
-
function detectPlatformFingerprint(input) {
|
|
6281
|
-
return matchPlatformSignature(PLATFORM_AGENT_SIGNATURES, input);
|
|
6282
|
-
}
|
|
6283
6492
|
// Annotate the CommonJS export names for ESM import in node:
|
|
6284
6493
|
0 && (module.exports = {
|
|
6285
6494
|
ACCESS_LEVEL_DESCRIPTIONS,
|
|
@@ -6288,6 +6497,7 @@ function detectPlatformFingerprint(input) {
|
|
|
6288
6497
|
AstraSync,
|
|
6289
6498
|
AstraSyncError,
|
|
6290
6499
|
AuthenticationError,
|
|
6500
|
+
CAPTURE_SCHEMA_VERSION,
|
|
6291
6501
|
ChallengeHandler,
|
|
6292
6502
|
DEFAULT_EDGE_CONFIG,
|
|
6293
6503
|
DEFAULT_TRUST_THRESHOLDS,
|
|
@@ -6306,9 +6516,11 @@ function detectPlatformFingerprint(input) {
|
|
|
6306
6516
|
authorizeSettlement,
|
|
6307
6517
|
awaitStepUpApproval,
|
|
6308
6518
|
buildGuidance,
|
|
6519
|
+
buildSdkObservedMetadata,
|
|
6309
6520
|
clearCache,
|
|
6310
6521
|
createMcpMiddleware,
|
|
6311
6522
|
degradeToObserve,
|
|
6523
|
+
deriveConnectionFromHeaders,
|
|
6312
6524
|
detectPlatformFingerprint,
|
|
6313
6525
|
determineAccessLevel,
|
|
6314
6526
|
express,
|