Session 2 — adversarial close
Three adversarial review passes, 47 findings closed.
- ImprovedBody text contrast lifted across the entire admin so every label clears WCAG 2.2 AA on both surface tones.
- ImprovedToggles, pickers, and segmented controls in settings + tickets + broadcast now expose role + checked state to screen readers.
- ImprovedThe kiosk delete confirm uses a real Radix dialog instead of the browser's native prompt — focus moves correctly and reads cleanly with VoiceOver.
- FixedLive kiosk mirror now runs on the new Broadcast-from-DB realtime path. KioskMirror picks up health snapshots on either channel and dedups by id.
- SecurityRLS hole on the device-existence check was always evaluating false. Replaced with a SECURITY DEFINER helper. Anon-key attack test verifies SELECT works for known device IDs and stays blocked for fabricated ones.
- SecurityPublic REST API (/api/v1) now requires the merchant in the Bearer key to match the merchant in every read. Verified with curl against the bare anon key (401) and a cross-tenant token (404 — never leaks existence).
- SecurityStripe checkout edge function now requires Bearer auth, allowlists priceId, and binds the calling user to the merchant before minting a checkout session.
- ImprovedSkip-to-content link added to the admin shell and every public marketing page. Keyboard users land in the main content with one tab.