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
389 lines
9.9 KiB
Markdown
389 lines
9.9 KiB
Markdown
# 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 orchestration
|
|
- `ee/temporal-workflows/src/db/tenant-operations.ts` - Database operations for tenant setup
|
|
- `ee/temporal-workflows/src/db/user-operations.ts` - User creation and management
|
|
- `ee/temporal-workflows/src/services/email-service.ts` - Email notification service
|
|
|
|
## Workflow Steps
|
|
|
|
### 1. Tenant Creation (`creating_tenant`)
|
|
- Creates tenant record in `tenants` table
|
|
- Optionally creates company record in `companies` table
|
|
- Establishes tenant-company relationship
|
|
- **Progress**: 10% → 40%
|
|
|
|
### 2. Admin User Creation (`creating_admin_user`)
|
|
- Creates admin user in `users` table
|
|
- Assigns admin role via `user_roles` table
|
|
- 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
|
|
|
|
```sql
|
|
-- 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
|
|
|
|
```typescript
|
|
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
|
|
|
|
```typescript
|
|
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
|
|
|
|
```typescript
|
|
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:
|
|
|
|
1. **User Rollback**: Removes user records and role assignments
|
|
2. **Tenant Rollback**: Removes tenant, company, and associated data
|
|
3. **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
|
|
|
|
```typescript
|
|
retry: {
|
|
maximumAttempts: 3,
|
|
backoffCoefficient: 2.0,
|
|
initialInterval: '1s',
|
|
maximumInterval: '30s',
|
|
nonRetryableErrorTypes: ['ValidationError', 'DuplicateError']
|
|
}
|
|
```
|
|
|
|
## Monitoring & Observability
|
|
|
|
### Workflow State Queries
|
|
|
|
```typescript
|
|
// 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
|
|
|
|
```typescript
|
|
// 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:
|
|
|
|
```bash
|
|
# 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
|
|
|
|
1. **Temporal Server**: Running and accessible
|
|
2. **PostgreSQL**: Alga database with proper schema
|
|
3. **Email Service**: Configured email provider (Resend, AWS SES, etc.)
|
|
4. **Worker Process**: Temporal worker running with proper activities
|
|
|
|
### Configuration
|
|
|
|
```typescript
|
|
// 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
|
|
|
|
```typescript
|
|
// 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
|
|
|
|
1. **Database Connection Failures**
|
|
- Check connection string and credentials
|
|
- Verify network connectivity
|
|
- Ensure database schema is up to date
|
|
|
|
2. **Email Delivery Failures**
|
|
- Verify email service API key
|
|
- Check rate limiting and quotas
|
|
- Validate email addresses
|
|
|
|
3. **Workflow Timeouts**
|
|
- Increase timeout values if needed
|
|
- Check for deadlocks or slow queries
|
|
- Monitor system resources
|
|
|
|
### Debugging
|
|
|
|
```typescript
|
|
// 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 |