[{"data":1,"prerenderedAt":3371},["ShallowReactive",2],{"navLinks":3,"sidebar_docs_navigation_\u002Fdocs\u002Fiam":64,"navigation":257,"navLinks_footer":837,"\u002Fdocs\u002Fiam\u002Fessentials\u002Fpassword-reset_page":850,"\u002Fdocs\u002Fiam\u002Fessentials\u002Fpassword-reset_surround":2324,"\u002Fdocs\u002Fiam\u002Fessentials\u002Fpassword-reset":2327},{"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":163,"body":852,"description":2317,"extension":2318,"icon":21,"meta":2319,"module":2320,"navigation":8,"path":164,"rawbody":2321,"seo":2322,"stem":165,"__hash__":2323},"docs\u002Fdocs\u002Fiam\u002F01.essentials\u002F20.password-reset.md",{"type":853,"value":854,"toc":2291},"minimark",[855,859,862,871,878,883,957,961,964,1089,1104,1108,1307,1311,1317,1360,1376,1378,1385,1392,1396,1449,1453,1585,1591,1593,1600,1611,1614,1691,1694,1699,1783,1786,1790,2048,2051,2072,2074,2078,2174,2176,2180,2213,2217,2250,2254,2261,2287],[856,857,858],"p",{},"The password reset flow is a two-phase operation. The first phase initiates the flow by sending a signed magic link to the user's email. The second phase verifies the link, validates and hashes the new password, revokes all active sessions, and sends a security notification. The flow does not apply to OAuth-only accounts, which have no password to reset.",[860,861],"hr",{},[863,864,866,867],"h2",{"id":865},"initiation-post-authforgot-password","Initiation: ",[868,869,870],"code",{},"POST \u002Fauth\u002Fforgot-password",[856,872,873,874,877],{},"The initiation endpoint accepts a JSON body containing the user's email address, applies several layers of rate limiting, and always returns ",[868,875,876],{},"200"," regardless of whether the email was found. This prevents email enumeration.",[879,880,882],"h3",{"id":881},"request","Request",[884,885,890],"pre",{"className":886,"code":887,"language":888,"meta":889,"style":889},"language-http shiki shiki-themes light-plus light-plus dracula","POST \u002Fauth\u002Fforgot-password\nContent-Type: application\u002Fjson\n\n{ \"email\": \"user@example.com\" }\n","http","",[868,891,892,905,920,926],{"__ignoreMap":889},[893,894,897,901],"span",{"class":895,"line":896},"line",1,[893,898,900],{"class":899},"sZ328","POST",[893,902,904],{"class":903},"sDd4n"," \u002Fauth\u002Fforgot-password\n",[893,906,908,912,916],{"class":895,"line":907},2,[893,909,911],{"class":910},"scd-l","Content-Type",[893,913,915],{"class":914},"sl46w",":",[893,917,919],{"class":918},"sFB1V"," application\u002Fjson\n",[893,921,923],{"class":895,"line":922},3,[893,924,925],{"emptyLinePlaceholder":8},"\n",[893,927,929,932,936,940,942,945,949,952,954],{"class":895,"line":928},4,[893,930,931],{"class":903},"{ ",[893,933,935],{"class":934},"saJyd","\"",[893,937,939],{"class":938},"s_W10","email",[893,941,935],{"class":934},[893,943,915],{"class":944},"saOXh",[893,946,948],{"class":947},"sFkSl"," \"",[893,950,951],{"class":918},"user@example.com",[893,953,935],{"class":947},[893,955,956],{"class":903}," }\n",[879,958,960],{"id":959},"rate-limiting","Rate limiting",[856,962,963],{},"Four limiters protect the initiation endpoint before the email is looked up:",[965,966,967,992],"table",{},[968,969,970],"thead",{},[971,972,973,977,980,983,986,989],"tr",{},[974,975,976],"th",{},"Limiter",[974,978,979],{},"Key",[974,981,982],{},"Default points",[974,984,985],{},"Default duration",[974,987,988],{},"Default block",[974,990,991],{},"Purpose",[993,994,995,1019,1043,1064],"tbody",{},[971,996,997,1003,1008,1011,1014,1016],{},[998,999,1000],"td",{},[868,1001,1002],{},"globalEmailLimiter",[998,1004,1005],{},[868,1006,1007],{},"'global_emails'",[998,1009,1010],{},"shared system budget",[998,1012,1013],{},"—",[998,1015,1013],{},[998,1017,1018],{},"Caps total outgoing emails system-wide",[971,1020,1021,1026,1031,1034,1037,1040],{},[998,1022,1023],{},[868,1024,1025],{},"ipLimiter",[998,1027,1028],{},[868,1029,1030],{},"${IP}",[998,1032,1033],{},"5",[998,1035,1036],{},"24hr",[998,1038,1039],{},"4hr",[998,1041,1042],{},"Caps reset requests per IP per day",[971,1044,1045,1050,1055,1057,1059,1061],{},[998,1046,1047],{},[868,1048,1049],{},"emailLimiter",[998,1051,1052],{},[868,1053,1054],{},"${email}",[998,1056,1033],{},[998,1058,1036],{},[998,1060,1039],{},[998,1062,1063],{},"Caps reset requests per email per day",[971,1065,1066,1072,1077,1080,1083,1086],{},[998,1067,1068,1071],{},[868,1069,1070],{},"uniLimiter"," (union)",[998,1073,1074],{},[868,1075,1076],{},"${IP}_${email}",[998,1078,1079],{},"burst + slow",[998,1081,1082],{},"1s \u002F 30min",[998,1084,1085],{},"30min",[998,1087,1088],{},"Blocks rapid or sustained composite attempts on failure",[856,1090,1091,1092,1094,1095,1097,1098,1100,1101,1103],{},"The ",[868,1093,1002],{}," and ",[868,1096,1025],{}," run before schema validation. The ",[868,1099,1049],{}," runs after validation. The ",[868,1102,1070],{}," is only consumed when the email is not found, adding a cost to probing non-existent addresses.",[879,1105,1107],{"id":1106},"initiation-flow","Initiation flow",[1109,1110,1112,1117,1128,1132,1148,1152,1163,1167,1182,1185,1256,1260,1288,1292],"steps",{"level":1111},"4",[1113,1114,1116],"h4",{"id":1115},"schema-validation","Schema validation",[856,1118,1119,1120,1123,1124,1127],{},"The request body is validated with a Zod schema that checks the email format. Invalid or XSS-flagged input returns ",[868,1121,1122],{},"400"," or ",[868,1125,1126],{},"403"," before any database query runs.",[1113,1129,1131],{"id":1130},"user-lookup","User lookup",[856,1133,1134,1137,1138,1141,1142,1144,1145,1147],{},[868,1135,1136],{},"sendTempPasswordResetLink"," queries the ",[868,1139,1140],{},"users"," table for a matching email. If no user is found, the ",[868,1143,1070],{}," is consumed for the composite key ",[868,1146,1076],{}," and the function returns without sending an email.",[1113,1149,1151],{"id":1150},"oauth-only-rejection","OAuth-only rejection",[856,1153,1154,1155,1158,1159,1162],{},"If the user's ",[868,1156,1157],{},"password_hash"," is ",[868,1160,1161],{},"'no_password'",", the user authenticated exclusively through OAuth and has no password to reset. The function returns without sending an email.",[1113,1164,1166],{"id":1165},"link-generation","Link generation",[856,1168,1169,1170,1173,1174,1177,1178,1181],{},"A unique JTI is generated using ",[868,1171,1172],{},"crypto.randomUUID()"," + ",[868,1175,1176],{},"crypto.randomBytes(64).toString('hex')",", producing a 164-character string. A random challenge is generated with ",[868,1179,1180],{},"crypto.randomBytes(128).toString('hex')",", then SHA-256 hashed.",[856,1183,1184],{},"A temporary JWT is signed with:",[965,1186,1187,1197],{},[968,1188,1189],{},[971,1190,1191,1194],{},[974,1192,1193],{},"Field",[974,1195,1196],{},"Value",[993,1198,1199,1211,1223,1236,1246],{},[971,1200,1201,1206],{},[998,1202,1203],{},[868,1204,1205],{},"purpose",[998,1207,1208],{},[868,1209,1210],{},"PASSWORD_RESET",[971,1212,1213,1218],{},[998,1214,1215],{},[868,1216,1217],{},"subject",[998,1219,1220],{},[868,1221,1222],{},"PASSWORD_RESET_{visitor_id}",[971,1224,1225,1230],{},[998,1226,1227],{},[868,1228,1229],{},"visitor",[998,1231,1232,1233],{},"The user's ",[868,1234,1235],{},"visitor_id",[971,1237,1238,1243],{},[998,1239,1240],{},[868,1241,1242],{},"randomHashed",[998,1244,1245],{},"SHA-256 hash of the random challenge",[971,1247,1248,1253],{},[998,1249,1250],{},[868,1251,1252],{},"jti",[998,1254,1255],{},"The 164-character JTI",[1113,1257,1259],{"id":1258},"link-delivery","Link delivery",[856,1261,1262,1263,1094,1266,1269,1270,1272,1273,1272,1276,1279,1280,1283,1284,1287],{},"The reset URL is built from ",[868,1264,1265],{},"magic_links.paths.pathForPasswordResetLink",[868,1267,1268],{},"magic_links.domain",", with ",[868,1271,1229],{},", ",[868,1274,1275],{},"token",[868,1277,1278],{},"random",", and ",[868,1281,1282],{},"reason"," appended as query parameters. The link is sent to the user's email via ",[868,1285,1286],{},"resetPasswordEmail",".",[1113,1289,1291],{"id":1290},"minimum-response-time","Minimum response time",[856,1293,1294,1295,1298,1299,1302,1303,1306],{},"The controller enforces a 3-second minimum response time using ",[868,1296,1297],{},"Date.now()"," at the start and ",[868,1300,1301],{},"waitSomeTime()"," in the ",[868,1304,1305],{},"finally"," block. This prevents timing-based enumeration regardless of how quickly the database query completes.",[879,1308,1310],{"id":1309},"response","Response",[856,1312,1313,1314,1316],{},"The endpoint always returns ",[868,1315,876],{}," after the minimum delay, whether or not an email was sent:",[884,1318,1321],{"className":1319,"code":1320,"language":5,"meta":889,"style":889},"language-json shiki shiki-themes light-plus light-plus dracula","{ \"success\": true, \"details\": \"A link to restart your password was sent to your email!\" }\n",[868,1322,1323],{"__ignoreMap":889},[893,1324,1325,1327,1329,1332,1334,1336,1340,1342,1344,1347,1349,1351,1353,1356,1358],{"class":895,"line":896},[893,1326,931],{"class":903},[893,1328,935],{"class":934},[893,1330,1331],{"class":938},"success",[893,1333,935],{"class":934},[893,1335,915],{"class":944},[893,1337,1339],{"class":1338},"sjR7W"," true",[893,1341,1272],{"class":903},[893,1343,935],{"class":934},[893,1345,1346],{"class":938},"details",[893,1348,935],{"class":934},[893,1350,915],{"class":944},[893,1352,948],{"class":947},[893,1354,1355],{"class":918},"A link to restart your password was sent to your email!",[893,1357,935],{"class":947},[893,1359,956],{"class":903},[1361,1362,1363],"note",{},[856,1364,1365,1366,1368,1369,1372,1373,1375],{},"If any rate limiter blocks the request before the ",[868,1367,1305],{}," block, the response is the limiter's error (typically ",[868,1370,1371],{},"429",") rather than the generic ",[868,1374,876],{},". The 3-second delay only applies to the success path.",[860,1377],{},[863,1379,1381,1382],{"id":1380},"link-verification-get-authreset-password","Link verification: ",[868,1383,1384],{},"GET \u002Fauth\u002Freset-password",[856,1386,1387,1388,1391],{},"When the user clicks the link in their email, the GET request validates the signed token without consuming it. The link can be visited up to ",[868,1389,1390],{},"allowedPerSuccessfulGet"," times (default: 5) before it is considered expired.",[879,1393,1395],{"id":1394},"query-parameters","Query parameters",[965,1397,1398,1408],{},[968,1399,1400],{},[971,1401,1402,1405],{},[974,1403,1404],{},"Parameter",[974,1406,1407],{},"Description",[993,1409,1410,1419,1428,1438],{},[971,1411,1412,1416],{},[998,1413,1414],{},[868,1415,1275],{},[998,1417,1418],{},"The signed temporary JWT",[971,1420,1421,1425],{},[998,1422,1423],{},[868,1424,1278],{},[998,1426,1427],{},"The raw random challenge (256 hex characters from 128 bytes)",[971,1429,1430,1434],{},[998,1431,1432],{},[868,1433,1229],{},[998,1435,1232,1436],{},[868,1437,1235],{},[971,1439,1440,1444],{},[998,1441,1442],{},[868,1443,1282],{},[998,1445,1446,1447],{},"Must be ",[868,1448,1210],{},[879,1450,1452],{"id":1451},"verification-steps","Verification steps",[1109,1454,1455,1458,1469,1473,1480,1484,1492,1496,1507,1511,1514,1551,1557,1561,1573,1577],{"level":1111},[1113,1456,1116],{"id":1457},"schema-validation-1",[856,1459,1460,1461,1464,1465,1123,1467,1287],{},"The query string is validated with a Zod schema (",[868,1462,1463],{},"buildInMfaFlows","). Malformed or XSS-flagged values return ",[868,1466,1122],{},[868,1468,1126],{},[1113,1470,1472],{"id":1471},"ip-rate-limit","IP rate limit",[856,1474,1475,1476,1479],{},"A per-IP limiter (",[868,1477,1478],{},"consecutiveForIpPassword",") is checked before JWT verification. Repeated failures from the same IP are blocked progressively.",[1113,1481,1483],{"id":1482},"jwt-verification","JWT verification",[856,1485,1486,1489,1490,1287],{},[868,1487,1488],{},"verifyTempJwtLink"," verifies the signed token. An invalid or expired token returns ",[868,1491,1122],{},[1113,1493,1495],{"id":1494},"visitor-match","Visitor match",[856,1497,1091,1498,1500,1501,1504,1505,1287],{},[868,1499,1229],{}," query parameter must match ",[868,1502,1503],{},"payload.visitor",". A mismatch returns ",[868,1506,1122],{},[1113,1508,1510],{"id":1509},"payload-integrity","Payload integrity",[856,1512,1513],{},"The following checks run against the decoded payload:",[1515,1516,1517,1530,1538],"ul",{},[1518,1519,1520,1523,1524,1526,1527,1529],"li",{},[868,1521,1522],{},"payload.purpose"," must equal ",[868,1525,1282],{}," (",[868,1528,1210],{},")",[1518,1531,1532,1523,1535],{},[868,1533,1534],{},"payload.subject",[868,1536,1537],{},"PASSWORD_RESET_{visitor}",[1518,1539,1540,1541,1543,1544,1547,1548],{},"The SHA-256 hash of ",[868,1542,1278],{}," must match ",[868,1545,1546],{},"payload.randomHashed"," via ",[868,1549,1550],{},"crypto.timingSafeEqual",[856,1552,1553,1554,1287],{},"Any mismatch returns ",[868,1555,1556],{},"401",[1113,1558,1560],{"id":1559},"jti-replay-check","JTI replay check",[856,1562,1091,1563,1566,1567,1569,1570,1287],{},[868,1564,1565],{},"usedJtiLimiter"," is checked. If the JTI has been blocked (consumed on a prior POST), the request returns ",[868,1568,1122],{}," with ",[868,1571,1572],{},"'Link is not valid or expired'",[1113,1574,1576],{"id":1575},"get-count-enforcement","GET count enforcement",[856,1578,1579,1580,1582,1583,1287],{},"An in-memory counter tracks how many times this JTI has been accessed via GET. Exceeding ",[868,1581,1390],{}," (default 5) returns ",[868,1584,1122],{},[856,1586,1587,1588,1590],{},"The GET handler returns ",[868,1589,876],{}," without a body if all checks pass. The client uses this to confirm the link is valid before rendering the password reset form.",[860,1592],{},[863,1594,1596,1597],{"id":1595},"password-submission-post-authreset-password","Password submission: ",[868,1598,1599],{},"POST \u002Fauth\u002Freset-password",[856,1601,1602,1603,1606,1607,1610],{},"The POST to the same route runs the same ",[868,1604,1605],{},"linkPasswordVerification"," middleware as the GET, then delegates to ",[868,1608,1609],{},"verifyNewPassword"," to validate and apply the new password.",[879,1612,882],{"id":1613},"request-1",[884,1615,1617],{"className":886,"code":1616,"language":888,"meta":889,"style":889},"POST \u002Fauth\u002Freset-password?token=\u003Cjwt>&random=\u003Chex>&visitor=\u003Cid>&reason=PASSWORD_RESET\nContent-Type: application\u002Fjson\n\n{\n  \"password\": \"new-password\",\n  \"confirmedPassword\": \"new-password\"\n}\n",[868,1618,1619,1626,1634,1638,1643,1666,1685],{"__ignoreMap":889},[893,1620,1621,1623],{"class":895,"line":896},[893,1622,900],{"class":899},[893,1624,1625],{"class":903}," \u002Fauth\u002Freset-password?token=\u003Cjwt>&random=\u003Chex>&visitor=\u003Cid>&reason=PASSWORD_RESET\n",[893,1627,1628,1630,1632],{"class":895,"line":907},[893,1629,911],{"class":910},[893,1631,915],{"class":914},[893,1633,919],{"class":918},[893,1635,1636],{"class":895,"line":922},[893,1637,925],{"emptyLinePlaceholder":8},[893,1639,1640],{"class":895,"line":928},[893,1641,1642],{"class":903},"{\n",[893,1644,1646,1649,1652,1654,1656,1658,1661,1663],{"class":895,"line":1645},5,[893,1647,1648],{"class":934},"  \"",[893,1650,1651],{"class":938},"password",[893,1653,935],{"class":934},[893,1655,915],{"class":944},[893,1657,948],{"class":947},[893,1659,1660],{"class":918},"new-password",[893,1662,935],{"class":947},[893,1664,1665],{"class":903},",\n",[893,1667,1669,1671,1674,1676,1678,1680,1682],{"class":895,"line":1668},6,[893,1670,1648],{"class":934},[893,1672,1673],{"class":938},"confirmedPassword",[893,1675,935],{"class":934},[893,1677,915],{"class":944},[893,1679,948],{"class":947},[893,1681,1660],{"class":918},[893,1683,1684],{"class":947},"\"\n",[893,1686,1688],{"class":895,"line":1687},7,[893,1689,1690],{"class":903},"}\n",[879,1692,960],{"id":1693},"rate-limiting-1",[856,1695,1696,1697,915],{},"Three limiters protect the POST submission inside ",[868,1698,1609],{},[965,1700,1701,1717],{},[968,1702,1703],{},[971,1704,1705,1707,1709,1711,1713,1715],{},[974,1706,976],{},[974,1708,979],{},[974,1710,982],{},[974,1712,985],{},[974,1714,988],{},[974,1716,991],{},[993,1718,1719,1742,1761],{},[971,1720,1721,1726,1731,1734,1737,1739],{},[998,1722,1723],{},[868,1724,1725],{},"ipLimit",[998,1727,1728],{},[868,1729,1730],{},"${JTI}",[998,1732,1733],{},"6",[998,1735,1736],{},"10min",[998,1738,1736],{},[998,1740,1741],{},"Caps attempts per verification session",[971,1743,1744,1748,1752,1754,1756,1758],{},[998,1745,1746],{},[868,1747,1725],{},[998,1749,1750],{},[868,1751,1030],{},[998,1753,1733],{},[998,1755,1736],{},[998,1757,1736],{},[998,1759,1760],{},"Caps attempts per IP",[971,1762,1763,1767,1772,1774,1777,1780],{},[998,1764,1765,1071],{},[868,1766,1070],{},[998,1768,1769],{},[868,1770,1771],{},"${IP}_${visitor_id}",[998,1773,1079],{},[998,1775,1776],{},"1s \u002F 10min",[998,1778,1779],{},"30min \u002F 10min",[998,1781,1782],{},"Blocks rapid or sustained composite attempts",[856,1784,1785],{},"Each failed attempt increments the corresponding consecutive cache. Exceeding the threshold blocks further attempts for the cache duration (10–20 minutes).",[879,1787,1789],{"id":1788},"submission-flow","Submission flow",[1109,1791,1792,1796,1805,1809,1824,1828,1833,1836,1850,1854,1866,1870,1879,1926,1930,1936,1939,1949,1953,1980,1990,1994,1997,2017,2021,2027,2031,2041,2045],{"level":1111},[1113,1793,1795],{"id":1794},"content-type-check","Content type check",[856,1797,1798,1799,1802,1803,1287],{},"The request must have ",[868,1800,1801],{},"Content-Type: application\u002Fjson",". Any other content type returns ",[868,1804,1122],{},[1113,1806,1808],{"id":1807},"link-purpose-check","Link purpose check",[856,1810,1811,1814,1815,1094,1817,1814,1820,1504,1822,1287],{},[868,1812,1813],{},"req.link.purpose"," must be ",[868,1816,1210],{},[868,1818,1819],{},"req.link.subject",[868,1821,1537],{},[868,1823,1122],{},[1113,1825,1827],{"id":1826},"rate-limit-checks","Rate limit checks",[856,1829,1830,1831,1287],{},"The three limiters above are checked in order: JTI limiter, IP limiter, then composite union limiter. Any failure returns ",[868,1832,1371],{},[1113,1834,1116],{"id":1835},"schema-validation-2",[856,1837,1838,1839,1842,1843,1094,1845,1847,1848,1287],{},"The request body is validated against the ",[868,1840,1841],{},"passwords"," Zod schema, which requires both ",[868,1844,1651],{},[868,1846,1673],{},". Invalid input returns ",[868,1849,1122],{},[1113,1851,1853],{"id":1852},"password-match","Password match",[856,1855,1856,1094,1858,1860,1861,1569,1863,1287],{},[868,1857,1651],{},[868,1859,1673],{}," are compared. A mismatch returns ",[868,1862,1122],{},[868,1864,1865],{},"{ \"error\": \"Password doesn't match\", \"banned\": false }",[1113,1867,1869],{"id":1868},"breach-check","Breach check",[856,1871,1872,1873,1876,1877,915],{},"The password is checked against the HaveIBeenPwned API via ",[868,1874,1875],{},"isPwned",". If the password appears in a known data breach, the request is rejected with ",[868,1878,1122],{},[884,1880,1882],{"className":1319,"code":1881,"language":5,"meta":889,"style":889},"{\n  \"ok\": false,\n  \"error\": \"Our system identified this password in X data breaches. Please choose a different password.\"\n}\n",[868,1883,1884,1888,1904,1922],{"__ignoreMap":889},[893,1885,1886],{"class":895,"line":896},[893,1887,1642],{"class":903},[893,1889,1890,1892,1895,1897,1899,1902],{"class":895,"line":907},[893,1891,1648],{"class":934},[893,1893,1894],{"class":938},"ok",[893,1896,935],{"class":934},[893,1898,915],{"class":944},[893,1900,1901],{"class":1338}," false",[893,1903,1665],{"class":903},[893,1905,1906,1908,1911,1913,1915,1917,1920],{"class":895,"line":922},[893,1907,1648],{"class":934},[893,1909,1910],{"class":938},"error",[893,1912,935],{"class":934},[893,1914,915],{"class":944},[893,1916,948],{"class":947},[893,1918,1919],{"class":918},"Our system identified this password in X data breaches. Please choose a different password.",[893,1921,1684],{"class":947},[893,1923,1924],{"class":895,"line":928},[893,1925,1690],{"class":903},[1113,1927,1929],{"id":1928},"password-hashing","Password hashing",[856,1931,1932,1933,1287],{},"The new password is hashed with Argon2id via ",[868,1934,1935],{},"hashPassword",[1113,1937,1131],{"id":1938},"user-lookup-1",[856,1940,1941,1942,1944,1945,1948],{},"The user record is fetched from the database using the ",[868,1943,1235],{}," from the link token, locked with ",[868,1946,1947],{},"FOR UPDATE"," inside a transaction.",[1113,1950,1952],{"id":1951},"password-update","Password update",[884,1954,1958],{"className":1955,"code":1956,"language":1957,"meta":889,"style":889},"language-sql shiki shiki-themes light-plus light-plus dracula","UPDATE users\nSET password_hash = ?\nWHERE id = ? AND visitor_id = ?\nLIMIT 1\n","sql",[868,1959,1960,1965,1970,1975],{"__ignoreMap":889},[893,1961,1962],{"class":895,"line":896},[893,1963,1964],{},"UPDATE users\n",[893,1966,1967],{"class":895,"line":907},[893,1968,1969],{},"SET password_hash = ?\n",[893,1971,1972],{"class":895,"line":922},[893,1973,1974],{},"WHERE id = ? AND visitor_id = ?\n",[893,1976,1977],{"class":895,"line":928},[893,1978,1979],{},"LIMIT 1\n",[856,1981,1982,1983,1986,1987,1989],{},"If ",[868,1984,1985],{},"affectedRows"," is not exactly 1, the transaction rolls back and ",[868,1988,1122],{}," is returned.",[1113,1991,1993],{"id":1992},"session-revocation","Session revocation",[856,1995,1996],{},"All active refresh tokens for the user are invalidated:",[884,1998,2000],{"className":1955,"code":1999,"language":1957,"meta":889,"style":889},"UPDATE refresh_tokens\nSET valid = 0\nWHERE user_id = ? AND valid = 1\n",[868,2001,2002,2007,2012],{"__ignoreMap":889},[893,2003,2004],{"class":895,"line":896},[893,2005,2006],{},"UPDATE refresh_tokens\n",[893,2008,2009],{"class":895,"line":907},[893,2010,2011],{},"SET valid = 0\n",[893,2013,2014],{"class":895,"line":922},[893,2015,2016],{},"WHERE user_id = ? AND valid = 1\n",[1113,2018,2020],{"id":2019},"jti-block","JTI block",[856,2022,2023,2024,2026],{},"The JTI is blocked in ",[868,2025,1565],{}," for 20 minutes, preventing link reuse.",[1113,2028,2030],{"id":2029},"notification-email","Notification email",[856,2032,2033,2034,2037,2038,1287],{},"After a successful commit, a security notification email is sent to the user's address with the subject ",[868,2035,2036],{},"\"Security Alert: Password Reset Successful\"",". The email includes a link to the login page configured at ",[868,2039,2040],{},"magic_links.notificationEmail.loginPageLink",[1113,2042,2044],{"id":2043},"rate-limiter-cleanup","Rate limiter cleanup",[856,2046,2047],{},"All consecutive caches and the union limiter for the composite key are reset on success.",[879,2049,1310],{"id":2050},"response-1",[884,2052,2054],{"className":1319,"code":2053,"language":5,"meta":889,"style":889},"{ \"success\": true }\n",[868,2055,2056],{"__ignoreMap":889},[893,2057,2058,2060,2062,2064,2066,2068,2070],{"class":895,"line":896},[893,2059,931],{"class":903},[893,2061,935],{"class":934},[893,2063,1331],{"class":938},[893,2065,935],{"class":934},[893,2067,915],{"class":944},[893,2069,1339],{"class":1338},[893,2071,956],{"class":903},[860,2073],{},[863,2075,2077],{"id":2076},"security-properties","Security properties",[965,2079,2080,2089],{},[968,2081,2082],{},[971,2083,2084,2087],{},[974,2085,2086],{},"Property",[974,2088,1196],{},[993,2090,2091,2102,2114,2125,2133,2144,2152,2159,2166],{},[971,2092,2093,2096],{},[998,2094,2095],{},"Enumeration protection",[998,2097,2098,2099,2101],{},"Always returns ",[868,2100,876],{}," on the initiation endpoint after a 3-second minimum delay",[971,2103,2104,2107],{},[998,2105,2106],{},"OAuth accounts",[998,2108,2109,2110,2113],{},"Users with ",[868,2111,2112],{},"password_hash = 'no_password'"," are silently skipped",[971,2115,2116,2119],{},[998,2117,2118],{},"Link integrity",[998,2120,2121,2122,2124],{},"Random challenge verified with ",[868,2123,1550],{},"; purpose and subject claims validated",[971,2126,2127,2130],{},[998,2128,2129],{},"Link reuse",[998,2131,2132],{},"JTI blocked for 20 minutes after successful POST",[971,2134,2135,2138],{},[998,2136,2137],{},"Link expiry",[998,2139,2140,2141],{},"Determined by the temporary JWT TTL configured in ",[868,2142,2143],{},"magic_links",[971,2145,2146,2149],{},[998,2147,2148],{},"GET limit",[998,2150,2151],{},"Default 5 previews per link before it is considered expired",[971,2153,2154,2156],{},[998,2155,1869],{},[998,2157,2158],{},"HaveIBeenPwned API called before storing the new hash",[971,2160,2161,2163],{},[998,2162,1993],{},[998,2164,2165],{},"All active refresh tokens invalidated on success",[971,2167,2168,2171],{},[998,2169,2170],{},"Notification",[998,2172,2173],{},"Security email sent to confirm the change; alerts the user if unauthorized",[860,2175],{},[863,2177,2179],{"id":2178},"configuration-reference","Configuration reference",[2181,2182,2183,2194,2199,2206],"field-group",{},[2184,2185,2188],"field",{"name":1265,"type":2186,":required":2187},"string","true",[856,2189,2190,2191,2193],{},"The path component of the password reset URL. Combined with ",[868,2192,1268],{}," to build the full reset link sent in the email.",[2184,2195,2196],{"name":2040,"type":2186,":required":2187},[856,2197,2198],{},"URL of the login page, included in the post-reset security notification email as the call-to-action link.",[2184,2200,2203],{"name":2201,"type":2202,"default":1033},"magic_links.thresholds.linkPasswordVerification.allowedPerSuccessfulGet","number",[856,2204,2205],{},"Number of times a password reset link may be visited via GET before it is considered expired.",[2184,2207,2210],{"name":2208,"type":2202,"default":2209},"magic_links.thresholds.linkPasswordVerification.allowedPerSuccessfulPost","3",[856,2211,2212],{},"Number of POST submission attempts allowed per successful link verification session.",[879,2214,2216],{"id":2215},"initiation-rate-limiters","Initiation rate limiters",[2181,2218,2219,2229,2238,2244],{},[2184,2220,2223],{"name":2221,"type":2222},"rate_limiters.initPasswordResetLimiters.unionLimiters.limit","object",[856,2224,2225,2226,2228],{},"Burst limiter for the ",[868,2227,1076],{}," composite key. Defaults: 1 point, 1s duration, 30min block. Consumed only on failed email lookups.",[2184,2230,2232],{"name":2231,"type":2222},"rate_limiters.initPasswordResetLimiters.unionLimiters.longLimiter",[856,2233,2234,2235,2237],{},"Slow limiter for the ",[868,2236,1076],{}," composite key. Defaults: 4 points, 30min duration, 15min block.",[2184,2239,2241],{"name":2240,"type":2222},"rate_limiters.initPasswordResetLimiters.ipLimiter",[856,2242,2243],{},"Per-IP limiter. Defaults: 5 points, 24hr duration, 4hr block.",[2184,2245,2247],{"name":2246,"type":2222},"rate_limiters.initPasswordResetLimiters.emailLimiter",[856,2248,2249],{},"Per-email limiter. Defaults: 5 points, 24hr duration, 4hr block.",[879,2251,2253],{"id":2252},"verification-rate-limiters","Verification rate limiters",[856,2255,2256,2257,2260],{},"These use the ",[868,2258,2259],{},"tempPostRoutesLimiters"," limiter group shared with other temporary-link POST routes:",[2181,2262,2263,2272,2281],{},[2184,2264,2266],{"name":2265,"type":2222},"rate_limiters.tempPostRoutesLimiters.unionLimiters.limit",[856,2267,2268,2269,2271],{},"Burst limiter keyed by ",[868,2270,1771],{},". Defaults: 1 point, 1s duration, 30min block.",[2184,2273,2275],{"name":2274,"type":2222},"rate_limiters.tempPostRoutesLimiters.unionLimiters.slowLimit",[856,2276,2277,2278,2280],{},"Slow limiter keyed by ",[868,2279,1771],{},". Defaults: 5 points, 10min duration, 10min block.",[2184,2282,2284],{"name":2283,"type":2222},"rate_limiters.tempPostRoutesLimiters.ipLimit",[856,2285,2286],{},"Per-IP and per-JTI limiter. Defaults: 6 points, 10min duration, 10min block.",[2288,2289,2290],"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 .scd-l, html code.shiki .scd-l{--shiki-light:#800000;--shiki-default:#800000;--shiki-dark:#FF79C6}html pre.shiki code .sl46w, html code.shiki .sl46w{--shiki-light:#0000FF;--shiki-default:#0000FF;--shiki-dark:#FF79C6}html pre.shiki code .sFB1V, html code.shiki .sFB1V{--shiki-light:#A31515;--shiki-default:#A31515;--shiki-dark:#F1FA8C}html pre.shiki code .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 .saOXh, html code.shiki .saOXh{--shiki-light:#000000;--shiki-default:#000000;--shiki-dark:#FF79C6}html pre.shiki code .sFkSl, html code.shiki .sFkSl{--shiki-light:#A31515;--shiki-default:#A31515;--shiki-dark:#E9F284}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 .sjR7W, html code.shiki .sjR7W{--shiki-light:#0000FF;--shiki-default:#0000FF;--shiki-dark:#BD93F9}",{"title":889,"searchDepth":907,"depth":907,"links":2292},[2293,2300,2305,2312,2313],{"id":865,"depth":907,"text":2294,"children":2295},"Initiation: POST \u002Fauth\u002Fforgot-password",[2296,2297,2298,2299],{"id":881,"depth":922,"text":882},{"id":959,"depth":922,"text":960},{"id":1106,"depth":922,"text":1107},{"id":1309,"depth":922,"text":1310},{"id":1380,"depth":907,"text":2301,"children":2302},"Link verification: GET \u002Fauth\u002Freset-password",[2303,2304],{"id":1394,"depth":922,"text":1395},{"id":1451,"depth":922,"text":1452},{"id":1595,"depth":907,"text":2306,"children":2307},"Password submission: POST \u002Fauth\u002Freset-password",[2308,2309,2310,2311],{"id":1613,"depth":922,"text":882},{"id":1693,"depth":922,"text":960},{"id":1788,"depth":922,"text":1789},{"id":2050,"depth":922,"text":1310},{"id":2076,"depth":907,"text":2077},{"id":2178,"depth":907,"text":2179,"children":2314},[2315,2316],{"id":2215,"depth":922,"text":2216},{"id":2252,"depth":922,"text":2253},"The full password reset lifecycle in the IAM service, from initiation via POST \u002Fauth\u002Fforgot-password through link verification and new password submission at POST \u002Fauth\u002Freset-password, including rate limiting, breach checking, and post-reset notifications.","md",{},null,"---\ntitle: Password Reset\ndescription: The full password reset lifecycle in the IAM service, from initiation via POST \u002Fauth\u002Fforgot-password through link verification and new password submission at POST \u002Fauth\u002Freset-password, including rate limiting, breach checking, and post-reset notifications.\nicon: i-lucide-key-round\n---\n\nThe password reset flow is a two-phase operation. The first phase initiates the flow by sending a signed magic link to the user's email. The second phase verifies the link, validates and hashes the new password, revokes all active sessions, and sends a security notification. The flow does not apply to OAuth-only accounts, which have no password to reset.\n\n---\n\n## Initiation: `POST \u002Fauth\u002Fforgot-password`\n\nThe initiation endpoint accepts a JSON body containing the user's email address, applies several layers of rate limiting, and always returns `200` regardless of whether the email was found. This prevents email enumeration.\n\n### Request\n\n```http\nPOST \u002Fauth\u002Fforgot-password\nContent-Type: application\u002Fjson\n\n{ \"email\": \"user@example.com\" }\n```\n\n### Rate limiting\n\nFour limiters protect the initiation endpoint before the email is looked up:\n\n| Limiter | Key | Default points | Default duration | Default block | Purpose |\n|---|---|---|---|---|---|\n| `globalEmailLimiter` | `'global_emails'` | shared system budget | — | — | Caps total outgoing emails system-wide |\n| `ipLimiter` | `${IP}` | 5 | 24hr | 4hr | Caps reset requests per IP per day |\n| `emailLimiter` | `${email}` | 5 | 24hr | 4hr | Caps reset requests per email per day |\n| `uniLimiter` (union) | `${IP}_${email}` | burst + slow | 1s \u002F 30min | 30min | Blocks rapid or sustained composite attempts on failure |\n\nThe `globalEmailLimiter` and `ipLimiter` run before schema validation. The `emailLimiter` runs after validation. The `uniLimiter` is only consumed when the email is not found, adding a cost to probing non-existent addresses.\n\n### Initiation flow\n\n::steps{level=\"4\"}\n#### Schema validation\n\nThe request body is validated with a Zod schema that checks the email format. Invalid or XSS-flagged input returns `400` or `403` before any database query runs.\n\n#### User lookup\n\n`sendTempPasswordResetLink` queries the `users` table for a matching email. If no user is found, the `uniLimiter` is consumed for the composite key `${IP}_${email}` and the function returns without sending an email.\n\n#### OAuth-only rejection\n\nIf the user's `password_hash` is `'no_password'`, the user authenticated exclusively through OAuth and has no password to reset. The function returns without sending an email.\n\n#### Link generation\n\nA unique JTI is generated using `crypto.randomUUID()` + `crypto.randomBytes(64).toString('hex')`, producing a 164-character string. A random challenge is generated with `crypto.randomBytes(128).toString('hex')`, then SHA-256 hashed.\n\nA temporary JWT is signed with:\n\n| Field | Value |\n|---|---|\n| `purpose` | `PASSWORD_RESET` |\n| `subject` | `PASSWORD_RESET_{visitor_id}` |\n| `visitor` | The user's `visitor_id` |\n| `randomHashed` | SHA-256 hash of the random challenge |\n| `jti` | The 164-character JTI |\n\n#### Link delivery\n\nThe reset URL is built from `magic_links.paths.pathForPasswordResetLink` and `magic_links.domain`, with `visitor`, `token`, `random`, and `reason` appended as query parameters. The link is sent to the user's email via `resetPasswordEmail`.\n\n#### Minimum response time\n\nThe controller enforces a 3-second minimum response time using `Date.now()` at the start and `waitSomeTime()` in the `finally` block. This prevents timing-based enumeration regardless of how quickly the database query completes.\n::\n\n### Response\n\nThe endpoint always returns `200` after the minimum delay, whether or not an email was sent:\n\n```json\n{ \"success\": true, \"details\": \"A link to restart your password was sent to your email!\" }\n```\n\n::note\nIf any rate limiter blocks the request before the `finally` block, the response is the limiter's error (typically `429`) rather than the generic `200`. The 3-second delay only applies to the success path.\n::\n\n---\n\n## Link verification: `GET \u002Fauth\u002Freset-password`\n\nWhen the user clicks the link in their email, the GET request validates the signed token without consuming it. The link can be visited up to `allowedPerSuccessfulGet` times (default: 5) before it is considered expired.\n\n### Query parameters\n\n| Parameter | Description |\n|---|---|\n| `token` | The signed temporary JWT |\n| `random` | The raw random challenge (256 hex characters from 128 bytes) |\n| `visitor` | The user's `visitor_id` |\n| `reason` | Must be `PASSWORD_RESET` |\n\n### Verification steps\n\n::steps{level=\"4\"}\n#### Schema validation\n\nThe query string is validated with a Zod schema (`buildInMfaFlows`). Malformed or XSS-flagged values return `400` or `403`.\n\n#### IP rate limit\n\nA per-IP limiter (`consecutiveForIpPassword`) is checked before JWT verification. Repeated failures from the same IP are blocked progressively.\n\n#### JWT verification\n\n`verifyTempJwtLink` verifies the signed token. An invalid or expired token returns `400`.\n\n#### Visitor match\n\nThe `visitor` query parameter must match `payload.visitor`. A mismatch returns `400`.\n\n#### Payload integrity\n\nThe following checks run against the decoded payload:\n\n- `payload.purpose` must equal `reason` (`PASSWORD_RESET`)\n- `payload.subject` must equal `PASSWORD_RESET_{visitor}`\n- The SHA-256 hash of `random` must match `payload.randomHashed` via `crypto.timingSafeEqual`\n\nAny mismatch returns `401`.\n\n#### JTI replay check\n\nThe `usedJtiLimiter` is checked. If the JTI has been blocked (consumed on a prior POST), the request returns `400` with `'Link is not valid or expired'`.\n\n#### GET count enforcement\n\nAn in-memory counter tracks how many times this JTI has been accessed via GET. Exceeding `allowedPerSuccessfulGet` (default 5) returns `400`.\n::\n\nThe GET handler returns `200` without a body if all checks pass. The client uses this to confirm the link is valid before rendering the password reset form.\n\n---\n\n## Password submission: `POST \u002Fauth\u002Freset-password`\n\nThe POST to the same route runs the same `linkPasswordVerification` middleware as the GET, then delegates to `verifyNewPassword` to validate and apply the new password.\n\n### Request\n\n```http\nPOST \u002Fauth\u002Freset-password?token=\u003Cjwt>&random=\u003Chex>&visitor=\u003Cid>&reason=PASSWORD_RESET\nContent-Type: application\u002Fjson\n\n{\n  \"password\": \"new-password\",\n  \"confirmedPassword\": \"new-password\"\n}\n```\n\n### Rate limiting\n\nThree limiters protect the POST submission inside `verifyNewPassword`:\n\n| Limiter | Key | Default points | Default duration | Default block | Purpose |\n|---|---|---|---|---|---|\n| `ipLimit` | `${JTI}` | 6 | 10min | 10min | Caps attempts per verification session |\n| `ipLimit` | `${IP}` | 6 | 10min | 10min | Caps attempts per IP |\n| `uniLimiter` (union) | `${IP}_${visitor_id}` | burst + slow | 1s \u002F 10min | 30min \u002F 10min | Blocks rapid or sustained composite attempts |\n\nEach failed attempt increments the corresponding consecutive cache. Exceeding the threshold blocks further attempts for the cache duration (10–20 minutes).\n\n### Submission flow\n\n::steps{level=\"4\"}\n#### Content type check\n\nThe request must have `Content-Type: application\u002Fjson`. Any other content type returns `400`.\n\n#### Link purpose check\n\n`req.link.purpose` must be `PASSWORD_RESET` and `req.link.subject` must be `PASSWORD_RESET_{visitor}`. A mismatch returns `400`.\n\n#### Rate limit checks\n\nThe three limiters above are checked in order: JTI limiter, IP limiter, then composite union limiter. Any failure returns `429`.\n\n#### Schema validation\n\nThe request body is validated against the `passwords` Zod schema, which requires both `password` and `confirmedPassword`. Invalid input returns `400`.\n\n#### Password match\n\n`password` and `confirmedPassword` are compared. A mismatch returns `400` with `{ \"error\": \"Password doesn't match\", \"banned\": false }`.\n\n#### Breach check\n\nThe password is checked against the HaveIBeenPwned API via `isPwned`. If the password appears in a known data breach, the request is rejected with `400`:\n\n```json\n{\n  \"ok\": false,\n  \"error\": \"Our system identified this password in X data breaches. Please choose a different password.\"\n}\n```\n\n#### Password hashing\n\nThe new password is hashed with Argon2id via `hashPassword`.\n\n#### User lookup\n\nThe user record is fetched from the database using the `visitor_id` from the link token, locked with `FOR UPDATE` inside a transaction.\n\n#### Password update\n\n```sql\nUPDATE users\nSET password_hash = ?\nWHERE id = ? AND visitor_id = ?\nLIMIT 1\n```\n\nIf `affectedRows` is not exactly 1, the transaction rolls back and `400` is returned.\n\n#### Session revocation\n\nAll active refresh tokens for the user are invalidated:\n\n```sql\nUPDATE refresh_tokens\nSET valid = 0\nWHERE user_id = ? AND valid = 1\n```\n\n#### JTI block\n\nThe JTI is blocked in `usedJtiLimiter` for 20 minutes, preventing link reuse.\n\n#### Notification email\n\nAfter a successful commit, a security notification email is sent to the user's address with the subject `\"Security Alert: Password Reset Successful\"`. The email includes a link to the login page configured at `magic_links.notificationEmail.loginPageLink`.\n\n#### Rate limiter cleanup\n\nAll consecutive caches and the union limiter for the composite key are reset on success.\n::\n\n### Response\n\n```json\n{ \"success\": true }\n```\n\n---\n\n## Security properties\n\n| Property | Value |\n|---|---|\n| Enumeration protection | Always returns `200` on the initiation endpoint after a 3-second minimum delay |\n| OAuth accounts | Users with `password_hash = 'no_password'` are silently skipped |\n| Link integrity | Random challenge verified with `crypto.timingSafeEqual`; purpose and subject claims validated |\n| Link reuse | JTI blocked for 20 minutes after successful POST |\n| Link expiry | Determined by the temporary JWT TTL configured in `magic_links` |\n| GET limit | Default 5 previews per link before it is considered expired |\n| Breach check | HaveIBeenPwned API called before storing the new hash |\n| Session revocation | All active refresh tokens invalidated on success |\n| Notification | Security email sent to confirm the change; alerts the user if unauthorized |\n\n---\n\n## Configuration reference\n\n::field-group\n::field{name=\"magic_links.paths.pathForPasswordResetLink\" type=\"string\" required}\nThe path component of the password reset URL. Combined with `magic_links.domain` to build the full reset link sent in the email.\n::\n\n::field{name=\"magic_links.notificationEmail.loginPageLink\" type=\"string\" required}\nURL of the login page, included in the post-reset security notification email as the call-to-action link.\n::\n\n::field{name=\"magic_links.thresholds.linkPasswordVerification.allowedPerSuccessfulGet\" type=\"number\" default=\"5\"}\nNumber of times a password reset link may be visited via GET before it is considered expired.\n::\n\n::field{name=\"magic_links.thresholds.linkPasswordVerification.allowedPerSuccessfulPost\" type=\"number\" default=\"3\"}\nNumber of POST submission attempts allowed per successful link verification session.\n::\n::\n\n### Initiation rate limiters\n\n::field-group\n::field{name=\"rate_limiters.initPasswordResetLimiters.unionLimiters.limit\" type=\"object\"}\nBurst limiter for the `${IP}_${email}` composite key. Defaults: 1 point, 1s duration, 30min block. Consumed only on failed email lookups.\n::\n\n::field{name=\"rate_limiters.initPasswordResetLimiters.unionLimiters.longLimiter\" type=\"object\"}\nSlow limiter for the `${IP}_${email}` composite key. Defaults: 4 points, 30min duration, 15min block.\n::\n\n::field{name=\"rate_limiters.initPasswordResetLimiters.ipLimiter\" type=\"object\"}\nPer-IP limiter. Defaults: 5 points, 24hr duration, 4hr block.\n::\n\n::field{name=\"rate_limiters.initPasswordResetLimiters.emailLimiter\" type=\"object\"}\nPer-email limiter. Defaults: 5 points, 24hr duration, 4hr block.\n::\n::\n\n### Verification rate limiters\n\nThese use the `tempPostRoutesLimiters` limiter group shared with other temporary-link POST routes:\n\n::field-group\n::field{name=\"rate_limiters.tempPostRoutesLimiters.unionLimiters.limit\" type=\"object\"}\nBurst limiter keyed by `${IP}_${visitor_id}`. Defaults: 1 point, 1s duration, 30min block.\n::\n\n::field{name=\"rate_limiters.tempPostRoutesLimiters.unionLimiters.slowLimit\" type=\"object\"}\nSlow limiter keyed by `${IP}_${visitor_id}`. Defaults: 5 points, 10min duration, 10min block.\n::\n\n::field{name=\"rate_limiters.tempPostRoutesLimiters.ipLimit\" type=\"object\"}\nPer-IP and per-JTI limiter. Defaults: 6 points, 10min duration, 10min block.\n::\n::",{"title":163,"description":2317},"8B8Tz0CWm_ZtLuqPbSgZTb4RyYzO_gqH3Cvk4_3SqdI",[2325,2326],{"title":159,"path":160,"stem":161,"children":-1},{"title":167,"path":168,"stem":169,"children":-1},{"id":851,"title":163,"body":2328,"description":2317,"extension":2318,"icon":21,"meta":3369,"module":2320,"navigation":8,"path":164,"rawbody":2321,"seo":3370,"stem":165,"__hash__":2323},{"type":853,"value":2329,"toc":3346},[2330,2332,2334,2338,2342,2344,2386,2388,2390,2482,2492,2494,2622,2624,2628,2664,2674,2676,2680,2684,2686,2734,2736,2822,2826,2828,2832,2838,2840,2904,2906,2910,2984,2986,2988,3172,3174,3194,3196,3198,3272,3274,3276,3296,3298,3320,3322,3326,3344],[856,2331,858],{},[860,2333],{},[863,2335,866,2336],{"id":865},[868,2337,870],{},[856,2339,873,2340,877],{},[868,2341,876],{},[879,2343,882],{"id":881},[884,2345,2346],{"className":886,"code":887,"language":888,"meta":889,"style":889},[868,2347,2348,2354,2362,2366],{"__ignoreMap":889},[893,2349,2350,2352],{"class":895,"line":896},[893,2351,900],{"class":899},[893,2353,904],{"class":903},[893,2355,2356,2358,2360],{"class":895,"line":907},[893,2357,911],{"class":910},[893,2359,915],{"class":914},[893,2361,919],{"class":918},[893,2363,2364],{"class":895,"line":922},[893,2365,925],{"emptyLinePlaceholder":8},[893,2367,2368,2370,2372,2374,2376,2378,2380,2382,2384],{"class":895,"line":928},[893,2369,931],{"class":903},[893,2371,935],{"class":934},[893,2373,939],{"class":938},[893,2375,935],{"class":934},[893,2377,915],{"class":944},[893,2379,948],{"class":947},[893,2381,951],{"class":918},[893,2383,935],{"class":947},[893,2385,956],{"class":903},[879,2387,960],{"id":959},[856,2389,963],{},[965,2391,2392,2408],{},[968,2393,2394],{},[971,2395,2396,2398,2400,2402,2404,2406],{},[974,2397,976],{},[974,2399,979],{},[974,2401,982],{},[974,2403,985],{},[974,2405,988],{},[974,2407,991],{},[993,2409,2410,2428,2446,2464],{},[971,2411,2412,2416,2420,2422,2424,2426],{},[998,2413,2414],{},[868,2415,1002],{},[998,2417,2418],{},[868,2419,1007],{},[998,2421,1010],{},[998,2423,1013],{},[998,2425,1013],{},[998,2427,1018],{},[971,2429,2430,2434,2438,2440,2442,2444],{},[998,2431,2432],{},[868,2433,1025],{},[998,2435,2436],{},[868,2437,1030],{},[998,2439,1033],{},[998,2441,1036],{},[998,2443,1039],{},[998,2445,1042],{},[971,2447,2448,2452,2456,2458,2460,2462],{},[998,2449,2450],{},[868,2451,1049],{},[998,2453,2454],{},[868,2455,1054],{},[998,2457,1033],{},[998,2459,1036],{},[998,2461,1039],{},[998,2463,1063],{},[971,2465,2466,2470,2474,2476,2478,2480],{},[998,2467,2468,1071],{},[868,2469,1070],{},[998,2471,2472],{},[868,2473,1076],{},[998,2475,1079],{},[998,2477,1082],{},[998,2479,1085],{},[998,2481,1088],{},[856,2483,1091,2484,1094,2486,1097,2488,1100,2490,1103],{},[868,2485,1002],{},[868,2487,1025],{},[868,2489,1049],{},[868,2491,1070],{},[879,2493,1107],{"id":1106},[1109,2495,2496,2498,2504,2506,2516,2518,2524,2526,2534,2536,2594,2596,2612,2614],{"level":1111},[1113,2497,1116],{"id":1115},[856,2499,1119,2500,1123,2502,1127],{},[868,2501,1122],{},[868,2503,1126],{},[1113,2505,1131],{"id":1130},[856,2507,2508,1137,2510,1141,2512,1144,2514,1147],{},[868,2509,1136],{},[868,2511,1140],{},[868,2513,1070],{},[868,2515,1076],{},[1113,2517,1151],{"id":1150},[856,2519,1154,2520,1158,2522,1162],{},[868,2521,1157],{},[868,2523,1161],{},[1113,2525,1166],{"id":1165},[856,2527,1169,2528,1173,2530,1177,2532,1181],{},[868,2529,1172],{},[868,2531,1176],{},[868,2533,1180],{},[856,2535,1184],{},[965,2537,2538,2546],{},[968,2539,2540],{},[971,2541,2542,2544],{},[974,2543,1193],{},[974,2545,1196],{},[993,2547,2548,2558,2568,2578,2586],{},[971,2549,2550,2554],{},[998,2551,2552],{},[868,2553,1205],{},[998,2555,2556],{},[868,2557,1210],{},[971,2559,2560,2564],{},[998,2561,2562],{},[868,2563,1217],{},[998,2565,2566],{},[868,2567,1222],{},[971,2569,2570,2574],{},[998,2571,2572],{},[868,2573,1229],{},[998,2575,1232,2576],{},[868,2577,1235],{},[971,2579,2580,2584],{},[998,2581,2582],{},[868,2583,1242],{},[998,2585,1245],{},[971,2587,2588,2592],{},[998,2589,2590],{},[868,2591,1252],{},[998,2593,1255],{},[1113,2595,1259],{"id":1258},[856,2597,1262,2598,1094,2600,1269,2602,1272,2604,1272,2606,1279,2608,1283,2610,1287],{},[868,2599,1265],{},[868,2601,1268],{},[868,2603,1229],{},[868,2605,1275],{},[868,2607,1278],{},[868,2609,1282],{},[868,2611,1286],{},[1113,2613,1291],{"id":1290},[856,2615,1294,2616,1298,2618,1302,2620,1306],{},[868,2617,1297],{},[868,2619,1301],{},[868,2621,1305],{},[879,2623,1310],{"id":1309},[856,2625,1313,2626,1316],{},[868,2627,876],{},[884,2629,2630],{"className":1319,"code":1320,"language":5,"meta":889,"style":889},[868,2631,2632],{"__ignoreMap":889},[893,2633,2634,2636,2638,2640,2642,2644,2646,2648,2650,2652,2654,2656,2658,2660,2662],{"class":895,"line":896},[893,2635,931],{"class":903},[893,2637,935],{"class":934},[893,2639,1331],{"class":938},[893,2641,935],{"class":934},[893,2643,915],{"class":944},[893,2645,1339],{"class":1338},[893,2647,1272],{"class":903},[893,2649,935],{"class":934},[893,2651,1346],{"class":938},[893,2653,935],{"class":934},[893,2655,915],{"class":944},[893,2657,948],{"class":947},[893,2659,1355],{"class":918},[893,2661,935],{"class":947},[893,2663,956],{"class":903},[1361,2665,2666],{},[856,2667,1365,2668,1368,2670,1372,2672,1375],{},[868,2669,1305],{},[868,2671,1371],{},[868,2673,876],{},[860,2675],{},[863,2677,1381,2678],{"id":1380},[868,2679,1384],{},[856,2681,1387,2682,1391],{},[868,2683,1390],{},[879,2685,1395],{"id":1394},[965,2687,2688,2696],{},[968,2689,2690],{},[971,2691,2692,2694],{},[974,2693,1404],{},[974,2695,1407],{},[993,2697,2698,2706,2714,2724],{},[971,2699,2700,2704],{},[998,2701,2702],{},[868,2703,1275],{},[998,2705,1418],{},[971,2707,2708,2712],{},[998,2709,2710],{},[868,2711,1278],{},[998,2713,1427],{},[971,2715,2716,2720],{},[998,2717,2718],{},[868,2719,1229],{},[998,2721,1232,2722],{},[868,2723,1235],{},[971,2725,2726,2730],{},[998,2727,2728],{},[868,2729,1282],{},[998,2731,1446,2732],{},[868,2733,1210],{},[879,2735,1452],{"id":1451},[1109,2737,2738,2740,2748,2750,2754,2756,2762,2764,2772,2774,2776,2800,2804,2806,2814,2816],{"level":1111},[1113,2739,1116],{"id":1457},[856,2741,1460,2742,1464,2744,1123,2746,1287],{},[868,2743,1463],{},[868,2745,1122],{},[868,2747,1126],{},[1113,2749,1472],{"id":1471},[856,2751,1475,2752,1479],{},[868,2753,1478],{},[1113,2755,1483],{"id":1482},[856,2757,2758,1489,2760,1287],{},[868,2759,1488],{},[868,2761,1122],{},[1113,2763,1495],{"id":1494},[856,2765,1091,2766,1500,2768,1504,2770,1287],{},[868,2767,1229],{},[868,2769,1503],{},[868,2771,1122],{},[1113,2773,1510],{"id":1509},[856,2775,1513],{},[1515,2777,2778,2786,2792],{},[1518,2779,2780,1523,2782,1526,2784,1529],{},[868,2781,1522],{},[868,2783,1282],{},[868,2785,1210],{},[1518,2787,2788,1523,2790],{},[868,2789,1534],{},[868,2791,1537],{},[1518,2793,1540,2794,1543,2796,1547,2798],{},[868,2795,1278],{},[868,2797,1546],{},[868,2799,1550],{},[856,2801,1553,2802,1287],{},[868,2803,1556],{},[1113,2805,1560],{"id":1559},[856,2807,1091,2808,1566,2810,1569,2812,1287],{},[868,2809,1565],{},[868,2811,1122],{},[868,2813,1572],{},[1113,2815,1576],{"id":1575},[856,2817,1579,2818,1582,2820,1287],{},[868,2819,1390],{},[868,2821,1122],{},[856,2823,1587,2824,1590],{},[868,2825,876],{},[860,2827],{},[863,2829,1596,2830],{"id":1595},[868,2831,1599],{},[856,2833,1602,2834,1606,2836,1610],{},[868,2835,1605],{},[868,2837,1609],{},[879,2839,882],{"id":1613},[884,2841,2842],{"className":886,"code":1616,"language":888,"meta":889,"style":889},[868,2843,2844,2850,2858,2862,2866,2884,2900],{"__ignoreMap":889},[893,2845,2846,2848],{"class":895,"line":896},[893,2847,900],{"class":899},[893,2849,1625],{"class":903},[893,2851,2852,2854,2856],{"class":895,"line":907},[893,2853,911],{"class":910},[893,2855,915],{"class":914},[893,2857,919],{"class":918},[893,2859,2860],{"class":895,"line":922},[893,2861,925],{"emptyLinePlaceholder":8},[893,2863,2864],{"class":895,"line":928},[893,2865,1642],{"class":903},[893,2867,2868,2870,2872,2874,2876,2878,2880,2882],{"class":895,"line":1645},[893,2869,1648],{"class":934},[893,2871,1651],{"class":938},[893,2873,935],{"class":934},[893,2875,915],{"class":944},[893,2877,948],{"class":947},[893,2879,1660],{"class":918},[893,2881,935],{"class":947},[893,2883,1665],{"class":903},[893,2885,2886,2888,2890,2892,2894,2896,2898],{"class":895,"line":1668},[893,2887,1648],{"class":934},[893,2889,1673],{"class":938},[893,2891,935],{"class":934},[893,2893,915],{"class":944},[893,2895,948],{"class":947},[893,2897,1660],{"class":918},[893,2899,1684],{"class":947},[893,2901,2902],{"class":895,"line":1687},[893,2903,1690],{"class":903},[879,2905,960],{"id":1693},[856,2907,1696,2908,915],{},[868,2909,1609],{},[965,2911,2912,2928],{},[968,2913,2914],{},[971,2915,2916,2918,2920,2922,2924,2926],{},[974,2917,976],{},[974,2919,979],{},[974,2921,982],{},[974,2923,985],{},[974,2925,988],{},[974,2927,991],{},[993,2929,2930,2948,2966],{},[971,2931,2932,2936,2940,2942,2944,2946],{},[998,2933,2934],{},[868,2935,1725],{},[998,2937,2938],{},[868,2939,1730],{},[998,2941,1733],{},[998,2943,1736],{},[998,2945,1736],{},[998,2947,1741],{},[971,2949,2950,2954,2958,2960,2962,2964],{},[998,2951,2952],{},[868,2953,1725],{},[998,2955,2956],{},[868,2957,1030],{},[998,2959,1733],{},[998,2961,1736],{},[998,2963,1736],{},[998,2965,1760],{},[971,2967,2968,2972,2976,2978,2980,2982],{},[998,2969,2970,1071],{},[868,2971,1070],{},[998,2973,2974],{},[868,2975,1771],{},[998,2977,1079],{},[998,2979,1776],{},[998,2981,1779],{},[998,2983,1782],{},[856,2985,1785],{},[879,2987,1789],{"id":1788},[1109,2989,2990,2992,2998,3000,3012,3014,3018,3020,3030,3032,3042,3044,3050,3092,3094,3098,3100,3106,3108,3128,3134,3136,3138,3154,3156,3160,3162,3168,3170],{"level":1111},[1113,2991,1795],{"id":1794},[856,2993,1798,2994,1802,2996,1287],{},[868,2995,1801],{},[868,2997,1122],{},[1113,2999,1808],{"id":1807},[856,3001,3002,1814,3004,1094,3006,1814,3008,1504,3010,1287],{},[868,3003,1813],{},[868,3005,1210],{},[868,3007,1819],{},[868,3009,1537],{},[868,3011,1122],{},[1113,3013,1827],{"id":1826},[856,3015,1830,3016,1287],{},[868,3017,1371],{},[1113,3019,1116],{"id":1835},[856,3021,1838,3022,1842,3024,1094,3026,1847,3028,1287],{},[868,3023,1841],{},[868,3025,1651],{},[868,3027,1673],{},[868,3029,1122],{},[1113,3031,1853],{"id":1852},[856,3033,3034,1094,3036,1860,3038,1569,3040,1287],{},[868,3035,1651],{},[868,3037,1673],{},[868,3039,1122],{},[868,3041,1865],{},[1113,3043,1869],{"id":1868},[856,3045,1872,3046,1876,3048,915],{},[868,3047,1875],{},[868,3049,1122],{},[884,3051,3052],{"className":1319,"code":1881,"language":5,"meta":889,"style":889},[868,3053,3054,3058,3072,3088],{"__ignoreMap":889},[893,3055,3056],{"class":895,"line":896},[893,3057,1642],{"class":903},[893,3059,3060,3062,3064,3066,3068,3070],{"class":895,"line":907},[893,3061,1648],{"class":934},[893,3063,1894],{"class":938},[893,3065,935],{"class":934},[893,3067,915],{"class":944},[893,3069,1901],{"class":1338},[893,3071,1665],{"class":903},[893,3073,3074,3076,3078,3080,3082,3084,3086],{"class":895,"line":922},[893,3075,1648],{"class":934},[893,3077,1910],{"class":938},[893,3079,935],{"class":934},[893,3081,915],{"class":944},[893,3083,948],{"class":947},[893,3085,1919],{"class":918},[893,3087,1684],{"class":947},[893,3089,3090],{"class":895,"line":928},[893,3091,1690],{"class":903},[1113,3093,1929],{"id":1928},[856,3095,1932,3096,1287],{},[868,3097,1935],{},[1113,3099,1131],{"id":1938},[856,3101,1941,3102,1944,3104,1948],{},[868,3103,1235],{},[868,3105,1947],{},[1113,3107,1952],{"id":1951},[884,3109,3110],{"className":1955,"code":1956,"language":1957,"meta":889,"style":889},[868,3111,3112,3116,3120,3124],{"__ignoreMap":889},[893,3113,3114],{"class":895,"line":896},[893,3115,1964],{},[893,3117,3118],{"class":895,"line":907},[893,3119,1969],{},[893,3121,3122],{"class":895,"line":922},[893,3123,1974],{},[893,3125,3126],{"class":895,"line":928},[893,3127,1979],{},[856,3129,1982,3130,1986,3132,1989],{},[868,3131,1985],{},[868,3133,1122],{},[1113,3135,1993],{"id":1992},[856,3137,1996],{},[884,3139,3140],{"className":1955,"code":1999,"language":1957,"meta":889,"style":889},[868,3141,3142,3146,3150],{"__ignoreMap":889},[893,3143,3144],{"class":895,"line":896},[893,3145,2006],{},[893,3147,3148],{"class":895,"line":907},[893,3149,2011],{},[893,3151,3152],{"class":895,"line":922},[893,3153,2016],{},[1113,3155,2020],{"id":2019},[856,3157,2023,3158,2026],{},[868,3159,1565],{},[1113,3161,2030],{"id":2029},[856,3163,2033,3164,2037,3166,1287],{},[868,3165,2036],{},[868,3167,2040],{},[1113,3169,2044],{"id":2043},[856,3171,2047],{},[879,3173,1310],{"id":2050},[884,3175,3176],{"className":1319,"code":2053,"language":5,"meta":889,"style":889},[868,3177,3178],{"__ignoreMap":889},[893,3179,3180,3182,3184,3186,3188,3190,3192],{"class":895,"line":896},[893,3181,931],{"class":903},[893,3183,935],{"class":934},[893,3185,1331],{"class":938},[893,3187,935],{"class":934},[893,3189,915],{"class":944},[893,3191,1339],{"class":1338},[893,3193,956],{"class":903},[860,3195],{},[863,3197,2077],{"id":2076},[965,3199,3200,3208],{},[968,3201,3202],{},[971,3203,3204,3206],{},[974,3205,2086],{},[974,3207,1196],{},[993,3209,3210,3218,3226,3234,3240,3248,3254,3260,3266],{},[971,3211,3212,3214],{},[998,3213,2095],{},[998,3215,2098,3216,2101],{},[868,3217,876],{},[971,3219,3220,3222],{},[998,3221,2106],{},[998,3223,2109,3224,2113],{},[868,3225,2112],{},[971,3227,3228,3230],{},[998,3229,2118],{},[998,3231,2121,3232,2124],{},[868,3233,1550],{},[971,3235,3236,3238],{},[998,3237,2129],{},[998,3239,2132],{},[971,3241,3242,3244],{},[998,3243,2137],{},[998,3245,2140,3246],{},[868,3247,2143],{},[971,3249,3250,3252],{},[998,3251,2148],{},[998,3253,2151],{},[971,3255,3256,3258],{},[998,3257,1869],{},[998,3259,2158],{},[971,3261,3262,3264],{},[998,3263,1993],{},[998,3265,2165],{},[971,3267,3268,3270],{},[998,3269,2170],{},[998,3271,2173],{},[860,3273],{},[863,3275,2179],{"id":2178},[2181,3277,3278,3284,3288,3292],{},[2184,3279,3280],{"name":1265,"type":2186,":required":2187},[856,3281,2190,3282,2193],{},[868,3283,1268],{},[2184,3285,3286],{"name":2040,"type":2186,":required":2187},[856,3287,2198],{},[2184,3289,3290],{"name":2201,"type":2202,"default":1033},[856,3291,2205],{},[2184,3293,3294],{"name":2208,"type":2202,"default":2209},[856,3295,2212],{},[879,3297,2216],{"id":2215},[2181,3299,3300,3306,3312,3316],{},[2184,3301,3302],{"name":2221,"type":2222},[856,3303,2225,3304,2228],{},[868,3305,1076],{},[2184,3307,3308],{"name":2231,"type":2222},[856,3309,2234,3310,2237],{},[868,3311,1076],{},[2184,3313,3314],{"name":2240,"type":2222},[856,3315,2243],{},[2184,3317,3318],{"name":2246,"type":2222},[856,3319,2249],{},[879,3321,2253],{"id":2252},[856,3323,2256,3324,2260],{},[868,3325,2259],{},[2181,3327,3328,3334,3340],{},[2184,3329,3330],{"name":2265,"type":2222},[856,3331,2268,3332,2271],{},[868,3333,1771],{},[2184,3335,3336],{"name":2274,"type":2222},[856,3337,2277,3338,2280],{},[868,3339,1771],{},[2184,3341,3342],{"name":2283,"type":2222},[856,3343,2286],{},[2288,3345,2290],{},{"title":889,"searchDepth":907,"depth":907,"links":3347},[3348,3354,3358,3364,3365],{"id":865,"depth":907,"text":2294,"children":3349},[3350,3351,3352,3353],{"id":881,"depth":922,"text":882},{"id":959,"depth":922,"text":960},{"id":1106,"depth":922,"text":1107},{"id":1309,"depth":922,"text":1310},{"id":1380,"depth":907,"text":2301,"children":3355},[3356,3357],{"id":1394,"depth":922,"text":1395},{"id":1451,"depth":922,"text":1452},{"id":1595,"depth":907,"text":2306,"children":3359},[3360,3361,3362,3363],{"id":1613,"depth":922,"text":882},{"id":1693,"depth":922,"text":960},{"id":1788,"depth":922,"text":1789},{"id":2050,"depth":922,"text":1310},{"id":2076,"depth":907,"text":2077},{"id":2178,"depth":907,"text":2179,"children":3366},[3367,3368],{"id":2215,"depth":922,"text":2216},{"id":2252,"depth":922,"text":2253},{},{"title":163,"description":2317},1780436284296]