Commit Graph
8 Commits
Author SHA1 Message Date
Marc-André Bombeck 75eb0637e6 feat(strava): add per-user BYO-OAuth workout source + Garmin indirect-path docs
Add Strava as a per-user BYO-OAuth workout source, mirroring the shipped
WHOOP/Oura/Polar pattern. Strava caps every new app at single-player mode, so
each self-hoster registers their own app and pastes the client id/secret into
Settings (falling back to a shared env app). Strava is a workout source only —
it exposes no daily metrics and no training-depth analytics are derived.

- Schema (migration 0233): per-user encrypted client id/secret + access/refresh
  tokens, plaintext athlete id, incremental cursor, and backfill marker on
  `User`; `STRAVA` added to `MeasurementSource`.
- Token model follows Oura's reactive-refresh-on-401 with a compare-and-set on
  the stored refresh ciphertext, because Strava rotates its refresh token on
  every refresh.
- Client over safeFetch: authorization-code + refresh, activity list + budget-
  aware per-activity detail (for calories/HR), honouring the 200/15min cap; each
  activity maps to one `Workout` row. Activity name/description stay in metadata
  as data, never surfaced or interpolated.
- Dedup reuses the existing source-agnostic two-layer picker: `STRAVA` slots
  into the workout ladder below the device-native wearables and above
  MANUAL/IMPORT, so an Apple-Watch + Strava twin collapses to one canonical row.
- Poll-cohort hourly sync (:17) + self-converging boot backfill, wired into the
  integration-sync registrar. Webhook deferred.
- OAuth routes (connect/callback/credentials/disconnect/status/test) with signed
  state, cross-account re-auth rejection, and a surgical `www.strava.com`
  connect-src gated to the Strava surfaces.
- Settings card + consolidated status envelope entry; env + compose whitelist;
  i18n across all six locales.
- Garmin: no direct connector is possible (business-partner-only). Add
  docs/integrations/garmin.md documenting the Apple Health / Google Health
  Connect path and Garmin's withheld proprietary scores, cross-linked from both
  platform docs, plus a non-connector info note in the Connections panel.

Regenerate docs/api/openapi.yaml for the new `STRAVA` MeasurementSource value.
2026-07-09 21:25:25 +02:00
Marc-André Bombeck 951a8cf9ea test(e2e): count the Google Health status pill on the integrations page 2026-07-04 14:26:36 +02:00
Marc-André Bombeck 1d3ee1d93c test(integrations): expect six integration pills and drop unused field maps
The mobile settings test asserted three integration pills; Polar, Oura and
Nightscout bring the list to six. Remove the unused Oura and Polar field-map
documentation constants and the unused advanced-indices interface the dead-code
gate flagged.
2026-06-14 21:46:20 +02:00
Marc-André Bombeck ab1eea7f23 test(e2e): align export and integrations specs with removed surfaces
Drop the obsolete doctor-report dialog spec (the interactive export-page
dialog was removed; the report now lives under the health-record export),
remove the doctor-report testid from the export smoke, and update the
integrations layout spec to three cards after the moodLog removal.
2026-06-06 23:40:10 +02:00
Marc-André Bombeck 2d6603cd54 test(e2e): align integration fixture with the consolidated status envelope
The settings cards now read connection state from the consolidated
/api/integrations/status envelope (the per-provider status routes were dropped
from the section), so the mobile-layout fixture must supply the per-integration
connected/configured fields the pills key on.
2026-06-05 04:08:01 +02:00
Marc-André Bombeck 3186ecbe67 fix(settings): raise the Google Health tag contrast and update the integration-count assertion
The Fitbit & Pixel tag chip paired muted text on a muted background (below
WCAG AA); use foreground text. Update the mobile integrations e2e to expect
the fourth integration card (Google Health).
2026-06-05 01:33:42 +02:00
Marc-André Bombeck 98693cda6a test(e2e): expect three integration pills on mobile after WHOOP card
The WHOOP integration card adds a third status pill on
/settings/integrations. Update the Pixel-5 layout spec to expect three
pills and assert the two connected ones (Withings + moodLog) order-
independently, since WHOOP stays a dormant BYO-keys card until an
operator adds credentials.
2026-06-04 05:00:13 +02:00
Marc-André BombeckandClaude Opus 4.7 47a8fc7311 test(integrations): Pixel-5 e2e for consolidated status pill
Pins three contracts at the Pixel-5 viewport that the Vitest specs
can't see: no horizontal page scroll, exactly one pill per card with
the connected `data-state` marker, and the v1.4.18 redundant banner
is gone from the rendered DOM. Stubs all three integration endpoints
so no real Withings/Mood Log credentials are needed in CI.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-10 13:05:42 +02:00