Engineering manualDatabase declarations
supabase-brand-studio-review
Exact checked-in database declaration: docs/supabase-brand-studio-review.sql
Source: docs/supabase-brand-studio-review.sql. Declared objects: index:brand_studio_score_overrides_pull_idx, policy:brand_studio_score_overrides_delete_own, policy:brand_studio_score_overrides_insert_own, policy:brand_studio_score_overrides_select_own, policy:brand_studio_score_overrides_update_own, table:brand_studio_score_overrides. This is repository DDL, not a claim about live deployment.
All database declarations · Data structures and lineage
-- Brand Studio — human score overrides (R3: the review surface's disagreement layer).
--
-- ADDITIVE. Run AFTER docs/supabase-brand-studio-pulls.sql — this table's
-- composite FK targets brand_studio_pulls(id, user_id), which only exists
-- once that migration has run. Nothing here alters brand_studio_pulls; the
-- computed section_quality / analysis_quality columns on that table are never
-- written to by anything in this file.
--
-- The one rule this schema exists to enforce (see src/local/review-overrides.mjs):
-- an override sits BESIDE the computed score it disagrees with, never over
-- it. This table only ever grows; nobody UPDATEs a pull's section_quality
-- from a review.
create extension if not exists pgcrypto;
create table if not exists public.brand_studio_score_overrides (
id uuid primary key default gen_random_uuid(),
user_id uuid not null references auth.users(id) on delete cascade,
pull_id uuid not null,
section text not null,
-- Duplicated from the pull's section_quality at the moment of the review,
-- not joined live against it. A pull's section_quality can be recomputed
-- later — a scorer-version bump, a fix landing from the R5 audit — and if
-- this column were a live join instead of a pinned copy, that recompute
-- would retroactively change what the override appears to be disagreeing
-- with. Pinning it here is what keeps "the scorer used to say 2, a fix
-- changed it to 4, and this reviewer said 4 all along" a legible historical
-- fact instead of a silently rewritten one — the override is evidence
-- about a specific scorer run, not a live opinion about whatever the
-- scorer currently says.
computed_score numeric not null check (computed_score >= 1 and computed_score <= 5),
human_score numeric not null check (human_score >= 1 and human_score <= 5),
-- No default and NOT NULL by the check below: an override with no stated
-- reason teaches the scorer nothing (see applyOverride) and is refused
-- before it ever reaches this table, so a row that got here always has one.
reason text not null check (length(trim(reason)) > 0),
reviewer text not null default '',
scorer_version text not null default '',
created_at timestamptz not null default now(),
-- One reviewer, one CURRENT opinion per section. A reviewer who changes
-- their mind upserts this row (on conflict do update) rather than appending
-- a second one that would silently double-count them in overrideDrift.
unique (pull_id, section, reviewer),
-- A pull can only ever carry overrides from the SAME user who owns it —
-- physically impossible to attach a review to someone else's pull, not just
-- forbidden by the row-level policies below.
constraint brand_studio_score_overrides_pull_owner_fk
foreign key (pull_id, user_id)
references public.brand_studio_pulls (id, user_id)
on delete cascade
);
create index if not exists brand_studio_score_overrides_pull_idx
on public.brand_studio_score_overrides (pull_id);
-- ------------------------------------------------------------------ RLS ----
alter table public.brand_studio_score_overrides enable row level security;
drop policy if exists brand_studio_score_overrides_select_own on public.brand_studio_score_overrides;
create policy brand_studio_score_overrides_select_own on public.brand_studio_score_overrides
for select using (user_id = auth.uid());
drop policy if exists brand_studio_score_overrides_insert_own on public.brand_studio_score_overrides;
create policy brand_studio_score_overrides_insert_own on public.brand_studio_score_overrides
for insert with check (user_id = auth.uid());
drop policy if exists brand_studio_score_overrides_update_own on public.brand_studio_score_overrides;
create policy brand_studio_score_overrides_update_own on public.brand_studio_score_overrides
for update using (user_id = auth.uid()) with check (user_id = auth.uid());
drop policy if exists brand_studio_score_overrides_delete_own on public.brand_studio_score_overrides;
create policy brand_studio_score_overrides_delete_own on public.brand_studio_score_overrides
for delete using (user_id = auth.uid());