critical priority high complexity testing pending testing specialist Tier 4

Acceptance Criteria

All interactive elements (text fields, checkboxes, dropdowns, submit button, retry button, back button) have meaningful semantic labels that are announced correctly by VoiceOver and TalkBack — no element announces as 'button' or 'textfield' without a descriptive label.
Focus order follows a logical top-to-bottom, left-to-right reading order through the form; no focus jumps unexpectedly or gets trapped in a loop.
Form validation errors are announced as live regions — when a required field is left empty and the user attempts to submit, the error text is announced without the user navigating to it.
The submission success confirmation announces 'Report saved' as a live region; the screen reader user does not need to find and navigate to the element.
The draft indicator banner ('Draft saved') is announced when it appears on screen; it does not interrupt focus on the current form field.
The session-lock message (if the session has already been reported) is announced prominently and the form is correctly announced as read-only or disabled.
The speech-to-text activation button announces its current state ('Start dictation' / 'Stop dictation') and the live transcription text is announced as it changes.
No WCAG 2.2 AA violations remain unfixed after the testing session; all findings are documented in a structured test report with element, screen reader, OS version, finding, and fix status columns.
Contrast ratio for all text elements meets WCAG 2.2 AA minimum (4.5:1 for normal text, 3:1 for large text) verified with a contrast checker tool.
Touch target sizes for all interactive elements meet the WCAG 2.2 minimum of 24×24 CSS pixels (Flutter: 48×48 logical pixels recommended).

Technical Requirements

frameworks
Flutter
performance requirements
Screen must not drop frames during VoiceOver/TalkBack navigation — accessibility tree updates must be synchronous with UI state changes
security requirements
Sensitive fields (e.g. health status notes) must not have their content announced in notification banners or widget previews visible on the lock screen
Screen reader announcements for submission confirmation must not include personal data — only status messages
ui components
Semantics widgets wrapping all dynamic form fields with label, hint, and value properties
ExcludeSemantics wrapper for purely decorative icons
MergeSemantics for compound widgets (label + input pairs)
Semantics(liveRegion: true) on validation error texts and submission confirmation

Execution Context

Execution Tier
Tier 4

Tier 4 - 323 tasks

Can start after Tier 3 completes

Implementation Notes

Begin with Flutter's SemanticsDebugger (debugShowSemanticsNodes: true in MaterialApp) to inspect the semantic tree before physical device testing — catch obvious issues early. For dynamic form fields, the DynamicFieldRenderer must pass a semanticsLabel to each field widget based on the schema field's label property — never rely on placeholder text alone for semantic labelling. For live regions, use a dedicated LiveRegionAnnouncer utility that calls SemanticsService.announce() as a fallback for widgets that cannot use Semantics(liveRegion: true) directly (e.g., bottom sheets that are mounted after the triggering event). For focus order, use the FocusTraversalGroup widget to define explicit traversal order through the form sections (dynamic fields → way-forward section → submit button).

The draft indicator and session-lock banner must use Semantics(container: true, label: '...') so they are treated as standalone semantic nodes. Document each fix with a before/after description and the specific Semantics widget change applied.

Testing Requirements

Manual testing on physical devices is required — simulators do not accurately reproduce VoiceOver/TalkBack behaviour. iOS: iPhone running latest iOS with VoiceOver enabled; test all scenarios in the structured test script. Android: device running Android 13+ with TalkBack enabled; test all scenarios. Automated: flutter_test accessibility checks using tester.semantics and SemanticsHandle to verify semantic labels, live regions, and focus order in widget tests.

Use Flutter's built-in SemanticsDebugger overlay to inspect the accessibility tree during development. Document findings in a spreadsheet with columns: Element, Screen Reader, OS/Version, WCAG Criterion, Finding, Severity (A/AA/AAA), Status (Fixed/Deferred/Accepted).

Component
Post-Session Report Screen
ui high
Epic Risks (2)
medium impact high prob technical

End-to-end integration tests that span Flutter UI → Supabase → RLS → storage are inherently flaky in CI due to network timing, test database state, and Supabase cold-start latency. Flaky tests erode confidence and slow the release pipeline.

Mitigation & Contingency

Mitigation: Use a dedicated Supabase test project with seeded org and user fixtures. Wrap all E2E tests in retry logic with a fixed seed and tear-down hooks. Keep E2E tests in a separate test suite that runs on-demand rather than on every PR, with unit and widget tests as the primary CI gate.

Contingency: If E2E tests remain unreliable, replace the Supabase calls in integration tests with a verified fake (in-memory repository implementations) and promote the real Supabase tests to a nightly scheduled run rather than blocking PR merges.

high impact medium prob security

Health status, course interest, and assistive device fields contain personal health data. If any logger, analytics event, or crash reporter captures field values — through automated error serialisation or developer-added debug logs — the feature could violate GDPR and Blindeforbundet's data processor agreement.

Mitigation & Contingency

Mitigation: Audit all log statements in the report feature's code paths before the epic is marked done. Apply a PII-safe logging wrapper that strips field values from any serialised form state before it reaches the logger. Add a CI lint rule that flags direct logger calls within report-related files.

Contingency: If PII is found in logs post-launch, immediately disable the affected logging call and rotate any credentials that were exposed. Notify the data protection officer and document the incident per GDPR Article 33 requirements.