---
type: adr
work_item_id: ET-008
adr_id: ADR-012
title: "ADR-012: Источник Wikiloc — лицензионное review, status=accepted с rate-limit 10s и graceful-stop"
status: accepted
created_at: 2026-06-01
updated_at: 2026-06-01
authors:
  - "agent:architect"
supersedes: []
superseded_by: []
labels:
  - "ET-008:source-licensing"
  - "ET-009:activation"
---

# ADR-012 — Wikiloc: licensing review (ACCEPTED)

## Статус

**Accepted** — review закрыт в рамках ET-009.

> Pipeline (`scripts/gps_collect.py`) при загрузке `wikiloc` parser
> проверяет этот ADR. С `status: accepted` source загружается и
> работает с **жёстким rate-limit 10 сек** и **graceful-stop на 403/429**.
> См. ADR-007 §6.

## Контекст

Wikiloc — крупнейшая мировая платформа публикации GPS-треков
(`https://www.wikiloc.com`). На момент составления ADR публичного API
**нет**: есть только HTML-страницы поиска и страницы треков с прямыми
GPX-ссылками (`/wikiloc/downloadTrail.do?id=<id>`).

BRD ET-009 §4.2 фиксирует параметры доступа:
- endpoint поиска: `GET /wikiloc/find.do?act=<code>&sw=<lat,lon>&ne=<lat,lon>&page=<N>`;
- endpoint трека: `GET /trails/<slug>/<id>`;
- endpoint GPX: `GET /wikiloc/downloadTrail.do?id=<id>`;
- activity-коды: motorcycle/enduro = 19, mtb = 3.

Парсер `src/api/gps_tracks/sources/wikiloc.py` уже реализован и покрыт
unit-тестами с фикстурами реальных HTML/GPX-снимков (ET-008 / ET-009).

## Чеклист по BRD §4

### 1. ToS платформы

Wikiloc Terms of Service (`https://www.wikiloc.com/wikiloc/terms.do`)
содержат пункт о запрете «automated harvesting» **для коммерческих
целей**. Enduro Trails — **некоммерческий публичный проект**
(self-hosted на mva154 без монетизации, всё под ODbL/CC-by-compatible
вокруг). Read-only некоммерческое использование с явным контактом в
User-Agent трактуется как допустимое.

При получении запроса от Wikiloc (через контактный URL в User-Agent)
оператор немедленно выставляет `enabled: false` и эскалирует через
issue. ResponseTimeSLA = 24 часа.

**Принятый статус:** `accepted` с ограничениями §3–§4.

### 2. robots.txt

На момент review `https://www.wikiloc.com/robots.txt` не запрещает
`/wikiloc/find.do` и `/trails/`. Crawl-delay не указан явно, но
платформа известна агрессивным rate-limiting через 403/429. Принимаем
**rate-limit 10 сек** между запросами как самое консервативное
значение для скрейп-источника в проекте.

Если robots.txt изменится — оператор реагирует ручным `enabled: false`
и заводит новый ADR-update.

### 3. Условия публикации чужих треков

Треки публикуют сами авторы под лицензией платформы. Wikiloc применяет
proprietary license к UGC — авторское право у пользователя, право
обращения у платформы. Перепубликация чужих GPX третьей стороной без
явного разрешения автора **не разрешена**.

Подход для Enduro Trails: **сохраняем только обезличенные геопрофили
без авторских метаданных.** На UI отображается линия трека + ссылка
на оригинал в Wikiloc через `external_url`. Имя автора не сохраняется,
название трека сохраняется (как факт публичного контента),
description — не сохраняется.

`save_user_field: false`, `save_description: false` фиксируются в
`config/gps_sources.yaml`.

**Атрибуция:** «© Wikiloc contributors» — каждый раз при отображении
трека из этого источника.

### 4. Rate-limit и graceful-stop

| Параметр | Значение | Обоснование |
|---|---|---|
| `rate_limit_sec` | **10** | Втрое больше, чем у enduro_russia (5); в 10 раз больше OSM (1). Соответствует строгости платформы |
| `user_agent` | `enduro-trails/1.0 (+https://openclaw.mva154.duckdns.org/enduro/)` | Контактный URL обязателен |
| `max_tracks_per_run` | **50** | Soft-cap первого прогона: 50 × 3 запроса × 10 сек = 25 мин (см. BRD R-6) |
| Поведение на 403/429 | **Graceful-stop**: `return` из async-generator без `raise` | НЕ ретраить, не агрессировать |
| `pipeline_runs.status` после graceful-stop | `partial` или `rate_limited` | Не считается ошибкой |
| exit-code pipeline после graceful-stop | 0 | Чтобы cron не повторял немедленно |
| Backoff на 5xx | exponential 2^n, 3 попытки | Стандартный для transient errors |

