Wire session persistence listener in LoginFormBLoC
epic-email-password-login-auth-logic-task-009 — Add an on-success side-effect in LoginFormBLoC that triggers AuthService.persistSession() after emitting LoginSuccess. Also handle session restoration on BLoC initialization: if a valid persisted session is found, immediately emit LoginSuccess with the restored session without user interaction, bypassing the login form entirely.
Acceptance Criteria
Technical Requirements
Execution Context
Tier 6 - 158 tasks
Can start after Tier 5 completes
Implementation Notes
Trigger session restoration in the BLoC constructor by adding an AppStarted or CheckSessionEvent and dispatching it immediately in the constructor body. Set the BLoC's initial state to LoginLoading so the UI shows a spinner during the check. Use unawaited() (from dart:async) for persistSession() if you want fire-and-forget, or await it inside a try/catch that only logs on failure. Keep restoration logic inside AuthService — the BLoC should only call restoreSession() and react to the result, not implement token reading itself.
This keeps the BLoC thin and testable.
Testing Requirements
Unit tests using bloc_test. Test (1) BLoC init with valid stored session → emits LoginLoading then LoginSuccess; (2) BLoC init with no stored session → emits LoginLoading then LoginFormIdleState; (3) BLoC init with expired session → emits LoginLoading then LoginFormIdleState; (4) after SignIn success, verify persistSession() is called on mock AuthService; (5) persistSession() throws — verify LoginSuccess was already emitted and no additional state change occurs. Mock AuthService with Mockito/mocktail.
Supabase GoTrue returns HTTP error codes and string messages that may change between SDK versions. Incorrect or incomplete mapping could cause the wrong user-facing message to be shown (e.g., showing a generic error instead of a specific credential error), violating the plain-language feedback acceptance criteria and potentially exposing security-sensitive information.
Mitigation & Contingency
Mitigation: Pin the supabase_flutter SDK to a specific minor version in pubspec.yaml. Write integration tests that mock the Supabase HTTP layer and assert each error code maps to the correct domain exception. Document the mapping table as a constant in AuthService.
Contingency: If an unrecognized error code is received at runtime, catch it as an UnknownAuthException and display a generic safe message. Alert via crash reporting for triage and SDK update.
If the user taps the sign-in button multiple times rapidly, concurrent authentication requests could result in race conditions: duplicate network calls, out-of-order state emissions, or multiple session tokens being written to secure storage.
Mitigation & Contingency
Mitigation: Use bloc concurrency transformer (droppable or restartable) to ensure only one authentication event is processed at a time. The BLoC should guard against submission while in LoginLoading state.
Contingency: Add a UI-level disable on the submit button when loading state is active as a secondary guard independent of BLoC concurrency control.