-- t-paliad-184 / Fristen Phase 3 Slice 3 — wrap paliad.event_deadlines -- in a read-only trigger so nobody can edit either side mid-cutover. -- -- Slice 3 just moved 77 rows from event_deadlines → deadline_rules (mig -- 085). Until Slice 4 cuts every reader over and Slice 9 drops the -- legacy table, event_deadlines stays in place as the audit anchor and -- (briefly) a compat-read source. We must not let any writer mutate it -- behind the unified backend's back — diverging the two sides would -- silently regress "Was kommt nach…" parity. -- -- The trigger fires AFTER INSERT / UPDATE / DELETE and raises an -- EXCEPTION with a clear message pointing the writer at the unified -- table. SELECT is unaffected — the legacy EventDeadlineService's -- pre-Slice-3 SELECT path keeps working until Slice 4 swaps it. -- -- The supabase service_role bypasses RLS but NOT triggers — so -- direct DB maintenance (psql, migration scripts) is also blocked. -- This is intentional: any further edit to event_deadlines is a -- mistake until Slice 9 drops the table. -- -- Removed by Slice 9 (Step E, mig ~090) when paliad.event_deadlines is -- dropped. Until then the trigger is the only thing keeping the two -- tables in sync. CREATE OR REPLACE FUNCTION paliad.event_deadlines_readonly_trigger() RETURNS trigger LANGUAGE plpgsql AS $$ BEGIN RAISE EXCEPTION 'paliad.event_deadlines is read-only after Phase 3 Slice 3 — ' 'writes must go through paliad.deadline_rules (Pipeline C is ' 'unified; the source table is preserved as an audit anchor ' 'until Slice 9 drops it). Operation: %', TG_OP; END; $$; COMMENT ON FUNCTION paliad.event_deadlines_readonly_trigger() IS 'BEFORE INSERT/UPDATE/DELETE trigger function that raises on any ' 'write to paliad.event_deadlines. Lives only between Slice 3 and ' 'Slice 9 — removed when the source table is dropped.'; -- BEFORE-trigger so the write is blocked before any row image is -- captured. AFTER would still raise but the surrounding tx would -- have already taken row locks. DROP TRIGGER IF EXISTS event_deadlines_readonly ON paliad.event_deadlines; CREATE TRIGGER event_deadlines_readonly BEFORE INSERT OR UPDATE OR DELETE ON paliad.event_deadlines FOR EACH ROW EXECUTE FUNCTION paliad.event_deadlines_readonly_trigger(); -- Defensive INSERT-row-level trigger covers the COPY path too; same -- function, identical behaviour. COMMENT ON TRIGGER event_deadlines_readonly ON paliad.event_deadlines IS 'Phase 3 Slice 3 read-only wrapper. Blocks every INSERT/UPDATE/DELETE ' 'until Slice 9 drops the table. SELECT unaffected.';