[{"data":1,"prerenderedAt":1317},["ShallowReactive",2],{"navigation_docs":3,"-logging-audit-pipeline":429,"-logging-audit-pipeline-surround":1312},[4,35,159,201,289,326,413],{"title":5,"path":6,"stem":7,"children":8,"page":34},"Getting Started","\u002Fgetting-started","1.getting-started",[9,14,19,24,29],{"title":10,"path":11,"stem":12,"icon":13},"Introduction","\u002Fgetting-started\u002Fintroduction","1.getting-started\u002F1.introduction","i-lucide-info",{"title":15,"path":16,"stem":17,"icon":18},"Installation","\u002Fgetting-started\u002Finstallation","1.getting-started\u002F2.installation","i-lucide-download",{"title":20,"path":21,"stem":22,"icon":23},"Quick Start","\u002Fgetting-started\u002Fquick-start","1.getting-started\u002F3.quick-start","i-lucide-zap",{"title":25,"path":26,"stem":27,"icon":28},"Agent Skills","\u002Fgetting-started\u002Fagent-skills","1.getting-started\u002F4.agent-skills","i-lucide-sparkles",{"title":30,"path":31,"stem":32,"icon":33},"vs Other Loggers","\u002Fgetting-started\u002Fvs-other-loggers","1.getting-started\u002F5.vs-other-loggers","i-lucide-scale",false,{"title":36,"path":37,"stem":38,"children":39,"page":34},"Logging","\u002Flogging","2.logging",[40,45,50,55,60,65,70,99,127],{"title":41,"path":42,"stem":43,"icon":44},"Overview","\u002Flogging\u002Foverview","2.logging\u002F0.overview","i-lucide-list",{"title":46,"path":47,"stem":48,"icon":49},"Simple Logging","\u002Flogging\u002Fsimple-logging","2.logging\u002F1.simple-logging","i-lucide-terminal",{"title":51,"path":52,"stem":53,"icon":54},"Wide Events","\u002Flogging\u002Fwide-events","2.logging\u002F2.wide-events","i-lucide-layers",{"title":56,"path":57,"stem":58,"icon":59},"Structured Errors","\u002Flogging\u002Fstructured-errors","2.logging\u002F3.structured-errors","i-lucide-shield-alert",{"title":61,"path":62,"stem":63,"icon":64},"Catalogs","\u002Flogging\u002Fcatalogs","2.logging\u002F4.catalogs","i-lucide-book-open",{"title":66,"path":67,"stem":68,"icon":69},"Client Logging","\u002Flogging\u002Fclient-logging","2.logging\u002F5.client-logging","i-lucide-monitor",{"title":71,"icon":72,"path":73,"stem":74,"children":75,"page":34},"AI SDK","i-simple-icons-vercel","\u002Flogging\u002Fai-sdk","2.logging\u002F6.ai-sdk",[76,79,84,89,94],{"title":41,"path":77,"stem":78,"icon":44},"\u002Flogging\u002Fai-sdk\u002Foverview","2.logging\u002F6.ai-sdk\u002F01.overview",{"title":80,"path":81,"stem":82,"icon":83},"Usage","\u002Flogging\u002Fai-sdk\u002Fusage","2.logging\u002F6.ai-sdk\u002F02.usage","i-lucide-code",{"title":85,"path":86,"stem":87,"icon":88},"Options","\u002Flogging\u002Fai-sdk\u002Foptions","2.logging\u002F6.ai-sdk\u002F03.options","i-lucide-sliders",{"title":90,"path":91,"stem":92,"icon":93},"Metadata","\u002Flogging\u002Fai-sdk\u002Fmetadata","2.logging\u002F6.ai-sdk\u002F04.metadata","i-lucide-database",{"title":95,"path":96,"stem":97,"icon":98},"Telemetry","\u002Flogging\u002Fai-sdk\u002Ftelemetry","2.logging\u002F6.ai-sdk\u002F05.telemetry","i-lucide-activity",{"title":100,"icon":101,"path":102,"stem":103,"children":104,"page":34},"Better Auth","i-simple-icons-betterauth","\u002Flogging\u002Fbetter-auth","2.logging\u002F7.better-auth",[105,108,113,118,122],{"title":41,"path":106,"stem":107,"icon":44},"\u002Flogging\u002Fbetter-auth\u002Foverview","2.logging\u002F7.better-auth\u002F01.overview",{"title":109,"path":110,"stem":111,"icon":112},"Identify User","\u002Flogging\u002Fbetter-auth\u002Fidentify-user","2.logging\u002F7.better-auth\u002F02.identify-user","i-lucide-user-check",{"title":114,"path":115,"stem":116,"icon":117},"Middleware","\u002Flogging\u002Fbetter-auth\u002Fmiddleware","2.logging\u002F7.better-auth\u002F03.middleware","i-lucide-shield",{"title":119,"path":120,"stem":121,"icon":69},"Client Sync","\u002Flogging\u002Fbetter-auth\u002Fclient-sync","2.logging\u002F7.better-auth\u002F04.client-sync",{"title":123,"path":124,"stem":125,"icon":126},"Performance","\u002Flogging\u002Fbetter-auth\u002Fperformance","2.logging\u002F7.better-auth\u002F05.performance","i-lucide-gauge",{"title":128,"icon":129,"path":130,"stem":131,"children":132,"page":34},"Audit Logs","i-lucide-shield-check","\u002Flogging\u002Faudit","2.logging\u002F8.audit",[133,136,141,146,151,155],{"title":41,"path":134,"stem":135,"icon":44},"\u002Flogging\u002Faudit\u002Foverview","2.logging\u002F8.audit\u002F01.overview",{"title":137,"path":138,"stem":139,"icon":140},"Schema","\u002Flogging\u002Faudit\u002Fschema","2.logging\u002F8.audit\u002F02.schema","i-lucide-file-text",{"title":142,"path":143,"stem":144,"icon":145},"Recording","\u002Flogging\u002Faudit\u002Frecording","2.logging\u002F8.audit\u002F03.recording","i-lucide-pen-line",{"title":147,"path":148,"stem":149,"icon":150},"Drains","\u002Flogging\u002Faudit\u002Fpipeline","2.logging\u002F8.audit\u002F04.pipeline","i-lucide-link",{"title":152,"path":153,"stem":154,"icon":129},"Compliance","\u002Flogging\u002Faudit\u002Fcompliance","2.logging\u002F8.audit\u002F05.compliance",{"title":156,"path":157,"stem":158,"icon":64},"Recipes","\u002Flogging\u002Faudit\u002Frecipes","2.logging\u002F8.audit\u002F06.recipes",{"title":160,"path":161,"stem":162,"children":163,"page":34},"Core Concepts","\u002Fcore-concepts","3.core-concepts",[164,169,174,179,184,188,191,196],{"title":165,"path":166,"stem":167,"icon":168},"Lifecycle","\u002Fcore-concepts\u002Flifecycle","3.core-concepts\u002F0.lifecycle","i-lucide-arrow-right-left",{"title":170,"path":171,"stem":172,"icon":173},"Configuration","\u002Fcore-concepts\u002Fconfiguration","3.core-concepts\u002F1.configuration","i-lucide-settings",{"title":175,"path":176,"stem":177,"icon":178},"Sampling","\u002Fcore-concepts\u002Fsampling","3.core-concepts\u002F2.sampling","i-lucide-filter",{"title":180,"path":181,"stem":182,"icon":183},"Typed Fields","\u002Fcore-concepts\u002Ftyped-fields","3.core-concepts\u002F3.typed-fields","i-simple-icons-typescript",{"title":185,"path":186,"stem":187,"icon":129},"Best Practices","\u002Fcore-concepts\u002Fbest-practices","3.core-concepts\u002F4.best-practices",{"title":123,"path":189,"stem":190,"icon":126},"\u002Fcore-concepts\u002Fperformance","3.core-concepts\u002F5.performance",{"title":192,"path":193,"stem":194,"icon":195},"Vite Plugin","\u002Fcore-concepts\u002Fvite-plugin","3.core-concepts\u002F6.vite-plugin","i-custom-vite",{"title":197,"path":198,"stem":199,"icon":200},"Auto-Redaction","\u002Fcore-concepts\u002Fredaction","3.core-concepts\u002F7.redaction","i-lucide-eye-off",{"title":202,"path":203,"stem":204,"children":205,"page":34},"Frameworks","\u002Fframeworks","4.frameworks",[206,210,215,220,225,230,235,240,245,250,255,260,265,270,274,279,284],{"title":41,"path":207,"stem":208,"icon":209},"\u002Fframeworks\u002Foverview","4.frameworks\u002F00.overview","i-lucide-layout-grid",{"title":211,"path":212,"stem":213,"icon":214},"Nuxt","\u002Fframeworks\u002Fnuxt","4.frameworks\u002F01.nuxt","i-simple-icons-nuxtdotjs",{"title":216,"path":217,"stem":218,"icon":219},"Next.js","\u002Fframeworks\u002Fnextjs","4.frameworks\u002F02.nextjs","i-simple-icons-nextdotjs",{"title":221,"path":222,"stem":223,"icon":224},"SvelteKit","\u002Fframeworks\u002Fsveltekit","4.frameworks\u002F03.sveltekit","i-simple-icons-svelte",{"title":226,"path":227,"stem":228,"icon":229},"Nitro","\u002Fframeworks\u002Fnitro","4.frameworks\u002F04.nitro","i-custom-nitro",{"title":231,"path":232,"stem":233,"icon":234},"TanStack Start","\u002Fframeworks\u002Ftanstack-start","4.frameworks\u002F05.tanstack-start","i-custom-tanstack",{"title":236,"path":237,"stem":238,"icon":239},"NestJS","\u002Fframeworks\u002Fnestjs","4.frameworks\u002F06.nestjs","i-simple-icons-nestjs",{"title":241,"path":242,"stem":243,"icon":244},"Express","\u002Fframeworks\u002Fexpress","4.frameworks\u002F07.express","i-simple-icons-express",{"title":246,"path":247,"stem":248,"icon":249},"Hono","\u002Fframeworks\u002Fhono","4.frameworks\u002F08.hono","i-simple-icons-hono",{"title":251,"path":252,"stem":253,"icon":254},"Fastify","\u002Fframeworks\u002Ffastify","4.frameworks\u002F09.fastify","i-simple-icons-fastify",{"title":256,"path":257,"stem":258,"icon":259},"Elysia","\u002Fframeworks\u002Felysia","4.frameworks\u002F10.elysia","i-custom-elysia",{"title":261,"path":262,"stem":263,"icon":264},"React Router","\u002Fframeworks\u002Freact-router","4.frameworks\u002F11.react-router","i-custom-reactrouter",{"title":266,"path":267,"stem":268,"icon":269},"Cloudflare Workers","\u002Fframeworks\u002Fcloudflare-workers","4.frameworks\u002F12.cloudflare-workers","i-simple-icons-cloudflare",{"title":271,"path":272,"stem":273,"icon":183},"Standalone","\u002Fframeworks\u002Fstandalone","4.frameworks\u002F13.standalone",{"title":275,"path":276,"stem":277,"icon":278},"Astro","\u002Fframeworks\u002Fastro","4.frameworks\u002F14.astro","i-simple-icons-astro",{"title":280,"path":281,"stem":282,"icon":283},"AWS Lambda","\u002Fframeworks\u002Faws-lambda","4.frameworks\u002F16.aws-lambda","i-custom-lambda",{"title":285,"path":286,"stem":287,"icon":288},"Custom Integration","\u002Fframeworks\u002Fcustom-integration","4.frameworks\u002F17.custom-integration","i-lucide-puzzle",{"title":290,"path":291,"stem":292,"children":293,"page":34},"Build on top","\u002Fbuild-on-top","5.build-on-top",[294,297,302,307,312,317,321],{"title":41,"path":295,"stem":296,"icon":54},"\u002Fbuild-on-top\u002Foverview","5.build-on-top\u002F0.overview",{"title":298,"path":299,"stem":300,"icon":301},"Stream API","\u002Fbuild-on-top\u002Fstream-api","5.build-on-top\u002F1.stream-api","i-lucide-radio-tower",{"title":303,"path":304,"stem":305,"icon":306},"Stream server","\u002Fbuild-on-top\u002Fstream-server","5.build-on-top\u002F2.stream-server","i-lucide-radio",{"title":308,"path":309,"stem":310,"icon":311},"FS reader","\u002Fbuild-on-top\u002Ffs-reader","5.build-on-top\u002F3.fs-reader","i-lucide-folder-search",{"title":313,"path":314,"stem":315,"icon":316},"Identity headers","\u002Fbuild-on-top\u002Fidentity-headers","5.build-on-top\u002F4.identity-headers","i-lucide-fingerprint",{"title":156,"path":318,"stem":319,"icon":320},"\u002Fbuild-on-top\u002Frecipes","5.build-on-top\u002F5.recipes","i-lucide-chef-hat",{"title":322,"path":323,"stem":324,"icon":325},"Catalogs as packages","\u002Fbuild-on-top\u002Fcatalogs-as-packages","5.build-on-top\u002F6.catalogs-as-packages","i-lucide-package",{"title":327,"path":328,"stem":329,"children":330,"page":34},"Adapters","\u002Fadapters","6.adapters",[331,334,374,389],{"title":41,"path":332,"stem":333,"icon":44},"\u002Fadapters\u002Foverview","6.adapters\u002F01.overview",{"title":335,"path":336,"stem":337,"children":338,"page":34},"Cloud destinations","\u002Fadapters\u002Fcloud","6.adapters\u002F02.cloud",[339,344,349,354,359,364,369],{"title":340,"path":341,"stem":342,"icon":343},"Axiom","\u002Fadapters\u002Fcloud\u002Faxiom","6.adapters\u002F02.cloud\u002F01.axiom","i-custom-axiom",{"title":345,"path":346,"stem":347,"icon":348},"OTLP","\u002Fadapters\u002Fcloud\u002Fotlp","6.adapters\u002F02.cloud\u002F02.otlp","i-simple-icons-opentelemetry",{"title":350,"path":351,"stem":352,"icon":353},"PostHog","\u002Fadapters\u002Fcloud\u002Fposthog","6.adapters\u002F02.cloud\u002F03.posthog","i-simple-icons-posthog",{"title":355,"path":356,"stem":357,"icon":358},"Sentry","\u002Fadapters\u002Fcloud\u002Fsentry","6.adapters\u002F02.cloud\u002F04.sentry","i-simple-icons-sentry",{"title":360,"path":361,"stem":362,"icon":363},"Better Stack","\u002Fadapters\u002Fcloud\u002Fbetter-stack","6.adapters\u002F02.cloud\u002F05.better-stack","i-simple-icons-betterstack",{"title":365,"path":366,"stem":367,"icon":368},"Datadog","\u002Fadapters\u002Fcloud\u002Fdatadog","6.adapters\u002F02.cloud\u002F06.datadog","i-simple-icons-datadog",{"title":370,"path":371,"stem":372,"icon":373},"HyperDX","\u002Fadapters\u002Fcloud\u002Fhyperdx","6.adapters\u002F02.cloud\u002F07.hyperdx","i-custom-hyperdx",{"title":375,"path":376,"stem":377,"children":378,"page":34},"Self-hosted","\u002Fadapters\u002Fself-hosted","6.adapters\u002F03.self-hosted",[379,384],{"title":380,"path":381,"stem":382,"icon":383},"File System","\u002Fadapters\u002Fself-hosted\u002Ffs","6.adapters\u002F03.self-hosted\u002F01.fs","i-lucide-hard-drive",{"title":385,"path":386,"stem":387,"icon":388},"NuxtHub","\u002Fadapters\u002Fself-hosted\u002Fnuxthub","6.adapters\u002F03.self-hosted\u002F02.nuxthub","i-simple-icons-nuxt",{"title":390,"path":391,"stem":392,"children":393,"page":34},"Building blocks","\u002Fadapters\u002Fbuilding-blocks","6.adapters\u002F04.building-blocks",[394,399,404,408],{"title":395,"path":396,"stem":397,"icon":398},"Pipeline","\u002Fadapters\u002Fbuilding-blocks\u002Fpipeline","6.adapters\u002F04.building-blocks\u002F01.pipeline","i-lucide-workflow",{"title":400,"path":401,"stem":402,"icon":403},"HTTP","\u002Fadapters\u002Fbuilding-blocks\u002Fhttp","6.adapters\u002F04.building-blocks\u002F02.http","i-lucide-globe",{"title":405,"path":406,"stem":407,"icon":83},"Custom Adapters","\u002Fadapters\u002Fbuilding-blocks\u002Fcustom","6.adapters\u002F04.building-blocks\u002F03.custom",{"title":409,"path":410,"stem":411,"icon":412},"Toolkit","\u002Fadapters\u002Fbuilding-blocks\u002Ftoolkit","6.adapters\u002F04.building-blocks\u002F04.toolkit","i-lucide-blocks",{"title":414,"path":415,"stem":416,"children":417,"page":34},"Enrichers","\u002Fenrichers","7.enrichers",[418,421,425],{"title":41,"path":419,"stem":420,"icon":28},"\u002Fenrichers\u002Foverview","7.enrichers\u002F1.overview",{"title":422,"path":423,"stem":424,"icon":288},"Built-in","\u002Fenrichers\u002Fbuilt-in","7.enrichers\u002F2.built-in",{"title":426,"path":427,"stem":428,"icon":83},"Custom","\u002Fenrichers\u002Fcustom","7.enrichers\u002F3.custom",{"id":430,"title":431,"body":432,"description":1301,"extension":1302,"links":1303,"meta":1308,"navigation":1309,"path":148,"seo":1310,"stem":149,"__hash__":1311},"docs\u002F2.logging\u002F8.audit\u002F04.pipeline.md","Drains & Integrity",{"type":433,"value":434,"toc":1293},"minimark",[435,452,459,468,555,558,681,699,705,725,739,876,883,935,941,946,952,1009,1026,1031,1034,1109,1113,1116,1265,1271,1274,1289],[436,437,438,439,443,444,447,448,451],"p",{},"Three building blocks: ",[440,441,442],"code",{},"auditEnricher"," fills context, ",[440,445,446],{},"auditOnly"," routes audits to a dedicated drain, and ",[440,449,450],{},"signed"," adds tamper-evident integrity. Each is opt-in and replaceable.",[453,454,456],"h2",{"id":455},"auditenricher",[440,457,458],{},"auditEnricher()",[436,460,461,463,464,467],{},[440,462,458],{}," populates ",[440,465,466],{},"event.audit.context.{requestId, traceId, ip, userAgent, tenantId}",". Skip it and ship a custom enricher if your strategy differs.",[469,470,476],"pre",{"className":471,"code":472,"filename":473,"language":474,"meta":475,"style":475},"language-typescript shiki shiki-themes material-theme-lighter material-theme material-theme-palenight","import { auditEnricher } from 'evlog'\n\nnitro.hooks.hook('evlog:enrich', auditEnricher())\n","server\u002Fplugins\u002Fevlog.ts","typescript","",[440,477,478,511,518],{"__ignoreMap":475},[479,480,483,487,491,495,498,501,504,508],"span",{"class":481,"line":482},"line",1,[479,484,486],{"class":485},"s7zQu","import",[479,488,490],{"class":489},"sMK4o"," {",[479,492,494],{"class":493},"sTEyZ"," auditEnricher",[479,496,497],{"class":489}," }",[479,499,500],{"class":485}," from",[479,502,503],{"class":489}," '",[479,505,507],{"class":506},"sfazB","evlog",[479,509,510],{"class":489},"'\n",[479,512,514],{"class":481,"line":513},2,[479,515,517],{"emptyLinePlaceholder":516},true,"\n",[479,519,521,524,527,530,532,536,539,542,545,547,550,552],{"class":481,"line":520},3,[479,522,523],{"class":493},"nitro",[479,525,526],{"class":489},".",[479,528,529],{"class":493},"hooks",[479,531,526],{"class":489},[479,533,535],{"class":534},"s2Zo4","hook",[479,537,538],{"class":493},"(",[479,540,541],{"class":489},"'",[479,543,544],{"class":506},"evlog:enrich",[479,546,541],{"class":489},[479,548,549],{"class":489},",",[479,551,494],{"class":534},[479,553,554],{"class":493},"())\n",[436,556,557],{},"For multi-tenant apps and custom session bridges, pass options:",[469,559,561],{"className":471,"code":560,"language":474,"meta":475,"style":475},"nitro.hooks.hook('evlog:enrich', auditEnricher({\n  tenantId: ctx => ctx.event.tenant as string | undefined,\n  bridge: { getSession: async ctx => readSessionActor(ctx.headers) },\n}))\n",[440,562,563,592,636,672],{"__ignoreMap":475},[479,564,565,567,569,571,573,575,577,579,581,583,585,587,589],{"class":481,"line":482},[479,566,523],{"class":493},[479,568,526],{"class":489},[479,570,529],{"class":493},[479,572,526],{"class":489},[479,574,535],{"class":534},[479,576,538],{"class":493},[479,578,541],{"class":489},[479,580,544],{"class":506},[479,582,541],{"class":489},[479,584,549],{"class":489},[479,586,494],{"class":534},[479,588,538],{"class":493},[479,590,591],{"class":489},"{\n",[479,593,594,597,600,604,608,610,612,615,617,620,623,627,630,633],{"class":481,"line":513},[479,595,596],{"class":534},"  tenantId",[479,598,599],{"class":489},":",[479,601,603],{"class":602},"sHdIc"," ctx",[479,605,607],{"class":606},"spNyl"," =>",[479,609,603],{"class":493},[479,611,526],{"class":489},[479,613,614],{"class":493},"event",[479,616,526],{"class":489},[479,618,619],{"class":493},"tenant ",[479,621,622],{"class":485},"as",[479,624,626],{"class":625},"sBMFI"," string",[479,628,629],{"class":489}," |",[479,631,632],{"class":625}," undefined",[479,634,635],{"class":489},",\n",[479,637,638,642,644,646,649,651,654,656,658,661,664,666,669],{"class":481,"line":520},[479,639,641],{"class":640},"swJcz","  bridge",[479,643,599],{"class":489},[479,645,490],{"class":489},[479,647,648],{"class":534}," getSession",[479,650,599],{"class":489},[479,652,653],{"class":606}," async",[479,655,603],{"class":602},[479,657,607],{"class":606},[479,659,660],{"class":534}," readSessionActor",[479,662,663],{"class":493},"(ctx",[479,665,526],{"class":489},[479,667,668],{"class":493},"headers) ",[479,670,671],{"class":489},"},\n",[479,673,675,678],{"class":481,"line":674},4,[479,676,677],{"class":489},"}",[479,679,680],{"class":493},"))\n",[436,682,683,684,686,687,690,691,694,695,698],{},"Without ",[440,685,442],{},", ",[440,688,689],{},"audit.context"," stays empty — auditors and incident responders need at least ",[440,692,693],{},"requestId"," and ",[440,696,697],{},"ip"," to triangulate a recorded action.",[453,700,702],{"id":701},"auditonly",[440,703,704],{},"auditOnly()",[706,707,708,712,713,716,717,720,721,724],"tip",{},[709,710,711],"strong",{},"Why filter audits to a separate sink?"," Three reasons: ",[709,714,715],{},"cost"," (audit volume is tiny next to product telemetry — keep them separate so retention costs don't explode), ",[709,718,719],{},"permissions"," (the audit dataset should be read-only for engineers and write-only for the app), and ",[709,722,723],{},"retention"," (audits often live 7+ years; product logs rarely live more than 90 days).",[436,726,727,730,731,734,735,738],{},[440,728,729],{},"auditOnly(drain)"," only forwards events with an ",[440,732,733],{},"audit"," field. Compose with ",[709,736,737],{},"any"," drain:",[469,740,742],{"className":471,"code":741,"language":474,"meta":475,"style":475},"import { auditOnly } from 'evlog'\nimport { createAxiomDrain } from 'evlog\u002Faxiom'\n\n\u002F\u002F Send audits to a dedicated Axiom dataset:\nnitro.hooks.hook('evlog:drain', auditOnly(\n  createAxiomDrain({ dataset: 'audit', token: process.env.AXIOM_AUDIT_TOKEN }),\n))\n",[440,743,744,763,783,787,793,822,871],{"__ignoreMap":475},[479,745,746,748,750,753,755,757,759,761],{"class":481,"line":482},[479,747,486],{"class":485},[479,749,490],{"class":489},[479,751,752],{"class":493}," auditOnly",[479,754,497],{"class":489},[479,756,500],{"class":485},[479,758,503],{"class":489},[479,760,507],{"class":506},[479,762,510],{"class":489},[479,764,765,767,769,772,774,776,778,781],{"class":481,"line":513},[479,766,486],{"class":485},[479,768,490],{"class":489},[479,770,771],{"class":493}," createAxiomDrain",[479,773,497],{"class":489},[479,775,500],{"class":485},[479,777,503],{"class":489},[479,779,780],{"class":506},"evlog\u002Faxiom",[479,782,510],{"class":489},[479,784,785],{"class":481,"line":520},[479,786,517],{"emptyLinePlaceholder":516},[479,788,789],{"class":481,"line":674},[479,790,792],{"class":791},"sHwdD","\u002F\u002F Send audits to a dedicated Axiom dataset:\n",[479,794,796,798,800,802,804,806,808,810,813,815,817,819],{"class":481,"line":795},5,[479,797,523],{"class":493},[479,799,526],{"class":489},[479,801,529],{"class":493},[479,803,526],{"class":489},[479,805,535],{"class":534},[479,807,538],{"class":493},[479,809,541],{"class":489},[479,811,812],{"class":506},"evlog:drain",[479,814,541],{"class":489},[479,816,549],{"class":489},[479,818,752],{"class":534},[479,820,821],{"class":493},"(\n",[479,823,825,828,830,833,836,838,840,842,844,846,849,851,854,856,859,861,864,866,869],{"class":481,"line":824},6,[479,826,827],{"class":534},"  createAxiomDrain",[479,829,538],{"class":493},[479,831,832],{"class":489},"{",[479,834,835],{"class":640}," dataset",[479,837,599],{"class":489},[479,839,503],{"class":489},[479,841,733],{"class":506},[479,843,541],{"class":489},[479,845,549],{"class":489},[479,847,848],{"class":640}," token",[479,850,599],{"class":489},[479,852,853],{"class":493}," process",[479,855,526],{"class":489},[479,857,858],{"class":493},"env",[479,860,526],{"class":489},[479,862,863],{"class":493},"AXIOM_AUDIT_TOKEN ",[479,865,677],{"class":489},[479,867,868],{"class":493},")",[479,870,635],{"class":489},[479,872,874],{"class":481,"line":873},7,[479,875,680],{"class":493},[436,877,878,879,882],{},"Set ",[440,880,881],{},"await: true"," to make audit writes synchronous (no fire-and-forget for audits — crash-safe by default):",[469,884,886],{"className":471,"code":885,"language":474,"meta":475,"style":475},"auditOnly(createFsDrain({ dir: '.audit' }), { await: true })\n",[440,887,888],{"__ignoreMap":475},[479,889,890,892,894,897,899,901,904,906,908,911,913,915,917,919,921,924,926,930,932],{"class":481,"line":482},[479,891,446],{"class":534},[479,893,538],{"class":493},[479,895,896],{"class":534},"createFsDrain",[479,898,538],{"class":493},[479,900,832],{"class":489},[479,902,903],{"class":640}," dir",[479,905,599],{"class":489},[479,907,503],{"class":489},[479,909,910],{"class":506},".audit",[479,912,541],{"class":489},[479,914,497],{"class":489},[479,916,868],{"class":493},[479,918,549],{"class":489},[479,920,490],{"class":489},[479,922,923],{"class":640}," await",[479,925,599],{"class":489},[479,927,929],{"class":928},"sfNiH"," true",[479,931,497],{"class":489},[479,933,934],{"class":493},")\n",[436,936,937,938,940],{},"The ",[440,939,881],{}," flag costs you a small bit of latency per request that records an audit (one synchronous drain call), but guarantees the audit hits disk before the response is sent. For compliance-grade audits, the trade-off is always worth it.",[453,942,943],{"id":450},[440,944,945],{},"signed()",[436,947,948,951],{},[440,949,950],{},"signed(drain, opts)"," adds tamper-evident integrity. Two strategies:",[953,954,955,971],"table",{},[956,957,958],"thead",{},[959,960,961,965,968],"tr",{},[962,963,964],"th",{},"Strategy",[962,966,967],{},"What it adds",[962,969,970],{},"Use case",[972,973,974,991],"tbody",{},[959,975,976,982,988],{},[977,978,979],"td",{},[440,980,981],{},"'hmac'",[977,983,984,987],{},[440,985,986],{},"event.audit.signature"," (HMAC of the canonical event)",[977,989,990],{},"Single-event integrity check (any later mutation fails verification).",[959,992,993,998,1006],{},[977,994,995],{},[440,996,997],{},"'hash-chain'",[977,999,1000,694,1003],{},[440,1001,1002],{},"event.audit.prevHash",[440,1004,1005],{},"event.audit.hash",[977,1007,1008],{},"A verifiable chain — deletions and reordering also become detectable.",[706,1010,1011,1017,1018,1022,1023,1025],{},[709,1012,1013,1014,1016],{},"What ",[440,1015,945],{}," actually buys you."," Detection, not prevention. Anyone with write access to the underlying sink can still nuke the file or table — but the chain proves ",[1019,1020,1021],"em",{},"which"," events were dropped or modified after the fact. Skip ",[440,1024,945],{}," if you already write to an append-only \u002F WORM store (S3 Object Lock, Postgres with row-level immutability, BigQuery append-only tables); doubling integrity layers just adds latency without raising the bar.",[1027,1028,1030],"h3",{"id":1029},"hmac","HMAC",[436,1032,1033],{},"Each event gets a signature. Tampering with one row breaks that row's verification, but doesn't break later rows.",[469,1035,1037],{"className":471,"code":1036,"language":474,"meta":475,"style":475},"import { signed } from 'evlog'\n\nsigned(drain, { strategy: 'hmac', secret: process.env.AUDIT_SECRET! })\n",[440,1038,1039,1058,1062],{"__ignoreMap":475},[479,1040,1041,1043,1045,1048,1050,1052,1054,1056],{"class":481,"line":482},[479,1042,486],{"class":485},[479,1044,490],{"class":489},[479,1046,1047],{"class":493}," signed",[479,1049,497],{"class":489},[479,1051,500],{"class":485},[479,1053,503],{"class":489},[479,1055,507],{"class":506},[479,1057,510],{"class":489},[479,1059,1060],{"class":481,"line":513},[479,1061,517],{"emptyLinePlaceholder":516},[479,1063,1064,1066,1069,1071,1073,1076,1078,1080,1082,1084,1086,1089,1091,1093,1095,1097,1099,1102,1105,1107],{"class":481,"line":520},[479,1065,450],{"class":534},[479,1067,1068],{"class":493},"(drain",[479,1070,549],{"class":489},[479,1072,490],{"class":489},[479,1074,1075],{"class":640}," strategy",[479,1077,599],{"class":489},[479,1079,503],{"class":489},[479,1081,1029],{"class":506},[479,1083,541],{"class":489},[479,1085,549],{"class":489},[479,1087,1088],{"class":640}," secret",[479,1090,599],{"class":489},[479,1092,853],{"class":493},[479,1094,526],{"class":489},[479,1096,858],{"class":493},[479,1098,526],{"class":489},[479,1100,1101],{"class":493},"AUDIT_SECRET",[479,1103,1104],{"class":489},"!",[479,1106,497],{"class":489},[479,1108,934],{"class":493},[1027,1110,1112],{"id":1111},"hash-chain","Hash-chain",[436,1114,1115],{},"Each event references the previous event's hash. Deleting any row breaks the chain forward of that point, so the verifier can pinpoint the exact row that was tampered with.",[469,1117,1119],{"className":471,"code":1118,"language":474,"meta":475,"style":475},"signed(drain, {\n  strategy: 'hash-chain',\n  state: {\n    load: () => fs.readFile('.audit\u002Fhead', 'utf8').catch(() => null),\n    save: (h) => fs.writeFile('.audit\u002Fhead', h),\n  },\n})\n",[440,1120,1121,1132,1147,1156,1215,1254,1259],{"__ignoreMap":475},[479,1122,1123,1125,1127,1129],{"class":481,"line":482},[479,1124,450],{"class":534},[479,1126,1068],{"class":493},[479,1128,549],{"class":489},[479,1130,1131],{"class":489}," {\n",[479,1133,1134,1137,1139,1141,1143,1145],{"class":481,"line":513},[479,1135,1136],{"class":640},"  strategy",[479,1138,599],{"class":489},[479,1140,503],{"class":489},[479,1142,1111],{"class":506},[479,1144,541],{"class":489},[479,1146,635],{"class":489},[479,1148,1149,1152,1154],{"class":481,"line":520},[479,1150,1151],{"class":640},"  state",[479,1153,599],{"class":489},[479,1155,1131],{"class":489},[479,1157,1158,1161,1163,1166,1168,1171,1173,1176,1178,1180,1183,1185,1187,1189,1192,1194,1196,1198,1201,1203,1206,1208,1211,1213],{"class":481,"line":674},[479,1159,1160],{"class":534},"    load",[479,1162,599],{"class":489},[479,1164,1165],{"class":489}," ()",[479,1167,607],{"class":606},[479,1169,1170],{"class":493}," fs",[479,1172,526],{"class":489},[479,1174,1175],{"class":534},"readFile",[479,1177,538],{"class":493},[479,1179,541],{"class":489},[479,1181,1182],{"class":506},".audit\u002Fhead",[479,1184,541],{"class":489},[479,1186,549],{"class":489},[479,1188,503],{"class":489},[479,1190,1191],{"class":506},"utf8",[479,1193,541],{"class":489},[479,1195,868],{"class":493},[479,1197,526],{"class":489},[479,1199,1200],{"class":534},"catch",[479,1202,538],{"class":493},[479,1204,1205],{"class":489},"()",[479,1207,607],{"class":606},[479,1209,1210],{"class":489}," null",[479,1212,868],{"class":493},[479,1214,635],{"class":489},[479,1216,1217,1220,1222,1225,1228,1230,1232,1234,1236,1239,1241,1243,1245,1247,1249,1252],{"class":481,"line":795},[479,1218,1219],{"class":534},"    save",[479,1221,599],{"class":489},[479,1223,1224],{"class":489}," (",[479,1226,1227],{"class":602},"h",[479,1229,868],{"class":489},[479,1231,607],{"class":606},[479,1233,1170],{"class":493},[479,1235,526],{"class":489},[479,1237,1238],{"class":534},"writeFile",[479,1240,538],{"class":493},[479,1242,541],{"class":489},[479,1244,1182],{"class":506},[479,1246,541],{"class":489},[479,1248,549],{"class":489},[479,1250,1251],{"class":493}," h)",[479,1253,635],{"class":489},[479,1255,1256],{"class":481,"line":824},[479,1257,1258],{"class":489},"  },\n",[479,1260,1261,1263],{"class":481,"line":873},[479,1262,677],{"class":489},[479,1264,934],{"class":493},[436,1266,937,1267,1270],{},[440,1268,1269],{},"state"," config is required for cross-process or durable chains: load the previous head hash from your own store (Redis, Postgres, file) before each event, save the new head after.",[1272,1273],"hash-chain-tamper",{},[1275,1276,1277,1278,1281,1282,1285,1286,526],"note",{},"A CLI to walk and verify the chain (",[440,1279,1280],{},"evlog audit verify",") is on the roadmap. Until then, validate by recomputing the hashes of stored events and comparing each ",[440,1283,1284],{},"prevHash"," against the previous event's ",[440,1287,1288],{},"hash",[1290,1291,1292],"style",{},"html pre.shiki code .s7zQu, html code.shiki .s7zQu{--shiki-light:#39ADB5;--shiki-light-font-style:italic;--shiki-default:#89DDFF;--shiki-default-font-style:italic;--shiki-dark:#89DDFF;--shiki-dark-font-style:italic}html pre.shiki code .sMK4o, html code.shiki .sMK4o{--shiki-light:#39ADB5;--shiki-default:#89DDFF;--shiki-dark:#89DDFF}html pre.shiki code .sTEyZ, html code.shiki .sTEyZ{--shiki-light:#90A4AE;--shiki-default:#EEFFFF;--shiki-dark:#BABED8}html pre.shiki code .sfazB, html code.shiki .sfazB{--shiki-light:#91B859;--shiki-default:#C3E88D;--shiki-dark:#C3E88D}html pre.shiki code .s2Zo4, html code.shiki .s2Zo4{--shiki-light:#6182B8;--shiki-default:#82AAFF;--shiki-dark:#82AAFF}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 .sHdIc, html code.shiki .sHdIc{--shiki-light:#90A4AE;--shiki-light-font-style:italic;--shiki-default:#EEFFFF;--shiki-default-font-style:italic;--shiki-dark:#BABED8;--shiki-dark-font-style:italic}html pre.shiki code .spNyl, html code.shiki .spNyl{--shiki-light:#9C3EDA;--shiki-default:#C792EA;--shiki-dark:#C792EA}html pre.shiki code .sBMFI, html code.shiki .sBMFI{--shiki-light:#E2931D;--shiki-default:#FFCB6B;--shiki-dark:#FFCB6B}html pre.shiki code .swJcz, html code.shiki .swJcz{--shiki-light:#E53935;--shiki-default:#F07178;--shiki-dark:#F07178}html pre.shiki code .sHwdD, html code.shiki .sHwdD{--shiki-light:#90A4AE;--shiki-light-font-style:italic;--shiki-default:#546E7A;--shiki-default-font-style:italic;--shiki-dark:#676E95;--shiki-dark-font-style:italic}html pre.shiki code .sfNiH, html code.shiki .sfNiH{--shiki-light:#FF5370;--shiki-default:#FF9CAC;--shiki-dark:#FF9CAC}",{"title":475,"searchDepth":513,"depth":513,"links":1294},[1295,1296,1297],{"id":455,"depth":513,"text":458},{"id":701,"depth":513,"text":704},{"id":450,"depth":513,"text":945,"children":1298},[1299,1300],{"id":1029,"depth":520,"text":1030},{"id":1111,"depth":520,"text":1112},"auditEnricher to auto-fill request context, auditOnly to route audits to a dedicated sink, and signed for tamper-evident HMAC or hash-chain integrity.","md",[1304,1307],{"label":142,"icon":145,"to":143,"color":1305,"variant":1306},"neutral","subtle",{"label":152,"icon":129,"to":153,"color":1305,"variant":1306},{},{"title":147,"icon":150},{"title":431,"description":1301},"_3JRqd31dDWZXAN9m-j4Ikhyg3JwAr_LT4cmpgR6ppw",[1313,1315],{"title":142,"path":143,"stem":144,"description":1314,"icon":145,"children":-1},"log.audit, log.audit.deny, standalone audit(), withAudit auto-instrumentation, defineAuditAction and defineAuditCatalog registries, and auditDiff change patches.",{"title":152,"path":153,"stem":154,"description":1316,"icon":129,"children":-1},"Integrity, redact presets, GDPR vs append-only, retention windows, and the most common pitfalls when shipping audit logs to production.",1778336623858]