feat: Initial commit of FitTrack_GarminSync project

This commit is contained in:
2025-10-10 12:20:48 -07:00
parent d0e29fbeb4
commit 18f9f6fa18
229 changed files with 21035 additions and 42 deletions

View File

@@ -0,0 +1,56 @@
# Requirements Checklist: IntialSpecV2
**Purpose**: Validate the completeness and clarity of the `IntialSpecV2` feature specification.
**Created**: 2025-10-09
**Feature**: [`specs/002-intialspecv2/spec.md`](specs/002-intialspecv2/spec.md)
## Functional Requirements
- [x] CHK-FR-001: System MUST support Garmin Connect username and password authentication for user authorization.
- [x] CHK-FR-002: System MUST download activity files (FIT, GPX, TCX) from Garmin Connect.
- [x] CHK-FR-003: System MUST store downloaded activity files in CentralDB.
- [x] CHK-FR-004: System MUST synchronize health metrics data from Garmin Connect to CentralDB.
- [x] CHK-FR-005: System MUST allow users to upload workouts to Garmin Connect.
- [x] CHK-FR-006: System MUST provide a `POST /api/sync/garmin/activities` API endpoint to trigger activity synchronization.
- [x] CHK-FR-007: System MUST provide a `GET /api/sync/status` API endpoint to check the current status of synchronization processes.
- [x] CHK-FR-008: System MUST process all synchronization tasks as background jobs to ensure responsiveness.
- [x] CHK-FR-009: System MUST implement rate limiting mechanisms for all external API calls, especially to Garmin Connect.
- [x] CHK-FR-010: System MUST include robust error handling and retry logic for transient failures during external API interactions and CentralDB operations.
- [x] CHK-FR-011: System MUST maintain a history of synchronization events and provide mechanisms for conflict resolution using CentralDB.
- [x] CHK-FR-012: The application MUST be designed as a single-user system.
- [x] CHK-FR-013: The service MUST default to listening on port 8001.
- [x] CHK-FR-014: System MUST support configuration via YAML files or environment variables.
- [x] CHK-FR-015: System MUST reuse existing code and logic from @GarminAnalyser.md for Garmin integration where applicable.
- [x] CHK-FR-016: System MUST utilize CentralDB for all persistent storage, including user authentication tokens (e.g., OAuth2 refresh tokens).
- [x] CHK-FR-017: System MUST integrate with the CentralDB API as defined in @DB_API_SPEC.json (with the ability to refresh the spec from `http://localhost:8000/openapi.json`).
- [x] CHK-FR-018: System SHOULD support Fitbit weight data synchronization in a future iteration.
## User Scenarios
- [x] CHK-US-001: User Story 1 (Garmin Connect Activity Synchronization) is clear, testable, and has clear acceptance criteria.
- [x] CHK-US-002: User Story 2 (Garmin Connect Health Metrics Synchronization) is clear, testable, and has clear acceptance criteria.
- [x] CHK-US-003: User Story 3 (Garmin Workout Upload) is clear, testable, and has clear acceptance criteria.
- [x] CHK-US-004: User Story 4 (Check Sync Status) is clear, testable, and has clear acceptance criteria.
## Edge Cases
- [x] CHK-EC-001: Edge cases cover Garmin Connect API unavailability/errors.
- [x] CHK-EC-002: Edge cases cover Garmin Connect API rate limiting.
- [x] CHK-EC-003: Edge cases cover CentralDB unavailability/errors.
- [x] CHK-EC-004: Edge cases cover user authentication credential changes/revocation.
- [x] CHK-EC-005: Edge cases cover data conflicts during synchronization.
## Success Criteria
- [x] CHK-SC-001: SC-001 (Activity sync completion time) is measurable and technology-agnostic.
- [x] CHK-SC-002: SC-002 (Username and password authentication success rate) is measurable and technology-agnostic.
- [x] CHK-SC-003: SC-003 (Sync status endpoint response time) is measurable and technology-agnostic.
- [x] CHK-SC-004: SC-004 (CentralDB data integrity/availability) is measurable and technology-agnostic.
- [x] CHK-SC-005: SC-005 (Workout upload success rate) is measurable and technology-agnostic.
## General Specification Quality
- [x] CHK-GEN-001: All mandatory sections are present and filled.
- [x] CHK-GEN-002: No more than 3 `[NEEDS CLARIFICATION]` markers are present. (1 present)
- [x] CHK-GEN-003: Feature branch name is specified or marked for clarification. (Marked for clarification)
- [x] CHK-GEN-004: Specification is clear, concise, and unambiguous.

View File

