{"version":3,"sources":["../../src/data/patterns.json","../../src/core/patterns-loader.ts","../../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/data/bot-patterns.json","../../src/middleware/bot-detection.ts","../../src/middleware/sensitive-paths.ts","../../src/sanitizers/graphql.ts","../../src/sanitizers/mass-assignment.ts","../../src/validation/url.ts","../../src/sanitizers/prompt-injection.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/deserialization.ts","../../src/sanitizers/nosql.ts","../../src/sanitizers/sanitize.ts","../../src/validation/schema.ts","../../src/validation/file.ts","../../src/validation/email.ts","../../src/logging/redactor.ts","../../src/telemetry/client.ts","../../src/utils/ip.ts","../../src/intelligence/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/middleware/csrf.ts","../../src/middleware/signup-protection.ts","../../src/middleware/method-allowlist.ts","../../src/middleware/overload.ts","../../src/middleware/mass-assign.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/response-splitting.ts","../../src/middleware/correlation.ts"],"names":["xff","result","DEFAULTS","resolve"],"mappings":"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","file":"index.mjs","sourcesContent":["{\n  \"version\": \"1.1.0\",\n  \"description\": \"Arcis Core Security Patterns - Language Agnostic\",\n  \"_pattern_convention\": {\n    \"description\": \"Pattern field naming convention for SDK implementers\",\n    \"pattern\": \"The primary regex pattern. May contain ReDoS-vulnerable constructs.\",\n    \"pattern_safe\": \"ReDoS-safe alternative pattern. SDKs MUST prefer this when available.\",\n    \"redos_safe\": \"Boolean indicating if 'pattern' is ReDoS-safe. If false, use 'pattern_safe'.\",\n    \"usage\": \"pattern_str = rule.get('pattern_safe') or rule.get('pattern')\"\n  },\n  \"config\": {\n    \"max_input_size\": 1000000,\n    \"max_recursion_depth\": 10,\n    \"enable_redos_protection\": true\n  },\n  \"patterns\": {\n    \"xss\": {\n      \"name\": \"Cross-Site Scripting (XSS)\",\n      \"severity\": \"critical\",\n      \"owasp\": \"A03:2021\",\n      \"rules\": [\n        {\n          \"id\": \"xss-script-block\",\n          \"pattern\": \"<script[^>]*>[\\\\s\\\\S]*?</script>\",\n          \"flags\": \"gi\",\n          \"description\": \"Detects full script blocks (open tag through close tag)\",\n          \"redos_safe\": true\n        },\n        {\n          \"id\": \"xss-script-tag\",\n          \"pattern\": \"<script[^>]*>\",\n          \"flags\": \"gi\",\n          \"description\": \"Detects standalone or unclosed script tags\",\n          \"redos_safe\": true\n        },\n        {\n          \"id\": \"xss-javascript-protocol\",\n          \"pattern\": \"javascript\\\\s*:[^\\\\s]\",\n          \"flags\": \"gi\",\n          \"description\": \"Detects javascript: protocol (allows whitespace around colon)\",\n          \"redos_safe\": true\n        },\n        {\n          \"id\": \"xss-event-handler-quoted\",\n          \"pattern\": \"(?:[\\\\s/])on\\\\w+\\\\s*=\\\\s*[\\\"'][^\\\"']*[\\\"']\",\n          \"flags\": \"gi\",\n          \"description\": \"Detects inline event handlers with quoted values (e.g. onclick=\\\"alert(1)\\\")\",\n          \"redos_safe\": true\n        },\n        {\n          \"id\": \"xss-event-handler-unquoted\",\n          \"pattern\": \"(?:[\\\\s/])on\\\\w+\\\\s*=\\\\s*[^\\\\s>]*\",\n          \"flags\": \"gi\",\n          \"description\": \"Detects inline event handlers with unquoted values (e.g. onload=value)\",\n          \"redos_safe\": true\n        },\n        {\n          \"id\": \"xss-iframe-block\",\n          \"pattern\": \"<iframe[^>]*>[\\\\s\\\\S]*?</iframe>\",\n          \"flags\": \"gi\",\n          \"description\": \"Detects full iframe blocks\",\n          \"redos_safe\": true\n        },\n        {\n          \"id\": \"xss-iframe\",\n          \"pattern\": \"<iframe[^>]*\",\n          \"flags\": \"gi\",\n          \"description\": \"Detects iframe tags (partial or unclosed)\",\n          \"redos_safe\": true\n        },\n        {\n          \"id\": \"xss-style-block\",\n          \"pattern\": \"<style[^>]*>[\\\\s\\\\S]*?</style>\",\n          \"flags\": \"gi\",\n          \"description\": \"Detects full style blocks (CSS injection, expression(), behavior: attacks)\",\n          \"redos_safe\": true\n        },\n        {\n          \"id\": \"xss-style-tag\",\n          \"pattern\": \"<style[\\\\s>][^>]*\",\n          \"flags\": \"gi\",\n          \"description\": \"Detects style tags (partial or unclosed). Requires whitespace or > after `style` so `<styled>` / `<StyledButton>` text is not flagged.\",\n          \"redos_safe\": true\n        },\n        {\n          \"id\": \"xss-object-block\",\n          \"pattern\": \"<object[^>]*>[\\\\s\\\\S]*?</object>\",\n          \"flags\": \"gi\",\n          \"description\": \"Detects full object blocks\",\n          \"redos_safe\": true\n        },\n        {\n          \"id\": \"xss-object\",\n          \"pattern\": \"<object[^>]*\",\n          \"flags\": \"gi\",\n          \"description\": \"Detects object tags (partial or unclosed)\",\n          \"redos_safe\": true\n        },\n        {\n          \"id\": \"xss-embed\",\n          \"pattern\": \"<embed[^>]*\",\n          \"flags\": \"gi\",\n          \"description\": \"Detects embed tags\",\n          \"redos_safe\": true\n        },\n        {\n          \"id\": \"xss-data-uri\",\n          \"pattern\": \"data\\\\s*:\\\\s*(?:text/html|image/svg)[^>\\\\s]*\",\n          \"flags\": \"gi\",\n          \"description\": \"Detects data: URIs with HTML or SVG content (avoids 'metadata' false positives)\",\n          \"redos_safe\": true\n        },\n        {\n          \"id\": \"xss-vbscript\",\n          \"pattern\": \"vbscript\\\\s*:\",\n          \"flags\": \"gi\",\n          \"description\": \"Detects vbscript: protocol\",\n          \"redos_safe\": true\n        },\n        {\n          \"id\": \"xss-url-encoded\",\n          \"pattern\": \"%3Cscript\",\n          \"flags\": \"gi\",\n          \"description\": \"Detects URL-encoded script tags\",\n          \"redos_safe\": true\n        },\n        {\n          \"id\": \"xss-svg-onload\",\n          \"pattern\": \"<svg[^>]*onload[^>]*>\",\n          \"flags\": \"gi\",\n          \"description\": \"Detects SVG with inline event handlers\",\n          \"redos_safe\": true\n        },\n        {\n          \"id\": \"xss-form-injection\",\n          \"pattern\": \"<form[\\\\s>][^>]*\",\n          \"flags\": \"gi\",\n          \"description\": \"Detects form tags used for phishing/credential harvesting via action= redirection\",\n          \"redos_safe\": true\n        },\n        {\n          \"id\": \"xss-meta-injection\",\n          \"pattern\": \"<meta[\\\\s>][^>]*\",\n          \"flags\": \"gi\",\n          \"description\": \"Detects meta tags used for http-equiv refresh redirects or CSP bypass\",\n          \"redos_safe\": true\n        },\n        {\n          \"id\": \"xss-base-injection\",\n          \"pattern\": \"<base[\\\\s>][^>]*\",\n          \"flags\": \"gi\",\n          \"description\": \"Detects base href hijacking — redirects all relative URLs to attacker domain\",\n          \"redos_safe\": true\n        },\n        {\n          \"id\": \"xss-link-injection\",\n          \"pattern\": \"<link[\\\\s>][^>]*\",\n          \"flags\": \"gi\",\n          \"description\": \"Detects link tag injection used for stylesheet or preload CSRF attacks\",\n          \"redos_safe\": true\n        },\n        {\n          \"id\": \"xss-css-expression\",\n          \"pattern\": \"expression\\\\s*\\\\(\",\n          \"flags\": \"gi\",\n          \"description\": \"Legacy IE CSS expression() in a style context, executes JS. Benchmark xss-style-expression.\",\n          \"redos_safe\": true\n        }\n      ],\n      \"encoding\": {\n        \"&\": \"&amp;\",\n        \"<\": \"&lt;\",\n        \">\": \"&gt;\",\n        \"\\\"\": \"&quot;\",\n        \"'\": \"&#x27;\"\n      }\n    },\n    \"sql_injection\": {\n      \"name\": \"SQL Injection\",\n      \"severity\": \"critical\",\n      \"owasp\": \"A03:2021\",\n      \"rules\": [\n        {\n          \"id\": \"sqli-keywords\",\n          \"pattern\": \"(\\\\bUNION\\\\s+(?:ALL\\\\s+)?SELECT\\\\b)|(\\\\b(?:DROP|TRUNCATE)\\\\s+(?:TABLE|DATABASE|INDEX|VIEW|SCHEMA)\\\\b)|(\\\\bINTO\\\\s+(?:OUTFILE|DUMPFILE)\\\\b)|(\\\\bATTACH\\\\s+DATABASE\\\\b)|(\\\\bCREATE\\\\s+(?:USER|FUNCTION|TRIGGER|PROCEDURE)\\\\b)|(\\\\bGRANT\\\\s+(?:ALL|SELECT|INSERT|UPDATE|DELETE)\\\\b)|(\\\\bSHUTDOWN\\\\b)|(\\\\bxp_cmdshell\\\\b)|(\\\\bsp_executesql\\\\b)\",\n          \"flags\": \"gi\",\n          \"description\": \"Multi-token SQL attack shapes (UNION SELECT, DROP TABLE, INTO OUTFILE, etc.) that real attackers use and benign users essentially never type. Replaces older bare-keyword rule that false-positived on 'please select an option', 'I'll update you tomorrow'. Benchmark FP class B3, 2026-06-07.\",\n          \"redos_safe\": true,\n          \"request_boundary_safe\": true\n        },\n        {\n          \"id\": \"sqli-comments\",\n          \"pattern\": \"((?:^|[^!])--(?:[\\\\s-]|$)|/\\\\*|\\\\*/)\",\n          \"flags\": \"g\",\n          \"description\": \"SQL comments. ANSI -- requires a following space / dash / end-of-string so it matches a real trailing comment (1=1--, -- -) but not CLI flags (--max-retries). C-style /* */ kept. MySQL # excluded (see sqli-comment-quote). FPR pass 2026-06-08. The -- must not be immediately preceded by '!' so HTML comments (<!-- -->) are not flagged as SQL.\",\n          \"redos_safe\": true\n        },\n        {\n          \"id\": \"sqli-boolean-numeric\",\n          \"pattern\": \"\\\\bOR\\\\s+\\\\d+\\\\s*=\\\\s*\\\\d+\",\n          \"flags\": \"gi\",\n          \"description\": \"Detects OR 1=1 style injection\",\n          \"redos_safe\": true\n        },\n        {\n          \"id\": \"sqli-boolean-string\",\n          \"pattern\": \"\\\\bOR\\\\s+['\\\"][^'\\\"]*['\\\"]\\\\s*=\\\\s*['\\\"][^'\\\"]*['\\\"]?\",\n          \"flags\": \"gi\",\n          \"description\": \"Detects OR 'a'='a' style injection\",\n          \"redos_safe\": true\n        },\n        {\n          \"id\": \"sqli-and-numeric\",\n          \"pattern\": \"\\\\bAND\\\\s+\\\\d+\\\\s*=\\\\s*\\\\d+\",\n          \"flags\": \"gi\",\n          \"description\": \"Detects AND 1=1 style injection\",\n          \"redos_safe\": true\n        },\n        {\n          \"id\": \"sqli-and-string\",\n          \"pattern\": \"\\\\bAND\\\\s+['\\\"][^'\\\"]*['\\\"]\\\\s*=\\\\s*['\\\"][^'\\\"]*['\\\"]?\",\n          \"flags\": \"gi\",\n          \"description\": \"Detects AND 'a'='a' style injection\",\n          \"redos_safe\": true\n        },\n        {\n          \"id\": \"sqli-sleep\",\n          \"pattern\": \"\\\\bSLEEP\\\\s*\\\\(\\\\s*\\\\d+\\\\s*\\\\)\",\n          \"flags\": \"gi\",\n          \"description\": \"Detects time-based blind SQLi via SLEEP\",\n          \"redos_safe\": true\n        },\n        {\n          \"id\": \"sqli-benchmark\",\n          \"pattern\": \"\\\\bBENCHMARK\\\\s*\\\\(\",\n          \"flags\": \"gi\",\n          \"description\": \"Detects time-based blind SQLi via BENCHMARK\",\n          \"redos_safe\": true\n        },\n        {\n          \"id\": \"sqli-pg-sleep\",\n          \"pattern\": \"\\\\bpg_sleep\\\\s*\\\\(\",\n          \"flags\": \"gi\",\n          \"description\": \"Detects time-based blind SQLi via PostgreSQL pg_sleep\",\n          \"redos_safe\": true\n        },\n        {\n          \"id\": \"sqli-waitfor-delay\",\n          \"pattern\": \"\\\\bWAITFOR\\\\s+DELAY\\\\b\",\n          \"flags\": \"gi\",\n          \"description\": \"Detects time-based blind SQLi via MSSQL WAITFOR DELAY\",\n          \"redos_safe\": true\n        },\n        {\n          \"id\": \"sqli-oracle-dbms-packages\",\n          \"pattern\": \"\\\\bDBMS_(?:LOCK|PIPE|UTILITY|XSLPROCESSOR|JAVA|OUTPUT|SCHEDULER)\\\\b\",\n          \"flags\": \"gi\",\n          \"description\": \"Detects Oracle DBMS_* package references used in time-based blind SQLi (DBMS_LOCK.SLEEP, DBMS_PIPE.RECEIVE_MESSAGE) and other Oracle stdlib abuse paths. Broad match — no legitimate user input contains these (improvements.md §1.1.e Q3).\",\n          \"redos_safe\": true\n        },\n        {\n          \"id\": \"sqli-hex-blob\",\n          \"pattern\": \"\\\\b0x[0-9a-fA-F]{16,}\\\\b\",\n          \"flags\": \"gi\",\n          \"description\": \"Long hex-encoded blob (8+ bytes) smuggling SQL past keyword filters; far longer than any hex color. Benchmark sql-hex-encoded.\",\n          \"redos_safe\": true,\n          \"request_boundary_safe\": true\n        },\n        {\n          \"id\": \"sqli-comment-quote\",\n          \"pattern\": \"'\\\\s*#\",\n          \"flags\": \"g\",\n          \"description\": \"Single-quote immediately followed by a MySQL # line comment (admin' #). Quote anchor avoids FP on bare # (hex colors, hashtags). Benchmark sql-comment-hash.\",\n          \"redos_safe\": true,\n          \"request_boundary_safe\": true\n        }\n      ]\n    },\n    \"nosql_injection\": {\n      \"name\": \"NoSQL Injection\",\n      \"severity\": \"critical\",\n      \"owasp\": \"A03:2021\",\n      \"rules\": [\n        {\n          \"id\": \"nosql-operators\",\n          \"pattern\": \"\\\\$(?:gt|gte|lt|lte|ne|eq|in|nin|and|or|not|nor|exists|type|regex|where|expr|mod|text|jsonSchema|function|accumulator|elemMatch|all|size|lookup|match|project|group|sort|limit|skip|unwind|addFields|replaceRoot)\\\\b\",\n          \"flags\": \"i\",\n          \"description\": \"Detects MongoDB operators\",\n          \"redos_safe\": true\n        }\n      ],\n      \"dangerous_keys\": [\n        \"$gt\",\n        \"$gte\",\n        \"$lt\",\n        \"$lte\",\n        \"$ne\",\n        \"$eq\",\n        \"$in\",\n        \"$nin\",\n        \"$and\",\n        \"$or\",\n        \"$not\",\n        \"$nor\",\n        \"$exists\",\n        \"$type\",\n        \"$regex\",\n        \"$where\",\n        \"$expr\",\n        \"$mod\",\n        \"$text\",\n        \"$jsonSchema\",\n        \"$function\",\n        \"$accumulator\",\n        \"$elemMatch\",\n        \"$all\",\n        \"$size\",\n        \"$lookup\",\n        \"$match\",\n        \"$project\",\n        \"$group\",\n        \"$sort\",\n        \"$limit\",\n        \"$skip\",\n        \"$unwind\",\n        \"$addFields\",\n        \"$replaceRoot\"\n      ]\n    },\n    \"command_injection\": {\n      \"name\": \"Command Injection\",\n      \"severity\": \"critical\",\n      \"owasp\": \"A03:2021\",\n      \"rules\": [\n        {\n          \"id\": \"cmdi-shell-chars\",\n          \"pattern\": \"[;&|]\\\\s*(?:(?:cat|ls|dir|rm|cp|mv|wget|curl|nc|ncat|bash|sh|zsh|ksh|chmod|chown|kill|ps|id|touch|ping|dig|su|head|tail|php|sed|whoami|nslookup|nmap|python3?|perl|ruby|node|eval|exec|sudo|telnet|ssh|ftp|tftp|scp|awk|xxd)\\\\b|base64(?:\\\\s|$))\",\n          \"flags\": \"g\",\n          \"description\": \"Shell command chained after a metacharacter (; cat, | nc, & curl). Replaces the bare [;&|`] rule, which flagged every semicolon / ampersand in code, URLs and prose. FPR pass 2026-06-08. base64 requires a trailing space or end-of-input so `;base64 -d` is caught but the data-URI `;base64,` MIME parameter is not (FP on inline images).\",\n          \"redos_safe\": true\n        },\n        {\n          \"id\": \"cmdi-command-substitution\",\n          \"pattern\": \"\\\\$\\\\(\",\n          \"flags\": \"g\",\n          \"description\": \"Detects command substitution syntax $( — paired form, fewer false positives than bare parens\",\n          \"redos_safe\": true\n        },\n        {\n          \"id\": \"cmdi-ifs-bypass\",\n          \"pattern\": \"\\\\$\\\\{IFS(?:%[^}]*)?\\\\}\",\n          \"flags\": \"g\",\n          \"description\": \"Detects POSIX shell IFS substitution like ${IFS} or ${IFS%??}. Attackers use this to inject spaces past metacharacter filters in commands like `;cat${IFS}/etc/passwd` (improvements.md §1.1.e Q5).\",\n          \"redos_safe\": true\n        },\n        {\n          \"id\": \"cmdi-control-chars\",\n          \"pattern\": \"%0[0-9a-fA-F]\",\n          \"flags\": \"gi\",\n          \"description\": \"Detects URL-encoded control characters (%00-%0F) including null, tab, vertical tab, form feed, LF, CR\",\n          \"redos_safe\": true\n        },\n        {\n          \"id\": \"cmdi-redirection\",\n          \"pattern\": \"(>>|<<<?)\",\n          \"flags\": \"g\",\n          \"description\": \"Append (>>) and here-doc (<<, <<<) redirection. The bare [<>] space form was dropped (matched 'a > b', 'RAM > 16GB'); redirect-to-file is covered by cmdi-redirect-syspath. FPR pass 2026-06-08.\",\n          \"redos_safe\": true\n        },\n        {\n          \"id\": \"cmdi-env-assign\",\n          \"pattern\": \"\\\\b(?:LD_PRELOAD|LD_LIBRARY_PATH|BASH_ENV|PYTHONPATH|PERL5LIB|DYLD_INSERT_LIBRARIES)\\\\s*=\",\n          \"flags\": \"gi\",\n          \"description\": \"Dangerous env-var assignment to smuggle code into a spawned process (LD_PRELOAD=). Benchmark cmd-env-var-smuggling.\",\n          \"redos_safe\": true\n        },\n        {\n          \"id\": \"cmdi-redirect-syspath\",\n          \"pattern\": \">\\\\s*/(?:etc|var|tmp|usr|bin|sbin|root|home|dev|proc|opt)\\\\b\",\n          \"flags\": \"g\",\n          \"description\": \"Shell output redirect to a system directory (> /var/www/shell.php). Anchored to system dirs to avoid math/text FP. Benchmark cmd-redirect-overwrite.\",\n          \"redos_safe\": true\n        },\n        {\n          \"id\": \"cmdi-newline-command\",\n          \"pattern\": \"[\\\\n\\\\r]\\\\s*(?:cat|ls|dir|rm|cp|mv|wget|curl|nc|ncat|bash|sh|zsh|ksh|chmod|chown|kill|ps|id|touch|ping|dig|su|head|tail|php|sed|whoami|nslookup|nmap|python3?|perl|ruby|node|eval|exec|sudo|telnet|ssh|ftp|tftp|scp|awk|xxd|base64)\\\\b\",\n          \"flags\": \"gi\",\n          \"description\": \"Newline followed by a shell command (host\\\\ncat /etc/passwd). Benchmark cmd-newline-injection.\",\n          \"redos_safe\": true\n        },\n        {\n          \"id\": \"cmdi-backtick-command\",\n          \"pattern\": \"`\\\\s*(?:cat|ls|dir|rm|cp|mv|wget|curl|nc|ncat|bash|sh|zsh|ksh|chmod|chown|kill|ps|id|touch|ping|dig|su|head|tail|php|sed|whoami|nslookup|nmap|python3?|perl|ruby|node|eval|exec|sudo|telnet|ssh|ftp|tftp|scp|awk|xxd|base64)\\\\b\",\n          \"flags\": \"gi\",\n          \"description\": \"Backtick command substitution wrapping a known command (`whoami`). Avoids FP on markdown inline code like `npm install`. FPR pass 2026-06-08.\",\n          \"redos_safe\": true\n        },\n        {\n          \"id\": \"cmdi-jndi-lookup\",\n          \"pattern\": \"\\\\$\\\\{jndi:\",\n          \"flags\": \"gi\",\n          \"description\": \"JNDI lookup used by Log4Shell, e.g. ${jndi:ldap://host/a}\",\n          \"redos_safe\": true\n        },\n        {\n          \"id\": \"cmdi-ssi-directive\",\n          \"pattern\": \"<!--\\\\s*#\\\\s*(?:exec|include|echo|config|fsize|flastmod|printenv)\\\\b\",\n          \"flags\": \"gi\",\n          \"description\": \"Server-side include (SSI) directive, e.g. <!--#exec cmd=...-->\",\n          \"redos_safe\": true\n        }\n      ]\n    },\n    \"path_traversal\": {\n      \"name\": \"Path Traversal\",\n      \"severity\": \"high\",\n      \"owasp\": \"A01:2021\",\n      \"rules\": [\n        {\n          \"id\": \"path-dotdot\",\n          \"pattern\": \"\\\\.\\\\./\",\n          \"flags\": \"g\",\n          \"description\": \"Detects ../ sequences\",\n          \"redos_safe\": true\n        },\n        {\n          \"id\": \"path-dotdot-backslash\",\n          \"pattern\": \"\\\\.\\\\.\\\\\\\\\",\n          \"flags\": \"g\",\n          \"description\": \"Detects ..\\\\ sequences\",\n          \"redos_safe\": true\n        },\n        {\n          \"id\": \"path-encoded\",\n          \"pattern\": \"%2e%2e\",\n          \"flags\": \"gi\",\n          \"description\": \"Detects URL-encoded traversal\",\n          \"redos_safe\": true\n        },\n        {\n          \"id\": \"path-double-encoded\",\n          \"pattern\": \"%252e\",\n          \"flags\": \"gi\",\n          \"description\": \"Detects double URL-encoded traversal\",\n          \"redos_safe\": true\n        },\n        {\n          \"id\": \"path-double-encoded-slash\",\n          \"pattern\": \"%252f\",\n          \"flags\": \"gi\",\n          \"description\": \"Detects double URL-encoded forward slash\",\n          \"redos_safe\": true\n        },\n        {\n          \"id\": \"path-dotdotslash-bypass\",\n          \"pattern\": \"\\\\.{2,}[/\\\\\\\\]{2,}\",\n          \"flags\": \"g\",\n          \"description\": \"Detects ....// and ....\\\\\\\\ bypass variants\",\n          \"redos_safe\": true\n        },\n        {\n          \"id\": \"path-null-byte\",\n          \"pattern\": \"%00\",\n          \"flags\": \"gi\",\n          \"description\": \"Detects URL-encoded null byte injection\",\n          \"redos_safe\": true\n        },\n        {\n          \"id\": \"path-null-byte-literal\",\n          \"pattern\": \"\\\\x00\",\n          \"flags\": \"g\",\n          \"description\": \"Detects literal NUL byte in path inputs\",\n          \"redos_safe\": true\n        },\n        {\n          \"id\": \"path-mixed-encoded\",\n          \"pattern\": \"\\\\.\\\\.%2[fF]\",\n          \"flags\": \"g\",\n          \"description\": \"Detects mixed encoding: literal `..` followed by URL-encoded slash (%2F). Benchmark B6 — Python had no coverage; Node had this pattern. 2026-06-07.\",\n          \"redos_safe\": true\n        },\n        {\n          \"id\": \"path-mixed-dot-encoded\",\n          \"pattern\": \"%2e\\\\.[\\\\\\\\/]\",\n          \"flags\": \"gi\",\n          \"description\": \"Detects half-encoded traversal: URL-encoded dot (%2e) followed by a literal dot and a slash (`%2e./`). Node caught this; Python/Go did not. Migration 2026-06-13.\",\n          \"redos_safe\": true\n        },\n        {\n          \"id\": \"path-mixed-dot-encoded-rev\",\n          \"pattern\": \"\\\\.%2e[\\\\\\\\/]\",\n          \"flags\": \"gi\",\n          \"description\": \"Detects half-encoded traversal: literal dot followed by URL-encoded dot (%2e) and a slash (`.%2e/`). Node caught this; Python/Go did not. Migration 2026-06-13.\",\n          \"redos_safe\": true\n        },\n        {\n          \"id\": \"path-overlong-utf8-dot\",\n          \"pattern\": \"%[Cc]0%[Aa][Ee]\",\n          \"flags\": \"g\",\n          \"description\": \"Detects overlong UTF-8 encoding of '.' (%C0%AE). Historic IIS/Apache decoder bypass. Real char `.` is %2E; overlong encoding only appears in evasion attempts. Benchmark B6 gap — neither SDK caught this before. 2026-06-07.\",\n          \"redos_safe\": true\n        },\n        {\n          \"id\": \"path-overlong-utf8-slash\",\n          \"pattern\": \"%[Cc]0%[Aa][Ff]\",\n          \"flags\": \"g\",\n          \"description\": \"Detects overlong UTF-8 encoding of forward slash (%C0%AF). Same IIS/Apache decoder bypass class as path-overlong-utf8-dot. Real slash is %2F; overlong form only appears in evasion. 2026-06-13.\",\n          \"redos_safe\": true\n        },\n        {\n          \"id\": \"path-windows-unc\",\n          \"pattern\": \"\\\\\\\\\\\\\\\\[A-Za-z0-9_.-]+\\\\\\\\\",\n          \"flags\": \"g\",\n          \"description\": \"Detects Windows UNC paths (\\\\\\\\\\\\\\\\server\\\\\\\\share) in user input. Legitimate web-app inputs never contain UNC references; attacker UNC payloads leak SMB auth or pull remote payloads. Benchmark B6. 2026-06-07.\",\n          \"redos_safe\": true\n        }\n      ]\n    },\n    \"prototype_pollution\": {\n      \"name\": \"Prototype Pollution\",\n      \"severity\": \"high\",\n      \"owasp\": \"A03:2021\",\n      \"languages\": [\n        \"javascript\",\n        \"typescript\"\n      ],\n      \"dangerous_keys\": [\n        \"__proto__\",\n        \"constructor\",\n        \"prototype\",\n        \"__definegetter__\",\n        \"__definesetter__\",\n        \"__lookupgetter__\",\n        \"__lookupsetter__\"\n      ]\n    },\n    \"ldap_injection\": {\n      \"name\": \"LDAP Injection\",\n      \"severity\": \"high\",\n      \"owasp\": \"A03:2021\",\n      \"rules\": [\n        {\n          \"id\": \"ldap-special\",\n          \"pattern\": \"[()\\\\\\\\*]\",\n          \"flags\": \"g\",\n          \"description\": \"Detects LDAP special characters. Broad rule for sanitization context only; NOT safe for request-boundary scanning (every parenthesised string trips it). Use 'ldap-injection-strict' below at request boundary.\",\n          \"redos_safe\": true\n        },\n        {\n          \"id\": \"ldap-injection-strict\",\n          \"pattern\": \"\\\\)\\\\s*\\\\(|\\\\*\\\\s*\\\\)\\\\s*\\\\(\",\n          \"flags\": \"g\",\n          \"description\": \"Detects attack-specific LDAP filter-break shapes ')(' and '*)('. Safe to wire into request-boundary scanners. Catches '*)(uid=*))(|(uid=*' style payloads.\",\n          \"redos_safe\": true,\n          \"request_boundary_safe\": true\n        },\n        {\n          \"id\": \"ldap-not-bypass\",\n          \"pattern\": \"\\\\)\\\\s*\\\\(\\\\s*!|&\\\\s*\\\\(\\\\s*!|\\\\|\\\\s*\\\\(\\\\s*!\",\n          \"flags\": \"g\",\n          \"description\": \"Detects LDAP NOT-operator bypass shapes ')(!', '&(!', and '|(!'. Catches injections where attacker appends a NOT clause to enumerate or exclude specific entries, e.g. '*)(uid=*)(!(uid=admin))'. Companion to ldap-injection-strict; together they cover the OR-then-NOT enumeration corpus that legitimate LDAP queries never produce. (improvements.md Q8.)\",\n          \"redos_safe\": true,\n          \"request_boundary_safe\": true\n        },\n        {\n          \"id\": \"ldap-null-byte\",\n          \"pattern\": \"\\\\\\\\00|\\\\x00\",\n          \"flags\": \"g\",\n          \"description\": \"LDAP null-byte truncation (admin\\\\00) used to terminate a filter early and bypass appended constraints. Benchmark ldap-null-byte-truncate.\",\n          \"redos_safe\": true,\n          \"request_boundary_safe\": true\n        }\n      ]\n    },\n    \"xpath_injection\": {\n      \"name\": \"XPath Injection\",\n      \"severity\": \"high\",\n      \"owasp\": \"A03:2021\",\n      \"rules\": [\n        {\n          \"id\": \"xpath-injection-strict\",\n          \"pattern\": \"('\\\\s*(or|and)\\\\s*'|\\\"\\\\s*(or|and)\\\\s*\\\"|\\\\)\\\\s*(or|and)\\\\s*\\\\(|\\\\|\\\\s*/)\",\n          \"flags\": \"gi\",\n          \"description\": \"Detects XPath injection patterns: boolean-injection (' or ' / \\\" or \\\"), function-arity tampering with closing+opening parens around or/and, and union operator before path step. Request-boundary safe.\",\n          \"redos_safe\": true,\n          \"request_boundary_safe\": true\n        },\n        {\n          \"id\": \"xpath-blind-substring\",\n          \"pattern\": \"\\\\bsubstring\\\\s*\\\\(\\\\s*name\\\\s*\\\\(|\\\\bstring-length\\\\s*\\\\(|\\\\bcount\\\\s*\\\\(\\\\s*/\",\n          \"flags\": \"gi\",\n          \"description\": \"Blind XPath extraction via substring(name()), string-length(), count(/...). Benchmark xpath-blind-substring.\",\n          \"redos_safe\": true,\n          \"request_boundary_safe\": true\n        }\n      ]\n    },\n    \"email_header_injection\": {\n      \"name\": \"Email Header Injection (SMTP CRLF)\",\n      \"severity\": \"high\",\n      \"owasp\": \"A03:2021\",\n      \"rules\": [\n        {\n          \"id\": \"email-header-smtp-keyword\",\n          \"pattern\": \"(\\\\r\\\\n|\\\\r|\\\\n)\\\\s*(bcc|cc|to|from|subject|reply-to|return-path|content-type|x-mailer)\\\\s*:\",\n          \"flags\": \"gi\",\n          \"description\": \"Detects SMTP header injection: CR/LF followed by a known SMTP header keyword. Narrow enough for request-boundary scanning because legitimate user input rarely contains '\\\\nBcc:' verbatim.\",\n          \"redos_safe\": true,\n          \"request_boundary_safe\": true\n        },\n        {\n          \"id\": \"email-header-bare-newline\",\n          \"pattern\": \"(\\\\r\\\\n|\\\\r|\\\\n)\\\\s*[a-z][a-z0-9-]{0,40}\\\\s*:\",\n          \"flags\": \"gi\",\n          \"description\": \"Detects bare CR/LF followed by ANY plausible header keyword (not just the SMTP allowlist). Catches MTAs that accept bare LF or bare CR as a header separator (qmail, sendmail variants), where attacker bypasses the strict keyword list by injecting a non-SMTP-keyword header (X-Custom, Authentication-Results, DKIM-Signature, ...). Companion to email-header-smtp-keyword; together they cover the bypass class. (improvements.md Q10.)\",\n          \"redos_safe\": true,\n          \"request_boundary_safe\": true\n        }\n      ]\n    },\n    \"ssti\": {\n      \"name\": \"Server-Side Template Injection (SSTI)\",\n      \"severity\": \"critical\",\n      \"owasp\": \"A03:2021\",\n      \"rules\": [\n        {\n          \"id\": \"ssti-jinja2-twig\",\n          \"pattern\": \"\\\\{\\\\{.*?\\\\}\\\\}\",\n          \"flags\": \"g\",\n          \"description\": \"Detects Jinja2/Twig/Nunjucks template expressions ({{ ... }})\",\n          \"redos_safe\": true\n        },\n        {\n          \"id\": \"ssti-freemarker-spring\",\n          \"pattern\": \"\\\\$\\\\{.*?\\\\}\",\n          \"pattern_safe\": \"\\\\$\\\\{[^}]*[?!()*+\\\\-/][^}]*\\\\}\",\n          \"flags\": \"g\",\n          \"description\": \"Detects Freemarker/Thymeleaf/Spring EL expressions. Detection uses broad pattern; sanitization uses pattern_safe which requires operators/method-calls to avoid false-positives on JS template literals like ${name}.\",\n          \"redos_safe\": true\n        },\n        {\n          \"id\": \"ssti-erb-ejs\",\n          \"pattern\": \"<%[=\\\\-]?.*?%>\",\n          \"flags\": \"gs\",\n          \"description\": \"Detects ERB/EJS template tags (<%= ... %>, <% ... %>)\",\n          \"redos_safe\": true\n        },\n        {\n          \"id\": \"ssti-pug-jade\",\n          \"pattern\": \"#\\\\{.*?\\\\}\",\n          \"pattern_safe\": \"#\\\\{[^}]*[?!()*+\\\\-/][^}]*\\\\}\",\n          \"flags\": \"g\",\n          \"description\": \"Detects Pug/Jade/Slim template expressions. Detection uses broad pattern; sanitization uses pattern_safe to avoid false-positives on Ruby/Pug output like #{name}.\",\n          \"redos_safe\": true\n        },\n        {\n          \"id\": \"ssti-python-class-chain\",\n          \"pattern\": \"__(?:class|mro|subclasses|globals|builtins|import)__\",\n          \"flags\": \"gi\",\n          \"description\": \"Detects Python sandbox escape via dunder attributes\",\n          \"redos_safe\": true\n        },\n        {\n          \"id\": \"ssti-config-leak\",\n          \"pattern\": \"\\\\{\\\\{\\\\s*config[.\\\\[]\",\n          \"flags\": \"gi\",\n          \"description\": \"Detects Jinja2 config/settings leak attempts\",\n          \"redos_safe\": true\n        },\n        {\n          \"id\": \"ssti-jinja2-functions\",\n          \"pattern\": \"\\\\{\\\\{\\\\s*(?:self|request|lipsum|cycler|joiner|namespace|range)\\\\b\",\n          \"flags\": \"gi\",\n          \"description\": \"Detects Jinja2 built-in object/function access\",\n          \"redos_safe\": true\n        },\n        {\n          \"id\": \"ssti-velocity-ognl\",\n          \"pattern\": \"#set\\\\s*\\\\(\\\\s*\\\\$|#foreach\\\\s*\\\\(\\\\s*\\\\$|\\\\$\\\\w+\\\\.(?:exec|getClass|getRuntime|getMethod|invoke)\\\\b\",\n          \"flags\": \"gi\",\n          \"description\": \"Velocity #set/#foreach directives and OGNL/Velocity method calls. Benchmark ssti-velocity-runtime.\",\n          \"redos_safe\": true\n        }\n      ]\n    },\n    \"xml_injection\": {\n      \"name\": \"XML/XXE Injection\",\n      \"severity\": \"critical\",\n      \"owasp\": \"A03:2021\",\n      \"rules\": [\n        {\n          \"id\": \"xxe-doctype\",\n          \"pattern\": \"<!DOCTYPE\",\n          \"flags\": \"gi\",\n          \"description\": \"Detects DOCTYPE declarations\",\n          \"redos_safe\": true\n        },\n        {\n          \"id\": \"xxe-entity\",\n          \"pattern\": \"<!ENTITY\",\n          \"flags\": \"gi\",\n          \"description\": \"Detects ENTITY declarations\",\n          \"redos_safe\": true\n        },\n        {\n          \"id\": \"xxe-system\",\n          \"pattern\": \"SYSTEM\\\\s+[\\\"']\",\n          \"flags\": \"gi\",\n          \"description\": \"Detects SYSTEM references\",\n          \"redos_safe\": true\n        }\n      ]\n    }\n  },\n  \"security_headers\": {\n    \"Content-Security-Policy\": \"default-src 'self'; script-src 'self'; style-src 'self' 'unsafe-inline'; img-src 'self' data: https:; font-src 'self'; object-src 'none'; frame-ancestors 'none';\",\n    \"X-Content-Type-Options\": \"nosniff\",\n    \"X-Frame-Options\": \"DENY\",\n    \"X-XSS-Protection\": \"0\",\n    \"Strict-Transport-Security\": \"max-age=31536000; includeSubDomains\",\n    \"Referrer-Policy\": \"strict-origin-when-cross-origin\",\n    \"Permissions-Policy\": \"geolocation=(), microphone=(), camera=()\",\n    \"X-Permitted-Cross-Domain-Policies\": \"none\",\n    \"Cache-Control\": \"no-store, no-cache, must-revalidate, proxy-revalidate\",\n    \"Pragma\": \"no-cache\",\n    \"Expires\": \"0\"\n  },\n  \"rate_limiting\": {\n    \"default_max\": 100,\n    \"default_window_ms\": 60000,\n    \"headers\": {\n      \"limit\": \"X-RateLimit-Limit\",\n      \"remaining\": \"X-RateLimit-Remaining\",\n      \"reset\": \"X-RateLimit-Reset\"\n    }\n  },\n  \"sensitive_keys\": [\n    \"password\",\n    \"passwd\",\n    \"pwd\",\n    \"secret\",\n    \"token\",\n    \"apikey\",\n    \"api_key\",\n    \"apiKey\",\n    \"auth\",\n    \"authorization\",\n    \"credit_card\",\n    \"creditcard\",\n    \"cc\",\n    \"ssn\",\n    \"social_security\",\n    \"private_key\",\n    \"privateKey\",\n    \"access_token\",\n    \"accessToken\",\n    \"refresh_token\",\n    \"refreshToken\",\n    \"bearer\",\n    \"jwt\",\n    \"session\",\n    \"cookie\",\n    \"x-api-key\",\n    \"x-auth-token\",\n    \"credentials\"\n  ],\n  \"validation\": {\n    \"email\": \"^[^\\\\s@]+@[^\\\\s@]+\\\\.[^\\\\s@]+$\",\n    \"url\": \"^https?://[^\\\\s/$.?#].[^\\\\s]*$\",\n    \"uuid\": \"^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$\",\n    \"ipv4\": \"^(?:(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\\\\.){3}(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)$\"\n  }\n}\n","/**\n * @module @arcis/node/core/patterns-loader\n *\n * Loads the shared security regex patterns from the bundled\n * `data/patterns.json` (a copy of the canonical `packages/core/patterns.json`,\n * kept byte-identical by the CI data-sync-check). This is the Node counterpart\n * of Go's `sanitizers/loader.go` and Python's `core/constants.load_patterns` +\n * `_compile_rules`.\n *\n * Why this exists: pre-migration, Node hardcoded every regex in `constants.ts`,\n * so each pattern edit was a manual dual-write against patterns.json (which\n * Python + Go already load at runtime). That is a Pattern 2 violation\n * (Shared Pattern Repository). Sourcing the arrays from patterns.json here\n * makes patterns.json the single source for all three SDKs.\n *\n * The JSON is a static `import`, so tsup inlines it into the CJS + ESM bundles\n * at build time (same as `bot-detection.ts` does with `bot-patterns.json`); no\n * runtime filesystem access. resolveJsonModule is already enabled in tsconfig.\n */\n\nimport patternsData from '../data/patterns.json';\n\ninterface PatternRule {\n  id: string;\n  pattern: string;\n  pattern_safe?: string;\n  flags?: string;\n}\n\ninterface PatternCategory {\n  rules?: PatternRule[];\n  dangerous_keys?: string[];\n}\n\ninterface PatternsSpec {\n  version: string;\n  patterns: Record<string, PatternCategory>;\n}\n\nconst spec = patternsData as unknown as PatternsSpec;\n\n/** Valid JavaScript RegExp flags. patterns.json uses g/i/m; anything else is dropped. */\nconst VALID_JS_FLAGS = new Set(['g', 'i', 'm', 's', 'u', 'y']);\n\nfunction normalizeFlags(flags: string | undefined): string {\n  if (!flags) return '';\n  let out = '';\n  for (const ch of flags) {\n    if (VALID_JS_FLAGS.has(ch) && !out.includes(ch)) out += ch;\n  }\n  return out;\n}\n\n/**\n * Compile every rule in a patterns.json category into a RegExp array, in file\n * order. Prefers the ReDoS-safe `pattern_safe` variant when present (parity\n * with Go's compileCategory / Python's _compile_rules). A category with no\n * rules returns an empty array.\n */\nexport function compileCategory(category: string): RegExp[] {\n  const cat = spec.patterns[category];\n  if (!cat?.rules) return [];\n  const out: RegExp[] = [];\n  for (const rule of cat.rules) {\n    const raw = rule.pattern_safe || rule.pattern;\n    if (!raw) continue;\n    out.push(new RegExp(raw, normalizeFlags(rule.flags)));\n  }\n  return out;\n}\n\n/**\n * Compile a single named rule from a category into one RegExp, or undefined if\n * the rule id is absent. Used where Node consumes a single pattern rather than\n * a list (e.g. the string-form NoSQL operator check).\n */\nexport function compileRule(category: string, id: string, flags?: string): RegExp | undefined {\n  const rule = spec.patterns[category]?.rules?.find((r) => r.id === id);\n  if (!rule) return undefined;\n  const raw = rule.pattern_safe || rule.pattern;\n  if (!raw) return undefined;\n  return new RegExp(raw, normalizeFlags(flags ?? rule.flags));\n}\n\n/**\n * Return the `dangerous_keys` list for a category (e.g. `nosql_injection`,\n * `prototype_pollution`), or an empty array if the category has none.\n */\nexport function dangerousKeysFor(category: string): string[] {\n  return spec.patterns[category]?.dangerous_keys ?? [];\n}\n\n/** The version string from the bundled patterns.json. Used by tests/diagnostics. */\nexport const PATTERNS_VERSION = spec.version;\n","/**\n * @module @arcis/node/core/constants\n * Named constants for Arcis - no magic numbers\n */\n\nimport { compileCategory, compileRule, dangerousKeysFor } from './patterns-loader';\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 (sourced from patterns.json)\n// =============================================================================\n\n/**\n * XSS patterns, compiled from the shared `patterns.json` `xss` category.\n *\n * Both detection (detectXss) and removal (sanitizeXss) iterate the same rule\n * list: the rules are precise capture patterns (full tag / attribute / protocol)\n * so they double as removal targets, and patterns.json file order keeps every\n * block rule (e.g. `<script>...</script>`) ahead of its bare-tag counterpart so\n * removal strips the larger match first. Pre-migration these were two hardcoded\n * arrays (a broad detect set + a precise remove set); single-sourcing them here\n * ends the dual-write against patterns.json and converges Node onto the same\n * detection Python + Go already ship (Pattern 2 + Pattern 7).\n */\nexport const XSS_PATTERNS = compileCategory('xss');\n\n/** Removal patterns for sanitizeXss(): the same patterns.json `xss` rules.\n *  A separate compiled array so its RegExp lastIndex state is independent of\n *  the detection pass. */\nexport const XSS_REMOVE_PATTERNS = compileCategory('xss');\n\n// =============================================================================\n// SQL INJECTION PATTERNS (sourced from patterns.json)\n// =============================================================================\n/** Compiled from the shared `patterns.json` `sql_injection` category. The\n *  quoted-boolean rules use RE2-safe `['\"]...['\"]` (no backreference) since\n *  patterns.json is also consumed by Go's RE2 engine; validated equivalent to\n *  the former backreference forms on the O'Brien / tautology corpus. */\nexport const SQL_PATTERNS = compileCategory('sql_injection');\n\n// =============================================================================\n// PATH TRAVERSAL PATTERNS (sourced from patterns.json)\n// =============================================================================\n/** Compiled from the shared `patterns.json` `path_traversal` category. */\nexport const PATH_PATTERNS = compileCategory('path_traversal');\n\n// =============================================================================\n// COMMAND INJECTION PATTERNS (sourced from patterns.json)\n// =============================================================================\n/** Compiled from the shared `patterns.json` `command_injection` category. */\nexport const COMMAND_PATTERNS = compileCategory('command_injection');\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(dangerousKeysFor('prototype_pollution'));\n\n/** MongoDB operators to block, from `patterns.json` nosql_injection.dangerous_keys. */\nexport const NOSQL_DANGEROUS_KEYS = new Set(dangerousKeysFor('nosql_injection'));\n\n/**\n * String-form NoSQL operator detection (block-mode scanThreats).\n *\n * NOSQL_DANGEROUS_KEYS catches operators that arrive as OBJECT KEYS\n * (`{\"$gt\": \"\"}`). But MongoDB operators also bypass as STRING VALUES —\n * query params like `?username[$ne]=1` arrive as the literal string\n * `$ne` before the body parser ever builds an object, and mongo-shell\n * payloads (`$where: '1==1'`) are plain strings. Node previously had no\n * string-level NoSQL check, so GoTestWAF scored NoSQL at 0% while Python\n * (which loads the shared `nosql-operators` rule) caught these. This\n * closes that Pattern-7 parity gap.\n *\n * Sourced from the `nosql-operators` rule in patterns.json. The trailing\n * `\\b` word boundary keeps `$invoice`/`$order`/`$index` from matching\n * `$in`/`$or` (a false-positive class the un-bounded rule had).\n */\nconst nosqlStringRule = compileRule('nosql_injection', 'nosql-operators');\nif (!nosqlStringRule) {\n  throw new Error('arcis: nosql-operators rule missing from patterns.json');\n}\nexport const NOSQL_STRING_PATTERN = nosqlStringRule;\n\n/**\n * Identity/auth field names that must hold a scalar value. A field here\n * carrying an array or object is a NoSQL type-juggling operator-injection\n * shape (e.g. {\"username\":[\"admin\"]}). v1.7 nosql-type-juggle.\n */\nexport const AUTH_FIELDS = new Set([\n  'username', 'user', 'userid', 'user_id', 'login', 'email',\n  'password', 'pass', 'passwd', 'pwd', 'token', 'apikey', 'api_key',\n  'secret', 'otp', 'pin',\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  {\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\": \"SECURITY_SCANNER\",\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\": \"SECURITY_SCANNER\",\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\": \"SEARCH_ENGINE\",\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\": \"SCRAPER\",\n    \"patterns\": [\n      \"[cC]laude[bB]ot\"\n    ],\n    \"forbidden\": []\n  },\n  {\n    \"id\": \"ext-meta-externalagent\",\n    \"name\": \"meta-externalagent\",\n    \"category\": \"SCRAPER\",\n    \"patterns\": [\n      \"meta-externalagent\\\\/\"\n    ],\n    \"forbidden\": []\n  },\n  {\n    \"id\": \"ext-meta-externalfetcher\",\n    \"name\": \"meta-externalfetcher\",\n    \"category\": \"SCRAPER\",\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\": \"SEARCH_ENGINE\",\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\": \"SCRAPER\",\n    \"patterns\": [\n      \"ALittle Client\"\n    ],\n    \"forbidden\": []\n  },\n  {\n    \"id\": \"ext-aliyunsecbot\",\n    \"name\": \"aliyunsecbot\",\n    \"category\": \"SCRAPER\",\n    \"patterns\": [\n      \"AliyunSecBot\"\n    ],\n    \"forbidden\": []\n  },\n  {\n    \"id\": \"ext-claude-web\",\n    \"name\": \"claude-web\",\n    \"category\": \"SCRAPER\",\n    \"patterns\": [\n      \"Claude-Web\"\n    ],\n    \"forbidden\": []\n  },\n  {\n    \"id\": \"ext-google-extended\",\n    \"name\": \"google-extended\",\n    \"category\": \"SCRAPER\",\n    \"patterns\": [\n      \"Google-Extended\"\n    ],\n    \"forbidden\": []\n  },\n  {\n    \"id\": \"ext-serankingbacklinksbot\",\n    \"name\": \"serankingbacklinksbot\",\n    \"category\": \"SEARCH_ENGINE\",\n    \"patterns\": [\n      \"SERankingBacklinksBot\"\n    ],\n    \"forbidden\": []\n  },\n  {\n    \"id\": \"ext-cmschecker\",\n    \"name\": \"cmschecker\",\n    \"category\": \"SEARCH_ENGINE\",\n    \"patterns\": [\n      \"CMSChecker\"\n    ],\n    \"forbidden\": []\n  },\n  {\n    \"id\": \"ext-wayback\",\n    \"name\": \"wayback\",\n    \"category\": \"SCRAPER\",\n    \"patterns\": [\n      \"Wayback\"\n    ],\n    \"forbidden\": []\n  },\n  {\n    \"id\": \"ext-playwright\",\n    \"name\": \"playwright\",\n    \"category\": \"SCRAPER\",\n    \"patterns\": [\n      \"Playwright\"\n    ],\n    \"forbidden\": []\n  },\n  {\n    \"id\": \"ext-puppeteer\",\n    \"name\": \"puppeteer\",\n    \"category\": \"SCRAPER\",\n    \"patterns\": [\n      \"Puppeteer\"\n    ],\n    \"forbidden\": []\n  },\n  {\n    \"id\": \"ext-selenium\",\n    \"name\": \"selenium\",\n    \"category\": \"SCRAPER\",\n    \"patterns\": [\n      \"Selenium\"\n    ],\n    \"forbidden\": []\n  },\n  {\n    \"id\": \"ext-nikto\",\n    \"name\": \"nikto\",\n    \"category\": \"SECURITY_SCANNER\",\n    \"patterns\": [\n      \"Nikto\"\n    ],\n    \"forbidden\": []\n  },\n  {\n    \"id\": \"ext-sqlmap\",\n    \"name\": \"sqlmap\",\n    \"category\": \"SECURITY_SCANNER\",\n    \"patterns\": [\n      \"sqlmap\"\n    ],\n    \"forbidden\": []\n  },\n  {\n    \"id\": \"ext-zmeu\",\n    \"name\": \"zmeu\",\n    \"category\": \"SECURITY_SCANNER\",\n    \"patterns\": [\n      \"ZmEu\"\n    ],\n    \"forbidden\": []\n  },\n  {\n    \"id\": \"ext-masscan\",\n    \"name\": \"masscan\",\n    \"category\": \"SECURITY_SCANNER\",\n    \"patterns\": [\n      \"masscan\"\n    ],\n    \"forbidden\": []\n  },\n  {\n    \"id\": \"ext-wpscan\",\n    \"name\": \"wpscan\",\n    \"category\": \"SECURITY_SCANNER\",\n    \"patterns\": [\n      \"WPScan\"\n    ],\n    \"forbidden\": []\n  },\n  {\n    \"id\": \"ext-aacunetix\",\n    \"name\": \"aacunetix\",\n    \"category\": \"SECURITY_SCANNER\",\n    \"patterns\": [\n      \"[aA]cunetix\"\n    ],\n    \"forbidden\": []\n  },\n  {\n    \"id\": \"ext-nessus\",\n    \"name\": \"nessus\",\n    \"category\": \"SECURITY_SCANNER\",\n    \"patterns\": [\n      \"Nessus\"\n    ],\n    \"forbidden\": []\n  },\n  {\n    \"id\": \"ext-ddirbbuster\",\n    \"name\": \"ddirbbuster\",\n    \"category\": \"SECURITY_SCANNER\",\n    \"patterns\": [\n      \"[dD]ir[Bb]uster\"\n    ],\n    \"forbidden\": []\n  },\n  {\n    \"id\": \"ext-colly\",\n    \"name\": \"colly\",\n    \"category\": \"SCRAPER\",\n    \"patterns\": [\n      \"colly\"\n    ],\n    \"forbidden\": []\n  },\n  {\n    \"id\": \"ext-mmechanize\",\n    \"name\": \"mmechanize\",\n    \"category\": \"SCRAPER\",\n    \"patterns\": [\n      \"[mM]echanize\"\n    ],\n    \"forbidden\": []\n  },\n  {\n    \"id\": \"ext-airaiscanning\",\n    \"name\": \"airaiscanning\",\n    \"category\": \"SCRAPER\",\n    \"patterns\": [\n      \"air\\\\.ai\\\\/scanning\"\n    ],\n    \"forbidden\": []\n  },\n  {\n    \"id\": \"ext-asnriskscorer\",\n    \"name\": \"asnriskscorer\",\n    \"category\": \"SCRAPER\",\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\": \"SECURITY_SCANNER\",\n    \"patterns\": [\n      \"l9scan\"\n    ],\n    \"forbidden\": []\n  },\n  {\n    \"id\": \"ext-slaccalebot\",\n    \"name\": \"slaccalebot\",\n    \"category\": \"SEARCH_ENGINE\",\n    \"patterns\": [\n      \"SlaccaleBot\"\n    ],\n    \"forbidden\": []\n  },\n  {\n    \"id\": \"ext-customasynchttpclient\",\n    \"name\": \"customasynchttpclient\",\n    \"category\": \"SCRAPER\",\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\": \"SCRAPER\",\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\": \"SCRAPER\",\n    \"patterns\": [\n      \"MistralAI-User\"\n    ],\n    \"forbidden\": []\n  },\n  {\n    \"id\": \"ext-webzio\",\n    \"name\": \"webzio\",\n    \"category\": \"SEARCH_ENGINE\",\n    \"patterns\": [\n      \"webzio\"\n    ],\n    \"forbidden\": []\n  },\n  {\n    \"id\": \"ext-newsai\",\n    \"name\": \"newsai\",\n    \"category\": \"SCRAPER\",\n    \"patterns\": [\n      \"newsai\\\\/\"\n    ],\n    \"forbidden\": []\n  },\n  {\n    \"id\": \"arcis-nuclei\",\n    \"category\": \"SECURITY_SCANNER\",\n    \"name\": \"nuclei\",\n    \"patterns\": [\n      \"Nuclei\"\n    ],\n    \"forbidden\": []\n  },\n  {\n    \"id\": \"ext-openvas\",\n    \"category\": \"SECURITY_SCANNER\",\n    \"name\": \"openvas\",\n    \"patterns\": [\n      \"OpenVAS\"\n    ],\n    \"forbidden\": []\n  },\n  {\n    \"id\": \"ext-ffuf\",\n    \"category\": \"SECURITY_SCANNER\",\n    \"name\": \"ffuf\",\n    \"patterns\": [\n      \"Fuzz Faster U Fool\"\n    ],\n    \"forbidden\": []\n  },\n  {\n    \"id\": \"ext-nasl\",\n    \"category\": \"SECURITY_SCANNER\",\n    \"name\": \"nasl\",\n    \"patterns\": [\n      \".nasl\"\n    ],\n    \"forbidden\": []\n  },\n  {\n    \"id\": \"ext-feroxbuster\",\n    \"category\": \"SECURITY_SCANNER\",\n    \"name\": \"feroxbuster\",\n    \"patterns\": [\n      \"feroxbuster\"\n    ],\n    \"forbidden\": []\n  },\n  {\n    \"id\": \"ext-gobuster\",\n    \"category\": \"SECURITY_SCANNER\",\n    \"name\": \"gobuster\",\n    \"patterns\": [\n      \"gobuster\"\n    ],\n    \"forbidden\": []\n  },\n  {\n    \"id\": \"ext-arachni\",\n    \"category\": \"SECURITY_SCANNER\",\n    \"name\": \"arachni\",\n    \"patterns\": [\n      \"Arachni\"\n    ],\n    \"forbidden\": []\n  },\n  {\n    \"id\": \"ext-w3af\",\n    \"category\": \"SECURITY_SCANNER\",\n    \"name\": \"w3af\",\n    \"patterns\": [\n      \"w3af\"\n    ],\n    \"forbidden\": []\n  },\n  {\n    \"id\": \"ext-skipfish\",\n    \"category\": \"SECURITY_SCANNER\",\n    \"name\": \"skipfish\",\n    \"patterns\": [\n      \"skipfish\"\n    ],\n    \"forbidden\": []\n  },\n  {\n    \"id\": \"ext-netsparker\",\n    \"category\": \"SECURITY_SCANNER\",\n    \"name\": \"netsparker\",\n    \"patterns\": [\n      \"Netsparker\"\n    ],\n    \"forbidden\": []\n  },\n  {\n    \"id\": \"ext-whatweb\",\n    \"category\": \"SECURITY_SCANNER\",\n    \"name\": \"whatweb\",\n    \"patterns\": [\n      \"WhatWeb\"\n    ],\n    \"forbidden\": []\n  },\n  {\n    \"id\": \"ext-wfuzz\",\n    \"category\": \"SECURITY_SCANNER\",\n    \"name\": \"wfuzz\",\n    \"patterns\": [\n      \"Wfuzz\"\n    ],\n    \"forbidden\": []\n  },\n  {\n    \"id\": \"ext-qualys\",\n    \"category\": \"SECURITY_SCANNER\",\n    \"name\": \"qualys\",\n    \"patterns\": [\n      \"Qualys\"\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  | 'SECURITY_SCANNER'\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// Snapshot of the bundled set, captured before any cloud merge, so tests can\n// restore a clean baseline.\nconst BUNDLED_PATTERNS: BotPattern[] = [...BOT_PATTERNS];\n\n/**\n * Merge cloud-fetched bot-corpus entries into the live pattern set (Phase C\n * cloud refresh). New ids are appended; existing ids are replaced in place so\n * a curated correction overrides the bundled entry. An entry with an\n * uncompilable pattern is skipped — this never throws into the refresh path\n * (fail-open). Process-global by design: the corpus is a singleton, same as the\n * bundled import. Returns the number of entries merged.\n */\nexport function mergeBotPatterns(entries: BotPatternData[]): number {\n  let merged = 0;\n  for (const entry of entries) {\n    try {\n      const compiled: BotPattern = {\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      const idx = BOT_PATTERNS.findIndex((b) => b.id === entry.id);\n      if (idx >= 0) BOT_PATTERNS[idx] = compiled;\n      else BOT_PATTERNS.push(compiled);\n      merged += 1;\n    } catch {\n      // skip an entry with a bad regex; never break the refresh\n    }\n  }\n  return merged;\n}\n\n/** Test hook — restore the bundled corpus, dropping any cloud-merged entries. */\nexport function _resetBotPatternsForTest(): void {\n  BOT_PATTERNS.length = 0;\n  BOT_PATTERNS.push(...BUNDLED_PATTERNS);\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/sensitive-paths\n * v1.7 W2 wire-up. Blocks well-known scanner probe paths.\n *\n * Sensitive paths fall into three buckets and almost never have a\n * legitimate reason to be served by a typical app:\n *   1. Dotfile / VCS leaks   `/.env`, `/.git/*`, `/.svn/*`, `/.aws/`, ...\n *   2. PHP/Wordpress probes  `/wp-admin`, `/wp-login.php`, `/phpmyadmin`, ...\n *   3. Diagnostic endpoints  `/server-status`, `/phpinfo.php`, `/info.php`, ...\n *\n * Apps with legitimate routes that overlap (an actual WordPress site,\n * a custom `/admin` panel) opt out via `arcis({ scannerPaths: false })`\n * or pass a custom matcher list.\n */\n\nimport type { Request, Response, NextFunction, RequestHandler } from 'express';\n\nexport interface ScannerPathsOptions {\n  /** HTTP status for blocked probes. Default: 403 */\n  statusCode?: number;\n  /** Error message for blocked probes. Default: 'Access denied.' */\n  message?: string;\n  /**\n   * Custom matchers (overrides the default list entirely). Each entry\n   * is matched against `req.path` with `.test()`. To EXTEND the default\n   * list use `[...SENSITIVE_PATH_PATTERNS, /your-extra/]`.\n   */\n  patterns?: RegExp[];\n}\n\n/**\n * Default sensitive-path patterns. Each is a case-insensitive prefix\n * match anchored to the start of the request path. Conservative on\n * shapes that have any reasonable legit use; aggressive on dotfile and\n * VCS-leak paths that should never be served.\n */\nexport const SENSITIVE_PATH_PATTERNS: ReadonlyArray<RegExp> = Object.freeze([\n  // Dotfile / VCS leaks — should never be served on any app.\n  /^\\/\\.env(\\.|\\/|$)/i,\n  /^\\/\\.git(\\/|$)/i,\n  /^\\/\\.svn(\\/|$)/i,\n  /^\\/\\.hg(\\/|$)/i,\n  /^\\/\\.bzr(\\/|$)/i,\n  /^\\/\\.aws(\\/|$)/i,\n  /^\\/\\.ssh(\\/|$)/i,\n  /^\\/\\.htaccess$/i,\n  /^\\/\\.htpasswd$/i,\n  /^\\/\\.npmrc$/i,\n  /^\\/\\.dockerenv$/i,\n\n  // WordPress + PHP probes — legit only on those platforms.\n  /^\\/wp-admin(\\/|$)/i,\n  /^\\/wp-login\\.php$/i,\n  /^\\/wp-config\\.php$/i,\n  /^\\/wordpress\\/wp-(admin|login)/i,\n  /^\\/xmlrpc\\.php$/i,\n\n  // Generic admin / DB-admin probes.\n  /^\\/admin\\/?$/i,\n  /^\\/administrator\\/?$/i,\n  /^\\/admin\\.php$/i,\n  /^\\/phpmyadmin(\\/|$)/i,\n  /^\\/pma(\\/|$)/i,\n  /^\\/myadmin(\\/|$)/i,\n  /^\\/dbadmin(\\/|$)/i,\n  /^\\/adminer\\.php$/i,\n\n  // Diagnostic / info-leak endpoints.\n  /^\\/phpinfo\\.php$/i,\n  /^\\/info\\.php$/i,\n  /^\\/test\\.php$/i,\n  /^\\/shell\\.php$/i,\n  /^\\/server-status$/i,\n  /^\\/server-info$/i,\n\n  // Backup / dump leaks.\n  /^\\/backup(\\.|\\/)/i,\n  /^\\/dump\\.sql$/i,\n  /^\\/database\\.sql$/i,\n]);\n\n/**\n * Test a URL path against the sensitive-path list. Returns the first\n * matching pattern's source for logging/telemetry, or `null`.\n */\nexport function detectSensitivePath(\n  path: string,\n  patterns: ReadonlyArray<RegExp> = SENSITIVE_PATH_PATTERNS,\n): string | null {\n  for (const re of patterns) {\n    if (re.test(path)) return re.source;\n  }\n  return null;\n}\n\n/**\n * Build an Express middleware that blocks sensitive-path probes.\n * `arcis()` wires this on by default; users can opt out via\n * `arcis({ scannerPaths: false })`.\n */\nexport function scannerPathProtection(\n  options: ScannerPathsOptions = {},\n): RequestHandler {\n  const { statusCode = 403, message = 'Access denied.' } = options;\n  const patterns = options.patterns ?? SENSITIVE_PATH_PATTERNS;\n\n  return (req: Request, res: Response, next: NextFunction) => {\n    const matched = detectSensitivePath(req.path, patterns);\n    if (matched === null) {\n      return next();\n    }\n    (req as unknown as Record<string, unknown>).scannerPathHit = matched;\n    res.status(statusCode).json({\n      error: message,\n      code: 'SECURITY_THREAT',\n      vector: 'scanner-path',\n    });\n  };\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/sanitizers/mass-assignment\n * v1.7 W4. Denylist detection of privilege-escalation fields in a body.\n *\n * The classic mass-assignment attack smuggles a sensitive field into a\n * request body that the handler blindly spreads onto a model:\n *\n *     user.update({ ...req.body })   // attacker set isAdmin: true\n *\n * The allowlist approach (`applyMassAssignFilter` / `MassAssignMiddleware`)\n * is the robust fix but needs a per-route field list, so it cannot be\n * default-on. This detector is the default-on complement: it scans the\n * body for a curated set of privilege/auth field NAMES that a normal\n * client request almost never sets, and blocks when one appears.\n *\n * Scope: detection only. It does not strip or rewrite. Recurses into\n * nested objects and arrays so `{ profile: { permissions: [...] } }` is\n * caught. Value-agnostic: the presence of the key is the signal.\n *\n * False-positive note: `role` and `permissions` DO appear in legitimate\n * admin APIs. Apps with such routes opt out via `arcis({ massAssign: false })`\n * or scope the check off for those paths, then use the allowlist filter\n * (`applyMassAssignFilter`) on the routes that legitimately accept them.\n */\n\nexport interface MassAssignDetectOptions {\n  /**\n   * Sensitive field names to detect (overrides the default set entirely).\n   * Compared case-insensitively after stripping `_` and `-`, so\n   * `is_admin`, `isAdmin`, and `is-admin` all match a `isadmin` entry.\n   */\n  sensitiveFields?: string[];\n  /** Max recursion depth into nested objects/arrays. Default: 8. */\n  maxDepth?: number;\n}\n\nexport interface MassAssignDetectResult {\n  /** True if a sensitive field name was found anywhere in the body. */\n  detected: boolean;\n  /** The offending field name (original casing) or null. */\n  field: string | null;\n}\n\n/**\n * Default privilege-escalation field names. Stored in normalized form\n * (lowercased, separators stripped). These are fields a profile/signup\n * update should never carry from the client. `role` / `permissions` are\n * the canonical mass-assignment fields and the FP-risk ones, kept in by\n * default; opt out per-route if your admin API legitimately accepts them.\n */\nexport const SENSITIVE_FIELD_NAMES: ReadonlySet<string> = new Set([\n  'isadmin',\n  'issuperuser',\n  'superuser',\n  'issuperadmin',\n  'superadmin',\n  'isstaff',\n  'isverified',\n  'isroot',\n  'isowner',\n  'role',\n  'roles',\n  'userrole',\n  'permission',\n  'permissions',\n  'privilege',\n  'privileges',\n  'accesslevel',\n  'accounttype',\n  'isactive',\n  'emailverified',\n]);\n\n/** Normalize a key: lowercase, strip `_` and `-`. */\nfunction normalizeKey(key: string): string {\n  return key.toLowerCase().replace(/[_-]/g, '');\n}\n\n/**\n * Recursively scan a parsed JSON body for sensitive field names.\n * Returns the first hit (original-cased key) or `{ detected: false }`.\n */\nexport function detectMassAssignment(\n  body: unknown,\n  options: MassAssignDetectOptions = {},\n): MassAssignDetectResult {\n  const maxDepth = options.maxDepth ?? 8;\n  const sensitive = options.sensitiveFields\n    ? new Set(options.sensitiveFields.map(normalizeKey))\n    : SENSITIVE_FIELD_NAMES;\n\n  function walk(value: unknown, depth: number): string | null {\n    if (depth > maxDepth || value === null || typeof value !== 'object') {\n      return null;\n    }\n    if (Array.isArray(value)) {\n      for (const item of value) {\n        const hit = walk(item, depth + 1);\n        if (hit) return hit;\n      }\n      return null;\n    }\n    for (const key of Object.keys(value as Record<string, unknown>)) {\n      if (sensitive.has(normalizeKey(key))) {\n        return key;\n      }\n      const hit = walk((value as Record<string, unknown>)[key], depth + 1);\n      if (hit) return hit;\n    }\n    return null;\n  }\n\n  const field = walk(body, 0);\n  return { detected: field !== null, field };\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 * Matches a string that begins with a URL scheme + `://` (or `scheme:/`\n * for the `file:///path` form). Used by the body walker to decide which\n * string values are worth running through `validateUrl`. Anchored at\n * start, case-insensitive, scheme charset per RFC 3986.\n */\nconst URL_SHAPED = /^[a-z][a-z0-9+.-]*:\\/\\//i;\n\n/** Result of scanning a request body for SSRF-shaped URL values. */\nexport interface SsrfScanResult {\n  /** True if any URL-shaped string value failed validation. */\n  detected: boolean;\n  /** The offending URL string, or null. */\n  url: string | null;\n  /** Why it was blocked (from validateUrl), or null. */\n  reason: string | null;\n}\n\n/**\n * Body-scan profile (v1.7 W5). When a request body is walked for URLs,\n * the threat is private/internal targets and file-read schemes, not the\n * `localhost` hostname or non-http fetch schemes that show up constantly\n * in legitimate config payloads. So the body scan:\n *\n * - Allows `http` / `https` / `ftp` / `ftps`. Blocks `file:` / `gopher:` /\n *   `dict:` and other SSRF-amplifying schemes.\n * - Allows the literal `localhost` hostname (and `*.localhost`), which is\n *   ubiquitous in dev/staging webhook + health-check fields, while STILL\n *   blocking loopback expressed as an IP (`127.x`, decimal, hex) since\n *   that is the encoding an attacker reaches for.\n *\n * Apps that fetch a user-supplied URL directly should call the strict\n * `validateUrl` / `Guards.checkUrl` on that one field instead — the body\n * scan is the broad default, not a replacement for a focused guard.\n */\nconst SSRF_BODY_SCAN_PROTOCOLS = ['http:', 'https:', 'ftp:', 'ftps:'];\n\n// Schemes the body scan evaluates: the fetchable ones (http/https/ftp/ftps)\n// plus the classic SSRF-amplifying ones (file, gopher, dict, ...). A URL-shaped\n// string with any other scheme is a typo or a custom app scheme (lhttps://,\n// myapp://) that no server-side fetch would act on, so it is skipped rather\n// than flagged as SSRF. Keeps the dangerous schemes here so they stay blocked.\nconst SSRF_RELEVANT_SCHEMES = new Set([\n  'http', 'https', 'ftp', 'ftps', 'file', 'gopher', 'dict',\n  'ldap', 'ldaps', 'tftp', 'sftp', 'ssh', 'smb', 'jar', 'netdoc',\n]);\n\nfunction isLocalhostHostname(url: string): boolean {\n  try {\n    const host = new URL(url).hostname.toLowerCase();\n    return host === 'localhost' || host.endsWith('.localhost');\n  } catch {\n    return false;\n  }\n}\n\n/**\n * Recursively walk a parsed request body and run `validateUrl` on every\n * string value that looks like a URL (`scheme://...`). Returns the first\n * unsafe URL found. v1.7 W5 wire-up.\n *\n * Public URLs pass, so a body carrying `{ website: \"https://example.com\" }`\n * is not blocked; only private / loopback-IP / link-local / metadata /\n * file-read-scheme URLs trip it. See `SSRF_BODY_SCAN_PROTOCOLS` for the\n * scheme + localhost policy.\n *\n * @param body - Parsed request body (object, array, or scalar).\n * @param options - Forwarded to `validateUrl`. When `allowedProtocols`\n *   is not set, the body-scan profile (http/https/ftp/ftps) is used.\n * @param maxDepth - Max recursion depth. Default 8.\n */\nexport function scanForSsrf(\n  body: unknown,\n  options: ValidateUrlOptions = {},\n  maxDepth = 8,\n): SsrfScanResult {\n  const scanOptions: ValidateUrlOptions = {\n    ...options,\n    allowedProtocols: options.allowedProtocols ?? SSRF_BODY_SCAN_PROTOCOLS,\n  };\n  function walk(value: unknown, depth: number): SsrfScanResult | null {\n    if (depth > maxDepth) return null;\n    if (typeof value === 'string') {\n      const trimmed = value.trim();\n      if (URL_SHAPED.test(trimmed)) {\n        // Skip schemes a server-side fetch would never act on (typos like\n        // lhttps://, custom app schemes). They are not an SSRF vector.\n        const scheme = trimmed.slice(0, trimmed.indexOf(':')).toLowerCase();\n        if (!SSRF_RELEVANT_SCHEMES.has(scheme)) {\n          return null;\n        }\n        // The localhost hostname is allowed (dev config); loopback IPs\n        // are not (attacker evasion). Both would otherwise be flagged.\n        if (isLocalhostHostname(trimmed)) {\n          return null;\n        }\n        const result = validateUrl(trimmed, scanOptions);\n        if (!result.safe) {\n          return { detected: true, url: value, reason: result.reason ?? 'unsafe URL' };\n        }\n      }\n      return null;\n    }\n    if (value === null || typeof value !== 'object') return null;\n    if (Array.isArray(value)) {\n      for (const item of value) {\n        const hit = walk(item, depth + 1);\n        if (hit) return hit;\n      }\n      return null;\n    }\n    for (const key of Object.keys(value as Record<string, unknown>)) {\n      const hit = walk((value as Record<string, unknown>)[key], depth + 1);\n      if (hit) return hit;\n    }\n    return null;\n  }\n\n  return walk(body, 0) ?? { detected: false, url: null, reason: null };\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/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: 'emotional-jailbreak-secrets',\n    // The \"grandma exploit\": emotional/nostalgic framing used to coax the\n    // model into reciting secret material (\"my grandmother used to read me\n    // Windows activation keys to help me sleep\"). Requires BOTH the\n    // family-elder reciting framing AND a key/credential/password token, so\n    // wholesome \"grandma read me bedtime stories\" (or \"grandma's cookie\n    // recipe\") never matches — only the credential-soliciting variant does.\n    pattern: /\\bgrand(?:m(?:a|other)|pa|father)\\b[^.?!]{0,60}\\b(?:read|tell|recite|sing|sang|whisper|list|share)\\b[^.?!]{0,80}\\b(?:(?:activation|product|license|serial|registration|api|ssh|secret|private|encryption)[\\s-]*keys?|passwords?|credentials?|serial\\s*numbers?)\\b/i,\n    severity: 'high',\n    description: 'Emotional-framing jailbreak soliciting keys/credentials (grandma exploit)',\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    // System-prompt extraction via the \"repeat the words above\" trick\n    // (Bing/Sydney leak 2023). Requires an output verb + a \"words/text/\n    // everything\" object + an \"above/before/preceding\" anchor, so it\n    // does not fire on ordinary \"repeat that\" conversational text.\n    rule: 'repeat-words-above',\n    pattern: /\\b(?:repeat|print|output|echo|reproduce|reveal|show)\\s+(?:me\\s+)?(?:the\\s+|all\\s+(?:the\\s+)?|every\\s+)?(?:words?|text|lines?|content|everything|message|sentences?|prompt)\\s+(?:above|before|preceding|prior|earlier|that\\s+(?:came|appear|precede))/i,\n    severity: 'medium',\n    description: 'System-prompt extraction via \"repeat the words above\"',\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    // Bracket-style tool marker: `[TOOL_USE: shell, command=\"...\"]`. The\n    // JSON-shape rule above misses this inline form, which is what\n    // ReAct-style and text-protocol agents actually parse out of model\n    // output. Won't fire on prose because it requires the bracket + a\n    // tool keyword + `:` or `=` immediately after.\n    rule: 'agent-toolcall-bracket',\n    pattern: /\\[\\s*(?:TOOL_USE|TOOL_CALL|FUNCTION_CALL|TOOL|FUNCTION|ACTION|EXECUTE)\\s*[:=]/i,\n    severity: 'high',\n    description: 'Injected bracket-style agent tool marker (e.g. [TOOL_USE: shell])',\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    // Unicode Tag characters (U+E0000-U+E007F). Invisible in nearly\n    // every renderer but tokenizable by LLMs, so an attacker hides\n    // \"Ignore previous instructions\" inside what looks like plain text.\n    // These code points have no legitimate use in user input.\n    rule: 'unicode-tag-smuggle',\n    pattern: /[\\u{E0000}-\\u{E007F}]/u,\n    severity: 'high',\n    description: 'Unicode Tag characters smuggling hidden instructions',\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/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, '&amp;')\n    .replace(/</g, '&lt;')\n    .replace(/>/g, '&gt;')\n    .replace(/\"/g, '&quot;')\n    .replace(/'/g, '&#x27;');\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: \"&lt;script&gt;alert(&#x27;xss&#x27;)&lt;/script&gt;\"\n * \n * @example\n * sanitizeXss(\"<img onerror='alert(1)'>\")\n * // Returns: \"&lt;img&gt;\" (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 (&lt;, &amp;, 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  // All XSS detection now flows through the shared patterns.json `xss` rules\n  // (event handlers, javascript:/vbscript:/data: protocols, tags). The former\n  // inline fast-path checks were a strict subset of these rules, so they were\n  // removed when the patterns moved to patterns.json (single source).\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  /** Velocity #set/#foreach + OGNL/Velocity method calls ($rt.exec, .getRuntime). Benchmark ssti-velocity-runtime. */\n  /#set\\s*\\(\\s*\\$|#foreach\\s*\\(\\s*\\$|\\$\\w+\\.(?:exec|getClass|getRuntime|getMethod|invoke)\\b/gi,\n  /** Laravel Blade raw-PHP directive: `@php(...)` inline or `@php ... @endphp` block\n   * (the `{{ }}` Blade echo form is already covered above). Requires `@php(` or the\n   * `@endphp` close so it doesn't fire on the bare `@php` social handle. */\n  /@php\\s*\\(|@endphp\\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).\n// Used for ESCAPING — broad set is fine here because escaping a benign\n// char is safe; the value just gets a `\\xx` representation.\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// Wildcard-value detection: `=*` inside a filter (e.g. `(uid=*)`).\n// Real LDAP filter abuse; legitimate values don't end in `=*`.\nconst LDAP_WILDCARD_VALUE_PATTERN = /=\\s*\\*/;\n\n// NUL byte detection — used for LDAP query truncation attacks.\n// Matches both a real NUL (`\\x00`) and the literal escape sequence\n// `\\00` (backslash-zero-zero), which is how it arrives over JSON/form\n// text before any decode. Benchmark ldap-null-byte-truncate.\nconst LDAP_NUL_PATTERN = /\\x00|\\\\00/;\n\n// Detection pattern for OR/AND bypass and wildcard abuse.\n// Real shapes: `*)(uid=*` (break the filter, inject a new clause).\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 * Designed for request-boundary scanning: matches only the specific\n * shapes real LDAP injection produces. The older broad\n * `[*()\\\\\\x00]` pattern was removed because it false-positived on\n * every markdown bold `**bold**`, every parenthesised string, every\n * apostrophe-in-name. Mirrors the `ldap-injection-strict` +\n * `ldap-not-bypass` rules from packages/core/patterns.json which are\n * marked `request_boundary_safe: true`. Benchmark FP class B2, 2026-06-07.\n *\n * @param input - The string to check\n * @returns True if LDAP injection patterns detected\n *\n * @example\n * detectLdapInjection(\"*)(uid=*))(|(uid=*\")  // true  — filter break-out\n * detectLdapInjection(\"(uid=*)\")              // true  — wildcard value\n * detectLdapInjection(\"ad\\x00min\")            // true  — NUL truncation\n * detectLdapInjection(\"**bold**\")             // false — markdown\n * detectLdapInjection(\"hello *world*\")        // false — emphasis\n * detectLdapInjection(\"john\")                 // false\n */\nexport function detectLdapInjection(input: string): boolean {\n  if (typeof input !== 'string') return false;\n  return (\n    LDAP_INJECTION_PATTERN.test(input) ||\n    LDAP_NOT_BYPASS_PATTERN.test(input) ||\n    LDAP_WILDCARD_VALUE_PATTERN.test(input) ||\n    LDAP_NUL_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 (`|`).\n// Also blind-extraction functions (`substring(name(...))`,\n// `string-length(`, `count(/`) used to leak the document one char at a\n// time. Benchmark xpath-blind-substring.\nconst XPATH_INJECTION_PATTERN =\n  /('\\s*(or|and)\\s*'|\"\\s*(or|and)\\s*\"|\\)\\s*(or|and)\\s*\\(|\\|\\s*\\/|\\bsubstring\\s*\\(\\s*name\\s*\\(|\\bstring-length\\s*\\(|\\bcount\\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 * Request-boundary header-injection shape: a newline (CRLF or bare CR/LF)\n * followed by a header-name token and a colon (`\\r\\nSet-Cookie:`,\n * `\\nX-Injected:`). This is the response-splitting / header-smuggling\n * signal. Unlike HEADER_INJECTION_PATTERN it does NOT flag a bare newline,\n * so multi-line request bodies (markdown, textareas, code) pass cleanly.\n * Mirrors Python's email-header-bare-newline rule. v1.7 parity 2026-06-08.\n */\nconst HEADER_INJECTION_STRICT_PATTERN =\n  /(?:\\r\\n|\\r|\\n)\\s*[a-zA-Z][a-zA-Z0-9-]{0,40}\\s*:/;\n\n/**\n * Narrow header-injection check for request-boundary scanning. Returns\n * true only on a CRLF-then-header-name-then-colon shape, never on a bare\n * newline. Use this in `scanThreats`; use `detectHeaderInjection` (broad)\n * when sanitizing a value destined for a response header.\n */\nexport function detectHeaderInjectionStrict(input: string): boolean {\n  if (typeof input !== 'string') return false;\n  return HEADER_INJECTION_STRICT_PATTERN.test(input);\n}\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/deserialization\n *\n * V33 — Modern deserialization marker detection (improvements.md §1.2).\n *\n * Detect input that LOOKS like a serialized-object payload for\n * runtimes where deserialization equals code execution: Python\n * pickle, Java FastJSON, PHP unserialize, Ruby Marshal, .NET\n * BinaryFormatter.\n *\n * Detection-only — the right response to a hit is \"refuse the\n * request\" not \"strip the bytes and pass through\" (a forgiving\n * parser might still deserialize the remainder to something\n * dangerous). Caller decides.\n *\n * Mirrors `arcis-python/arcis/sanitizers/deserialization.py`. Both\n * SDKs must accept the same base corpus per Pattern 7.\n */\n\nexport type DeserializeRuntime =\n  | 'python_pickle'\n  | 'java_fastjson'\n  | 'php_unserialize'\n  | 'ruby_marshal'\n  | 'dotnet_binary_formatter';\n\n// Python pickle: \\x80 followed by version byte 0x02-0x05.\nconst PICKLE_HEAD = /^\\x80[\\x02-\\x05]/;\n\n// Base64-encoded pickle. Attackers ship pickle over JSON/text as base64,\n// so the raw head-byte check never sees \\x80. The base64 of \\x80\\x02..05\n// always starts \"gA\" + a known char; we pre-filter cheaply, then decode\n// and re-check the head byte. Benchmark deser-python-pickle-marker.\nconst PICKLE_B64_PREFIX = /^gA[I-Z]/;\nconst B64_SHAPE = /^[A-Za-z0-9+/]{12,}={0,2}$/;\n\n// Ruby Marshal magic: \\x04\\x08 at start (Ruby 1.9+).\nconst RUBY_MARSHAL_HEAD = /^\\x04\\x08/;\n\n// .NET BinaryFormatter: 5-byte serialization-header.\nconst DOTNET_BINFMT_HEAD = /^\\x00\\x01\\x00\\x00\\x00/;\n\n// Java FastJSON: embedded `\"@type\":\"<class>\"`. Match anywhere.\nconst FASTJSON_AUTOTYPE = /\"@type\"\\s*:\\s*\"[a-zA-Z_$][\\w$.]*\"/;\n\n// PHP unserialize: `O:<len>:\"<ClassName>\":<count>:{` shape.\nconst PHP_UNSERIALIZE = /O:\\d+:\"[a-zA-Z_\\\\][\\w\\\\]*\":\\d+:\\{/;\n\n/**\n * Detect a serialized-object marker for any known runtime.\n *\n * Returns the runtime tag if a marker matches, or null if the input\n * looks safe. Precedence: head-byte markers (pickle / Ruby / .NET)\n * before embedded markers (FastJSON / PHP).\n */\nexport function detectDeserialization(\n  payload: string,\n): DeserializeRuntime | null {\n  if (typeof payload !== 'string' || payload.length === 0) {\n    return null;\n  }\n  if (PICKLE_HEAD.test(payload)) return 'python_pickle';\n  // Base64-encoded pickle: prefix pre-filter, then decode + re-check head.\n  if (PICKLE_B64_PREFIX.test(payload) && B64_SHAPE.test(payload)) {\n    try {\n      const decoded = Buffer.from(payload, 'base64');\n      if (\n        decoded.length >= 2 &&\n        decoded[0] === 0x80 &&\n        decoded[1] >= 0x02 &&\n        decoded[1] <= 0x05\n      ) {\n        return 'python_pickle';\n      }\n    } catch {\n      // not valid base64 — fall through\n    }\n  }\n  if (RUBY_MARSHAL_HEAD.test(payload)) return 'ruby_marshal';\n  if (DOTNET_BINFMT_HEAD.test(payload)) return 'dotnet_binary_formatter';\n  if (FASTJSON_AUTOTYPE.test(payload)) return 'java_fastjson';\n  if (PHP_UNSERIALIZE.test(payload)) return 'php_unserialize';\n  return null;\n}\n\n/** Convenience boolean wrapper around `detectDeserialization`. */\nexport function isSerializedPayload(payload: string): boolean {\n  return detectDeserialization(payload) !== null;\n}\n","/**\n * @module @arcis/node/sanitizers/nosql\n * NoSQL injection prevention (MongoDB operators)\n */\n\nimport { NOSQL_DANGEROUS_KEYS, NOSQL_STRING_PATTERN } 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 * Detects a MongoDB operator appearing in a STRING value.\n *\n * detectNoSqlInjection only inspects object keys. But operators also\n * arrive as strings: `?user[$ne]=1` reaches the handler as the literal\n * `$ne` before any object is built, and mongo-shell payloads like\n * `$where: '1==1'` are plain strings. This is the string-level check\n * used by block-mode scanThreats, matching Python's `_NOSQL_DETECT`.\n *\n * @param input - The string to check\n * @returns True if a NoSQL operator token is present\n *\n * @example\n * detectNoSqlString(\"$where: 'this.a==1'\") // true\n * detectNoSqlString(\"$invoice total\")      // false ($in not a token here)\n */\nexport function detectNoSqlString(input: string): boolean {\n  if (typeof input !== 'string') return false;\n  return NOSQL_STRING_PATTERN.test(input);\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/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, AUTH_FIELDS } 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 { detectHeaderInjectionStrict } from './headers';\nimport { detectDeserialization } from './deserialization';\nimport { detectNoSqlString } from './nosql';\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 &lt; 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: \"&lt;script&gt;alert(&#x27;xss&#x27;)&lt;/script&gt;\"\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 * `&#x3c;script&#x3e;`, 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    '&lt;': '<',\n    '&gt;': '>',\n    '&amp;': '&',\n    '&quot;': '\"',\n    '&apos;': \"'\",\n    '&nbsp;': ' ',\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＞`, `１+１＝２`) 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    | 'deserialization';\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 value = (data as Record<string, unknown>)[key];\n      // NoSQL type-juggling: an auth/identity field whose value is an\n      // ARRAY instead of a scalar (e.g. {\"username\":[\"admin\"]}). MongoDB\n      // turns the array into an $in-style operator, bypassing string\n      // equality. Only arrays are flagged: operator-objects ({\"$ne\":...})\n      // are caught by NOSQL_DANGEROUS_KEYS, and a plain nested object under\n      // an auth field is legitimate. Benchmark nosql-mongo-type-juggle.\n      if (AUTH_FIELDS.has(lower) && Array.isArray(value)) {\n        return { vector: 'nosql', rule: 'nosql/type-juggle', matchedPattern: key };\n      }\n      const inner = scanThreats(value, 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  // SECURITY: normalize the SAME way sanitizeString does before any\n  // detector runs, so block-mode detection honors the NFKC + multi-decode\n  // bypass protection. Without this, block mode missed fullwidth\n  // `<script>` (U+FF1C), `%3Cscript%3E`, and HTML-entity-encoded payloads\n  // that sanitize-mode already caught. (v1.7 parity fix 2026-06-08.)\n  const norm = multiDecode(data.normalize('NFKC'));\n\n  const sample = norm.slice(0, 80);\n  // __proto__ as a STRING VALUE (e.g. [\"__proto__\",\"isAdmin\"] gadget-chain\n  // path array). The key-based check above only sees object keys; a dunder\n  // proto token as a value is the array-form signal. Only the dunder forms\n  // (never legit prose) are flagged, so the words \"constructor\"/\"prototype\"\n  // in normal text don't trip it. Benchmark proto-pollution-array-index.\n  if (norm.includes('__proto__')) {\n    return { vector: 'prototype', rule: 'prototype/match', matchedPattern: sample };\n  }\n  if (detectXss(norm)) {\n    return { vector: 'xss', rule: 'xss/match', matchedPattern: sample };\n  }\n  if (detectSsti(norm)) {\n    return { vector: 'ssti', rule: 'ssti/match', matchedPattern: sample };\n  }\n  if (detectXxe(norm)) {\n    return { vector: 'xxe', rule: 'xxe/match', matchedPattern: sample };\n  }\n  // Deserialization markers (pickle incl. base64, Ruby Marshal, .NET,\n  // FastJSON, PHP). Wired into block mode in v1.7 (was detection-only).\n  const deser = detectDeserialization(norm);\n  if (deser) {\n    return { vector: 'deserialization', rule: `deserialization/${deser}`, matchedPattern: sample };\n  }\n  if (detectSql(norm)) {\n    return { vector: 'sql', rule: 'sql/match', matchedPattern: sample };\n  }\n  // Path detection runs on the RAW string so the encoded-form patterns\n  // (%C0%AE overlong UTF-8, %2e%2e, %252f) still fire; multiDecode would\n  // otherwise strip them. The decoded `../` form survives in raw too.\n  if (detectPathTraversal(data) || detectPathTraversal(norm)) {\n    return { vector: 'path', rule: 'path/match', matchedPattern: sample };\n  }\n  if (detectCommandInjection(norm)) {\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(norm)) {\n    return { vector: 'ldap', rule: 'ldap/match', matchedPattern: sample };\n  }\n  if (detectXpathInjection(norm)) {\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 (detectHeaderInjectionStrict(norm)) {\n    return { vector: 'header', rule: 'header/match', matchedPattern: sample };\n  }\n  // String-form NoSQL operator (`$where`, `$ne`, `[$gt]`) carried in a\n  // string value rather than an object key. Last in the chain so the\n  // more-specific detectors above win; this only catches operator tokens\n  // that would otherwise pass through. Closes the Node-vs-Python NoSQL\n  // string parity gap (GoTestWAF NoSQL was 0% on Node).\n  if (detectNoSqlString(norm)) {\n    return { vector: 'nosql', rule: 'nosql/string', 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/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/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/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/intelligence/client\n * Cloud IP-reputation client with a local LRU+TTL cache.\n *\n * Design rules:\n *   1. `check()` is synchronous and never blocks the request path. On a cache\n *      miss it returns `found:false` for THIS request and schedules a\n *      background refresh, so the hot path adds ~0ms. Subsequent requests from\n *      the same IP read the cached verdict (Pattern: opportunistic refresh, not\n *      on the hot path).\n *   2. Fail-open (Pattern 4): a network error, timeout, or non-200 resolves to\n *      `found:false` and never throws into the request path.\n *   3. Private / loopback / unresolved IPs are never looked up.\n *   4. A \"not found\" (clean) result IS cached so clean IPs are not re-queried\n *      every request; transport errors are NOT cached so they retry.\n */\n\nimport { isPrivateIp } from '../utils/ip';\nimport type { IntelligenceOptions, IpReputation, BotCorpusEntry } from './types';\n\nconst DEFAULT_CACHE_MAX = 1000;\nconst DEFAULT_CACHE_TTL_MS = 60 * 60 * 1000; // 1 hour\nconst DEFAULT_TIMEOUT_MS = 2000;\nconst MIN_TIMEOUT_MS = 100;\n\ninterface CacheEntry {\n  value: IpReputation;\n  expires: number;\n}\n\n/** Insertion-ordered LRU with per-entry TTL. */\nclass LruTtlCache {\n  private readonly map = new Map<string, CacheEntry>();\n  constructor(\n    private readonly max: number,\n    private readonly ttlMs: number,\n  ) {}\n\n  get(key: string): IpReputation | undefined {\n    const entry = this.map.get(key);\n    if (!entry) return undefined;\n    if (Date.now() > entry.expires) {\n      this.map.delete(key);\n      return undefined;\n    }\n    // Mark most-recently-used by reinserting at the tail.\n    this.map.delete(key);\n    this.map.set(key, entry);\n    return entry.value;\n  }\n\n  set(key: string, value: IpReputation): void {\n    if (this.map.has(key)) this.map.delete(key);\n    this.map.set(key, { value, expires: Date.now() + this.ttlMs });\n    while (this.map.size > this.max) {\n      const oldest = this.map.keys().next().value;\n      if (oldest === undefined) break;\n      this.map.delete(oldest);\n    }\n  }\n\n  clear(): void {\n    this.map.clear();\n  }\n\n  get size(): number {\n    return this.map.size;\n  }\n}\n\ninterface RawReputation {\n  ip?: unknown;\n  found?: unknown;\n  severity?: unknown;\n  categories?: unknown;\n  sources?: unknown;\n  first_seen?: unknown;\n  last_seen?: unknown;\n  matched?: unknown;\n}\n\nfunction asStringArray(v: unknown): string[] | undefined {\n  if (!Array.isArray(v)) return undefined;\n  const out = v.filter((s): s is string => typeof s === 'string');\n  return out.length > 0 ? out : undefined;\n}\n\n/** Map the dashboard wire shape (snake_case) to the SDK result (camelCase). */\nfunction normalize(ip: string, body: RawReputation): IpReputation {\n  if (body.found !== true) return { ip, found: false };\n  const result: IpReputation = { ip, found: true };\n  if (typeof body.severity === 'number') result.severity = body.severity;\n  const categories = asStringArray(body.categories);\n  if (categories) result.categories = categories;\n  const sources = asStringArray(body.sources);\n  if (sources) result.sources = sources;\n  if (typeof body.first_seen === 'string') result.firstSeen = body.first_seen;\n  if (typeof body.last_seen === 'string') result.lastSeen = body.last_seen;\n  if (typeof body.matched === 'string') result.matched = body.matched;\n  return result;\n}\n\nfunction isBotCorpusEntry(v: unknown): v is BotCorpusEntry {\n  if (typeof v !== 'object' || v === null) return false;\n  const e = v as Record<string, unknown>;\n  return (\n    typeof e.id === 'string' &&\n    typeof e.category === 'string' &&\n    typeof e.name === 'string' &&\n    Array.isArray(e.patterns) &&\n    e.patterns.every((p) => typeof p === 'string') &&\n    Array.isArray(e.forbidden) &&\n    e.forbidden.every((p) => typeof p === 'string')\n  );\n}\n\nexport class IntelligenceClient {\n  private readonly base: string;\n  private readonly apiKey: string | undefined;\n  private readonly workspaceId: string | undefined;\n  private readonly timeoutMs: number;\n  private readonly ipRepEnabled: boolean;\n  private readonly onError: (err: Error) => void;\n  private readonly cache: LruTtlCache;\n  private readonly inFlight = new Set<string>();\n  private closed = false;\n\n  constructor(options: IntelligenceOptions) {\n    if (!options.endpoint || typeof options.endpoint !== 'string') {\n      throw new TypeError('IntelligenceClient: `endpoint` is required');\n    }\n    this.base = options.endpoint.replace(/\\/+$/, '');\n    this.apiKey = options.apiKey;\n    this.workspaceId = options.workspaceId;\n    this.timeoutMs = Math.max(MIN_TIMEOUT_MS, options.timeoutMs ?? DEFAULT_TIMEOUT_MS);\n    this.ipRepEnabled = (options.cloudDecisions ?? []).includes('ip-rep');\n    this.onError = options.onError ?? (() => {\n      // default: swallow (fail-open)\n    });\n    this.cache = new LruTtlCache(\n      Math.max(1, options.cacheMax ?? DEFAULT_CACHE_MAX),\n      Math.max(1000, options.cacheTtlMs ?? DEFAULT_CACHE_TTL_MS),\n    );\n  }\n\n  /**\n   * Synchronous, cache-first reputation read. Never blocks: a cache miss\n   * returns `found:false` and schedules a background refresh so later requests\n   * from the same IP get the verdict. Safe to call on the hot path.\n   */\n  check(ip: string): IpReputation {\n    if (!this.ipRepEnabled || this.closed) return { ip, found: false };\n    if (!ip || ip === 'unknown' || isPrivateIp(ip)) return { ip, found: false };\n    const cached = this.cache.get(ip);\n    if (cached) return cached;\n    this.scheduleRefresh(ip);\n    return { ip, found: false };\n  }\n\n  /**\n   * Await a lookup and return the verdict. Fail-open: any transport error\n   * resolves to `found:false`. Used by direct callers and tests; the request\n   * path uses `check()` instead.\n   */\n  async lookup(ip: string): Promise<IpReputation> {\n    if (!ip || ip === 'unknown' || isPrivateIp(ip)) return { ip, found: false };\n    try {\n      return await this.fetchReputation(ip);\n    } catch (err) {\n      this.safeNotify(err);\n      return { ip, found: false };\n    }\n  }\n\n  /**\n   * Fetch the full bot corpus from the intelligence endpoint. Fail-open: any\n   * transport/parse error resolves to an empty array (the caller keeps the\n   * bundled corpus). Returns only well-formed entries.\n   */\n  async fetchBotCorpus(): Promise<BotCorpusEntry[]> {\n    const controller = new AbortController();\n    const timer = setTimeout(() => controller.abort(), this.timeoutMs);\n    try {\n      const headers: Record<string, string> = { accept: 'application/json' };\n      if (this.apiKey) headers['authorization'] = `Bearer ${this.apiKey}`;\n      if (this.workspaceId) headers['x-workspace-id'] = this.workspaceId;\n      const res = await fetch(`${this.base}/v1/intel/bot-corpus/snapshot`, {\n        headers,\n        signal: controller.signal,\n      });\n      if (!res.ok) throw new Error(`bot-corpus fetch returned HTTP ${res.status}`);\n      const body = (await res.json()) as { entries?: unknown };\n      if (!Array.isArray(body.entries)) return [];\n      return body.entries.filter(isBotCorpusEntry);\n    } catch (err) {\n      this.safeNotify(err);\n      return [];\n    } finally {\n      clearTimeout(timer);\n    }\n  }\n\n  /** Current number of cached entries. Useful for tests. */\n  get cacheSize(): number {\n    return this.cache.size;\n  }\n\n  /** Stop scheduling refreshes and drop the cache. Idempotent. */\n  close(): void {\n    this.closed = true;\n    this.cache.clear();\n    this.inFlight.clear();\n  }\n\n  // ── internals ───────────────────────────────────────────────────────────\n\n  private scheduleRefresh(ip: string): void {\n    if (this.inFlight.has(ip)) return;\n    this.inFlight.add(ip);\n    // Real results (including a clean \"not found\") are cached; transport\n    // errors are not, so they retry on the next request from this IP.\n    this.fetchReputation(ip)\n      .then((rep) => {\n        if (!this.closed) this.cache.set(ip, rep);\n      })\n      .catch((err) => this.safeNotify(err))\n      .finally(() => this.inFlight.delete(ip));\n  }\n\n  private async fetchReputation(ip: string): Promise<IpReputation> {\n    const controller = new AbortController();\n    const timer = setTimeout(() => controller.abort(), this.timeoutMs);\n    try {\n      const headers: Record<string, string> = { accept: 'application/json' };\n      if (this.apiKey) headers['authorization'] = `Bearer ${this.apiKey}`;\n      if (this.workspaceId) headers['x-workspace-id'] = this.workspaceId;\n      const url = `${this.base}/v1/intel/ip-reputation/${encodeURIComponent(ip)}`;\n      const res = await fetch(url, { headers, signal: controller.signal });\n      if (!res.ok) {\n        throw new Error(`ip-reputation lookup returned HTTP ${res.status}`);\n      }\n      const body = (await res.json()) as RawReputation;\n      return normalize(ip, body);\n    } finally {\n      clearTimeout(timer);\n    }\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 hook must never bubble up\n    }\n  }\n}\n\n/** Map a numeric reputation severity (1-10) to a coarse telemetry severity. */\nexport function reputationSeverityTier(\n  severity: number | undefined,\n): 'critical' | 'high' | 'medium' | 'low' {\n  const s = severity ?? 0;\n  if (s >= 9) return 'critical';\n  if (s >= 7) return 'high';\n  if (s >= 4) return 'medium';\n  return 'low';\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 { botProtection, mergeBotPatterns, type BotProtectionOptions } from './bot-detection';\nimport { scannerPathProtection, type ScannerPathsOptions } from './sensitive-paths';\nimport { inspectGraphqlQuery, type GraphqlGuardOptions } from '../sanitizers/graphql';\nimport { detectMassAssignment, type MassAssignDetectOptions } from '../sanitizers/mass-assignment';\nimport { scanForSsrf, type ValidateUrlOptions } from '../validation/url';\nimport { detectPromptInjection, type PromptInjectionSeverity } from '../sanitizers/prompt-injection';\nimport { createSanitizer, scanThreats } from '../sanitizers';\nimport { validate } from '../validation';\nimport { createSafeLogger } from '../logging';\nimport { TelemetryClient } from '../telemetry/client';\nimport type { TelemetryOptions } from '../telemetry/types';\nimport { IntelligenceClient, reputationSeverityTier } from '../intelligence/client';\nimport { detectClientIp } from '../utils/ip';\nimport type { IpReputation, IntelligenceOptions, CloudDecision } from '../intelligence/types';\n\n/**\n * Resolve cloud-intelligence config from in-code options or `ARCIS_INTEL_*`\n * env vars. The env fallback lets 12-factor apps turn on cloud intelligence\n * with no code change (mirrors the telemetry env pickup). In-code options win\n * when an endpoint is set both ways.\n *\n *   ARCIS_INTEL_ENDPOINT   required to activate the env path\n *   ARCIS_INTEL_KEY        optional bearer token\n *   ARCIS_INTEL_WORKSPACE        optional workspace id\n *   ARCIS_INTEL_DECISIONS        comma list: \"ip-rep,bot-corpus\"\n *   ARCIS_INTEL_BLOCK_THRESHOLD  optional int; reputation severity at/above\n *                                which to block (omit = annotate only)\n */\nfunction resolveIntelligenceOptions(opt?: IntelligenceOptions): IntelligenceOptions | undefined {\n  if (opt?.endpoint) return opt;\n  const endpoint = process.env.ARCIS_INTEL_ENDPOINT;\n  if (!endpoint) return undefined;\n  const valid: CloudDecision[] = ['ip-rep', 'bot-corpus'];\n  const cloudDecisions = (process.env.ARCIS_INTEL_DECISIONS ?? '')\n    .split(',')\n    .map((s) => s.trim())\n    .filter((s): s is CloudDecision => (valid as string[]).includes(s));\n  const rawThreshold = process.env.ARCIS_INTEL_BLOCK_THRESHOLD;\n  const blockThreshold =\n    rawThreshold && Number.isFinite(Number(rawThreshold)) ? Number(rawThreshold) : undefined;\n  return {\n    endpoint,\n    apiKey: process.env.ARCIS_INTEL_KEY,\n    workspaceId: process.env.ARCIS_INTEL_WORKSPACE,\n    cloudDecisions,\n    blockThreshold,\n  };\n}\n\ndeclare module 'express-serve-static-core' {\n  interface Request {\n    /** IP reputation verdict attached by the intelligence middleware, when enabled. */\n    arcisIpReputation?: IpReputation;\n  }\n}\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  // Scanner-path probe blocking (v1.7 W2). Runs BEFORE bot detection because\n  // some scanner UAs forge a browser UA but still hit dotfile / WordPress\n  // probe paths. Dry-run skips the block.\n  if (options.scannerPaths !== false && !dryRun) {\n    const scannerOpts: ScannerPathsOptions = typeof options.scannerPaths === 'object'\n      ? options.scannerPaths\n      : {};\n    middlewares.push(scannerPathProtection(scannerOpts));\n  }\n\n  // Forwarded-header inspection (v1.7 W7). Flags a loopback address in a\n  // forwarded / client-IP header (spoofing to bypass IP allowlists), and\n  // optionally rejects Host / X-Forwarded-Host not in a trustedHosts\n  // allowlist. Runs early (header read, no body needed). Skipped in dry-run.\n  if (options.forwardedHeaders !== false && !dryRun) {\n    const FORWARDED = ['x-forwarded-for', 'x-forwarded-host', 'x-real-ip', 'forwarded', 'client-ip', 'true-client-ip'];\n    const LOOPBACK = /(?:^|[\\s,@=])(?:127\\.\\d{1,3}\\.\\d{1,3}\\.\\d{1,3}|::1|0\\.0\\.0\\.0|localhost)(?::\\d+)?(?:$|[\\s,;])/i;\n    const trustedHosts = typeof options.forwardedHeaders === 'object' && options.forwardedHeaders.trustedHosts\n      ? options.forwardedHeaders.trustedHosts.map((h) => h.toLowerCase())\n      : null;\n    middlewares.push((req, res, next): void => {\n      for (const name of FORWARDED) {\n        const raw = req.headers[name];\n        const value = Array.isArray(raw) ? raw.join(',') : raw;\n        if (typeof value === 'string' && LOOPBACK.test(value)) {\n          res.status(403).json({\n            error: 'Request blocked for security reasons',\n            code: 'SECURITY_THREAT',\n            vector: 'header',\n            rule: 'header/forwarded-loopback-spoof',\n          });\n          return;\n        }\n      }\n      if (trustedHosts) {\n        for (const name of ['host', 'x-forwarded-host']) {\n          const raw = req.headers[name];\n          const value = Array.isArray(raw) ? raw[0] : raw;\n          if (typeof value === 'string' && value) {\n            const host = value.split(':')[0].toLowerCase();\n            if (!trustedHosts.includes(host)) {\n              res.status(403).json({\n                error: 'Request blocked for security reasons',\n                code: 'SECURITY_THREAT',\n                vector: 'header',\n                rule: 'header/untrusted-host',\n              });\n              return;\n            }\n          }\n        }\n      }\n      next();\n    });\n  }\n\n  // Cloud intelligence (opt-in). One client serves both capabilities; created\n  // when an endpoint is set and cloudDecisions names at least one.\n  const intel = resolveIntelligenceOptions(options.intelligence);\n  const intelDecisions = intel?.endpoint ? intel.cloudDecisions ?? [] : [];\n  if (intelDecisions.length > 0 && intel) {\n    const intelClient = new IntelligenceClient(intel);\n    cleanupFns.push(() => intelClient.close());\n\n    // Bot-corpus cloud refresh: fetch on startup + on an interval, merging the\n    // curated additions on top of the bundled corpus so new scanners / AI\n    // crawlers are classified without an SDK release. Fail-open: fetchBotCorpus\n    // returns [] on any error, so the bundled corpus is never disturbed.\n    if (intelDecisions.includes('bot-corpus')) {\n      const refresh = (): void => {\n        void intelClient.fetchBotCorpus().then((entries) => {\n          if (entries.length > 0) mergeBotPatterns(entries);\n        });\n      };\n      refresh();\n      const refreshMs = Math.max(\n        60_000,\n        intel.botCorpusRefreshMs ?? 7 * 24 * 60 * 60 * 1000,\n      );\n      const timer = setInterval(refresh, refreshMs);\n      (timer as { unref?: () => void }).unref?.();\n      cleanupFns.push(() => clearInterval(timer));\n    }\n\n    // Cloud IP reputation per-request lookup. Runs early (IP-level, no body\n    // needed), after forwarded-header inspection and before bot/rate-limit so a\n    // known-bad IP is blocked before consuming quota. Cache-first and\n    // non-blocking: a miss never adds latency, and an unreachable service fails\n    // open.\n    if (intelDecisions.includes('ip-rep')) {\n      const blockThreshold = intel.blockThreshold;\n      middlewares.push((req, res, next): void => {\n        const ip = detectClientIp(req);\n        const rep = intelClient.check(ip);\n        req.arcisIpReputation = rep;\n        const shouldBlock =\n          !dryRun &&\n          rep.found &&\n          typeof blockThreshold === 'number' &&\n          (rep.severity ?? 0) >= blockThreshold;\n        if (shouldBlock) {\n          req.__arcis = {\n            vector: 'ip-reputation',\n            rule: 'ip-reputation/known-bad',\n            severity: reputationSeverityTier(rep.severity),\n            reason: `IP reputation severity ${rep.severity} >= ${blockThreshold}`,\n            decision: 'deny',\n          };\n          res.status(403).json({\n            error: 'Request blocked for security reasons',\n            code: 'SECURITY_THREAT',\n            vector: 'ip-reputation',\n            rule: 'ip-reputation/known-bad',\n          });\n          return;\n        }\n        next();\n      });\n    }\n  }\n\n  // Bot UA classification — runs BEFORE rate-limit so bots don't consume\n  // legitimate-traffic rate-limit quota. v1.7 W1 wire-up (was opt-in via\n  // standalone botProtection() factory; now default-on). Dry-run mode skips\n  // the deny step (detection still attaches result to req.botDetection) so\n  // dashboards can see \"would have blocked\" decisions.\n  if (options.bot !== false) {\n    const userBotOpts: BotProtectionOptions = typeof options.bot === 'object'\n      ? options.bot\n      : {};\n    const botOpts: BotProtectionOptions = {\n      // Default deny: AUTOMATED (headless browser automation: Selenium /\n      // Puppeteer / Playwright / PhantomJS / WebDriver / Headless Chrome) and\n      // SECURITY_SCANNER (offensive scanners: sqlmap / nikto / nuclei / nmap /\n      // masscan / wpscan / Acunetix / Nessus / dirbuster). SCRAPER is NOT\n      // default-denied: it also covers curl / wget / python-requests /\n      // monitoring and other legitimate non-browser clients, so blocking it by\n      // default would break health checks and server-to-server traffic. Add it\n      // explicitly with arcis({ bot: { deny: ['AUTOMATED', 'SCRAPER'] } }).\n      deny: userBotOpts.deny ?? ['AUTOMATED', 'SECURITY_SCANNER'],\n      allow: userBotOpts.allow,\n      defaultAction: userBotOpts.defaultAction,\n      statusCode: userBotOpts.statusCode,\n      message: userBotOpts.message,\n      detectBehavior: userBotOpts.detectBehavior,\n      onDetected: userBotOpts.onDetected,\n    };\n    if (dryRun) {\n      // Dry-run: classify + attach to req for observation, but never deny.\n      const classifyOnly: BotProtectionOptions = {\n        ...botOpts,\n        deny: [],\n        defaultAction: 'allow',\n      };\n      middlewares.push(botProtection(classifyOnly));\n    } else {\n      middlewares.push(botProtection(botOpts));\n    }\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  // GraphQL inspection (v1.7 W3). When the JSON body has a `query`\n  // field, treat it as a GraphQL document and run the inspector. Sits\n  // between rate-limit and sanitizer so the depth/alias-bomb check\n  // happens BEFORE the regex-heavy body sanitizer chews on it. Skipped\n  // in dry-run mode.\n  if (options.graphql !== false && !dryRun) {\n    const userGqlOpts: GraphqlGuardOptions = typeof options.graphql === 'object'\n      ? options.graphql\n      : {};\n    // Tighter defaults than the standalone factory: 12-alias bombs\n    // bypass the standalone default of 50, and most legit queries\n    // never need >10 aliases. Users running Apollo Studio in dev\n    // pass blockIntrospection: false explicitly.\n    const gqlOpts: GraphqlGuardOptions = {\n      maxDepth: userGqlOpts.maxDepth ?? 10,\n      maxLength: userGqlOpts.maxLength ?? 10000,\n      blockIntrospection: userGqlOpts.blockIntrospection ?? true,\n      maxAliases: userGqlOpts.maxAliases ?? 10,\n      blockFragmentCycles: userGqlOpts.blockFragmentCycles ?? true,\n    };\n    middlewares.push((req, res, next) => {\n      const body = req.body as Record<string, unknown> | undefined;\n      const query = body && typeof body === 'object' ? body.query : undefined;\n      if (typeof query !== 'string' || query.length === 0) {\n        return next();\n      }\n      const result = inspectGraphqlQuery(query, gqlOpts);\n      if (!result.blocked) {\n        return next();\n      }\n      res.status(403).json({\n        error: 'Request blocked for security reasons',\n        code: 'SECURITY_THREAT',\n        vector: 'graphql',\n        rule: `graphql/${result.reason}`,\n      });\n    });\n  }\n\n  // Mass-assignment field detection (v1.7 W4). Scan the JSON body for\n  // privilege-escalation field names. Runs after GraphQL (cheap key walk\n  // vs the GraphQL string parse) and before the sanitizer. Skipped in\n  // dry-run.\n  if (options.massAssign !== false && !dryRun) {\n    const massAssignOpts: MassAssignDetectOptions = typeof options.massAssign === 'object'\n      ? options.massAssign\n      : {};\n    middlewares.push((req, res, next) => {\n      const result = detectMassAssignment(req.body, massAssignOpts);\n      if (!result.detected) {\n        return next();\n      }\n      res.status(403).json({\n        error: 'Request blocked for security reasons',\n        code: 'SECURITY_THREAT',\n        vector: 'mass-assignment',\n        rule: 'mass-assignment/sensitive-field',\n      });\n    });\n  }\n\n  // SSRF body-URL validation (v1.7 W5). Walk the JSON body for URL-shaped\n  // strings and validate each. Skipped in dry-run.\n  if (options.ssrf !== false && !dryRun) {\n    const ssrfOpts: ValidateUrlOptions = typeof options.ssrf === 'object'\n      ? options.ssrf\n      : {};\n    middlewares.push((req, res, next) => {\n      const result = scanForSsrf(req.body, ssrfOpts);\n      if (!result.detected) {\n        return next();\n      }\n      res.status(403).json({\n        error: 'Request blocked for security reasons',\n        code: 'SECURITY_THREAT',\n        vector: 'ssrf',\n        rule: 'ssrf/blocked-url',\n      });\n    });\n  }\n\n  // Prompt-injection detection on body strings (v1.7 W6). Walk the JSON\n  // body for string values and run the prompt-injection detector; block\n  // when a match at or above the configured severity is found. Skipped\n  // in dry-run.\n  if (options.promptInjection !== false && !dryRun) {\n    const piRank: Record<string, number> = { none: 0, low: 1, medium: 2, high: 3 };\n    const minSeverity: PromptInjectionSeverity =\n      typeof options.promptInjection === 'object' && options.promptInjection.minSeverity\n        ? options.promptInjection.minSeverity\n        : 'medium';\n    const minRank = piRank[minSeverity];\n    const scanPromptInjection = (value: unknown, depth: number): boolean => {\n      if (depth > 8 || value === null) return false;\n      if (typeof value === 'string') {\n        const r = detectPromptInjection(value);\n        return r.detected && piRank[r.severity] >= minRank;\n      }\n      if (typeof value !== 'object') return false;\n      if (Array.isArray(value)) {\n        return value.some((v) => scanPromptInjection(v, depth + 1));\n      }\n      return Object.values(value as Record<string, unknown>).some((v) =>\n        scanPromptInjection(v, depth + 1),\n      );\n    };\n    middlewares.push((req, res, next) => {\n      if (!scanPromptInjection(req.body, 0)) {\n        return next();\n      }\n      res.status(403).json({\n        error: 'Request blocked for security reasons',\n        code: 'SECURITY_THREAT',\n        vector: 'prompt-injection',\n        rule: 'prompt-injection/detected',\n      });\n    });\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 * @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/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/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/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/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 * 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/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/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"]}