critical priority medium complexity frontend pending frontend specialist Tier 5

Acceptance Criteria

SubmitPressed (after passing validation) emits LoginLoading as first state transition
Successful AuthService.signIn() result emits LoginSuccess with session and role payload
InvalidCredentialsException from AuthService maps to LoginCredentialError state
NetworkException maps to LoginNetworkError state
RateLimitException maps to LoginRateLimitError state
ServerException maps to LoginServerError state
Unknown/unhandled exception maps to LoginServerError with generic fallback message key
All error states include a messageKey string referencing the error message registry (not raw user-facing strings)
LoginSuccess state includes both the authenticated session object and the resolved user role
After emitting any error state, BLoC returns to a recoverable state (user can re-submit)
No error state is a generic 'LoginError' — each category has its own typed state class
LoginLoading state does not carry field values (clean loading indicator state)

Technical Requirements

frameworks
Flutter
BLoC (flutter_bloc)
apis
AuthService.signIn(email, password)
data models
LoginSuccess (session, role)
LoginCredentialError (messageKey)
LoginNetworkError (messageKey)
LoginRateLimitError (messageKey)
LoginServerError (messageKey)
LoginLoading
AuthSession
UserRole
performance requirements
AuthService.signIn() must be awaited within the event handler — no fire-and-forget
Error state emission must be immediate upon exception catch — no retry delay in BLoC layer
security requirements
Credentials must not be stored in any emitted state after SubmitPressed
LoginLoading and all error/success states must not carry raw email/password values
Exception messages from Supabase must never be forwarded directly to UI — only messageKey references

Execution Context

Execution Tier
Tier 5

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.

Component
Login Form BLoC
service medium
Epic Risks (2)
high impact medium prob integration

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.

medium impact medium prob technical

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.