[{"data":1,"prerenderedAt":3524},["ShallowReactive",2],{"navLinks":3,"sidebar_docs_navigation_\u002Fdocs\u002Fiam":64,"navigation":257,"navLinks_footer":837,"\u002Fdocs\u002Fiam\u002Fessentials\u002Fsignup_page":850,"\u002Fdocs\u002Fiam\u002Fessentials\u002Fsignup_surround":2394,"\u002Fdocs\u002Fiam\u002Fessentials\u002Fsignup":2397},{"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":99,"body":852,"description":2386,"extension":2387,"icon":2388,"meta":2389,"module":2390,"navigation":8,"path":100,"rawbody":2391,"seo":2392,"stem":101,"__hash__":2393},"docs\u002Fdocs\u002Fiam\u002F01.essentials\u002F04.signup.md",{"type":853,"value":854,"toc":2373},"minimark",[855,864,867,870,875,913,919,929,944,951,953,957,1298,1317,1326,1328,1332,1335,1568,1570,1574,1581,1808,1810,1814,1819,1917,1920,1986,1994,1998,2054,2056,2060,2073,2104,2107,2109,2113,2120,2226,2236,2238,2242,2364,2369],[856,857,858,859,863],"p",{},"The signup route creates a new user account from an email, password, and name. Before the account is created, the request passes through six layers of validation: rate limiting, schema validation, email domain verification, disposable email detection, password breach checking, and password hashing. Only after all six layers pass does the service insert a row into the ",[860,861,862],"code",{},"users"," table and issue tokens.",[856,865,866],{},"No verification email is sent during signup. The user receives an access token and a refresh token immediately and is considered authenticated.",[868,869],"hr",{},[871,872,874],"h2",{"id":873},"route","Route",[876,877,878,894],"table",{},[879,880,881],"thead",{},[882,883,884,888,891],"tr",{},[885,886,887],"th",{},"Method",[885,889,890],{},"Path",[885,892,893],{},"Body limit",[895,896,897],"tbody",{},[882,898,899,905,910],{},[900,901,902],"td",{},[860,903,904],{},"POST",[900,906,907],{},[860,908,909],{},"\u002Fsignup",[900,911,912],{},"1 KB",[856,914,915],{},[916,917,918],"strong",{},"Middleware chain:",[920,921,926],"pre",{"className":922,"code":924,"language":925},[923],"language-text","validateContentType('application\u002Fjson'), express.json({ limit: '1kb' }), canary_id check, handleSignUp\n","text",[860,927,924],{"__ignoreMap":928},"",[856,930,931,932,935,936,939,940,943],{},"The ",[860,933,934],{},"canary_id"," cookie must be present. This cookie is set by the ",[937,938,399],"a",{"href":404}," on first contact and is used to look up the visitor record that will be linked to the new user. If the cookie is missing, the route returns ",[860,941,942],{},"400",".",[856,945,946,947,950],{},"See ",[937,948,949],{"href":255},"Routes"," for how to mount the authentication router on your Express application.",[868,952],{},[871,954,956],{"id":955},"request-body","Request body",[920,958,962],{"className":959,"code":960,"language":961,"meta":928,"style":928},"language-ts shiki shiki-themes light-plus light-plus dracula","import { z } from 'zod'\n\nconst signupSchema = z.strictObject({\n  name: z.string().min(2).max(72),               \u002F\u002F Lowercase-transformed, XSS-sanitized\n  email: z.string().min(10).max(80).email(),      \u002F\u002F Lowercase-transformed, XSS-sanitized\n  password: z.string().min(12).max(64),           \u002F\u002F Must match password policy regex\n  confirmedPassword: z.string().min(12).max(64),  \u002F\u002F Must match password\n  rememberUser: z.literal('on').optional(),        \u002F\u002F Checkbox toggle\n  termsConsent: z.literal('on'),                   \u002F\u002F Required acceptance\n}).refine(data => data.password === data.confirmedPassword)\n","ts",[860,963,964,998,1004,1031,1079,1121,1159,1195,1231,1259],{"__ignoreMap":928},[965,966,969,973,977,981,984,987,991,995],"span",{"class":967,"line":968},"line",1,[965,970,972],{"class":971},"sZ328","import",[965,974,976],{"class":975},"sDd4n"," { ",[965,978,980],{"class":979},"sjsA6","z",[965,982,983],{"class":975}," } ",[965,985,986],{"class":971},"from",[965,988,990],{"class":989},"sFkSl"," '",[965,992,994],{"class":993},"sFB1V","zod",[965,996,997],{"class":989},"'\n",[965,999,1001],{"class":967,"line":1000},2,[965,1002,1003],{"emptyLinePlaceholder":8},"\n",[965,1005,1007,1011,1015,1019,1022,1024,1028],{"class":967,"line":1006},3,[965,1008,1010],{"class":1009},"sl46w","const",[965,1012,1014],{"class":1013},"s3JHE"," signupSchema",[965,1016,1018],{"class":1017},"saOXh"," =",[965,1020,1021],{"class":979}," z",[965,1023,943],{"class":975},[965,1025,1027],{"class":1026},"sHOzp","strictObject",[965,1029,1030],{"class":975},"({\n",[965,1032,1034,1037,1041,1043,1045,1048,1051,1054,1057,1061,1064,1067,1069,1072,1075],{"class":967,"line":1033},4,[965,1035,1036],{"class":979},"  name",[965,1038,1040],{"class":1039},"s34zl",":",[965,1042,1021],{"class":979},[965,1044,943],{"class":975},[965,1046,1047],{"class":1026},"string",[965,1049,1050],{"class":975},"().",[965,1052,1053],{"class":1026},"min",[965,1055,1056],{"class":975},"(",[965,1058,1060],{"class":1059},"spgvN","2",[965,1062,1063],{"class":975},").",[965,1065,1066],{"class":1026},"max",[965,1068,1056],{"class":975},[965,1070,1071],{"class":1059},"72",[965,1073,1074],{"class":975},"),               ",[965,1076,1078],{"class":1077},"sghk6","\u002F\u002F Lowercase-transformed, XSS-sanitized\n",[965,1080,1082,1085,1087,1089,1091,1093,1095,1097,1099,1102,1104,1106,1108,1111,1113,1116,1119],{"class":967,"line":1081},5,[965,1083,1084],{"class":979},"  email",[965,1086,1040],{"class":1039},[965,1088,1021],{"class":979},[965,1090,943],{"class":975},[965,1092,1047],{"class":1026},[965,1094,1050],{"class":975},[965,1096,1053],{"class":1026},[965,1098,1056],{"class":975},[965,1100,1101],{"class":1059},"10",[965,1103,1063],{"class":975},[965,1105,1066],{"class":1026},[965,1107,1056],{"class":975},[965,1109,1110],{"class":1059},"80",[965,1112,1063],{"class":975},[965,1114,1115],{"class":1026},"email",[965,1117,1118],{"class":975},"(),      ",[965,1120,1078],{"class":1077},[965,1122,1124,1127,1129,1131,1133,1135,1137,1139,1141,1144,1146,1148,1150,1153,1156],{"class":967,"line":1123},6,[965,1125,1126],{"class":979},"  password",[965,1128,1040],{"class":1039},[965,1130,1021],{"class":979},[965,1132,943],{"class":975},[965,1134,1047],{"class":1026},[965,1136,1050],{"class":975},[965,1138,1053],{"class":1026},[965,1140,1056],{"class":975},[965,1142,1143],{"class":1059},"12",[965,1145,1063],{"class":975},[965,1147,1066],{"class":1026},[965,1149,1056],{"class":975},[965,1151,1152],{"class":1059},"64",[965,1154,1155],{"class":975},"),           ",[965,1157,1158],{"class":1077},"\u002F\u002F Must match password policy regex\n",[965,1160,1162,1165,1167,1169,1171,1173,1175,1177,1179,1181,1183,1185,1187,1189,1192],{"class":967,"line":1161},7,[965,1163,1164],{"class":979},"  confirmedPassword",[965,1166,1040],{"class":1039},[965,1168,1021],{"class":979},[965,1170,943],{"class":975},[965,1172,1047],{"class":1026},[965,1174,1050],{"class":975},[965,1176,1053],{"class":1026},[965,1178,1056],{"class":975},[965,1180,1143],{"class":1059},[965,1182,1063],{"class":975},[965,1184,1066],{"class":1026},[965,1186,1056],{"class":975},[965,1188,1152],{"class":1059},[965,1190,1191],{"class":975},"),  ",[965,1193,1194],{"class":1077},"\u002F\u002F Must match password\n",[965,1196,1198,1201,1203,1205,1207,1210,1212,1215,1218,1220,1222,1225,1228],{"class":967,"line":1197},8,[965,1199,1200],{"class":979},"  rememberUser",[965,1202,1040],{"class":1039},[965,1204,1021],{"class":979},[965,1206,943],{"class":975},[965,1208,1209],{"class":1026},"literal",[965,1211,1056],{"class":975},[965,1213,1214],{"class":989},"'",[965,1216,1217],{"class":993},"on",[965,1219,1214],{"class":989},[965,1221,1063],{"class":975},[965,1223,1224],{"class":1026},"optional",[965,1226,1227],{"class":975},"(),        ",[965,1229,1230],{"class":1077},"\u002F\u002F Checkbox toggle\n",[965,1232,1234,1237,1239,1241,1243,1245,1247,1249,1251,1253,1256],{"class":967,"line":1233},9,[965,1235,1236],{"class":979},"  termsConsent",[965,1238,1040],{"class":1039},[965,1240,1021],{"class":979},[965,1242,943],{"class":975},[965,1244,1209],{"class":1026},[965,1246,1056],{"class":975},[965,1248,1214],{"class":989},[965,1250,1217],{"class":993},[965,1252,1214],{"class":989},[965,1254,1255],{"class":975},"),                   ",[965,1257,1258],{"class":1077},"\u002F\u002F Required acceptance\n",[965,1260,1262,1265,1268,1270,1274,1277,1280,1282,1285,1288,1290,1292,1295],{"class":967,"line":1261},10,[965,1263,1264],{"class":975},"}).",[965,1266,1267],{"class":1026},"refine",[965,1269,1056],{"class":975},[965,1271,1273],{"class":1272},"sygFZ","data",[965,1275,1276],{"class":1009}," =>",[965,1278,1279],{"class":979}," data",[965,1281,943],{"class":975},[965,1283,1284],{"class":979},"password",[965,1286,1287],{"class":1017}," ===",[965,1289,1279],{"class":979},[965,1291,943],{"class":975},[965,1293,1294],{"class":979},"confirmedPassword",[965,1296,1297],{"class":975},")\n",[856,1299,1300,1301,1304,1305,1307,1308,1311,1312,1316],{},"The password regex enforces at least one lowercase letter, one uppercase letter, one digit, and one special character, with no whitespace allowed. The ",[860,1302,1303],{},"name"," and ",[860,1306,1115],{}," fields are processed through ",[860,1309,1310],{},"makeSafeString",", which strips HTML tags and triggers an ",[937,1313,1315],{"href":1314},"#xss-detection","XSS ban"," if any are found.",[856,1318,1319,1322,1323,1325],{},[860,1320,1321],{},"z.strictObject"," rejects any fields not defined in the schema. Extra properties in the request body cause a ",[860,1324,942],{}," validation error.",[868,1327],{},[871,1329,1331],{"id":1330},"the-validation-pipeline","The validation pipeline",[856,1333,1334],{},"The steps run in sequence. The first failure returns an error response and the controller exits.",[1336,1337,1339,1344,1353,1357,1382,1386,1393,1397,1414,1418,1434,1438,1441,1445,1463,1477,1480,1484,1493,1562],"steps",{"level":1338},"4",[1340,1341,1343],"h4",{"id":1342},"rate-limiting-ip","Rate limiting (IP)",[856,1345,1346,1347,1350,1351],{},"A union limiter combines a burst guard (2 points per second, blocks for 15 minutes) with a slow guard (5 points per 30 minutes, blocks for 15 minutes). Both are keyed on ",[860,1348,1349],{},"req.ip",". If the IP has been blocked by a previous violation, the request is rejected immediately from an in-memory cache without touching the database. See ",[937,1352,147],{"href":148},[1340,1354,1356],{"id":1355},"schema-validation","Schema validation",[856,1358,1359,1360,1362,1363,1365,1366,1368,1369,1371,1372,1375,1376,1378,1379,943],{},"The request body is validated against the Zod schema above. If validation fails, the controller returns ",[860,1361,942],{}," with the Zod error details. If the ",[860,1364,1310],{}," check detects HTML tags in the ",[860,1367,1303],{}," or ",[860,1370,1115],{}," fields, the controller calls ",[860,1373,1374],{},"handleXSS",", which bans the IP through the ",[937,1377,399],{"href":35},", marks the visitor as a bot, and returns ",[860,1380,1381],{},"403 { banned: true }",[1340,1383,1385],{"id":1384},"rate-limiting-composite-key","Rate limiting (composite key)",[856,1387,1388,1389,1392],{},"A second union limiter is keyed on a composite of ",[860,1390,1391],{},"ip + email",". The burst window is 1 point per second (blocks for 30 minutes) and the slow window is 3 points per 24 hours (blocks for 24 hours).",[1340,1394,1396],{"id":1395},"email-domain-verification","Email domain verification",[856,1398,931,1399,1402,1403,1406,1407,1368,1410,1413],{},[860,1400,1401],{},"isValidDomain"," function splits the email address, converts the domain to ASCII with ",[860,1404,1405],{},"domainToASCII",", and performs a DNS lookup. It checks for MX records first. If none are found, it falls back to A and AAAA record lookups. The results are cached in an LRU cache for 24 hours. If a transient DNS failure occurs (anything other than ",[860,1408,1409],{},"ENODATA",[860,1411,1412],{},"ENOTFOUND","), the domain is allowed through to avoid blocking users during DNS outages.",[1340,1415,1417],{"id":1416},"disposable-email-detection","Disposable email detection",[856,1419,931,1420,1423,1424,1430,1431,943],{},[860,1421,1422],{},"isDisposable"," function checks the email domain against a pre-loaded ",[937,1425,1429],{"href":1426,"rel":1427},"https:\u002F\u002Fen.wikipedia.org\u002Fwiki\u002FLightning_Memory-Mapped_Database",[1428],"nofollow","LMDB"," map of known disposable email providers. If the domain is found in the list, the request is rejected. The disposable email list is loaded once at startup from a local database file managed by the ",[937,1432,1433],{"href":408},"Shield Base CLI",[1340,1435,1437],{"id":1436},"rate-limiting-email","Rate limiting (email)",[856,1439,1440],{},"A final limiter is keyed on the email address alone: 3 points per 24 hours, blocks for 24 hours. This prevents repeated signup attempts with the same email regardless of IP.",[1340,1442,1444],{"id":1443},"password-breach-check","Password breach check",[856,1446,931,1447,1450,1451,1456,1457,1462],{},[860,1448,1449],{},"isPwned"," function checks the password against the ",[937,1452,1455],{"href":1453,"rel":1454},"https:\u002F\u002Fhaveibeenpwned.com\u002FAPI\u002Fv3#PwnedPasswords",[1428],"Have I Been Pwned"," Passwords API using the ",[937,1458,1461],{"href":1459,"rel":1460},"https:\u002F\u002Fen.wikipedia.org\u002Fwiki\u002FK-anonymity",[1428],"k-Anonymity"," model. It SHA-1 hashes the password, sends the first 5 characters of the hash to the API, and checks whether the remaining suffix appears in the response.",[856,1464,1465,1466,1469,1470,1472,1473,1476],{},"On signup, a breached password ",[916,1467,1468],{},"blocks registration"," and returns ",[860,1471,942],{}," with a message asking the user to choose a different password. This is stricter than the ",[937,1474,1475],{"href":104},"login"," flow, where breached passwords produce an advisory warning but do not block authentication.",[856,1478,1479],{},"Results are cached at two levels: the prefix-to-suffix map is cached for 48 hours, and individual results are cached for 15 minutes.",[1340,1481,1483],{"id":1482},"password-hashing","Password hashing",[856,1485,1486,1487,1492],{},"The password is hashed with ",[937,1488,1491],{"href":1489,"rel":1490},"https:\u002F\u002Fen.wikipedia.org\u002Fwiki\u002FArgon2",[1428],"Argon2"," using the following parameters:",[876,1494,1495,1508],{},[879,1496,1497],{},[882,1498,1499,1502,1505],{},[885,1500,1501],{},"Parameter",[885,1503,1504],{},"Default",[885,1506,1507],{},"Config key",[895,1509,1510,1523,1536,1549],{},[882,1511,1512,1515,1518],{},[900,1513,1514],{},"Hash length",[900,1516,1517],{},"50 bytes",[900,1519,1520],{},[860,1521,1522],{},"password.hashLength",[882,1524,1525,1528,1531],{},[900,1526,1527],{},"Time cost",[900,1529,1530],{},"4 iterations",[900,1532,1533],{},[860,1534,1535],{},"password.timeCost",[882,1537,1538,1541,1544],{},[900,1539,1540],{},"Memory cost",[900,1542,1543],{},"2^18 KiB (256 MB)",[900,1545,1546],{},[860,1547,1548],{},"password.memoryCost",[882,1550,1551,1554,1557],{},[900,1552,1553],{},"Secret",[900,1555,1556],{},"Pepper from config",[900,1558,1559],{},[860,1560,1561],{},"password.pepper",[856,1563,1564,1565,1567],{},"The pepper is a server-side secret that is mixed into every hash. Even if the database is compromised, the attacker cannot crack the hashes without the pepper. See ",[937,1566,237],{"href":238}," for the full password options.",[868,1569],{},[871,1571,1573],{"id":1572},"user-creation","User creation",[856,1575,1576,1577,1580],{},"After all validation passes, the controller calls ",[860,1578,1579],{},"createUser(canary_id, validatedData)",". This function:",[1336,1582,1583,1587,1615,1619,1644,1648,1654,1778,1790,1794],{"level":1338},[1340,1584,1586],{"id":1585},"look-up-the-visitor","Look up the visitor",[856,1588,1589,1590,1593,1594,1596,1597,1600,1601,1600,1604,1607,1608,1611,1612,1614],{},"Queries the ",[860,1591,1592],{},"visitors"," table using the ",[860,1595,934],{}," cookie to retrieve the visitor's ",[860,1598,1599],{},"country",", ",[860,1602,1603],{},"city",[860,1605,1606],{},"district",", and ",[860,1609,1610],{},"visitor_id",". If no visitor record exists for the cookie, the signup fails. The visitor record is created by the ",[937,1613,399],{"href":404}," middleware on the user's first request.",[1340,1616,1618],{"id":1617},"split-the-name","Split the name",[856,1620,931,1621,1623,1624,1626,1627,1630,1631,1634,1635,1600,1638,1641,1642,943],{},[860,1622,1303],{}," field is split on spaces and commas. The first token becomes the ",[860,1625,1303],{}," column and all remaining tokens are joined as ",[860,1628,1629],{},"last_name",". For example, ",[860,1632,1633],{},"\"Alice Johnson\""," becomes ",[860,1636,1637],{},"name: 'alice'",[860,1639,1640],{},"last_name: 'johnson'",". Single-word names produce an empty ",[860,1643,1629],{},[1340,1645,1647],{"id":1646},"insert-the-user-row","Insert the user row",[856,1649,1650,1651,1653],{},"The function inserts a row into the ",[860,1652,862],{}," table with the following columns:",[876,1655,1656,1666],{},[879,1657,1658],{},[882,1659,1660,1663],{},[885,1661,1662],{},"Column",[885,1664,1665],{},"Source",[895,1667,1668,1677,1686,1695,1705,1715,1729,1745,1757,1769],{},[882,1669,1670,1674],{},[900,1671,1672],{},[860,1673,1303],{},[900,1675,1676],{},"First token from name split",[882,1678,1679,1683],{},[900,1680,1681],{},[860,1682,1629],{},[900,1684,1685],{},"Remaining tokens from name split",[882,1687,1688,1692],{},[900,1689,1690],{},[860,1691,1115],{},[900,1693,1694],{},"Validated, lowercased email",[882,1696,1697,1702],{},[900,1698,1699],{},[860,1700,1701],{},"password_hash",[900,1703,1704],{},"Argon2 hash from the previous step",[882,1706,1707,1712],{},[900,1708,1709],{},[860,1710,1711],{},"remember_user",[900,1713,1714],{},"From the request body (boolean)",[882,1716,1717,1722],{},[900,1718,1719],{},[860,1720,1721],{},"terms_and_privacy_agreement",[900,1723,1724,1725,1728],{},"From the request body (required ",[860,1726,1727],{},"true",")",[882,1730,1731,1735],{},[900,1732,1733],{},[860,1734,1599],{},[900,1736,1737,1738,1741,1742,1728],{},"From the visitor record (or ",[860,1739,1740],{},"null"," if ",[860,1743,1744],{},"'unknown'",[882,1746,1747,1751],{},[900,1748,1749],{},[860,1750,1603],{},[900,1752,1737,1753,1741,1755,1728],{},[860,1754,1740],{},[860,1756,1744],{},[882,1758,1759,1763],{},[900,1760,1761],{},[860,1762,1606],{},[900,1764,1737,1765,1741,1767,1728],{},[860,1766,1740],{},[860,1768,1744],{},[882,1770,1771,1775],{},[900,1772,1773],{},[860,1774,1610],{},[900,1776,1777],{},"From the visitor record (UUID foreign key)",[856,1779,931,1780,1782,1783,1786,1787,943],{},[860,1781,1115],{}," column has a unique constraint. If a user with the same email already exists, the database returns an ",[860,1784,1785],{},"ER_DUP_ENTRY"," error and the controller responds with ",[860,1788,1789],{},"409 { error: 'E-mail already registered' }",[1340,1791,1793],{"id":1792},"issue-tokens","Issue tokens",[856,1795,1796,1797,1304,1800,1803,1804,1304,1806,943],{},"On successful insertion, the function generates a refresh token and an access token for the new user. Both are created using the same ",[860,1798,1799],{},"generateRefreshToken",[860,1801,1802],{},"generateAccessToken"," functions described in ",[937,1805,91],{"href":92},[937,1807,87],{"href":88},[868,1809],{},[871,1811,1813],{"id":1812},"response","Response",[1815,1816,1818],"h3",{"id":1817},"success-201","Success (201)",[920,1820,1823],{"className":1821,"code":1822,"language":5,"meta":928,"style":928},"language-json shiki shiki-themes light-plus light-plus dracula","{\n  \"ok\": true,\n  \"receivedAt\": \"2025-01-15T10:30:00.000Z\",\n  \"accessToken\": \"\u003Csigned JWT>\",\n  \"accessIat\": \"1705312200000\"\n}\n",[860,1824,1825,1830,1852,1873,1893,1912],{"__ignoreMap":928},[965,1826,1827],{"class":967,"line":968},[965,1828,1829],{"class":975},"{\n",[965,1831,1832,1836,1840,1843,1845,1849],{"class":967,"line":1000},[965,1833,1835],{"class":1834},"saJyd","  \"",[965,1837,1839],{"class":1838},"s_W10","ok",[965,1841,1842],{"class":1834},"\"",[965,1844,1040],{"class":1017},[965,1846,1848],{"class":1847},"sjR7W"," true",[965,1850,1851],{"class":975},",\n",[965,1853,1854,1856,1859,1861,1863,1866,1869,1871],{"class":967,"line":1006},[965,1855,1835],{"class":1834},[965,1857,1858],{"class":1838},"receivedAt",[965,1860,1842],{"class":1834},[965,1862,1040],{"class":1017},[965,1864,1865],{"class":989}," \"",[965,1867,1868],{"class":993},"2025-01-15T10:30:00.000Z",[965,1870,1842],{"class":989},[965,1872,1851],{"class":975},[965,1874,1875,1877,1880,1882,1884,1886,1889,1891],{"class":967,"line":1033},[965,1876,1835],{"class":1834},[965,1878,1879],{"class":1838},"accessToken",[965,1881,1842],{"class":1834},[965,1883,1040],{"class":1017},[965,1885,1865],{"class":989},[965,1887,1888],{"class":993},"\u003Csigned JWT>",[965,1890,1842],{"class":989},[965,1892,1851],{"class":975},[965,1894,1895,1897,1900,1902,1904,1906,1909],{"class":967,"line":1081},[965,1896,1835],{"class":1834},[965,1898,1899],{"class":1838},"accessIat",[965,1901,1842],{"class":1834},[965,1903,1040],{"class":1017},[965,1905,1865],{"class":989},[965,1907,1908],{"class":993},"1705312200000",[965,1910,1911],{"class":989},"\"\n",[965,1913,1914],{"class":967,"line":1123},[965,1915,1916],{"class":975},"}\n",[856,1918,1919],{},"Two cookies are set alongside the JSON response:",[876,1921,1922,1935],{},[879,1923,1924],{},[882,1925,1926,1929,1932],{},[885,1927,1928],{},"Cookie",[885,1930,1931],{},"Value",[885,1933,1934],{},"Options",[895,1936,1937,1964],{},[882,1938,1939,1944,1950],{},[900,1940,1941],{},[860,1942,1943],{},"iat",[900,1945,1946,1949],{},[860,1947,1948],{},"Date.now()"," as string",[900,1951,1952,1600,1955,1600,1958,1600,1961],{},[860,1953,1954],{},"httpOnly",[860,1956,1957],{},"secure",[860,1959,1960],{},"sameSite: strict",[860,1962,1963],{},"path: \u002F",[882,1965,1966,1971,1974],{},[900,1967,1968],{},[860,1969,1970],{},"session",[900,1972,1973],{},"Raw refresh token (64 hex bytes)",[900,1975,1976,1600,1978,1600,1980,1600,1982,1985],{},[860,1977,1954],{},[860,1979,1957],{},[860,1981,1960],{},[860,1983,1984],{},"domain"," from config",[856,1987,931,1988,1990,1991,1993],{},[860,1989,1943],{}," cookie is a client-readable timestamp that tells the frontend when the access token was issued. The ",[860,1992,1970],{}," cookie carries the raw refresh token and is never readable by JavaScript.",[1815,1995,1997],{"id":1996},"error-responses","Error responses",[876,1999,2000,2010],{},[879,2001,2002],{},[882,2003,2004,2007],{},[885,2005,2006],{},"Status",[885,2008,2009],{},"Condition",[895,2011,2012,2024,2034,2044],{},[882,2013,2014,2018],{},[900,2015,2016],{},[860,2017,942],{},[900,2019,2020,2021,2023],{},"Invalid JSON, schema validation failure, empty body, missing ",[860,2022,934],{},", breached password, invalid email domain, disposable email",[882,2025,2026,2031],{},[900,2027,2028],{},[860,2029,2030],{},"403",[900,2032,2033],{},"HTML\u002FXSS detected in input fields",[882,2035,2036,2041],{},[900,2037,2038],{},[860,2039,2040],{},"409",[900,2042,2043],{},"Email already registered",[882,2045,2046,2051],{},[900,2047,2048],{},[860,2049,2050],{},"429",[900,2052,2053],{},"Rate limit exceeded on any of the three limiters",[868,2055],{},[871,2057,2059],{"id":2058},"xss-detection","XSS detection",[856,2061,931,2062,2064,2065,1304,2067,2069,2070,2072],{},[860,2063,1310],{}," Zod helper runs input sanitization on the ",[860,2066,1303],{},[860,2068,1115],{}," fields during schema validation. If HTML tags are detected in the input, the validation pipeline triggers ",[860,2071,1374],{},", which:",[2074,2075,2076,2086,2092,2099],"ol",{},[2077,2078,2079,2080,2082,2083,1728],"li",{},"Bans the client IP through the ",[937,2081,399],{"href":35}," (",[860,2084,2085],{},"banIp",[2077,2087,2088,2089],{},"Marks the visitor record as ",[860,2090,2091],{},"is_bot = true",[2077,2093,2094,2095,2098],{},"Inserts the IP into the ",[860,2096,2097],{},"banned"," table",[2077,2100,2101,2102],{},"Returns ",[860,2103,1381],{},[856,2105,2106],{},"This is a permanent ban. The IP is blocked from all future requests, not just signup.",[868,2108],{},[871,2110,2112],{"id":2111},"rate-limiter-reference","Rate limiter reference",[856,2114,2115,2116,2119],{},"All signup rate limiters are configurable under ",[860,2117,2118],{},"rate_limiters"," in the configuration object. The defaults are:",[876,2121,2122,2141],{},[879,2123,2124],{},[882,2125,2126,2129,2132,2135,2138],{},[885,2127,2128],{},"Limiter",[885,2130,2131],{},"Key",[885,2133,2134],{},"Points",[885,2136,2137],{},"Window",[885,2139,2140],{},"Block duration",[895,2142,2143,2161,2178,2194,2211],{},[882,2144,2145,2148,2152,2155,2158],{},[900,2146,2147],{},"IP burst",[900,2149,2150],{},[860,2151,1349],{},[900,2153,2154],{},"2 \u002F 1 second",[900,2156,2157],{},"1 s",[900,2159,2160],{},"15 min",[882,2162,2163,2166,2170,2173,2176],{},[900,2164,2165],{},"IP slow",[900,2167,2168],{},[860,2169,1349],{},[900,2171,2172],{},"5 \u002F 30 minutes",[900,2174,2175],{},"30 min",[900,2177,2160],{},[882,2179,2180,2183,2187,2190,2192],{},[900,2181,2182],{},"Composite burst",[900,2184,2185],{},[860,2186,1391],{},[900,2188,2189],{},"1 \u002F 1 second",[900,2191,2157],{},[900,2193,2175],{},[882,2195,2196,2199,2203,2206,2209],{},[900,2197,2198],{},"Composite slow",[900,2200,2201],{},[860,2202,1391],{},[900,2204,2205],{},"3 \u002F 24 hours",[900,2207,2208],{},"24 h",[900,2210,2208],{},[882,2212,2213,2216,2220,2222,2224],{},[900,2214,2215],{},"Email",[900,2217,2218],{},[860,2219,1115],{},[900,2221,2205],{},[900,2223,2208],{},[900,2225,2208],{},[856,2227,931,2228,2231,2232,2235],{},[860,2229,2230],{},"guard()"," function also uses in-memory LRU caches to track consecutive violations. After a configurable number of consecutive blocks, the key is escalated to a longer-duration block. See ",[937,2233,147],{"href":2234},"\u002Fdocs\u002Fiam\u002Frate-limiting"," for the escalation mechanics.",[868,2237],{},[871,2239,2241],{"id":2240},"configuration-reference","Configuration reference",[876,2243,2244,2260],{},[879,2245,2246],{},[882,2247,2248,2251,2254,2257],{},[885,2249,2250],{},"Option",[885,2252,2253],{},"Location",[885,2255,2256],{},"Type",[885,2258,2259],{},"Description",[895,2261,2262,2278,2294,2309,2324,2343],{},[882,2263,2264,2268,2271,2275],{},[900,2265,2266],{},[860,2267,1561],{},[900,2269,2270],{},"Root config",[900,2272,2273],{},[860,2274,1047],{},[900,2276,2277],{},"Server-side secret mixed into Argon2 hashes",[882,2279,2280,2284,2286,2291],{},[900,2281,2282],{},[860,2283,1522],{},[900,2285,2270],{},[900,2287,2288],{},[860,2289,2290],{},"number",[900,2292,2293],{},"Argon2 output length in bytes (default: 50)",[882,2295,2296,2300,2302,2306],{},[900,2297,2298],{},[860,2299,1535],{},[900,2301,2270],{},[900,2303,2304],{},[860,2305,2290],{},[900,2307,2308],{},"Argon2 iteration count (default: 4)",[882,2310,2311,2315,2317,2321],{},[900,2312,2313],{},[860,2314,1548],{},[900,2316,2270],{},[900,2318,2319],{},[860,2320,2290],{},[900,2322,2323],{},"Argon2 memory in KiB (default: 2^18)",[882,2325,2326,2331,2336,2340],{},[900,2327,2328],{},[860,2329,2330],{},"jwt.refresh_tokens.refresh_ttl",[900,2332,2333],{},[860,2334,2335],{},"jwt",[900,2337,2338],{},[860,2339,2290],{},[900,2341,2342],{},"Refresh token lifetime in milliseconds",[882,2344,2345,2350,2354,2358],{},[900,2346,2347],{},[860,2348,2349],{},"jwt.refresh_tokens.domain",[900,2351,2352],{},[860,2353,2335],{},[900,2355,2356],{},[860,2357,1047],{},[900,2359,2360,2361,2363],{},"Cookie domain for the ",[860,2362,1970],{}," cookie",[856,2365,946,2366,2368],{},[937,2367,237],{"href":238}," for the full schema reference.",[2370,2371,2372],"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 .sl46w, html code.shiki .sl46w{--shiki-light:#0000FF;--shiki-default:#0000FF;--shiki-dark:#FF79C6}html pre.shiki code .s3JHE, html code.shiki .s3JHE{--shiki-light:#0070C1;--shiki-default:#0070C1;--shiki-dark:#F8F8F2}html pre.shiki code .saOXh, html code.shiki .saOXh{--shiki-light:#000000;--shiki-default:#000000;--shiki-dark:#FF79C6}html pre.shiki code .sHOzp, html code.shiki .sHOzp{--shiki-light:#795E26;--shiki-default:#795E26;--shiki-dark:#50FA7B}html pre.shiki code .s34zl, html code.shiki .s34zl{--shiki-light:#001080;--shiki-default:#001080;--shiki-dark:#FF79C6}html pre.shiki code .spgvN, html code.shiki .spgvN{--shiki-light:#098658;--shiki-default:#098658;--shiki-dark:#BD93F9}html pre.shiki code .sghk6, html code.shiki .sghk6{--shiki-light:#008000;--shiki-default:#008000;--shiki-dark:#6272A4}html pre.shiki code .sygFZ, html code.shiki .sygFZ{--shiki-light:#001080;--shiki-light-font-style:inherit;--shiki-default:#001080;--shiki-default-font-style:inherit;--shiki-dark:#FFB86C;--shiki-dark-font-style:italic}html .light .shiki span {color: var(--shiki-light);background: var(--shiki-light-bg);font-style: var(--shiki-light-font-style);font-weight: var(--shiki-light-font-weight);text-decoration: var(--shiki-light-text-decoration);}html.light .shiki span {color: var(--shiki-light);background: var(--shiki-light-bg);font-style: var(--shiki-light-font-style);font-weight: var(--shiki-light-font-weight);text-decoration: var(--shiki-light-text-decoration);}html .default .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}html .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}html .dark .shiki span {color: var(--shiki-dark);background: var(--shiki-dark-bg);font-style: var(--shiki-dark-font-style);font-weight: var(--shiki-dark-font-weight);text-decoration: var(--shiki-dark-text-decoration);}html.dark .shiki span {color: var(--shiki-dark);background: var(--shiki-dark-bg);font-style: var(--shiki-dark-font-style);font-weight: var(--shiki-dark-font-weight);text-decoration: var(--shiki-dark-text-decoration);}html pre.shiki code .saJyd, html code.shiki .saJyd{--shiki-light:#0451A5;--shiki-default:#0451A5;--shiki-dark:#8BE9FE}html pre.shiki code .s_W10, html code.shiki .s_W10{--shiki-light:#0451A5;--shiki-default:#0451A5;--shiki-dark:#8BE9FD}html pre.shiki code .sjR7W, html code.shiki .sjR7W{--shiki-light:#0000FF;--shiki-default:#0000FF;--shiki-dark:#BD93F9}",{"title":928,"searchDepth":1000,"depth":1000,"links":2374},[2375,2376,2377,2378,2379,2383,2384,2385],{"id":873,"depth":1000,"text":874},{"id":955,"depth":1000,"text":956},{"id":1330,"depth":1000,"text":1331},{"id":1572,"depth":1000,"text":1573},{"id":1812,"depth":1000,"text":1813,"children":2380},[2381,2382],{"id":1817,"depth":1006,"text":1818},{"id":1996,"depth":1006,"text":1997},{"id":2058,"depth":1000,"text":2059},{"id":2111,"depth":1000,"text":2112},{"id":2240,"depth":1000,"text":2241},"How the IAM service registers new users, the full validation pipeline from rate limiting through email domain verification to password breach checks, and what happens in the database when a user is created.","md","i-lucide-user-plus",{},null,"---\ntitle: Signup\ndescription: How the IAM service registers new users, the full validation pipeline from rate limiting through email domain verification to password breach checks, and what happens in the database when a user is created.\nicon: i-lucide-user-plus\n---\n\nThe signup route creates a new user account from an email, password, and name. Before the account is created, the request passes through six layers of validation: rate limiting, schema validation, email domain verification, disposable email detection, password breach checking, and password hashing. Only after all six layers pass does the service insert a row into the `users` table and issue tokens.\n\nNo verification email is sent during signup. The user receives an access token and a refresh token immediately and is considered authenticated.\n\n---\n\n## Route\n\n| Method | Path | Body limit |\n|---|---|---|\n| `POST` | `\u002Fsignup` | 1 KB |\n\n**Middleware chain:**\n\n```\nvalidateContentType('application\u002Fjson'), express.json({ limit: '1kb' }), canary_id check, handleSignUp\n```\n\nThe `canary_id` cookie must be present. This cookie is set by the [Bot Detector](\u002Fdocs\u002Fbot-detection\u002Fgetting-started) on first contact and is used to look up the visitor record that will be linked to the new user. If the cookie is missing, the route returns `400`.\n\nSee [Routes](\u002Fdocs\u002Fiam\u002Fapi\u002Froutes) for how to mount the authentication router on your Express application.\n\n---\n\n## Request body\n\n```ts\nimport { z } from 'zod'\n\nconst signupSchema = z.strictObject({\n  name: z.string().min(2).max(72),               \u002F\u002F Lowercase-transformed, XSS-sanitized\n  email: z.string().min(10).max(80).email(),      \u002F\u002F Lowercase-transformed, XSS-sanitized\n  password: z.string().min(12).max(64),           \u002F\u002F Must match password policy regex\n  confirmedPassword: z.string().min(12).max(64),  \u002F\u002F Must match password\n  rememberUser: z.literal('on').optional(),        \u002F\u002F Checkbox toggle\n  termsConsent: z.literal('on'),                   \u002F\u002F Required acceptance\n}).refine(data => data.password === data.confirmedPassword)\n```\n\nThe password regex enforces at least one lowercase letter, one uppercase letter, one digit, and one special character, with no whitespace allowed. The `name` and `email` fields are processed through `makeSafeString`, which strips HTML tags and triggers an [XSS ban](#xss-detection) if any are found.\n\n`z.strictObject` rejects any fields not defined in the schema. Extra properties in the request body cause a `400` validation error.\n\n---\n\n## The validation pipeline\n\nThe steps run in sequence. The first failure returns an error response and the controller exits.\n\n::steps{level=\"4\"}\n#### Rate limiting (IP)\n\nA union limiter combines a burst guard (2 points per second, blocks for 15 minutes) with a slow guard (5 points per 30 minutes, blocks for 15 minutes). Both are keyed on `req.ip`. If the IP has been blocked by a previous violation, the request is rejected immediately from an in-memory cache without touching the database. See [Rate Limiting](\u002Fdocs\u002Fiam\u002Fessentials\u002Frate-limiting)\n\n#### Schema validation\n\nThe request body is validated against the Zod schema above. If validation fails, the controller returns `400` with the Zod error details. If the `makeSafeString` check detects HTML tags in the `name` or `email` fields, the controller calls `handleXSS`, which bans the IP through the [Bot Detector](\u002Fdocs\u002Fbot-detection), marks the visitor as a bot, and returns `403 { banned: true }`.\n\n#### Rate limiting (composite key)\n\nA second union limiter is keyed on a composite of `ip + email`. The burst window is 1 point per second (blocks for 30 minutes) and the slow window is 3 points per 24 hours (blocks for 24 hours).\n#### Email domain verification\n\nThe `isValidDomain` function splits the email address, converts the domain to ASCII with `domainToASCII`, and performs a DNS lookup. It checks for MX records first. If none are found, it falls back to A and AAAA record lookups. The results are cached in an LRU cache for 24 hours. If a transient DNS failure occurs (anything other than `ENODATA` or `ENOTFOUND`), the domain is allowed through to avoid blocking users during DNS outages.\n\n#### Disposable email detection\n\nThe `isDisposable` function checks the email domain against a pre-loaded [LMDB](https:\u002F\u002Fen.wikipedia.org\u002Fwiki\u002FLightning_Memory-Mapped_Database) map of known disposable email providers. If the domain is found in the list, the request is rejected. The disposable email list is loaded once at startup from a local database file managed by the [Shield Base CLI](\u002Fdocs\u002Fbot-detection\u002Fcli).\n\n#### Rate limiting (email)\n\nA final limiter is keyed on the email address alone: 3 points per 24 hours, blocks for 24 hours. This prevents repeated signup attempts with the same email regardless of IP.\n\n#### Password breach check\n\nThe `isPwned` function checks the password against the [Have I Been Pwned](https:\u002F\u002Fhaveibeenpwned.com\u002FAPI\u002Fv3#PwnedPasswords) Passwords API using the [k-Anonymity](https:\u002F\u002Fen.wikipedia.org\u002Fwiki\u002FK-anonymity) model. It SHA-1 hashes the password, sends the first 5 characters of the hash to the API, and checks whether the remaining suffix appears in the response.\n\nOn signup, a breached password **blocks registration** and returns `400` with a message asking the user to choose a different password. This is stricter than the [login](\u002Fdocs\u002Fiam\u002Fessentials\u002Flogin) flow, where breached passwords produce an advisory warning but do not block authentication.\n\nResults are cached at two levels: the prefix-to-suffix map is cached for 48 hours, and individual results are cached for 15 minutes.\n\n#### Password hashing\n\nThe password is hashed with [Argon2](https:\u002F\u002Fen.wikipedia.org\u002Fwiki\u002FArgon2) using the following parameters:\n\n| Parameter | Default | Config key |\n|---|---|---|\n| Hash length | 50 bytes | `password.hashLength` |\n| Time cost | 4 iterations | `password.timeCost` |\n| Memory cost | 2^18 KiB (256 MB) | `password.memoryCost` |\n| Secret | Pepper from config | `password.pepper` |\n\nThe pepper is a server-side secret that is mixed into every hash. Even if the database is compromised, the attacker cannot crack the hashes without the pepper. See [Configuration](\u002Fdocs\u002Fiam\u002Fconfiguration) for the full password options.\n::\n\n---\n\n## User creation\n\nAfter all validation passes, the controller calls `createUser(canary_id, validatedData)`. This function:\n\n::steps{level=\"4\"}\n#### Look up the visitor\n\nQueries the `visitors` table using the `canary_id` cookie to retrieve the visitor's `country`, `city`, `district`, and `visitor_id`. If no visitor record exists for the cookie, the signup fails. The visitor record is created by the [Bot Detector](\u002Fdocs\u002Fbot-detection\u002Fgetting-started) middleware on the user's first request.\n\n#### Split the name\n\nThe `name` field is split on spaces and commas. The first token becomes the `name` column and all remaining tokens are joined as `last_name`. For example, `\"Alice Johnson\"` becomes `name: 'alice'`, `last_name: 'johnson'`. Single-word names produce an empty `last_name`.\n\n#### Insert the user row\n\nThe function inserts a row into the `users` table with the following columns:\n\n| Column | Source |\n|---|---|\n| `name` | First token from name split |\n| `last_name` | Remaining tokens from name split |\n| `email` | Validated, lowercased email |\n| `password_hash` | Argon2 hash from the previous step |\n| `remember_user` | From the request body (boolean) |\n| `terms_and_privacy_agreement` | From the request body (required `true`) |\n| `country` | From the visitor record (or `null` if `'unknown'`) |\n| `city` | From the visitor record (or `null` if `'unknown'`) |\n| `district` | From the visitor record (or `null` if `'unknown'`) |\n| `visitor_id` | From the visitor record (UUID foreign key) |\n\nThe `email` column has a unique constraint. If a user with the same email already exists, the database returns an `ER_DUP_ENTRY` error and the controller responds with `409 { error: 'E-mail already registered' }`.\n\n#### Issue tokens\n\nOn successful insertion, the function generates a refresh token and an access token for the new user. Both are created using the same `generateRefreshToken` and `generateAccessToken` functions described in [Refresh Tokens](\u002Fdocs\u002Fiam\u002Fessentials\u002Frefresh-tokens) and [Access Tokens](\u002Fdocs\u002Fiam\u002Fessentials\u002Faccess-tokens).\n::\n\n---\n\n## Response\n\n### Success (201)\n\n```json\n{\n  \"ok\": true,\n  \"receivedAt\": \"2025-01-15T10:30:00.000Z\",\n  \"accessToken\": \"\u003Csigned JWT>\",\n  \"accessIat\": \"1705312200000\"\n}\n```\n\nTwo cookies are set alongside the JSON response:\n\n| Cookie | Value | Options |\n|---|---|---|\n| `iat` | `Date.now()` as string | `httpOnly`, `secure`, `sameSite: strict`, `path: \u002F` |\n| `session` | Raw refresh token (64 hex bytes) | `httpOnly`, `secure`, `sameSite: strict`, `domain` from config |\n\nThe `iat` cookie is a client-readable timestamp that tells the frontend when the access token was issued. The `session` cookie carries the raw refresh token and is never readable by JavaScript.\n\n### Error responses\n\n| Status | Condition |\n|---|---|\n| `400` | Invalid JSON, schema validation failure, empty body, missing `canary_id`, breached password, invalid email domain, disposable email |\n| `403` | HTML\u002FXSS detected in input fields |\n| `409` | Email already registered |\n| `429` | Rate limit exceeded on any of the three limiters |\n\n---\n\n## XSS detection\n\nThe `makeSafeString` Zod helper runs input sanitization on the `name` and `email` fields during schema validation. If HTML tags are detected in the input, the validation pipeline triggers `handleXSS`, which:\n\n1. Bans the client IP through the [Bot Detector](\u002Fdocs\u002Fbot-detection) (`banIp`)\n2. Marks the visitor record as `is_bot = true`\n3. Inserts the IP into the `banned` table\n4. Returns `403 { banned: true }`\n\nThis is a permanent ban. The IP is blocked from all future requests, not just signup.\n\n---\n\n## Rate limiter reference\n\nAll signup rate limiters are configurable under `rate_limiters` in the configuration object. The defaults are:\n\n| Limiter | Key | Points | Window | Block duration |\n|---|---|---|---|---|\n| IP burst | `req.ip` | 2 \u002F 1 second | 1 s | 15 min |\n| IP slow | `req.ip` | 5 \u002F 30 minutes | 30 min | 15 min |\n| Composite burst | `ip + email` | 1 \u002F 1 second | 1 s | 30 min |\n| Composite slow | `ip + email` | 3 \u002F 24 hours | 24 h | 24 h |\n| Email | `email` | 3 \u002F 24 hours | 24 h | 24 h |\n\nThe `guard()` function also uses in-memory LRU caches to track consecutive violations. After a configurable number of consecutive blocks, the key is escalated to a longer-duration block. See [Rate Limiting](\u002Fdocs\u002Fiam\u002Frate-limiting) for the escalation mechanics.\n\n---\n\n## Configuration reference\n\n| Option | Location | Type | Description |\n|---|---|---|---|\n| `password.pepper` | Root config | `string` | Server-side secret mixed into Argon2 hashes |\n| `password.hashLength` | Root config | `number` | Argon2 output length in bytes (default: 50) |\n| `password.timeCost` | Root config | `number` | Argon2 iteration count (default: 4) |\n| `password.memoryCost` | Root config | `number` | Argon2 memory in KiB (default: 2^18) |\n| `jwt.refresh_tokens.refresh_ttl` | `jwt` | `number` | Refresh token lifetime in milliseconds |\n| `jwt.refresh_tokens.domain` | `jwt` | `string` | Cookie domain for the `session` cookie |\n\nSee [Configuration](\u002Fdocs\u002Fiam\u002Fconfiguration) for the full schema reference.",{"title":99,"description":2386},"ziMXSwYJU93wuKzNJQROvtpvybL6jJz-bKqUCY-F6HI",[2395,2396],{"title":95,"path":96,"stem":97,"children":-1},{"title":103,"path":104,"stem":105,"children":-1},{"id":851,"title":99,"body":2398,"description":2386,"extension":2387,"icon":2388,"meta":3522,"module":2390,"navigation":8,"path":100,"rawbody":2391,"seo":3523,"stem":101,"__hash__":2393},{"type":853,"value":2399,"toc":3509},[2400,2404,2406,2408,2410,2436,2440,2445,2453,2457,2459,2461,2715,2725,2731,2733,2735,2737,2885,2887,2889,2893,3063,3065,3067,3069,3147,3149,3201,3207,3209,3255,3257,3259,3269,3289,3291,3293,3295,3299,3387,3393,3395,3397,3503,3507],[856,2401,858,2402,863],{},[860,2403,862],{},[856,2405,866],{},[868,2407],{},[871,2409,874],{"id":873},[876,2411,2412,2422],{},[879,2413,2414],{},[882,2415,2416,2418,2420],{},[885,2417,887],{},[885,2419,890],{},[885,2421,893],{},[895,2423,2424],{},[882,2425,2426,2430,2434],{},[900,2427,2428],{},[860,2429,904],{},[900,2431,2432],{},[860,2433,909],{},[900,2435,912],{},[856,2437,2438],{},[916,2439,918],{},[920,2441,2443],{"className":2442,"code":924,"language":925},[923],[860,2444,924],{"__ignoreMap":928},[856,2446,931,2447,935,2449,939,2451,943],{},[860,2448,934],{},[937,2450,399],{"href":404},[860,2452,942],{},[856,2454,946,2455,950],{},[937,2456,949],{"href":255},[868,2458],{},[871,2460,956],{"id":955},[920,2462,2463],{"className":959,"code":960,"language":961,"meta":928,"style":928},[860,2464,2465,2483,2487,2503,2535,2571,2603,2635,2663,2687],{"__ignoreMap":928},[965,2466,2467,2469,2471,2473,2475,2477,2479,2481],{"class":967,"line":968},[965,2468,972],{"class":971},[965,2470,976],{"class":975},[965,2472,980],{"class":979},[965,2474,983],{"class":975},[965,2476,986],{"class":971},[965,2478,990],{"class":989},[965,2480,994],{"class":993},[965,2482,997],{"class":989},[965,2484,2485],{"class":967,"line":1000},[965,2486,1003],{"emptyLinePlaceholder":8},[965,2488,2489,2491,2493,2495,2497,2499,2501],{"class":967,"line":1006},[965,2490,1010],{"class":1009},[965,2492,1014],{"class":1013},[965,2494,1018],{"class":1017},[965,2496,1021],{"class":979},[965,2498,943],{"class":975},[965,2500,1027],{"class":1026},[965,2502,1030],{"class":975},[965,2504,2505,2507,2509,2511,2513,2515,2517,2519,2521,2523,2525,2527,2529,2531,2533],{"class":967,"line":1033},[965,2506,1036],{"class":979},[965,2508,1040],{"class":1039},[965,2510,1021],{"class":979},[965,2512,943],{"class":975},[965,2514,1047],{"class":1026},[965,2516,1050],{"class":975},[965,2518,1053],{"class":1026},[965,2520,1056],{"class":975},[965,2522,1060],{"class":1059},[965,2524,1063],{"class":975},[965,2526,1066],{"class":1026},[965,2528,1056],{"class":975},[965,2530,1071],{"class":1059},[965,2532,1074],{"class":975},[965,2534,1078],{"class":1077},[965,2536,2537,2539,2541,2543,2545,2547,2549,2551,2553,2555,2557,2559,2561,2563,2565,2567,2569],{"class":967,"line":1081},[965,2538,1084],{"class":979},[965,2540,1040],{"class":1039},[965,2542,1021],{"class":979},[965,2544,943],{"class":975},[965,2546,1047],{"class":1026},[965,2548,1050],{"class":975},[965,2550,1053],{"class":1026},[965,2552,1056],{"class":975},[965,2554,1101],{"class":1059},[965,2556,1063],{"class":975},[965,2558,1066],{"class":1026},[965,2560,1056],{"class":975},[965,2562,1110],{"class":1059},[965,2564,1063],{"class":975},[965,2566,1115],{"class":1026},[965,2568,1118],{"class":975},[965,2570,1078],{"class":1077},[965,2572,2573,2575,2577,2579,2581,2583,2585,2587,2589,2591,2593,2595,2597,2599,2601],{"class":967,"line":1123},[965,2574,1126],{"class":979},[965,2576,1040],{"class":1039},[965,2578,1021],{"class":979},[965,2580,943],{"class":975},[965,2582,1047],{"class":1026},[965,2584,1050],{"class":975},[965,2586,1053],{"class":1026},[965,2588,1056],{"class":975},[965,2590,1143],{"class":1059},[965,2592,1063],{"class":975},[965,2594,1066],{"class":1026},[965,2596,1056],{"class":975},[965,2598,1152],{"class":1059},[965,2600,1155],{"class":975},[965,2602,1158],{"class":1077},[965,2604,2605,2607,2609,2611,2613,2615,2617,2619,2621,2623,2625,2627,2629,2631,2633],{"class":967,"line":1161},[965,2606,1164],{"class":979},[965,2608,1040],{"class":1039},[965,2610,1021],{"class":979},[965,2612,943],{"class":975},[965,2614,1047],{"class":1026},[965,2616,1050],{"class":975},[965,2618,1053],{"class":1026},[965,2620,1056],{"class":975},[965,2622,1143],{"class":1059},[965,2624,1063],{"class":975},[965,2626,1066],{"class":1026},[965,2628,1056],{"class":975},[965,2630,1152],{"class":1059},[965,2632,1191],{"class":975},[965,2634,1194],{"class":1077},[965,2636,2637,2639,2641,2643,2645,2647,2649,2651,2653,2655,2657,2659,2661],{"class":967,"line":1197},[965,2638,1200],{"class":979},[965,2640,1040],{"class":1039},[965,2642,1021],{"class":979},[965,2644,943],{"class":975},[965,2646,1209],{"class":1026},[965,2648,1056],{"class":975},[965,2650,1214],{"class":989},[965,2652,1217],{"class":993},[965,2654,1214],{"class":989},[965,2656,1063],{"class":975},[965,2658,1224],{"class":1026},[965,2660,1227],{"class":975},[965,2662,1230],{"class":1077},[965,2664,2665,2667,2669,2671,2673,2675,2677,2679,2681,2683,2685],{"class":967,"line":1233},[965,2666,1236],{"class":979},[965,2668,1040],{"class":1039},[965,2670,1021],{"class":979},[965,2672,943],{"class":975},[965,2674,1209],{"class":1026},[965,2676,1056],{"class":975},[965,2678,1214],{"class":989},[965,2680,1217],{"class":993},[965,2682,1214],{"class":989},[965,2684,1255],{"class":975},[965,2686,1258],{"class":1077},[965,2688,2689,2691,2693,2695,2697,2699,2701,2703,2705,2707,2709,2711,2713],{"class":967,"line":1261},[965,2690,1264],{"class":975},[965,2692,1267],{"class":1026},[965,2694,1056],{"class":975},[965,2696,1273],{"class":1272},[965,2698,1276],{"class":1009},[965,2700,1279],{"class":979},[965,2702,943],{"class":975},[965,2704,1284],{"class":979},[965,2706,1287],{"class":1017},[965,2708,1279],{"class":979},[965,2710,943],{"class":975},[965,2712,1294],{"class":979},[965,2714,1297],{"class":975},[856,2716,1300,2717,1304,2719,1307,2721,1311,2723,1316],{},[860,2718,1303],{},[860,2720,1115],{},[860,2722,1310],{},[937,2724,1315],{"href":1314},[856,2726,2727,1322,2729,1325],{},[860,2728,1321],{},[860,2730,942],{},[868,2732],{},[871,2734,1331],{"id":1330},[856,2736,1334],{},[1336,2738,2739,2741,2747,2749,2765,2767,2771,2773,2783,2785,2794,2796,2798,2800,2810,2818,2820,2822,2827,2881],{"level":1338},[1340,2740,1343],{"id":1342},[856,2742,1346,2743,1350,2745],{},[860,2744,1349],{},[937,2746,147],{"href":148},[1340,2748,1356],{"id":1355},[856,2750,1359,2751,1362,2753,1365,2755,1368,2757,1371,2759,1375,2761,1378,2763,943],{},[860,2752,942],{},[860,2754,1310],{},[860,2756,1303],{},[860,2758,1115],{},[860,2760,1374],{},[937,2762,399],{"href":35},[860,2764,1381],{},[1340,2766,1385],{"id":1384},[856,2768,1388,2769,1392],{},[860,2770,1391],{},[1340,2772,1396],{"id":1395},[856,2774,931,2775,1402,2777,1406,2779,1368,2781,1413],{},[860,2776,1401],{},[860,2778,1405],{},[860,2780,1409],{},[860,2782,1412],{},[1340,2784,1417],{"id":1416},[856,2786,931,2787,1423,2789,1430,2792,943],{},[860,2788,1422],{},[937,2790,1429],{"href":1426,"rel":2791},[1428],[937,2793,1433],{"href":408},[1340,2795,1437],{"id":1436},[856,2797,1440],{},[1340,2799,1444],{"id":1443},[856,2801,931,2802,1450,2804,1456,2807,1462],{},[860,2803,1449],{},[937,2805,1455],{"href":1453,"rel":2806},[1428],[937,2808,1461],{"href":1459,"rel":2809},[1428],[856,2811,1465,2812,1469,2814,1472,2816,1476],{},[916,2813,1468],{},[860,2815,942],{},[937,2817,1475],{"href":104},[856,2819,1479],{},[1340,2821,1483],{"id":1482},[856,2823,1486,2824,1492],{},[937,2825,1491],{"href":1489,"rel":2826},[1428],[876,2828,2829,2839],{},[879,2830,2831],{},[882,2832,2833,2835,2837],{},[885,2834,1501],{},[885,2836,1504],{},[885,2838,1507],{},[895,2840,2841,2851,2861,2871],{},[882,2842,2843,2845,2847],{},[900,2844,1514],{},[900,2846,1517],{},[900,2848,2849],{},[860,2850,1522],{},[882,2852,2853,2855,2857],{},[900,2854,1527],{},[900,2856,1530],{},[900,2858,2859],{},[860,2860,1535],{},[882,2862,2863,2865,2867],{},[900,2864,1540],{},[900,2866,1543],{},[900,2868,2869],{},[860,2870,1548],{},[882,2872,2873,2875,2877],{},[900,2874,1553],{},[900,2876,1556],{},[900,2878,2879],{},[860,2880,1561],{},[856,2882,1564,2883,1567],{},[937,2884,237],{"href":238},[868,2886],{},[871,2888,1573],{"id":1572},[856,2890,1576,2891,1580],{},[860,2892,1579],{},[1336,2894,2895,2897,2913,2915,2931,2933,2937,3043,3051,3053],{"level":1338},[1340,2896,1586],{"id":1585},[856,2898,1589,2899,1593,2901,1596,2903,1600,2905,1600,2907,1607,2909,1611,2911,1614],{},[860,2900,1592],{},[860,2902,934],{},[860,2904,1599],{},[860,2906,1603],{},[860,2908,1606],{},[860,2910,1610],{},[937,2912,399],{"href":404},[1340,2914,1618],{"id":1617},[856,2916,931,2917,1623,2919,1626,2921,1630,2923,1634,2925,1600,2927,1641,2929,943],{},[860,2918,1303],{},[860,2920,1303],{},[860,2922,1629],{},[860,2924,1633],{},[860,2926,1637],{},[860,2928,1640],{},[860,2930,1629],{},[1340,2932,1647],{"id":1646},[856,2934,1650,2935,1653],{},[860,2936,862],{},[876,2938,2939,2947],{},[879,2940,2941],{},[882,2942,2943,2945],{},[885,2944,1662],{},[885,2946,1665],{},[895,2948,2949,2957,2965,2973,2981,2989,2999,3011,3023,3035],{},[882,2950,2951,2955],{},[900,2952,2953],{},[860,2954,1303],{},[900,2956,1676],{},[882,2958,2959,2963],{},[900,2960,2961],{},[860,2962,1629],{},[900,2964,1685],{},[882,2966,2967,2971],{},[900,2968,2969],{},[860,2970,1115],{},[900,2972,1694],{},[882,2974,2975,2979],{},[900,2976,2977],{},[860,2978,1701],{},[900,2980,1704],{},[882,2982,2983,2987],{},[900,2984,2985],{},[860,2986,1711],{},[900,2988,1714],{},[882,2990,2991,2995],{},[900,2992,2993],{},[860,2994,1721],{},[900,2996,1724,2997,1728],{},[860,2998,1727],{},[882,3000,3001,3005],{},[900,3002,3003],{},[860,3004,1599],{},[900,3006,1737,3007,1741,3009,1728],{},[860,3008,1740],{},[860,3010,1744],{},[882,3012,3013,3017],{},[900,3014,3015],{},[860,3016,1603],{},[900,3018,1737,3019,1741,3021,1728],{},[860,3020,1740],{},[860,3022,1744],{},[882,3024,3025,3029],{},[900,3026,3027],{},[860,3028,1606],{},[900,3030,1737,3031,1741,3033,1728],{},[860,3032,1740],{},[860,3034,1744],{},[882,3036,3037,3041],{},[900,3038,3039],{},[860,3040,1610],{},[900,3042,1777],{},[856,3044,931,3045,1782,3047,1786,3049,943],{},[860,3046,1115],{},[860,3048,1785],{},[860,3050,1789],{},[1340,3052,1793],{"id":1792},[856,3054,1796,3055,1304,3057,1803,3059,1304,3061,943],{},[860,3056,1799],{},[860,3058,1802],{},[937,3060,91],{"href":92},[937,3062,87],{"href":88},[868,3064],{},[871,3066,1813],{"id":1812},[1815,3068,1818],{"id":1817},[920,3070,3071],{"className":1821,"code":1822,"language":5,"meta":928,"style":928},[860,3072,3073,3077,3091,3109,3127,3143],{"__ignoreMap":928},[965,3074,3075],{"class":967,"line":968},[965,3076,1829],{"class":975},[965,3078,3079,3081,3083,3085,3087,3089],{"class":967,"line":1000},[965,3080,1835],{"class":1834},[965,3082,1839],{"class":1838},[965,3084,1842],{"class":1834},[965,3086,1040],{"class":1017},[965,3088,1848],{"class":1847},[965,3090,1851],{"class":975},[965,3092,3093,3095,3097,3099,3101,3103,3105,3107],{"class":967,"line":1006},[965,3094,1835],{"class":1834},[965,3096,1858],{"class":1838},[965,3098,1842],{"class":1834},[965,3100,1040],{"class":1017},[965,3102,1865],{"class":989},[965,3104,1868],{"class":993},[965,3106,1842],{"class":989},[965,3108,1851],{"class":975},[965,3110,3111,3113,3115,3117,3119,3121,3123,3125],{"class":967,"line":1033},[965,3112,1835],{"class":1834},[965,3114,1879],{"class":1838},[965,3116,1842],{"class":1834},[965,3118,1040],{"class":1017},[965,3120,1865],{"class":989},[965,3122,1888],{"class":993},[965,3124,1842],{"class":989},[965,3126,1851],{"class":975},[965,3128,3129,3131,3133,3135,3137,3139,3141],{"class":967,"line":1081},[965,3130,1835],{"class":1834},[965,3132,1899],{"class":1838},[965,3134,1842],{"class":1834},[965,3136,1040],{"class":1017},[965,3138,1865],{"class":989},[965,3140,1908],{"class":993},[965,3142,1911],{"class":989},[965,3144,3145],{"class":967,"line":1123},[965,3146,1916],{"class":975},[856,3148,1919],{},[876,3150,3151,3161],{},[879,3152,3153],{},[882,3154,3155,3157,3159],{},[885,3156,1928],{},[885,3158,1931],{},[885,3160,1934],{},[895,3162,3163,3183],{},[882,3164,3165,3169,3173],{},[900,3166,3167],{},[860,3168,1943],{},[900,3170,3171,1949],{},[860,3172,1948],{},[900,3174,3175,1600,3177,1600,3179,1600,3181],{},[860,3176,1954],{},[860,3178,1957],{},[860,3180,1960],{},[860,3182,1963],{},[882,3184,3185,3189,3191],{},[900,3186,3187],{},[860,3188,1970],{},[900,3190,1973],{},[900,3192,3193,1600,3195,1600,3197,1600,3199,1985],{},[860,3194,1954],{},[860,3196,1957],{},[860,3198,1960],{},[860,3200,1984],{},[856,3202,931,3203,1990,3205,1993],{},[860,3204,1943],{},[860,3206,1970],{},[1815,3208,1997],{"id":1996},[876,3210,3211,3219],{},[879,3212,3213],{},[882,3214,3215,3217],{},[885,3216,2006],{},[885,3218,2009],{},[895,3220,3221,3231,3239,3247],{},[882,3222,3223,3227],{},[900,3224,3225],{},[860,3226,942],{},[900,3228,2020,3229,2023],{},[860,3230,934],{},[882,3232,3233,3237],{},[900,3234,3235],{},[860,3236,2030],{},[900,3238,2033],{},[882,3240,3241,3245],{},[900,3242,3243],{},[860,3244,2040],{},[900,3246,2043],{},[882,3248,3249,3253],{},[900,3250,3251],{},[860,3252,2050],{},[900,3254,2053],{},[868,3256],{},[871,3258,2059],{"id":2058},[856,3260,931,3261,2064,3263,1304,3265,2069,3267,2072],{},[860,3262,1310],{},[860,3264,1303],{},[860,3266,1115],{},[860,3268,1374],{},[2074,3270,3271,3277,3281,3285],{},[2077,3272,2079,3273,2082,3275,1728],{},[937,3274,399],{"href":35},[860,3276,2085],{},[2077,3278,2088,3279],{},[860,3280,2091],{},[2077,3282,2094,3283,2098],{},[860,3284,2097],{},[2077,3286,2101,3287],{},[860,3288,1381],{},[856,3290,2106],{},[868,3292],{},[871,3294,2112],{"id":2111},[856,3296,2115,3297,2119],{},[860,3298,2118],{},[876,3300,3301,3315],{},[879,3302,3303],{},[882,3304,3305,3307,3309,3311,3313],{},[885,3306,2128],{},[885,3308,2131],{},[885,3310,2134],{},[885,3312,2137],{},[885,3314,2140],{},[895,3316,3317,3331,3345,3359,3373],{},[882,3318,3319,3321,3325,3327,3329],{},[900,3320,2147],{},[900,3322,3323],{},[860,3324,1349],{},[900,3326,2154],{},[900,3328,2157],{},[900,3330,2160],{},[882,3332,3333,3335,3339,3341,3343],{},[900,3334,2165],{},[900,3336,3337],{},[860,3338,1349],{},[900,3340,2172],{},[900,3342,2175],{},[900,3344,2160],{},[882,3346,3347,3349,3353,3355,3357],{},[900,3348,2182],{},[900,3350,3351],{},[860,3352,1391],{},[900,3354,2189],{},[900,3356,2157],{},[900,3358,2175],{},[882,3360,3361,3363,3367,3369,3371],{},[900,3362,2198],{},[900,3364,3365],{},[860,3366,1391],{},[900,3368,2205],{},[900,3370,2208],{},[900,3372,2208],{},[882,3374,3375,3377,3381,3383,3385],{},[900,3376,2215],{},[900,3378,3379],{},[860,3380,1115],{},[900,3382,2205],{},[900,3384,2208],{},[900,3386,2208],{},[856,3388,931,3389,2231,3391,2235],{},[860,3390,2230],{},[937,3392,147],{"href":2234},[868,3394],{},[871,3396,2241],{"id":2240},[876,3398,3399,3411],{},[879,3400,3401],{},[882,3402,3403,3405,3407,3409],{},[885,3404,2250],{},[885,3406,2253],{},[885,3408,2256],{},[885,3410,2259],{},[895,3412,3413,3427,3441,3455,3469,3485],{},[882,3414,3415,3419,3421,3425],{},[900,3416,3417],{},[860,3418,1561],{},[900,3420,2270],{},[900,3422,3423],{},[860,3424,1047],{},[900,3426,2277],{},[882,3428,3429,3433,3435,3439],{},[900,3430,3431],{},[860,3432,1522],{},[900,3434,2270],{},[900,3436,3437],{},[860,3438,2290],{},[900,3440,2293],{},[882,3442,3443,3447,3449,3453],{},[900,3444,3445],{},[860,3446,1535],{},[900,3448,2270],{},[900,3450,3451],{},[860,3452,2290],{},[900,3454,2308],{},[882,3456,3457,3461,3463,3467],{},[900,3458,3459],{},[860,3460,1548],{},[900,3462,2270],{},[900,3464,3465],{},[860,3466,2290],{},[900,3468,2323],{},[882,3470,3471,3475,3479,3483],{},[900,3472,3473],{},[860,3474,2330],{},[900,3476,3477],{},[860,3478,2335],{},[900,3480,3481],{},[860,3482,2290],{},[900,3484,2342],{},[882,3486,3487,3491,3495,3499],{},[900,3488,3489],{},[860,3490,2349],{},[900,3492,3493],{},[860,3494,2335],{},[900,3496,3497],{},[860,3498,1047],{},[900,3500,2360,3501,2363],{},[860,3502,1970],{},[856,3504,946,3505,2368],{},[937,3506,237],{"href":238},[2370,3508,2372],{},{"title":928,"searchDepth":1000,"depth":1000,"links":3510},[3511,3512,3513,3514,3515,3519,3520,3521],{"id":873,"depth":1000,"text":874},{"id":955,"depth":1000,"text":956},{"id":1330,"depth":1000,"text":1331},{"id":1572,"depth":1000,"text":1573},{"id":1812,"depth":1000,"text":1813,"children":3516},[3517,3518],{"id":1817,"depth":1006,"text":1818},{"id":1996,"depth":1006,"text":1997},{"id":2058,"depth":1000,"text":2059},{"id":2111,"depth":1000,"text":2112},{"id":2240,"depth":1000,"text":2241},{},{"title":99,"description":2386},1780436280703]