feat(settings): module-owned settings screen with change password, biometrics, and autofill#60
Merged
Conversation
Replace the Text("SETTINGS") placeholder with the real SettingsScreen and add
the :feature:settings dependency. Additionally, remove the unused connectivity
route placeholder.
Allows getting enabled state
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
…faithful ChangePasswordUseCase now passes the recovered ARK directly to the wrapper and scrubs that single array, instead of wrapping a copy and scrubbing only the original — the copy variant left an un-zeroed ARK lingering in the heap. Root cause: FakeKeyWrapper aliased the key arrays it was given (stored and returned the same reference), unlike the real UniFFI wrapper which copies key material across the FFI boundary and returns fresh arrays. Make the fake's wrap/unwrap defensively copy so it matches real behavior and callers can scrub recovered keys safely. UnlockWithPasswordUseCaseTest relied on that aliasing via a ByteArray assertEquals (reference equality); switch it to assertContentEquals. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Add the presentation layer for the change-master-password feature: state (TextFieldState fields, field errors, password score), one-shot events, and a ViewModel that orchestrates ChangePasswordUseCase for both password and biometric reauthentication paths. Wire the missing missingDimensionStrategy and core:item / testFixtures dependencies so the settings module's unit tests resolve the flavored transitive dependency graph. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
…route Introduce SettingsGraphRoute/SettingsHomeRoute/ChangePasswordRoute and a NavGraphBuilder.settingsGraph() builder so :feature:settings owns its nested navigation graph (settings list + change-password screen). Wire the existing "Reset password" row to emit NavigateToChangePassword, which the screen forwards to onOpenChangePassword. Add the serialization plugin and navigation-compose to the module so the @serializable routes and graph builder compile. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Make the app's sealed RouteDestination extend the open core.ui.RouteDestination and drop its Settings object; retype AppDestinations.route and NavigationWrapper to the open interface so the Settings tab can be backed by the module-owned SettingsGraphRoute. Replace the single Settings composable in MainActivity with settingsGraph(...), wiring change-password navigation and up/back. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Co-authored-by: Claude Fable 5 <noreply@anthropic.com>
Add a new "Backup" section to the settings screen featuring export and import data actions. This includes updating the ViewModel, defining new UI events, and adding the required string resources.
Wipe the caller-supplied ARK and both derived KEKs in finally blocks so no key copy survives an early return or a failed re-wrap. Key derivation now suspends and runs on Dispatchers.Default instead of blocking the caller thread. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Enable requests now open the system autofill selection while disable requests stop the service and refresh state (the branches were swapped). The biometrics toggle is hidden when biometrics are unavailable, enrollment failures surface a snackbar unless the user dismissed the prompt, export/import callbacks are actually invoked, and the event channel is buffered so taps made while a prompt is open are not dropped. Adds a placeholder Connectivity route. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Move FakeAutofillServiceRepository into :feature:autofill testFixtures and add FakeAppVersionRepository to new :feature:settings testFixtures, replacing the fakes previously defined inline in SettingsViewModelTest. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
7 tasks
There was a problem hiding this comment.
Pull request overview
This PR introduces a new :feature:settings module that owns the Settings tab navigation graph and UI, and adds a change-password flow with optional biometric reauthentication. It also updates autofill/biometric plumbing and refactors account observation to use a Flow-based API.
Changes:
- Added
:feature:settingswith a module-owned settings graph, composable Settings UI DSL, and change-password screen/ViewModel. - Implemented
ChangePasswordUseCasewith key derivation off the main thread and explicit scrubbing of transient key material. - Added autofill service state querying/disable repository + updated biometric error modeling/mapping and account repository observation.
Reviewed changes
Copilot reviewed 55 out of 57 changed files in this pull request and generated 4 comments.
Show a summary per file
| File | Description |
|---|---|
| settings.gradle.kts | Includes the new :feature:settings module in the build. |
| rust/src/testFixtures/kotlin/de/davis/keygo/rust/FakeKeyWrapper.kt | Fixes test fixture key aliasing by copying key material in/out. |
| rust/src/main/kotlin/de/davis/keygo/rust/derive/KeyDeriver.kt | Makes password KEK derivation suspend and moves it to Dispatchers.Default. |
| gradle/libs.versions.toml | Adds AboutLibraries version, library, and plugin alias entries. |
| feature/settings/src/testFixtures/kotlin/de/davis/keygo/core/feature/settings/FakeAppVersionRepository.kt | Adds settings test fixture for app version lookup. |
| feature/settings/src/test/kotlin/de/davis/keygo/feature/settings/presentation/SettingsViewModelTest.kt | Adds SettingsViewModel unit tests. |
| feature/settings/src/test/kotlin/de/davis/keygo/feature/settings/presentation/component/SettingsDslTest.kt | Adds unit tests for the settings list DSL. |
| feature/settings/src/test/kotlin/de/davis/keygo/feature/settings/presentation/changepassword/ChangePasswordViewModelTest.kt | Adds ChangePasswordViewModel tests including biometric fallback flows. |
| feature/settings/src/main/res/values/strings.xml | Adds settings and change-password UI strings. |
| feature/settings/src/main/kotlin/de/davis/keygo/feature/settings/presentation/SettingsViewModel.kt | Implements SettingsViewModel combining account + OS-polled state and emitting UI events. |
| feature/settings/src/main/kotlin/de/davis/keygo/feature/settings/presentation/SettingsUiState.kt | Defines settings screen UI state model. |
| feature/settings/src/main/kotlin/de/davis/keygo/feature/settings/presentation/SettingsUiEvent.kt | Defines UI events originating from the settings UI. |
| feature/settings/src/main/kotlin/de/davis/keygo/feature/settings/presentation/SettingsScreen.kt | Wires settings UI to navigation/actions, biometric enrollment adapter, and autofill intent. |
| feature/settings/src/main/kotlin/de/davis/keygo/feature/settings/presentation/SettingsRoutes.kt | Adds a module-owned navigation graph for settings + change password. |
| feature/settings/src/main/kotlin/de/davis/keygo/feature/settings/presentation/SettingsEvent.kt | Defines one-shot events emitted by SettingsViewModel. |
| feature/settings/src/main/kotlin/de/davis/keygo/feature/settings/presentation/SettingsContent.kt | Builds the settings list sections/rows using the new DSL. |
| feature/settings/src/main/kotlin/de/davis/keygo/feature/settings/presentation/component/SettingsList.kt | Implements the LazyColumn-based settings list renderer. |
| feature/settings/src/main/kotlin/de/davis/keygo/feature/settings/presentation/component/SettingsEntry.kt | Defines settings row entry models (toggle/action/value). |
| feature/settings/src/main/kotlin/de/davis/keygo/feature/settings/presentation/component/SettingsDsl.kt | Adds the settings DSL for grouping entries into sections. |
| feature/settings/src/main/kotlin/de/davis/keygo/feature/settings/presentation/changepassword/ChangePasswordViewModel.kt | Implements change-password logic with optional biometric reauth and error handling. |
| feature/settings/src/main/kotlin/de/davis/keygo/feature/settings/presentation/changepassword/ChangePasswordState.kt | Defines change-password screen state and events. |
| feature/settings/src/main/kotlin/de/davis/keygo/feature/settings/presentation/changepassword/ChangePasswordScreen.kt | Implements change-password UI + biometric prompt integration. |
| feature/settings/src/main/kotlin/de/davis/keygo/feature/settings/domain/repository/AppVersionRepository.kt | Adds app-version abstraction for settings. |
| feature/settings/src/main/kotlin/de/davis/keygo/feature/settings/domain/model/OsState.kt | Adds OS-polled state model for settings (autofill/biometrics availability). |
| feature/settings/src/main/kotlin/de/davis/keygo/feature/settings/di/FeatureSettingsModule.kt | Registers Koin module/component scan for settings feature. |
| feature/settings/src/main/kotlin/de/davis/keygo/feature/settings/data/repository/AppVersionRepositoryImpl.kt | Implements version name retrieval via PackageManager. |
| feature/settings/consumer-rules.pro | Adds consumer ProGuard rules file for the new module. |
| feature/settings/build.gradle.kts | Adds module build config, dependencies, and enables test fixtures. |
| feature/credentials/src/main/kotlin/de/davis/keygo/feature/credentials/presentation/auth/SessionAuthState.kt | Updates biometric error mapping to the new semantic BiometricAuthError model. |
| feature/credentials/build.gradle.kts | Removes direct core.security dependency (now exposed via core.identity). |
| feature/autofill/src/testFixtures/kotlin/de/davis/keygo/core/feature/autofill/FakeAutofillServiceRepository.kt | Adds autofill repository fake for tests. |
| feature/autofill/src/main/kotlin/de/davis/keygo/feature/autofill/domain/repository/AutofillServiceRepository.kt | Introduces autofill service state/disable abstraction. |
| feature/autofill/src/main/kotlin/de/davis/keygo/feature/autofill/di/AutofillModule.kt | Provides AutofillManager via DI. |
| feature/autofill/src/main/kotlin/de/davis/keygo/feature/autofill/data/repository/AutofillServiceRepositoryImpl.kt | Implements autofill service repository via AutofillManager. |
| feature/autofill/build.gradle.kts | Removes direct core.security dependency. |
| feature/auth/build.gradle.kts | Removes direct core.security dependency and enables Kotlin serialization plugin. |
| core/security/src/test/kotlin/de/davis/keygo/core/security/presentation/BiometricAuthErrorFromTest.kt | Adds unit tests for biometric error code mapping. |
| core/security/src/main/kotlin/de/davis/keygo/core/security/presentation/BiometricCryptoControllerImpl.kt | Centralizes mapping from BiometricPrompt error codes to semantic errors. |
| core/security/src/main/kotlin/de/davis/keygo/core/security/domain/model/BiometricAuthError.kt | Reworks biometric error model into semantic cases (Declined, LockedOut, Canceled, Unknown, etc.). |
| core/identity/src/testFixtures/kotlin/de/davis/keygo/core/identity/FakeAccountRepository.kt | Updates fake repository to support observe(): Flow<Account?>. |
| core/identity/src/test/kotlin/de/davis/keygo/core/identity/domain/usecase/UnlockWithPasswordUseCaseTest.kt | Fixes array equality assertion for ARK comparison. |
| core/identity/src/test/kotlin/de/davis/keygo/core/identity/domain/usecase/ChangePasswordUseCaseTest.kt | Adds unit tests for change-password behavior and key scrubbing. |
| core/identity/src/main/kotlin/de/davis/keygo/core/identity/presentation/BiometricEnrollmentAdapterImpl.kt | Adds biometric enrollment adapter to wrap/store ARK via biometric crypto controller. |
| core/identity/src/main/kotlin/de/davis/keygo/core/identity/presentation/BiometricEnrollmentAdapter.kt | Adds enrollment adapter interface and helper for calling member-extension APIs. |
| core/identity/src/main/kotlin/de/davis/keygo/core/identity/domain/usecase/ChangePasswordUseCase.kt | Adds the change-password use case with password/biometric reauth and scrubbing. |
| core/identity/src/main/kotlin/de/davis/keygo/core/identity/domain/repository/AccountRepository.kt | Adds observe(): Flow<Account?> to account repository API. |
| core/identity/src/main/kotlin/de/davis/keygo/core/identity/domain/model/Reauthentication.kt | Adds reauthentication model for change-password paths. |
| core/identity/src/main/kotlin/de/davis/keygo/core/identity/domain/model/ChangePasswordError.kt | Adds domain error types for change-password use case. |
| core/identity/src/main/kotlin/de/davis/keygo/core/identity/domain/model/BiometricEnrollmentError.kt | Adds error types for biometric enrollment adapter. |
| core/identity/src/main/kotlin/de/davis/keygo/core/identity/data/repository/AccountRepositoryImpl.kt | Implements observe() and updates getOrNull() to use the flow. |
| core/identity/build.gradle.kts | Changes core.security dependency to api to expose security types to consumers. |
| build.gradle.kts | Adds AboutLibraries Gradle plugin alias (apply false). |
| app/src/main/kotlin/de/davis/keygo/core/presentation/model/RouteDestination.kt | Aligns app-level RouteDestination with core.ui.RouteDestination and adds Libraries destination. |
| app/src/main/kotlin/de/davis/keygo/app/presentation/MainActivity.kt | Integrates settings graph and AboutLibraries screen into the app NavHost. |
| app/src/main/kotlin/de/davis/keygo/app/presentation/component/NavigationWrapper.kt | Switches to the core.ui.RouteDestination type. |
| app/src/main/kotlin/de/davis/keygo/app/presentation/AppDestinations.kt | Points Settings tab destination to SettingsGraphRoute. |
| app/build.gradle.kts | Applies AboutLibraries plugin, adds dependency, and includes :feature:settings. |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
…ault Update the UI state directly in SettingsViewModel when disabling autofill to prevent race conditions with OS polling. Additionally, adjust FakeAutofillServiceRepository to better mirror real-world asynchronous propagation and change the default biometricsAvailable state to false.
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.
Summary
Introduces the
:feature:settingsmodule with a module-owned navigation graph backing the Settings tab, replacing the previous placeholder.ChangePasswordUseCase+ ViewModel/Screen) with password or biometric reauthentication; transient key material (ARK, derived KEKs) is zeroized infinallyblocks, and key derivation now suspends onDispatchers.Default.AutofillServiceRepositorywith system-state refresh; enable requests open the system autofill selection, disable requests stop the service.BiometricCryptoController, failures surfaced as snackbars unless user-dismissed.FakeAutofillServiceRepositoryin:feature:autofill,FakeAppVersionRepositoryin new:feature:settingsfixtures).Test plan
:rust:testDebugUnitTest,:core:identity:testDebugUnitTest,:feature:settings:testDebugUnitTestpass locally🤖 Generated with Claude Code