Files
enduro-trails/docs/work-items/ET-009/10-tech-risks.md
claude-bot 4be7fbf3de
Some checks failed
CI / lint (push) Failing after 4s
CI / test (push) Failing after 6s
CI / build (push) Has been skipped
feat(ET-009): architect deliverables — ADR, infra requirements, data requirements, tech risks, wikiloc parser stub
2026-06-01 19:20:15 +00:00

22 KiB
Raw Blame History

type, work_item_id, title, version, status, created_at, authors
type work_item_id title version status created_at authors
tech-risks ET-009 Технические риски — ET-009: Активация EnduroRussia + Wikiloc 1 approved 2026-06-01
agent:architect

Технические риски — ET-009

Технические риски этапа активации двух новых GPS-источников. Бизнес-риски — в BRD §6 ET-009. Многие риски наследуются от ET-008 (R-1, R-5, R-9 из docs/work-items/ET-008/10-tech-risks.md); здесь — специфика ET-009. Шкала: вероятность (Н/С/В) × влияние (Н/С/В).

R-1 — Wikiloc меняет HTML → парсер возвращает 0 треков

  • Описание: Парсер Wikiloc опирается на regex-извлечение <a href="/trails/…/<id>"> и <h1> для названия. Wikiloc может в любой момент изменить разметку (новый шаблон, JS-rendering) → парсер вернёт 0 треков.
  • Вероятность / Влияние: В / С.
  • Митигация:
    • Парсер уже спроектирован graceful: return без raise при отсутствии match'ей regex (см. wikiloc.py::_extract_track_paths).
    • Health-эндпоинт показывает tracks_by_source.wikiloc = 0 после прогона → видимый сигнал оператору.
    • Unit-тест UT-WL-01 на снимке wikiloc-search-page1.html — при смене разметки CI зелёным быть не сможет, разработчик обновит фикстуру + парсер за 1 итерацию.
    • gps_sources.yaml::wikiloc.enabled: false — мгновенное отключение без deploy при критической поломке.
  • Наследник от: ET-008 R-1 (general).

R-2 — Wikiloc банит IP mva154

  • Описание: Скрейпер с фиксированного IP может попасть в чёрный список Wikiloc'а (особенно при ошибках rate-limit или накоплении 1000+ запросов в сутки). Pipeline начнёт получать 403/429 на все запросы → новых треков не будет.
  • Вероятность / Влияние: С / В.
  • Митигация:
    • rate_limit_sec: 10 — самый консервативный rate в проекте.
    • max_tracks_per_run: 50 — soft-cap на первом прогоне; ≤ 150 запросов на одну активацию.
    • User-Agent с контактным URL — платформа может связаться через email до бана.
    • Graceful-stop на 403/429 — не агрессивный retry, не вызывает дополнительных запросов.
    • Мониторинг первых 3 прогонов оператором; при систематических 403 → enabled: false + новый ADR-update «Wikiloc deprecated».
    • Запрет использования прокси через сторонний IP (нарушает дух прозрачности; см. ET-008 R-5).

R-3 — EnduroRussia API меняет схему ответа

  • Описание: enduro_russia.py::_parse_gpx ожидает поля id, name, difficulty, created_at в JSON-items. Платформа может добавить/переименовать поля.
  • Вероятность / Влияние: Н / С.
  • Митигация:
    • Парсер использует .get() с дефолтами — отсутствие необязательных полей не валит.
    • Отсутствие id → запись пропускается (continue), не валит весь прогон.
    • Контрактный smoke-тест tests/contract/test_endurorussia_api_smoke.py с маркером @pytest.mark.network — запускается nightly или вручную, сигнализирует о поломке внешнего API до пропущенного cron-прогона.
    • Pipeline-error не лоадит всю БД: errors_json фиксирует, оператор видит через /health.

R-4 — Расхождение конфига enduro-russia.ru (с дефисом) vs

реального endurorussia.ru (без дефиса)

  • Описание: До ET-009 gps_sources.yaml::enduro_russia.base_url содержит https://enduro-russia.ru (с дефисом), но реальный домен — https://endurorussia.ru (без дефиса; парсер по default использует именно его). При активации enabled: true без фикса URL парсер использовал бы default из кода, но external_url сохранённых треков опирался бы на base_url из конфига → fragmentation external_url'ов между «корректным» и «дефис-вариантом».
  • Вероятность / Влияние: Случилось (известный bug в конфиге) / В (при активации).
  • Митигация:
    • F-01 в BRD/TRZ — фикс URL в одно изменение.
    • Регрессионный тест UT-ER-05 — проверяет, что парсер сохраняет URL без дефиса при передаче base_url без дефиса.
    • One-shot UPDATE для существующих треков (опционально, см. 07-infra-requirements.md §4.1).

