[{"data":1,"prerenderedAt":2401},["ShallowReactive",2],{"navigation_docs":3,"-use-cases-audit-recipes":533,"-use-cases-audit-recipes-surround":2396},[4,29,76,122,304,436,495],{"title":5,"path":6,"stem":7,"children":8,"page":28},"Start","\u002Fstart","1.start",[9,13,18,23],{"title":10,"path":11,"stem":12},"Introduction","\u002Fstart\u002Fintroduction","1.start\u002F1.introduction",{"title":14,"path":15,"stem":16,"icon":17},"Why start with evlog","\u002Fstart\u002Fwhy-evlog","1.start\u002F2.why-evlog","i-lucide-rocket",{"title":19,"path":20,"stem":21,"icon":22},"Installation","\u002Fstart\u002Finstallation","1.start\u002F3.installation","i-lucide-download",{"title":24,"path":25,"stem":26,"icon":27},"Quick Start","\u002Fstart\u002Fquick-start","1.start\u002F4.quick-start","i-lucide-zap",false,{"title":30,"path":31,"stem":32,"children":33,"page":28},"Learn","\u002Flearn","2.learn",[34,38,43,48,53,58,62,67,72],{"title":35,"path":36,"stem":37},"Learn evlog","\u002Flearn\u002Foverview","2.learn\u002F0.overview",{"title":39,"path":40,"stem":41,"icon":42},"Simple Logging","\u002Flearn\u002Fsimple-logging","2.learn\u002F1.simple-logging","i-lucide-terminal",{"title":44,"path":45,"stem":46,"icon":47},"Wide Events","\u002Flearn\u002Fwide-events","2.learn\u002F2.wide-events","i-lucide-layers",{"title":49,"path":50,"stem":51,"icon":52},"Structured Errors","\u002Flearn\u002Fstructured-errors","2.learn\u002F3.structured-errors","i-lucide-shield-alert",{"title":54,"path":55,"stem":56,"icon":57},"Lifecycle","\u002Flearn\u002Flifecycle","2.learn\u002F4.lifecycle","i-lucide-arrow-right-left",{"title":59,"path":60,"stem":61},"Sampling","\u002Flearn\u002Fsampling","2.learn\u002F5.sampling",{"title":63,"path":64,"stem":65,"icon":66},"Auto-Redaction","\u002Flearn\u002Fredaction","2.learn\u002F6.redaction","i-lucide-eye-off",{"title":68,"path":69,"stem":70,"icon":71},"Typed Fields","\u002Flearn\u002Ftyped-fields","2.learn\u002F7.typed-fields","i-simple-icons-typescript",{"title":73,"path":74,"stem":75},"Catalogs","\u002Flearn\u002Fcatalogs","2.learn\u002F8.catalogs",{"title":77,"path":78,"stem":79,"children":80,"page":28},"CLI","\u002Fcli","3.cli",[81,85,90,95,99,103,108,113,118],{"title":82,"path":83,"stem":84},"evlog CLI","\u002Fcli\u002Foverview","3.cli\u002F0.overview",{"title":86,"path":87,"stem":88,"icon":89},"init","\u002Fcli\u002Finit","3.cli\u002F1.init","i-lucide-wand-sparkles",{"title":91,"path":92,"stem":93,"icon":94},"map","\u002Fcli\u002Fmap","3.cli\u002F2.map","i-lucide-radar",{"title":96,"path":97,"stem":98},"Map rules","\u002Fcli\u002Frules","3.cli\u002F3.rules",{"title":100,"path":101,"stem":102},"Map scoring","\u002Fcli\u002Fscoring","3.cli\u002F4.scoring",{"title":104,"path":105,"stem":106,"icon":107},"CI","\u002Fcli\u002Fci","3.cli\u002F5.ci","i-lucide-git-pull-request",{"title":109,"path":110,"stem":111,"icon":112},"doctor","\u002Fcli\u002Fdoctor","3.cli\u002F6.doctor","i-lucide-stethoscope",{"title":114,"path":115,"stem":116,"icon":117},"telemetry","\u002Fcli\u002Ftelemetry","3.cli\u002F7.telemetry","i-lucide-bar-chart-3",{"title":119,"path":120,"stem":121},"evlog agents","\u002Fcli\u002Fagents","3.cli\u002F8.agents",{"title":123,"path":124,"stem":125,"children":126,"page":28},"Integrate","\u002Fintegrate","4.integrate",[127,132,216],{"title":128,"path":129,"stem":130,"icon":131},"Overview","\u002Fintegrate\u002Foverview","4.integrate\u002F0.overview","i-lucide-plug",{"title":133,"path":134,"stem":135,"children":136,"page":28},"Adapters","\u002Fintegrate\u002Fadapters","4.integrate\u002Fadapters",[137,141,171,196],{"title":128,"path":138,"stem":139,"icon":140},"\u002Fintegrate\u002Fadapters\u002Foverview","4.integrate\u002Fadapters\u002F01.overview","i-lucide-list",{"title":142,"path":143,"stem":144,"children":145,"page":28},"Cloud","\u002Fintegrate\u002Fadapters\u002Fcloud","4.integrate\u002Fadapters\u002Fcloud",[146,151,156,161,166],{"title":147,"path":148,"stem":149,"icon":150},"Axiom","\u002Fintegrate\u002Fadapters\u002Fcloud\u002Faxiom","4.integrate\u002Fadapters\u002Fcloud\u002F01.axiom","i-custom-axiom",{"title":152,"path":153,"stem":154,"icon":155},"PostHog","\u002Fintegrate\u002Fadapters\u002Fcloud\u002Fposthog","4.integrate\u002Fadapters\u002Fcloud\u002F02.posthog","i-simple-icons-posthog",{"title":157,"path":158,"stem":159,"icon":160},"Sentry","\u002Fintegrate\u002Fadapters\u002Fcloud\u002Fsentry","4.integrate\u002Fadapters\u002Fcloud\u002F03.sentry","i-simple-icons-sentry",{"title":162,"path":163,"stem":164,"icon":165},"Better Stack","\u002Fintegrate\u002Fadapters\u002Fcloud\u002Fbetter-stack","4.integrate\u002Fadapters\u002Fcloud\u002F04.better-stack","i-simple-icons-betterstack",{"title":167,"path":168,"stem":169,"icon":170},"Datadog","\u002Fintegrate\u002Fadapters\u002Fcloud\u002Fdatadog","4.integrate\u002Fadapters\u002Fcloud\u002F05.datadog","i-simple-icons-datadog",{"title":172,"path":173,"stem":174,"children":175,"page":28},"Cloud or Self-Hosted","\u002Fintegrate\u002Fadapters\u002Fhybrid","4.integrate\u002Fadapters\u002Fhybrid",[176,181,186,191],{"title":177,"path":178,"stem":179,"icon":180},"Grafana Loki","\u002Fintegrate\u002Fadapters\u002Fhybrid\u002Floki","4.integrate\u002Fadapters\u002Fhybrid\u002F01.loki","i-simple-icons-grafana",{"title":182,"path":183,"stem":184,"icon":185},"ClickHouse","\u002Fintegrate\u002Fadapters\u002Fhybrid\u002Fclickhouse","4.integrate\u002Fadapters\u002Fhybrid\u002F02.clickhouse","i-simple-icons-clickhouse",{"title":187,"path":188,"stem":189,"icon":190},"OTLP","\u002Fintegrate\u002Fadapters\u002Fhybrid\u002Fotlp","4.integrate\u002Fadapters\u002Fhybrid\u002F03.otlp","i-simple-icons-opentelemetry",{"title":192,"path":193,"stem":194,"icon":195},"HyperDX","\u002Fintegrate\u002Fadapters\u002Fhybrid\u002Fhyperdx","4.integrate\u002Fadapters\u002Fhybrid\u002F04.hyperdx","i-custom-hyperdx",{"title":197,"path":198,"stem":199,"children":200,"page":28},"Self-Hosted","\u002Fintegrate\u002Fadapters\u002Fself-hosted","4.integrate\u002Fadapters\u002Fself-hosted",[201,206,211],{"title":202,"path":203,"stem":204,"icon":205},"File System","\u002Fintegrate\u002Fadapters\u002Fself-hosted\u002Ffs","4.integrate\u002Fadapters\u002Fself-hosted\u002F01.fs","i-lucide-hard-drive",{"title":207,"path":208,"stem":209,"icon":210},"NuxtHub","\u002Fintegrate\u002Fadapters\u002Fself-hosted\u002Fnuxthub","4.integrate\u002Fadapters\u002Fself-hosted\u002F02.nuxthub","i-simple-icons-nuxt",{"title":212,"path":213,"stem":214,"icon":215},"Memory","\u002Fintegrate\u002Fadapters\u002Fself-hosted\u002Fmemory","4.integrate\u002Fadapters\u002Fself-hosted\u002F03.memory","i-lucide-cpu",{"title":217,"path":218,"stem":219,"children":220,"page":28},"Frameworks","\u002Fintegrate\u002Fframeworks","4.integrate\u002Fframeworks",[221,225,230,235,240,245,250,255,260,265,270,275,280,285,289,294,299],{"title":128,"path":222,"stem":223,"icon":224},"\u002Fintegrate\u002Fframeworks\u002Foverview","4.integrate\u002Fframeworks\u002F00.overview","i-lucide-layout-grid",{"title":226,"path":227,"stem":228,"icon":229},"Nuxt","\u002Fintegrate\u002Fframeworks\u002Fnuxt","4.integrate\u002Fframeworks\u002F01.nuxt","i-simple-icons-nuxtdotjs",{"title":231,"path":232,"stem":233,"icon":234},"Next.js","\u002Fintegrate\u002Fframeworks\u002Fnextjs","4.integrate\u002Fframeworks\u002F02.nextjs","i-simple-icons-nextdotjs",{"title":236,"path":237,"stem":238,"icon":239},"SvelteKit","\u002Fintegrate\u002Fframeworks\u002Fsveltekit","4.integrate\u002Fframeworks\u002F03.sveltekit","i-simple-icons-svelte",{"title":241,"path":242,"stem":243,"icon":244},"Nitro","\u002Fintegrate\u002Fframeworks\u002Fnitro","4.integrate\u002Fframeworks\u002F04.nitro","i-custom-nitro",{"title":246,"path":247,"stem":248,"icon":249},"TanStack Start","\u002Fintegrate\u002Fframeworks\u002Ftanstack-start","4.integrate\u002Fframeworks\u002F05.tanstack-start","i-custom-tanstack",{"title":251,"path":252,"stem":253,"icon":254},"NestJS","\u002Fintegrate\u002Fframeworks\u002Fnestjs","4.integrate\u002Fframeworks\u002F06.nestjs","i-simple-icons-nestjs",{"title":256,"path":257,"stem":258,"icon":259},"Express","\u002Fintegrate\u002Fframeworks\u002Fexpress","4.integrate\u002Fframeworks\u002F07.express","i-simple-icons-express",{"title":261,"path":262,"stem":263,"icon":264},"Hono","\u002Fintegrate\u002Fframeworks\u002Fhono","4.integrate\u002Fframeworks\u002F08.hono","i-simple-icons-hono",{"title":266,"path":267,"stem":268,"icon":269},"Fastify","\u002Fintegrate\u002Fframeworks\u002Ffastify","4.integrate\u002Fframeworks\u002F09.fastify","i-simple-icons-fastify",{"title":271,"path":272,"stem":273,"icon":274},"Elysia","\u002Fintegrate\u002Fframeworks\u002Felysia","4.integrate\u002Fframeworks\u002F10.elysia","i-custom-elysia",{"title":276,"path":277,"stem":278,"icon":279},"React Router","\u002Fintegrate\u002Fframeworks\u002Freact-router","4.integrate\u002Fframeworks\u002F11.react-router","i-custom-reactrouter",{"title":281,"path":282,"stem":283,"icon":284},"Cloudflare Workers","\u002Fintegrate\u002Fframeworks\u002Fcloudflare-workers","4.integrate\u002Fframeworks\u002F12.cloudflare-workers","i-simple-icons-cloudflare",{"title":286,"path":287,"stem":288,"icon":71},"Standalone","\u002Fintegrate\u002Fframeworks\u002Fstandalone","4.integrate\u002Fframeworks\u002F13.standalone",{"title":290,"path":291,"stem":292,"icon":293},"Astro","\u002Fintegrate\u002Fframeworks\u002Fastro","4.integrate\u002Fframeworks\u002F14.astro","i-simple-icons-astro",{"title":295,"path":296,"stem":297,"icon":298},"oRPC","\u002Fintegrate\u002Fframeworks\u002Forpc","4.integrate\u002Fframeworks\u002F15.orpc","i-lucide-network",{"title":300,"path":301,"stem":302,"icon":303},"AWS Lambda","\u002Fintegrate\u002Fframeworks\u002Faws-lambda","4.integrate\u002Fframeworks\u002F16.aws-lambda","i-custom-lambda",{"title":305,"path":306,"stem":307,"children":308,"page":28},"Use Cases","\u002Fuse-cases","5.use-cases",[309,312,317,346,374,407,427,432],{"title":305,"path":310,"stem":311},"\u002Fuse-cases\u002Foverview","5.use-cases\u002F0.overview",{"title":313,"path":314,"stem":315,"icon":316},"Client Logging","\u002Fuse-cases\u002Fclient-logging","5.use-cases\u002F1.client-logging","i-lucide-monitor",{"title":318,"icon":319,"path":320,"stem":321,"children":322,"page":28},"AI SDK","i-simple-icons-vercel","\u002Fuse-cases\u002Fai-sdk","5.use-cases\u002F2.ai-sdk",[323,326,331,336,341],{"title":128,"path":324,"stem":325,"icon":140},"\u002Fuse-cases\u002Fai-sdk\u002Foverview","5.use-cases\u002F2.ai-sdk\u002F01.overview",{"title":327,"path":328,"stem":329,"icon":330},"Usage","\u002Fuse-cases\u002Fai-sdk\u002Fusage","5.use-cases\u002F2.ai-sdk\u002F02.usage","i-lucide-code",{"title":332,"path":333,"stem":334,"icon":335},"Options","\u002Fuse-cases\u002Fai-sdk\u002Foptions","5.use-cases\u002F2.ai-sdk\u002F03.options","i-lucide-sliders",{"title":337,"path":338,"stem":339,"icon":340},"Metadata","\u002Fuse-cases\u002Fai-sdk\u002Fmetadata","5.use-cases\u002F2.ai-sdk\u002F04.metadata","i-lucide-database",{"title":342,"path":343,"stem":344,"icon":345},"Telemetry","\u002Fuse-cases\u002Fai-sdk\u002Ftelemetry","5.use-cases\u002F2.ai-sdk\u002F05.telemetry","i-lucide-activity",{"title":347,"icon":348,"path":349,"stem":350,"children":351,"page":28},"Better Auth","i-simple-icons-betterauth","\u002Fuse-cases\u002Fbetter-auth","5.use-cases\u002F3.better-auth",[352,355,360,365,369],{"title":128,"path":353,"stem":354,"icon":140},"\u002Fuse-cases\u002Fbetter-auth\u002Foverview","5.use-cases\u002F3.better-auth\u002F01.overview",{"title":356,"path":357,"stem":358,"icon":359},"Identify User","\u002Fuse-cases\u002Fbetter-auth\u002Fidentify-user","5.use-cases\u002F3.better-auth\u002F02.identify-user","i-lucide-user-check",{"title":361,"path":362,"stem":363,"icon":364},"Middleware","\u002Fuse-cases\u002Fbetter-auth\u002Fmiddleware","5.use-cases\u002F3.better-auth\u002F03.middleware","i-lucide-shield",{"title":366,"path":367,"stem":368,"icon":316},"Client Sync","\u002Fuse-cases\u002Fbetter-auth\u002Fclient-sync","5.use-cases\u002F3.better-auth\u002F04.client-sync",{"title":370,"path":371,"stem":372,"icon":373},"Performance","\u002Fuse-cases\u002Fbetter-auth\u002Fperformance","5.use-cases\u002F3.better-auth\u002F05.performance","i-lucide-gauge",{"title":375,"icon":376,"path":377,"stem":378,"children":379,"page":28},"Audit Logs","i-lucide-shield-check","\u002Fuse-cases\u002Faudit","5.use-cases\u002F4.audit",[380,383,388,393,398,402],{"title":128,"path":381,"stem":382,"icon":140},"\u002Fuse-cases\u002Faudit\u002Foverview","5.use-cases\u002F4.audit\u002F01.overview",{"title":384,"path":385,"stem":386,"icon":387},"Schema","\u002Fuse-cases\u002Faudit\u002Fschema","5.use-cases\u002F4.audit\u002F02.schema","i-lucide-file-text",{"title":389,"path":390,"stem":391,"icon":392},"Recording","\u002Fuse-cases\u002Faudit\u002Frecording","5.use-cases\u002F4.audit\u002F03.recording","i-lucide-pen-line",{"title":394,"path":395,"stem":396,"icon":397},"Drains","\u002Fuse-cases\u002Faudit\u002Fpipeline","5.use-cases\u002F4.audit\u002F04.pipeline","i-lucide-link",{"title":399,"path":400,"stem":401,"icon":376},"Compliance","\u002Fuse-cases\u002Faudit\u002Fcompliance","5.use-cases\u002F4.audit\u002F05.compliance",{"title":403,"path":404,"stem":405,"icon":406},"Recipes","\u002Fuse-cases\u002Faudit\u002Frecipes","5.use-cases\u002F4.audit\u002F06.recipes","i-lucide-book-open",{"title":342,"icon":373,"path":408,"stem":409,"children":410,"page":28},"\u002Fuse-cases\u002Ftelemetry","5.use-cases\u002F4.telemetry",[411,414,419,423],{"title":128,"path":412,"stem":413,"icon":140},"\u002Fuse-cases\u002Ftelemetry\u002Foverview","5.use-cases\u002F4.telemetry\u002F01.overview",{"title":415,"path":416,"stem":417,"icon":418},"Setup","\u002Fuse-cases\u002Ftelemetry\u002Fsetup","5.use-cases\u002F4.telemetry\u002F02.setup","i-lucide-wrench",{"title":420,"path":421,"stem":422},"Telemetry Ingest","\u002Fuse-cases\u002Ftelemetry\u002Fingest","5.use-cases\u002F4.telemetry\u002F03.ingest",{"title":424,"path":425,"stem":426,"icon":406},"Reference","\u002Fuse-cases\u002Ftelemetry\u002Freference","5.use-cases\u002F4.telemetry\u002F04.reference",{"title":428,"path":429,"stem":430,"icon":431},"Enrichers","\u002Fuse-cases\u002Fenrichers","5.use-cases\u002F5.enrichers","i-lucide-sparkles",{"title":433,"path":434,"stem":435},"eve","\u002Fuse-cases\u002Feve","5.use-cases\u002F5.eve",{"title":437,"path":438,"stem":439,"children":440,"page":28},"Extend","\u002Fextend","6.extend",[441,445,450,455,459,464,468,472,476,481,486,491],{"title":128,"path":442,"stem":443,"icon":444},"\u002Fextend\u002Foverview","6.extend\u002F0.overview","i-lucide-blocks",{"title":446,"path":447,"stem":448,"icon":449},"Stream","\u002Fextend\u002Fstream","6.extend\u002F1.stream","i-lucide-radio-tower",{"title":451,"path":452,"stem":453,"icon":454},"Custom framework","\u002Fextend\u002Fcustom-framework","6.extend\u002F10.custom-framework","i-lucide-puzzle",{"title":456,"path":457,"stem":458,"icon":449},"Diagnostics channel","\u002Fextend\u002Fdiagnostics-channel","6.extend\u002F11.diagnostics-channel",{"title":460,"path":461,"stem":462,"icon":463},"FS reader","\u002Fextend\u002Ffs-reader","6.extend\u002F2.fs-reader","i-lucide-folder-search",{"title":403,"path":465,"stem":466,"icon":467},"\u002Fextend\u002Fconsumer-recipes","6.extend\u002F3.consumer-recipes","i-lucide-chef-hat",{"title":469,"path":470,"stem":471},"Plugins","\u002Fextend\u002Fplugins","6.extend\u002F4.plugins",{"title":473,"path":474,"stem":475,"icon":431},"Custom enrichers","\u002Fextend\u002Fcustom-enrichers","6.extend\u002F5.custom-enrichers",{"title":477,"path":478,"stem":479,"icon":480},"Tail sampling","\u002Fextend\u002Ftail-sampling","6.extend\u002F6.tail-sampling","i-lucide-filter",{"title":482,"path":483,"stem":484,"icon":485},"Identity headers","\u002Fextend\u002Fidentity-headers","6.extend\u002F7.identity-headers","i-lucide-fingerprint",{"title":487,"path":488,"stem":489,"icon":490},"Custom drains","\u002Fextend\u002Fcustom-drains","6.extend\u002F8.custom-drains","i-lucide-share-2",{"title":492,"path":493,"stem":494},"Drain Pipeline","\u002Fextend\u002Fdrain-pipeline","6.extend\u002F9.drain-pipeline",{"title":424,"path":496,"stem":497,"children":498,"page":28},"\u002Freference","7.reference",[499,503,508,511,516,520,525,529],{"title":128,"path":500,"stem":501,"icon":502},"\u002Freference\u002Foverview","7.reference\u002F0.overview","i-lucide-book-marked",{"title":504,"path":505,"stem":506,"icon":507},"Configuration","\u002Freference\u002Fconfiguration","7.reference\u002F1.configuration","i-lucide-settings",{"title":370,"path":509,"stem":510,"icon":373},"\u002Freference\u002Fperformance","7.reference\u002F2.performance",{"title":512,"path":513,"stem":514,"icon":515},"Vite Plugin","\u002Freference\u002Fvite-plugin","7.reference\u002F3.vite-plugin","i-custom-vite",{"title":517,"path":518,"stem":519,"icon":376},"Best Practices","\u002Freference\u002Fbest-practices","7.reference\u002F4.best-practices",{"title":521,"path":522,"stem":523,"icon":524},"vs Other Loggers","\u002Freference\u002Fvs-other-loggers","7.reference\u002F5.vs-other-loggers","i-lucide-scale",{"title":526,"path":527,"stem":528,"icon":431},"Agent Skills","\u002Freference\u002Fagent-skills","7.reference\u002F6.agent-skills",{"title":530,"path":531,"stem":532},"Log cost","\u002Freference\u002Fcost","7.reference\u002F7.cost",{"id":534,"title":535,"body":536,"description":2385,"extension":2386,"links":2387,"meta":2392,"navigation":2393,"path":404,"seo":2394,"stem":405,"__hash__":2395},"docs\u002F5.use-cases\u002F4.audit\u002F06.recipes.md","Recipes & Reference",{"type":537,"value":538,"toc":2378},"minimark",[539,556,561,1169,1178,1182,1481,1484,1488,1863,1873,1877,1893,2139,2153,2164,2168,2368,2374],[540,541,542,543,547,548,551,552,555],"p",{},"Pick the recipe that matches your drain, drop it in, and you have a tamper-evident audit log. Each recipe composes the same primitives (",[544,545,546],"code",{},"auditOnly",", ",[544,549,550],{},"signed",", optional ",[544,553,554],{},"await: true",") over different drains.",[557,558,560],"h2",{"id":559},"audit-logs-on-disk","Audit logs on disk",[562,563,564,770],"code-group",{},[565,566,572],"pre",{"className":567,"code":568,"filename":569,"language":570,"meta":571,"style":571},"language-typescript shiki shiki-themes material-theme-lighter material-theme material-theme-palenight","import { auditOnly, signed } from 'evlog'\nimport { createFsDrain } from 'evlog\u002Ffs'\n\nnitro.hooks.hook('evlog:drain', auditOnly(\n  signed(createFsDrain({ dir: '.audit', maxFiles: 30 }), { strategy: 'hash-chain' }),\n  { await: true },\n))\n","Input — server\u002Fplugins\u002Fevlog.ts","typescript","",[544,573,574,613,634,641,677,746,764],{"__ignoreMap":571},[575,576,579,583,587,591,594,597,600,603,606,610],"span",{"class":577,"line":578},"line",1,[575,580,582],{"class":581},"s7zQu","import",[575,584,586],{"class":585},"sMK4o"," {",[575,588,590],{"class":589},"sTEyZ"," auditOnly",[575,592,593],{"class":585},",",[575,595,596],{"class":589}," signed",[575,598,599],{"class":585}," }",[575,601,602],{"class":581}," from",[575,604,605],{"class":585}," '",[575,607,609],{"class":608},"sfazB","evlog",[575,611,612],{"class":585},"'\n",[575,614,616,618,620,623,625,627,629,632],{"class":577,"line":615},2,[575,617,582],{"class":581},[575,619,586],{"class":585},[575,621,622],{"class":589}," createFsDrain",[575,624,599],{"class":585},[575,626,602],{"class":581},[575,628,605],{"class":585},[575,630,631],{"class":608},"evlog\u002Ffs",[575,633,612],{"class":585},[575,635,637],{"class":577,"line":636},3,[575,638,640],{"emptyLinePlaceholder":639},true,"\n",[575,642,644,647,650,653,655,659,662,665,668,670,672,674],{"class":577,"line":643},4,[575,645,646],{"class":589},"nitro",[575,648,649],{"class":585},".",[575,651,652],{"class":589},"hooks",[575,654,649],{"class":585},[575,656,658],{"class":657},"s2Zo4","hook",[575,660,661],{"class":589},"(",[575,663,664],{"class":585},"'",[575,666,667],{"class":608},"evlog:drain",[575,669,664],{"class":585},[575,671,593],{"class":585},[575,673,590],{"class":657},[575,675,676],{"class":589},"(\n",[575,678,680,683,685,688,690,693,697,700,702,705,707,709,712,714,718,720,723,725,727,730,732,734,737,739,741,743],{"class":577,"line":679},5,[575,681,682],{"class":657},"  signed",[575,684,661],{"class":589},[575,686,687],{"class":657},"createFsDrain",[575,689,661],{"class":589},[575,691,692],{"class":585},"{",[575,694,696],{"class":695},"swJcz"," dir",[575,698,699],{"class":585},":",[575,701,605],{"class":585},[575,703,704],{"class":608},".audit",[575,706,664],{"class":585},[575,708,593],{"class":585},[575,710,711],{"class":695}," maxFiles",[575,713,699],{"class":585},[575,715,717],{"class":716},"sbssI"," 30",[575,719,599],{"class":585},[575,721,722],{"class":589},")",[575,724,593],{"class":585},[575,726,586],{"class":585},[575,728,729],{"class":695}," strategy",[575,731,699],{"class":585},[575,733,605],{"class":585},[575,735,736],{"class":608},"hash-chain",[575,738,664],{"class":585},[575,740,599],{"class":585},[575,742,722],{"class":589},[575,744,745],{"class":585},",\n",[575,747,749,752,755,757,761],{"class":577,"line":748},6,[575,750,751],{"class":585},"  {",[575,753,754],{"class":695}," await",[575,756,699],{"class":585},[575,758,760],{"class":759},"sfNiH"," true",[575,762,763],{"class":585}," },\n",[575,765,767],{"class":577,"line":766},7,[575,768,769],{"class":589},"))\n",[565,771,776],{"className":772,"code":773,"filename":774,"language":775,"meta":571,"style":571},"language-jsonl shiki shiki-themes material-theme-lighter material-theme material-theme-palenight","{\"audit\":{\"action\":\"invoice.refund\",\"actor\":{\"type\":\"user\",\"id\":\"usr_42\"},\"target\":{\"type\":\"invoice\",\"id\":\"inv_889\"},\"outcome\":\"success\",\"version\":1,\"idempotencyKey\":\"ak_8f3c4b2a1e5d6f7c\",\"prevHash\":null,\"hash\":\"3f2c8e1a...\"}}\n{\"audit\":{\"action\":\"user.update\",\"actor\":{\"type\":\"user\",\"id\":\"usr_42\"},\"target\":{\"type\":\"user\",\"id\":\"usr_99\"},\"outcome\":\"success\",\"version\":1,\"idempotencyKey\":\"ak_5e7d8f9a0b1c2d3e\",\"prevHash\":\"3f2c8e1a...\",\"hash\":\"9a1b4d7c...\"}}\n","Output — .audit\u002F2026-04-24.ndjson","jsonl",[544,777,778,981],{"__ignoreMap":571},[575,779,780,782,785,789,791,794,796,800,802,804,806,809,811,813,815,818,820,822,824,827,829,831,833,836,838,840,842,845,847,849,851,854,856,859,861,864,866,868,870,872,874,876,878,881,883,885,887,889,891,893,895,898,900,902,904,907,909,911,913,916,918,920,922,925,927,929,932,934,936,939,941,943,945,948,950,952,954,957,959,962,964,967,969,971,973,976,978],{"class":577,"line":578},[575,781,692],{"class":585},[575,783,784],{"class":585},"\"",[575,786,788],{"class":787},"spNyl","audit",[575,790,784],{"class":585},[575,792,793],{"class":585},":{",[575,795,784],{"class":585},[575,797,799],{"class":798},"sBMFI","action",[575,801,784],{"class":585},[575,803,699],{"class":585},[575,805,784],{"class":585},[575,807,808],{"class":608},"invoice.refund",[575,810,784],{"class":585},[575,812,593],{"class":585},[575,814,784],{"class":585},[575,816,817],{"class":798},"actor",[575,819,784],{"class":585},[575,821,793],{"class":585},[575,823,784],{"class":585},[575,825,826],{"class":716},"type",[575,828,784],{"class":585},[575,830,699],{"class":585},[575,832,784],{"class":585},[575,834,835],{"class":608},"user",[575,837,784],{"class":585},[575,839,593],{"class":585},[575,841,784],{"class":585},[575,843,844],{"class":716},"id",[575,846,784],{"class":585},[575,848,699],{"class":585},[575,850,784],{"class":585},[575,852,853],{"class":608},"usr_42",[575,855,784],{"class":585},[575,857,858],{"class":585},"},",[575,860,784],{"class":585},[575,862,863],{"class":798},"target",[575,865,784],{"class":585},[575,867,793],{"class":585},[575,869,784],{"class":585},[575,871,826],{"class":716},[575,873,784],{"class":585},[575,875,699],{"class":585},[575,877,784],{"class":585},[575,879,880],{"class":608},"invoice",[575,882,784],{"class":585},[575,884,593],{"class":585},[575,886,784],{"class":585},[575,888,844],{"class":716},[575,890,784],{"class":585},[575,892,699],{"class":585},[575,894,784],{"class":585},[575,896,897],{"class":608},"inv_889",[575,899,784],{"class":585},[575,901,858],{"class":585},[575,903,784],{"class":585},[575,905,906],{"class":798},"outcome",[575,908,784],{"class":585},[575,910,699],{"class":585},[575,912,784],{"class":585},[575,914,915],{"class":608},"success",[575,917,784],{"class":585},[575,919,593],{"class":585},[575,921,784],{"class":585},[575,923,924],{"class":798},"version",[575,926,784],{"class":585},[575,928,699],{"class":585},[575,930,931],{"class":716},"1",[575,933,593],{"class":585},[575,935,784],{"class":585},[575,937,938],{"class":798},"idempotencyKey",[575,940,784],{"class":585},[575,942,699],{"class":585},[575,944,784],{"class":585},[575,946,947],{"class":608},"ak_8f3c4b2a1e5d6f7c",[575,949,784],{"class":585},[575,951,593],{"class":585},[575,953,784],{"class":585},[575,955,956],{"class":798},"prevHash",[575,958,784],{"class":585},[575,960,961],{"class":585},":null,",[575,963,784],{"class":585},[575,965,966],{"class":798},"hash",[575,968,784],{"class":585},[575,970,699],{"class":585},[575,972,784],{"class":585},[575,974,975],{"class":608},"3f2c8e1a...",[575,977,784],{"class":585},[575,979,980],{"class":585},"}}\n",[575,982,983,985,987,989,991,993,995,997,999,1001,1003,1006,1008,1010,1012,1014,1016,1018,1020,1022,1024,1026,1028,1030,1032,1034,1036,1038,1040,1042,1044,1046,1048,1050,1052,1054,1056,1058,1060,1062,1064,1066,1068,1070,1072,1074,1076,1078,1080,1082,1084,1087,1089,1091,1093,1095,1097,1099,1101,1103,1105,1107,1109,1111,1113,1115,1117,1119,1121,1123,1125,1127,1129,1132,1134,1136,1138,1140,1142,1144,1146,1148,1150,1152,1154,1156,1158,1160,1162,1165,1167],{"class":577,"line":615},[575,984,692],{"class":585},[575,986,784],{"class":585},[575,988,788],{"class":787},[575,990,784],{"class":585},[575,992,793],{"class":585},[575,994,784],{"class":585},[575,996,799],{"class":798},[575,998,784],{"class":585},[575,1000,699],{"class":585},[575,1002,784],{"class":585},[575,1004,1005],{"class":608},"user.update",[575,1007,784],{"class":585},[575,1009,593],{"class":585},[575,1011,784],{"class":585},[575,1013,817],{"class":798},[575,1015,784],{"class":585},[575,1017,793],{"class":585},[575,1019,784],{"class":585},[575,1021,826],{"class":716},[575,1023,784],{"class":585},[575,1025,699],{"class":585},[575,1027,784],{"class":585},[575,1029,835],{"class":608},[575,1031,784],{"class":585},[575,1033,593],{"class":585},[575,1035,784],{"class":585},[575,1037,844],{"class":716},[575,1039,784],{"class":585},[575,1041,699],{"class":585},[575,1043,784],{"class":585},[575,1045,853],{"class":608},[575,1047,784],{"class":585},[575,1049,858],{"class":585},[575,1051,784],{"class":585},[575,1053,863],{"class":798},[575,1055,784],{"class":585},[575,1057,793],{"class":585},[575,1059,784],{"class":585},[575,1061,826],{"class":716},[575,1063,784],{"class":585},[575,1065,699],{"class":585},[575,1067,784],{"class":585},[575,1069,835],{"class":608},[575,1071,784],{"class":585},[575,1073,593],{"class":585},[575,1075,784],{"class":585},[575,1077,844],{"class":716},[575,1079,784],{"class":585},[575,1081,699],{"class":585},[575,1083,784],{"class":585},[575,1085,1086],{"class":608},"usr_99",[575,1088,784],{"class":585},[575,1090,858],{"class":585},[575,1092,784],{"class":585},[575,1094,906],{"class":798},[575,1096,784],{"class":585},[575,1098,699],{"class":585},[575,1100,784],{"class":585},[575,1102,915],{"class":608},[575,1104,784],{"class":585},[575,1106,593],{"class":585},[575,1108,784],{"class":585},[575,1110,924],{"class":798},[575,1112,784],{"class":585},[575,1114,699],{"class":585},[575,1116,931],{"class":716},[575,1118,593],{"class":585},[575,1120,784],{"class":585},[575,1122,938],{"class":798},[575,1124,784],{"class":585},[575,1126,699],{"class":585},[575,1128,784],{"class":585},[575,1130,1131],{"class":608},"ak_5e7d8f9a0b1c2d3e",[575,1133,784],{"class":585},[575,1135,593],{"class":585},[575,1137,784],{"class":585},[575,1139,956],{"class":798},[575,1141,784],{"class":585},[575,1143,699],{"class":585},[575,1145,784],{"class":585},[575,1147,975],{"class":608},[575,1149,784],{"class":585},[575,1151,593],{"class":585},[575,1153,784],{"class":585},[575,1155,966],{"class":798},[575,1157,784],{"class":585},[575,1159,699],{"class":585},[575,1161,784],{"class":585},[575,1163,1164],{"class":608},"9a1b4d7c...",[575,1166,784],{"class":585},[575,1168,980],{"class":585},[540,1170,1171,1172,1174,1175,1177],{},"Each line's ",[544,1173,956],{}," matches the previous line's ",[544,1176,966],{},". Tampering with any row breaks the chain forward of that point, and a verifier replays the hashes and reports the first mismatch.",[557,1179,1181],{"id":1180},"audit-logs-to-a-dedicated-axiom-dataset","Audit logs to a dedicated Axiom dataset",[562,1183,1184,1351,1419],{},[565,1185,1187],{"className":567,"code":1186,"filename":569,"language":570,"meta":571,"style":571},"import { auditOnly } from 'evlog'\nimport { createAxiomDrain } from 'evlog\u002Faxiom'\n\nnitro.hooks.hook('evlog:drain', createAxiomDrain({ dataset: 'logs' }))\nnitro.hooks.hook('evlog:drain', auditOnly(\n  createAxiomDrain({ dataset: 'audit', apiKey: process.env.AXIOM_AUDIT_API_KEY }),\n))\n",[544,1188,1189,1207,1227,1231,1275,1301,1347],{"__ignoreMap":571},[575,1190,1191,1193,1195,1197,1199,1201,1203,1205],{"class":577,"line":578},[575,1192,582],{"class":581},[575,1194,586],{"class":585},[575,1196,590],{"class":589},[575,1198,599],{"class":585},[575,1200,602],{"class":581},[575,1202,605],{"class":585},[575,1204,609],{"class":608},[575,1206,612],{"class":585},[575,1208,1209,1211,1213,1216,1218,1220,1222,1225],{"class":577,"line":615},[575,1210,582],{"class":581},[575,1212,586],{"class":585},[575,1214,1215],{"class":589}," createAxiomDrain",[575,1217,599],{"class":585},[575,1219,602],{"class":581},[575,1221,605],{"class":585},[575,1223,1224],{"class":608},"evlog\u002Faxiom",[575,1226,612],{"class":585},[575,1228,1229],{"class":577,"line":636},[575,1230,640],{"emptyLinePlaceholder":639},[575,1232,1233,1235,1237,1239,1241,1243,1245,1247,1249,1251,1253,1255,1257,1259,1262,1264,1266,1269,1271,1273],{"class":577,"line":643},[575,1234,646],{"class":589},[575,1236,649],{"class":585},[575,1238,652],{"class":589},[575,1240,649],{"class":585},[575,1242,658],{"class":657},[575,1244,661],{"class":589},[575,1246,664],{"class":585},[575,1248,667],{"class":608},[575,1250,664],{"class":585},[575,1252,593],{"class":585},[575,1254,1215],{"class":657},[575,1256,661],{"class":589},[575,1258,692],{"class":585},[575,1260,1261],{"class":695}," dataset",[575,1263,699],{"class":585},[575,1265,605],{"class":585},[575,1267,1268],{"class":608},"logs",[575,1270,664],{"class":585},[575,1272,599],{"class":585},[575,1274,769],{"class":589},[575,1276,1277,1279,1281,1283,1285,1287,1289,1291,1293,1295,1297,1299],{"class":577,"line":679},[575,1278,646],{"class":589},[575,1280,649],{"class":585},[575,1282,652],{"class":589},[575,1284,649],{"class":585},[575,1286,658],{"class":657},[575,1288,661],{"class":589},[575,1290,664],{"class":585},[575,1292,667],{"class":608},[575,1294,664],{"class":585},[575,1296,593],{"class":585},[575,1298,590],{"class":657},[575,1300,676],{"class":589},[575,1302,1303,1306,1308,1310,1312,1314,1316,1318,1320,1322,1325,1327,1330,1332,1335,1337,1340,1343,1345],{"class":577,"line":748},[575,1304,1305],{"class":657},"  createAxiomDrain",[575,1307,661],{"class":589},[575,1309,692],{"class":585},[575,1311,1261],{"class":695},[575,1313,699],{"class":585},[575,1315,605],{"class":585},[575,1317,788],{"class":608},[575,1319,664],{"class":585},[575,1321,593],{"class":585},[575,1323,1324],{"class":695}," apiKey",[575,1326,699],{"class":585},[575,1328,1329],{"class":589}," process",[575,1331,649],{"class":585},[575,1333,1334],{"class":589},"env",[575,1336,649],{"class":585},[575,1338,1339],{"class":589},"AXIOM_AUDIT_API_KEY ",[575,1341,1342],{"class":585},"}",[575,1344,722],{"class":589},[575,1346,745],{"class":585},[575,1348,1349],{"class":577,"line":766},[575,1350,769],{"class":589},[565,1352,1357],{"className":1353,"code":1354,"filename":1355,"language":1356,"meta":571,"style":571},"language-kusto shiki shiki-themes material-theme-lighter material-theme material-theme-palenight","['audit']\n| where audit.action == \"invoice.refund\"\n| summarize count() by audit.outcome, bin(_time, 1h)\n","Output — Axiom query","kusto",[544,1358,1359,1373,1391],{"__ignoreMap":571},[575,1360,1361,1364,1366,1368,1370],{"class":577,"line":578},[575,1362,1363],{"class":589},"[",[575,1365,664],{"class":585},[575,1367,788],{"class":608},[575,1369,664],{"class":585},[575,1371,1372],{"class":589},"]\n",[575,1374,1375,1378,1381,1384,1386,1388],{"class":577,"line":615},[575,1376,1377],{"class":589},"| ",[575,1379,1380],{"class":716},"where",[575,1382,1383],{"class":589}," audit.action == ",[575,1385,784],{"class":585},[575,1387,808],{"class":608},[575,1389,1390],{"class":585},"\"\n",[575,1392,1393,1395,1398,1401,1404,1407,1410,1413,1416],{"class":577,"line":636},[575,1394,1377],{"class":589},[575,1396,1397],{"class":716},"summarize",[575,1399,1400],{"class":657}," count()",[575,1402,1403],{"class":716}," by",[575,1405,1406],{"class":589}," audit.outcome, ",[575,1408,1409],{"class":657},"bin",[575,1411,1412],{"class":589},"(_time, ",[575,1414,1415],{"class":716},"1h",[575,1417,1418],{"class":589},")\n",[565,1420,1423],{"className":1353,"code":1421,"filename":1422,"language":1356,"meta":571,"style":571},"['audit']\n| where audit.outcome == \"denied\"\n| summarize count() by audit.actor.id, audit.action\n| order by count_ desc\n","Output — denials by actor",[544,1424,1425,1437,1453,1466],{"__ignoreMap":571},[575,1426,1427,1429,1431,1433,1435],{"class":577,"line":578},[575,1428,1363],{"class":589},[575,1430,664],{"class":585},[575,1432,788],{"class":608},[575,1434,664],{"class":585},[575,1436,1372],{"class":589},[575,1438,1439,1441,1443,1446,1448,1451],{"class":577,"line":615},[575,1440,1377],{"class":589},[575,1442,1380],{"class":716},[575,1444,1445],{"class":589}," audit.outcome == ",[575,1447,784],{"class":585},[575,1449,1450],{"class":608},"denied",[575,1452,1390],{"class":585},[575,1454,1455,1457,1459,1461,1463],{"class":577,"line":636},[575,1456,1377],{"class":589},[575,1458,1397],{"class":716},[575,1460,1400],{"class":657},[575,1462,1403],{"class":716},[575,1464,1465],{"class":589}," audit.actor.id, audit.action\n",[575,1467,1468,1470,1473,1475,1478],{"class":577,"line":643},[575,1469,1377],{"class":589},[575,1471,1472],{"class":716},"order",[575,1474,1403],{"class":716},[575,1476,1477],{"class":589}," count_ ",[575,1479,1480],{"class":716},"desc\n",[540,1482,1483],{},"Splitting datasets means the audit dataset can have a longer retention (7y), tighter access controls, and a separate billing line, without touching the rest of your pipeline.",[557,1485,1487],{"id":1486},"audit-logs-in-postgres","Audit logs in Postgres",[562,1489,1490,1743],{},[565,1491,1493],{"className":567,"code":1492,"filename":569,"language":570,"meta":571,"style":571},"import { auditOnly } from 'evlog'\nimport type { DrainContext } from 'evlog'\n\nconst postgresAudit = async (ctx: DrainContext) => {\n  await db.insert(auditEvents).values({\n    id: ctx.event.audit!.idempotencyKey,\n    timestamp: new Date(ctx.event.timestamp),\n    payload: ctx.event,\n  }).onConflictDoNothing()\n}\n\nnitro.hooks.hook('evlog:drain', auditOnly(postgresAudit, { await: true }))\n",[544,1494,1495,1513,1535,1539,1572,1602,1628,1658,1674,1690,1696,1701],{"__ignoreMap":571},[575,1496,1497,1499,1501,1503,1505,1507,1509,1511],{"class":577,"line":578},[575,1498,582],{"class":581},[575,1500,586],{"class":585},[575,1502,590],{"class":589},[575,1504,599],{"class":585},[575,1506,602],{"class":581},[575,1508,605],{"class":585},[575,1510,609],{"class":608},[575,1512,612],{"class":585},[575,1514,1515,1517,1520,1522,1525,1527,1529,1531,1533],{"class":577,"line":615},[575,1516,582],{"class":581},[575,1518,1519],{"class":581}," type",[575,1521,586],{"class":585},[575,1523,1524],{"class":589}," DrainContext",[575,1526,599],{"class":585},[575,1528,602],{"class":581},[575,1530,605],{"class":585},[575,1532,609],{"class":608},[575,1534,612],{"class":585},[575,1536,1537],{"class":577,"line":636},[575,1538,640],{"emptyLinePlaceholder":639},[575,1540,1541,1544,1547,1550,1553,1556,1560,1562,1564,1566,1569],{"class":577,"line":643},[575,1542,1543],{"class":787},"const",[575,1545,1546],{"class":589}," postgresAudit ",[575,1548,1549],{"class":585},"=",[575,1551,1552],{"class":787}," async",[575,1554,1555],{"class":585}," (",[575,1557,1559],{"class":1558},"sHdIc","ctx",[575,1561,699],{"class":585},[575,1563,1524],{"class":798},[575,1565,722],{"class":585},[575,1567,1568],{"class":787}," =>",[575,1570,1571],{"class":585}," {\n",[575,1573,1574,1577,1580,1582,1585,1587,1590,1592,1594,1597,1599],{"class":577,"line":679},[575,1575,1576],{"class":581},"  await",[575,1578,1579],{"class":589}," db",[575,1581,649],{"class":585},[575,1583,1584],{"class":657},"insert",[575,1586,661],{"class":695},[575,1588,1589],{"class":589},"auditEvents",[575,1591,722],{"class":695},[575,1593,649],{"class":585},[575,1595,1596],{"class":657},"values",[575,1598,661],{"class":695},[575,1600,1601],{"class":585},"{\n",[575,1603,1604,1607,1609,1612,1614,1617,1619,1621,1624,1626],{"class":577,"line":748},[575,1605,1606],{"class":695},"    id",[575,1608,699],{"class":585},[575,1610,1611],{"class":589}," ctx",[575,1613,649],{"class":585},[575,1615,1616],{"class":589},"event",[575,1618,649],{"class":585},[575,1620,788],{"class":589},[575,1622,1623],{"class":585},"!.",[575,1625,938],{"class":589},[575,1627,745],{"class":585},[575,1629,1630,1633,1635,1638,1641,1643,1645,1647,1649,1651,1654,1656],{"class":577,"line":766},[575,1631,1632],{"class":695},"    timestamp",[575,1634,699],{"class":585},[575,1636,1637],{"class":585}," new",[575,1639,1640],{"class":657}," Date",[575,1642,661],{"class":695},[575,1644,1559],{"class":589},[575,1646,649],{"class":585},[575,1648,1616],{"class":589},[575,1650,649],{"class":585},[575,1652,1653],{"class":589},"timestamp",[575,1655,722],{"class":695},[575,1657,745],{"class":585},[575,1659,1661,1664,1666,1668,1670,1672],{"class":577,"line":1660},8,[575,1662,1663],{"class":695},"    payload",[575,1665,699],{"class":585},[575,1667,1611],{"class":589},[575,1669,649],{"class":585},[575,1671,1616],{"class":589},[575,1673,745],{"class":585},[575,1675,1677,1680,1682,1684,1687],{"class":577,"line":1676},9,[575,1678,1679],{"class":585},"  }",[575,1681,722],{"class":695},[575,1683,649],{"class":585},[575,1685,1686],{"class":657},"onConflictDoNothing",[575,1688,1689],{"class":695},"()\n",[575,1691,1693],{"class":577,"line":1692},10,[575,1694,1695],{"class":585},"}\n",[575,1697,1699],{"class":577,"line":1698},11,[575,1700,640],{"emptyLinePlaceholder":639},[575,1702,1704,1706,1708,1710,1712,1714,1716,1718,1720,1722,1724,1726,1729,1731,1733,1735,1737,1739,1741],{"class":577,"line":1703},12,[575,1705,646],{"class":589},[575,1707,649],{"class":585},[575,1709,652],{"class":589},[575,1711,649],{"class":585},[575,1713,658],{"class":657},[575,1715,661],{"class":589},[575,1717,664],{"class":585},[575,1719,667],{"class":608},[575,1721,664],{"class":585},[575,1723,593],{"class":585},[575,1725,590],{"class":657},[575,1727,1728],{"class":589},"(postgresAudit",[575,1730,593],{"class":585},[575,1732,586],{"class":585},[575,1734,754],{"class":695},[575,1736,699],{"class":585},[575,1738,760],{"class":759},[575,1740,599],{"class":585},[575,1742,769],{"class":589},[565,1744,1749],{"className":1745,"code":1746,"filename":1747,"language":1748,"meta":571,"style":571},"language-sql shiki shiki-themes material-theme-lighter material-theme material-theme-palenight","SELECT id, timestamp, payload->'audit'->>'action' AS action,\n       payload->'audit'->>'outcome' AS outcome\nFROM audit_events\nWHERE id = 'ak_8f3c4b2a1e5d6f7c';\n\n--          id          |       timestamp       |     action      | outcome\n-- ---------------------+-----------------------+-----------------+---------\n--  ak_8f3c4b2a1e5d6f7c | 2026-04-24 10:23:45.6 | invoice.refund  | success\n","Output — audit_events row","sql",[544,1750,1751,1790,1816,1824,1843,1847,1853,1858],{"__ignoreMap":571},[575,1752,1753,1756,1759,1761,1764,1767,1769,1771,1773,1776,1778,1780,1782,1785,1788],{"class":577,"line":578},[575,1754,1755],{"class":716},"SELECT",[575,1757,1758],{"class":589}," id, ",[575,1760,1653],{"class":787},[575,1762,1763],{"class":589},", payload",[575,1765,1766],{"class":585},"->",[575,1768,664],{"class":585},[575,1770,788],{"class":608},[575,1772,664],{"class":585},[575,1774,1775],{"class":585},"->>",[575,1777,664],{"class":585},[575,1779,799],{"class":608},[575,1781,664],{"class":585},[575,1783,1784],{"class":716}," AS",[575,1786,1787],{"class":716}," action",[575,1789,745],{"class":589},[575,1791,1792,1795,1797,1799,1801,1803,1805,1807,1809,1811,1813],{"class":577,"line":615},[575,1793,1794],{"class":589},"       payload",[575,1796,1766],{"class":585},[575,1798,664],{"class":585},[575,1800,788],{"class":608},[575,1802,664],{"class":585},[575,1804,1775],{"class":585},[575,1806,664],{"class":585},[575,1808,906],{"class":608},[575,1810,664],{"class":585},[575,1812,1784],{"class":716},[575,1814,1815],{"class":589}," outcome\n",[575,1817,1818,1821],{"class":577,"line":636},[575,1819,1820],{"class":716},"FROM",[575,1822,1823],{"class":589}," audit_events\n",[575,1825,1826,1829,1832,1834,1836,1838,1840],{"class":577,"line":643},[575,1827,1828],{"class":716},"WHERE",[575,1830,1831],{"class":589}," id ",[575,1833,1549],{"class":585},[575,1835,605],{"class":585},[575,1837,947],{"class":608},[575,1839,664],{"class":585},[575,1841,1842],{"class":589},";\n",[575,1844,1845],{"class":577,"line":679},[575,1846,640],{"emptyLinePlaceholder":639},[575,1848,1849],{"class":577,"line":748},[575,1850,1852],{"class":1851},"sHwdD","--          id          |       timestamp       |     action      | outcome\n",[575,1854,1855],{"class":577,"line":766},[575,1856,1857],{"class":1851},"-- ---------------------+-----------------------+-----------------+---------\n",[575,1859,1860],{"class":577,"line":1660},[575,1861,1862],{"class":1851},"--  ak_8f3c4b2a1e5d6f7c | 2026-04-24 10:23:45.6 | invoice.refund  | success\n",[540,1864,1865,1866,1868,1869,1872],{},"The deterministic ",[544,1867,938],{}," makes retries safe: duplicate inserts collapse via ",[544,1870,1871],{},"ON CONFLICT DO NOTHING",". Without it, a transient network blip during a retry would create a duplicate audit row, which is exactly what you don't want.",[557,1874,1876],{"id":1875},"test-what-you-recorded","Test what you recorded",[540,1878,1879,1882,1883,547,1886,1889,1890,699],{},[544,1880,1881],{},"mockAudit()"," captures every audit event on emit, from standalone ",[544,1884,1885],{},"audit()",[544,1887,1888],{},"log.audit()",", and ",[544,1891,1892],{},"log.set({ audit })",[565,1894,1896],{"className":567,"code":1895,"language":570,"meta":571,"style":571},"import { mockAudit } from 'evlog'\n\nit('refunds the invoice and records an audit', async () => {\n  const captured = mockAudit()\n\n  await refundInvoice({ id: 'inv_889' }, { actor: { type: 'user', id: 'u1' } })\n\n  captured.assertAudit({\n    action: 'invoice.refund',\n    target: { type: 'invoice', id: 'inv_889' },\n    outcome: 'success',\n  })\n\n  captured.restore()\n})\n",[544,1897,1898,1917,1921,1946,1961,1965,2028,2032,2046,2061,2094,2109,2115,2120,2132],{"__ignoreMap":571},[575,1899,1900,1902,1904,1907,1909,1911,1913,1915],{"class":577,"line":578},[575,1901,582],{"class":581},[575,1903,586],{"class":585},[575,1905,1906],{"class":589}," mockAudit",[575,1908,599],{"class":585},[575,1910,602],{"class":581},[575,1912,605],{"class":585},[575,1914,609],{"class":608},[575,1916,612],{"class":585},[575,1918,1919],{"class":577,"line":615},[575,1920,640],{"emptyLinePlaceholder":639},[575,1922,1923,1926,1928,1930,1933,1935,1937,1939,1942,1944],{"class":577,"line":636},[575,1924,1925],{"class":657},"it",[575,1927,661],{"class":589},[575,1929,664],{"class":585},[575,1931,1932],{"class":608},"refunds the invoice and records an audit",[575,1934,664],{"class":585},[575,1936,593],{"class":585},[575,1938,1552],{"class":787},[575,1940,1941],{"class":585}," ()",[575,1943,1568],{"class":787},[575,1945,1571],{"class":585},[575,1947,1948,1951,1954,1957,1959],{"class":577,"line":643},[575,1949,1950],{"class":787},"  const",[575,1952,1953],{"class":589}," captured",[575,1955,1956],{"class":585}," =",[575,1958,1906],{"class":657},[575,1960,1689],{"class":695},[575,1962,1963],{"class":577,"line":679},[575,1964,640],{"emptyLinePlaceholder":639},[575,1966,1967,1969,1972,1974,1976,1979,1981,1983,1985,1987,1990,1992,1995,1997,1999,2001,2003,2005,2007,2009,2011,2013,2015,2017,2020,2022,2024,2026],{"class":577,"line":748},[575,1968,1576],{"class":581},[575,1970,1971],{"class":657}," refundInvoice",[575,1973,661],{"class":695},[575,1975,692],{"class":585},[575,1977,1978],{"class":695}," id",[575,1980,699],{"class":585},[575,1982,605],{"class":585},[575,1984,897],{"class":608},[575,1986,664],{"class":585},[575,1988,1989],{"class":585}," },",[575,1991,586],{"class":585},[575,1993,1994],{"class":695}," actor",[575,1996,699],{"class":585},[575,1998,586],{"class":585},[575,2000,1519],{"class":695},[575,2002,699],{"class":585},[575,2004,605],{"class":585},[575,2006,835],{"class":608},[575,2008,664],{"class":585},[575,2010,593],{"class":585},[575,2012,1978],{"class":695},[575,2014,699],{"class":585},[575,2016,605],{"class":585},[575,2018,2019],{"class":608},"u1",[575,2021,664],{"class":585},[575,2023,599],{"class":585},[575,2025,599],{"class":585},[575,2027,1418],{"class":695},[575,2029,2030],{"class":577,"line":766},[575,2031,640],{"emptyLinePlaceholder":639},[575,2033,2034,2037,2039,2042,2044],{"class":577,"line":1660},[575,2035,2036],{"class":589},"  captured",[575,2038,649],{"class":585},[575,2040,2041],{"class":657},"assertAudit",[575,2043,661],{"class":695},[575,2045,1601],{"class":585},[575,2047,2048,2051,2053,2055,2057,2059],{"class":577,"line":1676},[575,2049,2050],{"class":695},"    action",[575,2052,699],{"class":585},[575,2054,605],{"class":585},[575,2056,808],{"class":608},[575,2058,664],{"class":585},[575,2060,745],{"class":585},[575,2062,2063,2066,2068,2070,2072,2074,2076,2078,2080,2082,2084,2086,2088,2090,2092],{"class":577,"line":1692},[575,2064,2065],{"class":695},"    target",[575,2067,699],{"class":585},[575,2069,586],{"class":585},[575,2071,1519],{"class":695},[575,2073,699],{"class":585},[575,2075,605],{"class":585},[575,2077,880],{"class":608},[575,2079,664],{"class":585},[575,2081,593],{"class":585},[575,2083,1978],{"class":695},[575,2085,699],{"class":585},[575,2087,605],{"class":585},[575,2089,897],{"class":608},[575,2091,664],{"class":585},[575,2093,763],{"class":585},[575,2095,2096,2099,2101,2103,2105,2107],{"class":577,"line":1698},[575,2097,2098],{"class":695},"    outcome",[575,2100,699],{"class":585},[575,2102,605],{"class":585},[575,2104,915],{"class":608},[575,2106,664],{"class":585},[575,2108,745],{"class":585},[575,2110,2111,2113],{"class":577,"line":1703},[575,2112,1679],{"class":585},[575,2114,1418],{"class":695},[575,2116,2118],{"class":577,"line":2117},13,[575,2119,640],{"emptyLinePlaceholder":639},[575,2121,2123,2125,2127,2130],{"class":577,"line":2122},14,[575,2124,2036],{"class":589},[575,2126,649],{"class":585},[575,2128,2129],{"class":657},"restore",[575,2131,1689],{"class":695},[575,2133,2135,2137],{"class":577,"line":2134},15,[575,2136,1342],{"class":585},[575,2138,1418],{"class":589},[540,2140,2141,2142,2145,2146,2149,2150,649],{},"Prefer ",[544,2143,2144],{},"assertAudit()"," when a missing audit should fail the test with a readable message. Use ",[544,2147,2148],{},"toIncludeAuditOf()"," when you need a boolean inside ",[544,2151,2152],{},"expect(...)",[540,2154,2155,2156,2159,2160,2163],{},"Always call ",[544,2157,2158],{},"captured.restore()"," in an ",[544,2161,2162],{},"afterEach"," (or wrap with a fixture) so a failing assertion never leaks into the next test.",[557,2165,2167],{"id":2166},"every-audit-export","Every audit export",[2169,2170,2171,2187],"table",{},[2172,2173,2174],"thead",{},[2175,2176,2177,2181,2184],"tr",{},[2178,2179,2180],"th",{},"Symbol",[2178,2182,2183],{},"Kind",[2178,2185,2186],{},"Notes",[2188,2189,2190,2203,2216,2228,2244,2256,2269,2282,2298,2315,2328,2343,2355],"tbody",{},[2175,2191,2192,2198,2200],{},[2193,2194,2195],"td",{},[544,2196,2197],{},"AuditFields",[2193,2199,826],{},[2193,2201,2202],{},"Reserved field on the wide event",[2175,2204,2205,2210,2213],{},[2193,2206,2207],{},[544,2208,2209],{},"defineAuditAction(name, opts?)",[2193,2211,2212],{},"factory",[2193,2214,2215],{},"Typed action registry, infers target shape",[2175,2217,2218,2223,2225],{},[2193,2219,2220],{},[544,2221,2222],{},"defineAuditCatalog(prefix, map)",[2193,2224,2212],{},[2193,2226,2227],{},"Bundle of typed audit actions sharing a prefix",[2175,2229,2230,2235,2238],{},[2193,2231,2232],{},[544,2233,2234],{},"log.audit(fields)",[2193,2236,2237],{},"method",[2193,2239,2240,2241,2243],{},"Sugar over ",[544,2242,1892],{}," + force-keep",[2175,2245,2246,2251,2253],{},[2193,2247,2248],{},[544,2249,2250],{},"log.audit.deny(reason, fields)",[2193,2252,2237],{},[2193,2254,2255],{},"Records a denied action",[2175,2257,2258,2263,2266],{},[2193,2259,2260],{},[544,2261,2262],{},"audit(fields)",[2193,2264,2265],{},"function",[2193,2267,2268],{},"Standalone for scripts \u002F jobs",[2175,2270,2271,2276,2279],{},[2193,2272,2273],{},[544,2274,2275],{},"withAudit({ action, target })(fn)",[2193,2277,2278],{},"wrapper",[2193,2280,2281],{},"Auto-emit success \u002F failure \u002F denied",[2175,2283,2284,2289,2292],{},[2193,2285,2286],{},[544,2287,2288],{},"auditDiff(before, after)",[2193,2290,2291],{},"helper",[2193,2293,2294,2295],{},"Redact-aware JSON Patch for ",[544,2296,2297],{},"changes",[2175,2299,2300,2304,2307],{},[2193,2301,2302],{},[544,2303,1881],{},[2193,2305,2306],{},"test util",[2193,2308,2309,2310,2312,2313],{},"Capture audits on emit; ",[544,2311,2144],{}," or ",[544,2314,2148],{},[2175,2316,2317,2322,2325],{},[2193,2318,2319],{},[544,2320,2321],{},"auditEnricher(opts?)",[2193,2323,2324],{},"enricher",[2193,2326,2327],{},"Auto-fill request \u002F runtime \u002F tenant context",[2175,2329,2330,2335,2337],{},[2193,2331,2332],{},[544,2333,2334],{},"auditOnly(drain, { await? })",[2193,2336,2278],{},[2193,2338,2339,2340,2342],{},"Routes only events with an ",[544,2341,788],{}," field",[2175,2344,2345,2350,2352],{},[2193,2346,2347],{},[544,2348,2349],{},"signed(drain, opts)",[2193,2351,2278],{},[2193,2353,2354],{},"Generic integrity wrapper (hmac \u002F hash-chain)",[2175,2356,2357,2362,2365],{},[2193,2358,2359],{},[544,2360,2361],{},"auditRedactPreset",[2193,2363,2364],{},"config",[2193,2366,2367],{},"Strict PII for audit events",[540,2369,2370,2371,2373],{},"Everything ships from the main ",[544,2372,609],{}," entrypoint.",[2375,2376,2377],"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 pre.shiki code .swJcz, html code.shiki .swJcz{--shiki-light:#E53935;--shiki-default:#F07178;--shiki-dark:#F07178}html pre.shiki code .sbssI, html code.shiki .sbssI{--shiki-light:#F76D47;--shiki-default:#F78C6C;--shiki-dark:#F78C6C}html pre.shiki code .sfNiH, html code.shiki .sfNiH{--shiki-light:#FF5370;--shiki-default:#FF9CAC;--shiki-dark:#FF9CAC}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 .spNyl, html code.shiki .spNyl{--shiki-light:#9C3EDA;--shiki-default:#C792EA;--shiki-dark:#C792EA}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 .sBMFI, html code.shiki .sBMFI{--shiki-light:#E2931D;--shiki-default:#FFCB6B;--shiki-dark:#FFCB6B}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}",{"title":571,"searchDepth":615,"depth":615,"links":2379},[2380,2381,2382,2383,2384],{"id":559,"depth":615,"text":560},{"id":1180,"depth":615,"text":1181},{"id":1486,"depth":615,"text":1487},{"id":1875,"depth":615,"text":1876},{"id":2166,"depth":615,"text":2167},"File system, Axiom, and Postgres recipes for audit logs, plus mockAudit for tests and the full API reference.","md",[2388,2391],{"label":399,"icon":376,"to":400,"color":2389,"variant":2390},"neutral","subtle",{"label":133,"icon":131,"to":138,"color":2389,"variant":2390},{},{"title":403,"icon":406},{"title":535,"description":2385},"_5RK4jKMdGZrkk5XjLN6rkbGLur3OTXTtCRkWokVX7w",[2397,2399],{"title":399,"path":400,"stem":401,"description":2398,"icon":376,"children":-1},"Integrity, redact presets, GDPR vs append-only, retention windows, and the most common pitfalls when shipping audit logs to production.",{"title":128,"path":412,"stem":413,"description":2400,"icon":140,"children":-1},"One event per run for CLIs and automation, with privacy-safe flags, consent, an outbox, and disclosure generated from the same config.",1786806597104]