@@ -0,0 +1,85 @@
{
"openapi": "3.0.0",
"info": {
"title": "GarminSync Service API - Garmin Authentication and Linking",
"version": "1.0.0",
"description": "API for initiating and managing Garmin Connect authentication and account linking."
},
"paths": {
"/api/garmin/auth/link": {
"post": {
"summary": "Initiate Garmin Connect Account Linking (Direct Email/Password)",
"operationId": "linkGarminAccountDirect",
"requestBody": {
"description": "Garmin Connect credentials for direct authentication.",
"required": true,
"content": {
"application/json": {
"schema": {
"type": "object",
"properties": {
"email": {
"type": "string",
"format": "email",
"description": "Garmin Connect account email."
},
"password": {
"type": "string",
"format": "password",
"description": "Garmin Connect account password."
}
},
"required": [
"email",
"password"
]
}
}
}
},
"responses": {
"200": {
"description": "Garmin Connect account linked successfully.",
"content": {
"application/json": {
"schema": {
"type": "object",
"properties": {
"message": {
"type": "string",
"description": "Confirmation message."
},
"user_id": {
"type": "string",
"format": "uuid",
"description": "ID of the user for whom the account was linked."
},
"garmin_connect_account_id": {
"type": "string",
"format": "uuid",
"description": "ID of the newly linked Garmin Connect account."
}
},
"required": [
"message",
"user_id",
"garmin_connect_account_id"
]
}
}
}
},
"400": {
"description": "Invalid credentials or account already linked."
},
"500": {
"description": "Internal server error during linking process."
}
},
"tags": [
"Authentication"
]
}
}
}
}

View File

@@ -0,0 +1,85 @@
{
"openapi": "3.0.0",
"info": {
"title": "GarminSync Service API - Activity Sync",
"version": "1.0.0",
"description": "API for triggering and managing Garmin Connect activity synchronization."
},
"paths": {
"/api/sync/garmin/activities": {
"post": {
"summary": "Trigger Garmin Connect Activity Synchronization",
"operationId": "triggerActivitySync",
"requestBody": {
"description": "Optional parameters to control the synchronization process.",
"required": false,
"content": {
"application/json": {
"schema": {
"type": "object",
"properties": {
"force_resync": {
"type": "boolean",
"description": "If true, re-download activities even if they exist. Defaults to false.",
"default": false
},
"start_date": {
"type": "string",
"format": "date",
"description": "Optional start date (YYYY-MM-DD) to sync activities from. If not provided, syncs recent activities."
},
"end_date": {
"type": "string",
"format": "date",
"description": "Optional end date (YYYY-MM-DD) to sync activities up to."
}
}
}
}
}
},
"responses": {
"202": {
"description": "Activity synchronization initiated successfully. Returns a SyncJob ID.",
"content": {
"application/json": {
"schema": {
"type": "object",
"properties": {
"job_id": {
"type": "string",
"format": "uuid",
"description": "Unique identifier for the initiated synchronization job."
},
"status": {
"type": "string",
"description": "Current status of the job (e.g., 'pending', 'in_progress')."
},
"message": {
"type": "string",
"description": "Confirmation message."
}
},
"required": [
"job_id",
"status",
"message"
]
}
}
}
},
"401": {
"description": "Unauthorized. User not authenticated with Garmin Connect."
},
"500": {
"description": "Internal server error."
}
},
"tags": [
"Synchronization"
]
}
}
}
}

View File

@@ -0,0 +1,87 @@
{
"openapi": "3.0.0",
"info": {
"title": "GarminSync Service API - Health Metrics Sync",
"version": "1.0.0",
"description": "API for triggering and managing Garmin Connect health metrics synchronization."
},
"paths": {
"/api/sync/garmin/health_metrics": {
"post": {
"summary": "Trigger Garmin Connect Health Metrics Synchronization",
"operationId": "triggerHealthMetricsSync",
"requestBody": {
"description": "Optional parameters to control the synchronization process.",
"required": false,
"content": {
"application/json": {
"schema": {
"type": "object",
"properties": {
"metric_types": {
"type": "array",
"items": {
"type": "string"
},
"description": "List of specific health metric types to synchronize (e.g., 'heart_rate', 'sleep'). If empty, syncs all available metrics."
},
"start_date": {
"type": "string",
"format": "date",
"description": "Optional start date (YYYY-MM-DD) to sync metrics from."
},
"end_date": {
"type": "string",
"format": "date",
"description": "Optional end date (YYYY-MM-DD) to sync metrics up to."
}
}
}
}
}
},
"responses": {
"202": {
"description": "Health metrics synchronization initiated successfully. Returns a SyncJob ID.",
"content": {
"application/json": {
"schema": {
"type": "object",
"properties": {
"job_id": {
"type": "string",
"format": "uuid",
"description": "Unique identifier for the initiated synchronization job."
},
"status": {
"type": "string",
"description": "Current status of the job (e.g., 'pending', 'in_progress')."
},
"message": {
"type": "string",
"description": "Confirmation message."
}
},
"required": [
"job_id",
"status",
"message"
]
}
}
}
},
"401": {
"description": "Unauthorized. User not authenticated with Garmin Connect."
},
"500": {
"description": "Internal server error."
}
},
"tags": [
"Synchronization"
]
}
}
}
}

