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