fix(passkeys): make Git sync durable and recover remote credentials on miss - #104
Conversation
…ity destruction Replace lifecycleScope-based git sync in AppPasskeyProviderActivity with a PasskeySyncWorker (CoroutineWorker) that runs independently of the activity lifecycle. The previous approach launched sync in lifecycleScope and immediately called finish(), which cancelled the coroutine before the git operation could complete. The worker performs git add/commit/pull/push directly using JGit with non-interactive SSH/HTTPS authentication. It gracefully fails when authentication requires user interaction (biometric prompts, host key verification dialogs) and logs the failure. Fixes #98
Maintainability ReviewReviewed the branch for maintainability issues. Applied two high-value fixes: Applied now1. SSH connection leak in
2.
Recommend, but defer3. Duplicated SSH session/process classes (refactor)
Do not pursue
|
Updated approachReplaced the lifecycle-scoped Changes:
UX impact:
Resolves: #98 This PR was generated by Forkline — AI-powered code contributions. |
|
✅ Fix pushed: Fixed the CI failure. The issue was a flaky test in Changes made:
The fix has been pushed to |
158fbb1 to
4d3213d
Compare
|
⏸️ CI Auto-Fix paused A user commit was detected after an automated fix. CI auto-fix is now paused To resume CI auto-fix, use the |
Summary
Fixes #98 by moving passkey auto-sync out of
AppPasskeyProviderActivity.lifecycleScopeand into durable, one-shot WorkManager work, and also makes stale devices recover passkeys that already exist in remote Git during Credential Manager discovery.The normal path remains local and fast. Network I/O is only attempted when the complete local credential lookup produces no matching candidate.
Outbound sync
PasskeySyncWorkerinstead of launching Git work in the provider Activity lifecycle.APPEND_OR_REPLACE, so new ceremonies do not cancel an in-flight Git operation.PasswordRepositoryafter process death.PasskeyGitSyncEngineperforms headless add/commit/pull/push using stored non-interactive credentials.PullResult.isSuccessful, including rebase outcomes.Remote credential miss recovery
When Credential Manager asks APS for a passkey:
fido2/<rp>/<credential-id>.gpgpath,IndexedPasskeyStorageaddresses that exact file directly: it resolves its source version, decrypts only that file's metadata, validates credential ID and RP/path binding, and upserts it. A deleted path removes the corresponding indexed entry.A full index invalidation/rebuild is retained only as a correctness fallback for merge conflicts,
.gpg-idchanges, unknown/unavailable source versions, duplicate credential IDs, malformed or inconsistent passkey paths, or other incremental-reconciliation failures.UX and concurrency
CancellationSignalcancels the provider request coroutine and suppresses callbacks after Android no longer needs the result.GitOperationCoordinator, preventing concurrent JGit access to the same worktree.Tests
.gpg-idchanges do.Resolves #98