Skip to content

feat: reuse Pubky Ring identities#1109

Draft
Jasonvdb wants to merge 3 commits into
codex/970-pubky-paykit-ui-parityfrom
codex/shared-pubky-ring
Draft

feat: reuse Pubky Ring identities#1109
Jasonvdb wants to merge 3 commits into
codex/970-pubky-paykit-ui-parityfrom
codex/shared-pubky-ring

Conversation

@Jasonvdb

@Jasonvdb Jasonvdb commented Jul 24, 2026

Copy link
Copy Markdown
Contributor

Important

Dependencies and merge/release order

  1. Publish the final legacy Pubky Ring v1.17 sunset build.
  2. Merge the Bitkit parent UI stacks before their consumers: Bitkit iOS #636, and Bitkit Android #1084 followed by #1097.
  3. Complete the cross-repository release gates: provision the iOS shared Keychain group/profiles and confirm the Android Play-installed signing-certificate model.
  4. Merge and release Pubky Ring #342 with the production-compatible signing certificate.
  5. Rebase and merge the consumer PRs, Bitkit iOS #643 and this PR, onto their merged parents, then release them after Ring.

This branch is stacked on #1097, which depends on #1084; the iOS parent does not block this branch. At runtime, this PR and Ring #342 are counterparts: Ring-to-Bitkit requires Ring to ship first, while Ring's reverse “Use from Bitkit” flow becomes available after this consumer ships its Bitkit-owned provider. This PR must remain draft until final Play-signed Ring and Bitkit artifacts pass installed interoperability tests.

Description

This PR:

  1. Discovers source-owned Pubky Ring identities through a signature-protected, read-only provider and presents them in the redesigned Profile choice screen.
  2. Lets the user explicitly connect one Ring profile while reading its credential only just in time; Bitkit persists a source reference and session, never the borrowed private key.
  3. Exposes Bitkit-owned Pubky identities to the exact Ring package through a signature permission, exact caller/UID checks, and runtime signing-certificate verification.
  4. Revalidates borrowed identities on initialization, foreground, session refresh, and authenticated operations, disconnecting locally when the source disappears.
  5. Serializes identity lifecycle changes and fails closed on malformed protocol data, key mismatches, conflicting provenance, incomplete cleanup, and unsafe secret replacement.

The versioned provider protocol carries only a canonical 52-character bare Pubky for discovery and a 64-character lowercase secret-key encoding on the explicitly selected credential route. Borrowed credentials are excluded from app-private key storage and backups.

Migration is deliberately non-destructive: an existing Bitkit private key remains the canonical source, and sharing is enabled only after deriving and verifying the same public key. Export state is a separate, fail-closed gate. Cleanup disables sharing first, while quarantine markers preserve ambiguous private state for recovery instead of silently reclassifying or deleting it.

The provider uses dynamic Bitkit authorities for build variants while keeping the production source identity canonical. Dev and testnet merged manifests resolve to their expected authorities and signature permissions.

Production release still requires confirming that the Bitkit CI keystore certificate is the Play-installed app-signing certificate rather than only an upload certificate. If Play uses a distinct app-signing key, Ring's upload signing and installed-certificate pinning must be handled separately, and the Play-generated Ring APK must be verified against the installed Bitkit certificate.

Preview

An independent six-screen audit accounts for every supplied reference. The new Profile choice screen matches its reference with 97% certainty. The audit found and corrected a pre-existing FOUND CONTACTS copy/layout mismatch in Import Overview; its final native render is within 0–2 px of the measured reference. The other four screens remain unchanged parent implementations with matching static copy and structure. OS chrome and dynamic identity/avatar content are excluded.

QA Notes

Manual Tests

  • 1. Same-certificate Pubky Ring install with profiles → Bitkit → Profile: each Ring profile appears beside Create Profile with the Figma layout.
  • 2. Profile → select a Ring profile: Bitkit connects that exact identity and continues to contact import without persisting its private key.
  • 3. Existing active or recoverable Bitkit profile → relaunch/update: no Ring profile silently replaces it, and the Bitkit-owned identity becomes available to Ring.
  • 4. Connected Ring profile → terminate and relaunch Bitkit: the session restores only while the same provider identity remains available.
  • 5. Connected Ring profile → remove the identity from Ring or uninstall Ring → foreground Bitkit: Bitkit disconnects the borrowed identity locally.
  • 6. Existing pre-sharing Bitkit identity → update: the private source remains intact and Ring can read it only after export validation.
  • 7. Sign out, delete profile, or wipe wallet: Bitkit disables the provider before clearing applicable local identity state.
  • 8. regression: Borrowed Ring profile → approve Pubky Auth: approval retrieves and verifies the source key just in time.
  • 9. Install mismatched-certificate Ring build → Profile: no identities are exposed or accepted.

Automated Checks

  • SharedPubkyContractTest.kt, SharedPubkyManifestTest.kt, and SharedPubkyProviderTest.kt cover strict wire parsing, source ownership, provider rows, export gating, and manifest security.
  • PubkyRepoTest.kt and PaykitSdkServiceTest.kt cover adoption, source loss, lifecycle serialization, quarantine recovery, backup exclusion, and non-persistence of borrowed credentials.
  • PubkyChoiceViewModelTest.kt covers discovery, profile resolution, explicit selection, import routing, and failures.
  • AppViewModelSendFlowTest.kt verifies foreground source validation reaches the Pubky repository.
  • Local: fixture-free just compile, just lint, and all 1,709 unit tests pass with zero failures, errors, or skips; git diff --check is clean.
  • Dev and testnet merged manifests pass authority/permission inspection. Local mainnet manifest generation remains blocked by the existing google-services.json lacking a to.bitkit Firebase client; placeholder expansion itself is deterministic.
  • Final Play-signed two-app interoperability remains a release gate.

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.

1 participant