One-shot prettier pass so the new format:check gate starts from a clean
baseline. Formatting only — no behaviour change. Generator-owned and
vendored artifacts stay untouched via .prettierignore.
Extend the Fitbit/Google Health provider with the read path: the
dataPoints.list client half, the metrics-bundle sync, the poll + backfill
jobs, and the connection-management routes. Builds on the existing OAuth +
credentials + token-refresh layer.
- client: paginated `fetchDataPoints` walker over `safeFetch` keyed on
`nextPageToken`, encoding each data type kebab-case in the path and
snake_case in the filter predicate; defensive per-type mappers (finite +
positive guards) for weight, body fat, daily SpO2, daily HRV, daily resting
heart rate, daily respiratory rate, intraday heart rate, sleep-temperature
derivations, and a height profile-seed extractor. `FITBIT_FIELD_MAP` +
`mapping.md` are the source of truth.
- mapping (no new MeasurementType): weight→WEIGHT, body-fat→BODY_FAT,
SpO2→OXYGEN_SATURATION, HRV→HEART_RATE_VARIABILITY (SDNN slot, not
HRV_RMSSD), resting-HR→RESTING_HEART_RATE, respiratory-rate→RESPIRATORY_RATE,
heart-rate→PULSE, sleep-temp→WRIST_TEMPERATURE, height→User.heightCm when
null. Steps/distance/energy/floors/VO2 + sleep + workouts stay for a later
wave.
- sync: `syncUserFitbit` orchestrator with the reauth short-circuit, the
per-data-class 403 soft-skip (the six Restricted bundles grant
independently), the all-soft-skipped success guard, and incremental-vs-full
windows; `upsertFitbitMeasurements` keyed (userId,type,FITBIT,externalId)
with a 24 h overlap for after-the-fact daily re-rolls, recomputing rollups
and invalidating status caches. Google refresh tokens do not rotate, so the
stored refresh token is kept unless a new one is returned.
- jobs: hourly `fitbit-sync` poll (poll-only; Pub/Sub deferred), the
self-converging boot backfill, and the daily OAuth-state sweep — every queue
registered in both `allQueues` and a `boss.work` binding, staggered off the
WHOOP/Withings crons.
- routes: status / sync / disconnect mirroring the WHOOP shape.
Tests cover the mappers, the casing invariant, `fetchDataPoints`, the
orchestrator soft-skip guard, the idempotent upsert, the backfill discovery,
and the queue registration; an integration test pins the upsert idempotency,
the DAY rollup fold, and the Fitbit-vs-Withings per-source no-collapse against
the Postgres testcontainer.