Description
Organization ownership is currently derived from two different fields in different parts of the app:
organizations.ownerId
organization_members.role (owner / member)
When those values drift (common in self-hosted/manual DB edits or migrations), behavior becomes inconsistent:
- Some UI surfaces show a user as
Member while others treat them as Owner
- Invite permissions are checked against
organizations.ownerId, so users with membership role owner can still be blocked from inviting
Expected behavior:
- Role display should come from membership role (
organization_members.role)
- Invite authorization should allow users whose membership role is
owner for that organization
This issue tracks the fix to make role display and invite permissions consistent with membership role ownership.
Reproduction
- Create an organization with user A as
organizations.ownerId.
- Set organization membership rows so ownership data is inconsistent, for example:
- Case 1: user A has
organization_members.role = member
- Case 2: user B has
organization_members.role = owner but organizations.ownerId = user A
- Sign in as the affected user(s).
- Open organization-related UI pages (members views / org indicators) and try to send invites.
Actual:
- Role labels can differ across UI surfaces.
- Invite permission is tied to
organizations.ownerId and may reject a membership owner.
Expected:
- UI role labels consistently reflect
organization_members.role.
- Membership
owner users can send invites.
Additional Context
- Cap version: current
main (self-hosted)
- Operating system, version: Linux server (Docker), browser client
- Device (optional): N/A
Description
Organization ownership is currently derived from two different fields in different parts of the app:
organizations.ownerIdorganization_members.role(owner/member)When those values drift (common in self-hosted/manual DB edits or migrations), behavior becomes inconsistent:
Memberwhile others treat them asOwnerorganizations.ownerId, so users with membership roleownercan still be blocked from invitingExpected behavior:
organization_members.role)ownerfor that organizationThis issue tracks the fix to make role display and invite permissions consistent with membership role ownership.
Reproduction
organizations.ownerId.organization_members.role = memberorganization_members.role = ownerbutorganizations.ownerId = user AActual:
organizations.ownerIdand may reject a membershipowner.Expected:
organization_members.role.ownerusers can send invites.Additional Context
main(self-hosted)