Set up and configure the PostgreSQL database schema with Supabase migrations
8Space uses PostgreSQL via Supabase with a comprehensive schema for multi-tenant project management, including projects, tasks, workflows, and team collaboration features.
create table public.tenants ( id uuid primary key default gen_random_uuid(), name text not null check (char_length(name) between 1 and 120), slug text not null unique check (slug ~ '^[a-z0-9]+(?:-[a-z0-9]+)*$'), created_by uuid not null references public.profiles (id) on delete restrict, created_at timestamptz not null default now(), archived_at timestamptz);
Each tenant has a unique slug used for URL routing: /app/t/{tenant-slug}
create table public.projects ( id uuid primary key default gen_random_uuid(), tenant_id uuid not null references public.tenants (id) on delete cascade, name text not null check (char_length(name) between 1 and 120), description text, created_by uuid not null references public.profiles (id) on delete restrict, created_at timestamptz not null default now(), archived_at timestamptz);
create table public.workflow_columns ( id uuid primary key default gen_random_uuid(), project_id uuid not null references public.projects (id) on delete cascade, name text not null check (char_length(name) between 1 and 80), kind public.workflow_column_kind not null default 'custom', position integer not null, wip_limit integer, definition_of_done text, created_at timestamptz not null default now(), updated_at timestamptz not null default now());
create type public.project_role as enum ('owner', 'editor', 'viewer');create type public.tenant_role as enum ('owner', 'admin', 'member');create type public.task_priority as enum ('p0', 'p1', 'p2');create type public.workflow_column_kind as enum ( 'backlog', 'todo', 'in_progress', 'done', 'custom');create type public.dependency_type as enum ('FS');
All tables have RLS enabled with policies based on tenant and project membership:
-- Example: Projects table policiescreate policy "projects_select_members"on public.projects for select to authenticatedusing (public.is_project_member(id));create policy "projects_insert_owner"on public.projects for insert to authenticatedwith check ( created_by = auth.uid() and public.is_tenant_member(tenant_id));create policy "projects_update_owner"on public.projects for update to authenticatedusing (public.is_project_owner(id));
RLS ensures users can only access data within their tenants and projects, with appropriate permissions.
-- Task queriescreate index tasks_project_column_rank_idx on public.tasks (project_id, status_column_id, order_rank);create index tasks_project_due_date_idx on public.tasks (project_id, due_date);-- Lookupscreate index task_assignees_user_idx on public.task_assignees (user_id);create index project_members_user_idx on public.project_members (user_id);create index tenant_members_user_idx on public.tenant_members (user_id);