high priority low complexity backend pending backend specialist Tier 1

Acceptance Criteria

distancePrefillServiceProvider is a Provider<DistancePrefillService> (not autoDispose, as it must survive UI navigation to maintain the stream subscription)
The provider subscribes to the Supabase auth state stream on first build via ref.listen or an internal StreamSubscription
On detecting an AuthChangeEvent.signedOut event, clearOnLogout is called with the previously authenticated userId
The stream subscription is cancelled in the provider's onDispose callback to prevent memory leaks
If the user signs out and signs back in as a different user, the new userId's prefill state is independent
The provider can be overridden in tests via ProviderContainer.overrides with a fake DistancePrefillService
No direct Supabase SDK calls in the DistancePrefillService itself — auth stream is accessed via a separate authStateChangesProvider and passed to this provider layer

Technical Requirements

frameworks
Dart (latest)
Flutter
Riverpod
Supabase
apis
Supabase Auth (onAuthStateChange stream)
data models
LocalDistanceCache
performance requirements
Stream subscription must be created once per app lifecycle, not once per widget rebuild
clearOnLogout must be a fire-and-forget operation — do not await it in a synchronous provider build
security requirements
Ensure clearOnLogout is always called on sign-out even if the UI has been navigated away from the mileage entry screen
Do not store userId in provider state beyond what is needed for the clearOnLogout call

Execution Context

Execution Tier
Tier 1

Tier 1 - 540 tasks

Can start after Tier 0 completes

Implementation Notes

Pattern: create a Notifier or use a plain Provider with a ref.onDispose block. Use Riverpod's ref.listen to watch an authStateChangesProvider (a StreamProvider wrapping supabase.client.auth.onAuthStateChange). In the listen callback, check if the event is AuthChangeEvent.signedOut and call service.clearOnLogout(previousUserId). Store the previous userId by reading the current session before the sign-out event clears it.

If using a Notifier, the build() method initialises the stream watcher via ref.listen. Avoid using keepAlive() unless the provider is explicitly required to persist — prefer letting the provider tree manage lifecycle naturally.

Testing Requirements

Unit tests (flutter_test with ProviderContainer): verify distancePrefillServiceProvider resolves without error; verify that simulating a sign-out event via a fake auth state stream causes clearOnLogout to be called on the fake DistancePrefillService (use a spy/mock); verify that provider disposal cancels the stream subscription (check that the fake stream's cancel callback is invoked). Use ProviderContainer with overrides for all dependencies.

Component
Distance Prefill Service
service low
Epic Risks (2)
medium impact medium prob integration

If OrgRateConfigRepository caches the per-km rate aggressively and an admin updates the rate mid-session, ongoing form interactions will show the old rate until the Stream emits. This could result in the UI showing a rate that differs from what is stored when the claim is submitted, causing confusion or disputes.

Mitigation & Contingency

Mitigation: Subscribe to a Supabase Realtime channel for the org_configuration table so config changes propagate within seconds. Document the eventual-consistency window in code comments.

Contingency: If Realtime subscription proves unreliable in test, add a polling fallback with a configurable interval (default 5 minutes) and display a 'rate updated' toast when the stream emits a changed value.

medium impact medium prob scope

The correction window within which a claim can be deleted or voided is not explicitly specified in the feature documentation. Implementing the wrong window (e.g. 24 hours vs 7 days) could lock users out of corrections or allow inappropriate post-approval modifications.

Mitigation & Contingency

Mitigation: Raise the correction window definition as a blocking question to the HLF product owner before implementing the delete/void path in MileageClaimRepository. Implement the window duration as an org-level configuration value rather than a hardcoded constant.

Contingency: If the question cannot be resolved before implementation, default to 24 hours as the most conservative option and flag the value for review in the first user-acceptance test.