critical priority medium complexity deployment pending devops specialist Tier 6

Acceptance Criteria

A dedicated CI workflow step named 'Accessibility Audit Gate' runs flutter test integration_test/accessibility_audit_runner_test.dart on every pull request targeting main/develop branches
The step sets the ACCESSIBILITY_REPORT_PATH environment variable to a workspace-relative path before running the test
The step exits with code 0 only when the accessibility report file exists AND totalViolations == 0; any other condition (file missing, parse error, violations > 0) causes exit code 1
The JSON report is archived as a CI build artifact named accessibility-audit-report-{run_id}.json on every run, regardless of pass/fail
PR merge is blocked when the accessibility audit step fails (branch protection rule configured)
A ACCESSIBILITY_FALSE_POSITIVE annotation mechanism is supported: developers can add a // accessibility: suppress(<violation-type>, reason: '<reason>') comment in widget code; the audit runner reads these annotations and excludes matching nodes from the report
The CI workflow includes a step that posts a summary comment on the PR with violation count and a link to the archived report when violations are found
A CONTRIBUTING.md section or inline documentation explains: how to read the report, how to add suppressions, and how to run the audit locally with flutter test integration_test/accessibility_audit_runner_test.dart

Technical Requirements

frameworks
Flutter
flutter_test
GitHub Actions (or equivalent CI)
apis
flutter test CLI
GitHub Actions actions/upload-artifact
GitHub Actions actions/github-script (for PR comments)
jq (for JSON parsing in shell)
data models
AccessibilityViolationReport (JSON schema from task-011)
performance requirements
The CI step must complete within 10 minutes total (Flutter setup + test run + report upload)
The report upload must not block the pass/fail determination
security requirements
The CI step must not expose secrets or API keys in the report artifact
Branch protection must require the accessibility audit check to pass before merge — this cannot be bypassed without admin override

Execution Context

Execution Tier
Tier 6

Tier 6 - 158 tasks

Can start after Tier 5 completes

Implementation Notes

The CI workflow step for violation checking should use a shell script: `VIOLATIONS=$(jq '.totalViolations' build/accessibility-audit-report.json); if [ "$VIOLATIONS" != '0' ]; then echo 'Accessibility violations found: '$VIOLATIONS; exit 1; fi`. For the false-positive suppression mechanism, use a SemanticsSuppression annotation class that the audit runner reads from the widget tree via the SemanticsConfiguration.tagForChildren mechanism — this avoids string-scanning source files. The PR comment step should only run when the audit fails (if: failure()) to avoid noise on passing PRs. Ensure the Flutter integration test is run with --dart-define=ACCESSIBILITY_REPORT_PATH=build/...

rather than relying on shell env var export to avoid cross-platform issues. This gate enforces WCAG 2.2 AA compliance continuously — a commitment to all three client organizations (NHF, Blindeforbundet, HLF) who specified accessibility as a MUST HAVE in Phase 1.

Testing Requirements

Manual verification: create a PR with a known accessibility violation and confirm the CI step fails and posts a comment; create a PR with no violations and confirm the step passes and the report is still archived. Automated test for the report-parsing shell script: provide a sample JSON with totalViolations=0 and assert exit 0; provide one with totalViolations=3 and assert exit 1; provide malformed JSON and assert exit 1. Document the test in the CI workflow file as inline comments. Regression test: after adding a suppression annotation, confirm the suppressed violation no longer appears in the report.

Component
Accessibility Audit Runner
infrastructure medium
Epic Risks (2)
high impact medium prob dependency

Flutter's SemanticsController used in integration tests is an internal or semi-internal API that can break between Flutter stable releases. If the audit runner relies heavily on undocumented semantics tree traversal, a Flutter upgrade could silently disable the audit checks without a build failure, creating false confidence.

Mitigation & Contingency

Mitigation: Use only the public flutter_test accessibility APIs (meetsGuideline, SemanticsController.ensureSemantics) and wrap all SemanticsController calls in a versioned helper class with explicit assertions that the expected semantics tree shape is still available. Pin the Flutter SDK range in pubspec.yaml.

Contingency: If SemanticsController APIs break on a Flutter upgrade, fall back to widget-level golden tests that include the semantics tree snapshot, combined with manual Switch Access and VoiceOver QA checklists executed before each release.

low impact medium prob resource

Flutter integration tests that simulate Switch Access traversal on multiple screens can be slow (30–120 seconds per test flow), which may make the audit runner impractical to run on every CI commit if the test suite already has long run times.

Mitigation & Contingency

Mitigation: Scope the audit runner to a dedicated integration test target that runs on pull requests targeting main and on nightly builds, not on every push. Parallelise test shards in CI to keep wall-clock time acceptable. Profile audit run times during development and trim any flows that duplicate coverage.

Contingency: If CI run times exceed acceptable thresholds, split the audit runner into a fast smoke suite (touch targets and semantic labels only, runs on every PR) and a thorough traversal suite (Switch Access simulation, runs nightly), with the nightly failure blocking the release branch rather than every PR.