Files
IronStorage/android/README.md
T
hugo e079b82b15
Dependency security audit / rustsec (push) Failing after 22s
Scaffold native Android build and enforce Rust boundaries (#89)
2026-10-08 10:16:51 +02:00

90 lines
4.8 KiB
Markdown

# Native Android build
Architecture and issue ownership: [ADR](../docs/android/architecture.md) and
[parity matrix](../docs/android/parity.md). This scaffold implements #89. It is
an installable native Compose foundation; onboarding, secure storage and native
runtime packaging are implemented by their milestone issues.
## Reproducible setup
Use a stable workspace Rust toolchain satisfying Cargo.toml, a JDK 25 installation
(Android Studio's JetBrains Runtime 25 is suitable), Android SDK Platform 37,
build-tools 36.0.0 and NDK 30.0.16248370. The app emits JVM 17-compatible code
and supports minSdk 26. Set JAVA_HOME and ANDROID_HOME/ANDROID_SDK_ROOT or create
an ignored local.properties containing sdk.dir. Cargo must be in the IDE/build
process PATH, or set CARGO to its absolute executable path. No machine paths are
committed.
The committed Gradle 9.8.1 wrapper verifies the distribution SHA-256. Its JAR
SHA-256 is 3b8a25775a69158b5ad2b1d17a80a88dc7b40a352a73eb27d06c612a7ce68e98,
verified against the official Gradle version metadata. AGP 9.4.1 includes Kotlin
support; the Kotlin JVM/Compose plugin pin upgrades its classpath consistently
to 2.4.20. Do not additionally apply kotlin-android with built-in Kotlin enabled.
The version catalog is the single source for Android dependency/SDK/NDK pins.
From this directory:
```sh
./gradlew :app:assembleDebug :app:assembleRelease :app:testDebugUnitTest :app:lintDebug ktlintCheck
./gradlew :app:connectedDebugAndroidTest
```
Repeat the first command to verify configuration-cache reuse. Dependency
verification is strict by default; committed SHA-256 metadata covers resolved
build/test artifacts. Locks pin resolvable module configurations. To update an
approved version, edit the catalog, verify the upstream artifact/release/license,
then explicitly regenerate checksums/locks, inspect the diff and run the gates:
```sh
./gradlew :app:assembleDebug :app:assembleRelease :app:testDebugUnitTest :app:lintDebug ktlintCheck --write-verification-metadata sha256 --write-locks
```
## Boundaries and fixtures
The app composition root injects an Android-facing ShellRepository. Compose
features consume that contract through a Hilt ViewModel and collect immutable
StateFlow state with lifecycle awareness. Only core depends on rust-bridge;
platform implements core OS contracts. Gradle rejects forbidden module edges
and competing domain dependencies. The Rust android-build tool checks Kotlin
source/import boundaries and subprocess paths before every Android build.
These static checks accompany code review; they do not prove arbitrary Kotlin
code cannot conceal a domain implementation.
Debug-only Loading/Empty/Ready/Locked/Error fixtures are generated from the
storage-owned MobileShell::fixture by the Rust build tool. Debug controls select
the fixture and native tabs; these controls and generated fake states are absent
from release. Release displays the scaffold state and does not pretend to have
opened/decrypted a repository. Future #92 replaces scaffold wiring with generated
UniFFI calls; feature code continues to consume the facade.
## Identity, signing and update
All app build types keep de.rfc1437.ironstorage; test IDs are derived by AGP.
Version code 1 and name 1.0.1 are deterministic initial metadata. Debug signing
uses the standard local debug key. Release has no configured signing key and
produces an unsigned APK; #112 configures protected upload signing. Do not add
signing secrets or store passwords to the repository. Native symbol level FULL
and the selected three ABIs are declared for later Rust packaging; the scaffold
ships no native secret runtime or development network endpoint.
The manifest has only the exported launcher activity. Backup/cloud/device-transfer
exclusions and cleartext denial are explicit. Feature-specific services/permissions
are added with their owning issues. Resources use values directories for future
localization; vector/adaptive/monochrome icons and R8 consumer rules are present.
The launcher uses an unchanged copy of the iPhone vault artwork from
apple/Assets.xcassets/AppIcon.appiconset/AppIcon.png, inset for Android's adaptive
mask. Its themed monochrome layer keeps the round vault, wheel and hinge motif.
Keep the two platforms' launcher branding aligned when updating that artwork.
Install updates over the existing simulator app without uninstall or data reset:
```sh
adb -s DEVICE install -r app/build/outputs/apk/debug/app-debug.apk
```
Keep the same AVD and application ID. Never wipe its data/keychain or seed a test
app-data package as an update. After closing an issue, clean its project build
outputs and Cargo target; preserve the emulator and shared SDK/toolchain caches.
AGP's leaveApksInstalledAfterRun option is enabled so instrumented checks do not
uninstall the app after running. Keep it enabled for this persistent test device.