Skip to content

bug: an interrupted ring pubky pick leaves a half-saved session #1363

Description

@ovitrif

Refs:

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): adoptRingIdentity runs in the choice screen's viewModelScope. Pressing back cancels it after pubkyService.signIn() has saved PAYKIT_SESSION and SHARED_PUBKY_SOURCE. runSuspendCatching rethrows the CancellationException, so the onFailure cleanup never runs, _publicKey is never set and the pending profile setup flag is never written. The header shows the user signed out; after a relaunch initialize() 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 / signUp call activateBootstrapResult, which saves PAYKIT_SESSION, removes the local PUBKY_SECRET_KEY for an adopted Ring pubky, then calls handle.initialize(). If that throws, the adoption failure handler deletes only SHARED_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

  1. Delete the profile, open Pubky Choice with a Ring pubky listed.
  2. Tap the Ring pubky, then press back before it finishes loading.
  3. See the header signed out.
  4. 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 MainActivityPubkyAuth alias gets disabled and is only recomputed when publicKey changes, so pubkyauth:// 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

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

Labels

No labels
No labels

Type

Projects

No projects

    Milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions