Database Schema
PostgreSQL on Supabase. All tables use UUID primary keys with gen_random_uuid(). Row Level Security (RLS) is enabled on all tables. Timestamps are timestamptz defaulting to now().
Current schema version: migration 059.
teams
Organizations/workspaces. Auto-created on user signup via handle_new_user() trigger.
| Column | Type | Nullable | Default | Description |
|---|---|---|---|---|
id | uuid | No | gen_random_uuid() | Primary key |
name | text | No | — | Team name |
suspended_at | timestamptz | Yes | NULL | When set, team is suspended (read-only) |
created_at | timestamptz | Yes | now() | Creation timestamp |
updated_at | timestamptz | Yes | now() | Last update (auto-trigger) |
RLS policies:
- SELECT: Members of the team
- INSERT: Anyone (auto-created on signup)
- UPDATE: Owner or admin members
team_members
Team membership with role-based access.
| Column | Type | Nullable | Default | Description |
|---|---|---|---|---|
team_id | uuid | No | — | FK -> teams.id (CASCADE) |
user_id | uuid | No | — | FK -> auth.users.id (CASCADE) |
role | text | No | 'member' | owner, admin, or member |
created_at | timestamptz | Yes | now() | Join timestamp |
Primary key: (team_id, user_id)
Indexes: team_members_user_id_idx
scripts
Quantum script/template definitions. Both platform-seeded templates and user-uploaded scripts.
| Column | Type | Nullable | Default | Description |
|---|---|---|---|---|
id | uuid | No | gen_random_uuid() | Primary key |
slug | text | No | — | URL-friendly identifier |
name | text | No | — | Display name |
description | text | Yes | — | Description |
category | text | No | — | Category (e.g., Fundamentals, Chemistry) |
qubits | integer | No | 2 | Number of qubits |
file_path | text | No | — | Path to script file (legacy) |
script_content | text | Yes | — | Inline Python source code |
requirements | text | Yes | — | requirements.txt content |
framework | text | Yes | — | qiskit, cirq, pennylane, openqasm, marqov |
script_type | text | Yes | — | workflow or task |
default_parameters | jsonb | Yes | {} | Default execution parameters |
estimated_cost_usd | numeric | Yes | — | Estimated cost |
is_active | boolean | Yes | true | Soft-delete flag |
is_public | boolean | Yes | — | Published status |
user_id | uuid | Yes | — | FK -> auth.users.id (uploader) |
team_id | uuid | Yes | — | FK -> teams.id (NULL = platform template) |
created_at | timestamptz | Yes | now() | — |
updated_at | timestamptz | Yes | now() | Auto-trigger |
Unique constraint: scripts_slug_framework_key (slug, framework) with NULLS NOT DISTINCT
RLS policies:
- SELECT: Active scripts visible to all; users can see own scripts
- INSERT: Users can create their own scripts (
user_id = auth.uid())
job_runs
Quantum job execution records.
| Column | Type | Nullable | Default | Description |
|---|---|---|---|---|
id | uuid | No | gen_random_uuid() | Primary key |
team_id | uuid | No | — | FK -> teams.id (CASCADE) |
user_id | uuid | Yes | — | FK -> auth.users.id (SET NULL) |
script_id | uuid | Yes | — | FK -> scripts.id (SET NULL) |
inline_code | text | Yes | — | Code snapshot from playground |
framework | text | Yes | — | Quantum framework |
status | text | No | 'pending' | pending, queued, running, completed, failed, cancelled |
backend | text | No | 'local' | Backend slug |
parameters | jsonb | Yes | {} | Execution parameters |
execution_mode | text | Yes | 'direct' | direct or temporal |
workflow_id | text | Yes | — | Temporal workflow ID |
temporal_run_id | text | Yes | — | Temporal run ID |
temporal_status | text | Yes | — | Temporal workflow status |
workflow_metadata | jsonb | Yes | — | Task graph, timeline, per-task timing |
braket_task_arns | text[] | Yes | — | AWS Braket task ARNs |
started_at | timestamptz | Yes | — | Execution start time |
completed_at | timestamptz | Yes | — | Completion time |
wall_time_seconds | numeric | Yes | — | Total wall clock time |
quantum_time_seconds | numeric | Yes | — | QPU time only |
estimated_cost_usd | numeric | Yes | — | Estimated cost |
actual_cost_usd | numeric | Yes | — | Actual cost |
error_message | text | Yes | — | Error message (if failed) |
error_details | jsonb | Yes | — | Detailed error info |
create_capsule | boolean | Yes | false | Whether to create a capsule |
capsule_name | text | Yes | — | Capsule name |
created_at | timestamptz | Yes | now() | — |
updated_at | timestamptz | Yes | now() | Auto-trigger |
Constraint: job_runs_has_code: script_id IS NOT NULL OR inline_code IS NOT NULL
Indexes: team_id, user_id, status, workflow_id, created_at DESC
Realtime: Enabled (supabase_realtime)
job_results
Individual result records from job executions.
| Column | Type | Nullable | Default | Description |
|---|---|---|---|---|
id | uuid | No | gen_random_uuid() | Primary key |
job_run_id | uuid | No | — | FK -> job_runs.id (CASCADE) |
result_type | text | No | — | Type of result |
result_data | jsonb | No | — | Result payload |
quantum_time_seconds | numeric | Yes | — | QPU time |
shots | integer | Yes | — | Shots executed |
created_at | timestamptz | Yes | now() | — |
backends
Available quantum backends with pricing and metadata.
| Column | Type | Nullable | Default | Description |
|---|---|---|---|---|
id | uuid | No | gen_random_uuid() | Primary key |
slug | text | No | — | Unique URL-friendly ID (e.g., sv1) |
name | text | No | — | Display name |
provider | text | No | — | Provider (e.g., AWS Braket, IonQ) |
device_type | text | No | — | simulator or qpu |
device_arn | text | No | — | Unique provider device ARN |
provider_target_id | text | Yes | — | Provider-specific target ID |
region | text | Yes | — | AWS region |
qubit_count | integer | Yes | — | Number of qubits |
topology | text | Yes | — | Connectivity (e.g., all-to-all) |
is_available | boolean | Yes | true | Accepting jobs |
status | text | Yes | 'online' | online, offline, maintenance |
pricing | jsonb | Yes | — | { taskFee, perShot, minimumCost } |
max_shots | integer | Yes | 100000 | Maximum shots |
max_qubits | integer | Yes | — | Maximum qubits |
description | text | Yes | — | Description |
documentation_url | text | Yes | — | Provider docs URL |
tags | text[] | Yes | — | Searchable tags |
display_order | integer | Yes | 0 | UI sort order |
is_recommended | boolean | Yes | false | Featured backend |
created_at | timestamptz | Yes | now() | — |
updated_at | timestamptz | Yes | now() | Auto-trigger |
RLS: SELECT only where is_available = true. No public INSERT/UPDATE/DELETE (managed via SQL Editor).
Seeded backends: sv1, dm1, tn1, ionq-aria-1, ionq-aria-2, ionq-forte-1, rigetti-ankaa-2, rigetti-ankaa-3, iqm-garnet, iqm-emerald, quera-aquila.
capsules
Reproducible workflow packages for quantum-classical workflows.
| Column | Type | Nullable | Default | Description |
|---|---|---|---|---|
id | uuid | No | gen_random_uuid() | Primary key |
team_id | uuid | No | — | FK -> teams.id (CASCADE) |
user_id | uuid | Yes | — | FK -> auth.users.id (SET NULL) |
name | text | No | — | Capsule name |
description | text | Yes | — | Description |
version | text | No | '1.0.0' | Schema version |
lifecycle_state | text | No | 'draft' | draft, runnable, sealed, archived |
job_id | uuid | Yes | — | FK -> job_runs.id (SET NULL) |
run_id | uuid | No | gen_random_uuid() | Unique run identifier |
git_sha | text | Yes | — | Source commit SHA |
git_repo | text | Yes | — | Source repository URL |
parent_capsule_id | uuid | Yes | — | FK -> capsules.id (SET NULL) |
custom_metadata | jsonb | Yes | {} | Tags, budget, retention, backends |
started_at | timestamptz | Yes | — | Execution start |
completed_at | timestamptz | Yes | — | Execution end |
wall_time_seconds | numeric | Yes | — | Total wall time |
num_tasks | integer | Yes | 0 | Task count |
total_shots | integer | Yes | 0 | Total shots |
max_budget_usd | numeric | Yes | — | Budget cap |
estimated_cost_usd | numeric | Yes | — | Estimated cost |
actual_cost_usd | numeric | Yes | 0 | Actual cost |
cost_breakdown | jsonb | Yes | [] | Per-task cost details |
digests | jsonb | Yes | — | SHA256 hashes for verification |
regulatory_framework | text | Yes | — | e.g., FDA-21CFR11 |
retention_years | integer | Yes | — | Data retention period |
doi | text | Yes | — | Digital Object Identifier |
sealed_at | timestamptz | Yes | — | Seal timestamp |
sealed_by | uuid | Yes | — | FK -> auth.users.id |
created_at | timestamptz | Yes | now() | — |
updated_at | timestamptz | Yes | now() | Auto-trigger |
Lifecycle: draft -> runnable -> sealed -> archived. Sealed capsules are immutable.
Indexes: team_id, user_id, job_id, lifecycle_state, created_at DESC, run_id, full-text search on name + description.
Realtime: Enabled.
capsule_artifacts
File artifacts associated with capsules.
| Column | Type | Nullable | Default | Description |
|---|---|---|---|---|
id | uuid | No | gen_random_uuid() | Primary key |
capsule_id | uuid | No | — | FK -> capsules.id (CASCADE) |
name | text | No | — | Filename (e.g., workflow.json) |
artifact_type | text | No | — | workflow, environment, backends, data, results, provenance, other |
storage_path | text | Yes | — | S3 path |
content_type | text | Yes | — | MIME type |
size_bytes | bigint | Yes | — | File size |
digest | text | Yes | — | SHA256 hash (sha256:HEX) |
content_text | text | Yes | — | Inline content (YAML/JSON) |
content_binary | bytea | Yes | — | Binary content |
created_at | timestamptz | Yes | now() | — |
capsule_task_executions
Individual task executions within a capsule workflow.
| Column | Type | Nullable | Default | Description |
|---|---|---|---|---|
id | uuid | No | gen_random_uuid() | Primary key |
capsule_id | uuid | No | — | FK -> capsules.id (CASCADE) |
task_id | text | No | — | Task identifier |
backend | text | No | — | Backend slug |
start_time | timestamptz | Yes | — | Start time |
end_time | timestamptz | Yes | — | End time |
wall_time_seconds | numeric | Yes | — | Duration |
queue_time_seconds | numeric | Yes | 0 | Queue wait time |
cost_usd | numeric | Yes | 0 | Task cost |
shots | integer | Yes | — | Shots executed |
job_id | text | Yes | — | Backend job ID |
qpu_calibration | jsonb | Yes | — | QPU calibration snapshot |
outputs_digest | text | Yes | — | SHA256 of outputs |
created_at | timestamptz | Yes | now() | — |
team_secrets
Encrypted team-scoped provider credentials.
| Column | Type | Nullable | Default | Description |
|---|---|---|---|---|
id | uuid | No | gen_random_uuid() | Primary key |
team_id | uuid | No | — | FK -> teams.id |
provider | text | No | — | Provider name |
key_name | text | No | — | Secret key name |
encrypted_value | text | No | — | Encrypted secret value |
description | text | Yes | — | Description |
is_active | boolean | Yes | true | Active flag |
validation_status | text | Yes | — | Last validation result |
last_validated_at | timestamptz | Yes | — | Last validation time |
validation_error | text | Yes | — | Validation error message |
last_used_at | timestamptz | Yes | — | Last usage time |
created_at | timestamptz | Yes | now() | — |
updated_at | timestamptz | Yes | now() | — |
Upsert function: upsert_team_secret(p_team_id, p_provider, p_key_name, p_value, p_created_by) — encrypts value server-side.
team_invitations
Pending team invitations.
| Column | Type | Nullable | Default | Description |
|---|---|---|---|---|
id | uuid | No | gen_random_uuid() | Primary key |
team_id | uuid | No | — | FK -> teams.id |
email | text | No | — | Invitee email |
role | text | No | — | admin or member |
token | text | No | — | Secure invitation token (64 hex chars) |
invited_by | uuid | No | — | FK -> auth.users.id |
status | text | No | 'pending' | pending, accepted, expired, revoked |
expires_at | timestamptz | No | — | Expiration (7 days from creation) |
created_at | timestamptz | Yes | now() | — |
simulation_events
Browser simulation telemetry.
| Column | Type | Nullable | Default | Description |
|---|---|---|---|---|
id | uuid | No | gen_random_uuid() | Primary key |
user_id | uuid | No | — | FK -> auth.users.id |
team_id | uuid | No | — | FK -> teams.id |
session_id | text | No | — | Client session ID |
simulator | text | No | — | quantum-circuit or qulacs-wasm |
qasm_input | text | No | — | QASM input |
shots | integer | No | — | Shots executed |
qubit_count | integer | No | — | Number of qubits |
gate_count | integer | No | — | Number of gates |
execution_time_ms | real | No | — | Execution time in ms |
counts | jsonb | No | {} | Measurement counts |
source_framework | text | Yes | — | Source framework |
user_agent | text | Yes | — | Browser user agent |
created_at | timestamptz | No | now() | — |
RLS: Users can INSERT and SELECT their own events. Service role can SELECT all.
benchmark_suites
Benchmark suite definitions (created from migration 010).
| Column | Type | Description |
|---|---|---|
id | uuid | Primary key |
team_id | uuid | FK -> teams.id |
user_id | uuid | FK -> auth.users.id |
name | text | Suite name |
description | text | Description |
status | text | pending, running, completed, failed |
tags | text[] | Searchable tags |
created_at | timestamptz | — |
updated_at | timestamptz | — |
Key Relationships
auth.users
|-- team_members (user_id)
|-- job_runs (user_id)
|-- capsules (user_id, sealed_by)
|-- scripts (user_id)
|-- simulation_events (user_id)
teams
|-- team_members (team_id)
|-- job_runs (team_id)
|-- capsules (team_id)
|-- team_secrets (team_id)
|-- team_invitations (team_id)
|-- webhook_endpoints (team_id)
scripts
|-- job_runs (script_id)
job_runs
|-- job_results (job_run_id)
|-- capsules (job_id)
capsules
|-- capsule_artifacts (capsule_id)
|-- capsule_task_executions (capsule_id)
|-- capsules (parent_capsule_id, self-referential)Migration History (Key Migrations)
| # | File | Description |
|---|---|---|
| 001 | 001_initial_schema.sql | Core tables: teams, team_members, scripts, job_runs, job_results, webhooks, RLS |
| 006 | 006_create_backends_table.sql | Backends table with seeded devices |
| 010 | 010_benchmark_suites.sql | Benchmark suites |
| 012 | 012_capsules.sql | Capsules, artifacts, task executions |
| 014 | 014_invitation_codes.sql | Invitation code system |
| 042 | 042_create_providers_table.sql | Providers table |
| 045 | 045_add_cost_tracking.sql | Cost tracking |
| 047 | 047_team_suspension.sql | Team suspension (suspended_at) |
| 048 | 048_security_hardening_rls.sql | RLS security hardening |
| 050 | 050_simulation_events.sql | Browser simulation telemetry |
| 051 | 051_template_migration_schema.sql | Framework column on scripts, execution_mode on job_runs |
| 054 | 054_inline_code_on_job_runs.sql | Inline code + framework on job_runs |
| 056 | 056_add_marqov_simulator_backend.sql | Marqov branded simulator |
| 058 | 058_add_workflow_metadata_column.sql | Workflow metadata on job_runs |
| 059 | 059_add_quantum_brilliance_backends.sql | Quantum Brilliance backends |