feat: build Stride local app with Garmin imports and friends-only sharing

This commit is contained in:
Peter Stockings
2026-10-01 14:55:59 +10:00
parent 16e71a69d5
commit e37569ad09
45 changed files with 3735 additions and 40 deletions
+41
View File
@@ -0,0 +1,41 @@
# Stride local application
Updated: 2026-10-01
## Delivered
- Flask application factory and Jinja UI; local Waitress server on loopback port 5000.
- SQLite for local development, PostgreSQL driver/configuration, Alembic migrations.
- Name/email/password signup, generated profile identifier, session login/logout.
- CSRF checks, password hashing, login rate limits and no-store responses.
- Local first-account setup imports the existing Garmin cache privately.
- FIT upload, owner-specific cached imports, checksummed sync files and deduplication
by source identity. Cross-source file-versus-Garmin reconciliation remains a follow-up.
- Overview with distance/time/pace totals and weekly volume; activity pages with
route maps, pace/heart-rate charts and recorded laps.
- Profile editing and time-zone selection.
- Activity sharing choices: private or accepted friends. No public activity access.
- Friend requests by exact email, recipient acceptance, decline/cancel/remove,
friends feed and friendship-gated profiles. Full routes shown without masking.
- Local JavaScript assets with upstream licenses; OpenStreetMap tiles are fetched
by the browser with attribution. Select an appropriate tile service for deployment.
## Validation
- Offline sync and application tests cover FIT decoding, original downloads,
retries, credential redaction, ownership, private/friend visibility, CSRF,
friend acceptance/removal and preservation of full start/finish coordinates.
- Real local Garmin files imported into a temporary in-memory database successfully.
- Schema migrations applied to local SQLite.
- Browser checks use an isolated synthetic fixture: overview chart and route map
render; the real application remains ready for the user to create their account.
## Next increments
1. Web token upload with encrypted per-user sessions and connection validation.
2. Background imports, retries, refresh locking and scheduled Garmin polling.
3. Email verification and account recovery before broader hosted signup.
4. PostgreSQL integration checks and Dokku Docker deployment/backup process.
5. Deletion/export controls, pagination at larger activity counts and moderation.
Current local development choices are not a claim of production readiness.
+30
View File
@@ -0,0 +1,30 @@
# Local sync validation
Date: 2026-09-30
## Implemented and verified offline
- Python 3.12.12 virtual environment created locally with uv.
- Garmin client pinned to 0.3.17; complete dependency resolution in uv.lock.
- Interactive login/MFA, token import, password-free session verification, and sync CLI.
- Bounded recent activity pagination; all activities or running filter.
- Original download preservation, CRC-checked FIT decoding, sessions/laps/records JSON.
- Account-partitioned storage, profile locks, atomic files, checksums and repeat-run skipping.
- Errors suppress raw provider responses and credential-bearing exception text.
- Automated tests cover synthetic FIT decoding/CRC, archives, pagination, retries,
account separation, credential persistence, and secret redaction.
## Live account checks
- [x] Owner completes local login and MFA where required.
- [x] Saved session verifies in a new process without a password.
- [x] At least one completed activity is downloaded from Garmin.
- [x] FIT decoding reports recorded samples (or explains a valid activity without samples).
- [ ] Repeating the same sync skips completed activities.
- [ ] Exported session is validated on a separate Linux/Dokku runtime.
- [ ] A real refresh/reconnect lifecycle is observed.
User-confirmed live result: 5 found, 5 downloaded, 0 failed, 10,599 recorded
samples. Login and sync ran as separate CLI processes. Local Flask importer also
successfully read these files into a temporary database, with repeat imports
producing no duplicates. Linux/Dokku portability and live refresh remain unverified.