@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.mjs
CHANGED
|
@@ -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();
|
|
@@ -95,7 +113,7 @@ async function performInitCheck(apiBaseUrl, debug, strictInit, apiKey) {
|
|
|
95
113
|
initCheckPerformed = true;
|
|
96
114
|
try {
|
|
97
115
|
const probeUrl = `${apiBaseUrl}/agents/verify-access`;
|
|
98
|
-
const response = await
|
|
116
|
+
const response = await sdkFetch(probeUrl, { method: "HEAD" });
|
|
99
117
|
const contentType = response.headers.get("content-type") ?? "";
|
|
100
118
|
if (contentType.startsWith("text/html")) {
|
|
101
119
|
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).`;
|
|
@@ -109,7 +127,7 @@ async function performInitCheck(apiBaseUrl, debug, strictInit, apiKey) {
|
|
|
109
127
|
);
|
|
110
128
|
}
|
|
111
129
|
if (apiKey) {
|
|
112
|
-
const selfCheck = await
|
|
130
|
+
const selfCheck = await sdkFetch(`${apiBaseUrl}/agents/verify-access/self-check`, {
|
|
113
131
|
headers: { Authorization: `Bearer ${apiKey}` }
|
|
114
132
|
});
|
|
115
133
|
if (selfCheck.status === 401) {
|
|
@@ -356,7 +374,7 @@ async function callVerifyAccessAPI(config, request) {
|
|
|
356
374
|
headers["X-API-Key"] = config.apiKey;
|
|
357
375
|
}
|
|
358
376
|
try {
|
|
359
|
-
const response = await
|
|
377
|
+
const response = await sdkFetch(`${config.apiBaseUrl}/agents/verify-access`, {
|
|
360
378
|
method: "POST",
|
|
361
379
|
headers,
|
|
362
380
|
body: JSON.stringify(body),
|
|
@@ -601,7 +619,7 @@ async function fetchRoutes(config, counterpartyId) {
|
|
|
601
619
|
headers["X-API-Key"] = config.apiKey;
|
|
602
620
|
}
|
|
603
621
|
try {
|
|
604
|
-
const response = await
|
|
622
|
+
const response = await sdkFetch(
|
|
605
623
|
`${config.apiBaseUrl}/endpoints/${encodeURIComponent(counterpartyId)}/routes`,
|
|
606
624
|
{ method: "GET", headers }
|
|
607
625
|
);
|
|
@@ -620,7 +638,7 @@ async function reportUnregisteredAttempt(config, data) {
|
|
|
620
638
|
...counterpartyUrl && { counterpartyUrl },
|
|
621
639
|
...config.counterpartyId && { counterpartyId: config.counterpartyId }
|
|
622
640
|
};
|
|
623
|
-
await
|
|
641
|
+
await sdkFetch(`${apiBaseUrl}/verification-activity/unregistered-attempt`, {
|
|
624
642
|
method: "POST",
|
|
625
643
|
headers: { "Content-Type": "application/json" },
|
|
626
644
|
body: JSON.stringify(body)
|
|
@@ -629,7 +647,7 @@ async function reportUnregisteredAttempt(config, data) {
|
|
|
629
647
|
}
|
|
630
648
|
async function reportCounterpartyPreCheckFailure(config, data) {
|
|
631
649
|
const apiBaseUrl = config.apiBaseUrl || DEFAULT_CONFIG.apiBaseUrl;
|
|
632
|
-
await
|
|
650
|
+
await sdkFetch(`${apiBaseUrl}/verification-activity/counterparty-pre-check-failure`, {
|
|
633
651
|
method: "POST",
|
|
634
652
|
headers: { "Content-Type": "application/json" },
|
|
635
653
|
body: JSON.stringify(data)
|
|
@@ -768,7 +786,13 @@ var PLATFORM_HEADER_NAMES = /* @__PURE__ */ new Set([
|
|
|
768
786
|
"x-agent-card-url",
|
|
769
787
|
"x-agent-provider"
|
|
770
788
|
]);
|
|
771
|
-
var PLATFORM_HEADER_PREFIXES = [
|
|
789
|
+
var PLATFORM_HEADER_PREFIXES = [
|
|
790
|
+
"x-goog-",
|
|
791
|
+
"x-stainless-",
|
|
792
|
+
"x-anthropic-",
|
|
793
|
+
"x-openai-",
|
|
794
|
+
"sec-ch-"
|
|
795
|
+
];
|
|
772
796
|
var KEY_FORMAT_PREFIXES = [
|
|
773
797
|
"sk-ant-api03",
|
|
774
798
|
"sk-ant-api",
|
|
@@ -840,6 +864,7 @@ function sanitizeHeaders(raw) {
|
|
|
840
864
|
const headers = {};
|
|
841
865
|
const platformHeaders = {};
|
|
842
866
|
let apiKeyFormat;
|
|
867
|
+
let cookieCount;
|
|
843
868
|
let totalBytes = 0;
|
|
844
869
|
let count = 0;
|
|
845
870
|
if (!raw) return { headers };
|
|
@@ -854,6 +879,9 @@ function sanitizeHeaders(raw) {
|
|
|
854
879
|
if (fmt && !apiKeyFormat) apiKeyFormat = fmt;
|
|
855
880
|
continue;
|
|
856
881
|
}
|
|
882
|
+
if (name === "cookie") {
|
|
883
|
+
cookieCount = joined.split(";").filter((s) => s.trim().length > 0).length;
|
|
884
|
+
}
|
|
857
885
|
if (isSecretHeader(name)) continue;
|
|
858
886
|
let value = joined;
|
|
859
887
|
if (byteLength(value) > MAX_HEADER_VALUE_BYTES) {
|
|
@@ -869,6 +897,7 @@ function sanitizeHeaders(raw) {
|
|
|
869
897
|
const result = { headers };
|
|
870
898
|
if (apiKeyFormat) result.apiKeyFormat = apiKeyFormat;
|
|
871
899
|
if (Object.keys(platformHeaders).length > 0) result.platformHeaders = platformHeaders;
|
|
900
|
+
if (cookieCount !== void 0) result.cookieCount = cookieCount;
|
|
872
901
|
return result;
|
|
873
902
|
}
|
|
874
903
|
var CONNECTION_HEADER_SOURCES = [
|
|
@@ -880,6 +909,9 @@ var CONNECTION_HEADER_SOURCES = [
|
|
|
880
909
|
["region", ["x-vercel-ip-country-region", "cloudfront-viewer-country-region"]],
|
|
881
910
|
["countryRegionName", ["cloudfront-viewer-country-region-name"]],
|
|
882
911
|
["city", ["x-vercel-ip-city", "cloudfront-viewer-city"]],
|
|
912
|
+
["latitude", ["x-vercel-ip-latitude", "cloudfront-viewer-latitude"]],
|
|
913
|
+
["longitude", ["x-vercel-ip-longitude", "cloudfront-viewer-longitude"]],
|
|
914
|
+
["postalCode", ["x-vercel-ip-postal-code", "cloudfront-viewer-postal-code"]],
|
|
883
915
|
["asn", ["cloudfront-viewer-asn"]],
|
|
884
916
|
["tlsVersion", ["cloudfront-viewer-tls"]],
|
|
885
917
|
["httpVersion", ["cloudfront-viewer-http-version"]],
|
|
@@ -914,19 +946,25 @@ function deriveConnectionFromHeaders(headers) {
|
|
|
914
946
|
}
|
|
915
947
|
}
|
|
916
948
|
}
|
|
917
|
-
|
|
949
|
+
{
|
|
918
950
|
const addr = lower["cloudfront-viewer-address"]?.trim();
|
|
919
|
-
|
|
951
|
+
const portMatch = addr?.match(/:(\d+)$/);
|
|
952
|
+
if (portMatch) connection.sourcePort = portMatch[1];
|
|
953
|
+
if (!connection.ip && addr) connection.ip = addr.replace(/:\d+$/, "");
|
|
920
954
|
}
|
|
921
955
|
if (!connection.ip) {
|
|
922
956
|
const xff = lower["x-forwarded-for"];
|
|
923
957
|
const client = xff?.split(",")[0]?.trim();
|
|
924
958
|
if (client) connection.ip = client;
|
|
925
959
|
}
|
|
960
|
+
if (!connection.tlsCipher) {
|
|
961
|
+
const cipher = connection.tlsVersion?.split(":")[1];
|
|
962
|
+
if (cipher) connection.tlsCipher = cipher;
|
|
963
|
+
}
|
|
926
964
|
return Object.keys(connection).length > 0 ? connection : void 0;
|
|
927
965
|
}
|
|
928
966
|
function buildSdkObservedMetadata(rawHeaders) {
|
|
929
|
-
const { headers, apiKeyFormat, platformHeaders } = sanitizeHeaders(rawHeaders);
|
|
967
|
+
const { headers, apiKeyFormat, platformHeaders, cookieCount } = sanitizeHeaders(rawHeaders);
|
|
930
968
|
const flat = {};
|
|
931
969
|
if (rawHeaders) {
|
|
932
970
|
for (const name of Object.keys(rawHeaders)) {
|
|
@@ -941,6 +979,7 @@ function buildSdkObservedMetadata(rawHeaders) {
|
|
|
941
979
|
...apiKeyFormat && { apiKeyFormat },
|
|
942
980
|
...platformHeaders && { platformHeaders },
|
|
943
981
|
...connection && { connection },
|
|
982
|
+
...cookieCount !== void 0 && { cookieCount },
|
|
944
983
|
schemaVersion: CAPTURE_SCHEMA_VERSION
|
|
945
984
|
};
|
|
946
985
|
}
|
|
@@ -985,7 +1024,7 @@ async function fetchEdgeConfig(config, counterpartyId, opts) {
|
|
|
985
1024
|
}
|
|
986
1025
|
if (opts?.etag) headers["If-None-Match"] = opts.etag;
|
|
987
1026
|
try {
|
|
988
|
-
const response = await
|
|
1027
|
+
const response = await sdkFetch(
|
|
989
1028
|
`${config.apiBaseUrl}/endpoints/${encodeURIComponent(counterpartyId)}/edge-config`,
|
|
990
1029
|
{ method: "GET", headers, signal: AbortSignal.timeout(opts?.timeoutMs ?? 5e3) }
|
|
991
1030
|
);
|
|
@@ -1097,12 +1136,43 @@ var PLATFORM_AGENT_SIGNATURES = [
|
|
|
1097
1136
|
uaPatterns: [/perplexity/i],
|
|
1098
1137
|
agentCardPatterns: [/perplexity\.ai/i],
|
|
1099
1138
|
apiKeyFormatPatterns: [/^pplx-/i]
|
|
1139
|
+
},
|
|
1140
|
+
// Agentic browsers — versioned-token patterns ONLY (a stock Chrome UA must
|
|
1141
|
+
// never match). Distinct vendor keys (not 'chatgpt'/'perplexity'): the
|
|
1142
|
+
// browser product is a different surface than the assistant service, and
|
|
1143
|
+
// the DB registry mirrors one row per vendor. These sit after the primary
|
|
1144
|
+
// vendor entries so a UA carrying an explicit vendor token keeps its
|
|
1145
|
+
// primary attribution; a browser-shaped UA with the agentic token is
|
|
1146
|
+
// caught here BEFORE classify's human tier, which is what makes these
|
|
1147
|
+
// visits observable at all. Token drift is real (some builds mimic Chrome
|
|
1148
|
+
// outright) — re-verify against captured events when a new browser ships,
|
|
1149
|
+
// and check `sec-ch-ua` platformHeaders for the real brand.
|
|
1150
|
+
{
|
|
1151
|
+
vendor: "chatgpt-atlas",
|
|
1152
|
+
displayName: "ChatGPT Atlas browser",
|
|
1153
|
+
uaPatterns: [/\batlas\/\d/i],
|
|
1154
|
+
headerPatterns: [/^sec-ch-ua: .*atlas/i]
|
|
1155
|
+
},
|
|
1156
|
+
{
|
|
1157
|
+
vendor: "perplexity-comet",
|
|
1158
|
+
displayName: "Perplexity Comet browser",
|
|
1159
|
+
uaPatterns: [/\bcomet\/\d/i],
|
|
1160
|
+
headerPatterns: [/^sec-ch-ua: .*comet/i]
|
|
1161
|
+
},
|
|
1162
|
+
// Our own SDK self-identifies (sdkFetch stamps this UA) — first-party
|
|
1163
|
+
// traffic must never pollute the unknown/anonymous pool it exists to audit.
|
|
1164
|
+
{
|
|
1165
|
+
vendor: "astrasync-sdk",
|
|
1166
|
+
displayName: "AstraSync SDK",
|
|
1167
|
+
uaPatterns: [/^astrasync-sdk\//i]
|
|
1100
1168
|
}
|
|
1101
1169
|
];
|
|
1102
1170
|
function matchPlatformSignature(signatures, input) {
|
|
1103
1171
|
const ua = input.userAgent ?? "";
|
|
1104
1172
|
const cardUrl = input.agentCardUrl ?? "";
|
|
1105
1173
|
const apiKeyFormat = input.apiKeyFormat ?? "";
|
|
1174
|
+
const ja4 = input.ja4 ?? "";
|
|
1175
|
+
const asn = input.asn ?? "";
|
|
1106
1176
|
const headerLines = [];
|
|
1107
1177
|
if (input.platformHeaders) {
|
|
1108
1178
|
for (const [name, value] of Object.entries(input.platformHeaders)) {
|
|
@@ -1114,7 +1184,9 @@ function matchPlatformSignature(signatures, input) {
|
|
|
1114
1184
|
const cardMatch = sig.agentCardPatterns?.some((p) => p.test(cardUrl));
|
|
1115
1185
|
const keyMatch = apiKeyFormat.length > 0 && sig.apiKeyFormatPatterns?.some((p) => p.test(apiKeyFormat));
|
|
1116
1186
|
const headerMatch = headerLines.length > 0 && sig.headerPatterns?.some((p) => headerLines.some((line) => p.test(line)));
|
|
1117
|
-
|
|
1187
|
+
const ja4Match = ja4.length > 0 && sig.ja4Patterns?.some((p) => p.test(ja4));
|
|
1188
|
+
const asnMatch = asn.length > 0 && sig.asnList?.includes(asn);
|
|
1189
|
+
if (uaMatch || cardMatch || keyMatch || headerMatch || ja4Match || asnMatch) {
|
|
1118
1190
|
const uaBase = ua.split(/[\s/]/)[0]?.toLowerCase() ?? "";
|
|
1119
1191
|
const cardHost = (() => {
|
|
1120
1192
|
try {
|
|
@@ -1123,7 +1195,7 @@ function matchPlatformSignature(signatures, input) {
|
|
|
1123
1195
|
return "";
|
|
1124
1196
|
}
|
|
1125
1197
|
})();
|
|
1126
|
-
const keyBasis = uaBase || cardHost || apiKeyFormat || "unknown";
|
|
1198
|
+
const keyBasis = uaBase || cardHost || apiKeyFormat || ja4 || asn && `asn${asn}` || "unknown";
|
|
1127
1199
|
return {
|
|
1128
1200
|
vendor: sig.vendor,
|
|
1129
1201
|
fingerprintKey: `${sig.vendor}:${keyBasis}`,
|