feat: admin invite codes with plan assignment + user detail page #73

Merged
chihlasm merged 3 commits from feat/admin-invite-user-management into main 2026-02-12 04:52:18 +00:00
chihlasm commented 2026-02-12 02:43:22 +00:00 (Migrated from github.com)

Summary

  • Invite codes now support plan assignment (free/pro/team) with optional trial duration (1-90 days) and email delivery via Resend
  • Registration applies invite plan/trial to new subscription automatically, regardless of REQUIRE_INVITE_CODE setting
  • Enriched admin user detail page with account, subscription, recent sessions/audit logs, and invite code used
  • Admin subscription management: change plan and extend/start trial from user detail page
  • Auto-downgrade expired trials on authenticated access (lightweight login-time check)
  • Fixed API path drift: frontend now correctly uses /invites instead of /invite-codes

Backend

  • Migration 030: email, assigned_plan, trial_duration_days, email_sent_at on invite_codes with 3 CHECK constraints
  • EmailService with Resend (graceful degradation when API key not configured)
  • PUT /admin/users/{id}/subscription/plan and PUT /admin/users/{id}/subscription/extend-trial
  • Enriched GET /admin/users/{id} response with account/subscription/sessions/audit/invite data
  • Trial expiry auto-downgrade in get_current_active_user

Frontend

  • Enhanced invite codes page: email, plan selector, trial duration in create form; new table columns
  • New user detail page at /admin/users/:userId with subscription controls
  • Users page: "View Detail" action navigates to detail page

Test plan

  • 11 new backend tests covering invite creation, registration with plan/trial, admin subscription management, enriched user detail
  • 416 total backend tests passing
  • Frontend build passes (npm run build)
  • Manual: create invite with email + plan + trial → register → verify subscription → change plan → extend trial

🤖 Generated with Claude Code

## Summary - **Invite codes now support plan assignment** (free/pro/team) with optional trial duration (1-90 days) and email delivery via Resend - **Registration applies invite plan/trial** to new subscription automatically, regardless of `REQUIRE_INVITE_CODE` setting - **Enriched admin user detail page** with account, subscription, recent sessions/audit logs, and invite code used - **Admin subscription management**: change plan and extend/start trial from user detail page - **Auto-downgrade expired trials** on authenticated access (lightweight login-time check) - **Fixed API path drift**: frontend now correctly uses `/invites` instead of `/invite-codes` ### Backend - Migration 030: `email`, `assigned_plan`, `trial_duration_days`, `email_sent_at` on `invite_codes` with 3 CHECK constraints - `EmailService` with Resend (graceful degradation when API key not configured) - `PUT /admin/users/{id}/subscription/plan` and `PUT /admin/users/{id}/subscription/extend-trial` - Enriched `GET /admin/users/{id}` response with account/subscription/sessions/audit/invite data - Trial expiry auto-downgrade in `get_current_active_user` ### Frontend - Enhanced invite codes page: email, plan selector, trial duration in create form; new table columns - New user detail page at `/admin/users/:userId` with subscription controls - Users page: "View Detail" action navigates to detail page ## Test plan - [x] 11 new backend tests covering invite creation, registration with plan/trial, admin subscription management, enriched user detail - [x] 416 total backend tests passing - [x] Frontend build passes (`npm run build`) - [ ] Manual: create invite with email + plan + trial → register → verify subscription → change plan → extend trial 🤖 Generated with [Claude Code](https://claude.com/claude-code)
railway-app[bot] commented 2026-02-12 02:43:33 +00:00 (Migrated from github.com)

🚅 Deployed to the patherly-pr-73 environment in selfless-grace

Service Status Web Updated (UTC)
hopeful-liberation Success (View Logs) Web Feb 12, 2026 at 4:47 am
patherly Success (View Logs) Web Feb 12, 2026 at 4:46 am
<!-- railway-bot-comment-version=2 --> <!-- railway-project-id="22b9b58c-271b-42e5-a10e-6fdec8d00134" railway-project-name="selfless-grace" --> 🚅 Deployed to the [patherly-pr-73](https://railway.com/project/22b9b58c-271b-42e5-a10e-6fdec8d00134?environmentId=a6d16fc5-e7a8-4139-a242-df349d68d96b) environment in **[selfless-grace](https://railway.com/project/22b9b58c-271b-42e5-a10e-6fdec8d00134)** | **Service** | **Status** | **Web** | **Updated** (UTC) | | :--- | :--- | :--- | :--- | | hopeful-liberation | ✅ Success ([View Logs](https://railway.com/project/22b9b58c-271b-42e5-a10e-6fdec8d00134/service/e1db2ee3-d241-4f45-abe4-c9c5fdf483d5?id=8fe8ab7c-562e-491a-9e6c-d4f0c34e7c1b&environmentId=a6d16fc5-e7a8-4139-a242-df349d68d96b)) | [Web](https://hopeful-liberation-patherly-pr-73.up.railway.app) | Feb 12, 2026 at 4:47 am | | patherly | ✅ Success ([View Logs](https://railway.com/project/22b9b58c-271b-42e5-a10e-6fdec8d00134/service/95f556ff-5264-4116-a0c2-618a2fc53ba4?id=19fc9435-06ce-4ed7-8436-14ba0d8020d3&environmentId=a6d16fc5-e7a8-4139-a242-df349d68d96b)) | [Web](https://patherly-patherly-pr-73.up.railway.app) | Feb 12, 2026 at 4:46 am |
Sign in to join this conversation.