traffic-guard 0.1.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.
@@ -0,0 +1,7 @@
1
+ {
2
+ "version": 3,
3
+ "sources": ["../src/battery.ts", "../src/crypto.ts", "../src/normalizer.ts", "../src/policy.ts", "../src/gate.ts", "../src/index.ts"],
4
+ "sourcesContent": ["import type { AssessmentResult, NormalizedRequest, RequestContext } from './types.js';\n\nlet sdkChoice: any = null;\nlet sdkNoul: any = null;\nlet sdkScore: any = null;\nlet sdkLoaded = false;\n\nexport async function loadTypeSafePrimitives() {\n if (!sdkLoaded) {\n try {\n const sdk = await import('@typesafe-ai/sdk');\n sdkChoice = sdk.choice;\n sdkNoul = sdk.noul;\n sdkScore = sdk.score;\n sdkLoaded = true;\n } catch {\n sdkLoaded = true;\n }\n }\n return { choice: sdkChoice, noul: sdkNoul, score: sdkScore };\n}\n\nexport function createBotGateBattery() {\n if (sdkNoul && sdkChoice && sdkScore) {\n return {\n is_bot: sdkNoul(\n 'Evaluate whether the incoming HTTP request in `request` is generated by an automated bot, script, crawler, scraper, or headless browser, rather than a genuine human user interacting with a standard web browser.',\n {\n true: 'Clear indicators of automation, scripting libraries, automated headless execution, scraper activity, or non-human interaction patterns.',\n false: 'Natural human interactive web browser navigation.'\n }\n ),\n is_attack: sdkNoul(\n 'Evaluate whether the request contains an attack payload, exploit attempt, injection, path traversal, probe for sensitive files, or vulnerability scan.',\n {\n true: 'Malicious payloads, SQLi, XSS, SSRF, command injection, path traversal, exploit probes, or sensitive credential/file hunting.',\n false: 'Safe, legitimate, benign application interaction without exploitation intent.'\n }\n ),\n is_spoofed: sdkNoul(\n 'Evaluate whether the request headers exhibit spoofing or client impersonation (such as claiming a browser User-Agent while lacking standard browser headers, or conflicting platform tokens).',\n {\n true: 'Mismatched, counterfeit, or contradictory headers indicating spoofed client identity.',\n false: 'Headers are coherent and authentic for the specified client.'\n }\n ),\n traffic_type: sdkChoice(\n 'Classify the primary nature of this incoming HTTP traffic.',\n {\n human: 'Legitimate human visitor navigating the website.',\n good_bot: 'Beneficial search engine indexer, feed fetcher, or uptime monitor (e.g. Googlebot, Bingbot, Slackbot).',\n bad_bot: 'Automated scraper, content scraper, spam bot, or unauthorized scraping tool.',\n attack: 'Hostile attacker executing vulnerability scans, exploit probes, or injection attacks.'\n }\n ),\n risk_level: sdkScore(\n 'Rate the security and operational risk this request poses to the website or service.',\n [\n 'Level 0: Safe - normal human traffic or well-behaved verified search crawler.',\n 'Level 1: Low risk - minor header anomaly or benign unfamiliar crawler without malicious activity.',\n 'Level 2: Suspicious - aggressive automated scraping, suspicious probes, or inconsistent headers.',\n 'Level 3: Dangerous - active exploitation, injection payload, unauthorized sensitive path probe, or credential abuse.'\n ]\n )\n };\n }\n\n // Pure data structure fallback if SDK is not imported\n return {\n is_bot: { type: 'noul', instructions: 'Is bot?' },\n is_attack: { type: 'noul', instructions: 'Is attack?' },\n is_spoofed: { type: 'noul', instructions: 'Is spoofed?' },\n traffic_type: { type: 'choice', instructions: 'Traffic type' },\n risk_level: { type: 'score', instructions: 'Risk level' }\n };\n}\n\n/**\n * Computes Shannon entropy of a string using Uint8Array frequency table.\n * Useful for detecting obfuscated attack strings and random scanner paths.\n */\nexport function calculateShannonEntropy(str: string): number {\n if (!str || str.length === 0) return 0;\n const len = str.length;\n const frequencies = new Uint16Array(256);\n\n for (let i = 0; i < len; i++) {\n frequencies[str.charCodeAt(i) & 0xff]++;\n }\n\n let entropy = 0;\n for (let i = 0; i < 256; i++) {\n const count = frequencies[i];\n if (count > 0) {\n const p = count / len;\n entropy -= p * Math.log2(p);\n }\n }\n return entropy;\n}\n\nexport function heuristicAssessment(\n request: NormalizedRequest,\n context: RequestContext\n): AssessmentResult {\n const userAgent = (request.headers['user-agent'] || '').toLowerCase();\n const path = request.path.toLowerCase();\n const queryStr = JSON.stringify(request.query).toLowerCase();\n const bodyStr = typeof request.body === 'string' ? request.body.toLowerCase() : JSON.stringify(request.body || '').toLowerCase();\n const headersStr = JSON.stringify(request.headers).toLowerCase();\n const fullTarget = `${path} ${queryStr} ${bodyStr} ${headersStr}`;\n\n let botScore = 0.05;\n let attackScore = 0.02;\n let spoofScore = 0.05;\n\n // Good bots check\n if (context.isKnownSearchBot) {\n botScore = 0.95;\n attackScore = 0.01;\n return {\n isBotProbability: botScore,\n isAttackProbability: attackScore,\n isSpoofedProbability: 0.02,\n trafficType: 'good_bot',\n trafficTypeConfidence: 0.96,\n trafficTypeDistribution: { good_bot: 0.94, human: 0.02, bad_bot: 0.03, attack: 0.01 },\n riskScore: 0.1,\n riskConfidence: 0.95,\n riskLevelDistribution: { '0': 0.92, '1': 0.07, '2': 0.01, '3': 0.0 }\n };\n }\n\n // Known attack tools\n if (context.suspiciousSignatures.length > 0) {\n botScore = 0.99;\n attackScore = 0.98;\n spoofScore = 0.85;\n }\n\n // Common CLI / automation tools\n const cliTools = [\n 'curl/', 'python-requests', 'aiohttp', 'httpx', 'wget/', 'go-http-client',\n 'axios/', 'node-fetch', 'libwww-perl', 'postmanruntime', 'scrapy'\n ];\n if (cliTools.some((t) => userAgent.includes(t))) {\n botScore = Math.max(botScore, 0.92);\n }\n\n // Headless browsers\n if (\n userAgent.includes('headlesschrome') ||\n userAgent.includes('phantomjs') ||\n userAgent.includes('selenium') ||\n userAgent.includes('puppeteer')\n ) {\n botScore = Math.max(botScore, 0.97);\n spoofScore = Math.max(spoofScore, 0.80);\n }\n\n // Missing browser headers when claiming browser\n if (context.claimsBrowser && context.missingBrowserHeaders.length > 0) {\n spoofScore = Math.max(spoofScore, 0.40 + context.missingBrowserHeaders.length * 0.20);\n botScore = Math.max(botScore, 0.65);\n }\n\n // Common sensitive path hunting & vulnerability scanning\n const sensitivePaths = [\n '/.env',\n '/wp-login.php',\n '/wp-admin',\n '/.git',\n '/actuator',\n '/phpmyadmin',\n '/config.json',\n '/database.yml',\n '/.aws/credentials'\n ];\n if (sensitivePaths.some((p) => path.includes(p))) {\n attackScore = Math.max(attackScore, 0.85);\n botScore = Math.max(botScore, 0.80);\n }\n\n // Injection signatures (SQLi, XSS, Path Traversal, Command Injection, Log4j)\n const sqliSignatures = [\n \"' or 1=1\", '\" or 1=1', 'union select', 'union all select',\n 'sleep(', 'benchmark(', 'information_schema', 'select sleep'\n ];\n const xssSignatures = ['<script>', 'javascript:', '<svg onload', 'onerror=alert'];\n const traversalSignatures = ['../', '..\\\\', '%2e%2e%2f', '%252e%252e'];\n const cmdSignatures = ['; cat ', '| whoami', '&& id', '`whoami`', '${jndi:'];\n\n if (sqliSignatures.some((sig) => fullTarget.includes(sig))) {\n attackScore = Math.max(attackScore, 0.96);\n botScore = Math.max(botScore, 0.75);\n }\n if (xssSignatures.some((sig) => fullTarget.includes(sig))) {\n attackScore = Math.max(attackScore, 0.92);\n }\n if (traversalSignatures.some((sig) => fullTarget.includes(sig))) {\n attackScore = Math.max(attackScore, 0.95);\n botScore = Math.max(botScore, 0.80);\n }\n if (cmdSignatures.some((sig) => fullTarget.includes(sig))) {\n attackScore = Math.max(attackScore, 0.98);\n }\n\n // High entropy in query strings often signals binary shellcode or obfuscated injection\n if (queryStr.length > 30) {\n const entropy = calculateShannonEntropy(queryStr);\n if (entropy > 4.6 && attackScore < 0.6) {\n attackScore = Math.max(attackScore, 0.65);\n }\n }\n\n // Determine traffic category\n let trafficType: 'human' | 'good_bot' | 'bad_bot' | 'attack' = 'human';\n if (attackScore >= 0.70) {\n trafficType = 'attack';\n } else if (botScore >= 0.60) {\n trafficType = 'bad_bot';\n }\n\n let calculatedRisk = attackScore * 2.8 + botScore * 0.7;\n if (calculatedRisk > 3.0) calculatedRisk = 3.0;\n\n const typeDistribution: Record<string, number> = {\n human: trafficType === 'human' ? 0.85 : 0.05,\n good_bot: 0.02,\n bad_bot: trafficType === 'bad_bot' ? 0.80 : 0.10,\n attack: trafficType === 'attack' ? 0.90 : 0.05\n };\n const total = Object.values(typeDistribution).reduce((a, b) => a + b, 0);\n for (const k of Object.keys(typeDistribution)) {\n typeDistribution[k] = Math.round((typeDistribution[k] / total) * 100) / 100;\n }\n\n return {\n isBotProbability: Math.min(1.0, Math.round(botScore * 100) / 100),\n isAttackProbability: Math.min(1.0, Math.round(attackScore * 100) / 100),\n isSpoofedProbability: Math.min(1.0, Math.round(spoofScore * 100) / 100),\n trafficType,\n trafficTypeConfidence: 0.88,\n trafficTypeDistribution: typeDistribution,\n riskScore: Math.round(calculatedRisk * 100) / 100,\n riskConfidence: 0.85,\n riskLevelDistribution: {\n '0': calculatedRisk < 0.5 ? 0.9 : 0.05,\n '1': calculatedRisk >= 0.5 && calculatedRisk < 1.5 ? 0.8 : 0.1,\n '2': calculatedRisk >= 1.5 && calculatedRisk < 2.5 ? 0.85 : 0.1,\n '3': calculatedRisk >= 2.5 ? 0.9 : 0.05\n }\n };\n}\n", "import { createHash, createHmac, randomBytes } from 'node:crypto';\n\nconst DEFAULT_SECRET = 'traffic-guard-default-secret-key-32b!';\n\nexport interface BotCookiePayload {\n h: string; // client signature hash (ip + ua)\n c: number; // request count in window\n ws: number; // window start timestamp\n v?: number; // verified until timestamp\n}\n\nexport function createClientHash(ip: string = '', userAgent: string = ''): string {\n return createHash('sha256')\n .update(`${ip}::${userAgent.toLowerCase()}`)\n .digest('hex')\n .slice(0, 16);\n}\n\nexport function signBotToken(payload: BotCookiePayload, secret: string = DEFAULT_SECRET): string {\n const jsonStr = JSON.stringify(payload);\n const b64Payload = Buffer.from(jsonStr, 'utf8').toString('base64url');\n const signature = createHmac('sha256', secret).update(b64Payload).digest('base64url');\n return `${b64Payload}.${signature}`;\n}\n\nexport function verifyBotToken(token: string, secret: string = DEFAULT_SECRET): BotCookiePayload | null {\n try {\n const parts = token.split('.');\n if (parts.length !== 2) return null;\n const [b64Payload, signature] = parts;\n const expectedSig = createHmac('sha256', secret).update(b64Payload).digest('base64url');\n if (signature !== expectedSig) return null;\n const jsonStr = Buffer.from(b64Payload, 'base64url').toString('utf8');\n return JSON.parse(jsonStr) as BotCookiePayload;\n } catch {\n return null;\n }\n}\n\nexport function parseCookies(cookieHeader: string = ''): Record<string, string> {\n const cookies: Record<string, string> = {};\n if (!cookieHeader) return cookies;\n const pairs = cookieHeader.split(';');\n for (const pair of pairs) {\n const idx = pair.indexOf('=');\n if (idx > 0) {\n const key = pair.slice(0, idx).trim();\n const val = pair.slice(idx + 1).trim();\n cookies[key] = val;\n }\n }\n return cookies;\n}\n\nexport function createPoWChallenge(secret: string = DEFAULT_SECRET, difficulty: number = 4): { seed: string; difficulty: number } {\n const ts = Date.now();\n const rand = randomBytes(8).toString('hex');\n const payload = `${ts}:${rand}:${difficulty}`;\n const sig = createHmac('sha256', secret).update(payload).digest('hex').slice(0, 16);\n const seed = `${payload}:${sig}`;\n return { seed, difficulty };\n}\n\nexport function verifyPoW(seed: string, nonce: string, minDifficulty: number = 1, secret: string = DEFAULT_SECRET): boolean {\n try {\n const parts = seed.split(':');\n if (parts.length !== 4) return false;\n const [tsStr, rand, diffStr, sig] = parts;\n const payload = `${tsStr}:${rand}:${diffStr}`;\n const expectedSig = createHmac('sha256', secret).update(payload).digest('hex').slice(0, 16);\n if (sig !== expectedSig) return false;\n\n // Reject puzzles older than 3 minutes\n const ts = parseInt(tsStr, 10);\n if (Date.now() - ts > 180_000) return false;\n\n const diff = parseInt(diffStr, 10);\n if (diff < minDifficulty) return false;\n\n // Check proof-of-work\n const hash = createHash('sha256').update(`${seed}:${nonce}`).digest('hex');\n return hash.startsWith('0'.repeat(diff));\n } catch {\n return false;\n }\n}\n\nexport function generateChallengeHtml(seed: string, difficulty: number, returnUrl: string = '/'): string {\n return `<!DOCTYPE html>\n<html lang=\"en\">\n<head>\n <meta charset=\"utf-8\">\n <meta name=\"viewport\" content=\"width=device-width, initial-scale=1\">\n <title>Verifying Connection...</title>\n <style>\n body { font-family: -apple-system, BlinkMacSystemFont, \"Segoe UI\", Roboto, sans-serif; display: flex; justify-content: center; align-items: center; height: 100vh; margin: 0; background: #fafafa; color: #222; }\n .card { background: #fff; border: 1px solid #e0e0e0; border-radius: 8px; padding: 32px; max-width: 400px; text-align: center; box-shadow: 0 4px 12px rgba(0,0,0,0.05); }\n .spinner { border: 3px solid #f3f3f3; border-top: 3px solid #111; border-radius: 50%; width: 32px; height: 32px; animation: spin 0.8s linear infinite; margin: 20px auto; }\n @keyframes spin { 0% { transform: rotate(0deg); } 100% { transform: rotate(360deg); } }\n h2 { font-size: 18px; margin-bottom: 8px; }\n p { font-size: 14px; color: #666; margin: 0; }\n </style>\n</head>\n<body>\n <div class=\"card\">\n <h2>Verifying Connection</h2>\n <p>Please wait a moment while your browser verifies your session...</p>\n <div class=\"spinner\"></div>\n </div>\n <script>\n (async function() {\n const seed = \"${seed}\";\n const difficulty = ${difficulty};\n const returnUrl = \"${returnUrl}\";\n const targetPrefix = \"0\".repeat(difficulty);\n\n // Automated browser checks\n const isAutomated = !!(navigator.webdriver || window._phantom || window.__nightmare || !window.chrome);\n\n async function sha256(message) {\n const msgBuffer = new TextEncoder().encode(message);\n const hashBuffer = await crypto.subtle.digest('SHA-256', msgBuffer);\n const hashArray = Array.from(new Uint8Array(hashBuffer));\n return hashArray.map(b => b.toString(16).padStart(2, '0')).join('');\n }\n\n let nonce = 0;\n while (true) {\n const hash = await sha256(seed + \":\" + nonce);\n if (hash.startsWith(targetPrefix)) break;\n nonce++;\n if (nonce > 500000) break;\n }\n\n try {\n const res = await fetch(\"/__trafficguard/verify\", {\n method: \"POST\",\n headers: { \"Content-Type\": \"application/json\" },\n body: JSON.stringify({ seed, nonce: String(nonce), isAutomated, returnUrl })\n });\n if (res.ok) {\n window.location.href = returnUrl;\n } else {\n document.querySelector(\"p\").innerText = \"Verification challenge failed.\";\n }\n } catch (e) {\n window.location.reload();\n }\n })();\n </script>\n</body>\n</html>`;\n}\n", "import { calculateShannonEntropy } from './battery.js';\nimport { parseCookies } from './crypto.js';\nimport type { NormalizedRequest, RequestContext, RequestInput } from './types.js';\n\nconst KNOWN_GOOD_BOTS = [\n 'googlebot',\n 'bingbot',\n 'yandexbot',\n 'duckduckbot',\n 'slurp',\n 'baiduspider',\n 'facebookexternalhit',\n 'twitterbot',\n 'linkedinbot',\n 'embedly',\n 'quora link preview',\n 'showyoubot',\n 'outbrain',\n 'pinterest',\n 'slackbot',\n 'vkshare',\n 'w3c_validator',\n 'uptime'\n];\n\nconst KNOWN_ATTACK_TOOLS = [\n 'sqlmap',\n 'nikto',\n 'nmap',\n 'masscan',\n 'acunetix',\n 'dirbuster',\n 'gobuster',\n 'wfuzz',\n 'burpcollaborator',\n 'hydra',\n 'havij'\n];\n\nexport function checkHeaderOrderAnomaly(rawHeaders: string[] | undefined, userAgent: string): boolean {\n if (!rawHeaders || rawHeaders.length < 6) return false;\n\n const order: string[] = [];\n for (let i = 0; i < rawHeaders.length; i += 2) {\n order.push(rawHeaders[i].toLowerCase());\n }\n\n const ua = userAgent.toLowerCase();\n const claimsChromium = ua.includes('chrome/') || ua.includes('edg/');\n const hostIdx = order.indexOf('host');\n const uaIdx = order.indexOf('user-agent');\n const secChUaIdx = order.indexOf('sec-ch-ua');\n\n // Anomaly 1: User-Agent sent BEFORE Host (common in scripts like python-requests or manual curl)\n if (uaIdx !== -1 && hostIdx !== -1 && uaIdx < hostIdx) {\n return true;\n }\n\n // Anomaly 2: Claims Chromium, but sec-ch-ua is placed at the end after accept-encoding/language\n if (claimsChromium && secChUaIdx !== -1 && uaIdx !== -1) {\n // In real Chromium, sec-ch-ua precedes or immediately neighbors User-Agent\n const acceptEncIdx = order.indexOf('accept-encoding');\n if (acceptEncIdx !== -1 && secChUaIdx > acceptEncIdx + 2) {\n return true;\n }\n }\n\n return false;\n}\n\nexport function normalizeRequest(input: RequestInput): {\n request: NormalizedRequest;\n context: RequestContext;\n} {\n let method = 'GET';\n let path = '/';\n let query: Record<string, string | string[]> = {};\n const headers: Record<string, string> = {};\n let rawHeaders: string[] | undefined;\n let body: string | Record<string, unknown> | null = null;\n let ip: string | undefined;\n let cookies: Record<string, string> = {};\n\n if (typeof input === 'string') {\n try {\n const parsed = new URL(input, 'http://localhost');\n path = parsed.pathname;\n parsed.searchParams.forEach((v, k) => {\n query[k] = v;\n });\n } catch {\n path = input;\n }\n } else if (typeof input === 'object' && input !== null) {\n const raw = input as any;\n method = (raw.method || 'GET').toUpperCase();\n\n const rawUrl = raw.url || raw.originalUrl || raw.path || '/';\n try {\n const parsed = new URL(rawUrl, 'http://localhost');\n path = parsed.pathname;\n parsed.searchParams.forEach((v, k) => {\n query[k] = v;\n });\n } catch {\n path = typeof rawUrl === 'string' ? rawUrl : '/';\n }\n\n if (raw.query && typeof raw.query === 'object') {\n query = { ...query, ...raw.query };\n }\n\n if (raw.headers && typeof raw.headers === 'object') {\n for (const [k, v] of Object.entries(raw.headers)) {\n if (typeof v === 'string') {\n headers[k.toLowerCase()] = v;\n } else if (Array.isArray(v)) {\n headers[k.toLowerCase()] = v.join(', ');\n }\n }\n }\n\n rawHeaders = raw.rawHeaders;\n body = raw.body ?? null;\n ip = raw.ip || raw.socket?.remoteAddress || headers['x-forwarded-for']?.split(',')[0]?.trim();\n cookies = raw.cookies || parseCookies(headers['cookie']);\n }\n\n const userAgent = (headers['user-agent'] || '').toLowerCase();\n const claimsBrowser =\n userAgent.includes('mozilla/') &&\n (userAgent.includes('chrome/') ||\n userAgent.includes('safari/') ||\n userAgent.includes('firefox/') ||\n userAgent.includes('edg/'));\n\n const isKnownSearchBot = KNOWN_GOOD_BOTS.some((bot) => userAgent.includes(bot));\n\n const missingBrowserHeaders: string[] = [];\n if (claimsBrowser && !isKnownSearchBot) {\n if (!headers['accept-language']) missingBrowserHeaders.push('accept-language');\n if (!headers['accept-encoding']) missingBrowserHeaders.push('accept-encoding');\n const isChromium = userAgent.includes('chrome/') || userAgent.includes('edg/');\n if (isChromium && !headers['sec-ch-ua']) {\n missingBrowserHeaders.push('sec-ch-ua');\n }\n }\n\n const suspiciousSignatures: string[] = [];\n for (const tool of KNOWN_ATTACK_TOOLS) {\n if (userAgent.includes(tool)) {\n suspiciousSignatures.push(`known_attack_tool:${tool}`);\n }\n }\n\n const headerOrderAnomaly = checkHeaderOrderAnomaly(rawHeaders, userAgent);\n const targetForEntropy = path + ' ' + JSON.stringify(query);\n const shannonEntropy = calculateShannonEntropy(targetForEntropy);\n\n const normalized: NormalizedRequest = {\n method,\n path,\n query,\n headers,\n rawHeaders,\n body,\n ip,\n url: path,\n cookies\n };\n\n const context: RequestContext = {\n missingBrowserHeaders,\n suspiciousSignatures,\n claimsBrowser,\n isKnownSearchBot,\n headerOrderAnomaly,\n shannonEntropy\n };\n\n return { request: normalized, context };\n}\n", "import type {\n ActionType,\n AssessmentResult,\n BotGateDecision,\n GatePolicy,\n PolicyName,\n BotGateOptions,\n RequestContext\n} from './types.js';\n\nexport const DEFAULT_POLICIES: Record<PolicyName, GatePolicy> = {\n balanced: {\n attackThreshold: 0.75,\n botThreshold: 0.85,\n challengeThreshold: 0.50,\n riskBlock: 2.2,\n riskChallenge: 1.4,\n spoofThreshold: 0.60,\n velocityBurstLimit: 40 // requests per 10s window\n },\n strict: {\n attackThreshold: 0.60,\n botThreshold: 0.70,\n challengeThreshold: 0.35,\n riskBlock: 1.8,\n riskChallenge: 1.0,\n spoofThreshold: 0.40,\n velocityBurstLimit: 20\n },\n permissive: {\n attackThreshold: 0.88,\n botThreshold: 0.92,\n challengeThreshold: 0.70,\n riskBlock: 2.6,\n riskChallenge: 2.0,\n spoofThreshold: 0.75,\n velocityBurstLimit: 80\n }\n};\n\nexport function resolvePolicy(policy?: PolicyName | Partial<GatePolicy>): GatePolicy {\n if (typeof policy === 'string') {\n return DEFAULT_POLICIES[policy] || DEFAULT_POLICIES.balanced;\n }\n if (typeof policy === 'object' && policy !== null) {\n return {\n ...DEFAULT_POLICIES.balanced,\n ...policy\n };\n }\n return DEFAULT_POLICIES.balanced;\n}\n\nexport function evaluateDecision(\n assessment: AssessmentResult,\n policy: GatePolicy,\n options: BotGateOptions,\n durationMs: number,\n context?: RequestContext\n): BotGateDecision {\n const allowGoodBots = options.allowGoodBots !== false;\n const reasons: string[] = [];\n\n // Honeypot trigger: immediate block\n if (context?.isHoneypot) {\n return {\n action: 'block',\n shouldBlock: true,\n shouldChallenge: false,\n shouldTarpit: false,\n isBot: true,\n isAttack: true,\n category: 'attack',\n riskScore: 3.0,\n confidence: 1.0,\n reasons: ['Visited canary honeypot URL trap intended for crawlers'],\n assessment: {\n ...assessment,\n isAttackProbability: 1.0,\n isBotProbability: 1.0,\n riskScore: 3.0\n },\n durationMs\n };\n }\n\n // Check good bot exception\n if (allowGoodBots && assessment.trafficType === 'good_bot' && assessment.isAttackProbability < 0.4) {\n return {\n action: 'allow',\n shouldBlock: false,\n shouldChallenge: false,\n shouldTarpit: false,\n isBot: true,\n isAttack: false,\n category: 'good_bot',\n riskScore: assessment.riskScore,\n confidence: assessment.trafficTypeConfidence,\n reasons: ['Verified legitimate crawler allowed by policy'],\n assessment,\n durationMs\n };\n }\n\n let action: ActionType = 'allow';\n\n // 1. Attack evaluation (highest priority)\n if (assessment.isAttackProbability >= policy.attackThreshold) {\n action = 'block';\n reasons.push(\n `Detected malicious attack payload or exploit attempt (probability: ${Math.round(assessment.isAttackProbability * 100)}%)`\n );\n }\n\n // 2. Risk level evaluation\n if (assessment.riskScore >= policy.riskBlock) {\n action = 'block';\n reasons.push(`High risk severity score (${assessment.riskScore.toFixed(2)} >= ${policy.riskBlock})`);\n } else if (assessment.riskScore >= policy.riskChallenge && action !== 'block') {\n action = 'challenge';\n reasons.push(`Elevated risk severity score (${assessment.riskScore.toFixed(2)} >= ${policy.riskChallenge})`);\n }\n\n // 3. Velocity burst evaluation (advanced defense pattern)\n if (context?.rateCount && context.rateCount > policy.velocityBurstLimit) {\n if (action !== 'block') {\n action = 'tarpit';\n reasons.push(\n `High request burst velocity (${context.rateCount} reqs in window > ${policy.velocityBurstLimit} limit)`\n );\n }\n }\n\n // 4. Bad bot evaluation\n if (assessment.isBotProbability >= policy.botThreshold && assessment.trafficType === 'bad_bot') {\n if (action !== 'block') {\n action = 'block';\n reasons.push(\n `Unapproved automated bot/scraper detected (probability: ${Math.round(assessment.isBotProbability * 100)}%)`\n );\n }\n } else if (assessment.isBotProbability >= policy.challengeThreshold && action === 'allow') {\n action = 'challenge';\n reasons.push(\n `Possible automated traffic requiring verification (probability: ${Math.round(assessment.isBotProbability * 100)}%)`\n );\n }\n\n // 5. Header spoofing & ordering anomaly evaluation (advanced defense pattern)\n if (context?.headerOrderAnomaly) {\n reasons.push('Abnormal HTTP header sequence inconsistent with declared browser');\n if (action === 'allow') {\n action = 'challenge';\n }\n }\n if (assessment.isSpoofedProbability >= policy.spoofThreshold && action === 'allow') {\n action = 'challenge';\n reasons.push(\n `Suspicious header inconsistency or impersonation detected (probability: ${Math.round(assessment.isSpoofedProbability * 100)}%)`\n );\n }\n\n if (action === 'allow' && reasons.length === 0) {\n reasons.push('Traffic matches expected legitimate profile');\n }\n\n const shouldBlock = action === 'block';\n const shouldChallenge = action === 'challenge';\n const shouldTarpit = action === 'tarpit';\n const isBot = assessment.isBotProbability >= 0.5;\n const isAttack = assessment.isAttackProbability >= 0.5;\n\n const decision: BotGateDecision = {\n action,\n shouldBlock,\n shouldChallenge,\n shouldTarpit,\n isBot,\n isAttack,\n category: assessment.trafficType,\n riskScore: assessment.riskScore,\n confidence: assessment.trafficTypeConfidence,\n reasons,\n assessment,\n durationMs,\n async respond(res: any): Promise<boolean> {\n if (!res || typeof res.status !== 'function') return false;\n\n if (shouldTarpit) {\n if (options.onTarpit) {\n options.onTarpit(decision, null, res);\n } else {\n const delay = options.tarpitMs || 3000;\n await new Promise((r) => setTimeout(r, delay));\n res.status(429).json({\n error: 'Too Many Requests',\n message: 'Request velocity exceeded threshold',\n action: 'tarpit',\n reasons: decision.reasons\n });\n }\n return true;\n }\n\n if (shouldBlock) {\n if (options.onBlock) {\n options.onBlock(decision, null, res);\n } else {\n res.status(403).json({\n error: 'Forbidden',\n message: 'Access blocked by BotGate security policy',\n reasons: decision.reasons\n });\n }\n return true;\n }\n\n if (shouldChallenge) {\n if (options.onChallenge) {\n options.onChallenge(decision, null, res);\n } else if (options.enablePoWChallenge !== false && decision.challengeHtml) {\n res.status(428);\n res.setHeader('Content-Type', 'text/html; charset=utf-8');\n res.end(decision.challengeHtml);\n } else {\n res.status(428).json({\n error: 'Precondition Required',\n message: 'Traffic verification or challenge required',\n reasons: decision.reasons\n });\n }\n return true;\n }\n\n return false;\n }\n };\n\n return decision;\n}\n", "import { createBotGateBattery, heuristicAssessment, loadTypeSafePrimitives } from './battery.js';\nimport {\n createClientHash,\n createPoWChallenge,\n generateChallengeHtml,\n signBotToken,\n verifyBotToken,\n verifyPoW,\n type BotCookiePayload\n} from './crypto.js';\nimport { normalizeRequest } from './normalizer.js';\nimport { evaluateDecision, resolvePolicy } from './policy.js';\nimport type {\n AssessmentResult,\n BotGateDecision,\n BotGateOptions,\n RequestInput,\n TrafficCategory\n} from './types.js';\n\nlet sdkLoaded = false;\nlet TypeSafeClientClass: any = null;\n\nasync function getTypeSafeClientClass() {\n if (!sdkLoaded) {\n try {\n const sdk = await import('@typesafe-ai/sdk');\n TypeSafeClientClass = sdk.TypeSafeClient;\n await loadTypeSafePrimitives();\n } catch {\n TypeSafeClientClass = null;\n }\n sdkLoaded = true;\n }\n return TypeSafeClientClass;\n}\n\nexport class BotGate {\n private client: any = null;\n private clientInitAttempted = false;\n private options: BotGateOptions;\n private battery = createBotGateBattery();\n\n constructor(options: BotGateOptions = {}) {\n this.options = options;\n }\n\n private async getClient() {\n if (!this.clientInitAttempted) {\n this.clientInitAttempted = true;\n const apiKey = this.options.apiKey || process.env.TYPESAFE_API_KEY;\n if (apiKey) {\n const ClientClass = await getTypeSafeClientClass();\n if (ClientClass) {\n this.client = new ClientClass({\n apiKey,\n baseURL: this.options.endpoint || process.env.TYPESAFE_ENDPOINT,\n timeout: this.options.timeout || 15000\n });\n this.battery = createBotGateBattery();\n }\n }\n }\n return this.client;\n }\n\n async inspect(input: RequestInput, runtimeOptions: BotGateOptions = {}): Promise<BotGateDecision> {\n const startTime = performance.now();\n const opts = { ...this.options, ...runtimeOptions };\n const policy = resolvePolicy(opts.policy);\n const { request, context } = normalizeRequest(input);\n\n // Fast-path 1: Path whitelist\n if (opts.whitelistedPaths) {\n for (const pattern of opts.whitelistedPaths) {\n if (typeof pattern === 'string' && request.path === pattern) {\n return this.createAllowedDecision('Path whitelisted', startTime);\n }\n if (pattern instanceof RegExp && pattern.test(request.path)) {\n return this.createAllowedDecision('Path matched whitelist pattern', startTime);\n }\n }\n }\n\n // Fast-path 2: IP whitelist\n if (opts.whitelistedIps && request.ip && opts.whitelistedIps.includes(request.ip)) {\n return this.createAllowedDecision('Client IP whitelisted', startTime);\n }\n\n // Fast-path 3: Canary honeypot traps (advanced defense pattern)\n if (opts.honeypotPaths && opts.honeypotPaths.includes(request.path)) {\n context.isHoneypot = true;\n }\n\n // Fast-path 4: Stateless HMAC Cookie & Velocity Tracking (advanced defense pattern)\n const secret = opts.secretKey || process.env.TRAFFICGUARD_SECRET || process.env.BOTGATE_SECRET || 'traffic-guard-default-secret-key-32b!';\n const userAgent = request.headers['user-agent'] || '';\n const clientHash = createClientHash(request.ip, userAgent);\n const rawCookie = request.cookies?.['__trafficguard'] || request.cookies?.['__botgate'];\n const now = Date.now();\n\n let cookiePayload: BotCookiePayload | null = null;\n if (rawCookie) {\n cookiePayload = verifyBotToken(rawCookie, secret);\n }\n\n // Check if client previously verified a challenge and token is valid\n if (cookiePayload && cookiePayload.h === clientHash && cookiePayload.v && cookiePayload.v > now) {\n // Verified human pass\n return this.createAllowedDecision('Client passed cryptographic verification', startTime);\n }\n\n // Track request velocity in 10-second sliding window\n let currentCount = 1;\n let windowStart = now;\n if (cookiePayload && cookiePayload.h === clientHash) {\n if (now - cookiePayload.ws < 10_000) {\n currentCount = cookiePayload.c + 1;\n windowStart = cookiePayload.ws;\n }\n }\n context.rateCount = currentCount;\n\n let assessment: AssessmentResult;\n const client = await this.getClient();\n\n if (client && !context.isHoneypot) {\n try {\n const state = {\n request: {\n method: request.method,\n path: request.path,\n headers: request.headers,\n query: request.query,\n body: (request.body ?? null) as any,\n ip: (request.ip ?? null) as any\n },\n context: {\n missing_browser_headers: context.missingBrowserHeaders,\n suspicious_signatures: context.suspiciousSignatures,\n claims_browser: context.claimsBrowser,\n is_known_search_bot: context.isKnownSearchBot,\n header_order_anomaly: context.headerOrderAnomaly,\n shannon_entropy: context.shannonEntropy,\n rate_count: context.rateCount\n }\n };\n\n const response = await client.systemOne({\n model: opts.model || 'jev-latest',\n state: state as any,\n questions: this.battery as any\n });\n\n const answers = response.answers as any;\n\n const isBotProb = answers.is_bot?.noul ?? 0.1;\n const isAttackProb = answers.is_attack?.noul ?? 0.05;\n const isSpoofedProb = answers.is_spoofed?.noul ?? 0.05;\n\n const trafficTypeAnswer = answers.traffic_type;\n const trafficType = (trafficTypeAnswer?.choice as TrafficCategory) || 'human';\n const trafficTypeConfidence = trafficTypeAnswer?.confidence ?? 0.8;\n const trafficTypeDist = trafficTypeAnswer?.probabilities ?? {};\n\n const riskAnswer = answers.risk_level;\n const riskScore = riskAnswer?.score ?? 0;\n const riskConfidence = riskAnswer?.confidence ?? 0.8;\n const riskDist = riskAnswer?.probabilities ?? {};\n\n assessment = {\n isBotProbability: isBotProb,\n isAttackProbability: isAttackProb,\n isSpoofedProbability: isSpoofedProb,\n trafficType,\n trafficTypeConfidence,\n trafficTypeDistribution: trafficTypeDist,\n riskScore,\n riskConfidence,\n riskLevelDistribution: riskDist\n };\n } catch (err) {\n if (opts.fallback === 'block') {\n return this.createBlockedDecision('TypeSafe API unavailable (fallback: block)', startTime);\n }\n if (opts.fallback === 'allow') {\n return this.createAllowedDecision('TypeSafe API unavailable (fallback: allow)', startTime);\n }\n assessment = heuristicAssessment(request, context);\n }\n } else {\n assessment = heuristicAssessment(request, context);\n }\n\n const durationMs = Math.round((performance.now() - startTime) * 100) / 100;\n const decision = evaluateDecision(assessment, policy, opts, durationMs, context);\n\n // Prepare updated stateless cookie\n const updatedPayload: BotCookiePayload = {\n h: clientHash,\n c: currentCount,\n ws: windowStart\n };\n const newToken = signBotToken(updatedPayload, secret);\n decision.setCookieHeader = `__trafficguard=${newToken}; Path=/; HttpOnly; SameSite=Lax; Max-Age=3600`;\n\n // If challenged, attach PoW challenge payload\n if (decision.shouldChallenge) {\n const pow = createPoWChallenge(secret, 4);\n decision.challengeHtml = generateChallengeHtml(pow.seed, pow.difficulty, request.url || '/');\n }\n\n return decision;\n }\n\n middleware(middlewareOptions: BotGateOptions = {}) {\n const opts = { ...this.options, ...middlewareOptions };\n const secret = opts.secretKey || process.env.TRAFFICGUARD_SECRET || process.env.BOTGATE_SECRET || 'traffic-guard-default-secret-key-32b!';\n\n return async (req: any, res: any, next: (err?: any) => void) => {\n try {\n // Handle PoW Challenge verification endpoint\n if (req.method === 'POST' && (req.url === '/__trafficguard/verify' || req.path === '/__trafficguard/verify' || req.url === '/__botgate/verify' || req.path === '/__botgate/verify')) {\n let body = req.body;\n if (typeof body === 'string') {\n try { body = JSON.parse(body); } catch {}\n }\n const { seed, nonce, isAutomated, returnUrl } = body || {};\n const isValid = !isAutomated && verifyPoW(seed, nonce, 1, secret);\n\n if (isValid) {\n const userAgent = req.headers['user-agent'] || '';\n const ip = req.ip || req.socket?.remoteAddress || '';\n const clientHash = createClientHash(ip, userAgent);\n // Grant 30 minutes verification\n const token = signBotToken({ h: clientHash, c: 1, ws: Date.now(), v: Date.now() + 1800_000 }, secret);\n res.setHeader('Set-Cookie', `__trafficguard=${token}; Path=/; HttpOnly; SameSite=Lax; Max-Age=1800`);\n return res.status(200).json({ status: 'ok', redirect: returnUrl || '/' });\n } else {\n return res.status(403).json({ error: 'Verification failed' });\n }\n }\n\n const decision = await this.inspect(req, opts);\n req.trafficGuard = decision;\n req.botGate = decision;\n\n if (decision.setCookieHeader) {\n res.setHeader('Set-Cookie', decision.setCookieHeader);\n }\n\n if (decision.shouldTarpit) {\n if (opts.onTarpit) {\n return opts.onTarpit(decision, req, res);\n }\n const delay = opts.tarpitMs || 3000;\n await new Promise((r) => setTimeout(r, delay));\n return res.status(429).json({\n error: 'Too Many Requests',\n message: 'Velocity exceeded threshold',\n action: decision.action,\n reasons: decision.reasons\n });\n }\n\n if (decision.shouldBlock) {\n if (opts.onBlock) {\n return opts.onBlock(decision, req, res);\n }\n return res.status(403).json({\n error: 'Forbidden',\n message: 'Access blocked by BotGate security policy',\n action: decision.action,\n reasons: decision.reasons,\n category: decision.category,\n riskScore: decision.riskScore\n });\n }\n\n if (decision.shouldChallenge) {\n if (opts.onChallenge) {\n return opts.onChallenge(decision, req, res);\n }\n if (opts.enablePoWChallenge !== false && decision.challengeHtml) {\n res.status(428);\n res.setHeader('Content-Type', 'text/html; charset=utf-8');\n return res.end(decision.challengeHtml);\n }\n res.setHeader('X-BotGate-Action', 'challenge');\n res.setHeader('X-BotGate-Risk', decision.riskScore.toString());\n } else {\n res.setHeader('X-BotGate-Action', 'allow');\n }\n\n next();\n } catch (err) {\n next(err);\n }\n };\n }\n\n private createAllowedDecision(reason: string, startTime: number): BotGateDecision {\n const durationMs = Math.round((performance.now() - startTime) * 100) / 100;\n return {\n action: 'allow',\n shouldBlock: false,\n shouldChallenge: false,\n shouldTarpit: false,\n isBot: false,\n isAttack: false,\n category: 'human',\n riskScore: 0,\n confidence: 1.0,\n reasons: [reason],\n assessment: {\n isBotProbability: 0,\n isAttackProbability: 0,\n isSpoofedProbability: 0,\n trafficType: 'human',\n trafficTypeConfidence: 1.0,\n trafficTypeDistribution: { human: 1.0 },\n riskScore: 0,\n riskConfidence: 1.0,\n riskLevelDistribution: { '0': 1.0 }\n },\n durationMs,\n respond: () => false\n };\n }\n\n private createBlockedDecision(reason: string, startTime: number): BotGateDecision {\n const durationMs = Math.round((performance.now() - startTime) * 100) / 100;\n return {\n action: 'block',\n shouldBlock: true,\n shouldChallenge: false,\n shouldTarpit: false,\n isBot: true,\n isAttack: true,\n category: 'attack',\n riskScore: 3.0,\n confidence: 1.0,\n reasons: [reason],\n assessment: {\n isBotProbability: 1.0,\n isAttackProbability: 1.0,\n isSpoofedProbability: 1.0,\n trafficType: 'attack',\n trafficTypeConfidence: 1.0,\n trafficTypeDistribution: { attack: 1.0 },\n riskScore: 3.0,\n riskConfidence: 1.0,\n riskLevelDistribution: { '3': 1.0 }\n },\n durationMs,\n respond: (res: any) => {\n if (res && typeof res.status === 'function') {\n res.status(403).json({ error: 'Forbidden', message: reason });\n return true;\n }\n return false;\n }\n };\n }\n}\n\nexport type TrafficGuard = BotGate;\nexport const TrafficGuard = BotGate;\n", "import { BotGate, TrafficGuard } from './gate.js';\nimport type { BotGateDecision, BotGateOptions, RequestInput, TrafficDecision, TrafficGuardOptions } from './types.js';\n\nlet defaultGuard: TrafficGuard | null = null;\n\nfunction getDefaultGuard(): TrafficGuard {\n if (!defaultGuard) {\n defaultGuard = new TrafficGuard();\n }\n return defaultGuard;\n}\n\n/**\n * Inspects an incoming request and returns a bot/attack defense decision in under 30 \u00B5s.\n *\n * @example\n * ```ts\n * import trafficguard from 'traffic-guard';\n *\n * const decision = await trafficguard(req);\n * if (decision.shouldBlock) {\n * return res.status(403).json({ error: 'Forbidden', reasons: decision.reasons });\n * }\n * ```\n */\nasync function trafficguard(input: RequestInput, options?: TrafficGuardOptions): Promise<TrafficDecision> {\n if (options) {\n const guard = new TrafficGuard(options);\n return guard.inspect(input);\n }\n return getDefaultGuard().inspect(input);\n}\n\ntrafficguard.create = (options?: TrafficGuardOptions) => new TrafficGuard(options);\n\ntrafficguard.inspect = (input: RequestInput, options?: TrafficGuardOptions) => {\n return trafficguard(input, options);\n};\n\ntrafficguard.middleware = (options?: TrafficGuardOptions) => {\n const guard = options ? new TrafficGuard(options) : getDefaultGuard();\n return guard.middleware(options);\n};\n\ntrafficguard.TrafficGuard = TrafficGuard;\ntrafficguard.BotGate = BotGate;\n\nconst botgate = trafficguard;\nconst trafficGuard = trafficguard;\n\nexport { TrafficGuard, BotGate, trafficguard, trafficGuard, botgate };\nexport { normalizeRequest, checkHeaderOrderAnomaly } from './normalizer.js';\nexport { DEFAULT_POLICIES, evaluateDecision, resolvePolicy } from './policy.js';\nexport { createBotGateBattery, heuristicAssessment, calculateShannonEntropy } from './battery.js';\nexport {\n signBotToken,\n verifyBotToken,\n createPoWChallenge,\n verifyPoW,\n generateChallengeHtml,\n createClientHash\n} from './crypto.js';\nexport type * from './types.js';\n\nexport default trafficguard;\n"],
5
+ "mappings": "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",
6
+ "names": ["sdkLoaded"]
7
+ }
@@ -0,0 +1,6 @@
1
+ import type { NormalizedRequest, RequestContext, RequestInput } from './types.js';
2
+ export declare function checkHeaderOrderAnomaly(rawHeaders: string[] | undefined, userAgent: string): boolean;
3
+ export declare function normalizeRequest(input: RequestInput): {
4
+ request: NormalizedRequest;
5
+ context: RequestContext;
6
+ };
@@ -0,0 +1,4 @@
1
+ import type { AssessmentResult, BotGateDecision, GatePolicy, PolicyName, BotGateOptions, RequestContext } from './types.js';
2
+ export declare const DEFAULT_POLICIES: Record<PolicyName, GatePolicy>;
3
+ export declare function resolvePolicy(policy?: PolicyName | Partial<GatePolicy>): GatePolicy;
4
+ export declare function evaluateDecision(assessment: AssessmentResult, policy: GatePolicy, options: BotGateOptions, durationMs: number, context?: RequestContext): BotGateDecision;
@@ -0,0 +1,96 @@
1
+ export type PolicyName = 'balanced' | 'strict' | 'permissive';
2
+ export type ActionType = 'allow' | 'challenge' | 'block' | 'tarpit' | 'monitor';
3
+ export type TrafficCategory = 'human' | 'good_bot' | 'bad_bot' | 'attack';
4
+ export interface NormalizedRequest {
5
+ method: string;
6
+ path: string;
7
+ query: Record<string, string | string[]>;
8
+ headers: Record<string, string>;
9
+ rawHeaders?: string[];
10
+ body?: string | Record<string, unknown> | null;
11
+ ip?: string;
12
+ url?: string;
13
+ cookies?: Record<string, string>;
14
+ }
15
+ export interface RequestContext {
16
+ missingBrowserHeaders: string[];
17
+ suspiciousSignatures: string[];
18
+ claimsBrowser: boolean;
19
+ isKnownSearchBot: boolean;
20
+ headerOrderAnomaly: boolean;
21
+ shannonEntropy: number;
22
+ rateCount?: number;
23
+ isHoneypot?: boolean;
24
+ }
25
+ export interface GatePolicy {
26
+ attackThreshold: number;
27
+ botThreshold: number;
28
+ challengeThreshold: number;
29
+ riskBlock: number;
30
+ riskChallenge: number;
31
+ spoofThreshold: number;
32
+ velocityBurstLimit: number;
33
+ }
34
+ export interface BotGateOptions {
35
+ policy?: PolicyName | Partial<GatePolicy>;
36
+ apiKey?: string;
37
+ endpoint?: string;
38
+ model?: string;
39
+ timeout?: number;
40
+ allowGoodBots?: boolean;
41
+ whitelistedPaths?: (string | RegExp)[];
42
+ whitelistedIps?: string[];
43
+ honeypotPaths?: string[];
44
+ secretKey?: string;
45
+ tarpitMs?: number;
46
+ enablePoWChallenge?: boolean;
47
+ fallback?: 'heuristic' | 'allow' | 'block';
48
+ onBlock?: (decision: BotGateDecision, req: unknown, res: unknown) => void;
49
+ onChallenge?: (decision: BotGateDecision, req: unknown, res: unknown) => void;
50
+ onTarpit?: (decision: BotGateDecision, req: unknown, res: unknown) => void;
51
+ }
52
+ export interface AssessmentResult {
53
+ isBotProbability: number;
54
+ isAttackProbability: number;
55
+ isSpoofedProbability: number;
56
+ trafficType: TrafficCategory;
57
+ trafficTypeConfidence: number;
58
+ trafficTypeDistribution: Record<string, number>;
59
+ riskScore: number;
60
+ riskConfidence: number;
61
+ riskLevelDistribution: Record<string, number>;
62
+ }
63
+ export interface BotGateDecision {
64
+ action: ActionType;
65
+ shouldBlock: boolean;
66
+ shouldChallenge: boolean;
67
+ shouldTarpit: boolean;
68
+ isBot: boolean;
69
+ isAttack: boolean;
70
+ category: TrafficCategory;
71
+ riskScore: number;
72
+ confidence: number;
73
+ reasons: string[];
74
+ assessment: AssessmentResult;
75
+ durationMs: number;
76
+ setCookieHeader?: string;
77
+ challengeHtml?: string;
78
+ respond?: (res: any) => Promise<boolean> | boolean;
79
+ }
80
+ export type TrafficGuardOptions = BotGateOptions;
81
+ export type TrafficDecision = BotGateDecision;
82
+ export type RequestInput = string | NormalizedRequest | {
83
+ method?: string;
84
+ url?: string;
85
+ path?: string;
86
+ originalUrl?: string;
87
+ headers?: Record<string, string | string[] | undefined>;
88
+ rawHeaders?: string[];
89
+ query?: Record<string, unknown>;
90
+ body?: unknown;
91
+ ip?: string;
92
+ socket?: {
93
+ remoteAddress?: string;
94
+ };
95
+ cookies?: Record<string, string>;
96
+ };
package/package.json ADDED
@@ -0,0 +1,54 @@
1
+ {
2
+ "name": "traffic-guard",
3
+ "version": "0.1.0",
4
+ "description": "High-throughput traffic and attack defense gate with zero required dependencies, wire-order analysis, and TypeSafe System One acceleration.",
5
+ "type": "module",
6
+ "main": "dist/index.cjs",
7
+ "module": "dist/index.mjs",
8
+ "types": "dist/index.d.ts",
9
+ "exports": {
10
+ ".": {
11
+ "import": {
12
+ "types": "./dist/index.d.ts",
13
+ "default": "./dist/index.mjs"
14
+ },
15
+ "require": {
16
+ "types": "./dist/index.d.ts",
17
+ "default": "./dist/index.cjs"
18
+ }
19
+ }
20
+ },
21
+ "files": [
22
+ "dist",
23
+ "README.md",
24
+ "LICENSE"
25
+ ],
26
+ "scripts": {
27
+ "build": "node build.mjs && tsc --emitDeclarationOnly",
28
+ "test": "node --experimental-strip-types --test test/*.test.ts",
29
+ "prepublishOnly": "npm run build && npm test"
30
+ },
31
+ "keywords": [
32
+ "traffic-guard",
33
+ "bot-detection",
34
+ "waf",
35
+ "attack-detection",
36
+ "typesafe",
37
+ "system-one",
38
+ "security-gate",
39
+ "zero-dependency",
40
+ "express-middleware"
41
+ ],
42
+ "author": "Hemanth HM <hemanth@h3manth.com> (https://h3manth.com)",
43
+ "license": "MIT",
44
+ "dependencies": {},
45
+ "optionalDependencies": {
46
+ "@typesafe-ai/sdk": "^0.6.0"
47
+ },
48
+ "devDependencies": {
49
+ "@types/node": "^22.13.9",
50
+ "@typesafe-ai/sdk": "^0.6.0",
51
+ "esbuild": "^0.25.0",
52
+ "typescript": "^5.8.2"
53
+ }
54
+ }