critical priority low complexity infrastructure pending infrastructure specialist Tier 2

Acceptance Criteria

A `noAccessConfigRepositoryProvider` Riverpod provider is defined and exported from the feature's provider file
The provider creates a `NoAccessConfigRepository` instance, injecting the Supabase client from an existing `supabaseClientProvider` (or equivalent)
Provider type is `Provider<NoAccessConfigRepository>` (not `FutureProvider`) — the async work is handled inside `getConfig()`, not at construction time
The provider is accessible from `AccessDenialService` and `NoAccessRouteGuard` via `ref.read` or `ref.watch`
The provider is placed in the correct providers file (e.g., `lib/features/no_access/providers/no_access_providers.dart`)
`flutter analyze` reports zero warnings or errors
Downstream providers/guards can be tested using `ProviderContainer` with an overridden `noAccessConfigRepositoryProvider`

Technical Requirements

frameworks
Flutter
Dart
Riverpod
data models
NoAccessConfig
NoAccessConfigRepository
performance requirements
Provider construction is synchronous — no `await` at provider creation time
Provider is not `autoDispose` unless the repository's in-memory cache should be cleared on screen exit (discuss with team — likely keep-alive is preferred)
security requirements
The Supabase client injected into the repository must come from the app's authenticated Supabase provider, not a hardcoded instance

Execution Context

Execution Tier
Tier 2

Tier 2 - 518 tasks

Can start after Tier 1 completes

Implementation Notes

Use `Provider((ref) { final client = ref.read(supabaseClientProvider); return NoAccessConfigRepository(client); })` as the standard pattern. If the project uses code generation (`riverpod_generator`), define with `@riverpod` annotation instead. Do not use `FutureProvider` here — the repository's async interface (`getConfig()`) is already `Future`-based, so the provider itself does not need to be async. Prefer `keepAlive: true` (or omit `autoDispose`) so the cache survives navigation and is not destroyed when the guard temporarily loses all listeners.

Place the provider in the feature's providers file and barrel-export it from the feature's main export file.

Testing Requirements

No dedicated test file required for the provider declaration itself. Testability is validated by overriding `noAccessConfigRepositoryProvider` in `AccessDenialService` and `NoAccessRouteGuard` unit tests using `ProviderContainer(overrides: [noAccessConfigRepositoryProvider.overrideWithValue(mockRepo)])`. Verify this override pattern works correctly as part of the dependent component test tasks.

Epic Risks (2)
high impact medium prob technical

Supabase remote config may be unavailable at app startup (network error, cold start), causing the repository to return no blocked-role list. If the fallback is empty, blocked users could access the app.

Mitigation & Contingency

Mitigation: Define a local constants fallback list of blocked roles compiled into the app binary. Remote config enriches or overrides this list when available.

Contingency: If remote config repeatedly fails in production, pin the blocked-role list to local constants only and disable remote override until the Supabase config endpoint is stabilised.

medium impact low prob dependency

url_launcher package behaviour differs between iOS and Android (e.g. canLaunchUrl returning false on some Android configurations), leading to silent failures when the admin portal link is tapped.

Mitigation & Contingency

Mitigation: Run canLaunchUrl check before every launch attempt and surface a descriptive inline error message (e.g. 'Could not open link — visit admin.example.org manually') when the check fails.

Contingency: If canLaunchUrl is consistently unreliable on a target platform, replace the tap-to-open pattern with a copyable text field showing the URL as a fallback.