Files
FitTrack_GarminSync/specs/010-specification-overview-the/quickstart.md
sstent 846725a81e feat(plan): create implementation plan for persisted auth
Adds the technical plan, data model, API contracts, and research for the persisted Garmin authentication feature.
2025-12-22 07:24:47 -08:00

52 lines
3.0 KiB
Markdown

# Quickstart: Implementing Persisted Garmin Authentication
**Date**: 2025-12-22
This guide provides a high-level overview for developers implementing the `Persist Garmin Authentication for Stateless Sync` feature.
## 1. Database Model
- **Action**: Implement the `GarminAuthenticationState` model as defined in `data-model.md`.
- **File**: Create a new model in `src/models/garmin_auth_state.py`.
- **Details**: Ensure the model includes `user_id`, `session_data`, `mfa_pending`, and `last_validated` fields. Use SQLAlchemy and create a corresponding Alembic migration script.
## 2. API Endpoints
- **Action**: Implement the three new endpoints defined in `contracts/garmin_auth_session.json`.
- **Files**: Add a new router in `src/api/v1/auth.py`.
- **Logic**:
- `POST /api/v1/garmin/session/login`:
- Initialize `garth`.
- Call `garth.login(username, password)`.
- If `garth.MFARequired` is raised, create/update the `GarminAuthenticationState` record with `mfa_pending=True` and return `{"status": "MFA_REQUIRED"}`.
- If successful, `dumps()` the session, save it to `session_data`, set `mfa_pending=False`, and return `{"status": "SUCCESS"}`.
- `POST /api/v1/garmin/session/mfa`:
- Load the pending `garth` client state.
- Call `garth.enter_mfa(mfa_code)`.
- On success, `dumps()` the completed session and persist it to the database.
- `GET /api/v1/garmin/session/status`:
- Query the `GarminAuthenticationState` for the current user.
- Perform a lightweight validation call with the loaded session (e.g., `garth.connectapi.get_user_settings()`).
- Return the status (`VALID`, `MISSING`, `EXPIRED`, `MFA_PENDING`).
## 3. Update Background Sync Services
- **Action**: Modify the existing background sync services (`GarminActivityService`, `GarminHealthService`) to use the persisted session.
- **Files**: Update the relevant service files in `src/services/`.
- **Pattern: Load-Use-Update**:
1. **Load**: At the start of the job, fetch the `session_data` from the database.
2. **Initialize**: Call `garth.client.loads(session_data)` to initialize the client.
3. **Use**: Perform the sync operations. `garth` will handle automatic token refreshes.
4. **Update**: Before the job finishes, check if the session was modified (refreshed). If so, `dumps()` the new session and update the `session_data` field in the database. This is critical for maintaining a fresh session for the next job.
## 4. Error Handling
- Implement logic to catch `garth` exceptions for invalid sessions.
- If a session is invalid and cannot be refreshed, update the sync job status to `AUTH_EXPIRED` and clear the `session_data` from the database.
## 5. Testing
- Write unit tests for the new API endpoints and the Load-Use-Update pattern.
- Write integration tests that cover the full login (including MFA) and background sync flow.
- Mock the `garth` library to simulate different scenarios: successful login, MFA required, invalid session, and token refresh.