View File

@@ -0,0 +1,102 @@
{
"openapi": "3.0.0",
"info": {
"title": "GarminSync Service API - Workout Upload",
"version": "1.0.0",
"description": "API for uploading workouts to Garmin Connect."
},
"paths": {
"/api/sync/garmin/workouts": {
"post": {
"summary": "Upload Workout to Garmin Connect",
"operationId": "uploadGarminWorkout",
"requestBody": {
"description": "Workout definition to be uploaded.",
"required": true,
"content": {
"application/json": {
"schema": {
"type": "object",
"properties": {
"workout_id": {
"type": "string",
"format": "uuid",
"description": "Unique identifier of the workout within the application."
},
"workout_name": {
"type": "string",
"description": "Name of the workout."
},
"workout_type": {
"type": "string",
"description": "Type of workout (e.g., 'running', 'cycling')."
},
"scheduled_date": {
"type": "string",
"format": "date",
"description": "Date the workout is scheduled for (YYYY-MM-DD)."
},
"workout_data": {
"type": "object",
"description": "Structured data defining the workout steps and targets. (Schema to be defined based on Garmin Connect workout API)."
}
},
"required": [
"workout_id",
"workout_name",
"workout_type",
"scheduled_date",
"workout_data"
]
}
}
}
},
"responses": {
"202": {
"description": "Workout upload initiated successfully. Returns a SyncJob ID.",
"content": {
"application/json": {
"schema": {
"type": "object",
"properties": {
"job_id": {
"type": "string",
"format": "uuid",
"description": "Unique identifier for the initiated workout upload job."
},
"status": {
"type": "string",
"description": "Current status of the job (e.g., 'pending', 'in_progress')."
},
"message": {
"type": "string",
"description": "Confirmation message."
}
},
"required": [
"job_id",
"status",
"message"
]
}
}
}
},
"400": {
"description": "Invalid workout data provided."
},
"401": {
"description": "Unauthorized. User not authenticated with Garmin Connect."
},
"500": {
"description": "Internal server error."
}
},
"tags": [
"Synchronization"
]
}
}
}
}

View File

@@ -0,0 +1,128 @@
{
"openapi": "3.0.0",
"info": {
"title": "GarminSync Service API - Synchronization Status",
"version": "1.0.0",
"description": "API for checking the status of synchronization processes."
},
"paths": {
"/api/sync/status": {
"get": {
"summary": "Get Synchronization Status",
"operationId": "getSyncStatus",
"parameters": [
{
"name": "job_id",
"in": "query",
"required": false,
"schema": {
"type": "string",
"format": "uuid"
},
"description": "Optional: Filter status by a specific synchronization job ID."
},
{
"name": "job_type",
"in": "query",
"required": false,
"schema": {
"type": "string",
"enum": [
"activity_sync",
"health_metrics_sync",
"workout_upload"
]
},
"description": "Optional: Filter status by job type."
}
],
"responses": {
"200": {
"description": "Returns the current status of synchronization jobs.",
"content": {
"application/json": {
"schema": {
"type": "object",
"properties": {
"jobs": {
"type": "array",
"items": {
"$ref": "#/components/schemas/SyncJobStatus"
}
}
},
"required": [
"jobs"
]
}
}
}
},
"401": {
"description": "Unauthorized. User not authenticated."
},
"500": {
"description": "Internal server error."
}
},
"tags": [
"Synchronization"
]
}
}
},
"components": {
"schemas": {
"SyncJobStatus": {
"type": "object",
"properties": {
"job_id": {
"type": "string",
"format": "uuid",
"description": "Unique identifier for the synchronization job."
},
"job_type": {
"type": "string",
"description": "Type of synchronization (e.g., 'activity_sync')."
},
"status": {
"type": "string",
"description": "Current status of the job (e.g., 'pending', 'in_progress', 'completed', 'failed')."
},
"progress": {
"type": "number",
"format": "float",
"description": "Percentage completion (0.0 to 1.0)."
},
"start_time": {
"type": "string",
"format": "date-time",
"description": "Timestamp when the job started."
},
"end_time": {
"type": "string",
"format": "date-time",
"description": "Timestamp when the job ended (if completed or failed)."
},
"error_message": {
"type": "string",
"nullable": true,
"description": "Any error message if the job failed."
},
"details": {
"type": "object",
"nullable": true,
"description": "Additional job-specific details (e.g., number of items synced, skipped)."
}
},
"required": [
"job_id",
"job_type",
"status",
"progress",
"start_time"
]
}
}
}
}

