@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/index.d.mts
CHANGED
|
@@ -127,6 +127,55 @@ declare function getWellKnownUrls(apiBaseUrl: string): Promise<WellKnownAgenticC
|
|
|
127
127
|
*/
|
|
128
128
|
declare function getCachedWellKnownUrls(apiBaseUrl: string): WellKnownAgenticCommerce | undefined;
|
|
129
129
|
|
|
130
|
+
/**
|
|
131
|
+
* HTTP-client RUNTIME signatures — a display-only vocabulary, disjoint from
|
|
132
|
+
* the platform-agent vendor vocabulary in `platform-signatures.ts`.
|
|
133
|
+
*
|
|
134
|
+
* A UA of `node` or `python-requests` identifies the HTTP STACK, never the
|
|
135
|
+
* operator: OpenAI Codex, Claude Code, Perplexity's tooling, and our own SDK
|
|
136
|
+
* all fetch through Node — labeling any of them a vendor from the runtime
|
|
137
|
+
* alone would be fabrication. What we CAN say honestly is "undeclared
|
|
138
|
+
* automation on the Node.js runtime", which beats "unknown" in every surface.
|
|
139
|
+
*
|
|
140
|
+
* HARD RULE: this module must NEVER be consulted by `edge-core/classify.ts`,
|
|
141
|
+
* `detectPlatformFingerprint`, or any tiering / orphan-provisioning path.
|
|
142
|
+
* Runtime matches carry no identity: promoting them to the `identified` tier
|
|
143
|
+
* would flip anonymous-bot traffic to 1:1 beacons and auto-provision orphan
|
|
144
|
+
* agents literally named "node". Display and clustering layers only.
|
|
145
|
+
*/
|
|
146
|
+
interface RuntimeSignature {
|
|
147
|
+
/** Stable runtime key — namespace disjoint from `PlatformAgentVendor`. */
|
|
148
|
+
runtime: string;
|
|
149
|
+
/** Human-readable label, e.g. "Node.js runtime". */
|
|
150
|
+
displayName: string;
|
|
151
|
+
uaPatterns: RegExp[];
|
|
152
|
+
}
|
|
153
|
+
/** First match wins — order more-specific tokens before generic ones. */
|
|
154
|
+
declare const RUNTIME_SIGNATURES: ReadonlyArray<RuntimeSignature>;
|
|
155
|
+
/**
|
|
156
|
+
* Detect the HTTP-client runtime from a User-Agent. Returns the displayName
|
|
157
|
+
* (e.g. "Node.js runtime") or undefined when the UA doesn't look like a bare
|
|
158
|
+
* runtime/library client.
|
|
159
|
+
*/
|
|
160
|
+
declare function detectRuntime(userAgent: string | undefined | null): string | undefined;
|
|
161
|
+
|
|
162
|
+
/**
|
|
163
|
+
* Shared outbound-HTTP wrapper — every request the SDK makes to the
|
|
164
|
+
* AstraSync backend (or anywhere else) goes through `sdkFetch` so it
|
|
165
|
+
* carries an identifying User-Agent.
|
|
166
|
+
*
|
|
167
|
+
* Why: Node's global fetch defaults to `user-agent: node`, which is
|
|
168
|
+
* indistinguishable from every other Node client on the wire. Visit
|
|
169
|
+
* Intelligence observed our own SDK/beacon traffic as anonymous "node"
|
|
170
|
+
* visits. Self-identification is the platform's own medicine.
|
|
171
|
+
*
|
|
172
|
+
* Browser note: some browsers filter the User-Agent request header
|
|
173
|
+
* silently (never throwing), so this is a no-op there — which is correct:
|
|
174
|
+
* in a browser the page's real UA is the honest identity.
|
|
175
|
+
*/
|
|
176
|
+
declare const SDK_USER_AGENT = "astrasync-sdk/4.4.0";
|
|
177
|
+
declare const sdkFetch: typeof fetch;
|
|
178
|
+
|
|
130
179
|
/**
|
|
131
180
|
* Single source-of-truth for the SDK's
|
|
132
181
|
* package version emitted on verify-access bodies (and any future
|
|
@@ -145,6 +194,6 @@ declare function getCachedWellKnownUrls(apiBaseUrl: string): WellKnownAgenticCom
|
|
|
145
194
|
* is fine — bumping both in the release-ceremony commit keeps them
|
|
146
195
|
* lockstep.
|
|
147
196
|
*/
|
|
148
|
-
declare const SDK_VERSION = "4.
|
|
197
|
+
declare const SDK_VERSION = "4.4.0";
|
|
149
198
|
|
|
150
|
-
export { EnhancedVerificationResult, GatewayConfig, type SettlementDecision, type SettlementRequest, StepUpApprovalInfo, StepUpApprovalStatus, StepUpOutcome, SDK_VERSION as VERSION, type WellKnownAgenticCommerce, authorizeSettlement, awaitStepUpApproval, getCachedWellKnownUrls, getWellKnownUrls, pollStepUpStatus, prefetchWellKnown };
|
|
199
|
+
export { EnhancedVerificationResult, GatewayConfig, RUNTIME_SIGNATURES, type RuntimeSignature, SDK_USER_AGENT, type SettlementDecision, type SettlementRequest, StepUpApprovalInfo, StepUpApprovalStatus, StepUpOutcome, SDK_VERSION as VERSION, type WellKnownAgenticCommerce, authorizeSettlement, awaitStepUpApproval, detectRuntime, getCachedWellKnownUrls, getWellKnownUrls, pollStepUpStatus, prefetchWellKnown, sdkFetch };
|
package/dist/index.d.ts
CHANGED
|
@@ -127,6 +127,55 @@ declare function getWellKnownUrls(apiBaseUrl: string): Promise<WellKnownAgenticC
|
|
|
127
127
|
*/
|
|
128
128
|
declare function getCachedWellKnownUrls(apiBaseUrl: string): WellKnownAgenticCommerce | undefined;
|
|
129
129
|
|
|
130
|
+
/**
|
|
131
|
+
* HTTP-client RUNTIME signatures — a display-only vocabulary, disjoint from
|
|
132
|
+
* the platform-agent vendor vocabulary in `platform-signatures.ts`.
|
|
133
|
+
*
|
|
134
|
+
* A UA of `node` or `python-requests` identifies the HTTP STACK, never the
|
|
135
|
+
* operator: OpenAI Codex, Claude Code, Perplexity's tooling, and our own SDK
|
|
136
|
+
* all fetch through Node — labeling any of them a vendor from the runtime
|
|
137
|
+
* alone would be fabrication. What we CAN say honestly is "undeclared
|
|
138
|
+
* automation on the Node.js runtime", which beats "unknown" in every surface.
|
|
139
|
+
*
|
|
140
|
+
* HARD RULE: this module must NEVER be consulted by `edge-core/classify.ts`,
|
|
141
|
+
* `detectPlatformFingerprint`, or any tiering / orphan-provisioning path.
|
|
142
|
+
* Runtime matches carry no identity: promoting them to the `identified` tier
|
|
143
|
+
* would flip anonymous-bot traffic to 1:1 beacons and auto-provision orphan
|
|
144
|
+
* agents literally named "node". Display and clustering layers only.
|
|
145
|
+
*/
|
|
146
|
+
interface RuntimeSignature {
|
|
147
|
+
/** Stable runtime key — namespace disjoint from `PlatformAgentVendor`. */
|
|
148
|
+
runtime: string;
|
|
149
|
+
/** Human-readable label, e.g. "Node.js runtime". */
|
|
150
|
+
displayName: string;
|
|
151
|
+
uaPatterns: RegExp[];
|
|
152
|
+
}
|
|
153
|
+
/** First match wins — order more-specific tokens before generic ones. */
|
|
154
|
+
declare const RUNTIME_SIGNATURES: ReadonlyArray<RuntimeSignature>;
|
|
155
|
+
/**
|
|
156
|
+
* Detect the HTTP-client runtime from a User-Agent. Returns the displayName
|
|
157
|
+
* (e.g. "Node.js runtime") or undefined when the UA doesn't look like a bare
|
|
158
|
+
* runtime/library client.
|
|
159
|
+
*/
|
|
160
|
+
declare function detectRuntime(userAgent: string | undefined | null): string | undefined;
|
|
161
|
+
|
|
162
|
+
/**
|
|
163
|
+
* Shared outbound-HTTP wrapper — every request the SDK makes to the
|
|
164
|
+
* AstraSync backend (or anywhere else) goes through `sdkFetch` so it
|
|
165
|
+
* carries an identifying User-Agent.
|
|
166
|
+
*
|
|
167
|
+
* Why: Node's global fetch defaults to `user-agent: node`, which is
|
|
168
|
+
* indistinguishable from every other Node client on the wire. Visit
|
|
169
|
+
* Intelligence observed our own SDK/beacon traffic as anonymous "node"
|
|
170
|
+
* visits. Self-identification is the platform's own medicine.
|
|
171
|
+
*
|
|
172
|
+
* Browser note: some browsers filter the User-Agent request header
|
|
173
|
+
* silently (never throwing), so this is a no-op there — which is correct:
|
|
174
|
+
* in a browser the page's real UA is the honest identity.
|
|
175
|
+
*/
|
|
176
|
+
declare const SDK_USER_AGENT = "astrasync-sdk/4.4.0";
|
|
177
|
+
declare const sdkFetch: typeof fetch;
|
|
178
|
+
|
|
130
179
|
/**
|
|
131
180
|
* Single source-of-truth for the SDK's
|
|
132
181
|
* package version emitted on verify-access bodies (and any future
|
|
@@ -145,6 +194,6 @@ declare function getCachedWellKnownUrls(apiBaseUrl: string): WellKnownAgenticCom
|
|
|
145
194
|
* is fine — bumping both in the release-ceremony commit keeps them
|
|
146
195
|
* lockstep.
|
|
147
196
|
*/
|
|
148
|
-
declare const SDK_VERSION = "4.
|
|
197
|
+
declare const SDK_VERSION = "4.4.0";
|
|
149
198
|
|
|
150
|
-
export { EnhancedVerificationResult, GatewayConfig, type SettlementDecision, type SettlementRequest, StepUpApprovalInfo, StepUpApprovalStatus, StepUpOutcome, SDK_VERSION as VERSION, type WellKnownAgenticCommerce, authorizeSettlement, awaitStepUpApproval, getCachedWellKnownUrls, getWellKnownUrls, pollStepUpStatus, prefetchWellKnown };
|
|
199
|
+
export { EnhancedVerificationResult, GatewayConfig, RUNTIME_SIGNATURES, type RuntimeSignature, SDK_USER_AGENT, type SettlementDecision, type SettlementRequest, StepUpApprovalInfo, StepUpApprovalStatus, StepUpOutcome, SDK_VERSION as VERSION, type WellKnownAgenticCommerce, authorizeSettlement, awaitStepUpApproval, detectRuntime, getCachedWellKnownUrls, getWellKnownUrls, pollStepUpStatus, prefetchWellKnown, sdkFetch };
|
package/dist/index.js
CHANGED
|
@@ -45,9 +45,11 @@ __export(src_exports, {
|
|
|
45
45
|
MAX_HEADER_VALUE_BYTES: () => MAX_HEADER_VALUE_BYTES,
|
|
46
46
|
MAX_TOTAL_BYTES: () => MAX_TOTAL_BYTES,
|
|
47
47
|
PLATFORM_AGENT_SIGNATURES: () => PLATFORM_AGENT_SIGNATURES,
|
|
48
|
+
RUNTIME_SIGNATURES: () => RUNTIME_SIGNATURES,
|
|
48
49
|
RegistrationDeniedError: () => RegistrationDeniedError,
|
|
49
50
|
RegistrationExpiredError: () => RegistrationExpiredError,
|
|
50
51
|
RegistrationTimeoutError: () => RegistrationTimeoutError,
|
|
52
|
+
SDK_USER_AGENT: () => SDK_USER_AGENT,
|
|
51
53
|
TRUST_LEVEL_RANGES: () => TRUST_LEVEL_RANGES,
|
|
52
54
|
VERSION: () => SDK_VERSION,
|
|
53
55
|
_resetEdgeConfigCache: () => _resetEdgeConfigCache,
|
|
@@ -61,6 +63,7 @@ __export(src_exports, {
|
|
|
61
63
|
degradeToObserve: () => degradeToObserve,
|
|
62
64
|
deriveConnectionFromHeaders: () => deriveConnectionFromHeaders,
|
|
63
65
|
detectPlatformFingerprint: () => detectPlatformFingerprint,
|
|
66
|
+
detectRuntime: () => detectRuntime,
|
|
64
67
|
determineAccessLevel: () => determineAccessLevel,
|
|
65
68
|
express: () => express_exports,
|
|
66
69
|
extractApiKeyFormat: () => extractApiKeyFormat,
|
|
@@ -89,6 +92,7 @@ __export(src_exports, {
|
|
|
89
92
|
reportUnregisteredAttempt: () => reportUnregisteredAttempt,
|
|
90
93
|
sanitizeHeaders: () => sanitizeHeaders,
|
|
91
94
|
sdk: () => sdk_exports,
|
|
95
|
+
sdkFetch: () => sdkFetch,
|
|
92
96
|
setMcpMeta: () => setMcpMeta,
|
|
93
97
|
transport: () => transport_exports,
|
|
94
98
|
verify: () => verify
|
|
@@ -217,7 +221,25 @@ function getCapabilities(accessLevel) {
|
|
|
217
221
|
}
|
|
218
222
|
|
|
219
223
|
// src/version.ts
|
|
220
|
-
var SDK_VERSION = "4.
|
|
224
|
+
var SDK_VERSION = "4.4.0";
|
|
225
|
+
|
|
226
|
+
// src/http.ts
|
|
227
|
+
var SDK_USER_AGENT = `astrasync-sdk/${SDK_VERSION}`;
|
|
228
|
+
function withUserAgent(initHeaders) {
|
|
229
|
+
if (!initHeaders) return { "user-agent": SDK_USER_AGENT };
|
|
230
|
+
if (initHeaders instanceof Headers) {
|
|
231
|
+
const copy = new Headers(initHeaders);
|
|
232
|
+
if (!copy.has("user-agent")) copy.set("user-agent", SDK_USER_AGENT);
|
|
233
|
+
return copy;
|
|
234
|
+
}
|
|
235
|
+
if (Array.isArray(initHeaders)) {
|
|
236
|
+
const has2 = initHeaders.some(([name]) => name.toLowerCase() === "user-agent");
|
|
237
|
+
return has2 ? initHeaders : [...initHeaders, ["user-agent", SDK_USER_AGENT]];
|
|
238
|
+
}
|
|
239
|
+
const has = Object.keys(initHeaders).some((name) => name.toLowerCase() === "user-agent");
|
|
240
|
+
return has ? initHeaders : { "user-agent": SDK_USER_AGENT, ...initHeaders };
|
|
241
|
+
}
|
|
242
|
+
var sdkFetch = (input, init) => fetch(input, { ...init, headers: withUserAgent(init?.headers) });
|
|
221
243
|
|
|
222
244
|
// src/well-known.ts
|
|
223
245
|
var CACHE_TTL_MS = 60 * 60 * 1e3;
|
|
@@ -229,7 +251,7 @@ function wellKnownUrl(apiBaseUrl) {
|
|
|
229
251
|
}
|
|
230
252
|
async function fetchWellKnown(apiBaseUrl) {
|
|
231
253
|
const url = wellKnownUrl(apiBaseUrl);
|
|
232
|
-
const response = await
|
|
254
|
+
const response = await sdkFetch(url, {
|
|
233
255
|
method: "GET",
|
|
234
256
|
headers: { Accept: "application/json" },
|
|
235
257
|
signal: AbortSignal.timeout(5e3)
|
|
@@ -299,7 +321,7 @@ async function performInitCheck(apiBaseUrl, debug, strictInit, apiKey) {
|
|
|
299
321
|
initCheckPerformed = true;
|
|
300
322
|
try {
|
|
301
323
|
const probeUrl = `${apiBaseUrl}/agents/verify-access`;
|
|
302
|
-
const response = await
|
|
324
|
+
const response = await sdkFetch(probeUrl, { method: "HEAD" });
|
|
303
325
|
const contentType = response.headers.get("content-type") ?? "";
|
|
304
326
|
if (contentType.startsWith("text/html")) {
|
|
305
327
|
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).`;
|
|
@@ -313,7 +335,7 @@ async function performInitCheck(apiBaseUrl, debug, strictInit, apiKey) {
|
|
|
313
335
|
);
|
|
314
336
|
}
|
|
315
337
|
if (apiKey) {
|
|
316
|
-
const selfCheck = await
|
|
338
|
+
const selfCheck = await sdkFetch(`${apiBaseUrl}/agents/verify-access/self-check`, {
|
|
317
339
|
headers: { Authorization: `Bearer ${apiKey}` }
|
|
318
340
|
});
|
|
319
341
|
if (selfCheck.status === 401) {
|
|
@@ -566,7 +588,7 @@ async function callVerifyAccessAPI(config, request) {
|
|
|
566
588
|
headers["X-API-Key"] = config.apiKey;
|
|
567
589
|
}
|
|
568
590
|
try {
|
|
569
|
-
const response = await
|
|
591
|
+
const response = await sdkFetch(`${config.apiBaseUrl}/agents/verify-access`, {
|
|
570
592
|
method: "POST",
|
|
571
593
|
headers,
|
|
572
594
|
body: JSON.stringify(body),
|
|
@@ -809,7 +831,7 @@ async function recordDecision(config, sessionId, decision, reason) {
|
|
|
809
831
|
headers["Authorization"] = `Bearer ${config.apiKey}`;
|
|
810
832
|
headers["X-API-Key"] = config.apiKey;
|
|
811
833
|
}
|
|
812
|
-
await
|
|
834
|
+
await sdkFetch(`${config.apiBaseUrl}/agents/verify-access/${sessionId}/decision`, {
|
|
813
835
|
method: "POST",
|
|
814
836
|
headers,
|
|
815
837
|
body: JSON.stringify({ decision, reason })
|
|
@@ -827,7 +849,7 @@ async function reportAttempt(config, report) {
|
|
|
827
849
|
...report,
|
|
828
850
|
...!report.counterpartyId && config.counterpartyId && { counterpartyId: config.counterpartyId }
|
|
829
851
|
};
|
|
830
|
-
await
|
|
852
|
+
await sdkFetch(`${apiBaseUrl}/agents/verify-access/attempt-report`, {
|
|
831
853
|
method: "POST",
|
|
832
854
|
headers,
|
|
833
855
|
body: JSON.stringify(body)
|
|
@@ -842,7 +864,7 @@ async function fetchRoutes(config, counterpartyId) {
|
|
|
842
864
|
headers["X-API-Key"] = config.apiKey;
|
|
843
865
|
}
|
|
844
866
|
try {
|
|
845
|
-
const response = await
|
|
867
|
+
const response = await sdkFetch(
|
|
846
868
|
`${config.apiBaseUrl}/endpoints/${encodeURIComponent(counterpartyId)}/routes`,
|
|
847
869
|
{ method: "GET", headers }
|
|
848
870
|
);
|
|
@@ -861,7 +883,7 @@ async function reportUnregisteredAttempt(config, data) {
|
|
|
861
883
|
...counterpartyUrl && { counterpartyUrl },
|
|
862
884
|
...config.counterpartyId && { counterpartyId: config.counterpartyId }
|
|
863
885
|
};
|
|
864
|
-
await
|
|
886
|
+
await sdkFetch(`${apiBaseUrl}/verification-activity/unregistered-attempt`, {
|
|
865
887
|
method: "POST",
|
|
866
888
|
headers: { "Content-Type": "application/json" },
|
|
867
889
|
body: JSON.stringify(body)
|
|
@@ -870,7 +892,7 @@ async function reportUnregisteredAttempt(config, data) {
|
|
|
870
892
|
}
|
|
871
893
|
async function reportCounterpartyPreCheckFailure(config, data) {
|
|
872
894
|
const apiBaseUrl = config.apiBaseUrl || DEFAULT_CONFIG.apiBaseUrl;
|
|
873
|
-
await
|
|
895
|
+
await sdkFetch(`${apiBaseUrl}/verification-activity/counterparty-pre-check-failure`, {
|
|
874
896
|
method: "POST",
|
|
875
897
|
headers: { "Content-Type": "application/json" },
|
|
876
898
|
body: JSON.stringify(data)
|
|
@@ -904,7 +926,7 @@ function resolvePollUrl(config, pollUrl) {
|
|
|
904
926
|
async function pollStepUpStatus(config, approval) {
|
|
905
927
|
if (!approval.pollUrl) return null;
|
|
906
928
|
try {
|
|
907
|
-
const res = await
|
|
929
|
+
const res = await sdkFetch(resolvePollUrl(config, approval.pollUrl), {
|
|
908
930
|
method: "GET",
|
|
909
931
|
signal: AbortSignal.timeout(POLL_REQUEST_TIMEOUT_MS)
|
|
910
932
|
});
|
|
@@ -1279,7 +1301,13 @@ var PLATFORM_HEADER_NAMES = /* @__PURE__ */ new Set([
|
|
|
1279
1301
|
"x-agent-card-url",
|
|
1280
1302
|
"x-agent-provider"
|
|
1281
1303
|
]);
|
|
1282
|
-
var PLATFORM_HEADER_PREFIXES = [
|
|
1304
|
+
var PLATFORM_HEADER_PREFIXES = [
|
|
1305
|
+
"x-goog-",
|
|
1306
|
+
"x-stainless-",
|
|
1307
|
+
"x-anthropic-",
|
|
1308
|
+
"x-openai-",
|
|
1309
|
+
"sec-ch-"
|
|
1310
|
+
];
|
|
1283
1311
|
var KEY_FORMAT_PREFIXES = [
|
|
1284
1312
|
"sk-ant-api03",
|
|
1285
1313
|
"sk-ant-api",
|
|
@@ -1351,6 +1379,7 @@ function sanitizeHeaders(raw) {
|
|
|
1351
1379
|
const headers = {};
|
|
1352
1380
|
const platformHeaders = {};
|
|
1353
1381
|
let apiKeyFormat;
|
|
1382
|
+
let cookieCount;
|
|
1354
1383
|
let totalBytes = 0;
|
|
1355
1384
|
let count = 0;
|
|
1356
1385
|
if (!raw) return { headers };
|
|
@@ -1365,6 +1394,9 @@ function sanitizeHeaders(raw) {
|
|
|
1365
1394
|
if (fmt && !apiKeyFormat) apiKeyFormat = fmt;
|
|
1366
1395
|
continue;
|
|
1367
1396
|
}
|
|
1397
|
+
if (name === "cookie") {
|
|
1398
|
+
cookieCount = joined.split(";").filter((s) => s.trim().length > 0).length;
|
|
1399
|
+
}
|
|
1368
1400
|
if (isSecretHeader(name)) continue;
|
|
1369
1401
|
let value = joined;
|
|
1370
1402
|
if (byteLength(value) > MAX_HEADER_VALUE_BYTES) {
|
|
@@ -1380,6 +1412,7 @@ function sanitizeHeaders(raw) {
|
|
|
1380
1412
|
const result = { headers };
|
|
1381
1413
|
if (apiKeyFormat) result.apiKeyFormat = apiKeyFormat;
|
|
1382
1414
|
if (Object.keys(platformHeaders).length > 0) result.platformHeaders = platformHeaders;
|
|
1415
|
+
if (cookieCount !== void 0) result.cookieCount = cookieCount;
|
|
1383
1416
|
return result;
|
|
1384
1417
|
}
|
|
1385
1418
|
function extractPlatformHeaders(sanitized) {
|
|
@@ -1399,6 +1432,9 @@ var CONNECTION_HEADER_SOURCES = [
|
|
|
1399
1432
|
["region", ["x-vercel-ip-country-region", "cloudfront-viewer-country-region"]],
|
|
1400
1433
|
["countryRegionName", ["cloudfront-viewer-country-region-name"]],
|
|
1401
1434
|
["city", ["x-vercel-ip-city", "cloudfront-viewer-city"]],
|
|
1435
|
+
["latitude", ["x-vercel-ip-latitude", "cloudfront-viewer-latitude"]],
|
|
1436
|
+
["longitude", ["x-vercel-ip-longitude", "cloudfront-viewer-longitude"]],
|
|
1437
|
+
["postalCode", ["x-vercel-ip-postal-code", "cloudfront-viewer-postal-code"]],
|
|
1402
1438
|
["asn", ["cloudfront-viewer-asn"]],
|
|
1403
1439
|
["tlsVersion", ["cloudfront-viewer-tls"]],
|
|
1404
1440
|
["httpVersion", ["cloudfront-viewer-http-version"]],
|
|
@@ -1433,19 +1469,25 @@ function deriveConnectionFromHeaders(headers) {
|
|
|
1433
1469
|
}
|
|
1434
1470
|
}
|
|
1435
1471
|
}
|
|
1436
|
-
|
|
1472
|
+
{
|
|
1437
1473
|
const addr = lower["cloudfront-viewer-address"]?.trim();
|
|
1438
|
-
|
|
1474
|
+
const portMatch = addr?.match(/:(\d+)$/);
|
|
1475
|
+
if (portMatch) connection.sourcePort = portMatch[1];
|
|
1476
|
+
if (!connection.ip && addr) connection.ip = addr.replace(/:\d+$/, "");
|
|
1439
1477
|
}
|
|
1440
1478
|
if (!connection.ip) {
|
|
1441
1479
|
const xff = lower["x-forwarded-for"];
|
|
1442
1480
|
const client = xff?.split(",")[0]?.trim();
|
|
1443
1481
|
if (client) connection.ip = client;
|
|
1444
1482
|
}
|
|
1483
|
+
if (!connection.tlsCipher) {
|
|
1484
|
+
const cipher = connection.tlsVersion?.split(":")[1];
|
|
1485
|
+
if (cipher) connection.tlsCipher = cipher;
|
|
1486
|
+
}
|
|
1445
1487
|
return Object.keys(connection).length > 0 ? connection : void 0;
|
|
1446
1488
|
}
|
|
1447
1489
|
function buildSdkObservedMetadata(rawHeaders) {
|
|
1448
|
-
const { headers, apiKeyFormat, platformHeaders } = sanitizeHeaders(rawHeaders);
|
|
1490
|
+
const { headers, apiKeyFormat, platformHeaders, cookieCount } = sanitizeHeaders(rawHeaders);
|
|
1449
1491
|
const flat = {};
|
|
1450
1492
|
if (rawHeaders) {
|
|
1451
1493
|
for (const name of Object.keys(rawHeaders)) {
|
|
@@ -1460,6 +1502,7 @@ function buildSdkObservedMetadata(rawHeaders) {
|
|
|
1460
1502
|
...apiKeyFormat && { apiKeyFormat },
|
|
1461
1503
|
...platformHeaders && { platformHeaders },
|
|
1462
1504
|
...connection && { connection },
|
|
1505
|
+
...cookieCount !== void 0 && { cookieCount },
|
|
1463
1506
|
schemaVersion: CAPTURE_SCHEMA_VERSION
|
|
1464
1507
|
};
|
|
1465
1508
|
}
|
|
@@ -1504,7 +1547,7 @@ async function fetchEdgeConfig(config, counterpartyId, opts) {
|
|
|
1504
1547
|
}
|
|
1505
1548
|
if (opts?.etag) headers["If-None-Match"] = opts.etag;
|
|
1506
1549
|
try {
|
|
1507
|
-
const response = await
|
|
1550
|
+
const response = await sdkFetch(
|
|
1508
1551
|
`${config.apiBaseUrl}/endpoints/${encodeURIComponent(counterpartyId)}/edge-config`,
|
|
1509
1552
|
{ method: "GET", headers, signal: AbortSignal.timeout(opts?.timeoutMs ?? 5e3) }
|
|
1510
1553
|
);
|
|
@@ -1630,12 +1673,43 @@ var PLATFORM_AGENT_SIGNATURES = [
|
|
|
1630
1673
|
uaPatterns: [/perplexity/i],
|
|
1631
1674
|
agentCardPatterns: [/perplexity\.ai/i],
|
|
1632
1675
|
apiKeyFormatPatterns: [/^pplx-/i]
|
|
1676
|
+
},
|
|
1677
|
+
// Agentic browsers — versioned-token patterns ONLY (a stock Chrome UA must
|
|
1678
|
+
// never match). Distinct vendor keys (not 'chatgpt'/'perplexity'): the
|
|
1679
|
+
// browser product is a different surface than the assistant service, and
|
|
1680
|
+
// the DB registry mirrors one row per vendor. These sit after the primary
|
|
1681
|
+
// vendor entries so a UA carrying an explicit vendor token keeps its
|
|
1682
|
+
// primary attribution; a browser-shaped UA with the agentic token is
|
|
1683
|
+
// caught here BEFORE classify's human tier, which is what makes these
|
|
1684
|
+
// visits observable at all. Token drift is real (some builds mimic Chrome
|
|
1685
|
+
// outright) — re-verify against captured events when a new browser ships,
|
|
1686
|
+
// and check `sec-ch-ua` platformHeaders for the real brand.
|
|
1687
|
+
{
|
|
1688
|
+
vendor: "chatgpt-atlas",
|
|
1689
|
+
displayName: "ChatGPT Atlas browser",
|
|
1690
|
+
uaPatterns: [/\batlas\/\d/i],
|
|
1691
|
+
headerPatterns: [/^sec-ch-ua: .*atlas/i]
|
|
1692
|
+
},
|
|
1693
|
+
{
|
|
1694
|
+
vendor: "perplexity-comet",
|
|
1695
|
+
displayName: "Perplexity Comet browser",
|
|
1696
|
+
uaPatterns: [/\bcomet\/\d/i],
|
|
1697
|
+
headerPatterns: [/^sec-ch-ua: .*comet/i]
|
|
1698
|
+
},
|
|
1699
|
+
// Our own SDK self-identifies (sdkFetch stamps this UA) — first-party
|
|
1700
|
+
// traffic must never pollute the unknown/anonymous pool it exists to audit.
|
|
1701
|
+
{
|
|
1702
|
+
vendor: "astrasync-sdk",
|
|
1703
|
+
displayName: "AstraSync SDK",
|
|
1704
|
+
uaPatterns: [/^astrasync-sdk\//i]
|
|
1633
1705
|
}
|
|
1634
1706
|
];
|
|
1635
1707
|
function matchPlatformSignature(signatures, input) {
|
|
1636
1708
|
const ua = input.userAgent ?? "";
|
|
1637
1709
|
const cardUrl = input.agentCardUrl ?? "";
|
|
1638
1710
|
const apiKeyFormat = input.apiKeyFormat ?? "";
|
|
1711
|
+
const ja4 = input.ja4 ?? "";
|
|
1712
|
+
const asn = input.asn ?? "";
|
|
1639
1713
|
const headerLines = [];
|
|
1640
1714
|
if (input.platformHeaders) {
|
|
1641
1715
|
for (const [name, value] of Object.entries(input.platformHeaders)) {
|
|
@@ -1647,7 +1721,9 @@ function matchPlatformSignature(signatures, input) {
|
|
|
1647
1721
|
const cardMatch = sig.agentCardPatterns?.some((p) => p.test(cardUrl));
|
|
1648
1722
|
const keyMatch = apiKeyFormat.length > 0 && sig.apiKeyFormatPatterns?.some((p) => p.test(apiKeyFormat));
|
|
1649
1723
|
const headerMatch = headerLines.length > 0 && sig.headerPatterns?.some((p) => headerLines.some((line) => p.test(line)));
|
|
1650
|
-
|
|
1724
|
+
const ja4Match = ja4.length > 0 && sig.ja4Patterns?.some((p) => p.test(ja4));
|
|
1725
|
+
const asnMatch = asn.length > 0 && sig.asnList?.includes(asn);
|
|
1726
|
+
if (uaMatch || cardMatch || keyMatch || headerMatch || ja4Match || asnMatch) {
|
|
1651
1727
|
const uaBase = ua.split(/[\s/]/)[0]?.toLowerCase() ?? "";
|
|
1652
1728
|
const cardHost = (() => {
|
|
1653
1729
|
try {
|
|
@@ -1656,7 +1732,7 @@ function matchPlatformSignature(signatures, input) {
|
|
|
1656
1732
|
return "";
|
|
1657
1733
|
}
|
|
1658
1734
|
})();
|
|
1659
|
-
const keyBasis = uaBase || cardHost || apiKeyFormat || "unknown";
|
|
1735
|
+
const keyBasis = uaBase || cardHost || apiKeyFormat || ja4 || asn && `asn${asn}` || "unknown";
|
|
1660
1736
|
return {
|
|
1661
1737
|
vendor: sig.vendor,
|
|
1662
1738
|
fingerprintKey: `${sig.vendor}:${keyBasis}`,
|
|
@@ -3487,7 +3563,7 @@ async function fetchUCPManifest(manifestUrl, options = {}) {
|
|
|
3487
3563
|
const controller = new AbortController();
|
|
3488
3564
|
const timer = setTimeout(() => controller.abort(), timeoutMs);
|
|
3489
3565
|
try {
|
|
3490
|
-
const res = await
|
|
3566
|
+
const res = await sdkFetch(manifestUrl, { signal: controller.signal });
|
|
3491
3567
|
if (!res.ok) return null;
|
|
3492
3568
|
return await res.json();
|
|
3493
3569
|
} catch {
|
|
@@ -6032,7 +6108,7 @@ var AstraSync = class {
|
|
|
6032
6108
|
*/
|
|
6033
6109
|
async pollRegistration(requestId) {
|
|
6034
6110
|
const url = `${this.baseUrl}/api/agents/request-registration/${requestId}`;
|
|
6035
|
-
const res = await
|
|
6111
|
+
const res = await sdkFetch(url, { headers: { Accept: "application/json" } });
|
|
6036
6112
|
if (!res.ok) {
|
|
6037
6113
|
const errBody = await res.json().catch(() => ({}));
|
|
6038
6114
|
throw new AstraSyncError(
|
|
@@ -6089,7 +6165,7 @@ var AstraSync = class {
|
|
|
6089
6165
|
* Check API health.
|
|
6090
6166
|
*/
|
|
6091
6167
|
async health() {
|
|
6092
|
-
const res = await
|
|
6168
|
+
const res = await sdkFetch(`${this.baseUrl}/api/health/`);
|
|
6093
6169
|
if (!res.ok) {
|
|
6094
6170
|
throw new AstraSyncError(`Health check failed: ${res.status}`, res.status);
|
|
6095
6171
|
}
|
|
@@ -6116,7 +6192,7 @@ var AstraSync = class {
|
|
|
6116
6192
|
const signature = await this.signRequest(method, endpoint, body || {});
|
|
6117
6193
|
headers["X-AstraSync-Signature"] = signature;
|
|
6118
6194
|
}
|
|
6119
|
-
const res = await
|
|
6195
|
+
const res = await sdkFetch(url, {
|
|
6120
6196
|
method,
|
|
6121
6197
|
headers,
|
|
6122
6198
|
...body ? { body: JSON.stringify(body) } : {}
|
|
@@ -6141,7 +6217,7 @@ var AstraSync = class {
|
|
|
6141
6217
|
if (this.cachedJwt && this.jwtExpiresAt && Date.now() < this.jwtExpiresAt) {
|
|
6142
6218
|
return this.cachedJwt;
|
|
6143
6219
|
}
|
|
6144
|
-
const res = await
|
|
6220
|
+
const res = await sdkFetch(`${this.baseUrl}/api/auth/login`, {
|
|
6145
6221
|
method: "POST",
|
|
6146
6222
|
headers: { "Content-Type": "application/json" },
|
|
6147
6223
|
body: JSON.stringify({ email: this.email, password: this.password })
|
|
@@ -6284,7 +6360,7 @@ var AgentClient = class _AgentClient {
|
|
|
6284
6360
|
const url = `${this.apiBaseUrl.replace(/\/+$/, "")}/api/agents/${encodeURIComponent(
|
|
6285
6361
|
this.credentials.agentId
|
|
6286
6362
|
)}/ownership`;
|
|
6287
|
-
const resp = await
|
|
6363
|
+
const resp = await sdkFetch(url, {
|
|
6288
6364
|
method: "GET",
|
|
6289
6365
|
headers: {
|
|
6290
6366
|
Authorization: `Bearer ${this.apiKey}`,
|
|
@@ -6322,7 +6398,7 @@ var AgentClient = class _AgentClient {
|
|
|
6322
6398
|
}
|
|
6323
6399
|
}
|
|
6324
6400
|
const enrichedHeaders = setHttpHeaders(existingHeaders, creds);
|
|
6325
|
-
return
|
|
6401
|
+
return sdkFetch(url, {
|
|
6326
6402
|
...fetchOptions,
|
|
6327
6403
|
headers: enrichedHeaders
|
|
6328
6404
|
});
|
|
@@ -6511,7 +6587,7 @@ async function recordDecision2(config, params) {
|
|
|
6511
6587
|
if (config.customHeaders) {
|
|
6512
6588
|
Object.assign(headers, config.customHeaders);
|
|
6513
6589
|
}
|
|
6514
|
-
const response = await
|
|
6590
|
+
const response = await sdkFetch(url, {
|
|
6515
6591
|
method: "POST",
|
|
6516
6592
|
headers,
|
|
6517
6593
|
body: JSON.stringify(body)
|
|
@@ -6528,6 +6604,51 @@ async function recordDecision2(config, params) {
|
|
|
6528
6604
|
blockchainTxHash: result.blockchainTxHash
|
|
6529
6605
|
};
|
|
6530
6606
|
}
|
|
6607
|
+
|
|
6608
|
+
// src/runtime-signatures.ts
|
|
6609
|
+
var RUNTIME_SIGNATURES = [
|
|
6610
|
+
{
|
|
6611
|
+
runtime: "browser-automation",
|
|
6612
|
+
displayName: "Browser automation",
|
|
6613
|
+
uaPatterns: [/headless/i, /phantomjs/i, /selenium/i, /playwright/i, /puppeteer/i]
|
|
6614
|
+
},
|
|
6615
|
+
{
|
|
6616
|
+
runtime: "nodejs",
|
|
6617
|
+
displayName: "Node.js runtime",
|
|
6618
|
+
// `node` exactly is the global-fetch default UA; the token forms cover
|
|
6619
|
+
// the common Node HTTP libraries.
|
|
6620
|
+
uaPatterns: [/^node$/i, /^undici/i, /node-fetch/i, /^axios/i, /^got\b/i, /needle/i]
|
|
6621
|
+
},
|
|
6622
|
+
{
|
|
6623
|
+
runtime: "python",
|
|
6624
|
+
displayName: "Python runtime",
|
|
6625
|
+
uaPatterns: [/python-requests/i, /python-urllib/i, /^python\b/i, /httpx/i, /aiohttp/i]
|
|
6626
|
+
},
|
|
6627
|
+
{ runtime: "go", displayName: "Go runtime", uaPatterns: [/go-http-client/i] },
|
|
6628
|
+
{
|
|
6629
|
+
runtime: "java",
|
|
6630
|
+
displayName: "Java runtime",
|
|
6631
|
+
uaPatterns: [/^java\//i, /okhttp/i, /apache-httpclient/i]
|
|
6632
|
+
},
|
|
6633
|
+
{ runtime: "curl", displayName: "curl", uaPatterns: [/^curl\//i] },
|
|
6634
|
+
{ runtime: "wget", displayName: "wget", uaPatterns: [/^wget\//i] },
|
|
6635
|
+
{ runtime: "ruby", displayName: "Ruby runtime", uaPatterns: [/^ruby\b/i, /faraday/i] },
|
|
6636
|
+
{
|
|
6637
|
+
runtime: "php",
|
|
6638
|
+
displayName: "PHP runtime",
|
|
6639
|
+
uaPatterns: [/^php\b/i, /guzzlehttp/i, /^symfony/i]
|
|
6640
|
+
},
|
|
6641
|
+
{ runtime: "dotnet", displayName: ".NET runtime", uaPatterns: [/^dotnet/i, /httpclient/i] },
|
|
6642
|
+
{ runtime: "dart", displayName: "Dart runtime", uaPatterns: [/^dart/i] }
|
|
6643
|
+
];
|
|
6644
|
+
function detectRuntime(userAgent) {
|
|
6645
|
+
if (!userAgent) return void 0;
|
|
6646
|
+
const ua = userAgent.trim();
|
|
6647
|
+
for (const sig of RUNTIME_SIGNATURES) {
|
|
6648
|
+
if (sig.uaPatterns.some((p) => p.test(ua))) return sig.displayName;
|
|
6649
|
+
}
|
|
6650
|
+
return void 0;
|
|
6651
|
+
}
|
|
6531
6652
|
// Annotate the CommonJS export names for ESM import in node:
|
|
6532
6653
|
0 && (module.exports = {
|
|
6533
6654
|
ACCESS_LEVEL_DESCRIPTIONS,
|
|
@@ -6545,9 +6666,11 @@ async function recordDecision2(config, params) {
|
|
|
6545
6666
|
MAX_HEADER_VALUE_BYTES,
|
|
6546
6667
|
MAX_TOTAL_BYTES,
|
|
6547
6668
|
PLATFORM_AGENT_SIGNATURES,
|
|
6669
|
+
RUNTIME_SIGNATURES,
|
|
6548
6670
|
RegistrationDeniedError,
|
|
6549
6671
|
RegistrationExpiredError,
|
|
6550
6672
|
RegistrationTimeoutError,
|
|
6673
|
+
SDK_USER_AGENT,
|
|
6551
6674
|
TRUST_LEVEL_RANGES,
|
|
6552
6675
|
VERSION,
|
|
6553
6676
|
_resetEdgeConfigCache,
|
|
@@ -6561,6 +6684,7 @@ async function recordDecision2(config, params) {
|
|
|
6561
6684
|
degradeToObserve,
|
|
6562
6685
|
deriveConnectionFromHeaders,
|
|
6563
6686
|
detectPlatformFingerprint,
|
|
6687
|
+
detectRuntime,
|
|
6564
6688
|
determineAccessLevel,
|
|
6565
6689
|
express,
|
|
6566
6690
|
extractApiKeyFormat,
|
|
@@ -6589,6 +6713,7 @@ async function recordDecision2(config, params) {
|
|
|
6589
6713
|
reportUnregisteredAttempt,
|
|
6590
6714
|
sanitizeHeaders,
|
|
6591
6715
|
sdk,
|
|
6716
|
+
sdkFetch,
|
|
6592
6717
|
setMcpMeta,
|
|
6593
6718
|
transport,
|
|
6594
6719
|
verify
|