Files
enduro-trails/docs/work-items/ET-013/07-infra-requirements.md
claude-bot 6b88bcee28
Some checks failed
CI / lint (push) Successful in 5s
CI / test (push) Failing after 5s
CI / build (push) Has been skipped
architect(ET): auto-commit from architect run_id=79
2026-06-04 09:40:50 +00:00

23 KiB
Raw Blame History

type, work_item_id, title, version, status, created_at, authors
type work_item_id title version status created_at authors
infra-requirements ET-013 Инфраструктурные требования — ET-013: Zoom-aware paint для terrain-слоёв на z9-z11 1 approved 2026-06-04
agent:architect

Инфраструктурные требования — ET-013

1. Резюме

ET-013 — frontend paint-калибровка. Меняются два файла исходного кода (src/web/app.js, src/web/index.html) + добавляются тесты. Инфраструктура не меняется:

  • 0 новых docker-сервисов;
  • 0 изменений в Dockerfile;
  • 0 изменений в docker-compose.yml;
  • 0 новых файлов БД, миграций, индексов;
  • 0 новых cron-записей;
  • 0 новых env / секретов / API-ключей;
  • 0 новых исходящих HTTPS-соединений;
  • 0 новых портов;
  • 0 изменений в nginx (тайлы рельефа отдаются с тех же путей /enduro/terrain/{layer}/{z}/{x}/{y}.png);
  • 0 изменений в backend (src/api/main.py:terrain_tile без правок).

Эскалация: minor change (см. ADR-017 §«Классификация изменения»).

2. Контейнеры и сервисы