R-5 — EnduroRussia и Wikiloc — двойник одного и того же трека → массовые дубли

  • Описание: Авторы часто публикуют одну и ту же поездку и на Wikiloc, и на EnduroRussia (Wikiloc даже сохраняет creator=Wikiloc в GPX мета-теге, что подтверждается на практике). Без правильно работающего dedup'а в БД появятся два трека с одинаковой геометрией.
  • Вероятность / Влияние: В / С.
  • Митигация:
    • compute_dedup_key (ADR-006) основан на bbox+length+date, который при достаточно похожих координатах и одной дате попадает в один bucket → upsert ON CONFLICT мержит.
    • Интеграционный тест IT-DEDUP-01 — задаёт фикстуру wikiloc-track.gpx с координатами, совпадающими с одним из EnduroRussia-треков; проверяет итоговое объединение sources_json=['enduro_russia','wikiloc'].
    • Метаданные при merge — берутся от source с большим source_priority (enduro_russia=80 > wikiloc=70); external_urlsоба сохраняются.
    • Если на практике dedup пропускает (например, точное время / точный bbox slightly off): план отступления ADR-006 §8 (сузить length-bucket, добавить activity).

R-6 — Cron первого прогона превышает окно из-за rate-limit Wikiloc

  • Описание: При больших cap'ах max_tracks_per_run и rate-limit 10 сек × 3 запроса/трек первый прогон Wikiloc может занять часы.
  • Вероятность / Влияние: С / Н.
  • Митигация:
    • max_tracks_per_run: 50 — soft-cap → ≤ 25 минут на прогон Wikiloc.
    • EnduroRussia при rate-limit 5 сек × 305 треков ≈ 25 минут — окей.
    • Cron автоматизация отложена до отдельного DevOps-task'а после двух успешных ручных прогонов; оператор контролирует длительность.
    • Опционально: timeout 21600 docker compose ... в cron (ET-008 R-11 уже фиксирует).

R-7 — UI-фильтр «Источник» не подхватывает новые ID

  • Описание: Если в ET-008 UI-фильтр (#gps-source-grid) построен с захардкоженным списком [osm], новые источники не появятся как чекбоксы.
  • Вероятность / Влияние: Н / С.
  • Митигация:
    • Дизайн ET-008: UI строит фильтр динамически из ответа /api/gps-tracks/health.tracks_by_source (источники с count > 0). После первого прогона ET-009 — фильтр сам покажет 3 чекбокса.
    • UI-тест TC-UI-04 (в 04b-ui-test-cases.md ET-008) расширен для ET-009: проверяет наличие 3 чекбоксов после двух прогонов.
    • Маппинг SOURCE_LABELSgps_tracks.js) расширяется явно в ET-009 — даёт корректные читаемые названия.

R-8 — Цветовая палитра в style.json / style-dark.json не содержит новых ID → линии серые

  • Описание: В ET-008 match-expression line-color может содержать только osm; новые источники получат fallback-серый.
  • Вероятность / Влияние: В / Н.
  • Митигация:
    • REQ-F-13 явно требует обновить match-expression с тремя источниками + fallback.
    • Code-review-чеклист: проверить наличие enduro_russia, wikiloc в paint.line-color обоих стилей.
    • При пропуске: визуальный регресс легко заметен в smoke-тесте (TC-UI-05).

R-9 — Дамп БД (резервная копия с старым URL) — orphan записи

  • Описание: Если на test-сервере есть резервная копия БД, в которой external_urls_json содержит enduro-russia.ru (с дефисом), то после фикса URL новые treki будут иметь endurorussia.ru (без дефиса), а старые — enduro-russia.ru. Это не криминал, но фрагментация атрибуции.
  • Вероятность / Влияние: Н / Н.
  • Митигация:
    • На практике enduro_russia до ET-009 был enabled: false → таких записей нет. Риск гипотетический.
    • Опциональный one-shot UPDATE tracks SET external_urls_json = REPLACE(...) — фиксируется в 14-deploy-log.md если применяется.

