CREATE TABLE IF NOT EXISTS user_channels ( id uuid PRIMARY KEY DEFAULT gen_random_uuid(), organization_id uuid NOT NULL REFERENCES organizations(id) ON DELETE CASCADE, channel_type text NOT NULL DEFAULT 'agentbus', display_name text NOT NULL, external_user_ref text, agentbus_ws_token_ciphertext text NOT NULL, agentbus_bot_address text, enabled boolean NOT NULL DEFAULT true, status text NOT NULL DEFAULT 'disabled', last_connected_at timestamptz, last_session_epoch bigint, last_error text, created_by uuid REFERENCES users(id) ON DELETE SET NULL, created_at timestamptz NOT NULL DEFAULT now(), updated_at timestamptz NOT NULL DEFAULT now(), CONSTRAINT user_channels_type_check CHECK (channel_type = 'agentbus'), CONSTRAINT user_channels_status_check CHECK (status IN ('disabled', 'connecting', 'connected', 'error')), UNIQUE (organization_id, display_name) ); CREATE INDEX IF NOT EXISTS user_channels_enabled_idx ON user_channels (organization_id, enabled, updated_at DESC); ALTER TABLE tasks ADD COLUMN IF NOT EXISTS channel_id uuid REFERENCES user_channels(id) ON DELETE SET NULL; CREATE INDEX IF NOT EXISTS tasks_channel_idx ON tasks (organization_id, channel_id, created_at DESC); CREATE TABLE IF NOT EXISTS agentbus_deliveries ( id uuid PRIMARY KEY DEFAULT gen_random_uuid(), organization_id uuid NOT NULL REFERENCES organizations(id) ON DELETE CASCADE, channel_id uuid NOT NULL REFERENCES user_channels(id) ON DELETE CASCADE, task_id uuid NOT NULL REFERENCES tasks(id) ON DELETE CASCADE, inbound_frame_id text NOT NULL, inbound_from text NOT NULL, conversation_id text, delivery_kind text NOT NULL, payload jsonb NOT NULL DEFAULT '{}'::jsonb, delivery_status text NOT NULL DEFAULT 'pending', attempt_count integer NOT NULL DEFAULT 0, next_attempt_at timestamptz NOT NULL DEFAULT now(), last_error text, delivered_at timestamptz, created_at timestamptz NOT NULL DEFAULT now(), updated_at timestamptz NOT NULL DEFAULT now(), CONSTRAINT agentbus_deliveries_kind_check CHECK (delivery_kind IN ('accepted', 'result')), CONSTRAINT agentbus_deliveries_status_check CHECK (delivery_status IN ('pending', 'sending', 'delivered', 'failed')), UNIQUE (channel_id, inbound_frame_id, delivery_kind) ); CREATE INDEX IF NOT EXISTS agentbus_deliveries_pending_idx ON agentbus_deliveries (channel_id, delivery_status, next_attempt_at, created_at) WHERE delivery_status IN ('pending', 'sending', 'failed'); CREATE INDEX IF NOT EXISTS agentbus_deliveries_task_idx ON agentbus_deliveries (organization_id, task_id, delivery_kind, created_at);