critical priority medium complexity backend pending backend specialist Tier 3

Acceptance Criteria

OrgLabelsProvider is implemented as a Riverpod AsyncNotifier<Map<LabelKey, String>>
Provider loads label mappings for the currently selected organization on initialization
All four partner organizations (NHF, Blindeforbundet, HLF, Barnekreftforeningen) have label override maps defined
When the selected organization changes, OrgLabelsProvider automatically reloads and exposes the new org's labels
In the loading state, widgets consuming the provider display a loading indicator without crashing
In the error state, the provider exposes a typed error and widgets fall back to default Norwegian labels
Label maps are serializable and can be sourced from either a Supabase table or a bundled JSON asset — implementation must support both without changing the provider interface
Unit tests verify that switching orgs triggers a fresh label load
Terminology overrides match the documented per-org terminology (e.g., NHF uses 'chapter' vs. HLF uses 'local branch')

Technical Requirements

frameworks
Flutter
Riverpod (AsyncNotifier)
Supabase Dart SDK
apis
Supabase REST API — org_labels table or equivalent, filtered by organization_id
Flutter asset bundle (bundled JSON fallback)
data models
LabelKey (enum or sealed class of all known label keys)
OrgLabelMap (Map<LabelKey, String>)
Organization
performance requirements
Label map must be loaded before the first screen requiring terminology is displayed
Cached in memory for the duration of the session — no repeated network calls for the same org
security requirements
Label data is non-sensitive and does not require encryption
Supabase RLS should allow all authenticated users to read org_labels for their own org
ui components
AsyncValue loading/error widgets in consuming screens

Execution Context

Execution Tier
Tier 3

Tier 3 - 413 tasks

Can start after Tier 2 completes

Implementation Notes

Define LabelKey as an enum covering all known terminology keys (e.g., LabelKey.peerMentor, LabelKey.localChapter, LabelKey.coordinator). The Map approach is type-safe and avoids stringly-typed lookups. For the data source strategy, prefer a bundled JSON asset as the primary source (zero network latency, works offline) and treat Supabase as an optional override layer for dynamic updates — this follows the design principle of lowest cognitive load and resilient UX. The AsyncNotifier's build() method should: (1) read the current org ID from OrgSelectionService, (2) load the label map for that org, (3) merge org-specific overrides on top of a default Norwegian base map.

Use ref.watch(currentOrgProvider) inside build() so Riverpod automatically invalidates and rebuilds when the org changes.

Testing Requirements

Use flutter_test with Riverpod's ProviderContainer for isolated provider testing. Test cases: (1) provider loads correct labels for each of the four orgs, (2) provider emits loading state before data arrives, (3) provider emits error state on Supabase failure and labels fall back gracefully, (4) switching orgs (invalidating the provider) triggers a fresh load, (5) bundled JSON fallback is used when Supabase is unreachable. Mock both the Supabase client and the asset bundle in tests.

Component
Organization Labels Provider
infrastructure 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.