Commit graph

937 commits

Author SHA1 Message Date
Ullrich Schäfer
9cf6398a76
ci: pin openspec via devDependency
Adds @fission-ai/openspec ^1.3.1 as a root devDependency so local and CI
run the same lockfile-pinned version, and dependabot can bump it. CI now
runs `pnpm openspec validate --all --strict` instead of npx.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-08 02:36:53 +02:00
Ullrich Schäfer
5b6fecf416
ci: fix openspec package name
The npm package `openspec` is an unrelated 0.0.0 placeholder; the real
CLI ships as `@fission-ai/openspec`.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-08 02:35:10 +02:00
Ullrich Schäfer
b78c7b77e0
ci: validate openspec specs and changes
Adds a fast standalone job that runs `openspec validate --all --strict`
via npx, gating PRs on spec/change well-formedness.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-08 02:33:39 +02:00
Ullrich Schäfer
1a0a212139
Merge pull request #366 from trails-cool/fix/mobile-terms-gate
fix: enforce Terms gate on bearer-token API requests
2026-05-08 02:06:19 +02:00
Ullrich Schäfer
1e43e96732
Archive mobile-terms-gate + sync spec delta
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-08 02:02:24 +02:00
Ullrich Schäfer
067e2ebd0b
fix: enforce Terms gate on bearer-token API requests
Mobile API requests authenticated via OAuth2 bearer tokens bypassed the
Terms gate that the root loader applies to web cookie sessions. Extend
requireApiUser to compare the user's termsVersion with TERMS_VERSION
and return a structured 403 { code: "TERMS_OUTDATED", currentTermsVersion }
on mismatch so mobile clients can surface their own re-acceptance UI.

Spec delta on journal-auth captures the new requirement.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-08 01:59:28 +02:00
Ullrich Schäfer
eee5689a75
Merge pull request #361 from trails-cool/architecture/deepen-connected-services
Deepen connected-services architecture (sync provider seam)
2026-05-08 01:39:44 +02:00
Ullrich Schäfer
7cd785e937
Archive deepen-connected-services + sync spec deltas
Task 7.3: applies the MODIFIED + ADDED requirements from
changes/deepen-connected-services/specs/ into openspec/specs/:

- connected-services/spec.md:
  - MODIFIED: OAuth token storage (renamed sync_connections → connected_services
    with credential_kind discriminator + JSONB credentials shape).
  - ADDED: Capability seams for providers (Importer / RoutePusher /
    WebhookReceiver per ADR-0002, no unified SyncProvider).
  - ADDED: Centralized credential lifecycle via ConnectedServiceManager.

- wahoo-import/spec.md: Provider-agnostic framework rewritten to reference
  capability seams + per-provider manifest. Token refresh now goes through
  withFreshCredentials. Renames sync_connections → connected_services
  throughout.

- wahoo-route-push/spec.md: Renames sync_connections → connected_services.
  ADDED: RoutePusher capability seam — shape (service, route) →
  {remoteId, version} per ADR-0003; Wahoo workarounds stay inside the
  adapter.

Change directory moved to openspec/changes/archive/2026-05-08-deepen-connected-services/.

29/29 tasks complete.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-08 01:36:19 +02:00
Ullrich Schäfer
14da6e6b53
Mark manual smoke test complete (task 6.3)
Verified live against local dev with HTTPS:
- Wahoo OAuth connect flow
- Import list (Importer.listImportable + withFreshCredentials)
- Single workout import
- Route push (POST then PUT after edit)
- Disconnect + reconnect (unique constraint upsert)

28/29 tasks complete. Only 7.3 (spec deltas at archive) remains —
applied automatically by /opsx:archive.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-08 01:33:12 +02:00
Ullrich Schäfer
e6212ad6fc
Annotate komoot-import design with deepen-connected-services supersession
Task 7.2: when komoot-import is implemented, it must use the
connected_services + web-login credential kind shape, not a separate
journal.integrations table. Note added to komoot-import/design.md
referencing ADR-0001 and CONTEXT.md.

Also marks tasks 6.2 (no Wahoo e2e tests exist; nothing to run) and
7.1 (no CONTEXT.md term changes during impl) complete in tasks.md.

