Repository navigation
bug: an interrupted ring pubky pick leaves a half-saved session #1363
Description
Refs:
- feat: share pubky keys with pubky ring #1329
- feat: share pubky keys with pubky ring #1329 (comment)
- feat: share pubky keys with pubky ring #1329 (review)
What happened?
Picking a Pubky Ring pubky on Pubky Choice can stop halfway and leave a session behind that the app doesn't show. Two paths lead there, both raised in the review of #1329 at 3ff19f5.
- Back before the pick finishes (@jvsena42, and @piotr-iohk's first finding):
adoptRingIdentityruns in the choice screen'sviewModelScope. Pressing back cancels it afterpubkyService.signIn()has savedPAYKIT_SESSIONandSHARED_PUBKY_SOURCE.runSuspendCatchingrethrows theCancellationException, so theonFailurecleanup never runs,_publicKeyis never set and the pending profile setup flag is never written. The header shows the user signed out; after a relaunchinitialize()restores the session and the user is signed in as the abandoned pubky, with no profile setup or contact import. - Activation fails after the session is saved (@piotr-iohk's second finding):
PaykitSdkService.signIn/signUpcallactivateBootstrapResult, which savesPAYKIT_SESSION, removes the localPUBKY_SECRET_KEYfor an adopted Ring pubky, then callshandle.initialize(). If that throws, the adoption failure handler deletes onlySHARED_PUBKY_SOURCE, leaving a saved session with neither a local key nor the Ring reference to sign with.
iOS (synonymdev/bitkit-ios#774) handles both paths differently: its adoption runs in an unstructured Task, and a failed adoption discards the session before clearing the reference.
Expected behavior
An interrupted or failed pick ends in one consistent state: either the pubky is picked and its profile setup can resume after a relaunch, or the user is signed out with no session and no Ring reference left behind.
Steps to Reproduce
- Delete the profile, open Pubky Choice with a Ring pubky listed.
- Tap the Ring pubky, then press back before it finishes loading.
- See the header signed out.
- Relaunch Bitkit: it restores the session and shows the abandoned pubky as signed in, without Create Profile.
Logs / Screenshots / Recordings
From @jvsena42's repro:
Upserted value for key 'SHARED_PUBKY_SOURCE'
Upserted value for key 'PAYKIT_SESSION'
(no "Adopted ring identity" line)
... relaunch ...
Restored paykit session for 'pubkyrc…ib4re3o'
Repro video: https://github.com/user-attachments/assets/a85cbded-aa0e-4565-bfc5-4fa6e84d2dec
Bitkit Version
#1329 at 3ff19f5 (not released)
Device / OS
Android
Reproducibility
Always, when back is pressed after sign-in and before the pick finishes; the activation path needs handle.initialize() to fail.
Additional context
Suggested fix from the review: run the part of adoptRingIdentity that writes to the keychain and signs in under NonCancellable, as signOut() does, or clean up when the pick is cancelled; on activation failure, remove both the session and SHARED_PUBKY_SOURCE. Add regression tests that cancel the pick after sign-in succeeds and that throw from activation after the session is saved.
Also raised by @jvsena42 in the same comment, lower priority:
- When Ring is unavailable at launch, the
MainActivityPubkyAuthalias gets disabled and is only recomputed whenpublicKeychanges, sopubkyauth://links don't reach Bitkit after Ring comes back until the app restarts. - The source-loss warning redacts the whole reference, so the log shows
'app.pub…ib4re3o'.
Activity