A few places still trust the shape of what the server or the radio hands back:
RepeaterClaim.fromJson reads repeater, name and iata with as String?. A non-string value throws a TypeError, and tryFromJson only catches FormatException, so one odd row aborts the whole mine reconcile instead of being dropped. RepeaterAdminApi already has tolerant _asString / _asInt helpers for exactly this; the models should use the same idea.
ProvenNeighbour.tryFromJson has the same as String? on hex / prefix, and heard_at accepts an int or a numeric string but not a num, unlike snr two lines up.
RepeaterClaim.fromJson's FormatException message carries the full raw key, while hexToBytes next to it truncates to a prefix. Nothing logs it today, but a later debugError('$e') would leak a whole key.
parseNeighbourPage has no guard on prefixLen < 1, so a bad caller value ends in a RangeError rather than the FormatException everything else raises.
AccessList.entries and NeighbourPage.entries hand out growable lists; wrapping them in List.unmodifiable would stop a consumer mutating a parse result in place.
A few places still trust the shape of what the server or the radio hands back:
RepeaterClaim.fromJsonreadsrepeater,nameandiatawithas String?. A non-string value throws aTypeError, andtryFromJsononly catchesFormatException, so one odd row aborts the wholeminereconcile instead of being dropped.RepeaterAdminApialready has tolerant_asString/_asInthelpers for exactly this; the models should use the same idea.ProvenNeighbour.tryFromJsonhas the sameas String?onhex/prefix, andheard_ataccepts an int or a numeric string but not anum, unlikesnrtwo lines up.RepeaterClaim.fromJson'sFormatExceptionmessage carries the full raw key, whilehexToBytesnext to it truncates to a prefix. Nothing logs it today, but a laterdebugError('$e')would leak a whole key.parseNeighbourPagehas no guard onprefixLen < 1, so a bad caller value ends in aRangeErrorrather than theFormatExceptioneverything else raises.AccessList.entriesandNeighbourPage.entrieshand out growable lists; wrapping them inList.unmodifiablewould stop a consumer mutating a parse result in place.