Аспект Требование
Новый сервис Нет
Изменения Dockerfile Нет
Изменения docker-compose.yml Нет
Перезапуск app после деплоя Нужен — docker compose up -d --no-deps app (≈ 5 сек простоя). Подхватывает обновлённые src/web/app.js и src/web/index.html (отдаются как статика из контейнера)
Перезапуск gps-collector Не нужен (не затронут)
Очистка серверных кэшей Не требуется (backend не меняется; /terrain/* endpoint и Cache-Control: max-age=31536000, immutable без изменений)
Очистка клиентских кэшей Не требуется как часть деплоя, но пользователю при первой загрузке после деплоя браузер дёрнет свежий app.js (cache-busting через nginx if-modified-since)

2.1 Зависимости между сервисами

Без изменений vs PH-6 / ET-007:

  • app → файлы /app/data/terrain/{hillshade,tri,hypso}/{z}/{x}/{y}.png (read-only при отдаче клиенту).
  • nginx (host)app:8000 через docker-network bridge.

3. Сеть

Аспект Требование
Новые входящие порты Нет
Изменения nginx Нет (location /enduro/terrain/ без правок; новые комбинации (z, x, y) для z=9 — просто другие значения существующего path-параметра)
nginx gzip для PNG Не применяется (PNG уже сжат). Без изменений vs PH-6
Кэш-заголовки на /terrain/* Без изменений: Cache-Control: public, max-age=31536000, immutable (см. src/api/main.py:1252). Браузерный кэш + nginx-кэш агрессивно поглощают повторы
Новые исходящие соединения Нет — никаких внешних API не дёргается, всё локально
CORS Без изменений; /terrain/* отдаётся в том же origin, что и index.html
HTTPS / TLS Без изменений — nginx с Let's Encrypt сертификатом DuckDNS

3.1 Ingress / Egress — оценка дельты

Изменения сетевого паттерна (BRD M-10, NFR-03):

  • Hillshade: UI-минзум понижается с 10 до 9 → пользователь видит слой на одной zoom-ступени раньше. Один тайл z9 == 4 тайла z10 по покрытию территории, поэтому при «активной zoom-сессии» z=8→z=12 с включённым hillshade добавляется ≤ 1 zoom-ступень тайлов.
  • TRI: minzoom источника не меняется (5), opacity меняется только для уже-запрашиваемых тайлов. Дельта запросов 0.
  • Итого: при типичной сессии «10 зумов между z8 и z12 с обоими слоями» объём PNG растёт ≤ 35% (BRD M-10, AC-21).

Размер одного PNG-тайла рельефа (terrain) ≈ 8-30 KB (без gzip — PNG уже сжат). На сессию: было ~60 тайлов × 20 KB = 1.2 MB, станет ~80 тайлов × 20 KB = 1.6 MB. Дельта на пользователя: ~0.4 MB.

При 10 одновременных пользователях на mva154 — пик ≈ 4 MB/сек дополнительного uplink, мизер по сравнению с uplink сервера (≥ 100 Mbps по DuckDNS).

Кэш браузера (immutable, max-age=31536000) поглощает 2-й и последующие визиты целиком.

3.2 Rate-limit на /terrain/*

Не вводим в этой итерации. PNG-тайлы — статика с агрессивным кэшем; DDoS-стоимость низкая (sendfile из ФС без вычислений). Если в проде обнаружится скан z=9-z=14 grid'а — добавляется отдельным DevOps-task'ом, не в ET-013.

4. Серверные ресурсы

Аспект Требование
CPU app Без изменений по архитектуре. Раздача PNG — FileResponse (sendfile, zero-copy через ядро), CPU-cost пренебрежимый. Рост запросов до +35% даёт +0.5% CPU на сервере при пике сессий
RAM app Без изменений. PNG не буферизуются в памяти; sendfile из файловой системы
Disk app Без изменений. Тайлы рельефа лежат в /home/slin/enduro-trails/data/terrain/{hillshade,tri,hypso}/{z}/{x}/{y}.png (объём по PH-6 baseline). Никаких новых файлов / volume
CPU gps-collector Без изменений (не затронут)
RAM gps-collector Без изменений
Disk gps-collector Без изменений

4.1 Размер тайлов рельефа на диске

Не меняется. ET-013 не перегенерирует тайлы; используются существующие нарезки z8-z14 из PH-6. Если pre-deploy smoke (см. §6.2 шаг 1) обнаружит отсутствие тайлов z9-z11 — задача останавливается, открывается PH-6 follow-up на догенерацию (BRD R-11, AC-19).

5. Конфигурация и секреты

Аспект Требование
Новые env-переменные Нет
Новые секреты Нет
Новые API-ключи Нет
Изменения config/*.yaml Нет
Изменения runtime config НетHILLSHADE_PAINT и TRI_PAINT — JS-константы, живут в коде и меняются коммитом (BRD §6 q&a, ADR-017 §M)
Изменения style.json / style-dark.json Нет — растровые terrain-слои добавляются динамически из JS, в стилях не описаны

6. Деплой

6.1 Среды

  • dev (локально): make dev (docker compose up app). Достаточно git pull && make dev для смены поведения.
  • test (mva154): https://openclaw.mva154.duckdns.org/enduro/. CI/CD — Gitea Actions; деплой через make deploy-test или ручной SSH + docker compose up -d --no-deps --build app (см. §6.2).
  • prod — пока не задействован; ET-013 деплоится только в test.

6.2 Процедура деплоя в test

Последовательность шагов (REQ-F-20 в TRZ §3):

  1. Pre-deploy smoke: проверить наличие тайлов z9-z11 на test-среде:
    curl -sI 'https://openclaw.mva154.duckdns.org/enduro/terrain/hillshade/9/308/158.png'  | head -1
    curl -sI 'https://openclaw.mva154.duckdns.org/enduro/terrain/hillshade/10/617/317.png' | head -1
    curl -sI 'https://openclaw.mva154.duckdns.org/enduro/terrain/hillshade/11/1234/635.png' | head -1
    
    Ожидается HTTP/1.1 200 OK на все три. Если хотя бы один 404 — merge приостанавливается (AC-19), открывается PH-6 follow-up на догенерацию тайлов.
  2. Сборка образа: docker compose build app на mva154 (после git pull).
  3. Перезапуск app: docker compose up -d --no-deps app.
  4. Post-deploy smoke:
    # Проверка статики app.js обновился
    curl -s 'https://openclaw.mva154.duckdns.org/enduro/app.js' | grep -c 'HILLSHADE_PAINT'
    # Ожидается ≥ 1
    
  5. Ручная валидация AC-03..AC-12 через DevTools:
    • открыть карту, центр над Окой/югом Москвы ([37.6, 54.5]);
    • window._map.setZoom(9) — кнопка «Тени рельефа» активна, hint скрыт;
    • включить «Тени рельефа» и «Перепады»;
    • скриншоты на z9/z10/z11/z14 → визуальная приёмка AC-07..AC-10;
    • переключить тему theme-dark → проверить AC-11;
    • переключить подложку #base-btn-satellite → проверить AC-12.
  6. Запись результатов в 13-test-report.md и 14-deploy-log.md.

6.3 Rollback

В случае проблем (например, AC-11 «hillshade сливается с dark-темой», без возможности быстрой donastройки stops):

  1. Frontend rollback: git revert <commit> + docker compose up -d --no-deps --build app.
  2. Cache invalidation: не требуется (backend не меняется, browser cache на статике app.js инвалидируется по if-modified-since автоматически).

RTO: ≤ 5 минут (один docker compose up -d --no-deps app). RPO: 0 — никаких изменений в БД, никаких данных не теряется.

6.4 CI/CD-гейты

  • make lint (ruff + eslint) — должен быть зелёным (AC-18).
  • make test (pytest unit + integration) — зелёный (AC-15..AC-17).
  • pytest tests/integration/test_terrain_z9_tiles.py — c @pytest.mark.skipif для CI без данных (AC-16), не блокирует merge.

7. Observability / Логирование

Аспект Требование
Новые лог-сообщения Нет (NFR-06 в TRZ §4)
Существующие лог-сообщения uvicorn.access логирует все запросы к /terrain/* с длиной ответа — этого достаточно для мониторинга дельты трафика после деплоя
Метрики / Prometheus Не вводим в MVP
Health-endpoint GET /api/health (если есть) — без изменений

7.1 Что мониторить после деплоя

В nginx access.log на mva154 (вручную, без алёртов) — первая неделя:

  • Запросы к /terrain/hillshade/9/*/*.png: должны появиться (раньше клиент их не дёргал). Если 404 — data/terrain/hillshade/9/ отсутствует, инцидент (BRD R-11).
  • Объём ответов: ≤ +35% к baseline на терминальную пользовательскую сессию (BRD M-10, AC-21).
  • Status codes: только 200/304 (304 от if-modified-since). Никаких 500/502 быть не должно.

8. Резервное копирование / Disaster recovery

Аспект Требование
Backup БД Без изменений vs ET-008/PH-6 (ET-013 не трогает БД)
Backup тайлов рельефа Без изменений vs PH-6. Регенерируемы из SRTM при необходимости
Время восстановления (RTO) ≤ 5 минут (rollback контейнера, см. §6.3)
Точка восстановления (RPO) 0 — никаких данных не теряется

9. Безопасность

Аспект Требование
Auth / Authorization Без изменений (NFR-05 в TRZ §4). /terrain/* — публичный (как и был)
Валидация входных данных Без изменений; existing валидация (z, x, y) в terrain_tile уже корректно принимает любые валидные z
CSP Без изменений
Rate-limit Не вводим в MVP (см. §3.2)
TLS Без изменений — nginx с Let's Encrypt сертификатом DuckDNS

10. Совместимость

Аспект Требование
API контракт /terrain/* Не меняется (REQ-F-18). Любые клиенты (старые tab'ы со старым app.js) продолжают работать; они просто не дёргают z=9 hillshade
MapLibre GL JS совместимость MapLibre 4.7.0 (index.html:10) поддерживает interpolate для raster-opacity и raster-contrast. raster-resampling не поддерживает interpolate — поэтому глобально 'nearest' (см. ADR-017 §R)
Совместимость с PH-6 stack Никаких изменений; калибровка идёт поверх существующих PH-6 тайлов
Совместимость с ET-007 (Спутник) AC-12 проверяет визуально. В случае проблем — открывается ADR-018 (theme-specific paint)
Совместимость с ET-005 (units), ET-006 (GPX), ET-008 (public tracks) Без изменений; ET-013 трогает только terrain-слои
Совместимость с OSRM Не затронуто (роутинг работает с OSRM-графом независимо)
localStorage migration Не нужно (REQ-F-17). Существующие ключи terrain-hillshade, terrain-tri — без изменений. Пользователи с включённым hillshade автоматически увидят слой на z9 при следующей загрузке

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

  • 01-brd.md §3 (F-01..F-14), §6 (Зависимости, инфра), AC §AC-19 (pre-deploy check)
  • 02-trz.md §3 REQ-F-20 Деплой и валидация, §4 NFR
  • 06-adr/ADR-017-zoom-aware-terrain-paint.md §«Классификация изменения», §«Последствия»
  • 08-data-requirements.md (этот пакет)
  • 10-tech-risks.md (этот пакет)
  • docs/work-items/ET-012/07-infra-requirements.md — образец «zero-infra» work-item (наследие)
  • docs/work-items/ET-011/07-infra-requirements.md — образец «zero-infra» work-item (наследие)