# Release status

Public snapshot of what Gradeful actually ships. This page is the product map, not an attack guide. It updates when the site is deployed.

Live student copy in the app always wins over older inventories in `01`–`06`.

Live app SHA: `111936e`. App rollback SHA if this release must be reverted: `640eff4`. Database migrations are additive and are not reverted by rolling the app back.

## What students can do

- Search for a course on `/` and `/courses` (anonymous and logged-in users with no active plan)
- Logged-in users with active `user_access` hitting `/` go to `/dashboard` (server-side, no homepage flash)
- Preview original notes and practice on `/courses/[slug]`
- Pay with Whish on `/checkout` → `orders` → `user_access`
- Study from `/dashboard` into `/my-courses/{slug}` (restored pre-redesign dashboard and course tabs)
- Manage account from Settings (profile, notifications, billing, security, help, danger)
- Read this public map at `/connects` (no login)

`/access` is a leftover URL. It redirects to `/pricing`.

## Sources of truth

| Question | Source |
|---|---|
| Display price | `lib/payments/catalog.ts` via `getPaymentPlans()` |
| Amount charged | `orders.amount` written by the server |
| Entitlement (which courses) | `user_access.course_ids` (and `orders.course_ids` on the order) |
| Student home | `/dashboard` |
| Study URL | `/my-courses/{slug}` |

Junction tables `order_courses` and `access_grant_courses` may exist for dual-write. They are **not** the read source of truth. Invoker RLS helpers such as `student_has_paid_course` must read `user_access.course_ids` only. Do not cut over reads to the junctions in this release.

## Do not reintroduce

- Fake testimonials or review marquees
- Reservation checkout, reservation lookup, or `/api/reservations`
- Manual `/api/orders` inserts
- Sandbox OTP hints on live payment pages
- XP, public leaderboards, tournaments, boss battles, live presence
- Campus petitions or schedule-upload lockout
- Appearance / language settings UI until a real theme and i18n ship
- Public `user_badges` SELECT (`USING true`)

## Known accepted items

- AI Tutor stays **Coming soon** on the homepage while `workspace_ai_tutor_enabled` is off
- Practice-exam / mock-exam cards describe Gradeful practice, not university exams
- Auth leaked-password protection is an Auth dashboard setting, not something this site toggles in SQL
- Payment audit events are server-only by design
- Some historic tables keep RLS on with no client policies because grants were revoked (server-only / archived)
- Multiple permissive SELECT policies (admin + public/own) are an accepted pattern
- Exact pre-redesign copy that would be false or legally unsafe was not restored (see UI / copy restore in this file)

Full list: [08-known-limitations.md](./08-known-limitations.md)

## UI / copy restore (this change)

Visual and copy revert from Git history. Not a database rollback.

| Concern | Git reference |
|---|---|
| General dashboard UI | `89d0991` (parent of `88fc130` next-study-action redesign) |
| Course workspace UI | `c7fc162` (parent of `4c91035` Learn/Practice/Review) |
| Marketing/product copy + AUB/LAU tag colors | `a7de9a9` (parent of `d7f3973` tutoring-platform rewrite) |

Canonical dashboard route: `/dashboard`. Authoritative active access: `user_access` paid/confirmed, unexpired.

Copy that was **not** restored exactly (factual/legal):

- Fake testimonials / review marquees / a “what students say” section
- Welcome “Then your dashboard” (free users now land on `/` or `/courses`, not a paid dashboard)
- Plan durations still use live `durationDays` rather than a hardcoded “full semester” that can drift from catalog
- AI tutor / analytics / syllabus / exam-date privacy language that describes data the live system actually collects
- Checkout independence acknowledgement (legal) kept next to the restored personal-study checkbox
- `/access` links stay pointed at `/pricing` (legacy URL is a redirect)
- Sandbox OTP hints
- The old homepage affiliation pill (compatibility-only framing is used instead: `Course-specific study packs`)
- Exam-insider and professor-match claims from the old feature cards
- Unverifiable prestige / “top student” social proof
- Reservation / schedule-lockout / public leaderboard / XP copy
- Plan prices still come from `getPaymentPlans()` (not hardcoded dollar amounts in the homepage body)

AUB/LAU tags: catalog cards and homepage marquee use filled `brand-pine` / `brand-peach`; `UniversityBadge` / course-page chips use the bordered pine/peach tokens from `getUniversityBadgeStyles`.

## Hosted schema (additive, no table drops)

Applied on the live Gradeful database through `20260910080000` (array-SOT entitlement helper) and `20260910075625` (drop public badge count, drop duplicate `analytics_events_name_idx`). Entitlement **reads** still use `course_ids` arrays. Junctions are dual-write only.

## Rollback

1. Revert the Vercel production deployment to SHA `640eff4`, or `git revert` the app commit on `main` and push. Do **not** `git push --force`.
2. Leave hosted SQL in place. Additive migrations (`student_has_paid_course` array SOT, badge policy drop, index drop) are safe to keep.
3. Do not run `supabase db reset` or drop archived tables to roll back.

## Monitoring

- Vercel production deployment for **branch `main`** only (not a `cursor/*` preview)
- `bash scripts/verify-live.sh`
- Supabase Auth dashboard: enable leaked-password protection (HaveIBeenPwned)
- Supabase advisors: `rls_enabled_no_policy` on archived/server-only tables is accepted
- Whish reconcile: daily cron on hobby; payment webhook still required for live grants

## Legacy tables (kept, not dropped)

Historic rows may still exist for support dumps: `reservations`, `campus_petitions`, `schedule_verifications`, `course_xp`, `tournaments`, `payment_sessions`. The product does not write them anymore.
