Files
enduro-trails/docs/work-items/ET-007/08-data-requirements.md
claude-bot 1984b0bde6
All checks were successful
CI / lint (push) Successful in 4s
CI / test (push) Successful in 6s
CI / lint (pull_request) Successful in 4s
CI / test (pull_request) Successful in 5s
CI / build (push) Successful in 4s
CI / build (pull_request) Successful in 2s
fix(ET-007): address 6 P1 findings from review (docs + code)
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>
2026-05-31 21:05:49 +00:00

171 lines
12 KiB
Markdown
Raw Permalink Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
---
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 |
| Размер плитки | ≈ 3080 КБ |
| Диапазон 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:128163`) | Dark (`style-dark.json:128163`) |
|----------|------------------------------|----------------------------------|
| `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:5670`, `93107`):
| Базовый слой | 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).