Remaining: 6.3 (manual smoke), 6.4 (staging migration test), 7.3
(spec deltas at archive).

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-08 01:26:21 +02:00
Ullrich Schäfer
8e5b6d6fe9
Wahoo capability adapters + caller migration (groups 3-5)
Implements tasks 1.3, 3.2-3.3, 4.1-4.4, 5.1-5.6, 6.1 of
deepen-connected-services. Built TDD: contract test red, adapter green
for each capability seam.

Capability adapters (providers/wahoo/):
- importer.ts: Importer seam — listImportable + importOne against
  Wahoo /v1/workouts. Filters fitness_app_id >= 1000 (Wahoo doesn't
  share third-party data). 2 contract tests green.
- pusher.ts: RoutePusher seam — pushRoute(ctx, input) -> {remoteId,
  version}. FIT-Course conversion, route:<id> external_id, PUT-vs-POST
  decision, PUT->POST-on-404 fallback all internal to the adapter
  (per ADR-0003). Idempotency via sync_pushes preserved. 4 contract
  tests green.
- webhook.ts: WebhookReceiver seam — parseWebhook + handle. Routes
  events to local users via provider_user_id; unknown user returns
  silently. 6 contract tests green.
- manifest.ts: declares credential_kind=oauth, OAuth config, scopes,
  buildAuthUrl, exchangeCode, and references each capability adapter.

Module shape:
- connected-services/index.ts: side-effect imports providers/index.ts
  to register manifests, then re-exports manager + registry + types.
- connected-services/providers/index.ts: barrel that calls
  registerManifest(wahooManifest).
- connected-services/oauth-state.server.ts: OAuth state encode/decode
  (extracted from legacy pushes.server.ts).
- connected-services/push-action.server.ts: orchestration above the
  RoutePusher seam — load route, ownership check, scope check, build
  RoutePushInput, invoke pusher, return PushOutcome union. Replaces
  the legacy pushRouteToProvider in lib/sync/pushes.server.ts.

Caller migration (group 5):
- api.sync.connect.$provider.ts -> manifest.buildAuthUrl
- api.sync.callback.$provider.ts -> manifest.exchangeCode + link()
- api.sync.disconnect.$provider.ts -> unlinkByUserProvider (calls
  best-effort revoke via the credential adapter, then deletes locally)
- api.sync.webhook.$provider.ts -> manifest.webhookReceiver dispatch
- api.sync.push.$provider.$routeId.ts -> push-action.pushRouteToProvider
- sync.import.$provider.tsx -> manifest.importer.listImportable +
  inline FIT->GPX in the action (form-supplied metadata bypasses the
  Importer seam which is reserved for automatic / webhook imports)
- routes.$id.tsx -> getService instead of getConnection
- settings.connections.tsx -> getAllManifests instead of legacy registry

Legacy lib/sync/ deleted except imports.server.ts (which manages the
sync_imports table, untouched by this change).

DB migration verified locally (task 1.3): pnpm db:migrate-data renamed
the table and backfilled credentials JSONB; pnpm db:push then dropped
the legacy access_token/refresh_token/expires_at columns. Final shape
matches the schema; check constraints + unique index in place.

Test status (task 6.1):
- pnpm typecheck: green across all 15 workspaces
- pnpm lint: green
- @trails-cool/journal: 112 passed, 31 skipped — 12 fewer tests than
  before because pushes.server.test.ts and the legacy wahoo.test.ts
  were deleted. Their coverage is replaced by the new contract tests
  (importer/pusher/webhook) plus manager.test.ts + oauth.test.ts.

Remaining: 6.2 (e2e), 6.3-6.4 (manual smoke + staging migration test),
7.1-7.3 (followups + spec deltas at archive).

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-08 01:25:33 +02:00
Ullrich Schäfer
5dda69ab49
Lint fix: drop unused ProviderOAuthConfig type import
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-08 01:14:38 +02:00
Ullrich Schäfer
6de516718d
Schema rename + ConnectedServiceManager foundation (groups 1-2)
Implements tasks 1.1-1.4 and 2.1-2.5 of deepen-connected-services:

DB:
- Rename journal.sync_connections -> journal.connected_services.
- Add credential_kind discriminator (oauth | web-login | device) and
  credentials JSONB (shape per kind), status column, and a unique index
  on (user_id, provider) lifting the previously app-only invariant
  into the DB.
