WF-109: License Seat Reallocation
Overview
This workflow handles the reallocation of license seats from inactive or departing users to new team members. It manages the seat pool, enforces grace periods for reallocation, handles active session termination, and ensures license compliance.
Trigger: HTTP POST to /api/v1/organizations/{org_id}/licenses/reallocate
Duration: ~3-5 seconds
Related Workflows: WF-005 (Invitation), WF-008 (Offboarding), WF-002 (Subscription)
Prerequisites
Before reallocating a license seat:
- Requester must be organization admin or owner
- Source user must have an assigned license
- Target user must be organization member without license
- Organization must have active subscription
Seat States
| State | Description | Can Reallocate? |
|---|---|---|
| Assigned | Actively used by a user | Yes (with grace period) |
| Unassigned | In seat pool, available | Immediate |
| Pending | Reserved for invited user | Cancel invitation first |
| Suspended | Payment issue, temporarily disabled | Resolve payment first |
Workflow Diagram
Step-by-Step Narrative
Step 1: Validate Request
- Node: Request Validation
- Type: API Middleware
- Actions:
- Validates required fields:
from_user_id,to_user_id,license_id - Confirms requester has admin/owner role
- Verifies both users are organization members
- Checks license belongs to organization
- Validates required fields:
Step 2: Check License Status
- Node: License Lookup
- Type: PostgreSQL Select
- Table:
licenses,license_assignments - Actions:
- Retrieves license details and current assignment
- Checks license is in
activestatus - Verifies source user currently holds this license
- Confirms target user doesn't already have a license
Step 3: Evaluate Reallocation Path
- Node: Reallocation Decision
- Type: Business Logic
- Actions:
- Checks source user's last activity date
- Determines reallocation path:
- Immediate: User inactive >30 days, or explicitly released
- Grace Period: User active within 30 days
- Blocked: User has active sessions in progress
- Returns reallocation eligibility and path
Step 4a: Immediate Reallocation Path
For inactive users (>30 days) or explicit release:
- Node: Immediate Transfer
- Actions:
- Terminate any lingering sessions for source user
- Update
license_assignmentsto unassign from source - Create new assignment for target user
- Set
assigned_atto current timestamp - Clear any cached license tokens for source user
Step 4b: Grace Period Reallocation Path
For active users:
- Node: Scheduled Reallocation
- Actions:
- Create
pending_reallocationsrecord:scheduled_at: now + 24 hoursstatus: pendingnotified: false
- Send notification to source user:
- Email: "Your license will be reassigned in 24 hours"
- In-app notification
- Include option to "Save Work" or "Request Extension"
- Schedule Celery task to execute after grace period
- Return pending status to admin
- Create
Step 5: Handle Active Sessions
- Node: Session Management
- Type: Session Service
- Actions:
- List all active sessions for source user
- For immediate reallocation:
- Terminate sessions with "License Reassigned" message
- Allow 60-second grace for work saving
- For grace period:
- Sessions continue until grace period ends
- Warning banner shown in active sessions
Step 6: Complete Assignment
- Node: Assign to Target
- Type: License Service
- Actions:
- Creates new
license_assignmentfor target user - Generates new license token
- Sets seat status to
assigned - Updates seat utilization count
- Creates new
Step 7: Notifications
- Node: Send Notifications
- Type: Notification Service
- Actions:
- Source User:
- Email: "Your CODITECT license has been reassigned"
- Details: New assignment holder (if permitted), effective date
- Target User:
- Email: "A CODITECT license has been assigned to you"
- Details: License type, getting started link
- Admins:
- Activity feed entry for reallocation
- Source User:
Step 8: Audit Trail
- Node: Audit Log
- Type: PostgreSQL Insert
- Actions:
- Records reallocation event:
action:license.seat.reallocatedfrom_user_id,to_user_idlicense_id,reallocation_typeinitiated_by,completed_at
- Linked to compliance reporting
- Records reallocation event:
Error Handling
| Error | Code | Resolution |
|---|---|---|
| Unauthorized | 401 | Provide valid JWT token |
| Forbidden | 403 | Requires admin/owner role |
| License Not Found | 404 | Verify license ID |
| Already Assigned | 409 | Target user already has license |
| Active Sessions | 409 | User has active work - use grace period |
| Payment Issue | 402 | Resolve subscription payment first |
API Endpoints
| Method | Endpoint | Description |
|---|---|---|
| GET | /api/v1/organizations/{id}/licenses | List all licenses |
| GET | /api/v1/organizations/{id}/licenses/available | List unassigned seats |
| POST | /api/v1/organizations/{id}/licenses/reallocate | Reallocate seat |
| POST | /api/v1/organizations/{id}/licenses/{id}/release | Release seat to pool |
| DELETE | /api/v1/organizations/{id}/licenses/pending/{id} | Cancel pending reallocation |