Reference

Database schema

OpsDash uses Supabase (PostgreSQL 15). All tables have Row-Level Security enabled. The schema is managed by 57 additive migrations in supabase/migrations/ — migrations are never breaking.

Key convention: All domain tables include org_id uuid NOT NULL REFERENCES organizations(id) ON DELETE CASCADE and an RLS policy checking is_org_member(org_id).

organizations

Workspaces — the root of all data scoping.

ColumnTypeNotes
iduuid PKgen_random_uuid()
nametextDisplay name
slugtext UNIQUEURL identifier — /org/[slug]/
typetext'personal' | 'team'
billing_owner_user_iduuid FK → usersBilling anchor for team orgs
onboarding_completedbooleanFalse until setup wizard completes
settingsjsonbOrg-level preferences
deleted_attimestamptzSoft-delete timestamp; NULL = active
created_attimestamptzRow creation timestamp

users

Public profile for auth.users. Created by handle_new_user() trigger.

ColumnTypeNotes
iduuid PK FK → auth.usersSame UUID as Supabase auth
full_nametextDisplay name
avatar_urltextProfile image URL
current_org_iduuid FK → organizationsLast active org — used for login redirect
preferencesjsonbNotification, theme preferences
created_attimestamptz

org_members

Join table for users ↔ organizations with role.

ColumnTypeNotes
iduuid PK
user_iduuid FK → users
org_iduuid FK → organizations
roleorg_role ENUM'owner' | 'admin' | 'member' | 'viewer'
created_attimestamptz

subscriptions

One row per org. Plan drives feature access.

ColumnTypeNotes
iduuid PK
org_iduuid FK → organizationsOne subscription per org
plansubscription_plan ENUM'free' | 'pro' | 'enterprise'
statussubscription_status ENUM'active' | 'trialing' | 'past_due' | 'canceled'
stripe_subscription_idtextStripe subscription reference
stripe_customer_idtextStripe customer reference
current_period_endtimestamptzWhen current billing period ends

feature_flags

Per-org feature toggles with role restrictions.

ColumnTypeNotes
iduuid PK
org_iduuid FK → organizations
feature_keytexte.g. 'crm:contacts', 'projects:milestones'
enabledbooleanFeature on/off for this org
allowed_rolestext[]NULL = all roles; array = restrict to listed roles
created_attimestamptz

contacts

CRM contacts — people the agency works with.

ColumnTypeNotes
iduuid PK
org_iduuid FK → organizationsRLS scope
full_nametext
emailtext
phonetext
company_iduuid FK → companiesOptional link
lead_sourcetext
tagstext[]Max 30 per contact — enforced by trigger
assigned_touuid FK → users
metadatajsonbCustom field values
deleted_attimestamptzSoft-delete
created_attimestamptz

deals

Sales pipeline deals.

ColumnTypeNotes
iduuid PK
org_iduuid FK → organizations
titletext
valuenumericDeal value in org currency
probabilityinteger0–100
stage_iduuid FK → deal_stages
contact_iduuid FK → contacts
company_iduuid FK → companies
expected_close_datedate
statustext'open' | 'won' | 'lost'
metadatajsonbCustom field values
deleted_attimestamptz

projects

Delivery projects — linked to deals.

ColumnTypeNotes
iduuid PK
org_iduuid FK → organizations
nametext
statustext'planning' | 'active' | 'on_hold' | 'completed'
deal_iduuid FK → dealsOptional — links delivery to sale
budgetnumericProject budget
start_datedate
end_datedate
clienttextClient name (denormalized for display)
metadatajsonbCustom field values
deleted_attimestamptz

tasks

Atomic units of work within projects.

ColumnTypeNotes
iduuid PK
project_iduuid FK → projects
org_iduuid FK → organizations
titletext
statustext'todo' | 'in_progress' | 'in_review' | 'done'
prioritytext'low' | 'medium' | 'high' | 'urgent'
assignee_iduuid FK → users
due_datedate
story_pointsintegerEstimation (Pro)
parent_task_iduuid FK → tasksFor subtasks (Pro)
deal_iduuid FK → dealsOptional deal link
deleted_attimestamptzSoft-delete

task_time_entries

Time logged against tasks — drives profitability calculation.

ColumnTypeNotes
iduuid PK
task_iduuid FK → tasks
user_iduuid FK → users
org_iduuid FK → organizations
duration_minutesinteger
descriptiontext
logged_atdate

audit_logs

Immutable log of every mutation.

ColumnTypeNotes
iduuid PK
org_iduuid FK → organizations
user_iduuid FK → users
actiontexte.g. contact.created, deal.updated
metadatajsonbEntity IDs and field values
created_attimestamptz