critical priority low complexity backend pending backend specialist Tier 0

Acceptance Criteria

An abstract class OrgSelectionService is defined under lib/domain/services/
loadOrganizations() returns Future<List<Organization>> — fetches all available organizations
selectOrganization(String orgId) returns Future<void> — persists the selection
getSelectedOrganization() returns Future<Organization?> — returns current selection or null
clearSelection() returns Future<void> — removes persisted selection
An immutable Organization data class is defined under lib/domain/models/ with fields: id (String), name (String), labels (Map<String, String>), and brandingConfig (OrgBrandingConfig)
OrgBrandingConfig is a separate immutable class with fields for primary color, logo URL, and any org-specific display overrides
Organization implements equality (==, hashCode) based on id
Both classes use copyWith() for immutable updates
All files are exported from domain barrel; zero dart analyzer errors

Technical Requirements

frameworks
Flutter
Dart
data models
Organization
OrgBrandingConfig
performance requirements
Data classes are lightweight value objects — no async logic, no external calls
security requirements
OrgBrandingConfig must not expose auth tokens or sensitive configuration — branding only
labels map values are display strings only, not access control data

Execution Context

Execution Tier
Tier 0

Tier 0 - 440 tasks

Implementation Notes

File locations: lib/domain/services/org_selection_service.dart (interface), lib/domain/models/organization.dart (data class), lib/domain/models/org_branding_config.dart (branding sub-model). Use Dart's built-in const constructors where possible for Organization and OrgBrandingConfig. For the labels map, type it as Map at this layer — the LabelKey enum (defined in task-002) will be used by OrgLabelsProvider, not directly in the Organization model, keeping this model framework-agnostic. Consider using freezed or equatable packages if already in pubspec; otherwise, implement == and hashCode manually based on id only.

The labels map on Organization is the raw data from Supabase — OrgLabelsProvider (task-002) is the typed access layer on top.

Testing Requirements

No direct tests for the abstract interface. Test the Organization data model: verify equality by id (two organizations with same id but different name are equal), verify copyWith produces a new object with the updated field, verify fromJson/toJson round-trips if JSON serialization is added. Use flutter_test with plain unit tests — no mocks needed for pure data classes.

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.