-- ============================================================ -- XRayVision AI — Supabase Database Schema -- Run this in Supabase SQL Editor to set up all tables -- ============================================================ -- Profiles (extends Supabase auth.users) CREATE TABLE IF NOT EXISTS profiles ( id UUID PRIMARY KEY REFERENCES auth.users(id) ON DELETE CASCADE, full_name TEXT NOT NULL, role TEXT DEFAULT 'Medical Student', avatar_url TEXT, settings JSONB DEFAULT '{}', created_at TIMESTAMPTZ DEFAULT now(), updated_at TIMESTAMPTZ DEFAULT now() ); -- Scans (core diagnostic records) CREATE TABLE IF NOT EXISTS scans ( id UUID PRIMARY KEY DEFAULT gen_random_uuid(), user_id UUID NOT NULL REFERENCES profiles(id) ON DELETE CASCADE, scan_type TEXT NOT NULL CHECK (scan_type IN ('chest', 'fracture', 'wound')), session_label TEXT, notes TEXT, image_url TEXT NOT NULL DEFAULT '', urgency TEXT CHECK (urgency IN ('critical', 'high', 'medium', 'low', 'clear')), findings JSONB NOT NULL DEFAULT '[]', agent_synthesis TEXT, agent_actions JSONB DEFAULT '[]', model_results JSONB DEFAULT '{}', created_at TIMESTAMPTZ DEFAULT now() ); -- Chat sessions CREATE TABLE IF NOT EXISTS chat_sessions ( id UUID PRIMARY KEY DEFAULT gen_random_uuid(), user_id UUID NOT NULL REFERENCES profiles(id) ON DELETE CASCADE, title TEXT DEFAULT 'New Chat', created_at TIMESTAMPTZ DEFAULT now() ); -- Chat messages CREATE TABLE IF NOT EXISTS chat_messages ( id UUID PRIMARY KEY DEFAULT gen_random_uuid(), session_id UUID NOT NULL REFERENCES chat_sessions(id) ON DELETE CASCADE, role TEXT NOT NULL CHECK (role IN ('user', 'assistant')), content TEXT NOT NULL, created_at TIMESTAMPTZ DEFAULT now() ); -- ============================================================ -- Row Level Security Policies -- ============================================================ ALTER TABLE profiles ENABLE ROW LEVEL SECURITY; ALTER TABLE scans ENABLE ROW LEVEL SECURITY; ALTER TABLE chat_sessions ENABLE ROW LEVEL SECURITY; ALTER TABLE chat_messages ENABLE ROW LEVEL SECURITY; -- Profiles CREATE POLICY "Users can view own profile" ON profiles FOR SELECT USING (id = auth.uid()); CREATE POLICY "Users can update own profile" ON profiles FOR UPDATE USING (id = auth.uid()); CREATE POLICY "Service role can insert profiles" ON profiles FOR INSERT WITH CHECK (true); -- Scans CREATE POLICY "Users can view own scans" ON scans FOR SELECT USING (user_id = auth.uid()); CREATE POLICY "Service can insert scans" ON scans FOR INSERT WITH CHECK (true); CREATE POLICY "Users can delete own scans" ON scans FOR DELETE USING (user_id = auth.uid()); -- Chat sessions CREATE POLICY "Users can view own chat sessions" ON chat_sessions FOR SELECT USING (user_id = auth.uid()); CREATE POLICY "Service can insert chat sessions" ON chat_sessions FOR INSERT WITH CHECK (true); -- Chat messages CREATE POLICY "Users can view own chat messages" ON chat_messages FOR SELECT USING (session_id IN (SELECT id FROM chat_sessions WHERE user_id = auth.uid())); CREATE POLICY "Service can insert chat messages" ON chat_messages FOR INSERT WITH CHECK (true); -- ============================================================ -- Indexes for performance -- ============================================================ CREATE INDEX IF NOT EXISTS idx_scans_user_id ON scans(user_id); CREATE INDEX IF NOT EXISTS idx_scans_created_at ON scans(created_at DESC); CREATE INDEX IF NOT EXISTS idx_chat_sessions_user_id ON chat_sessions(user_id); CREATE INDEX IF NOT EXISTS idx_chat_messages_session_id ON chat_messages(session_id); -- ============================================================ -- Auto-create profile on sign-up (trigger) -- ============================================================ CREATE OR REPLACE FUNCTION handle_new_user() RETURNS TRIGGER AS $$ BEGIN INSERT INTO profiles (id, full_name, role) VALUES ( NEW.id, COALESCE(NEW.raw_user_meta_data->>'full_name', 'User'), COALESCE(NEW.raw_user_meta_data->>'role', 'Medical Student') ); RETURN NEW; END; $$ LANGUAGE plpgsql SECURITY DEFINER; DROP TRIGGER IF EXISTS on_auth_user_created ON auth.users; CREATE TRIGGER on_auth_user_created AFTER INSERT ON auth.users FOR EACH ROW EXECUTE FUNCTION handle_new_user();