@astrasyncai/verification-gateway 5.21.1 → 5.22.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/CHANGELOG.md +16 -0
- package/README.md +19 -7
- package/dist/adapters/express.js +75 -9
- package/dist/adapters/express.js.map +1 -1
- package/dist/adapters/express.mjs +75 -9
- package/dist/adapters/express.mjs.map +1 -1
- package/dist/adapters/mcp.js +34 -3
- package/dist/adapters/mcp.js.map +1 -1
- package/dist/adapters/mcp.mjs +34 -3
- package/dist/adapters/mcp.mjs.map +1 -1
- package/dist/adapters/nextjs.js +75 -9
- package/dist/adapters/nextjs.js.map +1 -1
- package/dist/adapters/nextjs.mjs +75 -9
- package/dist/adapters/nextjs.mjs.map +1 -1
- package/dist/adapters/sdk.js +1 -1
- package/dist/adapters/sdk.js.map +1 -1
- package/dist/adapters/sdk.mjs +1 -1
- package/dist/adapters/sdk.mjs.map +1 -1
- package/dist/agent/index.js +1 -1
- package/dist/agent/index.js.map +1 -1
- package/dist/agent/index.mjs +1 -1
- package/dist/agent/index.mjs.map +1 -1
- package/dist/bin/astrasync-claude-hook.js +1 -1
- package/dist/bin/astrasync-codex-hook.js +1 -1
- package/dist/bin/astrasync-guard.js +1 -1
- package/dist/bin/astrasync.js +1 -1
- package/dist/browser/background.js +1 -1
- package/dist/browser/background.js.map +1 -1
- package/dist/browser/background.mjs +1 -1
- package/dist/browser/background.mjs.map +1 -1
- package/dist/cli/index.js +1 -1
- package/dist/cli/index.js.map +1 -1
- package/dist/cli/index.mjs +1 -1
- package/dist/cli/index.mjs.map +1 -1
- package/dist/codex/index.js +1 -1
- package/dist/codex/index.js.map +1 -1
- package/dist/codex/index.mjs +1 -1
- package/dist/codex/index.mjs.map +1 -1
- package/dist/cursor/extension.js +1 -1
- package/dist/cursor/extension.js.map +1 -1
- package/dist/cursor/extension.mjs +1 -1
- package/dist/cursor/extension.mjs.map +1 -1
- package/dist/edge-config.js +1 -1
- package/dist/edge-config.js.map +1 -1
- package/dist/edge-config.mjs +1 -1
- package/dist/edge-config.mjs.map +1 -1
- package/dist/edge-core/index.d.mts +4 -1
- package/dist/edge-core/index.d.ts +4 -1
- package/dist/edge-core/index.js +60 -13
- package/dist/edge-core/index.js.map +1 -1
- package/dist/edge-core/index.mjs +60 -13
- package/dist/edge-core/index.mjs.map +1 -1
- package/dist/gateway/gateway.js +1 -1
- package/dist/gateway/gateway.js.map +1 -1
- package/dist/gateway/gateway.mjs +1 -1
- package/dist/gateway/gateway.mjs.map +1 -1
- package/dist/index.d.mts +27 -6
- package/dist/index.d.ts +27 -6
- package/dist/index.js +75 -9
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +75 -9
- package/dist/index.mjs.map +1 -1
- package/dist/metadata-capture.d.mts +5 -3
- package/dist/metadata-capture.d.ts +5 -3
- package/dist/metadata-capture.js +33 -2
- package/dist/metadata-capture.js.map +1 -1
- package/dist/metadata-capture.mjs +33 -2
- package/dist/metadata-capture.mjs.map +1 -1
- package/dist/platform-signatures.d.mts +20 -1
- package/dist/platform-signatures.d.ts +20 -1
- package/dist/platform-signatures.js +41 -6
- package/dist/platform-signatures.js.map +1 -1
- package/dist/platform-signatures.mjs +41 -6
- package/dist/platform-signatures.mjs.map +1 -1
- package/dist/registration/index.js +1 -1
- package/dist/registration/index.js.map +1 -1
- package/dist/registration/index.mjs +1 -1
- package/dist/registration/index.mjs.map +1 -1
- package/dist/transport/index.js +1 -1
- package/dist/transport/index.js.map +1 -1
- package/dist/transport/index.mjs +1 -1
- package/dist/transport/index.mjs.map +1 -1
- package/dist/verify.js +1 -1
- package/dist/verify.js.map +1 -1
- package/dist/verify.mjs +1 -1
- package/dist/verify.mjs.map +1 -1
- package/package.json +3 -3
package/dist/index.d.mts
CHANGED
|
@@ -155,9 +155,11 @@ declare function extractPlatformHeaders(sanitized: Record<string, string> | unde
|
|
|
155
155
|
* `connection` keys the edge adapters populate natively, so SDK-only
|
|
156
156
|
* deployments still get IP / geo / TLS attribution. Precedence per key:
|
|
157
157
|
*
|
|
158
|
-
* - `ip`: `cf-connecting-ip` > `fastly-client-ip` > `
|
|
159
|
-
* `
|
|
160
|
-
* `x-forwarded-for`
|
|
158
|
+
* - `ip`: `cf-connecting-ip` > `fastly-client-ip` > `incap-client-ip`
|
|
159
|
+
* (Imperva) > `true-client-ip` (Akamai et al.) > `x-real-ip` >
|
|
160
|
+
* `cloudfront-viewer-address` (port stripped) > leftmost `x-forwarded-for`
|
|
161
|
+
* - Akamai `x-akamai-edgescape` fills country / region / city / lat / long /
|
|
162
|
+
* timeZone / asn / continent where no header above supplied them
|
|
161
163
|
* - `country`: `cf-ipcountry` > `x-vercel-ip-country` >
|
|
162
164
|
* `cloudfront-viewer-country` > `fastly-geo-country`
|
|
163
165
|
* - `region` / `city` / `timeZone`: Vercel then CloudFront viewer headers
|
|
@@ -5322,7 +5324,7 @@ declare function _resetEdgeConfigCache(): void;
|
|
|
5322
5324
|
* Pure regex — no Node built-ins, edge-safe. Detection is regex-only for
|
|
5323
5325
|
* v2.9 — TLS fingerprinting / behavioural signatures are deferred.
|
|
5324
5326
|
*/
|
|
5325
|
-
type PlatformAgentVendor = 'claude' | 'chatgpt' | 'gemini' | 'cursor' | 'goose' | 'perplexity' | 'chatgpt-atlas' | 'perplexity-comet' | 'astrasync-bridge' | 'astrasync-sdk' | 'unknown';
|
|
5327
|
+
type PlatformAgentVendor = 'claude' | 'chatgpt' | 'gemini' | 'cursor' | 'goose' | 'perplexity' | 'grok' | 'meta-ai' | 'chatgpt-atlas' | 'perplexity-comet' | 'astrasync-bridge' | 'astrasync-sdk' | 'unknown';
|
|
5326
5328
|
interface PlatformFingerprint {
|
|
5327
5329
|
vendor: PlatformAgentVendor;
|
|
5328
5330
|
/** A stable identifier used as the orphan-agent dedup key. */
|
|
@@ -5358,6 +5360,13 @@ interface PlatformDetectionInput {
|
|
|
5358
5360
|
* provider — registry validation rejects ASN-only signatures.
|
|
5359
5361
|
*/
|
|
5360
5362
|
asn?: string;
|
|
5363
|
+
/**
|
|
5364
|
+
* Round 31 — bot labels a customer's WAF attached to the request (AWS Bot
|
|
5365
|
+
* Control `…:bot:name:x`, Akamai Bot Manager bot name, Cloudflare
|
|
5366
|
+
* verified-bot category, Imperva client classification). Present only on
|
|
5367
|
+
* rows read from WAF security logs. Matched against `wafLabelPatterns`.
|
|
5368
|
+
*/
|
|
5369
|
+
wafLabels?: string[];
|
|
5361
5370
|
}
|
|
5362
5371
|
/**
|
|
5363
5372
|
* A signature definition, generic over the vendor key. The seed constant
|
|
@@ -5386,6 +5395,8 @@ interface PlatformSignatureDef<V extends string = string> {
|
|
|
5386
5395
|
ja4Patterns?: RegExp[];
|
|
5387
5396
|
/** Exact ASN strings this signature matches (never regex). */
|
|
5388
5397
|
asnList?: string[];
|
|
5398
|
+
/** Patterns tested against each WAF bot label (round 31; see PlatformDetectionInput.wafLabels). */
|
|
5399
|
+
wafLabelPatterns?: RegExp[];
|
|
5389
5400
|
}
|
|
5390
5401
|
/**
|
|
5391
5402
|
* A fingerprint whose vendor may be a dynamically-promoted (non-seed) key.
|
|
@@ -5402,6 +5413,16 @@ interface DynamicPlatformFingerprint {
|
|
|
5402
5413
|
* Patterns are intentionally permissive (case-insensitive substring match) since
|
|
5403
5414
|
* platform UA strings drift between versions. False positives are tolerable —
|
|
5404
5415
|
* the orphan record is informational, not enforcement.
|
|
5416
|
+
*
|
|
5417
|
+
* Round 31: `wafLabelPatterns` attribute rows read from a customer's WAF
|
|
5418
|
+
* security logs by the bot name THEIR WAF assigned; they never match inline
|
|
5419
|
+
* traffic (no labels there).
|
|
5420
|
+
*
|
|
5421
|
+
* NOT detectable here, by design (Oct 2026): Meta's Muse and OpenAI's Dots
|
|
5422
|
+
* publish no user agent and browse through real Chromium sessions that are
|
|
5423
|
+
* indistinguishable from a person's. There is no signature to find — don't
|
|
5424
|
+
* chase one. Verified identity (an ASTRA-id the agent presents) is the only
|
|
5425
|
+
* durable way to know such an agent is there; that is the product's point.
|
|
5405
5426
|
*/
|
|
5406
5427
|
declare const PLATFORM_AGENT_SIGNATURES: ReadonlyArray<PlatformSignatureDef<PlatformAgentVendor>>;
|
|
5407
5428
|
/**
|
|
@@ -5466,7 +5487,7 @@ declare function detectRuntime(userAgent: string | undefined | null): string | u
|
|
|
5466
5487
|
* silently (never throwing), so this is a no-op there — which is correct:
|
|
5467
5488
|
* in a browser the page's real UA is the honest identity.
|
|
5468
5489
|
*/
|
|
5469
|
-
declare const SDK_USER_AGENT = "astrasync-sdk/5.
|
|
5490
|
+
declare const SDK_USER_AGENT = "astrasync-sdk/5.22.0";
|
|
5470
5491
|
declare const sdkFetch: typeof fetch;
|
|
5471
5492
|
|
|
5472
5493
|
interface LocalPolicy {
|
|
@@ -5584,7 +5605,7 @@ declare function parseYaml(yamlContent: string): ParseResult;
|
|
|
5584
5605
|
* is fine — bumping both in the release-ceremony commit keeps them
|
|
5585
5606
|
* lockstep.
|
|
5586
5607
|
*/
|
|
5587
|
-
declare const SDK_VERSION = "5.
|
|
5608
|
+
declare const SDK_VERSION = "5.22.0";
|
|
5588
5609
|
|
|
5589
5610
|
/**
|
|
5590
5611
|
* 5.15.0 — the `UCP-Agent` request header (UCP 2026-08-25): an RFC 8941
|
package/dist/index.d.ts
CHANGED
|
@@ -155,9 +155,11 @@ declare function extractPlatformHeaders(sanitized: Record<string, string> | unde
|
|
|
155
155
|
* `connection` keys the edge adapters populate natively, so SDK-only
|
|
156
156
|
* deployments still get IP / geo / TLS attribution. Precedence per key:
|
|
157
157
|
*
|
|
158
|
-
* - `ip`: `cf-connecting-ip` > `fastly-client-ip` > `
|
|
159
|
-
* `
|
|
160
|
-
* `x-forwarded-for`
|
|
158
|
+
* - `ip`: `cf-connecting-ip` > `fastly-client-ip` > `incap-client-ip`
|
|
159
|
+
* (Imperva) > `true-client-ip` (Akamai et al.) > `x-real-ip` >
|
|
160
|
+
* `cloudfront-viewer-address` (port stripped) > leftmost `x-forwarded-for`
|
|
161
|
+
* - Akamai `x-akamai-edgescape` fills country / region / city / lat / long /
|
|
162
|
+
* timeZone / asn / continent where no header above supplied them
|
|
161
163
|
* - `country`: `cf-ipcountry` > `x-vercel-ip-country` >
|
|
162
164
|
* `cloudfront-viewer-country` > `fastly-geo-country`
|
|
163
165
|
* - `region` / `city` / `timeZone`: Vercel then CloudFront viewer headers
|
|
@@ -5322,7 +5324,7 @@ declare function _resetEdgeConfigCache(): void;
|
|
|
5322
5324
|
* Pure regex — no Node built-ins, edge-safe. Detection is regex-only for
|
|
5323
5325
|
* v2.9 — TLS fingerprinting / behavioural signatures are deferred.
|
|
5324
5326
|
*/
|
|
5325
|
-
type PlatformAgentVendor = 'claude' | 'chatgpt' | 'gemini' | 'cursor' | 'goose' | 'perplexity' | 'chatgpt-atlas' | 'perplexity-comet' | 'astrasync-bridge' | 'astrasync-sdk' | 'unknown';
|
|
5327
|
+
type PlatformAgentVendor = 'claude' | 'chatgpt' | 'gemini' | 'cursor' | 'goose' | 'perplexity' | 'grok' | 'meta-ai' | 'chatgpt-atlas' | 'perplexity-comet' | 'astrasync-bridge' | 'astrasync-sdk' | 'unknown';
|
|
5326
5328
|
interface PlatformFingerprint {
|
|
5327
5329
|
vendor: PlatformAgentVendor;
|
|
5328
5330
|
/** A stable identifier used as the orphan-agent dedup key. */
|
|
@@ -5358,6 +5360,13 @@ interface PlatformDetectionInput {
|
|
|
5358
5360
|
* provider — registry validation rejects ASN-only signatures.
|
|
5359
5361
|
*/
|
|
5360
5362
|
asn?: string;
|
|
5363
|
+
/**
|
|
5364
|
+
* Round 31 — bot labels a customer's WAF attached to the request (AWS Bot
|
|
5365
|
+
* Control `…:bot:name:x`, Akamai Bot Manager bot name, Cloudflare
|
|
5366
|
+
* verified-bot category, Imperva client classification). Present only on
|
|
5367
|
+
* rows read from WAF security logs. Matched against `wafLabelPatterns`.
|
|
5368
|
+
*/
|
|
5369
|
+
wafLabels?: string[];
|
|
5361
5370
|
}
|
|
5362
5371
|
/**
|
|
5363
5372
|
* A signature definition, generic over the vendor key. The seed constant
|
|
@@ -5386,6 +5395,8 @@ interface PlatformSignatureDef<V extends string = string> {
|
|
|
5386
5395
|
ja4Patterns?: RegExp[];
|
|
5387
5396
|
/** Exact ASN strings this signature matches (never regex). */
|
|
5388
5397
|
asnList?: string[];
|
|
5398
|
+
/** Patterns tested against each WAF bot label (round 31; see PlatformDetectionInput.wafLabels). */
|
|
5399
|
+
wafLabelPatterns?: RegExp[];
|
|
5389
5400
|
}
|
|
5390
5401
|
/**
|
|
5391
5402
|
* A fingerprint whose vendor may be a dynamically-promoted (non-seed) key.
|
|
@@ -5402,6 +5413,16 @@ interface DynamicPlatformFingerprint {
|
|
|
5402
5413
|
* Patterns are intentionally permissive (case-insensitive substring match) since
|
|
5403
5414
|
* platform UA strings drift between versions. False positives are tolerable —
|
|
5404
5415
|
* the orphan record is informational, not enforcement.
|
|
5416
|
+
*
|
|
5417
|
+
* Round 31: `wafLabelPatterns` attribute rows read from a customer's WAF
|
|
5418
|
+
* security logs by the bot name THEIR WAF assigned; they never match inline
|
|
5419
|
+
* traffic (no labels there).
|
|
5420
|
+
*
|
|
5421
|
+
* NOT detectable here, by design (Oct 2026): Meta's Muse and OpenAI's Dots
|
|
5422
|
+
* publish no user agent and browse through real Chromium sessions that are
|
|
5423
|
+
* indistinguishable from a person's. There is no signature to find — don't
|
|
5424
|
+
* chase one. Verified identity (an ASTRA-id the agent presents) is the only
|
|
5425
|
+
* durable way to know such an agent is there; that is the product's point.
|
|
5405
5426
|
*/
|
|
5406
5427
|
declare const PLATFORM_AGENT_SIGNATURES: ReadonlyArray<PlatformSignatureDef<PlatformAgentVendor>>;
|
|
5407
5428
|
/**
|
|
@@ -5466,7 +5487,7 @@ declare function detectRuntime(userAgent: string | undefined | null): string | u
|
|
|
5466
5487
|
* silently (never throwing), so this is a no-op there — which is correct:
|
|
5467
5488
|
* in a browser the page's real UA is the honest identity.
|
|
5468
5489
|
*/
|
|
5469
|
-
declare const SDK_USER_AGENT = "astrasync-sdk/5.
|
|
5490
|
+
declare const SDK_USER_AGENT = "astrasync-sdk/5.22.0";
|
|
5470
5491
|
declare const sdkFetch: typeof fetch;
|
|
5471
5492
|
|
|
5472
5493
|
interface LocalPolicy {
|
|
@@ -5584,7 +5605,7 @@ declare function parseYaml(yamlContent: string): ParseResult;
|
|
|
5584
5605
|
* is fine — bumping both in the release-ceremony commit keeps them
|
|
5585
5606
|
* lockstep.
|
|
5586
5607
|
*/
|
|
5587
|
-
declare const SDK_VERSION = "5.
|
|
5608
|
+
declare const SDK_VERSION = "5.22.0";
|
|
5588
5609
|
|
|
5589
5610
|
/**
|
|
5590
5611
|
* 5.15.0 — the `UCP-Agent` request header (UCP 2026-08-25): an RFC 8941
|
package/dist/index.js
CHANGED
|
@@ -229,7 +229,7 @@ function getTrustLevel(score) {
|
|
|
229
229
|
}
|
|
230
230
|
|
|
231
231
|
// src/version.ts
|
|
232
|
-
var SDK_VERSION = "5.
|
|
232
|
+
var SDK_VERSION = "5.22.0";
|
|
233
233
|
|
|
234
234
|
// src/http.ts
|
|
235
235
|
var SDK_USER_AGENT = `astrasync-sdk/${SDK_VERSION}`;
|
|
@@ -1404,7 +1404,11 @@ var PLATFORM_HEADER_NAMES = /* @__PURE__ */ new Set([
|
|
|
1404
1404
|
"x-goog-api-client",
|
|
1405
1405
|
"user-agent",
|
|
1406
1406
|
"x-agent-card-url",
|
|
1407
|
-
"x-agent-provider"
|
|
1407
|
+
"x-agent-provider",
|
|
1408
|
+
// Round 31 — Web Bot Auth's Signature-Agent names the signing agent's
|
|
1409
|
+
// directory host (a public URL, never a secret). It attributes a signed
|
|
1410
|
+
// agent even when its UA is stock Chrome.
|
|
1411
|
+
"signature-agent"
|
|
1408
1412
|
]);
|
|
1409
1413
|
var PLATFORM_HEADER_PREFIXES = [
|
|
1410
1414
|
"x-goog-",
|
|
@@ -1535,7 +1539,12 @@ function extractPlatformHeaders(sanitized) {
|
|
|
1535
1539
|
return out;
|
|
1536
1540
|
}
|
|
1537
1541
|
var CONNECTION_HEADER_SOURCES = [
|
|
1538
|
-
|
|
1542
|
+
// Round 31: `incap-client-ip` = Imperva Cloud WAF; `true-client-ip` is
|
|
1543
|
+
// also Akamai's client-IP header when the property enables it.
|
|
1544
|
+
[
|
|
1545
|
+
"ip",
|
|
1546
|
+
["cf-connecting-ip", "fastly-client-ip", "incap-client-ip", "true-client-ip", "x-real-ip"]
|
|
1547
|
+
],
|
|
1539
1548
|
[
|
|
1540
1549
|
"country",
|
|
1541
1550
|
["cf-ipcountry", "x-vercel-ip-country", "cloudfront-viewer-country", "fastly-geo-country"]
|
|
@@ -1586,6 +1595,28 @@ function deriveConnectionFromHeaders(headers) {
|
|
|
1586
1595
|
if (portMatch) connection.sourcePort = portMatch[1];
|
|
1587
1596
|
if (!connection.ip && addr) connection.ip = addr.replace(/:\d+$/, "");
|
|
1588
1597
|
}
|
|
1598
|
+
{
|
|
1599
|
+
const edgescape = (lower["x-akamai-edgescape"] ?? lower["akamai-edgescape"])?.trim();
|
|
1600
|
+
if (edgescape) {
|
|
1601
|
+
const fields = /* @__PURE__ */ new Map();
|
|
1602
|
+
for (const pair of edgescape.split(",")) {
|
|
1603
|
+
const i = pair.indexOf("=");
|
|
1604
|
+
if (i > 0) fields.set(pair.slice(0, i).trim().toLowerCase(), pair.slice(i + 1).trim());
|
|
1605
|
+
}
|
|
1606
|
+
const fill = (key, field) => {
|
|
1607
|
+
const v = fields.get(field);
|
|
1608
|
+
if (v && !connection[key]) connection[key] = v.slice(0, MAX_CONNECTION_VALUE_CHARS);
|
|
1609
|
+
};
|
|
1610
|
+
fill("country", "country_code");
|
|
1611
|
+
fill("region", "region_code");
|
|
1612
|
+
fill("city", "city");
|
|
1613
|
+
fill("latitude", "lat");
|
|
1614
|
+
fill("longitude", "long");
|
|
1615
|
+
fill("timeZone", "timezone");
|
|
1616
|
+
fill("asn", "asnum");
|
|
1617
|
+
fill("continent", "continent");
|
|
1618
|
+
}
|
|
1619
|
+
}
|
|
1589
1620
|
if (!connection.ip) {
|
|
1590
1621
|
const xff = lower["x-forwarded-for"];
|
|
1591
1622
|
const client = xff?.split(",")[0]?.trim();
|
|
@@ -2284,7 +2315,8 @@ var PLATFORM_AGENT_SIGNATURES = [
|
|
|
2284
2315
|
uaPatterns: [/claude/i, /anthropic/i],
|
|
2285
2316
|
agentCardPatterns: [/anthropic\.com/i, /claude\.ai/i],
|
|
2286
2317
|
apiKeyFormatPatterns: [/^sk-ant/i],
|
|
2287
|
-
headerPatterns: [/^anthropic-version/i, /^anthropic-beta/i, /^x-anthropic-/i]
|
|
2318
|
+
headerPatterns: [/^anthropic-version/i, /^anthropic-beta/i, /^x-anthropic-/i],
|
|
2319
|
+
wafLabelPatterns: [/\bclaude/i, /\banthropic/i]
|
|
2288
2320
|
},
|
|
2289
2321
|
{
|
|
2290
2322
|
vendor: "chatgpt",
|
|
@@ -2295,7 +2327,14 @@ var PLATFORM_AGENT_SIGNATURES = [
|
|
|
2295
2327
|
uaPatterns: [/chatgpt/i, /openai/i, /gpt-?\d/i, /\bGPTBot\b/i, /\bOAI-SearchBot\b/i],
|
|
2296
2328
|
agentCardPatterns: [/openai\.com/i, /chatgpt\.com/i],
|
|
2297
2329
|
apiKeyFormatPatterns: [/^sk-proj/i, /^sk-svcacct/i],
|
|
2298
|
-
headerPatterns: [
|
|
2330
|
+
headerPatterns: [
|
|
2331
|
+
/^openai-organization/i,
|
|
2332
|
+
/^openai-project/i,
|
|
2333
|
+
/^openai-version/i,
|
|
2334
|
+
// ChatGPT agent signs with Web Bot Auth under this directory host.
|
|
2335
|
+
/^signature-agent: "?https:\/\/chatgpt\.com/i
|
|
2336
|
+
],
|
|
2337
|
+
wafLabelPatterns: [/\bgptbot\b/i, /\bchatgpt/i, /\boai-searchbot\b/i, /\bopenai/i]
|
|
2299
2338
|
},
|
|
2300
2339
|
{
|
|
2301
2340
|
vendor: "gemini",
|
|
@@ -2316,7 +2355,8 @@ var PLATFORM_AGENT_SIGNATURES = [
|
|
|
2316
2355
|
],
|
|
2317
2356
|
agentCardPatterns: [/gemini\.google\.com/i, /ai\.google\.dev/i],
|
|
2318
2357
|
apiKeyFormatPatterns: [/^aiza/i],
|
|
2319
|
-
headerPatterns: [/^x-goog-user-project/i, /^x-goog-api-client/i]
|
|
2358
|
+
headerPatterns: [/^x-goog-user-project/i, /^x-goog-api-client/i],
|
|
2359
|
+
wafLabelPatterns: [/\bgoogle-extended\b/i, /\bgoogleother\b/i, /\bgemini/i]
|
|
2320
2360
|
},
|
|
2321
2361
|
{
|
|
2322
2362
|
vendor: "cursor",
|
|
@@ -2335,7 +2375,31 @@ var PLATFORM_AGENT_SIGNATURES = [
|
|
|
2335
2375
|
displayName: "Perplexity",
|
|
2336
2376
|
uaPatterns: [/perplexity/i],
|
|
2337
2377
|
agentCardPatterns: [/perplexity\.ai/i],
|
|
2338
|
-
apiKeyFormatPatterns: [/^pplx-/i]
|
|
2378
|
+
apiKeyFormatPatterns: [/^pplx-/i],
|
|
2379
|
+
wafLabelPatterns: [/\bperplexity/i]
|
|
2380
|
+
},
|
|
2381
|
+
// Round 30.1: xAI's documented crawlers (GrokBot/1.0, xAI-Grok/1.0,
|
|
2382
|
+
// Grok-DeepSearch/1.0). Anchored, versioned tokens — never in a stock UA.
|
|
2383
|
+
{
|
|
2384
|
+
vendor: "grok",
|
|
2385
|
+
displayName: "xAI Grok",
|
|
2386
|
+
uaPatterns: [/\bGrokBot\//i, /\bxAI-Grok\//i, /\bGrok-DeepSearch\//i],
|
|
2387
|
+
agentCardPatterns: [/\bx\.ai\b/i, /grok\.com/i],
|
|
2388
|
+
apiKeyFormatPatterns: [/^xai-/i],
|
|
2389
|
+
wafLabelPatterns: [/\bgrok/i, /\bxai\b/i]
|
|
2390
|
+
},
|
|
2391
|
+
// Round 30.1: Meta AI's index and fetch crawlers. facebookexternalhit
|
|
2392
|
+
// (link previews) is deliberately NOT here — it stays a generic crawler.
|
|
2393
|
+
{
|
|
2394
|
+
vendor: "meta-ai",
|
|
2395
|
+
displayName: "Meta AI",
|
|
2396
|
+
uaPatterns: [/\bMeta-WebIndexer\b/i, /\bMeta-ExternalFetcher\b/i],
|
|
2397
|
+
agentCardPatterns: [/meta\.ai/i],
|
|
2398
|
+
wafLabelPatterns: [
|
|
2399
|
+
/\bmeta-webindexer\b/i,
|
|
2400
|
+
/\bmeta-externalfetcher\b/i,
|
|
2401
|
+
/\bmeta-externalagent\b/i
|
|
2402
|
+
]
|
|
2339
2403
|
},
|
|
2340
2404
|
// Agentic browsers — versioned-token patterns ONLY (a stock Chrome UA must
|
|
2341
2405
|
// never match). Distinct vendor keys (not 'chatgpt'/'perplexity'): the
|
|
@@ -2383,6 +2447,7 @@ function matchPlatformSignature(signatures, input) {
|
|
|
2383
2447
|
const apiKeyFormat = input.apiKeyFormat ?? "";
|
|
2384
2448
|
const ja4 = input.ja4 ?? "";
|
|
2385
2449
|
const asn = input.asn ?? "";
|
|
2450
|
+
const wafLabels = input.wafLabels ?? [];
|
|
2386
2451
|
const headerLines = [];
|
|
2387
2452
|
if (input.platformHeaders) {
|
|
2388
2453
|
for (const [name, value] of Object.entries(input.platformHeaders)) {
|
|
@@ -2396,7 +2461,8 @@ function matchPlatformSignature(signatures, input) {
|
|
|
2396
2461
|
const headerMatch = headerLines.length > 0 && sig.headerPatterns?.some((p) => headerLines.some((line) => p.test(line)));
|
|
2397
2462
|
const ja4Match = ja4.length > 0 && sig.ja4Patterns?.some((p) => p.test(ja4));
|
|
2398
2463
|
const asnMatch = asn.length > 0 && sig.asnList?.includes(asn);
|
|
2399
|
-
|
|
2464
|
+
const wafMatch = wafLabels.length > 0 && sig.wafLabelPatterns?.some((p) => wafLabels.some((label) => p.test(label)));
|
|
2465
|
+
if (uaMatch || cardMatch || keyMatch || headerMatch || ja4Match || asnMatch || wafMatch) {
|
|
2400
2466
|
const uaBase = ua.split(/[\s/]/)[0]?.toLowerCase() ?? "";
|
|
2401
2467
|
const cardHost = (() => {
|
|
2402
2468
|
try {
|
|
@@ -2405,7 +2471,7 @@ function matchPlatformSignature(signatures, input) {
|
|
|
2405
2471
|
return "";
|
|
2406
2472
|
}
|
|
2407
2473
|
})();
|
|
2408
|
-
const keyBasis = uaBase || cardHost || apiKeyFormat || ja4 || asn && `asn${asn}` || "unknown";
|
|
2474
|
+
const keyBasis = uaBase || cardHost || apiKeyFormat || ja4 || asn && `asn${asn}` || wafMatch && `waf:${wafLabels[0]?.toLowerCase()}` || "unknown";
|
|
2409
2475
|
return {
|
|
2410
2476
|
vendor: sig.vendor,
|
|
2411
2477
|
fingerprintKey: `${sig.vendor}:${keyBasis}`,
|