Implement AuthService with Supabase email/password sign-in
epic-email-password-login-auth-logic-task-003 — Implement the concrete AuthService class wrapping supabase.auth.signInWithPassword(). Call the GoTrue error mapper on all caught exceptions and rethrow as typed domain exceptions. Return a typed SessionResult on success containing the Supabase Session. Wire dependency injection via Riverpod provider.
Acceptance Criteria
Technical Requirements
Execution Context
Tier 2 - 518 tasks
Can start after Tier 1 completes
Implementation Notes
Use constructor injection for SupabaseClient rather than Supabase.instance.client to keep the class testable. The Riverpod provider should read the SupabaseClient from a supabaseClientProvider (already present in most Supabase+Riverpod setups). Wrap the signInWithPassword call in a try/catch(Object e) — catch Object, not Exception, because GoTrue may throw non-Exception Dart errors on network failures. After catching, immediately call GoTrueErrorMapper.map(e) and throw the result.
Never swallow exceptions silently. SessionResult should be a simple immutable value object (Dart record or @freezed class): `(String userId, String accessToken)`. Keep the implementation file under 100 lines; if it grows, extract helper methods.
Testing Requirements
Two test layers: (1) Unit tests using a MockSupabaseClient (mockito or mocktail): verify signIn() calls signInWithPassword with the correct arguments; verify GoTrueErrorMapper is invoked on caught exceptions; verify AuthSuccess is returned on mock success. (2) Integration test (optional, run against a Supabase local dev instance via supabase start): verify real sign-in with seeded credentials returns a valid Session. Use flutter_test with group('SupabaseAuthService', ...) structure. Mock the SupabaseClient, not the GoTrueErrorMapper — test the mapper separately.
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.