CREATE TABLE IF NOT EXISTS gateway_request_assets ( id uuid PRIMARY KEY DEFAULT gen_random_uuid(), sha256 text NOT NULL, content_type text NOT NULL, byte_size bigint NOT NULL, url text NOT NULL, storage_provider text NOT NULL, local_path text, expires_at timestamptz, expired_at timestamptz, ref_count integer NOT NULL DEFAULT 0, created_at timestamptz NOT NULL DEFAULT now(), updated_at timestamptz NOT NULL DEFAULT now(), UNIQUE (sha256, content_type) ); CREATE INDEX IF NOT EXISTS idx_gateway_request_assets_expires ON gateway_request_assets(storage_provider, expires_at) WHERE expires_at IS NOT NULL AND expired_at IS NULL; CREATE INDEX IF NOT EXISTS idx_gateway_request_assets_local_path ON gateway_request_assets(local_path) WHERE local_path IS NOT NULL; CREATE TABLE IF NOT EXISTS gateway_conversations ( id uuid PRIMARY KEY DEFAULT gen_random_uuid(), user_id text NOT NULL, gateway_user_id uuid REFERENCES gateway_users(id) ON DELETE SET NULL, conversation_key text NOT NULL, metadata jsonb NOT NULL DEFAULT '{}'::jsonb, created_at timestamptz NOT NULL DEFAULT now(), updated_at timestamptz NOT NULL DEFAULT now(), UNIQUE (user_id, conversation_key) ); CREATE TABLE IF NOT EXISTS gateway_conversation_messages ( id uuid PRIMARY KEY DEFAULT gen_random_uuid(), conversation_id uuid NOT NULL REFERENCES gateway_conversations(id) ON DELETE CASCADE, message_hash text NOT NULL, role text, message_snapshot jsonb NOT NULL, asset_sha256s text[] NOT NULL DEFAULT '{}', created_at timestamptz NOT NULL DEFAULT now(), updated_at timestamptz NOT NULL DEFAULT now(), UNIQUE (conversation_id, message_hash) ); CREATE INDEX IF NOT EXISTS idx_gateway_conversation_messages_conversation ON gateway_conversation_messages(conversation_id, created_at); CREATE TABLE IF NOT EXISTS gateway_task_message_refs ( task_id uuid NOT NULL REFERENCES gateway_tasks(id) ON DELETE CASCADE, message_id uuid NOT NULL REFERENCES gateway_conversation_messages(id) ON DELETE CASCADE, position integer NOT NULL, created_at timestamptz NOT NULL DEFAULT now(), PRIMARY KEY (task_id, position) ); CREATE INDEX IF NOT EXISTS idx_gateway_task_message_refs_message ON gateway_task_message_refs(message_id); ALTER TABLE gateway_tasks ADD COLUMN IF NOT EXISTS conversation_id uuid REFERENCES gateway_conversations(id) ON DELETE SET NULL, ADD COLUMN IF NOT EXISTS new_message_count integer NOT NULL DEFAULT 0; CREATE INDEX IF NOT EXISTS idx_gateway_tasks_conversation_created ON gateway_tasks(conversation_id, created_at DESC) WHERE conversation_id IS NOT NULL;