auto-claude: subtask-4-4 - Create chat_sessions and chat_messages tables in Supabase
Create SQL migration for chatbot database tables: - chat_sessions: Stores visitor session data with visitor_id, metadata, timestamps - chat_messages: Stores chat messages with role (user/assistant/system), content - Proper indexes for visitor lookup and message ordering - Row Level Security (RLS) enabled with policies for: - Service role full access (for server-side API) - Visitor-based access via x-visitor-id header (for potential future client-side) - Trigger for automatic updated_at column on chat_sessions Also updated ChatSession interface in chat.ts to include updated_at field. Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
This commit is contained in:
@@ -6,6 +6,7 @@ export type ChatRole = 'user' | 'assistant' | 'system';
|
|||||||
export interface ChatSession {
|
export interface ChatSession {
|
||||||
id: string;
|
id: string;
|
||||||
created_at: string;
|
created_at: string;
|
||||||
|
updated_at: string;
|
||||||
visitor_id: string;
|
visitor_id: string;
|
||||||
metadata: Record<string, unknown>;
|
metadata: Record<string, unknown>;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -0,0 +1,155 @@
|
|||||||
|
-- Chat Tables Migration
|
||||||
|
-- Creates tables for chatbot functionality with visitor sessions and message history
|
||||||
|
-- Version: 001
|
||||||
|
-- Date: 2026-01-25
|
||||||
|
|
||||||
|
-- ============================================================================
|
||||||
|
-- Table: chat_sessions
|
||||||
|
-- Stores chatbot session information for visitors
|
||||||
|
-- ============================================================================
|
||||||
|
CREATE TABLE IF NOT EXISTS chat_sessions (
|
||||||
|
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
|
||||||
|
created_at TIMESTAMP WITH TIME ZONE DEFAULT NOW() NOT NULL,
|
||||||
|
visitor_id TEXT NOT NULL,
|
||||||
|
metadata JSONB DEFAULT '{}'::jsonb,
|
||||||
|
updated_at TIMESTAMP WITH TIME ZONE DEFAULT NOW() NOT NULL
|
||||||
|
);
|
||||||
|
|
||||||
|
-- Index for quick lookup by visitor_id (used for session continuity)
|
||||||
|
CREATE INDEX IF NOT EXISTS idx_chat_sessions_visitor_id ON chat_sessions(visitor_id);
|
||||||
|
|
||||||
|
-- Index for ordering sessions by creation time
|
||||||
|
CREATE INDEX IF NOT EXISTS idx_chat_sessions_created_at ON chat_sessions(created_at DESC);
|
||||||
|
|
||||||
|
-- Comment on table
|
||||||
|
COMMENT ON TABLE chat_sessions IS 'Stores chatbot sessions for website visitors';
|
||||||
|
COMMENT ON COLUMN chat_sessions.visitor_id IS 'Unique identifier for the visitor (generated client-side or from fingerprint)';
|
||||||
|
COMMENT ON COLUMN chat_sessions.metadata IS 'Additional session data (locale, user_agent, referrer, etc.)';
|
||||||
|
|
||||||
|
-- ============================================================================
|
||||||
|
-- Table: chat_messages
|
||||||
|
-- Stores individual chat messages within a session
|
||||||
|
-- ============================================================================
|
||||||
|
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', 'system')),
|
||||||
|
content TEXT NOT NULL,
|
||||||
|
created_at TIMESTAMP WITH TIME ZONE DEFAULT NOW() NOT NULL
|
||||||
|
);
|
||||||
|
|
||||||
|
-- Index for fetching messages by session (primary query pattern)
|
||||||
|
CREATE INDEX IF NOT EXISTS idx_chat_messages_session_id ON chat_messages(session_id);
|
||||||
|
|
||||||
|
-- Composite index for fetching messages in order within a session
|
||||||
|
CREATE INDEX IF NOT EXISTS idx_chat_messages_session_created ON chat_messages(session_id, created_at ASC);
|
||||||
|
|
||||||
|
-- Comment on table
|
||||||
|
COMMENT ON TABLE chat_messages IS 'Stores individual messages in chatbot conversations';
|
||||||
|
COMMENT ON COLUMN chat_messages.role IS 'Message sender role: user, assistant (AI), or system (instructions)';
|
||||||
|
COMMENT ON COLUMN chat_messages.content IS 'The message text content';
|
||||||
|
|
||||||
|
-- ============================================================================
|
||||||
|
-- Updated At Trigger for chat_sessions
|
||||||
|
-- Automatically updates the updated_at column when a session is modified
|
||||||
|
-- ============================================================================
|
||||||
|
CREATE OR REPLACE FUNCTION update_updated_at_column()
|
||||||
|
RETURNS TRIGGER AS $$
|
||||||
|
BEGIN
|
||||||
|
NEW.updated_at = NOW();
|
||||||
|
RETURN NEW;
|
||||||
|
END;
|
||||||
|
$$ LANGUAGE plpgsql;
|
||||||
|
|
||||||
|
CREATE TRIGGER update_chat_sessions_updated_at
|
||||||
|
BEFORE UPDATE ON chat_sessions
|
||||||
|
FOR EACH ROW
|
||||||
|
EXECUTE FUNCTION update_updated_at_column();
|
||||||
|
|
||||||
|
-- ============================================================================
|
||||||
|
-- Row Level Security (RLS)
|
||||||
|
-- Enabled for production security - server uses service role key to bypass
|
||||||
|
-- ============================================================================
|
||||||
|
|
||||||
|
-- Enable RLS on chat_sessions
|
||||||
|
ALTER TABLE chat_sessions ENABLE ROW LEVEL SECURITY;
|
||||||
|
|
||||||
|
-- Enable RLS on chat_messages
|
||||||
|
ALTER TABLE chat_messages ENABLE ROW LEVEL SECURITY;
|
||||||
|
|
||||||
|
-- ============================================================================
|
||||||
|
-- RLS Policies for chat_sessions
|
||||||
|
-- ============================================================================
|
||||||
|
|
||||||
|
-- Policy: Allow service role full access (for server-side API routes)
|
||||||
|
-- Note: Service role key automatically bypasses RLS, but this is explicit
|
||||||
|
CREATE POLICY "Service role has full access to chat_sessions"
|
||||||
|
ON chat_sessions
|
||||||
|
FOR ALL
|
||||||
|
TO service_role
|
||||||
|
USING (true)
|
||||||
|
WITH CHECK (true);
|
||||||
|
|
||||||
|
-- Policy: Allow visitors to read their own sessions (for potential future client-side access)
|
||||||
|
CREATE POLICY "Visitors can read their own sessions"
|
||||||
|
ON chat_sessions
|
||||||
|
FOR SELECT
|
||||||
|
TO anon, authenticated
|
||||||
|
USING (visitor_id = current_setting('request.headers')::json->>'x-visitor-id');
|
||||||
|
|
||||||
|
-- Policy: Allow visitors to create sessions (for potential future client-side access)
|
||||||
|
CREATE POLICY "Visitors can create sessions"
|
||||||
|
ON chat_sessions
|
||||||
|
FOR INSERT
|
||||||
|
TO anon, authenticated
|
||||||
|
WITH CHECK (visitor_id = current_setting('request.headers')::json->>'x-visitor-id');
|
||||||
|
|
||||||
|
-- ============================================================================
|
||||||
|
-- RLS Policies for chat_messages
|
||||||
|
-- ============================================================================
|
||||||
|
|
||||||
|
-- Policy: Allow service role full access (for server-side API routes)
|
||||||
|
CREATE POLICY "Service role has full access to chat_messages"
|
||||||
|
ON chat_messages
|
||||||
|
FOR ALL
|
||||||
|
TO service_role
|
||||||
|
USING (true)
|
||||||
|
WITH CHECK (true);
|
||||||
|
|
||||||
|
-- Policy: Allow visitors to read messages from their sessions
|
||||||
|
CREATE POLICY "Visitors can read messages from their sessions"
|
||||||
|
ON chat_messages
|
||||||
|
FOR SELECT
|
||||||
|
TO anon, authenticated
|
||||||
|
USING (
|
||||||
|
EXISTS (
|
||||||
|
SELECT 1 FROM chat_sessions
|
||||||
|
WHERE chat_sessions.id = chat_messages.session_id
|
||||||
|
AND chat_sessions.visitor_id = current_setting('request.headers')::json->>'x-visitor-id'
|
||||||
|
)
|
||||||
|
);
|
||||||
|
|
||||||
|
-- Policy: Allow visitors to insert messages into their sessions
|
||||||
|
CREATE POLICY "Visitors can insert messages into their sessions"
|
||||||
|
ON chat_messages
|
||||||
|
FOR INSERT
|
||||||
|
TO anon, authenticated
|
||||||
|
WITH CHECK (
|
||||||
|
EXISTS (
|
||||||
|
SELECT 1 FROM chat_sessions
|
||||||
|
WHERE chat_sessions.id = chat_messages.session_id
|
||||||
|
AND chat_sessions.visitor_id = current_setting('request.headers')::json->>'x-visitor-id'
|
||||||
|
)
|
||||||
|
);
|
||||||
|
|
||||||
|
-- ============================================================================
|
||||||
|
-- Grants
|
||||||
|
-- ============================================================================
|
||||||
|
|
||||||
|
-- Grant usage on tables to authenticated and anon roles
|
||||||
|
GRANT SELECT, INSERT ON chat_sessions TO anon, authenticated;
|
||||||
|
GRANT SELECT, INSERT ON chat_messages TO anon, authenticated;
|
||||||
|
|
||||||
|
-- Grant all to service role (for server-side operations)
|
||||||
|
GRANT ALL ON chat_sessions TO service_role;
|
||||||
|
GRANT ALL ON chat_messages TO service_role;
|
||||||
Reference in New Issue
Block a user