- Idempotent backfill in 0002_connected_services.sql moves existing
  Wahoo rows' tokens into the JSONB blob with credential_kind='oauth'.

Code:
- New apps/journal/app/lib/connected-services/ module:
  - types.ts: ConnectedService, CredentialKind, OAuthCredentials,
    NeedsRelinkError, CredentialAdapter, ProviderOAuthConfig, etc.
  - credential-adapters/oauth.ts: standard OAuth2 refresh_token flow,
    revoke endpoint, 4xx -> NeedsRelinkError / 5xx -> transient.
  - manager.ts: ConnectedServiceManager (link, unlink, withFreshCredentials,
    markNeedsRelink). Centralizes credential lifecycle in one chokepoint.
  - registry.ts: ProviderManifest type + capability seam interfaces
    (Importer, RoutePusher, WebhookReceiver). Manifests register
    themselves at import time.

Tests:
- manager.test.ts (8 tests): refresh-on-expired, refresh-fail->needs_relink,
  ConnectionNotActiveError, link/unlink, revoke is best-effort.
- credential-adapters/oauth.test.ts (10 tests): refresh contract,
  refresh_token retention, 4xx vs 5xx behaviour, revoke.
- All 18 new tests pass.

Compatibility:
- apps/journal/app/lib/sync/connections.server.ts is now a thin shim
  translating the legacy TokenSet API onto the JSONB-shaped table so
  existing callers (routes, pushes.server.ts) keep working until tasks
  5.x migrate them to the manager. To be deleted in task 5.6.

Pre-existing journal test failures (12) are unrelated to this change:
they pre-date this PR and stem from a workspace resolution issue with
@trails-cool/fit (verified by running tests against main).

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-08 01:14:38 +02:00
Ullrich Schäfer
cfba3146e2
Add deepen-connected-services architecture artifacts
Reshape the sync-providers seam before Komoot (web-login) and Apple
Health (device) adapters land. Captures the decisions in three ADRs,
seeds CONTEXT.md with Connected Services vocabulary, and proposes the
OpenSpec change covering schema rename + ConnectedServiceManager +
capability seams (Importer / RoutePusher / WebhookReceiver).

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-08 01:14:38 +02:00
Ullrich Schäfer
ede480e652
Merge pull request #365 from trails-cool/e2e-hydration-and-workers
Stabilize e2e against Vite dev hydration race
2026-05-08 01:13:33 +02:00
Ullrich Schäfer
e6dc809e08
Drop workers=1 — hydration helper is sufficient
The hydration helper alone fixes the flake; restoring CPU-count
workers locally cuts the suite from 55s to 22s. Cover the two
remaining /auth/login navigations the prior commit missed.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-08 01:10:15 +02:00
Ullrich Schäfer
b7ed54ba72
Stabilize e2e against Vite dev hydration race
Two issues caused the same class of flake locally:

1. Default workers were CPU-count, but the journal/planner are served
   by Vite dev (not the production build CI uses). Cold-compiling
   `/api/auth/register` under N parallel hits produced 30s timeouts
   on a quarter of runs. Set workers to 1 in both environments for
   parity with CI.
2. Even sequentially, a button is clickable per Playwright's
   actionability check before React has hydrated its `onClick`. So
   the first click after a navigation could fire native form submit
   (or do nothing), which manifested as "URL never changed to /" or
   "menuitem Log Out never appeared". Add a `waitForHydration` helper
   that polls for React fibers (`__reactProps$<id>`) attached to a
   DOM node and call it after each cross-page navigation that ends
   in an interactive form or dropdown.

CI is unaffected (production builds hydrate fast and didn't expose
either bug), but the helper is harmless there.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-08 01:06:27 +02:00
Ullrich Schäfer
fc2d0a02d5
Merge pull request #364 from trails-cool/e2e-silent-drop-sentry
Silently drop Sentry envelope requests in e2e fixture
2026-05-08 00:59:18 +02:00
Ullrich Schäfer
796dbea804
Silently drop Sentry envelope requests in e2e fixture
Two e2e tests intermittently failed with "unmocked external request"
when the Sentry browser SDK emitted an envelope to the real ingest
endpoint despite `enabled: false`. The BrowserTracing integration
captures the page-load transaction before init's enabled flag fully
propagates, so a single envelope leaks on cold start.

