All checks were successful
12-review.md (REQUEST_CHANGES, attempt 2/3) flagged 6 must-fix items
in the analysis/architecture artefacts plus matching bugs that had
already leaked into the committed implementation. This patch lands
both: documents corrected, code aligned with corrected specs, tests
updated.
P1-1: TRZ/ADR/Data/Risks referenced fictional layer ids
(`trails-grade1..5-halo-satellite`, `paths-bridleway-halo-satellite`).
Actual style*.json has only `trails-track-halo-satellite` and
`trails-path-bridleway-halo-satellite`; grade differentiation lives
inside one `match` expression on `tracktype` within `trails-track`.
Docs rewritten to operate on real ids.
P1-2: POI labels contrast was broken — spec changed only halo-color
to black, leaving `text-color: #333333` (light theme baseline)
unreadable over the new black halo. Code+docs now switch BOTH
`text-color` (-> `#ffffff` on satellite) AND halo together, with
per-theme baselines (`#333333` light / `#e0e0e0` dark) restored on
return to Schematic.
P1-3: BRD §5 hillshade risk said «hillshade auto-disabled on
satellite», contradicting TRZ/ADR/AC. BRD wording aligned: hillshade
keeps working over satellite; visual check is AC-04.
P1-4: background-color had four divergent sources (`#1a1a1a`,
`#2a2a2a`, `#1a1a2e`, `#f0ede6`), incl. an inverted-theme typo and a
baseline `#1a1a1a` that didn't match the actual `style-dark.json:28`
value `#1a1a2e`. Settled on ADR-004's single-constant model: `#2a2a2a`
on satellite for both themes; on Schematic restore per-theme baselines
`#f0ede6` (light) / `#1a1a2e` (dark). `_applyBackgroundForSatellite`
fixed accordingly.
P1-5: app.js already had `layerState.basemap` and `toggleLayer
('basemap')` (legacy «Базовая карта» switch). Neither TRZ nor ADR
specified the interaction. Added save&restore contract: on entering
Satellite save `layerState.basemap` to `_savedBasemapState` and
force-hide `osm-base`; on returning to Schematic restore osm-base
visibility from the saved value. CSS hook `body.satellite-active
#btn-basemap { display:none }` keeps the user from trying to enable
a hybrid mode (out of scope, BRD §3). TRZ §5.6, ADR-004 §8.
P1-6: `restoreTrailsState()` and `onTrailsCheckbox()` only managed
visibility of `trails-track` / `trails-path-bridleway`, leaving
their halo-underlay siblings as «phantom» halos when the user
unchecked grunты/тропы under Satellite. Introduced
`_applyTrailHaloVisibility(map, base)` reading checkbox state from
DOM; called from `onTrailsCheckbox`, `restoreTrailsState`, and both
branches of `applyBaseLayer`. Rule: halo visible ⇔ (base ===
satellite) AND (checkbox ON). TRZ §5.7, ADR-004 §9.
Docs bumped: BRD v2, TRZ v2, AC v2, Data v2, Risks v2; ADR-004
получает «Ревизии»-секцию (status remains accepted — only editorial
fixes, no decision change).
Tests:
- tests/unit/base_layer.test.js: rewritten 2 background-color
assertions (#1a1a1a expectation removed), added 6 new tests for
P1-2 / P1-4 (POI text-color per-theme baselines, single satellite
bg #2a2a2a, baseline restore on Schematic).
- All 33 JS unit tests + 22 pytest static checks green.
- Full pytest suite: 76 passed (excluding pre-existing
shapely-import skipped collection in tests/unit/test_health.py).
Refs: ET-007
Review: docs/work-items/ET-007/12-review.md (P1-1..P1-6)
ADR: docs/work-items/ET-007/06-adr/ADR-004-satellite-base-layer.md (rev. 2026-05-31)
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
16 KiB
16 KiB
type, work_item_id, title, version, status, created_at, changelog, authors
| type | work_item_id | title | version | status | created_at | changelog | authors | ||
|---|---|---|---|---|---|---|---|---|---|
| tech-risks | ET-007 | Технические риски — ET-007: Спутниковая карта (Схема / Спутник) | 2 | approved | 2026-05-31 |
|
|
Технические риски — ET-007
Технические риски этапа разработки. Бизнес-риски — в BRD §5 (пересечение есть, здесь акцент на техническую митигацию). Шкала: вероятность (Н/С/В) × влияние (Н/С/В).
R-1 — Дрейф halo-слоёв в style.json / style-dark.json
- Описание: ADR-004 §5 решает читаемость линий грунтовок и троп
на спутнике через парные «underlay»-слои с
visibility: noneв обоих файлах стилей. Реальные id (подтверждены кодомstyle.json:56–70,93–107иstyle-dark.json:56–70,93–107):trails-track-halo-satellite,trails-path-bridleway-halo-satellite. Любая будущая правка основных trails-слоёв (цвет, ширина, фильтр) требует согласованной правки halo-слоёв в обоих файлах. Без явной проверки легко забыть один из четырёх случаев (2 темы × 2 рода слоёв). - Вероятность / Влияние: С / Н.
- Митигация:
- При разработке завести единый список затрагиваемых пар в
applyBaseLayer(): массив пар[('trails-track', 'trails-track-halo-satellite'), ('trails-path-bridleway', 'trails-path-bridleway-halo-satellite')]. Производное правило «<base>-halo-satellite» допустимо, но только для этих двух base-id; массив['trails-grade1..5'](как в более раннем черновике, см. 12-review.md P1-1) не использовать — таких слоёв вstyle.jsonнет, дифференциация grade хранится внутри одногоmatch-выражения поtracktypeвtrails-track. - Code review-чеклист: при правке
trails-track,trails-path- bridlewayв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.
- Точка расширения локализована: единственный объект source-spec
в
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на единую satellite-константу#2a2a2a(обе темы) при включении «Спутник» и возвращать к исходному при возврате на «Схему». «Исходные» значения (#f0ede6для светлой,#1a1a2eдля тёмной — именно#1a1a2e, как вstyle-dark.json:28, а не#1a1a1aиз более раннего черновика, см. 12-review.md P1-4 / P2-3) дублируются в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 поверх спутника» отлавливает регрессию.
- ADR-004 §4 явно фиксирует:
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
или возврат в Анализ не требуются.