critical priority medium complexity backend pending backend specialist Tier 2

Acceptance Criteria

SupabaseAuthService implements AuthService (the interface from task-001)
signIn() calls supabase.auth.signInWithPassword(email: email, password: password) inside a try/catch
All caught exceptions are passed through GoTrueErrorMapper before being rethrown as domain exceptions
On success, signIn() returns AuthSuccess wrapping a SessionResult containing userId and accessToken
signOut() calls supabase.auth.signOut() and rethrows mapped exceptions on failure
A Riverpod Provider<AuthService> (or AsyncNotifierProvider) is defined in lib/features/auth/data/auth_service_provider.dart
The provider exposes AuthService (the interface), not SupabaseAuthService (the concrete class)
SupabaseClient is injected into SupabaseAuthService via constructor (not accessed as global singleton)
No BLoC or UI imports exist in this file
Integration test confirms a valid sign-in returns AuthSuccess; an invalid one returns AuthFailure with InvalidCredentialsException
flutter analyze reports zero errors or warnings on this file

Technical Requirements

frameworks
Flutter
Dart
Supabase Flutter SDK
Riverpod
apis
Supabase Auth — signInWithPassword
Supabase Auth — signOut
data models
SessionResult
AuthResult
AuthSuccess
AuthFailure
performance requirements
signIn() must complete within 5 seconds on a standard mobile network; enforce timeout at the HTTP client level if needed
security requirements
Password must never be logged or stored beyond the duration of the sign-in call
Access tokens must not be stored in plain shared preferences — use flutter_secure_storage (task-004 handles persistence, but this layer must not bypass it)

Execution Context

Execution Tier
Tier 2

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.

Component
Authentication Service
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.