R-10 — ADR-010 / ADR-012 регрессировали в proposed

  • Описание: Между моментом написания BRD/TRZ ET-009 и моментом активации (merge → deploy) кто-то откатил статус ADR в proposed. Pipeline-guard заблокирует source с skipped_license.
  • Вероятность / Влияние: Н / В.
  • Митигация:
    • F-03 / REQ-F-05 — pre-check перед активацией:
      grep -E "^status:" docs/work-items/ET-008/06-adr/ADR-010-enduro-russia-licensing.md
      grep -E "^status:" docs/work-items/ET-008/06-adr/ADR-012-wikiloc-licensing.md
      
      Оба должны вернуть accepted. Иначе — STOP и эскалация архитектору.
    • Интеграционный тест IT-LIC-01 проверяет работу pipeline-guard'а: подменяет accepted → proposed в копии ADR-010 и убеждается, что pipeline скипает source с status='skipped_license'.
  • Наследник от: ET-008 R-9.

R-11 — Пользовательский opt-in для новых источников

  • Описание: Пользователи с уже сохранённым localStorage['gps-tracks-sources'] = ["osm"] после ET-009 не увидят треки EnduroRussia/Wikiloc на своих устройствах — клиент сохраняет старое значение, новые источники по умолчанию не enabled в UI.
  • Вероятность / Влияние: В / Н.
  • Митигация:
    • Это сознательное решение UX (см. 08-data-requirements.md §4.2): добавление источников без согласия пользователя — нарушение принципа без сюрпризов.
    • Чекбоксы новых источников появятся в #sheet-gps-filters automatically (через health-endpoint), пользователь может включить их вручную.
    • В release-notes (если они есть в проекте) — фиксируем «появились два новых источника, активация в фильтре».

R-12 — Wikiloc-парсер сохраняет описание / автора несмотря на ADR-012

  • Описание: ADR-012 §3 явно запрещает сохранять description и user для Wikiloc. Если реализация парсера не уважает этот запрет (например, TrackInsert.description заполняется), нарушение licensing-условий.
  • Вероятность / Влияние: Н / В.
  • Митигация:
    • Текущая реализация: wikiloc.py::_parse_gpx возвращает TrackInsert(description=None, user=None) (зашито в коде).
    • Unit-тест UT-WL-05 проверяет, что description=None и user=None в возвращаемом TrackInsert.
    • Code-review checklist в 12-review.md: при любом изменении парсера Wikiloc убедиться, что эти поля остаются null.

R-13 — Тестовые фикстуры устаревают

  • Описание: Снимки HTML/JSON, использованные в unit-тестах, отражают состояние API/HTML на момент снятия. Через 6-12 месяцев платформа может изменить разметку, и фикстуры станут неактуальны. Тесты пройдут (фикстура соответствует тесту), но парсер не будет работать в production.
  • Вероятность / Влияние: С / С.
  • Митигация:
    • Контрактный smoke-тест test_endurorussia_api_smoke.py (@pytest.mark.network, nightly) — проверяет реальную схему API, ловит расхождение.
    • Аналогичный smoke для Wikiloc не делаем (риск бана IP при регулярных запросах; ETC-009 §«REQ-F-16»).
    • Health-эндпоинт показывает tracks_by_source.wikiloc после каждого продакшн-прогона; устойчивое 0 — сигнал.
    • При устаревании фикстуры — снимаем заново (1 час работы), парсер обновляем (1-3 часа).

R-14 — Производительность endpoint деградирует при росте кол-ва треков

  • Описание: REQ-NF-02 ET-008 фиксирует p95 ≤ 300 мс на bbox с ≤ 500 треков. После ET-009 в БД появятся ещё ≤ 250 треков — пренебрежимо относительно 5000 OSM.
  • Вероятность / Влияние: Н / Н.
  • Митигация:
    • R-tree индекс по geom (ADR-005) → O(log n) bbox-prefetch.
    • AC-20 — нагрузочный тест 100 запросов после первого прогона.
    • При деградации — анализ EXPLAIN QUERY PLAN; добавление индекса idx_tracks_source опционально (out of scope ET-009).

