high priority medium complexity infrastructure pending devops specialist Tier 6

Acceptance Criteria

AccessibilityAuditService.runAudit() is executed against every named route in the application's router configuration — no screens omitted
Each per-screen audit report is serialised as JSON and written to a CI artefact directory (e.g. build/accessibility-reports/)
A consolidated summary report aggregates violations by: screen name, violation type (missing label, low contrast, focus order, tap target size), and severity (critical, major, minor)
The consolidated report is printed as a structured JSON object to stdout so CI can parse and diff it between runs
A violation count by severity is output as a machine-readable summary (e.g. { critical: 3, major: 12, minor: 7 }) to enable threshold-based CI gates in future
The baseline report is committed or stored as a CI artefact so regressions can be detected by comparing future runs
All screens from the current app architecture are covered: Home (3 role variants), Contacts list, Contact detail, Edit contact, Peer mentor detail, Add action menu, Activity wizard (all steps), Event wizard (all steps), Settings, Tools placeholder, Notifications placeholder, Organisation selection, Login
The audit script is runnable locally with a single command documented in the accessibility developer guide (task-018)

Technical Requirements

frameworks
flutter_test
integration_test
AccessibilityAuditService (internal)
AccessibilityTestHarness (internal)
apis
AccessibilityAuditService.runAudit()
GoRouter (route enumeration)
dart:io (file write for artefacts)
data models
AccessibilityViolation
ScreenAuditReport
ConsolidatedAuditReport
performance requirements
Full audit of all screens completes within 10 minutes in CI
Audit runs are non-destructive — no writes to Supabase, all data layer mocked
security requirements
Audit artefacts must not contain real user data — use mock auth session with synthetic user
CI artefacts should be treated as internal-only and not published to public artefact storage

Execution Context

Execution Tier
Tier 6

Tier 6 - 158 tasks

Can start after Tier 5 completes

Implementation Notes

Enumerate screens programmatically from the GoRouter configuration rather than hardcoding a list, to ensure new screens are automatically included in future audit runs. For screens that require navigation state (e.g. wizard step 2 requires step 1 completion), create minimal navigation helpers that drive the wizard to the target step before running the audit. Severity classification should follow WCAG 2.2 AA: missing semantic labels and focus traps are critical; insufficient tap target size and missing heading roles are major; colour contrast on non-interactive decorative elements is minor.

The baseline artefact is explicitly for the Blindeforbundet pilot preparation — document this context in the report header. After the audit, do NOT automatically fix violations in this task; create tickets in the remediation backlog instead.

Testing Requirements

This is an infrastructure task, not a feature test. The audit runner itself should be a standalone integration_test script. Use a seeded mock auth session so all role-gated screens (coordinator, org admin, peer mentor) are reachable. For multi-step wizards, navigate to each step individually so each step's widget tree is audited.

Write a helper that enumerates all GoRouter routes and drives the harness to each one. After each screen audit, serialise the report using jsonEncode() and append to a per-run output file. Validate that the output JSON is parseable in a post-audit assertion to catch serialisation bugs.

Component
Accessibility Audit Service
service high
Epic Risks (3)
high impact high prob technical

Flutter's build pipeline and SemanticsService.announce() operate asynchronously. Announcements triggered too early (before the semantic tree settles) may be swallowed silently on both platforms, causing acceptance criteria around the 500ms window to fail intermittently in CI and on device, which would block pilot launch.

Mitigation & Contingency

Mitigation: Implement the LiveRegionAnnouncer with a post-frame callback delay and an internal timing guard. Write integration tests using WidgetTester.pump() sequences that verify announcement delivery across multiple frame boundaries. Validate on physical devices at each sprint boundary, not only in CI.

Contingency: If consistent announcement timing cannot be achieved within Flutter's semantic pipeline, switch to a platform channel approach that calls native UIAccessibility.post (iOS) and AccessibilityManager.announce (Android) directly, bypassing Flutter's intermediary.

high impact medium prob technical

Flutter does not natively emit a focus-gain event to Dart code when VoiceOver or TalkBack moves focus to a specific widget. If the intercept mechanism for the SensitiveFieldWarningDialog relies on an unsupported or undocumented hook in the semantics tree, it may miss focus events for some field types or in some navigation contexts, leaving sensitive data unprotected.

Mitigation & Contingency

Mitigation: Prototype the focus-intercept mechanism during the first sprint of this epic, before building the dialog UI. Evaluate Flutter's SemanticsBinding.instance callbacks and custom SemanticsActions as intercept points. Document the chosen mechanism with platform compatibility notes.

Contingency: If no reliable focus-intercept is available, implement an alternative where sensitive fields show a static 'Screen reader active — tap to reveal' overlay instead of an OS dialog, which is less seamless but achieves equivalent privacy protection without relying on an unreliable event hook.

medium impact low prob dependency

The AccessibilityTestHarness depends on internal flutter_test semantic tree APIs that can change between Flutter minor versions. If the project upgrades Flutter during this epic, the harness may break silently, causing CI accessibility tests to pass while actually skipping assertions.

Mitigation & Contingency

Mitigation: Pin the Flutter SDK version in pubspec.yaml for the duration of this epic. Document which flutter_test APIs are used and their stability tier. Add a canary test that explicitly fails if the semantic tree API surface changes.

Contingency: If a forced Flutter upgrade breaks the harness, prioritise patching the harness as a blocking task before any other epic work continues, using the canary test failure as the trigger.