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>
171 lines
12 KiB
Markdown
171 lines
12 KiB
Markdown
---
|
||
type: data-requirements
|
||
work_item_id: ET-007
|
||
title: "Требования к данным — ET-007: Спутниковая карта (Схема / Спутник)"
|
||
version: 2
|
||
status: approved
|
||
created_at: 2026-05-31
|
||
changelog:
|
||
- "v2 (2026-05-31): code-review fixes (12-review.md P1-1, P1-2, P1-4) — реальные id halo-слоёв (trails-track/path-bridleway), полная таблица baseline POI per-theme, satellite-bg как единая константа #2a2a2a, исправление dark baseline #1a1a1a→#1a1a2e, добавлено поле _savedBasemapState."
|
||
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 (см. таблицу ниже) | константы per-theme | референсы для возврата с «Спутник» на «Схему» |
|
||
| baseline-значения `background-color` для тёмной/светлой темы | две строковые константы | `#f0ede6` (light), `#1a1a2e` (dark) — задублированы из `style.json:28` и `style-dark.json:28`, см. ADR-004 §6 |
|
||
| satellite-константа `background-color` | одна строковая константа | `#2a2a2a` для обеих тем (ADR-004 §6) |
|
||
| `_savedBasemapState` | `boolean \| null` | сохранённое значение `layerState.basemap` на время активного «Спутник»; восстанавливается при возврате на «Схему» (TRZ §5.6, P1-5) |
|
||
| флаг «satellite source уже добавлен в стиль» | bool | оптимизация: при повторном входе в «Спутник» в той же сессии стиля не добавляем повторно |
|
||
|
||
### 5.1 Baseline paint-значений POI на «Схеме» (источник истины)
|
||
|
||
| Свойство | Light (`style.json:128–163`) | Dark (`style-dark.json:128–163`) |
|
||
|----------|------------------------------|----------------------------------|
|
||
| `poi-circles` `circle-stroke-color` | `#ffffff` | `#333333` |
|
||
| `poi-circles` `circle-stroke-width` | `1.5` | `1.5` |
|
||
| `poi-labels` `text-color` | `#333333` | `#e0e0e0` |
|
||
| `poi-labels` `text-halo-color` | `#ffffff` | `#1a1a2e` |
|
||
| `poi-labels` `text-halo-width` | `1.5` | `2` |
|
||
|
||
### 5.2 Значения POI в режиме «Спутник» (общие для обеих тем)
|
||
|
||
| Свойство | Satellite |
|
||
|----------|-----------|
|
||
| `poi-circles` `circle-stroke-color` | `#ffffff` |
|
||
| `poi-circles` `circle-stroke-width` | `2` |
|
||
| `poi-labels` `text-color` | `#ffffff` |
|
||
| `poi-labels` `text-halo-color` | `#000000` |
|
||
| `poi-labels` `text-halo-width` | `2` |
|
||
|
||
Менять обе пары (`text-color` + `text-halo-*`) обязательно: без правки
|
||
`text-color` тёмный baseline-текст светлой темы (`#333333`) поверх
|
||
чёрного halo не читается (см. 12-review.md P1-2).
|
||
|
||
baseline POI-значения, `background-color` light/dark и satellite-
|
||
константа фона — **единственные** задублированные значения между
|
||
`style*.json` и `app.js`. Их рассинхрон ловится UI-тестами AC-04 (POI
|
||
видимость на спутнике) и AC-06 (смена темы при активном «Спутник»).
|
||
|
||
## 6. Halo-слои в `style.json`
|
||
|
||
В обоих `src/web/style.json` и `src/web/style-dark.json` уже
|
||
присутствуют парные «underlay»-слои halo для линий грунтовок и троп
|
||
(см. `style.json:56–70`, `93–107`):
|
||
|
||
| Базовый слой | Halo-слой | Фильтр базового слоя | Назначение |
|
||
|--------------|-----------|----------------------|------------|
|
||
| `trails-track` | `trails-track-halo-satellite` | `highway == 'track'` (grade1..5 различаются `match`-выражением внутри `line-color`) | широкая полупрозрачная белая обводка под основной линией |
|
||
| `trails-path-bridleway` | `trails-path-bridleway-halo-satellite` | `highway in path/bridleway/footway` | то же |
|
||
|
||
Слоёв на каждую grade (`trails-grade1..5-halo-satellite`) **нет** и
|
||
заводить не планируется: дифференциация grade зашита в один
|
||
`match`-expression по `tracktype` внутри `trails-track`, а halo на
|
||
спутнике достаточно единого цвета/ширины поверх всего трека (под halo
|
||
ляжет цветная линия `trails-track`, разделение halo по grade
|
||
визуально не различимо). Аналогично для троп — единый
|
||
`trails-path-bridleway-halo-satellite` покрывает всю группу
|
||
`path/bridleway/footway`. Слой `trails-asphalt` halo не получает: по
|
||
умолчанию `visibility: none` + `line-opacity: 0`.
|
||
|
||
Параметры halo-слоёв (ширина, цвет, opacity) уже зафиксированы в
|
||
коде; будущие правки — данные дизайна, не данные домена; их изменение
|
||
не требует миграции пользовательского состояния.
|
||
|
||
## 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).
|