RBAC, Permissions, and Export/Import
This commit is contained in:
439
docs/status_definitions.md
Normal file
439
docs/status_definitions.md
Normal file
@@ -0,0 +1,439 @@
|
||||
# Membership Status Definitions & Transitions
|
||||
|
||||
This document defines all user membership statuses, their meanings, valid transitions, and automated rules.
|
||||
|
||||
## Status Overview
|
||||
|
||||
| Status | Type | Description | Member Access |
|
||||
|--------|------|-------------|---------------|
|
||||
| `pending_email` | Registration | User registered, awaiting email verification | None |
|
||||
| `pending_validation` | Registration | Email verified, awaiting event attendance | Newsletter only |
|
||||
| `pre_validated` | Registration | Attended event or referred, ready for admin validation | Newsletter only |
|
||||
| `payment_pending` | Registration | Admin validated, awaiting payment | Newsletter only |
|
||||
| `active` | Active | Payment completed, full member access | Full access |
|
||||
| `inactive` | Inactive | Membership deactivated manually | None |
|
||||
| `canceled` | Terminated | User or admin canceled membership | None |
|
||||
| `expired` | Terminated | Subscription ended without renewal | Limited (historical) |
|
||||
| `abandoned` | Terminated | Incomplete registration after reminders | None |
|
||||
|
||||
---
|
||||
|
||||
## Detailed Status Definitions
|
||||
|
||||
### 1. pending_email
|
||||
|
||||
**Definition:** User has registered but not verified their email address.
|
||||
|
||||
**How User Enters:**
|
||||
- User completes registration form (Step 1-4)
|
||||
- System creates user account with `pending_email` status
|
||||
|
||||
**Valid Transitions:**
|
||||
- → `pending_validation` (email verified)
|
||||
- → `pre_validated` (email verified + referred by member)
|
||||
- → `abandoned` (optional: 30 days without verification after reminders)
|
||||
|
||||
**Member Access:**
|
||||
- Cannot login
|
||||
- Cannot access any member features
|
||||
- Not subscribed to newsletter
|
||||
|
||||
**Reminder Schedule:**
|
||||
- Day 3: First reminder email
|
||||
- Day 7: Second reminder email
|
||||
- Day 14: Third reminder email
|
||||
- Day 30: Final reminder (optional: transition to abandoned)
|
||||
|
||||
**Admin Actions:**
|
||||
- Can manually resend verification email
|
||||
- Can manually verify email (bypass)
|
||||
- Can delete user account
|
||||
|
||||
---
|
||||
|
||||
### 2. pending_validation
|
||||
|
||||
**Definition:** Email verified, user needs to attend an event within 90 days (per LOAF policy).
|
||||
|
||||
**How User Enters:**
|
||||
- Email verification successful (from `pending_email`)
|
||||
- 90-day countdown timer starts
|
||||
|
||||
**Valid Transitions:**
|
||||
- → `pre_validated` (attended event marked by admin)
|
||||
- → `abandoned` (90 days without event attendance - per policy)
|
||||
|
||||
**Member Access:**
|
||||
- Can login to view dashboard
|
||||
- Subscribed to newsletter
|
||||
- Cannot access member-only features
|
||||
- Can view public events
|
||||
|
||||
**Reminder Schedule:**
|
||||
- Day 30: "You have 60 days remaining to attend an event"
|
||||
- Day 60: "You have 30 days remaining to attend an event"
|
||||
- Day 80: "Reminder: 10 days left to attend an event"
|
||||
- Day 85: "Final reminder: 5 days left"
|
||||
- Day 90: Transition to `abandoned`, remove from newsletter
|
||||
|
||||
**Admin Actions:**
|
||||
- Can mark event attendance (triggers transition to `pre_validated`)
|
||||
- Can manually transition to `pre_validated` (bypass event requirement)
|
||||
- Can extend deadline
|
||||
|
||||
---
|
||||
|
||||
### 3. pre_validated
|
||||
|
||||
**Definition:** User attended event or was referred, awaiting admin validation.
|
||||
|
||||
**How User Enters:**
|
||||
- Admin marked event attendance (from `pending_validation`)
|
||||
- User registered with valid member referral (skipped `pending_validation`)
|
||||
|
||||
**Valid Transitions:**
|
||||
- → `payment_pending` (admin validates application)
|
||||
- → `inactive` (admin rejects application - rare)
|
||||
|
||||
**Member Access:**
|
||||
- Can login to view dashboard
|
||||
- Subscribed to newsletter
|
||||
- Cannot access member-only features
|
||||
- Can view public events
|
||||
|
||||
**Automated Rules:**
|
||||
- None (requires admin action)
|
||||
|
||||
**Admin Actions:**
|
||||
- Review application in Validation Queue
|
||||
- Validate → transition to `payment_pending` (sends payment email)
|
||||
- Reject → transition to `inactive` (sends rejection email)
|
||||
|
||||
---
|
||||
|
||||
### 4. payment_pending
|
||||
|
||||
**Definition:** Admin validated application, user needs to complete payment.
|
||||
|
||||
**How User Enters:**
|
||||
- Admin validates application (from `pre_validated`)
|
||||
- Payment email sent with Stripe Checkout link
|
||||
|
||||
**Valid Transitions:**
|
||||
- → `active` (payment successful via Stripe webhook)
|
||||
- → `abandoned` (optional: 60 days without payment after reminders)
|
||||
|
||||
**Member Access:**
|
||||
- Can login to view dashboard
|
||||
- Subscribed to newsletter
|
||||
- Cannot access member-only features
|
||||
- Can view subscription plans page
|
||||
|
||||
**Reminder Schedule:**
|
||||
- Day 7: First payment reminder
|
||||
- Day 14: Second payment reminder
|
||||
- Day 21: Third payment reminder
|
||||
- Day 30: Fourth payment reminder
|
||||
- Day 45: Fifth payment reminder
|
||||
- Day 60: Final reminder (optional: transition to abandoned)
|
||||
|
||||
**Note:** Since admin already validated this user, consider keeping them in this status indefinitely rather than auto-abandoning.
|
||||
|
||||
**Admin Actions:**
|
||||
- Can manually activate membership (for offline payments: cash, check, bank transfer)
|
||||
- Can resend payment email
|
||||
|
||||
---
|
||||
|
||||
### 5. active
|
||||
|
||||
**Definition:** Payment completed, full membership access granted.
|
||||
|
||||
**How User Enters:**
|
||||
- Stripe payment successful (from `payment_pending`)
|
||||
- Admin manually activated (offline payment)
|
||||
|
||||
**Valid Transitions:**
|
||||
- → `expired` (subscription end date reached without renewal)
|
||||
- → `canceled` (user or admin cancels membership)
|
||||
- → `inactive` (admin manually deactivates)
|
||||
|
||||
**Member Access:**
|
||||
- Full member dashboard access
|
||||
- All member-only features
|
||||
- Event RSVP and attendance tracking
|
||||
- Member directory listing
|
||||
- Newsletter subscribed
|
||||
|
||||
**Renewal Reminder Schedule:**
|
||||
- 60 days before expiration: First renewal reminder
|
||||
- 30 days before expiration: Second renewal reminder
|
||||
- 14 days before expiration: Third renewal reminder
|
||||
- 7 days before expiration: Final renewal reminder
|
||||
- On expiration: Transition to `expired`
|
||||
|
||||
**Admin Actions:**
|
||||
- Can cancel membership → `canceled`
|
||||
- Can manually deactivate → `inactive`
|
||||
- Can extend subscription end_date
|
||||
|
||||
---
|
||||
|
||||
### 6. inactive
|
||||
|
||||
**Definition:** Membership manually deactivated by admin.
|
||||
|
||||
**How User Enters:**
|
||||
- Admin manually sets status to `inactive`
|
||||
- Used for temporary suspensions or admin rejections
|
||||
|
||||
**Valid Transitions:**
|
||||
- → `active` (admin reactivates)
|
||||
- → `payment_pending` (admin prompts for payment)
|
||||
|
||||
**Member Access:**
|
||||
- Can login but no member features
|
||||
- Not subscribed to newsletter
|
||||
- Cannot access member-only content
|
||||
|
||||
**Automated Rules:**
|
||||
- None (requires admin action to exit)
|
||||
|
||||
**Admin Actions:**
|
||||
- Reactivate membership → `active`
|
||||
- Prompt for payment → `payment_pending`
|
||||
- Delete user account
|
||||
|
||||
---
|
||||
|
||||
### 7. canceled
|
||||
|
||||
**Definition:** Membership canceled by user or admin.
|
||||
|
||||
**How User Enters:**
|
||||
- User cancels subscription via Stripe portal
|
||||
- Admin cancels membership
|
||||
- Stripe webhook: `customer.subscription.deleted`
|
||||
|
||||
**Valid Transitions:**
|
||||
- → `payment_pending` (user requests to rejoin)
|
||||
- → `active` (admin reactivates with new subscription)
|
||||
|
||||
**Member Access:**
|
||||
- Can login to view dashboard (historical data)
|
||||
- Not subscribed to newsletter
|
||||
- Cannot access current member-only features
|
||||
- Can view historical event attendance
|
||||
|
||||
**Automated Rules:**
|
||||
- Stripe webhook triggers automatic transition
|
||||
|
||||
**Admin Actions:**
|
||||
- Can invite user to rejoin → `payment_pending`
|
||||
- Can manually reactivate → `active` (if subscription still valid)
|
||||
|
||||
---
|
||||
|
||||
### 8. expired
|
||||
|
||||
**Definition:** Subscription ended without renewal.
|
||||
|
||||
**How User Enters:**
|
||||
- Subscription `end_date` reached without renewal
|
||||
- Automated check runs daily
|
||||
|
||||
**Valid Transitions:**
|
||||
- → `payment_pending` (user chooses to renew)
|
||||
- → `active` (admin manually renews/extends)
|
||||
|
||||
**Member Access:**
|
||||
- Can login to view dashboard (historical data)
|
||||
- Not subscribed to newsletter
|
||||
- Cannot access current member-only features
|
||||
- Can view historical event attendance
|
||||
- Shown renewal prompts
|
||||
|
||||
**Automated Rules:**
|
||||
- Daily check for subscriptions past `end_date` → transition to `expired`
|
||||
- Send renewal invitation email on transition
|
||||
|
||||
**Post-Expiration Reminders:**
|
||||
- Immediate: Expiration notification + renewal link
|
||||
- 7 days after: Renewal reminder
|
||||
- 30 days after: Final renewal reminder
|
||||
- 90 days after: Optional cleanup/archive
|
||||
|
||||
**Admin Actions:**
|
||||
- Manually extend subscription → `active`
|
||||
- Send renewal invitation → `payment_pending`
|
||||
|
||||
---
|
||||
|
||||
### 9. abandoned
|
||||
|
||||
**Definition:** User failed to complete registration process after multiple reminders.
|
||||
|
||||
**How User Enters:**
|
||||
- From `pending_email`: 30 days without verification (optional - after 4 reminders)
|
||||
- From `pending_validation`: 90 days without event attendance (after 4 reminders)
|
||||
- From `payment_pending`: 60 days without payment (optional - after 6 reminders)
|
||||
|
||||
**Valid Transitions:**
|
||||
- → `pending_email` (admin resets application, resends verification)
|
||||
- → `pending_validation` (admin resets, manually verifies email)
|
||||
- → `payment_pending` (admin resets, bypasses requirements)
|
||||
|
||||
**Member Access:**
|
||||
- Cannot login
|
||||
- Not subscribed to newsletter
|
||||
- All access revoked
|
||||
|
||||
**Automated Rules:**
|
||||
- Send "incomplete application" notification email on transition
|
||||
- Optional: Purge from database after 180 days (configurable)
|
||||
|
||||
**Admin Actions:**
|
||||
- Can reset application → return to appropriate pending state
|
||||
- Can delete user account
|
||||
- Can view abandoned applications in admin dashboard
|
||||
|
||||
---
|
||||
|
||||
## State Transition Diagram
|
||||
|
||||
```
|
||||
┌──────────────┐
|
||||
│ Registration │
|
||||
│ (Guest) │
|
||||
└──────────────┘
|
||||
│
|
||||
↓
|
||||
┌───────────────┐ (30 days) ┌──────────┐
|
||||
│ pending_email │──────────────────→│abandoned │
|
||||
└───────────────┘ └──────────┘
|
||||
│ ↑
|
||||
(verify email) │
|
||||
│ │
|
||||
↓ │
|
||||
┌────────────────────┐ (90 days) │
|
||||
│pending_validation │───────────────────┘
|
||||
│ (or pre_validated) │
|
||||
└────────────────────┘
|
||||
│
|
||||
(event/admin)
|
||||
│
|
||||
↓
|
||||
┌────────────────┐
|
||||
│ pre_validated │
|
||||
└────────────────┘
|
||||
│
|
||||
(admin validates)
|
||||
│
|
||||
↓
|
||||
┌─────────────────┐ (60 days) ┌──────────┐
|
||||
│payment_pending │──────────────────→│abandoned │
|
||||
└─────────────────┘ └──────────┘
|
||||
│
|
||||
(payment)
|
||||
│
|
||||
↓
|
||||
┌─────────┐
|
||||
│ active │←────────────┐
|
||||
└─────────┘ │
|
||||
│ │
|
||||
├────(expires)────→┌─────────┐
|
||||
│ │expired │
|
||||
├────(cancels)────→├─────────┤
|
||||
│ │canceled │
|
||||
└──(deactivate)───→├─────────┤
|
||||
│inactive │
|
||||
└─────────┘
|
||||
│
|
||||
(renew/reactivate)
|
||||
│
|
||||
└──────────┘
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Email Notification Summary
|
||||
|
||||
| Trigger | Emails Sent |
|
||||
|---------|-------------|
|
||||
| Registration complete | Verification email (immediate) |
|
||||
| pending_email day 3, 7, 14, 30 | Verification reminders |
|
||||
| Email verified | Welcome + event attendance instructions |
|
||||
| pending_validation day 30, 60, 80, 85 | Event attendance reminders |
|
||||
| Admin validates | Payment instructions |
|
||||
| payment_pending day 7, 14, 21, 30, 45, 60 | Payment reminders |
|
||||
| Payment successful | Membership activation confirmation |
|
||||
| active: 60, 30, 14, 7 days before expiry | Renewal reminders |
|
||||
| Subscription expires | Expiration notice + renewal link |
|
||||
| expired: 7, 30, 90 days after | Post-expiration renewal reminders |
|
||||
| Status → abandoned | Incomplete application notice |
|
||||
| Admin cancels | Cancellation confirmation |
|
||||
|
||||
---
|
||||
|
||||
## Implementation Notes
|
||||
|
||||
### Configuration Options
|
||||
|
||||
All timeout periods should be configurable via environment variables:
|
||||
|
||||
```bash
|
||||
# Abandonment timeouts (in days, 0 = never auto-abandon)
|
||||
EMAIL_VERIFICATION_TIMEOUT=30
|
||||
EVENT_ATTENDANCE_TIMEOUT=90
|
||||
PAYMENT_TIMEOUT=0 # Don't auto-abandon payment_pending
|
||||
|
||||
# Reminder schedules (comma-separated days)
|
||||
EMAIL_REMINDERS=3,7,14,30
|
||||
EVENT_REMINDERS=30,60,80,85
|
||||
PAYMENT_REMINDERS=7,14,21,30,45,60
|
||||
RENEWAL_REMINDERS=60,30,14,7
|
||||
EXPIRED_REMINDERS=7,30,90
|
||||
```
|
||||
|
||||
### Background Jobs Required
|
||||
|
||||
1. **Daily Status Check** (runs at 00:00 UTC)
|
||||
- Check for expired subscriptions → `expired`
|
||||
- Check for abandonment timeouts (if enabled)
|
||||
|
||||
2. **Hourly Reminder Check** (runs every hour)
|
||||
- Calculate days since status change
|
||||
- Send appropriate reminder emails based on schedule
|
||||
|
||||
### Database Indexes
|
||||
|
||||
```sql
|
||||
CREATE INDEX idx_users_status ON users(status);
|
||||
CREATE INDEX idx_users_created_at ON users(created_at);
|
||||
CREATE INDEX idx_users_updated_at ON users(updated_at);
|
||||
CREATE INDEX idx_subscriptions_end_date ON subscriptions(end_date) WHERE status = 'active';
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Testing Checklist
|
||||
|
||||
- [ ] Reminder emails sent on correct schedule
|
||||
- [ ] Abandonment timeouts respect configuration
|
||||
- [ ] Manual status transitions work correctly
|
||||
- [ ] Role updates on status change
|
||||
- [ ] Newsletter subscription/unsubscription on status change
|
||||
- [ ] Email notifications use correct templates
|
||||
- [ ] Stripe webhook integration for cancellations/expirations
|
||||
- [ ] Admin can bypass requirements and manually transition
|
||||
- [ ] Users can complete registration even after reminders stop
|
||||
|
||||
---
|
||||
|
||||
## Future Enhancements
|
||||
|
||||
1. **Audit Logging**: Create `user_status_log` table to track all transitions
|
||||
2. **Re-engagement Campaigns**: Target abandoned users with special offers
|
||||
3. **Flexible Timeout Periods**: Per-user timeout overrides for special cases
|
||||
4. **A/B Testing**: Test different reminder schedules for better completion rates
|
||||
5. **SMS Reminders**: Optional SMS for critical reminders (payment due, expiration)
|
||||
Reference in New Issue
Block a user