Skip to content

Seed Data Specification

Purpose

Define the minimum bootstrap data required for a greenfield launch of db_schema_v1.sql. This is static reference data — SKU catalog, policy definitions, global policy values, the default pricing plan, and role baseline metadata.

The seed is idempotent. Running it multiple times on the same database is safe.

How to Run

# Apply schema first, then seed:
scripts/db-init.sh && psql $DATABASE_URL -f scripts/seed.sql

Or via the Makefile target:

make db-init && make seed


What Gets Seeded

1. SKU Catalog (sku_catalog)

GPU model definitions used as the reference for node assignments, marketplace display, and billing rate lookup.

SKU Vendor Display Name GPUs Rate (USD/GPU/hr)
mi300x AMD AMD MI300X 8 4.00
h200 NVIDIA NVIDIA H200 8 4.00
h100 NVIDIA NVIDIA H100 8 2.00
mi210x AMD AMD MI210X 8 2.00
cs-3 Cerebras Cerebras CS-3 1 5.00
cs-4 Cerebras Cerebras CS-4 1 5.00

Billing calculation: total_cost = gpus_total_snapshot × gpu_hourly_price_minor × hours.

Slice SKU resource profiles:

h200-sxm-slice stores mutable lab/runtime shape choices in sku_catalog.resource_profile until they stabilize into a first-class table. The current seed includes named slice_vm_profiles and a default_slice_vm_profile rather than a hidden CPU/memory constant:

Profile GPU count vCPU Memory
h200_1g_12c_64g 1 12 64 GiB
h200_1g_24c_64g 1 24 64 GiB
h200_2g_48c_128g 2 48 128 GiB
h200_4g_96c_256g 4 96 256 GiB
h200_8g_192c_512g 8 192 512 GiB

The default is h200_1g_24c_64g, matching the latest tested prototype. Future implementation must snapshot the selected profile name and resolved CPU/memory values onto the allocation placement so later seed updates do not change running allocations.

2. Policy Definitions (policy_definitions)

Defines every valid policy key with its type, description, and allowed bounds. Must be present before any policy_values row can be inserted (FK constraint).

Policy Key Type Default Bounds Purpose
billing.low_balance_threshold_minor integer 500 min 1, max 100000 Cents below which billing.low_balance_warning is emitted
billing.window_seconds integer 60 min 30, max 3600 Billing accrual interval
billing.minimum_deposit_minor integer 1000 min 100, max 1000000 Minimum Stripe checkout amount (cents)
billing.maximum_deposit_minor integer 100000 min 1000, max 10000000 Maximum Stripe checkout amount (cents)
allocation.max_concurrent_per_user integer 50 min 1, max 100 Max active allocations per user
allocation.refund_window_days integer 30 min 0, max 365 Days after credit posting for refund eligibility
rate_limit.api_requests_per_minute integer 120 min 1, max 10000 API rate limit per authenticated user
rate_limit.platform_proxy_requests_per_minute integer 1200 min 1, max 10000 Browser-facing platform proxy traffic rate limit per authenticated user
rate_limit.terminal_token_requests_per_minute integer 10 min 1, max 1000 Terminal token minting rate limit
rate_limit.financial_requests_per_minute integer 30 min 1, max 1000 Financial endpoint rate limit
rate_limit.admin_overview_requests_per_minute integer 600 min 1, max 5000 Admin overview polling rate limit
terminal.session_max_ttl_seconds integer 14400 min 300, max 86400 Maximum lifetime of an active terminal session (independent of token TTL)
auth.service_account_token_ttl_seconds integer 900 min 60, max 3600 Service-account access token lifetime in seconds
notification.low_balance_enabled boolean true Enable low-balance warning notifications
notification.balance_depleted_enabled boolean true Enable balance-depleted notifications
allocation.isolation_model string user-revoke user-revoke, full-reimage Node isolation strategy between allocations: user-revoke revokes the OS user and SSH key (fast, ~10 s); full-reimage triggers a MAAS re-deploy (full OS wipe, ~5–15 min). Requires maas.enabled=true for full-reimage.
maas.enabled boolean false Enable Canonical MAAS bare-metal integration. When true, the provisioning worker uses packages/services/maas.MAASClient for machine deploy/release; cloud-init userdata is delivered via the MAAS deploy API.

Rate-limit strategy: - rate_limit.api_requests_per_minute is the global default. - Middleware resolves route-class overrides (platform_proxy, terminal_token, financial, admin_overview) and falls back to global default.

3. Global Policy Values (policy_values)

One scope_type = 'global' row per policy key, setting the system-wide default. Per-org or per-user overrides can be added via the Admin API post-launch without touching the seed.

The global values match the default_value column in policy_definitions. They are inserted conditionally — if a global value already exists for a key the row is skipped (idempotent by design).

4. Default Pricing Plan (pricing_plans)

A single standard pay-as-you-go plan is seeded with a stable UUID so it can be referenced safely in subsequent scripts. New plans can be added via the Admin API.

