BoxApp uses Supabase migrations to manage database schema changes. All migrations are stored as SQL files in the supabase/migrations/ directory and are version-controlled with the codebase.
Migrations follow a timestamp-based naming convention: YYYYMMDD_description.sql
The most critical migration establishes Row Level Security for multi-tenant data isolation:
20260219_rls_multi_tenant_isolation.sql
-- Helper function to get current user's box_idCREATE OR REPLACE FUNCTION public.current_user_box_id()RETURNS UUID LANGUAGE sql SECURITY DEFINER STABLE AS $$ SELECT box_id FROM public.profiles WHERE id = auth.uid()$$;-- Example: WODs table tenant isolationALTER TABLE public.wods ENABLE ROW LEVEL SECURITY;CREATE POLICY "tenant_isolation_select" ON public.wods FOR SELECT TO authenticated USING (box_id = public.current_user_box_id());CREATE POLICY "tenant_isolation_insert" ON public.wods FOR INSERT TO authenticated WITH CHECK (box_id = public.current_user_box_id());
This migration:
Enables RLS on all tenant-scoped tables
Creates policies to restrict data access by box_id
Ensures users only see data for their gym
Critical for production: The RLS migration prevents data leakage between different gyms (boxes) using the platform. Never disable RLS on production tables.
CREATE TABLE IF NOT EXISTS public.competitions ( id UUID PRIMARY KEY DEFAULT gen_random_uuid(), box_id UUID NOT NULL REFERENCES public.boxes(id) ON DELETE CASCADE, name TEXT NOT NULL, start_date TIMESTAMPTZ NOT NULL, end_date TIMESTAMPTZ NOT NULL, status TEXT DEFAULT 'draft', created_at TIMESTAMPTZ DEFAULT NOW());
CREATE TABLE IF NOT EXISTS public.audit_logs ( id UUID PRIMARY KEY DEFAULT gen_random_uuid(), user_id UUID REFERENCES auth.users(id), action TEXT NOT NULL, table_name TEXT NOT NULL, record_id UUID, timestamp TIMESTAMPTZ DEFAULT NOW());
Always write migrations that can run multiple times safely:
-- ✅ Good: Checks if table existsCREATE TABLE IF NOT EXISTS public.my_table ( id UUID PRIMARY KEY);-- ❌ Bad: Fails if table existsCREATE TABLE public.my_table ( id UUID PRIMARY KEY);
DO $$ BEGIN IF EXISTS ( SELECT 1 FROM information_schema.tables WHERE table_schema='public' AND table_name='wods' ) THEN ALTER TABLE public.wods ENABLE ROW LEVEL SECURITY; RAISE NOTICE 'RLS applied to: wods'; END IF;END $$;