- Max 10 pending invites per user (400 if exceeded)
- List sorted: pending → used → expired
- Expired invites hidden after 30 days
- Frontend shows error toast from server message on invite creation failure
- Tests: testInviteMaxTenPending, testInviteListSortOrder, testInviteExpiredHiddenAfter30Days
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
- 401 for unauthenticated requests
- 403 for authenticated non-admin users
- 200 with full user list for admin (looks up existing ADMIN_EMAIL user,
skips gracefully if not present in DB)
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Registration failed visibly because the controller returned successfully
(user created, invite consumed) but the JS then called loadGoals() without
an authenticated session — causing a 401 that surfaced as an error to the user.
- Add Security::login() after user creation so the session is established
immediately, matching the documented "registers + auto-logs in" behavior
- Wrap user persist and invite consumption in a single DB transaction so
the invite token can never be consumed if user creation fails
- Add 12 integration tests covering auto-login, locale updates, logout,
partial goal updates, invite isolation, and various edge cases (110 assertions total)
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>