@astrasyncai/verification-gateway 4.3.0 → 4.5.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/adapters/express.js +104 -28
- package/dist/adapters/express.js.map +1 -1
- package/dist/adapters/express.mjs +104 -28
- package/dist/adapters/express.mjs.map +1 -1
- package/dist/adapters/mcp.js +63 -21
- package/dist/adapters/mcp.js.map +1 -1
- package/dist/adapters/mcp.mjs +63 -21
- package/dist/adapters/mcp.mjs.map +1 -1
- package/dist/adapters/nextjs.js +103 -27
- package/dist/adapters/nextjs.js.map +1 -1
- package/dist/adapters/nextjs.mjs +103 -27
- package/dist/adapters/nextjs.mjs.map +1 -1
- package/dist/adapters/sdk.js +33 -12
- package/dist/adapters/sdk.js.map +1 -1
- package/dist/adapters/sdk.mjs +33 -12
- package/dist/adapters/sdk.mjs.map +1 -1
- package/dist/agent/index.js +24 -3
- package/dist/agent/index.js.map +1 -1
- package/dist/agent/index.mjs +24 -3
- package/dist/agent/index.mjs.map +1 -1
- package/dist/bin/astrasync-claude-hook.js +31 -10
- package/dist/bin/astrasync-codex-hook.js +31 -10
- package/dist/bin/astrasync-guard.js +35 -14
- package/dist/bin/astrasync.js +75 -29
- package/dist/browser/background.js +31 -10
- package/dist/browser/background.js.map +1 -1
- package/dist/browser/background.mjs +31 -10
- package/dist/browser/background.mjs.map +1 -1
- package/dist/cli/index.js +23 -2
- package/dist/cli/index.js.map +1 -1
- package/dist/cli/index.mjs +23 -2
- package/dist/cli/index.mjs.map +1 -1
- package/dist/codex/index.js +31 -10
- package/dist/codex/index.js.map +1 -1
- package/dist/codex/index.mjs +31 -10
- package/dist/codex/index.mjs.map +1 -1
- package/dist/cursor/extension.js +31 -10
- package/dist/cursor/extension.js.map +1 -1
- package/dist/cursor/extension.mjs +31 -10
- package/dist/cursor/extension.mjs.map +1 -1
- package/dist/edge-config.d.mts +11 -4
- package/dist/edge-config.d.ts +11 -4
- package/dist/edge-config.js +24 -1
- package/dist/edge-config.js.map +1 -1
- package/dist/edge-config.mjs +22 -1
- package/dist/edge-config.mjs.map +1 -1
- package/dist/edge-core/index.d.mts +21 -7
- package/dist/edge-core/index.d.ts +21 -7
- package/dist/edge-core/index.js +170 -25
- package/dist/edge-core/index.js.map +1 -1
- package/dist/edge-core/index.mjs +170 -25
- package/dist/edge-core/index.mjs.map +1 -1
- package/dist/gateway/gateway.js +31 -10
- package/dist/gateway/gateway.js.map +1 -1
- package/dist/gateway/gateway.mjs +31 -10
- package/dist/gateway/gateway.mjs.map +1 -1
- package/dist/index.d.mts +51 -2
- package/dist/index.d.ts +51 -2
- package/dist/index.js +169 -40
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +165 -40
- package/dist/index.mjs.map +1 -1
- package/dist/metadata-capture.d.mts +17 -0
- package/dist/metadata-capture.d.ts +17 -0
- package/dist/metadata-capture.js +25 -4
- package/dist/metadata-capture.js.map +1 -1
- package/dist/metadata-capture.mjs +25 -4
- package/dist/metadata-capture.mjs.map +1 -1
- package/dist/platform-signatures.d.mts +18 -1
- package/dist/platform-signatures.d.ts +18 -1
- package/dist/platform-signatures.js +35 -2
- package/dist/platform-signatures.js.map +1 -1
- package/dist/platform-signatures.mjs +35 -2
- package/dist/platform-signatures.mjs.map +1 -1
- package/dist/registration/index.js +25 -4
- package/dist/registration/index.js.map +1 -1
- package/dist/registration/index.mjs +25 -4
- package/dist/registration/index.mjs.map +1 -1
- package/dist/transport/index.js +22 -1
- package/dist/transport/index.js.map +1 -1
- package/dist/transport/index.mjs +22 -1
- package/dist/transport/index.mjs.map +1 -1
- package/dist/verify.js +38 -17
- package/dist/verify.js.map +1 -1
- package/dist/verify.mjs +38 -17
- package/dist/verify.mjs.map +1 -1
- package/package.json +2 -2
|
@@ -1,3 +1,24 @@
|
|
|
1
|
+
// src/version.ts
|
|
2
|
+
var SDK_VERSION = "4.5.0";
|
|
3
|
+
|
|
4
|
+
// src/http.ts
|
|
5
|
+
var SDK_USER_AGENT = `astrasync-sdk/${SDK_VERSION}`;
|
|
6
|
+
function withUserAgent(initHeaders) {
|
|
7
|
+
if (!initHeaders) return { "user-agent": SDK_USER_AGENT };
|
|
8
|
+
if (initHeaders instanceof Headers) {
|
|
9
|
+
const copy = new Headers(initHeaders);
|
|
10
|
+
if (!copy.has("user-agent")) copy.set("user-agent", SDK_USER_AGENT);
|
|
11
|
+
return copy;
|
|
12
|
+
}
|
|
13
|
+
if (Array.isArray(initHeaders)) {
|
|
14
|
+
const has2 = initHeaders.some(([name]) => name.toLowerCase() === "user-agent");
|
|
15
|
+
return has2 ? initHeaders : [...initHeaders, ["user-agent", SDK_USER_AGENT]];
|
|
16
|
+
}
|
|
17
|
+
const has = Object.keys(initHeaders).some((name) => name.toLowerCase() === "user-agent");
|
|
18
|
+
return has ? initHeaders : { "user-agent": SDK_USER_AGENT, ...initHeaders };
|
|
19
|
+
}
|
|
20
|
+
var sdkFetch = (input, init) => fetch(input, { ...init, headers: withUserAgent(init?.headers) });
|
|
21
|
+
|
|
1
22
|
// src/adapters/stepup-poll.ts
|
|
2
23
|
var DEFAULT_POLL_INTERVAL_MS = 3e3;
|
|
3
24
|
var MIN_POLL_INTERVAL_MS = 250;
|
|
@@ -12,7 +33,7 @@ function resolvePollUrl(config, pollUrl) {
|
|
|
12
33
|
async function pollStepUpStatus(config, approval) {
|
|
13
34
|
if (!approval.pollUrl) return null;
|
|
14
35
|
try {
|
|
15
|
-
const res = await
|
|
36
|
+
const res = await sdkFetch(resolvePollUrl(config, approval.pollUrl), {
|
|
16
37
|
method: "GET",
|
|
17
38
|
signal: AbortSignal.timeout(POLL_REQUEST_TIMEOUT_MS)
|
|
18
39
|
});
|
|
@@ -64,9 +85,6 @@ function getTrustLevel(score) {
|
|
|
64
85
|
return "BRONZE";
|
|
65
86
|
}
|
|
66
87
|
|
|
67
|
-
// src/version.ts
|
|
68
|
-
var SDK_VERSION = "4.1.0";
|
|
69
|
-
|
|
70
88
|
// src/well-known.ts
|
|
71
89
|
var CACHE_TTL_MS = 60 * 60 * 1e3;
|
|
72
90
|
var cache = /* @__PURE__ */ new Map();
|
|
@@ -77,7 +95,7 @@ function wellKnownUrl(apiBaseUrl) {
|
|
|
77
95
|
}
|
|
78
96
|
async function fetchWellKnown(apiBaseUrl) {
|
|
79
97
|
const url = wellKnownUrl(apiBaseUrl);
|
|
80
|
-
const response = await
|
|
98
|
+
const response = await sdkFetch(url, {
|
|
81
99
|
method: "GET",
|
|
82
100
|
headers: { Accept: "application/json" },
|
|
83
101
|
signal: AbortSignal.timeout(5e3)
|
|
@@ -147,7 +165,7 @@ async function performInitCheck(apiBaseUrl, debug, strictInit, apiKey) {
|
|
|
147
165
|
initCheckPerformed = true;
|
|
148
166
|
try {
|
|
149
167
|
const probeUrl = `${apiBaseUrl}/agents/verify-access`;
|
|
150
|
-
const response = await
|
|
168
|
+
const response = await sdkFetch(probeUrl, { method: "HEAD" });
|
|
151
169
|
const contentType = response.headers.get("content-type") ?? "";
|
|
152
170
|
if (contentType.startsWith("text/html")) {
|
|
153
171
|
const message = `[VerificationGateway] apiBaseUrl '${apiBaseUrl}' returned HTML (content-type: ${contentType}). This usually means apiBaseUrl is pointing at a marketing site instead of the API. Expected: 'https://astrasync.ai/api' (prod) or 'https://staging.astrasync.ai/api' (staging).`;
|
|
@@ -161,7 +179,7 @@ async function performInitCheck(apiBaseUrl, debug, strictInit, apiKey) {
|
|
|
161
179
|
);
|
|
162
180
|
}
|
|
163
181
|
if (apiKey) {
|
|
164
|
-
const selfCheck = await
|
|
182
|
+
const selfCheck = await sdkFetch(`${apiBaseUrl}/agents/verify-access/self-check`, {
|
|
165
183
|
headers: { Authorization: `Bearer ${apiKey}` }
|
|
166
184
|
});
|
|
167
185
|
if (selfCheck.status === 401) {
|
|
@@ -408,7 +426,7 @@ async function callVerifyAccessAPI(config, request) {
|
|
|
408
426
|
headers["X-API-Key"] = config.apiKey;
|
|
409
427
|
}
|
|
410
428
|
try {
|
|
411
|
-
const response = await
|
|
429
|
+
const response = await sdkFetch(`${config.apiBaseUrl}/agents/verify-access`, {
|
|
412
430
|
method: "POST",
|
|
413
431
|
headers,
|
|
414
432
|
body: JSON.stringify(body),
|
|
@@ -590,12 +608,15 @@ async function verify(config, request, options) {
|
|
|
590
608
|
const verificationContext = apiResponse.verificationContext;
|
|
591
609
|
const accessLevel = apiResponse.access?.accessLevel ?? "standard";
|
|
592
610
|
const result = {
|
|
593
|
-
//
|
|
594
|
-
//
|
|
595
|
-
//
|
|
596
|
-
//
|
|
597
|
-
//
|
|
598
|
-
|
|
611
|
+
// 4.5.0 (probe F1): read idVerified from verificationContext with the
|
|
612
|
+
// SAME absent⇒false default as the deny branch. The previous `!== false`
|
|
613
|
+
// default manufactured `identityVerified: true` for anonymous
|
|
614
|
+
// allow_full/allow_partial/audit responses (which allow access but omit
|
|
615
|
+
// verificationContext entirely) — the "anonymous caller labelled
|
|
616
|
+
// verified" defect. Every authenticated success response has carried
|
|
617
|
+
// `verificationContext.idVerified: true` since v2.2.4, so a truth claim
|
|
618
|
+
// this load-bearing must never be defaulted on.
|
|
619
|
+
identityVerified: apiResponse.verificationContext?.idVerified === true,
|
|
599
620
|
policyAllowed: true,
|
|
600
621
|
accessLevel,
|
|
601
622
|
agent,
|
|
@@ -651,7 +672,7 @@ async function recordDecision(config, sessionId, decision, reason) {
|
|
|
651
672
|
headers["Authorization"] = `Bearer ${config.apiKey}`;
|
|
652
673
|
headers["X-API-Key"] = config.apiKey;
|
|
653
674
|
}
|
|
654
|
-
await
|
|
675
|
+
await sdkFetch(`${config.apiBaseUrl}/agents/verify-access/${sessionId}/decision`, {
|
|
655
676
|
method: "POST",
|
|
656
677
|
headers,
|
|
657
678
|
body: JSON.stringify({ decision, reason })
|
|
@@ -666,7 +687,7 @@ async function fetchRoutes(config, counterpartyId) {
|
|
|
666
687
|
headers["X-API-Key"] = config.apiKey;
|
|
667
688
|
}
|
|
668
689
|
try {
|
|
669
|
-
const response = await
|
|
690
|
+
const response = await sdkFetch(
|
|
670
691
|
`${config.apiBaseUrl}/endpoints/${encodeURIComponent(counterpartyId)}/routes`,
|
|
671
692
|
{ method: "GET", headers }
|
|
672
693
|
);
|
|
@@ -685,7 +706,7 @@ async function reportUnregisteredAttempt(config, data) {
|
|
|
685
706
|
...counterpartyUrl && { counterpartyUrl },
|
|
686
707
|
...config.counterpartyId && { counterpartyId: config.counterpartyId }
|
|
687
708
|
};
|
|
688
|
-
await
|
|
709
|
+
await sdkFetch(`${apiBaseUrl}/verification-activity/unregistered-attempt`, {
|
|
689
710
|
method: "POST",
|
|
690
711
|
headers: { "Content-Type": "application/json" },
|
|
691
712
|
body: JSON.stringify(body)
|
|
@@ -694,7 +715,7 @@ async function reportUnregisteredAttempt(config, data) {
|
|
|
694
715
|
}
|
|
695
716
|
async function reportCounterpartyPreCheckFailure(config, data) {
|
|
696
717
|
const apiBaseUrl = config.apiBaseUrl || DEFAULT_CONFIG.apiBaseUrl;
|
|
697
|
-
await
|
|
718
|
+
await sdkFetch(`${apiBaseUrl}/verification-activity/counterparty-pre-check-failure`, {
|
|
698
719
|
method: "POST",
|
|
699
720
|
headers: { "Content-Type": "application/json" },
|
|
700
721
|
body: JSON.stringify(data)
|
|
@@ -950,7 +971,13 @@ var PLATFORM_HEADER_NAMES = /* @__PURE__ */ new Set([
|
|
|
950
971
|
"x-agent-card-url",
|
|
951
972
|
"x-agent-provider"
|
|
952
973
|
]);
|
|
953
|
-
var PLATFORM_HEADER_PREFIXES = [
|
|
974
|
+
var PLATFORM_HEADER_PREFIXES = [
|
|
975
|
+
"x-goog-",
|
|
976
|
+
"x-stainless-",
|
|
977
|
+
"x-anthropic-",
|
|
978
|
+
"x-openai-",
|
|
979
|
+
"sec-ch-"
|
|
980
|
+
];
|
|
954
981
|
var KEY_FORMAT_PREFIXES = [
|
|
955
982
|
"sk-ant-api03",
|
|
956
983
|
"sk-ant-api",
|
|
@@ -1022,6 +1049,7 @@ function sanitizeHeaders(raw) {
|
|
|
1022
1049
|
const headers = {};
|
|
1023
1050
|
const platformHeaders = {};
|
|
1024
1051
|
let apiKeyFormat;
|
|
1052
|
+
let cookieCount;
|
|
1025
1053
|
let totalBytes = 0;
|
|
1026
1054
|
let count = 0;
|
|
1027
1055
|
if (!raw) return { headers };
|
|
@@ -1036,6 +1064,9 @@ function sanitizeHeaders(raw) {
|
|
|
1036
1064
|
if (fmt && !apiKeyFormat) apiKeyFormat = fmt;
|
|
1037
1065
|
continue;
|
|
1038
1066
|
}
|
|
1067
|
+
if (name === "cookie") {
|
|
1068
|
+
cookieCount = joined.split(";").filter((s) => s.trim().length > 0).length;
|
|
1069
|
+
}
|
|
1039
1070
|
if (isSecretHeader(name)) continue;
|
|
1040
1071
|
let value = joined;
|
|
1041
1072
|
if (byteLength(value) > MAX_HEADER_VALUE_BYTES) {
|
|
@@ -1051,6 +1082,7 @@ function sanitizeHeaders(raw) {
|
|
|
1051
1082
|
const result = { headers };
|
|
1052
1083
|
if (apiKeyFormat) result.apiKeyFormat = apiKeyFormat;
|
|
1053
1084
|
if (Object.keys(platformHeaders).length > 0) result.platformHeaders = platformHeaders;
|
|
1085
|
+
if (cookieCount !== void 0) result.cookieCount = cookieCount;
|
|
1054
1086
|
return result;
|
|
1055
1087
|
}
|
|
1056
1088
|
var CONNECTION_HEADER_SOURCES = [
|
|
@@ -1062,6 +1094,9 @@ var CONNECTION_HEADER_SOURCES = [
|
|
|
1062
1094
|
["region", ["x-vercel-ip-country-region", "cloudfront-viewer-country-region"]],
|
|
1063
1095
|
["countryRegionName", ["cloudfront-viewer-country-region-name"]],
|
|
1064
1096
|
["city", ["x-vercel-ip-city", "cloudfront-viewer-city"]],
|
|
1097
|
+
["latitude", ["x-vercel-ip-latitude", "cloudfront-viewer-latitude"]],
|
|
1098
|
+
["longitude", ["x-vercel-ip-longitude", "cloudfront-viewer-longitude"]],
|
|
1099
|
+
["postalCode", ["x-vercel-ip-postal-code", "cloudfront-viewer-postal-code"]],
|
|
1065
1100
|
["asn", ["cloudfront-viewer-asn"]],
|
|
1066
1101
|
["tlsVersion", ["cloudfront-viewer-tls"]],
|
|
1067
1102
|
["httpVersion", ["cloudfront-viewer-http-version"]],
|
|
@@ -1096,19 +1131,25 @@ function deriveConnectionFromHeaders(headers) {
|
|
|
1096
1131
|
}
|
|
1097
1132
|
}
|
|
1098
1133
|
}
|
|
1099
|
-
|
|
1134
|
+
{
|
|
1100
1135
|
const addr = lower["cloudfront-viewer-address"]?.trim();
|
|
1101
|
-
|
|
1136
|
+
const portMatch = addr?.match(/:(\d+)$/);
|
|
1137
|
+
if (portMatch) connection.sourcePort = portMatch[1];
|
|
1138
|
+
if (!connection.ip && addr) connection.ip = addr.replace(/:\d+$/, "");
|
|
1102
1139
|
}
|
|
1103
1140
|
if (!connection.ip) {
|
|
1104
1141
|
const xff = lower["x-forwarded-for"];
|
|
1105
1142
|
const client = xff?.split(",")[0]?.trim();
|
|
1106
1143
|
if (client) connection.ip = client;
|
|
1107
1144
|
}
|
|
1145
|
+
if (!connection.tlsCipher) {
|
|
1146
|
+
const cipher = connection.tlsVersion?.split(":")[1];
|
|
1147
|
+
if (cipher) connection.tlsCipher = cipher;
|
|
1148
|
+
}
|
|
1108
1149
|
return Object.keys(connection).length > 0 ? connection : void 0;
|
|
1109
1150
|
}
|
|
1110
1151
|
function buildSdkObservedMetadata(rawHeaders) {
|
|
1111
|
-
const { headers, apiKeyFormat, platformHeaders } = sanitizeHeaders(rawHeaders);
|
|
1152
|
+
const { headers, apiKeyFormat, platformHeaders, cookieCount } = sanitizeHeaders(rawHeaders);
|
|
1112
1153
|
const flat = {};
|
|
1113
1154
|
if (rawHeaders) {
|
|
1114
1155
|
for (const name of Object.keys(rawHeaders)) {
|
|
@@ -1123,6 +1164,7 @@ function buildSdkObservedMetadata(rawHeaders) {
|
|
|
1123
1164
|
...apiKeyFormat && { apiKeyFormat },
|
|
1124
1165
|
...platformHeaders && { platformHeaders },
|
|
1125
1166
|
...connection && { connection },
|
|
1167
|
+
...cookieCount !== void 0 && { cookieCount },
|
|
1126
1168
|
schemaVersion: CAPTURE_SCHEMA_VERSION
|
|
1127
1169
|
};
|
|
1128
1170
|
}
|
|
@@ -1167,7 +1209,7 @@ async function fetchEdgeConfig(config, counterpartyId, opts) {
|
|
|
1167
1209
|
}
|
|
1168
1210
|
if (opts?.etag) headers["If-None-Match"] = opts.etag;
|
|
1169
1211
|
try {
|
|
1170
|
-
const response = await
|
|
1212
|
+
const response = await sdkFetch(
|
|
1171
1213
|
`${config.apiBaseUrl}/endpoints/${encodeURIComponent(counterpartyId)}/edge-config`,
|
|
1172
1214
|
{ method: "GET", headers, signal: AbortSignal.timeout(opts?.timeoutMs ?? 5e3) }
|
|
1173
1215
|
);
|
|
@@ -1279,12 +1321,43 @@ var PLATFORM_AGENT_SIGNATURES = [
|
|
|
1279
1321
|
uaPatterns: [/perplexity/i],
|
|
1280
1322
|
agentCardPatterns: [/perplexity\.ai/i],
|
|
1281
1323
|
apiKeyFormatPatterns: [/^pplx-/i]
|
|
1324
|
+
},
|
|
1325
|
+
// Agentic browsers — versioned-token patterns ONLY (a stock Chrome UA must
|
|
1326
|
+
// never match). Distinct vendor keys (not 'chatgpt'/'perplexity'): the
|
|
1327
|
+
// browser product is a different surface than the assistant service, and
|
|
1328
|
+
// the DB registry mirrors one row per vendor. These sit after the primary
|
|
1329
|
+
// vendor entries so a UA carrying an explicit vendor token keeps its
|
|
1330
|
+
// primary attribution; a browser-shaped UA with the agentic token is
|
|
1331
|
+
// caught here BEFORE classify's human tier, which is what makes these
|
|
1332
|
+
// visits observable at all. Token drift is real (some builds mimic Chrome
|
|
1333
|
+
// outright) — re-verify against captured events when a new browser ships,
|
|
1334
|
+
// and check `sec-ch-ua` platformHeaders for the real brand.
|
|
1335
|
+
{
|
|
1336
|
+
vendor: "chatgpt-atlas",
|
|
1337
|
+
displayName: "ChatGPT Atlas browser",
|
|
1338
|
+
uaPatterns: [/\batlas\/\d/i],
|
|
1339
|
+
headerPatterns: [/^sec-ch-ua: .*atlas/i]
|
|
1340
|
+
},
|
|
1341
|
+
{
|
|
1342
|
+
vendor: "perplexity-comet",
|
|
1343
|
+
displayName: "Perplexity Comet browser",
|
|
1344
|
+
uaPatterns: [/\bcomet\/\d/i],
|
|
1345
|
+
headerPatterns: [/^sec-ch-ua: .*comet/i]
|
|
1346
|
+
},
|
|
1347
|
+
// Our own SDK self-identifies (sdkFetch stamps this UA) — first-party
|
|
1348
|
+
// traffic must never pollute the unknown/anonymous pool it exists to audit.
|
|
1349
|
+
{
|
|
1350
|
+
vendor: "astrasync-sdk",
|
|
1351
|
+
displayName: "AstraSync SDK",
|
|
1352
|
+
uaPatterns: [/^astrasync-sdk\//i]
|
|
1282
1353
|
}
|
|
1283
1354
|
];
|
|
1284
1355
|
function matchPlatformSignature(signatures, input) {
|
|
1285
1356
|
const ua = input.userAgent ?? "";
|
|
1286
1357
|
const cardUrl = input.agentCardUrl ?? "";
|
|
1287
1358
|
const apiKeyFormat = input.apiKeyFormat ?? "";
|
|
1359
|
+
const ja4 = input.ja4 ?? "";
|
|
1360
|
+
const asn = input.asn ?? "";
|
|
1288
1361
|
const headerLines = [];
|
|
1289
1362
|
if (input.platformHeaders) {
|
|
1290
1363
|
for (const [name, value] of Object.entries(input.platformHeaders)) {
|
|
@@ -1296,7 +1369,9 @@ function matchPlatformSignature(signatures, input) {
|
|
|
1296
1369
|
const cardMatch = sig.agentCardPatterns?.some((p) => p.test(cardUrl));
|
|
1297
1370
|
const keyMatch = apiKeyFormat.length > 0 && sig.apiKeyFormatPatterns?.some((p) => p.test(apiKeyFormat));
|
|
1298
1371
|
const headerMatch = headerLines.length > 0 && sig.headerPatterns?.some((p) => headerLines.some((line) => p.test(line)));
|
|
1299
|
-
|
|
1372
|
+
const ja4Match = ja4.length > 0 && sig.ja4Patterns?.some((p) => p.test(ja4));
|
|
1373
|
+
const asnMatch = asn.length > 0 && sig.asnList?.includes(asn);
|
|
1374
|
+
if (uaMatch || cardMatch || keyMatch || headerMatch || ja4Match || asnMatch) {
|
|
1300
1375
|
const uaBase = ua.split(/[\s/]/)[0]?.toLowerCase() ?? "";
|
|
1301
1376
|
const cardHost = (() => {
|
|
1302
1377
|
try {
|
|
@@ -1305,7 +1380,7 @@ function matchPlatformSignature(signatures, input) {
|
|
|
1305
1380
|
return "";
|
|
1306
1381
|
}
|
|
1307
1382
|
})();
|
|
1308
|
-
const keyBasis = uaBase || cardHost || apiKeyFormat || "unknown";
|
|
1383
|
+
const keyBasis = uaBase || cardHost || apiKeyFormat || ja4 || asn && `asn${asn}` || "unknown";
|
|
1309
1384
|
return {
|
|
1310
1385
|
vendor: sig.vendor,
|
|
1311
1386
|
fingerprintKey: `${sig.vendor}:${keyBasis}`,
|
|
@@ -1321,9 +1396,10 @@ function detectPlatformFingerprint(input) {
|
|
|
1321
1396
|
|
|
1322
1397
|
// src/edge-core/classify.ts
|
|
1323
1398
|
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;
|
|
1399
|
+
var SELF_UA_PATTERN = /^astrasync-sdk\//i;
|
|
1324
1400
|
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;
|
|
1325
1401
|
var BROWSER_UA_PATTERN = /mozilla\/\d/i;
|
|
1326
|
-
var _patterns = { STATIC_EXTENSIONS, BOT_UA_PATTERN, BROWSER_UA_PATTERN };
|
|
1402
|
+
var _patterns = { STATIC_EXTENSIONS, BOT_UA_PATTERN, BROWSER_UA_PATTERN, SELF_UA_PATTERN };
|
|
1327
1403
|
|
|
1328
1404
|
// src/edge-core/events.ts
|
|
1329
1405
|
function sampled(rate, random = Math.random) {
|
|
@@ -1743,7 +1819,7 @@ function createMiddleware(options) {
|
|
|
1743
1819
|
let result = await verify(config, verificationRequest);
|
|
1744
1820
|
req.agentVerification = result;
|
|
1745
1821
|
let sessionId = result.sessionId;
|
|
1746
|
-
if (config.stepUpMaxWaitMs !== void 0 && result.
|
|
1822
|
+
if (config.stepUpMaxWaitMs !== void 0 && result.policyAllowed && requiresHumanApproval(result) && result.stepUpApproval?.pollUrl) {
|
|
1747
1823
|
const outcome = await awaitStepUpApproval(config, result.stepUpApproval);
|
|
1748
1824
|
res.setHeader("X-Astra-Step-Up", outcome);
|
|
1749
1825
|
if (outcome === "approved") {
|
|
@@ -1754,7 +1830,7 @@ function createMiddleware(options) {
|
|
|
1754
1830
|
result.stepUpOutcome = outcome;
|
|
1755
1831
|
}
|
|
1756
1832
|
}
|
|
1757
|
-
if (!result.
|
|
1833
|
+
if (!result.policyAllowed) {
|
|
1758
1834
|
if (shouldRecordDecisions && sessionId) {
|
|
1759
1835
|
recordDecision(config, sessionId, "denied", result.denialReasons?.[0]).catch(() => {
|
|
1760
1836
|
});
|