import type { CollectionConfig } from "payload"; export const users: CollectionConfig = { slug: "users", auth: true, admin: { useAsTitle: "email", }, custom: { retention: { purgeSchedule: "daily", postDeletion: { duration: "P30D", trigger: "after-deletion", action: "hard-delete", }, }, subject: { kind: "self", field: "id" }, // Collection-level PII map consumed by the DSR walkers (audit finding // A5): export includes fields marked exportable; the soft-delete path // redacts them. `email` is auto-added by Payload's `auth: true` and has // no explicit field entry below, so it MUST be declared here or Art. 15 // export misses it and Art. 17 soft delete leaves it behind. pii: { email: { category: "contact-email", purpose: ["account-authentication", "transactional-notifications"], exportable: true, restrictable: true, }, username: { category: "identification-username", purpose: ["service-delivery"], exportable: true, restrictable: true, }, displayName: { category: "identification-username", purpose: ["service-delivery"], exportable: true, restrictable: true, }, }, }, fields: [ { // Read/written by the production UsersRepository (getUserByUsername, // createUser). Pinned by collections/users.test.ts against // USERS_REPOSITORY_FIELDS so repo <-> collection drift fails fast. name: "username", type: "text", required: true, unique: true, index: true, custom: { pii: { category: "identification-username", purpose: ["service-delivery"], exportable: true, restrictable: true, }, }, }, { // Credential material — must never leave the server. `access.read` // returns false unconditionally so the field is stripped from every // REST/GraphQL/admin API response; the auth repository still reads it // through the local API with `overrideAccess: true`. name: "passwordHash", type: "text", required: true, admin: { hidden: true }, access: { read: () => false }, }, { name: "displayName", type: "text", custom: { pii: { category: "identification-username", purpose: ["service-delivery"], exportable: true, restrictable: true, }, }, }, { name: "role", type: "select", options: [ { label: "Admin", value: "admin" }, { label: "Editor", value: "editor" }, { label: "Author", value: "author" }, ], defaultValue: "author", required: true, }, { name: "consentState", type: "json", }, ], };