You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
We closed #296 when we implemented admin-initiated user merging. This tracks adding a self-service flow so users can merge their own duplicate accounts without admin involvement.
Motivation
We know users end up with multiple accounts under different email addresses. Right now an admin has to be involved for every merge. In addition to reducing the operation burden on admins, if we achieve our long-term ambitions of supporting multi-tenancy and (at least increasingly) open signups, admins will become less well-positioned to validate a merge vs. an honest user who actually owns both accounts. However, we need to make sure the authentication scheme is strong enough to prevent a malicious user from merging away an account they don't own.
Data analysis
We've been approaching this from intuition about the types of merges that we need to do, but I thought it would be good to do some actual analysis on the data.
As of today (February 2026), we have 728 user accounts. Of those:
Roughly 34% have never meaningfully used Jolly Roger. Either they have no authentication configured (presumably, they signed up one year and were created by an operator but never actually enrolled, roughly 14%) or have credentials set but have never sent a chat message (presumably, realized they were in the wrong account and switched, roughly 20%). Out of that 34%, roughly 48 (6.5% of the whole) have email addresses that seem likely unrecoverable (.edu domains, obvious typos, or seem like an employer rather than personal); the rest are major email providers (Gmail, Hotmail, etc.) or seem like personal domains.
By looking at display names and the local parts of email addresses, we can pick out 55 groups of users that potentially should be merged together (or alternatively, roughly 58 users that should be eliminated). Of course, there's some overlap with the 34% of ghost users, and those heuristics may over-match.
As expected, a lot of the merge groups we can identify are groups that have @mit.edu, @alum.mit.edu, and/or @gmail.com addresses, which supports the theory that some users will no longer have access to the emails behind one of the accounts.
Counter to my expectations, we do have some users whose activity is somewhat distributed across different accounts, with hundreds or thousands of messages each.
However, the stats suggest that theoretically most users would be in a position to self-service if we gave them that ability.
Design constraints
The core concern (raised by @zarvox in #2810) is that merging is irreversible and destructive. Unlike virtually everything else a user can do in Jolly Roger, it permanently destroys an account. That means the authorization bar should be higher than for typical actions (including password resets, even though both are a form of account takeover). Specifically:
Bilateral consent: We should confirm intent on both sides of the merge (i.e. prove you control both accounts), not just one.
Account takeover risk: A low-friction flow makes it too easy for someone to merge away an account they don't own. Inaction-based schemes (where the merge proceeds unless you cancel within a time window) are explicitly off the table for this reason.
Proportional authorization: Merging away a ghost account (zero messages, zero guesses, never enrolled) is categorically less destructive than merging away an active account with years of history. The authorization bar should reflect this — requiring the same proof-of-ownership for both over-burdens the common case or under-protects the dangerous one.
Potential authentication schemes
Email-token (what was originally implemented in Add user account merging #2810): target user enters source email, we send a confirmation link. Source user clicks link while logged in as target. From an account takeover perspective, this is roughly equivalent to a password reset (if you can receive email at the address, you could just reset the password instead). But a password reset is reversible; merging is not, so the same level of proof may not be sufficient. This also doesn't help the subset of users who no longer have access to the email in question
Password-based: target user enters the source account's email and password. Server verifies the password hash. This is strong bilateral proof in a single session. The main gap is accounts that have no password set (either were never enrolled or only use OAuth), which is probably common for the exact accounts most likely to need merging.
Dual-login: target user initiates the merge, source user logs in separately and approves. True bilateral consent, but requires the source user to be able to log in (same gap as password-based) and a more complex flow (lots of logging out and logging back in).
Next steps
There's probably no one-size-fits-all auth scheme here, and which auth scheme we use for a given merge is likely a function of the condition of the source account.
I'd propose the following decision tree for how to authenticate:
Is the source active? (Has >X chat messages)
YES [High stakes merge]
Does the source account have a password set?
YES: -> Either password-based or dual-login
NO: -> Admin-only (Too high stakes for email-only proof)
NO [Low stakes merge]
Can the user receive email at the source address?
YES: -> Email-token verification (There's nothing to protect so this is proportionate)
NO: -> Admin-only (No way to in-band prove ownership)
UI requirements
Regardless of which authentication scheme we pick, the confirmation page should include (per @zarvox's review on #2810):
A visual indicator of which account is being kept and which is being destroyed (avatar, display name, email, linked accounts, hunt memberships)
A summary of data being transferred (N hunts, N chat messages, N guesses, etc.)
A typed confirmation phrase (similar to purgeHunt)
This is a followup to #296 and #2810.
We closed #296 when we implemented admin-initiated user merging. This tracks adding a self-service flow so users can merge their own duplicate accounts without admin involvement.
Motivation
We know users end up with multiple accounts under different email addresses. Right now an admin has to be involved for every merge. In addition to reducing the operation burden on admins, if we achieve our long-term ambitions of supporting multi-tenancy and (at least increasingly) open signups, admins will become less well-positioned to validate a merge vs. an honest user who actually owns both accounts. However, we need to make sure the authentication scheme is strong enough to prevent a malicious user from merging away an account they don't own.
Data analysis
We've been approaching this from intuition about the types of merges that we need to do, but I thought it would be good to do some actual analysis on the data.
As of today (February 2026), we have 728 user accounts. Of those:
As expected, a lot of the merge groups we can identify are groups that have @mit.edu, @alum.mit.edu, and/or @gmail.com addresses, which supports the theory that some users will no longer have access to the emails behind one of the accounts.
Counter to my expectations, we do have some users whose activity is somewhat distributed across different accounts, with hundreds or thousands of messages each.
However, the stats suggest that theoretically most users would be in a position to self-service if we gave them that ability.
Design constraints
The core concern (raised by @zarvox in #2810) is that merging is irreversible and destructive. Unlike virtually everything else a user can do in Jolly Roger, it permanently destroys an account. That means the authorization bar should be higher than for typical actions (including password resets, even though both are a form of account takeover). Specifically:
Potential authentication schemes
Email-token (what was originally implemented in Add user account merging #2810): target user enters source email, we send a confirmation link. Source user clicks link while logged in as target. From an account takeover perspective, this is roughly equivalent to a password reset (if you can receive email at the address, you could just reset the password instead). But a password reset is reversible; merging is not, so the same level of proof may not be sufficient. This also doesn't help the subset of users who no longer have access to the email in question
Password-based: target user enters the source account's email and password. Server verifies the password hash. This is strong bilateral proof in a single session. The main gap is accounts that have no password set (either were never enrolled or only use OAuth), which is probably common for the exact accounts most likely to need merging.
Dual-login: target user initiates the merge, source user logs in separately and approves. True bilateral consent, but requires the source user to be able to log in (same gap as password-based) and a more complex flow (lots of logging out and logging back in).
Next steps
There's probably no one-size-fits-all auth scheme here, and which auth scheme we use for a given merge is likely a function of the condition of the source account.
I'd propose the following decision tree for how to authenticate:
UI requirements
Regardless of which authentication scheme we pick, the confirmation page should include (per @zarvox's review on #2810):
purgeHunt)