[{"data":1,"prerenderedAt":5127},["ShallowReactive",2],{"navLinks":3,"sidebar_docs_navigation_\u002Fdocs\u002Fiam":64,"navigation":257,"navLinks_footer":837,"\u002Fdocs\u002Fiam\u002Fessentials\u002Flogging_page":850,"\u002Fdocs\u002Fiam\u002Fessentials\u002Flogging_surround":3259,"\u002Fdocs\u002Fiam\u002Fessentials\u002Flogging":3262},{"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":143,"body":852,"description":3251,"extension":3252,"icon":3253,"meta":3254,"module":3255,"navigation":8,"path":144,"rawbody":3256,"seo":3257,"stem":145,"__hash__":3258},"docs\u002Fdocs\u002Fiam\u002F01.essentials\u002F15.logging.md",{"type":853,"value":854,"toc":3217},"minimark",[855,881,900,913,916,921,924,942,945,1043,1058,1073,1075,1079,1084,1094,1203,1206,1212,1241,1245,1256,1315,1318,1322,1333,1337,1344,1438,1440,1444,1451,1455,1603,1607,1637,1656,1658,1662,1668,1672,1752,1756,1764,2015,2032,2034,2038,2041,2045,2053,2060,2064,2067,2117,2121,2124,2198,2214,2218,2221,2262,2268,2272,2275,2358,2362,2365,2439,2445,2679,2683,2686,2735,2749,2753,2763,2765,2769,2773,2851,2855,2861,2882,2885,2899,2903,2912,3076,3078,3082,3213],[856,857,858,859,866,867,871,872,875,876,880],"p",{},"The IAM service uses ",[860,861,865],"a",{"href":862,"rel":863},"https:\u002F\u002Fgetpino.io\u002F",[864],"nofollow","Pino"," for all logging. There are two distinct logger instances: an ",[868,869,870],"strong",{},"application logger"," for general-purpose messages (auth decisions, token operations, anomaly events), and an ",[868,873,874],{},"HTTP logger"," for per-request lifecycle tracking (method, status, latency, IP). Both write to files inside the ",[877,878,879],"code",{},"auth-logs\u002F"," directory, both redact sensitive fields before anything reaches disk, and both attach structured metadata so every log entry carries machine-readable context.",[856,882,883,884,887,888,891,892,895,896,899],{},"The application logger is a singleton. It is created once at startup and shared across the entire process through ",[877,885,886],{},"getLogger()",". Every module that needs to log creates a ",[868,889,890],{},"child logger"," from that singleton, tagging entries with a ",[877,893,894],{},"service"," and ",[877,897,898],{},"branch"," field so you can filter by domain (tokens, OAuth, MFA, anomalies) without splitting into separate files.",[856,901,902,903,908,909,912],{},"The HTTP logger is an Express middleware powered by ",[860,904,907],{"href":905,"rel":906},"https:\u002F\u002Fgithub.com\u002Fpinojs\u002Fpino-http",[864],"pino-http",". It wraps each request in a log entry that records timing, status, client IP, user agent, and the full URL. It assigns a unique request ID to every inbound request and propagates it in the ",[877,910,911],{},"X-Request-Id"," response header.",[914,915],"hr",{},[917,918,920],"h2",{"id":919},"log-directory","Log Directory",[856,922,923],{},"All log files live under a single directory. The service resolves the path in this order:",[925,926,927,935],"ol",{},[928,929,930,931,934],"li",{},"If the ",[877,932,933],{},"LOG_DIR"," environment variable is set, use that value.",[928,936,937,938,941],{},"Otherwise, default to ",[877,939,940],{},"${PROJECT_ROOT}\u002Fauth-logs",".",[856,943,944],{},"The directory is created automatically at startup if it does not exist. Four files are written:",[946,947,948,967],"table",{},[949,950,951],"thead",{},[952,953,954,958,961,964],"tr",{},[955,956,957],"th",{},"File",[955,959,960],{},"Logger",[955,962,963],{},"Minimum Level",[955,965,966],{},"Contents",[968,969,970,992,1009,1026],"tbody",{},[952,971,972,978,981,986],{},[973,974,975],"td",{},[877,976,977],{},"info.log",[973,979,980],{},"Application",[973,982,983],{},[877,984,985],{},"info",[973,987,988,989,991],{},"Everything at ",[877,990,985],{}," level and above (info, warn, error, fatal)",[952,993,994,999,1001,1006],{},[973,995,996],{},[877,997,998],{},"warn.log",[973,1000,980],{},[973,1002,1003],{},[877,1004,1005],{},"warn",[973,1007,1008],{},"Warnings and errors only (warn, error, fatal)",[952,1010,1011,1016,1018,1023],{},[973,1012,1013],{},[877,1014,1015],{},"errors.log",[973,1017,980],{},[973,1019,1020],{},[877,1021,1022],{},"error",[973,1024,1025],{},"Errors and fatal entries only (error, fatal)",[952,1027,1028,1033,1036,1040],{},[973,1029,1030],{},[877,1031,1032],{},"http.log",[973,1034,1035],{},"HTTP",[973,1037,1038],{},[877,1039,985],{},[973,1041,1042],{},"One entry per HTTP request (status, latency, IP, URL)",[856,1044,1045,1046,1048,1049,1051,1052,1054,1055,1057],{},"The first three files are fed by the application logger through Pino's transport pipeline. Each transport targets a different file with a different minimum level, so the same application log entry can appear in ",[877,1047,977],{},", ",[877,1050,998],{},", and ",[877,1053,1015],{}," simultaneously if its level qualifies. The HTTP logger writes exclusively to ",[877,1056,1032],{}," through its own separate Pino instance.",[1059,1060,1061],"tip",{},[856,1062,1063,1064,1066,1067,1069,1070,1072],{},"Tail ",[877,1065,1015],{}," during debugging to focus on failures. Tail ",[877,1068,1032],{}," to see traffic patterns and latency spikes. ",[877,1071,977],{}," is the most verbose file and contains the union of all application-level activity.",[914,1074],{},[917,1076,1078],{"id":1077},"application-logger","Application Logger",[1080,1081,1083],"h3",{"id":1082},"singleton-pattern","Singleton Pattern",[856,1085,1086,1087,1089,1090,1093],{},"The application logger is created by ",[877,1088,886],{},". On the first call, it reads the ",[877,1091,1092],{},"logLevel"," field from the service configuration, builds a Pino instance with three file transports, and caches it. Every subsequent call returns the same instance.",[1095,1096,1101],"pre",{"className":1097,"code":1098,"language":1099,"meta":1100,"style":1100},"language-ts shiki shiki-themes light-plus light-plus dracula","import { getLogger } from '@riavzon\u002Fauth'\n\nconst log = getLogger()\nlog.info({ userId: 42 }, 'Token generated')\n","ts","",[877,1102,1103,1137,1143,1165],{"__ignoreMap":1100},[1104,1105,1108,1112,1116,1120,1123,1126,1130,1134],"span",{"class":1106,"line":1107},"line",1,[1104,1109,1111],{"class":1110},"sZ328","import",[1104,1113,1115],{"class":1114},"sDd4n"," { ",[1104,1117,1119],{"class":1118},"sjsA6","getLogger",[1104,1121,1122],{"class":1114}," } ",[1104,1124,1125],{"class":1110},"from",[1104,1127,1129],{"class":1128},"sFkSl"," '",[1104,1131,1133],{"class":1132},"sFB1V","@riavzon\u002Fauth",[1104,1135,1136],{"class":1128},"'\n",[1104,1138,1140],{"class":1106,"line":1139},2,[1104,1141,1142],{"emptyLinePlaceholder":8},"\n",[1104,1144,1146,1150,1154,1158,1162],{"class":1106,"line":1145},3,[1104,1147,1149],{"class":1148},"sl46w","const",[1104,1151,1153],{"class":1152},"s3JHE"," log",[1104,1155,1157],{"class":1156},"saOXh"," =",[1104,1159,1161],{"class":1160},"sHOzp"," getLogger",[1104,1163,1164],{"class":1114},"()\n",[1104,1166,1168,1171,1173,1175,1178,1181,1185,1189,1192,1195,1198,1200],{"class":1106,"line":1167},4,[1104,1169,1170],{"class":1118},"log",[1104,1172,941],{"class":1114},[1104,1174,985],{"class":1160},[1104,1176,1177],{"class":1114},"({ ",[1104,1179,1180],{"class":1118},"userId",[1104,1182,1184],{"class":1183},"s34zl",":",[1104,1186,1188],{"class":1187},"spgvN"," 42",[1104,1190,1191],{"class":1114}," }, ",[1104,1193,1194],{"class":1128},"'",[1104,1196,1197],{"class":1132},"Token generated",[1104,1199,1194],{"class":1128},[1104,1201,1202],{"class":1114},")\n",[1080,1204,237],{"id":1205},"configuration",[856,1207,1208,1209,1211],{},"The ",[877,1210,1092],{}," field in the service configuration controls the minimum severity for the application logger. It accepts any standard Pino level.",[1213,1214,1215],"field-group",{},[1216,1217,1219],"field",{"name":1092,"type":1218},"string",[856,1220,1221,1222,1048,1225,1048,1228,1048,1230,1048,1232,1048,1234,1237,1238,1240],{},"Minimum log level for the application logger. Accepted values: ",[877,1223,1224],{},"trace",[877,1226,1227],{},"debug",[877,1229,985],{},[877,1231,1005],{},[877,1233,1022],{},[877,1235,1236],{},"fatal",". Optional. Defaults to the Pino default (",[877,1239,985],{},") when omitted.",[1080,1242,1244],{"id":1243},"transports","Transports",[856,1246,1247,1248,1251,1252,1255],{},"The logger uses ",[877,1249,1250],{},"pino.transport()"," with three ",[877,1253,1254],{},"pino\u002Ffile"," targets:",[946,1257,1258,1271],{},[949,1259,1260],{},[952,1261,1262,1265,1268],{},[955,1263,1264],{},"Target",[955,1266,1267],{},"Destination",[955,1269,1270],{},"Level",[968,1272,1273,1287,1301],{},[952,1274,1275,1278,1283],{},[973,1276,1277],{},"1",[973,1279,1280],{},[877,1281,1282],{},"auth-logs\u002Finfo.log",[973,1284,1285],{},[877,1286,985],{},[952,1288,1289,1292,1297],{},[973,1290,1291],{},"2",[973,1293,1294],{},[877,1295,1296],{},"auth-logs\u002Fwarn.log",[973,1298,1299],{},[877,1300,1005],{},[952,1302,1303,1306,1311],{},[973,1304,1305],{},"3",[973,1307,1308],{},[877,1309,1310],{},"auth-logs\u002Ferrors.log",[973,1312,1313],{},[877,1314,1022],{},[856,1316,1317],{},"Each target is a Pino file transport that appends newline-delimited JSON. The targets run in worker threads managed by Pino's transport system, so log writes do not block the main event loop.",[1080,1319,1321],{"id":1320},"timestamps","Timestamps",[856,1323,1324,1325,1328,1329,1332],{},"Every log entry carries an ISO 8601 timestamp generated by ",[877,1326,1327],{},"pino.stdTimeFunctions.isoTime",". This produces values like ",[877,1330,1331],{},"\"2025-01-15T14:30:00.000Z\""," rather than Unix epoch milliseconds.",[1080,1334,1336],{"id":1335},"uptime-mixin","Uptime Mixin",[856,1338,1339,1340,1343],{},"A mixin function injects ",[877,1341,1342],{},"process.uptime()"," into every log entry. Both the application logger and the HTTP logger include this field. It records how many seconds the Node.js process has been running at the moment the log line was emitted. It helps correlate events to process lifecycle phases (startup, steady state, post-restart).",[1095,1345,1348],{"className":1346,"code":1347,"language":5,"meta":1100,"style":1100},"language-json shiki shiki-themes light-plus light-plus dracula","{\n  \"level\": 30,\n  \"time\": \"2025-01-15T14:30:00.000Z\",\n  \"uptime\": 842.331,\n  \"msg\": \"Token generated\"\n}\n",[877,1349,1350,1355,1376,1397,1413,1432],{"__ignoreMap":1100},[1104,1351,1352],{"class":1106,"line":1107},[1104,1353,1354],{"class":1114},"{\n",[1104,1356,1357,1361,1365,1368,1370,1373],{"class":1106,"line":1139},[1104,1358,1360],{"class":1359},"saJyd","  \"",[1104,1362,1364],{"class":1363},"s_W10","level",[1104,1366,1367],{"class":1359},"\"",[1104,1369,1184],{"class":1156},[1104,1371,1372],{"class":1187}," 30",[1104,1374,1375],{"class":1114},",\n",[1104,1377,1378,1380,1383,1385,1387,1390,1393,1395],{"class":1106,"line":1145},[1104,1379,1360],{"class":1359},[1104,1381,1382],{"class":1363},"time",[1104,1384,1367],{"class":1359},[1104,1386,1184],{"class":1156},[1104,1388,1389],{"class":1128}," \"",[1104,1391,1392],{"class":1132},"2025-01-15T14:30:00.000Z",[1104,1394,1367],{"class":1128},[1104,1396,1375],{"class":1114},[1104,1398,1399,1401,1404,1406,1408,1411],{"class":1106,"line":1167},[1104,1400,1360],{"class":1359},[1104,1402,1403],{"class":1363},"uptime",[1104,1405,1367],{"class":1359},[1104,1407,1184],{"class":1156},[1104,1409,1410],{"class":1187}," 842.331",[1104,1412,1375],{"class":1114},[1104,1414,1416,1418,1421,1423,1425,1427,1429],{"class":1106,"line":1415},5,[1104,1417,1360],{"class":1359},[1104,1419,1420],{"class":1363},"msg",[1104,1422,1367],{"class":1359},[1104,1424,1184],{"class":1156},[1104,1426,1389],{"class":1128},[1104,1428,1197],{"class":1132},[1104,1430,1431],{"class":1128},"\"\n",[1104,1433,1435],{"class":1106,"line":1434},6,[1104,1436,1437],{"class":1114},"}\n",[914,1439],{},[917,1441,1443],{"id":1442},"redaction","Redaction",[856,1445,1446,1447,1450],{},"Both loggers aggressively redact sensitive data. Pino replaces the value of any matching path with ",[877,1448,1449],{},"[SECRET]"," before the entry reaches the transport layer - the raw value never appears in the log file.",[1080,1452,1454],{"id":1453},"application-logger-redaction-paths","Application Logger Redaction Paths",[946,1456,1457,1467],{},[949,1458,1459],{},[952,1460,1461,1464],{},[955,1462,1463],{},"Path",[955,1465,1466],{},"What it protects",[968,1468,1469,1479,1489,1499,1509,1519,1529,1539,1549,1559,1569,1579,1589],{},[952,1470,1471,1476],{},[973,1472,1473],{},[877,1474,1475],{},"req.headers.authorization",[973,1477,1478],{},"Bearer tokens in request headers",[952,1480,1481,1486],{},[973,1482,1483],{},[877,1484,1485],{},"user.password",[973,1487,1488],{},"Raw or hashed passwords on user objects",[952,1490,1491,1496],{},[973,1492,1493],{},[877,1494,1495],{},"accessToken",[973,1497,1498],{},"Signed JWT access tokens",[952,1500,1501,1506],{},[973,1502,1503],{},[877,1504,1505],{},"refresh_token",[973,1507,1508],{},"Raw refresh token strings",[952,1510,1511,1516],{},[973,1512,1513],{},[877,1514,1515],{},"cookie",[973,1517,1518],{},"Full cookie header strings",[952,1520,1521,1526],{},[973,1522,1523],{},[877,1524,1525],{},"cookies",[973,1527,1528],{},"Parsed cookie objects",[952,1530,1531,1536],{},[973,1532,1533],{},[877,1534,1535],{},"canary_id",[973,1537,1538],{},"Bot-detector visitor identifier",[952,1540,1541,1546],{},[973,1542,1543],{},[877,1544,1545],{},"req.cookies",[973,1547,1548],{},"Parsed cookies from the request",[952,1550,1551,1556],{},[973,1552,1553],{},[877,1554,1555],{},"req.cookie",[973,1557,1558],{},"Raw cookie header from the request",[952,1560,1561,1566],{},[973,1562,1563],{},[877,1564,1565],{},"access_token",[973,1567,1568],{},"Access tokens in any property name",[952,1570,1571,1576],{},[973,1572,1573],{},[877,1574,1575],{},"email",[973,1577,1578],{},"User email addresses",[952,1580,1581,1586],{},[973,1582,1583],{},[877,1584,1585],{},"name",[973,1587,1588],{},"User names",[952,1590,1591,1596],{},[973,1592,1593],{},[877,1594,1595],{},"*.secret",[973,1597,1598,1599,1602],{},"Any nested property named ",[877,1600,1601],{},"secret"," (wildcard path)",[1080,1604,1606],{"id":1605},"http-logger-redaction-paths","HTTP Logger Redaction Paths",[946,1608,1609,1617],{},[949,1610,1611],{},[952,1612,1613,1615],{},[955,1614,1463],{},[955,1616,1466],{},[968,1618,1619,1627],{},[952,1620,1621,1625],{},[973,1622,1623],{},[877,1624,1475],{},[973,1626,1478],{},[952,1628,1629,1634],{},[973,1630,1631],{},[877,1632,1633],{},"req.cookies.session",[973,1635,1636],{},"The refresh token cookie value",[1638,1639,1640],"warning",{},[856,1641,1642,1643,1048,1645,1048,1647,1649,1650,1652,1653,1655],{},"The application logger redacts 13 paths including wildcards. If you log a custom object that contains a field named ",[877,1644,1575],{},[877,1646,1585],{},[877,1648,1515],{},", or ",[877,1651,1601],{},", Pino replaces it with ",[877,1654,1449],{}," automatically. Be aware of this behavior when adding new log calls with domain-specific objects.",[914,1657],{},[917,1659,1661],{"id":1660},"child-loggers","Child Loggers",[856,1663,1664,1665,1667],{},"Modules and controllers do not use the root logger directly. Instead, each creates a ",[868,1666,890],{}," that inherits all transports, redaction, and formatting from the parent but adds contextual fields. This pattern makes it possible to filter logs by service domain, branch, or request type without modifying the log destination.",[1080,1669,1671],{"id":1670},"creating-a-child-logger","Creating a Child Logger",[1095,1673,1675],{"className":1097,"code":1674,"language":1099,"meta":1100,"style":1100},"const log = getLogger().child({ service: 'auth', branch: 'access token' })\n\nlog.info('New access token issued')\n\u002F\u002F Output includes: { \"service\": \"auth\", \"branch\": \"access token\", ... }\n",[877,1676,1677,1722,1726,1746],{"__ignoreMap":1100},[1104,1678,1679,1681,1683,1685,1687,1690,1693,1695,1697,1699,1701,1704,1706,1708,1710,1712,1714,1717,1719],{"class":1106,"line":1107},[1104,1680,1149],{"class":1148},[1104,1682,1153],{"class":1152},[1104,1684,1157],{"class":1156},[1104,1686,1161],{"class":1160},[1104,1688,1689],{"class":1114},"().",[1104,1691,1692],{"class":1160},"child",[1104,1694,1177],{"class":1114},[1104,1696,894],{"class":1118},[1104,1698,1184],{"class":1183},[1104,1700,1129],{"class":1128},[1104,1702,1703],{"class":1132},"auth",[1104,1705,1194],{"class":1128},[1104,1707,1048],{"class":1114},[1104,1709,898],{"class":1118},[1104,1711,1184],{"class":1183},[1104,1713,1129],{"class":1128},[1104,1715,1716],{"class":1132},"access token",[1104,1718,1194],{"class":1128},[1104,1720,1721],{"class":1114}," })\n",[1104,1723,1724],{"class":1106,"line":1139},[1104,1725,1142],{"emptyLinePlaceholder":8},[1104,1727,1728,1730,1732,1734,1737,1739,1742,1744],{"class":1106,"line":1145},[1104,1729,1170],{"class":1118},[1104,1731,941],{"class":1114},[1104,1733,985],{"class":1160},[1104,1735,1736],{"class":1114},"(",[1104,1738,1194],{"class":1128},[1104,1740,1741],{"class":1132},"New access token issued",[1104,1743,1194],{"class":1128},[1104,1745,1202],{"class":1114},[1104,1747,1748],{"class":1106,"line":1167},[1104,1749,1751],{"class":1750},"sghk6","\u002F\u002F Output includes: { \"service\": \"auth\", \"branch\": \"access token\", ... }\n",[1080,1753,1755],{"id":1754},"naming-conventions","Naming Conventions",[856,1757,1208,1758,1760,1761,1763],{},[877,1759,894],{}," field identifies the subsystem. The ",[877,1762,898],{}," field narrows it to a specific operation. Some branches add extra fields for request-level tracing:",[946,1765,1766,1780],{},[949,1767,1768],{},[952,1769,1770,1772,1774,1777],{},[955,1771,894],{},[955,1773,898],{},[955,1775,1776],{},"Extra fields",[955,1778,1779],{},"Used by",[968,1781,1782,1797,1813,1836,1855,1874,1896,1912,1928,1944,1960,1979,1998],{},[952,1783,1784,1788,1792,1794],{},[973,1785,1786],{},[877,1787,1703],{},[973,1789,1790],{},[877,1791,1716],{},[973,1793],{},[973,1795,1796],{},"Access token generation and verification",[952,1798,1799,1803,1808,1810],{},[973,1800,1801],{},[877,1802,1703],{},[973,1804,1805],{},[877,1806,1807],{},"refresh tokens",[973,1809],{},[973,1811,1812],{},"Refresh token lifecycle (generate, verify, revoke, rotate)",[952,1814,1815,1819,1824,1833],{},[973,1816,1817],{},[877,1818,1703],{},[973,1820,1821],{},[877,1822,1823],{},"classic",[973,1825,1826,1829,1830],{},[877,1827,1828],{},"type: 'login'"," or ",[877,1831,1832],{},"type: 'signup'",[973,1834,1835],{},"Login and signup controllers",[952,1837,1838,1842,1847,1852],{},[973,1839,1840],{},[877,1841,1703],{},[973,1843,1844],{},[877,1845,1846],{},"tempLinks",[973,1848,1849],{},[877,1850,1851],{},"type: 'signature'",[973,1853,1854],{},"Magic link signature verification",[952,1856,1857,1861,1866,1871],{},[973,1858,1859],{},[877,1860,1703],{},[973,1862,1863],{},[877,1864,1865],{},"mfa",[973,1867,1868],{},[877,1869,1870],{},"visitorId",[973,1872,1873],{},"MFA code generation and verification",[952,1875,1876,1880,1885,1893],{},[973,1877,1878],{},[877,1879,1703],{},[973,1881,1882],{},[877,1883,1884],{},"anomalies",[973,1886,1887,1048,1890],{},[877,1888,1889],{},"visitor_cookie",[877,1891,1892],{},"ip",[973,1894,1895],{},"Anomaly detection engine",[952,1897,1898,1902,1907,1909],{},[973,1899,1900],{},[877,1901,1703],{},[973,1903,1904],{},[877,1905,1906],{},"oauth",[973,1908],{},[973,1910,1911],{},"OAuth provider flow",[952,1913,1914,1918,1923,1925],{},[973,1915,1916],{},[877,1917,1703],{},[973,1919,1920],{},[877,1921,1922],{},"logout",[973,1924],{},[973,1926,1927],{},"Logout and session teardown",[952,1929,1930,1934,1939,1941],{},[973,1931,1932],{},[877,1933,1703],{},[973,1935,1936],{},[877,1937,1938],{},"content guard",[973,1940],{},[973,1942,1943],{},"Content security enforcement",[952,1945,1946,1950,1955,1957],{},[973,1947,1948],{},[877,1949,1703],{},[973,1951,1952],{},[877,1953,1954],{},"password-reset",[973,1956],{},[973,1958,1959],{},"Password change flow",[952,1961,1962,1966,1971,1976],{},[973,1963,1964],{},[877,1965,1703],{},[973,1967,1968],{},[877,1969,1970],{},"routes",[973,1972,1973],{},[877,1974,1975],{},"type: 'Json checker'",[973,1977,1978],{},"Request body validation middleware",[952,1980,1981,1985,1990,1995],{},[973,1982,1983],{},[877,1984,1703],{},[973,1986,1987],{},[877,1988,1989],{},"utils",[973,1991,1992],{},[877,1993,1994],{},"type: 'sanitizeInputString'",[973,1996,1997],{},"HTML sanitization utility",[952,1999,2000,2005,2007,2012],{},[973,2001,2002],{},[877,2003,2004],{},"HMAC",[973,2006],{},[973,2008,2009],{},[877,2010,2011],{},"clientId",[973,2013,2014],{},"HMAC signature verification",[1059,2016,2017],{},[856,2018,2019,2020,2022,2023,2025,2026,895,2029,2031],{},"To trace a single user's MFA flow in production, filter ",[877,2021,1032],{}," by request ID, then cross-reference with ",[877,2024,977],{}," entries where ",[877,2027,2028],{},"branch = \"mfa\"",[877,2030,1870],{}," matches. The combination of HTTP and application logs covers both the request lifecycle and the business logic decisions.",[914,2033],{},[917,2035,2037],{"id":2036},"http-logger","HTTP Logger",[856,2039,2040],{},"The HTTP logger is an Express middleware that wraps every inbound request in a structured log entry. It is the first middleware mounted in the Express chain, so it captures the full lifecycle of every request including those rejected by later middleware.",[1080,2042,2044],{"id":2043},"middleware-position","Middleware Position",[1095,2046,2051],{"className":2047,"code":2049,"language":2050},[2048],"language-text","httpLogger → helmet → headers → validateIp → hmacAuth? → json → cookieParser → routes\n","text",[877,2052,2049],{"__ignoreMap":1100},[856,2054,2055,2056,2059],{},"Because ",[877,2057,2058],{},"httpLogger"," runs before everything else, every request gets a log entry regardless of whether it passes authentication, HMAC validation, or body parsing.",[1080,2061,2063],{"id":2062},"request-id","Request ID",[856,2065,2066],{},"The HTTP logger generates a unique identifier for every request and exposes it in the response:",[2068,2069,2071,2076,2083,2087,2096,2100,2107,2111],"steps",{"level":2070},"4",[2072,2073,2075],"h4",{"id":2074},"check-for-existing-id","Check for existing ID",[856,2077,2078,2079,2082],{},"If ",[877,2080,2081],{},"req.id"," is already set (by an upstream proxy or load balancer), the logger uses it.",[2072,2084,2086],{"id":2085},"check-the-header","Check the header",[856,2088,2078,2089,2091,2092,2095],{},[877,2090,2081],{}," is not set, the logger checks for an ",[877,2093,2094],{},"x-request-id"," header. If present, it uses that value.",[2072,2097,2099],{"id":2098},"generate-a-new-id","Generate a new ID",[856,2101,2102,2103,2106],{},"If neither source provides an ID, the logger generates one with ",[877,2104,2105],{},"crypto.randomUUID()"," (UUIDv4).",[2072,2108,2110],{"id":2109},"set-the-response-header","Set the response header",[856,2112,2113,2114,2116],{},"The logger always sets ",[877,2115,911],{}," on the response, so the client (or downstream service) can correlate its own logs to this specific request.",[1080,2118,2120],{"id":2119},"log-levels-by-status-code","Log Levels by Status Code",[856,2122,2123],{},"The HTTP logger assigns a severity level to each request based on the response status code:",[946,2125,2126,2139],{},[949,2127,2128],{},[952,2129,2130,2133,2136],{},[955,2131,2132],{},"Status Range",[955,2134,2135],{},"Log Level",[955,2137,2138],{},"Meaning",[968,2140,2141,2155,2169,2183],{},[952,2142,2143,2148,2152],{},[973,2144,2145],{},[877,2146,2147],{},"500+",[973,2149,2150],{},[877,2151,1022],{},[973,2153,2154],{},"Server error. Something broke.",[952,2156,2157,2162,2166],{},[973,2158,2159],{},[877,2160,2161],{},"400-499",[973,2163,2164],{},[877,2165,1005],{},[973,2167,2168],{},"Client error. Bad input, unauthorized, rate limited.",[952,2170,2171,2176,2180],{},[973,2172,2173],{},[877,2174,2175],{},"200-399",[973,2177,2178],{},[877,2179,985],{},[973,2181,2182],{},"Success. Normal operation.",[952,2184,2185,2190,2195],{},[973,2186,2187],{},[877,2188,2189],{},"\u002F.well-known\u002F",[973,2191,2192],{},[877,2193,2194],{},"silent",[973,2196,2197],{},"Suppressed entirely. Health checks and ACME challenges produce no log output.",[2199,2200,2201],"note",{},[856,2202,2203,2204,2206,2207,2209,2210,2213],{},"Requests to ",[877,2205,2189],{}," paths are silenced to prevent health check probes from flooding ",[877,2208,1032],{},". This is controlled by a path check in the ",[877,2211,2212],{},"customLogLevel"," function.",[1080,2215,2217],{"id":2216},"asset-filtering","Asset Filtering",[856,2219,2220],{},"Static asset requests are excluded entirely from HTTP logging. The logger checks the request URL against a regex of file extensions and skips the log entry if any match:",[856,2222,2223,1048,2226,1048,2229,1048,2232,1048,2235,1048,2238,1048,2241,1048,2244,1048,2247,1048,2250,1048,2253,1048,2256,1048,2259],{},[877,2224,2225],{},".css",[877,2227,2228],{},".js",[877,2230,2231],{},".png",[877,2233,2234],{},".jpg",[877,2236,2237],{},".jpeg",[877,2239,2240],{},".svg",[877,2242,2243],{},".ico",[877,2245,2246],{},".woff",[877,2248,2249],{},".woff2",[877,2251,2252],{},".ttf",[877,2254,2255],{},".map",[877,2257,2258],{},".webp",[877,2260,2261],{},".json",[856,2263,2264,2265,2267],{},"This prevents CDN or browser cache-miss requests for static files from cluttering ",[877,2266,1032],{}," with entries that carry no diagnostic value.",[1080,2269,2271],{"id":2270},"custom-properties","Custom Properties",[856,2273,2274],{},"Each HTTP log entry includes these additional fields beyond the standard pino-http output:",[946,2276,2277,2290],{},[949,2278,2279],{},[952,2280,2281,2284,2287],{},[955,2282,2283],{},"Field",[955,2285,2286],{},"Source",[955,2288,2289],{},"Description",[968,2291,2292,2310,2325,2340],{},[952,2293,2294,2298,2303],{},[973,2295,2296],{},[877,2297,1892],{},[973,2299,2300],{},[877,2301,2302],{},"req.ip",[973,2304,2305,2306,2309],{},"Client IP address as seen by Express (respects ",[877,2307,2308],{},"trust proxy",")",[952,2311,2312,2317,2322],{},[973,2313,2314],{},[877,2315,2316],{},"userAgent",[973,2318,2319],{},[877,2320,2321],{},"req.headers['user-agent']",[973,2323,2324],{},"Raw User-Agent header string",[952,2326,2327,2332,2337],{},[973,2328,2329],{},[877,2330,2331],{},"FullUrl",[973,2333,2334],{},[877,2335,2336],{},"req.protocol + ':\u002F\u002F' + req.hostname + req.originalUrl",[973,2338,2339],{},"Complete URL including protocol, host, and query string",[952,2341,2342,2346,2351],{},[973,2343,2344],{},[877,2345,1525],{},[973,2347,2348],{},[877,2349,2350],{},"req.headers.cookie",[973,2352,2353,2354,2357],{},"Raw cookie header (redacted for ",[877,2355,2356],{},"session"," via redaction paths)",[1080,2359,2361],{"id":2360},"custom-attribute-keys","Custom Attribute Keys",[856,2363,2364],{},"The HTTP logger renames pino-http's default attribute keys to more descriptive names:",[946,2366,2367,2377],{},[949,2368,2369],{},[952,2370,2371,2374],{},[955,2372,2373],{},"Default Key",[955,2375,2376],{},"Custom Key",[968,2378,2379,2391,2403,2415,2427],{},[952,2380,2381,2386],{},[973,2382,2383],{},[877,2384,2385],{},"req",[973,2387,2388],{},[877,2389,2390],{},"httpRequest",[952,2392,2393,2398],{},[973,2394,2395],{},[877,2396,2397],{},"res",[973,2399,2400],{},[877,2401,2402],{},"httpResponse",[952,2404,2405,2410],{},[973,2406,2407],{},[877,2408,2409],{},"err",[973,2411,2412],{},[877,2413,2414],{},"httpError",[952,2416,2417,2422],{},[973,2418,2419],{},[877,2420,2421],{},"responseTime",[973,2423,2424],{},[877,2425,2426],{},"latency",[952,2428,2429,2434],{},[973,2430,2431],{},[877,2432,2433],{},"reqId",[973,2435,2436],{},[877,2437,2438],{},"requestId",[856,2440,2441,2442,2444],{},"A typical ",[877,2443,1032],{}," entry looks like this:",[1095,2446,2448],{"className":1346,"code":2447,"language":5,"meta":1100,"style":1100},"{\n  \"level\": 30,\n  \"time\": \"2025-01-15T14:30:00.000Z\",\n  \"requestId\": \"a1b2c3d4-e5f6-7890-abcd-ef1234567890\",\n  \"httpRequest\": { \"method\": \"POST\", \"url\": \"\u002Fauth\u002Fuser\u002Frefresh-session\" },\n  \"httpResponse\": { \"statusCode\": 201 },\n  \"latency\": 23,\n  \"ip\": \"192.168.1.1\",\n  \"userAgent\": \"Mozilla\u002F5.0 ...\",\n  \"FullUrl\": \"https:\u002F\u002Fauth.example.com\u002Fauth\u002Fuser\u002Frefresh-session\",\n  \"msg\": \"POST \u002Fauth\u002Fuser\u002Frefresh-session 201 23ms\"\n}\n",[877,2449,2450,2454,2468,2486,2505,2554,2580,2596,2616,2636,2656,2674],{"__ignoreMap":1100},[1104,2451,2452],{"class":1106,"line":1107},[1104,2453,1354],{"class":1114},[1104,2455,2456,2458,2460,2462,2464,2466],{"class":1106,"line":1139},[1104,2457,1360],{"class":1359},[1104,2459,1364],{"class":1363},[1104,2461,1367],{"class":1359},[1104,2463,1184],{"class":1156},[1104,2465,1372],{"class":1187},[1104,2467,1375],{"class":1114},[1104,2469,2470,2472,2474,2476,2478,2480,2482,2484],{"class":1106,"line":1145},[1104,2471,1360],{"class":1359},[1104,2473,1382],{"class":1363},[1104,2475,1367],{"class":1359},[1104,2477,1184],{"class":1156},[1104,2479,1389],{"class":1128},[1104,2481,1392],{"class":1132},[1104,2483,1367],{"class":1128},[1104,2485,1375],{"class":1114},[1104,2487,2488,2490,2492,2494,2496,2498,2501,2503],{"class":1106,"line":1167},[1104,2489,1360],{"class":1359},[1104,2491,2438],{"class":1363},[1104,2493,1367],{"class":1359},[1104,2495,1184],{"class":1156},[1104,2497,1389],{"class":1128},[1104,2499,2500],{"class":1132},"a1b2c3d4-e5f6-7890-abcd-ef1234567890",[1104,2502,1367],{"class":1128},[1104,2504,1375],{"class":1114},[1104,2506,2507,2509,2511,2513,2515,2517,2519,2522,2524,2526,2528,2531,2533,2535,2537,2540,2542,2544,2546,2549,2551],{"class":1106,"line":1415},[1104,2508,1360],{"class":1359},[1104,2510,2390],{"class":1363},[1104,2512,1367],{"class":1359},[1104,2514,1184],{"class":1156},[1104,2516,1115],{"class":1114},[1104,2518,1367],{"class":1359},[1104,2520,2521],{"class":1363},"method",[1104,2523,1367],{"class":1359},[1104,2525,1184],{"class":1156},[1104,2527,1389],{"class":1128},[1104,2529,2530],{"class":1132},"POST",[1104,2532,1367],{"class":1128},[1104,2534,1048],{"class":1114},[1104,2536,1367],{"class":1359},[1104,2538,2539],{"class":1363},"url",[1104,2541,1367],{"class":1359},[1104,2543,1184],{"class":1156},[1104,2545,1389],{"class":1128},[1104,2547,2548],{"class":1132},"\u002Fauth\u002Fuser\u002Frefresh-session",[1104,2550,1367],{"class":1128},[1104,2552,2553],{"class":1114}," },\n",[1104,2555,2556,2558,2560,2562,2564,2566,2568,2571,2573,2575,2578],{"class":1106,"line":1434},[1104,2557,1360],{"class":1359},[1104,2559,2402],{"class":1363},[1104,2561,1367],{"class":1359},[1104,2563,1184],{"class":1156},[1104,2565,1115],{"class":1114},[1104,2567,1367],{"class":1359},[1104,2569,2570],{"class":1363},"statusCode",[1104,2572,1367],{"class":1359},[1104,2574,1184],{"class":1156},[1104,2576,2577],{"class":1187}," 201",[1104,2579,2553],{"class":1114},[1104,2581,2583,2585,2587,2589,2591,2594],{"class":1106,"line":2582},7,[1104,2584,1360],{"class":1359},[1104,2586,2426],{"class":1363},[1104,2588,1367],{"class":1359},[1104,2590,1184],{"class":1156},[1104,2592,2593],{"class":1187}," 23",[1104,2595,1375],{"class":1114},[1104,2597,2599,2601,2603,2605,2607,2609,2612,2614],{"class":1106,"line":2598},8,[1104,2600,1360],{"class":1359},[1104,2602,1892],{"class":1363},[1104,2604,1367],{"class":1359},[1104,2606,1184],{"class":1156},[1104,2608,1389],{"class":1128},[1104,2610,2611],{"class":1132},"192.168.1.1",[1104,2613,1367],{"class":1128},[1104,2615,1375],{"class":1114},[1104,2617,2619,2621,2623,2625,2627,2629,2632,2634],{"class":1106,"line":2618},9,[1104,2620,1360],{"class":1359},[1104,2622,2316],{"class":1363},[1104,2624,1367],{"class":1359},[1104,2626,1184],{"class":1156},[1104,2628,1389],{"class":1128},[1104,2630,2631],{"class":1132},"Mozilla\u002F5.0 ...",[1104,2633,1367],{"class":1128},[1104,2635,1375],{"class":1114},[1104,2637,2639,2641,2643,2645,2647,2649,2652,2654],{"class":1106,"line":2638},10,[1104,2640,1360],{"class":1359},[1104,2642,2331],{"class":1363},[1104,2644,1367],{"class":1359},[1104,2646,1184],{"class":1156},[1104,2648,1389],{"class":1128},[1104,2650,2651],{"class":1132},"https:\u002F\u002Fauth.example.com\u002Fauth\u002Fuser\u002Frefresh-session",[1104,2653,1367],{"class":1128},[1104,2655,1375],{"class":1114},[1104,2657,2659,2661,2663,2665,2667,2669,2672],{"class":1106,"line":2658},11,[1104,2660,1360],{"class":1359},[1104,2662,1420],{"class":1363},[1104,2664,1367],{"class":1359},[1104,2666,1184],{"class":1156},[1104,2668,1389],{"class":1128},[1104,2670,2671],{"class":1132},"POST \u002Fauth\u002Fuser\u002Frefresh-session 201 23ms",[1104,2673,1431],{"class":1128},[1104,2675,2677],{"class":1106,"line":2676},12,[1104,2678,1437],{"class":1114},[1080,2680,2682],{"id":2681},"custom-messages","Custom Messages",[856,2684,2685],{},"The HTTP logger generates context-aware log messages depending on the response status:",[946,2687,2688,2698],{},[949,2689,2690],{},[952,2691,2692,2695],{},[955,2693,2694],{},"Condition",[955,2696,2697],{},"Message format",[968,2699,2700,2713,2725],{},[952,2701,2702,2708],{},[973,2703,2704,2705],{},"Status ",[877,2706,2707],{},"404",[973,2709,2710],{},[877,2711,2712],{},"\"{method} {url} {status} Referer: {referer} {latency}ms\"",[952,2714,2715,2720],{},[973,2716,2704,2717,2719],{},[877,2718,2147],{}," (with error)",[973,2721,2722],{},[877,2723,2724],{},"\"{error.name}: {error.message} {error.stack}\"",[952,2726,2727,2730],{},[973,2728,2729],{},"All other statuses",[973,2731,2732],{},[877,2733,2734],{},"\"{method} {url} {status} {latency}ms\"",[856,2736,1208,2737,2739,2740,2743,2744,2746,2747,941],{},[877,2738,2707],{}," message includes the ",[877,2741,2742],{},"Referer"," header to help trace where broken links originate. Error messages include the full stack trace so you can diagnose server errors directly from ",[877,2745,1032],{}," without needing to correlate with ",[877,2748,1015],{},[1080,2750,2752],{"id":2751},"serializers","Serializers",[856,2754,2755,2756,1048,2758,1051,2760,2762],{},"The HTTP logger uses pino-http's built-in ",[877,2757,2385],{},[877,2759,2397],{},[877,2761,2409],{}," serializers. These extract a safe subset of request and response data (method, url, headers for requests; statusCode for responses; message, type, stack for errors) while avoiding circular references and excessively large objects.",[914,2764],{},[917,2766,2768],{"id":2767},"accessing-logs","Accessing Logs",[1080,2770,2772],{"id":2771},"file-system","File System",[1095,2774,2778],{"className":2775,"code":2776,"language":2777,"meta":1100,"style":1100},"language-bash shiki shiki-themes light-plus light-plus dracula","# Real-time application errors\ntail -f auth-logs\u002Ferrors.log\n\n# Real-time HTTP traffic\ntail -f auth-logs\u002Fhttp.log\n\n# Warnings and errors together\ntail -f auth-logs\u002Fwarn.log\n\n# Everything (most verbose)\ntail -f auth-logs\u002Finfo.log\n","bash",[877,2779,2780,2785,2797,2801,2806,2815,2819,2824,2833,2837,2842],{"__ignoreMap":1100},[1104,2781,2782],{"class":1106,"line":1107},[1104,2783,2784],{"class":1750},"# Real-time application errors\n",[1104,2786,2787,2790,2794],{"class":1106,"line":1139},[1104,2788,2789],{"class":1160},"tail",[1104,2791,2793],{"class":2792},"sjR7W"," -f",[1104,2795,2796],{"class":1132}," auth-logs\u002Ferrors.log\n",[1104,2798,2799],{"class":1106,"line":1145},[1104,2800,1142],{"emptyLinePlaceholder":8},[1104,2802,2803],{"class":1106,"line":1167},[1104,2804,2805],{"class":1750},"# Real-time HTTP traffic\n",[1104,2807,2808,2810,2812],{"class":1106,"line":1415},[1104,2809,2789],{"class":1160},[1104,2811,2793],{"class":2792},[1104,2813,2814],{"class":1132}," auth-logs\u002Fhttp.log\n",[1104,2816,2817],{"class":1106,"line":1434},[1104,2818,1142],{"emptyLinePlaceholder":8},[1104,2820,2821],{"class":1106,"line":2582},[1104,2822,2823],{"class":1750},"# Warnings and errors together\n",[1104,2825,2826,2828,2830],{"class":1106,"line":2598},[1104,2827,2789],{"class":1160},[1104,2829,2793],{"class":2792},[1104,2831,2832],{"class":1132}," auth-logs\u002Fwarn.log\n",[1104,2834,2835],{"class":1106,"line":2618},[1104,2836,1142],{"emptyLinePlaceholder":8},[1104,2838,2839],{"class":1106,"line":2638},[1104,2840,2841],{"class":1750},"# Everything (most verbose)\n",[1104,2843,2844,2846,2848],{"class":1106,"line":2658},[1104,2845,2789],{"class":1160},[1104,2847,2793],{"class":2792},[1104,2849,2850],{"class":1132}," auth-logs\u002Finfo.log\n",[1080,2852,2854],{"id":2853},"docker-compose","Docker Compose",[856,2856,2857,2858,2860],{},"When the IAM service runs inside Docker, the ",[877,2859,879],{}," directory is typically mounted as a volume. You can tail logs from the host:",[1095,2862,2864],{"className":2775,"code":2863,"language":2777,"meta":1100,"style":1100},"docker compose logs -f auth\n",[877,2865,2866],{"__ignoreMap":1100},[1104,2867,2868,2871,2874,2877,2879],{"class":1106,"line":1107},[1104,2869,2870],{"class":1160},"docker",[1104,2872,2873],{"class":1132}," compose",[1104,2875,2876],{"class":1132}," logs",[1104,2878,2793],{"class":2792},[1104,2880,2881],{"class":1132}," auth\n",[856,2883,2884],{},"Or access the log files directly in the mounted volume:",[1095,2886,2888],{"className":2775,"code":2887,"language":2777,"meta":1100,"style":1100},"tail -f .\u002Fauth-logs\u002Ferrors.log\n",[877,2889,2890],{"__ignoreMap":1100},[1104,2891,2892,2894,2896],{"class":1106,"line":1107},[1104,2893,2789],{"class":1160},[1104,2895,2793],{"class":2792},[1104,2897,2898],{"class":1132}," .\u002Fauth-logs\u002Ferrors.log\n",[1080,2900,2902],{"id":2901},"filtering-with-jq","Filtering with jq",[856,2904,2905,2906,2911],{},"Since every log file contains newline-delimited JSON, you can use ",[860,2907,2910],{"href":2908,"rel":2909},"https:\u002F\u002Fjqlang.github.io\u002Fjq\u002F",[864],"jq"," to filter entries:",[1095,2913,2915],{"className":2775,"code":2914,"language":2777,"meta":1100,"style":1100},"# All MFA-related application logs\ncat auth-logs\u002Finfo.log | jq 'select(.branch == \"mfa\")'\n\n# All HTTP 500 errors with latency > 100ms\ncat auth-logs\u002Fhttp.log | jq 'select(.httpResponse.statusCode >= 500 and .latency > 100)'\n\n# All requests from a specific IP\ncat auth-logs\u002Fhttp.log | jq 'select(.ip == \"203.0.113.42\")'\n\n# Trace a request by ID across both logs\nexport RID=\"a1b2c3d4-e5f6-7890-abcd-ef1234567890\"\ncat auth-logs\u002Fhttp.log | jq \"select(.requestId == \\\"$RID\\\")\"\ncat auth-logs\u002Finfo.log | jq \"select(.requestId == \\\"$RID\\\")\"\n",[877,2916,2917,2922,2943,2947,2952,2970,2974,2979,2996,3000,3005,3023,3051],{"__ignoreMap":1100},[1104,2918,2919],{"class":1106,"line":1107},[1104,2920,2921],{"class":1750},"# All MFA-related application logs\n",[1104,2923,2924,2927,2930,2933,2936,2938,2941],{"class":1106,"line":1139},[1104,2925,2926],{"class":1160},"cat",[1104,2928,2929],{"class":1132}," auth-logs\u002Finfo.log",[1104,2931,2932],{"class":1156}," |",[1104,2934,2935],{"class":1160}," jq",[1104,2937,1129],{"class":1128},[1104,2939,2940],{"class":1132},"select(.branch == \"mfa\")",[1104,2942,1136],{"class":1128},[1104,2944,2945],{"class":1106,"line":1145},[1104,2946,1142],{"emptyLinePlaceholder":8},[1104,2948,2949],{"class":1106,"line":1167},[1104,2950,2951],{"class":1750},"# All HTTP 500 errors with latency > 100ms\n",[1104,2953,2954,2956,2959,2961,2963,2965,2968],{"class":1106,"line":1415},[1104,2955,2926],{"class":1160},[1104,2957,2958],{"class":1132}," auth-logs\u002Fhttp.log",[1104,2960,2932],{"class":1156},[1104,2962,2935],{"class":1160},[1104,2964,1129],{"class":1128},[1104,2966,2967],{"class":1132},"select(.httpResponse.statusCode >= 500 and .latency > 100)",[1104,2969,1136],{"class":1128},[1104,2971,2972],{"class":1106,"line":1434},[1104,2973,1142],{"emptyLinePlaceholder":8},[1104,2975,2976],{"class":1106,"line":2582},[1104,2977,2978],{"class":1750},"# All requests from a specific IP\n",[1104,2980,2981,2983,2985,2987,2989,2991,2994],{"class":1106,"line":2598},[1104,2982,2926],{"class":1160},[1104,2984,2958],{"class":1132},[1104,2986,2932],{"class":1156},[1104,2988,2935],{"class":1160},[1104,2990,1129],{"class":1128},[1104,2992,2993],{"class":1132},"select(.ip == \"203.0.113.42\")",[1104,2995,1136],{"class":1128},[1104,2997,2998],{"class":1106,"line":2618},[1104,2999,1142],{"emptyLinePlaceholder":8},[1104,3001,3002],{"class":1106,"line":2638},[1104,3003,3004],{"class":1750},"# Trace a request by ID across both logs\n",[1104,3006,3007,3010,3014,3017,3019,3021],{"class":1106,"line":2658},[1104,3008,3009],{"class":1148},"export",[1104,3011,3013],{"class":3012},"sWkX1"," RID",[1104,3015,3016],{"class":1156},"=",[1104,3018,1367],{"class":1128},[1104,3020,2500],{"class":1132},[1104,3022,1431],{"class":1128},[1104,3024,3025,3027,3029,3031,3033,3035,3038,3042,3045,3047,3049],{"class":1106,"line":2676},[1104,3026,2926],{"class":1160},[1104,3028,2958],{"class":1132},[1104,3030,2932],{"class":1156},[1104,3032,2935],{"class":1160},[1104,3034,1389],{"class":1128},[1104,3036,3037],{"class":1132},"select(.requestId == ",[1104,3039,3041],{"class":3040},"st6lo","\\\"",[1104,3043,3044],{"class":3012},"$RID",[1104,3046,3041],{"class":3040},[1104,3048,2309],{"class":1132},[1104,3050,1431],{"class":1128},[1104,3052,3054,3056,3058,3060,3062,3064,3066,3068,3070,3072,3074],{"class":1106,"line":3053},13,[1104,3055,2926],{"class":1160},[1104,3057,2929],{"class":1132},[1104,3059,2932],{"class":1156},[1104,3061,2935],{"class":1160},[1104,3063,1389],{"class":1128},[1104,3065,3037],{"class":1132},[1104,3067,3041],{"class":3040},[1104,3069,3044],{"class":3012},[1104,3071,3041],{"class":3040},[1104,3073,2309],{"class":1132},[1104,3075,1431],{"class":1128},[914,3077],{},[917,3079,3081],{"id":3080},"summary","Summary",[946,3083,3084,3095],{},[949,3085,3086],{},[952,3087,3088,3091,3093],{},[955,3089,3090],{},"Aspect",[955,3092,1078],{},[955,3094,2037],{},[968,3096,3097,3107,3120,3137,3150,3162,3171,3182,3193],{},[952,3098,3099,3101,3104],{},[973,3100,51],{},[973,3102,3103],{},"Pino 10",[973,3105,3106],{},"pino-http 10",[952,3108,3109,3112,3117],{},[973,3110,3111],{},"Instance",[973,3113,3114,3115],{},"Singleton via ",[877,3116,886],{},[973,3118,3119],{},"Express middleware",[952,3121,3122,3125,3133],{},[973,3123,3124],{},"Log files",[973,3126,3127,1048,3129,1048,3131],{},[877,3128,977],{},[877,3130,998],{},[877,3132,1015],{},[973,3134,3135],{},[877,3136,1032],{},[952,3138,3139,3142,3148],{},[973,3140,3141],{},"Redaction paths",[973,3143,3144,3145,3147],{},"13 (including ",[877,3146,1595],{}," wildcard)",[973,3149,1291],{},[952,3151,3152,3154,3157],{},[973,3153,2063],{},[973,3155,3156],{},"Not generated (use child logger fields)",[973,3158,3159,3160,2309],{},"Generated per request (",[877,3161,2105],{},[952,3163,3164,3166,3169],{},[973,3165,1321],{},[973,3167,3168],{},"ISO 8601",[973,3170,3168],{},[952,3172,3173,3176,3179],{},[973,3174,3175],{},"Asset filtering",[973,3177,3178],{},"N\u002FA",[973,3180,3181],{},"Excludes 13 static file extensions",[952,3183,3184,3187,3190],{},[973,3185,3186],{},"Child loggers",[973,3188,3189],{},"Yes, per module\u002Fcontroller",[973,3191,3192],{},"No",[952,3194,3195,3198,3203],{},[973,3196,3197],{},"Custom fields",[973,3199,3200,3202],{},[877,3201,1403],{}," (mixin)",[973,3204,3205,1048,3207,1048,3209,1048,3211],{},[877,3206,1892],{},[877,3208,2316],{},[877,3210,2331],{},[877,3212,1525],{},[3214,3215,3216],"style",{},"html pre.shiki code .sZ328, html code.shiki .sZ328{--shiki-light:#AF00DB;--shiki-default:#AF00DB;--shiki-dark:#FF79C6}html pre.shiki code .sDd4n, html code.shiki .sDd4n{--shiki-light:#000000;--shiki-default:#000000;--shiki-dark:#F8F8F2}html pre.shiki code .sjsA6, html code.shiki .sjsA6{--shiki-light:#001080;--shiki-default:#001080;--shiki-dark:#F8F8F2}html pre.shiki code .sFkSl, html code.shiki .sFkSl{--shiki-light:#A31515;--shiki-default:#A31515;--shiki-dark:#E9F284}html pre.shiki code .sFB1V, html code.shiki .sFB1V{--shiki-light:#A31515;--shiki-default:#A31515;--shiki-dark:#F1FA8C}html pre.shiki code .sl46w, html code.shiki .sl46w{--shiki-light:#0000FF;--shiki-default:#0000FF;--shiki-dark:#FF79C6}html pre.shiki code .s3JHE, html code.shiki .s3JHE{--shiki-light:#0070C1;--shiki-default:#0070C1;--shiki-dark:#F8F8F2}html pre.shiki code .saOXh, html code.shiki .saOXh{--shiki-light:#000000;--shiki-default:#000000;--shiki-dark:#FF79C6}html pre.shiki code .sHOzp, html code.shiki .sHOzp{--shiki-light:#795E26;--shiki-default:#795E26;--shiki-dark:#50FA7B}html pre.shiki code .s34zl, html code.shiki .s34zl{--shiki-light:#001080;--shiki-default:#001080;--shiki-dark:#FF79C6}html pre.shiki code .spgvN, html code.shiki .spgvN{--shiki-light:#098658;--shiki-default:#098658;--shiki-dark:#BD93F9}html .light .shiki span {color: var(--shiki-light);background: var(--shiki-light-bg);font-style: var(--shiki-light-font-style);font-weight: var(--shiki-light-font-weight);text-decoration: var(--shiki-light-text-decoration);}html.light .shiki span {color: var(--shiki-light);background: var(--shiki-light-bg);font-style: var(--shiki-light-font-style);font-weight: var(--shiki-light-font-weight);text-decoration: var(--shiki-light-text-decoration);}html .default .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}html .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}html .dark .shiki span {color: var(--shiki-dark);background: var(--shiki-dark-bg);font-style: var(--shiki-dark-font-style);font-weight: var(--shiki-dark-font-weight);text-decoration: var(--shiki-dark-text-decoration);}html.dark .shiki span {color: var(--shiki-dark);background: var(--shiki-dark-bg);font-style: var(--shiki-dark-font-style);font-weight: var(--shiki-dark-font-weight);text-decoration: var(--shiki-dark-text-decoration);}html pre.shiki code .saJyd, html code.shiki .saJyd{--shiki-light:#0451A5;--shiki-default:#0451A5;--shiki-dark:#8BE9FE}html pre.shiki code .s_W10, html code.shiki .s_W10{--shiki-light:#0451A5;--shiki-default:#0451A5;--shiki-dark:#8BE9FD}html pre.shiki code .sghk6, html code.shiki .sghk6{--shiki-light:#008000;--shiki-default:#008000;--shiki-dark:#6272A4}html pre.shiki code .sjR7W, html code.shiki .sjR7W{--shiki-light:#0000FF;--shiki-default:#0000FF;--shiki-dark:#BD93F9}html pre.shiki code .sWkX1, html code.shiki .sWkX1{--shiki-light:#001080;--shiki-default:#001080;--shiki-dark:#BD93F9}html pre.shiki code .st6lo, html code.shiki .st6lo{--shiki-light:#EE0000;--shiki-default:#EE0000;--shiki-dark:#FF79C6}",{"title":1100,"searchDepth":1139,"depth":1139,"links":3218},[3219,3220,3227,3231,3235,3245,3250],{"id":919,"depth":1139,"text":920},{"id":1077,"depth":1139,"text":1078,"children":3221},[3222,3223,3224,3225,3226],{"id":1082,"depth":1145,"text":1083},{"id":1205,"depth":1145,"text":237},{"id":1243,"depth":1145,"text":1244},{"id":1320,"depth":1145,"text":1321},{"id":1335,"depth":1145,"text":1336},{"id":1442,"depth":1139,"text":1443,"children":3228},[3229,3230],{"id":1453,"depth":1145,"text":1454},{"id":1605,"depth":1145,"text":1606},{"id":1660,"depth":1139,"text":1661,"children":3232},[3233,3234],{"id":1670,"depth":1145,"text":1671},{"id":1754,"depth":1145,"text":1755},{"id":2036,"depth":1139,"text":2037,"children":3236},[3237,3238,3239,3240,3241,3242,3243,3244],{"id":2043,"depth":1145,"text":2044},{"id":2062,"depth":1145,"text":2063},{"id":2119,"depth":1145,"text":2120},{"id":2216,"depth":1145,"text":2217},{"id":2270,"depth":1145,"text":2271},{"id":2360,"depth":1145,"text":2361},{"id":2681,"depth":1145,"text":2682},{"id":2751,"depth":1145,"text":2752},{"id":2767,"depth":1139,"text":2768,"children":3246},[3247,3248,3249],{"id":2771,"depth":1145,"text":2772},{"id":2853,"depth":1145,"text":2854},{"id":2901,"depth":1145,"text":2902},{"id":3080,"depth":1139,"text":3081},"How the IAM service structures application and HTTP request logging with Pino, including log file layout, redaction, request IDs, child loggers, and asset filtering.","md","i-lucide-file-text",{},null,"---\ntitle: Logging\ndescription: How the IAM service structures application and HTTP request logging with Pino, including log file layout, redaction, request IDs, child loggers, and asset filtering.\nicon: i-lucide-file-text\n---\n\nThe IAM service uses [Pino](https:\u002F\u002Fgetpino.io\u002F) for all logging. There are two distinct logger instances: an **application logger** for general-purpose messages (auth decisions, token operations, anomaly events), and an **HTTP logger** for per-request lifecycle tracking (method, status, latency, IP). Both write to files inside the `auth-logs\u002F` directory, both redact sensitive fields before anything reaches disk, and both attach structured metadata so every log entry carries machine-readable context.\n\nThe application logger is a singleton. It is created once at startup and shared across the entire process through `getLogger()`. Every module that needs to log creates a **child logger** from that singleton, tagging entries with a `service` and `branch` field so you can filter by domain (tokens, OAuth, MFA, anomalies) without splitting into separate files.\n\nThe HTTP logger is an Express middleware powered by [pino-http](https:\u002F\u002Fgithub.com\u002Fpinojs\u002Fpino-http). It wraps each request in a log entry that records timing, status, client IP, user agent, and the full URL. It assigns a unique request ID to every inbound request and propagates it in the `X-Request-Id` response header.\n\n---\n\n## Log Directory\n\nAll log files live under a single directory. The service resolves the path in this order:\n\n1. If the `LOG_DIR` environment variable is set, use that value.\n2. Otherwise, default to `${PROJECT_ROOT}\u002Fauth-logs`.\n\nThe directory is created automatically at startup if it does not exist. Four files are written:\n\n| File | Logger | Minimum Level | Contents |\n|---|---|---|---|\n| `info.log` | Application | `info` | Everything at `info` level and above (info, warn, error, fatal) |\n| `warn.log` | Application | `warn` | Warnings and errors only (warn, error, fatal) |\n| `errors.log` | Application | `error` | Errors and fatal entries only (error, fatal) |\n| `http.log` | HTTP | `info` | One entry per HTTP request (status, latency, IP, URL) |\n\nThe first three files are fed by the application logger through Pino's transport pipeline. Each transport targets a different file with a different minimum level, so the same application log entry can appear in `info.log`, `warn.log`, and `errors.log` simultaneously if its level qualifies. The HTTP logger writes exclusively to `http.log` through its own separate Pino instance.\n\n::tip\nTail `errors.log` during debugging to focus on failures. Tail `http.log` to see traffic patterns and latency spikes. `info.log` is the most verbose file and contains the union of all application-level activity.\n::\n\n---\n\n## Application Logger\n\n### Singleton Pattern\n\nThe application logger is created by `getLogger()`. On the first call, it reads the `logLevel` field from the service configuration, builds a Pino instance with three file transports, and caches it. Every subsequent call returns the same instance.\n\n```ts\nimport { getLogger } from '@riavzon\u002Fauth'\n\nconst log = getLogger()\nlog.info({ userId: 42 }, 'Token generated')\n```\n\n### Configuration\n\nThe `logLevel` field in the service configuration controls the minimum severity for the application logger. It accepts any standard Pino level.\n\n::field-group\n  ::field{name=\"logLevel\" type=\"string\"}\n  Minimum log level for the application logger. Accepted values: `trace`, `debug`, `info`, `warn`, `error`, `fatal`. Optional. Defaults to the Pino default (`info`) when omitted.\n  ::\n::\n\n### Transports\n\nThe logger uses `pino.transport()` with three `pino\u002Ffile` targets:\n\n| Target | Destination | Level |\n|---|---|---|\n| 1 | `auth-logs\u002Finfo.log` | `info` |\n| 2 | `auth-logs\u002Fwarn.log` | `warn` |\n| 3 | `auth-logs\u002Ferrors.log` | `error` |\n\nEach target is a Pino file transport that appends newline-delimited JSON. The targets run in worker threads managed by Pino's transport system, so log writes do not block the main event loop.\n\n### Timestamps\n\nEvery log entry carries an ISO 8601 timestamp generated by `pino.stdTimeFunctions.isoTime`. This produces values like `\"2025-01-15T14:30:00.000Z\"` rather than Unix epoch milliseconds.\n\n### Uptime Mixin\n\nA mixin function injects `process.uptime()` into every log entry. Both the application logger and the HTTP logger include this field. It records how many seconds the Node.js process has been running at the moment the log line was emitted. It helps correlate events to process lifecycle phases (startup, steady state, post-restart).\n\n```json\n{\n  \"level\": 30,\n  \"time\": \"2025-01-15T14:30:00.000Z\",\n  \"uptime\": 842.331,\n  \"msg\": \"Token generated\"\n}\n```\n\n---\n\n## Redaction\n\nBoth loggers aggressively redact sensitive data. Pino replaces the value of any matching path with `[SECRET]` before the entry reaches the transport layer - the raw value never appears in the log file.\n\n### Application Logger Redaction Paths\n\n| Path | What it protects |\n|---|---|\n| `req.headers.authorization` | Bearer tokens in request headers |\n| `user.password` | Raw or hashed passwords on user objects |\n| `accessToken` | Signed JWT access tokens |\n| `refresh_token` | Raw refresh token strings |\n| `cookie` | Full cookie header strings |\n| `cookies` | Parsed cookie objects |\n| `canary_id` | Bot-detector visitor identifier |\n| `req.cookies` | Parsed cookies from the request |\n| `req.cookie` | Raw cookie header from the request |\n| `access_token` | Access tokens in any property name |\n| `email` | User email addresses |\n| `name` | User names |\n| `*.secret` | Any nested property named `secret` (wildcard path) |\n\n### HTTP Logger Redaction Paths\n\n| Path | What it protects |\n|---|---|\n| `req.headers.authorization` | Bearer tokens in request headers |\n| `req.cookies.session` | The refresh token cookie value |\n\n::warning\nThe application logger redacts 13 paths including wildcards. If you log a custom object that contains a field named `email`, `name`, `cookie`, or `secret`, Pino replaces it with `[SECRET]` automatically. Be aware of this behavior when adding new log calls with domain-specific objects.\n::\n\n---\n\n## Child Loggers\n\nModules and controllers do not use the root logger directly. Instead, each creates a **child logger** that inherits all transports, redaction, and formatting from the parent but adds contextual fields. This pattern makes it possible to filter logs by service domain, branch, or request type without modifying the log destination.\n\n### Creating a Child Logger\n\n```ts\nconst log = getLogger().child({ service: 'auth', branch: 'access token' })\n\nlog.info('New access token issued')\n\u002F\u002F Output includes: { \"service\": \"auth\", \"branch\": \"access token\", ... }\n```\n\n### Naming Conventions\n\nThe `service` field identifies the subsystem. The `branch` field narrows it to a specific operation. Some branches add extra fields for request-level tracing:\n\n| service | branch | Extra fields | Used by |\n|---|---|---|---|\n| `auth` | `access token` | | Access token generation and verification |\n| `auth` | `refresh tokens` | | Refresh token lifecycle (generate, verify, revoke, rotate) |\n| `auth` | `classic` | `type: 'login'` or `type: 'signup'` | Login and signup controllers |\n| `auth` | `tempLinks` | `type: 'signature'` | Magic link signature verification |\n| `auth` | `mfa` | `visitorId` | MFA code generation and verification |\n| `auth` | `anomalies` | `visitor_cookie`, `ip` | Anomaly detection engine |\n| `auth` | `oauth` | | OAuth provider flow |\n| `auth` | `logout` | | Logout and session teardown |\n| `auth` | `content guard` | | Content security enforcement |\n| `auth` | `password-reset` | | Password change flow |\n| `auth` | `routes` | `type: 'Json checker'` | Request body validation middleware |\n| `auth` | `utils` | `type: 'sanitizeInputString'` | HTML sanitization utility |\n| `HMAC` | | `clientId` | HMAC signature verification |\n\n::tip\nTo trace a single user's MFA flow in production, filter `http.log` by request ID, then cross-reference with `info.log` entries where `branch = \"mfa\"` and `visitorId` matches. The combination of HTTP and application logs covers both the request lifecycle and the business logic decisions.\n::\n\n---\n\n## HTTP Logger\n\nThe HTTP logger is an Express middleware that wraps every inbound request in a structured log entry. It is the first middleware mounted in the Express chain, so it captures the full lifecycle of every request including those rejected by later middleware.\n\n### Middleware Position\n\n```\nhttpLogger → helmet → headers → validateIp → hmacAuth? → json → cookieParser → routes\n```\n\nBecause `httpLogger` runs before everything else, every request gets a log entry regardless of whether it passes authentication, HMAC validation, or body parsing.\n\n### Request ID\n\nThe HTTP logger generates a unique identifier for every request and exposes it in the response:\n\n::steps{level=\"4\"}\n#### Check for existing ID\nIf `req.id` is already set (by an upstream proxy or load balancer), the logger uses it.\n\n#### Check the header\nIf `req.id` is not set, the logger checks for an `x-request-id` header. If present, it uses that value.\n\n#### Generate a new ID\nIf neither source provides an ID, the logger generates one with `crypto.randomUUID()` (UUIDv4).\n\n#### Set the response header\nThe logger always sets `X-Request-Id` on the response, so the client (or downstream service) can correlate its own logs to this specific request.\n::\n\n### Log Levels by Status Code\n\nThe HTTP logger assigns a severity level to each request based on the response status code:\n\n| Status Range | Log Level | Meaning |\n|---|---|---|\n| `500+` | `error` | Server error. Something broke. |\n| `400-499` | `warn` | Client error. Bad input, unauthorized, rate limited. |\n| `200-399` | `info` | Success. Normal operation. |\n| `\u002F.well-known\u002F` | `silent` | Suppressed entirely. Health checks and ACME challenges produce no log output. |\n\n::note\nRequests to `\u002F.well-known\u002F` paths are silenced to prevent health check probes from flooding `http.log`. This is controlled by a path check in the `customLogLevel` function.\n::\n\n### Asset Filtering\n\nStatic asset requests are excluded entirely from HTTP logging. The logger checks the request URL against a regex of file extensions and skips the log entry if any match:\n\n`.css`, `.js`, `.png`, `.jpg`, `.jpeg`, `.svg`, `.ico`, `.woff`, `.woff2`, `.ttf`, `.map`, `.webp`, `.json`\n\nThis prevents CDN or browser cache-miss requests for static files from cluttering `http.log` with entries that carry no diagnostic value.\n\n### Custom Properties\n\nEach HTTP log entry includes these additional fields beyond the standard pino-http output:\n\n| Field | Source | Description |\n|---|---|---|\n| `ip` | `req.ip` | Client IP address as seen by Express (respects `trust proxy`) |\n| `userAgent` | `req.headers['user-agent']` | Raw User-Agent header string |\n| `FullUrl` | `req.protocol + ':\u002F\u002F' + req.hostname + req.originalUrl` | Complete URL including protocol, host, and query string |\n| `cookies` | `req.headers.cookie` | Raw cookie header (redacted for `session` via redaction paths) |\n\n### Custom Attribute Keys\n\nThe HTTP logger renames pino-http's default attribute keys to more descriptive names:\n\n| Default Key | Custom Key |\n|---|---|\n| `req` | `httpRequest` |\n| `res` | `httpResponse` |\n| `err` | `httpError` |\n| `responseTime` | `latency` |\n| `reqId` | `requestId` |\n\nA typical `http.log` entry looks like this:\n\n```json\n{\n  \"level\": 30,\n  \"time\": \"2025-01-15T14:30:00.000Z\",\n  \"requestId\": \"a1b2c3d4-e5f6-7890-abcd-ef1234567890\",\n  \"httpRequest\": { \"method\": \"POST\", \"url\": \"\u002Fauth\u002Fuser\u002Frefresh-session\" },\n  \"httpResponse\": { \"statusCode\": 201 },\n  \"latency\": 23,\n  \"ip\": \"192.168.1.1\",\n  \"userAgent\": \"Mozilla\u002F5.0 ...\",\n  \"FullUrl\": \"https:\u002F\u002Fauth.example.com\u002Fauth\u002Fuser\u002Frefresh-session\",\n  \"msg\": \"POST \u002Fauth\u002Fuser\u002Frefresh-session 201 23ms\"\n}\n```\n\n### Custom Messages\n\nThe HTTP logger generates context-aware log messages depending on the response status:\n\n| Condition | Message format |\n|---|---|\n| Status `404` | `\"{method} {url} {status} Referer: {referer} {latency}ms\"` |\n| Status `500+` (with error) | `\"{error.name}: {error.message} {error.stack}\"` |\n| All other statuses | `\"{method} {url} {status} {latency}ms\"` |\n\nThe `404` message includes the `Referer` header to help trace where broken links originate. Error messages include the full stack trace so you can diagnose server errors directly from `http.log` without needing to correlate with `errors.log`.\n\n### Serializers\n\nThe HTTP logger uses pino-http's built-in `req`, `res`, and `err` serializers. These extract a safe subset of request and response data (method, url, headers for requests; statusCode for responses; message, type, stack for errors) while avoiding circular references and excessively large objects.\n\n---\n\n## Accessing Logs\n\n### File System\n\n```bash\n# Real-time application errors\ntail -f auth-logs\u002Ferrors.log\n\n# Real-time HTTP traffic\ntail -f auth-logs\u002Fhttp.log\n\n# Warnings and errors together\ntail -f auth-logs\u002Fwarn.log\n\n# Everything (most verbose)\ntail -f auth-logs\u002Finfo.log\n```\n\n### Docker Compose\n\nWhen the IAM service runs inside Docker, the `auth-logs\u002F` directory is typically mounted as a volume. You can tail logs from the host:\n\n```bash\ndocker compose logs -f auth\n```\n\nOr access the log files directly in the mounted volume:\n\n```bash\ntail -f .\u002Fauth-logs\u002Ferrors.log\n```\n\n### Filtering with jq\n\nSince every log file contains newline-delimited JSON, you can use [jq](https:\u002F\u002Fjqlang.github.io\u002Fjq\u002F) to filter entries:\n\n```bash\n# All MFA-related application logs\ncat auth-logs\u002Finfo.log | jq 'select(.branch == \"mfa\")'\n\n# All HTTP 500 errors with latency > 100ms\ncat auth-logs\u002Fhttp.log | jq 'select(.httpResponse.statusCode >= 500 and .latency > 100)'\n\n# All requests from a specific IP\ncat auth-logs\u002Fhttp.log | jq 'select(.ip == \"203.0.113.42\")'\n\n# Trace a request by ID across both logs\nexport RID=\"a1b2c3d4-e5f6-7890-abcd-ef1234567890\"\ncat auth-logs\u002Fhttp.log | jq \"select(.requestId == \\\"$RID\\\")\"\ncat auth-logs\u002Finfo.log | jq \"select(.requestId == \\\"$RID\\\")\"\n```\n\n---\n\n## Summary\n\n| Aspect | Application Logger | HTTP Logger |\n|---|---|---|\n| Library | Pino 10 | pino-http 10 |\n| Instance | Singleton via `getLogger()` | Express middleware |\n| Log files | `info.log`, `warn.log`, `errors.log` | `http.log` |\n| Redaction paths | 13 (including `*.secret` wildcard) | 2 |\n| Request ID | Not generated (use child logger fields) | Generated per request (`crypto.randomUUID()`) |\n| Timestamps | ISO 8601 | ISO 8601 |\n| Asset filtering | N\u002FA | Excludes 13 static file extensions |\n| Child loggers | Yes, per module\u002Fcontroller | No |\n| Custom fields | `uptime` (mixin) | `ip`, `userAgent`, `FullUrl`, `cookies` |\n",{"title":143,"description":3251},"iGZcoCCl7j5qQ7k3OXMT79wFMfEFQu5GP2rum8g94Ww",[3260,3261],{"title":139,"path":140,"stem":141,"children":-1},{"title":147,"path":148,"stem":149,"children":-1},{"id":851,"title":143,"body":3263,"description":3251,"extension":3252,"icon":3253,"meta":5125,"module":3255,"navigation":8,"path":144,"rawbody":3256,"seo":5126,"stem":145,"__hash__":3258},{"type":853,"value":3264,"toc":5091},[3265,3276,3286,3293,3295,3297,3299,3309,3311,3385,3395,3405,3407,3409,3411,3417,3481,3483,3487,3507,3509,3515,3565,3567,3569,3575,3577,3581,3655,3657,3659,3663,3665,3783,3785,3813,3827,3829,3831,3835,3837,3907,3909,3915,4129,4141,4143,4145,4147,4149,4154,4158,4160,4162,4190,4192,4194,4256,4266,4268,4270,4298,4302,4304,4306,4372,4374,4376,4438,4442,4656,4658,4660,4700,4710,4712,4720,4722,4724,4726,4790,4792,4796,4812,4814,4826,4828,4833,4975,4977,4979,5089],[856,3266,858,3267,866,3270,871,3272,875,3274,880],{},[860,3268,865],{"href":862,"rel":3269},[864],[868,3271,870],{},[868,3273,874],{},[877,3275,879],{},[856,3277,883,3278,887,3280,891,3282,895,3284,899],{},[877,3279,886],{},[868,3281,890],{},[877,3283,894],{},[877,3285,898],{},[856,3287,902,3288,908,3291,912],{},[860,3289,907],{"href":905,"rel":3290},[864],[877,3292,911],{},[914,3294],{},[917,3296,920],{"id":919},[856,3298,923],{},[925,3300,3301,3305],{},[928,3302,930,3303,934],{},[877,3304,933],{},[928,3306,937,3307,941],{},[877,3308,940],{},[856,3310,944],{},[946,3312,3313,3325],{},[949,3314,3315],{},[952,3316,3317,3319,3321,3323],{},[955,3318,957],{},[955,3320,960],{},[955,3322,963],{},[955,3324,966],{},[968,3326,3327,3343,3357,3371],{},[952,3328,3329,3333,3335,3339],{},[973,3330,3331],{},[877,3332,977],{},[973,3334,980],{},[973,3336,3337],{},[877,3338,985],{},[973,3340,988,3341,991],{},[877,3342,985],{},[952,3344,3345,3349,3351,3355],{},[973,3346,3347],{},[877,3348,998],{},[973,3350,980],{},[973,3352,3353],{},[877,3354,1005],{},[973,3356,1008],{},[952,3358,3359,3363,3365,3369],{},[973,3360,3361],{},[877,3362,1015],{},[973,3364,980],{},[973,3366,3367],{},[877,3368,1022],{},[973,3370,1025],{},[952,3372,3373,3377,3379,3383],{},[973,3374,3375],{},[877,3376,1032],{},[973,3378,1035],{},[973,3380,3381],{},[877,3382,985],{},[973,3384,1042],{},[856,3386,1045,3387,1048,3389,1051,3391,1054,3393,1057],{},[877,3388,977],{},[877,3390,998],{},[877,3392,1015],{},[877,3394,1032],{},[1059,3396,3397],{},[856,3398,1063,3399,1066,3401,1069,3403,1072],{},[877,3400,1015],{},[877,3402,1032],{},[877,3404,977],{},[914,3406],{},[917,3408,1078],{"id":1077},[1080,3410,1083],{"id":1082},[856,3412,1086,3413,1089,3415,1093],{},[877,3414,886],{},[877,3416,1092],{},[1095,3418,3419],{"className":1097,"code":1098,"language":1099,"meta":1100,"style":1100},[877,3420,3421,3439,3443,3455],{"__ignoreMap":1100},[1104,3422,3423,3425,3427,3429,3431,3433,3435,3437],{"class":1106,"line":1107},[1104,3424,1111],{"class":1110},[1104,3426,1115],{"class":1114},[1104,3428,1119],{"class":1118},[1104,3430,1122],{"class":1114},[1104,3432,1125],{"class":1110},[1104,3434,1129],{"class":1128},[1104,3436,1133],{"class":1132},[1104,3438,1136],{"class":1128},[1104,3440,3441],{"class":1106,"line":1139},[1104,3442,1142],{"emptyLinePlaceholder":8},[1104,3444,3445,3447,3449,3451,3453],{"class":1106,"line":1145},[1104,3446,1149],{"class":1148},[1104,3448,1153],{"class":1152},[1104,3450,1157],{"class":1156},[1104,3452,1161],{"class":1160},[1104,3454,1164],{"class":1114},[1104,3456,3457,3459,3461,3463,3465,3467,3469,3471,3473,3475,3477,3479],{"class":1106,"line":1167},[1104,3458,1170],{"class":1118},[1104,3460,941],{"class":1114},[1104,3462,985],{"class":1160},[1104,3464,1177],{"class":1114},[1104,3466,1180],{"class":1118},[1104,3468,1184],{"class":1183},[1104,3470,1188],{"class":1187},[1104,3472,1191],{"class":1114},[1104,3474,1194],{"class":1128},[1104,3476,1197],{"class":1132},[1104,3478,1194],{"class":1128},[1104,3480,1202],{"class":1114},[1080,3482,237],{"id":1205},[856,3484,1208,3485,1211],{},[877,3486,1092],{},[1213,3488,3489],{},[1216,3490,3491],{"name":1092,"type":1218},[856,3492,1221,3493,1048,3495,1048,3497,1048,3499,1048,3501,1048,3503,1237,3505,1240],{},[877,3494,1224],{},[877,3496,1227],{},[877,3498,985],{},[877,3500,1005],{},[877,3502,1022],{},[877,3504,1236],{},[877,3506,985],{},[1080,3508,1244],{"id":1243},[856,3510,1247,3511,1251,3513,1255],{},[877,3512,1250],{},[877,3514,1254],{},[946,3516,3517,3527],{},[949,3518,3519],{},[952,3520,3521,3523,3525],{},[955,3522,1264],{},[955,3524,1267],{},[955,3526,1270],{},[968,3528,3529,3541,3553],{},[952,3530,3531,3533,3537],{},[973,3532,1277],{},[973,3534,3535],{},[877,3536,1282],{},[973,3538,3539],{},[877,3540,985],{},[952,3542,3543,3545,3549],{},[973,3544,1291],{},[973,3546,3547],{},[877,3548,1296],{},[973,3550,3551],{},[877,3552,1005],{},[952,3554,3555,3557,3561],{},[973,3556,1305],{},[973,3558,3559],{},[877,3560,1310],{},[973,3562,3563],{},[877,3564,1022],{},[856,3566,1317],{},[1080,3568,1321],{"id":1320},[856,3570,1324,3571,1328,3573,1332],{},[877,3572,1327],{},[877,3574,1331],{},[1080,3576,1336],{"id":1335},[856,3578,1339,3579,1343],{},[877,3580,1342],{},[1095,3582,3583],{"className":1346,"code":1347,"language":5,"meta":1100,"style":1100},[877,3584,3585,3589,3603,3621,3635,3651],{"__ignoreMap":1100},[1104,3586,3587],{"class":1106,"line":1107},[1104,3588,1354],{"class":1114},[1104,3590,3591,3593,3595,3597,3599,3601],{"class":1106,"line":1139},[1104,3592,1360],{"class":1359},[1104,3594,1364],{"class":1363},[1104,3596,1367],{"class":1359},[1104,3598,1184],{"class":1156},[1104,3600,1372],{"class":1187},[1104,3602,1375],{"class":1114},[1104,3604,3605,3607,3609,3611,3613,3615,3617,3619],{"class":1106,"line":1145},[1104,3606,1360],{"class":1359},[1104,3608,1382],{"class":1363},[1104,3610,1367],{"class":1359},[1104,3612,1184],{"class":1156},[1104,3614,1389],{"class":1128},[1104,3616,1392],{"class":1132},[1104,3618,1367],{"class":1128},[1104,3620,1375],{"class":1114},[1104,3622,3623,3625,3627,3629,3631,3633],{"class":1106,"line":1167},[1104,3624,1360],{"class":1359},[1104,3626,1403],{"class":1363},[1104,3628,1367],{"class":1359},[1104,3630,1184],{"class":1156},[1104,3632,1410],{"class":1187},[1104,3634,1375],{"class":1114},[1104,3636,3637,3639,3641,3643,3645,3647,3649],{"class":1106,"line":1415},[1104,3638,1360],{"class":1359},[1104,3640,1420],{"class":1363},[1104,3642,1367],{"class":1359},[1104,3644,1184],{"class":1156},[1104,3646,1389],{"class":1128},[1104,3648,1197],{"class":1132},[1104,3650,1431],{"class":1128},[1104,3652,3653],{"class":1106,"line":1434},[1104,3654,1437],{"class":1114},[914,3656],{},[917,3658,1443],{"id":1442},[856,3660,1446,3661,1450],{},[877,3662,1449],{},[1080,3664,1454],{"id":1453},[946,3666,3667,3675],{},[949,3668,3669],{},[952,3670,3671,3673],{},[955,3672,1463],{},[955,3674,1466],{},[968,3676,3677,3685,3693,3701,3709,3717,3725,3733,3741,3749,3757,3765,3773],{},[952,3678,3679,3683],{},[973,3680,3681],{},[877,3682,1475],{},[973,3684,1478],{},[952,3686,3687,3691],{},[973,3688,3689],{},[877,3690,1485],{},[973,3692,1488],{},[952,3694,3695,3699],{},[973,3696,3697],{},[877,3698,1495],{},[973,3700,1498],{},[952,3702,3703,3707],{},[973,3704,3705],{},[877,3706,1505],{},[973,3708,1508],{},[952,3710,3711,3715],{},[973,3712,3713],{},[877,3714,1515],{},[973,3716,1518],{},[952,3718,3719,3723],{},[973,3720,3721],{},[877,3722,1525],{},[973,3724,1528],{},[952,3726,3727,3731],{},[973,3728,3729],{},[877,3730,1535],{},[973,3732,1538],{},[952,3734,3735,3739],{},[973,3736,3737],{},[877,3738,1545],{},[973,3740,1548],{},[952,3742,3743,3747],{},[973,3744,3745],{},[877,3746,1555],{},[973,3748,1558],{},[952,3750,3751,3755],{},[973,3752,3753],{},[877,3754,1565],{},[973,3756,1568],{},[952,3758,3759,3763],{},[973,3760,3761],{},[877,3762,1575],{},[973,3764,1578],{},[952,3766,3767,3771],{},[973,3768,3769],{},[877,3770,1585],{},[973,3772,1588],{},[952,3774,3775,3779],{},[973,3776,3777],{},[877,3778,1595],{},[973,3780,1598,3781,1602],{},[877,3782,1601],{},[1080,3784,1606],{"id":1605},[946,3786,3787,3795],{},[949,3788,3789],{},[952,3790,3791,3793],{},[955,3792,1463],{},[955,3794,1466],{},[968,3796,3797,3805],{},[952,3798,3799,3803],{},[973,3800,3801],{},[877,3802,1475],{},[973,3804,1478],{},[952,3806,3807,3811],{},[973,3808,3809],{},[877,3810,1633],{},[973,3812,1636],{},[1638,3814,3815],{},[856,3816,1642,3817,1048,3819,1048,3821,1649,3823,1652,3825,1655],{},[877,3818,1575],{},[877,3820,1585],{},[877,3822,1515],{},[877,3824,1601],{},[877,3826,1449],{},[914,3828],{},[917,3830,1661],{"id":1660},[856,3832,1664,3833,1667],{},[868,3834,890],{},[1080,3836,1671],{"id":1670},[1095,3838,3839],{"className":1097,"code":1674,"language":1099,"meta":1100,"style":1100},[877,3840,3841,3881,3885,3903],{"__ignoreMap":1100},[1104,3842,3843,3845,3847,3849,3851,3853,3855,3857,3859,3861,3863,3865,3867,3869,3871,3873,3875,3877,3879],{"class":1106,"line":1107},[1104,3844,1149],{"class":1148},[1104,3846,1153],{"class":1152},[1104,3848,1157],{"class":1156},[1104,3850,1161],{"class":1160},[1104,3852,1689],{"class":1114},[1104,3854,1692],{"class":1160},[1104,3856,1177],{"class":1114},[1104,3858,894],{"class":1118},[1104,3860,1184],{"class":1183},[1104,3862,1129],{"class":1128},[1104,3864,1703],{"class":1132},[1104,3866,1194],{"class":1128},[1104,3868,1048],{"class":1114},[1104,3870,898],{"class":1118},[1104,3872,1184],{"class":1183},[1104,3874,1129],{"class":1128},[1104,3876,1716],{"class":1132},[1104,3878,1194],{"class":1128},[1104,3880,1721],{"class":1114},[1104,3882,3883],{"class":1106,"line":1139},[1104,3884,1142],{"emptyLinePlaceholder":8},[1104,3886,3887,3889,3891,3893,3895,3897,3899,3901],{"class":1106,"line":1145},[1104,3888,1170],{"class":1118},[1104,3890,941],{"class":1114},[1104,3892,985],{"class":1160},[1104,3894,1736],{"class":1114},[1104,3896,1194],{"class":1128},[1104,3898,1741],{"class":1132},[1104,3900,1194],{"class":1128},[1104,3902,1202],{"class":1114},[1104,3904,3905],{"class":1106,"line":1167},[1104,3906,1751],{"class":1750},[1080,3908,1755],{"id":1754},[856,3910,1208,3911,1760,3913,1763],{},[877,3912,894],{},[877,3914,898],{},[946,3916,3917,3929],{},[949,3918,3919],{},[952,3920,3921,3923,3925,3927],{},[955,3922,894],{},[955,3924,898],{},[955,3926,1776],{},[955,3928,1779],{},[968,3930,3931,3945,3959,3977,3993,4009,4027,4041,4055,4069,4083,4099,4115],{},[952,3932,3933,3937,3941,3943],{},[973,3934,3935],{},[877,3936,1703],{},[973,3938,3939],{},[877,3940,1716],{},[973,3942],{},[973,3944,1796],{},[952,3946,3947,3951,3955,3957],{},[973,3948,3949],{},[877,3950,1703],{},[973,3952,3953],{},[877,3954,1807],{},[973,3956],{},[973,3958,1812],{},[952,3960,3961,3965,3969,3975],{},[973,3962,3963],{},[877,3964,1703],{},[973,3966,3967],{},[877,3968,1823],{},[973,3970,3971,1829,3973],{},[877,3972,1828],{},[877,3974,1832],{},[973,3976,1835],{},[952,3978,3979,3983,3987,3991],{},[973,3980,3981],{},[877,3982,1703],{},[973,3984,3985],{},[877,3986,1846],{},[973,3988,3989],{},[877,3990,1851],{},[973,3992,1854],{},[952,3994,3995,3999,4003,4007],{},[973,3996,3997],{},[877,3998,1703],{},[973,4000,4001],{},[877,4002,1865],{},[973,4004,4005],{},[877,4006,1870],{},[973,4008,1873],{},[952,4010,4011,4015,4019,4025],{},[973,4012,4013],{},[877,4014,1703],{},[973,4016,4017],{},[877,4018,1884],{},[973,4020,4021,1048,4023],{},[877,4022,1889],{},[877,4024,1892],{},[973,4026,1895],{},[952,4028,4029,4033,4037,4039],{},[973,4030,4031],{},[877,4032,1703],{},[973,4034,4035],{},[877,4036,1906],{},[973,4038],{},[973,4040,1911],{},[952,4042,4043,4047,4051,4053],{},[973,4044,4045],{},[877,4046,1703],{},[973,4048,4049],{},[877,4050,1922],{},[973,4052],{},[973,4054,1927],{},[952,4056,4057,4061,4065,4067],{},[973,4058,4059],{},[877,4060,1703],{},[973,4062,4063],{},[877,4064,1938],{},[973,4066],{},[973,4068,1943],{},[952,4070,4071,4075,4079,4081],{},[973,4072,4073],{},[877,4074,1703],{},[973,4076,4077],{},[877,4078,1954],{},[973,4080],{},[973,4082,1959],{},[952,4084,4085,4089,4093,4097],{},[973,4086,4087],{},[877,4088,1703],{},[973,4090,4091],{},[877,4092,1970],{},[973,4094,4095],{},[877,4096,1975],{},[973,4098,1978],{},[952,4100,4101,4105,4109,4113],{},[973,4102,4103],{},[877,4104,1703],{},[973,4106,4107],{},[877,4108,1989],{},[973,4110,4111],{},[877,4112,1994],{},[973,4114,1997],{},[952,4116,4117,4121,4123,4127],{},[973,4118,4119],{},[877,4120,2004],{},[973,4122],{},[973,4124,4125],{},[877,4126,2011],{},[973,4128,2014],{},[1059,4130,4131],{},[856,4132,2019,4133,2022,4135,2025,4137,895,4139,2031],{},[877,4134,1032],{},[877,4136,977],{},[877,4138,2028],{},[877,4140,1870],{},[914,4142],{},[917,4144,2037],{"id":2036},[856,4146,2040],{},[1080,4148,2044],{"id":2043},[1095,4150,4152],{"className":4151,"code":2049,"language":2050},[2048],[877,4153,2049],{"__ignoreMap":1100},[856,4155,2055,4156,2059],{},[877,4157,2058],{},[1080,4159,2063],{"id":2062},[856,4161,2066],{},[2068,4163,4164,4166,4170,4172,4178,4180,4184,4186],{"level":2070},[2072,4165,2075],{"id":2074},[856,4167,2078,4168,2082],{},[877,4169,2081],{},[2072,4171,2086],{"id":2085},[856,4173,2078,4174,2091,4176,2095],{},[877,4175,2081],{},[877,4177,2094],{},[2072,4179,2099],{"id":2098},[856,4181,2102,4182,2106],{},[877,4183,2105],{},[2072,4185,2110],{"id":2109},[856,4187,2113,4188,2116],{},[877,4189,911],{},[1080,4191,2120],{"id":2119},[856,4193,2123],{},[946,4195,4196,4206],{},[949,4197,4198],{},[952,4199,4200,4202,4204],{},[955,4201,2132],{},[955,4203,2135],{},[955,4205,2138],{},[968,4207,4208,4220,4232,4244],{},[952,4209,4210,4214,4218],{},[973,4211,4212],{},[877,4213,2147],{},[973,4215,4216],{},[877,4217,1022],{},[973,4219,2154],{},[952,4221,4222,4226,4230],{},[973,4223,4224],{},[877,4225,2161],{},[973,4227,4228],{},[877,4229,1005],{},[973,4231,2168],{},[952,4233,4234,4238,4242],{},[973,4235,4236],{},[877,4237,2175],{},[973,4239,4240],{},[877,4241,985],{},[973,4243,2182],{},[952,4245,4246,4250,4254],{},[973,4247,4248],{},[877,4249,2189],{},[973,4251,4252],{},[877,4253,2194],{},[973,4255,2197],{},[2199,4257,4258],{},[856,4259,2203,4260,2206,4262,2209,4264,2213],{},[877,4261,2189],{},[877,4263,1032],{},[877,4265,2212],{},[1080,4267,2217],{"id":2216},[856,4269,2220],{},[856,4271,4272,1048,4274,1048,4276,1048,4278,1048,4280,1048,4282,1048,4284,1048,4286,1048,4288,1048,4290,1048,4292,1048,4294,1048,4296],{},[877,4273,2225],{},[877,4275,2228],{},[877,4277,2231],{},[877,4279,2234],{},[877,4281,2237],{},[877,4283,2240],{},[877,4285,2243],{},[877,4287,2246],{},[877,4289,2249],{},[877,4291,2252],{},[877,4293,2255],{},[877,4295,2258],{},[877,4297,2261],{},[856,4299,2264,4300,2267],{},[877,4301,1032],{},[1080,4303,2271],{"id":2270},[856,4305,2274],{},[946,4307,4308,4318],{},[949,4309,4310],{},[952,4311,4312,4314,4316],{},[955,4313,2283],{},[955,4315,2286],{},[955,4317,2289],{},[968,4319,4320,4334,4346,4358],{},[952,4321,4322,4326,4330],{},[973,4323,4324],{},[877,4325,1892],{},[973,4327,4328],{},[877,4329,2302],{},[973,4331,2305,4332,2309],{},[877,4333,2308],{},[952,4335,4336,4340,4344],{},[973,4337,4338],{},[877,4339,2316],{},[973,4341,4342],{},[877,4343,2321],{},[973,4345,2324],{},[952,4347,4348,4352,4356],{},[973,4349,4350],{},[877,4351,2331],{},[973,4353,4354],{},[877,4355,2336],{},[973,4357,2339],{},[952,4359,4360,4364,4368],{},[973,4361,4362],{},[877,4363,1525],{},[973,4365,4366],{},[877,4367,2350],{},[973,4369,2353,4370,2357],{},[877,4371,2356],{},[1080,4373,2361],{"id":2360},[856,4375,2364],{},[946,4377,4378,4386],{},[949,4379,4380],{},[952,4381,4382,4384],{},[955,4383,2373],{},[955,4385,2376],{},[968,4387,4388,4398,4408,4418,4428],{},[952,4389,4390,4394],{},[973,4391,4392],{},[877,4393,2385],{},[973,4395,4396],{},[877,4397,2390],{},[952,4399,4400,4404],{},[973,4401,4402],{},[877,4403,2397],{},[973,4405,4406],{},[877,4407,2402],{},[952,4409,4410,4414],{},[973,4411,4412],{},[877,4413,2409],{},[973,4415,4416],{},[877,4417,2414],{},[952,4419,4420,4424],{},[973,4421,4422],{},[877,4423,2421],{},[973,4425,4426],{},[877,4427,2426],{},[952,4429,4430,4434],{},[973,4431,4432],{},[877,4433,2433],{},[973,4435,4436],{},[877,4437,2438],{},[856,4439,2441,4440,2444],{},[877,4441,1032],{},[1095,4443,4444],{"className":1346,"code":2447,"language":5,"meta":1100,"style":1100},[877,4445,4446,4450,4464,4482,4500,4544,4568,4582,4600,4618,4636,4652],{"__ignoreMap":1100},[1104,4447,4448],{"class":1106,"line":1107},[1104,4449,1354],{"class":1114},[1104,4451,4452,4454,4456,4458,4460,4462],{"class":1106,"line":1139},[1104,4453,1360],{"class":1359},[1104,4455,1364],{"class":1363},[1104,4457,1367],{"class":1359},[1104,4459,1184],{"class":1156},[1104,4461,1372],{"class":1187},[1104,4463,1375],{"class":1114},[1104,4465,4466,4468,4470,4472,4474,4476,4478,4480],{"class":1106,"line":1145},[1104,4467,1360],{"class":1359},[1104,4469,1382],{"class":1363},[1104,4471,1367],{"class":1359},[1104,4473,1184],{"class":1156},[1104,4475,1389],{"class":1128},[1104,4477,1392],{"class":1132},[1104,4479,1367],{"class":1128},[1104,4481,1375],{"class":1114},[1104,4483,4484,4486,4488,4490,4492,4494,4496,4498],{"class":1106,"line":1167},[1104,4485,1360],{"class":1359},[1104,4487,2438],{"class":1363},[1104,4489,1367],{"class":1359},[1104,4491,1184],{"class":1156},[1104,4493,1389],{"class":1128},[1104,4495,2500],{"class":1132},[1104,4497,1367],{"class":1128},[1104,4499,1375],{"class":1114},[1104,4501,4502,4504,4506,4508,4510,4512,4514,4516,4518,4520,4522,4524,4526,4528,4530,4532,4534,4536,4538,4540,4542],{"class":1106,"line":1415},[1104,4503,1360],{"class":1359},[1104,4505,2390],{"class":1363},[1104,4507,1367],{"class":1359},[1104,4509,1184],{"class":1156},[1104,4511,1115],{"class":1114},[1104,4513,1367],{"class":1359},[1104,4515,2521],{"class":1363},[1104,4517,1367],{"class":1359},[1104,4519,1184],{"class":1156},[1104,4521,1389],{"class":1128},[1104,4523,2530],{"class":1132},[1104,4525,1367],{"class":1128},[1104,4527,1048],{"class":1114},[1104,4529,1367],{"class":1359},[1104,4531,2539],{"class":1363},[1104,4533,1367],{"class":1359},[1104,4535,1184],{"class":1156},[1104,4537,1389],{"class":1128},[1104,4539,2548],{"class":1132},[1104,4541,1367],{"class":1128},[1104,4543,2553],{"class":1114},[1104,4545,4546,4548,4550,4552,4554,4556,4558,4560,4562,4564,4566],{"class":1106,"line":1434},[1104,4547,1360],{"class":1359},[1104,4549,2402],{"class":1363},[1104,4551,1367],{"class":1359},[1104,4553,1184],{"class":1156},[1104,4555,1115],{"class":1114},[1104,4557,1367],{"class":1359},[1104,4559,2570],{"class":1363},[1104,4561,1367],{"class":1359},[1104,4563,1184],{"class":1156},[1104,4565,2577],{"class":1187},[1104,4567,2553],{"class":1114},[1104,4569,4570,4572,4574,4576,4578,4580],{"class":1106,"line":2582},[1104,4571,1360],{"class":1359},[1104,4573,2426],{"class":1363},[1104,4575,1367],{"class":1359},[1104,4577,1184],{"class":1156},[1104,4579,2593],{"class":1187},[1104,4581,1375],{"class":1114},[1104,4583,4584,4586,4588,4590,4592,4594,4596,4598],{"class":1106,"line":2598},[1104,4585,1360],{"class":1359},[1104,4587,1892],{"class":1363},[1104,4589,1367],{"class":1359},[1104,4591,1184],{"class":1156},[1104,4593,1389],{"class":1128},[1104,4595,2611],{"class":1132},[1104,4597,1367],{"class":1128},[1104,4599,1375],{"class":1114},[1104,4601,4602,4604,4606,4608,4610,4612,4614,4616],{"class":1106,"line":2618},[1104,4603,1360],{"class":1359},[1104,4605,2316],{"class":1363},[1104,4607,1367],{"class":1359},[1104,4609,1184],{"class":1156},[1104,4611,1389],{"class":1128},[1104,4613,2631],{"class":1132},[1104,4615,1367],{"class":1128},[1104,4617,1375],{"class":1114},[1104,4619,4620,4622,4624,4626,4628,4630,4632,4634],{"class":1106,"line":2638},[1104,4621,1360],{"class":1359},[1104,4623,2331],{"class":1363},[1104,4625,1367],{"class":1359},[1104,4627,1184],{"class":1156},[1104,4629,1389],{"class":1128},[1104,4631,2651],{"class":1132},[1104,4633,1367],{"class":1128},[1104,4635,1375],{"class":1114},[1104,4637,4638,4640,4642,4644,4646,4648,4650],{"class":1106,"line":2658},[1104,4639,1360],{"class":1359},[1104,4641,1420],{"class":1363},[1104,4643,1367],{"class":1359},[1104,4645,1184],{"class":1156},[1104,4647,1389],{"class":1128},[1104,4649,2671],{"class":1132},[1104,4651,1431],{"class":1128},[1104,4653,4654],{"class":1106,"line":2676},[1104,4655,1437],{"class":1114},[1080,4657,2682],{"id":2681},[856,4659,2685],{},[946,4661,4662,4670],{},[949,4663,4664],{},[952,4665,4666,4668],{},[955,4667,2694],{},[955,4669,2697],{},[968,4671,4672,4682,4692],{},[952,4673,4674,4678],{},[973,4675,2704,4676],{},[877,4677,2707],{},[973,4679,4680],{},[877,4681,2712],{},[952,4683,4684,4688],{},[973,4685,2704,4686,2719],{},[877,4687,2147],{},[973,4689,4690],{},[877,4691,2724],{},[952,4693,4694,4696],{},[973,4695,2729],{},[973,4697,4698],{},[877,4699,2734],{},[856,4701,1208,4702,2739,4704,2743,4706,2746,4708,941],{},[877,4703,2707],{},[877,4705,2742],{},[877,4707,1032],{},[877,4709,1015],{},[1080,4711,2752],{"id":2751},[856,4713,2755,4714,1048,4716,1051,4718,2762],{},[877,4715,2385],{},[877,4717,2397],{},[877,4719,2409],{},[914,4721],{},[917,4723,2768],{"id":2767},[1080,4725,2772],{"id":2771},[1095,4727,4728],{"className":2775,"code":2776,"language":2777,"meta":1100,"style":1100},[877,4729,4730,4734,4742,4746,4750,4758,4762,4766,4774,4778,4782],{"__ignoreMap":1100},[1104,4731,4732],{"class":1106,"line":1107},[1104,4733,2784],{"class":1750},[1104,4735,4736,4738,4740],{"class":1106,"line":1139},[1104,4737,2789],{"class":1160},[1104,4739,2793],{"class":2792},[1104,4741,2796],{"class":1132},[1104,4743,4744],{"class":1106,"line":1145},[1104,4745,1142],{"emptyLinePlaceholder":8},[1104,4747,4748],{"class":1106,"line":1167},[1104,4749,2805],{"class":1750},[1104,4751,4752,4754,4756],{"class":1106,"line":1415},[1104,4753,2789],{"class":1160},[1104,4755,2793],{"class":2792},[1104,4757,2814],{"class":1132},[1104,4759,4760],{"class":1106,"line":1434},[1104,4761,1142],{"emptyLinePlaceholder":8},[1104,4763,4764],{"class":1106,"line":2582},[1104,4765,2823],{"class":1750},[1104,4767,4768,4770,4772],{"class":1106,"line":2598},[1104,4769,2789],{"class":1160},[1104,4771,2793],{"class":2792},[1104,4773,2832],{"class":1132},[1104,4775,4776],{"class":1106,"line":2618},[1104,4777,1142],{"emptyLinePlaceholder":8},[1104,4779,4780],{"class":1106,"line":2638},[1104,4781,2841],{"class":1750},[1104,4783,4784,4786,4788],{"class":1106,"line":2658},[1104,4785,2789],{"class":1160},[1104,4787,2793],{"class":2792},[1104,4789,2850],{"class":1132},[1080,4791,2854],{"id":2853},[856,4793,2857,4794,2860],{},[877,4795,879],{},[1095,4797,4798],{"className":2775,"code":2863,"language":2777,"meta":1100,"style":1100},[877,4799,4800],{"__ignoreMap":1100},[1104,4801,4802,4804,4806,4808,4810],{"class":1106,"line":1107},[1104,4803,2870],{"class":1160},[1104,4805,2873],{"class":1132},[1104,4807,2876],{"class":1132},[1104,4809,2793],{"class":2792},[1104,4811,2881],{"class":1132},[856,4813,2884],{},[1095,4815,4816],{"className":2775,"code":2887,"language":2777,"meta":1100,"style":1100},[877,4817,4818],{"__ignoreMap":1100},[1104,4819,4820,4822,4824],{"class":1106,"line":1107},[1104,4821,2789],{"class":1160},[1104,4823,2793],{"class":2792},[1104,4825,2898],{"class":1132},[1080,4827,2902],{"id":2901},[856,4829,2905,4830,2911],{},[860,4831,2910],{"href":2908,"rel":4832},[864],[1095,4834,4835],{"className":2775,"code":2914,"language":2777,"meta":1100,"style":1100},[877,4836,4837,4841,4857,4861,4865,4881,4885,4889,4905,4909,4913,4927,4951],{"__ignoreMap":1100},[1104,4838,4839],{"class":1106,"line":1107},[1104,4840,2921],{"class":1750},[1104,4842,4843,4845,4847,4849,4851,4853,4855],{"class":1106,"line":1139},[1104,4844,2926],{"class":1160},[1104,4846,2929],{"class":1132},[1104,4848,2932],{"class":1156},[1104,4850,2935],{"class":1160},[1104,4852,1129],{"class":1128},[1104,4854,2940],{"class":1132},[1104,4856,1136],{"class":1128},[1104,4858,4859],{"class":1106,"line":1145},[1104,4860,1142],{"emptyLinePlaceholder":8},[1104,4862,4863],{"class":1106,"line":1167},[1104,4864,2951],{"class":1750},[1104,4866,4867,4869,4871,4873,4875,4877,4879],{"class":1106,"line":1415},[1104,4868,2926],{"class":1160},[1104,4870,2958],{"class":1132},[1104,4872,2932],{"class":1156},[1104,4874,2935],{"class":1160},[1104,4876,1129],{"class":1128},[1104,4878,2967],{"class":1132},[1104,4880,1136],{"class":1128},[1104,4882,4883],{"class":1106,"line":1434},[1104,4884,1142],{"emptyLinePlaceholder":8},[1104,4886,4887],{"class":1106,"line":2582},[1104,4888,2978],{"class":1750},[1104,4890,4891,4893,4895,4897,4899,4901,4903],{"class":1106,"line":2598},[1104,4892,2926],{"class":1160},[1104,4894,2958],{"class":1132},[1104,4896,2932],{"class":1156},[1104,4898,2935],{"class":1160},[1104,4900,1129],{"class":1128},[1104,4902,2993],{"class":1132},[1104,4904,1136],{"class":1128},[1104,4906,4907],{"class":1106,"line":2618},[1104,4908,1142],{"emptyLinePlaceholder":8},[1104,4910,4911],{"class":1106,"line":2638},[1104,4912,3004],{"class":1750},[1104,4914,4915,4917,4919,4921,4923,4925],{"class":1106,"line":2658},[1104,4916,3009],{"class":1148},[1104,4918,3013],{"class":3012},[1104,4920,3016],{"class":1156},[1104,4922,1367],{"class":1128},[1104,4924,2500],{"class":1132},[1104,4926,1431],{"class":1128},[1104,4928,4929,4931,4933,4935,4937,4939,4941,4943,4945,4947,4949],{"class":1106,"line":2676},[1104,4930,2926],{"class":1160},[1104,4932,2958],{"class":1132},[1104,4934,2932],{"class":1156},[1104,4936,2935],{"class":1160},[1104,4938,1389],{"class":1128},[1104,4940,3037],{"class":1132},[1104,4942,3041],{"class":3040},[1104,4944,3044],{"class":3012},[1104,4946,3041],{"class":3040},[1104,4948,2309],{"class":1132},[1104,4950,1431],{"class":1128},[1104,4952,4953,4955,4957,4959,4961,4963,4965,4967,4969,4971,4973],{"class":1106,"line":3053},[1104,4954,2926],{"class":1160},[1104,4956,2929],{"class":1132},[1104,4958,2932],{"class":1156},[1104,4960,2935],{"class":1160},[1104,4962,1389],{"class":1128},[1104,4964,3037],{"class":1132},[1104,4966,3041],{"class":3040},[1104,4968,3044],{"class":3012},[1104,4970,3041],{"class":3040},[1104,4972,2309],{"class":1132},[1104,4974,1431],{"class":1128},[914,4976],{},[917,4978,3081],{"id":3080},[946,4980,4981,4991],{},[949,4982,4983],{},[952,4984,4985,4987,4989],{},[955,4986,3090],{},[955,4988,1078],{},[955,4990,2037],{},[968,4992,4993,5001,5011,5027,5037,5047,5055,5063,5071],{},[952,4994,4995,4997,4999],{},[973,4996,51],{},[973,4998,3103],{},[973,5000,3106],{},[952,5002,5003,5005,5009],{},[973,5004,3111],{},[973,5006,3114,5007],{},[877,5008,886],{},[973,5010,3119],{},[952,5012,5013,5015,5023],{},[973,5014,3124],{},[973,5016,5017,1048,5019,1048,5021],{},[877,5018,977],{},[877,5020,998],{},[877,5022,1015],{},[973,5024,5025],{},[877,5026,1032],{},[952,5028,5029,5031,5035],{},[973,5030,3141],{},[973,5032,3144,5033,3147],{},[877,5034,1595],{},[973,5036,1291],{},[952,5038,5039,5041,5043],{},[973,5040,2063],{},[973,5042,3156],{},[973,5044,3159,5045,2309],{},[877,5046,2105],{},[952,5048,5049,5051,5053],{},[973,5050,1321],{},[973,5052,3168],{},[973,5054,3168],{},[952,5056,5057,5059,5061],{},[973,5058,3175],{},[973,5060,3178],{},[973,5062,3181],{},[952,5064,5065,5067,5069],{},[973,5066,3186],{},[973,5068,3189],{},[973,5070,3192],{},[952,5072,5073,5075,5079],{},[973,5074,3197],{},[973,5076,5077,3202],{},[877,5078,1403],{},[973,5080,5081,1048,5083,1048,5085,1048,5087],{},[877,5082,1892],{},[877,5084,2316],{},[877,5086,2331],{},[877,5088,1525],{},[3214,5090,3216],{},{"title":1100,"searchDepth":1139,"depth":1139,"links":5092},[5093,5094,5101,5105,5109,5119,5124],{"id":919,"depth":1139,"text":920},{"id":1077,"depth":1139,"text":1078,"children":5095},[5096,5097,5098,5099,5100],{"id":1082,"depth":1145,"text":1083},{"id":1205,"depth":1145,"text":237},{"id":1243,"depth":1145,"text":1244},{"id":1320,"depth":1145,"text":1321},{"id":1335,"depth":1145,"text":1336},{"id":1442,"depth":1139,"text":1443,"children":5102},[5103,5104],{"id":1453,"depth":1145,"text":1454},{"id":1605,"depth":1145,"text":1606},{"id":1660,"depth":1139,"text":1661,"children":5106},[5107,5108],{"id":1670,"depth":1145,"text":1671},{"id":1754,"depth":1145,"text":1755},{"id":2036,"depth":1139,"text":2037,"children":5110},[5111,5112,5113,5114,5115,5116,5117,5118],{"id":2043,"depth":1145,"text":2044},{"id":2062,"depth":1145,"text":2063},{"id":2119,"depth":1145,"text":2120},{"id":2216,"depth":1145,"text":2217},{"id":2270,"depth":1145,"text":2271},{"id":2360,"depth":1145,"text":2361},{"id":2681,"depth":1145,"text":2682},{"id":2751,"depth":1145,"text":2752},{"id":2767,"depth":1139,"text":2768,"children":5120},[5121,5122,5123],{"id":2771,"depth":1145,"text":2772},{"id":2853,"depth":1145,"text":2854},{"id":2901,"depth":1145,"text":2902},{"id":3080,"depth":1139,"text":3081},{},{"title":143,"description":3251},1780436283109]