Adds a new "procedural" tree type for linear step-by-step project workflows (domain controller setup, M365 onboarding, VPN config, etc). Includes intake form builder, two-panel step navigation, variable resolution, procedural exports, 3 seed templates, and UI rename from "Trees" to "Flows". Also archives 19 implemented plan docs and creates deferred features backlog. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
174 lines
6.7 KiB
Markdown
174 lines
6.7 KiB
Markdown
# Admin Panel: Invite Codes + User Management Enhancement
|
|
|
|
## Context
|
|
|
|
The admin panel has basic invite code CRUD and user listing, but lacks:
|
|
- **Plan assignment on invite codes** — all registrations get "free" plan
|
|
- **Email delivery** — admin must manually copy/send codes
|
|
- **Trial duration** — no time-limited plan access for beta testers
|
|
- **User detail page** — no way to view/manage a user's subscription, activity, or trial
|
|
|
|
This change enables the admin to create invite codes tied to specific plans (free/pro/team) with optional trial durations, send branded invite emails via Resend, and manage user subscriptions from a detailed user page.
|
|
|
|
---
|
|
|
|
## Phase 1: Database Migration (030)
|
|
|
|
**New file:** `backend/alembic/versions/030_enhance_invite_codes.py`
|
|
|
|
Add columns to `invite_codes`:
|
|
- `email` (String(255), nullable, indexed)
|
|
- `assigned_plan` (String(50), nullable, default `'free'`, CHECK `free/pro/team`)
|
|
- `trial_duration_days` (Integer, nullable)
|
|
- `email_sent_at` (DateTime(timezone=True), nullable)
|
|
|
|
**Update:** `backend/app/models/invite_code.py` — add fields + `has_trial` and `email_sent` properties
|
|
|
|
---
|
|
|
|
## Phase 2: Resend Email Integration
|
|
|
|
**New file:** `backend/app/core/email.py`
|
|
- `EmailService` class with `send_invite_email(to, code, plan, trial_days)`
|
|
- Graceful degradation: if `RESEND_API_KEY` not set, log warning, skip sending
|
|
- Email failure doesn't block invite creation (best-effort)
|
|
|
|
**New file:** `backend/app/templates/invite_email.html`
|
|
- Branded HTML email: monochrome design, ResolutionFlow logo, CTA button
|
|
- Shows invite code, plan name, trial duration if applicable, signup link
|
|
|
|
**Update:** `backend/app/core/config.py` — add `RESEND_API_KEY`, `FROM_EMAIL`, `email_enabled` property
|
|
**Update:** `backend/requirements.txt` — add `resend`
|
|
|
|
**Env vars:** `RESEND_API_KEY`, `FROM_EMAIL=ResolutionFlow <invites@resolutionflow.com>`
|
|
|
|
---
|
|
|
|
## Phase 3: Backend API Changes
|
|
|
|
### Invite code enhancements
|
|
|
|
**Update:** `backend/app/schemas/invite_code.py`
|
|
- `InviteCodeCreate`: add `email`, `assigned_plan`, `trial_duration_days`
|
|
- `InviteCodeResponse`: add new fields + computed `has_trial`, `email_sent`
|
|
|
|
**Update:** `backend/app/api/endpoints/invite.py`
|
|
- `create_invite_code`: accept new fields, send email if email provided, set `email_sent_at`, audit log
|
|
|
|
### Registration plan assignment
|
|
|
|
**Update:** `backend/app/api/endpoints/auth.py` (lines 178-183)
|
|
- When `invite_code_record` has `assigned_plan`/`trial_duration_days`, apply to new subscription
|
|
- Set `plan=invite_code_record.assigned_plan`, `status='trialing'` if trial, calculate `current_period_end`
|
|
|
|
### Subscription management endpoints
|
|
|
|
**Update:** `backend/app/api/endpoints/admin.py`
|
|
- `PUT /admin/users/{id}/subscription/plan` — change plan
|
|
- `PUT /admin/users/{id}/subscription/extend-trial` — add days to trial
|
|
- `GET /admin/users/{id}/detail` — enhanced user detail with account, subscription, sessions, audit logs, invite code used
|
|
|
|
**New file:** `backend/app/schemas/subscription.py` — `SubscriptionPlanUpdate`, `ExtendTrialRequest`, `SubscriptionResponse`
|
|
**New file:** `backend/app/schemas/user_detail.py` — `UserDetailResponse`, `SessionSummary`, `AuditLogSummary`, `AccountSummary`
|
|
|
|
### Trial expiry on login (lightweight)
|
|
|
|
**Update:** `backend/app/api/deps.py` — in `get_current_active_user`, check if subscription is trialing and expired → auto-downgrade to free
|
|
|
|
---
|
|
|
|
## Phase 4: Frontend Types & API Client
|
|
|
|
**Update:** `frontend/src/types/admin.ts`
|
|
- Enhanced `InviteCodeResponse` with email/plan/trial fields
|
|
- New: `UserDetail`, `SubscriptionDetail`, `SessionSummary`, `AuditLogSummary`, `AccountSummary`
|
|
|
|
**Update:** `frontend/src/api/admin.ts`
|
|
- Enhanced `createInviteCode` with new fields
|
|
- New: `getUserDetail`, `updateUserSubscriptionPlan`, `extendUserTrial`
|
|
|
|
---
|
|
|
|
## Phase 5: Frontend — Enhanced Invite Codes Page
|
|
|
|
**Update:** `frontend/src/pages/admin/InviteCodesPage.tsx`
|
|
|
|
Create form additions:
|
|
- Email input (optional, validated)
|
|
- Plan selector dropdown (Free / Pro / Team)
|
|
- Trial duration input (number of days, shown only if plan != free)
|
|
|
|
Table additions:
|
|
- "Recipient" column (email or "—")
|
|
- "Plan" column with badge
|
|
- "Trial" column (days or "—")
|
|
- "Email Sent" indicator
|
|
|
|
---
|
|
|
|
## Phase 6: Frontend — User Detail Page
|
|
|
|
**New file:** `frontend/src/pages/admin/UserDetailPage.tsx`
|
|
|
|
Sections:
|
|
1. **Header** — name, email, role badges, active status
|
|
2. **Account & Subscription card** — plan, status, trial end date, account display code
|
|
3. **Admin Actions card** — Change Role, Change Plan, Extend Trial, Activate/Deactivate (modal-based)
|
|
4. **Recent Sessions tab** — tree name, started, completed, outcome
|
|
5. **Audit Logs tab** — action, resource, timestamp, expandable details
|
|
6. **Invite Code card** — code used, plan assigned, who created it
|
|
|
|
**Update:** `frontend/src/router.tsx` — add route `admin/users/:userId`
|
|
**Update:** `frontend/src/pages/admin/UsersPage.tsx` — make user rows clickable → navigate to detail page
|
|
|
|
---
|
|
|
|
## Implementation Order
|
|
|
|
1. Migration 030 (invite code fields)
|
|
2. Model update (invite_code.py)
|
|
3. Resend integration (email.py, config.py, template, requirements.txt)
|
|
4. Backend schemas (invite_code, subscription, user_detail)
|
|
5. Backend API (invite.py, auth.py, admin.py, deps.py)
|
|
6. Backend tests
|
|
7. Frontend types + API client
|
|
8. Frontend invite codes page enhancement
|
|
9. Frontend user detail page
|
|
10. End-to-end testing
|
|
|
|
---
|
|
|
|
## Files to Create
|
|
- `backend/alembic/versions/030_enhance_invite_codes.py`
|
|
- `backend/app/core/email.py`
|
|
- `backend/app/templates/invite_email.html`
|
|
- `backend/app/schemas/subscription.py`
|
|
- `backend/app/schemas/user_detail.py`
|
|
- `frontend/src/pages/admin/UserDetailPage.tsx`
|
|
|
|
## Files to Modify
|
|
- `backend/app/models/invite_code.py`
|
|
- `backend/app/schemas/invite_code.py`
|
|
- `backend/app/api/endpoints/invite.py`
|
|
- `backend/app/api/endpoints/auth.py` (lines 178-183)
|
|
- `backend/app/api/endpoints/admin.py`
|
|
- `backend/app/api/deps.py`
|
|
- `backend/app/core/config.py`
|
|
- `backend/requirements.txt`
|
|
- `frontend/src/types/admin.ts`
|
|
- `frontend/src/api/admin.ts`
|
|
- `frontend/src/pages/admin/InviteCodesPage.tsx`
|
|
- `frontend/src/pages/admin/UsersPage.tsx`
|
|
- `frontend/src/router.tsx`
|
|
|
|
---
|
|
|
|
## Verification
|
|
|
|
1. **Backend tests:** Create invite with plan+trial → register with code → verify subscription has correct plan/status/period_end
|
|
2. **Email test:** Mock Resend, verify template renders, verify email_sent_at set on success
|
|
3. **Trial expiry:** Create expired trial → login → verify auto-downgrade to free
|
|
4. **Admin UI:** Create invite with email+plan+trial → verify email sent → register → verify in user detail page → change plan → extend trial
|
|
5. **Build:** `cd frontend && npm run build` passes
|
|
6. **Full test suite:** `cd backend && pytest --override-ini="addopts="` passes
|