Skip to content

Record people by id in proposals, never by name - #36

Merged
mgilardi merged 2 commits into
mainfrom
plugin-opaque-ids
Nov 11, 2026
Merged

mgilardi merged 2 commits into
mainfrom
plugin-opaque-ids

Conversation

@mgilardi

Copy link
Copy Markdown
Collaborator

Why

An accepted proposal sealed a name the host chose (proposals.nameOf) into the new snapshot, inside its checksum. A name there can't be taken out when a person leaves a site, and a published version may already be pinned and cited.

What changes

  • proposals.personId({ req }) gives an opaque id (default: the signed-in user's document id). That id is all a proposal stores about its author, and all an accepted proposal seals for the author and the manager.
  • An id is 1 to 64 letters, digits, ., _, : and -, starting with a letter or digit. An email address or a name with a space is refused: the action stops, nothing is saved, and the refused value isn't logged.
  • proposals.displayName({ req, personId }) is optional. It is looked up each time a proposal is read (once per person per request) and returned as authorName. It is never stored or sealed.
  • proposals.nameOf is removed. The plugin isn't on npm, so nothing released changes.
  • Core still seals the strings it is given. Only comments and one error text changed there.
  • The example site keeps its handle, shown through displayName.

Tested

  • 526 unit tests, 142 of them in the plugin on Payload 3.93 with an in-memory MongoDB.
  • The example site's smoke test: 47 checks, on next dev and on the built site.
  • Eight deliberate breaks of the new code, one at a time. Each failed a test.

Not tested, and limits

  • Postgres or SQLite, and a host with more than one auth collection.
  • A one-word handle passes the id pattern. The plugin can't tell it from an id; the README says not to give one.
  • A proposal's title, each move's note and the manager's note are sealed as written and aren't screened.
  • An accepted proposal keeps its relationship to the user document. No code can change it.

🤖 Generated with Claude Code

mgilardi and others added 2 commits November 11, 2026 15:08
An accepted proposal sealed a name the host chose into the new snapshot,
inside its checksum. A name there can't be taken out when a person leaves
a site, and a published version may already be pinned and cited.

The plugin now stores and seals only an opaque person id
(proposals.personId, default the user document's id). It refuses anything
that isn't a plain id, so an email address or a name with a space never
passes, and it never logs a refused value. A display name comes from the
optional proposals.displayName, looked up each time a proposal is read and
returned as authorName; it is never stored. proposals.nameOf is removed.
The plugin has not been published, so nothing released changes.

Core still seals the strings it is given; only its comments and one error
text changed. The example site shows the handle through displayName.

Tested: 526 unit tests (142 in the plugin, on Payload 3.93 with an
in-memory MongoDB), the example's 47 smoke checks on next dev and on the
built site, and eight deliberate breaks of the new code, each caught.
Not tested: Postgres or SQLite, or a host with more than one auth
collection. A one-word handle still passes the id pattern, and titles and
notes are sealed as written; the README says both.

Co-Authored-By: Claude <noreply@anthropic.com>
The status line still said 139 tests; the person id change made it 142.

Co-Authored-By: Claude <noreply@anthropic.com>
@mgilardi
mgilardi merged commit 9425837 into main Nov 11, 2026
1 check passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant