@astrasyncai/verification-gateway 4.3.0 → 4.4.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 +91 -19
- package/dist/adapters/express.js.map +1 -1
- package/dist/adapters/express.mjs +91 -19
- package/dist/adapters/express.mjs.map +1 -1
- package/dist/adapters/mcp.js +52 -13
- package/dist/adapters/mcp.js.map +1 -1
- package/dist/adapters/mcp.mjs +52 -13
- package/dist/adapters/mcp.mjs.map +1 -1
- package/dist/adapters/nextjs.js +89 -17
- package/dist/adapters/nextjs.js.map +1 -1
- package/dist/adapters/nextjs.mjs +89 -17
- package/dist/adapters/nextjs.mjs.map +1 -1
- package/dist/adapters/sdk.js +24 -6
- package/dist/adapters/sdk.js.map +1 -1
- package/dist/adapters/sdk.mjs +24 -6
- 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 +22 -4
- package/dist/bin/astrasync-codex-hook.js +22 -4
- package/dist/bin/astrasync-guard.js +26 -8
- package/dist/bin/astrasync.js +66 -23
- package/dist/browser/background.js +22 -4
- package/dist/browser/background.js.map +1 -1
- package/dist/browser/background.mjs +22 -4
- 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 +22 -4
- package/dist/codex/index.js.map +1 -1
- package/dist/codex/index.mjs +22 -4
- package/dist/codex/index.mjs.map +1 -1
- package/dist/cursor/extension.js +22 -4
- package/dist/cursor/extension.js.map +1 -1
- package/dist/cursor/extension.mjs +22 -4
- package/dist/cursor/extension.mjs.map +1 -1
- 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.js +96 -11
- package/dist/edge-core/index.js.map +1 -1
- package/dist/edge-core/index.mjs +96 -11
- package/dist/edge-core/index.mjs.map +1 -1
- package/dist/gateway/gateway.js +22 -4
- package/dist/gateway/gateway.js.map +1 -1
- package/dist/gateway/gateway.mjs +22 -4
- 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 +151 -26
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +147 -26
- 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 +29 -11
- package/dist/verify.js.map +1 -1
- package/dist/verify.mjs +29 -11
- package/dist/verify.mjs.map +1 -1
- package/package.json +1 -1
|
@@ -1,3 +1,24 @@
|
|
|
1
|
+
// src/version.ts
|
|
2
|
+
var SDK_VERSION = "4.4.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),
|
|
@@ -651,7 +669,7 @@ async function recordDecision(config, sessionId, decision, reason) {
|
|
|
651
669
|
headers["Authorization"] = `Bearer ${config.apiKey}`;
|
|
652
670
|
headers["X-API-Key"] = config.apiKey;
|
|
653
671
|
}
|
|
654
|
-
await
|
|
672
|
+
await sdkFetch(`${config.apiBaseUrl}/agents/verify-access/${sessionId}/decision`, {
|
|
655
673
|
method: "POST",
|
|
656
674
|
headers,
|
|
657
675
|
body: JSON.stringify({ decision, reason })
|
|
@@ -666,7 +684,7 @@ async function fetchRoutes(config, counterpartyId) {
|
|
|
666
684
|
headers["X-API-Key"] = config.apiKey;
|
|
667
685
|
}
|
|
668
686
|
try {
|
|
669
|
-
const response = await
|
|
687
|
+
const response = await sdkFetch(
|
|
670
688
|
`${config.apiBaseUrl}/endpoints/${encodeURIComponent(counterpartyId)}/routes`,
|
|
671
689
|
{ method: "GET", headers }
|
|
672
690
|
);
|
|
@@ -685,7 +703,7 @@ async function reportUnregisteredAttempt(config, data) {
|
|
|
685
703
|
...counterpartyUrl && { counterpartyUrl },
|
|
686
704
|
...config.counterpartyId && { counterpartyId: config.counterpartyId }
|
|
687
705
|
};
|
|
688
|
-
await
|
|
706
|
+
await sdkFetch(`${apiBaseUrl}/verification-activity/unregistered-attempt`, {
|
|
689
707
|
method: "POST",
|
|
690
708
|
headers: { "Content-Type": "application/json" },
|
|
691
709
|
body: JSON.stringify(body)
|
|
@@ -694,7 +712,7 @@ async function reportUnregisteredAttempt(config, data) {
|
|
|
694
712
|
}
|
|
695
713
|
async function reportCounterpartyPreCheckFailure(config, data) {
|
|
696
714
|
const apiBaseUrl = config.apiBaseUrl || DEFAULT_CONFIG.apiBaseUrl;
|
|
697
|
-
await
|
|
715
|
+
await sdkFetch(`${apiBaseUrl}/verification-activity/counterparty-pre-check-failure`, {
|
|
698
716
|
method: "POST",
|
|
699
717
|
headers: { "Content-Type": "application/json" },
|
|
700
718
|
body: JSON.stringify(data)
|
|
@@ -950,7 +968,13 @@ var PLATFORM_HEADER_NAMES = /* @__PURE__ */ new Set([
|
|
|
950
968
|
"x-agent-card-url",
|
|
951
969
|
"x-agent-provider"
|
|
952
970
|
]);
|
|
953
|
-
var PLATFORM_HEADER_PREFIXES = [
|
|
971
|
+
var PLATFORM_HEADER_PREFIXES = [
|
|
972
|
+
"x-goog-",
|
|
973
|
+
"x-stainless-",
|
|
974
|
+
"x-anthropic-",
|
|
975
|
+
"x-openai-",
|
|
976
|
+
"sec-ch-"
|
|
977
|
+
];
|
|
954
978
|
var KEY_FORMAT_PREFIXES = [
|
|
955
979
|
"sk-ant-api03",
|
|
956
980
|
"sk-ant-api",
|
|
@@ -1022,6 +1046,7 @@ function sanitizeHeaders(raw) {
|
|
|
1022
1046
|
const headers = {};
|
|
1023
1047
|
const platformHeaders = {};
|
|
1024
1048
|
let apiKeyFormat;
|
|
1049
|
+
let cookieCount;
|
|
1025
1050
|
let totalBytes = 0;
|
|
1026
1051
|
let count = 0;
|
|
1027
1052
|
if (!raw) return { headers };
|
|
@@ -1036,6 +1061,9 @@ function sanitizeHeaders(raw) {
|
|
|
1036
1061
|
if (fmt && !apiKeyFormat) apiKeyFormat = fmt;
|
|
1037
1062
|
continue;
|
|
1038
1063
|
}
|
|
1064
|
+
if (name === "cookie") {
|
|
1065
|
+
cookieCount = joined.split(";").filter((s) => s.trim().length > 0).length;
|
|
1066
|
+
}
|
|
1039
1067
|
if (isSecretHeader(name)) continue;
|
|
1040
1068
|
let value = joined;
|
|
1041
1069
|
if (byteLength(value) > MAX_HEADER_VALUE_BYTES) {
|
|
@@ -1051,6 +1079,7 @@ function sanitizeHeaders(raw) {
|
|
|
1051
1079
|
const result = { headers };
|
|
1052
1080
|
if (apiKeyFormat) result.apiKeyFormat = apiKeyFormat;
|
|
1053
1081
|
if (Object.keys(platformHeaders).length > 0) result.platformHeaders = platformHeaders;
|
|
1082
|
+
if (cookieCount !== void 0) result.cookieCount = cookieCount;
|
|
1054
1083
|
return result;
|
|
1055
1084
|
}
|
|
1056
1085
|
var CONNECTION_HEADER_SOURCES = [
|
|
@@ -1062,6 +1091,9 @@ var CONNECTION_HEADER_SOURCES = [
|
|
|
1062
1091
|
["region", ["x-vercel-ip-country-region", "cloudfront-viewer-country-region"]],
|
|
1063
1092
|
["countryRegionName", ["cloudfront-viewer-country-region-name"]],
|
|
1064
1093
|
["city", ["x-vercel-ip-city", "cloudfront-viewer-city"]],
|
|
1094
|
+
["latitude", ["x-vercel-ip-latitude", "cloudfront-viewer-latitude"]],
|
|
1095
|
+
["longitude", ["x-vercel-ip-longitude", "cloudfront-viewer-longitude"]],
|
|
1096
|
+
["postalCode", ["x-vercel-ip-postal-code", "cloudfront-viewer-postal-code"]],
|
|
1065
1097
|
["asn", ["cloudfront-viewer-asn"]],
|
|
1066
1098
|
["tlsVersion", ["cloudfront-viewer-tls"]],
|
|
1067
1099
|
["httpVersion", ["cloudfront-viewer-http-version"]],
|
|
@@ -1096,19 +1128,25 @@ function deriveConnectionFromHeaders(headers) {
|
|
|
1096
1128
|
}
|
|
1097
1129
|
}
|
|
1098
1130
|
}
|
|
1099
|
-
|
|
1131
|
+
{
|
|
1100
1132
|
const addr = lower["cloudfront-viewer-address"]?.trim();
|
|
1101
|
-
|
|
1133
|
+
const portMatch = addr?.match(/:(\d+)$/);
|
|
1134
|
+
if (portMatch) connection.sourcePort = portMatch[1];
|
|
1135
|
+
if (!connection.ip && addr) connection.ip = addr.replace(/:\d+$/, "");
|
|
1102
1136
|
}
|
|
1103
1137
|
if (!connection.ip) {
|
|
1104
1138
|
const xff = lower["x-forwarded-for"];
|
|
1105
1139
|
const client = xff?.split(",")[0]?.trim();
|
|
1106
1140
|
if (client) connection.ip = client;
|
|
1107
1141
|
}
|
|
1142
|
+
if (!connection.tlsCipher) {
|
|
1143
|
+
const cipher = connection.tlsVersion?.split(":")[1];
|
|
1144
|
+
if (cipher) connection.tlsCipher = cipher;
|
|
1145
|
+
}
|
|
1108
1146
|
return Object.keys(connection).length > 0 ? connection : void 0;
|
|
1109
1147
|
}
|
|
1110
1148
|
function buildSdkObservedMetadata(rawHeaders) {
|
|
1111
|
-
const { headers, apiKeyFormat, platformHeaders } = sanitizeHeaders(rawHeaders);
|
|
1149
|
+
const { headers, apiKeyFormat, platformHeaders, cookieCount } = sanitizeHeaders(rawHeaders);
|
|
1112
1150
|
const flat = {};
|
|
1113
1151
|
if (rawHeaders) {
|
|
1114
1152
|
for (const name of Object.keys(rawHeaders)) {
|
|
@@ -1123,6 +1161,7 @@ function buildSdkObservedMetadata(rawHeaders) {
|
|
|
1123
1161
|
...apiKeyFormat && { apiKeyFormat },
|
|
1124
1162
|
...platformHeaders && { platformHeaders },
|
|
1125
1163
|
...connection && { connection },
|
|
1164
|
+
...cookieCount !== void 0 && { cookieCount },
|
|
1126
1165
|
schemaVersion: CAPTURE_SCHEMA_VERSION
|
|
1127
1166
|
};
|
|
1128
1167
|
}
|
|
@@ -1167,7 +1206,7 @@ async function fetchEdgeConfig(config, counterpartyId, opts) {
|
|
|
1167
1206
|
}
|
|
1168
1207
|
if (opts?.etag) headers["If-None-Match"] = opts.etag;
|
|
1169
1208
|
try {
|
|
1170
|
-
const response = await
|
|
1209
|
+
const response = await sdkFetch(
|
|
1171
1210
|
`${config.apiBaseUrl}/endpoints/${encodeURIComponent(counterpartyId)}/edge-config`,
|
|
1172
1211
|
{ method: "GET", headers, signal: AbortSignal.timeout(opts?.timeoutMs ?? 5e3) }
|
|
1173
1212
|
);
|
|
@@ -1279,12 +1318,43 @@ var PLATFORM_AGENT_SIGNATURES = [
|
|
|
1279
1318
|
uaPatterns: [/perplexity/i],
|
|
1280
1319
|
agentCardPatterns: [/perplexity\.ai/i],
|
|
1281
1320
|
apiKeyFormatPatterns: [/^pplx-/i]
|
|
1321
|
+
},
|
|
1322
|
+
// Agentic browsers — versioned-token patterns ONLY (a stock Chrome UA must
|
|
1323
|
+
// never match). Distinct vendor keys (not 'chatgpt'/'perplexity'): the
|
|
1324
|
+
// browser product is a different surface than the assistant service, and
|
|
1325
|
+
// the DB registry mirrors one row per vendor. These sit after the primary
|
|
1326
|
+
// vendor entries so a UA carrying an explicit vendor token keeps its
|
|
1327
|
+
// primary attribution; a browser-shaped UA with the agentic token is
|
|
1328
|
+
// caught here BEFORE classify's human tier, which is what makes these
|
|
1329
|
+
// visits observable at all. Token drift is real (some builds mimic Chrome
|
|
1330
|
+
// outright) — re-verify against captured events when a new browser ships,
|
|
1331
|
+
// and check `sec-ch-ua` platformHeaders for the real brand.
|
|
1332
|
+
{
|
|
1333
|
+
vendor: "chatgpt-atlas",
|
|
1334
|
+
displayName: "ChatGPT Atlas browser",
|
|
1335
|
+
uaPatterns: [/\batlas\/\d/i],
|
|
1336
|
+
headerPatterns: [/^sec-ch-ua: .*atlas/i]
|
|
1337
|
+
},
|
|
1338
|
+
{
|
|
1339
|
+
vendor: "perplexity-comet",
|
|
1340
|
+
displayName: "Perplexity Comet browser",
|
|
1341
|
+
uaPatterns: [/\bcomet\/\d/i],
|
|
1342
|
+
headerPatterns: [/^sec-ch-ua: .*comet/i]
|
|
1343
|
+
},
|
|
1344
|
+
// Our own SDK self-identifies (sdkFetch stamps this UA) — first-party
|
|
1345
|
+
// traffic must never pollute the unknown/anonymous pool it exists to audit.
|
|
1346
|
+
{
|
|
1347
|
+
vendor: "astrasync-sdk",
|
|
1348
|
+
displayName: "AstraSync SDK",
|
|
1349
|
+
uaPatterns: [/^astrasync-sdk\//i]
|
|
1282
1350
|
}
|
|
1283
1351
|
];
|
|
1284
1352
|
function matchPlatformSignature(signatures, input) {
|
|
1285
1353
|
const ua = input.userAgent ?? "";
|
|
1286
1354
|
const cardUrl = input.agentCardUrl ?? "";
|
|
1287
1355
|
const apiKeyFormat = input.apiKeyFormat ?? "";
|
|
1356
|
+
const ja4 = input.ja4 ?? "";
|
|
1357
|
+
const asn = input.asn ?? "";
|
|
1288
1358
|
const headerLines = [];
|
|
1289
1359
|
if (input.platformHeaders) {
|
|
1290
1360
|
for (const [name, value] of Object.entries(input.platformHeaders)) {
|
|
@@ -1296,7 +1366,9 @@ function matchPlatformSignature(signatures, input) {
|
|
|
1296
1366
|
const cardMatch = sig.agentCardPatterns?.some((p) => p.test(cardUrl));
|
|
1297
1367
|
const keyMatch = apiKeyFormat.length > 0 && sig.apiKeyFormatPatterns?.some((p) => p.test(apiKeyFormat));
|
|
1298
1368
|
const headerMatch = headerLines.length > 0 && sig.headerPatterns?.some((p) => headerLines.some((line) => p.test(line)));
|
|
1299
|
-
|
|
1369
|
+
const ja4Match = ja4.length > 0 && sig.ja4Patterns?.some((p) => p.test(ja4));
|
|
1370
|
+
const asnMatch = asn.length > 0 && sig.asnList?.includes(asn);
|
|
1371
|
+
if (uaMatch || cardMatch || keyMatch || headerMatch || ja4Match || asnMatch) {
|
|
1300
1372
|
const uaBase = ua.split(/[\s/]/)[0]?.toLowerCase() ?? "";
|
|
1301
1373
|
const cardHost = (() => {
|
|
1302
1374
|
try {
|
|
@@ -1305,7 +1377,7 @@ function matchPlatformSignature(signatures, input) {
|
|
|
1305
1377
|
return "";
|
|
1306
1378
|
}
|
|
1307
1379
|
})();
|
|
1308
|
-
const keyBasis = uaBase || cardHost || apiKeyFormat || "unknown";
|
|
1380
|
+
const keyBasis = uaBase || cardHost || apiKeyFormat || ja4 || asn && `asn${asn}` || "unknown";
|
|
1309
1381
|
return {
|
|
1310
1382
|
vendor: sig.vendor,
|
|
1311
1383
|
fingerprintKey: `${sig.vendor}:${keyBasis}`,
|