high priority low complexity testing pending testing specialist Tier 4

Acceptance Criteria

Sign-in success path: after signInWithEmailAndPassword with valid credentials, encrypted storage write is called exactly once with the returned session token
Sign-in failure path: Supabase 400 response is mapped to AuthResult.failure(AuthError.invalidCredentials)
Session restore path: restoreSession() with a valid cached token returns SessionRestoreResult.restored without calling signInWithPassword
Token refresh path: restoreSession() with an expired access token but valid refresh token calls refreshSession() and writes the refreshed token to storage
Sign-out path: signOut() calls Supabase signOut() and then calls encrypted storage delete — verified via mock interaction assertions
Expired + no-refresh path: restoreSession() with both tokens invalid returns SessionRestoreResult.expired and deletes the token from storage
No-session path: restoreSession() when storage returns null returns SessionRestoreResult.noSession without any Supabase API call
Rate-limit error (429) from Supabase is mapped to AuthError.tooManyRequests
All tests are deterministic and pass consistently without real network calls to Supabase production
Tests complete within 3 seconds total

Technical Requirements

frameworks
Flutter
flutter_test
mocktail or mockito
apis
Supabase GoTrue (mocked)
flutter_secure_storage (mocked)
data models
AuthRepository
Session
AuthResult
SessionRestoreResult
AuthError
performance requirements
All integration tests must complete within 3 seconds
No real network calls — all external dependencies are mocked
security requirements
Mock tokens used in tests must be clearly synthetic and not resemble real JWT structure with sensitive payloads
Test fixtures must not be committed with real Supabase project credentials

Execution Context

Execution Tier
Tier 4

Tier 4 - 323 tasks

Can start after Tier 3 completes

Implementation Notes

The primary challenge is mocking the Supabase Flutter SDK cleanly. SupabaseClient and GoTrueClient are not abstract classes by default, so use mocktail's registerFallbackValue() for any custom types passed to mock methods. Inject SupabaseClient and the storage adapter via the AuthRepository constructor for testability — avoid using Supabase.instance.client directly inside the repository. For the expired-token scenario, configure the mock to throw AuthException with the appropriate status code on recoverSession() and return a valid response on refreshSession().

Document the mock setup clearly so future engineers understand what each stub represents. Keep test fixture tokens as short opaque strings like 'mock-access-token-001'.

Testing Requirements

Integration tests using flutter_test with mocktail (preferred) or mockito for mocking SupabaseClient, GoTrueClient, and FlutterSecureStorage. Each lifecycle scenario gets its own test() with explicit mock setup via when().thenAnswer() and interaction verification via verify(). Use setUp() to reset mocks between tests. Group tests by scenario: sign-in, session restore, sign-out.

Test the AuthRepository in isolation — do not test BLoC or UI layers here. Run with flutter test test/repositories/auth_repository_test.dart.

Component
Authentication Repository
data low
Epic Risks (2)
high impact low prob integration

Supabase client initialization may fail silently in certain Flutter environments if environment variables are missing or the anon key is rotated, leading to runtime null-pointer errors throughout the auth layer.

Mitigation & Contingency

Mitigation: Add explicit assertion checks during app startup that verify the Supabase client is initialized before the router resolves. Document required --dart-define keys in the project README and add a CI step that validates their presence.

Contingency: Implement a fallback initialization error screen with a clear message and a retry button. Log initialization failures to crash reporting immediately.

medium impact medium prob technical

The flutter_secure_storage package behaviour differs between iOS Keychain and Android Keystore implementations. On Android, biometric-enrolled devices may require additional authentication to read stored tokens, causing unexpected session read failures.

Mitigation & Contingency

Mitigation: Test the repository on Android devices with and without biometric enrollment early in development. Use accessibility options in flutter_secure_storage to configure whether biometric authentication is required for storage access.

Contingency: If biometric-gated storage causes regressions, fall back to a non-biometric storage option for session tokens (reserving biometric-gated storage for higher-sensitivity credentials only).