View File

@@ -0,0 +1,102 @@
# Implementation Plan: [FEATURE]
**Branch**: `[###-feature-name]` | **Date**: [DATE] | **Spec**: [link]
**Input**: Feature specification from `/specs/[###-feature-name]/spec.md`
**Note**: This template is filled in by the `/speckit.plan` command. See `.specify/templates/commands/plan.md` for the execution workflow.
## Summary
[Extract from feature spec: primary requirement + technical approach from research]
## Technical Context
<!--
ACTION REQUIRED: Replace the content in this section with the technical details
for the project. The structure here is presented in advisory capacity to guide
the iteration process.
-->
**Language/Version**: Python 3.13
**Primary Dependencies**: FastAPI, garth, garminconnect
**Storage**: In-memory for job tracking, CentralDB for all other data.
**Testing**: pytest
**Target Platform**: Linux server
**Project Type**: Web application (backend only)
**Performance Goals**: [domain-specific, e.g., 1000 req/s, 10k lines/sec, 60 fps or NEEDS CLARIFICATION]
**Constraints**: [domain-specific, e.g., <200ms p95, <100MB memory, offline-capable or NEEDS CLARIFICATION]
**Scale/Scope**: [domain-specific, e.g., 10k users, 1M LOC, 50 screens or NEEDS CLARIFICATION]
## Constitution Check
*GATE: Must pass before Phase 0 research. Re-check after Phase 1 design.*
[Gates determined based on constitution file]
## Project Structure
### Documentation (this feature)
```
specs/[###-feature]/
├── plan.md # This file (/speckit.plan command output)
├── research.md # Phase 0 output (/speckit.plan command)
├── quickstart.md # Phase 1 output (/speckit.plan command)
├── contracts/ # Phase 1 output (/speckit.plan command)
└── tasks.md # Phase 2 output (/speckit.tasks command - NOT created by /speckit.plan)
```
### Source Code (repository root)
<!--
ACTION REQUIRED: Replace the placeholder tree below with the concrete layout
for this feature. Delete unused options and expand the chosen structure with
real paths (e.g., apps/admin, packages/something). The delivered plan must
not include Option labels.
-->
```
# [REMOVE IF UNUSED] Option 1: Single project (DEFAULT)
src/
├── models/
├── services/
├── cli/
└── lib/
tests/
├── contract/
├── integration/
└── unit/
# [REMOVE IF UNUSED] Option 2: Web application (when "frontend" + "backend" detected)
backend/
├── src/
│ ├── services/
│ └── api/
└── tests/
frontend/
├── src/
│ ├── components/
│ ├── pages/
│ └── services/
└── tests/
# [REMOVE IF UNUSED] Option 3: Mobile + API (when "iOS/Android" detected)
api/
└── [same as backend above]
ios/ or android/
└── [platform-specific structure: feature modules, UI flows, platform tests]
```
**Structure Decision**: [Document the selected structure and reference the real
directories captured above]
## Complexity Tracking
*Fill ONLY if Constitution Check has violations that must be justified*
| Violation | Why Needed | Simpler Alternative Rejected Because |
|-----------|------------|-------------------------------------|
| [e.g., 4th project] | [current need] | [why 3 projects insufficient] |
| [e.g., Repository pattern] | [specific problem] | [why direct DB access insufficient] |

View File

