Scaffold the Android Gradle project and enforce module boundaries #89

Closed
opened 2026-08-17 19:10:17 +00:00 by hugo · 1 comment
Owner

Goal

Create the native Android project structure that will host the Kotlin application without weakening IronStorage's Rust-owned domain boundary.

Scope

  • Add an android/ Gradle build using Gradle Kotlin DSL, a version catalog, the Android application plugin, Kotlin, Compose, Hilt/KSP, and reproducible wrapper/toolchain settings.
  • Use a single-activity Compose application and separate modules where the boundary is useful: application/navigation, feature UI modules, Android platform adapters, and the generated Rust bridge. Avoid a module-per-screen architecture.
  • Give the production application the stable package/application ID de.rfc1437.ironstorage; derive service/test IDs without changing the main identity.
  • Define build types, signing placeholders, manifest merging, resources, localization structure, ProGuard/R8 rules, native debug symbols, and deterministic version metadata without committing signing secrets.
  • Enforce allowed dependency direction: Compose features depend on an Android-facing repository/facade; only that facade depends on generated UniFFI types; platform adapters implement narrow OS contracts; no feature module reads the password-store filesystem.
  • Pin stable dependencies through the version catalog and enable dependency verification/locking where supported.
  • Add debug fixtures/fakes for every shell state so UI development does not require real secret material.

Libraries and tools

Android Gradle Plugin, Kotlin Gradle plugin, Compose BOM/Material 3, Activity Compose, Lifecycle, Navigation, Hilt with KSP, Gradle version catalogs, Android Lint, and the NDK plugin/toolchain settings required by the Rust packaging issue.

Acceptance criteria

  • A clean checkout can configure and assemble a placeholder debug APK with no externally installed helper process at application runtime.
  • Package IDs, min/target SDK policy, namespace, modules, dependency direction, and build types match #88.
  • Release configuration contains no development endpoint, credential, key, or signing material.
  • Android feature modules cannot directly depend on Rust implementation crates, filesystem/Git libraries, or competing crypto/OTP libraries.
  • Gradle configuration is cacheable and CI-ready, and generated/native outputs stay out of source control unless explicitly reviewed as release artifacts.

Depends on #88. 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 Create the native Android project structure that will host the Kotlin application without weakening IronStorage's Rust-owned domain boundary. ## Scope - Add an `android/` Gradle build using Gradle Kotlin DSL, a version catalog, the Android application plugin, Kotlin, Compose, Hilt/KSP, and reproducible wrapper/toolchain settings. - Use a single-activity Compose application and separate modules where the boundary is useful: application/navigation, feature UI modules, Android platform adapters, and the generated Rust bridge. Avoid a module-per-screen architecture. - Give the production application the stable package/application ID `de.rfc1437.ironstorage`; derive service/test IDs without changing the main identity. - Define build types, signing placeholders, manifest merging, resources, localization structure, ProGuard/R8 rules, native debug symbols, and deterministic version metadata without committing signing secrets. - Enforce allowed dependency direction: Compose features depend on an Android-facing repository/facade; only that facade depends on generated UniFFI types; platform adapters implement narrow OS contracts; no feature module reads the password-store filesystem. - Pin stable dependencies through the version catalog and enable dependency verification/locking where supported. - Add debug fixtures/fakes for every shell state so UI development does not require real secret material. ## Libraries and tools Android Gradle Plugin, Kotlin Gradle plugin, Compose BOM/Material 3, Activity Compose, Lifecycle, Navigation, Hilt with KSP, Gradle version catalogs, Android Lint, and the NDK plugin/toolchain settings required by the Rust packaging issue. ## Acceptance criteria - A clean checkout can configure and assemble a placeholder debug APK with no externally installed helper process at application runtime. - Package IDs, min/target SDK policy, namespace, modules, dependency direction, and build types match #88. - Release configuration contains no development endpoint, credential, key, or signing material. - Android feature modules cannot directly depend on Rust implementation crates, filesystem/Git libraries, or competing crypto/OTP libraries. - Gradle configuration is cacheable and CI-ready, and generated/native outputs stay out of source control unless explicitly reviewed as release artifacts. Depends on #88. 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:17 +00:00
hugo added the enhancement label 2026-08-17 19:10:17 +00:00
Author
Owner

Implemented in commit e079b82 (pushed to main).

