critical priority low complexity backend pending backend specialist Tier 1

Acceptance Criteria

An abstract class OrgLabelsProvider is defined under lib/domain/providers/ or lib/domain/services/
getLabel(LabelKey key) returns String — synchronous lookup for a label in the active organization's scope, returning the default term if no override exists
getLabelsForOrg(String orgId) returns Map<LabelKey, String> — returns all label overrides for a given org
A LabelKey enum is defined in lib/domain/models/label_key.dart covering at minimum: activity, peer_mentor, coordinator, organization, report, event, contact, role, registration
Each LabelKey enum value has a defaultValue getter returning the standard English term used as fallback
The LabelKey enum is exhaustive — no raw string label keys exist anywhere in the app outside this file
OrgLabelsProvider is exported from the domain barrel
Dart analyzer reports zero errors and zero warnings across all new files

Technical Requirements

frameworks
Flutter
Dart
Riverpod
data models
Organization
LabelKey
performance requirements
getLabel() must be synchronous (O(1) map lookup) — no async calls during UI rendering
Label maps are loaded once at org selection time, not on every widget build
security requirements
Label values are display strings only — must not be used for access control, routing, or business logic decisions
No user-supplied label values must be rendered as raw HTML — escape at the UI layer

Execution Context

Execution Tier
Tier 1

Tier 1 - 540 tasks

Can start after Tier 0 completes

Implementation Notes

File locations: lib/domain/services/org_labels_provider.dart (interface), lib/domain/models/label_key.dart (enum). The LabelKey enum pattern is critical for preventing terminology drift across org configurations — NHF, Blindeforbundet, and HLF all use different terminology for the same concepts (e.g., 'likeperson' vs 'peer supporter'). Define defaultValue on the enum using an extension or a static map: extension LabelKeyDefault on LabelKey { String get defaultValue => const { LabelKey.peer_mentor: 'Peer Mentor', ... }[this]!; }.

Keep all string keys out of widget build methods — widgets should always call provider.getLabel(LabelKey.peer_mentor), never hardcode 'Peer Mentor'. This architecture supports the multi-org label system described in the source documentation where each organization has customized terminology.

Testing Requirements

Unit tests for LabelKey enum: verify each key's defaultValue is non-empty and meaningful. Unit tests for a future concrete OrgLabelsProvider implementation should verify: getLabel returns the org-specific override when present, getLabel returns the LabelKey.defaultValue when no override exists for the active org, getLabelsForOrg returns an empty map for an org with no overrides. Use flutter_test. No mock framework needed for enum 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.