fix(auth): add username + passwordHash fields to users collection

The production UsersRepository reads and writes username + passwordHash
via the Payload local API, but the users collection never declared them,
so production sign-up/sign-in was broken (audit finding B1). passwordHash
uses access.read: () => false so credential material never serializes
through any Payload API surface; the repository still reads it with
overrideAccess: true. A contract-shaped test pins every repo-used field
(USERS_REPOSITORY_FIELDS) against the collection config so drift fails
at test time without a database.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
This commit is contained in:
2026-07-10 17:21:16 +02:00
parent bb2751eede
commit c9db7c8cd7
4 changed files with 131 additions and 7 deletions

View File

@@ -18,6 +18,35 @@ export const users: CollectionConfig = {
subject: { kind: "self", field: "id" },
},
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",