@@ -340,13 +340,14 @@ final class ParseableClient: Sendable {
340 // an unexpected body yields an empty, non-throwing config rather than
340 // an unexpected body yields an empty, non-throwing config rather than
341 // a DecodingError — indistinguishable from a server that genuinely has
341 // a DecodingError — indistinguishable from a server that genuinely has
342 // no alerts. Only fall back to the legacy per-stream endpoint when the
342 // no alerts. Only fall back to the legacy per-stream endpoint when the
343− // body ISN'T a recognizable alerts container (a top-level array, or an
343+ // body ISN'T a recognizable alerts container. Any top-level JSON array
344− // object carrying an "alerts" key). When it is, an empty result is
344+ // OR object is the modern endpoint answering — including an empty object
345+ // `{}` or `{"alerts": []}` meaning "no alerts" — and is authoritative, so
345− // authoritative and must not be replaced with unrelated legacy alerts.
346+ // it must not be replaced with unrelated legacy per-stream alerts. Only a
347+ // non-JSON / unparseable body counts as unrecognized.
346 if config.alerts?.isEmpty ?? true {
348 if config.alerts?.isEmpty ?? true {
347 let json = try? JSONSerialization.jsonObject(with: data)
349 let json = try? JSONSerialization.jsonObject(with: data)
348− let isRecognizedShape = json is [Any]
350+ let isRecognizedShape = json is [Any] || json is [String: Any]
349− || (json as? [String: Any])?["alerts"] != nil
350 if !isRecognizedShape,
351 if !isRecognizedShape,
351 let legacy = try? await legacyAlerts(), !(legacy.alerts?.isEmpty ?? true) {
352 let legacy = try? await legacyAlerts(), !(legacy.alerts?.isEmpty ?? true) {
352 return legacy
353 return legacy