fix(ingest): keep the batch sample's unit captured, not authoritative

The record-unit conversion is now opt-in per caller and only the
`export.xml` archive path opts in. There the attribute is authoritative:
Apple stamps every quantity `<Record>` with the account's own display
unit, so `km` means kilometres and the reading is meaningless without it.

`POST /api/measurements/batch` keeps its documented contract — `unit` is
captured for audit and never read. Nothing in the tree pins the native
client's unit strings for the seventeen convertible identifiers, and a
client that reads a sample in metres while stamping the person's display
unit into the field would have had every walking distance multiplied by a
thousand on ingest. Reading the field there is a wire change and needs
the client's strings pinned first.

The mapping-table audit and the shared conversion module stay. The batch
path's identity behaviour is written down where it is decided and pinned
twice: every convertible identifier round-trips a sibling unit unchanged
by default, and a walking-distance entry sent as `km` is stored as it
arrived. The OpenAPI description says what the server actually does.

Review finding H2.
This commit is contained in:
Marc-André Bombeck committed 2026-09-10 00:24:59 +02:00
1 parent e031e2211c
commit 65e9ecbde6
6 files changed
+161 -30

No files matched your search

+3 -3
View File
@@ -21350,9 +21350,9 @@ components:
type: string
minLength: 1
maxLength: 60
description: Apple's `HKUnit` string for `value`. The server converts the reading into the unit it stores the identifier
in when the two differ and the factor is known (`km` to `m`, `lb` to `kg`, `degF` to `degC`, and their
siblings); a unit the server cannot place leaves the reading untouched.
description: "Apple's `HKUnit` string for `value`, captured for audit. The server does NOT convert from it: `value` is
read in the unit HealthLog stores the identifier in (`m` for walking distance, `kg` for body mass, `kcal`
for energy, `degC` for temperature). Send the sample in that unit."
startDate:
type: string
format: date-time