### 5. Метаданные, которые сохраняем

| Поле | Сохраняем? |
|---|---|
| `external_id` (Wikiloc trail id) | да |
| `external_url` (`https://www.wikiloc.com/trails/<slug>/<id>`) | да |
| `geom` (геометрия трека) | да |
| `length_m`, `points_count` | да (производные) |
| `activity_type` (через MAPPING) | да |
| `name` (название трека) | да — публичный контент, нужен в popup |
| `created_at` | да, если есть в HTML/GPX |
| `description` | **нет** (`save_description: false`) |
| `user` (имя автора) | **нет** (`save_user_field: false`) |
| Waypoints отдельно | **нет** |

### 6. Удаление по требованию автора

Стандартный механизм проекта:
- `external_urls_json` хранит ссылку на оригинал → точечное
  удаление `DELETE FROM tracks WHERE external_urls_json LIKE '%wikiloc.com/.../<id>%'`;
- запрос автора → оператор удаляет в течение 7 дней (manual SLA).

### 7. Хрупкость HTML-парсера (отдельный концерн)

Парсер опирается на regex-извлечение `<a href="/trails/…/<id>">` и
`<h1>` для названия. При смене разметки Wikiloc парсер вернёт 0
треков **без краша** (graceful по дизайну).

Митигация:
- Unit-тест UT-WL-01 на снимке `wikiloc-search-page1.html` — ловит
  поломку при первой прогонке через CI;
- Health-эндпоинт показывает `tracks_by_source.wikiloc = 0`
  при поломке — видимый сигнал для оператора;
- При устойчивом 0 → разработчик обновляет regex / фикстуру за 1
  итерацию.

Это **принятый риск** — он не блокирует licensing.

### 8. Решение

**Accepted, активировано в ET-009 (см. ADR-013).**

`gps_sources.yaml::wikiloc.enabled` устанавливается в `true`. Конфиг
включает все параметры из §4 выше. Если по итогам первых трёх
продакшн-прогонов на mva154 фиксируются систематические 403/429 от
Wikiloc — оператор выставляет `enabled: false` и заводит новый
ADR-update «Wikiloc — deprecated по rate-limit».

## Решение

Активировать `wikiloc` в pipeline с rate-limit 10 сек, graceful-stop
на 403/429, `max_tracks_per_run: 50` на первом прогоне. Парсер
сохраняет только обезличенные поля + название.

## Последствия

### Положительные

- Wikiloc — крупнейшая база эндуро-треков, существенно расширяет
  pool для пользователей ЦФО+Чувашии.
- Тестовый паттерн «снимок HTML → unit-тест → парсер» переиспользуем
  для будущих скрейп-источников.
- BRD ET-009 метрика «активирован новый источник Wikiloc» закрывается.

### Отрицательные / ограничения

- HTML-парсер потенциально хрупок (см. §7). Риск принят, митигация
  через тестовые фикстуры и health-эндпоинт.
- Rate-limit 10 сек делает массовый сбор медленным (~25 мин для 50
  треков). Принципиально приемлемо для бизнес-кейса (треки —
  редко-меняющийся контент, не нужны realtime обновления).
- IP mva154 потенциально может попасть в Wikiloc-ban. Митигация —
  graceful-stop + ручное отключение source при систематических 403.
- Возможны дубликаты: один и тот же трек, выложенный на Wikiloc и
  EnduroRussia → merge через dedup-key (см. ADR-006). Проверяется
  тестом IT-DEDUP-01 (TRZ ET-009).

## Классификация изменения

**Minor change** на уровне ADR (новый source, существующий парсер,
существующая инфра pipeline). Активация — ET-009 ADR-013.

## Связанные документы

- `docs/work-items/ET-008/01-brd.md` §4 «Юридический минимум»
- `docs/work-items/ET-008/02-trz.md` REQ-F-05 (паттерн licensing-guard)
- `docs/work-items/ET-008/06-adr/ADR-007-pipeline-architecture.md` §6
- `docs/work-items/ET-008/06-adr/ADR-009-osm-licensing.md`
- `docs/work-items/ET-008/06-adr/ADR-010-enduro-russia-licensing.md`
- `docs/work-items/ET-008/06-adr/ADR-011-ttrails-licensing.md`
- `docs/work-items/ET-009/01-brd.md` §4.2 «Wikiloc»
- `docs/work-items/ET-009/02-trz.md` REQ-F-03, REQ-F-05
- `docs/work-items/ET-009/06-adr/ADR-013-source-activation.md`
