diff --git a/packages/core-audit/src/di/bind-audit.test.ts b/packages/core-audit/src/di/bind-audit.test.ts index c9dafb9..9cc9b65 100644 --- a/packages/core-audit/src/di/bind-audit.test.ts +++ b/packages/core-audit/src/di/bind-audit.test.ts @@ -7,6 +7,7 @@ import { NoopAuditLog } from "../noop-audit-log"; import { StdoutJsonAuditLog } from "../stdout-json-audit-log"; import { PayloadAuditLog } from "../payload-audit-log"; import { MultiSinkAuditLog } from "../multi-sink-audit-log"; +import { TraceIdEnrichingAuditLog } from "../trace-id-enriching-audit-log"; import type { IAuditLog } from "../audit-log.interface"; describe("bindAudit", () => { @@ -14,28 +15,32 @@ describe("bindAudit", () => { const container = new Container(); bindAudit(container, { payloadConfig: {} as never }); const auditLog = container.get(AUDIT_SYMBOLS.IAuditLog); - expect(auditLog).toBeInstanceOf(MultiSinkAuditLog); + expect(auditLog).toBeInstanceOf(TraceIdEnrichingAuditLog); + expect((auditLog as unknown as { inner: unknown }).inner).toBeInstanceOf(MultiSinkAuditLog); }); it("returns StdoutJsonAuditLog alone when payloadConfig omitted + default sinks", () => { const container = new Container(); bindAudit(container, {}); const auditLog = container.get(AUDIT_SYMBOLS.IAuditLog); - expect(auditLog).toBeInstanceOf(StdoutJsonAuditLog); + expect(auditLog).toBeInstanceOf(TraceIdEnrichingAuditLog); + expect((auditLog as unknown as { inner: unknown }).inner).toBeInstanceOf(StdoutJsonAuditLog); }); it("returns NoopAuditLog when sinks=[]", () => { const container = new Container(); bindAudit(container, { sinks: [] }); const auditLog = container.get(AUDIT_SYMBOLS.IAuditLog); - expect(auditLog).toBeInstanceOf(NoopAuditLog); + expect(auditLog).toBeInstanceOf(TraceIdEnrichingAuditLog); + expect((auditLog as unknown as { inner: unknown }).inner).toBeInstanceOf(NoopAuditLog); }); it("returns PayloadAuditLog when sinks=['payload'] only", () => { const container = new Container(); bindAudit(container, { payloadConfig: {} as never, sinks: ["payload"] }); const auditLog = container.get(AUDIT_SYMBOLS.IAuditLog); - expect(auditLog).toBeInstanceOf(PayloadAuditLog); + expect(auditLog).toBeInstanceOf(TraceIdEnrichingAuditLog); + expect((auditLog as unknown as { inner: unknown }).inner).toBeInstanceOf(PayloadAuditLog); }); it("validates AUDIT_PSEUDONYM_SALT in production", () => { diff --git a/packages/core-audit/src/di/bind-audit.ts b/packages/core-audit/src/di/bind-audit.ts index 590c101..f4154bb 100644 --- a/packages/core-audit/src/di/bind-audit.ts +++ b/packages/core-audit/src/di/bind-audit.ts @@ -7,6 +7,7 @@ import { StdoutJsonAuditLog } from "../stdout-json-audit-log"; import { MultiSinkAuditLog } from "../multi-sink-audit-log"; import type { IAuditLog } from "../audit-log.interface"; import { AUDIT_SYMBOLS } from "./symbols"; +import { TraceIdEnrichingAuditLog } from "../trace-id-enriching-audit-log"; export type BindAuditOpts = { /** Payload config; required if "payload" is in sinks. */ @@ -25,8 +26,9 @@ export type BindAuditOpts = { * if not — better to refuse to start than to ship audit data with a dev-fallback * salt that an attacker could reverse. * - * Note: Phase 4 wraps the returned auditLog in TraceIdEnrichingAuditLog - * for OTel correlation. Phase 2 returns the inner sink/fan-out directly. + * The returned auditLog is wrapped in TraceIdEnrichingAuditLog (Phase 4) + * so all sinks receive AuditEntry.correlationId auto-populated from the + * active OTel span. The inner sink/fan-out is accessible via `.inner`. */ export function bindAudit( container: Container, @@ -49,10 +51,11 @@ export function bindAudit( sinks.push(new StdoutJsonAuditLog()); } - const auditLog: IAuditLog = + const inner: IAuditLog = sinks.length > 1 ? new MultiSinkAuditLog(sinks) : sinks.length === 1 ? sinks[0]! : new NoopAuditLog(); + const auditLog: IAuditLog = new TraceIdEnrichingAuditLog(inner); if (container.isBound(AUDIT_SYMBOLS.IAuditLog)) { container.unbind(AUDIT_SYMBOLS.IAuditLog); diff --git a/packages/core-audit/src/index.ts b/packages/core-audit/src/index.ts index d1502b3..01450e1 100644 --- a/packages/core-audit/src/index.ts +++ b/packages/core-audit/src/index.ts @@ -6,6 +6,7 @@ export { PayloadAuditLog } from "./payload-audit-log"; export { MultiSinkAuditLog } from "./multi-sink-audit-log"; export { auditLogsCollection } from "./audit-logs-collection"; export { bindAudit, type BindAuditOpts } from "./di/bind-audit"; +export { TraceIdEnrichingAuditLog } from "./trace-id-enriching-audit-log"; export { AUDIT_SYMBOLS } from "./di/symbols"; // Phase 3 — GDPR erasure export { pseudonymize } from "./pseudonymize";