[LWDM] fix(lld): preserve userId during identities migration for returning users#18770
[LWDM] fix(lld): preserve userId during identities migration for returning users#18770gre-ledger wants to merge 2 commits into
Conversation
Web Tools Build Status
|
Rsdoctor Bundle Diff AnalysisFound 7 projects in monorepo, 7 projects with changes. 📊 Quick Summary
📋 Detailed Reports (Click to expand)📁 desktop-mainPath:
📁 desktop-preloaderPath:
📁 desktop-rendererPath:
📁 desktop-webviewDappPreloaderPath:
📁 desktop-webviewPreloaderPath:
📁 desktop-workersPath:
📁 mobilePath:
Generated by Rsdoctor GitHub Action |
There was a problem hiding this comment.
Pull request overview
Fixes Ledger Live Desktop’s identities boot migration to prevent returning users from being assigned a fresh analytics userId when upgrading from a state where app.identities exists but only contains deviceIds (deviceId rollout), by recovering the legacy userId (and datadogId) from legacy storage before initializing the identities slice.
Changes:
- Exported
shouldUsePersistedIdfrom@ledgerhq/client-ids/storeso “usable id” logic is shared across consumers. - Updated desktop
initIdentitiesto merge legacyuserId/datadogIdinto persisted identities when the persisted ids are unusable. - Updated/added Jest tests to cover the regression and a localStorage fallback path; added a changeset for patch releases.
Reviewed changes
Copilot reviewed 4 out of 4 changed files in this pull request and generated 1 comment.
| File | Description |
|---|---|
libs/client-ids/src/store/slice.ts |
Exports the id-usability helper so desktop init logic can align with slice behavior. |
apps/ledger-live-desktop/src/renderer/helpers/identities.ts |
Recovers legacy ids during boot when persisted ids are missing/unusable, while preserving persisted deviceIds/push state. |
apps/ledger-live-desktop/src/renderer/helpers/identities.test.ts |
Reworks regression coverage to assert legacy id recovery; adds localStorage-only recovery test. |
.changeset/identities-userid-migration-fix.md |
Declares patch bumps and documents the migration fix behavior. |
feb073a to
76fe619
Compare
…sers When app.identities was created by the deviceId rollout (deviceIds only, no userId), boot generated a new userId instead of recovering the legacy app.user/localStorage id, making returning users appear as new in Segment and Braze. Recover the legacy id when the persisted one is unusable; only generate a fresh id when none exists. Mirrors the mobile precedence. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
76fe619 to
7817aff
Compare
In the persisted-identities branch, legacy ids were only consulted when the persisted userId was unusable, so a returning user with a valid persisted userId but missing/invalid datadogId always got a freshly generated one even when app.user.datadogId existed. Consult readLegacyIds() when either id is unusable and fill only the missing piece, matching the PR intent and mobile. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
|
|



✅ Checklist
npx changesetwas attached.app.identitieswith deviceIds but nouserId(deviceId rollout) whileapp.user.idexists — verify Settings → Developer → userId still matches the legacy id after upgrade.📝 Description
Since LLD 2.145.0, a migration bug can assign a new
userIdto existing users on upgrade, so returning users appear as new in Segment (and Braze, which shares the id).Root cause: desktop
initIdentitiesbranched on the mere existence ofapp.identities. Records created by the earlier deviceId rollout (~2.140) containdeviceIdsonly — nouserId— so the slice generated a fresh UUID and the legacyapp.user.idwas never read. The wrong id was then persisted, making it permanent.Fix: when the persisted
userIdis unusable, recover the legacy id fromapp.user(thenlocalStorage.userId) and merge it onto the persisteddeviceIds/push state. A fresh id is only generated when no legacy id exists anywhere. This mirrors the precedence mobile already uses.datadogIdis recovered the same way.shouldUsePersistedIdis now exported from@ledgerhq/client-ids/storeso the helper and the slice agree on what counts as a usable id.Tests: the previous test that encoded the bug as intentional ("persisted takes precedence") is rewritten to assert the legacy id is recovered; a localStorage-fallback variant is added. Both new tests were confirmed to fail against the old code before the fix.
❓ Context