Added the native single-activity Compose project with app, features, core, platform and rust-bridge modules; stable de.rfc1437.ironstorage identity; SDK 26/37 policy; deterministic versions; unsigned/minified release configuration; backup exclusions; and the existing iPhone vault artwork adapted for Android adaptive/themed launchers. The Kotlin facade and Hilt ViewModel expose typed immutable StateFlow presentation state. Gradle enforces module edges and competing-domain dependency restrictions; the Rust android-build tool checks source boundaries and generates all five debug shell states directly from storage-owned MobileShell fixtures. Runtime/native domain wiring remains assigned to #91/#92, and complete adaptive navigation to #102.

Pinned stable Gradle/AGP/Kotlin/KSP/Hilt/AndroidX versions, verified wrapper checksums, committed dependency SHA-256 verification metadata and configuration locks, and disabled automatic JDK substitution. Generated/local/signing/build outputs are ignored. Build/update procedures and boundary review limitations are documented in android/README.md. Instrumented tests retain installed APKs so the persistent emulator's app data is preserved.

Validation and review against every acceptance criterion:

  • All required Rust gates passed: fmt, warning-denied workspace check, clippy, and 411 workspace tests.
  • ktlintCheck, debug/release assembly, debug unit tests and Android Lint passed with strict artifact verification/locks.
  • A fresh source export with no project-generated outputs or local.properties assembled the debug APK using documented installed toolchains and shared dependency caches; configuration-cache reuse passed.
  • API 37 Medium Phone instrumented UI validation tapped every fixture and each of the five tabs (25 combinations), checking the Rust-provided headings. Additional autonomous ADB UI inspection/taps/swipes verified Loading, Empty, Ready, Locked, Error and Preferences; screenshots verified system-bar spacing and the vault launcher icon.
  • An app-private validation file survived install -r and another instrumented run; the app stayed installed. No AVD/data/keychain reset was used.
  • Release APK identity/SDK metadata and absence of debug fixture classes were checked. No signing key, credential or development endpoint is configured.

The reviewed result completes #89's scaffold scope; subsequent milestone issues implement real repository/security workflows.

Implemented in commit e079b82 (pushed to main). Added the native single-activity Compose project with app, features, core, platform and rust-bridge modules; stable de.rfc1437.ironstorage identity; SDK 26/37 policy; deterministic versions; unsigned/minified release configuration; backup exclusions; and the existing iPhone vault artwork adapted for Android adaptive/themed launchers. The Kotlin facade and Hilt ViewModel expose typed immutable StateFlow presentation state. Gradle enforces module edges and competing-domain dependency restrictions; the Rust android-build tool checks source boundaries and generates all five debug shell states directly from storage-owned MobileShell fixtures. Runtime/native domain wiring remains assigned to #91/#92, and complete adaptive navigation to #102. Pinned stable Gradle/AGP/Kotlin/KSP/Hilt/AndroidX versions, verified wrapper checksums, committed dependency SHA-256 verification metadata and configuration locks, and disabled automatic JDK substitution. Generated/local/signing/build outputs are ignored. Build/update procedures and boundary review limitations are documented in android/README.md. Instrumented tests retain installed APKs so the persistent emulator's app data is preserved. Validation and review against every acceptance criterion: - All required Rust gates passed: fmt, warning-denied workspace check, clippy, and 411 workspace tests. - ktlintCheck, debug/release assembly, debug unit tests and Android Lint passed with strict artifact verification/locks. - A fresh source export with no project-generated outputs or local.properties assembled the debug APK using documented installed toolchains and shared dependency caches; configuration-cache reuse passed. - API 37 Medium Phone instrumented UI validation tapped every fixture and each of the five tabs (25 combinations), checking the Rust-provided headings. Additional autonomous ADB UI inspection/taps/swipes verified Loading, Empty, Ready, Locked, Error and Preferences; screenshots verified system-bar spacing and the vault launcher icon. - An app-private validation file survived install -r and another instrumented run; the app stayed installed. No AVD/data/keychain reset was used. - Release APK identity/SDK metadata and absence of debug fixture classes were checked. No signing key, credential or development endpoint is configured. The reviewed result completes #89's scaffold scope; subsequent milestone issues implement real repository/security workflows.
hugo closed this issue 2026-10-08 08:17:28 +00:00
Sign in to join this conversation.