-- V14 — Repair EXCHANGE_MATCH rules persisted with fireMode=null.
-- Root cause: the rule editor wizard reset the condition payload on kind
-- change without seeding a fireMode default, and the backend ctor allowed
-- null to pass. Stricter ctor in ExchangeMatchCondition now rejects null
-- fireMode — existing rows need to be repaired so startup doesn't fail
-- deserialization and the evaluator stops NPE-looping on them.
--
-- Default to PER_EXCHANGE + perExchangeLingerSeconds=300 — the same default
-- the UI now seeds when a user picks EXCHANGE_MATCH.
UPDATE alert_rules
   SET condition = jsonb_set(
                     jsonb_set(condition, '{fireMode}', '"PER_EXCHANGE"', true),
                     '{perExchangeLingerSeconds}',
                     COALESCE(condition->'perExchangeLingerSeconds', '300'::jsonb),
                     true
                   ),
       updated_at = now()
 WHERE condition_kind = 'EXCHANGE_MATCH'
   AND (condition->>'fireMode') IS NULL;