@@ -0,0 +1,129 @@
# Quickstart Guide for GarminSync Service
This guide provides instructions to quickly set up and run the GarminSync service.
## Prerequisites
* Python 3.13 or newer
* Docker and Docker Compose (version 3.x)
* Git
## 1. Clone the Repository
First, clone the project repository to your local machine:
```bash
git clone https://github.com/your-repo/GarminSync.git
cd GarminSync
```
## 2. Set up Python Virtual Environment
It is highly recommended to use a Python virtual environment to manage dependencies.
```bash
python3.13 -m venv .venv
source .venv/bin/activate
pip install -r requirements.txt
```
## 3. Configure Environment Variables
The service can be configured via environment variables. Create a `.env` file in the project root based on `example.env` (if provided) or set them directly in your shell.
**Essential Environment Variables**:
* `GARMIN_CONNECT_EMAIL`: Your Garmin Connect account email.
* `GARMIN_CONNECT_PASSWORD`: Your Garmin Connect account password. *(Ensure secure handling of this variable)*
* `API_PORT`: The port the service will listen on (defaults to `8001`).
Example `.env` content:
```
GARMIN_CONNECT_EMAIL="your_email@example.com"
GARMIN_CONNECT_PASSWORD="your_garmin_password"
API_PORT=8001
```
## 4. Run the Service (Development)
You can run the service directly using `uvicorn` or via Docker Compose.
### Option A: Using Uvicorn (for local development)
```bash
source .venv/bin/activate
uvicorn src.main:app --host 0.0.0.0 --port ${API_PORT:-8001} --reload
```
### Option B: Using Docker Compose
For a containerized development environment:
```bash
docker compose -f docker-compose.dev.yml up --build
```
## 5. Access the API Documentation
Once the service is running, you can access the interactive API documentation (Swagger UI) at:
`http://localhost:8001/docs` (or your configured `API_PORT`)
## 6. Basic Usage
### Link Garmin Account
To link your Garmin Connect account, send a POST request to `/api/garmin/auth/link`:
```bash
curl -X POST "http://localhost:8001/api/garmin/auth/link" \
-H "Content-Type: application/json" \
-d '{
"email": "your_email@example.com",
"password": "your_garmin_password"
}'
```
### Trigger Activity Sync
To trigger activity synchronization:
```bash
curl -X POST "http://localhost:8001/api/sync/garmin/activities" \
-H "Content-Type: application/json" \
-d '{}'
```
### Trigger Health Metrics Sync
To trigger health metrics synchronization:
```bash
curl -X POST "http://localhost:8001/api/sync/garmin/health-metrics" \
-H "Content-Type: application/json" \
-d '{}'
```
### Upload Workout
To upload a workout (replace `<WORKOUT_ID>` with an actual workout ID from your CentralDB):
```bash
curl -X POST "http://localhost:8001/api/sync/garmin/workouts" \
-H "Content-Type: application/json" \
-d '{
"workout_id": "<WORKOUT_ID>"
}'
```
### Check Sync Status
To check the status of synchronization jobs:
```bash
curl "http://localhost:8001/api/sync/status"
```
---
**Note**: This quickstart assumes a basic setup. Refer to the full documentation for advanced configuration, deployment, and troubleshooting.

View File

