docs(ET-007): architecture - ADR, infra-requirements, data-requirements, tech-risks
This commit is contained in:
305
docs/work-items/ET-007/06-adr/ADR-004-satellite-base-layer.md
Normal file
305
docs/work-items/ET-007/06-adr/ADR-004-satellite-base-layer.md
Normal file
@@ -0,0 +1,305 @@
|
||||
---
|
||||
type: adr
|
||||
work_item_id: ET-007
|
||||
adr_id: ADR-004
|
||||
title: "ADR-004: Спутниковая подложка — провайдер Esri World Imagery, лениво-добавляемый raster-source, гибридная стратегия halo"
|
||||
status: accepted
|
||||
created_at: 2026-05-31
|
||||
authors:
|
||||
- "agent:architect"
|
||||
supersedes: []
|
||||
superseded_by: []
|
||||
labels: []
|
||||
---
|
||||
|
||||
# ADR-004 — Спутниковая подложка: провайдер, размещение кода, схема восстановления
|
||||
|
||||
## Статус
|
||||
|
||||
Accepted
|
||||
|
||||
## Контекст
|
||||
|
||||
ET-007 вводит вторую базовую подложку карты — спутниковые растровые
|
||||
снимки — с переключателем «Схема / Спутник» в попапе слоёв
|
||||
(см. `01-brd.md`, `02-trz.md`, `03-acceptance-criteria.md`).
|
||||
|
||||
Существующее состояние, проверенное в коде:
|
||||
|
||||
- В обоих стилях карты (`src/web/style.json` стр. 16–41,
|
||||
`src/web/style-dark.json`) уже определён единственный raster-source
|
||||
`osm-raster` и слой `osm-base`, лежащий поверх слоя `background`.
|
||||
Тайлы OSM раздаются `https://tile.openstreetmap.org/{z}/{x}/{y}.png`
|
||||
— то есть прецедент **внешней (кросс-оригинальной) тайл-зависимости с
|
||||
атрибуцией без API-ключа уже существует**.
|
||||
- `src/web/app.js` (3 132 строки) содержит функцию `rebuildMapOverlays()`
|
||||
(стр. 127), которая последовательно вызывает `restoreTerrainState()`,
|
||||
`restoreTrailsState()`, `restorePoiState()`, перерисовку маршрутов /
|
||||
GPX / линейки. Эта функция — единственная точка восстановления
|
||||
визуальных слоёв после `map.setStyle()` (переключение тёмной/светлой
|
||||
темы, `switchMapStyle()` стр. 100–117).
|
||||
- Фронтенд плоский, без сборщика: `index.html`, `app.js`, `units.js`
|
||||
(190 строк, ADR-0001), `gpx.js` (1 242 строки, ADR-002). Сложившийся
|
||||
паттерн — «одна крупная фича = один классический скрипт + глобали»
|
||||
(ADR-002). Все JS-функции глобальные, обработчики навешаны через
|
||||
инлайновые `onclick`.
|
||||
- Динамические мутации слоёв через `setPaintProperty` /
|
||||
`setLayoutProperty` / `addSource` / `addLayer` в `app.js` уже широко
|
||||
используются (~30 вхождений).
|
||||
- В `app.js` уже есть зрелые «restore*State()»-функции для каждой
|
||||
группы слоёв; ET-007 встраивается в этот же паттерн ещё одной такой
|
||||
функцией `restoreBaseLayerState()`.
|
||||
|
||||
Решения, которые предстоит зафиксировать архитектурно:
|
||||
|
||||
1. Какого провайдера спутниковых тайлов выбрать.
|
||||
2. Где разместить код переключателя — в `app.js` или в новом модуле.
|
||||
3. Как именно добавлять спутниковый source/layer (заранее в `style.json`
|
||||
или лениво из JS), и как переживать `map.setStyle()`.
|
||||
4. Каким способом обеспечивать читаемость линий грунтовок/троп и POI
|
||||
на тёмной спутниковой подложке (halo).
|
||||
5. Классификацию изменения и нужна ли эскалация `arch:major-change`.
|
||||
|
||||
## Рассмотренные варианты
|
||||
|
||||
### Вариант P (провайдер) — выбор провайдера спутниковых тайлов
|
||||
|
||||
| Провайдер | API-ключ | Лицензия / условия | Покрытие | Решение |
|
||||
|---|---|---|---|---|
|
||||
| **Esri World Imagery** (`server.arcgisonline.com/.../World_Imagery/MapServer/tile/{z}/{y}/{x}`) | нет | Условия Esri ArcGIS Online: бесплатное использование с атрибуцией для некоммерческой и demo-разработки; широко применяется open-source-проектами (Leaflet, OpenLayers, QGIS) | глобальное, до z19 | **выбран** |
|
||||
| Mapbox Satellite | требуется | бесплатный квот-лимит, далее платно | глобальное | отклонён — BRD F-02 явно требует «без API-ключа» |
|
||||
| Bing Maps | требуется | сложная лицензия, обязательная регистрация | глобальное | отклонён — то же |
|
||||
| Google Maps Tiles | требуется | прямо запрещён ToS для нативного встраивания не через Google Maps JS API | глобальное | отклонён |
|
||||
| OpenAerialMap | нет | open-source, CC-BY | **фрагментарное**, нет глобального бесшовного слоя | отклонён — не покрывает РФ-эндуро-сценарии |
|
||||
| MapTiler Satellite | требуется | бесплатный квот-лимит | глобальное | отклонён — API-ключ |
|
||||
|
||||
Esri World Imagery — единственный вариант, удовлетворяющий
|
||||
**одновременно** трём ограничениям BRD: без API-ключа, с глобальным
|
||||
покрытием, с лицензионно допустимой формой использования через
|
||||
атрибуцию.
|
||||
|
||||
### Вариант M (модуль) — где разместить код
|
||||
|
||||
- **M-A — добавить в `app.js`** (выбран). +~150 строк
|
||||
(`onBaseLayerToggle`, `applyBaseLayer`, `restoreBaseLayerState`,
|
||||
`syncBaseLayerUI`, плюс хук в `rebuildMapOverlays()` и handler
|
||||
`onclick` в `index.html`). Минимальный blast radius, никаких новых
|
||||
файлов, никаких изменений в подключении скриптов.
|
||||
- **M-B — выделить `src/web/basemap.js`** (по аналогии с ADR-002 для
|
||||
GPX). Отклонён: ADR-002 разделил фичу, потому что её объём был
|
||||
600–900 строк и она имела собственную модель данных (`gpxTracks`),
|
||||
собственный bottom sheet и собственный canvas. Здесь фича плоская и
|
||||
объём в 5–7 раз меньше; разделение даёт чистоту, но не покрывает
|
||||
стоимости новой связки `app.js ↔ basemap.js` ради ~150 строк.
|
||||
Контракт интеграции с `rebuildMapOverlays()` и так глобальный —
|
||||
никакой инкапсуляции отдельный файл не добавит.
|
||||
|
||||
### Вариант S (source) — как добавить спутниковый source/layer
|
||||
|
||||
- **S-A — задекларировать source `satellite-raster` и слой
|
||||
`satellite-base` (`visibility: none`) в обоих `style.json` /
|
||||
`style-dark.json`**. Source активен всегда, тайлы не запрашиваются
|
||||
до показа слоя. Плюс: восстановление после `setStyle()`
|
||||
тривиально (`setLayoutProperty('satellite-base', 'visibility', ...)`).
|
||||
Минус: `style.json` обоих тем нужно править симметрично; дрейф
|
||||
значений между двумя стилями.
|
||||
- **S-B — лениво создавать source и layer из JS при первом включении
|
||||
«Спутник»** (выбран, совпадает с TRZ §1 REQ-F-02). Плюс: `style.json`
|
||||
не трогаем; ноль внешних запросов у пользователей, которые не
|
||||
включают спутник; единая точка определения source — в `app.js`. После
|
||||
`map.setStyle()` source и layer исчезают и переcоздаются вызовом
|
||||
`restoreBaseLayerState()` из `rebuildMapOverlays()` — это та же
|
||||
логика, что уже используется для terrain/trails/POI/GPX. Минус:
|
||||
холодное переключение «Схема → Спутник» включает в себя `addSource`
|
||||
+ `addLayer` + сетевой запрос — но укладывается в НФТ 500 мс.
|
||||
|
||||
### Вариант O (order) — порядок восстановления в `rebuildMapOverlays()`
|
||||
|
||||
- **O-A — `restoreBaseLayerState()` вызывается ПЕРВЫМ**, до
|
||||
`restoreTerrainState()` (выбран, совпадает с TRZ §5.5). Гарантирует
|
||||
z-order: `background` → `satellite-base` → `osm-base` → terrain →
|
||||
trails → POI → routes → GPX. terrain/trails/POI оказываются выше
|
||||
спутника, маршрут/GPX — выше terrain.
|
||||
- **O-B — добавлять `satellite-base` с явным `beforeId` первого
|
||||
trails-слоя**. Идемпотентно к порядку, но в `rebuildMapOverlays()`
|
||||
моменты создания слоёв не атомарны (terrain/trails добавляются
|
||||
асинхронно); использовать `beforeId` слоёв, которых ещё нет, нельзя.
|
||||
Поэтому простой «вызвать первым» надёжнее.
|
||||
|
||||
### Вариант H (halo) — обеспечение читаемости поверх спутника
|
||||
|
||||
- **H-A — динамический `setPaintProperty` по всем затрагиваемым слоям**.
|
||||
Все правки делаем из `applyBaseLayer()`; на «Схема» возвращаем
|
||||
исходные значения. Минус: нужно где-то хранить «исходные» paint-
|
||||
значения; при `map.setStyle()` они сбрасываются, что повышает риск
|
||||
drift между двумя темами.
|
||||
- **H-B — отдельные «underlay»-слои с halo, `visibility: none` по
|
||||
умолчанию, включаются на спутнике** + **`setPaintProperty` только
|
||||
для POI text-halo** (выбран, совпадает с TRZ §1 REQ-F-04). Halo-линии
|
||||
декларативны в `style.json` обеих тем — никакого «запомнить
|
||||
исходное» не нужно, восстановление по `visibility`. Для POI label
|
||||
правок одна (`text-halo-color`/`text-halo-width`) — её проще менять
|
||||
динамически, чем заводить параллельные label-слои.
|
||||
- **H-C — толстая полупрозрачная белая обводка прямо в существующих
|
||||
trails-слоях через `line-gap-width`**. Отклонён: ломает «Схему»
|
||||
(там halo не нужен и портит вид светлой подложки).
|
||||
|
||||
## Решение
|
||||
|
||||
Принимается комбинация: **P-Esri + M-A + S-B + O-A + H-B**.
|
||||
|
||||
1. **Провайдер — Esri World Imagery.** URL-шаблон, атрибуция и параметры
|
||||
source — как в TRZ §4.1. HTTPS обязателен. Атрибуция строки —
|
||||
`"Source: Esri, Maxar, Earthstar Geographics, and the GIS User Community"`.
|
||||
Альтернативные провайдеры не закладываются в код фичи; точка
|
||||
расширения — единственный объект source-spec в `applyBaseLayer()`,
|
||||
при будущей смене провайдера правка локализуется одним местом
|
||||
(см. R-2 в `10-tech-risks.md`).
|
||||
|
||||
2. **Код фичи живёт в `app.js`.** Никакой новый JS-файл не вводится.
|
||||
Новые глобальные функции — `onBaseLayerToggle()`, `applyBaseLayer()`,
|
||||
`restoreBaseLayerState()`, `syncBaseLayerUI()` — добавляются по
|
||||
соседству с уже существующими `restoreTerrainState()` /
|
||||
`restoreTrailsState()`. Если в будущей фазе появится потребность
|
||||
(например, второй провайдер, гибридный режим, оффлайн-кэш) — фича
|
||||
мигрирует в `src/web/basemap.js` без изменения публичного контракта
|
||||
(имена функций глобальные и стабильные).
|
||||
|
||||
3. **Source и layer добавляются лениво** при первом включении
|
||||
«Спутник» через `addSource('satellite-raster', {...})` +
|
||||
`addLayer({ id: 'satellite-base', ... })`. До этого момента
|
||||
запросов к `server.arcgisonline.com` не происходит. Это важно с
|
||||
точки зрения приватности: пользователи, которые никогда не
|
||||
используют спутник, не светят свой IP на серверы Esri (см.
|
||||
`10-tech-risks.md`, R-3).
|
||||
|
||||
4. **Восстановление после `map.setStyle()` — через `rebuildMapOverlays()`.**
|
||||
В функцию добавляется **первым** вызов
|
||||
`if (typeof restoreBaseLayerState === 'function') restoreBaseLayerState();`
|
||||
до `restoreTerrainState()`. Это гарантирует, что terrain и trails
|
||||
окажутся выше спутника, без необходимости вычислять `beforeId`.
|
||||
`restoreBaseLayerState()` идемпотентен: читает `localStorage` ключа
|
||||
`map-base-layer` и применяет `applyBaseLayer()`.
|
||||
|
||||
5. **Halo — гибридный подход:**
|
||||
|
||||
- Для **линий grade1..5 и paths/bridleway** в обоих `style.json` /
|
||||
`style-dark.json` заводятся парные «underlay»-слои
|
||||
(`*-halo-satellite`) с более широкой полупрозрачной белой
|
||||
обводкой и `layout.visibility = "none"`. При входе в «Спутник»
|
||||
эти слои становятся видимыми; при возврате на «Схему» —
|
||||
скрываются. Никаких runtime-правок paint не требуется.
|
||||
- Для **POI labels** меняются динамически только два свойства —
|
||||
`text-halo-color` (`#000000` на спутнике / исходное на схеме) и
|
||||
`text-halo-width` (`2` на спутнике / исходное на схеме) — через
|
||||
`setPaintProperty`. Эти исходные значения известны и
|
||||
зафиксированы в `style.json`; читать «текущее» через
|
||||
`getPaintProperty` не нужно — всегда выставляем явные значения
|
||||
для обоих режимов.
|
||||
- **POI circles** — обводка `circle-stroke-color: #ffffff` /
|
||||
`circle-stroke-width: 2` динамически на спутнике, возврат к
|
||||
исходным значениям из `style.json` на схеме.
|
||||
|
||||
6. **Цвет `background`** в режиме «Спутник» меняется через
|
||||
`setPaintProperty('background', 'background-color', '#2a2a2a')`
|
||||
(тёмно-серый), чтобы не «бликовало» под медленно подгружающимися
|
||||
спутниковыми плитками. При возврате на «Схему» восстанавливаются
|
||||
исходные значения из `style.json` (`#f0ede6` для светлой темы,
|
||||
тёмное значение из `style-dark.json` для тёмной). Эти константы —
|
||||
единственные «дублирующие» значения; они зафиксированы в
|
||||
`applyBaseLayer()` и в `08-data-requirements.md` §5.
|
||||
|
||||
7. **localStorage — ключ `map-base-layer`** (см. TRZ §4.3), значения
|
||||
`"schematic"` / `"satellite"`, default `"schematic"`. Ключ
|
||||
полностью обособлен от существующих UI-настроек
|
||||
(`enduro-theme-mode`, `distance_unit`, `terrain-*`, `trails-*`,
|
||||
`poi-visible`) — никаких миграций старых значений не требуется.
|
||||
|
||||
8. **C4 / архитектурная диаграмма.** В репозитории нет файлов
|
||||
`c4-*.mmd`; описание архитектуры — текстовое в
|
||||
`docs/architecture/README.md`. Туда добавляется отдельный раздел
|
||||
«Внешние тайл-провайдеры» с двумя строками: OSM (существующий)
|
||||
и Esri World Imagery (новый, для подложки «Спутник»). Дополнительно
|
||||
`docs/architecture/adr/README.md` пополняется записью ADR-004.
|
||||
|
||||
## Последствия
|
||||
|
||||
### Положительные
|
||||
|
||||
- Изменения — **только в коде фронтенда** (`src/web/index.html`,
|
||||
`src/web/app.js`, `src/web/app.css`, оба `style*.json`). Backend,
|
||||
БД, OSRM, nginx, Docker-конфигурация — без изменений (см.
|
||||
`07-infra-requirements.md`).
|
||||
- Лазерная локальность точки расширения: для смены провайдера
|
||||
достаточно отредактировать один объект source-spec в `app.js`.
|
||||
- НФТ 500 мс выполнима: при холодном переключении расходы — это
|
||||
единичные вызовы `addSource` + `addLayer` + первая сетевая загрузка
|
||||
плитки z=текущий; последующие переключения мгновенные (только
|
||||
`visibility`).
|
||||
- Пользователи, никогда не использующие «Спутник», не отправляют ни
|
||||
одного запроса на серверы Esri — минимизация утечки данных по
|
||||
умолчанию (см. R-3).
|
||||
- Существующая инфраструктура восстановления после `map.setStyle()`
|
||||
переиспользуется без изменения её формы — единый паттерн для
|
||||
terrain/trails/POI/GPX/base-layer.
|
||||
|
||||
### Отрицательные / ограничения
|
||||
|
||||
- **Зависимость от третьей стороны.** Сервис Esri может ввести
|
||||
лимит / потребовать API-ключ / изменить URL. Митигация: точка
|
||||
расширения в `applyBaseLayer()`; риск зафиксирован
|
||||
(`10-tech-risks.md`, R-2).
|
||||
- **Утечка IP при использовании спутника.** При активном «Спутник»
|
||||
IP пользователя становится виден Esri (так же, как сейчас он виден
|
||||
tile.openstreetmap.org). Это **не регрессия приватности относительно
|
||||
OSM**, но — расширение перечня третьих сторон, к которым клиент
|
||||
обращается. Зафиксировано в `08-data-requirements.md` §5 и
|
||||
`10-tech-risks.md` R-3.
|
||||
- **Корпоративные / анти-трекинг блокировки.** Часть пользователей
|
||||
(корпсети, NextDNS-фильтры) могут блокировать `arcgisonline.com`.
|
||||
Поведение в этом случае — MapLibre показывает прозрачные плитки
|
||||
поверх `#2a2a2a` фона; пользователь сам переключится на «Схему».
|
||||
Это нормальное поведение (TRZ §1 REQ-F-08); fallback на схему
|
||||
автоматически — **не закладываем**.
|
||||
- **Halo-слои в `style.json` обоих тем.** Любые будущие правки
|
||||
trails-слоёв требуют согласованной правки соответствующих
|
||||
`*-halo-satellite` слоёв. Зафиксировано в `10-tech-risks.md` R-1.
|
||||
- **Background цвет.** В коде `applyBaseLayer()` появляется маленький
|
||||
дубль констант фона по темам. При смене палитры тем — править здесь
|
||||
тоже. Зафиксировано в `10-tech-risks.md` R-5.
|
||||
|
||||
### Технический долг
|
||||
|
||||
- Если позже появится потребность во **втором** провайдере (например,
|
||||
для альтернативной геополитической юрисдикции) или в гибридном
|
||||
режиме «Спутник + подписи дорог OSM поверх», логичный путь —
|
||||
вынести фичу в `src/web/basemap.js` (ADR-002-стиль) и расширить
|
||||
локальное состояние до `{ provider, hybrid }`. Имена глобальных
|
||||
функций (`onBaseLayerToggle`, `restoreBaseLayerState`) остаются
|
||||
стабильным контрактом — `index.html` и `app.js` не меняются.
|
||||
- Если в проект введут CSP-заголовок (сейчас его нет, см. ET-006
|
||||
`07-infra-requirements.md` §4), для спутника потребуется
|
||||
`img-src 'self' https://*.openstreetmap.org https://server.arcgisonline.com data:;`.
|
||||
|
||||
## Классификация изменения
|
||||
|
||||
**Minor change.** Новых контейнеров, сервисов, БД, серверных API
|
||||
ET-007 не вводит. Внешний тайл-провайдер — расширение уже
|
||||
существующего класса зависимостей (OSM-tile), а не новый
|
||||
архитектурный класс. Лейбл `arch:major-change` **не требуется**.
|
||||
Обязательного дополнительного архитектурного approve не требуется.
|
||||
|
||||
## Связанные документы
|
||||
|
||||
- `docs/work-items/ET-007/01-brd.md`
|
||||
- `docs/work-items/ET-007/02-trz.md`
|
||||
- `docs/work-items/ET-007/03-acceptance-criteria.md`
|
||||
- `docs/work-items/ET-007/04-test-plan.yaml`
|
||||
- `docs/work-items/ET-007/04b-ui-test-cases.md`
|
||||
- `docs/work-items/ET-007/07-infra-requirements.md`
|
||||
- `docs/work-items/ET-007/08-data-requirements.md`
|
||||
- `docs/work-items/ET-007/10-tech-risks.md`
|
||||
- `docs/architecture/README.md`
|
||||
- `docs/architecture/adr/README.md`
|
||||
- ADR-0001 (ET-005) — паттерн классических скриптов
|
||||
- ADR-002 (ET-006) — «одна фича = один скрипт + глобали»
|
||||
163
docs/work-items/ET-007/07-infra-requirements.md
Normal file
163
docs/work-items/ET-007/07-infra-requirements.md
Normal file
@@ -0,0 +1,163 @@
|
||||
---
|
||||
type: infra-requirements
|
||||
work_item_id: ET-007
|
||||
title: "Инфраструктурные требования — ET-007: Спутниковая карта (Схема / Спутник)"
|
||||
version: 1
|
||||
status: approved
|
||||
created_at: 2026-05-31
|
||||
authors:
|
||||
- "agent:architect"
|
||||
---
|
||||
|
||||
# Инфраструктурные требования — ET-007
|
||||
|
||||
## 1. Резюме
|
||||
|
||||
ET-007 — изменение **исключительно фронтенда**: `src/web/index.html`,
|
||||
`src/web/app.js`, `src/web/app.css`, `src/web/style.json`,
|
||||
`src/web/style-dark.json`. Новой инфраструктуры, новых контейнеров,
|
||||
новых портов и серверной конфигурации **не требуется**. Документ
|
||||
зафиксирован для полноты work-item и явно подтверждает отсутствие
|
||||
инфра-воздействия (см. `06-adr/ADR-004-satellite-base-layer.md`).
|
||||
|
||||
## 2. Контейнеры и сервисы
|
||||
|
||||
| Аспект | Требование |
|
||||
|--------|------------|
|
||||
| Новые контейнеры | Нет |
|
||||
| Изменения существующих сервисов (api, osrm, nginx) | Нет |
|
||||
| Изменения `docker-compose.yml` | Нет |
|
||||
| Изменения `Dockerfile` | Нет — все правки попадают в образ через уже существующий `COPY src/web/ ./src/web/` |
|
||||
| Изменения подключения скриптов в `index.html` | Нет новых `<script>`; добавляется только разметка попапа и обработчики |
|
||||
| Перезапуск backend / OSRM | Не требуется |
|
||||
| Простой (downtime) | Отсутствует — изменение только в статике фронтенда |
|
||||
|
||||
## 3. Сеть
|
||||
|
||||
| Аспект | Требование |
|
||||
|--------|------------|
|
||||
| Новые серверные порты | Нет |
|
||||
| Изменения reverse proxy (nginx, `/enduro/`) | Нет |
|
||||
| Новые внутренние DNS-записи | Нет |
|
||||
| **Новые исходящие сетевые вызовы из браузера клиента** | **Да** — `GET https://server.arcgisonline.com/ArcGIS/rest/services/World_Imagery/MapServer/tile/{z}/{y}/{x}` (HTTPS, без авторизации, raster PNG/JPEG ≈ 30–80 КБ на плитку). Запросы инициируются **только** при активном режиме «Спутник» (лениво — см. ADR-004 §5) |
|
||||
| Серверный трафик | Не меняется — спутниковые тайлы идут напрямую браузер ↔ Esri, не через mva154 |
|
||||
|
||||
### 3.1 Корпоративные/DNS-фильтры
|
||||
|
||||
Часть пользователей может работать в сетях, блокирующих
|
||||
`arcgisonline.com` (анти-трекинг-DNS, корпсети). Поведение в этом
|
||||
случае задокументировано в TRZ §1 REQ-F-08: MapLibre показывает
|
||||
прозрачные плитки поверх фона `#2a2a2a`; пользователь возвращается на
|
||||
«Схему» вручную. Никаких серверных обходов или прокси через
|
||||
`/enduro/` не закладывается.
|
||||
|
||||
### 3.2 CSP-заголовок
|
||||
|
||||
В проекте сейчас CSP не задаётся (подтверждено в ET-006
|
||||
`07-infra-requirements.md` §4). Если CSP будет введён в будущем,
|
||||
директива `img-src` должна включать `https://server.arcgisonline.com`
|
||||
(а также уже используемые `https://tile.openstreetmap.org` и
|
||||
`data:`). На данном этапе никаких заголовков ET-007 не вводит.
|
||||
|
||||
## 4. Хранилища данных
|
||||
|
||||
| Аспект | Требование |
|
||||
|--------|------------|
|
||||
| Изменения схемы SQLite / Spatialite | Нет |
|
||||
| Миграции БД (`migrations/`) | Нет |
|
||||
| Серверное хранилище состояния | Нет |
|
||||
| Клиентское хранилище | `localStorage`, единственный ключ `map-base-layer`, значения `"schematic"` \| `"satellite"`, ≤ 16 байт |
|
||||
| Кэширование спутниковых тайлов | Только штатный HTTP-кэш браузера. Самостоятельный offline-кэш (Service Worker, IndexedDB) — out of scope, относится к PH-9 (см. BRD §3) |
|
||||
|
||||
Подробности по данным — `08-data-requirements.md`.
|
||||
|
||||
## 5. Конфигурация и секреты
|
||||
|
||||
| Аспект | Требование |
|
||||
|--------|------------|
|
||||
| Новые переменные окружения | Нет |
|
||||
| Новые секреты / API-ключи | **Нет** — выбран провайдер без API-ключа (см. ADR-004 §1, BRD F-02) |
|
||||
| Изменения конфигурации FastAPI / uvicorn | Нет |
|
||||
| Изменения конфигурации OSRM | Нет |
|
||||
|
||||
## 6. Зависимости
|
||||
|
||||
| Аспект | Требование |
|
||||
|--------|------------|
|
||||
| Новые npm / Python-пакеты | Нет |
|
||||
| Версия MapLibre GL JS | Без изменений (4.7.0) |
|
||||
| Новые self-hosted сервисы | Нет |
|
||||
| **Новые третьи стороны во время выполнения** | **Да** — `server.arcgisonline.com` (Esri ArcGIS Online, World Imagery). Юридическое основание: бесплатное использование с атрибуцией для некоммерческой / demo-разработки; атрибуция выводится автоматически MapLibre при активном source. Зафиксировано в `docs/architecture/README.md` §«Внешние тайл-провайдеры» |
|
||||
| Альтернативный провайдер (fail-over) | Не закладывается; точка расширения — один объект source-spec в `applyBaseLayer()` |
|
||||
|
||||
## 7. Сборка и деплой
|
||||
|
||||
- **Pipeline:** существующий Gitea Actions без изменений (`make lint`
|
||||
+ `make test` + `make build`). ESLint автоматически покрывает
|
||||
правки в `app.js`. Бэкенд-тесты (`pytest`) ET-007 не затрагивает.
|
||||
- **Артефакт:** статические ассеты фронтенда (`src/web/`). Никаких
|
||||
новых файлов — модифицируются существующие.
|
||||
- **Деплой:** стандартный — `make deploy-test` →
|
||||
`docker compose up -d` на mva154. Время простоя: 0 (только
|
||||
перевыкладка статики).
|
||||
- **Smoke-проверка после деплоя** на
|
||||
`https://openclaw.mva154.duckdns.org/enduro/`:
|
||||
1. Открыть карту, открыть попап «Рельеф».
|
||||
2. Убедиться, что виден переключатель «Подложка [Схема][Спутник]».
|
||||
3. Переключить на «Спутник» — увидеть растровые снимки и атрибуцию
|
||||
Esri в правом нижнем углу.
|
||||
4. Перезагрузить страницу — режим «Спутник» сохранён.
|
||||
5. Переключить тёмную/светлую тему — режим «Спутник» сохранён,
|
||||
слои не исчезли.
|
||||
|
||||
## 8. Rollback
|
||||
|
||||
- **План отката:** обратный коммит (revert) и повторный
|
||||
`docker compose up -d`. Времени отката ≈ 1–2 минуты (пересборка
|
||||
Docker-образа со статикой).
|
||||
- **Серверного состояния / миграций / графов**, которые требуется
|
||||
отдельно откатывать, нет.
|
||||
- **Сохранившиеся `localStorage`-значения у пользователей.** После
|
||||
отката ключ `map-base-layer` остаётся в `localStorage`, но
|
||||
игнорируется старым кодом — безвреден. Принудительная очистка не
|
||||
требуется.
|
||||
|
||||
## 9. Ресурсы (CPU / RAM / диск)
|
||||
|
||||
- **Сервер mva154:** воздействие отсутствует. Спутниковые тайлы идут
|
||||
напрямую от Esri к браузеру; mva154 не проксирует, не кэширует, не
|
||||
логирует их.
|
||||
- **Клиент-браузер:** при активном «Спутник» — дополнительные
|
||||
растровые загрузки 30–80 КБ × число видимых плиток (типично
|
||||
10–30 плиток на viewport). Это сопоставимо со стоимостью текущего
|
||||
OSM-слоя и не создаёт регрессий по памяти/CPU.
|
||||
|
||||
## 10. Наблюдаемость
|
||||
|
||||
- Новые серверные метрики, логи и алерты **не требуются**.
|
||||
- Поведение проверяется автотестами (UI/e2e) по плану
|
||||
`04-test-plan.yaml` и `04b-ui-test-cases.md`.
|
||||
- Серверные логи /enduro/ дополнений не получают — все обращения к
|
||||
Esri идут с браузера, минуя mva154.
|
||||
|
||||
## 11. Влияние на C4 / архитектурную документацию
|
||||
|
||||
Состав внутренних компонентов системы (Frontend, Backend, Tile
|
||||
Server, OSRM, БД) **не меняется**. Меняется только перечень внешних
|
||||
зависимостей в выполнении: добавляется Esri World Imagery как второй
|
||||
внешний raster-tile провайдер наряду с уже используемым
|
||||
tile.openstreetmap.org.
|
||||
|
||||
В репозитории нет файлов `c4-*.mmd` — описание архитектуры текстовое
|
||||
в `docs/architecture/README.md`. ET-007 обновляет этот документ:
|
||||
добавляется раздел/строка «Внешние тайл-провайдеры» со списком из двух
|
||||
провайдеров и условием активации каждого.
|
||||
|
||||
## 12. Вывод
|
||||
|
||||
Инфраструктурных, сетевых, конфигурационных, серверных и
|
||||
БД-изменений на стороне mva154 **нет**. Единственное архитектурное
|
||||
расширение — новая клиентская зависимость от внешнего raster-tile
|
||||
провайдера (Esri World Imagery), активируемая лениво и только при
|
||||
явном пользовательском выборе режима «Спутник». Деплой штатный,
|
||||
эскалация `arch:major-change` не требуется.
|
||||
135
docs/work-items/ET-007/08-data-requirements.md
Normal file
135
docs/work-items/ET-007/08-data-requirements.md
Normal file
@@ -0,0 +1,135 @@
|
||||
---
|
||||
type: data-requirements
|
||||
work_item_id: ET-007
|
||||
title: "Требования к данным — ET-007: Спутниковая карта (Схема / Спутник)"
|
||||
version: 1
|
||||
status: approved
|
||||
created_at: 2026-05-31
|
||||
authors:
|
||||
- "agent:architect"
|
||||
---
|
||||
|
||||
# Требования к данным — ET-007
|
||||
|
||||
## 1. Резюме
|
||||
|
||||
ET-007 не вводит и не изменяет ни одной серверной структуры данных.
|
||||
Единственные «данные» фичи на стороне приложения — пользовательский
|
||||
UI-выбор подложки в `localStorage`. На стороне внешнего источника —
|
||||
бесконтекстные растровые плитки PNG/JPEG, потребляемые браузером.
|
||||
|
||||
## 2. Серверные данные
|
||||
|
||||
| Аспект | Требование |
|
||||
|--------|------------|
|
||||
| Изменения схемы SQLite / Spatialite | Нет |
|
||||
| Новые таблицы / колонки / индексы | Нет |
|
||||
| Миграции (`migrations/`) | Нет |
|
||||
| Изменения контракта API `/api/*` | Нет |
|
||||
| Серверное логирование выбора подложки | Нет — выбор остаётся в браузере |
|
||||
|
||||
## 3. Внешние входные данные (спутниковые тайлы)
|
||||
|
||||
| Параметр | Значение |
|
||||
|----------|----------|
|
||||
| Источник | Esri World Imagery (см. ADR-004 §1) |
|
||||
| URL-шаблон | `https://server.arcgisonline.com/ArcGIS/rest/services/World_Imagery/MapServer/tile/{z}/{y}/{x}` |
|
||||
| Протокол | HTTPS, без авторизации |
|
||||
| Формат | растровый PNG / JPEG, 256 × 256 px |
|
||||
| Размер плитки | ≈ 30–80 КБ |
|
||||
| Диапазон z | 0 … 19 |
|
||||
| Привязка | Web Mercator (EPSG:3857) — совместима с MapLibre по умолчанию |
|
||||
| Атрибуция (обязательна) | `"Source: Esri, Maxar, Earthstar Geographics, and the GIS User Community"` |
|
||||
| Содержимое запроса | `{z}`, `{y}`, `{x}` — обезличенные координаты тайла; больше ничего не передаётся |
|
||||
| Cookies / заголовки авторизации | Не отправляются |
|
||||
|
||||
Изменение MapLibre source при будущей смене провайдера локализовано
|
||||
одним объектом source-spec в `applyBaseLayer()` — это единственная
|
||||
точка системы, знающая URL Esri (см. ADR-004 §1 «точка расширения»).
|
||||
|
||||
## 4. Клиентское хранилище
|
||||
|
||||
| Параметр | Значение |
|
||||
|----------|----------|
|
||||
| Механизм | `localStorage` |
|
||||
| Ключ | `map-base-layer` |
|
||||
| Допустимые значения | `"schematic"` \| `"satellite"` |
|
||||
| Значение по умолчанию | `"schematic"` (при отсутствии ключа или некорректном значении) |
|
||||
| Объём полезной нагрузки | ≤ 16 байт на браузер |
|
||||
| Запись | в `onBaseLayerToggle(base)` при изменении выбора |
|
||||
| Чтение | в `restoreBaseLayerState()` — при старте приложения и в каждом вызове `rebuildMapOverlays()` (после `map.setStyle()`) |
|
||||
| Миграция со старых значений | Не требуется — ключ новый, конфликта нет |
|
||||
|
||||
Имя ключа `map-base-layer` соответствует сложившейся в проекте
|
||||
конвенции UI-настроек в `localStorage` (`enduro-theme-mode`,
|
||||
`distance_unit`, `terrain-*`, `trails-*`, `poi-visible`,
|
||||
`MARKERS_KEY`). Префиксации проектом не предусмотрено.
|
||||
|
||||
## 5. Внутреннее состояние модуля
|
||||
|
||||
Дополнительные неперсистентные данные, удерживаемые в памяти браузера
|
||||
в течение сессии:
|
||||
|
||||
| Поле | Тип | Назначение |
|
||||
|------|-----|------------|
|
||||
| текущий базовый слой | `'schematic' \| 'satellite'` | проекция `localStorage['map-base-layer']` |
|
||||
| baseline-значения paint POI (text-halo, circle-stroke) | объекты per-layer | референсы для возврата с «Спутник» на «Схему» |
|
||||
| baseline-значения `background-color` для тёмной/светлой темы | две строковые константы | `#f0ede6` (light), `#1a1a1a` (dark) — задублированы из `style*.json`, см. ADR-004 §6 |
|
||||
| флаг «satellite source уже добавлен в стиль» | bool | оптимизация: при повторном входе в «Спутник» в той же сессии стиля не добавляем повторно |
|
||||
|
||||
baseline POI-значения и `background-color` — единственные
|
||||
**задублированные** значения между `style*.json` и `app.js`. Их
|
||||
рассинхрон ловится UI-тестами AC-04 и AC-06.
|
||||
|
||||
## 6. Halo-слои в `style.json`
|
||||
|
||||
В обоих `src/web/style.json` и `src/web/style-dark.json` добавляются
|
||||
парные «underlay»-слои halo для линий грунтовок/троп, например:
|
||||
|
||||
| Базовый слой | Halo-слой | Назначение |
|
||||
|--------------|-----------|------------|
|
||||
| `trails-grade1` | `trails-grade1-halo-satellite` | широкая полупрозрачная белая обводка под основной линией |
|
||||
| `trails-grade2` | `trails-grade2-halo-satellite` | то же |
|
||||
| ... | ... | для каждой grade и для paths/bridleway |
|
||||
| `paths-bridleway` | `paths-bridleway-halo-satellite` | то же |
|
||||
|
||||
Параметры halo-слоёв (ширина, цвет, opacity) — на этапе разработки;
|
||||
дизайн уточняется визуальной проверкой на тёмных снимках. У всех
|
||||
halo-слоёв `layout.visibility = "none"` по умолчанию; включаются в
|
||||
`applyBaseLayer('satellite')` через `setLayoutProperty`. Точные
|
||||
численные значения halo — данные дизайна, не данные домена; их
|
||||
изменение не требует миграции пользовательского состояния.
|
||||
|
||||
## 7. Персональные данные
|
||||
|
||||
| Канал | PII |
|
||||
|-------|-----|
|
||||
| `localStorage['map-base-layer']` | нет (обезличенный UI-флаг) |
|
||||
| Запросы к `tile.openstreetmap.org` (уже существуют) | IP пользователя становится виден OSM при использовании «Схемы» |
|
||||
| Запросы к `server.arcgisonline.com` (новые) | IP пользователя становится виден Esri **только** при активном режиме «Спутник» (лениво — см. ADR-004 §3) |
|
||||
| Передача координат поездок / маршрутов на сторонние сервисы | Нет — координаты в URL не передаются, передаётся только `{z}/{y}/{x}` тайл-сетки |
|
||||
|
||||
Это **не регрессия** относительно текущего состояния (OSM-tile
|
||||
уже работает на тех же условиях), но — расширение списка третьих
|
||||
сторон, к которым обращается клиент. Пользователи, никогда не
|
||||
включающие «Спутник», ни одного запроса в Esri не отправляют — это
|
||||
прямое следствие ленивого создания source (ADR-004 §3). См. также
|
||||
`10-tech-risks.md`, R-3.
|
||||
|
||||
Серверных обязательств по хранению / удержанию / удалению PII
|
||||
ET-007 **не порождает** — на mva154 никаких новых данных не оседает.
|
||||
|
||||
## 8. Резервное копирование и ретенция
|
||||
|
||||
Не применимо — серверных данных у ET-007 нет. Клиентский
|
||||
`localStorage['map-base-layer']` не подлежит резервному копированию
|
||||
(пользовательская UI-настройка, утрата которой безболезненна).
|
||||
|
||||
## 9. Вывод
|
||||
|
||||
Серверная модель данных, схемы и контракты API ET-007 **не
|
||||
затрагивает**. Единственное персистентное данное — обезличенный
|
||||
клиентский флаг `localStorage['map-base-layer']` (≤ 16 байт).
|
||||
Внешний источник предоставляет публичные растровые тайлы; никакие
|
||||
данные пользователя в запросах к нему не передаются помимо штатной
|
||||
для HTTP-клиента информации (IP, User-Agent).
|
||||
200
docs/work-items/ET-007/10-tech-risks.md
Normal file
200
docs/work-items/ET-007/10-tech-risks.md
Normal 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 30–80 КБ из Esri CDN на канале
|
||||
≥ 5 Мбит/с укладывается в 200–300 мс на тайл (по практике
|
||||
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`
|
||||
или возврат в Анализ не требуются.
|
||||
Reference in New Issue
Block a user