critical priority medium complexity frontend pending frontend specialist Tier 1

Acceptance Criteria

EncryptedFieldDisplay renders a row containing: a label text, masked bullet string ('••••••••'), and a lock icon button
The lock icon button's tappable area is at least 44x44 logical pixels in both light and dark themes
The widget accepts required named parameters: label (String), ciphertext (String), and onRevealRequested (VoidCallback)
Masked bullets and label use design token colours; contrast ratio is ≥ 4.5:1 against the card background in both light and dark themes (verified via flutter_test accessibility checker or manual measurement)
The lock icon uses the semantics label 'Reveal [label]' where [label] is the field label prop — announced correctly by TalkBack and VoiceOver
The entire row has a merged semantics node with value 'Hidden' so screen readers announce the masked state without reading individual bullet characters
No plaintext or decrypted value is present in the widget tree when in masked state
The widget is stateless in its masked form; all state management is handled by the parent BLoC/provider
Widget test confirms that the lock icon Semantics node has the correct label and that bullets are rendered

Technical Requirements

frameworks
Flutter
Dart
performance requirements
Widget build must complete in a single frame (< 16 ms); avoid synchronous crypto calls in build()
security requirements
The plaintext/decrypted value must NOT be passed as a parameter to this widget; only ciphertext is accepted
No print() or debugPrint() calls that could expose the ciphertext in production logs
ui components
EncryptedFieldDisplay (new stateless widget)
Design token color references: AppColors.textPrimary, AppColors.iconSecondary, AppColors.surfaceCard
Lock icon: Icons.lock_outline (Material) or equivalent from the project icon set
Semantics wrapper with excludeSemantics on bullet text node

Execution Context

Execution Tier
Tier 1

Tier 1 - 540 tasks

Can start after Tier 0 completes

Implementation Notes

Create lib/widgets/encrypted_field_display.dart. Keep it a StatelessWidget; expose: `const EncryptedFieldDisplay({required this.label, required this.ciphertext, required this.onRevealRequested, super.key})`. The bullet string can be a fixed '••••••••' (8 bullets) regardless of actual field length — this prevents length-based information leakage. Wrap the lock IconButton in a SizedBox(width: 44, height: 44) and set padding: EdgeInsets.zero on the IconButton itself; use iconSize: 20 so the visual icon is smaller than the touch target.

Use Semantics(label: 'Reveal $label', child: ...) around the IconButton and set excludeSemantics: true on the Row's bullet Text widget. For design tokens, reference the existing AppColors / AppTextStyles already used in the project — do not hardcode hex values. The ciphertext parameter is accepted so the parent can pass it down for later decryption, but this widget itself never calls decryptField.

Testing Requirements

Widget tests (flutter_test): (1) render EncryptedFieldDisplay and assert the bullet string is visible and the label is visible; (2) assert lock icon button has a hit-testable area of at least 44x44 via tester.getSize(); (3) tap lock icon and verify onRevealRequested callback is called exactly once; (4) assert no plaintext is in the widget tree by verifying find.text() for any non-bullet, non-label string returns zero matches; (5) test in both ThemeMode.light and ThemeMode.dark and assert no contrast violations using SemanticsController. Golden tests are optional but recommended for visual regression.

Component
Encrypted Field Display Widget
ui high
Epic Risks (3)
medium impact medium prob scope

The encrypted-field-display confirmation dialog adds interaction steps that may frustrate coordinators who access sensitive fields frequently, leading to requests to bypass the flow or skip read-receipt logging, which would violate Blindeforbundet's compliance requirements.

Mitigation & Contingency

Mitigation: Design the confirmation dialog to be as minimal as possible (one clear sentence, single confirm action) and ensure it does not reappear for the same field within a single screen session. Validate the UX with Blindeforbundet coordinators during the TestFlight pilot before finalising.

Contingency: If coordinators raise strong objections, escalate to Blindeforbundet's data protection officer to determine whether a lighter confirmation pattern (e.g., biometric confirmation instead of dialog) satisfies their compliance obligation.

medium impact medium prob technical

The activity-history-list infinite scroll requires paginated Supabase queries. Contacts with hundreds of activities (e.g., an HLF peer mentor with 380 annual registrations) could cause slow page loads or memory pressure on older devices if pagination boundaries are set too large.

Mitigation & Contingency

Mitigation: Use a page size of 20 records with cursor-based pagination. Implement list item recycling using Flutter's ListView.builder. Benchmark memory usage with 400+ item simulation on a low-end test device before TestFlight release.

Contingency: If performance degrades on older devices, reduce page size to 10 and add a time-window filter (last 30 days, last 6 months, all) so the default view loads a manageable record count for most coordinators.

low impact high prob scope

The cognitive load rule engine (from the Cognitive Accessibility feature) mandates no more than 7 fields per screen section. If a contact model has more than 7 editable fields, the edit-contact-screen layout must be split into sections, adding complexity not accounted for in the initial scope.

Mitigation & Contingency

Mitigation: Audit the full contact field list from all four organisations before implementation. Group fields into logical sections (personal info, contact details, affiliation) so no single section exceeds 7 fields. Use the cognitive-load-rule-engine component if it is already delivered by the Cognitive Accessibility feature.

Contingency: If the rule-engine component is not yet available, implement a simple manual section layout with accordion-style expansion for less-frequently edited fields to stay within the 7-field guideline without blocking delivery.