Files
enduro-trails/docs/work-items/ET-008/01-brd.md

99 lines
7.0 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
---
type: brd
work_item_id: ET-008
title: "BRD: GPS-треки с публичных платформ на карте"
version: 1
status: draft
created_at: 2026-06-01
updated_at: 2026-06-01
authors:
- "agent:analyst"
---
# BRD — ET-008: GPS-треки с публичных платформ на карте
## 1. Цель
Дать пользователю возможность увидеть на карте Enduro Trails GPS-треки
с публичных источников без скачивания файлов вручную: либо вставив
прямую ссылку на GPX, либо найдя чужие публичные треки в видимой
области карты (через OSM Public GPS Traces).
## 2. Контекст
- ET-006 реализовал клиентский GPX-стек: парсер, модель
`window.gpxTracks`, sheet `#sheet-gpx`, статистика, профиль высот,
переживание `map.setStyle()` через `rebuildGpxOverlays()`. Источник
данных — только локальный файл пользователя.
- Roadmap-фаза PH-3 «Smart Route» включает работу с GPX (импорт/экспорт).
- В стеке нет пользовательских аккаунтов и БД пользователей. Платформы с
обязательным OAuth (Strava, Komoot) поэтому вне scope текущей итерации.
- Браузер не может тянуть GPX напрямую с большинства публичных платформ
из-за CORS. OSM API не разрешает кросс-доменные запросы → прокси
через FastAPI обязателен.
- OSM Public GPS Traces — открытый бесплатный источник публичных
GPS-треков, формат GPX, есть bbox-поиск, нет авторизации для чтения.
## 3. Scope
### In scope
| # | Функция |
|------|---------|
| F-01 | Поле ввода URL прямой ссылки на GPX в `#sheet-gpx` |
| F-02 | Импорт GPX по URL через прокси-эндпоинт `/api/gpx/fetch` |
| F-03 | Кнопка «Найти публичные треки» в `#sheet-gpx` — поиск в bbox видимой области карты |
| F-04 | Прокси-эндпоинт `/api/gpx/osm/traces` для OSM Public GPS Traces |
| F-05 | Список найденных OSM-треков с метаданными (длина, точек, описание, автор) |
| F-06 | Импорт выбранного OSM-трека одним тапом |
| F-07 | Серверный LRU-кэш ответов внешних API (TTL 24 ч, in-memory) |
| F-08 | Источник трека (URL / OSM trace id + ссылка) виден в карточке трека |
| F-09 | Лимит размера загруженного по URL файла: 50 МБ (как ET-006) |
| F-10 | Внятные сообщения об ошибках (CORS-фейл, 404, лимит API, битый GPX) |
| F-11 | Импортированные треки попадают в общий список `window.gpxTracks` и неотличимы от локальных по поведению |
### Out of scope
- OAuth-интеграции (Strava, Komoot)
- Платный API Wikiloc
- Поиск треков глобально (без bbox)
- Сохранение треков в БД между сессиями
- Подписки на пользователей других платформ
- Загрузка собственных треков на публичные платформы
## 4. Метрики успеха
| Метрика | Критерий |
|---------|----------|
| URL-импорт | Прямая ссылка на GPX до 50 МБ загружается за ≤ 5 сек на средней сети |
| OSM-поиск bbox | Запрос видимой области возвращает результат за ≤ 3 сек (с кэшем — мгновенно) |
| Точность | OSM-трек после импорта визуально совпадает с тем же треком из osm.org |
| Кэш | Повторный запрос той же области/URL в течение 24 ч — без обращения к внешнему API |
| UX | Все ошибки (CORS, 404, лимит, формат) — внятные toast-уведомления, не падение |
| Совместимость с ET-006 | Локальные и удалённые треки в одном списке, поведение идентично |
| Сохранение при смене стиля | Импортированные треки переживают переключение тёмной темы и слоёв рельефа |
## 5. Риски
| Риск | Вероятность | Влияние | Митигация |
|------|-------------|---------|-----------|
| OSM API rate limit (1 запрос / IP / сек) | Высокая | Среднее | Серверный кэш по bbox + дебаунс на клиенте |
| URL-прокси превращается в open redirect / SSRF | Средняя | Высокое | Whitelist схем (http/https), блок приватных IP, лимит размера, таймаут |
| Большие OSM-страницы (1000+ треков) → длинный список | Средняя | Низкое | Пагинация: показывать первые N, кнопка «ещё» |
| GPX по URL не существует / 404 | Высокая | Низкое | Toast с понятной ошибкой |
| Content-Type не `application/gpx+xml` | Высокая | Низкое | Проверять по содержимому (DOMParser), не по заголовкам |
| Чужой публичный трек содержит вредоносный XML / XXE | Низкая | Высокое | DOMParser в браузере (XXE отключён), на бэкенде — `defusedxml` |
| Внешний API внезапно недоступен | Средняя | Низкое | Graceful degradation: показать сообщение, не блокировать другие функции |
## 6. Зависимости
- **ET-006** — модель `window.gpxTracks`, рендеринг, sheet `#sheet-gpx`,
парсер `parseGpx()`. Без ET-006 эта задача не имеет смысла.
- **Backend (FastAPI)** — новые эндпоинты `/api/gpx/fetch`,
`/api/gpx/osm/traces`, добавление `httpx` (уже есть) и `defusedxml`
(новая зависимость, опционально — для server-side валидации).
- Внешние сервисы:
- `https://api.openstreetmap.org/api/0.6/trackpoints` — публичный API
OSM, ограничения: 1 req/sec/IP, 5000 точек/страница, до 5 страниц.
- Произвольные HTTPS-хосты (для URL-импорта) — без SLA, fail-soft.