Add a SILENT_DROP list that aborts matching requests without recording
them as blocked, so legitimate missing-mock failures still surface.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-08 00:53:41 +02:00
Ullrich Schäfer
ddbf95f6bf
Merge pull request #363 from trails-cool/brouter-auto-segments
Auto-download BRouter segments on first container start
2026-05-08 00:47:17 +02:00
Ullrich Schäfer
46743a91db
Auto-download BRouter segments on first container start
Fresh `pnpm dev:services` checkouts came up with an empty
brouter_segments volume, so every routing request returned
"datafile not found" and the e2e suite's BRouter tests failed.

Add an entrypoint that runs download-segments.sh when /data/segments
has no rd5 files, then exec's the existing server command. Subsequent
starts find the populated volume and skip straight to the server.
Keep wget in the final image (previously stripped) so the entrypoint
can fetch segments at runtime.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-08 00:43:43 +02:00
Ullrich Schäfer
f1963aab7a
Merge pull request #362 from trails-cool/fit-typecheck
Add typescript to root devDependencies
2026-05-08 00:41:29 +02:00
Ullrich Schäfer
588323730f
Add typescript to root devDependencies
Workspace packages run `tsc` in their typecheck scripts but don't declare
typescript as a dep — they relied on it being hoisted. On a clean local
install the binary wasn't present at node_modules/.bin/tsc, so every
package failed with `tsc: command not found`. Declaring typescript at the
root makes the dependency explicit and removes the latent fragility.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-08 00:37:42 +02:00
Ullrich Schäfer
946cfe7e44
Merge pull request #360 from trails-cool/stigi/preview-comment-update
Update single PR comment across preview deploy + teardown
2026-05-04 07:21:24 +02:00
Ullrich Schäfer
bdf9270f88
Update single PR comment across preview deploy + teardown
The deploy job was creating a fresh comment on every push, so PRs
accumulated a wall of preview-URL comments. Now we look up the existing
comment by an HTML marker (`<!-- cd-staging:preview -->`) and edit it
in place — both on push and on teardown. Comment also gains a link to
the GitHub Actions run that produced the preview, plus the head SHA.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
2026-05-04 07:17:57 +02:00
Ullrich Schäfer
fbe9882455
Merge pull request #359 from trails-cool/stigi/caddyfile-staging-ports
Update Caddyfile staging upstreams to ports 3110/3111
2026-05-03 22:52:14 +02:00
Ullrich Schäfer
8f5de34e50
Update Caddyfile staging upstreams to ports 3110/3111
Companion to PR #358 which moved the staging compose ports off 3100/3101
(Loki conflict on the vSwitch). The Caddyfile staging blocks have the
upstream ports baked in so they need bumping too — already applied
manually on the flagship to unblock staging; this lands it in-repo so it
survives the next cd-infra deploy.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
2026-05-03 22:48:53 +02:00
Ullrich Schäfer
32ff7c81ec
Merge pull request #358 from trails-cool/stigi/staging-port-fix
Move persistent staging off port 3100 to avoid Loki conflict
2026-05-03 22:42:29 +02:00
Ullrich Schäfer
e93cfd2adb
Trigger cd-staging on its own config changes + workflow_dispatch
So a port bump or compose edit doesn't sit unapplied until the next
apps/ push, and so persistent staging can be redeployed manually
without forcing a no-op apps/ change.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
2026-05-03 22:39:16 +02:00
Ullrich Schäfer
34711550fc
Move persistent staging off port 3100 to avoid Loki conflict
Loki binds 10.0.0.2:3100 on the vSwitch interface so the BRouter host can
ship logs in. Persistent staging was trying to publish 0.0.0.0:3100 which
conflicts because Linux refuses 0.0.0.0:<P> when any specific-interface
:<P> is already in use. Move staging journal to 3110, planner to 3111.

PR previews are unaffected — they're already on 3200+2N.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
2026-05-03 22:38:38 +02:00
Ullrich Schäfer
c703bf4c76
Merge pull request #357 from trails-cool/stigi/preview-test
Test cd-staging preview lifecycle
2026-05-03 22:33:09 +02:00
Ullrich Schäfer
25d21161c5
Fix staging port binding + diagnostic ps env file
Two bugs in the staging-environments rollout:

