critical priority low complexity backend pending backend specialist Tier 0

Acceptance Criteria

SensitiveFieldConfig is a Dart class (or sealed class / freezed value object) with at minimum: fieldIdentifier (String), sensitivityLevel (SensitivityLevel enum), warningMessageKey (String), and requiresPerSessionConfirmation (bool)
SensitivityLevel enum defines at least three levels: high (e.g. personal ID number, health data), medium (e.g. phone, address), low (e.g. date of birth)
The registry is defined as a const/final Map<String, SensitiveFieldConfig> where keys are field identifier strings
The registry includes entries for all sensitive field types identified in the source requirements: personal ID number, phone number, home address, health/diagnosis notes, and assignment details (oppdragsdetaljer)
A lookup API (e.g. SensitiveFieldRegistry.forIdentifier(String id)) returns the config or null — it does not throw on unknown identifiers
Warning message keys in the registry match keys defined in the app's existing localisation/string resource system (or a placeholder key convention is documented if the l10n system is not yet in place)
The class and registry are covered by unit tests that verify: correct field returned for known identifier, null returned for unknown identifier, and all enum values have at least one registry entry
No mutable global state — registry is immutable and safe for concurrent access

Technical Requirements

frameworks
flutter_test
freezed (optional — for immutable value object generation)
data models
SensitiveFieldConfig
SensitivityLevel
SensitiveFieldRegistry
performance requirements
Registry lookup must be O(1) — use a Map, not a list scan
The registry must be const-constructible or initialised once at startup with no runtime cost
security requirements
SensitiveFieldConfig must be immutable — use final fields and no setters
Field identifiers must be well-defined constants (not free-form strings passed from UI) to prevent spoofing
High-sensitivity fields (personal ID, health data) must have requiresPerSessionConfirmation set to true

Execution Context

Execution Tier
Tier 0

Tier 0 - 440 tasks

Implementation Notes

Define field identifier strings as a companion constants class (e.g. SensitiveFieldIdentifiers.phoneNumber, SensitiveFieldIdentifiers.personalId) to prevent typo-based lookup misses across the codebase. This is particularly important because the sensitive field warning system (task-011) and per-session confirmation registry (task-015) will both consume these identifiers — a typo in one place would silently bypass the warning. The requirements from the Blindeforbundet workshop explicitly call out sensitive personal information (personal ID, home address, health records / epikrise) as requiring delivery confirmation and read confirmation — map these directly to high-sensitivity entries with requiresPerSessionConfirmation = true.

If the app uses a Dart l10n arb file, define warning message keys that follow the existing arb key naming convention (e.g. sensitiveField_phoneNumber_warning) and add placeholder arb entries so the l10n build does not fail.

Testing Requirements

Unit tests using flutter_test. Test file: test/accessibility/sensitive_field_config_test.dart. Tests must cover: (1) known field identifier returns the correct SensitiveFieldConfig with expected sensitivityLevel and warningMessageKey, (2) unknown identifier returns null from forIdentifier(), (3) all SensitivityLevel enum variants have at least one registry entry (to prevent dead enum values), (4) requiresPerSessionConfirmation is true for all high-sensitivity entries. No widget or integration tests required for this data model task.

Component
Sensitive Field Configuration
data low
Epic Risks (2)
high impact medium prob technical

Flutter's SemanticsService behaves differently between iOS (VoiceOver) and Android (TalkBack) in edge cases — e.g., announcement queuing, focus-gain timing, and attribute support. If the facade does not correctly abstract these differences, announcements may be silent or misfired on one platform, causing regression on the other platform to go unnoticed until device testing.

Mitigation & Contingency

Mitigation: Write platform-divergence unit tests early using SemanticsServiceFacade mocks. Validate announcement delivery on a physical iPhone (VoiceOver) and Android device (TalkBack) at the end of each sprint. Document known platform differences in the facade's inline API comments.

Contingency: If a platform difference cannot be abstracted cleanly, expose a platform-specific override path in the facade and implement targeted workarounds per platform, accepting the added complexity in exchange for correct behaviour.

medium impact medium prob scope

Accessibility preferences stored in local storage may need new fields as higher-tier epics are implemented (e.g., announcement verbosity, sensitive-field guard toggle). Schema changes to an already-persisted store risk data migration failures or silent defaults on existing installs, breaking user preferences.

Mitigation & Contingency

Mitigation: Design the AccessibilitySettingsRepository with a versioned JSON schema from the start, using merge-with-defaults on read so new fields fall back gracefully. Define the full expected field list upfront based on all downstream epic requirements before writing the first record.

Contingency: If migration fails on a live install, fall back to full reset-to-defaults with a one-time in-app notification informing the user that accessibility preferences have been reset and inviting them to reconfigure.