v1.46.0
[1.46.0] — 2026-05-18
WS2 #5 + #6 + #21 + #24 — scan SSE accessibility.
🐛 Fixes
fix(a11y): scan SSE — live-log region, Stop, run-state, error banner— four UX-audit findings on#/scan:- #5 the streaming console (
<pre id="scan-console">) was a bare element; screen readers got no announcement of scanned lines. Nowrole="log" aria-live="polite" aria-relevant="additions"+ anaria-label+tabindex="0"(keyboard-scrollable). A separate visually-hiddenrole="status" aria-live="assertive"region announces terminal events (complete / failed / stopped). - #6 an in-flight
EventSourcescan had no abort path. The handle is now captured (activeES) and a Stop button closes it (es.close()), cancels the result poll, and resets state. Stop is shown only while a scan runs. - #21 the Scan button stayed enabled with no busy cue during a multi-minute crawl.
setScanRunning()now disables it + setsaria-busyand toggles the Stop button across both stream paths (single-phasestreamToand multi-phaserunScanAll— the latter only ends the run on the terminaldone,final !== false). - #24 an SSE failure was a 3.5 s toast only. A persistent
role="alert"banner now shows the error with a Retry scan action (re-invokes the last run fn); cleared on the next run.
- #5 the streaming console (
- All side-effecting closures keep the existing
__cancelActiveScanPoll()hashchange cleanup.
🌐 i18n
- 8 new keys × 8 locales —
scan.consoleLabel/stop/stopped/statusDone/statusFailed/statusStopped/errBannerTitle/errRetry.i18n-coveragegate green.
🧪 Tests
test: tests/scan-sse-a11y.test.mjs— 7 cases (log-region roles, assertive status, Stop closes EventSource on both paths, run-state aria-busy, persistent alert + Retry, terminal-done gating, 8 i18n keys ×8). 660 → 667.
Verification
$ npm run test:ci
# 667 / 667 · ✓ no .also( leftovers · ✓ CHANGELOG parity: all 8 locales at v1.46.0
# Playwright #/scan: console role=log aria-live=polite tabindex=0 · status role=status · error role=alert(hidden) · Stop hidden · 0 errors