Plan: Section 508 / WCAG 2.1 AA Accessibility Compliance
On this page
Status
| Step | Description | Status |
|---|---|---|
1 |
Plan file and nav entry |
Done (pre-ADR-030) |
2 |
Accessibility audit (automated + manual) |
Done (pre-ADR-030) — 41 pages audited, axe-core infrastructure in place |
3 |
Remediation — semantic HTML + ARIA |
Done (pre-ADR-030) — case detail tab-strip: role="tablist"/role="tab", aria-selected, keyboard enter |
4 |
Remediation — keyboard navigation |
Done (pre-ADR-030) — tab-strip keyboard navigation with tabindex + @keydown.enter |
5 |
Remediation — color contrast + visual |
Done (2026-03-21) — MR !51 — all pages WCAG AA clean |
6 |
Remediation — form accessibility |
N/A — forms passed audit (proper labels, required attributes) |
7 |
Remediation — table accessibility |
N/A — tables passed audit |
8 |
Axe-core CI integration |
Done (pre-ADR-030) — audit spec converted to blocking gate; 41 pages clean; ACCESSIBILITY_AUDIT env-var gate removed from [playwright.config.ts](tests/e2e/playwright.config.ts) and [xtask/src/cmd/e2e.rs](xtask/src/cmd/e2e.rs) |
9 |
Verification + VPAT document |
Done (pre-ADR-030) — [vpat.adoc](docs/modules/ROOT/pages/vpat.adoc) published under Operations nav |
10 |
Documentation, commit, push, MR |
Done (pre-ADR-030) — this MR |
Issues: TBD (audit + remediation work landed via MR !51; file a tracking issue when picking up the residual steps 8–10)
Branch: feature/accessibility-508
Steps 1–7 (audit + remediation) are shipped. This plan’s residual scope is axe-core CI integration (step 8), VPAT document (step 9), and plan-completion MR (step 10). The Design sections below for steps 3–7 are retained as historical context; they describe work already on main.
|
Context
Section 508 compliance is a federal legal requirement for systems that process Title IV-E data. CRAIG’s web UI (craig-web) was built with htmx + Alpine.js + Askama templates. Some accessibility basics are in place (semantic HTML, form labels), but no systematic audit has been performed and no VPAT (Voluntary Product Accessibility Template) exists.
The roadmap marks accessibility as "partial" (roadmap.adoc:298).
Scope
In scope:
-
Automated accessibility audit of all 25+ web pages using axe-core
-
Manual keyboard navigation audit
-
Remediation of all WCAG 2.1 Level AA violations
-
Axe-core integration in E2E test suite (Playwright + @axe-core/playwright)
-
Partial VPAT document
Out of scope:
-
WCAG 2.1 Level AAA (aspirational, not required by Section 508)
-
Screen reader testing with specific assistive technologies (would require manual QA)
-
PDF accessibility (document exports)
Design
| Step 2 (audit) must be completed before Steps 3-7 can be fully specified. The remediation steps below list expected categories of issues based on common web application patterns. Exact issues will be documented after the audit. |
Step 2: Accessibility Audit
Run axe-core against all pages via Playwright:
import AxeBuilder from '@axe-core/playwright';
test('page has no accessibility violations', async ({ page }) => {
await page.goto('/cases/');
const results = await new AxeBuilder({ page })
.withTags(['wcag2a', 'wcag2aa', 'section508'])
.analyze();
expect(results.violations).toEqual([]);
});
Run against all 25+ pages. Document each violation with:
* Rule ID (e.g., color-contrast, label, aria-required-attr)
* Affected element(s)
* Impact level (critical, serious, moderate, minor)
* Template file and line number
Expected Remediation Categories
Step 3: Semantic HTML + ARIA
Common issues:
* Missing role attributes on interactive elements
* Missing aria-label on icon-only buttons
* Missing aria-live regions for htmx dynamic content updates
* Landmark roles (main, nav, banner, contentinfo) on layout elements
Files: templates/base.html (layout landmarks), all templates with buttons/links
Step 4: Keyboard Navigation
Common issues:
* Focus trapping in Alpine.js modals/dropdowns
* Tab order for sortable table headers
* Skip-to-content link
* Focus visible indicators (:focus-visible CSS)
Files: static/css/components.css, templates with Alpine.js x-show/x-data
Step 5: Color Contrast + Visual
Common issues:
* Badge text contrast ratios below 4.5:1
* Muted text (color-sage) contrast ratio
* Focus indicator contrast
* Error state visibility (not color-alone)
Files: services/craig-web/static/css/tokens.css, services/craig-web/static/css/components.css (actual CSS layout — no theme-georgia-orchard.css file exists; theme is composed via token layers)
Step 8: Axe-core CI Integration
The audit spec tests/e2e/specs/accessibility-audit.spec.ts already exists with axe-core infrastructure. Step 8 upgrades it to a blocking CI gate: wire the existing spec into the default test matrix (currently it’s invoked manually during audits) and fail the pre-push battery on any AA violation. Also add @axe-core/playwright to the Playwright project matrix in tests/e2e/playwright.config.ts.
// tests/e2e/package.json — add dev dependency
"@axe-core/playwright": "^4"
Verification
-
Axe-core reports zero violations on all pages (AA level)
-
All pages keyboard-navigable without mouse
-
Color contrast ratios meet 4.5:1 for normal text, 3:1 for large text
-
All form inputs have associated labels
-
All data tables have proper header scope
-
Existing E2E tests pass unchanged
Documentation Updates
-
CHANGELOG.adoc -
docs/modules/ROOT/pages/roadmap.adoc— update from "partial" to complete -
Create VPAT document (accessibility conformance report)