feat: upgrade paykit auth to rc50 - #697
Conversation
Greptile SummaryThe PR upgrades Paykit to rc50 and adopts app-scoped Pubky grants with environment-stable Bitkit client IDs.
Confidence Score: 4/5The PR should not merge until failed grant revocation can leave the retained authenticated account's payment-sharing state intact for a safe retry. Normal sign-out deletes and persists endpoint state before attempting the operation allowed to fail, so the advertised failure recovery retains the identity but not its prior payment configuration. Files Needing Attention: Bitkit/Managers/PubkyProfileManager.swift
|
| Filename | Overview |
|---|---|
| Bitkit/Managers/PubkyProfileManager.swift | Coordinates the new revoke/forget lifecycle, but normal sign-out mutates payment state before revocation succeeds and can leave a retained account partially dismantled. |
| Bitkit/Services/PubkyService.swift | Adopts rc50 client-scoped bootstrap/session access and exposes explicit revoke and local-forget operations. |
| BitkitTests/PubkyProfileManagerTests.swift | Updates cancellation and backup-replacement tests, but does not cover normal sign-out when endpoint cleanup succeeds and revocation fails. |
| BitkitTests/PaykitSdkClientConfigTests.swift | Verifies the network-dependent stable Bitkit client ID and existing Pubky client configuration. |
| Bitkit.xcodeproj/project.xcworkspace/xcshareddata/swiftpm/Package.resolved | Resolves Paykit 0.1.0-rc50 at the updated revision. |
Sequence Diagram
sequenceDiagram
participant U as User
participant M as PubkyProfileManager
participant P as Paykit endpoint state
participant G as Pubky grant
U->>M: Sign out
M->>P: Remove private/public endpoints
P-->>M: Cleanup persisted
M->>G: Revoke Bitkit grant
G-->>M: Revocation error
M-->>U: Show error and remain authenticated
Note over U,P: Account remains active with payment sharing already dismantled
Reviews (1): Last reviewed commit: "feat: upgrade paykit auth to rc50" | Re-trigger Greptile
| try await Self.removePrivatePaykitEndpoints(context: "PubkyProfileManager.signOut") | ||
| } | ||
| await Self.removePublicPaykitEndpointsBestEffort(context: "PubkyProfileManager.signOut") | ||
| do { | ||
| try await PubkyService.signOut() | ||
| } catch { | ||
| Logger.warn("Server sign out failed, forcing local sign out: \(error)", context: "PubkyProfileManager") | ||
| } | ||
| await Self.clearLocalState() | ||
| try await PubkyService.signOut() |
There was a problem hiding this comment.
Revocation failure dismantles payment state
When endpoint cleanup succeeds but grant revocation fails, this ordering leaves the user authenticated after already deleting private payment lists and disabling public sharing, so retrying sign-out cannot restore the retained account's previous payment configuration.
Knowledge Base Used: Contacts and Pubky identity
There was a problem hiding this comment.
Fixed in 65ec4c8. If cleanup or grant revocation fails, Bitkit now marks the enabled Paykit state for reconciliation. The next retry republishes public endpoints, restores the private-only receiver marker, and rebuilds private contact endpoints instead of leaving the authenticated identity with its payment state removed. Added regression coverage; all 73 focused Paykit/Pubky tests pass.
ovitrif
left a comment
There was a problem hiding this comment.
The restore-on-retry path for private contact endpoints is untested. After a failed sign-out the account stays authenticated with sharing still enabled, and nothing would fail if that publishingEnabledKey check were inverted so retry kept deleting those endpoints.
| let savedKeys = Set(normalizedSavedContactKeys(publicKeys)) | ||
| let isFullCleanupPending = UserDefaults.standard.bool(forKey: Self.cleanupPendingKey) | ||
| if isFullCleanupPending, | ||
| UserDefaults.standard.bool(forKey: Self.publishingEnabledKey) |
There was a problem hiding this comment.
The new restore branch in retryPendingEndpointReconciliation is what turns a failed sign-out back into working private contact endpoints: cleanup is still pending, sharing is still enabled, so it calls prepareSavedContacts instead of removing lists. testFailedSignOutMarksEnabledPaykitStateForReconciliation only checks that the pending flags are set, and testPendingReconciliationRestoresPrivateOnlyReceiverMarker only covers the public marker mode. Nothing would fail if this publishingEnabledKey check were inverted and a still-enabled account kept taking the deletion path. Could we extract that restore-versus-remove decision and assert it the same way pendingReconciliationMode is tested?
This PR:
0.1.0-rc46to0.1.0-rc50.Description
Paykit rc50 introduces the new Pubky grant lifecycle from paykit-rs #143 and paykit-rs #146.
Bitkit now identifies itself as
bitkit.toon mainnet andstaging.bitkit.toelsewhere. Normal sign-out remotely revokes only Bitkit's current grant. If revocation cannot be confirmed, the profile and private Paykit state remain available so the user can retry instead of silently leaving a valid grant behind.Completed Ring authentication that is later canceled, and identity creation that fails after activating a session, also attempt secure revocation. Explicit app reset and backup replacement use rc50's local-only forget operation.
No migration is included because this auth model has not shipped in Bitkit.
Linked Issues/Tasks
Screenshot / Video
N/A — no visual changes.
QA Notes
Manual Tests
regression:restore a wallet backup with different Pubky state: the previous local session is forgotten and the backup identity is installed.Automated Checks
PubkyProfileManagerTests.swift: covers canceled completed authentication revocation and backup session replacement.PaykitSdkClientConfigTests.swift: covers the stable Bitkit client ID and Pubky client configuration.0.1.0-rc50.git diff --checkpassed.