@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
package/dist/adapters/express.js
CHANGED
|
@@ -25,6 +25,27 @@ __export(express_exports, {
|
|
|
25
25
|
});
|
|
26
26
|
module.exports = __toCommonJS(express_exports);
|
|
27
27
|
|
|
28
|
+
// src/version.ts
|
|
29
|
+
var SDK_VERSION = "4.5.0";
|
|
30
|
+
|
|
31
|
+
// src/http.ts
|
|
32
|
+
var SDK_USER_AGENT = `astrasync-sdk/${SDK_VERSION}`;
|
|
33
|
+
function withUserAgent(initHeaders) {
|
|
34
|
+
if (!initHeaders) return { "user-agent": SDK_USER_AGENT };
|
|
35
|
+
if (initHeaders instanceof Headers) {
|
|
36
|
+
const copy = new Headers(initHeaders);
|
|
37
|
+
if (!copy.has("user-agent")) copy.set("user-agent", SDK_USER_AGENT);
|
|
38
|
+
return copy;
|
|
39
|
+
}
|
|
40
|
+
if (Array.isArray(initHeaders)) {
|
|
41
|
+
const has2 = initHeaders.some(([name]) => name.toLowerCase() === "user-agent");
|
|
42
|
+
return has2 ? initHeaders : [...initHeaders, ["user-agent", SDK_USER_AGENT]];
|
|
43
|
+
}
|
|
44
|
+
const has = Object.keys(initHeaders).some((name) => name.toLowerCase() === "user-agent");
|
|
45
|
+
return has ? initHeaders : { "user-agent": SDK_USER_AGENT, ...initHeaders };
|
|
46
|
+
}
|
|
47
|
+
var sdkFetch = (input, init) => fetch(input, { ...init, headers: withUserAgent(init?.headers) });
|
|
48
|
+
|
|
28
49
|
// src/adapters/stepup-poll.ts
|
|
29
50
|
var DEFAULT_POLL_INTERVAL_MS = 3e3;
|
|
30
51
|
var MIN_POLL_INTERVAL_MS = 250;
|
|
@@ -39,7 +60,7 @@ function resolvePollUrl(config, pollUrl) {
|
|
|
39
60
|
async function pollStepUpStatus(config, approval) {
|
|
40
61
|
if (!approval.pollUrl) return null;
|
|
41
62
|
try {
|
|
42
|
-
const res = await
|
|
63
|
+
const res = await sdkFetch(resolvePollUrl(config, approval.pollUrl), {
|
|
43
64
|
method: "GET",
|
|
44
65
|
signal: AbortSignal.timeout(POLL_REQUEST_TIMEOUT_MS)
|
|
45
66
|
});
|
|
@@ -91,9 +112,6 @@ function getTrustLevel(score) {
|
|
|
91
112
|
return "BRONZE";
|
|
92
113
|
}
|
|
93
114
|
|
|
94
|
-
// src/version.ts
|
|
95
|
-
var SDK_VERSION = "4.1.0";
|
|
96
|
-
|
|
97
115
|
// src/well-known.ts
|
|
98
116
|
var CACHE_TTL_MS = 60 * 60 * 1e3;
|
|
99
117
|
var cache = /* @__PURE__ */ new Map();
|
|
@@ -104,7 +122,7 @@ function wellKnownUrl(apiBaseUrl) {
|
|
|
104
122
|
}
|
|
105
123
|
async function fetchWellKnown(apiBaseUrl) {
|
|
106
124
|
const url = wellKnownUrl(apiBaseUrl);
|
|
107
|
-
const response = await
|
|
125
|
+
const response = await sdkFetch(url, {
|
|
108
126
|
method: "GET",
|
|
109
127
|
headers: { Accept: "application/json" },
|
|
110
128
|
signal: AbortSignal.timeout(5e3)
|
|
@@ -174,7 +192,7 @@ async function performInitCheck(apiBaseUrl, debug, strictInit, apiKey) {
|
|
|
174
192
|
initCheckPerformed = true;
|
|
175
193
|
try {
|
|
176
194
|
const probeUrl = `${apiBaseUrl}/agents/verify-access`;
|
|
177
|
-
const response = await
|
|
195
|
+
const response = await sdkFetch(probeUrl, { method: "HEAD" });
|
|
178
196
|
const contentType = response.headers.get("content-type") ?? "";
|
|
179
197
|
if (contentType.startsWith("text/html")) {
|
|
180
198
|
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).`;
|
|
@@ -188,7 +206,7 @@ async function performInitCheck(apiBaseUrl, debug, strictInit, apiKey) {
|
|
|
188
206
|
);
|
|
189
207
|
}
|
|
190
208
|
if (apiKey) {
|
|
191
|
-
const selfCheck = await
|
|
209
|
+
const selfCheck = await sdkFetch(`${apiBaseUrl}/agents/verify-access/self-check`, {
|
|
192
210
|
headers: { Authorization: `Bearer ${apiKey}` }
|
|
193
211
|
});
|
|
194
212
|
if (selfCheck.status === 401) {
|
|
@@ -435,7 +453,7 @@ async function callVerifyAccessAPI(config, request) {
|
|
|
435
453
|
headers["X-API-Key"] = config.apiKey;
|
|
436
454
|
}
|
|
437
455
|
try {
|
|
438
|
-
const response = await
|
|
456
|
+
const response = await sdkFetch(`${config.apiBaseUrl}/agents/verify-access`, {
|
|
439
457
|
method: "POST",
|
|
440
458
|
headers,
|
|
441
459
|
body: JSON.stringify(body),
|
|
@@ -617,12 +635,15 @@ async function verify(config, request, options) {
|
|
|
617
635
|
const verificationContext = apiResponse.verificationContext;
|
|
618
636
|
const accessLevel = apiResponse.access?.accessLevel ?? "standard";
|
|
619
637
|
const result = {
|
|
620
|
-
//
|
|
621
|
-
//
|
|
622
|
-
//
|
|
623
|
-
//
|
|
624
|
-
//
|
|
625
|
-
|
|
638
|
+
// 4.5.0 (probe F1): read idVerified from verificationContext with the
|
|
639
|
+
// SAME absent⇒false default as the deny branch. The previous `!== false`
|
|
640
|
+
// default manufactured `identityVerified: true` for anonymous
|
|
641
|
+
// allow_full/allow_partial/audit responses (which allow access but omit
|
|
642
|
+
// verificationContext entirely) — the "anonymous caller labelled
|
|
643
|
+
// verified" defect. Every authenticated success response has carried
|
|
644
|
+
// `verificationContext.idVerified: true` since v2.2.4, so a truth claim
|
|
645
|
+
// this load-bearing must never be defaulted on.
|
|
646
|
+
identityVerified: apiResponse.verificationContext?.idVerified === true,
|
|
626
647
|
policyAllowed: true,
|
|
627
648
|
accessLevel,
|
|
628
649
|
agent,
|
|
@@ -678,7 +699,7 @@ async function recordDecision(config, sessionId, decision, reason) {
|
|
|
678
699
|
headers["Authorization"] = `Bearer ${config.apiKey}`;
|
|
679
700
|
headers["X-API-Key"] = config.apiKey;
|
|
680
701
|
}
|
|
681
|
-
await
|
|
702
|
+
await sdkFetch(`${config.apiBaseUrl}/agents/verify-access/${sessionId}/decision`, {
|
|
682
703
|
method: "POST",
|
|
683
704
|
headers,
|
|
684
705
|
body: JSON.stringify({ decision, reason })
|
|
@@ -693,7 +714,7 @@ async function fetchRoutes(config, counterpartyId) {
|
|
|
693
714
|
headers["X-API-Key"] = config.apiKey;
|
|
694
715
|
}
|
|
695
716
|
try {
|
|
696
|
-
const response = await
|
|
717
|
+
const response = await sdkFetch(
|
|
697
718
|
`${config.apiBaseUrl}/endpoints/${encodeURIComponent(counterpartyId)}/routes`,
|
|
698
719
|
{ method: "GET", headers }
|
|
699
720
|
);
|
|
@@ -712,7 +733,7 @@ async function reportUnregisteredAttempt(config, data) {
|
|
|
712
733
|
...counterpartyUrl && { counterpartyUrl },
|
|
713
734
|
...config.counterpartyId && { counterpartyId: config.counterpartyId }
|
|
714
735
|
};
|
|
715
|
-
await
|
|
736
|
+
await sdkFetch(`${apiBaseUrl}/verification-activity/unregistered-attempt`, {
|
|
716
737
|
method: "POST",
|
|
717
738
|
headers: { "Content-Type": "application/json" },
|
|
718
739
|
body: JSON.stringify(body)
|
|
@@ -721,7 +742,7 @@ async function reportUnregisteredAttempt(config, data) {
|
|
|
721
742
|
}
|
|
722
743
|
async function reportCounterpartyPreCheckFailure(config, data) {
|
|
723
744
|
const apiBaseUrl = config.apiBaseUrl || DEFAULT_CONFIG.apiBaseUrl;
|
|
724
|
-
await
|
|
745
|
+
await sdkFetch(`${apiBaseUrl}/verification-activity/counterparty-pre-check-failure`, {
|
|
725
746
|
method: "POST",
|
|
726
747
|
headers: { "Content-Type": "application/json" },
|
|
727
748
|
body: JSON.stringify(data)
|
|
@@ -977,7 +998,13 @@ var PLATFORM_HEADER_NAMES = /* @__PURE__ */ new Set([
|
|
|
977
998
|
"x-agent-card-url",
|
|
978
999
|
"x-agent-provider"
|
|
979
1000
|
]);
|
|
980
|
-
var PLATFORM_HEADER_PREFIXES = [
|
|
1001
|
+
var PLATFORM_HEADER_PREFIXES = [
|
|
1002
|
+
"x-goog-",
|
|
1003
|
+
"x-stainless-",
|
|
1004
|
+
"x-anthropic-",
|
|
1005
|
+
"x-openai-",
|
|
1006
|
+
"sec-ch-"
|
|
1007
|
+
];
|
|
981
1008
|
var KEY_FORMAT_PREFIXES = [
|
|
982
1009
|
"sk-ant-api03",
|
|
983
1010
|
"sk-ant-api",
|
|
@@ -1049,6 +1076,7 @@ function sanitizeHeaders(raw) {
|
|
|
1049
1076
|
const headers = {};
|
|
1050
1077
|
const platformHeaders = {};
|
|
1051
1078
|
let apiKeyFormat;
|
|
1079
|
+
let cookieCount;
|
|
1052
1080
|
let totalBytes = 0;
|
|
1053
1081
|
let count = 0;
|
|
1054
1082
|
if (!raw) return { headers };
|
|
@@ -1063,6 +1091,9 @@ function sanitizeHeaders(raw) {
|
|
|
1063
1091
|
if (fmt && !apiKeyFormat) apiKeyFormat = fmt;
|
|
1064
1092
|
continue;
|
|
1065
1093
|
}
|
|
1094
|
+
if (name === "cookie") {
|
|
1095
|
+
cookieCount = joined.split(";").filter((s) => s.trim().length > 0).length;
|
|
1096
|
+
}
|
|
1066
1097
|
if (isSecretHeader(name)) continue;
|
|
1067
1098
|
let value = joined;
|
|
1068
1099
|
if (byteLength(value) > MAX_HEADER_VALUE_BYTES) {
|
|
@@ -1078,6 +1109,7 @@ function sanitizeHeaders(raw) {
|
|
|
1078
1109
|
const result = { headers };
|
|
1079
1110
|
if (apiKeyFormat) result.apiKeyFormat = apiKeyFormat;
|
|
1080
1111
|
if (Object.keys(platformHeaders).length > 0) result.platformHeaders = platformHeaders;
|
|
1112
|
+
if (cookieCount !== void 0) result.cookieCount = cookieCount;
|
|
1081
1113
|
return result;
|
|
1082
1114
|
}
|
|
1083
1115
|
var CONNECTION_HEADER_SOURCES = [
|
|
@@ -1089,6 +1121,9 @@ var CONNECTION_HEADER_SOURCES = [
|
|
|
1089
1121
|
["region", ["x-vercel-ip-country-region", "cloudfront-viewer-country-region"]],
|
|
1090
1122
|
["countryRegionName", ["cloudfront-viewer-country-region-name"]],
|
|
1091
1123
|
["city", ["x-vercel-ip-city", "cloudfront-viewer-city"]],
|
|
1124
|
+
["latitude", ["x-vercel-ip-latitude", "cloudfront-viewer-latitude"]],
|
|
1125
|
+
["longitude", ["x-vercel-ip-longitude", "cloudfront-viewer-longitude"]],
|
|
1126
|
+
["postalCode", ["x-vercel-ip-postal-code", "cloudfront-viewer-postal-code"]],
|
|
1092
1127
|
["asn", ["cloudfront-viewer-asn"]],
|
|
1093
1128
|
["tlsVersion", ["cloudfront-viewer-tls"]],
|
|
1094
1129
|
["httpVersion", ["cloudfront-viewer-http-version"]],
|
|
@@ -1123,19 +1158,25 @@ function deriveConnectionFromHeaders(headers) {
|
|
|
1123
1158
|
}
|
|
1124
1159
|
}
|
|
1125
1160
|
}
|
|
1126
|
-
|
|
1161
|
+
{
|
|
1127
1162
|
const addr = lower["cloudfront-viewer-address"]?.trim();
|
|
1128
|
-
|
|
1163
|
+
const portMatch = addr?.match(/:(\d+)$/);
|
|
1164
|
+
if (portMatch) connection.sourcePort = portMatch[1];
|
|
1165
|
+
if (!connection.ip && addr) connection.ip = addr.replace(/:\d+$/, "");
|
|
1129
1166
|
}
|
|
1130
1167
|
if (!connection.ip) {
|
|
1131
1168
|
const xff = lower["x-forwarded-for"];
|
|
1132
1169
|
const client = xff?.split(",")[0]?.trim();
|
|
1133
1170
|
if (client) connection.ip = client;
|
|
1134
1171
|
}
|
|
1172
|
+
if (!connection.tlsCipher) {
|
|
1173
|
+
const cipher = connection.tlsVersion?.split(":")[1];
|
|
1174
|
+
if (cipher) connection.tlsCipher = cipher;
|
|
1175
|
+
}
|
|
1135
1176
|
return Object.keys(connection).length > 0 ? connection : void 0;
|
|
1136
1177
|
}
|
|
1137
1178
|
function buildSdkObservedMetadata(rawHeaders) {
|
|
1138
|
-
const { headers, apiKeyFormat, platformHeaders } = sanitizeHeaders(rawHeaders);
|
|
1179
|
+
const { headers, apiKeyFormat, platformHeaders, cookieCount } = sanitizeHeaders(rawHeaders);
|
|
1139
1180
|
const flat = {};
|
|
1140
1181
|
if (rawHeaders) {
|
|
1141
1182
|
for (const name of Object.keys(rawHeaders)) {
|
|
@@ -1150,6 +1191,7 @@ function buildSdkObservedMetadata(rawHeaders) {
|
|
|
1150
1191
|
...apiKeyFormat && { apiKeyFormat },
|
|
1151
1192
|
...platformHeaders && { platformHeaders },
|
|
1152
1193
|
...connection && { connection },
|
|
1194
|
+
...cookieCount !== void 0 && { cookieCount },
|
|
1153
1195
|
schemaVersion: CAPTURE_SCHEMA_VERSION
|
|
1154
1196
|
};
|
|
1155
1197
|
}
|
|
@@ -1194,7 +1236,7 @@ async function fetchEdgeConfig(config, counterpartyId, opts) {
|
|
|
1194
1236
|
}
|
|
1195
1237
|
if (opts?.etag) headers["If-None-Match"] = opts.etag;
|
|
1196
1238
|
try {
|
|
1197
|
-
const response = await
|
|
1239
|
+
const response = await sdkFetch(
|
|
1198
1240
|
`${config.apiBaseUrl}/endpoints/${encodeURIComponent(counterpartyId)}/edge-config`,
|
|
1199
1241
|
{ method: "GET", headers, signal: AbortSignal.timeout(opts?.timeoutMs ?? 5e3) }
|
|
1200
1242
|
);
|
|
@@ -1306,12 +1348,43 @@ var PLATFORM_AGENT_SIGNATURES = [
|
|
|
1306
1348
|
uaPatterns: [/perplexity/i],
|
|
1307
1349
|
agentCardPatterns: [/perplexity\.ai/i],
|
|
1308
1350
|
apiKeyFormatPatterns: [/^pplx-/i]
|
|
1351
|
+
},
|
|
1352
|
+
// Agentic browsers — versioned-token patterns ONLY (a stock Chrome UA must
|
|
1353
|
+
// never match). Distinct vendor keys (not 'chatgpt'/'perplexity'): the
|
|
1354
|
+
// browser product is a different surface than the assistant service, and
|
|
1355
|
+
// the DB registry mirrors one row per vendor. These sit after the primary
|
|
1356
|
+
// vendor entries so a UA carrying an explicit vendor token keeps its
|
|
1357
|
+
// primary attribution; a browser-shaped UA with the agentic token is
|
|
1358
|
+
// caught here BEFORE classify's human tier, which is what makes these
|
|
1359
|
+
// visits observable at all. Token drift is real (some builds mimic Chrome
|
|
1360
|
+
// outright) — re-verify against captured events when a new browser ships,
|
|
1361
|
+
// and check `sec-ch-ua` platformHeaders for the real brand.
|
|
1362
|
+
{
|
|
1363
|
+
vendor: "chatgpt-atlas",
|
|
1364
|
+
displayName: "ChatGPT Atlas browser",
|
|
1365
|
+
uaPatterns: [/\batlas\/\d/i],
|
|
1366
|
+
headerPatterns: [/^sec-ch-ua: .*atlas/i]
|
|
1367
|
+
},
|
|
1368
|
+
{
|
|
1369
|
+
vendor: "perplexity-comet",
|
|
1370
|
+
displayName: "Perplexity Comet browser",
|
|
1371
|
+
uaPatterns: [/\bcomet\/\d/i],
|
|
1372
|
+
headerPatterns: [/^sec-ch-ua: .*comet/i]
|
|
1373
|
+
},
|
|
1374
|
+
// Our own SDK self-identifies (sdkFetch stamps this UA) — first-party
|
|
1375
|
+
// traffic must never pollute the unknown/anonymous pool it exists to audit.
|
|
1376
|
+
{
|
|
1377
|
+
vendor: "astrasync-sdk",
|
|
1378
|
+
displayName: "AstraSync SDK",
|
|
1379
|
+
uaPatterns: [/^astrasync-sdk\//i]
|
|
1309
1380
|
}
|
|
1310
1381
|
];
|
|
1311
1382
|
function matchPlatformSignature(signatures, input) {
|
|
1312
1383
|
const ua = input.userAgent ?? "";
|
|
1313
1384
|
const cardUrl = input.agentCardUrl ?? "";
|
|
1314
1385
|
const apiKeyFormat = input.apiKeyFormat ?? "";
|
|
1386
|
+
const ja4 = input.ja4 ?? "";
|
|
1387
|
+
const asn = input.asn ?? "";
|
|
1315
1388
|
const headerLines = [];
|
|
1316
1389
|
if (input.platformHeaders) {
|
|
1317
1390
|
for (const [name, value] of Object.entries(input.platformHeaders)) {
|
|
@@ -1323,7 +1396,9 @@ function matchPlatformSignature(signatures, input) {
|
|
|
1323
1396
|
const cardMatch = sig.agentCardPatterns?.some((p) => p.test(cardUrl));
|
|
1324
1397
|
const keyMatch = apiKeyFormat.length > 0 && sig.apiKeyFormatPatterns?.some((p) => p.test(apiKeyFormat));
|
|
1325
1398
|
const headerMatch = headerLines.length > 0 && sig.headerPatterns?.some((p) => headerLines.some((line) => p.test(line)));
|
|
1326
|
-
|
|
1399
|
+
const ja4Match = ja4.length > 0 && sig.ja4Patterns?.some((p) => p.test(ja4));
|
|
1400
|
+
const asnMatch = asn.length > 0 && sig.asnList?.includes(asn);
|
|
1401
|
+
if (uaMatch || cardMatch || keyMatch || headerMatch || ja4Match || asnMatch) {
|
|
1327
1402
|
const uaBase = ua.split(/[\s/]/)[0]?.toLowerCase() ?? "";
|
|
1328
1403
|
const cardHost = (() => {
|
|
1329
1404
|
try {
|
|
@@ -1332,7 +1407,7 @@ function matchPlatformSignature(signatures, input) {
|
|
|
1332
1407
|
return "";
|
|
1333
1408
|
}
|
|
1334
1409
|
})();
|
|
1335
|
-
const keyBasis = uaBase || cardHost || apiKeyFormat || "unknown";
|
|
1410
|
+
const keyBasis = uaBase || cardHost || apiKeyFormat || ja4 || asn && `asn${asn}` || "unknown";
|
|
1336
1411
|
return {
|
|
1337
1412
|
vendor: sig.vendor,
|
|
1338
1413
|
fingerprintKey: `${sig.vendor}:${keyBasis}`,
|
|
@@ -1348,9 +1423,10 @@ function detectPlatformFingerprint(input) {
|
|
|
1348
1423
|
|
|
1349
1424
|
// src/edge-core/classify.ts
|
|
1350
1425
|
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;
|
|
1426
|
+
var SELF_UA_PATTERN = /^astrasync-sdk\//i;
|
|
1351
1427
|
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;
|
|
1352
1428
|
var BROWSER_UA_PATTERN = /mozilla\/\d/i;
|
|
1353
|
-
var _patterns = { STATIC_EXTENSIONS, BOT_UA_PATTERN, BROWSER_UA_PATTERN };
|
|
1429
|
+
var _patterns = { STATIC_EXTENSIONS, BOT_UA_PATTERN, BROWSER_UA_PATTERN, SELF_UA_PATTERN };
|
|
1354
1430
|
|
|
1355
1431
|
// src/edge-core/events.ts
|
|
1356
1432
|
function sampled(rate, random = Math.random) {
|
|
@@ -1770,7 +1846,7 @@ function createMiddleware(options) {
|
|
|
1770
1846
|
let result = await verify(config, verificationRequest);
|
|
1771
1847
|
req.agentVerification = result;
|
|
1772
1848
|
let sessionId = result.sessionId;
|
|
1773
|
-
if (config.stepUpMaxWaitMs !== void 0 && result.
|
|
1849
|
+
if (config.stepUpMaxWaitMs !== void 0 && result.policyAllowed && requiresHumanApproval(result) && result.stepUpApproval?.pollUrl) {
|
|
1774
1850
|
const outcome = await awaitStepUpApproval(config, result.stepUpApproval);
|
|
1775
1851
|
res.setHeader("X-Astra-Step-Up", outcome);
|
|
1776
1852
|
if (outcome === "approved") {
|
|
@@ -1781,7 +1857,7 @@ function createMiddleware(options) {
|
|
|
1781
1857
|
result.stepUpOutcome = outcome;
|
|
1782
1858
|
}
|
|
1783
1859
|
}
|
|
1784
|
-
if (!result.
|
|
1860
|
+
if (!result.policyAllowed) {
|
|
1785
1861
|
if (shouldRecordDecisions && sessionId) {
|
|
1786
1862
|
recordDecision(config, sessionId, "denied", result.denialReasons?.[0]).catch(() => {
|
|
1787
1863
|
});
|