CREATE TABLE push_wake_outbox ( community_id UUID NOT NULL REFERENCES communities(id), id UUID NOT NULL DEFAULT gen_random_uuid(), author BYTEA NOT NULL CHECK (length(author) = 32), installation_id TEXT NOT NULL, lease_generation BIGINT NOT NULL CHECK (lease_generation > 0), endpoint_hash BYTEA NOT NULL CHECK (length(endpoint_hash) = 32), event_id BYTEA NOT NULL CHECK (length(event_id) = 32), class TEXT NOT NULL CHECK (class IN ('silent','default','time_sensitive','urgent')), expires_at BIGINT NOT NULL, state TEXT NOT NULL DEFAULT 'pending' CHECK (state IN ('pending','sending','delivered','failed')), attempts INTEGER NOT NULL DEFAULT 0 CHECK (attempts >= 0), next_attempt_at TIMESTAMPTZ NOT NULL DEFAULT now(), lease_until TIMESTAMPTZ, claim_id UUID, created_at TIMESTAMPTZ NOT NULL DEFAULT now(), PRIMARY KEY (community_id, id), FOREIGN KEY (community_id, author, installation_id) REFERENCES push_leases (community_id, author, installation_id), UNIQUE (community_id, endpoint_hash, event_id) ); CREATE INDEX push_wake_outbox_due ON push_wake_outbox (community_id, next_attempt_at) WHERE state = 'pending'; CREATE INDEX push_wake_outbox_recovery ON push_wake_outbox (community_id, lease_until) WHERE state = 'sending';