Some checks failed
relay-tripwire / cross-tenant-tripwire (push) Has been cancelled
ios / package-tests (APIClient) (push) Has been cancelled
ios / package-tests (HostRegistry) (push) Has been cancelled
ios / package-tests (SessionCore) (push) Has been cancelled
ios / package-tests (WireProtocol) (push) Has been cancelled
ios / testsupport-tests (push) Has been cancelled
ios / app-tests (push) Has been cancelled
ios / ipad-tests (push) Has been cancelled
ios / integration-tests (push) Has been cancelled
ios / ui-test (push) Has been cancelled
ios / ios17-floor-tests (push) Has been cancelled
Mirror the iOS P0+P1 client as a Gradle multi-module app. Pure-JVM (Kover ≥80% gated): :wire-protocol (frozen contract + HostEndpoint CSWSH origin + byte-exact codec), :session-core (SessionEngine + reconnect/ping/gate/digest reducers), :api-client, :client-tls (pure PKCS12/keymanager), :transport-okhttp (OkHttp WS+REST). Framework: :app (Compose M3 Adaptive, Hilt, FCM, 11 screens + NavGraph), :terminal-view (Termux terminal-emulator/-view via JitPack, Apache-2.0 — the renderer seam proven headless), :host-registry (DataStore), :client-tls-android (AndroidKeyStore + Tink). Highlights: single-key-home mTLS (non-exportable AndroidKeyStore key + re-reading X509KeyManager + connectionPool.evictAll on rotation, ping-pong single-commit so a failed rotation never clobbers the prior identity); FCM Allow/Deny trust split (Deny=BroadcastReceiver, Allow=trampoline Activity hosting BiometricPrompt); per-consumer-Channel EventBus (R10); config-surviving RetainedSessionHolder; byte-exact KeyByteMap; §5.4 pairing warning tiers. Verified: ~484 JVM tests + Kover ≥80% on the pure modules + :app assembles to an APK; all framework modules assemble. Device behaviors (rendering/IME/FCM/biometric/camera, E2E A34/A35, S2 real-handset FCM spike) deferred to android/DEVICE_QA_CHECKLIST.md per plan §7 (no emulator/Firebase here). Built via multi-agent orchestration (TDD builders → adversarial cross-review → fix → re-verify → independent gate); progress in android/PROGRESS_ANDROID.md.
54 lines
2.7 KiB
Plaintext
54 lines
2.7 KiB
Plaintext
// ─────────────────────────────────────────────────────────────────────────────
|
|
// :client-tls-android — the FRAMEWORK half of ClientTLS (plan A11).
|
|
//
|
|
// The ONE key home is AndroidKeyStore: a `.p12` is PARSED via the pure :client-tls
|
|
// half (KeyStore("PKCS12"), import-parse only), then the private key is imported
|
|
// NON-EXPORTABLE into AndroidKeyStore. Tink AEAD (AndroidKeystore master key)
|
|
// encrypts ONLY the cert-chain + metadata blob at rest — never the private key,
|
|
// never the .p12, never the passphrase. A re-reading X509KeyManager presents the
|
|
// AndroidKeyStore key/chain PER handshake so a mid-run import/rotation is used on
|
|
// the NEXT handshake with no relaunch (R4); rotation calls connectionPool.evictAll()
|
|
// on the shared OkHttpClient so pooled/resumed connections drop the old identity.
|
|
//
|
|
// Instrumented tests use the real AndroidKeyStore provider (NOT Robolectric — plan
|
|
// §7), so they only COMPILE here (no emulator) and RUN during device QA.
|
|
//
|
|
// AGP 9 has BUILT-IN Kotlin — apply ONLY com.android.library (adding kotlin.android
|
|
// errors). This module must NOT depend on :transport-okhttp; the :app wiring (A15)
|
|
// bridges IdentityRepository → :transport-okhttp's ClientIdentityProvider seam.
|
|
// ─────────────────────────────────────────────────────────────────────────────
|
|
|
|
plugins {
|
|
id("com.android.library")
|
|
}
|
|
|
|
android {
|
|
namespace = "wang.yaojia.webterm.tlsandroid"
|
|
compileSdk = 36
|
|
defaultConfig {
|
|
minSdk = 29
|
|
testInstrumentationRunner = "androidx.test.runner.AndroidJUnitRunner"
|
|
}
|
|
}
|
|
|
|
kotlin {
|
|
jvmToolchain(17)
|
|
}
|
|
|
|
dependencies {
|
|
// Pure half: Pkcs12Parse (parse+validate), ClientKeyManagerLogic (alias truth table),
|
|
// CertificateSummary(Reader). `api` so :app sees the shared ParsedClientIdentity/summary types.
|
|
// (No :wire-protocol dep — nothing in src/main references wang.yaojia.webterm.wire*.)
|
|
api(project(":client-tls"))
|
|
implementation(libs.tink.android)
|
|
implementation(libs.okhttp)
|
|
// Mutex serializes the two-store rotation commit (single-commit invariant, A11).
|
|
implementation(libs.kotlinx.coroutines.core)
|
|
|
|
// Instrumented (androidTest) — compile here, run on a device (real AndroidKeyStore).
|
|
androidTestImplementation(libs.androidx.test.ext.junit)
|
|
androidTestImplementation(libs.androidx.test.core)
|
|
androidTestImplementation(libs.androidx.test.runner)
|
|
androidTestImplementation(libs.kotlinx.coroutines.core) // runBlocking for suspend mutators
|
|
}
|