1. Staging containers published on 127.0.0.1 are unreachable from the
   production Caddy container, which connects via the Docker bridge IP
   (host.docker.internal:host-gateway resolves to the bridge, not
   loopback). Bind to 0.0.0.0 instead — Hetzner Cloud firewall blocks
   ports 3000+ from the public internet, so it stays internal-only.

2. The trailing 'docker compose ps' diagnostic in deploy-staging /
   deploy-preview was missing --env-file staging.env, so compose
   failed env interpolation and the job exited non-zero even when the
   actual deploy succeeded.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
2026-05-03 22:30:05 +02:00
Ullrich Schäfer
7615ecb6e7
Test PR for staging preview lifecycle
Adds a one-line clarifying comment near TERMS_GATE_ALLOWLIST. The point
of this PR is to exercise cd-staging.yml end-to-end (preview deploy on
open, update on push, teardown on close).

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
2026-05-03 22:18:06 +02:00
Ullrich Schäfer
de5c96351c
Merge pull request #356 from trails-cool/stigi/staging-envs
Add staging + PR-preview environments on the flagship
2026-05-03 22:13:55 +02:00
Ullrich Schäfer
4c62c0b5aa
Merge branch 'main' into stigi/staging-envs 2026-05-03 22:10:25 +02:00
Ullrich Schäfer
c8a7a0b253
Add staging + PR-preview environments on the flagship
Implements the staging-environments OpenSpec change. Persistent staging at
staging.trails.cool / planner.staging.trails.cool deploys from main; PR
opens get a journal-only preview at pr-<N>.staging.trails.cool that shares
the persistent planner. cd-staging.yml builds tagged images, manages
per-PR Postgres databases and Caddyfile snippets, evicts the oldest
preview at the cap of 3, and tears everything down on PR close.
staging-cleanup.yml runs weekly to sweep orphaned previews.

DNS records (staging + *.staging A/AAAA) already applied to production
via tofu.

