Implement end-to-end invitation acceptance: neutral entry route validates token and routes to register (new users), login (existing users), or auto-accepts (authenticated users). Handles 2FA token survival via session, email case-insensitive matching, and dedicated error pages. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
1.6 KiB
1.6 KiB
Deferred Work
From: tech-spec-fix-permission-nudge-bulk-bugs (2026-03-27)
- Null contact_email guard in BulkNotificationController — If a client exists but has null
contact_email,Mail::to(null)will throw. Add a filter for non-null email before sending. - Cross-page selection UX on declarations page — Navigating between pages clears selections silently. Consider persisting selections across pages or warning the user.
- Bulk notify count mismatch UX — When some selected declarations are filtered out (no client), the success message count differs from the selection count with no explanation. Consider showing skipped count.
- Nudge email template null guards —
nudge-notification.blade.phprenders$clientName,$declarationType,$dueDatewithout null fallbacks, producing blank labels.
From: tech-spec-team-invitation-acceptance (2026-03-27)
- Race condition on concurrent invitation acceptance — Two users clicking the same invitation link simultaneously could both pass
isValid()before either setsaccepted_at. Fix withSELECT FOR UPDATEor atomicUPDATE WHERE accepted_at IS NULL. - Multiple pending invitations per email/workspace — No unique constraint on
[workspace_id, email]inteam_invitations. Multiple tokens can exist for the same email+workspace. Second token inCreateNewUserpath would hit unique constraint onworkspace_userand throw. - Vue cross-link URLs should come from PHP props — Register.vue and Login.vue construct invitation-aware login/register URLs via JS string interpolation instead of receiving them as props from the controller.