# 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.
