···581581- Admin link shows in auth menu only for admin users
582582- Redirects to home page if non-admin accesses admin page
583583584584+## Subscription System
585585+586586+The application uses Polar for subscription management to gate access to transcription features.
587587+588588+**Subscription requirement:**
589589+- Users must have an active subscription to upload and transcribe audio files
590590+- Users can join classes and request classes without a subscription
591591+- Admins bypass subscription requirements
592592+593593+**Protected routes:**
594594+- `POST /api/transcriptions` - Upload audio file (requires subscription or admin)
595595+- `GET /api/transcriptions` - List user's transcriptions (requires subscription or admin)
596596+- `GET /api/transcriptions/:id` - Get transcription details (requires subscription or admin)
597597+- `GET /api/transcriptions/:id/audio` - Download audio file (requires subscription or admin)
598598+- `GET /api/transcriptions/:id/stream` - Real-time transcription updates (requires subscription or admin)
599599+600600+**Open routes (no subscription required):**
601601+- All authentication endpoints (`/api/auth/*`)
602602+- Class search and joining (`/api/classes/search`, `/api/classes/join`)
603603+- Waitlist requests (`/api/classes/waitlist`)
604604+- Billing/subscription management (`/api/billing/*`)
605605+606606+**Subscription statuses:**
607607+- `active` - Full access to transcription features
608608+- `trialing` - Trial period, full access
609609+- `past_due` - Payment failed but still has access (grace period)
610610+- `canceled` - No access to transcription features
611611+- `expired` - No access to transcription features
612612+613613+**Implementation:**
614614+- `subscriptions` table tracks user subscriptions from Polar
615615+- `hasActiveSubscription(userId)` checks for active/trialing/past_due status
616616+- `requireSubscription()` middleware enforces subscription requirement
617617+- `/api/auth/me` returns `has_subscription` boolean
618618+- Webhook at `/api/webhooks/polar` receives subscription updates from Polar
619619+- Frontend components check `has_subscription` and show subscribe prompt
620620+621621+**User settings with query parameters:**
622622+- Settings page supports `?tab=<tabname>` query parameter to open specific tabs
623623+- Valid tabs: `account`, `sessions`, `passkeys`, `billing`, `danger`
624624+- Example: `/settings?tab=billing` opens the billing tab directly
625625+- Subscribe prompts link to `/settings?tab=billing` for direct access
626626+- URL updates when switching tabs (browser history support)
627627+628628+**Testing subscriptions:**
629629+Manually add a test subscription to the database:
630630+```sql
631631+INSERT INTO subscriptions (id, user_id, customer_id, status)
632632+VALUES ('test-sub', <user_id>, 'test-customer', 'active');
633633+```
634634+584635## Future Additions
585636586637As the codebase grows, document: