# BRD: Скачивание трека из popup на карте

**Work Item:** ET-011
**Стадия:** Анализ
**Автор:** analyst
**Дата:** 2026-06-03

---

## 1. Контекст и проблема

Пользователь (мотоциклист-эндурист) изучает карту, видит публичные GPS-треки
(слой ET-008 «Публичные треки»), тапает понравившийся трек и видит во
всплывающем окне его метаданные: название, активность, длину, точки, дату,
источники. Однако сейчас **нет способа сохранить трек к себе** — приходится
переходить по внешней ссылке источника (если она есть) и искать там кнопку
скачивания, либо вообще нет возможности (например, в OSM-источнике).

**Боль:** мотоциклист, готовясь к выезду в офлайн-режиме, не может за один
тап забрать понравившийся трек в свой GPS-навигатор (Garmin, OsmAnd,
Locus, smartphone) или планировщик.

## 2. Цель

Дать пользователю **скачать понравившийся трек прямо из popup на карте**
одним нажатием — получить файл в стандартном формате (GPX), пригодный
для импорта в любой GPS-софт.

## 3. Целевая аудитория

- Мотоциклист-эндурист, изучающий маршруты перед поездкой
- Велосипедист / турист, скачивающий чужой трек для повторного прохождения
- Турфирма / организатор, готовящая раздаточный материал

## 4. Бизнес-ценность

| Метрика                                              | Эффект ожидаемый                                |
|------------------------------------------------------|-------------------------------------------------|
| Доля сессий с тапом по треку → действие              | Сейчас 0% (только просмотр), цель ≥ 20%         |
| Возвраты пользователя за треками                     | ↑ (приложение становится «полезным», а не «смотровым») |
| Конверсия публичных треков в реальные пройденные     | ↑ (треки начинают перетекать в GPS)             |

## 5. Область (Scope)

### В скоупе

1. **UI:** в существующем popup публичного трека (`_renderTrackPopupHtml`
   в `src/web/gps_tracks.js`) появляется кнопка/иконка «Скачать».
2. **Backend:** новый эндпоинт отдачи GPX-файла по идентификатору трека
   из таблицы `tracks` БД `gps_tracks.sqlite`.
3. **Формат:** GPX 1.1 — обязательно.
4. **Формат:** KML 2.2 — опционально, если бюджет позволяет (R-K-01,
   см. ниже).
5. **Имя файла:** человекочитаемое, из имени трека (см. NFR-04).

### Вне скоупа

- Авторизация / приватные треки — все треки в БД публичны.
- Массовое скачивание (пачкой) — только по одному.
- Кастомизация GPX (waypoints, расширения Garmin, цвета) — отдаём
  «голую» трассу.
- Скачивание загруженных пользователем GPX (ET-006) — там уже есть
  кнопка скачивания в panel `sheet-gpx`, и это другой источник данных.
- Скачивание построенного маршрута (Route / Scenic / Link) — это
  отдельный поток `downloadGPX()` в `sheet-route`, не трогаем.
- Регулирование rate limit и квоты — нет, трафик низкий.

## 6. Пользовательские истории

**US-1 (Mandatory):** Как мотоциклист, я хочу тапнуть трек на карте,
увидеть popup с его метаданными и нажать «Скачать», чтобы получить GPX-файл
в загрузках браузера — без перехода на сторонний сайт.

**US-2 (Mandatory):** Как пользователь мобильного браузера, я хочу получить
файл в формате, который мой телефон сразу предложит «Открыть в…» или
«Сохранить» (стандартный `Content-Disposition: attachment`).

**US-3 (Optional, R-K-01):** Как пользователь Google Earth / некоторых
старых навигаторов, я хочу выбрать формат KML вместо GPX.

**US-4 (Mandatory):** Как пользователь, я хочу, чтобы имя файла отражало
название трека (а не голый `id.gpx`), чтобы не путаться в загрузках.

## 7. Ограничения и допущения

- A1: треки в БД хранятся как WKB LineString в столбце `tracks.geom`,
  координаты EPSG:4326 (lon, lat).
- A2: высоты (`ele`) в БД **не хранятся** — отдаём GPX без `<ele>`.
  Время точек (`time`) — тоже не хранится, отдаём без `<time>`.
- A3: трек идентифицируется числовым `tracks.id`.
- A4: атрибуция источника (OSM / EnduroRussia / Wikiloc / ttrails) уже
  попадает в popup как ссылки и должна **попасть в GPX как metadata**
  (см. NFR-03).
- C1: размер ответа разумно ограничить (см. NFR-02) — кейс трека на
  десятки тысяч точек редок, но возможен.

## 8. Риски

| ID     | Риск                                                                 | Митигация                                                                                              |
|--------|----------------------------------------------------------------------|--------------------------------------------------------------------------------------------------------|
| R-1    | iOS Safari не отдаёт файл по `Content-Disposition`, открывает inline | Тестировать на iOS Safari, при необходимости использовать `<a download="...">` с `URL.createObjectURL` |
| R-2    | Имя файла с кириллицей ломается в некоторых браузерах                | RFC 5987 `filename*=UTF-8''...` (NFR-04)                                                               |
| R-3    | Треки с десятками тысяч точек дают тяжёлый XML (> 5 МБ)              | Логировать размер, NFR-02 устанавливает потолок                                                        |
| R-4    | Лицензия источника (Wikiloc ARR) запрещает реэкспорт                 | Решение: для OSM (ODbL) — можно; для остальных — обсудить с Owner. См. **Открытые вопросы Q-1**       |
| R-5    | Лицензия должна попасть в файл (OSM ODbL требует атрибуции)          | NFR-03: metadata в GPX содержит атрибуцию источника                                                    |

## 9. Открытые вопросы для Owner

| ID  | Вопрос                                                                                                  | Дефолт (если не ответят)                            |
|-----|---------------------------------------------------------------------------------------------------------|-----------------------------------------------------|
| Q-1 | Можно ли отдавать треки источников Wikiloc / EnduroRussia / ttrails? Их лицензии — All Rights Reserved. | **Только OSM-источник**. Для остальных — 403 + tooltip «Источник запрещает скачивание, перейдите на сайт источника». |
| Q-2 | KML делаем в этой итерации или откладываем?                                                             | **Откладываем.** Только GPX (R-K-01 переезжает в backlog).  |
| Q-3 | Кнопку рисовать иконкой (как в `sheet-route`) или текстовой кнопкой «Скачать GPX»?                      | **Иконка ⬇** + tooltip «Скачать GPX», по тапу на мобильных — лейбл.                      |

> Эти вопросы должны быть закрыты до перехода в Architecture. Если ответы
> не получены — реализация идёт по дефолтам.

## 10. Acceptance summary

См. `03-acceptance-criteria.md`. Кратко: пользователь нажимает «Скачать»
в popup трека → браузер скачивает валидный GPX 1.1 с именем
`<trail-name>.gpx`, который импортируется в OsmAnd, Garmin BaseCamp и
QGIS без ошибок.
