Files
agentic-dev/packages/core-shared/src/trpc/require-authenticated.test.ts
Danijel Martinek 318a69e780 fix(compliance): port DSR/consent/audit/retention audit fixes
Ports the upstream compliance-core audit fixes onto the kept core-dsr,
core-consent, core-audit, core-cms and core-shared packages (pristine
template state here, so taken to the fixed end-state):

- core-dsr: scope DSR operations to the caller's own subject (A11);
  include the subject's audit trail in exports; resolve the per-request
  binding from ctx instead of a throwing singleton proxy.
- core-consent: build the consent router from the shared superjson
  transformer (A10); merge per-category on persist instead of replacing;
  validate migrated categories against an allow-list.
- core-audit: keyed 128-bit pseudonyms + salted DSR certificate; add the
  audit-logs collection and the req-scoped GDPR audit-erasure afterDelete
  hook (A6).
- core-shared: grace-purge soft-deleted rows via a retention-purge task +
  tombstone field and boot registration (A2/A3); add the
  require-authenticated tRPC helper; derive clientIp + resolve the session
  user in createTrpcContext (B2/A11).
- core-cms: register audit-logs, wire the audit-erasure hook and
  retention-purge tasks; adapted to our collection set (users, workspaces).

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_016j8z4VHjedXDTjEDNg7qHK
2026-07-12 23:54:14 +02:00

51 lines
1.5 KiB
TypeScript

import { describe, it, expect } from "vitest";
import { z } from "zod";
import { t } from "@/trpc/init";
import {
requireAuthenticated,
protectedProcedure,
} from "@/trpc/require-authenticated";
const echoRouter = t.router({
publicEcho: t.procedure
.input(z.object({ value: z.string() }).strict())
.query(({ input }) => input.value),
protectedEcho: protectedProcedure
.input(z.object({ value: z.string() }).strict())
.mutation(({ input, ctx }) => ({
value: input.value,
userId: (ctx as { user: { id: string } }).user.id,
})),
composedEcho: t.procedure
.use(requireAuthenticated)
.input(z.object({}).strict())
.mutation(() => "ok"),
});
describe("requireAuthenticated middleware (B7)", () => {
it("rejects anonymous callers with UNAUTHORIZED", async () => {
const caller = echoRouter.createCaller({});
await expect(caller.protectedEcho({ value: "x" })).rejects.toMatchObject({
code: "UNAUTHORIZED",
});
await expect(caller.composedEcho({})).rejects.toMatchObject({
code: "UNAUTHORIZED",
});
});
it("passes through authenticated callers and exposes ctx.user", async () => {
const caller = echoRouter.createCaller({
user: { id: "user-1", roles: [] },
});
await expect(caller.protectedEcho({ value: "x" })).resolves.toEqual({
value: "x",
userId: "user-1",
});
});
it("leaves public procedures untouched", async () => {
const caller = echoRouter.createCaller({});
await expect(caller.publicEcho({ value: "hi" })).resolves.toBe("hi");
});
});