trails/openspec/changes/mobile-app/specs/device-management/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

1.8 KiB

ADDED Requirements

Requirement: Connected devices list

The Journal web settings page SHALL display a list of connected devices (active OAuth2 sessions).

Scenario: View connected devices

  • WHEN the user opens the account settings page on the Journal web UI
  • THEN a "Connected Devices" section lists all active OAuth2 tokens with device name, last active timestamp, and approximate location (derived from IP)

Scenario: Device shows last active time

  • WHEN a device makes an API request using its OAuth2 token
  • THEN the Journal updates the token's last active timestamp and IP address

Requirement: Device metadata on token

Each OAuth2 token SHALL store device name, last active timestamp, and IP address.

Scenario: Device name stored on token exchange

  • WHEN the mobile app exchanges an authorization code for tokens via POST /oauth/token
  • THEN the device name (sent in the request body, e.g., "iPhone 15, iOS 18") is stored alongside the token record

Scenario: Last active updated on API use

  • WHEN a bearer token is used to authenticate an API request
  • THEN the token's lastActiveAt and lastActiveIp fields are updated

Requirement: Revoke individual device tokens

Users SHALL be able to revoke individual device sessions from the Journal web settings page.

Scenario: Revoke device from web

  • WHEN the user clicks "Revoke" on a connected device in the Journal settings
  • THEN the OAuth2 token for that device is deleted and all subsequent API requests from that device fail with 401

Scenario: Revoke device from API

  • WHEN a client sends DELETE /api/v1/auth/devices/:id with a valid bearer token
  • THEN the targeted device token is revoked (the requesting device can revoke other devices, not itself via this endpoint)