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:

  1. Subdomain: https://{subdomain}.tgm.ensolutions.ca
  2. 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

  1. Use meaningful names - Choose names that identify the purpose (e.g., "client-demo-q4", "training-team-b")

  2. Select appropriate templates - Start with demo_light for quick demos, demo_full for comprehensive testing

  3. Manage access carefully - Grant minimum required access level to users

  4. Clean up unused sandboxes - Terminate sandboxes that are no longer needed

  5. 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