# Known limitations

Public list of accepted gaps, dual-write warnings, and things this release does not ship. Not an attack guide.

## Entitlements

- **Read source of truth is `user_access.course_ids`.** `orders.course_ids` records what was purchased. Junctions `order_courses` and `access_grant_courses` are dual-write only.
- Cutting invoker RLS over to `access_grant_courses` caused permission denied on entitled course loads. Do not repeat that cutover until a dedicated migration grants the right reads.
- `public.student_has_paid_course(uuid)` is `SECURITY INVOKER` and must keep reading the array.

## Auth

- Leaked-password protection is off until it is toggled in the Supabase Auth dashboard (HaveIBeenPwned). SQL cannot enable it.
- Phone signup is not offered.
- Dark mode and i18n are not shipped. Appearance and language settings UI stay removed.

## Payments

- Live checkout is Whish. There is no reservation path and no placeholder provider.
- Refunds are course withdrawal/drop with university documentation only.
- Hobby Vercel uses a daily Whish reconcile cron; webhooks are still the live grant path.

## Routing

- Anonymous `/` → marketing homepage
- Logged-in, no active `user_access` → marketing homepage
- Logged-in, pending/abandoned/expired/revoked access → marketing homepage
- Logged-in, any currently valid paid plan → `/dashboard` (proxy + `app/page.tsx`, no homepage flash)
- Active users may still open `/pricing`, `/courses`, public course pages, and legal pages on purpose

## Product flags

- Homepage AI Tutor stays Coming soon while `workspace_ai_tutor_enabled` is off.
- Public leaderboards, XP, tournaments, boss battles, campus petitions, and schedule-upload lockout are retired. Tables may still exist with grants revoked.

## SEO

- `/robots.txt` disallows `/dashboard`, `/my-courses`, `/admin`, `/checkout`, `/welcome`, `/api/`, and auth/dev routes.
- `/connects` stays indexable. `/sitemap.xml` lists marketing pages, catalog courses, and connects docs.

## Database advisors (accepted)

- INFO `rls_enabled_no_policy` on archived or server-only tables (`orders`, `payment_events`, `order_courses`, reservations, petitions, XP, tournaments). Grants were revoked.
- WARN `multiple_permissive_policies` on public catalog tables (admin SELECT plus public/own SELECT).
- INFO unused indexes: do not drop or add indexes on archived tables in this pass.
- WARN `auth_leaked_password_protection`: dashboard toggle, documented above.

## Error catalog (student-facing)

| Situation | What the student sees |
|---|---|
| Catalog / Supabase outage | Clean empty or retry copy. Raw PostgREST messages are never shown. |
| Anonymous `/dashboard` | Redirect to `/login?next=…` |
| No paid access on a course workspace URL | Redirect to `/pricing` |
| Whish payment failure | `/checkout/payment/failure` |
| Maintenance flag | `/maintenance` except login, auth, connects |

## Not in this release

- Junction-table entitlement cutover
- Dropping `course_ids` arrays or archived tables
- Enabling AI Tutor on the homepage without the platform flag
- Dark mode / language switching
- Playwright suites or new npm packages