Seed UUID: 10000000-0000-4000-8000-000000000001

5. Dev User Tenant/Project Bootstrap (conditional)

For each existing user row, seed ensures: - a personal tenant exists, - a default project exists, - active tenant/project membership rows exist.

This is idempotent and only normalizes already-existing users; it does not create new users.

6. Platform Role Baseline

Seed inserts built-in platform role definitions and v1 role versions: - platform_superadmin - platform_ops - platform_user

For existing users with users.role='admin', seed inserts active platform_role_bindings to platform_superadmin. This preserves admin reachability when PLATFORM_ROLE_SOURCE=bindings is enabled.

7. App Catalog Baseline

Seed inserts the baseline app catalog plus one active version for each seeded app.

Current seeded catalog entries: - ollama -> runtime backend bare_metal - meta-llama-3-8b -> runtime backend bare_metal - mlflow -> runtime backend bare_metal - open-webui -> runtime backend bare_metal - nginx -> runtime backend bare_metal - postgresql -> runtime backend bare_metal - slurm-reference -> runtime backend slurm - rke2-self-managed -> runtime backend rke2

The rke2-self-managed entry is the first-slice self-managed Kubernetes validation offering. It is intentionally narrow and is not the managed-Kubernetes product contract.


What Does NOT Get Seeded

Data Reason
Users No user data in seed — including no admin user (see Admin Bootstrap below)
User SSH public keys (user_ssh_public_keys) User-provided runtime credentials; never seeded
User POSIX identities (user_posix_identities) Created lazily on first provisioning request per user; not seeded
Nodes Nodes are registered post-launch via POST /api/v1/admin/nodes
Organizations / Projects Not pre-created globally; created on demand and conditionally bootstrapped for existing users
Ledger entries / usage records Transactional data — never seeded
Stripe events Live data — never seeded
Audit logs Immutable live data — never seeded

Admin Bootstrap Procedure

The first admin account is not created in the seed SQL — admin credentials in SQL files are a security risk.

Development (local)

The Keycloak dev realm includes a dev-admin user (admin123) with the admin realm role. On first OIDC login via the app, the auth service creates the user record in users with role = 'admin' (mapped from Keycloak's realm_access.roles claim).

No manual DB intervention required for local dev.

Local reset convenience: - make db-reset-fast and make dev-reset-full-web run scripts/seed-local-dev-identities.sh after schema + seed. - This script bootstraps local-only identities aligned to current Keycloak sub claims for the V3 persona set: dev-user, dev-project-admin, dev-tenant-admin, dev-platform-admin, and dev-ops. - The legacy dev-admin smoke account remains available for scripts and broad admin testing. - scripts/seed.sql still does not seed users.

API-backed local bootstrap helpers

Use SQL seed for foundational reference data only. Use API-backed helpers for runtime/product-managed objects once the owning domain API exists, so local and kind setup exercises the same validation, idempotency, audit, and authz paths as real operators.

Current classification:

Bootstrap data Owner Mechanism
Policy definitions/values Platform policy scripts/seed.sql
Static catalog baselines Inventory/app platform scripts/seed.sql until CRUD ownership is complete
Local identity subject alignment Auth/dev harness scripts/seed-local-dev-identities.sh because it must align Keycloak sub claims with DB users
MAAS local site/profile Provisioning/MAAS make seed-local-maas through admin APIs
Persona platform roles IAM/platform roles make seed-local-platform-roles-api through admin APIs

make seed-local-platform-roles-api binds dev-admin, dev-platform-admin, and dev-ops through POST /api/v1/admin/users/{user_id}/platform-roles and verifies the result through GET /api/v1/admin/users/{user_id}/platform-roles. Run it after the API is up. It is intentionally separate from db-reset-fast, because db-reset-fast must remain usable before API containers are started.

Production

  1. Create the first admin account in Keycloak admin console (http://<keycloak>/admin).
  2. Assign the admin realm role.
  3. Log in via the app OIDC flow — the user record is created automatically with role = admin.
  4. All subsequent admin operations are available via POST /api/v1/admin/* endpoints.

If OIDC is not yet configured, use the POST /api/v1/auth/personal/login endpoint (requires password_hash set directly in the DB via a one-time bootstrap script — not the seed — and must be removed after OIDC is operational).


Idempotency Guarantee

All inserts in seed.sql use either: - ON CONFLICT (pk) DO NOTHING for tables with stable primary keys - A WHERE NOT EXISTS guard for policy_values (global scope uniqueness is enforced by a partial unique index, not the PK)

Running the seed after a partial failure or re-deployment is safe.

SSH Key Selection Policy (runtime, not seed)

  • Users upload keys via POST /api/v1/ssh-keys.
  • Exactly one active key per user may be marked default (is_default = true).
  • New allocations use the user's default active key unless the request sets ssh_key_ids.
  • PUT /api/v1/allocations/{allocation_id}/ssh-keys supports per-allocation multi-key override and rotation.