Parity with the Android client: drop the "Allow self-signed certificate" escape hatch. The app now performs system TLS trust only — a self-signed appliance must have its CA installed on the device (MDM/profile). A code-only public-key pinning policy remains (no UI). - ServerTrustEvaluator: remove ServerTrustPolicy.allowSelfSignedForHost and its challenge handler; keep .system (default) and .pinPublicKeySHA256. - SettingsView: remove the self-signed toggle/state/prefill; makeConfig uses the default .system policy. - MCMSConnection / APIConfiguration: update usage-sketch + doc comments. - README / GUI-NOTES / MCMS_API.md: document system-trust-only; self-signed boxes need their CA installed on the device. - Add CHANGELOG.md for this session, flagged for the Android port. Note: configs previously persisted with the self-signed policy fail to decode and reset to defaults (one-time re-entry of the server URL). Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
3.3 KiB
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
- 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.
- Delete the template
ContentView.swiftand the generatedAppstruct — this scaffold provides its own@maininApp/MCMSMobileApp.swift. - 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:
<key>NSAppTransportSecurity</key>
<dict>
<key>NSExceptionDomains</key>
<dict>
<key>10.2.10.29</key>
<dict>
<key>NSExceptionAllowsInsecureHTTPLoads</key><true/>
<key>NSIncludesSubdomains</key><false/>
</dict>
</dict>
</dict>
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/v1vs/v1and thedatabases/selectionbody 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 realopenapi.jsonand a live response. The Config tab'sJSONTreeViewshows 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.