Implement LoginFormBLoC authentication dispatch and state emission
epic-email-password-login-auth-logic-task-008 — Implement the SubmitPressed handler that dispatches signIn to AuthService, emits LoginLoading, then maps the typed domain exception results to the corresponding error states (LoginCredentialError, LoginNetworkError, LoginRateLimitError, LoginServerError) or LoginSuccess. Error state payloads must include a plain-language message key referencing the error message registry.
Acceptance Criteria
Technical Requirements
Execution Context
Tier 5 - 253 tasks
Can start after Tier 4 completes
Implementation Notes
Use a sealed class or abstract base class for LoginFormState with subtypes: LoginFormIdleState, LoginLoading, LoginSuccess, LoginCredentialError, LoginNetworkError, LoginRateLimitError, LoginServerError. The SubmitPressed handler in task-008 picks up after task-007's validation guard — structure the handler so validation check and auth dispatch are clearly separated (early return pattern). Catch exceptions by type using on clauses in a try/catch chain — avoid catching Exception broadly first. The messageKey values should be defined as string constants (e.g.
ErrorKeys.invalidCredentials) so the UI layer can look them up in a localization/message map. After emitting an error state, the BLoC should not require a reset — the user can immediately re-type and resubmit.
Testing Requirements
Unit tests using bloc_test. For each exception type thrown by mocked AuthService, assert: (1) LoginLoading is emitted first, (2) correct typed error state is emitted second with correct messageKey. For success path: assert LoginLoading then LoginSuccess with correct session and role. Verify no LoginLoading emitted if validation fails (integration with task-007 handler).
Use Mockito or mocktail to mock AuthService. Test the unknown exception fallback branch explicitly. Target 100% branch coverage on the catch block.
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.