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

  1. Application Manager platform is running
  2. At least one application is registered with provisioning endpoints configured
  3. AdminUser has tenant:manage capability
  4. Database schema for tenant entities is initialized
  5. Application webhooks are accessible and authenticated

Postconditions

Success Postconditions

  1. Tenant record created/updated in Application Manager database
  2. Tenant provisioned in target application(s) via webhook callbacks
  3. Tenant ID assigned to ApplicationUser(s)
  4. Tenant context available for session validation
  5. Provisioning status logged in audit trail
  6. Billing system notified of tenant lifecycle events (if integrated)

Failure Postconditions

  1. Tenant provisioning rolled back if webhook calls fail
  2. ApplicationUser creation blocked if provisioning fails (configurable)
  3. Error logged with detailed failure reason
  4. Alert sent to AdminUser for manual intervention
  5. 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

  1. Tenant Creation Triggered

    • ApplicationUser creation (UC-015) triggers tenant provisioning
    • OR AdminUser explicitly creates tenant for organization
    • OR Application registration creates admin tenant
  2. System Generates Tenant Record

    • Create Tenant entity with unique GUID
    • Set Status = Provisioning
    • Assign OrganizationName, ContactEmail, PlanTier
    • Generate ApiKey for tenant-to-platform communication
    • Set CreatedBy to AdminUser ID
    • Set CreatedAt timestamp
  3. System Retrieves Application List

    • Query all registered applications with ProvisioningUrl configured
    • Filter by applications user should have access to (based on plan/roles)
    • Order by priority (critical apps first)
  4. 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
  5. 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
  6. System Records Provisioning Results

    • Create ApplicationTenantMapping for each successful provisioning
    • Store application-specific tenant ID if returned
    • Update Tenant.Status = Active when all apps succeed
    • Update Tenant.Status = PartiallyProvisioned if some fail
    • Log failures with error messages for retry
  7. System Links User to Tenant

    • Update ApplicationUser.TenantId with new tenant ID
    • Create default tenant admin role assignment
    • Grant access to provisioned applications
  8. 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:

  1. Application webhook call fails (timeout, 5xx error, network issue)
  2. System immediately retries (attempt 1 of 3) after 10 seconds
  3. If still failing, wait 30 seconds and retry (attempt 2)
  4. If still failing, wait 90 seconds and final retry (attempt 3)
  5. After 3 failures, mark ApplicationTenantMapping.Status = Failed
  6. Update Tenant.Status = PartiallyProvisioned (if other apps succeeded)
  7. Create alert for AdminUser with error details
  8. AdminUser can manually retry via UI: "Retry Failed Provisioning"
  9. 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:

  1. System provisions tenant across 3 applications
  2. App1 succeeds, App2 fails, App3 succeeds
  3. Tenant.Status = PartiallyProvisioned
  4. AdminUser sees status: "2 of 3 applications provisioned"
  5. AdminUser options:
    • Retry failed application
    • Mark tenant as Active (accept partial provisioning)
    • Deprovision successful apps and abort
  6. User can still access successfully provisioned applications

Alt Flow 3: Tenant Suspension (Non-Payment)

Steps:

  1. Billing system detects failed payment
  2. Billing system calls: PATCH /api/v1/tenants/{id}/suspend
  3. System validates billing system API key
  4. System updates Tenant.Status = Suspended
  5. System calls suspension webhook for each application:
    • PATCH /api/tenants/{tenantId}/suspend
  6. Applications disable access but retain data
  7. Users attempting to access see "Account Suspended" message
  8. AdminUser can view suspension reason: "Payment Failed - Renew by "
  9. After grace period (default 30 days), tenant moves to deprovisioning

Alt Flow 4: Tenant Reactivation

Steps:

  1. Billing system confirms payment received
  2. Billing system calls: PATCH /api/v1/tenants/{id}/reactivate
  3. System validates tenant was suspended (not deprovisioned)
  4. System updates Tenant.Status = Active
  5. System calls reactivation webhook for each application:
    • PATCH /api/tenants/{tenantId}/reactivate
  6. Applications re-enable access
  7. System sends welcome back email to organization
  8. Audit log records reactivation with reason

Alt Flow 5: Tenant Data Retention (Compliance)

Steps:

  1. AdminUser initiates soft delete: "Deprovision but retain for 90 days"
  2. System updates Tenant.Status = Deprovisioned
  3. System sets Tenant.DataRetentionUntil = Now + 90 days
  4. System calls application deprovisioning webhooks
  5. Applications archive tenant data (move to cold storage)
  6. Users cannot access applications
  7. After 90 days, scheduled job calls hard delete:
    • Applications permanently purge tenant data
    • Application Manager removes ApplicationTenantMapping records
    • Tenant metadata retained indefinitely for audit

Alt Flow 6: Tenant Migration (Environment Transfer)

Steps:

  1. AdminUser requests tenant migration: Dev → Staging → Production
  2. System validates target environment is registered
  3. System exports tenant metadata and configuration
  4. System provisions tenant in target environment (normal flow)
  5. Applications handle data migration (out of scope for Application Manager)
  6. System updates tenant's environment identifier
  7. Users receive notification of migration
  8. 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 progress
  • Active - All applications provisioned successfully
  • PartiallyProvisioned - Some applications failed, manual intervention needed
  • Suspended - 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 tier
  • environment - Filter by environment
  • search - Search by organization name or contact email
  • page - 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:delete capability
  • 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
  • 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

  1. 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.
  2. How do we handle multi-region tenant provisioning (e.g., EU data residency requirements)?

    • Recommendation: Tenant.Metadata includes dataRegion field, applications handle region-specific provisioning.
  3. Should we support tenant hierarchies (parent/child organizations)?

    • Recommendation: V2 feature. V1 supports flat tenant structure only.
  4. How do we handle tenant migrations between environments (dev → staging → prod)?

    • Recommendation: UC-017: Tenant Migration (separate use case for complex multi-step process).
  5. Should billing integration be part of Application Manager or separate service?

    • Recommendation: Separate service. Application Manager sends webhook events to billing system.
  6. 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)