Some checks are pending
Bidi Control Character Guard / bidi-control-guard (push) Waiting to run
Circular Dependency Check / Check for new circular dependencies (push) Waiting to run
Citus Migration Smoke / Combined migrations on single-node Citus (push) Waiting to run
E2E Fresh Install Tests / fresh-install-e2e (push) Waiting to run
ext-v2 guardrails / Run ext-v2 guard and ESLint (push) Waiting to run
Integration Tests / Check for relevant changes (push) Waiting to run
Integration Tests / ${{ (github.event_name == 'schedule' || github.event.inputs.suite == 'full') && 'Full integration suite' || 'Tier-1 integration subset' }} (push) Blocked by required conditions
Mobile checks / Mobile lint + typecheck (push) Waiting to run
Mobile checks / Mobile unit tests (push) Waiting to run
Mobile checks / Mobile dependency audit (report) (push) Waiting to run
Mobile checks / Mobile reproducibility checks (push) Waiting to run
Secrets guard (env backups) / Ensure no tracked env backup files (push) Waiting to run
Temporal Readiness / fast-readiness (push) Waiting to run
Temporal Readiness / docker-parity (push) Waiting to run
TypeScript Type Check / Nx affected typecheck (push) Waiting to run
Unit Tests / Skipped-test budget (push) Waiting to run
Unit Tests / Nx affected unit tests (push) Waiting to run
Unit Tests / Server unit coverage (informational) (push) Waiting to run
Validate Tenant Management Schema / Check for relevant changes (push) Waiting to run
Validate Tenant Management Schema / Validate Tenant Management Schema (push) Blocked by required conditions
EE Workflows Build Guard / ee-workflows-build-guard (push) Waiting to run
Excluded: .git, node_modules, secrets/, compose.env, assemblyscript tgz Source: /opt/alga-psa on psa.joliet.tech
9.9 KiB
9.9 KiB
Tenant Onboarding Process
Overview
The tenant onboarding process is a fully automated workflow that provisions new tenants in the Alga PSA system. This process uses Temporal workflows to ensure reliability, consistency, and proper error handling throughout the tenant creation process.
Architecture
Components
- Temporal Workflows: Orchestrate the multi-step tenant creation process
- Database Operations: Handle tenant, user, and company creation in PostgreSQL
- Email Service: Send welcome emails to new admin users
- Rollback System: Automatic cleanup in case of failures
Key Files
ee/temporal-workflows/src/workflows/tenant-creation-workflow.ts- Main workflow orchestrationee/temporal-workflows/src/db/tenant-operations.ts- Database operations for tenant setupee/temporal-workflows/src/db/user-operations.ts- User creation and managementee/temporal-workflows/src/services/email-service.ts- Email notification service
Workflow Steps
1. Tenant Creation (creating_tenant)
- Creates tenant record in
tenantstable - Optionally creates company record in
companiestable - Establishes tenant-company relationship
- Progress: 10% → 40%
2. Admin User Creation (creating_admin_user)
- Creates admin user in
userstable - Assigns admin role via
user_rolestable - Generates temporary password
- Progress: 40% → 60%
3. Tenant Data Setup (setting_up_data)
- Configures tenant email settings in
tenant_email_settings - Sets up tenant-company associations in
tenant_companies - Initializes default configurations
- Progress: 60% → 85%
4. Welcome Email (sending_welcome_email)
- Sends welcome email to admin user
- Includes login credentials and setup instructions
- Progress: 85% → 100%
Database Schema
Core Tables
-- Tenant record
tenants (
tenant VARCHAR PRIMARY KEY,
company_name VARCHAR,
email VARCHAR,
created_at TIMESTAMP,
updated_at TIMESTAMP
)
-- Company record
companies (
company_id VARCHAR PRIMARY KEY,
company_name VARCHAR,
tenant VARCHAR REFERENCES tenants(tenant),
created_at TIMESTAMP,
updated_at TIMESTAMP
)
-- Admin user
users (
user_id VARCHAR PRIMARY KEY,
tenant VARCHAR REFERENCES tenants(tenant),
first_name VARCHAR,
last_name VARCHAR,
email VARCHAR,
password_hash VARCHAR,
created_at TIMESTAMP,
updated_at TIMESTAMP
)
-- User roles
user_roles (
user_id VARCHAR REFERENCES users(user_id),
role_id VARCHAR,
tenant VARCHAR REFERENCES tenants(tenant),
created_at TIMESTAMP,
updated_at TIMESTAMP
)
-- Email settings
tenant_email_settings (
tenant_id VARCHAR,
email_provider VARCHAR DEFAULT 'resend',
fallback_enabled BOOLEAN DEFAULT true,
tracking_enabled BOOLEAN DEFAULT false,
created_at TIMESTAMP,
updated_at TIMESTAMP
)
-- Tenant-company associations
tenant_companies (
tenant VARCHAR REFERENCES tenants(tenant),
company_id VARCHAR REFERENCES companies(company_id),
is_default BOOLEAN DEFAULT false,
created_at TIMESTAMP,
updated_at TIMESTAMP
)
API Usage
Starting a Tenant Creation Workflow
import { Client } from '@temporalio/client';
const client = new Client({ address: 'localhost:7233' });
const result = await client.workflow.start('tenantCreationWorkflow', {
workflowId: `tenant-creation-${Date.now()}`,
taskQueue: 'tenant-creation',
args: [{
tenantName: 'Acme Corp',
adminUser: {
firstName: 'John',
lastName: 'Doe',
email: 'john.doe@acme.com'
},
companyName: 'Acme Corporation',
contractLine: 'professional'
}]
});
// Monitor progress
const handle = client.workflow.getHandle(result.workflowId);
const state = await handle.query('getState');
console.log('Current step:', state.step, 'Progress:', state.progress + '%');
Input Parameters
interface TenantCreationInput {
tenantName: string; // Display name for the tenant
adminUser: {
firstName: string;
lastName: string;
email: string; // Admin user email (also used for tenant)
};
companyName?: string; // Optional company name
contractLine?: string; // Optional contract line (default: 'basic')
}
Output Results
interface TenantCreationResult {
tenantId: string; // Generated tenant ID
adminUserId: string; // Generated admin user ID
companyId?: string; // Generated company ID (if applicable)
temporaryPassword: string; // Temporary password for admin user
emailSent: boolean; // Whether welcome email was sent
success: boolean; // Overall success status
createdAt: string; // ISO timestamp of completion
}
Error Handling & Rollback
Automatic Rollback
The workflow includes comprehensive rollback mechanisms:
- User Rollback: Removes user records and role assignments
- Tenant Rollback: Removes tenant, company, and associated data
- Cascade Cleanup: Handles foreign key relationships properly
Error Types
- ValidationError: Invalid input data (non-retryable)
- DuplicateError: Tenant/user already exists (non-retryable)
- DatabaseError: Connection or query issues (retryable)
- EmailError: Email service failures (retryable)
Retry Policy
retry: {
maximumAttempts: 3,
backoffCoefficient: 2.0,
initialInterval: '1s',
maximumInterval: '30s',
nonRetryableErrorTypes: ['ValidationError', 'DuplicateError']
}
Monitoring & Observability
Workflow State Queries
// Get current workflow state
const state = await handle.query('getState');
// State includes:
// - step: Current workflow step
// - progress: Completion percentage (0-100)
// - tenantId: Created tenant ID
// - adminUserId: Created admin user ID
// - companyId: Created company ID
// - emailSent: Email delivery status
// - error: Error message (if failed)
Workflow Signals
// Cancel workflow
await handle.signal('cancel', {
reason: 'User requested cancellation',
cancelledBy: 'admin@example.com'
});
// Update workflow parameters
await handle.signal('update', {
field: 'contractLine',
value: 'enterprise'
});
Testing
E2E Tests
The system includes comprehensive end-to-end tests:
# Run all E2E tests
cd ee/temporal-workflows
npm run test:e2e
# Run specific tenant creation test
npm run test:e2e -- tenant-creation-workflow.e2e.test.ts
Test Coverage
- ✅ Complete tenant creation workflow
- ✅ Database rollback on failures
- ✅ Email service integration
- ✅ Workflow state management
- ✅ Error handling and retries
- ✅ Signal and query operations
Production Deployment
Prerequisites
- Temporal Server: Running and accessible
- PostgreSQL: Alga database with proper schema
- Email Service: Configured email provider (Resend, AWS SES, etc.)
- Worker Process: Temporal worker running with proper activities
Configuration
// Worker configuration
const worker = new Worker({
taskQueue: 'tenant-creation',
workflowsPath: require.resolve('./workflows'),
activitiesPath: require.resolve('./activities'),
// Database connection
connection: {
host: process.env.DB_HOST,
port: parseInt(process.env.DB_PORT || '5432'),
database: process.env.DB_NAME,
user: process.env.DB_USER,
password: process.env.DB_PASSWORD
},
// Email service
email: {
provider: process.env.EMAIL_PROVIDER || 'resend',
apiKey: process.env.EMAIL_API_KEY
}
});
Health Checks
// Basic health check workflow
const health = await client.workflow.execute('healthCheckWorkflow', {
workflowId: 'health-check',
taskQueue: 'tenant-creation'
});
console.log('System status:', health.status); // 'healthy'
Security Considerations
Data Protection
- All passwords are hashed using bcrypt
- Temporary passwords are cryptographically secure
- Database connections use SSL/TLS
- Email content is sanitized
Access Control
- Workflow execution requires proper Temporal permissions
- Database operations use principle of least privilege
- Email service API keys are encrypted at rest
Audit Trail
- All workflow executions are logged
- Database operations include audit timestamps
- Email delivery is tracked and logged
Performance Metrics
Typical Execution Times
- Total Workflow: 2-5 seconds
- Database Operations: 1-2 seconds
- Email Delivery: 1-3 seconds
- Rollback Operations: 0.5-1 second
Resource Usage
- Memory: ~50MB per workflow execution
- CPU: Minimal (I/O bound operations)
- Database: 5-10 queries per tenant creation
Troubleshooting
Common Issues
-
Database Connection Failures
- Check connection string and credentials
- Verify network connectivity
- Ensure database schema is up to date
-
Email Delivery Failures
- Verify email service API key
- Check rate limiting and quotas
- Validate email addresses
-
Workflow Timeouts
- Increase timeout values if needed
- Check for deadlocks or slow queries
- Monitor system resources
Debugging
// Enable debug logging
const client = new Client({
address: 'localhost:7233',
logger: new DefaultLogger('DEBUG')
});
// Query workflow history
const history = await handle.fetchHistory();
console.log('Workflow events:', history.events);
Future Enhancements
Planned Features
- Bulk Tenant Creation: Support for creating multiple tenants
- Custom Email Templates: Configurable welcome email content
- Integration Webhooks: Notify external systems of tenant creation
- Advanced Analytics: Tenant creation metrics and reporting
- Self-Service Portal: Allow customers to create their own tenants
Scaling Considerations
- Database Sharding: For high-volume tenant creation
- Workflow Batching: Group operations for efficiency
- Async Email: Decouple email sending from workflow
- Caching: Cache frequently accessed data