trails/apps/journal/app/lib/connected-services
Ullrich Schäfer 7a1dca378f
journal: branded ownership loading for routes and activities
Ownership was checked ad hoc: some handlers loaded-and-compared
ownerId, some lib mutators enforced it in WHERE clauses and silently
no-op'd for non-owners, and nothing tied the two together. Two real
authorization bugs hid in the gaps: linkActivityToRoute ignored its
ownerId parameter entirely (any logged-in user could relink any
activity), and createRouteFromActivity loaded any activity without an
ownership check (a non-owner could copy a private activity's GPX into
their own route). PUT /api/v1/routes/:id also returned ok:true for
non-owners without updating anything.

ownership.server.ts is now the single enforcement point:

- loadOwnedRoute / loadOwnedActivity (non-throwing, for callers with
  their own error vocabulary) and requireOwnedRoute /
  requireOwnedActivity (throwing data() 404/403 for web handlers; 404
  by default so guessed ids don't leak existence)
- the returned entities carry an Owned<> brand; mutators (updateRoute,
  deleteRoute, deleteActivity, updateActivityVisibility,
  linkActivityToRoute, createRouteFromActivity) now require an
  OwnedRef, so skipping the check is a compile error
- vouchOwnership is the explicit, greppable escape hatch for the one
  non-session authorization path (the Planner JWT callback)
- WHERE ownerId clauses stay in the mutators as defense in depth

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-06-10 02:35:00 +02:00
..
credential-adapters Add Komoot import with public (bio verification) and authenticated modes 2026-05-23 10:18:46 +02:00
providers feat(journal): Garmin activity import — provider, webhook pipeline, backfill (§1–5) 2026-06-07 17:47:22 +02:00
fit.ts chore(ts): eliminate the remaining 4 \as any\ casts in production code 2026-05-26 07:11:02 +02:00
index.ts Wahoo capability adapters + caller migration (groups 3-5) 2026-05-08 01:25:33 +02:00
manager.test.ts Schema rename + ConnectedServiceManager foundation (groups 1-2) 2026-05-08 01:14:38 +02:00
manager.ts feat(journal): Garmin activity import — provider, webhook pipeline, backfill (§1–5) 2026-06-07 17:47:22 +02:00
oauth-state.server.ts feat(journal): Garmin activity import — provider, webhook pipeline, backfill (§1–5) 2026-06-07 17:47:22 +02:00
oauth-state.test.ts feat(journal): Garmin activity import — provider, webhook pipeline, backfill (§1–5) 2026-06-07 17:47:22 +02:00
push-action.server.ts journal: branded ownership loading for routes and activities 2026-06-10 02:35:00 +02:00
registry.ts feat(journal): Garmin activity import — provider, webhook pipeline, backfill (§1–5) 2026-06-07 17:47:22 +02:00
types.ts Add Komoot import with public (bio verification) and authenticated modes 2026-05-23 10:18:46 +02:00