high priority low complexity frontend pending frontend specialist Tier 3

Acceptance Criteria

AssignmentStatusIndicator reads from org-labels-provider (Riverpod provider or equivalent) to obtain the org-specific label for each AssignmentStatus value when no explicit orgLabel parameter is passed
If an explicit orgLabel parameter is passed to the widget, it takes precedence over the org-labels-provider value
A Semantics widget wraps the badge with a label in the format '{orgLabel} status' or '{defaultLabel} status' β€” e.g. 'Open status' or 'PΓ₯gΓ₯ende oppgave status'
The Semantics label announces the meaningful name, not the bullet/icon or raw colour β€” screen reader users hear 'Open status', not 'amber circle'
When the org-labels-provider overrides the label to a non-English term, the Semantics label uses the overridden term
Widget tests cover: all three statuses with default labels, all three statuses with org-labels-provider override, explicit orgLabel parameter override, and Semantics label text correctness for each
Widget continues to meet WCAG 2.2 AA contrast after this change (no colour regressions)
The org-labels-provider is read using a Riverpod ConsumerWidget or Consumer widget β€” AssignmentStatusIndicator may need to change from StatelessWidget to ConsumerWidget if Riverpod is used

Technical Requirements

frameworks
Flutter
Riverpod (for org-labels-provider consumption)
apis
org-labels-provider Riverpod provider interface
data models
AssignmentStatus enum
OrgLabels model (map of status β†’ display string)
performance requirements
Provider read is synchronous (org labels are loaded at app start) β€” no FutureProvider or async work in build()
ui components
Semantics widget wrapping the badge Container
ConsumerWidget base class (if converting from StatelessWidget)

Execution Context

Execution Tier
Tier 3

Tier 3 - 413 tasks

Can start after Tier 2 completes

Implementation Notes

Convert AssignmentStatusIndicator from StatelessWidget to ConsumerWidget to access the org-labels-provider via ref.watch(). The precedence chain should be: (1) explicit orgLabel parameter β†’ (2) org-labels-provider value β†’ (3) hardcoded English default. Implement this as a simple null-coalescing chain. The Semantics widget should have excludeSemantics: false so inner Text widgets don't double-announce.

Set the Semantics.label to the resolved display name + ' status' suffix β€” this gives screen reader users context that the element represents a status, not just a label. If org-labels-provider is not yet implemented, define a minimal OrgLabelsProvider stub that returns defaults β€” the interface must be agreed to allow this task to proceed without blocking on provider implementation.

Testing Requirements

Widget tests: (1) pump the widget inside a ProviderScope with a mock OrgLabels map that overrides 'open' to 'Aktiv sak' β€” verify badge text shows 'Aktiv sak', (2) verify Semantics label is 'Aktiv sak status' when override is active, (3) verify explicit orgLabel='Custom' overrides both provider and default, (4) repeat for pending and completed statuses, (5) verify that without a ProviderScope override, default English labels are shown. Use ProviderContainer and overrides from Riverpod testing utilities. Verify Semantics tree with tester.getSemantics() and check label property.

Component
Assignment Status Indicator
ui low
Epic Risks (3)
high impact medium prob security

Blindeforbundet's encryption key retrieval mechanism may not be finalised at implementation time, or session key availability via Supabase RLS may be inconsistent, causing decryption failures that expose masked placeholders to users and degrade the experience.

Mitigation & Contingency

Mitigation: Agree with Blindeforbundet on key storage and retrieval contract before implementation starts. Prototype key retrieval in a spike against the staging Supabase instance and validate the full decrypt/verify cycle with real test data before committing to the implementation.

Contingency: Implement a fallback that shows a 'field temporarily unavailable' state with a retry affordance. Log decryption failures server-side for audit. Escalate to Blindeforbundet stakeholders to unblock key management before the service tier epic begins.

medium impact medium prob technical

NHF contacts may belong to up to 5 chapters, each governed by separate RLS policies. A coordinator's chapter scope may not cover all affiliations, causing partial profile reads or silent data omissions that are difficult to detect in tests.

Mitigation & Contingency

Mitigation: Map all RLS policy combinations for multi-chapter contacts early. Write integration tests that create contacts with 5 affiliations and query them from coordinators with varying chapter scopes. Use Supabase's RLS test utilities to verify row visibility per role.

Contingency: Add an explicit 'affiliation partially visible' state in the repository response model so the UI can communicate scope limitations to the coordinator rather than silently showing incomplete data.

low impact medium prob scope

Organisation-specific validation rules (e.g., NHF chapter limit, Blindeforbundet encrypted field edit flow) may expand in scope during implementation as edge cases are discovered, causing the validator to grow beyond the planned complexity.

Mitigation & Contingency

Mitigation: Define the complete validation rule set with product and org stakeholders before coding begins. Document each rule with its source organisation and acceptance test. Use a rule registry pattern so new rules can be added without modifying core validator logic.

Contingency: Timebox validator enhancements to 2 hours per additional rule. Defer non-blocking rules to a follow-on maintenance task rather than blocking the epic delivery.