---
type: infra-requirements
work_item_id: ET-014
title: "Инфраструктурные требования — ET-014: Z-index фикс — terrain-popup уступает sheet'у"
version: 1
status: approved
created_at: 2026-06-04
authors:
  - "agent:architect"
---

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

## 1. Резюме

ET-014 — **frontend UI/DOM-stacking fix**. Меняется один файл исходного
кода (`src/web/app.js`) на ~8 строк (+1 helper-функция, +1 вызов в
`openSheet`). Инфраструктура **не меняется**:

- 0 новых docker-сервисов;
- 0 изменений в `Dockerfile`;
- 0 изменений в `docker-compose.yml`;
- 0 новых файлов БД, миграций, индексов;
- 0 новых cron-записей;
- 0 новых env / секретов / API-ключей;
- 0 новых исходящих HTTPS-соединений;
- 0 новых портов;
- 0 изменений в nginx;
- 0 изменений в backend (`src/api/*` без правок);
- 0 изменений в `src/web/app.css` (z-index стек не трогается — см. ADR-019);
- 0 изменений в `src/web/index.html`;
- 0 изменений в `src/web/gps_tracks.js`;
- 0 изменений в `style.json` / `style-dark.json`.

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

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

| Аспект                                | Требование                                                                                                                                                       |
|---------------------------------------|------------------------------------------------------------------------------------------------------------------------------------------------------------------|
| Новый сервис                          | **Нет**                                                                                                                                                          |
| Изменения `Dockerfile`                | **Нет**                                                                                                                                                          |
| Изменения `docker-compose.yml`        | **Нет**                                                                                                                                                          |
| Перезапуск `app` после деплоя         | Нужен — `docker compose up -d --no-deps app` (≈ 5 сек простоя). Подхватывает обновлённый `src/web/app.js` (отдаётся как статика из контейнера) |
| Перезапуск `gps-collector`            | Не нужен (не затронут)                                                                                                                                           |
| Очистка серверных кэшей               | Не требуется (backend не меняется)                                                                                                                                |
| Очистка клиентских кэшей              | Не требуется. При первом обращении после деплоя браузер сделает conditional GET (`If-Modified-Since`) → 200 (свежий `app.js`) или 304                            |

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

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

- `app` → отдаёт `/enduro/app.js` как статику.
- `nginx (host)` → `app:8000` через docker-network bridge.

Никаких новых межсервисных вызовов.

## 3. Сеть

| Аспект                         | Требование                                                                                                                                                  |
|--------------------------------|-------------------------------------------------------------------------------------------------------------------------------------------------------------|
| Новые входящие порты           | **Нет**                                                                                                                                                     |
| Изменения nginx                | **Нет**                                                                                                                                                     |
| Новые исходящие соединения     | **Нет**                                                                                                                                                     |
| CORS                           | Без изменений                                                                                                                                               |
| HTTPS / TLS                    | Без изменений — nginx с Let's Encrypt сертификатом DuckDNS                                                                                                  |

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

ET-014 меняет порядок вызовов JS-функций; **сетевой паттерн не меняется**.

