Make all storage-owned files work correctly inside Android's sandbox and survive safe application updates without leaking into device or cloud backups.
Scope
Pass canonical Android app-private files, cache, and no-backup directories into the Rust runtime at initialization; do not infer Android paths from HOME, current working directory, or public storage.
Keep the password-store clone, GPG key material, config.toml, TOTP discovery catalog, and transactional scratch space under storage-owned capability roots with atomic mutation behavior.
Choose files versus no-backup placement per threat and recovery model. Exclude the repository, key material, secure-store ciphertext, token/passphrase artifacts, TOTP catalog, and temporary plaintext from Auto Backup/device transfer unless a later audited encrypted export feature explicitly permits it.
Preserve the repository, configuration, credentials, and TOTP cache across normal APK/Play updates. Do not treat update as uninstall/reset.
Handle low-storage, read-only, missing, corrupt, restored-without-Keystore, interrupted atomic write, and process-death cases with typed recovery.
Set the strongest meaningful Unix-style permissions on Android while relying on the application sandbox rather than claiming unsupported filesystem guarantees.
Ensure cache and temporary cleanup never traverses or mutates the password-store repository outside Rust-owned capabilities.
Add migration/version hooks for future Android storage layout changes.
Libraries and APIs
Android Context.filesDir, cacheDir, noBackupFilesDir, data-extraction/backup rules, and storage-owned Rust filesystem/capability APIs. No Storage Access Framework access is needed for the live repository.
Acceptance criteria
Fresh install, app update, process recreation, storage pressure, and corrupt cache fixtures have deterministic outcomes.
Normal updates retain the local repository and valid TOTP cache; uninstall behavior is documented.
Backup inspection shows no password repository, GPG key, secret-store payload, token, passphrase, TOTP metadata, or plaintext temporary file.
Kotlin never lists or mutates repository contents.
Android path behavior has Rust unit tests and instrumented sandbox tests.
Depends on #88, the Rust/UniFFI packaging issue, and the platform-neutral contract 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
Make all storage-owned files work correctly inside Android's sandbox and survive safe application updates without leaking into device or cloud backups.
## Scope
- Pass canonical Android app-private files, cache, and no-backup directories into the Rust runtime at initialization; do not infer Android paths from `HOME`, current working directory, or public storage.
- Keep the password-store clone, GPG key material, `config.toml`, TOTP discovery catalog, and transactional scratch space under storage-owned capability roots with atomic mutation behavior.
- Choose files versus no-backup placement per threat and recovery model. Exclude the repository, key material, secure-store ciphertext, token/passphrase artifacts, TOTP catalog, and temporary plaintext from Auto Backup/device transfer unless a later audited encrypted export feature explicitly permits it.
- Preserve the repository, configuration, credentials, and TOTP cache across normal APK/Play updates. Do not treat update as uninstall/reset.
- Handle low-storage, read-only, missing, corrupt, restored-without-Keystore, interrupted atomic write, and process-death cases with typed recovery.
- Set the strongest meaningful Unix-style permissions on Android while relying on the application sandbox rather than claiming unsupported filesystem guarantees.
- Ensure cache and temporary cleanup never traverses or mutates the password-store repository outside Rust-owned capabilities.
- Add migration/version hooks for future Android storage layout changes.
## Libraries and APIs
Android `Context.filesDir`, `cacheDir`, `noBackupFilesDir`, data-extraction/backup rules, and storage-owned Rust filesystem/capability APIs. No Storage Access Framework access is needed for the live repository.
## Acceptance criteria
- Fresh install, app update, process recreation, storage pressure, and corrupt cache fixtures have deterministic outcomes.
- Normal updates retain the local repository and valid TOTP cache; uninstall behavior is documented.
- Backup inspection shows no password repository, GPG key, secret-store payload, token, passphrase, TOTP metadata, or plaintext temporary file.
- Kotlin never lists or mutates repository contents.
- Android path behavior has Rust unit tests and instrumented sandbox tests.
Depends on #88, the Rust/UniFFI packaging issue, and the platform-neutral contract 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:19 +00:00
Rust now initializes from the three canonical Android Context roots. Repository, keys, configuration, TOTP catalog, version/device binding, and scratch live under no-backup capabilities; disposable cache has a separate capability. Existing default Rust APIs use the explicit process context and Android never infers HOME/cwd/public paths.
Added atomic versioned layout, 0700/0600 permissions, bounded/corrupt catalog recovery, safe orphan cleanup, live-owner locks and creation gates, non-destructive configuration/interrupted-setup recovery, and typed filesystem/secure-binding errors. Missing layout metadata cannot silently discard a prior binding. Device-binding verification executes through the existing platform callback; #93 owns the real Android Keystore adapter.
Fixed the Android sandbox incompatibilities discovered by native testing: safe rustix file locks for the pinned std, private named atomic files instead of forbidden anonymous /proc linking, and atomic no-overwrite rename instead of forbidden configuration hard links. Shared callers retain their existing behavior on other platforms.
Kotlin supplies only OS directory facts, invokes Rust off the UI thread, and presents Rust state/recovery. It does not list/read/write repository contents. Manifest backup remains disabled; installed legacy/cloud/device-transfer XML excludes all nine protected domains. Update/uninstall and recovery policy is documented in docs/android/private-storage.md.
Verification: all four required workspace gates passed (431 Rust tests). Android ktlint, unit tests, lint, and debug/release APK+AAB audits passed for all three ABIs. Each persistent API 37 emulator (4 KB and strict 16 KB) passed eight native tests plus two app tests covering 25 shell state/tab combinations and installed backup policy. A fresh native sandbox created a real protected GPG key and Git repository, saved preferences, and retained that fixture through later test/APK updates. Autonomous ADB UI checks covered all five tabs, process recreation, debug/release install-over updates, native release startup and preserved layout. Rust fixtures verify encrypted pass data and valid TOTP cache across updates/relocation, corrupt cache, interrupted writes/setup, lock ownership, link-safe cleanup, version changes and device-binding loss/mismatch.
Swift native private-storage/redaction validation and 588 shared phone/Watch contract entries passed. xcodegen and affected iPhone/Watch/AutoFill simulator builds passed; the persistent iPhone app launched with its existing store intact. No simulator was erased or app uninstalled. Testing uses emulators only, as requested.
Final review matched every #90 scope/acceptance item to implementation and evidence. Backup inspection was read-only: automatic approval review rejected an active bmgr backupnow attempt because its transport could export sensitive data. Installed flags/XML and no-backup placement were verified instead; no backup payload was exported. App update and process-state preservation were checked independently of build success.
Implemented in [874c813](https://git.rfc1437.de/hugo/IronStorage/commit/874c8139a4add6aba780c410c92e257fbbde8da6).
- Rust now initializes from the three canonical Android Context roots. Repository, keys, configuration, TOTP catalog, version/device binding, and scratch live under no-backup capabilities; disposable cache has a separate capability. Existing default Rust APIs use the explicit process context and Android never infers HOME/cwd/public paths.
- Added atomic versioned layout, 0700/0600 permissions, bounded/corrupt catalog recovery, safe orphan cleanup, live-owner locks and creation gates, non-destructive configuration/interrupted-setup recovery, and typed filesystem/secure-binding errors. Missing layout metadata cannot silently discard a prior binding. Device-binding verification executes through the existing platform callback; #93 owns the real Android Keystore adapter.
- Fixed the Android sandbox incompatibilities discovered by native testing: safe rustix file locks for the pinned std, private named atomic files instead of forbidden anonymous /proc linking, and atomic no-overwrite rename instead of forbidden configuration hard links. Shared callers retain their existing behavior on other platforms.
- Kotlin supplies only OS directory facts, invokes Rust off the UI thread, and presents Rust state/recovery. It does not list/read/write repository contents. Manifest backup remains disabled; installed legacy/cloud/device-transfer XML excludes all nine protected domains. Update/uninstall and recovery policy is documented in docs/android/private-storage.md.
Verification: all four required workspace gates passed (431 Rust tests). Android ktlint, unit tests, lint, and debug/release APK+AAB audits passed for all three ABIs. Each persistent API 37 emulator (4 KB and strict 16 KB) passed eight native tests plus two app tests covering 25 shell state/tab combinations and installed backup policy. A fresh native sandbox created a real protected GPG key and Git repository, saved preferences, and retained that fixture through later test/APK updates. Autonomous ADB UI checks covered all five tabs, process recreation, debug/release install-over updates, native release startup and preserved layout. Rust fixtures verify encrypted pass data and valid TOTP cache across updates/relocation, corrupt cache, interrupted writes/setup, lock ownership, link-safe cleanup, version changes and device-binding loss/mismatch.
Swift native private-storage/redaction validation and 588 shared phone/Watch contract entries passed. xcodegen and affected iPhone/Watch/AutoFill simulator builds passed; the persistent iPhone app launched with its existing store intact. No simulator was erased or app uninstalled. Testing uses emulators only, as requested.
Final review matched every #90 scope/acceptance item to implementation and evidence. Backup inspection was read-only: automatic approval review rejected an active bmgr backupnow attempt because its transport could export sensitive data. Installed flags/XML and no-backup placement were verified instead; no backup payload was exported. App update and process-state preservation were checked independently of build success.
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
Make all storage-owned files work correctly inside Android's sandbox and survive safe application updates without leaking into device or cloud backups.
Scope
HOME, current working directory, or public storage.config.toml, TOTP discovery catalog, and transactional scratch space under storage-owned capability roots with atomic mutation behavior.Libraries and APIs
Android
Context.filesDir,cacheDir,noBackupFilesDir, data-extraction/backup rules, and storage-owned Rust filesystem/capability APIs. No Storage Access Framework access is needed for the live repository.Acceptance criteria
Depends on #88, the Rust/UniFFI packaging issue, and the platform-neutral contract 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.
Implemented in 874c813.
Verification: all four required workspace gates passed (431 Rust tests). Android ktlint, unit tests, lint, and debug/release APK+AAB audits passed for all three ABIs. Each persistent API 37 emulator (4 KB and strict 16 KB) passed eight native tests plus two app tests covering 25 shell state/tab combinations and installed backup policy. A fresh native sandbox created a real protected GPG key and Git repository, saved preferences, and retained that fixture through later test/APK updates. Autonomous ADB UI checks covered all five tabs, process recreation, debug/release install-over updates, native release startup and preserved layout. Rust fixtures verify encrypted pass data and valid TOTP cache across updates/relocation, corrupt cache, interrupted writes/setup, lock ownership, link-safe cleanup, version changes and device-binding loss/mismatch.
Swift native private-storage/redaction validation and 588 shared phone/Watch contract entries passed. xcodegen and affected iPhone/Watch/AutoFill simulator builds passed; the persistent iPhone app launched with its existing store intact. No simulator was erased or app uninstalled. Testing uses emulators only, as requested.
Final review matched every #90 scope/acceptance item to implementation and evidence. Backup inspection was read-only: automatic approval review rejected an active bmgr backupnow attempt because its transport could export sensitive data. Installed flags/XML and no-backup placement were verified instead; no backup payload was exported. App update and process-state preservation were checked independently of build success.