fix: prevent sign-out crash and surface real email-send failures
CI / skip-ci-check (pull_request) Successful in 4s
CI / docker-ci (pull_request) Successful in 6s
CI / secret-scan (pull_request) Successful in 9s

- NextAuth session/jwt callbacks no longer return null (the client
  useSession() hook chokes on a null session, crashing the app on
  sign-out for deactivated/refreshed sessions) — fixes #57
- UserMenu/Header sign-out handlers close the Manage Users overlay and
  popover before calling signOut(), and no longer let a rejected
  signOut() promise go unhandled
- Added an app-level error boundary as a safety net for any remaining
  client render errors
- Registration and forgot-password flows now tell the user honestly
  when the confirmation/reset email failed to send instead of always
  claiming success — related to #56
- lib/email.ts throws a clear, actionable error when neither
  SMTP nor Resend is configured, instead of a cryptic SDK error
- Documented required SMTP/Resend env vars in DEPLOYMENT_CHECKLIST.md
  (were missing entirely, which is why no confirmation/reset emails
  were ever sent in deployed environments) — fixes #56
This commit is contained in:
2026-07-14 12:44:33 -04:00
parent 3e39f978f6
commit bb09159133
9 changed files with 121 additions and 18 deletions
+11 -1
View File
@@ -29,7 +29,17 @@ function UserMenu() {
const [popoverOpen, setPopoverOpen] = useState(false);
const handleSignOut = async () => {
await signOut({ callbackUrl: '/' });
// Close any overlays tied to the authenticated state (e.g. Manage Users)
// *before* the session clears, otherwise their effects/portals can unmount
// mid-transition and throw (issue #57).
setPopoverOpen(false);
setManageUsersOpen(false);
try {
await signOut({ callbackUrl: '/' });
} catch (error) {
console.error('[SIGN_OUT] Failed to sign out cleanly:', error);
router.push('/');
}
};
if (status === 'loading') {