-- t-paliad-195 / Fristen Phase 3 Slice 9 Step E (design §3.E, §9.1). -- m approved the downtime window 2026-05-15 ("paliad ist nicht in use -- heute, downtime ist egal") so the destructive drops can land. -- -- This migration drops the four legacy columns on -- paliad.deadline_rules that the unified Phase 3 calculator no longer -- reads. The replacements have been backfilled (Slice 2 mig 082/083/ -- 084), wired into the calculator (Slice 4), and on the wire (Slice 8): -- -- is_mandatory → priority='mandatory' | (recommended | optional | informational) -- is_optional → priority='optional' (the RoP.151 T/T case) -- condition_flag → condition_expr (jsonb long form) -- condition_rule_id → DEAD (no live rows, Q13 m's approved drop) -- -- Sibling drops (event_deadlines/trigger_events tables, retire of -- litigation category) are deferred from this slice per the live-data -- audit (see head ping). This file is the legacy-column-drop only. -- -- Backup: paliad.deadline_rules_pre_091 snapshot of the four columns + -- id BEFORE the drop, so the down-migration can restore individual -- values if a deploy needs to roll back. The backup uses CREATE TABLE -- IF NOT EXISTS so a re-applied migration is a no-op. -- -- Audit-reason set at the top: the mig 079 trigger fires on every -- UPDATE/DELETE on paliad.deadline_rules; ALTER TABLE DROP COLUMN -- doesn't fire the row-level trigger but the wrapper is the standard -- Phase 3 pattern. The reason persists in the audit log only for -- write paths. SELECT set_config( 'paliad.audit_reason', 'mig 091: drop legacy rule columns per design §3.E + m''s 2026-05-15 approval', true); -- ============================================================================= -- 1. Snapshot of the four columns + id, so the down-migration can -- restore values to existing rows. Skipping the snapshot table -- would mean a rollback adds the columns back but with NULL data; -- the snapshot preserves the legacy values for any downstream -- consumer the audit might surface. -- ============================================================================= CREATE TABLE IF NOT EXISTS paliad.deadline_rules_pre_091 AS SELECT id, is_mandatory, is_optional, condition_flag, condition_rule_id, now() AS snapshotted_at FROM paliad.deadline_rules; COMMENT ON TABLE paliad.deadline_rules_pre_091 IS 'Snapshot of paliad.deadline_rules.(is_mandatory, is_optional, ' 'condition_flag, condition_rule_id) before mig 091''s drop. Lets ' 'a rollback restore the legacy values for the 172 rules that ' 'existed at drop time. Drop this table after Slice 9 is verified ' 'in prod (a focused follow-up slice or part of Slice 12 cleanup).'; -- ============================================================================= -- 2. Drop the columns. Order doesn't matter — none of them reference -- each other or other tables (condition_rule_id was a dead self-FK -- that no live row uses, Q13). -- ============================================================================= ALTER TABLE paliad.deadline_rules DROP COLUMN IF EXISTS is_mandatory, DROP COLUMN IF EXISTS is_optional, DROP COLUMN IF EXISTS condition_flag, DROP COLUMN IF EXISTS condition_rule_id; -- ============================================================================= -- 3. Hard assertion: every remaining row carries a valid priority + -- has condition_expr populated when its legacy condition_flag was -- non-empty pre-mig. Belt-and-braces — Slice 2 backfilled both -- paths and Slice 4 unified the calculator, but a stale row would -- light up here BEFORE we hand the schema to the unified code. -- ============================================================================= DO $$ DECLARE n_total int; n_null_prio int; n_lost int; BEGIN SELECT count(*), count(*) FILTER (WHERE priority IS NULL) INTO n_total, n_null_prio FROM paliad.deadline_rules; -- Cross-check against the snapshot: every pre-mig row with a -- non-empty condition_flag must have a non-NULL condition_expr -- post-mig. If any row lost its gate, the calculator's gate -- behaviour would silently change — surface it loudly. SELECT count(*) INTO n_lost FROM paliad.deadline_rules_pre_091 b JOIN paliad.deadline_rules dr ON dr.id = b.id WHERE b.condition_flag IS NOT NULL AND array_length(b.condition_flag, 1) > 0 AND dr.condition_expr IS NULL; RAISE NOTICE 'mig 091: % rules, % with NULL priority, % lost condition_expr', n_total, n_null_prio, n_lost; IF n_null_prio > 0 THEN RAISE EXCEPTION 'mig 091: % rules have priority IS NULL post-drop — ' 'the priority column must be backfilled (Slice 2 mig 083) ' 'before legacy columns are dropped', n_null_prio; END IF; IF n_lost > 0 THEN RAISE EXCEPTION 'mig 091: % rules had a condition_flag pre-drop but no ' 'condition_expr post-drop — Slice 2 mig 084 missed them', n_lost; END IF; END $$;