Apply code-review fixes: identity/pagination, load races, TLS pin, leaks

Addresses a multi-agent code review (26 confirmed findings + a URLSession
leak) across correctness, concurrency, security, and cleanup:

- MongoDocument.id: deterministic fallback (was UUID() on every access) to stop
  SwiftUI List/ForEach identity churn; getAll pagination drives its cursor off
  the real _id via documentId, so a missing _id stops paging instead of looping
  on a fabricated cursor.
- View models: per-load generation guard (+ captured-tab guard on ONU detail)
  so a cancelled or overlapping load can't commit stale results or land data on
  the wrong tab.
- JSONValue.intValue: guard Int(d) against NaN/inf/out-of-range (crash).
- ServerTrustEvaluator: hash the real SubjectPublicKeyInfo (prepend the
  algorithm-specific ASN.1 SPKI header) so a standard openssl-captured
  public-key pin actually matches; unknown key types fail closed.
- AppEnvironment.configure: clear stale cookies + Keychain creds on host change.
- FirmwareFile.isCompatible: empty metadata no longer passes as compatible-for-all.
- APIClient: invalidate URLSession on deinit (per-configure/probe leak).
- Dashboard best-effort sections keep last-good on transient failure; unified
  optical thresholds; LoginView prefill-once; populatedBuckets unique ForEach id;
  Format rounding rollover; dead-code/docstring/dedup cleanups.

Verification pending on the Mac (no Swift toolchain on the Linux dev box).

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
Jon Vanvik 2026-05-31 16:36:49 +02:00
parent 8de962eeb8
commit 203465913c
21 changed files with 303 additions and 103 deletions

View file

@ -24,55 +24,65 @@ final class DashboardViewModel {
var lasersOffOLTs: [OLTStateDoc] = []
private let connection: MCMSConnection
/// Bumped per load; only the latest load commits, so the 30s auto-refresh loop
/// and a manual pull-to-refresh can't interleave partial writes.
private var loadGeneration = 0
init(connection: MCMSConnection) { self.connection = connection }
/// Light by default: the ONU count, state breakdown, OLT traffic and
/// laser-off count all come from the (small) OLT-STATE docs. The heavy
/// per-ONU optical scan runs only when `extraStats` is on.
func load(extraStats: Bool = false) async {
loadGeneration += 1
let gen = loadGeneration
phase = .loading
do {
// OLT-STATE drives the OLT count, ONU registration (dev guide
// Procedure 2), total traffic, and laser state all from a handful
// of small docs.
// of small docs. Fetch everything into locals first, then commit once,
// so an overlapping load can't publish a half-updated dashboard.
let olts = try await connection.olt.allStates()
oltCount = olts.count
let registration = OLTRepository.registrationMap(from: olts)
// Best-effort sections: nil means "fetch failed this cycle" keep the
// last good value rather than flicker to empty/zero on a transient blip.
let controllers = try? await connection.controller.allConfigs().count
let alarms = try? await connection.onu.alarmHistories()
// Opt-in heavy scan: pull every ONU-STATE for the Rx optical check.
var optAvailable = false
var abnormal: [ONUStateDoc] = []
if extraStats {
let onus = try await connection.onu.allStates()
optAvailable = onus.contains { $0.rxOpticalDBm != nil }
abnormal = onus.filter { $0.rxOpticalDBm.map(OpticalThreshold.rxAbnormal) ?? false }
}
guard gen == loadGeneration, !Task.isCancelled else { return }
oltCount = olts.count
onuTotal = registration.count
onuCounts = Dictionary(grouping: registration.values, by: { $0 })
.map { (state: $0.key, count: $0.value.count) }
.sorted { $0.count > $1.count }
totalDownstreamBps = olts.compactMap(\.txRateBps).reduce(0, +)
totalUpstreamBps = olts.compactMap(\.rxRateBps).reduce(0, +)
lasersOffOLTs = olts.filter(\.isLaserOff)
lasersOffCount = lasersOffOLTs.count
controllerCount = (try? await connection.controller.allConfigs().count) ?? 0
if let alarms = try? await connection.onu.alarmHistories() {
if let controllers { controllerCount = controllers } // else keep last good
if let alarms {
severityCounts = Dictionary(grouping: alarms, by: { $0.severity })
.map { (severity: $0.key, count: $0.value.count) }
.sorted { $0.severity.rank < $1.severity.rank }
}
} // else keep last good
// Opt-in heavy scan: pull every ONU-STATE for the Rx optical check.
if extraStats {
let onus = try await connection.onu.allStates()
opticalAvailable = onus.contains { $0.rxOpticalDBm != nil }
abnormalRxONUs = onus.filter { onu in
guard let rx = onu.rxOpticalDBm else { return false }
return rx < -28 || rx > -10
}
abnormalRxCount = abnormalRxONUs.count
} else {
opticalAvailable = false
abnormalRxONUs = []
abnormalRxCount = 0
}
opticalAvailable = optAvailable
abnormalRxONUs = abnormal
abnormalRxCount = abnormal.count
phase = .loaded
} catch {
guard gen == loadGeneration, !Task.isCancelled else { return }
phase = .failed((error as? APIError)?.localizedDescription ?? error.localizedDescription)
}
}