Files
agentic-dev/packages/core-audit/src/with-audit.ts
danijel-lf 0a34b45bb7
Some checks failed
CI / typecheck + lint + boundaries + test + build (push) Has been cancelled
CodeQL / Analyze (javascript-typescript) (push) Has been cancelled
Coverage snapshot / snapshot (push) Has been cancelled
Release Please / release-please (push) Has been cancelled
Sentry PII guard (R31) / pii-guard (push) Has been cancelled
CI / Playwright e2e (push) Has been cancelled
CI / Storybook smoke tests + visual regression (push) Has been cancelled
Mutation testing (nightly) / mutate (push) Has been cancelled
Library trace revalidation (weekly) / revalidate (push) Has been cancelled
feat(auth): implement session methods with Payload-backed JWT
Replace NotImplementedError stubs in AuthenticationService with working
implementations: createSession signs a HS256 JWT using Payload's instance
secret, validateSession verifies and decodes the token then looks up the
user, invalidateSession returns a blank cookie with maxAge 0. No external
JWT dependency — uses Node crypto HMAC directly.

Also clarify withAudit/withAnalytics comments: the wrappers intentionally
delegate recording to the use case body (only it knows which fields to
extract), so the TODO was misleading.
2026-05-28 22:41:30 +02:00

36 lines
1.7 KiB
TypeScript

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<I, O, M>` 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> = 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<Args extends unknown[], R>(
// The wrapper attaches the brand and ensures the auditLog dependency is
// available at bind time. Actual `auditLog.record()` calls live in the
// use case body — only the use case knows which fields to extract from
// its input/output for the audit entry.
auditLog: IAuditLog,
fn: (...args: Args) => Promise<R>,
): Audited<(...args: Args) => Promise<R>> {
void auditLog;
const wrapped: (...args: Args) => Promise<R> = (...args) => fn(...args);
attachBrand(wrapped, "__audited");
return wrapped as Audited<(...args: Args) => Promise<R>>;
}