[{"data":1,"prerenderedAt":4541},["ShallowReactive",2],{"navLinks":3,"sidebar_docs_navigation_\u002Fdocs\u002Fiam":64,"navigation":257,"navLinks_footer":837,"\u002Fdocs\u002Fiam\u002Fconfiguration_page":850,"\u002Fdocs\u002Fiam\u002Fconfiguration_surround":2969,"\u002Fdocs\u002Fiam\u002Fconfiguration":2972},{"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":27,"path":29,"stem":70,"children":71},"docs\u002Fiam\u002Findex",[72,73,76,216,219,236,240],{"title":27,"path":29,"stem":70},{"title":14,"path":74,"stem":75},"\u002Fdocs\u002Fiam\u002Fgetting-started","docs\u002Fiam\u002F00.getting-started",{"title":77,"path":78,"stem":79,"children":80},"Essentials","\u002Fdocs\u002Fiam\u002Fessentials","docs\u002Fiam\u002F01.essentials\u002Findex",[81,82,86,90,94,98,102,106,110,114,118,122,126,130,134,138,142,146,150,154,158,162,166],{"title":77,"path":78,"stem":79},{"title":83,"path":84,"stem":85},"Tokens","\u002Fdocs\u002Fiam\u002Fessentials\u002Ftokens","docs\u002Fiam\u002F01.essentials\u002F00.tokens",{"title":87,"path":88,"stem":89},"Access Tokens","\u002Fdocs\u002Fiam\u002Fessentials\u002Faccess-tokens","docs\u002Fiam\u002F01.essentials\u002F01.access-tokens",{"title":91,"path":92,"stem":93},"Refresh Tokens","\u002Fdocs\u002Fiam\u002Fessentials\u002Frefresh-tokens","docs\u002Fiam\u002F01.essentials\u002F02.refresh-tokens",{"title":95,"path":96,"stem":97},"Anomaly Detection","\u002Fdocs\u002Fiam\u002Fessentials\u002Fanomalies","docs\u002Fiam\u002F01.essentials\u002F03.anomalies",{"title":99,"path":100,"stem":101},"Signup","\u002Fdocs\u002Fiam\u002Fessentials\u002Fsignup","docs\u002Fiam\u002F01.essentials\u002F04.signup",{"title":103,"path":104,"stem":105},"Login","\u002Fdocs\u002Fiam\u002Fessentials\u002Flogin","docs\u002Fiam\u002F01.essentials\u002F05.login",{"title":107,"path":108,"stem":109},"Logout","\u002Fdocs\u002Fiam\u002Fessentials\u002Flogout","docs\u002Fiam\u002F01.essentials\u002F06.logout",{"title":111,"path":112,"stem":113},"OAuth","\u002Fdocs\u002Fiam\u002Fessentials\u002Foauth","docs\u002Fiam\u002F01.essentials\u002F07.oauth",{"title":115,"path":116,"stem":117},"Magic Links","\u002Fdocs\u002Fiam\u002Fessentials\u002Fmagic-links","docs\u002Fiam\u002F01.essentials\u002F08.magic-links",{"title":119,"path":120,"stem":121},"Emails","\u002Fdocs\u002Fiam\u002Fessentials\u002Femails","docs\u002Fiam\u002F01.essentials\u002F09.emails",{"title":123,"path":124,"stem":125},"MFA","\u002Fdocs\u002Fiam\u002Fessentials\u002Fmfa","docs\u002Fiam\u002F01.essentials\u002F10.mfa",{"title":127,"path":128,"stem":129},"Fingerprinting","\u002Fdocs\u002Fiam\u002Fessentials\u002Ffingerprinting","docs\u002Fiam\u002F01.essentials\u002F11.fingerprinting",{"title":131,"path":132,"stem":133},"Backend for Frontend","\u002Fdocs\u002Fiam\u002Fessentials\u002Fbff","docs\u002Fiam\u002F01.essentials\u002F12.bff",{"title":135,"path":136,"stem":137},"HMAC Authentication","\u002Fdocs\u002Fiam\u002Fessentials\u002Fhmac","docs\u002Fiam\u002F01.essentials\u002F13.hmac",{"title":139,"path":140,"stem":141},"XSS Protection","\u002Fdocs\u002Fiam\u002Fessentials\u002Fxss","docs\u002Fiam\u002F01.essentials\u002F14.xss",{"title":143,"path":144,"stem":145},"Logging","\u002Fdocs\u002Fiam\u002Fessentials\u002Flogging","docs\u002Fiam\u002F01.essentials\u002F15.logging",{"title":147,"path":148,"stem":149},"Rate Limiting","\u002Fdocs\u002Fiam\u002Fessentials\u002Frate-limiting","docs\u002Fiam\u002F01.essentials\u002F16.rate-limiting",{"title":151,"path":152,"stem":153},"Database","\u002Fdocs\u002Fiam\u002Fessentials\u002Fdatabase","docs\u002Fiam\u002F01.essentials\u002F17.database",{"title":155,"path":156,"stem":157},"Cookies","\u002Fdocs\u002Fiam\u002Fessentials\u002Fcookies","docs\u002Fiam\u002F01.essentials\u002F18.cookies",{"title":159,"path":160,"stem":161},"Service Startup","\u002Fdocs\u002Fiam\u002Fessentials\u002Fservice","docs\u002Fiam\u002F01.essentials\u002F19.service",{"title":163,"path":164,"stem":165},"Password Reset","\u002Fdocs\u002Fiam\u002Fessentials\u002Fpassword-reset","docs\u002Fiam\u002F01.essentials\u002F20.password-reset",{"title":167,"path":168,"stem":169,"children":170},"API Tokens","\u002Fdocs\u002Fiam\u002Fessentials\u002Fapi","docs\u002Fiam\u002F01.essentials\u002F21.api\u002Findex",[171,172,176,180,210,213],{"title":167,"path":168,"stem":169},{"title":173,"path":174,"stem":175},"Creating Tokens","\u002Fdocs\u002Fiam\u002Fessentials\u002Fapi\u002Fcreation","docs\u002Fiam\u002F01.essentials\u002F21.api\u002F00.creation",{"title":177,"path":178,"stem":179},"Verifying Tokens","\u002Fdocs\u002Fiam\u002Fessentials\u002Fapi\u002Fverification","docs\u002Fiam\u002F01.essentials\u002F21.api\u002F01.verification",{"title":181,"path":182,"stem":183,"children":184},"Manage Tokens","\u002Fdocs\u002Fiam\u002Fessentials\u002Fapi\u002Fmanagement","docs\u002Fiam\u002F01.essentials\u002F21.api\u002F02.management\u002Findex",[185,186,190,194,198,202,206],{"title":181,"path":182,"stem":183},{"title":187,"path":188,"stem":189},"Privileges","\u002Fdocs\u002Fiam\u002Fessentials\u002Fapi\u002Fmanagement\u002Fprivilege","docs\u002Fiam\u002F01.essentials\u002F21.api\u002F02.management\u002F00.privilege",{"title":191,"path":192,"stem":193},"Revocation","\u002Fdocs\u002Fiam\u002Fessentials\u002Fapi\u002Fmanagement\u002Frevocation","docs\u002Fiam\u002F01.essentials\u002F21.api\u002F02.management\u002F01.revocation",{"title":195,"path":196,"stem":197},"Rotation","\u002Fdocs\u002Fiam\u002Fessentials\u002Fapi\u002Fmanagement\u002Frotation","docs\u002Fiam\u002F01.essentials\u002F21.api\u002F02.management\u002F02.rotation",{"title":199,"path":200,"stem":201},"IP Restriction","\u002Fdocs\u002Fiam\u002Fessentials\u002Fapi\u002Fmanagement\u002Fip-updates","docs\u002Fiam\u002F01.essentials\u002F21.api\u002F02.management\u002F03.ip-updates",{"title":203,"path":204,"stem":205},"Metadata","\u002Fdocs\u002Fiam\u002Fessentials\u002Fapi\u002Fmanagement\u002Fmetadata","docs\u002Fiam\u002F01.essentials\u002F21.api\u002F02.management\u002F04.metadata",{"title":207,"path":208,"stem":209},"Token Listing","\u002Fdocs\u002Fiam\u002Fessentials\u002Fapi\u002Fmanagement\u002Flist","docs\u002Fiam\u002F01.essentials\u002F21.api\u002F02.management\u002F05.list",{"title":147,"path":211,"stem":212},"\u002Fdocs\u002Fiam\u002Fessentials\u002Fapi\u002Frate-limiting","docs\u002Fiam\u002F01.essentials\u002F21.api\u002F03.rate-limiting",{"title":38,"path":214,"stem":215},"\u002Fdocs\u002Fiam\u002Fessentials\u002Fapi\u002Fsecurity","docs\u002Fiam\u002F01.essentials\u002F21.api\u002F04.security",{"title":38,"path":217,"stem":218},"\u002Fdocs\u002Fiam\u002Fsecurity","docs\u002Fiam\u002F02.security",{"title":220,"path":221,"stem":222,"children":223,"page":53},"Guides","\u002Fdocs\u002Fiam\u002Fguides","docs\u002Fiam\u002F03.guides",[224,228,232],{"title":225,"path":226,"stem":227},"Deployment","\u002Fdocs\u002Fiam\u002Fguides\u002Fdeployment","docs\u002Fiam\u002F03.guides\u002Fdeployment",{"title":229,"path":230,"stem":231},"Operation Scripts","\u002Fdocs\u002Fiam\u002Fguides\u002Foperation-scripts","docs\u002Fiam\u002F03.guides\u002Foperation-scripts",{"title":233,"path":234,"stem":235},"Role-Based Access Control","\u002Fdocs\u002Fiam\u002Fguides\u002Frbac","docs\u002Fiam\u002F03.guides\u002Frbac",{"title":237,"path":238,"stem":239},"Configuration","\u002Fdocs\u002Fiam\u002Fconfiguration","docs\u002Fiam\u002F04.configuration",{"title":241,"path":242,"stem":243,"children":244,"page":53},"Api","\u002Fdocs\u002Fiam\u002Fapi","docs\u002Fiam\u002F05.API",[245,249,253],{"title":246,"path":247,"stem":248},"API Reference","\u002Fdocs\u002Fiam\u002Fapi\u002Fapi","docs\u002Fiam\u002F05.API\u002F00.api",{"title":250,"path":251,"stem":252},"Middleware Reference","\u002Fdocs\u002Fiam\u002Fapi\u002Fmiddlewares","docs\u002Fiam\u002F05.API\u002F02.middlewares",{"title":254,"path":255,"stem":256},"Routes Reference","\u002Fdocs\u002Fiam\u002Fapi\u002Froutes","docs\u002Fiam\u002F05.API\u002F03.routes",[258],{"title":9,"path":66,"stem":67,"children":259,"page":53},[260,398,516,521,577,644],{"title":20,"path":22,"stem":261,"children":262},"docs\u002Fauth-h3client\u002Findex",[263,264,273,307,331,353,356,376,379],{"title":20,"path":22,"stem":261},{"title":14,"path":265,"stem":266,"children":267},"\u002Fdocs\u002Fauth-h3client\u002Fgetting-started","docs\u002Fauth-h3client\u002F00.getting-started\u002Findex",[268,269],{"title":14,"path":265,"stem":266},{"title":270,"path":271,"stem":272},"Nuxt Module","\u002Fdocs\u002Fauth-h3client\u002Fgetting-started\u002Fnuxt","docs\u002Fauth-h3client\u002F00.getting-started\u002F00.nuxt",{"title":77,"path":274,"stem":275,"children":276},"\u002Fdocs\u002Fauth-h3client\u002Fessentials","docs\u002Fauth-h3client\u002F01.essentials\u002Findex",[277,278,282,286,290,294,298,301,304],{"title":77,"path":274,"stem":275},{"title":279,"path":280,"stem":281},"Session Management","\u002Fdocs\u002Fauth-h3client\u002Fessentials\u002Fsession","docs\u002Fauth-h3client\u002F01.essentials\u002F00.session",{"title":283,"path":284,"stem":285},"Route Protection","\u002Fdocs\u002Fauth-h3client\u002Fessentials\u002Froute-protection","docs\u002Fauth-h3client\u002F01.essentials\u002F01.route-protection",{"title":287,"path":288,"stem":289},"CSRF Protection","\u002Fdocs\u002Fauth-h3client\u002Fessentials\u002Fcsrf","docs\u002Fauth-h3client\u002F01.essentials\u002F02.csrf",{"title":291,"path":292,"stem":293},"Auth Flows","\u002Fdocs\u002Fauth-h3client\u002Fessentials\u002Fauth-flows","docs\u002Fauth-h3client\u002F01.essentials\u002F03.auth-flows",{"title":295,"path":296,"stem":297},"OAuth and OIDC","\u002Fdocs\u002Fauth-h3client\u002Fessentials\u002Foauth","docs\u002Fauth-h3client\u002F01.essentials\u002F04.oauth",{"title":33,"path":299,"stem":300},"\u002Fdocs\u002Fauth-h3client\u002Fessentials\u002Fbot-detection","docs\u002Fauth-h3client\u002F01.essentials\u002F05.bot-detection",{"title":155,"path":302,"stem":303},"\u002Fdocs\u002Fauth-h3client\u002Fessentials\u002Fcookies","docs\u002Fauth-h3client\u002F01.essentials\u002F06.cookies",{"title":143,"path":305,"stem":306},"\u002Fdocs\u002Fauth-h3client\u002Fessentials\u002Flogging","docs\u002Fauth-h3client\u002F01.essentials\u002F07.logging",{"title":123,"path":308,"stem":309,"children":310},"\u002Fdocs\u002Fauth-h3client\u002Fmfa","docs\u002Fauth-h3client\u002F02.mfa\u002Findex",[311,312,316,319,323,327],{"title":123,"path":308,"stem":309},{"title":313,"path":314,"stem":315},"Built-in MFA","\u002Fdocs\u002Fauth-h3client\u002Fmfa\u002Fbuilt-in-flow","docs\u002Fauth-h3client\u002F02.mfa\u002F01.built-in-flow",{"title":163,"path":317,"stem":318},"\u002Fdocs\u002Fauth-h3client\u002Fmfa\u002Fpassword-reset","docs\u002Fauth-h3client\u002F02.mfa\u002F02.password-reset",{"title":320,"path":321,"stem":322},"Email Change","\u002Fdocs\u002Fauth-h3client\u002Fmfa\u002Femail-change","docs\u002Fauth-h3client\u002F02.mfa\u002F03.email-change",{"title":324,"path":325,"stem":326},"Custom MFA Flow","\u002Fdocs\u002Fauth-h3client\u002Fmfa\u002Fcustom-flow","docs\u002Fauth-h3client\u002F02.mfa\u002F04.custom-flow",{"title":328,"path":329,"stem":330},"Client-Side MFA","\u002Fdocs\u002Fauth-h3client\u002Fmfa\u002Fclient-side","docs\u002Fauth-h3client\u002F02.mfa\u002F05.client-side",{"title":332,"path":333,"stem":334,"children":335},"Client-side","\u002Fdocs\u002Fauth-h3client\u002Fclient","docs\u002Fauth-h3client\u002F03.client\u002Findex",[336,337,341,345,349],{"title":332,"path":333,"stem":334},{"title":338,"path":339,"stem":340},"useAuthData","\u002Fdocs\u002Fauth-h3client\u002Fclient\u002Fuse-auth-data","docs\u002Fauth-h3client\u002F03.client\u002F00.use-auth-data",{"title":342,"path":343,"stem":344},"useMagicLink","\u002Fdocs\u002Fauth-h3client\u002Fclient\u002Fuse-magic-link","docs\u002Fauth-h3client\u002F03.client\u002F01.use-magic-link",{"title":346,"path":347,"stem":348},"executeRequest","\u002Fdocs\u002Fauth-h3client\u002Fclient\u002Fexecute-request","docs\u002Fauth-h3client\u002F03.client\u002F02.execute-request",{"title":350,"path":351,"stem":352},"getCsrfToken","\u002Fdocs\u002Fauth-h3client\u002Fclient\u002Fget-csrf-token","docs\u002Fauth-h3client\u002F03.client\u002F03.get-csrf-token",{"title":38,"path":354,"stem":355},"\u002Fdocs\u002Fauth-h3client\u002Fsecurity","docs\u002Fauth-h3client\u002F04.security",{"title":220,"path":357,"stem":358,"children":359,"page":53},"\u002Fdocs\u002Fauth-h3client\u002Fguides","docs\u002Fauth-h3client\u002F05.guides",[360,364,368,372],{"title":361,"path":362,"stem":363},"H3 and Nitro Setup","\u002Fdocs\u002Fauth-h3client\u002Fguides\u002Fh3-nitro","docs\u002Fauth-h3client\u002F05.guides\u002F00.h3-nitro",{"title":365,"path":366,"stem":367},"HMAC Inter-service Auth","\u002Fdocs\u002Fauth-h3client\u002Fguides\u002Fhmac","docs\u002Fauth-h3client\u002F05.guides\u002Fhmac",{"title":369,"path":370,"stem":371},"Image Upload","\u002Fdocs\u002Fauth-h3client\u002Fguides\u002Fimage-upload","docs\u002Fauth-h3client\u002F05.guides\u002Fimage-upload",{"title":373,"path":374,"stem":375},"mTLS Configuration","\u002Fdocs\u002Fauth-h3client\u002Fguides\u002Fmtls","docs\u002Fauth-h3client\u002F05.guides\u002Fmtls",{"title":237,"path":377,"stem":378},"\u002Fdocs\u002Fauth-h3client\u002Fconfiguration","docs\u002Fauth-h3client\u002F06.configuration",{"title":246,"path":380,"stem":381,"children":382},"\u002Fdocs\u002Fauth-h3client\u002Fapi","docs\u002Fauth-h3client\u002F07.api\u002Findex",[383,384,387,390,394],{"title":246,"path":380,"stem":381},{"title":254,"path":385,"stem":386},"\u002Fdocs\u002Fauth-h3client\u002Fapi\u002Fcontrollers","docs\u002Fauth-h3client\u002F07.api\u002F00.controllers",{"title":250,"path":388,"stem":389},"\u002Fdocs\u002Fauth-h3client\u002Fapi\u002Fmiddleware","docs\u002Fauth-h3client\u002F07.api\u002F01.middleware",{"title":391,"path":392,"stem":393},"Client-side Reference","\u002Fdocs\u002Fauth-h3client\u002Fapi\u002Fcomposables","docs\u002Fauth-h3client\u002F07.api\u002F02.composables",{"title":395,"path":396,"stem":397},"Utilities","\u002Fdocs\u002Fauth-h3client\u002Fapi\u002Futilities","docs\u002Fauth-h3client\u002F07.api\u002F03.utilities",{"title":399,"path":35,"stem":400,"children":401},"Bot Detector","docs\u002Fbot-detection\u002Findex",[402,403,406,410,414,433,507,510,513],{"title":399,"path":35,"stem":400},{"title":14,"path":404,"stem":405},"\u002Fdocs\u002Fbot-detection\u002Fgetting-started","docs\u002Fbot-detection\u002F00.getting-started",{"title":407,"path":408,"stem":409},"CLI","\u002Fdocs\u002Fbot-detection\u002Fcli","docs\u002Fbot-detection\u002F01.cli",{"title":411,"path":412,"stem":413},"Data Sources","\u002Fdocs\u002Fbot-detection\u002Fdata-sources","docs\u002Fbot-detection\u002F02.data-sources",{"title":220,"path":415,"stem":416,"children":417,"page":53},"\u002Fdocs\u002Fbot-detection\u002Fguides","docs\u002Fbot-detection\u002F03.guides",[418,422,426,429],{"title":419,"path":420,"stem":421},"Custom Checkers","\u002Fdocs\u002Fbot-detection\u002Fguides\u002Fcustom","docs\u002Fbot-detection\u002F03.guides\u002FCUSTOM",{"title":423,"path":424,"stem":425},"Scheduling Database Generation","\u002Fdocs\u002Fbot-detection\u002Fguides\u002Fgenerate","docs\u002Fbot-detection\u002F03.guides\u002FGENERATE",{"title":143,"path":427,"stem":428},"\u002Fdocs\u002Fbot-detection\u002Fguides\u002Flogging","docs\u002Fbot-detection\u002F03.guides\u002FLOGGING",{"title":430,"path":431,"stem":432},"Score Modes and Reputation Healing","\u002Fdocs\u002Fbot-detection\u002Fguides\u002Fscore","docs\u002Fbot-detection\u002F03.guides\u002FSCORE",{"title":434,"path":435,"stem":436,"children":437},"Checkers","\u002Fdocs\u002Fbot-detection\u002Fcheckers","docs\u002Fbot-detection\u002F04.checkers\u002Findex",[438,439,443,447,451,455,459,463,467,471,475,479,483,487,491,495,499,503],{"title":434,"path":435,"stem":436},{"title":440,"path":441,"stem":442},"IP Validation","\u002Fdocs\u002Fbot-detection\u002Fcheckers\u002Fip-validation","docs\u002Fbot-detection\u002F04.checkers\u002F01.ip-validation",{"title":444,"path":445,"stem":446},"Good \u002F Bad Bot Verification","\u002Fdocs\u002Fbot-detection\u002Fcheckers\u002Fgood-bots","docs\u002Fbot-detection\u002F04.checkers\u002F02.good-bots",{"title":448,"path":449,"stem":450},"Browser & Device Fingerprint","\u002Fdocs\u002Fbot-detection\u002Fcheckers\u002Fbrowser-device","docs\u002Fbot-detection\u002F04.checkers\u002F03.browser-device",{"title":452,"path":453,"stem":454},"Locale Map","\u002Fdocs\u002Fbot-detection\u002Fcheckers\u002Flocale-map","docs\u002Fbot-detection\u002F04.checkers\u002F04.locale-map",{"title":456,"path":457,"stem":458},"Known Threats","\u002Fdocs\u002Fbot-detection\u002Fcheckers\u002Fknown-threats","docs\u002Fbot-detection\u002F04.checkers\u002F05.known-threats",{"title":460,"path":461,"stem":462},"ASN Classification","\u002Fdocs\u002Fbot-detection\u002Fcheckers\u002Fasn-classification","docs\u002Fbot-detection\u002F04.checkers\u002F06.asn-classification",{"title":464,"path":465,"stem":466},"Tor Analysis","\u002Fdocs\u002Fbot-detection\u002Fcheckers\u002Ftor-analysis","docs\u002Fbot-detection\u002F04.checkers\u002F07.tor-analysis",{"title":468,"path":469,"stem":470},"Timezone Consistency","\u002Fdocs\u002Fbot-detection\u002Fcheckers\u002Ftimezone-consistency","docs\u002Fbot-detection\u002F04.checkers\u002F08.timezone-consistency",{"title":472,"path":473,"stem":474},"Honeypot","\u002Fdocs\u002Fbot-detection\u002Fcheckers\u002Fhoneypot","docs\u002Fbot-detection\u002F04.checkers\u002F09.honeypot",{"title":476,"path":477,"stem":478},"Known Bad IPs","\u002Fdocs\u002Fbot-detection\u002Fcheckers\u002Fknown-bad-ips","docs\u002Fbot-detection\u002F04.checkers\u002F10.known-bad-ips",{"title":480,"path":481,"stem":482},"Behavior Rate","\u002Fdocs\u002Fbot-detection\u002Fcheckers\u002Fbehavior-rate","docs\u002Fbot-detection\u002F04.checkers\u002F11.behavior-rate",{"title":484,"path":485,"stem":486},"Proxy \u002F ISP \u002F Cookie","\u002Fdocs\u002Fbot-detection\u002Fcheckers\u002Fproxy-isp-cookies","docs\u002Fbot-detection\u002F04.checkers\u002F12.proxy-isp-cookies",{"title":488,"path":489,"stem":490},"Session Coherence","\u002Fdocs\u002Fbot-detection\u002Fcheckers\u002Fsession-coherence","docs\u002Fbot-detection\u002F04.checkers\u002F13.session-coherence",{"title":492,"path":493,"stem":494},"Velocity Fingerprint","\u002Fdocs\u002Fbot-detection\u002Fcheckers\u002Fvelocity-fingerprint","docs\u002Fbot-detection\u002F04.checkers\u002F14.velocity-fingerprint",{"title":496,"path":497,"stem":498},"UA & Header Analysis","\u002Fdocs\u002Fbot-detection\u002Fcheckers\u002Fua-header","docs\u002Fbot-detection\u002F04.checkers\u002F15.ua-header",{"title":500,"path":501,"stem":502},"Geolocation","\u002Fdocs\u002Fbot-detection\u002Fcheckers\u002Fgeolocation","docs\u002Fbot-detection\u002F04.checkers\u002F16.geolocation",{"title":504,"path":505,"stem":506},"Known Bad User-Agents","\u002Fdocs\u002Fbot-detection\u002Fcheckers\u002Fknown-bad-ua","docs\u002Fbot-detection\u002F04.checkers\u002F17.known-bad-ua",{"title":38,"path":508,"stem":509},"\u002Fdocs\u002Fbot-detection\u002Fsecurity","docs\u002Fbot-detection\u002F04.security",{"title":246,"path":511,"stem":512},"\u002Fdocs\u002Fbot-detection\u002Fapi","docs\u002Fbot-detection\u002F05.api",{"title":237,"path":514,"stem":515},"\u002Fdocs\u002Fbot-detection\u002Fconfiguration","docs\u002Fbot-detection\u002F06.configuration",{"title":517,"path":11,"stem":518,"children":519},"Introduction","docs\u002Fgetting-started\u002Findex",[520],{"title":517,"path":11,"stem":518},{"title":27,"path":29,"stem":70,"children":522},[523,524,525,565,566,571,572],{"title":27,"path":29,"stem":70},{"title":14,"path":74,"stem":75},{"title":77,"path":78,"stem":79,"children":526},[527,528,529,530,531,532,533,534,535,536,537,538,539,540,541,542,543,544,545,546,547,548,549],{"title":77,"path":78,"stem":79},{"title":83,"path":84,"stem":85},{"title":87,"path":88,"stem":89},{"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},{"title":111,"path":112,"stem":113},{"title":115,"path":116,"stem":117},{"title":119,"path":120,"stem":121},{"title":123,"path":124,"stem":125},{"title":127,"path":128,"stem":129},{"title":131,"path":132,"stem":133},{"title":135,"path":136,"stem":137},{"title":139,"path":140,"stem":141},{"title":143,"path":144,"stem":145},{"title":147,"path":148,"stem":149},{"title":151,"path":152,"stem":153},{"title":155,"path":156,"stem":157},{"title":159,"path":160,"stem":161},{"title":163,"path":164,"stem":165},{"title":167,"path":168,"stem":169,"children":550},[551,552,553,554,563,564],{"title":167,"path":168,"stem":169},{"title":173,"path":174,"stem":175},{"title":177,"path":178,"stem":179},{"title":181,"path":182,"stem":183,"children":555},[556,557,558,559,560,561,562],{"title":181,"path":182,"stem":183},{"title":187,"path":188,"stem":189},{"title":191,"path":192,"stem":193},{"title":195,"path":196,"stem":197},{"title":199,"path":200,"stem":201},{"title":203,"path":204,"stem":205},{"title":207,"path":208,"stem":209},{"title":147,"path":211,"stem":212},{"title":38,"path":214,"stem":215},{"title":38,"path":217,"stem":218},{"title":220,"path":221,"stem":222,"children":567,"page":53},[568,569,570],{"title":225,"path":226,"stem":227},{"title":229,"path":230,"stem":231},{"title":233,"path":234,"stem":235},{"title":237,"path":238,"stem":239},{"title":241,"path":242,"stem":243,"children":573,"page":53},[574,575,576],{"title":246,"path":247,"stem":248},{"title":250,"path":251,"stem":252},{"title":254,"path":255,"stem":256},{"title":40,"path":42,"stem":578,"children":579},"docs\u002Fshield-base\u002Findex",[580,581,584,588,629,633,637,641],{"title":40,"path":42,"stem":578},{"title":14,"path":582,"stem":583},"\u002Fdocs\u002Fshield-base\u002Fgetting-started","docs\u002Fshield-base\u002F00.getting-started",{"title":585,"path":586,"stem":587},"CLI Reference","\u002Fdocs\u002Fshield-base\u002Fcli","docs\u002Fshield-base\u002F01.cli",{"title":411,"path":589,"stem":590,"children":591},"\u002Fdocs\u002Fshield-base\u002Fdata-sources","docs\u002Fshield-base\u002F02.data-sources\u002Findex",[592,593,597,601,605,609,613,617,621,625],{"title":411,"path":589,"stem":590},{"title":594,"path":595,"stem":596},"BGP \u002F ASN","\u002Fdocs\u002Fshield-base\u002Fdata-sources\u002Fbgp","docs\u002Fshield-base\u002F02.data-sources\u002Fbgp",{"title":598,"path":599,"stem":600},"City Geolocation","\u002Fdocs\u002Fshield-base\u002Fdata-sources\u002Fcity","docs\u002Fshield-base\u002F02.data-sources\u002Fcity",{"title":602,"path":603,"stem":604},"Country Geolocation","\u002Fdocs\u002Fshield-base\u002Fdata-sources\u002Fcountry","docs\u002Fshield-base\u002F02.data-sources\u002Fcountry",{"title":606,"path":607,"stem":608},"Verified Crawlers","\u002Fdocs\u002Fshield-base\u002Fdata-sources\u002Fcrawlers","docs\u002Fshield-base\u002F02.data-sources\u002Fcrawlers",{"title":610,"path":611,"stem":612},"Disposable Emails","\u002Fdocs\u002Fshield-base\u002Fdata-sources\u002Femail","docs\u002Fshield-base\u002F02.data-sources\u002Femail",{"title":614,"path":615,"stem":616},"FireHOL Threat Intelligence","\u002Fdocs\u002Fshield-base\u002Fdata-sources\u002Ffirehol","docs\u002Fshield-base\u002F02.data-sources\u002Ffirehol",{"title":618,"path":619,"stem":620},"Proxy Detection","\u002Fdocs\u002Fshield-base\u002Fdata-sources\u002Fproxy","docs\u002Fshield-base\u002F02.data-sources\u002Fproxy",{"title":622,"path":623,"stem":624},"Tor Nodes","\u002Fdocs\u002Fshield-base\u002Fdata-sources\u002Ftor","docs\u002Fshield-base\u002F02.data-sources\u002Ftor",{"title":626,"path":627,"stem":628},"Suspicious User-Agents","\u002Fdocs\u002Fshield-base\u002Fdata-sources\u002Fuseragent","docs\u002Fshield-base\u002F02.data-sources\u002Fuseragent",{"title":630,"path":631,"stem":632},"Programmatic Usage","\u002Fdocs\u002Fshield-base\u002Fusage","docs\u002Fshield-base\u002F03.usage",{"title":634,"path":635,"stem":636},"Custom Data Sources","\u002Fdocs\u002Fshield-base\u002Fcustom-data-sources","docs\u002Fshield-base\u002F04.custom-data-sources",{"title":638,"path":639,"stem":640},"TypeScript Types","\u002Fdocs\u002Fshield-base\u002Ftypes","docs\u002Fshield-base\u002F05.types",{"title":246,"path":642,"stem":643},"\u002Fdocs\u002Fshield-base\u002Fapi","docs\u002Fshield-base\u002F06.api",{"title":395,"path":48,"stem":645,"children":646},"docs\u002Futils\u002Findex",[647,648,665,698,795],{"title":395,"path":48,"stem":645},{"title":649,"path":650,"stem":651,"children":652,"page":53},"Eslint","\u002Fdocs\u002Futils\u002Feslint","docs\u002Futils\u002Feslint",[653,657,661],{"title":654,"path":655,"stem":656},"React Config","\u002Fdocs\u002Futils\u002Feslint\u002Freact","docs\u002Futils\u002Feslint\u002Freact",{"title":658,"path":659,"stem":660},"TypeScript Config","\u002Fdocs\u002Futils\u002Feslint\u002Ftypescript","docs\u002Futils\u002Feslint\u002Ftypescript",{"title":662,"path":663,"stem":664},"Vue Config","\u002Fdocs\u002Futils\u002Feslint\u002Fvue","docs\u002Futils\u002Feslint\u002Fvue",{"title":666,"path":667,"stem":668,"children":669,"page":53},"Server","\u002Fdocs\u002Futils\u002Fserver","docs\u002Futils\u002Fserver",[670,674,678,682,686,690,694],{"title":671,"path":672,"stem":673},"Encryption","\u002Fdocs\u002Futils\u002Fserver\u002Fencryption","docs\u002Futils\u002Fserver\u002Fencryption",{"title":675,"path":676,"stem":677},"Path Resolver","\u002Fdocs\u002Futils\u002Fserver\u002Fpathresolver","docs\u002Futils\u002Fserver\u002FpathResolver",{"title":679,"path":680,"stem":681},"File Replacements","\u002Fdocs\u002Futils\u002Fserver\u002Freplace","docs\u002Futils\u002Fserver\u002Freplace",{"title":683,"path":684,"stem":685},"run","\u002Fdocs\u002Futils\u002Fserver\u002Frun","docs\u002Futils\u002Fserver\u002Frun",{"title":687,"path":688,"stem":689},"scheduleTask","\u002Fdocs\u002Futils\u002Fserver\u002Fscheduletask","docs\u002Futils\u002Fserver\u002FscheduleTask",{"title":691,"path":692,"stem":693},"spawnRun","\u002Fdocs\u002Futils\u002Fserver\u002Fspawnrun","docs\u002Futils\u002Fserver\u002FspawnRun",{"title":695,"path":696,"stem":697},"uploadCsv","\u002Fdocs\u002Futils\u002Fserver\u002Fuploadcsv","docs\u002Futils\u002Fserver\u002FuploadCsv",{"title":699,"path":700,"stem":701,"children":702,"page":53},"Shared","\u002Fdocs\u002Futils\u002Fshared","docs\u002Futils\u002Fshared",[703,707,711,715,719,723,727,731,735,739,743,747,751,755,759,763,767,771,775,779,783,787,791],{"title":704,"path":705,"stem":706},"BatchQueue","\u002Fdocs\u002Futils\u002Fshared\u002Fbatchqueue","docs\u002Futils\u002Fshared\u002FbatchQueue",{"title":708,"path":709,"stem":710},"capitalize","\u002Fdocs\u002Futils\u002Fshared\u002Fcapitalize","docs\u002Futils\u002Fshared\u002Fcapitalize",{"title":712,"path":713,"stem":714},"chunkProcess","\u002Fdocs\u002Futils\u002Fshared\u002Fchunkprocess","docs\u002Futils\u002Fshared\u002FchunkProcess",{"title":716,"path":717,"stem":718},"cleanObject","\u002Fdocs\u002Futils\u002Fshared\u002Fcleanobject","docs\u002Futils\u002Fshared\u002FcleanObject",{"title":720,"path":721,"stem":722},"createConfigManager","\u002Fdocs\u002Futils\u002Fshared\u002Fconfigurationdefiner","docs\u002Futils\u002Fshared\u002FconfigurationDefiner",{"title":724,"path":725,"stem":726},"debounce","\u002Fdocs\u002Futils\u002Fshared\u002Fdebounce","docs\u002Futils\u002Fshared\u002Fdebounce",{"title":728,"path":729,"stem":730},"ensureArray","\u002Fdocs\u002Futils\u002Fshared\u002Fensurearray","docs\u002Futils\u002Fshared\u002FensureArray",{"title":732,"path":733,"stem":734},"fetchWithRetry","\u002Fdocs\u002Futils\u002Fshared\u002Ffetchwithretry","docs\u002Futils\u002Fshared\u002FfetchWithRetry",{"title":736,"path":737,"stem":738},"filterEmptyValues","\u002Fdocs\u002Futils\u002Fshared\u002Ffilteremptyvalues","docs\u002Futils\u002Fshared\u002FfilterEmptyValues",{"title":740,"path":741,"stem":742},"findStringsInObject","\u002Fdocs\u002Futils\u002Fshared\u002Ffindobjectvalues","docs\u002Futils\u002Fshared\u002FfindObjectValues",{"title":744,"path":745,"stem":746},"fisherYatesShuffle","\u002Fdocs\u002Futils\u002Fshared\u002Ffisheryatesshuffle","docs\u002Futils\u002Fshared\u002FfisherYatesShuffle",{"title":748,"path":749,"stem":750},"getRandomImage","\u002Fdocs\u002Futils\u002Fshared\u002Fgetrandomimage","docs\u002Futils\u002Fshared\u002FgetRandomImage",{"title":752,"path":753,"stem":754},"isObjectHasValues","\u002Fdocs\u002Futils\u002Fshared\u002Fisobjecthasvalues","docs\u002Futils\u002Fshared\u002FisObjectHasValues",{"title":756,"path":757,"stem":758},"isAsyncOrPromise","\u002Fdocs\u002Futils\u002Fshared\u002Fispromise","docs\u002Futils\u002Fshared\u002FisPromise",{"title":760,"path":761,"stem":762},"MiniCache","\u002Fdocs\u002Futils\u002Fshared\u002Fminicache","docs\u002Futils\u002Fshared\u002FminiCache",{"title":764,"path":765,"stem":766},"parseCookies","\u002Fdocs\u002Futils\u002Fshared\u002Fparserawcookies","docs\u002Futils\u002Fshared\u002FparseRawCookies",{"title":768,"path":769,"stem":770},"safeAction","\u002Fdocs\u002Futils\u002Fshared\u002Fpromiselocker","docs\u002Futils\u002Fshared\u002FpromiseLocker",{"title":772,"path":773,"stem":774},"Random","\u002Fdocs\u002Futils\u002Fshared\u002Frandom","docs\u002Futils\u002Fshared\u002Frandom",{"title":776,"path":777,"stem":778},"range","\u002Fdocs\u002Futils\u002Fshared\u002Frange","docs\u002Futils\u002Fshared\u002Frange",{"title":780,"path":781,"stem":782},"rateLimiters","\u002Fdocs\u002Futils\u002Fshared\u002Fratelimiters","docs\u002Futils\u002Fshared\u002FrateLimiters",{"title":784,"path":785,"stem":786},"safeObjectMerge","\u002Fdocs\u002Futils\u002Fshared\u002Fsafemerge","docs\u002Futils\u002Fshared\u002FsafeMerge",{"title":788,"path":789,"stem":790},"textTruncation","\u002Fdocs\u002Futils\u002Fshared\u002Ftexttruncation","docs\u002Futils\u002Fshared\u002FtextTruncation",{"title":792,"path":793,"stem":794},"validateZodSchema","\u002Fdocs\u002Futils\u002Fshared\u002Fvalidatezodschema","docs\u002Futils\u002Fshared\u002FvalidateZodSchema",{"title":796,"path":797,"stem":798,"children":799},"Utility Types","\u002Fdocs\u002Futils\u002Ftypes","docs\u002Futils\u002Ftypes\u002Findex",[800,801,805,809,813,817,821,825,829,833],{"title":796,"path":797,"stem":798},{"title":802,"path":803,"stem":804},"Brand","\u002Fdocs\u002Futils\u002Ftypes\u002Fbrand","docs\u002Futils\u002Ftypes\u002FBrand",{"title":806,"path":807,"stem":808},"DeepPartial","\u002Fdocs\u002Futils\u002Ftypes\u002Fdeeppartial","docs\u002Futils\u002Ftypes\u002FDeepPartial",{"title":810,"path":811,"stem":812},"Merge","\u002Fdocs\u002Futils\u002Ftypes\u002Fmerge","docs\u002Futils\u002Ftypes\u002FMerge",{"title":814,"path":815,"stem":816},"NonNullable","\u002Fdocs\u002Futils\u002Ftypes\u002Fnonnullable","docs\u002Futils\u002Ftypes\u002FNonNullable",{"title":818,"path":819,"stem":820},"Prettify","\u002Fdocs\u002Futils\u002Ftypes\u002Fprettify","docs\u002Futils\u002Ftypes\u002FPrettify",{"title":822,"path":823,"stem":824},"PromiseType","\u002Fdocs\u002Futils\u002Ftypes\u002Fpromisetype","docs\u002Futils\u002Ftypes\u002FPromiseType",{"title":826,"path":827,"stem":828},"RequireKeys","\u002Fdocs\u002Futils\u002Ftypes\u002Frequirekeys","docs\u002Futils\u002Ftypes\u002FRequireKeys",{"title":830,"path":831,"stem":832},"StandardResponse","\u002Fdocs\u002Futils\u002Ftypes\u002Fstandardresponse","docs\u002Futils\u002Ftypes\u002FStandardResponse",{"title":834,"path":835,"stem":836},"ValueOf","\u002Fdocs\u002Futils\u002Ftypes\u002Fvalueof","docs\u002Futils\u002Ftypes\u002FValueOf",{"id":4,"extension":5,"links":838,"meta":849,"stem":62,"__hash__":63},[839,847,848],{"nested":8,"label":9,"icon":10,"to":11,"children":840},[841,842,843,844,845,846],{"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":851,"title":237,"body":852,"description":2961,"extension":2962,"icon":2963,"meta":2964,"module":2965,"navigation":8,"path":238,"rawbody":2966,"seo":2967,"stem":239,"__hash__":2968},"docs\u002Fdocs\u002Fiam\u002F04.configuration.md",{"type":853,"value":854,"toc":2928},"minimark",[855,872,1122,1131,1134,1140,1152,1171,1185,1306,1312,1314,1319,1322,1362,1386,1417,1419,1424,1430,1465,1473,1475,1481,1489,1525,1605,1610,1619,1665,1668,1670,1676,1682,1699,1701,1706,1715,1793,1797,1800,1821,1838,1855,1860,1863,1890,1896,1900,1906,1933,1938,1941,1976,1978,1983,1986,1989,1995,2127,2133,2257,2310,2317,2319,2325,2335,2337,2342,2345,2364,2368,2465,2469,2504,2509,2511,2515,2518,2544,2546,2551,2554,2589,2595,2601,2611,2626,2628,2634,2639,2663,2665,2671,2676,2702,2704,2710,2715,2747,2749,2755,2758,2777,2779,2785,2796,2828,2830,2836,2841,2862,2864,2870,2873,2899,2901,2906,2924],[856,857,858,859,863,864,871],"p",{},"The IAM service is initialized by calling ",[860,861,862],"code",{},"configuration()"," with a single typed object. The schema is validated at startup with ",[865,866,870],"a",{"href":867,"rel":868},"https:\u002F\u002Fzod.dev\u002F",[869],"nofollow","Zod"," and any missing or invalid field throws immediately, preventing the service from starting with a broken config.",[873,874,880],"pre",{"className":875,"code":876,"filename":877,"language":878,"meta":879,"style":879},"language-ts shiki shiki-themes light-plus light-plus dracula","import { configuration } from '@riavzon\u002Fauth'\n\nawait configuration({\n  store: { \u002F* ... *\u002F },\n  password: { pepper: process.env.PEPPER! },\n  botDetector: { enableBotDetector: true },\n  htmlSanitizer: { IrritationCount: 50, maxAllowedInputLength: 50000 },\n  magic_links: { \u002F* ... *\u002F },\n  jwt: { \u002F* ... *\u002F },\n  email: { resend_key: process.env.RESEND_KEY!, email: 'no-reply@example.com' },\n})\n","server.ts","ts","",[860,881,882,916,922,935,954,990,1011,1043,1057,1071,1116],{"__ignoreMap":879},[883,884,887,891,895,899,902,905,909,913],"span",{"class":885,"line":886},"line",1,[883,888,890],{"class":889},"sZ328","import",[883,892,894],{"class":893},"sDd4n"," { ",[883,896,898],{"class":897},"sjsA6","configuration",[883,900,901],{"class":893}," } ",[883,903,904],{"class":889},"from",[883,906,908],{"class":907},"sFkSl"," '",[883,910,912],{"class":911},"sFB1V","@riavzon\u002Fauth",[883,914,915],{"class":907},"'\n",[883,917,919],{"class":885,"line":918},2,[883,920,921],{"emptyLinePlaceholder":8},"\n",[883,923,925,928,932],{"class":885,"line":924},3,[883,926,927],{"class":889},"await",[883,929,931],{"class":930},"sHOzp"," configuration",[883,933,934],{"class":893},"({\n",[883,936,938,941,945,947,951],{"class":885,"line":937},4,[883,939,940],{"class":897},"  store",[883,942,944],{"class":943},"s34zl",":",[883,946,894],{"class":893},[883,948,950],{"class":949},"sghk6","\u002F* ... *\u002F",[883,952,953],{"class":893}," },\n",[883,955,957,960,962,964,967,969,972,975,978,980,984,988],{"class":885,"line":956},5,[883,958,959],{"class":897},"  password",[883,961,944],{"class":943},[883,963,894],{"class":893},[883,965,966],{"class":897},"pepper",[883,968,944],{"class":943},[883,970,971],{"class":897}," process",[883,973,974],{"class":893},".",[883,976,977],{"class":897},"env",[883,979,974],{"class":893},[883,981,983],{"class":982},"sPzPf","PEPPER",[883,985,987],{"class":986},"saOXh","!",[883,989,953],{"class":893},[883,991,993,996,998,1000,1003,1005,1009],{"class":885,"line":992},6,[883,994,995],{"class":897},"  botDetector",[883,997,944],{"class":943},[883,999,894],{"class":893},[883,1001,1002],{"class":897},"enableBotDetector",[883,1004,944],{"class":943},[883,1006,1008],{"class":1007},"sjR7W"," true",[883,1010,953],{"class":893},[883,1012,1014,1017,1019,1021,1024,1026,1030,1033,1036,1038,1041],{"class":885,"line":1013},7,[883,1015,1016],{"class":897},"  htmlSanitizer",[883,1018,944],{"class":943},[883,1020,894],{"class":893},[883,1022,1023],{"class":897},"IrritationCount",[883,1025,944],{"class":943},[883,1027,1029],{"class":1028},"spgvN"," 50",[883,1031,1032],{"class":893},", ",[883,1034,1035],{"class":897},"maxAllowedInputLength",[883,1037,944],{"class":943},[883,1039,1040],{"class":1028}," 50000",[883,1042,953],{"class":893},[883,1044,1046,1049,1051,1053,1055],{"class":885,"line":1045},8,[883,1047,1048],{"class":897},"  magic_links",[883,1050,944],{"class":943},[883,1052,894],{"class":893},[883,1054,950],{"class":949},[883,1056,953],{"class":893},[883,1058,1060,1063,1065,1067,1069],{"class":885,"line":1059},9,[883,1061,1062],{"class":897},"  jwt",[883,1064,944],{"class":943},[883,1066,894],{"class":893},[883,1068,950],{"class":949},[883,1070,953],{"class":893},[883,1072,1074,1077,1079,1081,1084,1086,1088,1090,1092,1094,1097,1099,1101,1104,1106,1108,1111,1114],{"class":885,"line":1073},10,[883,1075,1076],{"class":897},"  email",[883,1078,944],{"class":943},[883,1080,894],{"class":893},[883,1082,1083],{"class":897},"resend_key",[883,1085,944],{"class":943},[883,1087,971],{"class":897},[883,1089,974],{"class":893},[883,1091,977],{"class":897},[883,1093,974],{"class":893},[883,1095,1096],{"class":982},"RESEND_KEY",[883,1098,987],{"class":986},[883,1100,1032],{"class":893},[883,1102,1103],{"class":897},"email",[883,1105,944],{"class":943},[883,1107,908],{"class":907},[883,1109,1110],{"class":911},"no-reply@example.com",[883,1112,1113],{"class":907},"'",[883,1115,953],{"class":893},[883,1117,1119],{"class":885,"line":1118},11,[883,1120,1121],{"class":893},"})\n",[1123,1124,1125],"warning",{},[856,1126,1127,1128,1130],{},"Call ",[860,1129,862],{}," once before mounting any routes. The service reads the resolved config on every request: calling it more than once replaces the previous config globally.",[1132,1133],"hr",{},[1135,1136,1138],"h2",{"id":1137},"store",[860,1139,1137],{},[856,1141,1142,1143,1151],{},"Database connection pools for the main application database and the rate-limiter store. Both pools accept any valid ",[865,1144,1147,1148],{"href":1145,"rel":1146},"https:\u002F\u002Fsidorares.github.io\u002Fnode-mysql2\u002Fdocs",[869],"mysql2 ",[860,1149,1150],{},"PoolOptions"," object.",[1153,1154,1155,1164],"field-group",{},[1156,1157,1161],"field",{"name":1158,"type":1159,":required":1160},"main","mysql.PoolOptions","true",[856,1162,1163],{},"Primary MySQL connection pool used for visitor persistence, token storage, user accounts, and all core queries.",[1156,1165,1168],{"name":1166,"type":1167,":required":1160},"rate_limiters_pool","object",[856,1169,1170],{},"Connection pool dedicated to the rate-limiter tables. Keeping rate-limiter state in a separate database prevents lock contention with the main application pool under heavy load.",[1153,1172,1173,1178],{"name":1166},[1156,1174,1175],{"name":1137,"type":1159,":required":1160},[856,1176,1177],{},"MySQL connection options for the rate-limiter database.",[1156,1179,1182],{"name":1180,"type":1181,":required":1160},"dbName","string",[856,1183,1184],{},"Database name for the limiter tables. Must match the database created for rate-limiter state.",[873,1186,1188],{"className":875,"code":1187,"filename":877,"language":878,"meta":879,"style":879},"store: {\n  main: { host: 'localhost', user: 'root', password: 'secret', database: 'auth' },\n  rate_limiters_pool: {\n    store: { host: 'localhost', user: 'root', password: 'secret', database: 'auth_limiters' },\n    dbName: 'auth_limiters',\n  },\n}\n",[860,1189,1190,1195,1239,1244,1282,1296,1301],{"__ignoreMap":879},[883,1191,1192],{"class":885,"line":886},[883,1193,1194],{"class":893},"store: {\n",[883,1196,1197,1200,1202,1205,1207,1210,1212,1215,1217,1220,1222,1225,1227,1230,1232,1235,1237],{"class":885,"line":918},[883,1198,1199],{"class":893},"  main: { host: ",[883,1201,1113],{"class":907},[883,1203,1204],{"class":911},"localhost",[883,1206,1113],{"class":907},[883,1208,1209],{"class":893},", user: ",[883,1211,1113],{"class":907},[883,1213,1214],{"class":911},"root",[883,1216,1113],{"class":907},[883,1218,1219],{"class":893},", password: ",[883,1221,1113],{"class":907},[883,1223,1224],{"class":911},"secret",[883,1226,1113],{"class":907},[883,1228,1229],{"class":893},", database: ",[883,1231,1113],{"class":907},[883,1233,1234],{"class":911},"auth",[883,1236,1113],{"class":907},[883,1238,953],{"class":893},[883,1240,1241],{"class":885,"line":924},[883,1242,1243],{"class":893},"  rate_limiters_pool: {\n",[883,1245,1246,1249,1251,1253,1255,1257,1259,1261,1263,1265,1267,1269,1271,1273,1275,1278,1280],{"class":885,"line":937},[883,1247,1248],{"class":893},"    store: { host: ",[883,1250,1113],{"class":907},[883,1252,1204],{"class":911},[883,1254,1113],{"class":907},[883,1256,1209],{"class":893},[883,1258,1113],{"class":907},[883,1260,1214],{"class":911},[883,1262,1113],{"class":907},[883,1264,1219],{"class":893},[883,1266,1113],{"class":907},[883,1268,1224],{"class":911},[883,1270,1113],{"class":907},[883,1272,1229],{"class":893},[883,1274,1113],{"class":907},[883,1276,1277],{"class":911},"auth_limiters",[883,1279,1113],{"class":907},[883,1281,953],{"class":893},[883,1283,1284,1287,1289,1291,1293],{"class":885,"line":956},[883,1285,1286],{"class":893},"    dbName: ",[883,1288,1113],{"class":907},[883,1290,1277],{"class":911},[883,1292,1113],{"class":907},[883,1294,1295],{"class":893},",\n",[883,1297,1298],{"class":885,"line":992},[883,1299,1300],{"class":893},"  },\n",[883,1302,1303],{"class":885,"line":1013},[883,1304,1305],{"class":893},"}\n",[1307,1308,1309],"tip",{},[856,1310,1311],{},"You can point both pools at the same MySQL server with different database names, or use separate servers for isolation.",[1132,1313],{},[1135,1315,1317],{"id":1316},"service",[860,1318,1316],{},[856,1320,1321],{},"Runtime service settings for proxy trust, port binding, and optional HMAC inter-service authentication. This entire section is optional.",[1153,1323,1324,1334,1343,1350,1356],{},[1156,1325,1327],{"name":1326,"type":1167},"Hmac",[856,1328,1329,1330,1333],{},"When present, enables HMAC request signing and verification for inter-service calls. See the ",[865,1331,1332],{"href":136},"HMAC guide"," for full details.",[1156,1335,1337],{"name":1336,"type":1167,":required":1160},"proxy",[856,1338,1339,1340,1342],{},"Proxy and IP extraction settings. Required when ",[860,1341,1316],{}," is provided.",[1156,1344,1347],{"name":1345,"type":1346},"port","number",[856,1348,1349],{},"Port the service listens on when running in standalone mode.",[1156,1351,1353],{"name":1352,"type":1181},"ipAddress",[856,1354,1355],{},"IP address to bind when running in standalone mode.",[1156,1357,1359],{"name":1358,"type":1181},"clientIp",[856,1360,1361],{},"Override for client IP extraction. Use this when your reverse proxy sets a non-standard header for the real client IP.",[1153,1363,1364,1370,1376],{"name":1326},[1156,1365,1367],{"name":1366,"type":1181,":required":1160},"sharedSecret",[856,1368,1369],{},"Shared secret used to sign and verify HMAC request signatures. Must match between all communicating services.",[1156,1371,1373],{"name":1372,"type":1181,":required":1160},"clientId",[856,1374,1375],{},"Client identifier sent with every HMAC-signed request. The receiving service uses this to look up the correct shared secret.",[1156,1377,1379],{"name":1378,"type":1346,":required":1160},"maxClockSkew",[856,1380,1381,1382,1385],{},"Maximum allowed clock skew in milliseconds between the signing and verifying services. Defaults to ",[860,1383,1384],{},"300000"," (5 minutes). Requests with a timestamp outside this window are rejected.",[1153,1387,1388,1402,1411],{"name":1336},[1156,1389,1392],{"name":1390,"type":1391,":required":1160},"trust","boolean",[856,1393,1394,1395,1398,1399,1401],{},"Whether to trust ",[860,1396,1397],{},"X-Forwarded-*"," headers from the upstream proxy. Set to ",[860,1400,1160],{}," when running behind a reverse proxy such as Nginx or Caddy.",[1156,1403,1405],{"name":1404,"type":1181,":required":1160},"ipToTrust",[856,1406,1407,1408,1410],{},"Specific proxy IP address to trust. Only ",[860,1409,1397],{}," headers from this IP are accepted.",[1156,1412,1414],{"name":1413,"type":1181},"server",[856,1415,1416],{},"Optional upstream server identifier for logging and diagnostics.",[1132,1418],{},[1135,1420,1422],{"id":1421},"password",[860,1423,1421],{},[856,1425,1426,1427,1429],{},"Controls Argon2id password hashing parameters. The ",[860,1428,966],{}," value is combined with the user's password before hashing: rotate it to invalidate all existing hashes.",[1153,1431,1432,1437,1447,1456],{},[1156,1433,1434],{"name":966,"type":1181,":required":1160},[856,1435,1436],{},"Secret added to every password before hashing. Store this in an environment variable or a secrets manager. Never commit it to version control.",[1156,1438,1440],{"name":1439,"type":1346},"hashLength",[856,1441,1442,1443,1446],{},"Default: ",[860,1444,1445],{},"50",". Output hash length in bytes.",[1156,1448,1450],{"name":1449,"type":1346},"timeCost",[856,1451,1442,1452,1455],{},[860,1453,1454],{},"4",". Argon2 time cost (number of iterations). Higher values increase resistance to brute-force attacks at the cost of slower hashing.",[1156,1457,1459],{"name":1458,"type":1346},"memoryCost",[856,1460,1442,1461,1464],{},[860,1462,1463],{},"262144"," (256 MiB). Memory usage in KiB. Higher values make GPU-based attacks more expensive.",[1123,1466,1467],{},[856,1468,1469,1470,1472],{},"Store ",[860,1471,966],{}," in an environment variable or a secrets manager. Never commit it to version control.",[1132,1474],{},[1135,1476,1478],{"id":1477},"botdetector",[860,1479,1480],{},"botDetector",[856,1482,1483,1484,1486,1487,974],{},"Controls whether the ",[865,1485,399],{"href":35}," module runs during authentication flows. When enabled, IP geolocation and device fingerprinting data feed directly into anomaly detection. This is a discriminated union keyed on ",[860,1488,1002],{},[1153,1490,1491,1508],{},[1156,1492,1493],{"name":1002,"type":1391,":required":1160},[856,1494,1495,1496,1498,1499,1502,1503,1507],{},"Set to ",[860,1497,1160],{}," to enable the Bot Detector middleware with active scoring and blocking. Set to ",[860,1500,1501],{},"false"," to switch to ",[1504,1505,1506],"strong",{},"passive mode"," (see below).",[1156,1509,1512],{"name":1510,"type":1511},"settings","BotDetectorConfigInput",[856,1513,1514,1515,1517,1518,1520,1521,1524],{},"Only available when ",[860,1516,1002],{}," is ",[860,1519,1160],{},". Optional custom configuration passed directly to the Bot Detector module. See the ",[865,1522,1523],{"href":514},"Bot Detector Configuration"," for the full reference.",[873,1526,1528],{"className":875,"code":1527,"language":878,"meta":879,"style":879},"\u002F\u002F Passive mode\nbotDetector: { enableBotDetector: false }\n\n\u002F\u002F Enabled with defaults\nbotDetector: { enableBotDetector: true }\n\n\u002F\u002F Enabled with custom settings\nbotDetector: {\n  enableBotDetector: true,\n  settings: { banScore: 75, checkers: { enableTorAnalysis: { enable: false } } },\n}\n",[860,1529,1530,1535,1545,1549,1554,1562,1566,1571,1576,1585,1601],{"__ignoreMap":879},[883,1531,1532],{"class":885,"line":886},[883,1533,1534],{"class":949},"\u002F\u002F Passive mode\n",[883,1536,1537,1540,1542],{"class":885,"line":918},[883,1538,1539],{"class":893},"botDetector: { enableBotDetector: ",[883,1541,1501],{"class":1007},[883,1543,1544],{"class":893}," }\n",[883,1546,1547],{"class":885,"line":924},[883,1548,921],{"emptyLinePlaceholder":8},[883,1550,1551],{"class":885,"line":937},[883,1552,1553],{"class":949},"\u002F\u002F Enabled with defaults\n",[883,1555,1556,1558,1560],{"class":885,"line":956},[883,1557,1539],{"class":893},[883,1559,1160],{"class":1007},[883,1561,1544],{"class":893},[883,1563,1564],{"class":885,"line":992},[883,1565,921],{"emptyLinePlaceholder":8},[883,1567,1568],{"class":885,"line":1013},[883,1569,1570],{"class":949},"\u002F\u002F Enabled with custom settings\n",[883,1572,1573],{"class":885,"line":1045},[883,1574,1575],{"class":893},"botDetector: {\n",[883,1577,1578,1581,1583],{"class":885,"line":1059},[883,1579,1580],{"class":893},"  enableBotDetector: ",[883,1582,1160],{"class":1007},[883,1584,1295],{"class":893},[883,1586,1587,1590,1593,1596,1598],{"class":885,"line":1073},[883,1588,1589],{"class":893},"  settings: { banScore: ",[883,1591,1592],{"class":1028},"75",[883,1594,1595],{"class":893},", checkers: { enableTorAnalysis: { enable: ",[883,1597,1501],{"class":1007},[883,1599,1600],{"class":893}," } } },\n",[883,1602,1603],{"class":885,"line":1118},[883,1604,1305],{"class":893},[1606,1607,1609],"h3",{"id":1608},"passive-mode","Passive mode",[856,1611,1612,1613,1615,1616,1618],{},"Setting ",[860,1614,1002],{}," to ",[860,1617,1501],{}," does not shut the Bot Detector down. The middleware still runs and maintains its database connection, but it switches to a passive configuration that disables all active scoring:",[1620,1621,1622,1626,1639,1652],"ul",{},[1623,1624,1625],"li",{},"All 17 security checkers are disabled (IP checks, geo checks, TOR analysis, browser\u002Fdevice checks, session coherence, velocity fingerprinting, and so on).",[1623,1627,1628,1631,1632,1615,1635,1638],{},[860,1629,1630],{},"maxScore"," is raised from ",[860,1633,1634],{},"100",[860,1636,1637],{},"300",", making it virtually impossible for any request to reach the ban threshold.",[1623,1640,1641,1644,1645,1615,1648,1651],{},[860,1642,1643],{},"restoredReputationPoints"," drops from ",[860,1646,1647],{},"10",[860,1649,1650],{},"1",", so scores heal much more slowly across requests.",[1623,1653,1654,1657,1658,1615,1661,1664],{},[860,1655,1656],{},"logLevel"," changes from ",[860,1659,1660],{},"info",[860,1662,1663],{},"warn",", reducing noise to only warnings.",[856,1666,1667],{},"The bot detector still tracks requests and maintains reputation data in the database. This means you can switch back to active mode at any time without losing historical context. Passive mode is useful during development, initial deployment, or when you want to observe traffic patterns before enforcing scoring rules.",[1132,1669],{},[1135,1671,1673],{"id":1672},"htmlsanitizer",[860,1674,1675],{},"htmlSanitizer",[856,1677,1678,1679,1681],{},"Controls the multi-pass XSS sanitization pipeline applied to all user-supplied strings before they reach the database. See ",[865,1680,139],{"href":140}," for full details on the sanitization process.",[1153,1683,1684,1691],{},[1156,1685,1686],{"name":1023,"type":1346,":required":1160},[856,1687,1442,1688,1690],{},[860,1689,1445],{},". Number of sanitization loop iterations. Each pass strips one layer of encoded or obfuscated HTML. Keep this high enough to catch layered obfuscation but not so high that it becomes a CPU exhaustion vector under load.",[1156,1692,1693],{"name":1035,"type":1346,":required":1160},[856,1694,1442,1695,1698],{},[860,1696,1697],{},"50000",". Maximum number of bytes accepted in a single input string. Inputs exceeding this length are rejected before sanitization begins.",[1132,1700],{},[1135,1702,1704],{"id":1703},"magic_links",[860,1705,1703],{},[856,1707,1708,1709,1711,1712,1714],{},"Configuration for signed temporary JWT links used in email MFA and password-reset flows. See ",[865,1710,115],{"href":116}," and ",[865,1713,123],{"href":124}," for usage details.",[1153,1716,1717,1723,1741,1748,1754,1760,1766,1775,1781,1787],{},[1156,1718,1720],{"name":1719,"type":1181,":required":1160},"jwt_secret_key",[856,1721,1722],{},"HMAC secret used to sign and verify magic link tokens. Must be different from the main JWT secret.",[1156,1724,1727],{"name":1725,"type":1726},"expiresIn","string | number",[856,1728,1729,1730,1733,1734,1737,1738,974],{},"Token lifetime as a string (",[860,1731,1732],{},"\"20m\"",") or number of seconds (",[860,1735,1736],{},"1200","). Mutually exclusive with ",[860,1739,1740],{},"expiresInMs",[1156,1742,1743],{"name":1740,"type":1346},[856,1744,1745,1746,974],{},"Token lifetime in milliseconds. Mutually exclusive with ",[860,1747,1725],{},[1156,1749,1751],{"name":1750,"type":1181,":required":1160},"domain",[856,1752,1753],{},"Full origin including the protocol. Used to construct the magic link URL sent in emails.",[1156,1755,1757],{"name":1756,"type":1346},"maxCacheEntries",[856,1758,1759],{},"Maximum number of issued link tokens held in the in-memory LRU cache. Each token is cached until it is consumed or expires.",[1156,1761,1763],{"name":1762,"type":1167},"thresholds",[856,1764,1765],{},"Per-flow thresholds that limit how many times a user can request or consume a magic link before the flow is temporarily locked.",[1156,1767,1769],{"name":1768,"type":1181},"linkToResetPasswordPage",[856,1770,1442,1771,1774],{},[860,1772,1773],{},"\"https:\u002F\u002Flocalhost\u002Faccounts\"",". The URL the user is redirected to when they click a password-reset magic link.",[1156,1776,1778],{"name":1777,"type":1167},"emailImages",[856,1779,1780],{},"URLs for images embedded in OTP and notification emails.",[1156,1782,1784],{"name":1783,"type":1167},"paths",[856,1785,1786],{},"Route paths the magic link URLs resolve to on your frontend.",[1156,1788,1790],{"name":1789,"type":1167,":required":1160},"notificationEmail",[856,1791,1792],{},"Branding and link configuration for system notification emails.",[1606,1794,1795],{"id":1762},[860,1796,1762],{},[856,1798,1799],{},"Each threshold object controls how many GET requests (page loads) and POST requests (form submissions) a user can make to a specific magic link flow before the service stops issuing new links.",[1153,1801,1803,1812],{"name":1802},"thresholds.adaptiveMfa",[1156,1804,1806],{"name":1805,"type":1346},"allowedPerSuccessfulGet",[856,1807,1442,1808,1811],{},[860,1809,1810],{},"5",". Maximum page loads allowed for the adaptive MFA verification page.",[1156,1813,1815],{"name":1814,"type":1346},"allowedPerSuccessfulPost",[856,1816,1442,1817,1820],{},[860,1818,1819],{},"3",". Maximum form submissions allowed for the adaptive MFA verification page.",[1153,1822,1824,1831],{"name":1823},"thresholds.linkPasswordVerification",[1156,1825,1826],{"name":1805,"type":1346},[856,1827,1442,1828,1830],{},[860,1829,1810],{},". Maximum page loads for the password-reset verification page.",[1156,1832,1833],{"name":1814,"type":1346},[856,1834,1442,1835,1837],{},[860,1836,1819],{},". Maximum form submissions for the password-reset verification page.",[1153,1839,1841,1848],{"name":1840},"thresholds.customMfaFlowsAndEmailChanges",[1156,1842,1843],{"name":1805,"type":1346},[856,1844,1442,1845,1847],{},[860,1846,1810],{},". Maximum page loads for custom MFA and email-change flows.",[1156,1849,1850],{"name":1814,"type":1346},[856,1851,1442,1852,1854],{},[860,1853,1819],{},". Maximum form submissions for custom MFA and email-change flows.",[1606,1856,1858],{"id":1857},"emailimages",[860,1859,1777],{},[856,1861,1862],{},"URLs for images embedded in outgoing emails. All fields have default values pointing to the Riavzon media CDN.",[1153,1864,1866,1872,1878,1884],{"name":1865},"emailImages.otp",[1156,1867,1869],{"name":1868,"type":1181},"bannerImage",[856,1870,1871],{},"URL for the banner image shown at the top of OTP emails.",[1156,1873,1875],{"name":1874,"type":1181},"device_image",[856,1876,1877],{},"URL for the device icon shown next to the device name in OTP emails.",[1156,1879,1881],{"name":1880,"type":1181},"location_image",[856,1882,1883],{},"URL for the location icon shown next to the geographic location in OTP emails.",[1156,1885,1887],{"name":1886,"type":1181},"date_image",[856,1888,1889],{},"URL for the date\u002Ftime icon shown next to the timestamp in OTP emails.",[1156,1891,1893],{"name":1892,"type":1181},"emailImages.notificationBanner",[856,1894,1895],{},"Default banner image URL for notification emails.",[1606,1897,1898],{"id":1783},[860,1899,1783],{},[856,1901,1902,1903,974],{},"Route paths that magic link URLs resolve to on your frontend. All defaults point to ",[860,1904,1905],{},"\u002Fauth\u002Fbounce",[1153,1907,1908,1917,1925],{},[1156,1909,1911],{"name":1910,"type":1181},"pathForCustomFlow",[856,1912,1442,1913,1916],{},[860,1914,1915],{},"\"\u002Fauth\u002Fbounce\"",". Path used for custom MFA flow magic links.",[1156,1918,1920],{"name":1919,"type":1181},"pathForPasswordResetLink",[856,1921,1442,1922,1924],{},[860,1923,1915],{},". Path used for password-reset magic links.",[1156,1926,1928],{"name":1927,"type":1181},"pathForAdaptiveMfaLink",[856,1929,1442,1930,1932],{},[860,1931,1915],{},". Path used for adaptive MFA magic links.",[1606,1934,1936],{"id":1935},"notificationemail",[860,1937,1789],{},[856,1939,1940],{},"Branding and navigation links included in all system notification emails (login alerts, password-change alerts, etc.).",[1153,1942,1943,1952,1958,1964,1970],{},[1156,1944,1946],{"name":1945,"type":1181},"websiteName",[856,1947,1442,1948,1951],{},[860,1949,1950],{},"\"Security Service\"",". Display name shown in the email header and subject line.",[1156,1953,1955],{"name":1954,"type":1181,":required":1160},"privacyPolicyLink",[856,1956,1957],{},"URL to your privacy policy page. Included in the email footer.",[1156,1959,1961],{"name":1960,"type":1181,":required":1160},"contactPageLink",[856,1962,1963],{},"URL to your contact page. Included in the email footer so users can report suspicious activity.",[1156,1965,1967],{"name":1966,"type":1181,":required":1160},"changePasswordPageLink",[856,1968,1969],{},"URL to your password-change page. Included in login-alert emails so users can immediately secure their account.",[1156,1971,1973],{"name":1972,"type":1181,":required":1160},"loginPageLink",[856,1974,1975],{},"URL to your login page. Included in notification emails as a navigation link.",[1132,1977],{},[1135,1979,1981],{"id":1980},"providers",[860,1982,1980],{},[856,1984,1985],{},"Defines the OAuth social login providers the service accepts. Each entry maps an incoming OAuth profile to the internal user schema. This field is optional: omit it entirely if your application does not use social login.",[856,1987,1988],{},"Each provider is defined using one of two approaches:",[856,1990,1991,1994],{},[1504,1992,1993],{},"Custom Zod schema:"," Full control over validation and transformation.",[873,1996,1998],{"className":875,"code":1997,"language":878,"meta":879,"style":879},"providers: [\n  {\n    name: 'github',\n    schema: z.object({\n      id: z.number(),\n      login: z.string(),\n      email: z.string().email(),\n      avatar_url: z.string().url(),\n    }),\n  },\n]\n",[860,1999,2000,2005,2010,2026,2042,2058,2073,2093,2113,2118,2122],{"__ignoreMap":879},[883,2001,2002],{"class":885,"line":886},[883,2003,2004],{"class":893},"providers: [\n",[883,2006,2007],{"class":885,"line":918},[883,2008,2009],{"class":893},"  {\n",[883,2011,2012,2015,2017,2019,2022,2024],{"class":885,"line":924},[883,2013,2014],{"class":897},"    name",[883,2016,944],{"class":943},[883,2018,908],{"class":907},[883,2020,2021],{"class":911},"github",[883,2023,1113],{"class":907},[883,2025,1295],{"class":893},[883,2027,2028,2031,2033,2036,2038,2040],{"class":885,"line":937},[883,2029,2030],{"class":897},"    schema",[883,2032,944],{"class":943},[883,2034,2035],{"class":897}," z",[883,2037,974],{"class":893},[883,2039,1167],{"class":930},[883,2041,934],{"class":893},[883,2043,2044,2047,2049,2051,2053,2055],{"class":885,"line":956},[883,2045,2046],{"class":897},"      id",[883,2048,944],{"class":943},[883,2050,2035],{"class":897},[883,2052,974],{"class":893},[883,2054,1346],{"class":930},[883,2056,2057],{"class":893},"(),\n",[883,2059,2060,2063,2065,2067,2069,2071],{"class":885,"line":992},[883,2061,2062],{"class":897},"      login",[883,2064,944],{"class":943},[883,2066,2035],{"class":897},[883,2068,974],{"class":893},[883,2070,1181],{"class":930},[883,2072,2057],{"class":893},[883,2074,2075,2078,2080,2082,2084,2086,2089,2091],{"class":885,"line":1013},[883,2076,2077],{"class":897},"      email",[883,2079,944],{"class":943},[883,2081,2035],{"class":897},[883,2083,974],{"class":893},[883,2085,1181],{"class":930},[883,2087,2088],{"class":893},"().",[883,2090,1103],{"class":930},[883,2092,2057],{"class":893},[883,2094,2095,2098,2100,2102,2104,2106,2108,2111],{"class":885,"line":1045},[883,2096,2097],{"class":897},"      avatar_url",[883,2099,944],{"class":943},[883,2101,2035],{"class":897},[883,2103,974],{"class":893},[883,2105,1181],{"class":930},[883,2107,2088],{"class":893},[883,2109,2110],{"class":930},"url",[883,2112,2057],{"class":893},[883,2114,2115],{"class":885,"line":1059},[883,2116,2117],{"class":893},"    }),\n",[883,2119,2120],{"class":885,"line":1073},[883,2121,1300],{"class":893},[883,2123,2124],{"class":885,"line":1118},[883,2125,2126],{"class":893},"]\n",[856,2128,2129,2132],{},[1504,2130,2131],{},"Field-type map:"," A shorthand that builds the schema automatically from a record of field names to type tokens.",[873,2134,2136],{"className":875,"code":2135,"language":878,"meta":879,"style":879},"providers: [\n  {\n    name: 'google',\n    useStandardProfile: true,\n    fields: {\n      sub: 'string',\n      email: 'email',\n      name: 'safeString',\n      picture: 'url?',\n    },\n  },\n]\n",[860,2137,2138,2142,2146,2161,2172,2182,2197,2211,2227,2243,2248,2252],{"__ignoreMap":879},[883,2139,2140],{"class":885,"line":886},[883,2141,2004],{"class":893},[883,2143,2144],{"class":885,"line":918},[883,2145,2009],{"class":893},[883,2147,2148,2150,2152,2154,2157,2159],{"class":885,"line":924},[883,2149,2014],{"class":897},[883,2151,944],{"class":943},[883,2153,908],{"class":907},[883,2155,2156],{"class":911},"google",[883,2158,1113],{"class":907},[883,2160,1295],{"class":893},[883,2162,2163,2166,2168,2170],{"class":885,"line":937},[883,2164,2165],{"class":897},"    useStandardProfile",[883,2167,944],{"class":943},[883,2169,1008],{"class":1007},[883,2171,1295],{"class":893},[883,2173,2174,2177,2179],{"class":885,"line":956},[883,2175,2176],{"class":897},"    fields",[883,2178,944],{"class":943},[883,2180,2181],{"class":893}," {\n",[883,2183,2184,2187,2189,2191,2193,2195],{"class":885,"line":992},[883,2185,2186],{"class":897},"      sub",[883,2188,944],{"class":943},[883,2190,908],{"class":907},[883,2192,1181],{"class":911},[883,2194,1113],{"class":907},[883,2196,1295],{"class":893},[883,2198,2199,2201,2203,2205,2207,2209],{"class":885,"line":1013},[883,2200,2077],{"class":897},[883,2202,944],{"class":943},[883,2204,908],{"class":907},[883,2206,1103],{"class":911},[883,2208,1113],{"class":907},[883,2210,1295],{"class":893},[883,2212,2213,2216,2218,2220,2223,2225],{"class":885,"line":1045},[883,2214,2215],{"class":897},"      name",[883,2217,944],{"class":943},[883,2219,908],{"class":907},[883,2221,2222],{"class":911},"safeString",[883,2224,1113],{"class":907},[883,2226,1295],{"class":893},[883,2228,2229,2232,2234,2236,2239,2241],{"class":885,"line":1059},[883,2230,2231],{"class":897},"      picture",[883,2233,944],{"class":943},[883,2235,908],{"class":907},[883,2237,2238],{"class":911},"url?",[883,2240,1113],{"class":907},[883,2242,1295],{"class":893},[883,2244,2245],{"class":885,"line":1073},[883,2246,2247],{"class":893},"    },\n",[883,2249,2250],{"class":885,"line":1118},[883,2251,1300],{"class":893},[883,2253,2255],{"class":885,"line":2254},12,[883,2256,2126],{"class":893},[856,2258,2259,2262,2263,1032,2266,1032,2269,1032,2272,1032,2275,1032,2278,1032,2281,1032,2284,1032,2287,1032,2290,1032,2293,1032,2296,1032,2299,1032,2302,2305,2306,2309],{},[860,2260,2261],{},"FieldToken"," is one of: ",[860,2264,2265],{},"'string'",[860,2267,2268],{},"'string?'",[860,2270,2271],{},"'email'",[860,2273,2274],{},"'email?'",[860,2276,2277],{},"'boolean'",[860,2279,2280],{},"'boolean?'",[860,2282,2283],{},"'url'",[860,2285,2286],{},"'url?'",[860,2288,2289],{},"'number'",[860,2291,2292],{},"'number?'",[860,2294,2295],{},"'int'",[860,2297,2298],{},"'int?'",[860,2300,2301],{},"'safeString'",[860,2303,2304],{},"'safeString?'",". Append ",[860,2307,2308],{},"?"," to mark a field optional.",[856,2311,2312,2313,2316],{},"See ",[865,2314,111],{"href":2315},"\u002Fdocs\u002Fiam\u002Fessentials\u002FOAuth"," for a full provider definition example.",[1132,2318],{},[1135,2320,2322],{"id":2321},"trustuserdeviceonauth",[860,2323,2324],{},"trustUserDeviceOnAuth",[1156,2326,2327],{"name":2324,"type":1391},[856,2328,1442,2329,2331,2332,2334],{},[860,2330,1501],{},". When ",[860,2333,1160],{},", a successful login marks the device as trusted and skips adaptive MFA when the canary cookie is missing on the next session. This reduces friction for users who log in from the same device frequently but weakens the anomaly detection layer.",[1132,2336],{},[1135,2338,2340],{"id":2339},"jwt",[860,2341,2339],{},[856,2343,2344],{},"Controls both access token and refresh token behavior.",[1153,2346,2347,2352,2358],{},[1156,2348,2349],{"name":1719,"type":1181,":required":1160},[856,2350,2351],{},"HMAC or RSA key used to sign access tokens. Must be kept secret. Use an environment variable or secrets manager.",[1156,2353,2355],{"name":2354,"type":1167,":required":1160},"access_tokens",[856,2356,2357],{},"Configuration for short-lived access tokens.",[1156,2359,2361],{"name":2360,"type":1167,":required":1160},"refresh_tokens",[856,2362,2363],{},"Configuration for long-lived refresh tokens stored hashed in MySQL.",[1606,2365,2366],{"id":2354},[860,2367,2354],{},[1153,2369,2370,2380,2386,2428,2437,2445,2453,2458],{},[1156,2371,2372],{"name":1725,"type":1726},[856,2373,1729,2374,2377,2378,974],{},[860,2375,2376],{},"\"15m\"",") or number of seconds. Mutually exclusive with ",[860,2379,1740],{},[1156,2381,2382],{"name":1740,"type":1346},[856,2383,1745,2384,974],{},[860,2385,1725],{},[1156,2387,2389],{"name":2388,"type":1181},"algorithm",[856,2390,2391,2392,1032,2395,1032,2398,1032,2401,1032,2404,1032,2407,1032,2410,1032,2413,1032,2416,1032,2419,1032,2422,1032,2425,974],{},"Signing algorithm. Supported values: ",[860,2393,2394],{},"HS256",[860,2396,2397],{},"HS384",[860,2399,2400],{},"HS512",[860,2402,2403],{},"RS256",[860,2405,2406],{},"RS384",[860,2408,2409],{},"RS512",[860,2411,2412],{},"ES256",[860,2414,2415],{},"ES384",[860,2417,2418],{},"ES512",[860,2420,2421],{},"PS256",[860,2423,2424],{},"PS384",[860,2426,2427],{},"PS512",[1156,2429,2431],{"name":2430,"type":1181},"audience",[856,2432,2433,2436],{},[860,2434,2435],{},"aud"," claim set on every access token.",[1156,2438,2440],{"name":2439,"type":1181},"issuer",[856,2441,2442,2436],{},[860,2443,2444],{},"iss",[1156,2446,2448],{"name":2447,"type":1181},"subject",[856,2449,2450,2436],{},[860,2451,2452],{},"sub",[1156,2454,2455],{"name":1756,"type":1346},[856,2456,2457],{},"LRU cache size for verified access tokens. Cached tokens skip the cryptographic verification step on subsequent requests within their lifetime.",[1156,2459,2462],{"name":2460,"type":2461},"payload","Record\u003Cstring, unknown>",[856,2463,2464],{},"Extra claims merged into every access token payload. Use this to include application-specific data such as roles or permissions.",[1606,2466,2467],{"id":2360},[860,2468,2360],{},[1153,2470,2471,2477,2486,2492,2498],{},[1156,2472,2474],{"name":2473,"type":1346,":required":1160},"refresh_ttl",[856,2475,2476],{},"Refresh token lifetime in milliseconds. After this duration, the token is considered expired and the user must re-authenticate.",[1156,2478,2479],{"name":1750,"type":1181,":required":1160},[856,2480,2481,2482,2485],{},"Cookie domain for the refresh token cookie. Set this to your root domain (e.g. ",[860,2483,2484],{},"\"example.com\"",") so the cookie is sent on all subdomains.",[1156,2487,2489],{"name":2488,"type":1346,":required":1160},"MAX_SESSION_LIFE",[856,2490,2491],{},"Maximum total session lifetime in milliseconds. Even if the refresh token is continuously rotated, the session is forcibly ended after this duration.",[1156,2493,2495],{"name":2494,"type":1346,":required":1160},"maxAllowedSessionsPerUser",[856,2496,2497],{},"Maximum number of concurrent active sessions allowed per user. When a new login exceeds this limit, the oldest session is invalidated.",[1156,2499,2501],{"name":2500,"type":1346,":required":1160},"byPassAnomaliesFor",[856,2502,2503],{},"Duration in milliseconds after a successful MFA verification during which anomaly detection checks are bypassed. This prevents the user from being challenged again immediately after proving their identity.",[856,2505,2312,2506,2508],{},[865,2507,83],{"href":84}," for full token lifecycle details.",[1132,2510],{},[1135,2512,2513],{"id":1103},[860,2514,1103],{},[856,2516,2517],{},"Resend API credentials used for all outgoing system and MFA emails.",[1153,2519,2520,2531],{},[1156,2521,2522],{"name":1083,"type":1181,":required":1160},[856,2523,2524,2525,2530],{},"Your ",[865,2526,2529],{"href":2527,"rel":2528},"https:\u002F\u002Fresend.com\u002F",[869],"Resend"," API key.",[1156,2532,2533],{"name":1103,"type":1181,":required":1160},[856,2534,2535,2536,2539,2540,2543],{},"The ",[860,2537,2538],{},"From"," address for all outgoing emails (e.g. ",[860,2541,2542],{},"\"no-reply@example.com\"","). This address must be verified in your Resend account.",[1132,2545],{},[1135,2547,2549],{"id":2548},"rate_limiters",[860,2550,2548],{},[856,2552,2553],{},"Fine-grained rate-limiter configurations for every sensitive endpoint. This entire section is optional, and every individual limiter group within it is also optional. When the section or any group is omitted, the service falls back to built-in defaults. Rate limiting is always active. Every individual limiter within each group shares the same shape:",[1153,2555,2556,2562,2572,2577,2583],{},[1156,2557,2559],{"name":2558,"type":1346},"inMemoryBlockOnConsumed",[856,2560,2561],{},"Number of consumed points at which the in-memory block triggers. This provides fast rejection without hitting the database.",[1156,2563,2565],{"name":2564,"type":1346},"points",[856,2566,2567,2568,2571],{},"Number of allowed requests per ",[860,2569,2570],{},"duration"," window.",[1156,2573,2574],{"name":2570,"type":1346},[856,2575,2576],{},"Window length in seconds.",[1156,2578,2580],{"name":2579,"type":1346},"blockDuration",[856,2581,2582],{},"How long in seconds the client is blocked after exceeding the limit.",[1156,2584,2586],{"name":2585,"type":1346},"inMemoryBlockDuration",[856,2587,2588],{},"How long in seconds the in-memory block lasts.",[856,2590,2312,2591,2594],{},[865,2592,147],{"href":2593},"\u002Fdocs\u002Fiam\u002Frate-limiting"," for detailed usage examples, union limiter patterns, and the full schema for each group.",[1606,2596,2598],{"id":2597},"linkverificationlimiter",[860,2599,2600],{},"linkVerificationLimiter",[856,2602,2603,2604,1711,2607,2610],{},"Protects ",[860,2605,2606],{},"\u002Fauth\u002Fverify-mfa",[860,2608,2609],{},"\u002Fauth\u002Freset-password"," endpoints.",[1153,2612,2613,2620],{},[1156,2614,2617],{"name":2615,"type":2616},"unionLimiter.burstLimiter","LimiterConfig",[856,2618,2619],{},"Short-window burst limiter. Catches rapid-fire verification attempts.",[1156,2621,2623],{"name":2622,"type":2616},"unionLimiter.slowLimiter",[856,2624,2625],{},"Long-window slow limiter. Catches distributed or slow-burn enumeration attempts.",[1132,2627],{},[1606,2629,2631],{"id":2630},"loginlimiters",[860,2632,2633],{},"loginLimiters",[856,2635,2603,2636,974],{},[860,2637,2638],{},"POST \u002Flogin",[1153,2640,2641,2646,2651,2657],{},[1156,2642,2643],{"name":2615,"type":2616},[856,2644,2645],{},"Short-window burst limiter for login attempts.",[1156,2647,2648],{"name":2622,"type":2616},[856,2649,2650],{},"Long-window slow limiter for login attempts.",[1156,2652,2654],{"name":2653,"type":2616},"ipLimiter",[856,2655,2656],{},"Per-IP limiter applied independently of the union limiter.",[1156,2658,2660],{"name":2659,"type":2616},"emailLimiter",[856,2661,2662],{},"Per-email limiter that prevents credential stuffing against a single account.",[1132,2664],{},[1606,2666,2668],{"id":2667},"oauthlimiters",[860,2669,2670],{},"oauthLimiters",[856,2672,2603,2673,974],{},[860,2674,2675],{},"POST \u002Fauth\u002FOAuth\u002F:providerName",[1153,2677,2678,2684,2690,2696],{},[1156,2679,2681],{"name":2680,"type":2616},"unionLimiter.ipLimiterBrute",[856,2682,2683],{},"Short-window burst limiter keyed by IP.",[1156,2685,2687],{"name":2686,"type":2616},"unionLimiter.ipLimiterSlow",[856,2688,2689],{},"Long-window slow limiter keyed by IP.",[1156,2691,2693],{"name":2692,"type":2616},"subLimiter",[856,2694,2695],{},"Per-subject limiter that limits attempts per OAuth subject identifier.",[1156,2697,2699],{"name":2698,"type":2616},"compositeKeyLimiter",[856,2700,2701],{},"Composite key limiter combining IP and subject for fine-grained control.",[1132,2703],{},[1606,2705,2707],{"id":2706},"signuplimiters",[860,2708,2709],{},"signupLimiters",[856,2711,2603,2712,974],{},[860,2713,2714],{},"POST \u002Fsignup",[1153,2716,2717,2723,2729,2735,2741],{},[1156,2718,2720],{"name":2719,"type":2616},"unionLimiters.uniLimiterIp.ipLimit",[856,2721,2722],{},"Short-window IP burst limiter for signups.",[1156,2724,2726],{"name":2725,"type":2616},"unionLimiters.uniLimiterIp.slowIpLimit",[856,2727,2728],{},"Long-window IP slow limiter for signups.",[1156,2730,2732],{"name":2731,"type":2616},"unionLimiters.uniLimiterComposite.compositeKeyLimit",[856,2733,2734],{},"Short-window composite key (IP + email) burst limiter.",[1156,2736,2738],{"name":2737,"type":2616},"unionLimiters.uniLimiterComposite.slowCompositeKeyLimit",[856,2739,2740],{},"Long-window composite key slow limiter.",[1156,2742,2744],{"name":2743,"type":2616},"emailLimit",[856,2745,2746],{},"Per-email limiter that prevents mass account creation with variations of the same address.",[1132,2748],{},[1606,2750,2752],{"id":2751},"temppostrouteslimiters",[860,2753,2754],{},"tempPostRoutesLimiters",[856,2756,2757],{},"Protects temporary POST routes such as email update and custom MFA initiation.",[1153,2759,2760,2766,2772],{},[1156,2761,2763],{"name":2762,"type":2616},"unionLimiters.limit",[856,2764,2765],{},"Short-window burst limiter.",[1156,2767,2769],{"name":2768,"type":2616},"unionLimiters.slowLimit",[856,2770,2771],{},"Long-window slow limiter.",[1156,2773,2775],{"name":2774,"type":2616},"ipLimit",[856,2776,2656],{},[1132,2778],{},[1606,2780,2782],{"id":2781},"tokenlimiters",[860,2783,2784],{},"tokenLimiters",[856,2786,2787,2788,2791,2792,2795],{},"Protects the ",[860,2789,2790],{},"\u002Fauth\u002Fuser\u002Frefresh-session"," rotation route and the ",[860,2793,2794],{},"\u002Fauth\u002Flogout"," route.",[1153,2797,2798,2804,2810,2816,2822],{},[1156,2799,2801],{"name":2800,"type":2616},"unionLimiters.refreshAccessTokenLimiter.accessTokenBrute",[856,2802,2803],{},"Short-window burst limiter for access token refresh.",[1156,2805,2807],{"name":2806,"type":2616},"unionLimiters.refreshAccessTokenLimiter.accessTokenSlow",[856,2808,2809],{},"Long-window slow limiter for access token refresh.",[1156,2811,2813],{"name":2812,"type":2616},"unionLimiters.refreshTokenLimiterUnion.refreshTokenBrute",[856,2814,2815],{},"Short-window burst limiter for refresh token rotation.",[1156,2817,2819],{"name":2818,"type":2616},"unionLimiters.refreshTokenLimiterUnion.refreshTokenSlow",[856,2820,2821],{},"Long-window slow limiter for refresh token rotation.",[1156,2823,2825],{"name":2824,"type":2616},"refreshTokenLimiter",[856,2826,2827],{},"Standalone limiter applied to all refresh token operations.",[1132,2829],{},[1606,2831,2833],{"id":2832},"initpasswordresetlimiters",[860,2834,2835],{},"initPasswordResetLimiters",[856,2837,2603,2838,974],{},[860,2839,2840],{},"POST \u002Fauth\u002Fforgot-password",[1153,2842,2843,2847,2852,2857],{},[1156,2844,2845],{"name":2762,"type":2616},[856,2846,2765],{},[1156,2848,2850],{"name":2849,"type":2616},"unionLimiters.longLimiter",[856,2851,2771],{},[1156,2853,2854],{"name":2653,"type":2616},[856,2855,2856],{},"Per-IP limiter.",[1156,2858,2859],{"name":2659,"type":2616},[856,2860,2861],{},"Per-email limiter that prevents password-reset spam against a single account.",[1132,2863],{},[1606,2865,2867],{"id":2866},"emailmfalimiters",[860,2868,2869],{},"emailMfaLimiters",[856,2871,2872],{},"Protects email MFA sending endpoints.",[1153,2874,2875,2879,2883,2887,2893],{},[1156,2876,2877],{"name":2762,"type":2616},[856,2878,2765],{},[1156,2880,2881],{"name":2849,"type":2616},[856,2882,2771],{},[1156,2884,2885],{"name":2653,"type":2616},[856,2886,2856],{},[1156,2888,2890],{"name":2889,"type":2616},"userIdLimiter",[856,2891,2892],{},"Per-user limiter that prevents a single user from triggering excessive MFA emails.",[1156,2894,2896],{"name":2895,"type":2616},"globalEmailLimiter",[856,2897,2898],{},"Global limiter that caps the total number of MFA emails sent across all users. Protects your Resend quota from abuse.",[1132,2900],{},[1135,2902,2904],{"id":2903},"loglevel",[860,2905,1656],{},[1156,2907,2909],{"name":1656,"type":2908},"'trace' | 'debug' | 'info' | 'warn' | 'error' | 'fatal'",[856,2910,2911,2912,2915,2916,2919,2920,2923],{},"Pino log level for the service logger. Use ",[860,2913,2914],{},"'debug'"," during development to see detailed request processing. Set ",[860,2917,2918],{},"'warn'"," or ",[860,2921,2922],{},"'error'"," in production to reduce log volume.",[2925,2926,2927],"style",{},"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 .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 .sHOzp, html code.shiki .sHOzp{--shiki-light:#795E26;--shiki-default:#795E26;--shiki-dark:#50FA7B}html pre.shiki code .s34zl, html code.shiki .s34zl{--shiki-light:#001080;--shiki-default:#001080;--shiki-dark:#FF79C6}html pre.shiki code .sghk6, html code.shiki .sghk6{--shiki-light:#008000;--shiki-default:#008000;--shiki-dark:#6272A4}html pre.shiki code .sPzPf, html code.shiki .sPzPf{--shiki-light:#0070C1;--shiki-default:#0070C1;--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}html pre.shiki code .spgvN, html code.shiki .spgvN{--shiki-light:#098658;--shiki-default:#098658;--shiki-dark:#BD93F9}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);}",{"title":879,"searchDepth":918,"depth":918,"links":2929},[2930,2931,2932,2933,2936,2937,2943,2944,2945,2949,2950,2960],{"id":1137,"depth":918,"text":1137},{"id":1316,"depth":918,"text":1316},{"id":1421,"depth":918,"text":1421},{"id":1477,"depth":918,"text":1480,"children":2934},[2935],{"id":1608,"depth":924,"text":1609},{"id":1672,"depth":918,"text":1675},{"id":1703,"depth":918,"text":1703,"children":2938},[2939,2940,2941,2942],{"id":1762,"depth":924,"text":1762},{"id":1857,"depth":924,"text":1777},{"id":1783,"depth":924,"text":1783},{"id":1935,"depth":924,"text":1789},{"id":1980,"depth":918,"text":1980},{"id":2321,"depth":918,"text":2324},{"id":2339,"depth":918,"text":2339,"children":2946},[2947,2948],{"id":2354,"depth":924,"text":2354},{"id":2360,"depth":924,"text":2360},{"id":1103,"depth":918,"text":1103},{"id":2548,"depth":918,"text":2548,"children":2951},[2952,2953,2954,2955,2956,2957,2958,2959],{"id":2597,"depth":924,"text":2600},{"id":2630,"depth":924,"text":2633},{"id":2667,"depth":924,"text":2670},{"id":2706,"depth":924,"text":2709},{"id":2751,"depth":924,"text":2754},{"id":2781,"depth":924,"text":2784},{"id":2832,"depth":924,"text":2835},{"id":2866,"depth":924,"text":2869},{"id":2903,"depth":918,"text":1656},"Full reference for every option accepted by the configuration function.","md","i-lucide-settings",{},null,"---\ntitle: Configuration\ndescription: Full reference for every option accepted by the configuration function.\nicon: i-lucide-settings\n---\n\nThe IAM service is initialized by calling `configuration()` with a single typed object. The schema is validated at startup with [Zod](https:\u002F\u002Fzod.dev\u002F) and any missing or invalid field throws immediately, preventing the service from starting with a broken config.\n\n```ts [server.ts]\nimport { configuration } from '@riavzon\u002Fauth'\n\nawait configuration({\n  store: { \u002F* ... *\u002F },\n  password: { pepper: process.env.PEPPER! },\n  botDetector: { enableBotDetector: true },\n  htmlSanitizer: { IrritationCount: 50, maxAllowedInputLength: 50000 },\n  magic_links: { \u002F* ... *\u002F },\n  jwt: { \u002F* ... *\u002F },\n  email: { resend_key: process.env.RESEND_KEY!, email: 'no-reply@example.com' },\n})\n```\n\n::warning\nCall `configuration()` once before mounting any routes. The service reads the resolved config on every request: calling it more than once replaces the previous config globally.\n::\n\n---\n\n## `store`\n\nDatabase connection pools for the main application database and the rate-limiter store. Both pools accept any valid [mysql2 `PoolOptions`](https:\u002F\u002Fsidorares.github.io\u002Fnode-mysql2\u002Fdocs) object.\n\n::field-group\n::field{name=\"main\" type=\"mysql.PoolOptions\" required}\nPrimary MySQL connection pool used for visitor persistence, token storage, user accounts, and all core queries.\n::\n\n::field{name=\"rate_limiters_pool\" type=\"object\" required}\nConnection pool dedicated to the rate-limiter tables. Keeping rate-limiter state in a separate database prevents lock contention with the main application pool under heavy load.\n::\n::\n\n::field-group{name=\"rate_limiters_pool\"}\n::field{name=\"store\" type=\"mysql.PoolOptions\" required}\nMySQL connection options for the rate-limiter database.\n::\n\n::field{name=\"dbName\" type=\"string\" required}\nDatabase name for the limiter tables. Must match the database created for rate-limiter state.\n::\n::\n\n```ts [server.ts]\nstore: {\n  main: { host: 'localhost', user: 'root', password: 'secret', database: 'auth' },\n  rate_limiters_pool: {\n    store: { host: 'localhost', user: 'root', password: 'secret', database: 'auth_limiters' },\n    dbName: 'auth_limiters',\n  },\n}\n```\n\n::tip\nYou can point both pools at the same MySQL server with different database names, or use separate servers for isolation.\n::\n\n---\n\n## `service`\n\nRuntime service settings for proxy trust, port binding, and optional HMAC inter-service authentication. This entire section is optional.\n\n::field-group\n::field{name=\"Hmac\" type=\"object\"}\nWhen present, enables HMAC request signing and verification for inter-service calls. See the [HMAC guide](\u002Fdocs\u002Fiam\u002Fessentials\u002Fhmac) for full details.\n::\n\n::field{name=\"proxy\" type=\"object\" required}\nProxy and IP extraction settings. Required when `service` is provided.\n::\n\n::field{name=\"port\" type=\"number\"}\nPort the service listens on when running in standalone mode.\n::\n\n::field{name=\"ipAddress\" type=\"string\"}\nIP address to bind when running in standalone mode.\n::\n\n::field{name=\"clientIp\" type=\"string\"}\nOverride for client IP extraction. Use this when your reverse proxy sets a non-standard header for the real client IP.\n::\n::\n\n::field-group{name=\"Hmac\"}\n::field{name=\"sharedSecret\" type=\"string\" required}\nShared secret used to sign and verify HMAC request signatures. Must match between all communicating services.\n::\n\n::field{name=\"clientId\" type=\"string\" required}\nClient identifier sent with every HMAC-signed request. The receiving service uses this to look up the correct shared secret.\n::\n\n::field{name=\"maxClockSkew\" type=\"number\" required}\nMaximum allowed clock skew in milliseconds between the signing and verifying services. Defaults to `300000` (5 minutes). Requests with a timestamp outside this window are rejected.\n::\n::\n\n::field-group{name=\"proxy\"}\n::field{name=\"trust\" type=\"boolean\" required}\nWhether to trust `X-Forwarded-*` headers from the upstream proxy. Set to `true` when running behind a reverse proxy such as Nginx or Caddy.\n::\n\n::field{name=\"ipToTrust\" type=\"string\" required}\nSpecific proxy IP address to trust. Only `X-Forwarded-*` headers from this IP are accepted.\n::\n\n::field{name=\"server\" type=\"string\"}\nOptional upstream server identifier for logging and diagnostics.\n::\n::\n\n---\n\n## `password`\n\nControls Argon2id password hashing parameters. The `pepper` value is combined with the user's password before hashing: rotate it to invalidate all existing hashes.\n\n::field-group\n::field{name=\"pepper\" type=\"string\" required}\nSecret added to every password before hashing. Store this in an environment variable or a secrets manager. Never commit it to version control.\n::\n\n::field{name=\"hashLength\" type=\"number\"}\nDefault: `50`. Output hash length in bytes.\n::\n\n::field{name=\"timeCost\" type=\"number\"}\nDefault: `4`. Argon2 time cost (number of iterations). Higher values increase resistance to brute-force attacks at the cost of slower hashing.\n::\n\n::field{name=\"memoryCost\" type=\"number\"}\nDefault: `262144` (256 MiB). Memory usage in KiB. Higher values make GPU-based attacks more expensive.\n::\n::\n\n::warning\nStore `pepper` in an environment variable or a secrets manager. Never commit it to version control.\n::\n\n---\n\n## `botDetector`\n\nControls whether the [Bot Detector](\u002Fdocs\u002Fbot-detection) module runs during authentication flows. When enabled, IP geolocation and device fingerprinting data feed directly into anomaly detection. This is a discriminated union keyed on `enableBotDetector`.\n\n::field-group\n::field{name=\"enableBotDetector\" type=\"boolean\" required}\nSet to `true` to enable the Bot Detector middleware with active scoring and blocking. Set to `false` to switch to **passive mode** (see below).\n::\n\n::field{name=\"settings\" type=\"BotDetectorConfigInput\"}\nOnly available when `enableBotDetector` is `true`. Optional custom configuration passed directly to the Bot Detector module. See the [Bot Detector Configuration](\u002Fdocs\u002Fbot-detection\u002Fconfiguration) for the full reference.\n::\n::\n\n```ts\n\u002F\u002F Passive mode\nbotDetector: { enableBotDetector: false }\n\n\u002F\u002F Enabled with defaults\nbotDetector: { enableBotDetector: true }\n\n\u002F\u002F Enabled with custom settings\nbotDetector: {\n  enableBotDetector: true,\n  settings: { banScore: 75, checkers: { enableTorAnalysis: { enable: false } } },\n}\n```\n\n### Passive mode\n\nSetting `enableBotDetector` to `false` does not shut the Bot Detector down. The middleware still runs and maintains its database connection, but it switches to a passive configuration that disables all active scoring:\n\n- All 17 security checkers are disabled (IP checks, geo checks, TOR analysis, browser\u002Fdevice checks, session coherence, velocity fingerprinting, and so on).\n- `maxScore` is raised from `100` to `300`, making it virtually impossible for any request to reach the ban threshold.\n- `restoredReputationPoints` drops from `10` to `1`, so scores heal much more slowly across requests.\n- `logLevel` changes from `info` to `warn`, reducing noise to only warnings.\n\nThe bot detector still tracks requests and maintains reputation data in the database. This means you can switch back to active mode at any time without losing historical context. Passive mode is useful during development, initial deployment, or when you want to observe traffic patterns before enforcing scoring rules.\n\n---\n\n## `htmlSanitizer`\n\nControls the multi-pass XSS sanitization pipeline applied to all user-supplied strings before they reach the database. See [XSS Protection](\u002Fdocs\u002Fiam\u002Fessentials\u002Fxss) for full details on the sanitization process.\n\n::field-group\n::field{name=\"IrritationCount\" type=\"number\" required}\nDefault: `50`. Number of sanitization loop iterations. Each pass strips one layer of encoded or obfuscated HTML. Keep this high enough to catch layered obfuscation but not so high that it becomes a CPU exhaustion vector under load.\n::\n\n::field{name=\"maxAllowedInputLength\" type=\"number\" required}\nDefault: `50000`. Maximum number of bytes accepted in a single input string. Inputs exceeding this length are rejected before sanitization begins.\n::\n::\n\n---\n\n## `magic_links`\n\nConfiguration for signed temporary JWT links used in email MFA and password-reset flows. See [Magic Links](\u002Fdocs\u002Fiam\u002Fessentials\u002Fmagic-links) and [MFA](\u002Fdocs\u002Fiam\u002Fessentials\u002Fmfa) for usage details.\n\n::field-group\n::field{name=\"jwt_secret_key\" type=\"string\" required}\nHMAC secret used to sign and verify magic link tokens. Must be different from the main JWT secret.\n::\n\n::field{name=\"expiresIn\" type=\"string | number\"}\nToken lifetime as a string (`\"20m\"`) or number of seconds (`1200`). Mutually exclusive with `expiresInMs`.\n::\n\n::field{name=\"expiresInMs\" type=\"number\"}\nToken lifetime in milliseconds. Mutually exclusive with `expiresIn`.\n::\n\n::field{name=\"domain\" type=\"string\" required}\nFull origin including the protocol. Used to construct the magic link URL sent in emails.\n::\n\n::field{name=\"maxCacheEntries\" type=\"number\"}\nMaximum number of issued link tokens held in the in-memory LRU cache. Each token is cached until it is consumed or expires.\n::\n\n::field{name=\"thresholds\" type=\"object\"}\nPer-flow thresholds that limit how many times a user can request or consume a magic link before the flow is temporarily locked.\n::\n\n::field{name=\"linkToResetPasswordPage\" type=\"string\"}\nDefault: `\"https:\u002F\u002Flocalhost\u002Faccounts\"`. The URL the user is redirected to when they click a password-reset magic link.\n::\n\n::field{name=\"emailImages\" type=\"object\"}\nURLs for images embedded in OTP and notification emails.\n::\n\n::field{name=\"paths\" type=\"object\"}\nRoute paths the magic link URLs resolve to on your frontend.\n::\n\n::field{name=\"notificationEmail\" type=\"object\" required}\nBranding and link configuration for system notification emails.\n::\n::\n\n### `thresholds`\n\nEach threshold object controls how many GET requests (page loads) and POST requests (form submissions) a user can make to a specific magic link flow before the service stops issuing new links.\n\n::field-group{name=\"thresholds.adaptiveMfa\"}\n::field{name=\"allowedPerSuccessfulGet\" type=\"number\"}\nDefault: `5`. Maximum page loads allowed for the adaptive MFA verification page.\n::\n\n::field{name=\"allowedPerSuccessfulPost\" type=\"number\"}\nDefault: `3`. Maximum form submissions allowed for the adaptive MFA verification page.\n::\n::\n\n::field-group{name=\"thresholds.linkPasswordVerification\"}\n::field{name=\"allowedPerSuccessfulGet\" type=\"number\"}\nDefault: `5`. Maximum page loads for the password-reset verification page.\n::\n\n::field{name=\"allowedPerSuccessfulPost\" type=\"number\"}\nDefault: `3`. Maximum form submissions for the password-reset verification page.\n::\n::\n\n::field-group{name=\"thresholds.customMfaFlowsAndEmailChanges\"}\n::field{name=\"allowedPerSuccessfulGet\" type=\"number\"}\nDefault: `5`. Maximum page loads for custom MFA and email-change flows.\n::\n\n::field{name=\"allowedPerSuccessfulPost\" type=\"number\"}\nDefault: `3`. Maximum form submissions for custom MFA and email-change flows.\n::\n::\n\n### `emailImages`\n\nURLs for images embedded in outgoing emails. All fields have default values pointing to the Riavzon media CDN.\n\n::field-group{name=\"emailImages.otp\"}\n::field{name=\"bannerImage\" type=\"string\"}\nURL for the banner image shown at the top of OTP emails.\n::\n\n::field{name=\"device_image\" type=\"string\"}\nURL for the device icon shown next to the device name in OTP emails.\n::\n\n::field{name=\"location_image\" type=\"string\"}\nURL for the location icon shown next to the geographic location in OTP emails.\n::\n\n::field{name=\"date_image\" type=\"string\"}\nURL for the date\u002Ftime icon shown next to the timestamp in OTP emails.\n::\n::\n\n::field{name=\"emailImages.notificationBanner\" type=\"string\"}\nDefault banner image URL for notification emails.\n::\n\n### `paths`\n\nRoute paths that magic link URLs resolve to on your frontend. All defaults point to `\u002Fauth\u002Fbounce`.\n\n::field-group\n::field{name=\"pathForCustomFlow\" type=\"string\"}\nDefault: `\"\u002Fauth\u002Fbounce\"`. Path used for custom MFA flow magic links.\n::\n\n::field{name=\"pathForPasswordResetLink\" type=\"string\"}\nDefault: `\"\u002Fauth\u002Fbounce\"`. Path used for password-reset magic links.\n::\n\n::field{name=\"pathForAdaptiveMfaLink\" type=\"string\"}\nDefault: `\"\u002Fauth\u002Fbounce\"`. Path used for adaptive MFA magic links.\n::\n::\n\n### `notificationEmail`\n\nBranding and navigation links included in all system notification emails (login alerts, password-change alerts, etc.).\n\n::field-group\n::field{name=\"websiteName\" type=\"string\"}\nDefault: `\"Security Service\"`. Display name shown in the email header and subject line.\n::\n\n::field{name=\"privacyPolicyLink\" type=\"string\" required}\nURL to your privacy policy page. Included in the email footer.\n::\n\n::field{name=\"contactPageLink\" type=\"string\" required}\nURL to your contact page. Included in the email footer so users can report suspicious activity.\n::\n\n::field{name=\"changePasswordPageLink\" type=\"string\" required}\nURL to your password-change page. Included in login-alert emails so users can immediately secure their account.\n::\n\n::field{name=\"loginPageLink\" type=\"string\" required}\nURL to your login page. Included in notification emails as a navigation link.\n::\n::\n\n---\n\n## `providers`\n\nDefines the OAuth social login providers the service accepts. Each entry maps an incoming OAuth profile to the internal user schema. This field is optional: omit it entirely if your application does not use social login.\n\nEach provider is defined using one of two approaches:\n\n**Custom Zod schema:** Full control over validation and transformation.\n\n```ts\nproviders: [\n  {\n    name: 'github',\n    schema: z.object({\n      id: z.number(),\n      login: z.string(),\n      email: z.string().email(),\n      avatar_url: z.string().url(),\n    }),\n  },\n]\n```\n\n**Field-type map:** A shorthand that builds the schema automatically from a record of field names to type tokens.\n\n```ts\nproviders: [\n  {\n    name: 'google',\n    useStandardProfile: true,\n    fields: {\n      sub: 'string',\n      email: 'email',\n      name: 'safeString',\n      picture: 'url?',\n    },\n  },\n]\n```\n\n`FieldToken` is one of: `'string'`, `'string?'`, `'email'`, `'email?'`, `'boolean'`, `'boolean?'`, `'url'`, `'url?'`, `'number'`, `'number?'`, `'int'`, `'int?'`, `'safeString'`, `'safeString?'`. Append `?` to mark a field optional.\n\nSee [OAuth](\u002Fdocs\u002Fiam\u002Fessentials\u002FOAuth) for a full provider definition example.\n\n---\n\n## `trustUserDeviceOnAuth`\n\n::field{name=\"trustUserDeviceOnAuth\" type=\"boolean\"}\nDefault: `false`. When `true`, a successful login marks the device as trusted and skips adaptive MFA when the canary cookie is missing on the next session. This reduces friction for users who log in from the same device frequently but weakens the anomaly detection layer.\n::\n\n---\n\n## `jwt`\n\nControls both access token and refresh token behavior.\n\n::field-group\n::field{name=\"jwt_secret_key\" type=\"string\" required}\nHMAC or RSA key used to sign access tokens. Must be kept secret. Use an environment variable or secrets manager.\n::\n\n::field{name=\"access_tokens\" type=\"object\" required}\nConfiguration for short-lived access tokens.\n::\n\n::field{name=\"refresh_tokens\" type=\"object\" required}\nConfiguration for long-lived refresh tokens stored hashed in MySQL.\n::\n::\n\n### `access_tokens`\n\n::field-group\n::field{name=\"expiresIn\" type=\"string | number\"}\nToken lifetime as a string (`\"15m\"`) or number of seconds. Mutually exclusive with `expiresInMs`.\n::\n\n::field{name=\"expiresInMs\" type=\"number\"}\nToken lifetime in milliseconds. Mutually exclusive with `expiresIn`.\n::\n\n::field{name=\"algorithm\" type=\"string\"}\nSigning algorithm. Supported values: `HS256`, `HS384`, `HS512`, `RS256`, `RS384`, `RS512`, `ES256`, `ES384`, `ES512`, `PS256`, `PS384`, `PS512`.\n::\n\n::field{name=\"audience\" type=\"string\"}\n`aud` claim set on every access token.\n::\n\n::field{name=\"issuer\" type=\"string\"}\n`iss` claim set on every access token.\n::\n\n::field{name=\"subject\" type=\"string\"}\n`sub` claim set on every access token.\n::\n\n::field{name=\"maxCacheEntries\" type=\"number\"}\nLRU cache size for verified access tokens. Cached tokens skip the cryptographic verification step on subsequent requests within their lifetime.\n::\n\n::field{name=\"payload\" type=\"Record\u003Cstring, unknown>\"}\nExtra claims merged into every access token payload. Use this to include application-specific data such as roles or permissions.\n::\n::\n\n### `refresh_tokens`\n\n::field-group\n::field{name=\"refresh_ttl\" type=\"number\" required}\nRefresh token lifetime in milliseconds. After this duration, the token is considered expired and the user must re-authenticate.\n::\n\n::field{name=\"domain\" type=\"string\" required}\nCookie domain for the refresh token cookie. Set this to your root domain (e.g. `\"example.com\"`) so the cookie is sent on all subdomains.\n::\n\n::field{name=\"MAX_SESSION_LIFE\" type=\"number\" required}\nMaximum total session lifetime in milliseconds. Even if the refresh token is continuously rotated, the session is forcibly ended after this duration.\n::\n\n::field{name=\"maxAllowedSessionsPerUser\" type=\"number\" required}\nMaximum number of concurrent active sessions allowed per user. When a new login exceeds this limit, the oldest session is invalidated.\n::\n\n::field{name=\"byPassAnomaliesFor\" type=\"number\" required}\nDuration in milliseconds after a successful MFA verification during which anomaly detection checks are bypassed. This prevents the user from being challenged again immediately after proving their identity.\n::\n::\n\nSee [Tokens](\u002Fdocs\u002Fiam\u002Fessentials\u002Ftokens) for full token lifecycle details.\n\n---\n\n## `email`\n\nResend API credentials used for all outgoing system and MFA emails.\n\n::field-group\n::field{name=\"resend_key\" type=\"string\" required}\nYour [Resend](https:\u002F\u002Fresend.com\u002F) API key.\n::\n\n::field{name=\"email\" type=\"string\" required}\nThe `From` address for all outgoing emails (e.g. `\"no-reply@example.com\"`). This address must be verified in your Resend account.\n::\n::\n\n---\n\n## `rate_limiters`\n\nFine-grained rate-limiter configurations for every sensitive endpoint. This entire section is optional, and every individual limiter group within it is also optional. When the section or any group is omitted, the service falls back to built-in defaults. Rate limiting is always active. Every individual limiter within each group shares the same shape:\n\n::field-group\n::field{name=\"inMemoryBlockOnConsumed\" type=\"number\"}\nNumber of consumed points at which the in-memory block triggers. This provides fast rejection without hitting the database.\n::\n\n::field{name=\"points\" type=\"number\"}\nNumber of allowed requests per `duration` window.\n::\n\n::field{name=\"duration\" type=\"number\"}\nWindow length in seconds.\n::\n\n::field{name=\"blockDuration\" type=\"number\"}\nHow long in seconds the client is blocked after exceeding the limit.\n::\n\n::field{name=\"inMemoryBlockDuration\" type=\"number\"}\nHow long in seconds the in-memory block lasts.\n::\n::\n\nSee [Rate Limiting](\u002Fdocs\u002Fiam\u002Frate-limiting) for detailed usage examples, union limiter patterns, and the full schema for each group.\n\n### `linkVerificationLimiter`\n\nProtects `\u002Fauth\u002Fverify-mfa` and `\u002Fauth\u002Freset-password` endpoints.\n\n::field-group\n::field{name=\"unionLimiter.burstLimiter\" type=\"LimiterConfig\"}\nShort-window burst limiter. Catches rapid-fire verification attempts.\n::\n\n::field{name=\"unionLimiter.slowLimiter\" type=\"LimiterConfig\"}\nLong-window slow limiter. Catches distributed or slow-burn enumeration attempts.\n::\n::\n\n---\n\n### `loginLimiters`\n\nProtects `POST \u002Flogin`.\n\n::field-group\n::field{name=\"unionLimiter.burstLimiter\" type=\"LimiterConfig\"}\nShort-window burst limiter for login attempts.\n::\n\n::field{name=\"unionLimiter.slowLimiter\" type=\"LimiterConfig\"}\nLong-window slow limiter for login attempts.\n::\n\n::field{name=\"ipLimiter\" type=\"LimiterConfig\"}\nPer-IP limiter applied independently of the union limiter.\n::\n\n::field{name=\"emailLimiter\" type=\"LimiterConfig\"}\nPer-email limiter that prevents credential stuffing against a single account.\n::\n::\n\n---\n\n### `oauthLimiters`\n\nProtects `POST \u002Fauth\u002FOAuth\u002F:providerName`.\n\n::field-group\n::field{name=\"unionLimiter.ipLimiterBrute\" type=\"LimiterConfig\"}\nShort-window burst limiter keyed by IP.\n::\n\n::field{name=\"unionLimiter.ipLimiterSlow\" type=\"LimiterConfig\"}\nLong-window slow limiter keyed by IP.\n::\n\n::field{name=\"subLimiter\" type=\"LimiterConfig\"}\nPer-subject limiter that limits attempts per OAuth subject identifier.\n::\n\n::field{name=\"compositeKeyLimiter\" type=\"LimiterConfig\"}\nComposite key limiter combining IP and subject for fine-grained control.\n::\n::\n\n---\n\n### `signupLimiters`\n\nProtects `POST \u002Fsignup`.\n\n::field-group\n::field{name=\"unionLimiters.uniLimiterIp.ipLimit\" type=\"LimiterConfig\"}\nShort-window IP burst limiter for signups.\n::\n\n::field{name=\"unionLimiters.uniLimiterIp.slowIpLimit\" type=\"LimiterConfig\"}\nLong-window IP slow limiter for signups.\n::\n\n::field{name=\"unionLimiters.uniLimiterComposite.compositeKeyLimit\" type=\"LimiterConfig\"}\nShort-window composite key (IP + email) burst limiter.\n::\n\n::field{name=\"unionLimiters.uniLimiterComposite.slowCompositeKeyLimit\" type=\"LimiterConfig\"}\nLong-window composite key slow limiter.\n::\n\n::field{name=\"emailLimit\" type=\"LimiterConfig\"}\nPer-email limiter that prevents mass account creation with variations of the same address.\n::\n::\n\n---\n\n### `tempPostRoutesLimiters`\n\nProtects temporary POST routes such as email update and custom MFA initiation.\n\n::field-group\n::field{name=\"unionLimiters.limit\" type=\"LimiterConfig\"}\nShort-window burst limiter.\n::\n\n::field{name=\"unionLimiters.slowLimit\" type=\"LimiterConfig\"}\nLong-window slow limiter.\n::\n\n::field{name=\"ipLimit\" type=\"LimiterConfig\"}\nPer-IP limiter applied independently of the union limiter.\n::\n::\n\n---\n\n### `tokenLimiters`\n\nProtects the `\u002Fauth\u002Fuser\u002Frefresh-session` rotation route and the `\u002Fauth\u002Flogout` route.\n\n::field-group\n::field{name=\"unionLimiters.refreshAccessTokenLimiter.accessTokenBrute\" type=\"LimiterConfig\"}\nShort-window burst limiter for access token refresh.\n::\n\n::field{name=\"unionLimiters.refreshAccessTokenLimiter.accessTokenSlow\" type=\"LimiterConfig\"}\nLong-window slow limiter for access token refresh.\n::\n\n::field{name=\"unionLimiters.refreshTokenLimiterUnion.refreshTokenBrute\" type=\"LimiterConfig\"}\nShort-window burst limiter for refresh token rotation.\n::\n\n::field{name=\"unionLimiters.refreshTokenLimiterUnion.refreshTokenSlow\" type=\"LimiterConfig\"}\nLong-window slow limiter for refresh token rotation.\n::\n\n::field{name=\"refreshTokenLimiter\" type=\"LimiterConfig\"}\nStandalone limiter applied to all refresh token operations.\n::\n::\n\n---\n\n### `initPasswordResetLimiters`\n\nProtects `POST \u002Fauth\u002Fforgot-password`.\n\n::field-group\n::field{name=\"unionLimiters.limit\" type=\"LimiterConfig\"}\nShort-window burst limiter.\n::\n\n::field{name=\"unionLimiters.longLimiter\" type=\"LimiterConfig\"}\nLong-window slow limiter.\n::\n\n::field{name=\"ipLimiter\" type=\"LimiterConfig\"}\nPer-IP limiter.\n::\n\n::field{name=\"emailLimiter\" type=\"LimiterConfig\"}\nPer-email limiter that prevents password-reset spam against a single account.\n::\n::\n\n---\n\n### `emailMfaLimiters`\n\nProtects email MFA sending endpoints.\n\n::field-group\n::field{name=\"unionLimiters.limit\" type=\"LimiterConfig\"}\nShort-window burst limiter.\n::\n\n::field{name=\"unionLimiters.longLimiter\" type=\"LimiterConfig\"}\nLong-window slow limiter.\n::\n\n::field{name=\"ipLimiter\" type=\"LimiterConfig\"}\nPer-IP limiter.\n::\n\n::field{name=\"userIdLimiter\" type=\"LimiterConfig\"}\nPer-user limiter that prevents a single user from triggering excessive MFA emails.\n::\n\n::field{name=\"globalEmailLimiter\" type=\"LimiterConfig\"}\nGlobal limiter that caps the total number of MFA emails sent across all users. Protects your Resend quota from abuse.\n::\n::\n\n---\n\n## `logLevel`\n\n::field{name=\"logLevel\" type=\"'trace' | 'debug' | 'info' | 'warn' | 'error' | 'fatal'\"}\nPino log level for the service logger. Use `'debug'` during development to see detailed request processing. Set `'warn'` or `'error'` in production to reduce log volume.\n::\n",{"title":237,"description":2961},"4B7NlJ2yRWJzsIxVZ20_zqv5j0kCP6E3Yq0y29-sfGk",[2970,2971],{"title":233,"path":234,"stem":235,"children":-1},{"title":246,"path":247,"stem":248,"children":-1},{"id":851,"title":237,"body":2973,"description":2961,"extension":2962,"icon":2963,"meta":4539,"module":2965,"navigation":8,"path":238,"rawbody":2966,"seo":4540,"stem":239,"__hash__":2968},{"type":853,"value":2974,"toc":4506},[2975,2982,3160,3166,3168,3172,3179,3189,3199,3303,3307,3309,3313,3315,3341,3357,3377,3379,3383,3387,3411,3417,3419,3423,3429,3451,3519,3521,3527,3555,3557,3559,3563,3567,3581,3583,3587,3593,3645,3649,3651,3665,3679,3693,3697,3699,3717,3721,3725,3729,3749,3753,3755,3779,3781,3785,3787,3789,3793,3909,3913,4025,4059,4063,4065,4069,4077,4079,4083,4085,4099,4103,4173,4177,4201,4205,4207,4211,4213,4230,4232,4236,4238,4262,4266,4270,4276,4286,4288,4292,4296,4314,4316,4320,4324,4342,4344,4348,4352,4374,4376,4380,4382,4396,4398,4402,4408,4430,4432,4436,4440,4458,4460,4464,4466,4488,4490,4494,4504],[856,2976,858,2977,863,2979,871],{},[860,2978,862],{},[865,2980,870],{"href":867,"rel":2981},[869],[873,2983,2984],{"className":875,"code":876,"filename":877,"language":878,"meta":879,"style":879},[860,2985,2986,3004,3008,3016,3028,3054,3070,3094,3106,3118,3156],{"__ignoreMap":879},[883,2987,2988,2990,2992,2994,2996,2998,3000,3002],{"class":885,"line":886},[883,2989,890],{"class":889},[883,2991,894],{"class":893},[883,2993,898],{"class":897},[883,2995,901],{"class":893},[883,2997,904],{"class":889},[883,2999,908],{"class":907},[883,3001,912],{"class":911},[883,3003,915],{"class":907},[883,3005,3006],{"class":885,"line":918},[883,3007,921],{"emptyLinePlaceholder":8},[883,3009,3010,3012,3014],{"class":885,"line":924},[883,3011,927],{"class":889},[883,3013,931],{"class":930},[883,3015,934],{"class":893},[883,3017,3018,3020,3022,3024,3026],{"class":885,"line":937},[883,3019,940],{"class":897},[883,3021,944],{"class":943},[883,3023,894],{"class":893},[883,3025,950],{"class":949},[883,3027,953],{"class":893},[883,3029,3030,3032,3034,3036,3038,3040,3042,3044,3046,3048,3050,3052],{"class":885,"line":956},[883,3031,959],{"class":897},[883,3033,944],{"class":943},[883,3035,894],{"class":893},[883,3037,966],{"class":897},[883,3039,944],{"class":943},[883,3041,971],{"class":897},[883,3043,974],{"class":893},[883,3045,977],{"class":897},[883,3047,974],{"class":893},[883,3049,983],{"class":982},[883,3051,987],{"class":986},[883,3053,953],{"class":893},[883,3055,3056,3058,3060,3062,3064,3066,3068],{"class":885,"line":992},[883,3057,995],{"class":897},[883,3059,944],{"class":943},[883,3061,894],{"class":893},[883,3063,1002],{"class":897},[883,3065,944],{"class":943},[883,3067,1008],{"class":1007},[883,3069,953],{"class":893},[883,3071,3072,3074,3076,3078,3080,3082,3084,3086,3088,3090,3092],{"class":885,"line":1013},[883,3073,1016],{"class":897},[883,3075,944],{"class":943},[883,3077,894],{"class":893},[883,3079,1023],{"class":897},[883,3081,944],{"class":943},[883,3083,1029],{"class":1028},[883,3085,1032],{"class":893},[883,3087,1035],{"class":897},[883,3089,944],{"class":943},[883,3091,1040],{"class":1028},[883,3093,953],{"class":893},[883,3095,3096,3098,3100,3102,3104],{"class":885,"line":1045},[883,3097,1048],{"class":897},[883,3099,944],{"class":943},[883,3101,894],{"class":893},[883,3103,950],{"class":949},[883,3105,953],{"class":893},[883,3107,3108,3110,3112,3114,3116],{"class":885,"line":1059},[883,3109,1062],{"class":897},[883,3111,944],{"class":943},[883,3113,894],{"class":893},[883,3115,950],{"class":949},[883,3117,953],{"class":893},[883,3119,3120,3122,3124,3126,3128,3130,3132,3134,3136,3138,3140,3142,3144,3146,3148,3150,3152,3154],{"class":885,"line":1073},[883,3121,1076],{"class":897},[883,3123,944],{"class":943},[883,3125,894],{"class":893},[883,3127,1083],{"class":897},[883,3129,944],{"class":943},[883,3131,971],{"class":897},[883,3133,974],{"class":893},[883,3135,977],{"class":897},[883,3137,974],{"class":893},[883,3139,1096],{"class":982},[883,3141,987],{"class":986},[883,3143,1032],{"class":893},[883,3145,1103],{"class":897},[883,3147,944],{"class":943},[883,3149,908],{"class":907},[883,3151,1110],{"class":911},[883,3153,1113],{"class":907},[883,3155,953],{"class":893},[883,3157,3158],{"class":885,"line":1118},[883,3159,1121],{"class":893},[1123,3161,3162],{},[856,3163,1127,3164,1130],{},[860,3165,862],{},[1132,3167],{},[1135,3169,3170],{"id":1137},[860,3171,1137],{},[856,3173,1142,3174,1151],{},[865,3175,1147,3177],{"href":1145,"rel":3176},[869],[860,3178,1150],{},[1153,3180,3181,3185],{},[1156,3182,3183],{"name":1158,"type":1159,":required":1160},[856,3184,1163],{},[1156,3186,3187],{"name":1166,"type":1167,":required":1160},[856,3188,1170],{},[1153,3190,3191,3195],{"name":1166},[1156,3192,3193],{"name":1137,"type":1159,":required":1160},[856,3194,1177],{},[1156,3196,3197],{"name":1180,"type":1181,":required":1160},[856,3198,1184],{},[873,3200,3201],{"className":875,"code":1187,"filename":877,"language":878,"meta":879,"style":879},[860,3202,3203,3207,3243,3247,3283,3295,3299],{"__ignoreMap":879},[883,3204,3205],{"class":885,"line":886},[883,3206,1194],{"class":893},[883,3208,3209,3211,3213,3215,3217,3219,3221,3223,3225,3227,3229,3231,3233,3235,3237,3239,3241],{"class":885,"line":918},[883,3210,1199],{"class":893},[883,3212,1113],{"class":907},[883,3214,1204],{"class":911},[883,3216,1113],{"class":907},[883,3218,1209],{"class":893},[883,3220,1113],{"class":907},[883,3222,1214],{"class":911},[883,3224,1113],{"class":907},[883,3226,1219],{"class":893},[883,3228,1113],{"class":907},[883,3230,1224],{"class":911},[883,3232,1113],{"class":907},[883,3234,1229],{"class":893},[883,3236,1113],{"class":907},[883,3238,1234],{"class":911},[883,3240,1113],{"class":907},[883,3242,953],{"class":893},[883,3244,3245],{"class":885,"line":924},[883,3246,1243],{"class":893},[883,3248,3249,3251,3253,3255,3257,3259,3261,3263,3265,3267,3269,3271,3273,3275,3277,3279,3281],{"class":885,"line":937},[883,3250,1248],{"class":893},[883,3252,1113],{"class":907},[883,3254,1204],{"class":911},[883,3256,1113],{"class":907},[883,3258,1209],{"class":893},[883,3260,1113],{"class":907},[883,3262,1214],{"class":911},[883,3264,1113],{"class":907},[883,3266,1219],{"class":893},[883,3268,1113],{"class":907},[883,3270,1224],{"class":911},[883,3272,1113],{"class":907},[883,3274,1229],{"class":893},[883,3276,1113],{"class":907},[883,3278,1277],{"class":911},[883,3280,1113],{"class":907},[883,3282,953],{"class":893},[883,3284,3285,3287,3289,3291,3293],{"class":885,"line":956},[883,3286,1286],{"class":893},[883,3288,1113],{"class":907},[883,3290,1277],{"class":911},[883,3292,1113],{"class":907},[883,3294,1295],{"class":893},[883,3296,3297],{"class":885,"line":992},[883,3298,1300],{"class":893},[883,3300,3301],{"class":885,"line":1013},[883,3302,1305],{"class":893},[1307,3304,3305],{},[856,3306,1311],{},[1132,3308],{},[1135,3310,3311],{"id":1316},[860,3312,1316],{},[856,3314,1321],{},[1153,3316,3317,3323,3329,3333,3337],{},[1156,3318,3319],{"name":1326,"type":1167},[856,3320,1329,3321,1333],{},[865,3322,1332],{"href":136},[1156,3324,3325],{"name":1336,"type":1167,":required":1160},[856,3326,1339,3327,1342],{},[860,3328,1316],{},[1156,3330,3331],{"name":1345,"type":1346},[856,3332,1349],{},[1156,3334,3335],{"name":1352,"type":1181},[856,3336,1355],{},[1156,3338,3339],{"name":1358,"type":1181},[856,3340,1361],{},[1153,3342,3343,3347,3351],{"name":1326},[1156,3344,3345],{"name":1366,"type":1181,":required":1160},[856,3346,1369],{},[1156,3348,3349],{"name":1372,"type":1181,":required":1160},[856,3350,1375],{},[1156,3352,3353],{"name":1378,"type":1346,":required":1160},[856,3354,1381,3355,1385],{},[860,3356,1384],{},[1153,3358,3359,3367,3373],{"name":1336},[1156,3360,3361],{"name":1390,"type":1391,":required":1160},[856,3362,1394,3363,1398,3365,1401],{},[860,3364,1397],{},[860,3366,1160],{},[1156,3368,3369],{"name":1404,"type":1181,":required":1160},[856,3370,1407,3371,1410],{},[860,3372,1397],{},[1156,3374,3375],{"name":1413,"type":1181},[856,3376,1416],{},[1132,3378],{},[1135,3380,3381],{"id":1421},[860,3382,1421],{},[856,3384,1426,3385,1429],{},[860,3386,966],{},[1153,3388,3389,3393,3399,3405],{},[1156,3390,3391],{"name":966,"type":1181,":required":1160},[856,3392,1436],{},[1156,3394,3395],{"name":1439,"type":1346},[856,3396,1442,3397,1446],{},[860,3398,1445],{},[1156,3400,3401],{"name":1449,"type":1346},[856,3402,1442,3403,1455],{},[860,3404,1454],{},[1156,3406,3407],{"name":1458,"type":1346},[856,3408,1442,3409,1464],{},[860,3410,1463],{},[1123,3412,3413],{},[856,3414,1469,3415,1472],{},[860,3416,966],{},[1132,3418],{},[1135,3420,3421],{"id":1477},[860,3422,1480],{},[856,3424,1483,3425,1486,3427,974],{},[865,3426,399],{"href":35},[860,3428,1002],{},[1153,3430,3431,3441],{},[1156,3432,3433],{"name":1002,"type":1391,":required":1160},[856,3434,1495,3435,1498,3437,1502,3439,1507],{},[860,3436,1160],{},[860,3438,1501],{},[1504,3440,1506],{},[1156,3442,3443],{"name":1510,"type":1511},[856,3444,1514,3445,1517,3447,1520,3449,1524],{},[860,3446,1002],{},[860,3448,1160],{},[865,3450,1523],{"href":514},[873,3452,3453],{"className":875,"code":1527,"language":878,"meta":879,"style":879},[860,3454,3455,3459,3467,3471,3475,3483,3487,3491,3495,3503,3515],{"__ignoreMap":879},[883,3456,3457],{"class":885,"line":886},[883,3458,1534],{"class":949},[883,3460,3461,3463,3465],{"class":885,"line":918},[883,3462,1539],{"class":893},[883,3464,1501],{"class":1007},[883,3466,1544],{"class":893},[883,3468,3469],{"class":885,"line":924},[883,3470,921],{"emptyLinePlaceholder":8},[883,3472,3473],{"class":885,"line":937},[883,3474,1553],{"class":949},[883,3476,3477,3479,3481],{"class":885,"line":956},[883,3478,1539],{"class":893},[883,3480,1160],{"class":1007},[883,3482,1544],{"class":893},[883,3484,3485],{"class":885,"line":992},[883,3486,921],{"emptyLinePlaceholder":8},[883,3488,3489],{"class":885,"line":1013},[883,3490,1570],{"class":949},[883,3492,3493],{"class":885,"line":1045},[883,3494,1575],{"class":893},[883,3496,3497,3499,3501],{"class":885,"line":1059},[883,3498,1580],{"class":893},[883,3500,1160],{"class":1007},[883,3502,1295],{"class":893},[883,3504,3505,3507,3509,3511,3513],{"class":885,"line":1073},[883,3506,1589],{"class":893},[883,3508,1592],{"class":1028},[883,3510,1595],{"class":893},[883,3512,1501],{"class":1007},[883,3514,1600],{"class":893},[883,3516,3517],{"class":885,"line":1118},[883,3518,1305],{"class":893},[1606,3520,1609],{"id":1608},[856,3522,1612,3523,1615,3525,1618],{},[860,3524,1002],{},[860,3526,1501],{},[1620,3528,3529,3531,3539,3547],{},[1623,3530,1625],{},[1623,3532,3533,1631,3535,1615,3537,1638],{},[860,3534,1630],{},[860,3536,1634],{},[860,3538,1637],{},[1623,3540,3541,1644,3543,1615,3545,1651],{},[860,3542,1643],{},[860,3544,1647],{},[860,3546,1650],{},[1623,3548,3549,1657,3551,1615,3553,1664],{},[860,3550,1656],{},[860,3552,1660],{},[860,3554,1663],{},[856,3556,1667],{},[1132,3558],{},[1135,3560,3561],{"id":1672},[860,3562,1675],{},[856,3564,1678,3565,1681],{},[865,3566,139],{"href":140},[1153,3568,3569,3575],{},[1156,3570,3571],{"name":1023,"type":1346,":required":1160},[856,3572,1442,3573,1690],{},[860,3574,1445],{},[1156,3576,3577],{"name":1035,"type":1346,":required":1160},[856,3578,1442,3579,1698],{},[860,3580,1697],{},[1132,3582],{},[1135,3584,3585],{"id":1703},[860,3586,1703],{},[856,3588,1708,3589,1711,3591,1714],{},[865,3590,115],{"href":116},[865,3592,123],{"href":124},[1153,3594,3595,3599,3609,3615,3619,3623,3627,3633,3637,3641],{},[1156,3596,3597],{"name":1719,"type":1181,":required":1160},[856,3598,1722],{},[1156,3600,3601],{"name":1725,"type":1726},[856,3602,1729,3603,1733,3605,1737,3607,974],{},[860,3604,1732],{},[860,3606,1736],{},[860,3608,1740],{},[1156,3610,3611],{"name":1740,"type":1346},[856,3612,1745,3613,974],{},[860,3614,1725],{},[1156,3616,3617],{"name":1750,"type":1181,":required":1160},[856,3618,1753],{},[1156,3620,3621],{"name":1756,"type":1346},[856,3622,1759],{},[1156,3624,3625],{"name":1762,"type":1167},[856,3626,1765],{},[1156,3628,3629],{"name":1768,"type":1181},[856,3630,1442,3631,1774],{},[860,3632,1773],{},[1156,3634,3635],{"name":1777,"type":1167},[856,3636,1780],{},[1156,3638,3639],{"name":1783,"type":1167},[856,3640,1786],{},[1156,3642,3643],{"name":1789,"type":1167,":required":1160},[856,3644,1792],{},[1606,3646,3647],{"id":1762},[860,3648,1762],{},[856,3650,1799],{},[1153,3652,3653,3659],{"name":1802},[1156,3654,3655],{"name":1805,"type":1346},[856,3656,1442,3657,1811],{},[860,3658,1810],{},[1156,3660,3661],{"name":1814,"type":1346},[856,3662,1442,3663,1820],{},[860,3664,1819],{},[1153,3666,3667,3673],{"name":1823},[1156,3668,3669],{"name":1805,"type":1346},[856,3670,1442,3671,1830],{},[860,3672,1810],{},[1156,3674,3675],{"name":1814,"type":1346},[856,3676,1442,3677,1837],{},[860,3678,1819],{},[1153,3680,3681,3687],{"name":1840},[1156,3682,3683],{"name":1805,"type":1346},[856,3684,1442,3685,1847],{},[860,3686,1810],{},[1156,3688,3689],{"name":1814,"type":1346},[856,3690,1442,3691,1854],{},[860,3692,1819],{},[1606,3694,3695],{"id":1857},[860,3696,1777],{},[856,3698,1862],{},[1153,3700,3701,3705,3709,3713],{"name":1865},[1156,3702,3703],{"name":1868,"type":1181},[856,3704,1871],{},[1156,3706,3707],{"name":1874,"type":1181},[856,3708,1877],{},[1156,3710,3711],{"name":1880,"type":1181},[856,3712,1883],{},[1156,3714,3715],{"name":1886,"type":1181},[856,3716,1889],{},[1156,3718,3719],{"name":1892,"type":1181},[856,3720,1895],{},[1606,3722,3723],{"id":1783},[860,3724,1783],{},[856,3726,1902,3727,974],{},[860,3728,1905],{},[1153,3730,3731,3737,3743],{},[1156,3732,3733],{"name":1910,"type":1181},[856,3734,1442,3735,1916],{},[860,3736,1915],{},[1156,3738,3739],{"name":1919,"type":1181},[856,3740,1442,3741,1924],{},[860,3742,1915],{},[1156,3744,3745],{"name":1927,"type":1181},[856,3746,1442,3747,1932],{},[860,3748,1915],{},[1606,3750,3751],{"id":1935},[860,3752,1789],{},[856,3754,1940],{},[1153,3756,3757,3763,3767,3771,3775],{},[1156,3758,3759],{"name":1945,"type":1181},[856,3760,1442,3761,1951],{},[860,3762,1950],{},[1156,3764,3765],{"name":1954,"type":1181,":required":1160},[856,3766,1957],{},[1156,3768,3769],{"name":1960,"type":1181,":required":1160},[856,3770,1963],{},[1156,3772,3773],{"name":1966,"type":1181,":required":1160},[856,3774,1969],{},[1156,3776,3777],{"name":1972,"type":1181,":required":1160},[856,3778,1975],{},[1132,3780],{},[1135,3782,3783],{"id":1980},[860,3784,1980],{},[856,3786,1985],{},[856,3788,1988],{},[856,3790,3791,1994],{},[1504,3792,1993],{},[873,3794,3795],{"className":875,"code":1997,"language":878,"meta":879,"style":879},[860,3796,3797,3801,3805,3819,3833,3847,3861,3879,3897,3901,3905],{"__ignoreMap":879},[883,3798,3799],{"class":885,"line":886},[883,3800,2004],{"class":893},[883,3802,3803],{"class":885,"line":918},[883,3804,2009],{"class":893},[883,3806,3807,3809,3811,3813,3815,3817],{"class":885,"line":924},[883,3808,2014],{"class":897},[883,3810,944],{"class":943},[883,3812,908],{"class":907},[883,3814,2021],{"class":911},[883,3816,1113],{"class":907},[883,3818,1295],{"class":893},[883,3820,3821,3823,3825,3827,3829,3831],{"class":885,"line":937},[883,3822,2030],{"class":897},[883,3824,944],{"class":943},[883,3826,2035],{"class":897},[883,3828,974],{"class":893},[883,3830,1167],{"class":930},[883,3832,934],{"class":893},[883,3834,3835,3837,3839,3841,3843,3845],{"class":885,"line":956},[883,3836,2046],{"class":897},[883,3838,944],{"class":943},[883,3840,2035],{"class":897},[883,3842,974],{"class":893},[883,3844,1346],{"class":930},[883,3846,2057],{"class":893},[883,3848,3849,3851,3853,3855,3857,3859],{"class":885,"line":992},[883,3850,2062],{"class":897},[883,3852,944],{"class":943},[883,3854,2035],{"class":897},[883,3856,974],{"class":893},[883,3858,1181],{"class":930},[883,3860,2057],{"class":893},[883,3862,3863,3865,3867,3869,3871,3873,3875,3877],{"class":885,"line":1013},[883,3864,2077],{"class":897},[883,3866,944],{"class":943},[883,3868,2035],{"class":897},[883,3870,974],{"class":893},[883,3872,1181],{"class":930},[883,3874,2088],{"class":893},[883,3876,1103],{"class":930},[883,3878,2057],{"class":893},[883,3880,3881,3883,3885,3887,3889,3891,3893,3895],{"class":885,"line":1045},[883,3882,2097],{"class":897},[883,3884,944],{"class":943},[883,3886,2035],{"class":897},[883,3888,974],{"class":893},[883,3890,1181],{"class":930},[883,3892,2088],{"class":893},[883,3894,2110],{"class":930},[883,3896,2057],{"class":893},[883,3898,3899],{"class":885,"line":1059},[883,3900,2117],{"class":893},[883,3902,3903],{"class":885,"line":1073},[883,3904,1300],{"class":893},[883,3906,3907],{"class":885,"line":1118},[883,3908,2126],{"class":893},[856,3910,3911,2132],{},[1504,3912,2131],{},[873,3914,3915],{"className":875,"code":2135,"language":878,"meta":879,"style":879},[860,3916,3917,3921,3925,3939,3949,3957,3971,3985,3999,4013,4017,4021],{"__ignoreMap":879},[883,3918,3919],{"class":885,"line":886},[883,3920,2004],{"class":893},[883,3922,3923],{"class":885,"line":918},[883,3924,2009],{"class":893},[883,3926,3927,3929,3931,3933,3935,3937],{"class":885,"line":924},[883,3928,2014],{"class":897},[883,3930,944],{"class":943},[883,3932,908],{"class":907},[883,3934,2156],{"class":911},[883,3936,1113],{"class":907},[883,3938,1295],{"class":893},[883,3940,3941,3943,3945,3947],{"class":885,"line":937},[883,3942,2165],{"class":897},[883,3944,944],{"class":943},[883,3946,1008],{"class":1007},[883,3948,1295],{"class":893},[883,3950,3951,3953,3955],{"class":885,"line":956},[883,3952,2176],{"class":897},[883,3954,944],{"class":943},[883,3956,2181],{"class":893},[883,3958,3959,3961,3963,3965,3967,3969],{"class":885,"line":992},[883,3960,2186],{"class":897},[883,3962,944],{"class":943},[883,3964,908],{"class":907},[883,3966,1181],{"class":911},[883,3968,1113],{"class":907},[883,3970,1295],{"class":893},[883,3972,3973,3975,3977,3979,3981,3983],{"class":885,"line":1013},[883,3974,2077],{"class":897},[883,3976,944],{"class":943},[883,3978,908],{"class":907},[883,3980,1103],{"class":911},[883,3982,1113],{"class":907},[883,3984,1295],{"class":893},[883,3986,3987,3989,3991,3993,3995,3997],{"class":885,"line":1045},[883,3988,2215],{"class":897},[883,3990,944],{"class":943},[883,3992,908],{"class":907},[883,3994,2222],{"class":911},[883,3996,1113],{"class":907},[883,3998,1295],{"class":893},[883,4000,4001,4003,4005,4007,4009,4011],{"class":885,"line":1059},[883,4002,2231],{"class":897},[883,4004,944],{"class":943},[883,4006,908],{"class":907},[883,4008,2238],{"class":911},[883,4010,1113],{"class":907},[883,4012,1295],{"class":893},[883,4014,4015],{"class":885,"line":1073},[883,4016,2247],{"class":893},[883,4018,4019],{"class":885,"line":1118},[883,4020,1300],{"class":893},[883,4022,4023],{"class":885,"line":2254},[883,4024,2126],{"class":893},[856,4026,4027,2262,4029,1032,4031,1032,4033,1032,4035,1032,4037,1032,4039,1032,4041,1032,4043,1032,4045,1032,4047,1032,4049,1032,4051,1032,4053,1032,4055,2305,4057,2309],{},[860,4028,2261],{},[860,4030,2265],{},[860,4032,2268],{},[860,4034,2271],{},[860,4036,2274],{},[860,4038,2277],{},[860,4040,2280],{},[860,4042,2283],{},[860,4044,2286],{},[860,4046,2289],{},[860,4048,2292],{},[860,4050,2295],{},[860,4052,2298],{},[860,4054,2301],{},[860,4056,2304],{},[860,4058,2308],{},[856,4060,2312,4061,2316],{},[865,4062,111],{"href":2315},[1132,4064],{},[1135,4066,4067],{"id":2321},[860,4068,2324],{},[1156,4070,4071],{"name":2324,"type":1391},[856,4072,1442,4073,2331,4075,2334],{},[860,4074,1501],{},[860,4076,1160],{},[1132,4078],{},[1135,4080,4081],{"id":2339},[860,4082,2339],{},[856,4084,2344],{},[1153,4086,4087,4091,4095],{},[1156,4088,4089],{"name":1719,"type":1181,":required":1160},[856,4090,2351],{},[1156,4092,4093],{"name":2354,"type":1167,":required":1160},[856,4094,2357],{},[1156,4096,4097],{"name":2360,"type":1167,":required":1160},[856,4098,2363],{},[1606,4100,4101],{"id":2354},[860,4102,2354],{},[1153,4104,4105,4113,4119,4147,4153,4159,4165,4169],{},[1156,4106,4107],{"name":1725,"type":1726},[856,4108,1729,4109,2377,4111,974],{},[860,4110,2376],{},[860,4112,1740],{},[1156,4114,4115],{"name":1740,"type":1346},[856,4116,1745,4117,974],{},[860,4118,1725],{},[1156,4120,4121],{"name":2388,"type":1181},[856,4122,2391,4123,1032,4125,1032,4127,1032,4129,1032,4131,1032,4133,1032,4135,1032,4137,1032,4139,1032,4141,1032,4143,1032,4145,974],{},[860,4124,2394],{},[860,4126,2397],{},[860,4128,2400],{},[860,4130,2403],{},[860,4132,2406],{},[860,4134,2409],{},[860,4136,2412],{},[860,4138,2415],{},[860,4140,2418],{},[860,4142,2421],{},[860,4144,2424],{},[860,4146,2427],{},[1156,4148,4149],{"name":2430,"type":1181},[856,4150,4151,2436],{},[860,4152,2435],{},[1156,4154,4155],{"name":2439,"type":1181},[856,4156,4157,2436],{},[860,4158,2444],{},[1156,4160,4161],{"name":2447,"type":1181},[856,4162,4163,2436],{},[860,4164,2452],{},[1156,4166,4167],{"name":1756,"type":1346},[856,4168,2457],{},[1156,4170,4171],{"name":2460,"type":2461},[856,4172,2464],{},[1606,4174,4175],{"id":2360},[860,4176,2360],{},[1153,4178,4179,4183,4189,4193,4197],{},[1156,4180,4181],{"name":2473,"type":1346,":required":1160},[856,4182,2476],{},[1156,4184,4185],{"name":1750,"type":1181,":required":1160},[856,4186,2481,4187,2485],{},[860,4188,2484],{},[1156,4190,4191],{"name":2488,"type":1346,":required":1160},[856,4192,2491],{},[1156,4194,4195],{"name":2494,"type":1346,":required":1160},[856,4196,2497],{},[1156,4198,4199],{"name":2500,"type":1346,":required":1160},[856,4200,2503],{},[856,4202,2312,4203,2508],{},[865,4204,83],{"href":84},[1132,4206],{},[1135,4208,4209],{"id":1103},[860,4210,1103],{},[856,4212,2517],{},[1153,4214,4215,4222],{},[1156,4216,4217],{"name":1083,"type":1181,":required":1160},[856,4218,2524,4219,2530],{},[865,4220,2529],{"href":2527,"rel":4221},[869],[1156,4223,4224],{"name":1103,"type":1181,":required":1160},[856,4225,2535,4226,2539,4228,2543],{},[860,4227,2538],{},[860,4229,2542],{},[1132,4231],{},[1135,4233,4234],{"id":2548},[860,4235,2548],{},[856,4237,2553],{},[1153,4239,4240,4244,4250,4254,4258],{},[1156,4241,4242],{"name":2558,"type":1346},[856,4243,2561],{},[1156,4245,4246],{"name":2564,"type":1346},[856,4247,2567,4248,2571],{},[860,4249,2570],{},[1156,4251,4252],{"name":2570,"type":1346},[856,4253,2576],{},[1156,4255,4256],{"name":2579,"type":1346},[856,4257,2582],{},[1156,4259,4260],{"name":2585,"type":1346},[856,4261,2588],{},[856,4263,2312,4264,2594],{},[865,4265,147],{"href":2593},[1606,4267,4268],{"id":2597},[860,4269,2600],{},[856,4271,2603,4272,1711,4274,2610],{},[860,4273,2606],{},[860,4275,2609],{},[1153,4277,4278,4282],{},[1156,4279,4280],{"name":2615,"type":2616},[856,4281,2619],{},[1156,4283,4284],{"name":2622,"type":2616},[856,4285,2625],{},[1132,4287],{},[1606,4289,4290],{"id":2630},[860,4291,2633],{},[856,4293,2603,4294,974],{},[860,4295,2638],{},[1153,4297,4298,4302,4306,4310],{},[1156,4299,4300],{"name":2615,"type":2616},[856,4301,2645],{},[1156,4303,4304],{"name":2622,"type":2616},[856,4305,2650],{},[1156,4307,4308],{"name":2653,"type":2616},[856,4309,2656],{},[1156,4311,4312],{"name":2659,"type":2616},[856,4313,2662],{},[1132,4315],{},[1606,4317,4318],{"id":2667},[860,4319,2670],{},[856,4321,2603,4322,974],{},[860,4323,2675],{},[1153,4325,4326,4330,4334,4338],{},[1156,4327,4328],{"name":2680,"type":2616},[856,4329,2683],{},[1156,4331,4332],{"name":2686,"type":2616},[856,4333,2689],{},[1156,4335,4336],{"name":2692,"type":2616},[856,4337,2695],{},[1156,4339,4340],{"name":2698,"type":2616},[856,4341,2701],{},[1132,4343],{},[1606,4345,4346],{"id":2706},[860,4347,2709],{},[856,4349,2603,4350,974],{},[860,4351,2714],{},[1153,4353,4354,4358,4362,4366,4370],{},[1156,4355,4356],{"name":2719,"type":2616},[856,4357,2722],{},[1156,4359,4360],{"name":2725,"type":2616},[856,4361,2728],{},[1156,4363,4364],{"name":2731,"type":2616},[856,4365,2734],{},[1156,4367,4368],{"name":2737,"type":2616},[856,4369,2740],{},[1156,4371,4372],{"name":2743,"type":2616},[856,4373,2746],{},[1132,4375],{},[1606,4377,4378],{"id":2751},[860,4379,2754],{},[856,4381,2757],{},[1153,4383,4384,4388,4392],{},[1156,4385,4386],{"name":2762,"type":2616},[856,4387,2765],{},[1156,4389,4390],{"name":2768,"type":2616},[856,4391,2771],{},[1156,4393,4394],{"name":2774,"type":2616},[856,4395,2656],{},[1132,4397],{},[1606,4399,4400],{"id":2781},[860,4401,2784],{},[856,4403,2787,4404,2791,4406,2795],{},[860,4405,2790],{},[860,4407,2794],{},[1153,4409,4410,4414,4418,4422,4426],{},[1156,4411,4412],{"name":2800,"type":2616},[856,4413,2803],{},[1156,4415,4416],{"name":2806,"type":2616},[856,4417,2809],{},[1156,4419,4420],{"name":2812,"type":2616},[856,4421,2815],{},[1156,4423,4424],{"name":2818,"type":2616},[856,4425,2821],{},[1156,4427,4428],{"name":2824,"type":2616},[856,4429,2827],{},[1132,4431],{},[1606,4433,4434],{"id":2832},[860,4435,2835],{},[856,4437,2603,4438,974],{},[860,4439,2840],{},[1153,4441,4442,4446,4450,4454],{},[1156,4443,4444],{"name":2762,"type":2616},[856,4445,2765],{},[1156,4447,4448],{"name":2849,"type":2616},[856,4449,2771],{},[1156,4451,4452],{"name":2653,"type":2616},[856,4453,2856],{},[1156,4455,4456],{"name":2659,"type":2616},[856,4457,2861],{},[1132,4459],{},[1606,4461,4462],{"id":2866},[860,4463,2869],{},[856,4465,2872],{},[1153,4467,4468,4472,4476,4480,4484],{},[1156,4469,4470],{"name":2762,"type":2616},[856,4471,2765],{},[1156,4473,4474],{"name":2849,"type":2616},[856,4475,2771],{},[1156,4477,4478],{"name":2653,"type":2616},[856,4479,2856],{},[1156,4481,4482],{"name":2889,"type":2616},[856,4483,2892],{},[1156,4485,4486],{"name":2895,"type":2616},[856,4487,2898],{},[1132,4489],{},[1135,4491,4492],{"id":2903},[860,4493,1656],{},[1156,4495,4496],{"name":1656,"type":2908},[856,4497,2911,4498,2915,4500,2919,4502,2923],{},[860,4499,2914],{},[860,4501,2918],{},[860,4503,2922],{},[2925,4505,2927],{},{"title":879,"searchDepth":918,"depth":918,"links":4507},[4508,4509,4510,4511,4514,4515,4521,4522,4523,4527,4528,4538],{"id":1137,"depth":918,"text":1137},{"id":1316,"depth":918,"text":1316},{"id":1421,"depth":918,"text":1421},{"id":1477,"depth":918,"text":1480,"children":4512},[4513],{"id":1608,"depth":924,"text":1609},{"id":1672,"depth":918,"text":1675},{"id":1703,"depth":918,"text":1703,"children":4516},[4517,4518,4519,4520],{"id":1762,"depth":924,"text":1762},{"id":1857,"depth":924,"text":1777},{"id":1783,"depth":924,"text":1783},{"id":1935,"depth":924,"text":1789},{"id":1980,"depth":918,"text":1980},{"id":2321,"depth":918,"text":2324},{"id":2339,"depth":918,"text":2339,"children":4524},[4525,4526],{"id":2354,"depth":924,"text":2354},{"id":2360,"depth":924,"text":2360},{"id":1103,"depth":918,"text":1103},{"id":2548,"depth":918,"text":2548,"children":4529},[4530,4531,4532,4533,4534,4535,4536,4537],{"id":2597,"depth":924,"text":2600},{"id":2630,"depth":924,"text":2633},{"id":2667,"depth":924,"text":2670},{"id":2706,"depth":924,"text":2709},{"id":2751,"depth":924,"text":2754},{"id":2781,"depth":924,"text":2784},{"id":2832,"depth":924,"text":2835},{"id":2866,"depth":924,"text":2869},{"id":2903,"depth":918,"text":1656},{},{"title":237,"description":2961},1780436278918]