-- dialog plugin schema — forums / threads / comments (+ comment_stats view). -- -- Captured 2026-06-29 from the live openbureau dev DB (CT 134 → openbureau-db, -- supabase/postgres 15.8) via `pg_dump --schema-only --no-owner --no-privileges` -- of public.{forums,threads,comments,comment_stats}. Made idempotent (IF NOT -- EXISTS / OR REPLACE / constraint guards) so it is a no-op against the existing -- openbureau DB and safe to apply to a fresh instance. -- -- Notes: -- * gen_random_uuid() is built into Postgres 13+ — no pgcrypto extension needed. -- * RLS is enabled with NO policies: every read/write is mediated by the CMS -- using the Supabase service_role key (which bypasses RLS). The dialog plugin -- therefore only makes sense with `auth: supabase`; kgva (local auth) omits it. -- * `posts` exists in the live DB but the dialog code never touches it — NOT a -- dialog table, intentionally excluded. -- ── tables ────────────────────────────────────────────────────────────────── CREATE TABLE IF NOT EXISTS public.forums ( id uuid DEFAULT gen_random_uuid() NOT NULL, slug text NOT NULL, name text NOT NULL, description text DEFAULT ''::text, color text, sort integer DEFAULT 0 NOT NULL, kind text DEFAULT 'forum'::text NOT NULL, created_at timestamp with time zone DEFAULT now() NOT NULL ); CREATE TABLE IF NOT EXISTS public.threads ( id uuid DEFAULT gen_random_uuid() NOT NULL, forum_id uuid, key text NOT NULL, title text NOT NULL, url text, kind text DEFAULT 'forum'::text NOT NULL, author_name text, user_id uuid, locked boolean DEFAULT false NOT NULL, deleted boolean DEFAULT false NOT NULL, created_at timestamp with time zone DEFAULT now() NOT NULL ); CREATE TABLE IF NOT EXISTS public.comments ( id uuid DEFAULT gen_random_uuid() NOT NULL, thread text NOT NULL, parent_id uuid, user_id uuid, author_name text, author_avatar text, body text NOT NULL, created_at timestamp with time zone DEFAULT now() NOT NULL, deleted boolean DEFAULT false NOT NULL, author_role text ); -- ── constraints (guarded — Postgres has no ADD CONSTRAINT IF NOT EXISTS) ────── DO $$ BEGIN IF NOT EXISTS (SELECT 1 FROM pg_constraint WHERE conname = 'forums_pkey') THEN ALTER TABLE ONLY public.forums ADD CONSTRAINT forums_pkey PRIMARY KEY (id); END IF; IF NOT EXISTS (SELECT 1 FROM pg_constraint WHERE conname = 'forums_slug_key') THEN ALTER TABLE ONLY public.forums ADD CONSTRAINT forums_slug_key UNIQUE (slug); END IF; IF NOT EXISTS (SELECT 1 FROM pg_constraint WHERE conname = 'threads_pkey') THEN ALTER TABLE ONLY public.threads ADD CONSTRAINT threads_pkey PRIMARY KEY (id); END IF; IF NOT EXISTS (SELECT 1 FROM pg_constraint WHERE conname = 'threads_key_key') THEN ALTER TABLE ONLY public.threads ADD CONSTRAINT threads_key_key UNIQUE (key); END IF; IF NOT EXISTS (SELECT 1 FROM pg_constraint WHERE conname = 'comments_pkey') THEN ALTER TABLE ONLY public.comments ADD CONSTRAINT comments_pkey PRIMARY KEY (id); END IF; IF NOT EXISTS (SELECT 1 FROM pg_constraint WHERE conname = 'threads_forum_id_fkey') THEN ALTER TABLE ONLY public.threads ADD CONSTRAINT threads_forum_id_fkey FOREIGN KEY (forum_id) REFERENCES public.forums(id) ON DELETE CASCADE; END IF; IF NOT EXISTS (SELECT 1 FROM pg_constraint WHERE conname = 'comments_parent_id_fkey') THEN ALTER TABLE ONLY public.comments ADD CONSTRAINT comments_parent_id_fkey FOREIGN KEY (parent_id) REFERENCES public.comments(id) ON DELETE CASCADE; END IF; END $$; -- ── indexes ─────────────────────────────────────────────────────────────────── CREATE INDEX IF NOT EXISTS threads_forum_idx ON public.threads USING btree (forum_id); CREATE INDEX IF NOT EXISTS comments_thread_idx ON public.comments USING btree (thread, created_at); -- ── view: per-thread comment counts (used by dialog-store) ──────────────────── CREATE OR REPLACE VIEW public.comment_stats AS SELECT comments.thread, (count(*))::integer AS count, max(comments.created_at) AS last FROM public.comments WHERE (NOT comments.deleted) GROUP BY comments.thread; -- ── row-level security (enabled, no policies — service_role-mediated) ───────── ALTER TABLE public.forums ENABLE ROW LEVEL SECURITY; ALTER TABLE public.threads ENABLE ROW LEVEL SECURITY; ALTER TABLE public.comments ENABLE ROW LEVEL SECURITY;