Skip to content

fix(invitations): keep every invited role through acceptance - #126

Merged
kipavy merged 1 commit into
mainfrom
fix/invite-multi-role
Nov 8, 2026
Merged

kipavy merged 1 commit into
mainfrom
fix/invite-multi-role

Conversation

@kipavy

@kipavy kipavy commented Nov 8, 2026

Copy link
Copy Markdown
Contributor

Server side of VoltiusApp/voltius#779.

A pending invitation stored one builtin role name. An invite with several roles kept only the first one, and an invite with a custom role failed.

Change

  • Migration 066 adds pending_invitations.role_ids UUID[] NOT NULL DEFAULT '{}'.
  • POST /v1/teams/:id/members and POST /v1/teams/:id/invite accept an optional role_ids. Each id goes through the same check as Assign role (require_may_assign_role, now shared with assign_member_role):
    • the role must belong to the team (400 otherwise);
    • custom roles need Business (402);
    • the inviter must cover the role (403).
      A request can carry at most 32 ids.
  • admit_member assigns every invited id that still exists. It falls back to the builtin role name only when none of them does, so a role deleted before acceptance is skipped.
  • Resending an invite replaces its role_ids, the same way it already replaced role.
  • role now holds the most senior invited role, which invitees see in the invite preview and in their pending list. The team's pending list also returns role_ids.
  • Audit metadata carries role_ids.

Compatibility

  • Clients that send only role get exactly what they get today.
  • New clients talking to an older server still send role (a builtin), so the invitee gets that one role.

Tests (new invite_role_tests module)

  • Every chosen role survives acceptance, for both the by-id and the email endpoints.
  • A role from another team gets 400. A role above the inviter's gets 403. A custom role on a Teams-tier team gets 402, while a builtin role on the same team is accepted.
  • A resend replaces the roles. A deleted role is skipped. The display name and the list role_ids are correct.
  • Full suite: 815 passed (rust:alpine with a throwaway Postgres).

Needs a deploy before the client change does anything; the client PR follows.

A pending invitation stored one builtin role name, so an invite with
several roles kept only the first, and a custom role could not be
invited at all.

pending_invitations gains role_ids. Both invite endpoints accept
role_ids, each checked like assigning it: same team, Business gate for
custom roles, and the inviter must cover it. Acceptance assigns every
id that still exists and falls back to the builtin role name only when
none does. Clients that send only `role` behave as before. The pending
list returns role_ids, and `role` holds the most senior invited role
for display.

assign_member_role and invite share require_may_assign_role.

Refs VoltiusApp/voltius#779
@kipavy
kipavy merged commit ad25887 into main Nov 8, 2026
1 check passed
@kipavy
kipavy deleted the fix/invite-multi-role branch November 8, 2026 21:00
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant