Problem
POST /api/conversations/join authenticates the caller and resolves their internal user ID, but it adds that user to the requested SSE room without checking conversation_participants.
An authenticated user who obtains another conversation UUID can therefore join that room and receive events broadcast to it, including new-message metadata and typing activity. Other conversation endpoints already enforce participant membership.
Expected behavior
Only active conversation participants (left_at IS NULL) should be added to the SSE room. Non-participants should receive HTTP 403.
Suggested fix
Query conversation_participants for the conversation and internal user ID before calling sseManager.joinRoom, and add regression coverage for allowed and denied joins.
Problem
POST /api/conversations/joinauthenticates the caller and resolves their internal user ID, but it adds that user to the requested SSE room without checkingconversation_participants.An authenticated user who obtains another conversation UUID can therefore join that room and receive events broadcast to it, including new-message metadata and typing activity. Other conversation endpoints already enforce participant membership.
Expected behavior
Only active conversation participants (
left_at IS NULL) should be added to the SSE room. Non-participants should receive HTTP 403.Suggested fix
Query
conversation_participantsfor the conversation and internal user ID before callingsseManager.joinRoom, and add regression coverage for allowed and denied joins.