Decorator implementing IAuditLog that auto-populates AuditEntry.correlationId
from the active OTel span via currentTraceId(). Caller-supplied correlationId
always wins (explicit > implicit). eraseSubject passes through unmodified.
Adds @opentelemetry/{api,sdk-trace-base,context-async-hooks} as devDeps for
test infrastructure.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
31 lines
1.1 KiB
TypeScript
31 lines
1.1 KiB
TypeScript
import type { AuditEntry } from "@repo/core-shared/audit";
|
|
import { currentTraceId } from "@repo/core-shared/instrumentation";
|
|
import type { IAuditLog } from "./audit-log.interface";
|
|
|
|
/**
|
|
* Decorates any IAuditLog by auto-populating AuditEntry.correlationId from
|
|
* the active OTel span (when present and the caller didn't supply a value).
|
|
* Caller-supplied correlationId always wins — explicit > implicit.
|
|
*
|
|
* Applied at bind time by bindAudit so all sinks see entries with
|
|
* correlationId already set. Single source of truth for the OTel-audit bridge.
|
|
*/
|
|
export class TraceIdEnrichingAuditLog implements IAuditLog {
|
|
constructor(readonly inner: IAuditLog) {}
|
|
|
|
async record(entry: AuditEntry): Promise<void> {
|
|
if (entry.correlationId) {
|
|
return this.inner.record(entry);
|
|
}
|
|
const traceId = currentTraceId();
|
|
if (!traceId) {
|
|
return this.inner.record(entry);
|
|
}
|
|
return this.inner.record({ ...entry, correlationId: traceId });
|
|
}
|
|
|
|
eraseSubject(actorId: string, mode: "pseudonymize" | "delete"): Promise<void> {
|
|
return this.inner.eraseSubject(actorId, mode);
|
|
}
|
|
}
|