Skip to content

ADA audit chain — stages 2+: tagged PDF, reading order, alt-text lint, table semantics, CI #7

Description

@agiacalone

Follow-up to #5, which closed after stage 1 (palette contrast) shipped in #6. This tracks the remaining stages of the ADA Title II / WCAG 2.1 AA audit chain toward the 2027-04-26 DOJ deadline.

Status (updated 2026-06-23, PR #15 merged): the audit chain is built and operational — 8 of the 9 stage boxes below are done; generation is gated end-to-end. Two items remain and this issue stays open to plan them: (1) full PDF/UA-1 is blocked on a LaTeX-tagging-backend gap (3/5 artifacts), and (2) CI is written but not yet live. Authoritative record: docs/ACCESSIBILITY.md (the pipeline is framed as a compiler; veraPDF is its type-checker) + docs/plans/2026-06-23-a11y-roadmap.md.

Done already (context)

Stage 1 — palette contrast — is live: lib/a11y/, npm run verify:a11y, and a generate.js gate. Student palette passes AA 20/20. See #5 / #6.

Remaining stages

PDF/UA structure (veraPDF backbone)

  • Tagged PDF emission\DocumentMetadata{...pdfstandard=ua-1,pdfversion=1.7,testphase={phase-III,table}} in both shared preambles; all artifacts emit a real StructTreeRoot (verified on TL2026).
  • Reading order — verified by veraPDF; no artifact fails reading order (quiz + quiz-key are fully PDF/UA-1).
  • Heading hierarchy — gap-free outline; no artifact fails this check.
  • Table semantics — header cells emit real /TH via group-scoped \tagpdfsetup{table/header-rows={1}} (the \thead{} route was a dead end; pikepdf confirms TH=3). Layout tables are not data tables; no headerless data tables.
  • veraPDF stagelib/a11y/pdfua.js wraps veraPDF (PDF/UA-1) with a pdfinfo smoke-check fallback; veraPDF 1.30.2 installed; wired into the post-generation gate; decision logic in unit-tested evaluatePdfUaGate.

Source-level lint (pre-LaTeX, better error messages)

  • Alt-text lintlib/a11y/alt-text.js: first-class stage, collects every missing [alt::] with source line.
  • Color-independence validatorlib/a11y/color-independence.js: verifying sweep over emitters.

Reporting + enforcement

  • Per-artifact JSON reporta11y-report.json ({stage, ok, rows:[{name,pass,detail,ua1?}]}).
  • CI job.github/workflows/a11y.yml is written (TeX Live + veraPDF; default gate blocking + --strict-a11y informational) but not yet live: currently workflow_dispatch-only because the org Actions policy blocks the third-party teatimeguest/setup-texlive-action ("Repository access blocked"), and it needs one validation run. The hermetic test job runs the full vitest suite on every PR.

Acceptance

  • Audit chain runs end-to-end over the student-facing PDFs and emits a per-artifact status report.
  • [~] A failing artifact blocks generation and CI with an actionable message. (Generation: ✅ — untagged fails the build, --strict-a11y fails on any PDF/UA-1 miss. CI: ⛔ pending the CI-job item above.)
  • With all stages green, the "fully ADA Title II compliant" claim is backed by an artifact-level audit trail. (Audit trail ✅; "all green" not yet — see the two open items below.)

Open work — plan to full compliance

A. Full PDF/UA-1 (the last rule) — toolchain-gated

Current: 2/5 artifacts fully PDF/UA-1 (quiz, quiz-key); the other 3 fail exactly one rule — clause 7.1 t3 ("content shall be marked as Artifact or tagged as real content"). Root cause is a codegen-gap in the LaTeX tagging backend (testphase=phase-III on TL2026): table border rules (\hline/|/booktabs) and mdframed background fills reach the PDF untagged. Proven not source-fixable — a full de-styling experiment left the failure unchanged at ~100 untagged items (and would have removed the Cornell handout's fill-in cells / cue structure for zero compliance gain). Paths:

  • Preferred — wait/adopt the toolchain. Re-run verapdf -f ua1 on each TeX Live upgrade; adopt rule/frame artifacting when a later LaTeX tagging phase ships it. The advisory gate reports the gap on every build meanwhile.
  • Source-side mitigation worth exploring: emit fill-in cells as accessible AcroForm \TextFields (better a11y and avoids the untagged fill).

B. Activate CI (Phase 4)

  • Get the org to allowlist teatimeguest/setup-texlive-action (or switch to an allowed TeX Live install path / a TL container).
  • One live validation run to prove the TeX Live package list + the veraPDF headless install.
  • Then re-enable the pull_request: trigger and, once A is green, drop continue-on-error so --strict-a11y blocks CI.

Pattern is fixed by stage 1 (lib/a11y/): each stage is a module + tests behind the same runner/gate.

Metadata

Metadata

Assignees

No one assigned

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions