import type { CollectionAfterDeleteHook } from "payload"; import type { IAuditLog } from "../audit-log.interface"; export type AuditErasureHookOpts = { /** The audit log impl that will perform the erasure. */ auditLog: IAuditLog; /** * Erasure mode. Defaults to "pseudonymize" — the softer option that * retains the audit trail shape while removing PII linkage. Use * "delete" only when the data-subject specifically requests hard removal. */ mode?: "pseudonymize" | "delete"; }; /** * Payload `afterDelete` hook factory for GDPR erasure. * * Wire this on any collection whose `id` doubles as an audit subject * (e.g., the users collection). When Payload deletes a document, the * hook calls `auditLog.eraseSubject(String(doc.id), mode)`, removing * or pseudonymizing all audit entries recorded for that actor. * * The hook has no schema-specific knowledge — it works on any collection * that stores the subject identifier as its document `id`. * * Non-string, non-numeric ids are silently skipped (safe guard against * undefined/null that Payload may produce in edge cases). */ export function createAuditErasureHook( opts: AuditErasureHookOpts, ): CollectionAfterDeleteHook { const mode = opts.mode ?? "pseudonymize"; return async ({ doc }) => { if (typeof doc.id === "string" || typeof doc.id === "number") { await opts.auditLog.eraseSubject(String(doc.id), mode); } }; }