@@ -0,0 +1,117 @@
# Feature Specification: IntialSpecV2
**Feature Branch**: `feature/intial-spec-v2`
**Created**: 2025-10-09
**Status**: Draft
**Input**: User description: "Create a detailed feature specification based on the provided context."
## User Scenarios & Testing *(mandatory)*
### User Story 1 - Garmin Connect Activity Synchronization (Priority: P1)
As a user, I want to authenticate with Garmin Connect and have my activities (FIT, GPX, TCX files) downloaded and stored in CentralDB so that I can track my fitness data.
**Why this priority**: This is a core function for the GarminSync service, enabling fundamental data collection.
**Independent Test**: Can be fully tested by authenticating with Garmin Connect, triggering an activity sync, and then verifying that activity files are correctly stored in CentralDB.
**Acceptance Scenarios**:
1. **Given** a user has successfully authenticated with Garmin Connect, **When** they trigger an activity sync via `POST /api/sync/garmin/activities`, **Then** their recent activities are downloaded from Garmin Connect and stored as FIT/GPX/TCX files in CentralDB.
2. **Given** a user has authenticated with Garmin Connect, **When** a sync is triggered, **Then** only new or updated activities are downloaded to avoid redundant data.
---
### User Story 2 - Garmin Connect Health Metrics Synchronization (Priority: P2)
As a user, I want my health metrics to be synchronized from Garmin Connect to CentralDB so I can have a comprehensive view of my health data.
**Why this priority**: Important for a holistic view of user health, complementing activity data.
**Independent Test**: Can be fully tested by authenticating with Garmin Connect, triggering a sync, and verifying that health metrics (e.g., heart rate, sleep data) are correctly synchronized and stored in CentralDB.
**Acceptance Scenarios**:
1. **Given** a user has successfully authenticated with Garmin Connect, **When** they trigger a sync, **Then** their health metrics are synchronized from Garmin Connect to CentralDB.
---
### User Story 3 - Garmin Workout Upload (Priority: P2)
As a user, I want to be able to upload workouts from the application to Garmin Connect.
**Why this priority**: This provides bidirectional sync functionality, enhancing the utility of the service.
**Independent Test**: Can be fully tested by creating a workout in the application, initiating its upload to Garmin Connect, and then verifying that the workout appears correctly on the user's Garmin Connect account.
**Acceptance Scenarios**:
1. **Given** a user has a workout defined within the application, **When** they initiate the workout upload to Garmin, **Then** the workout is successfully transmitted and appears on their Garmin Connect account.
---
### User Story 4 - Check Sync Status (Priority: P3)
As a user, I want to be able to check the status of my synchronization processes.
**Why this priority**: Provides essential feedback to the user on ongoing and completed operations, improving user experience.
**Independent Test**: Can be fully tested by triggering a synchronization process, then querying the `/api/sync/status` endpoint to verify that it accurately reflects the ongoing or completed status of the sync.
**Acceptance Scenarios**:
1. **Given** a synchronization process is in progress, **When** the user makes a `GET` request to `/api/sync/status`, **Then** the system returns the current status of the synchronization, including any progress or errors.
2. **Given** a synchronization process has completed, **When** the user makes a `GET` request to `/api/sync/status`, **Then** the system returns the final status of the synchronization, including success or failure details.
---
### Edge Cases
- What happens when the Garmin Connect API is unavailable or returns an error during activity or health metrics synchronization?
- How does the system handle exceeding rate limits imposed by the Garmin Connect API?
- What is the behavior of the system if CentralDB is unavailable or encounters an error during data storage operations?
- How does the system respond if a user revokes the OAuth2 authentication for Garmin Connect?
- What happens if there are conflicts between existing data in CentralDB and incoming data from Garmin Connect during synchronization?
## Requirements *(mandatory)*
### Functional Requirements
- **FR-001**: System MUST support Garmin Connect username and password authentication for user authorization.
- **FR-002**: System MUST download activity files (FIT, GPX, TCX) from Garmin Connect.
- **FR-003**: System MUST store downloaded activity files in CentralDB.
- **FR-004**: System MUST synchronize health metrics data from Garmin Connect to CentralDB.
- **FR-005**: System MUST allow users to upload workouts to Garmin Connect.
- **FR-006**: System MUST provide a `POST /api/sync/garmin/activities` API endpoint to trigger activity synchronization.
- **FR-007**: System MUST provide a `GET /api/sync/status` API endpoint to check the current status of synchronization processes.
- **FR-008**: System MUST process all synchronization tasks as background jobs to ensure responsiveness.
- **FR-009**: System MUST implement rate limiting mechanisms for all external API calls, especially to Garmin Connect.
- **FR-010**: System MUST include robust error handling and retry logic for transient failures during external API interactions and CentralDB operations.
- **FR-011**: System MUST maintain a history of synchronization events and provide mechanisms for conflict resolution using CentralDB.
- **FR-012**: The application MUST be designed as a single-user system.
- **FR-013**: The service MUST default to listening on port 8001.
- **FR-014**: System MUST support configuration via YAML files or environment variables.
- **FR-015**: System MUST reuse existing code and logic from @GarminAnalyser.md for Garmin integration where applicable.
- **FR-016**: System MUST utilize CentralDB for all persistent storage, including user authentication tokens (e.g., username and password hashes).
- **FR-019**: System WILL leverage the `garth` and `garminconnect` libraries for Garmin Connect integration, particularly for handling authentication and data synchronization.
- **FR-017**: System MUST integrate with the CentralDB API as defined in @DB_API_SPEC.json (with the ability to refresh the spec from `http://localhost:8000/openapi.json`).
- **FR-018**: System SHOULD support Fitbit weight data synchronization in a future iteration.
### Key Entities *(include if feature involves data)*
- **User**: The single authenticated individual utilizing the GarminSync service.
- **Garmin Connect Account**: Represents the user's linked Garmin account, storing OAuth2 tokens and other necessary authentication credentials.
- **Activity**: A record of a fitness activity (e.g., running, cycling) obtained from Garmin Connect, encompassing raw data files (FIT, GPX, TCX) and metadata.
- **Health Metric**: A data point representing a user's health measurement (e.g., heart rate, sleep data, body composition) synchronized from Garmin Connect.
- **Workout**: A structured training plan or session that can be uploaded to Garmin Connect.
- **Sync Job**: An instance of a synchronization operation (e.g., activity sync, health metrics sync), tracking its status, progress, and any associated errors.
## Success Criteria *(mandatory)*
### Measurable Outcomes
- **SC-001**: 95% of all triggered Garmin Connect activity synchronizations complete successfully within 5 minutes.
- **SC-002**: Garmin Connect OAuth2 authentication process completes successfully for 100% of first-time users.
- **SC-003**: The `GET /api/sync/status` endpoint returns an accurate synchronization status within 5 seconds of being queried.
- **SC-004**: Data stored in CentralDB (activities, health metrics, tokens) maintains 99.9% integrity and availability.
- **SC-005**: Workout uploads to Garmin Connect succeed for 98% of attempts.

View File

