import type { IAuditLog } from "./audit-log.interface"; import { attachBrand } from "@repo/core-shared/conformance"; /** * Phantom-type brand attached at wrap time by `withAudit`. The conformance * system uses this as the type-level seam for mutating use cases that * declare `audits: [...]` in their manifest — without `__audited`, the * binding is not assignable to `ProductionUseCase` when M demands * it. At runtime the brand is a non-enumerable property attached by * `attachBrand` from `@repo/core-shared/conformance`, so the boot-time * assertion can verify the binding went through the audit-aware path. */ export type Audited = F & { readonly __audited: true }; /** * Use-case wrapper applied at DI bind time. The wrapper is a thin closure * that forwards to `fn` unchanged and carries the `__audited` brand. The * forward closure (instead of returning `fn` directly) keeps the brand on * a fresh function so the caller's original `fn` is not mutated — important * when the same factory output is used elsewhere unwrapped (dev-seed paths, * tests). */ export function withAudit( // TODO: wire automated recording from manifest declarations. // `audits[]` declarations. For now, the wrapper exists to: // (1) require callers to pass the auditLog at bind time (dep is available) // (2) attach the `__audited` brand so the boot-time assertion can verify // mutating use cases were bound through the audit-aware path. auditLog: IAuditLog, fn: (...args: Args) => Promise, ): Audited<(...args: Args) => Promise> { void auditLog; const wrapped: (...args: Args) => Promise = (...args) => fn(...args); attachBrand(wrapped, "__audited"); return wrapped as Audited<(...args: Args) => Promise>; }