high priority low complexity frontend pending frontend specialist Tier 1

Acceptance Criteria

`launchUrl` (or a new overload `launchUrlWithFeedback`) accepts an optional `BuildContext? context` or `void Function(String message)? onFailure` callback parameter
When `UrlLaunchResult.unsupported` is returned AND a context/callback is provided, a `SnackBar` with a localised error message is shown via `ScaffoldMessenger.of(context)`
When `UrlLaunchResult.error(message)` is returned AND a context/callback is provided, the same snackbar mechanism triggers with an appropriate user-facing message (not the raw platform error string)
When `UrlLaunchResult.success` is returned, no snackbar or dialog is displayed
When no context/callback is provided, failures are silent (callers that handle `UrlLaunchResult` themselves are unaffected)
The snackbar message copy is sourced from the app's localisation/design-token system, not hardcoded strings
The snackbar meets WCAG 2.2 AA contrast requirements (matches the design token system)
`flutter analyze` passes with zero issues after changes

Technical Requirements

frameworks
Flutter
url_launcher (^6.x)
data models
UrlLaunchResult
performance requirements
SnackBar display adds no perceptible latency to the tap response
security requirements
Raw platform exception messages must not be surfaced in the snackbar text to avoid information leakage
ui components
SnackBar
ScaffoldMessenger

Execution Context

Execution Tier
Tier 1

Tier 1 - 540 tasks

Can start after Tier 0 completes

Implementation Notes

Prefer an optional `onFailure` callback over passing `BuildContext` directly into the utility class—this keeps the utility layer decoupled from the widget tree and easier to test without a full widget pump. The callback signature `void Function(UrlLaunchResult result)` gives callers full flexibility (snackbar, dialog, log, etc.). The no-access screen widget will provide the concrete implementation that shows the snackbar. If the project has a centralised `AppSnackbar.show(context, message)` helper, use it here for consistency.

Ensure the user-facing message is distinct for `unsupported` (e.g., 'No app found to open this link') vs `error` (e.g., 'Could not open link. Try again later.'). Both messages need to be accessible to screen readers—`SnackBar.content` should be a `Text` widget with correct semantics.

Testing Requirements

Covered by `epic-no-access-screen-foundation-task-007`. For this subtask, add a widget test that pumps a minimal `Scaffold` wrapping a button that calls `launchUrlWithFeedback` with a mocked failing platform, then asserts that a `SnackBar` with the expected message text appears in the widget tree using `find.byType(SnackBar)` and `find.text(...)`. Verify the success path does NOT produce a snackbar.

Component
URL Launcher Utility
infrastructure low
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.