From c1edd4d52df59d3da4f2366e7cf20e6c4ad9c2ec Mon Sep 17 00:00:00 2001 From: FuelBoard Contributor Date: Tue, 11 Aug 2026 21:28:19 +0100 Subject: [PATCH] App-side defensive price guard: drop grades outside 50-500p at decode (belt-and-braces vs relay regression) --- Shared/FuelPriceProvider.swift | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/Shared/FuelPriceProvider.swift b/Shared/FuelPriceProvider.swift index 09c4b05..320fbaf 100644 --- a/Shared/FuelPriceProvider.swift +++ b/Shared/FuelPriceProvider.swift @@ -84,11 +84,15 @@ private struct RelayResponse: Codable { let prices: [String: Double]? /// Map relay grade keys (E5/E10/DIESEL) to FuelType for ALL fuels the - /// station sells — one fetch populates every fuel tab. + /// station sells — one fetch populates every fuel tab. Defensive guard: + /// any grade outside the 50–500 pence/litre band is dropped, so a relay + /// regression (e.g. the band being removed server-side) can't re-poison + /// the nationwide cheapest reference with 1.3p / 1589p garbage. var allPrices: [FuelType: Double] { var result: [FuelType: Double] = [:] if let prices { for (grade, value) in prices { + guard (50...500).contains(value) else { continue } switch grade.uppercased() { case "E10": result[.e10] = value case "E5": result[.e5] = value @@ -98,7 +102,7 @@ private struct RelayResponse: Codable { } } // Backwards-compat: relay versions without `prices` still send `price`. - if result.isEmpty, let price { + if result.isEmpty, let price, (50...500).contains(price) { result[.e10] = price } return result