-- 003: early-signal buffering (review SAGA-10/DX-8/SAGA-14).
--
-- A `RoutesToStep` signal that arrives BEFORE its target step suspends is
-- now persisted and consumed the moment the step suspends, instead of
-- reporting "not awaiting" and forcing the caller to retry. The row carries a
-- `consumed_at` marker: NULL = pending (awaiting its step's suspension),
-- non-NULL = already delivered to the step.
--
-- This also gives SAGA-14 (signal rows never drained) an exact retention
-- predicate: a future job can prune `consumed_at < now() - retention`.
--
-- Append-only migration — does not touch 001/002 tables. Idempotent.

ALTER TABLE es_saga_signals
    ADD COLUMN IF NOT EXISTS consumed_at TIMESTAMPTZ NULL;

-- Suspend-side lookup + the at-most-one-pending invariant: the oldest
-- unconsumed signal for (saga, instance, type). Partial index stays tiny —
-- only pending rows are indexed.
CREATE INDEX IF NOT EXISTS idx_saga_signals_unconsumed
    ON es_saga_signals (saga_name, instance_id, signal_type, id)
    WHERE consumed_at IS NULL;
