[{"data":1,"prerenderedAt":5533},["ShallowReactive",2],{"navLinks":3,"sidebar_docs_navigation_\u002Fdocs\u002Fbot-detection":64,"navigation":191,"navLinks_footer":816,"\u002Fdocs\u002Fbot-detection\u002Fconfiguration_page":829,"\u002Fdocs\u002Fbot-detection\u002Fconfiguration_surround":3513,"\u002Fdocs\u002Fbot-detection\u002Fconfiguration":3515},{"id":4,"extension":5,"links":6,"meta":61,"stem":62,"__hash__":63},"navigationMenu\u002Fnavigation.json","json",[7,52,57],{"nested":8,"label":9,"icon":10,"to":11,"children":12},true,"Docs","i-lucide-book-open","\u002Fdocs\u002Fgetting-started",[13,19,26,32,39,45],{"label":14,"icon":15,"to":11,"description":16,"github":17,"badge":18},"Getting Started","i-lucide-rocket","An introduction to help you understand the core components.","https:\u002F\u002Fgithub.com\u002FSergo706\u002Fdocshub","Start Here",{"label":20,"icon":21,"to":22,"description":23,"github":24,"badge":25},"Auth H3 Client","i-lucide-key-round","\u002Fdocs\u002Fauth-h3client","Seamlessly enforce OAuth 2.0 authentication and session management integrated directly as the client of the IAM module.","https:\u002F\u002Fgithub.com\u002FSergo706\u002Fauth-h3client","Core",{"label":27,"icon":28,"to":29,"description":30,"github":31,"badge":25},"IAM","i-lucide-shield-check","\u002Fdocs\u002Fiam","Identity and Access Management featuring granular roles, permissions, and security policies.","https:\u002F\u002Fgithub.com\u002FSergo706\u002Fauth",{"label":33,"icon":34,"to":35,"description":36,"github":37,"badge":38},"Bot Detection","i-lucide-cpu","\u002Fdocs\u002Fbot-detection","Advanced behavioral analysis and request fingerprinting to stop malicious automated traffic.","https:\u002F\u002Fgithub.com\u002FSergo706\u002Fbot-detector","Security",{"label":40,"icon":41,"to":42,"description":43,"github":44,"badge":38},"Shield Base","i-lucide-database-zap","\u002Fdocs\u002Fshield-base","CLI and programmatic toolkit for compiling offline-ready IP intelligence databases from BGP, GeoIP, Tor, FireHOL, and other public threat feeds.","https:\u002F\u002Fgithub.com\u002FSergo706\u002Fshield-base-cli",{"label":46,"icon":47,"to":48,"description":49,"github":50,"badge":51},"Utils","i-lucide-wrench","\u002Fdocs\u002Futils","A standard library of highly optimized helpers for formatting, validation, and core logic.","https:\u002F\u002Fgithub.com\u002FSergo706\u002Futils","Library",{"nested":53,"label":54,"icon":55,"to":56},false,"Blog","i-lucide-pen-line","\u002Fblog",{"nested":53,"label":58,"icon":59,"to":60},"Website","lucide:app-window-mac","https:\u002F\u002Friavzon.com",{},"navigation","gkaQ0xRGxSLrLyM3kttLe0oBwkrR1EBjlepF8LSbwF8",[65],{"title":9,"path":66,"stem":67,"children":68,"page":53},"\u002Fdocs","docs",[69],{"title":70,"path":35,"stem":71,"children":72},"Bot Detector","docs\u002Fbot-detection\u002Findex",[73,74,77,81,85,106,180,183,187],{"title":70,"path":35,"stem":71},{"title":14,"path":75,"stem":76},"\u002Fdocs\u002Fbot-detection\u002Fgetting-started","docs\u002Fbot-detection\u002F00.getting-started",{"title":78,"path":79,"stem":80},"CLI","\u002Fdocs\u002Fbot-detection\u002Fcli","docs\u002Fbot-detection\u002F01.cli",{"title":82,"path":83,"stem":84},"Data Sources","\u002Fdocs\u002Fbot-detection\u002Fdata-sources","docs\u002Fbot-detection\u002F02.data-sources",{"title":86,"path":87,"stem":88,"children":89,"page":53},"Guides","\u002Fdocs\u002Fbot-detection\u002Fguides","docs\u002Fbot-detection\u002F03.guides",[90,94,98,102],{"title":91,"path":92,"stem":93},"Custom Checkers","\u002Fdocs\u002Fbot-detection\u002Fguides\u002Fcustom","docs\u002Fbot-detection\u002F03.guides\u002FCUSTOM",{"title":95,"path":96,"stem":97},"Scheduling Database Generation","\u002Fdocs\u002Fbot-detection\u002Fguides\u002Fgenerate","docs\u002Fbot-detection\u002F03.guides\u002FGENERATE",{"title":99,"path":100,"stem":101},"Logging","\u002Fdocs\u002Fbot-detection\u002Fguides\u002Flogging","docs\u002Fbot-detection\u002F03.guides\u002FLOGGING",{"title":103,"path":104,"stem":105},"Score Modes and Reputation Healing","\u002Fdocs\u002Fbot-detection\u002Fguides\u002Fscore","docs\u002Fbot-detection\u002F03.guides\u002FSCORE",{"title":107,"path":108,"stem":109,"children":110},"Checkers","\u002Fdocs\u002Fbot-detection\u002Fcheckers","docs\u002Fbot-detection\u002F04.checkers\u002Findex",[111,112,116,120,124,128,132,136,140,144,148,152,156,160,164,168,172,176],{"title":107,"path":108,"stem":109},{"title":113,"path":114,"stem":115},"IP Validation","\u002Fdocs\u002Fbot-detection\u002Fcheckers\u002Fip-validation","docs\u002Fbot-detection\u002F04.checkers\u002F01.ip-validation",{"title":117,"path":118,"stem":119},"Good \u002F Bad Bot Verification","\u002Fdocs\u002Fbot-detection\u002Fcheckers\u002Fgood-bots","docs\u002Fbot-detection\u002F04.checkers\u002F02.good-bots",{"title":121,"path":122,"stem":123},"Browser & Device Fingerprint","\u002Fdocs\u002Fbot-detection\u002Fcheckers\u002Fbrowser-device","docs\u002Fbot-detection\u002F04.checkers\u002F03.browser-device",{"title":125,"path":126,"stem":127},"Locale Map","\u002Fdocs\u002Fbot-detection\u002Fcheckers\u002Flocale-map","docs\u002Fbot-detection\u002F04.checkers\u002F04.locale-map",{"title":129,"path":130,"stem":131},"Known Threats","\u002Fdocs\u002Fbot-detection\u002Fcheckers\u002Fknown-threats","docs\u002Fbot-detection\u002F04.checkers\u002F05.known-threats",{"title":133,"path":134,"stem":135},"ASN Classification","\u002Fdocs\u002Fbot-detection\u002Fcheckers\u002Fasn-classification","docs\u002Fbot-detection\u002F04.checkers\u002F06.asn-classification",{"title":137,"path":138,"stem":139},"Tor Analysis","\u002Fdocs\u002Fbot-detection\u002Fcheckers\u002Ftor-analysis","docs\u002Fbot-detection\u002F04.checkers\u002F07.tor-analysis",{"title":141,"path":142,"stem":143},"Timezone Consistency","\u002Fdocs\u002Fbot-detection\u002Fcheckers\u002Ftimezone-consistency","docs\u002Fbot-detection\u002F04.checkers\u002F08.timezone-consistency",{"title":145,"path":146,"stem":147},"Honeypot","\u002Fdocs\u002Fbot-detection\u002Fcheckers\u002Fhoneypot","docs\u002Fbot-detection\u002F04.checkers\u002F09.honeypot",{"title":149,"path":150,"stem":151},"Known Bad IPs","\u002Fdocs\u002Fbot-detection\u002Fcheckers\u002Fknown-bad-ips","docs\u002Fbot-detection\u002F04.checkers\u002F10.known-bad-ips",{"title":153,"path":154,"stem":155},"Behavior Rate","\u002Fdocs\u002Fbot-detection\u002Fcheckers\u002Fbehavior-rate","docs\u002Fbot-detection\u002F04.checkers\u002F11.behavior-rate",{"title":157,"path":158,"stem":159},"Proxy \u002F ISP \u002F Cookie","\u002Fdocs\u002Fbot-detection\u002Fcheckers\u002Fproxy-isp-cookies","docs\u002Fbot-detection\u002F04.checkers\u002F12.proxy-isp-cookies",{"title":161,"path":162,"stem":163},"Session Coherence","\u002Fdocs\u002Fbot-detection\u002Fcheckers\u002Fsession-coherence","docs\u002Fbot-detection\u002F04.checkers\u002F13.session-coherence",{"title":165,"path":166,"stem":167},"Velocity Fingerprint","\u002Fdocs\u002Fbot-detection\u002Fcheckers\u002Fvelocity-fingerprint","docs\u002Fbot-detection\u002F04.checkers\u002F14.velocity-fingerprint",{"title":169,"path":170,"stem":171},"UA & Header Analysis","\u002Fdocs\u002Fbot-detection\u002Fcheckers\u002Fua-header","docs\u002Fbot-detection\u002F04.checkers\u002F15.ua-header",{"title":173,"path":174,"stem":175},"Geolocation","\u002Fdocs\u002Fbot-detection\u002Fcheckers\u002Fgeolocation","docs\u002Fbot-detection\u002F04.checkers\u002F16.geolocation",{"title":177,"path":178,"stem":179},"Known Bad User-Agents","\u002Fdocs\u002Fbot-detection\u002Fcheckers\u002Fknown-bad-ua","docs\u002Fbot-detection\u002F04.checkers\u002F17.known-bad-ua",{"title":38,"path":181,"stem":182},"\u002Fdocs\u002Fbot-detection\u002Fsecurity","docs\u002Fbot-detection\u002F04.security",{"title":184,"path":185,"stem":186},"API Reference","\u002Fdocs\u002Fbot-detection\u002Fapi","docs\u002Fbot-detection\u002F05.api",{"title":188,"path":189,"stem":190},"Configuration","\u002Fdocs\u002Fbot-detection\u002Fconfiguration","docs\u002Fbot-detection\u002F06.configuration",[192],{"title":9,"path":66,"stem":67,"children":193,"page":53},[194,338,373,378,556,623],{"title":20,"path":22,"stem":195,"children":196},"docs\u002Fauth-h3client\u002Findex",[197,198,207,243,269,291,294,314,317],{"title":20,"path":22,"stem":195},{"title":14,"path":199,"stem":200,"children":201},"\u002Fdocs\u002Fauth-h3client\u002Fgetting-started","docs\u002Fauth-h3client\u002F00.getting-started\u002Findex",[202,203],{"title":14,"path":199,"stem":200},{"title":204,"path":205,"stem":206},"Nuxt Module","\u002Fdocs\u002Fauth-h3client\u002Fgetting-started\u002Fnuxt","docs\u002Fauth-h3client\u002F00.getting-started\u002F00.nuxt",{"title":208,"path":209,"stem":210,"children":211},"Essentials","\u002Fdocs\u002Fauth-h3client\u002Fessentials","docs\u002Fauth-h3client\u002F01.essentials\u002Findex",[212,213,217,221,225,229,233,236,240],{"title":208,"path":209,"stem":210},{"title":214,"path":215,"stem":216},"Session Management","\u002Fdocs\u002Fauth-h3client\u002Fessentials\u002Fsession","docs\u002Fauth-h3client\u002F01.essentials\u002F00.session",{"title":218,"path":219,"stem":220},"Route Protection","\u002Fdocs\u002Fauth-h3client\u002Fessentials\u002Froute-protection","docs\u002Fauth-h3client\u002F01.essentials\u002F01.route-protection",{"title":222,"path":223,"stem":224},"CSRF Protection","\u002Fdocs\u002Fauth-h3client\u002Fessentials\u002Fcsrf","docs\u002Fauth-h3client\u002F01.essentials\u002F02.csrf",{"title":226,"path":227,"stem":228},"Auth Flows","\u002Fdocs\u002Fauth-h3client\u002Fessentials\u002Fauth-flows","docs\u002Fauth-h3client\u002F01.essentials\u002F03.auth-flows",{"title":230,"path":231,"stem":232},"OAuth and OIDC","\u002Fdocs\u002Fauth-h3client\u002Fessentials\u002Foauth","docs\u002Fauth-h3client\u002F01.essentials\u002F04.oauth",{"title":33,"path":234,"stem":235},"\u002Fdocs\u002Fauth-h3client\u002Fessentials\u002Fbot-detection","docs\u002Fauth-h3client\u002F01.essentials\u002F05.bot-detection",{"title":237,"path":238,"stem":239},"Cookies","\u002Fdocs\u002Fauth-h3client\u002Fessentials\u002Fcookies","docs\u002Fauth-h3client\u002F01.essentials\u002F06.cookies",{"title":99,"path":241,"stem":242},"\u002Fdocs\u002Fauth-h3client\u002Fessentials\u002Flogging","docs\u002Fauth-h3client\u002F01.essentials\u002F07.logging",{"title":244,"path":245,"stem":246,"children":247},"MFA","\u002Fdocs\u002Fauth-h3client\u002Fmfa","docs\u002Fauth-h3client\u002F02.mfa\u002Findex",[248,249,253,257,261,265],{"title":244,"path":245,"stem":246},{"title":250,"path":251,"stem":252},"Built-in MFA","\u002Fdocs\u002Fauth-h3client\u002Fmfa\u002Fbuilt-in-flow","docs\u002Fauth-h3client\u002F02.mfa\u002F01.built-in-flow",{"title":254,"path":255,"stem":256},"Password Reset","\u002Fdocs\u002Fauth-h3client\u002Fmfa\u002Fpassword-reset","docs\u002Fauth-h3client\u002F02.mfa\u002F02.password-reset",{"title":258,"path":259,"stem":260},"Email Change","\u002Fdocs\u002Fauth-h3client\u002Fmfa\u002Femail-change","docs\u002Fauth-h3client\u002F02.mfa\u002F03.email-change",{"title":262,"path":263,"stem":264},"Custom MFA Flow","\u002Fdocs\u002Fauth-h3client\u002Fmfa\u002Fcustom-flow","docs\u002Fauth-h3client\u002F02.mfa\u002F04.custom-flow",{"title":266,"path":267,"stem":268},"Client-Side MFA","\u002Fdocs\u002Fauth-h3client\u002Fmfa\u002Fclient-side","docs\u002Fauth-h3client\u002F02.mfa\u002F05.client-side",{"title":270,"path":271,"stem":272,"children":273},"Client-side","\u002Fdocs\u002Fauth-h3client\u002Fclient","docs\u002Fauth-h3client\u002F03.client\u002Findex",[274,275,279,283,287],{"title":270,"path":271,"stem":272},{"title":276,"path":277,"stem":278},"useAuthData","\u002Fdocs\u002Fauth-h3client\u002Fclient\u002Fuse-auth-data","docs\u002Fauth-h3client\u002F03.client\u002F00.use-auth-data",{"title":280,"path":281,"stem":282},"useMagicLink","\u002Fdocs\u002Fauth-h3client\u002Fclient\u002Fuse-magic-link","docs\u002Fauth-h3client\u002F03.client\u002F01.use-magic-link",{"title":284,"path":285,"stem":286},"executeRequest","\u002Fdocs\u002Fauth-h3client\u002Fclient\u002Fexecute-request","docs\u002Fauth-h3client\u002F03.client\u002F02.execute-request",{"title":288,"path":289,"stem":290},"getCsrfToken","\u002Fdocs\u002Fauth-h3client\u002Fclient\u002Fget-csrf-token","docs\u002Fauth-h3client\u002F03.client\u002F03.get-csrf-token",{"title":38,"path":292,"stem":293},"\u002Fdocs\u002Fauth-h3client\u002Fsecurity","docs\u002Fauth-h3client\u002F04.security",{"title":86,"path":295,"stem":296,"children":297,"page":53},"\u002Fdocs\u002Fauth-h3client\u002Fguides","docs\u002Fauth-h3client\u002F05.guides",[298,302,306,310],{"title":299,"path":300,"stem":301},"H3 and Nitro Setup","\u002Fdocs\u002Fauth-h3client\u002Fguides\u002Fh3-nitro","docs\u002Fauth-h3client\u002F05.guides\u002F00.h3-nitro",{"title":303,"path":304,"stem":305},"HMAC Inter-service Auth","\u002Fdocs\u002Fauth-h3client\u002Fguides\u002Fhmac","docs\u002Fauth-h3client\u002F05.guides\u002Fhmac",{"title":307,"path":308,"stem":309},"Image Upload","\u002Fdocs\u002Fauth-h3client\u002Fguides\u002Fimage-upload","docs\u002Fauth-h3client\u002F05.guides\u002Fimage-upload",{"title":311,"path":312,"stem":313},"mTLS Configuration","\u002Fdocs\u002Fauth-h3client\u002Fguides\u002Fmtls","docs\u002Fauth-h3client\u002F05.guides\u002Fmtls",{"title":188,"path":315,"stem":316},"\u002Fdocs\u002Fauth-h3client\u002Fconfiguration","docs\u002Fauth-h3client\u002F06.configuration",{"title":184,"path":318,"stem":319,"children":320},"\u002Fdocs\u002Fauth-h3client\u002Fapi","docs\u002Fauth-h3client\u002F07.api\u002Findex",[321,322,326,330,334],{"title":184,"path":318,"stem":319},{"title":323,"path":324,"stem":325},"Routes Reference","\u002Fdocs\u002Fauth-h3client\u002Fapi\u002Fcontrollers","docs\u002Fauth-h3client\u002F07.api\u002F00.controllers",{"title":327,"path":328,"stem":329},"Middleware Reference","\u002Fdocs\u002Fauth-h3client\u002Fapi\u002Fmiddleware","docs\u002Fauth-h3client\u002F07.api\u002F01.middleware",{"title":331,"path":332,"stem":333},"Client-side Reference","\u002Fdocs\u002Fauth-h3client\u002Fapi\u002Fcomposables","docs\u002Fauth-h3client\u002F07.api\u002F02.composables",{"title":335,"path":336,"stem":337},"Utilities","\u002Fdocs\u002Fauth-h3client\u002Fapi\u002Futilities","docs\u002Fauth-h3client\u002F07.api\u002F03.utilities",{"title":70,"path":35,"stem":71,"children":339},[340,341,342,343,344,350,370,371,372],{"title":70,"path":35,"stem":71},{"title":14,"path":75,"stem":76},{"title":78,"path":79,"stem":80},{"title":82,"path":83,"stem":84},{"title":86,"path":87,"stem":88,"children":345,"page":53},[346,347,348,349],{"title":91,"path":92,"stem":93},{"title":95,"path":96,"stem":97},{"title":99,"path":100,"stem":101},{"title":103,"path":104,"stem":105},{"title":107,"path":108,"stem":109,"children":351},[352,353,354,355,356,357,358,359,360,361,362,363,364,365,366,367,368,369],{"title":107,"path":108,"stem":109},{"title":113,"path":114,"stem":115},{"title":117,"path":118,"stem":119},{"title":121,"path":122,"stem":123},{"title":125,"path":126,"stem":127},{"title":129,"path":130,"stem":131},{"title":133,"path":134,"stem":135},{"title":137,"path":138,"stem":139},{"title":141,"path":142,"stem":143},{"title":145,"path":146,"stem":147},{"title":149,"path":150,"stem":151},{"title":153,"path":154,"stem":155},{"title":157,"path":158,"stem":159},{"title":161,"path":162,"stem":163},{"title":165,"path":166,"stem":167},{"title":169,"path":170,"stem":171},{"title":173,"path":174,"stem":175},{"title":177,"path":178,"stem":179},{"title":38,"path":181,"stem":182},{"title":184,"path":185,"stem":186},{"title":188,"path":189,"stem":190},{"title":374,"path":11,"stem":375,"children":376},"Introduction","docs\u002Fgetting-started\u002Findex",[377],{"title":374,"path":11,"stem":375},{"title":27,"path":29,"stem":379,"children":380},"docs\u002Fiam\u002Findex",[381,382,385,520,523,539,542],{"title":27,"path":29,"stem":379},{"title":14,"path":383,"stem":384},"\u002Fdocs\u002Fiam\u002Fgetting-started","docs\u002Fiam\u002F00.getting-started",{"title":208,"path":386,"stem":387,"children":388},"\u002Fdocs\u002Fiam\u002Fessentials","docs\u002Fiam\u002F01.essentials\u002Findex",[389,390,394,398,402,406,410,414,418,422,426,430,433,437,441,445,449,452,456,460,463,467,470],{"title":208,"path":386,"stem":387},{"title":391,"path":392,"stem":393},"Tokens","\u002Fdocs\u002Fiam\u002Fessentials\u002Ftokens","docs\u002Fiam\u002F01.essentials\u002F00.tokens",{"title":395,"path":396,"stem":397},"Access Tokens","\u002Fdocs\u002Fiam\u002Fessentials\u002Faccess-tokens","docs\u002Fiam\u002F01.essentials\u002F01.access-tokens",{"title":399,"path":400,"stem":401},"Refresh Tokens","\u002Fdocs\u002Fiam\u002Fessentials\u002Frefresh-tokens","docs\u002Fiam\u002F01.essentials\u002F02.refresh-tokens",{"title":403,"path":404,"stem":405},"Anomaly Detection","\u002Fdocs\u002Fiam\u002Fessentials\u002Fanomalies","docs\u002Fiam\u002F01.essentials\u002F03.anomalies",{"title":407,"path":408,"stem":409},"Signup","\u002Fdocs\u002Fiam\u002Fessentials\u002Fsignup","docs\u002Fiam\u002F01.essentials\u002F04.signup",{"title":411,"path":412,"stem":413},"Login","\u002Fdocs\u002Fiam\u002Fessentials\u002Flogin","docs\u002Fiam\u002F01.essentials\u002F05.login",{"title":415,"path":416,"stem":417},"Logout","\u002Fdocs\u002Fiam\u002Fessentials\u002Flogout","docs\u002Fiam\u002F01.essentials\u002F06.logout",{"title":419,"path":420,"stem":421},"OAuth","\u002Fdocs\u002Fiam\u002Fessentials\u002Foauth","docs\u002Fiam\u002F01.essentials\u002F07.oauth",{"title":423,"path":424,"stem":425},"Magic Links","\u002Fdocs\u002Fiam\u002Fessentials\u002Fmagic-links","docs\u002Fiam\u002F01.essentials\u002F08.magic-links",{"title":427,"path":428,"stem":429},"Emails","\u002Fdocs\u002Fiam\u002Fessentials\u002Femails","docs\u002Fiam\u002F01.essentials\u002F09.emails",{"title":244,"path":431,"stem":432},"\u002Fdocs\u002Fiam\u002Fessentials\u002Fmfa","docs\u002Fiam\u002F01.essentials\u002F10.mfa",{"title":434,"path":435,"stem":436},"Fingerprinting","\u002Fdocs\u002Fiam\u002Fessentials\u002Ffingerprinting","docs\u002Fiam\u002F01.essentials\u002F11.fingerprinting",{"title":438,"path":439,"stem":440},"Backend for Frontend","\u002Fdocs\u002Fiam\u002Fessentials\u002Fbff","docs\u002Fiam\u002F01.essentials\u002F12.bff",{"title":442,"path":443,"stem":444},"HMAC Authentication","\u002Fdocs\u002Fiam\u002Fessentials\u002Fhmac","docs\u002Fiam\u002F01.essentials\u002F13.hmac",{"title":446,"path":447,"stem":448},"XSS Protection","\u002Fdocs\u002Fiam\u002Fessentials\u002Fxss","docs\u002Fiam\u002F01.essentials\u002F14.xss",{"title":99,"path":450,"stem":451},"\u002Fdocs\u002Fiam\u002Fessentials\u002Flogging","docs\u002Fiam\u002F01.essentials\u002F15.logging",{"title":453,"path":454,"stem":455},"Rate Limiting","\u002Fdocs\u002Fiam\u002Fessentials\u002Frate-limiting","docs\u002Fiam\u002F01.essentials\u002F16.rate-limiting",{"title":457,"path":458,"stem":459},"Database","\u002Fdocs\u002Fiam\u002Fessentials\u002Fdatabase","docs\u002Fiam\u002F01.essentials\u002F17.database",{"title":237,"path":461,"stem":462},"\u002Fdocs\u002Fiam\u002Fessentials\u002Fcookies","docs\u002Fiam\u002F01.essentials\u002F18.cookies",{"title":464,"path":465,"stem":466},"Service Startup","\u002Fdocs\u002Fiam\u002Fessentials\u002Fservice","docs\u002Fiam\u002F01.essentials\u002F19.service",{"title":254,"path":468,"stem":469},"\u002Fdocs\u002Fiam\u002Fessentials\u002Fpassword-reset","docs\u002Fiam\u002F01.essentials\u002F20.password-reset",{"title":471,"path":472,"stem":473,"children":474},"API Tokens","\u002Fdocs\u002Fiam\u002Fessentials\u002Fapi","docs\u002Fiam\u002F01.essentials\u002F21.api\u002Findex",[475,476,480,484,514,517],{"title":471,"path":472,"stem":473},{"title":477,"path":478,"stem":479},"Creating Tokens","\u002Fdocs\u002Fiam\u002Fessentials\u002Fapi\u002Fcreation","docs\u002Fiam\u002F01.essentials\u002F21.api\u002F00.creation",{"title":481,"path":482,"stem":483},"Verifying Tokens","\u002Fdocs\u002Fiam\u002Fessentials\u002Fapi\u002Fverification","docs\u002Fiam\u002F01.essentials\u002F21.api\u002F01.verification",{"title":485,"path":486,"stem":487,"children":488},"Manage Tokens","\u002Fdocs\u002Fiam\u002Fessentials\u002Fapi\u002Fmanagement","docs\u002Fiam\u002F01.essentials\u002F21.api\u002F02.management\u002Findex",[489,490,494,498,502,506,510],{"title":485,"path":486,"stem":487},{"title":491,"path":492,"stem":493},"Privileges","\u002Fdocs\u002Fiam\u002Fessentials\u002Fapi\u002Fmanagement\u002Fprivilege","docs\u002Fiam\u002F01.essentials\u002F21.api\u002F02.management\u002F00.privilege",{"title":495,"path":496,"stem":497},"Revocation","\u002Fdocs\u002Fiam\u002Fessentials\u002Fapi\u002Fmanagement\u002Frevocation","docs\u002Fiam\u002F01.essentials\u002F21.api\u002F02.management\u002F01.revocation",{"title":499,"path":500,"stem":501},"Rotation","\u002Fdocs\u002Fiam\u002Fessentials\u002Fapi\u002Fmanagement\u002Frotation","docs\u002Fiam\u002F01.essentials\u002F21.api\u002F02.management\u002F02.rotation",{"title":503,"path":504,"stem":505},"IP Restriction","\u002Fdocs\u002Fiam\u002Fessentials\u002Fapi\u002Fmanagement\u002Fip-updates","docs\u002Fiam\u002F01.essentials\u002F21.api\u002F02.management\u002F03.ip-updates",{"title":507,"path":508,"stem":509},"Metadata","\u002Fdocs\u002Fiam\u002Fessentials\u002Fapi\u002Fmanagement\u002Fmetadata","docs\u002Fiam\u002F01.essentials\u002F21.api\u002F02.management\u002F04.metadata",{"title":511,"path":512,"stem":513},"Token Listing","\u002Fdocs\u002Fiam\u002Fessentials\u002Fapi\u002Fmanagement\u002Flist","docs\u002Fiam\u002F01.essentials\u002F21.api\u002F02.management\u002F05.list",{"title":453,"path":515,"stem":516},"\u002Fdocs\u002Fiam\u002Fessentials\u002Fapi\u002Frate-limiting","docs\u002Fiam\u002F01.essentials\u002F21.api\u002F03.rate-limiting",{"title":38,"path":518,"stem":519},"\u002Fdocs\u002Fiam\u002Fessentials\u002Fapi\u002Fsecurity","docs\u002Fiam\u002F01.essentials\u002F21.api\u002F04.security",{"title":38,"path":521,"stem":522},"\u002Fdocs\u002Fiam\u002Fsecurity","docs\u002Fiam\u002F02.security",{"title":86,"path":524,"stem":525,"children":526,"page":53},"\u002Fdocs\u002Fiam\u002Fguides","docs\u002Fiam\u002F03.guides",[527,531,535],{"title":528,"path":529,"stem":530},"Deployment","\u002Fdocs\u002Fiam\u002Fguides\u002Fdeployment","docs\u002Fiam\u002F03.guides\u002Fdeployment",{"title":532,"path":533,"stem":534},"Operation Scripts","\u002Fdocs\u002Fiam\u002Fguides\u002Foperation-scripts","docs\u002Fiam\u002F03.guides\u002Foperation-scripts",{"title":536,"path":537,"stem":538},"Role-Based Access Control","\u002Fdocs\u002Fiam\u002Fguides\u002Frbac","docs\u002Fiam\u002F03.guides\u002Frbac",{"title":188,"path":540,"stem":541},"\u002Fdocs\u002Fiam\u002Fconfiguration","docs\u002Fiam\u002F04.configuration",{"title":543,"path":544,"stem":545,"children":546,"page":53},"Api","\u002Fdocs\u002Fiam\u002Fapi","docs\u002Fiam\u002F05.API",[547,550,553],{"title":184,"path":548,"stem":549},"\u002Fdocs\u002Fiam\u002Fapi\u002Fapi","docs\u002Fiam\u002F05.API\u002F00.api",{"title":327,"path":551,"stem":552},"\u002Fdocs\u002Fiam\u002Fapi\u002Fmiddlewares","docs\u002Fiam\u002F05.API\u002F02.middlewares",{"title":323,"path":554,"stem":555},"\u002Fdocs\u002Fiam\u002Fapi\u002Froutes","docs\u002Fiam\u002F05.API\u002F03.routes",{"title":40,"path":42,"stem":557,"children":558},"docs\u002Fshield-base\u002Findex",[559,560,563,567,608,612,616,620],{"title":40,"path":42,"stem":557},{"title":14,"path":561,"stem":562},"\u002Fdocs\u002Fshield-base\u002Fgetting-started","docs\u002Fshield-base\u002F00.getting-started",{"title":564,"path":565,"stem":566},"CLI Reference","\u002Fdocs\u002Fshield-base\u002Fcli","docs\u002Fshield-base\u002F01.cli",{"title":82,"path":568,"stem":569,"children":570},"\u002Fdocs\u002Fshield-base\u002Fdata-sources","docs\u002Fshield-base\u002F02.data-sources\u002Findex",[571,572,576,580,584,588,592,596,600,604],{"title":82,"path":568,"stem":569},{"title":573,"path":574,"stem":575},"BGP \u002F ASN","\u002Fdocs\u002Fshield-base\u002Fdata-sources\u002Fbgp","docs\u002Fshield-base\u002F02.data-sources\u002Fbgp",{"title":577,"path":578,"stem":579},"City Geolocation","\u002Fdocs\u002Fshield-base\u002Fdata-sources\u002Fcity","docs\u002Fshield-base\u002F02.data-sources\u002Fcity",{"title":581,"path":582,"stem":583},"Country Geolocation","\u002Fdocs\u002Fshield-base\u002Fdata-sources\u002Fcountry","docs\u002Fshield-base\u002F02.data-sources\u002Fcountry",{"title":585,"path":586,"stem":587},"Verified Crawlers","\u002Fdocs\u002Fshield-base\u002Fdata-sources\u002Fcrawlers","docs\u002Fshield-base\u002F02.data-sources\u002Fcrawlers",{"title":589,"path":590,"stem":591},"Disposable Emails","\u002Fdocs\u002Fshield-base\u002Fdata-sources\u002Femail","docs\u002Fshield-base\u002F02.data-sources\u002Femail",{"title":593,"path":594,"stem":595},"FireHOL Threat Intelligence","\u002Fdocs\u002Fshield-base\u002Fdata-sources\u002Ffirehol","docs\u002Fshield-base\u002F02.data-sources\u002Ffirehol",{"title":597,"path":598,"stem":599},"Proxy Detection","\u002Fdocs\u002Fshield-base\u002Fdata-sources\u002Fproxy","docs\u002Fshield-base\u002F02.data-sources\u002Fproxy",{"title":601,"path":602,"stem":603},"Tor Nodes","\u002Fdocs\u002Fshield-base\u002Fdata-sources\u002Ftor","docs\u002Fshield-base\u002F02.data-sources\u002Ftor",{"title":605,"path":606,"stem":607},"Suspicious User-Agents","\u002Fdocs\u002Fshield-base\u002Fdata-sources\u002Fuseragent","docs\u002Fshield-base\u002F02.data-sources\u002Fuseragent",{"title":609,"path":610,"stem":611},"Programmatic Usage","\u002Fdocs\u002Fshield-base\u002Fusage","docs\u002Fshield-base\u002F03.usage",{"title":613,"path":614,"stem":615},"Custom Data Sources","\u002Fdocs\u002Fshield-base\u002Fcustom-data-sources","docs\u002Fshield-base\u002F04.custom-data-sources",{"title":617,"path":618,"stem":619},"TypeScript Types","\u002Fdocs\u002Fshield-base\u002Ftypes","docs\u002Fshield-base\u002F05.types",{"title":184,"path":621,"stem":622},"\u002Fdocs\u002Fshield-base\u002Fapi","docs\u002Fshield-base\u002F06.api",{"title":335,"path":48,"stem":624,"children":625},"docs\u002Futils\u002Findex",[626,627,644,677,774],{"title":335,"path":48,"stem":624},{"title":628,"path":629,"stem":630,"children":631,"page":53},"Eslint","\u002Fdocs\u002Futils\u002Feslint","docs\u002Futils\u002Feslint",[632,636,640],{"title":633,"path":634,"stem":635},"React Config","\u002Fdocs\u002Futils\u002Feslint\u002Freact","docs\u002Futils\u002Feslint\u002Freact",{"title":637,"path":638,"stem":639},"TypeScript Config","\u002Fdocs\u002Futils\u002Feslint\u002Ftypescript","docs\u002Futils\u002Feslint\u002Ftypescript",{"title":641,"path":642,"stem":643},"Vue Config","\u002Fdocs\u002Futils\u002Feslint\u002Fvue","docs\u002Futils\u002Feslint\u002Fvue",{"title":645,"path":646,"stem":647,"children":648,"page":53},"Server","\u002Fdocs\u002Futils\u002Fserver","docs\u002Futils\u002Fserver",[649,653,657,661,665,669,673],{"title":650,"path":651,"stem":652},"Encryption","\u002Fdocs\u002Futils\u002Fserver\u002Fencryption","docs\u002Futils\u002Fserver\u002Fencryption",{"title":654,"path":655,"stem":656},"Path Resolver","\u002Fdocs\u002Futils\u002Fserver\u002Fpathresolver","docs\u002Futils\u002Fserver\u002FpathResolver",{"title":658,"path":659,"stem":660},"File Replacements","\u002Fdocs\u002Futils\u002Fserver\u002Freplace","docs\u002Futils\u002Fserver\u002Freplace",{"title":662,"path":663,"stem":664},"run","\u002Fdocs\u002Futils\u002Fserver\u002Frun","docs\u002Futils\u002Fserver\u002Frun",{"title":666,"path":667,"stem":668},"scheduleTask","\u002Fdocs\u002Futils\u002Fserver\u002Fscheduletask","docs\u002Futils\u002Fserver\u002FscheduleTask",{"title":670,"path":671,"stem":672},"spawnRun","\u002Fdocs\u002Futils\u002Fserver\u002Fspawnrun","docs\u002Futils\u002Fserver\u002FspawnRun",{"title":674,"path":675,"stem":676},"uploadCsv","\u002Fdocs\u002Futils\u002Fserver\u002Fuploadcsv","docs\u002Futils\u002Fserver\u002FuploadCsv",{"title":678,"path":679,"stem":680,"children":681,"page":53},"Shared","\u002Fdocs\u002Futils\u002Fshared","docs\u002Futils\u002Fshared",[682,686,690,694,698,702,706,710,714,718,722,726,730,734,738,742,746,750,754,758,762,766,770],{"title":683,"path":684,"stem":685},"BatchQueue","\u002Fdocs\u002Futils\u002Fshared\u002Fbatchqueue","docs\u002Futils\u002Fshared\u002FbatchQueue",{"title":687,"path":688,"stem":689},"capitalize","\u002Fdocs\u002Futils\u002Fshared\u002Fcapitalize","docs\u002Futils\u002Fshared\u002Fcapitalize",{"title":691,"path":692,"stem":693},"chunkProcess","\u002Fdocs\u002Futils\u002Fshared\u002Fchunkprocess","docs\u002Futils\u002Fshared\u002FchunkProcess",{"title":695,"path":696,"stem":697},"cleanObject","\u002Fdocs\u002Futils\u002Fshared\u002Fcleanobject","docs\u002Futils\u002Fshared\u002FcleanObject",{"title":699,"path":700,"stem":701},"createConfigManager","\u002Fdocs\u002Futils\u002Fshared\u002Fconfigurationdefiner","docs\u002Futils\u002Fshared\u002FconfigurationDefiner",{"title":703,"path":704,"stem":705},"debounce","\u002Fdocs\u002Futils\u002Fshared\u002Fdebounce","docs\u002Futils\u002Fshared\u002Fdebounce",{"title":707,"path":708,"stem":709},"ensureArray","\u002Fdocs\u002Futils\u002Fshared\u002Fensurearray","docs\u002Futils\u002Fshared\u002FensureArray",{"title":711,"path":712,"stem":713},"fetchWithRetry","\u002Fdocs\u002Futils\u002Fshared\u002Ffetchwithretry","docs\u002Futils\u002Fshared\u002FfetchWithRetry",{"title":715,"path":716,"stem":717},"filterEmptyValues","\u002Fdocs\u002Futils\u002Fshared\u002Ffilteremptyvalues","docs\u002Futils\u002Fshared\u002FfilterEmptyValues",{"title":719,"path":720,"stem":721},"findStringsInObject","\u002Fdocs\u002Futils\u002Fshared\u002Ffindobjectvalues","docs\u002Futils\u002Fshared\u002FfindObjectValues",{"title":723,"path":724,"stem":725},"fisherYatesShuffle","\u002Fdocs\u002Futils\u002Fshared\u002Ffisheryatesshuffle","docs\u002Futils\u002Fshared\u002FfisherYatesShuffle",{"title":727,"path":728,"stem":729},"getRandomImage","\u002Fdocs\u002Futils\u002Fshared\u002Fgetrandomimage","docs\u002Futils\u002Fshared\u002FgetRandomImage",{"title":731,"path":732,"stem":733},"isObjectHasValues","\u002Fdocs\u002Futils\u002Fshared\u002Fisobjecthasvalues","docs\u002Futils\u002Fshared\u002FisObjectHasValues",{"title":735,"path":736,"stem":737},"isAsyncOrPromise","\u002Fdocs\u002Futils\u002Fshared\u002Fispromise","docs\u002Futils\u002Fshared\u002FisPromise",{"title":739,"path":740,"stem":741},"MiniCache","\u002Fdocs\u002Futils\u002Fshared\u002Fminicache","docs\u002Futils\u002Fshared\u002FminiCache",{"title":743,"path":744,"stem":745},"parseCookies","\u002Fdocs\u002Futils\u002Fshared\u002Fparserawcookies","docs\u002Futils\u002Fshared\u002FparseRawCookies",{"title":747,"path":748,"stem":749},"safeAction","\u002Fdocs\u002Futils\u002Fshared\u002Fpromiselocker","docs\u002Futils\u002Fshared\u002FpromiseLocker",{"title":751,"path":752,"stem":753},"Random","\u002Fdocs\u002Futils\u002Fshared\u002Frandom","docs\u002Futils\u002Fshared\u002Frandom",{"title":755,"path":756,"stem":757},"range","\u002Fdocs\u002Futils\u002Fshared\u002Frange","docs\u002Futils\u002Fshared\u002Frange",{"title":759,"path":760,"stem":761},"rateLimiters","\u002Fdocs\u002Futils\u002Fshared\u002Fratelimiters","docs\u002Futils\u002Fshared\u002FrateLimiters",{"title":763,"path":764,"stem":765},"safeObjectMerge","\u002Fdocs\u002Futils\u002Fshared\u002Fsafemerge","docs\u002Futils\u002Fshared\u002FsafeMerge",{"title":767,"path":768,"stem":769},"textTruncation","\u002Fdocs\u002Futils\u002Fshared\u002Ftexttruncation","docs\u002Futils\u002Fshared\u002FtextTruncation",{"title":771,"path":772,"stem":773},"validateZodSchema","\u002Fdocs\u002Futils\u002Fshared\u002Fvalidatezodschema","docs\u002Futils\u002Fshared\u002FvalidateZodSchema",{"title":775,"path":776,"stem":777,"children":778},"Utility Types","\u002Fdocs\u002Futils\u002Ftypes","docs\u002Futils\u002Ftypes\u002Findex",[779,780,784,788,792,796,800,804,808,812],{"title":775,"path":776,"stem":777},{"title":781,"path":782,"stem":783},"Brand","\u002Fdocs\u002Futils\u002Ftypes\u002Fbrand","docs\u002Futils\u002Ftypes\u002FBrand",{"title":785,"path":786,"stem":787},"DeepPartial","\u002Fdocs\u002Futils\u002Ftypes\u002Fdeeppartial","docs\u002Futils\u002Ftypes\u002FDeepPartial",{"title":789,"path":790,"stem":791},"Merge","\u002Fdocs\u002Futils\u002Ftypes\u002Fmerge","docs\u002Futils\u002Ftypes\u002FMerge",{"title":793,"path":794,"stem":795},"NonNullable","\u002Fdocs\u002Futils\u002Ftypes\u002Fnonnullable","docs\u002Futils\u002Ftypes\u002FNonNullable",{"title":797,"path":798,"stem":799},"Prettify","\u002Fdocs\u002Futils\u002Ftypes\u002Fprettify","docs\u002Futils\u002Ftypes\u002FPrettify",{"title":801,"path":802,"stem":803},"PromiseType","\u002Fdocs\u002Futils\u002Ftypes\u002Fpromisetype","docs\u002Futils\u002Ftypes\u002FPromiseType",{"title":805,"path":806,"stem":807},"RequireKeys","\u002Fdocs\u002Futils\u002Ftypes\u002Frequirekeys","docs\u002Futils\u002Ftypes\u002FRequireKeys",{"title":809,"path":810,"stem":811},"StandardResponse","\u002Fdocs\u002Futils\u002Ftypes\u002Fstandardresponse","docs\u002Futils\u002Ftypes\u002FStandardResponse",{"title":813,"path":814,"stem":815},"ValueOf","\u002Fdocs\u002Futils\u002Ftypes\u002Fvalueof","docs\u002Futils\u002Ftypes\u002FValueOf",{"id":4,"extension":5,"links":817,"meta":828,"stem":62,"__hash__":63},[818,826,827],{"nested":8,"label":9,"icon":10,"to":11,"children":819},[820,821,822,823,824,825],{"label":14,"icon":15,"to":11,"description":16,"github":17,"badge":18},{"label":20,"icon":21,"to":22,"description":23,"github":24,"badge":25},{"label":27,"icon":28,"to":29,"description":30,"github":31,"badge":25},{"label":33,"icon":34,"to":35,"description":36,"github":37,"badge":38},{"label":40,"icon":41,"to":42,"description":43,"github":44,"badge":38},{"label":46,"icon":47,"to":48,"description":49,"github":50,"badge":51},{"nested":53,"label":54,"icon":55,"to":56},{"nested":53,"label":58,"icon":59,"to":60},{},{"id":830,"title":188,"body":831,"description":3505,"extension":3506,"icon":3507,"meta":3508,"module":3509,"navigation":8,"path":189,"rawbody":3510,"seo":3511,"stem":190,"__hash__":3512},"docs\u002Fdocs\u002Fbot-detection\u002F06.configuration.md",{"type":832,"value":833,"toc":3468},"minimark",[834,846,951,954,960,969,984,1079,1207,1209,1214,1219,1230,1389,1473,1493,1495,1501,1525,1541,1543,1549,1559,1561,1567,1589,1591,1597,1633,1635,1641,1650,1688,1690,1696,1699,1727,1774,1776,1782,1785,1813,1815,1821,1844,1858,1860,1866,1886,1888,1893,1904,1976,1983,1989,1996,2006,2008,2014,2018,2025,2037,2059,2061,2067,2071,2074,2081,2164,2166,2172,2176,2185,2189,2230,2232,2238,2242,2253,2265,2307,2309,2315,2319,2322,2326,2374,2376,2382,2386,2389,2393,2443,2445,2451,2455,2458,2467,2469,2474,2478,2495,2506,2568,2570,2576,2580,2591,2603,2612,2614,2620,2625,2636,2661,2719,2721,2727,2731,2738,2742,2804,2806,2812,2816,2819,2823,2871,2873,2879,2883,2886,2895,2902,2986,2988,2994,2998,3008,3012,3038,3040,3046,3050,3057,3074,3076,3081,3085,3088,3092,3126,3142,3144,3150,3156,3323,3325,3331,3338,3389,3391,3396,3406,3464],[835,836,837,841,842,845],"p",{},[838,839,840],"code",{},"defineConfiguration"," accepts a single configuration object. Every field has a default value, only ",[838,843,844],{},"store.main"," is required. The configuration is validated against a Zod schema at startup. Invalid values cause the server to fail immediately with a clear error message.",[847,848,854],"pre",{"className":849,"code":850,"filename":851,"language":852,"meta":853,"style":853},"language-ts shiki shiki-themes light-plus light-plus dracula","await defineConfiguration({\n  store: {\n    main: { driver: 'sqlite', name: '.\u002Fbot-detector.db' },\n  },\n  \u002F\u002F All other options are optional and have defaults\n})\n","server.ts","ts","",[838,855,856,873,887,932,938,945],{"__ignoreMap":853},[857,858,861,865,869],"span",{"class":859,"line":860},"line",1,[857,862,864],{"class":863},"sZ328","await",[857,866,868],{"class":867},"sHOzp"," defineConfiguration",[857,870,872],{"class":871},"sDd4n","({\n",[857,874,876,880,884],{"class":859,"line":875},2,[857,877,879],{"class":878},"sjsA6","  store",[857,881,883],{"class":882},"s34zl",":",[857,885,886],{"class":871}," {\n",[857,888,890,893,895,898,901,903,907,911,914,917,920,922,924,927,929],{"class":859,"line":889},3,[857,891,892],{"class":878},"    main",[857,894,883],{"class":882},[857,896,897],{"class":871}," { ",[857,899,900],{"class":878},"driver",[857,902,883],{"class":882},[857,904,906],{"class":905},"sFkSl"," '",[857,908,910],{"class":909},"sFB1V","sqlite",[857,912,913],{"class":905},"'",[857,915,916],{"class":871},", ",[857,918,919],{"class":878},"name",[857,921,883],{"class":882},[857,923,906],{"class":905},[857,925,926],{"class":909},".\u002Fbot-detector.db",[857,928,913],{"class":905},[857,930,931],{"class":871}," },\n",[857,933,935],{"class":859,"line":934},4,[857,936,937],{"class":871},"  },\n",[857,939,941],{"class":859,"line":940},5,[857,942,944],{"class":943},"sghk6","  \u002F\u002F All other options are optional and have defaults\n",[857,946,948],{"class":859,"line":947},6,[857,949,950],{"class":871},"})\n",[952,953],"hr",{},[955,956,958],"h2",{"id":957},"store",[838,959,957],{},[835,961,962,963,965,966,968],{},"The ",[838,964,957],{}," object configures the persistent database where visitor records and ban history are stored. Only ",[838,967,844],{}," is required.",[970,971,975],"field",{"name":972,"type":973,":required":974},"main","DbConfig","true",[835,976,977,978,980,981,983],{},"The database driver configuration. Pass the driver name and any connection options it requires. ",[838,979,973],{}," is a discriminated union keyed on ",[838,982,900],{},".",[985,986,987,1005],"table",{},[988,989,990],"thead",{},[991,992,993,997,1002],"tr",{},[994,995,996],"th",{},"Driver",[994,998,999,1001],{},[838,1000,900],{}," value",[994,1003,1004],{},"Required peer dep",[1006,1007,1008,1023,1038,1053,1066],"tbody",{},[991,1009,1010,1014,1018],{},[1011,1012,1013],"td",{},"SQLite",[1011,1015,1016],{},[838,1017,910],{},[1011,1019,1020],{},[838,1021,1022],{},"better-sqlite3",[991,1024,1025,1028,1033],{},[1011,1026,1027],{},"MySQL connection pool",[1011,1029,1030],{},[838,1031,1032],{},"mysql-pool",[1011,1034,1035],{},[838,1036,1037],{},"mysql2 >= 3",[991,1039,1040,1043,1048],{},[1011,1041,1042],{},"PostgreSQL",[1011,1044,1045],{},[838,1046,1047],{},"postgresql",[1011,1049,1050],{},[838,1051,1052],{},"pg",[991,1054,1055,1058,1063],{},[1011,1056,1057],{},"Cloudflare D1",[1011,1059,1060],{},[838,1061,1062],{},"cloudflare-d1",[1011,1064,1065],{},"Worker environment binding",[991,1067,1068,1071,1076],{},[1011,1069,1070],{},"PlanetScale",[1011,1072,1073],{},[838,1074,1075],{},"planetscale",[1011,1077,1078],{},"Serverless driver",[847,1080,1082],{"className":849,"code":1081,"filename":851,"language":852,"meta":853,"style":853},"\u002F\u002F SQLite: good default for single-server deployments\nstore: { main: { driver: 'sqlite', name: '.\u002Fbot-detector.db' } }\n\n\u002F\u002F MySQL pool\nstore: { main: { driver: 'mysql-pool', host: 'localhost', user: 'root', password: 'secret', database: 'mydb' } }\n\n\u002F\u002F PostgreSQL\nstore: { main: { driver: 'postgresql', connectionString: 'postgres:\u002F\u002Fuser:pass@localhost\u002Fmydb' } }\n",[838,1083,1084,1089,1112,1117,1122,1174,1178,1184],{"__ignoreMap":853},[857,1085,1086],{"class":859,"line":860},[857,1087,1088],{"class":943},"\u002F\u002F SQLite: good default for single-server deployments\n",[857,1090,1091,1094,1096,1098,1100,1103,1105,1107,1109],{"class":859,"line":875},[857,1092,1093],{"class":871},"store: { main: { driver: ",[857,1095,913],{"class":905},[857,1097,910],{"class":909},[857,1099,913],{"class":905},[857,1101,1102],{"class":871},", name: ",[857,1104,913],{"class":905},[857,1106,926],{"class":909},[857,1108,913],{"class":905},[857,1110,1111],{"class":871}," } }\n",[857,1113,1114],{"class":859,"line":889},[857,1115,1116],{"emptyLinePlaceholder":8},"\n",[857,1118,1119],{"class":859,"line":934},[857,1120,1121],{"class":943},"\u002F\u002F MySQL pool\n",[857,1123,1124,1126,1128,1130,1132,1135,1137,1140,1142,1145,1147,1150,1152,1155,1157,1160,1162,1165,1167,1170,1172],{"class":859,"line":940},[857,1125,1093],{"class":871},[857,1127,913],{"class":905},[857,1129,1032],{"class":909},[857,1131,913],{"class":905},[857,1133,1134],{"class":871},", host: ",[857,1136,913],{"class":905},[857,1138,1139],{"class":909},"localhost",[857,1141,913],{"class":905},[857,1143,1144],{"class":871},", user: ",[857,1146,913],{"class":905},[857,1148,1149],{"class":909},"root",[857,1151,913],{"class":905},[857,1153,1154],{"class":871},", password: ",[857,1156,913],{"class":905},[857,1158,1159],{"class":909},"secret",[857,1161,913],{"class":905},[857,1163,1164],{"class":871},", database: ",[857,1166,913],{"class":905},[857,1168,1169],{"class":909},"mydb",[857,1171,913],{"class":905},[857,1173,1111],{"class":871},[857,1175,1176],{"class":859,"line":947},[857,1177,1116],{"emptyLinePlaceholder":8},[857,1179,1181],{"class":859,"line":1180},7,[857,1182,1183],{"class":943},"\u002F\u002F PostgreSQL\n",[857,1185,1187,1189,1191,1193,1195,1198,1200,1203,1205],{"class":859,"line":1186},8,[857,1188,1093],{"class":871},[857,1190,913],{"class":905},[857,1192,1047],{"class":909},[857,1194,913],{"class":905},[857,1196,1197],{"class":871},", connectionString: ",[857,1199,913],{"class":905},[857,1201,1202],{"class":909},"postgres:\u002F\u002Fuser:pass@localhost\u002Fmydb",[857,1204,913],{"class":905},[857,1206,1111],{"class":871},[952,1208],{},[955,1210,1212],{"id":1211},"storage",[838,1213,1211],{},[835,1215,962,1216,1218],{},[838,1217,1211],{}," field configures the cache layer where visitor state, behavioral rate counters, and session records are stored between requests. When omitted, everything is stored in process memory, which works for single-process deployments but is lost on restart and not shared across multiple instances.",[970,1220,1222],{"name":1211,"type":1221},"CacheConfig",[835,1223,1224,1225,980,1227,1229],{},"Optional cache driver configuration. ",[838,1226,1221],{},[838,1228,900],{},". Omit this field to use in-process memory.",[985,1231,1232,1245],{},[988,1233,1234],{},[991,1235,1236,1238,1242],{},[994,1237,996],{},[994,1239,1240,1001],{},[838,1241,900],{},[994,1243,1244],{},"Notes",[1006,1246,1247,1264,1285,1298,1311,1324,1341,1362,1376],{},[991,1248,1249,1252,1261],{},[1011,1250,1251],{},"Memory (default)",[1011,1253,1254],{},[1255,1256,1257,1258,1260],"em",{},"(omit ",[838,1259,1211],{},")",[1011,1262,1263],{},"Single-process only, lost on restart",[991,1265,1266,1269,1274],{},[1011,1267,1268],{},"LRU cache",[1011,1270,1271],{},[838,1272,1273],{},"lru",[1011,1275,1276,1277,1280,1281,1284],{},"In-process LRU; set ",[838,1278,1279],{},"max"," (item limit) and ",[838,1282,1283],{},"ttl"," (ms)",[991,1286,1287,1290,1295],{},[1011,1288,1289],{},"Redis",[1011,1291,1292],{},[838,1293,1294],{},"redis",[1011,1296,1297],{},"Recommended for multi-instance deployments",[991,1299,1300,1303,1308],{},[1011,1301,1302],{},"Upstash Redis",[1011,1304,1305],{},[838,1306,1307],{},"upstash",[1011,1309,1310],{},"Serverless Redis via HTTP",[991,1312,1313,1316,1321],{},[1011,1314,1315],{},"Filesystem",[1011,1317,1318],{},[838,1319,1320],{},"fs",[1011,1322,1323],{},"Persistent local storage, good for development",[991,1325,1326,1329,1334],{},[1011,1327,1328],{},"Cloudflare KV (binding)",[1011,1330,1331],{},[838,1332,1333],{},"cloudflare-kv-binding",[1011,1335,1336,1337,1340],{},"Pass ",[838,1338,1339],{},"binding"," from the Worker environment",[991,1342,1343,1346,1351],{},[1011,1344,1345],{},"Cloudflare KV (HTTP)",[1011,1347,1348],{},[838,1349,1350],{},"cloudflare-kv-http",[1011,1352,1336,1353,916,1356,916,1359],{},[838,1354,1355],{},"accountId",[838,1357,1358],{},"namespaceId",[838,1360,1361],{},"apiToken",[991,1363,1364,1367,1372],{},[1011,1365,1366],{},"Cloudflare R2",[1011,1368,1369],{},[838,1370,1371],{},"cloudflare-r2-binding",[1011,1373,1336,1374],{},[838,1375,1339],{},[991,1377,1378,1381,1386],{},[1011,1379,1380],{},"Vercel",[1011,1382,1383],{},[838,1384,1385],{},"vercel",[1011,1387,1388],{},"Vercel Runtime Cache",[847,1390,1392],{"className":849,"code":1391,"filename":851,"language":852,"meta":853,"style":853},"\u002F\u002F Redis: shared state across multiple app instances\nstorage: { driver: 'redis', host: 'localhost', port: 6379 }\n\n\u002F\u002F LRU: bounded in-process cache\nstorage: { driver: 'lru', max: 10000, ttl: 1000 * 60 * 10 }\n",[838,1393,1394,1399,1428,1432,1437],{"__ignoreMap":853},[857,1395,1396],{"class":859,"line":860},[857,1397,1398],{"class":943},"\u002F\u002F Redis: shared state across multiple app instances\n",[857,1400,1401,1404,1406,1408,1410,1412,1414,1416,1418,1421,1425],{"class":859,"line":875},[857,1402,1403],{"class":871},"storage: { driver: ",[857,1405,913],{"class":905},[857,1407,1294],{"class":909},[857,1409,913],{"class":905},[857,1411,1134],{"class":871},[857,1413,913],{"class":905},[857,1415,1139],{"class":909},[857,1417,913],{"class":905},[857,1419,1420],{"class":871},", port: ",[857,1422,1424],{"class":1423},"spgvN","6379",[857,1426,1427],{"class":871}," }\n",[857,1429,1430],{"class":859,"line":889},[857,1431,1116],{"emptyLinePlaceholder":8},[857,1433,1434],{"class":859,"line":934},[857,1435,1436],{"class":943},"\u002F\u002F LRU: bounded in-process cache\n",[857,1438,1439,1441,1443,1445,1447,1450,1453,1456,1459,1463,1466,1468,1471],{"class":859,"line":940},[857,1440,1403],{"class":871},[857,1442,913],{"class":905},[857,1444,1273],{"class":909},[857,1446,913],{"class":905},[857,1448,1449],{"class":871},", max: ",[857,1451,1452],{"class":1423},"10000",[857,1454,1455],{"class":871},", ttl: ",[857,1457,1458],{"class":1423},"1000",[857,1460,1462],{"class":1461},"saOXh"," *",[857,1464,1465],{"class":1423}," 60",[857,1467,1462],{"class":1461},[857,1469,1470],{"class":1423}," 10",[857,1472,1427],{"class":871},[1474,1475,1476],"warning",{},[835,1477,1478,1479,1481,1482,916,1484,1486,1487,1489,1490,1492],{},"When running multiple Node.js processes behind a load balancer, omitting ",[838,1480,1211],{}," or using an in-process driver (",[838,1483,1273],{},[838,1485,1320],{},") means each process maintains its own independent behavioral state. The rate tracking, velocity fingerprint, and session coherence checkers all key their cache entries by canary cookie. If a load balancer routes consecutive requests from the same visitor to different processes, those checkers will see incomplete histories and produce weaker or inconsistent signals. Configure a shared external driver such as ",[838,1488,1294],{}," or ",[838,1491,1307],{}," so all instances read and write the same state.",[952,1494],{},[955,1496,1498],{"id":1497},"banscore",[838,1499,1500],{},"banScore",[970,1502,1504,1515],{"name":1500,"type":1503},"number",[835,1505,1506,1507,1510,1511,1514],{},"Default: ",[838,1508,1509],{},"100",". The cumulative score threshold at which a visitor is banned. When a request's accumulated penalty points reach or exceed this value at any point in the pipeline, the middleware immediately responds with ",[838,1512,1513],{},"403"," and records the ban.",[835,1516,1517,1518,1521,1522,1524],{},"Lower values ban visitors more aggressively. A value of ",[838,1519,1520],{},"30"," would ban a visitor that triggers just two or three moderate checks, while the default of ",[838,1523,1509],{}," requires several checks to fail before a ban is issued.",[847,1526,1528],{"className":849,"code":1527,"language":852,"meta":853,"style":853},"banScore: 75 \u002F\u002F ban after accumulating 75 penalty points\n",[838,1529,1530],{"__ignoreMap":853},[857,1531,1532,1535,1538],{"class":859,"line":860},[857,1533,1534],{"class":871},"banScore: ",[857,1536,1537],{"class":1423},"75",[857,1539,1540],{"class":943}," \u002F\u002F ban after accumulating 75 penalty points\n",[952,1542],{},[955,1544,1546],{"id":1545},"maxscore",[838,1547,1548],{},"maxScore",[970,1550,1551],{"name":1548,"type":1503},[835,1552,1506,1553,1555,1556,1558],{},[838,1554,1509],{},". The ceiling on the total score that any single request can accumulate. Penalty points beyond this value are ignored. In most configurations this matches ",[838,1557,1500],{},", but you can set it lower to cap extreme outliers from inflating scores beyond what is meaningful.",[952,1560],{},[955,1562,1564],{"id":1563},"restoredreputationpoints",[838,1565,1566],{},"restoredReputationPoints",[970,1568,1569,1575],{"name":1566,"type":1503},[835,1570,1506,1571,1574],{},[838,1572,1573],{},"10",". The number of points the reputation healer subtracts from a visitor's stored score after each clean request. A clean request is one that does not result in a ban. This gives legitimate visitors a path to recover from an initial high score caused by unusual network conditions.",[835,1576,1577,1578,1581,1582,1585,1586,983],{},"For example, with ",[838,1579,1580],{},"restoredReputationPoints: 10"," and an initial score of ",[838,1583,1584],{},"40",", a visitor needs four consecutive clean requests to reach a score of ",[838,1587,1588],{},"0",[952,1590],{},[955,1592,1594],{"id":1593},"setnewcomputedscore",[838,1595,1596],{},"setNewComputedScore",[970,1598,1600,1606,1619,1627],{"name":1596,"type":1599},"boolean",[835,1601,1506,1602,1605],{},[838,1603,1604],{},"false",". Controls how the computed bot score is written to the database on each request.",[955,1607,1609,1615,1616,1618],{"id":1608},"false-snapshot-then-heal-default-the-detector-writes-the-computed-score-once-on-the-visitors-first-request-or-after-the-cache-expires-on-every-subsequent-request-the-reputation-healer-decrements-the-stored-score-by-restoredreputationpoints-this-mode-is-efficient-because-the-expensive-score-computation-only-runs-on-cache-misses",[1610,1611,1612,1614],"strong",{},[838,1613,1604],{},": Snapshot then heal (default)."," The detector writes the computed score once on the visitor's first request (or after the cache expires). On every subsequent request, the reputation healer decrements the stored score by ",[838,1617,1566],{},". This mode is efficient because the expensive score computation only runs on cache misses.",[835,1620,1621,1626],{},[1610,1622,1623,1625],{},[838,1624,974],{},": Live snapshot."," The detector overwrites the stored score on every single request. The reputation healer then immediately decrements it. The database always reflects the freshest computed risk for every visitor, at the cost of one extra database write per request.",[835,1628,1629,1630,1632],{},"Choose ",[838,1631,974],{}," when you need your dashboard or reporting tools to show the current risk score after every page view.",[952,1634],{},[955,1636,1638],{"id":1637},"whitelist",[838,1639,1640],{},"whiteList",[970,1642,1644],{"name":1640,"type":1643},"(IPv4 | IPv6 | string)[]",[835,1645,1506,1646,1649],{},[838,1647,1648],{},"[]",". A list of IP addresses or CIDR strings that bypass the entire detection pipeline. Requests from these addresses skip all checkers and pass directly to the next handler. This is useful for internal monitoring tools, health check probes, or trusted partner IPs.",[847,1651,1653],{"className":849,"code":1652,"language":852,"meta":853,"style":853},"whiteList: ['127.0.0.1', '::1', '10.0.0.0\u002F8']\n",[838,1654,1655],{"__ignoreMap":853},[857,1656,1657,1660,1662,1665,1667,1669,1671,1674,1676,1678,1680,1683,1685],{"class":859,"line":860},[857,1658,1659],{"class":871},"whiteList: [",[857,1661,913],{"class":905},[857,1663,1664],{"class":909},"127.0.0.1",[857,1666,913],{"class":905},[857,1668,916],{"class":871},[857,1670,913],{"class":905},[857,1672,1673],{"class":909},"::1",[857,1675,913],{"class":905},[857,1677,916],{"class":871},[857,1679,913],{"class":905},[857,1681,1682],{"class":909},"10.0.0.0\u002F8",[857,1684,913],{"class":905},[857,1686,1687],{"class":871},"]\n",[952,1689],{},[955,1691,1693],{"id":1692},"checkstimeratecontrol",[838,1694,1695],{},"checksTimeRateControl",[835,1697,1698],{},"Controls how often the full detection pipeline runs for returning visitors who are already cached.",[1700,1701,1702,1713],"field-group",{},[970,1703,1705],{"name":1704,"type":1599},"checkEveryRequest",[835,1706,1506,1707,1709,1710,1712],{},[838,1708,974],{},". When ",[838,1711,974],{},", runs the full pipeline on every request regardless of cache.",[970,1714,1716],{"name":1715,"type":1503},"checkEvery",[835,1717,1506,1718,1709,1721,1723,1724,1726],{},[838,1719,1720],{},"300000",[838,1722,1704],{}," is ",[838,1725,1604],{},", only re-runs the pipeline after this many milliseconds (5 minutes by default). A visitor whose result is cached passes through immediately until this interval elapses.",[847,1728,1730],{"className":849,"code":1729,"language":852,"meta":853,"style":853},"checksTimeRateControl: {\n  checkEveryRequest: false,\n  checkEvery: 1000 * 60 * 2, \u002F\u002F re-check every 2 minutes\n}\n",[838,1731,1732,1737,1748,1769],{"__ignoreMap":853},[857,1733,1734],{"class":859,"line":860},[857,1735,1736],{"class":871},"checksTimeRateControl: {\n",[857,1738,1739,1742,1745],{"class":859,"line":875},[857,1740,1741],{"class":871},"  checkEveryRequest: ",[857,1743,1604],{"class":1744},"sjR7W",[857,1746,1747],{"class":871},",\n",[857,1749,1750,1753,1755,1757,1759,1761,1764,1766],{"class":859,"line":889},[857,1751,1752],{"class":871},"  checkEvery: ",[857,1754,1458],{"class":1423},[857,1756,1462],{"class":1461},[857,1758,1465],{"class":1423},[857,1760,1462],{"class":1461},[857,1762,1763],{"class":1423}," 2",[857,1765,916],{"class":871},[857,1767,1768],{"class":943},"\u002F\u002F re-check every 2 minutes\n",[857,1770,1771],{"class":859,"line":934},[857,1772,1773],{"class":871},"}\n",[952,1775],{},[955,1777,1779],{"id":1778},"batchqueue",[838,1780,1781],{},"batchQueue",[835,1783,1784],{},"The batch queue collects visitor writes and flushes them to the database asynchronously. This decouples visitor persistence from the request path, so database latency never affects response time.",[1700,1786,1787,1796,1804],{},[970,1788,1790],{"name":1789,"type":1503},"flushIntervalMs",[835,1791,1506,1792,1795],{},[838,1793,1794],{},"5000",". How often the queue flushes pending writes, in milliseconds. Increase this to reduce database load on busy servers.",[970,1797,1799],{"name":1798,"type":1503},"maxBufferSize",[835,1800,1506,1801,1803],{},[838,1802,1509],{},". Triggers an immediate flush when this many jobs are queued. Increase this if your batch sizes consistently hit the limit before the interval fires.",[970,1805,1807],{"name":1806,"type":1503},"maxRetries",[835,1808,1506,1809,1812],{},[838,1810,1811],{},"3",". Retry attempts on a failed flush before the batch is discarded.",[952,1814],{},[955,1816,1818],{"id":1817},"punishmenttype",[838,1819,1820],{},"punishmentType",[1700,1822,1823],{},[970,1824,1826],{"name":1825,"type":1599},"enableFireWallBan",[835,1827,1506,1828,1709,1830,1832,1833,1836,1837,1839,1840,1843],{},[838,1829,1604],{},[838,1831,974],{},", issues a ",[838,1834,1835],{},"ufw"," OS-level firewall rule in addition to the ",[838,1838,1513],{}," response. Banned IPs are blocked at the network layer via ",[838,1841,1842],{},"sudo ufw insert 1 deny from \u003Cip>",", preventing traffic from reaching the Node.js process on subsequent connections.",[1474,1845,1846],{},[835,1847,1848,1850,1851,1853,1854,1857],{},[838,1849,1825],{}," requires a Linux environment with ",[838,1852,1835],{}," installed and passwordless ",[838,1855,1856],{},"sudo"," access for the Node.js process. It has no effect and should not be enabled on macOS or Windows.",[952,1859],{},[955,1861,1863],{"id":1862},"loglevel",[838,1864,1865],{},"logLevel",[970,1867,1869],{"name":1865,"type":1868},"'debug' | 'info' | 'warn' | 'error' | 'fatal'",[835,1870,1506,1871,1874,1875,1878,1879,1489,1882,1885],{},[838,1872,1873],{},"'info'",". Sets the Pino log level for the middleware. Use ",[838,1876,1877],{},"'debug'"," during development to see per-request checker decisions. Set ",[838,1880,1881],{},"'warn'",[838,1883,1884],{},"'error'"," in production to reduce log volume.",[952,1887],{},[955,1889,1891],{"id":1890},"checkers",[838,1892,1890],{},[835,1894,1895,1896,1899,1900,1903],{},"Every checker is enabled by default. To disable a checker entirely, pass ",[838,1897,1898],{},"{ enable: false }",". To adjust its penalty values, pass ",[838,1901,1902],{},"{ enable: true, penalties: { ... } }"," with the fields you want to override, all unspecified fields keep their defaults.",[847,1905,1907],{"className":849,"code":1906,"language":852,"meta":853,"style":853},"checkers: {\n  enableTorAnalysis: { enable: false }, \u002F\u002F disable completely\n  enableBehaviorRateCheck: {\n    enable: true,\n    behavioral_threshold: 20, \u002F\u002F stricter rate limit\n    penalties: 80,            \u002F\u002F heavier penalty\n  },\n}\n",[838,1908,1909,1914,1927,1932,1941,1954,1968,1972],{"__ignoreMap":853},[857,1910,1911],{"class":859,"line":860},[857,1912,1913],{"class":871},"checkers: {\n",[857,1915,1916,1919,1921,1924],{"class":859,"line":875},[857,1917,1918],{"class":871},"  enableTorAnalysis: { enable: ",[857,1920,1604],{"class":1744},[857,1922,1923],{"class":871}," }, ",[857,1925,1926],{"class":943},"\u002F\u002F disable completely\n",[857,1928,1929],{"class":859,"line":889},[857,1930,1931],{"class":871},"  enableBehaviorRateCheck: {\n",[857,1933,1934,1937,1939],{"class":859,"line":934},[857,1935,1936],{"class":871},"    enable: ",[857,1938,974],{"class":1744},[857,1940,1747],{"class":871},[857,1942,1943,1946,1949,1951],{"class":859,"line":940},[857,1944,1945],{"class":871},"    behavioral_threshold: ",[857,1947,1948],{"class":1423},"20",[857,1950,916],{"class":871},[857,1952,1953],{"class":943},"\u002F\u002F stricter rate limit\n",[857,1955,1956,1959,1962,1965],{"class":859,"line":947},[857,1957,1958],{"class":871},"    penalties: ",[857,1960,1961],{"class":1423},"80",[857,1963,1964],{"class":871},",            ",[857,1966,1967],{"class":943},"\u002F\u002F heavier penalty\n",[857,1969,1970],{"class":859,"line":1180},[857,1971,937],{"class":871},[857,1973,1974],{"class":859,"line":1186},[857,1975,1773],{"class":871},[1977,1978,1980],"h3",{"id":1979},"enableipchecks",[838,1981,1982],{},"enableIpChecks",[835,1984,1985,1988],{},[1610,1986,1987],{},"Phase:"," cheap",[835,1990,1991,1992,1995],{},"Validates that the client IP is a properly formatted IPv4 or IPv6 address. Requests with a malformed or missing IP receive a penalty. Automated scripts that manipulate the ",[838,1993,1994],{},"X-Forwarded-For"," header to produce an invalid IP value are caught here.",[1700,1997,1998],{},[970,1999,2001],{"name":2000,"type":1503},"penalties",[835,2002,1506,2003,2005],{},[838,2004,1573],{},". Applied when the IP is invalid or cannot be parsed.",[952,2007],{},[1977,2009,2011],{"id":2010},"enablegoodbotschecks",[838,2012,2013],{},"enableGoodBotsChecks",[835,2015,2016,1988],{},[1610,2017,1987],{},[835,2019,2020,2021,2024],{},"Identifies legitimate crawlers such as Googlebot, Bingbot, DuckDuckBot, Apple, and Meta by matching the client IP against the compiled ",[838,2022,2023],{},"goodBots.mmdb",". When a match is found, the request is immediately exempted from scoring.",[835,2026,2027,2030,2031,2033,2034,2036],{},[838,2028,2029],{},"banUnlistedBots"," controls what happens when a request presents a bot-like User-Agent that is not in the verified crawler list. When ",[838,2032,974],{}," (default), unlisted bots receive the full ",[838,2035,2000],{}," score.",[1700,2038,2039,2048],{},[970,2040,2041],{"name":2029,"type":1599},[835,2042,1506,2043,1709,2045,2047],{},[838,2044,974],{},[838,2046,974],{},", bots not present in the verified crawler database receive the full penalty score.",[970,2049,2050],{"name":2000,"type":1503},[835,2051,1506,2052,2054,2055,1723,2057,983],{},[838,2053,1509],{},". Score applied to unlisted bots when ",[838,2056,2029],{},[838,2058,974],{},[952,2060],{},[1977,2062,2064],{"id":2063},"enablebrowseranddevicechecks",[838,2065,2066],{},"enableBrowserAndDeviceChecks",[835,2068,2069,1988],{},[1610,2070,1987],{},[835,2072,2073],{},"Inspects the parsed User-Agent for browsers and device combinations that are impossible or highly suspicious in a real-user context. Each condition carries its own penalty weight.",[835,2075,2076,2077,2080],{},"All weights below live inside the ",[838,2078,2079],{},"penalties: {}"," sub-object.",[1700,2082,2083,2091,2099,2107,2115,2123,2131,2139,2147,2155],{},[970,2084,2086],{"name":2085,"type":1503},"cliOrLibrary",[835,2087,1506,2088,2090],{},[838,2089,1509],{},". User-Agent belongs to a CLI tool or HTTP library (curl, python-requests, etc.).",[970,2092,2094],{"name":2093,"type":1503},"internetExplorer",[835,2095,1506,2096,2098],{},[838,2097,1509],{},". User-Agent identifies as Internet Explorer.",[970,2100,2102],{"name":2101,"type":1503},"linuxOs",[835,2103,1506,2104,2106],{},[838,2105,1573],{},". Desktop visit from Linux (elevated risk signal, not a ban signal alone).",[970,2108,2110],{"name":2109,"type":1503},"impossibleBrowserCombinations",[835,2111,1506,2112,2114],{},[838,2113,1520],{},". Browser and OS combination that cannot exist in practice.",[970,2116,2118],{"name":2117,"type":1503},"browserTypeUnknown",[835,2119,1506,2120,2122],{},[838,2121,1573],{},". Browser type field could not be determined.",[970,2124,2126],{"name":2125,"type":1503},"browserNameUnknown",[835,2127,1506,2128,2130],{},[838,2129,1573],{},". Browser name field could not be determined.",[970,2132,2134],{"name":2133,"type":1503},"desktopWithoutOS",[835,2135,1506,2136,2138],{},[838,2137,1573],{},". Desktop device type with no operating system in the UA.",[970,2140,2142],{"name":2141,"type":1503},"deviceVendorUnknown",[835,2143,1506,2144,2146],{},[838,2145,1573],{},". Device vendor could not be determined.",[970,2148,2150],{"name":2149,"type":1503},"browserVersionUnknown",[835,2151,1506,2152,2154],{},[838,2153,1573],{},". Browser version could not be determined.",[970,2156,2158],{"name":2157,"type":1503},"deviceModelUnknown",[835,2159,1506,2160,2163],{},[838,2161,2162],{},"5",". Device model could not be determined.",[952,2165],{},[1977,2167,2169],{"id":2168},"localemapscheck",[838,2170,2171],{},"localeMapsCheck",[835,2173,2174,1988],{},[1610,2175,1987],{},[835,2177,2178,2179,2182,2183,983],{},"Compares the ",[838,2180,2181],{},"Accept-Language"," header with the geolocation of the client IP. A legitimate browser sends a language that matches the country the IP is registered in. Automated tools often send a hardcoded or missing ",[838,2184,2181],{},[835,2186,2076,2187,2080],{},[838,2188,2079],{},[1700,2190,2191,2202,2212,2220],{},[970,2192,2194],{"name":2193,"type":1503},"ipAndHeaderMismatch",[835,2195,1506,2196,2198,2199,2201],{},[838,2197,1948],{},". ",[838,2200,2181],{}," locale does not match the IP's geo locale.",[970,2203,2205],{"name":2204,"type":1503},"missingHeader",[835,2206,1506,2207,2198,2209,2211],{},[838,2208,1948],{},[838,2210,2181],{}," header is absent.",[970,2213,2215],{"name":2214,"type":1503},"missingGeoData",[835,2216,1506,2217,2219],{},[838,2218,1948],{},". Geo data is unavailable for the IP.",[970,2221,2223],{"name":2222,"type":1503},"malformedHeader",[835,2224,1506,2225,2198,2227,2229],{},[838,2226,1520],{},[838,2228,2181],{}," header is present but cannot be parsed.",[952,2231],{},[1977,2233,2235],{"id":2234},"enableknownthreatsdetections",[838,2236,2237],{},"enableKnownThreatsDetections",[835,2239,2240,1988],{},[1610,2241,1987],{},[835,2243,2244,2245,2252],{},"Checks the client IP against the ",[2246,2247,2251],"a",{"href":2248,"rel":2249},"https:\u002F\u002Fiplists.firehol.org\u002F",[2250],"nofollow","FireHOL"," threat intelligence feeds. FireHOL maintains four ranked lists of known malicious IPs, plus an anonymizer feed for VPNs and anonymizing proxies.",[835,2254,2076,2255,2257,2258,2261,2262,983],{},[838,2256,2079],{}," sub-object. The four ",[838,2259,2260],{},"threatLevels"," fields are nested one level deeper inside ",[838,2263,2264],{},"penalties.threatLevels: {}",[1700,2266,2267,2275,2283,2291,2299],{},[970,2268,2270],{"name":2269,"type":1503},"anonymiseNetwork",[835,2271,1506,2272,2274],{},[838,2273,1948],{},". IP is in the FireHOL anonymous (VPN\u002Fanonymizer) feed.",[970,2276,2278],{"name":2277,"type":1503},"threatLevels.criticalLevel1",[835,2279,1506,2280,2282],{},[838,2281,1584],{},". IP is in FireHOL level 1 (active attack sources).",[970,2284,2286],{"name":2285,"type":1503},"threatLevels.currentAttacksLevel2",[835,2287,1506,2288,2290],{},[838,2289,1520],{},". IP is in FireHOL level 2 (current attack participants).",[970,2292,2294],{"name":2293,"type":1503},"threatLevels.threatLevel3",[835,2295,1506,2296,2298],{},[838,2297,1948],{},". IP is in FireHOL level 3 (broader threat list).",[970,2300,2302],{"name":2301,"type":1503},"threatLevels.threatLevel4",[835,2303,1506,2304,2306],{},[838,2305,1573],{},". IP is in FireHOL level 4 (extended watch list).",[952,2308],{},[1977,2310,2312],{"id":2311},"enableasnclassification",[838,2313,2314],{},"enableAsnClassification",[835,2316,2317,1988],{},[1610,2318,1987],{},[835,2320,2321],{},"Checks the Autonomous System Number associated with the client IP. Hosting providers, cloud platforms, and data centers make up the majority of bot traffic. IPs from AS networks classified as hosting or content delivery receive a penalty. Networks with very few visible routes (low visibility) are also penalized, as they are characteristic of residential proxy services.",[835,2323,2076,2324,2080],{},[838,2325,2079],{},[1700,2327,2328,2336,2344,2355,2366],{},[970,2329,2331],{"name":2330,"type":1503},"contentClassification",[835,2332,1506,2333,2335],{},[838,2334,1948],{},". ASN is classified as a hosting or CDN network.",[970,2337,2339],{"name":2338,"type":1503},"unknownClassification",[835,2340,1506,2341,2343],{},[838,2342,1573],{},". ASN classification cannot be determined.",[970,2345,2347],{"name":2346,"type":1503},"lowVisibilityPenalty",[835,2348,1506,2349,2351,2352,983],{},[838,2350,1573],{},". ASN has fewer routes visible than ",[838,2353,2354],{},"lowVisibilityThreshold",[970,2356,2357],{"name":2354,"type":1503},[835,2358,1506,2359,2362,2363,2365],{},[838,2360,2361],{},"15",". Minimum route count before ",[838,2364,2346],{}," applies.",[970,2367,2369],{"name":2368,"type":1503},"comboHostingLowVisibility",[835,2370,1506,2371,2373],{},[838,2372,1948],{},". ASN is both hosting-classified and low-visibility.",[952,2375],{},[1977,2377,2379],{"id":2378},"enabletoranalysis",[838,2380,2381],{},"enableTorAnalysis",[835,2383,2384,1988],{},[1610,2385,1987],{},[835,2387,2388],{},"Checks the client IP against the compiled Tor relay database. Tor exit nodes are the most likely to be used for malicious automation, while guard nodes and running relays carry lower risk. Obsolete Tor versions suggest a misconfigured or malicious relay.",[835,2390,2076,2391,2080],{},[838,2392,2079],{},[1700,2394,2395,2403,2411,2419,2427,2435],{},[970,2396,2398],{"name":2397,"type":1503},"runningNode",[835,2399,1506,2400,2402],{},[838,2401,2361],{},". IP belongs to an active Tor relay.",[970,2404,2406],{"name":2405,"type":1503},"exitNode",[835,2407,1506,2408,2410],{},[838,2409,1948],{},". IP is a Tor exit node.",[970,2412,2414],{"name":2413,"type":1503},"webExitCapable",[835,2415,1506,2416,2418],{},[838,2417,2361],{},". IP is capable of exiting to web ports.",[970,2420,2422],{"name":2421,"type":1503},"guardNode",[835,2423,1506,2424,2426],{},[838,2425,1573],{},". IP is a Tor guard (entry) node.",[970,2428,2430],{"name":2429,"type":1503},"badExit",[835,2431,1506,2432,2434],{},[838,2433,1584],{},". IP is flagged as a bad Tor exit.",[970,2436,2438],{"name":2437,"type":1503},"obsoleteVersion",[835,2439,1506,2440,2442],{},[838,2441,1573],{},". IP is running an outdated Tor version.",[952,2444],{},[1977,2446,2448],{"id":2447},"enabletimezoneconsistency",[838,2449,2450],{},"enableTimezoneConsistency",[835,2452,2453,1988],{},[1610,2454,1987],{},[835,2456,2457],{},"Compares the timezone sent in request headers against the timezone expected for the client's geo IP. A mismatch suggests the visitor is using a VPN or proxy that routes through a different region than their actual location.",[1700,2459,2460],{},[970,2461,2462],{"name":2000,"type":1503},[835,2463,1506,2464,2466],{},[838,2465,1948],{},". Applied when the declared timezone does not match the geo timezone.",[952,2468],{},[1977,2470,2472],{"id":2471},"honeypot",[838,2473,2471],{},[835,2475,2476,1988],{},[1610,2477,1987],{},[835,2479,2480,2481,916,2484,2487,2488,2491,2492,2494],{},"Monitors requests to a configurable list of trap URLs. These paths serve no legitimate purpose and should never be visited by a real user. Automated scanners and vulnerability probes routinely request paths like ",[838,2482,2483],{},"\u002F.env",[838,2485,2486],{},"\u002Fwp-login.php",", and ",[838,2489,2490],{},"\u002Fadmin",". Any request to a listed path immediately sets the score to ",[838,2493,1500],{},", triggering a ban.",[1700,2496,2497],{},[970,2498,2501],{"name":2499,"type":2500},"paths","string[]",[835,2502,1506,2503,2505],{},[838,2504,1648],{},". List of URL paths to treat as honeypots. Any request matching one of these paths is banned immediately.",[847,2507,2509],{"className":849,"code":2508,"language":852,"meta":853,"style":853},"honeypot: {\n  enable: true,\n  paths: ['\u002F.env', '\u002Fwp-login.php', '\u002Fadmin', '\u002FphpMyAdmin'],\n}\n",[838,2510,2511,2516,2525,2564],{"__ignoreMap":853},[857,2512,2513],{"class":859,"line":860},[857,2514,2515],{"class":871},"honeypot: {\n",[857,2517,2518,2521,2523],{"class":859,"line":875},[857,2519,2520],{"class":871},"  enable: ",[857,2522,974],{"class":1744},[857,2524,1747],{"class":871},[857,2526,2527,2530,2532,2534,2536,2538,2540,2542,2544,2546,2548,2550,2552,2554,2556,2559,2561],{"class":859,"line":889},[857,2528,2529],{"class":871},"  paths: [",[857,2531,913],{"class":905},[857,2533,2483],{"class":909},[857,2535,913],{"class":905},[857,2537,916],{"class":871},[857,2539,913],{"class":905},[857,2541,2486],{"class":909},[857,2543,913],{"class":905},[857,2545,916],{"class":871},[857,2547,913],{"class":905},[857,2549,2490],{"class":909},[857,2551,913],{"class":905},[857,2553,916],{"class":871},[857,2555,913],{"class":905},[857,2557,2558],{"class":909},"\u002FphpMyAdmin",[857,2560,913],{"class":905},[857,2562,2563],{"class":871},"],\n",[857,2565,2566],{"class":859,"line":934},[857,2567,1773],{"class":871},[952,2569],{},[1977,2571,2573],{"id":2572},"enableknownbadipscheck",[838,2574,2575],{},"enableKnownBadIpsCheck",[835,2577,2578,1988],{},[1610,2579,1987],{},[835,2581,2582,2583,2586,2587,2590],{},"Checks the client IP against your custom ",[838,2584,2585],{},"highRisk.mmdb",", which is generated by ",[838,2588,2589],{},"bot-detector generate"," from your own visitor history. IPs that have previously accumulated a high suspicion score in your database are caught here on all future requests without re-running the full pipeline.",[1700,2592,2593],{},[970,2594,2596],{"name":2595,"type":1503},"highRiskPenalty",[835,2597,1506,2598,2600,2601,983],{},[838,2599,1520],{},". Score applied when the IP is found in ",[838,2602,2585],{},[2604,2605,2606],"tip",{},[835,2607,2608,2609,2611],{},"Run ",[838,2610,2589],{}," periodically to keep this database current with your latest visitor data.",[952,2613],{},[1977,2615,2617],{"id":2616},"enablebehaviorratecheck",[838,2618,2619],{},"enableBehaviorRateCheck",[835,2621,2622,2624],{},[1610,2623,1987],{}," heavy",[835,2626,2627,2628,2631,2632,2635],{},"Tracks request frequency per canary cookie. When a visitor sends more requests than ",[838,2629,2630],{},"behavioral_threshold"," within the ",[838,2633,2634],{},"behavioral_window"," time period, the excess is penalized. This catches fast-scanning bots and automated scripts that make hundreds of requests per minute.",[1700,2637,2638,2646,2653],{},[970,2639,2640],{"name":2634,"type":1503},[835,2641,1506,2642,2645],{},[838,2643,2644],{},"60000",". Sliding time window in milliseconds (1 minute by default).",[970,2647,2648],{"name":2630,"type":1503},[835,2649,1506,2650,2652],{},[838,2651,1520],{},". Maximum requests allowed within the window before the penalty applies.",[970,2654,2655],{"name":2000,"type":1503},[835,2656,1506,2657,2660],{},[838,2658,2659],{},"60",". Score applied when the threshold is exceeded.",[847,2662,2664],{"className":849,"code":2663,"language":852,"meta":853,"style":853},"enableBehaviorRateCheck: {\n  enable: true,\n  behavioral_window: 60_000,   \u002F\u002F 1-minute window\n  behavioral_threshold: 15,    \u002F\u002F stricter: max 15 req\u002Fmin\n  penalties: 80,\n}\n",[838,2665,2666,2671,2679,2693,2706,2715],{"__ignoreMap":853},[857,2667,2668],{"class":859,"line":860},[857,2669,2670],{"class":871},"enableBehaviorRateCheck: {\n",[857,2672,2673,2675,2677],{"class":859,"line":875},[857,2674,2520],{"class":871},[857,2676,974],{"class":1744},[857,2678,1747],{"class":871},[857,2680,2681,2684,2687,2690],{"class":859,"line":889},[857,2682,2683],{"class":871},"  behavioral_window: ",[857,2685,2686],{"class":1423},"60_000",[857,2688,2689],{"class":871},",   ",[857,2691,2692],{"class":943},"\u002F\u002F 1-minute window\n",[857,2694,2695,2698,2700,2703],{"class":859,"line":934},[857,2696,2697],{"class":871},"  behavioral_threshold: ",[857,2699,2361],{"class":1423},[857,2701,2702],{"class":871},",    ",[857,2704,2705],{"class":943},"\u002F\u002F stricter: max 15 req\u002Fmin\n",[857,2707,2708,2711,2713],{"class":859,"line":940},[857,2709,2710],{"class":871},"  penalties: ",[857,2712,1961],{"class":1423},[857,2714,1747],{"class":871},[857,2716,2717],{"class":859,"line":947},[857,2718,1773],{"class":871},[952,2720],{},[1977,2722,2724],{"id":2723},"enableproxyispcookieschecks",[838,2725,2726],{},"enableProxyIspCookiesChecks",[835,2728,2729,2624],{},[1610,2730,1987],{},[835,2732,2733,2734,2737],{},"Performs three related checks: proxy detection against the compiled ",[838,2735,2736],{},"proxy.mmdb",", ISP classification for unknown or suspicious providers, and canary cookie presence. A missing canary cookie on a non-first request strongly suggests a bot that discards cookies between requests.",[835,2739,2076,2740,2080],{},[838,2741,2079],{},[1700,2743,2744,2755,2763,2772,2780,2788,2796],{},[970,2745,2747],{"name":2746,"type":1503},"cookieMissing",[835,2748,1506,2749,2198,2751,2754],{},[838,2750,1961],{},[838,2752,2753],{},"canary_id"," cookie is absent on a non-first request.",[970,2756,2758],{"name":2757,"type":1503},"proxyDetected",[835,2759,1506,2760,2762],{},[838,2761,1584],{},". IP is in the proxy database.",[970,2764,2766],{"name":2765,"type":1503},"hostingDetected",[835,2767,1506,2768,2771],{},[838,2769,2770],{},"50",". IP belongs to a known hosting or data-center provider.",[970,2773,2775],{"name":2774,"type":1503},"ispUnknown",[835,2776,1506,2777,2779],{},[838,2778,1573],{},". ISP cannot be determined from the IP.",[970,2781,2783],{"name":2782,"type":1503},"orgUnknown",[835,2784,1506,2785,2787],{},[838,2786,1573],{},". Organisation cannot be determined from the IP.",[970,2789,2791],{"name":2790,"type":1503},"multiSourceBonus2to3",[835,2792,1506,2793,2795],{},[838,2794,1573],{},". IP flagged by 2 to 3 proxy sources (cumulative risk bonus).",[970,2797,2799],{"name":2798,"type":1503},"multiSourceBonus4plus",[835,2800,1506,2801,2803],{},[838,2802,1948],{},". IP flagged by 4 or more proxy sources.",[952,2805],{},[1977,2807,2809],{"id":2808},"enableuaandheaderchecks",[838,2810,2811],{},"enableUaAndHeaderChecks",[835,2813,2814,2624],{},[1610,2815,1987],{},[835,2817,2818],{},"Runs a multi-factor inspection of the User-Agent and HTTP headers. It detects headless browsers by looking for tell-tale header patterns, penalizes suspiciously short User-Agents, and checks basic TLS cipher, protocol version, and HTTP version consistency.",[835,2820,2076,2821,2080],{},[838,2822,2079],{},[1700,2824,2825,2833,2841,2857],{},[970,2826,2828],{"name":2827,"type":1503},"headlessBrowser",[835,2829,1506,2830,2832],{},[838,2831,1509],{},". Headers match known headless browser patterns (Puppeteer, Playwright, etc.).",[970,2834,2836],{"name":2835,"type":1503},"shortUserAgent",[835,2837,1506,2838,2840],{},[838,2839,1961],{},". User-Agent string is shorter than expected for a real browser.",[970,2842,2844],{"name":2843,"type":1503},"tlsCheckFailed",[835,2845,1506,2846,2848,2849,2852,2853,2856],{},[838,2847,2659],{},". The TLS cipher suite, TLS version, or HTTP protocol version forwarded by the proxy does not match what a real browser would use. Requires the proxy to set ",[838,2850,2851],{},"x-client-cipher"," and ",[838,2854,2855],{},"x-client-tls-version"," headers.",[970,2858,2860],{"name":2859,"type":1599},"badUaChecker",[835,2861,1506,2862,1709,2864,2866,2867,2870],{},[838,2863,974],{},[838,2865,974],{},", the LMDB User-Agent pattern library is consulted and penalties from ",[838,2868,2869],{},"knownBadUserAgents"," apply.",[952,2872],{},[1977,2874,2876],{"id":2875},"enablegeochecks",[838,2877,2878],{},"enableGeoChecks",[835,2880,2881,2624],{},[1610,2882,1987],{},[835,2884,2885],{},"Checks for missing or incomplete geolocation data and enforces country-level bans. Legitimate residential IPs consistently resolve to a full set of geo fields. Requests where city, region, country, timezone, or coordinates are unknown may originate from misconfigured VPNs, private IP ranges leaked through proxies, or IP addresses not present in the geo database.",[835,2887,2888,2891,2892,2894],{},[838,2889,2890],{},"bannedCountries"," accepts a list of ISO 3166-1 alpha-2 country codes. Any request from a banned country receives the full ",[838,2893,1500],{},", triggering an immediate ban.",[835,2896,2897,2899,2900,2080],{},[838,2898,2890],{}," is a top-level field on the checker. All geo unknown penalty weights live inside the ",[838,2901,2079],{},[1700,2903,2904,2914,2922,2930,2938,2946,2954,2962,2970,2978],{},[970,2905,2906],{"name":2890,"type":2500},[835,2907,1506,2908,2910,2911,983],{},[838,2909,1648],{},". ISO 3166-1 alpha-2 country codes to ban outright. Example: ",[838,2912,2913],{},"['KP', 'IR']",[970,2915,2917],{"name":2916,"type":1503},"countryUnknown",[835,2918,1506,2919,2921],{},[838,2920,1573],{},". Country cannot be determined.",[970,2923,2925],{"name":2924,"type":1503},"regionUnknown",[835,2926,1506,2927,2929],{},[838,2928,1573],{},". Region cannot be determined.",[970,2931,2933],{"name":2932,"type":1503},"latLonUnknown",[835,2934,1506,2935,2937],{},[838,2936,1573],{},". Coordinates cannot be determined.",[970,2939,2941],{"name":2940,"type":1503},"districtUnknown",[835,2942,1506,2943,2945],{},[838,2944,1573],{},". District cannot be determined.",[970,2947,2949],{"name":2948,"type":1503},"cityUnknown",[835,2950,1506,2951,2953],{},[838,2952,1573],{},". City cannot be determined.",[970,2955,2957],{"name":2956,"type":1503},"timezoneUnknown",[835,2958,1506,2959,2961],{},[838,2960,1573],{},". Timezone cannot be determined.",[970,2963,2965],{"name":2964,"type":1503},"subregionUnknown",[835,2966,1506,2967,2969],{},[838,2968,1573],{},". Sub-region cannot be determined.",[970,2971,2973],{"name":2972,"type":1503},"phoneUnknown",[835,2974,1506,2975,2977],{},[838,2976,1573],{},". Phone prefix cannot be determined.",[970,2979,2981],{"name":2980,"type":1503},"continentUnknown",[835,2982,1506,2983,2985],{},[838,2984,1573],{},". Continent cannot be determined.",[952,2987],{},[1977,2989,2991],{"id":2990},"enablesessioncoherence",[838,2992,2993],{},"enableSessionCoherence",[835,2995,2996,2624],{},[1610,2997,1987],{},[835,2999,3000,3001,3004,3005,3007],{},"Inspects the ",[838,3002,3003],{},"Referer"," header for consistency with the request path and domain. Legitimate browsers include a ",[838,3006,3003],{}," header on navigation requests and it consistently matches the current site's domain. Bots that crawl by constructing URLs directly often produce missing, mismatched, or cross-domain referers.",[835,3009,2076,3010,2080],{},[838,3011,2079],{},[1700,3013,3014,3022,3030],{},[970,3015,3017],{"name":3016,"type":1503},"pathMismatch",[835,3018,1506,3019,3021],{},[838,3020,1573],{},". Referer path does not match the expected navigation flow.",[970,3023,3025],{"name":3024,"type":1503},"missingReferer",[835,3026,1506,3027,3029],{},[838,3028,1948],{},". Referer is absent on a request that should have one.",[970,3031,3033],{"name":3032,"type":1503},"domainMismatch",[835,3034,1506,3035,3037],{},[838,3036,1520],{},". Referer domain does not match the current site domain.",[952,3039],{},[1977,3041,3043],{"id":3042},"enablevelocityfingerprint",[838,3044,3045],{},"enableVelocityFingerprint",[835,3047,3048,2624],{},[1610,3049,1987],{},[835,3051,3052,3053,3056],{},"Measures the statistical regularity of a visitor's inter-request timing using the coefficient of variation (CV). Human users have naturally irregular timing between requests. Automated scripts often produce highly regular intervals. When the CV of a visitor's request timing falls below ",[838,3054,3055],{},"cvThreshold",", the request is penalized.",[1700,3058,3059,3067],{},[970,3060,3061],{"name":3055,"type":1503},[835,3062,1506,3063,3066],{},[838,3064,3065],{},"0.1",". Minimum coefficient of variation before the penalty applies. Lower values require more regularity to trigger.",[970,3068,3069],{"name":2000,"type":1503},[835,3070,1506,3071,3073],{},[838,3072,1584],{},". Score applied when timing is unnaturally regular.",[952,3075],{},[1977,3077,3079],{"id":3078},"knownbaduseragents",[838,3080,2869],{},[835,3082,3083,2624],{},[1610,3084,1987],{},[835,3086,3087],{},"Cross-references the User-Agent string against an LMDB database of known malicious, scraper, and vulnerability-scanner patterns. Each pattern carries a severity level that maps to a separate penalty. This checker is the most comprehensive User-Agent check and is backed by a continuously updated pattern library.",[835,3089,2076,3090,2080],{},[838,3091,2079],{},[1700,3093,3094,3102,3110,3118],{},[970,3095,3097],{"name":3096,"type":1503},"criticalSeverity",[835,3098,1506,3099,3101],{},[838,3100,1509],{},". Pattern matches a known critical-severity bad User-Agent.",[970,3103,3105],{"name":3104,"type":1503},"highSeverity",[835,3106,1506,3107,3109],{},[838,3108,1961],{},". Pattern matches a high-severity bad User-Agent.",[970,3111,3113],{"name":3112,"type":1503},"mediumSeverity",[835,3114,1506,3115,3117],{},[838,3116,1520],{},". Pattern matches a medium-severity bad User-Agent.",[970,3119,3121],{"name":3120,"type":1503},"lowSeverity",[835,3122,1506,3123,3125],{},[838,3124,1573],{},". Pattern matches a low-severity bad User-Agent.",[3127,3128,3129],"note",{},[835,3130,3131,3132,1723,3135,3137,3138,3141],{},"This checker only runs when ",[838,3133,3134],{},"enableUaAndHeaderChecks.penalties.badUaChecker",[838,3136,974],{}," (the default). Disabling that option bypasses this checker regardless of its own ",[838,3139,3140],{},"enable"," setting.",[952,3143],{},[955,3145,3147],{"id":3146},"headeroptions",[838,3148,3149],{},"headerOptions",[835,3151,3152,3153,3155],{},"Fine-grained penalty weights for the HTTP header fingerprint analysis performed by ",[838,3154,2811],{},". Each weight corresponds to a specific header anomaly. The total accumulated weight across all detected anomalies is added to the request score.",[1700,3157,3158,3166,3174,3182,3193,3204,3218,3228,3239,3247,3258,3266,3276,3290,3301,3312],{},[970,3159,3161],{"name":3160,"type":1503},"weightPerMustHeader",[835,3162,1506,3163,3165],{},[838,3164,1948],{},". Each mandatory header that is absent for the declared browser type.",[970,3167,3169],{"name":3168,"type":1503},"missingBrowserEngine",[835,3170,1506,3171,3173],{},[838,3172,1520],{},". No browser engine header present.",[970,3175,3177],{"name":3176,"type":1503},"postManOrInsomiaHeaders",[835,3178,1506,3179,3181],{},[838,3180,2770],{},". Headers characteristic of Postman or Insomnia REST clients.",[970,3183,3185],{"name":3184,"type":1503},"AJAXHeaderExists",[835,3186,1506,3187,2198,3189,3192],{},[838,3188,1520],{},[838,3190,3191],{},"X-Requested-With: XMLHttpRequest"," present in a non-AJAX context.",[970,3194,3196],{"name":3195,"type":1503},"connectionHeaderIsClose",[835,3197,1506,3198,2198,3200,3203],{},[838,3199,1948],{},[838,3201,3202],{},"Connection: close"," header, which browsers do not send by default.",[970,3205,3207],{"name":3206,"type":1503},"originHeaderIsNULL",[835,3208,1506,3209,2198,3211,3214,3215,983],{},[838,3210,1573],{},[838,3212,3213],{},"Origin"," header is present but set to ",[838,3216,3217],{},"null",[970,3219,3221],{"name":3220,"type":1503},"originHeaderMismatch",[835,3222,1506,3223,2198,3225,3227],{},[838,3224,1520],{},[838,3226,3213],{}," header domain does not match the request host.",[970,3229,3231],{"name":3230,"type":1503},"omittedAcceptHeader",[835,3232,1506,3233,2198,3235,3238],{},[838,3234,1520],{},[838,3236,3237],{},"Accept"," header is completely absent.",[970,3240,3242],{"name":3241,"type":1503},"clientHintsMissingForBlink",[835,3243,1506,3244,3246],{},[838,3245,1520],{},". Client hint headers are absent for a Chromium (Blink) User-Agent.",[970,3248,3250],{"name":3249,"type":1503},"teHeaderUnexpectedForBlink",[835,3251,1506,3252,2198,3254,3257],{},[838,3253,1573],{},[838,3255,3256],{},"TE"," header present in a Chromium request (Chromium does not send it).",[970,3259,3261],{"name":3260,"type":1503},"clientHintsUnexpectedForGecko",[835,3262,1506,3263,3265],{},[838,3264,1520],{},". Client hint headers are present for a Firefox (Gecko) User-Agent.",[970,3267,3269],{"name":3268,"type":1503},"teHeaderMissingForGecko",[835,3270,1506,3271,2198,3273,3275],{},[838,3272,1948],{},[838,3274,3256],{}," header absent for a Firefox User-Agent (Firefox sends it).",[970,3277,3279],{"name":3278,"type":1503},"aggressiveCacheControlOnGet",[835,3280,1506,3281,2198,3283,1489,3286,3289],{},[838,3282,2361],{},[838,3284,3285],{},"Cache-Control: no-cache",[838,3287,3288],{},"no-store"," on a GET request.",[970,3291,3293],{"name":3292,"type":1503},"crossSiteRequestMissingReferer",[835,3294,1506,3295,3297,3298,3300],{},[838,3296,1573],{},". Cross-site navigation without a ",[838,3299,3003],{}," header.",[970,3302,3304],{"name":3303,"type":1503},"inconsistentSecFetchMode",[835,3305,1506,3306,2198,3308,3311],{},[838,3307,1948],{},[838,3309,3310],{},"Sec-Fetch-Mode"," value inconsistent with the request type.",[970,3313,3315],{"name":3314,"type":1503},"hostMismatchWeight",[835,3316,1506,3317,2198,3319,3322],{},[838,3318,1584],{},[838,3320,3321],{},"Host"," header does not match the configured server host.",[952,3324],{},[955,3326,3328],{"id":3327},"pathtraveler",[838,3329,3330],{},"pathTraveler",[835,3332,3333,3334,3337],{},"Configuration for the path traversal detection logic, which catches requests attempting to access files outside the web root using encoded ",[838,3335,3336],{},"..\u002F"," sequences.",[1700,3339,3340,3348,3357,3367,3378],{},[970,3341,3343],{"name":3342,"type":1503},"maxIterations",[835,3344,1506,3345,3347],{},[838,3346,1811],{},". Maximum decoding passes to attempt when looking for traversal sequences.",[970,3349,3351],{"name":3350,"type":1503},"maxPathLength",[835,3352,1506,3353,3356],{},[838,3354,3355],{},"1500",". Maximum raw path length in characters before a penalty applies.",[970,3358,3360],{"name":3359,"type":1503},"pathLengthToLong",[835,3361,1506,3362,3364,3365,983],{},[838,3363,1509],{},". Penalty applied when the path exceeds ",[838,3366,3350],{},[970,3368,3370],{"name":3369,"type":1503},"longDecoding",[835,3371,1506,3372,3374,3375,3377],{},[838,3373,1509],{},". Penalty applied when the path requires more than ",[838,3376,3342],{}," decoding passes.",[970,3379,3381],{"name":3380,"type":1503},"traversalDetected",[835,3382,1506,3383,3385,3386,3388],{},[838,3384,2659],{},". Penalty applied when a ",[838,3387,3336],{}," traversal sequence is found after decoding.",[952,3390],{},[955,3392,3394],{"id":3393},"generator",[838,3395,3393],{},[835,3397,3398,3399,3401,3402,3405],{},"Controls how ",[838,3400,2589],{}," (and the programmatic ",[838,3403,3404],{},"runGeneration()",") compiles your visitor history into custom MMDB databases.",[1700,3407,3408,3424,3434,3444],{},[970,3409,3411],{"name":3410,"type":1503},"scoreThreshold",[835,3412,1506,3413,3416,3417,3420,3421,3423],{},[838,3414,3415],{},"70",". Minimum ",[838,3418,3419],{},"suspicious_activity_score"," a visitor row must have to be included in ",[838,3422,2585],{},". Lowering it includes more visitors in the fast-rejection list; raising it makes the list more conservative.",[970,3425,3427],{"name":3426,"type":1599},"generateTypes",[835,3428,1506,3429,1709,3431,3433],{},[838,3430,1604],{},[838,3432,974],{},", generates TypeScript type definitions alongside the MMDB files.",[970,3435,3437],{"name":3436,"type":1599},"deleteAfterBuild",[835,3438,1506,3439,1709,3441,3443],{},[838,3440,1604],{},[838,3442,974],{},", deletes the source database rows after a successful compile. Useful for keeping your database lean. Banned rows and high-risk visitor records compiled into MMDB are no longer needed in SQL form.",[970,3445,3448],{"name":3446,"type":3447},"mmdbctlPath","string",[835,3449,1506,3450,3453,3454,3457,3458,3460,3461,983],{},[838,3451,3452],{},"'mmdbctl'",". Path to the ",[838,3455,3456],{},"mmdbctl"," binary. Override this when ",[838,3459,3456],{}," is not on the system ",[838,3462,3463],{},"PATH",[3465,3466,3467],"style",{},"html pre.shiki code .sZ328, html code.shiki .sZ328{--shiki-light:#AF00DB;--shiki-default:#AF00DB;--shiki-dark:#FF79C6}html pre.shiki code .sHOzp, html code.shiki .sHOzp{--shiki-light:#795E26;--shiki-default:#795E26;--shiki-dark:#50FA7B}html pre.shiki code .sDd4n, html code.shiki .sDd4n{--shiki-light:#000000;--shiki-default:#000000;--shiki-dark:#F8F8F2}html pre.shiki code .sjsA6, html code.shiki .sjsA6{--shiki-light:#001080;--shiki-default:#001080;--shiki-dark:#F8F8F2}html pre.shiki code .s34zl, html code.shiki .s34zl{--shiki-light:#001080;--shiki-default:#001080;--shiki-dark:#FF79C6}html pre.shiki code .sFkSl, html code.shiki .sFkSl{--shiki-light:#A31515;--shiki-default:#A31515;--shiki-dark:#E9F284}html pre.shiki code .sFB1V, html code.shiki .sFB1V{--shiki-light:#A31515;--shiki-default:#A31515;--shiki-dark:#F1FA8C}html pre.shiki code .sghk6, html code.shiki .sghk6{--shiki-light:#008000;--shiki-default:#008000;--shiki-dark:#6272A4}html .light .shiki span {color: var(--shiki-light);background: var(--shiki-light-bg);font-style: var(--shiki-light-font-style);font-weight: var(--shiki-light-font-weight);text-decoration: var(--shiki-light-text-decoration);}html.light .shiki span {color: var(--shiki-light);background: var(--shiki-light-bg);font-style: var(--shiki-light-font-style);font-weight: var(--shiki-light-font-weight);text-decoration: var(--shiki-light-text-decoration);}html .default .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}html .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}html .dark .shiki span {color: var(--shiki-dark);background: var(--shiki-dark-bg);font-style: var(--shiki-dark-font-style);font-weight: var(--shiki-dark-font-weight);text-decoration: var(--shiki-dark-text-decoration);}html.dark .shiki span {color: var(--shiki-dark);background: var(--shiki-dark-bg);font-style: var(--shiki-dark-font-style);font-weight: var(--shiki-dark-font-weight);text-decoration: var(--shiki-dark-text-decoration);}html pre.shiki code .spgvN, html code.shiki .spgvN{--shiki-light:#098658;--shiki-default:#098658;--shiki-dark:#BD93F9}html pre.shiki code .saOXh, html code.shiki .saOXh{--shiki-light:#000000;--shiki-default:#000000;--shiki-dark:#FF79C6}html pre.shiki code .sjR7W, html code.shiki .sjR7W{--shiki-light:#0000FF;--shiki-default:#0000FF;--shiki-dark:#BD93F9}",{"title":853,"searchDepth":875,"depth":875,"links":3469},[3470,3471,3472,3473,3474,3475,3476,3478,3479,3480,3481,3482,3483,3502,3503,3504],{"id":957,"depth":875,"text":957},{"id":1211,"depth":875,"text":1211},{"id":1497,"depth":875,"text":1500},{"id":1545,"depth":875,"text":1548},{"id":1563,"depth":875,"text":1566},{"id":1593,"depth":875,"text":1596},{"id":1608,"depth":875,"text":3477},"false: Snapshot then heal (default). The detector writes the computed score once on the visitor's first request (or after the cache expires). On every subsequent request, the reputation healer decrements the stored score by restoredReputationPoints. This mode is efficient because the expensive score computation only runs on cache misses.",{"id":1637,"depth":875,"text":1640},{"id":1692,"depth":875,"text":1695},{"id":1778,"depth":875,"text":1781},{"id":1817,"depth":875,"text":1820},{"id":1862,"depth":875,"text":1865},{"id":1890,"depth":875,"text":1890,"children":3484},[3485,3486,3487,3488,3489,3490,3491,3492,3493,3494,3495,3496,3497,3498,3499,3500,3501],{"id":1979,"depth":889,"text":1982},{"id":2010,"depth":889,"text":2013},{"id":2063,"depth":889,"text":2066},{"id":2168,"depth":889,"text":2171},{"id":2234,"depth":889,"text":2237},{"id":2311,"depth":889,"text":2314},{"id":2378,"depth":889,"text":2381},{"id":2447,"depth":889,"text":2450},{"id":2471,"depth":889,"text":2471},{"id":2572,"depth":889,"text":2575},{"id":2616,"depth":889,"text":2619},{"id":2723,"depth":889,"text":2726},{"id":2808,"depth":889,"text":2811},{"id":2875,"depth":889,"text":2878},{"id":2990,"depth":889,"text":2993},{"id":3042,"depth":889,"text":3045},{"id":3078,"depth":889,"text":2869},{"id":3146,"depth":875,"text":3149},{"id":3327,"depth":875,"text":3330},{"id":3393,"depth":875,"text":3393},"Full reference for every option accepted by defineConfiguration.","md","i-lucide-settings",{},null,"---\ntitle: Configuration\ndescription: Full reference for every option accepted by defineConfiguration.\nicon: i-lucide-settings\n---\n\n`defineConfiguration` accepts a single configuration object. Every field has a default value, only `store.main` is required. The configuration is validated against a Zod schema at startup. Invalid values cause the server to fail immediately with a clear error message.\n\n```ts [server.ts]\nawait defineConfiguration({\n  store: {\n    main: { driver: 'sqlite', name: '.\u002Fbot-detector.db' },\n  },\n  \u002F\u002F All other options are optional and have defaults\n})\n```\n\n---\n\n## `store`\n\nThe `store` object configures the persistent database where visitor records and ban history are stored. Only `store.main` is required.\n\n::field{name=\"main\" type=\"DbConfig\" required}\nThe database driver configuration. Pass the driver name and any connection options it requires. `DbConfig` is a discriminated union keyed on `driver`.\n::\n\n| Driver | `driver` value | Required peer dep |\n| --- | --- | --- |\n| SQLite | `sqlite` | `better-sqlite3` |\n| MySQL connection pool | `mysql-pool` | `mysql2 >= 3` |\n| PostgreSQL | `postgresql` | `pg` |\n| Cloudflare D1 | `cloudflare-d1` | Worker environment binding |\n| PlanetScale | `planetscale` | Serverless driver |\n\n```ts [server.ts]\n\u002F\u002F SQLite: good default for single-server deployments\nstore: { main: { driver: 'sqlite', name: '.\u002Fbot-detector.db' } }\n\n\u002F\u002F MySQL pool\nstore: { main: { driver: 'mysql-pool', host: 'localhost', user: 'root', password: 'secret', database: 'mydb' } }\n\n\u002F\u002F PostgreSQL\nstore: { main: { driver: 'postgresql', connectionString: 'postgres:\u002F\u002Fuser:pass@localhost\u002Fmydb' } }\n```\n\n---\n\n## `storage`\n\nThe `storage` field configures the cache layer where visitor state, behavioral rate counters, and session records are stored between requests. When omitted, everything is stored in process memory, which works for single-process deployments but is lost on restart and not shared across multiple instances.\n\n::field{name=\"storage\" type=\"CacheConfig\"}\nOptional cache driver configuration. `CacheConfig` is a discriminated union keyed on `driver`. Omit this field to use in-process memory.\n::\n \n| Driver | `driver` value | Notes |\n| --- | --- | --- |\n| Memory (default) | *(omit `storage`)* | Single-process only, lost on restart |\n| LRU cache | `lru` | In-process LRU; set `max` (item limit) and `ttl` (ms) |\n| Redis | `redis` | Recommended for multi-instance deployments |\n| Upstash Redis | `upstash` | Serverless Redis via HTTP |\n| Filesystem | `fs` | Persistent local storage, good for development |\n| Cloudflare KV (binding) | `cloudflare-kv-binding` | Pass `binding` from the Worker environment |\n| Cloudflare KV (HTTP) | `cloudflare-kv-http` | Pass `accountId`, `namespaceId`, `apiToken` |\n| Cloudflare R2 | `cloudflare-r2-binding` | Pass `binding` |\n| Vercel | `vercel` | Vercel Runtime Cache |\n\n```ts [server.ts]\n\u002F\u002F Redis: shared state across multiple app instances\nstorage: { driver: 'redis', host: 'localhost', port: 6379 }\n\n\u002F\u002F LRU: bounded in-process cache\nstorage: { driver: 'lru', max: 10000, ttl: 1000 * 60 * 10 }\n```\n\n::warning\nWhen running multiple Node.js processes behind a load balancer, omitting `storage` or using an in-process driver (`lru`, `fs`) means each process maintains its own independent behavioral state. The rate tracking, velocity fingerprint, and session coherence checkers all key their cache entries by canary cookie. If a load balancer routes consecutive requests from the same visitor to different processes, those checkers will see incomplete histories and produce weaker or inconsistent signals. Configure a shared external driver such as `redis` or `upstash` so all instances read and write the same state.\n::\n\n---\n\n## `banScore`\n\n::field{name=\"banScore\" type=\"number\"}\nDefault: `100`. The cumulative score threshold at which a visitor is banned. When a request's accumulated penalty points reach or exceed this value at any point in the pipeline, the middleware immediately responds with `403` and records the ban.\n\nLower values ban visitors more aggressively. A value of `30` would ban a visitor that triggers just two or three moderate checks, while the default of `100` requires several checks to fail before a ban is issued.\n::\n\n```ts\nbanScore: 75 \u002F\u002F ban after accumulating 75 penalty points\n```\n\n---\n\n## `maxScore`\n\n::field{name=\"maxScore\" type=\"number\"}\nDefault: `100`. The ceiling on the total score that any single request can accumulate. Penalty points beyond this value are ignored. In most configurations this matches `banScore`, but you can set it lower to cap extreme outliers from inflating scores beyond what is meaningful.\n::\n\n---\n\n## `restoredReputationPoints`\n\n::field{name=\"restoredReputationPoints\" type=\"number\"}\nDefault: `10`. The number of points the reputation healer subtracts from a visitor's stored score after each clean request. A clean request is one that does not result in a ban. This gives legitimate visitors a path to recover from an initial high score caused by unusual network conditions.\n\nFor example, with `restoredReputationPoints: 10` and an initial score of `40`, a visitor needs four consecutive clean requests to reach a score of `0`.\n::\n\n---\n\n## `setNewComputedScore`\n\n::field{name=\"setNewComputedScore\" type=\"boolean\"}\nDefault: `false`. Controls how the computed bot score is written to the database on each request.\n\n\n**`false`: Snapshot then heal (default).** The detector writes the computed score once on the visitor's first request (or after the cache expires). On every subsequent request, the reputation healer decrements the stored score by `restoredReputationPoints`. This mode is efficient because the expensive score computation only runs on cache misses.\n---\n\n**`true`: Live snapshot.** The detector overwrites the stored score on every single request. The reputation healer then immediately decrements it. The database always reflects the freshest computed risk for every visitor, at the cost of one extra database write per request.\n\nChoose `true` when you need your dashboard or reporting tools to show the current risk score after every page view.\n::\n\n---\n\n## `whiteList`\n\n::field{name=\"whiteList\" type=\"(IPv4 | IPv6 | string)[]\"}\nDefault: `[]`. A list of IP addresses or CIDR strings that bypass the entire detection pipeline. Requests from these addresses skip all checkers and pass directly to the next handler. This is useful for internal monitoring tools, health check probes, or trusted partner IPs.\n::\n\n```ts\nwhiteList: ['127.0.0.1', '::1', '10.0.0.0\u002F8']\n```\n\n---\n\n## `checksTimeRateControl`\n\nControls how often the full detection pipeline runs for returning visitors who are already cached.\n\n::field-group\n::field{name=\"checkEveryRequest\" type=\"boolean\"}\nDefault: `true`. When `true`, runs the full pipeline on every request regardless of cache.\n::\n\n::field{name=\"checkEvery\" type=\"number\"}\nDefault: `300000`. When `checkEveryRequest` is `false`, only re-runs the pipeline after this many milliseconds (5 minutes by default). A visitor whose result is cached passes through immediately until this interval elapses.\n::\n::\n\n```ts\nchecksTimeRateControl: {\n  checkEveryRequest: false,\n  checkEvery: 1000 * 60 * 2, \u002F\u002F re-check every 2 minutes\n}\n```\n\n---\n\n## `batchQueue`\n\nThe batch queue collects visitor writes and flushes them to the database asynchronously. This decouples visitor persistence from the request path, so database latency never affects response time.\n\n::field-group\n::field{name=\"flushIntervalMs\" type=\"number\"}\nDefault: `5000`. How often the queue flushes pending writes, in milliseconds. Increase this to reduce database load on busy servers.\n::\n\n::field{name=\"maxBufferSize\" type=\"number\"}\nDefault: `100`. Triggers an immediate flush when this many jobs are queued. Increase this if your batch sizes consistently hit the limit before the interval fires.\n::\n\n::field{name=\"maxRetries\" type=\"number\"}\nDefault: `3`. Retry attempts on a failed flush before the batch is discarded.\n::\n::\n\n---\n\n## `punishmentType`\n\n::field-group\n::field{name=\"enableFireWallBan\" type=\"boolean\"}\nDefault: `false`. When `true`, issues a `ufw` OS-level firewall rule in addition to the `403` response. Banned IPs are blocked at the network layer via `sudo ufw insert 1 deny from \u003Cip>`, preventing traffic from reaching the Node.js process on subsequent connections.\n::\n::\n\n::warning\n`enableFireWallBan` requires a Linux environment with `ufw` installed and passwordless `sudo` access for the Node.js process. It has no effect and should not be enabled on macOS or Windows.\n::\n\n---\n\n## `logLevel`\n\n::field{name=\"logLevel\" type=\"'debug' | 'info' | 'warn' | 'error' | 'fatal'\"}\nDefault: `'info'`. Sets the Pino log level for the middleware. Use `'debug'` during development to see per-request checker decisions. Set `'warn'` or `'error'` in production to reduce log volume.\n::\n\n---\n\n## `checkers`\n\nEvery checker is enabled by default. To disable a checker entirely, pass `{ enable: false }`. To adjust its penalty values, pass `{ enable: true, penalties: { ... } }` with the fields you want to override, all unspecified fields keep their defaults.\n\n```ts\ncheckers: {\n  enableTorAnalysis: { enable: false }, \u002F\u002F disable completely\n  enableBehaviorRateCheck: {\n    enable: true,\n    behavioral_threshold: 20, \u002F\u002F stricter rate limit\n    penalties: 80,            \u002F\u002F heavier penalty\n  },\n}\n```\n\n### `enableIpChecks`\n\n**Phase:** cheap\n\nValidates that the client IP is a properly formatted IPv4 or IPv6 address. Requests with a malformed or missing IP receive a penalty. Automated scripts that manipulate the `X-Forwarded-For` header to produce an invalid IP value are caught here.\n\n::field-group\n::field{name=\"penalties\" type=\"number\"}\nDefault: `10`. Applied when the IP is invalid or cannot be parsed.\n::\n::\n\n---\n\n### `enableGoodBotsChecks`\n\n**Phase:** cheap\n\nIdentifies legitimate crawlers such as Googlebot, Bingbot, DuckDuckBot, Apple, and Meta by matching the client IP against the compiled `goodBots.mmdb`. When a match is found, the request is immediately exempted from scoring.\n\n`banUnlistedBots` controls what happens when a request presents a bot-like User-Agent that is not in the verified crawler list. When `true` (default), unlisted bots receive the full `penalties` score.\n\n::field-group\n::field{name=\"banUnlistedBots\" type=\"boolean\"}\nDefault: `true`. When `true`, bots not present in the verified crawler database receive the full penalty score.\n::\n\n::field{name=\"penalties\" type=\"number\"}\nDefault: `100`. Score applied to unlisted bots when `banUnlistedBots` is `true`.\n::\n::\n\n---\n\n### `enableBrowserAndDeviceChecks`\n\n**Phase:** cheap\n\nInspects the parsed User-Agent for browsers and device combinations that are impossible or highly suspicious in a real-user context. Each condition carries its own penalty weight.\n\nAll weights below live inside the `penalties: {}` sub-object.\n\n::field-group\n::field{name=\"cliOrLibrary\" type=\"number\"}\nDefault: `100`. User-Agent belongs to a CLI tool or HTTP library (curl, python-requests, etc.).\n::\n\n::field{name=\"internetExplorer\" type=\"number\"}\nDefault: `100`. User-Agent identifies as Internet Explorer.\n::\n\n::field{name=\"linuxOs\" type=\"number\"}\nDefault: `10`. Desktop visit from Linux (elevated risk signal, not a ban signal alone).\n::\n\n::field{name=\"impossibleBrowserCombinations\" type=\"number\"}\nDefault: `30`. Browser and OS combination that cannot exist in practice.\n::\n\n::field{name=\"browserTypeUnknown\" type=\"number\"}\nDefault: `10`. Browser type field could not be determined.\n::\n\n::field{name=\"browserNameUnknown\" type=\"number\"}\nDefault: `10`. Browser name field could not be determined.\n::\n\n::field{name=\"desktopWithoutOS\" type=\"number\"}\nDefault: `10`. Desktop device type with no operating system in the UA.\n::\n\n::field{name=\"deviceVendorUnknown\" type=\"number\"}\nDefault: `10`. Device vendor could not be determined.\n::\n\n::field{name=\"browserVersionUnknown\" type=\"number\"}\nDefault: `10`. Browser version could not be determined.\n::\n\n::field{name=\"deviceModelUnknown\" type=\"number\"}\nDefault: `5`. Device model could not be determined.\n::\n::\n\n---\n\n### `localeMapsCheck`\n\n**Phase:** cheap\n\nCompares the `Accept-Language` header with the geolocation of the client IP. A legitimate browser sends a language that matches the country the IP is registered in. Automated tools often send a hardcoded or missing `Accept-Language`.\n\nAll weights below live inside the `penalties: {}` sub-object.\n\n::field-group\n::field{name=\"ipAndHeaderMismatch\" type=\"number\"}\nDefault: `20`. `Accept-Language` locale does not match the IP's geo locale.\n::\n\n::field{name=\"missingHeader\" type=\"number\"}\nDefault: `20`. `Accept-Language` header is absent.\n::\n\n::field{name=\"missingGeoData\" type=\"number\"}\nDefault: `20`. Geo data is unavailable for the IP.\n::\n\n::field{name=\"malformedHeader\" type=\"number\"}\nDefault: `30`. `Accept-Language` header is present but cannot be parsed.\n::\n::\n\n---\n\n### `enableKnownThreatsDetections`\n\n**Phase:** cheap\n\nChecks the client IP against the [FireHOL](https:\u002F\u002Fiplists.firehol.org\u002F) threat intelligence feeds. FireHOL maintains four ranked lists of known malicious IPs, plus an anonymizer feed for VPNs and anonymizing proxies.\n\nAll weights below live inside the `penalties: {}` sub-object. The four `threatLevels` fields are nested one level deeper inside `penalties.threatLevels: {}`.\n\n::field-group\n::field{name=\"anonymiseNetwork\" type=\"number\"}\nDefault: `20`. IP is in the FireHOL anonymous (VPN\u002Fanonymizer) feed.\n::\n\n::field{name=\"threatLevels.criticalLevel1\" type=\"number\"}\nDefault: `40`. IP is in FireHOL level 1 (active attack sources).\n::\n\n::field{name=\"threatLevels.currentAttacksLevel2\" type=\"number\"}\nDefault: `30`. IP is in FireHOL level 2 (current attack participants).\n::\n\n::field{name=\"threatLevels.threatLevel3\" type=\"number\"}\nDefault: `20`. IP is in FireHOL level 3 (broader threat list).\n::\n\n::field{name=\"threatLevels.threatLevel4\" type=\"number\"}\nDefault: `10`. IP is in FireHOL level 4 (extended watch list).\n::\n::\n\n---\n\n### `enableAsnClassification`\n\n**Phase:** cheap\n\nChecks the Autonomous System Number associated with the client IP. Hosting providers, cloud platforms, and data centers make up the majority of bot traffic. IPs from AS networks classified as hosting or content delivery receive a penalty. Networks with very few visible routes (low visibility) are also penalized, as they are characteristic of residential proxy services.\n\nAll weights below live inside the `penalties: {}` sub-object.\n\n::field-group\n::field{name=\"contentClassification\" type=\"number\"}\nDefault: `20`. ASN is classified as a hosting or CDN network.\n::\n\n::field{name=\"unknownClassification\" type=\"number\"}\nDefault: `10`. ASN classification cannot be determined.\n::\n\n::field{name=\"lowVisibilityPenalty\" type=\"number\"}\nDefault: `10`. ASN has fewer routes visible than `lowVisibilityThreshold`.\n::\n\n::field{name=\"lowVisibilityThreshold\" type=\"number\"}\nDefault: `15`. Minimum route count before `lowVisibilityPenalty` applies.\n::\n\n::field{name=\"comboHostingLowVisibility\" type=\"number\"}\nDefault: `20`. ASN is both hosting-classified and low-visibility.\n::\n::\n\n---\n\n### `enableTorAnalysis`\n\n**Phase:** cheap\n\nChecks the client IP against the compiled Tor relay database. Tor exit nodes are the most likely to be used for malicious automation, while guard nodes and running relays carry lower risk. Obsolete Tor versions suggest a misconfigured or malicious relay.\n\nAll weights below live inside the `penalties: {}` sub-object.\n\n::field-group\n::field{name=\"runningNode\" type=\"number\"}\nDefault: `15`. IP belongs to an active Tor relay.\n::\n\n::field{name=\"exitNode\" type=\"number\"}\nDefault: `20`. IP is a Tor exit node.\n::\n\n::field{name=\"webExitCapable\" type=\"number\"}\nDefault: `15`. IP is capable of exiting to web ports.\n::\n\n::field{name=\"guardNode\" type=\"number\"}\nDefault: `10`. IP is a Tor guard (entry) node.\n::\n\n::field{name=\"badExit\" type=\"number\"}\nDefault: `40`. IP is flagged as a bad Tor exit.\n::\n\n::field{name=\"obsoleteVersion\" type=\"number\"}\nDefault: `10`. IP is running an outdated Tor version.\n::\n::\n\n---\n\n### `enableTimezoneConsistency`\n\n**Phase:** cheap\n\nCompares the timezone sent in request headers against the timezone expected for the client's geo IP. A mismatch suggests the visitor is using a VPN or proxy that routes through a different region than their actual location.\n\n::field-group\n::field{name=\"penalties\" type=\"number\"}\nDefault: `20`. Applied when the declared timezone does not match the geo timezone.\n::\n::\n\n---\n\n### `honeypot`\n\n**Phase:** cheap\n\nMonitors requests to a configurable list of trap URLs. These paths serve no legitimate purpose and should never be visited by a real user. Automated scanners and vulnerability probes routinely request paths like `\u002F.env`, `\u002Fwp-login.php`, and `\u002Fadmin`. Any request to a listed path immediately sets the score to `banScore`, triggering a ban.\n\n::field-group\n::field{name=\"paths\" type=\"string[]\"}\nDefault: `[]`. List of URL paths to treat as honeypots. Any request matching one of these paths is banned immediately.\n::\n::\n\n```ts\nhoneypot: {\n  enable: true,\n  paths: ['\u002F.env', '\u002Fwp-login.php', '\u002Fadmin', '\u002FphpMyAdmin'],\n}\n```\n\n---\n\n### `enableKnownBadIpsCheck`\n\n**Phase:** cheap\n\nChecks the client IP against your custom `highRisk.mmdb`, which is generated by `bot-detector generate` from your own visitor history. IPs that have previously accumulated a high suspicion score in your database are caught here on all future requests without re-running the full pipeline.\n\n::field-group\n::field{name=\"highRiskPenalty\" type=\"number\"}\nDefault: `30`. Score applied when the IP is found in `highRisk.mmdb`.\n::\n::\n\n::tip\nRun `bot-detector generate` periodically to keep this database current with your latest visitor data.\n::\n\n---\n\n### `enableBehaviorRateCheck`\n\n**Phase:** heavy\n\nTracks request frequency per canary cookie. When a visitor sends more requests than `behavioral_threshold` within the `behavioral_window` time period, the excess is penalized. This catches fast-scanning bots and automated scripts that make hundreds of requests per minute.\n\n::field-group\n::field{name=\"behavioral_window\" type=\"number\"}\nDefault: `60000`. Sliding time window in milliseconds (1 minute by default).\n::\n\n::field{name=\"behavioral_threshold\" type=\"number\"}\nDefault: `30`. Maximum requests allowed within the window before the penalty applies.\n::\n\n::field{name=\"penalties\" type=\"number\"}\nDefault: `60`. Score applied when the threshold is exceeded.\n::\n::\n\n```ts\nenableBehaviorRateCheck: {\n  enable: true,\n  behavioral_window: 60_000,   \u002F\u002F 1-minute window\n  behavioral_threshold: 15,    \u002F\u002F stricter: max 15 req\u002Fmin\n  penalties: 80,\n}\n```\n\n---\n\n### `enableProxyIspCookiesChecks`\n\n**Phase:** heavy\n\nPerforms three related checks: proxy detection against the compiled `proxy.mmdb`, ISP classification for unknown or suspicious providers, and canary cookie presence. A missing canary cookie on a non-first request strongly suggests a bot that discards cookies between requests.\n\nAll weights below live inside the `penalties: {}` sub-object.\n\n::field-group\n::field{name=\"cookieMissing\" type=\"number\"}\nDefault: `80`. `canary_id` cookie is absent on a non-first request.\n::\n\n::field{name=\"proxyDetected\" type=\"number\"}\nDefault: `40`. IP is in the proxy database.\n::\n\n::field{name=\"hostingDetected\" type=\"number\"}\nDefault: `50`. IP belongs to a known hosting or data-center provider.\n::\n\n::field{name=\"ispUnknown\" type=\"number\"}\nDefault: `10`. ISP cannot be determined from the IP.\n::\n\n::field{name=\"orgUnknown\" type=\"number\"}\nDefault: `10`. Organisation cannot be determined from the IP.\n::\n\n::field{name=\"multiSourceBonus2to3\" type=\"number\"}\nDefault: `10`. IP flagged by 2 to 3 proxy sources (cumulative risk bonus).\n::\n\n::field{name=\"multiSourceBonus4plus\" type=\"number\"}\nDefault: `20`. IP flagged by 4 or more proxy sources.\n::\n::\n\n---\n\n### `enableUaAndHeaderChecks`\n\n**Phase:** heavy\n\nRuns a multi-factor inspection of the User-Agent and HTTP headers. It detects headless browsers by looking for tell-tale header patterns, penalizes suspiciously short User-Agents, and checks basic TLS cipher, protocol version, and HTTP version consistency.\n\nAll weights below live inside the `penalties: {}` sub-object.\n\n::field-group\n::field{name=\"headlessBrowser\" type=\"number\"}\nDefault: `100`. Headers match known headless browser patterns (Puppeteer, Playwright, etc.).\n::\n\n::field{name=\"shortUserAgent\" type=\"number\"}\nDefault: `80`. User-Agent string is shorter than expected for a real browser.\n::\n\n::field{name=\"tlsCheckFailed\" type=\"number\"}\nDefault: `60`. The TLS cipher suite, TLS version, or HTTP protocol version forwarded by the proxy does not match what a real browser would use. Requires the proxy to set `x-client-cipher` and `x-client-tls-version` headers.\n::\n\n::field{name=\"badUaChecker\" type=\"boolean\"}\nDefault: `true`. When `true`, the LMDB User-Agent pattern library is consulted and penalties from `knownBadUserAgents` apply.\n::\n::\n\n---\n\n### `enableGeoChecks`\n\n**Phase:** heavy\n\nChecks for missing or incomplete geolocation data and enforces country-level bans. Legitimate residential IPs consistently resolve to a full set of geo fields. Requests where city, region, country, timezone, or coordinates are unknown may originate from misconfigured VPNs, private IP ranges leaked through proxies, or IP addresses not present in the geo database.\n\n`bannedCountries` accepts a list of ISO 3166-1 alpha-2 country codes. Any request from a banned country receives the full `banScore`, triggering an immediate ban.\n\n`bannedCountries` is a top-level field on the checker. All geo unknown penalty weights live inside the `penalties: {}` sub-object.\n\n::field-group\n::field{name=\"bannedCountries\" type=\"string[]\"}\nDefault: `[]`. ISO 3166-1 alpha-2 country codes to ban outright. Example: `['KP', 'IR']`.\n::\n\n::field{name=\"countryUnknown\" type=\"number\"}\nDefault: `10`. Country cannot be determined.\n::\n\n::field{name=\"regionUnknown\" type=\"number\"}\nDefault: `10`. Region cannot be determined.\n::\n\n::field{name=\"latLonUnknown\" type=\"number\"}\nDefault: `10`. Coordinates cannot be determined.\n::\n\n::field{name=\"districtUnknown\" type=\"number\"}\nDefault: `10`. District cannot be determined.\n::\n\n::field{name=\"cityUnknown\" type=\"number\"}\nDefault: `10`. City cannot be determined.\n::\n\n::field{name=\"timezoneUnknown\" type=\"number\"}\nDefault: `10`. Timezone cannot be determined.\n::\n\n::field{name=\"subregionUnknown\" type=\"number\"}\nDefault: `10`. Sub-region cannot be determined.\n::\n\n::field{name=\"phoneUnknown\" type=\"number\"}\nDefault: `10`. Phone prefix cannot be determined.\n::\n\n::field{name=\"continentUnknown\" type=\"number\"}\nDefault: `10`. Continent cannot be determined.\n::\n::\n\n---\n\n### `enableSessionCoherence`\n\n**Phase:** heavy\n\nInspects the `Referer` header for consistency with the request path and domain. Legitimate browsers include a `Referer` header on navigation requests and it consistently matches the current site's domain. Bots that crawl by constructing URLs directly often produce missing, mismatched, or cross-domain referers.\n\nAll weights below live inside the `penalties: {}` sub-object.\n\n::field-group\n::field{name=\"pathMismatch\" type=\"number\"}\nDefault: `10`. Referer path does not match the expected navigation flow.\n::\n\n::field{name=\"missingReferer\" type=\"number\"}\nDefault: `20`. Referer is absent on a request that should have one.\n::\n\n::field{name=\"domainMismatch\" type=\"number\"}\nDefault: `30`. Referer domain does not match the current site domain.\n::\n::\n\n---\n\n### `enableVelocityFingerprint`\n\n**Phase:** heavy\n\nMeasures the statistical regularity of a visitor's inter-request timing using the coefficient of variation (CV). Human users have naturally irregular timing between requests. Automated scripts often produce highly regular intervals. When the CV of a visitor's request timing falls below `cvThreshold`, the request is penalized.\n\n::field-group\n::field{name=\"cvThreshold\" type=\"number\"}\nDefault: `0.1`. Minimum coefficient of variation before the penalty applies. Lower values require more regularity to trigger.\n::\n\n::field{name=\"penalties\" type=\"number\"}\nDefault: `40`. Score applied when timing is unnaturally regular.\n::\n::\n\n---\n\n### `knownBadUserAgents`\n\n**Phase:** heavy\n\nCross-references the User-Agent string against an LMDB database of known malicious, scraper, and vulnerability-scanner patterns. Each pattern carries a severity level that maps to a separate penalty. This checker is the most comprehensive User-Agent check and is backed by a continuously updated pattern library.\n\nAll weights below live inside the `penalties: {}` sub-object.\n\n::field-group\n::field{name=\"criticalSeverity\" type=\"number\"}\nDefault: `100`. Pattern matches a known critical-severity bad User-Agent.\n::\n\n::field{name=\"highSeverity\" type=\"number\"}\nDefault: `80`. Pattern matches a high-severity bad User-Agent.\n::\n\n::field{name=\"mediumSeverity\" type=\"number\"}\nDefault: `30`. Pattern matches a medium-severity bad User-Agent.\n::\n\n::field{name=\"lowSeverity\" type=\"number\"}\nDefault: `10`. Pattern matches a low-severity bad User-Agent.\n::\n::\n\n::note\nThis checker only runs when `enableUaAndHeaderChecks.penalties.badUaChecker` is `true` (the default). Disabling that option bypasses this checker regardless of its own `enable` setting.\n::\n\n---\n\n## `headerOptions`\n\nFine-grained penalty weights for the HTTP header fingerprint analysis performed by `enableUaAndHeaderChecks`. Each weight corresponds to a specific header anomaly. The total accumulated weight across all detected anomalies is added to the request score.\n\n::field-group\n::field{name=\"weightPerMustHeader\" type=\"number\"}\nDefault: `20`. Each mandatory header that is absent for the declared browser type.\n::\n\n::field{name=\"missingBrowserEngine\" type=\"number\"}\nDefault: `30`. No browser engine header present.\n::\n\n::field{name=\"postManOrInsomiaHeaders\" type=\"number\"}\nDefault: `50`. Headers characteristic of Postman or Insomnia REST clients.\n::\n\n::field{name=\"AJAXHeaderExists\" type=\"number\"}\nDefault: `30`. `X-Requested-With: XMLHttpRequest` present in a non-AJAX context.\n::\n\n::field{name=\"connectionHeaderIsClose\" type=\"number\"}\nDefault: `20`. `Connection: close` header, which browsers do not send by default.\n::\n\n::field{name=\"originHeaderIsNULL\" type=\"number\"}\nDefault: `10`. `Origin` header is present but set to `null`.\n::\n\n::field{name=\"originHeaderMismatch\" type=\"number\"}\nDefault: `30`. `Origin` header domain does not match the request host.\n::\n\n::field{name=\"omittedAcceptHeader\" type=\"number\"}\nDefault: `30`. `Accept` header is completely absent.\n::\n\n::field{name=\"clientHintsMissingForBlink\" type=\"number\"}\nDefault: `30`. Client hint headers are absent for a Chromium (Blink) User-Agent.\n::\n\n::field{name=\"teHeaderUnexpectedForBlink\" type=\"number\"}\nDefault: `10`. `TE` header present in a Chromium request (Chromium does not send it).\n::\n\n::field{name=\"clientHintsUnexpectedForGecko\" type=\"number\"}\nDefault: `30`. Client hint headers are present for a Firefox (Gecko) User-Agent.\n::\n\n::field{name=\"teHeaderMissingForGecko\" type=\"number\"}\nDefault: `20`. `TE` header absent for a Firefox User-Agent (Firefox sends it).\n::\n\n::field{name=\"aggressiveCacheControlOnGet\" type=\"number\"}\nDefault: `15`. `Cache-Control: no-cache` or `no-store` on a GET request.\n::\n\n::field{name=\"crossSiteRequestMissingReferer\" type=\"number\"}\nDefault: `10`. Cross-site navigation without a `Referer` header.\n::\n\n::field{name=\"inconsistentSecFetchMode\" type=\"number\"}\nDefault: `20`. `Sec-Fetch-Mode` value inconsistent with the request type.\n::\n\n::field{name=\"hostMismatchWeight\" type=\"number\"}\nDefault: `40`. `Host` header does not match the configured server host.\n::\n::\n\n---\n\n## `pathTraveler`\n\nConfiguration for the path traversal detection logic, which catches requests attempting to access files outside the web root using encoded `..\u002F` sequences.\n\n::field-group\n::field{name=\"maxIterations\" type=\"number\"}\nDefault: `3`. Maximum decoding passes to attempt when looking for traversal sequences.\n::\n\n::field{name=\"maxPathLength\" type=\"number\"}\nDefault: `1500`. Maximum raw path length in characters before a penalty applies.\n::\n\n::field{name=\"pathLengthToLong\" type=\"number\"}\nDefault: `100`. Penalty applied when the path exceeds `maxPathLength`.\n::\n\n::field{name=\"longDecoding\" type=\"number\"}\nDefault: `100`. Penalty applied when the path requires more than `maxIterations` decoding passes.\n::\n\n::field{name=\"traversalDetected\" type=\"number\"}\nDefault: `60`. Penalty applied when a `..\u002F` traversal sequence is found after decoding.\n::\n::\n\n---\n\n## `generator`\n\nControls how `bot-detector generate` (and the programmatic `runGeneration()`) compiles your visitor history into custom MMDB databases.\n\n::field-group\n::field{name=\"scoreThreshold\" type=\"number\"}\nDefault: `70`. Minimum `suspicious_activity_score` a visitor row must have to be included in `highRisk.mmdb`. Lowering it includes more visitors in the fast-rejection list; raising it makes the list more conservative.\n::\n\n::field{name=\"generateTypes\" type=\"boolean\"}\nDefault: `false`. When `true`, generates TypeScript type definitions alongside the MMDB files.\n::\n\n::field{name=\"deleteAfterBuild\" type=\"boolean\"}\nDefault: `false`. When `true`, deletes the source database rows after a successful compile. Useful for keeping your database lean. Banned rows and high-risk visitor records compiled into MMDB are no longer needed in SQL form.\n::\n\n::field{name=\"mmdbctlPath\" type=\"string\"}\nDefault: `'mmdbctl'`. Path to the `mmdbctl` binary. Override this when `mmdbctl` is not on the system `PATH`.\n::\n::\n",{"title":188,"description":3505},"v5IeRTEP6Z0zaQO5-IMMkMsDiOf4tmlk-qxoKF7AQs8",[3514,3509],{"title":184,"path":185,"stem":186,"children":-1},{"id":830,"title":188,"body":3516,"description":3505,"extension":3506,"icon":3507,"meta":5531,"module":3509,"navigation":8,"path":189,"rawbody":3510,"seo":5532,"stem":190,"__hash__":3512},{"type":832,"value":3517,"toc":5495},[3518,3524,3588,3590,3594,3600,3608,3680,3788,3790,3794,3798,3806,3928,3996,4010,4012,4016,4030,4042,4044,4048,4056,4058,4062,4076,4078,4082,4106,4108,4112,4118,4150,4152,4156,4158,4178,4216,4218,4222,4224,4244,4246,4250,4266,4276,4278,4282,4294,4296,4300,4306,4364,4368,4372,4376,4384,4386,4390,4394,4398,4406,4426,4428,4432,4436,4438,4442,4504,4506,4510,4514,4520,4524,4556,4558,4562,4566,4571,4579,4611,4613,4617,4621,4623,4627,4663,4665,4669,4673,4675,4679,4717,4719,4723,4727,4729,4737,4739,4743,4747,4757,4765,4821,4823,4827,4831,4837,4847,4853,4855,4859,4863,4869,4889,4937,4939,4943,4947,4951,4955,5001,5003,5007,5011,5013,5017,5051,5053,5057,5061,5063,5069,5075,5139,5141,5145,5149,5155,5159,5179,5181,5185,5189,5193,5207,5209,5213,5217,5219,5223,5249,5259,5261,5265,5269,5393,5395,5399,5403,5441,5443,5447,5453,5493],[835,3519,3520,841,3522,845],{},[838,3521,840],{},[838,3523,844],{},[847,3525,3526],{"className":849,"code":850,"filename":851,"language":852,"meta":853,"style":853},[838,3527,3528,3536,3544,3576,3580,3584],{"__ignoreMap":853},[857,3529,3530,3532,3534],{"class":859,"line":860},[857,3531,864],{"class":863},[857,3533,868],{"class":867},[857,3535,872],{"class":871},[857,3537,3538,3540,3542],{"class":859,"line":875},[857,3539,879],{"class":878},[857,3541,883],{"class":882},[857,3543,886],{"class":871},[857,3545,3546,3548,3550,3552,3554,3556,3558,3560,3562,3564,3566,3568,3570,3572,3574],{"class":859,"line":889},[857,3547,892],{"class":878},[857,3549,883],{"class":882},[857,3551,897],{"class":871},[857,3553,900],{"class":878},[857,3555,883],{"class":882},[857,3557,906],{"class":905},[857,3559,910],{"class":909},[857,3561,913],{"class":905},[857,3563,916],{"class":871},[857,3565,919],{"class":878},[857,3567,883],{"class":882},[857,3569,906],{"class":905},[857,3571,926],{"class":909},[857,3573,913],{"class":905},[857,3575,931],{"class":871},[857,3577,3578],{"class":859,"line":934},[857,3579,937],{"class":871},[857,3581,3582],{"class":859,"line":940},[857,3583,944],{"class":943},[857,3585,3586],{"class":859,"line":947},[857,3587,950],{"class":871},[952,3589],{},[955,3591,3592],{"id":957},[838,3593,957],{},[835,3595,962,3596,965,3598,968],{},[838,3597,957],{},[838,3599,844],{},[970,3601,3602],{"name":972,"type":973,":required":974},[835,3603,977,3604,980,3606,983],{},[838,3605,973],{},[838,3607,900],{},[985,3609,3610,3622],{},[988,3611,3612],{},[991,3613,3614,3616,3620],{},[994,3615,996],{},[994,3617,3618,1001],{},[838,3619,900],{},[994,3621,1004],{},[1006,3623,3624,3636,3648,3660,3670],{},[991,3625,3626,3628,3632],{},[1011,3627,1013],{},[1011,3629,3630],{},[838,3631,910],{},[1011,3633,3634],{},[838,3635,1022],{},[991,3637,3638,3640,3644],{},[1011,3639,1027],{},[1011,3641,3642],{},[838,3643,1032],{},[1011,3645,3646],{},[838,3647,1037],{},[991,3649,3650,3652,3656],{},[1011,3651,1042],{},[1011,3653,3654],{},[838,3655,1047],{},[1011,3657,3658],{},[838,3659,1052],{},[991,3661,3662,3664,3668],{},[1011,3663,1057],{},[1011,3665,3666],{},[838,3667,1062],{},[1011,3669,1065],{},[991,3671,3672,3674,3678],{},[1011,3673,1070],{},[1011,3675,3676],{},[838,3677,1075],{},[1011,3679,1078],{},[847,3681,3682],{"className":849,"code":1081,"filename":851,"language":852,"meta":853,"style":853},[838,3683,3684,3688,3708,3712,3716,3760,3764,3768],{"__ignoreMap":853},[857,3685,3686],{"class":859,"line":860},[857,3687,1088],{"class":943},[857,3689,3690,3692,3694,3696,3698,3700,3702,3704,3706],{"class":859,"line":875},[857,3691,1093],{"class":871},[857,3693,913],{"class":905},[857,3695,910],{"class":909},[857,3697,913],{"class":905},[857,3699,1102],{"class":871},[857,3701,913],{"class":905},[857,3703,926],{"class":909},[857,3705,913],{"class":905},[857,3707,1111],{"class":871},[857,3709,3710],{"class":859,"line":889},[857,3711,1116],{"emptyLinePlaceholder":8},[857,3713,3714],{"class":859,"line":934},[857,3715,1121],{"class":943},[857,3717,3718,3720,3722,3724,3726,3728,3730,3732,3734,3736,3738,3740,3742,3744,3746,3748,3750,3752,3754,3756,3758],{"class":859,"line":940},[857,3719,1093],{"class":871},[857,3721,913],{"class":905},[857,3723,1032],{"class":909},[857,3725,913],{"class":905},[857,3727,1134],{"class":871},[857,3729,913],{"class":905},[857,3731,1139],{"class":909},[857,3733,913],{"class":905},[857,3735,1144],{"class":871},[857,3737,913],{"class":905},[857,3739,1149],{"class":909},[857,3741,913],{"class":905},[857,3743,1154],{"class":871},[857,3745,913],{"class":905},[857,3747,1159],{"class":909},[857,3749,913],{"class":905},[857,3751,1164],{"class":871},[857,3753,913],{"class":905},[857,3755,1169],{"class":909},[857,3757,913],{"class":905},[857,3759,1111],{"class":871},[857,3761,3762],{"class":859,"line":947},[857,3763,1116],{"emptyLinePlaceholder":8},[857,3765,3766],{"class":859,"line":1180},[857,3767,1183],{"class":943},[857,3769,3770,3772,3774,3776,3778,3780,3782,3784,3786],{"class":859,"line":1186},[857,3771,1093],{"class":871},[857,3773,913],{"class":905},[857,3775,1047],{"class":909},[857,3777,913],{"class":905},[857,3779,1197],{"class":871},[857,3781,913],{"class":905},[857,3783,1202],{"class":909},[857,3785,913],{"class":905},[857,3787,1111],{"class":871},[952,3789],{},[955,3791,3792],{"id":1211},[838,3793,1211],{},[835,3795,962,3796,1218],{},[838,3797,1211],{},[970,3799,3800],{"name":1211,"type":1221},[835,3801,1224,3802,980,3804,1229],{},[838,3803,1221],{},[838,3805,900],{},[985,3807,3808,3820],{},[988,3809,3810],{},[991,3811,3812,3814,3818],{},[994,3813,996],{},[994,3815,3816,1001],{},[838,3817,900],{},[994,3819,1244],{},[1006,3821,3822,3834,3848,3858,3868,3878,3890,3906,3918],{},[991,3823,3824,3826,3832],{},[1011,3825,1251],{},[1011,3827,3828],{},[1255,3829,1257,3830,1260],{},[838,3831,1211],{},[1011,3833,1263],{},[991,3835,3836,3838,3842],{},[1011,3837,1268],{},[1011,3839,3840],{},[838,3841,1273],{},[1011,3843,1276,3844,1280,3846,1284],{},[838,3845,1279],{},[838,3847,1283],{},[991,3849,3850,3852,3856],{},[1011,3851,1289],{},[1011,3853,3854],{},[838,3855,1294],{},[1011,3857,1297],{},[991,3859,3860,3862,3866],{},[1011,3861,1302],{},[1011,3863,3864],{},[838,3865,1307],{},[1011,3867,1310],{},[991,3869,3870,3872,3876],{},[1011,3871,1315],{},[1011,3873,3874],{},[838,3875,1320],{},[1011,3877,1323],{},[991,3879,3880,3882,3886],{},[1011,3881,1328],{},[1011,3883,3884],{},[838,3885,1333],{},[1011,3887,1336,3888,1340],{},[838,3889,1339],{},[991,3891,3892,3894,3898],{},[1011,3893,1345],{},[1011,3895,3896],{},[838,3897,1350],{},[1011,3899,1336,3900,916,3902,916,3904],{},[838,3901,1355],{},[838,3903,1358],{},[838,3905,1361],{},[991,3907,3908,3910,3914],{},[1011,3909,1366],{},[1011,3911,3912],{},[838,3913,1371],{},[1011,3915,1336,3916],{},[838,3917,1339],{},[991,3919,3920,3922,3926],{},[1011,3921,1380],{},[1011,3923,3924],{},[838,3925,1385],{},[1011,3927,1388],{},[847,3929,3930],{"className":849,"code":1391,"filename":851,"language":852,"meta":853,"style":853},[838,3931,3932,3936,3960,3964,3968],{"__ignoreMap":853},[857,3933,3934],{"class":859,"line":860},[857,3935,1398],{"class":943},[857,3937,3938,3940,3942,3944,3946,3948,3950,3952,3954,3956,3958],{"class":859,"line":875},[857,3939,1403],{"class":871},[857,3941,913],{"class":905},[857,3943,1294],{"class":909},[857,3945,913],{"class":905},[857,3947,1134],{"class":871},[857,3949,913],{"class":905},[857,3951,1139],{"class":909},[857,3953,913],{"class":905},[857,3955,1420],{"class":871},[857,3957,1424],{"class":1423},[857,3959,1427],{"class":871},[857,3961,3962],{"class":859,"line":889},[857,3963,1116],{"emptyLinePlaceholder":8},[857,3965,3966],{"class":859,"line":934},[857,3967,1436],{"class":943},[857,3969,3970,3972,3974,3976,3978,3980,3982,3984,3986,3988,3990,3992,3994],{"class":859,"line":940},[857,3971,1403],{"class":871},[857,3973,913],{"class":905},[857,3975,1273],{"class":909},[857,3977,913],{"class":905},[857,3979,1449],{"class":871},[857,3981,1452],{"class":1423},[857,3983,1455],{"class":871},[857,3985,1458],{"class":1423},[857,3987,1462],{"class":1461},[857,3989,1465],{"class":1423},[857,3991,1462],{"class":1461},[857,3993,1470],{"class":1423},[857,3995,1427],{"class":871},[1474,3997,3998],{},[835,3999,1478,4000,1481,4002,916,4004,1486,4006,1489,4008,1492],{},[838,4001,1211],{},[838,4003,1273],{},[838,4005,1320],{},[838,4007,1294],{},[838,4009,1307],{},[952,4011],{},[955,4013,4014],{"id":1497},[838,4015,1500],{},[970,4017,4018,4024],{"name":1500,"type":1503},[835,4019,1506,4020,1510,4022,1514],{},[838,4021,1509],{},[838,4023,1513],{},[835,4025,1517,4026,1521,4028,1524],{},[838,4027,1520],{},[838,4029,1509],{},[847,4031,4032],{"className":849,"code":1527,"language":852,"meta":853,"style":853},[838,4033,4034],{"__ignoreMap":853},[857,4035,4036,4038,4040],{"class":859,"line":860},[857,4037,1534],{"class":871},[857,4039,1537],{"class":1423},[857,4041,1540],{"class":943},[952,4043],{},[955,4045,4046],{"id":1545},[838,4047,1548],{},[970,4049,4050],{"name":1548,"type":1503},[835,4051,1506,4052,1555,4054,1558],{},[838,4053,1509],{},[838,4055,1500],{},[952,4057],{},[955,4059,4060],{"id":1563},[838,4061,1566],{},[970,4063,4064,4068],{"name":1566,"type":1503},[835,4065,1506,4066,1574],{},[838,4067,1573],{},[835,4069,1577,4070,1581,4072,1585,4074,983],{},[838,4071,1580],{},[838,4073,1584],{},[838,4075,1588],{},[952,4077],{},[955,4079,4080],{"id":1593},[838,4081,1596],{},[970,4083,4084,4088,4096,4102],{"name":1596,"type":1599},[835,4085,1506,4086,1605],{},[838,4087,1604],{},[955,4089,4090,1615,4094,1618],{"id":1608},[1610,4091,4092,1614],{},[838,4093,1604],{},[838,4095,1566],{},[835,4097,4098,1626],{},[1610,4099,4100,1625],{},[838,4101,974],{},[835,4103,1629,4104,1632],{},[838,4105,974],{},[952,4107],{},[955,4109,4110],{"id":1637},[838,4111,1640],{},[970,4113,4114],{"name":1640,"type":1643},[835,4115,1506,4116,1649],{},[838,4117,1648],{},[847,4119,4120],{"className":849,"code":1652,"language":852,"meta":853,"style":853},[838,4121,4122],{"__ignoreMap":853},[857,4123,4124,4126,4128,4130,4132,4134,4136,4138,4140,4142,4144,4146,4148],{"class":859,"line":860},[857,4125,1659],{"class":871},[857,4127,913],{"class":905},[857,4129,1664],{"class":909},[857,4131,913],{"class":905},[857,4133,916],{"class":871},[857,4135,913],{"class":905},[857,4137,1673],{"class":909},[857,4139,913],{"class":905},[857,4141,916],{"class":871},[857,4143,913],{"class":905},[857,4145,1682],{"class":909},[857,4147,913],{"class":905},[857,4149,1687],{"class":871},[952,4151],{},[955,4153,4154],{"id":1692},[838,4155,1695],{},[835,4157,1698],{},[1700,4159,4160,4168],{},[970,4161,4162],{"name":1704,"type":1599},[835,4163,1506,4164,1709,4166,1712],{},[838,4165,974],{},[838,4167,974],{},[970,4169,4170],{"name":1715,"type":1503},[835,4171,1506,4172,1709,4174,1723,4176,1726],{},[838,4173,1720],{},[838,4175,1704],{},[838,4177,1604],{},[847,4179,4180],{"className":849,"code":1729,"language":852,"meta":853,"style":853},[838,4181,4182,4186,4194,4212],{"__ignoreMap":853},[857,4183,4184],{"class":859,"line":860},[857,4185,1736],{"class":871},[857,4187,4188,4190,4192],{"class":859,"line":875},[857,4189,1741],{"class":871},[857,4191,1604],{"class":1744},[857,4193,1747],{"class":871},[857,4195,4196,4198,4200,4202,4204,4206,4208,4210],{"class":859,"line":889},[857,4197,1752],{"class":871},[857,4199,1458],{"class":1423},[857,4201,1462],{"class":1461},[857,4203,1465],{"class":1423},[857,4205,1462],{"class":1461},[857,4207,1763],{"class":1423},[857,4209,916],{"class":871},[857,4211,1768],{"class":943},[857,4213,4214],{"class":859,"line":934},[857,4215,1773],{"class":871},[952,4217],{},[955,4219,4220],{"id":1778},[838,4221,1781],{},[835,4223,1784],{},[1700,4225,4226,4232,4238],{},[970,4227,4228],{"name":1789,"type":1503},[835,4229,1506,4230,1795],{},[838,4231,1794],{},[970,4233,4234],{"name":1798,"type":1503},[835,4235,1506,4236,1803],{},[838,4237,1509],{},[970,4239,4240],{"name":1806,"type":1503},[835,4241,1506,4242,1812],{},[838,4243,1811],{},[952,4245],{},[955,4247,4248],{"id":1817},[838,4249,1820],{},[1700,4251,4252],{},[970,4253,4254],{"name":1825,"type":1599},[835,4255,1506,4256,1709,4258,1832,4260,1836,4262,1839,4264,1843],{},[838,4257,1604],{},[838,4259,974],{},[838,4261,1835],{},[838,4263,1513],{},[838,4265,1842],{},[1474,4267,4268],{},[835,4269,4270,1850,4272,1853,4274,1857],{},[838,4271,1825],{},[838,4273,1835],{},[838,4275,1856],{},[952,4277],{},[955,4279,4280],{"id":1862},[838,4281,1865],{},[970,4283,4284],{"name":1865,"type":1868},[835,4285,1506,4286,1874,4288,1878,4290,1489,4292,1885],{},[838,4287,1873],{},[838,4289,1877],{},[838,4291,1881],{},[838,4293,1884],{},[952,4295],{},[955,4297,4298],{"id":1890},[838,4299,1890],{},[835,4301,1895,4302,1899,4304,1903],{},[838,4303,1898],{},[838,4305,1902],{},[847,4307,4308],{"className":849,"code":1906,"language":852,"meta":853,"style":853},[838,4309,4310,4314,4324,4328,4336,4346,4356,4360],{"__ignoreMap":853},[857,4311,4312],{"class":859,"line":860},[857,4313,1913],{"class":871},[857,4315,4316,4318,4320,4322],{"class":859,"line":875},[857,4317,1918],{"class":871},[857,4319,1604],{"class":1744},[857,4321,1923],{"class":871},[857,4323,1926],{"class":943},[857,4325,4326],{"class":859,"line":889},[857,4327,1931],{"class":871},[857,4329,4330,4332,4334],{"class":859,"line":934},[857,4331,1936],{"class":871},[857,4333,974],{"class":1744},[857,4335,1747],{"class":871},[857,4337,4338,4340,4342,4344],{"class":859,"line":940},[857,4339,1945],{"class":871},[857,4341,1948],{"class":1423},[857,4343,916],{"class":871},[857,4345,1953],{"class":943},[857,4347,4348,4350,4352,4354],{"class":859,"line":947},[857,4349,1958],{"class":871},[857,4351,1961],{"class":1423},[857,4353,1964],{"class":871},[857,4355,1967],{"class":943},[857,4357,4358],{"class":859,"line":1180},[857,4359,937],{"class":871},[857,4361,4362],{"class":859,"line":1186},[857,4363,1773],{"class":871},[1977,4365,4366],{"id":1979},[838,4367,1982],{},[835,4369,4370,1988],{},[1610,4371,1987],{},[835,4373,1991,4374,1995],{},[838,4375,1994],{},[1700,4377,4378],{},[970,4379,4380],{"name":2000,"type":1503},[835,4381,1506,4382,2005],{},[838,4383,1573],{},[952,4385],{},[1977,4387,4388],{"id":2010},[838,4389,2013],{},[835,4391,4392,1988],{},[1610,4393,1987],{},[835,4395,2020,4396,2024],{},[838,4397,2023],{},[835,4399,4400,2030,4402,2033,4404,2036],{},[838,4401,2029],{},[838,4403,974],{},[838,4405,2000],{},[1700,4407,4408,4416],{},[970,4409,4410],{"name":2029,"type":1599},[835,4411,1506,4412,1709,4414,2047],{},[838,4413,974],{},[838,4415,974],{},[970,4417,4418],{"name":2000,"type":1503},[835,4419,1506,4420,2054,4422,1723,4424,983],{},[838,4421,1509],{},[838,4423,2029],{},[838,4425,974],{},[952,4427],{},[1977,4429,4430],{"id":2063},[838,4431,2066],{},[835,4433,4434,1988],{},[1610,4435,1987],{},[835,4437,2073],{},[835,4439,2076,4440,2080],{},[838,4441,2079],{},[1700,4443,4444,4450,4456,4462,4468,4474,4480,4486,4492,4498],{},[970,4445,4446],{"name":2085,"type":1503},[835,4447,1506,4448,2090],{},[838,4449,1509],{},[970,4451,4452],{"name":2093,"type":1503},[835,4453,1506,4454,2098],{},[838,4455,1509],{},[970,4457,4458],{"name":2101,"type":1503},[835,4459,1506,4460,2106],{},[838,4461,1573],{},[970,4463,4464],{"name":2109,"type":1503},[835,4465,1506,4466,2114],{},[838,4467,1520],{},[970,4469,4470],{"name":2117,"type":1503},[835,4471,1506,4472,2122],{},[838,4473,1573],{},[970,4475,4476],{"name":2125,"type":1503},[835,4477,1506,4478,2130],{},[838,4479,1573],{},[970,4481,4482],{"name":2133,"type":1503},[835,4483,1506,4484,2138],{},[838,4485,1573],{},[970,4487,4488],{"name":2141,"type":1503},[835,4489,1506,4490,2146],{},[838,4491,1573],{},[970,4493,4494],{"name":2149,"type":1503},[835,4495,1506,4496,2154],{},[838,4497,1573],{},[970,4499,4500],{"name":2157,"type":1503},[835,4501,1506,4502,2163],{},[838,4503,2162],{},[952,4505],{},[1977,4507,4508],{"id":2168},[838,4509,2171],{},[835,4511,4512,1988],{},[1610,4513,1987],{},[835,4515,2178,4516,2182,4518,983],{},[838,4517,2181],{},[838,4519,2181],{},[835,4521,2076,4522,2080],{},[838,4523,2079],{},[1700,4525,4526,4534,4542,4548],{},[970,4527,4528],{"name":2193,"type":1503},[835,4529,1506,4530,2198,4532,2201],{},[838,4531,1948],{},[838,4533,2181],{},[970,4535,4536],{"name":2204,"type":1503},[835,4537,1506,4538,2198,4540,2211],{},[838,4539,1948],{},[838,4541,2181],{},[970,4543,4544],{"name":2214,"type":1503},[835,4545,1506,4546,2219],{},[838,4547,1948],{},[970,4549,4550],{"name":2222,"type":1503},[835,4551,1506,4552,2198,4554,2229],{},[838,4553,1520],{},[838,4555,2181],{},[952,4557],{},[1977,4559,4560],{"id":2234},[838,4561,2237],{},[835,4563,4564,1988],{},[1610,4565,1987],{},[835,4567,2244,4568,2252],{},[2246,4569,2251],{"href":2248,"rel":4570},[2250],[835,4572,2076,4573,2257,4575,2261,4577,983],{},[838,4574,2079],{},[838,4576,2260],{},[838,4578,2264],{},[1700,4580,4581,4587,4593,4599,4605],{},[970,4582,4583],{"name":2269,"type":1503},[835,4584,1506,4585,2274],{},[838,4586,1948],{},[970,4588,4589],{"name":2277,"type":1503},[835,4590,1506,4591,2282],{},[838,4592,1584],{},[970,4594,4595],{"name":2285,"type":1503},[835,4596,1506,4597,2290],{},[838,4598,1520],{},[970,4600,4601],{"name":2293,"type":1503},[835,4602,1506,4603,2298],{},[838,4604,1948],{},[970,4606,4607],{"name":2301,"type":1503},[835,4608,1506,4609,2306],{},[838,4610,1573],{},[952,4612],{},[1977,4614,4615],{"id":2311},[838,4616,2314],{},[835,4618,4619,1988],{},[1610,4620,1987],{},[835,4622,2321],{},[835,4624,2076,4625,2080],{},[838,4626,2079],{},[1700,4628,4629,4635,4641,4649,4657],{},[970,4630,4631],{"name":2330,"type":1503},[835,4632,1506,4633,2335],{},[838,4634,1948],{},[970,4636,4637],{"name":2338,"type":1503},[835,4638,1506,4639,2343],{},[838,4640,1573],{},[970,4642,4643],{"name":2346,"type":1503},[835,4644,1506,4645,2351,4647,983],{},[838,4646,1573],{},[838,4648,2354],{},[970,4650,4651],{"name":2354,"type":1503},[835,4652,1506,4653,2362,4655,2365],{},[838,4654,2361],{},[838,4656,2346],{},[970,4658,4659],{"name":2368,"type":1503},[835,4660,1506,4661,2373],{},[838,4662,1948],{},[952,4664],{},[1977,4666,4667],{"id":2378},[838,4668,2381],{},[835,4670,4671,1988],{},[1610,4672,1987],{},[835,4674,2388],{},[835,4676,2076,4677,2080],{},[838,4678,2079],{},[1700,4680,4681,4687,4693,4699,4705,4711],{},[970,4682,4683],{"name":2397,"type":1503},[835,4684,1506,4685,2402],{},[838,4686,2361],{},[970,4688,4689],{"name":2405,"type":1503},[835,4690,1506,4691,2410],{},[838,4692,1948],{},[970,4694,4695],{"name":2413,"type":1503},[835,4696,1506,4697,2418],{},[838,4698,2361],{},[970,4700,4701],{"name":2421,"type":1503},[835,4702,1506,4703,2426],{},[838,4704,1573],{},[970,4706,4707],{"name":2429,"type":1503},[835,4708,1506,4709,2434],{},[838,4710,1584],{},[970,4712,4713],{"name":2437,"type":1503},[835,4714,1506,4715,2442],{},[838,4716,1573],{},[952,4718],{},[1977,4720,4721],{"id":2447},[838,4722,2450],{},[835,4724,4725,1988],{},[1610,4726,1987],{},[835,4728,2457],{},[1700,4730,4731],{},[970,4732,4733],{"name":2000,"type":1503},[835,4734,1506,4735,2466],{},[838,4736,1948],{},[952,4738],{},[1977,4740,4741],{"id":2471},[838,4742,2471],{},[835,4744,4745,1988],{},[1610,4746,1987],{},[835,4748,2480,4749,916,4751,2487,4753,2491,4755,2494],{},[838,4750,2483],{},[838,4752,2486],{},[838,4754,2490],{},[838,4756,1500],{},[1700,4758,4759],{},[970,4760,4761],{"name":2499,"type":2500},[835,4762,1506,4763,2505],{},[838,4764,1648],{},[847,4766,4767],{"className":849,"code":2508,"language":852,"meta":853,"style":853},[838,4768,4769,4773,4781,4817],{"__ignoreMap":853},[857,4770,4771],{"class":859,"line":860},[857,4772,2515],{"class":871},[857,4774,4775,4777,4779],{"class":859,"line":875},[857,4776,2520],{"class":871},[857,4778,974],{"class":1744},[857,4780,1747],{"class":871},[857,4782,4783,4785,4787,4789,4791,4793,4795,4797,4799,4801,4803,4805,4807,4809,4811,4813,4815],{"class":859,"line":889},[857,4784,2529],{"class":871},[857,4786,913],{"class":905},[857,4788,2483],{"class":909},[857,4790,913],{"class":905},[857,4792,916],{"class":871},[857,4794,913],{"class":905},[857,4796,2486],{"class":909},[857,4798,913],{"class":905},[857,4800,916],{"class":871},[857,4802,913],{"class":905},[857,4804,2490],{"class":909},[857,4806,913],{"class":905},[857,4808,916],{"class":871},[857,4810,913],{"class":905},[857,4812,2558],{"class":909},[857,4814,913],{"class":905},[857,4816,2563],{"class":871},[857,4818,4819],{"class":859,"line":934},[857,4820,1773],{"class":871},[952,4822],{},[1977,4824,4825],{"id":2572},[838,4826,2575],{},[835,4828,4829,1988],{},[1610,4830,1987],{},[835,4832,2582,4833,2586,4835,2590],{},[838,4834,2585],{},[838,4836,2589],{},[1700,4838,4839],{},[970,4840,4841],{"name":2595,"type":1503},[835,4842,1506,4843,2600,4845,983],{},[838,4844,1520],{},[838,4846,2585],{},[2604,4848,4849],{},[835,4850,2608,4851,2611],{},[838,4852,2589],{},[952,4854],{},[1977,4856,4857],{"id":2616},[838,4858,2619],{},[835,4860,4861,2624],{},[1610,4862,1987],{},[835,4864,2627,4865,2631,4867,2635],{},[838,4866,2630],{},[838,4868,2634],{},[1700,4870,4871,4877,4883],{},[970,4872,4873],{"name":2634,"type":1503},[835,4874,1506,4875,2645],{},[838,4876,2644],{},[970,4878,4879],{"name":2630,"type":1503},[835,4880,1506,4881,2652],{},[838,4882,1520],{},[970,4884,4885],{"name":2000,"type":1503},[835,4886,1506,4887,2660],{},[838,4888,2659],{},[847,4890,4891],{"className":849,"code":2663,"language":852,"meta":853,"style":853},[838,4892,4893,4897,4905,4915,4925,4933],{"__ignoreMap":853},[857,4894,4895],{"class":859,"line":860},[857,4896,2670],{"class":871},[857,4898,4899,4901,4903],{"class":859,"line":875},[857,4900,2520],{"class":871},[857,4902,974],{"class":1744},[857,4904,1747],{"class":871},[857,4906,4907,4909,4911,4913],{"class":859,"line":889},[857,4908,2683],{"class":871},[857,4910,2686],{"class":1423},[857,4912,2689],{"class":871},[857,4914,2692],{"class":943},[857,4916,4917,4919,4921,4923],{"class":859,"line":934},[857,4918,2697],{"class":871},[857,4920,2361],{"class":1423},[857,4922,2702],{"class":871},[857,4924,2705],{"class":943},[857,4926,4927,4929,4931],{"class":859,"line":940},[857,4928,2710],{"class":871},[857,4930,1961],{"class":1423},[857,4932,1747],{"class":871},[857,4934,4935],{"class":859,"line":947},[857,4936,1773],{"class":871},[952,4938],{},[1977,4940,4941],{"id":2723},[838,4942,2726],{},[835,4944,4945,2624],{},[1610,4946,1987],{},[835,4948,2733,4949,2737],{},[838,4950,2736],{},[835,4952,2076,4953,2080],{},[838,4954,2079],{},[1700,4956,4957,4965,4971,4977,4983,4989,4995],{},[970,4958,4959],{"name":2746,"type":1503},[835,4960,1506,4961,2198,4963,2754],{},[838,4962,1961],{},[838,4964,2753],{},[970,4966,4967],{"name":2757,"type":1503},[835,4968,1506,4969,2762],{},[838,4970,1584],{},[970,4972,4973],{"name":2765,"type":1503},[835,4974,1506,4975,2771],{},[838,4976,2770],{},[970,4978,4979],{"name":2774,"type":1503},[835,4980,1506,4981,2779],{},[838,4982,1573],{},[970,4984,4985],{"name":2782,"type":1503},[835,4986,1506,4987,2787],{},[838,4988,1573],{},[970,4990,4991],{"name":2790,"type":1503},[835,4992,1506,4993,2795],{},[838,4994,1573],{},[970,4996,4997],{"name":2798,"type":1503},[835,4998,1506,4999,2803],{},[838,5000,1948],{},[952,5002],{},[1977,5004,5005],{"id":2808},[838,5006,2811],{},[835,5008,5009,2624],{},[1610,5010,1987],{},[835,5012,2818],{},[835,5014,2076,5015,2080],{},[838,5016,2079],{},[1700,5018,5019,5025,5031,5041],{},[970,5020,5021],{"name":2827,"type":1503},[835,5022,1506,5023,2832],{},[838,5024,1509],{},[970,5026,5027],{"name":2835,"type":1503},[835,5028,1506,5029,2840],{},[838,5030,1961],{},[970,5032,5033],{"name":2843,"type":1503},[835,5034,1506,5035,2848,5037,2852,5039,2856],{},[838,5036,2659],{},[838,5038,2851],{},[838,5040,2855],{},[970,5042,5043],{"name":2859,"type":1599},[835,5044,1506,5045,1709,5047,2866,5049,2870],{},[838,5046,974],{},[838,5048,974],{},[838,5050,2869],{},[952,5052],{},[1977,5054,5055],{"id":2875},[838,5056,2878],{},[835,5058,5059,2624],{},[1610,5060,1987],{},[835,5062,2885],{},[835,5064,5065,2891,5067,2894],{},[838,5066,2890],{},[838,5068,1500],{},[835,5070,5071,2899,5073,2080],{},[838,5072,2890],{},[838,5074,2079],{},[1700,5076,5077,5085,5091,5097,5103,5109,5115,5121,5127,5133],{},[970,5078,5079],{"name":2890,"type":2500},[835,5080,1506,5081,2910,5083,983],{},[838,5082,1648],{},[838,5084,2913],{},[970,5086,5087],{"name":2916,"type":1503},[835,5088,1506,5089,2921],{},[838,5090,1573],{},[970,5092,5093],{"name":2924,"type":1503},[835,5094,1506,5095,2929],{},[838,5096,1573],{},[970,5098,5099],{"name":2932,"type":1503},[835,5100,1506,5101,2937],{},[838,5102,1573],{},[970,5104,5105],{"name":2940,"type":1503},[835,5106,1506,5107,2945],{},[838,5108,1573],{},[970,5110,5111],{"name":2948,"type":1503},[835,5112,1506,5113,2953],{},[838,5114,1573],{},[970,5116,5117],{"name":2956,"type":1503},[835,5118,1506,5119,2961],{},[838,5120,1573],{},[970,5122,5123],{"name":2964,"type":1503},[835,5124,1506,5125,2969],{},[838,5126,1573],{},[970,5128,5129],{"name":2972,"type":1503},[835,5130,1506,5131,2977],{},[838,5132,1573],{},[970,5134,5135],{"name":2980,"type":1503},[835,5136,1506,5137,2985],{},[838,5138,1573],{},[952,5140],{},[1977,5142,5143],{"id":2990},[838,5144,2993],{},[835,5146,5147,2624],{},[1610,5148,1987],{},[835,5150,3000,5151,3004,5153,3007],{},[838,5152,3003],{},[838,5154,3003],{},[835,5156,2076,5157,2080],{},[838,5158,2079],{},[1700,5160,5161,5167,5173],{},[970,5162,5163],{"name":3016,"type":1503},[835,5164,1506,5165,3021],{},[838,5166,1573],{},[970,5168,5169],{"name":3024,"type":1503},[835,5170,1506,5171,3029],{},[838,5172,1948],{},[970,5174,5175],{"name":3032,"type":1503},[835,5176,1506,5177,3037],{},[838,5178,1520],{},[952,5180],{},[1977,5182,5183],{"id":3042},[838,5184,3045],{},[835,5186,5187,2624],{},[1610,5188,1987],{},[835,5190,3052,5191,3056],{},[838,5192,3055],{},[1700,5194,5195,5201],{},[970,5196,5197],{"name":3055,"type":1503},[835,5198,1506,5199,3066],{},[838,5200,3065],{},[970,5202,5203],{"name":2000,"type":1503},[835,5204,1506,5205,3073],{},[838,5206,1584],{},[952,5208],{},[1977,5210,5211],{"id":3078},[838,5212,2869],{},[835,5214,5215,2624],{},[1610,5216,1987],{},[835,5218,3087],{},[835,5220,2076,5221,2080],{},[838,5222,2079],{},[1700,5224,5225,5231,5237,5243],{},[970,5226,5227],{"name":3096,"type":1503},[835,5228,1506,5229,3101],{},[838,5230,1509],{},[970,5232,5233],{"name":3104,"type":1503},[835,5234,1506,5235,3109],{},[838,5236,1961],{},[970,5238,5239],{"name":3112,"type":1503},[835,5240,1506,5241,3117],{},[838,5242,1520],{},[970,5244,5245],{"name":3120,"type":1503},[835,5246,1506,5247,3125],{},[838,5248,1573],{},[3127,5250,5251],{},[835,5252,3131,5253,1723,5255,3137,5257,3141],{},[838,5254,3134],{},[838,5256,974],{},[838,5258,3140],{},[952,5260],{},[955,5262,5263],{"id":3146},[838,5264,3149],{},[835,5266,3152,5267,3155],{},[838,5268,2811],{},[1700,5270,5271,5277,5283,5289,5297,5305,5315,5323,5331,5337,5345,5351,5359,5369,5377,5385],{},[970,5272,5273],{"name":3160,"type":1503},[835,5274,1506,5275,3165],{},[838,5276,1948],{},[970,5278,5279],{"name":3168,"type":1503},[835,5280,1506,5281,3173],{},[838,5282,1520],{},[970,5284,5285],{"name":3176,"type":1503},[835,5286,1506,5287,3181],{},[838,5288,2770],{},[970,5290,5291],{"name":3184,"type":1503},[835,5292,1506,5293,2198,5295,3192],{},[838,5294,1520],{},[838,5296,3191],{},[970,5298,5299],{"name":3195,"type":1503},[835,5300,1506,5301,2198,5303,3203],{},[838,5302,1948],{},[838,5304,3202],{},[970,5306,5307],{"name":3206,"type":1503},[835,5308,1506,5309,2198,5311,3214,5313,983],{},[838,5310,1573],{},[838,5312,3213],{},[838,5314,3217],{},[970,5316,5317],{"name":3220,"type":1503},[835,5318,1506,5319,2198,5321,3227],{},[838,5320,1520],{},[838,5322,3213],{},[970,5324,5325],{"name":3230,"type":1503},[835,5326,1506,5327,2198,5329,3238],{},[838,5328,1520],{},[838,5330,3237],{},[970,5332,5333],{"name":3241,"type":1503},[835,5334,1506,5335,3246],{},[838,5336,1520],{},[970,5338,5339],{"name":3249,"type":1503},[835,5340,1506,5341,2198,5343,3257],{},[838,5342,1573],{},[838,5344,3256],{},[970,5346,5347],{"name":3260,"type":1503},[835,5348,1506,5349,3265],{},[838,5350,1520],{},[970,5352,5353],{"name":3268,"type":1503},[835,5354,1506,5355,2198,5357,3275],{},[838,5356,1948],{},[838,5358,3256],{},[970,5360,5361],{"name":3278,"type":1503},[835,5362,1506,5363,2198,5365,1489,5367,3289],{},[838,5364,2361],{},[838,5366,3285],{},[838,5368,3288],{},[970,5370,5371],{"name":3292,"type":1503},[835,5372,1506,5373,3297,5375,3300],{},[838,5374,1573],{},[838,5376,3003],{},[970,5378,5379],{"name":3303,"type":1503},[835,5380,1506,5381,2198,5383,3311],{},[838,5382,1948],{},[838,5384,3310],{},[970,5386,5387],{"name":3314,"type":1503},[835,5388,1506,5389,2198,5391,3322],{},[838,5390,1584],{},[838,5392,3321],{},[952,5394],{},[955,5396,5397],{"id":3327},[838,5398,3330],{},[835,5400,3333,5401,3337],{},[838,5402,3336],{},[1700,5404,5405,5411,5417,5425,5433],{},[970,5406,5407],{"name":3342,"type":1503},[835,5408,1506,5409,3347],{},[838,5410,1811],{},[970,5412,5413],{"name":3350,"type":1503},[835,5414,1506,5415,3356],{},[838,5416,3355],{},[970,5418,5419],{"name":3359,"type":1503},[835,5420,1506,5421,3364,5423,983],{},[838,5422,1509],{},[838,5424,3350],{},[970,5426,5427],{"name":3369,"type":1503},[835,5428,1506,5429,3374,5431,3377],{},[838,5430,1509],{},[838,5432,3342],{},[970,5434,5435],{"name":3380,"type":1503},[835,5436,1506,5437,3385,5439,3388],{},[838,5438,2659],{},[838,5440,3336],{},[952,5442],{},[955,5444,5445],{"id":3393},[838,5446,3393],{},[835,5448,3398,5449,3401,5451,3405],{},[838,5450,2589],{},[838,5452,3404],{},[1700,5454,5455,5465,5473,5481],{},[970,5456,5457],{"name":3410,"type":1503},[835,5458,1506,5459,3416,5461,3420,5463,3423],{},[838,5460,3415],{},[838,5462,3419],{},[838,5464,2585],{},[970,5466,5467],{"name":3426,"type":1599},[835,5468,1506,5469,1709,5471,3433],{},[838,5470,1604],{},[838,5472,974],{},[970,5474,5475],{"name":3436,"type":1599},[835,5476,1506,5477,1709,5479,3443],{},[838,5478,1604],{},[838,5480,974],{},[970,5482,5483],{"name":3446,"type":3447},[835,5484,1506,5485,3453,5487,3457,5489,3460,5491,983],{},[838,5486,3452],{},[838,5488,3456],{},[838,5490,3456],{},[838,5492,3463],{},[3465,5494,3467],{},{"title":853,"searchDepth":875,"depth":875,"links":5496},[5497,5498,5499,5500,5501,5502,5503,5504,5505,5506,5507,5508,5509,5528,5529,5530],{"id":957,"depth":875,"text":957},{"id":1211,"depth":875,"text":1211},{"id":1497,"depth":875,"text":1500},{"id":1545,"depth":875,"text":1548},{"id":1563,"depth":875,"text":1566},{"id":1593,"depth":875,"text":1596},{"id":1608,"depth":875,"text":3477},{"id":1637,"depth":875,"text":1640},{"id":1692,"depth":875,"text":1695},{"id":1778,"depth":875,"text":1781},{"id":1817,"depth":875,"text":1820},{"id":1862,"depth":875,"text":1865},{"id":1890,"depth":875,"text":1890,"children":5510},[5511,5512,5513,5514,5515,5516,5517,5518,5519,5520,5521,5522,5523,5524,5525,5526,5527],{"id":1979,"depth":889,"text":1982},{"id":2010,"depth":889,"text":2013},{"id":2063,"depth":889,"text":2066},{"id":2168,"depth":889,"text":2171},{"id":2234,"depth":889,"text":2237},{"id":2311,"depth":889,"text":2314},{"id":2378,"depth":889,"text":2381},{"id":2447,"depth":889,"text":2450},{"id":2471,"depth":889,"text":2471},{"id":2572,"depth":889,"text":2575},{"id":2616,"depth":889,"text":2619},{"id":2723,"depth":889,"text":2726},{"id":2808,"depth":889,"text":2811},{"id":2875,"depth":889,"text":2878},{"id":2990,"depth":889,"text":2993},{"id":3042,"depth":889,"text":3045},{"id":3078,"depth":889,"text":2869},{"id":3146,"depth":875,"text":3149},{"id":3327,"depth":875,"text":3330},{"id":3393,"depth":875,"text":3393},{},{"title":188,"description":3505},1780436274352]