# Handoff — PON Go Android Context for the next session/developer. Pairs with [`README.md`](README.md) and [`docs/MCMS_API.md`](docs/MCMS_API.md). ## Architecture - **`core/`** — pure Kotlin, no Android UI deps. Mirrors the iOS networking core. - JSON: MCMS docs are heterogeneous Mongo documents, so we keep raw `kotlinx.serialization` `JsonElement` trees and read fields via the accessors in `Json.kt` (`el["key"]`, `.string/.int/.double/.array/.obj`) — the analogue of the iOS `JSONValue`. Models (`Models.kt`) are thin wrappers over a `JsonElement` with computed properties. - `ApiClient` (OkHttp): builds versioned requests, injects `Referer` + `X-CSRFToken` (writes), unwraps the `{status,data}` envelope, maps status codes to `ApiError`, paginates via the `next` cursor. `Call.await()` bridges OkHttp to coroutines with cancellation. - Repositories return model wrappers; `McmsConnection` wires it all; auth/cookies in `Networking.kt` (`SessionCookieJar` + `SessionStore`), TLS policy in `ServerTrust`, secrets in `KeychainStore` (EncryptedSharedPreferences). - **`ui/`** — Jetpack Compose. Navigation is **state-based** in `MainActivity` (a `List` back stack + `BackHandler`), not Navigation-Compose — so detail screens and the dashboard drill-downs can take in-memory objects directly. Each screen has a plain **state-holder class** (`…Model`) exposing `mutableStateOf` fields + `suspend load()/refresh()` — the analogue of the iOS `@Observable` view models. No androidx `ViewModel`/DI. ## Build / verify loop (this matters) The dev machine had **no `kotlinc`/`gradle` on PATH**, but Android Studio provides everything. Two loops: - **Full build (authoritative):** ``` export JAVA_HOME="/Applications/Android Studio.app/Contents/jbr/Contents/Home" ./gradlew :app:assembleDebug --no-daemon --console=plain ``` Needs `local.properties` (`sdk.dir=…`, git-ignored). First run downloads deps to `~/.gradle`; afterwards it's ~20–60 s. This is what proves the whole app (UI + resources + manifest + icons) compiles. - **Quick core-only check (no Gradle), when iterating on `core/`:** the bundled compiler at `…/Android Studio.app/Contents/plugins/Kotlin/kotlinc/bin/kotlinc` with `-Xplugin=…/kotlinc/lib/kotlinx-serialization-compiler-plugin.jar` and a classpath of Maven jars (kotlinx-serialization-json/core, okhttp, okio-jvm, kotlinx-coroutines-core-jvm). Compiles every `core/*.kt` except `KeychainStore.kt` (androidx). Faster than a Gradle round-trip. ## API gotchas (all handled in code — don't regress) - **Single-encode URLs.** Ids stay RAW in `McmsEndpoint`; `ApiClient` encodes the path once via `HttpUrl.addPathSegments`. Pre-encoding double-encoded MAC colons (`:` → `%3A` → `%253A`) → MCMS "invalid id". - **401 bounces to login; 403 does NOT** (permission/CSRF — `requiresReauthentication` is 401-only). - **Writes return `{"status":"success"}` with no `data`** — the unwrap tolerates it. - **ONU registration lives on OLT-STATE buckets** (`OltRepository.registrationMap`), not ONU-STATE. Friendly names are `ONU.Name` / `OLT.Name` (NOT `NETCONF.Name`). - **CPE DHCP** comes from the web helper `GET /api/cpe/onu//` — a versionless, bare `[code, cpe…]` array (use `ApiClient.getRaw`). - **Firmware** = Procedure 7: GET ONU-CFG → write filename/version into the **inactive** bank → full-doc PUT (`FirmwareUpgrade.apply`). Inactive-bank only, so service stays up until the ONU reboots. Still worth testing on a spare ONU. - Field paths were confirmed against live JSON; see `docs/MCMS_API.md` and the model accessors. ## Trimmed vs iOS (intentional, easy to restore) - ONU detail tabs are **Overview / CPE / Logs / Config** — no separate Alarms tab. Current alarms live on ONU-STATE `"Alarm"` buckets if you want to add it. - **Config** shows pretty-printed JSON text, not the collapsible tree the iOS app has. - Dashboard **ONU-state rows aren't tappable** (the Health rows are). The iOS app drills ONU-state → filtered ONU list. - Toggles use `rememberSaveable` (survive rotation, not process death). Persist in prefs if you want parity with iOS `@AppStorage`. - Self-signed/cleartext: the TLS trust policy is in `ServerTrust`. Plain-HTTP hosts also need a `usesCleartextTraffic`/network-security-config exception (Android's ATS analogue) — add when needed. ## Repo split This folder is self-contained (has its own `docs/MCMS_API.md`). To make it a git repo: `git init` here; the included `.gitignore` already excludes `build/`, `.gradle/`, `local.properties`, `.idea/`. Commit the Gradle wrapper (`gradlew`, `gradle/wrapper/*`). The full dev-guide PDFs (`323-1961-30x`) live in the iOS repo if you ever need the deep source. ## Possible next steps Restore the trimmed items above; add OLT firmware (Procedure 8 bulk task); per-ONU live-alarms view; charts for PM history; pull-to-refresh on lists; dark-theme polish; a proper app theme from the brand colours.