feat(users): site setting to disable self-service username changes (#298) - #299
Merged
Conversation
) Adds `username_changes_enabled` (default on) so deployments with provisioned names can pin usernames to what was issued: - Off gates only the self-service path: POST /api/auth/change-username 403s, checked before the password verification so a disabled endpoint never acts as a password oracle. An admin rename (manage_users, Admin → Users) is deliberately unaffected — it's the provisioning path this setting exists to protect. - The toggle lives on Admin → Site settings → General (manage_site_settings) and rides the existing operational PUT, emitting site.settings_updated. Omitted-in-PUT = unchanged, the update_checks_enabled contract — a scripted whole-object PUT must not silently re-enable it. - Exposed on the public GET /api/site-settings (like registration_open), so the profile page hides its username card with no extra request. - One migration, server_default TRUE (verified against real Postgres); new admin strings born extracted (ADR-0029), es/fr/pl synced. Tests: 403 + gate-before-password ordering, admin rename while disabled, re-enable restores, public exposure + operational round-trip + omission semantics; frontend card-hidden case. Full suites green (backend 1122, frontend 373), plus a live E2E against the dev stack. Closes #298 Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
Closes #298 — the first v1.6.0 issue. Adds a global operational setting,
username_changes_enabled(default on), so deployments withprovisioned names (schools, corporate events) can pin usernames to what
was issued.
Behaviour
POST /api/auth/change-usernamereturns 403 ("Username changes are disabled on this platform"). The
gate sits before password verification, so a disabled endpoint never
acts as a password oracle; the per-request throttle still applies first.
manage_usersholders keep renamingfrom Admin → Users. That's the provisioning path the setting protects.
(
manage_site_settings), rides the existing operational PUT, and emitsthe existing
site.settings_updatedaudit event.update_checks_enabledcontract: a scripted whole-object PUT that omits the field can't
silently re-enable a feature an admin turned off.
GET /api/site-settings(likeregistration_open), so the profile page hides its username card withno extra request. While hidden, the cooldown mechanics of feat(users): self-service username change — cooldown, admin rename, audited #284 are
untouched for when it's re-enabled.
Implementation
SiteSettings.username_changes_enabled+ one migration(
server_defaultTRUE — verified against real Postgres via the devstack:
d1a6b83f47c2 → e7b2c94a63d1applied cleanly).SiteSettingsOut(public) /OperationalSettingsOut/OperationalSettingsUpdate(nullable, omission-safe) + PUT wiring.SiteSettings/OperationalSettingstypes +FALLBACK_SETTINGS, a General-tab On/Off card (strings bornextracted into
admin.settings, ADR-0029, es/fr/pl synced), andusername-card.tsxreturning null when the flag is off.Tests
disabled is still 403), admin rename while disabled, re-enable restores
self-service, public exposure + operational round-trip + omission
semantics. The public-payload exact key-set tests updated for the new
field.
Verification
pytest— 1122 passedtscclean,eslintclean,vitest373 passed,npm run buildsucceeds (Y.js singleton check passes)public reflects false → participant rename 403s with the right detail →
admin rename 200s → restored to default.
Note: one unrelated full-suite run hung at 98% CPU near the audit-log
tests and would not reproduce (solo and prefix runs green, and this
plumbing passed CI 7× today). Flagged separately for investigation rather
than papered over here.
🤖 Generated with Claude Code