TGM Manager provides isolated sandbox environments that allow users to test features, train staff, or demonstrate the system without affecting production data. Each sandbox has its own database schema with complete data isolation.
Overview¶
Sandbox environments are useful for:
- Testing - Try new configurations without risk
- Training - Onboard new users with realistic data
- Demos - Showcase features to stakeholders
- Development - Test integrations in isolation
Each sandbox includes: - Isolated PostgreSQL schema - Optional pre-populated mock data - Configurable access levels - Unique URL (subdomain or custom domain)
Sandbox Status¶
| Status | Description |
|---|---|
PENDING |
Sandbox created but schema not yet provisioned |
PROVISIONING |
Schema is being created and migrations running |
ACTIVE |
Ready for use |
SUSPENDED |
Temporarily disabled (can be reactivated) |
TERMINATED |
Permanently deleted, schema dropped |
Access Levels¶
| Level | Permissions |
|---|---|
OWNER |
Full control including delete |
ADMIN |
Manage users and settings |
USER |
Full data access (read/write) |
VIEWER |
Read-only access |
REST API¶
Sandbox Management¶
List User's Sandboxes¶
GET /api/sandboxes
Response:
[
{
"id": 1,
"name": "Happy Lion",
"slug": "happy-lion",
"description": "Development testing environment",
"url": "https://happy-lion.tgm.ensolutions.ca",
"subdomain": "happy-lion",
"customDomain": null,
"status": "ACTIVE",
"mockDataTemplate": "demo_light",
"mockDataSeeded": true,
"createdAt": "2024-01-15T10:30:00",
"lastAccessedAt": "2024-01-20T14:22:00",
"currentUserAccess": "OWNER",
"isActive": true,
"ownerId": 1,
"ownerName": "John Doe"
}
]
Create Sandbox¶
POST /api/sandboxes
Content-Type: application/json
{
"name": "Happy Lion",
"slug": "happy-lion",
"description": "Development testing environment",
"subdomain": "happy-lion",
"customDomain": null,
"mockDataTemplate": "demo_light"
}
Parameters:
- name (required) - Display name (3-100 characters)
- slug (required) - URL-friendly identifier (3-50 chars, lowercase, numbers, hyphens)
- description (optional) - Description (max 500 characters)
- subdomain (optional) - Subdomain for sandbox URL
- customDomain (optional) - Custom domain (max 255 characters)
- mockDataTemplate (optional) - Mock data template (default: "empty")
Required Role: SUPER_ADMIN, ADMIN, or MANAGER
Get Sandbox Details¶
GET /api/sandboxes/{id}
Get Sandbox by Slug¶
GET /api/sandboxes/slug/{slug}
Terminate Sandbox¶
Permanently delete a sandbox and all its data. Only the owner can perform this action.
DELETE /api/sandboxes/{id}
Lifecycle Management¶
Suspend Sandbox¶
Temporarily disable a sandbox (can be reactivated later).
POST /api/sandboxes/{id}/suspend
Activate Sandbox¶
Re-enable a suspended sandbox.
POST /api/sandboxes/{id}/activate
Reset Sandbox Data¶
Clear all data and optionally re-seed with a different template.
POST /api/sandboxes/{id}/reset
Content-Type: application/json
{
"template": "demo_full"
}
Access Management¶
List Users with Access¶
GET /api/sandboxes/{id}/access
Response:
[
{
"userId": 1,
"username": "john.doe",
"accessLevel": "OWNER",
"grantedAt": "2024-01-15T10:30:00"
},
{
"userId": 2,
"username": "jane.smith",
"accessLevel": "USER",
"grantedAt": "2024-01-16T09:00:00"
}
]
Grant Access¶
POST /api/sandboxes/{id}/access
Content-Type: application/json
{
"userId": 2,
"accessLevel": "USER"
}
Revoke Access¶
DELETE /api/sandboxes/{id}/access/{userId}
Name Generation¶
Generate Unique Name¶
Generates a random name in format "adjective-animal" (e.g., "happy-lion").
GET /api/sandboxes/generate-name
Response:
{
"name": "swift-falcon",
"slug": "swift-falcon",
"displayName": "Swift Falcon"
}
Generate Multiple Names¶
GET /api/sandboxes/generate-names?count=5
Response:
[
{ "name": "swift-falcon", "slug": "swift-falcon", "displayName": "Swift Falcon" },
{ "name": "brave-wolf", "slug": "brave-wolf", "displayName": "Brave Wolf" },
{ "name": "quiet-owl", "slug": "quiet-owl", "displayName": "Quiet Owl" },
{ "name": "happy-dolphin", "slug": "happy-dolphin", "displayName": "Happy Dolphin" },
{ "name": "gentle-bear", "slug": "gentle-bear", "displayName": "Gentle Bear" }
]
Check Slug Availability¶
GET /api/sandboxes/check-slug/{slug}
Response:
{
"slug": "happy-lion",
"available": true
}
Templates & Info¶
List Available Templates¶
GET /api/sandboxes/templates
Response:
[
{
"id": "empty",
"name": "Empty",
"description": "Clean slate with no mock data",
"users": 0,
"locations": 0,
"units": 0,
"components": 0
},
{
"id": "demo_light",
"name": "Demo Light",
"description": "Quick demo with 5 users, 2 locations, 10 units, 50 components",
"users": 5,
"locations": 2,
"units": 10,
"components": 50
},
{
"id": "demo_full",
"name": "Demo Full",
"description": "Full demo with 20 users, 5 locations, 50 units, 200 components and history",
"users": 20,
"locations": 5,
"units": 50,
"components": 200
},
{
"id": "training",
"name": "Training",
"description": "Training scenarios with 10 users, 3 locations, 20 units, 80 components",
"users": 10,
"locations": 3,
"units": 20,
"components": 80
}
]
Get Sandbox Statistics¶
GET /api/sandboxes/stats
Required Role: SUPER_ADMIN or ADMIN
Admin API¶
Administrative endpoints for system-wide sandbox management.
Base URL: /api/admin/sandboxes
Required Role: SUPER_ADMIN or ADMIN
List All Sandboxes¶
GET /api/admin/sandboxes
Get System Statistics¶
GET /api/admin/sandboxes/stats
Get Sandbox Settings¶
GET /api/admin/sandboxes/settings
Update Setting¶
PUT /api/admin/sandboxes/settings/{key}
Content-Type: application/json
{
"value": "new_value"
}
Update Maximum Sandboxes Limit¶
PUT /api/admin/sandboxes/settings/max-sandboxes
Content-Type: application/json
{
"max": 50
}
Enable/Disable Sandbox Feature¶
PUT /api/admin/sandboxes/settings/enabled
Content-Type: application/json
{
"enabled": true
}
Mock Data Templates¶
| Template | Description |
|---|---|
empty |
Clean slate with no data |
demo_light |
Quick demo: 5 users, 2 locations, 10 units, 50 components |
demo_full |
Full demo: 20 users, 5 locations, 50 units, 200 components + history |
training |
Training scenarios: 10 users, 3 locations, 20 units, 80 components |
Usage Examples¶
Creating a Demo Sandbox¶
# Generate a unique name
curl -X GET http://localhost:1337/api/sandboxes/generate-name \
-H "Authorization: Bearer $JWT"
# Create the sandbox with demo data
curl -X POST http://localhost:1337/api/sandboxes \
-H "Authorization: Bearer $JWT" \
-H "Content-Type: application/json" \
-d '{
"name": "Swift Falcon",
"slug": "swift-falcon",
"description": "Demo environment for client presentation",
"subdomain": "swift-falcon",
"mockDataTemplate": "demo_full"
}'
Inviting a User to a Sandbox¶
# Grant user access
curl -X POST http://localhost:1337/api/sandboxes/1/access \
-H "Authorization: Bearer $JWT" \
-H "Content-Type: application/json" \
-d '{
"userId": 5,
"accessLevel": "USER"
}'
Resetting a Training Sandbox¶
# Reset with training template
curl -X POST http://localhost:1337/api/sandboxes/1/reset \
-H "Authorization: Bearer $JWT" \
-H "Content-Type: application/json" \
-d '{
"template": "training"
}'
Architecture¶
Schema Isolation¶
Each sandbox creates an isolated PostgreSQL schema:
sandbox_happy_lion/
├── users
├── locations
├── units
├── components
├── inspections
├── interventions
└── ... (all TGM tables)
The schema name is derived from the slug: sandbox_{slug} (with hyphens converted to underscores).
URL Patterns¶
Sandboxes can be accessed via:
- Subdomain:
https://{subdomain}.tgm.ensolutions.ca - Custom Domain:
https://{custom-domain}
Multi-Tenancy¶
The system uses PostgreSQL's search_path to route queries to the correct schema based on:
- Subdomain detection in requests
- JWT token with sandbox context
- API header X-Sandbox-Slug
Best Practices¶
-
Use meaningful names - Choose names that identify the purpose (e.g., "client-demo-q4", "training-team-b")
-
Select appropriate templates - Start with
demo_lightfor quick demos,demo_fullfor comprehensive testing -
Manage access carefully - Grant minimum required access level to users
-
Clean up unused sandboxes - Terminate sandboxes that are no longer needed
-
Reset before demos - Reset sandbox data before important presentations
Error Codes¶
| Error | Status | Description |
|---|---|---|
| Sandbox limit reached | 400 | User has reached maximum allowed sandboxes |
| Slug already taken | 409 | The requested slug is already in use |
| Access denied | 403 | User doesn't have permission for this action |
| Sandbox not found | 404 | The specified sandbox doesn't exist |
| Invalid template | 400 | The specified mock data template is not valid |