import type { PgTransaction } from "drizzle-orm/pg-core"; import type { ExtractTablesWithRelations } from "drizzle-orm"; import type { NodePgQueryResultHKT } from "drizzle-orm/node-postgres"; import { db } from "@/db"; import * as schema from "@/db/schema"; import { auditLog } from "@/db/schema"; /** * Transaktionstyp des Drizzle-pg-Clients (kein `any`). Server Actions, die in * einer Transaktion schreiben, übergeben ihre `tx` an `writeAudit`, damit das * Audit-Insert Teil derselben atomaren Operation ist. */ export type Tx = PgTransaction< NodePgQueryResultHKT, typeof schema, ExtractTablesWithRelations >; /** Audit-fähiges Ziel-Objekt. `zielId` ist eine UUID (Schema-Spalte). */ export type AuditZielTyp = | "brigade" | "user" | "merkmal" | "vehicle" | "equipment" | "vehicle_template" | "equipment_category"; /** * EINE Signatur (Querschnittsstandard 6) für alle Schreib-Actions. Mit * optionalem `tx`: ohne `tx` läuft das Insert auf dem Pool-`db`. * * `details` ist serialisierbares JSON (kein PII über das Nötige hinaus). Der * `actorUserId` referenziert `users.id` (FK set-null), sodass die Historie auch * nach Benutzerlöschung erhalten bleibt. */ export async function writeAudit( actorUserId: string | null, aktion: string, zielTyp: AuditZielTyp | null, zielId: string | null, details?: Record, tx?: Tx, ): Promise { const exec = tx ?? db; await exec.insert(auditLog).values({ actorUserId: actorUserId ?? null, aktion, zielTyp, zielId, details: details ?? null, }); }