Implements the verifiable pure-Kotlin core of the Android client per
docs/ANDROID_CLIENT_PLAN.md, mirroring the iOS SPM package set as Gradle modules.
Built + reviewed via multi-agent workflow (explore→implement→verify→review),
then review findings fixed with regression tests.
Modules (all pure JVM, kotlin("jvm"); Android-framework modules scaffolded but
gated off in settings — no Android SDK in this env):
- :wire-protocol — frozen wire contract (sealed Client/ServerMessage, enums,
HostEndpoint CSWSH origin derivation, transport interfaces), hand-rolled codec
byte-identical to the server's JSON.stringify + tolerant kotlinx decode.
- :session-core — ReconnectMachine (1→2→4→8→16→30 backoff), PingScheduler,
GateTracker (two-line epoch guard), AwayDigest, UnreadLedger, TitleSanitizer,
KeyByteMap (byte-matches public/keybar.ts).
- :api-client — all REST routes, tolerant decode, Origin-iff-guarded, prefs
unknown-key preservation, pairing probe + host-tier classifier.
- :client-tls — pure half: PKCS#12 parse, X509KeyManager alias logic,
CertificateSummary, provider-agnostic wrong-passphrase classification.
- :test-support — FakeTransport / FakeHttpTransport / virtual-clock fakes.
Verify: ./gradlew clean test → 218 tests, 0 failures (wire-protocol 47,
session-core 60, api-client 69, client-tls 27, test-support 15).
Review (3 lenses, 8/10 each) findings fixed: sessionId JSON-injection escape,
CancellationException propagation in PingScheduler, PairingProbe close-on-cancel
leak, HostEndpoint trim, HostClassifier hoisted to :wire-protocol (type unified),
BouncyCastle-portable wrong-passphrase detection, lone-surrogate escaping.
Known gap (documented, deferred): /push/fcm-token has no server route yet —
plan task A33 (src/push/fcm.ts) delivers it.
49 lines
1.9 KiB
Plaintext
49 lines
1.9 KiB
Plaintext
// ─────────────────────────────────────────────────────────────────────────────
|
|
// :app — the Android application (Compose UI, ViewModels, Hilt DI, FCM push,
|
|
// DeepLinkRouter, DesignSystem, EventBus). Mirrors iOS App/WebTerm.
|
|
//
|
|
// SCAFFOLD STUB ONLY. This module is COMMENTED OUT in settings.gradle.kts because
|
|
// this build environment has NO Android SDK. The block below is the intended shape;
|
|
// it applies the Android Gradle Plugin, which cannot resolve without an SDK.
|
|
//
|
|
// TODO(android-sdk): uncomment the include in settings.gradle.kts AND this block,
|
|
// add AGP + google() to pluginManagement, and provide local.properties -> sdk.dir.
|
|
// ─────────────────────────────────────────────────────────────────────────────
|
|
|
|
/*
|
|
plugins {
|
|
id("com.android.application")
|
|
alias(libs.plugins.kotlin.android)
|
|
alias(libs.plugins.kotlin.serialization)
|
|
id("com.google.dagger.hilt.android")
|
|
id("com.google.gms.google-services")
|
|
}
|
|
|
|
android {
|
|
namespace = "wang.yaojia.webterm"
|
|
compileSdk = 35
|
|
|
|
defaultConfig {
|
|
applicationId = "wang.yaojia.webterm"
|
|
minSdk = 29
|
|
targetSdk = 35
|
|
versionCode = 1
|
|
versionName = "0.1.0"
|
|
}
|
|
|
|
buildFeatures { compose = true }
|
|
}
|
|
|
|
kotlin { jvmToolchain(17) }
|
|
|
|
dependencies {
|
|
implementation(project(":wire-protocol"))
|
|
implementation(project(":session-core"))
|
|
implementation(project(":api-client"))
|
|
implementation(project(":client-tls"))
|
|
implementation(project(":client-tls-android"))
|
|
implementation(project(":host-registry"))
|
|
implementation(project(":terminal-view"))
|
|
}
|
|
*/
|