|
1 | 1 | # evlog |
2 | 2 |
|
| 3 | +## 2.14.0 |
| 4 | + |
| 5 | +### Minor Changes |
| 6 | + |
| 7 | +- [#295](https://github.com/HugoRCD/evlog/pull/295) [`aa9984f`](https://github.com/HugoRCD/evlog/commit/aa9984f50259b292e8d1a2a671b600fcb74844db) Thanks [@HugoRCD](https://github.com/HugoRCD)! - Expose AI SDK execution metadata as a public API on `AILogger`. Three new methods let app code read the same data that gets attached to wide events: `getMetadata()` returns an immutable snapshot of the run (model, provider, tokens, calls, steps, tool calls, cost, finish reason, embeddings), `getEstimatedCost()` returns the dollar cost computed from the configured pricing map, and `onUpdate(cb)` subscribes to incremental snapshots emitted on every step, embedding, error, and integration finish (returns an unsubscribe function). New types `AIMetadata` (alias for `AIEventData`) and `AIMetadataListener` are exported. `model` and `provider` on `AIMetadata` are now optional to reflect early-snapshot reality (e.g. embedding-only runs). |
| 8 | + |
| 9 | +- [#302](https://github.com/HugoRCD/evlog/pull/302) [`7060006`](https://github.com/HugoRCD/evlog/commit/70600062eeafd86bd4e76d30aae3789434ca7f9b) Thanks [@HugoRCD](https://github.com/HugoRCD)! - Add first-class audit logs as a thin layer over existing evlog primitives. Audit is not a parallel system: it is a typed `audit` field on the wide event plus a few opt-in helpers and drain wrappers. Companies already running evlog can enable audit logs by adding 1 enricher + 1 drain wrapper + `log.audit()`, with zero new sub-exports. |
| 10 | + |
| 11 | + New API on the main `evlog` entrypoint: |
| 12 | + - `AuditFields` reserved on `BaseWideEvent` (`action`, `actor`, `target`, `outcome`, `reason`, `changes`, `causationId`, `correlationId`, `version`, `idempotencyKey`, `context`, `signature`, `prevHash`, `hash`) plus `AUDIT_SCHEMA_VERSION`. |
| 13 | + - `log.audit(fields)` and `log.audit.deny(reason, fields)` on `RequestLogger` and the return value of `createLogger()`. Sugar over `log.set({ audit })` that also force-keeps the event through tail sampling. |
| 14 | + - Standalone `audit(fields)` for jobs / scripts / CLIs. |
| 15 | + - `withAudit({ action, target, actor? })(fn)` higher-order wrapper that auto-emits `success` / `failure` / `denied` based on the wrapped function's outcome (with `AuditDeniedError` for AuthZ refusals). |
| 16 | + - `defineAuditAction(name, opts)` typed action registry, `auditDiff(before, after)` redact-aware JSON Patch helper, `mockAudit()` test utility (`expectIncludes`, `expectActionCount`, `clear`, `restore`). |
| 17 | + - `auditEnricher({ tenantId?, betterAuth? })` enricher that auto-fills `event.audit.context` (`requestId`, `traceId`, `ip`, `userAgent`, `tenantId`) and optionally bridges `actor` from a session. |
| 18 | + - `auditOnly(drain, { await? })` drain wrapper that filters to events with `event.audit` set, optionally awaiting writes for crash safety. `signed(drain, { strategy: 'hmac' | 'hash-chain', ... })` generic tamper-evidence wrapper with pluggable `state.{load,save}` for hash chains. |
| 19 | + - `auditRedactPreset` strict PII preset composable with existing `RedactConfig`. |
| 20 | + |
| 21 | + Audit events are always force-kept by tail sampling and get a deterministic `idempotencyKey` derived from `action + actor + target + timestamp` so retries are safe across drains. Schema is OTEL-compatible and the `actor.type === 'agent'` slot carries `model`, `tools`, `reason`, `promptId` for AI agent auditing. No new sub-exports were added. |
| 22 | + |
3 | 23 | ## 2.13.0 |
4 | 24 |
|
5 | 25 | ### Minor Changes |
|
0 commit comments