Files
agentic-dev/packages/core-audit/src/integrations/api/router.ts
Danijel Martinek 131efd5d2f feat(core-audit): admin tRPC procedure for eraseSubject
Adds auditProcedure (adminOnly middleware + defineErrorMiddleware([])) in
core-audit/src/integrations/api/procedures.ts. Adds createAuditRouter that
captures an IAuditLog and exposes a single eraseSubject mutation with zod
input validation. Non-admins receive FORBIDDEN. Barrel re-exports
pseudonymize, createAuditErasureHook, createAuditRouter, auditRouter,
AuditRouter, auditProcedure, AdminTrpcUser. Adds AUDIT_PSEUDONYM_SALT to
turbo.json globalEnv to clear lint warnings.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-11 16:25:09 +02:00

55 lines
1.7 KiB
TypeScript

import { z } from "zod";
import { t } from "@repo/core-shared/trpc/init";
import type { IAuditLog } from "../../audit-log.interface";
import { auditProcedure } from "./procedures";
/**
* Creates the audit admin tRPC router.
*
* The `auditLog` parameter is captured at router-creation time. Apps that
* mount this router must pass the `IAuditLog` impl returned by `bindAudit`.
*
* @example
* ```ts
* const { auditLog } = bindAudit(container, { payloadConfig, sinks: ["payload", "stdout"] });
* const appRouter = t.router({ ..., audit: createAuditRouter(auditLog) });
* ```
*/
export function createAuditRouter(auditLog: IAuditLog) {
return t.router({
eraseSubject: auditProcedure
.input(
z
.object({
actorId: z.string().min(1),
mode: z.enum(["pseudonymize", "delete"]).default("pseudonymize"),
})
.strict(),
)
.mutation(async ({ input }) => {
await auditLog.eraseSubject(input.actorId, input.mode);
return { ok: true as const };
}),
});
}
/**
* Convenience singleton for projects that have a single audit log instance.
* Most callers should use `createAuditRouter` and pass the IAuditLog explicitly.
* This export is a stub that throws at call time if auditLog has not been
* provided — it exists for type inference purposes (`AuditRouter`).
*/
export const auditRouter = createAuditRouter(
new Proxy({} as IAuditLog, {
get(_target, prop) {
if (prop === "then") return undefined; // not a Promise
throw new Error(
`auditRouter singleton used without providing an IAuditLog. ` +
`Use createAuditRouter(auditLog) instead.`,
);
},
}),
);
export type AuditRouter = ReturnType<typeof createAuditRouter>;