# 12 — QA Checklist

These gates run on CI for every PR. PRs cannot merge without all gates green.

## Repo-wide

- [ ] `pnpm typecheck` clean across all packages and apps
- [ ] `pnpm lint` clean (eslint + prettier)
- [ ] `pnpm test` clean (vitest / jest)
- [ ] `pnpm build` clean for all apps
- [ ] No new secrets committed (gitleaks)
- [ ] License headers and `LICENSE.md` intact
- [ ] `.env.example` updated when env vars change
- [ ] Changeset / changelog entry on user-visible change

## API

- [ ] Prisma migration applies cleanly on a fresh DB
- [ ] `GET /v1/health` returns 200
- [ ] Auth flows: signup → OTP → login → refresh → logout all green
- [ ] RBAC: anonymous request to a protected route → 401; authenticated without permission → 403
- [ ] Audit log row written for: login, password change, role change, booking create/cancel, refund, partner approve, content publish
- [ ] Rate limit returns 429 after burst
- [ ] OpenAPI generated and committed
- [ ] Request validation (Zod) blocks malformed inputs
- [ ] Idempotency: duplicate `Idempotency-Key` returns the original response

## Mobile

- [ ] App boots on iOS and Android sims without crash
- [ ] Splash → Onboarding → Login flow works
- [ ] Tabs switch and persist scroll
- [ ] Locale toggle EN/AR flips text + RTL layout, then re-renders
- [ ] Offline state visible when disconnected
- [ ] Empty/error/loading/denied states render in core screens
- [ ] Deep links resolve to the right screen
- [ ] No tokens written to AsyncStorage; SecureStore only

## Dashboard

- [ ] Login route renders, invalid creds show error
- [ ] Protected routes redirect to `/login` when unauthenticated
- [ ] Sidebar items reflect the user's permissions
- [ ] Partner test user cannot read another partner's bookings (fixture test)
- [ ] Audit log table loads with server-side pagination

## Website

- [ ] All routes render at /en and /ar
- [ ] Lighthouse: Performance ≥ 80, A11y ≥ 90, SEO ≥ 95 on landing
- [ ] hreflang and canonical tags present
- [ ] Contact form submits and shows confirmation
- [ ] No client-side secrets

## Accessibility

- [ ] Color contrast ≥ 4.5:1 on body text
- [ ] Keyboard navigation works on web
- [ ] Screen-reader labels on custom controls (mobile + web)

## Security

- [ ] CSP, HSTS, X-Content-Type-Options headers on web apps
- [ ] CORS allow-list explicit, no `*` for credentialed requests
- [ ] Dependency scan (npm audit / Snyk) — no high/critical
- [ ] Tokens are short-lived; refresh tokens rotate on use

## Release readiness

- [ ] Changelog updated
- [ ] Migration plan documented
- [ ] Rollback plan documented
- [ ] Feature flags in place for risky changes
