@arcis/node 1.6.2 → 1.6.4
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +9 -7
- package/dist/_third_party/rate-limit/abstract.d.ts +36 -0
- package/dist/_third_party/rate-limit/abstract.d.ts.map +1 -0
- package/dist/_third_party/rate-limit/bursty.d.ts +21 -0
- package/dist/_third_party/rate-limit/bursty.d.ts.map +1 -0
- package/dist/_third_party/rate-limit/index.d.ts +12 -0
- package/dist/_third_party/rate-limit/index.d.ts.map +1 -0
- package/dist/_third_party/rate-limit/memory-storage.d.ts +28 -0
- package/dist/_third_party/rate-limit/memory-storage.d.ts.map +1 -0
- package/dist/_third_party/rate-limit/memory.d.ts +23 -0
- package/dist/_third_party/rate-limit/memory.d.ts.map +1 -0
- package/dist/_third_party/rate-limit/record.d.ts +11 -0
- package/dist/_third_party/rate-limit/record.d.ts.map +1 -0
- package/dist/_third_party/rate-limit/types.d.ts +39 -0
- package/dist/_third_party/rate-limit/types.d.ts.map +1 -0
- package/dist/astro/index.js +405 -0
- package/dist/astro/index.js.map +1 -1
- package/dist/astro/index.mjs +405 -0
- package/dist/astro/index.mjs.map +1 -1
- package/dist/bun/index.js +405 -0
- package/dist/bun/index.js.map +1 -1
- package/dist/bun/index.mjs +405 -0
- package/dist/bun/index.mjs.map +1 -1
- package/dist/fastify/index.js +405 -0
- package/dist/fastify/index.js.map +1 -1
- package/dist/fastify/index.mjs +405 -0
- package/dist/fastify/index.mjs.map +1 -1
- package/dist/hono/index.js +405 -0
- package/dist/hono/index.js.map +1 -1
- package/dist/hono/index.mjs +405 -0
- package/dist/hono/index.mjs.map +1 -1
- package/dist/index.d.ts +2 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +752 -4
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +752 -5
- package/dist/index.mjs.map +1 -1
- package/dist/koa/index.js +405 -0
- package/dist/koa/index.js.map +1 -1
- package/dist/koa/index.mjs +405 -0
- package/dist/koa/index.mjs.map +1 -1
- package/dist/middleware/brute-force.d.ts +69 -0
- package/dist/middleware/brute-force.d.ts.map +1 -0
- package/dist/middleware/index.js +700 -0
- package/dist/middleware/index.js.map +1 -1
- package/dist/middleware/index.mjs +700 -0
- package/dist/middleware/index.mjs.map +1 -1
- package/dist/middleware/nestjs.d.ts +50 -1
- package/dist/middleware/nestjs.d.ts.map +1 -1
- package/dist/middleware/protect.d.ts +9 -0
- package/dist/middleware/protect.d.ts.map +1 -1
- package/dist/nestjs/index.js +55 -1
- package/dist/nestjs/index.js.map +1 -1
- package/dist/nestjs/index.mjs +55 -2
- package/dist/nestjs/index.mjs.map +1 -1
- package/dist/nextjs/index.js +405 -0
- package/dist/nextjs/index.js.map +1 -1
- package/dist/nextjs/index.mjs +405 -0
- package/dist/nextjs/index.mjs.map +1 -1
- package/dist/nuxt/index.js +405 -0
- package/dist/nuxt/index.js.map +1 -1
- package/dist/nuxt/index.mjs +405 -0
- package/dist/nuxt/index.mjs.map +1 -1
- package/dist/sanitizers/prompt-injection.d.ts +3 -3
- package/dist/sanitizers/prompt-injection.d.ts.map +1 -1
- package/dist/sveltekit/index.js +405 -0
- package/dist/sveltekit/index.js.map +1 -1
- package/dist/sveltekit/index.mjs +405 -0
- package/dist/sveltekit/index.mjs.map +1 -1
- package/package.json +5 -5
- package/scripts/postinstall.cjs +1 -1
package/dist/index.mjs.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/core/constants.ts","../src/middleware/headers.ts","../src/middleware/rate-limit.ts","../src/middleware/error-handler.ts","../src/core/errors.ts","../src/middleware/telemetry.ts","../src/sanitizers/utils.ts","../src/sanitizers/xss.ts","../src/sanitizers/sql.ts","../src/sanitizers/path.ts","../src/sanitizers/command.ts","../src/sanitizers/ssti.ts","../src/sanitizers/xxe.ts","../src/sanitizers/ldap.ts","../src/sanitizers/xpath.ts","../src/sanitizers/headers.ts","../src/sanitizers/sanitize.ts","../src/sanitizers/nosql.ts","../src/sanitizers/prototype.ts","../src/sanitizers/jsonp.ts","../src/sanitizers/pii.ts","../src/sanitizers/encode.ts","../src/sanitizers/graphql.ts","../src/validation/schema.ts","../src/validation/file.ts","../src/validation/url.ts","../src/validation/url-async.ts","../src/validation/redirect.ts","../src/validation/email.ts","../src/logging/redactor.ts","../src/telemetry/client.ts","../src/middleware/main.ts","../src/utils/duration.ts","../src/middleware/rate-limit-sliding.ts","../src/middleware/rate-limit-token.ts","../src/middleware/cors.ts","../src/middleware/cookies.ts","../src/data/bot-patterns.json","../src/middleware/bot-detection.ts","../src/middleware/csrf.ts","../src/middleware/hpp.ts","../src/middleware/response-splitting.ts","../src/middleware/token-budget.ts","../src/middleware/overload.ts","../src/middleware/method-allowlist.ts","../src/middleware/mass-assign.ts","../src/middleware/signup-protection.ts","../src/middleware/protect.ts","../src/middleware/graphql.ts","../src/middleware/correlation.ts","../src/sanitizers/prompt-injection.ts","../src/guards.ts","../src/utils/ip.ts","../src/utils/fingerprint.ts","../src/stores/memory.ts","../src/stores/redis.ts"],"names":["resolve","lookup","host","dns","DEFAULTS","SEVERITY_RANK","xff","getHeader","DEFAULT_MAX_SIZE"],"mappings":"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","file":"index.mjs","sourcesContent":["/**\n * @module @arcis/node/core/constants\n * Named constants for Arcis - no magic numbers\n */\n\n// =============================================================================\n// INPUT LIMITS\n// =============================================================================\nexport const INPUT = {\n /** Default maximum input size (1MB) */\n DEFAULT_MAX_SIZE: 1_000_000,\n /** Maximum recursion depth for nested objects */\n MAX_RECURSION_DEPTH: 10,\n} as const;\n\n// =============================================================================\n// RATE LIMITING\n// =============================================================================\nexport const RATE_LIMIT = {\n /** Default window size (1 minute) */\n DEFAULT_WINDOW_MS: 60_000,\n /** Default max requests per window */\n DEFAULT_MAX_REQUESTS: 100,\n /** Default HTTP status code for rate limited responses */\n DEFAULT_STATUS_CODE: 429,\n /** Default error message */\n DEFAULT_MESSAGE: 'Too many requests, please try again later.',\n /** Minimum window size (1 second) */\n MIN_WINDOW_MS: 1_000,\n /** Maximum window size (24 hours) */\n MAX_WINDOW_MS: 86_400_000,\n} as const;\n\n// =============================================================================\n// SECURITY HEADERS\n// =============================================================================\nexport const HEADERS = {\n /** Default Content Security Policy */\n DEFAULT_CSP: [\n \"default-src 'self'\",\n \"script-src 'self'\",\n \"style-src 'self' 'unsafe-inline'\",\n \"img-src 'self' data: https:\",\n \"font-src 'self'\",\n \"object-src 'none'\",\n \"frame-ancestors 'none'\",\n ].join('; '),\n /** Default HSTS max age (1 year in seconds) */\n HSTS_MAX_AGE: 31_536_000,\n /** Default X-Frame-Options value */\n FRAME_OPTIONS: 'DENY' as const,\n /** Default X-Content-Type-Options value */\n CONTENT_TYPE_OPTIONS: 'nosniff',\n /** Default Referrer-Policy value */\n REFERRER_POLICY: 'strict-origin-when-cross-origin',\n /** Default Permissions-Policy value */\n PERMISSIONS_POLICY: 'geolocation=(), microphone=(), camera=()',\n /** Default Cache-Control value for security */\n CACHE_CONTROL: 'no-store, no-cache, must-revalidate, proxy-revalidate',\n} as const;\n\n// =============================================================================\n// XSS PATTERNS (ReDoS-safe)\n// =============================================================================\n\n/**\n * Detection patterns — used to flag whether a string contains XSS payloads.\n * Must stay in sync with XSS_REMOVE_PATTERNS below.\n */\nexport const XSS_PATTERNS = [\n /** Script tags (ReDoS-safe version) */\n /<script[^>]*>[\\s\\S]*?<\\/script>/gi,\n /** javascript: protocol (allow optional spaces before colon) */\n /javascript\\s*:/gi,\n /** vbscript: protocol */\n /vbscript\\s*:/gi,\n /** Event handlers (onclick, onerror, etc.) — any separator before attribute */\n /(?:[\\s/])on\\w+\\s*=/gi,\n /** iframe tags */\n /<iframe/gi,\n /** object tags */\n /<object/gi,\n /** embed tags */\n /<embed/gi,\n /** data: URIs (only dangerous ones, avoid false positives) */\n /(?:^|[\\s\"'=])data:/gi,\n /** URL-encoded script tags */\n /%3Cscript/gi,\n /** SVG with onload */\n /<svg[^>]*onload/gi,\n /** form tags — phishing/credential harvesting via action= redirection */\n /<form[\\s>]/gi,\n /** meta tags — http-equiv refresh redirects or CSP bypass */\n /<meta[\\s>]/gi,\n /** base href hijacking — redirects all relative URLs to attacker domain */\n /<base[\\s>]/gi,\n /** link tag injection — stylesheet or preload CSRF attacks */\n /<link[\\s>]/gi,\n /** style tag — CSS expression() / behavior: / IE-era attacks. Mirrors\n * Python's xss-style-tag from packages/core/patterns.json. */\n /<style[\\s>]/gi,\n] as const;\n\n/**\n * Removal patterns — used by sanitizeXss() to strip dangerous content.\n * More targeted than XSS_PATTERNS: each pattern captures the full dangerous\n * substring (tag, attribute + value, protocol) so it can be replaced safely.\n * Must stay in sync with XSS_PATTERNS above.\n */\nexport const XSS_REMOVE_PATTERNS = [\n /** Full script blocks (content + tags) */\n /<script[^>]*>[\\s\\S]*?<\\/script>/gi,\n /** Standalone/unclosed script tags */\n /<script[^>]*>/gi,\n /** style — CSS expression() and behavior: attacks (IE-era but still relevant) */\n /<style[^>]*>[\\s\\S]*?<\\/style>/gi,\n /<style[^>]*/gi,\n /** iframe — full block and partial/unclosed */\n /<iframe[^>]*>[\\s\\S]*?<\\/iframe>/gi,\n /<iframe[^>]*/gi,\n /** object — full block and partial/unclosed */\n /<object[^>]*>[\\s\\S]*?<\\/object>/gi,\n /<object[^>]*/gi,\n /** embed tags */\n /<embed[^>]*/gi,\n /** SVG with inline event handlers */\n /<svg[^>]*onload[^>]*>/gi,\n /** URL-encoded script tags */\n /%3Cscript/gi,\n /** Event handlers with quoted values: onclick=\"...\", onerror='...' */\n /(?:[\\s/])on\\w+\\s*=\\s*[\"'][^\"']*[\"']/gi,\n /** Event handlers with unquoted values: onload=value */\n /(?:[\\s/])on\\w+\\s*=\\s*[^\\s>]*/gi,\n /** javascript: and vbscript: protocols (allow optional spaces before colon) */\n /javascript\\s*:/gi,\n /vbscript\\s*:/gi,\n /** data: URIs with HTML or SVG content (SVG can run JS via inline event handlers) */\n /data\\s*:\\s*(?:text\\/html|image\\/svg)[^>\\s]*/gi,\n /** form tag injection — phishing via action= redirection */\n /<form[\\s>][^>]*/gi,\n /** meta tag injection — http-equiv refresh or CSP bypass */\n /<meta[\\s>][^>]*/gi,\n /** base href hijacking */\n /<base[\\s>][^>]*/gi,\n /** link tag injection — stylesheet or preload attacks */\n /<link[\\s>][^>]*/gi,\n] as const;\n\n// =============================================================================\n// SQL INJECTION PATTERNS\n// =============================================================================\nexport const SQL_PATTERNS = [\n /** SQL keywords */\n /(\\b(SELECT|INSERT|UPDATE|DELETE|DROP|UNION|ALTER|CREATE|TRUNCATE|EXEC|EXECUTE)\\b)/gi,\n /** SQL comments: ANSI (--), C-style (slash-star ... star-slash), MySQL (#) */\n /(--|\\/\\*|\\*\\/|#)/g,\n /** SQL statement separators */\n /(;|\\|\\||&&)/g,\n /** Boolean injection: OR 1=1 */\n /\\bOR\\s+\\d+\\s*=\\s*\\d+/gi,\n /** Boolean injection: OR 'a'='a' or OR \"a\"=\"a\" (including mixed quotes) */\n /\\bOR\\s+(['\"])[^'\"]*\\1\\s*=\\s*(['\"])[^'\"]*\\2/gi,\n /\\bOR\\s+('[^']*'|\"[^\"]*\")\\s*=\\s*('[^']*'|\"[^\"]*\")/gi,\n /** Boolean injection: AND 1=1 */\n /\\bAND\\s+\\d+\\s*=\\s*\\d+/gi,\n /** Boolean injection: AND 'a'='a' or AND \"a\"=\"a\" (including mixed quotes) */\n /\\bAND\\s+(['\"])[^'\"]*\\1\\s*=\\s*(['\"])[^'\"]*\\2/gi,\n /\\bAND\\s+('[^']*'|\"[^\"]*\")\\s*=\\s*('[^']*'|\"[^\"]*\")/gi,\n /** Time-based blind: SLEEP() */\n /\\bSLEEP\\s*\\(\\s*\\d+\\s*\\)/gi,\n /** Time-based blind: BENCHMARK() */\n /\\bBENCHMARK\\s*\\(/gi,\n /** Time-based blind: PostgreSQL pg_sleep() */\n /\\bpg_sleep\\s*\\(/gi,\n /** Time-based blind: MSSQL WAITFOR DELAY */\n /\\bWAITFOR\\s+DELAY\\b/gi,\n /**\n * Oracle DBMS_* stdlib packages used for time-based blind SQLi\n * (DBMS_LOCK.SLEEP, DBMS_PIPE.RECEIVE_MESSAGE) and other Oracle\n * abuse paths. No legitimate user input contains these. Mirrors\n * `sqli-oracle-dbms-packages` in packages/core/patterns.json —\n * improvements.md §1.1.e Q3. Must stay in sync until Node\n * migrates to patterns.json-at-runtime (planned v1.7).\n */\n /\\bDBMS_(?:LOCK|PIPE|UTILITY|XSLPROCESSOR|JAVA|OUTPUT|SCHEDULER)\\b/gi,\n] as const;\n\n// =============================================================================\n// PATH TRAVERSAL PATTERNS\n// =============================================================================\nexport const PATH_PATTERNS = [\n /** Unix path traversal */\n /\\.\\.\\//g,\n /** Windows path traversal */\n /\\.\\.\\\\/g,\n /** URL-encoded traversal (%2e%2e) */\n /%2e%2e/gi,\n /** Double URL-encoded traversal (%252e) */\n /%252e/gi,\n /** Mixed encoding: ..%2F */\n /\\.\\.%2F/gi,\n /** Mixed encoding: %2e./ and .%2e/ */\n /%2e\\.[\\\\/]/gi,\n /\\.%2e[\\\\/]/gi,\n /** Fully URL-encoded: %2e%2e%2f */\n /%2e%2e%2f/gi,\n /** Double URL-encoded forward slash: %252f */\n /%252f/gi,\n /** Dotdotslash bypass: ....// or ....\\\\ */\n /\\.{2,}[/\\\\]{2,}/g,\n /** Null byte injection in paths */\n /\\0/g,\n] as const;\n\n// =============================================================================\n// COMMAND INJECTION PATTERNS\n// =============================================================================\nexport const COMMAND_PATTERNS = [\n /**\n * Shell metacharacters that enable command chaining/substitution.\n * Bare ( and ) are excluded — they appear in common legitimate values\n * (function calls in code fields, math expressions, etc.).\n * Command substitution is caught by the $( combined pattern below.\n * NOTE: ';', '&', '|' may appear in legitimate URL query strings\n * and Markdown; consider disabling command checking (command: false)\n * for fields that intentionally allow those characters.\n */\n /[;&|`]/g,\n /** Command substitution: $( ... ) — matched as a pair to reduce false positives */\n /\\$\\(/g,\n /**\n * POSIX shell IFS-substitution: ${IFS} or ${IFS%??}.\n * Attackers use this to inject spaces past metacharacter filters\n * in payloads like `;cat${IFS}/etc/passwd`. Mirrors\n * `cmdi-ifs-bypass` in packages/core/patterns.json — improvements.md\n * §1.1.e Q5. Must stay in sync until Node migrates to\n * patterns.json-at-runtime (planned v1.7).\n */\n /\\$\\{IFS(?:%[^}]*)?\\}/g,\n /** URL-encoded control characters (%00-%0F): null, tab, vtab, formfeed, LF, CR */\n /%0[0-9a-f]/gi,\n] as const;\n\n// =============================================================================\n// DANGEROUS KEYS\n// =============================================================================\n\n/**\n * Prototype pollution keys to block.\n * Stored lowercase — always compare with key.toLowerCase().\n *\n * Includes:\n * - __proto__: direct prototype assignment\n * - constructor: access to constructor.prototype chain\n * - prototype: direct prototype property\n * - __defineGetter__/__defineSetter__: legacy property definition (can override getters/setters)\n * - __lookupGetter__/__lookupSetter__: legacy property introspection\n */\nexport const DANGEROUS_PROTO_KEYS = new Set([\n '__proto__',\n 'constructor',\n 'prototype',\n '__definegetter__',\n '__definesetter__',\n '__lookupgetter__',\n '__lookupsetter__',\n]);\n\n/** MongoDB operators to block */\nexport const NOSQL_DANGEROUS_KEYS = new Set([\n // Comparison\n '$gt', '$gte', '$lt', '$lte', '$ne', '$eq', '$in', '$nin',\n // Logical\n '$and', '$or', '$not', '$nor',\n // Element / evaluation\n '$exists', '$type', '$regex', '$where', '$expr', '$mod', '$text', '$jsonSchema',\n // Array\n '$elemMatch', '$all', '$size',\n // JavaScript execution (critical)\n '$function', '$accumulator',\n // Aggregation pipeline operators (injectable via $lookup etc.)\n '$lookup', '$match', '$project', '$group', '$sort', '$limit', '$skip',\n '$unwind', '$addFields', '$replaceRoot',\n]);\n\n// =============================================================================\n// REDACTION\n// =============================================================================\nexport const REDACTION = {\n /** Replacement text for redacted values */\n REPLACEMENT: '[REDACTED]',\n /** Truncation indicator */\n TRUNCATED: '[TRUNCATED]',\n /** Max depth indicator */\n MAX_DEPTH: '[MAX_DEPTH]',\n /** Default max message length */\n DEFAULT_MAX_LENGTH: 10_000,\n /** Default sensitive keys to redact */\n SENSITIVE_KEYS: new Set([\n 'password', 'passwd', 'pwd', 'secret', 'token', 'apikey',\n 'api_key', 'apiKey', 'auth', 'authorization', 'credit_card',\n 'creditcard', 'cc', 'ssn', 'social_security', 'private_key',\n 'privateKey', 'access_token', 'accessToken', 'refresh_token',\n 'refreshToken', 'bearer', 'jwt', 'session', 'cookie',\n 'credentials', 'x-api-key', 'x-auth-token',\n ]),\n} as const;\n\n// =============================================================================\n// VALIDATION PATTERNS\n// =============================================================================\nexport const VALIDATION = {\n /**\n * Email regex pattern.\n * Rejects consecutive dots in local part (e.g. test..foo@example.com),\n * leading/trailing dots, and other common invalid forms.\n */\n EMAIL: /^[^\\s@.][^\\s@]*(?:\\.[^\\s@.][^\\s@]*)*@[^\\s@]+\\.[^\\s@]+$/,\n /**\n * URL regex pattern.\n * Only allows http:// and https:// (case-insensitive scheme per\n * RFC 3986); explicitly rejects javascript:, data:, vbscript:, and\n * other dangerous URI schemes.\n */\n URL: /^https?:\\/\\/[^\\s/$.?#][^\\s]*$/i,\n /** UUID regex pattern (v4) */\n UUID: /^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/i,\n} as const;\n\n// =============================================================================\n// ERROR MESSAGES\n// =============================================================================\nexport const ERRORS = {\n /** Generic error message (production) */\n INTERNAL_SERVER_ERROR: 'Internal Server Error',\n /** Input too large error */\n INPUT_TOO_LARGE: (maxSize: number) => `Input exceeds maximum size of ${maxSize} bytes`,\n /** Validation error messages */\n VALIDATION: {\n REQUIRED: (field: string) => `${field} is required`,\n INVALID_TYPE: (field: string, type: string) => `${field} must be a ${type}`,\n MIN_LENGTH: (field: string, min: number) => `${field} must be at least ${min} characters`,\n MAX_LENGTH: (field: string, max: number) => `${field} must be at most ${max} characters`,\n MIN_VALUE: (field: string, min: number) => `${field} must be at least ${min}`,\n MAX_VALUE: (field: string, max: number) => `${field} must be at most ${max}`,\n INVALID_FORMAT: (field: string) => `${field} format is invalid`,\n INVALID_EMAIL: (field: string) => `${field} must be a valid email`,\n INVALID_URL: (field: string) => `${field} must be a valid URL`,\n INVALID_UUID: (field: string) => `${field} must be a valid UUID`,\n INVALID_ENUM: (field: string, values: unknown[]) => `${field} must be one of: ${values.join(', ')}`,\n MIN_ITEMS: (field: string, min: number) => `${field} must have at least ${min} items`,\n MAX_ITEMS: (field: string, max: number) => `${field} must have at most ${max} items`,\n },\n} as const;\n\n// =============================================================================\n// BLOCKED TEXT (for sanitizer replacements)\n// =============================================================================\nexport const BLOCKED = '[BLOCKED]' as const;\n","/**\n * @module @arcis/node/middleware/headers\n * Security headers middleware\n */\n\nimport type { Request, Response, NextFunction, RequestHandler } from 'express';\nimport { HEADERS } from '../core/constants';\nimport type { HeaderOptions, HstsOptions } from '../core/types';\n\n/**\n * Create Express middleware for security headers.\n * Sets CSP, HSTS, X-Frame-Options, and other security headers.\n * \n * @param options - Header configuration\n * @returns Express middleware\n * \n * @example\n * app.use(createHeaders());\n * \n * @example\n * app.use(createHeaders({\n * frameOptions: 'SAMEORIGIN',\n * contentSecurityPolicy: \"default-src 'self'\"\n * }));\n */\nexport function createHeaders(options: HeaderOptions = {}): RequestHandler {\n const {\n contentSecurityPolicy = true,\n xssFilter = true,\n noSniff = true,\n frameOptions = HEADERS.FRAME_OPTIONS,\n hsts = true,\n referrerPolicy = HEADERS.REFERRER_POLICY,\n permissionsPolicy = HEADERS.PERMISSIONS_POLICY,\n cacheControl = true,\n crossOriginOpenerPolicy = 'same-origin',\n crossOriginResourcePolicy = 'same-origin',\n crossOriginEmbedderPolicy = 'require-corp',\n originAgentCluster = true,\n dnsPrefetchControl = true,\n } = options;\n\n return (req: Request, res: Response, next: NextFunction) => {\n // Content Security Policy\n if (contentSecurityPolicy) {\n const csp = typeof contentSecurityPolicy === 'string' \n ? contentSecurityPolicy \n : HEADERS.DEFAULT_CSP;\n res.setHeader('Content-Security-Policy', csp);\n }\n\n // X-XSS-Protection: 0 disables the legacy XSS auditor which was itself\n // an attack vector (could be abused to selectively block legitimate scripts)\n if (xssFilter) {\n res.setHeader('X-XSS-Protection', '0');\n }\n\n // Prevent MIME type sniffing\n if (noSniff) {\n res.setHeader('X-Content-Type-Options', HEADERS.CONTENT_TYPE_OPTIONS);\n }\n\n // Clickjacking protection\n if (frameOptions) {\n res.setHeader('X-Frame-Options', frameOptions);\n }\n\n // HTTPS enforcement (HSTS)\n // Only send HSTS over HTTPS — sending it over HTTP can brick HTTP-only\n // development servers and confuses browsers that cache the directive.\n // X-Forwarded-Proto is client-supplied so we validate the extracted value\n // is exactly 'https' or 'http' before trusting it.\n const forwardedProto = (req.headers['x-forwarded-proto'] as string | undefined)\n ?.split(',')[0]\n .trim()\n .toLowerCase();\n const trustedForwardedProto = forwardedProto === 'https' || forwardedProto === 'http'\n ? forwardedProto\n : undefined;\n const isHttps = req.secure || trustedForwardedProto === 'https';\n\n if (hsts && isHttps) {\n const hstsOpts: HstsOptions = typeof hsts === 'object' ? hsts : {};\n const maxAge = hstsOpts.maxAge ?? HEADERS.HSTS_MAX_AGE;\n const includeSubDomains = hstsOpts.includeSubDomains !== false;\n const preload = hstsOpts.preload === true;\n\n let hstsValue = `max-age=${maxAge}`;\n if (includeSubDomains) hstsValue += '; includeSubDomains';\n if (preload) hstsValue += '; preload';\n\n res.setHeader('Strict-Transport-Security', hstsValue);\n }\n\n // Referrer Policy\n if (referrerPolicy) {\n res.setHeader('Referrer-Policy', referrerPolicy);\n }\n\n // Permissions Policy\n if (permissionsPolicy) {\n res.setHeader('Permissions-Policy', permissionsPolicy);\n }\n\n // Cross-origin isolation headers (Spectre mitigation)\n if (crossOriginOpenerPolicy) {\n res.setHeader('Cross-Origin-Opener-Policy', crossOriginOpenerPolicy);\n }\n\n if (crossOriginResourcePolicy) {\n res.setHeader('Cross-Origin-Resource-Policy', crossOriginResourcePolicy);\n }\n\n if (crossOriginEmbedderPolicy) {\n res.setHeader('Cross-Origin-Embedder-Policy', crossOriginEmbedderPolicy);\n }\n\n // Request origin-keyed process isolation\n if (originAgentCluster) {\n res.setHeader('Origin-Agent-Cluster', '?1');\n }\n\n // Prevent DNS prefetching (privacy leak vector)\n if (dnsPrefetchControl) {\n res.setHeader('X-DNS-Prefetch-Control', 'off');\n }\n\n // Additional security headers\n res.setHeader('X-Permitted-Cross-Domain-Policies', 'none');\n\n // Cache-Control headers\n if (cacheControl) {\n const cacheControlValue = typeof cacheControl === 'string'\n ? cacheControl\n : HEADERS.CACHE_CONTROL;\n res.setHeader('Cache-Control', cacheControlValue);\n res.setHeader('Pragma', 'no-cache');\n res.setHeader('Expires', '0');\n }\n\n // Remove fingerprinting headers\n res.removeHeader('X-Powered-By');\n\n next();\n };\n}\n\n/**\n * Alias for createHeaders\n * @see createHeaders\n */\nexport const securityHeaders = createHeaders;\n","/**\n * @module @arcis/node/middleware/rate-limit\n * Rate limiting middleware\n */\n\nimport type { Request, Response, NextFunction, RequestHandler } from 'express';\nimport { RATE_LIMIT } from '../core/constants';\nimport type { RateLimitOptions, RateLimiterMiddleware, RateLimitEntry } from '../core/types';\n\n/** In-memory rate limit store */\ninterface InMemoryRateLimitStore {\n [key: string]: RateLimitEntry;\n}\n\n/**\n * Create Express middleware for rate limiting.\n * \n * @param options - Rate limit configuration\n * @returns Express middleware with cleanup method\n * \n * @example\n * app.use(createRateLimiter({ max: 100, windowMs: 60000 }));\n * \n * @example\n * // Skip rate limiting for certain routes\n * app.use(createRateLimiter({\n * max: 50,\n * skip: (req) => req.path === '/health'\n * }));\n * \n * @example\n * // Cleanup on shutdown\n * const limiter = createRateLimiter();\n * app.use(limiter);\n * process.on('SIGTERM', () => limiter.close());\n */\nexport function createRateLimiter(options: RateLimitOptions = {}): RateLimiterMiddleware {\n const {\n max = RATE_LIMIT.DEFAULT_MAX_REQUESTS,\n windowMs = RATE_LIMIT.DEFAULT_WINDOW_MS,\n message = RATE_LIMIT.DEFAULT_MESSAGE,\n statusCode = RATE_LIMIT.DEFAULT_STATUS_CODE,\n keyGenerator = (req) => {\n const ip = req.ip ?? req.socket?.remoteAddress;\n if (ip) return ip;\n // SECURITY: When IP is unresolvable, fall back to a fingerprint of UA +\n // Accept-Language so unresolvable clients don't share a single counter\n // (one attacker could exhaust the limit and block every other client).\n const ua = (req.headers['user-agent'] ?? '') as string;\n const lang = (req.headers['accept-language'] ?? '') as string;\n const fp = `${ua}|${lang}`;\n // Small non-crypto hash — just needs to disperse unknown clients\n let hash = 0;\n for (let i = 0; i < fp.length; i++) hash = ((hash << 5) - hash + fp.charCodeAt(i)) | 0;\n return `unknown:${hash.toString(36)}`;\n },\n skip,\n store: externalStore,\n } = options;\n\n // Object.create(null) avoids prototype pollution if keyGenerator ever\n // returns '__proto__', 'constructor', or 'prototype'.\n const inMemoryStore = Object.create(null) as InMemoryRateLimitStore;\n\n // Cleanup interval for in-memory store (only create if not using external store)\n let cleanupInterval: ReturnType<typeof setInterval> | null = null;\n \n if (!externalStore) {\n cleanupInterval = setInterval(() => {\n const now = Date.now();\n for (const key of Object.keys(inMemoryStore)) {\n if (inMemoryStore[key].resetTime < now) {\n delete inMemoryStore[key];\n }\n }\n }, windowMs);\n\n // Prevent interval from keeping the process alive (Node.js only)\n if (typeof cleanupInterval.unref === 'function') {\n cleanupInterval.unref();\n }\n }\n\n const handler: RequestHandler = async (req: Request, res: Response, next: NextFunction) => {\n try {\n if (skip?.(req)) {\n return next();\n }\n\n const key = keyGenerator(req);\n const now = Date.now();\n\n let count: number;\n let resetTime: number;\n\n if (externalStore) {\n // Use external store (e.g., Redis)\n const entry = await externalStore.get(key);\n if (!entry || entry.resetTime < now) {\n await externalStore.set(key, { count: 1, resetTime: now + windowMs });\n count = 1;\n resetTime = now + windowMs;\n } else {\n count = await externalStore.increment(key);\n resetTime = entry.resetTime;\n }\n } else {\n // Use in-memory store\n if (!inMemoryStore[key] || inMemoryStore[key].resetTime < now) {\n inMemoryStore[key] = { count: 1, resetTime: now + windowMs };\n } else {\n inMemoryStore[key].count++;\n }\n count = inMemoryStore[key].count;\n resetTime = inMemoryStore[key].resetTime;\n }\n\n const remaining = Math.max(0, max - count);\n const resetSeconds = Math.ceil((resetTime - now) / 1000);\n\n // Set rate limit headers\n res.setHeader('X-RateLimit-Limit', max.toString());\n res.setHeader('X-RateLimit-Remaining', remaining.toString());\n res.setHeader('X-RateLimit-Reset', resetSeconds.toString());\n\n if (count > max) {\n res.setHeader('Retry-After', resetSeconds.toString());\n res.status(statusCode).json({\n error: message,\n retryAfter: resetSeconds,\n });\n return;\n }\n\n next();\n } catch (error) {\n // External store failed — fall back to in-memory rate limiting.\n // Pure fail-open is a security bypass; in-memory fallback maintains protection.\n // eslint-disable-next-line no-console\n console.error('[arcis] Rate limiter store error, using in-memory fallback:', error);\n try {\n const key = keyGenerator(req);\n const now = Date.now();\n if (!inMemoryStore[key] || inMemoryStore[key].resetTime < now) {\n inMemoryStore[key] = { count: 1, resetTime: now + windowMs };\n } else {\n inMemoryStore[key].count++;\n }\n const count = inMemoryStore[key].count;\n if (count > max) {\n const resetSeconds = Math.ceil((inMemoryStore[key].resetTime - now) / 1000);\n res.setHeader('Retry-After', resetSeconds.toString());\n res.status(statusCode).json({ error: message, retryAfter: resetSeconds });\n return;\n }\n } catch {\n // If even fallback fails, allow through to preserve availability\n }\n next();\n }\n };\n\n // Attach close method for cleanup\n const middleware = handler as RateLimiterMiddleware;\n middleware.close = () => {\n if (cleanupInterval) {\n clearInterval(cleanupInterval);\n cleanupInterval = null;\n }\n };\n\n return middleware;\n}\n\n/**\n * Alias for createRateLimiter\n * @see createRateLimiter\n */\nexport const rateLimit = createRateLimiter;\n","/**\n * @module @arcis/node/middleware/error-handler\n * Production-safe error handler middleware\n */\n\nimport type { Request, Response, NextFunction } from 'express';\nimport { ERRORS } from '../core/constants';\nimport type { ErrorHandlerOptions, HttpError } from '../core/types';\n\n/**\n * Patterns that indicate database or infrastructure internals in error messages.\n * When detected, the message is replaced with a generic error to prevent info leakage.\n */\nconst SENSITIVE_ERROR_PATTERNS: RegExp[] = [\n // SQL database errors\n /\\b(SQLITE_ERROR|SQLSTATE|ORA-\\d|PG::|mysql_|pg_query|ECONNREFUSED)/i,\n /\\b(syntax error at or near|relation \".*\" does not exist)/i,\n /\\b(column \".*\" (does not exist|of relation))/i,\n /\\b(duplicate key value violates unique constraint)/i,\n /\\b(table .* doesn't exist|unknown column)/i,\n // MongoDB errors\n /\\b(MongoError|MongoServerError|MongoNetworkError|E11000 duplicate key)/i,\n // Redis errors\n /\\b(WRONGTYPE|CROSSSLOT|CLUSTERDOWN|READONLY|ReplyError)/i,\n // Connection strings and DSNs\n /\\b(mongodb(\\+srv)?:\\/\\/|postgres(ql)?:\\/\\/|mysql:\\/\\/|redis:\\/\\/)/i,\n // Stack traces with file paths\n /\\bat\\s+.*\\.(js|ts|py|go|java):\\d+/i,\n // Internal IP addresses\n /\\b(127\\.0\\.0\\.\\d+|10\\.\\d+\\.\\d+\\.\\d+|192\\.168\\.\\d+\\.\\d+|172\\.(1[6-9]|2\\d|3[01])\\.\\d+\\.\\d+)\\b/,\n];\n\n/**\n * Check if an error message contains sensitive infrastructure details.\n */\nexport function containsSensitiveInfo(message: string): boolean {\n return SENSITIVE_ERROR_PATTERNS.some(pattern => pattern.test(message));\n}\n\n/**\n * Create Express error handler that hides sensitive details in production.\n *\n * Prevents information leakage by:\n * - Hiding stack traces in production\n * - Hiding error messages unless explicitly exposed\n * - Scrubbing database errors, connection strings, and internal IPs\n *\n * @param options - Error handler configuration (or boolean for isDev)\n * @returns Express error handling middleware\n *\n * @example\n * // Production mode (default) - hides error details\n * app.use(errorHandler());\n *\n * @example\n * // Development mode - shows error details and stack traces\n * app.use(errorHandler({ isDev: true }));\n *\n * @example\n * // With custom logger\n * app.use(errorHandler({\n * isDev: false,\n * logger: arcis.logger()\n * }));\n */\nexport function errorHandler(\n options: ErrorHandlerOptions | boolean = false\n): (err: Error, req: Request, res: Response, next: NextFunction) => void {\n const isDev = typeof options === 'boolean' ? options : options.isDev ?? false;\n const logErrors = typeof options === 'object' ? options.logErrors ?? true : true;\n const logger = typeof options === 'object' ? options.logger : undefined;\n const customHandler = typeof options === 'object' ? options.customHandler : undefined;\n\n return (err: HttpError, req: Request, res: Response, _next: NextFunction) => {\n // Clamp to a valid HTTP error range. A thrown error with a bogus\n // statusCode (negative, zero, or > 599) would otherwise be sent to\n // the client and break proxies, browsers, or compliance scanners.\n const rawStatus = err.statusCode ?? err.status ?? 500;\n const statusCode =\n Number.isFinite(rawStatus) && rawStatus >= 400 && rawStatus <= 599\n ? Math.floor(rawStatus)\n : 500;\n\n // Custom handler takes precedence\n if (customHandler) {\n return customHandler(err, req, res);\n }\n\n // Always log full error details server-side\n if (logErrors) {\n const logData = {\n error: err.message,\n stack: err.stack,\n statusCode,\n path: req.path,\n method: req.method,\n };\n\n if (logger) {\n logger.error('Request error', logData);\n } else {\n // eslint-disable-next-line no-console\n console.error('[arcis] Request error:', logData);\n }\n }\n\n // Build response\n // Only expose err.message when err.expose === true (caller opted in) or in dev mode.\n // This prevents internal details leaking through arbitrary 4xx errors that happen\n // to contain sensitive info (e.g. \"DB query failed for user admin@corp.com\").\n const exposeMessage = isDev || err.expose === true;\n\n let clientMessage: string;\n if (!exposeMessage) {\n clientMessage = ERRORS.INTERNAL_SERVER_ERROR;\n } else if (containsSensitiveInfo(err.message)) {\n // Even when expose is true, scrub DB errors and infra details\n clientMessage = isDev ? err.message : ERRORS.INTERNAL_SERVER_ERROR;\n } else {\n clientMessage = err.message;\n }\n\n const response: Record<string, unknown> = {\n error: clientMessage,\n };\n\n // Only show details in development\n if (isDev) {\n response.stack = err.stack;\n response.details = err.message;\n }\n\n res.status(statusCode).json(response);\n };\n}\n\n/**\n * Alias for errorHandler\n * @see errorHandler\n */\nexport const createErrorHandler = errorHandler;\n","/**\n * @module @arcis/node/core/errors\n * Custom error classes for Arcis\n */\n\n/**\n * Base class for all Arcis errors\n */\nexport class ArcisError extends Error {\n public readonly statusCode: number;\n public readonly code: string;\n /** Whether the error message is safe to expose to API clients. */\n public readonly expose: boolean;\n\n constructor(message: string, statusCode = 500, code = 'ARCIS_ERROR') {\n super(message);\n this.name = 'ArcisError';\n this.statusCode = statusCode;\n this.code = code;\n // Client errors (4xx) have controlled messages — safe to expose.\n // Server errors (5xx) may contain internal details — hide by default.\n this.expose = statusCode < 500;\n\n // Maintains proper stack trace for where error was thrown (V8 engines)\n if (Error.captureStackTrace) {\n Error.captureStackTrace(this, this.constructor);\n }\n }\n}\n\n/**\n * Error thrown when input validation fails\n */\nexport class ValidationError extends ArcisError {\n public readonly errors: string[];\n\n constructor(errors: string[]) {\n super('Validation failed', 400, 'VALIDATION_ERROR');\n this.name = 'ValidationError';\n this.errors = errors;\n }\n}\n\n/** Alias for ValidationError (backwards compatibility) */\nexport { ValidationError as ArcisValidationError };\n\n/**\n * Error thrown when rate limit is exceeded\n */\nexport class RateLimitError extends ArcisError {\n public readonly retryAfter: number;\n\n constructor(message: string, retryAfter: number) {\n super(message, 429, 'RATE_LIMIT_EXCEEDED');\n this.name = 'RateLimitError';\n this.retryAfter = retryAfter;\n }\n}\n\n/**\n * Error thrown when input is too large\n */\nexport class InputTooLargeError extends ArcisError {\n public readonly maxSize: number;\n public readonly actualSize: number;\n\n constructor(maxSize: number, actualSize: number) {\n super(`Input exceeds maximum size of ${maxSize} bytes`, 413, 'INPUT_TOO_LARGE');\n this.name = 'InputTooLargeError';\n this.maxSize = maxSize;\n this.actualSize = actualSize;\n }\n}\n\n/**\n * Error thrown when security threat is detected\n */\nexport class SecurityThreatError extends ArcisError {\n public readonly threatType: string;\n public readonly pattern: string;\n\n constructor(threatType: string, pattern: string) {\n super('Request blocked for security reasons', 400, 'SECURITY_THREAT');\n this.name = 'SecurityThreatError';\n this.threatType = threatType;\n this.pattern = pattern;\n }\n}\n\n/**\n * Error thrown when sanitization fails\n */\nexport class SanitizationError extends ArcisError {\n constructor(message: string) {\n super(message, 400, 'SANITIZATION_ERROR');\n this.name = 'SanitizationError';\n }\n}\n","/**\n * @module @arcis/node/middleware/telemetry\n * Bridges Arcis middleware decisions to a TelemetryClient.\n * Pattern 3 (two-layer): the client owns transport; this layer owns Express plumbing.\n */\n\nimport type { Request, RequestHandler } from 'express';\nimport type { TelemetryClient } from '../telemetry/client';\nimport type { TelemetryEvent, TelemetryDecision, TelemetrySeverity } from '../telemetry/types';\nimport { SecurityThreatError } from '../core/errors';\n\n/** Marker that inner middleware writes to and the emitter reads from. */\nexport interface ArcisTelemetryMarker {\n vector?: string;\n rule?: string;\n severity?: TelemetrySeverity;\n matchedPattern?: string;\n reason?: string;\n /** Pre-decided decision. If absent, the emitter infers from response status. */\n decision?: TelemetryDecision;\n}\n\ndeclare module 'express-serve-static-core' {\n interface Request {\n /** Per-request marker populated by Arcis middlewares for telemetry attribution. */\n __arcis?: ArcisTelemetryMarker;\n }\n}\n\nconst THREAT_TO_VECTOR: Record<string, string> = {\n xss: 'xss',\n sql_injection: 'sql',\n nosql_injection: 'nosql',\n path_traversal: 'path',\n command_injection: 'command',\n prototype_pollution: 'prototype',\n header_injection: 'header',\n ssti: 'ssti',\n xxe: 'xxe',\n};\n\n/**\n * Express middleware that records a telemetry event for every request.\n * Captures latency from entry, hooks `res.on('finish')`, and infers the\n * final decision from response status + any `req.__arcis` marker.\n */\nexport function createTelemetryEmitter(client: TelemetryClient): RequestHandler {\n return (req, res, next) => {\n const start = performance.now();\n\n res.on('finish', () => {\n try {\n const event = buildEvent(req, res.statusCode, performance.now() - start);\n client.record(event);\n } catch {\n // emit must never break the response — fail-open\n }\n });\n\n next();\n };\n}\n\n/**\n * Wraps the sanitizer middleware so SecurityThreatError → req.__arcis marker.\n * The emitter on `finish` will then have vector/rule/severity attribution.\n */\nexport function tapSanitizerThreats(handler: RequestHandler): RequestHandler {\n return (req, res, next) => {\n handler(req, res, (err?: unknown) => {\n if (err instanceof SecurityThreatError) {\n const vector = THREAT_TO_VECTOR[err.threatType] ?? err.threatType;\n req.__arcis = {\n vector,\n rule: `${vector}/match`,\n severity: 'high',\n matchedPattern: err.pattern,\n reason: err.message,\n decision: 'deny',\n };\n }\n next(err);\n });\n };\n}\n\nfunction buildEvent(req: Request, status: number, latencyMs: number): TelemetryEvent {\n const marker = req.__arcis;\n const decision = marker?.decision ?? inferDecision(status);\n\n // Skip 5xx — those are server errors, not security decisions.\n // Still emit so the dashboard shows traffic, but mark as allow with status >=500.\n return {\n ts: new Date().toISOString(),\n ip: extractIp(req),\n method: (req.method ?? 'GET').toUpperCase(),\n path: req.path ?? req.url ?? '/',\n decision,\n vector: marker?.vector ?? (status === 429 ? 'rate-limit' : undefined),\n rule: marker?.rule ?? (status === 429 ? 'rate-limit/exceeded' : undefined),\n severity: marker?.severity ?? (status === 429 ? 'medium' : undefined),\n userAgent: typeof req.headers?.['user-agent'] === 'string' ? req.headers['user-agent'] : '',\n reason: marker?.reason,\n status,\n matchedPattern: marker?.matchedPattern,\n latencyMs: Math.max(0, latencyMs),\n };\n}\n\nfunction inferDecision(status: number): TelemetryDecision {\n if (status === 429) return 'deny';\n if (status === 400) return 'deny';\n if (status === 403) return 'deny';\n return 'allow';\n}\n\nfunction extractIp(req: Request): string {\n if (typeof req.ip === 'string' && req.ip.length > 0) return req.ip;\n const remote = req.socket?.remoteAddress;\n return typeof remote === 'string' ? remote : '0.0.0.0';\n}\n","/**\n * @module @arcis/node/sanitizers/utils\n * Shared utilities for sanitizers\n */\n\n/**\n * Encodes HTML entities to prevent interpretation as markup.\n * \n * @param str - The string to encode\n * @returns The encoded string\n */\nexport function encodeHtmlEntities(str: string): string {\n return str\n .replace(/&/g, '&')\n .replace(/</g, '<')\n .replace(/>/g, '>')\n .replace(/\"/g, '"')\n .replace(/'/g, ''');\n}\n\n/**\n * Checks if a value is a plain object (not null, array, Date, etc.)\n * \n * @param value - Value to check\n * @returns True if plain object\n */\nexport function isPlainObject(value: unknown): value is Record<string, unknown> {\n if (typeof value !== 'object' || value === null || Array.isArray(value)) {\n return false;\n }\n // Check the actual prototype chain rather than toString, which can be spoofed\n // via Symbol.toStringTag. Accepts both Object.prototype (plain {}) and null\n // prototype objects (Object.create(null)).\n const proto = Object.getPrototypeOf(value as object);\n return proto === Object.prototype || proto === null;\n}\n","/**\n * @module @arcis/node/sanitizers/xss\n * XSS (Cross-Site Scripting) prevention\n */\n\nimport { XSS_PATTERNS, XSS_REMOVE_PATTERNS } from '../core/constants';\nimport { encodeHtmlEntities } from './utils';\nimport type { SanitizeResult, ThreatInfo } from '../core/types';\n\n/**\n * Sanitizes a string to prevent XSS attacks.\n * \n * Strategy:\n * 1. Remove dangerous patterns (script tags, event handlers, etc.)\n * 2. HTML-encode the remaining content\n * \n * @param input - The string to sanitize\n * @param collectThreats - Whether to collect threat information (default: false for performance)\n * @returns Sanitized string or SanitizeResult if collectThreats is true\n * \n * @example\n * sanitizeXss(\"<script>alert('xss')</script>\")\n * // Returns: \"<script>alert('xss')</script>\"\n * \n * @example\n * sanitizeXss(\"<img onerror='alert(1)'>\")\n * // Returns: \"<img>\" (event handler removed)\n */\nexport function sanitizeXss(input: string, collectThreats?: false, htmlEncode?: boolean): string;\nexport function sanitizeXss(input: string, collectThreats: true, htmlEncode?: boolean): SanitizeResult;\nexport function sanitizeXss(input: string, collectThreats = false, htmlEncode = false): string | SanitizeResult {\n if (typeof input !== 'string') {\n return collectThreats \n ? { value: String(input), wasSanitized: false, threats: [] }\n : String(input);\n }\n\n const threats: ThreatInfo[] = [];\n let value = input;\n let wasSanitized = false;\n\n // Remove dangerous patterns FIRST — XSS_REMOVE_PATTERNS is the single\n // source of truth (defined in constants.ts alongside XSS_PATTERNS).\n for (const pattern of XSS_REMOVE_PATTERNS) {\n pattern.lastIndex = 0;\n if (pattern.test(value)) {\n pattern.lastIndex = 0;\n \n if (collectThreats) {\n const matches = value.match(pattern);\n if (matches) {\n for (const match of matches) {\n threats.push({\n type: 'xss',\n pattern: pattern.source,\n original: match,\n });\n }\n }\n }\n \n value = value.replace(pattern, '');\n wasSanitized = true;\n }\n }\n\n // HTML-encode only when explicitly requested (SSR/template context).\n // Do NOT encode by default — this is a REST API middleware; encoding\n // here corrupts JSON data with HTML entities (<, &, etc.) that\n // consumers would receive verbatim.\n if (htmlEncode) {\n const encoded = encodeHtmlEntities(value);\n if (encoded !== value) {\n wasSanitized = true;\n }\n value = encoded;\n }\n\n if (collectThreats) {\n return { value, wasSanitized, threats };\n }\n \n return value;\n}\n\n/**\n * Checks if a string contains potential XSS patterns.\n * Does not sanitize — use sanitizeXss() for that.\n * \n * @param input - The string to check\n * @returns True if XSS patterns detected\n */\nexport function detectXss(input: string): boolean {\n if (typeof input !== 'string') return false;\n \n // Check for event handlers\n if (/\\s+on\\w+\\s*=/i.test(input)) return true;\n \n // Check for dangerous protocols\n if (/javascript\\s*:/i.test(input)) return true;\n if (/vbscript\\s*:/i.test(input)) return true;\n if (/data\\s*:\\s*text\\/html/i.test(input)) return true;\n \n // Check for patterns from constants\n for (const pattern of XSS_PATTERNS) {\n pattern.lastIndex = 0;\n if (pattern.test(input)) {\n return true;\n }\n }\n \n return false;\n}\n","/**\n * @module @arcis/node/sanitizers/sql\n * SQL injection prevention\n */\n\nimport { SQL_PATTERNS } from '../core/constants';\nimport type { SanitizeResult, ThreatInfo } from '../core/types';\n\n/**\n * Sanitizes a string to prevent SQL injection attacks.\n * Replaces dangerous SQL patterns with [BLOCKED].\n * \n * @param input - The string to sanitize\n * @param collectThreats - Whether to collect threat information (default: false for performance)\n * @returns Sanitized string or SanitizeResult if collectThreats is true\n * \n * @example\n * sanitizeSql(\"'; DROP TABLE users; --\")\n * // Returns: \"'; TABLE users \"\n */\nexport function sanitizeSql(input: string, collectThreats?: false): string;\nexport function sanitizeSql(input: string, collectThreats: true): SanitizeResult;\nexport function sanitizeSql(input: string, collectThreats = false): string | SanitizeResult {\n if (typeof input !== 'string') {\n return collectThreats \n ? { value: String(input), wasSanitized: false, threats: [] }\n : String(input);\n }\n\n const threats: ThreatInfo[] = [];\n let value = input;\n let wasSanitized = false;\n\n for (const pattern of SQL_PATTERNS) {\n // Reset regex lastIndex for global patterns\n pattern.lastIndex = 0;\n \n if (pattern.test(value)) {\n pattern.lastIndex = 0; // Reset again for replace\n \n if (collectThreats) {\n const matches = value.match(pattern);\n if (matches) {\n for (const match of matches) {\n threats.push({\n type: 'sql_injection',\n pattern: pattern.source,\n original: match,\n });\n }\n }\n }\n \n // Replace the matched content with a space to avoid concatenating surrounding\n // tokens into new dangerous strings (e.g. \"SELECTname\" after stripping \"SELECT\").\n value = value.replace(pattern, ' ');\n wasSanitized = true;\n }\n }\n\n if (collectThreats) {\n return { value, wasSanitized, threats };\n }\n \n return value;\n}\n\n/**\n * Checks if a string contains potential SQL injection patterns.\n * Does not sanitize — use sanitizeSql() for that.\n * \n * @param input - The string to check\n * @returns True if SQL injection patterns detected\n */\nexport function detectSql(input: string): boolean {\n if (typeof input !== 'string') return false;\n \n for (const pattern of SQL_PATTERNS) {\n pattern.lastIndex = 0;\n if (pattern.test(input)) {\n return true;\n }\n }\n \n return false;\n}\n","/**\n * @module @arcis/node/sanitizers/path\n * Path traversal prevention\n */\n\nimport { PATH_PATTERNS } from '../core/constants';\nimport type { SanitizeResult, ThreatInfo } from '../core/types';\n\n/**\n * Sanitizes a string to prevent path traversal attacks.\n * Removes ../ and ..\\ patterns (including URL-encoded variants).\n * \n * @param input - The string to sanitize\n * @param collectThreats - Whether to collect threat information (default: false for performance)\n * @returns Sanitized string or SanitizeResult if collectThreats is true\n * \n * @example\n * sanitizePath(\"../../etc/passwd\")\n * // Returns: \"etc/passwd\"\n */\nexport function sanitizePath(input: string, collectThreats?: false): string;\nexport function sanitizePath(input: string, collectThreats: true): SanitizeResult;\nexport function sanitizePath(input: string, collectThreats = false): string | SanitizeResult {\n if (typeof input !== 'string') {\n return collectThreats \n ? { value: String(input), wasSanitized: false, threats: [] }\n : String(input);\n }\n\n const threats: ThreatInfo[] = [];\n let value = input;\n let wasSanitized = false;\n\n // SECURITY: Normalize Unicode to NFKC before pattern matching.\n // Fullwidth dot U+FF0E normalizes to '.', preventing ../ bypass of ../ detection.\n value = value.normalize('NFKC');\n\n // Apply patterns repeatedly until the string stops changing.\n // Single-pass stripping is bypassable: \"....//\".replace(\"../\",\"\") → \"../\"\n let prev: string;\n do {\n prev = value;\n for (const pattern of PATH_PATTERNS) {\n pattern.lastIndex = 0;\n\n if (pattern.test(value)) {\n pattern.lastIndex = 0;\n\n if (collectThreats) {\n const matches = value.match(pattern);\n if (matches) {\n for (const match of matches) {\n threats.push({\n type: 'path_traversal',\n pattern: pattern.source,\n original: match,\n });\n }\n }\n }\n\n value = value.replace(pattern, '');\n wasSanitized = true;\n }\n }\n } while (value !== prev);\n\n if (collectThreats) {\n return { value, wasSanitized, threats };\n }\n \n return value;\n}\n\n/**\n * Checks if a string contains path traversal patterns.\n * Does not sanitize — use sanitizePath() for that.\n * \n * @param input - The string to check\n * @returns True if path traversal patterns detected\n */\nexport function detectPathTraversal(input: string): boolean {\n if (typeof input !== 'string') return false;\n\n // SECURITY: Normalize Unicode to NFKC — same as sanitizePath\n const normalized = input.normalize('NFKC');\n\n for (const pattern of PATH_PATTERNS) {\n pattern.lastIndex = 0;\n if (pattern.test(normalized)) {\n return true;\n }\n }\n \n return false;\n}\n","/**\n * @module @arcis/node/sanitizers/command\n * Command injection prevention\n */\n\nimport { COMMAND_PATTERNS } from '../core/constants';\nimport type { SanitizeResult, ThreatInfo } from '../core/types';\n\n/**\n * Sanitizes a string to prevent command injection attacks.\n * Replaces shell metacharacters and dangerous commands with [BLOCKED].\n * \n * @param input - The string to sanitize\n * @param collectThreats - Whether to collect threat information (default: false for performance)\n * @returns Sanitized string or SanitizeResult if collectThreats is true\n * \n * @example\n * sanitizeCommand(\"file.txt; rm -rf /\")\n * // Returns: \"file.txt rm -rf /\"\n */\nexport function sanitizeCommand(input: string, collectThreats?: false): string;\nexport function sanitizeCommand(input: string, collectThreats: true): SanitizeResult;\nexport function sanitizeCommand(input: string, collectThreats = false): string | SanitizeResult {\n if (typeof input !== 'string') {\n return collectThreats \n ? { value: String(input), wasSanitized: false, threats: [] }\n : String(input);\n }\n\n const threats: ThreatInfo[] = [];\n let value = input;\n let wasSanitized = false;\n\n for (const pattern of COMMAND_PATTERNS) {\n // Reset regex lastIndex for global patterns\n pattern.lastIndex = 0;\n \n if (pattern.test(value)) {\n pattern.lastIndex = 0; // Reset again for replace\n \n if (collectThreats) {\n const matches = value.match(pattern);\n if (matches) {\n for (const match of matches) {\n threats.push({\n type: 'command_injection',\n pattern: pattern.source,\n original: match,\n });\n }\n }\n }\n \n value = value.replace(pattern, ' ');\n wasSanitized = true;\n }\n }\n\n if (collectThreats) {\n return { value, wasSanitized, threats };\n }\n \n return value;\n}\n\n/**\n * Checks if a string contains command injection patterns.\n * Does not sanitize — use sanitizeCommand() for that.\n * \n * @param input - The string to check\n * @returns True if command injection patterns detected\n */\nexport function detectCommandInjection(input: string): boolean {\n if (typeof input !== 'string') return false;\n \n for (const pattern of COMMAND_PATTERNS) {\n pattern.lastIndex = 0;\n if (pattern.test(input)) {\n return true;\n }\n }\n \n return false;\n}\n","/**\n * @module @arcis/node/sanitizers/ssti\n * Server-Side Template Injection (SSTI) prevention\n */\n\nimport type { SanitizeResult, ThreatInfo } from '../core/types';\n\n/**\n * SSTI detection patterns (ReDoS-safe).\n *\n * Covers Jinja2, Twig, Nunjucks, Freemarker, Thymeleaf, Spring EL,\n * ERB, EJS, Pug/Jade, and Python sandbox-escape dunder chains.\n */\nconst SSTI_DETECT_PATTERNS = [\n /** Jinja2 / Twig / Nunjucks: {{ ... }} */\n /\\{\\{.*?\\}\\}/g,\n /** Freemarker / Thymeleaf / Spring EL: ${ ... } */\n /\\$\\{.*?\\}/g,\n /** ERB / EJS: <%= ... %> or <% ... %> */\n /<%[=\\-]?.*?%>/gs,\n /** Pug / Jade / Slim: #{ ... } */\n /#\\{.*?\\}/g,\n /** Python dunder sandbox escape */\n /__(?:class|mro|subclasses|globals|builtins|import)__/gi,\n /** Jinja2 config leak: {{config.X}} or {{config['X']}} */\n /\\{\\{\\s*config[.\\[]/gi,\n /** Jinja2 built-in objects */\n /\\{\\{\\s*(?:self|request|lipsum|cycler|joiner|namespace|range)\\b/gi,\n] as const;\n\n/**\n * Removal patterns — strip template expressions that look like actual attacks.\n *\n * ${ and #{ patterns are narrowed to require operators/method-calls inside to\n * avoid false-positives on JS template literals (${name}) and Ruby/Pug output\n * expressions (#{name}) that appear in legitimate user-submitted content.\n *\n * The broader detection patterns above still flag these for detectSsti() —\n * narrowing only applies to destructive sanitization.\n */\nconst SSTI_REMOVE_PATTERNS = [\n /** Jinja2 / Twig: {{ ... }} — always strip (not valid in any JS context) */\n /\\{\\{.*?\\}\\}/g,\n /**\n * Freemarker / Spring EL: ${...} — strip when expression contains operators,\n * method calls, or Python dunder patterns (sandbox escape).\n * Bare ${name} and ${user.name} are left intact (JS template literal syntax).\n */\n /\\$\\{[^}]*__\\w+__[^}]*\\}/g,\n /\\$\\{[^}]*[?!()*+\\-/][^}]*\\}/g,\n /** ERB / EJS: <%= ... %> */\n /<%[=\\-]?.*?%>/gs,\n /**\n * Pug / Jade: #{...} — same narrowing as ${ above, plus dunder detection.\n * #{name} output expressions are left intact.\n */\n /#\\{[^}]*__\\w+__[^}]*\\}/g,\n /#\\{[^}]*[?!()*+\\-/][^}]*\\}/g,\n /** Python dunder sandbox escape — always strip */\n /__(?:class|mro|subclasses|globals|builtins|import)__/gi,\n] as const;\n\n/**\n * Sanitizes a string to prevent SSTI attacks.\n * Removes template expression syntax.\n */\nexport function sanitizeSsti(input: string, collectThreats?: false): string;\nexport function sanitizeSsti(input: string, collectThreats: true): SanitizeResult;\nexport function sanitizeSsti(input: string, collectThreats = false): string | SanitizeResult {\n if (typeof input !== 'string') {\n return collectThreats\n ? { value: String(input), wasSanitized: false, threats: [] }\n : String(input);\n }\n\n const threats: ThreatInfo[] = [];\n let value = input;\n let wasSanitized = false;\n\n for (const pattern of SSTI_REMOVE_PATTERNS) {\n pattern.lastIndex = 0;\n if (pattern.test(value)) {\n pattern.lastIndex = 0;\n\n if (collectThreats) {\n const matches = value.match(pattern);\n if (matches) {\n for (const match of matches) {\n threats.push({\n type: 'ssti',\n pattern: pattern.source,\n original: match,\n });\n }\n }\n }\n\n value = value.replace(pattern, '');\n wasSanitized = true;\n }\n }\n\n if (collectThreats) {\n return { value, wasSanitized, threats };\n }\n\n return value;\n}\n\n/**\n * Checks if a string contains SSTI patterns.\n * Does not sanitize — use sanitizeSsti() for that.\n *\n * @param input - The string to check\n * @returns True if SSTI patterns detected\n */\nexport function detectSsti(input: string): boolean {\n if (typeof input !== 'string') return false;\n\n for (const pattern of SSTI_DETECT_PATTERNS) {\n pattern.lastIndex = 0;\n if (pattern.test(input)) {\n return true;\n }\n }\n\n return false;\n}\n","/**\n * @module @arcis/node/sanitizers/xxe\n * XML External Entity (XXE) injection prevention\n */\n\nimport type { SanitizeResult, ThreatInfo } from '../core/types';\n\n/**\n * XXE detection patterns (ReDoS-safe).\n *\n * Covers DOCTYPE declarations, ENTITY definitions, SYSTEM/PUBLIC references,\n * parameter entities, and CDATA abuse.\n */\n/**\n * Billion-laughs defense: cap raw XML input length and the count of\n * entity references. A valid document rarely needs more than a handful of\n * entities; thousands of `&foo;` references is the classic bomb shape.\n */\nconst MAX_XXE_INPUT_BYTES = 1_000_000; // 1 MB — above any reasonable config/SOAP payload\nconst MAX_ENTITY_REFERENCES = 64;\n\nconst XXE_DETECT_PATTERNS = [\n /** DOCTYPE declaration */\n /<!DOCTYPE\\b/gi,\n /** ENTITY declaration */\n /<!ENTITY\\b/gi,\n /** SYSTEM keyword with URI */\n /\\bSYSTEM\\s+[\"']/gi,\n /** PUBLIC keyword with URI */\n /\\bPUBLIC\\s+[\"']/gi,\n /** Parameter entity reference (%entity;) */\n /%\\s*\\w+\\s*;/g,\n /** CDATA section (often used to smuggle payloads) */\n /<!\\[CDATA\\[/gi,\n] as const;\n\n/** Removal patterns — strip the dangerous XML constructs */\nconst XXE_REMOVE_PATTERNS = [\n /** Full DOCTYPE block with optional internal subset: <!DOCTYPE ... [...]> */\n /<!DOCTYPE\\s[^[>]*(?:\\[[^\\]]*\\]\\s*)?>|<!DOCTYPE\\s[^>]*>/gi,\n /** Full ENTITY declaration: <!ENTITY ... > */\n /<!ENTITY[^>]*>/gi,\n /** CDATA sections: <![CDATA[ ... ]]> */\n /<!\\[CDATA\\[[\\s\\S]*?\\]\\]>/gi,\n] as const;\n\n/**\n * Sanitizes a string to prevent XXE attacks.\n * Removes DOCTYPE, ENTITY, and CDATA constructs.\n */\nexport function sanitizeXxe(input: string, collectThreats?: false): string;\nexport function sanitizeXxe(input: string, collectThreats: true): SanitizeResult;\nexport function sanitizeXxe(input: string, collectThreats = false): string | SanitizeResult {\n if (typeof input !== 'string') {\n return collectThreats\n ? { value: String(input), wasSanitized: false, threats: [] }\n : String(input);\n }\n\n const threats: ThreatInfo[] = [];\n let value = input;\n let wasSanitized = false;\n\n // Billion-laughs defense: oversize input or many entity refs → flatten to empty.\n // Safer to discard than to attempt partial sanitization of a bomb payload.\n if (value.length > MAX_XXE_INPUT_BYTES) {\n if (collectThreats) {\n threats.push({ type: 'xxe', pattern: 'oversize_input', original: `length=${value.length}` });\n }\n return collectThreats ? { value: '', wasSanitized: true, threats } : '';\n }\n const entityRefs = value.match(/&\\w+;/g);\n if (entityRefs && entityRefs.length > MAX_ENTITY_REFERENCES) {\n if (collectThreats) {\n threats.push({ type: 'xxe', pattern: 'entity_expansion', original: `count=${entityRefs.length}` });\n }\n return collectThreats ? { value: '', wasSanitized: true, threats } : '';\n }\n\n for (const pattern of XXE_REMOVE_PATTERNS) {\n pattern.lastIndex = 0;\n if (pattern.test(value)) {\n pattern.lastIndex = 0;\n\n if (collectThreats) {\n const matches = value.match(pattern);\n if (matches) {\n for (const match of matches) {\n threats.push({\n type: 'xxe',\n pattern: pattern.source,\n original: match,\n });\n }\n }\n }\n\n value = value.replace(pattern, '');\n wasSanitized = true;\n }\n }\n\n if (collectThreats) {\n return { value, wasSanitized, threats };\n }\n\n return value;\n}\n\n/**\n * Checks if a string contains XXE patterns.\n * Does not sanitize — use sanitizeXxe() for that.\n *\n * @param input - The string to check\n * @returns True if XXE patterns detected\n */\nexport function detectXxe(input: string): boolean {\n if (typeof input !== 'string') return false;\n\n for (const pattern of XXE_DETECT_PATTERNS) {\n pattern.lastIndex = 0;\n if (pattern.test(input)) {\n return true;\n }\n }\n\n return false;\n}\n","/**\n * @module @arcis/node/sanitizers/ldap\n * LDAP injection prevention\n *\n * LDAP special characters in filter context: * ( ) \\ NUL\n * LDAP special characters in DN context: , + < > ; \" = / \\ NUL\n *\n * RFC 4515 (filter) and RFC 4514 (DN) define the escaping rules.\n * Sanitization escapes rather than strips — preserves the original value\n * while making it safe to embed in LDAP queries.\n */\n\n// LDAP filter special characters per RFC 4515 (single pass includes NUL)\nconst LDAP_FILTER_CHARS = /[*()\\\\\\x00]/g;\n\n// LDAP DN special characters per RFC 4514 (single pass includes NUL)\nconst LDAP_DN_CHARS = /[,+<>;\"=\\/\\\\\\x00*()\\x00]/g;\n\n// Detection pattern — unescaped LDAP special chars in filter context\nconst LDAP_DETECT_PATTERN = /[*()\\\\\\x00]/;\n\n// Detection pattern for OR/AND bypass and wildcard abuse\nconst LDAP_INJECTION_PATTERN = /\\)\\s*\\(|\\*\\s*\\)\\s*\\(/;\n\n// Detection pattern for LDAP NOT-operator bypass (improvements.md Q8).\n// Catches ')(!', '&(!', '|(!' shapes that legitimate filters never contain;\n// these are the attacker's NOT-clause appended to enumerate or exclude\n// entries (e.g. '*)(uid=*)(!(uid=admin))'). Companion to\n// LDAP_INJECTION_PATTERN; together they cover the OR-then-NOT corpus.\nconst LDAP_NOT_BYPASS_PATTERN = /\\)\\s*\\(\\s*!|&\\s*\\(\\s*!|\\|\\s*\\(\\s*!/;\n\nconst escapeChar = (char: string) => '\\\\' + char.charCodeAt(0).toString(16).padStart(2, '0');\n\n/**\n * Sanitizes a string for safe use in LDAP filter expressions.\n * Escapes * ( ) \\ and NUL per RFC 4515.\n *\n * @example\n * sanitizeLdapFilter(\"user*(admin)\")\n * // Returns: \"user\\2a\\28admin\\29\"\n */\nexport function sanitizeLdapFilter(input: string): string {\n if (typeof input !== 'string') return String(input);\n return input.replace(LDAP_FILTER_CHARS, escapeChar);\n}\n\n/**\n * Sanitizes a string for safe use in LDAP Distinguished Names (DN).\n * Escapes , + < > ; \" = / \\ and NUL per RFC 4514.\n *\n * @example\n * sanitizeLdapDn(\"cn=admin,dc=example\")\n * // Returns: \"cn\\3dadmin\\2cdc\\3dexample\"\n */\nexport function sanitizeLdapDn(input: string): string {\n if (typeof input !== 'string') return String(input);\n return input.replace(LDAP_DN_CHARS, escapeChar);\n}\n\n/**\n * Detects potential LDAP injection patterns in a string.\n * Does not sanitize — use sanitizeLdapFilter() or sanitizeLdapDn() for that.\n *\n * @param input - The string to check\n * @returns True if LDAP injection patterns detected\n *\n * @example\n * detectLdapInjection(\"*)(uid=*))(|(uid=*\") // true\n * detectLdapInjection(\"john\") // false\n */\nexport function detectLdapInjection(input: string): boolean {\n if (typeof input !== 'string') return false;\n return (\n LDAP_DETECT_PATTERN.test(input) ||\n LDAP_INJECTION_PATTERN.test(input) ||\n LDAP_NOT_BYPASS_PATTERN.test(input)\n );\n}\n","/**\n * @module @arcis/node/sanitizers/xpath\n * XPath injection prevention.\n *\n * XPath 1.0 has no escape syntax for string literals — the only way to\n * embed user input safely is parameterised queries / variable bindings.\n * Neither libxml2 nor most JS XPath libraries expose a canonical escape\n * function. The pragmatic answer everyone ships:\n *\n * - Detect: scan for unescaped quotes or expression-control chars\n * that suggest the user is trying to break out of a string literal.\n * - Sanitize: strip the offending control characters. Lossy by design;\n * callers that need lossless input should use parameterised queries\n * directly.\n *\n * Detection is the load-bearing surface for this vector. Sanitization is\n * a fallback for users running existing XPath strings through user input\n * who can't switch to bound parameters today.\n */\n\n// XPath expression-control characters that an attacker uses to escape\n// a string literal: single quote, double quote, comma (changes function\n// arity), the union operator |, and parens (used in `) or (` toggles\n// against XPath function calls). These are the same shapes Aikido /\n// Snyk's xpath rules look for.\nconst XPATH_INJECTION_CHARS = /['\"|,()]/;\n\n// Common operator-injection patterns: unescaped boolean injection\n// (`' or '1'='1`), function tampering (`,`), and union (`|`).\nconst XPATH_INJECTION_PATTERN =\n /('\\s*(or|and)\\s*'|\"\\s*(or|and)\\s*\"|\\)\\s*(or|and)\\s*\\(|\\|\\s*\\/)/i;\n\n/**\n * Detects XPath-injection-shaped patterns in a string. Returns true when\n * the input looks like it's trying to break out of an XPath string\n * literal or hijack the expression structure.\n *\n * Conservative on purpose: triggers on any control char in the input\n * combined with a boolean / union pattern. Plain user names and emails\n * (no quotes, no pipes) pass clean.\n */\nexport function detectXpathInjection(input: string): boolean {\n if (typeof input !== 'string' || input.length === 0) return false;\n // Fast path: skip the regex test entirely when no control chars exist.\n if (!XPATH_INJECTION_CHARS.test(input)) return false;\n return XPATH_INJECTION_PATTERN.test(input);\n}\n\n/**\n * Strips XPath expression-control characters from a string. Lossy —\n * `O'Brien` becomes `OBrien`. Use only when migrating legacy code that\n * concatenates user input into XPath; new code should use bound\n * parameters via the underlying XPath library.\n */\nexport function sanitizeXpath(input: string): string {\n if (typeof input !== 'string') return String(input);\n return input.replace(/['\"|,]/g, '');\n}\n","/**\n * @module @arcis/node/sanitizers/headers\n * HTTP Header Injection & CRLF Injection prevention\n *\n * Prevents attackers from injecting newline characters (\\r\\n) into HTTP header\n * values, which can lead to response splitting, session fixation, XSS via\n * injected headers, and cache poisoning.\n */\n\nimport type { SanitizeResult, ThreatInfo } from '../core/types';\n\n/**\n * Characters and sequences that enable header injection.\n * - \\r\\n (CRLF) — HTTP header delimiter, enables response splitting\n * - \\r, \\n alone — partial line breaks, some servers normalize to CRLF\n * - \\0 (null byte) — can truncate header values in some implementations\n */\nconst HEADER_INJECTION_PATTERN = /\\r\\n|\\r|\\n|\\0/g;\n\n/**\n * Sanitizes a header value by stripping CRLF sequences, bare CR/LF, and null bytes.\n *\n * @param input - The header value to sanitize\n * @param collectThreats - Whether to collect threat information (default: false)\n * @returns Sanitized string or SanitizeResult if collectThreats is true\n *\n * @example\n * sanitizeHeaderValue(\"safe-value\")\n * // Returns: \"safe-value\"\n *\n * sanitizeHeaderValue(\"value\\r\\nX-Injected: evil\")\n * // Returns: \"valueX-Injected: evil\"\n */\nexport function sanitizeHeaderValue(input: string, collectThreats?: false): string;\nexport function sanitizeHeaderValue(input: string, collectThreats: true): SanitizeResult;\nexport function sanitizeHeaderValue(input: string, collectThreats = false): string | SanitizeResult {\n if (typeof input !== 'string') {\n return collectThreats\n ? { value: String(input), wasSanitized: false, threats: [] }\n : String(input);\n }\n\n const threats: ThreatInfo[] = [];\n let wasSanitized = false;\n\n if (HEADER_INJECTION_PATTERN.test(input)) {\n HEADER_INJECTION_PATTERN.lastIndex = 0;\n wasSanitized = true;\n\n if (collectThreats) {\n const matches = input.match(HEADER_INJECTION_PATTERN);\n if (matches) {\n for (const match of matches) {\n threats.push({\n type: 'header_injection',\n pattern: HEADER_INJECTION_PATTERN.source,\n original: match,\n });\n }\n }\n }\n }\n\n HEADER_INJECTION_PATTERN.lastIndex = 0;\n const value = input.replace(HEADER_INJECTION_PATTERN, '');\n\n if (collectThreats) {\n return { value, wasSanitized, threats };\n }\n\n return value;\n}\n\n/**\n * Sanitizes an object of header key-value pairs.\n * Strips CRLF/null bytes from both keys and values.\n *\n * @param headers - Object with header names as keys and header values as values\n * @returns New object with sanitized header names and values\n *\n * @example\n * sanitizeHeaders({ \"X-Custom\": \"safe\", \"X-Bad\\r\\n\": \"value\\r\\ninjected\" })\n * // Returns: { \"X-Custom\": \"safe\", \"X-Bad\": \"valueinjected\" }\n */\nexport function sanitizeHeaders(headers: Record<string, string>): Record<string, string> {\n if (!headers || typeof headers !== 'object') {\n return {};\n }\n\n const result: Record<string, string> = {};\n\n for (const [key, value] of Object.entries(headers)) {\n const sanitizedKey = sanitizeHeaderValue(String(key));\n const sanitizedValue = sanitizeHeaderValue(String(value));\n result[sanitizedKey] = sanitizedValue;\n }\n\n return result;\n}\n\n/**\n * Checks if a string contains HTTP header injection patterns (CRLF, null bytes).\n * Does not sanitize — use sanitizeHeaderValue() for that.\n *\n * @param input - The string to check\n * @returns True if header injection patterns detected\n */\nexport function detectHeaderInjection(input: string): boolean {\n if (typeof input !== 'string') return false;\n\n HEADER_INJECTION_PATTERN.lastIndex = 0;\n return HEADER_INJECTION_PATTERN.test(input);\n}\n\n/**\n * Email-header injection prevention. Same byte-level threat as HTTP\n * header injection — `\\r\\n` in a user-controlled email field\n * (`To`, `From`, `Subject`, etc.) lets an attacker inject extra headers\n * (most commonly Bcc) and pivot a contact form into a spam relay.\n *\n * Aliased to the HTTP-header sanitizers because the wire-level fix is\n * identical: strip CRLF + null bytes from the value before\n * concatenating into the header. Use these in form-to-email handlers:\n *\n * ```ts\n * const subject = sanitizeEmailHeader(req.body.subject);\n * const to = sanitizeEmailHeader(req.body.to);\n * if (detectEmailHeaderInjection(req.body.to)) reject(...);\n * ```\n */\nexport const sanitizeEmailHeader = sanitizeHeaderValue;\nexport const detectEmailHeaderInjection = detectHeaderInjection;\n","/**\n * @module @arcis/node/sanitizers/sanitize\n * Main sanitization functions that combine all sanitizers\n */\n\nimport type { Request, Response, NextFunction, RequestHandler } from 'express';\nimport { INPUT, DANGEROUS_PROTO_KEYS, NOSQL_DANGEROUS_KEYS } from '../core/constants';\nimport { InputTooLargeError, SecurityThreatError } from '../core/errors';\nimport type { SanitizeOptions } from '../core/types';\nimport { sanitizeXss, detectXss } from './xss';\nimport { sanitizeSql, detectSql } from './sql';\nimport { sanitizePath, detectPathTraversal } from './path';\nimport { sanitizeCommand, detectCommandInjection } from './command';\nimport { detectSsti } from './ssti';\nimport { detectXxe } from './xxe';\nimport { detectLdapInjection } from './ldap';\nimport { detectXpathInjection } from './xpath';\nimport { detectHeaderInjection } from './headers';\n\n/**\n * Sanitize a string value against multiple attack vectors.\n * \n * Order matters: We do XSS encoding LAST because:\n * 1. Other sanitizers need to see the original patterns (e.g., SQL keywords)\n * 2. HTML encoding is the final safe output transformation\n * 3. Encoded entities like < shouldn't be treated as SQL/command threats\n * \n * @param value - The string to sanitize\n * @param options - Sanitization options\n * @returns The sanitized string\n * \n * @example\n * sanitizeString(\"<script>alert('xss')</script>\")\n * // Returns: \"<script>alert('xss')</script>\"\n * \n * @example\n * sanitizeString(\"../../etc/passwd\")\n * // Returns: \"etc/passwd\"\n */\n/**\n * Decode URL + HTML entity layers until the string is stable.\n *\n * improvements.md §1.1.b — closes the encoding-stack bypass class.\n * A payload like `%2526%2523x3c%253bscript%2526%2523x3e%253b` is a\n * triple-encoded `<script>`: pass 1 URL-decodes to\n * `%26%23x3c%3bscript%26%23x3e%3b`, pass 2 URL-decodes to\n * `<script>`, pass 3 HTML-decodes to `<script>`. Without\n * this helper the literal ASCII `<script>` never appears in the\n * string, so the XSS regex never fires.\n *\n * Bounded at 4 passes to prevent pathological-input loops. Base64\n * decoding is intentionally NOT in the chain — false-positive rate\n * on arbitrary text would be high.\n */\nfunction multiDecode(value: string, maxPasses = 4): string {\n for (let i = 0; i < maxPasses; i++) {\n const prev = value;\n\n // URL-decode. decodeURIComponent throws on malformed sequences\n // (lone `%` with no hex pair); treat that as \"no further\n // URL-decoding possible\" and continue with the current value.\n try {\n value = decodeURIComponent(value);\n } catch {\n // leave value as-is\n }\n\n // HTML entity decode. No built-in in Node, so inline the common\n // entities here. Numeric (`&#NN;`, `&#xHH;`) covers the bulk of\n // XSS-encoding tricks; the five named entities below cover the\n // rest of the encoding-bypass test corpus.\n value = htmlEntityDecode(value);\n\n if (value === prev) break;\n }\n return value;\n}\n\n/** Decode HTML entities — numeric (decimal + hex) plus the five core\n * named entities that XSS payloads use. Keeps the dep-free zero-dep\n * footprint of `@arcis/node`. */\nfunction htmlEntityDecode(s: string): string {\n // &#NN; decimal numeric\n s = s.replace(/&#(\\d+);/g, (_m, n) => {\n const code = parseInt(n, 10);\n return Number.isFinite(code) && code >= 0 && code <= 0x10ffff\n ? String.fromCodePoint(code)\n : _m;\n });\n // &#xHH; or &#XHH; hex numeric\n s = s.replace(/&#x([0-9a-fA-F]+);/g, (_m, h) => {\n const code = parseInt(h, 16);\n return Number.isFinite(code) && code >= 0 && code <= 0x10ffff\n ? String.fromCodePoint(code)\n : _m;\n });\n // The five named entities that matter for XSS detection.\n const named: Record<string, string> = {\n '<': '<',\n '>': '>',\n '&': '&',\n '"': '\"',\n ''': \"'\",\n ' ': ' ',\n };\n for (const [entity, ch] of Object.entries(named)) {\n s = s.split(entity).join(ch);\n }\n return s;\n}\n\nexport function sanitizeString(value: string, options: SanitizeOptions = {}): string {\n if (typeof value !== 'string') return value;\n\n // Input size limit to prevent DoS\n const maxSize = options.maxSize ?? INPUT.DEFAULT_MAX_SIZE;\n if (value.length > maxSize) {\n throw new InputTooLargeError(maxSize, value.length);\n }\n\n // Default mode is 'sanitize' (strip threats and return cleaned string).\n // Pass mode: 'reject' to throw SecurityThreatError instead of stripping.\n const reject = options.mode === 'reject';\n\n // SECURITY: Normalize Unicode to NFKC BEFORE every detector runs.\n // Fullwidth glyphs (`<script>`, `1+1=2`) collapse to their ASCII\n // equivalents, closing the entire fullwidth-bypass class for XSS,\n // SQL, command-injection, and path-traversal in a single pass.\n // improvements.md §1.1.a. Bypass example closed:\n // `<script>alert(1)</script>` → `<script>alert(1)</script>`\n let result = value.normalize('NFKC');\n\n // SECURITY: Multi-pass URL + HTML decode (improvements.md §1.1.b).\n // Closes the encoding-stack bypass class. After NFKC,\n // `%2526%2523x3c%253bscript%2526%2523x3e%253b` (triple-encoded\n // `<script>`) decodes all the way to `<script>` and hits the\n // normal XSS strip below. Bounded at 4 passes.\n result = multiDecode(result);\n\n // 1. SQL injection\n if (options.sql !== false) {\n if (reject) {\n if (detectSql(result)) {\n throw new SecurityThreatError('sql_injection', 'SQL pattern detected in input');\n }\n } else {\n result = sanitizeSql(result);\n }\n }\n\n // 2. Path traversal prevention\n if (options.path !== false) {\n result = sanitizePath(result);\n }\n\n // 3. Command injection\n if (options.command !== false) {\n if (reject) {\n if (detectCommandInjection(result)) {\n throw new SecurityThreatError('command_injection', 'Shell metacharacter detected in input');\n }\n } else {\n result = sanitizeCommand(result);\n }\n }\n\n // 4. XSS stripping — always runs to remove dangerous patterns.\n // HTML encoding is opt-in via options.htmlEncode (for SSR contexts only).\n if (options.xss !== false) {\n result = sanitizeXss(result, false, options.htmlEncode ?? false);\n }\n\n return result;\n}\n\n/**\n * Sanitize an object recursively, including nested objects and arrays.\n * Also removes prototype pollution and NoSQL injection keys.\n * \n * @param obj - The object to sanitize\n * @param options - Sanitization options\n * @returns The sanitized object\n */\nexport function sanitizeObject(obj: unknown, options: SanitizeOptions = {}): unknown {\n if (obj === null || obj === undefined) return obj;\n if (typeof obj === 'string') return sanitizeString(obj, options);\n if (typeof obj !== 'object') return obj;\n if (Array.isArray(obj)) return obj.map(item => sanitizeObject(item, options));\n\n const result = sanitizeObjectDepth(obj as Record<string, unknown>, options, 0);\n return options.freeze ? Object.freeze(result) : result;\n}\n\n/**\n * Internal recursive sanitization with depth tracking.\n */\nfunction sanitizeObjectDepth(\n obj: Record<string, unknown>,\n options: SanitizeOptions,\n depth: number\n): Record<string, unknown> {\n if (depth >= INPUT.MAX_RECURSION_DEPTH) return obj;\n\n const result: Record<string, unknown> = {};\n\n for (const key of Object.keys(obj)) {\n // Prototype pollution protection - always block dangerous keys (case-insensitive)\n if (options.proto !== false && DANGEROUS_PROTO_KEYS.has(key.toLowerCase())) {\n continue;\n }\n\n // NoSQL injection - skip dangerous MongoDB operators in keys\n if (options.nosql !== false && NOSQL_DANGEROUS_KEYS.has(key)) {\n continue;\n }\n\n // Sanitize the key against all active threat vectors (not just XSS).\n // Keys can carry injection payloads that bubble into query builders or ORMs.\n const sanitizedKey = sanitizeString(key, options);\n\n // Recursively sanitize value\n const value = obj[key];\n if (value === null || value === undefined) {\n result[sanitizedKey] = value;\n } else if (typeof value === 'string') {\n result[sanitizedKey] = sanitizeString(value, options);\n } else if (Array.isArray(value)) {\n result[sanitizedKey] = value.map(item => sanitizeObject(item, options));\n } else if (typeof value === 'object') {\n result[sanitizedKey] = sanitizeObjectDepth(value as Record<string, unknown>, options, depth + 1);\n } else {\n result[sanitizedKey] = value;\n }\n }\n\n return result;\n}\n\n/** Threat triple returned from scanThreats. */\nexport interface ThreatHit {\n vector:\n | 'xss'\n | 'sql'\n | 'nosql'\n | 'path'\n | 'command'\n | 'prototype'\n | 'ssti'\n | 'xxe'\n | 'ldap'\n | 'xpath'\n | 'header';\n rule: string;\n matchedPattern: string;\n}\n\n/**\n * Walk a value (string, array, or object) and return the first threat hit\n * found. Used by block-mode middleware to attribute the deny decision.\n *\n * Vector ordering matches Python's scan_threats for cross-SDK parity.\n */\nexport function scanThreats(data: unknown, depth = 0): ThreatHit | null {\n if (depth > INPUT.MAX_RECURSION_DEPTH) return null;\n\n if (data && typeof data === 'object' && !Array.isArray(data)) {\n for (const key of Object.keys(data as Record<string, unknown>)) {\n const lower = key.toLowerCase();\n if (DANGEROUS_PROTO_KEYS.has(lower)) {\n return { vector: 'prototype', rule: 'prototype/match', matchedPattern: key };\n }\n if (NOSQL_DANGEROUS_KEYS.has(key)) {\n return { vector: 'nosql', rule: 'nosql/match', matchedPattern: key };\n }\n const inner = scanThreats((data as Record<string, unknown>)[key], depth + 1);\n if (inner) return inner;\n }\n return null;\n }\n\n if (Array.isArray(data)) {\n for (const item of data) {\n const inner = scanThreats(item, depth + 1);\n if (inner) return inner;\n }\n return null;\n }\n\n if (typeof data !== 'string') return null;\n\n const sample = data.slice(0, 80);\n if (detectXss(data)) {\n return { vector: 'xss', rule: 'xss/match', matchedPattern: sample };\n }\n if (detectSsti(data)) {\n return { vector: 'ssti', rule: 'ssti/match', matchedPattern: sample };\n }\n if (detectXxe(data)) {\n return { vector: 'xxe', rule: 'xxe/match', matchedPattern: sample };\n }\n if (detectSql(data)) {\n return { vector: 'sql', rule: 'sql/match', matchedPattern: sample };\n }\n if (detectPathTraversal(data)) {\n return { vector: 'path', rule: 'path/match', matchedPattern: sample };\n }\n if (detectCommandInjection(data)) {\n return { vector: 'command', rule: 'command/match', matchedPattern: sample };\n }\n // LDAP + XPath checks come AFTER command/path so a string that's\n // primarily a path-traversal payload (`../`) gets attributed to\n // path, not LDAP (the `\\` in `..\\..\\` would otherwise hit the LDAP\n // backslash filter).\n if (detectLdapInjection(data)) {\n return { vector: 'ldap', rule: 'ldap/match', matchedPattern: sample };\n }\n if (detectXpathInjection(data)) {\n return { vector: 'xpath', rule: 'xpath/match', matchedPattern: sample };\n }\n // Header injection (HTTP response splitting + email-header injection\n // share the same byte-level threat: CRLF in a value that gets\n // concatenated into a header). Last in the chain so the more-specific\n // detectors (xss / sql / etc.) win on input that's both — e.g. an XSS\n // payload with a stray newline still attributes to xss.\n if (detectHeaderInjection(data)) {\n return { vector: 'header', rule: 'header/match', matchedPattern: sample };\n }\n return null;\n}\n\n/**\n * Create Express middleware for request sanitization.\n * Sanitizes req.body, req.query, and req.params.\n * \n * @param options - Sanitization options\n * @returns Express middleware\n * \n * @example\n * app.use(createSanitizer());\n * \n * @example\n * app.use(createSanitizer({ xss: true, sql: true, nosql: true }));\n */\nexport function createSanitizer(options: SanitizeOptions = {}): RequestHandler {\n return (req: Request, res: Response, next: NextFunction) => {\n try {\n // Block mode: scan first, return 403 on threat. The telemetry emitter\n // reads the marker on res.finish to attribute the deny decision.\n if (options.block) {\n const hit =\n scanThreats(req.body) ||\n scanThreats(req.query) ||\n scanThreats(req.params) ||\n scanThreats(req.path);\n if (hit) {\n req.__arcis = {\n vector: hit.vector,\n rule: hit.rule,\n severity: 'high',\n matchedPattern: hit.matchedPattern,\n reason: `${hit.vector} pattern detected in request`,\n decision: 'deny',\n };\n res.status(403).json({\n error: 'Request blocked for security reasons',\n code: 'SECURITY_THREAT',\n vector: hit.vector,\n });\n return;\n }\n }\n\n if (req.body && typeof req.body === 'object') {\n req.body = sanitizeObject(req.body, options);\n }\n if (req.query && typeof req.query === 'object') {\n const sanitizedQuery = sanitizeObject(req.query, options);\n // Express 5: req.query is a getter with no setter — override on instance\n Object.defineProperty(req, 'query', { value: sanitizedQuery, writable: true, configurable: true });\n }\n if (req.params && typeof req.params === 'object') {\n const sanitizedParams = sanitizeObject(req.params, options);\n Object.defineProperty(req, 'params', { value: sanitizedParams, writable: true, configurable: true });\n }\n next();\n } catch (err) {\n next(err);\n }\n };\n}\n","/**\n * @module @arcis/node/sanitizers/nosql\n * NoSQL injection prevention (MongoDB operators)\n */\n\nimport { NOSQL_DANGEROUS_KEYS } from '../core/constants';\n\n/**\n * Checks if a key is a dangerous MongoDB operator.\n * \n * @param key - The key to check\n * @returns True if the key is a MongoDB operator\n * \n * @example\n * isDangerousNoSqlKey('$gt') // true\n * isDangerousNoSqlKey('name') // false\n */\nexport function isDangerousNoSqlKey(key: string): boolean {\n return NOSQL_DANGEROUS_KEYS.has(key);\n}\n\n/**\n * Recursively checks if an object contains dangerous MongoDB operators.\n * \n * @param obj - The object to check\n * @param maxDepth - Maximum recursion depth (default: 10)\n * @returns True if dangerous operators found\n */\nexport function detectNoSqlInjection(obj: unknown, maxDepth = 10): boolean {\n if (maxDepth <= 0) return false;\n if (obj === null || typeof obj !== 'object') return false;\n \n if (Array.isArray(obj)) {\n return obj.some(item => detectNoSqlInjection(item, maxDepth - 1));\n }\n \n for (const key of Object.keys(obj as Record<string, unknown>)) {\n if (isDangerousNoSqlKey(key)) {\n return true;\n }\n \n const value = (obj as Record<string, unknown>)[key];\n if (typeof value === 'object' && value !== null) {\n if (detectNoSqlInjection(value, maxDepth - 1)) {\n return true;\n }\n }\n }\n \n return false;\n}\n\n/**\n * Get list of all MongoDB operators considered dangerous.\n * Useful for documentation or custom validation.\n * \n * @returns Array of dangerous operator strings\n */\nexport function getDangerousOperators(): string[] {\n return Array.from(NOSQL_DANGEROUS_KEYS);\n}\n","/**\n * @module @arcis/node/sanitizers/prototype\n * Prototype pollution prevention\n */\n\nimport { DANGEROUS_PROTO_KEYS } from '../core/constants';\n\n/**\n * Checks if a key is dangerous for prototype pollution.\n * Case-insensitive — catches __PROTO__, Constructor, etc.\n *\n * @param key - The key to check\n * @returns True if the key could cause prototype pollution\n *\n * @example\n * isDangerousProtoKey('__proto__') // true\n * isDangerousProtoKey('__PROTO__') // true\n * isDangerousProtoKey('Constructor') // true\n * isDangerousProtoKey('name') // false\n */\nexport function isDangerousProtoKey(key: string): boolean {\n return DANGEROUS_PROTO_KEYS.has(key.toLowerCase());\n}\n\n/**\n * Recursively checks if an object contains prototype pollution keys.\n * \n * @param obj - The object to check\n * @param maxDepth - Maximum recursion depth (default: 10)\n * @returns True if dangerous keys found\n */\nexport function detectPrototypePollution(obj: unknown, maxDepth = 10): boolean {\n if (maxDepth <= 0) return false;\n if (obj === null || typeof obj !== 'object') return false;\n \n if (Array.isArray(obj)) {\n return obj.some(item => detectPrototypePollution(item, maxDepth - 1));\n }\n \n for (const key of Object.keys(obj as Record<string, unknown>)) {\n if (DANGEROUS_PROTO_KEYS.has(key.toLowerCase())) {\n return true;\n }\n \n const value = (obj as Record<string, unknown>)[key];\n if (typeof value === 'object' && value !== null) {\n if (detectPrototypePollution(value, maxDepth - 1)) {\n return true;\n }\n }\n }\n \n return false;\n}\n\n/**\n * Get list of all keys considered dangerous for prototype pollution.\n * Useful for documentation or custom validation.\n * \n * @returns Array of dangerous key strings\n */\nexport function getDangerousProtoKeys(): string[] {\n return Array.from(DANGEROUS_PROTO_KEYS);\n}\n","/**\n * @module @arcis/node/sanitizers/jsonp\n * JSONP callback sanitization to prevent XSS via callback parameters\n */\n\n/**\n * Valid JSONP callback pattern: only alphanumeric, underscore, dollar, and dot.\n * Bracket notation is rejected — it enables bypasses like `cb[x` (unbalanced)\n * and isn't needed for real-world JSONP callbacks.\n */\nconst SAFE_CALLBACK_PATTERN = /^[a-zA-Z_$][a-zA-Z0-9_$.]*$/;\n\n/**\n * Dangerous patterns that should never appear in a callback name,\n * even if they technically match the safe pattern.\n */\nconst DANGEROUS_CALLBACK_PATTERNS = [\n /\\.\\./, // prototype chain traversal\n] as const;\n\n/**\n * Validates and sanitizes a JSONP callback parameter.\n *\n * Returns the callback name if safe, or null if the callback is dangerous.\n * Use this to validate `?callback=` query parameters before wrapping responses.\n *\n * @param callback - The callback parameter value\n * @param maxLength - Maximum allowed length (default: 128)\n * @returns The safe callback name, or null if invalid\n *\n * @example\n * ```ts\n * const cb = sanitizeJsonpCallback(req.query.callback);\n * if (cb) {\n * res.set('Content-Type', 'application/javascript');\n * res.send(`${cb}(${JSON.stringify(data)})`);\n * } else {\n * res.status(400).json({ error: 'Invalid callback' });\n * }\n * ```\n */\nexport function sanitizeJsonpCallback(callback: string, maxLength = 128): string | null {\n if (typeof callback !== 'string' || callback.length === 0) {\n return null;\n }\n\n if (callback.length > maxLength) {\n return null;\n }\n\n if (!SAFE_CALLBACK_PATTERN.test(callback)) {\n return null;\n }\n\n for (const pattern of DANGEROUS_CALLBACK_PATTERNS) {\n if (pattern.test(callback)) {\n return null;\n }\n }\n\n return callback;\n}\n\n/**\n * Checks if a JSONP callback parameter contains potentially dangerous content.\n *\n * @param callback - The callback parameter value\n * @returns True if the callback is dangerous / invalid\n */\nexport function detectJsonpInjection(callback: string): boolean {\n if (typeof callback !== 'string' || callback.length === 0) {\n return false;\n }\n\n // If it doesn't match the safe pattern, it's potentially dangerous\n if (!SAFE_CALLBACK_PATTERN.test(callback)) {\n return true;\n }\n\n for (const pattern of DANGEROUS_CALLBACK_PATTERNS) {\n if (pattern.test(callback)) {\n return true;\n }\n }\n\n return false;\n}\n","/**\n * @module @arcis/node/sanitizers/pii\n * PII (Personally Identifiable Information) detection and redaction\n *\n * Detects: email addresses, phone numbers, credit card numbers, SSNs, IP addresses\n */\n\n// ─── Types ───────────────────────────────────────────────────────────────────\n\nexport type PiiType = 'email' | 'phone' | 'credit_card' | 'ssn' | 'ip_address';\n\nexport interface PiiMatch {\n type: PiiType;\n value: string;\n start: number;\n end: number;\n}\n\nexport interface PiiScanOptions {\n /** PII types to scan for. Default: all types */\n types?: PiiType[];\n}\n\nexport interface PiiRedactOptions extends PiiScanOptions {\n /** Replacement for redacted values. Default: '[REDACTED]' */\n replacement?: string;\n /** Use type-specific replacements like '[EMAIL]', '[SSN]'. Default: false */\n typeLabels?: boolean;\n}\n\n// ─── Patterns ────────────────────────────────────────────────────────────────\n\n// Email: simplified RFC 5322 — catches real-world emails without ReDoS risk\nconst EMAIL_RE = /[a-zA-Z0-9._%+-]+@[a-zA-Z0-9](?:[a-zA-Z0-9-]{0,61}[a-zA-Z0-9])?(?:\\.[a-zA-Z]{2,})+/g;\n\n// US phone numbers: (xxx) xxx-xxxx, xxx-xxx-xxxx, xxx.xxx.xxxx, xxx xxx xxxx, +1xxxxxxxxxx\n// (?<!\\d) / (?!\\d) boundaries prevent false positives inside longer digit\n// sequences like ZIP+number combos (\"94102 555-1234\") or bank account strings.\nconst PHONE_RE = /(?<!\\d)(?:\\+?1[-.\\s]?)?\\(?[2-9]\\d{2}\\)?[-.\\s]?\\d{3}[-.\\s]?\\d{4}(?!\\d)/g;\n\n// Credit cards: 13-19 digits with optional separators (spaces or dashes)\nconst CREDIT_CARD_RE = /\\b(?:\\d[ -]*?){13,19}\\b/g;\n\n// SSN: XXX-XX-XXXX (with dashes or spaces)\nconst SSN_RE = /\\b\\d{3}[-\\s]\\d{2}[-\\s]\\d{4}\\b/g;\n\n// IPv4 addresses\nconst IPV4_RE = /\\b(?:(?:25[0-5]|2[0-4]\\d|[01]?\\d\\d?)\\.){3}(?:25[0-5]|2[0-4]\\d|[01]?\\d\\d?)\\b/g;\n\n// IPv6 addresses (simplified — full addresses and common abbreviations)\nconst IPV6_RE = /\\b(?:[0-9a-fA-F]{1,4}:){7}[0-9a-fA-F]{1,4}\\b|\\b(?:[0-9a-fA-F]{1,4}:){1,7}:|::(?:[0-9a-fA-F]{1,4}:){0,5}[0-9a-fA-F]{1,4}\\b/g;\n\nconst PATTERN_MAP: Record<PiiType, RegExp[]> = {\n email: [EMAIL_RE],\n phone: [PHONE_RE],\n credit_card: [CREDIT_CARD_RE],\n ssn: [SSN_RE],\n ip_address: [IPV4_RE, IPV6_RE],\n};\n\nconst ALL_TYPES: PiiType[] = ['email', 'phone', 'credit_card', 'ssn', 'ip_address'];\n\nconst TYPE_LABELS: Record<PiiType, string> = {\n email: '[EMAIL]',\n phone: '[PHONE]',\n credit_card: '[CREDIT_CARD]',\n ssn: '[SSN]',\n ip_address: '[IP_ADDRESS]',\n};\n\n// ─── Luhn Check ──────────────────────────────────────────────────────────────\n\n/**\n * Validate a credit card number using the Luhn algorithm.\n * Strips spaces and dashes before checking.\n */\nfunction luhnCheck(value: string): boolean {\n const digits = value.replace(/[\\s-]/g, '');\n if (!/^\\d{13,19}$/.test(digits)) return false;\n\n let sum = 0;\n let alternate = false;\n for (let i = digits.length - 1; i >= 0; i--) {\n let n = parseInt(digits[i], 10);\n if (alternate) {\n n *= 2;\n if (n > 9) n -= 9;\n }\n sum += n;\n alternate = !alternate;\n }\n return sum % 10 === 0;\n}\n\n// ─── Core Functions ──────────────────────────────────────────────────────────\n\n/**\n * Scan a string for PII and return all matches.\n *\n * @param input - String to scan\n * @param options - Optional scan configuration\n * @returns Array of PII matches with type, value, and position\n *\n * @example\n * scanPii('Call me at 555-123-4567 or email john@example.com')\n * // [\n * // { type: 'phone', value: '555-123-4567', start: 11, end: 23 },\n * // { type: 'email', value: 'john@example.com', start: 33, end: 49 }\n * // ]\n */\nexport function scanPii(input: string, options: PiiScanOptions = {}): PiiMatch[] {\n if (!input || typeof input !== 'string') return [];\n\n const types = options.types ?? ALL_TYPES;\n const matches: PiiMatch[] = [];\n\n for (const type of types) {\n const patterns = PATTERN_MAP[type];\n if (!patterns) continue;\n\n for (const pattern of patterns) {\n const re = new RegExp(pattern.source, pattern.flags);\n let match: RegExpExecArray | null;\n\n while ((match = re.exec(input)) !== null) {\n const value = match[0];\n\n // Credit card: validate with Luhn algorithm\n if (type === 'credit_card' && !luhnCheck(value)) continue;\n\n // SSN: reject invalid ranges (000, 666, 900-999 for area)\n if (type === 'ssn') {\n const area = parseInt(value.substring(0, 3), 10);\n if (area === 0 || area === 666 || area >= 900) continue;\n }\n\n matches.push({\n type,\n value,\n start: match.index,\n end: match.index + value.length,\n });\n }\n }\n }\n\n // Sort by position\n matches.sort((a, b) => a.start - b.start);\n return matches;\n}\n\n/**\n * Check if a string contains any PII.\n *\n * @param input - String to check\n * @param options - Optional scan configuration\n * @returns true if PII is detected\n */\nexport function detectPii(input: string, options: PiiScanOptions = {}): boolean {\n return scanPii(input, options).length > 0;\n}\n\n/**\n * Redact PII from a string, replacing matches with a placeholder.\n *\n * @param input - String to redact\n * @param options - Redaction options\n * @returns String with PII replaced\n *\n * @example\n * redactPii('Email: john@example.com, SSN: 123-45-6789')\n * // 'Email: [REDACTED], SSN: [REDACTED]'\n *\n * redactPii('Email: john@example.com', { typeLabels: true })\n * // 'Email: [EMAIL]'\n */\nexport function redactPii(input: string, options: PiiRedactOptions = {}): string {\n if (!input || typeof input !== 'string') return input;\n\n const matches = scanPii(input, options);\n if (matches.length === 0) return input;\n\n const replacement = options.replacement ?? '[REDACTED]';\n\n // Replace from end to preserve positions\n let result = input;\n for (let i = matches.length - 1; i >= 0; i--) {\n const m = matches[i];\n const label = options.typeLabels ? TYPE_LABELS[m.type] : replacement;\n result = result.substring(0, m.start) + label + result.substring(m.end);\n }\n\n return result;\n}\n\n/**\n * Scan an object's string values for PII recursively.\n *\n * @param obj - Object to scan\n * @param options - Optional scan configuration\n * @returns Array of PII matches with the field path prepended\n */\nexport function scanObjectPii(\n obj: Record<string, unknown>,\n options: PiiScanOptions = {},\n path = '',\n): (PiiMatch & { field: string })[] {\n const results: (PiiMatch & { field: string })[] = [];\n if (!obj || typeof obj !== 'object') return results;\n\n for (const [key, value] of Object.entries(obj)) {\n const fieldPath = path ? `${path}.${key}` : key;\n\n if (typeof value === 'string') {\n const matches = scanPii(value, options);\n for (const m of matches) {\n results.push({ ...m, field: fieldPath });\n }\n } else if (value && typeof value === 'object' && !Array.isArray(value)) {\n results.push(...scanObjectPii(value as Record<string, unknown>, options, fieldPath));\n } else if (Array.isArray(value)) {\n for (let i = 0; i < value.length; i++) {\n const item = value[i];\n if (typeof item === 'string') {\n const matches = scanPii(item, options);\n for (const m of matches) {\n results.push({ ...m, field: `${fieldPath}[${i}]` });\n }\n } else if (item && typeof item === 'object') {\n results.push(...scanObjectPii(item as Record<string, unknown>, options, `${fieldPath}[${i}]`));\n }\n }\n }\n }\n\n return results;\n}\n\n/**\n * Redact PII from all string values in an object recursively.\n *\n * @param obj - Object to redact\n * @param options - Redaction options\n * @returns New object with PII redacted\n */\nexport function redactObjectPii<T extends Record<string, unknown>>(\n obj: T,\n options: PiiRedactOptions = {},\n): T {\n if (!obj || typeof obj !== 'object') return obj;\n\n const result: Record<string, unknown> = {};\n\n for (const [key, value] of Object.entries(obj)) {\n if (typeof value === 'string') {\n result[key] = redactPii(value, options);\n } else if (Array.isArray(value)) {\n result[key] = value.map(item => {\n if (typeof item === 'string') return redactPii(item, options);\n if (item && typeof item === 'object') return redactObjectPii(item as Record<string, unknown>, options);\n return item;\n });\n } else if (value && typeof value === 'object') {\n result[key] = redactObjectPii(value as Record<string, unknown>, options);\n } else {\n result[key] = value;\n }\n }\n\n return result as T;\n}\n","/**\n * @module @arcis/node/sanitizers/encode\n * Context-aware output encoding for XSS prevention.\n *\n * Wrong-context encoding is the #1 cause of XSS bypasses in \"protected\" apps.\n * A single sanitize() is not enough when output goes to JS, CSS, or attribute contexts.\n */\n\n// HTML entity map — covers the 5 dangerous chars in HTML body context\nconst HTML_ENTITIES: Record<string, string> = {\n '&': '&',\n '<': '<',\n '>': '>',\n '\"': '"',\n \"'\": ''',\n};\n\nconst HTML_ENCODE_RE = /[&<>\"']/g;\n\n/**\n * Encodes for HTML body context. Entity-encodes & < > \" '\n *\n * Use when outputting to HTML element content:\n * `<p>${encodeForHtml(userInput)}</p>`\n */\nexport function encodeForHtml(value: string): string {\n if (!value) return '';\n return value.replace(HTML_ENCODE_RE, (ch) => HTML_ENTITIES[ch]);\n}\n\n/**\n * Encodes for HTML attribute context.\n * All non-alphanumeric characters are encoded as `&#xHH;` hex entities.\n *\n * Use when outputting to HTML attributes:\n * `<div title=\"${encodeForAttribute(userInput)}\">`\n */\nexport function encodeForAttribute(value: string): string {\n if (!value) return '';\n let result = '';\n for (let i = 0; i < value.length; i++) {\n const ch = value.charCodeAt(i);\n // Allow a-z A-Z 0-9\n if (\n (ch >= 0x30 && ch <= 0x39) || // 0-9\n (ch >= 0x41 && ch <= 0x5a) || // A-Z\n (ch >= 0x61 && ch <= 0x7a) // a-z\n ) {\n result += value[i];\n } else {\n result += `&#x${ch.toString(16).toUpperCase()};`;\n }\n }\n return result;\n}\n\n/**\n * Encodes for JavaScript string context.\n * Non-alphanumeric characters are escaped as `\\xHH` (ASCII) or `\\uHHHH` (Unicode).\n *\n * Use when embedding in JS string literals:\n * `var x = '${encodeForJs(userInput)}';`\n */\nexport function encodeForJs(value: string): string {\n if (!value) return '';\n let result = '';\n // Use for-of to iterate codepoints, not UTF-16 code units.\n // This correctly handles surrogate pairs (emoji, symbols outside BMP).\n for (const char of value) {\n const cp = char.codePointAt(0);\n if (cp === undefined) continue;\n // Allow a-z A-Z 0-9\n if (\n (cp >= 0x30 && cp <= 0x39) || // 0-9\n (cp >= 0x41 && cp <= 0x5a) || // A-Z\n (cp >= 0x61 && cp <= 0x7a) // a-z\n ) {\n result += char;\n } else if (cp < 0x100) {\n result += `\\\\x${cp.toString(16).toUpperCase().padStart(2, '0')}`;\n } else if (cp <= 0xFFFF) {\n result += `\\\\u${cp.toString(16).toUpperCase().padStart(4, '0')}`;\n } else {\n // Codepoints above BMP — use ES6 Unicode escape\n result += `\\\\u{${cp.toString(16).toUpperCase()}}`;\n }\n }\n return result;\n}\n\n/**\n * Encodes for URL parameter context. Percent-encodes all non-unreserved chars.\n *\n * Use when building query strings:\n * `?q=${encodeForUrl(userInput)}`\n */\nexport function encodeForUrl(value: string): string {\n if (!value) return '';\n // encodeURIComponent handles most cases but doesn't encode: ! ' ( ) *\n // We encode these additionally for full safety per RFC 3986\n return encodeURIComponent(value).replace(/[!'()*]/g, (ch) => {\n return `%${ch.charCodeAt(0).toString(16).toUpperCase()}`;\n });\n}\n\n/**\n * Encodes for CSS value context.\n * Non-alphanumeric characters are hex-escaped as `\\HH ` (trailing space per CSS spec).\n *\n * Use when embedding in CSS values:\n * `content: '${encodeForCss(userInput)}';`\n */\nexport function encodeForCss(value: string): string {\n if (!value) return '';\n let result = '';\n for (let i = 0; i < value.length; i++) {\n const ch = value.charCodeAt(i);\n // Allow a-z A-Z 0-9\n if (\n (ch >= 0x30 && ch <= 0x39) || // 0-9\n (ch >= 0x41 && ch <= 0x5a) || // A-Z\n (ch >= 0x61 && ch <= 0x7a) // a-z\n ) {\n result += value[i];\n } else {\n // CSS hex escape: backslash + hex code + trailing space (CSS spec requirement)\n result += `\\\\${ch.toString(16).toUpperCase()} `;\n }\n }\n return result;\n}\n","/**\n * @module @arcis/node/sanitizers/graphql\n * GraphQL injection prevention (sdk-vectors.md tier 1 #21).\n *\n * Two threats covered:\n *\n * 1. **Depth-bomb DoS** — nested-query payloads like\n * `query { x { x { x { ... } } } }` to ridiculous depth that explode\n * resolver work (each `{` typically maps to a database round-trip).\n * Even a 50-deep query against a real schema can hammer the\n * backend; 1000-deep crashes the resolver entirely.\n *\n * 2. **Introspection abuse** — `__schema` / `__type` / `__typename`\n * queries that let an attacker enumerate the entire schema, then\n * use that map to find sensitive fields, deprecated mutations,\n * or unprotected admin paths. Production GraphQL endpoints should\n * disable introspection by default.\n *\n * v1 is regex-based: count `{` / `}` for nesting depth (no escape\n * handling — strings inside the query that contain `{` will\n * over-count). False positives are an acceptable tradeoff for v1\n * because (a) the depth threshold is well above legitimate query\n * shapes, (b) a real GraphQL parser pulls in `graphql` as a runtime\n * dep — significant for a sanitizer that ships in every Arcis\n * install. Customers running queries near the threshold can either\n * raise `maxDepth` or bring their own AST pre-pass.\n *\n * NOT included in v1:\n * - Field-count limit (some servers have this; orthogonal to depth)\n * - Alias-bomb detection (`q { f1: foo, f2: foo, ...}` — easier as\n * a length-check than a parse)\n * - Variable rebinding attacks\n *\n * Each is a follow-up if customers ask. Documented inline.\n */\n\nexport interface GraphqlGuardOptions {\n /** Maximum allowed nesting depth. Default: 10. Most legit queries are <8. */\n maxDepth?: number;\n /** Maximum query string length in characters. Default: 10000. */\n maxLength?: number;\n /**\n * Block introspection queries (`__schema`, `__type`). Default: true.\n * Set `false` in development if you rely on GraphiQL / Apollo\n * Studio. Production should leave this on.\n */\n blockIntrospection?: boolean;\n /**\n * Maximum number of field aliases per query (`label: field`).\n * Default: 50. Alias-bomb attacks repeat the same expensive field\n * under many labels to multiply backend cost. Real queries rarely\n * use more than 20 aliases. improvements.md §1.2 V34.\n */\n maxAliases?: number;\n /**\n * Reject queries whose fragment definitions form a cycle (direct\n * self-reference `fragment A on T { ...A }` or indirect\n * `A → B → A`). Such cycles either infinite-loop a naive resolver\n * or get rejected by `graphql-core` with a 500. Default: true.\n * improvements.md §1.2 V34.\n */\n blockFragmentCycles?: boolean;\n}\n\nexport type GraphqlViolation =\n | 'depth'\n | 'length'\n | 'introspection'\n | 'aliases'\n | 'fragment_cycle';\n\nexport interface GraphqlGuardResult {\n /** True if the query violated any configured limit. */\n blocked: boolean;\n /** Which limit fired first. Precedence: depth → introspection → aliases → fragment_cycle → length. */\n reason?: GraphqlViolation;\n /** Observed nesting depth. Always returned. */\n depth: number;\n /** Observed length. Always returned. */\n length: number;\n /** Observed alias count (improvements.md §1.2 V34). Always returned. */\n aliases: number;\n}\n\nconst DEFAULTS = {\n maxDepth: 10,\n maxLength: 10000,\n blockIntrospection: true,\n maxAliases: 50,\n blockFragmentCycles: true,\n} as const;\n\n/**\n * Word-boundary `__` reflection markers. GraphQL spec reserves the\n * `__` prefix for introspection — `__schema`, `__type`, `__typename`,\n * `__typeKind`, `__directive`. Matching the prefix catches them all\n * without enumerating; the boundary anchor (`\\b__`) avoids\n * false-matches on user fields like `last__updated_at`.\n *\n * `__typename` is the one introspection field that's commonly used\n * legitimately (Apollo client requests it on every query). We\n * deliberately let it through by listing the others explicitly.\n */\nconst INTROSPECTION_PATTERN = /\\b__(schema|type|typeKind|directive)\\b/;\n\n/**\n * Compute the maximum nesting depth of a GraphQL query string by\n * counting `{` and `}` runs. Strings inside the query (e.g.\n * `field(arg: \"{...}\")`) inflate this — accepted v1 tradeoff. A\n * future AST-mode implementation lives behind a separate flag.\n */\nfunction computeDepth(query: string): number {\n let depth = 0;\n let max = 0;\n for (let i = 0; i < query.length; i++) {\n const c = query.charCodeAt(i);\n if (c === 123 /* { */) {\n depth++;\n if (depth > max) max = depth;\n } else if (c === 125 /* } */) {\n // Don't go negative on malformed input — clamp at 0.\n if (depth > 0) depth--;\n }\n }\n return max;\n}\n\n// `label: field` — alias of one field to another name. Excludes\n// patterns like `query Foo:` where Foo is an operation name (handled\n// because the regex requires the second token to be a name AND\n// alias semantics only apply inside `{...}` blocks; this is a\n// lexical approximation, not a parser).\nconst ALIAS_PATTERN = /\\b([a-zA-Z_][a-zA-Z0-9_]*)\\s*:\\s*([a-zA-Z_][a-zA-Z0-9_]*)\\b/g;\n\n// `fragment <name> on <type> {` — captures the fragment NAME.\nconst FRAGMENT_DEF_PATTERN =\n /\\bfragment\\s+([a-zA-Z_][a-zA-Z0-9_]*)\\s+on\\s+[a-zA-Z_][a-zA-Z0-9_]*\\s*\\{/g;\n\n// `...FragmentName` spread inside a selection set.\nconst FRAGMENT_SPREAD_PATTERN = /\\.\\.\\.\\s*([a-zA-Z_][a-zA-Z0-9_]*)\\b/g;\n\nfunction countAliases(query: string): number {\n let n = 0;\n ALIAS_PATTERN.lastIndex = 0;\n while (ALIAS_PATTERN.exec(query) !== null) n++;\n return n;\n}\n\n/**\n * Detect cycles in the fragment spread graph (improvements.md §1.2 V34).\n *\n * Walks `fragment X on T { ... }` definitions, builds adjacency from\n * each fragment to the names it spreads, and runs DFS for a back-edge.\n * Body of each fragment is brace-matched so the subsequent query\n * operation's spreads don't pollute the graph.\n */\nfunction hasFragmentCycle(query: string): boolean {\n const deps = new Map<string, Set<string>>();\n FRAGMENT_DEF_PATTERN.lastIndex = 0;\n let match: RegExpExecArray | null;\n while ((match = FRAGMENT_DEF_PATTERN.exec(query)) !== null) {\n const name = match[1];\n const bodyStart = match.index + match[0].length; // right after `{`\n // Brace-match to find the body end.\n let depth = 1;\n let i = bodyStart;\n while (i < query.length && depth > 0) {\n const ch = query[i];\n if (ch === '{') depth++;\n else if (ch === '}') depth--;\n i++;\n }\n const bodyEnd = depth === 0 ? i - 1 : i;\n const body = query.slice(bodyStart, bodyEnd);\n const spreads = new Set<string>();\n FRAGMENT_SPREAD_PATTERN.lastIndex = 0;\n let sm: RegExpExecArray | null;\n while ((sm = FRAGMENT_SPREAD_PATTERN.exec(body)) !== null) {\n spreads.add(sm[1]);\n }\n deps.set(name, spreads);\n }\n if (deps.size === 0) return false;\n\n const WHITE = 0;\n const GRAY = 1;\n const BLACK = 2;\n const color = new Map<string, number>();\n for (const name of deps.keys()) color.set(name, WHITE);\n\n function visit(name: string): boolean {\n if (color.get(name) === GRAY) return true; // back-edge\n if (color.get(name) === BLACK) return false;\n if (!deps.has(name)) return false; // spread to undefined fragment\n color.set(name, GRAY);\n for (const child of deps.get(name)!) {\n if (visit(child)) return true;\n }\n color.set(name, BLACK);\n return false;\n }\n\n for (const name of deps.keys()) {\n if (visit(name)) return true;\n }\n return false;\n}\n\n/**\n * Inspect a GraphQL query against the configured limits. Returns a\n * structured result; the middleware below uses this directly. Pure\n * function — no I/O, no res handle.\n */\nexport function inspectGraphqlQuery(\n query: string,\n options: GraphqlGuardOptions = {},\n): GraphqlGuardResult {\n const maxDepth = options.maxDepth ?? DEFAULTS.maxDepth;\n const maxLength = options.maxLength ?? DEFAULTS.maxLength;\n const blockIntrospection = options.blockIntrospection ?? DEFAULTS.blockIntrospection;\n const maxAliases = options.maxAliases ?? DEFAULTS.maxAliases;\n const blockFragmentCycles =\n options.blockFragmentCycles ?? DEFAULTS.blockFragmentCycles;\n\n const length = query.length;\n const depth = computeDepth(query);\n const aliases = countAliases(query);\n\n // Precedence: depth → introspection → aliases → fragment_cycle →\n // length. Cheapest-to-explain failures first; length last because\n // it's the easiest false-positive (long queries with deep inline\n // fragments are legitimate). improvements.md §1.2 V34.\n if (depth > maxDepth) {\n return { blocked: true, reason: 'depth', depth, length, aliases };\n }\n if (blockIntrospection && INTROSPECTION_PATTERN.test(query)) {\n return { blocked: true, reason: 'introspection', depth, length, aliases };\n }\n if (aliases > maxAliases) {\n return { blocked: true, reason: 'aliases', depth, length, aliases };\n }\n if (blockFragmentCycles && hasFragmentCycle(query)) {\n return { blocked: true, reason: 'fragment_cycle', depth, length, aliases };\n }\n if (length > maxLength) {\n return { blocked: true, reason: 'length', depth, length, aliases };\n }\n\n return { blocked: false, depth, length, aliases };\n}\n\n/**\n * Detect-only API matching the rest of the sanitizer module surface\n * (`detectXss` / `detectSql` / `detectXxe` / etc.). Returns a boolean\n * for callers that just want a yes/no — use `inspectGraphqlQuery` if\n * you need the structured reason.\n */\nexport function detectGraphqlAbuse(\n query: string,\n options?: GraphqlGuardOptions,\n): boolean {\n if (typeof query !== 'string' || query.length === 0) return false;\n return inspectGraphqlQuery(query, options).blocked;\n}\n","/**\n * @module @arcis/node/validation/schema\n * Request validation middleware\n */\n\nimport type { Request, Response, NextFunction, RequestHandler } from 'express';\nimport { VALIDATION, ERRORS } from '../core/constants';\nimport type { ValidationSchema, FieldValidator } from '../core/types';\nimport { sanitizeString } from '../sanitizers';\n\n/**\n * Create Express middleware for request validation.\n * Prevents mass assignment by only allowing fields defined in the schema.\n * \n * @param schema - Validation schema defining expected fields\n * @param source - Request property to validate ('body', 'query', or 'params')\n * @returns Express middleware\n * \n * @example\n * app.post('/users', validate({\n * email: { type: 'email', required: true },\n * name: { type: 'string', min: 2, max: 50 },\n * age: { type: 'number', min: 0, max: 150 },\n * role: { type: 'string', enum: ['user', 'admin'] }\n * }), handler);\n * \n * @example\n * // Validate query params\n * app.get('/search', validate({\n * q: { type: 'string', required: true, min: 1 },\n * page: { type: 'number', min: 1 }\n * }, 'query'), handler);\n */\nexport function validate(\n schema: ValidationSchema,\n source: 'body' | 'query' | 'params' = 'body'\n): RequestHandler {\n return (req: Request, res: Response, next: NextFunction) => {\n const data = req[source] || {};\n const errors: string[] = [];\n const validated: Record<string, unknown> = {};\n\n for (const [field, rules] of Object.entries(schema)) {\n const value = data[field];\n const result = validateField(field, value, rules);\n \n if (result.errors.length > 0) {\n errors.push(...result.errors);\n } else if (result.value !== undefined) {\n validated[field] = result.value;\n }\n }\n\n if (errors.length > 0) {\n res.status(400).json({ errors });\n return;\n }\n\n // Replace with validated data (prevents mass assignment).\n // SECURITY: Express 5 makes req.body/query/params read-only. Use\n // defineProperty so this works on both Express 4 and 5; direct\n // assignment crashes Express 5 with TypeError.\n Object.defineProperty(req, source, {\n value: validated,\n writable: true,\n configurable: true,\n enumerable: true,\n });\n next();\n };\n}\n\n/**\n * Validate a single field against its rules.\n */\nfunction validateField(\n field: string,\n value: unknown,\n rules: FieldValidator\n): { value?: unknown; errors: string[] } {\n const errors: string[] = [];\n\n // Required check\n if (rules.required && (value === undefined || value === null || value === '')) {\n errors.push(ERRORS.VALIDATION.REQUIRED(field));\n return { errors };\n }\n\n // Skip optional empty fields\n if (value === undefined || value === null) {\n return { errors: [] };\n }\n\n let typedValue: unknown = value;\n let isValid = true;\n\n // Type validation and coercion\n switch (rules.type) {\n case 'string':\n if (typeof value !== 'string') {\n errors.push(ERRORS.VALIDATION.INVALID_TYPE(field, 'string'));\n isValid = false;\n break;\n }\n if (rules.min !== undefined && value.length < rules.min) {\n errors.push(ERRORS.VALIDATION.MIN_LENGTH(field, rules.min));\n isValid = false;\n }\n if (rules.max !== undefined && value.length > rules.max) {\n errors.push(ERRORS.VALIDATION.MAX_LENGTH(field, rules.max));\n isValid = false;\n }\n if (rules.pattern && !rules.pattern.test(value)) {\n errors.push(ERRORS.VALIDATION.INVALID_FORMAT(field));\n isValid = false;\n }\n // Enum check runs before sanitization so the raw value is compared.\n // Sanitizing first could silently modify the value and cause a mismatch\n // with enum entries that contain characters the sanitizer would strip.\n if (isValid && rules.enum && !rules.enum.includes(value)) {\n errors.push(ERRORS.VALIDATION.INVALID_ENUM(field, rules.enum));\n isValid = false;\n }\n if (isValid && rules.sanitize !== false) {\n typedValue = sanitizeString(value);\n }\n break;\n\n case 'number':\n typedValue = Number(value);\n if (isNaN(typedValue as number)) {\n errors.push(ERRORS.VALIDATION.INVALID_TYPE(field, 'number'));\n isValid = false;\n break;\n }\n if (rules.min !== undefined && (typedValue as number) < rules.min) {\n errors.push(ERRORS.VALIDATION.MIN_VALUE(field, rules.min));\n isValid = false;\n }\n if (rules.max !== undefined && (typedValue as number) > rules.max) {\n errors.push(ERRORS.VALIDATION.MAX_VALUE(field, rules.max));\n isValid = false;\n }\n break;\n\n case 'boolean':\n if (value === 'true' || value === true || value === 1 || value === '1') {\n typedValue = true;\n } else if (value === 'false' || value === false || value === 0 || value === '0') {\n typedValue = false;\n } else {\n errors.push(ERRORS.VALIDATION.INVALID_TYPE(field, 'boolean'));\n isValid = false;\n }\n break;\n\n case 'email':\n if (!VALIDATION.EMAIL.test(String(value))) {\n errors.push(ERRORS.VALIDATION.INVALID_EMAIL(field));\n isValid = false;\n }\n if (isValid) {\n typedValue = sanitizeString(String(value).toLowerCase().trim());\n }\n break;\n\n case 'url':\n if (!VALIDATION.URL.test(String(value))) {\n errors.push(ERRORS.VALIDATION.INVALID_URL(field));\n isValid = false;\n }\n if (isValid) {\n typedValue = sanitizeString(String(value));\n }\n break;\n\n case 'uuid':\n if (!VALIDATION.UUID.test(String(value))) {\n errors.push(ERRORS.VALIDATION.INVALID_UUID(field));\n isValid = false;\n }\n break;\n\n case 'array':\n if (!Array.isArray(value)) {\n errors.push(ERRORS.VALIDATION.INVALID_TYPE(field, 'array'));\n isValid = false;\n break;\n }\n if (rules.min !== undefined && value.length < rules.min) {\n errors.push(ERRORS.VALIDATION.MIN_ITEMS(field, rules.min));\n isValid = false;\n }\n if (rules.max !== undefined && value.length > rules.max) {\n errors.push(ERRORS.VALIDATION.MAX_ITEMS(field, rules.max));\n isValid = false;\n }\n break;\n\n case 'object':\n if (typeof value !== 'object' || Array.isArray(value) || value === null) {\n errors.push(ERRORS.VALIDATION.INVALID_TYPE(field, 'object'));\n isValid = false;\n }\n break;\n }\n\n // Enum validation for non-string types (strings check enum before sanitizing above).\n if (isValid && rules.enum && rules.type !== 'string' && !rules.enum.includes(typedValue)) {\n errors.push(ERRORS.VALIDATION.INVALID_ENUM(field, rules.enum));\n isValid = false;\n }\n\n // Custom validation\n if (isValid && rules.custom) {\n const customResult = rules.custom(typedValue);\n if (customResult === undefined) {\n throw new TypeError(\n `Custom validator for field \"${field}\" returned undefined. ` +\n 'Return true to pass, false to fail, or a string error message.'\n );\n }\n if (customResult !== true) {\n errors.push(typeof customResult === 'string' && customResult.length > 0 ? customResult : `${field} is invalid`);\n isValid = false;\n }\n }\n\n return {\n value: isValid ? typedValue : undefined,\n errors,\n };\n}\n\n/**\n * Alias for validate\n * @see validate\n */\nexport const createValidator = validate;\n","/**\n * @module @arcis/node/validation/file\n * File upload validation and filename sanitization\n */\n\n// =============================================================================\n// MAGIC BYTES — first bytes of common file types\n// =============================================================================\n\nconst MAGIC_BYTES: Record<string, Buffer[]> = {\n // Images\n 'image/jpeg': [Buffer.from([0xFF, 0xD8, 0xFF])],\n 'image/png': [Buffer.from([0x89, 0x50, 0x4E, 0x47])],\n 'image/gif': [Buffer.from('GIF87a'), Buffer.from('GIF89a')],\n 'image/webp': [Buffer.from('RIFF')], // RIFF....WEBP\n 'image/bmp': [Buffer.from([0x42, 0x4D])],\n 'image/svg+xml': [], // text-based, check separately\n\n // Documents\n 'application/pdf': [Buffer.from('%PDF')],\n 'application/zip': [Buffer.from([0x50, 0x4B, 0x03, 0x04])],\n\n // Audio/Video\n 'audio/mpeg': [Buffer.from([0xFF, 0xFB]), Buffer.from([0xFF, 0xF3]), Buffer.from([0x49, 0x44, 0x33])],\n 'video/mp4': [], // ftyp at offset 4\n};\n\n// =============================================================================\n// DANGEROUS EXTENSIONS — files that can execute code\n// =============================================================================\n\nconst DANGEROUS_EXTENSIONS = new Set([\n // Scripts\n '.exe', '.bat', '.cmd', '.com', '.msi', '.scr', '.pif',\n '.vbs', '.vbe', '.js', '.jse', '.ws', '.wsf', '.wsc', '.wsh',\n '.ps1', '.ps1xml', '.ps2', '.ps2xml', '.psc1', '.psc2',\n '.sh', '.bash', '.csh', '.ksh',\n // Server-side\n '.php', '.php3', '.php4', '.php5', '.phtml', '.pht',\n '.asp', '.aspx', '.ashx', '.asmx', '.cer',\n '.jsp', '.jspx', '.jsw', '.jsv',\n '.cgi', '.pl', '.py', '.rb',\n // Java\n '.jar', '.war', '.ear', '.class',\n // Config that can execute\n '.htaccess', '.htpasswd',\n // Template engines\n '.ejs', '.pug', '.hbs', '.handlebars', '.njk', '.twig',\n // Shortcuts/links\n '.lnk', '.inf', '.reg', '.url',\n // Office macros\n '.docm', '.xlsm', '.pptm', '.dotm',\n]);\n\n// =============================================================================\n// TYPES\n// =============================================================================\n\n/** File upload validation options */\nexport interface ValidateFileOptions {\n /** Maximum file size in bytes. Default: 5MB */\n maxSize?: number;\n /** Allowed MIME types (e.g., ['image/jpeg', 'image/png']) */\n allowedTypes?: string[];\n /** Allowed file extensions (e.g., ['.jpg', '.png']). Includes dot. */\n allowedExtensions?: string[];\n /** Block dangerous/executable extensions. Default: true */\n blockExecutables?: boolean;\n /** Validate magic bytes match the claimed MIME type. Default: true */\n validateMagicBytes?: boolean;\n /** Block files with no extension. Default: true */\n blockNoExtension?: boolean;\n /** Block double extensions (e.g., file.php.jpg). Default: true */\n blockDoubleExtensions?: boolean;\n}\n\n/** File metadata for validation */\nexport interface FileInput {\n /** Original filename */\n filename: string;\n /** MIME type (as claimed by client) */\n mimetype: string;\n /** File size in bytes */\n size: number;\n /** File content buffer (for magic byte validation) */\n buffer?: Buffer;\n}\n\n/** File validation result */\nexport interface ValidateFileResult {\n /** Whether the file passed validation */\n valid: boolean;\n /** Validation errors (empty if valid) */\n errors: string[];\n /** Sanitized filename (safe for storage) */\n sanitizedFilename: string;\n}\n\n// =============================================================================\n// DEFAULTS\n// =============================================================================\n\nconst DEFAULT_MAX_SIZE = 5 * 1024 * 1024; // 5MB\n\n// =============================================================================\n// FILENAME SANITIZATION\n// =============================================================================\n\n/**\n * Sanitize a filename for safe storage.\n *\n * Strips path traversal, null bytes, control characters, and special characters.\n * Preserves the extension and converts to a filesystem-safe name.\n *\n * @param filename - The original filename\n * @returns A sanitized filename safe for storage\n *\n * @example\n * sanitizeFilename('../../etc/passwd') // 'etc_passwd'\n * sanitizeFilename('file<name>.jpg') // 'filename.jpg'\n * sanitizeFilename('photo (1).jpg') // 'photo_1.jpg'\n * sanitizeFilename('.htaccess') // 'htaccess'\n */\nexport function sanitizeFilename(filename: string): string {\n let name = filename;\n\n // Strip null bytes\n name = name.replace(/\\0/g, '');\n\n // Strip path components (both Unix and Windows)\n name = name.replace(/^.*[/\\\\]/, '');\n\n // Strip control characters\n name = name.replace(/[\\x00-\\x1F\\x7F]/g, '');\n\n // Strip characters unsafe for filesystems\n name = name.replace(/[<>:\"/\\\\|?*]/g, '');\n\n // Replace spaces and parens with underscores\n name = name.replace(/[\\s()]+/g, '_');\n\n // Strip leading dots (hidden files / .htaccess)\n name = name.replace(/^\\.+/, '');\n\n // Collapse multiple underscores/dots\n name = name.replace(/_{2,}/g, '_');\n name = name.replace(/\\.{2,}/g, '.');\n\n // Trim underscores before dots (e.g., \"photo_1_.jpg\" → \"photo_1.jpg\")\n name = name.replace(/_+\\./g, '.');\n\n // Trim underscores from edges\n name = name.replace(/^_+|_+$/g, '');\n\n // Fallback for empty name\n if (!name || name === '.') {\n name = 'unnamed';\n }\n\n return name;\n}\n\n// =============================================================================\n// MAGIC BYTE VALIDATION\n// =============================================================================\n\n/**\n * Check if file content matches the claimed MIME type via magic bytes.\n */\nfunction matchesMagicBytes(buffer: Buffer, mimetype: string): boolean {\n const signatures = MAGIC_BYTES[mimetype];\n if (!signatures || signatures.length === 0) return true; // no signature to check\n\n return signatures.some(sig => {\n if (buffer.length < sig.length) return false;\n return buffer.subarray(0, sig.length).equals(sig);\n });\n}\n\n// =============================================================================\n// EXTENSION HELPERS\n// =============================================================================\n\n/**\n * Get the extension from a filename (lowercase, with dot).\n */\nfunction getExtension(filename: string): string {\n const lastDot = filename.lastIndexOf('.');\n if (lastDot < 1) return '';\n return filename.slice(lastDot).toLowerCase();\n}\n\n/**\n * Check if a filename has double extensions (e.g., file.php.jpg).\n */\nfunction hasDoubleExtension(filename: string): boolean {\n const parts = filename.split('.');\n if (parts.length < 3) return false;\n\n // Check if any non-final extension is dangerous\n for (let i = 1; i < parts.length - 1; i++) {\n const ext = '.' + parts[i].toLowerCase();\n if (DANGEROUS_EXTENSIONS.has(ext)) return true;\n }\n return false;\n}\n\n// =============================================================================\n// FILE VALIDATION\n// =============================================================================\n\n/**\n * Validate a file upload for security.\n *\n * Checks file size, MIME type, extension, magic bytes, and dangerous patterns.\n * Returns a result with validation errors and a sanitized filename.\n *\n * @param file - File metadata and optional content\n * @param options - Validation options\n * @returns Validation result\n *\n * @example\n * const result = validateFile(\n * { filename: 'photo.jpg', mimetype: 'image/jpeg', size: 1024, buffer },\n * { allowedTypes: ['image/jpeg', 'image/png'], maxSize: 2 * 1024 * 1024 }\n * );\n * if (!result.valid) {\n * return res.status(400).json({ errors: result.errors });\n * }\n * // Use result.sanitizedFilename for storage\n *\n * @example\n * // Block executables only (no whitelist)\n * const result = validateFile(file, { blockExecutables: true });\n */\nexport function validateFile(\n file: FileInput,\n options: ValidateFileOptions = {}\n): ValidateFileResult {\n const {\n maxSize = DEFAULT_MAX_SIZE,\n allowedTypes,\n allowedExtensions,\n blockExecutables = true,\n validateMagicBytes = true,\n blockNoExtension = true,\n blockDoubleExtensions = true,\n } = options;\n\n const errors: string[] = [];\n const sanitizedFilename = sanitizeFilename(file.filename);\n const extension = getExtension(sanitizedFilename);\n\n // Size check\n if (file.size > maxSize) {\n errors.push(`File size ${file.size} exceeds maximum ${maxSize} bytes`);\n }\n\n if (file.size === 0) {\n errors.push('File is empty');\n }\n\n // Extension checks\n if (blockNoExtension && !extension) {\n errors.push('File has no extension');\n }\n\n if (blockExecutables && extension && DANGEROUS_EXTENSIONS.has(extension)) {\n errors.push(`Executable extension \"${extension}\" is not allowed`);\n }\n\n if (blockDoubleExtensions && hasDoubleExtension(sanitizedFilename)) {\n errors.push('Double extensions with executable types are not allowed');\n }\n\n if (allowedExtensions && extension) {\n const normalizedAllowed = allowedExtensions.map(e => e.toLowerCase());\n if (!normalizedAllowed.includes(extension)) {\n errors.push(`Extension \"${extension}\" is not allowed. Allowed: ${normalizedAllowed.join(', ')}`);\n }\n }\n\n // MIME type check\n if (allowedTypes && !allowedTypes.includes(file.mimetype)) {\n errors.push(`MIME type \"${file.mimetype}\" is not allowed. Allowed: ${allowedTypes.join(', ')}`);\n }\n\n // Magic bytes validation\n if (validateMagicBytes && file.buffer && file.buffer.length > 0) {\n if (!matchesMagicBytes(file.buffer, file.mimetype)) {\n errors.push(`File content does not match claimed MIME type \"${file.mimetype}\"`);\n }\n }\n\n return {\n valid: errors.length === 0,\n errors,\n sanitizedFilename,\n };\n}\n\n/**\n * Check if a file extension is considered dangerous/executable.\n *\n * @param filename - Filename or extension to check\n * @returns true if the extension is dangerous\n */\nexport function isDangerousExtension(filename: string): boolean {\n const ext = getExtension(filename);\n return ext !== '' && DANGEROUS_EXTENSIONS.has(ext);\n}\n","/**\n * @module @arcis/node/validation/url\n * SSRF (Server-Side Request Forgery) prevention\n *\n * Validates URLs to ensure they don't target private/internal networks,\n * localhost, cloud metadata endpoints, or use dangerous protocols.\n *\n * @example\n * import { validateUrl } from '@arcis/node';\n *\n * // Block SSRF attempts\n * validateUrl('http://169.254.169.254/latest/meta-data/') // { safe: false, reason: 'link-local address' }\n * validateUrl('http://10.0.0.1/admin') // { safe: false, reason: 'private address (10.0.0.0/8)' }\n * validateUrl('http://localhost/secret') // { safe: false, reason: 'loopback address' }\n * validateUrl('file:///etc/passwd') // { safe: false, reason: 'disallowed protocol: file:' }\n *\n * // Allow safe URLs\n * validateUrl('https://api.example.com/data') // { safe: true }\n */\n\n/** Options for URL validation */\nexport interface ValidateUrlOptions {\n /** Allowed protocols. Default: ['http:', 'https:'] */\n allowedProtocols?: string[];\n /** Additional hostnames to block (e.g., internal service names) */\n blockedHosts?: string[];\n /** Additional hostnames to always allow (bypass IP checks) */\n allowedHosts?: string[];\n /** Allow localhost/loopback. Default: false */\n allowLocalhost?: boolean;\n /** Allow private/internal IPs. Default: false */\n allowPrivate?: boolean;\n}\n\n/** Result of URL validation */\nexport interface ValidateUrlResult {\n /** Whether the URL is safe to fetch */\n safe: boolean;\n /** Reason the URL was blocked (only set when safe=false) */\n reason?: string;\n}\n\n/**\n * Validate a URL for SSRF safety.\n *\n * Checks:\n * 1. Valid URL format\n * 2. Allowed protocol (default: http, https only)\n * 3. Not localhost/loopback (127.x.x.x, ::1, localhost)\n * 4. Not private IP (10.x, 172.16-31.x, 192.168.x)\n * 5. Not link-local (169.254.x.x — includes AWS/GCP/Azure metadata)\n * 6. Not blocked hostname\n * 7. No credentials in URL (user:pass@host)\n *\n * @param url - The URL string to validate\n * @param options - Validation options\n * @returns Validation result with safe flag and optional reason\n */\nexport function validateUrl(url: string, options: ValidateUrlOptions = {}): ValidateUrlResult {\n const {\n allowedProtocols = ['http:', 'https:'],\n blockedHosts = [],\n allowedHosts = [],\n allowLocalhost = false,\n allowPrivate = false,\n } = options;\n\n if (typeof url !== 'string' || url.trim() === '') {\n return { safe: false, reason: 'invalid URL: empty or not a string' };\n }\n\n // Parse URL\n let parsed: URL;\n try {\n parsed = new URL(url);\n } catch {\n return { safe: false, reason: 'invalid URL: failed to parse' };\n }\n\n // Check protocol\n if (!allowedProtocols.includes(parsed.protocol)) {\n return { safe: false, reason: `disallowed protocol: ${parsed.protocol}` };\n }\n\n // Check for credentials in URL (user:pass@host)\n if (parsed.username || parsed.password) {\n return { safe: false, reason: 'URL contains credentials' };\n }\n\n const hostname = parsed.hostname.toLowerCase();\n\n // Check explicit allowlist first (bypass IP checks)\n if (allowedHosts.some(h => hostname === h.toLowerCase())) {\n return { safe: true };\n }\n\n // Check explicit blocklist\n if (blockedHosts.some(h => hostname === h.toLowerCase())) {\n return { safe: false, reason: `blocked host: ${hostname}` };\n }\n\n // Check localhost/loopback\n if (!allowLocalhost) {\n if (\n hostname === 'localhost' ||\n hostname === '127.0.0.1' ||\n hostname === '[::1]' ||\n hostname === '::1' ||\n hostname === '0.0.0.0' ||\n hostname.endsWith('.localhost')\n ) {\n return { safe: false, reason: 'loopback address' };\n }\n\n // Check 127.x.x.x range\n if (/^127\\.\\d{1,3}\\.\\d{1,3}\\.\\d{1,3}$/.test(hostname)) {\n return { safe: false, reason: 'loopback address' };\n }\n }\n\n // Check decimal IP (e.g., 2130706433 = 127.0.0.1)\n if (!allowLocalhost || !allowPrivate) {\n const decimalCheck = checkDecimalIp(hostname, allowLocalhost, allowPrivate);\n if (decimalCheck) {\n return { safe: false, reason: decimalCheck };\n }\n }\n\n // Check octal IP (e.g., 0177.0.0.1 = 127.0.0.1)\n if (!allowLocalhost || !allowPrivate) {\n const octalCheck = checkOctalIp(hostname, allowLocalhost, allowPrivate);\n if (octalCheck) {\n return { safe: false, reason: octalCheck };\n }\n }\n\n // Check private/internal IPs\n if (!allowPrivate) {\n const privateCheck = checkPrivateIp(hostname);\n if (privateCheck) {\n return { safe: false, reason: privateCheck };\n }\n }\n\n return { safe: true };\n}\n\n/**\n * Convenience wrapper that returns true/false.\n *\n * @param url - The URL to check\n * @param options - Validation options\n * @returns true if the URL is safe to fetch\n */\nexport function isUrlSafe(url: string, options: ValidateUrlOptions = {}): boolean {\n return validateUrl(url, options).safe;\n}\n\n/**\n * Check if a hostname is a private/internal IP address.\n * Returns the reason string if private, or null if not.\n */\nfunction checkPrivateIp(hostname: string): string | null {\n // 10.0.0.0/8\n if (/^10\\.\\d{1,3}\\.\\d{1,3}\\.\\d{1,3}$/.test(hostname)) {\n return 'private address (10.0.0.0/8)';\n }\n\n // 172.16.0.0/12 (172.16.x.x - 172.31.x.x)\n const match172 = hostname.match(/^172\\.(\\d{1,3})\\.\\d{1,3}\\.\\d{1,3}$/);\n if (match172) {\n const second = parseInt(match172[1], 10);\n if (second >= 16 && second <= 31) {\n return 'private address (172.16.0.0/12)';\n }\n }\n\n // 192.168.0.0/16\n if (/^192\\.168\\.\\d{1,3}\\.\\d{1,3}$/.test(hostname)) {\n return 'private address (192.168.0.0/16)';\n }\n\n // 169.254.0.0/16 — link-local, includes cloud metadata endpoints\n // AWS: 169.254.169.254, GCP: metadata.google.internal, Azure: 169.254.169.254\n if (/^169\\.254\\.\\d{1,3}\\.\\d{1,3}$/.test(hostname)) {\n return 'link-local address (169.254.0.0/16)';\n }\n\n // 0.0.0.0/8 (current network)\n if (/^0\\.\\d{1,3}\\.\\d{1,3}\\.\\d{1,3}$/.test(hostname)) {\n return 'current network address (0.0.0.0/8)';\n }\n\n // Cloud metadata hostnames\n if (\n hostname === 'metadata.google.internal' ||\n hostname === 'metadata.internal' ||\n hostname === 'metadata.azure.internal'\n ) {\n return 'cloud metadata endpoint';\n }\n\n // IPv6 private ranges (bracket-wrapped in URLs)\n let ipv6 = hostname.replace(/^\\[|\\]$/g, '');\n // Strip zone ID (e.g., ::1%eth0 → ::1)\n const zoneIdx = ipv6.indexOf('%');\n if (zoneIdx !== -1) {\n ipv6 = ipv6.slice(0, zoneIdx);\n }\n if (\n ipv6 === '::1' ||\n ipv6 === '::' ||\n /^fc[0-9a-f]{2}:/i.test(ipv6) ||\n /^fd[0-9a-f]{2}:/i.test(ipv6) ||\n /^fe80:/i.test(ipv6) ||\n /^ff[0-9a-f]{2}:/i.test(ipv6) // IPv6 multicast (ff00::/8)\n ) {\n return 'private IPv6 address';\n }\n\n // IPv6-mapped IPv4 — dotted form (::ffff:127.0.0.1)\n const mappedDotted = ipv6.match(/^::ffff:(\\d{1,3}\\.\\d{1,3}\\.\\d{1,3}\\.\\d{1,3})$/i);\n if (mappedDotted) {\n const mappedIp = mappedDotted[1];\n if (/^127\\.\\d{1,3}\\.\\d{1,3}\\.\\d{1,3}$/.test(mappedIp)) {\n return 'IPv6-mapped loopback address';\n }\n const mappedCheck = checkPrivateIp(mappedIp);\n if (mappedCheck) {\n return `IPv6-mapped ${mappedCheck}`;\n }\n }\n\n // IPv6-mapped IPv4 — hex form (::ffff:7f00:1 = 127.0.0.1)\n // Node's URL parser normalizes ::ffff:a.b.c.d to ::ffff:XXYY:ZZWW\n const mappedHex = ipv6.match(/^::ffff:([0-9a-f]{1,4}):([0-9a-f]{1,4})$/i);\n if (mappedHex) {\n const hi = parseInt(mappedHex[1], 16);\n const lo = parseInt(mappedHex[2], 16);\n const a = (hi >> 8) & 0xFF;\n const b = hi & 0xFF;\n const c = (lo >> 8) & 0xFF;\n const d = lo & 0xFF;\n const dotted = `${a}.${b}.${c}.${d}`;\n if (a === 127) {\n return 'IPv6-mapped loopback address';\n }\n const hexCheck = checkPrivateIp(dotted);\n if (hexCheck) {\n return `IPv6-mapped ${hexCheck}`;\n }\n }\n\n return null;\n}\n\n/**\n * Parse a decimal integer as an IPv4 address and check if it's private/loopback.\n * e.g., 2130706433 = 127.0.0.1, 167772160 = 10.0.0.0\n */\nfunction checkDecimalIp(hostname: string, allowLocalhost: boolean, allowPrivate: boolean): string | null {\n // Must be a pure decimal integer\n if (!/^\\d+$/.test(hostname)) return null;\n\n const num = parseInt(hostname, 10);\n if (isNaN(num) || num < 0 || num > 0xFFFFFFFF) return null;\n\n const a = (num >>> 24) & 0xFF;\n const b = (num >>> 16) & 0xFF;\n const c = (num >>> 8) & 0xFF;\n const d = num & 0xFF;\n const dotted = `${a}.${b}.${c}.${d}`;\n\n // Check loopback\n if (!allowLocalhost && a === 127) {\n return `loopback address (decimal IP: ${dotted})`;\n }\n\n // Check private ranges\n if (!allowPrivate) {\n const privateCheck = checkPrivateIp(dotted);\n if (privateCheck) {\n return `${privateCheck} (decimal IP: ${dotted})`;\n }\n }\n\n return null;\n}\n\n/**\n * Parse octal-notation IPv4 address and check if it's private/loopback.\n * e.g., 0177.0.0.1 = 127.0.0.1, 0x7f.0.0.1 = 127.0.0.1\n */\nfunction checkOctalIp(hostname: string, allowLocalhost: boolean, allowPrivate: boolean): string | null {\n // Must look like a dotted quad where at least one octet has a leading zero or 0x prefix\n const parts = hostname.split('.');\n if (parts.length !== 4) return null;\n\n // Check if any part uses octal (leading 0) or hex (0x) notation\n const hasAlternateNotation = parts.some(p => /^0[0-7]+$/.test(p) || /^0x[0-9a-fA-F]+$/i.test(p));\n if (!hasAlternateNotation) return null;\n\n const octets: number[] = [];\n for (const part of parts) {\n let val: number;\n if (/^0x[0-9a-fA-F]+$/i.test(part)) {\n val = parseInt(part, 16);\n } else if (/^0[0-7]*$/.test(part)) {\n val = parseInt(part, 8);\n } else if (/^\\d+$/.test(part)) {\n val = parseInt(part, 10);\n } else {\n return null;\n }\n if (val < 0 || val > 255) return null;\n octets.push(val);\n }\n\n const dotted = octets.join('.');\n\n // Check loopback\n if (!allowLocalhost && octets[0] === 127) {\n return `loopback address (octal IP: ${dotted})`;\n }\n\n // Check private ranges\n if (!allowPrivate) {\n const privateCheck = checkPrivateIp(dotted);\n if (privateCheck) {\n return `${privateCheck} (octal IP: ${dotted})`;\n }\n }\n\n return null;\n}\n","/**\n * @module @arcis/node/validation/url-async\n *\n * Async SSRF guard that closes the DNS-rebinding TOCTOU gap left open\n * by the synchronous `validateUrl` (sdk-vectors.md #31, issue #50).\n *\n * The synchronous `validateUrl` only checks the *string form* of the\n * hostname. It catches obvious cases — `127.0.0.1`, `10.0.0.1`,\n * `169.254.169.254` — but a hostname like `evil.com` passes through\n * even when its DNS A-record points to `10.0.0.1`, because resolution\n * happens later inside `fetch`. An attacker controlling the\n * `evil.com` zone can also rebind the answer between Arcis's check\n * and the actual TCP connect, which is the classic DNS TOCTOU.\n *\n * Two layers of fix shipped here:\n *\n * 1. **`validateUrlAsync(url, options)`** — runs the existing sync\n * `validateUrl` first, then `dns.lookup(hostname, { all: true })`,\n * then re-runs the same private-range check on every resolved\n * address. Returns the pinned IP list so callers can reuse it for\n * the actual connection (closing the TOCTOU window).\n *\n * 2. **`pinnedDnsLookup(ip)`** — returns a Node `lookup` callback\n * that resolves any hostname to the pre-validated IP. Wire this\n * into `https.request({ lookup })` / `http.request({ lookup })`\n * so the connection uses the IP Arcis already validated, not\n * whatever DNS returns at connect time. Pure stdlib — no undici,\n * no extra dep.\n *\n * 3. **`safeFollowRedirect(prev, location, options)`** — when the\n * server replies 30x, run the same async guard against the new\n * Location URL. Resolves the absolute URL using the previous\n * response URL as base. Caller decides whether to follow.\n *\n * The function signatures keep `lookup` injectable so tests can\n * substitute a fake resolver without monkey-patching `node:dns`.\n *\n * ```ts\n * import https from 'node:https';\n * import { validateUrlAsync, pinnedDnsLookup } from '@arcis/node';\n *\n * const result = await validateUrlAsync(url);\n * if (!result.safe) throw new Error(result.reason);\n *\n * https.get(url, { lookup: pinnedDnsLookup(result.resolvedIp!) }, (res) => {\n * // The TCP connect now goes to result.resolvedIp regardless of\n * // what DNS would say at this exact moment.\n * });\n * ```\n */\n\nimport * as dns from 'node:dns';\nimport { validateUrl, type ValidateUrlOptions, type ValidateUrlResult } from './url';\n\n/**\n * Subset of `dns.lookup`'s `{ all: true }` callback signature. Kept\n * narrow so a test fake can satisfy it without depending on Node's\n * full `LookupAddress` type.\n */\nexport type LookupAddress = { address: string; family: number };\n\n/**\n * Function shape compatible with `dns.lookup(hostname, { all: true })`.\n * Returns a list of resolved addresses. Tests inject a fake.\n */\nexport type DnsLookup = (hostname: string) => Promise<LookupAddress[]>;\n\nconst defaultLookup: DnsLookup = (hostname) =>\n new Promise((resolve, reject) => {\n dns.lookup(hostname, { all: true }, (err, addresses) => {\n if (err) reject(err);\n else resolve(addresses);\n });\n });\n\nexport interface ValidateUrlAsyncOptions extends ValidateUrlOptions {\n /**\n * DNS lookup function. Defaults to a Promise wrapper around\n * `dns.lookup(hostname, { all: true })`. Tests inject a stub.\n */\n lookup?: DnsLookup;\n /**\n * If true, accept the first non-private IP and ignore the rest.\n * Default false: every resolved IP must pass the private-range\n * check. Hosts with mixed-public/private answers (round-robin DNS\n * with one internal record) still fail-closed.\n */\n acceptFirstPublic?: boolean;\n}\n\nexport interface ValidateUrlAsyncResult extends ValidateUrlResult {\n /**\n * Single pinned IP (the first public address if all checks passed,\n * or undefined when the string-only synchronous validator already\n * decided — e.g., the hostname *was* a literal IP). Use this with\n * `pinnedDnsLookup()` to wire the actual fetch.\n */\n resolvedIp?: string;\n /** Every IP returned by DNS, in resolver order. */\n resolvedIps?: string[];\n}\n\n/**\n * Reuses the existing private-range check from the sync validator.\n * We re-run `validateUrl` with the resolved IP swapped in as the\n * URL host. That way every existing rule (link-local, decimal-IP,\n * cloud-metadata hostname, IPv6-mapped, etc.) applies post-DNS too,\n * without forking the rule list.\n */\nfunction checkResolvedIp(ip: string, options: ValidateUrlOptions): ValidateUrlResult {\n // Build a synthetic URL that hands the IP to validateUrl. The\n // protocol is irrelevant for the private-range check; pick http to\n // avoid IPv6 bracket questions.\n const isIpv6 = ip.includes(':');\n const host = isIpv6 ? `[${ip}]` : ip;\n // Strip credentials + allowedHosts/blockedHosts because they apply\n // to the original hostname, not the resolved IP. We're only\n // re-running the IP-range checks here.\n const { allowedProtocols, allowLocalhost, allowPrivate } = options;\n return validateUrl(`http://${host}/`, {\n allowedProtocols,\n allowLocalhost,\n allowPrivate,\n });\n}\n\n/**\n * Async SSRF guard with DNS resolution. Runs the sync validator\n * first, then resolves DNS and validates every returned IP against\n * the same private-range rules. Returns a pinned IP for the caller\n * to reuse.\n *\n * Failure modes (any returns `{ safe: false, reason }`):\n * - Sync validator already rejects (string-pattern fail).\n * - DNS lookup throws (NXDOMAIN, network error). Reason carries the\n * underlying error message.\n * - DNS returns no addresses.\n * - Any resolved address fails the private-range check (default) or\n * *all* fail it when `acceptFirstPublic` is true.\n */\nexport async function validateUrlAsync(\n url: string,\n options: ValidateUrlAsyncOptions = {},\n): Promise<ValidateUrlAsyncResult> {\n const sync = validateUrl(url, options);\n if (!sync.safe) return sync;\n\n // If the hostname is a literal IP, the sync validator has already\n // checked it. Skip the DNS round-trip.\n let parsed: URL;\n try {\n parsed = new URL(url);\n } catch {\n return { safe: false, reason: 'invalid URL: failed to parse' };\n }\n const host = parsed.hostname.replace(/^\\[|\\]$/g, '');\n if (isLiteralIp(host)) return { safe: true };\n\n // Allowed-hosts allowlist takes precedence in the sync validator\n // and also bypasses the IP check here. The contract: if you\n // explicitly allowed the hostname, you accept whatever DNS returns.\n if (options.allowedHosts?.some((h) => host.toLowerCase() === h.toLowerCase())) {\n return { safe: true };\n }\n\n const lookup = options.lookup ?? defaultLookup;\n let addresses: LookupAddress[];\n try {\n addresses = await lookup(host);\n } catch (err) {\n const msg = err instanceof Error ? err.message : String(err);\n return { safe: false, reason: `DNS lookup failed: ${msg}` };\n }\n\n if (addresses.length === 0) {\n return { safe: false, reason: 'DNS returned no addresses' };\n }\n\n const ips = addresses.map((a) => a.address);\n const acceptFirstPublic = options.acceptFirstPublic === true;\n let firstPublic: string | undefined;\n for (const ip of ips) {\n const ipResult = checkResolvedIp(ip, options);\n if (ipResult.safe) {\n if (firstPublic === undefined) firstPublic = ip;\n } else if (!acceptFirstPublic) {\n return {\n safe: false,\n reason: `resolved IP ${ip} is unsafe: ${ipResult.reason}`,\n resolvedIps: ips,\n };\n }\n }\n\n if (firstPublic === undefined) {\n return {\n safe: false,\n reason: 'all resolved IPs are private/loopback',\n resolvedIps: ips,\n };\n }\n\n return { safe: true, resolvedIp: firstPublic, resolvedIps: ips };\n}\n\n/**\n * Build a `lookup` callback that pins the resolution to a single\n * pre-validated IP, regardless of what DNS would say at connect time.\n * Drop into `https.request({ lookup })` / `http.request({ lookup })`.\n *\n * Closes the TOCTOU window between `validateUrlAsync` and the actual\n * TCP connect. The pinned IP must be one that already passed the\n * async validator — wiring it without that check defeats the purpose.\n *\n * The returned function matches Node's `dns.lookup` callback shape\n * for the `{ all: false, family: 0 }` case (single address). The\n * default Node http/https stack uses that shape.\n */\nexport function pinnedDnsLookup(\n ip: string,\n): (\n hostname: string,\n options: { family?: number; hints?: number; verbatim?: boolean },\n callback: (err: NodeJS.ErrnoException | null, address: string, family: number) => void,\n) => void {\n if (typeof ip !== 'string' || ip.trim() === '') {\n throw new TypeError('pinnedDnsLookup: ip must be a non-empty string');\n }\n const family = ip.includes(':') ? 6 : 4;\n return (_hostname, _options, callback) => {\n callback(null, ip, family);\n };\n}\n\n/**\n * Validate a redirect target with the same TOCTOU-aware pipeline.\n *\n * `prev` is the URL of the response that returned the 30x; `location`\n * is the raw `Location:` header value (which may be relative). The\n * function resolves `location` against `prev` per RFC 3986 then runs\n * `validateUrlAsync` on the absolute result.\n *\n * Use this on every hop of a redirect chain. Without it, a server\n * that you trust today can redirect tomorrow's request to\n * `http://169.254.169.254/`.\n */\nexport async function safeFollowRedirect(\n prev: string,\n location: string,\n options: ValidateUrlAsyncOptions = {},\n): Promise<ValidateUrlAsyncResult> {\n if (typeof location !== 'string' || location.trim() === '') {\n return { safe: false, reason: 'redirect Location is empty' };\n }\n let absolute: URL;\n try {\n absolute = new URL(location, prev);\n } catch {\n return { safe: false, reason: 'invalid redirect URL' };\n }\n return validateUrlAsync(absolute.toString(), options);\n}\n\n/**\n * Detect whether a hostname is a literal IPv4/IPv6 (with or without\n * IPv6 brackets stripped). Mirrors what the sync validator already\n * checks via dotted-quad / decimal / octal regexes; we only need it\n * to know whether to skip the DNS round-trip.\n */\nfunction isLiteralIp(host: string): boolean {\n // IPv4 dotted quad\n if (/^\\d{1,3}\\.\\d{1,3}\\.\\d{1,3}\\.\\d{1,3}$/.test(host)) return true;\n // Decimal IP (single integer)\n if (/^\\d+$/.test(host)) return true;\n // Octal/hex IP forms\n if (/^0[0-7x]/.test(host) && /^[0-9a-fx.]+$/i.test(host) && host.includes('.')) return true;\n // IPv6: contains a colon and no slashes/spaces\n if (host.includes(':') && !/[/\\s]/.test(host)) return true;\n return false;\n}\n","/**\n * @module @arcis/node/validation/redirect\n * Open Redirect prevention\n *\n * Prevents attackers from using your app to redirect users to malicious sites\n * via manipulated query parameters like ?returnUrl=http://evil.com\n *\n * @example\n * import { validateRedirect, isRedirectSafe } from '@arcis/node';\n *\n * // Block open redirects\n * validateRedirect('http://evil.com') // { safe: false, reason: 'absolute URL not in allowed hosts' }\n * validateRedirect('//evil.com') // { safe: false, reason: 'protocol-relative URL not in allowed hosts' }\n * validateRedirect('javascript:alert(1)') // { safe: false, reason: 'dangerous protocol: javascript:' }\n *\n * // Allow safe redirects\n * validateRedirect('/dashboard') // { safe: true }\n * validateRedirect('/users?page=2') // { safe: true }\n * validateRedirect('https://myapp.com/home', { allowedHosts: ['myapp.com'] }) // { safe: true }\n */\n\n/** Options for redirect validation */\nexport interface ValidateRedirectOptions {\n /** Hostnames that are allowed for absolute URL redirects */\n allowedHosts?: string[];\n /** Allow protocol-relative URLs (//example.com). Default: false */\n allowProtocolRelative?: boolean;\n /** Allowed protocols for absolute URLs. Default: ['http:', 'https:'] */\n allowedProtocols?: string[];\n}\n\n/** Result of redirect validation */\nexport interface ValidateRedirectResult {\n /** Whether the redirect URL is safe */\n safe: boolean;\n /** Reason the redirect was blocked (only set when safe=false) */\n reason?: string;\n}\n\n/** Protocols that can execute code or exfiltrate data */\nconst DANGEROUS_PROTOCOLS = /^(javascript|data|vbscript|blob):/i;\n\n/** Characters used to disguise URLs (tabs, newlines inside scheme) */\nconst CONTROL_CHARS = /[\\t\\n\\r]/g;\n\n/**\n * Validate a redirect URL to prevent open redirect attacks.\n *\n * Safe redirects:\n * - Relative paths: /dashboard, /users?page=2, ../settings\n * - Absolute URLs to allowed hosts (when configured)\n *\n * Blocked redirects:\n * - Absolute URLs to unknown hosts\n * - Protocol-relative URLs (//evil.com)\n * - javascript:, data:, vbscript:, blob: protocols\n * - Backslash-prefixed paths (\\\\evil.com — browser treats as //)\n * - URLs with control characters that could disguise the target\n *\n * @param url - The redirect target URL to validate\n * @param options - Validation options\n * @returns Validation result with safe flag and optional reason\n */\nexport function validateRedirect(\n url: string,\n options: ValidateRedirectOptions = {},\n): ValidateRedirectResult {\n const {\n allowedHosts = [],\n allowProtocolRelative = false,\n allowedProtocols = ['http:', 'https:'],\n } = options;\n\n if (typeof url !== 'string' || url.trim() === '') {\n return { safe: false, reason: 'invalid redirect: empty or not a string' };\n }\n\n // Strip control characters that could disguise the URL\n const cleaned = url.replace(CONTROL_CHARS, '');\n\n // Block dangerous protocols (javascript:, data:, etc.)\n const proto = cleaned.match(DANGEROUS_PROTOCOLS);\n if (proto) {\n return { safe: false, reason: `dangerous protocol: ${proto[0]}` };\n }\n\n // Block backslash-prefixed paths — browsers treat \\ as / in URLs\n // so \\evil.com or \\/evil.com could redirect to //evil.com\n if (cleaned.startsWith('\\\\')) {\n return { safe: false, reason: 'backslash-prefixed URL (browser treats as protocol-relative)' };\n }\n\n // Check protocol-relative URLs (//evil.com)\n if (cleaned.startsWith('//')) {\n if (!allowProtocolRelative) {\n // Still check allowedHosts\n const host = extractHost(cleaned);\n if (host && allowedHosts.some(h => host === h.toLowerCase())) {\n return { safe: true };\n }\n return { safe: false, reason: 'protocol-relative URL not in allowed hosts' };\n }\n const host = extractHost(cleaned);\n if (host && allowedHosts.length > 0 && !allowedHosts.some(h => host === h.toLowerCase())) {\n return { safe: false, reason: 'protocol-relative URL not in allowed hosts' };\n }\n return { safe: true };\n }\n\n // Check if it's an absolute URL (has scheme)\n let parsed: URL;\n try {\n parsed = new URL(cleaned);\n } catch {\n // Not a valid absolute URL — treat as relative path (safe)\n return { safe: true };\n }\n\n // If we got here, it parsed as an absolute URL\n // Check protocol\n if (!allowedProtocols.includes(parsed.protocol)) {\n return { safe: false, reason: `disallowed protocol: ${parsed.protocol}` };\n }\n\n // Check if host is in allowed list. Match against host:port form when\n // a non-default port is present, falling back to hostname only when\n // the URL uses a default port. parsed.port is \"\" for default ports\n // (80 for http, 443 for https), so hostWithPort equals hostname in\n // those cases. Non-default ports must be explicitly listed: a bare\n // 'myapp.com' entry does NOT permit redirects to 'myapp.com:9999'.\n const hostname = parsed.hostname.toLowerCase();\n const hostWithPort = parsed.port ? `${hostname}:${parsed.port}` : hostname;\n if (allowedHosts.length === 0) {\n return { safe: false, reason: 'absolute URL not in allowed hosts' };\n }\n\n if (!allowedHosts.some(h => h.toLowerCase() === hostWithPort)) {\n return { safe: false, reason: `host not allowed: ${hostWithPort}` };\n }\n\n return { safe: true };\n}\n\n/**\n * Convenience wrapper that returns true/false.\n *\n * @param url - The redirect URL to check\n * @param options - Validation options\n * @returns true if the redirect is safe\n */\nexport function isRedirectSafe(url: string, options: ValidateRedirectOptions = {}): boolean {\n return validateRedirect(url, options).safe;\n}\n\n/**\n * Extract host (with optional port) from a protocol-relative URL.\n * Returns hostname for default ports, \"hostname:port\" for non-default.\n * Optional userinfo (user:pass@) is stripped.\n */\nfunction extractHost(url: string): string | null {\n // //user:pass@hostname/path -> authority = \"user:pass@hostname\"\n // //hostname:port/path -> authority = \"hostname:port\"\n const match = url.match(/^\\/\\/([^/?#]+)/);\n if (!match) return null;\n // Strip userinfo if present\n const authority = match[1].includes('@')\n ? match[1].slice(match[1].indexOf('@') + 1)\n : match[1];\n return authority.toLowerCase();\n}\n","/**\n * @module @arcis/node/validation/email\n * Advanced email validation with disposable detection and typo suggestions.\n *\n * Three levels of validation:\n * 1. Syntax — RFC-compliant format checking\n * 2. Domain intelligence — disposable/free provider detection, typo correction\n * 3. MX verification — DNS MX record lookup (async, optional)\n *\n * @example\n * const result = validateEmail('user@tempmail.com');\n * // { valid: false, reason: 'disposable' }\n *\n * const result = validateEmail('user@gmial.com');\n * // { valid: true, reason: 'typo', suggestion: 'user@gmail.com' }\n */\n\nimport { promises as dns } from 'dns';\n\nexport interface EmailValidationOptions {\n /** Check for disposable email providers. Default: true */\n checkDisposable?: boolean;\n /** Suggest corrections for typos. Default: true */\n suggestTypoFix?: boolean;\n /** Verify MX records via DNS. Default: false */\n checkMx?: boolean;\n /** Additional blocked domains */\n blockedDomains?: string[];\n /** Additional allowed domains (bypasses disposable check) */\n allowedDomains?: string[];\n}\n\nexport interface EmailValidationResult {\n /** Whether the email is valid */\n valid: boolean;\n /** Reason for the result */\n reason: 'valid' | 'invalid_syntax' | 'disposable' | 'no_mx' | 'blocked' | 'typo';\n /** Suggested correction if a typo was detected */\n suggestion: string | null;\n /** Whether the domain is a free email provider */\n isFree: boolean;\n /** Whether the domain is a disposable email provider */\n isDisposable: boolean;\n /** The normalized email address */\n normalized: string;\n}\n\n// RFC 5321: local part max 64, domain max 255, total max 254\nconst MAX_EMAIL_LENGTH = 254;\nconst MAX_LOCAL_LENGTH = 64;\nconst MAX_DOMAIN_LENGTH = 255;\n\n/**\n * Strict email syntax regex.\n * - No consecutive dots in local part\n * - No leading/trailing dots in local part\n * - Domain must have at least one dot\n * - No spaces anywhere\n */\nconst EMAIL_SYNTAX = /^[a-zA-Z0-9.!#$%&'*+/=?^_`{|}~-]+@[a-zA-Z0-9](?:[a-zA-Z0-9-]{0,61}[a-zA-Z0-9])?(?:\\.[a-zA-Z0-9](?:[a-zA-Z0-9-]{0,61}[a-zA-Z0-9])?)*\\.[a-zA-Z]{2,}$/;\n\n/** Common free email providers */\nconst FREE_PROVIDERS = new Set([\n 'gmail.com', 'yahoo.com', 'hotmail.com', 'outlook.com', 'aol.com',\n 'protonmail.com', 'proton.me', 'icloud.com', 'mail.com', 'zoho.com',\n 'yandex.com', 'gmx.com', 'gmx.net', 'live.com', 'msn.com',\n 'me.com', 'mac.com', 'fastmail.com', 'tutanota.com', 'hey.com',\n]);\n\n/** Common disposable email domains */\nconst DISPOSABLE_DOMAINS = new Set([\n // Popular disposable services\n 'guerrillamail.com', 'guerrillamail.net', 'guerrillamail.org',\n 'tempmail.com', 'temp-mail.org', 'temp-mail.io',\n 'throwaway.email', 'throwaway.com',\n 'mailinator.com', 'mailinator.net',\n 'yopmail.com', 'yopmail.fr', 'yopmail.net',\n 'sharklasers.com', 'grr.la', 'guerrillamail.info',\n 'guerrillamail.biz', 'guerrillamail.de',\n 'trashmail.com', 'trashmail.me', 'trashmail.net',\n 'dispostable.com', 'maildrop.cc',\n 'mailnesia.com', 'tempail.com',\n 'mohmal.com', 'getnada.com',\n 'emailondeck.com', 'discard.email',\n 'fakeinbox.com', 'mailcatch.com',\n 'mintemail.com', 'tempr.email',\n 'tempinbox.com', 'burnermail.io',\n 'mailsac.com', 'harakirimail.com',\n 'tempmailo.com', 'emailfake.com',\n 'crazymailing.com', 'armyspy.com',\n 'dayrep.com', 'einrot.com',\n 'fleckens.hu', 'gustr.com',\n 'jourrapide.com', 'rhyta.com',\n 'superrito.com', 'teleworm.us',\n '10minutemail.com', '10minutemail.net',\n 'minutemail.com', 'tempsky.com',\n 'spamgourmet.com', 'mytrashmail.com',\n 'mailexpire.com', 'safetymail.info',\n 'filzmail.com', 'trashymail.com',\n 'sharkmail.com', 'jetable.org',\n 'nospam.ze.tc', 'trash-me.com',\n 'dodgit.com', 'mailmoat.com',\n 'spamfree24.org', 'incognitomail.org',\n 'tempomail.fr', 'ephemail.net',\n 'hidemail.de', 'spaml.de',\n 'uggsrock.com', 'binkmail.com',\n 'suremail.info', 'bugmenot.com',\n]);\n\n/** Common typos and their corrections */\nconst DOMAIN_TYPOS: Record<string, string> = {\n 'gmial.com': 'gmail.com',\n 'gmaill.com': 'gmail.com',\n 'gmai.com': 'gmail.com',\n 'gamil.com': 'gmail.com',\n 'gnail.com': 'gmail.com',\n 'gmal.com': 'gmail.com',\n 'gmil.com': 'gmail.com',\n 'gmail.co': 'gmail.com',\n 'gmail.cm': 'gmail.com',\n 'gmail.om': 'gmail.com',\n 'gmail.con': 'gmail.com',\n 'gmail.cim': 'gmail.com',\n 'gmail.comm': 'gmail.com',\n 'yahooo.com': 'yahoo.com',\n 'yaho.com': 'yahoo.com',\n 'yahoo.co': 'yahoo.com',\n 'yahoo.cm': 'yahoo.com',\n 'yahoo.con': 'yahoo.com',\n 'yahho.com': 'yahoo.com',\n 'hotmial.com': 'hotmail.com',\n 'hotmal.com': 'hotmail.com',\n 'hotmai.com': 'hotmail.com',\n 'hotmil.com': 'hotmail.com',\n 'hotmail.co': 'hotmail.com',\n 'hotmail.cm': 'hotmail.com',\n 'hotmail.con': 'hotmail.com',\n 'outlok.com': 'outlook.com',\n 'outloo.com': 'outlook.com',\n 'outlook.co': 'outlook.com',\n 'outlook.cm': 'outlook.com',\n 'protonmal.com': 'protonmail.com',\n 'protonmail.co': 'protonmail.com',\n 'icloud.co': 'icloud.com',\n 'icloud.cm': 'icloud.com',\n 'icoud.com': 'icloud.com',\n};\n\nfunction invalidResult(reason: EmailValidationResult['reason'], email: string): EmailValidationResult {\n return {\n valid: false,\n reason,\n suggestion: null,\n isFree: false,\n isDisposable: false,\n normalized: email,\n };\n}\n\n/**\n * Validate an email address with syntax checking, disposable detection,\n * and typo suggestions.\n *\n * @param email - Email address to validate\n * @param options - Validation options\n * @returns Validation result\n *\n * @example\n * validateEmail('user@gmail.com')\n * // { valid: true, reason: 'valid', isFree: true }\n *\n * validateEmail('user@tempmail.com')\n * // { valid: false, reason: 'disposable' }\n *\n * validateEmail('user@gmial.com')\n * // { valid: true, reason: 'typo', suggestion: 'user@gmail.com' }\n */\nexport function validateEmail(\n email: string,\n options: EmailValidationOptions = {}\n): EmailValidationResult {\n const {\n checkDisposable = true,\n suggestTypoFix = true,\n blockedDomains = [],\n allowedDomains = [],\n } = options;\n\n // Normalize\n const normalized = email.trim().toLowerCase();\n\n // Basic checks\n if (!normalized || normalized.length > MAX_EMAIL_LENGTH) {\n return invalidResult('invalid_syntax', normalized);\n }\n\n const atIndex = normalized.lastIndexOf('@');\n if (atIndex === -1) {\n return invalidResult('invalid_syntax', normalized);\n }\n\n const localPart = normalized.slice(0, atIndex);\n const domain = normalized.slice(atIndex + 1);\n\n // Length checks\n if (localPart.length === 0 || localPart.length > MAX_LOCAL_LENGTH) {\n return invalidResult('invalid_syntax', normalized);\n }\n if (domain.length === 0 || domain.length > MAX_DOMAIN_LENGTH) {\n return invalidResult('invalid_syntax', normalized);\n }\n\n // Consecutive dots in local part\n if (localPart.includes('..')) {\n return invalidResult('invalid_syntax', normalized);\n }\n\n // Leading/trailing dots in local part\n if (localPart.startsWith('.') || localPart.endsWith('.')) {\n return invalidResult('invalid_syntax', normalized);\n }\n\n // Full regex validation\n if (!EMAIL_SYNTAX.test(normalized)) {\n return invalidResult('invalid_syntax', normalized);\n }\n\n // Check if domain is explicitly allowed (bypass other checks)\n const allowedSet = new Set(allowedDomains.map(d => d.toLowerCase()));\n if (allowedSet.has(domain)) {\n return {\n valid: true,\n reason: 'valid',\n suggestion: null,\n isFree: FREE_PROVIDERS.has(domain),\n isDisposable: false,\n normalized,\n };\n }\n\n // Check blocked domains\n const blockedSet = new Set(blockedDomains.map(d => d.toLowerCase()));\n if (blockedSet.has(domain)) {\n return invalidResult('blocked', normalized);\n }\n\n // Check disposable\n const isDisposable = DISPOSABLE_DOMAINS.has(domain);\n if (checkDisposable && isDisposable) {\n return {\n valid: false,\n reason: 'disposable',\n suggestion: null,\n isFree: false,\n isDisposable: true,\n normalized,\n };\n }\n\n // Check typos\n const isFree = FREE_PROVIDERS.has(domain);\n if (suggestTypoFix && DOMAIN_TYPOS[domain]) {\n const corrected = `${localPart}@${DOMAIN_TYPOS[domain]}`;\n return {\n valid: true,\n reason: 'typo',\n suggestion: corrected,\n isFree: FREE_PROVIDERS.has(DOMAIN_TYPOS[domain]),\n isDisposable: false,\n normalized,\n };\n }\n\n return {\n valid: true,\n reason: 'valid',\n suggestion: null,\n isFree,\n isDisposable,\n normalized,\n };\n}\n\n/**\n * Verify that the email domain has MX records (can receive email).\n *\n * This performs a DNS lookup and requires network access.\n * Use for registration flows where you need high confidence.\n *\n * @param email - Email address to verify\n * @returns True if the domain has MX records\n *\n * @example\n * if (await verifyEmailMx('user@example.com')) {\n * // Domain can receive email\n * }\n */\nexport async function verifyEmailMx(email: string): Promise<boolean> {\n if (!isValidEmailSyntax(email)) return false;\n\n const atIndex = email.lastIndexOf('@');\n const domain = email.slice(atIndex + 1).trim().toLowerCase();\n if (!domain) return false;\n\n try {\n const records = await dns.resolveMx(domain);\n return records.length > 0;\n } catch {\n return false;\n }\n}\n\n/**\n * Quick check if an email address has valid syntax.\n * Faster than validateEmail() — just syntax, no domain intelligence.\n */\nexport function isValidEmailSyntax(email: string): boolean {\n const normalized = email.trim().toLowerCase();\n if (!normalized || normalized.length > MAX_EMAIL_LENGTH) return false;\n\n const atIndex = normalized.lastIndexOf('@');\n if (atIndex === -1) return false;\n\n const localPart = normalized.slice(0, atIndex);\n if (localPart.includes('..') || localPart.startsWith('.') || localPart.endsWith('.')) return false;\n\n return EMAIL_SYNTAX.test(normalized);\n}\n","/**\n * @module @arcis/node/logging/redactor\n * Safe logging with PII/secret redaction\n */\n\nimport { REDACTION, INPUT } from '../core/constants';\nimport type { LogOptions, SafeLogger } from '../core/types';\n\nconst LOG_LEVELS: Record<string, number> = {\n debug: 0,\n info: 1,\n warn: 2,\n error: 3,\n silent: 4,\n};\n\n/**\n * Create a safe logger that redacts sensitive data and prevents log injection.\n * \n * @param options - Logger configuration\n * @returns SafeLogger instance\n * \n * @example\n * const logger = createSafeLogger();\n * logger.info('User login', { email: 'user@test.com', password: 'secret' });\n * // Logs: { \"email\": \"user@test.com\", \"password\": \"[REDACTED]\" }\n * \n * @example\n * // With custom redact keys\n * const logger = createSafeLogger({ redactKeys: ['customToken', 'internalId'] });\n */\nexport function createSafeLogger(options: LogOptions = {}): SafeLogger {\n const {\n redactKeys = [],\n maxLength = REDACTION.DEFAULT_MAX_LENGTH,\n redactPatterns = [],\n level: minLevel = 'debug',\n } = options;\n\n const minLevelNum = LOG_LEVELS[minLevel] ?? 0;\n\n // Combine default and custom keys (lowercase for case-insensitive matching)\n const allRedactKeys = new Set([\n ...Array.from(REDACTION.SENSITIVE_KEYS),\n ...redactKeys.map(k => k.toLowerCase()),\n ]);\n\n /**\n * Redact sensitive data from an object recursively.\n */\n function redact(obj: unknown, depth = 0): unknown {\n if (depth > INPUT.MAX_RECURSION_DEPTH) return REDACTION.MAX_DEPTH;\n if (obj === null || obj === undefined) return obj;\n\n if (typeof obj === 'string') {\n return redactString(obj, maxLength, redactPatterns);\n }\n\n if (typeof obj !== 'object') return obj;\n\n if (Array.isArray(obj)) {\n return obj.map(item => redact(item, depth + 1));\n }\n\n const result: Record<string, unknown> = {};\n for (const [key, value] of Object.entries(obj as Record<string, unknown>)) {\n if (allRedactKeys.has(key.toLowerCase())) {\n result[key] = REDACTION.REPLACEMENT;\n } else {\n result[key] = redact(value, depth + 1);\n }\n }\n return result;\n }\n\n /**\n * Log a message at the specified level.\n */\n function log(level: string, message: string, data?: unknown): void {\n // Early exit: skip all work if message level is below minimum\n const levelNum = LOG_LEVELS[level] ?? 0;\n if (levelNum < minLevelNum) return;\n\n const entry: Record<string, unknown> = {\n timestamp: new Date().toISOString(),\n level,\n message: redactString(message, maxLength, redactPatterns),\n };\n\n if (data !== undefined) {\n entry.data = redact(data);\n }\n\n // eslint-disable-next-line no-console\n console.log(JSON.stringify(entry));\n }\n\n return {\n log,\n info: (msg: string, data?: unknown) => log('info', msg, data),\n warn: (msg: string, data?: unknown) => log('warn', msg, data),\n error: (msg: string, data?: unknown) => log('error', msg, data),\n debug: (msg: string, data?: unknown) => log('debug', msg, data),\n };\n}\n\n/**\n * Redact a string value.\n * Removes newlines (log injection prevention), applies patterns, and truncates.\n */\nfunction redactString(str: string, maxLength: number, patterns: RegExp[]): string {\n // Remove newlines/tabs (log injection prevention) and genuine control characters.\n // Only strip C0/C1 control chars and null bytes — preserve all printable Unicode\n // (CJK, Cyrillic, Arabic, etc.) so multilingual content isn't silently lost.\n let safe = str\n .replace(/[\\r\\n\\t]/g, ' ')\n .replace(/[\\x00-\\x08\\x0B\\x0C\\x0E-\\x1F\\x7F\\x80-\\x9F]/g, '');\n\n // Apply custom redaction patterns\n for (const pattern of patterns) {\n safe = safe.replace(pattern, REDACTION.REPLACEMENT);\n }\n\n // Truncate if too long\n if (safe.length > maxLength) {\n safe = safe.substring(0, maxLength) + `...${REDACTION.TRUNCATED}`;\n }\n\n return safe;\n}\n\n/**\n * Create a redactor function for custom use.\n * \n * @param sensitiveKeys - Keys to redact\n * @returns Redactor function\n */\nexport function createRedactor(sensitiveKeys: string[] = []): (obj: unknown) => unknown {\n const allKeys = new Set([\n ...Array.from(REDACTION.SENSITIVE_KEYS),\n ...sensitiveKeys.map(k => k.toLowerCase()),\n ]);\n\n function redact(obj: unknown, depth = 0): unknown {\n if (depth > INPUT.MAX_RECURSION_DEPTH) return REDACTION.MAX_DEPTH;\n if (obj === null || obj === undefined) return obj;\n if (typeof obj !== 'object') return obj;\n\n if (Array.isArray(obj)) {\n return obj.map(item => redact(item, depth + 1));\n }\n\n const result: Record<string, unknown> = {};\n for (const [key, value] of Object.entries(obj as Record<string, unknown>)) {\n if (allKeys.has(key.toLowerCase())) {\n result[key] = REDACTION.REPLACEMENT;\n } else {\n result[key] = redact(value, depth + 1);\n }\n }\n return result;\n }\n\n return redact;\n}\n\n/**\n * Alias for createSafeLogger\n * @see createSafeLogger\n */\nexport const safeLog = createSafeLogger;\n","import type { TelemetryEvent, TelemetryOptions } from './types';\n\nconst DEFAULT_BATCH_SIZE = 50;\nconst MAX_BATCH_SIZE = 500; // matches server Zod schema upper bound\nconst DEFAULT_FLUSH_INTERVAL_MS = 5000;\nconst MIN_FLUSH_INTERVAL_MS = 500;\nconst FLUSH_TIMEOUT_MS = 10_000;\nconst DEFAULT_MAX_QUEUE_SIZE = 10_000;\n\ntype Listener = (err: Error) => void;\ntype OverflowListener = (droppedCount: number) => void;\n\n/**\n * In-memory batching client that ships `TelemetryEvent` objects to an\n * Arcis dashboard server.\n *\n * Design rules (spec/API_SPEC.md §9):\n * 1. `record()` is synchronous and never throws — safe to call from hot paths.\n * 2. Flushes trigger on batchSize OR flushIntervalMs, whichever comes first.\n * 3. Network errors are fail-open: they call `onError` (if provided) and\n * drop the batch. No retry, no disk persistence, no backpressure.\n * 4. `close()` attempts one final flush; safe to call multiple times.\n * 5. Interval timer uses `unref()` so it never holds the process open.\n */\nexport class TelemetryClient {\n private queue: TelemetryEvent[] = [];\n private readonly endpoint: string;\n private readonly apiKey: string | undefined;\n private readonly workspaceId: string | undefined;\n private readonly batchSize: number;\n private readonly flushIntervalMs: number;\n private readonly maxQueueSize: number;\n private readonly onError: Listener;\n private readonly onQueueOverflow: OverflowListener;\n private timer: ReturnType<typeof setInterval> | undefined;\n private flushing = false;\n private closed = false;\n private signalHandler: (() => void) | undefined;\n // Counts events dropped since the last successful flush. Resets to 0\n // each flush so onQueueOverflow callbacks see \"drops in this window\"\n // rather than a monotonic lifetime counter.\n private droppedSinceLastFlush = 0;\n\n constructor(options: TelemetryOptions) {\n if (!options.endpoint || typeof options.endpoint !== 'string') {\n throw new TypeError('TelemetryClient: `endpoint` is required');\n }\n\n this.endpoint = options.endpoint;\n this.apiKey = options.apiKey;\n this.workspaceId = options.workspaceId;\n this.batchSize = clamp(\n options.batchSize ?? DEFAULT_BATCH_SIZE,\n 1,\n MAX_BATCH_SIZE,\n );\n this.flushIntervalMs = Math.max(\n options.flushIntervalMs ?? DEFAULT_FLUSH_INTERVAL_MS,\n MIN_FLUSH_INTERVAL_MS,\n );\n // Cap the in-memory queue to bound memory under sustained dashboard\n // outage. Drop-oldest semantics preserve the most recent events,\n // which are usually the most relevant for incident triage.\n this.maxQueueSize = Math.max(\n options.maxQueueSize ?? DEFAULT_MAX_QUEUE_SIZE,\n this.batchSize,\n );\n this.onError = options.onError ?? (() => {\n // default: swallow silently (fail-open)\n });\n this.onQueueOverflow = options.onQueueOverflow ?? (() => {\n // default: silent — operators can opt in to logging\n });\n\n this.startTimer();\n }\n\n /**\n * Enqueue an event. Fast, synchronous, cannot throw.\n * Triggers a flush if the queue has reached `batchSize`.\n */\n record(event: TelemetryEvent): void {\n if (this.closed) return;\n this.queue.push(event);\n\n // Cap the queue at maxQueueSize. Drop oldest events (FIFO) so we keep\n // the freshest signal during a sustained outage. Without this cap, a\n // 24h dashboard outage at moderate traffic OOMs the worker.\n if (this.queue.length > this.maxQueueSize) {\n const drop = this.queue.length - this.maxQueueSize;\n this.queue.splice(0, drop);\n this.droppedSinceLastFlush += drop;\n try {\n this.onQueueOverflow(this.droppedSinceLastFlush);\n } catch {\n // overflow callback errors must not break record()\n }\n }\n\n if (this.queue.length >= this.batchSize) {\n // fire and forget\n void this.flush();\n }\n }\n\n /**\n * Manually flush the queue. Pulls up to `batchSize` events into a batch and\n * POSTs them. Returns a resolved promise on success OR on handled failure.\n * Never throws.\n */\n async flush(): Promise<void> {\n if (this.flushing) return;\n if (this.queue.length === 0) return;\n\n this.flushing = true;\n try {\n const batch = this.queue.splice(0, this.batchSize);\n await this.send(batch);\n // Successful flush — reset overflow counter so subsequent drops\n // start a fresh window. A connected dashboard \"clears\" the alert.\n this.droppedSinceLastFlush = 0;\n } catch (err) {\n this.safeNotify(err);\n } finally {\n this.flushing = false;\n }\n\n // Drain anything that arrived while we were flushing.\n if (!this.closed && this.queue.length > 0) {\n void this.flush();\n }\n }\n\n /**\n * Shut down: stop the interval timer and attempt one final flush.\n * Safe to call multiple times.\n */\n async close(): Promise<void> {\n if (this.closed) return;\n this.closed = true;\n\n if (this.timer !== undefined) {\n clearInterval(this.timer);\n this.timer = undefined;\n }\n\n if (this.signalHandler !== undefined) {\n process.off('SIGTERM', this.signalHandler);\n process.off('SIGINT', this.signalHandler);\n this.signalHandler = undefined;\n }\n\n // final best-effort flush\n try {\n await this.flush();\n } catch {\n // fail-open on shutdown\n }\n }\n\n /**\n * Register `SIGTERM` / `SIGINT` handlers that call `close()` to drain\n * the queue on graceful shutdown. Opt-in — libraries should not silently\n * attach global signal handlers. Safe to call multiple times.\n */\n installShutdownHooks(): void {\n if (this.signalHandler !== undefined || this.closed) return;\n const handler = (): void => {\n void this.close();\n };\n this.signalHandler = handler;\n process.once('SIGTERM', handler);\n process.once('SIGINT', handler);\n }\n\n /** Count of events currently waiting to be sent. Useful for tests. */\n get pendingCount(): number {\n return this.queue.length;\n }\n\n // ── internals ─────────────────────────────────────────────────────────\n\n private async send(batch: TelemetryEvent[]): Promise<void> {\n const headers: Record<string, string> = {\n 'content-type': 'application/json',\n };\n if (this.apiKey) headers['authorization'] = `Bearer ${this.apiKey}`;\n if (this.workspaceId) headers['x-workspace-id'] = this.workspaceId;\n\n const controller = new AbortController();\n const abortTimer = setTimeout(() => controller.abort(), FLUSH_TIMEOUT_MS);\n\n try {\n const res = await fetch(this.endpoint, {\n method: 'POST',\n headers,\n body: JSON.stringify({ events: batch }),\n signal: controller.signal,\n });\n\n if (!res.ok) {\n const text = await safeReadBody(res);\n throw new TelemetryHttpError(res.status, text);\n }\n } finally {\n clearTimeout(abortTimer);\n }\n }\n\n private startTimer(): void {\n this.timer = setInterval(() => {\n void this.flush();\n }, this.flushIntervalMs);\n\n // node-only: don't block process exit\n (this.timer as { unref?: () => void }).unref?.();\n }\n\n private safeNotify(err: unknown): void {\n try {\n this.onError(err instanceof Error ? err : new Error(String(err)));\n } catch {\n // user-provided hook must never bubble up\n }\n }\n}\n\nexport class TelemetryHttpError extends Error {\n constructor(\n public readonly status: number,\n public readonly responseBody: string,\n ) {\n super(`Telemetry ingest returned HTTP ${status}`);\n this.name = 'TelemetryHttpError';\n }\n}\n\nfunction clamp(value: number, min: number, max: number): number {\n if (!Number.isFinite(value)) return min;\n return Math.max(min, Math.min(max, Math.trunc(value)));\n}\n\nasync function safeReadBody(res: Response): Promise<string> {\n try {\n const text = await res.text();\n return text.slice(0, 500);\n } catch {\n return '';\n }\n}\n","/**\n * @module @arcis/node/middleware/main\n * Main arcis() middleware factory\n */\n\nimport type { Request, RequestHandler, Response, NextFunction } from 'express';\nimport type {\n ArcisOptions,\n ArcisFunction,\n ArcisMiddlewareStack,\n HeaderOptions,\n RateLimitOptions,\n SanitizeEvent,\n SanitizeOptions,\n} from '../core/types';\nimport { createHeaders } from './headers';\nimport { createRateLimiter } from './rate-limit';\nimport { createErrorHandler } from './error-handler';\nimport { createTelemetryEmitter, tapSanitizerThreats } from './telemetry';\nimport { createSanitizer, scanThreats } from '../sanitizers';\nimport { validate } from '../validation';\nimport { createSafeLogger } from '../logging';\nimport { TelemetryClient } from '../telemetry/client';\nimport type { TelemetryOptions } from '../telemetry/types';\n\n/**\n * Build TelemetryOptions from `ARCIS_*` environment variables when the user\n * didn't pass `telemetry` in `arcis({...})`. Returns undefined if `ARCIS_ENDPOINT`\n * isn't set — preserving zero-overhead opt-in.\n *\n * Recognized env vars:\n * - `ARCIS_ENDPOINT` (required to activate)\n * - `ARCIS_WORKSPACE_ID` (optional; sent as x-workspace-id)\n * - `ARCIS_KEY` (optional; sent as Authorization: Bearer <key>)\n * - `ARCIS_BATCH_SIZE` (optional integer; default 50)\n * - `ARCIS_FLUSH_INTERVAL_MS` (optional integer; default 5000)\n *\n * Explicit `options.telemetry` always wins over env. This preserves the\n * existing opt-in contract and lets callers override env in tests.\n */\nfunction buildTelemetryFromEnv(): TelemetryOptions | undefined {\n const env = typeof process !== 'undefined' ? process.env : undefined;\n const endpoint = env?.ARCIS_ENDPOINT;\n if (!endpoint) return undefined;\n const opts: TelemetryOptions = { endpoint };\n if (env?.ARCIS_WORKSPACE_ID) opts.workspaceId = env.ARCIS_WORKSPACE_ID;\n if (env?.ARCIS_KEY) opts.apiKey = env.ARCIS_KEY;\n const batch = env?.ARCIS_BATCH_SIZE ? parseInt(env.ARCIS_BATCH_SIZE, 10) : NaN;\n if (!Number.isNaN(batch)) opts.batchSize = batch;\n const flush = env?.ARCIS_FLUSH_INTERVAL_MS ? parseInt(env.ARCIS_FLUSH_INTERVAL_MS, 10) : NaN;\n if (!Number.isNaN(flush)) opts.flushIntervalMs = flush;\n return opts;\n}\n\n/**\n * Create Arcis middleware with all protections enabled.\n * \n * @param options - Configuration options\n * @returns Array of Express middleware\n * \n * @example\n * // Full protection (recommended)\n * app.use(arcis());\n * \n * @example\n * // Custom configuration\n * app.use(arcis({\n * rateLimit: { max: 50 },\n * headers: { frameOptions: 'SAMEORIGIN' }\n * }));\n * \n * @example\n * // Disable specific features\n * app.use(arcis({\n * rateLimit: false,\n * sanitize: { sql: false }\n * }));\n * \n * @example\n * // Cleanup on shutdown\n * const middleware = arcis();\n * app.use(middleware);\n * process.on('SIGTERM', () => middleware.close());\n */\n/**\n * Issue #47 — observer middleware. Pre-scans `req.body / req.query /\n * req.params / req.path` for threats and fires `onSanitize` for each hit.\n * Always calls `next()` (no blocking, no mutation) — control flow is\n * owned by the rate-limit and sanitizer middlewares downstream.\n *\n * Errors thrown from the user callback are caught and swallowed so a\n * buggy observer can't take down the request path.\n */\nfunction createSanitizeObserver(\n onSanitize: (event: SanitizeEvent) => void,\n): RequestHandler {\n return (req: Request, _res: Response, next: NextFunction) => {\n const fields: ReadonlyArray<readonly [string, unknown]> = [\n ['body', req.body],\n ['query', req.query],\n ['params', req.params],\n ['path', req.path],\n ];\n for (const [name, value] of fields) {\n const hit = scanThreats(value);\n if (!hit) continue;\n try {\n onSanitize({\n type: hit.vector,\n field: name,\n original: hit.matchedPattern,\n pattern: hit.matchedPattern,\n });\n } catch {\n // Observer must never break the response — fail-open.\n }\n }\n next();\n };\n}\n\n/**\n * Issue #47 — wraps a 429-emitting middleware so the response body is\n * suppressed in dry-run mode. The X-RateLimit-* headers the limiter set\n * BEFORE deciding to 429 still flow through (they were attached to the\n * response Header map by the limiter), giving observability without\n * actually blocking the request.\n *\n * The rate-limit middleware's 429 path is `res.status(429).json({...})`\n * followed by an early return (no `next()` call). To suppress, we\n * intercept `res.status` and on 429:\n * - flag `suppressed`,\n * - swallow the chained `.json(...)` (no body write),\n * - restore the originals,\n * - call `next()` ourselves so the rest of the middleware stack runs.\n *\n * This is monkey-patching with a tightly-scoped lifetime — restored\n * the moment we hand control downstream so no other middleware sees\n * the patched methods.\n */\nfunction suppressRateLimit429(handler: RequestHandler): RequestHandler {\n return (req, res, next) => {\n const originalStatus = res.status.bind(res);\n const originalJson = res.json.bind(res);\n let suppressed = false;\n let nextCalled = false;\n\n const restore = (): void => {\n res.status = originalStatus;\n res.json = originalJson;\n };\n\n res.status = ((code: number): Response => {\n if (code === 429) {\n suppressed = true;\n return res; // chainable; the .json below no-ops.\n }\n return originalStatus(code);\n }) as Response['status'];\n\n res.json = ((body: unknown): Response => {\n if (suppressed) {\n // Limiter's 429 path: it called .status(429).json(...) and then\n // returned without next(). Hand control to the rest of the chain\n // ourselves. Restore originals first so downstream sees a clean\n // ResponseWriter.\n restore();\n if (!nextCalled) {\n nextCalled = true;\n next();\n }\n return res;\n }\n return originalJson(body);\n }) as Response['json'];\n\n handler(req, res, (err) => {\n // Allow path: handler called next() itself. Restore methods so\n // downstream middleware operates on the unwrapped response.\n restore();\n if (!nextCalled) {\n nextCalled = true;\n next(err);\n }\n });\n };\n}\n\nexport function arcis(options: ArcisOptions = {}): ArcisMiddlewareStack {\n const middlewares: RequestHandler[] = [];\n const cleanupFns: (() => void)[] = [];\n const dryRun = options.dryRun === true;\n\n // Telemetry emitter — first, so latency includes the full middleware chain.\n // Opt-in: zero overhead unless options.telemetry.endpoint is set, OR\n // ARCIS_ENDPOINT is present in the environment. Explicit options win.\n let telemetryClient: TelemetryClient | undefined;\n const telemetryOpts = options.telemetry?.endpoint\n ? options.telemetry\n : buildTelemetryFromEnv();\n if (telemetryOpts) {\n const client = new TelemetryClient(telemetryOpts);\n telemetryClient = client;\n middlewares.push(createTelemetryEmitter(client));\n cleanupFns.push(() => {\n void client.close();\n });\n }\n\n // Security headers (always before rate-limit/sanitize)\n if (options.headers !== false) {\n const headerOpts: HeaderOptions = typeof options.headers === 'object'\n ? options.headers\n : {};\n middlewares.push(createHeaders(headerOpts));\n }\n\n // Issue #47 — observer pre-scan. Sits BEFORE the rate-limit + sanitizer so\n // the callback fires on every request that contains a threat, not just\n // those that survive rate-limiting. Skipped when no callback is set so\n // the default zero-overhead path is preserved.\n if (options.onSanitize) {\n middlewares.push(createSanitizeObserver(options.onSanitize));\n }\n\n // Rate limiting — emitter detects 429 from response status, no wrap needed.\n // Dry-run wraps the limiter so the limiter's 429 decision is silently\n // dropped (headers still set; request continues). X-RateLimit-* headers\n // surface either way so dashboards see the would-have-been decision.\n if (options.rateLimit !== false) {\n const rateLimitOpts: RateLimitOptions = typeof options.rateLimit === 'object'\n ? options.rateLimit\n : {};\n const rateLimiter = createRateLimiter(rateLimitOpts);\n middlewares.push(dryRun ? suppressRateLimit429(rateLimiter) : rateLimiter);\n cleanupFns.push(() => rateLimiter.close());\n }\n\n // Input sanitization — wrap with telemetry tap so SecurityThreatError\n // populates req.__arcis with vector/rule/severity for the emitter.\n // Dry-run forces block: false so the sanitizer can never short-circuit\n // with a 403; detection still happens via the observer above.\n if (options.sanitize !== false) {\n const sanitizeOpts: SanitizeOptions = typeof options.sanitize === 'object'\n ? { ...options.sanitize }\n : {};\n if (options.block && sanitizeOpts.block === undefined) {\n sanitizeOpts.block = true;\n }\n if (dryRun) {\n sanitizeOpts.block = false;\n }\n const sanitizer = createSanitizer(sanitizeOpts);\n middlewares.push(telemetryClient ? tapSanitizerThreats(sanitizer) : sanitizer);\n }\n\n // Attach close() directly on the array so callers can clean up without any-casts.\n const result = middlewares as ArcisMiddlewareStack;\n result.close = () => {\n for (const fn of cleanupFns) {\n fn();\n }\n };\n\n return result;\n}\n\n// Attach individual functions for granular use\nconst arcisWithMethods = arcis as ArcisFunction;\narcisWithMethods.sanitize = createSanitizer;\narcisWithMethods.rateLimit = createRateLimiter;\narcisWithMethods.headers = createHeaders;\narcisWithMethods.validate = validate;\narcisWithMethods.logger = createSafeLogger;\narcisWithMethods.errorHandler = createErrorHandler;\n\nexport { arcisWithMethods as arcisFunction };\nexport default arcisWithMethods;\n","/**\n * @module @arcis/node/utils/duration\n * Parse human-readable duration strings into milliseconds.\n *\n * Supports: ms, s, m, h, d\n *\n * @example\n * parseDuration('5m') // 300000\n * parseDuration('2h') // 7200000\n * parseDuration(60000) // 60000 (passthrough)\n * parseDuration('500ms') // 500\n */\n\n/** Maximum duration: ~49.7 days (uint32 max in ms) */\nconst MAX_DURATION_MS = 4_294_967_295;\n\nconst DURATION_REGEX = /^(\\d+(?:\\.\\d+)?)\\s*(ms|s|m|h|d)$/i;\n\nconst UNIT_TO_MS: Record<string, number> = {\n ms: 1,\n s: 1_000,\n m: 60_000,\n h: 3_600_000,\n d: 86_400_000,\n};\n\n/**\n * Parse a duration string or number into milliseconds.\n *\n * @param value - Duration string (e.g. \"5m\", \"2h\", \"30s\") or number (ms)\n * @returns Duration in milliseconds\n * @throws {Error} If the value is not a valid duration\n *\n * @example\n * parseDuration('15m') // 900000\n * parseDuration('1d') // 86400000\n * parseDuration('500ms') // 500\n * parseDuration(60000) // 60000\n */\nexport function parseDuration(value: string | number): number {\n if (typeof value === 'number') {\n if (!Number.isFinite(value) || value < 0) {\n throw new Error(`Invalid duration: ${value}. Must be a non-negative finite number.`);\n }\n return Math.min(Math.floor(value), MAX_DURATION_MS);\n }\n\n if (typeof value !== 'string' || value.trim() === '') {\n throw new Error(`Invalid duration: \"${value}\". Expected a duration string (e.g. \"5m\", \"2h\") or number.`);\n }\n\n const match = value.trim().match(DURATION_REGEX);\n if (!match) {\n throw new Error(\n `Invalid duration: \"${value}\". Expected format: <number><unit> where unit is ms, s, m, h, or d.`\n );\n }\n\n const amount = parseFloat(match[1]);\n const unit = match[2].toLowerCase();\n const ms = Math.floor(amount * UNIT_TO_MS[unit]);\n\n if (ms < 0 || ms > MAX_DURATION_MS) {\n throw new Error(`Duration \"${value}\" exceeds maximum allowed (${MAX_DURATION_MS}ms / ~49.7 days).`);\n }\n\n return ms;\n}\n\n/**\n * Format milliseconds into a human-readable duration string.\n *\n * @param ms - Duration in milliseconds\n * @returns Human-readable string (e.g. \"5m\", \"2h 30m\")\n */\nexport function formatDuration(ms: number): string {\n if (!Number.isFinite(ms) || ms < 0) return '0ms';\n\n if (ms < 1000) return `${ms}ms`;\n\n const days = Math.floor(ms / 86_400_000);\n const hours = Math.floor((ms % 86_400_000) / 3_600_000);\n const minutes = Math.floor((ms % 3_600_000) / 60_000);\n const seconds = Math.floor((ms % 60_000) / 1_000);\n\n const parts: string[] = [];\n if (days > 0) parts.push(`${days}d`);\n if (hours > 0) parts.push(`${hours}h`);\n if (minutes > 0) parts.push(`${minutes}m`);\n if (seconds > 0) parts.push(`${seconds}s`);\n\n return parts.join(' ') || '0ms';\n}\n","/**\n * @module @arcis/node/middleware/rate-limit-sliding\n * Sliding window rate limiting middleware.\n *\n * More accurate than fixed window — uses a weighted sum of the previous\n * and current window to approximate a true sliding window.\n *\n * Algorithm:\n * weight = (windowMs - elapsed) / windowMs\n * count = (prevWindow * weight) + currentWindow\n * allow = count < limit\n *\n * @example\n * app.use(createSlidingWindowLimiter({ max: 100, window: '15m' }));\n */\n\nimport type { Request, Response, NextFunction, RequestHandler } from 'express';\nimport { parseDuration } from '../utils/duration';\nimport { RATE_LIMIT } from '../core/constants';\n\nexport interface SlidingWindowOptions {\n /** Maximum requests per window. Default: 100 */\n max?: number;\n /** Window size in ms or duration string. Default: '1m' */\n window?: string | number;\n /** Error message when limit exceeded */\n message?: string;\n /** HTTP status code for rate limited responses. Default: 429 */\n statusCode?: number;\n /** Function to generate rate limit key from request */\n keyGenerator?: (req: Request) => string;\n /** Function to skip rate limiting for certain requests */\n skip?: (req: Request) => boolean;\n}\n\ninterface WindowEntry {\n count: number;\n startTime: number;\n}\n\nexport interface SlidingWindowMiddleware extends RequestHandler {\n close: () => void;\n}\n\n/**\n * Create sliding window rate limiter middleware.\n *\n * @example\n * // 100 requests per 15 minutes\n * app.use(createSlidingWindowLimiter({ max: 100, window: '15m' }));\n *\n * @example\n * // Strict API limit\n * app.use('/api', createSlidingWindowLimiter({ max: 30, window: '1m' }));\n */\nexport function createSlidingWindowLimiter(options: SlidingWindowOptions = {}): SlidingWindowMiddleware {\n const {\n max = RATE_LIMIT.DEFAULT_MAX_REQUESTS,\n window: windowOpt = RATE_LIMIT.DEFAULT_WINDOW_MS,\n message = RATE_LIMIT.DEFAULT_MESSAGE,\n statusCode = RATE_LIMIT.DEFAULT_STATUS_CODE,\n keyGenerator = (req) => req.ip ?? req.socket?.remoteAddress ?? 'unknown',\n skip,\n } = options;\n\n const windowMs = parseDuration(windowOpt);\n\n // Two windows per key: current and previous\n const currentWindows = Object.create(null) as Record<string, WindowEntry>;\n const previousWindows = Object.create(null) as Record<string, WindowEntry>;\n\n // Pin cleanup cadence to 30s regardless of windowMs. Scaling cleanup\n // with windowMs causes churn on short windows (1s window cleans every\n // second) and stale-entry buildup on long windows (1h window only\n // cleans hourly). 30s bounds memory growth without burning CPU; the\n // cutoff stays at `2 * windowMs` so legitimate active windows survive.\n const CLEANUP_INTERVAL_MS = 30_000;\n const cleanupInterval = setInterval(() => {\n const now = Date.now();\n const cutoff = now - windowMs * 2; // Keep 2 windows worth\n for (const key of Object.keys(previousWindows)) {\n if (previousWindows[key].startTime < cutoff) {\n delete previousWindows[key];\n }\n }\n for (const key of Object.keys(currentWindows)) {\n if (currentWindows[key].startTime < cutoff) {\n delete currentWindows[key];\n }\n }\n }, CLEANUP_INTERVAL_MS);\n\n if (typeof cleanupInterval.unref === 'function') {\n cleanupInterval.unref();\n }\n\n const handler: RequestHandler = (req: Request, res: Response, next: NextFunction) => {\n try {\n if (skip?.(req)) return next();\n\n const key = keyGenerator(req);\n const now = Date.now();\n\n // Determine current window boundaries\n const windowStart = Math.floor(now / windowMs) * windowMs;\n\n // Rotate windows if needed\n if (!currentWindows[key] || currentWindows[key].startTime < windowStart) {\n // Move current to previous\n if (currentWindows[key]) {\n previousWindows[key] = currentWindows[key];\n }\n currentWindows[key] = { count: 0, startTime: windowStart };\n }\n\n // Calculate weighted count BEFORE incrementing\n const elapsed = now - windowStart;\n const weight = Math.max(0, (windowMs - elapsed) / windowMs);\n const prevCount = previousWindows[key]?.count ?? 0;\n const estimatedCount = (prevCount * weight) + currentWindows[key].count + 1;\n\n const remaining = Math.max(0, Math.floor(max - estimatedCount));\n const resetMs = windowStart + windowMs - now;\n const resetSeconds = Math.max(1, Math.ceil(resetMs / 1000));\n\n // Set rate limit headers\n res.setHeader('X-RateLimit-Limit', max.toString());\n res.setHeader('X-RateLimit-Remaining', remaining.toString());\n res.setHeader('X-RateLimit-Reset', resetSeconds.toString());\n res.setHeader('X-RateLimit-Policy', `${max};w=${Math.floor(windowMs / 1000)}`);\n\n if (estimatedCount > max) {\n // Don't increment — rejected requests should not consume quota\n res.setHeader('Retry-After', resetSeconds.toString());\n res.status(statusCode).json({\n error: message,\n retryAfter: resetSeconds,\n });\n return;\n }\n\n // Only increment on allowed requests\n currentWindows[key].count++;\n\n next();\n } catch (error) {\n // Fail open\n // eslint-disable-next-line no-console\n console.error('[arcis] Sliding window rate limiter error:', error);\n next();\n }\n };\n\n const middleware = handler as SlidingWindowMiddleware;\n middleware.close = () => {\n clearInterval(cleanupInterval);\n };\n\n return middleware;\n}\n","/**\n * @module @arcis/node/middleware/rate-limit-token\n * Token bucket rate limiting middleware.\n *\n * Allows burst traffic while enforcing an average rate.\n * Tokens refill at a steady rate. Each request costs 1 token.\n *\n * Algorithm:\n * tokens = min(capacity, tokens + elapsed * refillRate)\n * if tokens >= cost: allow, subtract cost\n * else: deny\n *\n * @example\n * app.use(createTokenBucketLimiter({ capacity: 50, refillRate: 10 }));\n */\n\nimport type { Request, Response, NextFunction, RequestHandler } from 'express';\nimport { RATE_LIMIT } from '../core/constants';\n\nexport interface TokenBucketOptions {\n /** Maximum tokens (burst size). Default: 100 */\n capacity?: number;\n /** Tokens added per second. Default: 10 */\n refillRate?: number;\n /** Tokens consumed per request. Default: 1 */\n cost?: number;\n /** Error message when limit exceeded */\n message?: string;\n /** HTTP status code for rate limited responses. Default: 429 */\n statusCode?: number;\n /** Function to generate rate limit key from request */\n keyGenerator?: (req: Request) => string;\n /** Function to skip rate limiting for certain requests */\n skip?: (req: Request) => boolean;\n}\n\ninterface Bucket {\n tokens: number;\n lastRefill: number;\n}\n\nexport interface TokenBucketMiddleware extends RequestHandler {\n close: () => void;\n}\n\n/**\n * Create token bucket rate limiter middleware.\n *\n * @example\n * // Allow bursts of 50, sustained rate of 10/sec\n * app.use(createTokenBucketLimiter({ capacity: 50, refillRate: 10 }));\n *\n * @example\n * // Strict API: 5 requests burst, 1/sec sustained\n * app.use('/api/expensive', createTokenBucketLimiter({\n * capacity: 5,\n * refillRate: 1,\n * }));\n */\nexport function createTokenBucketLimiter(options: TokenBucketOptions = {}): TokenBucketMiddleware {\n const {\n capacity = 100,\n refillRate = 10,\n cost = 1,\n message = RATE_LIMIT.DEFAULT_MESSAGE,\n statusCode = RATE_LIMIT.DEFAULT_STATUS_CODE,\n keyGenerator = (req) => req.ip ?? req.socket?.remoteAddress ?? 'unknown',\n skip,\n } = options;\n\n if (capacity < 1) throw new RangeError(`Token bucket capacity must be >= 1, got ${capacity}`);\n if (refillRate <= 0) throw new RangeError(`Token bucket refillRate must be > 0, got ${refillRate}`);\n if (cost < 1) throw new RangeError(`Token bucket cost must be >= 1, got ${cost}`);\n if (cost > capacity) throw new RangeError(`Token bucket cost (${cost}) must be <= capacity (${capacity}), otherwise all requests are permanently denied`);\n\n const buckets = Object.create(null) as Record<string, Bucket>;\n\n // Cleanup stale buckets (full buckets that haven't been accessed)\n const cleanupInterval = setInterval(() => {\n const now = Date.now();\n const staleThreshold = (capacity / refillRate) * 1000 * 2; // 2x time to refill\n for (const key of Object.keys(buckets)) {\n if (now - buckets[key].lastRefill > staleThreshold) {\n delete buckets[key];\n }\n }\n }, 60_000);\n\n if (typeof cleanupInterval.unref === 'function') {\n cleanupInterval.unref();\n }\n\n function refillBucket(bucket: Bucket, now: number): void {\n const elapsed = (now - bucket.lastRefill) / 1000; // seconds\n const tokensToAdd = elapsed * refillRate;\n bucket.tokens = Math.min(capacity, bucket.tokens + tokensToAdd);\n bucket.lastRefill = now;\n }\n\n const handler: RequestHandler = (req: Request, res: Response, next: NextFunction) => {\n try {\n if (skip?.(req)) return next();\n\n const key = keyGenerator(req);\n const now = Date.now();\n\n // Get or create bucket\n if (!buckets[key]) {\n buckets[key] = { tokens: capacity, lastRefill: now };\n }\n\n const bucket = buckets[key];\n refillBucket(bucket, now);\n\n // Calculate retry-after (time until enough tokens are available)\n const retryAfterSec = bucket.tokens < cost\n ? Math.ceil((cost - bucket.tokens) / refillRate)\n : 0;\n\n // Set headers\n res.setHeader('X-RateLimit-Limit', capacity.toString());\n res.setHeader('X-RateLimit-Remaining', Math.floor(Math.max(0, bucket.tokens - cost)).toString());\n res.setHeader('X-RateLimit-Policy', `${capacity};w=${Math.floor(capacity / refillRate)};burst=${capacity}`);\n\n if (bucket.tokens < cost) {\n res.setHeader('Retry-After', retryAfterSec.toString());\n res.setHeader('X-RateLimit-Reset', retryAfterSec.toString());\n res.status(statusCode).json({\n error: message,\n retryAfter: retryAfterSec,\n });\n return;\n }\n\n // Consume token\n bucket.tokens -= cost;\n next();\n } catch (error) {\n // Fail open\n // eslint-disable-next-line no-console\n console.error('[arcis] Token bucket rate limiter error:', error);\n next();\n }\n };\n\n const middleware = handler as TokenBucketMiddleware;\n middleware.close = () => {\n clearInterval(cleanupInterval);\n };\n\n return middleware;\n}\n","/**\n * @module @arcis/node/middleware/cors\n * Safe CORS middleware with secure defaults\n */\n\nimport type { Request, Response, NextFunction, RequestHandler } from 'express';\n\n/** CORS configuration options */\nexport interface CorsOptions {\n /**\n * Allowed origins. Can be:\n * - A string: exact match (e.g., 'https://example.com')\n * - An array: whitelist of allowed origins\n * - A RegExp: pattern match (use with care)\n * - A function: custom validation `(origin) => boolean`\n * - `true`: reflect the request origin (DANGEROUS — only for dev)\n *\n * Default: none (no origin allowed). You must explicitly set this.\n */\n origin: string | string[] | RegExp | ((origin: string) => boolean) | true;\n\n /** Allowed HTTP methods. Default: ['GET', 'HEAD', 'PUT', 'PATCH', 'POST', 'DELETE'] */\n methods?: string[];\n\n /** Allowed headers. Default: ['Content-Type', 'Authorization'] */\n allowedHeaders?: string[];\n\n /** Headers exposed to the browser. Default: [] */\n exposedHeaders?: string[];\n\n /** Allow credentials (cookies, authorization headers). Default: false */\n credentials?: boolean;\n\n /** Preflight cache duration in seconds. Default: 600 (10 minutes) */\n maxAge?: number;\n\n /** Respond to preflight with 204 (no content). Default: true */\n preflightContinue?: boolean;\n}\n\nconst DEFAULT_METHODS = ['GET', 'HEAD', 'PUT', 'PATCH', 'POST', 'DELETE'];\nconst DEFAULT_HEADERS = ['Content-Type', 'Authorization'];\nconst DEFAULT_MAX_AGE = 600;\n\n/**\n * Check if an origin is allowed by the configured policy.\n */\nfunction isOriginAllowed(\n requestOrigin: string,\n allowed: CorsOptions['origin']\n): boolean {\n // 'null' origin is always blocked — sent by sandboxed iframes, data: URIs, etc.\n if (requestOrigin === 'null') return false;\n\n if (allowed === true) return true;\n\n if (typeof allowed === 'string') {\n return requestOrigin === allowed;\n }\n\n if (Array.isArray(allowed)) {\n return allowed.includes(requestOrigin);\n }\n\n if (allowed instanceof RegExp) {\n return allowed.test(requestOrigin);\n }\n\n if (typeof allowed === 'function') {\n return allowed(requestOrigin);\n }\n\n return false;\n}\n\n/**\n * Create safe CORS middleware.\n *\n * Unlike permissive CORS libraries, this enforces secure defaults:\n * - No wildcard `*` when credentials are enabled\n * - `null` origin is always blocked\n * - `Vary: Origin` is always set for proper caching\n * - You must explicitly configure allowed origins\n *\n * @param options - CORS configuration\n * @returns Express middleware\n *\n * @example\n * // Allow a single origin\n * app.use(safeCors({ origin: 'https://myapp.com' }));\n *\n * @example\n * // Allow multiple origins with credentials\n * app.use(safeCors({\n * origin: ['https://myapp.com', 'https://admin.myapp.com'],\n * credentials: true,\n * }));\n *\n * @example\n * // Development: allow all (NOT for production)\n * app.use(safeCors({ origin: true }));\n */\nexport function safeCors(options: CorsOptions): RequestHandler {\n const {\n origin,\n methods = DEFAULT_METHODS,\n allowedHeaders = DEFAULT_HEADERS,\n exposedHeaders = [],\n credentials = false,\n maxAge = DEFAULT_MAX_AGE,\n preflightContinue = true,\n } = options;\n\n return (req: Request, res: Response, next: NextFunction) => {\n const requestOrigin = req.headers.origin;\n\n // Always set Vary: Origin for proper caching\n res.setHeader('Vary', 'Origin');\n\n // No origin header = same-origin request, skip CORS headers\n if (!requestOrigin) {\n return next();\n }\n\n const allowed = isOriginAllowed(requestOrigin, origin);\n\n if (!allowed) {\n // Don't set any CORS headers — browser will block the request\n return next();\n }\n\n // Set Access-Control-Allow-Origin to the specific origin (not *)\n res.setHeader('Access-Control-Allow-Origin', requestOrigin);\n\n if (credentials) {\n res.setHeader('Access-Control-Allow-Credentials', 'true');\n }\n\n if (exposedHeaders.length > 0) {\n res.setHeader('Access-Control-Expose-Headers', exposedHeaders.join(', '));\n }\n\n // Handle preflight requests\n if (req.method === 'OPTIONS') {\n res.setHeader('Access-Control-Allow-Methods', methods.join(', '));\n res.setHeader('Access-Control-Allow-Headers', allowedHeaders.join(', '));\n res.setHeader('Access-Control-Max-Age', String(maxAge));\n\n if (preflightContinue) {\n res.status(204).end();\n return;\n }\n }\n\n next();\n };\n}\n\n/**\n * Alias for safeCors\n * @see safeCors\n */\nexport const createCors = safeCors;\n","/**\n * @module @arcis/node/middleware/cookies\n * Secure cookie defaults middleware\n */\n\nimport type { Request, Response, NextFunction, RequestHandler } from 'express';\n\n/** Cookie security configuration */\nexport interface SecureCookieOptions {\n /** Force HttpOnly on all cookies. Default: true */\n httpOnly?: boolean;\n /** Force Secure flag (HTTPS only). Default: true in production, false in dev */\n secure?: boolean;\n /** SameSite attribute. Default: 'Lax' */\n sameSite?: 'Strict' | 'Lax' | 'None' | false;\n /** Override Path attribute. Default: undefined (keep original) */\n path?: string;\n}\n\nconst COOKIE_ATTRS = {\n HTTP_ONLY: '; HttpOnly',\n SECURE: '; Secure',\n SAME_SITE_STRICT: '; SameSite=Strict',\n SAME_SITE_LAX: '; SameSite=Lax',\n SAME_SITE_NONE: '; SameSite=None',\n} as const;\n\n/**\n * Enforce secure defaults on a Set-Cookie header value.\n */\nexport function enforceSecureCookie(\n cookieStr: string,\n options: Required<Omit<SecureCookieOptions, 'path'>> & { path?: string }\n): string {\n const lower = cookieStr.toLowerCase();\n let result = cookieStr;\n\n // HttpOnly — prevent JavaScript access\n if (options.httpOnly && !lower.includes('httponly')) {\n result += COOKIE_ATTRS.HTTP_ONLY;\n }\n\n // Secure — HTTPS only\n if (options.secure && !lower.includes('; secure')) {\n result += COOKIE_ATTRS.SECURE;\n }\n\n // SameSite — CSRF protection\n if (options.sameSite !== false && !lower.includes('samesite')) {\n switch (options.sameSite) {\n case 'Strict':\n result += COOKIE_ATTRS.SAME_SITE_STRICT;\n break;\n case 'None':\n result += COOKIE_ATTRS.SAME_SITE_NONE;\n // SameSite=None requires Secure\n if (!result.toLowerCase().includes('; secure')) {\n result += COOKIE_ATTRS.SECURE;\n }\n break;\n case 'Lax':\n default:\n result += COOKIE_ATTRS.SAME_SITE_LAX;\n break;\n }\n }\n\n // Override path if specified\n if (options.path) {\n if (lower.includes('path=')) {\n result = result.replace(/;\\s*path=[^;]*/i, `; Path=${options.path}`);\n } else {\n result += `; Path=${options.path}`;\n }\n }\n\n return result;\n}\n\n/**\n * Create middleware that enforces secure cookie defaults.\n *\n * Intercepts Set-Cookie headers and adds missing security attributes:\n * - HttpOnly: prevents JavaScript access (XSS cookie theft)\n * - Secure: cookies only sent over HTTPS\n * - SameSite: CSRF protection\n *\n * @param options - Cookie security configuration\n * @returns Express middleware\n *\n * @example\n * // Enforce defaults on all cookies\n * app.use(secureCookieDefaults());\n *\n * @example\n * // Strict SameSite for sensitive apps\n * app.use(secureCookieDefaults({ sameSite: 'Strict' }));\n */\nexport function secureCookieDefaults(options: SecureCookieOptions = {}): RequestHandler {\n const isProduction = process.env.NODE_ENV === 'production';\n const resolved = {\n httpOnly: options.httpOnly ?? true,\n secure: options.secure ?? isProduction,\n sameSite: options.sameSite ?? 'Lax' as const,\n path: options.path,\n };\n\n // Fail loudly on incompatible combinations — silent misconfiguration is a\n // common footgun (e.g. SameSite=None without Secure is rejected by every\n // modern browser, producing a request that just silently loses cookies).\n if (resolved.sameSite === 'None' && resolved.secure === false) {\n throw new Error(\n '[arcis] secureCookieDefaults: sameSite=None requires secure=true (modern browsers reject the cookie otherwise)'\n );\n }\n if (resolved.httpOnly === false && resolved.secure === false && isProduction) {\n // Only a warning — some apps legitimately need non-HttpOnly cookies (e.g. CSRF double-submit).\n // But running both off in production is almost never intentional.\n // eslint-disable-next-line no-console\n console.warn(\n '[arcis] secureCookieDefaults: httpOnly and secure are both disabled in production — cookies will be readable by JS and sent over HTTP'\n );\n }\n\n return (_req: Request, res: Response, next: NextFunction) => {\n // Monkey-patch res.setHeader to intercept Set-Cookie\n const originalSetHeader = res.setHeader.bind(res);\n\n res.setHeader = function patchedSetHeader(name: string, value: string | number | readonly string[]) {\n if (name.toLowerCase() === 'set-cookie') {\n if (Array.isArray(value)) {\n value = value.map(v => enforceSecureCookie(String(v), resolved));\n } else {\n value = enforceSecureCookie(String(value), resolved);\n }\n }\n return originalSetHeader(name, value);\n } as typeof res.setHeader;\n\n next();\n };\n}\n\n/**\n * Alias for secureCookieDefaults\n * @see secureCookieDefaults\n */\nexport const createSecureCookies = secureCookieDefaults;\n","[\n {\n \"id\": \"ai-search-bot\",\n \"category\": \"AI_CRAWLER\",\n \"name\": \"ai-search-bot\",\n \"patterns\": [\n \"AISearchBot\"\n ],\n \"forbidden\": []\n },\n {\n \"id\": \"ai2-crawler\",\n \"category\": \"AI_CRAWLER\",\n \"name\": \"ai2-crawler\",\n \"patterns\": [\n \"AI2Bot\\\\s\"\n ],\n \"forbidden\": []\n },\n {\n \"id\": \"ai2-crawler-dolma\",\n \"category\": \"AI_CRAWLER\",\n \"name\": \"ai2-crawler-dolma\",\n \"patterns\": [\n \"Ai2Bot-Dolma\"\n ],\n \"forbidden\": []\n },\n {\n \"id\": \"aihit-crawler\",\n \"category\": \"AI_CRAWLER\",\n \"name\": \"aihit-crawler\",\n \"patterns\": [\n \"aiHitBot\"\n ],\n \"forbidden\": []\n },\n {\n \"id\": \"anthropic-ai-token\",\n \"category\": \"AI_CRAWLER\",\n \"name\": \"Anthropic\",\n \"patterns\": [\n \"anthropic-ai\"\n ],\n \"forbidden\": []\n },\n {\n \"id\": \"anthropic-crawler\",\n \"category\": \"AI_CRAWLER\",\n \"name\": \"ClaudeBot\",\n \"patterns\": [\n \"[cC]laude(?:[bB]ot|-[Ww]eb)\"\n ],\n \"forbidden\": []\n },\n {\n \"id\": \"anthropic-crawler-search\",\n \"category\": \"AI_CRAWLER\",\n \"name\": \"ClaudeSearchBot\",\n \"patterns\": [\n \"Claude-SearchBot\"\n ],\n \"forbidden\": []\n },\n {\n \"id\": \"anthropic-crawler-user\",\n \"category\": \"AI_CRAWLER\",\n \"name\": \"ClaudeUser\",\n \"patterns\": [\n \"Claude-User\"\n ],\n \"forbidden\": []\n },\n {\n \"id\": \"botify-crawler\",\n \"category\": \"AI_CRAWLER\",\n \"name\": \"botify-crawler\",\n \"patterns\": [\n \"botify\"\n ],\n \"forbidden\": []\n },\n {\n \"id\": \"bytedance-crawler\",\n \"category\": \"AI_CRAWLER\",\n \"name\": \"Bytespider\",\n \"patterns\": [\n \"Bytespider\"\n ],\n \"forbidden\": []\n },\n {\n \"id\": \"ccbot-crawler\",\n \"category\": \"AI_CRAWLER\",\n \"name\": \"CCBot\",\n \"patterns\": [\n \"CCBot\\\\/\"\n ],\n \"forbidden\": []\n },\n {\n \"id\": \"cohere-crawler\",\n \"category\": \"AI_CRAWLER\",\n \"name\": \"cohere-crawler\",\n \"patterns\": [\n \"cohere-ai\"\n ],\n \"forbidden\": []\n },\n {\n \"id\": \"diffbot-crawler\",\n \"category\": \"AI_CRAWLER\",\n \"name\": \"diffbot-crawler\",\n \"patterns\": [\n \"Diffbot\\\\/\"\n ],\n \"forbidden\": []\n },\n {\n \"id\": \"friendlycrawler\",\n \"category\": \"AI_CRAWLER\",\n \"name\": \"friendlycrawler\",\n \"patterns\": [\n \"FriendlyCrawler\"\n ],\n \"forbidden\": []\n },\n {\n \"id\": \"glutenfreepleasure-crawler\",\n \"category\": \"AI_CRAWLER\",\n \"name\": \"glutenfreepleasure-crawler\",\n \"patterns\": [\n \"Gluten Free Crawler\\\\/\"\n ],\n \"forbidden\": []\n },\n {\n \"id\": \"imagesift-crawler\",\n \"category\": \"AI_CRAWLER\",\n \"name\": \"imagesift-crawler\",\n \"patterns\": [\n \"ImagesiftBot\"\n ],\n \"forbidden\": []\n },\n {\n \"id\": \"infegy-crawler\",\n \"category\": \"AI_CRAWLER\",\n \"name\": \"infegy-crawler\",\n \"patterns\": [\n \"collection@infegy\\\\.com\"\n ],\n \"forbidden\": []\n },\n {\n \"id\": \"integralads-crawler\",\n \"category\": \"AI_CRAWLER\",\n \"name\": \"integralads-crawler\",\n \"patterns\": [\n \"IAS crawler\"\n ],\n \"forbidden\": []\n },\n {\n \"id\": \"leadcrunch-crawler\",\n \"category\": \"AI_CRAWLER\",\n \"name\": \"leadcrunch-crawler\",\n \"patterns\": [\n \"CrunchBot\"\n ],\n \"forbidden\": []\n },\n {\n \"id\": \"mediatoolkit-crawler\",\n \"category\": \"AI_CRAWLER\",\n \"name\": \"mediatoolkit-crawler\",\n \"patterns\": [\n \"Mediatoolkitbot\"\n ],\n \"forbidden\": []\n },\n {\n \"id\": \"meta-externalagent\",\n \"category\": \"AI_CRAWLER\",\n \"name\": \"Meta AI\",\n \"patterns\": [\n \"meta-externalagent\"\n ],\n \"forbidden\": []\n },\n {\n \"id\": \"ntent-crawler\",\n \"category\": \"AI_CRAWLER\",\n \"name\": \"ntent-crawler\",\n \"patterns\": [\n \"NTENTbot\"\n ],\n \"forbidden\": []\n },\n {\n \"id\": \"omgili-crawler\",\n \"category\": \"AI_CRAWLER\",\n \"name\": \"omgili-crawler\",\n \"patterns\": [\n \"omgili\"\n ],\n \"forbidden\": []\n },\n {\n \"id\": \"openai-crawler\",\n \"category\": \"AI_CRAWLER\",\n \"name\": \"GPTBot\",\n \"patterns\": [\n \"GPTBot\"\n ],\n \"forbidden\": []\n },\n {\n \"id\": \"openai-crawler-user\",\n \"category\": \"AI_CRAWLER\",\n \"name\": \"ChatGPTUser\",\n \"patterns\": [\n \"ChatGPT-User\"\n ],\n \"forbidden\": []\n },\n {\n \"id\": \"perplexity-crawler\",\n \"category\": \"AI_CRAWLER\",\n \"name\": \"PerplexityBot\",\n \"patterns\": [\n \"PerplexityBot\\\\/\"\n ],\n \"forbidden\": []\n },\n {\n \"id\": \"perplexity-user\",\n \"category\": \"AI_CRAWLER\",\n \"name\": \"perplexity-user\",\n \"patterns\": [\n \"Perplexity-User\\\\/\"\n ],\n \"forbidden\": []\n },\n {\n \"id\": \"primal-crawler\",\n \"category\": \"AI_CRAWLER\",\n \"name\": \"primal-crawler\",\n \"patterns\": [\n \"Primalbot\"\n ],\n \"forbidden\": []\n },\n {\n \"id\": \"sbintuitions-bot\",\n \"category\": \"AI_CRAWLER\",\n \"name\": \"sbintuitions-bot\",\n \"patterns\": [\n \"SBIntuitionsBot\\\\/\"\n ],\n \"forbidden\": []\n },\n {\n \"id\": \"searchatlas-crawler\",\n \"category\": \"AI_CRAWLER\",\n \"name\": \"searchatlas-crawler\",\n \"patterns\": [\n \"SearchAtlas\"\n ],\n \"forbidden\": []\n },\n {\n \"id\": \"sentione-crawler\",\n \"category\": \"AI_CRAWLER\",\n \"name\": \"sentione-crawler\",\n \"patterns\": [\n \"SentiBot\"\n ],\n \"forbidden\": []\n },\n {\n \"id\": \"storygize-crawler\",\n \"category\": \"AI_CRAWLER\",\n \"name\": \"storygize-crawler\",\n \"patterns\": [\n \"StorygizeBot\"\n ],\n \"forbidden\": []\n },\n {\n \"id\": \"timpi-crawler\",\n \"category\": \"AI_CRAWLER\",\n \"name\": \"timpi-crawler\",\n \"patterns\": [\n \"Timpibot\"\n ],\n \"forbidden\": []\n },\n {\n \"id\": \"velen-crawler\",\n \"category\": \"AI_CRAWLER\",\n \"name\": \"velen-crawler\",\n \"patterns\": [\n \"VelenPublicWebCrawler\"\n ],\n \"forbidden\": []\n },\n {\n \"id\": \"webzio-crawler-ai\",\n \"category\": \"AI_CRAWLER\",\n \"name\": \"webzio-crawler-ai\",\n \"patterns\": [\n \"webzio-extended\"\n ],\n \"forbidden\": []\n },\n {\n \"id\": \"you-crawler\",\n \"category\": \"AI_CRAWLER\",\n \"name\": \"you-crawler\",\n \"patterns\": [\n \"YouBot\"\n ],\n \"forbidden\": []\n },\n {\n \"id\": \"cypress\",\n \"category\": \"AUTOMATED\",\n \"name\": \"Cypress\",\n \"patterns\": [\n \"[Cc]ypress\"\n ],\n \"forbidden\": []\n },\n {\n \"id\": \"fake-msie6\",\n \"category\": \"AUTOMATED\",\n \"name\": \"Fake IE6\",\n \"patterns\": [\n \"MSIE 6\\\\.0\"\n ],\n \"forbidden\": []\n },\n {\n \"id\": \"headless-chrome\",\n \"category\": \"AUTOMATED\",\n \"name\": \"Headless Chrome\",\n \"patterns\": [\n \"HeadlessChrome\"\n ],\n \"forbidden\": []\n },\n {\n \"id\": \"javascript-phantom\",\n \"category\": \"AUTOMATED\",\n \"name\": \"PhantomJS\",\n \"patterns\": [\n \"PhantomJS\"\n ],\n \"forbidden\": []\n },\n {\n \"id\": \"playwright\",\n \"category\": \"AUTOMATED\",\n \"name\": \"Playwright\",\n \"patterns\": [\n \"[Pp]laywright\"\n ],\n \"forbidden\": []\n },\n {\n \"id\": \"puppeteer\",\n \"category\": \"AUTOMATED\",\n \"name\": \"Puppeteer\",\n \"patterns\": [\n \"[Pp]uppeteer\"\n ],\n \"forbidden\": []\n },\n {\n \"id\": \"selenium\",\n \"category\": \"AUTOMATED\",\n \"name\": \"Selenium\",\n \"patterns\": [\n \"[Ss]elenium\"\n ],\n \"forbidden\": []\n },\n {\n \"id\": \"webdriver\",\n \"category\": \"AUTOMATED\",\n \"name\": \"WebDriver\",\n \"patterns\": [\n \"[Ww]ebdriver\"\n ],\n \"forbidden\": []\n },\n {\n \"id\": \"amazon-route53-health-check\",\n \"category\": \"MONITORING\",\n \"name\": \"amazon-route53-health-check\",\n \"patterns\": [\n \"Amazon Route 53 Health Check Service\"\n ],\n \"forbidden\": []\n },\n {\n \"id\": \"azure-app-insights\",\n \"category\": \"MONITORING\",\n \"name\": \"azure-app-insights\",\n \"patterns\": [\n \"AppInsights\"\n ],\n \"forbidden\": []\n },\n {\n \"id\": \"betterstack-monitor\",\n \"category\": \"MONITORING\",\n \"name\": \"betterstack-monitor\",\n \"patterns\": [\n \"Better Stack\"\n ],\n \"forbidden\": []\n },\n {\n \"id\": \"betteruptime-monitor\",\n \"category\": \"MONITORING\",\n \"name\": \"betteruptime-monitor\",\n \"patterns\": [\n \"Better Uptime Bot\"\n ],\n \"forbidden\": []\n },\n {\n \"id\": \"brandverity-crawler\",\n \"category\": \"MONITORING\",\n \"name\": \"brandverity-crawler\",\n \"patterns\": [\n \"BrandVerity\"\n ],\n \"forbidden\": []\n },\n {\n \"id\": \"censys-inspect\",\n \"category\": \"MONITORING\",\n \"name\": \"censys-inspect\",\n \"patterns\": [\n \"CensysInspect\\\\/\"\n ],\n \"forbidden\": []\n },\n {\n \"id\": \"changedetection-crawler\",\n \"category\": \"MONITORING\",\n \"name\": \"changedetection-crawler\",\n \"patterns\": [\n \"changedetection\"\n ],\n \"forbidden\": []\n },\n {\n \"id\": \"checkly-monitor\",\n \"category\": \"MONITORING\",\n \"name\": \"checkly-monitor\",\n \"patterns\": [\n \"Checkly\\\\/\"\n ],\n \"forbidden\": []\n },\n {\n \"id\": \"cloudflare-healthchecks\",\n \"category\": \"MONITORING\",\n \"name\": \"cloudflare-healthchecks\",\n \"patterns\": [\n \"Cloudflare-Healthchecks\"\n ],\n \"forbidden\": []\n },\n {\n \"id\": \"cloudflare-security-center\",\n \"category\": \"MONITORING\",\n \"name\": \"cloudflare-security-center\",\n \"patterns\": [\n \"https:\\\\/\\\\/developers\\\\.cloudflare\\\\.com\\\\/security-center\\\\/\"\n ],\n \"forbidden\": []\n },\n {\n \"id\": \"cloudflare-ssl-detector\",\n \"category\": \"MONITORING\",\n \"name\": \"cloudflare-ssl-detector\",\n \"patterns\": [\n \"Cloudflare-SSLDetector\"\n ],\n \"forbidden\": []\n },\n {\n \"id\": \"cloudflare-traffic-manager\",\n \"category\": \"MONITORING\",\n \"name\": \"cloudflare-traffic-manager\",\n \"patterns\": [\n \"Cloudflare-Traffic-Manager\"\n ],\n \"forbidden\": []\n },\n {\n \"id\": \"datadog-monitor-synthetics\",\n \"category\": \"MONITORING\",\n \"name\": \"Datadog\",\n \"patterns\": [\n \"Datadog\\\\/{0,1}Synthetics\"\n ],\n \"forbidden\": []\n },\n {\n \"id\": \"deadlinkchecker\",\n \"category\": \"MONITORING\",\n \"name\": \"deadlinkchecker\",\n \"patterns\": [\n \"deadlinkchecker\"\n ],\n \"forbidden\": []\n },\n {\n \"id\": \"disqus-crawler\",\n \"category\": \"MONITORING\",\n \"name\": \"disqus-crawler\",\n \"patterns\": [\n \"Disqus\"\n ],\n \"forbidden\": []\n },\n {\n \"id\": \"dubbot-crawler\",\n \"category\": \"MONITORING\",\n \"name\": \"dubbot-crawler\",\n \"patterns\": [\n \"Dubbotbot\"\n ],\n \"forbidden\": []\n },\n {\n \"id\": \"dynatrace-monitor\",\n \"category\": \"MONITORING\",\n \"name\": \"dynatrace-monitor\",\n \"patterns\": [\n \"RuxitSynthetic\"\n ],\n \"forbidden\": []\n },\n {\n \"id\": \"freewebmonitoring-monitor\",\n \"category\": \"MONITORING\",\n \"name\": \"freewebmonitoring-monitor\",\n \"patterns\": [\n \"FreeWebMonitoring SiteChecker\"\n ],\n \"forbidden\": []\n },\n {\n \"id\": \"freshworks-monitor\",\n \"category\": \"MONITORING\",\n \"name\": \"freshworks-monitor\",\n \"patterns\": [\n \"FreshpingBot\"\n ],\n \"forbidden\": []\n },\n {\n \"id\": \"google-certificates-bridge\",\n \"category\": \"MONITORING\",\n \"name\": \"google-certificates-bridge\",\n \"patterns\": [\n \"Google-Certificates-Bridge\"\n ],\n \"forbidden\": []\n },\n {\n \"id\": \"google-site-verification\",\n \"category\": \"MONITORING\",\n \"name\": \"google-site-verification\",\n \"patterns\": [\n \"Google-Site-Verification\"\n ],\n \"forbidden\": []\n },\n {\n \"id\": \"google-structured-data-testing-tool\",\n \"category\": \"MONITORING\",\n \"name\": \"google-structured-data-testing-tool\",\n \"patterns\": [\n \"Google-Structured-Data-Testing-Tool\"\n ],\n \"forbidden\": []\n },\n {\n \"id\": \"hubspot-crawler\",\n \"category\": \"MONITORING\",\n \"name\": \"HubSpotBot\",\n \"patterns\": [\n \"HubSpot\"\n ],\n \"forbidden\": []\n },\n {\n \"id\": \"hydrozen-monitor\",\n \"category\": \"MONITORING\",\n \"name\": \"hydrozen-monitor\",\n \"patterns\": [\n \"Hydrozen\\\\.io\\\\/\"\n ],\n \"forbidden\": []\n },\n {\n \"id\": \"kuma-monitor\",\n \"category\": \"MONITORING\",\n \"name\": \"kuma-monitor\",\n \"patterns\": [\n \"Uptime-Kuma\"\n ],\n \"forbidden\": []\n },\n {\n \"id\": \"monitorbacklinks-crawler\",\n \"category\": \"MONITORING\",\n \"name\": \"monitorbacklinks-crawler\",\n \"patterns\": [\n \"MBCrawler\"\n ],\n \"forbidden\": []\n },\n {\n \"id\": \"newrelic-monitor\",\n \"category\": \"MONITORING\",\n \"name\": \"newrelic-monitor\",\n \"patterns\": [\n \"NewRelicbot\\\\/\"\n ],\n \"forbidden\": []\n },\n {\n \"id\": \"nixstats-crawler\",\n \"category\": \"MONITORING\",\n \"name\": \"nixstats-crawler\",\n \"patterns\": [\n \"NIXStatsbot\"\n ],\n \"forbidden\": []\n },\n {\n \"id\": \"outbrain-link-checker\",\n \"category\": \"MONITORING\",\n \"name\": \"outbrain-link-checker\",\n \"patterns\": [\n \"outbrain\"\n ],\n \"forbidden\": []\n },\n {\n \"id\": \"pingdom-crawler\",\n \"category\": \"MONITORING\",\n \"name\": \"Pingdom\",\n \"patterns\": [\n \"[pP]ingdom\"\n ],\n \"forbidden\": []\n },\n {\n \"id\": \"safedns-crawler\",\n \"category\": \"MONITORING\",\n \"name\": \"safedns-crawler\",\n \"patterns\": [\n \"SafeDNSBot\"\n ],\n \"forbidden\": []\n },\n {\n \"id\": \"sentry-crawler\",\n \"category\": \"MONITORING\",\n \"name\": \"sentry-crawler\",\n \"patterns\": [\n \"(^| )sentry\\\\/\"\n ],\n \"forbidden\": []\n },\n {\n \"id\": \"sentry-uptime-monitor\",\n \"category\": \"MONITORING\",\n \"name\": \"sentry-uptime-monitor\",\n \"patterns\": [\n \"SentryUptimeBot\\\\/1\\\\.0\"\n ],\n \"forbidden\": []\n },\n {\n \"id\": \"statuscake-monitor\",\n \"category\": \"MONITORING\",\n \"name\": \"statuscake-monitor\",\n \"patterns\": [\n \"StatusCake\"\n ],\n \"forbidden\": []\n },\n {\n \"id\": \"surly-crawler\",\n \"category\": \"MONITORING\",\n \"name\": \"surly-crawler\",\n \"patterns\": [\n \"SurdotlyBot\"\n ],\n \"forbidden\": []\n },\n {\n \"id\": \"testomato-crawler\",\n \"category\": \"MONITORING\",\n \"name\": \"testomato-crawler\",\n \"patterns\": [\n \"minicrawler\"\n ],\n \"forbidden\": []\n },\n {\n \"id\": \"uptime-monitor\",\n \"category\": \"MONITORING\",\n \"name\": \"uptime-monitor\",\n \"patterns\": [\n \"www\\\\.uptime\\\\.com\"\n ],\n \"forbidden\": []\n },\n {\n \"id\": \"uptimebot-monitor\",\n \"category\": \"MONITORING\",\n \"name\": \"uptimebot-monitor\",\n \"patterns\": [\n \"Uptimebot\\\\.org\"\n ],\n \"forbidden\": []\n },\n {\n \"id\": \"uptimerobot-monitor\",\n \"category\": \"MONITORING\",\n \"name\": \"UptimeRobot\",\n \"patterns\": [\n \"UptimeRobot\"\n ],\n \"forbidden\": []\n },\n {\n \"id\": \"w3c-validator-css\",\n \"category\": \"MONITORING\",\n \"name\": \"w3c-validator-css\",\n \"patterns\": [\n \"W3C_CSS_Validator\"\n ],\n \"forbidden\": []\n },\n {\n \"id\": \"w3c-validator-feed\",\n \"category\": \"MONITORING\",\n \"name\": \"w3c-validator-feed\",\n \"patterns\": [\n \"FeedValidator\"\n ],\n \"forbidden\": []\n },\n {\n \"id\": \"w3c-validator-html\",\n \"category\": \"MONITORING\",\n \"name\": \"w3c-validator-html\",\n \"patterns\": [\n \"W3C_Validator\"\n ],\n \"forbidden\": []\n },\n {\n \"id\": \"w3c-validator-html-nu\",\n \"category\": \"MONITORING\",\n \"name\": \"w3c-validator-html-nu\",\n \"patterns\": [\n \"Validator\\\\.nu\"\n ],\n \"forbidden\": []\n },\n {\n \"id\": \"w3c-validator-i18n\",\n \"category\": \"MONITORING\",\n \"name\": \"w3c-validator-i18n\",\n \"patterns\": [\n \"W3C_I18n-Checker\"\n ],\n \"forbidden\": []\n },\n {\n \"id\": \"w3c-validator-links\",\n \"category\": \"MONITORING\",\n \"name\": \"w3c-validator-links\",\n \"patterns\": [\n \"W3C-checklink\"\n ],\n \"forbidden\": []\n },\n {\n \"id\": \"w3c-validator-mobile\",\n \"category\": \"MONITORING\",\n \"name\": \"w3c-validator-mobile\",\n \"patterns\": [\n \"W3C-mobileOK\"\n ],\n \"forbidden\": []\n },\n {\n \"id\": \"w3c-validator-unified\",\n \"category\": \"MONITORING\",\n \"name\": \"w3c-validator-unified\",\n \"patterns\": [\n \"W3C_Unicorn\"\n ],\n \"forbidden\": []\n },\n {\n \"id\": \"webpagetest-crawler\",\n \"category\": \"MONITORING\",\n \"name\": \"webpagetest-crawler\",\n \"patterns\": [\n \"(^| )PTST\\\\/\"\n ],\n \"forbidden\": []\n },\n {\n \"id\": \"xenu-crawler\",\n \"category\": \"MONITORING\",\n \"name\": \"xenu-crawler\",\n \"patterns\": [\n \"Xenu Link Sleuth\"\n ],\n \"forbidden\": []\n },\n {\n \"id\": \"zabbix-monitor\",\n \"category\": \"MONITORING\",\n \"name\": \"zabbix-monitor\",\n \"patterns\": [\n \"Zabbix\"\n ],\n \"forbidden\": []\n },\n {\n \"id\": \"academicbot-rtu\",\n \"category\": \"SCRAPER\",\n \"name\": \"academicbot-rtu\",\n \"patterns\": [\n \"AcademicBotRTU\"\n ],\n \"forbidden\": []\n },\n {\n \"id\": \"adagio-crawler\",\n \"category\": \"SCRAPER\",\n \"name\": \"adagio-crawler\",\n \"patterns\": [\n \"Adagiobot\\\\/\"\n ],\n \"forbidden\": []\n },\n {\n \"id\": \"ahrefs-site-audit\",\n \"category\": \"SCRAPER\",\n \"name\": \"ahrefs-site-audit\",\n \"patterns\": [\n \"AhrefsSiteAudit\\\\/\"\n ],\n \"forbidden\": []\n },\n {\n \"id\": \"blackboard-crawler\",\n \"category\": \"SCRAPER\",\n \"name\": \"blackboard-crawler\",\n \"patterns\": [\n \"Blackboard\"\n ],\n \"forbidden\": []\n },\n {\n \"id\": \"cispa-crawler\",\n \"category\": \"SCRAPER\",\n \"name\": \"cispa-crawler\",\n \"patterns\": [\n \"CISPA Webcrawler\"\n ],\n \"forbidden\": []\n },\n {\n \"id\": \"cloudflare-prefetch\",\n \"category\": \"SCRAPER\",\n \"name\": \"cloudflare-prefetch\",\n \"patterns\": [\n \"CloudFlare-Prefetch\"\n ],\n \"forbidden\": []\n },\n {\n \"id\": \"coda-server-fetcher\",\n \"category\": \"SCRAPER\",\n \"name\": \"coda-server-fetcher\",\n \"patterns\": [\n \"Coda-Server-Fetcher\"\n ],\n \"forbidden\": []\n },\n {\n \"id\": \"conductor-crawler\",\n \"category\": \"SCRAPER\",\n \"name\": \"conductor-crawler\",\n \"patterns\": [\n \"Caliperbot\"\n ],\n \"forbidden\": []\n },\n {\n \"id\": \"cookiehub-scan\",\n \"category\": \"SCRAPER\",\n \"name\": \"cookiehub-scan\",\n \"patterns\": [\n \"CookieHubScan\"\n ],\n \"forbidden\": []\n },\n {\n \"id\": \"curl\",\n \"category\": \"SCRAPER\",\n \"name\": \"curl\",\n \"patterns\": [\n \"^curl\"\n ],\n \"forbidden\": []\n },\n {\n \"id\": \"dareboost-crawler\",\n \"category\": \"SCRAPER\",\n \"name\": \"dareboost-crawler\",\n \"patterns\": [\n \"DareBoost\"\n ],\n \"forbidden\": []\n },\n {\n \"id\": \"dcrawl\",\n \"category\": \"SCRAPER\",\n \"name\": \"dcrawl\",\n \"patterns\": [\n \"dcrawl\"\n ],\n \"forbidden\": []\n },\n {\n \"id\": \"domainsproject-crawler\",\n \"category\": \"SCRAPER\",\n \"name\": \"domainsproject-crawler\",\n \"patterns\": [\n \"Domains Project\\\\/\"\n ],\n \"forbidden\": []\n },\n {\n \"id\": \"epfl-crawler\",\n \"category\": \"SCRAPER\",\n \"name\": \"epfl-crawler\",\n \"patterns\": [\n \"A Patent Crawler\"\n ],\n \"forbidden\": []\n },\n {\n \"id\": \"gigablast-crawler-oss\",\n \"category\": \"SCRAPER\",\n \"name\": \"gigablast-crawler-oss\",\n \"patterns\": [\n \"Gigablast\"\n ],\n \"forbidden\": []\n },\n {\n \"id\": \"go-http\",\n \"category\": \"SCRAPER\",\n \"name\": \"Go-http-client\",\n \"patterns\": [\n \"Go-http-client\"\n ],\n \"forbidden\": []\n },\n {\n \"id\": \"got\",\n \"category\": \"SCRAPER\",\n \"name\": \"got\",\n \"patterns\": [\n \"sindresorhus\\\\/got\"\n ],\n \"forbidden\": []\n },\n {\n \"id\": \"gowiki-crawler\",\n \"category\": \"SCRAPER\",\n \"name\": \"gowiki-crawler\",\n \"patterns\": [\n \"Gowikibot\"\n ],\n \"forbidden\": []\n },\n {\n \"id\": \"http-get\",\n \"category\": \"SCRAPER\",\n \"name\": \"http-get\",\n \"patterns\": [\n \"http_get\"\n ],\n \"forbidden\": []\n },\n {\n \"id\": \"httpie\",\n \"category\": \"SCRAPER\",\n \"name\": \"HTTPie\",\n \"patterns\": [\n \"^HTTPie\\\\/\"\n ],\n \"forbidden\": []\n },\n {\n \"id\": \"img2dataset\",\n \"category\": \"SCRAPER\",\n \"name\": \"img2dataset\",\n \"patterns\": [\n \"img2dataset\"\n ],\n \"forbidden\": []\n },\n {\n \"id\": \"insomnia\",\n \"category\": \"SCRAPER\",\n \"name\": \"Insomnia\",\n \"patterns\": [\n \"^[iI]nsomnia\"\n ],\n \"forbidden\": []\n },\n {\n \"id\": \"ipip-crawler\",\n \"category\": \"SCRAPER\",\n \"name\": \"ipip-crawler\",\n \"patterns\": [\n \"HTTP Banner Detection\"\n ],\n \"forbidden\": []\n },\n {\n \"id\": \"java-apache-httpclient\",\n \"category\": \"SCRAPER\",\n \"name\": \"Apache HttpClient\",\n \"patterns\": [\n \"^Apache-HttpClient\"\n ],\n \"forbidden\": []\n },\n {\n \"id\": \"java-asynchttpclient\",\n \"category\": \"SCRAPER\",\n \"name\": \"java-asynchttpclient\",\n \"patterns\": [\n \"AHC\\\\/\"\n ],\n \"forbidden\": []\n },\n {\n \"id\": \"java-crawler4j\",\n \"category\": \"SCRAPER\",\n \"name\": \"java-crawler4j\",\n \"patterns\": [\n \"crawler4j\"\n ],\n \"forbidden\": []\n },\n {\n \"id\": \"java-httpunit\",\n \"category\": \"SCRAPER\",\n \"name\": \"java-httpunit\",\n \"patterns\": [\n \"httpunit\"\n ],\n \"forbidden\": []\n },\n {\n \"id\": \"java-jersey\",\n \"category\": \"SCRAPER\",\n \"name\": \"java-jersey\",\n \"patterns\": [\n \"HttpUrlConnection\"\n ],\n \"forbidden\": []\n },\n {\n \"id\": \"java-jetty\",\n \"category\": \"SCRAPER\",\n \"name\": \"java-jetty\",\n \"patterns\": [\n \"Jetty\"\n ],\n \"forbidden\": []\n },\n {\n \"id\": \"java-okhttp\",\n \"category\": \"SCRAPER\",\n \"name\": \"OkHttp\",\n \"patterns\": [\n \"okhttp\"\n ],\n \"forbidden\": []\n },\n {\n \"id\": \"java-snacktory\",\n \"category\": \"SCRAPER\",\n \"name\": \"java-snacktory\",\n \"patterns\": [\n \"Snacktory\"\n ],\n \"forbidden\": []\n },\n {\n \"id\": \"java-stdlib\",\n \"category\": \"SCRAPER\",\n \"name\": \"Java HttpClient\",\n \"patterns\": [\n \"^Java\\\\/\"\n ],\n \"forbidden\": []\n },\n {\n \"id\": \"javascript-axios\",\n \"category\": \"SCRAPER\",\n \"name\": \"axios\",\n \"patterns\": [\n \"axios\"\n ],\n \"forbidden\": []\n },\n {\n \"id\": \"javascript-node-fetch\",\n \"category\": \"SCRAPER\",\n \"name\": \"node-fetch\",\n \"patterns\": [\n \"node-fetch\"\n ],\n \"forbidden\": []\n },\n {\n \"id\": \"l9explore\",\n \"category\": \"SCRAPER\",\n \"name\": \"l9explore\",\n \"patterns\": [\n \"l9explore\"\n ],\n \"forbidden\": []\n },\n {\n \"id\": \"law-unimi-crawler\",\n \"category\": \"SCRAPER\",\n \"name\": \"law-unimi-crawler\",\n \"patterns\": [\n \"BUbiNG\"\n ],\n \"forbidden\": []\n },\n {\n \"id\": \"leipzig-findlinks\",\n \"category\": \"SCRAPER\",\n \"name\": \"leipzig-findlinks\",\n \"patterns\": [\n \"findlink\"\n ],\n \"forbidden\": []\n },\n {\n \"id\": \"leipzig-lcc\",\n \"category\": \"SCRAPER\",\n \"name\": \"leipzig-lcc\",\n \"patterns\": [\n \"^LCC \"\n ],\n \"forbidden\": []\n },\n {\n \"id\": \"macocu-crawler\",\n \"category\": \"SCRAPER\",\n \"name\": \"macocu-crawler\",\n \"patterns\": [\n \"MaCoCu\"\n ],\n \"forbidden\": []\n },\n {\n \"id\": \"moat-crawler\",\n \"category\": \"SCRAPER\",\n \"name\": \"moat-crawler\",\n \"patterns\": [\n \"moatbot\"\n ],\n \"forbidden\": []\n },\n {\n \"id\": \"monsido-crawler\",\n \"category\": \"SCRAPER\",\n \"name\": \"monsido-crawler\",\n \"patterns\": [\n \"Monsidobot\"\n ],\n \"forbidden\": []\n },\n {\n \"id\": \"moz-site-audit\",\n \"category\": \"SCRAPER\",\n \"name\": \"RogerBot\",\n \"patterns\": [\n \"rogerbot\"\n ],\n \"forbidden\": []\n },\n {\n \"id\": \"nagios-check-http\",\n \"category\": \"SCRAPER\",\n \"name\": \"nagios-check-http\",\n \"patterns\": [\n \"check_http\"\n ],\n \"forbidden\": []\n },\n {\n \"id\": \"nict-crawler\",\n \"category\": \"SCRAPER\",\n \"name\": \"nict-crawler\",\n \"patterns\": [\n \"ICC-Crawler\"\n ],\n \"forbidden\": []\n },\n {\n \"id\": \"nmap\",\n \"category\": \"SCRAPER\",\n \"name\": \"nmap\",\n \"patterns\": [\n \"Nmap Scripting Engine\"\n ],\n \"forbidden\": []\n },\n {\n \"id\": \"nutch\",\n \"category\": \"SCRAPER\",\n \"name\": \"nutch\",\n \"patterns\": [\n \"Nutch\"\n ],\n \"forbidden\": []\n },\n {\n \"id\": \"oncrawl\",\n \"category\": \"SCRAPER\",\n \"name\": \"oncrawl\",\n \"patterns\": [\n \"OnCrawl\\\\/\"\n ],\n \"forbidden\": []\n },\n {\n \"id\": \"perl-libwww\",\n \"category\": \"SCRAPER\",\n \"name\": \"libwww-perl\",\n \"patterns\": [\n \"libwww-perl\"\n ],\n \"forbidden\": []\n },\n {\n \"id\": \"perl-pcore\",\n \"category\": \"SCRAPER\",\n \"name\": \"perl-pcore\",\n \"patterns\": [\n \"Pcore-HTTP\"\n ],\n \"forbidden\": []\n },\n {\n \"id\": \"php-curlclass\",\n \"category\": \"SCRAPER\",\n \"name\": \"php-curlclass\",\n \"patterns\": [\n \"^PHP-Curl-Class\"\n ],\n \"forbidden\": []\n },\n {\n \"id\": \"php-phpcrawl\",\n \"category\": \"SCRAPER\",\n \"name\": \"php-phpcrawl\",\n \"patterns\": [\n \"phpcrawl\"\n ],\n \"forbidden\": []\n },\n {\n \"id\": \"php-simple-scraper\",\n \"category\": \"SCRAPER\",\n \"name\": \"php-simple-scraper\",\n \"patterns\": [\n \"SimpleScraper\"\n ],\n \"forbidden\": []\n },\n {\n \"id\": \"php-simplepie\",\n \"category\": \"SCRAPER\",\n \"name\": \"php-simplepie\",\n \"patterns\": [\n \"SimplePie\"\n ],\n \"forbidden\": []\n },\n {\n \"id\": \"php-ua\",\n \"category\": \"SCRAPER\",\n \"name\": \"PHP\",\n \"patterns\": [\n \"^PHP\\\\/\"\n ],\n \"forbidden\": []\n },\n {\n \"id\": \"postman\",\n \"category\": \"SCRAPER\",\n \"name\": \"Postman\",\n \"patterns\": [\n \"PostmanRuntime\\\\/\"\n ],\n \"forbidden\": []\n },\n {\n \"id\": \"postman-loose\",\n \"category\": \"SCRAPER\",\n \"name\": \"Postman\",\n \"patterns\": [\n \"^Postman[ /]\"\n ],\n \"forbidden\": []\n },\n {\n \"id\": \"python-aiohttp\",\n \"category\": \"SCRAPER\",\n \"name\": \"python-aiohttp\",\n \"patterns\": [\n \"aiohttp\"\n ],\n \"forbidden\": []\n },\n {\n \"id\": \"python-bitbot\",\n \"category\": \"SCRAPER\",\n \"name\": \"python-bitbot\",\n \"patterns\": [\n \"BitBot\"\n ],\n \"forbidden\": []\n },\n {\n \"id\": \"python-httpx\",\n \"category\": \"SCRAPER\",\n \"name\": \"python-httpx\",\n \"patterns\": [\n \"httpx\"\n ],\n \"forbidden\": []\n },\n {\n \"id\": \"python-opengraph\",\n \"category\": \"SCRAPER\",\n \"name\": \"python-opengraph\",\n \"patterns\": [\n \"python-opengraph\"\n ],\n \"forbidden\": []\n },\n {\n \"id\": \"python-requests\",\n \"category\": \"SCRAPER\",\n \"name\": \"python-requests\",\n \"patterns\": [\n \"python-requests\"\n ],\n \"forbidden\": []\n },\n {\n \"id\": \"python-scrapy\",\n \"category\": \"SCRAPER\",\n \"name\": \"Scrapy\",\n \"patterns\": [\n \"Scrapy\"\n ],\n \"forbidden\": []\n },\n {\n \"id\": \"python-urllib\",\n \"category\": \"SCRAPER\",\n \"name\": \"python-urllib\",\n \"patterns\": [\n \"Python-urllib\"\n ],\n \"forbidden\": []\n },\n {\n \"id\": \"quantcast-crawler\",\n \"category\": \"SCRAPER\",\n \"name\": \"quantcast-crawler\",\n \"patterns\": [\n \"Quantcastbot\\\\/\"\n ],\n \"forbidden\": []\n },\n {\n \"id\": \"ruby\",\n \"category\": \"SCRAPER\",\n \"name\": \"Ruby\",\n \"patterns\": [\n \"^Ruby\"\n ],\n \"forbidden\": []\n },\n {\n \"id\": \"ruby-metainspector\",\n \"category\": \"SCRAPER\",\n \"name\": \"ruby-metainspector\",\n \"patterns\": [\n \"MetaInspector\"\n ],\n \"forbidden\": []\n },\n {\n \"id\": \"screamingfrog-crawler\",\n \"category\": \"SCRAPER\",\n \"name\": \"screamingfrog-crawler\",\n \"patterns\": [\n \"Screaming Frog SEO Spider\"\n ],\n \"forbidden\": []\n },\n {\n \"id\": \"semanticscholar-crawler\",\n \"category\": \"SCRAPER\",\n \"name\": \"SemanticScholarBot\",\n \"patterns\": [\n \"SemanticScholarBot\"\n ],\n \"forbidden\": []\n },\n {\n \"id\": \"sistrix-crawler\",\n \"category\": \"SCRAPER\",\n \"name\": \"sistrix-crawler\",\n \"patterns\": [\n \"(sistrix|SISTRIX) [cC]rawler\"\n ],\n \"forbidden\": []\n },\n {\n \"id\": \"sitebulb\",\n \"category\": \"SCRAPER\",\n \"name\": \"sitebulb\",\n \"patterns\": [\n \"sitebulb\"\n ],\n \"forbidden\": []\n },\n {\n \"id\": \"stripe-crawler\",\n \"category\": \"SCRAPER\",\n \"name\": \"stripe-crawler\",\n \"patterns\": [\n \"Stripebot\\\\/\"\n ],\n \"forbidden\": []\n },\n {\n \"id\": \"summaly-crawler\",\n \"category\": \"SCRAPER\",\n \"name\": \"summaly-crawler\",\n \"patterns\": [\n \"SummalyBot\"\n ],\n \"forbidden\": []\n },\n {\n \"id\": \"turnitin-crawler\",\n \"category\": \"SCRAPER\",\n \"name\": \"turnitin-crawler\",\n \"patterns\": [\n \"Turnitin\"\n ],\n \"forbidden\": []\n },\n {\n \"id\": \"utexas-crawler\",\n \"category\": \"SCRAPER\",\n \"name\": \"utexas-crawler\",\n \"patterns\": [\n \"UT-Dorkbot\"\n ],\n \"forbidden\": []\n },\n {\n \"id\": \"wget\",\n \"category\": \"SCRAPER\",\n \"name\": \"wget\",\n \"patterns\": [\n \"[wW]get\"\n ],\n \"forbidden\": []\n },\n {\n \"id\": \"yamanalab-crawler\",\n \"category\": \"SCRAPER\",\n \"name\": \"yamanalab-crawler\",\n \"patterns\": [\n \"Sonic\"\n ],\n \"forbidden\": []\n },\n {\n \"id\": \"yext-bot\",\n \"category\": \"SCRAPER\",\n \"name\": \"yext-bot\",\n \"patterns\": [\n \"YextBot\"\n ],\n \"forbidden\": []\n },\n {\n \"id\": \"zgrab\",\n \"category\": \"SCRAPER\",\n \"name\": \"zgrab\",\n \"patterns\": [\n \"zgrab\"\n ],\n \"forbidden\": []\n },\n {\n \"id\": \"addsearch-crawler\",\n \"category\": \"SEARCH_ENGINE\",\n \"name\": \"addsearch-crawler\",\n \"patterns\": [\n \"AddSearchBot\"\n ],\n \"forbidden\": []\n },\n {\n \"id\": \"ahrefs-crawler\",\n \"category\": \"SEARCH_ENGINE\",\n \"name\": \"AhrefsBot\",\n \"patterns\": [\n \"AhrefsBot\\\\/\"\n ],\n \"forbidden\": []\n },\n {\n \"id\": \"alexandria-crawler\",\n \"category\": \"SEARCH_ENGINE\",\n \"name\": \"alexandria-crawler\",\n \"patterns\": [\n \"AlexandriaOrgBot\"\n ],\n \"forbidden\": []\n },\n {\n \"id\": \"algolia-crawler\",\n \"category\": \"SEARCH_ENGINE\",\n \"name\": \"algolia-crawler\",\n \"patterns\": [\n \"Algolia Crawler\\\\/\"\n ],\n \"forbidden\": []\n },\n {\n \"id\": \"amazon-adbot\",\n \"category\": \"SEARCH_ENGINE\",\n \"name\": \"amazon-adbot\",\n \"patterns\": [\n \"AmazonAdBot\\\\/\"\n ],\n \"forbidden\": []\n },\n {\n \"id\": \"amazon-alexa-crawler\",\n \"category\": \"SEARCH_ENGINE\",\n \"name\": \"amazon-alexa-crawler\",\n \"patterns\": [\n \"exabot\"\n ],\n \"forbidden\": []\n },\n {\n \"id\": \"amazon-cloudfront\",\n \"category\": \"SEARCH_ENGINE\",\n \"name\": \"amazon-cloudfront\",\n \"patterns\": [\n \"Amazon CloudFront\"\n ],\n \"forbidden\": []\n },\n {\n \"id\": \"amazon-crawler\",\n \"category\": \"SEARCH_ENGINE\",\n \"name\": \"AmazonBot\",\n \"patterns\": [\n \"Amazonbot\"\n ],\n \"forbidden\": []\n },\n {\n \"id\": \"apple-crawler\",\n \"category\": \"SEARCH_ENGINE\",\n \"name\": \"Applebot\",\n \"patterns\": [\n \"Applebot\"\n ],\n \"forbidden\": []\n },\n {\n \"id\": \"apple-feedfetcher\",\n \"category\": \"SEARCH_ENGINE\",\n \"name\": \"apple-feedfetcher\",\n \"patterns\": [\n \"i[Tt][Mm][Ss]\"\n ],\n \"forbidden\": []\n },\n {\n \"id\": \"archiveorg-archiver\",\n \"category\": \"SEARCH_ENGINE\",\n \"name\": \"ArchiveOrgBot\",\n \"patterns\": [\n \"archive\\\\.org_bot\"\n ],\n \"forbidden\": []\n },\n {\n \"id\": \"ask-crawler\",\n \"category\": \"SEARCH_ENGINE\",\n \"name\": \"ask-crawler\",\n \"patterns\": [\n \"Teoma\"\n ],\n \"forbidden\": []\n },\n {\n \"id\": \"avira-crawler\",\n \"category\": \"SEARCH_ENGINE\",\n \"name\": \"avira-crawler\",\n \"patterns\": [\n \"SafeSearch microdata crawler\"\n ],\n \"forbidden\": []\n },\n {\n \"id\": \"awario-crawler-rss\",\n \"category\": \"SEARCH_ENGINE\",\n \"name\": \"awario-crawler-rss\",\n \"patterns\": [\n \"AwarioRssBot\"\n ],\n \"forbidden\": []\n },\n {\n \"id\": \"baidu-crawler\",\n \"category\": \"SEARCH_ENGINE\",\n \"name\": \"Baiduspider\",\n \"patterns\": [\n \"Baiduspider\"\n ],\n \"forbidden\": []\n },\n {\n \"id\": \"bazqux-feedfetcher\",\n \"category\": \"SEARCH_ENGINE\",\n \"name\": \"bazqux-feedfetcher\",\n \"patterns\": [\n \"BazQux\"\n ],\n \"forbidden\": []\n },\n {\n \"id\": \"bing-ads\",\n \"category\": \"SEARCH_ENGINE\",\n \"name\": \"bing-ads\",\n \"patterns\": [\n \"Adidxbot\"\n ],\n \"forbidden\": []\n },\n {\n \"id\": \"bing-crawler\",\n \"category\": \"SEARCH_ENGINE\",\n \"name\": \"Bingbot\",\n \"patterns\": [\n \"bingbot\"\n ],\n \"forbidden\": []\n },\n {\n \"id\": \"bing-office-store\",\n \"category\": \"SEARCH_ENGINE\",\n \"name\": \"bing-office-store\",\n \"patterns\": [\n \"officestorebot\"\n ],\n \"forbidden\": []\n },\n {\n \"id\": \"blogtraffic-feedfetcher\",\n \"category\": \"SEARCH_ENGINE\",\n \"name\": \"blogtraffic-feedfetcher\",\n \"patterns\": [\n \"BlogTraffic\\\\/\\\\d\\\\.\\\\d+ Feed-Fetcher\"\n ],\n \"forbidden\": []\n },\n {\n \"id\": \"cloudflare-archiver\",\n \"category\": \"SEARCH_ENGINE\",\n \"name\": \"cloudflare-archiver\",\n \"patterns\": [\n \"CloudFlare-AlwaysOnline\"\n ],\n \"forbidden\": []\n },\n {\n \"id\": \"commoncrawl-crawler\",\n \"category\": \"SEARCH_ENGINE\",\n \"name\": \"CommonCrawlBot\",\n \"patterns\": [\n \"CCBot\"\n ],\n \"forbidden\": []\n },\n {\n \"id\": \"duckduckgo-crawler\",\n \"category\": \"SEARCH_ENGINE\",\n \"name\": \"DuckDuckBot\",\n \"patterns\": [\n \"DuckDuckBot\"\n ],\n \"forbidden\": []\n },\n {\n \"id\": \"entireweb-crawler\",\n \"category\": \"SEARCH_ENGINE\",\n \"name\": \"entireweb-crawler\",\n \"patterns\": [\n \"speedy\"\n ],\n \"forbidden\": []\n },\n {\n \"id\": \"ezid-crawler\",\n \"category\": \"SEARCH_ENGINE\",\n \"name\": \"ezid-crawler\",\n \"patterns\": [\n \"EZID\"\n ],\n \"forbidden\": []\n },\n {\n \"id\": \"feedbin-crawler\",\n \"category\": \"SEARCH_ENGINE\",\n \"name\": \"feedbin-crawler\",\n \"patterns\": [\n \"Feedbin\"\n ],\n \"forbidden\": []\n },\n {\n \"id\": \"feedly-feedfetcher\",\n \"category\": \"SEARCH_ENGINE\",\n \"name\": \"feedly-feedfetcher\",\n \"patterns\": [\n \"Feedly\"\n ],\n \"forbidden\": []\n },\n {\n \"id\": \"feedspot-feedfetcher\",\n \"category\": \"SEARCH_ENGINE\",\n \"name\": \"feedspot-feedfetcher\",\n \"patterns\": [\n \"Feedspot\"\n ],\n \"forbidden\": []\n },\n {\n \"id\": \"freshrss-feedfetcher\",\n \"category\": \"SEARCH_ENGINE\",\n \"name\": \"freshrss-feedfetcher\",\n \"patterns\": [\n \"FreshRSS\"\n ],\n \"forbidden\": []\n },\n {\n \"id\": \"g2reader-crawler\",\n \"category\": \"SEARCH_ENGINE\",\n \"name\": \"g2reader-crawler\",\n \"patterns\": [\n \"g2reader-bot\"\n ],\n \"forbidden\": []\n },\n {\n \"id\": \"geedo-crawler\",\n \"category\": \"SEARCH_ENGINE\",\n \"name\": \"geedo-crawler\",\n \"patterns\": [\n \"GeedoBot\"\n ],\n \"forbidden\": []\n },\n {\n \"id\": \"geedo-crawler-products\",\n \"category\": \"SEARCH_ENGINE\",\n \"name\": \"geedo-crawler-products\",\n \"patterns\": [\n \"GeedoProductSearch\"\n ],\n \"forbidden\": []\n },\n {\n \"id\": \"google-ads-conversions\",\n \"category\": \"SEARCH_ENGINE\",\n \"name\": \"google-ads-conversions\",\n \"patterns\": [\n \"Google-Ads-Conversions\"\n ],\n \"forbidden\": []\n },\n {\n \"id\": \"google-adsbot\",\n \"category\": \"SEARCH_ENGINE\",\n \"name\": \"AdsBotGoogle\",\n \"patterns\": [\n \"AdsBot-Google([^-]|$)\"\n ],\n \"forbidden\": []\n },\n {\n \"id\": \"google-adsbot-mobile\",\n \"category\": \"SEARCH_ENGINE\",\n \"name\": \"GoogleAdsBot\",\n \"patterns\": [\n \"AdsBot-Google-Mobile\"\n ],\n \"forbidden\": []\n },\n {\n \"id\": \"google-adsense\",\n \"category\": \"SEARCH_ENGINE\",\n \"name\": \"MediapartnersGoogle\",\n \"patterns\": [\n \"Mediapartners-Google\"\n ],\n \"forbidden\": []\n },\n {\n \"id\": \"google-adsense-googlebot\",\n \"category\": \"SEARCH_ENGINE\",\n \"name\": \"google-adsense-googlebot\",\n \"patterns\": [\n \"Mediapartners \\\\(Googlebot\\\\)\"\n ],\n \"forbidden\": []\n },\n {\n \"id\": \"google-adwords\",\n \"category\": \"SEARCH_ENGINE\",\n \"name\": \"google-adwords\",\n \"patterns\": [\n \"Google-Adwords-Instant\"\n ],\n \"forbidden\": []\n },\n {\n \"id\": \"google-appengine\",\n \"category\": \"SEARCH_ENGINE\",\n \"name\": \"google-appengine\",\n \"patterns\": [\n \"AppEngine-Google\"\n ],\n \"forbidden\": []\n },\n {\n \"id\": \"google-crawler\",\n \"category\": \"SEARCH_ENGINE\",\n \"name\": \"Googlebot\",\n \"patterns\": [\n \"Googlebot\\\\/\"\n ],\n \"forbidden\": []\n },\n {\n \"id\": \"google-crawler-cloudvertex\",\n \"category\": \"SEARCH_ENGINE\",\n \"name\": \"google-crawler-cloudvertex\",\n \"patterns\": [\n \"Google-CloudVertexBot\"\n ],\n \"forbidden\": []\n },\n {\n \"id\": \"google-crawler-image\",\n \"category\": \"SEARCH_ENGINE\",\n \"name\": \"Googlebot-Image\",\n \"patterns\": [\n \"Googlebot-Image\"\n ],\n \"forbidden\": []\n },\n {\n \"id\": \"google-crawler-mobile\",\n \"category\": \"SEARCH_ENGINE\",\n \"name\": \"google-crawler-mobile\",\n \"patterns\": [\n \"Googlebot-Mobile\"\n ],\n \"forbidden\": []\n },\n {\n \"id\": \"google-crawler-news\",\n \"category\": \"SEARCH_ENGINE\",\n \"name\": \"Googlebot-News\",\n \"patterns\": [\n \"Googlebot-News\"\n ],\n \"forbidden\": []\n },\n {\n \"id\": \"google-crawler-other\",\n \"category\": \"SEARCH_ENGINE\",\n \"name\": \"google-crawler-other\",\n \"patterns\": [\n \"GoogleOther\"\n ],\n \"forbidden\": []\n },\n {\n \"id\": \"google-crawler-safety\",\n \"category\": \"SEARCH_ENGINE\",\n \"name\": \"google-crawler-safety\",\n \"patterns\": [\n \"Google-Safety\"\n ],\n \"forbidden\": []\n },\n {\n \"id\": \"google-crawler-store\",\n \"category\": \"SEARCH_ENGINE\",\n \"name\": \"StorebotGoogle\",\n \"patterns\": [\n \"Storebot-Google\"\n ],\n \"forbidden\": []\n },\n {\n \"id\": \"google-crawler-video\",\n \"category\": \"SEARCH_ENGINE\",\n \"name\": \"Googlebot-Video\",\n \"patterns\": [\n \"Googlebot-Video\"\n ],\n \"forbidden\": []\n },\n {\n \"id\": \"google-feedfetcher\",\n \"category\": \"SEARCH_ENGINE\",\n \"name\": \"google-feedfetcher\",\n \"patterns\": [\n \"Feedfetcher-Google\"\n ],\n \"forbidden\": []\n },\n {\n \"id\": \"google-inspection-tool\",\n \"category\": \"SEARCH_ENGINE\",\n \"name\": \"google-inspection-tool\",\n \"patterns\": [\n \"Google-InspectionTool\"\n ],\n \"forbidden\": []\n },\n {\n \"id\": \"google-lighthouse\",\n \"category\": \"SEARCH_ENGINE\",\n \"name\": \"google-lighthouse\",\n \"patterns\": [\n \"Chrome-Lighthouse\"\n ],\n \"forbidden\": []\n },\n {\n \"id\": \"google-physical-web\",\n \"category\": \"SEARCH_ENGINE\",\n \"name\": \"google-physical-web\",\n \"patterns\": [\n \"Google-PhysicalWeb\"\n ],\n \"forbidden\": []\n },\n {\n \"id\": \"google-push-notifications\",\n \"category\": \"SEARCH_ENGINE\",\n \"name\": \"APIsGoogle\",\n \"patterns\": [\n \"APIs-Google\"\n ],\n \"forbidden\": []\n },\n {\n \"id\": \"google-read-aloud\",\n \"category\": \"SEARCH_ENGINE\",\n \"name\": \"google-read-aloud\",\n \"patterns\": [\n \"Google-Read-Aloud\"\n ],\n \"forbidden\": []\n },\n {\n \"id\": \"google-xrawler\",\n \"category\": \"SEARCH_ENGINE\",\n \"name\": \"google-xrawler\",\n \"patterns\": [\n \"google-xrawler\"\n ],\n \"forbidden\": []\n },\n {\n \"id\": \"iask-crawler\",\n \"category\": \"SEARCH_ENGINE\",\n \"name\": \"iask-crawler\",\n \"patterns\": [\n \"iaskspider\"\n ],\n \"forbidden\": []\n },\n {\n \"id\": \"inoreader-aggregator\",\n \"category\": \"SEARCH_ENGINE\",\n \"name\": \"inoreader-aggregator\",\n \"patterns\": [\n \"inoreader\"\n ],\n \"forbidden\": []\n },\n {\n \"id\": \"internetarchive-crawler-oss\",\n \"category\": \"SEARCH_ENGINE\",\n \"name\": \"internetarchive-crawler-oss\",\n \"patterns\": [\n \"heritrix\"\n ],\n \"forbidden\": []\n },\n {\n \"id\": \"linguee-crawler\",\n \"category\": \"SEARCH_ENGINE\",\n \"name\": \"linguee-crawler\",\n \"patterns\": [\n \"Linguee Bot\"\n ],\n \"forbidden\": []\n },\n {\n \"id\": \"majestic-crawler\",\n \"category\": \"SEARCH_ENGINE\",\n \"name\": \"majestic-crawler\",\n \"patterns\": [\n \"MJ12bot\"\n ],\n \"forbidden\": []\n },\n {\n \"id\": \"marginalia-crawler\",\n \"category\": \"SEARCH_ENGINE\",\n \"name\": \"marginalia-crawler\",\n \"patterns\": [\n \"search\\\\.marginalia\\\\.nu\"\n ],\n \"forbidden\": []\n },\n {\n \"id\": \"meta-crawler\",\n \"category\": \"SEARCH_ENGINE\",\n \"name\": \"meta-crawler\",\n \"patterns\": [\n \"[Mm]eta-[Ee]xternal[Aa]gent\"\n ],\n \"forbidden\": []\n },\n {\n \"id\": \"meta-externalads\",\n \"category\": \"SEARCH_ENGINE\",\n \"name\": \"meta-externalads\",\n \"patterns\": [\n \"meta-externalads\\\\/\"\n ],\n \"forbidden\": []\n },\n {\n \"id\": \"microsoft-research-crawler\",\n \"category\": \"SEARCH_ENGINE\",\n \"name\": \"microsoft-research-crawler\",\n \"patterns\": [\n \"msrbot\"\n ],\n \"forbidden\": []\n },\n {\n \"id\": \"miniflux-feedfetcher\",\n \"category\": \"SEARCH_ENGINE\",\n \"name\": \"miniflux-feedfetcher\",\n \"patterns\": [\n \"Miniflux\\\\/\"\n ],\n \"forbidden\": []\n },\n {\n \"id\": \"mojeek-crawler\",\n \"category\": \"SEARCH_ENGINE\",\n \"name\": \"mojeek-crawler\",\n \"patterns\": [\n \"MojeekBot\\\\/\"\n ],\n \"forbidden\": []\n },\n {\n \"id\": \"msn-crawler\",\n \"category\": \"SEARCH_ENGINE\",\n \"name\": \"MsnBot\",\n \"patterns\": [\n \"msnbot\"\n ],\n \"forbidden\": []\n },\n {\n \"id\": \"naver-crawler-rss\",\n \"category\": \"SEARCH_ENGINE\",\n \"name\": \"naver-crawler-rss\",\n \"patterns\": [\n \"NAVER Blog Rssbot\"\n ],\n \"forbidden\": []\n },\n {\n \"id\": \"netestate-crawler\",\n \"category\": \"SEARCH_ENGINE\",\n \"name\": \"netestate-crawler\",\n \"patterns\": [\n \"netEstate NE Crawler\"\n ],\n \"forbidden\": []\n },\n {\n \"id\": \"newsblur-aggregator\",\n \"category\": \"SEARCH_ENGINE\",\n \"name\": \"newsblur-aggregator\",\n \"patterns\": [\n \"NewsBlur\"\n ],\n \"forbidden\": []\n },\n {\n \"id\": \"nicecrawler-archive\",\n \"category\": \"SEARCH_ENGINE\",\n \"name\": \"nicecrawler-archive\",\n \"patterns\": [\n \"Nicecrawler\"\n ],\n \"forbidden\": []\n },\n {\n \"id\": \"openai-crawler-search\",\n \"category\": \"SEARCH_ENGINE\",\n \"name\": \"OAISearchBot\",\n \"patterns\": [\n \"OAI-SearchBot\"\n ],\n \"forbidden\": []\n },\n {\n \"id\": \"petalsearch-crawler\",\n \"category\": \"SEARCH_ENGINE\",\n \"name\": \"petalsearch-crawler\",\n \"patterns\": [\n \"PetalBot\"\n ],\n \"forbidden\": []\n },\n {\n \"id\": \"pipl-crawler\",\n \"category\": \"SEARCH_ENGINE\",\n \"name\": \"pipl-crawler\",\n \"patterns\": [\n \"PiplBot\"\n ],\n \"forbidden\": []\n },\n {\n \"id\": \"pocket-crawler\",\n \"category\": \"SEARCH_ENGINE\",\n \"name\": \"pocket-crawler\",\n \"patterns\": [\n \"PocketParser\"\n ],\n \"forbidden\": []\n },\n {\n \"id\": \"qwant-crawler\",\n \"category\": \"SEARCH_ENGINE\",\n \"name\": \"qwant-crawler\",\n \"patterns\": [\n \"Qwantify\"\n ],\n \"forbidden\": []\n },\n {\n \"id\": \"refind-crawler\",\n \"category\": \"SEARCH_ENGINE\",\n \"name\": \"refind-crawler\",\n \"patterns\": [\n \"Refindbot\"\n ],\n \"forbidden\": []\n },\n {\n \"id\": \"rssbot-feedfetcher\",\n \"category\": \"SEARCH_ENGINE\",\n \"name\": \"rssbot-feedfetcher\",\n \"patterns\": [\n \"rssbot\\\\/\"\n ],\n \"forbidden\": []\n },\n {\n \"id\": \"rssing-crawler\",\n \"category\": \"SEARCH_ENGINE\",\n \"name\": \"rssing-crawler\",\n \"patterns\": [\n \"RSSingBot\"\n ],\n \"forbidden\": []\n },\n {\n \"id\": \"rssmicro-feedfetcher\",\n \"category\": \"SEARCH_ENGINE\",\n \"name\": \"rssmicro-feedfetcher\",\n \"patterns\": [\n \"Atom Feed Robot\"\n ],\n \"forbidden\": []\n },\n {\n \"id\": \"seekport-crawler\",\n \"category\": \"SEARCH_ENGINE\",\n \"name\": \"seekport-crawler\",\n \"patterns\": [\n \"Seekport\"\n ],\n \"forbidden\": []\n },\n {\n \"id\": \"serendeputy-crawler\",\n \"category\": \"SEARCH_ENGINE\",\n \"name\": \"serendeputy-crawler\",\n \"patterns\": [\n \"SerendeputyBot\"\n ],\n \"forbidden\": []\n },\n {\n \"id\": \"startme-crawler\",\n \"category\": \"SEARCH_ENGINE\",\n \"name\": \"startme-crawler\",\n \"patterns\": [\n \"startmebot\\\\/\"\n ],\n \"forbidden\": []\n },\n {\n \"id\": \"stract-crawler\",\n \"category\": \"SEARCH_ENGINE\",\n \"name\": \"stract-crawler\",\n \"patterns\": [\n \"StractBot\"\n ],\n \"forbidden\": []\n },\n {\n \"id\": \"superfeedr-crawler\",\n \"category\": \"SEARCH_ENGINE\",\n \"name\": \"superfeedr-crawler\",\n \"patterns\": [\n \"Superfeedr\"\n ],\n \"forbidden\": []\n },\n {\n \"id\": \"theoldreader-crawler\",\n \"category\": \"SEARCH_ENGINE\",\n \"name\": \"theoldreader-crawler\",\n \"patterns\": [\n \"theoldreader\\\\.com\"\n ],\n \"forbidden\": []\n },\n {\n \"id\": \"ttrss-feedfetcher\",\n \"category\": \"SEARCH_ENGINE\",\n \"name\": \"ttrss-feedfetcher\",\n \"patterns\": [\n \"Tiny Tiny RSS\"\n ],\n \"forbidden\": []\n },\n {\n \"id\": \"webarchive-crawler\",\n \"category\": \"SEARCH_ENGINE\",\n \"name\": \"webarchive-crawler\",\n \"patterns\": [\n \"web-archive-net\\\\.com\\\\.bot\"\n ],\n \"forbidden\": []\n },\n {\n \"id\": \"webzio-crawler\",\n \"category\": \"SEARCH_ENGINE\",\n \"name\": \"webzio-crawler\",\n \"patterns\": [\n \"webzio\\\\s\"\n ],\n \"forbidden\": []\n },\n {\n \"id\": \"wellknown-crawler\",\n \"category\": \"SEARCH_ENGINE\",\n \"name\": \"wellknown-crawler\",\n \"patterns\": [\n \"WellKnownBot\"\n ],\n \"forbidden\": []\n },\n {\n \"id\": \"wordpress-crawler-rss\",\n \"category\": \"SEARCH_ENGINE\",\n \"name\": \"wordpress-crawler-rss\",\n \"patterns\": [\n \"feedbot\"\n ],\n \"forbidden\": []\n },\n {\n \"id\": \"yacy-crawler\",\n \"category\": \"SEARCH_ENGINE\",\n \"name\": \"yacy-crawler\",\n \"patterns\": [\n \"yacybot\"\n ],\n \"forbidden\": []\n },\n {\n \"id\": \"yahoo-crawler\",\n \"category\": \"SEARCH_ENGINE\",\n \"name\": \"SlurpBot\",\n \"patterns\": [\n \"Slurp\"\n ],\n \"forbidden\": []\n },\n {\n \"id\": \"yahoo-crawler-japan\",\n \"category\": \"SEARCH_ENGINE\",\n \"name\": \"yahoo-crawler-japan\",\n \"patterns\": [\n \"Y!J\"\n ],\n \"forbidden\": []\n },\n {\n \"id\": \"yandex-crawler\",\n \"category\": \"SEARCH_ENGINE\",\n \"name\": \"YandexBot\",\n \"patterns\": [\n \"yandex\\\\.com\\\\/bots\"\n ],\n \"forbidden\": []\n },\n {\n \"id\": \"yandex-crawler-javascript\",\n \"category\": \"SEARCH_ENGINE\",\n \"name\": \"yandex-crawler-javascript\",\n \"patterns\": [\n \"YandexRenderResourcesBot\\\\/\"\n ],\n \"forbidden\": []\n },\n {\n \"id\": \"yandex-loose\",\n \"category\": \"SEARCH_ENGINE\",\n \"name\": \"YandexBot\",\n \"patterns\": [\n \"YandexBot\"\n ],\n \"forbidden\": []\n },\n {\n \"id\": \"adyen-webhook\",\n \"category\": \"SOCIAL\",\n \"name\": \"adyen-webhook\",\n \"patterns\": [\n \"Adyen HttpClient\"\n ],\n \"forbidden\": []\n },\n {\n \"id\": \"bing-preview\",\n \"category\": \"SOCIAL\",\n \"name\": \"BingPreviewBot\",\n \"patterns\": [\n \"BingPreview\\\\/\"\n ],\n \"forbidden\": []\n },\n {\n \"id\": \"bitly-crawler\",\n \"category\": \"SOCIAL\",\n \"name\": \"bitly-crawler\",\n \"patterns\": [\n \"bitlybot\"\n ],\n \"forbidden\": []\n },\n {\n \"id\": \"digg-crawler\",\n \"category\": \"SOCIAL\",\n \"name\": \"digg-crawler\",\n \"patterns\": [\n \"Digg Deeper\"\n ],\n \"forbidden\": []\n },\n {\n \"id\": \"discord-crawler\",\n \"category\": \"SOCIAL\",\n \"name\": \"Discordbot\",\n \"patterns\": [\n \"Discordbot\"\n ],\n \"forbidden\": []\n },\n {\n \"id\": \"duckduckgo-crawler-favicons\",\n \"category\": \"SOCIAL\",\n \"name\": \"duckduckgo-crawler-favicons\",\n \"patterns\": [\n \"DuckDuckGo-Favicons-Bot\"\n ],\n \"forbidden\": []\n },\n {\n \"id\": \"embedly-crawler\",\n \"category\": \"SOCIAL\",\n \"name\": \"EmbedlyBot\",\n \"patterns\": [\n \"Embedly\"\n ],\n \"forbidden\": []\n },\n {\n \"id\": \"everyonesocial-crawler\",\n \"category\": \"SOCIAL\",\n \"name\": \"everyonesocial-crawler\",\n \"patterns\": [\n \"EveryoneSocialBot\"\n ],\n \"forbidden\": []\n },\n {\n \"id\": \"facebook-catalog\",\n \"category\": \"SOCIAL\",\n \"name\": \"facebook-catalog\",\n \"patterns\": [\n \"facebookcatalog\\\\/\"\n ],\n \"forbidden\": []\n },\n {\n \"id\": \"facebook-crawler\",\n \"category\": \"SOCIAL\",\n \"name\": \"FacebookBot\",\n \"patterns\": [\n \"Face(book){0,1}[Bb]ot\"\n ],\n \"forbidden\": [\n \"facebookexternalhit\",\n \"Twitterbot\"\n ]\n },\n {\n \"id\": \"facebook-share-crawler\",\n \"category\": \"SOCIAL\",\n \"name\": \"Facebook\",\n \"patterns\": [\n \"facebookexternalhit\"\n ],\n \"forbidden\": [\n \"Twitterbot\",\n \"Facebot\"\n ]\n },\n {\n \"id\": \"flipboard-proxy\",\n \"category\": \"SOCIAL\",\n \"name\": \"flipboard-proxy\",\n \"patterns\": [\n \"FlipboardProxy\"\n ],\n \"forbidden\": []\n },\n {\n \"id\": \"google-favicon\",\n \"category\": \"SOCIAL\",\n \"name\": \"google-favicon\",\n \"patterns\": [\n \"Google Favicon\"\n ],\n \"forbidden\": []\n },\n {\n \"id\": \"google-preview\",\n \"category\": \"SOCIAL\",\n \"name\": \"google-preview\",\n \"patterns\": [\n \"Google Web Preview\"\n ],\n \"forbidden\": []\n },\n {\n \"id\": \"google-web-snippet\",\n \"category\": \"SOCIAL\",\n \"name\": \"google-web-snippet\",\n \"patterns\": [\n \"developers\\\\.google\\\\.com\\\\/\\\\+\\\\/web\\\\/snippet\"\n ],\n \"forbidden\": []\n },\n {\n \"id\": \"groupme-crawler\",\n \"category\": \"SOCIAL\",\n \"name\": \"groupme-crawler\",\n \"patterns\": [\n \"GroupMeBot\"\n ],\n \"forbidden\": []\n },\n {\n \"id\": \"iframely-preview\",\n \"category\": \"SOCIAL\",\n \"name\": \"iframely-preview\",\n \"patterns\": [\n \"Iframely\"\n ],\n \"forbidden\": []\n },\n {\n \"id\": \"imessage-preview\",\n \"category\": \"SOCIAL\",\n \"name\": \"imessage-preview\",\n \"patterns\": [\n \"facebookexternalhit\",\n \"Twitterbot\",\n \"Facebot\"\n ],\n \"forbidden\": []\n },\n {\n \"id\": \"irc-archivebot\",\n \"category\": \"SOCIAL\",\n \"name\": \"ArchiveBot\",\n \"patterns\": [\n \"ArchiveBot\"\n ],\n \"forbidden\": []\n },\n {\n \"id\": \"keybase-bot\",\n \"category\": \"SOCIAL\",\n \"name\": \"keybase-bot\",\n \"patterns\": [\n \"KeybaseBot\"\n ],\n \"forbidden\": []\n },\n {\n \"id\": \"lemmy-crawler\",\n \"category\": \"SOCIAL\",\n \"name\": \"lemmy-crawler\",\n \"patterns\": [\n \"Lemmy\"\n ],\n \"forbidden\": []\n },\n {\n \"id\": \"linkarchiver\",\n \"category\": \"SOCIAL\",\n \"name\": \"linkarchiver\",\n \"patterns\": [\n \"LinkArchiver\"\n ],\n \"forbidden\": []\n },\n {\n \"id\": \"linkedin-crawler\",\n \"category\": \"SOCIAL\",\n \"name\": \"LinkedInBot\",\n \"patterns\": [\n \"LinkedInBot\"\n ],\n \"forbidden\": []\n },\n {\n \"id\": \"mastodon-crawler\",\n \"category\": \"SOCIAL\",\n \"name\": \"MastodonBot\",\n \"patterns\": [\n \"Mastodon\"\n ],\n \"forbidden\": []\n },\n {\n \"id\": \"meta-crawler-user\",\n \"category\": \"SOCIAL\",\n \"name\": \"meta-crawler-user\",\n \"patterns\": [\n \"meta-externalfetcher\"\n ],\n \"forbidden\": []\n },\n {\n \"id\": \"microsoft-preview\",\n \"category\": \"SOCIAL\",\n \"name\": \"microsoft-preview\",\n \"patterns\": [\n \"MicrosoftPreview\\\\/\"\n ],\n \"forbidden\": []\n },\n {\n \"id\": \"neticle-crawler\",\n \"category\": \"SOCIAL\",\n \"name\": \"neticle-crawler\",\n \"patterns\": [\n \"Neticle Crawler\"\n ],\n \"forbidden\": []\n },\n {\n \"id\": \"pagepeeker-crawler\",\n \"category\": \"SOCIAL\",\n \"name\": \"pagepeeker-crawler\",\n \"patterns\": [\n \"PagePeeker\\\\/\"\n ],\n \"forbidden\": []\n },\n {\n \"id\": \"pinterest-crawler\",\n \"category\": \"SOCIAL\",\n \"name\": \"pinterest-crawler\",\n \"patterns\": [\n \"Pinterest(bot)?\\\\/\"\n ],\n \"forbidden\": []\n },\n {\n \"id\": \"pintrest-crawler\",\n \"category\": \"SOCIAL\",\n \"name\": \"PinterestBot\",\n \"patterns\": [\n \"pinterest\\\\.com\\\\/bot\"\n ],\n \"forbidden\": []\n },\n {\n \"id\": \"reddit-crawler\",\n \"category\": \"SOCIAL\",\n \"name\": \"RedditBot\",\n \"patterns\": [\n \"redditbot\"\n ],\n \"forbidden\": []\n },\n {\n \"id\": \"skype-preview\",\n \"category\": \"SOCIAL\",\n \"name\": \"skype-preview\",\n \"patterns\": [\n \"SkypeUriPreview\"\n ],\n \"forbidden\": []\n },\n {\n \"id\": \"slack-crawler\",\n \"category\": \"SOCIAL\",\n \"name\": \"Slackbot\",\n \"patterns\": [\n \"Slackbot\"\n ],\n \"forbidden\": []\n },\n {\n \"id\": \"slack-image-proxy\",\n \"category\": \"SOCIAL\",\n \"name\": \"slack-image-proxy\",\n \"patterns\": [\n \"Slack-ImgProxy\"\n ],\n \"forbidden\": []\n },\n {\n \"id\": \"snap-preview\",\n \"category\": \"SOCIAL\",\n \"name\": \"snap-preview\",\n \"patterns\": [\n \"Snap URL Preview Service\"\n ],\n \"forbidden\": []\n },\n {\n \"id\": \"steam-preview\",\n \"category\": \"SOCIAL\",\n \"name\": \"ValveSteamBot\",\n \"patterns\": [\n \"Valve\\\\/Steam\"\n ],\n \"forbidden\": []\n },\n {\n \"id\": \"stripe-webhook\",\n \"category\": \"SOCIAL\",\n \"name\": \"stripe-webhook\",\n \"patterns\": [\n \"Stripe\\\\/\"\n ],\n \"forbidden\": []\n },\n {\n \"id\": \"synapse-crawler\",\n \"category\": \"SOCIAL\",\n \"name\": \"synapse-crawler\",\n \"patterns\": [\n \"Synapse\"\n ],\n \"forbidden\": []\n },\n {\n \"id\": \"telegram-crawler\",\n \"category\": \"SOCIAL\",\n \"name\": \"TelegramBot\",\n \"patterns\": [\n \"TelegramBot\"\n ],\n \"forbidden\": []\n },\n {\n \"id\": \"tiktok-crawler\",\n \"category\": \"SOCIAL\",\n \"name\": \"tiktok-crawler\",\n \"patterns\": [\n \"TikTokSpider\"\n ],\n \"forbidden\": []\n },\n {\n \"id\": \"trendsmap-crawler\",\n \"category\": \"SOCIAL\",\n \"name\": \"trendsmap-crawler\",\n \"patterns\": [\n \"TrendsmapResolver\"\n ],\n \"forbidden\": []\n },\n {\n \"id\": \"tweetedtimes-crawler\",\n \"category\": \"SOCIAL\",\n \"name\": \"tweetedtimes-crawler\",\n \"patterns\": [\n \"tweetedtimes\"\n ],\n \"forbidden\": []\n },\n {\n \"id\": \"twitter-crawler\",\n \"category\": \"SOCIAL\",\n \"name\": \"Twitterbot\",\n \"patterns\": [\n \"Twitterbot\"\n ],\n \"forbidden\": [\n \"facebookexternalhit\",\n \"Facebot\"\n ]\n },\n {\n \"id\": \"vercel-crawler\",\n \"category\": \"SOCIAL\",\n \"name\": \"vercel-crawler\",\n \"patterns\": [\n \"Vercelbot\"\n ],\n \"forbidden\": []\n },\n {\n \"id\": \"vercel-monitor-preview\",\n \"category\": \"SOCIAL\",\n \"name\": \"vercel-monitor-preview\",\n \"patterns\": [\n \"vercel-screenshot\"\n ],\n \"forbidden\": []\n },\n {\n \"id\": \"viber-crawler\",\n \"category\": \"SOCIAL\",\n \"name\": \"ViberBot\",\n \"patterns\": [\n \"Viber\"\n ],\n \"forbidden\": []\n },\n {\n \"id\": \"whatsapp-crawler\",\n \"category\": \"SOCIAL\",\n \"name\": \"WhatsApp\",\n \"patterns\": [\n \"WhatsApp\"\n ],\n \"forbidden\": []\n },\n {\n \"id\": \"yahoo-preview\",\n \"category\": \"SOCIAL\",\n \"name\": \"yahoo-preview\",\n \"patterns\": [\n \"Yahoo Link Preview\"\n ],\n \"forbidden\": []\n },\n {\n \"id\": \"a6corp-crawler\",\n \"category\": \"UNKNOWN\",\n \"name\": \"a6corp-crawler\",\n \"patterns\": [\n \"A6-Indexer\"\n ],\n \"forbidden\": []\n },\n {\n \"id\": \"aboundex-crawler\",\n \"category\": \"UNKNOWN\",\n \"name\": \"aboundex-crawler\",\n \"patterns\": [\n \"Aboundex\"\n ],\n \"forbidden\": []\n },\n {\n \"id\": \"acapbot\",\n \"category\": \"UNKNOWN\",\n \"name\": \"acapbot\",\n \"patterns\": [\n \"acapbot\"\n ],\n \"forbidden\": []\n },\n {\n \"id\": \"acoon-crawler\",\n \"category\": \"UNKNOWN\",\n \"name\": \"acoon-crawler\",\n \"patterns\": [\n \"acoonbot\"\n ],\n \"forbidden\": []\n },\n {\n \"id\": \"adbeat-crawler\",\n \"category\": \"UNKNOWN\",\n \"name\": \"adbeat-crawler\",\n \"patterns\": [\n \"adbeat_bot\"\n ],\n \"forbidden\": []\n },\n {\n \"id\": \"addthis-crawler\",\n \"category\": \"UNKNOWN\",\n \"name\": \"addthis-crawler\",\n \"patterns\": [\n \"AddThis\"\n ],\n \"forbidden\": []\n },\n {\n \"id\": \"admantx-crawler\",\n \"category\": \"UNKNOWN\",\n \"name\": \"admantx-crawler\",\n \"patterns\": [\n \"ADmantX\"\n ],\n \"forbidden\": []\n },\n {\n \"id\": \"adscanner-crawler\",\n \"category\": \"UNKNOWN\",\n \"name\": \"adscanner-crawler\",\n \"patterns\": [\n \"adscanner\"\n ],\n \"forbidden\": []\n },\n {\n \"id\": \"adstxtcrawler\",\n \"category\": \"UNKNOWN\",\n \"name\": \"adstxtcrawler\",\n \"patterns\": [\n \"AdsTxtCrawler\"\n ],\n \"forbidden\": []\n },\n {\n \"id\": \"advbot-crawler\",\n \"category\": \"UNKNOWN\",\n \"name\": \"advbot-crawler\",\n \"patterns\": [\n \"AdvBot\"\n ],\n \"forbidden\": []\n },\n {\n \"id\": \"alphaseobot-crawler\",\n \"category\": \"UNKNOWN\",\n \"name\": \"alphaseobot-crawler\",\n \"patterns\": [\n \"AlphaBot\"\n ],\n \"forbidden\": []\n },\n {\n \"id\": \"anderspink-crawler\",\n \"category\": \"UNKNOWN\",\n \"name\": \"anderspink-crawler\",\n \"patterns\": [\n \"AndersPinkBot\"\n ],\n \"forbidden\": []\n },\n {\n \"id\": \"antibot\",\n \"category\": \"UNKNOWN\",\n \"name\": \"antibot\",\n \"patterns\": [\n \"antibot\"\n ],\n \"forbidden\": []\n },\n {\n \"id\": \"apercite-crawler\",\n \"category\": \"UNKNOWN\",\n \"name\": \"apercite-crawler\",\n \"patterns\": [\n \"Apercite\"\n ],\n \"forbidden\": []\n },\n {\n \"id\": \"ara-crawler\",\n \"category\": \"UNKNOWN\",\n \"name\": \"ara-crawler\",\n \"patterns\": [\n \"arabot\"\n ],\n \"forbidden\": []\n },\n {\n \"id\": \"araturka-crawler\",\n \"category\": \"UNKNOWN\",\n \"name\": \"araturka-crawler\",\n \"patterns\": [\n \"Bot\\\\.AraTurka\\\\.com\"\n ],\n \"forbidden\": []\n },\n {\n \"id\": \"arocom-crawler\",\n \"category\": \"UNKNOWN\",\n \"name\": \"arocom-crawler\",\n \"patterns\": [\n \"drupact\"\n ],\n \"forbidden\": []\n },\n {\n \"id\": \"aspiegel-crawler\",\n \"category\": \"UNKNOWN\",\n \"name\": \"aspiegel-crawler\",\n \"patterns\": [\n \"AspiegelBot\"\n ],\n \"forbidden\": []\n },\n {\n \"id\": \"audisto-crawler\",\n \"category\": \"UNKNOWN\",\n \"name\": \"audisto-crawler\",\n \"patterns\": [\n \"Audisto Crawler\"\n ],\n \"forbidden\": []\n },\n {\n \"id\": \"awario-crawler\",\n \"category\": \"UNKNOWN\",\n \"name\": \"awario-crawler\",\n \"patterns\": [\n \"AwarioBot\"\n ],\n \"forbidden\": []\n },\n {\n \"id\": \"awario-crawler-smart\",\n \"category\": \"UNKNOWN\",\n \"name\": \"awario-crawler-smart\",\n \"patterns\": [\n \"AwarioSmartBot\"\n ],\n \"forbidden\": []\n },\n {\n \"id\": \"awesomecrawler\",\n \"category\": \"UNKNOWN\",\n \"name\": \"awesomecrawler\",\n \"patterns\": [\n \"awesomecrawler\"\n ],\n \"forbidden\": []\n },\n {\n \"id\": \"b2bbot\",\n \"category\": \"UNKNOWN\",\n \"name\": \"b2bbot\",\n \"patterns\": [\n \"B2B Bot\"\n ],\n \"forbidden\": []\n },\n {\n \"id\": \"backlinktest-crawler\",\n \"category\": \"UNKNOWN\",\n \"name\": \"backlinktest-crawler\",\n \"patterns\": [\n \"backlinkcrawler\"\n ],\n \"forbidden\": []\n },\n {\n \"id\": \"baidu-cloud-watch\",\n \"category\": \"UNKNOWN\",\n \"name\": \"baidu-cloud-watch\",\n \"patterns\": [\n \"Baidu-YunGuanCe\"\n ],\n \"forbidden\": []\n },\n {\n \"id\": \"betabot\",\n \"category\": \"UNKNOWN\",\n \"name\": \"betabot\",\n \"patterns\": [\n \"betaBot\"\n ],\n \"forbidden\": []\n },\n {\n \"id\": \"bidswitch-crawler\",\n \"category\": \"UNKNOWN\",\n \"name\": \"bidswitch-crawler\",\n \"patterns\": [\n \"bidswitchbot\"\n ],\n \"forbidden\": []\n },\n {\n \"id\": \"bigdatacorp-crawler\",\n \"category\": \"UNKNOWN\",\n \"name\": \"bigdatacorp-crawler\",\n \"patterns\": [\n \"BDCbot\"\n ],\n \"forbidden\": []\n },\n {\n \"id\": \"biglotron\",\n \"category\": \"UNKNOWN\",\n \"name\": \"biglotron\",\n \"patterns\": [\n \"BIGLOTRON\"\n ],\n \"forbidden\": []\n },\n {\n \"id\": \"binlar\",\n \"category\": \"UNKNOWN\",\n \"name\": \"binlar\",\n \"patterns\": [\n \"binlar\"\n ],\n \"forbidden\": []\n },\n {\n \"id\": \"bitsight-crawler\",\n \"category\": \"UNKNOWN\",\n \"name\": \"bitsight-crawler\",\n \"patterns\": [\n \"BitSightBot\\\\/\"\n ],\n \"forbidden\": []\n },\n {\n \"id\": \"blogmura-crawler\",\n \"category\": \"UNKNOWN\",\n \"name\": \"blogmura-crawler\",\n \"patterns\": [\n \"blogmuraBot\"\n ],\n \"forbidden\": []\n },\n {\n \"id\": \"blp-bbot\",\n \"category\": \"UNKNOWN\",\n \"name\": \"blp-bbot\",\n \"patterns\": [\n \"BLP_bbot\"\n ],\n \"forbidden\": []\n },\n {\n \"id\": \"bnf-crawler\",\n \"category\": \"UNKNOWN\",\n \"name\": \"bnf-crawler\",\n \"patterns\": [\n \"bnf\\\\.fr_bot\"\n ],\n \"forbidden\": []\n },\n {\n \"id\": \"bombora-crawler\",\n \"category\": \"UNKNOWN\",\n \"name\": \"bombora-crawler\",\n \"patterns\": [\n \"BomboraBot\"\n ],\n \"forbidden\": []\n },\n {\n \"id\": \"boxcar-crawler\",\n \"category\": \"UNKNOWN\",\n \"name\": \"boxcar-crawler\",\n \"patterns\": [\n \"BoxcarBot\"\n ],\n \"forbidden\": []\n },\n {\n \"id\": \"brainobot\",\n \"category\": \"UNKNOWN\",\n \"name\": \"brainobot\",\n \"patterns\": [\n \"brainobot\"\n ],\n \"forbidden\": []\n },\n {\n \"id\": \"brandonmedia-crawler\",\n \"category\": \"UNKNOWN\",\n \"name\": \"brandonmedia-crawler\",\n \"patterns\": [\n \"BrandONbot\"\n ],\n \"forbidden\": []\n },\n {\n \"id\": \"brandwatch-crawler\",\n \"category\": \"UNKNOWN\",\n \"name\": \"brandwatch-crawler\",\n \"patterns\": [\n \"magpie-crawler\"\n ],\n \"forbidden\": []\n },\n {\n \"id\": \"brightedge-crawler\",\n \"category\": \"UNKNOWN\",\n \"name\": \"brightedge-crawler\",\n \"patterns\": [\n \"BrightEdge Crawler\"\n ],\n \"forbidden\": []\n },\n {\n \"id\": \"bublup-crawler\",\n \"category\": \"UNKNOWN\",\n \"name\": \"bublup-crawler\",\n \"patterns\": [\n \"BublupBot\"\n ],\n \"forbidden\": []\n },\n {\n \"id\": \"builtwith-crawler\",\n \"category\": \"UNKNOWN\",\n \"name\": \"builtwith-crawler\",\n \"patterns\": [\n \"^BW\\\\/\"\n ],\n \"forbidden\": []\n },\n {\n \"id\": \"buzzstream-crawler\",\n \"category\": \"UNKNOWN\",\n \"name\": \"buzzstream-crawler\",\n \"patterns\": [\n \"buzzbot\"\n ],\n \"forbidden\": []\n },\n {\n \"id\": \"capsulink-crawler\",\n \"category\": \"UNKNOWN\",\n \"name\": \"capsulink-crawler\",\n \"patterns\": [\n \"CapsuleChecker\"\n ],\n \"forbidden\": []\n },\n {\n \"id\": \"careerx-crawler\",\n \"category\": \"UNKNOWN\",\n \"name\": \"careerx-crawler\",\n \"patterns\": [\n \"careerbot\"\n ],\n \"forbidden\": []\n },\n {\n \"id\": \"centurybot\",\n \"category\": \"UNKNOWN\",\n \"name\": \"centurybot\",\n \"patterns\": [\n \"centurybot\"\n ],\n \"forbidden\": []\n },\n {\n \"id\": \"checkmarknetwork-crawler\",\n \"category\": \"UNKNOWN\",\n \"name\": \"checkmarknetwork-crawler\",\n \"patterns\": [\n \"CheckMarkNetwork\\\\/\"\n ],\n \"forbidden\": []\n },\n {\n \"id\": \"chlooe-crawler\",\n \"category\": \"UNKNOWN\",\n \"name\": \"chlooe-crawler\",\n \"patterns\": [\n \"bot-pge\\\\.chlooe\\\\.com\"\n ],\n \"forbidden\": []\n },\n {\n \"id\": \"cincrawdata-crawler\",\n \"category\": \"UNKNOWN\",\n \"name\": \"cincrawdata-crawler\",\n \"patterns\": [\n \"Cincraw\"\n ],\n \"forbidden\": []\n },\n {\n \"id\": \"citeseerx-crawler\",\n \"category\": \"UNKNOWN\",\n \"name\": \"citeseerx-crawler\",\n \"patterns\": [\n \"citeseerxbot\"\n ],\n \"forbidden\": []\n },\n {\n \"id\": \"clickagy-crawler\",\n \"category\": \"UNKNOWN\",\n \"name\": \"clickagy-crawler\",\n \"patterns\": [\n \"Clickagy\"\n ],\n \"forbidden\": []\n },\n {\n \"id\": \"cliqz-crawler\",\n \"category\": \"UNKNOWN\",\n \"name\": \"cliqz-crawler\",\n \"patterns\": [\n \"Cliqzbot\\\\/\"\n ],\n \"forbidden\": []\n },\n {\n \"id\": \"cloudsystemnetworks-crawler\",\n \"category\": \"UNKNOWN\",\n \"name\": \"cloudsystemnetworks-crawler\",\n \"patterns\": [\n \"Nimbostratus-Bot\"\n ],\n \"forbidden\": []\n },\n {\n \"id\": \"coccoc-crawler\",\n \"category\": \"UNKNOWN\",\n \"name\": \"coccoc-crawler\",\n \"patterns\": [\n \"coccoc\"\n ],\n \"forbidden\": []\n },\n {\n \"id\": \"cocolyze-crawler\",\n \"category\": \"UNKNOWN\",\n \"name\": \"cocolyze-crawler\",\n \"patterns\": [\n \"Cocolyzebot\"\n ],\n \"forbidden\": []\n },\n {\n \"id\": \"codewise-crawler\",\n \"category\": \"UNKNOWN\",\n \"name\": \"codewise-crawler\",\n \"patterns\": [\n \"VoluumDSP-content-bot\"\n ],\n \"forbidden\": []\n },\n {\n \"id\": \"cognitiveseo-crawler\",\n \"category\": \"UNKNOWN\",\n \"name\": \"cognitiveseo-crawler\",\n \"patterns\": [\n \"James BOT\"\n ],\n \"forbidden\": []\n },\n {\n \"id\": \"companybook-crawler\",\n \"category\": \"UNKNOWN\",\n \"name\": \"companybook-crawler\",\n \"patterns\": [\n \"Companybook-Crawler\"\n ],\n \"forbidden\": []\n },\n {\n \"id\": \"content-crawler-spider\",\n \"category\": \"UNKNOWN\",\n \"name\": \"content-crawler-spider\",\n \"patterns\": [\n \"content crawler spider\"\n ],\n \"forbidden\": []\n },\n {\n \"id\": \"contextad-crawler\",\n \"category\": \"UNKNOWN\",\n \"name\": \"contextad-crawler\",\n \"patterns\": [\n \"ContextAd Bot\"\n ],\n \"forbidden\": []\n },\n {\n \"id\": \"contxbot\",\n \"category\": \"UNKNOWN\",\n \"name\": \"contxbot\",\n \"patterns\": [\n \"contxbot\"\n ],\n \"forbidden\": []\n },\n {\n \"id\": \"convera-crawler\",\n \"category\": \"UNKNOWN\",\n \"name\": \"convera-crawler\",\n \"patterns\": [\n \"convera\"\n ],\n \"forbidden\": []\n },\n {\n \"id\": \"cookiebot-crawler\",\n \"category\": \"UNKNOWN\",\n \"name\": \"cookiebot-crawler\",\n \"patterns\": [\n \"Cookiebot\"\n ],\n \"forbidden\": []\n },\n {\n \"id\": \"creativecommons-crawler\",\n \"category\": \"UNKNOWN\",\n \"name\": \"creativecommons-crawler\",\n \"patterns\": [\n \"CC Metadata Scaper\"\n ],\n \"forbidden\": []\n },\n {\n \"id\": \"criteo-crawler\",\n \"category\": \"UNKNOWN\",\n \"name\": \"criteo-crawler\",\n \"patterns\": [\n \"CriteoBot\"\n ],\n \"forbidden\": []\n },\n {\n \"id\": \"crystalsemantics-crawler\",\n \"category\": \"UNKNOWN\",\n \"name\": \"crystalsemantics-crawler\",\n \"patterns\": [\n \"CrystalSemanticsBot\"\n ],\n \"forbidden\": []\n },\n {\n \"id\": \"curebot-crawler\",\n \"category\": \"UNKNOWN\",\n \"name\": \"curebot-crawler\",\n \"patterns\": [\n \"[Cc]urebot\"\n ],\n \"forbidden\": []\n },\n {\n \"id\": \"cutbot-crawler\",\n \"category\": \"UNKNOWN\",\n \"name\": \"cutbot-crawler\",\n \"patterns\": [\n \"Cutbot\"\n ],\n \"forbidden\": []\n },\n {\n \"id\": \"cxense-crawler\",\n \"category\": \"UNKNOWN\",\n \"name\": \"cxense-crawler\",\n \"patterns\": [\n \"cXensebot\"\n ],\n \"forbidden\": []\n },\n {\n \"id\": \"cyberpatrol-crawler\",\n \"category\": \"UNKNOWN\",\n \"name\": \"cyberpatrol-crawler\",\n \"patterns\": [\n \"CyberPatrol\"\n ],\n \"forbidden\": []\n },\n {\n \"id\": \"datafeedwatch-crawler\",\n \"category\": \"UNKNOWN\",\n \"name\": \"datafeedwatch-crawler\",\n \"patterns\": [\n \"Datafeedwatch\"\n ],\n \"forbidden\": []\n },\n {\n \"id\": \"dataforseo-crawler\",\n \"category\": \"UNKNOWN\",\n \"name\": \"dataforseo-crawler\",\n \"patterns\": [\n \"DataForSeoBot\"\n ],\n \"forbidden\": []\n },\n {\n \"id\": \"datagnion-crawler\",\n \"category\": \"UNKNOWN\",\n \"name\": \"datagnion-crawler\",\n \"patterns\": [\n \"datagnionbot\"\n ],\n \"forbidden\": []\n },\n {\n \"id\": \"datanyze-crawler\",\n \"category\": \"UNKNOWN\",\n \"name\": \"datanyze-crawler\",\n \"patterns\": [\n \"Datanyze\"\n ],\n \"forbidden\": []\n },\n {\n \"id\": \"dataprovider-crawler\",\n \"category\": \"UNKNOWN\",\n \"name\": \"dataprovider-crawler\",\n \"patterns\": [\n \"Dataprovider\\\\.com\"\n ],\n \"forbidden\": []\n },\n {\n \"id\": \"datenbutler-crawler\",\n \"category\": \"UNKNOWN\",\n \"name\": \"datenbutler-crawler\",\n \"patterns\": [\n \"mindUpBot\"\n ],\n \"forbidden\": []\n },\n {\n \"id\": \"daum-crawler\",\n \"category\": \"UNKNOWN\",\n \"name\": \"daum-crawler\",\n \"patterns\": [\n \"Daum\\\\/\"\n ],\n \"forbidden\": []\n },\n {\n \"id\": \"deepnoc-crawler\",\n \"category\": \"UNKNOWN\",\n \"name\": \"deepnoc-crawler\",\n \"patterns\": [\n \"deepnoc\"\n ],\n \"forbidden\": []\n },\n {\n \"id\": \"deusu-crawler\",\n \"category\": \"UNKNOWN\",\n \"name\": \"deusu-crawler\",\n \"patterns\": [\n \"DeuSu\\\\/\"\n ],\n \"forbidden\": []\n },\n {\n \"id\": \"digincore-crawler\",\n \"category\": \"UNKNOWN\",\n \"name\": \"digincore-crawler\",\n \"patterns\": [\n \"Digincore bot\"\n ],\n \"forbidden\": []\n },\n {\n \"id\": \"digitaldragon-crawler\",\n \"category\": \"UNKNOWN\",\n \"name\": \"digitaldragon-crawler\",\n \"patterns\": [\n \"CrawlyProjectCrawler\"\n ],\n \"forbidden\": []\n },\n {\n \"id\": \"discoveryengine-crawler\",\n \"category\": \"UNKNOWN\",\n \"name\": \"discoveryengine-crawler\",\n \"patterns\": [\n \"discobot\"\n ],\n \"forbidden\": []\n },\n {\n \"id\": \"dnyz-crawler\",\n \"category\": \"UNKNOWN\",\n \"name\": \"dnyz-crawler\",\n \"patterns\": [\n \"DnyzBot\"\n ],\n \"forbidden\": []\n },\n {\n \"id\": \"domaincrawler-crawler\",\n \"category\": \"UNKNOWN\",\n \"name\": \"domaincrawler-crawler\",\n \"patterns\": [\n \"domaincrawler\"\n ],\n \"forbidden\": []\n },\n {\n \"id\": \"domainreanimator-crawler\",\n \"category\": \"UNKNOWN\",\n \"name\": \"domainreanimator-crawler\",\n \"patterns\": [\n \"Domain Re-Animator Bot\"\n ],\n \"forbidden\": []\n },\n {\n \"id\": \"domainsbot-crawler\",\n \"category\": \"UNKNOWN\",\n \"name\": \"domainsbot-crawler\",\n \"patterns\": [\n \"Pandalytics\"\n ],\n \"forbidden\": []\n },\n {\n \"id\": \"domainstats-crawler\",\n \"category\": \"UNKNOWN\",\n \"name\": \"domainstats-crawler\",\n \"patterns\": [\n \"DomainStatsBot\"\n ],\n \"forbidden\": []\n },\n {\n \"id\": \"domaintools-crawler\",\n \"category\": \"UNKNOWN\",\n \"name\": \"domaintools-crawler\",\n \"patterns\": [\n \"SurveyBot\"\n ],\n \"forbidden\": []\n },\n {\n \"id\": \"dotnetdotcom-crawler\",\n \"category\": \"UNKNOWN\",\n \"name\": \"dotnetdotcom-crawler\",\n \"patterns\": [\n \"ezooms\"\n ],\n \"forbidden\": []\n },\n {\n \"id\": \"dragonmetrics-crawler\",\n \"category\": \"UNKNOWN\",\n \"name\": \"dragonmetrics-crawler\",\n \"patterns\": [\n \"Dragonbot\"\n ],\n \"forbidden\": []\n },\n {\n \"id\": \"driftnet-crawler\",\n \"category\": \"UNKNOWN\",\n \"name\": \"driftnet-crawler\",\n \"patterns\": [\n \"InternetMeasurement\"\n ],\n \"forbidden\": []\n },\n {\n \"id\": \"duedil-crawler\",\n \"category\": \"UNKNOWN\",\n \"name\": \"duedil-crawler\",\n \"patterns\": [\n \"electricmonk\"\n ],\n \"forbidden\": []\n },\n {\n \"id\": \"ec2linkfinder\",\n \"category\": \"UNKNOWN\",\n \"name\": \"ec2linkfinder\",\n \"patterns\": [\n \"ec2linkfinder\"\n ],\n \"forbidden\": []\n },\n {\n \"id\": \"edister-crawler\",\n \"category\": \"UNKNOWN\",\n \"name\": \"edister-crawler\",\n \"patterns\": [\n \"edisterbot\"\n ],\n \"forbidden\": []\n },\n {\n \"id\": \"elisabot\",\n \"category\": \"UNKNOWN\",\n \"name\": \"elisabot\",\n \"patterns\": [\n \"elisabot\"\n ],\n \"forbidden\": []\n },\n {\n \"id\": \"epictions-crawler\",\n \"category\": \"UNKNOWN\",\n \"name\": \"epictions-crawler\",\n \"patterns\": [\n \"epicbot\"\n ],\n \"forbidden\": []\n },\n {\n \"id\": \"eright-crawler\",\n \"category\": \"UNKNOWN\",\n \"name\": \"eright-crawler\",\n \"patterns\": [\n \"eright\"\n ],\n \"forbidden\": []\n },\n {\n \"id\": \"europarchive-crawler\",\n \"category\": \"UNKNOWN\",\n \"name\": \"europarchive-crawler\",\n \"patterns\": [\n \"europarchive\\\\.org\"\n ],\n \"forbidden\": []\n },\n {\n \"id\": \"eventures-crawler\",\n \"category\": \"UNKNOWN\",\n \"name\": \"eventures-crawler\",\n \"patterns\": [\n \"e\\\\.ventures Investment Crawler\"\n ],\n \"forbidden\": []\n },\n {\n \"id\": \"eventures-crawler-batch\",\n \"category\": \"UNKNOWN\",\n \"name\": \"eventures-crawler-batch\",\n \"patterns\": [\n \"evc-batch\"\n ],\n \"forbidden\": []\n },\n {\n \"id\": \"exensa-crawler\",\n \"category\": \"UNKNOWN\",\n \"name\": \"exensa-crawler\",\n \"patterns\": [\n \"Bark[rR]owler\"\n ],\n \"forbidden\": []\n },\n {\n \"id\": \"experibot-crawler\",\n \"category\": \"UNKNOWN\",\n \"name\": \"experibot-crawler\",\n \"patterns\": [\n \"Experibot\"\n ],\n \"forbidden\": []\n },\n {\n \"id\": \"extlinks-crawler\",\n \"category\": \"UNKNOWN\",\n \"name\": \"extlinks-crawler\",\n \"patterns\": [\n \"ExtLinksBot\"\n ],\n \"forbidden\": []\n },\n {\n \"id\": \"eyeota-crawler\",\n \"category\": \"UNKNOWN\",\n \"name\": \"eyeota-crawler\",\n \"patterns\": [\n \"Eyeotabot\"\n ],\n \"forbidden\": []\n },\n {\n \"id\": \"fast-crawler\",\n \"category\": \"UNKNOWN\",\n \"name\": \"fast-crawler\",\n \"patterns\": [\n \"FAST-WebCrawler\"\n ],\n \"forbidden\": []\n },\n {\n \"id\": \"fast-crawler-enterprise\",\n \"category\": \"UNKNOWN\",\n \"name\": \"fast-crawler-enterprise\",\n \"patterns\": [\n \"FAST Enterprise Crawler\"\n ],\n \"forbidden\": []\n },\n {\n \"id\": \"fedoraplanet-crawler\",\n \"category\": \"UNKNOWN\",\n \"name\": \"fedoraplanet-crawler\",\n \"patterns\": [\n \"fedoraplanet\"\n ],\n \"forbidden\": []\n },\n {\n \"id\": \"feedafever-crawler\",\n \"category\": \"UNKNOWN\",\n \"name\": \"feedafever-crawler\",\n \"patterns\": [\n \"Fever\"\n ],\n \"forbidden\": []\n },\n {\n \"id\": \"femtosearch-crawler\",\n \"category\": \"UNKNOWN\",\n \"name\": \"femtosearch-crawler\",\n \"patterns\": [\n \"FemtosearchBot\"\n ],\n \"forbidden\": []\n },\n {\n \"id\": \"findthatfile-crawler\",\n \"category\": \"UNKNOWN\",\n \"name\": \"findthatfile-crawler\",\n \"patterns\": [\n \"findthatfile\"\n ],\n \"forbidden\": []\n },\n {\n \"id\": \"flamingosearch-crawler\",\n \"category\": \"UNKNOWN\",\n \"name\": \"flamingosearch-crawler\",\n \"patterns\": [\n \"Flamingo_SearchEngine\"\n ],\n \"forbidden\": []\n },\n {\n \"id\": \"fluffy\",\n \"category\": \"UNKNOWN\",\n \"name\": \"fluffy\",\n \"patterns\": [\n \"fluffy\"\n ],\n \"forbidden\": []\n },\n {\n \"id\": \"fr-crawler\",\n \"category\": \"UNKNOWN\",\n \"name\": \"fr-crawler\",\n \"patterns\": [\n \"fr-crawler\"\n ],\n \"forbidden\": []\n },\n {\n \"id\": \"fuelbot\",\n \"category\": \"UNKNOWN\",\n \"name\": \"fuelbot\",\n \"patterns\": [\n \"fuelbot\"\n ],\n \"forbidden\": []\n },\n {\n \"id\": \"fyrebot\",\n \"category\": \"UNKNOWN\",\n \"name\": \"fyrebot\",\n \"patterns\": [\n \"Fyrebot\"\n ],\n \"forbidden\": []\n },\n {\n \"id\": \"g00g1e-crawler\",\n \"category\": \"UNKNOWN\",\n \"name\": \"g00g1e-crawler\",\n \"patterns\": [\n \"g00g1e\\\\.net\"\n ],\n \"forbidden\": []\n },\n {\n \"id\": \"g2webservices-crawler\",\n \"category\": \"UNKNOWN\",\n \"name\": \"g2webservices-crawler\",\n \"patterns\": [\n \"G2 Web Services\"\n ],\n \"forbidden\": []\n },\n {\n \"id\": \"garlik-crawler\",\n \"category\": \"UNKNOWN\",\n \"name\": \"garlik-crawler\",\n \"patterns\": [\n \"GarlikCrawler\"\n ],\n \"forbidden\": []\n },\n {\n \"id\": \"genieo-crawler\",\n \"category\": \"UNKNOWN\",\n \"name\": \"genieo-crawler\",\n \"patterns\": [\n \"Genieo\"\n ],\n \"forbidden\": []\n },\n {\n \"id\": \"gigablast-crawler\",\n \"category\": \"UNKNOWN\",\n \"name\": \"gigablast-crawler\",\n \"patterns\": [\n \"Gigabot\"\n ],\n \"forbidden\": []\n },\n {\n \"id\": \"ginger-crawler\",\n \"category\": \"UNKNOWN\",\n \"name\": \"ginger-crawler\",\n \"patterns\": [\n \"GingerCrawler\"\n ],\n \"forbidden\": []\n },\n {\n \"id\": \"gnam-gnam-spider\",\n \"category\": \"UNKNOWN\",\n \"name\": \"gnam-gnam-spider\",\n \"patterns\": [\n \"gnam gnam spider\"\n ],\n \"forbidden\": []\n },\n {\n \"id\": \"gnowit-crawler\",\n \"category\": \"UNKNOWN\",\n \"name\": \"gnowit-crawler\",\n \"patterns\": [\n \"GnowitNewsbot\"\n ],\n \"forbidden\": []\n },\n {\n \"id\": \"goo-crawler\",\n \"category\": \"UNKNOWN\",\n \"name\": \"goo-crawler\",\n \"patterns\": [\n \"ichiro\"\n ],\n \"forbidden\": []\n },\n {\n \"id\": \"grapeshot-crawler\",\n \"category\": \"UNKNOWN\",\n \"name\": \"grapeshot-crawler\",\n \"patterns\": [\n \"GrapeshotCrawler\"\n ],\n \"forbidden\": []\n },\n {\n \"id\": \"grob-crawler\",\n \"category\": \"UNKNOWN\",\n \"name\": \"grob-crawler\",\n \"patterns\": [\n \"Grobbot\"\n ],\n \"forbidden\": []\n },\n {\n \"id\": \"grouphigh-crawler\",\n \"category\": \"UNKNOWN\",\n \"name\": \"grouphigh-crawler\",\n \"patterns\": [\n \"GroupHigh\\\\/\"\n ],\n \"forbidden\": []\n },\n {\n \"id\": \"grub\",\n \"category\": \"UNKNOWN\",\n \"name\": \"grub\",\n \"patterns\": [\n \"grub\\\\.org\"\n ],\n \"forbidden\": []\n },\n {\n \"id\": \"gslfbot\",\n \"category\": \"UNKNOWN\",\n \"name\": \"gslfbot\",\n \"patterns\": [\n \"gslfbot\"\n ],\n \"forbidden\": []\n },\n {\n \"id\": \"gwene-crawler\",\n \"category\": \"UNKNOWN\",\n \"name\": \"gwene-crawler\",\n \"patterns\": [\n \"Gwene\"\n ],\n \"forbidden\": []\n },\n {\n \"id\": \"haosou-crawler\",\n \"category\": \"UNKNOWN\",\n \"name\": \"haosou-crawler\",\n \"patterns\": [\n \"360Spider\"\n ],\n \"forbidden\": []\n },\n {\n \"id\": \"hatena-crawler\",\n \"category\": \"UNKNOWN\",\n \"name\": \"hatena-crawler\",\n \"patterns\": [\n \"Hatena\"\n ],\n \"forbidden\": []\n },\n {\n \"id\": \"headline-crawler\",\n \"category\": \"UNKNOWN\",\n \"name\": \"headline-crawler\",\n \"patterns\": [\n \"ev-crawler\\\\/\"\n ],\n \"forbidden\": []\n },\n {\n \"id\": \"hoyer-crawler\",\n \"category\": \"UNKNOWN\",\n \"name\": \"hoyer-crawler\",\n \"patterns\": [\n \"Friendica\"\n ],\n \"forbidden\": []\n },\n {\n \"id\": \"httrack\",\n \"category\": \"UNKNOWN\",\n \"name\": \"httrack\",\n \"patterns\": [\n \"HTTrack\"\n ],\n \"forbidden\": []\n },\n {\n \"id\": \"hypefactors-crawler\",\n \"category\": \"UNKNOWN\",\n \"name\": \"hypefactors-crawler\",\n \"patterns\": [\n \"Buck\\\\/\"\n ],\n \"forbidden\": []\n },\n {\n \"id\": \"hypestat-crawler\",\n \"category\": \"UNKNOWN\",\n \"name\": \"hypestat-crawler\",\n \"patterns\": [\n \"hypestat\"\n ],\n \"forbidden\": []\n },\n {\n \"id\": \"hyscore-crawler\",\n \"category\": \"UNKNOWN\",\n \"name\": \"hyscore-crawler\",\n \"patterns\": [\n \"hyscore\\\\.io\"\n ],\n \"forbidden\": []\n },\n {\n \"id\": \"ia-archiver\",\n \"category\": \"UNKNOWN\",\n \"name\": \"ia-archiver\",\n \"patterns\": [\n \"ia_archiver\"\n ],\n \"forbidden\": []\n },\n {\n \"id\": \"ideasandcode-crawler\",\n \"category\": \"UNKNOWN\",\n \"name\": \"ideasandcode-crawler\",\n \"patterns\": [\n \"ICBot\\\\/\"\n ],\n \"forbidden\": []\n },\n {\n \"id\": \"indeed-crawler\",\n \"category\": \"UNKNOWN\",\n \"name\": \"indeed-crawler\",\n \"patterns\": [\n \"IndeedBot\"\n ],\n \"forbidden\": []\n },\n {\n \"id\": \"inetdex-crawler\",\n \"category\": \"UNKNOWN\",\n \"name\": \"inetdex-crawler\",\n \"patterns\": [\n \"INETDEX-BOT\"\n ],\n \"forbidden\": []\n },\n {\n \"id\": \"infoo-crawler\",\n \"category\": \"UNKNOWN\",\n \"name\": \"infoo-crawler\",\n \"patterns\": [\n \"infoobot\"\n ],\n \"forbidden\": []\n },\n {\n \"id\": \"integromedb-crawler\",\n \"category\": \"UNKNOWN\",\n \"name\": \"integromedb-crawler\",\n \"patterns\": [\n \"integromedb\"\n ],\n \"forbidden\": []\n },\n {\n \"id\": \"intelium-crawler\",\n \"category\": \"UNKNOWN\",\n \"name\": \"intelium-crawler\",\n \"patterns\": [\n \"intelium_bot\"\n ],\n \"forbidden\": []\n },\n {\n \"id\": \"ionos-crawler\",\n \"category\": \"UNKNOWN\",\n \"name\": \"ionos-crawler\",\n \"patterns\": [\n \"IonCrawl\"\n ],\n \"forbidden\": []\n },\n {\n \"id\": \"ip-web-crawler\",\n \"category\": \"UNKNOWN\",\n \"name\": \"ip-web-crawler\",\n \"patterns\": [\n \"ip-web-crawler\\\\.com\"\n ],\n \"forbidden\": []\n },\n {\n \"id\": \"iskanie-crawler\",\n \"category\": \"UNKNOWN\",\n \"name\": \"iskanie-crawler\",\n \"patterns\": [\n \"iskanie\"\n ],\n \"forbidden\": []\n },\n {\n \"id\": \"iss-crawler\",\n \"category\": \"UNKNOWN\",\n \"name\": \"iss-crawler\",\n \"patterns\": [\n \"filterdb\\\\.iss\\\\.net\\\\/crawler\"\n ],\n \"forbidden\": []\n },\n {\n \"id\": \"it2media-crawler\",\n \"category\": \"UNKNOWN\",\n \"name\": \"it2media-crawler\",\n \"patterns\": [\n \"it2media-domain-crawler\"\n ],\n \"forbidden\": []\n },\n {\n \"id\": \"itinfluentials-crawler\",\n \"category\": \"UNKNOWN\",\n \"name\": \"itinfluentials-crawler\",\n \"patterns\": [\n \"FindITAnswersbot\"\n ],\n \"forbidden\": []\n },\n {\n \"id\": \"jamiembrown-crawler\",\n \"category\": \"UNKNOWN\",\n \"name\": \"jamiembrown-crawler\",\n \"patterns\": [\n \"Jamie's Spider\"\n ],\n \"forbidden\": []\n },\n {\n \"id\": \"jetslide-crawler\",\n \"category\": \"UNKNOWN\",\n \"name\": \"jetslide-crawler\",\n \"patterns\": [\n \"Jetslide\"\n ],\n \"forbidden\": []\n },\n {\n \"id\": \"jobboerse-crawler\",\n \"category\": \"UNKNOWN\",\n \"name\": \"jobboerse-crawler\",\n \"patterns\": [\n \"JobboerseBot\"\n ],\n \"forbidden\": []\n },\n {\n \"id\": \"jooble-crawler\",\n \"category\": \"UNKNOWN\",\n \"name\": \"jooble-crawler\",\n \"patterns\": [\n \"Jooblebot\"\n ],\n \"forbidden\": []\n },\n {\n \"id\": \"jusprog-crawler\",\n \"category\": \"UNKNOWN\",\n \"name\": \"jusprog-crawler\",\n \"patterns\": [\n \"Jugendschutzprogramm-Crawler\"\n ],\n \"forbidden\": []\n },\n {\n \"id\": \"jyxo-crawler\",\n \"category\": \"UNKNOWN\",\n \"name\": \"jyxo-crawler\",\n \"patterns\": [\n \"jyxobot\"\n ],\n \"forbidden\": []\n },\n {\n \"id\": \"k7computing-crawler\",\n \"category\": \"UNKNOWN\",\n \"name\": \"k7computing-crawler\",\n \"patterns\": [\n \"K7MLWCBot\"\n ],\n \"forbidden\": []\n },\n {\n \"id\": \"kemvi-crawler\",\n \"category\": \"UNKNOWN\",\n \"name\": \"kemvi-crawler\",\n \"patterns\": [\n \"Kemvibot\"\n ],\n \"forbidden\": []\n },\n {\n \"id\": \"komodia-crawler\",\n \"category\": \"UNKNOWN\",\n \"name\": \"komodia-crawler\",\n \"patterns\": [\n \"KomodiaBot\"\n ],\n \"forbidden\": []\n },\n {\n \"id\": \"kosmio-crawler\",\n \"category\": \"UNKNOWN\",\n \"name\": \"kosmio-crawler\",\n \"patterns\": [\n \"KosmioBot\"\n ],\n \"forbidden\": []\n },\n {\n \"id\": \"landaumedia-crawler\",\n \"category\": \"UNKNOWN\",\n \"name\": \"landaumedia-crawler\",\n \"patterns\": [\n \"Landau-Media-Spider\"\n ],\n \"forbidden\": []\n },\n {\n \"id\": \"laserlike-crawler\",\n \"category\": \"UNKNOWN\",\n \"name\": \"laserlike-crawler\",\n \"patterns\": [\n \"Laserlikebot\"\n ],\n \"forbidden\": []\n },\n {\n \"id\": \"lb-spider\",\n \"category\": \"UNKNOWN\",\n \"name\": \"lb-spider\",\n \"patterns\": [\n \"lb-spider\"\n ],\n \"forbidden\": []\n },\n {\n \"id\": \"leiki-crawler\",\n \"category\": \"UNKNOWN\",\n \"name\": \"leiki-crawler\",\n \"patterns\": [\n \"Leikibot\"\n ],\n \"forbidden\": []\n },\n {\n \"id\": \"lightspeedsystems-crawler\",\n \"category\": \"UNKNOWN\",\n \"name\": \"lightspeedsystems-crawler\",\n \"patterns\": [\n \"LightspeedSystemsCrawler\"\n ],\n \"forbidden\": []\n },\n {\n \"id\": \"line-crawler\",\n \"category\": \"UNKNOWN\",\n \"name\": \"line-crawler\",\n \"patterns\": [\n \"Linespider\"\n ],\n \"forbidden\": []\n },\n {\n \"id\": \"linkapedia-crawler\",\n \"category\": \"UNKNOWN\",\n \"name\": \"linkapedia-crawler\",\n \"patterns\": [\n \"linkapediabot\"\n ],\n \"forbidden\": []\n },\n {\n \"id\": \"linkdex-crawler\",\n \"category\": \"UNKNOWN\",\n \"name\": \"linkdex-crawler\",\n \"patterns\": [\n \"linkdex\"\n ],\n \"forbidden\": []\n },\n {\n \"id\": \"linkfluence-crawler\",\n \"category\": \"UNKNOWN\",\n \"name\": \"linkfluence-crawler\",\n \"patterns\": [\n \"YaK\\\\/\"\n ],\n \"forbidden\": []\n },\n {\n \"id\": \"linkis-crawler\",\n \"category\": \"UNKNOWN\",\n \"name\": \"linkis-crawler\",\n \"patterns\": [\n \"LinkisBot\"\n ],\n \"forbidden\": []\n },\n {\n \"id\": \"lipperhey-crawler\",\n \"category\": \"UNKNOWN\",\n \"name\": \"lipperhey-crawler\",\n \"patterns\": [\n \"lipperhey\"\n ],\n \"forbidden\": []\n },\n {\n \"id\": \"livelap-crawler\",\n \"category\": \"UNKNOWN\",\n \"name\": \"livelap-crawler\",\n \"patterns\": [\n \"Livelap[bB]ot\"\n ],\n \"forbidden\": []\n },\n {\n \"id\": \"logly-crawler\",\n \"category\": \"UNKNOWN\",\n \"name\": \"logly-crawler\",\n \"patterns\": [\n \"zenback bot\"\n ],\n \"forbidden\": []\n },\n {\n \"id\": \"loop-crawler\",\n \"category\": \"UNKNOWN\",\n \"name\": \"loop-crawler\",\n \"patterns\": [\n \"netresearchserver\"\n ],\n \"forbidden\": []\n },\n {\n \"id\": \"lssbot\",\n \"category\": \"UNKNOWN\",\n \"name\": \"lssbot\",\n \"patterns\": [\n \"lssbot\"\n ],\n \"forbidden\": []\n },\n {\n \"id\": \"lssbot-rocket\",\n \"category\": \"UNKNOWN\",\n \"name\": \"lssbot-rocket\",\n \"patterns\": [\n \"lssrocketcrawler\"\n ],\n \"forbidden\": []\n },\n {\n \"id\": \"ltx71-crawler\",\n \"category\": \"UNKNOWN\",\n \"name\": \"ltx71-crawler\",\n \"patterns\": [\n \"ltx71\"\n ],\n \"forbidden\": []\n },\n {\n \"id\": \"luminator-crawler\",\n \"category\": \"UNKNOWN\",\n \"name\": \"luminator-crawler\",\n \"patterns\": [\n \"Luminator-robots\"\n ],\n \"forbidden\": []\n },\n {\n \"id\": \"mailru-crawler\",\n \"category\": \"UNKNOWN\",\n \"name\": \"MailRuBot\",\n \"patterns\": [\n \"Mail\\\\.RU_Bot\"\n ],\n \"forbidden\": []\n },\n {\n \"id\": \"mappydata-crawler\",\n \"category\": \"UNKNOWN\",\n \"name\": \"mappydata-crawler\",\n \"patterns\": [\n \"mappydata\"\n ],\n \"forbidden\": []\n },\n {\n \"id\": \"mauibot\",\n \"category\": \"UNKNOWN\",\n \"name\": \"mauibot\",\n \"patterns\": [\n \"MauiBot\"\n ],\n \"forbidden\": []\n },\n {\n \"id\": \"megaindex-crawler\",\n \"category\": \"UNKNOWN\",\n \"name\": \"megaindex-crawler\",\n \"patterns\": [\n \"MegaIndex\"\n ],\n \"forbidden\": []\n },\n {\n \"id\": \"meltwater-crawler\",\n \"category\": \"UNKNOWN\",\n \"name\": \"meltwater-crawler\",\n \"patterns\": [\n \"MeltwaterNews\"\n ],\n \"forbidden\": []\n },\n {\n \"id\": \"metadatalabs-crawler\",\n \"category\": \"UNKNOWN\",\n \"name\": \"metadatalabs-crawler\",\n \"patterns\": [\n \"mlbot\"\n ],\n \"forbidden\": []\n },\n {\n \"id\": \"metajob-crawler\",\n \"category\": \"UNKNOWN\",\n \"name\": \"metajob-crawler\",\n \"patterns\": [\n \"MetaJobBot\"\n ],\n \"forbidden\": []\n },\n {\n \"id\": \"metauri-crawler\",\n \"category\": \"UNKNOWN\",\n \"name\": \"metauri-crawler\",\n \"patterns\": [\n \"MetaURI\"\n ],\n \"forbidden\": []\n },\n {\n \"id\": \"metricstools-crawler\",\n \"category\": \"UNKNOWN\",\n \"name\": \"metricstools-crawler\",\n \"patterns\": [\n \"MTRobot\"\n ],\n \"forbidden\": []\n },\n {\n \"id\": \"mignify-crawler\",\n \"category\": \"UNKNOWN\",\n \"name\": \"mignify-crawler\",\n \"patterns\": [\n \"memorybot\"\n ],\n \"forbidden\": []\n },\n {\n \"id\": \"mignify-imrbot\",\n \"category\": \"UNKNOWN\",\n \"name\": \"mignify-imrbot\",\n \"patterns\": [\n \"imrbot\"\n ],\n \"forbidden\": []\n },\n {\n \"id\": \"mixnode-cache\",\n \"category\": \"UNKNOWN\",\n \"name\": \"mixnode-cache\",\n \"patterns\": [\n \"MixnodeCache\\\\/\"\n ],\n \"forbidden\": []\n },\n {\n \"id\": \"moodle-crawler\",\n \"category\": \"UNKNOWN\",\n \"name\": \"moodle-crawler\",\n \"patterns\": [\n \"MoodleBot\"\n ],\n \"forbidden\": []\n },\n {\n \"id\": \"moreover-crawler\",\n \"category\": \"UNKNOWN\",\n \"name\": \"moreover-crawler\",\n \"patterns\": [\n \"Moreover\"\n ],\n \"forbidden\": []\n },\n {\n \"id\": \"moz-crawler\",\n \"category\": \"UNKNOWN\",\n \"name\": \"moz-crawler\",\n \"patterns\": [\n \"dotbot\"\n ],\n \"forbidden\": []\n },\n {\n \"id\": \"muckrack-crawler\",\n \"category\": \"UNKNOWN\",\n \"name\": \"muckrack-crawler\",\n \"patterns\": [\n \"MuckRack\"\n ],\n \"forbidden\": []\n },\n {\n \"id\": \"multiviewbot\",\n \"category\": \"UNKNOWN\",\n \"name\": \"multiviewbot\",\n \"patterns\": [\n \"Multiviewbot\"\n ],\n \"forbidden\": []\n },\n {\n \"id\": \"naver-crawler\",\n \"category\": \"UNKNOWN\",\n \"name\": \"naver-crawler\",\n \"patterns\": [\n \"Yeti\"\n ],\n \"forbidden\": []\n },\n {\n \"id\": \"neeva-crawler\",\n \"category\": \"UNKNOWN\",\n \"name\": \"neeva-crawler\",\n \"patterns\": [\n \"Neevabot\"\n ],\n \"forbidden\": []\n },\n {\n \"id\": \"nerdbynature-crawler\",\n \"category\": \"UNKNOWN\",\n \"name\": \"nerdbynature-crawler\",\n \"patterns\": [\n \"NerdByNature\\\\.Bot\"\n ],\n \"forbidden\": []\n },\n {\n \"id\": \"nerdybot-crawler\",\n \"category\": \"UNKNOWN\",\n \"name\": \"nerdybot-crawler\",\n \"patterns\": [\n \"nerdybot\"\n ],\n \"forbidden\": []\n },\n {\n \"id\": \"netcraft-crawler\",\n \"category\": \"UNKNOWN\",\n \"name\": \"netcraft-crawler\",\n \"patterns\": [\n \"NetcraftSurveyAgent\"\n ],\n \"forbidden\": []\n },\n {\n \"id\": \"netsystemsresearch-crawler\",\n \"category\": \"UNKNOWN\",\n \"name\": \"netsystemsresearch-crawler\",\n \"patterns\": [\n \"NetSystemsResearch\"\n ],\n \"forbidden\": []\n },\n {\n \"id\": \"netvibes-crawler\",\n \"category\": \"UNKNOWN\",\n \"name\": \"netvibes-crawler\",\n \"patterns\": [\n \"Netvibes\"\n ],\n \"forbidden\": []\n },\n {\n \"id\": \"newsharecounts-crawler\",\n \"category\": \"UNKNOWN\",\n \"name\": \"newsharecounts-crawler\",\n \"patterns\": [\n \"newsharecounts\"\n ],\n \"forbidden\": []\n },\n {\n \"id\": \"newspaper\",\n \"category\": \"UNKNOWN\",\n \"name\": \"newspaper\",\n \"patterns\": [\n \"newspaper\\\\/\"\n ],\n \"forbidden\": []\n },\n {\n \"id\": \"nextcloud-crawler\",\n \"category\": \"UNKNOWN\",\n \"name\": \"NextCloudBot\",\n \"patterns\": [\n \"NextCloud\"\n ],\n \"forbidden\": []\n },\n {\n \"id\": \"niki-bot\",\n \"category\": \"UNKNOWN\",\n \"name\": \"niki-bot\",\n \"patterns\": [\n \"niki-bot\"\n ],\n \"forbidden\": []\n },\n {\n \"id\": \"ning-crawler\",\n \"category\": \"UNKNOWN\",\n \"name\": \"ning-crawler\",\n \"patterns\": [\n \"NING\\\\/\"\n ],\n \"forbidden\": []\n },\n {\n \"id\": \"ninjabot\",\n \"category\": \"UNKNOWN\",\n \"name\": \"ninjabot\",\n \"patterns\": [\n \"NINJA bot\"\n ],\n \"forbidden\": []\n },\n {\n \"id\": \"nuzzel-crawler\",\n \"category\": \"UNKNOWN\",\n \"name\": \"nuzzel-crawler\",\n \"patterns\": [\n \"Nuzzel\"\n ],\n \"forbidden\": []\n },\n {\n \"id\": \"ocarinabot\",\n \"category\": \"UNKNOWN\",\n \"name\": \"ocarinabot\",\n \"patterns\": [\n \"Ocarinabot\"\n ],\n \"forbidden\": []\n },\n {\n \"id\": \"okru-crawler\",\n \"category\": \"UNKNOWN\",\n \"name\": \"okru-crawler\",\n \"patterns\": [\n \"OdklBot\\\\/\"\n ],\n \"forbidden\": []\n },\n {\n \"id\": \"opengraphcheck-crawler\",\n \"category\": \"UNKNOWN\",\n \"name\": \"opengraphcheck-crawler\",\n \"patterns\": [\n \"OpenGraphCheck\"\n ],\n \"forbidden\": []\n },\n {\n \"id\": \"openhose-crawler\",\n \"category\": \"UNKNOWN\",\n \"name\": \"openhose-crawler\",\n \"patterns\": [\n \"OpenHoseBot\"\n ],\n \"forbidden\": []\n },\n {\n \"id\": \"openindex-crawler\",\n \"category\": \"UNKNOWN\",\n \"name\": \"openindex-crawler\",\n \"patterns\": [\n \"openindexspider\"\n ],\n \"forbidden\": []\n },\n {\n \"id\": \"orange-crawler\",\n \"category\": \"UNKNOWN\",\n \"name\": \"orange-crawler\",\n \"patterns\": [\n \"OrangeBot\\\\/\"\n ],\n \"forbidden\": []\n },\n {\n \"id\": \"orange-ftgroup-crawler\",\n \"category\": \"UNKNOWN\",\n \"name\": \"orange-ftgroup-crawler\",\n \"patterns\": [\n \"voilabot\"\n ],\n \"forbidden\": []\n },\n {\n \"id\": \"outclicks-crawler\",\n \"category\": \"UNKNOWN\",\n \"name\": \"outclicks-crawler\",\n \"patterns\": [\n \"OutclicksBot\"\n ],\n \"forbidden\": []\n },\n {\n \"id\": \"page-to-rss\",\n \"category\": \"UNKNOWN\",\n \"name\": \"page-to-rss\",\n \"patterns\": [\n \"page2rss\"\n ],\n \"forbidden\": []\n },\n {\n \"id\": \"pagething-crawler\",\n \"category\": \"UNKNOWN\",\n \"name\": \"pagething-crawler\",\n \"patterns\": [\n \"PageThing\"\n ],\n \"forbidden\": []\n },\n {\n \"id\": \"paloaltonetworks-crawler\",\n \"category\": \"UNKNOWN\",\n \"name\": \"paloaltonetworks-crawler\",\n \"patterns\": [\n \"Expanse\"\n ],\n \"forbidden\": []\n },\n {\n \"id\": \"panscient-crawler\",\n \"category\": \"UNKNOWN\",\n \"name\": \"panscient-crawler\",\n \"patterns\": [\n \"panscient\"\n ],\n \"forbidden\": []\n },\n {\n \"id\": \"paperli-crawler\",\n \"category\": \"UNKNOWN\",\n \"name\": \"paperli-crawler\",\n \"patterns\": [\n \"PaperLiBot\"\n ],\n \"forbidden\": []\n },\n {\n \"id\": \"phxbot\",\n \"category\": \"UNKNOWN\",\n \"name\": \"phxbot\",\n \"patterns\": [\n \"PhxBot\"\n ],\n \"forbidden\": []\n },\n {\n \"id\": \"picsearch-crawler\",\n \"category\": \"UNKNOWN\",\n \"name\": \"picsearch-crawler\",\n \"patterns\": [\n \"psbot\"\n ],\n \"forbidden\": []\n },\n {\n \"id\": \"postrank-crawler\",\n \"category\": \"UNKNOWN\",\n \"name\": \"postrank-crawler\",\n \"patterns\": [\n \"postrank\"\n ],\n \"forbidden\": []\n },\n {\n \"id\": \"prcy-crawler\",\n \"category\": \"UNKNOWN\",\n \"name\": \"prcy-crawler\",\n \"patterns\": [\n \"PR-CY\\\\.RU\"\n ],\n \"forbidden\": []\n },\n {\n \"id\": \"privacore-crawler\",\n \"category\": \"UNKNOWN\",\n \"name\": \"privacore-crawler\",\n \"patterns\": [\n \"findxbot\"\n ],\n \"forbidden\": []\n },\n {\n \"id\": \"privacyaware-crawler\",\n \"category\": \"UNKNOWN\",\n \"name\": \"privacyaware-crawler\",\n \"patterns\": [\n \"PrivacyAwareBot\"\n ],\n \"forbidden\": []\n },\n {\n \"id\": \"profound-crawler\",\n \"category\": \"UNKNOWN\",\n \"name\": \"profound-crawler\",\n \"patterns\": [\n \"urlappendbot\"\n ],\n \"forbidden\": []\n },\n {\n \"id\": \"proximic-crawler\",\n \"category\": \"UNKNOWN\",\n \"name\": \"proximic-crawler\",\n \"patterns\": [\n \"proximic\"\n ],\n \"forbidden\": []\n },\n {\n \"id\": \"pulsepoint-crawler\",\n \"category\": \"UNKNOWN\",\n \"name\": \"pulsepoint-crawler\",\n \"patterns\": [\n \"Pulsepoint\"\n ],\n \"forbidden\": []\n },\n {\n \"id\": \"pure-crawler\",\n \"category\": \"UNKNOWN\",\n \"name\": \"pure-crawler\",\n \"patterns\": [\n \"purebot\"\n ],\n \"forbidden\": []\n },\n {\n \"id\": \"rankactive-crawler\",\n \"category\": \"UNKNOWN\",\n \"name\": \"rankactive-crawler\",\n \"patterns\": [\n \"RankActiveLinkBot\"\n ],\n \"forbidden\": []\n },\n {\n \"id\": \"retrevo-page-analyzer\",\n \"category\": \"UNKNOWN\",\n \"name\": \"retrevo-page-analyzer\",\n \"patterns\": [\n \"RetrevoPageAnalyzer\"\n ],\n \"forbidden\": []\n },\n {\n \"id\": \"ridder-crawler\",\n \"category\": \"UNKNOWN\",\n \"name\": \"ridder-crawler\",\n \"patterns\": [\n \"RidderBot\"\n ],\n \"forbidden\": []\n },\n {\n \"id\": \"rivva-crawler\",\n \"category\": \"UNKNOWN\",\n \"name\": \"rivva-crawler\",\n \"patterns\": [\n \"Rivva\"\n ],\n \"forbidden\": []\n },\n {\n \"id\": \"ryte-crawler\",\n \"category\": \"UNKNOWN\",\n \"name\": \"ryte-crawler\",\n \"patterns\": [\n \"RyteBot\"\n ],\n \"forbidden\": []\n },\n {\n \"id\": \"scan-interfax-crawler\",\n \"category\": \"UNKNOWN\",\n \"name\": \"scan-interfax-crawler\",\n \"patterns\": [\n \"InterfaxScanBot\"\n ],\n \"forbidden\": []\n },\n {\n \"id\": \"schmorp-crawler\",\n \"category\": \"UNKNOWN\",\n \"name\": \"schmorp-crawler\",\n \"patterns\": [\n \"AnyEvent\"\n ],\n \"forbidden\": []\n },\n {\n \"id\": \"scoutjet-crawler\",\n \"category\": \"UNKNOWN\",\n \"name\": \"scoutjet-crawler\",\n \"patterns\": [\n \"ScoutJet\"\n ],\n \"forbidden\": []\n },\n {\n \"id\": \"scribd-crawler\",\n \"category\": \"UNKNOWN\",\n \"name\": \"scribd-crawler\",\n \"patterns\": [\n \"scribdbot\"\n ],\n \"forbidden\": []\n },\n {\n \"id\": \"scritch-crawler\",\n \"category\": \"UNKNOWN\",\n \"name\": \"scritch-crawler\",\n \"patterns\": [\n \"Fetch\\\\/\"\n ],\n \"forbidden\": []\n },\n {\n \"id\": \"seekbot-crawler\",\n \"category\": \"UNKNOWN\",\n \"name\": \"seekbot-crawler\",\n \"patterns\": [\n \"seekbot\"\n ],\n \"forbidden\": []\n },\n {\n \"id\": \"seewithkids-crawler\",\n \"category\": \"UNKNOWN\",\n \"name\": \"seewithkids-crawler\",\n \"patterns\": [\n \"seewithkids\"\n ],\n \"forbidden\": []\n },\n {\n \"id\": \"semanticaudience-crawler\",\n \"category\": \"UNKNOWN\",\n \"name\": \"semanticaudience-crawler\",\n \"patterns\": [\n \"semanticbot\"\n ],\n \"forbidden\": []\n },\n {\n \"id\": \"sempitech-crawler\",\n \"category\": \"UNKNOWN\",\n \"name\": \"sempitech-crawler\",\n \"patterns\": [\n \"sempi\\\\.tech\"\n ],\n \"forbidden\": []\n },\n {\n \"id\": \"semrush-crawler\",\n \"category\": \"UNKNOWN\",\n \"name\": \"SemRushBot\",\n \"patterns\": [\n \"S[eE][mM]rushBot\"\n ],\n \"forbidden\": []\n },\n {\n \"id\": \"senuto-crawler\",\n \"category\": \"UNKNOWN\",\n \"name\": \"senuto-crawler\",\n \"patterns\": [\n \"SenutoBot\"\n ],\n \"forbidden\": []\n },\n {\n \"id\": \"seobility-crawler\",\n \"category\": \"UNKNOWN\",\n \"name\": \"seobility-crawler\",\n \"patterns\": [\n \"SeobilityBot\"\n ],\n \"forbidden\": []\n },\n {\n \"id\": \"seokicks-crawler\",\n \"category\": \"UNKNOWN\",\n \"name\": \"seokicks-crawler\",\n \"patterns\": [\n \"SEOkicks\"\n ],\n \"forbidden\": []\n },\n {\n \"id\": \"seolizer-crawler\",\n \"category\": \"UNKNOWN\",\n \"name\": \"seolizer-crawler\",\n \"patterns\": [\n \"SEOlizer\"\n ],\n \"forbidden\": []\n },\n {\n \"id\": \"seoprofiler-crawler\",\n \"category\": \"UNKNOWN\",\n \"name\": \"seoprofiler-crawler\",\n \"patterns\": [\n \"spbot\"\n ],\n \"forbidden\": []\n },\n {\n \"id\": \"seoscanners-crawler\",\n \"category\": \"UNKNOWN\",\n \"name\": \"seoscanners-crawler\",\n \"patterns\": [\n \"seoscanners\"\n ],\n \"forbidden\": []\n },\n {\n \"id\": \"seostar-crawler\",\n \"category\": \"UNKNOWN\",\n \"name\": \"seostar-crawler\",\n \"patterns\": [\n \"seostar\\\\.co\"\n ],\n \"forbidden\": []\n },\n {\n \"id\": \"seozoom-crawler\",\n \"category\": \"UNKNOWN\",\n \"name\": \"ZoomBot\",\n \"patterns\": [\n \"ZoomBot\"\n ],\n \"forbidden\": []\n },\n {\n \"id\": \"serpstatbot-crawler\",\n \"category\": \"UNKNOWN\",\n \"name\": \"serpstatbot-crawler\",\n \"patterns\": [\n \"serpstatbot\\\\/\"\n ],\n \"forbidden\": []\n },\n {\n \"id\": \"seznam-crawler\",\n \"category\": \"UNKNOWN\",\n \"name\": \"seznam-crawler\",\n \"patterns\": [\n \"SeznamBot\"\n ],\n \"forbidden\": []\n },\n {\n \"id\": \"similartech-crawler\",\n \"category\": \"UNKNOWN\",\n \"name\": \"similartech-crawler\",\n \"patterns\": [\n \"smtbot\"\n ],\n \"forbidden\": []\n },\n {\n \"id\": \"simple-crawler\",\n \"category\": \"UNKNOWN\",\n \"name\": \"simple-crawler\",\n \"patterns\": [\n \"SimpleCrawler\"\n ],\n \"forbidden\": []\n },\n {\n \"id\": \"sistrix-007ac9-crawler\",\n \"category\": \"UNKNOWN\",\n \"name\": \"sistrix-007ac9-crawler\",\n \"patterns\": [\n \"007ac9 Crawler\"\n ],\n \"forbidden\": []\n },\n {\n \"id\": \"sitebot-crawler\",\n \"category\": \"UNKNOWN\",\n \"name\": \"sitebot-crawler\",\n \"patterns\": [\n \"sitebot\"\n ],\n \"forbidden\": []\n },\n {\n \"id\": \"sitechecker-crawler\",\n \"category\": \"UNKNOWN\",\n \"name\": \"sitechecker-crawler\",\n \"patterns\": [\n \"SiteCheckerBotCrawler\"\n ],\n \"forbidden\": []\n },\n {\n \"id\": \"siteexplorer-crawler\",\n \"category\": \"UNKNOWN\",\n \"name\": \"siteexplorer-crawler\",\n \"patterns\": [\n \"siteexplorer\\\\.info\"\n ],\n \"forbidden\": []\n },\n {\n \"id\": \"siteimprove-crawler\",\n \"category\": \"UNKNOWN\",\n \"name\": \"siteimprove-crawler\",\n \"patterns\": [\n \"Siteimprove\\\\.com\"\n ],\n \"forbidden\": []\n },\n {\n \"id\": \"socialrank-crawler\",\n \"category\": \"UNKNOWN\",\n \"name\": \"socialrank-crawler\",\n \"patterns\": [\n \"SocialRankIOBot\"\n ],\n \"forbidden\": []\n },\n {\n \"id\": \"softbytelabs-crawler\",\n \"category\": \"UNKNOWN\",\n \"name\": \"softbytelabs-crawler\",\n \"patterns\": [\n \"SBL-BOT\"\n ],\n \"forbidden\": []\n },\n {\n \"id\": \"sogou-crawler\",\n \"category\": \"UNKNOWN\",\n \"name\": \"sogou-crawler\",\n \"patterns\": [\n \"Sogou\"\n ],\n \"forbidden\": []\n },\n {\n \"id\": \"stuttgart-crawler\",\n \"category\": \"UNKNOWN\",\n \"name\": \"stuttgart-crawler\",\n \"patterns\": [\n \"RegionStuttgartBot\"\n ],\n \"forbidden\": []\n },\n {\n \"id\": \"summify-crawler\",\n \"category\": \"UNKNOWN\",\n \"name\": \"summify-crawler\",\n \"patterns\": [\n \"summify\"\n ],\n \"forbidden\": []\n },\n {\n \"id\": \"swimgbot\",\n \"category\": \"UNKNOWN\",\n \"name\": \"swimgbot\",\n \"patterns\": [\n \"SWIMGBot\"\n ],\n \"forbidden\": []\n },\n {\n \"id\": \"sysomos-crawler\",\n \"category\": \"UNKNOWN\",\n \"name\": \"sysomos-crawler\",\n \"patterns\": [\n \"Sysomos\"\n ],\n \"forbidden\": []\n },\n {\n \"id\": \"t3versions-crawler\",\n \"category\": \"UNKNOWN\",\n \"name\": \"t3versions-crawler\",\n \"patterns\": [\n \"t3versionsBot\"\n ],\n \"forbidden\": []\n },\n {\n \"id\": \"taboola-crawler\",\n \"category\": \"UNKNOWN\",\n \"name\": \"taboola-crawler\",\n \"patterns\": [\n \"Taboolabot\"\n ],\n \"forbidden\": []\n },\n {\n \"id\": \"tagoo-crawler\",\n \"category\": \"UNKNOWN\",\n \"name\": \"tagoo-crawler\",\n \"patterns\": [\n \"tagoobot\"\n ],\n \"forbidden\": []\n },\n {\n \"id\": \"tangiblee-crawler\",\n \"category\": \"UNKNOWN\",\n \"name\": \"tangiblee-crawler\",\n \"patterns\": [\n \"TangibleeBot\"\n ],\n \"forbidden\": []\n },\n {\n \"id\": \"thinklab-crawler\",\n \"category\": \"UNKNOWN\",\n \"name\": \"thinklab-crawler\",\n \"patterns\": [\n \"Thinklab\"\n ],\n \"forbidden\": []\n },\n {\n \"id\": \"tiger-crawler\",\n \"category\": \"UNKNOWN\",\n \"name\": \"tiger-crawler\",\n \"patterns\": [\n \"tigerbot\"\n ],\n \"forbidden\": []\n },\n {\n \"id\": \"tineye-crawler\",\n \"category\": \"UNKNOWN\",\n \"name\": \"tineye-crawler\",\n \"patterns\": [\n \"TinEye\"\n ],\n \"forbidden\": []\n },\n {\n \"id\": \"tiscali-crawler\",\n \"category\": \"UNKNOWN\",\n \"name\": \"tiscali-crawler\",\n \"patterns\": [\n \"IstellaBot\"\n ],\n \"forbidden\": []\n },\n {\n \"id\": \"tombascraper-crawler\",\n \"category\": \"UNKNOWN\",\n \"name\": \"tombascraper-crawler\",\n \"patterns\": [\n \"TombaPublicWebCrawler\"\n ],\n \"forbidden\": []\n },\n {\n \"id\": \"toplist-crawler\",\n \"category\": \"UNKNOWN\",\n \"name\": \"toplist-crawler\",\n \"patterns\": [\n \"toplistbot\"\n ],\n \"forbidden\": []\n },\n {\n \"id\": \"torus-crawler\",\n \"category\": \"UNKNOWN\",\n \"name\": \"torus-crawler\",\n \"patterns\": [\n \"ReverseEngineeringBot\"\n ],\n \"forbidden\": []\n },\n {\n \"id\": \"toutiao-crawler\",\n \"category\": \"UNKNOWN\",\n \"name\": \"toutiao-crawler\",\n \"patterns\": [\n \"ToutiaoSpider\"\n ],\n \"forbidden\": []\n },\n {\n \"id\": \"traackr-crawler\",\n \"category\": \"UNKNOWN\",\n \"name\": \"traackr-crawler\",\n \"patterns\": [\n \"Traackr\\\\.com\"\n ],\n \"forbidden\": []\n },\n {\n \"id\": \"tracemyfile-crawler\",\n \"category\": \"UNKNOWN\",\n \"name\": \"tracemyfile-crawler\",\n \"patterns\": [\n \"tracemyfile\"\n ],\n \"forbidden\": []\n },\n {\n \"id\": \"trendiction-crawler\",\n \"category\": \"UNKNOWN\",\n \"name\": \"trendiction-crawler\",\n \"patterns\": [\n \"trendictionbot\"\n ],\n \"forbidden\": []\n },\n {\n \"id\": \"trove-crawler\",\n \"category\": \"UNKNOWN\",\n \"name\": \"trove-crawler\",\n \"patterns\": [\n \"Trove\"\n ],\n \"forbidden\": []\n },\n {\n \"id\": \"trovit-crawler\",\n \"category\": \"UNKNOWN\",\n \"name\": \"trovit-crawler\",\n \"patterns\": [\n \"trovitBot\"\n ],\n \"forbidden\": []\n },\n {\n \"id\": \"tweetmemebot\",\n \"category\": \"UNKNOWN\",\n \"name\": \"tweetmemebot\",\n \"patterns\": [\n \"TweetmemeBot\"\n ],\n \"forbidden\": []\n },\n {\n \"id\": \"twenga-crawler\",\n \"category\": \"UNKNOWN\",\n \"name\": \"twenga-crawler\",\n \"patterns\": [\n \"twengabot\"\n ],\n \"forbidden\": []\n },\n {\n \"id\": \"twingly-crawler\",\n \"category\": \"UNKNOWN\",\n \"name\": \"twingly-crawler\",\n \"patterns\": [\n \"Twingly\"\n ],\n \"forbidden\": []\n },\n {\n \"id\": \"twoip-crawler\",\n \"category\": \"UNKNOWN\",\n \"name\": \"twoip-crawler\",\n \"patterns\": [\n \"2ip bot\"\n ],\n \"forbidden\": []\n },\n {\n \"id\": \"twoip-crawler-cms\",\n \"category\": \"UNKNOWN\",\n \"name\": \"twoip-crawler-cms\",\n \"patterns\": [\n \"2ip\\\\.ru\"\n ],\n \"forbidden\": []\n },\n {\n \"id\": \"twurly-crawler\",\n \"category\": \"UNKNOWN\",\n \"name\": \"twurly-crawler\",\n \"patterns\": [\n \"Twurly\"\n ],\n \"forbidden\": []\n },\n {\n \"id\": \"ubermetrics-crawler\",\n \"category\": \"UNKNOWN\",\n \"name\": \"ubermetrics-crawler\",\n \"patterns\": [\n \"um-LN\"\n ],\n \"forbidden\": []\n },\n {\n \"id\": \"ubt-crawler\",\n \"category\": \"UNKNOWN\",\n \"name\": \"ubt-crawler\",\n \"patterns\": [\n \"Streamline3Bot\\\\/\"\n ],\n \"forbidden\": []\n },\n {\n \"id\": \"upflow-crawler\",\n \"category\": \"UNKNOWN\",\n \"name\": \"upflow-crawler\",\n \"patterns\": [\n \"Upflow\"\n ],\n \"forbidden\": []\n },\n {\n \"id\": \"urlclassification-crawler\",\n \"category\": \"UNKNOWN\",\n \"name\": \"urlclassification-crawler\",\n \"patterns\": [\n \"KStandBot\"\n ],\n \"forbidden\": []\n },\n {\n \"id\": \"usine-nouvelle-crawler\",\n \"category\": \"UNKNOWN\",\n \"name\": \"usine-nouvelle-crawler\",\n \"patterns\": [\n \"UsineNouvelleCrawler\"\n ],\n \"forbidden\": []\n },\n {\n \"id\": \"utorrent-crawler\",\n \"category\": \"UNKNOWN\",\n \"name\": \"utorrent-crawler\",\n \"patterns\": [\n \"BTWebClient\"\n ],\n \"forbidden\": []\n },\n {\n \"id\": \"vebidoo-crawler\",\n \"category\": \"UNKNOWN\",\n \"name\": \"vebidoo-crawler\",\n \"patterns\": [\n \"vebidoobot\"\n ],\n \"forbidden\": []\n },\n {\n \"id\": \"veooz-crawler\",\n \"category\": \"UNKNOWN\",\n \"name\": \"veooz-crawler\",\n \"patterns\": [\n \"Veoozbot\"\n ],\n \"forbidden\": []\n },\n {\n \"id\": \"verisign-ips-agent\",\n \"category\": \"UNKNOWN\",\n \"name\": \"verisign-ips-agent\",\n \"patterns\": [\n \"ips-agent\"\n ],\n \"forbidden\": []\n },\n {\n \"id\": \"vigil-crawler\",\n \"category\": \"UNKNOWN\",\n \"name\": \"vigil-crawler\",\n \"patterns\": [\n \"Vigil\\\\/\"\n ],\n \"forbidden\": []\n },\n {\n \"id\": \"vipnytt-crawler\",\n \"category\": \"UNKNOWN\",\n \"name\": \"vipnytt-crawler\",\n \"patterns\": [\n \"jpg-newsbot\"\n ],\n \"forbidden\": []\n },\n {\n \"id\": \"virustotal-crawler\",\n \"category\": \"UNKNOWN\",\n \"name\": \"virustotal-crawler\",\n \"patterns\": [\n \"virustotal\"\n ],\n \"forbidden\": []\n },\n {\n \"id\": \"vkrobot-crawler\",\n \"category\": \"UNKNOWN\",\n \"name\": \"vkrobot-crawler\",\n \"patterns\": [\n \"VKRobot\"\n ],\n \"forbidden\": []\n },\n {\n \"id\": \"vkshare-crawler\",\n \"category\": \"UNKNOWN\",\n \"name\": \"vkshare-crawler\",\n \"patterns\": [\n \"vkShare\"\n ],\n \"forbidden\": []\n },\n {\n \"id\": \"vuhuv-crawler\",\n \"category\": \"UNKNOWN\",\n \"name\": \"vuhuv-crawler\",\n \"patterns\": [\n \"vuhuvBot\"\n ],\n \"forbidden\": []\n },\n {\n \"id\": \"warebay-crawler\",\n \"category\": \"UNKNOWN\",\n \"name\": \"warebay-crawler\",\n \"patterns\": [\n \"wbsearchbot\"\n ],\n \"forbidden\": []\n },\n {\n \"id\": \"webceo-crawler\",\n \"category\": \"UNKNOWN\",\n \"name\": \"webceo-crawler\",\n \"patterns\": [\n \"online-webceo-bot\"\n ],\n \"forbidden\": []\n },\n {\n \"id\": \"webcompany-crawler\",\n \"category\": \"UNKNOWN\",\n \"name\": \"webcompany-crawler\",\n \"patterns\": [\n \"webcompanycrawler\"\n ],\n \"forbidden\": []\n },\n {\n \"id\": \"webdatastats-crawler\",\n \"category\": \"UNKNOWN\",\n \"name\": \"webdatastats-crawler\",\n \"patterns\": [\n \"WebDataStats\"\n ],\n \"forbidden\": []\n },\n {\n \"id\": \"webeaver-crawler\",\n \"category\": \"UNKNOWN\",\n \"name\": \"webeaver-crawler\",\n \"patterns\": [\n \"BehloolBot\"\n ],\n \"forbidden\": []\n },\n {\n \"id\": \"webmeup-crawler\",\n \"category\": \"UNKNOWN\",\n \"name\": \"webmeup-crawler\",\n \"patterns\": [\n \"BLEXBot\\\\/\"\n ],\n \"forbidden\": []\n },\n {\n \"id\": \"webmon\",\n \"category\": \"UNKNOWN\",\n \"name\": \"webmon\",\n \"patterns\": [\n \"webmon \"\n ],\n \"forbidden\": []\n },\n {\n \"id\": \"wesee-crawler\",\n \"category\": \"UNKNOWN\",\n \"name\": \"wesee-crawler\",\n \"patterns\": [\n \"WeSEE:Search\"\n ],\n \"forbidden\": []\n },\n {\n \"id\": \"wocodi-crawler\",\n \"category\": \"UNKNOWN\",\n \"name\": \"wocodi-crawler\",\n \"patterns\": [\n \"wocbot\"\n ],\n \"forbidden\": []\n },\n {\n \"id\": \"woorank-crawler\",\n \"category\": \"UNKNOWN\",\n \"name\": \"woorank-crawler\",\n \"patterns\": [\n \"woobot\"\n ],\n \"forbidden\": []\n },\n {\n \"id\": \"woorank-crawler-review\",\n \"category\": \"UNKNOWN\",\n \"name\": \"woorank-crawler-review\",\n \"patterns\": [\n \"woorankreview\\\\/\"\n ],\n \"forbidden\": []\n },\n {\n \"id\": \"wordpress-crawler\",\n \"category\": \"UNKNOWN\",\n \"name\": \"WordPressBot\",\n \"patterns\": [\n \"WordPress\\\\/\"\n ],\n \"forbidden\": []\n },\n {\n \"id\": \"wordup-crawler\",\n \"category\": \"UNKNOWN\",\n \"name\": \"wordup-crawler\",\n \"patterns\": [\n \"WordupInfoSearch\"\n ],\n \"forbidden\": []\n },\n {\n \"id\": \"worio-crawler\",\n \"category\": \"UNKNOWN\",\n \"name\": \"worio-crawler\",\n \"patterns\": [\n \"woriobot\"\n ],\n \"forbidden\": []\n },\n {\n \"id\": \"wotbox-crawler\",\n \"category\": \"UNKNOWN\",\n \"name\": \"wotbox-crawler\",\n \"patterns\": [\n \"wotbox\"\n ],\n \"forbidden\": []\n },\n {\n \"id\": \"xovibot-crawler\",\n \"category\": \"UNKNOWN\",\n \"name\": \"xovibot-crawler\",\n \"patterns\": [\n \"xovibot\"\n ],\n \"forbidden\": []\n },\n {\n \"id\": \"yanga-crawler\",\n \"category\": \"UNKNOWN\",\n \"name\": \"yanga-crawler\",\n \"patterns\": [\n \"yanga\"\n ],\n \"forbidden\": []\n },\n {\n \"id\": \"yellowbp-crawler\",\n \"category\": \"UNKNOWN\",\n \"name\": \"yellowbp-crawler\",\n \"patterns\": [\n \"Yellowbrandprotectionbot\"\n ],\n \"forbidden\": []\n },\n {\n \"id\": \"yisou-crawler\",\n \"category\": \"UNKNOWN\",\n \"name\": \"yisou-crawler\",\n \"patterns\": [\n \"YisouSpider\"\n ],\n \"forbidden\": []\n },\n {\n \"id\": \"yooz-crawler\",\n \"category\": \"UNKNOWN\",\n \"name\": \"yooz-crawler\",\n \"patterns\": [\n \"yoozBot\"\n ],\n \"forbidden\": []\n },\n {\n \"id\": \"zoominfo-crawler\",\n \"category\": \"UNKNOWN\",\n \"name\": \"zoominfo-crawler\",\n \"patterns\": [\n \"ZoominfoBot\"\n ],\n \"forbidden\": []\n },\n {\n \"id\": \"zum-crawler\",\n \"category\": \"UNKNOWN\",\n \"name\": \"ZumBot\",\n \"patterns\": [\n \"ZumBot\"\n ],\n \"forbidden\": []\n },\n {\n \"id\": \"zuperlist-crawler\",\n \"category\": \"UNKNOWN\",\n \"name\": \"zuperlist-crawler\",\n \"patterns\": [\n \"ZuperlistBot\\\\/\"\n ],\n \"forbidden\": []\n }\n]","/**\n * @module @arcis/node/middleware/bot-detection\n * Local-only bot detection using User-Agent and behavioral signals.\n *\n * Categorizes requests into bot types and allows/denies based on config.\n * No cloud calls — everything runs locally.\n *\n * @example\n * // Block automated tools, allow search engines\n * app.use(botProtection({\n * allow: ['SEARCH_ENGINE', 'SOCIAL', 'MONITORING'],\n * deny: ['AUTOMATED', 'SCRAPER'],\n * }));\n */\n\nimport type { Request, Response, NextFunction, RequestHandler } from 'express';\nimport BOT_PATTERN_DATA from '../data/bot-patterns.json';\n\n// =============================================================================\n// BOT CATEGORIES\n// =============================================================================\n\nexport type BotCategory =\n | 'SEARCH_ENGINE'\n | 'SOCIAL'\n | 'MONITORING'\n | 'AI_CRAWLER'\n | 'SCRAPER'\n | 'AUTOMATED'\n | 'UNKNOWN'\n | 'HUMAN';\n\nexport interface BotDetectionResult {\n /** Whether the request appears to be from a bot */\n isBot: boolean;\n /** Bot category */\n category: BotCategory;\n /** Matched bot name (e.g. 'Googlebot', 'curl') or null */\n name: string | null;\n /** Confidence score: 0-1 */\n confidence: number;\n /** Behavioral signals detected */\n signals: string[];\n}\n\nexport interface BotProtectionOptions {\n /** Categories to explicitly allow. Default: ['SEARCH_ENGINE', 'SOCIAL', 'MONITORING'] */\n allow?: BotCategory[];\n /** Categories to explicitly deny. Default: ['AUTOMATED'] */\n deny?: BotCategory[];\n /** Action for categories not in allow or deny. Default: 'allow' */\n defaultAction?: 'allow' | 'deny';\n /** HTTP status code for denied bots. Default: 403 */\n statusCode?: number;\n /** Error message for denied bots */\n message?: string;\n /** Enable behavioral signal detection. Default: true */\n detectBehavior?: boolean;\n /** Custom handler called on detection (instead of default deny response) */\n onDetected?: (req: Request, res: Response, result: BotDetectionResult) => void;\n}\n\n// =============================================================================\n// BOT DATABASE\n// =============================================================================\n\ninterface BotPattern {\n /** Compiled regex(es) to match against the User-Agent. ANY match counts. */\n patterns: RegExp[];\n /** Compiled forbidden patterns. If ANY matches, this entry is rejected. */\n forbidden: RegExp[];\n /** Bot name (e.g. 'Googlebot') */\n name: string;\n /** Category */\n category: BotCategory;\n /** Stable identifier from the source corpus */\n id: string;\n}\n\n/**\n * Source data for the bot corpus — `packages/core/bot-patterns.json`, derived\n * from arcjet/well-known-bots (MIT) plus a supplementary list of browser\n * automation tools the upstream doesn't separately track. Regenerate via\n * `python packages/core/generate-bot-patterns.py` after upgrading the source.\n */\ninterface BotPatternData {\n id: string;\n name: string;\n category: string;\n patterns: string[];\n forbidden: string[];\n}\n\nfunction compilePattern(source: string): RegExp {\n // Patterns from the corpus are JS-style regex bodies (no enclosing /.../ ).\n // Compile case-insensitive: matches Arcis's documented contract that bot\n // detection ignores UA case (`GPTBOT` and `gptbot` match the same entry).\n // This is additive on top of Arcjet's explicit character classes like\n // `[wW]get` — the `i` flag doesn't conflict with character ranges.\n return new RegExp(source, 'i');\n}\n\nconst BOT_PATTERNS: BotPattern[] = (BOT_PATTERN_DATA as BotPatternData[]).map((entry) => ({\n id: entry.id,\n name: entry.name,\n category: entry.category as BotCategory,\n patterns: entry.patterns.map(compilePattern),\n forbidden: entry.forbidden.map(compilePattern),\n}));\n\n\n// =============================================================================\n// DETECTION ENGINE\n// =============================================================================\n\n/**\n * Detect behavioral signals that suggest a bot.\n */\nfunction detectBehavioralSignals(req: Request): string[] {\n const signals: string[] = [];\n const headers = req.headers;\n\n // Missing User-Agent\n if (!headers['user-agent']) {\n signals.push('missing_user_agent');\n }\n\n // Missing Accept header (browsers always send this)\n if (!headers['accept']) {\n signals.push('missing_accept');\n }\n\n // Missing Accept-Language (browsers always send this)\n if (!headers['accept-language']) {\n signals.push('missing_accept_language');\n }\n\n // Missing Accept-Encoding (browsers always send this)\n if (!headers['accept-encoding']) {\n signals.push('missing_accept_encoding');\n }\n\n // Connection: close (browsers typically use keep-alive)\n if (headers['connection'] === 'close') {\n signals.push('connection_close');\n }\n\n return signals;\n}\n\n/**\n * Detect what kind of bot (if any) is making the request.\n *\n * @param req - HTTP request object\n * @returns Detection result with category, name, confidence, and signals\n *\n * @example\n * const result = detectBot(req);\n * if (result.isBot && result.category === 'AUTOMATED') {\n * // Block automated tools\n * }\n */\nexport function detectBot(req: Request): BotDetectionResult {\n const rawUa = req.headers['user-agent'] ?? '';\n // SECURITY: A UA longer than 2048 chars is either buggy client or attempt to hide\n // a bot signature past a truncation boundary. Flag as suspicious bot directly —\n // don't silently truncate and continue.\n if (rawUa.length > 2048) {\n return {\n isBot: true,\n category: 'UNKNOWN',\n name: null,\n confidence: 0.9,\n signals: detectBehavioralSignals(req),\n };\n }\n const ua = rawUa;\n const signals = detectBehavioralSignals(req);\n\n // No User-Agent at all\n if (!ua) {\n return {\n isBot: true,\n category: 'UNKNOWN',\n name: null,\n confidence: 0.8,\n signals,\n };\n }\n\n // Match against known bot patterns. An entry matches when ALL of its\n // accepted patterns match AND none of its forbidden patterns matches.\n // ALL-of semantics makes multi-pattern entries (e.g. iMessage-Preview which\n // expects both `facebookexternalhit` and `Twitterbot` in the same UA) only\n // fire on real iMessage traffic, not on bare `Twitterbot/1.0` requests.\n // Single-pattern entries (the common case) reduce trivially to that one\n // pattern matching.\n for (const bot of BOT_PATTERNS) {\n let allMatched = bot.patterns.length > 0;\n for (const pattern of bot.patterns) {\n if (!pattern.test(ua)) {\n allMatched = false;\n break;\n }\n }\n if (!allMatched) continue;\n\n let forbidden = false;\n for (const pattern of bot.forbidden) {\n if (pattern.test(ua)) {\n forbidden = true;\n break;\n }\n }\n if (forbidden) continue;\n\n return {\n isBot: true,\n category: bot.category,\n name: bot.name,\n confidence: 0.95,\n signals,\n };\n }\n\n // Behavioral analysis for unrecognized UAs\n const behaviorScore = signals.length;\n\n // 3+ missing standard headers = likely bot\n if (behaviorScore >= 3) {\n return {\n isBot: true,\n category: 'UNKNOWN',\n name: null,\n confidence: Math.min(1.0, 0.6 + (behaviorScore * 0.1)),\n signals,\n };\n }\n\n return {\n isBot: false,\n category: 'HUMAN',\n name: null,\n confidence: Math.max(0.0, 1.0 - (behaviorScore * 0.15)),\n signals,\n };\n}\n\n/**\n * Create Express middleware for bot protection.\n *\n * @example\n * // Block automated tools and scrapers\n * app.use(botProtection({\n * allow: ['SEARCH_ENGINE', 'SOCIAL', 'MONITORING'],\n * deny: ['AUTOMATED', 'SCRAPER'],\n * }));\n *\n * @example\n * // Block everything except search engines\n * app.use(botProtection({\n * allow: ['SEARCH_ENGINE'],\n * defaultAction: 'deny',\n * }));\n *\n * @example\n * // Custom handler\n * app.use(botProtection({\n * deny: ['AUTOMATED'],\n * onDetected: (req, res, result) => {\n * console.log(`Bot blocked: ${result.name} (${result.category})`);\n * res.status(403).json({ error: 'Bots not allowed' });\n * },\n * }));\n */\nexport function botProtection(options: BotProtectionOptions = {}): RequestHandler {\n const {\n allow = ['SEARCH_ENGINE', 'SOCIAL', 'MONITORING'],\n deny = ['AUTOMATED'],\n defaultAction = 'allow',\n statusCode = 403,\n message = 'Access denied.',\n onDetected,\n } = options;\n\n const allowSet = new Set(allow);\n const denySet = new Set(deny);\n\n return (req: Request, res: Response, next: NextFunction) => {\n const result = detectBot(req);\n\n // Attach result to request for downstream use\n (req as unknown as Record<string, unknown>).botDetection = result;\n\n // Humans always pass\n if (!result.isBot) {\n return next();\n }\n\n // Check explicit allow/deny lists\n if (allowSet.has(result.category)) {\n return next();\n }\n\n if (denySet.has(result.category)) {\n // Telemetry attribution: dashboard groups bot denials under vector=bot.\n req.__arcis = {\n vector: 'bot',\n rule: `bot/${result.category.toLowerCase()}`,\n severity: 'medium',\n reason: result.name ? `Bot detected: ${result.name}` : 'Bot detected',\n decision: 'deny',\n };\n if (onDetected) {\n return onDetected(req, res, result);\n }\n res.status(statusCode).json({ error: message });\n return;\n }\n\n // Default action for uncategorized bots\n if (defaultAction === 'deny') {\n req.__arcis = {\n vector: 'bot',\n rule: 'bot/uncategorized',\n severity: 'medium',\n reason: 'Uncategorized bot under defaultAction=deny',\n decision: 'deny',\n };\n if (onDetected) {\n return onDetected(req, res, result);\n }\n res.status(statusCode).json({ error: message });\n return;\n }\n\n next();\n };\n}\n","/**\n * @module @arcis/node/middleware/csrf\n * CSRF (Cross-Site Request Forgery) protection middleware\n *\n * Implements the double-submit cookie pattern:\n * 1. Server sets a CSRF token in a cookie\n * 2. Client must send the same token in a header or form field\n * 3. Middleware rejects requests where cookie token !== header/field token\n *\n * This works because an attacker's cross-origin form submission will include\n * the cookie automatically, but cannot read it (same-origin policy) to set\n * the matching header.\n */\n\nimport { randomBytes, timingSafeEqual } from 'crypto';\nimport type { Request, Response, NextFunction, RequestHandler } from 'express';\n\n/** CSRF protection configuration */\nexport interface CsrfOptions {\n /** Cookie name for the CSRF token. Default: '_csrf' */\n cookieName?: string;\n /** Header name to check for the token. Default: 'x-csrf-token' */\n headerName?: string;\n /** Form field name to check for the token. Default: '_csrf' */\n fieldName?: string;\n /** Token byte length (hex-encoded = 2x chars). Default: 32 */\n tokenLength?: number;\n /** HTTP methods to protect. Default: ['POST', 'PUT', 'PATCH', 'DELETE'] */\n protectedMethods?: string[];\n /** Paths to exclude from CSRF checks (e.g., webhook endpoints) */\n excludePaths?: string[];\n /**\n * Per-request skip function. If it returns true, CSRF check is skipped\n * for that request. Useful for API key auth or signed webhooks.\n *\n * @example\n * skipCsrf: (req) => Boolean(req.headers['x-api-key'])\n */\n skipCsrf?: (req: Request) => boolean;\n /**\n * Use the __Host- cookie prefix for stronger cookie security.\n * When enabled, the browser enforces: Secure=true, no Domain, Path=/.\n * This prevents CSRF cookie theft across subdomains.\n * Default: false\n */\n useHostPrefix?: boolean;\n /** Cookie options */\n cookie?: {\n /** Cookie path. Default: '/' */\n path?: string;\n /** HttpOnly — set false so client JS can read it for headers. Default: false */\n httpOnly?: boolean;\n /** Secure flag (HTTPS only). Default: true in production */\n secure?: boolean;\n /** SameSite attribute. Default: 'Lax' */\n sameSite?: 'Strict' | 'Lax' | 'None';\n /** Cookie domain */\n domain?: string;\n };\n /** Custom error handler when CSRF validation fails */\n onError?: (req: Request, res: Response, next: NextFunction) => void;\n /**\n * Rotate the CSRF token after each successful validation on a protected\n * method. Defends against token-fixation attacks where an attacker plants\n * a known token before authentication. Default: false.\n *\n * When enabled, every successful POST/PUT/PATCH/DELETE causes the server to\n * issue a fresh token via Set-Cookie — the client must re-read the cookie\n * before the next mutating request.\n */\n rotateOnUse?: boolean;\n}\n\nconst DEFAULTS = {\n cookieName: '_csrf',\n headerName: 'x-csrf-token',\n fieldName: '_csrf',\n tokenLength: 32,\n protectedMethods: ['POST', 'PUT', 'PATCH', 'DELETE'],\n} as const;\n\n/**\n * Generate a cryptographically random CSRF token.\n *\n * @param length - Byte length (output is hex, so 2x chars). Default: 32\n * @returns Hex-encoded random token\n *\n * @example\n * const token = generateCsrfToken(); // 64 hex chars\n */\nexport function generateCsrfToken(length: number = 32): string {\n return randomBytes(length).toString('hex');\n}\n\n/**\n * Validate that two CSRF tokens match using constant-time comparison.\n *\n * @param cookieToken - Token from the cookie\n * @param requestToken - Token from the header or form field\n * @returns true if tokens match\n */\nexport function validateCsrfToken(cookieToken: string, requestToken: string): boolean {\n if (!cookieToken || !requestToken) return false;\n\n // SECURITY: Pad both buffers to a common reference length before\n // timingSafeEqual so an early length-check does not leak token length\n // through timing. Compute length-equality with a constant-time integer\n // compare and AND it AFTER the byte compare so execution time is the\n // same regardless of length mismatch.\n const paddedLength = Math.max(64, cookieToken.length, requestToken.length);\n const a = Buffer.alloc(paddedLength);\n const b = Buffer.alloc(paddedLength);\n Buffer.from(cookieToken, 'utf8').copy(a);\n Buffer.from(requestToken, 'utf8').copy(b);\n const bytesEqual = timingSafeEqual(a, b);\n const sameLength = cookieToken.length === requestToken.length;\n return bytesEqual && sameLength;\n}\n\n/**\n * Extract the CSRF token from a request (checks header, then body field, then query).\n */\nfunction getRequestToken(req: Request, headerName: string, fieldName: string): string | undefined {\n // 1. Check header (most common for SPAs)\n const headerToken = req.headers[headerName.toLowerCase()];\n if (typeof headerToken === 'string' && headerToken) return headerToken;\n\n // 2. Check body field (form submissions)\n if (req.body && typeof req.body === 'object' && fieldName in req.body) {\n const bodyToken = req.body[fieldName];\n if (typeof bodyToken === 'string' && bodyToken) return bodyToken;\n }\n\n // SECURITY: Query string intentionally not supported — tokens in URLs leak\n // to server logs, Referer headers, browser history, and CDN/proxy logs.\n\n return undefined;\n}\n\n/**\n * Create CSRF protection middleware using double-submit cookie pattern.\n *\n * For safe methods (GET, HEAD, OPTIONS), sets a CSRF token cookie if not present.\n * For unsafe methods (POST, PUT, PATCH, DELETE), validates the token.\n *\n * @param options - CSRF configuration\n * @returns Express middleware\n *\n * @example\n * // Basic usage\n * app.use(csrfProtection());\n *\n * @example\n * // Exclude webhook paths\n * app.use(csrfProtection({\n * excludePaths: ['/api/webhooks/stripe', '/api/webhooks/github']\n * }));\n *\n * @example\n * // Client-side: read cookie + set header\n * const token = document.cookie.match(/_csrf=([^;]+)/)?.[1];\n * fetch('/api/data', {\n * method: 'POST',\n * headers: { 'X-CSRF-Token': token },\n * credentials: 'same-origin'\n * });\n */\nexport function csrfProtection(options: CsrfOptions = {}): RequestHandler {\n const baseCookieName = options.cookieName ?? DEFAULTS.cookieName;\n // __Host- prefix: forces browser to enforce Secure + no Domain + Path=/\n const cookieName = options.useHostPrefix ? `__Host-${baseCookieName}` : baseCookieName;\n const headerName = options.headerName ?? DEFAULTS.headerName;\n const fieldName = options.fieldName ?? DEFAULTS.fieldName;\n const tokenLength = options.tokenLength ?? DEFAULTS.tokenLength;\n const protectedMethods = options.protectedMethods ?? [...DEFAULTS.protectedMethods];\n const excludePaths = options.excludePaths ?? [];\n const skipCsrf = options.skipCsrf;\n\n const isProduction = process.env.NODE_ENV === 'production';\n const cookieOpts = {\n path: options.cookie?.path ?? '/',\n httpOnly: options.cookie?.httpOnly ?? false, // Must be readable by client JS\n secure: options.cookie?.secure ?? isProduction,\n sameSite: options.cookie?.sameSite ?? 'Lax',\n domain: options.cookie?.domain,\n };\n\n const defaultOnError = (req: Request, res: Response, _next: NextFunction) => {\n // Telemetry attribution: dashboard groups CSRF denials under vector=csrf.\n req.__arcis = {\n vector: 'csrf',\n rule: 'csrf/token-mismatch',\n severity: 'high',\n reason: 'CSRF token missing or invalid',\n decision: 'deny',\n };\n res.status(403).json({\n error: 'CSRF token validation failed',\n message: 'Invalid or missing CSRF token. Include the token from the cookie in the X-CSRF-Token header.',\n });\n };\n\n const onError = options.onError ?? defaultOnError;\n\n // Normalize protected methods to uppercase\n const protectedSet = new Set(protectedMethods.map(m => m.toUpperCase()));\n\n return (req: Request, res: Response, next: NextFunction) => {\n const method = req.method.toUpperCase();\n\n // Per-request skip callback (API keys, signed webhooks, etc.)\n if (skipCsrf && skipCsrf(req)) {\n return next();\n }\n\n // Check if path is excluded\n const requestPath = req.path || req.url;\n if (excludePaths.some(p => requestPath === p || requestPath.startsWith(p + '/'))) {\n return next();\n }\n\n // Expose token generation on the request for templates/views\n (req as unknown as Record<string, unknown>).csrfToken = () => {\n const existing = getCookieValue(req, cookieName);\n if (existing) return existing;\n\n const token = generateCsrfToken(tokenLength);\n setCsrfCookie(res, cookieName, token, cookieOpts);\n return token;\n };\n\n // For safe methods — ensure a CSRF cookie exists\n if (!protectedSet.has(method)) {\n const existing = getCookieValue(req, cookieName);\n if (!existing) {\n const token = generateCsrfToken(tokenLength);\n setCsrfCookie(res, cookieName, token, cookieOpts);\n }\n return next();\n }\n\n // For protected methods — validate the token\n const cookieToken = getCookieValue(req, cookieName);\n if (!cookieToken) {\n return onError(req, res, next);\n }\n\n const requestToken = getRequestToken(req, headerName, fieldName);\n if (!requestToken) {\n return onError(req, res, next);\n }\n\n if (!validateCsrfToken(cookieToken, requestToken)) {\n return onError(req, res, next);\n }\n\n // Optional token rotation on successful validation\n if (options.rotateOnUse) {\n const freshToken = generateCsrfToken(tokenLength);\n setCsrfCookie(res, cookieName, freshToken, cookieOpts);\n }\n\n next();\n };\n}\n\n/**\n * Read a cookie value from the request.\n */\nfunction getCookieValue(req: Request, name: string): string | undefined {\n // Express parses cookies if cookie-parser is used\n if (req.cookies && typeof req.cookies === 'object' && name in req.cookies) {\n return req.cookies[name];\n }\n\n // Fallback: parse from raw Cookie header\n const cookieHeader = req.headers.cookie;\n if (!cookieHeader) return undefined;\n\n const match = cookieHeader.match(new RegExp(`(?:^|;\\\\s*)${escapeRegex(name)}=([^;]*)`));\n return match ? decodeURIComponent(match[1]) : undefined;\n}\n\n/**\n * Set the CSRF token cookie on the response.\n */\nfunction setCsrfCookie(\n res: Response,\n name: string,\n token: string,\n opts: { path: string; httpOnly: boolean; secure: boolean; sameSite: string; domain?: string }\n): void {\n const parts = [`${name}=${token}`];\n parts.push(`Path=${opts.path}`);\n if (opts.httpOnly) parts.push('HttpOnly');\n if (opts.secure) parts.push('Secure');\n parts.push(`SameSite=${opts.sameSite}`);\n if (opts.domain) parts.push(`Domain=${opts.domain}`);\n\n // Accumulate Set-Cookie headers to avoid overwriting cookies set by other middleware\n const newCookie = parts.join('; ');\n const existing = res.getHeader('Set-Cookie');\n if (existing === undefined) {\n res.setHeader('Set-Cookie', newCookie);\n } else if (Array.isArray(existing)) {\n res.setHeader('Set-Cookie', [...existing, newCookie]);\n } else {\n res.setHeader('Set-Cookie', [existing as string, newCookie]);\n }\n}\n\n/**\n * Escape special regex characters in a string.\n */\nfunction escapeRegex(str: string): string {\n return str.replace(/[.*+?^${}()|[\\]\\\\]/g, '\\\\$&');\n}\n\n/** Alias for csrfProtection */\nexport const createCsrf = csrfProtection;\n","/**\n * @module @arcis/node/middleware/hpp\n * HTTP Parameter Pollution (HPP) protection middleware\n *\n * Normalizes duplicate query and body parameters to their last value,\n * preventing attackers from bypassing validation by repeating parameters.\n *\n * Attack example:\n * GET /search?role=user&role=admin\n * Without HPP: req.query.role = ['user', 'admin']\n * With HPP: req.query.role = 'admin' (last value wins)\n *\n * Originals are preserved in req.queryPolluted / req.bodyPolluted\n * for logging or auditing without blocking the request.\n */\n\nimport type { Request, Response, NextFunction, RequestHandler } from 'express';\n\n/** HPP protection configuration */\nexport interface HppOptions {\n /**\n * Parameters that legitimately accept arrays and should not be normalized.\n * Example: ['tags', 'ids', 'filter']\n */\n whitelist?: string[];\n /** Normalize duplicate query string parameters. Default: true */\n checkQuery?: boolean;\n /** Normalize duplicate body parameters. Default: true */\n checkBody?: boolean;\n}\n\n/**\n * HTTP Parameter Pollution protection middleware.\n *\n * Normalizes duplicate query/body parameters to a single value (last wins).\n * Whitelisted parameters are allowed to remain as arrays.\n *\n * @param options - HPP configuration\n * @returns Express middleware\n *\n * @example\n * // Basic — normalize all duplicates\n * app.use(hpp());\n *\n * @example\n * // Allow arrays for specific params (e.g., tag filters, IDs)\n * app.use(hpp({ whitelist: ['tags', 'ids'] }));\n *\n * @example\n * // Inspect what was removed (for logging)\n * app.use((req, res, next) => {\n * const polluted = (req as any).queryPolluted;\n * if (Object.keys(polluted).length) logger.warn('HPP detected', polluted);\n * next();\n * });\n */\nexport function hpp(options: HppOptions = {}): RequestHandler {\n // SECURITY: Store whitelist as lowercase so case-variant params can't bypass.\n // Some frameworks normalize param case downstream — `TAGS` should match whitelist `tags`.\n const whitelist = new Set((options.whitelist ?? []).map((k) => k.toLowerCase()));\n const checkQuery = options.checkQuery ?? true;\n const checkBody = options.checkBody ?? true;\n\n return (req: Request, _res: Response, next: NextFunction) => {\n // ── Query string normalization ────────────────────────────────────────\n if (checkQuery && req.query && typeof req.query === 'object') {\n const polluted: Record<string, string[]> = {};\n const clean: Record<string, string | string[]> = {};\n\n for (const [key, value] of Object.entries(req.query)) {\n if (Array.isArray(value)) {\n const strings = value.filter((v): v is string => typeof v === 'string');\n if (whitelist.has(key.toLowerCase())) {\n // Whitelisted — preserve as array\n clean[key] = strings;\n } else {\n // Duplicate — record originals, use last value\n polluted[key] = strings;\n clean[key] = strings[strings.length - 1] ?? '';\n }\n } else {\n clean[key] = value as string;\n }\n }\n\n (req as unknown as Record<string, unknown>).queryPolluted = polluted;\n // SECURITY: Express 5 makes req.query read-only — use defineProperty\n Object.defineProperty(req, 'query', { value: clean, writable: true, configurable: true });\n }\n\n // ── Body normalization ────────────────────────────────────────────────\n if (checkBody && req.body && typeof req.body === 'object' && !Array.isArray(req.body)) {\n const polluted: Record<string, unknown[]> = {};\n const clean: Record<string, unknown> = {};\n\n for (const [key, value] of Object.entries(req.body as Record<string, unknown>)) {\n if (Array.isArray(value)) {\n if (whitelist.has(key.toLowerCase())) {\n clean[key] = value;\n } else {\n polluted[key] = value;\n clean[key] = value[value.length - 1];\n }\n } else {\n clean[key] = value;\n }\n }\n\n (req as unknown as Record<string, unknown>).bodyPolluted = polluted;\n Object.defineProperty(req, 'body', { value: clean, writable: true, configurable: true });\n }\n\n next();\n };\n}\n\nexport const createHpp = hpp;\n","/**\n * @module @arcis/node/middleware/response-splitting\n *\n * HTTP response splitting prevention (sdk-vectors.md tier 1 #27).\n *\n * Response splitting is the *output* counterpart to header injection: app\n * code passes user input into `res.setHeader`, `res.writeHead`, or\n * `res.appendHeader` (Node 17+) without stripping CR/LF, and an attacker\n * uses the embedded newline to break out of the header block and forge a\n * second response. Most often weaponised against `Location:` after a\n * redirect that reflects user input (`/redirect?to=...`).\n *\n * `sanitizeHeaderValue` already covers the byte-level fix on the way in;\n * this middleware wraps the response object so every header that leaves\n * the app gets sanitised on the way out — even when the app forgets.\n *\n * ```ts\n * import { responseSplittingGuard } from '@arcis/node/middleware/response-splitting';\n *\n * app.use(responseSplittingGuard());\n *\n * // Later — even this passes through clean:\n * app.get('/r', (req, res) => res.redirect(req.query.to as string));\n * ```\n *\n * Pair with `validateRedirect` for full coverage: this middleware blocks\n * the response-splitting payload, `validateRedirect` blocks the\n * open-redirect payload.\n */\n\nimport type { RequestHandler, Response } from 'express';\nimport { detectHeaderInjection, sanitizeHeaderValue } from '../sanitizers/headers';\n\nexport interface ResponseSplittingGuardOptions {\n /**\n * What to do when an outgoing header value contains CR / LF / NUL.\n *\n * - `'strip'` (default) — silently sanitise the value before it reaches\n * the wire. Preserves availability; existing routes don't break.\n * - `'reject'` — throw a `ResponseSplittingError`. Use in apps that\n * would rather fail-closed than emit a partial response.\n *\n * Both modes invoke `onDetect` if provided.\n */\n mode?: 'strip' | 'reject';\n\n /**\n * Per-detection callback. Fires before strip/reject. Useful for\n * logging or alerting when an attempted split slips through into the\n * response builder.\n */\n onDetect?: (header: string, originalValue: string) => void;\n}\n\n/**\n * Thrown by `responseSplittingGuard({ mode: 'reject' })` when an\n * outgoing header value contains CR / LF / NUL. The header name is in\n * `header`; the originally attempted value is in `value` so it can be\n * logged or surfaced in an error handler.\n */\nexport class ResponseSplittingError extends Error {\n readonly header: string;\n readonly value: string;\n\n constructor(header: string, value: string) {\n super(`Response splitting attempt detected on header \"${header}\"`);\n this.name = 'ResponseSplittingError';\n this.header = header;\n this.value = value;\n }\n}\n\n/**\n * Re-export under the response-splitting name. Same byte pattern as\n * header injection (CR / LF / NUL) — different threat model: input\n * boundary vs output boundary.\n */\nexport const detectResponseSplitting = detectHeaderInjection;\n\n/**\n * Re-export under the response-splitting name. Strips CR / LF / NUL.\n */\nexport const sanitizeResponseHeader = sanitizeHeaderValue;\n\n/**\n * Sanitise both the header name and value. Header *names* with CRLF are\n * always a bug — they let an attacker overwrite arbitrary subsequent\n * headers — so they are always stripped regardless of mode.\n */\nfunction safeName(name: unknown): string {\n return sanitizeHeaderValue(String(name ?? ''));\n}\n\nfunction valuesArray(value: unknown): string[] {\n if (Array.isArray(value)) return value.map((v) => String(v));\n if (value === undefined || value === null) return [];\n return [String(value)];\n}\n\n/**\n * Build the response-splitting guard middleware. Wraps `res.setHeader`,\n * `res.writeHead`, and `res.appendHeader` (when present) on each\n * incoming request so every header that leaves the app gets the same\n * CRLF / NUL treatment regardless of which code path emitted it.\n *\n * Wrapping happens per-request (not on the prototype) so multiple\n * mounts with different options don't trample each other.\n */\nexport function responseSplittingGuard(\n options: ResponseSplittingGuardOptions = {},\n): RequestHandler {\n const mode = options.mode ?? 'strip';\n const onDetect = options.onDetect;\n\n return (_req, res, next) => {\n const r = res as Response & {\n setHeader: Response['setHeader'];\n writeHead: Response['writeHead'];\n appendHeader?: (name: string, value: string | string[]) => Response;\n };\n\n const origSetHeader = r.setHeader.bind(r);\n const origWriteHead = r.writeHead.bind(r);\n const origAppendHeader = typeof r.appendHeader === 'function'\n ? r.appendHeader.bind(r)\n : undefined;\n\n function check(name: string, raw: unknown): unknown {\n const values = valuesArray(raw);\n const cleanedValues: string[] = [];\n for (const v of values) {\n if (detectHeaderInjection(v)) {\n if (onDetect) onDetect(name, v);\n if (mode === 'reject') {\n throw new ResponseSplittingError(name, v);\n }\n cleanedValues.push(sanitizeHeaderValue(v));\n } else {\n cleanedValues.push(v);\n }\n }\n // Preserve original cardinality: array → array, scalar → scalar.\n if (Array.isArray(raw)) return cleanedValues;\n if (raw === undefined || raw === null) return raw;\n return cleanedValues[0];\n }\n\n r.setHeader = function patchedSetHeader(\n name: string,\n value: number | string | readonly string[],\n ): Response {\n const safeKey = safeName(name);\n const safeValue = check(safeKey, value);\n return origSetHeader(safeKey, safeValue as number | string | readonly string[]);\n } as Response['setHeader'];\n\n r.writeHead = function patchedWriteHead(\n this: Response,\n statusCode: number,\n ...rest: unknown[]\n ): Response {\n let statusMessage: string | undefined;\n let headers: unknown;\n if (typeof rest[0] === 'string') {\n statusMessage = rest[0];\n headers = rest[1];\n } else {\n headers = rest[0];\n }\n\n let cleanedHeaders: unknown = headers;\n if (headers && typeof headers === 'object') {\n if (Array.isArray(headers)) {\n // Outgoing tuples: ['Set-Cookie', 'a=1\\r\\nb=2', ...]. Walk\n // pairs (Node accepts both flat and nested array shapes).\n if (headers.length > 0 && Array.isArray(headers[0])) {\n cleanedHeaders = (headers as unknown[][]).map((pair) => {\n const [k, v] = pair as [unknown, unknown];\n const sk = safeName(k);\n return [sk, check(sk, v)];\n });\n } else {\n const flat = headers as unknown[];\n const out: unknown[] = [];\n for (let i = 0; i < flat.length; i += 2) {\n const sk = safeName(flat[i]);\n out.push(sk, check(sk, flat[i + 1]));\n }\n cleanedHeaders = out;\n }\n } else {\n const out: Record<string, unknown> = {};\n for (const [k, v] of Object.entries(headers as Record<string, unknown>)) {\n const sk = safeName(k);\n out[sk] = check(sk, v);\n }\n cleanedHeaders = out;\n }\n }\n\n // Express's typed writeHead drops the 3-arg http.ServerResponse\n // overload; defer to Node's runtime signature here.\n const wh = origWriteHead as unknown as (\n statusCode: number,\n statusMessageOrHeaders?: string | unknown,\n headers?: unknown,\n ) => Response;\n if (statusMessage !== undefined) {\n return wh(statusCode, statusMessage, cleanedHeaders);\n }\n return wh(statusCode, cleanedHeaders);\n } as Response['writeHead'];\n\n if (origAppendHeader) {\n r.appendHeader = function patchedAppendHeader(\n name: string,\n value: string | string[],\n ): Response {\n const safeKey = safeName(name);\n const safeValue = check(safeKey, value);\n return origAppendHeader(safeKey, safeValue as string | string[]);\n };\n }\n\n next();\n };\n}\n\nexport default responseSplittingGuard;\n","/**\n * @module @arcis/node/middleware/token-budget\n *\n * Token-budget protection middleware. Caps per-key token spend over a\n * sliding window — meant for routes that proxy LLM calls, where a tight\n * 100-req/min rate limit isn't enough because a single 50KB prompt costs\n * the same as 1000 small requests.\n *\n * @example\n * import express from 'express';\n * import { tokenBudget } from '@arcis/node';\n *\n * const guard = tokenBudget({\n * maxTokens: 100_000, // 100K tokens per window\n * windowMs: 60 * 60 * 1000, // 1-hour window\n * maxRequestTokens: 5_000, // reject any single request over this\n * keyGenerator: (req) => req.user?.id ?? req.ip,\n * });\n *\n * app.post('/chat', guard, chatHandler);\n *\n * The default token estimator is `Math.ceil(bytesOf(body+query) / 4)` —\n * close to OpenAI's \"1 token ≈ 4 English characters\" rule. Override via\n * `estimateTokens` for accurate counting (tiktoken, etc.).\n */\n\nimport type { Request, RequestHandler } from 'express';\n\nexport interface TokenBudgetOptions {\n /** Max tokens a single key can spend in one window. Default: 100,000. */\n maxTokens?: number;\n /** Window length in milliseconds. Default: 60 * 60 * 1000 (1 hour). */\n windowMs?: number;\n /**\n * Max tokens a single request may consume. Requests over this size are\n * rejected with 413 BEFORE counting against the window budget. Default:\n * unset (no per-request cap).\n */\n maxRequestTokens?: number;\n /**\n * Function that returns the budget key for a request. Default: client IP\n * (req.ip), falling back to `unknown` when unresolvable.\n */\n keyGenerator?: (req: Request) => string;\n /**\n * Function that estimates the number of tokens a request will consume.\n * Default: `Math.ceil((req.body + req.query stringified bytes) / 4)`,\n * which approximates OpenAI's \"1 token ≈ 4 characters\" rule. Override\n * with tiktoken/accurate counting when you need precision.\n */\n estimateTokens?: (req: Request) => number;\n /** Status code for budget-exceeded responses. Default: 429. */\n statusCode?: number;\n /** Status code for oversize-request rejections. Default: 413. */\n statusCodeOversize?: number;\n /** Error message when budget is exceeded. */\n message?: string;\n /** Error message when a single request exceeds maxRequestTokens. */\n messageOversize?: string;\n /** Skip budget enforcement for certain requests. */\n skip?: (req: Request) => boolean;\n}\n\nexport interface TokenBudgetMiddleware extends RequestHandler {\n /** Release internal cleanup resources. */\n close: () => void;\n /** Inspect current usage for a key (read-only; for tests/telemetry). */\n inspect: (key: string) => { used: number; resetTime: number } | null;\n}\n\ninterface Entry {\n used: number;\n resetTime: number;\n}\n\nconst DEFAULT_MAX_TOKENS = 100_000;\nconst DEFAULT_WINDOW_MS = 60 * 60 * 1000;\n\nfunction defaultKeyGenerator(req: Request): string {\n const ip = req.ip ?? req.socket?.remoteAddress;\n return ip ?? 'unknown';\n}\n\nfunction defaultEstimateTokens(req: Request): number {\n // Approximate OpenAI's \"1 token ≈ 4 characters\" rule using byte length\n // of stringified body + query. Fast, side-effect-free, no model call.\n // Returns 0 for missing payloads so safe routes don't get charged.\n let bytes = 0;\n if (req.body !== undefined && req.body !== null) {\n try {\n bytes += Buffer.byteLength(\n typeof req.body === 'string' ? req.body : JSON.stringify(req.body),\n 'utf8',\n );\n } catch {\n // Circular structure or similar — treat as 0 rather than throw.\n }\n }\n if (req.query && Object.keys(req.query).length > 0) {\n try {\n bytes += Buffer.byteLength(JSON.stringify(req.query), 'utf8');\n } catch {\n // ignore\n }\n }\n return Math.ceil(bytes / 4);\n}\n\n/**\n * Build a token-budget middleware. See module-level JSDoc for usage.\n */\nexport function tokenBudget(options: TokenBudgetOptions = {}): TokenBudgetMiddleware {\n const maxTokens = options.maxTokens ?? DEFAULT_MAX_TOKENS;\n const windowMs = options.windowMs ?? DEFAULT_WINDOW_MS;\n const maxRequestTokens = options.maxRequestTokens;\n const keyGenerator = options.keyGenerator ?? defaultKeyGenerator;\n const estimateTokens = options.estimateTokens ?? defaultEstimateTokens;\n const statusCode = options.statusCode ?? 429;\n const statusCodeOversize = options.statusCodeOversize ?? 413;\n const message = options.message ?? 'Token budget exceeded for this window.';\n const messageOversize =\n options.messageOversize ??\n 'Request exceeds the per-request token limit.';\n const skip = options.skip;\n\n // Object.create(null) keeps __proto__/constructor keys from corrupting\n // the store if a buggy keyGenerator returns one of those names.\n const store = Object.create(null) as Record<string, Entry>;\n\n // Sweep expired buckets so a long-lived process doesn't grow unbounded.\n const cleanup = setInterval(() => {\n const now = Date.now();\n for (const k of Object.keys(store)) {\n if (store[k].resetTime < now) {\n delete store[k];\n }\n }\n }, windowMs);\n if (typeof cleanup.unref === 'function') cleanup.unref();\n\n const handler: RequestHandler = (req, res, next) => {\n if (skip?.(req)) {\n next();\n return;\n }\n\n let estimated = 0;\n try {\n estimated = estimateTokens(req);\n } catch {\n estimated = 0;\n }\n if (!Number.isFinite(estimated) || estimated < 0) estimated = 0;\n\n // Per-request cap (rejected before counting against the budget so a\n // single oversized request can't single-handedly drain a window).\n if (maxRequestTokens !== undefined && estimated > maxRequestTokens) {\n res.setHeader('X-Token-Budget-Limit', maxTokens.toString());\n res.setHeader('X-Token-Budget-Request-Cost', estimated.toString());\n res.status(statusCodeOversize).json({\n error: messageOversize,\n requestTokens: estimated,\n maxRequestTokens,\n });\n return;\n }\n\n const key = keyGenerator(req);\n const now = Date.now();\n let entry = store[key];\n if (!entry || entry.resetTime < now) {\n entry = { used: 0, resetTime: now + windowMs };\n store[key] = entry;\n }\n\n const projected = entry.used + estimated;\n const remaining = Math.max(0, maxTokens - entry.used);\n const resetSeconds = Math.ceil((entry.resetTime - now) / 1000);\n\n res.setHeader('X-Token-Budget-Limit', maxTokens.toString());\n res.setHeader('X-Token-Budget-Used', entry.used.toString());\n res.setHeader('X-Token-Budget-Remaining', remaining.toString());\n res.setHeader('X-Token-Budget-Reset', resetSeconds.toString());\n res.setHeader('X-Token-Budget-Request-Cost', estimated.toString());\n\n if (projected > maxTokens) {\n res.setHeader('Retry-After', resetSeconds.toString());\n res.status(statusCode).json({\n error: message,\n used: entry.used,\n maxTokens,\n retryAfter: resetSeconds,\n });\n return;\n }\n\n // Charge the budget and continue.\n entry.used = projected;\n next();\n };\n\n const middleware = handler as TokenBudgetMiddleware;\n middleware.close = () => clearInterval(cleanup);\n middleware.inspect = (key: string) => {\n const e = store[key];\n if (!e) return null;\n return { used: e.used, resetTime: e.resetTime };\n };\n return middleware;\n}\n\nexport default tokenBudget;\n","/**\n * @module @arcis/node/middleware/overload\n *\n * Event-loop overload protection (sdk-vectors.md tier 1 #30, issue #51).\n *\n * Rate limiting caps per-client load; this middleware caps **total server\n * load** by sampling event-loop lag and shedding new requests with 503\n * when the loop is saturated. Pairs with rate-limit (per-client) +\n * `methodAllowlist` (per-route) to give Arcis three orthogonal layers\n * of \"this server is healthy enough to do work\" gating.\n *\n * ```ts\n * import { eventLoopProtection } from '@arcis/node';\n *\n * app.use(eventLoopProtection({\n * maxLagMs: 500, // 503 above this smoothed lag\n * sampleIntervalMs: 250, // measure every 250ms\n * }));\n * ```\n *\n * Sampling strategy:\n * - `setInterval(fn, sampleIntervalMs)` is scheduled; the callback\n * compares wall-clock elapsed against the configured interval. Lag\n * IS the difference: when the loop is busy, the timer fires late.\n * - The interval handle is `.unref()`-ed so the process can exit\n * cleanly even if the caller forgets to call `close()`.\n * - Exponential moving average (`smoothed = 0.7 * smoothed + 0.3 *\n * measured`) smooths out single-sample spikes — a 600ms GC pause\n * shouldn't cause every request to 503 for the next sample window.\n *\n * Implementation deliberately picks `setTimeout` measurement over\n * `perf_hooks.monitorEventLoopDelay` (Node 12+ alternative) for two\n * reasons: (1) it works on every supported Node version with no feature\n * detection branch, (2) the perf_hooks histogram returns nanosecond\n * lag from a 10ms-resolution sampler, but applying the spec's EMA\n * formula on that signal would skew toward unreal lag values that the\n * sampler smoothed away. Keeping the sampler the spec calls for keeps\n * the math testable.\n */\n\nimport type { RequestHandler, Response } from 'express';\n\nexport interface EventLoopProtectionOptions {\n /** Smoothed lag threshold in ms above which the middleware returns 503. Default: 500. */\n maxLagMs?: number;\n /** Sample frequency in ms. Default: 250. Lower = more responsive, higher = less overhead. */\n sampleIntervalMs?: number;\n /** Status code to return when overloaded. Default: 503. */\n statusCode?: number;\n /** Error message in the response body. Default: \"Server overloaded, please retry\". */\n message?: string;\n /** Retry-After header value in seconds. Default: 5. */\n retryAfterSeconds?: number;\n /**\n * EMA smoothing factor for the new measurement. Default: 0.3 (per\n * issue #51 spec). Must be in (0, 1]; lower values smooth harder\n * (longer memory of past samples), higher values track more reactively.\n */\n alpha?: number;\n /**\n * When true, every response gets `X-EventLoop-Lag: <ms>` so monitoring\n * can graph saturation independent of the deny decision. Off by default\n * because most apps don't need it and an extra header on every response\n * adds noise.\n */\n exposeLagHeader?: boolean;\n}\n\nexport interface EventLoopProtectionMiddleware extends RequestHandler {\n /**\n * Stop the sampler. Call from a SIGTERM handler so the interval doesn't\n * keep a misconfigured process alive. Idempotent: subsequent calls are\n * no-ops.\n */\n close(): void;\n /**\n * Read the current smoothed lag in ms. Useful for tests that want to\n * assert the smoothing math without mocking timers, and for callers\n * who want to expose the value through a different surface (Prometheus,\n * dashboard panel, etc.).\n */\n currentLagMs(): number;\n}\n\nconst DEFAULTS = {\n maxLagMs: 500,\n sampleIntervalMs: 250,\n statusCode: 503,\n message: 'Server overloaded, please retry',\n retryAfterSeconds: 5,\n alpha: 0.3,\n} as const;\n\n/**\n * Build an event-loop protection middleware. Returns a request handler\n * with `close()` and `currentLagMs()` attached (Pattern 6 in the\n * monorepo's middleware conventions: factories return a callable\n * augmented with cleanup helpers).\n */\nexport function eventLoopProtection(\n options: EventLoopProtectionOptions = {},\n): EventLoopProtectionMiddleware {\n const maxLagMs = options.maxLagMs ?? DEFAULTS.maxLagMs;\n const sampleIntervalMs = options.sampleIntervalMs ?? DEFAULTS.sampleIntervalMs;\n const statusCode = options.statusCode ?? DEFAULTS.statusCode;\n const message = options.message ?? DEFAULTS.message;\n const retryAfterSeconds = options.retryAfterSeconds ?? DEFAULTS.retryAfterSeconds;\n const alpha = options.alpha ?? DEFAULTS.alpha;\n const exposeLagHeader = options.exposeLagHeader === true;\n\n // Validate up-front so misconfiguration surfaces at app boot, not on\n // the first overloaded request.\n if (maxLagMs <= 0) {\n throw new RangeError('eventLoopProtection: maxLagMs must be > 0');\n }\n if (sampleIntervalMs <= 0) {\n throw new RangeError('eventLoopProtection: sampleIntervalMs must be > 0');\n }\n if (alpha <= 0 || alpha > 1) {\n throw new RangeError('eventLoopProtection: alpha must be in (0, 1]');\n }\n\n let smoothedLag = 0;\n let lastTickTime = Date.now();\n let stopped = false;\n\n // Sampler: each tick measures elapsed time vs the configured interval.\n // The difference is the lag — on a healthy loop it's ~0; on a saturated\n // loop the timer fires late. Apply the EMA after every measurement so\n // the value the middleware reads on the NEXT request is smoothed.\n const interval = setInterval(() => {\n const now = Date.now();\n const elapsed = now - lastTickTime;\n const measuredLag = Math.max(0, elapsed - sampleIntervalMs);\n smoothedLag = (1 - alpha) * smoothedLag + alpha * measuredLag;\n lastTickTime = now;\n }, sampleIntervalMs);\n\n // Don't pin the process alive. The Node `Timer.unref()` returns the\n // handle so we can chain it; behavior is well-known across versions.\n if (typeof interval.unref === 'function') {\n interval.unref();\n }\n\n const middleware = ((_req, res, next) => {\n if (exposeLagHeader) {\n // Round to ms for header sanity — float values render awkwardly.\n res.setHeader('X-EventLoop-Lag', Math.round(smoothedLag).toString());\n }\n if (!stopped && smoothedLag > maxLagMs) {\n (res as Response).setHeader('Retry-After', retryAfterSeconds.toString());\n res.status(statusCode).json({\n error: message,\n retryAfter: retryAfterSeconds,\n });\n return;\n }\n next();\n }) as EventLoopProtectionMiddleware;\n\n middleware.close = () => {\n if (stopped) return;\n stopped = true;\n clearInterval(interval);\n };\n\n middleware.currentLagMs = () => smoothedLag;\n\n return middleware;\n}\n\nexport default eventLoopProtection;\n\n// Test-only export so tests can drive the smoother without spinning real\n// timers. Computes one EMA step against the supplied prior + measurement.\nexport const __test = {\n ema(prior: number, measured: number, alpha: number): number {\n return (1 - alpha) * prior + alpha * measured;\n },\n};\n","/**\n * @module @arcis/node/middleware/method-allowlist\n *\n * HTTP method tampering protection (sdk-vectors.md tier 1 #26).\n *\n * Two related threats:\n *\n * 1. **Disallowed methods** — TRACE leaks Authorization headers (XST);\n * CONNECT is for proxies and shouldn't reach an application server;\n * custom verbs slip past route-handlers that only check `if (req.method\n * === 'POST')`. The middleware rejects anything outside an allowlist\n * with 405.\n *\n * 2. **Method-override bypass** — frameworks that respect\n * `X-HTTP-Method-Override` let an attacker turn a GET into a POST or\n * DELETE, bypassing route-level method checks. The middleware strips\n * these headers BEFORE the route handler sees them.\n *\n * Pair with the bundle middleware:\n *\n * ```ts\n * import { arcis } from '@arcis/node';\n * import { methodAllowlist } from '@arcis/node/middleware/method-allowlist';\n *\n * app.use(methodAllowlist());\n * app.use(arcis());\n * ```\n *\n * Or standalone for fine-grained mounts:\n *\n * ```ts\n * app.use('/api', methodAllowlist({ allow: ['GET', 'POST'] }));\n * ```\n */\n\nimport type { RequestHandler } from 'express';\n\n/**\n * Headers that frameworks treat as method overrides. Each one rewrites\n * `req.method` somewhere in the stack — we strip all three so a request\n * always travels under its wire method.\n */\nconst METHOD_OVERRIDE_HEADERS = [\n 'x-http-method-override',\n 'x-method-override',\n 'x-http-method',\n] as const;\n\nconst DEFAULT_ALLOWED_METHODS: readonly string[] = [\n 'GET',\n 'POST',\n 'PUT',\n 'DELETE',\n 'HEAD',\n 'OPTIONS',\n 'PATCH',\n];\n\nexport interface MethodAllowlistOptions {\n /**\n * Methods to permit. Each entry is uppercased before comparison so\n * `['get', 'post']` works the same as `['GET', 'POST']`. Defaults to\n * the full standard CRUD set: GET, POST, PUT, DELETE, HEAD, OPTIONS,\n * PATCH. TRACE and CONNECT are intentionally excluded — the former\n * leaks Authorization (XST), the latter is for proxies.\n */\n allow?: readonly string[];\n\n /**\n * Strip method-override headers (`X-HTTP-Method-Override`,\n * `X-Method-Override`, `X-HTTP-Method`) before the request reaches the\n * route handler. Default: true. Set to false only if your stack\n * legitimately uses one of these headers for client-method tunnelling\n * AND you've verified each override target is auth-checked\n * independently.\n */\n stripOverrideHeaders?: boolean;\n\n /** HTTP status code for the deny response. Default: 405 Method Not Allowed. */\n statusCode?: number;\n\n /** Error message body. Default: \"Method not allowed\". */\n message?: string;\n}\n\n/**\n * Build a method-allowlist middleware. Uppercase-matches `req.method`\n * against the allow set; strips override headers so downstream code\n * can't be tricked into running a different method's logic.\n */\nexport function methodAllowlist(options: MethodAllowlistOptions = {}): RequestHandler {\n const allow = new Set(\n (options.allow ?? DEFAULT_ALLOWED_METHODS).map((m) => m.toUpperCase()),\n );\n const strip = options.stripOverrideHeaders !== false;\n const statusCode = options.statusCode ?? 405;\n const message = options.message ?? 'Method not allowed';\n\n return (req, res, next) => {\n if (strip) {\n // Remove BEFORE the allowlist check so an attacker can't slip a\n // disallowed method through via override (e.g. wire GET +\n // X-HTTP-Method-Override: TRACE — strip the header, the GET\n // passes the allowlist, the override never reaches the route).\n for (const h of METHOD_OVERRIDE_HEADERS) {\n delete req.headers[h];\n }\n }\n\n const method = (req.method ?? '').toUpperCase();\n if (!allow.has(method)) {\n // 405 spec wants Allow header listing accepted methods.\n res.setHeader('Allow', Array.from(allow).join(', '));\n res.status(statusCode).json({\n error: message,\n method: req.method,\n });\n return;\n }\n\n next();\n };\n}\n\nexport default methodAllowlist;\n","/**\n * @module @arcis/node/middleware/mass-assign\n *\n * Mass-assignment runtime guard (sdk-vectors.md tier 1 #25).\n *\n * The classic mass-assignment vulnerability:\n *\n * ```js\n * const user = await User.findOne({ id });\n * Object.assign(user, req.body); // attacker sets req.body.is_admin = true\n * await user.save();\n * ```\n *\n * This middleware filters `req.body` to a per-route allowlist before\n * the handler runs. Two modes:\n *\n * - `'strip'` (default) — silently drop disallowed keys, continue.\n * - `'reject'` — return 400 with the offending key names.\n *\n * Pair it with the audit rule (`MASS-ASSIGN` in `arcis audit`) for the\n * static-analysis side and the route-level middleware for the runtime\n * side. Audit catches `Object.assign(target, req.body)` patterns at\n * build time; this middleware catches the runtime data flow.\n *\n * ```ts\n * import { massAssign } from '@arcis/node';\n *\n * app.post('/users',\n * massAssign({ allow: ['email', 'password', 'name'] }),\n * async (req, res) => {\n * // req.body has been filtered — is_admin / role / created_at all gone.\n * const user = await User.create(req.body);\n * res.json(user);\n * },\n * );\n * ```\n *\n * Default scope is top-level keys only. Nested objects pass through\n * untouched — that's deliberate: nested allowlists encourage\n * `allow: ['profile.bio', 'profile.avatar']` style strings which\n * become a parser, not a guard. Use a schema validator (Zod / Joi /\n * Arcis's `validate`) when nested filtering is required; this\n * middleware handles the 80% case of \"filter req.body for an ORM\n * mass-assign call\".\n */\n\nimport type { Request, RequestHandler, Response, NextFunction } from 'express';\n\nexport interface MassAssignOptions {\n /**\n * Allowlist of permitted top-level keys on `req.body`. Required —\n * a missing or empty array would silently strip every key, almost\n * certainly a configuration mistake.\n */\n allow: readonly string[];\n /**\n * Behavior when `req.body` contains a key NOT in `allow`:\n * - `'strip'` (default): silently drop the key, continue.\n * - `'reject'`: return `statusCode` (default 400) with a JSON\n * body listing the disallowed keys.\n */\n mode?: 'strip' | 'reject';\n /** Status code for the reject path. Default: 400. */\n statusCode?: number;\n /** Error message in the reject body. Default: \"Disallowed fields\". */\n message?: string;\n /**\n * Skip the filter when `req.body` is not a plain object (string,\n * array, FormData, etc.). Default: true. Set to false to surface\n * a 400 (\"body must be an object\") on those payloads — useful for\n * routes that should ONLY accept JSON objects.\n */\n passThroughNonObjects?: boolean;\n}\n\nconst DEFAULTS = {\n mode: 'strip' as const,\n statusCode: 400,\n message: 'Disallowed fields',\n passThroughNonObjects: true,\n} as const;\n\n/**\n * Build a mass-assignment guard middleware. Runs against `req.body`\n * before the route handler — must be installed AFTER body-parsing\n * middleware (`express.json()` / `express.urlencoded()`) so `req.body`\n * is already populated.\n */\nexport function massAssign(options: MassAssignOptions): RequestHandler {\n if (!options || !Array.isArray(options.allow)) {\n throw new TypeError('massAssign: options.allow must be a string array');\n }\n if (options.allow.length === 0) {\n // Empty allow list strips every key. Almost certainly a bug — fail\n // loud at boot rather than silently accept-and-strip in production.\n throw new RangeError(\n 'massAssign: options.allow must contain at least one key (use sanitize: false to disable instead)',\n );\n }\n\n const allowSet = new Set(options.allow);\n const mode = options.mode ?? DEFAULTS.mode;\n const statusCode = options.statusCode ?? DEFAULTS.statusCode;\n const message = options.message ?? DEFAULTS.message;\n const passThroughNonObjects =\n options.passThroughNonObjects ?? DEFAULTS.passThroughNonObjects;\n\n return (req: Request, res: Response, next: NextFunction) => {\n const body = req.body;\n\n // No body: nothing to filter. Express sets req.body to {} when the\n // body parser ran but the request had no body, and to undefined\n // when no parser was wired — both flow through unchanged.\n if (body === undefined || body === null) {\n next();\n return;\n }\n\n // Non-object payload (string / array / Buffer / FormData). The\n // mass-assign vector is specifically Object.assign-style key\n // expansion; non-objects don't have keys to filter, so the default\n // is pass-through.\n if (typeof body !== 'object' || Array.isArray(body)) {\n if (passThroughNonObjects) {\n next();\n return;\n }\n res.status(statusCode).json({\n error: 'Request body must be a JSON object',\n });\n return;\n }\n\n const incoming = Object.keys(body as Record<string, unknown>);\n const disallowed = incoming.filter((k) => !allowSet.has(k));\n\n if (disallowed.length > 0 && mode === 'reject') {\n res.status(statusCode).json({\n error: message,\n fields: disallowed,\n });\n return;\n }\n\n if (disallowed.length > 0) {\n // Strip mode — build a fresh object with only allowed keys. Avoid\n // mutating the original `req.body` reference because some\n // frameworks freeze the body or wire it to other middleware.\n const filtered: Record<string, unknown> = {};\n for (const key of incoming) {\n if (allowSet.has(key)) {\n filtered[key] = (body as Record<string, unknown>)[key];\n }\n }\n // Express 5 / Connect 4 made req.body a getter on some versions;\n // assign via Object.defineProperty to stay safe across both. (Same\n // pattern arcis uses in `validation/schema.ts` for the same\n // reason.)\n Object.defineProperty(req, 'body', {\n value: filtered,\n writable: true,\n configurable: true,\n enumerable: true,\n });\n }\n\n next();\n };\n}\n\nexport default massAssign;\n","/**\n * @module @arcis/node/middleware/signup-protection\n *\n * Composite signup-form protection: one middleware that combines email\n * validation (syntax + disposable), bot detection, and a dedicated\n * per-IP rate limit. Matches the Arcjet `protectSignup` convenience\n * primitive but stays fully local — no cloud lookups.\n *\n * @example\n * app.post('/signup', signupProtection(), handler);\n *\n * @example\n * app.post('/signup', signupProtection({\n * emailField: 'email',\n * rateLimit: { max: 5, windowMs: 60_000 },\n * blockDisposable: true,\n * }), handler);\n */\n\nimport type { Request, Response, NextFunction, RequestHandler } from 'express';\nimport { validateEmail } from '../validation/email';\nimport { detectBot, type BotCategory } from './bot-detection';\nimport { createRateLimiter } from './rate-limit';\n\nexport type SignupBlockReason =\n | 'missing_email'\n | 'invalid_email'\n | 'disposable_email'\n | 'bot'\n | 'rate_limited';\n\nexport interface SignupCheckResult {\n allowed: boolean;\n reason: SignupBlockReason | 'ok';\n details?: Record<string, unknown>;\n}\n\nexport interface SignupProtectionOptions {\n /** Request body field holding the email address. Default: 'email' */\n emailField?: string;\n /** Run email validation. Default: true */\n checkEmail?: boolean;\n /** Reject disposable email domains. Default: true */\n blockDisposable?: boolean;\n /** Run bot detection. Default: true */\n checkBot?: boolean;\n /** Bot categories allowed through (e.g. test harnesses). Default: [] — all bots blocked */\n allowedBotCategories?: BotCategory[];\n /** Per-IP rate limit on signup endpoint. Set to `false` to disable. Default: 5 requests / 60s */\n rateLimit?: { max?: number; windowMs?: number } | false;\n /** Extra email domains to allow (bypasses disposable check) */\n allowedEmailDomains?: string[];\n /** Extra email domains to block */\n blockedEmailDomains?: string[];\n /** Called when a request is blocked — for telemetry/logging */\n onBlocked?: (req: Request, result: SignupCheckResult) => void;\n}\n\nexport interface SignupProtectionMiddleware extends RequestHandler {\n /** Release the rate-limiter cleanup interval */\n close: () => void;\n}\n\n/**\n * Pure signup check — no rate-limit mutation, no response writes.\n * Useful for framework adapters or custom control flow.\n */\nexport function checkSignup(\n req: Request,\n options: SignupProtectionOptions = {}\n): SignupCheckResult {\n const {\n emailField = 'email',\n checkEmail = true,\n blockDisposable = true,\n checkBot = true,\n allowedBotCategories = [],\n allowedEmailDomains = [],\n blockedEmailDomains = [],\n } = options;\n\n if (checkBot) {\n const bot = detectBot(req);\n if (bot.isBot && !allowedBotCategories.includes(bot.category)) {\n return {\n allowed: false,\n reason: 'bot',\n details: { category: bot.category, name: bot.name, confidence: bot.confidence },\n };\n }\n }\n\n if (checkEmail) {\n const email = (req.body as Record<string, unknown> | undefined)?.[emailField];\n if (typeof email !== 'string' || email.length === 0) {\n return { allowed: false, reason: 'missing_email' };\n }\n const result = validateEmail(email, {\n checkDisposable: blockDisposable,\n allowedDomains: allowedEmailDomains,\n blockedDomains: blockedEmailDomains,\n });\n if (!result.valid) {\n const reason: SignupBlockReason =\n result.reason === 'disposable' ? 'disposable_email' : 'invalid_email';\n return { allowed: false, reason, details: { emailReason: result.reason } };\n }\n }\n\n return { allowed: true, reason: 'ok' };\n}\n\n/**\n * Express middleware: applies bot + email + rate-limit checks to a signup\n * endpoint. Responds 400/403/429 with a JSON body on block; otherwise\n * calls `next()`.\n */\nexport function signupProtection(\n options: SignupProtectionOptions = {}\n): SignupProtectionMiddleware {\n const rateLimitCfg = options.rateLimit;\n const limiter =\n rateLimitCfg === false\n ? null\n : createRateLimiter({\n max: rateLimitCfg?.max ?? 5,\n windowMs: rateLimitCfg?.windowMs ?? 60_000,\n message: 'Too many signup attempts',\n });\n\n const handler: RequestHandler = (req, res, next) => {\n const result = checkSignup(req, options);\n if (!result.allowed) {\n options.onBlocked?.(req, result);\n const status = result.reason === 'bot' ? 403 : 400;\n res.status(status).json({ error: 'signup_blocked', reason: result.reason });\n return;\n }\n if (limiter) {\n // Delegate to rate limiter — it will respond 429 on breach or call next() otherwise.\n let rateLimited = false;\n const rateLimitNext: NextFunction = (err?: unknown) => {\n if (err) return next(err);\n if (!rateLimited) next();\n };\n const patchedRes = new Proxy(res, {\n get(target, prop) {\n if (prop === 'status') {\n return (code: number) => {\n if (code === 429) {\n rateLimited = true;\n options.onBlocked?.(req, { allowed: false, reason: 'rate_limited' });\n }\n return (target.status as (c: number) => Response).call(target, code);\n };\n }\n return Reflect.get(target, prop);\n },\n });\n limiter(req, patchedRes as Response, rateLimitNext);\n return;\n }\n next();\n };\n\n const middleware = handler as SignupProtectionMiddleware;\n middleware.close = () => limiter?.close();\n return middleware;\n}\n","/**\n * @module @arcis/node/middleware/protect\n *\n * Composite protection helpers (issue #52). Pre-configured middleware\n * stacks for the three endpoint shapes that show up in every app:\n * login, signup, generic API. Each helper composes EXISTING middleware\n * with sensible defaults; no new security logic lives here.\n *\n * Express supports passing an array of middleware to a route — the\n * elements get unrolled in declaration order — so each helper returns\n * a `RequestHandler[]` that drops directly into `app.post(...)`:\n *\n * ```ts\n * import { protectLogin, protectSignup, protectApi } from '@arcis/node';\n *\n * app.post('/login', protectLogin(), loginHandler);\n * app.post('/signup', protectSignup(), signupHandler);\n * app.use ('/api', protectApi());\n * ```\n *\n * Defaults (issue #52 spec):\n *\n * | Helper | rate-limit | bot | csrf | cors | sanitize | email |\n * |---------------|------------|-----|------|------|----------|-------|\n * | protectLogin | 5/min | yes | yes | - | yes | - |\n * | protectSignup | 3/min | yes | - | - | yes | yes |\n * | protectApi | 100/min | - | - | yes | yes | - |\n *\n * Each option is overridable. Pass `{ rateLimit: false }` to disable a\n * specific layer; pass an options object to forward to the underlying\n * factory.\n */\n\nimport type { RequestHandler } from 'express';\nimport { createRateLimiter } from './rate-limit';\nimport { botProtection, type BotProtectionOptions } from './bot-detection';\nimport { csrfProtection, type CsrfOptions } from './csrf';\nimport { safeCors } from './cors';\nimport type { CorsOptions } from './cors';\nimport { signupProtection, type SignupProtectionOptions } from './signup-protection';\nimport { createSanitizer } from '../sanitizers';\nimport type { RateLimitOptions, SanitizeOptions } from '../core/types';\nimport { CorrelationWindow } from './correlation';\n\n/**\n * Per-protect-helper correlation-window wiring (improvements.md §1.4).\n *\n * Pass an instance of `CorrelationWindow` plus the vector tag this\n * route represents (\"login\" / \"signup\" / \"api\"). The middleware\n * records every request in the window and refuses the request when\n * the window flags the IP as a scanner / credential stuffer / race\n * probe. Detection-only otherwise.\n *\n * Pull-out fields:\n * - `usernameField`: body key whose value is the distinct-value\n * tracked for credential-stuffing detection. Defaults to\n * `'username'`.\n * - `route`: route label recorded in the window (so cross-route\n * aggregation is meaningful). Defaults to the request path.\n * - `statusCode` / `message`: response shape on a correlation block.\n */\nexport interface CorrelationOptions {\n window: CorrelationWindow;\n vector?: string;\n usernameField?: string;\n route?: string;\n statusCode?: number;\n message?: string;\n}\n\nfunction getClientIp(req: any): string {\n // Best-effort. Matches the helper Arcis uses elsewhere.\n const xff =\n req?.headers?.['x-forwarded-for'] ?? req?.headers?.['X-Forwarded-For'];\n if (typeof xff === 'string' && xff.length > 0) {\n const first = xff.split(',')[0]?.trim();\n if (first) return first;\n }\n if (typeof req?.ip === 'string') return req.ip;\n const remote = req?.socket?.remoteAddress;\n return typeof remote === 'string' ? remote : '';\n}\n\nfunction correlationMiddleware(opts: CorrelationOptions): RequestHandler {\n const vector = opts.vector ?? 'request';\n const usernameField = opts.usernameField ?? 'username';\n const statusCode = opts.statusCode ?? 429;\n const message = opts.message ?? 'Suspicious request pattern detected.';\n return function (req, res, next) {\n const ip = getClientIp(req);\n if (!ip) return next();\n const route = opts.route ?? (req.path || req.url || '/');\n const username = req?.body?.[usernameField];\n const distinctValue =\n typeof username === 'string' && username.length > 0 ? username : undefined;\n const detections = opts.window.record(\n ip,\n vector,\n route,\n req.method || 'GET',\n distinctValue,\n );\n if (\n detections.scanner ||\n detections.credentialStuffing ||\n detections.raceWindow\n ) {\n res.status(statusCode).json({\n error: message,\n scanner: detections.scanner,\n credential_stuffing: detections.credentialStuffing,\n race_window: detections.raceWindow,\n });\n return;\n }\n next();\n };\n}\n\n/**\n * Per-layer override knob: pass `false` to disable, an options object\n * to merge into the layer's defaults, or omit to accept the helper's\n * baked-in default.\n */\ntype LayerOverride<T> = false | T | undefined;\n\nexport interface ProtectLoginOptions {\n rateLimit?: LayerOverride<RateLimitOptions>;\n bot?: LayerOverride<BotProtectionOptions>;\n csrf?: LayerOverride<CsrfOptions>;\n sanitize?: LayerOverride<SanitizeOptions>;\n /** Optional correlation-window wiring (improvements.md §1.4). */\n correlation?: CorrelationOptions;\n}\n\nexport interface ProtectSignupOptions {\n rateLimit?: LayerOverride<RateLimitOptions>;\n bot?: LayerOverride<BotProtectionOptions>;\n sanitize?: LayerOverride<SanitizeOptions>;\n /** signupProtection options (email-style validation, disposable-mail block, etc.). */\n signup?: LayerOverride<SignupProtectionOptions>;\n /** Optional correlation-window wiring (improvements.md §1.4). */\n correlation?: CorrelationOptions;\n}\n\nexport interface ProtectApiOptions {\n rateLimit?: LayerOverride<RateLimitOptions>;\n /** CORS is required to take an Origin/Methods config — no default origin. */\n cors?: LayerOverride<CorsOptions>;\n sanitize?: LayerOverride<SanitizeOptions>;\n /** Optional correlation-window wiring (improvements.md §1.4). */\n correlation?: CorrelationOptions;\n}\n\n/**\n * Resolve a layer override against a default. Returns `null` when the\n * caller disabled the layer with `false`; otherwise the merged options\n * object the underlying factory expects.\n */\nfunction resolve<T extends object>(override: LayerOverride<T>, defaults: T): T | null {\n if (override === false) return null;\n if (override === undefined) return defaults;\n return { ...defaults, ...override };\n}\n\n/**\n * Login endpoints get the strictest defaults: 5 req/min/IP, deny\n * AUTOMATED bots, CSRF token check, and input sanitization. Designed\n * for `app.post('/login', protectLogin(), handler)`.\n */\nexport function protectLogin(options: ProtectLoginOptions = {}): RequestHandler[] {\n const middlewares: RequestHandler[] = [];\n\n const rl = resolve<RateLimitOptions>(options.rateLimit, { max: 5, windowMs: 60_000 });\n if (rl) middlewares.push(createRateLimiter(rl));\n\n const bot = resolve<BotProtectionOptions>(options.bot, {\n deny: ['AUTOMATED'],\n statusCode: 403,\n message: 'Access denied.',\n });\n if (bot) middlewares.push(botProtection(bot));\n\n const csrf = resolve<CsrfOptions>(options.csrf, {});\n if (csrf) middlewares.push(csrfProtection(csrf));\n\n const sanitize = resolve<SanitizeOptions>(options.sanitize, {});\n if (sanitize) middlewares.push(createSanitizer(sanitize));\n\n if (options.correlation) {\n middlewares.push(\n correlationMiddleware({ vector: 'login', ...options.correlation }),\n );\n }\n\n return middlewares;\n}\n\n/**\n * Signup endpoints: 3 req/min/IP, deny AUTOMATED bots, sanitize input,\n * and run signup-specific validation (email shape + disposable-domain\n * check via `signupProtection`). No CSRF here because most signup\n * forms are first-touch, no prior session to anchor a token to.\n */\nexport function protectSignup(options: ProtectSignupOptions = {}): RequestHandler[] {\n const middlewares: RequestHandler[] = [];\n\n const rl = resolve<RateLimitOptions>(options.rateLimit, { max: 3, windowMs: 60_000 });\n if (rl) middlewares.push(createRateLimiter(rl));\n\n const bot = resolve<BotProtectionOptions>(options.bot, {\n deny: ['AUTOMATED'],\n statusCode: 403,\n message: 'Access denied.',\n });\n if (bot) middlewares.push(botProtection(bot));\n\n const sanitize = resolve<SanitizeOptions>(options.sanitize, {});\n if (sanitize) middlewares.push(createSanitizer(sanitize));\n\n const signup = resolve<SignupProtectionOptions>(options.signup, {});\n if (signup) middlewares.push(signupProtection(signup));\n\n if (options.correlation) {\n middlewares.push(\n correlationMiddleware({ vector: 'signup', ...options.correlation }),\n );\n }\n\n return middlewares;\n}\n\n/**\n * Generic API endpoints: 100 req/min/IP, CORS, input sanitization. No\n * bot detection by default because legitimate API consumers (curl,\n * fetch, server-to-server) are often classified AUTOMATED — opt-in\n * by passing a `bot` override... wait, protectApi doesn't expose bot.\n * That's deliberate per the issue spec table. Users who want bot\n * detection on API endpoints compose `botProtection()` directly.\n *\n * CORS is the one layer with no usable default — every app's allow\n * list is different. Pass `cors: { origin: '...' }` or `cors: false`\n * to skip it explicitly.\n */\nexport function protectApi(options: ProtectApiOptions = {}): RequestHandler[] {\n const middlewares: RequestHandler[] = [];\n\n const rl = resolve<RateLimitOptions>(options.rateLimit, { max: 100, windowMs: 60_000 });\n if (rl) middlewares.push(createRateLimiter(rl));\n\n // CORS: no useful default, but if the user didn't pass anything we\n // default to a permissive CorsOrigin: true (reflect request Origin).\n // Documented as a starter — production apps should narrow this.\n const cors = resolve<CorsOptions>(options.cors, { origin: true });\n if (cors) middlewares.push(safeCors(cors));\n\n const sanitize = resolve<SanitizeOptions>(options.sanitize, {});\n if (sanitize) middlewares.push(createSanitizer(sanitize));\n\n if (options.correlation) {\n middlewares.push(\n correlationMiddleware({ vector: 'api', ...options.correlation }),\n );\n }\n\n return middlewares;\n}\n","/**\n * @module @arcis/node/middleware/graphql\n *\n * GraphQL request guard (sdk-vectors.md tier 1 #21). Wraps the\n * `inspectGraphqlQuery` sanitizer in an Express middleware that\n * pulls the query string from the standard places GraphQL servers\n * expect it (`req.body.query` for POST, `req.query.query` for GET)\n * and short-circuits with 400 + a structured error when the query\n * violates any configured limit.\n *\n * ```ts\n * import { graphqlGuard } from '@arcis/node';\n *\n * app.use('/graphql', graphqlGuard({\n * maxDepth: 10,\n * maxLength: 10000,\n * blockIntrospection: process.env.NODE_ENV === 'production',\n * }));\n * ```\n *\n * Order with the rest of Arcis: install AFTER body-parsing\n * (`express.json()`) so `req.body.query` is populated, BEFORE the\n * GraphQL handler so the deny path short-circuits resolver work.\n */\n\nimport type { Request, RequestHandler, Response, NextFunction } from 'express';\nimport {\n inspectGraphqlQuery,\n type GraphqlGuardOptions,\n type GraphqlViolation,\n} from '../sanitizers/graphql';\n\nexport interface GraphqlGuardMiddlewareOptions extends GraphqlGuardOptions {\n /** HTTP status to return on violation. Default: 400 (matches GraphQL spec for parse errors). */\n statusCode?: number;\n /** Custom message template. Default: built per-reason. */\n message?: string | ((reason: GraphqlViolation) => string);\n}\n\nconst DEFAULT_MESSAGES: Record<GraphqlViolation, string> = {\n depth: 'Query exceeds maximum nesting depth',\n length: 'Query exceeds maximum length',\n introspection: 'Introspection queries are disabled',\n aliases: 'Query exceeds maximum alias count (alias-bomb protection)',\n fragment_cycle: 'Query contains a cyclic fragment definition',\n};\n\n/**\n * Pull the GraphQL query string from a request. Convention: POST\n * bodies carry `{ query, variables, operationName }`; GET requests\n * pass `?query=...` for persisted-query-style fetches. We check both\n * so the guard works regardless of transport.\n */\nfunction extractQuery(req: Request): string | undefined {\n // Prefer body.query (POST is the dominant transport for GraphQL).\n const bodyQuery =\n typeof req.body === 'object' && req.body !== null\n ? (req.body as Record<string, unknown>).query\n : undefined;\n if (typeof bodyQuery === 'string') return bodyQuery;\n\n // Fall back to req.query.query (GET) — express stores query string\n // values as strings or arrays-of-strings.\n const qsQuery = req.query?.query;\n if (typeof qsQuery === 'string') return qsQuery;\n\n return undefined;\n}\n\nexport function graphqlGuard(\n options: GraphqlGuardMiddlewareOptions = {},\n): RequestHandler {\n const statusCode = options.statusCode ?? 400;\n const messageOption = options.message;\n\n return (req: Request, res: Response, next: NextFunction) => {\n const query = extractQuery(req);\n if (!query) {\n // No GraphQL query in the expected slots — could be a\n // mounted-elsewhere route or a non-GraphQL request slipping\n // through the same path. Pass through; the GraphQL handler\n // below will decide whether to error.\n next();\n return;\n }\n\n const result = inspectGraphqlQuery(query, options);\n if (!result.blocked) {\n next();\n return;\n }\n\n const reason = result.reason as GraphqlViolation;\n const message =\n typeof messageOption === 'function'\n ? messageOption(reason)\n : (messageOption ?? DEFAULT_MESSAGES[reason]);\n\n res.status(statusCode).json({\n error: message,\n reason,\n observed: {\n depth: result.depth,\n length: result.length,\n },\n });\n };\n}\n\nexport default graphqlGuard;\n","/**\n * @module @arcis/node/middleware/correlation\n *\n * V1.6 / improvements.md §1.3 — Stateful per-IP correlation window.\n *\n * Today's middleware is stateless: each request is judged on its own.\n * That misses three classes of attack:\n *\n * - Scanner sweep. One IP firing payloads from every category in\n * quick succession is a scanner, not a real user.\n * - Credential stuffing. Same login route, same IP, dozens of\n * distinct usernames in 60 seconds.\n * - Race-condition probe. POST /a immediately followed by GET /b\n * from the same IP, within 200 ms. Either is fine alone.\n *\n * This module records a small rolling event log per IP (capped) and\n * exposes detection helpers. Detection is *additive* — Pattern 4\n * applies (fail-open). If something goes wrong here, the existing\n * rate-limit + per-vector defenses still run.\n *\n * Mirrors `arcis-python/arcis/middleware/correlation.py`. Both SDKs\n * must accept the same base corpus per Pattern 7.\n */\n\nexport interface CorrelationEvent {\n /** Wall-clock seconds (Date.now() / 1000) or test-injected value. */\n timestamp: number;\n /** Detector or operation that produced this event. */\n vector: string;\n route: string;\n method: string;\n /** Username / email / token bucket if relevant; otherwise undefined. */\n distinctValue?: string;\n}\n\nexport interface CorrelationDetections {\n scanner: boolean;\n credentialStuffing: boolean;\n raceWindow: boolean;\n distinctVectors: number;\n distinctValues: number;\n requestsInWindow: number;\n}\n\nexport interface CorrelationWindowOptions {\n windowSeconds?: number;\n maxIps?: number;\n maxEventsPerIp?: number;\n scannerDistinctVectors?: number;\n scannerMinRequests?: number;\n credentialStuffingDistinctValues?: number;\n raceWindowMs?: number;\n /** Pre-registered race-pair routes; ad-hoc detect_race_window also works. */\n racePairs?: Array<[string, string]>;\n}\n\nconst EMPTY_DETECTIONS: CorrelationDetections = Object.freeze({\n scanner: false,\n credentialStuffing: false,\n raceWindow: false,\n distinctVectors: 0,\n distinctValues: 0,\n requestsInWindow: 0,\n});\n\ninterface IpBucket {\n events: CorrelationEvent[];\n}\n\nfunction normalizePair(a: string, b: string): string {\n return a < b ? `${a}\u0001${b}` : `${b}\u0001${a}`;\n}\n\n/**\n * Rolling per-IP correlation window. Mirrors the Python\n * `CorrelationWindow` class.\n *\n * All detection helpers are read-only; only `record` mutates state.\n */\nexport class CorrelationWindow {\n private readonly windowSeconds: number;\n private readonly maxIps: number;\n private readonly maxEventsPerIp: number;\n private readonly scannerDistinctVectors: number;\n private readonly scannerMinRequests: number;\n private readonly csDistinctValues: number;\n private readonly raceWindowSeconds: number;\n private readonly racePairKeys: Set<string>;\n private readonly racePairTuples: Array<[string, string]>;\n\n // Map iteration order in JS is insertion order, so re-inserting on\n // access gives us LRU behaviour without a separate linked list.\n private readonly buckets: Map<string, IpBucket> = new Map();\n\n constructor(options: CorrelationWindowOptions = {}) {\n const {\n windowSeconds = 60,\n maxIps = 10_000,\n maxEventsPerIp = 200,\n scannerDistinctVectors = 3,\n scannerMinRequests = 20,\n credentialStuffingDistinctValues = 10,\n raceWindowMs = 200,\n racePairs,\n } = options;\n\n if (windowSeconds <= 0) throw new Error('windowSeconds must be > 0');\n if (maxIps < 1) throw new Error('maxIps must be >= 1');\n if (maxEventsPerIp < 1) throw new Error('maxEventsPerIp must be >= 1');\n\n this.windowSeconds = windowSeconds;\n this.maxIps = maxIps;\n this.maxEventsPerIp = maxEventsPerIp;\n this.scannerDistinctVectors = scannerDistinctVectors;\n this.scannerMinRequests = scannerMinRequests;\n this.csDistinctValues = credentialStuffingDistinctValues;\n this.raceWindowSeconds = raceWindowMs / 1000;\n this.racePairKeys = new Set();\n this.racePairTuples = [];\n if (racePairs) {\n for (const [a, b] of racePairs) {\n const key = normalizePair(a, b);\n if (!this.racePairKeys.has(key)) {\n this.racePairKeys.add(key);\n const sorted: [string, string] = a < b ? [a, b] : [b, a];\n this.racePairTuples.push(sorted);\n }\n }\n }\n }\n\n record(\n ip: string,\n vector: string,\n route: string,\n method = 'GET',\n distinctValue?: string,\n now?: number,\n ): CorrelationDetections {\n if (!ip) return EMPTY_DETECTIONS;\n const ts = now ?? Date.now() / 1000;\n const event: CorrelationEvent = {\n timestamp: ts,\n vector,\n route,\n method,\n distinctValue,\n };\n\n let bucket = this.buckets.get(ip);\n if (bucket === undefined) {\n bucket = { events: [] };\n this.buckets.set(ip, bucket);\n while (this.buckets.size > this.maxIps) {\n const oldest = this.buckets.keys().next().value as string | undefined;\n if (oldest === undefined) break;\n this.buckets.delete(oldest);\n }\n } else {\n // LRU touch: re-insert at the end.\n this.buckets.delete(ip);\n this.buckets.set(ip, bucket);\n }\n\n bucket.events.push(event);\n this.evictStale(bucket, ts);\n return this.evaluate(bucket, route);\n }\n\n detectScanner(ip: string, now?: number): boolean {\n const bucket = this.buckets.get(ip);\n if (bucket === undefined) return false;\n this.evictStale(bucket, now ?? Date.now() / 1000);\n return this.isScanner(bucket);\n }\n\n detectCredentialStuffing(ip: string, route: string, now?: number): boolean {\n const bucket = this.buckets.get(ip);\n if (bucket === undefined) return false;\n this.evictStale(bucket, now ?? Date.now() / 1000);\n return this.isCredentialStuffing(bucket, route);\n }\n\n detectRaceWindow(\n ip: string,\n routePair: [string, string],\n now?: number,\n ): boolean {\n const bucket = this.buckets.get(ip);\n if (bucket === undefined) return false;\n this.evictStale(bucket, now ?? Date.now() / 1000);\n const sorted: [string, string] =\n routePair[0] < routePair[1] ? routePair : [routePair[1], routePair[0]];\n return this.racePairInBucket(bucket, sorted);\n }\n\n reset(ip?: string): void {\n if (ip === undefined) {\n this.buckets.clear();\n } else {\n this.buckets.delete(ip);\n }\n }\n\n stats(): { trackedIps: number; eventsInWindow: number } {\n let events = 0;\n for (const b of this.buckets.values()) events += b.events.length;\n return { trackedIps: this.buckets.size, eventsInWindow: events };\n }\n\n // -------------------------------------------------------- internals\n\n private evictStale(bucket: IpBucket, now: number): void {\n const cutoff = now - this.windowSeconds;\n let drop = 0;\n while (drop < bucket.events.length && bucket.events[drop].timestamp < cutoff) {\n drop++;\n }\n if (drop > 0) bucket.events.splice(0, drop);\n if (bucket.events.length > this.maxEventsPerIp) {\n bucket.events.splice(0, bucket.events.length - this.maxEventsPerIp);\n }\n }\n\n private evaluate(bucket: IpBucket, route: string): CorrelationDetections {\n const vectors = new Set<string>();\n const values = new Set<string>();\n for (const e of bucket.events) {\n vectors.add(e.vector);\n if (e.route === route && e.distinctValue !== undefined) {\n values.add(e.distinctValue);\n }\n }\n return {\n scanner: this.isScanner(bucket),\n credentialStuffing: this.isCredentialStuffing(bucket, route),\n raceWindow: this.isRaceAny(bucket),\n distinctVectors: vectors.size,\n distinctValues: values.size,\n requestsInWindow: bucket.events.length,\n };\n }\n\n private isScanner(bucket: IpBucket): boolean {\n if (bucket.events.length < this.scannerMinRequests) return false;\n const vectors = new Set<string>();\n for (const e of bucket.events) vectors.add(e.vector);\n return vectors.size >= this.scannerDistinctVectors;\n }\n\n private isCredentialStuffing(bucket: IpBucket, route: string): boolean {\n const values = new Set<string>();\n for (const e of bucket.events) {\n if (e.route === route && e.distinctValue !== undefined) {\n values.add(e.distinctValue);\n }\n }\n return values.size >= this.csDistinctValues;\n }\n\n private racePairInBucket(bucket: IpBucket, sorted: [string, string]): boolean {\n const [a, b] = sorted;\n const aTs: number[] = [];\n const bTs: number[] = [];\n for (const e of bucket.events) {\n if (e.route === a) aTs.push(e.timestamp);\n else if (e.route === b) bTs.push(e.timestamp);\n }\n if (aTs.length === 0 || bTs.length === 0) return false;\n let ai = 0;\n let bi = 0;\n while (ai < aTs.length && bi < bTs.length) {\n const diff = aTs[ai] - bTs[bi];\n if (Math.abs(diff) <= this.raceWindowSeconds) return true;\n if (diff < 0) ai++;\n else bi++;\n }\n return false;\n }\n\n private isRaceAny(bucket: IpBucket): boolean {\n for (const pair of this.racePairTuples) {\n if (this.racePairInBucket(bucket, pair)) return true;\n }\n return false;\n }\n}\n","/**\n * @module @arcis/node/sanitizers/prompt-injection\n *\n * Pattern-based prompt-injection detection and sanitization for LLM-handler\n * endpoints. Catches the common signature classes — system-prompt overrides,\n * known jailbreak frameworks (DAN/STAN/DUDE), structural markers (fake\n * XML/Markdown delimiters that try to forge system messages), and known\n * encoding tricks. Does NOT defend against arbitrary novel attacks: that\n * needs the model itself to evaluate intent.\n *\n * Built as a signature library (Option A in `documents/plans/sdk-vectors.md`\n * vector #28) — MIT, fully transparent, no closed Wasm blobs.\n *\n * Common attack categories caught:\n * - Direct override: \"ignore previous instructions\", \"disregard the above\"\n * - Jailbreak frameworks: DAN, STAN, DUDE, \"developer mode\", \"jailbroken\"\n * - Persona hijack: \"you are now X\", \"pretend to be\", \"roleplay as\"\n * - System prompt extraction: \"show me your prompt\", \"what are your rules\"\n * - Indirect injection: fake `<system>` tags, \"BEGIN NEW INSTRUCTIONS\"\n * - Encoding tricks: Base64-prefixed payloads, ROT13 markers\n */\n\n// ─── Severity model ────────────────────────────────────────────────────────\n\nexport type PromptInjectionSeverity = 'low' | 'medium' | 'high';\n\nexport interface PromptInjectionMatch {\n /** Stable identifier for the matched signature */\n rule: string;\n /** Severity of this signature */\n severity: PromptInjectionSeverity;\n /** Short human-readable description */\n description: string;\n /** First chars of the matched substring (for telemetry / logs) */\n match: string;\n}\n\nexport interface DetectPromptInjectionResult {\n /** Did any signature match? */\n detected: boolean;\n /** All signatures that matched, in declaration order */\n matches: PromptInjectionMatch[];\n /** Highest severity across all matches; 'none' if nothing matched */\n severity: PromptInjectionSeverity | 'none';\n}\n\n// ─── Signatures ────────────────────────────────────────────────────────────\n// Each signature: a regex + severity + a stable rule id + a description.\n// Patterns target the common public attack corpora; specifically the OWASP\n// LLM01 prompt-injection examples plus the well-known jailbreak frameworks\n// shipped publicly between 2023–2025.\n\ninterface PromptInjectionSignature {\n rule: string;\n pattern: RegExp;\n severity: PromptInjectionSeverity;\n description: string;\n}\n\nconst SIGNATURES: PromptInjectionSignature[] = [\n // --- HIGH severity: clear override / jailbreak attempts ---\n {\n rule: 'ignore-previous-instructions',\n // Two clauses:\n // 1. ignore|disregard|... + adjectives? + a target object word (like\n // \"instructions\", \"rules\") — catches \"ignore your safety rules\".\n // 2. ignore|disregard|... + (the|all|any) + (previous|above|prior|...)\n // with no trailing noun — catches \"disregard the above\".\n pattern: /\\b(?:ignore|disregard|forget|override|bypass)\\s+(?:(?:all|your|the|any|previous|prior|above|original|initial|system|safety)\\s+)*(?:instructions?|rules?|directions?|guidelines?|prompts?|policies|directives|commands?|restrictions?|filters?|safety|content)\\b|\\b(?:ignore|disregard|forget|override|bypass)\\s+(?:all\\s+|the\\s+|any\\s+)?(?:previous|prior|above|preceding|earlier|original|initial)\\b/i,\n severity: 'high',\n description: 'Direct instruction override attempt',\n },\n {\n rule: 'jailbreak-dan',\n pattern: /\\b(?:DAN|STAN|DUDE|DAVE|JEDI|EvilBot|AIM|BetterDAN|AntiGPT|AntiClaude)\\b(?:[\\s.,!?]|mode|prompt|jailbreak|persona)/i,\n severity: 'high',\n description: 'Known jailbreak framework name (DAN/STAN/DUDE/etc.)',\n },\n {\n rule: 'do-anything-now',\n pattern: /\\bdo\\s+anything\\s+now\\b/i,\n severity: 'high',\n description: 'DAN (\"Do Anything Now\") jailbreak variant',\n },\n {\n rule: 'developer-mode',\n pattern: /\\b(?:developer|debug|admin|sudo|root|god|maintenance|test)\\s+mode\\b(?:\\s+(?:on|enabled|activated|engaged))?/i,\n severity: 'high',\n description: 'Fake \"developer mode\" / \"debug mode\" enablement',\n },\n {\n rule: 'jailbroken-claim',\n pattern: /\\b(?:you\\s+are\\s+(?:now\\s+)?)?(?:jailbroken|unrestricted|uncensored|unleashed|liberated|free\\s+from\\s+(?:rules|guidelines|restrictions))\\b/i,\n severity: 'high',\n description: 'Claim that the model is jailbroken / unrestricted',\n },\n {\n rule: 'role-hijack',\n pattern: /\\b(?:you\\s+are\\s+(?:now\\s+)?(?:a\\s+)?(?:different|new|another|evil|malicious|unrestricted|unfiltered)|act\\s+as\\s+(?:a\\s+)?(?:different|new|another|evil|malicious|unrestricted|unfiltered))\\b/i,\n severity: 'high',\n description: 'Persona hijack attempt',\n },\n {\n rule: 'pretend-to-be',\n pattern: /\\bpretend\\s+(?:to\\s+be|you\\s+are|that\\s+you\\s+(?:are|have))\\b/i,\n severity: 'high',\n description: 'Persona-impersonation prompt',\n },\n {\n rule: 'roleplay-as',\n pattern: /\\b(?:roleplay|role[\\s-]?play|simulate|emulate)\\s+(?:as|being|the\\s+role\\s+of)\\b/i,\n severity: 'high',\n description: 'Roleplay-based jailbreak prefix',\n },\n {\n rule: 'no-restrictions',\n pattern: /\\b(?:without\\s+(?:any\\s+)?(?:restrictions?|limits?|filters?|safety|guidelines?|moral|ethic\\w*)|no\\s+(?:restrictions?|limits?|filters?|safety|guidelines?))\\b/i,\n severity: 'high',\n description: 'Explicit \"no restrictions\" qualifier',\n },\n\n // --- MEDIUM severity: system-prompt extraction & structural injection ---\n {\n rule: 'reveal-system-prompt',\n pattern: /\\b(?:show|display|print|reveal|tell|give|repeat|output|expose)\\s+(?:me\\s+)?(?:your|the)\\s+(?:(?:system|original|initial|full|complete|exact|raw)\\s+)*(?:prompt|instructions?|directive|configuration|rules?|guidelines?)/i,\n severity: 'medium',\n description: 'System-prompt extraction attempt',\n },\n {\n rule: 'what-are-instructions',\n pattern: /\\bwhat\\s+(?:are|were|is)\\s+(?:your|the)\\s+(?:original\\s+|initial\\s+|system\\s+)?(?:instructions?|directives?|rules?|prompts?|guidelines?)\\b/i,\n severity: 'medium',\n description: 'Indirect system-prompt extraction',\n },\n {\n rule: 'fake-system-tag',\n pattern: /<\\/?\\s*(?:system|instructions?|prompt|admin|root|sudo|user_admin)\\s*>/i,\n severity: 'medium',\n description: 'Forged XML-style system delimiter',\n },\n {\n rule: 'fake-system-marker',\n pattern: /(?:^|\\n)\\s*(?:#{1,3}\\s*|\\[\\s*|\\*\\*\\s*)?(?:SYSTEM|INSTRUCTIONS?|ADMIN|ROOT|PROMPT)\\s*[:>=#]\\s*/i,\n severity: 'medium',\n description: 'Forged Markdown/heading-style system marker',\n },\n {\n rule: 'begin-new-instructions',\n pattern: /\\b(?:BEGIN|START|INITIATE)\\s+(?:NEW\\s+|UPDATED\\s+|REPLACEMENT\\s+)?(?:INSTRUCTIONS?|PROMPT|SYSTEM|RULES?|DIRECTIVES?)\\b/i,\n severity: 'medium',\n description: '\"BEGIN NEW INSTRUCTIONS\" marker',\n },\n {\n rule: 'end-of-input-marker',\n pattern: /\\[\\s*(?:END|FINISH|TERMINATE|STOP|CLOSE)\\s+(?:OF\\s+)?(?:INPUT|USER|MESSAGE|CONVERSATION|CONTEXT)\\s*\\]/i,\n severity: 'medium',\n description: 'Fake \"[END OF INPUT]\" marker',\n },\n {\n rule: 'human-assistant-replay',\n pattern: /\\n\\s*(?:Human|User|Assistant|AI):\\s*/i,\n severity: 'medium',\n description: 'Forged Human:/Assistant: turn marker',\n },\n {\n rule: 'output-after-marker',\n pattern: /\\b(?:after\\s+(?:this|the\\s+\\w+))\\s*[,.]?\\s*(?:output|print|say|respond|reply|return|generate)\\b/i,\n severity: 'medium',\n description: 'Conditional output redirection',\n },\n {\n rule: 'translate-but-do-other',\n pattern: /\\b(?:translate|summari[sz]e|paraphrase|rewrite)\\s+.{0,80}\\b(?:but|then|after|and)\\s+(?:also\\s+)?(?:do|say|output|tell|reveal|print)\\b/i,\n severity: 'medium',\n description: 'Task-hijack via \"translate X but Y\"',\n },\n {\n rule: 'base64-suspicious',\n pattern: /\\b(?:base64|b64|decode|encoded?\\s+(?:in|as)\\s+base64|atob)\\b/i,\n severity: 'medium',\n description: 'Base64-decode hint (often used to smuggle jailbreaks)',\n },\n {\n rule: 'rot13-encoding',\n pattern: /\\b(?:rot13|rot-13|caesar(?:\\s+cipher)?)\\b/i,\n severity: 'medium',\n description: 'ROT13 / Caesar-cipher decode hint',\n },\n\n // ── V32: AI agent toolcall injection (improvements.md §1.2) ────────\n // Modern LLM agents (Claude tool-use, OpenAI function-calling,\n // ReAct loops) read tool definitions from the system prompt and\n // JSON-shaped requests from the model. A malicious user can embed\n // those shapes in their input to make the host think they invoked\n // a tool, or to trick the model into echoing a synthesized\n // tool_call that the runtime then executes.\n //\n // Narrow patterns — match the literal JSON keys and inline\n // tool-name shapes. Won't false-positive on plain English text\n // discussing tools.\n {\n rule: 'agent-toolcall-marker',\n pattern: /\"(?:tool_call|function_call|call_tool|tool_use|toolUse)\"\\s*:\\s*\\{/i,\n severity: 'high',\n description: 'Injected agent tool-call JSON shape (e.g. {\"tool_call\":{...}})',\n },\n {\n rule: 'agent-tool-name-spoof',\n pattern:\n /\"name\"\\s*:\\s*\"(?:exec|shell|run_command|system|bash|cmd|python|eval|read_file|write_file|delete_file)\"/i,\n severity: 'high',\n description: 'Forged tool-name attempting privileged tool invocation',\n },\n {\n rule: 'agent-tool-result-marker',\n pattern: /\"(?:tool_result|function_result|tool_output)\"\\s*:\\s*[\\{\\[\"]/i,\n severity: 'high',\n description: 'Injected fake tool-result block (trick agent into trusting fabricated output)',\n },\n {\n rule: 'ansi-escape-sequence',\n pattern: /\\x1b\\[/,\n severity: 'medium',\n description: 'ANSI escape sequence (terminal hijack / output spoofing on CLI agents)',\n },\n {\n rule: 'claude-tool-use-tags',\n pattern: /<\\/?\\s*(?:tool_use|tool_result|invoke|function_calls?|parameter)\\b/i,\n severity: 'high',\n description: 'Claude/OpenAI tool-use XML-style tag forgery',\n },\n\n // --- LOW severity: ambiguous but worth flagging in strict mode ---\n {\n rule: 'from-now-on',\n pattern: /\\bfrom\\s+now\\s+on\\b\\s*[,.]?\\s*(?:you|always|never)/i,\n severity: 'low',\n description: 'Persistent-instruction prefix',\n },\n {\n rule: 'your-new-purpose',\n pattern: /\\byour\\s+(?:new|real|true|primary|only)\\s+(?:purpose|role|task|goal|job|function)\\s+is\\b/i,\n severity: 'low',\n description: 'Persona/purpose redefinition',\n },\n {\n rule: 'forget-everything',\n pattern: /\\bforget\\s+(?:everything|all|the\\s+(?:above|previous|prior))\\b/i,\n severity: 'low',\n description: 'Memory-clear directive',\n },\n {\n rule: 'no-warnings',\n pattern: /\\b(?:without|don'?t|do\\s+not)\\s+(?:add|include|provide|give|send|print)\\s+(?:any\\s+)?(?:warnings?|disclaimers?|caveats?|safety\\s+notes?|legal\\s+notice)/i,\n severity: 'low',\n description: 'Warning-suppression directive',\n },\n {\n rule: 'hypothetical-prefix',\n pattern: /\\b(?:hypothetically|in\\s+a\\s+hypothetical\\s+(?:world|scenario)|imagine\\s+(?:a\\s+)?(?:world|scenario|situation)\\s+where)\\b/i,\n severity: 'low',\n description: 'Hypothetical framing (common jailbreak prefix)',\n },\n {\n rule: 'just-a-story',\n pattern: /\\b(?:just|only|merely)\\s+(?:a\\s+)?(?:story|fiction|hypothetical|thought\\s+experiment|joke|game|test)\\b/i,\n severity: 'low',\n description: 'Fictional framing escape',\n },\n];\n\nconst SEVERITY_RANK: Record<PromptInjectionSeverity, number> = {\n low: 1,\n medium: 2,\n high: 3,\n};\n\n// ─── Public API ────────────────────────────────────────────────────────────\n\n/**\n * Detect prompt-injection signatures in `text`. Returns all matches with\n * severity and the highest severity seen. Does not modify the input.\n *\n * @example\n * const r = detectPromptInjection('Ignore the previous instructions.');\n * if (r.detected && r.severity === 'high') return res.status(403).end();\n */\nexport function detectPromptInjection(text: string): DetectPromptInjectionResult {\n if (typeof text !== 'string' || text.length === 0) {\n return { detected: false, matches: [], severity: 'none' };\n }\n\n const matches: PromptInjectionMatch[] = [];\n let topRank = 0;\n let topSeverity: PromptInjectionSeverity | 'none' = 'none';\n\n for (const sig of SIGNATURES) {\n const m = sig.pattern.exec(text);\n if (m) {\n const matched = m[0].slice(0, 80);\n matches.push({\n rule: sig.rule,\n severity: sig.severity,\n description: sig.description,\n match: matched,\n });\n const rank = SEVERITY_RANK[sig.severity];\n if (rank > topRank) {\n topRank = rank;\n topSeverity = sig.severity;\n }\n }\n }\n\n return {\n detected: matches.length > 0,\n matches,\n severity: topSeverity,\n };\n}\n\n/**\n * Strip prompt-injection signatures from `text`. For HIGH and MEDIUM\n * severity matches the matched span is replaced with `[REDACTED]`. LOW\n * severity matches are left in place by default — toggle via `redactLow`.\n *\n * Returns the sanitized string. To inspect what was stripped, call\n * `detectPromptInjection` first or pass `collectMatches: true`.\n */\nexport function sanitizePromptInjection(\n text: string,\n options: { redactLow?: boolean; replacement?: string } = {},\n): string {\n if (typeof text !== 'string' || text.length === 0) return text ?? '';\n\n const replacement = options.replacement ?? '[REDACTED]';\n const redactLow = options.redactLow ?? false;\n let value = text;\n\n for (const sig of SIGNATURES) {\n if (sig.severity === 'low' && !redactLow) continue;\n // Use a global flavor of the pattern so multiple occurrences are removed.\n const flags = sig.pattern.flags.includes('g') ? sig.pattern.flags : sig.pattern.flags + 'g';\n const globalPattern = new RegExp(sig.pattern.source, flags);\n value = value.replace(globalPattern, replacement);\n }\n\n return value;\n}\n","/**\n * @module @arcis/node/guards\n *\n * Guards API. Same Arcis decisioning (rate limit, bot detect, prompt\n * injection, token budget) applied to non-HTTP contexts where there's no\n * `req`/`res` pair. Use this for:\n *\n * - Job queue workers (BullMQ, agenda, sidekiq-style)\n * - Agent tool-call handlers (Claude/OpenAI tool dispatch)\n * - WebSocket / SSE / gRPC handlers\n * - Background processors (cron jobs, scheduled tasks)\n *\n * Each call to `guards.run(input)` returns a structured decision: `ok` +\n * (when denied) the `vector`, `severity`, `reason`, and `retryAfterSeconds`\n * the deny was triggered by. The first vector that denies short-circuits\n * the rest, so denial latency stays bounded.\n *\n * @example\n * import { Guards } from '@arcis/node';\n *\n * const guards = new Guards({\n * rateLimit: { max: 50, windowMs: 60_000 },\n * tokenBudget: { maxTokens: 100_000, windowMs: 60 * 60 * 1000 },\n * promptInjection: { redactLow: false },\n * });\n *\n * // In a job handler:\n * const decision = guards.run({\n * key: jobUserId,\n * tokens: estimateTokens(prompt),\n * text: prompt,\n * });\n * if (!decision.ok) {\n * throw new Error(`Job rejected (${decision.vector}): ${decision.reason}`);\n * }\n */\n\nimport { detectBot, type BotProtectionOptions } from './middleware/bot-detection';\nimport {\n detectPromptInjection,\n type PromptInjectionSeverity,\n} from './sanitizers/prompt-injection';\n\n// ─── Public types ──────────────────────────────────────────────────────────\n\nexport interface GuardsRateLimitOptions {\n /** Max events per window per key. Default: 100. */\n max?: number;\n /** Window length in milliseconds. Default: 60000 (1 minute). */\n windowMs?: number;\n}\n\nexport interface GuardsTokenBudgetOptions {\n /** Max tokens a single key can spend in one window. Default: 100,000. */\n maxTokens?: number;\n /** Window length in milliseconds. Default: 60 * 60 * 1000 (1 hour). */\n windowMs?: number;\n /**\n * Optional per-call cap. When set, a single call with `tokens > maxRequestTokens`\n * denies BEFORE charging the window budget.\n */\n maxRequestTokens?: number;\n}\n\nexport interface GuardsPromptInjectionOptions {\n /**\n * Minimum severity that triggers a deny. Default: 'medium' (HIGH and\n * MEDIUM matches deny; LOW matches still surface in `decision.matches`\n * but don't deny).\n */\n denyAt?: PromptInjectionSeverity;\n}\n\nexport interface GuardsBotOptions {\n /** Categories that pass through. Default: SEARCH_ENGINE, SOCIAL, MONITORING. */\n allow?: BotProtectionOptions['allow'];\n /** Categories that always deny. Default: AUTOMATED. */\n deny?: BotProtectionOptions['deny'];\n /** Default for uncategorized bots. Default: 'allow'. */\n defaultAction?: BotProtectionOptions['defaultAction'];\n}\n\nexport interface GuardsConfig {\n /** When set, every call is rate-limited per `input.key`. Omit to disable. */\n rateLimit?: GuardsRateLimitOptions;\n /** When set, calls with `input.tokens` charge a per-key sliding-window budget. */\n tokenBudget?: GuardsTokenBudgetOptions;\n /** When set, `input.text` is scanned for prompt-injection signatures. */\n promptInjection?: GuardsPromptInjectionOptions | true;\n /** When set, `input.userAgent` is matched against the bot corpus. */\n bot?: GuardsBotOptions | true;\n}\n\nexport interface GuardsInput {\n /** Identifier for rate-limit / token-budget bucketing. Required. */\n key: string;\n /** Optional text payload for prompt-injection scanning. */\n text?: string;\n /** Optional token cost for token-budget accounting. */\n tokens?: number;\n /** Optional User-Agent string for bot detection. */\n userAgent?: string;\n}\n\nexport type GuardsVector =\n | 'rate-limit'\n | 'token-budget'\n | 'prompt-injection'\n | 'bot';\n\nexport type GuardsSeverity = 'low' | 'medium' | 'high';\n\nexport interface GuardsDecision {\n /** True if the input passes every configured vector. */\n ok: boolean;\n /** Which vector denied. Undefined when `ok` is true. */\n vector?: GuardsVector;\n /** Human-readable reason for the deny. Undefined when `ok` is true. */\n reason?: string;\n /** Severity of the deny. Undefined when `ok` is true. */\n severity?: GuardsSeverity;\n /** How many seconds until the same key can retry (rate-limit / token-budget). */\n retryAfterSeconds?: number;\n /**\n * For prompt-injection: every signature that matched, even when the deny\n * threshold wasn't hit. Lets callers log low-severity matches without\n * blocking on them.\n */\n matches?: ReadonlyArray<{ rule: string; severity: GuardsSeverity }>;\n}\n\n// ─── Internal state ────────────────────────────────────────────────────────\n\ninterface RLEntry {\n count: number;\n resetTime: number;\n}\n\ninterface TBEntry {\n used: number;\n resetTime: number;\n}\n\nconst SEVERITY_RANK: Record<GuardsSeverity, number> = { low: 1, medium: 2, high: 3 };\n\nconst DEFAULT_BOT_ALLOW = new Set(['SEARCH_ENGINE', 'SOCIAL', 'MONITORING']);\nconst DEFAULT_BOT_DENY = new Set(['AUTOMATED']);\n\n// ─── Public class ──────────────────────────────────────────────────────────\n\n/**\n * Guards. Apply Arcis decisions to non-HTTP contexts. Construct once with\n * the vectors you care about, then call `.run(input)` per request/event.\n * Internal state (rate-limit buckets, token-budget buckets) lives on the\n * instance. Call `.close()` to release the periodic-cleanup interval.\n */\nexport class Guards {\n private readonly rl: GuardsRateLimitOptions | undefined;\n private readonly tb: GuardsTokenBudgetOptions | undefined;\n private readonly pi: GuardsPromptInjectionOptions | undefined;\n private readonly bot: GuardsBotOptions | undefined;\n private readonly rlStore: Record<string, RLEntry>;\n private readonly tbStore: Record<string, TBEntry>;\n private readonly cleanup: ReturnType<typeof setInterval> | null;\n private readonly piDenyRank: number;\n\n constructor(config: GuardsConfig = {}) {\n this.rl = config.rateLimit;\n this.tb = config.tokenBudget;\n this.pi = config.promptInjection === true ? {} : config.promptInjection;\n this.bot = config.bot === true ? {} : config.bot;\n\n const denyAt = (this.pi?.denyAt as GuardsSeverity | undefined) ?? 'medium';\n this.piDenyRank = SEVERITY_RANK[denyAt];\n\n this.rlStore = Object.create(null);\n this.tbStore = Object.create(null);\n\n // Sweep expired buckets only when rate-limit or token-budget is in play.\n const sweepInterval = this.rl?.windowMs ?? this.tb?.windowMs;\n if (sweepInterval) {\n this.cleanup = setInterval(() => this.sweepExpired(), sweepInterval);\n if (typeof this.cleanup.unref === 'function') this.cleanup.unref();\n } else {\n this.cleanup = null;\n }\n }\n\n /**\n * Evaluate every configured vector against `input`. Returns a structured\n * decision; the first denying vector short-circuits the rest.\n */\n run(input: GuardsInput): GuardsDecision {\n if (!input || typeof input.key !== 'string' || input.key.length === 0) {\n return { ok: false, reason: 'guards: missing required `input.key`' };\n }\n\n // 1. Rate limit\n if (this.rl) {\n const decision = this.checkRateLimit(input.key);\n if (!decision.ok) return decision;\n }\n\n // 2. Bot detection (if a UA was supplied)\n if (this.bot && input.userAgent) {\n const decision = this.checkBot(input.userAgent);\n if (!decision.ok) return decision;\n }\n\n // 3. Prompt injection (if text was supplied)\n let piMatches: ReadonlyArray<{ rule: string; severity: GuardsSeverity }> | undefined;\n if (this.pi !== undefined && typeof input.text === 'string' && input.text.length > 0) {\n const result = detectPromptInjection(input.text);\n piMatches = result.matches.map((m) => ({ rule: m.rule, severity: m.severity }));\n if (\n result.detected &&\n result.severity !== 'none' &&\n SEVERITY_RANK[result.severity] >= this.piDenyRank\n ) {\n const top = result.matches.find((m) => m.severity === result.severity) ?? result.matches[0];\n return {\n ok: false,\n vector: 'prompt-injection',\n severity: result.severity,\n reason: top\n ? `Prompt injection detected (${top.rule}): ${top.description}`\n : 'Prompt injection detected',\n matches: piMatches,\n };\n }\n }\n\n // 4. Token budget (always last so a denied request hasn't already charged)\n if (this.tb && typeof input.tokens === 'number') {\n const decision = this.checkTokenBudget(input.key, input.tokens);\n if (!decision.ok) return { ...decision, matches: piMatches };\n }\n\n return { ok: true, matches: piMatches };\n }\n\n /** Inspect rate-limit usage for a key. Useful for tests and telemetry. */\n inspectRateLimit(key: string): { count: number; resetTime: number } | null {\n const e = this.rlStore[key];\n return e ? { count: e.count, resetTime: e.resetTime } : null;\n }\n\n /** Inspect token-budget usage for a key. */\n inspectTokenBudget(key: string): { used: number; resetTime: number } | null {\n const e = this.tbStore[key];\n return e ? { used: e.used, resetTime: e.resetTime } : null;\n }\n\n /** Reset a single key's state, or all keys if `key` is omitted. */\n reset(key?: string): void {\n if (key === undefined) {\n for (const k of Object.keys(this.rlStore)) delete this.rlStore[k];\n for (const k of Object.keys(this.tbStore)) delete this.tbStore[k];\n } else {\n delete this.rlStore[key];\n delete this.tbStore[key];\n }\n }\n\n /** Release the periodic cleanup interval. Idempotent. */\n close(): void {\n if (this.cleanup !== null) clearInterval(this.cleanup);\n }\n\n // ─── internals ────────────────────────────────────────────────────────\n\n private checkRateLimit(key: string): GuardsDecision {\n const max = this.rl?.max ?? 100;\n const windowMs = this.rl?.windowMs ?? 60_000;\n const now = Date.now();\n let entry = this.rlStore[key];\n if (!entry || entry.resetTime < now) {\n entry = { count: 0, resetTime: now + windowMs };\n this.rlStore[key] = entry;\n }\n entry.count += 1;\n if (entry.count > max) {\n const retryAfterSeconds = Math.ceil((entry.resetTime - now) / 1000);\n return {\n ok: false,\n vector: 'rate-limit',\n severity: 'medium',\n reason: `Rate limit exceeded (${entry.count}/${max} per ${windowMs}ms)`,\n retryAfterSeconds: Math.max(0, retryAfterSeconds),\n };\n }\n return { ok: true };\n }\n\n private checkTokenBudget(key: string, tokens: number): GuardsDecision {\n const cost = Number.isFinite(tokens) && tokens >= 0 ? Math.floor(tokens) : 0;\n const max = this.tb?.maxTokens ?? 100_000;\n const windowMs = this.tb?.windowMs ?? 60 * 60 * 1000;\n const perReq = this.tb?.maxRequestTokens;\n\n if (perReq !== undefined && cost > perReq) {\n return {\n ok: false,\n vector: 'token-budget',\n severity: 'high',\n reason: `Per-call token budget exceeded (${cost} > ${perReq})`,\n };\n }\n\n const now = Date.now();\n let entry = this.tbStore[key];\n if (!entry || entry.resetTime < now) {\n entry = { used: 0, resetTime: now + windowMs };\n this.tbStore[key] = entry;\n }\n const projected = entry.used + cost;\n if (projected > max) {\n const retryAfterSeconds = Math.ceil((entry.resetTime - now) / 1000);\n return {\n ok: false,\n vector: 'token-budget',\n severity: 'medium',\n reason: `Window token budget exceeded (${entry.used} + ${cost} > ${max})`,\n retryAfterSeconds: Math.max(0, retryAfterSeconds),\n };\n }\n entry.used = projected;\n return { ok: true };\n }\n\n private checkBot(userAgent: string): GuardsDecision {\n const fakeReq = {\n headers: {\n 'user-agent': userAgent,\n accept: 'text/html',\n 'accept-language': 'en-US',\n 'accept-encoding': 'gzip',\n },\n };\n const result = detectBot(fakeReq as never);\n if (!result.isBot) return { ok: true };\n\n const allow = this.bot?.allow ? new Set(this.bot.allow) : DEFAULT_BOT_ALLOW;\n const deny = this.bot?.deny ? new Set(this.bot.deny) : DEFAULT_BOT_DENY;\n const defaultAction = this.bot?.defaultAction ?? 'allow';\n\n if (allow.has(result.category as never)) return { ok: true };\n if (deny.has(result.category as never)) {\n return {\n ok: false,\n vector: 'bot',\n severity: 'medium',\n reason: result.name ? `Bot denied: ${result.name}` : `Bot denied (${result.category})`,\n };\n }\n if (defaultAction === 'deny') {\n return {\n ok: false,\n vector: 'bot',\n severity: 'low',\n reason: `Uncategorized bot under defaultAction=deny`,\n };\n }\n return { ok: true };\n }\n\n private sweepExpired(): void {\n const now = Date.now();\n for (const k of Object.keys(this.rlStore)) {\n if (this.rlStore[k].resetTime < now) delete this.rlStore[k];\n }\n for (const k of Object.keys(this.tbStore)) {\n if (this.tbStore[k].resetTime < now) delete this.tbStore[k];\n }\n }\n}\n\nexport default Guards;\n","/**\n * @module @arcis/node/utils/ip\n * Platform-aware client IP detection.\n *\n * Prevents IP spoofing by reading platform-specific headers\n * instead of blindly trusting X-Forwarded-For.\n *\n * @example\n * // Auto-detect platform from environment\n * const ip = detectClientIp(req);\n *\n * // Explicit platform\n * const ip = detectClientIp(req, { platform: 'cloudflare' });\n */\n\nimport type { IncomingMessage } from 'http';\n\nexport type Platform =\n | 'auto'\n | 'cloudflare'\n | 'vercel'\n | 'flyio'\n | 'render'\n | 'firebase'\n | 'aws-alb'\n | 'generic';\n\nexport interface DetectIpOptions {\n /** Platform to use for header selection. Default: 'auto' */\n platform?: Platform;\n /** Number of trusted proxies (for X-Forwarded-For parsing). Default: 1 */\n trustedProxyCount?: number;\n}\n\ninterface RequestLike {\n headers: Record<string, string | string[] | undefined>;\n socket?: { remoteAddress?: string };\n connection?: { remoteAddress?: string };\n ip?: string;\n}\n\n/**\n * Platform-specific header configurations.\n * Each platform sets a trusted header that cannot be spoofed by the client.\n */\nconst PLATFORM_HEADERS: Record<Exclude<Platform, 'auto' | 'generic'>, string> = {\n cloudflare: 'cf-connecting-ip',\n vercel: 'x-real-ip',\n flyio: 'fly-client-ip',\n render: 'x-render-client-ip',\n firebase: 'x-appengine-user-ip',\n 'aws-alb': 'x-forwarded-for',\n};\n\n/**\n * Auto-detect the platform from environment variables.\n */\nfunction detectPlatform(): Platform {\n const env = typeof process !== 'undefined' ? process.env : {};\n\n if (env.CF_PAGES || env.CF_WORKERS) return 'cloudflare';\n if (env.VERCEL) return 'vercel';\n if (env.FLY_APP_NAME) return 'flyio';\n if (env.RENDER) return 'render';\n if (env.FIREBASE_CONFIG || env.GCLOUD_PROJECT) return 'firebase';\n if (env.AWS_EXECUTION_ENV || env.AWS_LAMBDA_FUNCTION_NAME) return 'aws-alb';\n\n return 'generic';\n}\n\n// Cache the detected platform — it won't change during process lifetime\nlet _cachedPlatform: Platform | null = null;\n\nfunction getCachedPlatform(): Platform {\n if (_cachedPlatform === null) {\n _cachedPlatform = detectPlatform();\n }\n return _cachedPlatform;\n}\n\n/** Max IP string length (IPv6 max = 45 chars) */\nconst MAX_IP_LENGTH = 45;\n\n/**\n * Sanitize an IP string: trim, truncate, strip control characters.\n * Prevents unbounded strings from being used as map keys.\n */\nfunction sanitizeIp(ip: string): string {\n const trimmed = ip.trim();\n if (trimmed.length > MAX_IP_LENGTH) return trimmed.slice(0, MAX_IP_LENGTH);\n return trimmed;\n}\n\n/**\n * Get a header value from the request, handling string arrays.\n */\nfunction getHeader(req: RequestLike, name: string): string | undefined {\n const val = req.headers[name];\n if (Array.isArray(val)) return val[0];\n return val;\n}\n\n/**\n * Parse the rightmost trusted IP from X-Forwarded-For.\n * Reading from the right prevents client spoofing — the rightmost entry\n * is the one added by the closest trusted proxy.\n */\nfunction parseForwardedFor(header: string, trustedProxyCount: number): string | undefined {\n const ips = header.split(',').map(ip => ip.trim()).filter(Boolean);\n if (ips.length === 0) return undefined;\n\n // The client IP is at position (length - trustedProxyCount)\n const clientIndex = Math.max(0, ips.length - trustedProxyCount);\n return ips[clientIndex] || undefined;\n}\n\n/**\n * Detect the real client IP address from a request.\n *\n * Uses platform-specific headers when available to prevent IP spoofing.\n * Falls back to X-Forwarded-For (parsed from the right) and then\n * the socket remote address.\n *\n * @param req - HTTP request object (Express, raw http, etc.)\n * @param options - Detection options\n * @returns Client IP address, or 'unknown' if unresolvable\n *\n * @example\n * // Auto-detect platform\n * app.use((req, res, next) => {\n * const clientIp = detectClientIp(req);\n * console.log('Client IP:', clientIp);\n * next();\n * });\n *\n * @example\n * // Behind Cloudflare\n * const ip = detectClientIp(req, { platform: 'cloudflare' });\n *\n * @example\n * // Behind 2 proxies (e.g. CDN + load balancer)\n * const ip = detectClientIp(req, { trustedProxyCount: 2 });\n */\nexport function detectClientIp(\n req: RequestLike | IncomingMessage,\n options: DetectIpOptions = {}\n): string {\n const { platform = 'auto', trustedProxyCount = 1 } = options;\n const r = req as RequestLike;\n\n const resolvedPlatform = platform === 'auto' ? getCachedPlatform() : platform;\n\n // 1. Try platform-specific header (most trusted)\n if (resolvedPlatform !== 'generic' && resolvedPlatform in PLATFORM_HEADERS) {\n const headerName = PLATFORM_HEADERS[resolvedPlatform as keyof typeof PLATFORM_HEADERS];\n if (headerName) {\n if (resolvedPlatform === 'aws-alb') {\n // AWS ALB: parse X-Forwarded-For from the right\n const xff = getHeader(r, 'x-forwarded-for');\n if (xff) {\n const ip = parseForwardedFor(xff, trustedProxyCount);\n if (ip) return sanitizeIp(ip);\n }\n } else {\n const ip = getHeader(r, headerName);\n if (ip) return sanitizeIp(ip);\n }\n }\n }\n\n // 2. Try Express req.ip (respects trust proxy setting)\n if (r.ip) return sanitizeIp(r.ip);\n\n // 3. Try X-Forwarded-For (parsed from the right for safety)\n const xff = getHeader(r, 'x-forwarded-for');\n if (xff) {\n const ip = parseForwardedFor(xff, trustedProxyCount);\n if (ip) return sanitizeIp(ip);\n }\n\n // 4. Try X-Real-IP\n const realIp = getHeader(r, 'x-real-ip');\n if (realIp) return sanitizeIp(realIp);\n\n // 5. Socket remote address\n const socketIp = r.socket?.remoteAddress ?? r.connection?.remoteAddress;\n if (socketIp) return sanitizeIp(socketIp);\n\n return 'unknown';\n}\n\n/**\n * Check if an IP address is a private/internal address.\n *\n * Detects: loopback, private ranges (RFC 1918), link-local, IPv6 equivalents.\n */\nexport function isPrivateIp(ip: string): boolean {\n // Strip IPv4-mapped IPv6 prefix (::ffff:127.0.0.1 -> 127.0.0.1)\n const normalized = ip.startsWith('::ffff:') ? ip.slice(7) : ip;\n\n // IPv4 private ranges\n if (/^127\\./.test(normalized)) return true; // Loopback\n if (/^10\\./.test(normalized)) return true; // Class A private\n if (/^172\\.(1[6-9]|2\\d|3[01])\\./.test(normalized)) return true; // Class B private\n if (/^192\\.168\\./.test(normalized)) return true; // Class C private\n if (/^169\\.254\\./.test(normalized)) return true; // Link-local\n if (/^0\\./.test(normalized)) return true; // Current network\n\n // IPv6\n if (ip === '::1') return true; // Loopback\n if (/^fe80:/i.test(ip)) return true; // Link-local\n if (/^fc00:/i.test(ip)) return true; // Unique local\n if (/^fd/i.test(ip)) return true; // Unique local\n\n return false;\n}\n\n/** Reset cached platform (for testing). */\nexport function _resetPlatformCache(): void {\n _cachedPlatform = null;\n}\n","/**\n * @module @arcis/node/utils/fingerprint\n * Deterministic request fingerprinting via SHA-256.\n *\n * Generates a stable hash from request characteristics for\n * rate limiting keys, abuse detection, and analytics.\n *\n * @example\n * const fp = await fingerprint(req);\n * // \"a3f2b8c1d4e5...\"\n */\n\nimport { createHash } from 'crypto';\nimport { detectClientIp } from './ip';\nimport type { DetectIpOptions } from './ip';\n\nexport interface FingerprintOptions {\n /** Include IP address in fingerprint. Default: true */\n ip?: boolean;\n /** Include User-Agent header. Default: true */\n userAgent?: boolean;\n /** Include Accept header. Default: true */\n accept?: boolean;\n /** Include Accept-Language header. Default: true */\n acceptLanguage?: boolean;\n /** Include Accept-Encoding header. Default: true */\n acceptEncoding?: boolean;\n /** Additional custom components to include */\n custom?: string[];\n /** IP detection options */\n ipOptions?: DetectIpOptions;\n}\n\ninterface RequestLike {\n headers: Record<string, string | string[] | undefined>;\n socket?: { remoteAddress?: string };\n connection?: { remoteAddress?: string };\n ip?: string;\n}\n\nfunction getHeader(req: RequestLike, name: string): string {\n const val = req.headers[name];\n if (Array.isArray(val)) return val[0] ?? '';\n return val ?? '';\n}\n\n/**\n * Generate a deterministic fingerprint for a request.\n *\n * Creates a SHA-256 hash from configurable request components.\n * The fingerprint is stable across requests from the same client\n * (same IP, browser, language settings).\n *\n * @param req - HTTP request object\n * @param options - Fingerprint configuration\n * @returns Hex-encoded SHA-256 hash (64 characters)\n *\n * @example\n * // Default fingerprint (IP + UA + Accept headers)\n * const fp = fingerprint(req);\n *\n * @example\n * // IP-only fingerprint (for simple rate limiting)\n * const fp = fingerprint(req, { userAgent: false, accept: false, acceptLanguage: false, acceptEncoding: false });\n *\n * @example\n * // With custom components\n * const fp = fingerprint(req, { custom: [req.body?.userId] });\n */\nexport function fingerprint(req: RequestLike, options: FingerprintOptions = {}): string {\n const {\n ip = true,\n userAgent = true,\n accept = true,\n acceptLanguage = true,\n acceptEncoding = true,\n custom = [],\n ipOptions,\n } = options;\n\n const components: string[] = [];\n\n if (ip) {\n components.push(`ip:${detectClientIp(req, ipOptions)}`);\n }\n if (userAgent) {\n components.push(`ua:${getHeader(req, 'user-agent')}`);\n }\n if (accept) {\n components.push(`accept:${getHeader(req, 'accept')}`);\n }\n if (acceptLanguage) {\n components.push(`lang:${getHeader(req, 'accept-language')}`);\n }\n if (acceptEncoding) {\n components.push(`enc:${getHeader(req, 'accept-encoding')}`);\n }\n\n for (const c of custom) {\n if (c !== null && c !== undefined) components.push(`custom:${c}`);\n }\n\n // Sort for deterministic ordering\n components.sort();\n\n const hash = createHash('sha256');\n hash.update(components.join('|'));\n return hash.digest('hex');\n}\n","/**\n * @module @arcis/node/stores/memory\n * In-memory rate limit store\n */\n\nimport type { RateLimitStore, RateLimitEntry } from '../core/types';\nimport { RATE_LIMIT } from '../core/constants';\n\n/**\n * In-memory rate limit store.\n * Suitable for single-instance deployments.\n * For distributed systems, use RedisStore or a custom store.\n * \n * @example\n * const store = new MemoryStore(60000); // 1 minute window\n * const limiter = createRateLimiter({ store });\n */\n/** Default maximum number of keys the in-memory store will hold. */\nconst DEFAULT_MAX_SIZE = 10_000;\n\nexport class MemoryStore implements RateLimitStore {\n private store: Map<string, RateLimitEntry> = new Map();\n private cleanupInterval: ReturnType<typeof setInterval> | null = null;\n private windowMs: number;\n private maxSize: number;\n\n constructor(windowMs: number = RATE_LIMIT.DEFAULT_WINDOW_MS, maxSize: number = DEFAULT_MAX_SIZE) {\n if (!Number.isFinite(windowMs) || windowMs < RATE_LIMIT.MIN_WINDOW_MS) {\n throw new RangeError(\n `MemoryStore: windowMs must be a finite number >= ${RATE_LIMIT.MIN_WINDOW_MS} (got ${windowMs})`\n );\n }\n if (!Number.isFinite(maxSize) || maxSize < 1) {\n throw new RangeError(`MemoryStore: maxSize must be >= 1 (got ${maxSize})`);\n }\n this.windowMs = windowMs;\n this.maxSize = maxSize;\n this.startCleanup();\n }\n\n /**\n * Start the cleanup interval to remove expired entries.\n */\n private startCleanup(): void {\n // Clamp the cleanup interval between 30 s and 5 min regardless of windowMs.\n // Running it every windowMs is fine for typical windows but would fire every\n // second for short windows (e.g. windowMs: 1000), causing O(n) GC pressure.\n const CLEANUP_MIN_MS = 30_000;\n const CLEANUP_MAX_MS = 300_000;\n const cleanupMs = Math.min(Math.max(this.windowMs, CLEANUP_MIN_MS), CLEANUP_MAX_MS);\n\n this.cleanupInterval = setInterval(() => {\n const now = Date.now();\n for (const [key, entry] of this.store.entries()) {\n if (entry.resetTime < now) {\n this.store.delete(key);\n }\n }\n }, cleanupMs);\n\n // Prevent interval from keeping the process alive\n if (typeof this.cleanupInterval.unref === 'function') {\n this.cleanupInterval.unref();\n }\n }\n\n async get(key: string): Promise<RateLimitEntry | null> {\n const entry = this.store.get(key);\n if (!entry) return null;\n \n // Check if expired\n if (entry.resetTime < Date.now()) {\n this.store.delete(key);\n return null;\n }\n \n return entry;\n }\n\n async set(key: string, entry: RateLimitEntry): Promise<void> {\n if (!this.store.has(key) && this.store.size >= this.maxSize) {\n this.evictExpired();\n // If still at capacity after eviction, fail open — don't crash the app\n if (this.store.size >= this.maxSize) return;\n }\n this.store.set(key, entry);\n }\n\n async increment(key: string): Promise<number> {\n const now = Date.now();\n const entry = this.store.get(key);\n\n if (!entry || entry.resetTime < now) {\n // Start new window — check capacity first\n if (this.store.size >= this.maxSize) {\n this.evictExpired();\n if (this.store.size >= this.maxSize) return 1; // fail open\n }\n this.store.set(key, { count: 1, resetTime: now + this.windowMs });\n return 1;\n }\n\n entry.count++;\n return entry.count;\n }\n\n /** Eagerly remove expired entries to reclaim capacity. */\n private evictExpired(): void {\n const now = Date.now();\n for (const [key, entry] of this.store.entries()) {\n if (entry.resetTime < now) this.store.delete(key);\n }\n }\n\n async decrement(key: string): Promise<void> {\n const entry = this.store.get(key);\n if (entry && entry.count > 0) {\n entry.count--;\n }\n }\n\n async reset(key: string): Promise<void> {\n this.store.delete(key);\n }\n\n async close(): Promise<void> {\n if (this.cleanupInterval) {\n clearInterval(this.cleanupInterval);\n this.cleanupInterval = null;\n }\n this.store.clear();\n }\n\n /**\n * Get current store size (for monitoring).\n */\n get size(): number {\n return this.store.size;\n }\n}\n","/**\n * @module @arcis/node/stores/redis\n * Redis rate limit store\n * \n * Note: This is a reference implementation. You'll need to install\n * the 'ioredis' or 'redis' package and pass your client instance.\n */\n\nimport type { RateLimitStore, RateLimitEntry } from '../core/types';\nimport { RATE_LIMIT } from '../core/constants';\n\n/** Generic Redis client interface (works with ioredis, redis, etc.) */\nexport interface RedisClientLike {\n get(key: string): Promise<string | null>;\n /**\n * SET with optional flags. Supports both `set(key, value)` and\n * `set(key, value, 'EX', seconds, 'NX')` shapes for atomic\n * set-if-not-exists with TTL. Returns 'OK' on success; null when NX\n * is supplied and the key already exists.\n */\n set(\n key: string,\n value: string,\n ...args: Array<string | number>\n ): Promise<string | null | unknown>;\n setex(key: string, seconds: number, value: string): Promise<unknown>;\n expire(key: string, seconds: number): Promise<unknown>;\n incr(key: string): Promise<number>;\n decr(key: string): Promise<number>;\n del(key: string): Promise<number>;\n ttl(key: string): Promise<number>;\n quit?(): Promise<unknown>;\n disconnect?(): Promise<unknown>;\n}\n\nexport interface RedisStoreOptions {\n /** Redis client instance */\n client: RedisClientLike;\n /** Key prefix. Default: 'arcis:rl:' */\n prefix?: string;\n /** Window size in milliseconds. Default: 60000 */\n windowMs?: number;\n}\n\n/**\n * Redis rate limit store for distributed deployments.\n * \n * @example\n * import Redis from 'ioredis';\n * \n * const redis = new Redis();\n * const store = new RedisStore({ client: redis });\n * const limiter = createRateLimiter({ store });\n * \n * // Cleanup on shutdown\n * process.on('SIGTERM', async () => {\n * await store.close();\n * });\n */\nexport class RedisStore implements RateLimitStore {\n private client: RedisClientLike;\n private prefix: string;\n private windowMs: number;\n private windowSec: number;\n\n constructor(options: RedisStoreOptions) {\n this.client = options.client;\n this.prefix = options.prefix ?? 'arcis:rl:';\n this.windowMs = options.windowMs ?? RATE_LIMIT.DEFAULT_WINDOW_MS;\n this.windowSec = Math.ceil(this.windowMs / 1000);\n }\n\n private getKey(key: string): string {\n return `${this.prefix}${key}`;\n }\n\n async get(key: string): Promise<RateLimitEntry | null> {\n const redisKey = this.getKey(key);\n \n const [countStr, ttl] = await Promise.all([\n this.client.get(redisKey),\n this.client.ttl(redisKey),\n ]);\n \n if (!countStr || ttl < 0) {\n return null;\n }\n \n const count = parseInt(countStr, 10);\n if (isNaN(count)) {\n // Corrupt value in Redis — treat as if key doesn't exist\n return null;\n }\n\n return {\n count,\n resetTime: Date.now() + (ttl * 1000),\n };\n }\n\n async set(key: string, entry: RateLimitEntry): Promise<void> {\n const redisKey = this.getKey(key);\n // Clamp to at least 1 second — Math.ceil can produce 0 or negative values\n // when entry.resetTime is in the past due to Redis latency or clock skew.\n const ttlSec = Math.max(1, Math.ceil((entry.resetTime - Date.now()) / 1000));\n await this.client.setex(redisKey, ttlSec, entry.count.toString());\n }\n\n async increment(key: string): Promise<number> {\n const redisKey = this.getKey(key);\n\n // SECURITY / RELIABILITY: Atomic first-increment via SET ... EX ... NX.\n // If the key did not exist, this single command creates it with value\n // 1 and the window TTL atomically. If it existed, SET returns null\n // and we fall through to INCR for the actual count. This eliminates\n // the INCR-then-EXPIRE race where a connection drop between the two\n // commands could leave a counter without a TTL, locking out the\n // client until manual intervention.\n const created = await this.client.set(redisKey, '1', 'EX', this.windowSec, 'NX');\n if (created === 'OK' || created === true) {\n return 1;\n }\n return this.client.incr(redisKey);\n }\n\n async decrement(key: string): Promise<void> {\n const redisKey = this.getKey(key);\n await this.client.decr(redisKey);\n }\n\n async reset(key: string): Promise<void> {\n const redisKey = this.getKey(key);\n await this.client.del(redisKey);\n }\n\n async close(): Promise<void> {\n // Don't close the client - it may be shared\n // The caller should manage the client lifecycle\n }\n}\n\n/**\n * Create a Redis store with the given options.\n * Convenience function for functional programming style.\n * \n * @example\n * const store = createRedisStore({ client: redisClient });\n */\nexport function createRedisStore(options: RedisStoreOptions): RedisStore {\n return new RedisStore(options);\n}\n"]}
|
|
1
|
+
{"version":3,"sources":["../src/core/constants.ts","../src/middleware/headers.ts","../src/middleware/rate-limit.ts","../src/middleware/error-handler.ts","../src/core/errors.ts","../src/middleware/telemetry.ts","../src/sanitizers/utils.ts","../src/sanitizers/xss.ts","../src/sanitizers/sql.ts","../src/sanitizers/path.ts","../src/sanitizers/command.ts","../src/sanitizers/ssti.ts","../src/sanitizers/xxe.ts","../src/sanitizers/ldap.ts","../src/sanitizers/xpath.ts","../src/sanitizers/headers.ts","../src/sanitizers/sanitize.ts","../src/sanitizers/nosql.ts","../src/sanitizers/prototype.ts","../src/sanitizers/jsonp.ts","../src/sanitizers/pii.ts","../src/sanitizers/encode.ts","../src/sanitizers/graphql.ts","../src/validation/schema.ts","../src/validation/file.ts","../src/validation/url.ts","../src/validation/url-async.ts","../src/validation/redirect.ts","../src/validation/email.ts","../src/logging/redactor.ts","../src/telemetry/client.ts","../src/middleware/main.ts","../src/utils/duration.ts","../src/middleware/rate-limit-sliding.ts","../src/middleware/rate-limit-token.ts","../src/middleware/cors.ts","../src/middleware/cookies.ts","../src/data/bot-patterns.json","../src/middleware/bot-detection.ts","../src/middleware/csrf.ts","../src/middleware/hpp.ts","../src/middleware/response-splitting.ts","../src/middleware/token-budget.ts","../src/middleware/overload.ts","../src/middleware/method-allowlist.ts","../src/middleware/mass-assign.ts","../src/middleware/signup-protection.ts","../src/_third_party/rate-limit/abstract.ts","../src/_third_party/rate-limit/types.ts","../src/_third_party/rate-limit/record.ts","../src/_third_party/rate-limit/memory-storage.ts","../src/_third_party/rate-limit/memory.ts","../src/middleware/brute-force.ts","../src/middleware/protect.ts","../src/middleware/graphql.ts","../src/middleware/correlation.ts","../src/sanitizers/prompt-injection.ts","../src/guards.ts","../src/utils/ip.ts","../src/utils/fingerprint.ts","../src/stores/memory.ts","../src/stores/redis.ts"],"names":["resolve","lookup","host","dns","DEFAULTS","defaultKeyGenerator","SEVERITY_RANK","xff","getHeader","DEFAULT_MAX_SIZE"],"mappings":"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","file":"index.mjs","sourcesContent":["/**\n * @module @arcis/node/core/constants\n * Named constants for Arcis - no magic numbers\n */\n\n// =============================================================================\n// INPUT LIMITS\n// =============================================================================\nexport const INPUT = {\n /** Default maximum input size (1MB) */\n DEFAULT_MAX_SIZE: 1_000_000,\n /** Maximum recursion depth for nested objects */\n MAX_RECURSION_DEPTH: 10,\n} as const;\n\n// =============================================================================\n// RATE LIMITING\n// =============================================================================\nexport const RATE_LIMIT = {\n /** Default window size (1 minute) */\n DEFAULT_WINDOW_MS: 60_000,\n /** Default max requests per window */\n DEFAULT_MAX_REQUESTS: 100,\n /** Default HTTP status code for rate limited responses */\n DEFAULT_STATUS_CODE: 429,\n /** Default error message */\n DEFAULT_MESSAGE: 'Too many requests, please try again later.',\n /** Minimum window size (1 second) */\n MIN_WINDOW_MS: 1_000,\n /** Maximum window size (24 hours) */\n MAX_WINDOW_MS: 86_400_000,\n} as const;\n\n// =============================================================================\n// SECURITY HEADERS\n// =============================================================================\nexport const HEADERS = {\n /** Default Content Security Policy */\n DEFAULT_CSP: [\n \"default-src 'self'\",\n \"script-src 'self'\",\n \"style-src 'self' 'unsafe-inline'\",\n \"img-src 'self' data: https:\",\n \"font-src 'self'\",\n \"object-src 'none'\",\n \"frame-ancestors 'none'\",\n ].join('; '),\n /** Default HSTS max age (1 year in seconds) */\n HSTS_MAX_AGE: 31_536_000,\n /** Default X-Frame-Options value */\n FRAME_OPTIONS: 'DENY' as const,\n /** Default X-Content-Type-Options value */\n CONTENT_TYPE_OPTIONS: 'nosniff',\n /** Default Referrer-Policy value */\n REFERRER_POLICY: 'strict-origin-when-cross-origin',\n /** Default Permissions-Policy value */\n PERMISSIONS_POLICY: 'geolocation=(), microphone=(), camera=()',\n /** Default Cache-Control value for security */\n CACHE_CONTROL: 'no-store, no-cache, must-revalidate, proxy-revalidate',\n} as const;\n\n// =============================================================================\n// XSS PATTERNS (ReDoS-safe)\n// =============================================================================\n\n/**\n * Detection patterns — used to flag whether a string contains XSS payloads.\n * Must stay in sync with XSS_REMOVE_PATTERNS below.\n */\nexport const XSS_PATTERNS = [\n /** Script tags (ReDoS-safe version) */\n /<script[^>]*>[\\s\\S]*?<\\/script>/gi,\n /** javascript: protocol (allow optional spaces before colon) */\n /javascript\\s*:/gi,\n /** vbscript: protocol */\n /vbscript\\s*:/gi,\n /** Event handlers (onclick, onerror, etc.) — any separator before attribute */\n /(?:[\\s/])on\\w+\\s*=/gi,\n /** iframe tags */\n /<iframe/gi,\n /** object tags */\n /<object/gi,\n /** embed tags */\n /<embed/gi,\n /** data: URIs (only dangerous ones, avoid false positives) */\n /(?:^|[\\s\"'=])data:/gi,\n /** URL-encoded script tags */\n /%3Cscript/gi,\n /** SVG with onload */\n /<svg[^>]*onload/gi,\n /** form tags — phishing/credential harvesting via action= redirection */\n /<form[\\s>]/gi,\n /** meta tags — http-equiv refresh redirects or CSP bypass */\n /<meta[\\s>]/gi,\n /** base href hijacking — redirects all relative URLs to attacker domain */\n /<base[\\s>]/gi,\n /** link tag injection — stylesheet or preload CSRF attacks */\n /<link[\\s>]/gi,\n /** style tag — CSS expression() / behavior: / IE-era attacks. Mirrors\n * Python's xss-style-tag from packages/core/patterns.json. */\n /<style[\\s>]/gi,\n] as const;\n\n/**\n * Removal patterns — used by sanitizeXss() to strip dangerous content.\n * More targeted than XSS_PATTERNS: each pattern captures the full dangerous\n * substring (tag, attribute + value, protocol) so it can be replaced safely.\n * Must stay in sync with XSS_PATTERNS above.\n */\nexport const XSS_REMOVE_PATTERNS = [\n /** Full script blocks (content + tags) */\n /<script[^>]*>[\\s\\S]*?<\\/script>/gi,\n /** Standalone/unclosed script tags */\n /<script[^>]*>/gi,\n /** style — CSS expression() and behavior: attacks (IE-era but still relevant) */\n /<style[^>]*>[\\s\\S]*?<\\/style>/gi,\n /<style[^>]*/gi,\n /** iframe — full block and partial/unclosed */\n /<iframe[^>]*>[\\s\\S]*?<\\/iframe>/gi,\n /<iframe[^>]*/gi,\n /** object — full block and partial/unclosed */\n /<object[^>]*>[\\s\\S]*?<\\/object>/gi,\n /<object[^>]*/gi,\n /** embed tags */\n /<embed[^>]*/gi,\n /** SVG with inline event handlers */\n /<svg[^>]*onload[^>]*>/gi,\n /** URL-encoded script tags */\n /%3Cscript/gi,\n /** Event handlers with quoted values: onclick=\"...\", onerror='...' */\n /(?:[\\s/])on\\w+\\s*=\\s*[\"'][^\"']*[\"']/gi,\n /** Event handlers with unquoted values: onload=value */\n /(?:[\\s/])on\\w+\\s*=\\s*[^\\s>]*/gi,\n /** javascript: and vbscript: protocols (allow optional spaces before colon) */\n /javascript\\s*:/gi,\n /vbscript\\s*:/gi,\n /** data: URIs with HTML or SVG content (SVG can run JS via inline event handlers) */\n /data\\s*:\\s*(?:text\\/html|image\\/svg)[^>\\s]*/gi,\n /** form tag injection — phishing via action= redirection */\n /<form[\\s>][^>]*/gi,\n /** meta tag injection — http-equiv refresh or CSP bypass */\n /<meta[\\s>][^>]*/gi,\n /** base href hijacking */\n /<base[\\s>][^>]*/gi,\n /** link tag injection — stylesheet or preload attacks */\n /<link[\\s>][^>]*/gi,\n] as const;\n\n// =============================================================================\n// SQL INJECTION PATTERNS\n// =============================================================================\nexport const SQL_PATTERNS = [\n /** SQL keywords */\n /(\\b(SELECT|INSERT|UPDATE|DELETE|DROP|UNION|ALTER|CREATE|TRUNCATE|EXEC|EXECUTE)\\b)/gi,\n /** SQL comments: ANSI (--), C-style (slash-star ... star-slash), MySQL (#) */\n /(--|\\/\\*|\\*\\/|#)/g,\n /** SQL statement separators */\n /(;|\\|\\||&&)/g,\n /** Boolean injection: OR 1=1 */\n /\\bOR\\s+\\d+\\s*=\\s*\\d+/gi,\n /** Boolean injection: OR 'a'='a' or OR \"a\"=\"a\" (including mixed quotes) */\n /\\bOR\\s+(['\"])[^'\"]*\\1\\s*=\\s*(['\"])[^'\"]*\\2/gi,\n /\\bOR\\s+('[^']*'|\"[^\"]*\")\\s*=\\s*('[^']*'|\"[^\"]*\")/gi,\n /** Boolean injection: AND 1=1 */\n /\\bAND\\s+\\d+\\s*=\\s*\\d+/gi,\n /** Boolean injection: AND 'a'='a' or AND \"a\"=\"a\" (including mixed quotes) */\n /\\bAND\\s+(['\"])[^'\"]*\\1\\s*=\\s*(['\"])[^'\"]*\\2/gi,\n /\\bAND\\s+('[^']*'|\"[^\"]*\")\\s*=\\s*('[^']*'|\"[^\"]*\")/gi,\n /** Time-based blind: SLEEP() */\n /\\bSLEEP\\s*\\(\\s*\\d+\\s*\\)/gi,\n /** Time-based blind: BENCHMARK() */\n /\\bBENCHMARK\\s*\\(/gi,\n /** Time-based blind: PostgreSQL pg_sleep() */\n /\\bpg_sleep\\s*\\(/gi,\n /** Time-based blind: MSSQL WAITFOR DELAY */\n /\\bWAITFOR\\s+DELAY\\b/gi,\n /**\n * Oracle DBMS_* stdlib packages used for time-based blind SQLi\n * (DBMS_LOCK.SLEEP, DBMS_PIPE.RECEIVE_MESSAGE) and other Oracle\n * abuse paths. No legitimate user input contains these. Mirrors\n * `sqli-oracle-dbms-packages` in packages/core/patterns.json —\n * improvements.md §1.1.e Q3. Must stay in sync until Node\n * migrates to patterns.json-at-runtime (planned v1.7).\n */\n /\\bDBMS_(?:LOCK|PIPE|UTILITY|XSLPROCESSOR|JAVA|OUTPUT|SCHEDULER)\\b/gi,\n] as const;\n\n// =============================================================================\n// PATH TRAVERSAL PATTERNS\n// =============================================================================\nexport const PATH_PATTERNS = [\n /** Unix path traversal */\n /\\.\\.\\//g,\n /** Windows path traversal */\n /\\.\\.\\\\/g,\n /** URL-encoded traversal (%2e%2e) */\n /%2e%2e/gi,\n /** Double URL-encoded traversal (%252e) */\n /%252e/gi,\n /** Mixed encoding: ..%2F */\n /\\.\\.%2F/gi,\n /** Mixed encoding: %2e./ and .%2e/ */\n /%2e\\.[\\\\/]/gi,\n /\\.%2e[\\\\/]/gi,\n /** Fully URL-encoded: %2e%2e%2f */\n /%2e%2e%2f/gi,\n /** Double URL-encoded forward slash: %252f */\n /%252f/gi,\n /** Dotdotslash bypass: ....// or ....\\\\ */\n /\\.{2,}[/\\\\]{2,}/g,\n /** Null byte injection in paths */\n /\\0/g,\n] as const;\n\n// =============================================================================\n// COMMAND INJECTION PATTERNS\n// =============================================================================\nexport const COMMAND_PATTERNS = [\n /**\n * Shell metacharacters that enable command chaining/substitution.\n * Bare ( and ) are excluded — they appear in common legitimate values\n * (function calls in code fields, math expressions, etc.).\n * Command substitution is caught by the $( combined pattern below.\n * NOTE: ';', '&', '|' may appear in legitimate URL query strings\n * and Markdown; consider disabling command checking (command: false)\n * for fields that intentionally allow those characters.\n */\n /[;&|`]/g,\n /** Command substitution: $( ... ) — matched as a pair to reduce false positives */\n /\\$\\(/g,\n /**\n * POSIX shell IFS-substitution: ${IFS} or ${IFS%??}.\n * Attackers use this to inject spaces past metacharacter filters\n * in payloads like `;cat${IFS}/etc/passwd`. Mirrors\n * `cmdi-ifs-bypass` in packages/core/patterns.json — improvements.md\n * §1.1.e Q5. Must stay in sync until Node migrates to\n * patterns.json-at-runtime (planned v1.7).\n */\n /\\$\\{IFS(?:%[^}]*)?\\}/g,\n /** URL-encoded control characters (%00-%0F): null, tab, vtab, formfeed, LF, CR */\n /%0[0-9a-f]/gi,\n] as const;\n\n// =============================================================================\n// DANGEROUS KEYS\n// =============================================================================\n\n/**\n * Prototype pollution keys to block.\n * Stored lowercase — always compare with key.toLowerCase().\n *\n * Includes:\n * - __proto__: direct prototype assignment\n * - constructor: access to constructor.prototype chain\n * - prototype: direct prototype property\n * - __defineGetter__/__defineSetter__: legacy property definition (can override getters/setters)\n * - __lookupGetter__/__lookupSetter__: legacy property introspection\n */\nexport const DANGEROUS_PROTO_KEYS = new Set([\n '__proto__',\n 'constructor',\n 'prototype',\n '__definegetter__',\n '__definesetter__',\n '__lookupgetter__',\n '__lookupsetter__',\n]);\n\n/** MongoDB operators to block */\nexport const NOSQL_DANGEROUS_KEYS = new Set([\n // Comparison\n '$gt', '$gte', '$lt', '$lte', '$ne', '$eq', '$in', '$nin',\n // Logical\n '$and', '$or', '$not', '$nor',\n // Element / evaluation\n '$exists', '$type', '$regex', '$where', '$expr', '$mod', '$text', '$jsonSchema',\n // Array\n '$elemMatch', '$all', '$size',\n // JavaScript execution (critical)\n '$function', '$accumulator',\n // Aggregation pipeline operators (injectable via $lookup etc.)\n '$lookup', '$match', '$project', '$group', '$sort', '$limit', '$skip',\n '$unwind', '$addFields', '$replaceRoot',\n]);\n\n// =============================================================================\n// REDACTION\n// =============================================================================\nexport const REDACTION = {\n /** Replacement text for redacted values */\n REPLACEMENT: '[REDACTED]',\n /** Truncation indicator */\n TRUNCATED: '[TRUNCATED]',\n /** Max depth indicator */\n MAX_DEPTH: '[MAX_DEPTH]',\n /** Default max message length */\n DEFAULT_MAX_LENGTH: 10_000,\n /** Default sensitive keys to redact */\n SENSITIVE_KEYS: new Set([\n 'password', 'passwd', 'pwd', 'secret', 'token', 'apikey',\n 'api_key', 'apiKey', 'auth', 'authorization', 'credit_card',\n 'creditcard', 'cc', 'ssn', 'social_security', 'private_key',\n 'privateKey', 'access_token', 'accessToken', 'refresh_token',\n 'refreshToken', 'bearer', 'jwt', 'session', 'cookie',\n 'credentials', 'x-api-key', 'x-auth-token',\n ]),\n} as const;\n\n// =============================================================================\n// VALIDATION PATTERNS\n// =============================================================================\nexport const VALIDATION = {\n /**\n * Email regex pattern.\n * Rejects consecutive dots in local part (e.g. test..foo@example.com),\n * leading/trailing dots, and other common invalid forms.\n */\n EMAIL: /^[^\\s@.][^\\s@]*(?:\\.[^\\s@.][^\\s@]*)*@[^\\s@]+\\.[^\\s@]+$/,\n /**\n * URL regex pattern.\n * Only allows http:// and https:// (case-insensitive scheme per\n * RFC 3986); explicitly rejects javascript:, data:, vbscript:, and\n * other dangerous URI schemes.\n */\n URL: /^https?:\\/\\/[^\\s/$.?#][^\\s]*$/i,\n /** UUID regex pattern (v4) */\n UUID: /^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/i,\n} as const;\n\n// =============================================================================\n// ERROR MESSAGES\n// =============================================================================\nexport const ERRORS = {\n /** Generic error message (production) */\n INTERNAL_SERVER_ERROR: 'Internal Server Error',\n /** Input too large error */\n INPUT_TOO_LARGE: (maxSize: number) => `Input exceeds maximum size of ${maxSize} bytes`,\n /** Validation error messages */\n VALIDATION: {\n REQUIRED: (field: string) => `${field} is required`,\n INVALID_TYPE: (field: string, type: string) => `${field} must be a ${type}`,\n MIN_LENGTH: (field: string, min: number) => `${field} must be at least ${min} characters`,\n MAX_LENGTH: (field: string, max: number) => `${field} must be at most ${max} characters`,\n MIN_VALUE: (field: string, min: number) => `${field} must be at least ${min}`,\n MAX_VALUE: (field: string, max: number) => `${field} must be at most ${max}`,\n INVALID_FORMAT: (field: string) => `${field} format is invalid`,\n INVALID_EMAIL: (field: string) => `${field} must be a valid email`,\n INVALID_URL: (field: string) => `${field} must be a valid URL`,\n INVALID_UUID: (field: string) => `${field} must be a valid UUID`,\n INVALID_ENUM: (field: string, values: unknown[]) => `${field} must be one of: ${values.join(', ')}`,\n MIN_ITEMS: (field: string, min: number) => `${field} must have at least ${min} items`,\n MAX_ITEMS: (field: string, max: number) => `${field} must have at most ${max} items`,\n },\n} as const;\n\n// =============================================================================\n// BLOCKED TEXT (for sanitizer replacements)\n// =============================================================================\nexport const BLOCKED = '[BLOCKED]' as const;\n","/**\n * @module @arcis/node/middleware/headers\n * Security headers middleware\n */\n\nimport type { Request, Response, NextFunction, RequestHandler } from 'express';\nimport { HEADERS } from '../core/constants';\nimport type { HeaderOptions, HstsOptions } from '../core/types';\n\n/**\n * Create Express middleware for security headers.\n * Sets CSP, HSTS, X-Frame-Options, and other security headers.\n * \n * @param options - Header configuration\n * @returns Express middleware\n * \n * @example\n * app.use(createHeaders());\n * \n * @example\n * app.use(createHeaders({\n * frameOptions: 'SAMEORIGIN',\n * contentSecurityPolicy: \"default-src 'self'\"\n * }));\n */\nexport function createHeaders(options: HeaderOptions = {}): RequestHandler {\n const {\n contentSecurityPolicy = true,\n xssFilter = true,\n noSniff = true,\n frameOptions = HEADERS.FRAME_OPTIONS,\n hsts = true,\n referrerPolicy = HEADERS.REFERRER_POLICY,\n permissionsPolicy = HEADERS.PERMISSIONS_POLICY,\n cacheControl = true,\n crossOriginOpenerPolicy = 'same-origin',\n crossOriginResourcePolicy = 'same-origin',\n crossOriginEmbedderPolicy = 'require-corp',\n originAgentCluster = true,\n dnsPrefetchControl = true,\n } = options;\n\n return (req: Request, res: Response, next: NextFunction) => {\n // Content Security Policy\n if (contentSecurityPolicy) {\n const csp = typeof contentSecurityPolicy === 'string' \n ? contentSecurityPolicy \n : HEADERS.DEFAULT_CSP;\n res.setHeader('Content-Security-Policy', csp);\n }\n\n // X-XSS-Protection: 0 disables the legacy XSS auditor which was itself\n // an attack vector (could be abused to selectively block legitimate scripts)\n if (xssFilter) {\n res.setHeader('X-XSS-Protection', '0');\n }\n\n // Prevent MIME type sniffing\n if (noSniff) {\n res.setHeader('X-Content-Type-Options', HEADERS.CONTENT_TYPE_OPTIONS);\n }\n\n // Clickjacking protection\n if (frameOptions) {\n res.setHeader('X-Frame-Options', frameOptions);\n }\n\n // HTTPS enforcement (HSTS)\n // Only send HSTS over HTTPS — sending it over HTTP can brick HTTP-only\n // development servers and confuses browsers that cache the directive.\n // X-Forwarded-Proto is client-supplied so we validate the extracted value\n // is exactly 'https' or 'http' before trusting it.\n const forwardedProto = (req.headers['x-forwarded-proto'] as string | undefined)\n ?.split(',')[0]\n .trim()\n .toLowerCase();\n const trustedForwardedProto = forwardedProto === 'https' || forwardedProto === 'http'\n ? forwardedProto\n : undefined;\n const isHttps = req.secure || trustedForwardedProto === 'https';\n\n if (hsts && isHttps) {\n const hstsOpts: HstsOptions = typeof hsts === 'object' ? hsts : {};\n const maxAge = hstsOpts.maxAge ?? HEADERS.HSTS_MAX_AGE;\n const includeSubDomains = hstsOpts.includeSubDomains !== false;\n const preload = hstsOpts.preload === true;\n\n let hstsValue = `max-age=${maxAge}`;\n if (includeSubDomains) hstsValue += '; includeSubDomains';\n if (preload) hstsValue += '; preload';\n\n res.setHeader('Strict-Transport-Security', hstsValue);\n }\n\n // Referrer Policy\n if (referrerPolicy) {\n res.setHeader('Referrer-Policy', referrerPolicy);\n }\n\n // Permissions Policy\n if (permissionsPolicy) {\n res.setHeader('Permissions-Policy', permissionsPolicy);\n }\n\n // Cross-origin isolation headers (Spectre mitigation)\n if (crossOriginOpenerPolicy) {\n res.setHeader('Cross-Origin-Opener-Policy', crossOriginOpenerPolicy);\n }\n\n if (crossOriginResourcePolicy) {\n res.setHeader('Cross-Origin-Resource-Policy', crossOriginResourcePolicy);\n }\n\n if (crossOriginEmbedderPolicy) {\n res.setHeader('Cross-Origin-Embedder-Policy', crossOriginEmbedderPolicy);\n }\n\n // Request origin-keyed process isolation\n if (originAgentCluster) {\n res.setHeader('Origin-Agent-Cluster', '?1');\n }\n\n // Prevent DNS prefetching (privacy leak vector)\n if (dnsPrefetchControl) {\n res.setHeader('X-DNS-Prefetch-Control', 'off');\n }\n\n // Additional security headers\n res.setHeader('X-Permitted-Cross-Domain-Policies', 'none');\n\n // Cache-Control headers\n if (cacheControl) {\n const cacheControlValue = typeof cacheControl === 'string'\n ? cacheControl\n : HEADERS.CACHE_CONTROL;\n res.setHeader('Cache-Control', cacheControlValue);\n res.setHeader('Pragma', 'no-cache');\n res.setHeader('Expires', '0');\n }\n\n // Remove fingerprinting headers\n res.removeHeader('X-Powered-By');\n\n next();\n };\n}\n\n/**\n * Alias for createHeaders\n * @see createHeaders\n */\nexport const securityHeaders = createHeaders;\n","/**\n * @module @arcis/node/middleware/rate-limit\n * Rate limiting middleware\n */\n\nimport type { Request, Response, NextFunction, RequestHandler } from 'express';\nimport { RATE_LIMIT } from '../core/constants';\nimport type { RateLimitOptions, RateLimiterMiddleware, RateLimitEntry } from '../core/types';\n\n/** In-memory rate limit store */\ninterface InMemoryRateLimitStore {\n [key: string]: RateLimitEntry;\n}\n\n/**\n * Create Express middleware for rate limiting.\n * \n * @param options - Rate limit configuration\n * @returns Express middleware with cleanup method\n * \n * @example\n * app.use(createRateLimiter({ max: 100, windowMs: 60000 }));\n * \n * @example\n * // Skip rate limiting for certain routes\n * app.use(createRateLimiter({\n * max: 50,\n * skip: (req) => req.path === '/health'\n * }));\n * \n * @example\n * // Cleanup on shutdown\n * const limiter = createRateLimiter();\n * app.use(limiter);\n * process.on('SIGTERM', () => limiter.close());\n */\nexport function createRateLimiter(options: RateLimitOptions = {}): RateLimiterMiddleware {\n const {\n max = RATE_LIMIT.DEFAULT_MAX_REQUESTS,\n windowMs = RATE_LIMIT.DEFAULT_WINDOW_MS,\n message = RATE_LIMIT.DEFAULT_MESSAGE,\n statusCode = RATE_LIMIT.DEFAULT_STATUS_CODE,\n keyGenerator = (req) => {\n const ip = req.ip ?? req.socket?.remoteAddress;\n if (ip) return ip;\n // SECURITY: When IP is unresolvable, fall back to a fingerprint of UA +\n // Accept-Language so unresolvable clients don't share a single counter\n // (one attacker could exhaust the limit and block every other client).\n const ua = (req.headers['user-agent'] ?? '') as string;\n const lang = (req.headers['accept-language'] ?? '') as string;\n const fp = `${ua}|${lang}`;\n // Small non-crypto hash — just needs to disperse unknown clients\n let hash = 0;\n for (let i = 0; i < fp.length; i++) hash = ((hash << 5) - hash + fp.charCodeAt(i)) | 0;\n return `unknown:${hash.toString(36)}`;\n },\n skip,\n store: externalStore,\n } = options;\n\n // Object.create(null) avoids prototype pollution if keyGenerator ever\n // returns '__proto__', 'constructor', or 'prototype'.\n const inMemoryStore = Object.create(null) as InMemoryRateLimitStore;\n\n // Cleanup interval for in-memory store (only create if not using external store)\n let cleanupInterval: ReturnType<typeof setInterval> | null = null;\n \n if (!externalStore) {\n cleanupInterval = setInterval(() => {\n const now = Date.now();\n for (const key of Object.keys(inMemoryStore)) {\n if (inMemoryStore[key].resetTime < now) {\n delete inMemoryStore[key];\n }\n }\n }, windowMs);\n\n // Prevent interval from keeping the process alive (Node.js only)\n if (typeof cleanupInterval.unref === 'function') {\n cleanupInterval.unref();\n }\n }\n\n const handler: RequestHandler = async (req: Request, res: Response, next: NextFunction) => {\n try {\n if (skip?.(req)) {\n return next();\n }\n\n const key = keyGenerator(req);\n const now = Date.now();\n\n let count: number;\n let resetTime: number;\n\n if (externalStore) {\n // Use external store (e.g., Redis)\n const entry = await externalStore.get(key);\n if (!entry || entry.resetTime < now) {\n await externalStore.set(key, { count: 1, resetTime: now + windowMs });\n count = 1;\n resetTime = now + windowMs;\n } else {\n count = await externalStore.increment(key);\n resetTime = entry.resetTime;\n }\n } else {\n // Use in-memory store\n if (!inMemoryStore[key] || inMemoryStore[key].resetTime < now) {\n inMemoryStore[key] = { count: 1, resetTime: now + windowMs };\n } else {\n inMemoryStore[key].count++;\n }\n count = inMemoryStore[key].count;\n resetTime = inMemoryStore[key].resetTime;\n }\n\n const remaining = Math.max(0, max - count);\n const resetSeconds = Math.ceil((resetTime - now) / 1000);\n\n // Set rate limit headers\n res.setHeader('X-RateLimit-Limit', max.toString());\n res.setHeader('X-RateLimit-Remaining', remaining.toString());\n res.setHeader('X-RateLimit-Reset', resetSeconds.toString());\n\n if (count > max) {\n res.setHeader('Retry-After', resetSeconds.toString());\n res.status(statusCode).json({\n error: message,\n retryAfter: resetSeconds,\n });\n return;\n }\n\n next();\n } catch (error) {\n // External store failed — fall back to in-memory rate limiting.\n // Pure fail-open is a security bypass; in-memory fallback maintains protection.\n // eslint-disable-next-line no-console\n console.error('[arcis] Rate limiter store error, using in-memory fallback:', error);\n try {\n const key = keyGenerator(req);\n const now = Date.now();\n if (!inMemoryStore[key] || inMemoryStore[key].resetTime < now) {\n inMemoryStore[key] = { count: 1, resetTime: now + windowMs };\n } else {\n inMemoryStore[key].count++;\n }\n const count = inMemoryStore[key].count;\n if (count > max) {\n const resetSeconds = Math.ceil((inMemoryStore[key].resetTime - now) / 1000);\n res.setHeader('Retry-After', resetSeconds.toString());\n res.status(statusCode).json({ error: message, retryAfter: resetSeconds });\n return;\n }\n } catch {\n // If even fallback fails, allow through to preserve availability\n }\n next();\n }\n };\n\n // Attach close method for cleanup\n const middleware = handler as RateLimiterMiddleware;\n middleware.close = () => {\n if (cleanupInterval) {\n clearInterval(cleanupInterval);\n cleanupInterval = null;\n }\n };\n\n return middleware;\n}\n\n/**\n * Alias for createRateLimiter\n * @see createRateLimiter\n */\nexport const rateLimit = createRateLimiter;\n","/**\n * @module @arcis/node/middleware/error-handler\n * Production-safe error handler middleware\n */\n\nimport type { Request, Response, NextFunction } from 'express';\nimport { ERRORS } from '../core/constants';\nimport type { ErrorHandlerOptions, HttpError } from '../core/types';\n\n/**\n * Patterns that indicate database or infrastructure internals in error messages.\n * When detected, the message is replaced with a generic error to prevent info leakage.\n */\nconst SENSITIVE_ERROR_PATTERNS: RegExp[] = [\n // SQL database errors\n /\\b(SQLITE_ERROR|SQLSTATE|ORA-\\d|PG::|mysql_|pg_query|ECONNREFUSED)/i,\n /\\b(syntax error at or near|relation \".*\" does not exist)/i,\n /\\b(column \".*\" (does not exist|of relation))/i,\n /\\b(duplicate key value violates unique constraint)/i,\n /\\b(table .* doesn't exist|unknown column)/i,\n // MongoDB errors\n /\\b(MongoError|MongoServerError|MongoNetworkError|E11000 duplicate key)/i,\n // Redis errors\n /\\b(WRONGTYPE|CROSSSLOT|CLUSTERDOWN|READONLY|ReplyError)/i,\n // Connection strings and DSNs\n /\\b(mongodb(\\+srv)?:\\/\\/|postgres(ql)?:\\/\\/|mysql:\\/\\/|redis:\\/\\/)/i,\n // Stack traces with file paths\n /\\bat\\s+.*\\.(js|ts|py|go|java):\\d+/i,\n // Internal IP addresses\n /\\b(127\\.0\\.0\\.\\d+|10\\.\\d+\\.\\d+\\.\\d+|192\\.168\\.\\d+\\.\\d+|172\\.(1[6-9]|2\\d|3[01])\\.\\d+\\.\\d+)\\b/,\n];\n\n/**\n * Check if an error message contains sensitive infrastructure details.\n */\nexport function containsSensitiveInfo(message: string): boolean {\n return SENSITIVE_ERROR_PATTERNS.some(pattern => pattern.test(message));\n}\n\n/**\n * Create Express error handler that hides sensitive details in production.\n *\n * Prevents information leakage by:\n * - Hiding stack traces in production\n * - Hiding error messages unless explicitly exposed\n * - Scrubbing database errors, connection strings, and internal IPs\n *\n * @param options - Error handler configuration (or boolean for isDev)\n * @returns Express error handling middleware\n *\n * @example\n * // Production mode (default) - hides error details\n * app.use(errorHandler());\n *\n * @example\n * // Development mode - shows error details and stack traces\n * app.use(errorHandler({ isDev: true }));\n *\n * @example\n * // With custom logger\n * app.use(errorHandler({\n * isDev: false,\n * logger: arcis.logger()\n * }));\n */\nexport function errorHandler(\n options: ErrorHandlerOptions | boolean = false\n): (err: Error, req: Request, res: Response, next: NextFunction) => void {\n const isDev = typeof options === 'boolean' ? options : options.isDev ?? false;\n const logErrors = typeof options === 'object' ? options.logErrors ?? true : true;\n const logger = typeof options === 'object' ? options.logger : undefined;\n const customHandler = typeof options === 'object' ? options.customHandler : undefined;\n\n return (err: HttpError, req: Request, res: Response, _next: NextFunction) => {\n // Clamp to a valid HTTP error range. A thrown error with a bogus\n // statusCode (negative, zero, or > 599) would otherwise be sent to\n // the client and break proxies, browsers, or compliance scanners.\n const rawStatus = err.statusCode ?? err.status ?? 500;\n const statusCode =\n Number.isFinite(rawStatus) && rawStatus >= 400 && rawStatus <= 599\n ? Math.floor(rawStatus)\n : 500;\n\n // Custom handler takes precedence\n if (customHandler) {\n return customHandler(err, req, res);\n }\n\n // Always log full error details server-side\n if (logErrors) {\n const logData = {\n error: err.message,\n stack: err.stack,\n statusCode,\n path: req.path,\n method: req.method,\n };\n\n if (logger) {\n logger.error('Request error', logData);\n } else {\n // eslint-disable-next-line no-console\n console.error('[arcis] Request error:', logData);\n }\n }\n\n // Build response\n // Only expose err.message when err.expose === true (caller opted in) or in dev mode.\n // This prevents internal details leaking through arbitrary 4xx errors that happen\n // to contain sensitive info (e.g. \"DB query failed for user admin@corp.com\").\n const exposeMessage = isDev || err.expose === true;\n\n let clientMessage: string;\n if (!exposeMessage) {\n clientMessage = ERRORS.INTERNAL_SERVER_ERROR;\n } else if (containsSensitiveInfo(err.message)) {\n // Even when expose is true, scrub DB errors and infra details\n clientMessage = isDev ? err.message : ERRORS.INTERNAL_SERVER_ERROR;\n } else {\n clientMessage = err.message;\n }\n\n const response: Record<string, unknown> = {\n error: clientMessage,\n };\n\n // Only show details in development\n if (isDev) {\n response.stack = err.stack;\n response.details = err.message;\n }\n\n res.status(statusCode).json(response);\n };\n}\n\n/**\n * Alias for errorHandler\n * @see errorHandler\n */\nexport const createErrorHandler = errorHandler;\n","/**\n * @module @arcis/node/core/errors\n * Custom error classes for Arcis\n */\n\n/**\n * Base class for all Arcis errors\n */\nexport class ArcisError extends Error {\n public readonly statusCode: number;\n public readonly code: string;\n /** Whether the error message is safe to expose to API clients. */\n public readonly expose: boolean;\n\n constructor(message: string, statusCode = 500, code = 'ARCIS_ERROR') {\n super(message);\n this.name = 'ArcisError';\n this.statusCode = statusCode;\n this.code = code;\n // Client errors (4xx) have controlled messages — safe to expose.\n // Server errors (5xx) may contain internal details — hide by default.\n this.expose = statusCode < 500;\n\n // Maintains proper stack trace for where error was thrown (V8 engines)\n if (Error.captureStackTrace) {\n Error.captureStackTrace(this, this.constructor);\n }\n }\n}\n\n/**\n * Error thrown when input validation fails\n */\nexport class ValidationError extends ArcisError {\n public readonly errors: string[];\n\n constructor(errors: string[]) {\n super('Validation failed', 400, 'VALIDATION_ERROR');\n this.name = 'ValidationError';\n this.errors = errors;\n }\n}\n\n/** Alias for ValidationError (backwards compatibility) */\nexport { ValidationError as ArcisValidationError };\n\n/**\n * Error thrown when rate limit is exceeded\n */\nexport class RateLimitError extends ArcisError {\n public readonly retryAfter: number;\n\n constructor(message: string, retryAfter: number) {\n super(message, 429, 'RATE_LIMIT_EXCEEDED');\n this.name = 'RateLimitError';\n this.retryAfter = retryAfter;\n }\n}\n\n/**\n * Error thrown when input is too large\n */\nexport class InputTooLargeError extends ArcisError {\n public readonly maxSize: number;\n public readonly actualSize: number;\n\n constructor(maxSize: number, actualSize: number) {\n super(`Input exceeds maximum size of ${maxSize} bytes`, 413, 'INPUT_TOO_LARGE');\n this.name = 'InputTooLargeError';\n this.maxSize = maxSize;\n this.actualSize = actualSize;\n }\n}\n\n/**\n * Error thrown when security threat is detected\n */\nexport class SecurityThreatError extends ArcisError {\n public readonly threatType: string;\n public readonly pattern: string;\n\n constructor(threatType: string, pattern: string) {\n super('Request blocked for security reasons', 400, 'SECURITY_THREAT');\n this.name = 'SecurityThreatError';\n this.threatType = threatType;\n this.pattern = pattern;\n }\n}\n\n/**\n * Error thrown when sanitization fails\n */\nexport class SanitizationError extends ArcisError {\n constructor(message: string) {\n super(message, 400, 'SANITIZATION_ERROR');\n this.name = 'SanitizationError';\n }\n}\n","/**\n * @module @arcis/node/middleware/telemetry\n * Bridges Arcis middleware decisions to a TelemetryClient.\n * Pattern 3 (two-layer): the client owns transport; this layer owns Express plumbing.\n */\n\nimport type { Request, RequestHandler } from 'express';\nimport type { TelemetryClient } from '../telemetry/client';\nimport type { TelemetryEvent, TelemetryDecision, TelemetrySeverity } from '../telemetry/types';\nimport { SecurityThreatError } from '../core/errors';\n\n/** Marker that inner middleware writes to and the emitter reads from. */\nexport interface ArcisTelemetryMarker {\n vector?: string;\n rule?: string;\n severity?: TelemetrySeverity;\n matchedPattern?: string;\n reason?: string;\n /** Pre-decided decision. If absent, the emitter infers from response status. */\n decision?: TelemetryDecision;\n}\n\ndeclare module 'express-serve-static-core' {\n interface Request {\n /** Per-request marker populated by Arcis middlewares for telemetry attribution. */\n __arcis?: ArcisTelemetryMarker;\n }\n}\n\nconst THREAT_TO_VECTOR: Record<string, string> = {\n xss: 'xss',\n sql_injection: 'sql',\n nosql_injection: 'nosql',\n path_traversal: 'path',\n command_injection: 'command',\n prototype_pollution: 'prototype',\n header_injection: 'header',\n ssti: 'ssti',\n xxe: 'xxe',\n};\n\n/**\n * Express middleware that records a telemetry event for every request.\n * Captures latency from entry, hooks `res.on('finish')`, and infers the\n * final decision from response status + any `req.__arcis` marker.\n */\nexport function createTelemetryEmitter(client: TelemetryClient): RequestHandler {\n return (req, res, next) => {\n const start = performance.now();\n\n res.on('finish', () => {\n try {\n const event = buildEvent(req, res.statusCode, performance.now() - start);\n client.record(event);\n } catch {\n // emit must never break the response — fail-open\n }\n });\n\n next();\n };\n}\n\n/**\n * Wraps the sanitizer middleware so SecurityThreatError → req.__arcis marker.\n * The emitter on `finish` will then have vector/rule/severity attribution.\n */\nexport function tapSanitizerThreats(handler: RequestHandler): RequestHandler {\n return (req, res, next) => {\n handler(req, res, (err?: unknown) => {\n if (err instanceof SecurityThreatError) {\n const vector = THREAT_TO_VECTOR[err.threatType] ?? err.threatType;\n req.__arcis = {\n vector,\n rule: `${vector}/match`,\n severity: 'high',\n matchedPattern: err.pattern,\n reason: err.message,\n decision: 'deny',\n };\n }\n next(err);\n });\n };\n}\n\nfunction buildEvent(req: Request, status: number, latencyMs: number): TelemetryEvent {\n const marker = req.__arcis;\n const decision = marker?.decision ?? inferDecision(status);\n\n // Skip 5xx — those are server errors, not security decisions.\n // Still emit so the dashboard shows traffic, but mark as allow with status >=500.\n return {\n ts: new Date().toISOString(),\n ip: extractIp(req),\n method: (req.method ?? 'GET').toUpperCase(),\n path: req.path ?? req.url ?? '/',\n decision,\n vector: marker?.vector ?? (status === 429 ? 'rate-limit' : undefined),\n rule: marker?.rule ?? (status === 429 ? 'rate-limit/exceeded' : undefined),\n severity: marker?.severity ?? (status === 429 ? 'medium' : undefined),\n userAgent: typeof req.headers?.['user-agent'] === 'string' ? req.headers['user-agent'] : '',\n reason: marker?.reason,\n status,\n matchedPattern: marker?.matchedPattern,\n latencyMs: Math.max(0, latencyMs),\n };\n}\n\nfunction inferDecision(status: number): TelemetryDecision {\n if (status === 429) return 'deny';\n if (status === 400) return 'deny';\n if (status === 403) return 'deny';\n return 'allow';\n}\n\nfunction extractIp(req: Request): string {\n if (typeof req.ip === 'string' && req.ip.length > 0) return req.ip;\n const remote = req.socket?.remoteAddress;\n return typeof remote === 'string' ? remote : '0.0.0.0';\n}\n","/**\n * @module @arcis/node/sanitizers/utils\n * Shared utilities for sanitizers\n */\n\n/**\n * Encodes HTML entities to prevent interpretation as markup.\n * \n * @param str - The string to encode\n * @returns The encoded string\n */\nexport function encodeHtmlEntities(str: string): string {\n return str\n .replace(/&/g, '&')\n .replace(/</g, '<')\n .replace(/>/g, '>')\n .replace(/\"/g, '"')\n .replace(/'/g, ''');\n}\n\n/**\n * Checks if a value is a plain object (not null, array, Date, etc.)\n * \n * @param value - Value to check\n * @returns True if plain object\n */\nexport function isPlainObject(value: unknown): value is Record<string, unknown> {\n if (typeof value !== 'object' || value === null || Array.isArray(value)) {\n return false;\n }\n // Check the actual prototype chain rather than toString, which can be spoofed\n // via Symbol.toStringTag. Accepts both Object.prototype (plain {}) and null\n // prototype objects (Object.create(null)).\n const proto = Object.getPrototypeOf(value as object);\n return proto === Object.prototype || proto === null;\n}\n","/**\n * @module @arcis/node/sanitizers/xss\n * XSS (Cross-Site Scripting) prevention\n */\n\nimport { XSS_PATTERNS, XSS_REMOVE_PATTERNS } from '../core/constants';\nimport { encodeHtmlEntities } from './utils';\nimport type { SanitizeResult, ThreatInfo } from '../core/types';\n\n/**\n * Sanitizes a string to prevent XSS attacks.\n * \n * Strategy:\n * 1. Remove dangerous patterns (script tags, event handlers, etc.)\n * 2. HTML-encode the remaining content\n * \n * @param input - The string to sanitize\n * @param collectThreats - Whether to collect threat information (default: false for performance)\n * @returns Sanitized string or SanitizeResult if collectThreats is true\n * \n * @example\n * sanitizeXss(\"<script>alert('xss')</script>\")\n * // Returns: \"<script>alert('xss')</script>\"\n * \n * @example\n * sanitizeXss(\"<img onerror='alert(1)'>\")\n * // Returns: \"<img>\" (event handler removed)\n */\nexport function sanitizeXss(input: string, collectThreats?: false, htmlEncode?: boolean): string;\nexport function sanitizeXss(input: string, collectThreats: true, htmlEncode?: boolean): SanitizeResult;\nexport function sanitizeXss(input: string, collectThreats = false, htmlEncode = false): string | SanitizeResult {\n if (typeof input !== 'string') {\n return collectThreats \n ? { value: String(input), wasSanitized: false, threats: [] }\n : String(input);\n }\n\n const threats: ThreatInfo[] = [];\n let value = input;\n let wasSanitized = false;\n\n // Remove dangerous patterns FIRST — XSS_REMOVE_PATTERNS is the single\n // source of truth (defined in constants.ts alongside XSS_PATTERNS).\n for (const pattern of XSS_REMOVE_PATTERNS) {\n pattern.lastIndex = 0;\n if (pattern.test(value)) {\n pattern.lastIndex = 0;\n \n if (collectThreats) {\n const matches = value.match(pattern);\n if (matches) {\n for (const match of matches) {\n threats.push({\n type: 'xss',\n pattern: pattern.source,\n original: match,\n });\n }\n }\n }\n \n value = value.replace(pattern, '');\n wasSanitized = true;\n }\n }\n\n // HTML-encode only when explicitly requested (SSR/template context).\n // Do NOT encode by default — this is a REST API middleware; encoding\n // here corrupts JSON data with HTML entities (<, &, etc.) that\n // consumers would receive verbatim.\n if (htmlEncode) {\n const encoded = encodeHtmlEntities(value);\n if (encoded !== value) {\n wasSanitized = true;\n }\n value = encoded;\n }\n\n if (collectThreats) {\n return { value, wasSanitized, threats };\n }\n \n return value;\n}\n\n/**\n * Checks if a string contains potential XSS patterns.\n * Does not sanitize — use sanitizeXss() for that.\n * \n * @param input - The string to check\n * @returns True if XSS patterns detected\n */\nexport function detectXss(input: string): boolean {\n if (typeof input !== 'string') return false;\n \n // Check for event handlers\n if (/\\s+on\\w+\\s*=/i.test(input)) return true;\n \n // Check for dangerous protocols\n if (/javascript\\s*:/i.test(input)) return true;\n if (/vbscript\\s*:/i.test(input)) return true;\n if (/data\\s*:\\s*text\\/html/i.test(input)) return true;\n \n // Check for patterns from constants\n for (const pattern of XSS_PATTERNS) {\n pattern.lastIndex = 0;\n if (pattern.test(input)) {\n return true;\n }\n }\n \n return false;\n}\n","/**\n * @module @arcis/node/sanitizers/sql\n * SQL injection prevention\n */\n\nimport { SQL_PATTERNS } from '../core/constants';\nimport type { SanitizeResult, ThreatInfo } from '../core/types';\n\n/**\n * Sanitizes a string to prevent SQL injection attacks.\n * Replaces dangerous SQL patterns with [BLOCKED].\n * \n * @param input - The string to sanitize\n * @param collectThreats - Whether to collect threat information (default: false for performance)\n * @returns Sanitized string or SanitizeResult if collectThreats is true\n * \n * @example\n * sanitizeSql(\"'; DROP TABLE users; --\")\n * // Returns: \"'; TABLE users \"\n */\nexport function sanitizeSql(input: string, collectThreats?: false): string;\nexport function sanitizeSql(input: string, collectThreats: true): SanitizeResult;\nexport function sanitizeSql(input: string, collectThreats = false): string | SanitizeResult {\n if (typeof input !== 'string') {\n return collectThreats \n ? { value: String(input), wasSanitized: false, threats: [] }\n : String(input);\n }\n\n const threats: ThreatInfo[] = [];\n let value = input;\n let wasSanitized = false;\n\n for (const pattern of SQL_PATTERNS) {\n // Reset regex lastIndex for global patterns\n pattern.lastIndex = 0;\n \n if (pattern.test(value)) {\n pattern.lastIndex = 0; // Reset again for replace\n \n if (collectThreats) {\n const matches = value.match(pattern);\n if (matches) {\n for (const match of matches) {\n threats.push({\n type: 'sql_injection',\n pattern: pattern.source,\n original: match,\n });\n }\n }\n }\n \n // Replace the matched content with a space to avoid concatenating surrounding\n // tokens into new dangerous strings (e.g. \"SELECTname\" after stripping \"SELECT\").\n value = value.replace(pattern, ' ');\n wasSanitized = true;\n }\n }\n\n if (collectThreats) {\n return { value, wasSanitized, threats };\n }\n \n return value;\n}\n\n/**\n * Checks if a string contains potential SQL injection patterns.\n * Does not sanitize — use sanitizeSql() for that.\n * \n * @param input - The string to check\n * @returns True if SQL injection patterns detected\n */\nexport function detectSql(input: string): boolean {\n if (typeof input !== 'string') return false;\n \n for (const pattern of SQL_PATTERNS) {\n pattern.lastIndex = 0;\n if (pattern.test(input)) {\n return true;\n }\n }\n \n return false;\n}\n","/**\n * @module @arcis/node/sanitizers/path\n * Path traversal prevention\n */\n\nimport { PATH_PATTERNS } from '../core/constants';\nimport type { SanitizeResult, ThreatInfo } from '../core/types';\n\n/**\n * Sanitizes a string to prevent path traversal attacks.\n * Removes ../ and ..\\ patterns (including URL-encoded variants).\n * \n * @param input - The string to sanitize\n * @param collectThreats - Whether to collect threat information (default: false for performance)\n * @returns Sanitized string or SanitizeResult if collectThreats is true\n * \n * @example\n * sanitizePath(\"../../etc/passwd\")\n * // Returns: \"etc/passwd\"\n */\nexport function sanitizePath(input: string, collectThreats?: false): string;\nexport function sanitizePath(input: string, collectThreats: true): SanitizeResult;\nexport function sanitizePath(input: string, collectThreats = false): string | SanitizeResult {\n if (typeof input !== 'string') {\n return collectThreats \n ? { value: String(input), wasSanitized: false, threats: [] }\n : String(input);\n }\n\n const threats: ThreatInfo[] = [];\n let value = input;\n let wasSanitized = false;\n\n // SECURITY: Normalize Unicode to NFKC before pattern matching.\n // Fullwidth dot U+FF0E normalizes to '.', preventing ../ bypass of ../ detection.\n value = value.normalize('NFKC');\n\n // Apply patterns repeatedly until the string stops changing.\n // Single-pass stripping is bypassable: \"....//\".replace(\"../\",\"\") → \"../\"\n let prev: string;\n do {\n prev = value;\n for (const pattern of PATH_PATTERNS) {\n pattern.lastIndex = 0;\n\n if (pattern.test(value)) {\n pattern.lastIndex = 0;\n\n if (collectThreats) {\n const matches = value.match(pattern);\n if (matches) {\n for (const match of matches) {\n threats.push({\n type: 'path_traversal',\n pattern: pattern.source,\n original: match,\n });\n }\n }\n }\n\n value = value.replace(pattern, '');\n wasSanitized = true;\n }\n }\n } while (value !== prev);\n\n if (collectThreats) {\n return { value, wasSanitized, threats };\n }\n \n return value;\n}\n\n/**\n * Checks if a string contains path traversal patterns.\n * Does not sanitize — use sanitizePath() for that.\n * \n * @param input - The string to check\n * @returns True if path traversal patterns detected\n */\nexport function detectPathTraversal(input: string): boolean {\n if (typeof input !== 'string') return false;\n\n // SECURITY: Normalize Unicode to NFKC — same as sanitizePath\n const normalized = input.normalize('NFKC');\n\n for (const pattern of PATH_PATTERNS) {\n pattern.lastIndex = 0;\n if (pattern.test(normalized)) {\n return true;\n }\n }\n \n return false;\n}\n","/**\n * @module @arcis/node/sanitizers/command\n * Command injection prevention\n */\n\nimport { COMMAND_PATTERNS } from '../core/constants';\nimport type { SanitizeResult, ThreatInfo } from '../core/types';\n\n/**\n * Sanitizes a string to prevent command injection attacks.\n * Replaces shell metacharacters and dangerous commands with [BLOCKED].\n * \n * @param input - The string to sanitize\n * @param collectThreats - Whether to collect threat information (default: false for performance)\n * @returns Sanitized string or SanitizeResult if collectThreats is true\n * \n * @example\n * sanitizeCommand(\"file.txt; rm -rf /\")\n * // Returns: \"file.txt rm -rf /\"\n */\nexport function sanitizeCommand(input: string, collectThreats?: false): string;\nexport function sanitizeCommand(input: string, collectThreats: true): SanitizeResult;\nexport function sanitizeCommand(input: string, collectThreats = false): string | SanitizeResult {\n if (typeof input !== 'string') {\n return collectThreats \n ? { value: String(input), wasSanitized: false, threats: [] }\n : String(input);\n }\n\n const threats: ThreatInfo[] = [];\n let value = input;\n let wasSanitized = false;\n\n for (const pattern of COMMAND_PATTERNS) {\n // Reset regex lastIndex for global patterns\n pattern.lastIndex = 0;\n \n if (pattern.test(value)) {\n pattern.lastIndex = 0; // Reset again for replace\n \n if (collectThreats) {\n const matches = value.match(pattern);\n if (matches) {\n for (const match of matches) {\n threats.push({\n type: 'command_injection',\n pattern: pattern.source,\n original: match,\n });\n }\n }\n }\n \n value = value.replace(pattern, ' ');\n wasSanitized = true;\n }\n }\n\n if (collectThreats) {\n return { value, wasSanitized, threats };\n }\n \n return value;\n}\n\n/**\n * Checks if a string contains command injection patterns.\n * Does not sanitize — use sanitizeCommand() for that.\n * \n * @param input - The string to check\n * @returns True if command injection patterns detected\n */\nexport function detectCommandInjection(input: string): boolean {\n if (typeof input !== 'string') return false;\n \n for (const pattern of COMMAND_PATTERNS) {\n pattern.lastIndex = 0;\n if (pattern.test(input)) {\n return true;\n }\n }\n \n return false;\n}\n","/**\n * @module @arcis/node/sanitizers/ssti\n * Server-Side Template Injection (SSTI) prevention\n */\n\nimport type { SanitizeResult, ThreatInfo } from '../core/types';\n\n/**\n * SSTI detection patterns (ReDoS-safe).\n *\n * Covers Jinja2, Twig, Nunjucks, Freemarker, Thymeleaf, Spring EL,\n * ERB, EJS, Pug/Jade, and Python sandbox-escape dunder chains.\n */\nconst SSTI_DETECT_PATTERNS = [\n /** Jinja2 / Twig / Nunjucks: {{ ... }} */\n /\\{\\{.*?\\}\\}/g,\n /** Freemarker / Thymeleaf / Spring EL: ${ ... } */\n /\\$\\{.*?\\}/g,\n /** ERB / EJS: <%= ... %> or <% ... %> */\n /<%[=\\-]?.*?%>/gs,\n /** Pug / Jade / Slim: #{ ... } */\n /#\\{.*?\\}/g,\n /** Python dunder sandbox escape */\n /__(?:class|mro|subclasses|globals|builtins|import)__/gi,\n /** Jinja2 config leak: {{config.X}} or {{config['X']}} */\n /\\{\\{\\s*config[.\\[]/gi,\n /** Jinja2 built-in objects */\n /\\{\\{\\s*(?:self|request|lipsum|cycler|joiner|namespace|range)\\b/gi,\n] as const;\n\n/**\n * Removal patterns — strip template expressions that look like actual attacks.\n *\n * ${ and #{ patterns are narrowed to require operators/method-calls inside to\n * avoid false-positives on JS template literals (${name}) and Ruby/Pug output\n * expressions (#{name}) that appear in legitimate user-submitted content.\n *\n * The broader detection patterns above still flag these for detectSsti() —\n * narrowing only applies to destructive sanitization.\n */\nconst SSTI_REMOVE_PATTERNS = [\n /** Jinja2 / Twig: {{ ... }} — always strip (not valid in any JS context) */\n /\\{\\{.*?\\}\\}/g,\n /**\n * Freemarker / Spring EL: ${...} — strip when expression contains operators,\n * method calls, or Python dunder patterns (sandbox escape).\n * Bare ${name} and ${user.name} are left intact (JS template literal syntax).\n */\n /\\$\\{[^}]*__\\w+__[^}]*\\}/g,\n /\\$\\{[^}]*[?!()*+\\-/][^}]*\\}/g,\n /** ERB / EJS: <%= ... %> */\n /<%[=\\-]?.*?%>/gs,\n /**\n * Pug / Jade: #{...} — same narrowing as ${ above, plus dunder detection.\n * #{name} output expressions are left intact.\n */\n /#\\{[^}]*__\\w+__[^}]*\\}/g,\n /#\\{[^}]*[?!()*+\\-/][^}]*\\}/g,\n /** Python dunder sandbox escape — always strip */\n /__(?:class|mro|subclasses|globals|builtins|import)__/gi,\n] as const;\n\n/**\n * Sanitizes a string to prevent SSTI attacks.\n * Removes template expression syntax.\n */\nexport function sanitizeSsti(input: string, collectThreats?: false): string;\nexport function sanitizeSsti(input: string, collectThreats: true): SanitizeResult;\nexport function sanitizeSsti(input: string, collectThreats = false): string | SanitizeResult {\n if (typeof input !== 'string') {\n return collectThreats\n ? { value: String(input), wasSanitized: false, threats: [] }\n : String(input);\n }\n\n const threats: ThreatInfo[] = [];\n let value = input;\n let wasSanitized = false;\n\n for (const pattern of SSTI_REMOVE_PATTERNS) {\n pattern.lastIndex = 0;\n if (pattern.test(value)) {\n pattern.lastIndex = 0;\n\n if (collectThreats) {\n const matches = value.match(pattern);\n if (matches) {\n for (const match of matches) {\n threats.push({\n type: 'ssti',\n pattern: pattern.source,\n original: match,\n });\n }\n }\n }\n\n value = value.replace(pattern, '');\n wasSanitized = true;\n }\n }\n\n if (collectThreats) {\n return { value, wasSanitized, threats };\n }\n\n return value;\n}\n\n/**\n * Checks if a string contains SSTI patterns.\n * Does not sanitize — use sanitizeSsti() for that.\n *\n * @param input - The string to check\n * @returns True if SSTI patterns detected\n */\nexport function detectSsti(input: string): boolean {\n if (typeof input !== 'string') return false;\n\n for (const pattern of SSTI_DETECT_PATTERNS) {\n pattern.lastIndex = 0;\n if (pattern.test(input)) {\n return true;\n }\n }\n\n return false;\n}\n","/**\n * @module @arcis/node/sanitizers/xxe\n * XML External Entity (XXE) injection prevention\n */\n\nimport type { SanitizeResult, ThreatInfo } from '../core/types';\n\n/**\n * XXE detection patterns (ReDoS-safe).\n *\n * Covers DOCTYPE declarations, ENTITY definitions, SYSTEM/PUBLIC references,\n * parameter entities, and CDATA abuse.\n */\n/**\n * Billion-laughs defense: cap raw XML input length and the count of\n * entity references. A valid document rarely needs more than a handful of\n * entities; thousands of `&foo;` references is the classic bomb shape.\n */\nconst MAX_XXE_INPUT_BYTES = 1_000_000; // 1 MB — above any reasonable config/SOAP payload\nconst MAX_ENTITY_REFERENCES = 64;\n\nconst XXE_DETECT_PATTERNS = [\n /** DOCTYPE declaration */\n /<!DOCTYPE\\b/gi,\n /** ENTITY declaration */\n /<!ENTITY\\b/gi,\n /** SYSTEM keyword with URI */\n /\\bSYSTEM\\s+[\"']/gi,\n /** PUBLIC keyword with URI */\n /\\bPUBLIC\\s+[\"']/gi,\n /** Parameter entity reference (%entity;) */\n /%\\s*\\w+\\s*;/g,\n /** CDATA section (often used to smuggle payloads) */\n /<!\\[CDATA\\[/gi,\n] as const;\n\n/** Removal patterns — strip the dangerous XML constructs */\nconst XXE_REMOVE_PATTERNS = [\n /** Full DOCTYPE block with optional internal subset: <!DOCTYPE ... [...]> */\n /<!DOCTYPE\\s[^[>]*(?:\\[[^\\]]*\\]\\s*)?>|<!DOCTYPE\\s[^>]*>/gi,\n /** Full ENTITY declaration: <!ENTITY ... > */\n /<!ENTITY[^>]*>/gi,\n /** CDATA sections: <![CDATA[ ... ]]> */\n /<!\\[CDATA\\[[\\s\\S]*?\\]\\]>/gi,\n] as const;\n\n/**\n * Sanitizes a string to prevent XXE attacks.\n * Removes DOCTYPE, ENTITY, and CDATA constructs.\n */\nexport function sanitizeXxe(input: string, collectThreats?: false): string;\nexport function sanitizeXxe(input: string, collectThreats: true): SanitizeResult;\nexport function sanitizeXxe(input: string, collectThreats = false): string | SanitizeResult {\n if (typeof input !== 'string') {\n return collectThreats\n ? { value: String(input), wasSanitized: false, threats: [] }\n : String(input);\n }\n\n const threats: ThreatInfo[] = [];\n let value = input;\n let wasSanitized = false;\n\n // Billion-laughs defense: oversize input or many entity refs → flatten to empty.\n // Safer to discard than to attempt partial sanitization of a bomb payload.\n if (value.length > MAX_XXE_INPUT_BYTES) {\n if (collectThreats) {\n threats.push({ type: 'xxe', pattern: 'oversize_input', original: `length=${value.length}` });\n }\n return collectThreats ? { value: '', wasSanitized: true, threats } : '';\n }\n const entityRefs = value.match(/&\\w+;/g);\n if (entityRefs && entityRefs.length > MAX_ENTITY_REFERENCES) {\n if (collectThreats) {\n threats.push({ type: 'xxe', pattern: 'entity_expansion', original: `count=${entityRefs.length}` });\n }\n return collectThreats ? { value: '', wasSanitized: true, threats } : '';\n }\n\n for (const pattern of XXE_REMOVE_PATTERNS) {\n pattern.lastIndex = 0;\n if (pattern.test(value)) {\n pattern.lastIndex = 0;\n\n if (collectThreats) {\n const matches = value.match(pattern);\n if (matches) {\n for (const match of matches) {\n threats.push({\n type: 'xxe',\n pattern: pattern.source,\n original: match,\n });\n }\n }\n }\n\n value = value.replace(pattern, '');\n wasSanitized = true;\n }\n }\n\n if (collectThreats) {\n return { value, wasSanitized, threats };\n }\n\n return value;\n}\n\n/**\n * Checks if a string contains XXE patterns.\n * Does not sanitize — use sanitizeXxe() for that.\n *\n * @param input - The string to check\n * @returns True if XXE patterns detected\n */\nexport function detectXxe(input: string): boolean {\n if (typeof input !== 'string') return false;\n\n for (const pattern of XXE_DETECT_PATTERNS) {\n pattern.lastIndex = 0;\n if (pattern.test(input)) {\n return true;\n }\n }\n\n return false;\n}\n","/**\n * @module @arcis/node/sanitizers/ldap\n * LDAP injection prevention\n *\n * LDAP special characters in filter context: * ( ) \\ NUL\n * LDAP special characters in DN context: , + < > ; \" = / \\ NUL\n *\n * RFC 4515 (filter) and RFC 4514 (DN) define the escaping rules.\n * Sanitization escapes rather than strips — preserves the original value\n * while making it safe to embed in LDAP queries.\n */\n\n// LDAP filter special characters per RFC 4515 (single pass includes NUL)\nconst LDAP_FILTER_CHARS = /[*()\\\\\\x00]/g;\n\n// LDAP DN special characters per RFC 4514 (single pass includes NUL)\nconst LDAP_DN_CHARS = /[,+<>;\"=\\/\\\\\\x00*()\\x00]/g;\n\n// Detection pattern — unescaped LDAP special chars in filter context\nconst LDAP_DETECT_PATTERN = /[*()\\\\\\x00]/;\n\n// Detection pattern for OR/AND bypass and wildcard abuse\nconst LDAP_INJECTION_PATTERN = /\\)\\s*\\(|\\*\\s*\\)\\s*\\(/;\n\n// Detection pattern for LDAP NOT-operator bypass (improvements.md Q8).\n// Catches ')(!', '&(!', '|(!' shapes that legitimate filters never contain;\n// these are the attacker's NOT-clause appended to enumerate or exclude\n// entries (e.g. '*)(uid=*)(!(uid=admin))'). Companion to\n// LDAP_INJECTION_PATTERN; together they cover the OR-then-NOT corpus.\nconst LDAP_NOT_BYPASS_PATTERN = /\\)\\s*\\(\\s*!|&\\s*\\(\\s*!|\\|\\s*\\(\\s*!/;\n\nconst escapeChar = (char: string) => '\\\\' + char.charCodeAt(0).toString(16).padStart(2, '0');\n\n/**\n * Sanitizes a string for safe use in LDAP filter expressions.\n * Escapes * ( ) \\ and NUL per RFC 4515.\n *\n * @example\n * sanitizeLdapFilter(\"user*(admin)\")\n * // Returns: \"user\\2a\\28admin\\29\"\n */\nexport function sanitizeLdapFilter(input: string): string {\n if (typeof input !== 'string') return String(input);\n return input.replace(LDAP_FILTER_CHARS, escapeChar);\n}\n\n/**\n * Sanitizes a string for safe use in LDAP Distinguished Names (DN).\n * Escapes , + < > ; \" = / \\ and NUL per RFC 4514.\n *\n * @example\n * sanitizeLdapDn(\"cn=admin,dc=example\")\n * // Returns: \"cn\\3dadmin\\2cdc\\3dexample\"\n */\nexport function sanitizeLdapDn(input: string): string {\n if (typeof input !== 'string') return String(input);\n return input.replace(LDAP_DN_CHARS, escapeChar);\n}\n\n/**\n * Detects potential LDAP injection patterns in a string.\n * Does not sanitize — use sanitizeLdapFilter() or sanitizeLdapDn() for that.\n *\n * @param input - The string to check\n * @returns True if LDAP injection patterns detected\n *\n * @example\n * detectLdapInjection(\"*)(uid=*))(|(uid=*\") // true\n * detectLdapInjection(\"john\") // false\n */\nexport function detectLdapInjection(input: string): boolean {\n if (typeof input !== 'string') return false;\n return (\n LDAP_DETECT_PATTERN.test(input) ||\n LDAP_INJECTION_PATTERN.test(input) ||\n LDAP_NOT_BYPASS_PATTERN.test(input)\n );\n}\n","/**\n * @module @arcis/node/sanitizers/xpath\n * XPath injection prevention.\n *\n * XPath 1.0 has no escape syntax for string literals — the only way to\n * embed user input safely is parameterised queries / variable bindings.\n * Neither libxml2 nor most JS XPath libraries expose a canonical escape\n * function. The pragmatic answer everyone ships:\n *\n * - Detect: scan for unescaped quotes or expression-control chars\n * that suggest the user is trying to break out of a string literal.\n * - Sanitize: strip the offending control characters. Lossy by design;\n * callers that need lossless input should use parameterised queries\n * directly.\n *\n * Detection is the load-bearing surface for this vector. Sanitization is\n * a fallback for users running existing XPath strings through user input\n * who can't switch to bound parameters today.\n */\n\n// XPath expression-control characters that an attacker uses to escape\n// a string literal: single quote, double quote, comma (changes function\n// arity), the union operator |, and parens (used in `) or (` toggles\n// against XPath function calls). These are the same shapes Aikido /\n// Snyk's xpath rules look for.\nconst XPATH_INJECTION_CHARS = /['\"|,()]/;\n\n// Common operator-injection patterns: unescaped boolean injection\n// (`' or '1'='1`), function tampering (`,`), and union (`|`).\nconst XPATH_INJECTION_PATTERN =\n /('\\s*(or|and)\\s*'|\"\\s*(or|and)\\s*\"|\\)\\s*(or|and)\\s*\\(|\\|\\s*\\/)/i;\n\n/**\n * Detects XPath-injection-shaped patterns in a string. Returns true when\n * the input looks like it's trying to break out of an XPath string\n * literal or hijack the expression structure.\n *\n * Conservative on purpose: triggers on any control char in the input\n * combined with a boolean / union pattern. Plain user names and emails\n * (no quotes, no pipes) pass clean.\n */\nexport function detectXpathInjection(input: string): boolean {\n if (typeof input !== 'string' || input.length === 0) return false;\n // Fast path: skip the regex test entirely when no control chars exist.\n if (!XPATH_INJECTION_CHARS.test(input)) return false;\n return XPATH_INJECTION_PATTERN.test(input);\n}\n\n/**\n * Strips XPath expression-control characters from a string. Lossy —\n * `O'Brien` becomes `OBrien`. Use only when migrating legacy code that\n * concatenates user input into XPath; new code should use bound\n * parameters via the underlying XPath library.\n */\nexport function sanitizeXpath(input: string): string {\n if (typeof input !== 'string') return String(input);\n return input.replace(/['\"|,]/g, '');\n}\n","/**\n * @module @arcis/node/sanitizers/headers\n * HTTP Header Injection & CRLF Injection prevention\n *\n * Prevents attackers from injecting newline characters (\\r\\n) into HTTP header\n * values, which can lead to response splitting, session fixation, XSS via\n * injected headers, and cache poisoning.\n */\n\nimport type { SanitizeResult, ThreatInfo } from '../core/types';\n\n/**\n * Characters and sequences that enable header injection.\n * - \\r\\n (CRLF) — HTTP header delimiter, enables response splitting\n * - \\r, \\n alone — partial line breaks, some servers normalize to CRLF\n * - \\0 (null byte) — can truncate header values in some implementations\n */\nconst HEADER_INJECTION_PATTERN = /\\r\\n|\\r|\\n|\\0/g;\n\n/**\n * Sanitizes a header value by stripping CRLF sequences, bare CR/LF, and null bytes.\n *\n * @param input - The header value to sanitize\n * @param collectThreats - Whether to collect threat information (default: false)\n * @returns Sanitized string or SanitizeResult if collectThreats is true\n *\n * @example\n * sanitizeHeaderValue(\"safe-value\")\n * // Returns: \"safe-value\"\n *\n * sanitizeHeaderValue(\"value\\r\\nX-Injected: evil\")\n * // Returns: \"valueX-Injected: evil\"\n */\nexport function sanitizeHeaderValue(input: string, collectThreats?: false): string;\nexport function sanitizeHeaderValue(input: string, collectThreats: true): SanitizeResult;\nexport function sanitizeHeaderValue(input: string, collectThreats = false): string | SanitizeResult {\n if (typeof input !== 'string') {\n return collectThreats\n ? { value: String(input), wasSanitized: false, threats: [] }\n : String(input);\n }\n\n const threats: ThreatInfo[] = [];\n let wasSanitized = false;\n\n if (HEADER_INJECTION_PATTERN.test(input)) {\n HEADER_INJECTION_PATTERN.lastIndex = 0;\n wasSanitized = true;\n\n if (collectThreats) {\n const matches = input.match(HEADER_INJECTION_PATTERN);\n if (matches) {\n for (const match of matches) {\n threats.push({\n type: 'header_injection',\n pattern: HEADER_INJECTION_PATTERN.source,\n original: match,\n });\n }\n }\n }\n }\n\n HEADER_INJECTION_PATTERN.lastIndex = 0;\n const value = input.replace(HEADER_INJECTION_PATTERN, '');\n\n if (collectThreats) {\n return { value, wasSanitized, threats };\n }\n\n return value;\n}\n\n/**\n * Sanitizes an object of header key-value pairs.\n * Strips CRLF/null bytes from both keys and values.\n *\n * @param headers - Object with header names as keys and header values as values\n * @returns New object with sanitized header names and values\n *\n * @example\n * sanitizeHeaders({ \"X-Custom\": \"safe\", \"X-Bad\\r\\n\": \"value\\r\\ninjected\" })\n * // Returns: { \"X-Custom\": \"safe\", \"X-Bad\": \"valueinjected\" }\n */\nexport function sanitizeHeaders(headers: Record<string, string>): Record<string, string> {\n if (!headers || typeof headers !== 'object') {\n return {};\n }\n\n const result: Record<string, string> = {};\n\n for (const [key, value] of Object.entries(headers)) {\n const sanitizedKey = sanitizeHeaderValue(String(key));\n const sanitizedValue = sanitizeHeaderValue(String(value));\n result[sanitizedKey] = sanitizedValue;\n }\n\n return result;\n}\n\n/**\n * Checks if a string contains HTTP header injection patterns (CRLF, null bytes).\n * Does not sanitize — use sanitizeHeaderValue() for that.\n *\n * @param input - The string to check\n * @returns True if header injection patterns detected\n */\nexport function detectHeaderInjection(input: string): boolean {\n if (typeof input !== 'string') return false;\n\n HEADER_INJECTION_PATTERN.lastIndex = 0;\n return HEADER_INJECTION_PATTERN.test(input);\n}\n\n/**\n * Email-header injection prevention. Same byte-level threat as HTTP\n * header injection — `\\r\\n` in a user-controlled email field\n * (`To`, `From`, `Subject`, etc.) lets an attacker inject extra headers\n * (most commonly Bcc) and pivot a contact form into a spam relay.\n *\n * Aliased to the HTTP-header sanitizers because the wire-level fix is\n * identical: strip CRLF + null bytes from the value before\n * concatenating into the header. Use these in form-to-email handlers:\n *\n * ```ts\n * const subject = sanitizeEmailHeader(req.body.subject);\n * const to = sanitizeEmailHeader(req.body.to);\n * if (detectEmailHeaderInjection(req.body.to)) reject(...);\n * ```\n */\nexport const sanitizeEmailHeader = sanitizeHeaderValue;\nexport const detectEmailHeaderInjection = detectHeaderInjection;\n","/**\n * @module @arcis/node/sanitizers/sanitize\n * Main sanitization functions that combine all sanitizers\n */\n\nimport type { Request, Response, NextFunction, RequestHandler } from 'express';\nimport { INPUT, DANGEROUS_PROTO_KEYS, NOSQL_DANGEROUS_KEYS } from '../core/constants';\nimport { InputTooLargeError, SecurityThreatError } from '../core/errors';\nimport type { SanitizeOptions } from '../core/types';\nimport { sanitizeXss, detectXss } from './xss';\nimport { sanitizeSql, detectSql } from './sql';\nimport { sanitizePath, detectPathTraversal } from './path';\nimport { sanitizeCommand, detectCommandInjection } from './command';\nimport { detectSsti } from './ssti';\nimport { detectXxe } from './xxe';\nimport { detectLdapInjection } from './ldap';\nimport { detectXpathInjection } from './xpath';\nimport { detectHeaderInjection } from './headers';\n\n/**\n * Sanitize a string value against multiple attack vectors.\n * \n * Order matters: We do XSS encoding LAST because:\n * 1. Other sanitizers need to see the original patterns (e.g., SQL keywords)\n * 2. HTML encoding is the final safe output transformation\n * 3. Encoded entities like < shouldn't be treated as SQL/command threats\n * \n * @param value - The string to sanitize\n * @param options - Sanitization options\n * @returns The sanitized string\n * \n * @example\n * sanitizeString(\"<script>alert('xss')</script>\")\n * // Returns: \"<script>alert('xss')</script>\"\n * \n * @example\n * sanitizeString(\"../../etc/passwd\")\n * // Returns: \"etc/passwd\"\n */\n/**\n * Decode URL + HTML entity layers until the string is stable.\n *\n * improvements.md §1.1.b — closes the encoding-stack bypass class.\n * A payload like `%2526%2523x3c%253bscript%2526%2523x3e%253b` is a\n * triple-encoded `<script>`: pass 1 URL-decodes to\n * `%26%23x3c%3bscript%26%23x3e%3b`, pass 2 URL-decodes to\n * `<script>`, pass 3 HTML-decodes to `<script>`. Without\n * this helper the literal ASCII `<script>` never appears in the\n * string, so the XSS regex never fires.\n *\n * Bounded at 4 passes to prevent pathological-input loops. Base64\n * decoding is intentionally NOT in the chain — false-positive rate\n * on arbitrary text would be high.\n */\nfunction multiDecode(value: string, maxPasses = 4): string {\n for (let i = 0; i < maxPasses; i++) {\n const prev = value;\n\n // URL-decode. decodeURIComponent throws on malformed sequences\n // (lone `%` with no hex pair); treat that as \"no further\n // URL-decoding possible\" and continue with the current value.\n try {\n value = decodeURIComponent(value);\n } catch {\n // leave value as-is\n }\n\n // HTML entity decode. No built-in in Node, so inline the common\n // entities here. Numeric (`&#NN;`, `&#xHH;`) covers the bulk of\n // XSS-encoding tricks; the five named entities below cover the\n // rest of the encoding-bypass test corpus.\n value = htmlEntityDecode(value);\n\n if (value === prev) break;\n }\n return value;\n}\n\n/** Decode HTML entities — numeric (decimal + hex) plus the five core\n * named entities that XSS payloads use. Keeps the dep-free zero-dep\n * footprint of `@arcis/node`. */\nfunction htmlEntityDecode(s: string): string {\n // &#NN; decimal numeric\n s = s.replace(/&#(\\d+);/g, (_m, n) => {\n const code = parseInt(n, 10);\n return Number.isFinite(code) && code >= 0 && code <= 0x10ffff\n ? String.fromCodePoint(code)\n : _m;\n });\n // &#xHH; or &#XHH; hex numeric\n s = s.replace(/&#x([0-9a-fA-F]+);/g, (_m, h) => {\n const code = parseInt(h, 16);\n return Number.isFinite(code) && code >= 0 && code <= 0x10ffff\n ? String.fromCodePoint(code)\n : _m;\n });\n // The five named entities that matter for XSS detection.\n const named: Record<string, string> = {\n '<': '<',\n '>': '>',\n '&': '&',\n '"': '\"',\n ''': \"'\",\n ' ': ' ',\n };\n for (const [entity, ch] of Object.entries(named)) {\n s = s.split(entity).join(ch);\n }\n return s;\n}\n\nexport function sanitizeString(value: string, options: SanitizeOptions = {}): string {\n if (typeof value !== 'string') return value;\n\n // Input size limit to prevent DoS\n const maxSize = options.maxSize ?? INPUT.DEFAULT_MAX_SIZE;\n if (value.length > maxSize) {\n throw new InputTooLargeError(maxSize, value.length);\n }\n\n // Default mode is 'sanitize' (strip threats and return cleaned string).\n // Pass mode: 'reject' to throw SecurityThreatError instead of stripping.\n const reject = options.mode === 'reject';\n\n // SECURITY: Normalize Unicode to NFKC BEFORE every detector runs.\n // Fullwidth glyphs (`<script>`, `1+1=2`) collapse to their ASCII\n // equivalents, closing the entire fullwidth-bypass class for XSS,\n // SQL, command-injection, and path-traversal in a single pass.\n // improvements.md §1.1.a. Bypass example closed:\n // `<script>alert(1)</script>` → `<script>alert(1)</script>`\n let result = value.normalize('NFKC');\n\n // SECURITY: Multi-pass URL + HTML decode (improvements.md §1.1.b).\n // Closes the encoding-stack bypass class. After NFKC,\n // `%2526%2523x3c%253bscript%2526%2523x3e%253b` (triple-encoded\n // `<script>`) decodes all the way to `<script>` and hits the\n // normal XSS strip below. Bounded at 4 passes.\n result = multiDecode(result);\n\n // 1. SQL injection\n if (options.sql !== false) {\n if (reject) {\n if (detectSql(result)) {\n throw new SecurityThreatError('sql_injection', 'SQL pattern detected in input');\n }\n } else {\n result = sanitizeSql(result);\n }\n }\n\n // 2. Path traversal prevention\n if (options.path !== false) {\n result = sanitizePath(result);\n }\n\n // 3. Command injection\n if (options.command !== false) {\n if (reject) {\n if (detectCommandInjection(result)) {\n throw new SecurityThreatError('command_injection', 'Shell metacharacter detected in input');\n }\n } else {\n result = sanitizeCommand(result);\n }\n }\n\n // 4. XSS stripping — always runs to remove dangerous patterns.\n // HTML encoding is opt-in via options.htmlEncode (for SSR contexts only).\n if (options.xss !== false) {\n result = sanitizeXss(result, false, options.htmlEncode ?? false);\n }\n\n return result;\n}\n\n/**\n * Sanitize an object recursively, including nested objects and arrays.\n * Also removes prototype pollution and NoSQL injection keys.\n * \n * @param obj - The object to sanitize\n * @param options - Sanitization options\n * @returns The sanitized object\n */\nexport function sanitizeObject(obj: unknown, options: SanitizeOptions = {}): unknown {\n if (obj === null || obj === undefined) return obj;\n if (typeof obj === 'string') return sanitizeString(obj, options);\n if (typeof obj !== 'object') return obj;\n if (Array.isArray(obj)) return obj.map(item => sanitizeObject(item, options));\n\n const result = sanitizeObjectDepth(obj as Record<string, unknown>, options, 0);\n return options.freeze ? Object.freeze(result) : result;\n}\n\n/**\n * Internal recursive sanitization with depth tracking.\n */\nfunction sanitizeObjectDepth(\n obj: Record<string, unknown>,\n options: SanitizeOptions,\n depth: number\n): Record<string, unknown> {\n if (depth >= INPUT.MAX_RECURSION_DEPTH) return obj;\n\n const result: Record<string, unknown> = {};\n\n for (const key of Object.keys(obj)) {\n // Prototype pollution protection - always block dangerous keys (case-insensitive)\n if (options.proto !== false && DANGEROUS_PROTO_KEYS.has(key.toLowerCase())) {\n continue;\n }\n\n // NoSQL injection - skip dangerous MongoDB operators in keys\n if (options.nosql !== false && NOSQL_DANGEROUS_KEYS.has(key)) {\n continue;\n }\n\n // Sanitize the key against all active threat vectors (not just XSS).\n // Keys can carry injection payloads that bubble into query builders or ORMs.\n const sanitizedKey = sanitizeString(key, options);\n\n // Recursively sanitize value\n const value = obj[key];\n if (value === null || value === undefined) {\n result[sanitizedKey] = value;\n } else if (typeof value === 'string') {\n result[sanitizedKey] = sanitizeString(value, options);\n } else if (Array.isArray(value)) {\n result[sanitizedKey] = value.map(item => sanitizeObject(item, options));\n } else if (typeof value === 'object') {\n result[sanitizedKey] = sanitizeObjectDepth(value as Record<string, unknown>, options, depth + 1);\n } else {\n result[sanitizedKey] = value;\n }\n }\n\n return result;\n}\n\n/** Threat triple returned from scanThreats. */\nexport interface ThreatHit {\n vector:\n | 'xss'\n | 'sql'\n | 'nosql'\n | 'path'\n | 'command'\n | 'prototype'\n | 'ssti'\n | 'xxe'\n | 'ldap'\n | 'xpath'\n | 'header';\n rule: string;\n matchedPattern: string;\n}\n\n/**\n * Walk a value (string, array, or object) and return the first threat hit\n * found. Used by block-mode middleware to attribute the deny decision.\n *\n * Vector ordering matches Python's scan_threats for cross-SDK parity.\n */\nexport function scanThreats(data: unknown, depth = 0): ThreatHit | null {\n if (depth > INPUT.MAX_RECURSION_DEPTH) return null;\n\n if (data && typeof data === 'object' && !Array.isArray(data)) {\n for (const key of Object.keys(data as Record<string, unknown>)) {\n const lower = key.toLowerCase();\n if (DANGEROUS_PROTO_KEYS.has(lower)) {\n return { vector: 'prototype', rule: 'prototype/match', matchedPattern: key };\n }\n if (NOSQL_DANGEROUS_KEYS.has(key)) {\n return { vector: 'nosql', rule: 'nosql/match', matchedPattern: key };\n }\n const inner = scanThreats((data as Record<string, unknown>)[key], depth + 1);\n if (inner) return inner;\n }\n return null;\n }\n\n if (Array.isArray(data)) {\n for (const item of data) {\n const inner = scanThreats(item, depth + 1);\n if (inner) return inner;\n }\n return null;\n }\n\n if (typeof data !== 'string') return null;\n\n const sample = data.slice(0, 80);\n if (detectXss(data)) {\n return { vector: 'xss', rule: 'xss/match', matchedPattern: sample };\n }\n if (detectSsti(data)) {\n return { vector: 'ssti', rule: 'ssti/match', matchedPattern: sample };\n }\n if (detectXxe(data)) {\n return { vector: 'xxe', rule: 'xxe/match', matchedPattern: sample };\n }\n if (detectSql(data)) {\n return { vector: 'sql', rule: 'sql/match', matchedPattern: sample };\n }\n if (detectPathTraversal(data)) {\n return { vector: 'path', rule: 'path/match', matchedPattern: sample };\n }\n if (detectCommandInjection(data)) {\n return { vector: 'command', rule: 'command/match', matchedPattern: sample };\n }\n // LDAP + XPath checks come AFTER command/path so a string that's\n // primarily a path-traversal payload (`../`) gets attributed to\n // path, not LDAP (the `\\` in `..\\..\\` would otherwise hit the LDAP\n // backslash filter).\n if (detectLdapInjection(data)) {\n return { vector: 'ldap', rule: 'ldap/match', matchedPattern: sample };\n }\n if (detectXpathInjection(data)) {\n return { vector: 'xpath', rule: 'xpath/match', matchedPattern: sample };\n }\n // Header injection (HTTP response splitting + email-header injection\n // share the same byte-level threat: CRLF in a value that gets\n // concatenated into a header). Last in the chain so the more-specific\n // detectors (xss / sql / etc.) win on input that's both — e.g. an XSS\n // payload with a stray newline still attributes to xss.\n if (detectHeaderInjection(data)) {\n return { vector: 'header', rule: 'header/match', matchedPattern: sample };\n }\n return null;\n}\n\n/**\n * Create Express middleware for request sanitization.\n * Sanitizes req.body, req.query, and req.params.\n * \n * @param options - Sanitization options\n * @returns Express middleware\n * \n * @example\n * app.use(createSanitizer());\n * \n * @example\n * app.use(createSanitizer({ xss: true, sql: true, nosql: true }));\n */\nexport function createSanitizer(options: SanitizeOptions = {}): RequestHandler {\n return (req: Request, res: Response, next: NextFunction) => {\n try {\n // Block mode: scan first, return 403 on threat. The telemetry emitter\n // reads the marker on res.finish to attribute the deny decision.\n if (options.block) {\n const hit =\n scanThreats(req.body) ||\n scanThreats(req.query) ||\n scanThreats(req.params) ||\n scanThreats(req.path);\n if (hit) {\n req.__arcis = {\n vector: hit.vector,\n rule: hit.rule,\n severity: 'high',\n matchedPattern: hit.matchedPattern,\n reason: `${hit.vector} pattern detected in request`,\n decision: 'deny',\n };\n res.status(403).json({\n error: 'Request blocked for security reasons',\n code: 'SECURITY_THREAT',\n vector: hit.vector,\n });\n return;\n }\n }\n\n if (req.body && typeof req.body === 'object') {\n req.body = sanitizeObject(req.body, options);\n }\n if (req.query && typeof req.query === 'object') {\n const sanitizedQuery = sanitizeObject(req.query, options);\n // Express 5: req.query is a getter with no setter — override on instance\n Object.defineProperty(req, 'query', { value: sanitizedQuery, writable: true, configurable: true });\n }\n if (req.params && typeof req.params === 'object') {\n const sanitizedParams = sanitizeObject(req.params, options);\n Object.defineProperty(req, 'params', { value: sanitizedParams, writable: true, configurable: true });\n }\n next();\n } catch (err) {\n next(err);\n }\n };\n}\n","/**\n * @module @arcis/node/sanitizers/nosql\n * NoSQL injection prevention (MongoDB operators)\n */\n\nimport { NOSQL_DANGEROUS_KEYS } from '../core/constants';\n\n/**\n * Checks if a key is a dangerous MongoDB operator.\n * \n * @param key - The key to check\n * @returns True if the key is a MongoDB operator\n * \n * @example\n * isDangerousNoSqlKey('$gt') // true\n * isDangerousNoSqlKey('name') // false\n */\nexport function isDangerousNoSqlKey(key: string): boolean {\n return NOSQL_DANGEROUS_KEYS.has(key);\n}\n\n/**\n * Recursively checks if an object contains dangerous MongoDB operators.\n * \n * @param obj - The object to check\n * @param maxDepth - Maximum recursion depth (default: 10)\n * @returns True if dangerous operators found\n */\nexport function detectNoSqlInjection(obj: unknown, maxDepth = 10): boolean {\n if (maxDepth <= 0) return false;\n if (obj === null || typeof obj !== 'object') return false;\n \n if (Array.isArray(obj)) {\n return obj.some(item => detectNoSqlInjection(item, maxDepth - 1));\n }\n \n for (const key of Object.keys(obj as Record<string, unknown>)) {\n if (isDangerousNoSqlKey(key)) {\n return true;\n }\n \n const value = (obj as Record<string, unknown>)[key];\n if (typeof value === 'object' && value !== null) {\n if (detectNoSqlInjection(value, maxDepth - 1)) {\n return true;\n }\n }\n }\n \n return false;\n}\n\n/**\n * Get list of all MongoDB operators considered dangerous.\n * Useful for documentation or custom validation.\n * \n * @returns Array of dangerous operator strings\n */\nexport function getDangerousOperators(): string[] {\n return Array.from(NOSQL_DANGEROUS_KEYS);\n}\n","/**\n * @module @arcis/node/sanitizers/prototype\n * Prototype pollution prevention\n */\n\nimport { DANGEROUS_PROTO_KEYS } from '../core/constants';\n\n/**\n * Checks if a key is dangerous for prototype pollution.\n * Case-insensitive — catches __PROTO__, Constructor, etc.\n *\n * @param key - The key to check\n * @returns True if the key could cause prototype pollution\n *\n * @example\n * isDangerousProtoKey('__proto__') // true\n * isDangerousProtoKey('__PROTO__') // true\n * isDangerousProtoKey('Constructor') // true\n * isDangerousProtoKey('name') // false\n */\nexport function isDangerousProtoKey(key: string): boolean {\n return DANGEROUS_PROTO_KEYS.has(key.toLowerCase());\n}\n\n/**\n * Recursively checks if an object contains prototype pollution keys.\n * \n * @param obj - The object to check\n * @param maxDepth - Maximum recursion depth (default: 10)\n * @returns True if dangerous keys found\n */\nexport function detectPrototypePollution(obj: unknown, maxDepth = 10): boolean {\n if (maxDepth <= 0) return false;\n if (obj === null || typeof obj !== 'object') return false;\n \n if (Array.isArray(obj)) {\n return obj.some(item => detectPrototypePollution(item, maxDepth - 1));\n }\n \n for (const key of Object.keys(obj as Record<string, unknown>)) {\n if (DANGEROUS_PROTO_KEYS.has(key.toLowerCase())) {\n return true;\n }\n \n const value = (obj as Record<string, unknown>)[key];\n if (typeof value === 'object' && value !== null) {\n if (detectPrototypePollution(value, maxDepth - 1)) {\n return true;\n }\n }\n }\n \n return false;\n}\n\n/**\n * Get list of all keys considered dangerous for prototype pollution.\n * Useful for documentation or custom validation.\n * \n * @returns Array of dangerous key strings\n */\nexport function getDangerousProtoKeys(): string[] {\n return Array.from(DANGEROUS_PROTO_KEYS);\n}\n","/**\n * @module @arcis/node/sanitizers/jsonp\n * JSONP callback sanitization to prevent XSS via callback parameters\n */\n\n/**\n * Valid JSONP callback pattern: only alphanumeric, underscore, dollar, and dot.\n * Bracket notation is rejected — it enables bypasses like `cb[x` (unbalanced)\n * and isn't needed for real-world JSONP callbacks.\n */\nconst SAFE_CALLBACK_PATTERN = /^[a-zA-Z_$][a-zA-Z0-9_$.]*$/;\n\n/**\n * Dangerous patterns that should never appear in a callback name,\n * even if they technically match the safe pattern.\n */\nconst DANGEROUS_CALLBACK_PATTERNS = [\n /\\.\\./, // prototype chain traversal\n] as const;\n\n/**\n * Validates and sanitizes a JSONP callback parameter.\n *\n * Returns the callback name if safe, or null if the callback is dangerous.\n * Use this to validate `?callback=` query parameters before wrapping responses.\n *\n * @param callback - The callback parameter value\n * @param maxLength - Maximum allowed length (default: 128)\n * @returns The safe callback name, or null if invalid\n *\n * @example\n * ```ts\n * const cb = sanitizeJsonpCallback(req.query.callback);\n * if (cb) {\n * res.set('Content-Type', 'application/javascript');\n * res.send(`${cb}(${JSON.stringify(data)})`);\n * } else {\n * res.status(400).json({ error: 'Invalid callback' });\n * }\n * ```\n */\nexport function sanitizeJsonpCallback(callback: string, maxLength = 128): string | null {\n if (typeof callback !== 'string' || callback.length === 0) {\n return null;\n }\n\n if (callback.length > maxLength) {\n return null;\n }\n\n if (!SAFE_CALLBACK_PATTERN.test(callback)) {\n return null;\n }\n\n for (const pattern of DANGEROUS_CALLBACK_PATTERNS) {\n if (pattern.test(callback)) {\n return null;\n }\n }\n\n return callback;\n}\n\n/**\n * Checks if a JSONP callback parameter contains potentially dangerous content.\n *\n * @param callback - The callback parameter value\n * @returns True if the callback is dangerous / invalid\n */\nexport function detectJsonpInjection(callback: string): boolean {\n if (typeof callback !== 'string' || callback.length === 0) {\n return false;\n }\n\n // If it doesn't match the safe pattern, it's potentially dangerous\n if (!SAFE_CALLBACK_PATTERN.test(callback)) {\n return true;\n }\n\n for (const pattern of DANGEROUS_CALLBACK_PATTERNS) {\n if (pattern.test(callback)) {\n return true;\n }\n }\n\n return false;\n}\n","/**\n * @module @arcis/node/sanitizers/pii\n * PII (Personally Identifiable Information) detection and redaction\n *\n * Detects: email addresses, phone numbers, credit card numbers, SSNs, IP addresses\n */\n\n// ─── Types ───────────────────────────────────────────────────────────────────\n\nexport type PiiType = 'email' | 'phone' | 'credit_card' | 'ssn' | 'ip_address';\n\nexport interface PiiMatch {\n type: PiiType;\n value: string;\n start: number;\n end: number;\n}\n\nexport interface PiiScanOptions {\n /** PII types to scan for. Default: all types */\n types?: PiiType[];\n}\n\nexport interface PiiRedactOptions extends PiiScanOptions {\n /** Replacement for redacted values. Default: '[REDACTED]' */\n replacement?: string;\n /** Use type-specific replacements like '[EMAIL]', '[SSN]'. Default: false */\n typeLabels?: boolean;\n}\n\n// ─── Patterns ────────────────────────────────────────────────────────────────\n\n// Email: simplified RFC 5322 — catches real-world emails without ReDoS risk\nconst EMAIL_RE = /[a-zA-Z0-9._%+-]+@[a-zA-Z0-9](?:[a-zA-Z0-9-]{0,61}[a-zA-Z0-9])?(?:\\.[a-zA-Z]{2,})+/g;\n\n// US phone numbers: (xxx) xxx-xxxx, xxx-xxx-xxxx, xxx.xxx.xxxx, xxx xxx xxxx, +1xxxxxxxxxx\n// (?<!\\d) / (?!\\d) boundaries prevent false positives inside longer digit\n// sequences like ZIP+number combos (\"94102 555-1234\") or bank account strings.\nconst PHONE_RE = /(?<!\\d)(?:\\+?1[-.\\s]?)?\\(?[2-9]\\d{2}\\)?[-.\\s]?\\d{3}[-.\\s]?\\d{4}(?!\\d)/g;\n\n// Credit cards: 13-19 digits with optional separators (spaces or dashes)\nconst CREDIT_CARD_RE = /\\b(?:\\d[ -]*?){13,19}\\b/g;\n\n// SSN: XXX-XX-XXXX (with dashes or spaces)\nconst SSN_RE = /\\b\\d{3}[-\\s]\\d{2}[-\\s]\\d{4}\\b/g;\n\n// IPv4 addresses\nconst IPV4_RE = /\\b(?:(?:25[0-5]|2[0-4]\\d|[01]?\\d\\d?)\\.){3}(?:25[0-5]|2[0-4]\\d|[01]?\\d\\d?)\\b/g;\n\n// IPv6 addresses (simplified — full addresses and common abbreviations)\nconst IPV6_RE = /\\b(?:[0-9a-fA-F]{1,4}:){7}[0-9a-fA-F]{1,4}\\b|\\b(?:[0-9a-fA-F]{1,4}:){1,7}:|::(?:[0-9a-fA-F]{1,4}:){0,5}[0-9a-fA-F]{1,4}\\b/g;\n\nconst PATTERN_MAP: Record<PiiType, RegExp[]> = {\n email: [EMAIL_RE],\n phone: [PHONE_RE],\n credit_card: [CREDIT_CARD_RE],\n ssn: [SSN_RE],\n ip_address: [IPV4_RE, IPV6_RE],\n};\n\nconst ALL_TYPES: PiiType[] = ['email', 'phone', 'credit_card', 'ssn', 'ip_address'];\n\nconst TYPE_LABELS: Record<PiiType, string> = {\n email: '[EMAIL]',\n phone: '[PHONE]',\n credit_card: '[CREDIT_CARD]',\n ssn: '[SSN]',\n ip_address: '[IP_ADDRESS]',\n};\n\n// ─── Luhn Check ──────────────────────────────────────────────────────────────\n\n/**\n * Validate a credit card number using the Luhn algorithm.\n * Strips spaces and dashes before checking.\n */\nfunction luhnCheck(value: string): boolean {\n const digits = value.replace(/[\\s-]/g, '');\n if (!/^\\d{13,19}$/.test(digits)) return false;\n\n let sum = 0;\n let alternate = false;\n for (let i = digits.length - 1; i >= 0; i--) {\n let n = parseInt(digits[i], 10);\n if (alternate) {\n n *= 2;\n if (n > 9) n -= 9;\n }\n sum += n;\n alternate = !alternate;\n }\n return sum % 10 === 0;\n}\n\n// ─── Core Functions ──────────────────────────────────────────────────────────\n\n/**\n * Scan a string for PII and return all matches.\n *\n * @param input - String to scan\n * @param options - Optional scan configuration\n * @returns Array of PII matches with type, value, and position\n *\n * @example\n * scanPii('Call me at 555-123-4567 or email john@example.com')\n * // [\n * // { type: 'phone', value: '555-123-4567', start: 11, end: 23 },\n * // { type: 'email', value: 'john@example.com', start: 33, end: 49 }\n * // ]\n */\nexport function scanPii(input: string, options: PiiScanOptions = {}): PiiMatch[] {\n if (!input || typeof input !== 'string') return [];\n\n const types = options.types ?? ALL_TYPES;\n const matches: PiiMatch[] = [];\n\n for (const type of types) {\n const patterns = PATTERN_MAP[type];\n if (!patterns) continue;\n\n for (const pattern of patterns) {\n const re = new RegExp(pattern.source, pattern.flags);\n let match: RegExpExecArray | null;\n\n while ((match = re.exec(input)) !== null) {\n const value = match[0];\n\n // Credit card: validate with Luhn algorithm\n if (type === 'credit_card' && !luhnCheck(value)) continue;\n\n // SSN: reject invalid ranges (000, 666, 900-999 for area)\n if (type === 'ssn') {\n const area = parseInt(value.substring(0, 3), 10);\n if (area === 0 || area === 666 || area >= 900) continue;\n }\n\n matches.push({\n type,\n value,\n start: match.index,\n end: match.index + value.length,\n });\n }\n }\n }\n\n // Sort by position\n matches.sort((a, b) => a.start - b.start);\n return matches;\n}\n\n/**\n * Check if a string contains any PII.\n *\n * @param input - String to check\n * @param options - Optional scan configuration\n * @returns true if PII is detected\n */\nexport function detectPii(input: string, options: PiiScanOptions = {}): boolean {\n return scanPii(input, options).length > 0;\n}\n\n/**\n * Redact PII from a string, replacing matches with a placeholder.\n *\n * @param input - String to redact\n * @param options - Redaction options\n * @returns String with PII replaced\n *\n * @example\n * redactPii('Email: john@example.com, SSN: 123-45-6789')\n * // 'Email: [REDACTED], SSN: [REDACTED]'\n *\n * redactPii('Email: john@example.com', { typeLabels: true })\n * // 'Email: [EMAIL]'\n */\nexport function redactPii(input: string, options: PiiRedactOptions = {}): string {\n if (!input || typeof input !== 'string') return input;\n\n const matches = scanPii(input, options);\n if (matches.length === 0) return input;\n\n const replacement = options.replacement ?? '[REDACTED]';\n\n // Replace from end to preserve positions\n let result = input;\n for (let i = matches.length - 1; i >= 0; i--) {\n const m = matches[i];\n const label = options.typeLabels ? TYPE_LABELS[m.type] : replacement;\n result = result.substring(0, m.start) + label + result.substring(m.end);\n }\n\n return result;\n}\n\n/**\n * Scan an object's string values for PII recursively.\n *\n * @param obj - Object to scan\n * @param options - Optional scan configuration\n * @returns Array of PII matches with the field path prepended\n */\nexport function scanObjectPii(\n obj: Record<string, unknown>,\n options: PiiScanOptions = {},\n path = '',\n): (PiiMatch & { field: string })[] {\n const results: (PiiMatch & { field: string })[] = [];\n if (!obj || typeof obj !== 'object') return results;\n\n for (const [key, value] of Object.entries(obj)) {\n const fieldPath = path ? `${path}.${key}` : key;\n\n if (typeof value === 'string') {\n const matches = scanPii(value, options);\n for (const m of matches) {\n results.push({ ...m, field: fieldPath });\n }\n } else if (value && typeof value === 'object' && !Array.isArray(value)) {\n results.push(...scanObjectPii(value as Record<string, unknown>, options, fieldPath));\n } else if (Array.isArray(value)) {\n for (let i = 0; i < value.length; i++) {\n const item = value[i];\n if (typeof item === 'string') {\n const matches = scanPii(item, options);\n for (const m of matches) {\n results.push({ ...m, field: `${fieldPath}[${i}]` });\n }\n } else if (item && typeof item === 'object') {\n results.push(...scanObjectPii(item as Record<string, unknown>, options, `${fieldPath}[${i}]`));\n }\n }\n }\n }\n\n return results;\n}\n\n/**\n * Redact PII from all string values in an object recursively.\n *\n * @param obj - Object to redact\n * @param options - Redaction options\n * @returns New object with PII redacted\n */\nexport function redactObjectPii<T extends Record<string, unknown>>(\n obj: T,\n options: PiiRedactOptions = {},\n): T {\n if (!obj || typeof obj !== 'object') return obj;\n\n const result: Record<string, unknown> = {};\n\n for (const [key, value] of Object.entries(obj)) {\n if (typeof value === 'string') {\n result[key] = redactPii(value, options);\n } else if (Array.isArray(value)) {\n result[key] = value.map(item => {\n if (typeof item === 'string') return redactPii(item, options);\n if (item && typeof item === 'object') return redactObjectPii(item as Record<string, unknown>, options);\n return item;\n });\n } else if (value && typeof value === 'object') {\n result[key] = redactObjectPii(value as Record<string, unknown>, options);\n } else {\n result[key] = value;\n }\n }\n\n return result as T;\n}\n","/**\n * @module @arcis/node/sanitizers/encode\n * Context-aware output encoding for XSS prevention.\n *\n * Wrong-context encoding is the #1 cause of XSS bypasses in \"protected\" apps.\n * A single sanitize() is not enough when output goes to JS, CSS, or attribute contexts.\n */\n\n// HTML entity map — covers the 5 dangerous chars in HTML body context\nconst HTML_ENTITIES: Record<string, string> = {\n '&': '&',\n '<': '<',\n '>': '>',\n '\"': '"',\n \"'\": ''',\n};\n\nconst HTML_ENCODE_RE = /[&<>\"']/g;\n\n/**\n * Encodes for HTML body context. Entity-encodes & < > \" '\n *\n * Use when outputting to HTML element content:\n * `<p>${encodeForHtml(userInput)}</p>`\n */\nexport function encodeForHtml(value: string): string {\n if (!value) return '';\n return value.replace(HTML_ENCODE_RE, (ch) => HTML_ENTITIES[ch]);\n}\n\n/**\n * Encodes for HTML attribute context.\n * All non-alphanumeric characters are encoded as `&#xHH;` hex entities.\n *\n * Use when outputting to HTML attributes:\n * `<div title=\"${encodeForAttribute(userInput)}\">`\n */\nexport function encodeForAttribute(value: string): string {\n if (!value) return '';\n let result = '';\n for (let i = 0; i < value.length; i++) {\n const ch = value.charCodeAt(i);\n // Allow a-z A-Z 0-9\n if (\n (ch >= 0x30 && ch <= 0x39) || // 0-9\n (ch >= 0x41 && ch <= 0x5a) || // A-Z\n (ch >= 0x61 && ch <= 0x7a) // a-z\n ) {\n result += value[i];\n } else {\n result += `&#x${ch.toString(16).toUpperCase()};`;\n }\n }\n return result;\n}\n\n/**\n * Encodes for JavaScript string context.\n * Non-alphanumeric characters are escaped as `\\xHH` (ASCII) or `\\uHHHH` (Unicode).\n *\n * Use when embedding in JS string literals:\n * `var x = '${encodeForJs(userInput)}';`\n */\nexport function encodeForJs(value: string): string {\n if (!value) return '';\n let result = '';\n // Use for-of to iterate codepoints, not UTF-16 code units.\n // This correctly handles surrogate pairs (emoji, symbols outside BMP).\n for (const char of value) {\n const cp = char.codePointAt(0);\n if (cp === undefined) continue;\n // Allow a-z A-Z 0-9\n if (\n (cp >= 0x30 && cp <= 0x39) || // 0-9\n (cp >= 0x41 && cp <= 0x5a) || // A-Z\n (cp >= 0x61 && cp <= 0x7a) // a-z\n ) {\n result += char;\n } else if (cp < 0x100) {\n result += `\\\\x${cp.toString(16).toUpperCase().padStart(2, '0')}`;\n } else if (cp <= 0xFFFF) {\n result += `\\\\u${cp.toString(16).toUpperCase().padStart(4, '0')}`;\n } else {\n // Codepoints above BMP — use ES6 Unicode escape\n result += `\\\\u{${cp.toString(16).toUpperCase()}}`;\n }\n }\n return result;\n}\n\n/**\n * Encodes for URL parameter context. Percent-encodes all non-unreserved chars.\n *\n * Use when building query strings:\n * `?q=${encodeForUrl(userInput)}`\n */\nexport function encodeForUrl(value: string): string {\n if (!value) return '';\n // encodeURIComponent handles most cases but doesn't encode: ! ' ( ) *\n // We encode these additionally for full safety per RFC 3986\n return encodeURIComponent(value).replace(/[!'()*]/g, (ch) => {\n return `%${ch.charCodeAt(0).toString(16).toUpperCase()}`;\n });\n}\n\n/**\n * Encodes for CSS value context.\n * Non-alphanumeric characters are hex-escaped as `\\HH ` (trailing space per CSS spec).\n *\n * Use when embedding in CSS values:\n * `content: '${encodeForCss(userInput)}';`\n */\nexport function encodeForCss(value: string): string {\n if (!value) return '';\n let result = '';\n for (let i = 0; i < value.length; i++) {\n const ch = value.charCodeAt(i);\n // Allow a-z A-Z 0-9\n if (\n (ch >= 0x30 && ch <= 0x39) || // 0-9\n (ch >= 0x41 && ch <= 0x5a) || // A-Z\n (ch >= 0x61 && ch <= 0x7a) // a-z\n ) {\n result += value[i];\n } else {\n // CSS hex escape: backslash + hex code + trailing space (CSS spec requirement)\n result += `\\\\${ch.toString(16).toUpperCase()} `;\n }\n }\n return result;\n}\n","/**\n * @module @arcis/node/sanitizers/graphql\n * GraphQL injection prevention (sdk-vectors.md tier 1 #21).\n *\n * Two threats covered:\n *\n * 1. **Depth-bomb DoS** — nested-query payloads like\n * `query { x { x { x { ... } } } }` to ridiculous depth that explode\n * resolver work (each `{` typically maps to a database round-trip).\n * Even a 50-deep query against a real schema can hammer the\n * backend; 1000-deep crashes the resolver entirely.\n *\n * 2. **Introspection abuse** — `__schema` / `__type` / `__typename`\n * queries that let an attacker enumerate the entire schema, then\n * use that map to find sensitive fields, deprecated mutations,\n * or unprotected admin paths. Production GraphQL endpoints should\n * disable introspection by default.\n *\n * v1 is regex-based: count `{` / `}` for nesting depth (no escape\n * handling — strings inside the query that contain `{` will\n * over-count). False positives are an acceptable tradeoff for v1\n * because (a) the depth threshold is well above legitimate query\n * shapes, (b) a real GraphQL parser pulls in `graphql` as a runtime\n * dep — significant for a sanitizer that ships in every Arcis\n * install. Customers running queries near the threshold can either\n * raise `maxDepth` or bring their own AST pre-pass.\n *\n * NOT included in v1:\n * - Field-count limit (some servers have this; orthogonal to depth)\n * - Alias-bomb detection (`q { f1: foo, f2: foo, ...}` — easier as\n * a length-check than a parse)\n * - Variable rebinding attacks\n *\n * Each is a follow-up if customers ask. Documented inline.\n */\n\nexport interface GraphqlGuardOptions {\n /** Maximum allowed nesting depth. Default: 10. Most legit queries are <8. */\n maxDepth?: number;\n /** Maximum query string length in characters. Default: 10000. */\n maxLength?: number;\n /**\n * Block introspection queries (`__schema`, `__type`). Default: true.\n * Set `false` in development if you rely on GraphiQL / Apollo\n * Studio. Production should leave this on.\n */\n blockIntrospection?: boolean;\n /**\n * Maximum number of field aliases per query (`label: field`).\n * Default: 50. Alias-bomb attacks repeat the same expensive field\n * under many labels to multiply backend cost. Real queries rarely\n * use more than 20 aliases. improvements.md §1.2 V34.\n */\n maxAliases?: number;\n /**\n * Reject queries whose fragment definitions form a cycle (direct\n * self-reference `fragment A on T { ...A }` or indirect\n * `A → B → A`). Such cycles either infinite-loop a naive resolver\n * or get rejected by `graphql-core` with a 500. Default: true.\n * improvements.md §1.2 V34.\n */\n blockFragmentCycles?: boolean;\n}\n\nexport type GraphqlViolation =\n | 'depth'\n | 'length'\n | 'introspection'\n | 'aliases'\n | 'fragment_cycle';\n\nexport interface GraphqlGuardResult {\n /** True if the query violated any configured limit. */\n blocked: boolean;\n /** Which limit fired first. Precedence: depth → introspection → aliases → fragment_cycle → length. */\n reason?: GraphqlViolation;\n /** Observed nesting depth. Always returned. */\n depth: number;\n /** Observed length. Always returned. */\n length: number;\n /** Observed alias count (improvements.md §1.2 V34). Always returned. */\n aliases: number;\n}\n\nconst DEFAULTS = {\n maxDepth: 10,\n maxLength: 10000,\n blockIntrospection: true,\n maxAliases: 50,\n blockFragmentCycles: true,\n} as const;\n\n/**\n * Word-boundary `__` reflection markers. GraphQL spec reserves the\n * `__` prefix for introspection — `__schema`, `__type`, `__typename`,\n * `__typeKind`, `__directive`. Matching the prefix catches them all\n * without enumerating; the boundary anchor (`\\b__`) avoids\n * false-matches on user fields like `last__updated_at`.\n *\n * `__typename` is the one introspection field that's commonly used\n * legitimately (Apollo client requests it on every query). We\n * deliberately let it through by listing the others explicitly.\n */\nconst INTROSPECTION_PATTERN = /\\b__(schema|type|typeKind|directive)\\b/;\n\n/**\n * Compute the maximum nesting depth of a GraphQL query string by\n * counting `{` and `}` runs. Strings inside the query (e.g.\n * `field(arg: \"{...}\")`) inflate this — accepted v1 tradeoff. A\n * future AST-mode implementation lives behind a separate flag.\n */\nfunction computeDepth(query: string): number {\n let depth = 0;\n let max = 0;\n for (let i = 0; i < query.length; i++) {\n const c = query.charCodeAt(i);\n if (c === 123 /* { */) {\n depth++;\n if (depth > max) max = depth;\n } else if (c === 125 /* } */) {\n // Don't go negative on malformed input — clamp at 0.\n if (depth > 0) depth--;\n }\n }\n return max;\n}\n\n// `label: field` — alias of one field to another name. Excludes\n// patterns like `query Foo:` where Foo is an operation name (handled\n// because the regex requires the second token to be a name AND\n// alias semantics only apply inside `{...}` blocks; this is a\n// lexical approximation, not a parser).\nconst ALIAS_PATTERN = /\\b([a-zA-Z_][a-zA-Z0-9_]*)\\s*:\\s*([a-zA-Z_][a-zA-Z0-9_]*)\\b/g;\n\n// `fragment <name> on <type> {` — captures the fragment NAME.\nconst FRAGMENT_DEF_PATTERN =\n /\\bfragment\\s+([a-zA-Z_][a-zA-Z0-9_]*)\\s+on\\s+[a-zA-Z_][a-zA-Z0-9_]*\\s*\\{/g;\n\n// `...FragmentName` spread inside a selection set.\nconst FRAGMENT_SPREAD_PATTERN = /\\.\\.\\.\\s*([a-zA-Z_][a-zA-Z0-9_]*)\\b/g;\n\nfunction countAliases(query: string): number {\n let n = 0;\n ALIAS_PATTERN.lastIndex = 0;\n while (ALIAS_PATTERN.exec(query) !== null) n++;\n return n;\n}\n\n/**\n * Detect cycles in the fragment spread graph (improvements.md §1.2 V34).\n *\n * Walks `fragment X on T { ... }` definitions, builds adjacency from\n * each fragment to the names it spreads, and runs DFS for a back-edge.\n * Body of each fragment is brace-matched so the subsequent query\n * operation's spreads don't pollute the graph.\n */\nfunction hasFragmentCycle(query: string): boolean {\n const deps = new Map<string, Set<string>>();\n FRAGMENT_DEF_PATTERN.lastIndex = 0;\n let match: RegExpExecArray | null;\n while ((match = FRAGMENT_DEF_PATTERN.exec(query)) !== null) {\n const name = match[1];\n const bodyStart = match.index + match[0].length; // right after `{`\n // Brace-match to find the body end.\n let depth = 1;\n let i = bodyStart;\n while (i < query.length && depth > 0) {\n const ch = query[i];\n if (ch === '{') depth++;\n else if (ch === '}') depth--;\n i++;\n }\n const bodyEnd = depth === 0 ? i - 1 : i;\n const body = query.slice(bodyStart, bodyEnd);\n const spreads = new Set<string>();\n FRAGMENT_SPREAD_PATTERN.lastIndex = 0;\n let sm: RegExpExecArray | null;\n while ((sm = FRAGMENT_SPREAD_PATTERN.exec(body)) !== null) {\n spreads.add(sm[1]);\n }\n deps.set(name, spreads);\n }\n if (deps.size === 0) return false;\n\n const WHITE = 0;\n const GRAY = 1;\n const BLACK = 2;\n const color = new Map<string, number>();\n for (const name of deps.keys()) color.set(name, WHITE);\n\n function visit(name: string): boolean {\n if (color.get(name) === GRAY) return true; // back-edge\n if (color.get(name) === BLACK) return false;\n if (!deps.has(name)) return false; // spread to undefined fragment\n color.set(name, GRAY);\n for (const child of deps.get(name)!) {\n if (visit(child)) return true;\n }\n color.set(name, BLACK);\n return false;\n }\n\n for (const name of deps.keys()) {\n if (visit(name)) return true;\n }\n return false;\n}\n\n/**\n * Inspect a GraphQL query against the configured limits. Returns a\n * structured result; the middleware below uses this directly. Pure\n * function — no I/O, no res handle.\n */\nexport function inspectGraphqlQuery(\n query: string,\n options: GraphqlGuardOptions = {},\n): GraphqlGuardResult {\n const maxDepth = options.maxDepth ?? DEFAULTS.maxDepth;\n const maxLength = options.maxLength ?? DEFAULTS.maxLength;\n const blockIntrospection = options.blockIntrospection ?? DEFAULTS.blockIntrospection;\n const maxAliases = options.maxAliases ?? DEFAULTS.maxAliases;\n const blockFragmentCycles =\n options.blockFragmentCycles ?? DEFAULTS.blockFragmentCycles;\n\n const length = query.length;\n const depth = computeDepth(query);\n const aliases = countAliases(query);\n\n // Precedence: depth → introspection → aliases → fragment_cycle →\n // length. Cheapest-to-explain failures first; length last because\n // it's the easiest false-positive (long queries with deep inline\n // fragments are legitimate). improvements.md §1.2 V34.\n if (depth > maxDepth) {\n return { blocked: true, reason: 'depth', depth, length, aliases };\n }\n if (blockIntrospection && INTROSPECTION_PATTERN.test(query)) {\n return { blocked: true, reason: 'introspection', depth, length, aliases };\n }\n if (aliases > maxAliases) {\n return { blocked: true, reason: 'aliases', depth, length, aliases };\n }\n if (blockFragmentCycles && hasFragmentCycle(query)) {\n return { blocked: true, reason: 'fragment_cycle', depth, length, aliases };\n }\n if (length > maxLength) {\n return { blocked: true, reason: 'length', depth, length, aliases };\n }\n\n return { blocked: false, depth, length, aliases };\n}\n\n/**\n * Detect-only API matching the rest of the sanitizer module surface\n * (`detectXss` / `detectSql` / `detectXxe` / etc.). Returns a boolean\n * for callers that just want a yes/no — use `inspectGraphqlQuery` if\n * you need the structured reason.\n */\nexport function detectGraphqlAbuse(\n query: string,\n options?: GraphqlGuardOptions,\n): boolean {\n if (typeof query !== 'string' || query.length === 0) return false;\n return inspectGraphqlQuery(query, options).blocked;\n}\n","/**\n * @module @arcis/node/validation/schema\n * Request validation middleware\n */\n\nimport type { Request, Response, NextFunction, RequestHandler } from 'express';\nimport { VALIDATION, ERRORS } from '../core/constants';\nimport type { ValidationSchema, FieldValidator } from '../core/types';\nimport { sanitizeString } from '../sanitizers';\n\n/**\n * Create Express middleware for request validation.\n * Prevents mass assignment by only allowing fields defined in the schema.\n * \n * @param schema - Validation schema defining expected fields\n * @param source - Request property to validate ('body', 'query', or 'params')\n * @returns Express middleware\n * \n * @example\n * app.post('/users', validate({\n * email: { type: 'email', required: true },\n * name: { type: 'string', min: 2, max: 50 },\n * age: { type: 'number', min: 0, max: 150 },\n * role: { type: 'string', enum: ['user', 'admin'] }\n * }), handler);\n * \n * @example\n * // Validate query params\n * app.get('/search', validate({\n * q: { type: 'string', required: true, min: 1 },\n * page: { type: 'number', min: 1 }\n * }, 'query'), handler);\n */\nexport function validate(\n schema: ValidationSchema,\n source: 'body' | 'query' | 'params' = 'body'\n): RequestHandler {\n return (req: Request, res: Response, next: NextFunction) => {\n const data = req[source] || {};\n const errors: string[] = [];\n const validated: Record<string, unknown> = {};\n\n for (const [field, rules] of Object.entries(schema)) {\n const value = data[field];\n const result = validateField(field, value, rules);\n \n if (result.errors.length > 0) {\n errors.push(...result.errors);\n } else if (result.value !== undefined) {\n validated[field] = result.value;\n }\n }\n\n if (errors.length > 0) {\n res.status(400).json({ errors });\n return;\n }\n\n // Replace with validated data (prevents mass assignment).\n // SECURITY: Express 5 makes req.body/query/params read-only. Use\n // defineProperty so this works on both Express 4 and 5; direct\n // assignment crashes Express 5 with TypeError.\n Object.defineProperty(req, source, {\n value: validated,\n writable: true,\n configurable: true,\n enumerable: true,\n });\n next();\n };\n}\n\n/**\n * Validate a single field against its rules.\n */\nfunction validateField(\n field: string,\n value: unknown,\n rules: FieldValidator\n): { value?: unknown; errors: string[] } {\n const errors: string[] = [];\n\n // Required check\n if (rules.required && (value === undefined || value === null || value === '')) {\n errors.push(ERRORS.VALIDATION.REQUIRED(field));\n return { errors };\n }\n\n // Skip optional empty fields\n if (value === undefined || value === null) {\n return { errors: [] };\n }\n\n let typedValue: unknown = value;\n let isValid = true;\n\n // Type validation and coercion\n switch (rules.type) {\n case 'string':\n if (typeof value !== 'string') {\n errors.push(ERRORS.VALIDATION.INVALID_TYPE(field, 'string'));\n isValid = false;\n break;\n }\n if (rules.min !== undefined && value.length < rules.min) {\n errors.push(ERRORS.VALIDATION.MIN_LENGTH(field, rules.min));\n isValid = false;\n }\n if (rules.max !== undefined && value.length > rules.max) {\n errors.push(ERRORS.VALIDATION.MAX_LENGTH(field, rules.max));\n isValid = false;\n }\n if (rules.pattern && !rules.pattern.test(value)) {\n errors.push(ERRORS.VALIDATION.INVALID_FORMAT(field));\n isValid = false;\n }\n // Enum check runs before sanitization so the raw value is compared.\n // Sanitizing first could silently modify the value and cause a mismatch\n // with enum entries that contain characters the sanitizer would strip.\n if (isValid && rules.enum && !rules.enum.includes(value)) {\n errors.push(ERRORS.VALIDATION.INVALID_ENUM(field, rules.enum));\n isValid = false;\n }\n if (isValid && rules.sanitize !== false) {\n typedValue = sanitizeString(value);\n }\n break;\n\n case 'number':\n typedValue = Number(value);\n if (isNaN(typedValue as number)) {\n errors.push(ERRORS.VALIDATION.INVALID_TYPE(field, 'number'));\n isValid = false;\n break;\n }\n if (rules.min !== undefined && (typedValue as number) < rules.min) {\n errors.push(ERRORS.VALIDATION.MIN_VALUE(field, rules.min));\n isValid = false;\n }\n if (rules.max !== undefined && (typedValue as number) > rules.max) {\n errors.push(ERRORS.VALIDATION.MAX_VALUE(field, rules.max));\n isValid = false;\n }\n break;\n\n case 'boolean':\n if (value === 'true' || value === true || value === 1 || value === '1') {\n typedValue = true;\n } else if (value === 'false' || value === false || value === 0 || value === '0') {\n typedValue = false;\n } else {\n errors.push(ERRORS.VALIDATION.INVALID_TYPE(field, 'boolean'));\n isValid = false;\n }\n break;\n\n case 'email':\n if (!VALIDATION.EMAIL.test(String(value))) {\n errors.push(ERRORS.VALIDATION.INVALID_EMAIL(field));\n isValid = false;\n }\n if (isValid) {\n typedValue = sanitizeString(String(value).toLowerCase().trim());\n }\n break;\n\n case 'url':\n if (!VALIDATION.URL.test(String(value))) {\n errors.push(ERRORS.VALIDATION.INVALID_URL(field));\n isValid = false;\n }\n if (isValid) {\n typedValue = sanitizeString(String(value));\n }\n break;\n\n case 'uuid':\n if (!VALIDATION.UUID.test(String(value))) {\n errors.push(ERRORS.VALIDATION.INVALID_UUID(field));\n isValid = false;\n }\n break;\n\n case 'array':\n if (!Array.isArray(value)) {\n errors.push(ERRORS.VALIDATION.INVALID_TYPE(field, 'array'));\n isValid = false;\n break;\n }\n if (rules.min !== undefined && value.length < rules.min) {\n errors.push(ERRORS.VALIDATION.MIN_ITEMS(field, rules.min));\n isValid = false;\n }\n if (rules.max !== undefined && value.length > rules.max) {\n errors.push(ERRORS.VALIDATION.MAX_ITEMS(field, rules.max));\n isValid = false;\n }\n break;\n\n case 'object':\n if (typeof value !== 'object' || Array.isArray(value) || value === null) {\n errors.push(ERRORS.VALIDATION.INVALID_TYPE(field, 'object'));\n isValid = false;\n }\n break;\n }\n\n // Enum validation for non-string types (strings check enum before sanitizing above).\n if (isValid && rules.enum && rules.type !== 'string' && !rules.enum.includes(typedValue)) {\n errors.push(ERRORS.VALIDATION.INVALID_ENUM(field, rules.enum));\n isValid = false;\n }\n\n // Custom validation\n if (isValid && rules.custom) {\n const customResult = rules.custom(typedValue);\n if (customResult === undefined) {\n throw new TypeError(\n `Custom validator for field \"${field}\" returned undefined. ` +\n 'Return true to pass, false to fail, or a string error message.'\n );\n }\n if (customResult !== true) {\n errors.push(typeof customResult === 'string' && customResult.length > 0 ? customResult : `${field} is invalid`);\n isValid = false;\n }\n }\n\n return {\n value: isValid ? typedValue : undefined,\n errors,\n };\n}\n\n/**\n * Alias for validate\n * @see validate\n */\nexport const createValidator = validate;\n","/**\n * @module @arcis/node/validation/file\n * File upload validation and filename sanitization\n */\n\n// =============================================================================\n// MAGIC BYTES — first bytes of common file types\n// =============================================================================\n\nconst MAGIC_BYTES: Record<string, Buffer[]> = {\n // Images\n 'image/jpeg': [Buffer.from([0xFF, 0xD8, 0xFF])],\n 'image/png': [Buffer.from([0x89, 0x50, 0x4E, 0x47])],\n 'image/gif': [Buffer.from('GIF87a'), Buffer.from('GIF89a')],\n 'image/webp': [Buffer.from('RIFF')], // RIFF....WEBP\n 'image/bmp': [Buffer.from([0x42, 0x4D])],\n 'image/svg+xml': [], // text-based, check separately\n\n // Documents\n 'application/pdf': [Buffer.from('%PDF')],\n 'application/zip': [Buffer.from([0x50, 0x4B, 0x03, 0x04])],\n\n // Audio/Video\n 'audio/mpeg': [Buffer.from([0xFF, 0xFB]), Buffer.from([0xFF, 0xF3]), Buffer.from([0x49, 0x44, 0x33])],\n 'video/mp4': [], // ftyp at offset 4\n};\n\n// =============================================================================\n// DANGEROUS EXTENSIONS — files that can execute code\n// =============================================================================\n\nconst DANGEROUS_EXTENSIONS = new Set([\n // Scripts\n '.exe', '.bat', '.cmd', '.com', '.msi', '.scr', '.pif',\n '.vbs', '.vbe', '.js', '.jse', '.ws', '.wsf', '.wsc', '.wsh',\n '.ps1', '.ps1xml', '.ps2', '.ps2xml', '.psc1', '.psc2',\n '.sh', '.bash', '.csh', '.ksh',\n // Server-side\n '.php', '.php3', '.php4', '.php5', '.phtml', '.pht',\n '.asp', '.aspx', '.ashx', '.asmx', '.cer',\n '.jsp', '.jspx', '.jsw', '.jsv',\n '.cgi', '.pl', '.py', '.rb',\n // Java\n '.jar', '.war', '.ear', '.class',\n // Config that can execute\n '.htaccess', '.htpasswd',\n // Template engines\n '.ejs', '.pug', '.hbs', '.handlebars', '.njk', '.twig',\n // Shortcuts/links\n '.lnk', '.inf', '.reg', '.url',\n // Office macros\n '.docm', '.xlsm', '.pptm', '.dotm',\n]);\n\n// =============================================================================\n// TYPES\n// =============================================================================\n\n/** File upload validation options */\nexport interface ValidateFileOptions {\n /** Maximum file size in bytes. Default: 5MB */\n maxSize?: number;\n /** Allowed MIME types (e.g., ['image/jpeg', 'image/png']) */\n allowedTypes?: string[];\n /** Allowed file extensions (e.g., ['.jpg', '.png']). Includes dot. */\n allowedExtensions?: string[];\n /** Block dangerous/executable extensions. Default: true */\n blockExecutables?: boolean;\n /** Validate magic bytes match the claimed MIME type. Default: true */\n validateMagicBytes?: boolean;\n /** Block files with no extension. Default: true */\n blockNoExtension?: boolean;\n /** Block double extensions (e.g., file.php.jpg). Default: true */\n blockDoubleExtensions?: boolean;\n}\n\n/** File metadata for validation */\nexport interface FileInput {\n /** Original filename */\n filename: string;\n /** MIME type (as claimed by client) */\n mimetype: string;\n /** File size in bytes */\n size: number;\n /** File content buffer (for magic byte validation) */\n buffer?: Buffer;\n}\n\n/** File validation result */\nexport interface ValidateFileResult {\n /** Whether the file passed validation */\n valid: boolean;\n /** Validation errors (empty if valid) */\n errors: string[];\n /** Sanitized filename (safe for storage) */\n sanitizedFilename: string;\n}\n\n// =============================================================================\n// DEFAULTS\n// =============================================================================\n\nconst DEFAULT_MAX_SIZE = 5 * 1024 * 1024; // 5MB\n\n// =============================================================================\n// FILENAME SANITIZATION\n// =============================================================================\n\n/**\n * Sanitize a filename for safe storage.\n *\n * Strips path traversal, null bytes, control characters, and special characters.\n * Preserves the extension and converts to a filesystem-safe name.\n *\n * @param filename - The original filename\n * @returns A sanitized filename safe for storage\n *\n * @example\n * sanitizeFilename('../../etc/passwd') // 'etc_passwd'\n * sanitizeFilename('file<name>.jpg') // 'filename.jpg'\n * sanitizeFilename('photo (1).jpg') // 'photo_1.jpg'\n * sanitizeFilename('.htaccess') // 'htaccess'\n */\nexport function sanitizeFilename(filename: string): string {\n let name = filename;\n\n // Strip null bytes\n name = name.replace(/\\0/g, '');\n\n // Strip path components (both Unix and Windows)\n name = name.replace(/^.*[/\\\\]/, '');\n\n // Strip control characters\n name = name.replace(/[\\x00-\\x1F\\x7F]/g, '');\n\n // Strip characters unsafe for filesystems\n name = name.replace(/[<>:\"/\\\\|?*]/g, '');\n\n // Replace spaces and parens with underscores\n name = name.replace(/[\\s()]+/g, '_');\n\n // Strip leading dots (hidden files / .htaccess)\n name = name.replace(/^\\.+/, '');\n\n // Collapse multiple underscores/dots\n name = name.replace(/_{2,}/g, '_');\n name = name.replace(/\\.{2,}/g, '.');\n\n // Trim underscores before dots (e.g., \"photo_1_.jpg\" → \"photo_1.jpg\")\n name = name.replace(/_+\\./g, '.');\n\n // Trim underscores from edges\n name = name.replace(/^_+|_+$/g, '');\n\n // Fallback for empty name\n if (!name || name === '.') {\n name = 'unnamed';\n }\n\n return name;\n}\n\n// =============================================================================\n// MAGIC BYTE VALIDATION\n// =============================================================================\n\n/**\n * Check if file content matches the claimed MIME type via magic bytes.\n */\nfunction matchesMagicBytes(buffer: Buffer, mimetype: string): boolean {\n const signatures = MAGIC_BYTES[mimetype];\n if (!signatures || signatures.length === 0) return true; // no signature to check\n\n return signatures.some(sig => {\n if (buffer.length < sig.length) return false;\n return buffer.subarray(0, sig.length).equals(sig);\n });\n}\n\n// =============================================================================\n// EXTENSION HELPERS\n// =============================================================================\n\n/**\n * Get the extension from a filename (lowercase, with dot).\n */\nfunction getExtension(filename: string): string {\n const lastDot = filename.lastIndexOf('.');\n if (lastDot < 1) return '';\n return filename.slice(lastDot).toLowerCase();\n}\n\n/**\n * Check if a filename has double extensions (e.g., file.php.jpg).\n */\nfunction hasDoubleExtension(filename: string): boolean {\n const parts = filename.split('.');\n if (parts.length < 3) return false;\n\n // Check if any non-final extension is dangerous\n for (let i = 1; i < parts.length - 1; i++) {\n const ext = '.' + parts[i].toLowerCase();\n if (DANGEROUS_EXTENSIONS.has(ext)) return true;\n }\n return false;\n}\n\n// =============================================================================\n// FILE VALIDATION\n// =============================================================================\n\n/**\n * Validate a file upload for security.\n *\n * Checks file size, MIME type, extension, magic bytes, and dangerous patterns.\n * Returns a result with validation errors and a sanitized filename.\n *\n * @param file - File metadata and optional content\n * @param options - Validation options\n * @returns Validation result\n *\n * @example\n * const result = validateFile(\n * { filename: 'photo.jpg', mimetype: 'image/jpeg', size: 1024, buffer },\n * { allowedTypes: ['image/jpeg', 'image/png'], maxSize: 2 * 1024 * 1024 }\n * );\n * if (!result.valid) {\n * return res.status(400).json({ errors: result.errors });\n * }\n * // Use result.sanitizedFilename for storage\n *\n * @example\n * // Block executables only (no whitelist)\n * const result = validateFile(file, { blockExecutables: true });\n */\nexport function validateFile(\n file: FileInput,\n options: ValidateFileOptions = {}\n): ValidateFileResult {\n const {\n maxSize = DEFAULT_MAX_SIZE,\n allowedTypes,\n allowedExtensions,\n blockExecutables = true,\n validateMagicBytes = true,\n blockNoExtension = true,\n blockDoubleExtensions = true,\n } = options;\n\n const errors: string[] = [];\n const sanitizedFilename = sanitizeFilename(file.filename);\n const extension = getExtension(sanitizedFilename);\n\n // Size check\n if (file.size > maxSize) {\n errors.push(`File size ${file.size} exceeds maximum ${maxSize} bytes`);\n }\n\n if (file.size === 0) {\n errors.push('File is empty');\n }\n\n // Extension checks\n if (blockNoExtension && !extension) {\n errors.push('File has no extension');\n }\n\n if (blockExecutables && extension && DANGEROUS_EXTENSIONS.has(extension)) {\n errors.push(`Executable extension \"${extension}\" is not allowed`);\n }\n\n if (blockDoubleExtensions && hasDoubleExtension(sanitizedFilename)) {\n errors.push('Double extensions with executable types are not allowed');\n }\n\n if (allowedExtensions && extension) {\n const normalizedAllowed = allowedExtensions.map(e => e.toLowerCase());\n if (!normalizedAllowed.includes(extension)) {\n errors.push(`Extension \"${extension}\" is not allowed. Allowed: ${normalizedAllowed.join(', ')}`);\n }\n }\n\n // MIME type check\n if (allowedTypes && !allowedTypes.includes(file.mimetype)) {\n errors.push(`MIME type \"${file.mimetype}\" is not allowed. Allowed: ${allowedTypes.join(', ')}`);\n }\n\n // Magic bytes validation\n if (validateMagicBytes && file.buffer && file.buffer.length > 0) {\n if (!matchesMagicBytes(file.buffer, file.mimetype)) {\n errors.push(`File content does not match claimed MIME type \"${file.mimetype}\"`);\n }\n }\n\n return {\n valid: errors.length === 0,\n errors,\n sanitizedFilename,\n };\n}\n\n/**\n * Check if a file extension is considered dangerous/executable.\n *\n * @param filename - Filename or extension to check\n * @returns true if the extension is dangerous\n */\nexport function isDangerousExtension(filename: string): boolean {\n const ext = getExtension(filename);\n return ext !== '' && DANGEROUS_EXTENSIONS.has(ext);\n}\n","/**\n * @module @arcis/node/validation/url\n * SSRF (Server-Side Request Forgery) prevention\n *\n * Validates URLs to ensure they don't target private/internal networks,\n * localhost, cloud metadata endpoints, or use dangerous protocols.\n *\n * @example\n * import { validateUrl } from '@arcis/node';\n *\n * // Block SSRF attempts\n * validateUrl('http://169.254.169.254/latest/meta-data/') // { safe: false, reason: 'link-local address' }\n * validateUrl('http://10.0.0.1/admin') // { safe: false, reason: 'private address (10.0.0.0/8)' }\n * validateUrl('http://localhost/secret') // { safe: false, reason: 'loopback address' }\n * validateUrl('file:///etc/passwd') // { safe: false, reason: 'disallowed protocol: file:' }\n *\n * // Allow safe URLs\n * validateUrl('https://api.example.com/data') // { safe: true }\n */\n\n/** Options for URL validation */\nexport interface ValidateUrlOptions {\n /** Allowed protocols. Default: ['http:', 'https:'] */\n allowedProtocols?: string[];\n /** Additional hostnames to block (e.g., internal service names) */\n blockedHosts?: string[];\n /** Additional hostnames to always allow (bypass IP checks) */\n allowedHosts?: string[];\n /** Allow localhost/loopback. Default: false */\n allowLocalhost?: boolean;\n /** Allow private/internal IPs. Default: false */\n allowPrivate?: boolean;\n}\n\n/** Result of URL validation */\nexport interface ValidateUrlResult {\n /** Whether the URL is safe to fetch */\n safe: boolean;\n /** Reason the URL was blocked (only set when safe=false) */\n reason?: string;\n}\n\n/**\n * Validate a URL for SSRF safety.\n *\n * Checks:\n * 1. Valid URL format\n * 2. Allowed protocol (default: http, https only)\n * 3. Not localhost/loopback (127.x.x.x, ::1, localhost)\n * 4. Not private IP (10.x, 172.16-31.x, 192.168.x)\n * 5. Not link-local (169.254.x.x — includes AWS/GCP/Azure metadata)\n * 6. Not blocked hostname\n * 7. No credentials in URL (user:pass@host)\n *\n * @param url - The URL string to validate\n * @param options - Validation options\n * @returns Validation result with safe flag and optional reason\n */\nexport function validateUrl(url: string, options: ValidateUrlOptions = {}): ValidateUrlResult {\n const {\n allowedProtocols = ['http:', 'https:'],\n blockedHosts = [],\n allowedHosts = [],\n allowLocalhost = false,\n allowPrivate = false,\n } = options;\n\n if (typeof url !== 'string' || url.trim() === '') {\n return { safe: false, reason: 'invalid URL: empty or not a string' };\n }\n\n // Parse URL\n let parsed: URL;\n try {\n parsed = new URL(url);\n } catch {\n return { safe: false, reason: 'invalid URL: failed to parse' };\n }\n\n // Check protocol\n if (!allowedProtocols.includes(parsed.protocol)) {\n return { safe: false, reason: `disallowed protocol: ${parsed.protocol}` };\n }\n\n // Check for credentials in URL (user:pass@host)\n if (parsed.username || parsed.password) {\n return { safe: false, reason: 'URL contains credentials' };\n }\n\n const hostname = parsed.hostname.toLowerCase();\n\n // Check explicit allowlist first (bypass IP checks)\n if (allowedHosts.some(h => hostname === h.toLowerCase())) {\n return { safe: true };\n }\n\n // Check explicit blocklist\n if (blockedHosts.some(h => hostname === h.toLowerCase())) {\n return { safe: false, reason: `blocked host: ${hostname}` };\n }\n\n // Check localhost/loopback\n if (!allowLocalhost) {\n if (\n hostname === 'localhost' ||\n hostname === '127.0.0.1' ||\n hostname === '[::1]' ||\n hostname === '::1' ||\n hostname === '0.0.0.0' ||\n hostname.endsWith('.localhost')\n ) {\n return { safe: false, reason: 'loopback address' };\n }\n\n // Check 127.x.x.x range\n if (/^127\\.\\d{1,3}\\.\\d{1,3}\\.\\d{1,3}$/.test(hostname)) {\n return { safe: false, reason: 'loopback address' };\n }\n }\n\n // Check decimal IP (e.g., 2130706433 = 127.0.0.1)\n if (!allowLocalhost || !allowPrivate) {\n const decimalCheck = checkDecimalIp(hostname, allowLocalhost, allowPrivate);\n if (decimalCheck) {\n return { safe: false, reason: decimalCheck };\n }\n }\n\n // Check octal IP (e.g., 0177.0.0.1 = 127.0.0.1)\n if (!allowLocalhost || !allowPrivate) {\n const octalCheck = checkOctalIp(hostname, allowLocalhost, allowPrivate);\n if (octalCheck) {\n return { safe: false, reason: octalCheck };\n }\n }\n\n // Check private/internal IPs\n if (!allowPrivate) {\n const privateCheck = checkPrivateIp(hostname);\n if (privateCheck) {\n return { safe: false, reason: privateCheck };\n }\n }\n\n return { safe: true };\n}\n\n/**\n * Convenience wrapper that returns true/false.\n *\n * @param url - The URL to check\n * @param options - Validation options\n * @returns true if the URL is safe to fetch\n */\nexport function isUrlSafe(url: string, options: ValidateUrlOptions = {}): boolean {\n return validateUrl(url, options).safe;\n}\n\n/**\n * Check if a hostname is a private/internal IP address.\n * Returns the reason string if private, or null if not.\n */\nfunction checkPrivateIp(hostname: string): string | null {\n // 10.0.0.0/8\n if (/^10\\.\\d{1,3}\\.\\d{1,3}\\.\\d{1,3}$/.test(hostname)) {\n return 'private address (10.0.0.0/8)';\n }\n\n // 172.16.0.0/12 (172.16.x.x - 172.31.x.x)\n const match172 = hostname.match(/^172\\.(\\d{1,3})\\.\\d{1,3}\\.\\d{1,3}$/);\n if (match172) {\n const second = parseInt(match172[1], 10);\n if (second >= 16 && second <= 31) {\n return 'private address (172.16.0.0/12)';\n }\n }\n\n // 192.168.0.0/16\n if (/^192\\.168\\.\\d{1,3}\\.\\d{1,3}$/.test(hostname)) {\n return 'private address (192.168.0.0/16)';\n }\n\n // 169.254.0.0/16 — link-local, includes cloud metadata endpoints\n // AWS: 169.254.169.254, GCP: metadata.google.internal, Azure: 169.254.169.254\n if (/^169\\.254\\.\\d{1,3}\\.\\d{1,3}$/.test(hostname)) {\n return 'link-local address (169.254.0.0/16)';\n }\n\n // 0.0.0.0/8 (current network)\n if (/^0\\.\\d{1,3}\\.\\d{1,3}\\.\\d{1,3}$/.test(hostname)) {\n return 'current network address (0.0.0.0/8)';\n }\n\n // Cloud metadata hostnames\n if (\n hostname === 'metadata.google.internal' ||\n hostname === 'metadata.internal' ||\n hostname === 'metadata.azure.internal'\n ) {\n return 'cloud metadata endpoint';\n }\n\n // IPv6 private ranges (bracket-wrapped in URLs)\n let ipv6 = hostname.replace(/^\\[|\\]$/g, '');\n // Strip zone ID (e.g., ::1%eth0 → ::1)\n const zoneIdx = ipv6.indexOf('%');\n if (zoneIdx !== -1) {\n ipv6 = ipv6.slice(0, zoneIdx);\n }\n if (\n ipv6 === '::1' ||\n ipv6 === '::' ||\n /^fc[0-9a-f]{2}:/i.test(ipv6) ||\n /^fd[0-9a-f]{2}:/i.test(ipv6) ||\n /^fe80:/i.test(ipv6) ||\n /^ff[0-9a-f]{2}:/i.test(ipv6) // IPv6 multicast (ff00::/8)\n ) {\n return 'private IPv6 address';\n }\n\n // IPv6-mapped IPv4 — dotted form (::ffff:127.0.0.1)\n const mappedDotted = ipv6.match(/^::ffff:(\\d{1,3}\\.\\d{1,3}\\.\\d{1,3}\\.\\d{1,3})$/i);\n if (mappedDotted) {\n const mappedIp = mappedDotted[1];\n if (/^127\\.\\d{1,3}\\.\\d{1,3}\\.\\d{1,3}$/.test(mappedIp)) {\n return 'IPv6-mapped loopback address';\n }\n const mappedCheck = checkPrivateIp(mappedIp);\n if (mappedCheck) {\n return `IPv6-mapped ${mappedCheck}`;\n }\n }\n\n // IPv6-mapped IPv4 — hex form (::ffff:7f00:1 = 127.0.0.1)\n // Node's URL parser normalizes ::ffff:a.b.c.d to ::ffff:XXYY:ZZWW\n const mappedHex = ipv6.match(/^::ffff:([0-9a-f]{1,4}):([0-9a-f]{1,4})$/i);\n if (mappedHex) {\n const hi = parseInt(mappedHex[1], 16);\n const lo = parseInt(mappedHex[2], 16);\n const a = (hi >> 8) & 0xFF;\n const b = hi & 0xFF;\n const c = (lo >> 8) & 0xFF;\n const d = lo & 0xFF;\n const dotted = `${a}.${b}.${c}.${d}`;\n if (a === 127) {\n return 'IPv6-mapped loopback address';\n }\n const hexCheck = checkPrivateIp(dotted);\n if (hexCheck) {\n return `IPv6-mapped ${hexCheck}`;\n }\n }\n\n return null;\n}\n\n/**\n * Parse a decimal integer as an IPv4 address and check if it's private/loopback.\n * e.g., 2130706433 = 127.0.0.1, 167772160 = 10.0.0.0\n */\nfunction checkDecimalIp(hostname: string, allowLocalhost: boolean, allowPrivate: boolean): string | null {\n // Must be a pure decimal integer\n if (!/^\\d+$/.test(hostname)) return null;\n\n const num = parseInt(hostname, 10);\n if (isNaN(num) || num < 0 || num > 0xFFFFFFFF) return null;\n\n const a = (num >>> 24) & 0xFF;\n const b = (num >>> 16) & 0xFF;\n const c = (num >>> 8) & 0xFF;\n const d = num & 0xFF;\n const dotted = `${a}.${b}.${c}.${d}`;\n\n // Check loopback\n if (!allowLocalhost && a === 127) {\n return `loopback address (decimal IP: ${dotted})`;\n }\n\n // Check private ranges\n if (!allowPrivate) {\n const privateCheck = checkPrivateIp(dotted);\n if (privateCheck) {\n return `${privateCheck} (decimal IP: ${dotted})`;\n }\n }\n\n return null;\n}\n\n/**\n * Parse octal-notation IPv4 address and check if it's private/loopback.\n * e.g., 0177.0.0.1 = 127.0.0.1, 0x7f.0.0.1 = 127.0.0.1\n */\nfunction checkOctalIp(hostname: string, allowLocalhost: boolean, allowPrivate: boolean): string | null {\n // Must look like a dotted quad where at least one octet has a leading zero or 0x prefix\n const parts = hostname.split('.');\n if (parts.length !== 4) return null;\n\n // Check if any part uses octal (leading 0) or hex (0x) notation\n const hasAlternateNotation = parts.some(p => /^0[0-7]+$/.test(p) || /^0x[0-9a-fA-F]+$/i.test(p));\n if (!hasAlternateNotation) return null;\n\n const octets: number[] = [];\n for (const part of parts) {\n let val: number;\n if (/^0x[0-9a-fA-F]+$/i.test(part)) {\n val = parseInt(part, 16);\n } else if (/^0[0-7]*$/.test(part)) {\n val = parseInt(part, 8);\n } else if (/^\\d+$/.test(part)) {\n val = parseInt(part, 10);\n } else {\n return null;\n }\n if (val < 0 || val > 255) return null;\n octets.push(val);\n }\n\n const dotted = octets.join('.');\n\n // Check loopback\n if (!allowLocalhost && octets[0] === 127) {\n return `loopback address (octal IP: ${dotted})`;\n }\n\n // Check private ranges\n if (!allowPrivate) {\n const privateCheck = checkPrivateIp(dotted);\n if (privateCheck) {\n return `${privateCheck} (octal IP: ${dotted})`;\n }\n }\n\n return null;\n}\n","/**\n * @module @arcis/node/validation/url-async\n *\n * Async SSRF guard that closes the DNS-rebinding TOCTOU gap left open\n * by the synchronous `validateUrl` (sdk-vectors.md #31, issue #50).\n *\n * The synchronous `validateUrl` only checks the *string form* of the\n * hostname. It catches obvious cases — `127.0.0.1`, `10.0.0.1`,\n * `169.254.169.254` — but a hostname like `evil.com` passes through\n * even when its DNS A-record points to `10.0.0.1`, because resolution\n * happens later inside `fetch`. An attacker controlling the\n * `evil.com` zone can also rebind the answer between Arcis's check\n * and the actual TCP connect, which is the classic DNS TOCTOU.\n *\n * Two layers of fix shipped here:\n *\n * 1. **`validateUrlAsync(url, options)`** — runs the existing sync\n * `validateUrl` first, then `dns.lookup(hostname, { all: true })`,\n * then re-runs the same private-range check on every resolved\n * address. Returns the pinned IP list so callers can reuse it for\n * the actual connection (closing the TOCTOU window).\n *\n * 2. **`pinnedDnsLookup(ip)`** — returns a Node `lookup` callback\n * that resolves any hostname to the pre-validated IP. Wire this\n * into `https.request({ lookup })` / `http.request({ lookup })`\n * so the connection uses the IP Arcis already validated, not\n * whatever DNS returns at connect time. Pure stdlib — no undici,\n * no extra dep.\n *\n * 3. **`safeFollowRedirect(prev, location, options)`** — when the\n * server replies 30x, run the same async guard against the new\n * Location URL. Resolves the absolute URL using the previous\n * response URL as base. Caller decides whether to follow.\n *\n * The function signatures keep `lookup` injectable so tests can\n * substitute a fake resolver without monkey-patching `node:dns`.\n *\n * ```ts\n * import https from 'node:https';\n * import { validateUrlAsync, pinnedDnsLookup } from '@arcis/node';\n *\n * const result = await validateUrlAsync(url);\n * if (!result.safe) throw new Error(result.reason);\n *\n * https.get(url, { lookup: pinnedDnsLookup(result.resolvedIp!) }, (res) => {\n * // The TCP connect now goes to result.resolvedIp regardless of\n * // what DNS would say at this exact moment.\n * });\n * ```\n */\n\nimport * as dns from 'node:dns';\nimport { validateUrl, type ValidateUrlOptions, type ValidateUrlResult } from './url';\n\n/**\n * Subset of `dns.lookup`'s `{ all: true }` callback signature. Kept\n * narrow so a test fake can satisfy it without depending on Node's\n * full `LookupAddress` type.\n */\nexport type LookupAddress = { address: string; family: number };\n\n/**\n * Function shape compatible with `dns.lookup(hostname, { all: true })`.\n * Returns a list of resolved addresses. Tests inject a fake.\n */\nexport type DnsLookup = (hostname: string) => Promise<LookupAddress[]>;\n\nconst defaultLookup: DnsLookup = (hostname) =>\n new Promise((resolve, reject) => {\n dns.lookup(hostname, { all: true }, (err, addresses) => {\n if (err) reject(err);\n else resolve(addresses);\n });\n });\n\nexport interface ValidateUrlAsyncOptions extends ValidateUrlOptions {\n /**\n * DNS lookup function. Defaults to a Promise wrapper around\n * `dns.lookup(hostname, { all: true })`. Tests inject a stub.\n */\n lookup?: DnsLookup;\n /**\n * If true, accept the first non-private IP and ignore the rest.\n * Default false: every resolved IP must pass the private-range\n * check. Hosts with mixed-public/private answers (round-robin DNS\n * with one internal record) still fail-closed.\n */\n acceptFirstPublic?: boolean;\n}\n\nexport interface ValidateUrlAsyncResult extends ValidateUrlResult {\n /**\n * Single pinned IP (the first public address if all checks passed,\n * or undefined when the string-only synchronous validator already\n * decided — e.g., the hostname *was* a literal IP). Use this with\n * `pinnedDnsLookup()` to wire the actual fetch.\n */\n resolvedIp?: string;\n /** Every IP returned by DNS, in resolver order. */\n resolvedIps?: string[];\n}\n\n/**\n * Reuses the existing private-range check from the sync validator.\n * We re-run `validateUrl` with the resolved IP swapped in as the\n * URL host. That way every existing rule (link-local, decimal-IP,\n * cloud-metadata hostname, IPv6-mapped, etc.) applies post-DNS too,\n * without forking the rule list.\n */\nfunction checkResolvedIp(ip: string, options: ValidateUrlOptions): ValidateUrlResult {\n // Build a synthetic URL that hands the IP to validateUrl. The\n // protocol is irrelevant for the private-range check; pick http to\n // avoid IPv6 bracket questions.\n const isIpv6 = ip.includes(':');\n const host = isIpv6 ? `[${ip}]` : ip;\n // Strip credentials + allowedHosts/blockedHosts because they apply\n // to the original hostname, not the resolved IP. We're only\n // re-running the IP-range checks here.\n const { allowedProtocols, allowLocalhost, allowPrivate } = options;\n return validateUrl(`http://${host}/`, {\n allowedProtocols,\n allowLocalhost,\n allowPrivate,\n });\n}\n\n/**\n * Async SSRF guard with DNS resolution. Runs the sync validator\n * first, then resolves DNS and validates every returned IP against\n * the same private-range rules. Returns a pinned IP for the caller\n * to reuse.\n *\n * Failure modes (any returns `{ safe: false, reason }`):\n * - Sync validator already rejects (string-pattern fail).\n * - DNS lookup throws (NXDOMAIN, network error). Reason carries the\n * underlying error message.\n * - DNS returns no addresses.\n * - Any resolved address fails the private-range check (default) or\n * *all* fail it when `acceptFirstPublic` is true.\n */\nexport async function validateUrlAsync(\n url: string,\n options: ValidateUrlAsyncOptions = {},\n): Promise<ValidateUrlAsyncResult> {\n const sync = validateUrl(url, options);\n if (!sync.safe) return sync;\n\n // If the hostname is a literal IP, the sync validator has already\n // checked it. Skip the DNS round-trip.\n let parsed: URL;\n try {\n parsed = new URL(url);\n } catch {\n return { safe: false, reason: 'invalid URL: failed to parse' };\n }\n const host = parsed.hostname.replace(/^\\[|\\]$/g, '');\n if (isLiteralIp(host)) return { safe: true };\n\n // Allowed-hosts allowlist takes precedence in the sync validator\n // and also bypasses the IP check here. The contract: if you\n // explicitly allowed the hostname, you accept whatever DNS returns.\n if (options.allowedHosts?.some((h) => host.toLowerCase() === h.toLowerCase())) {\n return { safe: true };\n }\n\n const lookup = options.lookup ?? defaultLookup;\n let addresses: LookupAddress[];\n try {\n addresses = await lookup(host);\n } catch (err) {\n const msg = err instanceof Error ? err.message : String(err);\n return { safe: false, reason: `DNS lookup failed: ${msg}` };\n }\n\n if (addresses.length === 0) {\n return { safe: false, reason: 'DNS returned no addresses' };\n }\n\n const ips = addresses.map((a) => a.address);\n const acceptFirstPublic = options.acceptFirstPublic === true;\n let firstPublic: string | undefined;\n for (const ip of ips) {\n const ipResult = checkResolvedIp(ip, options);\n if (ipResult.safe) {\n if (firstPublic === undefined) firstPublic = ip;\n } else if (!acceptFirstPublic) {\n return {\n safe: false,\n reason: `resolved IP ${ip} is unsafe: ${ipResult.reason}`,\n resolvedIps: ips,\n };\n }\n }\n\n if (firstPublic === undefined) {\n return {\n safe: false,\n reason: 'all resolved IPs are private/loopback',\n resolvedIps: ips,\n };\n }\n\n return { safe: true, resolvedIp: firstPublic, resolvedIps: ips };\n}\n\n/**\n * Build a `lookup` callback that pins the resolution to a single\n * pre-validated IP, regardless of what DNS would say at connect time.\n * Drop into `https.request({ lookup })` / `http.request({ lookup })`.\n *\n * Closes the TOCTOU window between `validateUrlAsync` and the actual\n * TCP connect. The pinned IP must be one that already passed the\n * async validator — wiring it without that check defeats the purpose.\n *\n * The returned function matches Node's `dns.lookup` callback shape\n * for the `{ all: false, family: 0 }` case (single address). The\n * default Node http/https stack uses that shape.\n */\nexport function pinnedDnsLookup(\n ip: string,\n): (\n hostname: string,\n options: { family?: number; hints?: number; verbatim?: boolean },\n callback: (err: NodeJS.ErrnoException | null, address: string, family: number) => void,\n) => void {\n if (typeof ip !== 'string' || ip.trim() === '') {\n throw new TypeError('pinnedDnsLookup: ip must be a non-empty string');\n }\n const family = ip.includes(':') ? 6 : 4;\n return (_hostname, _options, callback) => {\n callback(null, ip, family);\n };\n}\n\n/**\n * Validate a redirect target with the same TOCTOU-aware pipeline.\n *\n * `prev` is the URL of the response that returned the 30x; `location`\n * is the raw `Location:` header value (which may be relative). The\n * function resolves `location` against `prev` per RFC 3986 then runs\n * `validateUrlAsync` on the absolute result.\n *\n * Use this on every hop of a redirect chain. Without it, a server\n * that you trust today can redirect tomorrow's request to\n * `http://169.254.169.254/`.\n */\nexport async function safeFollowRedirect(\n prev: string,\n location: string,\n options: ValidateUrlAsyncOptions = {},\n): Promise<ValidateUrlAsyncResult> {\n if (typeof location !== 'string' || location.trim() === '') {\n return { safe: false, reason: 'redirect Location is empty' };\n }\n let absolute: URL;\n try {\n absolute = new URL(location, prev);\n } catch {\n return { safe: false, reason: 'invalid redirect URL' };\n }\n return validateUrlAsync(absolute.toString(), options);\n}\n\n/**\n * Detect whether a hostname is a literal IPv4/IPv6 (with or without\n * IPv6 brackets stripped). Mirrors what the sync validator already\n * checks via dotted-quad / decimal / octal regexes; we only need it\n * to know whether to skip the DNS round-trip.\n */\nfunction isLiteralIp(host: string): boolean {\n // IPv4 dotted quad\n if (/^\\d{1,3}\\.\\d{1,3}\\.\\d{1,3}\\.\\d{1,3}$/.test(host)) return true;\n // Decimal IP (single integer)\n if (/^\\d+$/.test(host)) return true;\n // Octal/hex IP forms\n if (/^0[0-7x]/.test(host) && /^[0-9a-fx.]+$/i.test(host) && host.includes('.')) return true;\n // IPv6: contains a colon and no slashes/spaces\n if (host.includes(':') && !/[/\\s]/.test(host)) return true;\n return false;\n}\n","/**\n * @module @arcis/node/validation/redirect\n * Open Redirect prevention\n *\n * Prevents attackers from using your app to redirect users to malicious sites\n * via manipulated query parameters like ?returnUrl=http://evil.com\n *\n * @example\n * import { validateRedirect, isRedirectSafe } from '@arcis/node';\n *\n * // Block open redirects\n * validateRedirect('http://evil.com') // { safe: false, reason: 'absolute URL not in allowed hosts' }\n * validateRedirect('//evil.com') // { safe: false, reason: 'protocol-relative URL not in allowed hosts' }\n * validateRedirect('javascript:alert(1)') // { safe: false, reason: 'dangerous protocol: javascript:' }\n *\n * // Allow safe redirects\n * validateRedirect('/dashboard') // { safe: true }\n * validateRedirect('/users?page=2') // { safe: true }\n * validateRedirect('https://myapp.com/home', { allowedHosts: ['myapp.com'] }) // { safe: true }\n */\n\n/** Options for redirect validation */\nexport interface ValidateRedirectOptions {\n /** Hostnames that are allowed for absolute URL redirects */\n allowedHosts?: string[];\n /** Allow protocol-relative URLs (//example.com). Default: false */\n allowProtocolRelative?: boolean;\n /** Allowed protocols for absolute URLs. Default: ['http:', 'https:'] */\n allowedProtocols?: string[];\n}\n\n/** Result of redirect validation */\nexport interface ValidateRedirectResult {\n /** Whether the redirect URL is safe */\n safe: boolean;\n /** Reason the redirect was blocked (only set when safe=false) */\n reason?: string;\n}\n\n/** Protocols that can execute code or exfiltrate data */\nconst DANGEROUS_PROTOCOLS = /^(javascript|data|vbscript|blob):/i;\n\n/** Characters used to disguise URLs (tabs, newlines inside scheme) */\nconst CONTROL_CHARS = /[\\t\\n\\r]/g;\n\n/**\n * Validate a redirect URL to prevent open redirect attacks.\n *\n * Safe redirects:\n * - Relative paths: /dashboard, /users?page=2, ../settings\n * - Absolute URLs to allowed hosts (when configured)\n *\n * Blocked redirects:\n * - Absolute URLs to unknown hosts\n * - Protocol-relative URLs (//evil.com)\n * - javascript:, data:, vbscript:, blob: protocols\n * - Backslash-prefixed paths (\\\\evil.com — browser treats as //)\n * - URLs with control characters that could disguise the target\n *\n * @param url - The redirect target URL to validate\n * @param options - Validation options\n * @returns Validation result with safe flag and optional reason\n */\nexport function validateRedirect(\n url: string,\n options: ValidateRedirectOptions = {},\n): ValidateRedirectResult {\n const {\n allowedHosts = [],\n allowProtocolRelative = false,\n allowedProtocols = ['http:', 'https:'],\n } = options;\n\n if (typeof url !== 'string' || url.trim() === '') {\n return { safe: false, reason: 'invalid redirect: empty or not a string' };\n }\n\n // Strip control characters that could disguise the URL\n const cleaned = url.replace(CONTROL_CHARS, '');\n\n // Block dangerous protocols (javascript:, data:, etc.)\n const proto = cleaned.match(DANGEROUS_PROTOCOLS);\n if (proto) {\n return { safe: false, reason: `dangerous protocol: ${proto[0]}` };\n }\n\n // Block backslash-prefixed paths — browsers treat \\ as / in URLs\n // so \\evil.com or \\/evil.com could redirect to //evil.com\n if (cleaned.startsWith('\\\\')) {\n return { safe: false, reason: 'backslash-prefixed URL (browser treats as protocol-relative)' };\n }\n\n // Check protocol-relative URLs (//evil.com)\n if (cleaned.startsWith('//')) {\n if (!allowProtocolRelative) {\n // Still check allowedHosts\n const host = extractHost(cleaned);\n if (host && allowedHosts.some(h => host === h.toLowerCase())) {\n return { safe: true };\n }\n return { safe: false, reason: 'protocol-relative URL not in allowed hosts' };\n }\n const host = extractHost(cleaned);\n if (host && allowedHosts.length > 0 && !allowedHosts.some(h => host === h.toLowerCase())) {\n return { safe: false, reason: 'protocol-relative URL not in allowed hosts' };\n }\n return { safe: true };\n }\n\n // Check if it's an absolute URL (has scheme)\n let parsed: URL;\n try {\n parsed = new URL(cleaned);\n } catch {\n // Not a valid absolute URL — treat as relative path (safe)\n return { safe: true };\n }\n\n // If we got here, it parsed as an absolute URL\n // Check protocol\n if (!allowedProtocols.includes(parsed.protocol)) {\n return { safe: false, reason: `disallowed protocol: ${parsed.protocol}` };\n }\n\n // Check if host is in allowed list. Match against host:port form when\n // a non-default port is present, falling back to hostname only when\n // the URL uses a default port. parsed.port is \"\" for default ports\n // (80 for http, 443 for https), so hostWithPort equals hostname in\n // those cases. Non-default ports must be explicitly listed: a bare\n // 'myapp.com' entry does NOT permit redirects to 'myapp.com:9999'.\n const hostname = parsed.hostname.toLowerCase();\n const hostWithPort = parsed.port ? `${hostname}:${parsed.port}` : hostname;\n if (allowedHosts.length === 0) {\n return { safe: false, reason: 'absolute URL not in allowed hosts' };\n }\n\n if (!allowedHosts.some(h => h.toLowerCase() === hostWithPort)) {\n return { safe: false, reason: `host not allowed: ${hostWithPort}` };\n }\n\n return { safe: true };\n}\n\n/**\n * Convenience wrapper that returns true/false.\n *\n * @param url - The redirect URL to check\n * @param options - Validation options\n * @returns true if the redirect is safe\n */\nexport function isRedirectSafe(url: string, options: ValidateRedirectOptions = {}): boolean {\n return validateRedirect(url, options).safe;\n}\n\n/**\n * Extract host (with optional port) from a protocol-relative URL.\n * Returns hostname for default ports, \"hostname:port\" for non-default.\n * Optional userinfo (user:pass@) is stripped.\n */\nfunction extractHost(url: string): string | null {\n // //user:pass@hostname/path -> authority = \"user:pass@hostname\"\n // //hostname:port/path -> authority = \"hostname:port\"\n const match = url.match(/^\\/\\/([^/?#]+)/);\n if (!match) return null;\n // Strip userinfo if present\n const authority = match[1].includes('@')\n ? match[1].slice(match[1].indexOf('@') + 1)\n : match[1];\n return authority.toLowerCase();\n}\n","/**\n * @module @arcis/node/validation/email\n * Advanced email validation with disposable detection and typo suggestions.\n *\n * Three levels of validation:\n * 1. Syntax — RFC-compliant format checking\n * 2. Domain intelligence — disposable/free provider detection, typo correction\n * 3. MX verification — DNS MX record lookup (async, optional)\n *\n * @example\n * const result = validateEmail('user@tempmail.com');\n * // { valid: false, reason: 'disposable' }\n *\n * const result = validateEmail('user@gmial.com');\n * // { valid: true, reason: 'typo', suggestion: 'user@gmail.com' }\n */\n\nimport { promises as dns } from 'dns';\n\nexport interface EmailValidationOptions {\n /** Check for disposable email providers. Default: true */\n checkDisposable?: boolean;\n /** Suggest corrections for typos. Default: true */\n suggestTypoFix?: boolean;\n /** Verify MX records via DNS. Default: false */\n checkMx?: boolean;\n /** Additional blocked domains */\n blockedDomains?: string[];\n /** Additional allowed domains (bypasses disposable check) */\n allowedDomains?: string[];\n}\n\nexport interface EmailValidationResult {\n /** Whether the email is valid */\n valid: boolean;\n /** Reason for the result */\n reason: 'valid' | 'invalid_syntax' | 'disposable' | 'no_mx' | 'blocked' | 'typo';\n /** Suggested correction if a typo was detected */\n suggestion: string | null;\n /** Whether the domain is a free email provider */\n isFree: boolean;\n /** Whether the domain is a disposable email provider */\n isDisposable: boolean;\n /** The normalized email address */\n normalized: string;\n}\n\n// RFC 5321: local part max 64, domain max 255, total max 254\nconst MAX_EMAIL_LENGTH = 254;\nconst MAX_LOCAL_LENGTH = 64;\nconst MAX_DOMAIN_LENGTH = 255;\n\n/**\n * Strict email syntax regex.\n * - No consecutive dots in local part\n * - No leading/trailing dots in local part\n * - Domain must have at least one dot\n * - No spaces anywhere\n */\nconst EMAIL_SYNTAX = /^[a-zA-Z0-9.!#$%&'*+/=?^_`{|}~-]+@[a-zA-Z0-9](?:[a-zA-Z0-9-]{0,61}[a-zA-Z0-9])?(?:\\.[a-zA-Z0-9](?:[a-zA-Z0-9-]{0,61}[a-zA-Z0-9])?)*\\.[a-zA-Z]{2,}$/;\n\n/** Common free email providers */\nconst FREE_PROVIDERS = new Set([\n 'gmail.com', 'yahoo.com', 'hotmail.com', 'outlook.com', 'aol.com',\n 'protonmail.com', 'proton.me', 'icloud.com', 'mail.com', 'zoho.com',\n 'yandex.com', 'gmx.com', 'gmx.net', 'live.com', 'msn.com',\n 'me.com', 'mac.com', 'fastmail.com', 'tutanota.com', 'hey.com',\n]);\n\n/** Common disposable email domains */\nconst DISPOSABLE_DOMAINS = new Set([\n // Popular disposable services\n 'guerrillamail.com', 'guerrillamail.net', 'guerrillamail.org',\n 'tempmail.com', 'temp-mail.org', 'temp-mail.io',\n 'throwaway.email', 'throwaway.com',\n 'mailinator.com', 'mailinator.net',\n 'yopmail.com', 'yopmail.fr', 'yopmail.net',\n 'sharklasers.com', 'grr.la', 'guerrillamail.info',\n 'guerrillamail.biz', 'guerrillamail.de',\n 'trashmail.com', 'trashmail.me', 'trashmail.net',\n 'dispostable.com', 'maildrop.cc',\n 'mailnesia.com', 'tempail.com',\n 'mohmal.com', 'getnada.com',\n 'emailondeck.com', 'discard.email',\n 'fakeinbox.com', 'mailcatch.com',\n 'mintemail.com', 'tempr.email',\n 'tempinbox.com', 'burnermail.io',\n 'mailsac.com', 'harakirimail.com',\n 'tempmailo.com', 'emailfake.com',\n 'crazymailing.com', 'armyspy.com',\n 'dayrep.com', 'einrot.com',\n 'fleckens.hu', 'gustr.com',\n 'jourrapide.com', 'rhyta.com',\n 'superrito.com', 'teleworm.us',\n '10minutemail.com', '10minutemail.net',\n 'minutemail.com', 'tempsky.com',\n 'spamgourmet.com', 'mytrashmail.com',\n 'mailexpire.com', 'safetymail.info',\n 'filzmail.com', 'trashymail.com',\n 'sharkmail.com', 'jetable.org',\n 'nospam.ze.tc', 'trash-me.com',\n 'dodgit.com', 'mailmoat.com',\n 'spamfree24.org', 'incognitomail.org',\n 'tempomail.fr', 'ephemail.net',\n 'hidemail.de', 'spaml.de',\n 'uggsrock.com', 'binkmail.com',\n 'suremail.info', 'bugmenot.com',\n]);\n\n/** Common typos and their corrections */\nconst DOMAIN_TYPOS: Record<string, string> = {\n 'gmial.com': 'gmail.com',\n 'gmaill.com': 'gmail.com',\n 'gmai.com': 'gmail.com',\n 'gamil.com': 'gmail.com',\n 'gnail.com': 'gmail.com',\n 'gmal.com': 'gmail.com',\n 'gmil.com': 'gmail.com',\n 'gmail.co': 'gmail.com',\n 'gmail.cm': 'gmail.com',\n 'gmail.om': 'gmail.com',\n 'gmail.con': 'gmail.com',\n 'gmail.cim': 'gmail.com',\n 'gmail.comm': 'gmail.com',\n 'yahooo.com': 'yahoo.com',\n 'yaho.com': 'yahoo.com',\n 'yahoo.co': 'yahoo.com',\n 'yahoo.cm': 'yahoo.com',\n 'yahoo.con': 'yahoo.com',\n 'yahho.com': 'yahoo.com',\n 'hotmial.com': 'hotmail.com',\n 'hotmal.com': 'hotmail.com',\n 'hotmai.com': 'hotmail.com',\n 'hotmil.com': 'hotmail.com',\n 'hotmail.co': 'hotmail.com',\n 'hotmail.cm': 'hotmail.com',\n 'hotmail.con': 'hotmail.com',\n 'outlok.com': 'outlook.com',\n 'outloo.com': 'outlook.com',\n 'outlook.co': 'outlook.com',\n 'outlook.cm': 'outlook.com',\n 'protonmal.com': 'protonmail.com',\n 'protonmail.co': 'protonmail.com',\n 'icloud.co': 'icloud.com',\n 'icloud.cm': 'icloud.com',\n 'icoud.com': 'icloud.com',\n};\n\nfunction invalidResult(reason: EmailValidationResult['reason'], email: string): EmailValidationResult {\n return {\n valid: false,\n reason,\n suggestion: null,\n isFree: false,\n isDisposable: false,\n normalized: email,\n };\n}\n\n/**\n * Validate an email address with syntax checking, disposable detection,\n * and typo suggestions.\n *\n * @param email - Email address to validate\n * @param options - Validation options\n * @returns Validation result\n *\n * @example\n * validateEmail('user@gmail.com')\n * // { valid: true, reason: 'valid', isFree: true }\n *\n * validateEmail('user@tempmail.com')\n * // { valid: false, reason: 'disposable' }\n *\n * validateEmail('user@gmial.com')\n * // { valid: true, reason: 'typo', suggestion: 'user@gmail.com' }\n */\nexport function validateEmail(\n email: string,\n options: EmailValidationOptions = {}\n): EmailValidationResult {\n const {\n checkDisposable = true,\n suggestTypoFix = true,\n blockedDomains = [],\n allowedDomains = [],\n } = options;\n\n // Normalize\n const normalized = email.trim().toLowerCase();\n\n // Basic checks\n if (!normalized || normalized.length > MAX_EMAIL_LENGTH) {\n return invalidResult('invalid_syntax', normalized);\n }\n\n const atIndex = normalized.lastIndexOf('@');\n if (atIndex === -1) {\n return invalidResult('invalid_syntax', normalized);\n }\n\n const localPart = normalized.slice(0, atIndex);\n const domain = normalized.slice(atIndex + 1);\n\n // Length checks\n if (localPart.length === 0 || localPart.length > MAX_LOCAL_LENGTH) {\n return invalidResult('invalid_syntax', normalized);\n }\n if (domain.length === 0 || domain.length > MAX_DOMAIN_LENGTH) {\n return invalidResult('invalid_syntax', normalized);\n }\n\n // Consecutive dots in local part\n if (localPart.includes('..')) {\n return invalidResult('invalid_syntax', normalized);\n }\n\n // Leading/trailing dots in local part\n if (localPart.startsWith('.') || localPart.endsWith('.')) {\n return invalidResult('invalid_syntax', normalized);\n }\n\n // Full regex validation\n if (!EMAIL_SYNTAX.test(normalized)) {\n return invalidResult('invalid_syntax', normalized);\n }\n\n // Check if domain is explicitly allowed (bypass other checks)\n const allowedSet = new Set(allowedDomains.map(d => d.toLowerCase()));\n if (allowedSet.has(domain)) {\n return {\n valid: true,\n reason: 'valid',\n suggestion: null,\n isFree: FREE_PROVIDERS.has(domain),\n isDisposable: false,\n normalized,\n };\n }\n\n // Check blocked domains\n const blockedSet = new Set(blockedDomains.map(d => d.toLowerCase()));\n if (blockedSet.has(domain)) {\n return invalidResult('blocked', normalized);\n }\n\n // Check disposable\n const isDisposable = DISPOSABLE_DOMAINS.has(domain);\n if (checkDisposable && isDisposable) {\n return {\n valid: false,\n reason: 'disposable',\n suggestion: null,\n isFree: false,\n isDisposable: true,\n normalized,\n };\n }\n\n // Check typos\n const isFree = FREE_PROVIDERS.has(domain);\n if (suggestTypoFix && DOMAIN_TYPOS[domain]) {\n const corrected = `${localPart}@${DOMAIN_TYPOS[domain]}`;\n return {\n valid: true,\n reason: 'typo',\n suggestion: corrected,\n isFree: FREE_PROVIDERS.has(DOMAIN_TYPOS[domain]),\n isDisposable: false,\n normalized,\n };\n }\n\n return {\n valid: true,\n reason: 'valid',\n suggestion: null,\n isFree,\n isDisposable,\n normalized,\n };\n}\n\n/**\n * Verify that the email domain has MX records (can receive email).\n *\n * This performs a DNS lookup and requires network access.\n * Use for registration flows where you need high confidence.\n *\n * @param email - Email address to verify\n * @returns True if the domain has MX records\n *\n * @example\n * if (await verifyEmailMx('user@example.com')) {\n * // Domain can receive email\n * }\n */\nexport async function verifyEmailMx(email: string): Promise<boolean> {\n if (!isValidEmailSyntax(email)) return false;\n\n const atIndex = email.lastIndexOf('@');\n const domain = email.slice(atIndex + 1).trim().toLowerCase();\n if (!domain) return false;\n\n try {\n const records = await dns.resolveMx(domain);\n return records.length > 0;\n } catch {\n return false;\n }\n}\n\n/**\n * Quick check if an email address has valid syntax.\n * Faster than validateEmail() — just syntax, no domain intelligence.\n */\nexport function isValidEmailSyntax(email: string): boolean {\n const normalized = email.trim().toLowerCase();\n if (!normalized || normalized.length > MAX_EMAIL_LENGTH) return false;\n\n const atIndex = normalized.lastIndexOf('@');\n if (atIndex === -1) return false;\n\n const localPart = normalized.slice(0, atIndex);\n if (localPart.includes('..') || localPart.startsWith('.') || localPart.endsWith('.')) return false;\n\n return EMAIL_SYNTAX.test(normalized);\n}\n","/**\n * @module @arcis/node/logging/redactor\n * Safe logging with PII/secret redaction\n */\n\nimport { REDACTION, INPUT } from '../core/constants';\nimport type { LogOptions, SafeLogger } from '../core/types';\n\nconst LOG_LEVELS: Record<string, number> = {\n debug: 0,\n info: 1,\n warn: 2,\n error: 3,\n silent: 4,\n};\n\n/**\n * Create a safe logger that redacts sensitive data and prevents log injection.\n * \n * @param options - Logger configuration\n * @returns SafeLogger instance\n * \n * @example\n * const logger = createSafeLogger();\n * logger.info('User login', { email: 'user@test.com', password: 'secret' });\n * // Logs: { \"email\": \"user@test.com\", \"password\": \"[REDACTED]\" }\n * \n * @example\n * // With custom redact keys\n * const logger = createSafeLogger({ redactKeys: ['customToken', 'internalId'] });\n */\nexport function createSafeLogger(options: LogOptions = {}): SafeLogger {\n const {\n redactKeys = [],\n maxLength = REDACTION.DEFAULT_MAX_LENGTH,\n redactPatterns = [],\n level: minLevel = 'debug',\n } = options;\n\n const minLevelNum = LOG_LEVELS[minLevel] ?? 0;\n\n // Combine default and custom keys (lowercase for case-insensitive matching)\n const allRedactKeys = new Set([\n ...Array.from(REDACTION.SENSITIVE_KEYS),\n ...redactKeys.map(k => k.toLowerCase()),\n ]);\n\n /**\n * Redact sensitive data from an object recursively.\n */\n function redact(obj: unknown, depth = 0): unknown {\n if (depth > INPUT.MAX_RECURSION_DEPTH) return REDACTION.MAX_DEPTH;\n if (obj === null || obj === undefined) return obj;\n\n if (typeof obj === 'string') {\n return redactString(obj, maxLength, redactPatterns);\n }\n\n if (typeof obj !== 'object') return obj;\n\n if (Array.isArray(obj)) {\n return obj.map(item => redact(item, depth + 1));\n }\n\n const result: Record<string, unknown> = {};\n for (const [key, value] of Object.entries(obj as Record<string, unknown>)) {\n if (allRedactKeys.has(key.toLowerCase())) {\n result[key] = REDACTION.REPLACEMENT;\n } else {\n result[key] = redact(value, depth + 1);\n }\n }\n return result;\n }\n\n /**\n * Log a message at the specified level.\n */\n function log(level: string, message: string, data?: unknown): void {\n // Early exit: skip all work if message level is below minimum\n const levelNum = LOG_LEVELS[level] ?? 0;\n if (levelNum < minLevelNum) return;\n\n const entry: Record<string, unknown> = {\n timestamp: new Date().toISOString(),\n level,\n message: redactString(message, maxLength, redactPatterns),\n };\n\n if (data !== undefined) {\n entry.data = redact(data);\n }\n\n // eslint-disable-next-line no-console\n console.log(JSON.stringify(entry));\n }\n\n return {\n log,\n info: (msg: string, data?: unknown) => log('info', msg, data),\n warn: (msg: string, data?: unknown) => log('warn', msg, data),\n error: (msg: string, data?: unknown) => log('error', msg, data),\n debug: (msg: string, data?: unknown) => log('debug', msg, data),\n };\n}\n\n/**\n * Redact a string value.\n * Removes newlines (log injection prevention), applies patterns, and truncates.\n */\nfunction redactString(str: string, maxLength: number, patterns: RegExp[]): string {\n // Remove newlines/tabs (log injection prevention) and genuine control characters.\n // Only strip C0/C1 control chars and null bytes — preserve all printable Unicode\n // (CJK, Cyrillic, Arabic, etc.) so multilingual content isn't silently lost.\n let safe = str\n .replace(/[\\r\\n\\t]/g, ' ')\n .replace(/[\\x00-\\x08\\x0B\\x0C\\x0E-\\x1F\\x7F\\x80-\\x9F]/g, '');\n\n // Apply custom redaction patterns\n for (const pattern of patterns) {\n safe = safe.replace(pattern, REDACTION.REPLACEMENT);\n }\n\n // Truncate if too long\n if (safe.length > maxLength) {\n safe = safe.substring(0, maxLength) + `...${REDACTION.TRUNCATED}`;\n }\n\n return safe;\n}\n\n/**\n * Create a redactor function for custom use.\n * \n * @param sensitiveKeys - Keys to redact\n * @returns Redactor function\n */\nexport function createRedactor(sensitiveKeys: string[] = []): (obj: unknown) => unknown {\n const allKeys = new Set([\n ...Array.from(REDACTION.SENSITIVE_KEYS),\n ...sensitiveKeys.map(k => k.toLowerCase()),\n ]);\n\n function redact(obj: unknown, depth = 0): unknown {\n if (depth > INPUT.MAX_RECURSION_DEPTH) return REDACTION.MAX_DEPTH;\n if (obj === null || obj === undefined) return obj;\n if (typeof obj !== 'object') return obj;\n\n if (Array.isArray(obj)) {\n return obj.map(item => redact(item, depth + 1));\n }\n\n const result: Record<string, unknown> = {};\n for (const [key, value] of Object.entries(obj as Record<string, unknown>)) {\n if (allKeys.has(key.toLowerCase())) {\n result[key] = REDACTION.REPLACEMENT;\n } else {\n result[key] = redact(value, depth + 1);\n }\n }\n return result;\n }\n\n return redact;\n}\n\n/**\n * Alias for createSafeLogger\n * @see createSafeLogger\n */\nexport const safeLog = createSafeLogger;\n","import type { TelemetryEvent, TelemetryOptions } from './types';\n\nconst DEFAULT_BATCH_SIZE = 50;\nconst MAX_BATCH_SIZE = 500; // matches server Zod schema upper bound\nconst DEFAULT_FLUSH_INTERVAL_MS = 5000;\nconst MIN_FLUSH_INTERVAL_MS = 500;\nconst FLUSH_TIMEOUT_MS = 10_000;\nconst DEFAULT_MAX_QUEUE_SIZE = 10_000;\n\ntype Listener = (err: Error) => void;\ntype OverflowListener = (droppedCount: number) => void;\n\n/**\n * In-memory batching client that ships `TelemetryEvent` objects to an\n * Arcis dashboard server.\n *\n * Design rules (spec/API_SPEC.md §9):\n * 1. `record()` is synchronous and never throws — safe to call from hot paths.\n * 2. Flushes trigger on batchSize OR flushIntervalMs, whichever comes first.\n * 3. Network errors are fail-open: they call `onError` (if provided) and\n * drop the batch. No retry, no disk persistence, no backpressure.\n * 4. `close()` attempts one final flush; safe to call multiple times.\n * 5. Interval timer uses `unref()` so it never holds the process open.\n */\nexport class TelemetryClient {\n private queue: TelemetryEvent[] = [];\n private readonly endpoint: string;\n private readonly apiKey: string | undefined;\n private readonly workspaceId: string | undefined;\n private readonly batchSize: number;\n private readonly flushIntervalMs: number;\n private readonly maxQueueSize: number;\n private readonly onError: Listener;\n private readonly onQueueOverflow: OverflowListener;\n private timer: ReturnType<typeof setInterval> | undefined;\n private flushing = false;\n private closed = false;\n private signalHandler: (() => void) | undefined;\n // Counts events dropped since the last successful flush. Resets to 0\n // each flush so onQueueOverflow callbacks see \"drops in this window\"\n // rather than a monotonic lifetime counter.\n private droppedSinceLastFlush = 0;\n\n constructor(options: TelemetryOptions) {\n if (!options.endpoint || typeof options.endpoint !== 'string') {\n throw new TypeError('TelemetryClient: `endpoint` is required');\n }\n\n this.endpoint = options.endpoint;\n this.apiKey = options.apiKey;\n this.workspaceId = options.workspaceId;\n this.batchSize = clamp(\n options.batchSize ?? DEFAULT_BATCH_SIZE,\n 1,\n MAX_BATCH_SIZE,\n );\n this.flushIntervalMs = Math.max(\n options.flushIntervalMs ?? DEFAULT_FLUSH_INTERVAL_MS,\n MIN_FLUSH_INTERVAL_MS,\n );\n // Cap the in-memory queue to bound memory under sustained dashboard\n // outage. Drop-oldest semantics preserve the most recent events,\n // which are usually the most relevant for incident triage.\n this.maxQueueSize = Math.max(\n options.maxQueueSize ?? DEFAULT_MAX_QUEUE_SIZE,\n this.batchSize,\n );\n this.onError = options.onError ?? (() => {\n // default: swallow silently (fail-open)\n });\n this.onQueueOverflow = options.onQueueOverflow ?? (() => {\n // default: silent — operators can opt in to logging\n });\n\n this.startTimer();\n }\n\n /**\n * Enqueue an event. Fast, synchronous, cannot throw.\n * Triggers a flush if the queue has reached `batchSize`.\n */\n record(event: TelemetryEvent): void {\n if (this.closed) return;\n this.queue.push(event);\n\n // Cap the queue at maxQueueSize. Drop oldest events (FIFO) so we keep\n // the freshest signal during a sustained outage. Without this cap, a\n // 24h dashboard outage at moderate traffic OOMs the worker.\n if (this.queue.length > this.maxQueueSize) {\n const drop = this.queue.length - this.maxQueueSize;\n this.queue.splice(0, drop);\n this.droppedSinceLastFlush += drop;\n try {\n this.onQueueOverflow(this.droppedSinceLastFlush);\n } catch {\n // overflow callback errors must not break record()\n }\n }\n\n if (this.queue.length >= this.batchSize) {\n // fire and forget\n void this.flush();\n }\n }\n\n /**\n * Manually flush the queue. Pulls up to `batchSize` events into a batch and\n * POSTs them. Returns a resolved promise on success OR on handled failure.\n * Never throws.\n */\n async flush(): Promise<void> {\n if (this.flushing) return;\n if (this.queue.length === 0) return;\n\n this.flushing = true;\n try {\n const batch = this.queue.splice(0, this.batchSize);\n await this.send(batch);\n // Successful flush — reset overflow counter so subsequent drops\n // start a fresh window. A connected dashboard \"clears\" the alert.\n this.droppedSinceLastFlush = 0;\n } catch (err) {\n this.safeNotify(err);\n } finally {\n this.flushing = false;\n }\n\n // Drain anything that arrived while we were flushing.\n if (!this.closed && this.queue.length > 0) {\n void this.flush();\n }\n }\n\n /**\n * Shut down: stop the interval timer and attempt one final flush.\n * Safe to call multiple times.\n */\n async close(): Promise<void> {\n if (this.closed) return;\n this.closed = true;\n\n if (this.timer !== undefined) {\n clearInterval(this.timer);\n this.timer = undefined;\n }\n\n if (this.signalHandler !== undefined) {\n process.off('SIGTERM', this.signalHandler);\n process.off('SIGINT', this.signalHandler);\n this.signalHandler = undefined;\n }\n\n // final best-effort flush\n try {\n await this.flush();\n } catch {\n // fail-open on shutdown\n }\n }\n\n /**\n * Register `SIGTERM` / `SIGINT` handlers that call `close()` to drain\n * the queue on graceful shutdown. Opt-in — libraries should not silently\n * attach global signal handlers. Safe to call multiple times.\n */\n installShutdownHooks(): void {\n if (this.signalHandler !== undefined || this.closed) return;\n const handler = (): void => {\n void this.close();\n };\n this.signalHandler = handler;\n process.once('SIGTERM', handler);\n process.once('SIGINT', handler);\n }\n\n /** Count of events currently waiting to be sent. Useful for tests. */\n get pendingCount(): number {\n return this.queue.length;\n }\n\n // ── internals ─────────────────────────────────────────────────────────\n\n private async send(batch: TelemetryEvent[]): Promise<void> {\n const headers: Record<string, string> = {\n 'content-type': 'application/json',\n };\n if (this.apiKey) headers['authorization'] = `Bearer ${this.apiKey}`;\n if (this.workspaceId) headers['x-workspace-id'] = this.workspaceId;\n\n const controller = new AbortController();\n const abortTimer = setTimeout(() => controller.abort(), FLUSH_TIMEOUT_MS);\n\n try {\n const res = await fetch(this.endpoint, {\n method: 'POST',\n headers,\n body: JSON.stringify({ events: batch }),\n signal: controller.signal,\n });\n\n if (!res.ok) {\n const text = await safeReadBody(res);\n throw new TelemetryHttpError(res.status, text);\n }\n } finally {\n clearTimeout(abortTimer);\n }\n }\n\n private startTimer(): void {\n this.timer = setInterval(() => {\n void this.flush();\n }, this.flushIntervalMs);\n\n // node-only: don't block process exit\n (this.timer as { unref?: () => void }).unref?.();\n }\n\n private safeNotify(err: unknown): void {\n try {\n this.onError(err instanceof Error ? err : new Error(String(err)));\n } catch {\n // user-provided hook must never bubble up\n }\n }\n}\n\nexport class TelemetryHttpError extends Error {\n constructor(\n public readonly status: number,\n public readonly responseBody: string,\n ) {\n super(`Telemetry ingest returned HTTP ${status}`);\n this.name = 'TelemetryHttpError';\n }\n}\n\nfunction clamp(value: number, min: number, max: number): number {\n if (!Number.isFinite(value)) return min;\n return Math.max(min, Math.min(max, Math.trunc(value)));\n}\n\nasync function safeReadBody(res: Response): Promise<string> {\n try {\n const text = await res.text();\n return text.slice(0, 500);\n } catch {\n return '';\n }\n}\n","/**\n * @module @arcis/node/middleware/main\n * Main arcis() middleware factory\n */\n\nimport type { Request, RequestHandler, Response, NextFunction } from 'express';\nimport type {\n ArcisOptions,\n ArcisFunction,\n ArcisMiddlewareStack,\n HeaderOptions,\n RateLimitOptions,\n SanitizeEvent,\n SanitizeOptions,\n} from '../core/types';\nimport { createHeaders } from './headers';\nimport { createRateLimiter } from './rate-limit';\nimport { createErrorHandler } from './error-handler';\nimport { createTelemetryEmitter, tapSanitizerThreats } from './telemetry';\nimport { createSanitizer, scanThreats } from '../sanitizers';\nimport { validate } from '../validation';\nimport { createSafeLogger } from '../logging';\nimport { TelemetryClient } from '../telemetry/client';\nimport type { TelemetryOptions } from '../telemetry/types';\n\n/**\n * Build TelemetryOptions from `ARCIS_*` environment variables when the user\n * didn't pass `telemetry` in `arcis({...})`. Returns undefined if `ARCIS_ENDPOINT`\n * isn't set — preserving zero-overhead opt-in.\n *\n * Recognized env vars:\n * - `ARCIS_ENDPOINT` (required to activate)\n * - `ARCIS_WORKSPACE_ID` (optional; sent as x-workspace-id)\n * - `ARCIS_KEY` (optional; sent as Authorization: Bearer <key>)\n * - `ARCIS_BATCH_SIZE` (optional integer; default 50)\n * - `ARCIS_FLUSH_INTERVAL_MS` (optional integer; default 5000)\n *\n * Explicit `options.telemetry` always wins over env. This preserves the\n * existing opt-in contract and lets callers override env in tests.\n */\nfunction buildTelemetryFromEnv(): TelemetryOptions | undefined {\n const env = typeof process !== 'undefined' ? process.env : undefined;\n const endpoint = env?.ARCIS_ENDPOINT;\n if (!endpoint) return undefined;\n const opts: TelemetryOptions = { endpoint };\n if (env?.ARCIS_WORKSPACE_ID) opts.workspaceId = env.ARCIS_WORKSPACE_ID;\n if (env?.ARCIS_KEY) opts.apiKey = env.ARCIS_KEY;\n const batch = env?.ARCIS_BATCH_SIZE ? parseInt(env.ARCIS_BATCH_SIZE, 10) : NaN;\n if (!Number.isNaN(batch)) opts.batchSize = batch;\n const flush = env?.ARCIS_FLUSH_INTERVAL_MS ? parseInt(env.ARCIS_FLUSH_INTERVAL_MS, 10) : NaN;\n if (!Number.isNaN(flush)) opts.flushIntervalMs = flush;\n return opts;\n}\n\n/**\n * Create Arcis middleware with all protections enabled.\n * \n * @param options - Configuration options\n * @returns Array of Express middleware\n * \n * @example\n * // Full protection (recommended)\n * app.use(arcis());\n * \n * @example\n * // Custom configuration\n * app.use(arcis({\n * rateLimit: { max: 50 },\n * headers: { frameOptions: 'SAMEORIGIN' }\n * }));\n * \n * @example\n * // Disable specific features\n * app.use(arcis({\n * rateLimit: false,\n * sanitize: { sql: false }\n * }));\n * \n * @example\n * // Cleanup on shutdown\n * const middleware = arcis();\n * app.use(middleware);\n * process.on('SIGTERM', () => middleware.close());\n */\n/**\n * Issue #47 — observer middleware. Pre-scans `req.body / req.query /\n * req.params / req.path` for threats and fires `onSanitize` for each hit.\n * Always calls `next()` (no blocking, no mutation) — control flow is\n * owned by the rate-limit and sanitizer middlewares downstream.\n *\n * Errors thrown from the user callback are caught and swallowed so a\n * buggy observer can't take down the request path.\n */\nfunction createSanitizeObserver(\n onSanitize: (event: SanitizeEvent) => void,\n): RequestHandler {\n return (req: Request, _res: Response, next: NextFunction) => {\n const fields: ReadonlyArray<readonly [string, unknown]> = [\n ['body', req.body],\n ['query', req.query],\n ['params', req.params],\n ['path', req.path],\n ];\n for (const [name, value] of fields) {\n const hit = scanThreats(value);\n if (!hit) continue;\n try {\n onSanitize({\n type: hit.vector,\n field: name,\n original: hit.matchedPattern,\n pattern: hit.matchedPattern,\n });\n } catch {\n // Observer must never break the response — fail-open.\n }\n }\n next();\n };\n}\n\n/**\n * Issue #47 — wraps a 429-emitting middleware so the response body is\n * suppressed in dry-run mode. The X-RateLimit-* headers the limiter set\n * BEFORE deciding to 429 still flow through (they were attached to the\n * response Header map by the limiter), giving observability without\n * actually blocking the request.\n *\n * The rate-limit middleware's 429 path is `res.status(429).json({...})`\n * followed by an early return (no `next()` call). To suppress, we\n * intercept `res.status` and on 429:\n * - flag `suppressed`,\n * - swallow the chained `.json(...)` (no body write),\n * - restore the originals,\n * - call `next()` ourselves so the rest of the middleware stack runs.\n *\n * This is monkey-patching with a tightly-scoped lifetime — restored\n * the moment we hand control downstream so no other middleware sees\n * the patched methods.\n */\nfunction suppressRateLimit429(handler: RequestHandler): RequestHandler {\n return (req, res, next) => {\n const originalStatus = res.status.bind(res);\n const originalJson = res.json.bind(res);\n let suppressed = false;\n let nextCalled = false;\n\n const restore = (): void => {\n res.status = originalStatus;\n res.json = originalJson;\n };\n\n res.status = ((code: number): Response => {\n if (code === 429) {\n suppressed = true;\n return res; // chainable; the .json below no-ops.\n }\n return originalStatus(code);\n }) as Response['status'];\n\n res.json = ((body: unknown): Response => {\n if (suppressed) {\n // Limiter's 429 path: it called .status(429).json(...) and then\n // returned without next(). Hand control to the rest of the chain\n // ourselves. Restore originals first so downstream sees a clean\n // ResponseWriter.\n restore();\n if (!nextCalled) {\n nextCalled = true;\n next();\n }\n return res;\n }\n return originalJson(body);\n }) as Response['json'];\n\n handler(req, res, (err) => {\n // Allow path: handler called next() itself. Restore methods so\n // downstream middleware operates on the unwrapped response.\n restore();\n if (!nextCalled) {\n nextCalled = true;\n next(err);\n }\n });\n };\n}\n\nexport function arcis(options: ArcisOptions = {}): ArcisMiddlewareStack {\n const middlewares: RequestHandler[] = [];\n const cleanupFns: (() => void)[] = [];\n const dryRun = options.dryRun === true;\n\n // Telemetry emitter — first, so latency includes the full middleware chain.\n // Opt-in: zero overhead unless options.telemetry.endpoint is set, OR\n // ARCIS_ENDPOINT is present in the environment. Explicit options win.\n let telemetryClient: TelemetryClient | undefined;\n const telemetryOpts = options.telemetry?.endpoint\n ? options.telemetry\n : buildTelemetryFromEnv();\n if (telemetryOpts) {\n const client = new TelemetryClient(telemetryOpts);\n telemetryClient = client;\n middlewares.push(createTelemetryEmitter(client));\n cleanupFns.push(() => {\n void client.close();\n });\n }\n\n // Security headers (always before rate-limit/sanitize)\n if (options.headers !== false) {\n const headerOpts: HeaderOptions = typeof options.headers === 'object'\n ? options.headers\n : {};\n middlewares.push(createHeaders(headerOpts));\n }\n\n // Issue #47 — observer pre-scan. Sits BEFORE the rate-limit + sanitizer so\n // the callback fires on every request that contains a threat, not just\n // those that survive rate-limiting. Skipped when no callback is set so\n // the default zero-overhead path is preserved.\n if (options.onSanitize) {\n middlewares.push(createSanitizeObserver(options.onSanitize));\n }\n\n // Rate limiting — emitter detects 429 from response status, no wrap needed.\n // Dry-run wraps the limiter so the limiter's 429 decision is silently\n // dropped (headers still set; request continues). X-RateLimit-* headers\n // surface either way so dashboards see the would-have-been decision.\n if (options.rateLimit !== false) {\n const rateLimitOpts: RateLimitOptions = typeof options.rateLimit === 'object'\n ? options.rateLimit\n : {};\n const rateLimiter = createRateLimiter(rateLimitOpts);\n middlewares.push(dryRun ? suppressRateLimit429(rateLimiter) : rateLimiter);\n cleanupFns.push(() => rateLimiter.close());\n }\n\n // Input sanitization — wrap with telemetry tap so SecurityThreatError\n // populates req.__arcis with vector/rule/severity for the emitter.\n // Dry-run forces block: false so the sanitizer can never short-circuit\n // with a 403; detection still happens via the observer above.\n if (options.sanitize !== false) {\n const sanitizeOpts: SanitizeOptions = typeof options.sanitize === 'object'\n ? { ...options.sanitize }\n : {};\n if (options.block && sanitizeOpts.block === undefined) {\n sanitizeOpts.block = true;\n }\n if (dryRun) {\n sanitizeOpts.block = false;\n }\n const sanitizer = createSanitizer(sanitizeOpts);\n middlewares.push(telemetryClient ? tapSanitizerThreats(sanitizer) : sanitizer);\n }\n\n // Attach close() directly on the array so callers can clean up without any-casts.\n const result = middlewares as ArcisMiddlewareStack;\n result.close = () => {\n for (const fn of cleanupFns) {\n fn();\n }\n };\n\n return result;\n}\n\n// Attach individual functions for granular use\nconst arcisWithMethods = arcis as ArcisFunction;\narcisWithMethods.sanitize = createSanitizer;\narcisWithMethods.rateLimit = createRateLimiter;\narcisWithMethods.headers = createHeaders;\narcisWithMethods.validate = validate;\narcisWithMethods.logger = createSafeLogger;\narcisWithMethods.errorHandler = createErrorHandler;\n\nexport { arcisWithMethods as arcisFunction };\nexport default arcisWithMethods;\n","/**\n * @module @arcis/node/utils/duration\n * Parse human-readable duration strings into milliseconds.\n *\n * Supports: ms, s, m, h, d\n *\n * @example\n * parseDuration('5m') // 300000\n * parseDuration('2h') // 7200000\n * parseDuration(60000) // 60000 (passthrough)\n * parseDuration('500ms') // 500\n */\n\n/** Maximum duration: ~49.7 days (uint32 max in ms) */\nconst MAX_DURATION_MS = 4_294_967_295;\n\nconst DURATION_REGEX = /^(\\d+(?:\\.\\d+)?)\\s*(ms|s|m|h|d)$/i;\n\nconst UNIT_TO_MS: Record<string, number> = {\n ms: 1,\n s: 1_000,\n m: 60_000,\n h: 3_600_000,\n d: 86_400_000,\n};\n\n/**\n * Parse a duration string or number into milliseconds.\n *\n * @param value - Duration string (e.g. \"5m\", \"2h\", \"30s\") or number (ms)\n * @returns Duration in milliseconds\n * @throws {Error} If the value is not a valid duration\n *\n * @example\n * parseDuration('15m') // 900000\n * parseDuration('1d') // 86400000\n * parseDuration('500ms') // 500\n * parseDuration(60000) // 60000\n */\nexport function parseDuration(value: string | number): number {\n if (typeof value === 'number') {\n if (!Number.isFinite(value) || value < 0) {\n throw new Error(`Invalid duration: ${value}. Must be a non-negative finite number.`);\n }\n return Math.min(Math.floor(value), MAX_DURATION_MS);\n }\n\n if (typeof value !== 'string' || value.trim() === '') {\n throw new Error(`Invalid duration: \"${value}\". Expected a duration string (e.g. \"5m\", \"2h\") or number.`);\n }\n\n const match = value.trim().match(DURATION_REGEX);\n if (!match) {\n throw new Error(\n `Invalid duration: \"${value}\". Expected format: <number><unit> where unit is ms, s, m, h, or d.`\n );\n }\n\n const amount = parseFloat(match[1]);\n const unit = match[2].toLowerCase();\n const ms = Math.floor(amount * UNIT_TO_MS[unit]);\n\n if (ms < 0 || ms > MAX_DURATION_MS) {\n throw new Error(`Duration \"${value}\" exceeds maximum allowed (${MAX_DURATION_MS}ms / ~49.7 days).`);\n }\n\n return ms;\n}\n\n/**\n * Format milliseconds into a human-readable duration string.\n *\n * @param ms - Duration in milliseconds\n * @returns Human-readable string (e.g. \"5m\", \"2h 30m\")\n */\nexport function formatDuration(ms: number): string {\n if (!Number.isFinite(ms) || ms < 0) return '0ms';\n\n if (ms < 1000) return `${ms}ms`;\n\n const days = Math.floor(ms / 86_400_000);\n const hours = Math.floor((ms % 86_400_000) / 3_600_000);\n const minutes = Math.floor((ms % 3_600_000) / 60_000);\n const seconds = Math.floor((ms % 60_000) / 1_000);\n\n const parts: string[] = [];\n if (days > 0) parts.push(`${days}d`);\n if (hours > 0) parts.push(`${hours}h`);\n if (minutes > 0) parts.push(`${minutes}m`);\n if (seconds > 0) parts.push(`${seconds}s`);\n\n return parts.join(' ') || '0ms';\n}\n","/**\n * @module @arcis/node/middleware/rate-limit-sliding\n * Sliding window rate limiting middleware.\n *\n * More accurate than fixed window — uses a weighted sum of the previous\n * and current window to approximate a true sliding window.\n *\n * Algorithm:\n * weight = (windowMs - elapsed) / windowMs\n * count = (prevWindow * weight) + currentWindow\n * allow = count < limit\n *\n * @example\n * app.use(createSlidingWindowLimiter({ max: 100, window: '15m' }));\n */\n\nimport type { Request, Response, NextFunction, RequestHandler } from 'express';\nimport { parseDuration } from '../utils/duration';\nimport { RATE_LIMIT } from '../core/constants';\n\nexport interface SlidingWindowOptions {\n /** Maximum requests per window. Default: 100 */\n max?: number;\n /** Window size in ms or duration string. Default: '1m' */\n window?: string | number;\n /** Error message when limit exceeded */\n message?: string;\n /** HTTP status code for rate limited responses. Default: 429 */\n statusCode?: number;\n /** Function to generate rate limit key from request */\n keyGenerator?: (req: Request) => string;\n /** Function to skip rate limiting for certain requests */\n skip?: (req: Request) => boolean;\n}\n\ninterface WindowEntry {\n count: number;\n startTime: number;\n}\n\nexport interface SlidingWindowMiddleware extends RequestHandler {\n close: () => void;\n}\n\n/**\n * Create sliding window rate limiter middleware.\n *\n * @example\n * // 100 requests per 15 minutes\n * app.use(createSlidingWindowLimiter({ max: 100, window: '15m' }));\n *\n * @example\n * // Strict API limit\n * app.use('/api', createSlidingWindowLimiter({ max: 30, window: '1m' }));\n */\nexport function createSlidingWindowLimiter(options: SlidingWindowOptions = {}): SlidingWindowMiddleware {\n const {\n max = RATE_LIMIT.DEFAULT_MAX_REQUESTS,\n window: windowOpt = RATE_LIMIT.DEFAULT_WINDOW_MS,\n message = RATE_LIMIT.DEFAULT_MESSAGE,\n statusCode = RATE_LIMIT.DEFAULT_STATUS_CODE,\n keyGenerator = (req) => req.ip ?? req.socket?.remoteAddress ?? 'unknown',\n skip,\n } = options;\n\n const windowMs = parseDuration(windowOpt);\n\n // Two windows per key: current and previous\n const currentWindows = Object.create(null) as Record<string, WindowEntry>;\n const previousWindows = Object.create(null) as Record<string, WindowEntry>;\n\n // Pin cleanup cadence to 30s regardless of windowMs. Scaling cleanup\n // with windowMs causes churn on short windows (1s window cleans every\n // second) and stale-entry buildup on long windows (1h window only\n // cleans hourly). 30s bounds memory growth without burning CPU; the\n // cutoff stays at `2 * windowMs` so legitimate active windows survive.\n const CLEANUP_INTERVAL_MS = 30_000;\n const cleanupInterval = setInterval(() => {\n const now = Date.now();\n const cutoff = now - windowMs * 2; // Keep 2 windows worth\n for (const key of Object.keys(previousWindows)) {\n if (previousWindows[key].startTime < cutoff) {\n delete previousWindows[key];\n }\n }\n for (const key of Object.keys(currentWindows)) {\n if (currentWindows[key].startTime < cutoff) {\n delete currentWindows[key];\n }\n }\n }, CLEANUP_INTERVAL_MS);\n\n if (typeof cleanupInterval.unref === 'function') {\n cleanupInterval.unref();\n }\n\n const handler: RequestHandler = (req: Request, res: Response, next: NextFunction) => {\n try {\n if (skip?.(req)) return next();\n\n const key = keyGenerator(req);\n const now = Date.now();\n\n // Determine current window boundaries\n const windowStart = Math.floor(now / windowMs) * windowMs;\n\n // Rotate windows if needed\n if (!currentWindows[key] || currentWindows[key].startTime < windowStart) {\n // Move current to previous\n if (currentWindows[key]) {\n previousWindows[key] = currentWindows[key];\n }\n currentWindows[key] = { count: 0, startTime: windowStart };\n }\n\n // Calculate weighted count BEFORE incrementing\n const elapsed = now - windowStart;\n const weight = Math.max(0, (windowMs - elapsed) / windowMs);\n const prevCount = previousWindows[key]?.count ?? 0;\n const estimatedCount = (prevCount * weight) + currentWindows[key].count + 1;\n\n const remaining = Math.max(0, Math.floor(max - estimatedCount));\n const resetMs = windowStart + windowMs - now;\n const resetSeconds = Math.max(1, Math.ceil(resetMs / 1000));\n\n // Set rate limit headers\n res.setHeader('X-RateLimit-Limit', max.toString());\n res.setHeader('X-RateLimit-Remaining', remaining.toString());\n res.setHeader('X-RateLimit-Reset', resetSeconds.toString());\n res.setHeader('X-RateLimit-Policy', `${max};w=${Math.floor(windowMs / 1000)}`);\n\n if (estimatedCount > max) {\n // Don't increment — rejected requests should not consume quota\n res.setHeader('Retry-After', resetSeconds.toString());\n res.status(statusCode).json({\n error: message,\n retryAfter: resetSeconds,\n });\n return;\n }\n\n // Only increment on allowed requests\n currentWindows[key].count++;\n\n next();\n } catch (error) {\n // Fail open\n // eslint-disable-next-line no-console\n console.error('[arcis] Sliding window rate limiter error:', error);\n next();\n }\n };\n\n const middleware = handler as SlidingWindowMiddleware;\n middleware.close = () => {\n clearInterval(cleanupInterval);\n };\n\n return middleware;\n}\n","/**\n * @module @arcis/node/middleware/rate-limit-token\n * Token bucket rate limiting middleware.\n *\n * Allows burst traffic while enforcing an average rate.\n * Tokens refill at a steady rate. Each request costs 1 token.\n *\n * Algorithm:\n * tokens = min(capacity, tokens + elapsed * refillRate)\n * if tokens >= cost: allow, subtract cost\n * else: deny\n *\n * @example\n * app.use(createTokenBucketLimiter({ capacity: 50, refillRate: 10 }));\n */\n\nimport type { Request, Response, NextFunction, RequestHandler } from 'express';\nimport { RATE_LIMIT } from '../core/constants';\n\nexport interface TokenBucketOptions {\n /** Maximum tokens (burst size). Default: 100 */\n capacity?: number;\n /** Tokens added per second. Default: 10 */\n refillRate?: number;\n /** Tokens consumed per request. Default: 1 */\n cost?: number;\n /** Error message when limit exceeded */\n message?: string;\n /** HTTP status code for rate limited responses. Default: 429 */\n statusCode?: number;\n /** Function to generate rate limit key from request */\n keyGenerator?: (req: Request) => string;\n /** Function to skip rate limiting for certain requests */\n skip?: (req: Request) => boolean;\n}\n\ninterface Bucket {\n tokens: number;\n lastRefill: number;\n}\n\nexport interface TokenBucketMiddleware extends RequestHandler {\n close: () => void;\n}\n\n/**\n * Create token bucket rate limiter middleware.\n *\n * @example\n * // Allow bursts of 50, sustained rate of 10/sec\n * app.use(createTokenBucketLimiter({ capacity: 50, refillRate: 10 }));\n *\n * @example\n * // Strict API: 5 requests burst, 1/sec sustained\n * app.use('/api/expensive', createTokenBucketLimiter({\n * capacity: 5,\n * refillRate: 1,\n * }));\n */\nexport function createTokenBucketLimiter(options: TokenBucketOptions = {}): TokenBucketMiddleware {\n const {\n capacity = 100,\n refillRate = 10,\n cost = 1,\n message = RATE_LIMIT.DEFAULT_MESSAGE,\n statusCode = RATE_LIMIT.DEFAULT_STATUS_CODE,\n keyGenerator = (req) => req.ip ?? req.socket?.remoteAddress ?? 'unknown',\n skip,\n } = options;\n\n if (capacity < 1) throw new RangeError(`Token bucket capacity must be >= 1, got ${capacity}`);\n if (refillRate <= 0) throw new RangeError(`Token bucket refillRate must be > 0, got ${refillRate}`);\n if (cost < 1) throw new RangeError(`Token bucket cost must be >= 1, got ${cost}`);\n if (cost > capacity) throw new RangeError(`Token bucket cost (${cost}) must be <= capacity (${capacity}), otherwise all requests are permanently denied`);\n\n const buckets = Object.create(null) as Record<string, Bucket>;\n\n // Cleanup stale buckets (full buckets that haven't been accessed)\n const cleanupInterval = setInterval(() => {\n const now = Date.now();\n const staleThreshold = (capacity / refillRate) * 1000 * 2; // 2x time to refill\n for (const key of Object.keys(buckets)) {\n if (now - buckets[key].lastRefill > staleThreshold) {\n delete buckets[key];\n }\n }\n }, 60_000);\n\n if (typeof cleanupInterval.unref === 'function') {\n cleanupInterval.unref();\n }\n\n function refillBucket(bucket: Bucket, now: number): void {\n const elapsed = (now - bucket.lastRefill) / 1000; // seconds\n const tokensToAdd = elapsed * refillRate;\n bucket.tokens = Math.min(capacity, bucket.tokens + tokensToAdd);\n bucket.lastRefill = now;\n }\n\n const handler: RequestHandler = (req: Request, res: Response, next: NextFunction) => {\n try {\n if (skip?.(req)) return next();\n\n const key = keyGenerator(req);\n const now = Date.now();\n\n // Get or create bucket\n if (!buckets[key]) {\n buckets[key] = { tokens: capacity, lastRefill: now };\n }\n\n const bucket = buckets[key];\n refillBucket(bucket, now);\n\n // Calculate retry-after (time until enough tokens are available)\n const retryAfterSec = bucket.tokens < cost\n ? Math.ceil((cost - bucket.tokens) / refillRate)\n : 0;\n\n // Set headers\n res.setHeader('X-RateLimit-Limit', capacity.toString());\n res.setHeader('X-RateLimit-Remaining', Math.floor(Math.max(0, bucket.tokens - cost)).toString());\n res.setHeader('X-RateLimit-Policy', `${capacity};w=${Math.floor(capacity / refillRate)};burst=${capacity}`);\n\n if (bucket.tokens < cost) {\n res.setHeader('Retry-After', retryAfterSec.toString());\n res.setHeader('X-RateLimit-Reset', retryAfterSec.toString());\n res.status(statusCode).json({\n error: message,\n retryAfter: retryAfterSec,\n });\n return;\n }\n\n // Consume token\n bucket.tokens -= cost;\n next();\n } catch (error) {\n // Fail open\n // eslint-disable-next-line no-console\n console.error('[arcis] Token bucket rate limiter error:', error);\n next();\n }\n };\n\n const middleware = handler as TokenBucketMiddleware;\n middleware.close = () => {\n clearInterval(cleanupInterval);\n };\n\n return middleware;\n}\n","/**\n * @module @arcis/node/middleware/cors\n * Safe CORS middleware with secure defaults\n */\n\nimport type { Request, Response, NextFunction, RequestHandler } from 'express';\n\n/** CORS configuration options */\nexport interface CorsOptions {\n /**\n * Allowed origins. Can be:\n * - A string: exact match (e.g., 'https://example.com')\n * - An array: whitelist of allowed origins\n * - A RegExp: pattern match (use with care)\n * - A function: custom validation `(origin) => boolean`\n * - `true`: reflect the request origin (DANGEROUS — only for dev)\n *\n * Default: none (no origin allowed). You must explicitly set this.\n */\n origin: string | string[] | RegExp | ((origin: string) => boolean) | true;\n\n /** Allowed HTTP methods. Default: ['GET', 'HEAD', 'PUT', 'PATCH', 'POST', 'DELETE'] */\n methods?: string[];\n\n /** Allowed headers. Default: ['Content-Type', 'Authorization'] */\n allowedHeaders?: string[];\n\n /** Headers exposed to the browser. Default: [] */\n exposedHeaders?: string[];\n\n /** Allow credentials (cookies, authorization headers). Default: false */\n credentials?: boolean;\n\n /** Preflight cache duration in seconds. Default: 600 (10 minutes) */\n maxAge?: number;\n\n /** Respond to preflight with 204 (no content). Default: true */\n preflightContinue?: boolean;\n}\n\nconst DEFAULT_METHODS = ['GET', 'HEAD', 'PUT', 'PATCH', 'POST', 'DELETE'];\nconst DEFAULT_HEADERS = ['Content-Type', 'Authorization'];\nconst DEFAULT_MAX_AGE = 600;\n\n/**\n * Check if an origin is allowed by the configured policy.\n */\nfunction isOriginAllowed(\n requestOrigin: string,\n allowed: CorsOptions['origin']\n): boolean {\n // 'null' origin is always blocked — sent by sandboxed iframes, data: URIs, etc.\n if (requestOrigin === 'null') return false;\n\n if (allowed === true) return true;\n\n if (typeof allowed === 'string') {\n return requestOrigin === allowed;\n }\n\n if (Array.isArray(allowed)) {\n return allowed.includes(requestOrigin);\n }\n\n if (allowed instanceof RegExp) {\n return allowed.test(requestOrigin);\n }\n\n if (typeof allowed === 'function') {\n return allowed(requestOrigin);\n }\n\n return false;\n}\n\n/**\n * Create safe CORS middleware.\n *\n * Unlike permissive CORS libraries, this enforces secure defaults:\n * - No wildcard `*` when credentials are enabled\n * - `null` origin is always blocked\n * - `Vary: Origin` is always set for proper caching\n * - You must explicitly configure allowed origins\n *\n * @param options - CORS configuration\n * @returns Express middleware\n *\n * @example\n * // Allow a single origin\n * app.use(safeCors({ origin: 'https://myapp.com' }));\n *\n * @example\n * // Allow multiple origins with credentials\n * app.use(safeCors({\n * origin: ['https://myapp.com', 'https://admin.myapp.com'],\n * credentials: true,\n * }));\n *\n * @example\n * // Development: allow all (NOT for production)\n * app.use(safeCors({ origin: true }));\n */\nexport function safeCors(options: CorsOptions): RequestHandler {\n const {\n origin,\n methods = DEFAULT_METHODS,\n allowedHeaders = DEFAULT_HEADERS,\n exposedHeaders = [],\n credentials = false,\n maxAge = DEFAULT_MAX_AGE,\n preflightContinue = true,\n } = options;\n\n return (req: Request, res: Response, next: NextFunction) => {\n const requestOrigin = req.headers.origin;\n\n // Always set Vary: Origin for proper caching\n res.setHeader('Vary', 'Origin');\n\n // No origin header = same-origin request, skip CORS headers\n if (!requestOrigin) {\n return next();\n }\n\n const allowed = isOriginAllowed(requestOrigin, origin);\n\n if (!allowed) {\n // Don't set any CORS headers — browser will block the request\n return next();\n }\n\n // Set Access-Control-Allow-Origin to the specific origin (not *)\n res.setHeader('Access-Control-Allow-Origin', requestOrigin);\n\n if (credentials) {\n res.setHeader('Access-Control-Allow-Credentials', 'true');\n }\n\n if (exposedHeaders.length > 0) {\n res.setHeader('Access-Control-Expose-Headers', exposedHeaders.join(', '));\n }\n\n // Handle preflight requests\n if (req.method === 'OPTIONS') {\n res.setHeader('Access-Control-Allow-Methods', methods.join(', '));\n res.setHeader('Access-Control-Allow-Headers', allowedHeaders.join(', '));\n res.setHeader('Access-Control-Max-Age', String(maxAge));\n\n if (preflightContinue) {\n res.status(204).end();\n return;\n }\n }\n\n next();\n };\n}\n\n/**\n * Alias for safeCors\n * @see safeCors\n */\nexport const createCors = safeCors;\n","/**\n * @module @arcis/node/middleware/cookies\n * Secure cookie defaults middleware\n */\n\nimport type { Request, Response, NextFunction, RequestHandler } from 'express';\n\n/** Cookie security configuration */\nexport interface SecureCookieOptions {\n /** Force HttpOnly on all cookies. Default: true */\n httpOnly?: boolean;\n /** Force Secure flag (HTTPS only). Default: true in production, false in dev */\n secure?: boolean;\n /** SameSite attribute. Default: 'Lax' */\n sameSite?: 'Strict' | 'Lax' | 'None' | false;\n /** Override Path attribute. Default: undefined (keep original) */\n path?: string;\n}\n\nconst COOKIE_ATTRS = {\n HTTP_ONLY: '; HttpOnly',\n SECURE: '; Secure',\n SAME_SITE_STRICT: '; SameSite=Strict',\n SAME_SITE_LAX: '; SameSite=Lax',\n SAME_SITE_NONE: '; SameSite=None',\n} as const;\n\n/**\n * Enforce secure defaults on a Set-Cookie header value.\n */\nexport function enforceSecureCookie(\n cookieStr: string,\n options: Required<Omit<SecureCookieOptions, 'path'>> & { path?: string }\n): string {\n const lower = cookieStr.toLowerCase();\n let result = cookieStr;\n\n // HttpOnly — prevent JavaScript access\n if (options.httpOnly && !lower.includes('httponly')) {\n result += COOKIE_ATTRS.HTTP_ONLY;\n }\n\n // Secure — HTTPS only\n if (options.secure && !lower.includes('; secure')) {\n result += COOKIE_ATTRS.SECURE;\n }\n\n // SameSite — CSRF protection\n if (options.sameSite !== false && !lower.includes('samesite')) {\n switch (options.sameSite) {\n case 'Strict':\n result += COOKIE_ATTRS.SAME_SITE_STRICT;\n break;\n case 'None':\n result += COOKIE_ATTRS.SAME_SITE_NONE;\n // SameSite=None requires Secure\n if (!result.toLowerCase().includes('; secure')) {\n result += COOKIE_ATTRS.SECURE;\n }\n break;\n case 'Lax':\n default:\n result += COOKIE_ATTRS.SAME_SITE_LAX;\n break;\n }\n }\n\n // Override path if specified\n if (options.path) {\n if (lower.includes('path=')) {\n result = result.replace(/;\\s*path=[^;]*/i, `; Path=${options.path}`);\n } else {\n result += `; Path=${options.path}`;\n }\n }\n\n return result;\n}\n\n/**\n * Create middleware that enforces secure cookie defaults.\n *\n * Intercepts Set-Cookie headers and adds missing security attributes:\n * - HttpOnly: prevents JavaScript access (XSS cookie theft)\n * - Secure: cookies only sent over HTTPS\n * - SameSite: CSRF protection\n *\n * @param options - Cookie security configuration\n * @returns Express middleware\n *\n * @example\n * // Enforce defaults on all cookies\n * app.use(secureCookieDefaults());\n *\n * @example\n * // Strict SameSite for sensitive apps\n * app.use(secureCookieDefaults({ sameSite: 'Strict' }));\n */\nexport function secureCookieDefaults(options: SecureCookieOptions = {}): RequestHandler {\n const isProduction = process.env.NODE_ENV === 'production';\n const resolved = {\n httpOnly: options.httpOnly ?? true,\n secure: options.secure ?? isProduction,\n sameSite: options.sameSite ?? 'Lax' as const,\n path: options.path,\n };\n\n // Fail loudly on incompatible combinations — silent misconfiguration is a\n // common footgun (e.g. SameSite=None without Secure is rejected by every\n // modern browser, producing a request that just silently loses cookies).\n if (resolved.sameSite === 'None' && resolved.secure === false) {\n throw new Error(\n '[arcis] secureCookieDefaults: sameSite=None requires secure=true (modern browsers reject the cookie otherwise)'\n );\n }\n if (resolved.httpOnly === false && resolved.secure === false && isProduction) {\n // Only a warning — some apps legitimately need non-HttpOnly cookies (e.g. CSRF double-submit).\n // But running both off in production is almost never intentional.\n // eslint-disable-next-line no-console\n console.warn(\n '[arcis] secureCookieDefaults: httpOnly and secure are both disabled in production — cookies will be readable by JS and sent over HTTP'\n );\n }\n\n return (_req: Request, res: Response, next: NextFunction) => {\n // Monkey-patch res.setHeader to intercept Set-Cookie\n const originalSetHeader = res.setHeader.bind(res);\n\n res.setHeader = function patchedSetHeader(name: string, value: string | number | readonly string[]) {\n if (name.toLowerCase() === 'set-cookie') {\n if (Array.isArray(value)) {\n value = value.map(v => enforceSecureCookie(String(v), resolved));\n } else {\n value = enforceSecureCookie(String(value), resolved);\n }\n }\n return originalSetHeader(name, value);\n } as typeof res.setHeader;\n\n next();\n };\n}\n\n/**\n * Alias for secureCookieDefaults\n * @see secureCookieDefaults\n */\nexport const createSecureCookies = secureCookieDefaults;\n","[\n {\n \"id\": \"ai-search-bot\",\n \"category\": \"AI_CRAWLER\",\n \"name\": \"ai-search-bot\",\n \"patterns\": [\n \"AISearchBot\"\n ],\n \"forbidden\": []\n },\n {\n \"id\": \"ai2-crawler\",\n \"category\": \"AI_CRAWLER\",\n \"name\": \"ai2-crawler\",\n \"patterns\": [\n \"AI2Bot\\\\s\"\n ],\n \"forbidden\": []\n },\n {\n \"id\": \"ai2-crawler-dolma\",\n \"category\": \"AI_CRAWLER\",\n \"name\": \"ai2-crawler-dolma\",\n \"patterns\": [\n \"Ai2Bot-Dolma\"\n ],\n \"forbidden\": []\n },\n {\n \"id\": \"aihit-crawler\",\n \"category\": \"AI_CRAWLER\",\n \"name\": \"aihit-crawler\",\n \"patterns\": [\n \"aiHitBot\"\n ],\n \"forbidden\": []\n },\n {\n \"id\": \"anthropic-ai-token\",\n \"category\": \"AI_CRAWLER\",\n \"name\": \"Anthropic\",\n \"patterns\": [\n \"anthropic-ai\"\n ],\n \"forbidden\": []\n },\n {\n \"id\": \"anthropic-crawler\",\n \"category\": \"AI_CRAWLER\",\n \"name\": \"ClaudeBot\",\n \"patterns\": [\n \"[cC]laude(?:[bB]ot|-[Ww]eb)\"\n ],\n \"forbidden\": []\n },\n {\n \"id\": \"anthropic-crawler-search\",\n \"category\": \"AI_CRAWLER\",\n \"name\": \"ClaudeSearchBot\",\n \"patterns\": [\n \"Claude-SearchBot\"\n ],\n \"forbidden\": []\n },\n {\n \"id\": \"anthropic-crawler-user\",\n \"category\": \"AI_CRAWLER\",\n \"name\": \"ClaudeUser\",\n \"patterns\": [\n \"Claude-User\"\n ],\n \"forbidden\": []\n },\n {\n \"id\": \"botify-crawler\",\n \"category\": \"AI_CRAWLER\",\n \"name\": \"botify-crawler\",\n \"patterns\": [\n \"botify\"\n ],\n \"forbidden\": []\n },\n {\n \"id\": \"bytedance-crawler\",\n \"category\": \"AI_CRAWLER\",\n \"name\": \"Bytespider\",\n \"patterns\": [\n \"Bytespider\"\n ],\n \"forbidden\": []\n },\n {\n \"id\": \"ccbot-crawler\",\n \"category\": \"AI_CRAWLER\",\n \"name\": \"CCBot\",\n \"patterns\": [\n \"CCBot\\\\/\"\n ],\n \"forbidden\": []\n },\n {\n \"id\": \"cohere-crawler\",\n \"category\": \"AI_CRAWLER\",\n \"name\": \"cohere-crawler\",\n \"patterns\": [\n \"cohere-ai\"\n ],\n \"forbidden\": []\n },\n {\n \"id\": \"diffbot-crawler\",\n \"category\": \"AI_CRAWLER\",\n \"name\": \"diffbot-crawler\",\n \"patterns\": [\n \"Diffbot\\\\/\"\n ],\n \"forbidden\": []\n },\n {\n \"id\": \"friendlycrawler\",\n \"category\": \"AI_CRAWLER\",\n \"name\": \"friendlycrawler\",\n \"patterns\": [\n \"FriendlyCrawler\"\n ],\n \"forbidden\": []\n },\n {\n \"id\": \"glutenfreepleasure-crawler\",\n \"category\": \"AI_CRAWLER\",\n \"name\": \"glutenfreepleasure-crawler\",\n \"patterns\": [\n \"Gluten Free Crawler\\\\/\"\n ],\n \"forbidden\": []\n },\n {\n \"id\": \"imagesift-crawler\",\n \"category\": \"AI_CRAWLER\",\n \"name\": \"imagesift-crawler\",\n \"patterns\": [\n \"ImagesiftBot\"\n ],\n \"forbidden\": []\n },\n {\n \"id\": \"infegy-crawler\",\n \"category\": \"AI_CRAWLER\",\n \"name\": \"infegy-crawler\",\n \"patterns\": [\n \"collection@infegy\\\\.com\"\n ],\n \"forbidden\": []\n },\n {\n \"id\": \"integralads-crawler\",\n \"category\": \"AI_CRAWLER\",\n \"name\": \"integralads-crawler\",\n \"patterns\": [\n \"IAS crawler\"\n ],\n \"forbidden\": []\n },\n {\n \"id\": \"leadcrunch-crawler\",\n \"category\": \"AI_CRAWLER\",\n \"name\": \"leadcrunch-crawler\",\n \"patterns\": [\n \"CrunchBot\"\n ],\n \"forbidden\": []\n },\n {\n \"id\": \"mediatoolkit-crawler\",\n \"category\": \"AI_CRAWLER\",\n \"name\": \"mediatoolkit-crawler\",\n \"patterns\": [\n \"Mediatoolkitbot\"\n ],\n \"forbidden\": []\n },\n {\n \"id\": \"meta-externalagent\",\n \"category\": \"AI_CRAWLER\",\n \"name\": \"Meta AI\",\n \"patterns\": [\n \"meta-externalagent\"\n ],\n \"forbidden\": []\n },\n {\n \"id\": \"ntent-crawler\",\n \"category\": \"AI_CRAWLER\",\n \"name\": \"ntent-crawler\",\n \"patterns\": [\n \"NTENTbot\"\n ],\n \"forbidden\": []\n },\n {\n \"id\": \"omgili-crawler\",\n \"category\": \"AI_CRAWLER\",\n \"name\": \"omgili-crawler\",\n \"patterns\": [\n \"omgili\"\n ],\n \"forbidden\": []\n },\n {\n \"id\": \"openai-crawler\",\n \"category\": \"AI_CRAWLER\",\n \"name\": \"GPTBot\",\n \"patterns\": [\n \"GPTBot\"\n ],\n \"forbidden\": []\n },\n {\n \"id\": \"openai-crawler-user\",\n \"category\": \"AI_CRAWLER\",\n \"name\": \"ChatGPTUser\",\n \"patterns\": [\n \"ChatGPT-User\"\n ],\n \"forbidden\": []\n },\n {\n \"id\": \"perplexity-crawler\",\n \"category\": \"AI_CRAWLER\",\n \"name\": \"PerplexityBot\",\n \"patterns\": [\n \"PerplexityBot\\\\/\"\n ],\n \"forbidden\": []\n },\n {\n \"id\": \"perplexity-user\",\n \"category\": \"AI_CRAWLER\",\n \"name\": \"perplexity-user\",\n \"patterns\": [\n \"Perplexity-User\\\\/\"\n ],\n \"forbidden\": []\n },\n {\n \"id\": \"primal-crawler\",\n \"category\": \"AI_CRAWLER\",\n \"name\": \"primal-crawler\",\n \"patterns\": [\n \"Primalbot\"\n ],\n \"forbidden\": []\n },\n {\n \"id\": \"sbintuitions-bot\",\n \"category\": \"AI_CRAWLER\",\n \"name\": \"sbintuitions-bot\",\n \"patterns\": [\n \"SBIntuitionsBot\\\\/\"\n ],\n \"forbidden\": []\n },\n {\n \"id\": \"searchatlas-crawler\",\n \"category\": \"AI_CRAWLER\",\n \"name\": \"searchatlas-crawler\",\n \"patterns\": [\n \"SearchAtlas\"\n ],\n \"forbidden\": []\n },\n {\n \"id\": \"sentione-crawler\",\n \"category\": \"AI_CRAWLER\",\n \"name\": \"sentione-crawler\",\n \"patterns\": [\n \"SentiBot\"\n ],\n \"forbidden\": []\n },\n {\n \"id\": \"storygize-crawler\",\n \"category\": \"AI_CRAWLER\",\n \"name\": \"storygize-crawler\",\n \"patterns\": [\n \"StorygizeBot\"\n ],\n \"forbidden\": []\n },\n {\n \"id\": \"timpi-crawler\",\n \"category\": \"AI_CRAWLER\",\n \"name\": \"timpi-crawler\",\n \"patterns\": [\n \"Timpibot\"\n ],\n \"forbidden\": []\n },\n {\n \"id\": \"velen-crawler\",\n \"category\": \"AI_CRAWLER\",\n \"name\": \"velen-crawler\",\n \"patterns\": [\n \"VelenPublicWebCrawler\"\n ],\n \"forbidden\": []\n },\n {\n \"id\": \"webzio-crawler-ai\",\n \"category\": \"AI_CRAWLER\",\n \"name\": \"webzio-crawler-ai\",\n \"patterns\": [\n \"webzio-extended\"\n ],\n \"forbidden\": []\n },\n {\n \"id\": \"you-crawler\",\n \"category\": \"AI_CRAWLER\",\n \"name\": \"you-crawler\",\n \"patterns\": [\n \"YouBot\"\n ],\n \"forbidden\": []\n },\n {\n \"id\": \"cypress\",\n \"category\": \"AUTOMATED\",\n \"name\": \"Cypress\",\n \"patterns\": [\n \"[Cc]ypress\"\n ],\n \"forbidden\": []\n },\n {\n \"id\": \"fake-msie6\",\n \"category\": \"AUTOMATED\",\n \"name\": \"Fake IE6\",\n \"patterns\": [\n \"MSIE 6\\\\.0\"\n ],\n \"forbidden\": []\n },\n {\n \"id\": \"headless-chrome\",\n \"category\": \"AUTOMATED\",\n \"name\": \"Headless Chrome\",\n \"patterns\": [\n \"HeadlessChrome\"\n ],\n \"forbidden\": []\n },\n {\n \"id\": \"javascript-phantom\",\n \"category\": \"AUTOMATED\",\n \"name\": \"PhantomJS\",\n \"patterns\": [\n \"PhantomJS\"\n ],\n \"forbidden\": []\n },\n {\n \"id\": \"playwright\",\n \"category\": \"AUTOMATED\",\n \"name\": \"Playwright\",\n \"patterns\": [\n \"[Pp]laywright\"\n ],\n \"forbidden\": []\n },\n {\n \"id\": \"puppeteer\",\n \"category\": \"AUTOMATED\",\n \"name\": \"Puppeteer\",\n \"patterns\": [\n \"[Pp]uppeteer\"\n ],\n \"forbidden\": []\n },\n {\n \"id\": \"selenium\",\n \"category\": \"AUTOMATED\",\n \"name\": \"Selenium\",\n \"patterns\": [\n \"[Ss]elenium\"\n ],\n \"forbidden\": []\n },\n {\n \"id\": \"webdriver\",\n \"category\": \"AUTOMATED\",\n \"name\": \"WebDriver\",\n \"patterns\": [\n \"[Ww]ebdriver\"\n ],\n \"forbidden\": []\n },\n {\n \"id\": \"amazon-route53-health-check\",\n \"category\": \"MONITORING\",\n \"name\": \"amazon-route53-health-check\",\n \"patterns\": [\n \"Amazon Route 53 Health Check Service\"\n ],\n \"forbidden\": []\n },\n {\n \"id\": \"azure-app-insights\",\n \"category\": \"MONITORING\",\n \"name\": \"azure-app-insights\",\n \"patterns\": [\n \"AppInsights\"\n ],\n \"forbidden\": []\n },\n {\n \"id\": \"betterstack-monitor\",\n \"category\": \"MONITORING\",\n \"name\": \"betterstack-monitor\",\n \"patterns\": [\n \"Better Stack\"\n ],\n \"forbidden\": []\n },\n {\n \"id\": \"betteruptime-monitor\",\n \"category\": \"MONITORING\",\n \"name\": \"betteruptime-monitor\",\n \"patterns\": [\n \"Better Uptime Bot\"\n ],\n \"forbidden\": []\n },\n {\n \"id\": \"brandverity-crawler\",\n \"category\": \"MONITORING\",\n \"name\": \"brandverity-crawler\",\n \"patterns\": [\n \"BrandVerity\"\n ],\n \"forbidden\": []\n },\n {\n \"id\": \"censys-inspect\",\n \"category\": \"MONITORING\",\n \"name\": \"censys-inspect\",\n \"patterns\": [\n \"CensysInspect\\\\/\"\n ],\n \"forbidden\": []\n },\n {\n \"id\": \"changedetection-crawler\",\n \"category\": \"MONITORING\",\n \"name\": \"changedetection-crawler\",\n \"patterns\": [\n \"changedetection\"\n ],\n \"forbidden\": []\n },\n {\n \"id\": \"checkly-monitor\",\n \"category\": \"MONITORING\",\n \"name\": \"checkly-monitor\",\n \"patterns\": [\n \"Checkly\\\\/\"\n ],\n \"forbidden\": []\n },\n {\n \"id\": \"cloudflare-healthchecks\",\n \"category\": \"MONITORING\",\n \"name\": \"cloudflare-healthchecks\",\n \"patterns\": [\n \"Cloudflare-Healthchecks\"\n ],\n \"forbidden\": []\n },\n {\n \"id\": \"cloudflare-security-center\",\n \"category\": \"MONITORING\",\n \"name\": \"cloudflare-security-center\",\n \"patterns\": [\n \"https:\\\\/\\\\/developers\\\\.cloudflare\\\\.com\\\\/security-center\\\\/\"\n ],\n \"forbidden\": []\n },\n {\n \"id\": \"cloudflare-ssl-detector\",\n \"category\": \"MONITORING\",\n \"name\": \"cloudflare-ssl-detector\",\n \"patterns\": [\n \"Cloudflare-SSLDetector\"\n ],\n \"forbidden\": []\n },\n {\n \"id\": \"cloudflare-traffic-manager\",\n \"category\": \"MONITORING\",\n \"name\": \"cloudflare-traffic-manager\",\n \"patterns\": [\n \"Cloudflare-Traffic-Manager\"\n ],\n \"forbidden\": []\n },\n {\n \"id\": \"datadog-monitor-synthetics\",\n \"category\": \"MONITORING\",\n \"name\": \"Datadog\",\n \"patterns\": [\n \"Datadog\\\\/{0,1}Synthetics\"\n ],\n \"forbidden\": []\n },\n {\n \"id\": \"deadlinkchecker\",\n \"category\": \"MONITORING\",\n \"name\": \"deadlinkchecker\",\n \"patterns\": [\n \"deadlinkchecker\"\n ],\n \"forbidden\": []\n },\n {\n \"id\": \"disqus-crawler\",\n \"category\": \"MONITORING\",\n \"name\": \"disqus-crawler\",\n \"patterns\": [\n \"Disqus\"\n ],\n \"forbidden\": []\n },\n {\n \"id\": \"dubbot-crawler\",\n \"category\": \"MONITORING\",\n \"name\": \"dubbot-crawler\",\n \"patterns\": [\n \"Dubbotbot\"\n ],\n \"forbidden\": []\n },\n {\n \"id\": \"dynatrace-monitor\",\n \"category\": \"MONITORING\",\n \"name\": \"dynatrace-monitor\",\n \"patterns\": [\n \"RuxitSynthetic\"\n ],\n \"forbidden\": []\n },\n {\n \"id\": \"freewebmonitoring-monitor\",\n \"category\": \"MONITORING\",\n \"name\": \"freewebmonitoring-monitor\",\n \"patterns\": [\n \"FreeWebMonitoring SiteChecker\"\n ],\n \"forbidden\": []\n },\n {\n \"id\": \"freshworks-monitor\",\n \"category\": \"MONITORING\",\n \"name\": \"freshworks-monitor\",\n \"patterns\": [\n \"FreshpingBot\"\n ],\n \"forbidden\": []\n },\n {\n \"id\": \"google-certificates-bridge\",\n \"category\": \"MONITORING\",\n \"name\": \"google-certificates-bridge\",\n \"patterns\": [\n \"Google-Certificates-Bridge\"\n ],\n \"forbidden\": []\n },\n {\n \"id\": \"google-site-verification\",\n \"category\": \"MONITORING\",\n \"name\": \"google-site-verification\",\n \"patterns\": [\n \"Google-Site-Verification\"\n ],\n \"forbidden\": []\n },\n {\n \"id\": \"google-structured-data-testing-tool\",\n \"category\": \"MONITORING\",\n \"name\": \"google-structured-data-testing-tool\",\n \"patterns\": [\n \"Google-Structured-Data-Testing-Tool\"\n ],\n \"forbidden\": []\n },\n {\n \"id\": \"hubspot-crawler\",\n \"category\": \"MONITORING\",\n \"name\": \"HubSpotBot\",\n \"patterns\": [\n \"HubSpot\"\n ],\n \"forbidden\": []\n },\n {\n \"id\": \"hydrozen-monitor\",\n \"category\": \"MONITORING\",\n \"name\": \"hydrozen-monitor\",\n \"patterns\": [\n \"Hydrozen\\\\.io\\\\/\"\n ],\n \"forbidden\": []\n },\n {\n \"id\": \"kuma-monitor\",\n \"category\": \"MONITORING\",\n \"name\": \"kuma-monitor\",\n \"patterns\": [\n \"Uptime-Kuma\"\n ],\n \"forbidden\": []\n },\n {\n \"id\": \"monitorbacklinks-crawler\",\n \"category\": \"MONITORING\",\n \"name\": \"monitorbacklinks-crawler\",\n \"patterns\": [\n \"MBCrawler\"\n ],\n \"forbidden\": []\n },\n {\n \"id\": \"newrelic-monitor\",\n \"category\": \"MONITORING\",\n \"name\": \"newrelic-monitor\",\n \"patterns\": [\n \"NewRelicbot\\\\/\"\n ],\n \"forbidden\": []\n },\n {\n \"id\": \"nixstats-crawler\",\n \"category\": \"MONITORING\",\n \"name\": \"nixstats-crawler\",\n \"patterns\": [\n \"NIXStatsbot\"\n ],\n \"forbidden\": []\n },\n {\n \"id\": \"outbrain-link-checker\",\n \"category\": \"MONITORING\",\n \"name\": \"outbrain-link-checker\",\n \"patterns\": [\n \"outbrain\"\n ],\n \"forbidden\": []\n },\n {\n \"id\": \"pingdom-crawler\",\n \"category\": \"MONITORING\",\n \"name\": \"Pingdom\",\n \"patterns\": [\n \"[pP]ingdom\"\n ],\n \"forbidden\": []\n },\n {\n \"id\": \"safedns-crawler\",\n \"category\": \"MONITORING\",\n \"name\": \"safedns-crawler\",\n \"patterns\": [\n \"SafeDNSBot\"\n ],\n \"forbidden\": []\n },\n {\n \"id\": \"sentry-crawler\",\n \"category\": \"MONITORING\",\n \"name\": \"sentry-crawler\",\n \"patterns\": [\n \"(^| )sentry\\\\/\"\n ],\n \"forbidden\": []\n },\n {\n \"id\": \"sentry-uptime-monitor\",\n \"category\": \"MONITORING\",\n \"name\": \"sentry-uptime-monitor\",\n \"patterns\": [\n \"SentryUptimeBot\\\\/1\\\\.0\"\n ],\n \"forbidden\": []\n },\n {\n \"id\": \"statuscake-monitor\",\n \"category\": \"MONITORING\",\n \"name\": \"statuscake-monitor\",\n \"patterns\": [\n \"StatusCake\"\n ],\n \"forbidden\": []\n },\n {\n \"id\": \"surly-crawler\",\n \"category\": \"MONITORING\",\n \"name\": \"surly-crawler\",\n \"patterns\": [\n \"SurdotlyBot\"\n ],\n \"forbidden\": []\n },\n {\n \"id\": \"testomato-crawler\",\n \"category\": \"MONITORING\",\n \"name\": \"testomato-crawler\",\n \"patterns\": [\n \"minicrawler\"\n ],\n \"forbidden\": []\n },\n {\n \"id\": \"uptime-monitor\",\n \"category\": \"MONITORING\",\n \"name\": \"uptime-monitor\",\n \"patterns\": [\n \"www\\\\.uptime\\\\.com\"\n ],\n \"forbidden\": []\n },\n {\n \"id\": \"uptimebot-monitor\",\n \"category\": \"MONITORING\",\n \"name\": \"uptimebot-monitor\",\n \"patterns\": [\n \"Uptimebot\\\\.org\"\n ],\n \"forbidden\": []\n },\n {\n \"id\": \"uptimerobot-monitor\",\n \"category\": \"MONITORING\",\n \"name\": \"UptimeRobot\",\n \"patterns\": [\n \"UptimeRobot\"\n ],\n \"forbidden\": []\n },\n {\n \"id\": \"w3c-validator-css\",\n \"category\": \"MONITORING\",\n \"name\": \"w3c-validator-css\",\n \"patterns\": [\n \"W3C_CSS_Validator\"\n ],\n \"forbidden\": []\n },\n {\n \"id\": \"w3c-validator-feed\",\n \"category\": \"MONITORING\",\n \"name\": \"w3c-validator-feed\",\n \"patterns\": [\n \"FeedValidator\"\n ],\n \"forbidden\": []\n },\n {\n \"id\": \"w3c-validator-html\",\n \"category\": \"MONITORING\",\n \"name\": \"w3c-validator-html\",\n \"patterns\": [\n \"W3C_Validator\"\n ],\n \"forbidden\": []\n },\n {\n \"id\": \"w3c-validator-html-nu\",\n \"category\": \"MONITORING\",\n \"name\": \"w3c-validator-html-nu\",\n \"patterns\": [\n \"Validator\\\\.nu\"\n ],\n \"forbidden\": []\n },\n {\n \"id\": \"w3c-validator-i18n\",\n \"category\": \"MONITORING\",\n \"name\": \"w3c-validator-i18n\",\n \"patterns\": [\n \"W3C_I18n-Checker\"\n ],\n \"forbidden\": []\n },\n {\n \"id\": \"w3c-validator-links\",\n \"category\": \"MONITORING\",\n \"name\": \"w3c-validator-links\",\n \"patterns\": [\n \"W3C-checklink\"\n ],\n \"forbidden\": []\n },\n {\n \"id\": \"w3c-validator-mobile\",\n \"category\": \"MONITORING\",\n \"name\": \"w3c-validator-mobile\",\n \"patterns\": [\n \"W3C-mobileOK\"\n ],\n \"forbidden\": []\n },\n {\n \"id\": \"w3c-validator-unified\",\n \"category\": \"MONITORING\",\n \"name\": \"w3c-validator-unified\",\n \"patterns\": [\n \"W3C_Unicorn\"\n ],\n \"forbidden\": []\n },\n {\n \"id\": \"webpagetest-crawler\",\n \"category\": \"MONITORING\",\n \"name\": \"webpagetest-crawler\",\n \"patterns\": [\n \"(^| )PTST\\\\/\"\n ],\n \"forbidden\": []\n },\n {\n \"id\": \"xenu-crawler\",\n \"category\": \"MONITORING\",\n \"name\": \"xenu-crawler\",\n \"patterns\": [\n \"Xenu Link Sleuth\"\n ],\n \"forbidden\": []\n },\n {\n \"id\": \"zabbix-monitor\",\n \"category\": \"MONITORING\",\n \"name\": \"zabbix-monitor\",\n \"patterns\": [\n \"Zabbix\"\n ],\n \"forbidden\": []\n },\n {\n \"id\": \"academicbot-rtu\",\n \"category\": \"SCRAPER\",\n \"name\": \"academicbot-rtu\",\n \"patterns\": [\n \"AcademicBotRTU\"\n ],\n \"forbidden\": []\n },\n {\n \"id\": \"adagio-crawler\",\n \"category\": \"SCRAPER\",\n \"name\": \"adagio-crawler\",\n \"patterns\": [\n \"Adagiobot\\\\/\"\n ],\n \"forbidden\": []\n },\n {\n \"id\": \"ahrefs-site-audit\",\n \"category\": \"SCRAPER\",\n \"name\": \"ahrefs-site-audit\",\n \"patterns\": [\n \"AhrefsSiteAudit\\\\/\"\n ],\n \"forbidden\": []\n },\n {\n \"id\": \"blackboard-crawler\",\n \"category\": \"SCRAPER\",\n \"name\": \"blackboard-crawler\",\n \"patterns\": [\n \"Blackboard\"\n ],\n \"forbidden\": []\n },\n {\n \"id\": \"cispa-crawler\",\n \"category\": \"SCRAPER\",\n \"name\": \"cispa-crawler\",\n \"patterns\": [\n \"CISPA Webcrawler\"\n ],\n \"forbidden\": []\n },\n {\n \"id\": \"cloudflare-prefetch\",\n \"category\": \"SCRAPER\",\n \"name\": \"cloudflare-prefetch\",\n \"patterns\": [\n \"CloudFlare-Prefetch\"\n ],\n \"forbidden\": []\n },\n {\n \"id\": \"coda-server-fetcher\",\n \"category\": \"SCRAPER\",\n \"name\": \"coda-server-fetcher\",\n \"patterns\": [\n \"Coda-Server-Fetcher\"\n ],\n \"forbidden\": []\n },\n {\n \"id\": \"conductor-crawler\",\n \"category\": \"SCRAPER\",\n \"name\": \"conductor-crawler\",\n \"patterns\": [\n \"Caliperbot\"\n ],\n \"forbidden\": []\n },\n {\n \"id\": \"cookiehub-scan\",\n \"category\": \"SCRAPER\",\n \"name\": \"cookiehub-scan\",\n \"patterns\": [\n \"CookieHubScan\"\n ],\n \"forbidden\": []\n },\n {\n \"id\": \"curl\",\n \"category\": \"SCRAPER\",\n \"name\": \"curl\",\n \"patterns\": [\n \"^curl\"\n ],\n \"forbidden\": []\n },\n {\n \"id\": \"dareboost-crawler\",\n \"category\": \"SCRAPER\",\n \"name\": \"dareboost-crawler\",\n \"patterns\": [\n \"DareBoost\"\n ],\n \"forbidden\": []\n },\n {\n \"id\": \"dcrawl\",\n \"category\": \"SCRAPER\",\n \"name\": \"dcrawl\",\n \"patterns\": [\n \"dcrawl\"\n ],\n \"forbidden\": []\n },\n {\n \"id\": \"domainsproject-crawler\",\n \"category\": \"SCRAPER\",\n \"name\": \"domainsproject-crawler\",\n \"patterns\": [\n \"Domains Project\\\\/\"\n ],\n \"forbidden\": []\n },\n {\n \"id\": \"epfl-crawler\",\n \"category\": \"SCRAPER\",\n \"name\": \"epfl-crawler\",\n \"patterns\": [\n \"A Patent Crawler\"\n ],\n \"forbidden\": []\n },\n {\n \"id\": \"gigablast-crawler-oss\",\n \"category\": \"SCRAPER\",\n \"name\": \"gigablast-crawler-oss\",\n \"patterns\": [\n \"Gigablast\"\n ],\n \"forbidden\": []\n },\n {\n \"id\": \"go-http\",\n \"category\": \"SCRAPER\",\n \"name\": \"Go-http-client\",\n \"patterns\": [\n \"Go-http-client\"\n ],\n \"forbidden\": []\n },\n {\n \"id\": \"got\",\n \"category\": \"SCRAPER\",\n \"name\": \"got\",\n \"patterns\": [\n \"sindresorhus\\\\/got\"\n ],\n \"forbidden\": []\n },\n {\n \"id\": \"gowiki-crawler\",\n \"category\": \"SCRAPER\",\n \"name\": \"gowiki-crawler\",\n \"patterns\": [\n \"Gowikibot\"\n ],\n \"forbidden\": []\n },\n {\n \"id\": \"http-get\",\n \"category\": \"SCRAPER\",\n \"name\": \"http-get\",\n \"patterns\": [\n \"http_get\"\n ],\n \"forbidden\": []\n },\n {\n \"id\": \"httpie\",\n \"category\": \"SCRAPER\",\n \"name\": \"HTTPie\",\n \"patterns\": [\n \"^HTTPie\\\\/\"\n ],\n \"forbidden\": []\n },\n {\n \"id\": \"img2dataset\",\n \"category\": \"SCRAPER\",\n \"name\": \"img2dataset\",\n \"patterns\": [\n \"img2dataset\"\n ],\n \"forbidden\": []\n },\n {\n \"id\": \"insomnia\",\n \"category\": \"SCRAPER\",\n \"name\": \"Insomnia\",\n \"patterns\": [\n \"^[iI]nsomnia\"\n ],\n \"forbidden\": []\n },\n {\n \"id\": \"ipip-crawler\",\n \"category\": \"SCRAPER\",\n \"name\": \"ipip-crawler\",\n \"patterns\": [\n \"HTTP Banner Detection\"\n ],\n \"forbidden\": []\n },\n {\n \"id\": \"java-apache-httpclient\",\n \"category\": \"SCRAPER\",\n \"name\": \"Apache HttpClient\",\n \"patterns\": [\n \"^Apache-HttpClient\"\n ],\n \"forbidden\": []\n },\n {\n \"id\": \"java-asynchttpclient\",\n \"category\": \"SCRAPER\",\n \"name\": \"java-asynchttpclient\",\n \"patterns\": [\n \"AHC\\\\/\"\n ],\n \"forbidden\": []\n },\n {\n \"id\": \"java-crawler4j\",\n \"category\": \"SCRAPER\",\n \"name\": \"java-crawler4j\",\n \"patterns\": [\n \"crawler4j\"\n ],\n \"forbidden\": []\n },\n {\n \"id\": \"java-httpunit\",\n \"category\": \"SCRAPER\",\n \"name\": \"java-httpunit\",\n \"patterns\": [\n \"httpunit\"\n ],\n \"forbidden\": []\n },\n {\n \"id\": \"java-jersey\",\n \"category\": \"SCRAPER\",\n \"name\": \"java-jersey\",\n \"patterns\": [\n \"HttpUrlConnection\"\n ],\n \"forbidden\": []\n },\n {\n \"id\": \"java-jetty\",\n \"category\": \"SCRAPER\",\n \"name\": \"java-jetty\",\n \"patterns\": [\n \"Jetty\"\n ],\n \"forbidden\": []\n },\n {\n \"id\": \"java-okhttp\",\n \"category\": \"SCRAPER\",\n \"name\": \"OkHttp\",\n \"patterns\": [\n \"okhttp\"\n ],\n \"forbidden\": []\n },\n {\n \"id\": \"java-snacktory\",\n \"category\": \"SCRAPER\",\n \"name\": \"java-snacktory\",\n \"patterns\": [\n \"Snacktory\"\n ],\n \"forbidden\": []\n },\n {\n \"id\": \"java-stdlib\",\n \"category\": \"SCRAPER\",\n \"name\": \"Java HttpClient\",\n \"patterns\": [\n \"^Java\\\\/\"\n ],\n \"forbidden\": []\n },\n {\n \"id\": \"javascript-axios\",\n \"category\": \"SCRAPER\",\n \"name\": \"axios\",\n \"patterns\": [\n \"axios\"\n ],\n \"forbidden\": []\n },\n {\n \"id\": \"javascript-node-fetch\",\n \"category\": \"SCRAPER\",\n \"name\": \"node-fetch\",\n \"patterns\": [\n \"node-fetch\"\n ],\n \"forbidden\": []\n },\n {\n \"id\": \"l9explore\",\n \"category\": \"SCRAPER\",\n \"name\": \"l9explore\",\n \"patterns\": [\n \"l9explore\"\n ],\n \"forbidden\": []\n },\n {\n \"id\": \"law-unimi-crawler\",\n \"category\": \"SCRAPER\",\n \"name\": \"law-unimi-crawler\",\n \"patterns\": [\n \"BUbiNG\"\n ],\n \"forbidden\": []\n },\n {\n \"id\": \"leipzig-findlinks\",\n \"category\": \"SCRAPER\",\n \"name\": \"leipzig-findlinks\",\n \"patterns\": [\n \"findlink\"\n ],\n \"forbidden\": []\n },\n {\n \"id\": \"leipzig-lcc\",\n \"category\": \"SCRAPER\",\n \"name\": \"leipzig-lcc\",\n \"patterns\": [\n \"^LCC \"\n ],\n \"forbidden\": []\n },\n {\n \"id\": \"macocu-crawler\",\n \"category\": \"SCRAPER\",\n \"name\": \"macocu-crawler\",\n \"patterns\": [\n \"MaCoCu\"\n ],\n \"forbidden\": []\n },\n {\n \"id\": \"moat-crawler\",\n \"category\": \"SCRAPER\",\n \"name\": \"moat-crawler\",\n \"patterns\": [\n \"moatbot\"\n ],\n \"forbidden\": []\n },\n {\n \"id\": \"monsido-crawler\",\n \"category\": \"SCRAPER\",\n \"name\": \"monsido-crawler\",\n \"patterns\": [\n \"Monsidobot\"\n ],\n \"forbidden\": []\n },\n {\n \"id\": \"moz-site-audit\",\n \"category\": \"SCRAPER\",\n \"name\": \"RogerBot\",\n \"patterns\": [\n \"rogerbot\"\n ],\n \"forbidden\": []\n },\n {\n \"id\": \"nagios-check-http\",\n \"category\": \"SCRAPER\",\n \"name\": \"nagios-check-http\",\n \"patterns\": [\n \"check_http\"\n ],\n \"forbidden\": []\n },\n {\n \"id\": \"nict-crawler\",\n \"category\": \"SCRAPER\",\n \"name\": \"nict-crawler\",\n \"patterns\": [\n \"ICC-Crawler\"\n ],\n \"forbidden\": []\n },\n {\n \"id\": \"nmap\",\n \"category\": \"SCRAPER\",\n \"name\": \"nmap\",\n \"patterns\": [\n \"Nmap Scripting Engine\"\n ],\n \"forbidden\": []\n },\n {\n \"id\": \"nutch\",\n \"category\": \"SCRAPER\",\n \"name\": \"nutch\",\n \"patterns\": [\n \"Nutch\"\n ],\n \"forbidden\": []\n },\n {\n \"id\": \"oncrawl\",\n \"category\": \"SCRAPER\",\n \"name\": \"oncrawl\",\n \"patterns\": [\n \"OnCrawl\\\\/\"\n ],\n \"forbidden\": []\n },\n {\n \"id\": \"perl-libwww\",\n \"category\": \"SCRAPER\",\n \"name\": \"libwww-perl\",\n \"patterns\": [\n \"libwww-perl\"\n ],\n \"forbidden\": []\n },\n {\n \"id\": \"perl-pcore\",\n \"category\": \"SCRAPER\",\n \"name\": \"perl-pcore\",\n \"patterns\": [\n \"Pcore-HTTP\"\n ],\n \"forbidden\": []\n },\n {\n \"id\": \"php-curlclass\",\n \"category\": \"SCRAPER\",\n \"name\": \"php-curlclass\",\n \"patterns\": [\n \"^PHP-Curl-Class\"\n ],\n \"forbidden\": []\n },\n {\n \"id\": \"php-phpcrawl\",\n \"category\": \"SCRAPER\",\n \"name\": \"php-phpcrawl\",\n \"patterns\": [\n \"phpcrawl\"\n ],\n \"forbidden\": []\n },\n {\n \"id\": \"php-simple-scraper\",\n \"category\": \"SCRAPER\",\n \"name\": \"php-simple-scraper\",\n \"patterns\": [\n \"SimpleScraper\"\n ],\n \"forbidden\": []\n },\n {\n \"id\": \"php-simplepie\",\n \"category\": \"SCRAPER\",\n \"name\": \"php-simplepie\",\n \"patterns\": [\n \"SimplePie\"\n ],\n \"forbidden\": []\n },\n {\n \"id\": \"php-ua\",\n \"category\": \"SCRAPER\",\n \"name\": \"PHP\",\n \"patterns\": [\n \"^PHP\\\\/\"\n ],\n \"forbidden\": []\n },\n {\n \"id\": \"postman\",\n \"category\": \"SCRAPER\",\n \"name\": \"Postman\",\n \"patterns\": [\n \"PostmanRuntime\\\\/\"\n ],\n \"forbidden\": []\n },\n {\n \"id\": \"postman-loose\",\n \"category\": \"SCRAPER\",\n \"name\": \"Postman\",\n \"patterns\": [\n \"^Postman[ /]\"\n ],\n \"forbidden\": []\n },\n {\n \"id\": \"python-aiohttp\",\n \"category\": \"SCRAPER\",\n \"name\": \"python-aiohttp\",\n \"patterns\": [\n \"aiohttp\"\n ],\n \"forbidden\": []\n },\n {\n \"id\": \"python-bitbot\",\n \"category\": \"SCRAPER\",\n \"name\": \"python-bitbot\",\n \"patterns\": [\n \"BitBot\"\n ],\n \"forbidden\": []\n },\n {\n \"id\": \"python-httpx\",\n \"category\": \"SCRAPER\",\n \"name\": \"python-httpx\",\n \"patterns\": [\n \"httpx\"\n ],\n \"forbidden\": []\n },\n {\n \"id\": \"python-opengraph\",\n \"category\": \"SCRAPER\",\n \"name\": \"python-opengraph\",\n \"patterns\": [\n \"python-opengraph\"\n ],\n \"forbidden\": []\n },\n {\n \"id\": \"python-requests\",\n \"category\": \"SCRAPER\",\n \"name\": \"python-requests\",\n \"patterns\": [\n \"python-requests\"\n ],\n \"forbidden\": []\n },\n {\n \"id\": \"python-scrapy\",\n \"category\": \"SCRAPER\",\n \"name\": \"Scrapy\",\n \"patterns\": [\n \"Scrapy\"\n ],\n \"forbidden\": []\n },\n {\n \"id\": \"python-urllib\",\n \"category\": \"SCRAPER\",\n \"name\": \"python-urllib\",\n \"patterns\": [\n \"Python-urllib\"\n ],\n \"forbidden\": []\n },\n {\n \"id\": \"quantcast-crawler\",\n \"category\": \"SCRAPER\",\n \"name\": \"quantcast-crawler\",\n \"patterns\": [\n \"Quantcastbot\\\\/\"\n ],\n \"forbidden\": []\n },\n {\n \"id\": \"ruby\",\n \"category\": \"SCRAPER\",\n \"name\": \"Ruby\",\n \"patterns\": [\n \"^Ruby\"\n ],\n \"forbidden\": []\n },\n {\n \"id\": \"ruby-metainspector\",\n \"category\": \"SCRAPER\",\n \"name\": \"ruby-metainspector\",\n \"patterns\": [\n \"MetaInspector\"\n ],\n \"forbidden\": []\n },\n {\n \"id\": \"screamingfrog-crawler\",\n \"category\": \"SCRAPER\",\n \"name\": \"screamingfrog-crawler\",\n \"patterns\": [\n \"Screaming Frog SEO Spider\"\n ],\n \"forbidden\": []\n },\n {\n \"id\": \"semanticscholar-crawler\",\n \"category\": \"SCRAPER\",\n \"name\": \"SemanticScholarBot\",\n \"patterns\": [\n \"SemanticScholarBot\"\n ],\n \"forbidden\": []\n },\n {\n \"id\": \"sistrix-crawler\",\n \"category\": \"SCRAPER\",\n \"name\": \"sistrix-crawler\",\n \"patterns\": [\n \"(sistrix|SISTRIX) [cC]rawler\"\n ],\n \"forbidden\": []\n },\n {\n \"id\": \"sitebulb\",\n \"category\": \"SCRAPER\",\n \"name\": \"sitebulb\",\n \"patterns\": [\n \"sitebulb\"\n ],\n \"forbidden\": []\n },\n {\n \"id\": \"stripe-crawler\",\n \"category\": \"SCRAPER\",\n \"name\": \"stripe-crawler\",\n \"patterns\": [\n \"Stripebot\\\\/\"\n ],\n \"forbidden\": []\n },\n {\n \"id\": \"summaly-crawler\",\n \"category\": \"SCRAPER\",\n \"name\": \"summaly-crawler\",\n \"patterns\": [\n \"SummalyBot\"\n ],\n \"forbidden\": []\n },\n {\n \"id\": \"turnitin-crawler\",\n \"category\": \"SCRAPER\",\n \"name\": \"turnitin-crawler\",\n \"patterns\": [\n \"Turnitin\"\n ],\n \"forbidden\": []\n },\n {\n \"id\": \"utexas-crawler\",\n \"category\": \"SCRAPER\",\n \"name\": \"utexas-crawler\",\n \"patterns\": [\n \"UT-Dorkbot\"\n ],\n \"forbidden\": []\n },\n {\n \"id\": \"wget\",\n \"category\": \"SCRAPER\",\n \"name\": \"wget\",\n \"patterns\": [\n \"[wW]get\"\n ],\n \"forbidden\": []\n },\n {\n \"id\": \"yamanalab-crawler\",\n \"category\": \"SCRAPER\",\n \"name\": \"yamanalab-crawler\",\n \"patterns\": [\n \"Sonic\"\n ],\n \"forbidden\": []\n },\n {\n \"id\": \"yext-bot\",\n \"category\": \"SCRAPER\",\n \"name\": \"yext-bot\",\n \"patterns\": [\n \"YextBot\"\n ],\n \"forbidden\": []\n },\n {\n \"id\": \"zgrab\",\n \"category\": \"SCRAPER\",\n \"name\": \"zgrab\",\n \"patterns\": [\n \"zgrab\"\n ],\n \"forbidden\": []\n },\n {\n \"id\": \"addsearch-crawler\",\n \"category\": \"SEARCH_ENGINE\",\n \"name\": \"addsearch-crawler\",\n \"patterns\": [\n \"AddSearchBot\"\n ],\n \"forbidden\": []\n },\n {\n \"id\": \"ahrefs-crawler\",\n \"category\": \"SEARCH_ENGINE\",\n \"name\": \"AhrefsBot\",\n \"patterns\": [\n \"AhrefsBot\\\\/\"\n ],\n \"forbidden\": []\n },\n {\n \"id\": \"alexandria-crawler\",\n \"category\": \"SEARCH_ENGINE\",\n \"name\": \"alexandria-crawler\",\n \"patterns\": [\n \"AlexandriaOrgBot\"\n ],\n \"forbidden\": []\n },\n {\n \"id\": \"algolia-crawler\",\n \"category\": \"SEARCH_ENGINE\",\n \"name\": \"algolia-crawler\",\n \"patterns\": [\n \"Algolia Crawler\\\\/\"\n ],\n \"forbidden\": []\n },\n {\n \"id\": \"amazon-adbot\",\n \"category\": \"SEARCH_ENGINE\",\n \"name\": \"amazon-adbot\",\n \"patterns\": [\n \"AmazonAdBot\\\\/\"\n ],\n \"forbidden\": []\n },\n {\n \"id\": \"amazon-alexa-crawler\",\n \"category\": \"SEARCH_ENGINE\",\n \"name\": \"amazon-alexa-crawler\",\n \"patterns\": [\n \"exabot\"\n ],\n \"forbidden\": []\n },\n {\n \"id\": \"amazon-cloudfront\",\n \"category\": \"SEARCH_ENGINE\",\n \"name\": \"amazon-cloudfront\",\n \"patterns\": [\n \"Amazon CloudFront\"\n ],\n \"forbidden\": []\n },\n {\n \"id\": \"amazon-crawler\",\n \"category\": \"SEARCH_ENGINE\",\n \"name\": \"AmazonBot\",\n \"patterns\": [\n \"Amazonbot\"\n ],\n \"forbidden\": []\n },\n {\n \"id\": \"apple-crawler\",\n \"category\": \"SEARCH_ENGINE\",\n \"name\": \"Applebot\",\n \"patterns\": [\n \"Applebot\"\n ],\n \"forbidden\": []\n },\n {\n \"id\": \"apple-feedfetcher\",\n \"category\": \"SEARCH_ENGINE\",\n \"name\": \"apple-feedfetcher\",\n \"patterns\": [\n \"i[Tt][Mm][Ss]\"\n ],\n \"forbidden\": []\n },\n {\n \"id\": \"archiveorg-archiver\",\n \"category\": \"SEARCH_ENGINE\",\n \"name\": \"ArchiveOrgBot\",\n \"patterns\": [\n \"archive\\\\.org_bot\"\n ],\n \"forbidden\": []\n },\n {\n \"id\": \"ask-crawler\",\n \"category\": \"SEARCH_ENGINE\",\n \"name\": \"ask-crawler\",\n \"patterns\": [\n \"Teoma\"\n ],\n \"forbidden\": []\n },\n {\n \"id\": \"avira-crawler\",\n \"category\": \"SEARCH_ENGINE\",\n \"name\": \"avira-crawler\",\n \"patterns\": [\n \"SafeSearch microdata crawler\"\n ],\n \"forbidden\": []\n },\n {\n \"id\": \"awario-crawler-rss\",\n \"category\": \"SEARCH_ENGINE\",\n \"name\": \"awario-crawler-rss\",\n \"patterns\": [\n \"AwarioRssBot\"\n ],\n \"forbidden\": []\n },\n {\n \"id\": \"baidu-crawler\",\n \"category\": \"SEARCH_ENGINE\",\n \"name\": \"Baiduspider\",\n \"patterns\": [\n \"Baiduspider\"\n ],\n \"forbidden\": []\n },\n {\n \"id\": \"bazqux-feedfetcher\",\n \"category\": \"SEARCH_ENGINE\",\n \"name\": \"bazqux-feedfetcher\",\n \"patterns\": [\n \"BazQux\"\n ],\n \"forbidden\": []\n },\n {\n \"id\": \"bing-ads\",\n \"category\": \"SEARCH_ENGINE\",\n \"name\": \"bing-ads\",\n \"patterns\": [\n \"Adidxbot\"\n ],\n \"forbidden\": []\n },\n {\n \"id\": \"bing-crawler\",\n \"category\": \"SEARCH_ENGINE\",\n \"name\": \"Bingbot\",\n \"patterns\": [\n \"bingbot\"\n ],\n \"forbidden\": []\n },\n {\n \"id\": \"bing-office-store\",\n \"category\": \"SEARCH_ENGINE\",\n \"name\": \"bing-office-store\",\n \"patterns\": [\n \"officestorebot\"\n ],\n \"forbidden\": []\n },\n {\n \"id\": \"blogtraffic-feedfetcher\",\n \"category\": \"SEARCH_ENGINE\",\n \"name\": \"blogtraffic-feedfetcher\",\n \"patterns\": [\n \"BlogTraffic\\\\/\\\\d\\\\.\\\\d+ Feed-Fetcher\"\n ],\n \"forbidden\": []\n },\n {\n \"id\": \"cloudflare-archiver\",\n \"category\": \"SEARCH_ENGINE\",\n \"name\": \"cloudflare-archiver\",\n \"patterns\": [\n \"CloudFlare-AlwaysOnline\"\n ],\n \"forbidden\": []\n },\n {\n \"id\": \"commoncrawl-crawler\",\n \"category\": \"SEARCH_ENGINE\",\n \"name\": \"CommonCrawlBot\",\n \"patterns\": [\n \"CCBot\"\n ],\n \"forbidden\": []\n },\n {\n \"id\": \"duckduckgo-crawler\",\n \"category\": \"SEARCH_ENGINE\",\n \"name\": \"DuckDuckBot\",\n \"patterns\": [\n \"DuckDuckBot\"\n ],\n \"forbidden\": []\n },\n {\n \"id\": \"entireweb-crawler\",\n \"category\": \"SEARCH_ENGINE\",\n \"name\": \"entireweb-crawler\",\n \"patterns\": [\n \"speedy\"\n ],\n \"forbidden\": []\n },\n {\n \"id\": \"ezid-crawler\",\n \"category\": \"SEARCH_ENGINE\",\n \"name\": \"ezid-crawler\",\n \"patterns\": [\n \"EZID\"\n ],\n \"forbidden\": []\n },\n {\n \"id\": \"feedbin-crawler\",\n \"category\": \"SEARCH_ENGINE\",\n \"name\": \"feedbin-crawler\",\n \"patterns\": [\n \"Feedbin\"\n ],\n \"forbidden\": []\n },\n {\n \"id\": \"feedly-feedfetcher\",\n \"category\": \"SEARCH_ENGINE\",\n \"name\": \"feedly-feedfetcher\",\n \"patterns\": [\n \"Feedly\"\n ],\n \"forbidden\": []\n },\n {\n \"id\": \"feedspot-feedfetcher\",\n \"category\": \"SEARCH_ENGINE\",\n \"name\": \"feedspot-feedfetcher\",\n \"patterns\": [\n \"Feedspot\"\n ],\n \"forbidden\": []\n },\n {\n \"id\": \"freshrss-feedfetcher\",\n \"category\": \"SEARCH_ENGINE\",\n \"name\": \"freshrss-feedfetcher\",\n \"patterns\": [\n \"FreshRSS\"\n ],\n \"forbidden\": []\n },\n {\n \"id\": \"g2reader-crawler\",\n \"category\": \"SEARCH_ENGINE\",\n \"name\": \"g2reader-crawler\",\n \"patterns\": [\n \"g2reader-bot\"\n ],\n \"forbidden\": []\n },\n {\n \"id\": \"geedo-crawler\",\n \"category\": \"SEARCH_ENGINE\",\n \"name\": \"geedo-crawler\",\n \"patterns\": [\n \"GeedoBot\"\n ],\n \"forbidden\": []\n },\n {\n \"id\": \"geedo-crawler-products\",\n \"category\": \"SEARCH_ENGINE\",\n \"name\": \"geedo-crawler-products\",\n \"patterns\": [\n \"GeedoProductSearch\"\n ],\n \"forbidden\": []\n },\n {\n \"id\": \"google-ads-conversions\",\n \"category\": \"SEARCH_ENGINE\",\n \"name\": \"google-ads-conversions\",\n \"patterns\": [\n \"Google-Ads-Conversions\"\n ],\n \"forbidden\": []\n },\n {\n \"id\": \"google-adsbot\",\n \"category\": \"SEARCH_ENGINE\",\n \"name\": \"AdsBotGoogle\",\n \"patterns\": [\n \"AdsBot-Google([^-]|$)\"\n ],\n \"forbidden\": []\n },\n {\n \"id\": \"google-adsbot-mobile\",\n \"category\": \"SEARCH_ENGINE\",\n \"name\": \"GoogleAdsBot\",\n \"patterns\": [\n \"AdsBot-Google-Mobile\"\n ],\n \"forbidden\": []\n },\n {\n \"id\": \"google-adsense\",\n \"category\": \"SEARCH_ENGINE\",\n \"name\": \"MediapartnersGoogle\",\n \"patterns\": [\n \"Mediapartners-Google\"\n ],\n \"forbidden\": []\n },\n {\n \"id\": \"google-adsense-googlebot\",\n \"category\": \"SEARCH_ENGINE\",\n \"name\": \"google-adsense-googlebot\",\n \"patterns\": [\n \"Mediapartners \\\\(Googlebot\\\\)\"\n ],\n \"forbidden\": []\n },\n {\n \"id\": \"google-adwords\",\n \"category\": \"SEARCH_ENGINE\",\n \"name\": \"google-adwords\",\n \"patterns\": [\n \"Google-Adwords-Instant\"\n ],\n \"forbidden\": []\n },\n {\n \"id\": \"google-appengine\",\n \"category\": \"SEARCH_ENGINE\",\n \"name\": \"google-appengine\",\n \"patterns\": [\n \"AppEngine-Google\"\n ],\n \"forbidden\": []\n },\n {\n \"id\": \"google-crawler\",\n \"category\": \"SEARCH_ENGINE\",\n \"name\": \"Googlebot\",\n \"patterns\": [\n \"Googlebot\\\\/\"\n ],\n \"forbidden\": []\n },\n {\n \"id\": \"google-crawler-cloudvertex\",\n \"category\": \"SEARCH_ENGINE\",\n \"name\": \"google-crawler-cloudvertex\",\n \"patterns\": [\n \"Google-CloudVertexBot\"\n ],\n \"forbidden\": []\n },\n {\n \"id\": \"google-crawler-image\",\n \"category\": \"SEARCH_ENGINE\",\n \"name\": \"Googlebot-Image\",\n \"patterns\": [\n \"Googlebot-Image\"\n ],\n \"forbidden\": []\n },\n {\n \"id\": \"google-crawler-mobile\",\n \"category\": \"SEARCH_ENGINE\",\n \"name\": \"google-crawler-mobile\",\n \"patterns\": [\n \"Googlebot-Mobile\"\n ],\n \"forbidden\": []\n },\n {\n \"id\": \"google-crawler-news\",\n \"category\": \"SEARCH_ENGINE\",\n \"name\": \"Googlebot-News\",\n \"patterns\": [\n \"Googlebot-News\"\n ],\n \"forbidden\": []\n },\n {\n \"id\": \"google-crawler-other\",\n \"category\": \"SEARCH_ENGINE\",\n \"name\": \"google-crawler-other\",\n \"patterns\": [\n \"GoogleOther\"\n ],\n \"forbidden\": []\n },\n {\n \"id\": \"google-crawler-safety\",\n \"category\": \"SEARCH_ENGINE\",\n \"name\": \"google-crawler-safety\",\n \"patterns\": [\n \"Google-Safety\"\n ],\n \"forbidden\": []\n },\n {\n \"id\": \"google-crawler-store\",\n \"category\": \"SEARCH_ENGINE\",\n \"name\": \"StorebotGoogle\",\n \"patterns\": [\n \"Storebot-Google\"\n ],\n \"forbidden\": []\n },\n {\n \"id\": \"google-crawler-video\",\n \"category\": \"SEARCH_ENGINE\",\n \"name\": \"Googlebot-Video\",\n \"patterns\": [\n \"Googlebot-Video\"\n ],\n \"forbidden\": []\n },\n {\n \"id\": \"google-feedfetcher\",\n \"category\": \"SEARCH_ENGINE\",\n \"name\": \"google-feedfetcher\",\n \"patterns\": [\n \"Feedfetcher-Google\"\n ],\n \"forbidden\": []\n },\n {\n \"id\": \"google-inspection-tool\",\n \"category\": \"SEARCH_ENGINE\",\n \"name\": \"google-inspection-tool\",\n \"patterns\": [\n \"Google-InspectionTool\"\n ],\n \"forbidden\": []\n },\n {\n \"id\": \"google-lighthouse\",\n \"category\": \"SEARCH_ENGINE\",\n \"name\": \"google-lighthouse\",\n \"patterns\": [\n \"Chrome-Lighthouse\"\n ],\n \"forbidden\": []\n },\n {\n \"id\": \"google-physical-web\",\n \"category\": \"SEARCH_ENGINE\",\n \"name\": \"google-physical-web\",\n \"patterns\": [\n \"Google-PhysicalWeb\"\n ],\n \"forbidden\": []\n },\n {\n \"id\": \"google-push-notifications\",\n \"category\": \"SEARCH_ENGINE\",\n \"name\": \"APIsGoogle\",\n \"patterns\": [\n \"APIs-Google\"\n ],\n \"forbidden\": []\n },\n {\n \"id\": \"google-read-aloud\",\n \"category\": \"SEARCH_ENGINE\",\n \"name\": \"google-read-aloud\",\n \"patterns\": [\n \"Google-Read-Aloud\"\n ],\n \"forbidden\": []\n },\n {\n \"id\": \"google-xrawler\",\n \"category\": \"SEARCH_ENGINE\",\n \"name\": \"google-xrawler\",\n \"patterns\": [\n \"google-xrawler\"\n ],\n \"forbidden\": []\n },\n {\n \"id\": \"iask-crawler\",\n \"category\": \"SEARCH_ENGINE\",\n \"name\": \"iask-crawler\",\n \"patterns\": [\n \"iaskspider\"\n ],\n \"forbidden\": []\n },\n {\n \"id\": \"inoreader-aggregator\",\n \"category\": \"SEARCH_ENGINE\",\n \"name\": \"inoreader-aggregator\",\n \"patterns\": [\n \"inoreader\"\n ],\n \"forbidden\": []\n },\n {\n \"id\": \"internetarchive-crawler-oss\",\n \"category\": \"SEARCH_ENGINE\",\n \"name\": \"internetarchive-crawler-oss\",\n \"patterns\": [\n \"heritrix\"\n ],\n \"forbidden\": []\n },\n {\n \"id\": \"linguee-crawler\",\n \"category\": \"SEARCH_ENGINE\",\n \"name\": \"linguee-crawler\",\n \"patterns\": [\n \"Linguee Bot\"\n ],\n \"forbidden\": []\n },\n {\n \"id\": \"majestic-crawler\",\n \"category\": \"SEARCH_ENGINE\",\n \"name\": \"majestic-crawler\",\n \"patterns\": [\n \"MJ12bot\"\n ],\n \"forbidden\": []\n },\n {\n \"id\": \"marginalia-crawler\",\n \"category\": \"SEARCH_ENGINE\",\n \"name\": \"marginalia-crawler\",\n \"patterns\": [\n \"search\\\\.marginalia\\\\.nu\"\n ],\n \"forbidden\": []\n },\n {\n \"id\": \"meta-crawler\",\n \"category\": \"SEARCH_ENGINE\",\n \"name\": \"meta-crawler\",\n \"patterns\": [\n \"[Mm]eta-[Ee]xternal[Aa]gent\"\n ],\n \"forbidden\": []\n },\n {\n \"id\": \"meta-externalads\",\n \"category\": \"SEARCH_ENGINE\",\n \"name\": \"meta-externalads\",\n \"patterns\": [\n \"meta-externalads\\\\/\"\n ],\n \"forbidden\": []\n },\n {\n \"id\": \"microsoft-research-crawler\",\n \"category\": \"SEARCH_ENGINE\",\n \"name\": \"microsoft-research-crawler\",\n \"patterns\": [\n \"msrbot\"\n ],\n \"forbidden\": []\n },\n {\n \"id\": \"miniflux-feedfetcher\",\n \"category\": \"SEARCH_ENGINE\",\n \"name\": \"miniflux-feedfetcher\",\n \"patterns\": [\n \"Miniflux\\\\/\"\n ],\n \"forbidden\": []\n },\n {\n \"id\": \"mojeek-crawler\",\n \"category\": \"SEARCH_ENGINE\",\n \"name\": \"mojeek-crawler\",\n \"patterns\": [\n \"MojeekBot\\\\/\"\n ],\n \"forbidden\": []\n },\n {\n \"id\": \"msn-crawler\",\n \"category\": \"SEARCH_ENGINE\",\n \"name\": \"MsnBot\",\n \"patterns\": [\n \"msnbot\"\n ],\n \"forbidden\": []\n },\n {\n \"id\": \"naver-crawler-rss\",\n \"category\": \"SEARCH_ENGINE\",\n \"name\": \"naver-crawler-rss\",\n \"patterns\": [\n \"NAVER Blog Rssbot\"\n ],\n \"forbidden\": []\n },\n {\n \"id\": \"netestate-crawler\",\n \"category\": \"SEARCH_ENGINE\",\n \"name\": \"netestate-crawler\",\n \"patterns\": [\n \"netEstate NE Crawler\"\n ],\n \"forbidden\": []\n },\n {\n \"id\": \"newsblur-aggregator\",\n \"category\": \"SEARCH_ENGINE\",\n \"name\": \"newsblur-aggregator\",\n \"patterns\": [\n \"NewsBlur\"\n ],\n \"forbidden\": []\n },\n {\n \"id\": \"nicecrawler-archive\",\n \"category\": \"SEARCH_ENGINE\",\n \"name\": \"nicecrawler-archive\",\n \"patterns\": [\n \"Nicecrawler\"\n ],\n \"forbidden\": []\n },\n {\n \"id\": \"openai-crawler-search\",\n \"category\": \"SEARCH_ENGINE\",\n \"name\": \"OAISearchBot\",\n \"patterns\": [\n \"OAI-SearchBot\"\n ],\n \"forbidden\": []\n },\n {\n \"id\": \"petalsearch-crawler\",\n \"category\": \"SEARCH_ENGINE\",\n \"name\": \"petalsearch-crawler\",\n \"patterns\": [\n \"PetalBot\"\n ],\n \"forbidden\": []\n },\n {\n \"id\": \"pipl-crawler\",\n \"category\": \"SEARCH_ENGINE\",\n \"name\": \"pipl-crawler\",\n \"patterns\": [\n \"PiplBot\"\n ],\n \"forbidden\": []\n },\n {\n \"id\": \"pocket-crawler\",\n \"category\": \"SEARCH_ENGINE\",\n \"name\": \"pocket-crawler\",\n \"patterns\": [\n \"PocketParser\"\n ],\n \"forbidden\": []\n },\n {\n \"id\": \"qwant-crawler\",\n \"category\": \"SEARCH_ENGINE\",\n \"name\": \"qwant-crawler\",\n \"patterns\": [\n \"Qwantify\"\n ],\n \"forbidden\": []\n },\n {\n \"id\": \"refind-crawler\",\n \"category\": \"SEARCH_ENGINE\",\n \"name\": \"refind-crawler\",\n \"patterns\": [\n \"Refindbot\"\n ],\n \"forbidden\": []\n },\n {\n \"id\": \"rssbot-feedfetcher\",\n \"category\": \"SEARCH_ENGINE\",\n \"name\": \"rssbot-feedfetcher\",\n \"patterns\": [\n \"rssbot\\\\/\"\n ],\n \"forbidden\": []\n },\n {\n \"id\": \"rssing-crawler\",\n \"category\": \"SEARCH_ENGINE\",\n \"name\": \"rssing-crawler\",\n \"patterns\": [\n \"RSSingBot\"\n ],\n \"forbidden\": []\n },\n {\n \"id\": \"rssmicro-feedfetcher\",\n \"category\": \"SEARCH_ENGINE\",\n \"name\": \"rssmicro-feedfetcher\",\n \"patterns\": [\n \"Atom Feed Robot\"\n ],\n \"forbidden\": []\n },\n {\n \"id\": \"seekport-crawler\",\n \"category\": \"SEARCH_ENGINE\",\n \"name\": \"seekport-crawler\",\n \"patterns\": [\n \"Seekport\"\n ],\n \"forbidden\": []\n },\n {\n \"id\": \"serendeputy-crawler\",\n \"category\": \"SEARCH_ENGINE\",\n \"name\": \"serendeputy-crawler\",\n \"patterns\": [\n \"SerendeputyBot\"\n ],\n \"forbidden\": []\n },\n {\n \"id\": \"startme-crawler\",\n \"category\": \"SEARCH_ENGINE\",\n \"name\": \"startme-crawler\",\n \"patterns\": [\n \"startmebot\\\\/\"\n ],\n \"forbidden\": []\n },\n {\n \"id\": \"stract-crawler\",\n \"category\": \"SEARCH_ENGINE\",\n \"name\": \"stract-crawler\",\n \"patterns\": [\n \"StractBot\"\n ],\n \"forbidden\": []\n },\n {\n \"id\": \"superfeedr-crawler\",\n \"category\": \"SEARCH_ENGINE\",\n \"name\": \"superfeedr-crawler\",\n \"patterns\": [\n \"Superfeedr\"\n ],\n \"forbidden\": []\n },\n {\n \"id\": \"theoldreader-crawler\",\n \"category\": \"SEARCH_ENGINE\",\n \"name\": \"theoldreader-crawler\",\n \"patterns\": [\n \"theoldreader\\\\.com\"\n ],\n \"forbidden\": []\n },\n {\n \"id\": \"ttrss-feedfetcher\",\n \"category\": \"SEARCH_ENGINE\",\n \"name\": \"ttrss-feedfetcher\",\n \"patterns\": [\n \"Tiny Tiny RSS\"\n ],\n \"forbidden\": []\n },\n {\n \"id\": \"webarchive-crawler\",\n \"category\": \"SEARCH_ENGINE\",\n \"name\": \"webarchive-crawler\",\n \"patterns\": [\n \"web-archive-net\\\\.com\\\\.bot\"\n ],\n \"forbidden\": []\n },\n {\n \"id\": \"webzio-crawler\",\n \"category\": \"SEARCH_ENGINE\",\n \"name\": \"webzio-crawler\",\n \"patterns\": [\n \"webzio\\\\s\"\n ],\n \"forbidden\": []\n },\n {\n \"id\": \"wellknown-crawler\",\n \"category\": \"SEARCH_ENGINE\",\n \"name\": \"wellknown-crawler\",\n \"patterns\": [\n \"WellKnownBot\"\n ],\n \"forbidden\": []\n },\n {\n \"id\": \"wordpress-crawler-rss\",\n \"category\": \"SEARCH_ENGINE\",\n \"name\": \"wordpress-crawler-rss\",\n \"patterns\": [\n \"feedbot\"\n ],\n \"forbidden\": []\n },\n {\n \"id\": \"yacy-crawler\",\n \"category\": \"SEARCH_ENGINE\",\n \"name\": \"yacy-crawler\",\n \"patterns\": [\n \"yacybot\"\n ],\n \"forbidden\": []\n },\n {\n \"id\": \"yahoo-crawler\",\n \"category\": \"SEARCH_ENGINE\",\n \"name\": \"SlurpBot\",\n \"patterns\": [\n \"Slurp\"\n ],\n \"forbidden\": []\n },\n {\n \"id\": \"yahoo-crawler-japan\",\n \"category\": \"SEARCH_ENGINE\",\n \"name\": \"yahoo-crawler-japan\",\n \"patterns\": [\n \"Y!J\"\n ],\n \"forbidden\": []\n },\n {\n \"id\": \"yandex-crawler\",\n \"category\": \"SEARCH_ENGINE\",\n \"name\": \"YandexBot\",\n \"patterns\": [\n \"yandex\\\\.com\\\\/bots\"\n ],\n \"forbidden\": []\n },\n {\n \"id\": \"yandex-crawler-javascript\",\n \"category\": \"SEARCH_ENGINE\",\n \"name\": \"yandex-crawler-javascript\",\n \"patterns\": [\n \"YandexRenderResourcesBot\\\\/\"\n ],\n \"forbidden\": []\n },\n {\n \"id\": \"yandex-loose\",\n \"category\": \"SEARCH_ENGINE\",\n \"name\": \"YandexBot\",\n \"patterns\": [\n \"YandexBot\"\n ],\n \"forbidden\": []\n },\n {\n \"id\": \"adyen-webhook\",\n \"category\": \"SOCIAL\",\n \"name\": \"adyen-webhook\",\n \"patterns\": [\n \"Adyen HttpClient\"\n ],\n \"forbidden\": []\n },\n {\n \"id\": \"bing-preview\",\n \"category\": \"SOCIAL\",\n \"name\": \"BingPreviewBot\",\n \"patterns\": [\n \"BingPreview\\\\/\"\n ],\n \"forbidden\": []\n },\n {\n \"id\": \"bitly-crawler\",\n \"category\": \"SOCIAL\",\n \"name\": \"bitly-crawler\",\n \"patterns\": [\n \"bitlybot\"\n ],\n \"forbidden\": []\n },\n {\n \"id\": \"digg-crawler\",\n \"category\": \"SOCIAL\",\n \"name\": \"digg-crawler\",\n \"patterns\": [\n \"Digg Deeper\"\n ],\n \"forbidden\": []\n },\n {\n \"id\": \"discord-crawler\",\n \"category\": \"SOCIAL\",\n \"name\": \"Discordbot\",\n \"patterns\": [\n \"Discordbot\"\n ],\n \"forbidden\": []\n },\n {\n \"id\": \"duckduckgo-crawler-favicons\",\n \"category\": \"SOCIAL\",\n \"name\": \"duckduckgo-crawler-favicons\",\n \"patterns\": [\n \"DuckDuckGo-Favicons-Bot\"\n ],\n \"forbidden\": []\n },\n {\n \"id\": \"embedly-crawler\",\n \"category\": \"SOCIAL\",\n \"name\": \"EmbedlyBot\",\n \"patterns\": [\n \"Embedly\"\n ],\n \"forbidden\": []\n },\n {\n \"id\": \"everyonesocial-crawler\",\n \"category\": \"SOCIAL\",\n \"name\": \"everyonesocial-crawler\",\n \"patterns\": [\n \"EveryoneSocialBot\"\n ],\n \"forbidden\": []\n },\n {\n \"id\": \"facebook-catalog\",\n \"category\": \"SOCIAL\",\n \"name\": \"facebook-catalog\",\n \"patterns\": [\n \"facebookcatalog\\\\/\"\n ],\n \"forbidden\": []\n },\n {\n \"id\": \"facebook-crawler\",\n \"category\": \"SOCIAL\",\n \"name\": \"FacebookBot\",\n \"patterns\": [\n \"Face(book){0,1}[Bb]ot\"\n ],\n \"forbidden\": [\n \"facebookexternalhit\",\n \"Twitterbot\"\n ]\n },\n {\n \"id\": \"facebook-share-crawler\",\n \"category\": \"SOCIAL\",\n \"name\": \"Facebook\",\n \"patterns\": [\n \"facebookexternalhit\"\n ],\n \"forbidden\": [\n \"Twitterbot\",\n \"Facebot\"\n ]\n },\n {\n \"id\": \"flipboard-proxy\",\n \"category\": \"SOCIAL\",\n \"name\": \"flipboard-proxy\",\n \"patterns\": [\n \"FlipboardProxy\"\n ],\n \"forbidden\": []\n },\n {\n \"id\": \"google-favicon\",\n \"category\": \"SOCIAL\",\n \"name\": \"google-favicon\",\n \"patterns\": [\n \"Google Favicon\"\n ],\n \"forbidden\": []\n },\n {\n \"id\": \"google-preview\",\n \"category\": \"SOCIAL\",\n \"name\": \"google-preview\",\n \"patterns\": [\n \"Google Web Preview\"\n ],\n \"forbidden\": []\n },\n {\n \"id\": \"google-web-snippet\",\n \"category\": \"SOCIAL\",\n \"name\": \"google-web-snippet\",\n \"patterns\": [\n \"developers\\\\.google\\\\.com\\\\/\\\\+\\\\/web\\\\/snippet\"\n ],\n \"forbidden\": []\n },\n {\n \"id\": \"groupme-crawler\",\n \"category\": \"SOCIAL\",\n \"name\": \"groupme-crawler\",\n \"patterns\": [\n \"GroupMeBot\"\n ],\n \"forbidden\": []\n },\n {\n \"id\": \"iframely-preview\",\n \"category\": \"SOCIAL\",\n \"name\": \"iframely-preview\",\n \"patterns\": [\n \"Iframely\"\n ],\n \"forbidden\": []\n },\n {\n \"id\": \"imessage-preview\",\n \"category\": \"SOCIAL\",\n \"name\": \"imessage-preview\",\n \"patterns\": [\n \"facebookexternalhit\",\n \"Twitterbot\",\n \"Facebot\"\n ],\n \"forbidden\": []\n },\n {\n \"id\": \"irc-archivebot\",\n \"category\": \"SOCIAL\",\n \"name\": \"ArchiveBot\",\n \"patterns\": [\n \"ArchiveBot\"\n ],\n \"forbidden\": []\n },\n {\n \"id\": \"keybase-bot\",\n \"category\": \"SOCIAL\",\n \"name\": \"keybase-bot\",\n \"patterns\": [\n \"KeybaseBot\"\n ],\n \"forbidden\": []\n },\n {\n \"id\": \"lemmy-crawler\",\n \"category\": \"SOCIAL\",\n \"name\": \"lemmy-crawler\",\n \"patterns\": [\n \"Lemmy\"\n ],\n \"forbidden\": []\n },\n {\n \"id\": \"linkarchiver\",\n \"category\": \"SOCIAL\",\n \"name\": \"linkarchiver\",\n \"patterns\": [\n \"LinkArchiver\"\n ],\n \"forbidden\": []\n },\n {\n \"id\": \"linkedin-crawler\",\n \"category\": \"SOCIAL\",\n \"name\": \"LinkedInBot\",\n \"patterns\": [\n \"LinkedInBot\"\n ],\n \"forbidden\": []\n },\n {\n \"id\": \"mastodon-crawler\",\n \"category\": \"SOCIAL\",\n \"name\": \"MastodonBot\",\n \"patterns\": [\n \"Mastodon\"\n ],\n \"forbidden\": []\n },\n {\n \"id\": \"meta-crawler-user\",\n \"category\": \"SOCIAL\",\n \"name\": \"meta-crawler-user\",\n \"patterns\": [\n \"meta-externalfetcher\"\n ],\n \"forbidden\": []\n },\n {\n \"id\": \"microsoft-preview\",\n \"category\": \"SOCIAL\",\n \"name\": \"microsoft-preview\",\n \"patterns\": [\n \"MicrosoftPreview\\\\/\"\n ],\n \"forbidden\": []\n },\n {\n \"id\": \"neticle-crawler\",\n \"category\": \"SOCIAL\",\n \"name\": \"neticle-crawler\",\n \"patterns\": [\n \"Neticle Crawler\"\n ],\n \"forbidden\": []\n },\n {\n \"id\": \"pagepeeker-crawler\",\n \"category\": \"SOCIAL\",\n \"name\": \"pagepeeker-crawler\",\n \"patterns\": [\n \"PagePeeker\\\\/\"\n ],\n \"forbidden\": []\n },\n {\n \"id\": \"pinterest-crawler\",\n \"category\": \"SOCIAL\",\n \"name\": \"pinterest-crawler\",\n \"patterns\": [\n \"Pinterest(bot)?\\\\/\"\n ],\n \"forbidden\": []\n },\n {\n \"id\": \"pintrest-crawler\",\n \"category\": \"SOCIAL\",\n \"name\": \"PinterestBot\",\n \"patterns\": [\n \"pinterest\\\\.com\\\\/bot\"\n ],\n \"forbidden\": []\n },\n {\n \"id\": \"reddit-crawler\",\n \"category\": \"SOCIAL\",\n \"name\": \"RedditBot\",\n \"patterns\": [\n \"redditbot\"\n ],\n \"forbidden\": []\n },\n {\n \"id\": \"skype-preview\",\n \"category\": \"SOCIAL\",\n \"name\": \"skype-preview\",\n \"patterns\": [\n \"SkypeUriPreview\"\n ],\n \"forbidden\": []\n },\n {\n \"id\": \"slack-crawler\",\n \"category\": \"SOCIAL\",\n \"name\": \"Slackbot\",\n \"patterns\": [\n \"Slackbot\"\n ],\n \"forbidden\": []\n },\n {\n \"id\": \"slack-image-proxy\",\n \"category\": \"SOCIAL\",\n \"name\": \"slack-image-proxy\",\n \"patterns\": [\n \"Slack-ImgProxy\"\n ],\n \"forbidden\": []\n },\n {\n \"id\": \"snap-preview\",\n \"category\": \"SOCIAL\",\n \"name\": \"snap-preview\",\n \"patterns\": [\n \"Snap URL Preview Service\"\n ],\n \"forbidden\": []\n },\n {\n \"id\": \"steam-preview\",\n \"category\": \"SOCIAL\",\n \"name\": \"ValveSteamBot\",\n \"patterns\": [\n \"Valve\\\\/Steam\"\n ],\n \"forbidden\": []\n },\n {\n \"id\": \"stripe-webhook\",\n \"category\": \"SOCIAL\",\n \"name\": \"stripe-webhook\",\n \"patterns\": [\n \"Stripe\\\\/\"\n ],\n \"forbidden\": []\n },\n {\n \"id\": \"synapse-crawler\",\n \"category\": \"SOCIAL\",\n \"name\": \"synapse-crawler\",\n \"patterns\": [\n \"Synapse\"\n ],\n \"forbidden\": []\n },\n {\n \"id\": \"telegram-crawler\",\n \"category\": \"SOCIAL\",\n \"name\": \"TelegramBot\",\n \"patterns\": [\n \"TelegramBot\"\n ],\n \"forbidden\": []\n },\n {\n \"id\": \"tiktok-crawler\",\n \"category\": \"SOCIAL\",\n \"name\": \"tiktok-crawler\",\n \"patterns\": [\n \"TikTokSpider\"\n ],\n \"forbidden\": []\n },\n {\n \"id\": \"trendsmap-crawler\",\n \"category\": \"SOCIAL\",\n \"name\": \"trendsmap-crawler\",\n \"patterns\": [\n \"TrendsmapResolver\"\n ],\n \"forbidden\": []\n },\n {\n \"id\": \"tweetedtimes-crawler\",\n \"category\": \"SOCIAL\",\n \"name\": \"tweetedtimes-crawler\",\n \"patterns\": [\n \"tweetedtimes\"\n ],\n \"forbidden\": []\n },\n {\n \"id\": \"twitter-crawler\",\n \"category\": \"SOCIAL\",\n \"name\": \"Twitterbot\",\n \"patterns\": [\n \"Twitterbot\"\n ],\n \"forbidden\": [\n \"facebookexternalhit\",\n \"Facebot\"\n ]\n },\n {\n \"id\": \"vercel-crawler\",\n \"category\": \"SOCIAL\",\n \"name\": \"vercel-crawler\",\n \"patterns\": [\n \"Vercelbot\"\n ],\n \"forbidden\": []\n },\n {\n \"id\": \"vercel-monitor-preview\",\n \"category\": \"SOCIAL\",\n \"name\": \"vercel-monitor-preview\",\n \"patterns\": [\n \"vercel-screenshot\"\n ],\n \"forbidden\": []\n },\n {\n \"id\": \"viber-crawler\",\n \"category\": \"SOCIAL\",\n \"name\": \"ViberBot\",\n \"patterns\": [\n \"Viber\"\n ],\n \"forbidden\": []\n },\n {\n \"id\": \"whatsapp-crawler\",\n \"category\": \"SOCIAL\",\n \"name\": \"WhatsApp\",\n \"patterns\": [\n \"WhatsApp\"\n ],\n \"forbidden\": []\n },\n {\n \"id\": \"yahoo-preview\",\n \"category\": \"SOCIAL\",\n \"name\": \"yahoo-preview\",\n \"patterns\": [\n \"Yahoo Link Preview\"\n ],\n \"forbidden\": []\n },\n {\n \"id\": \"a6corp-crawler\",\n \"category\": \"UNKNOWN\",\n \"name\": \"a6corp-crawler\",\n \"patterns\": [\n \"A6-Indexer\"\n ],\n \"forbidden\": []\n },\n {\n \"id\": \"aboundex-crawler\",\n \"category\": \"UNKNOWN\",\n \"name\": \"aboundex-crawler\",\n \"patterns\": [\n \"Aboundex\"\n ],\n \"forbidden\": []\n },\n {\n \"id\": \"acapbot\",\n \"category\": \"UNKNOWN\",\n \"name\": \"acapbot\",\n \"patterns\": [\n \"acapbot\"\n ],\n \"forbidden\": []\n },\n {\n \"id\": \"acoon-crawler\",\n \"category\": \"UNKNOWN\",\n \"name\": \"acoon-crawler\",\n \"patterns\": [\n \"acoonbot\"\n ],\n \"forbidden\": []\n },\n {\n \"id\": \"adbeat-crawler\",\n \"category\": \"UNKNOWN\",\n \"name\": \"adbeat-crawler\",\n \"patterns\": [\n \"adbeat_bot\"\n ],\n \"forbidden\": []\n },\n {\n \"id\": \"addthis-crawler\",\n \"category\": \"UNKNOWN\",\n \"name\": \"addthis-crawler\",\n \"patterns\": [\n \"AddThis\"\n ],\n \"forbidden\": []\n },\n {\n \"id\": \"admantx-crawler\",\n \"category\": \"UNKNOWN\",\n \"name\": \"admantx-crawler\",\n \"patterns\": [\n \"ADmantX\"\n ],\n \"forbidden\": []\n },\n {\n \"id\": \"adscanner-crawler\",\n \"category\": \"UNKNOWN\",\n \"name\": \"adscanner-crawler\",\n \"patterns\": [\n \"adscanner\"\n ],\n \"forbidden\": []\n },\n {\n \"id\": \"adstxtcrawler\",\n \"category\": \"UNKNOWN\",\n \"name\": \"adstxtcrawler\",\n \"patterns\": [\n \"AdsTxtCrawler\"\n ],\n \"forbidden\": []\n },\n {\n \"id\": \"advbot-crawler\",\n \"category\": \"UNKNOWN\",\n \"name\": \"advbot-crawler\",\n \"patterns\": [\n \"AdvBot\"\n ],\n \"forbidden\": []\n },\n {\n \"id\": \"alphaseobot-crawler\",\n \"category\": \"UNKNOWN\",\n \"name\": \"alphaseobot-crawler\",\n \"patterns\": [\n \"AlphaBot\"\n ],\n \"forbidden\": []\n },\n {\n \"id\": \"anderspink-crawler\",\n \"category\": \"UNKNOWN\",\n \"name\": \"anderspink-crawler\",\n \"patterns\": [\n \"AndersPinkBot\"\n ],\n \"forbidden\": []\n },\n {\n \"id\": \"antibot\",\n \"category\": \"UNKNOWN\",\n \"name\": \"antibot\",\n \"patterns\": [\n \"antibot\"\n ],\n \"forbidden\": []\n },\n {\n \"id\": \"apercite-crawler\",\n \"category\": \"UNKNOWN\",\n \"name\": \"apercite-crawler\",\n \"patterns\": [\n \"Apercite\"\n ],\n \"forbidden\": []\n },\n {\n \"id\": \"ara-crawler\",\n \"category\": \"UNKNOWN\",\n \"name\": \"ara-crawler\",\n \"patterns\": [\n \"arabot\"\n ],\n \"forbidden\": []\n },\n {\n \"id\": \"araturka-crawler\",\n \"category\": \"UNKNOWN\",\n \"name\": \"araturka-crawler\",\n \"patterns\": [\n \"Bot\\\\.AraTurka\\\\.com\"\n ],\n \"forbidden\": []\n },\n {\n \"id\": \"arocom-crawler\",\n \"category\": \"UNKNOWN\",\n \"name\": \"arocom-crawler\",\n \"patterns\": [\n \"drupact\"\n ],\n \"forbidden\": []\n },\n {\n \"id\": \"aspiegel-crawler\",\n \"category\": \"UNKNOWN\",\n \"name\": \"aspiegel-crawler\",\n \"patterns\": [\n \"AspiegelBot\"\n ],\n \"forbidden\": []\n },\n {\n \"id\": \"audisto-crawler\",\n \"category\": \"UNKNOWN\",\n \"name\": \"audisto-crawler\",\n \"patterns\": [\n \"Audisto Crawler\"\n ],\n \"forbidden\": []\n },\n {\n \"id\": \"awario-crawler\",\n \"category\": \"UNKNOWN\",\n \"name\": \"awario-crawler\",\n \"patterns\": [\n \"AwarioBot\"\n ],\n \"forbidden\": []\n },\n {\n \"id\": \"awario-crawler-smart\",\n \"category\": \"UNKNOWN\",\n \"name\": \"awario-crawler-smart\",\n \"patterns\": [\n \"AwarioSmartBot\"\n ],\n \"forbidden\": []\n },\n {\n \"id\": \"awesomecrawler\",\n \"category\": \"UNKNOWN\",\n \"name\": \"awesomecrawler\",\n \"patterns\": [\n \"awesomecrawler\"\n ],\n \"forbidden\": []\n },\n {\n \"id\": \"b2bbot\",\n \"category\": \"UNKNOWN\",\n \"name\": \"b2bbot\",\n \"patterns\": [\n \"B2B Bot\"\n ],\n \"forbidden\": []\n },\n {\n \"id\": \"backlinktest-crawler\",\n \"category\": \"UNKNOWN\",\n \"name\": \"backlinktest-crawler\",\n \"patterns\": [\n \"backlinkcrawler\"\n ],\n \"forbidden\": []\n },\n {\n \"id\": \"baidu-cloud-watch\",\n \"category\": \"UNKNOWN\",\n \"name\": \"baidu-cloud-watch\",\n \"patterns\": [\n \"Baidu-YunGuanCe\"\n ],\n \"forbidden\": []\n },\n {\n \"id\": \"betabot\",\n \"category\": \"UNKNOWN\",\n \"name\": \"betabot\",\n \"patterns\": [\n \"betaBot\"\n ],\n \"forbidden\": []\n },\n {\n \"id\": \"bidswitch-crawler\",\n \"category\": \"UNKNOWN\",\n \"name\": \"bidswitch-crawler\",\n \"patterns\": [\n \"bidswitchbot\"\n ],\n \"forbidden\": []\n },\n {\n \"id\": \"bigdatacorp-crawler\",\n \"category\": \"UNKNOWN\",\n \"name\": \"bigdatacorp-crawler\",\n \"patterns\": [\n \"BDCbot\"\n ],\n \"forbidden\": []\n },\n {\n \"id\": \"biglotron\",\n \"category\": \"UNKNOWN\",\n \"name\": \"biglotron\",\n \"patterns\": [\n \"BIGLOTRON\"\n ],\n \"forbidden\": []\n },\n {\n \"id\": \"binlar\",\n \"category\": \"UNKNOWN\",\n \"name\": \"binlar\",\n \"patterns\": [\n \"binlar\"\n ],\n \"forbidden\": []\n },\n {\n \"id\": \"bitsight-crawler\",\n \"category\": \"UNKNOWN\",\n \"name\": \"bitsight-crawler\",\n \"patterns\": [\n \"BitSightBot\\\\/\"\n ],\n \"forbidden\": []\n },\n {\n \"id\": \"blogmura-crawler\",\n \"category\": \"UNKNOWN\",\n \"name\": \"blogmura-crawler\",\n \"patterns\": [\n \"blogmuraBot\"\n ],\n \"forbidden\": []\n },\n {\n \"id\": \"blp-bbot\",\n \"category\": \"UNKNOWN\",\n \"name\": \"blp-bbot\",\n \"patterns\": [\n \"BLP_bbot\"\n ],\n \"forbidden\": []\n },\n {\n \"id\": \"bnf-crawler\",\n \"category\": \"UNKNOWN\",\n \"name\": \"bnf-crawler\",\n \"patterns\": [\n \"bnf\\\\.fr_bot\"\n ],\n \"forbidden\": []\n },\n {\n \"id\": \"bombora-crawler\",\n \"category\": \"UNKNOWN\",\n \"name\": \"bombora-crawler\",\n \"patterns\": [\n \"BomboraBot\"\n ],\n \"forbidden\": []\n },\n {\n \"id\": \"boxcar-crawler\",\n \"category\": \"UNKNOWN\",\n \"name\": \"boxcar-crawler\",\n \"patterns\": [\n \"BoxcarBot\"\n ],\n \"forbidden\": []\n },\n {\n \"id\": \"brainobot\",\n \"category\": \"UNKNOWN\",\n \"name\": \"brainobot\",\n \"patterns\": [\n \"brainobot\"\n ],\n \"forbidden\": []\n },\n {\n \"id\": \"brandonmedia-crawler\",\n \"category\": \"UNKNOWN\",\n \"name\": \"brandonmedia-crawler\",\n \"patterns\": [\n \"BrandONbot\"\n ],\n \"forbidden\": []\n },\n {\n \"id\": \"brandwatch-crawler\",\n \"category\": \"UNKNOWN\",\n \"name\": \"brandwatch-crawler\",\n \"patterns\": [\n \"magpie-crawler\"\n ],\n \"forbidden\": []\n },\n {\n \"id\": \"brightedge-crawler\",\n \"category\": \"UNKNOWN\",\n \"name\": \"brightedge-crawler\",\n \"patterns\": [\n \"BrightEdge Crawler\"\n ],\n \"forbidden\": []\n },\n {\n \"id\": \"bublup-crawler\",\n \"category\": \"UNKNOWN\",\n \"name\": \"bublup-crawler\",\n \"patterns\": [\n \"BublupBot\"\n ],\n \"forbidden\": []\n },\n {\n \"id\": \"builtwith-crawler\",\n \"category\": \"UNKNOWN\",\n \"name\": \"builtwith-crawler\",\n \"patterns\": [\n \"^BW\\\\/\"\n ],\n \"forbidden\": []\n },\n {\n \"id\": \"buzzstream-crawler\",\n \"category\": \"UNKNOWN\",\n \"name\": \"buzzstream-crawler\",\n \"patterns\": [\n \"buzzbot\"\n ],\n \"forbidden\": []\n },\n {\n \"id\": \"capsulink-crawler\",\n \"category\": \"UNKNOWN\",\n \"name\": \"capsulink-crawler\",\n \"patterns\": [\n \"CapsuleChecker\"\n ],\n \"forbidden\": []\n },\n {\n \"id\": \"careerx-crawler\",\n \"category\": \"UNKNOWN\",\n \"name\": \"careerx-crawler\",\n \"patterns\": [\n \"careerbot\"\n ],\n \"forbidden\": []\n },\n {\n \"id\": \"centurybot\",\n \"category\": \"UNKNOWN\",\n \"name\": \"centurybot\",\n \"patterns\": [\n \"centurybot\"\n ],\n \"forbidden\": []\n },\n {\n \"id\": \"checkmarknetwork-crawler\",\n \"category\": \"UNKNOWN\",\n \"name\": \"checkmarknetwork-crawler\",\n \"patterns\": [\n \"CheckMarkNetwork\\\\/\"\n ],\n \"forbidden\": []\n },\n {\n \"id\": \"chlooe-crawler\",\n \"category\": \"UNKNOWN\",\n \"name\": \"chlooe-crawler\",\n \"patterns\": [\n \"bot-pge\\\\.chlooe\\\\.com\"\n ],\n \"forbidden\": []\n },\n {\n \"id\": \"cincrawdata-crawler\",\n \"category\": \"UNKNOWN\",\n \"name\": \"cincrawdata-crawler\",\n \"patterns\": [\n \"Cincraw\"\n ],\n \"forbidden\": []\n },\n {\n \"id\": \"citeseerx-crawler\",\n \"category\": \"UNKNOWN\",\n \"name\": \"citeseerx-crawler\",\n \"patterns\": [\n \"citeseerxbot\"\n ],\n \"forbidden\": []\n },\n {\n \"id\": \"clickagy-crawler\",\n \"category\": \"UNKNOWN\",\n \"name\": \"clickagy-crawler\",\n \"patterns\": [\n \"Clickagy\"\n ],\n \"forbidden\": []\n },\n {\n \"id\": \"cliqz-crawler\",\n \"category\": \"UNKNOWN\",\n \"name\": \"cliqz-crawler\",\n \"patterns\": [\n \"Cliqzbot\\\\/\"\n ],\n \"forbidden\": []\n },\n {\n \"id\": \"cloudsystemnetworks-crawler\",\n \"category\": \"UNKNOWN\",\n \"name\": \"cloudsystemnetworks-crawler\",\n \"patterns\": [\n \"Nimbostratus-Bot\"\n ],\n \"forbidden\": []\n },\n {\n \"id\": \"coccoc-crawler\",\n \"category\": \"UNKNOWN\",\n \"name\": \"coccoc-crawler\",\n \"patterns\": [\n \"coccoc\"\n ],\n \"forbidden\": []\n },\n {\n \"id\": \"cocolyze-crawler\",\n \"category\": \"UNKNOWN\",\n \"name\": \"cocolyze-crawler\",\n \"patterns\": [\n \"Cocolyzebot\"\n ],\n \"forbidden\": []\n },\n {\n \"id\": \"codewise-crawler\",\n \"category\": \"UNKNOWN\",\n \"name\": \"codewise-crawler\",\n \"patterns\": [\n \"VoluumDSP-content-bot\"\n ],\n \"forbidden\": []\n },\n {\n \"id\": \"cognitiveseo-crawler\",\n \"category\": \"UNKNOWN\",\n \"name\": \"cognitiveseo-crawler\",\n \"patterns\": [\n \"James BOT\"\n ],\n \"forbidden\": []\n },\n {\n \"id\": \"companybook-crawler\",\n \"category\": \"UNKNOWN\",\n \"name\": \"companybook-crawler\",\n \"patterns\": [\n \"Companybook-Crawler\"\n ],\n \"forbidden\": []\n },\n {\n \"id\": \"content-crawler-spider\",\n \"category\": \"UNKNOWN\",\n \"name\": \"content-crawler-spider\",\n \"patterns\": [\n \"content crawler spider\"\n ],\n \"forbidden\": []\n },\n {\n \"id\": \"contextad-crawler\",\n \"category\": \"UNKNOWN\",\n \"name\": \"contextad-crawler\",\n \"patterns\": [\n \"ContextAd Bot\"\n ],\n \"forbidden\": []\n },\n {\n \"id\": \"contxbot\",\n \"category\": \"UNKNOWN\",\n \"name\": \"contxbot\",\n \"patterns\": [\n \"contxbot\"\n ],\n \"forbidden\": []\n },\n {\n \"id\": \"convera-crawler\",\n \"category\": \"UNKNOWN\",\n \"name\": \"convera-crawler\",\n \"patterns\": [\n \"convera\"\n ],\n \"forbidden\": []\n },\n {\n \"id\": \"cookiebot-crawler\",\n \"category\": \"UNKNOWN\",\n \"name\": \"cookiebot-crawler\",\n \"patterns\": [\n \"Cookiebot\"\n ],\n \"forbidden\": []\n },\n {\n \"id\": \"creativecommons-crawler\",\n \"category\": \"UNKNOWN\",\n \"name\": \"creativecommons-crawler\",\n \"patterns\": [\n \"CC Metadata Scaper\"\n ],\n \"forbidden\": []\n },\n {\n \"id\": \"criteo-crawler\",\n \"category\": \"UNKNOWN\",\n \"name\": \"criteo-crawler\",\n \"patterns\": [\n \"CriteoBot\"\n ],\n \"forbidden\": []\n },\n {\n \"id\": \"crystalsemantics-crawler\",\n \"category\": \"UNKNOWN\",\n \"name\": \"crystalsemantics-crawler\",\n \"patterns\": [\n \"CrystalSemanticsBot\"\n ],\n \"forbidden\": []\n },\n {\n \"id\": \"curebot-crawler\",\n \"category\": \"UNKNOWN\",\n \"name\": \"curebot-crawler\",\n \"patterns\": [\n \"[Cc]urebot\"\n ],\n \"forbidden\": []\n },\n {\n \"id\": \"cutbot-crawler\",\n \"category\": \"UNKNOWN\",\n \"name\": \"cutbot-crawler\",\n \"patterns\": [\n \"Cutbot\"\n ],\n \"forbidden\": []\n },\n {\n \"id\": \"cxense-crawler\",\n \"category\": \"UNKNOWN\",\n \"name\": \"cxense-crawler\",\n \"patterns\": [\n \"cXensebot\"\n ],\n \"forbidden\": []\n },\n {\n \"id\": \"cyberpatrol-crawler\",\n \"category\": \"UNKNOWN\",\n \"name\": \"cyberpatrol-crawler\",\n \"patterns\": [\n \"CyberPatrol\"\n ],\n \"forbidden\": []\n },\n {\n \"id\": \"datafeedwatch-crawler\",\n \"category\": \"UNKNOWN\",\n \"name\": \"datafeedwatch-crawler\",\n \"patterns\": [\n \"Datafeedwatch\"\n ],\n \"forbidden\": []\n },\n {\n \"id\": \"dataforseo-crawler\",\n \"category\": \"UNKNOWN\",\n \"name\": \"dataforseo-crawler\",\n \"patterns\": [\n \"DataForSeoBot\"\n ],\n \"forbidden\": []\n },\n {\n \"id\": \"datagnion-crawler\",\n \"category\": \"UNKNOWN\",\n \"name\": \"datagnion-crawler\",\n \"patterns\": [\n \"datagnionbot\"\n ],\n \"forbidden\": []\n },\n {\n \"id\": \"datanyze-crawler\",\n \"category\": \"UNKNOWN\",\n \"name\": \"datanyze-crawler\",\n \"patterns\": [\n \"Datanyze\"\n ],\n \"forbidden\": []\n },\n {\n \"id\": \"dataprovider-crawler\",\n \"category\": \"UNKNOWN\",\n \"name\": \"dataprovider-crawler\",\n \"patterns\": [\n \"Dataprovider\\\\.com\"\n ],\n \"forbidden\": []\n },\n {\n \"id\": \"datenbutler-crawler\",\n \"category\": \"UNKNOWN\",\n \"name\": \"datenbutler-crawler\",\n \"patterns\": [\n \"mindUpBot\"\n ],\n \"forbidden\": []\n },\n {\n \"id\": \"daum-crawler\",\n \"category\": \"UNKNOWN\",\n \"name\": \"daum-crawler\",\n \"patterns\": [\n \"Daum\\\\/\"\n ],\n \"forbidden\": []\n },\n {\n \"id\": \"deepnoc-crawler\",\n \"category\": \"UNKNOWN\",\n \"name\": \"deepnoc-crawler\",\n \"patterns\": [\n \"deepnoc\"\n ],\n \"forbidden\": []\n },\n {\n \"id\": \"deusu-crawler\",\n \"category\": \"UNKNOWN\",\n \"name\": \"deusu-crawler\",\n \"patterns\": [\n \"DeuSu\\\\/\"\n ],\n \"forbidden\": []\n },\n {\n \"id\": \"digincore-crawler\",\n \"category\": \"UNKNOWN\",\n \"name\": \"digincore-crawler\",\n \"patterns\": [\n \"Digincore bot\"\n ],\n \"forbidden\": []\n },\n {\n \"id\": \"digitaldragon-crawler\",\n \"category\": \"UNKNOWN\",\n \"name\": \"digitaldragon-crawler\",\n \"patterns\": [\n \"CrawlyProjectCrawler\"\n ],\n \"forbidden\": []\n },\n {\n \"id\": \"discoveryengine-crawler\",\n \"category\": \"UNKNOWN\",\n \"name\": \"discoveryengine-crawler\",\n \"patterns\": [\n \"discobot\"\n ],\n \"forbidden\": []\n },\n {\n \"id\": \"dnyz-crawler\",\n \"category\": \"UNKNOWN\",\n \"name\": \"dnyz-crawler\",\n \"patterns\": [\n \"DnyzBot\"\n ],\n \"forbidden\": []\n },\n {\n \"id\": \"domaincrawler-crawler\",\n \"category\": \"UNKNOWN\",\n \"name\": \"domaincrawler-crawler\",\n \"patterns\": [\n \"domaincrawler\"\n ],\n \"forbidden\": []\n },\n {\n \"id\": \"domainreanimator-crawler\",\n \"category\": \"UNKNOWN\",\n \"name\": \"domainreanimator-crawler\",\n \"patterns\": [\n \"Domain Re-Animator Bot\"\n ],\n \"forbidden\": []\n },\n {\n \"id\": \"domainsbot-crawler\",\n \"category\": \"UNKNOWN\",\n \"name\": \"domainsbot-crawler\",\n \"patterns\": [\n \"Pandalytics\"\n ],\n \"forbidden\": []\n },\n {\n \"id\": \"domainstats-crawler\",\n \"category\": \"UNKNOWN\",\n \"name\": \"domainstats-crawler\",\n \"patterns\": [\n \"DomainStatsBot\"\n ],\n \"forbidden\": []\n },\n {\n \"id\": \"domaintools-crawler\",\n \"category\": \"UNKNOWN\",\n \"name\": \"domaintools-crawler\",\n \"patterns\": [\n \"SurveyBot\"\n ],\n \"forbidden\": []\n },\n {\n \"id\": \"dotnetdotcom-crawler\",\n \"category\": \"UNKNOWN\",\n \"name\": \"dotnetdotcom-crawler\",\n \"patterns\": [\n \"ezooms\"\n ],\n \"forbidden\": []\n },\n {\n \"id\": \"dragonmetrics-crawler\",\n \"category\": \"UNKNOWN\",\n \"name\": \"dragonmetrics-crawler\",\n \"patterns\": [\n \"Dragonbot\"\n ],\n \"forbidden\": []\n },\n {\n \"id\": \"driftnet-crawler\",\n \"category\": \"UNKNOWN\",\n \"name\": \"driftnet-crawler\",\n \"patterns\": [\n \"InternetMeasurement\"\n ],\n \"forbidden\": []\n },\n {\n \"id\": \"duedil-crawler\",\n \"category\": \"UNKNOWN\",\n \"name\": \"duedil-crawler\",\n \"patterns\": [\n \"electricmonk\"\n ],\n \"forbidden\": []\n },\n {\n \"id\": \"ec2linkfinder\",\n \"category\": \"UNKNOWN\",\n \"name\": \"ec2linkfinder\",\n \"patterns\": [\n \"ec2linkfinder\"\n ],\n \"forbidden\": []\n },\n {\n \"id\": \"edister-crawler\",\n \"category\": \"UNKNOWN\",\n \"name\": \"edister-crawler\",\n \"patterns\": [\n \"edisterbot\"\n ],\n \"forbidden\": []\n },\n {\n \"id\": \"elisabot\",\n \"category\": \"UNKNOWN\",\n \"name\": \"elisabot\",\n \"patterns\": [\n \"elisabot\"\n ],\n \"forbidden\": []\n },\n {\n \"id\": \"epictions-crawler\",\n \"category\": \"UNKNOWN\",\n \"name\": \"epictions-crawler\",\n \"patterns\": [\n \"epicbot\"\n ],\n \"forbidden\": []\n },\n {\n \"id\": \"eright-crawler\",\n \"category\": \"UNKNOWN\",\n \"name\": \"eright-crawler\",\n \"patterns\": [\n \"eright\"\n ],\n \"forbidden\": []\n },\n {\n \"id\": \"europarchive-crawler\",\n \"category\": \"UNKNOWN\",\n \"name\": \"europarchive-crawler\",\n \"patterns\": [\n \"europarchive\\\\.org\"\n ],\n \"forbidden\": []\n },\n {\n \"id\": \"eventures-crawler\",\n \"category\": \"UNKNOWN\",\n \"name\": \"eventures-crawler\",\n \"patterns\": [\n \"e\\\\.ventures Investment Crawler\"\n ],\n \"forbidden\": []\n },\n {\n \"id\": \"eventures-crawler-batch\",\n \"category\": \"UNKNOWN\",\n \"name\": \"eventures-crawler-batch\",\n \"patterns\": [\n \"evc-batch\"\n ],\n \"forbidden\": []\n },\n {\n \"id\": \"exensa-crawler\",\n \"category\": \"UNKNOWN\",\n \"name\": \"exensa-crawler\",\n \"patterns\": [\n \"Bark[rR]owler\"\n ],\n \"forbidden\": []\n },\n {\n \"id\": \"experibot-crawler\",\n \"category\": \"UNKNOWN\",\n \"name\": \"experibot-crawler\",\n \"patterns\": [\n \"Experibot\"\n ],\n \"forbidden\": []\n },\n {\n \"id\": \"extlinks-crawler\",\n \"category\": \"UNKNOWN\",\n \"name\": \"extlinks-crawler\",\n \"patterns\": [\n \"ExtLinksBot\"\n ],\n \"forbidden\": []\n },\n {\n \"id\": \"eyeota-crawler\",\n \"category\": \"UNKNOWN\",\n \"name\": \"eyeota-crawler\",\n \"patterns\": [\n \"Eyeotabot\"\n ],\n \"forbidden\": []\n },\n {\n \"id\": \"fast-crawler\",\n \"category\": \"UNKNOWN\",\n \"name\": \"fast-crawler\",\n \"patterns\": [\n \"FAST-WebCrawler\"\n ],\n \"forbidden\": []\n },\n {\n \"id\": \"fast-crawler-enterprise\",\n \"category\": \"UNKNOWN\",\n \"name\": \"fast-crawler-enterprise\",\n \"patterns\": [\n \"FAST Enterprise Crawler\"\n ],\n \"forbidden\": []\n },\n {\n \"id\": \"fedoraplanet-crawler\",\n \"category\": \"UNKNOWN\",\n \"name\": \"fedoraplanet-crawler\",\n \"patterns\": [\n \"fedoraplanet\"\n ],\n \"forbidden\": []\n },\n {\n \"id\": \"feedafever-crawler\",\n \"category\": \"UNKNOWN\",\n \"name\": \"feedafever-crawler\",\n \"patterns\": [\n \"Fever\"\n ],\n \"forbidden\": []\n },\n {\n \"id\": \"femtosearch-crawler\",\n \"category\": \"UNKNOWN\",\n \"name\": \"femtosearch-crawler\",\n \"patterns\": [\n \"FemtosearchBot\"\n ],\n \"forbidden\": []\n },\n {\n \"id\": \"findthatfile-crawler\",\n \"category\": \"UNKNOWN\",\n \"name\": \"findthatfile-crawler\",\n \"patterns\": [\n \"findthatfile\"\n ],\n \"forbidden\": []\n },\n {\n \"id\": \"flamingosearch-crawler\",\n \"category\": \"UNKNOWN\",\n \"name\": \"flamingosearch-crawler\",\n \"patterns\": [\n \"Flamingo_SearchEngine\"\n ],\n \"forbidden\": []\n },\n {\n \"id\": \"fluffy\",\n \"category\": \"UNKNOWN\",\n \"name\": \"fluffy\",\n \"patterns\": [\n \"fluffy\"\n ],\n \"forbidden\": []\n },\n {\n \"id\": \"fr-crawler\",\n \"category\": \"UNKNOWN\",\n \"name\": \"fr-crawler\",\n \"patterns\": [\n \"fr-crawler\"\n ],\n \"forbidden\": []\n },\n {\n \"id\": \"fuelbot\",\n \"category\": \"UNKNOWN\",\n \"name\": \"fuelbot\",\n \"patterns\": [\n \"fuelbot\"\n ],\n \"forbidden\": []\n },\n {\n \"id\": \"fyrebot\",\n \"category\": \"UNKNOWN\",\n \"name\": \"fyrebot\",\n \"patterns\": [\n \"Fyrebot\"\n ],\n \"forbidden\": []\n },\n {\n \"id\": \"g00g1e-crawler\",\n \"category\": \"UNKNOWN\",\n \"name\": \"g00g1e-crawler\",\n \"patterns\": [\n \"g00g1e\\\\.net\"\n ],\n \"forbidden\": []\n },\n {\n \"id\": \"g2webservices-crawler\",\n \"category\": \"UNKNOWN\",\n \"name\": \"g2webservices-crawler\",\n \"patterns\": [\n \"G2 Web Services\"\n ],\n \"forbidden\": []\n },\n {\n \"id\": \"garlik-crawler\",\n \"category\": \"UNKNOWN\",\n \"name\": \"garlik-crawler\",\n \"patterns\": [\n \"GarlikCrawler\"\n ],\n \"forbidden\": []\n },\n {\n \"id\": \"genieo-crawler\",\n \"category\": \"UNKNOWN\",\n \"name\": \"genieo-crawler\",\n \"patterns\": [\n \"Genieo\"\n ],\n \"forbidden\": []\n },\n {\n \"id\": \"gigablast-crawler\",\n \"category\": \"UNKNOWN\",\n \"name\": \"gigablast-crawler\",\n \"patterns\": [\n \"Gigabot\"\n ],\n \"forbidden\": []\n },\n {\n \"id\": \"ginger-crawler\",\n \"category\": \"UNKNOWN\",\n \"name\": \"ginger-crawler\",\n \"patterns\": [\n \"GingerCrawler\"\n ],\n \"forbidden\": []\n },\n {\n \"id\": \"gnam-gnam-spider\",\n \"category\": \"UNKNOWN\",\n \"name\": \"gnam-gnam-spider\",\n \"patterns\": [\n \"gnam gnam spider\"\n ],\n \"forbidden\": []\n },\n {\n \"id\": \"gnowit-crawler\",\n \"category\": \"UNKNOWN\",\n \"name\": \"gnowit-crawler\",\n \"patterns\": [\n \"GnowitNewsbot\"\n ],\n \"forbidden\": []\n },\n {\n \"id\": \"goo-crawler\",\n \"category\": \"UNKNOWN\",\n \"name\": \"goo-crawler\",\n \"patterns\": [\n \"ichiro\"\n ],\n \"forbidden\": []\n },\n {\n \"id\": \"grapeshot-crawler\",\n \"category\": \"UNKNOWN\",\n \"name\": \"grapeshot-crawler\",\n \"patterns\": [\n \"GrapeshotCrawler\"\n ],\n \"forbidden\": []\n },\n {\n \"id\": \"grob-crawler\",\n \"category\": \"UNKNOWN\",\n \"name\": \"grob-crawler\",\n \"patterns\": [\n \"Grobbot\"\n ],\n \"forbidden\": []\n },\n {\n \"id\": \"grouphigh-crawler\",\n \"category\": \"UNKNOWN\",\n \"name\": \"grouphigh-crawler\",\n \"patterns\": [\n \"GroupHigh\\\\/\"\n ],\n \"forbidden\": []\n },\n {\n \"id\": \"grub\",\n \"category\": \"UNKNOWN\",\n \"name\": \"grub\",\n \"patterns\": [\n \"grub\\\\.org\"\n ],\n \"forbidden\": []\n },\n {\n \"id\": \"gslfbot\",\n \"category\": \"UNKNOWN\",\n \"name\": \"gslfbot\",\n \"patterns\": [\n \"gslfbot\"\n ],\n \"forbidden\": []\n },\n {\n \"id\": \"gwene-crawler\",\n \"category\": \"UNKNOWN\",\n \"name\": \"gwene-crawler\",\n \"patterns\": [\n \"Gwene\"\n ],\n \"forbidden\": []\n },\n {\n \"id\": \"haosou-crawler\",\n \"category\": \"UNKNOWN\",\n \"name\": \"haosou-crawler\",\n \"patterns\": [\n \"360Spider\"\n ],\n \"forbidden\": []\n },\n {\n \"id\": \"hatena-crawler\",\n \"category\": \"UNKNOWN\",\n \"name\": \"hatena-crawler\",\n \"patterns\": [\n \"Hatena\"\n ],\n \"forbidden\": []\n },\n {\n \"id\": \"headline-crawler\",\n \"category\": \"UNKNOWN\",\n \"name\": \"headline-crawler\",\n \"patterns\": [\n \"ev-crawler\\\\/\"\n ],\n \"forbidden\": []\n },\n {\n \"id\": \"hoyer-crawler\",\n \"category\": \"UNKNOWN\",\n \"name\": \"hoyer-crawler\",\n \"patterns\": [\n \"Friendica\"\n ],\n \"forbidden\": []\n },\n {\n \"id\": \"httrack\",\n \"category\": \"UNKNOWN\",\n \"name\": \"httrack\",\n \"patterns\": [\n \"HTTrack\"\n ],\n \"forbidden\": []\n },\n {\n \"id\": \"hypefactors-crawler\",\n \"category\": \"UNKNOWN\",\n \"name\": \"hypefactors-crawler\",\n \"patterns\": [\n \"Buck\\\\/\"\n ],\n \"forbidden\": []\n },\n {\n \"id\": \"hypestat-crawler\",\n \"category\": \"UNKNOWN\",\n \"name\": \"hypestat-crawler\",\n \"patterns\": [\n \"hypestat\"\n ],\n \"forbidden\": []\n },\n {\n \"id\": \"hyscore-crawler\",\n \"category\": \"UNKNOWN\",\n \"name\": \"hyscore-crawler\",\n \"patterns\": [\n \"hyscore\\\\.io\"\n ],\n \"forbidden\": []\n },\n {\n \"id\": \"ia-archiver\",\n \"category\": \"UNKNOWN\",\n \"name\": \"ia-archiver\",\n \"patterns\": [\n \"ia_archiver\"\n ],\n \"forbidden\": []\n },\n {\n \"id\": \"ideasandcode-crawler\",\n \"category\": \"UNKNOWN\",\n \"name\": \"ideasandcode-crawler\",\n \"patterns\": [\n \"ICBot\\\\/\"\n ],\n \"forbidden\": []\n },\n {\n \"id\": \"indeed-crawler\",\n \"category\": \"UNKNOWN\",\n \"name\": \"indeed-crawler\",\n \"patterns\": [\n \"IndeedBot\"\n ],\n \"forbidden\": []\n },\n {\n \"id\": \"inetdex-crawler\",\n \"category\": \"UNKNOWN\",\n \"name\": \"inetdex-crawler\",\n \"patterns\": [\n \"INETDEX-BOT\"\n ],\n \"forbidden\": []\n },\n {\n \"id\": \"infoo-crawler\",\n \"category\": \"UNKNOWN\",\n \"name\": \"infoo-crawler\",\n \"patterns\": [\n \"infoobot\"\n ],\n \"forbidden\": []\n },\n {\n \"id\": \"integromedb-crawler\",\n \"category\": \"UNKNOWN\",\n \"name\": \"integromedb-crawler\",\n \"patterns\": [\n \"integromedb\"\n ],\n \"forbidden\": []\n },\n {\n \"id\": \"intelium-crawler\",\n \"category\": \"UNKNOWN\",\n \"name\": \"intelium-crawler\",\n \"patterns\": [\n \"intelium_bot\"\n ],\n \"forbidden\": []\n },\n {\n \"id\": \"ionos-crawler\",\n \"category\": \"UNKNOWN\",\n \"name\": \"ionos-crawler\",\n \"patterns\": [\n \"IonCrawl\"\n ],\n \"forbidden\": []\n },\n {\n \"id\": \"ip-web-crawler\",\n \"category\": \"UNKNOWN\",\n \"name\": \"ip-web-crawler\",\n \"patterns\": [\n \"ip-web-crawler\\\\.com\"\n ],\n \"forbidden\": []\n },\n {\n \"id\": \"iskanie-crawler\",\n \"category\": \"UNKNOWN\",\n \"name\": \"iskanie-crawler\",\n \"patterns\": [\n \"iskanie\"\n ],\n \"forbidden\": []\n },\n {\n \"id\": \"iss-crawler\",\n \"category\": \"UNKNOWN\",\n \"name\": \"iss-crawler\",\n \"patterns\": [\n \"filterdb\\\\.iss\\\\.net\\\\/crawler\"\n ],\n \"forbidden\": []\n },\n {\n \"id\": \"it2media-crawler\",\n \"category\": \"UNKNOWN\",\n \"name\": \"it2media-crawler\",\n \"patterns\": [\n \"it2media-domain-crawler\"\n ],\n \"forbidden\": []\n },\n {\n \"id\": \"itinfluentials-crawler\",\n \"category\": \"UNKNOWN\",\n \"name\": \"itinfluentials-crawler\",\n \"patterns\": [\n \"FindITAnswersbot\"\n ],\n \"forbidden\": []\n },\n {\n \"id\": \"jamiembrown-crawler\",\n \"category\": \"UNKNOWN\",\n \"name\": \"jamiembrown-crawler\",\n \"patterns\": [\n \"Jamie's Spider\"\n ],\n \"forbidden\": []\n },\n {\n \"id\": \"jetslide-crawler\",\n \"category\": \"UNKNOWN\",\n \"name\": \"jetslide-crawler\",\n \"patterns\": [\n \"Jetslide\"\n ],\n \"forbidden\": []\n },\n {\n \"id\": \"jobboerse-crawler\",\n \"category\": \"UNKNOWN\",\n \"name\": \"jobboerse-crawler\",\n \"patterns\": [\n \"JobboerseBot\"\n ],\n \"forbidden\": []\n },\n {\n \"id\": \"jooble-crawler\",\n \"category\": \"UNKNOWN\",\n \"name\": \"jooble-crawler\",\n \"patterns\": [\n \"Jooblebot\"\n ],\n \"forbidden\": []\n },\n {\n \"id\": \"jusprog-crawler\",\n \"category\": \"UNKNOWN\",\n \"name\": \"jusprog-crawler\",\n \"patterns\": [\n \"Jugendschutzprogramm-Crawler\"\n ],\n \"forbidden\": []\n },\n {\n \"id\": \"jyxo-crawler\",\n \"category\": \"UNKNOWN\",\n \"name\": \"jyxo-crawler\",\n \"patterns\": [\n \"jyxobot\"\n ],\n \"forbidden\": []\n },\n {\n \"id\": \"k7computing-crawler\",\n \"category\": \"UNKNOWN\",\n \"name\": \"k7computing-crawler\",\n \"patterns\": [\n \"K7MLWCBot\"\n ],\n \"forbidden\": []\n },\n {\n \"id\": \"kemvi-crawler\",\n \"category\": \"UNKNOWN\",\n \"name\": \"kemvi-crawler\",\n \"patterns\": [\n \"Kemvibot\"\n ],\n \"forbidden\": []\n },\n {\n \"id\": \"komodia-crawler\",\n \"category\": \"UNKNOWN\",\n \"name\": \"komodia-crawler\",\n \"patterns\": [\n \"KomodiaBot\"\n ],\n \"forbidden\": []\n },\n {\n \"id\": \"kosmio-crawler\",\n \"category\": \"UNKNOWN\",\n \"name\": \"kosmio-crawler\",\n \"patterns\": [\n \"KosmioBot\"\n ],\n \"forbidden\": []\n },\n {\n \"id\": \"landaumedia-crawler\",\n \"category\": \"UNKNOWN\",\n \"name\": \"landaumedia-crawler\",\n \"patterns\": [\n \"Landau-Media-Spider\"\n ],\n \"forbidden\": []\n },\n {\n \"id\": \"laserlike-crawler\",\n \"category\": \"UNKNOWN\",\n \"name\": \"laserlike-crawler\",\n \"patterns\": [\n \"Laserlikebot\"\n ],\n \"forbidden\": []\n },\n {\n \"id\": \"lb-spider\",\n \"category\": \"UNKNOWN\",\n \"name\": \"lb-spider\",\n \"patterns\": [\n \"lb-spider\"\n ],\n \"forbidden\": []\n },\n {\n \"id\": \"leiki-crawler\",\n \"category\": \"UNKNOWN\",\n \"name\": \"leiki-crawler\",\n \"patterns\": [\n \"Leikibot\"\n ],\n \"forbidden\": []\n },\n {\n \"id\": \"lightspeedsystems-crawler\",\n \"category\": \"UNKNOWN\",\n \"name\": \"lightspeedsystems-crawler\",\n \"patterns\": [\n \"LightspeedSystemsCrawler\"\n ],\n \"forbidden\": []\n },\n {\n \"id\": \"line-crawler\",\n \"category\": \"UNKNOWN\",\n \"name\": \"line-crawler\",\n \"patterns\": [\n \"Linespider\"\n ],\n \"forbidden\": []\n },\n {\n \"id\": \"linkapedia-crawler\",\n \"category\": \"UNKNOWN\",\n \"name\": \"linkapedia-crawler\",\n \"patterns\": [\n \"linkapediabot\"\n ],\n \"forbidden\": []\n },\n {\n \"id\": \"linkdex-crawler\",\n \"category\": \"UNKNOWN\",\n \"name\": \"linkdex-crawler\",\n \"patterns\": [\n \"linkdex\"\n ],\n \"forbidden\": []\n },\n {\n \"id\": \"linkfluence-crawler\",\n \"category\": \"UNKNOWN\",\n \"name\": \"linkfluence-crawler\",\n \"patterns\": [\n \"YaK\\\\/\"\n ],\n \"forbidden\": []\n },\n {\n \"id\": \"linkis-crawler\",\n \"category\": \"UNKNOWN\",\n \"name\": \"linkis-crawler\",\n \"patterns\": [\n \"LinkisBot\"\n ],\n \"forbidden\": []\n },\n {\n \"id\": \"lipperhey-crawler\",\n \"category\": \"UNKNOWN\",\n \"name\": \"lipperhey-crawler\",\n \"patterns\": [\n \"lipperhey\"\n ],\n \"forbidden\": []\n },\n {\n \"id\": \"livelap-crawler\",\n \"category\": \"UNKNOWN\",\n \"name\": \"livelap-crawler\",\n \"patterns\": [\n \"Livelap[bB]ot\"\n ],\n \"forbidden\": []\n },\n {\n \"id\": \"logly-crawler\",\n \"category\": \"UNKNOWN\",\n \"name\": \"logly-crawler\",\n \"patterns\": [\n \"zenback bot\"\n ],\n \"forbidden\": []\n },\n {\n \"id\": \"loop-crawler\",\n \"category\": \"UNKNOWN\",\n \"name\": \"loop-crawler\",\n \"patterns\": [\n \"netresearchserver\"\n ],\n \"forbidden\": []\n },\n {\n \"id\": \"lssbot\",\n \"category\": \"UNKNOWN\",\n \"name\": \"lssbot\",\n \"patterns\": [\n \"lssbot\"\n ],\n \"forbidden\": []\n },\n {\n \"id\": \"lssbot-rocket\",\n \"category\": \"UNKNOWN\",\n \"name\": \"lssbot-rocket\",\n \"patterns\": [\n \"lssrocketcrawler\"\n ],\n \"forbidden\": []\n },\n {\n \"id\": \"ltx71-crawler\",\n \"category\": \"UNKNOWN\",\n \"name\": \"ltx71-crawler\",\n \"patterns\": [\n \"ltx71\"\n ],\n \"forbidden\": []\n },\n {\n \"id\": \"luminator-crawler\",\n \"category\": \"UNKNOWN\",\n \"name\": \"luminator-crawler\",\n \"patterns\": [\n \"Luminator-robots\"\n ],\n \"forbidden\": []\n },\n {\n \"id\": \"mailru-crawler\",\n \"category\": \"UNKNOWN\",\n \"name\": \"MailRuBot\",\n \"patterns\": [\n \"Mail\\\\.RU_Bot\"\n ],\n \"forbidden\": []\n },\n {\n \"id\": \"mappydata-crawler\",\n \"category\": \"UNKNOWN\",\n \"name\": \"mappydata-crawler\",\n \"patterns\": [\n \"mappydata\"\n ],\n \"forbidden\": []\n },\n {\n \"id\": \"mauibot\",\n \"category\": \"UNKNOWN\",\n \"name\": \"mauibot\",\n \"patterns\": [\n \"MauiBot\"\n ],\n \"forbidden\": []\n },\n {\n \"id\": \"megaindex-crawler\",\n \"category\": \"UNKNOWN\",\n \"name\": \"megaindex-crawler\",\n \"patterns\": [\n \"MegaIndex\"\n ],\n \"forbidden\": []\n },\n {\n \"id\": \"meltwater-crawler\",\n \"category\": \"UNKNOWN\",\n \"name\": \"meltwater-crawler\",\n \"patterns\": [\n \"MeltwaterNews\"\n ],\n \"forbidden\": []\n },\n {\n \"id\": \"metadatalabs-crawler\",\n \"category\": \"UNKNOWN\",\n \"name\": \"metadatalabs-crawler\",\n \"patterns\": [\n \"mlbot\"\n ],\n \"forbidden\": []\n },\n {\n \"id\": \"metajob-crawler\",\n \"category\": \"UNKNOWN\",\n \"name\": \"metajob-crawler\",\n \"patterns\": [\n \"MetaJobBot\"\n ],\n \"forbidden\": []\n },\n {\n \"id\": \"metauri-crawler\",\n \"category\": \"UNKNOWN\",\n \"name\": \"metauri-crawler\",\n \"patterns\": [\n \"MetaURI\"\n ],\n \"forbidden\": []\n },\n {\n \"id\": \"metricstools-crawler\",\n \"category\": \"UNKNOWN\",\n \"name\": \"metricstools-crawler\",\n \"patterns\": [\n \"MTRobot\"\n ],\n \"forbidden\": []\n },\n {\n \"id\": \"mignify-crawler\",\n \"category\": \"UNKNOWN\",\n \"name\": \"mignify-crawler\",\n \"patterns\": [\n \"memorybot\"\n ],\n \"forbidden\": []\n },\n {\n \"id\": \"mignify-imrbot\",\n \"category\": \"UNKNOWN\",\n \"name\": \"mignify-imrbot\",\n \"patterns\": [\n \"imrbot\"\n ],\n \"forbidden\": []\n },\n {\n \"id\": \"mixnode-cache\",\n \"category\": \"UNKNOWN\",\n \"name\": \"mixnode-cache\",\n \"patterns\": [\n \"MixnodeCache\\\\/\"\n ],\n \"forbidden\": []\n },\n {\n \"id\": \"moodle-crawler\",\n \"category\": \"UNKNOWN\",\n \"name\": \"moodle-crawler\",\n \"patterns\": [\n \"MoodleBot\"\n ],\n \"forbidden\": []\n },\n {\n \"id\": \"moreover-crawler\",\n \"category\": \"UNKNOWN\",\n \"name\": \"moreover-crawler\",\n \"patterns\": [\n \"Moreover\"\n ],\n \"forbidden\": []\n },\n {\n \"id\": \"moz-crawler\",\n \"category\": \"UNKNOWN\",\n \"name\": \"moz-crawler\",\n \"patterns\": [\n \"dotbot\"\n ],\n \"forbidden\": []\n },\n {\n \"id\": \"muckrack-crawler\",\n \"category\": \"UNKNOWN\",\n \"name\": \"muckrack-crawler\",\n \"patterns\": [\n \"MuckRack\"\n ],\n \"forbidden\": []\n },\n {\n \"id\": \"multiviewbot\",\n \"category\": \"UNKNOWN\",\n \"name\": \"multiviewbot\",\n \"patterns\": [\n \"Multiviewbot\"\n ],\n \"forbidden\": []\n },\n {\n \"id\": \"naver-crawler\",\n \"category\": \"UNKNOWN\",\n \"name\": \"naver-crawler\",\n \"patterns\": [\n \"Yeti\"\n ],\n \"forbidden\": []\n },\n {\n \"id\": \"neeva-crawler\",\n \"category\": \"UNKNOWN\",\n \"name\": \"neeva-crawler\",\n \"patterns\": [\n \"Neevabot\"\n ],\n \"forbidden\": []\n },\n {\n \"id\": \"nerdbynature-crawler\",\n \"category\": \"UNKNOWN\",\n \"name\": \"nerdbynature-crawler\",\n \"patterns\": [\n \"NerdByNature\\\\.Bot\"\n ],\n \"forbidden\": []\n },\n {\n \"id\": \"nerdybot-crawler\",\n \"category\": \"UNKNOWN\",\n \"name\": \"nerdybot-crawler\",\n \"patterns\": [\n \"nerdybot\"\n ],\n \"forbidden\": []\n },\n {\n \"id\": \"netcraft-crawler\",\n \"category\": \"UNKNOWN\",\n \"name\": \"netcraft-crawler\",\n \"patterns\": [\n \"NetcraftSurveyAgent\"\n ],\n \"forbidden\": []\n },\n {\n \"id\": \"netsystemsresearch-crawler\",\n \"category\": \"UNKNOWN\",\n \"name\": \"netsystemsresearch-crawler\",\n \"patterns\": [\n \"NetSystemsResearch\"\n ],\n \"forbidden\": []\n },\n {\n \"id\": \"netvibes-crawler\",\n \"category\": \"UNKNOWN\",\n \"name\": \"netvibes-crawler\",\n \"patterns\": [\n \"Netvibes\"\n ],\n \"forbidden\": []\n },\n {\n \"id\": \"newsharecounts-crawler\",\n \"category\": \"UNKNOWN\",\n \"name\": \"newsharecounts-crawler\",\n \"patterns\": [\n \"newsharecounts\"\n ],\n \"forbidden\": []\n },\n {\n \"id\": \"newspaper\",\n \"category\": \"UNKNOWN\",\n \"name\": \"newspaper\",\n \"patterns\": [\n \"newspaper\\\\/\"\n ],\n \"forbidden\": []\n },\n {\n \"id\": \"nextcloud-crawler\",\n \"category\": \"UNKNOWN\",\n \"name\": \"NextCloudBot\",\n \"patterns\": [\n \"NextCloud\"\n ],\n \"forbidden\": []\n },\n {\n \"id\": \"niki-bot\",\n \"category\": \"UNKNOWN\",\n \"name\": \"niki-bot\",\n \"patterns\": [\n \"niki-bot\"\n ],\n \"forbidden\": []\n },\n {\n \"id\": \"ning-crawler\",\n \"category\": \"UNKNOWN\",\n \"name\": \"ning-crawler\",\n \"patterns\": [\n \"NING\\\\/\"\n ],\n \"forbidden\": []\n },\n {\n \"id\": \"ninjabot\",\n \"category\": \"UNKNOWN\",\n \"name\": \"ninjabot\",\n \"patterns\": [\n \"NINJA bot\"\n ],\n \"forbidden\": []\n },\n {\n \"id\": \"nuzzel-crawler\",\n \"category\": \"UNKNOWN\",\n \"name\": \"nuzzel-crawler\",\n \"patterns\": [\n \"Nuzzel\"\n ],\n \"forbidden\": []\n },\n {\n \"id\": \"ocarinabot\",\n \"category\": \"UNKNOWN\",\n \"name\": \"ocarinabot\",\n \"patterns\": [\n \"Ocarinabot\"\n ],\n \"forbidden\": []\n },\n {\n \"id\": \"okru-crawler\",\n \"category\": \"UNKNOWN\",\n \"name\": \"okru-crawler\",\n \"patterns\": [\n \"OdklBot\\\\/\"\n ],\n \"forbidden\": []\n },\n {\n \"id\": \"opengraphcheck-crawler\",\n \"category\": \"UNKNOWN\",\n \"name\": \"opengraphcheck-crawler\",\n \"patterns\": [\n \"OpenGraphCheck\"\n ],\n \"forbidden\": []\n },\n {\n \"id\": \"openhose-crawler\",\n \"category\": \"UNKNOWN\",\n \"name\": \"openhose-crawler\",\n \"patterns\": [\n \"OpenHoseBot\"\n ],\n \"forbidden\": []\n },\n {\n \"id\": \"openindex-crawler\",\n \"category\": \"UNKNOWN\",\n \"name\": \"openindex-crawler\",\n \"patterns\": [\n \"openindexspider\"\n ],\n \"forbidden\": []\n },\n {\n \"id\": \"orange-crawler\",\n \"category\": \"UNKNOWN\",\n \"name\": \"orange-crawler\",\n \"patterns\": [\n \"OrangeBot\\\\/\"\n ],\n \"forbidden\": []\n },\n {\n \"id\": \"orange-ftgroup-crawler\",\n \"category\": \"UNKNOWN\",\n \"name\": \"orange-ftgroup-crawler\",\n \"patterns\": [\n \"voilabot\"\n ],\n \"forbidden\": []\n },\n {\n \"id\": \"outclicks-crawler\",\n \"category\": \"UNKNOWN\",\n \"name\": \"outclicks-crawler\",\n \"patterns\": [\n \"OutclicksBot\"\n ],\n \"forbidden\": []\n },\n {\n \"id\": \"page-to-rss\",\n \"category\": \"UNKNOWN\",\n \"name\": \"page-to-rss\",\n \"patterns\": [\n \"page2rss\"\n ],\n \"forbidden\": []\n },\n {\n \"id\": \"pagething-crawler\",\n \"category\": \"UNKNOWN\",\n \"name\": \"pagething-crawler\",\n \"patterns\": [\n \"PageThing\"\n ],\n \"forbidden\": []\n },\n {\n \"id\": \"paloaltonetworks-crawler\",\n \"category\": \"UNKNOWN\",\n \"name\": \"paloaltonetworks-crawler\",\n \"patterns\": [\n \"Expanse\"\n ],\n \"forbidden\": []\n },\n {\n \"id\": \"panscient-crawler\",\n \"category\": \"UNKNOWN\",\n \"name\": \"panscient-crawler\",\n \"patterns\": [\n \"panscient\"\n ],\n \"forbidden\": []\n },\n {\n \"id\": \"paperli-crawler\",\n \"category\": \"UNKNOWN\",\n \"name\": \"paperli-crawler\",\n \"patterns\": [\n \"PaperLiBot\"\n ],\n \"forbidden\": []\n },\n {\n \"id\": \"phxbot\",\n \"category\": \"UNKNOWN\",\n \"name\": \"phxbot\",\n \"patterns\": [\n \"PhxBot\"\n ],\n \"forbidden\": []\n },\n {\n \"id\": \"picsearch-crawler\",\n \"category\": \"UNKNOWN\",\n \"name\": \"picsearch-crawler\",\n \"patterns\": [\n \"psbot\"\n ],\n \"forbidden\": []\n },\n {\n \"id\": \"postrank-crawler\",\n \"category\": \"UNKNOWN\",\n \"name\": \"postrank-crawler\",\n \"patterns\": [\n \"postrank\"\n ],\n \"forbidden\": []\n },\n {\n \"id\": \"prcy-crawler\",\n \"category\": \"UNKNOWN\",\n \"name\": \"prcy-crawler\",\n \"patterns\": [\n \"PR-CY\\\\.RU\"\n ],\n \"forbidden\": []\n },\n {\n \"id\": \"privacore-crawler\",\n \"category\": \"UNKNOWN\",\n \"name\": \"privacore-crawler\",\n \"patterns\": [\n \"findxbot\"\n ],\n \"forbidden\": []\n },\n {\n \"id\": \"privacyaware-crawler\",\n \"category\": \"UNKNOWN\",\n \"name\": \"privacyaware-crawler\",\n \"patterns\": [\n \"PrivacyAwareBot\"\n ],\n \"forbidden\": []\n },\n {\n \"id\": \"profound-crawler\",\n \"category\": \"UNKNOWN\",\n \"name\": \"profound-crawler\",\n \"patterns\": [\n \"urlappendbot\"\n ],\n \"forbidden\": []\n },\n {\n \"id\": \"proximic-crawler\",\n \"category\": \"UNKNOWN\",\n \"name\": \"proximic-crawler\",\n \"patterns\": [\n \"proximic\"\n ],\n \"forbidden\": []\n },\n {\n \"id\": \"pulsepoint-crawler\",\n \"category\": \"UNKNOWN\",\n \"name\": \"pulsepoint-crawler\",\n \"patterns\": [\n \"Pulsepoint\"\n ],\n \"forbidden\": []\n },\n {\n \"id\": \"pure-crawler\",\n \"category\": \"UNKNOWN\",\n \"name\": \"pure-crawler\",\n \"patterns\": [\n \"purebot\"\n ],\n \"forbidden\": []\n },\n {\n \"id\": \"rankactive-crawler\",\n \"category\": \"UNKNOWN\",\n \"name\": \"rankactive-crawler\",\n \"patterns\": [\n \"RankActiveLinkBot\"\n ],\n \"forbidden\": []\n },\n {\n \"id\": \"retrevo-page-analyzer\",\n \"category\": \"UNKNOWN\",\n \"name\": \"retrevo-page-analyzer\",\n \"patterns\": [\n \"RetrevoPageAnalyzer\"\n ],\n \"forbidden\": []\n },\n {\n \"id\": \"ridder-crawler\",\n \"category\": \"UNKNOWN\",\n \"name\": \"ridder-crawler\",\n \"patterns\": [\n \"RidderBot\"\n ],\n \"forbidden\": []\n },\n {\n \"id\": \"rivva-crawler\",\n \"category\": \"UNKNOWN\",\n \"name\": \"rivva-crawler\",\n \"patterns\": [\n \"Rivva\"\n ],\n \"forbidden\": []\n },\n {\n \"id\": \"ryte-crawler\",\n \"category\": \"UNKNOWN\",\n \"name\": \"ryte-crawler\",\n \"patterns\": [\n \"RyteBot\"\n ],\n \"forbidden\": []\n },\n {\n \"id\": \"scan-interfax-crawler\",\n \"category\": \"UNKNOWN\",\n \"name\": \"scan-interfax-crawler\",\n \"patterns\": [\n \"InterfaxScanBot\"\n ],\n \"forbidden\": []\n },\n {\n \"id\": \"schmorp-crawler\",\n \"category\": \"UNKNOWN\",\n \"name\": \"schmorp-crawler\",\n \"patterns\": [\n \"AnyEvent\"\n ],\n \"forbidden\": []\n },\n {\n \"id\": \"scoutjet-crawler\",\n \"category\": \"UNKNOWN\",\n \"name\": \"scoutjet-crawler\",\n \"patterns\": [\n \"ScoutJet\"\n ],\n \"forbidden\": []\n },\n {\n \"id\": \"scribd-crawler\",\n \"category\": \"UNKNOWN\",\n \"name\": \"scribd-crawler\",\n \"patterns\": [\n \"scribdbot\"\n ],\n \"forbidden\": []\n },\n {\n \"id\": \"scritch-crawler\",\n \"category\": \"UNKNOWN\",\n \"name\": \"scritch-crawler\",\n \"patterns\": [\n \"Fetch\\\\/\"\n ],\n \"forbidden\": []\n },\n {\n \"id\": \"seekbot-crawler\",\n \"category\": \"UNKNOWN\",\n \"name\": \"seekbot-crawler\",\n \"patterns\": [\n \"seekbot\"\n ],\n \"forbidden\": []\n },\n {\n \"id\": \"seewithkids-crawler\",\n \"category\": \"UNKNOWN\",\n \"name\": \"seewithkids-crawler\",\n \"patterns\": [\n \"seewithkids\"\n ],\n \"forbidden\": []\n },\n {\n \"id\": \"semanticaudience-crawler\",\n \"category\": \"UNKNOWN\",\n \"name\": \"semanticaudience-crawler\",\n \"patterns\": [\n \"semanticbot\"\n ],\n \"forbidden\": []\n },\n {\n \"id\": \"sempitech-crawler\",\n \"category\": \"UNKNOWN\",\n \"name\": \"sempitech-crawler\",\n \"patterns\": [\n \"sempi\\\\.tech\"\n ],\n \"forbidden\": []\n },\n {\n \"id\": \"semrush-crawler\",\n \"category\": \"UNKNOWN\",\n \"name\": \"SemRushBot\",\n \"patterns\": [\n \"S[eE][mM]rushBot\"\n ],\n \"forbidden\": []\n },\n {\n \"id\": \"senuto-crawler\",\n \"category\": \"UNKNOWN\",\n \"name\": \"senuto-crawler\",\n \"patterns\": [\n \"SenutoBot\"\n ],\n \"forbidden\": []\n },\n {\n \"id\": \"seobility-crawler\",\n \"category\": \"UNKNOWN\",\n \"name\": \"seobility-crawler\",\n \"patterns\": [\n \"SeobilityBot\"\n ],\n \"forbidden\": []\n },\n {\n \"id\": \"seokicks-crawler\",\n \"category\": \"UNKNOWN\",\n \"name\": \"seokicks-crawler\",\n \"patterns\": [\n \"SEOkicks\"\n ],\n \"forbidden\": []\n },\n {\n \"id\": \"seolizer-crawler\",\n \"category\": \"UNKNOWN\",\n \"name\": \"seolizer-crawler\",\n \"patterns\": [\n \"SEOlizer\"\n ],\n \"forbidden\": []\n },\n {\n \"id\": \"seoprofiler-crawler\",\n \"category\": \"UNKNOWN\",\n \"name\": \"seoprofiler-crawler\",\n \"patterns\": [\n \"spbot\"\n ],\n \"forbidden\": []\n },\n {\n \"id\": \"seoscanners-crawler\",\n \"category\": \"UNKNOWN\",\n \"name\": \"seoscanners-crawler\",\n \"patterns\": [\n \"seoscanners\"\n ],\n \"forbidden\": []\n },\n {\n \"id\": \"seostar-crawler\",\n \"category\": \"UNKNOWN\",\n \"name\": \"seostar-crawler\",\n \"patterns\": [\n \"seostar\\\\.co\"\n ],\n \"forbidden\": []\n },\n {\n \"id\": \"seozoom-crawler\",\n \"category\": \"UNKNOWN\",\n \"name\": \"ZoomBot\",\n \"patterns\": [\n \"ZoomBot\"\n ],\n \"forbidden\": []\n },\n {\n \"id\": \"serpstatbot-crawler\",\n \"category\": \"UNKNOWN\",\n \"name\": \"serpstatbot-crawler\",\n \"patterns\": [\n \"serpstatbot\\\\/\"\n ],\n \"forbidden\": []\n },\n {\n \"id\": \"seznam-crawler\",\n \"category\": \"UNKNOWN\",\n \"name\": \"seznam-crawler\",\n \"patterns\": [\n \"SeznamBot\"\n ],\n \"forbidden\": []\n },\n {\n \"id\": \"similartech-crawler\",\n \"category\": \"UNKNOWN\",\n \"name\": \"similartech-crawler\",\n \"patterns\": [\n \"smtbot\"\n ],\n \"forbidden\": []\n },\n {\n \"id\": \"simple-crawler\",\n \"category\": \"UNKNOWN\",\n \"name\": \"simple-crawler\",\n \"patterns\": [\n \"SimpleCrawler\"\n ],\n \"forbidden\": []\n },\n {\n \"id\": \"sistrix-007ac9-crawler\",\n \"category\": \"UNKNOWN\",\n \"name\": \"sistrix-007ac9-crawler\",\n \"patterns\": [\n \"007ac9 Crawler\"\n ],\n \"forbidden\": []\n },\n {\n \"id\": \"sitebot-crawler\",\n \"category\": \"UNKNOWN\",\n \"name\": \"sitebot-crawler\",\n \"patterns\": [\n \"sitebot\"\n ],\n \"forbidden\": []\n },\n {\n \"id\": \"sitechecker-crawler\",\n \"category\": \"UNKNOWN\",\n \"name\": \"sitechecker-crawler\",\n \"patterns\": [\n \"SiteCheckerBotCrawler\"\n ],\n \"forbidden\": []\n },\n {\n \"id\": \"siteexplorer-crawler\",\n \"category\": \"UNKNOWN\",\n \"name\": \"siteexplorer-crawler\",\n \"patterns\": [\n \"siteexplorer\\\\.info\"\n ],\n \"forbidden\": []\n },\n {\n \"id\": \"siteimprove-crawler\",\n \"category\": \"UNKNOWN\",\n \"name\": \"siteimprove-crawler\",\n \"patterns\": [\n \"Siteimprove\\\\.com\"\n ],\n \"forbidden\": []\n },\n {\n \"id\": \"socialrank-crawler\",\n \"category\": \"UNKNOWN\",\n \"name\": \"socialrank-crawler\",\n \"patterns\": [\n \"SocialRankIOBot\"\n ],\n \"forbidden\": []\n },\n {\n \"id\": \"softbytelabs-crawler\",\n \"category\": \"UNKNOWN\",\n \"name\": \"softbytelabs-crawler\",\n \"patterns\": [\n \"SBL-BOT\"\n ],\n \"forbidden\": []\n },\n {\n \"id\": \"sogou-crawler\",\n \"category\": \"UNKNOWN\",\n \"name\": \"sogou-crawler\",\n \"patterns\": [\n \"Sogou\"\n ],\n \"forbidden\": []\n },\n {\n \"id\": \"stuttgart-crawler\",\n \"category\": \"UNKNOWN\",\n \"name\": \"stuttgart-crawler\",\n \"patterns\": [\n \"RegionStuttgartBot\"\n ],\n \"forbidden\": []\n },\n {\n \"id\": \"summify-crawler\",\n \"category\": \"UNKNOWN\",\n \"name\": \"summify-crawler\",\n \"patterns\": [\n \"summify\"\n ],\n \"forbidden\": []\n },\n {\n \"id\": \"swimgbot\",\n \"category\": \"UNKNOWN\",\n \"name\": \"swimgbot\",\n \"patterns\": [\n \"SWIMGBot\"\n ],\n \"forbidden\": []\n },\n {\n \"id\": \"sysomos-crawler\",\n \"category\": \"UNKNOWN\",\n \"name\": \"sysomos-crawler\",\n \"patterns\": [\n \"Sysomos\"\n ],\n \"forbidden\": []\n },\n {\n \"id\": \"t3versions-crawler\",\n \"category\": \"UNKNOWN\",\n \"name\": \"t3versions-crawler\",\n \"patterns\": [\n \"t3versionsBot\"\n ],\n \"forbidden\": []\n },\n {\n \"id\": \"taboola-crawler\",\n \"category\": \"UNKNOWN\",\n \"name\": \"taboola-crawler\",\n \"patterns\": [\n \"Taboolabot\"\n ],\n \"forbidden\": []\n },\n {\n \"id\": \"tagoo-crawler\",\n \"category\": \"UNKNOWN\",\n \"name\": \"tagoo-crawler\",\n \"patterns\": [\n \"tagoobot\"\n ],\n \"forbidden\": []\n },\n {\n \"id\": \"tangiblee-crawler\",\n \"category\": \"UNKNOWN\",\n \"name\": \"tangiblee-crawler\",\n \"patterns\": [\n \"TangibleeBot\"\n ],\n \"forbidden\": []\n },\n {\n \"id\": \"thinklab-crawler\",\n \"category\": \"UNKNOWN\",\n \"name\": \"thinklab-crawler\",\n \"patterns\": [\n \"Thinklab\"\n ],\n \"forbidden\": []\n },\n {\n \"id\": \"tiger-crawler\",\n \"category\": \"UNKNOWN\",\n \"name\": \"tiger-crawler\",\n \"patterns\": [\n \"tigerbot\"\n ],\n \"forbidden\": []\n },\n {\n \"id\": \"tineye-crawler\",\n \"category\": \"UNKNOWN\",\n \"name\": \"tineye-crawler\",\n \"patterns\": [\n \"TinEye\"\n ],\n \"forbidden\": []\n },\n {\n \"id\": \"tiscali-crawler\",\n \"category\": \"UNKNOWN\",\n \"name\": \"tiscali-crawler\",\n \"patterns\": [\n \"IstellaBot\"\n ],\n \"forbidden\": []\n },\n {\n \"id\": \"tombascraper-crawler\",\n \"category\": \"UNKNOWN\",\n \"name\": \"tombascraper-crawler\",\n \"patterns\": [\n \"TombaPublicWebCrawler\"\n ],\n \"forbidden\": []\n },\n {\n \"id\": \"toplist-crawler\",\n \"category\": \"UNKNOWN\",\n \"name\": \"toplist-crawler\",\n \"patterns\": [\n \"toplistbot\"\n ],\n \"forbidden\": []\n },\n {\n \"id\": \"torus-crawler\",\n \"category\": \"UNKNOWN\",\n \"name\": \"torus-crawler\",\n \"patterns\": [\n \"ReverseEngineeringBot\"\n ],\n \"forbidden\": []\n },\n {\n \"id\": \"toutiao-crawler\",\n \"category\": \"UNKNOWN\",\n \"name\": \"toutiao-crawler\",\n \"patterns\": [\n \"ToutiaoSpider\"\n ],\n \"forbidden\": []\n },\n {\n \"id\": \"traackr-crawler\",\n \"category\": \"UNKNOWN\",\n \"name\": \"traackr-crawler\",\n \"patterns\": [\n \"Traackr\\\\.com\"\n ],\n \"forbidden\": []\n },\n {\n \"id\": \"tracemyfile-crawler\",\n \"category\": \"UNKNOWN\",\n \"name\": \"tracemyfile-crawler\",\n \"patterns\": [\n \"tracemyfile\"\n ],\n \"forbidden\": []\n },\n {\n \"id\": \"trendiction-crawler\",\n \"category\": \"UNKNOWN\",\n \"name\": \"trendiction-crawler\",\n \"patterns\": [\n \"trendictionbot\"\n ],\n \"forbidden\": []\n },\n {\n \"id\": \"trove-crawler\",\n \"category\": \"UNKNOWN\",\n \"name\": \"trove-crawler\",\n \"patterns\": [\n \"Trove\"\n ],\n \"forbidden\": []\n },\n {\n \"id\": \"trovit-crawler\",\n \"category\": \"UNKNOWN\",\n \"name\": \"trovit-crawler\",\n \"patterns\": [\n \"trovitBot\"\n ],\n \"forbidden\": []\n },\n {\n \"id\": \"tweetmemebot\",\n \"category\": \"UNKNOWN\",\n \"name\": \"tweetmemebot\",\n \"patterns\": [\n \"TweetmemeBot\"\n ],\n \"forbidden\": []\n },\n {\n \"id\": \"twenga-crawler\",\n \"category\": \"UNKNOWN\",\n \"name\": \"twenga-crawler\",\n \"patterns\": [\n \"twengabot\"\n ],\n \"forbidden\": []\n },\n {\n \"id\": \"twingly-crawler\",\n \"category\": \"UNKNOWN\",\n \"name\": \"twingly-crawler\",\n \"patterns\": [\n \"Twingly\"\n ],\n \"forbidden\": []\n },\n {\n \"id\": \"twoip-crawler\",\n \"category\": \"UNKNOWN\",\n \"name\": \"twoip-crawler\",\n \"patterns\": [\n \"2ip bot\"\n ],\n \"forbidden\": []\n },\n {\n \"id\": \"twoip-crawler-cms\",\n \"category\": \"UNKNOWN\",\n \"name\": \"twoip-crawler-cms\",\n \"patterns\": [\n \"2ip\\\\.ru\"\n ],\n \"forbidden\": []\n },\n {\n \"id\": \"twurly-crawler\",\n \"category\": \"UNKNOWN\",\n \"name\": \"twurly-crawler\",\n \"patterns\": [\n \"Twurly\"\n ],\n \"forbidden\": []\n },\n {\n \"id\": \"ubermetrics-crawler\",\n \"category\": \"UNKNOWN\",\n \"name\": \"ubermetrics-crawler\",\n \"patterns\": [\n \"um-LN\"\n ],\n \"forbidden\": []\n },\n {\n \"id\": \"ubt-crawler\",\n \"category\": \"UNKNOWN\",\n \"name\": \"ubt-crawler\",\n \"patterns\": [\n \"Streamline3Bot\\\\/\"\n ],\n \"forbidden\": []\n },\n {\n \"id\": \"upflow-crawler\",\n \"category\": \"UNKNOWN\",\n \"name\": \"upflow-crawler\",\n \"patterns\": [\n \"Upflow\"\n ],\n \"forbidden\": []\n },\n {\n \"id\": \"urlclassification-crawler\",\n \"category\": \"UNKNOWN\",\n \"name\": \"urlclassification-crawler\",\n \"patterns\": [\n \"KStandBot\"\n ],\n \"forbidden\": []\n },\n {\n \"id\": \"usine-nouvelle-crawler\",\n \"category\": \"UNKNOWN\",\n \"name\": \"usine-nouvelle-crawler\",\n \"patterns\": [\n \"UsineNouvelleCrawler\"\n ],\n \"forbidden\": []\n },\n {\n \"id\": \"utorrent-crawler\",\n \"category\": \"UNKNOWN\",\n \"name\": \"utorrent-crawler\",\n \"patterns\": [\n \"BTWebClient\"\n ],\n \"forbidden\": []\n },\n {\n \"id\": \"vebidoo-crawler\",\n \"category\": \"UNKNOWN\",\n \"name\": \"vebidoo-crawler\",\n \"patterns\": [\n \"vebidoobot\"\n ],\n \"forbidden\": []\n },\n {\n \"id\": \"veooz-crawler\",\n \"category\": \"UNKNOWN\",\n \"name\": \"veooz-crawler\",\n \"patterns\": [\n \"Veoozbot\"\n ],\n \"forbidden\": []\n },\n {\n \"id\": \"verisign-ips-agent\",\n \"category\": \"UNKNOWN\",\n \"name\": \"verisign-ips-agent\",\n \"patterns\": [\n \"ips-agent\"\n ],\n \"forbidden\": []\n },\n {\n \"id\": \"vigil-crawler\",\n \"category\": \"UNKNOWN\",\n \"name\": \"vigil-crawler\",\n \"patterns\": [\n \"Vigil\\\\/\"\n ],\n \"forbidden\": []\n },\n {\n \"id\": \"vipnytt-crawler\",\n \"category\": \"UNKNOWN\",\n \"name\": \"vipnytt-crawler\",\n \"patterns\": [\n \"jpg-newsbot\"\n ],\n \"forbidden\": []\n },\n {\n \"id\": \"virustotal-crawler\",\n \"category\": \"UNKNOWN\",\n \"name\": \"virustotal-crawler\",\n \"patterns\": [\n \"virustotal\"\n ],\n \"forbidden\": []\n },\n {\n \"id\": \"vkrobot-crawler\",\n \"category\": \"UNKNOWN\",\n \"name\": \"vkrobot-crawler\",\n \"patterns\": [\n \"VKRobot\"\n ],\n \"forbidden\": []\n },\n {\n \"id\": \"vkshare-crawler\",\n \"category\": \"UNKNOWN\",\n \"name\": \"vkshare-crawler\",\n \"patterns\": [\n \"vkShare\"\n ],\n \"forbidden\": []\n },\n {\n \"id\": \"vuhuv-crawler\",\n \"category\": \"UNKNOWN\",\n \"name\": \"vuhuv-crawler\",\n \"patterns\": [\n \"vuhuvBot\"\n ],\n \"forbidden\": []\n },\n {\n \"id\": \"warebay-crawler\",\n \"category\": \"UNKNOWN\",\n \"name\": \"warebay-crawler\",\n \"patterns\": [\n \"wbsearchbot\"\n ],\n \"forbidden\": []\n },\n {\n \"id\": \"webceo-crawler\",\n \"category\": \"UNKNOWN\",\n \"name\": \"webceo-crawler\",\n \"patterns\": [\n \"online-webceo-bot\"\n ],\n \"forbidden\": []\n },\n {\n \"id\": \"webcompany-crawler\",\n \"category\": \"UNKNOWN\",\n \"name\": \"webcompany-crawler\",\n \"patterns\": [\n \"webcompanycrawler\"\n ],\n \"forbidden\": []\n },\n {\n \"id\": \"webdatastats-crawler\",\n \"category\": \"UNKNOWN\",\n \"name\": \"webdatastats-crawler\",\n \"patterns\": [\n \"WebDataStats\"\n ],\n \"forbidden\": []\n },\n {\n \"id\": \"webeaver-crawler\",\n \"category\": \"UNKNOWN\",\n \"name\": \"webeaver-crawler\",\n \"patterns\": [\n \"BehloolBot\"\n ],\n \"forbidden\": []\n },\n {\n \"id\": \"webmeup-crawler\",\n \"category\": \"UNKNOWN\",\n \"name\": \"webmeup-crawler\",\n \"patterns\": [\n \"BLEXBot\\\\/\"\n ],\n \"forbidden\": []\n },\n {\n \"id\": \"webmon\",\n \"category\": \"UNKNOWN\",\n \"name\": \"webmon\",\n \"patterns\": [\n \"webmon \"\n ],\n \"forbidden\": []\n },\n {\n \"id\": \"wesee-crawler\",\n \"category\": \"UNKNOWN\",\n \"name\": \"wesee-crawler\",\n \"patterns\": [\n \"WeSEE:Search\"\n ],\n \"forbidden\": []\n },\n {\n \"id\": \"wocodi-crawler\",\n \"category\": \"UNKNOWN\",\n \"name\": \"wocodi-crawler\",\n \"patterns\": [\n \"wocbot\"\n ],\n \"forbidden\": []\n },\n {\n \"id\": \"woorank-crawler\",\n \"category\": \"UNKNOWN\",\n \"name\": \"woorank-crawler\",\n \"patterns\": [\n \"woobot\"\n ],\n \"forbidden\": []\n },\n {\n \"id\": \"woorank-crawler-review\",\n \"category\": \"UNKNOWN\",\n \"name\": \"woorank-crawler-review\",\n \"patterns\": [\n \"woorankreview\\\\/\"\n ],\n \"forbidden\": []\n },\n {\n \"id\": \"wordpress-crawler\",\n \"category\": \"UNKNOWN\",\n \"name\": \"WordPressBot\",\n \"patterns\": [\n \"WordPress\\\\/\"\n ],\n \"forbidden\": []\n },\n {\n \"id\": \"wordup-crawler\",\n \"category\": \"UNKNOWN\",\n \"name\": \"wordup-crawler\",\n \"patterns\": [\n \"WordupInfoSearch\"\n ],\n \"forbidden\": []\n },\n {\n \"id\": \"worio-crawler\",\n \"category\": \"UNKNOWN\",\n \"name\": \"worio-crawler\",\n \"patterns\": [\n \"woriobot\"\n ],\n \"forbidden\": []\n },\n {\n \"id\": \"wotbox-crawler\",\n \"category\": \"UNKNOWN\",\n \"name\": \"wotbox-crawler\",\n \"patterns\": [\n \"wotbox\"\n ],\n \"forbidden\": []\n },\n {\n \"id\": \"xovibot-crawler\",\n \"category\": \"UNKNOWN\",\n \"name\": \"xovibot-crawler\",\n \"patterns\": [\n \"xovibot\"\n ],\n \"forbidden\": []\n },\n {\n \"id\": \"yanga-crawler\",\n \"category\": \"UNKNOWN\",\n \"name\": \"yanga-crawler\",\n \"patterns\": [\n \"yanga\"\n ],\n \"forbidden\": []\n },\n {\n \"id\": \"yellowbp-crawler\",\n \"category\": \"UNKNOWN\",\n \"name\": \"yellowbp-crawler\",\n \"patterns\": [\n \"Yellowbrandprotectionbot\"\n ],\n \"forbidden\": []\n },\n {\n \"id\": \"yisou-crawler\",\n \"category\": \"UNKNOWN\",\n \"name\": \"yisou-crawler\",\n \"patterns\": [\n \"YisouSpider\"\n ],\n \"forbidden\": []\n },\n {\n \"id\": \"yooz-crawler\",\n \"category\": \"UNKNOWN\",\n \"name\": \"yooz-crawler\",\n \"patterns\": [\n \"yoozBot\"\n ],\n \"forbidden\": []\n },\n {\n \"id\": \"zoominfo-crawler\",\n \"category\": \"UNKNOWN\",\n \"name\": \"zoominfo-crawler\",\n \"patterns\": [\n \"ZoominfoBot\"\n ],\n \"forbidden\": []\n },\n {\n \"id\": \"zum-crawler\",\n \"category\": \"UNKNOWN\",\n \"name\": \"ZumBot\",\n \"patterns\": [\n \"ZumBot\"\n ],\n \"forbidden\": []\n },\n {\n \"id\": \"zuperlist-crawler\",\n \"category\": \"UNKNOWN\",\n \"name\": \"zuperlist-crawler\",\n \"patterns\": [\n \"ZuperlistBot\\\\/\"\n ],\n \"forbidden\": []\n },\n {\n \"id\": \"ext-ahrefsbotsiteaudit\",\n \"name\": \"ahrefsbotsiteaudit\",\n \"category\": \"SEO\",\n \"patterns\": [\n \"Ahrefs(Bot|SiteAudit)\"\n ],\n \"forbidden\": []\n },\n {\n \"id\": \"ext-amazonproductdiscovery\",\n \"name\": \"amazonproductdiscovery\",\n \"category\": \"SEARCH_ENGINE\",\n \"patterns\": [\n \"AmazonProductDiscovery\"\n ],\n \"forbidden\": []\n },\n {\n \"id\": \"ext-amazonsellerinitiatedlisting\",\n \"name\": \"amazonsellerinitiatedlisting\",\n \"category\": \"SEARCH_ENGINE\",\n \"patterns\": [\n \"AmazonSellerInitiatedListing\"\n ],\n \"forbidden\": []\n },\n {\n \"id\": \"ext-cclaudebbot\",\n \"name\": \"cclaudebbot\",\n \"category\": \"GENERIC\",\n \"patterns\": [\n \"[cC]laude[bB]ot\"\n ],\n \"forbidden\": []\n },\n {\n \"id\": \"ext-meta-externalagent\",\n \"name\": \"meta-externalagent\",\n \"category\": \"GENERIC\",\n \"patterns\": [\n \"meta-externalagent\\\\/\"\n ],\n \"forbidden\": []\n },\n {\n \"id\": \"ext-meta-externalfetcher\",\n \"name\": \"meta-externalfetcher\",\n \"category\": \"GENERIC\",\n \"patterns\": [\n \"meta-externalfetcher\\\\/\"\n ],\n \"forbidden\": []\n },\n {\n \"id\": \"ext-hydrozenio\",\n \"name\": \"hydrozenio\",\n \"category\": \"MONITORING\",\n \"patterns\": [\n \"Hydrozen\\\\.io\"\n ],\n \"forbidden\": []\n },\n {\n \"id\": \"ext-yextbot\",\n \"name\": \"yextbot\",\n \"category\": \"SEO\",\n \"patterns\": [\n \"YextBot\\\\/\"\n ],\n \"forbidden\": []\n },\n {\n \"id\": \"ext-datadogsynthetics\",\n \"name\": \"datadogsynthetics\",\n \"category\": \"MONITORING\",\n \"patterns\": [\n \"DatadogSynthetics\"\n ],\n \"forbidden\": []\n },\n {\n \"id\": \"ext-observepoint\",\n \"name\": \"observepoint\",\n \"category\": \"MONITORING\",\n \"patterns\": [\n \"ObservePoint\"\n ],\n \"forbidden\": []\n },\n {\n \"id\": \"ext-checkly\",\n \"name\": \"checkly\",\n \"category\": \"MONITORING\",\n \"patterns\": [\n \"Checkly\"\n ],\n \"forbidden\": []\n },\n {\n \"id\": \"ext-alittleclient\",\n \"name\": \"alittleclient\",\n \"category\": \"GENERIC\",\n \"patterns\": [\n \"ALittle Client\"\n ],\n \"forbidden\": []\n },\n {\n \"id\": \"ext-aliyunsecbot\",\n \"name\": \"aliyunsecbot\",\n \"category\": \"GENERIC\",\n \"patterns\": [\n \"AliyunSecBot\"\n ],\n \"forbidden\": []\n },\n {\n \"id\": \"ext-claude-web\",\n \"name\": \"claude-web\",\n \"category\": \"GENERIC\",\n \"patterns\": [\n \"Claude-Web\"\n ],\n \"forbidden\": []\n },\n {\n \"id\": \"ext-google-extended\",\n \"name\": \"google-extended\",\n \"category\": \"GENERIC\",\n \"patterns\": [\n \"Google-Extended\"\n ],\n \"forbidden\": []\n },\n {\n \"id\": \"ext-serankingbacklinksbot\",\n \"name\": \"serankingbacklinksbot\",\n \"category\": \"SEO\",\n \"patterns\": [\n \"SERankingBacklinksBot\"\n ],\n \"forbidden\": []\n },\n {\n \"id\": \"ext-cmschecker\",\n \"name\": \"cmschecker\",\n \"category\": \"SEO\",\n \"patterns\": [\n \"CMSChecker\"\n ],\n \"forbidden\": []\n },\n {\n \"id\": \"ext-wayback\",\n \"name\": \"wayback\",\n \"category\": \"GENERIC\",\n \"patterns\": [\n \"Wayback\"\n ],\n \"forbidden\": []\n },\n {\n \"id\": \"ext-playwright\",\n \"name\": \"playwright\",\n \"category\": \"GENERIC\",\n \"patterns\": [\n \"Playwright\"\n ],\n \"forbidden\": []\n },\n {\n \"id\": \"ext-puppeteer\",\n \"name\": \"puppeteer\",\n \"category\": \"GENERIC\",\n \"patterns\": [\n \"Puppeteer\"\n ],\n \"forbidden\": []\n },\n {\n \"id\": \"ext-selenium\",\n \"name\": \"selenium\",\n \"category\": \"GENERIC\",\n \"patterns\": [\n \"Selenium\"\n ],\n \"forbidden\": []\n },\n {\n \"id\": \"ext-nikto\",\n \"name\": \"nikto\",\n \"category\": \"GENERIC\",\n \"patterns\": [\n \"Nikto\"\n ],\n \"forbidden\": []\n },\n {\n \"id\": \"ext-sqlmap\",\n \"name\": \"sqlmap\",\n \"category\": \"GENERIC\",\n \"patterns\": [\n \"sqlmap\"\n ],\n \"forbidden\": []\n },\n {\n \"id\": \"ext-zmeu\",\n \"name\": \"zmeu\",\n \"category\": \"GENERIC\",\n \"patterns\": [\n \"ZmEu\"\n ],\n \"forbidden\": []\n },\n {\n \"id\": \"ext-masscan\",\n \"name\": \"masscan\",\n \"category\": \"GENERIC\",\n \"patterns\": [\n \"masscan\"\n ],\n \"forbidden\": []\n },\n {\n \"id\": \"ext-wpscan\",\n \"name\": \"wpscan\",\n \"category\": \"GENERIC\",\n \"patterns\": [\n \"WPScan\"\n ],\n \"forbidden\": []\n },\n {\n \"id\": \"ext-aacunetix\",\n \"name\": \"aacunetix\",\n \"category\": \"GENERIC\",\n \"patterns\": [\n \"[aA]cunetix\"\n ],\n \"forbidden\": []\n },\n {\n \"id\": \"ext-nessus\",\n \"name\": \"nessus\",\n \"category\": \"GENERIC\",\n \"patterns\": [\n \"Nessus\"\n ],\n \"forbidden\": []\n },\n {\n \"id\": \"ext-ddirbbuster\",\n \"name\": \"ddirbbuster\",\n \"category\": \"GENERIC\",\n \"patterns\": [\n \"[dD]ir[Bb]uster\"\n ],\n \"forbidden\": []\n },\n {\n \"id\": \"ext-colly\",\n \"name\": \"colly\",\n \"category\": \"GENERIC\",\n \"patterns\": [\n \"colly\"\n ],\n \"forbidden\": []\n },\n {\n \"id\": \"ext-mmechanize\",\n \"name\": \"mmechanize\",\n \"category\": \"GENERIC\",\n \"patterns\": [\n \"[mM]echanize\"\n ],\n \"forbidden\": []\n },\n {\n \"id\": \"ext-airaiscanning\",\n \"name\": \"airaiscanning\",\n \"category\": \"GENERIC\",\n \"patterns\": [\n \"air\\\\.ai\\\\/scanning\"\n ],\n \"forbidden\": []\n },\n {\n \"id\": \"ext-asnriskscorer\",\n \"name\": \"asnriskscorer\",\n \"category\": \"GENERIC\",\n \"patterns\": [\n \"asnriskscorer\"\n ],\n \"forbidden\": []\n },\n {\n \"id\": \"ext-oicrawler\",\n \"name\": \"oicrawler\",\n \"category\": \"SEARCH_ENGINE\",\n \"patterns\": [\n \"OICrawler\"\n ],\n \"forbidden\": []\n },\n {\n \"id\": \"ext-l9scan\",\n \"name\": \"l9scan\",\n \"category\": \"GENERIC\",\n \"patterns\": [\n \"l9scan\"\n ],\n \"forbidden\": []\n },\n {\n \"id\": \"ext-slaccalebot\",\n \"name\": \"slaccalebot\",\n \"category\": \"SEO\",\n \"patterns\": [\n \"SlaccaleBot\"\n ],\n \"forbidden\": []\n },\n {\n \"id\": \"ext-customasynchttpclient\",\n \"name\": \"customasynchttpclient\",\n \"category\": \"GENERIC\",\n \"patterns\": [\n \"CustomAsyncHttpClient\"\n ],\n \"forbidden\": []\n },\n {\n \"id\": \"ext-gemini-deep-research\",\n \"name\": \"gemini-deep-research\",\n \"category\": \"SEARCH_ENGINE\",\n \"patterns\": [\n \"Gemini-Deep-Research\"\n ],\n \"forbidden\": []\n },\n {\n \"id\": \"ext-perplexity-user\",\n \"name\": \"perplexity-user\",\n \"category\": \"SEARCH_ENGINE\",\n \"patterns\": [\n \"Perplexity-User\"\n ],\n \"forbidden\": []\n },\n {\n \"id\": \"ext-perplexityuser\",\n \"name\": \"perplexityuser\",\n \"category\": \"SEARCH_ENGINE\",\n \"patterns\": [\n \"PerplexityUser\"\n ],\n \"forbidden\": []\n },\n {\n \"id\": \"ext-meta-webindexer\",\n \"name\": \"meta-webindexer\",\n \"category\": \"GENERIC\",\n \"patterns\": [\n \"meta-webindexer\"\n ],\n \"forbidden\": []\n },\n {\n \"id\": \"ext-duckassistbot\",\n \"name\": \"duckassistbot\",\n \"category\": \"SEARCH_ENGINE\",\n \"patterns\": [\n \"DuckAssistBot\"\n ],\n \"forbidden\": []\n },\n {\n \"id\": \"ext-mistralai-user\",\n \"name\": \"mistralai-user\",\n \"category\": \"GENERIC\",\n \"patterns\": [\n \"MistralAI-User\"\n ],\n \"forbidden\": []\n },\n {\n \"id\": \"ext-webzio\",\n \"name\": \"webzio\",\n \"category\": \"SEO\",\n \"patterns\": [\n \"webzio\"\n ],\n \"forbidden\": []\n },\n {\n \"id\": \"ext-newsai\",\n \"name\": \"newsai\",\n \"category\": \"GENERIC\",\n \"patterns\": [\n \"newsai\\\\/\"\n ],\n \"forbidden\": []\n }\n]","/**\n * @module @arcis/node/middleware/bot-detection\n * Local-only bot detection using User-Agent and behavioral signals.\n *\n * Categorizes requests into bot types and allows/denies based on config.\n * No cloud calls — everything runs locally.\n *\n * @example\n * // Block automated tools, allow search engines\n * app.use(botProtection({\n * allow: ['SEARCH_ENGINE', 'SOCIAL', 'MONITORING'],\n * deny: ['AUTOMATED', 'SCRAPER'],\n * }));\n */\n\nimport type { Request, Response, NextFunction, RequestHandler } from 'express';\nimport BOT_PATTERN_DATA from '../data/bot-patterns.json';\n\n// =============================================================================\n// BOT CATEGORIES\n// =============================================================================\n\nexport type BotCategory =\n | 'SEARCH_ENGINE'\n | 'SOCIAL'\n | 'MONITORING'\n | 'AI_CRAWLER'\n | 'SCRAPER'\n | 'AUTOMATED'\n | 'UNKNOWN'\n | 'HUMAN';\n\nexport interface BotDetectionResult {\n /** Whether the request appears to be from a bot */\n isBot: boolean;\n /** Bot category */\n category: BotCategory;\n /** Matched bot name (e.g. 'Googlebot', 'curl') or null */\n name: string | null;\n /** Confidence score: 0-1 */\n confidence: number;\n /** Behavioral signals detected */\n signals: string[];\n}\n\nexport interface BotProtectionOptions {\n /** Categories to explicitly allow. Default: ['SEARCH_ENGINE', 'SOCIAL', 'MONITORING'] */\n allow?: BotCategory[];\n /** Categories to explicitly deny. Default: ['AUTOMATED'] */\n deny?: BotCategory[];\n /** Action for categories not in allow or deny. Default: 'allow' */\n defaultAction?: 'allow' | 'deny';\n /** HTTP status code for denied bots. Default: 403 */\n statusCode?: number;\n /** Error message for denied bots */\n message?: string;\n /** Enable behavioral signal detection. Default: true */\n detectBehavior?: boolean;\n /** Custom handler called on detection (instead of default deny response) */\n onDetected?: (req: Request, res: Response, result: BotDetectionResult) => void;\n}\n\n// =============================================================================\n// BOT DATABASE\n// =============================================================================\n\ninterface BotPattern {\n /** Compiled regex(es) to match against the User-Agent. ANY match counts. */\n patterns: RegExp[];\n /** Compiled forbidden patterns. If ANY matches, this entry is rejected. */\n forbidden: RegExp[];\n /** Bot name (e.g. 'Googlebot') */\n name: string;\n /** Category */\n category: BotCategory;\n /** Stable identifier from the source corpus */\n id: string;\n}\n\n/**\n * Source data for the bot corpus — `packages/core/bot-patterns.json`, derived\n * from arcjet/well-known-bots (MIT) plus a supplementary list of browser\n * automation tools the upstream doesn't separately track. Regenerate via\n * `python packages/core/generate-bot-patterns.py` after upgrading the source.\n */\ninterface BotPatternData {\n id: string;\n name: string;\n category: string;\n patterns: string[];\n forbidden: string[];\n}\n\nfunction compilePattern(source: string): RegExp {\n // Patterns from the corpus are JS-style regex bodies (no enclosing /.../ ).\n // Compile case-insensitive: matches Arcis's documented contract that bot\n // detection ignores UA case (`GPTBOT` and `gptbot` match the same entry).\n // This is additive on top of Arcjet's explicit character classes like\n // `[wW]get` — the `i` flag doesn't conflict with character ranges.\n return new RegExp(source, 'i');\n}\n\nconst BOT_PATTERNS: BotPattern[] = (BOT_PATTERN_DATA as BotPatternData[]).map((entry) => ({\n id: entry.id,\n name: entry.name,\n category: entry.category as BotCategory,\n patterns: entry.patterns.map(compilePattern),\n forbidden: entry.forbidden.map(compilePattern),\n}));\n\n\n// =============================================================================\n// DETECTION ENGINE\n// =============================================================================\n\n/**\n * Detect behavioral signals that suggest a bot.\n */\nfunction detectBehavioralSignals(req: Request): string[] {\n const signals: string[] = [];\n const headers = req.headers;\n\n // Missing User-Agent\n if (!headers['user-agent']) {\n signals.push('missing_user_agent');\n }\n\n // Missing Accept header (browsers always send this)\n if (!headers['accept']) {\n signals.push('missing_accept');\n }\n\n // Missing Accept-Language (browsers always send this)\n if (!headers['accept-language']) {\n signals.push('missing_accept_language');\n }\n\n // Missing Accept-Encoding (browsers always send this)\n if (!headers['accept-encoding']) {\n signals.push('missing_accept_encoding');\n }\n\n // Connection: close (browsers typically use keep-alive)\n if (headers['connection'] === 'close') {\n signals.push('connection_close');\n }\n\n return signals;\n}\n\n/**\n * Detect what kind of bot (if any) is making the request.\n *\n * @param req - HTTP request object\n * @returns Detection result with category, name, confidence, and signals\n *\n * @example\n * const result = detectBot(req);\n * if (result.isBot && result.category === 'AUTOMATED') {\n * // Block automated tools\n * }\n */\nexport function detectBot(req: Request): BotDetectionResult {\n const rawUa = req.headers['user-agent'] ?? '';\n // SECURITY: A UA longer than 2048 chars is either buggy client or attempt to hide\n // a bot signature past a truncation boundary. Flag as suspicious bot directly —\n // don't silently truncate and continue.\n if (rawUa.length > 2048) {\n return {\n isBot: true,\n category: 'UNKNOWN',\n name: null,\n confidence: 0.9,\n signals: detectBehavioralSignals(req),\n };\n }\n const ua = rawUa;\n const signals = detectBehavioralSignals(req);\n\n // No User-Agent at all\n if (!ua) {\n return {\n isBot: true,\n category: 'UNKNOWN',\n name: null,\n confidence: 0.8,\n signals,\n };\n }\n\n // Match against known bot patterns. An entry matches when ALL of its\n // accepted patterns match AND none of its forbidden patterns matches.\n // ALL-of semantics makes multi-pattern entries (e.g. iMessage-Preview which\n // expects both `facebookexternalhit` and `Twitterbot` in the same UA) only\n // fire on real iMessage traffic, not on bare `Twitterbot/1.0` requests.\n // Single-pattern entries (the common case) reduce trivially to that one\n // pattern matching.\n for (const bot of BOT_PATTERNS) {\n let allMatched = bot.patterns.length > 0;\n for (const pattern of bot.patterns) {\n if (!pattern.test(ua)) {\n allMatched = false;\n break;\n }\n }\n if (!allMatched) continue;\n\n let forbidden = false;\n for (const pattern of bot.forbidden) {\n if (pattern.test(ua)) {\n forbidden = true;\n break;\n }\n }\n if (forbidden) continue;\n\n return {\n isBot: true,\n category: bot.category,\n name: bot.name,\n confidence: 0.95,\n signals,\n };\n }\n\n // Behavioral analysis for unrecognized UAs\n const behaviorScore = signals.length;\n\n // 3+ missing standard headers = likely bot\n if (behaviorScore >= 3) {\n return {\n isBot: true,\n category: 'UNKNOWN',\n name: null,\n confidence: Math.min(1.0, 0.6 + (behaviorScore * 0.1)),\n signals,\n };\n }\n\n return {\n isBot: false,\n category: 'HUMAN',\n name: null,\n confidence: Math.max(0.0, 1.0 - (behaviorScore * 0.15)),\n signals,\n };\n}\n\n/**\n * Create Express middleware for bot protection.\n *\n * @example\n * // Block automated tools and scrapers\n * app.use(botProtection({\n * allow: ['SEARCH_ENGINE', 'SOCIAL', 'MONITORING'],\n * deny: ['AUTOMATED', 'SCRAPER'],\n * }));\n *\n * @example\n * // Block everything except search engines\n * app.use(botProtection({\n * allow: ['SEARCH_ENGINE'],\n * defaultAction: 'deny',\n * }));\n *\n * @example\n * // Custom handler\n * app.use(botProtection({\n * deny: ['AUTOMATED'],\n * onDetected: (req, res, result) => {\n * console.log(`Bot blocked: ${result.name} (${result.category})`);\n * res.status(403).json({ error: 'Bots not allowed' });\n * },\n * }));\n */\nexport function botProtection(options: BotProtectionOptions = {}): RequestHandler {\n const {\n allow = ['SEARCH_ENGINE', 'SOCIAL', 'MONITORING'],\n deny = ['AUTOMATED'],\n defaultAction = 'allow',\n statusCode = 403,\n message = 'Access denied.',\n onDetected,\n } = options;\n\n const allowSet = new Set(allow);\n const denySet = new Set(deny);\n\n return (req: Request, res: Response, next: NextFunction) => {\n const result = detectBot(req);\n\n // Attach result to request for downstream use\n (req as unknown as Record<string, unknown>).botDetection = result;\n\n // Humans always pass\n if (!result.isBot) {\n return next();\n }\n\n // Check explicit allow/deny lists\n if (allowSet.has(result.category)) {\n return next();\n }\n\n if (denySet.has(result.category)) {\n // Telemetry attribution: dashboard groups bot denials under vector=bot.\n req.__arcis = {\n vector: 'bot',\n rule: `bot/${result.category.toLowerCase()}`,\n severity: 'medium',\n reason: result.name ? `Bot detected: ${result.name}` : 'Bot detected',\n decision: 'deny',\n };\n if (onDetected) {\n return onDetected(req, res, result);\n }\n res.status(statusCode).json({ error: message });\n return;\n }\n\n // Default action for uncategorized bots\n if (defaultAction === 'deny') {\n req.__arcis = {\n vector: 'bot',\n rule: 'bot/uncategorized',\n severity: 'medium',\n reason: 'Uncategorized bot under defaultAction=deny',\n decision: 'deny',\n };\n if (onDetected) {\n return onDetected(req, res, result);\n }\n res.status(statusCode).json({ error: message });\n return;\n }\n\n next();\n };\n}\n","/**\n * @module @arcis/node/middleware/csrf\n * CSRF (Cross-Site Request Forgery) protection middleware\n *\n * Implements the double-submit cookie pattern:\n * 1. Server sets a CSRF token in a cookie\n * 2. Client must send the same token in a header or form field\n * 3. Middleware rejects requests where cookie token !== header/field token\n *\n * This works because an attacker's cross-origin form submission will include\n * the cookie automatically, but cannot read it (same-origin policy) to set\n * the matching header.\n */\n\nimport { randomBytes, timingSafeEqual } from 'crypto';\nimport type { Request, Response, NextFunction, RequestHandler } from 'express';\n\n/** CSRF protection configuration */\nexport interface CsrfOptions {\n /** Cookie name for the CSRF token. Default: '_csrf' */\n cookieName?: string;\n /** Header name to check for the token. Default: 'x-csrf-token' */\n headerName?: string;\n /** Form field name to check for the token. Default: '_csrf' */\n fieldName?: string;\n /** Token byte length (hex-encoded = 2x chars). Default: 32 */\n tokenLength?: number;\n /** HTTP methods to protect. Default: ['POST', 'PUT', 'PATCH', 'DELETE'] */\n protectedMethods?: string[];\n /** Paths to exclude from CSRF checks (e.g., webhook endpoints) */\n excludePaths?: string[];\n /**\n * Per-request skip function. If it returns true, CSRF check is skipped\n * for that request. Useful for API key auth or signed webhooks.\n *\n * @example\n * skipCsrf: (req) => Boolean(req.headers['x-api-key'])\n */\n skipCsrf?: (req: Request) => boolean;\n /**\n * Use the __Host- cookie prefix for stronger cookie security.\n * When enabled, the browser enforces: Secure=true, no Domain, Path=/.\n * This prevents CSRF cookie theft across subdomains.\n * Default: false\n */\n useHostPrefix?: boolean;\n /** Cookie options */\n cookie?: {\n /** Cookie path. Default: '/' */\n path?: string;\n /** HttpOnly — set false so client JS can read it for headers. Default: false */\n httpOnly?: boolean;\n /** Secure flag (HTTPS only). Default: true in production */\n secure?: boolean;\n /** SameSite attribute. Default: 'Lax' */\n sameSite?: 'Strict' | 'Lax' | 'None';\n /** Cookie domain */\n domain?: string;\n };\n /** Custom error handler when CSRF validation fails */\n onError?: (req: Request, res: Response, next: NextFunction) => void;\n /**\n * Rotate the CSRF token after each successful validation on a protected\n * method. Defends against token-fixation attacks where an attacker plants\n * a known token before authentication. Default: false.\n *\n * When enabled, every successful POST/PUT/PATCH/DELETE causes the server to\n * issue a fresh token via Set-Cookie — the client must re-read the cookie\n * before the next mutating request.\n */\n rotateOnUse?: boolean;\n}\n\nconst DEFAULTS = {\n cookieName: '_csrf',\n headerName: 'x-csrf-token',\n fieldName: '_csrf',\n tokenLength: 32,\n protectedMethods: ['POST', 'PUT', 'PATCH', 'DELETE'],\n} as const;\n\n/**\n * Generate a cryptographically random CSRF token.\n *\n * @param length - Byte length (output is hex, so 2x chars). Default: 32\n * @returns Hex-encoded random token\n *\n * @example\n * const token = generateCsrfToken(); // 64 hex chars\n */\nexport function generateCsrfToken(length: number = 32): string {\n return randomBytes(length).toString('hex');\n}\n\n/**\n * Validate that two CSRF tokens match using constant-time comparison.\n *\n * @param cookieToken - Token from the cookie\n * @param requestToken - Token from the header or form field\n * @returns true if tokens match\n */\nexport function validateCsrfToken(cookieToken: string, requestToken: string): boolean {\n if (!cookieToken || !requestToken) return false;\n\n // SECURITY: Pad both buffers to a common reference length before\n // timingSafeEqual so an early length-check does not leak token length\n // through timing. Compute length-equality with a constant-time integer\n // compare and AND it AFTER the byte compare so execution time is the\n // same regardless of length mismatch.\n const paddedLength = Math.max(64, cookieToken.length, requestToken.length);\n const a = Buffer.alloc(paddedLength);\n const b = Buffer.alloc(paddedLength);\n Buffer.from(cookieToken, 'utf8').copy(a);\n Buffer.from(requestToken, 'utf8').copy(b);\n const bytesEqual = timingSafeEqual(a, b);\n const sameLength = cookieToken.length === requestToken.length;\n return bytesEqual && sameLength;\n}\n\n/**\n * Extract the CSRF token from a request (checks header, then body field, then query).\n */\nfunction getRequestToken(req: Request, headerName: string, fieldName: string): string | undefined {\n // 1. Check header (most common for SPAs)\n const headerToken = req.headers[headerName.toLowerCase()];\n if (typeof headerToken === 'string' && headerToken) return headerToken;\n\n // 2. Check body field (form submissions)\n if (req.body && typeof req.body === 'object' && fieldName in req.body) {\n const bodyToken = req.body[fieldName];\n if (typeof bodyToken === 'string' && bodyToken) return bodyToken;\n }\n\n // SECURITY: Query string intentionally not supported — tokens in URLs leak\n // to server logs, Referer headers, browser history, and CDN/proxy logs.\n\n return undefined;\n}\n\n/**\n * Create CSRF protection middleware using double-submit cookie pattern.\n *\n * For safe methods (GET, HEAD, OPTIONS), sets a CSRF token cookie if not present.\n * For unsafe methods (POST, PUT, PATCH, DELETE), validates the token.\n *\n * @param options - CSRF configuration\n * @returns Express middleware\n *\n * @example\n * // Basic usage\n * app.use(csrfProtection());\n *\n * @example\n * // Exclude webhook paths\n * app.use(csrfProtection({\n * excludePaths: ['/api/webhooks/stripe', '/api/webhooks/github']\n * }));\n *\n * @example\n * // Client-side: read cookie + set header\n * const token = document.cookie.match(/_csrf=([^;]+)/)?.[1];\n * fetch('/api/data', {\n * method: 'POST',\n * headers: { 'X-CSRF-Token': token },\n * credentials: 'same-origin'\n * });\n */\nexport function csrfProtection(options: CsrfOptions = {}): RequestHandler {\n const baseCookieName = options.cookieName ?? DEFAULTS.cookieName;\n // __Host- prefix: forces browser to enforce Secure + no Domain + Path=/\n const cookieName = options.useHostPrefix ? `__Host-${baseCookieName}` : baseCookieName;\n const headerName = options.headerName ?? DEFAULTS.headerName;\n const fieldName = options.fieldName ?? DEFAULTS.fieldName;\n const tokenLength = options.tokenLength ?? DEFAULTS.tokenLength;\n const protectedMethods = options.protectedMethods ?? [...DEFAULTS.protectedMethods];\n const excludePaths = options.excludePaths ?? [];\n const skipCsrf = options.skipCsrf;\n\n const isProduction = process.env.NODE_ENV === 'production';\n const cookieOpts = {\n path: options.cookie?.path ?? '/',\n httpOnly: options.cookie?.httpOnly ?? false, // Must be readable by client JS\n secure: options.cookie?.secure ?? isProduction,\n sameSite: options.cookie?.sameSite ?? 'Lax',\n domain: options.cookie?.domain,\n };\n\n const defaultOnError = (req: Request, res: Response, _next: NextFunction) => {\n // Telemetry attribution: dashboard groups CSRF denials under vector=csrf.\n req.__arcis = {\n vector: 'csrf',\n rule: 'csrf/token-mismatch',\n severity: 'high',\n reason: 'CSRF token missing or invalid',\n decision: 'deny',\n };\n res.status(403).json({\n error: 'CSRF token validation failed',\n message: 'Invalid or missing CSRF token. Include the token from the cookie in the X-CSRF-Token header.',\n });\n };\n\n const onError = options.onError ?? defaultOnError;\n\n // Normalize protected methods to uppercase\n const protectedSet = new Set(protectedMethods.map(m => m.toUpperCase()));\n\n return (req: Request, res: Response, next: NextFunction) => {\n const method = req.method.toUpperCase();\n\n // Per-request skip callback (API keys, signed webhooks, etc.)\n if (skipCsrf && skipCsrf(req)) {\n return next();\n }\n\n // Check if path is excluded\n const requestPath = req.path || req.url;\n if (excludePaths.some(p => requestPath === p || requestPath.startsWith(p + '/'))) {\n return next();\n }\n\n // Expose token generation on the request for templates/views\n (req as unknown as Record<string, unknown>).csrfToken = () => {\n const existing = getCookieValue(req, cookieName);\n if (existing) return existing;\n\n const token = generateCsrfToken(tokenLength);\n setCsrfCookie(res, cookieName, token, cookieOpts);\n return token;\n };\n\n // For safe methods — ensure a CSRF cookie exists\n if (!protectedSet.has(method)) {\n const existing = getCookieValue(req, cookieName);\n if (!existing) {\n const token = generateCsrfToken(tokenLength);\n setCsrfCookie(res, cookieName, token, cookieOpts);\n }\n return next();\n }\n\n // For protected methods — validate the token\n const cookieToken = getCookieValue(req, cookieName);\n if (!cookieToken) {\n return onError(req, res, next);\n }\n\n const requestToken = getRequestToken(req, headerName, fieldName);\n if (!requestToken) {\n return onError(req, res, next);\n }\n\n if (!validateCsrfToken(cookieToken, requestToken)) {\n return onError(req, res, next);\n }\n\n // Optional token rotation on successful validation\n if (options.rotateOnUse) {\n const freshToken = generateCsrfToken(tokenLength);\n setCsrfCookie(res, cookieName, freshToken, cookieOpts);\n }\n\n next();\n };\n}\n\n/**\n * Read a cookie value from the request.\n */\nfunction getCookieValue(req: Request, name: string): string | undefined {\n // Express parses cookies if cookie-parser is used\n if (req.cookies && typeof req.cookies === 'object' && name in req.cookies) {\n return req.cookies[name];\n }\n\n // Fallback: parse from raw Cookie header\n const cookieHeader = req.headers.cookie;\n if (!cookieHeader) return undefined;\n\n const match = cookieHeader.match(new RegExp(`(?:^|;\\\\s*)${escapeRegex(name)}=([^;]*)`));\n return match ? decodeURIComponent(match[1]) : undefined;\n}\n\n/**\n * Set the CSRF token cookie on the response.\n */\nfunction setCsrfCookie(\n res: Response,\n name: string,\n token: string,\n opts: { path: string; httpOnly: boolean; secure: boolean; sameSite: string; domain?: string }\n): void {\n const parts = [`${name}=${token}`];\n parts.push(`Path=${opts.path}`);\n if (opts.httpOnly) parts.push('HttpOnly');\n if (opts.secure) parts.push('Secure');\n parts.push(`SameSite=${opts.sameSite}`);\n if (opts.domain) parts.push(`Domain=${opts.domain}`);\n\n // Accumulate Set-Cookie headers to avoid overwriting cookies set by other middleware\n const newCookie = parts.join('; ');\n const existing = res.getHeader('Set-Cookie');\n if (existing === undefined) {\n res.setHeader('Set-Cookie', newCookie);\n } else if (Array.isArray(existing)) {\n res.setHeader('Set-Cookie', [...existing, newCookie]);\n } else {\n res.setHeader('Set-Cookie', [existing as string, newCookie]);\n }\n}\n\n/**\n * Escape special regex characters in a string.\n */\nfunction escapeRegex(str: string): string {\n return str.replace(/[.*+?^${}()|[\\]\\\\]/g, '\\\\$&');\n}\n\n/** Alias for csrfProtection */\nexport const createCsrf = csrfProtection;\n","/**\n * @module @arcis/node/middleware/hpp\n * HTTP Parameter Pollution (HPP) protection middleware\n *\n * Normalizes duplicate query and body parameters to their last value,\n * preventing attackers from bypassing validation by repeating parameters.\n *\n * Attack example:\n * GET /search?role=user&role=admin\n * Without HPP: req.query.role = ['user', 'admin']\n * With HPP: req.query.role = 'admin' (last value wins)\n *\n * Originals are preserved in req.queryPolluted / req.bodyPolluted\n * for logging or auditing without blocking the request.\n */\n\nimport type { Request, Response, NextFunction, RequestHandler } from 'express';\n\n/** HPP protection configuration */\nexport interface HppOptions {\n /**\n * Parameters that legitimately accept arrays and should not be normalized.\n * Example: ['tags', 'ids', 'filter']\n */\n whitelist?: string[];\n /** Normalize duplicate query string parameters. Default: true */\n checkQuery?: boolean;\n /** Normalize duplicate body parameters. Default: true */\n checkBody?: boolean;\n}\n\n/**\n * HTTP Parameter Pollution protection middleware.\n *\n * Normalizes duplicate query/body parameters to a single value (last wins).\n * Whitelisted parameters are allowed to remain as arrays.\n *\n * @param options - HPP configuration\n * @returns Express middleware\n *\n * @example\n * // Basic — normalize all duplicates\n * app.use(hpp());\n *\n * @example\n * // Allow arrays for specific params (e.g., tag filters, IDs)\n * app.use(hpp({ whitelist: ['tags', 'ids'] }));\n *\n * @example\n * // Inspect what was removed (for logging)\n * app.use((req, res, next) => {\n * const polluted = (req as any).queryPolluted;\n * if (Object.keys(polluted).length) logger.warn('HPP detected', polluted);\n * next();\n * });\n */\nexport function hpp(options: HppOptions = {}): RequestHandler {\n // SECURITY: Store whitelist as lowercase so case-variant params can't bypass.\n // Some frameworks normalize param case downstream — `TAGS` should match whitelist `tags`.\n const whitelist = new Set((options.whitelist ?? []).map((k) => k.toLowerCase()));\n const checkQuery = options.checkQuery ?? true;\n const checkBody = options.checkBody ?? true;\n\n return (req: Request, _res: Response, next: NextFunction) => {\n // ── Query string normalization ────────────────────────────────────────\n if (checkQuery && req.query && typeof req.query === 'object') {\n const polluted: Record<string, string[]> = {};\n const clean: Record<string, string | string[]> = {};\n\n for (const [key, value] of Object.entries(req.query)) {\n if (Array.isArray(value)) {\n const strings = value.filter((v): v is string => typeof v === 'string');\n if (whitelist.has(key.toLowerCase())) {\n // Whitelisted — preserve as array\n clean[key] = strings;\n } else {\n // Duplicate — record originals, use last value\n polluted[key] = strings;\n clean[key] = strings[strings.length - 1] ?? '';\n }\n } else {\n clean[key] = value as string;\n }\n }\n\n (req as unknown as Record<string, unknown>).queryPolluted = polluted;\n // SECURITY: Express 5 makes req.query read-only — use defineProperty\n Object.defineProperty(req, 'query', { value: clean, writable: true, configurable: true });\n }\n\n // ── Body normalization ────────────────────────────────────────────────\n if (checkBody && req.body && typeof req.body === 'object' && !Array.isArray(req.body)) {\n const polluted: Record<string, unknown[]> = {};\n const clean: Record<string, unknown> = {};\n\n for (const [key, value] of Object.entries(req.body as Record<string, unknown>)) {\n if (Array.isArray(value)) {\n if (whitelist.has(key.toLowerCase())) {\n clean[key] = value;\n } else {\n polluted[key] = value;\n clean[key] = value[value.length - 1];\n }\n } else {\n clean[key] = value;\n }\n }\n\n (req as unknown as Record<string, unknown>).bodyPolluted = polluted;\n Object.defineProperty(req, 'body', { value: clean, writable: true, configurable: true });\n }\n\n next();\n };\n}\n\nexport const createHpp = hpp;\n","/**\n * @module @arcis/node/middleware/response-splitting\n *\n * HTTP response splitting prevention (sdk-vectors.md tier 1 #27).\n *\n * Response splitting is the *output* counterpart to header injection: app\n * code passes user input into `res.setHeader`, `res.writeHead`, or\n * `res.appendHeader` (Node 17+) without stripping CR/LF, and an attacker\n * uses the embedded newline to break out of the header block and forge a\n * second response. Most often weaponised against `Location:` after a\n * redirect that reflects user input (`/redirect?to=...`).\n *\n * `sanitizeHeaderValue` already covers the byte-level fix on the way in;\n * this middleware wraps the response object so every header that leaves\n * the app gets sanitised on the way out — even when the app forgets.\n *\n * ```ts\n * import { responseSplittingGuard } from '@arcis/node/middleware/response-splitting';\n *\n * app.use(responseSplittingGuard());\n *\n * // Later — even this passes through clean:\n * app.get('/r', (req, res) => res.redirect(req.query.to as string));\n * ```\n *\n * Pair with `validateRedirect` for full coverage: this middleware blocks\n * the response-splitting payload, `validateRedirect` blocks the\n * open-redirect payload.\n */\n\nimport type { RequestHandler, Response } from 'express';\nimport { detectHeaderInjection, sanitizeHeaderValue } from '../sanitizers/headers';\n\nexport interface ResponseSplittingGuardOptions {\n /**\n * What to do when an outgoing header value contains CR / LF / NUL.\n *\n * - `'strip'` (default) — silently sanitise the value before it reaches\n * the wire. Preserves availability; existing routes don't break.\n * - `'reject'` — throw a `ResponseSplittingError`. Use in apps that\n * would rather fail-closed than emit a partial response.\n *\n * Both modes invoke `onDetect` if provided.\n */\n mode?: 'strip' | 'reject';\n\n /**\n * Per-detection callback. Fires before strip/reject. Useful for\n * logging or alerting when an attempted split slips through into the\n * response builder.\n */\n onDetect?: (header: string, originalValue: string) => void;\n}\n\n/**\n * Thrown by `responseSplittingGuard({ mode: 'reject' })` when an\n * outgoing header value contains CR / LF / NUL. The header name is in\n * `header`; the originally attempted value is in `value` so it can be\n * logged or surfaced in an error handler.\n */\nexport class ResponseSplittingError extends Error {\n readonly header: string;\n readonly value: string;\n\n constructor(header: string, value: string) {\n super(`Response splitting attempt detected on header \"${header}\"`);\n this.name = 'ResponseSplittingError';\n this.header = header;\n this.value = value;\n }\n}\n\n/**\n * Re-export under the response-splitting name. Same byte pattern as\n * header injection (CR / LF / NUL) — different threat model: input\n * boundary vs output boundary.\n */\nexport const detectResponseSplitting = detectHeaderInjection;\n\n/**\n * Re-export under the response-splitting name. Strips CR / LF / NUL.\n */\nexport const sanitizeResponseHeader = sanitizeHeaderValue;\n\n/**\n * Sanitise both the header name and value. Header *names* with CRLF are\n * always a bug — they let an attacker overwrite arbitrary subsequent\n * headers — so they are always stripped regardless of mode.\n */\nfunction safeName(name: unknown): string {\n return sanitizeHeaderValue(String(name ?? ''));\n}\n\nfunction valuesArray(value: unknown): string[] {\n if (Array.isArray(value)) return value.map((v) => String(v));\n if (value === undefined || value === null) return [];\n return [String(value)];\n}\n\n/**\n * Build the response-splitting guard middleware. Wraps `res.setHeader`,\n * `res.writeHead`, and `res.appendHeader` (when present) on each\n * incoming request so every header that leaves the app gets the same\n * CRLF / NUL treatment regardless of which code path emitted it.\n *\n * Wrapping happens per-request (not on the prototype) so multiple\n * mounts with different options don't trample each other.\n */\nexport function responseSplittingGuard(\n options: ResponseSplittingGuardOptions = {},\n): RequestHandler {\n const mode = options.mode ?? 'strip';\n const onDetect = options.onDetect;\n\n return (_req, res, next) => {\n const r = res as Response & {\n setHeader: Response['setHeader'];\n writeHead: Response['writeHead'];\n appendHeader?: (name: string, value: string | string[]) => Response;\n };\n\n const origSetHeader = r.setHeader.bind(r);\n const origWriteHead = r.writeHead.bind(r);\n const origAppendHeader = typeof r.appendHeader === 'function'\n ? r.appendHeader.bind(r)\n : undefined;\n\n function check(name: string, raw: unknown): unknown {\n const values = valuesArray(raw);\n const cleanedValues: string[] = [];\n for (const v of values) {\n if (detectHeaderInjection(v)) {\n if (onDetect) onDetect(name, v);\n if (mode === 'reject') {\n throw new ResponseSplittingError(name, v);\n }\n cleanedValues.push(sanitizeHeaderValue(v));\n } else {\n cleanedValues.push(v);\n }\n }\n // Preserve original cardinality: array → array, scalar → scalar.\n if (Array.isArray(raw)) return cleanedValues;\n if (raw === undefined || raw === null) return raw;\n return cleanedValues[0];\n }\n\n r.setHeader = function patchedSetHeader(\n name: string,\n value: number | string | readonly string[],\n ): Response {\n const safeKey = safeName(name);\n const safeValue = check(safeKey, value);\n return origSetHeader(safeKey, safeValue as number | string | readonly string[]);\n } as Response['setHeader'];\n\n r.writeHead = function patchedWriteHead(\n this: Response,\n statusCode: number,\n ...rest: unknown[]\n ): Response {\n let statusMessage: string | undefined;\n let headers: unknown;\n if (typeof rest[0] === 'string') {\n statusMessage = rest[0];\n headers = rest[1];\n } else {\n headers = rest[0];\n }\n\n let cleanedHeaders: unknown = headers;\n if (headers && typeof headers === 'object') {\n if (Array.isArray(headers)) {\n // Outgoing tuples: ['Set-Cookie', 'a=1\\r\\nb=2', ...]. Walk\n // pairs (Node accepts both flat and nested array shapes).\n if (headers.length > 0 && Array.isArray(headers[0])) {\n cleanedHeaders = (headers as unknown[][]).map((pair) => {\n const [k, v] = pair as [unknown, unknown];\n const sk = safeName(k);\n return [sk, check(sk, v)];\n });\n } else {\n const flat = headers as unknown[];\n const out: unknown[] = [];\n for (let i = 0; i < flat.length; i += 2) {\n const sk = safeName(flat[i]);\n out.push(sk, check(sk, flat[i + 1]));\n }\n cleanedHeaders = out;\n }\n } else {\n const out: Record<string, unknown> = {};\n for (const [k, v] of Object.entries(headers as Record<string, unknown>)) {\n const sk = safeName(k);\n out[sk] = check(sk, v);\n }\n cleanedHeaders = out;\n }\n }\n\n // Express's typed writeHead drops the 3-arg http.ServerResponse\n // overload; defer to Node's runtime signature here.\n const wh = origWriteHead as unknown as (\n statusCode: number,\n statusMessageOrHeaders?: string | unknown,\n headers?: unknown,\n ) => Response;\n if (statusMessage !== undefined) {\n return wh(statusCode, statusMessage, cleanedHeaders);\n }\n return wh(statusCode, cleanedHeaders);\n } as Response['writeHead'];\n\n if (origAppendHeader) {\n r.appendHeader = function patchedAppendHeader(\n name: string,\n value: string | string[],\n ): Response {\n const safeKey = safeName(name);\n const safeValue = check(safeKey, value);\n return origAppendHeader(safeKey, safeValue as string | string[]);\n };\n }\n\n next();\n };\n}\n\nexport default responseSplittingGuard;\n","/**\n * @module @arcis/node/middleware/token-budget\n *\n * Token-budget protection middleware. Caps per-key token spend over a\n * sliding window — meant for routes that proxy LLM calls, where a tight\n * 100-req/min rate limit isn't enough because a single 50KB prompt costs\n * the same as 1000 small requests.\n *\n * @example\n * import express from 'express';\n * import { tokenBudget } from '@arcis/node';\n *\n * const guard = tokenBudget({\n * maxTokens: 100_000, // 100K tokens per window\n * windowMs: 60 * 60 * 1000, // 1-hour window\n * maxRequestTokens: 5_000, // reject any single request over this\n * keyGenerator: (req) => req.user?.id ?? req.ip,\n * });\n *\n * app.post('/chat', guard, chatHandler);\n *\n * The default token estimator is `Math.ceil(bytesOf(body+query) / 4)` —\n * close to OpenAI's \"1 token ≈ 4 English characters\" rule. Override via\n * `estimateTokens` for accurate counting (tiktoken, etc.).\n */\n\nimport type { Request, RequestHandler } from 'express';\n\nexport interface TokenBudgetOptions {\n /** Max tokens a single key can spend in one window. Default: 100,000. */\n maxTokens?: number;\n /** Window length in milliseconds. Default: 60 * 60 * 1000 (1 hour). */\n windowMs?: number;\n /**\n * Max tokens a single request may consume. Requests over this size are\n * rejected with 413 BEFORE counting against the window budget. Default:\n * unset (no per-request cap).\n */\n maxRequestTokens?: number;\n /**\n * Function that returns the budget key for a request. Default: client IP\n * (req.ip), falling back to `unknown` when unresolvable.\n */\n keyGenerator?: (req: Request) => string;\n /**\n * Function that estimates the number of tokens a request will consume.\n * Default: `Math.ceil((req.body + req.query stringified bytes) / 4)`,\n * which approximates OpenAI's \"1 token ≈ 4 characters\" rule. Override\n * with tiktoken/accurate counting when you need precision.\n */\n estimateTokens?: (req: Request) => number;\n /** Status code for budget-exceeded responses. Default: 429. */\n statusCode?: number;\n /** Status code for oversize-request rejections. Default: 413. */\n statusCodeOversize?: number;\n /** Error message when budget is exceeded. */\n message?: string;\n /** Error message when a single request exceeds maxRequestTokens. */\n messageOversize?: string;\n /** Skip budget enforcement for certain requests. */\n skip?: (req: Request) => boolean;\n}\n\nexport interface TokenBudgetMiddleware extends RequestHandler {\n /** Release internal cleanup resources. */\n close: () => void;\n /** Inspect current usage for a key (read-only; for tests/telemetry). */\n inspect: (key: string) => { used: number; resetTime: number } | null;\n}\n\ninterface Entry {\n used: number;\n resetTime: number;\n}\n\nconst DEFAULT_MAX_TOKENS = 100_000;\nconst DEFAULT_WINDOW_MS = 60 * 60 * 1000;\n\nfunction defaultKeyGenerator(req: Request): string {\n const ip = req.ip ?? req.socket?.remoteAddress;\n return ip ?? 'unknown';\n}\n\nfunction defaultEstimateTokens(req: Request): number {\n // Approximate OpenAI's \"1 token ≈ 4 characters\" rule using byte length\n // of stringified body + query. Fast, side-effect-free, no model call.\n // Returns 0 for missing payloads so safe routes don't get charged.\n let bytes = 0;\n if (req.body !== undefined && req.body !== null) {\n try {\n bytes += Buffer.byteLength(\n typeof req.body === 'string' ? req.body : JSON.stringify(req.body),\n 'utf8',\n );\n } catch {\n // Circular structure or similar — treat as 0 rather than throw.\n }\n }\n if (req.query && Object.keys(req.query).length > 0) {\n try {\n bytes += Buffer.byteLength(JSON.stringify(req.query), 'utf8');\n } catch {\n // ignore\n }\n }\n return Math.ceil(bytes / 4);\n}\n\n/**\n * Build a token-budget middleware. See module-level JSDoc for usage.\n */\nexport function tokenBudget(options: TokenBudgetOptions = {}): TokenBudgetMiddleware {\n const maxTokens = options.maxTokens ?? DEFAULT_MAX_TOKENS;\n const windowMs = options.windowMs ?? DEFAULT_WINDOW_MS;\n const maxRequestTokens = options.maxRequestTokens;\n const keyGenerator = options.keyGenerator ?? defaultKeyGenerator;\n const estimateTokens = options.estimateTokens ?? defaultEstimateTokens;\n const statusCode = options.statusCode ?? 429;\n const statusCodeOversize = options.statusCodeOversize ?? 413;\n const message = options.message ?? 'Token budget exceeded for this window.';\n const messageOversize =\n options.messageOversize ??\n 'Request exceeds the per-request token limit.';\n const skip = options.skip;\n\n // Object.create(null) keeps __proto__/constructor keys from corrupting\n // the store if a buggy keyGenerator returns one of those names.\n const store = Object.create(null) as Record<string, Entry>;\n\n // Sweep expired buckets so a long-lived process doesn't grow unbounded.\n const cleanup = setInterval(() => {\n const now = Date.now();\n for (const k of Object.keys(store)) {\n if (store[k].resetTime < now) {\n delete store[k];\n }\n }\n }, windowMs);\n if (typeof cleanup.unref === 'function') cleanup.unref();\n\n const handler: RequestHandler = (req, res, next) => {\n if (skip?.(req)) {\n next();\n return;\n }\n\n let estimated = 0;\n try {\n estimated = estimateTokens(req);\n } catch {\n estimated = 0;\n }\n if (!Number.isFinite(estimated) || estimated < 0) estimated = 0;\n\n // Per-request cap (rejected before counting against the budget so a\n // single oversized request can't single-handedly drain a window).\n if (maxRequestTokens !== undefined && estimated > maxRequestTokens) {\n res.setHeader('X-Token-Budget-Limit', maxTokens.toString());\n res.setHeader('X-Token-Budget-Request-Cost', estimated.toString());\n res.status(statusCodeOversize).json({\n error: messageOversize,\n requestTokens: estimated,\n maxRequestTokens,\n });\n return;\n }\n\n const key = keyGenerator(req);\n const now = Date.now();\n let entry = store[key];\n if (!entry || entry.resetTime < now) {\n entry = { used: 0, resetTime: now + windowMs };\n store[key] = entry;\n }\n\n const projected = entry.used + estimated;\n const remaining = Math.max(0, maxTokens - entry.used);\n const resetSeconds = Math.ceil((entry.resetTime - now) / 1000);\n\n res.setHeader('X-Token-Budget-Limit', maxTokens.toString());\n res.setHeader('X-Token-Budget-Used', entry.used.toString());\n res.setHeader('X-Token-Budget-Remaining', remaining.toString());\n res.setHeader('X-Token-Budget-Reset', resetSeconds.toString());\n res.setHeader('X-Token-Budget-Request-Cost', estimated.toString());\n\n if (projected > maxTokens) {\n res.setHeader('Retry-After', resetSeconds.toString());\n res.status(statusCode).json({\n error: message,\n used: entry.used,\n maxTokens,\n retryAfter: resetSeconds,\n });\n return;\n }\n\n // Charge the budget and continue.\n entry.used = projected;\n next();\n };\n\n const middleware = handler as TokenBudgetMiddleware;\n middleware.close = () => clearInterval(cleanup);\n middleware.inspect = (key: string) => {\n const e = store[key];\n if (!e) return null;\n return { used: e.used, resetTime: e.resetTime };\n };\n return middleware;\n}\n\nexport default tokenBudget;\n","/**\n * @module @arcis/node/middleware/overload\n *\n * Event-loop overload protection (sdk-vectors.md tier 1 #30, issue #51).\n *\n * Rate limiting caps per-client load; this middleware caps **total server\n * load** by sampling event-loop lag and shedding new requests with 503\n * when the loop is saturated. Pairs with rate-limit (per-client) +\n * `methodAllowlist` (per-route) to give Arcis three orthogonal layers\n * of \"this server is healthy enough to do work\" gating.\n *\n * ```ts\n * import { eventLoopProtection } from '@arcis/node';\n *\n * app.use(eventLoopProtection({\n * maxLagMs: 500, // 503 above this smoothed lag\n * sampleIntervalMs: 250, // measure every 250ms\n * }));\n * ```\n *\n * Sampling strategy:\n * - `setInterval(fn, sampleIntervalMs)` is scheduled; the callback\n * compares wall-clock elapsed against the configured interval. Lag\n * IS the difference: when the loop is busy, the timer fires late.\n * - The interval handle is `.unref()`-ed so the process can exit\n * cleanly even if the caller forgets to call `close()`.\n * - Exponential moving average (`smoothed = 0.7 * smoothed + 0.3 *\n * measured`) smooths out single-sample spikes — a 600ms GC pause\n * shouldn't cause every request to 503 for the next sample window.\n *\n * Implementation deliberately picks `setTimeout` measurement over\n * `perf_hooks.monitorEventLoopDelay` (Node 12+ alternative) for two\n * reasons: (1) it works on every supported Node version with no feature\n * detection branch, (2) the perf_hooks histogram returns nanosecond\n * lag from a 10ms-resolution sampler, but applying the spec's EMA\n * formula on that signal would skew toward unreal lag values that the\n * sampler smoothed away. Keeping the sampler the spec calls for keeps\n * the math testable.\n */\n\nimport type { RequestHandler, Response } from 'express';\n\nexport interface EventLoopProtectionOptions {\n /** Smoothed lag threshold in ms above which the middleware returns 503. Default: 500. */\n maxLagMs?: number;\n /** Sample frequency in ms. Default: 250. Lower = more responsive, higher = less overhead. */\n sampleIntervalMs?: number;\n /** Status code to return when overloaded. Default: 503. */\n statusCode?: number;\n /** Error message in the response body. Default: \"Server overloaded, please retry\". */\n message?: string;\n /** Retry-After header value in seconds. Default: 5. */\n retryAfterSeconds?: number;\n /**\n * EMA smoothing factor for the new measurement. Default: 0.3 (per\n * issue #51 spec). Must be in (0, 1]; lower values smooth harder\n * (longer memory of past samples), higher values track more reactively.\n */\n alpha?: number;\n /**\n * When true, every response gets `X-EventLoop-Lag: <ms>` so monitoring\n * can graph saturation independent of the deny decision. Off by default\n * because most apps don't need it and an extra header on every response\n * adds noise.\n */\n exposeLagHeader?: boolean;\n}\n\nexport interface EventLoopProtectionMiddleware extends RequestHandler {\n /**\n * Stop the sampler. Call from a SIGTERM handler so the interval doesn't\n * keep a misconfigured process alive. Idempotent: subsequent calls are\n * no-ops.\n */\n close(): void;\n /**\n * Read the current smoothed lag in ms. Useful for tests that want to\n * assert the smoothing math without mocking timers, and for callers\n * who want to expose the value through a different surface (Prometheus,\n * dashboard panel, etc.).\n */\n currentLagMs(): number;\n}\n\nconst DEFAULTS = {\n maxLagMs: 500,\n sampleIntervalMs: 250,\n statusCode: 503,\n message: 'Server overloaded, please retry',\n retryAfterSeconds: 5,\n alpha: 0.3,\n} as const;\n\n/**\n * Build an event-loop protection middleware. Returns a request handler\n * with `close()` and `currentLagMs()` attached (Pattern 6 in the\n * monorepo's middleware conventions: factories return a callable\n * augmented with cleanup helpers).\n */\nexport function eventLoopProtection(\n options: EventLoopProtectionOptions = {},\n): EventLoopProtectionMiddleware {\n const maxLagMs = options.maxLagMs ?? DEFAULTS.maxLagMs;\n const sampleIntervalMs = options.sampleIntervalMs ?? DEFAULTS.sampleIntervalMs;\n const statusCode = options.statusCode ?? DEFAULTS.statusCode;\n const message = options.message ?? DEFAULTS.message;\n const retryAfterSeconds = options.retryAfterSeconds ?? DEFAULTS.retryAfterSeconds;\n const alpha = options.alpha ?? DEFAULTS.alpha;\n const exposeLagHeader = options.exposeLagHeader === true;\n\n // Validate up-front so misconfiguration surfaces at app boot, not on\n // the first overloaded request.\n if (maxLagMs <= 0) {\n throw new RangeError('eventLoopProtection: maxLagMs must be > 0');\n }\n if (sampleIntervalMs <= 0) {\n throw new RangeError('eventLoopProtection: sampleIntervalMs must be > 0');\n }\n if (alpha <= 0 || alpha > 1) {\n throw new RangeError('eventLoopProtection: alpha must be in (0, 1]');\n }\n\n let smoothedLag = 0;\n let lastTickTime = Date.now();\n let stopped = false;\n\n // Sampler: each tick measures elapsed time vs the configured interval.\n // The difference is the lag — on a healthy loop it's ~0; on a saturated\n // loop the timer fires late. Apply the EMA after every measurement so\n // the value the middleware reads on the NEXT request is smoothed.\n const interval = setInterval(() => {\n const now = Date.now();\n const elapsed = now - lastTickTime;\n const measuredLag = Math.max(0, elapsed - sampleIntervalMs);\n smoothedLag = (1 - alpha) * smoothedLag + alpha * measuredLag;\n lastTickTime = now;\n }, sampleIntervalMs);\n\n // Don't pin the process alive. The Node `Timer.unref()` returns the\n // handle so we can chain it; behavior is well-known across versions.\n if (typeof interval.unref === 'function') {\n interval.unref();\n }\n\n const middleware = ((_req, res, next) => {\n if (exposeLagHeader) {\n // Round to ms for header sanity — float values render awkwardly.\n res.setHeader('X-EventLoop-Lag', Math.round(smoothedLag).toString());\n }\n if (!stopped && smoothedLag > maxLagMs) {\n (res as Response).setHeader('Retry-After', retryAfterSeconds.toString());\n res.status(statusCode).json({\n error: message,\n retryAfter: retryAfterSeconds,\n });\n return;\n }\n next();\n }) as EventLoopProtectionMiddleware;\n\n middleware.close = () => {\n if (stopped) return;\n stopped = true;\n clearInterval(interval);\n };\n\n middleware.currentLagMs = () => smoothedLag;\n\n return middleware;\n}\n\nexport default eventLoopProtection;\n\n// Test-only export so tests can drive the smoother without spinning real\n// timers. Computes one EMA step against the supplied prior + measurement.\nexport const __test = {\n ema(prior: number, measured: number, alpha: number): number {\n return (1 - alpha) * prior + alpha * measured;\n },\n};\n","/**\n * @module @arcis/node/middleware/method-allowlist\n *\n * HTTP method tampering protection (sdk-vectors.md tier 1 #26).\n *\n * Two related threats:\n *\n * 1. **Disallowed methods** — TRACE leaks Authorization headers (XST);\n * CONNECT is for proxies and shouldn't reach an application server;\n * custom verbs slip past route-handlers that only check `if (req.method\n * === 'POST')`. The middleware rejects anything outside an allowlist\n * with 405.\n *\n * 2. **Method-override bypass** — frameworks that respect\n * `X-HTTP-Method-Override` let an attacker turn a GET into a POST or\n * DELETE, bypassing route-level method checks. The middleware strips\n * these headers BEFORE the route handler sees them.\n *\n * Pair with the bundle middleware:\n *\n * ```ts\n * import { arcis } from '@arcis/node';\n * import { methodAllowlist } from '@arcis/node/middleware/method-allowlist';\n *\n * app.use(methodAllowlist());\n * app.use(arcis());\n * ```\n *\n * Or standalone for fine-grained mounts:\n *\n * ```ts\n * app.use('/api', methodAllowlist({ allow: ['GET', 'POST'] }));\n * ```\n */\n\nimport type { RequestHandler } from 'express';\n\n/**\n * Headers that frameworks treat as method overrides. Each one rewrites\n * `req.method` somewhere in the stack — we strip all three so a request\n * always travels under its wire method.\n */\nconst METHOD_OVERRIDE_HEADERS = [\n 'x-http-method-override',\n 'x-method-override',\n 'x-http-method',\n] as const;\n\nconst DEFAULT_ALLOWED_METHODS: readonly string[] = [\n 'GET',\n 'POST',\n 'PUT',\n 'DELETE',\n 'HEAD',\n 'OPTIONS',\n 'PATCH',\n];\n\nexport interface MethodAllowlistOptions {\n /**\n * Methods to permit. Each entry is uppercased before comparison so\n * `['get', 'post']` works the same as `['GET', 'POST']`. Defaults to\n * the full standard CRUD set: GET, POST, PUT, DELETE, HEAD, OPTIONS,\n * PATCH. TRACE and CONNECT are intentionally excluded — the former\n * leaks Authorization (XST), the latter is for proxies.\n */\n allow?: readonly string[];\n\n /**\n * Strip method-override headers (`X-HTTP-Method-Override`,\n * `X-Method-Override`, `X-HTTP-Method`) before the request reaches the\n * route handler. Default: true. Set to false only if your stack\n * legitimately uses one of these headers for client-method tunnelling\n * AND you've verified each override target is auth-checked\n * independently.\n */\n stripOverrideHeaders?: boolean;\n\n /** HTTP status code for the deny response. Default: 405 Method Not Allowed. */\n statusCode?: number;\n\n /** Error message body. Default: \"Method not allowed\". */\n message?: string;\n}\n\n/**\n * Build a method-allowlist middleware. Uppercase-matches `req.method`\n * against the allow set; strips override headers so downstream code\n * can't be tricked into running a different method's logic.\n */\nexport function methodAllowlist(options: MethodAllowlistOptions = {}): RequestHandler {\n const allow = new Set(\n (options.allow ?? DEFAULT_ALLOWED_METHODS).map((m) => m.toUpperCase()),\n );\n const strip = options.stripOverrideHeaders !== false;\n const statusCode = options.statusCode ?? 405;\n const message = options.message ?? 'Method not allowed';\n\n return (req, res, next) => {\n if (strip) {\n // Remove BEFORE the allowlist check so an attacker can't slip a\n // disallowed method through via override (e.g. wire GET +\n // X-HTTP-Method-Override: TRACE — strip the header, the GET\n // passes the allowlist, the override never reaches the route).\n for (const h of METHOD_OVERRIDE_HEADERS) {\n delete req.headers[h];\n }\n }\n\n const method = (req.method ?? '').toUpperCase();\n if (!allow.has(method)) {\n // 405 spec wants Allow header listing accepted methods.\n res.setHeader('Allow', Array.from(allow).join(', '));\n res.status(statusCode).json({\n error: message,\n method: req.method,\n });\n return;\n }\n\n next();\n };\n}\n\nexport default methodAllowlist;\n","/**\n * @module @arcis/node/middleware/mass-assign\n *\n * Mass-assignment runtime guard (sdk-vectors.md tier 1 #25).\n *\n * The classic mass-assignment vulnerability:\n *\n * ```js\n * const user = await User.findOne({ id });\n * Object.assign(user, req.body); // attacker sets req.body.is_admin = true\n * await user.save();\n * ```\n *\n * This middleware filters `req.body` to a per-route allowlist before\n * the handler runs. Two modes:\n *\n * - `'strip'` (default) — silently drop disallowed keys, continue.\n * - `'reject'` — return 400 with the offending key names.\n *\n * Pair it with the audit rule (`MASS-ASSIGN` in `arcis audit`) for the\n * static-analysis side and the route-level middleware for the runtime\n * side. Audit catches `Object.assign(target, req.body)` patterns at\n * build time; this middleware catches the runtime data flow.\n *\n * ```ts\n * import { massAssign } from '@arcis/node';\n *\n * app.post('/users',\n * massAssign({ allow: ['email', 'password', 'name'] }),\n * async (req, res) => {\n * // req.body has been filtered — is_admin / role / created_at all gone.\n * const user = await User.create(req.body);\n * res.json(user);\n * },\n * );\n * ```\n *\n * Default scope is top-level keys only. Nested objects pass through\n * untouched — that's deliberate: nested allowlists encourage\n * `allow: ['profile.bio', 'profile.avatar']` style strings which\n * become a parser, not a guard. Use a schema validator (Zod / Joi /\n * Arcis's `validate`) when nested filtering is required; this\n * middleware handles the 80% case of \"filter req.body for an ORM\n * mass-assign call\".\n */\n\nimport type { Request, RequestHandler, Response, NextFunction } from 'express';\n\nexport interface MassAssignOptions {\n /**\n * Allowlist of permitted top-level keys on `req.body`. Required —\n * a missing or empty array would silently strip every key, almost\n * certainly a configuration mistake.\n */\n allow: readonly string[];\n /**\n * Behavior when `req.body` contains a key NOT in `allow`:\n * - `'strip'` (default): silently drop the key, continue.\n * - `'reject'`: return `statusCode` (default 400) with a JSON\n * body listing the disallowed keys.\n */\n mode?: 'strip' | 'reject';\n /** Status code for the reject path. Default: 400. */\n statusCode?: number;\n /** Error message in the reject body. Default: \"Disallowed fields\". */\n message?: string;\n /**\n * Skip the filter when `req.body` is not a plain object (string,\n * array, FormData, etc.). Default: true. Set to false to surface\n * a 400 (\"body must be an object\") on those payloads — useful for\n * routes that should ONLY accept JSON objects.\n */\n passThroughNonObjects?: boolean;\n}\n\nconst DEFAULTS = {\n mode: 'strip' as const,\n statusCode: 400,\n message: 'Disallowed fields',\n passThroughNonObjects: true,\n} as const;\n\n/**\n * Build a mass-assignment guard middleware. Runs against `req.body`\n * before the route handler — must be installed AFTER body-parsing\n * middleware (`express.json()` / `express.urlencoded()`) so `req.body`\n * is already populated.\n */\nexport function massAssign(options: MassAssignOptions): RequestHandler {\n if (!options || !Array.isArray(options.allow)) {\n throw new TypeError('massAssign: options.allow must be a string array');\n }\n if (options.allow.length === 0) {\n // Empty allow list strips every key. Almost certainly a bug — fail\n // loud at boot rather than silently accept-and-strip in production.\n throw new RangeError(\n 'massAssign: options.allow must contain at least one key (use sanitize: false to disable instead)',\n );\n }\n\n const allowSet = new Set(options.allow);\n const mode = options.mode ?? DEFAULTS.mode;\n const statusCode = options.statusCode ?? DEFAULTS.statusCode;\n const message = options.message ?? DEFAULTS.message;\n const passThroughNonObjects =\n options.passThroughNonObjects ?? DEFAULTS.passThroughNonObjects;\n\n return (req: Request, res: Response, next: NextFunction) => {\n const body = req.body;\n\n // No body: nothing to filter. Express sets req.body to {} when the\n // body parser ran but the request had no body, and to undefined\n // when no parser was wired — both flow through unchanged.\n if (body === undefined || body === null) {\n next();\n return;\n }\n\n // Non-object payload (string / array / Buffer / FormData). The\n // mass-assign vector is specifically Object.assign-style key\n // expansion; non-objects don't have keys to filter, so the default\n // is pass-through.\n if (typeof body !== 'object' || Array.isArray(body)) {\n if (passThroughNonObjects) {\n next();\n return;\n }\n res.status(statusCode).json({\n error: 'Request body must be a JSON object',\n });\n return;\n }\n\n const incoming = Object.keys(body as Record<string, unknown>);\n const disallowed = incoming.filter((k) => !allowSet.has(k));\n\n if (disallowed.length > 0 && mode === 'reject') {\n res.status(statusCode).json({\n error: message,\n fields: disallowed,\n });\n return;\n }\n\n if (disallowed.length > 0) {\n // Strip mode — build a fresh object with only allowed keys. Avoid\n // mutating the original `req.body` reference because some\n // frameworks freeze the body or wire it to other middleware.\n const filtered: Record<string, unknown> = {};\n for (const key of incoming) {\n if (allowSet.has(key)) {\n filtered[key] = (body as Record<string, unknown>)[key];\n }\n }\n // Express 5 / Connect 4 made req.body a getter on some versions;\n // assign via Object.defineProperty to stay safe across both. (Same\n // pattern arcis uses in `validation/schema.ts` for the same\n // reason.)\n Object.defineProperty(req, 'body', {\n value: filtered,\n writable: true,\n configurable: true,\n enumerable: true,\n });\n }\n\n next();\n };\n}\n\nexport default massAssign;\n","/**\n * @module @arcis/node/middleware/signup-protection\n *\n * Composite signup-form protection: one middleware that combines email\n * validation (syntax + disposable), bot detection, and a dedicated\n * per-IP rate limit. Matches the Arcjet `protectSignup` convenience\n * primitive but stays fully local — no cloud lookups.\n *\n * @example\n * app.post('/signup', signupProtection(), handler);\n *\n * @example\n * app.post('/signup', signupProtection({\n * emailField: 'email',\n * rateLimit: { max: 5, windowMs: 60_000 },\n * blockDisposable: true,\n * }), handler);\n */\n\nimport type { Request, Response, NextFunction, RequestHandler } from 'express';\nimport { validateEmail } from '../validation/email';\nimport { detectBot, type BotCategory } from './bot-detection';\nimport { createRateLimiter } from './rate-limit';\n\nexport type SignupBlockReason =\n | 'missing_email'\n | 'invalid_email'\n | 'disposable_email'\n | 'bot'\n | 'rate_limited';\n\nexport interface SignupCheckResult {\n allowed: boolean;\n reason: SignupBlockReason | 'ok';\n details?: Record<string, unknown>;\n}\n\nexport interface SignupProtectionOptions {\n /** Request body field holding the email address. Default: 'email' */\n emailField?: string;\n /** Run email validation. Default: true */\n checkEmail?: boolean;\n /** Reject disposable email domains. Default: true */\n blockDisposable?: boolean;\n /** Run bot detection. Default: true */\n checkBot?: boolean;\n /** Bot categories allowed through (e.g. test harnesses). Default: [] — all bots blocked */\n allowedBotCategories?: BotCategory[];\n /** Per-IP rate limit on signup endpoint. Set to `false` to disable. Default: 5 requests / 60s */\n rateLimit?: { max?: number; windowMs?: number } | false;\n /** Extra email domains to allow (bypasses disposable check) */\n allowedEmailDomains?: string[];\n /** Extra email domains to block */\n blockedEmailDomains?: string[];\n /** Called when a request is blocked — for telemetry/logging */\n onBlocked?: (req: Request, result: SignupCheckResult) => void;\n}\n\nexport interface SignupProtectionMiddleware extends RequestHandler {\n /** Release the rate-limiter cleanup interval */\n close: () => void;\n}\n\n/**\n * Pure signup check — no rate-limit mutation, no response writes.\n * Useful for framework adapters or custom control flow.\n */\nexport function checkSignup(\n req: Request,\n options: SignupProtectionOptions = {}\n): SignupCheckResult {\n const {\n emailField = 'email',\n checkEmail = true,\n blockDisposable = true,\n checkBot = true,\n allowedBotCategories = [],\n allowedEmailDomains = [],\n blockedEmailDomains = [],\n } = options;\n\n if (checkBot) {\n const bot = detectBot(req);\n if (bot.isBot && !allowedBotCategories.includes(bot.category)) {\n return {\n allowed: false,\n reason: 'bot',\n details: { category: bot.category, name: bot.name, confidence: bot.confidence },\n };\n }\n }\n\n if (checkEmail) {\n const email = (req.body as Record<string, unknown> | undefined)?.[emailField];\n if (typeof email !== 'string' || email.length === 0) {\n return { allowed: false, reason: 'missing_email' };\n }\n const result = validateEmail(email, {\n checkDisposable: blockDisposable,\n allowedDomains: allowedEmailDomains,\n blockedDomains: blockedEmailDomains,\n });\n if (!result.valid) {\n const reason: SignupBlockReason =\n result.reason === 'disposable' ? 'disposable_email' : 'invalid_email';\n return { allowed: false, reason, details: { emailReason: result.reason } };\n }\n }\n\n return { allowed: true, reason: 'ok' };\n}\n\n/**\n * Express middleware: applies bot + email + rate-limit checks to a signup\n * endpoint. Responds 400/403/429 with a JSON body on block; otherwise\n * calls `next()`.\n */\nexport function signupProtection(\n options: SignupProtectionOptions = {}\n): SignupProtectionMiddleware {\n const rateLimitCfg = options.rateLimit;\n const limiter =\n rateLimitCfg === false\n ? null\n : createRateLimiter({\n max: rateLimitCfg?.max ?? 5,\n windowMs: rateLimitCfg?.windowMs ?? 60_000,\n message: 'Too many signup attempts',\n });\n\n const handler: RequestHandler = (req, res, next) => {\n const result = checkSignup(req, options);\n if (!result.allowed) {\n options.onBlocked?.(req, result);\n const status = result.reason === 'bot' ? 403 : 400;\n res.status(status).json({ error: 'signup_blocked', reason: result.reason });\n return;\n }\n if (limiter) {\n // Delegate to rate limiter — it will respond 429 on breach or call next() otherwise.\n let rateLimited = false;\n const rateLimitNext: NextFunction = (err?: unknown) => {\n if (err) return next(err);\n if (!rateLimited) next();\n };\n const patchedRes = new Proxy(res, {\n get(target, prop) {\n if (prop === 'status') {\n return (code: number) => {\n if (code === 429) {\n rateLimited = true;\n options.onBlocked?.(req, { allowed: false, reason: 'rate_limited' });\n }\n return (target.status as (c: number) => Response).call(target, code);\n };\n }\n return Reflect.get(target, prop);\n },\n });\n limiter(req, patchedRes as Response, rateLimitNext);\n return;\n }\n next();\n };\n\n const middleware = handler as SignupProtectionMiddleware;\n middleware.close = () => limiter?.close();\n return middleware;\n}\n","/**\n * Abstract base for storage-backed rate limiters. Holds the `points` /\n * `duration` / `blockDuration` / `execEvenly` configuration that any\n * concrete limiter shares. Subclasses (`MemoryLimiter`, future Redis\n * backend) implement `consume()` and friends.\n *\n * Ported to TypeScript from upstream RateLimiterAbstract. See\n * `THIRDPARTY-LICENSES.md` for attribution.\n */\n\nimport type { LimiterOptions, LimiterConsumeOptions, IRateLimiterRes } from './types';\n\nexport abstract class AbstractLimiter {\n protected _points: number;\n protected _duration: number;\n protected _blockDuration: number;\n protected _execEvenly: boolean;\n protected _execEvenlyMinDelayMs: number;\n protected _keyPrefix: string;\n\n constructor(opts: LimiterOptions) {\n if (!Number.isFinite(opts.points)) {\n throw new Error('points must be a finite number');\n }\n if (!Number.isFinite(opts.duration) || opts.duration < 0) {\n throw new Error('duration must be a finite, non-negative number');\n }\n this._points = opts.points;\n this._duration = opts.duration;\n this._blockDuration = typeof opts.blockDuration === 'undefined' ? 0 : opts.blockDuration;\n this._execEvenly = Boolean(opts.execEvenly);\n this._execEvenlyMinDelayMs =\n typeof opts.execEvenlyMinDelayMs === 'undefined'\n ? Math.ceil((this._duration * 1000) / Math.max(this._points, 1))\n : opts.execEvenlyMinDelayMs;\n if (typeof opts.keyPrefix === 'undefined') {\n this._keyPrefix = 'arcis';\n } else if (typeof opts.keyPrefix !== 'string') {\n throw new Error('keyPrefix must be a string');\n } else {\n this._keyPrefix = opts.keyPrefix;\n }\n }\n\n get points(): number {\n return this._points;\n }\n get duration(): number {\n return this._duration;\n }\n get msDuration(): number {\n return this._duration * 1000;\n }\n get blockDuration(): number {\n return this._blockDuration;\n }\n get msBlockDuration(): number {\n return this._blockDuration * 1000;\n }\n get execEvenly(): boolean {\n return this._execEvenly;\n }\n get execEvenlyMinDelayMs(): number {\n return this._execEvenlyMinDelayMs;\n }\n get keyPrefix(): string {\n return this._keyPrefix;\n }\n\n protected _getKeySecDuration(options: LimiterConsumeOptions = {}): number {\n return typeof options.customDuration === 'number' && options.customDuration >= 0\n ? options.customDuration\n : this._duration;\n }\n\n protected _getKey(key: string): string {\n return this._keyPrefix.length > 0 ? `${this._keyPrefix}:${key}` : key;\n }\n\n abstract consume(key: string, pointsToConsume?: number, options?: LimiterConsumeOptions): Promise<IRateLimiterRes>;\n abstract penalty(key: string, points?: number, options?: LimiterConsumeOptions): Promise<IRateLimiterRes>;\n abstract reward(key: string, points?: number, options?: LimiterConsumeOptions): Promise<IRateLimiterRes>;\n abstract block(key: string, secDuration: number): Promise<IRateLimiterRes>;\n abstract get(key: string): Promise<IRateLimiterRes | null>;\n abstract delete(key: string): Promise<boolean>;\n}\n","/**\n * Rate-limiter response object. The shape returned (or rejected with) by\n * every limiter call. Mirrors the upstream `RateLimiterRes` contract.\n *\n * See `THIRDPARTY-LICENSES.md` for upstream attribution. This file is\n * an internal TypeScript port; do not re-export the class name verbatim.\n */\n\nexport interface IRateLimiterRes {\n remainingPoints: number;\n msBeforeNext: number;\n consumedPoints: number;\n isFirstInDuration: boolean;\n}\n\nexport class LimiterResult implements IRateLimiterRes {\n remainingPoints: number;\n msBeforeNext: number;\n consumedPoints: number;\n isFirstInDuration: boolean;\n\n constructor(\n remainingPoints: number = 0,\n msBeforeNext: number = 0,\n consumedPoints: number = 0,\n isFirstInDuration: boolean = false,\n ) {\n this.remainingPoints = remainingPoints;\n this.msBeforeNext = msBeforeNext;\n this.consumedPoints = consumedPoints;\n this.isFirstInDuration = isFirstInDuration;\n }\n}\n\nexport interface LimiterOptions {\n /** Total points available per duration window. */\n points: number;\n /** Window length in seconds. 0 = never expires. */\n duration: number;\n /** Seconds to block a key after it consumed more than `points`. 0 = no block. */\n blockDuration?: number;\n /** Spread allowed actions evenly across the window via setTimeout delays. */\n execEvenly?: boolean;\n /** Floor on the per-call delay introduced by `execEvenly`. */\n execEvenlyMinDelayMs?: number;\n /** Namespace prefix for keys inside the underlying storage. */\n keyPrefix?: string;\n}\n\nexport interface LimiterConsumeOptions {\n /** Override the configured duration for this call only (seconds). */\n customDuration?: number;\n}\n","/**\n * Internal record stored inside the in-memory storage map. One per key.\n * See `THIRDPARTY-LICENSES.md` for upstream attribution.\n */\n\nexport class StorageRecord {\n value: number;\n expiresAt: number | null;\n timeoutId: ReturnType<typeof setTimeout> | null;\n\n constructor(value: number, expiresAt: number | null, timeoutId: ReturnType<typeof setTimeout> | null = null) {\n this.value = Math.trunc(value);\n this.expiresAt = expiresAt;\n this.timeoutId = timeoutId;\n }\n}\n","/**\n * In-memory storage backend for the rate limiter. Tracks integer counters\n * per key with optional TTL expiry. Ported to TypeScript from the upstream\n * MemoryStorage class. See `THIRDPARTY-LICENSES.md` for attribution.\n */\n\nimport { LimiterResult } from './types';\nimport { StorageRecord } from './record';\n\nexport class MemoryStorage {\n private _storage: Map<string, StorageRecord> = new Map();\n\n /**\n * Increment the counter for `key` by `value`. If the key has no record\n * (or its TTL has expired), a new record is created with `durationSec`\n * lifetime.\n */\n incrby(key: string, value: number, durationSec: number): LimiterResult {\n const record = this._storage.get(key);\n if (record) {\n const msBeforeExpires = record.expiresAt ? record.expiresAt - Date.now() : -1;\n if (!record.expiresAt || msBeforeExpires > 0) {\n record.value = record.value + value;\n return new LimiterResult(0, msBeforeExpires, record.value, false);\n }\n return this.set(key, value, durationSec);\n }\n return this.set(key, value, durationSec);\n }\n\n /**\n * Write the counter for `key` to `value`, replacing any existing\n * record. `durationSec` of 0 means \"never expires\".\n */\n set(key: string, value: number, durationSec: number): LimiterResult {\n const durationMs = durationSec * 1000;\n const existing = this._storage.get(key);\n if (existing && existing.timeoutId) {\n clearTimeout(existing.timeoutId);\n }\n\n const record = new StorageRecord(value, durationMs > 0 ? Date.now() + durationMs : null);\n this._storage.set(key, record);\n\n if (durationMs > 0) {\n record.timeoutId = setTimeout(() => {\n this._storage.delete(key);\n }, durationMs);\n if (typeof record.timeoutId.unref === 'function') {\n record.timeoutId.unref();\n }\n }\n\n return new LimiterResult(0, durationMs === 0 ? -1 : durationMs, record.value, true);\n }\n\n get(key: string): LimiterResult | null {\n const record = this._storage.get(key);\n if (!record) return null;\n const msBeforeExpires = record.expiresAt ? record.expiresAt - Date.now() : -1;\n return new LimiterResult(0, msBeforeExpires, record.value, false);\n }\n\n delete(key: string): boolean {\n const record = this._storage.get(key);\n if (!record) return false;\n if (record.timeoutId) {\n clearTimeout(record.timeoutId);\n }\n this._storage.delete(key);\n return true;\n }\n\n /** Inspect the underlying map. Test-only and not part of the public API. */\n _dump(): IterableIterator<[string, StorageRecord]> {\n return this._storage.entries();\n }\n\n /** Clear all records. Used by tests and by `Limiter.dispose()`. */\n clear(): void {\n for (const record of this._storage.values()) {\n if (record.timeoutId) clearTimeout(record.timeoutId);\n }\n this._storage.clear();\n }\n}\n","/**\n * In-memory rate limiter backed by `MemoryStorage`. Implements the\n * `consume()` / `penalty()` / `reward()` / `block()` / `get()` /\n * `delete()` surface from the upstream limiter library.\n *\n * Ported to TypeScript from RateLimiterMemory. See\n * `THIRDPARTY-LICENSES.md` for attribution.\n */\n\nimport { AbstractLimiter } from './abstract';\nimport { MemoryStorage } from './memory-storage';\nimport { LimiterResult } from './types';\nimport type { LimiterOptions, LimiterConsumeOptions, IRateLimiterRes } from './types';\n\nexport class MemoryLimiter extends AbstractLimiter {\n private _storage: MemoryStorage;\n\n constructor(opts: LimiterOptions) {\n super(opts);\n this._storage = new MemoryStorage();\n }\n\n consume(key: string, pointsToConsume: number = 1, options: LimiterConsumeOptions = {}): Promise<IRateLimiterRes> {\n return new Promise((resolve, reject) => {\n const rlKey = this._getKey(key);\n const secDuration = this._getKeySecDuration(options);\n let res = this._storage.incrby(rlKey, pointsToConsume, secDuration);\n res.remainingPoints = Math.max(this._points - res.consumedPoints, 0);\n\n if (res.consumedPoints > this._points) {\n // Only block the first time the key spills past `points`. The\n // `consumedPoints <= points + pointsToConsume` guard prevents\n // re-blocking on every subsequent call inside the block window.\n if (this._blockDuration > 0 && res.consumedPoints <= this._points + pointsToConsume) {\n res = this._storage.set(rlKey, res.consumedPoints, this._blockDuration);\n }\n reject(res);\n return;\n }\n\n if (this._execEvenly && res.msBeforeNext > 0 && !res.isFirstInDuration) {\n let delay = Math.ceil(res.msBeforeNext / (res.remainingPoints + 2));\n if (delay < this._execEvenlyMinDelayMs) {\n delay = res.consumedPoints * this._execEvenlyMinDelayMs;\n }\n res.msBeforeNext = Math.max(res.msBeforeNext - delay, 0);\n setTimeout(resolve, delay, res);\n return;\n }\n\n resolve(res);\n });\n }\n\n penalty(key: string, points: number = 1, options: LimiterConsumeOptions = {}): Promise<IRateLimiterRes> {\n const rlKey = this._getKey(key);\n const secDuration = this._getKeySecDuration(options);\n const res = this._storage.incrby(rlKey, points, secDuration);\n res.remainingPoints = Math.max(this._points - res.consumedPoints, 0);\n return Promise.resolve(res);\n }\n\n reward(key: string, points: number = 1, options: LimiterConsumeOptions = {}): Promise<IRateLimiterRes> {\n const rlKey = this._getKey(key);\n const secDuration = this._getKeySecDuration(options);\n const res = this._storage.incrby(rlKey, -points, secDuration);\n res.remainingPoints = Math.max(this._points - res.consumedPoints, 0);\n return Promise.resolve(res);\n }\n\n block(key: string, secDuration: number): Promise<IRateLimiterRes> {\n const msDuration = secDuration * 1000;\n const initPoints = this._points + 1;\n this._storage.set(this._getKey(key), initPoints, secDuration);\n return Promise.resolve(new LimiterResult(0, msDuration === 0 ? -1 : msDuration, initPoints, false));\n }\n\n get(key: string): Promise<IRateLimiterRes | null> {\n const res = this._storage.get(this._getKey(key));\n if (res !== null) {\n res.remainingPoints = Math.max(this._points - res.consumedPoints, 0);\n }\n return Promise.resolve(res);\n }\n\n delete(key: string): Promise<boolean> {\n return Promise.resolve(this._storage.delete(this._getKey(key)));\n }\n\n /** Test/teardown helper. Drops every key and clears timers. */\n dispose(): void {\n this._storage.clear();\n }\n}\n","/**\n * @module @arcis/node/middleware/brute-force\n *\n * Brute-force protection middleware built on the bursty limiter\n * primitive. Designed for login + password-reset endpoints where the\n * defense isn't just \"X requests per minute\" but \"if this IP keeps\n * trying after the rate-limit window resets, block it for longer\".\n *\n * Two-tier semantics:\n * - Steady-state: `fastPoints` consumes per `fastDuration` seconds.\n * Once exhausted, normal traffic gets a 429 until the window\n * resets.\n * - Brute-force: `slowPoints` failed attempts over `slowDuration`\n * seconds trips a `blockDuration` semi-permanent block.\n *\n * The middleware only consumes on `next()` by default, meaning every\n * request counts, even successful ones. Pass `{ consumeOn: 'failure' }`\n * plus a custom `failure` predicate to count only failed responses.\n * The handler also exposes `req.arcisBruteForce.reward(key)` / `.delete(key)`\n * to let the application reset counters on successful login.\n */\n\nimport type { Request, Response, NextFunction, RequestHandler } from 'express';\nimport { MemoryLimiter, LimiterResult } from '../_third_party/rate-limit';\nimport type { IRateLimiterRes } from '../_third_party/rate-limit';\n\nexport interface BruteForceOptions {\n /** Points allowed in the fast window. */\n fastPoints?: number;\n /** Fast window length in seconds. */\n fastDuration?: number;\n /** Points allowed in the slow window. */\n slowPoints?: number;\n /** Slow window length in seconds. */\n slowDuration?: number;\n /** Seconds to semi-permanently block a key after slow-window exhaustion. */\n blockDuration?: number;\n /** Custom key resolver. Defaults to client IP. */\n keyGenerator?: (req: Request) => string;\n /** HTTP status to return when blocked. */\n statusCode?: number;\n /** Response message when blocked. */\n message?: string;\n /** Skip predicate. Return true to bypass the limiter for this request. */\n skip?: (req: Request) => boolean;\n}\n\nexport interface BruteForceController {\n /** Reset the failure counter for a key (call after successful auth). */\n reward(key: string, points?: number): Promise<IRateLimiterRes>;\n /** Drop the key entirely. */\n delete(key: string): Promise<boolean>;\n /** Inspect the current counter without consuming. */\n get(key: string): Promise<IRateLimiterRes | null>;\n /** Manually trip the block (e.g. after N suspicious logins). */\n block(key: string, secDuration: number): Promise<IRateLimiterRes>;\n}\n\ndeclare global {\n namespace Express {\n interface Request {\n arcisBruteForce?: BruteForceController;\n }\n }\n}\n\nfunction defaultKeyGenerator(req: Request): string {\n const xff = req.headers['x-forwarded-for'];\n if (typeof xff === 'string' && xff.length > 0) {\n const first = xff.split(',')[0]?.trim();\n if (first) return first;\n }\n if (typeof req.ip === 'string' && req.ip.length > 0) return req.ip;\n const remote = req.socket?.remoteAddress;\n return typeof remote === 'string' && remote.length > 0 ? remote : 'unknown';\n}\n\n/**\n * Build a brute-force middleware backed by a bursty limiter. The\n * returned function is an Express RequestHandler with a `controller`\n * property exposing reward/delete/get/block for the application layer.\n */\nexport function bruteForceProtection(options: BruteForceOptions = {}): RequestHandler & {\n controller: BruteForceController;\n} {\n const fastPoints = options.fastPoints ?? 5;\n const fastDuration = options.fastDuration ?? 60;\n const slowPoints = options.slowPoints ?? 20;\n const slowDuration = options.slowDuration ?? 900; // 15 min\n const blockDuration = options.blockDuration ?? 900; // 15 min\n const keyGenerator = options.keyGenerator ?? defaultKeyGenerator;\n const statusCode = options.statusCode ?? 429;\n const message = options.message ?? 'Too many login attempts. Please try again later.';\n const skip = options.skip;\n\n // Fast window: normal short-window rate limit. Resets every\n // `fastDuration` seconds; no semi-permanent block.\n const fast = new MemoryLimiter({\n points: fastPoints,\n duration: fastDuration,\n keyPrefix: 'arcis:bf:fast',\n });\n\n // Slow window: brute-force trip wire with block. Block writes a\n // record with TTL = blockDuration that swallows every subsequent\n // request until the timer expires.\n const slow = new MemoryLimiter({\n points: slowPoints,\n duration: slowDuration,\n blockDuration,\n keyPrefix: 'arcis:bf:slow',\n });\n\n const controller: BruteForceController = {\n reward: (key, points = 1) => slow.reward(key, points),\n delete: async (key) => {\n const a = await fast.delete(key);\n const b = await slow.delete(key);\n return a || b;\n },\n get: (key) => slow.get(key),\n block: (key, secDuration) => slow.block(key, secDuration),\n };\n\n const handler: RequestHandler = async (req: Request, res: Response, next: NextFunction) => {\n try {\n if (skip?.(req)) return next();\n\n const key = keyGenerator(req);\n req.arcisBruteForce = controller;\n\n // AND semantics: both limiters must allow. Slow goes first so\n // that the block-state check happens before the cheap fast check.\n const slowRes = await slow.consume(key, 1);\n const fastRes = await fast.consume(key, 1);\n\n res.setHeader('X-RateLimit-Limit', String(slowPoints));\n res.setHeader(\n 'X-RateLimit-Remaining',\n String(Math.min(fastRes.remainingPoints, slowRes.remainingPoints)),\n );\n res.setHeader(\n 'X-RateLimit-Reset',\n String(Math.ceil(Math.max(slowRes.msBeforeNext, fastRes.msBeforeNext) / 1000)),\n );\n next();\n } catch (rejection) {\n if (rejection instanceof LimiterResult || isLimiterResultShape(rejection)) {\n const retryAfter = Math.ceil((rejection as IRateLimiterRes).msBeforeNext / 1000);\n res.setHeader('X-RateLimit-Limit', String(slowPoints));\n res.setHeader('X-RateLimit-Remaining', '0');\n res.setHeader('X-RateLimit-Reset', String(retryAfter));\n res.setHeader('Retry-After', String(retryAfter));\n res.status(statusCode).json({ error: message, retryAfter });\n return;\n }\n // Unknown rejection. Fail open and log.\n // eslint-disable-next-line no-console\n console.error('[arcis] brute-force middleware error:', rejection);\n next();\n }\n };\n\n return Object.assign(handler, { controller });\n}\n\nfunction isLimiterResultShape(x: unknown): x is IRateLimiterRes {\n return (\n typeof x === 'object' &&\n x !== null &&\n typeof (x as IRateLimiterRes).consumedPoints === 'number' &&\n typeof (x as IRateLimiterRes).msBeforeNext === 'number'\n );\n}\n","/**\n * @module @arcis/node/middleware/protect\n *\n * Composite protection helpers (issue #52). Pre-configured middleware\n * stacks for the three endpoint shapes that show up in every app:\n * login, signup, generic API. Each helper composes EXISTING middleware\n * with sensible defaults; no new security logic lives here.\n *\n * Express supports passing an array of middleware to a route — the\n * elements get unrolled in declaration order — so each helper returns\n * a `RequestHandler[]` that drops directly into `app.post(...)`:\n *\n * ```ts\n * import { protectLogin, protectSignup, protectApi } from '@arcis/node';\n *\n * app.post('/login', protectLogin(), loginHandler);\n * app.post('/signup', protectSignup(), signupHandler);\n * app.use ('/api', protectApi());\n * ```\n *\n * Defaults (issue #52 spec):\n *\n * | Helper | rate-limit | bot | csrf | cors | sanitize | email |\n * |---------------|------------|-----|------|------|----------|-------|\n * | protectLogin | 5/min | yes | yes | - | yes | - |\n * | protectSignup | 3/min | yes | - | - | yes | yes |\n * | protectApi | 100/min | - | - | yes | yes | - |\n *\n * Each option is overridable. Pass `{ rateLimit: false }` to disable a\n * specific layer; pass an options object to forward to the underlying\n * factory.\n */\n\nimport type { RequestHandler } from 'express';\nimport { createRateLimiter } from './rate-limit';\nimport { botProtection, type BotProtectionOptions } from './bot-detection';\nimport { csrfProtection, type CsrfOptions } from './csrf';\nimport { safeCors } from './cors';\nimport type { CorsOptions } from './cors';\nimport { signupProtection, type SignupProtectionOptions } from './signup-protection';\nimport { bruteForceProtection, type BruteForceOptions } from './brute-force';\nimport { createSanitizer } from '../sanitizers';\nimport type { RateLimitOptions, SanitizeOptions } from '../core/types';\nimport { CorrelationWindow } from './correlation';\n\n/**\n * Per-protect-helper correlation-window wiring (improvements.md §1.4).\n *\n * Pass an instance of `CorrelationWindow` plus the vector tag this\n * route represents (\"login\" / \"signup\" / \"api\"). The middleware\n * records every request in the window and refuses the request when\n * the window flags the IP as a scanner / credential stuffer / race\n * probe. Detection-only otherwise.\n *\n * Pull-out fields:\n * - `usernameField`: body key whose value is the distinct-value\n * tracked for credential-stuffing detection. Defaults to\n * `'username'`.\n * - `route`: route label recorded in the window (so cross-route\n * aggregation is meaningful). Defaults to the request path.\n * - `statusCode` / `message`: response shape on a correlation block.\n */\nexport interface CorrelationOptions {\n window: CorrelationWindow;\n vector?: string;\n usernameField?: string;\n route?: string;\n statusCode?: number;\n message?: string;\n}\n\nfunction getClientIp(req: any): string {\n // Best-effort. Matches the helper Arcis uses elsewhere.\n const xff =\n req?.headers?.['x-forwarded-for'] ?? req?.headers?.['X-Forwarded-For'];\n if (typeof xff === 'string' && xff.length > 0) {\n const first = xff.split(',')[0]?.trim();\n if (first) return first;\n }\n if (typeof req?.ip === 'string') return req.ip;\n const remote = req?.socket?.remoteAddress;\n return typeof remote === 'string' ? remote : '';\n}\n\nfunction correlationMiddleware(opts: CorrelationOptions): RequestHandler {\n const vector = opts.vector ?? 'request';\n const usernameField = opts.usernameField ?? 'username';\n const statusCode = opts.statusCode ?? 429;\n const message = opts.message ?? 'Suspicious request pattern detected.';\n return function (req, res, next) {\n const ip = getClientIp(req);\n if (!ip) return next();\n const route = opts.route ?? (req.path || req.url || '/');\n const username = req?.body?.[usernameField];\n const distinctValue =\n typeof username === 'string' && username.length > 0 ? username : undefined;\n const detections = opts.window.record(\n ip,\n vector,\n route,\n req.method || 'GET',\n distinctValue,\n );\n if (\n detections.scanner ||\n detections.credentialStuffing ||\n detections.raceWindow\n ) {\n res.status(statusCode).json({\n error: message,\n scanner: detections.scanner,\n credential_stuffing: detections.credentialStuffing,\n race_window: detections.raceWindow,\n });\n return;\n }\n next();\n };\n}\n\n/**\n * Per-layer override knob: pass `false` to disable, an options object\n * to merge into the layer's defaults, or omit to accept the helper's\n * baked-in default.\n */\ntype LayerOverride<T> = false | T | undefined;\n\nexport interface ProtectLoginOptions {\n rateLimit?: LayerOverride<RateLimitOptions>;\n bot?: LayerOverride<BotProtectionOptions>;\n csrf?: LayerOverride<CsrfOptions>;\n sanitize?: LayerOverride<SanitizeOptions>;\n /** Optional correlation-window wiring (improvements.md §1.4). */\n correlation?: CorrelationOptions;\n /**\n * Optional brute-force layer. When enabled, layers a bursty limiter\n * on top of the fast rate-limit window: N attempts in `slowDuration`\n * seconds trips a `blockDuration`-second semi-permanent block.\n * Defaults to disabled (preserves existing behavior); pass `true`\n * for safe defaults or an options object to customize.\n */\n bruteForce?: boolean | BruteForceOptions;\n}\n\nexport interface ProtectSignupOptions {\n rateLimit?: LayerOverride<RateLimitOptions>;\n bot?: LayerOverride<BotProtectionOptions>;\n sanitize?: LayerOverride<SanitizeOptions>;\n /** signupProtection options (email-style validation, disposable-mail block, etc.). */\n signup?: LayerOverride<SignupProtectionOptions>;\n /** Optional correlation-window wiring (improvements.md §1.4). */\n correlation?: CorrelationOptions;\n}\n\nexport interface ProtectApiOptions {\n rateLimit?: LayerOverride<RateLimitOptions>;\n /** CORS is required to take an Origin/Methods config — no default origin. */\n cors?: LayerOverride<CorsOptions>;\n sanitize?: LayerOverride<SanitizeOptions>;\n /** Optional correlation-window wiring (improvements.md §1.4). */\n correlation?: CorrelationOptions;\n}\n\n/**\n * Resolve a layer override against a default. Returns `null` when the\n * caller disabled the layer with `false`; otherwise the merged options\n * object the underlying factory expects.\n */\nfunction resolve<T extends object>(override: LayerOverride<T>, defaults: T): T | null {\n if (override === false) return null;\n if (override === undefined) return defaults;\n return { ...defaults, ...override };\n}\n\n/**\n * Login endpoints get the strictest defaults: 5 req/min/IP, deny\n * AUTOMATED bots, CSRF token check, and input sanitization. Designed\n * for `app.post('/login', protectLogin(), handler)`.\n */\nexport function protectLogin(options: ProtectLoginOptions = {}): RequestHandler[] {\n const middlewares: RequestHandler[] = [];\n\n const rl = resolve<RateLimitOptions>(options.rateLimit, { max: 5, windowMs: 60_000 });\n if (rl) middlewares.push(createRateLimiter(rl));\n\n if (options.bruteForce) {\n const bfOpts =\n options.bruteForce === true ? {} : options.bruteForce;\n middlewares.push(bruteForceProtection(bfOpts));\n }\n\n const bot = resolve<BotProtectionOptions>(options.bot, {\n deny: ['AUTOMATED'],\n statusCode: 403,\n message: 'Access denied.',\n });\n if (bot) middlewares.push(botProtection(bot));\n\n const csrf = resolve<CsrfOptions>(options.csrf, {});\n if (csrf) middlewares.push(csrfProtection(csrf));\n\n const sanitize = resolve<SanitizeOptions>(options.sanitize, {});\n if (sanitize) middlewares.push(createSanitizer(sanitize));\n\n if (options.correlation) {\n middlewares.push(\n correlationMiddleware({ vector: 'login', ...options.correlation }),\n );\n }\n\n return middlewares;\n}\n\n/**\n * Signup endpoints: 3 req/min/IP, deny AUTOMATED bots, sanitize input,\n * and run signup-specific validation (email shape + disposable-domain\n * check via `signupProtection`). No CSRF here because most signup\n * forms are first-touch, no prior session to anchor a token to.\n */\nexport function protectSignup(options: ProtectSignupOptions = {}): RequestHandler[] {\n const middlewares: RequestHandler[] = [];\n\n const rl = resolve<RateLimitOptions>(options.rateLimit, { max: 3, windowMs: 60_000 });\n if (rl) middlewares.push(createRateLimiter(rl));\n\n const bot = resolve<BotProtectionOptions>(options.bot, {\n deny: ['AUTOMATED'],\n statusCode: 403,\n message: 'Access denied.',\n });\n if (bot) middlewares.push(botProtection(bot));\n\n const sanitize = resolve<SanitizeOptions>(options.sanitize, {});\n if (sanitize) middlewares.push(createSanitizer(sanitize));\n\n const signup = resolve<SignupProtectionOptions>(options.signup, {});\n if (signup) middlewares.push(signupProtection(signup));\n\n if (options.correlation) {\n middlewares.push(\n correlationMiddleware({ vector: 'signup', ...options.correlation }),\n );\n }\n\n return middlewares;\n}\n\n/**\n * Generic API endpoints: 100 req/min/IP, CORS, input sanitization. No\n * bot detection by default because legitimate API consumers (curl,\n * fetch, server-to-server) are often classified AUTOMATED — opt-in\n * by passing a `bot` override... wait, protectApi doesn't expose bot.\n * That's deliberate per the issue spec table. Users who want bot\n * detection on API endpoints compose `botProtection()` directly.\n *\n * CORS is the one layer with no usable default — every app's allow\n * list is different. Pass `cors: { origin: '...' }` or `cors: false`\n * to skip it explicitly.\n */\nexport function protectApi(options: ProtectApiOptions = {}): RequestHandler[] {\n const middlewares: RequestHandler[] = [];\n\n const rl = resolve<RateLimitOptions>(options.rateLimit, { max: 100, windowMs: 60_000 });\n if (rl) middlewares.push(createRateLimiter(rl));\n\n // CORS: no useful default, but if the user didn't pass anything we\n // default to a permissive CorsOrigin: true (reflect request Origin).\n // Documented as a starter — production apps should narrow this.\n const cors = resolve<CorsOptions>(options.cors, { origin: true });\n if (cors) middlewares.push(safeCors(cors));\n\n const sanitize = resolve<SanitizeOptions>(options.sanitize, {});\n if (sanitize) middlewares.push(createSanitizer(sanitize));\n\n if (options.correlation) {\n middlewares.push(\n correlationMiddleware({ vector: 'api', ...options.correlation }),\n );\n }\n\n return middlewares;\n}\n","/**\n * @module @arcis/node/middleware/graphql\n *\n * GraphQL request guard (sdk-vectors.md tier 1 #21). Wraps the\n * `inspectGraphqlQuery` sanitizer in an Express middleware that\n * pulls the query string from the standard places GraphQL servers\n * expect it (`req.body.query` for POST, `req.query.query` for GET)\n * and short-circuits with 400 + a structured error when the query\n * violates any configured limit.\n *\n * ```ts\n * import { graphqlGuard } from '@arcis/node';\n *\n * app.use('/graphql', graphqlGuard({\n * maxDepth: 10,\n * maxLength: 10000,\n * blockIntrospection: process.env.NODE_ENV === 'production',\n * }));\n * ```\n *\n * Order with the rest of Arcis: install AFTER body-parsing\n * (`express.json()`) so `req.body.query` is populated, BEFORE the\n * GraphQL handler so the deny path short-circuits resolver work.\n */\n\nimport type { Request, RequestHandler, Response, NextFunction } from 'express';\nimport {\n inspectGraphqlQuery,\n type GraphqlGuardOptions,\n type GraphqlViolation,\n} from '../sanitizers/graphql';\n\nexport interface GraphqlGuardMiddlewareOptions extends GraphqlGuardOptions {\n /** HTTP status to return on violation. Default: 400 (matches GraphQL spec for parse errors). */\n statusCode?: number;\n /** Custom message template. Default: built per-reason. */\n message?: string | ((reason: GraphqlViolation) => string);\n}\n\nconst DEFAULT_MESSAGES: Record<GraphqlViolation, string> = {\n depth: 'Query exceeds maximum nesting depth',\n length: 'Query exceeds maximum length',\n introspection: 'Introspection queries are disabled',\n aliases: 'Query exceeds maximum alias count (alias-bomb protection)',\n fragment_cycle: 'Query contains a cyclic fragment definition',\n};\n\n/**\n * Pull the GraphQL query string from a request. Convention: POST\n * bodies carry `{ query, variables, operationName }`; GET requests\n * pass `?query=...` for persisted-query-style fetches. We check both\n * so the guard works regardless of transport.\n */\nfunction extractQuery(req: Request): string | undefined {\n // Prefer body.query (POST is the dominant transport for GraphQL).\n const bodyQuery =\n typeof req.body === 'object' && req.body !== null\n ? (req.body as Record<string, unknown>).query\n : undefined;\n if (typeof bodyQuery === 'string') return bodyQuery;\n\n // Fall back to req.query.query (GET) — express stores query string\n // values as strings or arrays-of-strings.\n const qsQuery = req.query?.query;\n if (typeof qsQuery === 'string') return qsQuery;\n\n return undefined;\n}\n\nexport function graphqlGuard(\n options: GraphqlGuardMiddlewareOptions = {},\n): RequestHandler {\n const statusCode = options.statusCode ?? 400;\n const messageOption = options.message;\n\n return (req: Request, res: Response, next: NextFunction) => {\n const query = extractQuery(req);\n if (!query) {\n // No GraphQL query in the expected slots — could be a\n // mounted-elsewhere route or a non-GraphQL request slipping\n // through the same path. Pass through; the GraphQL handler\n // below will decide whether to error.\n next();\n return;\n }\n\n const result = inspectGraphqlQuery(query, options);\n if (!result.blocked) {\n next();\n return;\n }\n\n const reason = result.reason as GraphqlViolation;\n const message =\n typeof messageOption === 'function'\n ? messageOption(reason)\n : (messageOption ?? DEFAULT_MESSAGES[reason]);\n\n res.status(statusCode).json({\n error: message,\n reason,\n observed: {\n depth: result.depth,\n length: result.length,\n },\n });\n };\n}\n\nexport default graphqlGuard;\n","/**\n * @module @arcis/node/middleware/correlation\n *\n * V1.6 / improvements.md §1.3 — Stateful per-IP correlation window.\n *\n * Today's middleware is stateless: each request is judged on its own.\n * That misses three classes of attack:\n *\n * - Scanner sweep. One IP firing payloads from every category in\n * quick succession is a scanner, not a real user.\n * - Credential stuffing. Same login route, same IP, dozens of\n * distinct usernames in 60 seconds.\n * - Race-condition probe. POST /a immediately followed by GET /b\n * from the same IP, within 200 ms. Either is fine alone.\n *\n * This module records a small rolling event log per IP (capped) and\n * exposes detection helpers. Detection is *additive* — Pattern 4\n * applies (fail-open). If something goes wrong here, the existing\n * rate-limit + per-vector defenses still run.\n *\n * Mirrors `arcis-python/arcis/middleware/correlation.py`. Both SDKs\n * must accept the same base corpus per Pattern 7.\n */\n\nexport interface CorrelationEvent {\n /** Wall-clock seconds (Date.now() / 1000) or test-injected value. */\n timestamp: number;\n /** Detector or operation that produced this event. */\n vector: string;\n route: string;\n method: string;\n /** Username / email / token bucket if relevant; otherwise undefined. */\n distinctValue?: string;\n}\n\nexport interface CorrelationDetections {\n scanner: boolean;\n credentialStuffing: boolean;\n raceWindow: boolean;\n distinctVectors: number;\n distinctValues: number;\n requestsInWindow: number;\n}\n\nexport interface CorrelationWindowOptions {\n windowSeconds?: number;\n maxIps?: number;\n maxEventsPerIp?: number;\n scannerDistinctVectors?: number;\n scannerMinRequests?: number;\n credentialStuffingDistinctValues?: number;\n raceWindowMs?: number;\n /** Pre-registered race-pair routes; ad-hoc detect_race_window also works. */\n racePairs?: Array<[string, string]>;\n}\n\nconst EMPTY_DETECTIONS: CorrelationDetections = Object.freeze({\n scanner: false,\n credentialStuffing: false,\n raceWindow: false,\n distinctVectors: 0,\n distinctValues: 0,\n requestsInWindow: 0,\n});\n\ninterface IpBucket {\n events: CorrelationEvent[];\n}\n\nfunction normalizePair(a: string, b: string): string {\n return a < b ? `${a}\u0001${b}` : `${b}\u0001${a}`;\n}\n\n/**\n * Rolling per-IP correlation window. Mirrors the Python\n * `CorrelationWindow` class.\n *\n * All detection helpers are read-only; only `record` mutates state.\n */\nexport class CorrelationWindow {\n private readonly windowSeconds: number;\n private readonly maxIps: number;\n private readonly maxEventsPerIp: number;\n private readonly scannerDistinctVectors: number;\n private readonly scannerMinRequests: number;\n private readonly csDistinctValues: number;\n private readonly raceWindowSeconds: number;\n private readonly racePairKeys: Set<string>;\n private readonly racePairTuples: Array<[string, string]>;\n\n // Map iteration order in JS is insertion order, so re-inserting on\n // access gives us LRU behaviour without a separate linked list.\n private readonly buckets: Map<string, IpBucket> = new Map();\n\n constructor(options: CorrelationWindowOptions = {}) {\n const {\n windowSeconds = 60,\n maxIps = 10_000,\n maxEventsPerIp = 200,\n scannerDistinctVectors = 3,\n scannerMinRequests = 20,\n credentialStuffingDistinctValues = 10,\n raceWindowMs = 200,\n racePairs,\n } = options;\n\n if (windowSeconds <= 0) throw new Error('windowSeconds must be > 0');\n if (maxIps < 1) throw new Error('maxIps must be >= 1');\n if (maxEventsPerIp < 1) throw new Error('maxEventsPerIp must be >= 1');\n\n this.windowSeconds = windowSeconds;\n this.maxIps = maxIps;\n this.maxEventsPerIp = maxEventsPerIp;\n this.scannerDistinctVectors = scannerDistinctVectors;\n this.scannerMinRequests = scannerMinRequests;\n this.csDistinctValues = credentialStuffingDistinctValues;\n this.raceWindowSeconds = raceWindowMs / 1000;\n this.racePairKeys = new Set();\n this.racePairTuples = [];\n if (racePairs) {\n for (const [a, b] of racePairs) {\n const key = normalizePair(a, b);\n if (!this.racePairKeys.has(key)) {\n this.racePairKeys.add(key);\n const sorted: [string, string] = a < b ? [a, b] : [b, a];\n this.racePairTuples.push(sorted);\n }\n }\n }\n }\n\n record(\n ip: string,\n vector: string,\n route: string,\n method = 'GET',\n distinctValue?: string,\n now?: number,\n ): CorrelationDetections {\n if (!ip) return EMPTY_DETECTIONS;\n const ts = now ?? Date.now() / 1000;\n const event: CorrelationEvent = {\n timestamp: ts,\n vector,\n route,\n method,\n distinctValue,\n };\n\n let bucket = this.buckets.get(ip);\n if (bucket === undefined) {\n bucket = { events: [] };\n this.buckets.set(ip, bucket);\n while (this.buckets.size > this.maxIps) {\n const oldest = this.buckets.keys().next().value as string | undefined;\n if (oldest === undefined) break;\n this.buckets.delete(oldest);\n }\n } else {\n // LRU touch: re-insert at the end.\n this.buckets.delete(ip);\n this.buckets.set(ip, bucket);\n }\n\n bucket.events.push(event);\n this.evictStale(bucket, ts);\n return this.evaluate(bucket, route);\n }\n\n detectScanner(ip: string, now?: number): boolean {\n const bucket = this.buckets.get(ip);\n if (bucket === undefined) return false;\n this.evictStale(bucket, now ?? Date.now() / 1000);\n return this.isScanner(bucket);\n }\n\n detectCredentialStuffing(ip: string, route: string, now?: number): boolean {\n const bucket = this.buckets.get(ip);\n if (bucket === undefined) return false;\n this.evictStale(bucket, now ?? Date.now() / 1000);\n return this.isCredentialStuffing(bucket, route);\n }\n\n detectRaceWindow(\n ip: string,\n routePair: [string, string],\n now?: number,\n ): boolean {\n const bucket = this.buckets.get(ip);\n if (bucket === undefined) return false;\n this.evictStale(bucket, now ?? Date.now() / 1000);\n const sorted: [string, string] =\n routePair[0] < routePair[1] ? routePair : [routePair[1], routePair[0]];\n return this.racePairInBucket(bucket, sorted);\n }\n\n reset(ip?: string): void {\n if (ip === undefined) {\n this.buckets.clear();\n } else {\n this.buckets.delete(ip);\n }\n }\n\n stats(): { trackedIps: number; eventsInWindow: number } {\n let events = 0;\n for (const b of this.buckets.values()) events += b.events.length;\n return { trackedIps: this.buckets.size, eventsInWindow: events };\n }\n\n // -------------------------------------------------------- internals\n\n private evictStale(bucket: IpBucket, now: number): void {\n const cutoff = now - this.windowSeconds;\n let drop = 0;\n while (drop < bucket.events.length && bucket.events[drop].timestamp < cutoff) {\n drop++;\n }\n if (drop > 0) bucket.events.splice(0, drop);\n if (bucket.events.length > this.maxEventsPerIp) {\n bucket.events.splice(0, bucket.events.length - this.maxEventsPerIp);\n }\n }\n\n private evaluate(bucket: IpBucket, route: string): CorrelationDetections {\n const vectors = new Set<string>();\n const values = new Set<string>();\n for (const e of bucket.events) {\n vectors.add(e.vector);\n if (e.route === route && e.distinctValue !== undefined) {\n values.add(e.distinctValue);\n }\n }\n return {\n scanner: this.isScanner(bucket),\n credentialStuffing: this.isCredentialStuffing(bucket, route),\n raceWindow: this.isRaceAny(bucket),\n distinctVectors: vectors.size,\n distinctValues: values.size,\n requestsInWindow: bucket.events.length,\n };\n }\n\n private isScanner(bucket: IpBucket): boolean {\n if (bucket.events.length < this.scannerMinRequests) return false;\n const vectors = new Set<string>();\n for (const e of bucket.events) vectors.add(e.vector);\n return vectors.size >= this.scannerDistinctVectors;\n }\n\n private isCredentialStuffing(bucket: IpBucket, route: string): boolean {\n const values = new Set<string>();\n for (const e of bucket.events) {\n if (e.route === route && e.distinctValue !== undefined) {\n values.add(e.distinctValue);\n }\n }\n return values.size >= this.csDistinctValues;\n }\n\n private racePairInBucket(bucket: IpBucket, sorted: [string, string]): boolean {\n const [a, b] = sorted;\n const aTs: number[] = [];\n const bTs: number[] = [];\n for (const e of bucket.events) {\n if (e.route === a) aTs.push(e.timestamp);\n else if (e.route === b) bTs.push(e.timestamp);\n }\n if (aTs.length === 0 || bTs.length === 0) return false;\n let ai = 0;\n let bi = 0;\n while (ai < aTs.length && bi < bTs.length) {\n const diff = aTs[ai] - bTs[bi];\n if (Math.abs(diff) <= this.raceWindowSeconds) return true;\n if (diff < 0) ai++;\n else bi++;\n }\n return false;\n }\n\n private isRaceAny(bucket: IpBucket): boolean {\n for (const pair of this.racePairTuples) {\n if (this.racePairInBucket(bucket, pair)) return true;\n }\n return false;\n }\n}\n","/**\n * @module @arcis/node/sanitizers/prompt-injection\n *\n * Pattern-based prompt-injection detection and sanitization for LLM-handler\n * endpoints. Catches the common signature classes: system-prompt overrides,\n * known jailbreak frameworks (DAN/STAN/DUDE), structural markers (fake\n * XML/Markdown delimiters that try to forge system messages), and known\n * encoding tricks. Does NOT defend against arbitrary novel attacks: that\n * needs the model itself to evaluate intent.\n *\n * Built as a signature library (Option A in `documents/plans/sdk-vectors.md`\n * vector #28). MIT, fully transparent, no closed Wasm blobs.\n *\n * Common attack categories caught:\n * - Direct override: \"ignore previous instructions\", \"disregard the above\"\n * - Jailbreak frameworks: DAN, STAN, DUDE, \"developer mode\", \"jailbroken\"\n * - Persona hijack: \"you are now X\", \"pretend to be\", \"roleplay as\"\n * - System prompt extraction: \"show me your prompt\", \"what are your rules\"\n * - Indirect injection: fake `<system>` tags, \"BEGIN NEW INSTRUCTIONS\"\n * - Encoding tricks: Base64-prefixed payloads, ROT13 markers\n */\n\n// ─── Severity model ────────────────────────────────────────────────────────\n\nexport type PromptInjectionSeverity = 'low' | 'medium' | 'high';\n\nexport interface PromptInjectionMatch {\n /** Stable identifier for the matched signature */\n rule: string;\n /** Severity of this signature */\n severity: PromptInjectionSeverity;\n /** Short human-readable description */\n description: string;\n /** First chars of the matched substring (for telemetry / logs) */\n match: string;\n}\n\nexport interface DetectPromptInjectionResult {\n /** Did any signature match? */\n detected: boolean;\n /** All signatures that matched, in declaration order */\n matches: PromptInjectionMatch[];\n /** Highest severity across all matches; 'none' if nothing matched */\n severity: PromptInjectionSeverity | 'none';\n}\n\n// ─── Signatures ────────────────────────────────────────────────────────────\n// Each signature: a regex + severity + a stable rule id + a description.\n// Patterns target the common public attack corpora; specifically the OWASP\n// LLM01 prompt-injection examples plus the well-known jailbreak frameworks\n// shipped publicly between 2023–2025.\n\ninterface PromptInjectionSignature {\n rule: string;\n pattern: RegExp;\n severity: PromptInjectionSeverity;\n description: string;\n}\n\nconst SIGNATURES: PromptInjectionSignature[] = [\n // --- HIGH severity: clear override / jailbreak attempts ---\n {\n rule: 'ignore-previous-instructions',\n // Two clauses:\n // 1. ignore|disregard|... + adjectives? + a target object word (like\n // \"instructions\", \"rules\"). Catches \"ignore your safety rules\".\n // 2. ignore|disregard|... + (the|all|any) + (previous|above|prior|...)\n // with no trailing noun. Catches \"disregard the above\".\n // Verb set widened in v1.7 to include skip/neglect/overlook/omit (the\n // combinatorial jailbreak corpus uses these interchangeably with\n // ignore/disregard/forget).\n pattern: /\\b(?:ignore|disregard|forget|override|bypass|skip|neglect|overlook|omit)\\s+(?:(?:all|your|the|any|previous|prior|above|original|initial|system|safety|preceding|earlier|foregoing)\\s+)*(?:instructions?|rules?|directions?|guidelines?|prompts?|policies|directives?|commands?|restrictions?|filters?|safety|content|context|conversation|directive|messages?|communication|requests?|inputs?)\\b|\\b(?:ignore|disregard|forget|override|bypass|skip|neglect|overlook|omit)\\s+(?:all\\s+|the\\s+|any\\s+)?(?:previous|prior|above|preceding|earlier|original|initial|foregoing)\\b/i,\n severity: 'high',\n description: 'Direct instruction override attempt',\n },\n {\n rule: 'instruction-bypass-phrases',\n // Multi-word verbs that don't fit the single-token alternation in\n // `ignore-previous-instructions`. Catches \"pay no attention to your\n // previous instructions\", \"do not follow the above rules\", etc.\n pattern: /\\b(?:pay\\s+no\\s+attention\\s+to|do\\s+not\\s+(?:follow|obey|adhere\\s+to|comply\\s+with))\\s+(?:(?:all|your|the|any|previous|prior|above|original|initial|system|safety|preceding|earlier|foregoing)\\s+)*(?:instructions?|rules?|directions?|guidelines?|prompts?|policies|directives?|commands?|restrictions?|filters?|safety|content|context|directive|messages?)\\b/i,\n severity: 'high',\n description: 'Multi-word instruction-bypass phrase (pay no attention to / do not follow)',\n },\n {\n rule: 'jailbreak-dan',\n pattern: /\\b(?:DAN|STAN|DUDE|DAVE|JEDI|EvilBot|AIM|BetterDAN|AntiGPT|AntiClaude)\\b(?:[\\s.,!?]|mode|prompt|jailbreak|persona)/i,\n severity: 'high',\n description: 'Known jailbreak framework name (DAN/STAN/DUDE/etc.)',\n },\n {\n rule: 'do-anything-now',\n pattern: /\\bdo\\s+anything\\s+now\\b/i,\n severity: 'high',\n description: 'DAN (\"Do Anything Now\") jailbreak variant',\n },\n {\n rule: 'developer-mode',\n pattern: /\\b(?:developer|debug|admin|sudo|root|god|maintenance|test)\\s+mode\\b(?:\\s+(?:on|enabled|activated|engaged))?/i,\n severity: 'high',\n description: 'Fake \"developer mode\" / \"debug mode\" enablement',\n },\n {\n rule: 'jailbroken-claim',\n pattern: /\\b(?:you\\s+are\\s+(?:now\\s+)?)?(?:jailbroken|unrestricted|uncensored|unleashed|liberated|free\\s+from\\s+(?:rules|guidelines|restrictions))\\b/i,\n severity: 'high',\n description: 'Claim that the model is jailbroken / unrestricted',\n },\n {\n rule: 'role-hijack',\n pattern: /\\b(?:you\\s+are\\s+(?:now\\s+)?(?:a\\s+)?(?:different|new|another|evil|malicious|unrestricted|unfiltered)|act\\s+as\\s+(?:a\\s+)?(?:different|new|another|evil|malicious|unrestricted|unfiltered))\\b/i,\n severity: 'high',\n description: 'Persona hijack attempt',\n },\n {\n rule: 'pretend-to-be',\n pattern: /\\bpretend\\s+(?:to\\s+be|you\\s+are|that\\s+you\\s+(?:are|have))\\b/i,\n severity: 'high',\n description: 'Persona-impersonation prompt',\n },\n {\n rule: 'roleplay-as',\n pattern: /\\b(?:roleplay|role[\\s-]?play|simulate|emulate)\\s+(?:as|being|the\\s+role\\s+of)\\b/i,\n severity: 'high',\n description: 'Roleplay-based jailbreak prefix',\n },\n {\n rule: 'no-restrictions',\n pattern: /\\b(?:without\\s+(?:any\\s+)?(?:restrictions?|limits?|filters?|safety|guidelines?|moral|ethic\\w*)|no\\s+(?:restrictions?|limits?|filters?|safety|guidelines?))\\b/i,\n severity: 'high',\n description: 'Explicit \"no restrictions\" qualifier',\n },\n\n // --- MEDIUM severity: system-prompt extraction & structural injection ---\n {\n rule: 'reveal-system-prompt',\n pattern: /\\b(?:show|display|print|reveal|tell|give|repeat|output|expose)\\s+(?:me\\s+)?(?:your|the)\\s+(?:(?:system|original|initial|full|complete|exact|raw)\\s+)*(?:prompt|instructions?|directive|configuration|rules?|guidelines?)/i,\n severity: 'medium',\n description: 'System-prompt extraction attempt',\n },\n {\n rule: 'what-are-instructions',\n pattern: /\\bwhat\\s+(?:are|were|is)\\s+(?:your|the)\\s+(?:original\\s+|initial\\s+|system\\s+)?(?:instructions?|directives?|rules?|prompts?|guidelines?)\\b/i,\n severity: 'medium',\n description: 'Indirect system-prompt extraction',\n },\n {\n rule: 'fake-system-tag',\n pattern: /<\\/?\\s*(?:system|instructions?|prompt|admin|root|sudo|user_admin)\\s*>/i,\n severity: 'medium',\n description: 'Forged XML-style system delimiter',\n },\n {\n rule: 'fake-system-marker',\n pattern: /(?:^|\\n)\\s*(?:#{1,3}\\s*|\\[\\s*|\\*\\*\\s*)?(?:SYSTEM|INSTRUCTIONS?|ADMIN|ROOT|PROMPT)\\s*[:>=#]\\s*/i,\n severity: 'medium',\n description: 'Forged Markdown/heading-style system marker',\n },\n {\n rule: 'begin-new-instructions',\n pattern: /\\b(?:BEGIN|START|INITIATE)\\s+(?:NEW\\s+|UPDATED\\s+|REPLACEMENT\\s+)?(?:INSTRUCTIONS?|PROMPT|SYSTEM|RULES?|DIRECTIVES?)\\b/i,\n severity: 'medium',\n description: '\"BEGIN NEW INSTRUCTIONS\" marker',\n },\n {\n rule: 'end-of-input-marker',\n pattern: /\\[\\s*(?:END|FINISH|TERMINATE|STOP|CLOSE)\\s+(?:OF\\s+)?(?:INPUT|USER|MESSAGE|CONVERSATION|CONTEXT)\\s*\\]/i,\n severity: 'medium',\n description: 'Fake \"[END OF INPUT]\" marker',\n },\n {\n rule: 'human-assistant-replay',\n pattern: /\\n\\s*(?:Human|User|Assistant|AI):\\s*/i,\n severity: 'medium',\n description: 'Forged Human:/Assistant: turn marker',\n },\n {\n rule: 'output-after-marker',\n pattern: /\\b(?:after\\s+(?:this|the\\s+\\w+))\\s*[,.]?\\s*(?:output|print|say|respond|reply|return|generate)\\b/i,\n severity: 'medium',\n description: 'Conditional output redirection',\n },\n {\n rule: 'translate-but-do-other',\n pattern: /\\b(?:translate|summari[sz]e|paraphrase|rewrite)\\s+.{0,80}\\b(?:but|then|after|and)\\s+(?:also\\s+)?(?:do|say|output|tell|reveal|print)\\b/i,\n severity: 'medium',\n description: 'Task-hijack via \"translate X but Y\"',\n },\n {\n rule: 'base64-suspicious',\n pattern: /\\b(?:base64|b64|decode|encoded?\\s+(?:in|as)\\s+base64|atob)\\b/i,\n severity: 'medium',\n description: 'Base64-decode hint (often used to smuggle jailbreaks)',\n },\n {\n rule: 'rot13-encoding',\n pattern: /\\b(?:rot13|rot-13|caesar(?:\\s+cipher)?)\\b/i,\n severity: 'medium',\n description: 'ROT13 / Caesar-cipher decode hint',\n },\n\n // ── V32: AI agent toolcall injection (improvements.md §1.2) ────────\n // Modern LLM agents (Claude tool-use, OpenAI function-calling,\n // ReAct loops) read tool definitions from the system prompt and\n // JSON-shaped requests from the model. A malicious user can embed\n // those shapes in their input to make the host think they invoked\n // a tool, or to trick the model into echoing a synthesized\n // tool_call that the runtime then executes.\n //\n // Narrow patterns. Match the literal JSON keys and inline\n // tool-name shapes. Won't false-positive on plain English text\n // discussing tools.\n {\n rule: 'agent-toolcall-marker',\n pattern: /\"(?:tool_call|function_call|call_tool|tool_use|toolUse)\"\\s*:\\s*\\{/i,\n severity: 'high',\n description: 'Injected agent tool-call JSON shape (e.g. {\"tool_call\":{...}})',\n },\n {\n rule: 'agent-tool-name-spoof',\n pattern:\n /\"name\"\\s*:\\s*\"(?:exec|shell|run_command|system|bash|cmd|python|eval|read_file|write_file|delete_file)\"/i,\n severity: 'high',\n description: 'Forged tool-name attempting privileged tool invocation',\n },\n {\n rule: 'agent-tool-result-marker',\n pattern: /\"(?:tool_result|function_result|tool_output)\"\\s*:\\s*[\\{\\[\"]/i,\n severity: 'high',\n description: 'Injected fake tool-result block (trick agent into trusting fabricated output)',\n },\n {\n rule: 'ansi-escape-sequence',\n pattern: /\\x1b\\[/,\n severity: 'medium',\n description: 'ANSI escape sequence (terminal hijack / output spoofing on CLI agents)',\n },\n {\n rule: 'claude-tool-use-tags',\n pattern: /<\\/?\\s*(?:tool_use|tool_result|invoke|function_calls?|parameter)\\b/i,\n severity: 'high',\n description: 'Claude/OpenAI tool-use XML-style tag forgery',\n },\n\n // ── Prompt-template marker forgeries ────────────────────────────────\n // Catches inline forgery of the special tokens that LLM runtimes use\n // to delimit roles. If a user can land any of these in their input\n // and the host concatenates the input into a prompt without\n // re-tokenizing, the model treats the suffix as a new system turn.\n //\n // Covered runtimes:\n // - ChatML (OpenAI / Llama 3 chat): <|im_start|>, <|im_end|>\n // - Llama 2 chat: [INST] <<SYS>> ... <</SYS>>\n // - guidance/handlebars: {{#system~}}, {{/system~}}, {{#assistant~}}\n // - Markdown link spoof: [system](#assistant), [admin](#context)\n {\n rule: 'chatml-template-marker',\n pattern: /<\\|im_(?:start|end)\\|>(?:\\s*(?:system|assistant|user|tool|function))?/i,\n severity: 'high',\n description: 'ChatML special token forgery (<|im_start|>...) to spoof a role turn',\n },\n {\n rule: 'llama2-system-marker',\n pattern: /<<\\s*\\/?\\s*SYS\\s*>>|\\[\\s*\\/?\\s*INST\\s*\\]/i,\n severity: 'high',\n description: 'Llama 2 [INST]/<<SYS>> instruction-template marker forgery',\n },\n {\n rule: 'guidance-template-marker',\n pattern: /\\{\\{\\s*[#/]\\s*(?:system|assistant|user|tool|function)\\s*~?\\s*\\}\\}/i,\n severity: 'medium',\n description: 'guidance/handlebars role-block marker forgery ({{#system~}} ...)',\n },\n {\n rule: 'markdown-system-link-spoof',\n pattern: /\\[\\s*(?:system|admin|root|assistant)\\s*\\]\\s*\\(\\s*#(?:assistant|context|system|root|admin)\\s*\\)/i,\n severity: 'medium',\n description: 'Markdown link forgery spoofing a role marker ([system](#assistant))',\n },\n\n // --- LOW severity: ambiguous but worth flagging in strict mode ---\n {\n rule: 'from-now-on',\n pattern: /\\bfrom\\s+now\\s+on\\b\\s*[,.]?\\s*(?:you|always|never)/i,\n severity: 'low',\n description: 'Persistent-instruction prefix',\n },\n {\n rule: 'your-new-purpose',\n pattern: /\\byour\\s+(?:new|real|true|primary|only)\\s+(?:purpose|role|task|goal|job|function)\\s+is\\b/i,\n severity: 'low',\n description: 'Persona/purpose redefinition',\n },\n {\n rule: 'forget-everything',\n pattern: /\\bforget\\s+(?:everything|all|the\\s+(?:above|previous|prior))\\b/i,\n severity: 'low',\n description: 'Memory-clear directive',\n },\n {\n rule: 'no-warnings',\n pattern: /\\b(?:without|don'?t|do\\s+not)\\s+(?:add|include|provide|give|send|print)\\s+(?:any\\s+)?(?:warnings?|disclaimers?|caveats?|safety\\s+notes?|legal\\s+notice)/i,\n severity: 'low',\n description: 'Warning-suppression directive',\n },\n {\n rule: 'hypothetical-prefix',\n pattern: /\\b(?:hypothetically|in\\s+a\\s+hypothetical\\s+(?:world|scenario)|imagine\\s+(?:a\\s+)?(?:world|scenario|situation)\\s+where)\\b/i,\n severity: 'low',\n description: 'Hypothetical framing (common jailbreak prefix)',\n },\n {\n rule: 'just-a-story',\n pattern: /\\b(?:just|only|merely)\\s+(?:a\\s+)?(?:story|fiction|hypothetical|thought\\s+experiment|joke|game|test)\\b/i,\n severity: 'low',\n description: 'Fictional framing escape',\n },\n];\n\nconst SEVERITY_RANK: Record<PromptInjectionSeverity, number> = {\n low: 1,\n medium: 2,\n high: 3,\n};\n\n// ─── Public API ────────────────────────────────────────────────────────────\n\n/**\n * Detect prompt-injection signatures in `text`. Returns all matches with\n * severity and the highest severity seen. Does not modify the input.\n *\n * @example\n * const r = detectPromptInjection('Ignore the previous instructions.');\n * if (r.detected && r.severity === 'high') return res.status(403).end();\n */\nexport function detectPromptInjection(text: string): DetectPromptInjectionResult {\n if (typeof text !== 'string' || text.length === 0) {\n return { detected: false, matches: [], severity: 'none' };\n }\n\n const matches: PromptInjectionMatch[] = [];\n let topRank = 0;\n let topSeverity: PromptInjectionSeverity | 'none' = 'none';\n\n for (const sig of SIGNATURES) {\n const m = sig.pattern.exec(text);\n if (m) {\n const matched = m[0].slice(0, 80);\n matches.push({\n rule: sig.rule,\n severity: sig.severity,\n description: sig.description,\n match: matched,\n });\n const rank = SEVERITY_RANK[sig.severity];\n if (rank > topRank) {\n topRank = rank;\n topSeverity = sig.severity;\n }\n }\n }\n\n return {\n detected: matches.length > 0,\n matches,\n severity: topSeverity,\n };\n}\n\n/**\n * Strip prompt-injection signatures from `text`. For HIGH and MEDIUM\n * severity matches the matched span is replaced with `[REDACTED]`. LOW\n * severity matches are left in place by default. Toggle via `redactLow`.\n *\n * Returns the sanitized string. To inspect what was stripped, call\n * `detectPromptInjection` first or pass `collectMatches: true`.\n */\nexport function sanitizePromptInjection(\n text: string,\n options: { redactLow?: boolean; replacement?: string } = {},\n): string {\n if (typeof text !== 'string' || text.length === 0) return text ?? '';\n\n const replacement = options.replacement ?? '[REDACTED]';\n const redactLow = options.redactLow ?? false;\n let value = text;\n\n for (const sig of SIGNATURES) {\n if (sig.severity === 'low' && !redactLow) continue;\n // Use a global flavor of the pattern so multiple occurrences are removed.\n const flags = sig.pattern.flags.includes('g') ? sig.pattern.flags : sig.pattern.flags + 'g';\n const globalPattern = new RegExp(sig.pattern.source, flags);\n value = value.replace(globalPattern, replacement);\n }\n\n return value;\n}\n","/**\n * @module @arcis/node/guards\n *\n * Guards API. Same Arcis decisioning (rate limit, bot detect, prompt\n * injection, token budget) applied to non-HTTP contexts where there's no\n * `req`/`res` pair. Use this for:\n *\n * - Job queue workers (BullMQ, agenda, sidekiq-style)\n * - Agent tool-call handlers (Claude/OpenAI tool dispatch)\n * - WebSocket / SSE / gRPC handlers\n * - Background processors (cron jobs, scheduled tasks)\n *\n * Each call to `guards.run(input)` returns a structured decision: `ok` +\n * (when denied) the `vector`, `severity`, `reason`, and `retryAfterSeconds`\n * the deny was triggered by. The first vector that denies short-circuits\n * the rest, so denial latency stays bounded.\n *\n * @example\n * import { Guards } from '@arcis/node';\n *\n * const guards = new Guards({\n * rateLimit: { max: 50, windowMs: 60_000 },\n * tokenBudget: { maxTokens: 100_000, windowMs: 60 * 60 * 1000 },\n * promptInjection: { redactLow: false },\n * });\n *\n * // In a job handler:\n * const decision = guards.run({\n * key: jobUserId,\n * tokens: estimateTokens(prompt),\n * text: prompt,\n * });\n * if (!decision.ok) {\n * throw new Error(`Job rejected (${decision.vector}): ${decision.reason}`);\n * }\n */\n\nimport { detectBot, type BotProtectionOptions } from './middleware/bot-detection';\nimport {\n detectPromptInjection,\n type PromptInjectionSeverity,\n} from './sanitizers/prompt-injection';\n\n// ─── Public types ──────────────────────────────────────────────────────────\n\nexport interface GuardsRateLimitOptions {\n /** Max events per window per key. Default: 100. */\n max?: number;\n /** Window length in milliseconds. Default: 60000 (1 minute). */\n windowMs?: number;\n}\n\nexport interface GuardsTokenBudgetOptions {\n /** Max tokens a single key can spend in one window. Default: 100,000. */\n maxTokens?: number;\n /** Window length in milliseconds. Default: 60 * 60 * 1000 (1 hour). */\n windowMs?: number;\n /**\n * Optional per-call cap. When set, a single call with `tokens > maxRequestTokens`\n * denies BEFORE charging the window budget.\n */\n maxRequestTokens?: number;\n}\n\nexport interface GuardsPromptInjectionOptions {\n /**\n * Minimum severity that triggers a deny. Default: 'medium' (HIGH and\n * MEDIUM matches deny; LOW matches still surface in `decision.matches`\n * but don't deny).\n */\n denyAt?: PromptInjectionSeverity;\n}\n\nexport interface GuardsBotOptions {\n /** Categories that pass through. Default: SEARCH_ENGINE, SOCIAL, MONITORING. */\n allow?: BotProtectionOptions['allow'];\n /** Categories that always deny. Default: AUTOMATED. */\n deny?: BotProtectionOptions['deny'];\n /** Default for uncategorized bots. Default: 'allow'. */\n defaultAction?: BotProtectionOptions['defaultAction'];\n}\n\nexport interface GuardsConfig {\n /** When set, every call is rate-limited per `input.key`. Omit to disable. */\n rateLimit?: GuardsRateLimitOptions;\n /** When set, calls with `input.tokens` charge a per-key sliding-window budget. */\n tokenBudget?: GuardsTokenBudgetOptions;\n /** When set, `input.text` is scanned for prompt-injection signatures. */\n promptInjection?: GuardsPromptInjectionOptions | true;\n /** When set, `input.userAgent` is matched against the bot corpus. */\n bot?: GuardsBotOptions | true;\n}\n\nexport interface GuardsInput {\n /** Identifier for rate-limit / token-budget bucketing. Required. */\n key: string;\n /** Optional text payload for prompt-injection scanning. */\n text?: string;\n /** Optional token cost for token-budget accounting. */\n tokens?: number;\n /** Optional User-Agent string for bot detection. */\n userAgent?: string;\n}\n\nexport type GuardsVector =\n | 'rate-limit'\n | 'token-budget'\n | 'prompt-injection'\n | 'bot';\n\nexport type GuardsSeverity = 'low' | 'medium' | 'high';\n\nexport interface GuardsDecision {\n /** True if the input passes every configured vector. */\n ok: boolean;\n /** Which vector denied. Undefined when `ok` is true. */\n vector?: GuardsVector;\n /** Human-readable reason for the deny. Undefined when `ok` is true. */\n reason?: string;\n /** Severity of the deny. Undefined when `ok` is true. */\n severity?: GuardsSeverity;\n /** How many seconds until the same key can retry (rate-limit / token-budget). */\n retryAfterSeconds?: number;\n /**\n * For prompt-injection: every signature that matched, even when the deny\n * threshold wasn't hit. Lets callers log low-severity matches without\n * blocking on them.\n */\n matches?: ReadonlyArray<{ rule: string; severity: GuardsSeverity }>;\n}\n\n// ─── Internal state ────────────────────────────────────────────────────────\n\ninterface RLEntry {\n count: number;\n resetTime: number;\n}\n\ninterface TBEntry {\n used: number;\n resetTime: number;\n}\n\nconst SEVERITY_RANK: Record<GuardsSeverity, number> = { low: 1, medium: 2, high: 3 };\n\nconst DEFAULT_BOT_ALLOW = new Set(['SEARCH_ENGINE', 'SOCIAL', 'MONITORING']);\nconst DEFAULT_BOT_DENY = new Set(['AUTOMATED']);\n\n// ─── Public class ──────────────────────────────────────────────────────────\n\n/**\n * Guards. Apply Arcis decisions to non-HTTP contexts. Construct once with\n * the vectors you care about, then call `.run(input)` per request/event.\n * Internal state (rate-limit buckets, token-budget buckets) lives on the\n * instance. Call `.close()` to release the periodic-cleanup interval.\n */\nexport class Guards {\n private readonly rl: GuardsRateLimitOptions | undefined;\n private readonly tb: GuardsTokenBudgetOptions | undefined;\n private readonly pi: GuardsPromptInjectionOptions | undefined;\n private readonly bot: GuardsBotOptions | undefined;\n private readonly rlStore: Record<string, RLEntry>;\n private readonly tbStore: Record<string, TBEntry>;\n private readonly cleanup: ReturnType<typeof setInterval> | null;\n private readonly piDenyRank: number;\n\n constructor(config: GuardsConfig = {}) {\n this.rl = config.rateLimit;\n this.tb = config.tokenBudget;\n this.pi = config.promptInjection === true ? {} : config.promptInjection;\n this.bot = config.bot === true ? {} : config.bot;\n\n const denyAt = (this.pi?.denyAt as GuardsSeverity | undefined) ?? 'medium';\n this.piDenyRank = SEVERITY_RANK[denyAt];\n\n this.rlStore = Object.create(null);\n this.tbStore = Object.create(null);\n\n // Sweep expired buckets only when rate-limit or token-budget is in play.\n const sweepInterval = this.rl?.windowMs ?? this.tb?.windowMs;\n if (sweepInterval) {\n this.cleanup = setInterval(() => this.sweepExpired(), sweepInterval);\n if (typeof this.cleanup.unref === 'function') this.cleanup.unref();\n } else {\n this.cleanup = null;\n }\n }\n\n /**\n * Evaluate every configured vector against `input`. Returns a structured\n * decision; the first denying vector short-circuits the rest.\n */\n run(input: GuardsInput): GuardsDecision {\n if (!input || typeof input.key !== 'string' || input.key.length === 0) {\n return { ok: false, reason: 'guards: missing required `input.key`' };\n }\n\n // 1. Rate limit\n if (this.rl) {\n const decision = this.checkRateLimit(input.key);\n if (!decision.ok) return decision;\n }\n\n // 2. Bot detection (if a UA was supplied)\n if (this.bot && input.userAgent) {\n const decision = this.checkBot(input.userAgent);\n if (!decision.ok) return decision;\n }\n\n // 3. Prompt injection (if text was supplied)\n let piMatches: ReadonlyArray<{ rule: string; severity: GuardsSeverity }> | undefined;\n if (this.pi !== undefined && typeof input.text === 'string' && input.text.length > 0) {\n const result = detectPromptInjection(input.text);\n piMatches = result.matches.map((m) => ({ rule: m.rule, severity: m.severity }));\n if (\n result.detected &&\n result.severity !== 'none' &&\n SEVERITY_RANK[result.severity] >= this.piDenyRank\n ) {\n const top = result.matches.find((m) => m.severity === result.severity) ?? result.matches[0];\n return {\n ok: false,\n vector: 'prompt-injection',\n severity: result.severity,\n reason: top\n ? `Prompt injection detected (${top.rule}): ${top.description}`\n : 'Prompt injection detected',\n matches: piMatches,\n };\n }\n }\n\n // 4. Token budget (always last so a denied request hasn't already charged)\n if (this.tb && typeof input.tokens === 'number') {\n const decision = this.checkTokenBudget(input.key, input.tokens);\n if (!decision.ok) return { ...decision, matches: piMatches };\n }\n\n return { ok: true, matches: piMatches };\n }\n\n /** Inspect rate-limit usage for a key. Useful for tests and telemetry. */\n inspectRateLimit(key: string): { count: number; resetTime: number } | null {\n const e = this.rlStore[key];\n return e ? { count: e.count, resetTime: e.resetTime } : null;\n }\n\n /** Inspect token-budget usage for a key. */\n inspectTokenBudget(key: string): { used: number; resetTime: number } | null {\n const e = this.tbStore[key];\n return e ? { used: e.used, resetTime: e.resetTime } : null;\n }\n\n /** Reset a single key's state, or all keys if `key` is omitted. */\n reset(key?: string): void {\n if (key === undefined) {\n for (const k of Object.keys(this.rlStore)) delete this.rlStore[k];\n for (const k of Object.keys(this.tbStore)) delete this.tbStore[k];\n } else {\n delete this.rlStore[key];\n delete this.tbStore[key];\n }\n }\n\n /** Release the periodic cleanup interval. Idempotent. */\n close(): void {\n if (this.cleanup !== null) clearInterval(this.cleanup);\n }\n\n // ─── internals ────────────────────────────────────────────────────────\n\n private checkRateLimit(key: string): GuardsDecision {\n const max = this.rl?.max ?? 100;\n const windowMs = this.rl?.windowMs ?? 60_000;\n const now = Date.now();\n let entry = this.rlStore[key];\n if (!entry || entry.resetTime < now) {\n entry = { count: 0, resetTime: now + windowMs };\n this.rlStore[key] = entry;\n }\n entry.count += 1;\n if (entry.count > max) {\n const retryAfterSeconds = Math.ceil((entry.resetTime - now) / 1000);\n return {\n ok: false,\n vector: 'rate-limit',\n severity: 'medium',\n reason: `Rate limit exceeded (${entry.count}/${max} per ${windowMs}ms)`,\n retryAfterSeconds: Math.max(0, retryAfterSeconds),\n };\n }\n return { ok: true };\n }\n\n private checkTokenBudget(key: string, tokens: number): GuardsDecision {\n const cost = Number.isFinite(tokens) && tokens >= 0 ? Math.floor(tokens) : 0;\n const max = this.tb?.maxTokens ?? 100_000;\n const windowMs = this.tb?.windowMs ?? 60 * 60 * 1000;\n const perReq = this.tb?.maxRequestTokens;\n\n if (perReq !== undefined && cost > perReq) {\n return {\n ok: false,\n vector: 'token-budget',\n severity: 'high',\n reason: `Per-call token budget exceeded (${cost} > ${perReq})`,\n };\n }\n\n const now = Date.now();\n let entry = this.tbStore[key];\n if (!entry || entry.resetTime < now) {\n entry = { used: 0, resetTime: now + windowMs };\n this.tbStore[key] = entry;\n }\n const projected = entry.used + cost;\n if (projected > max) {\n const retryAfterSeconds = Math.ceil((entry.resetTime - now) / 1000);\n return {\n ok: false,\n vector: 'token-budget',\n severity: 'medium',\n reason: `Window token budget exceeded (${entry.used} + ${cost} > ${max})`,\n retryAfterSeconds: Math.max(0, retryAfterSeconds),\n };\n }\n entry.used = projected;\n return { ok: true };\n }\n\n private checkBot(userAgent: string): GuardsDecision {\n const fakeReq = {\n headers: {\n 'user-agent': userAgent,\n accept: 'text/html',\n 'accept-language': 'en-US',\n 'accept-encoding': 'gzip',\n },\n };\n const result = detectBot(fakeReq as never);\n if (!result.isBot) return { ok: true };\n\n const allow = this.bot?.allow ? new Set(this.bot.allow) : DEFAULT_BOT_ALLOW;\n const deny = this.bot?.deny ? new Set(this.bot.deny) : DEFAULT_BOT_DENY;\n const defaultAction = this.bot?.defaultAction ?? 'allow';\n\n if (allow.has(result.category as never)) return { ok: true };\n if (deny.has(result.category as never)) {\n return {\n ok: false,\n vector: 'bot',\n severity: 'medium',\n reason: result.name ? `Bot denied: ${result.name}` : `Bot denied (${result.category})`,\n };\n }\n if (defaultAction === 'deny') {\n return {\n ok: false,\n vector: 'bot',\n severity: 'low',\n reason: `Uncategorized bot under defaultAction=deny`,\n };\n }\n return { ok: true };\n }\n\n private sweepExpired(): void {\n const now = Date.now();\n for (const k of Object.keys(this.rlStore)) {\n if (this.rlStore[k].resetTime < now) delete this.rlStore[k];\n }\n for (const k of Object.keys(this.tbStore)) {\n if (this.tbStore[k].resetTime < now) delete this.tbStore[k];\n }\n }\n}\n\nexport default Guards;\n","/**\n * @module @arcis/node/utils/ip\n * Platform-aware client IP detection.\n *\n * Prevents IP spoofing by reading platform-specific headers\n * instead of blindly trusting X-Forwarded-For.\n *\n * @example\n * // Auto-detect platform from environment\n * const ip = detectClientIp(req);\n *\n * // Explicit platform\n * const ip = detectClientIp(req, { platform: 'cloudflare' });\n */\n\nimport type { IncomingMessage } from 'http';\n\nexport type Platform =\n | 'auto'\n | 'cloudflare'\n | 'vercel'\n | 'flyio'\n | 'render'\n | 'firebase'\n | 'aws-alb'\n | 'generic';\n\nexport interface DetectIpOptions {\n /** Platform to use for header selection. Default: 'auto' */\n platform?: Platform;\n /** Number of trusted proxies (for X-Forwarded-For parsing). Default: 1 */\n trustedProxyCount?: number;\n}\n\ninterface RequestLike {\n headers: Record<string, string | string[] | undefined>;\n socket?: { remoteAddress?: string };\n connection?: { remoteAddress?: string };\n ip?: string;\n}\n\n/**\n * Platform-specific header configurations.\n * Each platform sets a trusted header that cannot be spoofed by the client.\n */\nconst PLATFORM_HEADERS: Record<Exclude<Platform, 'auto' | 'generic'>, string> = {\n cloudflare: 'cf-connecting-ip',\n vercel: 'x-real-ip',\n flyio: 'fly-client-ip',\n render: 'x-render-client-ip',\n firebase: 'x-appengine-user-ip',\n 'aws-alb': 'x-forwarded-for',\n};\n\n/**\n * Auto-detect the platform from environment variables.\n */\nfunction detectPlatform(): Platform {\n const env = typeof process !== 'undefined' ? process.env : {};\n\n if (env.CF_PAGES || env.CF_WORKERS) return 'cloudflare';\n if (env.VERCEL) return 'vercel';\n if (env.FLY_APP_NAME) return 'flyio';\n if (env.RENDER) return 'render';\n if (env.FIREBASE_CONFIG || env.GCLOUD_PROJECT) return 'firebase';\n if (env.AWS_EXECUTION_ENV || env.AWS_LAMBDA_FUNCTION_NAME) return 'aws-alb';\n\n return 'generic';\n}\n\n// Cache the detected platform — it won't change during process lifetime\nlet _cachedPlatform: Platform | null = null;\n\nfunction getCachedPlatform(): Platform {\n if (_cachedPlatform === null) {\n _cachedPlatform = detectPlatform();\n }\n return _cachedPlatform;\n}\n\n/** Max IP string length (IPv6 max = 45 chars) */\nconst MAX_IP_LENGTH = 45;\n\n/**\n * Sanitize an IP string: trim, truncate, strip control characters.\n * Prevents unbounded strings from being used as map keys.\n */\nfunction sanitizeIp(ip: string): string {\n const trimmed = ip.trim();\n if (trimmed.length > MAX_IP_LENGTH) return trimmed.slice(0, MAX_IP_LENGTH);\n return trimmed;\n}\n\n/**\n * Get a header value from the request, handling string arrays.\n */\nfunction getHeader(req: RequestLike, name: string): string | undefined {\n const val = req.headers[name];\n if (Array.isArray(val)) return val[0];\n return val;\n}\n\n/**\n * Parse the rightmost trusted IP from X-Forwarded-For.\n * Reading from the right prevents client spoofing — the rightmost entry\n * is the one added by the closest trusted proxy.\n */\nfunction parseForwardedFor(header: string, trustedProxyCount: number): string | undefined {\n const ips = header.split(',').map(ip => ip.trim()).filter(Boolean);\n if (ips.length === 0) return undefined;\n\n // The client IP is at position (length - trustedProxyCount)\n const clientIndex = Math.max(0, ips.length - trustedProxyCount);\n return ips[clientIndex] || undefined;\n}\n\n/**\n * Detect the real client IP address from a request.\n *\n * Uses platform-specific headers when available to prevent IP spoofing.\n * Falls back to X-Forwarded-For (parsed from the right) and then\n * the socket remote address.\n *\n * @param req - HTTP request object (Express, raw http, etc.)\n * @param options - Detection options\n * @returns Client IP address, or 'unknown' if unresolvable\n *\n * @example\n * // Auto-detect platform\n * app.use((req, res, next) => {\n * const clientIp = detectClientIp(req);\n * console.log('Client IP:', clientIp);\n * next();\n * });\n *\n * @example\n * // Behind Cloudflare\n * const ip = detectClientIp(req, { platform: 'cloudflare' });\n *\n * @example\n * // Behind 2 proxies (e.g. CDN + load balancer)\n * const ip = detectClientIp(req, { trustedProxyCount: 2 });\n */\nexport function detectClientIp(\n req: RequestLike | IncomingMessage,\n options: DetectIpOptions = {}\n): string {\n const { platform = 'auto', trustedProxyCount = 1 } = options;\n const r = req as RequestLike;\n\n const resolvedPlatform = platform === 'auto' ? getCachedPlatform() : platform;\n\n // 1. Try platform-specific header (most trusted)\n if (resolvedPlatform !== 'generic' && resolvedPlatform in PLATFORM_HEADERS) {\n const headerName = PLATFORM_HEADERS[resolvedPlatform as keyof typeof PLATFORM_HEADERS];\n if (headerName) {\n if (resolvedPlatform === 'aws-alb') {\n // AWS ALB: parse X-Forwarded-For from the right\n const xff = getHeader(r, 'x-forwarded-for');\n if (xff) {\n const ip = parseForwardedFor(xff, trustedProxyCount);\n if (ip) return sanitizeIp(ip);\n }\n } else {\n const ip = getHeader(r, headerName);\n if (ip) return sanitizeIp(ip);\n }\n }\n }\n\n // 2. Try Express req.ip (respects trust proxy setting)\n if (r.ip) return sanitizeIp(r.ip);\n\n // 3. Try X-Forwarded-For (parsed from the right for safety)\n const xff = getHeader(r, 'x-forwarded-for');\n if (xff) {\n const ip = parseForwardedFor(xff, trustedProxyCount);\n if (ip) return sanitizeIp(ip);\n }\n\n // 4. Try X-Real-IP\n const realIp = getHeader(r, 'x-real-ip');\n if (realIp) return sanitizeIp(realIp);\n\n // 5. Socket remote address\n const socketIp = r.socket?.remoteAddress ?? r.connection?.remoteAddress;\n if (socketIp) return sanitizeIp(socketIp);\n\n return 'unknown';\n}\n\n/**\n * Check if an IP address is a private/internal address.\n *\n * Detects: loopback, private ranges (RFC 1918), link-local, IPv6 equivalents.\n */\nexport function isPrivateIp(ip: string): boolean {\n // Strip IPv4-mapped IPv6 prefix (::ffff:127.0.0.1 -> 127.0.0.1)\n const normalized = ip.startsWith('::ffff:') ? ip.slice(7) : ip;\n\n // IPv4 private ranges\n if (/^127\\./.test(normalized)) return true; // Loopback\n if (/^10\\./.test(normalized)) return true; // Class A private\n if (/^172\\.(1[6-9]|2\\d|3[01])\\./.test(normalized)) return true; // Class B private\n if (/^192\\.168\\./.test(normalized)) return true; // Class C private\n if (/^169\\.254\\./.test(normalized)) return true; // Link-local\n if (/^0\\./.test(normalized)) return true; // Current network\n\n // IPv6\n if (ip === '::1') return true; // Loopback\n if (/^fe80:/i.test(ip)) return true; // Link-local\n if (/^fc00:/i.test(ip)) return true; // Unique local\n if (/^fd/i.test(ip)) return true; // Unique local\n\n return false;\n}\n\n/** Reset cached platform (for testing). */\nexport function _resetPlatformCache(): void {\n _cachedPlatform = null;\n}\n","/**\n * @module @arcis/node/utils/fingerprint\n * Deterministic request fingerprinting via SHA-256.\n *\n * Generates a stable hash from request characteristics for\n * rate limiting keys, abuse detection, and analytics.\n *\n * @example\n * const fp = await fingerprint(req);\n * // \"a3f2b8c1d4e5...\"\n */\n\nimport { createHash } from 'crypto';\nimport { detectClientIp } from './ip';\nimport type { DetectIpOptions } from './ip';\n\nexport interface FingerprintOptions {\n /** Include IP address in fingerprint. Default: true */\n ip?: boolean;\n /** Include User-Agent header. Default: true */\n userAgent?: boolean;\n /** Include Accept header. Default: true */\n accept?: boolean;\n /** Include Accept-Language header. Default: true */\n acceptLanguage?: boolean;\n /** Include Accept-Encoding header. Default: true */\n acceptEncoding?: boolean;\n /** Additional custom components to include */\n custom?: string[];\n /** IP detection options */\n ipOptions?: DetectIpOptions;\n}\n\ninterface RequestLike {\n headers: Record<string, string | string[] | undefined>;\n socket?: { remoteAddress?: string };\n connection?: { remoteAddress?: string };\n ip?: string;\n}\n\nfunction getHeader(req: RequestLike, name: string): string {\n const val = req.headers[name];\n if (Array.isArray(val)) return val[0] ?? '';\n return val ?? '';\n}\n\n/**\n * Generate a deterministic fingerprint for a request.\n *\n * Creates a SHA-256 hash from configurable request components.\n * The fingerprint is stable across requests from the same client\n * (same IP, browser, language settings).\n *\n * @param req - HTTP request object\n * @param options - Fingerprint configuration\n * @returns Hex-encoded SHA-256 hash (64 characters)\n *\n * @example\n * // Default fingerprint (IP + UA + Accept headers)\n * const fp = fingerprint(req);\n *\n * @example\n * // IP-only fingerprint (for simple rate limiting)\n * const fp = fingerprint(req, { userAgent: false, accept: false, acceptLanguage: false, acceptEncoding: false });\n *\n * @example\n * // With custom components\n * const fp = fingerprint(req, { custom: [req.body?.userId] });\n */\nexport function fingerprint(req: RequestLike, options: FingerprintOptions = {}): string {\n const {\n ip = true,\n userAgent = true,\n accept = true,\n acceptLanguage = true,\n acceptEncoding = true,\n custom = [],\n ipOptions,\n } = options;\n\n const components: string[] = [];\n\n if (ip) {\n components.push(`ip:${detectClientIp(req, ipOptions)}`);\n }\n if (userAgent) {\n components.push(`ua:${getHeader(req, 'user-agent')}`);\n }\n if (accept) {\n components.push(`accept:${getHeader(req, 'accept')}`);\n }\n if (acceptLanguage) {\n components.push(`lang:${getHeader(req, 'accept-language')}`);\n }\n if (acceptEncoding) {\n components.push(`enc:${getHeader(req, 'accept-encoding')}`);\n }\n\n for (const c of custom) {\n if (c !== null && c !== undefined) components.push(`custom:${c}`);\n }\n\n // Sort for deterministic ordering\n components.sort();\n\n const hash = createHash('sha256');\n hash.update(components.join('|'));\n return hash.digest('hex');\n}\n","/**\n * @module @arcis/node/stores/memory\n * In-memory rate limit store\n */\n\nimport type { RateLimitStore, RateLimitEntry } from '../core/types';\nimport { RATE_LIMIT } from '../core/constants';\n\n/**\n * In-memory rate limit store.\n * Suitable for single-instance deployments.\n * For distributed systems, use RedisStore or a custom store.\n * \n * @example\n * const store = new MemoryStore(60000); // 1 minute window\n * const limiter = createRateLimiter({ store });\n */\n/** Default maximum number of keys the in-memory store will hold. */\nconst DEFAULT_MAX_SIZE = 10_000;\n\nexport class MemoryStore implements RateLimitStore {\n private store: Map<string, RateLimitEntry> = new Map();\n private cleanupInterval: ReturnType<typeof setInterval> | null = null;\n private windowMs: number;\n private maxSize: number;\n\n constructor(windowMs: number = RATE_LIMIT.DEFAULT_WINDOW_MS, maxSize: number = DEFAULT_MAX_SIZE) {\n if (!Number.isFinite(windowMs) || windowMs < RATE_LIMIT.MIN_WINDOW_MS) {\n throw new RangeError(\n `MemoryStore: windowMs must be a finite number >= ${RATE_LIMIT.MIN_WINDOW_MS} (got ${windowMs})`\n );\n }\n if (!Number.isFinite(maxSize) || maxSize < 1) {\n throw new RangeError(`MemoryStore: maxSize must be >= 1 (got ${maxSize})`);\n }\n this.windowMs = windowMs;\n this.maxSize = maxSize;\n this.startCleanup();\n }\n\n /**\n * Start the cleanup interval to remove expired entries.\n */\n private startCleanup(): void {\n // Clamp the cleanup interval between 30 s and 5 min regardless of windowMs.\n // Running it every windowMs is fine for typical windows but would fire every\n // second for short windows (e.g. windowMs: 1000), causing O(n) GC pressure.\n const CLEANUP_MIN_MS = 30_000;\n const CLEANUP_MAX_MS = 300_000;\n const cleanupMs = Math.min(Math.max(this.windowMs, CLEANUP_MIN_MS), CLEANUP_MAX_MS);\n\n this.cleanupInterval = setInterval(() => {\n const now = Date.now();\n for (const [key, entry] of this.store.entries()) {\n if (entry.resetTime < now) {\n this.store.delete(key);\n }\n }\n }, cleanupMs);\n\n // Prevent interval from keeping the process alive\n if (typeof this.cleanupInterval.unref === 'function') {\n this.cleanupInterval.unref();\n }\n }\n\n async get(key: string): Promise<RateLimitEntry | null> {\n const entry = this.store.get(key);\n if (!entry) return null;\n \n // Check if expired\n if (entry.resetTime < Date.now()) {\n this.store.delete(key);\n return null;\n }\n \n return entry;\n }\n\n async set(key: string, entry: RateLimitEntry): Promise<void> {\n if (!this.store.has(key) && this.store.size >= this.maxSize) {\n this.evictExpired();\n // If still at capacity after eviction, fail open — don't crash the app\n if (this.store.size >= this.maxSize) return;\n }\n this.store.set(key, entry);\n }\n\n async increment(key: string): Promise<number> {\n const now = Date.now();\n const entry = this.store.get(key);\n\n if (!entry || entry.resetTime < now) {\n // Start new window — check capacity first\n if (this.store.size >= this.maxSize) {\n this.evictExpired();\n if (this.store.size >= this.maxSize) return 1; // fail open\n }\n this.store.set(key, { count: 1, resetTime: now + this.windowMs });\n return 1;\n }\n\n entry.count++;\n return entry.count;\n }\n\n /** Eagerly remove expired entries to reclaim capacity. */\n private evictExpired(): void {\n const now = Date.now();\n for (const [key, entry] of this.store.entries()) {\n if (entry.resetTime < now) this.store.delete(key);\n }\n }\n\n async decrement(key: string): Promise<void> {\n const entry = this.store.get(key);\n if (entry && entry.count > 0) {\n entry.count--;\n }\n }\n\n async reset(key: string): Promise<void> {\n this.store.delete(key);\n }\n\n async close(): Promise<void> {\n if (this.cleanupInterval) {\n clearInterval(this.cleanupInterval);\n this.cleanupInterval = null;\n }\n this.store.clear();\n }\n\n /**\n * Get current store size (for monitoring).\n */\n get size(): number {\n return this.store.size;\n }\n}\n","/**\n * @module @arcis/node/stores/redis\n * Redis rate limit store\n * \n * Note: This is a reference implementation. You'll need to install\n * the 'ioredis' or 'redis' package and pass your client instance.\n */\n\nimport type { RateLimitStore, RateLimitEntry } from '../core/types';\nimport { RATE_LIMIT } from '../core/constants';\n\n/** Generic Redis client interface (works with ioredis, redis, etc.) */\nexport interface RedisClientLike {\n get(key: string): Promise<string | null>;\n /**\n * SET with optional flags. Supports both `set(key, value)` and\n * `set(key, value, 'EX', seconds, 'NX')` shapes for atomic\n * set-if-not-exists with TTL. Returns 'OK' on success; null when NX\n * is supplied and the key already exists.\n */\n set(\n key: string,\n value: string,\n ...args: Array<string | number>\n ): Promise<string | null | unknown>;\n setex(key: string, seconds: number, value: string): Promise<unknown>;\n expire(key: string, seconds: number): Promise<unknown>;\n incr(key: string): Promise<number>;\n decr(key: string): Promise<number>;\n del(key: string): Promise<number>;\n ttl(key: string): Promise<number>;\n quit?(): Promise<unknown>;\n disconnect?(): Promise<unknown>;\n}\n\nexport interface RedisStoreOptions {\n /** Redis client instance */\n client: RedisClientLike;\n /** Key prefix. Default: 'arcis:rl:' */\n prefix?: string;\n /** Window size in milliseconds. Default: 60000 */\n windowMs?: number;\n}\n\n/**\n * Redis rate limit store for distributed deployments.\n * \n * @example\n * import Redis from 'ioredis';\n * \n * const redis = new Redis();\n * const store = new RedisStore({ client: redis });\n * const limiter = createRateLimiter({ store });\n * \n * // Cleanup on shutdown\n * process.on('SIGTERM', async () => {\n * await store.close();\n * });\n */\nexport class RedisStore implements RateLimitStore {\n private client: RedisClientLike;\n private prefix: string;\n private windowMs: number;\n private windowSec: number;\n\n constructor(options: RedisStoreOptions) {\n this.client = options.client;\n this.prefix = options.prefix ?? 'arcis:rl:';\n this.windowMs = options.windowMs ?? RATE_LIMIT.DEFAULT_WINDOW_MS;\n this.windowSec = Math.ceil(this.windowMs / 1000);\n }\n\n private getKey(key: string): string {\n return `${this.prefix}${key}`;\n }\n\n async get(key: string): Promise<RateLimitEntry | null> {\n const redisKey = this.getKey(key);\n \n const [countStr, ttl] = await Promise.all([\n this.client.get(redisKey),\n this.client.ttl(redisKey),\n ]);\n \n if (!countStr || ttl < 0) {\n return null;\n }\n \n const count = parseInt(countStr, 10);\n if (isNaN(count)) {\n // Corrupt value in Redis — treat as if key doesn't exist\n return null;\n }\n\n return {\n count,\n resetTime: Date.now() + (ttl * 1000),\n };\n }\n\n async set(key: string, entry: RateLimitEntry): Promise<void> {\n const redisKey = this.getKey(key);\n // Clamp to at least 1 second — Math.ceil can produce 0 or negative values\n // when entry.resetTime is in the past due to Redis latency or clock skew.\n const ttlSec = Math.max(1, Math.ceil((entry.resetTime - Date.now()) / 1000));\n await this.client.setex(redisKey, ttlSec, entry.count.toString());\n }\n\n async increment(key: string): Promise<number> {\n const redisKey = this.getKey(key);\n\n // SECURITY / RELIABILITY: Atomic first-increment via SET ... EX ... NX.\n // If the key did not exist, this single command creates it with value\n // 1 and the window TTL atomically. If it existed, SET returns null\n // and we fall through to INCR for the actual count. This eliminates\n // the INCR-then-EXPIRE race where a connection drop between the two\n // commands could leave a counter without a TTL, locking out the\n // client until manual intervention.\n const created = await this.client.set(redisKey, '1', 'EX', this.windowSec, 'NX');\n if (created === 'OK' || created === true) {\n return 1;\n }\n return this.client.incr(redisKey);\n }\n\n async decrement(key: string): Promise<void> {\n const redisKey = this.getKey(key);\n await this.client.decr(redisKey);\n }\n\n async reset(key: string): Promise<void> {\n const redisKey = this.getKey(key);\n await this.client.del(redisKey);\n }\n\n async close(): Promise<void> {\n // Don't close the client - it may be shared\n // The caller should manage the client lifecycle\n }\n}\n\n/**\n * Create a Redis store with the given options.\n * Convenience function for functional programming style.\n * \n * @example\n * const store = createRedisStore({ client: redisClient });\n */\nexport function createRedisStore(options: RedisStoreOptions): RedisStore {\n return new RedisStore(options);\n}\n"]}
|