@@ -0,0 +1,222 @@
# Tasks: IntialSpecV2
**Input**: Design documents from `/specs/002-intialspecv2/`
**Prerequisites**: plan.md (required), spec.md (required for user stories), research.md, contracts/
**Tests**: The examples below include test tasks. Tests are OPTIONAL - only include them if explicitly requested in the feature specification.
**Organization**: Tasks are grouped by user story to enable independent implementation and testing of each story.
## Format: `[ID] [P?] [Story] Description`
- **[P]**: Can run in parallel (different files, no dependencies)
- **[Story]**: Which user story this task belongs to (e.g., US1, US2, US3)
- Include exact file paths in descriptions
## Path Conventions
- **Web app**: `backend/src/`, `frontend/src/`
## Phase 1: Setup (Shared Infrastructure)
**Purpose**: Project initialization and basic structure
- [X] T001 Create project structure (`backend/`, `frontend/`, `tests/`)
- [X] T002 Initialize Python backend project with dependencies (FastAPI, `garth`, `garminconnect`) in `backend/`
- [X] T003 [P] Configure linting and formatting tools for Python in `backend/`
- [X] T004 [P] Setup Docker and Docker Compose for development environment
---
## Phase 2: Foundational (Blocking Prerequisites)
**Purpose**: Core infrastructure that MUST be complete before ANY user story can be implemented
**⚠️ CRITICAL**: No user story work can begin until this phase is complete
- [X] T005 Setup CentralDB integration (FR-016, FR-017)
- [X] Define CentralDB client/SDK generation from `DB_API_SPEC.json`
- [X] Implement CentralDB client in `backend/src/services/central_db_service.py`
- [X] T007 Implement authentication/authorization framework (FR-001, FR-012)
- [X] Create User authentication service in `backend/src/services/auth_service.py` to use CentralDB for authentication
- [X] Implement Garmin Connect authentication flow using `garth` and `garminconnect` (FR-019)
- [X] T008 Setup API routing and middleware structure (FR-013: default to port 8001)
- [X] Create basic FastAPI application setup in `backend/src/main.py`
- [X] Implement configuration management (YAML/Environment variables) (FR-014)
- [X] T009 Configure error handling and logging infrastructure (FR-010)
- [X] T010 Implement in-memory background job processing mechanism (FR-008)
- [X] T011 Implement rate limiting for external API calls (FR-009)
- [X] T012 Integrate `garth` and `garminconnect` libraries (FR-019)
- [X] T013 Reuse code/logic from @GarminAnalyser.md (FR-015)
**Checkpoint**: Foundation ready - user story implementation can now begin in parallel
---
## Phase 3: User Story 1 - Garmin Connect Activity Synchronization (Priority: P1) 🎯 MVP
**Goal**: Synchronize Garmin Connect activities and store them as FIT/GPX/TCX files in CentralDB.
**Independent Test**: Authenticate with Garmin Connect, trigger an activity sync via `POST /api/sync/garmin/activities`, and then verify that activity files are correctly stored in CentralDB, with only new or updated activities downloaded.
### Implementation for User Story 1
- [X] T015 [P] [US1] Define `SyncJob` Pydantic model for in-memory job tracking
- [X] T016 [US1] Implement Garmin Activity Service for downloading activities (`backend/src/services/garmin_activity_service.py`) (FR-002)
- [X] T017 [US1] Implement CentralDB storage for activity files (`backend/src/services/central_db_service.py`) (FR-003)
- [X] T018 [US1] Implement activity synchronization logic (handling new/updated activities) (FR-002)
- [X] T019 [US1] Create `POST /api/sync/garmin/activities` endpoint (`backend/src/api/garmin_sync.py`) (FR-006)
- [X] T020 [US1] Implement background job for activity synchronization (FR-008)
- [X] T021 [US1] Add error handling and retry logic for activity sync (FR-010)
- [X] T022 [US1] Update in-memory `SyncJob` status and details (FR-011)
**Checkpoint**: At this point, User Story 1 should be fully functional and testable independently
---
## Phase 4: User Story 2 - Garmin Connect Health Metrics Synchronization (Priority: P2)
**Goal**: Synchronize Garmin Connect health metrics and store them in CentralDB.
**Independent Test**: Authenticate with Garmin Connect, trigger a sync, and verify that health metrics (e.g., heart rate, sleep data) are correctly synchronized and stored in CentralDB.
### Implementation for User Story 2
- [X] T024 [US2] Implement Garmin Health Metrics Service for downloading metrics (`backend/src/services/garmin_health_service.py`) (FR-004)
- [X] T025 [US2] Implement CentralDB storage for health metrics (`backend/src/services/central_db_service.py`) (FR-004)
- [X] T026 [US2] Implement health metrics synchronization logic
- [X] T027 [US2] Integrate health metrics sync into in-memory `SyncJob` mechanism
- [X] T028 [US2] Add error handling and retry logic for health metrics sync (FR-010)
**Checkpoint**: At this point, User Stories 1 AND 2 should both work independently
---
## Phase 5: User Story 3 - Garmin Workout Upload (Priority: P2)
**Goal**: Allow users to upload workouts from the application to Garmin Connect.
**Independent Test**: Create a workout in the application, initiate its upload to Garmin Connect, and then verify that the workout appears correctly on the user's Garmin Connect account.
### Implementation for User Story 3
- [X] T030 [US3] Implement Garmin Workout Service for uploading workouts (`backend/src/services/garmin_workout_service.py`) (FR-005)
- [X] T031 [US3] Create `POST /api/sync/garmin/workouts` endpoint (`backend/src/api/garmin_sync.py`) (FR-005)
- [X] T032 [US3] Implement background job for workout upload (FR-008)
- [X] T033 [US3] Add error handling and retry logic for workout upload (FR-010)
- [X] T034 [US3] Update in-memory `SyncJob` status and details for workout uploads
**Checkpoint**: All user stories should now be independently functional
---
## Phase 6: User Story 4 - Check Sync Status (Priority: P3)
**Goal**: Provide essential feedback to the user on ongoing and completed synchronization operations.
**Independent Test**: Trigger a synchronization process, then query the `/api/sync/status` endpoint to verify that it accurately reflects the ongoing or completed status of the sync.
### Implementation for User Story 4
- [X] T035 [US4] Implement `SyncStatusService` to query in-memory `SyncJob` records (`backend/src/services/sync_status_service.py`)
- [X] T036 [US4] Create `GET /api/sync/status` endpoint (`backend/src/api/garmin_sync.py`) (FR-007)
- [X] T037 [US4] Format and return synchronization status, progress, and error details
---
## Phase N: Polish & Cross-Cutting Concerns
**Purpose**: Improvements that affect multiple user stories
- [X] T038 [P] Documentation updates in `specs/002-intialspecv2/` (e.g., `quickstart.md` for new features)
- [X] T039 Code cleanup and refactoring across services and API endpoints
- [X] T040 Performance optimization (e.g., for large data syncs)
- [X] T041 [P] Additional unit tests for new services and utilities in `backend/tests/unit/`
- [X] T042 Security hardening (e.g., validation rules)
- [X] T043 Run `quickstart.md` validation and update as necessary
- [X] T044 Implement `auth_token` and `refresh_token` management (refreshing tokens before expiry)
---
## Dependencies & Execution Order
### Phase Dependencies
- **Setup (Phase 1)**: No dependencies - can start immediately
- **Foundational (Phase 2)**: Depends on Setup completion - BLOCKS all user stories
- **User Stories (Phase 3+)**: All depend on Foundational phase completion
- User stories can then proceed in parallel (if staffed)
- Or sequentially in priority order (P1 → P2 → P3)
- **Polish (Final Phase)**: Depends on all desired user stories being complete
### User Story Dependencies
- **User Story 1 (P1)**: Can start after Foundational (Phase 2) - No dependencies on other stories
- **User Story 2 (P2)**: Can start after Foundational (Phase 2) - May integrate with US1 but should be independently testable
- **User Story 3 (P3)**: Can start after Foundational (Phase 2) - May integrate with US1/US2 but should be independently testable
- **User Story 4 (P3)**: Can start after Foundational (Phase 2) - Depends on SyncJob from US1/US2/US3 to provide status
### Within Each User Story
- Tests (if included) MUST be written and FAIL before implementation
- Services before endpoints
- Core implementation before integration
- Story complete before moving to next priority
### Parallel Opportunities
- All Setup tasks marked [P] can run in parallel
- All Foundational tasks marked [P] can run in parallel (within Phase 2)
- Once Foundational phase completes, all user stories can start in parallel (if team capacity allows)
- All tests for a user story marked [P] can run in parallel
- Models within a story marked [P] can run in parallel
- Different user stories can be worked on in parallel by different team members
---
## Implementation Strategy
### MVP First (User Story 1 Only)
1. Complete Phase 1: Setup
2. Complete Phase 2: Foundational (CRITICAL - blocks all stories)
3. Complete Phase 3: User Story 1
4. **STOP and VALIDATE**: Test User Story 1 independently
5. Deploy/demo if ready
### Incremental Delivery
1. Complete Setup + Foundational → Foundation ready
2. Add User Story 1 → Test independently → Deploy/Demo (MVP!)
3. Add User Story 2 → Test independently → Deploy/Demo
4. Add User Story 3 → Test independently → Deploy/Demo
5. Add User Story 4 → Test independently → Deploy/Demo
6. Each story adds value without breaking previous stories
### Parallel Team Strategy
With multiple developers:
1. Team completes Setup + Foundational together
2. Once Foundational is done:
- Developer A: User Story 1
- Developer B: User Story 2
- Developer C: User Story 3
- Developer D: User Story 4
3. Stories complete and integrate independently
---
## Notes
- [P] tasks = different files, no dependencies
- [Story] label maps task to specific user story for traceability
- Each user story should be independently completable and testable
- Verify tests fail before implementing
- Commit after each task or logical group
- Stop at any checkpoint to validate story independently
- Avoid: vague tasks, same file conflicts, cross-story dependencies that break independence