--- 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.