critical priority medium complexity backend pending backend specialist Tier 4

Acceptance Criteria

selectOrganization() does not return/complete until OrgLabelsProvider has emitted a non-loading state (data or error)
After selectOrganization() completes, all downstream providers that depend on the selected org are fully initialized
Riverpod provider invalidation is triggered for OrgLabelsProvider and any org-config providers after a new org is selected
Branding tokens (color palette, logo URL) for the newly selected org are applied before the app navigates away from the selection screen
Feature flags specific to the selected org are loaded and accessible before navigation
If the initialization sequence fails (e.g., labels fail to load), selectOrganization() surfaces the error and does not navigate away from the selection screen
Re-selecting the same organization is a no-op (no unnecessary re-initialization)
Unit tests verify that provider invalidation is called after a successful selection
Integration test verifies the full selection → init → navigation sequence completes without intermediate loading screens visible to the user

Technical Requirements

frameworks
Flutter
Riverpod (ref.invalidate, ref.read, ProviderContainer)
Supabase Dart SDK
apis
Supabase REST API — org_config or feature_flags table filtered by organization_id
data models
Organization
OrgConfig (feature flags, branding tokens)
OrgLabelMap
performance requirements
Full post-selection init sequence (labels + config) must complete within 3 seconds on a 4G connection
Initialization must not block the UI thread — use async/await throughout
security requirements
Feature flags and branding tokens are non-sensitive but must be scoped to the authenticated user's org
Do not expose config from another org to the current user
ui components
Loading overlay or progress indicator on the org selection screen during init

Execution Context

Execution Tier
Tier 4

Tier 4 - 323 tasks

Can start after Tier 3 completes

Implementation Notes

The key challenge here is coordinating async initialization across multiple Riverpod providers without race conditions. The recommended pattern: in selectOrganization(), after persisting the org ID, call ref.invalidate(orgLabelProvider) and ref.invalidate(orgConfigProvider), then immediately await ref.read(orgLabelProvider.future) and ref.read(orgConfigProvider.future) to ensure both have settled before returning. This 'invalidate then await future' pattern is idiomatic Riverpod and prevents the navigation layer from proceeding before providers are ready. Do NOT use artificial delays or timers.

For branding tokens, apply design token overrides to a top-level ThemeData provider so the entire widget tree rebuilds with the new org's palette atomically.

Testing Requirements

Use flutter_test with Riverpod's ProviderContainer. Test cases: (1) after selectOrganization(), OrgLabelsProvider is in data state (not loading), (2) provider invalidation is called exactly once per new org selection, (3) re-selecting the same org does not trigger invalidation, (4) failure during label init causes selectOrganization() to throw and does not persist the org ID, (5) branding tokens are applied to the correct provider after selection. Mock all downstream providers and verify call order.

Component
Organization Selection Service
service low
Epic Risks (2)
high impact medium prob technical

The OrgLabelsProvider must be fully initialized before any UI widget renders organization-specific text. If the service triggers label initialization asynchronously and the UI builds before the labels stream emits, widgets will briefly display raw label keys instead of human-readable text, which constitutes a WCAG 2.2 AA failure for screen readers that announce whatever text is present at render time.

Mitigation & Contingency

Mitigation: Design the OrgSelectionService.select() method to await OrgLabelsProvider initialization before completing its Future — callers receive a resolved future only after labels are ready. Use an AsyncValue loading state to gate UI rendering via Riverpod's when() pattern.

Contingency: If awaiting initialization causes perceivable UI lag, implement an optimistic render with a skeleton loading state that is announced by the live-region-announcer as 'Loading organization content' so screen readers do not announce raw keys.

medium impact medium prob integration

If the label definitions loaded from the backend for each organization do not match the label key registry used in the UI, widgets will fall back to raw keys silently. This is particularly harmful for Blindeforbundet users relying on VoiceOver, where a raw key announced by a screen reader is incomprehensible.

Mitigation & Contingency

Mitigation: Define a compile-time label key registry (enum or const strings) and assert at OrgLabelsProvider initialization that all required keys are present in the loaded map. Log a structured warning for any missing key and substitute a human-readable fallback string rather than the raw key.

Contingency: If a label schema mismatch reaches production, the OrgLabelsProvider fallback mechanism ensures users see a reasonable English default rather than a raw key. A backend label patch can be deployed without an app release.