critical priority low complexity frontend pending frontend specialist Tier 1

Acceptance Criteria

LoginEvent sealed class is defined with subclasses: EmailChanged(String email), PasswordChanged(String password), SubmitPressed(), VisibilityToggled()
LoginState sealed class is defined with subclasses: LoginIdle, LoginLoading, LoginSuccess, LoginCredentialError, LoginNetworkError, LoginRateLimitError, LoginServerError
LoginSuccess carries session (SessionResult) and role (UserRole) fields
LoginRateLimitError carries optional retryAfterSeconds (int?) for displaying countdown to the user
LoginNetworkError carries isTimeout (bool) to distinguish timeout from no-connectivity
All state classes are immutable (final fields, const constructors where possible)
All event classes are immutable
LoginIdle is the initial state and carries email (String), password (String), and isPasswordVisible (bool) fields to allow form field restoration
No AuthService, Supabase, or Riverpod imports exist in this events/states file — pure BLoC domain
flutter analyze passes with zero warnings on this file

Technical Requirements

frameworks
Flutter
Dart
BLoC (flutter_bloc)
data models
SessionResult
UserRole
performance requirements
All state and event classes must be lightweight value objects — no heavy computation in constructors
security requirements
Password field must NOT be stored in any state class — only the BLoC holds transient form values, never emitting them back into state
Email field in LoginIdle is acceptable (low sensitivity), but password must be excluded from all state emissions
ui components
LoginScreen will consume these states to render error banners, loading spinner, and password visibility toggle
Semantics live region widget will subscribe to error state changes for WCAG 2.2 AA compliance

Execution Context

Execution Tier
Tier 1

Tier 1 - 540 tasks

Can start after Tier 0 completes

Implementation Notes

Place states in lib/features/auth/presentation/bloc/login_state.dart and events in login_event.dart. Use Dart 3 sealed classes for compile-time exhaustiveness in switch expressions in the UI layer — this is critical so the widget tree must handle every state variant or the compiler warns. Do NOT use a single LoginState with an error enum field — granular state types are required for WCAG 2.2 AA live region announcements (each distinct state triggers a Semantics announcement, whereas a single state with changing fields may not). Consider using package:equatable or @freezed for equality and copyWith — consistent with other BLoC classes in the project.

The password visibility toggle (VisibilityToggled event → isPasswordVisible in LoginIdle) must be handled without re-emitting the password value.

Testing Requirements

Unit tests in test/features/auth/presentation/login_form_bloc_test.dart (states/events file itself): (1) Verify LoginIdle, LoginLoading, and each error state can be instantiated. (2) Verify LoginSuccess carries non-null session and role. (3) Verify LoginRateLimitError with retryAfterSeconds: 30 exposes the value. (4) Verify LoginIdle.copyWith(email: 'x') returns a new instance with updated email and unchanged other fields (if copyWith is implemented).

(5) Accessibility test: verify each granular error state has a distinct type (not just a string field) so Semantics widgets can announce specific messages per error type. Use flutter_test, no mocking required.

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.