-- Materialized Result DB (user decision 2026-09-28): every row is disclosed, checked and stored when -- its source data changes, so UI, API and JSONL export read exactly the same verified content. -- Derived data only: rows are rebuilt from canonical tables and never edited by hand. CREATE TABLE assessor_result_db_rows ( result_projection_id text PRIMARY KEY CHECK (btrim(result_projection_id) <> ''), ordinal integer NOT NULL CHECK (ordinal >= 0), project_id text NOT NULL REFERENCES assessor_projects(id) ON DELETE CASCADE, source_kind text NOT NULL CHECK (btrim(source_kind) <> ''), row_data jsonb NOT NULL CHECK (jsonb_typeof(row_data) = 'object'), guard_withheld boolean NOT NULL DEFAULT false, source_revision bigint NOT NULL ); CREATE INDEX assessor_result_db_rows_project_idx ON assessor_result_db_rows(project_id, ordinal); CREATE INDEX assessor_result_db_rows_ordinal_idx ON assessor_result_db_rows(ordinal); -- One state record describes the stored Result DB as a whole. CREATE TABLE assessor_result_db_state ( singleton boolean PRIMARY KEY DEFAULT true CHECK (singleton), source_revision bigint NOT NULL, disclosure_policy_version text NOT NULL, identity_guard_version text NOT NULL, row_count integer NOT NULL CHECK (row_count >= 0), redaction_count integer NOT NULL CHECK (redaction_count >= 0), guard_withheld_row_count integer NOT NULL CHECK (guard_withheld_row_count >= 0), materialized_at timestamptz NOT NULL );