Skip to content

Add a users (logins) deduper - #2662

Merged
maebeale merged 3 commits into
mainfrom
maebeale/user-deduper-offer
Oct 14, 2026
Merged

maebeale merged 3 commits into
mainfrom
maebeale/user-deduper-offer

Conversation

@maebeale

@maebeale maebeale commented Oct 12, 2026 •

Copy link
Copy Markdown
Collaborator

🤖 suggested review level: 5 Inspect 🔬 deletes logins and changes the shared dedupe engine every deduper uses

Admins can now merge two logins into one — a person merge keeps both people's logins, and until now there was no way to fold the stale one away.

Users deduper (/users/dedupe_index)

  • Candidates are logins that share a person. The suggested keeper is a login that can sign in, most recently used first.
  • The pickers search every login, including unconfirmed, locked, and inactive ones, and label each with its status ("· Unconfirmed"). This uses a new virtual user_any_status search model; the shared user search is unchanged.
  • The preview compares email, admin, confirmation, and sign-in history side by side.
  • Blocked: logins of two different people (merge the people first), and merging away your own login.
  • Notes: which email stops signing in; lost admin access; a person-less keeper takes over the person.
  • Moves bookmarks, Ahoy events/visits, created_by/updated_by stamps, and paper_trail whodunnit.
  • Entry points: a Dedupe link on Users, plus a "Dedupe users" admin-home card.

Shared engine changes (affect every deduper)

  • reference_columns: — columns that point at the model without a DB foreign key. About 20 user stamp columns (grants, staff_tags, topic_subscriptions, …) and ahoy_events.user_id have none.
  • Self-references on the model's own table now follow the keeper. This also covers organizations.parent_id and event_registrations.transferred_from_registration_id. The keeper's own reference to the duplicate clears instead of pointing at itself.
  • A table that references the model twice gets one preview row per column ("Grants (created by)"). Before, index_by(label) hid one of them.
  • dedupe_update_keep/dedupe_perform now accept only editable_columns when a config lists them. Before, they accepted every column (e.g. encrypted_password, super_user).
  • The tracked dedupe.* event filters credential columns out of deleted_record. Emails are still kept for the audit trail.
  • New view options record_label (two logins of one person share a name) and read_only_columns.

🤖 Generated with Claude Code

@maebeale maebeale changed the title Add a user (login) deduper Add a users (logins) deduper Oct 12, 2026
@maebeale
maebeale force-pushed the maebeale/user-deduper-offer branch from 105b4b0 to 2bd06c5 Compare October 13, 2026 01:27
@maebeale
maebeale marked this pull request as ready for review October 13, 2026 01:46
@maebeale maebeale changed the title Add a users (logins) deduper JM: Add a users (logins) deduper Oct 13, 2026
@maebeale

Copy link
Copy Markdown
Collaborator Author

@jmilljr24 we need this to resolve people merges that create a person w multiple users

@maebeale
maebeale force-pushed the maebeale/user-deduper-offer branch from d08f71a to f642bec Compare October 13, 2026 02:07
@maebeale
maebeale requested a review from jmilljr24 October 13, 2026 14:18
@maebeale
maebeale force-pushed the maebeale/user-deduper-offer branch from f642bec to 1898192 Compare October 13, 2026 14:20
@maebeale maebeale changed the title JM: Add a users (logins) deduper Add a users (logins) deduper Oct 14, 2026
maebeale and others added 3 commits October 13, 2026 20:46
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
A person merge keeps both people's logins, so a person can end up with two.
Admins had no way to fold the stale one away. Users now plug into the shared
deduper: candidates are logins sharing a person, the most recently used is the
suggested keeper, and logins of different people (or your own) can't be merged.

The engine needed a few generic pieces for logins: reference columns without a
DB foreign key (created_by/updated_by stamps, ahoy user_id), self-references on
the model's own table, per-column labels when a table references the model
twice, an editable-column allowlist on save, and credential filtering in the
tracked deleted record.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Duplicate logins are often the unconfirmed or locked ones, and the shared user
search only returns logins with access, so admins couldn't pick them by hand.
The deduper's pickers now search every login and label each with its status.
The suggested keeper also prefers a login that can sign in, so a stale
unconfirmed login isn't suggested just because it was touched last.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
@maebeale
maebeale force-pushed the maebeale/user-deduper-offer branch from 1898192 to 5ad6eca Compare October 14, 2026 00:47
@maebeale
maebeale merged commit 8b9458f into main Oct 14, 2026
3 checks passed
@maebeale
maebeale deleted the maebeale/user-deduper-offer branch October 14, 2026 02:13
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.

2 participants