Add pending invite flow for collaboration rooms - #3182
Conversation
Room owners could previously add any real GitHub user to a room immediately, with no invite, no notification, and no way to decline. - New room_invites table tracking pending/accepted/declined status - Invite endpoint now creates a pending invite + notification instead of inserting directly into room_members - New accept/decline endpoints, only usable by the invited user - InviteModal no longer optimistically adds the invited user as a member in the UI - New PendingInvites component so invited users can see and respond to invites from the rooms page Fixes Priyanshu-byte-coder#3176
GSSoC Label Checklist 🏷️@Priyanshu-byte-coder — please apply the appropriate labels before merging: Difficulty (pick one):
Quality (optional):
Validation (required to score):
|
|
Thanks for this — the pending-invite flow has since shipped via #3269, which landed the same feature: a Closing as superseded rather than as a problem with the work — your version was a reasonable design, it just arrived alongside another that got there first. If you spot gaps in what shipped (the decline path and the list-my-invites endpoint are the thinnest parts), a follow-up PR against the current code would be very welcome. Sorry it sat here long enough for that to happen. |
Summary
Room owners could add anyone to a collaboration room just by typing a real GitHub username — no invite step, no notification, and no way to accept or decline. The person would wake up as a full member with their username/avatar visible to the whole room and access to chat history they never agreed to join.
Closes #3176
Type of Change
What Changed
room_invitestable (pending/accepted/declined/cancelled) —supabase/migrations/20260712000000_add_room_invites.sqlsrc/lib/supabase-rooms.ts: addedcreateRoomInvite,getPendingInvite,getPendingInvitesForUser,getInviteById,acceptRoomInvite,declineRoomInvite,getUserIdByGithubUsernamesrc/app/api/rooms/[roomId]/invite/route.ts: now creates a pending invite and fires a notification instead of callingaddRoomMemberdirectlyGET /api/rooms/invites(list my pending invites),POST /api/rooms/invites/[inviteId]/accept,POST /api/rooms/invites/[inviteId]/decline— both accept/decline verify the invite belongs to the requesting user before actingsrc/components/rooms/InviteModal.tsx: copy now says "Invite sent, they'll need to accept" instead of implying instant membershipsrc/components/rooms/MembersPanel.tsx: removed the optimisticonMemberAddedcall on invite success — the invited user isn't a member yet, so the UI shouldn't show them as onesrc/components/rooms/PendingInvites.tsx, mounted onsrc/app/rooms/RoomsListClient.tsx, so invited users can actually see and respond to invitesHow to Test
room_invitestable - a row should exist withstatus = 'pending'/roomswith Accept/Decline buttonsroom_membersrow is created and the invite flips tostatus = 'accepted'room_membersrow is created and the invite flips tostatus = 'declined''User is already a member'409'An invite is already pending for this user'instead of creating a duplicate rowExpected result: No one is ever added to a room without explicitly accepting an invite.
Checklist
console.log, debug code, or commented-out blocksnpm run lintpasses locallynpm run type-check)Additional Context
If an invited username has never logged into DevTrack, there's no
usersrow yet to attach a notification to — the invite is still created and will show up if/when they log in, it just won't trigger a notification at invite time.RLS is enabled on the new
room_invitestable for consistency with the existingcollaboration_rooms/room_messagestables, but actual access control happens in the API route / lib layer, matching how the existing room tables are already enforced (all routes use the service-role client, which bypasses RLS).No automated tests added this repo doesn't appear to have an existing test suite for the rooms feature to extend, so I tested manually per the steps above. Happy to add tests if there's a preferred pattern/framework you'd like me to follow.