feat(auth): implement invite and admin-approval registration policies #321
No reviewers
Labels
No labels
area:auth
area:ci
area:db
area:infra
area:native
area:pwa
area:service
epic
feature
foundation
No milestone
No project
No assignees
2 participants
Notifications
Due date
No due date set.
Dependencies
No dependencies set.
Reference
james/carol!321
Loading…
Add table
Add a link
Reference in a new issue
No description provided.
Delete branch "219-registration-policies"
Deleting a branch is permanent. Although the deleted branch may continue to exist for a short time before it actually gets removed, it CANNOT be undone in most cases. Continue?
Implements the
inviteandadmin-approvalREGISTRATION_POLICYvalues (#219), which were previously accepted but rejected every registration with503 policy_not_implemented.Backend
020_users_status(users.status:active|pending, default active) +021_invites(sha256token_hashUNIQUE,created_bycascade /consumed_byset-null).InvitesRepository(consume-once guard onconsumed_at IS NULL) +UsersRepositorystatus methods.registration.ts): first user is always allowed as active admin under any policy.open→ 201 active.invite→ requires a one-time token, consumed only on success (invite_required→403,invite_invalid→400,invite_consumed→409,invite_expired→410).admin-approval→ creates apendinguser, returns 202{status:"pending"}with no session.403 pending_approval./api/admin/*via a newrequireAdminhelper (session or bearer; 401 no creds / 403forbidden):/api/admin/invites(list cursor-paginated / mint, returns plaintexttokenonce)/api/admin/invites/{id}(revoke)/api/admin/pending-users/api/admin/pending-users/{id}/approve/api/admin/pending-users/{id}(reject = delete; identities cascade)Contract + client
openapi-routes.ts; rootopenapi.jsonregenerated (drift + coverage green, 104 pairs).@carol/api-clienttypes; newadmin-invites/admin-pending-usershooks.account.tsx(reveal-token-once + copy, list/revoke, approve/reject); optional invite-code field + awaiting-approval screen inregister.tsx; i18n + READMEREGISTRATION_POLICYrow updated.Verification
pnpm -F @carol/api test— 806 pass / 175 skipped (Postgres legs skip locally withoutTEST_POSTGRES_URL; CI's matrix runs them — migrations/repos written for both engines).openapi:checkup-to-date,openapi:coverage104 pairs.@carol/api-client+@carol/clienttypecheck,@carol/clientlint — clean.tests/db/invites.test.ts(both-engine),tests/api/registration-policies.test.ts(invite consume-once; admin-approval 202→403→approve→login; first-user-admin under every policy).First-user-is-admin semantics preserved under every policy. Email delivery of invites is out of scope per the ticket (token shown to admin to share manually).
Closes #219
🤖 Generated with Claude Code
📊 Test coverage
Patch coverage: no testable lines changed.
Overall (
app/,lib/,db/, excluding UI per ADR-0019):Soft thresholds per ADR-0019. Coverage is informational and does not block merge.