R-15 — Конфликт MAPPING-таблиц для одной активности

  • Описание: EnduroRussia маппит motorcycle → moto, Wikiloc тоже motorcycle → moto — корректно. Но: EnduroRussia при отсутствии match'а в MAPPING возвращает enduro (fallback), Wikiloc — moto. Для одного и того же трека (попавшего в оба источника) при merge получим activity_type от source с большим source_priority = enduro_russiaenduro. Это OK: priority делает выбор детерминированным.
  • Вероятность / Влияние: Н / Н.
  • Митигация:
    • Принято as is. Уточнение в 08-data-requirements.md §3.4.
    • Unit-тесты UT-ER-04 и UT-WL-06 проверяют отдельные MAPPING'и.

R-16 — Регрессия e2e-тестов ET-008

  • Описание: Расширение style.json / gps_tracks.js атрибуцией и цветами может случайно сломать существующие selectors / визуальные тесты ET-008.
  • Вероятность / Влияние: Н / С.
  • Митигация:
    • AC-19 — все e2e ET-008 (E-01..E-41) должны пройти после мерджа ET-009.
    • Регрессионный прогон pytest tests/e2e/ -v — обязательный шаг CI.

R-17 — Pipeline скипает source из-за неправильного license_adr path

  • Описание: Pipeline-guard _check_license_adr читает YAML front-matter файла по пути из license_adr. Если путь опечатан (например, ADR-12-... вместо ADR-012-...), guard вернёт false → status='skipped_license'.
  • Вероятность / Влияние: Н / В.
  • Митигация:
    • Pre-deploy check: убедиться, что license_adr указывает на реально существующий файл с status: accepted.
    • При первом запуске pipeline в test-среде оператор смотрит pipeline_runs[-1].status; если skipped_license — диагностирует и исправляет до merge в main.
    • Pydantic-валидация gps_sources.yaml в pipeline ET-008 уже требует обязательное license_adr поле; отсутствие — exception при старте.
  • Наследник от: ET-008 R-9.

Сводная таблица

ID Риск Вер. Влияние Класс Статус
R-1 Wikiloc меняет HTML В С Высокий принят + graceful + быстрое отключение
R-2 Wikiloc банит IP mva154 С В Высокий rate-limit 10s + cap 50 + UA + monitor
R-3 EnduroRussia API меняет схему Н С Низкий smoke-тест + graceful + health
R-4 Расхождение URL enduro-russia vs endurorussia Случилось В Высокий F-01 фикс + UT-ER-05
R-5 Дубли EnduroRussia/Wikiloc В С Средний dedup-key + IT-DEDUP-01
R-6 Cron первого прогона долго С Н Низкий max_tracks_per_run=50 + ручной прогон
R-7 UI-фильтр не подхватит Н С Низкий динамика из health + SOURCE_LABELS
R-8 Стили без новых цветов В Н Низкий REQ-F-13 + review + smoke
R-9 Orphan записи с старым URL Н Н Низкий гипотетический (БД чистая); опц UPDATE
R-10 ADR-010/012 регрессировали в proposed Н В Высокий pre-check + IT-LIC-01
R-11 Пользовательский opt-in для новых источников В Н Низкий сознательный UX-compromise
R-12 Wikiloc сохраняет description/user Н В Высокий parser-design + UT-WL-05 + review
R-13 Фикстуры устаревают С С Средний smoke-test + health + ручной refresh
R-14 Деградация endpoint Н Н Низкий R-tree + AC-20
R-15 Конфликт MAPPING Н Н Низкий source_priority детерминирует
R-16 Регрессия ET-008 e2e Н С Низкий AC-19 + pytest e2e
R-17 Неправильный license_adr path Н В Высокий pre-deploy check + Pydantic

Высокие классы:

  • R-1, R-2 — операционные, ожидаемые для скрейп-источника Wikiloc; митигация — multi-layer (graceful + monitor + конфиг-kill-switch).
  • R-4 — known bug в конфиге, прямо адресован REQ-F-01.
  • R-10, R-17 — критичны для legal compliance; митигация многослойная (pre-check + integration-тест + Pydantic).
  • R-12 — критичен для соблюдения ADR-012; митигация через design + UT-WL-05 + review.

Блокирующих рисков нет. Высокие классы требуют внимания на этапе разработки и code review.

Эскалация

  • arch:major-changeне выставляется (см. ADR-013 §«Классификация»). Изменение не вводит новых архитектурных компонентов.
  • back-to:analysis — не требуется. ТЗ полное, BRD ясный, open-questions в TRZ §6 закрыты дефолтными решениями.
  • Эскалация архитектору требуется только при срабатывании R-10 (ADR в proposed на момент активации). Тогда задача останавливается до повторного апрува ADR.