-- sql/127-news-future-date-guard.sql -- News published_at cannot be in the future: an article cannot be published after -- we scraped it. One future-dated row found 2026-07-06 (The Next Platform, pub -- 2026-07-15 but created/scraped 2026-06-19). One-time correction + ingest guard so -- it cannot recur (a CHECK with now() is not immutable/allowed -> BEFORE trigger). -- Idempotent; safe to re-run. -- One-time: clamp any future published_at to the scrape date (created_at), else now(). update news_articles set published_at = least(published_at, coalesce(created_at, now())) where published_at is not null and published_at > now(); create or replace function news_published_at_guard() returns trigger language plpgsql as $$ begin if NEW.published_at is not null and NEW.published_at > now() then NEW.published_at := least(coalesce(NEW.created_at, now()), now()); end if; return NEW; end $$; comment on function news_published_at_guard() is 'BEFORE INSERT/UPDATE on news_articles: clamps a future published_at to the scrape date (created_at) or now(). Prevents future-dated news polluting the feed.'; drop trigger if exists trg_news_published_at_guard on news_articles; create trigger trg_news_published_at_guard before insert or update on news_articles for each row execute function news_published_at_guard(); insert into _migrations (filename, applied_at) select '127-news-future-date-guard.sql', now() where not exists (select 1 from _migrations where filename = '127-news-future-date-guard.sql');