Ran axe-core against our own landing page. Fixed color contrast issues on brand-600 text (3.5:1 ratio — below the 4.5:1 AA threshold). Darkened all text and button colors to brand-700/brand-800. 0 violations, 25 checks passing.
SSRF protection in the scanner
Added URL validation with DNS resolution at both the API layer and the scanner service. Private IPs (RFC 1918), loopback, link-local, and cloud metadata endpoints (169.254.x.x) are blocked. Defense in depth — validated in Next.js before the request reaches Modal, and again in the scanner itself.
Security headers and input hardening
Added Strict-Transport-Security, X-Frame-Options (DENY), X-Content-Type-Options, Referrer-Policy, and Permissions-Policy headers. Scan quota enforcement now happens before running the scan, not after. Stripe webhook signature verification hardened with env var guard.
Initial release
AccessPulse MVP. Scanner runs axe-core 4.10 via Playwright on Modal (headless Chromium, pay-per-second). Tests against WCAG 2.0 A/AA, 2.1 A/AA, 2.2 AA, and best practices. Weighted scoring: critical violations (10x), serious (5x), moderate (2x), minor (1x). Free scan with no signup. Dashboard with magic link auth. Stripe billing for Developer ($29/mo), Team ($149/mo), and Agency ($399/mo) tiers.