docs(ET-007): architecture - ADR, infra-requirements, data-requirements, tech-risks
All checks were successful
CI / lint (push) Successful in 3s
CI / test (push) Successful in 6s
CI / build (push) Successful in 1s

This commit is contained in:
2026-05-31 20:01:06 +00:00
parent d7d06bb046
commit 231c99c045
6 changed files with 818 additions and 1 deletions

View File

@@ -0,0 +1,200 @@
---
type: tech-risks
work_item_id: ET-007
title: "Технические риски — ET-007: Спутниковая карта (Схема / Спутник)"
version: 1
status: approved
created_at: 2026-05-31
authors:
- "agent:architect"
---
# Технические риски — ET-007
Технические риски этапа разработки. Бизнес-риски — в BRD §5
(пересечение есть, здесь акцент на техническую митигацию).
Шкала: вероятность (Н/С/В) × влияние (Н/С/В).
## R-1 — Дрейф halo-слоёв в `style.json` / `style-dark.json`
- **Описание:** ADR-004 §5 решает читаемость линий грунтовок и троп
на спутнике через парные «underlay»-слои `*-halo-satellite` с
`visibility: none` в обоих файлах стилей. Любая будущая правка
основных trails-слоёв (цвет, ширина, фильтр) требует **согласованной
правки halo-слоёв** в обоих файлах. Без явной проверки легко
забыть один из четырёх случаев (2 темы × 2 рода слоёв).
- **Вероятность / Влияние:** С / Н.
- **Митигация:**
- При разработке завести единый список затрагиваемых пар в
`applyBaseLayer()`: массив `['trails-grade1', 'trails-grade2', ...]`
с производным правилом `<base>-halo-satellite`. Это исключит
«забытый» halo-слой со стороны JS.
- Code review-чеклист: при правке trails-* в `style*.json`
обязательная сверка `*-halo-satellite` в том же файле.
- UI-тест AC-04 проверяет видимость линий поверх спутника в обеих
темах.
## R-2 — Провайдер Esri меняет условия / URL / вводит API-ключ
- **Описание:** Esri World Imagery — единственная внешняя зависимость
фичи, выбранная без формального соглашения; в перспективе Esri
может ограничить бесплатный доступ, изменить URL-схему или ввести
обязательный API-ключ (BRD §5 риск №1). Тогда «Спутник» перестаёт
работать у всех пользователей одновременно.
- **Вероятность / Влияние:** С / В.
- **Митигация:**
- Точка расширения локализована: единственный объект source-spec
в `applyBaseLayer()` (ADR-004 §1).
- При деградации провайдера выполняется одна правка JS-фронтенда
(новый URL-шаблон + новая атрибуция), без миграций и серверных
изменений; откат прежнего поведения — обратный коммит.
- Альтернативные провайдеры предварительно рассмотрены в ADR-004
§«Вариант P»; быстрый switch на следующего по приоритету —
Mapbox или MapTiler — потребует только введения переменной
окружения для API-ключа (это уже инфра-изменение, выходящее за
scope ET-007).
- Регулярная smoke-проверка дос­тупности через UI-тест AC-02.
## R-3 — Утечка IP клиента на серверы Esri
- **Описание:** при активном «Спутник» браузер обращается напрямую
к `server.arcgisonline.com`; IP пользователя и User-Agent видны
Esri. Это **не регрессия** (OSM tile уже работает аналогично), но
расширение списка третьих сторон, к которым обращается клиент.
- **Вероятность / Влияние:** В (т.е. произойдёт всегда при включении
спутника, дизайн именно такой) / Н.
- **Митигация:**
- **Ленивое создание source** (ADR-004 §3): пользователь,
никогда не включающий «Спутник», ни одного запроса в Esri не
отправляет. Это обеспечивает «приватный по умолчанию» режим.
- Документировано в `08-data-requirements.md` §7.
- В отдельный политический документ выноситься не требуется —
приватность фичи на уровне рейзанса вынесена в ADR-004 §«Последствия».
## R-4 — Корпсеть / DNS-блокировка `arcgisonline.com`
- **Описание:** часть пользователей работает в сетях, блокирующих
arcgisonline.com (анти-трекинг-DNS типа NextDNS/Pi-hole,
корпоративные firewall). MapLibre будет показывать прозрачные
плитки поверх фона `#2a2a2a`; пользователь увидит «дыры».
- **Вероятность / Влияние:** Н / С.
- **Митигация:**
- TRZ §1 REQ-F-08 явно фиксирует: автоматический fallback на
«Схему» не закладывается — пользователь возвращается на схему
вручную; это сознательное проектное решение.
- В виду фона `#2a2a2a` пустота визуально опознаётся как ошибка
подложки, а не «лёг" сайт.
- Эскалация / альтернативный провайдер при единичных жалобах не
требуется; при системных — переход к R-2.
## R-5 — Дублирование `background-color` между `style*.json` и `app.js`
- **Описание:** ADR-004 §6 требует менять `background-color` на
тёмно-серый при включении «Спутник» и возвращать к исходному при
возврате на «Схему». «Исходные» значения (`#f0ede6` для светлой,
тёмное для тёмной) дублируются в `applyBaseLayer()` и в
`style*.json` — при смене палитры тем легко забыть один из двух.
- **Вероятность / Влияние:** Н / Н.
- **Митигация:**
- Альтернатива — при возврате на «Схему» **читать** актуальное
значение через `getPaintProperty('background', 'background-color')`
непосредственно перед мутацией в «Спутник», и кэшировать его в
замыкании. Однако `setStyle()` сбрасывает кэш, что усложняет
логику. Принято: задублировать в коде с явным комментарием
в `app.js` и code review-чеклистом.
- Покрытие AC-06 (смена темы при активном «Спутник») косвенно
проверяет согласованность.
## R-6 — Накопление обработчиков и source/layer после `map.setStyle()`
- **Описание:** при `map.setStyle()` (переключение тёмной/светлой
темы) спутниковый source/layer удаляются вместе со стилем.
`restoreBaseLayerState()` пересоздаёт их в `rebuildMapOverlays()`.
Аналогичный риск зафиксирован для GPX (ET-006, R-4: «дублирование
обработчиков»). Спутник, в отличие от GPX, **не вешает свои
`map.on('click', ...)`** обработчиков на свои слои (он —
невзаимодействующий растр), поэтому дублирования обработчиков
здесь не возникает.
- **Вероятность / Влияние:** Н / Н.
- **Митигация:** проверка перед `addSource` — `if
(!map.getSource('satellite-raster')) map.addSource(...)`; то же для
layer. Это идемпотентный паттерн, уже используемый в проекте для
terrain/trails.
## R-7 — Несовместимость z-order при `restoreBaseLayerState()` после terrain
- **Описание:** если разработчик случайно вызовет
`restoreBaseLayerState()` **после** `restoreTerrainState()` в
`rebuildMapOverlays()`, спутник окажется поверх hillshade и
перекроет его. Это нарушит AC-04 («Hillshade поверх спутника»).
- **Вероятность / Влияние:** Н / С.
- **Митигация:**
- ADR-004 §4 явно фиксирует: `restoreBaseLayerState()` вызывается
**ПЕРВЫМ** в `rebuildMapOverlays()`.
- Комментарий в коде `app.js` непосредственно у вызова —
`// ET-007/ADR-004: ПЕРВЫМ, чтобы trails/terrain легли поверх`.
- UI-тест AC-04 «Hillshade поверх спутника» отлавливает регрессию.
## R-8 — Производительность переключения «Схема → Спутник» > 500 мс
- **Описание:** НФТ ТЗ — ≤ 500 мс до первой видимой плитки. При
холодном переключении в одном кадре происходит: чтение
`localStorage`, `addSource`, `addLayer`, `setLayoutProperty`,
`setPaintProperty` ×N для POI, `setLayoutProperty` ×K для halo-
underlays. Главная неопределённость — сетевая задержка до Esri.
- **Вероятность / Влияние:** Н / С.
- **Митигация:**
- Все операции стиля MapLibre — синхронные O(1) на source/layer;
суммарно < 50 мс.
- Сетевая задержка для PNG 3080 КБ из Esri CDN на канале
≥ 5 Мбит/с укладывается в 200300 мс на тайл (по практике
Leaflet/OpenLayers с этим же провайдером).
- Тест НФТ TP-Performance в `04-test-plan.yaml` проверяет
верхнюю границу.
## R-9 — Конфликт mobile-вёрстки попапа
- **Описание:** новая строка `terrain-base-row` добавляется в
`#terrain-popup` сверху. На узких экранах (375 px, ET-005 TP-05)
возможен выход за пределы попапа или перекрытие смежных строк.
- **Вероятность / Влияние:** Н / Н.
- **Митигация:**
- Переиспользуется готовый компонент `.seg-control` (адаптивен по
ширине), без введения нового CSS-компонента.
- UI-тест AC-09 (mobile viewport 375 × 812) — обязательный.
## R-10 — Включение спутника после рестарта при отсутствии сети у Esri
- **Описание:** пользователь сохранил `map-base-layer = "satellite"`,
затем при следующем визите Esri недоступен. `restoreBaseLayerState()`
вызовет `applyBaseLayer('satellite')`, source создастся, плиток не
будет — пользователь увидит пустой тёмный фон вместо привычной
карты.
- **Вероятность / Влияние:** Н / Н.
- **Митигация:**
- Поведение явно соответствует TRZ §1 REQ-F-08; на mobile/desktop
пользователь нажмёт «Схема» и продолжит работу.
- Авто-fallback на «Схему» при сетевой ошибке провайдера —
**не закладывается** (см. ADR-004 §«Последствия»). Введение
fallback возможно в будущей итерации без изменения внешнего
контракта `applyBaseLayer()`.
## Сводная таблица
| ID | Риск | Вер. | Влияние | Класс | Статус |
|-----|------|------|---------|-------|--------|
| R-1 | Дрейф halo-слоёв в обоих style.json | С | Н | Средний | внимание разработки + review |
| R-2 | Esri меняет условия / URL / вводит ключ | С | В | Высокий | митигация — точка расширения |
| R-3 | Утечка IP на Esri при активном спутнике | В | Н | Средний | приватный-по-умолчанию (lazy) |
| R-4 | DNS-блокировка `arcgisonline.com` | Н | С | Низкий | принят (TRZ REQ-F-08) |
| R-5 | Дубль background-color в style/app.js | Н | Н | Низкий | принят + комментарий в коде |
| R-6 | Source/layer после setStyle | Н | Н | Низкий | идемпотентные `if (!getSource)` |
| R-7 | Неверный порядок restoreBaseLayerState | Н | С | Низкий | ADR явно + комментарий + AC-04 |
| R-8 | Переключение > 500 мс | Н | С | Низкий | покрыто НФТ-тестом |
| R-9 | Mobile-вёрстка попапа | Н | Н | Низкий | AC-09 |
| R-10 | Restore satellite при недоступности Esri | Н | Н | Низкий | принят, fallback не закладываем |
Блокирующих рисков нет. R-2 — единственный «высокий» класс, но
вероятность средняя и митигация (локализация точки расширения)
делает реакцию операционно простой. Эскалация `arch:major-change`
или возврат в Анализ не требуются.