- `/enduro/app.js`: при первом GET после деплоя — `app.js` отдаётся
  целиком (∆ размера +~300 байт за счёт helper'а и комментариев).
- Запросы к `/api/gps-tracks/*`, `/terrain/*`, `/api/route/*`,
  `/api/health` — без изменений.

Дельта на пользователя: ~300 байт единоразово при первой загрузке
после деплоя. Пренебрежимо.

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

| Аспект                  | Требование                                                                                              |
|-------------------------|---------------------------------------------------------------------------------------------------------|
| CPU `app`               | Без изменений                                                                                            |
| RAM `app`               | Без изменений                                                                                            |
| Disk `app`              | Без изменений (`app.js` ~300 байт больше — пренебрежимо)                                                 |
| CPU `gps-collector`     | Без изменений (не затронут)                                                                              |
| RAM `gps-collector`     | Без изменений                                                                                            |
| Disk `gps-collector`    | Без изменений                                                                                            |

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

| Аспект                              | Требование                                                                                                                                  |
|-------------------------------------|---------------------------------------------------------------------------------------------------------------------------------------------|
| Новые env-переменные                | **Нет**                                                                                                                                     |
| Новые секреты                       | **Нет**                                                                                                                                     |
| Новые API-ключи                     | **Нет**                                                                                                                                     |
| Изменения `config/*.yaml`           | **Нет**                                                                                                                                     |
| Изменения runtime config            | **Нет**                                                                                                                                     |
| Изменения `style.json`/`style-dark.json` | **Нет**                                                                                                                                |

## 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-014 деплоится только в test.

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

1. **Pre-deploy smoke**: проверить, что test-среда доступна:
   ```bash
   curl -sI 'https://openclaw.mva154.duckdns.org/enduro/' | head -1
   curl -sI 'https://openclaw.mva154.duckdns.org/enduro/app.js' | head -1
   ```
   Ожидается `HTTP/1.1 200 OK` на оба.

2. **Сборка образа**: `docker compose build app` на mva154 (после `git pull`).

3. **Перезапуск `app`**: `docker compose up -d --no-deps app`.

4. **Post-deploy smoke** — два grep'а по свежей статике:
   ```bash
   # Helper-функция доехала
   curl -s 'https://openclaw.mva154.duckdns.org/enduro/app.js' | grep -c 'function closeTerrainPopup'
   # Ожидается = 1

   # Вызов в openSheet доехал
   curl -s 'https://openclaw.mva154.duckdns.org/enduro/app.js' \
     | grep -A 4 'function openSheet' | grep -c 'closeTerrainPopup'
   # Ожидается ≥ 1
   ```

5. **Ручная валидация AC-01..AC-14** через мобильный и desktop браузер:
   - Mobile (DevTools 390×844, тёмная тема): Рельеф → ✓ Публичные треки →
     Фильтры… → ожидается **полностью видимая** панель «Фильтры публичных
     треков» поверх затемнённого backdrop'а (AC-01, AC-14).
   - Mobile: Фильтры открыты → клик по чекбоксу активности →
     ожидается изменение состояния (AC-03).
   - Mobile: Фильтры открыты → клик `✕` → ожидается возврат к карте без
     артефактов (AC-04).
   - Mobile: Фильтры открыты → клик по `#sheet-backdrop` → закрытие (AC-05).
   - Mobile: повторное открытие 3 раза подряд (AC-06).
   - Mobile: Рельеф → переключение чекбоксов рельефа/подложки/единиц →
     popup без изменений (AC-07).
   - Mobile: Рельеф → клик по карте → popup закрывается (AC-08).
   - Mobile: открыть `sheet-route`, `sheet-recon`, `sheet-scenic`,
     `sheet-link`, `sheet-gpx` через тулбар → без артефактов (AC-09).
   - Mobile: «Метка» → marker-dialog (z=500) поверх (AC-10).
   - Mobile: «Поиск» → search-panel (z=600) поверх (AC-11).
   - Mobile: «Линейка» → ruler-info (z=600) поверх (AC-12).
   - Mobile, светлая тема (`#btn-theme`): повторить AC-01 (AC-13).
   - Desktop 1440×900: Рельеф → ✓ Публичные треки → Фильтры… →
     sheet слева, popup исчез (AC-02).

6. **Запись результатов в `13-test-report.md` и `14-deploy-log.md`**.

### 6.3 Rollback

В случае проблем (например, регрессия закрытия одного из 5 «здоровых»
sheet'ов — крайне маловероятно, см. R-T-3 в `10-tech-risks.md`):

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

RTO: ≤ 5 минут.
RPO: 0 — никаких изменений в БД, никаких данных не теряется.

### 6.4 CI/CD-гейты

- `make lint` (ruff + eslint) — должен быть зелёным.
- `make test` (pytest unit + integration) — зелёный (никаких новых
  python-тестов в ET-014, существующие не задеты).
- Playwright UI test cases TC-UI-01..TC-UI-08
  (`04b-ui-test-cases.md`) — зелёные на CI или в локальном Playwright
  прогоне. Если Playwright не интегрирован в CI — ручная валидация
  по §6.2 шаг 5.

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

| Аспект                       | Требование                                                                                                                                            |
|------------------------------|-------------------------------------------------------------------------------------------------------------------------------------------------------|
| Новые лог-сообщения          | **Нет**                                                                                                                                                |
| Существующие лог-сообщения   | `uvicorn.access` без изменений (трафик паттерн тот же)                                                                                                |
| Метрики / Prometheus         | Не вводим                                                                                                                                              |
| Health-endpoint              | `GET /api/gps-tracks/health` — без изменений                                                                                                          |

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

В `nginx access.log` на mva154 (вручную, без алёртов) — первые сутки:

- **Запросы к `/enduro/app.js`** — должны вернуть 200 (свежая версия) или
  304 (для пользователей, у которых cache не протух).
- **Status codes для `/api/gps-tracks/*`** — без 5xx (мы не трогаем API).

Дополнительно, при ручной валидации (§6.2 шаг 5) — DevTools Console:
- Не должно быть новых warning'ов или error'ов JS.
- При открытии фильтров не должно быть `Uncaught ReferenceError:
  closeTerrainPopup is not defined` (sanity на правильность сборки).

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

| Аспект                       | Требование                                                                                          |
|------------------------------|-----------------------------------------------------------------------------------------------------|
| Backup БД                    | Без изменений vs ET-013/ET-008 (ET-014 не трогает БД)                                               |
| Backup статики `src/web/`    | Без изменений; git — источник истины                                                                |
| Время восстановления (RTO)   | ≤ 5 минут (rollback контейнера, см. §6.3)                                                            |
| Точка восстановления (RPO)   | 0 — никаких данных не теряется                                                                       |

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

| Аспект                              | Требование                                                                                                              |
|-------------------------------------|-------------------------------------------------------------------------------------------------------------------------|
| Auth / Authorization                | Без изменений                                                                                                            |
| Валидация входных данных            | Не применимо — клиентский UI-fix, никаких новых входов                                                                  |
| CSP                                 | Без изменений                                                                                                            |
| Rate-limit                          | Без изменений                                                                                                            |
| TLS                                 | Без изменений                                                                                                            |

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

| Аспект                                     | Требование                                                                                                                                                                                                                |
|--------------------------------------------|---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
| API контракт                                | Без изменений (никакие endpoint'ы не трогаются)                                                                                                                                                                            |
| Совместимость с PH-5/PH-6/PH-8 UI           | Полностью совместимо: terrain-popup, bottom-sheets, gps_tracks слой работают как раньше; меняется только порядок UI-вызовов                                                                                              |
| Совместимость с ET-007 (Спутник)            | Не задействован                                                                                                                                                                                                            |
| Совместимость с ET-008 (Публичные треки)    | Логика `togglePublicTracksFiltersSheet` не меняется; вызов `openSheet('sheet-gps-filters')` теперь корректно закрывает popup                                                                                                |
| Совместимость с ET-013 (terrain paint)      | Не задействован — paint terrain-слоёв в `applyTerrainLayer` без связи                                                                                                                                                      |
| Совместимость с MapLibre 4.7.0              | Не задействован — ET-014 не трогает MapLibre API                                                                                                                                                                          |
| localStorage migration                      | Не нужно. Никаких ключей `localStorage` ET-014 не добавляет и не меняет                                                                                                                                                    |
| Совместимость со старыми вкладками          | Старый `app.js` в кэше браузера продолжает работать со старой багой; при reload браузер дёрнет свежий → fix применится. Никакого hard-reload не нужно                                                                       |

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

- `01-brd.md` §4 (BR-01..BR-06), §9 (R1..R3)
- `02-trz.md` §1.3 (корень), §2.1 REQ-F-01..REQ-F-07, §2.2 REQ-NF-01..REQ-NF-05
- `03-acceptance-criteria.md` AC-01..AC-14
- `04b-ui-test-cases.md` TC-UI-01..TC-UI-08
- `06-adr/ADR-019-terrain-popup-yields-to-sheet.md`
- `08-data-requirements.md` (этот пакет)
- `10-tech-risks.md` (этот пакет)
- `docs/work-items/ET-013/07-infra-requirements.md` — образец «zero-infra»
  work-item (наследие)
- `docs/work-items/ET-012/07-infra-requirements.md` — образец «zero-infra»
  work-item (наследие)
