Files
enduro-trails/docs/work-items/ET-009/01-brd.md
claude-bot eaa6b4cd27
Some checks failed
CI / lint (push) Failing after 4s
CI / test (push) Failing after 5s
CI / build (push) Has been skipped
feat(ET-009): analyst artifacts — BRD, TRZ, AC, test plan
2026-06-01 17:51:47 +00:00

24 KiB
Raw Blame History

type, work_item_id, title, version, status, created_at, updated_at, authors, related
type work_item_id title version status created_at updated_at authors related
brd ET-009 BRD: Новые источники GPS-треков — EnduroRussia и Wikiloc 1 draft 2026-06-01 2026-06-01
agent:analyst
ET-008

BRD — ET-009: Новые источники GPS-треков — EnduroRussia и Wikiloc

1. Цель

Расширить пул реальных GPS-треков, видимых пользователю Enduro Trails, за счёт двух новых источниковendurorussia.ru и wikiloc.com. Pipeline сбора, БД, API и UI-слой уже построены в ET-008; ET-009 не строит инфраструктуру, а:

  1. Активирует EnduroRussia.ru как источник в продакшне (parser-код и ADR-010 уже готовы, но source находится в gps_sources.yaml как enabled: false; конфиг ссылается на enduro-russia.ru с дефисом — расхождение с реальным доменом endurorussia.ru без дефиса требует корректировки).
  2. Включает Wikiloc как новый источник: добавляет запись в gps_sources.yaml, привязывает к регионам, проверяет parser/lifecycle/ratelimit и активирует.
  3. Гарантирует, что после первого продакшн-прогона в БД data/gps_tracks.sqlite появляются треки с обоих новых источников и они корректно отдаются пользователю через существующие endpoints и UI-фильтры.

ET-009 — «заявить, подключить, доказать что работает», а не новая функциональность.

