[{"data":1,"prerenderedAt":2916},["ShallowReactive",2],{"navLinks":3,"sidebar_docs_navigation_\u002Fdocs\u002Fbot-detection":64,"navigation":191,"navLinks_footer":816,"\u002Fdocs\u002Fbot-detection\u002Fguides\u002Flogging_page":829,"\u002Fdocs\u002Fbot-detection\u002Fguides\u002Flogging_surround":1997,"\u002Fdocs\u002Fbot-detection\u002Fguides\u002Flogging":2000},{"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":99,"body":831,"description":1989,"extension":1990,"icon":1991,"meta":1992,"module":1993,"navigation":8,"path":100,"rawbody":1994,"seo":1995,"stem":101,"__hash__":1996},"docs\u002Fdocs\u002Fbot-detection\u002F03.guides\u002FLOGGING.md",{"type":832,"value":833,"toc":1981},"minimark",[834,850,853,858,861,934,949,982,984,988,995,1096,1157,1175,1177,1181,1206,1393,1399,1462,1464,1468,1471,1651,1660,1772,1778,1780,1784,1791,1899,1909,1911,1915,1928,1957,1963,1977],[835,836,837,841,842,849],"p",{},[838,839,840],"code",{},"bot-detector"," uses ",[843,844,848],"a",{"href":845,"rel":846},"https:\u002F\u002Fgetpino.io\u002F",[847],"nofollow","Pino"," for structured JSON logging. Every significant event in the detection pipeline writes a log entry: request phases start and end, each individual checker fires its own entries with duration and score, bans are recorded, and reputation updates are tracked. All output goes to files on disk, split by severity.",[851,852],"hr",{},[854,855,857],"h2",{"id":856},"log-files","Log Files",[835,859,860],{},"Three files are written on startup if they do not already exist. Each file captures its named level and everything above it.",[862,863,864,880],"table",{},[865,866,867],"thead",{},[868,869,870,874,877],"tr",{},[871,872,873],"th",{},"File",[871,875,876],{},"Level captured",[871,878,879],{},"Contents",[881,882,883,900,919],"tbody",{},[868,884,885,891,897],{},[886,887,888],"td",{},[838,889,890],{},"info.log",[886,892,893,896],{},[838,894,895],{},"info"," and above",[886,898,899],{},"Full pipeline trace: phase boundaries, per-checker results, reputation updates, cache hits",[868,901,902,907,912],{},[886,903,904],{},[838,905,906],{},"warn.log",[886,908,909,896],{},[838,910,911],{},"warn",[886,913,914,915,918],{},"Ban decisions, pipeline aborts when ",[838,916,917],{},"banScore"," is reached, missing visitor records",[868,920,921,926,931],{},[886,922,923],{},[838,924,925],{},"errors.log",[886,927,928,896],{},[838,929,930],{},"error",[886,932,933],{},"Storage failures, database errors, unexpected exceptions",[835,935,936,937,940,941,944,945,948],{},"The files are written to a ",[838,938,939],{},"bot-detector-logs\u002F"," directory resolved from ",[838,942,943],{},"process.cwd()",". Set the ",[838,946,947],{},"LOG_DIR"," environment variable to write logs to a different location.",[950,951,957],"pre",{"className":952,"code":953,"filename":954,"language":955,"meta":956,"style":956},"language-bash shiki shiki-themes light-plus light-plus dracula","LOG_DIR=\u002Fvar\u002Flog\u002Fbot-detector node server.js\n","Terminal","bash","",[838,958,959],{"__ignoreMap":956},[960,961,964,967,971,975,979],"span",{"class":962,"line":963},"line",1,[960,965,947],{"class":966},"sWkX1",[960,968,970],{"class":969},"saOXh","=",[960,972,974],{"class":973},"sFB1V","\u002Fvar\u002Flog\u002Fbot-detector",[960,976,978],{"class":977},"sHOzp"," node",[960,980,981],{"class":973}," server.js\n",[851,983],{},[854,985,987],{"id":986},"log-level","Log Level",[835,989,990,991,994],{},"The ",[838,992,993],{},"logLevel"," configuration option controls the minimum level that is processed. Lower levels produce more output; higher levels suppress verbose trace entries.",[950,996,1001],{"className":997,"code":998,"filename":999,"language":1000,"meta":956,"style":956},"language-ts shiki shiki-themes light-plus light-plus dracula","await defineConfiguration({\n  store: { main: { driver: 'sqlite', name: '.\u002Fbot-detector.db' } },\n  logLevel: 'info', \u002F\u002F 'debug' | 'info' | 'warn' | 'error' | 'fatal'\n})\n","server.ts","ts",[838,1002,1003,1016,1070,1090],{"__ignoreMap":956},[960,1004,1005,1009,1012],{"class":962,"line":963},[960,1006,1008],{"class":1007},"sZ328","await",[960,1010,1011],{"class":977}," defineConfiguration",[960,1013,1015],{"class":1014},"sDd4n","({\n",[960,1017,1019,1023,1027,1030,1033,1035,1037,1040,1042,1046,1049,1052,1055,1058,1060,1062,1065,1067],{"class":962,"line":1018},2,[960,1020,1022],{"class":1021},"sjsA6","  store",[960,1024,1026],{"class":1025},"s34zl",":",[960,1028,1029],{"class":1014}," { ",[960,1031,1032],{"class":1021},"main",[960,1034,1026],{"class":1025},[960,1036,1029],{"class":1014},[960,1038,1039],{"class":1021},"driver",[960,1041,1026],{"class":1025},[960,1043,1045],{"class":1044},"sFkSl"," '",[960,1047,1048],{"class":973},"sqlite",[960,1050,1051],{"class":1044},"'",[960,1053,1054],{"class":1014},", ",[960,1056,1057],{"class":1021},"name",[960,1059,1026],{"class":1025},[960,1061,1045],{"class":1044},[960,1063,1064],{"class":973},".\u002Fbot-detector.db",[960,1066,1051],{"class":1044},[960,1068,1069],{"class":1014}," } },\n",[960,1071,1073,1076,1078,1080,1082,1084,1086],{"class":962,"line":1072},3,[960,1074,1075],{"class":1021},"  logLevel",[960,1077,1026],{"class":1025},[960,1079,1045],{"class":1044},[960,1081,895],{"class":973},[960,1083,1051],{"class":1044},[960,1085,1054],{"class":1014},[960,1087,1089],{"class":1088},"sghk6","\u002F\u002F 'debug' | 'info' | 'warn' | 'error' | 'fatal'\n",[960,1091,1093],{"class":962,"line":1092},4,[960,1094,1095],{"class":1014},"})\n",[862,1097,1098,1108],{},[865,1099,1100],{},[868,1101,1102,1105],{},[871,1103,1104],{},"Level",[871,1106,1107],{},"When to use",[881,1109,1110,1120,1129,1138,1147],{},[868,1111,1112,1117],{},[886,1113,1114],{},[838,1115,1116],{},"debug",[886,1118,1119],{},"Development only. Produces extremely verbose output.",[868,1121,1122,1126],{},[886,1123,1124],{},[838,1125,895],{},[886,1127,1128],{},"Default. Full pipeline trace with per-checker timing.",[868,1130,1131,1135],{},[886,1132,1133],{},[838,1134,911],{},[886,1136,1137],{},"Production with moderate traffic. Ban decisions and errors only.",[868,1139,1140,1144],{},[886,1141,1142],{},[838,1143,930],{},[886,1145,1146],{},"Strict mode. Only infrastructure failures.",[868,1148,1149,1154],{},[886,1150,1151],{},[838,1152,1153],{},"fatal",[886,1155,1156],{},"Minimal. Only unrecoverable errors.",[1158,1159,1160],"tip",{},[835,1161,1162,1163,1165,1166,1168,1169,1171,1172,1174],{},"Use ",[838,1164,911],{}," in production environments where log volume is a concern. Ban decisions and errors are always captured at ",[838,1167,911],{}," and ",[838,1170,930],{}," respectively, so you lose nothing operationally by suppressing ",[838,1173,895],{}," in high-traffic deployments.",[851,1176],{},[854,1178,1180],{"id":1179},"log-structure","Log Structure",[835,1182,1183,1184,1054,1187,1190,1191,1194,1195,1198,1199,1168,1202,1205],{},"Every entry is a JSON object. Pino adds ",[838,1185,1186],{},"level",[838,1188,1189],{},"time",", and ",[838,1192,1193],{},"pid"," automatically. The logger adds ",[838,1196,1197],{},"uptime"," (seconds since process start) to every entry via a mixin. Internal modules add a ",[838,1200,1201],{},"service",[838,1203,1204],{},"branch"," field to identify where the entry came from.",[950,1207,1210],{"className":1208,"code":1209,"language":5,"meta":956,"style":956},"language-json shiki shiki-themes light-plus light-plus dracula","{\n  \"level\": 30,\n  \"time\": \"2025-04-01T12:00:00.000Z\",\n  \"pid\": 1234,\n  \"uptime\": 142.5,\n  \"service\": \"BOT DETECTOR\",\n  \"branch\": \"checks\",\n  \"phase\": \"cheapPhase\",\n  \"reqId\": 1743508800000,\n  \"event\": \"start\"\n}\n",[838,1211,1212,1217,1238,1258,1273,1289,1309,1329,1350,1367,1387],{"__ignoreMap":956},[960,1213,1214],{"class":962,"line":963},[960,1215,1216],{"class":1014},"{\n",[960,1218,1219,1223,1226,1229,1231,1235],{"class":962,"line":1018},[960,1220,1222],{"class":1221},"saJyd","  \"",[960,1224,1186],{"class":1225},"s_W10",[960,1227,1228],{"class":1221},"\"",[960,1230,1026],{"class":969},[960,1232,1234],{"class":1233},"spgvN"," 30",[960,1236,1237],{"class":1014},",\n",[960,1239,1240,1242,1244,1246,1248,1251,1254,1256],{"class":962,"line":1072},[960,1241,1222],{"class":1221},[960,1243,1189],{"class":1225},[960,1245,1228],{"class":1221},[960,1247,1026],{"class":969},[960,1249,1250],{"class":1044}," \"",[960,1252,1253],{"class":973},"2025-04-01T12:00:00.000Z",[960,1255,1228],{"class":1044},[960,1257,1237],{"class":1014},[960,1259,1260,1262,1264,1266,1268,1271],{"class":962,"line":1092},[960,1261,1222],{"class":1221},[960,1263,1193],{"class":1225},[960,1265,1228],{"class":1221},[960,1267,1026],{"class":969},[960,1269,1270],{"class":1233}," 1234",[960,1272,1237],{"class":1014},[960,1274,1276,1278,1280,1282,1284,1287],{"class":962,"line":1275},5,[960,1277,1222],{"class":1221},[960,1279,1197],{"class":1225},[960,1281,1228],{"class":1221},[960,1283,1026],{"class":969},[960,1285,1286],{"class":1233}," 142.5",[960,1288,1237],{"class":1014},[960,1290,1292,1294,1296,1298,1300,1302,1305,1307],{"class":962,"line":1291},6,[960,1293,1222],{"class":1221},[960,1295,1201],{"class":1225},[960,1297,1228],{"class":1221},[960,1299,1026],{"class":969},[960,1301,1250],{"class":1044},[960,1303,1304],{"class":973},"BOT DETECTOR",[960,1306,1228],{"class":1044},[960,1308,1237],{"class":1014},[960,1310,1312,1314,1316,1318,1320,1322,1325,1327],{"class":962,"line":1311},7,[960,1313,1222],{"class":1221},[960,1315,1204],{"class":1225},[960,1317,1228],{"class":1221},[960,1319,1026],{"class":969},[960,1321,1250],{"class":1044},[960,1323,1324],{"class":973},"checks",[960,1326,1228],{"class":1044},[960,1328,1237],{"class":1014},[960,1330,1332,1334,1337,1339,1341,1343,1346,1348],{"class":962,"line":1331},8,[960,1333,1222],{"class":1221},[960,1335,1336],{"class":1225},"phase",[960,1338,1228],{"class":1221},[960,1340,1026],{"class":969},[960,1342,1250],{"class":1044},[960,1344,1345],{"class":973},"cheapPhase",[960,1347,1228],{"class":1044},[960,1349,1237],{"class":1014},[960,1351,1353,1355,1358,1360,1362,1365],{"class":962,"line":1352},9,[960,1354,1222],{"class":1221},[960,1356,1357],{"class":1225},"reqId",[960,1359,1228],{"class":1221},[960,1361,1026],{"class":969},[960,1363,1364],{"class":1233}," 1743508800000",[960,1366,1237],{"class":1014},[960,1368,1370,1372,1375,1377,1379,1381,1384],{"class":962,"line":1369},10,[960,1371,1222],{"class":1221},[960,1373,1374],{"class":1225},"event",[960,1376,1228],{"class":1221},[960,1378,1026],{"class":969},[960,1380,1250],{"class":1044},[960,1382,1383],{"class":973},"start",[960,1385,1386],{"class":1044},"\"\n",[960,1388,1390],{"class":962,"line":1389},11,[960,1391,1392],{"class":1014},"}\n",[835,1394,1395,1396,1398],{},"Common ",[838,1397,1204],{}," values and what they cover:",[862,1400,1401,1412],{},[865,1402,1403],{},[868,1404,1405,1409],{},[871,1406,1407],{},[838,1408,1204],{},[871,1410,1411],{},"Source",[881,1413,1414,1423,1432,1442,1452],{},[868,1415,1416,1420],{},[886,1417,1418],{},[838,1419,1032],{},[886,1421,1422],{},"Top-level detection entry and ban decisions",[868,1424,1425,1429],{},[886,1426,1427],{},[838,1428,1324],{},[886,1430,1431],{},"Per-checker and per-phase timing",[868,1433,1434,1439],{},[886,1435,1436],{},[838,1437,1438],{},"reputation",[886,1440,1441],{},"Score healing and cache reads",[868,1443,1444,1449],{},[886,1445,1446],{},[838,1447,1448],{},"generator",[886,1450,1451],{},"MMDB compilation runs",[868,1453,1454,1459],{},[886,1455,1456],{},[838,1457,1458],{},"batchQueue",[886,1460,1461],{},"Deferred DB write operations",[851,1463],{},[854,1465,1467],{"id":1466},"per-checker-entries","Per-Checker Entries",[835,1469,1470],{},"For every checker that runs, two entries are written: one when the checker starts and one when it finishes. The finish entry includes the checker's name, how long it took, what score it returned, and what reason codes it fired.",[950,1472,1474],{"className":1208,"code":1473,"language":5,"meta":956,"style":956},"{\n  \"level\": 30,\n  \"service\": \"BOT DETECTOR\",\n  \"branch\": \"checks\",\n  \"reqId\": 1743508800000,\n  \"check\": \"Tor Analysis\",\n  \"event\": \"end\",\n  \"durationMs\": 0.041,\n  \"score\": 35,\n  \"reasons\": [\"TOR_ACTIVE_NODE\", \"TOR_EXIT_NODE\"]\n}\n",[838,1475,1476,1480,1494,1512,1530,1544,1563,1582,1598,1614,1647],{"__ignoreMap":956},[960,1477,1478],{"class":962,"line":963},[960,1479,1216],{"class":1014},[960,1481,1482,1484,1486,1488,1490,1492],{"class":962,"line":1018},[960,1483,1222],{"class":1221},[960,1485,1186],{"class":1225},[960,1487,1228],{"class":1221},[960,1489,1026],{"class":969},[960,1491,1234],{"class":1233},[960,1493,1237],{"class":1014},[960,1495,1496,1498,1500,1502,1504,1506,1508,1510],{"class":962,"line":1072},[960,1497,1222],{"class":1221},[960,1499,1201],{"class":1225},[960,1501,1228],{"class":1221},[960,1503,1026],{"class":969},[960,1505,1250],{"class":1044},[960,1507,1304],{"class":973},[960,1509,1228],{"class":1044},[960,1511,1237],{"class":1014},[960,1513,1514,1516,1518,1520,1522,1524,1526,1528],{"class":962,"line":1092},[960,1515,1222],{"class":1221},[960,1517,1204],{"class":1225},[960,1519,1228],{"class":1221},[960,1521,1026],{"class":969},[960,1523,1250],{"class":1044},[960,1525,1324],{"class":973},[960,1527,1228],{"class":1044},[960,1529,1237],{"class":1014},[960,1531,1532,1534,1536,1538,1540,1542],{"class":962,"line":1275},[960,1533,1222],{"class":1221},[960,1535,1357],{"class":1225},[960,1537,1228],{"class":1221},[960,1539,1026],{"class":969},[960,1541,1364],{"class":1233},[960,1543,1237],{"class":1014},[960,1545,1546,1548,1551,1553,1555,1557,1559,1561],{"class":962,"line":1291},[960,1547,1222],{"class":1221},[960,1549,1550],{"class":1225},"check",[960,1552,1228],{"class":1221},[960,1554,1026],{"class":969},[960,1556,1250],{"class":1044},[960,1558,137],{"class":973},[960,1560,1228],{"class":1044},[960,1562,1237],{"class":1014},[960,1564,1565,1567,1569,1571,1573,1575,1578,1580],{"class":962,"line":1311},[960,1566,1222],{"class":1221},[960,1568,1374],{"class":1225},[960,1570,1228],{"class":1221},[960,1572,1026],{"class":969},[960,1574,1250],{"class":1044},[960,1576,1577],{"class":973},"end",[960,1579,1228],{"class":1044},[960,1581,1237],{"class":1014},[960,1583,1584,1586,1589,1591,1593,1596],{"class":962,"line":1331},[960,1585,1222],{"class":1221},[960,1587,1588],{"class":1225},"durationMs",[960,1590,1228],{"class":1221},[960,1592,1026],{"class":969},[960,1594,1595],{"class":1233}," 0.041",[960,1597,1237],{"class":1014},[960,1599,1600,1602,1605,1607,1609,1612],{"class":962,"line":1352},[960,1601,1222],{"class":1221},[960,1603,1604],{"class":1225},"score",[960,1606,1228],{"class":1221},[960,1608,1026],{"class":969},[960,1610,1611],{"class":1233}," 35",[960,1613,1237],{"class":1014},[960,1615,1616,1618,1621,1623,1625,1628,1630,1633,1635,1637,1639,1642,1644],{"class":962,"line":1369},[960,1617,1222],{"class":1221},[960,1619,1620],{"class":1225},"reasons",[960,1622,1228],{"class":1221},[960,1624,1026],{"class":969},[960,1626,1627],{"class":1014}," [",[960,1629,1228],{"class":1044},[960,1631,1632],{"class":973},"TOR_ACTIVE_NODE",[960,1634,1228],{"class":1044},[960,1636,1054],{"class":1014},[960,1638,1228],{"class":1044},[960,1640,1641],{"class":973},"TOR_EXIT_NODE",[960,1643,1228],{"class":1044},[960,1645,1646],{"class":1014},"]\n",[960,1648,1649],{"class":962,"line":1389},[960,1650,1392],{"class":1014},[835,1652,1653,1654,1656,1657,1659],{},"When the accumulated score reaches ",[838,1655,917],{},", the pipeline stops and writes a ",[838,1658,911],{},"-level entry:",[950,1661,1663],{"className":1208,"code":1662,"language":5,"meta":956,"style":956},"{\n  \"level\": 40,\n  \"service\": \"BOT DETECTOR\",\n  \"branch\": \"checks\",\n  \"reqId\": 1743508800000,\n  \"botScore\": 100,\n  \"msg\": \"Bot detected — aborting checks\"\n}\n",[838,1664,1665,1669,1684,1702,1720,1734,1750,1768],{"__ignoreMap":956},[960,1666,1667],{"class":962,"line":963},[960,1668,1216],{"class":1014},[960,1670,1671,1673,1675,1677,1679,1682],{"class":962,"line":1018},[960,1672,1222],{"class":1221},[960,1674,1186],{"class":1225},[960,1676,1228],{"class":1221},[960,1678,1026],{"class":969},[960,1680,1681],{"class":1233}," 40",[960,1683,1237],{"class":1014},[960,1685,1686,1688,1690,1692,1694,1696,1698,1700],{"class":962,"line":1072},[960,1687,1222],{"class":1221},[960,1689,1201],{"class":1225},[960,1691,1228],{"class":1221},[960,1693,1026],{"class":969},[960,1695,1250],{"class":1044},[960,1697,1304],{"class":973},[960,1699,1228],{"class":1044},[960,1701,1237],{"class":1014},[960,1703,1704,1706,1708,1710,1712,1714,1716,1718],{"class":962,"line":1092},[960,1705,1222],{"class":1221},[960,1707,1204],{"class":1225},[960,1709,1228],{"class":1221},[960,1711,1026],{"class":969},[960,1713,1250],{"class":1044},[960,1715,1324],{"class":973},[960,1717,1228],{"class":1044},[960,1719,1237],{"class":1014},[960,1721,1722,1724,1726,1728,1730,1732],{"class":962,"line":1275},[960,1723,1222],{"class":1221},[960,1725,1357],{"class":1225},[960,1727,1228],{"class":1221},[960,1729,1026],{"class":969},[960,1731,1364],{"class":1233},[960,1733,1237],{"class":1014},[960,1735,1736,1738,1741,1743,1745,1748],{"class":962,"line":1291},[960,1737,1222],{"class":1221},[960,1739,1740],{"class":1225},"botScore",[960,1742,1228],{"class":1221},[960,1744,1026],{"class":969},[960,1746,1747],{"class":1233}," 100",[960,1749,1237],{"class":1014},[960,1751,1752,1754,1757,1759,1761,1763,1766],{"class":962,"line":1311},[960,1753,1222],{"class":1221},[960,1755,1756],{"class":1225},"msg",[960,1758,1228],{"class":1221},[960,1760,1026],{"class":969},[960,1762,1250],{"class":1044},[960,1764,1765],{"class":973},"Bot detected — aborting checks",[960,1767,1386],{"class":1044},[960,1769,1770],{"class":962,"line":1331},[960,1771,1392],{"class":1014},[835,1773,1774,1775,1777],{},"This entry tells you exactly which checker pushed the score over the threshold. The checkers that fired before this entry in the same ",[838,1776,1357],{}," group show you the full picture of why the visitor was banned.",[851,1779],{},[854,1781,1783],{"id":1782},"sensitive-field-redaction","Sensitive Field Redaction",[835,1785,1786,1787,1790],{},"The logger automatically redacts values at the following paths before writing to disk. Redacted values are replaced with ",[838,1788,1789],{},"[SECRET]",".",[862,1792,1793,1803],{},[865,1794,1795],{},[868,1796,1797,1800],{},[871,1798,1799],{},"Redacted path",[871,1801,1802],{},"Covers",[881,1804,1805,1819,1831,1843,1856,1869,1879,1889],{},[868,1806,1807,1812],{},[886,1808,1809],{},[838,1810,1811],{},"*.password",[886,1813,1814,1815,1818],{},"Any nested ",[838,1816,1817],{},"password"," field",[868,1820,1821,1826],{},[886,1822,1823],{},[838,1824,1825],{},"*.email",[886,1827,1814,1828,1818],{},[838,1829,1830],{},"email",[868,1832,1833,1840],{},[886,1834,1835,1054,1837],{},[838,1836,1057],{},[838,1838,1839],{},"Name",[886,1841,1842],{},"Top-level name fields",[868,1844,1845,1853],{},[886,1846,1847,1054,1850],{},[838,1848,1849],{},"cookie",[838,1851,1852],{},"cookies",[886,1854,1855],{},"Top-level cookie fields",[868,1857,1858,1866],{},[886,1859,1860,1054,1863],{},[838,1861,1862],{},"*.cookie",[838,1864,1865],{},"*.cookies",[886,1867,1868],{},"Any nested cookie fields",[868,1870,1871,1876],{},[886,1872,1873],{},[838,1874,1875],{},"*.accessToken",[886,1877,1878],{},"Any nested access token",[868,1880,1881,1886],{},[886,1882,1883],{},[838,1884,1885],{},"*.refresh_token",[886,1887,1888],{},"Any nested refresh token",[868,1890,1891,1896],{},[886,1892,1893],{},[838,1894,1895],{},"*.secret",[886,1897,1898],{},"Any nested secret field",[1900,1901,1902],"note",{},[835,1903,1904,1905,1908],{},"Canary cookie values appear as strings in some log entries (for cache key tracing). The redaction covers structured object fields, not inline string values in log messages. Avoid logging ",[838,1906,1907],{},"ctx.cookie"," directly in custom checkers.",[851,1910],{},[854,1912,1914],{"id":1913},"reading-logs-for-a-specific-request","Reading Logs for a Specific Request",[835,1916,1917,1918,1920,1921,1924,1925,1927],{},"Each request gets a ",[838,1919,1357],{}," derived from ",[838,1922,1923],{},"Date.now()"," at the point the pipeline starts. To trace all entries for a single request, filter by ",[838,1926,1357],{},". With standard Unix tools:",[950,1929,1931],{"className":952,"code":1930,"filename":954,"language":955,"meta":956,"style":956},"grep '\"reqId\":1743508800000' bot-detector-logs\u002Finfo.log | jq .\n",[838,1932,1933],{"__ignoreMap":956},[960,1934,1935,1938,1940,1943,1945,1948,1951,1954],{"class":962,"line":963},[960,1936,1937],{"class":977},"grep",[960,1939,1045],{"class":1044},[960,1941,1942],{"class":973},"\"reqId\":1743508800000",[960,1944,1051],{"class":1044},[960,1946,1947],{"class":973}," bot-detector-logs\u002Finfo.log",[960,1949,1950],{"class":969}," |",[960,1952,1953],{"class":977}," jq",[960,1955,1956],{"class":973}," .\n",[835,1958,1959,1960,1962],{},"The entries in order give you the full execution trace: phase start, each checker with its score and reasons, phase end, and if the visitor was banned, the ",[838,1961,911],{}," abort entry.",[1158,1964,1965],{},[835,1966,1967,1968,1970,1971,1973,1974,1976],{},"In production, pipe your ",[838,1969,890],{}," into a log aggregator (Loki, Datadog, CloudWatch) and filter by ",[838,1972,1357],{}," or ",[838,1975,1204],{}," in the aggregator's query interface rather than grepping files directly.",[1978,1979,1980],"style",{},"html pre.shiki code .sWkX1, html code.shiki .sWkX1{--shiki-light:#001080;--shiki-default:#001080;--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 .sFB1V, html code.shiki .sFB1V{--shiki-light:#A31515;--shiki-default:#A31515;--shiki-dark:#F1FA8C}html pre.shiki code .sHOzp, html code.shiki .sHOzp{--shiki-light:#795E26;--shiki-default:#795E26;--shiki-dark:#50FA7B}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 .sZ328, html code.shiki .sZ328{--shiki-light:#AF00DB;--shiki-default:#AF00DB;--shiki-dark:#FF79C6}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 .sghk6, html code.shiki .sghk6{--shiki-light:#008000;--shiki-default:#008000;--shiki-dark:#6272A4}html pre.shiki code .saJyd, html code.shiki .saJyd{--shiki-light:#0451A5;--shiki-default:#0451A5;--shiki-dark:#8BE9FE}html pre.shiki code .s_W10, html code.shiki .s_W10{--shiki-light:#0451A5;--shiki-default:#0451A5;--shiki-dark:#8BE9FD}html pre.shiki code .spgvN, html code.shiki .spgvN{--shiki-light:#098658;--shiki-default:#098658;--shiki-dark:#BD93F9}",{"title":956,"searchDepth":1018,"depth":1018,"links":1982},[1983,1984,1985,1986,1987,1988],{"id":856,"depth":1018,"text":857},{"id":986,"depth":1018,"text":987},{"id":1179,"depth":1018,"text":1180},{"id":1466,"depth":1018,"text":1467},{"id":1782,"depth":1018,"text":1783},{"id":1913,"depth":1018,"text":1914},"Understanding the structured log output, log files, log levels, and what each entry tells you about the detection pipeline.","md","i-lucide-scroll-text",{},null,"---\ntitle: Logging\ndescription: Understanding the structured log output, log files, log levels, and what each entry tells you about the detection pipeline.\nicon: i-lucide-scroll-text\n---\n\n`bot-detector` uses [Pino](https:\u002F\u002Fgetpino.io\u002F) for structured JSON logging. Every significant event in the detection pipeline writes a log entry: request phases start and end, each individual checker fires its own entries with duration and score, bans are recorded, and reputation updates are tracked. All output goes to files on disk, split by severity.\n\n---\n\n## Log Files\n\nThree files are written on startup if they do not already exist. Each file captures its named level and everything above it.\n\n| File | Level captured | Contents |\n| --- | --- | --- |\n| `info.log` | `info` and above | Full pipeline trace: phase boundaries, per-checker results, reputation updates, cache hits |\n| `warn.log` | `warn` and above | Ban decisions, pipeline aborts when `banScore` is reached, missing visitor records |\n| `errors.log` | `error` and above | Storage failures, database errors, unexpected exceptions |\n\nThe files are written to a `bot-detector-logs\u002F` directory resolved from `process.cwd()`. Set the `LOG_DIR` environment variable to write logs to a different location.\n\n```bash [Terminal]\nLOG_DIR=\u002Fvar\u002Flog\u002Fbot-detector node server.js\n```\n\n---\n \n## Log Level\n\nThe `logLevel` configuration option controls the minimum level that is processed. Lower levels produce more output; higher levels suppress verbose trace entries.\n\n```ts [server.ts]\nawait defineConfiguration({\n  store: { main: { driver: 'sqlite', name: '.\u002Fbot-detector.db' } },\n  logLevel: 'info', \u002F\u002F 'debug' | 'info' | 'warn' | 'error' | 'fatal'\n})\n```\n\n| Level | When to use |\n| --- | --- |\n| `debug` | Development only. Produces extremely verbose output. |\n| `info` | Default. Full pipeline trace with per-checker timing. |\n| `warn` | Production with moderate traffic. Ban decisions and errors only. |\n| `error` | Strict mode. Only infrastructure failures. |\n| `fatal` | Minimal. Only unrecoverable errors. |\n\n::tip\nUse `warn` in production environments where log volume is a concern. Ban decisions and errors are always captured at `warn` and `error` respectively, so you lose nothing operationally by suppressing `info` in high-traffic deployments.\n::\n\n---\n\n## Log Structure\n\nEvery entry is a JSON object. Pino adds `level`, `time`, and `pid` automatically. The logger adds `uptime` (seconds since process start) to every entry via a mixin. Internal modules add a `service` and `branch` field to identify where the entry came from.\n\n```json\n{\n  \"level\": 30,\n  \"time\": \"2025-04-01T12:00:00.000Z\",\n  \"pid\": 1234,\n  \"uptime\": 142.5,\n  \"service\": \"BOT DETECTOR\",\n  \"branch\": \"checks\",\n  \"phase\": \"cheapPhase\",\n  \"reqId\": 1743508800000,\n  \"event\": \"start\"\n}\n```\n\nCommon `branch` values and what they cover:\n\n| `branch` | Source |\n| --- | --- |\n| `main` | Top-level detection entry and ban decisions |\n| `checks` | Per-checker and per-phase timing |\n| `reputation` | Score healing and cache reads |\n| `generator` | MMDB compilation runs |\n| `batchQueue` | Deferred DB write operations |\n\n---\n\n## Per-Checker Entries\n\nFor every checker that runs, two entries are written: one when the checker starts and one when it finishes. The finish entry includes the checker's name, how long it took, what score it returned, and what reason codes it fired.\n\n```json\n{\n  \"level\": 30,\n  \"service\": \"BOT DETECTOR\",\n  \"branch\": \"checks\",\n  \"reqId\": 1743508800000,\n  \"check\": \"Tor Analysis\",\n  \"event\": \"end\",\n  \"durationMs\": 0.041,\n  \"score\": 35,\n  \"reasons\": [\"TOR_ACTIVE_NODE\", \"TOR_EXIT_NODE\"]\n}\n```\n\nWhen the accumulated score reaches `banScore`, the pipeline stops and writes a `warn`-level entry:\n\n```json\n{\n  \"level\": 40,\n  \"service\": \"BOT DETECTOR\",\n  \"branch\": \"checks\",\n  \"reqId\": 1743508800000,\n  \"botScore\": 100,\n  \"msg\": \"Bot detected — aborting checks\"\n}\n```\n\nThis entry tells you exactly which checker pushed the score over the threshold. The checkers that fired before this entry in the same `reqId` group show you the full picture of why the visitor was banned.\n\n---\n\n## Sensitive Field Redaction\n\nThe logger automatically redacts values at the following paths before writing to disk. Redacted values are replaced with `[SECRET]`.\n\n| Redacted path | Covers |\n| --- | --- |\n| `*.password` | Any nested `password` field |\n| `*.email` | Any nested `email` field |\n| `name`, `Name` | Top-level name fields |\n| `cookie`, `cookies` | Top-level cookie fields |\n| `*.cookie`, `*.cookies` | Any nested cookie fields |\n| `*.accessToken` | Any nested access token |\n| `*.refresh_token` | Any nested refresh token |\n| `*.secret` | Any nested secret field |\n\n::note\nCanary cookie values appear as strings in some log entries (for cache key tracing). The redaction covers structured object fields, not inline string values in log messages. Avoid logging `ctx.cookie` directly in custom checkers.\n::\n\n---\n\n## Reading Logs for a Specific Request\n\nEach request gets a `reqId` derived from `Date.now()` at the point the pipeline starts. To trace all entries for a single request, filter by `reqId`. With standard Unix tools:\n\n```bash [Terminal]\ngrep '\"reqId\":1743508800000' bot-detector-logs\u002Finfo.log | jq .\n```\n\nThe entries in order give you the full execution trace: phase start, each checker with its score and reasons, phase end, and if the visitor was banned, the `warn` abort entry.\n\n::tip\nIn production, pipe your `info.log` into a log aggregator (Loki, Datadog, CloudWatch) and filter by `reqId` or `branch` in the aggregator's query interface rather than grepping files directly.\n::\n",{"title":99,"description":1989},"QPRjasPzbBDWpQm0J9n4OeXOG1PrUKL7_jBUKdRhfTc",[1998,1999],{"title":95,"path":96,"stem":97,"children":-1},{"title":103,"path":104,"stem":105,"children":-1},{"id":830,"title":99,"body":2001,"description":1989,"extension":1990,"icon":1991,"meta":2914,"module":1993,"navigation":8,"path":100,"rawbody":1994,"seo":2915,"stem":101,"__hash__":1996},{"type":832,"value":2002,"toc":2906},[2003,2010,2012,2014,2016,2068,2076,2092,2094,2096,2100,2170,2222,2234,2236,2238,2252,2408,2412,2466,2468,2470,2472,2640,2646,2752,2756,2758,2760,2764,2850,2856,2858,2860,2868,2890,2894,2904],[835,2004,2005,841,2007,849],{},[838,2006,840],{},[843,2008,848],{"href":845,"rel":2009},[847],[851,2011],{},[854,2013,857],{"id":856},[835,2015,860],{},[862,2017,2018,2028],{},[865,2019,2020],{},[868,2021,2022,2024,2026],{},[871,2023,873],{},[871,2025,876],{},[871,2027,879],{},[881,2029,2030,2042,2056],{},[868,2031,2032,2036,2040],{},[886,2033,2034],{},[838,2035,890],{},[886,2037,2038,896],{},[838,2039,895],{},[886,2041,899],{},[868,2043,2044,2048,2052],{},[886,2045,2046],{},[838,2047,906],{},[886,2049,2050,896],{},[838,2051,911],{},[886,2053,914,2054,918],{},[838,2055,917],{},[868,2057,2058,2062,2066],{},[886,2059,2060],{},[838,2061,925],{},[886,2063,2064,896],{},[838,2065,930],{},[886,2067,933],{},[835,2069,936,2070,940,2072,944,2074,948],{},[838,2071,939],{},[838,2073,943],{},[838,2075,947],{},[950,2077,2078],{"className":952,"code":953,"filename":954,"language":955,"meta":956,"style":956},[838,2079,2080],{"__ignoreMap":956},[960,2081,2082,2084,2086,2088,2090],{"class":962,"line":963},[960,2083,947],{"class":966},[960,2085,970],{"class":969},[960,2087,974],{"class":973},[960,2089,978],{"class":977},[960,2091,981],{"class":973},[851,2093],{},[854,2095,987],{"id":986},[835,2097,990,2098,994],{},[838,2099,993],{},[950,2101,2102],{"className":997,"code":998,"filename":999,"language":1000,"meta":956,"style":956},[838,2103,2104,2112,2150,2166],{"__ignoreMap":956},[960,2105,2106,2108,2110],{"class":962,"line":963},[960,2107,1008],{"class":1007},[960,2109,1011],{"class":977},[960,2111,1015],{"class":1014},[960,2113,2114,2116,2118,2120,2122,2124,2126,2128,2130,2132,2134,2136,2138,2140,2142,2144,2146,2148],{"class":962,"line":1018},[960,2115,1022],{"class":1021},[960,2117,1026],{"class":1025},[960,2119,1029],{"class":1014},[960,2121,1032],{"class":1021},[960,2123,1026],{"class":1025},[960,2125,1029],{"class":1014},[960,2127,1039],{"class":1021},[960,2129,1026],{"class":1025},[960,2131,1045],{"class":1044},[960,2133,1048],{"class":973},[960,2135,1051],{"class":1044},[960,2137,1054],{"class":1014},[960,2139,1057],{"class":1021},[960,2141,1026],{"class":1025},[960,2143,1045],{"class":1044},[960,2145,1064],{"class":973},[960,2147,1051],{"class":1044},[960,2149,1069],{"class":1014},[960,2151,2152,2154,2156,2158,2160,2162,2164],{"class":962,"line":1072},[960,2153,1075],{"class":1021},[960,2155,1026],{"class":1025},[960,2157,1045],{"class":1044},[960,2159,895],{"class":973},[960,2161,1051],{"class":1044},[960,2163,1054],{"class":1014},[960,2165,1089],{"class":1088},[960,2167,2168],{"class":962,"line":1092},[960,2169,1095],{"class":1014},[862,2171,2172,2180],{},[865,2173,2174],{},[868,2175,2176,2178],{},[871,2177,1104],{},[871,2179,1107],{},[881,2181,2182,2190,2198,2206,2214],{},[868,2183,2184,2188],{},[886,2185,2186],{},[838,2187,1116],{},[886,2189,1119],{},[868,2191,2192,2196],{},[886,2193,2194],{},[838,2195,895],{},[886,2197,1128],{},[868,2199,2200,2204],{},[886,2201,2202],{},[838,2203,911],{},[886,2205,1137],{},[868,2207,2208,2212],{},[886,2209,2210],{},[838,2211,930],{},[886,2213,1146],{},[868,2215,2216,2220],{},[886,2217,2218],{},[838,2219,1153],{},[886,2221,1156],{},[1158,2223,2224],{},[835,2225,1162,2226,1165,2228,1168,2230,1171,2232,1174],{},[838,2227,911],{},[838,2229,911],{},[838,2231,930],{},[838,2233,895],{},[851,2235],{},[854,2237,1180],{"id":1179},[835,2239,1183,2240,1054,2242,1190,2244,1194,2246,1198,2248,1168,2250,1205],{},[838,2241,1186],{},[838,2243,1189],{},[838,2245,1193],{},[838,2247,1197],{},[838,2249,1201],{},[838,2251,1204],{},[950,2253,2254],{"className":1208,"code":1209,"language":5,"meta":956,"style":956},[838,2255,2256,2260,2274,2292,2306,2320,2338,2356,2374,2388,2404],{"__ignoreMap":956},[960,2257,2258],{"class":962,"line":963},[960,2259,1216],{"class":1014},[960,2261,2262,2264,2266,2268,2270,2272],{"class":962,"line":1018},[960,2263,1222],{"class":1221},[960,2265,1186],{"class":1225},[960,2267,1228],{"class":1221},[960,2269,1026],{"class":969},[960,2271,1234],{"class":1233},[960,2273,1237],{"class":1014},[960,2275,2276,2278,2280,2282,2284,2286,2288,2290],{"class":962,"line":1072},[960,2277,1222],{"class":1221},[960,2279,1189],{"class":1225},[960,2281,1228],{"class":1221},[960,2283,1026],{"class":969},[960,2285,1250],{"class":1044},[960,2287,1253],{"class":973},[960,2289,1228],{"class":1044},[960,2291,1237],{"class":1014},[960,2293,2294,2296,2298,2300,2302,2304],{"class":962,"line":1092},[960,2295,1222],{"class":1221},[960,2297,1193],{"class":1225},[960,2299,1228],{"class":1221},[960,2301,1026],{"class":969},[960,2303,1270],{"class":1233},[960,2305,1237],{"class":1014},[960,2307,2308,2310,2312,2314,2316,2318],{"class":962,"line":1275},[960,2309,1222],{"class":1221},[960,2311,1197],{"class":1225},[960,2313,1228],{"class":1221},[960,2315,1026],{"class":969},[960,2317,1286],{"class":1233},[960,2319,1237],{"class":1014},[960,2321,2322,2324,2326,2328,2330,2332,2334,2336],{"class":962,"line":1291},[960,2323,1222],{"class":1221},[960,2325,1201],{"class":1225},[960,2327,1228],{"class":1221},[960,2329,1026],{"class":969},[960,2331,1250],{"class":1044},[960,2333,1304],{"class":973},[960,2335,1228],{"class":1044},[960,2337,1237],{"class":1014},[960,2339,2340,2342,2344,2346,2348,2350,2352,2354],{"class":962,"line":1311},[960,2341,1222],{"class":1221},[960,2343,1204],{"class":1225},[960,2345,1228],{"class":1221},[960,2347,1026],{"class":969},[960,2349,1250],{"class":1044},[960,2351,1324],{"class":973},[960,2353,1228],{"class":1044},[960,2355,1237],{"class":1014},[960,2357,2358,2360,2362,2364,2366,2368,2370,2372],{"class":962,"line":1331},[960,2359,1222],{"class":1221},[960,2361,1336],{"class":1225},[960,2363,1228],{"class":1221},[960,2365,1026],{"class":969},[960,2367,1250],{"class":1044},[960,2369,1345],{"class":973},[960,2371,1228],{"class":1044},[960,2373,1237],{"class":1014},[960,2375,2376,2378,2380,2382,2384,2386],{"class":962,"line":1352},[960,2377,1222],{"class":1221},[960,2379,1357],{"class":1225},[960,2381,1228],{"class":1221},[960,2383,1026],{"class":969},[960,2385,1364],{"class":1233},[960,2387,1237],{"class":1014},[960,2389,2390,2392,2394,2396,2398,2400,2402],{"class":962,"line":1369},[960,2391,1222],{"class":1221},[960,2393,1374],{"class":1225},[960,2395,1228],{"class":1221},[960,2397,1026],{"class":969},[960,2399,1250],{"class":1044},[960,2401,1383],{"class":973},[960,2403,1386],{"class":1044},[960,2405,2406],{"class":962,"line":1389},[960,2407,1392],{"class":1014},[835,2409,1395,2410,1398],{},[838,2411,1204],{},[862,2413,2414,2424],{},[865,2415,2416],{},[868,2417,2418,2422],{},[871,2419,2420],{},[838,2421,1204],{},[871,2423,1411],{},[881,2425,2426,2434,2442,2450,2458],{},[868,2427,2428,2432],{},[886,2429,2430],{},[838,2431,1032],{},[886,2433,1422],{},[868,2435,2436,2440],{},[886,2437,2438],{},[838,2439,1324],{},[886,2441,1431],{},[868,2443,2444,2448],{},[886,2445,2446],{},[838,2447,1438],{},[886,2449,1441],{},[868,2451,2452,2456],{},[886,2453,2454],{},[838,2455,1448],{},[886,2457,1451],{},[868,2459,2460,2464],{},[886,2461,2462],{},[838,2463,1458],{},[886,2465,1461],{},[851,2467],{},[854,2469,1467],{"id":1466},[835,2471,1470],{},[950,2473,2474],{"className":1208,"code":1473,"language":5,"meta":956,"style":956},[838,2475,2476,2480,2494,2512,2530,2544,2562,2580,2594,2608,2636],{"__ignoreMap":956},[960,2477,2478],{"class":962,"line":963},[960,2479,1216],{"class":1014},[960,2481,2482,2484,2486,2488,2490,2492],{"class":962,"line":1018},[960,2483,1222],{"class":1221},[960,2485,1186],{"class":1225},[960,2487,1228],{"class":1221},[960,2489,1026],{"class":969},[960,2491,1234],{"class":1233},[960,2493,1237],{"class":1014},[960,2495,2496,2498,2500,2502,2504,2506,2508,2510],{"class":962,"line":1072},[960,2497,1222],{"class":1221},[960,2499,1201],{"class":1225},[960,2501,1228],{"class":1221},[960,2503,1026],{"class":969},[960,2505,1250],{"class":1044},[960,2507,1304],{"class":973},[960,2509,1228],{"class":1044},[960,2511,1237],{"class":1014},[960,2513,2514,2516,2518,2520,2522,2524,2526,2528],{"class":962,"line":1092},[960,2515,1222],{"class":1221},[960,2517,1204],{"class":1225},[960,2519,1228],{"class":1221},[960,2521,1026],{"class":969},[960,2523,1250],{"class":1044},[960,2525,1324],{"class":973},[960,2527,1228],{"class":1044},[960,2529,1237],{"class":1014},[960,2531,2532,2534,2536,2538,2540,2542],{"class":962,"line":1275},[960,2533,1222],{"class":1221},[960,2535,1357],{"class":1225},[960,2537,1228],{"class":1221},[960,2539,1026],{"class":969},[960,2541,1364],{"class":1233},[960,2543,1237],{"class":1014},[960,2545,2546,2548,2550,2552,2554,2556,2558,2560],{"class":962,"line":1291},[960,2547,1222],{"class":1221},[960,2549,1550],{"class":1225},[960,2551,1228],{"class":1221},[960,2553,1026],{"class":969},[960,2555,1250],{"class":1044},[960,2557,137],{"class":973},[960,2559,1228],{"class":1044},[960,2561,1237],{"class":1014},[960,2563,2564,2566,2568,2570,2572,2574,2576,2578],{"class":962,"line":1311},[960,2565,1222],{"class":1221},[960,2567,1374],{"class":1225},[960,2569,1228],{"class":1221},[960,2571,1026],{"class":969},[960,2573,1250],{"class":1044},[960,2575,1577],{"class":973},[960,2577,1228],{"class":1044},[960,2579,1237],{"class":1014},[960,2581,2582,2584,2586,2588,2590,2592],{"class":962,"line":1331},[960,2583,1222],{"class":1221},[960,2585,1588],{"class":1225},[960,2587,1228],{"class":1221},[960,2589,1026],{"class":969},[960,2591,1595],{"class":1233},[960,2593,1237],{"class":1014},[960,2595,2596,2598,2600,2602,2604,2606],{"class":962,"line":1352},[960,2597,1222],{"class":1221},[960,2599,1604],{"class":1225},[960,2601,1228],{"class":1221},[960,2603,1026],{"class":969},[960,2605,1611],{"class":1233},[960,2607,1237],{"class":1014},[960,2609,2610,2612,2614,2616,2618,2620,2622,2624,2626,2628,2630,2632,2634],{"class":962,"line":1369},[960,2611,1222],{"class":1221},[960,2613,1620],{"class":1225},[960,2615,1228],{"class":1221},[960,2617,1026],{"class":969},[960,2619,1627],{"class":1014},[960,2621,1228],{"class":1044},[960,2623,1632],{"class":973},[960,2625,1228],{"class":1044},[960,2627,1054],{"class":1014},[960,2629,1228],{"class":1044},[960,2631,1641],{"class":973},[960,2633,1228],{"class":1044},[960,2635,1646],{"class":1014},[960,2637,2638],{"class":962,"line":1389},[960,2639,1392],{"class":1014},[835,2641,1653,2642,1656,2644,1659],{},[838,2643,917],{},[838,2645,911],{},[950,2647,2648],{"className":1208,"code":1662,"language":5,"meta":956,"style":956},[838,2649,2650,2654,2668,2686,2704,2718,2732,2748],{"__ignoreMap":956},[960,2651,2652],{"class":962,"line":963},[960,2653,1216],{"class":1014},[960,2655,2656,2658,2660,2662,2664,2666],{"class":962,"line":1018},[960,2657,1222],{"class":1221},[960,2659,1186],{"class":1225},[960,2661,1228],{"class":1221},[960,2663,1026],{"class":969},[960,2665,1681],{"class":1233},[960,2667,1237],{"class":1014},[960,2669,2670,2672,2674,2676,2678,2680,2682,2684],{"class":962,"line":1072},[960,2671,1222],{"class":1221},[960,2673,1201],{"class":1225},[960,2675,1228],{"class":1221},[960,2677,1026],{"class":969},[960,2679,1250],{"class":1044},[960,2681,1304],{"class":973},[960,2683,1228],{"class":1044},[960,2685,1237],{"class":1014},[960,2687,2688,2690,2692,2694,2696,2698,2700,2702],{"class":962,"line":1092},[960,2689,1222],{"class":1221},[960,2691,1204],{"class":1225},[960,2693,1228],{"class":1221},[960,2695,1026],{"class":969},[960,2697,1250],{"class":1044},[960,2699,1324],{"class":973},[960,2701,1228],{"class":1044},[960,2703,1237],{"class":1014},[960,2705,2706,2708,2710,2712,2714,2716],{"class":962,"line":1275},[960,2707,1222],{"class":1221},[960,2709,1357],{"class":1225},[960,2711,1228],{"class":1221},[960,2713,1026],{"class":969},[960,2715,1364],{"class":1233},[960,2717,1237],{"class":1014},[960,2719,2720,2722,2724,2726,2728,2730],{"class":962,"line":1291},[960,2721,1222],{"class":1221},[960,2723,1740],{"class":1225},[960,2725,1228],{"class":1221},[960,2727,1026],{"class":969},[960,2729,1747],{"class":1233},[960,2731,1237],{"class":1014},[960,2733,2734,2736,2738,2740,2742,2744,2746],{"class":962,"line":1311},[960,2735,1222],{"class":1221},[960,2737,1756],{"class":1225},[960,2739,1228],{"class":1221},[960,2741,1026],{"class":969},[960,2743,1250],{"class":1044},[960,2745,1765],{"class":973},[960,2747,1386],{"class":1044},[960,2749,2750],{"class":962,"line":1331},[960,2751,1392],{"class":1014},[835,2753,1774,2754,1777],{},[838,2755,1357],{},[851,2757],{},[854,2759,1783],{"id":1782},[835,2761,1786,2762,1790],{},[838,2763,1789],{},[862,2765,2766,2774],{},[865,2767,2768],{},[868,2769,2770,2772],{},[871,2771,1799],{},[871,2773,1802],{},[881,2775,2776,2786,2796,2806,2816,2826,2834,2842],{},[868,2777,2778,2782],{},[886,2779,2780],{},[838,2781,1811],{},[886,2783,1814,2784,1818],{},[838,2785,1817],{},[868,2787,2788,2792],{},[886,2789,2790],{},[838,2791,1825],{},[886,2793,1814,2794,1818],{},[838,2795,1830],{},[868,2797,2798,2804],{},[886,2799,2800,1054,2802],{},[838,2801,1057],{},[838,2803,1839],{},[886,2805,1842],{},[868,2807,2808,2814],{},[886,2809,2810,1054,2812],{},[838,2811,1849],{},[838,2813,1852],{},[886,2815,1855],{},[868,2817,2818,2824],{},[886,2819,2820,1054,2822],{},[838,2821,1862],{},[838,2823,1865],{},[886,2825,1868],{},[868,2827,2828,2832],{},[886,2829,2830],{},[838,2831,1875],{},[886,2833,1878],{},[868,2835,2836,2840],{},[886,2837,2838],{},[838,2839,1885],{},[886,2841,1888],{},[868,2843,2844,2848],{},[886,2845,2846],{},[838,2847,1895],{},[886,2849,1898],{},[1900,2851,2852],{},[835,2853,1904,2854,1908],{},[838,2855,1907],{},[851,2857],{},[854,2859,1914],{"id":1913},[835,2861,1917,2862,1920,2864,1924,2866,1927],{},[838,2863,1357],{},[838,2865,1923],{},[838,2867,1357],{},[950,2869,2870],{"className":952,"code":1930,"filename":954,"language":955,"meta":956,"style":956},[838,2871,2872],{"__ignoreMap":956},[960,2873,2874,2876,2878,2880,2882,2884,2886,2888],{"class":962,"line":963},[960,2875,1937],{"class":977},[960,2877,1045],{"class":1044},[960,2879,1942],{"class":973},[960,2881,1051],{"class":1044},[960,2883,1947],{"class":973},[960,2885,1950],{"class":969},[960,2887,1953],{"class":977},[960,2889,1956],{"class":973},[835,2891,1959,2892,1962],{},[838,2893,911],{},[1158,2895,2896],{},[835,2897,1967,2898,1970,2900,1973,2902,1976],{},[838,2899,890],{},[838,2901,1357],{},[838,2903,1204],{},[1978,2905,1980],{},{"title":956,"searchDepth":1018,"depth":1018,"links":2907},[2908,2909,2910,2911,2912,2913],{"id":856,"depth":1018,"text":857},{"id":986,"depth":1018,"text":987},{"id":1179,"depth":1018,"text":1180},{"id":1466,"depth":1018,"text":1467},{"id":1782,"depth":1018,"text":1783},{"id":1913,"depth":1018,"text":1914},{},{"title":99,"description":1989},1780436274842]