[{"data":1,"prerenderedAt":1280},["ShallowReactive",2],{"navigation_docs":3,"-logging-audit-pipeline":392,"-logging-audit-pipeline-surround":1275},[4,35,159,201,289,376],{"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},"Adapters","\u002Fadapters","6.adapters",[294,297,337,352],{"title":41,"path":295,"stem":296,"icon":44},"\u002Fadapters\u002Foverview","6.adapters\u002F01.overview",{"title":298,"path":299,"stem":300,"children":301,"page":34},"Cloud destinations","\u002Fadapters\u002Fcloud","6.adapters\u002F02.cloud",[302,307,312,317,322,327,332],{"title":303,"path":304,"stem":305,"icon":306},"Axiom","\u002Fadapters\u002Fcloud\u002Faxiom","6.adapters\u002F02.cloud\u002F01.axiom","i-custom-axiom",{"title":308,"path":309,"stem":310,"icon":311},"OTLP","\u002Fadapters\u002Fcloud\u002Fotlp","6.adapters\u002F02.cloud\u002F02.otlp","i-simple-icons-opentelemetry",{"title":313,"path":314,"stem":315,"icon":316},"PostHog","\u002Fadapters\u002Fcloud\u002Fposthog","6.adapters\u002F02.cloud\u002F03.posthog","i-simple-icons-posthog",{"title":318,"path":319,"stem":320,"icon":321},"Sentry","\u002Fadapters\u002Fcloud\u002Fsentry","6.adapters\u002F02.cloud\u002F04.sentry","i-simple-icons-sentry",{"title":323,"path":324,"stem":325,"icon":326},"Better Stack","\u002Fadapters\u002Fcloud\u002Fbetter-stack","6.adapters\u002F02.cloud\u002F05.better-stack","i-simple-icons-betterstack",{"title":328,"path":329,"stem":330,"icon":331},"Datadog","\u002Fadapters\u002Fcloud\u002Fdatadog","6.adapters\u002F02.cloud\u002F06.datadog","i-simple-icons-datadog",{"title":333,"path":334,"stem":335,"icon":336},"HyperDX","\u002Fadapters\u002Fcloud\u002Fhyperdx","6.adapters\u002F02.cloud\u002F07.hyperdx","i-custom-hyperdx",{"title":338,"path":339,"stem":340,"children":341,"page":34},"Self-hosted","\u002Fadapters\u002Fself-hosted","6.adapters\u002F03.self-hosted",[342,347],{"title":343,"path":344,"stem":345,"icon":346},"File System","\u002Fadapters\u002Fself-hosted\u002Ffs","6.adapters\u002F03.self-hosted\u002F01.fs","i-lucide-hard-drive",{"title":348,"path":349,"stem":350,"icon":351},"NuxtHub","\u002Fadapters\u002Fself-hosted\u002Fnuxthub","6.adapters\u002F03.self-hosted\u002F02.nuxthub","i-simple-icons-nuxt",{"title":353,"path":354,"stem":355,"children":356,"page":34},"Building blocks","\u002Fadapters\u002Fbuilding-blocks","6.adapters\u002F04.building-blocks",[357,362,367,371],{"title":358,"path":359,"stem":360,"icon":361},"Pipeline","\u002Fadapters\u002Fbuilding-blocks\u002Fpipeline","6.adapters\u002F04.building-blocks\u002F01.pipeline","i-lucide-workflow",{"title":363,"path":364,"stem":365,"icon":366},"HTTP","\u002Fadapters\u002Fbuilding-blocks\u002Fhttp","6.adapters\u002F04.building-blocks\u002F02.http","i-lucide-globe",{"title":368,"path":369,"stem":370,"icon":83},"Custom Adapters","\u002Fadapters\u002Fbuilding-blocks\u002Fcustom","6.adapters\u002F04.building-blocks\u002F03.custom",{"title":372,"path":373,"stem":374,"icon":375},"Toolkit","\u002Fadapters\u002Fbuilding-blocks\u002Ftoolkit","6.adapters\u002F04.building-blocks\u002F04.toolkit","i-lucide-blocks",{"title":377,"path":378,"stem":379,"children":380,"page":34},"Enrichers","\u002Fenrichers","7.enrichers",[381,384,388],{"title":41,"path":382,"stem":383,"icon":28},"\u002Fenrichers\u002Foverview","7.enrichers\u002F1.overview",{"title":385,"path":386,"stem":387,"icon":288},"Built-in","\u002Fenrichers\u002Fbuilt-in","7.enrichers\u002F2.built-in",{"title":389,"path":390,"stem":391,"icon":83},"Custom","\u002Fenrichers\u002Fcustom","7.enrichers\u002F3.custom",{"id":393,"title":394,"body":395,"description":1264,"extension":1265,"links":1266,"meta":1271,"navigation":1272,"path":148,"seo":1273,"stem":149,"__hash__":1274},"docs\u002F2.logging\u002F8.audit\u002F04.pipeline.md","Drains & Integrity",{"type":396,"value":397,"toc":1256},"minimark",[398,415,422,431,518,521,644,662,668,688,702,839,846,898,904,909,915,972,989,994,997,1072,1076,1079,1228,1234,1237,1252],[399,400,401,402,406,407,410,411,414],"p",{},"Three building blocks: ",[403,404,405],"code",{},"auditEnricher"," fills context, ",[403,408,409],{},"auditOnly"," routes audits to a dedicated drain, and ",[403,412,413],{},"signed"," adds tamper-evident integrity. Each is opt-in and replaceable.",[416,417,419],"h2",{"id":418},"auditenricher",[403,420,421],{},"auditEnricher()",[399,423,424,426,427,430],{},[403,425,421],{}," populates ",[403,428,429],{},"event.audit.context.{requestId, traceId, ip, userAgent, tenantId}",". Skip it and ship a custom enricher if your strategy differs.",[432,433,439],"pre",{"className":434,"code":435,"filename":436,"language":437,"meta":438,"style":438},"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","",[403,440,441,474,481],{"__ignoreMap":438},[442,443,446,450,454,458,461,464,467,471],"span",{"class":444,"line":445},"line",1,[442,447,449],{"class":448},"s7zQu","import",[442,451,453],{"class":452},"sMK4o"," {",[442,455,457],{"class":456},"sTEyZ"," auditEnricher",[442,459,460],{"class":452}," }",[442,462,463],{"class":448}," from",[442,465,466],{"class":452}," '",[442,468,470],{"class":469},"sfazB","evlog",[442,472,473],{"class":452},"'\n",[442,475,477],{"class":444,"line":476},2,[442,478,480],{"emptyLinePlaceholder":479},true,"\n",[442,482,484,487,490,493,495,499,502,505,508,510,513,515],{"class":444,"line":483},3,[442,485,486],{"class":456},"nitro",[442,488,489],{"class":452},".",[442,491,492],{"class":456},"hooks",[442,494,489],{"class":452},[442,496,498],{"class":497},"s2Zo4","hook",[442,500,501],{"class":456},"(",[442,503,504],{"class":452},"'",[442,506,507],{"class":469},"evlog:enrich",[442,509,504],{"class":452},[442,511,512],{"class":452},",",[442,514,457],{"class":497},[442,516,517],{"class":456},"())\n",[399,519,520],{},"For multi-tenant apps and custom session bridges, pass options:",[432,522,524],{"className":434,"code":523,"language":437,"meta":438,"style":438},"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",[403,525,526,555,599,635],{"__ignoreMap":438},[442,527,528,530,532,534,536,538,540,542,544,546,548,550,552],{"class":444,"line":445},[442,529,486],{"class":456},[442,531,489],{"class":452},[442,533,492],{"class":456},[442,535,489],{"class":452},[442,537,498],{"class":497},[442,539,501],{"class":456},[442,541,504],{"class":452},[442,543,507],{"class":469},[442,545,504],{"class":452},[442,547,512],{"class":452},[442,549,457],{"class":497},[442,551,501],{"class":456},[442,553,554],{"class":452},"{\n",[442,556,557,560,563,567,571,573,575,578,580,583,586,590,593,596],{"class":444,"line":476},[442,558,559],{"class":497},"  tenantId",[442,561,562],{"class":452},":",[442,564,566],{"class":565},"sHdIc"," ctx",[442,568,570],{"class":569},"spNyl"," =>",[442,572,566],{"class":456},[442,574,489],{"class":452},[442,576,577],{"class":456},"event",[442,579,489],{"class":452},[442,581,582],{"class":456},"tenant ",[442,584,585],{"class":448},"as",[442,587,589],{"class":588},"sBMFI"," string",[442,591,592],{"class":452}," |",[442,594,595],{"class":588}," undefined",[442,597,598],{"class":452},",\n",[442,600,601,605,607,609,612,614,617,619,621,624,627,629,632],{"class":444,"line":483},[442,602,604],{"class":603},"swJcz","  bridge",[442,606,562],{"class":452},[442,608,453],{"class":452},[442,610,611],{"class":497}," getSession",[442,613,562],{"class":452},[442,615,616],{"class":569}," async",[442,618,566],{"class":565},[442,620,570],{"class":569},[442,622,623],{"class":497}," readSessionActor",[442,625,626],{"class":456},"(ctx",[442,628,489],{"class":452},[442,630,631],{"class":456},"headers) ",[442,633,634],{"class":452},"},\n",[442,636,638,641],{"class":444,"line":637},4,[442,639,640],{"class":452},"}",[442,642,643],{"class":456},"))\n",[399,645,646,647,649,650,653,654,657,658,661],{},"Without ",[403,648,405],{},", ",[403,651,652],{},"audit.context"," stays empty — auditors and incident responders need at least ",[403,655,656],{},"requestId"," and ",[403,659,660],{},"ip"," to triangulate a recorded action.",[416,663,665],{"id":664},"auditonly",[403,666,667],{},"auditOnly()",[669,670,671,675,676,679,680,683,684,687],"tip",{},[672,673,674],"strong",{},"Why filter audits to a separate sink?"," Three reasons: ",[672,677,678],{},"cost"," (audit volume is tiny next to product telemetry — keep them separate so retention costs don't explode), ",[672,681,682],{},"permissions"," (the audit dataset should be read-only for engineers and write-only for the app), and ",[672,685,686],{},"retention"," (audits often live 7+ years; product logs rarely live more than 90 days).",[399,689,690,693,694,697,698,701],{},[403,691,692],{},"auditOnly(drain)"," only forwards events with an ",[403,695,696],{},"audit"," field. Compose with ",[672,699,700],{},"any"," drain:",[432,703,705],{"className":434,"code":704,"language":437,"meta":438,"style":438},"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",[403,706,707,726,746,750,756,785,834],{"__ignoreMap":438},[442,708,709,711,713,716,718,720,722,724],{"class":444,"line":445},[442,710,449],{"class":448},[442,712,453],{"class":452},[442,714,715],{"class":456}," auditOnly",[442,717,460],{"class":452},[442,719,463],{"class":448},[442,721,466],{"class":452},[442,723,470],{"class":469},[442,725,473],{"class":452},[442,727,728,730,732,735,737,739,741,744],{"class":444,"line":476},[442,729,449],{"class":448},[442,731,453],{"class":452},[442,733,734],{"class":456}," createAxiomDrain",[442,736,460],{"class":452},[442,738,463],{"class":448},[442,740,466],{"class":452},[442,742,743],{"class":469},"evlog\u002Faxiom",[442,745,473],{"class":452},[442,747,748],{"class":444,"line":483},[442,749,480],{"emptyLinePlaceholder":479},[442,751,752],{"class":444,"line":637},[442,753,755],{"class":754},"sHwdD","\u002F\u002F Send audits to a dedicated Axiom dataset:\n",[442,757,759,761,763,765,767,769,771,773,776,778,780,782],{"class":444,"line":758},5,[442,760,486],{"class":456},[442,762,489],{"class":452},[442,764,492],{"class":456},[442,766,489],{"class":452},[442,768,498],{"class":497},[442,770,501],{"class":456},[442,772,504],{"class":452},[442,774,775],{"class":469},"evlog:drain",[442,777,504],{"class":452},[442,779,512],{"class":452},[442,781,715],{"class":497},[442,783,784],{"class":456},"(\n",[442,786,788,791,793,796,799,801,803,805,807,809,812,814,817,819,822,824,827,829,832],{"class":444,"line":787},6,[442,789,790],{"class":497},"  createAxiomDrain",[442,792,501],{"class":456},[442,794,795],{"class":452},"{",[442,797,798],{"class":603}," dataset",[442,800,562],{"class":452},[442,802,466],{"class":452},[442,804,696],{"class":469},[442,806,504],{"class":452},[442,808,512],{"class":452},[442,810,811],{"class":603}," token",[442,813,562],{"class":452},[442,815,816],{"class":456}," process",[442,818,489],{"class":452},[442,820,821],{"class":456},"env",[442,823,489],{"class":452},[442,825,826],{"class":456},"AXIOM_AUDIT_TOKEN ",[442,828,640],{"class":452},[442,830,831],{"class":456},")",[442,833,598],{"class":452},[442,835,837],{"class":444,"line":836},7,[442,838,643],{"class":456},[399,840,841,842,845],{},"Set ",[403,843,844],{},"await: true"," to make audit writes synchronous (no fire-and-forget for audits — crash-safe by default):",[432,847,849],{"className":434,"code":848,"language":437,"meta":438,"style":438},"auditOnly(createFsDrain({ dir: '.audit' }), { await: true })\n",[403,850,851],{"__ignoreMap":438},[442,852,853,855,857,860,862,864,867,869,871,874,876,878,880,882,884,887,889,893,895],{"class":444,"line":445},[442,854,409],{"class":497},[442,856,501],{"class":456},[442,858,859],{"class":497},"createFsDrain",[442,861,501],{"class":456},[442,863,795],{"class":452},[442,865,866],{"class":603}," dir",[442,868,562],{"class":452},[442,870,466],{"class":452},[442,872,873],{"class":469},".audit",[442,875,504],{"class":452},[442,877,460],{"class":452},[442,879,831],{"class":456},[442,881,512],{"class":452},[442,883,453],{"class":452},[442,885,886],{"class":603}," await",[442,888,562],{"class":452},[442,890,892],{"class":891},"sfNiH"," true",[442,894,460],{"class":452},[442,896,897],{"class":456},")\n",[399,899,900,901,903],{},"The ",[403,902,844],{}," 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.",[416,905,906],{"id":413},[403,907,908],{},"signed()",[399,910,911,914],{},[403,912,913],{},"signed(drain, opts)"," adds tamper-evident integrity. Two strategies:",[916,917,918,934],"table",{},[919,920,921],"thead",{},[922,923,924,928,931],"tr",{},[925,926,927],"th",{},"Strategy",[925,929,930],{},"What it adds",[925,932,933],{},"Use case",[935,936,937,954],"tbody",{},[922,938,939,945,951],{},[940,941,942],"td",{},[403,943,944],{},"'hmac'",[940,946,947,950],{},[403,948,949],{},"event.audit.signature"," (HMAC of the canonical event)",[940,952,953],{},"Single-event integrity check (any later mutation fails verification).",[922,955,956,961,969],{},[940,957,958],{},[403,959,960],{},"'hash-chain'",[940,962,963,657,966],{},[403,964,965],{},"event.audit.prevHash",[403,967,968],{},"event.audit.hash",[940,970,971],{},"A verifiable chain — deletions and reordering also become detectable.",[669,973,974,980,981,985,986,988],{},[672,975,976,977,979],{},"What ",[403,978,908],{}," 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 ",[982,983,984],"em",{},"which"," events were dropped or modified after the fact. Skip ",[403,987,908],{}," 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.",[990,991,993],"h3",{"id":992},"hmac","HMAC",[399,995,996],{},"Each event gets a signature. Tampering with one row breaks that row's verification, but doesn't break later rows.",[432,998,1000],{"className":434,"code":999,"language":437,"meta":438,"style":438},"import { signed } from 'evlog'\n\nsigned(drain, { strategy: 'hmac', secret: process.env.AUDIT_SECRET! })\n",[403,1001,1002,1021,1025],{"__ignoreMap":438},[442,1003,1004,1006,1008,1011,1013,1015,1017,1019],{"class":444,"line":445},[442,1005,449],{"class":448},[442,1007,453],{"class":452},[442,1009,1010],{"class":456}," signed",[442,1012,460],{"class":452},[442,1014,463],{"class":448},[442,1016,466],{"class":452},[442,1018,470],{"class":469},[442,1020,473],{"class":452},[442,1022,1023],{"class":444,"line":476},[442,1024,480],{"emptyLinePlaceholder":479},[442,1026,1027,1029,1032,1034,1036,1039,1041,1043,1045,1047,1049,1052,1054,1056,1058,1060,1062,1065,1068,1070],{"class":444,"line":483},[442,1028,413],{"class":497},[442,1030,1031],{"class":456},"(drain",[442,1033,512],{"class":452},[442,1035,453],{"class":452},[442,1037,1038],{"class":603}," strategy",[442,1040,562],{"class":452},[442,1042,466],{"class":452},[442,1044,992],{"class":469},[442,1046,504],{"class":452},[442,1048,512],{"class":452},[442,1050,1051],{"class":603}," secret",[442,1053,562],{"class":452},[442,1055,816],{"class":456},[442,1057,489],{"class":452},[442,1059,821],{"class":456},[442,1061,489],{"class":452},[442,1063,1064],{"class":456},"AUDIT_SECRET",[442,1066,1067],{"class":452},"!",[442,1069,460],{"class":452},[442,1071,897],{"class":456},[990,1073,1075],{"id":1074},"hash-chain","Hash-chain",[399,1077,1078],{},"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.",[432,1080,1082],{"className":434,"code":1081,"language":437,"meta":438,"style":438},"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",[403,1083,1084,1095,1110,1119,1178,1217,1222],{"__ignoreMap":438},[442,1085,1086,1088,1090,1092],{"class":444,"line":445},[442,1087,413],{"class":497},[442,1089,1031],{"class":456},[442,1091,512],{"class":452},[442,1093,1094],{"class":452}," {\n",[442,1096,1097,1100,1102,1104,1106,1108],{"class":444,"line":476},[442,1098,1099],{"class":603},"  strategy",[442,1101,562],{"class":452},[442,1103,466],{"class":452},[442,1105,1074],{"class":469},[442,1107,504],{"class":452},[442,1109,598],{"class":452},[442,1111,1112,1115,1117],{"class":444,"line":483},[442,1113,1114],{"class":603},"  state",[442,1116,562],{"class":452},[442,1118,1094],{"class":452},[442,1120,1121,1124,1126,1129,1131,1134,1136,1139,1141,1143,1146,1148,1150,1152,1155,1157,1159,1161,1164,1166,1169,1171,1174,1176],{"class":444,"line":637},[442,1122,1123],{"class":497},"    load",[442,1125,562],{"class":452},[442,1127,1128],{"class":452}," ()",[442,1130,570],{"class":569},[442,1132,1133],{"class":456}," fs",[442,1135,489],{"class":452},[442,1137,1138],{"class":497},"readFile",[442,1140,501],{"class":456},[442,1142,504],{"class":452},[442,1144,1145],{"class":469},".audit\u002Fhead",[442,1147,504],{"class":452},[442,1149,512],{"class":452},[442,1151,466],{"class":452},[442,1153,1154],{"class":469},"utf8",[442,1156,504],{"class":452},[442,1158,831],{"class":456},[442,1160,489],{"class":452},[442,1162,1163],{"class":497},"catch",[442,1165,501],{"class":456},[442,1167,1168],{"class":452},"()",[442,1170,570],{"class":569},[442,1172,1173],{"class":452}," null",[442,1175,831],{"class":456},[442,1177,598],{"class":452},[442,1179,1180,1183,1185,1188,1191,1193,1195,1197,1199,1202,1204,1206,1208,1210,1212,1215],{"class":444,"line":758},[442,1181,1182],{"class":497},"    save",[442,1184,562],{"class":452},[442,1186,1187],{"class":452}," (",[442,1189,1190],{"class":565},"h",[442,1192,831],{"class":452},[442,1194,570],{"class":569},[442,1196,1133],{"class":456},[442,1198,489],{"class":452},[442,1200,1201],{"class":497},"writeFile",[442,1203,501],{"class":456},[442,1205,504],{"class":452},[442,1207,1145],{"class":469},[442,1209,504],{"class":452},[442,1211,512],{"class":452},[442,1213,1214],{"class":456}," h)",[442,1216,598],{"class":452},[442,1218,1219],{"class":444,"line":787},[442,1220,1221],{"class":452},"  },\n",[442,1223,1224,1226],{"class":444,"line":836},[442,1225,640],{"class":452},[442,1227,897],{"class":456},[399,1229,900,1230,1233],{},[403,1231,1232],{},"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.",[1235,1236],"hash-chain-tamper",{},[1238,1239,1240,1241,1244,1245,1248,1249,489],"note",{},"A CLI to walk and verify the chain (",[403,1242,1243],{},"evlog audit verify",") is on the roadmap. Until then, validate by recomputing the hashes of stored events and comparing each ",[403,1246,1247],{},"prevHash"," against the previous event's ",[403,1250,1251],{},"hash",[1253,1254,1255],"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":438,"searchDepth":476,"depth":476,"links":1257},[1258,1259,1260],{"id":418,"depth":476,"text":421},{"id":664,"depth":476,"text":667},{"id":413,"depth":476,"text":908,"children":1261},[1262,1263],{"id":992,"depth":483,"text":993},{"id":1074,"depth":483,"text":1075},"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",[1267,1270],{"label":142,"icon":145,"to":143,"color":1268,"variant":1269},"neutral","subtle",{"label":152,"icon":129,"to":153,"color":1268,"variant":1269},{},{"title":147,"icon":150},{"title":394,"description":1264},"_3JRqd31dDWZXAN9m-j4Ikhyg3JwAr_LT4cmpgR6ppw",[1276,1278],{"title":142,"path":143,"stem":144,"description":1277,"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":1279,"icon":129,"children":-1},"Integrity, redact presets, GDPR vs append-only, retention windows, and the most common pitfalls when shipping audit logs to production.",1778106401798]