# WebTerm — Android client A native Android client for the WebTerm browser-terminal server, targeting functional parity with the shipped **iOS** client. See the full design in [`docs/ANDROID_CLIENT_PLAN.md`](../docs/ANDROID_CLIENT_PLAN.md) (stack §2, module architecture §3, server contract §4, task waves §5). This directory is a **Gradle multi-module** project. The module set mirrors the iOS SPM package set and inherits its rule: *dependencies only flow down; nothing points upward* (ARCHITECTURE §1). ## ⚠️ No-SDK constraint (why only 5 modules build here) The current build environment has **no Android SDK**. Everything that can be pure **Kotlin/JVM** (`kotlin("jvm")`) is built and unit-tested now; anything that needs the Android framework (`com.android.*` plugins) is **scaffolded but disabled**. - **Enabled now (pure Kotlin/JVM, `./gradlew test`-able):** `:wire-protocol`, `:session-core`, `:api-client`, `:client-tls`, `:test-support`. - **Scaffolded but COMMENTED OUT** in [`settings.gradle.kts`](settings.gradle.kts) (dirs + a `build.gradle.kts` stub exist, marked `// TODO(android-sdk)`): `:app`, `:terminal-view`, `:host-registry`, `:client-tls-android`. To bring the Android modules online later: install an SDK, add `local.properties` → `sdk.dir`, add the Android Gradle Plugin + `google()` to `pluginManagement`, then uncomment the `include(...)` lines and the plugin blocks in each stub. ## Module map (mirror of the iOS SPM packages — plan §3) | iOS SPM package | Android module | Kind | Status | |------------------------|------------------------|-------------------------------|--------| | WireProtocol | `:wire-protocol` | pure Kotlin/JVM | ✅ built | | SessionCore (reducers) | `:session-core` | pure Kotlin/JVM | ✅ built | | APIClient | `:api-client` | pure Kotlin/JVM | ✅ built | | ClientTLS (pure half) | `:client-tls` | pure Kotlin/JVM | ✅ built | | TestSupport | `:test-support` | pure Kotlin/JVM (fakes) | ✅ built | | ClientTLS (fwk half) | `:client-tls-android` | Android (AndroidKeyStore/Tink)| ⏸ SDK-gated | | HostRegistry | `:host-registry` | Android (DataStore) | ⏸ SDK-gated | | SwiftTerm host view | `:terminal-view` | Android (Termux wrap) | ⏸ SDK-gated | | App/WebTerm | `:app` | Android app (Compose/Hilt/FCM)| ⏸ SDK-gated | > Not yet scaffolded: `:transport-okhttp` (OkHttp `TermTransport`/`HttpTransport` > impls, JVM) is owned by task **A7** and will be added then. The iOS > `URLSession*Transport`s consolidate into it (plan §3 framing note). ### Dependency graph (arrows = "depends on") ``` :app (SDK-gated) ┌───────────────┬───┴────┬──────────────┬───────────────┐ ▼ ▼ ▼ ▼ ▼ :terminal-view :session-core :api-client :host-registry :client-tls-android (SDK-gated) │ │ (SDK-gated) │ │ │ │ ▼ │ │ │ :client-tls (pure) └──────┬───────┴──────────┴──────────────┬────────────────┘ ▼ ▼ :wire-protocol ◀──────────── :transport-okhttp (A7, not yet) ▲ └──────── :test-support → test source sets only ``` `:wire-protocol` is the **frozen shared contract** (Android analogue of `src/types.ts` + WireProtocol) — `ClientMessage`/`ServerMessage`, `MessageCodec`, `Validation`, `WireConstants`, `HostEndpoint` (the single Origin/wsURL derivation), and the `TermTransport` / `HttpTransport` / `PingableTermTransport` boundary interfaces. New wire types are added **only** here (a coordination point). ## Toolchain - **Gradle** 9.6.1 (via the committed wrapper — always use `./gradlew`). - **Kotlin** 2.3.21 (matches the Kotlin embedded in Gradle 9.6.1). - **JVM toolchain** 17 (`jvmToolchain(17)` in every module). - Versions are pinned in the version catalog [`gradle/libs.versions.toml`](gradle/libs.versions.toml): kotlinx-serialization-json, kotlinx-coroutines-core/-test, JUnit5 (Jupiter), Turbine, MockK. Pure modules apply `kotlin("jvm")` + `kotlin("plugin.serialization")`, wire the `libs.bundles.unit-test` bundle into `testImplementation`, and run tests on the JUnit Platform (`tasks.test { useJUnitPlatform() }`). ## Build & test ```bash # Use the committed wrapper for everything. ./gradlew help # sanity: the build configures ./gradlew projects # lists the 5 pure modules ./gradlew build # compile all pure modules ./gradlew test # run JVM unit tests (JUnit5 + coroutines-test + Turbine + MockK) ``` > Testing target: **≥80% Kover coverage** on the pure modules (`:wire-protocol`, > `:session-core`, `:api-client`, `:client-tls` pure half). TDD, immutable data, > small focused files — same discipline as the rest of the repo.