Spaces:
Running
Running
File size: 4,317 Bytes
ce4fddb | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 | -- ============================================================
-- 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();
|