Turn the current iPhone-oriented mobile surface into a shared mobile application contract that Android can consume without inheriting Apple or Watch assumptions.
Scope
Inventory crates/storage::mobile* and crates/apple exports against the Android parity matrix.
Move reusable UniFFI records/conversions into a shared bridge or generate equivalent bindings from one source of truth; prevent Swift and Kotlin APIs from drifting.
Replace Apple-specific presentation values such as SF Symbol names with typed semantic icon/action identifiers that each UI maps to native assets.
Separate Watch-only selection/snapshot/status fields from phone TOTP records so Android does not derive state from “unavailable” Watch display strings or expose dead controls.
Add typed contracts for platform paths, secure-secret operations, clipboard presentation, clock/lifecycle events, camera frames, and any Android-only credential-provider request that cannot be implemented directly in Rust.
Keep repository paths, configuration, parsing, mutation decisions, Git progress, authentication leases, TOTP timing, QR envelopes, and external-credential matching in crates/storage.
Define stable IDs, revision/conflict tokens, cancellation ownership, object lifetime, and secret-redaction behavior across UniFFI.
Add contract tests that generate both Swift and Kotlin bindings and compare the public feature inventory.
Acceptance criteria
The Android bridge presents every non-Watch current mobile workflow without copying Apple-specific conversion code.
Apple builds continue to work, while Watch-only data is explicitly opt-in and absent from Android records.
UI-visible actions and states are enums/records, not values recovered from labels, symbol names, or error text.
Platform callback interfaces contain OS mechanics only and cannot make storage-domain decisions.
Binding compatibility, cancellation, concurrency, lifetime, large payload, and redaction tests pass.
Depends on #88 and the Rust/UniFFI packaging issue. Part of #87.
Android support update (2026-10-08)
User-directed scope: Android release and CI targets are arm64-v8a and armeabi-v7a. x86_64 Android is excluded for now. Validation for every Android milestone issue uses emulator devices only; physical-device testing and physical-device checklists are excluded. Record the limits of available ARM emulator/API images without claiming physical-device coverage.
## Goal
Turn the current iPhone-oriented mobile surface into a shared mobile application contract that Android can consume without inheriting Apple or Watch assumptions.
## Scope
- Inventory `crates/storage::mobile*` and `crates/apple` exports against the Android parity matrix.
- Move reusable UniFFI records/conversions into a shared bridge or generate equivalent bindings from one source of truth; prevent Swift and Kotlin APIs from drifting.
- Replace Apple-specific presentation values such as SF Symbol names with typed semantic icon/action identifiers that each UI maps to native assets.
- Separate Watch-only selection/snapshot/status fields from phone TOTP records so Android does not derive state from “unavailable” Watch display strings or expose dead controls.
- Add typed contracts for platform paths, secure-secret operations, clipboard presentation, clock/lifecycle events, camera frames, and any Android-only credential-provider request that cannot be implemented directly in Rust.
- Keep repository paths, configuration, parsing, mutation decisions, Git progress, authentication leases, TOTP timing, QR envelopes, and external-credential matching in `crates/storage`.
- Define stable IDs, revision/conflict tokens, cancellation ownership, object lifetime, and secret-redaction behavior across UniFFI.
- Add contract tests that generate both Swift and Kotlin bindings and compare the public feature inventory.
## Acceptance criteria
- The Android bridge presents every non-Watch current mobile workflow without copying Apple-specific conversion code.
- Apple builds continue to work, while Watch-only data is explicitly opt-in and absent from Android records.
- UI-visible actions and states are enums/records, not values recovered from labels, symbol names, or error text.
- Platform callback interfaces contain OS mechanics only and cannot make storage-domain decisions.
- Binding compatibility, cancellation, concurrency, lifetime, large payload, and redaction tests pass.
Depends on #88 and the Rust/UniFFI packaging issue. Part of #87.
## Android support update (2026-10-08)
User-directed scope: Android release and CI targets are **arm64-v8a** and **armeabi-v7a**. x86_64 Android is excluded for now. Validation for every Android milestone issue uses emulator devices only; physical-device testing and physical-device checklists are excluded. Record the limits of available ARM emulator/API images without claiming physical-device coverage.
hugo
added this to the 06 - Implement an Android version of the software milestone 2026-08-17 19:10:20 +00:00
Implemented #91 in the shared mobile Rust contract.
Moved the reusable UniFFI exports/conversions into crates/mobile-bridge; Android and Apple are thin packaging crates. Android exposes every current phone workflow. Apple explicitly opts into Watch, whose types, fields and methods are absent from Android metadata.
Replaced storage-owned SF Symbol strings with typed semantic icons, mapped to native Swift assets and Android vectors. Storage still owns actions, parsing, repository/Git decisions, revisions, authentication and OTP state.
Added working typed OS contracts for private roots, secure-secret backend, monotonic clock/lifecycle, clipboard, bounded strided camera frames and credential-provider caller facts. Injected authentication uses the supplied backend for preferences as well as leases. Rust decodes camera QR payloads, validates paths/origins, and applies existing clipboard restore/cancellation rules.
Added generation/inventory/checksum checks for both languages, shared-signature comparison, Swift/Kotlin diagnostic redaction, and documented IDs, ownership, cancellation and secret lifetimes in docs/android/mobile-contract.md. Fixed the Gradle Rust compiler selection and serialized emulator instrumentation suites.
Validation: all required Rust gates passed (422 workspace tests); Android unit/lint/ktlint/debug/release/APK/AAB gates passed; all three packaged ABIs passed metadata/alignment audits. Seven native instrumentation tests and the 25-state/tab UI test passed independently on persistent ARM64 4 KB and strict 16 KB emulators. Optimized release Rust loading and navigation icons were also verified on both. Swift native contract probe passed callback, >1 MiB payload, redaction, cancellation and concurrency checks. The inventories contain 538 identical shared entries. xcodegen and iPhone/bundled Watch/AutoFill simulator builds passed.
Review: checked the complete change against the issue and architecture boundary. Android secure storage, initialization, onboarding UI and provider matching remain their own milestone issues; these callbacks provide their functional Rust contract rather than implementing UI features outside #91.
Remaining manual check (untested): iPhone browsing/preferences/locked-entry rendering worked with existing data, but biometric recovery required the user's GPG passphrase. The Mac subsequently locked, preventing further computer use. No Face ID re-enrollment, app uninstall, container/keychain reset or physical-device test was performed. Automated encrypted-fixture authentication and final-owner cleanup tests passed. The final app was installed over the same simulator/bundle identifier, preserving state.
Commit: [1808510](https://git.rfc1437.de/hugo/IronStorage/commit/1808510).
Implemented #91 in the shared mobile Rust contract.
- Moved the reusable UniFFI exports/conversions into `crates/mobile-bridge`; Android and Apple are thin packaging crates. Android exposes every current phone workflow. Apple explicitly opts into Watch, whose types, fields and methods are absent from Android metadata.
- Replaced storage-owned SF Symbol strings with typed semantic icons, mapped to native Swift assets and Android vectors. Storage still owns actions, parsing, repository/Git decisions, revisions, authentication and OTP state.
- Added working typed OS contracts for private roots, secure-secret backend, monotonic clock/lifecycle, clipboard, bounded strided camera frames and credential-provider caller facts. Injected authentication uses the supplied backend for preferences as well as leases. Rust decodes camera QR payloads, validates paths/origins, and applies existing clipboard restore/cancellation rules.
- Added generation/inventory/checksum checks for both languages, shared-signature comparison, Swift/Kotlin diagnostic redaction, and documented IDs, ownership, cancellation and secret lifetimes in `docs/android/mobile-contract.md`. Fixed the Gradle Rust compiler selection and serialized emulator instrumentation suites.
Validation: all required Rust gates passed (422 workspace tests); Android unit/lint/ktlint/debug/release/APK/AAB gates passed; all three packaged ABIs passed metadata/alignment audits. Seven native instrumentation tests and the 25-state/tab UI test passed independently on persistent ARM64 4 KB and strict 16 KB emulators. Optimized release Rust loading and navigation icons were also verified on both. Swift native contract probe passed callback, >1 MiB payload, redaction, cancellation and concurrency checks. The inventories contain 538 identical shared entries. xcodegen and iPhone/bundled Watch/AutoFill simulator builds passed.
Review: checked the complete change against the issue and architecture boundary. Android secure storage, initialization, onboarding UI and provider matching remain their own milestone issues; these callbacks provide their functional Rust contract rather than implementing UI features outside #91.
Remaining manual check (`untested`): iPhone browsing/preferences/locked-entry rendering worked with existing data, but biometric recovery required the user's GPG passphrase. The Mac subsequently locked, preventing further computer use. No Face ID re-enrollment, app uninstall, container/keychain reset or physical-device test was performed. Automated encrypted-fixture authentication and final-owner cleanup tests passed. The final app was installed over the same simulator/bundle identifier, preserving state.
Blocking a user prevents them from interacting with repositories, such as opening or commenting on pull requests or issues. Learn more about blocking a user.
Goal
Turn the current iPhone-oriented mobile surface into a shared mobile application contract that Android can consume without inheriting Apple or Watch assumptions.
Scope
crates/storage::mobile*andcrates/appleexports against the Android parity matrix.crates/storage.Acceptance criteria
Depends on #88 and the Rust/UniFFI packaging issue. Part of #87.
Android support update (2026-10-08)
User-directed scope: Android release and CI targets are arm64-v8a and armeabi-v7a. x86_64 Android is excluded for now. Validation for every Android milestone issue uses emulator devices only; physical-device testing and physical-device checklists are excluded. Record the limits of available ARM emulator/API images without claiming physical-device coverage.
Commit: 1808510.
Implemented #91 in the shared mobile Rust contract.
crates/mobile-bridge; Android and Apple are thin packaging crates. Android exposes every current phone workflow. Apple explicitly opts into Watch, whose types, fields and methods are absent from Android metadata.docs/android/mobile-contract.md. Fixed the Gradle Rust compiler selection and serialized emulator instrumentation suites.Validation: all required Rust gates passed (422 workspace tests); Android unit/lint/ktlint/debug/release/APK/AAB gates passed; all three packaged ABIs passed metadata/alignment audits. Seven native instrumentation tests and the 25-state/tab UI test passed independently on persistent ARM64 4 KB and strict 16 KB emulators. Optimized release Rust loading and navigation icons were also verified on both. Swift native contract probe passed callback, >1 MiB payload, redaction, cancellation and concurrency checks. The inventories contain 538 identical shared entries. xcodegen and iPhone/bundled Watch/AutoFill simulator builds passed.
Review: checked the complete change against the issue and architecture boundary. Android secure storage, initialization, onboarding UI and provider matching remain their own milestone issues; these callbacks provide their functional Rust contract rather than implementing UI features outside #91.
Remaining manual check (
untested): iPhone browsing/preferences/locked-entry rendering worked with existing data, but biometric recovery required the user's GPG passphrase. The Mac subsequently locked, preventing further computer use. No Face ID re-enrollment, app uninstall, container/keychain reset or physical-device test was performed. Automated encrypted-fixture authentication and final-owner cleanup tests passed. The final app was installed over the same simulator/bundle identifier, preserving state.