fix(mobile): dedupe host cards by pinned public key on re-pair (STA-1840)#8833
Conversation
…840)
Re-pairing an already-paired desktop minted a fresh host-${now} id and
appended a second host row, because persistHost dedups only on id and the
pairing coordinator always mints a new id. The desktop CTA to re-scan for
relay made this reachable in normal use, so one desktop showed as multiple
hosts.
Reuse the existing host id and name when the desktop pinned publicKeyB64 is
already stored, so the pairing merges into the existing card. Every downstream
write (journal, credential bundle, saveHost) then keys to the same id and
persistHost updates in place. A new desktop key falls through to a fresh id.
|
Caution Review failedThe pull request is closed. ℹ️ Recent review info⚙️ Run configurationConfiguration used: Repository UI Review profile: CHILL Plan: Pro Run ID: 📒 Files selected for processing (2)
📝 WalkthroughWalkthroughAdds durable host identity resolution by pinned public key, allowing pre-profile pairing to reuse existing host IDs and names or generate new identities. Host persistence now deduplicates matching records and cleans stale overlays, token-cache entries, and credentials. Relay overlay removal supports batches and avoids unchanged storage writes. Successful pairing closes cached host clients before navigation. Tests cover lookup, re-pairing, deduplication, cleanup, and storage behavior. 🚥 Pre-merge checks | ✅ 3 | ❌ 2❌ Failed checks (2 warnings)
✅ Passed checks (3 passed)
✨ Finishing Touches📝 Generate docstrings
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
9a88386 to
c7c0dca
Compare
…ects Re-pairing the same desktop now reuses its existing host id (STA-1840 dedup), so a client cached under that id keeps the stale endpoint/relay. A re-pair meant to switch a host onto relay (the exact 'connect from anywhere' case) would not take effect until an app restart. Close the host's client on pairing success so the destination screen opens a fresh client with the newly-paired profile — mirroring the removeHost() path that already refreshes the client on re-pair. A brand-new host has no cached entry, so this is a no-op there.
Summary
Re-pairing a desktop that was already paired created a duplicate host card on mobile (the STA-1840 "multiple hosts" symptom). The pairing coordinator always minted a fresh
host-${now}id, andpersistHostdedups only on that id, so a second row was appended for the same physical desktop. The "connect from anywhere" CTA on an unreachable direct-only host nudges the user to re-scan, which made this reachable in normal use.Pairing now resolves the durable host identity by the desktop's pinned
publicKeyB64— the desktop's stable, cryptographically-unique identity key — and reuses the existing host's id and name so the pairing merges into the existing card. Every downstream pairing artifact (relay journal, credential bundle,saveHost) then keys to the same id. A genuinely new desktop key falls through to a fresh id/name, so distinct desktops still get distinct cards.What this fixes (addresses all findings from review)
closeHost) so the destination screen opens a fresh client with the newly-paired profile — mirroring the existingremoveHost()refresh path. No-op for a brand-new host.Changes
host-store.ts:resolvePairingHostIdentity()(strict single read: reuse existing id/name by public key, else name a new host);persistHostcollapses same-key duplicate rows and cleans their credentials/overlays; clears the relay overlay on a direct-only save that reuses an id.mobile-relay-host-overlay-store.ts: batchedremoveMobileRelayHostOverlays; skip the storage write when nothing changed.pre-profile-pairing-coordinator.ts: resolve the host identity up front and thread it through the whole flow.pair-confirm.tsx/pair-scan.tsx:closeHost(hostId)on pairing success so a reused id reconnects on the new profile.Screenshots
No visual change — pairing-logic only. Behavior: re-pairing the same desktop updates the one existing row (and reconnects it) instead of adding a second row.
Testing
tsc --noEmit(mobile) — cleanoxlint/oxfmt --check(changed files) — cleanvitest run— full mobile suite: 242 files, 1,719 passed, 2 skipped. New/updated cases cover: resolve-by-key with one durable read, name-from-same-read, fail-closed on unreadable storage, collapse already-persisted duplicates, clear stale relay on direct-only re-pair, no-touch on a new direct host, batched/skip-no-op overlay writes.Notes
Mobile only — does not touch the desktop build. This is the P1-1 item from the v1.4.142 release audit. It does not address the separate relay-pairing P2s (offer-TTL, recovery-resurrect, clear-after-commit).