high priority low complexity frontend pending frontend specialist Tier 1

Acceptance Criteria

A logout button is rendered as the last interactive element in the no-access screen
The button uses the primary action button style from the design token system (AppButton or equivalent reusable widget)
The touch target is at least 44×44 dp
Tapping the button triggers the Supabase sign-out flow (auth.signOut())
After sign-out completes, the user is navigated to the authentication screen (organisation selection or login)
During the sign-out async operation, the button shows a loading indicator and is disabled to prevent double-tap
If sign-out fails, an error message (snackbar or dialog) is shown and the button returns to its default state
The button label is sourced from the ARB localisation file
A Semantics widget provides role: button and a descriptive label for screen readers
The button colour contrast meets WCAG 2.2 AA (4.5:1 for text on button background)

Technical Requirements

frameworks
Flutter
Riverpod
BLoC
apis
Supabase auth.signOut()
performance requirements
Sign-out must be async and not block the UI thread
Navigation after sign-out must use the router (GoRouter or equivalent) to reset the navigation stack
security requirements
After sign-out, all locally cached user session data and tokens must be cleared
Navigation stack must be fully reset so the back button cannot return to the no-access screen after logout
ui components
AppButton (existing reusable primary button widget) or equivalent design-token-styled button
CircularProgressIndicator inside the button during loading state
Semantics widget with button role and descriptive label

Execution Context

Execution Tier
Tier 1

Tier 1 - 540 tasks

Can start after Tier 0 completes

Implementation Notes

Use the project's existing authentication BLoC or Riverpod notifier to trigger sign-out rather than calling Supabase directly from the widget — this keeps the widget decoupled from the auth provider. The sign-out action should dispatch an event (e.g. AuthEvent.signOutRequested) and the widget should listen for the resulting state change to trigger navigation. Use the app's reusable AppButton widget to maintain consistent visual style.

Set the navigation action to use context.go('/') or equivalent router reset so the back stack is cleared. Ensure the ARB key is something like commonLogout or noAccessScreenLogoutButton.

Testing Requirements

Write widget and unit tests using flutter_test. Test 1: mock the auth sign-out method and assert it is called when the button is tapped. Test 2: assert the loading indicator appears while sign-out is in progress. Test 3: assert the button is disabled during loading (cannot be tapped twice).

Test 4: mock a sign-out failure and assert an error message is displayed. Test 5: assert navigation to the auth screen occurs after successful sign-out by verifying the router receives the correct navigation event. Test 6: verify the Semantics node has the correct label and button role.

Component
No-Access Screen
ui low
Epic Risks (2)
medium impact medium prob technical

Flutter's live region (SemanticsProperties.liveRegion) announcement may be delayed or swallowed by the OS accessibility engine if the Semantics tree is not fully built when the screen mounts, causing screen-reader users to miss the denial announcement.

Mitigation & Contingency

Mitigation: Trigger the live region announcement from a post-frame callback (WidgetsBinding.addPostFrameCallback) to ensure the Semantics tree is committed before the announcement fires. Test on both VoiceOver (iOS) and TalkBack (Android) physical devices.

Contingency: If live region timing is unreliable, fall back to using SemanticsService.announce() directly in the initState post-frame callback, which provides more deterministic announcement timing.

low impact low prob scope

The organisation logo may fail to load (network error, missing asset) leaving a broken image in an otherwise functional screen, degrading the professional appearance and potentially confusing users.

Mitigation & Contingency

Mitigation: Wrap the logo widget in an error builder that renders a styled fallback (organisation name text or a generic icon) when the logo asset or network image fails to load.

Contingency: If logo loading is persistently unreliable across organisations, remove the logo from the no-access screen entirely in favour of a text-only header using the organisation's display name from the design token system.