Files
hugo b54636b7bc
Android ARM verification / rust (push) Failing after 50m14s
Android ARM verification / android (push) Failing after 8s
Dependency security audit / rustsec (push) Failing after 23s
Complete Android parity and security audit (#111)
2026-10-15 13:40:50 +02:00

18 KiB
Raw Permalink Blame History

Android parity and issue ownership

Contract for #88, reviewed 2026-10-15 against apple/Sources/App/IronStorageApp.swift, apple/Sources/AutoFill/CredentialProviderViewController.swift, crates/apple/src/lib.rs, and crates/storage/src/mobile*.rs. See architecture.md for support, dependency, security and update policy.

Status: implementation issues #89–#110 are delivered. The #111 audit maps each capability to current Android components and executable checks below. audit.md records current results, dependency decisions and explicit runtime limits. Test names identify coverage; opt-in tests need separate runtime evidence and are not counted as exercised by a normal suite. Every implementation issue linked here belongs to milestone 23.

Current iPhone and shared-mobile capabilities

Existing capability / source Owning Rust API/module Android presentation / approved API Implementation and required evidence
Five destinations: Home, Passwords, Search, TOTP, Preferences; loading/empty/ready/locked/error fixtures (AppContext, ShellViewController) mobile::MobileShell, MobileTab, MobileShellState; config selected tab ShellScreen / ShellViewModel / MainActivity #89/#91/#102; shell fixtures, startup, back/navigation and recreation; Checks: ShellScreenTest, AdaptiveShellTest, Tier2WindowTest, HingeWindowTest
Local-first setup, generated/imported key, passphrase confirmation, staged QR import (SetupChoiceViewController, LocalSetupViewController) mobile_onboarding::MobileOnboardingOperation, crypto; mobile_key_transfer import OnboardingScreen / NativeOnboardingRepository #95/#106; real local init, key export/import, canceled/failed setup rollback; Checks: OnboardingScreenTest; Rust mobile_onboarding::android::tests
Optional HTTPS clone, server/account/token, repository/branch discovery; attach remote to local store (OnboardingViewController) mobile_onboarding::{MobileOnboardingRequest, MobileOnboardingOperation}; git/config/secret_store OnboardingScreen and SettingsScreen HTTPS actions #95; TLS/auth/branch/cancel/offline errors; repository remote authority; Checks: OnboardingScreenTest; Rust onboarding and git TLS/auth/remote-authority tests
Home history, ahead/behind, local/remote change status, commit activity (ShellViewController, MobileCommitActivityViewController) mobile_home::MobileHomePage/Operation and git HomeScreen / NativeHomeRepository #97; summaries and stale/error state, Git identity, author/history; Checks: HomeScreenTest; Rust mobile_home and tests/git_embedded.rs
Commit, Fetch, Pull, Push and pull-then-push Sync mobile_home::MobileHomeOperation; git sync/merge/conflicts/signing HomeScreen typed actions and progress #97; pull failure prevents push, conflict/data-loss cases and signing; Checks: HomeScreenTest; Rust mobile_home::android_tests and Git conflict/cancellation tests
Directory hierarchy, breadcrumbs, folder and entry rows (PasswordDirectoryViewController) mobile_passwords::MobilePasswordPage/Row/RowKind; repository/read PasswordScreen / NativePasswordRepository #96; deep tree, empty/error, keyboard and size changes; Checks: PasswordScreenTest, NativeEntryViewerTest, NativeTreeMutationTest
Password-store name search (PasswordSearchViewController) mobile_passwords::MobilePasswordPage::search SearchScreen / NativeSearchRepository #101; large-store responsiveness and canceled/stale results; Checks: SearchScreenTest; Rust mobile_passwords and large-store native instrumentation
Unlock entry, explicit user activity, timeout, manual/background lock; shared entry/TOTP/editor lease (LockedPasswordViewController, AppContext) mobile_authentication::MobileAuthentication; authentication generation/leases AuthenticationControls / AndroidKeystoreAdapter / MainActivity lifecycle #93/#98/#100; wrong passphrase, cancel, expiry, generation race, changed enrollment and process death; Checks: AuthenticationScreenTest, opt-in AuthenticationLeaseTest, AndroidKeystoreTest; tests/authentication_leases.rs
Structured fields/sections, masked secrets, explicit reveal/select/copy; OTP field diagnostics (MobileEntryFieldCell) mobile_entry::MobileEntryPage/Field; mobile_authentication::{entry_page,reveal_entry_field,copy_entry_field} EntryViewer / NativePasswordRepository #99/#100; no pre-unlock values, relock clears all views, copy expiry/ownership; Checks: EntryViewerTest, NativeEntryViewerTest, NativeOtpPresentationTest; tests/entry_documents.rs
Create entry/folder, structured multiline editing, add/remove/reorder fields, dirty discard confirmation (MobileEntryEditorViewController) mobile_entry::MobileEntryDraft; mobile_authentication editor session/create/save/discard; write EntryEditorScreen / NativeEditorRepository #103; actual encrypted saves, conflict tokens, interrupted saves and dirty navigation; Checks: EntryEditorScreenTest, NativeEntryViewerTest; Rust editor conflict/checkpoint/atomic-save tests
Password length/generation and replacement generate; mobile_entry::MobileEntryDraft::generate_password EntryEditorScreen generator controls #103; Rust validation and unbiased generated value; no Kotlin generator; Checks: EntryEditorScreenTest; tests/password_generation.rs
OTP URI input, camera/image import, review before Save (OtpImportViewController; TOTP Add action) mobile_entry::MobileEntryDraft::add_otp_image; document/otp/presentation EntryEditorScreen / QrCameraPane / AndroidQrCamera #103/#106/#107; URI/image/scan parity, invalid/oversized input, cancel; no payload parsing in Kotlin; Checks: EntryEditorScreenTest, AndroidQrCameraTest; Rust qr and tests/otp.rs
Move/copy/delete entries and folders, destination browse, overwrite and dirty-editor handling (PasswordMutationCoordinator) mobile_mutation::MobileMutationService/Plan/Request; mutation MutationDialog / NativePasswordRepository #108; revisions, destination conflicts, recipient reencryption and rollback; Checks: MutationWorkflowTest, NativeTreeMutationTest; tests/tree_mutations.rs and recipient_policy.rs
TOTP discovery catalog, incremental progress, warm cache, refresh, cancel/resume, cached search (TotpListViewController) mobile_totp discovery/catalog/operation; mobile_authentication cached/search APIs TotpScreen / NativeTotpRepository #90/#110; discovery behavior and evidence, cold/warm/change/add/remove/corrupt/wrong-store/concurrent-change tests; Checks: TotpDiscoveryFixtureTest, NativeTotpDiscoveryTest, NativeTotpPerformanceTest; tests/mobile_totp.rs
TOTP rows, large detail code, countdown/expiry, copying (TotpDetailViewController, TotpCodeView) mobile_totp::MobileOtpCodePresentation; otp; mobile_authentication::{presented_otp_code,copy_presented_otp_code,advance_presented_hotp} TotpScreen / OtpCodeView / EntryViewer #107/#100; OTP behavior and evidence, RFC vectors, boundary countdown, stale callback/relock and clipboard; Checks: TotpScreenTest, NativeOtpPresentationTest; Rust OTP boundary/relock/HOTP tests
Repository/server identity, local-only/add-remote Settings, token replace/remove (PreferencesViewController, TokenUpdateViewController) mobile_authentication::MobilePreferences; mobile_onboarding::replace_configured_application_token; config/secret_store SettingsScreen / NativeSettingsRepository #104/#95; no token display; protected replacement/removal and offline operation; Checks: SettingsScreenTest; Rust preference/token and Android onboarding tests
Key identity/fingerprint, GPG recovery import and public/private QR export (KeyImportScannerViewController, KeyExportListViewController, KeyQrExportViewController) mobile_key_transfer::{MobileKeyTransferService,MobileKeyTransferImport}; crypto/presentation SettingsScreen key transfer / QrCameraPane / AndroidQrCamera #106/#104; multi-frame order/duplicates/interruption, bounded frames, private export authorization and camera denial; Checks: SettingsScreenTest, AndroidQrCameraTest; Rust mobile_key_transfer frame/order/cancel/authorization tests
Inactivity timeout, biometric enable/disable, Lock Now, appearance and Git commit name/email mobile_authentication preference setters, git_identity; config SettingsScreen / AuthenticationControls / ApplicationTheme #98/#104; persistent settings, validation, Keystore enrollment/recovery and lease revocation; Checks: SettingsScreenTest, NativeEntryViewerTest, opt-in AuthenticationLeaseTest; Rust authenticated preference tests
AutoFill extension boundary (current iPhone controller is empty), shared identity/access domain and Android provider requirement mobile_credentials; mobile_authentication provider request/select/fill/save APIs IronCredentialProviderService / IronAutofillService / CredentialSelectionActivity #109; typed caller/site identity, non-secret candidates, explicit selection/auth, forged/stale requests, permissions and cross-process lifetime; Checks: ProviderIntentSecurityTest, CredentialSelectionScreenTest, NativeCredentialProviderTest; provider-client OS journeys
Camera permissions, private paths, secret-store mechanics, clipboard, scene/process events, screen privacy Rust repository/config/secret_store/authentication/presentation; platform callbacks contain facts only AndroidSecretClipboard / ProtectedInput / ProtectedPresentation / MainActivity #90/#93/#98/#100; backup inspection, sandbox paths, pressure/update, screen/clipboard/lifecycle tests; Checks: PresentationSecurityTest, BackupPolicyTest, AndroidQrCameraTest; Rust secret-store and editor recovery tests
Accessible labels/actions, large text, keyboard, responsive layout and localization Typed Rust state/actions; UI accessibility is Kotlin Compose semantics/resources / HingeSafeLayout / HingeSafeAlertDialog #105; measured keyboard/TalkBack/large-font/multi-window/RTL/rotation coverage; Checks: Tier2WindowTest, HingeWindowTest; hardening.md records manual accessibility and exact performance evidence
Watch pairing/install state in Settings; TOTP Watch selection, snapshots, receipts, transfer and watchOS detail mobile_watch; shared bridge's explicit watch feature enabled only by crates/apple Absent from Android records and UI (#91) Deliberate Watch-only exclusion; no unsupported placeholder controls or Wear implementation

Name search matches current mobile behavior; CLI/TUI decrypted grep is not an iPhone parity claim. Android has no separate filesystem-based search. The shared core's recipient/signing rules, pass/pass-otp format, HOTP counter safety, Git failure semantics and secret-redaction requirements remain binding wherever an Android workflow invokes them; platform presentation may not replace them.

Current iPhone camera adapters pass OS-decoded QR bytes. Android #106 supplies bounded Y-plane/stride/orientation facts through the shared native contract; storage decodes and reassembles the transfer. See key-transfer.md for interruption/security behavior and evidence. The external-credential matching/grant API is implemented in mobile_credentials and mobile_authentication; both Android providers delegate to it.

Complete milestone issue-to-layer map

Links identify the live issues by number and a concise description. Ordering follows the user's label priority, then numeric order; do not substitute a dependency from another milestone. This list gives ownership, not permission to skip acceptance criteria.

Issue Owning layer Approved implementation/API and completion gate
#88 Architecture/support/dependency policy Repository architecture decision This ADR and parity/owner matrix; review against current sources
#89 Gradle scaffold/module boundaries Android build/app/core/platform/bridge modules Kotlin DSL/catalog/wrapper, Compose/Hilt/KSP, source/dependency gates, all shell fixtures; clean debug APK
#90 Private paths/config/cache/backup crates/storage plus Android path adapter Context roots/capabilities, atomic layout/migrations, backup rules; Rust and sandbox/update tests
#91 Platform-neutral mobile contract crates/storage and shared UniFFI bridge Typed semantic actions/icons, opt-in Watch data, platform callbacks, shared Swift/Kotlin inventory tests
#92 Native Rust/UniFFI packaging Shared/Android Rust bridge and Gradle rust-bridge cargo-ndk, generated immutable Kotlin/JNA Android, both ARM ABIs, checksums/16 KB/loading/debug symbols
#93 Keystore adapter Delivered: Rust sealed-record orchestration and Android OS adapter Keystore policy and recovery; native AES-GCM/CryptoObject and Rust lifecycle tests
#94 CI/static analysis/reproducibility Build/CI/test infrastructure Cargo gates, Gradle build/Lint/ktlint, JVM/Compose/instrumented tests, verification/locks/SBOM/ABI checks
#95 Local-first/HTTPS onboarding storage mobile_onboarding plus Compose features Existing Rust initialization/discovery/clone/credentials; no Kotlin transport
#96 Hierarchical navigation storage mobile_passwords plus Compose features Material 3 Adaptive list/detail, typed rows/stable IDs
#97 Home/Git storage mobile_home/git plus Compose features Rust actions/history/progress/conflicts; Compose Home and activity
#98 Biometric authentication lease storage authentication/mobile_authentication plus platform adapter AndroidX BiometricPrompt/CryptoObject, KeyguardManager; Rust generations/policy
#99 Structured viewer storage mobile_entry/mobile_authentication plus Compose features Typed fields/sections/reveal/copy, Rust OTP and diagnostics
#100 Privacy/lifecycle/plaintext storage lease/presentation plus platform/app Lifecycle, FLAG_SECURE, ClipboardManager, no saved plaintext/logs, race tests
#101 Name search storage mobile_passwords plus Compose features Rust cached/name search, Flow cancellation/latest query wins
#102 Adaptive shell storage mobile shell contract plus Android app/features Navigation 3/Material 3 Adaptive, StateFlow, restoration without secrets
#103 Entry/folder/editor/generation storage mobile_entry/write/generate plus Compose features Rust editor sessions/drafts/atomic saves, structured multiline controls and OTP import
#104 Settings/recovery storage config/mobile_authentication/key transfer plus Compose features Shared setters, token/key recovery, Biometric/appearance/identity controls without Watch
#105 Accessibility/adaptive/localization/performance Android features/resources plus storage cancellation Compose semantics/TalkBack/resources, measured Macrobenchmark/profiles if justified
#106 CameraX GPG QR import/export storage QR/key transfer plus platform camera/Compose CameraX frames, Rust decode/envelope/matrices, permission and bounded payload checks
#107 TOTP list/detail storage mobile_totp/otp plus Compose features Rust codes/timing, large display/copy/refresh, OTP creation/import navigation
#108 Move/copy/delete storage mobile_mutation/mutation plus Compose features Mutation behavior and evidence; Rust plans/revisions/overwrite/reencryption, destination and confirmation UI
#109 Credential Manager/Autofill storage identity/permission/credential contract plus OS services AndroidX provider and framework AutofillService, explicit selection/lease before secrets
#110 TOTP catalog/discovery/search storage mobile_totp plus Compose features Existing hash/path/is_totp catalog, Rust progress/checkpoints/filter, no Watch
#111 Parity/security/reliability audit All above plus independent acceptance review Completed matrix evidence, Rust/Android release gates and emulator threat tests
#112 Google Play distribution Release tooling/listing and production app Protected signing/Play AAB, audited manifest/licenses, emulator install and update-preservation tests

#87 is the closed umbrella issue, not an open implementation candidate. Verify live issues after each closure; newly created bug/critical issues may change the order. #91 and #90 currently name later packaging/contract dependencies; their implementations may establish the necessary narrow Rust APIs before consuming full Android packaging, but they must meet all stated acceptance tests before closure. Do not close a partly integrated issue just because its unit tests pass.