Commit graph

12 commits

Author SHA1 Message Date
Ullrich Schäfer
2cb32cd2d3
activity-sport-type: schema, contract, write/read paths, federation
Implements the activity-sport-type change (specs/activity-sport-type):

- db: nullable `sport_type` column on journal.activities + SportType /
  SPORT_TYPES (text().$type<> convention).
- api: optional sportType on the activity read + create schemas (mirrored
  SPORT_TYPES; @trails-cool/api stays zod-only).
- write: ActivityInput + createActivity persist it; mapSportType() normalizes
  provider strings (Komoot bulk import passes tour.sport; Garmin unset);
  threaded through the unified importActivity.
- read/display: sportType added to the detail/feed/profile loaders and the v1
  REST endpoints; shared SportBadge (glyph + i18n label) on detail, feed, and
  profile; sport-aware feed verb; create-form <select>.
- i18n: journal.activities.sport.* (labels + verbs) in en + de.
- federation: `sport` PropertyValue on the Note when set.

Tests: mapSportType unit table; federation asserts the sport attachment is
present when set and omitted when unset. typecheck + lint + unit all green.
E2E (create→badge) still to add.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-12 14:11:41 +02:00
Ullrich Schäfer
01d4832edb
security: authorize and validate presigned upload requests
POST /api/v1/uploads minted an upload key from caller input with no
ownership check, no content-type allowlist, and the raw filename
interpolated into the S3 key.

- Ownership: a caller may only mint upload URLs for a route/activity
  they own, enforced via the branded loadOwnedRoute/loadOwnedActivity
  (404 on miss, no existence leak). Closes writing into another
  user's resource key-space.
- Content type: the request schema now constrains contentType to an
  image/gpx allowlist, so active content (HTML/SVG/JS) that would
  execute if served inline is rejected at the request boundary.
- Filename: sanitizeUploadFilename() reduces the client filename to a
  safe basename (charset-restricted, no path components, no leading
  dots, length-bounded) before it becomes part of the key.

Tests: schema allow/deny + filename sanitization in @trails-cool/api;
handler tests covering owned-success, not-owner 404, disallowed
content-type, and the route-vs-activity ownership branch.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-06-10 22:23:14 +02:00
Ullrich Schäfer
61a2d0085b
one source of truth for Route/Activity shapes; enforce api contracts
Route and Activity existed three times: hand-written interfaces in
packages/types, Zod contracts in packages/api, and Drizzle columns in
packages/db — each with different fields and nullability. The
hand-written ones had drifted so far they had zero importers; the Zod
contracts were advisory because v1 handlers hand-rolled Response.json
shapes nothing validated.

- packages/types keeps only what both apps actually share (Waypoint,
  WaypointPoiTags) and documents where row types and wire contracts
  live; the dead Route/RouteMetadata/RouteVersion/Activity interfaces
  are gone
- packages/db exports canonical inferred row types (RouteRow,
  ActivityRow, RouteVersionRow, UserRow)
- packages/api contracts are reconciled with the real wire format
  (RouteVersionSchema gains the id and createdBy fields the endpoint
  has always returned) and gain Create*ResponseSchemas
- apiJson(schema, payload) in api-guard parses every v1 response
  through its contract: drift is now a thrown ZodError in tests/CI,
  unknown keys are stripped, and payloads are compile-checked as
  z.input of the schema

Enforcement immediately caught two real drifts: nullable DB
descriptions could ship null where the contract promises string (now
coalesced at the boundary), and GET /api/v1/activities/:id was missing
the routeName and photos fields its contract declares.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-06-10 07:39:50 +02: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
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
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
edd2cabf12
DRY up ZodError → FieldError mapping
Five journal API route handlers had the same inline lambda:

    parsed.error.issues.map((i) => ({
      field: i.path.join("."),
      message: i.message,
    }))

Pull it into `zodIssuesToFieldErrors(error)` next to FieldError in
`@trails-cool/api/errors.ts` and re-export it so all five handlers
share the same implementation. The path-flattening rule now lives in
one place, and new routes get it for free.

Public error-response shape is unchanged.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-04-19 11:45:09 +02:00
Ullrich Schäfer
079c3de90c
Modernise zod idioms to v4
Replace the deprecated v3 string-method forms with the top-level
validator helpers zod 4 prefers:

