Skip to content

fix(waitlist): declined members no longer auto-promoted - #3010

Merged
mroderick merged 1 commit into
codebar:masterfrom
mroderick:fix/waitlist-declined-members-not-promotable
Oct 12, 2026
Merged

mroderick merged 1 commit into
codebar:masterfrom
mroderick:fix/waitlist-declined-members-not-promotable

Conversation

@mroderick

Copy link
Copy Markdown
Collaborator

Closes the residual seat-wasting path from #3003: a member who cancels after the close time keeps their waiting-list entry, and nothing stopped a later freed seat from being handed back to them.

Problem

Let X be a member who is attending and also holds a waiting-list entry (reachable through admin overrides or data carried over from before the self-promotion fix). If X cancels after the close time, the entry stays. A later cancellation by member Y promotes on auto_rsvp alone, so X can be re-confirmed as attending and emailed "your attendance has now been confirmed" despite having just said they cannot attend. If X does not show, the seat is spent and, past the 3.5-hour freeze, it cannot be filled again.

The two removal paths also disagreed: a member reject kept the rejecter's entry while an admin removal destroyed the removed member's entry.

Change

WaitingList.promote_next now considers only invitations whose attending flag is still undecided. The eligibility rule is "declined means parked": the entry stays on the printed list for the security handover, but is never auto-promoted. A cancelling member is already declined by the time promotion runs, so the excluding: parameter from #3003 is no longer needed and is removed. Accepted invitations with a lingering entry are skipped too.

The member reject path and the admin removal path now share one rule through WaitlistPromotionConcerns.

Review notes

  • The SQL is the one risk point: the scope joins :invitation and adds workshop_invitations.attending IS NULL. Worth re-reading promote_next in full, including the SKIP LOCKED pop that follows.
  • Deliberately not done: deleting declined entries (that would mutate the frozen handover list), changing any gate times, and touching the check-in or admin-entry flows beyond what the shared rule gives for free.
  • Specs: new model specs pin declined-not-promotable and accepted-not-promotable; the Allow post-close cancellations with frozen waitlist progression聽#3003 controller examples carry over unchanged, which is itself the pin that the rejecting member's entry survives their cancel.
State model behind the rule
Waiting-list entry owner attending on invitation Promotable? On security list?
Eager waitlisted member nil Yes Yes
Member who cancelled false No Yes
Accepted member with stale entry true No N/A (already attending)

A member who cancels after the close time keeps their waiting-list
entry, but nothing stopped a later freed seat from being handed to
that declined member: promotion eligible them on auto_rsvp alone, so
someone who said "I can no longer attend" could be re-confirmed and
emailed by another member's cancellation. The seat could end up spent
past the freeze on a member who will not attend.

promote_next now considers only invitations whose attending flag is
still undecided. A declined invitation (attending false) stays on the
printed list for the security handover but is never auto-promoted;
the excluder handoff the previous commit carried is not needed since
a cancelling member is already declined by the time promote_next
runs. Accepted invitations with a lingering entry are skipped too.

The admin removal path shares the same rule through
WaitlistPromotionConcerns, collapsing the difference where member
rejects kept the entry while admin removals destroyed it.
@mroderick
mroderick marked this pull request as ready for review October 12, 2026 11:30
@mroderick
mroderick merged commit 173aaec into codebar:master Oct 12, 2026
10 checks passed
@mroderick
mroderick deleted the fix/waitlist-declined-members-not-promotable branch October 12, 2026 11:33
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