-- ============================================================================ -- Cached OpenGraph previews. The edge function `og-preview` writes rows -- server-side (service-role). Clients read via RLS for any authenticated -- user. Rows are keyed by URL so hits across conversations deduplicate. -- ============================================================================ create table public.link_previews ( url text primary key, title text, description text, image_url text, site_name text, fetched_at timestamptz not null default now(), -- Absence of metadata (404, unreachable, parse failure) still produces a -- cache row so we don't spam the fetcher. `ok = false` signals the UI to -- hide the preview. ok boolean not null default true, error text ); create index link_previews_fetched_at_idx on public.link_previews (fetched_at); alter table public.link_previews enable row level security; create policy link_previews_select_authenticated on public.link_previews for select to authenticated using (true); -- No INSERT/UPDATE policy: writes flow exclusively through the edge function -- which authenticates with the service-role key.