CREATE TABLE IF NOT EXISTS rag_ocr_jobs ( job_id uuid PRIMARY KEY DEFAULT gen_random_uuid(), version_id uuid NOT NULL, document_id text NOT NULL, remote_job_id text NULL, remote_idempotency_key text NOT NULL, state text NOT NULL CHECK (state IN ('queued', 'running', 'succeeded', 'failed')), requested_pages integer[] NOT NULL, completed_pages integer NOT NULL DEFAULT 0 CHECK (completed_pages >= 0), config_version text NOT NULL, attempt_count integer NOT NULL DEFAULT 0 CHECK (attempt_count >= 0), heartbeat_at timestamptz NULL, lease_expires_at timestamptz NULL, next_attempt_at timestamptz NULL, error_code text NULL, error_detail text NULL, created_at timestamptz NOT NULL DEFAULT now(), started_at timestamptz NULL, completed_at timestamptz NULL, UNIQUE (version_id, document_id), FOREIGN KEY (version_id, document_id) REFERENCES rag_version_documents(version_id, document_id) ON DELETE RESTRICT ); CREATE TABLE IF NOT EXISTS rag_document_pages ( version_id uuid NOT NULL, document_id text NOT NULL, page_number integer NOT NULL CHECK (page_number > 0), extraction_method text NOT NULL CHECK (extraction_method IN ('native', 'ocr', 'blank')), native_text_hash char(64) NULL, ocr_text_hash char(64) NULL, candidate_text_hash char(64) NULL, reviewed_text_hash char(64) NULL, metrics jsonb NOT NULL DEFAULT '{}', risk_tokens jsonb NOT NULL DEFAULT '[]', blocked_reason text NULL, created_at timestamptz NOT NULL DEFAULT now(), PRIMARY KEY (version_id, document_id, page_number), FOREIGN KEY (version_id, document_id) REFERENCES rag_version_documents(version_id, document_id) ON DELETE RESTRICT ); CREATE TABLE IF NOT EXISTS rag_review_corrections ( correction_id uuid PRIMARY KEY DEFAULT gen_random_uuid(), version_id uuid NOT NULL, document_id text NOT NULL, page_number integer NOT NULL, line_id text NOT NULL, expected_line_hash char(64) NOT NULL, replacement_text text NOT NULL, reviewed_by text NOT NULL, created_at timestamptz NOT NULL DEFAULT now(), FOREIGN KEY (version_id, document_id, page_number) REFERENCES rag_document_pages(version_id, document_id, page_number) ON DELETE RESTRICT, UNIQUE (version_id, document_id, page_number, line_id) ); CREATE UNIQUE INDEX IF NOT EXISTS rag_one_pending_ocr_identity ON rag_source_versions(source_id, original_manifest_hash, processing_fingerprint, metadata_hash) WHERE source_content_hash IS NULL AND state IN ('pending', 'indexing', 'review_required');