Skip to content

feat: upgrade paykit auth to rc50 - #697

Open
ben-kaufman wants to merge 3 commits into
masterfrom
codex/paykit-rc50-auth
Open

feat: upgrade paykit auth to rc50#697
ben-kaufman wants to merge 3 commits into
masterfrom
codex/paykit-rc50-auth

Conversation

@ben-kaufman

Copy link
Copy Markdown
Contributor

This PR:

  1. Upgrades Paykit from 0.1.0-rc46 to 0.1.0-rc50.
  2. Adopts app-scoped Pubky grants using Bitkit's stable client ID.
  3. Revokes Bitkit's grant on normal sign-out while preserving local state when remote revocation fails.
  4. Restricts local-only session forgetting to destructive reset and backup-replacement flows.

Description

Paykit rc50 introduces the new Pubky grant lifecycle from paykit-rs #143 and paykit-rs #146.

Bitkit now identifies itself as bitkit.to on mainnet and staging.bitkit.to elsewhere. 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

  • 1. Pubky profile → Sign Out while online: Bitkit signs out and returns to the disconnected profile state.
  • 2. Pubky profile → interrupt network access → Sign Out: Bitkit shows an error and keeps the profile and private Paykit state; restore network access and retry successfully.
  • 3. Pubky auth → approve another app → Sign Out of Bitkit: Bitkit's session is revoked while the other app remains authorized.
  • 4. 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.
  • Focused iOS auth/configuration suite passed: 44 tests, 0 failures, using Paykit 0.1.0-rc50.
  • Dependency module-cache clean and git diff --check passed.
@greptile-apps

greptile-apps Bot commented Aug 31, 2026

Copy link
Copy Markdown

Greptile Summary

The PR upgrades Paykit to rc50 and adopts app-scoped Pubky grants with environment-stable Bitkit client IDs.

  • Replaces local session clearing with explicit remote revocation for ordinary sign-out and completed authentication cleanup.
  • Introduces local-only session forgetting for destructive reset and backup replacement.
  • Updates session bootstrap/provider configuration and adds focused authentication and client-ID tests.
  • Sign-out currently removes payment-sharing state before revocation is confirmed, undermining the intended retry behavior when revocation fails.

Confidence Score: 4/5

The 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

Important Files Changed

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
Loading

Reviews (1): Last reviewed commit: "feat: upgrade paykit auth to rc50" | Re-trigger Greptile

Comment on lines +774 to +777
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()

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P1 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

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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 ovitrif left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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)

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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?

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

Labels

None yet

2 participants