Commit graph

981 commits

Author SHA1 Message Date
Ullrich Schäfer
e5cb10fadc
Merge branch 'main' into stigi/visual-tests-ci 2026-05-10 19:23:13 +02:00
stigi
78a5a37214 chore: update visual snapshots [skip ci] 2026-05-10 17:15:46 +00:00
Ullrich Schäfer
4f8af21550
Fix update-visual-snapshots workflow: action versions + node version
- Switch checkout/setup-node/setup-pnpm to @v6 to match CI
- Replace node-version-file (.nvmrc doesn't exist) with node-version: 24
- Switch upload-artifact to @v7 to match CI

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-10 19:14:33 +02:00
Ullrich Schäfer
7c924827c9
Add initial visual snapshots and fix update script flag
Generate baseline screenshots (macOS/Chromium) for the elevation-chart
visual regression suite. The CI update-visual-snapshots workflow will
overwrite these with Linux variants on the first run.

Also fix the test:visual:update script: --update-snapshots is not a
valid Vitest 4 flag; the correct short form is -u.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-10 19:09:00 +02:00
Ullrich Schäfer
76028d277d
Remove invalid oxc.transform config from browser vitest config
OxcOptions doesn't have a transform key — Vite 8 handles TSX automatically.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-10 19:05:15 +02:00
Ullrich Schäfer
fcc4f88379
Fix Vitest browser provider setup and test cleanup
- Add @vitest/browser-playwright; use playwright() factory (not string)
- Import page from vitest/browser (not deprecated @vitest/browser/context)
- Add afterEach(cleanup) so each test gets a fresh DOM
- Use oxc transform for JSX instead of esbuild (avoids Vite 8 warning)

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-10 19:01:24 +02:00
Ullrich Schäfer
49c0b2d1f4
Add visual-tests job to CI
Runs Vitest browser visual regression tests (drawElevationChart) on every
PR and push to main. Uses the same Playwright/Chromium cache as the e2e job.

On first run (no committed snapshots yet) the tests create the snapshots and
pass. On subsequent runs they compare against committed snapshots and fail on
visual regression. Failed runs upload a visual-snapshots-diff artifact so the
diff is visible in the Actions UI.

To update snapshots after an intentional visual change:
  Actions → "Update visual snapshots" → Run workflow (or add the
  `update-snapshots` label to the PR).

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-10 18:56:57 +02:00
Ullrich Schäfer
01ab34c8d7
Merge pull request #379 from trails-cool/stigi/planner-component-split
Split ElevationChart + PlannerMap into deep modules; add visual regression testing
2026-05-10 16:45:15 +02:00
Ullrich Schäfer
34529a9432
Split ElevationChart + PlannerMap into deep modules; add visual regression testing
ElevationChart (1013 lines) split into:
- elevation-chart-draw.ts — pure drawElevationChart(ctx, w, h, params) function
- use-elevation-data.ts — useElevationData(routeData) hook
- ElevationChart.tsx — ~300 lines, interaction + render only

PlannerMap (869 lines) split into:
- MapHelpers.tsx — 7 Leaflet sub-components (MapExposer, RouteFitter, MapClickHandler,
  CursorTracker, NoGoAreaButton, OverlaySync, PoiRefresher)
- use-waypoint-manager.ts — all waypoint CRUD + route data sync
- use-gpx-drop.ts — GPX drag-and-drop hook
- PlannerMap.tsx — ~200 lines, orchestration only

Add Vitest browser visual regression tests for drawElevationChart via
@vitest/browser + Playwright (toMatchScreenshot). Tests cover plain, grade,
elevation, surface color modes plus hover and drag-select states.

Add update-visual-snapshots.yml workflow: triggered by workflow_dispatch or
the `update-snapshots` PR label; commits snapshots back to the branch.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-10 16:41:23 +02:00
Ullrich Schäfer
f843915c5a
Merge pull request #378 from trails-cool/stigi/spec-drift-catchup
Spec drift catch-up: FIT location, notification payload fields, shared-packages
2026-05-10 16:05:09 +02:00
Ullrich Schäfer
6c5fb6df0e
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 <noreply@anthropic.com>
2026-05-10 16:02:13 +02:00
Ullrich Schäfer
e6babd012a
Merge pull request #377 from trails-cool/stigi/arch-deepening-3-1-6
Deepen three architectural seams: FIT consolidation, host election, injectable db
2026-05-10 15:55:43 +02:00
Ullrich Schäfer
e387e1f798
Deepen three architectural seams: FIT consolidation, host election extraction, injectable db
- Extract shared fitToGpx into connected-services/fit.ts (FIT is a Garmin
  open standard used by Wahoo, Coros, Garmin — not provider-specific)
- Add importActivity() to sync/imports.server.ts so providers call one
  function instead of createActivity + recordImport separately; eliminates
  direct dependency on activities.server.ts from provider adapters
- Update wahoo importer + webhook to use both shared helpers
- Extract useHostElection(yjs) hook from useRouting so host election is
  independently testable without mounting the full routing stack
- Add setDb() to journal db.ts for module-level injection in unit tests

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-10 15:52:31 +02:00
Ullrich Schäfer
48d97be8f1
Merge pull request #376 from trails-cool/stigi/callback-e2e-test
Add e2e tests for Planner callback → geometry stored atomically
2026-05-10 15:27:59 +02:00
Ullrich Schäfer
557244ee87
Fix unused import lint error in api.e2e.route.$id.ts 2026-05-10 15:24:31 +02:00
Ullrich Schäfer
e7a0c132b9
Add e2e tests for Planner callback → geometry stored atomically
Introduces two E2E=true-gated test endpoints:
- POST /api/e2e/seed — creates a test user + bare route, returns routeId + JWT
- GET /api/e2e/route/:id — returns { hasGeom } for post-callback assertions

Three new integration tests:
- valid GPX via callback stores geometry (hasGeom = true)
- invalid GPX (< 2 track points) returns 400, geometry not stored
- missing token returns 401

CI: E2E=true added to the "Run E2E tests" step so the seed endpoints
are enabled when react-router-serve runs during the Playwright job.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-10 15:18:33 +02:00
Ullrich Schäfer
4189187dd4
Merge pull request #375 from trails-cool/stigi/atomic-gpx-save
Atomic GPX save: validate + persist row + geometry in one transaction
2026-05-10 15:15:05 +02:00
Ullrich Schäfer
abc3fbaa5b
Archive atomic-gpx-save + sync gpx-save spec to main
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-10 15:09:15 +02:00
Ullrich Schäfer
b17f8eb02a
Revert archive of atomic-gpx-save (will redo via skill) 2026-05-10 15:07:54 +02:00
Ullrich Schäfer
b4ef8b0e0e
Archive atomic-gpx-save change
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-10 15:06:55 +02:00
Ullrich Schäfer
78b8b8f55f
Atomic GPX save: validate + persist row + geometry in one transaction
Eliminates the silent-failure pattern where a route/activity row could
be committed with gpx IS NOT NULL but geom IS NULL if the PostGIS write
failed after the row insert.

- New gpx-save.server.ts owns all GPX validation (GpxValidationError,
  validateGpx) and PostGIS geometry writes (writeGeom, tx-aware)
- createRoute, updateRoute, createActivity, createRouteFromActivity all
  wrapped in db.transaction() covering row + geom + version snapshot
- demo-bot uses createRoute/createActivity instead of raw inserts;
  errors propagate loudly
- Callback endpoint returns 400 for GpxValidationError instead of 401
- ADR-0006 documents the invariant for future explorers

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-10 15:02:56 +02:00
Ullrich Schäfer
8ae58a2d26
Merge pull request #373 from trails-cool/dependabot/npm_and_yarn/development-c6c1c67e4a
Bump fit-file-parser from 2.3.3 to 3.0.0 in the development group across 1 directory
2026-05-10 13:27:13 +02:00
Ullrich Schäfer
890e1f3655
Merge branch 'main' into dependabot/npm_and_yarn/development-c6c1c67e4a 2026-05-10 13:24:03 +02:00
Ullrich Schäfer
b3003e8e80
Merge pull request #371 from trails-cool/dependabot/github_actions/peter-evans/find-comment-4
Bump peter-evans/find-comment from 3 to 4
2026-05-10 13:23:44 +02:00
Ullrich Schäfer
0aba220212
Merge branch 'main' into dependabot/github_actions/peter-evans/find-comment-4 2026-05-10 13:19:57 +02:00
Ullrich Schäfer
2ba43767db
Merge pull request #370 from trails-cool/dependabot/github_actions/peter-evans/create-or-update-comment-5
Bump peter-evans/create-or-update-comment from 4 to 5
2026-05-10 13:19:37 +02:00
dependabot[bot]
0e8978452a
Bump peter-evans/find-comment from 3 to 4
Bumps [peter-evans/find-comment](https://github.com/peter-evans/find-comment) from 3 to 4.
- [Release notes](https://github.com/peter-evans/find-comment/releases)
- [Commits](https://github.com/peter-evans/find-comment/compare/v3...v4)

---
updated-dependencies:
- dependency-name: peter-evans/find-comment
  dependency-version: '4'
  dependency-type: direct:production
  update-type: version-update:semver-major
...

Signed-off-by: dependabot[bot] <support@github.com>
2026-05-10 11:11:47 +00:00
dependabot[bot]
8f635fd5d1
Bump peter-evans/create-or-update-comment from 4 to 5
Bumps [peter-evans/create-or-update-comment](https://github.com/peter-evans/create-or-update-comment) from 4 to 5.
- [Release notes](https://github.com/peter-evans/create-or-update-comment/releases)
- [Commits](https://github.com/peter-evans/create-or-update-comment/compare/v4...v5)

---
updated-dependencies:
- dependency-name: peter-evans/create-or-update-comment
  dependency-version: '5'
  dependency-type: direct:production
  update-type: version-update:semver-major
...

Signed-off-by: dependabot[bot] <support@github.com>
2026-05-10 11:11:45 +00:00
Ullrich Schäfer
984b67963a
Merge pull request #374 from trails-cool/fix/preview-deploy-race
Fix concurrent preview deploy race: per-PR env files + server flock
2026-05-10 13:10:46 +02:00
dependabot[bot]
9c5cd7d6e8
Bump fit-file-parser in the development group across 1 directory
Bumps the development group with 1 update in the / directory: [fit-file-parser](https://github.com/jimmykane/fit-parser).


Updates `fit-file-parser` from 2.3.3 to 3.0.0
- [Changelog](https://github.com/jimmykane/fit-parser/blob/master/CHANGELOG.md)
- [Commits](https://github.com/jimmykane/fit-parser/commits)

---
updated-dependencies:
- dependency-name: fit-file-parser
  dependency-version: 3.0.0
  dependency-type: direct:development
  update-type: version-update:semver-major
  dependency-group: development
...

Signed-off-by: dependabot[bot] <support@github.com>
2026-05-10 11:09:33 +00:00
Ullrich Schäfer
be69abc0ee
Merge branch 'main' into fix/preview-deploy-race 2026-05-10 13:06:48 +02:00
Ullrich Schäfer
c42dff7f37
Merge pull request #372 from trails-cool/dependabot/npm_and_yarn/production-69e9f3c6a7
Bump the production group with 41 updates
2026-05-10 13:06:38 +02:00
Ullrich Schäfer
e23751f29e
Fix concurrent preview deploy race: per-PR env files + server flock
Three changes:

1. Skip GH-Actions-only Dependabot PRs (dependabot/github_actions/*) in
   deploy-preview — there is no app image to preview, and these PRs were
   landing phantom containers with mismatched ports.

2. Use per-PR env files (staging-pr-{N}.env) instead of the shared
   staging.env for preview deploys and teardowns. Concurrent SCP transfers
   to the same filename were overwriting each other, causing wrong
   JOURNAL_HOST_PORT / JOURNAL_IMAGE_TAG values to be used.

3. Serialize server-side deploy operations with a flock on
   /tmp/trails-preview-deploy.lock (300s timeout). Eviction + compose up
   must be atomic; without the lock, two simultaneous jobs could both see
   "3 active previews" and both evict different projects, or one could
   start compose up against a just-evicted env.

Triggered by a Dependabot batch today (PRs 371-373) that opened
simultaneously and produced a phantom trails-pr-371 container running
the pr-370 image on port 3940 while the Caddyfile expected 3942,
causing sustained 502s on pr-371.staging.trails.cool.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-10 13:03:52 +02:00
Ullrich Schäfer
6cd779ae02
Merge branch 'main' into dependabot/npm_and_yarn/production-69e9f3c6a7 2026-05-10 13:03:21 +02:00
Ullrich Schäfer
952480e077
Merge pull request #367 from trails-cool/architecture/unify-auth-completion
Centralize web auth completion in completeAuth
2026-05-10 12:55:21 +02:00
Ullrich Schäfer
c86b444ece
Merge branch 'main' into architecture/unify-auth-completion 2026-05-10 12:51:23 +02:00
dependabot[bot]
9c985d908c [github-actions] pnpm dedupe 2026-05-10 08:43:29 +00:00
dependabot[bot]
9cc08a725a
Bump the production group with 41 updates
Bumps the production group with 41 updates:

| Package | From | To |
| --- | --- | --- |
| [expo](https://github.com/expo/expo/tree/HEAD/packages/expo) | `55.0.19` | `55.0.23` |
| [react](https://github.com/facebook/react/tree/HEAD/packages/react) | `19.2.5` | `19.2.0` |
| [@expo/fingerprint](https://github.com/expo/expo/tree/HEAD/packages/@expo/fingerprint) | `0.16.6` | `0.16.7` |
| [i18next](https://github.com/i18next/i18next) | `26.0.8` | `26.0.10` |
| [react-i18next](https://github.com/i18next/react-i18next) | `17.0.6` | `17.0.7` |
| [turbo](https://github.com/vercel/turborepo) | `2.9.8` | `2.9.12` |
| [typescript-eslint](https://github.com/typescript-eslint/typescript-eslint/tree/HEAD/packages/typescript-eslint) | `8.59.1` | `8.59.2` |
| [isbot](https://github.com/omrilotan/isbot) | `5.1.39` | `5.1.40` |
| [zod](https://github.com/colinhacks/zod) | `4.4.2` | `4.4.3` |
| [@expo/metro-runtime](https://github.com/expo/expo) | `55.0.10` | `55.0.11` |
| [@gorhom/bottom-sheet](https://github.com/gorhom/react-native-bottom-sheet) | `5.2.13` | `5.2.14` |
| [@maplibre/maplibre-react-native](https://github.com/maplibre/maplibre-react-native) | `11.0.2` | `11.1.1` |
| [@sentry/react-native](https://github.com/getsentry/sentry-react-native) | `8.10.0` | `8.11.0` |
| [expo-constants](https://github.com/expo/expo/tree/HEAD/packages/expo-constants) | `55.0.15` | `55.0.16` |
| [expo-dev-client](https://github.com/expo/expo/tree/HEAD/packages/expo-dev-client) | `55.0.30` | `55.0.32` |
| [expo-dev-menu](https://github.com/expo/expo/tree/HEAD/packages/expo-dev-menu) | `55.0.26` | `55.0.27` |
| [expo-device](https://github.com/expo/expo/tree/HEAD/packages/expo-device) | `55.0.15` | `55.0.16` |
| [expo-file-system](https://github.com/expo/expo/tree/HEAD/packages/expo-file-system) | `55.0.17` | `55.0.19` |
| [expo-linking](https://github.com/expo/expo/tree/HEAD/packages/expo-linking) | `55.0.14` | `55.0.15` |
| [expo-location](https://github.com/expo/expo/tree/HEAD/packages/expo-location) | `55.1.8` | `55.1.9` |
| [expo-router](https://github.com/expo/expo/tree/HEAD/packages/expo-router) | `55.0.13` | `55.0.14` |
| [expo-splash-screen](https://github.com/expo/expo/tree/HEAD/packages/expo-splash-screen) | `55.0.19` | `55.0.20` |
| [expo-status-bar](https://github.com/expo/expo/tree/HEAD/packages/expo-status-bar) | `55.0.5` | `55.0.6` |
| [expo-system-ui](https://github.com/expo/expo/tree/HEAD/packages/expo-system-ui) | `55.0.16` | `55.0.17` |
| [expo-web-browser](https://github.com/expo/expo/tree/HEAD/packages/expo-web-browser) | `55.0.14` | `55.0.15` |
| [react-native-gesture-handler](https://github.com/software-mansion/react-native-gesture-handler) | `2.31.1` | `2.31.2` |
| [react-native-reanimated](https://github.com/software-mansion/react-native-reanimated/tree/HEAD/packages/react-native-reanimated) | `4.3.0` | `4.3.1` |
| [jest-expo](https://github.com/expo/expo/tree/HEAD/packages/jest-expo) | `55.0.16` | `55.0.17` |
| [react-test-renderer](https://github.com/facebook/react/tree/HEAD/packages/react-test-renderer) | `19.2.5` | `19.2.6` |
| [@codemirror/view](https://github.com/codemirror/view) | `6.41.1` | `6.42.1` |
| [@react-router/dev](https://github.com/remix-run/react-router/tree/HEAD/packages/react-router-dev) | `7.14.2` | `7.15.0` |
| [@react-router/node](https://github.com/remix-run/react-router/tree/HEAD/packages/react-router-node) | `7.14.2` | `7.15.0` |
| [@react-router/serve](https://github.com/remix-run/react-router/tree/HEAD/packages/react-router-serve) | `7.14.2` | `7.15.0` |
| [@sentry/node](https://github.com/getsentry/sentry-javascript) | `10.51.0` | `10.52.0` |
| [@sentry/react](https://github.com/getsentry/sentry-javascript) | `10.51.0` | `10.52.0` |
| [@tailwindcss/vite](https://github.com/tailwindlabs/tailwindcss/tree/HEAD/packages/@tailwindcss-vite) | `4.2.4` | `4.3.0` |
| [@types/node](https://github.com/DefinitelyTyped/DefinitelyTyped/tree/HEAD/types/node) | `22.19.17` | `22.19.18` |
| [react-dom](https://github.com/facebook/react/tree/HEAD/packages/react-dom) | `19.2.5` | `19.2.6` |
| [react-router](https://github.com/remix-run/react-router/tree/HEAD/packages/react-router) | `7.14.2` | `7.15.0` |
| [tailwindcss](https://github.com/tailwindlabs/tailwindcss/tree/HEAD/packages/tailwindcss) | `4.2.4` | `4.3.0` |
| [vite](https://github.com/vitejs/vite/tree/HEAD/packages/vite) | `7.3.2` | `7.3.3` |


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

Updates `react` from 19.2.5 to 19.2.0
- [Release notes](https://github.com/facebook/react/releases)
- [Changelog](https://github.com/facebook/react/blob/main/CHANGELOG.md)
- [Commits](https://github.com/facebook/react/commits/v19.2.0/packages/react)

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

Updates `i18next` from 26.0.8 to 26.0.10
- [Release notes](https://github.com/i18next/i18next/releases)
- [Changelog](https://github.com/i18next/i18next/blob/master/CHANGELOG.md)
- [Commits](https://github.com/i18next/i18next/compare/v26.0.8...v26.0.10)

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

Updates `turbo` from 2.9.8 to 2.9.12
- [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.8...v2.9.12)

Updates `typescript-eslint` from 8.59.1 to 8.59.2
- [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.2/packages/typescript-eslint)

Updates `isbot` from 5.1.39 to 5.1.40
- [Changelog](https://github.com/omrilotan/isbot/blob/main/CHANGELOG.md)
- [Commits](https://github.com/omrilotan/isbot/compare/v5.1.39...v5.1.40)

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

Updates `@expo/metro-runtime` from 55.0.10 to 55.0.11
- [Changelog](https://github.com/expo/expo/blob/main/CHANGELOG.md)
- [Commits](https://github.com/expo/expo/commits)

Updates `@gorhom/bottom-sheet` from 5.2.13 to 5.2.14
- [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.13...v5.2.14)

Updates `@maplibre/maplibre-react-native` from 11.0.2 to 11.1.1
- [Release notes](https://github.com/maplibre/maplibre-react-native/releases)
- [Changelog](https://github.com/maplibre/maplibre-react-native/blob/main/CHANGELOG.md)
- [Commits](https://github.com/maplibre/maplibre-react-native/compare/v11.0.2...v11.1.1)

Updates `@sentry/react-native` from 8.10.0 to 8.11.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.10.0...8.11.0)

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

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

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

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

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

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

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

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

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

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

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

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

Updates `react-native-gesture-handler` from 2.31.1 to 2.31.2
- [Release notes](https://github.com/software-mansion/react-native-gesture-handler/releases)
- [Commits](https://github.com/software-mansion/react-native-gesture-handler/compare/v2.31.1...v2.31.2)

Updates `react-native-reanimated` from 4.3.0 to 4.3.1
- [Release notes](https://github.com/software-mansion/react-native-reanimated/releases)
- [Changelog](https://github.com/software-mansion/react-native-reanimated/blob/main/packages/react-native-reanimated/RELEASE.md)
- [Commits](https://github.com/software-mansion/react-native-reanimated/commits/4.3.1/packages/react-native-reanimated)

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

Updates `react-test-renderer` from 19.2.5 to 19.2.6
- [Release notes](https://github.com/facebook/react/releases)
- [Changelog](https://github.com/facebook/react/blob/main/CHANGELOG.md)
- [Commits](https://github.com/facebook/react/commits/v19.2.6/packages/react-test-renderer)

Updates `@codemirror/view` from 6.41.1 to 6.42.1
- [Changelog](https://github.com/codemirror/view/blob/main/CHANGELOG.md)
- [Commits](https://github.com/codemirror/view/commits)

Updates `@react-router/dev` from 7.14.2 to 7.15.0
- [Release notes](https://github.com/remix-run/react-router/releases)
- [Changelog](https://github.com/remix-run/react-router/blob/main/packages/react-router-dev/CHANGELOG.md)
- [Commits](https://github.com/remix-run/react-router/commits/@react-router/dev@7.15.0/packages/react-router-dev)

Updates `@react-router/node` from 7.14.2 to 7.15.0
- [Release notes](https://github.com/remix-run/react-router/releases)
- [Changelog](https://github.com/remix-run/react-router/blob/main/packages/react-router-node/CHANGELOG.md)
- [Commits](https://github.com/remix-run/react-router/commits/@react-router/node@7.15.0/packages/react-router-node)

Updates `@react-router/serve` from 7.14.2 to 7.15.0
- [Release notes](https://github.com/remix-run/react-router/releases)
- [Changelog](https://github.com/remix-run/react-router/blob/main/packages/react-router-serve/CHANGELOG.md)
- [Commits](https://github.com/remix-run/react-router/commits/@react-router/serve@7.15.0/packages/react-router-serve)

Updates `@sentry/node` from 10.51.0 to 10.52.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.51.0...10.52.0)

Updates `@sentry/react` from 10.51.0 to 10.52.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.51.0...10.52.0)

Updates `@tailwindcss/vite` from 4.2.4 to 4.3.0
- [Release notes](https://github.com/tailwindlabs/tailwindcss/releases)
- [Changelog](https://github.com/tailwindlabs/tailwindcss/blob/main/CHANGELOG.md)
- [Commits](https://github.com/tailwindlabs/tailwindcss/commits/v4.3.0/packages/@tailwindcss-vite)

Updates `@types/node` from 22.19.17 to 22.19.18
- [Release notes](https://github.com/DefinitelyTyped/DefinitelyTyped/releases)
- [Commits](https://github.com/DefinitelyTyped/DefinitelyTyped/commits/HEAD/types/node)

Updates `react-dom` from 19.2.5 to 19.2.6
- [Release notes](https://github.com/facebook/react/releases)
- [Changelog](https://github.com/facebook/react/blob/main/CHANGELOG.md)
- [Commits](https://github.com/facebook/react/commits/v19.2.6/packages/react-dom)

Updates `react-router` from 7.14.2 to 7.15.0
- [Release notes](https://github.com/remix-run/react-router/releases)
- [Changelog](https://github.com/remix-run/react-router/blob/main/packages/react-router/CHANGELOG.md)
- [Commits](https://github.com/remix-run/react-router/commits/react-router@7.15.0/packages/react-router)

Updates `tailwindcss` from 4.2.4 to 4.3.0
- [Release notes](https://github.com/tailwindlabs/tailwindcss/releases)
- [Changelog](https://github.com/tailwindlabs/tailwindcss/blob/main/CHANGELOG.md)
- [Commits](https://github.com/tailwindlabs/tailwindcss/commits/v4.3.0/packages/tailwindcss)

Updates `vite` from 7.3.2 to 7.3.3
- [Release notes](https://github.com/vitejs/vite/releases)
- [Changelog](https://github.com/vitejs/vite/blob/v7.3.3/packages/vite/CHANGELOG.md)
- [Commits](https://github.com/vitejs/vite/commits/v7.3.3/packages/vite)

---
updated-dependencies:
- dependency-name: expo
  dependency-version: 55.0.23
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: production
- dependency-name: react
  dependency-version: 19.2.0
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: production
- dependency-name: "@expo/fingerprint"
  dependency-version: 0.16.7
  dependency-type: direct:development
  update-type: version-update:semver-patch
  dependency-group: production
- dependency-name: i18next
  dependency-version: 26.0.10
  dependency-type: direct:development
  update-type: version-update:semver-patch
  dependency-group: production
- dependency-name: react-i18next
  dependency-version: 17.0.7
  dependency-type: direct:development
  update-type: version-update:semver-patch
  dependency-group: production
- dependency-name: turbo
  dependency-version: 2.9.12
  dependency-type: direct:development
  update-type: version-update:semver-patch
  dependency-group: production
- dependency-name: typescript-eslint
  dependency-version: 8.59.2
  dependency-type: direct:development
  update-type: version-update:semver-patch
  dependency-group: production
- dependency-name: isbot
  dependency-version: 5.1.40
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: production
- dependency-name: zod
  dependency-version: 4.4.3
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: production
- dependency-name: "@expo/metro-runtime"
  dependency-version: 55.0.11
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: production
- dependency-name: "@gorhom/bottom-sheet"
  dependency-version: 5.2.14
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: production
- dependency-name: "@maplibre/maplibre-react-native"
  dependency-version: 11.1.1
  dependency-type: direct:production
  update-type: version-update:semver-minor
  dependency-group: production
- dependency-name: "@sentry/react-native"
  dependency-version: 8.11.0
  dependency-type: direct:production
  update-type: version-update:semver-minor
  dependency-group: production
- dependency-name: expo-constants
  dependency-version: 55.0.16
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: production
- dependency-name: expo-dev-client
  dependency-version: 55.0.32
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: production
- dependency-name: expo-dev-menu
  dependency-version: 55.0.27
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: production
- dependency-name: expo-device
  dependency-version: 55.0.16
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: production
- dependency-name: expo-file-system
  dependency-version: 55.0.19
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: production
- dependency-name: expo-linking
  dependency-version: 55.0.15
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: production
- dependency-name: expo-location
  dependency-version: 55.1.9
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: production
- dependency-name: expo-router
  dependency-version: 55.0.14
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: production
- dependency-name: expo-splash-screen
  dependency-version: 55.0.20
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: production
- dependency-name: expo-status-bar
  dependency-version: 55.0.6
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: production
- dependency-name: expo-system-ui
  dependency-version: 55.0.17
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: production
- dependency-name: expo-web-browser
  dependency-version: 55.0.15
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: production
- dependency-name: react-native-gesture-handler
  dependency-version: 2.31.2
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: production
- dependency-name: react-native-reanimated
  dependency-version: 4.3.1
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: production
- dependency-name: jest-expo
  dependency-version: 55.0.17
  dependency-type: direct:development
  update-type: version-update:semver-patch
  dependency-group: production
- dependency-name: react-test-renderer
  dependency-version: 19.2.6
  dependency-type: direct:development
  update-type: version-update:semver-patch
  dependency-group: production
- dependency-name: "@codemirror/view"
  dependency-version: 6.42.1
  dependency-type: direct:production
  update-type: version-update:semver-minor
  dependency-group: production
- dependency-name: "@react-router/dev"
  dependency-version: 7.15.0
  dependency-type: direct:production
  update-type: version-update:semver-minor
  dependency-group: production
- dependency-name: "@react-router/node"
  dependency-version: 7.15.0
  dependency-type: direct:production
  update-type: version-update:semver-minor
  dependency-group: production
- dependency-name: "@react-router/serve"
  dependency-version: 7.15.0
  dependency-type: direct:production
  update-type: version-update:semver-minor
  dependency-group: production
- dependency-name: "@sentry/node"
  dependency-version: 10.52.0
  dependency-type: direct:production
  update-type: version-update:semver-minor
  dependency-group: production
- dependency-name: "@sentry/react"
  dependency-version: 10.52.0
  dependency-type: direct:production
  update-type: version-update:semver-minor
  dependency-group: production
- dependency-name: "@tailwindcss/vite"
  dependency-version: 4.3.0
  dependency-type: direct:production
  update-type: version-update:semver-minor
  dependency-group: production
- dependency-name: "@types/node"
  dependency-version: 22.19.18
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: production
- dependency-name: react-dom
  dependency-version: 19.2.6
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: production
- dependency-name: react-router
  dependency-version: 7.15.0
  dependency-type: direct:production
  update-type: version-update:semver-minor
  dependency-group: production
- dependency-name: tailwindcss
  dependency-version: 4.3.0
  dependency-type: direct:production
  update-type: version-update:semver-minor
  dependency-group: production
- dependency-name: vite
  dependency-version: 7.3.3
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: production
...

Signed-off-by: dependabot[bot] <support@github.com>
2026-05-10 08:42:40 +00:00
Ullrich Schäfer
e268aeec10
Archive unify-auth-completion + sync spec delta (task 5.1)
Applies the ADDED requirement from
openspec/changes/unify-auth-completion/specs/authentication-methods/
into openspec/specs/authentication-methods/spec.md:

- Single web auth completion chokepoint (completeAuth at
  apps/journal/app/lib/auth/completion.server.ts) with five scenarios
  covering passkey register/login finish, magic-link verify-code,
  magic-link click-through, and returnTo sanitization.

Path in the synced requirement is .server.ts (the post-rename name),
not the .ts the delta originally captured.

Change moved to openspec/changes/archive/2026-05-08-unify-auth-completion/.
15/15 tasks complete.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-08 03:02:51 +02:00
Ullrich Schäfer
b9aac2859a
Drop auth.server.ts re-exports + rename to .server.ts convention (task 5.2)
Two cleanups in one pass:

1. Update import paths app-wide from `~/lib/auth.server` to
   `~/lib/auth/session.server` for the four session helpers
   (sessionStorage, createSession, getSessionUser, destroySession).
   ~40 files: 33 simple path swaps where the file imported only session
   symbols, 5 splits where it also imported per-method auth functions
   (auth.verify.tsx, api.settings.email.ts, activities.\$id.tsx,
   routes.\$id.tsx, auth.accept-terms.tsx) — those keep one import
   from auth.server (for verifyMagicToken, canView, recordTermsAcceptance,
   etc.) and gain a second import from auth/session.server.
   Two more files used relative paths and were missed by the first
   grep pass (lib/oauth.server.ts and routes/oauth.authorize.tsx) —
   migrated too.
   The @deprecated re-exports block in auth.server.ts is gone.

2. Rename the new auth files to follow the project's `.server.ts`
   convention so Vite/React Router treat them as server-only (they
   read process.env.SESSION_SECRET, hit the DB, etc. — must NOT enter
   the client bundle):
   - auth/session.ts → auth/session.server.ts
   - auth/completion.ts → auth/completion.server.ts
   - auth/completion.test.ts → auth/completion.server.test.ts
   Done with `git mv` so blame is preserved.

Verified: typecheck + lint green; 126 unit tests pass.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-08 03:01:30 +02:00
Ullrich Schäfer
fc2f938cf5
Mark task 4.3 (manual smoke) complete
All four flows verified locally over plain HTTP: passkey register,
passkey login, logout, magic-link 6-digit verify-code, magic-link
click-through. Session cookie set + correct redirect every time.

13/14 tasks done. Only 5.1 (spec delta sync at /opsx:archive time)
and 5.2 (optional follow-up to drop the auth.server.ts re-exports)
remain — neither blocks merge.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-08 02:55:19 +02:00
Ullrich Schäfer
2fdbe5281d
Merge pull request #368 from trails-cool/ci-openspec-validate
ci: validate openspec specs and changes
2026-05-08 02:40:38 +02:00
Ullrich Schäfer
d64c47614d
Implement completeAuth chokepoint + caller migration
Implements all of unify-auth-completion (12/14 tasks done; manual
smoke + archive-time spec sync remain).

Design refinement during implementation: completeAuth supports two
response shapes via a `mode` parameter:
- mode: 'redirect' (loaders / direct browser navigation; auth.verify.tsx)
- mode: 'json' (action handlers called by imperative fetch from
  client forms; api.auth.login, api.auth.register)

Both modes share createSession + safeReturnTo + Set-Cookie. JSON mode
carries `{ ok: true, step: "done", redirectTo }` (the `step` field
preserves the existing client-form check).

Why two modes: passkey ceremonies are inherently imperative
(start → browser WebAuthn API → finish), so action handlers can't
move to <Form>/useFetcher. Picking option (B) from the design grill —
the chokepoint owns destination selection while clients navigate —
required this dual shape. The 3 hardcoded client-side targets
(returnTo ?? "/", "/", "/?add-passkey=1") collapse into 1 server-side
sanitization pass (safeReturnTo) inside completeAuth.

New module:
- apps/journal/app/lib/auth/session.ts: cookie session storage
  (sessionStorage, createSession, getSessionUser, destroySession)
  moved from auth.server.ts. Legacy import path kept via re-exports
  with @deprecated JSDoc.
- apps/journal/app/lib/auth/completion.ts: completeAuth + safeReturnTo.
- apps/journal/app/lib/auth/completion.test.ts: 10 contract tests
  covering both modes, returnTo sanitization (path-relative, protocol-
  relative, absolute-URL, malformed), Set-Cookie attachment, redirect
  status, JSON shape.

Caller migration:
- api.auth.register.ts passkey-finish → completeAuth(json)
- api.auth.login.ts finish-passkey → completeAuth(json)
- api.auth.login.ts verify-code → completeAuth(json)
- auth.verify.tsx magic-link consumer → completeAuth(redirect)

Client form updates:
- auth.login.tsx: pass returnTo in fetch body, read result.redirectTo
  on done.
- auth.register.tsx: pass returnTo: "/?add-passkey=1" for the magic-
  link verify-code path (preserves the post-register passkey prompt
  via the chokepoint's safeReturnTo, instead of hardcoding it
  client-side).

Verified:
- pnpm typecheck && pnpm lint: green across all 15 workspaces.
- pnpm --filter @trails-cool/journal test: 126 passed.
- pnpm test:e2e auth: 4/4 passed without modification — confirms the
  refactor is behaviour-preserving for the user-facing flows that
  matter most (passkey register + login).

Spec delta in openspec/changes/unify-auth-completion/specs/ applies at
/opsx:archive time.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-08 02:38:15 +02:00
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
7e22f1260b
Add unify-auth-completion architecture artifacts
Extract the post-verify orchestration shared across passkey
register-finish, passkey login-finish, magic-link verify-code, and
magic-link click-through into a single completeAuth function. Two
ADRs record the decision:

- ADR-0004: centralize web auth completion (record terms + create
  session + redirect) in apps/journal/app/lib/auth/completion.ts.
- ADR-0005: explicitly no AuthMethod polymorphism. Passkey + magic-
  link is the entire identity surface; OAuth2/PKCE is session
  transport, not a peer method. Recorded as a negative decision so
  future architecture passes don't re-suggest extracting the
  interface.

CONTEXT.md gains an Authentication section covering completeAuth, the
two methods, the OAuth2-as-transport distinction, and where the Terms
gate enforcement lives (root loader for web, requireApiUser for API
per the just-merged mobile-terms-gate).

OpenSpec change unify-auth-completion captures the proposal, design
(5 decisions including the negative-scope choices), spec delta on
authentication-methods, and 14 tasks. Implementation follows on this
branch.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-08 02:18:06 +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