Files
enduro-trails/CHANGELOG.md
claude-bot 099669deeb
All checks were successful
CI / lint (push) Successful in 5s
CI / lint (pull_request) Successful in 5s
CI / test (push) Successful in 11s
CI / build (push) Successful in 3s
CI / test (pull_request) Successful in 10s
CI / build (pull_request) Successful in 2s
fix(terrain): расширить whitelist endpoint'а на tri (ET-013 review F-1)
Reviewer'ом найден pre-existing P1: backend `terrain_tile` whitelist
не пропускал слой `tri`, хотя фронтенд (`onTerrainCheckbox`) шлёт
запросы на `/terrain/tri/{z}/{x}/{y}.png` для слоя «Перепады высот».

На test/prod-среде эти запросы перехватывает nginx (подтверждено
эмпирически — 404 идёт с сигнатурой `nginx/1.18.0 (Ubuntu)`, а не
с FastAPI JSON-detail), но в dev-режиме (`make dev` → FastAPI на
:5556 напрямую) endpoint обязан поддерживать `tri` нативно.

Изменения:
- `src/api/main.py:1252`: whitelist `("hypso", "hillshade")` →
  `("hypso", "hillshade", "tri")`. Ответ-контракт и заголовки
  идентичны существующим слоям; REQ-F-18 «API contract без изменений»
  не нарушен (поведение для уже-известных layer'ов не меняется,
  добавляется только поддержка нового layer'а).
- `tests/integration/test_terrain_z9_tiles.py`: новый параметризованный
  тест `test_known_terrain_layer_accepted_by_whitelist[hypso|hillshade|tri]`,
  фиксирующий регрессию F-1 (не требует локальных PNG-данных:
  для несуществующего файла ожидает `detail: "Tile not found"`,
  а не `"Unknown layer"`).
- `tests/integration/test_terrain_z9_tiles.py`: параметризация
  `test_terrain_tile_available_z9_z10_z11` по `(layer × zoom)` —
  6 кейсов вместо 3 (review F-2).
- `tests/integration/test_terrain_z9_tiles.py`: убран неиспользуемый
  `from __future__ import annotations` (review F-4); type-аннотации
  упрощены (Python 3.10+ нативно).
- `tests/integration/test_terrain_z9_tiles.py`: `test_unknown_terrain_layer_returns_404`
  усилен ассертом `detail == "Unknown layer"` (парность с whitelist-тестом).

Тесты: 17/17 unit PASS, 6/6 non-data-зависимых integration PASS,
6 layer×zoom кейсов SKIPPED (нет PH-6 данных в sandbox — корректное
поведение `_maybe_skip`).

Refs: ET-013, review F-1/F-2/F-4 (`docs/work-items/ET-013/12-review.md`).

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-06-04 09:59:51 +00:00

110 lines
7.5 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# Changelog
All notable changes to this project will be documented in this file.
Format: [Keep a Changelog](https://keepachangelog.com/en/1.1.0/)
## [Unreleased]
### Added
- ET-013 (review F-1 fix): Слой `tri` (Terrain Ruggedness Index) добавлен
в whitelist FastAPI-endpoint'а `GET /terrain/{layer}/{z}/{x}/{y}.png`
(`src/api/main.py`). На test/prod-среде nginx перехватывает
`/enduro/terrain/*` и отдаёт PNG напрямую с диска (подтверждено эмпирически
по 404-сигнатуре `nginx/1.18.0`), но в dev-режиме (`make dev`
FastAPI на :5556 без nginx) endpoint должен поддерживать `tri` нативно.
Изменение аддитивное: ответ-контракт и заголовки идентичны существующим
слоям (`hypso`, `hillshade`); REQ-F-18 «API contract без изменений»
не нарушен. Регрессия: integration-тест `test_known_terrain_layer_accepted_by_whitelist`
параметризован по `(hypso, hillshade, tri)` и проверяет, что для
заведомо отсутствующего файла возвращается `detail: "Tile not found"`,
а не `"Unknown layer"`. Refs: ET-013, review F-1.
### Changed
- ET-013 (review F-2 fix): Integration-тест
`tests/integration/test_terrain_z9_tiles.py` параметризован по
`(layer ∈ {hillshade, tri}) × (zoom ∈ {9, 10, 11})` — 6 кейсов
вместо 3, покрывает оба слоя на расширенном диапазоне зумов
(ранее покрывался только `hillshade`). Refs: ET-013, review F-2.
- ET-012: Слой публичных GPS-треков теперь виден с зума z=5 (раньше — с z=8).
Калибровка существующей tier-структуры `build_gps_mvt`/`_simplify_coords`
(ADR-016): для z≤5 фильтр `min_length=10 км`, `limit=1500`; для z=6 —
`5 км`/`2000`; для z=7 — без изменений (`2 км`/`3000`). DP-tolerance
расширен парой стопов: z=6 → 0.018° (~2 км), z≤5 → 0.04° (~4 км).
На клиенте константа `GPS_TRACKS_MIN_ZOOM` понижена до 5;
`line-width`/halo-stops в MapLibre получили stop на z=5 (0.8/1.8 px),
hint обновлён с «Зум 8+» на «Зум 5+». Контракт API
`/api/gps-tracks/tiles/{z}/{x}/{y}.mvt` не изменился (REQ-F-15);
z≥8 не затронут (регрессия). Тесты: 18 unit zoom-tier+simplify,
9 integration endpoint z5-z7, 2 perf (PERF-Z5-01/02; avg ~64 мс,
p95 ~89 мс при 500 треках — ниже бюджета 200 мс/500 мс по M-6).
Refs: ET-012.
## [v0.0.3] — 2026-06-03 (tagged, NOT deployed)
> ⚠️ Тег создан и запушен, PR смерджен в `main`, но docker-образ на test
> **не задеплоен**: deploy-hook `/home/slin/bin/enduro-deploy-hook.sh`
> упал на `Permission denied` при записи в `/var/log/enduro-trails/`
> (каталог root-owned, у `slin` нет права записи и нет `NOPASSWD sudo`).
> Подробности и инструкция для ops: `docs/work-items/ET-011/14-deploy-log.md`.
### Added
- ET-011: Скачивание GPX из popup публичного трека. Новый эндпоинт
`GET /api/gps-tracks/{track_id}/download` собирает GPX 1.1 из геометрии
трека и отдаёт с `Content-Disposition: attachment` (UTF-8 имя файла по
RFC 5987). В popup на карте появилась кнопка «Скачать GPX» (32×32 CSS px,
mobile-friendly). Реализация: новый модуль `src/api/gps_tracks/export.py`
(`build_gpx`, `safe_filename`); расширение `config/gps_sources.yaml`
per-source флагом `download_allowed` (default-deny; MVP whitelist = `osm`,
см. ADR-015); helper `load_download_allowed_sources` в `config.py`.
Тесты: 13 unit GPX-builder + 10 unit filename + 11 integration download.
ADR-014, ADR-015. Refs: ET-011.
## [v0.0.2] — 2026-06-02
### Added
- ET-009: Активация GPS-источников EnduroRussia и Wikiloc — `config/gps_sources.yaml`
включает оба источника (`enabled: true`), для Wikiloc добавлен soft-cap
`max_tracks_per_run: 50` и activity-фильтр; `config/gps_regions.yaml` подписывает
`wikiloc` на регион `tsfo_plus_chuvashia`. Парсер `wikiloc.py` извлекает время из
GPX-metadata (для корректной дедупликации) и поддерживает `max_tracks_per_run`
cap. UI: цвет `wikiloc`, чекбокс источника, динамическая атрибуция
(`GPS_SOURCE_ATTRIBUTIONS`) подтягивается с `/api/gps-tracks/health`.
Тесты: 10 unit ER + 10 unit WL + 5 integration + 2 contract (nightly only).
PR #16, tag v0.0.2.
### Fixed
- ET-009: исправлен URL `enduro_russia` в `config/gps_sources.yaml`
(`https://enduro-russia.ru``https://endurorussia.ru`, без дефиса).
## [v0.0.1] — 2026-06-01
### Added
- ET-008: GPS-треки с публичных платформ на карте — новый модуль `src/web/gps_tracks.js`
с отображением публичных GPS-треков (OSM Traces, enduro_russia, ttrails) в виде
MVT-тайлов (z 811) и GeoJSON (z ≥ 12); фильтрация по активности и источнику,
попап с мета-данными трека, z-order ниже личных GPX-треков (AC-10).
Backend: FastAPI-пакет `src/api/gps_tracks/` (endpoint, MVT, LRU-кэш, дедупликация),
миграция `migrations/gps_tracks_001_init.sql`, pipeline-скрипт `scripts/gps_collect.py`,
Docker-сервис `gps-collector`. PR #12, tag v0.0.1.
## [Unreleased]
- Initial project structure
- CLAUDE.md project passport
- Agent system prompts (architect, developer, reviewer, tester, deployer)
- CI pipeline (Gitea Actions)
- Docker configuration
- ET-002: чекбокс «POI» в попапе рельефа — показ/скрытие маркеров POI
с сохранением состояния в localStorage (ключ `poi-visible`)
- ET-005: переключатель единиц измерения расстояний (км/мили) в попапе
рельефа — новый модуль `src/web/units.js` с централизованным
форматтером `Units.formatDistance()`; выбор сохраняется в localStorage
(ключ `distance_unit`), пересчёт всех видимых расстояний выполняется
единым оркестратором по событию `unitchange`
- ET-006: загрузка и визуализация GPX-треков — новый модуль
`src/web/gpx.js` с клиентским парсингом GPX 1.1 (`DOMParser`,
чанковая конвертация), отрисовкой треков и waypoints на карте,
панелью `#sheet-gpx` со списком треков, статистикой и canvas-профилем
высот; GPX-слои восстанавливаются после смены стиля карты через
`rebuildMapOverlays()`. Данные треков хранятся только в памяти сессии