# MCMS Mobile — GUI scaffold notes The SwiftUI layer sits on top of the networking core from the kickoff brief. It's a working skeleton you run against a live MCMS box, then refine. ## Layout ``` App/ MCMSMobileApp (@main), RootView routing, AppEnvironment UI/ Shared components (badges, count tiles, load/error states, LoadPhase) Features/ Settings/ Connection config + test (direct or proxy; system TLS trust only) Login/ Email/password, Keychain prefill Dashboard/ Device + alarm counts (VM + View) ONUList/ Searchable ONU list (VM + View) ONUDetail/ Stats / Config / Alarms / Logs tabs + Reset op (VM + View) ``` Flow: `RootView` shows **Settings** until a connection is configured, then **Login**, then the main **TabView**. `AppEnvironment` owns the `MCMSConnection`, persists the (non-secret) `APIConfiguration` to `UserDefaults`, and keeps credentials in the Keychain. ## Putting it in Xcode 1. New iOS App (SwiftUI lifecycle), **deployment target iOS 17.0+**, built with **Xcode 26 (iOS 26 SDK)**. The 26 SDK is required for App Store / TestFlight submission and makes standard components adopt the Liquid Glass look on iOS 26 devices automatically — no code and no opt-out flag needed; the UI here is stock. 2. Delete the template `ContentView.swift` and the generated `App` struct — this scaffold provides its own `@main` in `App/MCMSMobileApp.swift`. 3. Add the whole `MCMSMobile/` tree (networking core + this GUI). One module, no external dependencies. The view models use the `@Observable` macro and views use `@State`/`@Environment` (iOS 17+). If you ever need to drop below iOS 17, revert those to `ObservableObject`/`@Published` + `@StateObject`/`@EnvironmentObject` and reinstate a `ContentUnavailableView` shim. ## App Transport Security (the gotcha) TLS uses **system trust only** — there is no self-signed bypass. (Historical note: an earlier build had a `ServerTrustEvaluator` self-signed toggle; it was removed for parity with Android.) ATS is separate and can still block the connection: - **HTTPS to a self-signed host:** the connection FAILS unless the host's CA is installed on the device (MDM/configuration profile). Keep TLS 1.2+. - **Plain HTTP** (no TLS) or weak TLS: ATS blocks it by default. Add a *scoped* exception for your host in Info.plist rather than a blanket allow: ```xml NSAppTransportSecurity NSExceptionDomains 10.2.10.29 NSExceptionAllowsInsecureHTTPLoads NSIncludesSubdomains ``` Avoid `NSAllowsArbitraryLoads`. Behind a proxy with a real cert, you need none of this and should set the trust policy to `.system`. ## Known TODOs carried from the core - Confirm `/api/v1` vs `/v1` and the `databases/selection` body key. - The Mongo-document field accessors (ONU state/parent OLT, alarm severity/time, stat counter keys) are best-effort guesses marked `// TODO` — pin them to the real `openapi.json` and a live response. The Config tab's `JSONTreeView` shows the full raw document, which helps you discover the true field paths quickly. - Stats tab lists the latest sample's numeric counters; wire a chosen counter into Swift Charts once the keys are known.