0c36b7a28d
Closes Audit #3 sole P1 (F-A11Y-PA11Y-SCOPE-01). Pa11y was scanning handoff HTML prototypes from liderra_v8_handoff/concepts/ (3 URLs, ~10 contrast violations), NOT the live Vue app. Audit #2 baseline "0 errors" was inaccurate — real portal was never covered. Changes: - pa11y.config.json: now targets http://localhost:8000/<route> for 7 guest pages (login, register, forgot, 2fa, recovery, 403, 500) - pa11y-handoff.config.json: preserves historical handoff baseline as opt-in (`npm run a11y:handoff`) - package.json: new `a11y:handoff` script; `a11y` repointed to live target - RecoveryCodesView.vue: scoped CSS override fixes Vuetify warning-tonal alert content contrast (2.03:1 → ≥4.5:1, color #0a0700 per Pa11y rec) - .github/workflows/a11y.yml: new CI job with dev-server lifecycle (php artisan serve + curl wait-on + Pa11y + screenshot artifact upload) - docs/audit-baseline-pa11y.md: first live baseline document with per-URL status, ignore selectors rationale, re-run instructions Local verification: - npm run a11y: 7/7 URLs passed (0 violations) - vue-tsc: 0 errors - ESLint: 0 errors - Vitest: 88 files / 683 passed / 3 skipped / 0 failed (no regressions) Plan: docs/superpowers/plans/2026-05-14-audit3-deferred-fixes.md Task 1. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
86 lines
2.4 KiB
YAML
86 lines
2.4 KiB
YAML
name: Accessibility (Pa11y live)
|
|
|
|
on:
|
|
push:
|
|
branches: [main]
|
|
pull_request:
|
|
branches: [main]
|
|
|
|
jobs:
|
|
a11y:
|
|
runs-on: ubuntu-latest
|
|
|
|
steps:
|
|
- name: Checkout
|
|
uses: actions/checkout@v4
|
|
|
|
- name: Setup PHP 8.3
|
|
uses: shivammathur/setup-php@v2
|
|
with:
|
|
php-version: '8.3'
|
|
extensions: pdo, pdo_pgsql, redis, mbstring, intl, bcmath
|
|
coverage: none
|
|
|
|
- name: Setup Node 20
|
|
uses: actions/setup-node@v4
|
|
with:
|
|
node-version: '20'
|
|
cache: 'npm'
|
|
|
|
- name: Install root JS deps
|
|
run: npm ci --no-audit --no-fund
|
|
|
|
- name: Install app composer deps
|
|
working-directory: app
|
|
run: composer install --no-progress --no-interaction --prefer-dist --optimize-autoloader
|
|
|
|
- name: Install app JS deps
|
|
working-directory: app
|
|
run: npm ci --no-audit --no-fund
|
|
|
|
- name: Bootstrap .env + key
|
|
working-directory: app
|
|
run: |
|
|
cp .env.example .env
|
|
php artisan key:generate --force
|
|
|
|
- name: Prepare SQLite for CI (avoid pg-on-CI fixture cost)
|
|
working-directory: app
|
|
run: |
|
|
touch database/database.sqlite
|
|
sed -i 's/DB_CONNECTION=.*/DB_CONNECTION=sqlite/' .env
|
|
sed -i 's|DB_DATABASE=.*|DB_DATABASE=/home/runner/work/${{ github.event.repository.name }}/${{ github.event.repository.name }}/app/database/database.sqlite|' .env
|
|
|
|
- name: Build frontend assets
|
|
working-directory: app
|
|
run: npm run build
|
|
|
|
- name: Start Laravel dev-server
|
|
working-directory: app
|
|
run: nohup php artisan serve --host=127.0.0.1 --port=8000 > /tmp/laravel-serve.log 2>&1 &
|
|
|
|
- name: Wait for dev-server ready
|
|
run: |
|
|
for i in {1..30}; do
|
|
if curl -s -o /dev/null http://127.0.0.1:8000/login; then
|
|
echo "Dev-server up after ${i}s"
|
|
exit 0
|
|
fi
|
|
sleep 1
|
|
done
|
|
echo "Dev-server did not start within 30s"
|
|
tail -50 /tmp/laravel-serve.log
|
|
exit 1
|
|
|
|
- name: Run Pa11y (live Vue)
|
|
run: npm run a11y
|
|
|
|
- name: Upload Pa11y screenshots
|
|
if: always()
|
|
uses: actions/upload-artifact@v4
|
|
with:
|
|
name: a11y-screenshots
|
|
path: bin/a11y-screenshots/
|
|
if-no-files-found: warn
|
|
retention-days: 14
|