{"version":3,"sources":["../src/server/timezone.ts","../src/userAgent.ts","../src/server/tls.ts","../src/server/analysis.ts","../src/server/geoip.ts","../src/server/ipLists.ts","../src/server/enrich.ts","../src/automation.ts","../src/server/scoring.ts","../src/version.ts"],"names":["lookup","tail","groups","path","fileURLToPath","fs"],"mappings":"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","file":"server.cjs","sourcesContent":["const MINUTES_PER_HOUR = 60;\n\n/** Current UTC offset in minutes for an IANA timezone, or `null` when unknown. */\nexport function getTimezoneOffsetMinutes(\n  timeZone: string,\n  at: Date = new Date(),\n): number | null {\n  try {\n    const formatter = new Intl.DateTimeFormat(\"en-US\", {\n      timeZone,\n      timeZoneName: \"shortOffset\",\n    });\n    const parts = formatter.formatToParts(at);\n    const offsetPart = parts.find((part) => part.type === \"timeZoneName\")?.value;\n\n    if (!offsetPart) {\n      return null;\n    }\n\n    const match = offsetPart.match(/GMT([+-])(\\d{1,2})(?::?(\\d{2}))?/);\n    if (!match) {\n      return offsetPart === \"GMT\" ? 0 : null;\n    }\n\n    const sign = match[1] === \"-\" ? -1 : 1;\n    const hours = Number(match[2]);\n    const minutes = Number(match[3] ?? \"0\");\n\n    return sign * (hours * MINUTES_PER_HOUR + minutes);\n  } catch {\n    return null;\n  }\n}\n\n/**\n * Whether the client-reported timezone disagrees with the GeoIP timezone by\n * more than `toleranceMinutes` of UTC offset. Different zone names with the\n * same offset (e.g. `Europe/Paris` vs `Europe/Berlin`) do not mismatch.\n */\nexport function isTimezoneMismatch(\n  ipTimezone: string | undefined,\n  clientTimezone: string | undefined,\n  toleranceMinutes = 60,\n): boolean {\n  if (!ipTimezone || !clientTimezone) {\n    return false;\n  }\n\n  if (ipTimezone === clientTimezone) {\n    return false;\n  }\n\n  const ipOffset = getTimezoneOffsetMinutes(ipTimezone);\n  const clientOffset = getTimezoneOffsetMinutes(clientTimezone);\n\n  if (ipOffset === null || clientOffset === null) {\n    return false;\n  }\n\n  return Math.abs(ipOffset - clientOffset) > toleranceMinutes;\n}\n\nconst ACCEPT_LANGUAGE_Q_VALUE = /^(?:0(?:\\.\\d{0,3})?|1(?:\\.0{0,3})?)$/;\n\n/** Quality (`q`) parameter from an Accept-Language item; invalid q-values mean not usable. */\nfunction getAcceptLanguageQuality(parameters: string[]): number {\n  const qualityParameter = parameters\n    .map((parameter) => parameter.trim())\n    .find((parameter) => parameter.toLowerCase().startsWith(\"q=\"));\n\n  if (!qualityParameter) {\n    return 1;\n  }\n\n  const qualityText = qualityParameter.slice(2).trim();\n\n  return ACCEPT_LANGUAGE_Q_VALUE.test(qualityText) ? Number(qualityText) : 0;\n}\n\nfunction parseAcceptLanguageTags(acceptLanguage: string): string[] {\n  return acceptLanguage\n    .split(\",\")\n    .map((part) => {\n      const [rawTag, ...parameters] = part.trim().split(\";\");\n      const tag = rawTag.trim().toLowerCase().replace(/_/g, \"-\");\n      const quality = getAcceptLanguageQuality(parameters);\n\n      return tag.length > 0 && quality > 0 ? tag : undefined;\n    })\n    .filter((tag): tag is string => tag !== undefined);\n}\n\n/** Alpha-2 country region from a BCP 47 tag; numeric macroregions are not country claims. */\nfunction getRegionSubtag(languageTag: string): string | undefined {\n  try {\n    const region = new Intl.Locale(languageTag).region?.toLowerCase();\n\n    return region && /^[a-z]{2}$/.test(region) ? region : undefined;\n  } catch {\n    return undefined;\n  }\n}\n\n/**\n * Whether no Accept-Language alpha-2 country region matches the GeoIP country.\n * Region-less headers (plain `en`) and acceptable wildcards never mismatch.\n */\nexport function isAcceptLanguageGeoMismatch(\n  acceptLanguage: string | undefined,\n  ipCountry: string | undefined,\n): boolean {\n  if (!acceptLanguage || !ipCountry) {\n    return false;\n  }\n\n  const country = ipCountry.toLowerCase();\n  const tags = parseAcceptLanguageTags(acceptLanguage);\n\n  if (tags.includes(\"*\")) {\n    return false;\n  }\n\n  const regions = tags\n    .map(getRegionSubtag)\n    .filter((region): region is string => region !== undefined);\n\n  // Region-less tags like plain `en` carry no location claim — not enough\n  // information to call a mismatch.\n  if (regions.length === 0) {\n    return false;\n  }\n\n  return !regions.includes(country);\n}\n\n/** Datacenter/hosting IP presenting a residential browser User-Agent. */\nexport function isDatacenterBrowserMismatch(\n  isDatacenterIp: boolean | undefined,\n  userAgent: string | undefined,\n): boolean {\n  if (!isDatacenterIp) {\n    return false;\n  }\n\n  return /Mozilla\\/5\\.0 \\(/i.test(userAgent ?? \"\");\n}\n","export type ScriptingUserAgentKind = \"curl\" | \"python\" | \"go\" | \"java\";\n\nconst SCRIPTING_USER_AGENT_PATTERNS: Array<{\n  kind: ScriptingUserAgentKind;\n  pattern: RegExp;\n}> = [\n  {\n    kind: \"curl\",\n    pattern: /(?:^|[\\s;(])curl\\/\\d+(?:\\.\\d+)*(?=$|[\\s;)])/i,\n  },\n  {\n    kind: \"python\",\n    pattern:\n      /(?:^|[\\s;(])(?:python-requests|urllib3|python-urllib|aiohttp|httpx)\\/\\d+(?:\\.\\d+)*(?=$|[\\s;)])/i,\n  },\n  {\n    kind: \"go\",\n    pattern: /(?:^|[\\s;(])Go-http-client\\/\\d+(?:\\.\\d+)*(?=$|[\\s;)])/i,\n  },\n  {\n    kind: \"java\",\n    pattern:\n      /(?:^|[\\s;(])(?:Java|Java-http-client|Apache-HttpClient|okhttp)\\/\\d+(?:[._]\\d+)*(?=$|[\\s;)])/i,\n  },\n];\n\nexport type BotUserAgentKind =\n  | \"crawler\"\n  | \"http-client\"\n  | \"browser-automation\"\n  | \"playwright\"\n  | \"puppeteer\"\n  | \"selenium\"\n  | \"phantomjs\";\n\nconst BOT_USER_AGENT_PATTERNS: Array<{\n  kind: BotUserAgentKind;\n  pattern: RegExp;\n}> = [\n  {\n    kind: \"crawler\",\n    pattern:\n      /(?:^|[\\s;(])(?:Googlebot(?:-[A-Za-z]+)?|Google-InspectionTool|GoogleOther(?:-[A-Za-z]+)?|bingbot|Baiduspider|YandexBot|DuckDuckBot|Applebot|PetalBot|AhrefsBot|SemrushBot|GPTBot|OAI-SearchBot|ChatGPT-User|ClaudeBot|Claude-SearchBot|Amazonbot|Bytespider|CCBot|PerplexityBot|YouBot|facebookexternalhit|Twitterbot)\\/\\d+(?:\\.\\d+)*(?=$|[\\s;)])/i,\n  },\n  {\n    kind: \"crawler\",\n    pattern:\n      /(?:^|[\\s;(])(?:AdsBot-Google(?:-Mobile)?|GoogleOther(?:-[A-Za-z]+)?)(?=$|[\\s;)])/i,\n  },\n  {\n    kind: \"http-client\",\n    pattern: /(?:^|[\\s;(])Wget\\/\\d+(?:\\.\\d+)*(?=$|[\\s;)])/i,\n  },\n  {\n    kind: \"browser-automation\",\n    pattern: /(?:^|[\\s;(])HeadlessChrome\\/\\d+(?:\\.\\d+)*(?=$|[\\s;)])/i,\n  },\n  {\n    kind: \"playwright\",\n    pattern: /(?:^|[\\s;(])Playwright\\/\\d+(?:\\.\\d+)*(?=$|[\\s;)])/i,\n  },\n  {\n    kind: \"puppeteer\",\n    pattern: /(?:^|[\\s;(])Puppeteer\\/\\d+(?:\\.\\d+)*(?=$|[\\s;)])/i,\n  },\n  {\n    kind: \"selenium\",\n    pattern: /(?:^|[\\s;(])Selenium\\/\\d+(?:\\.\\d+)*(?=$|[\\s;)])/i,\n  },\n  {\n    kind: \"phantomjs\",\n    pattern: /(?:^|[\\s;(])(?:PhantomJS|SlimerJS)\\/\\d+(?:\\.\\d+)*(?=$|[\\s;)])/i,\n  },\n];\n\n/** Scripting HTTP client claimed by a well-formed User-Agent product token. */\nexport function getScriptingUserAgentKind(\n  userAgent: string,\n): ScriptingUserAgentKind | null {\n  return (\n    SCRIPTING_USER_AGENT_PATTERNS.find(({ pattern }) => pattern.test(userAgent))\n      ?.kind ?? null\n  );\n}\n\n/** Conservative known crawler, HTTP client, or browser-automation UA token. */\nexport function isBotUserAgent(userAgent: string | undefined): boolean {\n  return getBotUserAgentKind(userAgent) !== null;\n}\n\n/** Family claimed by a conservative bot or automation product token. */\nexport function getBotUserAgentKind(\n  userAgent: string | undefined,\n): BotUserAgentKind | null {\n  if (!userAgent) {\n    return null;\n  }\n\n  return (\n    BOT_USER_AGENT_PATTERNS.find(({ pattern }) => pattern.test(userAgent))\n      ?.kind ?? null\n  );\n}\n","import type { ConfidenceLevel } from \"./types.js\";\nimport { getScriptingUserAgentKind } from \"../userAgent.js\";\n\nexport interface TlsFingerprintEntry {\n  id: string;\n  label: string;\n  /** Defaults to `ja3` for backward compatibility. */\n  fingerprintType?: \"ja3\" | \"ja4\";\n  hash?: string;\n  prefix?: string;\n  families: UserAgentFamily[];\n  confidence: ConfidenceLevel;\n}\n\nexport type UserAgentFamily =\n  | \"chrome\"\n  | \"chrome-headless\"\n  | \"edge\"\n  | \"firefox\"\n  | \"safari\"\n  | \"curl\"\n  | \"python\"\n  | \"go\"\n  | \"java\"\n  | \"scripting\"\n  | \"unknown\";\n\n/** Curated automation and scripting TLS fingerprints (JA3 hash or prefix) */\nexport const KNOWN_SUSPICIOUS_TLS_FINGERPRINTS: TlsFingerprintEntry[] = [];\n\nconst JA3_HASH_PATTERN = /^[0-9a-f]{32}$/;\n\n/**\n * Whether a string is a well-formed JA3 hash (32-character lowercase MD5).\n * A hash of any other length can never match a real JA3 and is almost always\n * a typo or a truncated/expanded copy-paste.\n */\nexport function isValidJa3Hash(value: string): boolean {\n  return JA3_HASH_PATTERN.test(value.trim().toLowerCase());\n}\n\nconst BROWSER_UA_FAMILIES: UserAgentFamily[] = [\n  \"chrome\",\n  \"chrome-headless\",\n  \"edge\",\n  \"firefox\",\n  \"safari\",\n];\n\nconst UA_FAMILY_COMPATIBILITY: Record<UserAgentFamily, UserAgentFamily[]> = {\n  chrome: [\"chrome\", \"chrome-headless\", \"edge\"],\n  \"chrome-headless\": [\"chrome\", \"chrome-headless\", \"edge\"],\n  edge: [\"chrome\", \"edge\", \"chrome-headless\"],\n  firefox: [\"firefox\"],\n  safari: [\"safari\"],\n  curl: [\"curl\", \"scripting\"],\n  python: [\"python\", \"scripting\"],\n  go: [\"go\", \"scripting\"],\n  java: [\"java\", \"scripting\"],\n  scripting: [\"scripting\", \"python\", \"curl\", \"go\", \"java\"],\n  unknown: [],\n};\n\n/** Lowercases and trims a JA3/JA4 fingerprint for comparison. */\nexport function normalizeTlsFingerprint(fingerprint: string): string {\n  return fingerprint.trim().toLowerCase();\n}\n\n/** Coarse client family from a User-Agent string (`chrome`, `curl`, `python`, …). */\nexport function getUserAgentFamily(userAgent: string | undefined): UserAgentFamily {\n  if (!userAgent) {\n    return \"unknown\";\n  }\n\n  const scriptingFamily = getScriptingUserAgentKind(userAgent);\n  if (scriptingFamily) {\n    return scriptingFamily;\n  }\n\n  if (/HeadlessChrome/i.test(userAgent)) {\n    return \"chrome-headless\";\n  }\n\n  if (/Edg\\//i.test(userAgent)) {\n    return \"edge\";\n  }\n\n  if (/Chrome\\//i.test(userAgent)) {\n    return \"chrome\";\n  }\n\n  if (/Firefox\\//i.test(userAgent)) {\n    return \"firefox\";\n  }\n\n  if (/Safari\\//i.test(userAgent) && !/Chrome/i.test(userAgent)) {\n    return \"safari\";\n  }\n\n  return \"unknown\";\n}\n\n/** Whether the User-Agent claims to be a real browser (Chrome/Edge/Firefox/Safari). */\nexport function isBrowserLikeUserAgent(userAgent: string | undefined): boolean {\n  const family = getUserAgentFamily(userAgent);\n  return BROWSER_UA_FAMILIES.includes(family);\n}\n\n/** Finds the curated (or caller-supplied) entry matching a TLS fingerprint. */\nexport function findTlsFingerprintEntry(\n  fingerprint: string,\n  extraFingerprints: string[] = [],\n  fingerprintType: \"ja3\" | \"ja4\" = \"ja3\",\n  extraEntries: TlsFingerprintEntry[] = [],\n): TlsFingerprintEntry | undefined {\n  const normalized = normalizeTlsFingerprint(fingerprint);\n\n  for (const entry of [\n    ...KNOWN_SUSPICIOUS_TLS_FINGERPRINTS,\n    ...extraEntries,\n  ]) {\n    if ((entry.fingerprintType ?? \"ja3\") !== fingerprintType) {\n      continue;\n    }\n    const normalizedHash = entry.hash\n      ? normalizeTlsFingerprint(entry.hash)\n      : undefined;\n    if (normalizedHash && normalized === normalizedHash) {\n      return entry;\n    }\n\n    const normalizedPrefix = entry.prefix\n      ? normalizeTlsFingerprint(entry.prefix)\n      : undefined;\n    if (normalizedPrefix && normalized.startsWith(normalizedPrefix)) {\n      return entry;\n    }\n  }\n\n  for (const extra of extraFingerprints) {\n    const normalizedExtra = normalizeTlsFingerprint(extra);\n    if (!normalizedExtra) {\n      continue;\n    }\n\n    if (\n      normalized === normalizedExtra ||\n      normalized.startsWith(normalizedExtra)\n    ) {\n      return {\n        id: \"custom\",\n        label: \"Custom suspicious TLS fingerprint\",\n        families: [\"scripting\"],\n        confidence: \"high\",\n      };\n    }\n  }\n\n  return undefined;\n}\n\n/** Whether the fingerprint matches a known automation/scripting TLS client. */\nexport function isKnownSuspiciousTlsFingerprint(\n  fingerprint: string | undefined,\n  extraFingerprints: string[] = [],\n  fingerprintType: \"ja3\" | \"ja4\" = \"ja3\",\n  extraEntries: TlsFingerprintEntry[] = [],\n): boolean {\n  if (!fingerprint) {\n    return false;\n  }\n\n  return (\n    findTlsFingerprintEntry(\n      fingerprint,\n      extraFingerprints,\n      fingerprintType,\n      extraEntries,\n    ) !==\n    undefined\n  );\n}\n\n/**\n * Whether a recognized TLS fingerprint contradicts the declared User-Agent —\n * e.g. a curl JA3 hash presented alongside a Chrome UA.\n */\nexport function isTlsUserAgentMismatch(\n  fingerprint: string | undefined,\n  userAgent: string | undefined,\n  extraFingerprints: string[] = [],\n  fingerprintType: \"ja3\" | \"ja4\" = \"ja3\",\n  extraEntries: TlsFingerprintEntry[] = [],\n): boolean {\n  if (!fingerprint || !userAgent) {\n    return false;\n  }\n\n  const entry = findTlsFingerprintEntry(\n    fingerprint,\n    extraFingerprints,\n    fingerprintType,\n    extraEntries,\n  );\n  if (!entry) {\n    return false;\n  }\n  if (\n    entry.id === \"custom\" &&\n    ![...KNOWN_SUSPICIOUS_TLS_FINGERPRINTS, ...extraEntries].includes(entry)\n  ) {\n    return false;\n  }\n\n  const uaFamily = getUserAgentFamily(userAgent);\n  if (uaFamily === \"unknown\") {\n    return false;\n  }\n\n  const compatibleFamilies = UA_FAMILY_COMPATIBILITY[uaFamily];\n  return !entry.families.some((family) => compatibleFamilies.includes(family));\n}\n\n/** Browser-like UA arriving without a TLS fingerprint (only when `requireTlsFingerprint`). */\nexport function isMissingTlsFingerprint(\n  fingerprint: string | undefined,\n  userAgent: string | undefined,\n  requireTlsFingerprint: boolean,\n): boolean {\n  if (!requireTlsFingerprint) {\n    return false;\n  }\n\n  return isBrowserLikeUserAgent(userAgent) && !fingerprint;\n}\n","import {\n  isAcceptLanguageGeoMismatch,\n  isDatacenterBrowserMismatch,\n  isTimezoneMismatch,\n} from \"./timezone.js\";\nimport {\n  findTlsFingerprintEntry,\n  getUserAgentFamily,\n  isBrowserLikeUserAgent,\n  isKnownSuspiciousTlsFingerprint,\n  isMissingTlsFingerprint,\n  isTlsUserAgentMismatch,\n} from \"./tls.js\";\nimport type {\n  ConfidenceLevel,\n  ServerClientContext,\n  ServerDetectorOptions,\n  ServerSignal,\n} from \"./types.js\";\nimport { isBotUserAgent } from \"../userAgent.js\";\n\nfunction createSignal(\n  id: string,\n  description: string,\n  triggered: boolean,\n  weight: number,\n  confidence: ConfidenceLevel,\n): ServerSignal {\n  return {\n    id,\n    description,\n    triggered,\n    weight,\n    confidence,\n    score: triggered ? weight : 0,\n  };\n}\n\n/**\n * Explicit scripting-library User-Agent (curl, Python, Go, or Java).\n * @internal\n */\nexport function isScriptingUserAgent(userAgent: string | undefined): boolean {\n  const family = getUserAgentFamily(userAgent);\n  return [\"curl\", \"python\", \"go\", \"java\"].includes(family);\n}\n\n/**\n * Chromium UA version disagrees with the `sec-ch-ua` brand/version header.\n * @internal\n */\nexport function isClientHintsMismatch(\n  userAgent: string | undefined,\n  secChUa: string | undefined,\n): boolean {\n  if (!userAgent || !secChUa) {\n    return false;\n  }\n\n  const family = getUserAgentFamily(userAgent);\n  if (family !== \"chrome\" && family !== \"chrome-headless\" && family !== \"edge\") {\n    return false;\n  }\n\n  const uaMajor = userAgent.match(/(?:Chrome|Chromium)\\/(\\d+)/)?.[1];\n  const hintMajors = Array.from(\n    secChUa.matchAll(/\"(?:Chromium|Google Chrome|Microsoft Edge)\";v=\"(\\d+)/gi),\n    (match) => match[1],\n  );\n\n  return Boolean(\n    uaMajor &&\n      hintMajors.length > 0 &&\n      hintMajors.some((hintMajor) => hintMajor !== uaMajor),\n  );\n}\n\n/** HTTP User-Agent disagrees with the value observed by browser JavaScript. */\nexport function isClientUserAgentMismatch(\n  userAgent: string | undefined,\n  clientUserAgent: string | undefined,\n): boolean {\n  const normalizedUserAgent = userAgent?.trim();\n  const normalizedClientUserAgent = clientUserAgent?.trim();\n  return Boolean(\n    normalizedUserAgent &&\n      normalizedClientUserAgent &&\n      normalizedUserAgent !== normalizedClientUserAgent,\n  );\n}\n\nfunction firstAcceptedLanguage(acceptLanguage: string): string | undefined {\n  let preferred: string | undefined;\n  let preferredQuality = -1;\n  let wildcardQuality = -1;\n\n  for (const part of acceptLanguage.split(\",\")) {\n    const [language, ...parameters] = part.trim().split(\";\");\n    const normalizedLanguage = language?.trim().toLowerCase();\n    if (!normalizedLanguage) {\n      continue;\n    }\n\n    const qualityParameter = parameters.find((parameter) =>\n      /^q=/i.test(parameter.trim()),\n    );\n    const qualityMatch = qualityParameter\n      ?.trim()\n      .match(/^q=(0(?:\\.\\d{0,3})?|1(?:\\.0{0,3})?)$/i);\n    if (qualityParameter && !qualityMatch) {\n      continue;\n    }\n\n    const quality = qualityMatch ? Number(qualityMatch[1]) : 1;\n    if (normalizedLanguage === \"*\") {\n      wildcardQuality = Math.max(wildcardQuality, quality);\n      continue;\n    }\n    if (quality > 0 && quality > preferredQuality) {\n      preferred = normalizedLanguage;\n      preferredQuality = quality;\n    }\n  }\n\n  return wildcardQuality >= preferredQuality ? undefined : preferred;\n}\n\n/** Accept-Language's preferred value disagrees with Navigator language data. */\nexport function isClientLanguageMismatch(\n  acceptLanguage: string | undefined,\n  clientLanguage: string | undefined,\n  clientLanguages: string[] | undefined,\n): boolean {\n  if (!acceptLanguage || (!clientLanguage && !clientLanguages?.length)) {\n    return false;\n  }\n\n  const preferred = firstAcceptedLanguage(acceptLanguage);\n  if (!preferred) {\n    return false;\n  }\n\n  return Boolean(\n    (clientLanguage && clientLanguage.toLowerCase() !== preferred) ||\n      (clientLanguages?.[0] && clientLanguages[0].toLowerCase() !== preferred),\n  );\n}\n\nfunction claimedPlatform(userAgent: string): string | undefined {\n  if (/Android/i.test(userAgent)) return \"android\";\n  if (/CrOS/i.test(userAgent)) return \"chrome os\";\n  if (/Windows/i.test(userAgent)) return \"windows\";\n  if (/(?:iPhone|iPad|iPod)/i.test(userAgent)) return \"ios\";\n  if (/(?:Macintosh|Mac OS X)/i.test(userAgent)) return \"macos\";\n  if (/Linux/i.test(userAgent)) return \"linux\";\n  return undefined;\n}\n\nfunction normalizePlatform(platform: string): string | undefined {\n  const value = platform.trim().replace(/^\"|\"$/g, \"\").toLowerCase();\n  if (/^android(?:\\b|$)/.test(value)) return \"android\";\n  if (/^(?:cros|chrome os)(?:\\b|$)/.test(value)) return \"chrome os\";\n  if (/^(?:windows|win(?:16|32|64|ce)?)(?:\\b|$)/.test(value)) {\n    return \"windows\";\n  }\n  if (/^(?:iphone|ipad|ipod|ios)(?:\\b|$)/.test(value)) return \"ios\";\n  if (/^(?:mac(?:intel|ppc)?|macos|mac os)(?:\\b|$)/.test(value)) {\n    return \"macos\";\n  }\n  if (/^linux(?:\\b|$)/.test(value)) return \"linux\";\n  return undefined;\n}\n\nfunction platformMatches(\n  actual: string | undefined,\n  expected: string,\n  allowLegacyAliases: boolean,\n): boolean {\n  return actual === undefined ||\n    actual === expected ||\n    (allowLegacyAliases && expected === \"android\" && actual === \"linux\") ||\n    (allowLegacyAliases && expected === \"chrome os\" && actual === \"linux\") ||\n    (allowLegacyAliases && expected === \"ios\" && actual === \"macos\");\n}\n\n/** UA operating-system claim conflicts with JS platform or Client Hints. */\nexport function isClientPlatformMismatch(\n  userAgent: string | undefined,\n  clientPlatform: string | undefined,\n  secChUaPlatform: string | undefined,\n): boolean {\n  if (!userAgent) {\n    return false;\n  }\n\n  const expected = claimedPlatform(userAgent);\n  if (!expected) {\n    return false;\n  }\n\n  const client = clientPlatform ? normalizePlatform(clientPlatform) : undefined;\n  const hint = secChUaPlatform\n    ? normalizePlatform(secChUaPlatform)\n    : undefined;\n  return !platformMatches(client, expected, true) ||\n    !platformMatches(hint, expected, false);\n}\n\n/** sec-ch-ua-mobile conflicts with the User-Agent's mobile claim. */\nexport function isClientHintsMobileMismatch(\n  userAgent: string | undefined,\n  secChUaMobile: string | undefined,\n): boolean {\n  if (!userAgent || !secChUaMobile || !/^\\?[01]$/.test(secChUaMobile.trim())) {\n    return false;\n  }\n\n  return (secChUaMobile.trim() === \"?1\") !==\n    /(?:Mobi|iPhone|iPod)/i.test(userAgent);\n}\n\n/**\n * Browser UA missing one or more Fetch Metadata headers, when explicitly required.\n * @internal\n */\nexport function isMissingBrowserHeaders(\n  context: ServerClientContext,\n  requireBrowserHeaders: boolean,\n): boolean {\n  return (\n    requireBrowserHeaders &&\n    isBrowserLikeUserAgent(context.userAgent) &&\n    (!context.secFetchSite || !context.secFetchMode || !context.secFetchDest)\n  );\n}\n\n/**\n * Evaluates every server-side heuristic and returns the weighted signal list.\n * @internal\n */\nexport function buildServerSignals(\n  context: ServerClientContext,\n  options: ServerDetectorOptions = {},\n): ServerSignal[] {\n  const timezoneToleranceMinutes = options.timezoneToleranceMinutes ?? 60;\n  const suspiciousTlsFingerprints = options.suspiciousTlsFingerprints ?? [];\n  const suspiciousTlsFingerprintEntries =\n    options.suspiciousTlsFingerprintEntries ?? [];\n  const requireTlsFingerprint = options.requireTlsFingerprint ?? false;\n  const requireBrowserHeaders = options.requireBrowserHeaders ?? false;\n  const suspiciousTlsEntry = context.tlsFingerprint\n    ? findTlsFingerprintEntry(\n        context.tlsFingerprint,\n        suspiciousTlsFingerprints,\n        context.tlsFingerprintType,\n        suspiciousTlsFingerprintEntries,\n      )\n    : undefined;\n\n  return [\n    createSignal(\n      \"scripting-user-agent\",\n      \"User-Agent claims a scripting HTTP client\",\n      isScriptingUserAgent(context.userAgent),\n      0.75,\n      \"medium\",\n    ),\n    createSignal(\n      \"bot-user-agent\",\n      \"User-Agent claims a known bot, HTTP, or automation client\",\n      isBotUserAgent(context.userAgent),\n      0.9,\n      \"high\",\n    ),\n    createSignal(\n      \"crawler-identity-spoofed\",\n      \"Trusted edge conclusively rejected the claimed crawler identity\",\n      context.crawlerVerificationStatus === \"spoofed\",\n      0.95,\n      \"high\",\n    ),\n    createSignal(\n      \"client-hints-mismatch\",\n      \"User-Agent version conflicts with sec-ch-ua\",\n      isClientHintsMismatch(context.userAgent, context.secChUa),\n      0.65,\n      \"high\",\n    ),\n    createSignal(\n      \"client-user-agent-mismatch\",\n      \"HTTP User-Agent conflicts with the browser-reported User-Agent\",\n      isClientUserAgentMismatch(context.userAgent, context.clientUserAgent),\n      0.8,\n      \"high\",\n    ),\n    createSignal(\n      \"client-language-mismatch\",\n      \"Accept-Language conflicts with browser-reported languages\",\n      isClientLanguageMismatch(\n        context.acceptLanguage,\n        context.clientLanguage,\n        context.clientLanguages,\n      ),\n      0.45,\n      \"medium\",\n    ),\n    createSignal(\n      \"client-platform-mismatch\",\n      \"User-Agent OS conflicts with browser or Client Hints platform\",\n      isClientPlatformMismatch(\n        context.userAgent,\n        context.clientPlatform,\n        context.secChUaPlatform,\n      ),\n      0.55,\n      \"high\",\n    ),\n    createSignal(\n      \"client-hints-mobile-mismatch\",\n      \"sec-ch-ua-mobile conflicts with the User-Agent\",\n      isClientHintsMobileMismatch(context.userAgent, context.secChUaMobile),\n      0.55,\n      \"high\",\n    ),\n    createSignal(\n      \"missing-browser-headers\",\n      \"Browser-like User-Agent is missing Fetch Metadata headers\",\n      isMissingBrowserHeaders(context, requireBrowserHeaders),\n      0.35,\n      \"medium\",\n    ),\n    createSignal(\n      \"timezone-mismatch\",\n      \"Client-reported timezone does not match GeoIP timezone\",\n      isTimezoneMismatch(\n        context.ipTimezone,\n        context.clientTimezone,\n        timezoneToleranceMinutes,\n      ),\n      // Below the default 0.5 threshold on purpose: a lone timezone mismatch is\n      // routine for VPN users and travelers, so it corroborates rather than\n      // blocks on its own.\n      0.45,\n      \"high\",\n    ),\n    createSignal(\n      \"known-suspicious-tls\",\n      suspiciousTlsEntry\n        ? `TLS fingerprint matches ${suspiciousTlsEntry.label}`\n        : \"TLS fingerprint matches a known automation/scripting client\",\n      isKnownSuspiciousTlsFingerprint(\n        context.tlsFingerprint,\n        suspiciousTlsFingerprints,\n        context.tlsFingerprintType,\n        suspiciousTlsFingerprintEntries,\n      ),\n      0.55,\n      suspiciousTlsEntry?.confidence ?? \"high\",\n    ),\n    createSignal(\n      \"tls-user-agent-mismatch\",\n      \"TLS fingerprint is inconsistent with the declared user agent\",\n      isTlsUserAgentMismatch(\n        context.tlsFingerprint,\n        context.userAgent,\n        suspiciousTlsFingerprints,\n        context.tlsFingerprintType,\n        suspiciousTlsFingerprintEntries,\n      ),\n      0.5,\n      suspiciousTlsEntry?.confidence ?? \"high\",\n    ),\n    createSignal(\n      \"missing-tls-fingerprint\",\n      \"Browser-like user agent without a TLS fingerprint\",\n      isMissingTlsFingerprint(\n        context.tlsFingerprint,\n        context.userAgent,\n        requireTlsFingerprint,\n      ),\n      0.25,\n      \"medium\",\n    ),\n    createSignal(\n      \"accept-language-geo-mismatch\",\n      \"Accept-Language does not include the GeoIP country\",\n      isAcceptLanguageGeoMismatch(context.acceptLanguage, context.ipCountry),\n      0.2,\n      \"low\",\n    ),\n    createSignal(\n      \"datacenter-browser-mismatch\",\n      \"Datacenter/hosting IP with a residential browser user agent\",\n      isDatacenterBrowserMismatch(context.isDatacenterIp, context.userAgent),\n      0.35,\n      \"medium\",\n    ),\n    createSignal(\n      \"abuse-listed-ip\",\n      \"IP appears on the AbuseIPDB 30-day blocklist\",\n      Boolean(context.isAbuseListedIp),\n      0.6,\n      \"high\",\n    ),\n    createSignal(\n      \"icloud-private-relay\",\n      \"IP is an iCloud Private Relay egress address\",\n      Boolean(context.isIcloudPrivateRelay),\n      0.15,\n      \"low\",\n    ),\n  ];\n}\n","import { lookup } from \"doc999tor-fast-geoip\";\n\nexport interface IpGeoResult {\n  ipCountry?: string;\n  ipTimezone?: string;\n  city?: string;\n  region?: string;\n}\n\n/**\n * Looks up country, timezone, city, and region for an IP using the bundled\n * offline GeoIP database (`doc999tor-fast-geoip`). Returns `null` when the IP\n * is unknown or invalid — never throws.\n */\nexport async function lookupClientIpGeo(ip: string): Promise<IpGeoResult | null> {\n  try {\n    const geo = await lookup(ip);\n\n    if (!geo) {\n      return null;\n    }\n\n    return {\n      ipCountry: geo.country || undefined,\n      ipTimezone: geo.timezone || undefined,\n      city: geo.city || undefined,\n      region: geo.region || undefined,\n    };\n  } catch {\n    return null;\n  }\n}\n","import fs from \"node:fs\";\nimport path from \"node:path\";\nimport { fileURLToPath } from \"node:url\";\n\n// Track data dirs for which we've already emitted the \"no data\" warning.\nconst warnedAboutMissingData = new Set<string>();\n\n/** Result of matching one IP against the bundled blocklists. */\nexport interface IpListMatchResult {\n  /** IP falls inside a known datacenter/hosting provider range */\n  isDatacenterIp: boolean;\n  /** IP appears on the AbuseIPDB 30-day blocklist */\n  isAbuseListedIp: boolean;\n  /** IP is an iCloud Private Relay egress address */\n  isIcloudPrivateRelay: boolean;\n  /** Provider name when `isDatacenterIp` is true (e.g. `Amazon AWS`) */\n  datacenterProvider?: string;\n  /** ISO country code of the relay egress when `isIcloudPrivateRelay` is true */\n  icloudRelayCountry?: string;\n}\n\n/** Pre-parsed blocklist matcher. Create once and reuse — see {@link getIpListChecker}. */\nexport interface IpListChecker {\n  /** Match an IPv4 or IPv6 address against all bundled lists. Invalid input matches nothing. */\n  check(ip: string): IpListMatchResult;\n  /** Entry counts loaded from the data directory. */\n  stats: {\n    abuseIpCount: number;\n    datacenterRangeCount: number;\n    icloudRelayRangeCount: number;\n  };\n}\n\n// ---------------------------------------------------------------------------\n// IP parsing — self-contained so the library stays dependency-light.\n// IPv4 addresses become 32-bit numbers; IPv6 addresses become 128-bit bigints.\n// ---------------------------------------------------------------------------\n\nexport type ParsedIp =\n  | { kind: \"ipv4\"; value: number; canonical: string }\n  | { kind: \"ipv6\"; value: bigint; canonical: string };\n\nconst IPV4_MAPPED_PREFIX = 0xffffn << 32n;\nconst IPV4_MAPPED_MASK = ~0xffffffffn & ((1n << 128n) - 1n);\n\nfunction parseIpv4(address: string): ParsedIp | null {\n  const parts = address.split(\".\");\n  if (parts.length !== 4) {\n    return null;\n  }\n\n  let value = 0;\n  for (const part of parts) {\n    if (part.length === 0 || part.length > 3 || !/^\\d+$/.test(part)) {\n      return null;\n    }\n\n    const octet = Number(part);\n    if (octet > 255 || (part.length > 1 && part.startsWith(\"0\"))) {\n      return null;\n    }\n\n    value = value * 256 + octet;\n  }\n\n  return {\n    kind: \"ipv4\",\n    value,\n    canonical: `${(value >>> 24) & 0xff}.${(value >>> 16) & 0xff}.${(value >>> 8) & 0xff}.${value & 0xff}`,\n  };\n}\n\nfunction parseIpv6(address: string): ParsedIp | null {\n  // Strip zone index (fe80::1%eth0) — irrelevant for list matching.\n  let input = address.split(\"%\")[0].toLowerCase();\n\n  // Embedded IPv4 tail (::ffff:192.0.2.1) → two trailing hex groups.\n  if (input.includes(\".\")) {\n    const lastColon = input.lastIndexOf(\":\");\n    const tail = parseIpv4(input.slice(lastColon + 1));\n    if (!tail || tail.kind !== \"ipv4\") {\n      return null;\n    }\n\n    const high = (tail.value >>> 16) & 0xffff;\n    const low = tail.value & 0xffff;\n    input = `${input.slice(0, lastColon)}:${high.toString(16)}:${low.toString(16)}`;\n  }\n\n  const doubleColonSplit = input.split(\"::\");\n  if (doubleColonSplit.length > 2) {\n    return null;\n  }\n\n  const splitGroups = (segment: string): string[] | null => {\n    if (segment === \"\") {\n      return [];\n    }\n    const groups = segment.split(\":\");\n    return groups.every((group) => /^[0-9a-f]{1,4}$/.test(group)) ? groups : null;\n  };\n\n  const head = splitGroups(doubleColonSplit[0]);\n  const tail = doubleColonSplit.length === 2 ? splitGroups(doubleColonSplit[1]) : [];\n  if (!head || !tail) {\n    return null;\n  }\n\n  const missing = 8 - head.length - tail.length;\n  if (doubleColonSplit.length === 2 ? missing < 1 : missing !== 0) {\n    return null;\n  }\n\n  const groups = [...head, ...Array<string>(missing).fill(\"0\"), ...tail];\n  let value = 0n;\n  for (const group of groups) {\n    value = (value << 16n) | BigInt(parseInt(group, 16));\n  }\n\n  // IPv4-mapped (::ffff:a.b.c.d) → canonical IPv4 so all lists apply.\n  if ((value & IPV4_MAPPED_MASK) === IPV4_MAPPED_PREFIX) {\n    const v4 = Number(value & 0xffffffffn);\n    return {\n      kind: \"ipv4\",\n      value: v4,\n      canonical: `${(v4 >>> 24) & 0xff}.${(v4 >>> 16) & 0xff}.${(v4 >>> 8) & 0xff}.${v4 & 0xff}`,\n    };\n  }\n\n  const canonicalGroups: string[] = [];\n  for (let index = 7; index >= 0; index -= 1) {\n    canonicalGroups.push(((value >> BigInt(index * 16)) & 0xffffn).toString(16));\n  }\n\n  return { kind: \"ipv6\", value, canonical: canonicalGroups.join(\":\") };\n}\n\n/**\n * Parses an IPv4 or IPv6 address. IPv4-mapped IPv6 addresses (`::ffff:1.2.3.4`)\n * normalize to IPv4 so proxies handing over mapped addresses still match.\n * Returns `null` for anything that is not a valid address.\n */\nexport function parseIp(address: string): ParsedIp | null {\n  const trimmed = address.trim();\n  if (trimmed.length === 0) {\n    return null;\n  }\n\n  return trimmed.includes(\":\") ? parseIpv6(trimmed) : parseIpv4(trimmed);\n}\n\n// ---------------------------------------------------------------------------\n// Interval matching — lists are parsed once into sorted arrays, lookups are\n// binary searches. IPv4 and IPv6 live in separate arrays (different spaces).\n// ---------------------------------------------------------------------------\n\ninterface Interval<T extends number | bigint> {\n  start: T;\n  end: T;\n  payload: string;\n}\n\nfunction sortIntervals<T extends number | bigint>(intervals: Interval<T>[]): Interval<T>[] {\n  intervals.sort((left, right) => (left.start < right.start ? -1 : left.start > right.start ? 1 : 0));\n  return intervals;\n}\n\nfunction findInterval<T extends number | bigint>(\n  value: T,\n  intervals: Interval<T>[],\n): Interval<T> | undefined {\n  let low = 0;\n  let high = intervals.length - 1;\n\n  while (low <= high) {\n    const middle = (low + high) >>> 1;\n    const interval = intervals[middle];\n\n    if (value < interval.start) {\n      high = middle - 1;\n    } else if (value > interval.end) {\n      low = middle + 1;\n    } else {\n      return interval;\n    }\n  }\n\n  return undefined;\n}\n\ninterface IntervalSet {\n  v4: Interval<number>[];\n  v6: Interval<bigint>[];\n  size: number;\n}\n\nfunction createIntervalSet(): IntervalSet {\n  return { v4: [], v6: [], size: 0 };\n}\n\nfunction addCidr(set: IntervalSet, cidr: string, payload: string): void {\n  const [address, prefixText] = cidr.split(\"/\");\n  if (prefixText === undefined) {\n    return;\n  }\n\n  const prefix = Number(prefixText);\n  const parsed = parseIp(address);\n  if (!parsed || !Number.isInteger(prefix) || prefix < 0) {\n    return;\n  }\n\n  if (parsed.kind === \"ipv4\") {\n    if (prefix > 32) {\n      return;\n    }\n    const size = 2 ** (32 - prefix);\n    const start = Math.floor(parsed.value / size) * size;\n    set.v4.push({ start, end: start + size - 1, payload });\n  } else {\n    if (prefix > 128) {\n      return;\n    }\n    const hostBits = BigInt(128 - prefix);\n    const start = (parsed.value >> hostBits) << hostBits;\n    set.v6.push({ start, end: start + (1n << hostBits) - 1n, payload });\n  }\n\n  set.size += 1;\n}\n\nfunction addRange(set: IntervalSet, startIp: string, endIp: string, payload: string): void {\n  const start = parseIp(startIp);\n  const end = parseIp(endIp);\n  if (!start || !end || start.kind !== end.kind) {\n    return;\n  }\n\n  if (start.kind === \"ipv4\" && end.kind === \"ipv4\") {\n    if (start.value > end.value) {\n      return;\n    }\n\n    set.v4.push({ start: start.value, end: end.value, payload });\n    set.size += 1;\n  } else if (start.kind === \"ipv6\" && end.kind === \"ipv6\") {\n    if (start.value > end.value) {\n      return;\n    }\n\n    set.v6.push({ start: start.value, end: end.value, payload });\n    set.size += 1;\n  }\n}\n\nfunction finalizeIntervalSet(set: IntervalSet): IntervalSet {\n  sortIntervals(set.v4);\n  sortIntervals(set.v6);\n  return set;\n}\n\nfunction matchIntervalSet(set: IntervalSet, parsed: ParsedIp): string | undefined {\n  const match =\n    parsed.kind === \"ipv4\"\n      ? findInterval(parsed.value, set.v4)\n      : findInterval(parsed.value, set.v6);\n\n  return match?.payload;\n}\n\n// ---------------------------------------------------------------------------\n// Bundled CSV loading\n// ---------------------------------------------------------------------------\n\nfunction getDefaultDataDir(): string {\n  // Walk up from the module (src/server/ in development, dist/ when packaged)\n  // to the package root containing the bundled data/ directory.\n  let dir = path.dirname(fileURLToPath(import.meta.url));\n\n  for (let depth = 0; depth < 4; depth += 1) {\n    const candidate = path.join(dir, \"data\");\n    if (fs.existsSync(path.join(candidate, \"datacenter_ip_ranges.csv\"))) {\n      return candidate;\n    }\n    dir = path.dirname(dir);\n  }\n\n  return path.resolve(path.dirname(fileURLToPath(import.meta.url)), \"../data\");\n}\n\nfunction readDataFile(dataDir: string, filename: string): string {\n  const filePath = path.join(dataDir, filename);\n\n  if (!fs.existsSync(filePath)) {\n    return \"\";\n  }\n\n  return fs.readFileSync(filePath, \"utf-8\");\n}\n\nfunction eachDataLine(content: string, visit: (line: string) => void): void {\n  for (const rawLine of content.split(\"\\n\")) {\n    const line = rawLine.trim();\n    if (line && !line.startsWith(\"#\")) {\n      visit(line);\n    }\n  }\n}\n\n/** Bare IPs, optionally annotated (`1.2.3.4  # TH AS23969 provider`) */\nfunction loadAbuseIps(content: string): Set<string> {\n  const ips = new Set<string>();\n\n  eachDataLine(content, (line) => {\n    const spaceIndex = line.search(/[\\s#]/);\n    const parsed = parseIp(spaceIndex === -1 ? line : line.slice(0, spaceIndex));\n    if (parsed) {\n      ips.add(parsed.canonical);\n    }\n  });\n\n  return ips;\n}\n\n/** `start,end,provider,url` rows from ipcat datacenters.csv */\nfunction loadDatacenterRanges(content: string): IntervalSet {\n  const set = createIntervalSet();\n\n  eachDataLine(content, (line) => {\n    const [start, end, provider = \"unknown\"] = line\n      .split(\",\")\n      .map((column) => column.trim());\n    if (start && end) {\n      addRange(set, start, end, provider);\n    }\n  });\n\n  return finalizeIntervalSet(set);\n}\n\n/** `cidr,country` rows from Apple's egress-ip-ranges.csv (IPv4 and IPv6) */\nfunction loadIcloudRelayRanges(content: string): IntervalSet {\n  const set = createIntervalSet();\n\n  eachDataLine(content, (line) => {\n    const [cidr, country = \"\"] = line\n      .split(\",\")\n      .map((column) => column.trim());\n    addCidr(set, cidr, country);\n  });\n\n  return finalizeIntervalSet(set);\n}\n\n/**\n * Builds a blocklist matcher from the CSVs in `dataDir` (defaults to the\n * package's bundled `data/`). Parsing happens once here; `check` calls are\n * then O(log n) binary searches. Prefer {@link getIpListChecker}, which caches\n * the parsed lists per data directory.\n */\nexport function createIpListChecker(dataDir = getDefaultDataDir()): IpListChecker {\n  const abuseIps = loadAbuseIps(readDataFile(dataDir, \"abuse_ip_db_30d_ips.csv\"));\n  const datacenterRanges = loadDatacenterRanges(\n    readDataFile(dataDir, \"datacenter_ip_ranges.csv\"),\n  );\n  const icloudRelayRanges = loadIcloudRelayRanges(\n    readDataFile(dataDir, \"icloud_private_relay_ip_ranges.csv\"),\n  );\n\n  if (abuseIps.size + datacenterRanges.size + icloudRelayRanges.size === 0) {\n    // One-time warning so it doesn't spam on every request if misconfigured.\n    if (!warnedAboutMissingData.has(dataDir)) {\n      warnedAboutMissingData.add(dataDir);\n      process.emitWarning(\n        `bot-signal: no IP list data found in ${dataDir} — ` +\n          \"abuse/datacenter/iCloud relay checks will match nothing\",\n      );\n    }\n  }\n\n  return {\n    stats: {\n      abuseIpCount: abuseIps.size,\n      datacenterRangeCount: datacenterRanges.size,\n      icloudRelayRangeCount: icloudRelayRanges.size,\n    },\n    check(ip: string): IpListMatchResult {\n      const parsed = parseIp(ip);\n\n      if (!parsed) {\n        return {\n          isDatacenterIp: false,\n          isAbuseListedIp: false,\n          isIcloudPrivateRelay: false,\n        };\n      }\n\n      const datacenterProvider = matchIntervalSet(datacenterRanges, parsed);\n      const icloudRelayCountry = matchIntervalSet(icloudRelayRanges, parsed);\n\n      return {\n        isDatacenterIp: datacenterProvider !== undefined,\n        isAbuseListedIp: abuseIps.has(parsed.canonical),\n        isIcloudPrivateRelay: icloudRelayCountry !== undefined,\n        datacenterProvider,\n        icloudRelayCountry: icloudRelayCountry || undefined,\n      };\n    },\n  };\n}\n\nlet cachedChecker: IpListChecker | undefined;\nlet cachedDataDir: string | undefined;\n\n/**\n * Returns a cached {@link IpListChecker} for `dataDir`, creating it on first use.\n *\n * Note: Because of how ESM/CJS interop works, different module instances\n * (e.g. a mix of import vs require, or multiple copies of the package)\n * may each have their own cache. For most server apps this is fine.\n * Call `preloadIpLists()` early at boot.\n */\nexport function getIpListChecker(dataDir?: string): IpListChecker {\n  const resolvedDataDir = dataDir ?? getDefaultDataDir();\n\n  if (!cachedChecker || cachedDataDir !== resolvedDataDir) {\n    cachedChecker = createIpListChecker(resolvedDataDir);\n    cachedDataDir = resolvedDataDir;\n  }\n\n  return cachedChecker;\n}\n\n/**\n * Eagerly parses the bundled IP lists into the shared cache so the first\n * request-time check doesn't pay the one-off parse cost (~0.5s for the full\n * bundled data). Call once at server boot. Returns the loaded entry counts.\n *\n * See {@link getIpListChecker} for notes on module caching across ESM/CJS.\n */\nexport function preloadIpLists(dataDir?: string): IpListChecker[\"stats\"] {\n  return getIpListChecker(dataDir).stats;\n}\n\n/**\n * Clears the cached checker — used by tests that swap data directories.\n * @internal\n */\nexport function resetIpListCheckerCache(): void {\n  cachedChecker = undefined;\n  cachedDataDir = undefined;\n  warnedAboutMissingData.clear();\n}\n\n/**\n * Absolute path of the package's bundled `data/` directory.\n * @internal\n */\nexport function getDefaultIpDataDir(): string {\n  return getDefaultDataDir();\n}\n","import { lookupClientIpGeo } from \"./geoip.js\";\nimport { getIpListChecker } from \"./ipLists.js\";\nimport type { ServerClientContext, ServerDetectorOptions } from \"./types.js\";\n\nexport interface EnrichedServerContext extends ServerClientContext {\n  datacenterProvider?: string;\n  icloudRelayCountry?: string;\n}\n\n/**\n * Fills missing context fields from `clientIp`: GeoIP country/timezone\n * (unless `lookupGeo: false`) and bundled blocklist matches (unless\n * `checkIpLists: false`). Fields already present are never overwritten.\n */\nexport async function enrichServerContext(\n  context: ServerClientContext,\n  options: ServerDetectorOptions = {},\n): Promise<EnrichedServerContext> {\n  const enriched: EnrichedServerContext = { ...context };\n\n  if (context.clientIp) {\n    if (options.lookupGeo !== false) {\n      const geo = await lookupClientIpGeo(context.clientIp);\n\n      if (geo) {\n        enriched.ipCountry = enriched.ipCountry ?? geo.ipCountry;\n        enriched.ipTimezone = enriched.ipTimezone ?? geo.ipTimezone;\n      }\n    }\n\n    if (options.checkIpLists !== false) {\n      const checker = getIpListChecker(options.dataDir);\n      const match = checker.check(context.clientIp);\n\n      enriched.isDatacenterIp = enriched.isDatacenterIp ?? match.isDatacenterIp;\n      enriched.isAbuseListedIp = enriched.isAbuseListedIp ?? match.isAbuseListedIp;\n      enriched.isIcloudPrivateRelay =\n        enriched.isIcloudPrivateRelay ?? match.isIcloudPrivateRelay;\n      enriched.datacenterProvider = match.datacenterProvider;\n      enriched.icloudRelayCountry = match.icloudRelayCountry;\n    }\n  }\n\n  return enriched;\n}\n","export type AutomationConfidence = \"high\" | \"medium\" | \"low\";\n\nexport type AutomationKind =\n  | \"unknown\"\n  | \"browser-automation\"\n  | \"playwright\"\n  | \"patchright\"\n  | \"puppeteer\"\n  | \"selenium\"\n  | \"phantomjs\"\n  | \"nightmare\"\n  | \"curl\"\n  | \"python\"\n  | \"go\"\n  | \"java\";\n\n/** Best-effort attribution. Stealth tools can only be identified probabilistically. */\nexport interface AutomationAssessment {\n  /** Whether automation evidence was found; independent of enforcement threshold. */\n  isAutomated: boolean;\n  /** Most likely supported family, or `unknown` for unattributed/unsupported identities. */\n  kind: AutomationKind;\n  confidence: AutomationConfidence;\n  /** Human-readable facts used for attribution (not every scoring signal). */\n  evidence: string[];\n  /** Other plausible families when the available fingerprints overlap. */\n  alternatives: AutomationKind[];\n}\n\nexport function createAutomationAssessment(\n  isAutomated: boolean,\n  kind: AutomationKind,\n  confidence: AutomationConfidence,\n  evidence: string[],\n  alternatives: AutomationKind[] = [],\n): AutomationAssessment {\n  return { isAutomated, kind, confidence, evidence, alternatives };\n}\n","import { createAutomationAssessment } from \"../automation.js\";\nimport { getBotUserAgentKind } from \"../userAgent.js\";\nimport { enrichServerContext } from \"./enrich.js\";\nimport { buildServerSignals } from \"./analysis.js\";\nimport type {\n  ConfidenceLevel,\n  ServerClientContext,\n  ServerClientResult,\n  ServerDetectorOptions,\n  ServerSignal,\n} from \"./types.js\";\nimport type { EnrichedServerContext } from \"./enrich.js\";\nimport {\n  findTlsFingerprintEntry,\n  getUserAgentFamily,\n  isTlsUserAgentMismatch,\n  KNOWN_SUSPICIOUS_TLS_FINGERPRINTS,\n} from \"./tls.js\";\nimport type { TlsFingerprintEntry } from \"./tls.js\";\n\n/**\n * Combines triggered signal weights into one score:\n * `1 - Π(1 - weightᵢ)` — independent-probability union, so extra signals\n * always raise the score but never past 1.\n * @internal\n */\nexport function aggregateServerSuspicionScore(signals: ServerSignal[]): number {\n  const triggered = signals.filter((signal) => signal.triggered);\n\n  if (triggered.length === 0) {\n    return 0;\n  }\n\n  let score = 1;\n\n  for (const signal of triggered) {\n    score *= 1 - signal.weight;\n  }\n\n  return 1 - score;\n}\n\n/**\n * Confidence in the verdict based on high-confidence signal hits and score.\n * @internal\n */\nexport function resolveServerConfidence(\n  signals: ServerSignal[],\n  suspicionScore: number,\n): ConfidenceLevel {\n  const triggeredHigh = signals.filter(\n    (signal) => signal.triggered && signal.confidence === \"high\",\n  ).length;\n\n  if (triggeredHigh >= 1 || suspicionScore >= 0.7) {\n    return \"high\";\n  }\n\n  if (suspicionScore >= 0.35) {\n    return \"medium\";\n  }\n\n  return \"low\";\n}\n\nfunction buildResultContext(\n  context: EnrichedServerContext,\n): ServerClientResult[\"context\"] {\n  return {\n    clientIp: context.clientIp,\n    ipTimezone: context.ipTimezone,\n    clientTimezone: context.clientTimezone,\n    tlsFingerprint: context.tlsFingerprint,\n    tlsFingerprintType: context.tlsFingerprintType,\n    userAgent: context.userAgent,\n    clientUserAgent: context.clientUserAgent,\n    acceptLanguage: context.acceptLanguage,\n    clientLanguage: context.clientLanguage,\n    clientLanguages: context.clientLanguages,\n    clientPlatform: context.clientPlatform,\n    secChUa: context.secChUa,\n    secChUaPlatform: context.secChUaPlatform,\n    secChUaMobile: context.secChUaMobile,\n    secFetchSite: context.secFetchSite,\n    secFetchMode: context.secFetchMode,\n    secFetchDest: context.secFetchDest,\n    ipCountry: context.ipCountry,\n    isDatacenterIp: context.isDatacenterIp,\n    isAbuseListedIp: context.isAbuseListedIp,\n    isIcloudPrivateRelay: context.isIcloudPrivateRelay,\n    crawlerVerificationStatus: context.crawlerVerificationStatus,\n    datacenterProvider: context.datacenterProvider,\n    icloudRelayCountry: context.icloudRelayCountry,\n  };\n}\n\nfunction classifyServerAutomation(\n  context: ServerClientContext,\n  suspiciousTlsFingerprints: string[],\n  suspiciousTlsFingerprintEntries: TlsFingerprintEntry[],\n) {\n  const crawlerVerificationEvidence =\n    context.crawlerVerificationStatus === \"verified\"\n      ? \"Trusted edge verified an automated crawler identity\"\n      : context.crawlerVerificationStatus === \"spoofed\"\n        ? \"Trusted edge conclusively rejected the claimed crawler identity\"\n        : undefined;\n  const uaFamily = getUserAgentFamily(context.userAgent);\n  const tlsEntry = context.tlsFingerprint\n    ? findTlsFingerprintEntry(\n        context.tlsFingerprint,\n        suspiciousTlsFingerprints,\n        context.tlsFingerprintType,\n        suspiciousTlsFingerprintEntries,\n      )\n    : undefined;\n  const hasFamilyLabel = Boolean(\n    tlsEntry &&\n      (KNOWN_SUSPICIOUS_TLS_FINGERPRINTS.includes(tlsEntry) ||\n        suspiciousTlsFingerprintEntries.includes(tlsEntry)),\n  );\n  const tlsSupportsUa = Boolean(\n    hasFamilyLabel &&\n      context.tlsFingerprint &&\n      context.userAgent &&\n      !isTlsUserAgentMismatch(\n        context.tlsFingerprint,\n        context.userAgent,\n        suspiciousTlsFingerprints,\n        context.tlsFingerprintType,\n        suspiciousTlsFingerprintEntries,\n      ),\n  );\n  if ([\"curl\", \"python\", \"go\", \"java\"].includes(uaFamily)) {\n    return createAutomationAssessment(\n      true,\n      uaFamily as \"curl\" | \"python\" | \"go\" | \"java\",\n      crawlerVerificationEvidence ? \"high\" : \"medium\",\n      [\n        `User-Agent claims ${uaFamily}`,\n        ...(crawlerVerificationEvidence ? [crawlerVerificationEvidence] : []),\n        ...(tlsSupportsUa ? [`TLS fingerprint is compatible with ${uaFamily}`] : []),\n      ],\n    );\n  }\n\n  const botUaKind = getBotUserAgentKind(context.userAgent);\n  if (botUaKind) {\n    const alternatives = botUaKind === \"browser-automation\"\n      ? [\"patchright\", \"playwright\", \"puppeteer\", \"selenium\"] as const\n      : [];\n    return createAutomationAssessment(\n      true,\n      botUaKind === \"crawler\" || botUaKind === \"http-client\"\n        ? \"unknown\"\n        : botUaKind,\n      \"high\",\n      [\n        `User-Agent claims ${botUaKind}`,\n        ...(crawlerVerificationEvidence ? [crawlerVerificationEvidence] : []),\n        ...(tlsSupportsUa && uaFamily !== \"unknown\"\n          ? [`TLS fingerprint is compatible with ${uaFamily}`]\n          : []),\n      ],\n      [...alternatives],\n    );\n  }\n\n  if (crawlerVerificationEvidence) {\n    return createAutomationAssessment(\n      true,\n      \"unknown\",\n      \"high\",\n      [crawlerVerificationEvidence],\n    );\n  }\n\n  return createAutomationAssessment(false, \"unknown\", \"low\", []);\n}\n\n/**\n * Scores an already-enriched request context synchronously. Use this when you\n * have your own GeoIP/blocklist pipeline; otherwise prefer\n * {@link detectServerClientAsync}, which fills the context from `clientIp`.\n */\nexport function detectServerClient(\n  context: ServerClientContext,\n  options: ServerDetectorOptions = {},\n): ServerClientResult {\n  const scoreThreshold = options.scoreThreshold ?? 0.5;\n  const signals = buildServerSignals(context, options);\n  const suspicionScore = aggregateServerSuspicionScore(signals);\n  const confidence = resolveServerConfidence(signals, suspicionScore);\n  const isLegitClient = suspicionScore < scoreThreshold;\n\n  return {\n    suspicionScore,\n    confidence,\n    signals,\n    isLegitClient,\n    automation: classifyServerAutomation(\n      context,\n      options.suspiciousTlsFingerprints ?? [],\n      options.suspiciousTlsFingerprintEntries ?? [],\n    ),\n    context: buildResultContext(context),\n  };\n}\n\n/**\n * Scores a request in one call. When `clientIp` is set, the context is\n * auto-enriched with GeoIP country/timezone and bundled blocklist matches\n * (datacenter ranges, AbuseIPDB, iCloud Private Relay) before scoring.\n *\n * @example\n * const result = await detectServerClientAsync({\n *   clientIp: req.ip,\n *   clientTimezone: req.headers[\"x-timezone\"],\n *   userAgent: req.headers[\"user-agent\"],\n *   tlsFingerprint: req.headers[\"x-ja3-hash\"],\n * });\n * if (!result.isLegitClient) return res.status(403).end();\n */\nexport async function detectServerClientAsync(\n  context: ServerClientContext,\n  options: ServerDetectorOptions = {},\n): Promise<ServerClientResult> {\n  const enriched = await enrichServerContext(context, options);\n  return detectServerClient(enriched, options);\n}\n","// Keep in sync with package.json during releases.\n// Prefer importing the package's package.json for the canonical version when possible.\nexport const VERSION = \"2.0.14\";\n"]}