trails/openspec/changes/mobile-app/specs/photo-media/spec.md
Ullrich Schäfer cd939ccf07
Complete mobile app specs: fill all gaps
Design fixes:
- D6: Cleaned up, points to separate activity-recording change
- D13: Locked in TanStack Query + Zustand + React Context
- D14: Tile hosting (OpenFreeMap default, configurable tileUrl)
- D15: Photo/media (presigned upload URLs, thumbnails)
- D16: Journal REST API implementation (api.v1.*.ts route modules)

New specs (4):
- web-push-relay: Web Push → APNs/FCM relay (Mastodon pattern)
- api-contract-package: @trails-cool/api with Zod schemas
- device-management: Connected devices list + revoke
- photo-media: Presigned uploads, thumbnails, photo display

Task updates:
- Added Phase 2: Journal REST API (16 tasks)
- Added Phase 7: Notifications (8 tasks)
- Renumbered all phases (1-7)
- 112 total tasks

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

2.1 KiB

ADDED Requirements

Requirement: Presigned upload URL

The Journal API SHALL provide presigned upload URLs for direct-to-storage file uploads.

Scenario: Request upload URL

  • WHEN a client sends POST /api/v1/uploads with filename and content type
  • THEN the server returns a presigned upload URL for S3/Garage and a storage key to reference the uploaded file

Scenario: Upload photo directly to storage

  • WHEN the client receives a presigned URL
  • THEN the client uploads the file directly to S3/Garage using an HTTP PUT to the presigned URL, bypassing the Journal server

Requirement: Photo attachment on routes and activities

Routes and activities SHALL support an array of attached photos.

Scenario: Attach photo to route

  • WHEN a client creates or updates a route with storage keys in the photos array
  • THEN the route record stores the photo references and they are returned in subsequent GET requests with url and thumbnailUrl

Scenario: Attach photo to activity

  • WHEN a client creates an activity with storage keys in the photos array
  • THEN the activity record stores the photo references and they are returned in subsequent GET requests

Requirement: Server-side thumbnail generation

The Journal SHALL generate thumbnails when a photo upload is confirmed.

Scenario: Thumbnail created on upload confirmation

  • WHEN a route or activity is saved with a new photo storage key
  • THEN the server reads the original image from storage, generates a resized thumbnail, stores it alongside the original, and records both URLs

Requirement: Photo display

Clients SHALL display photos in route and activity detail views.

Scenario: View photos in route detail

  • WHEN a client fetches a route with attached photos
  • THEN the response includes an array of photo objects with url (full size) and thumbnailUrl (resized)

Scenario: Delete photo

  • WHEN a client updates a route or activity and removes a storage key from the photos array
  • THEN the photo and its thumbnail are deleted from storage on save