-- v1.1.1: abandoned_executions — design notes §3 #9.
--
-- Forensic table for the "dispatcher tried to resolve a oneshot inbox
-- but the receiver was already dropped" edge case. The orchestrator
-- timed out (returned 504 to the caller) and gave up on the channel,
-- but then the dispatcher's execution succeeded later. The caller
-- never sees the result; the row exists so the operator can
-- correlate when the abandoned-counter metric spikes.
--
-- Only the dispatcher-after-orchestrator-timeout edge case writes
-- here; ordinary "script timed out, caller got 504" stays uneventful.
--
-- 7-day retention, GC by `created_at`, sweep alongside dead_letters.

CREATE TABLE abandoned_executions (
    id              UUID PRIMARY KEY DEFAULT gen_random_uuid(),
    app_id          UUID NOT NULL REFERENCES apps(id) ON DELETE CASCADE,
    -- Original outbox row id (the row itself has been deleted).
    outbox_id       UUID NOT NULL,
    script_id       UUID,
    -- The inbox channel id the dispatcher tried to resolve.
    inbox_id        UUID NOT NULL,
    -- The HTTP status code the dispatcher attempted to send back.
    status_code     INT  NOT NULL,
    -- Truncated body / error description (capped at write time —
    -- the dispatcher doesn't need to ship megabytes here).
    result_summary  TEXT,
    created_at      TIMESTAMPTZ NOT NULL DEFAULT NOW()
);

CREATE INDEX idx_abandoned_executions_gc ON abandoned_executions (created_at);
