CREATE EXTENSION IF NOT EXISTS vector; CREATE TABLE IF NOT EXISTS documents ( id BIGSERIAL PRIMARY KEY, source_type TEXT NOT NULL, source_ref TEXT NOT NULL, source_url TEXT, title TEXT, content_hash TEXT NOT NULL UNIQUE, mime_type TEXT, file_type TEXT, extracted_text TEXT NOT NULL, metadata JSONB NOT NULL DEFAULT '{}'::jsonb, status TEXT NOT NULL DEFAULT 'ready', created_at TIMESTAMPTZ NOT NULL DEFAULT NOW(), updated_at TIMESTAMPTZ NOT NULL DEFAULT NOW() ); CREATE TABLE IF NOT EXISTS document_chunks ( id BIGSERIAL PRIMARY KEY, document_id BIGINT NOT NULL REFERENCES documents(id) ON DELETE CASCADE, chunk_index INTEGER NOT NULL, content TEXT NOT NULL, token_estimate INTEGER NOT NULL DEFAULT 0, metadata JSONB NOT NULL DEFAULT '{}'::jsonb, embedding VECTOR(768) NOT NULL, created_at TIMESTAMPTZ NOT NULL DEFAULT NOW(), UNIQUE (document_id, chunk_index) ); CREATE INDEX IF NOT EXISTS idx_documents_source_ref ON documents (source_ref); CREATE INDEX IF NOT EXISTS idx_documents_source_url ON documents (source_url); CREATE INDEX IF NOT EXISTS idx_document_chunks_document_id ON document_chunks (document_id); CREATE INDEX IF NOT EXISTS idx_document_chunks_embedding ON document_chunks USING ivfflat (embedding vector_cosine_ops) WITH (lists = 100); CREATE TABLE IF NOT EXISTS scheduled_jobs ( id BIGSERIAL PRIMARY KEY, job_type TEXT NOT NULL, cron_expression TEXT NOT NULL, payload JSONB NOT NULL DEFAULT '{}'::jsonb, enabled BOOLEAN NOT NULL DEFAULT TRUE, created_at TIMESTAMPTZ NOT NULL DEFAULT NOW(), updated_at TIMESTAMPTZ NOT NULL DEFAULT NOW() ); CREATE INDEX IF NOT EXISTS idx_scheduled_jobs_enabled ON scheduled_jobs (enabled);