{"version":3,"sources":["../../src/data/patterns.json","../../src/core/patterns-loader.ts","../../src/core/constants.ts","../../src/stores/memory.ts","../../src/stores/redis.ts"],"names":[],"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/stores/memory\n * In-memory rate limit store\n */\n\nimport type { RateLimitStore, RateLimitEntry } from '../core/types';\nimport { RATE_LIMIT } from '../core/constants';\n\n/**\n * In-memory rate limit store.\n * Suitable for single-instance deployments.\n * For distributed systems, use RedisStore or a custom store.\n * \n * @example\n * const store = new MemoryStore(60000); // 1 minute window\n * const limiter = createRateLimiter({ store });\n */\n/** Default maximum number of keys the in-memory store will hold. */\nconst DEFAULT_MAX_SIZE = 10_000;\n\nexport class MemoryStore implements RateLimitStore {\n  private store: Map<string, RateLimitEntry> = new Map();\n  private cleanupInterval: ReturnType<typeof setInterval> | null = null;\n  private windowMs: number;\n  private maxSize: number;\n\n  constructor(windowMs: number = RATE_LIMIT.DEFAULT_WINDOW_MS, maxSize: number = DEFAULT_MAX_SIZE) {\n    if (!Number.isFinite(windowMs) || windowMs < RATE_LIMIT.MIN_WINDOW_MS) {\n      throw new RangeError(\n        `MemoryStore: windowMs must be a finite number >= ${RATE_LIMIT.MIN_WINDOW_MS} (got ${windowMs})`\n      );\n    }\n    if (!Number.isFinite(maxSize) || maxSize < 1) {\n      throw new RangeError(`MemoryStore: maxSize must be >= 1 (got ${maxSize})`);\n    }\n    this.windowMs = windowMs;\n    this.maxSize = maxSize;\n    this.startCleanup();\n  }\n\n  /**\n   * Start the cleanup interval to remove expired entries.\n   */\n  private startCleanup(): void {\n    // Clamp the cleanup interval between 30 s and 5 min regardless of windowMs.\n    // Running it every windowMs is fine for typical windows but would fire every\n    // second for short windows (e.g. windowMs: 1000), causing O(n) GC pressure.\n    const CLEANUP_MIN_MS = 30_000;\n    const CLEANUP_MAX_MS = 300_000;\n    const cleanupMs = Math.min(Math.max(this.windowMs, CLEANUP_MIN_MS), CLEANUP_MAX_MS);\n\n    this.cleanupInterval = setInterval(() => {\n      const now = Date.now();\n      for (const [key, entry] of this.store.entries()) {\n        if (entry.resetTime < now) {\n          this.store.delete(key);\n        }\n      }\n    }, cleanupMs);\n\n    // Prevent interval from keeping the process alive\n    if (typeof this.cleanupInterval.unref === 'function') {\n      this.cleanupInterval.unref();\n    }\n  }\n\n  async get(key: string): Promise<RateLimitEntry | null> {\n    const entry = this.store.get(key);\n    if (!entry) return null;\n    \n    // Check if expired\n    if (entry.resetTime < Date.now()) {\n      this.store.delete(key);\n      return null;\n    }\n    \n    return entry;\n  }\n\n  async set(key: string, entry: RateLimitEntry): Promise<void> {\n    if (!this.store.has(key) && this.store.size >= this.maxSize) {\n      this.evictExpired();\n      // If still at capacity after eviction, fail open — don't crash the app\n      if (this.store.size >= this.maxSize) return;\n    }\n    this.store.set(key, entry);\n  }\n\n  async increment(key: string): Promise<number> {\n    const now = Date.now();\n    const entry = this.store.get(key);\n\n    if (!entry || entry.resetTime < now) {\n      // Start new window — check capacity first\n      if (this.store.size >= this.maxSize) {\n        this.evictExpired();\n        if (this.store.size >= this.maxSize) return 1; // fail open\n      }\n      this.store.set(key, { count: 1, resetTime: now + this.windowMs });\n      return 1;\n    }\n\n    entry.count++;\n    return entry.count;\n  }\n\n  /** Eagerly remove expired entries to reclaim capacity. */\n  private evictExpired(): void {\n    const now = Date.now();\n    for (const [key, entry] of this.store.entries()) {\n      if (entry.resetTime < now) this.store.delete(key);\n    }\n  }\n\n  async decrement(key: string): Promise<void> {\n    const entry = this.store.get(key);\n    if (entry && entry.count > 0) {\n      entry.count--;\n    }\n  }\n\n  async reset(key: string): Promise<void> {\n    this.store.delete(key);\n  }\n\n  async close(): Promise<void> {\n    if (this.cleanupInterval) {\n      clearInterval(this.cleanupInterval);\n      this.cleanupInterval = null;\n    }\n    this.store.clear();\n  }\n\n  /**\n   * Get current store size (for monitoring).\n   */\n  get size(): number {\n    return this.store.size;\n  }\n}\n","/**\n * @module @arcis/node/stores/redis\n * Redis rate limit store\n * \n * Note: This is a reference implementation. You'll need to install\n * the 'ioredis' or 'redis' package and pass your client instance.\n */\n\nimport type { RateLimitStore, RateLimitEntry } from '../core/types';\nimport { RATE_LIMIT } from '../core/constants';\n\n/** Generic Redis client interface (works with ioredis, redis, etc.) */\nexport interface RedisClientLike {\n  get(key: string): Promise<string | null>;\n  /**\n   * SET with optional flags. Supports both `set(key, value)` and\n   * `set(key, value, 'EX', seconds, 'NX')` shapes for atomic\n   * set-if-not-exists with TTL. Returns 'OK' on success; null when NX\n   * is supplied and the key already exists.\n   */\n  set(\n    key: string,\n    value: string,\n    ...args: Array<string | number>\n  ): Promise<string | null | unknown>;\n  setex(key: string, seconds: number, value: string): Promise<unknown>;\n  expire(key: string, seconds: number): Promise<unknown>;\n  incr(key: string): Promise<number>;\n  decr(key: string): Promise<number>;\n  del(key: string): Promise<number>;\n  ttl(key: string): Promise<number>;\n  quit?(): Promise<unknown>;\n  disconnect?(): Promise<unknown>;\n}\n\nexport interface RedisStoreOptions {\n  /** Redis client instance */\n  client: RedisClientLike;\n  /** Key prefix. Default: 'arcis:rl:' */\n  prefix?: string;\n  /** Window size in milliseconds. Default: 60000 */\n  windowMs?: number;\n}\n\n/**\n * Redis rate limit store for distributed deployments.\n * \n * @example\n * import Redis from 'ioredis';\n * \n * const redis = new Redis();\n * const store = new RedisStore({ client: redis });\n * const limiter = createRateLimiter({ store });\n * \n * // Cleanup on shutdown\n * process.on('SIGTERM', async () => {\n *   await store.close();\n * });\n */\nexport class RedisStore implements RateLimitStore {\n  private client: RedisClientLike;\n  private prefix: string;\n  private windowMs: number;\n  private windowSec: number;\n\n  constructor(options: RedisStoreOptions) {\n    this.client = options.client;\n    this.prefix = options.prefix ?? 'arcis:rl:';\n    this.windowMs = options.windowMs ?? RATE_LIMIT.DEFAULT_WINDOW_MS;\n    this.windowSec = Math.ceil(this.windowMs / 1000);\n  }\n\n  private getKey(key: string): string {\n    return `${this.prefix}${key}`;\n  }\n\n  async get(key: string): Promise<RateLimitEntry | null> {\n    const redisKey = this.getKey(key);\n    \n    const [countStr, ttl] = await Promise.all([\n      this.client.get(redisKey),\n      this.client.ttl(redisKey),\n    ]);\n    \n    if (!countStr || ttl < 0) {\n      return null;\n    }\n    \n    const count = parseInt(countStr, 10);\n    if (isNaN(count)) {\n      // Corrupt value in Redis — treat as if key doesn't exist\n      return null;\n    }\n\n    return {\n      count,\n      resetTime: Date.now() + (ttl * 1000),\n    };\n  }\n\n  async set(key: string, entry: RateLimitEntry): Promise<void> {\n    const redisKey = this.getKey(key);\n    // Clamp to at least 1 second — Math.ceil can produce 0 or negative values\n    // when entry.resetTime is in the past due to Redis latency or clock skew.\n    const ttlSec = Math.max(1, Math.ceil((entry.resetTime - Date.now()) / 1000));\n    await this.client.setex(redisKey, ttlSec, entry.count.toString());\n  }\n\n  async increment(key: string): Promise<number> {\n    const redisKey = this.getKey(key);\n\n    // SECURITY / RELIABILITY: Atomic first-increment via SET ... EX ... NX.\n    // If the key did not exist, this single command creates it with value\n    // 1 and the window TTL atomically. If it existed, SET returns null\n    // and we fall through to INCR for the actual count. This eliminates\n    // the INCR-then-EXPIRE race where a connection drop between the two\n    // commands could leave a counter without a TTL, locking out the\n    // client until manual intervention.\n    const created = await this.client.set(redisKey, '1', 'EX', this.windowSec, 'NX');\n    if (created === 'OK' || created === true) {\n      return 1;\n    }\n    return this.client.incr(redisKey);\n  }\n\n  async decrement(key: string): Promise<void> {\n    const redisKey = this.getKey(key);\n    await this.client.decr(redisKey);\n  }\n\n  async reset(key: string): Promise<void> {\n    const redisKey = this.getKey(key);\n    await this.client.del(redisKey);\n  }\n\n  async close(): Promise<void> {\n    // Don't close the client - it may be shared\n    // The caller should manage the client lifecycle\n  }\n}\n\n/**\n * Create a Redis store with the given options.\n * Convenience function for functional programming style.\n * \n * @example\n * const store = createRedisStore({ client: redisClient });\n */\nexport function createRedisStore(options: RedisStoreOptions): RedisStore {\n  return new RedisStore(options);\n}\n"]}