Merged
Conversation
e9f1173 to
506a924
Compare
There was a problem hiding this comment.
Pull request overview
This PR introduces device-to-device migration support by leveraging platform backups/transfers to restore account state, then re-initializing passkeys on the new device using a marker-folder mechanism to ensure the process runs once per account.
Changes:
- Add multiplatform file utilities (
expect/actual) to create/check a marker folder and per-account marker files. - Add a “backed up accounts” handling path that re-authenticates with the restored passkey, registers a new passkey, persists a fresh token, and updates account status.
- Enable Android backup/device-transfer rules and turn
android:allowBackupon, excluding only the marker folder.
Reviewed changes
Copilot reviewed 15 out of 15 changed files in this pull request and generated 8 comments.
Show a summary per file
| File | Description |
|---|---|
| multiplatform-lib/src/commonMain/kotlin/utils/FileUtils.kt | Declares common expect APIs for marker folder/file operations. |
| multiplatform-lib/src/androidMain/kotlin/utils/FileUtils.android.kt | Android implementations of marker folder/file operations in filesDir. |
| multiplatform-lib/src/appleMain/kotlin/utils/FileUtils.apple.kt | Apple implementations using Application Support directory (+ exclude from iCloud backup). |
| multiplatform-lib/src/appleMain/kotlin/internal/utils/FileUtils.kt | Adds helper to resolve Application Support directory on Apple platforms. |
| multiplatform-lib/src/commonMain/kotlin/internal/managers/MigrationManager.kt | Adds backed-up account re-initialization (re-register passkey + refresh token). |
| multiplatform-lib/src/commonMain/kotlin/internal/AuthenticatorFacadeImpl.kt | Calls backed-up account handler before legacy migration; writes marker files on addAccounts. |
| multiplatform-lib/src/commonMain/kotlin/internal/managers/AuthenticatorManager.kt | registerPasskey now returns keyId; token retrieval supports explicit keyId; adds keyId getter. |
| multiplatform-lib/src/commonMain/kotlin/internal/KeyManager.kt | Updates KeyPairManager API to search by predicate. |
| multiplatform-lib/src/commonMain/kotlin/internal/KeyPairManagerImpl.kt | Updates expect declaration for new predicate-based lookup. |
| multiplatform-lib/src/androidMain/kotlin/internal/KeyPairManagerImpl.android.kt | Implements predicate-based keyId lookup; small refactor naming. |
| multiplatform-lib/src/appleMain/kotlin/internal/KeyPairManagerImpl.apple.kt | Implements predicate-based keyId lookup in Keychain scanning logic. |
| app/src/main/res/xml/data_extraction_rules.xml | Enables broad device-transfer inclusion of files+db, excludes marker folder. |
| app/src/main/res/xml/backup_rules.xml | Enables broad Auto Backup (API<31) inclusion of files+db, excludes marker folder. |
| app/src/main/AndroidManifest.xml | Enables android:allowBackup="true" and hooks up the above rule files. |
Comments suppressed due to low confidence (1)
multiplatform-lib/src/commonMain/kotlin/internal/managers/AuthenticatorManager.kt:120
- The delete predicate
"-$passkeyId-" in itwon’t match iOS Keychain tags generated as"$userId-$keyId"(no trailing-). As a result, passkeys may never be deleted on iOS. Align the predicate with the platform storage naming/tagging scheme (e.g., exact match orstartsWith("$userId-$passkeyId")).
suspend fun removeAccount(token: String, userId: Long) {
val passkeyId = keyPairManager.findKeyIdFor { it.startsWith("$userId-") }.firstOrNull()
if (passkeyId != null) {
// If we have a passkey for this account, revoke it against the backend and delete it
webAuthnRepository.deletePasskey(token, passkeyId)
val _ = keyPairManager.deleteKeysMatching { "-$passkeyId-" in it }
}
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
3f41740 to
c5c9f3e
Compare
314d212 to
dd58255
Compare
# Conflicts: # multiplatform-lib/src/commonMain/kotlin/internal/AuthenticatorFacadeImpl.kt # multiplatform-lib/src/commonMain/kotlin/internal/managers/AuthenticatorManager.kt # multiplatform-lib/src/commonMain/kotlin/internal/managers/MigrationManager.kt
…ting two sets of files to handle migration account by account
This avoids having 2 files with the exact same name (FileUtils.kt), and centralizes this code.
Otherwise, the app will crash after restoring if there's a network or other kind of communication issue.
265260a to
d7c4974
Compare
LouisCAD
approved these changes
Apr 28, 2026
|
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.



No description provided.