2. Контекст

  • ET-008 разработал и развернул в test:
    • src/api/gps_tracks/ (модели, БД, дедуп, MVT, endpoint, parsers).
    • Pipeline scripts/gps_collect.py с поддержкой нескольких источников.
    • Конфиги config/gps_sources.yaml и config/gps_regions.yaml.
    • UI: чекбокс «Публичные треки», sheet фильтров, popup трека, halo-слой на спутнике.
    • ADR-009/010/011/012 (licensing OSM / EnduroRussia / ttrails / Wikiloc).
  • На момент старта ET-009:
    • osmenabled: true, работает в проде.
    • ttrailsenabled: false, в задаче ET-009 не активируется.
    • enduro_russia — parser-код есть, ADR-010 accepted, но gps_sources.yaml содержит enabled: false и URL enduro-russia.ru (с дефисом). Реальный домен по бизнес-требованию — endurorussia.ru (без дефиса), это подтверждает и parser-код (src/api/gps_tracks/sources/enduro_russia.py default https://endurorussia.ru).
    • wikiloc — parser-код есть, ADR-012 accepted, но в gps_sources.yaml отсутствует.
  • API EnduroRussia: открытый JSON, без авторизации, 305+ треков по РФ:
    • GET https://endurorussia.ru/api/tracks?page=N&limit=50
    • GET https://endurorussia.ru/api/tracks/{id}/gpx
  • Wikiloc: публичного API нет, доступ только через HTML-парсинг страниц поиска и треков; rate-limit жёсткий — 10 сек между запросами; при 403/429 — graceful-stop.

3. Scope

In scope

# Функция
F-01 Исправление gps_sources.yaml: enduro_russia.base_urlhttps://endurorussia.ru (без дефиса).
F-02 gps_sources.yaml: enduro_russia.enabledtrue.
F-03 Верификация ADR-010 (accepted) на момент активации — pipeline-guard должен пропустить source.
F-04 Добавление в gps_sources.yaml записи wikiloc с enabled: true, rate_limit_sec: 10, license_adr: docs/work-items/ET-008/06-adr/ADR-012-wikiloc-licensing.md.
F-05 Обновление config/gps_regions.yaml: tsfo_plus_chuvashia.sources дополняется значением wikiloc (osm уже есть, enduro_russia уже есть).
F-06 Интеграционные тесты на parser enduro_russia.py с фикстурами реальных ответов API: 1 страница списка + 3 GPX-файла + edge cases.
F-07 Интеграционные тесты на parser wikiloc.py с фикстурами реальных HTML-страниц: страница поиска, страница трека, GPX.
F-08 Тесты dedup-merge на пару (osm-трек, enduro_russia-трек) с одной поездкой → одна запись с sources=['osm','enduro_russia'].
F-09 Тесты graceful-stop wikiloc на 403/429: парсер останавливается, не падает, pipeline_runs.status='partial' или 'rate_limited'.
F-10 Health-эндпоинт /api/gps-tracks/health после прогона показывает tracks_by_source с ненулевыми значениями для enduro_russia и wikiloc.
F-11 UI: фильтр «Источник» в #sheet-gps-filters динамически отображает 3 чекбокса — OSM, EnduroRussia, Wikiloc — по данным API.
F-12 Атрибуция: в правом нижнем углу карты MapLibre Attribution содержит «EnduroRussia.ru» и «© Wikiloc contributors» при наличии треков из этих источников.
F-13 Цветовая палитра по источнику в style.json/style-dark.json содержит цвета для enduro_russia и wikiloc (а не только OSM).
F-14 Первый продакшн-прогон pipeline на test-сервере для региона tsfo_plus_chuvashia: собирает ≥ 200 треков с EnduroRussia и пробует Wikiloc (любое ненулевое количество приемлемо ввиду rate-limit).

Out of scope

  • Активация ttrails (Тропинки.ру) — отдельный work item.
  • Изменение схемы БД — структура gps_tracks.sqlite остаётся как в ET-008.
  • Новые поля метаданных — что собираем по каждому треку, определено ET-008.
  • Wikiloc Premium / OAuth — пользуемся только публичными HTML.
  • Расширение алгоритма дедупликации — берём как есть из ET-008.
  • Запуск автоматического cron — расписание cron включается отдельным task'ом после успешного ручного прогона (см. F-14). ET-009 ограничивается ручным python scripts/gps_collect.py --region tsfo_plus_chuvashia.
  • Удаление stale-треков (GC) — отдельный концерн pipeline, не активируется в ET-009.
  • Расширение на новые регионы — Северный Кавказ остаётся enabled: false.

4. Источники — детальное описание

4.1 EnduroRussia.ru

Параметр Значение
Тип доступа Публичный JSON API без авторизации
Базовый URL https://endurorussia.ru
Endpoint list GET /api/tracks?page=<N>&limit=50{items: [{id, name, difficulty, …}], total}
Endpoint GPX GET /api/tracks/{id}/gpx → GPX 1.1 XML
Объём ≥ 305 публичных треков (на момент составления BRD)
География Россия, преимущественно ЦФО, эндуро-категория
Активность enduro, мото, hard, soft, тур → MAPPING → enduro/moto
ToS Публичные треки; нет явного запрета на программный доступ; см. ADR-010
robots.txt Не запрещает /api/ для программного доступа с явным UA (см. ADR-010 §2)
Attribution «EnduroRussia.ru» в строке атрибуции карты
Rate-limit 5 сек между запросами (rate_limit_sec: 5)
save_user_field false — автор не сохраняется (ADR-010 §3)

4.2 Wikiloc

Параметр Значение
Тип доступа Парсинг публичных HTML-страниц (API недоступно)
Базовый URL https://www.wikiloc.com
Endpoint поиска GET /wikiloc/find.do?act=<code>&sw=<lat,lon>&ne=<lat,lon>&page=<N> → HTML с <a href="/trails/…/<id>">
Endpoint трека GET /trails/<slug>/<id> → HTML c ссылкой на GPX
Endpoint GPX GET /wikiloc/downloadTrail.do?id=<id> → GPX XML
Активности (act код) motorcycle=19, enduro=19, mtb=3
ToS Треки публичные; ADR-012 фиксирует условия некоммерческого использования
robots.txt Не запрещает страницы треков с явным UA (см. ADR-012 §2)
Attribution «© Wikiloc contributors» в строке атрибуции карты
Rate-limit 10 сек между запросами (rate_limit_sec: 10) — жёстко
Graceful-stop При HTTP 403/429 — немедленный stop без ретраев, статус прогона rate_limited или partial
Хрупкость HTML-парсер. При смене структуры — парсер вернёт 0 треков без краша. См. риск R-1.
save_user_field false — автор не сохраняется (ADR-012 §5)

4.3 Контроль licensing

Pipeline-guard _check_license_adr() уже реализован (см. scripts/gps_collect.py строки 3773): при enabled: true source загружается только если license_adr.status == 'accepted'. Перед активацией ET-009 обязательно перечитать ADR-010 и ADR-012 и убедиться, что обе ADR имеют status: accepted в YAML front-matter. Если на момент работы ET-009 одна из ADR оказалась в другом статусе — работу остановить, эскалировать архитектору.

5. Метрики успеха

Метрика Критерий
Конфиг корректен gps_sources.yaml содержит запись enduro_russia с base_url: https://endurorussia.ru (без дефиса) и enabled: true.
Wikiloc заведён gps_sources.yaml содержит запись wikiloc с enabled: true, rate_limit_sec: 10, license_adr: …ADR-012….
Регион подписан gps_regions.yaml для tsfo_plus_chuvashia содержит wikiloc в sources. enduro_russia уже подписан.
Pipeline-guard работает При status: proposed в ADR-010 (искусственно) — pipeline пропускает source с pipeline_runs.status='skipped_license'.
Покрытие EnduroRussia После прогона: tracks_by_source.enduro_russia ≥ 200 (исходим из ≥ 305 публичных треков с учётом фильтра bbox региона).
Покрытие Wikiloc После прогона: tracks_by_source.wikiloc ≥ 1 (rate-limit 10 сек × ≥ 3 запроса на трек делает сбор медленным; любое ненулевое значение приемлемо для validation того, что парсер работает end-to-end).
Дедупликация работает Среди ≥ 200 треков EnduroRussia: записи с sources=['osm','enduro_russia'] или sources=['enduro_russia','wikiloc'] существуют (хотя бы 1 в выборке).
Graceful-stop Mock-эмуляция HTTP 403 / 429 от Wikiloc в integration-тесте → pipeline не падает, статус прогона rate_limited или partial.
Атрибуция В правом нижнем углу карты после включения слоя видны строки «EnduroRussia.ru» и «© Wikiloc contributors».
UI-фильтр источников В #sheet-gps-filters после первого прогона видны минимум 3 чекбокса: OSM / EnduroRussia / Wikiloc; снятие галки с источника убирает соответствующие линии.
Производительность не деградировала /api/gps-tracks?bbox=… p95 не вырос относительно ET-008 baseline (≤ 300 мс на z ≥ 10, ≤ 500 треков в bbox).
Чистый health /api/gps-tracks/health возвращает last_run_status='ok' или 'partial' (не 'error'), errors_count == 0 или ≤ 5%.

6. Риски

# Риск Вероятность Влияние Митигация
R-1 Wikiloc меняет HTML → парсер возвращает 0 треков Высокая Среднее Парсер уже спроектирован graceful: возвращает 0, не падает. Health-эндпоинт показывает 0 в tracks_by_source.wikiloc → видимый сигнал.
R-2 Wikiloc банит IP mva154 Средняя Высокое Rate-limit 10 сек + UA с контактом + graceful-stop на 403/429. После активации мониторим первые 3 прогона; при систематических 403 — enabled: false и эскалация.
R-3 EnduroRussia API меняет схему ответа Низкая Среднее Parser проверяет наличие ключевых полей (items, id); при KeyError — tracks_new=0, статус error. Контрактный тест на JSON.
R-4 Расхождение конфига enduro-russia.ru vs реального endurorussia.ru Случилось Высокое F-01: исправляем gps_sources.yaml сразу. Регрессионный тест: parser отвечает на https://endurorussia.ru (не на enduro-russia.ru).
R-5 EnduroRussia треки уже содержат creator=Wikiloc в GPX → массовые дубли при включении Wikiloc Высокая Среднее ADR-012 §4 явно фиксирует. Тест dedup-merge: одна и та же поездка из enduro_russia и wikiloc → одна запись, sources объединён.
R-6 Cron первого прогона превышает окно (≥ 6 часов из-за rate-limit Wikiloc 10 сек × 305 EnduroRussia × 3 запроса/трек) Средняя Низкое EnduroRussia: 305 треков × 5 сек ≈ 25 минут — окей. Wikiloc: per-source максимум max_tracks_per_run: 50 в первом прогоне (cap в конфиге).
R-7 UI-фильтр «Источник» не подхватывает новые ID Низкая Среднее UI динамически строит фильтр из API (/api/gps-tracks?stats=true или из выгрузки) — изменений в коде клиента не требуется. Проверка через UI-тест TC-UI-04 (расширен в ET-009).
R-8 Цветовая палитра в стилях карты не содержит enduro_russia/wikiloc → линии серым Высокая Низкое F-13: добавить цвета в style.json/style-dark.json (match-expression line-color по get source).
R-9 Дамп БД (если есть резервная копия с старым enduro-russia.ru URL в external_url) — orphan-записи Низкая Низкое До первого прогона новой версии: оператор может выполнить UPDATE tracks SET external_urls_json = REPLACE(external_urls_json, 'enduro-russia.ru', 'endurorussia.ru'). Опционально, в 14-deploy-log.md.
R-10 ADR-010 / ADR-012 регрессировали в proposed Низкая Высокое F-03: pre-check на момент активации. Если ADR не accepted — задача останавливается, эскалация архитектору.

7. Зависимости

Backend

  • src/api/gps_tracks/sources/enduro_russia.pyкод существует (ET-008). Изменения возможны только при выявлении бага во время тестов F-06/F-08.
  • src/api/gps_tracks/sources/wikiloc.pyкод существует (ET-008). Изменения возможны только при выявлении бага во время F-07/F-09.
  • scripts/gps_collect.py — без изменений, используется как есть.
  • src/api/gps_tracks/db.py, dedup.py, endpoint.py, mvt.py — без изменений.

Конфиги

  • config/gps_sources.yaml — изменение F-01..F-04.
  • config/gps_regions.yaml — изменение F-05.

Фронтенд

  • src/web/style.json и src/web/style-dark.json — F-13: расширить match-expression line-color для слоя gps-tracks-layer.
  • src/web/gps_tracks.js (или модуль ET-008) — без изменений кода при условии, что фильтр-список источников строится из ответа API динамически. Если в ET-008 список захардкожен — добавить enduro_russia и wikiloc в маппинг лейблов источников и палитру. Это будет уточнено в TRZ §3.

Тестовые фикстуры

  • tests/fixtures/gps-tracks/enduro-russia-api-tracks-page1.json — реальный snapshot ответа /api/tracks?page=0.
  • tests/fixtures/gps-tracks/enduro-russia-track-{1,2,3}.gpx — три GPX.
  • tests/fixtures/gps-tracks/wikiloc-search-page1.html — HTML страницы поиска.
  • tests/fixtures/gps-tracks/wikiloc-trail-page.html — HTML страницы трека.
  • tests/fixtures/gps-tracks/wikiloc-track.gpx — GPX из Wikiloc.
  • tests/fixtures/gps-tracks/wikiloc-rate-limited.html — заглушка для 429-сценария.

Инфра

  • mva154: исходящие HTTPS к endurorussia.ru и www.wikiloc.com (уже разрешены DevOps-политикой).
  • Размер data/gps_tracks.sqlite не превысит 100 MB после первого прогона (200 треков × ~50 KB средний размер геометрии).

Документация

  • BRD/TRZ/AC/Test-plan этого work item.
  • Опциональный ADR 06-adr/ADR-013-domain-fix-enduro-russia.md — если расхождение конфиг/реальность сочтено архитектурным решением, а не баг-фиксом. По умолчанию — это bugfix, ADR не нужен.
  • Дополнения к 14-deploy-log.md после первого прогона: команда запуска, tracks_by_source, длительность.

Связи с другими work items

  • ET-008 — родительская задача; ET-009 расширяет её. Никаких изменений в артефактах ET-008 не делаем.
  • ttrails — отдельный work item на активацию третьего источника (после ET-009).
  • PH-3 Smart Route — растущая база публичных треков может в будущем улучшить smart-route. Не в scope.