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>
44 lines
1.4 KiB
TypeScript
44 lines
1.4 KiB
TypeScript
import { TRPCError } from "@trpc/server";
|
|
import { t } from "@repo/core-shared/trpc/init";
|
|
import { defineErrorMiddleware } from "@repo/core-shared/trpc/define-error-middleware";
|
|
|
|
/**
|
|
* The minimum user shape that the adminOnly middleware expects to find on `ctx`.
|
|
* Apps must include this field when creating their tRPC context for requests
|
|
* that may reach admin procedures. Unauthenticated requests leave `user`
|
|
* undefined, which the middleware treats as non-admin.
|
|
*/
|
|
export type AdminTrpcUser = {
|
|
roles: string[];
|
|
};
|
|
|
|
/**
|
|
* Middleware that blocks non-admin callers.
|
|
*
|
|
* Reads `ctx.user?.roles` from the tRPC context. Throws FORBIDDEN if the
|
|
* user is absent or lacks the "admin" role. Apps that mount the auditRouter
|
|
* must set `ctx.user` with the authenticated user's roles.
|
|
*/
|
|
const adminOnly = t.middleware(({ ctx, next }) => {
|
|
const user = (ctx as { user?: AdminTrpcUser }).user;
|
|
if (!user?.roles.includes("admin")) {
|
|
throw new TRPCError({
|
|
code: "FORBIDDEN",
|
|
message: "Admin role required",
|
|
});
|
|
}
|
|
return next({ ctx: { ...ctx, user } });
|
|
});
|
|
|
|
/**
|
|
* Base procedure for all audit admin routes.
|
|
*
|
|
* - `adminOnly` middleware gates every mutation/query.
|
|
* - `defineErrorMiddleware([])` — no audit-specific domain errors need tRPC
|
|
* mapping; the FORBIDDEN thrown by `adminOnly` is a plain TRPCError and
|
|
* propagates unchanged.
|
|
*/
|
|
export const auditProcedure = t.procedure
|
|
.use(adminOnly)
|
|
.use(defineErrorMiddleware([]));
|