- z.string().url()      → z.url()      (3 sites)
- z.string().uuid()     → z.uuid()     (5 sites)
- z.string().datetime() → z.iso.datetime() (9 sites)

Also swap the ZodIssueCode.custom compat-shim reference in
demo-bot.server.ts's superRefine for the bare string literal "custom",
which is v4's idiomatic form. No runtime change.

All 147 tests still pass.

The `parsed.error.issues.map(i => ({field, message}))` pattern in the
five journal API route handlers stays as-is — the fields we read are
unchanged in v4, and zod's new error helpers (z.treeifyError,
z.prettifyError) produce different shapes that would change our
public API error contract.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-04-19 11:41:03 +02:00
Ullrich Schäfer
0eea6f2047
Upgrade zod from 3 to 4
Mechanical bump across the three packages that pull zod directly:
- packages/api (8 schema files, ~300 lines)
- apps/journal (persona schema in demo-bot.server.ts, 5 API route
  handlers that introspect parsed.error.issues)
- apps/mobile (declared dep; no active imports yet)

No code changes required. The legacy methods we use (.url(), .uuid(),
.datetime() on strings) still parse identically in v4 via the compat
shim, and z.ZodIssueCode.custom retains its runtime value. Error-issue
introspection (parsed.error.issues.map(i => ...)) keeps the same shape
at the fields we read (path, message, code).

All 147 tests across journal + api + packages pass against zod 4.3.6.

Follow-ups out of scope for this PR:
- Modernise to top-level validator helpers (z.url(), z.iso.datetime()).
  The legacy string methods are deprecated but not removed.
- Consider migrating error introspection to the richer v4 shape (.path
  is now branded, .input is new) if we ever want structured error
  surfaces.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-04-19 11:35:39 +02:00
Ullrich Schäfer
2ac4014521
Standardize monorepo pipeline: test, lint, typecheck across all workspaces
Previously only 2-3 workspaces participated in each turbo task. This
expands test, lint, and typecheck to cover all 11 workspaces with
parallel execution and caching.

Test pipeline:
- Move from single root vitest to per-workspace test scripts via turbo
- Shared vitest config (vitest.shared.ts) with passWithNoTests
- Per-workspace configs re-export the shared base
- Mobile uses Jest (jest-expo + React Native Testing Library)
- Add node-environment GPX tests verifying linkedom fallback
- Add i18n mobile init tests
- Exclude apps/mobile from root vitest (uses Jest separately)

Lint pipeline:
- Add eslint lint script to all 9 previously unlinted workspaces
- Standardize all scripts to "eslint ." with shared root config
- Add .expo/ to global ESLint ignores
- Fix lint errors: unused imports in api/types, export parseGpx

Typecheck pipeline:
- Add "typecheck": "tsc" to all 8 packages
- Add @types/node (catalog) to gpx and db packages
- Fix mobile app.config.ts: remove deprecated experiments.monorepo
  and newArchEnabled (both default in Expo SDK 55)
- Add allowImportingTsExtensions to mobile tsconfig

Shared package compatibility (mobile-app Phase 1.3):
- Add linkedom as explicit dependency to @trails-cool/gpx
- Add initI18nMobile() export to @trails-cool/i18n
- Confirm @trails-cool/types is pure interfaces (no DOM deps)

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-13 00:00:43 +02:00
Ullrich Schäfer
47923040fc
Add unit tests for @trails-cool/api schemas (32 tests)
Tests cover all Zod schemas: validation of valid payloads, rejection
of invalid payloads, default values, coercion, nullable fields,
pagination limits, and endpoint path constants.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-12 22:53:41 +02:00
Ullrich Schäfer
49b304749e
Add @trails-cool/api package with Zod schemas for REST API contract
Single source of truth for the Journal REST API:
- API_VERSION semver constant (1.0.0)
- Endpoint path constants (routes, activities, auth, uploads, push)
- Zod schemas for all request/response shapes:
  - Routes: list, detail, create, update, compute
  - Activities: list, detail, create
  - Auth: token exchange, refresh, device management
  - Discovery: instance info + API version
  - Uploads: presigned URL flow
  - Errors: structured error response with field-level details
- Cursor-based pagination schemas
- TypeScript types inferred from Zod (z.infer)

Used by Journal server (validation) and mobile client (type safety).

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-12 22:49:30 +02:00