high priority low complexity backend pending backend specialist Tier 3

Acceptance Criteria

A top-level Riverpod provider named secureSessionStorageProvider is declared and exposes an ISecureSessionStorage instance
The provider is a Provider<ISecureSessionStorage> (not StateNotifierProvider — storage is stateless infrastructure)
The underlying FlutterSecureStorage instance is created inside the provider factory, not passed as an external parameter, unless an override is provided in tests
The provider file is placed under lib/features/auth/infrastructure/providers/ or lib/providers/ consistent with the project's existing provider organisation
The provider is globally scoped (declared at file-level, not inside a widget or function)
An override for testing is possible via ProviderContainer(overrides: [secureSessionStorageProvider.overrideWithValue(fakeStorage)])
No other file directly instantiates SecureSessionStorageImpl — all access goes through the provider

Technical Requirements

frameworks
Flutter
Riverpod (flutter_riverpod)
apis
Riverpod Provider
FlutterSecureStorage constructor
data models
ISecureSessionStorage
SecureSessionStorageImpl
performance requirements
Provider creation is synchronous and lightweight — FlutterSecureStorage constructor does no I/O
Provider must be kept alive for the app lifetime (no autoDispose)
security requirements
FlutterSecureStorage options (iOptions, aOptions) must be set in the provider factory to enforce Keychain accessibility and Android Keystore encryption, matching the settings used in SecureSessionStorageImpl
Provider must not cache decrypted session data in memory — reads always go through FlutterSecureStorage

Execution Context

Execution Tier
Tier 3

Tier 3 - 413 tasks

Can start after Tier 2 completes

Implementation Notes

Use a plain Provider rather than StateNotifierProvider because SecureSessionStorage holds no in-memory reactive state — it is a pure I/O adapter. If the project uses code generation (riverpod_generator), follow that pattern with @riverpod and ref.keepAlive(). If not, use the manual Provider() syntax. Place the FlutterSecureStorage instantiation here rather than inside SecureSessionStorageImpl's constructor, so the Riverpod layer owns the platform options configuration.

This separation makes it easy to supply a ProviderScope override in widget tests without touching the implementation class.

Testing Requirements

Unit tests using flutter_test and a ProviderContainer: (1) secureSessionStorageProvider resolves to an ISecureSessionStorage instance without throwing, (2) overriding the provider with a fake works correctly and the fake's methods are called instead of the real implementation. These are lightweight wiring tests — the storage behaviour itself is tested in task-010.

Component
Secure Session Storage
data low
Epic Risks (3)
high impact medium prob technical

iOS Keychain access requires correct entitlement configuration and provisioning profile setup. Misconfigured entitlements cause silent failures in CI/CD and on physical devices, where the plugin appears to work in the simulator but fails at runtime. This can delay foundation delivery and block all downstream epics.

Mitigation & Contingency

Mitigation: Add a dedicated integration test running on a physical iOS device early in the epic. Document required entitlements and provisioning steps in a developer runbook. Validate Keychain access in the CI pipeline using an iOS simulator with correct entitlements enabled.

Contingency: If Keychain entitlements cannot be resolved quickly, temporarily use in-memory storage behind the SecureSessionStorage interface to unblock downstream epics, then resolve the Keychain issue in a hotfix before release.

medium impact medium prob dependency

The Flutter local_auth plugin has a history of breaking API changes between major versions, and its Android implementation depends on BiometricPrompt which behaves differently across Android API levels (23-34). An incompatible plugin version or unexpected Android API behaviour can cause authentication failures on a significant portion of the target device fleet.

Mitigation & Contingency

Mitigation: Pin local_auth to a specific stable version in pubspec.yaml. Test against Android API levels 23, 28, and 33 in the CI matrix. Review the plugin changelog and migration guide before adopting any version bump.

Contingency: If the pinned version proves incompatible with target devices, evaluate flutter_local_auth_android as a replacement or fork the plugin adapter to isolate the breaking surface.

high impact low prob security

If users upgrade from a version of the app that stored session data in non-encrypted storage (SharedPreferences), a migration path is required. Failing to migrate silently leaves old tokens in plain storage, creating a security gap and potentially causing confusing authentication state on first launch of the new version.

Mitigation & Contingency

Mitigation: Audit existing storage usage across the codebase before writing SecureSessionStorage. If legacy plain storage keys exist, implement a one-time migration routine that reads from SharedPreferences, writes to Keychain/Keystore, and deletes the plain-text entry.

Contingency: If migration is discovered late, ship the migration as a mandatory patch release before the biometric feature is enabled for users, and add a startup check that blocks biometric opt-in until migration is confirmed complete.