docs: add ADR 004 — user registration, approval, and account state#61
Open
martinydeAI wants to merge 2 commits into
Open
docs: add ADR 004 — user registration, approval, and account state#61martinydeAI wants to merge 2 commits into
martinydeAI wants to merge 2 commits into
Conversation
Records the decision to model identity state with a status enum (pending | approved | blocked) on the User entity rather than gating via roles. Roles are kept orthogonal — they answer what a signed-in user can do, not whether they may sign in. The supporting architecture covers an env-backed email-domain allow-list for self-signup, a Symfony UserCheckerInterface that rejects login for non-approved users, and an approval queue restricted to users with domainManager=true. Notes that #45's active boolean is superseded by the enum and should be updated when implemented. Status: Draft. Index updated. CHANGELOG entry under [Unreleased] / Added. Closes #60. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
4 tasks
Folds the domainManager: bool field originally proposed in #45 into the existing roles column as ROLE_DOMAIN_MANAGER. Promote / demote is toggling the role; scope (which domain a manager can act on) is derived from the manager's own email domain via a small voter. Site admin (ROLE_ADMIN) sits above it via role_hierarchy and short-circuits the domain-match check. The 'Implication for #45' note is updated: the entity ships with only 'name' on top of the auth fields from #2 — both active and domainManager are superseded. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This was referenced Jun 12, 2026
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
Adds ADR 004 recording the architecture for user registration,
approval, and account-state lifecycle decided on #60.
The choice is modelled as a
statusenum (pending | approved | blocked) on theUserentity, deliberately kept orthogonal fromroles. Self-signup is gated by an env-backed e-mail domainallow-list, login is gated by a Symfony
UserCheckerInterface, andapproval is performed by users with
domainManager = true.Changes
docs/adr/004-user-approval-and-account-state.md(new, Draft).docs/adr/README.md— index entry for 004.CHANGELOG.md—[Unreleased] / Addedentry referencing Decide on user registration, approval, and account-state model #60.Note on #45
The
activeboolean planned in#45 is superseded by
the
statusenum. The Implication for #45 section of the ADR spellsthis out so the User-entity PR doesn't ship
activeonly to need afollow-up migration removing it.
Implementation
Filed as separate issues so this PR stays scoped to the decision:
UserCheckerInterfaceto gate login for non-approved usersdomainManagerusers(Issue numbers will appear in this body once filed.)
Test plan
task coding-standards-markdown-check→ clean.we discussed and that the env-backed domain list is the right
starting point.
Closes #60
🤖 Generated with Claude Code