NODEDC_PLATFORM/services/map-gateway/README.md

88 lines
8.1 KiB
Markdown
Raw 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.

# NODE.DC Map Gateway
`map-gateway` — единый платформенный boundary для map providers. Он не является частью Engine и не принадлежит отдельному Module Studio application.
## Что делает
- хранит master `CESIUM_ION_TOKEN` только в process environment;
- выдаёт браузеру только asset-scoped endpoint token для allowlisted ion assets;
- проксирует и кэширует tile/3D Tiles/terrain resources через `GET /api/map/cache?url=<https-url>`;
- может отдать перенесённый локальный Engine snapshot через `MAP_GATEWAY_LEGACY_CACHE_HOSTS`, но никогда не догружает для него cache miss из сети;
- работает с persistent volume, а не с Git или Docker image layer;
- при upstream outage отдаёт ранее сохранённый cache object; offline режим включается только для providers, явно разрешённых их лицензией;
- защищает proxy allowlist-ом upstream hosts, HTTPS-only правилом, лимитами размера и token-free cache key;
- ведёт лёгкий persistent cache index для LRU eviction и health/stats.
## API
```text
GET /healthz
GET /api/map/ion/assets/:assetId/endpoint
GET|HEAD /api/map/cache?url=<encoded-upstream-url>
```
`/api/map/ion/assets/:assetId/endpoint` разрешает только `CESIUM_ION_ASSET_ALLOWLIST`. Ответ содержит runtime asset token, а не master token. Browser использует endpoint вместе с Cesium `DefaultProxy`, направляющим resource requests в `/api/map/cache`.
Ion endpoint metadata также сохраняется в persistent volume с файловыми правами `0600`. Это нужно для cold start в offline: Cesium получает сохранённый asset URL и asset-scoped token, а proxy отвечает только из ранее записанного cache. В metadata никогда не записывается master token.
## Cache modes
- `readwrite` — свежий cache hit отдаётся сразу; stale object обновляется online; при upstream failure возвращается stale copy;
- `readonly` — использует cache, но не записывает новый;
- `offline` — никогда не идёт наружу; cache miss возвращает `504`.
`offline` дополнительно требует, чтобы hostname был явно указан в `MAP_GATEWAY_OFFLINE_PROVIDER_ALLOWLIST`. По умолчанию список пуст: Gateway не превращает Cesium ion или public OSM tile service в offline distribution. Это осознанная provider policy, а не техническая ошибка cache.
Range requests пока transparently проксируются и не записываются как partial cache object. Полные GET responses кэшируются. Это безопасная начальная граница для terrain/3D Tiles; отдельным следующим шагом добавляется range-aware chunk cache после замеров реальных GOS/3D Tiles assets.
## Persistent storage
Platform Compose использует два внешних named volume: mutable `nodedc-platform_map-live-tile-cache` монтируется в `/var/lib/nodedc-map-live-cache`, read-only snapshot `nodedc-platform_map-offline-snapshot` — в `/var/lib/nodedc-map-offline-snapshot`. Их содержимое намеренно исключено из Git. Внешний volume не удаляется через `docker compose down -v`; очистка требует явного `docker volume rm` при остановленном Gateway. При необходимости offline seed доставляется отдельным export/import artifact, а не коммитом runtime cache.
Кэш не способен создать участок карты, который никогда не был скачан. Для целевых офлайн-регионов нужен отдельный licensed dataset/provider и его `seed/prefetch` job: он заранее проходит разрешённые assets, zoom-диапазоны и географические области, записывает их в тот же persistent volume и формирует проверяемый export/import artifact. Эта задача не смешивается с runtime gateway и не помещает binary tiles в историю репозитория.
### Legacy Engine cache: локальный перенос без изменения Engine
В локальной Studio-песочнице существующий Engine cache можно скопировать в persistent volume как неизменяемый входной snapshot. Исходная директория Engine при этом только читается: import job не удаляет, не переименовывает и не изменяет ни одного её файла.
```bash
npm run audit:engine-cache -- /absolute/path/to/nodedc-data/api/cesium/manifest.json
```
Команда audit выдаёт агрегированный отчёт: hosts, число объектов, declared/on-disk размер и отсутствующие файлы. Сам перенос выполняется отдельно, после остановки gateway на время записи index:
```bash
npm run import:engine-cache -- /absolute/path/to/nodedc-data/api/cesium/manifest.json /persistent/map-tile-cache
```
По умолчанию действует режим `no-overwrite`: если объект уже присутствует в новом cache, он остаётся без изменений. `--dry-run` выводит план без копирования, `--refresh` разрешает осознанно заменить уже импортированный объект. Legacy `http` URLs нормализуются до `https`, чтобы совпасть с HTTPS-only Gateway; сами файлы, content-type, etag, timestamp и provenance сохраняются в новом index/import report.
Это sandbox-механизм переноса уже существующей локальной реализации. Для внешней коммерческой публикации потребуется отдельная provider/offline policy; она не блокирует текущую локальную миграцию, но и не должна смешиваться с ней. Runtime cache по-прежнему не попадает в Git или Docker image layer.
## Security and access
В local dev допускается `MAP_GATEWAY_ALLOW_ANONYMOUS=true`. В production он должен быть `false`; Caddy/Auth BFF проверяет Authentik session и передаёт очищенный trusted subject header в private platform network. Нельзя открывать gateway напрямую наружу и нельзя принимать user-provided upstream hosts вне allowlist.
## Required environment
```text
CESIUM_ION_TOKEN=
CESIUM_ION_ASSET_ALLOWLIST=1,96188
MAP_GATEWAY_UPSTREAM_ALLOWLIST=api.cesium.com,assets.ion.cesium.com,tile.openstreetmap.org
MAP_GATEWAY_LEGACY_CACHE_HOSTS=ecn.t0.tiles.virtualearth.net,ecn.t1.tiles.virtualearth.net,ecn.t2.tiles.virtualearth.net,ecn.t3.tiles.virtualearth.net
MAP_GATEWAY_OFFLINE_PROVIDER_ALLOWLIST=
MAP_CACHE_DIR=/var/lib/nodedc-map-cache
MAP_CACHE_MODE=readwrite
```
# Cache topology
`MAP_CACHE_DIR` is the mutable **live** cache. In the Platform compose profile it
is mounted as `map-live-tile-cache` and is the only store that can receive new
upstream objects.
`MAP_OFFLINE_SNAPSHOT_DIR` is optional and mounted read-only as
`map-offline-snapshot`. It is populated only by the controlled Engine cache
import. Requests marked with the `offline` cache profile are served exclusively
from this snapshot; a missing tile returns a cache miss and never reaches an
upstream provider.