From b99f2234a2356ad50beb08b97ec1c9d10d2dfd92 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marc-Andr=C3=A9=20Bombeck?= Date: Thu, 4 Jun 2026 15:57:14 +0200 Subject: [PATCH] fix(whoop): reject non-positive or non-finite body-measurement values WHOOP body fields are self-reported profile data; guard mapBody against absent, NaN/Infinity, or non-positive values so a garbage reading never seeds a WEIGHT measurement or a profile height of 0. --- src/lib/whoop/client.ts | 23 +++++++++++++---------- 1 file changed, 13 insertions(+), 10 deletions(-) diff --git a/src/lib/whoop/client.ts b/src/lib/whoop/client.ts index a9e8fc68c..51489db66 100644 --- a/src/lib/whoop/client.ts +++ b/src/lib/whoop/client.ts @@ -638,17 +638,20 @@ export interface MappedBodyMeasurement { * null and the sync layer skips it. */ export function mapBody(b: WhoopBodyMeasurement): MappedBodyMeasurement { + // WHOOP body fields are self-reported profile data. Guard against absent, + // non-finite (NaN/Infinity), or non-positive values so a garbage reading + // never seeds a real WEIGHT measurement or a `User.heightCm` of 0 + // (v1.11.3 QA L1). + const positive = (n: number | undefined): n is number => + typeof n === "number" && Number.isFinite(n) && n > 0; return { - weightKg: - typeof b.weight_kilogram === "number" ? round2(b.weight_kilogram) : null, - maxHeartRate: - typeof b.max_heart_rate === "number" - ? Math.round(b.max_heart_rate) - : null, - heightCm: - typeof b.height_meter === "number" - ? round2(b.height_meter * M_TO_CM) - : null, + weightKg: positive(b.weight_kilogram) ? round2(b.weight_kilogram) : null, + maxHeartRate: positive(b.max_heart_rate) + ? Math.round(b.max_heart_rate) + : null, + heightCm: positive(b.height_meter) + ? round2(b.height_meter * M_TO_CM) + : null, }; }