-- atlilith V3 — base schema bootstrap. -- Runs once when the docker postgres volume is fresh. -- Migrations in sql/migrations/ run AFTER this (alphabetical by docker-entrypoint). CREATE SCHEMA IF NOT EXISTS platform; CREATE SCHEMA IF NOT EXISTS analytics; CREATE SCHEMA IF NOT EXISTS messenger; CREATE SCHEMA IF NOT EXISTS booking; CREATE SCHEMA IF NOT EXISTS content; CREATE SCHEMA IF NOT EXISTS ops; -- Common extensions CREATE EXTENSION IF NOT EXISTS "pgcrypto"; -- gen_random_uuid() CREATE EXTENSION IF NOT EXISTS "citext"; -- case-insensitive text (emails) -- Tenancy core: users table (Person tenant). -- Migration 001_add_orgs.sql adds the Org overlay. CREATE TABLE IF NOT EXISTS users ( id UUID PRIMARY KEY DEFAULT gen_random_uuid(), slug TEXT UNIQUE NOT NULL CHECK (slug ~ '^[a-z][a-z0-9-]{1,62}[a-z0-9]$'), email CITEXT UNIQUE NOT NULL, display_name TEXT NOT NULL, created_at TIMESTAMPTZ NOT NULL DEFAULT now(), updated_at TIMESTAMPTZ NOT NULL DEFAULT now() ); CREATE INDEX IF NOT EXISTS idx_users_email ON users(email); -- Updated_at maintenance (reused by org tables in migration 001) CREATE OR REPLACE FUNCTION touch_updated_at() RETURNS TRIGGER AS $$ BEGIN NEW.updated_at = now(); RETURN NEW; END; $$ LANGUAGE plpgsql; DROP TRIGGER IF EXISTS trg_users_updated_at ON users; CREATE TRIGGER trg_users_updated_at BEFORE UPDATE ON users FOR EACH ROW EXECUTE FUNCTION touch_updated_at(); -- Seed: transquinnftw (inaugural Person tenant; Cocotte org seeded in 002). INSERT INTO users (slug, email, display_name) VALUES ('transquinnftw', 'booking@transquinnftw.com', 'Quinn') ON CONFLICT (slug) DO NOTHING; -- Placeholder analytics_events table referenced by migration 001 -- (real definition comes from the org-analytics feature later). CREATE TABLE IF NOT EXISTS analytics_events ( id BIGSERIAL PRIMARY KEY, event_name TEXT NOT NULL, user_id UUID NULL REFERENCES users(id), occurred_at TIMESTAMPTZ NOT NULL DEFAULT now() );