Skip to content

feat(web): allow promoting pending members to owner - #1694

Merged
brendan-kellam merged 2 commits into
mainfrom
brendan/promote-pending-members
Sep 28, 2026
Merged

brendan-kellam merged 2 commits into
mainfrom
brendan/promote-pending-members

Conversation

@brendan-kellam

@brendan-kellam brendan-kellam commented Sep 28, 2026 •

Copy link
Copy Markdown
Contributor

Summary

Owners can now promote a pending member (added to the organization but never signed in) to owner from the members table, and demote a pending owner back to member. Previously both the membership service and the action menu required the member to be active. Suspended members still cannot have their role changed.

Changes

  • membership.service.ts: setMemberRole rejects only suspended members. The last-owner guards in setMemberRole and removeMember now apply only when the target is an active owner. Pending owners are excluded from countActiveOwners, so without this a pending owner could not be demoted or removed while the actor was the sole active owner.
  • membersTableActions.tsx: promote and demote render for pending rows. The last-active-owner lock requires the row to be active, so it no longer disables demote or suspend on a pending owner. The promote confirmation for a pending member notes that access starts when they sign in.
  • errors.ts / errorCodes.ts: memberNotActiveError renamed to memberSuspendedError with code MEMBER_SUSPENDED, since suspension is now the only condition it describes. The old code had no other references.
  • Docs: short note in the roles guide on promoting pending members.

Semantics

A pending owner does not count toward the active-owner floor. You still cannot demote or leave as the only active owner even if a pending owner exists, matching how the table already computes activeOwnerCount.

Testing

  • Membership service tests: pending promotion, pending-owner demotion and removal bypassing the last-owner guard, suspended rejection.
  • Web typecheck and ESLint clean on the changed files.

🤖 Generated with Claude Code


Note

Medium Risk
Changes org ownership and last-owner invariants in membership service and UI; incorrect guards could lock admins out or allow unsafe demotions, though behavior is covered by updated unit tests.

Overview
Owners can promote or demote pending members (provisioned but never signed in) from the members table, instead of requiring an active membership first. Suspended members still cannot change role until reactivated.

The membership service now blocks role changes only for suspended users (MEMBER_SUSPENDED, replacing MEMBER_NOT_ACTIVE). Last-owner protection in setMemberRole and removeMember applies only when the target is an active owner (isActiveOwner), so pending owners can be demoted or removed without falsely treating them as the sole owner.

The members table shows Promote to owner / Demote to member for any non-suspended row (including pending), adjusts the promote confirmation copy for pending users, and keeps the “last active owner” lock tied to active owners only.

Reviewed by Cursor Bugbot for commit ad45763. Bugbot is set up for automated code reviews on this repo. Configure here.

Summary by CodeRabbit

  • New Features
    • Pending, unsuspended members can be promoted to owner from the members table. They gain owner access when they sign in.
    • Pending owners can be demoted or removed without triggering the last-active-owner restriction.
  • Bug Fixes
    • Suspended members cannot be promoted or demoted until reactivated.
    • The last-owner restriction now applies to active owners who have signed in.

brendan-kellam and others added 2 commits September 28, 2026 13:52
Role changes were rejected unless the member was active, both in the
membership service and in the members table action menu. Pending members
(added but never signed in) can now be promoted or demoted; suspended
members still cannot.

The last-owner guards count only active owners, so they now apply only
when the target itself is an active owner. Otherwise demoting or removing
a pending owner while you are the sole active owner would be refused.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
@coderabbitai

coderabbitai Bot commented Sep 28, 2026 •

Copy link
Copy Markdown
Contributor

Review in Change Stack →

Navigate logical layers of code changes, visualize relationships, and explore their blast radius.

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Essentials

Run ID: 4e19f4f8-5a86-4042-99e9-6295ffab6336

📥 Commits

Reviewing files that changed from the base of the PR and between b493151 and ad45763.

📒 Files selected for processing (6)
  • CHANGELOG.md
  • packages/web/src/app/(app)/settings/members/membersTableActions.tsx
  • packages/web/src/features/membership/errors.ts
  • packages/web/src/features/membership/membership.service.test.ts
  • packages/web/src/features/membership/membership.service.ts
  • packages/web/src/lib/errorCodes.ts

Included review availability: This review used your included allowance. Your plan provides up to 8 included reviews per hour; 6 remain after this review.


Walkthrough

Pending members can now be promoted or demoted when they are not suspended. Last-owner checks apply to active owners, and the settings table explains that a pending member receives owner access after signing in.

Changes

Member role management

Layer / File(s) Summary
Role-change and active-owner rules
packages/web/src/lib/errorCodes.ts, packages/web/src/features/membership/errors.ts, packages/web/src/features/membership/membership.service.ts, packages/web/src/features/membership/membership.service.test.ts
The service allows pending members to change roles and rejects suspended members with MEMBER_SUSPENDED. Last-owner checks apply to active owners. Tests cover promotion, demotion, and removal of pending owners.
Settings-table role actions
packages/web/src/app/(app)/settings/members/membersTableActions.tsx, CHANGELOG.md
The table offers role actions to unsuspended pending members and states that owner access begins after sign-in. The changelog records the support.

Priority: ⬇️ Low

Estimated code review effort: 2 (Simple) | ~10 minutes

Change: Feature

Merge Risk: ⚪ Minimal · up to ad457

No identified issue prevents merging the pending-member role changes after normal checks.

🚥 Pre-merge checks | ✅ 5
✅ Passed checks (5 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title clearly and concisely describes the primary change: allowing pending members to be promoted to owner.
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check. Docstring coverage is scoped to functions touched by this diff. Analyzed 0 functions across 5…
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.
✨ Finishing Touches
📝 Generate docstrings
  • Commit to this branch
  • Create a new PR
🧪 Generate unit tests (beta)
  • Commit to this branch
  • Create a new PR

Comment @coderabbitai help to get the list of available commands.

@brendan-kellam
brendan-kellam merged commit 5091d26 into main Sep 28, 2026
12 checks passed
@brendan-kellam
brendan-kellam deleted the brendan/promote-pending-members branch September 28, 2026 21:43
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