@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
package/dist/adapters/nextjs.js
CHANGED
|
@@ -35,6 +35,27 @@ __export(nextjs_exports, {
|
|
|
35
35
|
});
|
|
36
36
|
module.exports = __toCommonJS(nextjs_exports);
|
|
37
37
|
|
|
38
|
+
// src/version.ts
|
|
39
|
+
var SDK_VERSION = "4.4.0";
|
|
40
|
+
|
|
41
|
+
// src/http.ts
|
|
42
|
+
var SDK_USER_AGENT = `astrasync-sdk/${SDK_VERSION}`;
|
|
43
|
+
function withUserAgent(initHeaders) {
|
|
44
|
+
if (!initHeaders) return { "user-agent": SDK_USER_AGENT };
|
|
45
|
+
if (initHeaders instanceof Headers) {
|
|
46
|
+
const copy = new Headers(initHeaders);
|
|
47
|
+
if (!copy.has("user-agent")) copy.set("user-agent", SDK_USER_AGENT);
|
|
48
|
+
return copy;
|
|
49
|
+
}
|
|
50
|
+
if (Array.isArray(initHeaders)) {
|
|
51
|
+
const has2 = initHeaders.some(([name]) => name.toLowerCase() === "user-agent");
|
|
52
|
+
return has2 ? initHeaders : [...initHeaders, ["user-agent", SDK_USER_AGENT]];
|
|
53
|
+
}
|
|
54
|
+
const has = Object.keys(initHeaders).some((name) => name.toLowerCase() === "user-agent");
|
|
55
|
+
return has ? initHeaders : { "user-agent": SDK_USER_AGENT, ...initHeaders };
|
|
56
|
+
}
|
|
57
|
+
var sdkFetch = (input, init) => fetch(input, { ...init, headers: withUserAgent(init?.headers) });
|
|
58
|
+
|
|
38
59
|
// src/adapters/stepup-poll.ts
|
|
39
60
|
var DEFAULT_POLL_INTERVAL_MS = 3e3;
|
|
40
61
|
var MIN_POLL_INTERVAL_MS = 250;
|
|
@@ -49,7 +70,7 @@ function resolvePollUrl(config, pollUrl) {
|
|
|
49
70
|
async function pollStepUpStatus(config, approval) {
|
|
50
71
|
if (!approval.pollUrl) return null;
|
|
51
72
|
try {
|
|
52
|
-
const res = await
|
|
73
|
+
const res = await sdkFetch(resolvePollUrl(config, approval.pollUrl), {
|
|
53
74
|
method: "GET",
|
|
54
75
|
signal: AbortSignal.timeout(POLL_REQUEST_TIMEOUT_MS)
|
|
55
76
|
});
|
|
@@ -101,9 +122,6 @@ function getTrustLevel(score) {
|
|
|
101
122
|
return "BRONZE";
|
|
102
123
|
}
|
|
103
124
|
|
|
104
|
-
// src/version.ts
|
|
105
|
-
var SDK_VERSION = "4.1.0";
|
|
106
|
-
|
|
107
125
|
// src/well-known.ts
|
|
108
126
|
var CACHE_TTL_MS = 60 * 60 * 1e3;
|
|
109
127
|
var cache = /* @__PURE__ */ new Map();
|
|
@@ -132,7 +150,7 @@ async function performInitCheck(apiBaseUrl, debug, strictInit, apiKey) {
|
|
|
132
150
|
initCheckPerformed = true;
|
|
133
151
|
try {
|
|
134
152
|
const probeUrl = `${apiBaseUrl}/agents/verify-access`;
|
|
135
|
-
const response = await
|
|
153
|
+
const response = await sdkFetch(probeUrl, { method: "HEAD" });
|
|
136
154
|
const contentType = response.headers.get("content-type") ?? "";
|
|
137
155
|
if (contentType.startsWith("text/html")) {
|
|
138
156
|
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).`;
|
|
@@ -146,7 +164,7 @@ async function performInitCheck(apiBaseUrl, debug, strictInit, apiKey) {
|
|
|
146
164
|
);
|
|
147
165
|
}
|
|
148
166
|
if (apiKey) {
|
|
149
|
-
const selfCheck = await
|
|
167
|
+
const selfCheck = await sdkFetch(`${apiBaseUrl}/agents/verify-access/self-check`, {
|
|
150
168
|
headers: { Authorization: `Bearer ${apiKey}` }
|
|
151
169
|
});
|
|
152
170
|
if (selfCheck.status === 401) {
|
|
@@ -393,7 +411,7 @@ async function callVerifyAccessAPI(config, request) {
|
|
|
393
411
|
headers["X-API-Key"] = config.apiKey;
|
|
394
412
|
}
|
|
395
413
|
try {
|
|
396
|
-
const response = await
|
|
414
|
+
const response = await sdkFetch(`${config.apiBaseUrl}/agents/verify-access`, {
|
|
397
415
|
method: "POST",
|
|
398
416
|
headers,
|
|
399
417
|
body: JSON.stringify(body),
|
|
@@ -638,7 +656,7 @@ async function fetchRoutes(config, counterpartyId) {
|
|
|
638
656
|
headers["X-API-Key"] = config.apiKey;
|
|
639
657
|
}
|
|
640
658
|
try {
|
|
641
|
-
const response = await
|
|
659
|
+
const response = await sdkFetch(
|
|
642
660
|
`${config.apiBaseUrl}/endpoints/${encodeURIComponent(counterpartyId)}/routes`,
|
|
643
661
|
{ method: "GET", headers }
|
|
644
662
|
);
|
|
@@ -657,7 +675,7 @@ async function reportUnregisteredAttempt(config, data) {
|
|
|
657
675
|
...counterpartyUrl && { counterpartyUrl },
|
|
658
676
|
...config.counterpartyId && { counterpartyId: config.counterpartyId }
|
|
659
677
|
};
|
|
660
|
-
await
|
|
678
|
+
await sdkFetch(`${apiBaseUrl}/verification-activity/unregistered-attempt`, {
|
|
661
679
|
method: "POST",
|
|
662
680
|
headers: { "Content-Type": "application/json" },
|
|
663
681
|
body: JSON.stringify(body)
|
|
@@ -666,7 +684,7 @@ async function reportUnregisteredAttempt(config, data) {
|
|
|
666
684
|
}
|
|
667
685
|
async function reportCounterpartyPreCheckFailure(config, data) {
|
|
668
686
|
const apiBaseUrl = config.apiBaseUrl || DEFAULT_CONFIG.apiBaseUrl;
|
|
669
|
-
await
|
|
687
|
+
await sdkFetch(`${apiBaseUrl}/verification-activity/counterparty-pre-check-failure`, {
|
|
670
688
|
method: "POST",
|
|
671
689
|
headers: { "Content-Type": "application/json" },
|
|
672
690
|
body: JSON.stringify(data)
|
|
@@ -805,7 +823,13 @@ var PLATFORM_HEADER_NAMES = /* @__PURE__ */ new Set([
|
|
|
805
823
|
"x-agent-card-url",
|
|
806
824
|
"x-agent-provider"
|
|
807
825
|
]);
|
|
808
|
-
var PLATFORM_HEADER_PREFIXES = [
|
|
826
|
+
var PLATFORM_HEADER_PREFIXES = [
|
|
827
|
+
"x-goog-",
|
|
828
|
+
"x-stainless-",
|
|
829
|
+
"x-anthropic-",
|
|
830
|
+
"x-openai-",
|
|
831
|
+
"sec-ch-"
|
|
832
|
+
];
|
|
809
833
|
var KEY_FORMAT_PREFIXES = [
|
|
810
834
|
"sk-ant-api03",
|
|
811
835
|
"sk-ant-api",
|
|
@@ -877,6 +901,7 @@ function sanitizeHeaders(raw) {
|
|
|
877
901
|
const headers = {};
|
|
878
902
|
const platformHeaders = {};
|
|
879
903
|
let apiKeyFormat;
|
|
904
|
+
let cookieCount;
|
|
880
905
|
let totalBytes = 0;
|
|
881
906
|
let count = 0;
|
|
882
907
|
if (!raw) return { headers };
|
|
@@ -891,6 +916,9 @@ function sanitizeHeaders(raw) {
|
|
|
891
916
|
if (fmt && !apiKeyFormat) apiKeyFormat = fmt;
|
|
892
917
|
continue;
|
|
893
918
|
}
|
|
919
|
+
if (name === "cookie") {
|
|
920
|
+
cookieCount = joined.split(";").filter((s) => s.trim().length > 0).length;
|
|
921
|
+
}
|
|
894
922
|
if (isSecretHeader(name)) continue;
|
|
895
923
|
let value = joined;
|
|
896
924
|
if (byteLength(value) > MAX_HEADER_VALUE_BYTES) {
|
|
@@ -906,6 +934,7 @@ function sanitizeHeaders(raw) {
|
|
|
906
934
|
const result = { headers };
|
|
907
935
|
if (apiKeyFormat) result.apiKeyFormat = apiKeyFormat;
|
|
908
936
|
if (Object.keys(platformHeaders).length > 0) result.platformHeaders = platformHeaders;
|
|
937
|
+
if (cookieCount !== void 0) result.cookieCount = cookieCount;
|
|
909
938
|
return result;
|
|
910
939
|
}
|
|
911
940
|
var CONNECTION_HEADER_SOURCES = [
|
|
@@ -917,6 +946,9 @@ var CONNECTION_HEADER_SOURCES = [
|
|
|
917
946
|
["region", ["x-vercel-ip-country-region", "cloudfront-viewer-country-region"]],
|
|
918
947
|
["countryRegionName", ["cloudfront-viewer-country-region-name"]],
|
|
919
948
|
["city", ["x-vercel-ip-city", "cloudfront-viewer-city"]],
|
|
949
|
+
["latitude", ["x-vercel-ip-latitude", "cloudfront-viewer-latitude"]],
|
|
950
|
+
["longitude", ["x-vercel-ip-longitude", "cloudfront-viewer-longitude"]],
|
|
951
|
+
["postalCode", ["x-vercel-ip-postal-code", "cloudfront-viewer-postal-code"]],
|
|
920
952
|
["asn", ["cloudfront-viewer-asn"]],
|
|
921
953
|
["tlsVersion", ["cloudfront-viewer-tls"]],
|
|
922
954
|
["httpVersion", ["cloudfront-viewer-http-version"]],
|
|
@@ -951,19 +983,25 @@ function deriveConnectionFromHeaders(headers) {
|
|
|
951
983
|
}
|
|
952
984
|
}
|
|
953
985
|
}
|
|
954
|
-
|
|
986
|
+
{
|
|
955
987
|
const addr = lower["cloudfront-viewer-address"]?.trim();
|
|
956
|
-
|
|
988
|
+
const portMatch = addr?.match(/:(\d+)$/);
|
|
989
|
+
if (portMatch) connection.sourcePort = portMatch[1];
|
|
990
|
+
if (!connection.ip && addr) connection.ip = addr.replace(/:\d+$/, "");
|
|
957
991
|
}
|
|
958
992
|
if (!connection.ip) {
|
|
959
993
|
const xff = lower["x-forwarded-for"];
|
|
960
994
|
const client = xff?.split(",")[0]?.trim();
|
|
961
995
|
if (client) connection.ip = client;
|
|
962
996
|
}
|
|
997
|
+
if (!connection.tlsCipher) {
|
|
998
|
+
const cipher = connection.tlsVersion?.split(":")[1];
|
|
999
|
+
if (cipher) connection.tlsCipher = cipher;
|
|
1000
|
+
}
|
|
963
1001
|
return Object.keys(connection).length > 0 ? connection : void 0;
|
|
964
1002
|
}
|
|
965
1003
|
function buildSdkObservedMetadata(rawHeaders) {
|
|
966
|
-
const { headers, apiKeyFormat, platformHeaders } = sanitizeHeaders(rawHeaders);
|
|
1004
|
+
const { headers, apiKeyFormat, platformHeaders, cookieCount } = sanitizeHeaders(rawHeaders);
|
|
967
1005
|
const flat = {};
|
|
968
1006
|
if (rawHeaders) {
|
|
969
1007
|
for (const name of Object.keys(rawHeaders)) {
|
|
@@ -978,6 +1016,7 @@ function buildSdkObservedMetadata(rawHeaders) {
|
|
|
978
1016
|
...apiKeyFormat && { apiKeyFormat },
|
|
979
1017
|
...platformHeaders && { platformHeaders },
|
|
980
1018
|
...connection && { connection },
|
|
1019
|
+
...cookieCount !== void 0 && { cookieCount },
|
|
981
1020
|
schemaVersion: CAPTURE_SCHEMA_VERSION
|
|
982
1021
|
};
|
|
983
1022
|
}
|
|
@@ -1022,7 +1061,7 @@ async function fetchEdgeConfig(config, counterpartyId, opts) {
|
|
|
1022
1061
|
}
|
|
1023
1062
|
if (opts?.etag) headers["If-None-Match"] = opts.etag;
|
|
1024
1063
|
try {
|
|
1025
|
-
const response = await
|
|
1064
|
+
const response = await sdkFetch(
|
|
1026
1065
|
`${config.apiBaseUrl}/endpoints/${encodeURIComponent(counterpartyId)}/edge-config`,
|
|
1027
1066
|
{ method: "GET", headers, signal: AbortSignal.timeout(opts?.timeoutMs ?? 5e3) }
|
|
1028
1067
|
);
|
|
@@ -1134,12 +1173,43 @@ var PLATFORM_AGENT_SIGNATURES = [
|
|
|
1134
1173
|
uaPatterns: [/perplexity/i],
|
|
1135
1174
|
agentCardPatterns: [/perplexity\.ai/i],
|
|
1136
1175
|
apiKeyFormatPatterns: [/^pplx-/i]
|
|
1176
|
+
},
|
|
1177
|
+
// Agentic browsers — versioned-token patterns ONLY (a stock Chrome UA must
|
|
1178
|
+
// never match). Distinct vendor keys (not 'chatgpt'/'perplexity'): the
|
|
1179
|
+
// browser product is a different surface than the assistant service, and
|
|
1180
|
+
// the DB registry mirrors one row per vendor. These sit after the primary
|
|
1181
|
+
// vendor entries so a UA carrying an explicit vendor token keeps its
|
|
1182
|
+
// primary attribution; a browser-shaped UA with the agentic token is
|
|
1183
|
+
// caught here BEFORE classify's human tier, which is what makes these
|
|
1184
|
+
// visits observable at all. Token drift is real (some builds mimic Chrome
|
|
1185
|
+
// outright) — re-verify against captured events when a new browser ships,
|
|
1186
|
+
// and check `sec-ch-ua` platformHeaders for the real brand.
|
|
1187
|
+
{
|
|
1188
|
+
vendor: "chatgpt-atlas",
|
|
1189
|
+
displayName: "ChatGPT Atlas browser",
|
|
1190
|
+
uaPatterns: [/\batlas\/\d/i],
|
|
1191
|
+
headerPatterns: [/^sec-ch-ua: .*atlas/i]
|
|
1192
|
+
},
|
|
1193
|
+
{
|
|
1194
|
+
vendor: "perplexity-comet",
|
|
1195
|
+
displayName: "Perplexity Comet browser",
|
|
1196
|
+
uaPatterns: [/\bcomet\/\d/i],
|
|
1197
|
+
headerPatterns: [/^sec-ch-ua: .*comet/i]
|
|
1198
|
+
},
|
|
1199
|
+
// Our own SDK self-identifies (sdkFetch stamps this UA) — first-party
|
|
1200
|
+
// traffic must never pollute the unknown/anonymous pool it exists to audit.
|
|
1201
|
+
{
|
|
1202
|
+
vendor: "astrasync-sdk",
|
|
1203
|
+
displayName: "AstraSync SDK",
|
|
1204
|
+
uaPatterns: [/^astrasync-sdk\//i]
|
|
1137
1205
|
}
|
|
1138
1206
|
];
|
|
1139
1207
|
function matchPlatformSignature(signatures, input) {
|
|
1140
1208
|
const ua = input.userAgent ?? "";
|
|
1141
1209
|
const cardUrl = input.agentCardUrl ?? "";
|
|
1142
1210
|
const apiKeyFormat = input.apiKeyFormat ?? "";
|
|
1211
|
+
const ja4 = input.ja4 ?? "";
|
|
1212
|
+
const asn = input.asn ?? "";
|
|
1143
1213
|
const headerLines = [];
|
|
1144
1214
|
if (input.platformHeaders) {
|
|
1145
1215
|
for (const [name, value] of Object.entries(input.platformHeaders)) {
|
|
@@ -1151,7 +1221,9 @@ function matchPlatformSignature(signatures, input) {
|
|
|
1151
1221
|
const cardMatch = sig.agentCardPatterns?.some((p) => p.test(cardUrl));
|
|
1152
1222
|
const keyMatch = apiKeyFormat.length > 0 && sig.apiKeyFormatPatterns?.some((p) => p.test(apiKeyFormat));
|
|
1153
1223
|
const headerMatch = headerLines.length > 0 && sig.headerPatterns?.some((p) => headerLines.some((line) => p.test(line)));
|
|
1154
|
-
|
|
1224
|
+
const ja4Match = ja4.length > 0 && sig.ja4Patterns?.some((p) => p.test(ja4));
|
|
1225
|
+
const asnMatch = asn.length > 0 && sig.asnList?.includes(asn);
|
|
1226
|
+
if (uaMatch || cardMatch || keyMatch || headerMatch || ja4Match || asnMatch) {
|
|
1155
1227
|
const uaBase = ua.split(/[\s/]/)[0]?.toLowerCase() ?? "";
|
|
1156
1228
|
const cardHost = (() => {
|
|
1157
1229
|
try {
|
|
@@ -1160,7 +1232,7 @@ function matchPlatformSignature(signatures, input) {
|
|
|
1160
1232
|
return "";
|
|
1161
1233
|
}
|
|
1162
1234
|
})();
|
|
1163
|
-
const keyBasis = uaBase || cardHost || apiKeyFormat || "unknown";
|
|
1235
|
+
const keyBasis = uaBase || cardHost || apiKeyFormat || ja4 || asn && `asn${asn}` || "unknown";
|
|
1164
1236
|
return {
|
|
1165
1237
|
vendor: sig.vendor,
|
|
1166
1238
|
fingerprintKey: `${sig.vendor}:${keyBasis}`,
|