Spaces:
Sleeping
Sleeping
| -- Documents table β one row per ingested document (PDF, Confluence page, GitHub file, Jira issue) | |
| create table if not exists documents ( | |
| id uuid primary key default gen_random_uuid(), | |
| doc_id text not null unique, | |
| title text not null, | |
| source_url text not null, | |
| source_type text not null, | |
| team_id text not null, | |
| metadata jsonb not null default '{}', | |
| last_commit_sha text, | |
| created_at timestamptz not null default now(), | |
| updated_at timestamptz not null default now() | |
| ); | |
| create index if not exists documents_team_id_idx on documents (team_id); | |
| create index if not exists documents_source_type_idx on documents (source_type); | |
| create index if not exists documents_team_source_idx on documents (team_id, source_type); | |
| -- Lets the CAG job find repos for a team via metadata->>'repo' without a full scan | |
| create index if not exists documents_metadata_gin_idx on documents using gin (metadata); | |
| -- Chunks table β one row per text chunk produced by the chunker | |
| create table if not exists chunks ( | |
| id uuid primary key default gen_random_uuid(), | |
| chunk_id text not null unique, | |
| doc_id text not null references documents (doc_id) on delete cascade, | |
| text text not null, | |
| source text not null, | |
| source_type text not null, | |
| team_id text not null, | |
| chunk_index integer not null, | |
| created_at timestamptz not null default now() | |
| ); | |
| create index if not exists chunks_doc_id_idx on chunks (doc_id); | |
| create index if not exists chunks_team_id_idx on chunks (team_id); | |
| -- Teams table β one row per tenant team | |
| create table if not exists teams ( | |
| team_id text primary key, | |
| cag_snapshot text, | |
| snapshot_at timestamptz, | |
| created_at timestamptz not null default now() | |
| ); | |
| -- Ingest jobs table β tracks Celery task state for the API | |
| create table if not exists ingest_jobs ( | |
| job_id text primary key, | |
| celery_task_id text not null, | |
| status text not null default 'pending', | |
| source_type text not null, | |
| team_id text not null, | |
| chunks_ingested integer not null default 0, | |
| error text, | |
| created_at timestamptz not null default now(), | |
| completed_at timestamptz | |
| ); | |
| create index if not exists ingest_jobs_team_id_idx on ingest_jobs (team_id); | |
| create index if not exists ingest_jobs_status_idx on ingest_jobs (status); | |
| -- RLS: each team only sees its own documents and chunks | |
| alter table documents enable row level security; | |
| alter table chunks enable row level security; | |
| alter table ingest_jobs enable row level security; | |
| -- Service role bypasses RLS; these policies cover the anon / authenticated roles | |
| create policy "team isolation β documents" | |
| on documents for all | |
| using (team_id = current_setting('app.team_id', true)); | |
| create policy "team isolation β chunks" | |
| on chunks for all | |
| using (team_id = current_setting('app.team_id', true)); | |
| create policy "team isolation β ingest_jobs" | |
| on ingest_jobs for all | |
| using (team_id = current_setting('app.team_id', true)); | |