Caddy approach: per-PR Caddyfile snippets imported from /etc/caddy/sites/
and reloaded on each PR event — no wildcard / on-demand TLS, no router
service. Production compose gains a trails-shared network for the staging
project to reach Postgres, and host.docker.internal on Caddy so it can
reverse-proxy staging containers published on the host loopback.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
2026-05-03 22:03:38 +02:00
Ullrich Schäfer
de96c85172
Merge pull request #355 from trails-cool/stigi/index-capabilities
Index wahoo-route-push, demo-activity-bot, background-jobs
2026-05-03 21:43:35 +02:00
Ullrich Schäfer
cc1d5194b8
Index wahoo-route-push, demo-activity-bot, background-jobs in CAPABILITIES
Catch-up entries: wahoo-route-push (added in this PR's archive),
demo-activity-bot and background-jobs (created by PR #353 but missed
in the index). Renamed "Imports" group to "Imports & exports" so the
push capability has a sensible home.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
2026-05-03 21:40:10 +02:00
Ullrich Schäfer
795ec2215c
Merge pull request #354 from trails-cool/stigi/archive-wahoo-route
Archive wahoo-route-update
2026-05-03 21:39:36 +02:00
Ullrich Schäfer
6f6010cb51
Archive wahoo-route-update
Fold the wahoo-route-update delta into openspec/specs/wahoo-route-push/spec.md
(POST→PUT logic with 404 fallback, stable external_id, push-status UI) and
move the change directory to openspec/changes/archive/. Task 4.3 (Playwright
E2E) skipped — contract is fully covered by unit/integration tests in
wahoo.test.ts and pushes.server.test.ts.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
2026-05-03 21:36:15 +02:00
Ullrich Schäfer
a62b249aed
Merge pull request #352 from trails-cool/dependabot/npm_and_yarn/production-6f66162dcb
Bump the production group with 19 updates
2026-05-03 21:30:01 +02:00
Ullrich Schäfer
84cf0490d2
Merge branch 'main' into dependabot/npm_and_yarn/production-6f66162dcb 2026-05-03 21:26:49 +02:00
Ullrich Schäfer
16b82c6348
Merge pull request #353 from trails-cool/stigi/archivable-specs
Archive demo-activity-bot, pg-boss-background-jobs, configurable-demo-persona
2026-05-03 21:20:50 +02:00
Ullrich Schäfer
91e80ace36
Archive demo-activity-bot, pg-boss-background-jobs, configurable-demo-persona
Fold completed deltas into main specs (activity-feed, route-management,
infrastructure, planner-session), add new background-jobs and
demo-activity-bot capability specs, and move the three change dirs to
openspec/changes/archive/.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
2026-05-03 21:17:39 +02:00
dependabot[bot]
30ea93ae35 [github-actions] pnpm dedupe 2026-05-03 08:34:27 +00:00
dependabot[bot]
eec904971d
Bump the production group with 19 updates
Bumps the production group with 19 updates:

| Package | From | To |
| --- | --- | --- |
| [expo](https://github.com/expo/expo/tree/HEAD/packages/expo) | `55.0.17` | `55.0.19` |
| [@sentry/vite-plugin](https://github.com/getsentry/sentry-javascript-bundler-plugins) | `5.2.0` | `5.2.1` |
| [eslint](https://github.com/eslint/eslint) | `10.2.1` | `10.3.0` |
| [jsdom](https://github.com/jsdom/jsdom) | `29.0.2` | `29.1.1` |
| [react-i18next](https://github.com/i18next/react-i18next) | `17.0.4` | `17.0.6` |
| [turbo](https://github.com/vercel/turborepo) | `2.9.6` | `2.9.8` |
| [typescript-eslint](https://github.com/typescript-eslint/typescript-eslint/tree/HEAD/packages/typescript-eslint) | `8.59.0` | `8.59.1` |
| [jose](https://github.com/panva/jose) | `6.2.2` | `6.2.3` |
| [nodemailer](https://github.com/nodemailer/nodemailer) | `8.0.6` | `8.0.7` |
| [zod](https://github.com/colinhacks/zod) | `4.3.6` | `4.4.2` |
| [@gorhom/bottom-sheet](https://github.com/gorhom/react-native-bottom-sheet) | `5.2.10` | `5.2.13` |
| [@sentry/cli](https://github.com/getsentry/sentry-cli) | `3.4.0` | `3.4.1` |
| [@sentry/react-native](https://github.com/getsentry/sentry-react-native) | `8.9.1` | `8.10.0` |
| [expo-dev-client](https://github.com/expo/expo/tree/HEAD/packages/expo-dev-client) | `55.0.28` | `55.0.30` |
| [expo-dev-menu](https://github.com/expo/expo/tree/HEAD/packages/expo-dev-menu) | `55.0.24` | `55.0.26` |
| [expo-notifications](https://github.com/expo/expo/tree/HEAD/packages/expo-notifications) | `55.0.20` | `55.0.22` |
| [pg-boss](https://github.com/timgit/pg-boss) | `12.18.0` | `12.18.2` |
| [@sentry/node](https://github.com/getsentry/sentry-javascript) | `10.50.0` | `10.51.0` |
| [@sentry/react](https://github.com/getsentry/sentry-javascript) | `10.49.0` | `10.51.0` |


Updates `expo` from 55.0.17 to 55.0.19
- [Changelog](https://github.com/expo/expo/blob/main/CHANGELOG.md)
- [Commits](https://github.com/expo/expo/commits/HEAD/packages/expo)

Updates `@sentry/vite-plugin` from 5.2.0 to 5.2.1
- [Release notes](https://github.com/getsentry/sentry-javascript-bundler-plugins/releases)
- [Changelog](https://github.com/getsentry/sentry-javascript-bundler-plugins/blob/main/CHANGELOG.md)
- [Commits](https://github.com/getsentry/sentry-javascript-bundler-plugins/compare/5.2.0...5.2.1)

Updates `eslint` from 10.2.1 to 10.3.0
- [Release notes](https://github.com/eslint/eslint/releases)
- [Commits](https://github.com/eslint/eslint/compare/v10.2.1...v10.3.0)

Updates `jsdom` from 29.0.2 to 29.1.1
- [Release notes](https://github.com/jsdom/jsdom/releases)
- [Commits](https://github.com/jsdom/jsdom/compare/v29.0.2...v29.1.1)

Updates `react-i18next` from 17.0.4 to 17.0.6
- [Changelog](https://github.com/i18next/react-i18next/blob/master/CHANGELOG.md)
- [Commits](https://github.com/i18next/react-i18next/compare/v17.0.4...v17.0.6)

Updates `turbo` from 2.9.6 to 2.9.8
- [Release notes](https://github.com/vercel/turborepo/releases)
- [Changelog](https://github.com/vercel/turborepo/blob/main/RELEASE.md)
- [Commits](https://github.com/vercel/turborepo/compare/v2.9.6...v2.9.8)

Updates `typescript-eslint` from 8.59.0 to 8.59.1
- [Release notes](https://github.com/typescript-eslint/typescript-eslint/releases)
- [Changelog](https://github.com/typescript-eslint/typescript-eslint/blob/main/packages/typescript-eslint/CHANGELOG.md)
- [Commits](https://github.com/typescript-eslint/typescript-eslint/commits/v8.59.1/packages/typescript-eslint)

Updates `jose` from 6.2.2 to 6.2.3
- [Release notes](https://github.com/panva/jose/releases)
- [Changelog](https://github.com/panva/jose/blob/main/CHANGELOG.md)
- [Commits](https://github.com/panva/jose/compare/v6.2.2...v6.2.3)

Updates `nodemailer` from 8.0.6 to 8.0.7
- [Release notes](https://github.com/nodemailer/nodemailer/releases)
- [Changelog](https://github.com/nodemailer/nodemailer/blob/master/CHANGELOG.md)
- [Commits](https://github.com/nodemailer/nodemailer/compare/v8.0.6...v8.0.7)

Updates `zod` from 4.3.6 to 4.4.2
- [Release notes](https://github.com/colinhacks/zod/releases)
- [Commits](https://github.com/colinhacks/zod/compare/v4.3.6...v4.4.2)

Updates `@gorhom/bottom-sheet` from 5.2.10 to 5.2.13
- [Release notes](https://github.com/gorhom/react-native-bottom-sheet/releases)
- [Changelog](https://github.com/gorhom/react-native-bottom-sheet/blob/master/CHANGELOG.md)
- [Commits](https://github.com/gorhom/react-native-bottom-sheet/compare/v5.2.10...v5.2.13)

Updates `@sentry/cli` from 3.4.0 to 3.4.1
- [Release notes](https://github.com/getsentry/sentry-cli/releases)
- [Changelog](https://github.com/getsentry/sentry-cli/blob/master/CHANGELOG.md)
- [Commits](https://github.com/getsentry/sentry-cli/compare/3.4.0...3.4.1)

Updates `@sentry/react-native` from 8.9.1 to 8.10.0
- [Release notes](https://github.com/getsentry/sentry-react-native/releases)
- [Changelog](https://github.com/getsentry/sentry-react-native/blob/main/CHANGELOG.md)
- [Commits](https://github.com/getsentry/sentry-react-native/compare/8.9.1...8.10.0)

Updates `expo-dev-client` from 55.0.28 to 55.0.30
- [Changelog](https://github.com/expo/expo/blob/main/CHANGELOG.md)
- [Commits](https://github.com/expo/expo/commits/HEAD/packages/expo-dev-client)

Updates `expo-dev-menu` from 55.0.24 to 55.0.26
- [Changelog](https://github.com/expo/expo/blob/main/CHANGELOG.md)
- [Commits](https://github.com/expo/expo/commits/HEAD/packages/expo-dev-menu)

Updates `expo-notifications` from 55.0.20 to 55.0.22
- [Changelog](https://github.com/expo/expo/blob/main/CHANGELOG.md)
- [Commits](https://github.com/expo/expo/commits/HEAD/packages/expo-notifications)

Updates `pg-boss` from 12.18.0 to 12.18.2
- [Release notes](https://github.com/timgit/pg-boss/releases)
- [Commits](https://github.com/timgit/pg-boss/compare/12.18.0...12.18.2)

Updates `@sentry/node` from 10.50.0 to 10.51.0
- [Release notes](https://github.com/getsentry/sentry-javascript/releases)
- [Changelog](https://github.com/getsentry/sentry-javascript/blob/develop/CHANGELOG.md)
- [Commits](https://github.com/getsentry/sentry-javascript/compare/10.50.0...10.51.0)

Updates `@sentry/react` from 10.49.0 to 10.51.0
- [Release notes](https://github.com/getsentry/sentry-javascript/releases)
- [Changelog](https://github.com/getsentry/sentry-javascript/blob/develop/CHANGELOG.md)
- [Commits](https://github.com/getsentry/sentry-javascript/compare/10.49.0...10.51.0)

---
updated-dependencies:
- dependency-name: expo
  dependency-version: 55.0.19
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: production
- dependency-name: "@sentry/vite-plugin"
  dependency-version: 5.2.1
  dependency-type: direct:development
  update-type: version-update:semver-patch
  dependency-group: production
- dependency-name: eslint
  dependency-version: 10.3.0
  dependency-type: direct:development
  update-type: version-update:semver-minor
  dependency-group: production
- dependency-name: jsdom
  dependency-version: 29.1.1
  dependency-type: direct:development
  update-type: version-update:semver-minor
  dependency-group: production
- dependency-name: react-i18next
  dependency-version: 17.0.6
  dependency-type: direct:development
  update-type: version-update:semver-patch
  dependency-group: production
- dependency-name: turbo
  dependency-version: 2.9.8
  dependency-type: direct:development
  update-type: version-update:semver-patch
  dependency-group: production
- dependency-name: typescript-eslint
  dependency-version: 8.59.1
  dependency-type: direct:development
  update-type: version-update:semver-patch
  dependency-group: production
- dependency-name: jose
  dependency-version: 6.2.3
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: production
- dependency-name: nodemailer
  dependency-version: 8.0.7
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: production
- dependency-name: zod
  dependency-version: 4.4.2
  dependency-type: direct:production
  update-type: version-update:semver-minor
  dependency-group: production
- dependency-name: "@gorhom/bottom-sheet"
  dependency-version: 5.2.13
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: production
- dependency-name: "@sentry/cli"
  dependency-version: 3.4.1
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: production
- dependency-name: "@sentry/react-native"
  dependency-version: 8.10.0
  dependency-type: direct:production
  update-type: version-update:semver-minor
  dependency-group: production
- dependency-name: expo-dev-client
  dependency-version: 55.0.30
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: production
- dependency-name: expo-dev-menu
  dependency-version: 55.0.26
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: production
- dependency-name: expo-notifications
  dependency-version: 55.0.22
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: production
- dependency-name: pg-boss
  dependency-version: 12.18.2
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: production
- dependency-name: "@sentry/node"
  dependency-version: 10.51.0
  dependency-type: direct:production
  update-type: version-update:semver-minor
  dependency-group: production
- dependency-name: "@sentry/react"
  dependency-version: 10.51.0
  dependency-type: direct:production
  update-type: version-update:semver-minor
  dependency-group: production
...

Signed-off-by: dependabot[bot] <support@github.com>
2026-05-03 08:33:39 +00:00
Ullrich Schäfer
0254b2afd7
Merge pull request #351 from trails-cool/stigi/wahoo-route-update
Apply wahoo-route-update: PUT on re-push
2026-05-01 12:12:21 +02:00
Ullrich Schäfer
db3eeed60f
Apply wahoo-route-update: PUT on re-push instead of duplicate POST
Re-pushing an edited route to Wahoo now updates the existing remote
route via PUT against the stored remote_id instead of POSTing a new
copy. external_id drops the version suffix and identifies the logical
route. sync_pushes is keyed by (user, route, provider) and tracks
last_pushed_version for the "local newer" UI state.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
2026-05-01 12:08:16 +02:00
Ullrich Schäfer
4853a116ff
Merge pull request #350 from trails-cool/stigi/wahoo-openspec
Add openspec changes for Wahoo production cutover and route updates
2026-05-01 11:52:50 +02:00
Ullrich Schäfer
6a752e4933
Add openspec changes for Wahoo production cutover and route updates
- wahoo-production-cutover: ops checklist for moving the Wahoo Cloud
  API integration from sandbox to production tier (new app
  registration, logo upload, forced reauthorization).
- wahoo-route-update: switch the route push pipeline from POST-per-
  version to POST-then-PUT so re-pushing an edited route updates the
  existing Wahoo route instead of creating a duplicate.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
2026-05-01 11:37:42 +02:00