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