ALTER TABLE provider_object_event_watermarks ADD COLUMN IF NOT EXISTS requires_reconciliation BOOLEAN NOT NULL DEFAULT false, ADD COLUMN IF NOT EXISTS reconciliation_reason TEXT, ADD COLUMN IF NOT EXISTS last_snapshot_at TIMESTAMPTZ; CREATE TABLE IF NOT EXISTS stripe_subscription_reconciliations ( provider_subscription_id VARCHAR(200) PRIMARY KEY, reason TEXT NOT NULL, status VARCHAR(20) NOT NULL DEFAULT 'pending', attempts INTEGER NOT NULL DEFAULT 0, next_attempt_at TIMESTAMPTZ NOT NULL DEFAULT NOW(), last_error TEXT, lease_owner UUID, lease_until TIMESTAMPTZ, created_at TIMESTAMPTZ NOT NULL DEFAULT NOW(), updated_at TIMESTAMPTZ NOT NULL DEFAULT NOW(), completed_at TIMESTAMPTZ, CONSTRAINT stripe_subscription_reconciliations_status_check CHECK (status IN ('pending', 'processing', 'completed', 'failed')) ); WITH corrected AS ( UPDATE provider_object_event_watermarks SET last_event_created = 0, last_event_rank = 0, last_event_id = 'reconcile:migration', requires_reconciliation = true, reconciliation_reason = 'migration_016_non_causal_seed', updated_at = NOW() WHERE provider = 'stripe' AND object_type = 'subscription' AND is_deleted = false AND last_event_id LIKE 'migration:%' RETURNING provider_object_id ) INSERT INTO stripe_subscription_reconciliations ( provider_subscription_id, reason, status, next_attempt_at ) SELECT provider_object_id, 'migration_016_non_causal_seed', 'pending', NOW() FROM corrected ON CONFLICT (provider_subscription_id) DO UPDATE SET reason = EXCLUDED.reason, status = 'pending', next_attempt_at = NOW(), last_error = NULL, lease_owner = NULL, lease_until = NULL, completed_at = NULL, updated_at = NOW(); CREATE INDEX IF NOT EXISTS idx_stripe_subscription_reconciliations_ready ON stripe_subscription_reconciliations(next_attempt_at, updated_at) WHERE status IN ('pending', 'failed');