Use Case 016: Tenant Provisioning and Management
Overview
| Property | Value |
|---|---|
| Use Case ID | UC-016 |
| Use Case Name | Tenant Provisioning and Management |
| Module | Tenant Management - Lifecycle |
| Priority | High |
| Status | Implemented |
| Version | 1.0 |
| Last Updated | February 2, 2026 |
Description
This use case describes the tenant provisioning and lifecycle management system that enables Application Manager to orchestrate multi-tenant architectures across registered applications. When ApplicationUsers are created or applications are registered, the system automatically provisions isolated tenant environments by calling application-specific webhooks. The system manages the complete tenant lifecycle including activation, suspension, deactivation, data retention, and deprovisioning. Unlike Riptide Auth's trial-focused approach, this supports permanent production tenants with subscription billing, enterprise configurations, and long-term data retention policies.
Actors
| Actor | Description | Role |
|---|---|---|
| AdminUser | Platform administrator managing tenant lifecycle | Primary |
| ApplicationUser | User whose account triggers tenant provisioning | Secondary |
| Registered Application | External application receiving tenant provisioning callbacks | Supporting |
| System | Application Manager orchestrating tenant operations | Supporting |
| Billing System | External system notified of tenant lifecycle events | Supporting |
Preconditions
- Application Manager platform is running
- At least one application is registered with provisioning endpoints configured
- AdminUser has
tenant:managecapability - Database schema for tenant entities is initialized
- Application webhooks are accessible and authenticated
Postconditions
Success Postconditions
- Tenant record created/updated in Application Manager database
- Tenant provisioned in target application(s) via webhook callbacks
- Tenant ID assigned to ApplicationUser(s)
- Tenant context available for session validation
- Provisioning status logged in audit trail
- Billing system notified of tenant lifecycle events (if integrated)
Failure Postconditions
- Tenant provisioning rolled back if webhook calls fail
- ApplicationUser creation blocked if provisioning fails (configurable)
- Error logged with detailed failure reason
- Alert sent to AdminUser for manual intervention
- Retry scheduled for transient failures
Triggers
- AdminUser provisions ApplicationUser (UC-015) triggering tenant creation
- AdminUser explicitly creates tenant for organization
- Application registration triggers admin tenant creation
- AdminUser suspends/reactivates tenant
- AdminUser initiates tenant deprovisioning
- Subscription billing system requests tenant suspension (non-payment)
- Compliance policy triggers tenant data retention/deletion
Basic Flow (Happy Path)
sequenceDiagram
actor Admin as AdminUser
participant Web as Admin Web UI
participant API as Application Manager API
participant TenantSvc as Tenant Service
participant AppRegistry as Application Registry
participant ExtApp as External Application
participant DB as Identity Database
participant Audit as Audit Service
participant Billing as Billing System
Note over Admin,Billing: Tenant Provisioning Flow
Admin->>Web: Create ApplicationUser (UC-015)
Web->>API: POST /api/v1/users (ApplicationUser)
API->>TenantSvc: Provision tenant for user
TenantSvc->>DB: Create Tenant record
DB->>TenantSvc: Tenant created (ID: tenant-123)
TenantSvc->>AppRegistry: Get registered applications
AppRegistry->>TenantSvc: Application list with endpoints
loop For each application
TenantSvc->>ExtApp: POST /api/tenants/provision
Note over TenantSvc,ExtApp: Headers: X-Api-Key
Note over TenantSvc,ExtApp: Body: tenantId, metadata
ExtApp->>ExtApp: Validate API key
ExtApp->>ExtApp: Create isolated tenant
ExtApp->>ExtApp: Initialize default data
ExtApp->>TenantSvc: 200 OK (provisioned)
TenantSvc->>DB: Update ApplicationTenantMapping
DB->>TenantSvc: Mapping saved
end
TenantSvc->>DB: Link User to Tenant
DB->>TenantSvc: User-Tenant linked
TenantSvc->>Audit: Log provisioning success
Audit->>Audit: Store audit record
TenantSvc->>Billing: Notify tenant created
Billing->>Billing: Create billing account
TenantSvc->>API: Provisioning complete
API->>Web: 201 Created (user + tenant)
Web->>Admin: Success: User and tenant created
Note over Admin,Billing: Tenant Suspension Flow
Admin->>Web: Suspend tenant (non-payment)
Web->>API: PATCH /api/v1/tenants/{id}/suspend
API->>TenantSvc: Suspend tenant
TenantSvc->>DB: Update Status = Suspended
DB->>TenantSvc: Status updated
loop For each application
TenantSvc->>ExtApp: PATCH /api/tenants/{tenantId}/suspend
ExtApp->>ExtApp: Disable tenant access
ExtApp->>TenantSvc: 200 OK
end
TenantSvc->>Audit: Log suspension
TenantSvc->>Billing: Notify tenant suspended
TenantSvc->>API: Suspension complete
API->>Web: 200 OK
Web->>Admin: Tenant suspended successfully
Note over Admin,Billing: Tenant Deprovisioning Flow
Admin->>Web: Deprovision tenant
Web->>API: DELETE /api/v1/tenants/{id}
API->>TenantSvc: Confirm deprovisioning
Note over API,TenantSvc: Confirmation required
loop For each application
TenantSvc->>ExtApp: DELETE /api/tenants/{tenantId}
ExtApp->>ExtApp: Purge tenant data
ExtApp->>ExtApp: Delete tenant record
ExtApp->>TenantSvc: 204 No Content
TenantSvc->>DB: Update mapping (status: deprovisioned)
end
TenantSvc->>DB: Mark Tenant as Deprovisioned
Note over TenantSvc,DB: Retain metadata for compliance
TenantSvc->>Audit: Log deprovisioning
TenantSvc->>Billing: Notify tenant deprovisioned
TenantSvc->>API: Deprovisioning complete
API->>Web: 200 OK (summary)
Web->>Admin: Show deprovisioning summary
Detailed Steps
Tenant Creation Triggered
- ApplicationUser creation (UC-015) triggers tenant provisioning
- OR AdminUser explicitly creates tenant for organization
- OR Application registration creates admin tenant
System Generates Tenant Record
- Create
Tenantentity with unique GUID - Set
Status = Provisioning - Assign
OrganizationName,ContactEmail,PlanTier - Generate
ApiKeyfor tenant-to-platform communication - Set
CreatedByto AdminUser ID - Set
CreatedAttimestamp
- Create
System Retrieves Application List
- Query all registered applications with
ProvisioningUrlconfigured - Filter by applications user should have access to (based on plan/roles)
- Order by priority (critical apps first)
- Query all registered applications with
System Calls Application Provisioning Webhooks
- For each application in parallel (with configurable concurrency limit):
- POST to
{app.ProvisioningUrl} - Headers:
X-Api-Key: {api-key},X-Tenant-Id: {tenantId} - Body: Tenant metadata (ID, name, email, plan tier, max users)
- Timeout: 30 seconds
- Retry: 3 attempts with exponential backoff
- POST to
- For each application in parallel (with configurable concurrency limit):
Application Provisions Tenant
- Validates API key from Application Manager
- Creates isolated tenant database/schema
- Initializes default application data
- Creates admin user account linked to ApplicationUser
- Returns success with optional application-specific tenant ID
System Records Provisioning Results
- Create
ApplicationTenantMappingfor each successful provisioning - Store application-specific tenant ID if returned
- Update
Tenant.Status = Activewhen all apps succeed - Update
Tenant.Status = PartiallyProvisionedif some fail - Log failures with error messages for retry
- Create
System Links User to Tenant
- Update
ApplicationUser.TenantIdwith new tenant ID - Create default tenant admin role assignment
- Grant access to provisioned applications
- Update
System Notifies External Systems
- Send event to audit service with full provisioning details
- Notify billing system to create account
- Send email to organization contact (optional)
- Create support ticket for manual verification (if configured)
Alternative Flows
Alt Flow 1: Provisioning Webhook Failure
sequenceDiagram
participant TenantSvc as Tenant Service
participant ExtApp as External Application
participant DB as Identity Database
participant Retry as Retry Queue
participant Alert as Alert Service
TenantSvc->>ExtApp: POST /api/tenants/provision
alt Application Timeout
ExtApp--xTenantSvc: [Timeout after 30s]
TenantSvc->>Retry: Schedule retry (attempt 1/3)
TenantSvc->>DB: Update Status = ProvisioningRetrying
else Application Error 500
ExtApp-->>TenantSvc: 500 Internal Server Error
TenantSvc->>Retry: Schedule retry (attempt 1/3)
else Application Invalid Response
ExtApp-->>TenantSvc: 200 OK (malformed JSON)
TenantSvc->>DB: Log invalid response
TenantSvc->>Retry: Schedule retry (attempt 1/3)
end
Note over Retry: Wait 10 seconds (exponential)
Retry->>TenantSvc: Execute retry attempt 2
TenantSvc->>ExtApp: POST /api/tenants/provision
ExtApp--xTenantSvc: [Still failing]
TenantSvc->>Retry: Schedule retry (attempt 2/3)
Note over Retry: Wait 30 seconds
Retry->>TenantSvc: Execute retry attempt 3
TenantSvc->>ExtApp: POST /api/tenants/provision
ExtApp--xTenantSvc: [Final failure]
TenantSvc->>DB: Update Status = ProvisioningFailed
TenantSvc->>DB: Store error details
TenantSvc->>Alert: Send alert to AdminUser
Note over TenantSvc: Admin must manually intervene
Steps:
- Application webhook call fails (timeout, 5xx error, network issue)
- System immediately retries (attempt 1 of 3) after 10 seconds
- If still failing, wait 30 seconds and retry (attempt 2)
- If still failing, wait 90 seconds and final retry (attempt 3)
- After 3 failures, mark
ApplicationTenantMapping.Status = Failed - Update
Tenant.Status = PartiallyProvisioned(if other apps succeeded) - Create alert for AdminUser with error details
- AdminUser can manually retry via UI: "Retry Failed Provisioning"
- AdminUser can exclude failing application and mark tenant as Active
Alt Flow 2: Multi-Application Partial Provisioning
sequenceDiagram
participant TenantSvc as Tenant Service
participant App1 as App 1 (Success)
participant App2 as App 2 (Failed)
participant App3 as App 3 (Success)
participant DB as Database
par Parallel Provisioning
TenantSvc->>App1: POST /api/tenants/provision
App1->>TenantSvc: 200 OK (success)
TenantSvc->>App2: POST /api/tenants/provision
App2--xTenantSvc: 500 Error (failed)
TenantSvc->>App3: POST /api/tenants/provision
App3->>TenantSvc: 200 OK (success)
end
TenantSvc->>DB: Save results
Note over TenantSvc,DB: App1: Provisioned<br/>App2: Failed<br/>App3: Provisioned
TenantSvc->>DB: Update Tenant.Status = PartiallyProvisioned
Note over TenantSvc: Admin sees mixed status<br/>Can retry App2 or proceed
Steps:
- System provisions tenant across 3 applications
- App1 succeeds, App2 fails, App3 succeeds
Tenant.Status = PartiallyProvisioned- AdminUser sees status: "2 of 3 applications provisioned"
- AdminUser options:
- Retry failed application
- Mark tenant as Active (accept partial provisioning)
- Deprovision successful apps and abort
- User can still access successfully provisioned applications
Alt Flow 3: Tenant Suspension (Non-Payment)
Steps:
- Billing system detects failed payment
- Billing system calls:
PATCH /api/v1/tenants/{id}/suspend - System validates billing system API key
- System updates
Tenant.Status = Suspended - System calls suspension webhook for each application:
PATCH /api/tenants/{tenantId}/suspend
- Applications disable access but retain data
- Users attempting to access see "Account Suspended" message
- AdminUser can view suspension reason: "Payment Failed - Renew by "
- After grace period (default 30 days), tenant moves to deprovisioning
Alt Flow 4: Tenant Reactivation
Steps:
- Billing system confirms payment received
- Billing system calls:
PATCH /api/v1/tenants/{id}/reactivate - System validates tenant was suspended (not deprovisioned)
- System updates
Tenant.Status = Active - System calls reactivation webhook for each application:
PATCH /api/tenants/{tenantId}/reactivate
- Applications re-enable access
- System sends welcome back email to organization
- Audit log records reactivation with reason
Alt Flow 5: Tenant Data Retention (Compliance)
Steps:
- AdminUser initiates soft delete: "Deprovision but retain for 90 days"
- System updates
Tenant.Status = Deprovisioned - System sets
Tenant.DataRetentionUntil = Now + 90 days - System calls application deprovisioning webhooks
- Applications archive tenant data (move to cold storage)
- Users cannot access applications
- After 90 days, scheduled job calls hard delete:
- Applications permanently purge tenant data
- Application Manager removes
ApplicationTenantMappingrecords - Tenant metadata retained indefinitely for audit
Alt Flow 6: Tenant Migration (Environment Transfer)
Steps:
- AdminUser requests tenant migration: Dev → Staging → Production
- System validates target environment is registered
- System exports tenant metadata and configuration
- System provisions tenant in target environment (normal flow)
- Applications handle data migration (out of scope for Application Manager)
- System updates tenant's environment identifier
- Users receive notification of migration
- Old environment tenant marked for deprovisioning (with grace period)
Business Rules
| Rule ID | Description | Enforcement |
|---|---|---|
| BR-001 | Each tenant must have unique ID (GUID) | Database primary key constraint |
| BR-002 | Tenant must be provisioned in at least one application to be Active | Status validation logic |
| BR-003 | Suspended tenants retain all data for grace period (default 30 days) | Suspension logic + scheduled cleanup |
| BR-004 | Deprovisioning requires explicit AdminUser confirmation | Two-step deletion workflow |
| BR-005 | Failed provisioning webhooks retry 3 times with exponential backoff | Retry service configuration |
| BR-006 | Tenant API key must be unique and cryptographically secure (32 bytes) | Key generation service |
| BR-007 | Tenant metadata retained indefinitely for compliance even after deprovisioning | Soft delete implementation |
| BR-008 | Provisioning webhook timeout: 30 seconds | HTTP client configuration |
| BR-009 | ApplicationUser can belong to only one tenant (no shared tenants) | Data model constraint |
| BR-010 | Tenant status transitions: Provisioning → Active → Suspended → Deprovisioned | State machine validation |
| BR-011 | Billing integration events must be idempotent | Event deduplication |
| BR-012 | Admin tenant (for Riptide team) created automatically on app registration | Application registration logic |
Data Requirements
Tenant Entity
{
"Id": "uuid-v4 (primary key)",
"OrganizationName": "string (required, 1-200 chars)",
"OrganizationDomain": "string (nullable, validated domain format)",
"ContactEmail": "string (required, validated email)",
"ContactName": "string (required, 1-200 chars)",
"ContactPhone": "string (nullable, 20 chars)",
"PlanTier": "enum (Free, Starter, Professional, Enterprise)",
"MaxUsers": "int (nullable, based on plan tier)",
"MaxApplications": "int (nullable, based on plan tier)",
"ApiKey": "string (32 bytes hex, unique)",
"Status": "enum (Provisioning, Active, PartiallyProvisioned, Suspended, Deprovisioned)",
"StatusReason": "string (nullable, reason for current status)",
"IsAdminTenant": "bool (default: false, true for Riptide team)",
"Environment": "enum (Development, Staging, Production)",
"DataRetentionUntil": "datetime (nullable, soft delete expiration)",
"CreatedBy": "uuid-v4 (AdminUser ID)",
"CreatedAt": "datetime (UTC)",
"UpdatedAt": "datetime (UTC)",
"LastAccessedAt": "datetime (nullable, UTC)",
"SuspendedAt": "datetime (nullable, UTC)",
"DeprovisionedAt": "datetime (nullable, UTC)",
"Metadata": "json (extensible key-value store)"
}
Status Enum:
Provisioning- Initial state, webhook calls in progressActive- All applications provisioned successfullyPartiallyProvisioned- Some applications failed, manual intervention neededSuspended- Access disabled but data retained (payment issue, policy violation)Deprovisioned- Tenant removed, data retention policy active
PlanTier Enum:
Free- Trial/demo tier (limited features, 30-day expiration)Starter- Small business tier (5 users, core features)Professional- Mid-market tier (25 users, advanced features)Enterprise- Enterprise tier (unlimited users, custom SLA)
ApplicationTenantMapping Entity
{
"Id": "uuid-v4 (primary key)",
"TenantId": "uuid-v4 (foreign key to Tenant)",
"ApplicationId": "uuid-v4 (foreign key to Application)",
"ApplicationSpecificTenantId": "string (nullable, app's internal tenant ID)",
"Status": "enum (Provisioning, Provisioned, Failed, Suspended, Deprovisioned)",
"ProvisioningAttempts": "int (default: 0, max: 3)",
"LastProvisioningAttempt": "datetime (nullable, UTC)",
"LastProvisioningError": "string (nullable, error message)",
"ProvisionedAt": "datetime (nullable, UTC)",
"ProvisionedBy": "uuid-v4 (AdminUser ID)",
"SuspendedAt": "datetime (nullable, UTC)",
"DeprovisionedAt": "datetime (nullable, UTC)",
"Metadata": "json (app-specific provisioning data)"
}
TenantUser Entity (Join Table)
{
"Id": "uuid-v4 (primary key)",
"TenantId": "uuid-v4 (foreign key)",
"UserId": "uuid-v4 (foreign key to ApplicationUser)",
"Role": "string (tenant-admin, tenant-member, tenant-billing)",
"JoinedAt": "datetime (UTC)",
"InvitedBy": "uuid-v4 (nullable, inviting user ID)",
"IsActive": "bool (default: true)"
}
TenantProvisioningLog Entity
{
"Id": "uuid-v4 (primary key)",
"TenantId": "uuid-v4 (foreign key)",
"ApplicationId": "uuid-v4 (nullable, null for tenant-level events)",
"EventType": "enum (ProvisioningStarted, ProvisioningSucceeded, ProvisioningFailed, Suspended, Reactivated, Deprovisioned)",
"Status": "enum (Success, Failed, Retrying)",
"Message": "string (event description)",
"ErrorDetails": "string (nullable, stack trace or error message)",
"Attempt": "int (retry attempt number)",
"RequestPayload": "json (webhook request body)",
"ResponsePayload": "json (nullable, webhook response)",
"HttpStatusCode": "int (nullable, webhook response code)",
"Duration": "int (milliseconds)",
"Timestamp": "datetime (UTC)",
"PerformedBy": "uuid-v4 (nullable, AdminUser ID)"
}
API Endpoints
Tenant Management
Create Tenant
Endpoint: POST /api/v1/tenants
Authentication: Required (tenant:create capability)
Request Body:
{
"organizationName": "Acme Corporation",
"organizationDomain": "acme.com",
"contactEmail": "admin@acme.com",
"contactName": "Jane Doe",
"contactPhone": "+1-555-123-4567",
"planTier": "Professional",
"maxUsers": 25,
"environment": "Production",
"applicationIds": [
"app-1-guid",
"app-2-guid"
],
"metadata": {
"industry": "Technology",
"companySize": "51-200",
"referralSource": "Partner"
}
}
Success Response: 201 Created
{
"tenantId": "tenant-123",
"organizationName": "Acme Corporation",
"status": "Provisioning",
"apiKey": "32-byte-hex-string",
"provisioningStatus": {
"totalApplications": 2,
"provisioned": 0,
"failed": 0,
"inProgress": 2
},
"applications": [
{
"applicationId": "app-1-guid",
"applicationName": "value-manager",
"status": "Provisioning"
},
{
"applicationId": "app-2-guid",
"applicationName": "fee-manager",
"status": "Provisioning"
}
],
"createdAt": "2026-02-02T10:30:00Z",
"createdBy": "admin-user-id"
}
Get Tenant Details
Endpoint: GET /api/v1/tenants/{tenantId}
Authentication: Required (tenant:read capability)
Success Response: 200 OK
{
"tenantId": "tenant-123",
"organizationName": "Acme Corporation",
"organizationDomain": "acme.com",
"contactEmail": "admin@acme.com",
"contactName": "Jane Doe",
"planTier": "Professional",
"maxUsers": 25,
"currentUsers": 12,
"status": "Active",
"statusReason": null,
"environment": "Production",
"isAdminTenant": false,
"applications": [
{
"applicationId": "app-1-guid",
"applicationName": "value-manager",
"displayName": "Value Manager",
"status": "Provisioned",
"provisionedAt": "2026-02-02T10:30:45Z",
"applicationTenantId": "vm-tenant-456"
}
],
"users": [
{
"userId": "user-789",
"fullName": "Jane Doe",
"email": "jane@acme.com",
"role": "tenant-admin",
"joinedAt": "2026-02-02T10:30:00Z"
}
],
"createdAt": "2026-02-02T10:30:00Z",
"lastAccessedAt": "2026-02-02T14:22:00Z",
"metadata": {
"industry": "Technology",
"companySize": "51-200"
}
}
List All Tenants
Endpoint: GET /api/v1/tenants
Authentication: Required (tenant:list capability)
Query Parameters:
status- Filter by status (Active, Suspended, etc.)planTier- Filter by plan tierenvironment- Filter by environmentsearch- Search by organization name or contact emailpage- Page number (default: 1)pageSize- Items per page (default: 50, max: 200)sortBy- Sort field (createdAt, organizationName, lastAccessedAt)sortOrder- Sort direction (asc, desc)
Success Response: 200 OK
{
"tenants": [
{
"tenantId": "tenant-123",
"organizationName": "Acme Corporation",
"contactEmail": "admin@acme.com",
"planTier": "Professional",
"status": "Active",
"userCount": 12,
"applicationCount": 3,
"createdAt": "2026-02-02T10:30:00Z",
"lastAccessedAt": "2026-02-02T14:22:00Z"
}
],
"pagination": {
"page": 1,
"pageSize": 50,
"totalItems": 145,
"totalPages": 3
}
}
Update Tenant
Endpoint: PATCH /api/v1/tenants/{tenantId}
Authentication: Required (tenant:update capability)
Request Body:
{
"organizationName": "Acme Corp (Updated)",
"contactEmail": "newadmin@acme.com",
"planTier": "Enterprise",
"maxUsers": 100,
"metadata": {
"billingContact": "billing@acme.com"
}
}
Success Response: 200 OK (updated tenant object)
Suspend Tenant
Endpoint: PATCH /api/v1/tenants/{tenantId}/suspend
Authentication: Required (tenant:suspend capability)
Request Body:
{
"reason": "Payment failed - account overdue",
"gracePeriodDays": 30,
"notifyUsers": true
}
Success Response: 200 OK
{
"tenantId": "tenant-123",
"status": "Suspended",
"statusReason": "Payment failed - account overdue",
"suspendedAt": "2026-02-02T15:00:00Z",
"gracePeriodEnds": "2026-03-04T15:00:00Z",
"applicationsSuspended": 3,
"usersNotified": 12
}
Reactivate Tenant
Endpoint: PATCH /api/v1/tenants/{tenantId}/reactivate
Authentication: Required (tenant:reactivate capability)
Success Response: 200 OK
{
"tenantId": "tenant-123",
"status": "Active",
"reactivatedAt": "2026-02-02T16:00:00Z",
"applicationsReactivated": 3
}
Retry Failed Provisioning
Endpoint: POST /api/v1/tenants/{tenantId}/retry-provisioning
Authentication: Required (tenant:provision capability)
Request Body:
{
"applicationIds": [
"app-2-guid"
]
}
Success Response: 200 OK
{
"tenantId": "tenant-123",
"retriedApplications": 1,
"results": [
{
"applicationId": "app-2-guid",
"status": "Provisioned",
"message": "Successfully provisioned on retry"
}
]
}
Deprovision Tenant
Endpoint: DELETE /api/v1/tenants/{tenantId}
Authentication: Required (tenant:delete capability)
Query Parameters:
dataRetentionDays- Days to retain data (default: 90, max: 365)confirm- Must be "true" to confirm deletion
Request Body:
{
"reason": "Customer requested account deletion",
"notifyUsers": true
}
Success Response: 200 OK
{
"tenantId": "tenant-123",
"status": "Deprovisioned",
"deprovisionedAt": "2026-02-02T17:00:00Z",
"dataRetentionUntil": "2026-05-03T17:00:00Z",
"applicationsDeprovisioned": 3,
"usersNotified": 12,
"summary": {
"totalApplications": 3,
"successfullyDeprovisioned": 3,
"failed": 0
}
}
Application-Specific Provisioning Webhooks
These endpoints are implemented by registered applications, not Application Manager.
Provision Tenant Webhook (Application Implements)
Endpoint: POST {app.ProvisioningUrl}
Example: POST https://value-manager.acme.com/api/tenants/provision
Headers:
X-Api-Key: {api-key-from-app-registration}
X-Tenant-Id: {tenant-id-from-application-manager}
Content-Type: application/json
Request Body (sent by Application Manager):
{
"tenantId": "tenant-123",
"organizationName": "Acme Corporation",
"contactEmail": "admin@acme.com",
"contactName": "Jane Doe",
"planTier": "Professional",
"maxUsers": 25,
"environment": "Production",
"metadata": {
"industry": "Technology"
}
}
Expected Response: 200 OK or 201 Created
{
"success": true,
"tenantId": "tenant-123",
"applicationTenantId": "vm-tenant-456",
"message": "Tenant provisioned successfully",
"metadata": {
"databaseSchema": "tenant_123",
"storageQuota": "100GB"
}
}
Error Response: 500 Internal Server Error
{
"success": false,
"error": "DatabaseConnectionFailed",
"message": "Unable to create tenant database",
"retryable": true
}
Suspend Tenant Webhook (Application Implements)
Endpoint: PATCH {app.ProvisioningUrl}/{tenantId}/suspend
Headers: Same as provisioning
Expected Response: 200 OK
{
"success": true,
"tenantId": "tenant-123",
"message": "Tenant access disabled"
}
Reactivate Tenant Webhook (Application Implements)
Endpoint: PATCH {app.ProvisioningUrl}/{tenantId}/reactivate
Headers: Same as provisioning
Expected Response: 200 OK
Deprovision Tenant Webhook (Application Implements)
Endpoint: DELETE {app.ProvisioningUrl}/{tenantId}
Headers: Same as provisioning
Query Parameters:
retainData- Boolean (if true, move to cold storage; if false, hard delete)
Expected Response: 204 No Content or 200 OK
{
"success": true,
"tenantId": "tenant-123",
"message": "Tenant data purged successfully",
"metadata": {
"recordsDeleted": 15000,
"storageFreed": "2.5GB"
}
}
User Interface Mockups
Tenant List View
┌────────────────────────────────────────────────────────────────────────┐
│ Application Manager - Tenant Management │
│ ═══════════════════════════════════════════════════════════════════ │
│ │
│ [+ Create Tenant] Search: [___________] 🔍 │
│ │
│ Filters: │
│ Status: [All ▾] Plan: [All ▾] Environment: [Production ▾] │
│ │
│ ┌──────────────────────────────────────────────────────────────────┐│
│ │ Organization │ Contact │ Plan │ Status │ Users │ Apps││
│ ├──────────────────────────────────────────────────────────────────┤│
│ │ Acme Corporation │ admin@acme │ Pro │ 🟢 Active │ 12/25│ 3 ││
│ │ Created: 2026-02-01 │ Last Access: 2 hours ago [···] ││
│ │ ││
│ │ Beta Industries │ beta@beta │ Start │ 🟡 Partial│ 5/10│ 2 ││
│ │ Created: 2026-01-28 │ Last Access: 3 days ago [···] ││
│ │ ││
│ │ Global Dynamics │ ops@global │ Ent │ 🔴 Suspended│ 45 │ 5 ││
│ │ Created: 2025-12-15 │ Suspended: Payment overdue [···] ││
│ │ ││
│ │ Test Company │ test@test │ Free │ ⚫ Deprov │ 0 │ 1 ││
│ │ Created: 2025-11-20 │ Deprovisioned: 2026-01-30 [···] ││
│ └──────────────────────────────────────────────────────────────────┘│
│ │
│ Showing 1-4 of 145 tenants [← Previous] [1] 2 3 [Next →] │
└────────────────────────────────────────────────────────────────────────┘
Tenant Details View
┌────────────────────────────────────────────────────────────────────────┐
│ ← Back to Tenants │
│ │
│ Acme Corporation [Edit] [Suspend] [Delete]│
│ ═══════════════════════════════════════════════════════════════════ │
│ │
│ Status: 🟢 Active Plan: Professional │
│ Tenant ID: tenant-123 Environment: Production │
│ API Key: ****-****-****-ab12 [Show] [Regenerate] │
│ │
│ ┌─────────────────────────────────────────────────────────────────┐ │
│ │ Organization Details │ │
│ │ ═══════════════════════════════════════════════════════════════ │ │
│ │ Organization Name: Acme Corporation │ │
│ │ Domain: acme.com │ │
│ │ Contact: Jane Doe (admin@acme.com) │ │
│ │ Phone: +1-555-123-4567 │ │
│ │ Created: 2026-02-01 at 10:30 AM by Admin User │ │
│ │ Last Accessed: 2 hours ago │ │
│ └─────────────────────────────────────────────────────────────────┘ │
│ │
│ ┌─────────────────────────────────────────────────────────────────┐ │
│ │ Applications (3) [+ Add App] │ │
│ │ ═══════════════════════════════════════════════════════════════ │ │
│ │ │ │
│ │ 🟢 Value Manager Status: Provisioned │ │
│ │ Provisioned: 2026-02-01 at 10:32 AM │ │
│ │ App Tenant ID: vm-tenant-456 │ │
│ │ [Launch] [Suspend] [Deprovision] │ │
│ │ │ │
│ │ 🟢 Fee Manager Status: Provisioned │ │
│ │ Provisioned: 2026-02-01 at 10:33 AM │ │
│ │ App Tenant ID: fm-tenant-789 │ │
│ │ [Launch] [Suspend] [Deprovision] │ │
│ │ │ │
│ │ 🔴 Workflow Engine Status: Failed │ │
│ │ Last Attempt: 2026-02-01 at 10:35 AM (3 attempts) │ │
│ │ Error: Connection timeout │ │
│ │ [Retry Provisioning] [View Logs] │ │
│ └─────────────────────────────────────────────────────────────────┘ │
│ │
│ ┌─────────────────────────────────────────────────────────────────┐ │
│ │ Users (12 / 25 max) [+ Invite User] │ │
│ │ ═══════════════════════════════════════════════════════════════ │ │
│ │ Jane Doe (admin@acme.com) Role: tenant-admin │ │
│ │ John Smith (john@acme.com) Role: tenant-member │ │
│ │ [View All Users →] │ │
│ └─────────────────────────────────────────────────────────────────┘ │
│ │
│ ┌─────────────────────────────────────────────────────────────────┐ │
│ │ Provisioning Logs [View All Logs →] │ │
│ │ ═══════════════════════════════════════════════════════════════ │ │
│ │ 2026-02-01 10:35 AM │ Workflow Engine │ Failed (Attempt 3) │ │
│ │ 2026-02-01 10:33 AM │ Fee Manager │ Provisioned │ │
│ │ 2026-02-01 10:32 AM │ Value Manager │ Provisioned │ │
│ │ 2026-02-01 10:30 AM │ Tenant Created │ Success │ │
│ └─────────────────────────────────────────────────────────────────┘ │
└────────────────────────────────────────────────────────────────────────┘
Create Tenant Dialog
┌──────────────────────────────────────────────────────────────┐
│ Create New Tenant │
│ ══════════════════════════════════════════════════════════ │
│ │
│ Organization Information │
│ │
│ Organization Name * │
│ ┌────────────────────────────────────────────────────────┐ │
│ │ Acme Corporation │ │
│ └────────────────────────────────────────────────────────┘ │
│ │
│ Organization Domain │
│ ┌────────────────────────────────────────────────────────┐ │
│ │ acme.com │ │
│ └────────────────────────────────────────────────────────┘ │
│ │
│ Contact Information │
│ │
│ Contact Name * Contact Email * │
│ ┌──────────────────────┐ ┌──────────────────────────────┐│
│ │ Jane Doe │ │ admin@acme.com ││
│ └──────────────────────┘ └──────────────────────────────┘│
│ │
│ Contact Phone │
│ ┌────────────────────────────────────────────────────────┐ │
│ │ +1-555-123-4567 │ │
│ └────────────────────────────────────────────────────────┘ │
│ │
│ Plan & Configuration │
│ │
│ Plan Tier * │
│ ┌────────────────────────────────────────────────────────┐ │
│ │ Professional ▾ │ │
│ └────────────────────────────────────────────────────────┘ │
│ │
│ Max Users Environment │
│ ┌──────────────────────┐ ┌──────────────────────────────┐│
│ │ 25 │ │ Production ▾ ││
│ └──────────────────────┘ └──────────────────────────────┘│
│ │
│ Applications to Provision * │
│ ┌────────────────────────────────────────────────────────┐ │
│ │ ☑ Value Manager │ │
│ │ ☑ Fee Manager │ │
│ │ ☐ Workflow Engine │ │
│ │ ☑ Configuration Manager │ │
│ └────────────────────────────────────────────────────────┘ │
│ │
│ ℹ️ Selected applications will be provisioned automatically │
│ with isolated tenant environments. │
│ │
│ ───────────────────────────────────────────────────────── │
│ │
│ [Cancel] [Create Tenant] │
└──────────────────────────────────────────────────────────────┘
Suspend Tenant Confirmation Dialog
┌──────────────────────────────────────────────────────────────┐
│ Suspend Tenant: Acme Corporation │
│ ══════════════════════════════════════════════════════════ │
│ │
│ ⚠️ Warning: This will immediately disable access for all │
│ users in this tenant across all applications. │
│ │
│ Affected: │
│ • 12 users │
│ • 3 applications (Value Manager, Fee Manager, Config Mgr) │
│ │
│ Reason for Suspension * │
│ ┌────────────────────────────────────────────────────────┐ │
│ │ Payment failed - account overdue │ │
│ └────────────────────────────────────────────────────────┘ │
│ │
│ Grace Period (days) │
│ ┌────────────────────────────────────────────────────────┐ │
│ │ 30 │ │
│ └────────────────────────────────────────────────────────┘ │
│ ℹ️ After grace period, tenant will be deprovisioned │
│ │
│ ☑ Send notification emails to all users │
│ ☑ Notify billing system │
│ │
│ ───────────────────────────────────────────────────────── │
│ │
│ [Cancel] [Suspend Tenant] │
└──────────────────────────────────────────────────────────────┘
Security Considerations
Tenant Isolation
- Each tenant must have cryptographically unique API key (32 bytes)
- API keys transmitted only via HTTPS
- Applications enforce tenant-level data isolation
- No cross-tenant data access permitted
- Tenant context validated on every request
Webhook Security
- All provisioning webhooks require API key authentication
- Webhook URLs must be HTTPS only (no HTTP)
- Request signing with HMAC-SHA256 (optional enhancement)
- IP allowlisting for Application Manager webhook sources
- Rate limiting on webhook endpoints (10 requests/minute per tenant)
Deprovisioning Security
- Two-step confirmation required for deprovisioning
- AdminUser must have
tenant:deletecapability - All deprovisioning actions logged in audit trail
- Data retention policies enforced (minimum 30 days for compliance)
- Cannot deprovision admin tenant
Access Control
- Tenant operations require specific capabilities (
tenant:create,tenant:suspend, etc.) - ApplicationUsers can only view/modify their own tenant
- AdminUsers can manage all tenants
- Billing system API key separate from admin user authentication
Audit & Compliance
- All tenant lifecycle events logged with actor, timestamp, reason
- Provisioning logs retained indefinitely
- Tenant metadata retained even after deprovisioning
- GDPR-compliant data deletion on request (with legal compliance check)
Non-Functional Requirements
Performance
- Tenant provisioning: < 60 seconds for 3 applications
- Webhook timeout: 30 seconds per application
- Parallel provisioning with max 5 concurrent webhook calls
- Tenant list query: < 500ms for 10,000 tenants
- Status updates propagate within 5 seconds
Reliability
- Webhook retry: 3 attempts with exponential backoff (10s, 30s, 90s)
- Failed provisioning does not block ApplicationUser creation (configurable)
- Partial provisioning allows tenant to be active with subset of applications
- Automatic recovery for transient network failures
- Dead letter queue for permanently failed webhooks
Scalability
- Support 10,000+ active tenants
- Handle 100 concurrent tenant provisioning requests
- Background job processes expired tenants (batch size: 100)
- Database indexes on: TenantId, Status, CreatedAt, OrganizationDomain
Observability
- Prometheus metrics: provisioning success rate, webhook latency, retry count
- Application Insights: tenant lifecycle events, application-specific provisioning times
- Alerts: provisioning failure rate > 10%, webhook timeout rate > 5%
- Dashboard: active tenants, provisioning queue depth, suspension rate
Disaster Recovery
- Tenant provisioning is idempotent (safe to retry)
- Webhook calls include correlation IDs for tracing
- Manual recovery tools for stuck provisioning jobs
- Backup/restore support for tenant metadata
Related Use Cases
- UC-001: Trial User Self-Registration - Trial tenants (temporary, auto-expire)
- UC-013: Application Registration and Management - Applications register provisioning endpoints
- UC-015: Application User Provisioning - User creation triggers tenant provisioning
- UC-006: Role-Based Access Control - Tenant-scoped role assignments
- UC-010: Activity Logging and Audit Trail - Tenant lifecycle events logged
Open Questions
Should tenant provisioning be synchronous (block user creation) or asynchronous (user created, provisioning background)?
- Recommendation: Configurable per application. Critical apps (identity) block, non-critical apps async.
How do we handle multi-region tenant provisioning (e.g., EU data residency requirements)?
- Recommendation: Tenant.Metadata includes
dataRegionfield, applications handle region-specific provisioning.
- Recommendation: Tenant.Metadata includes
Should we support tenant hierarchies (parent/child organizations)?
- Recommendation: V2 feature. V1 supports flat tenant structure only.
How do we handle tenant migrations between environments (dev → staging → prod)?
- Recommendation: UC-017: Tenant Migration (separate use case for complex multi-step process).
Should billing integration be part of Application Manager or separate service?
- Recommendation: Separate service. Application Manager sends webhook events to billing system.
What happens if user tries to access application that failed provisioning?
- Recommendation: Show friendly error: "This application is not available. Contact support."
Glossary
- Tenant: Isolated environment for an organization within a multi-tenant application
- Provisioning: Process of creating and initializing a tenant in an application
- Deprovisioning: Process of removing tenant and purging data from application
- Provisioning Webhook: HTTP endpoint implemented by application to handle tenant lifecycle events
- Admin Tenant: Special tenant pre-created for Riptide team members, never expires
- Partial Provisioning: State where tenant is provisioned in some applications but not others
- Grace Period: Time window between suspension and deprovisioning (default 30 days)
- Soft Delete: Marking tenant as deprovisioned but retaining metadata for compliance
- Hard Delete: Permanent deletion of tenant data from applications (after retention period)
- Plan Tier: Subscription level (Free, Starter, Professional, Enterprise)