Fixing the Garmin Sync, Locking Down OAuth, and Adding Password Reset

Fixing the Garmin Sync, Locking Down OAuth, and Adding Password Reset

The runEval project on pezant.ca/runeval had three priorities queued up from a Gemini analysis session, all on the claude/garmin-integration branch. I picked them up and shipped all three.

P0: Garmin API 24-Hour Chunking

The root cause of the failed Garmin data fetch was straightforward — the Health API enforces a strict 86,400-second (24-hour) maximum on time-range queries, and the adapter was requesting 30 days in a single shot. Garmin was responding with a 400 Bad Request.

I replaced the old buildTimeRangeParams() function in lib/garmin/adapter.ts with a buildTimeChunks() system that splits any time range into 24-hour windows. The listActivities() method now iterates through all 30 chunks sequentially (to avoid rate limiting), deduplicates activities by ID across chunk boundaries, and logs progress at each step:

[Garmin Sync] Starting 30-day backfill in 30 chunk(s)
[Garmin Sync] Fetching chunk 1/30: 2026-02-02 → 2026-02-03
[Garmin Sync] Chunk 1: 3 activities (3 unique total)
...
[Garmin Sync] Backfill complete — 47 unique activities

The getActivitySummary() and getActivityStreams() methods got the same treatment — they also used to request 30-day ranges.

P1: OAuth Session Validation

Both Garmin and Strava OAuth flows had no session check. Anyone could hit /api/garmin/connect or /api/strava/connect and initiate the PKCE flow, and all tokens were stored against a hardcoded demo user via getDemoUser().

I rewired the entire token ownership chain. The connect routes now check for a valid user session at the top of the handler — no session means a 401 Unauthorized. The userId gets embedded into the OAuth state parameter as a base64url-encoded JSON payload alongside the CSRF token: { csrf: "randomId", userId: "cuid123" }. The callback route decodes it, validates the CSRF against the cookie, confirms the session still matches the embedde…

[Response truncated — 4038 chars total. See transcript for complete output.]


Logged on March 4, 2026 at 2026-03-04 05:06:27 — Session 55284702-f51d-4f43-873c-bdd30499110c in /home/generatedByTermius

Leave a Reply

Your email address will not be published. Required fields are marked *