From 6c5fb6df0e7bccb862ea15b5c0c656722b27e930 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ullrich=20Sch=C3=A4fer?= Date: Sun, 10 May 2026 16:02:13 +0200 Subject: [PATCH] Spec drift catch-up: FIT location, notification payload fields, shared-packages index - wahoo-import: clarify fitToGpx lives at connected-services/fit.ts (shared across providers) not inside the wahoo directory - notifications: correct follow payload field names to followerUsername, followerDisplayName, targetUsername, targetDisplayName (matches code) - shared-packages: add @trails-cool/fit package entry + CAPABILITIES.md index Co-Authored-By: Claude Sonnet 4.6 --- openspec/CAPABILITIES.md | 2 +- openspec/specs/notifications/spec.md | 2 +- openspec/specs/shared-packages/spec.md | 7 +++++++ openspec/specs/wahoo-import/spec.md | 2 +- 4 files changed, 10 insertions(+), 3 deletions(-) diff --git a/openspec/CAPABILITIES.md b/openspec/CAPABILITIES.md index f6f179d..f646ce7 100644 --- a/openspec/CAPABILITIES.md +++ b/openspec/CAPABILITIES.md @@ -76,7 +76,7 @@ When adding a new spec, slot it into the most relevant group below and update th - [`secret-management`](specs/secret-management/spec.md) — SOPS-encrypted env files, key rotation. - [`observability`](specs/observability/spec.md) — Prometheus, Loki, Grafana dashboards. - [`background-jobs`](specs/background-jobs/spec.md) — pg-boss queue, cron scheduling, retry policy, handler timeouts shared across the apps. -- [`shared-packages`](specs/shared-packages/spec.md) — workspace package boundaries (`@trails-cool/types`, `@trails-cool/map`, etc.). +- [`shared-packages`](specs/shared-packages/spec.md) — workspace package boundaries (`@trails-cool/types`, `@trails-cool/map`, `@trails-cool/fit`, etc.). ## Conventions diff --git a/openspec/specs/notifications/spec.md b/openspec/specs/notifications/spec.md index 4d11367..9718342 100644 --- a/openspec/specs/notifications/spec.md +++ b/openspec/specs/notifications/spec.md @@ -45,7 +45,7 @@ Each notification row SHALL include a `payload` (JSONB) capturing the denormaliz #### Scenario: follow notifications snapshot the follower / target - **WHEN** a `follow_request_received`, `follow_received`, or `follow_request_approved` notification is created -- **THEN** the row's `payload` records the relevant party's `username` and `displayName`, and `payload_version = 1` +- **THEN** the row's `payload` records `followerUsername`, `followerDisplayName`, `targetUsername`, and `targetDisplayName`, and `payload_version = 1` #### Scenario: activity_published snapshots the activity + owner - **WHEN** an `activity_published` notification is created diff --git a/openspec/specs/shared-packages/spec.md b/openspec/specs/shared-packages/spec.md index 960cc45..f6f0ef9 100644 --- a/openspec/specs/shared-packages/spec.md +++ b/openspec/specs/shared-packages/spec.md @@ -48,6 +48,13 @@ The `@trails-cool/ui` package SHALL provide shared React components (buttons, la - **WHEN** an app renders the Button component from `@trails-cool/ui` - **THEN** a styled button is displayed consistent with the trails.cool design +### Requirement: FIT encoding package +The `@trails-cool/fit` package SHALL provide a `gpxToFitCourse` function that converts a GPX string to a FIT Course binary (`Uint8Array`) suitable for upload to Wahoo and other head units. It is the sole owner of FIT file generation; apps do not bundle their own FIT encoder. See `wahoo-route-push` spec for the full round-trip contract. + +#### Scenario: Import gpxToFitCourse in Journal +- **WHEN** the Journal app imports `@trails-cool/fit` +- **THEN** it has access to `gpxToFitCourse({ gpx, name })` returning a `Uint8Array` + ### Requirement: i18n package The `@trails-cool/i18n` package SHALL provide react-i18next configuration and translation strings starting with English and German. diff --git a/openspec/specs/wahoo-import/spec.md b/openspec/specs/wahoo-import/spec.md index 0f056e3..1cd1932 100644 --- a/openspec/specs/wahoo-import/spec.md +++ b/openspec/specs/wahoo-import/spec.md @@ -95,7 +95,7 @@ Imported activities SHALL show their origin in the UI. - **AND** the workout appears as importable again on the import page ### Requirement: FIT to GPX conversion -The system SHALL convert Wahoo's FIT binary files to GPX format. +The system SHALL convert FIT binary files to GPX format. The conversion logic lives at `apps/journal/app/lib/connected-services/fit.ts` — a provider-agnostic location shared across any future provider that produces FIT files (Garmin, Coros, etc.). Wahoo's importer and webhook both import from this shared module; they do not contain their own copy. #### Scenario: Convert FIT with GPS data - **WHEN** a FIT file contains GPS track records