docs(map): define Cesium integration plan
This commit is contained in:
@@ -0,0 +1,350 @@
|
|||||||
|
# Mission Core Map Page + Cesium integration plan
|
||||||
|
|
||||||
|
Status: proposed for product-owner acceptance, 2026-07-29
|
||||||
|
|
||||||
|
## Objective
|
||||||
|
|
||||||
|
Replace the schematic `Control → Map` placeholder with one production map-first
|
||||||
|
workspace that reuses the canonical NODE.DC Map Page contract, the shared
|
||||||
|
Platform Map Gateway and its NAS TileCache.
|
||||||
|
|
||||||
|
The first delivery proves an operational base map in online, degraded and
|
||||||
|
cache-only conditions. It does not introduce a new product root, copy Engine
|
||||||
|
workflow UI, ship fake subjects or grant command authority.
|
||||||
|
|
||||||
|
## Sources of truth
|
||||||
|
|
||||||
|
- NODE.DC Design Guideline `Map Page 0.1.0`;
|
||||||
|
- `@nodedc/page-patterns` and canonical UI package exports;
|
||||||
|
- `docs/MAP_TEMPLATE.md`;
|
||||||
|
- `docs/FOUNDRY_MAP_CESIUM_CANON.md`;
|
||||||
|
- the read-only Foundry Page Library and inspected editable Map application
|
||||||
|
manifests;
|
||||||
|
- Mission Core product UI, component architecture and surface-extension
|
||||||
|
canons.
|
||||||
|
|
||||||
|
Foundry application source is not a dependency. A reusable runtime component
|
||||||
|
must be published through a reviewed package boundary before Mission Core
|
||||||
|
consumes it.
|
||||||
|
|
||||||
|
## Product-surface decision
|
||||||
|
|
||||||
|
### Operator and job
|
||||||
|
|
||||||
|
A field operator opens `Control → Map` before or during a mission to understand
|
||||||
|
the scanner, mission geometry and selected operational subjects relative to
|
||||||
|
real geography, terrain and buildings. The same workspace must remain useful
|
||||||
|
when provider egress is unavailable but the shared NAS cache is reachable.
|
||||||
|
|
||||||
|
### Primary entity and lifecycle
|
||||||
|
|
||||||
|
The primary entity is a versioned Map view:
|
||||||
|
|
||||||
|
- provider-neutral camera and visual settings;
|
||||||
|
- base-layer visibility and provider readiness;
|
||||||
|
- cache intent;
|
||||||
|
- real geodetic subjects and selection;
|
||||||
|
- persisted Inspector state.
|
||||||
|
|
||||||
|
Cesium viewer instances, provider URLs, credentials and cache files are
|
||||||
|
runtime implementation details and are not product identities.
|
||||||
|
|
||||||
|
### Selected placement
|
||||||
|
|
||||||
|
Keep the existing `world-map` workspace under the current Control/Observation
|
||||||
|
root. Replace only its fake composition with a full map-first stage.
|
||||||
|
|
||||||
|
Rejected alternatives:
|
||||||
|
|
||||||
|
- a new product root: the operator job already belongs to Control and has one
|
||||||
|
admitted workspace;
|
||||||
|
- a modal or floating map: the map is the primary task, not auxiliary content;
|
||||||
|
- a Foundry iframe: it duplicates shell/navigation, breaks same-origin product
|
||||||
|
ownership and couples Mission Core to Foundry session state;
|
||||||
|
- reuse of the current generic `MapWorkspace` branch for both `world-map` and
|
||||||
|
`Missions → Routes`: the two workspaces have different lifecycle and
|
||||||
|
authority, so the mission-route editor remains separate.
|
||||||
|
|
||||||
|
This is novelty class A for the existing workspace composition, plus a shared
|
||||||
|
runtime-package admission gate for the generic Cesium adapter.
|
||||||
|
|
||||||
|
## Resulting composition
|
||||||
|
|
||||||
|
The default `Control → Map` surface is the map. Remove from this workspace:
|
||||||
|
|
||||||
|
- the schematic SVG route and contour drawing;
|
||||||
|
- the static right-side `Рабочая композиция` card;
|
||||||
|
- the product-facing feature inventory and `Картографический модуль` roadmap
|
||||||
|
copy;
|
||||||
|
- all fake routes, targets, geozones, heights and readiness statuses.
|
||||||
|
|
||||||
|
Retain canonical Map Page interactions:
|
||||||
|
|
||||||
|
- draggable Map Inspector;
|
||||||
|
- compact Layers overlay;
|
||||||
|
- central Map Toolbar;
|
||||||
|
- map expand/restore behavior owned by the existing workspace shell;
|
||||||
|
- provider-neutral selection and elevated target presentation when real data
|
||||||
|
exists.
|
||||||
|
|
||||||
|
The Layers overlay contains only imagery, terrain, 3D buildings, grid and
|
||||||
|
TileCache health in the first slice. Engine/Data Product layer menus are not
|
||||||
|
copied. Future Mission Core layers appear only after a real typed binding
|
||||||
|
exists.
|
||||||
|
|
||||||
|
## Settings retained from Foundry
|
||||||
|
|
||||||
|
The Inspector keeps:
|
||||||
|
|
||||||
|
1. Underlay and terrain.
|
||||||
|
2. Atmosphere and lighting.
|
||||||
|
3. 3D buildings.
|
||||||
|
4. Mission Core target presentation.
|
||||||
|
5. Grid and LOD.
|
||||||
|
6. Camera animation.
|
||||||
|
7. TileCache intent and safe health.
|
||||||
|
8. Selected entity details when a real selection exists.
|
||||||
|
|
||||||
|
Do not copy:
|
||||||
|
|
||||||
|
- `Классы состояния`;
|
||||||
|
- `HGeoZone`;
|
||||||
|
- `Метро`;
|
||||||
|
- `Вокзалы`;
|
||||||
|
- `Станции РЖД`;
|
||||||
|
- Foundry fleet bindings, provider-specific subjects or Engine execution
|
||||||
|
controls.
|
||||||
|
|
||||||
|
Canonical controls are `Inspector`, `ControlRow`, `InspectorSelectField`,
|
||||||
|
`Checker`, `RangeControl`, `ColorField`, `IconButton`, `Icon`,
|
||||||
|
`MapGlassSurface`, `Toolbar` and `WorkspaceWindow`. Mission Core does not
|
||||||
|
reimplement their geometry or interaction states.
|
||||||
|
|
||||||
|
## Runtime and dependency boundaries
|
||||||
|
|
||||||
|
```text
|
||||||
|
Mission Core browser on :8000
|
||||||
|
│ same-origin /api/v1/map/*
|
||||||
|
▼
|
||||||
|
Mission Core Map BFF
|
||||||
|
│ server-configured internal Gateway route
|
||||||
|
│ trusted server-side subject, no provider credential
|
||||||
|
▼
|
||||||
|
Shared Platform Map Gateway
|
||||||
|
├─ warm hit → shared NAS live TileCache
|
||||||
|
└─ cold miss / explicit refresh → approved platform egress → provider
|
||||||
|
```
|
||||||
|
|
||||||
|
The browser never connects directly to Cesium, Map Gateway, AMD Proxy or a NAS
|
||||||
|
address. The Gateway address is server configuration and is never hard-coded in
|
||||||
|
the frontend, map layout or router settings.
|
||||||
|
|
||||||
|
Mission Core reuses the existing shared cache. It must not create a local
|
||||||
|
browser cache, per-application TileCache, Docker volume or a second Gateway.
|
||||||
|
|
||||||
|
### Shared renderer gate
|
||||||
|
|
||||||
|
`@nodedc/page-patterns` already publishes the runtime-neutral Map Page
|
||||||
|
definition, but the Cesium adapter is not a published package. Production reuse
|
||||||
|
requires a shared reviewed package for:
|
||||||
|
|
||||||
|
- provider startup and independent imagery/terrain/buildings readiness;
|
||||||
|
- Gateway-proxied Cesium resource creation;
|
||||||
|
- render-loop recovery;
|
||||||
|
- provider-neutral scene/selection adapters;
|
||||||
|
- elevated target and label presentation;
|
||||||
|
- camera and cache-intent application.
|
||||||
|
|
||||||
|
Foundry and Mission Core must consume the same package revision. Copying the
|
||||||
|
Foundry application renderer into Mission Core is rejected. Cesium remains a
|
||||||
|
lazy chunk loaded only when the map workspace opens.
|
||||||
|
|
||||||
|
## Credential and control-plane decision
|
||||||
|
|
||||||
|
Mission Core does not need to receive a Cesium token to render the map. The
|
||||||
|
existing platform token remains owned by Platform Map Gateway, and Mission Core
|
||||||
|
uses it only after Gateway reports a configured/verified state. The current
|
||||||
|
network check did not independently verify that state.
|
||||||
|
|
||||||
|
The proposed `API и ключи` settings section is a write-only Platform
|
||||||
|
control-plane client:
|
||||||
|
|
||||||
|
1. The input is a password field, exists only in transient form state and is
|
||||||
|
cleared immediately after submit or cancel.
|
||||||
|
2. Browser submits the candidate through a same-origin authenticated request.
|
||||||
|
3. Mission Core revalidates an explicit admin authority.
|
||||||
|
4. The backend forwards the candidate through the canonical signed Gateway
|
||||||
|
admin route.
|
||||||
|
5. Gateway verifies assets `1`, `2` and `96188` before atomic replacement.
|
||||||
|
6. The response contains only `configured`, verification state, update time and
|
||||||
|
actor; the token is never returned.
|
||||||
|
7. A failed candidate preserves the previous working token.
|
||||||
|
|
||||||
|
The token is not stored in Mission Core environment settings, `.env`, browser
|
||||||
|
storage, logs, Git or Ops. The authoritative private file remains owned by
|
||||||
|
Platform Map Gateway.
|
||||||
|
|
||||||
|
Mission Core currently has no Launcher/Authentik role boundary. Therefore the
|
||||||
|
token-entry mutation is blocked until an authenticated admin control plane is
|
||||||
|
present. A hidden local button or loopback-only server is not sufficient
|
||||||
|
production authorization. Data-plane map work can proceed independently once
|
||||||
|
the existing Gateway is reachable and reports a configured state.
|
||||||
|
|
||||||
|
## Map state contract
|
||||||
|
|
||||||
|
Add a versioned Mission Core map document outside operator environment media,
|
||||||
|
for example `missioncore.map-view/v1`, with optimistic revision:
|
||||||
|
|
||||||
|
- camera: longitude, latitude, height, heading, pitch and roll;
|
||||||
|
- provider-neutral visual settings compatible with Map Page;
|
||||||
|
- map height;
|
||||||
|
- `inspectorOpenSections`;
|
||||||
|
- cache intent (`enabled`, `noOverwrite`), never server-level cache mode;
|
||||||
|
- selected stable subject id, or `null`;
|
||||||
|
- layer visibility;
|
||||||
|
- no credentials, upstream URLs, cache objects or transient Cesium ids.
|
||||||
|
|
||||||
|
Resolution order:
|
||||||
|
|
||||||
|
```text
|
||||||
|
canonical Map Page defaults
|
||||||
|
→ Mission Core persisted map view
|
||||||
|
→ transient operator changes
|
||||||
|
→ bounded runtime-only recovery overrides
|
||||||
|
```
|
||||||
|
|
||||||
|
Provider root failures are independent. Imagery failure must not blank terrain;
|
||||||
|
buildings failure must not stop the rest of the scene.
|
||||||
|
|
||||||
|
## Target and selection contract
|
||||||
|
|
||||||
|
The renderer supports canonical `elevated-spike` targets and
|
||||||
|
`map.moving_object` / `map.place_target` semantics from the start, but the
|
||||||
|
product renders no target without real geodetic evidence.
|
||||||
|
|
||||||
|
The current K1 acquisition contract exposes local `map_enu` trajectory and
|
||||||
|
`gnss_mode=none`; it does not expose a proved longitude/latitude/altitude
|
||||||
|
anchor. Local scan coordinates must not be plotted as world coordinates.
|
||||||
|
|
||||||
|
A real Mission Core map subject requires:
|
||||||
|
|
||||||
|
- stable `sourceId`;
|
||||||
|
- semantic type;
|
||||||
|
- longitude and latitude;
|
||||||
|
- optional altitude with an explicit height datum;
|
||||||
|
- observed/received timestamps;
|
||||||
|
- availability and motion states derived from real contracts;
|
||||||
|
- optional heading and trace;
|
||||||
|
- provenance linking the position to a session/device/mission.
|
||||||
|
|
||||||
|
Until that contract exists, the basemap remains valid with an honest empty
|
||||||
|
subject state and the selected-entity section remains absent.
|
||||||
|
|
||||||
|
## State grammar
|
||||||
|
|
||||||
|
The UI must distinguish:
|
||||||
|
|
||||||
|
- `loading`: runtime config and providers are being prepared;
|
||||||
|
- `ready`: selected providers are available;
|
||||||
|
- `degraded`: one or more providers failed while the scene remains useful;
|
||||||
|
- `empty`: basemap works but no real Mission Core subjects are bound;
|
||||||
|
- `offline-cache`: Gateway is reachable and the requested objects are served
|
||||||
|
without egress;
|
||||||
|
- `cache-miss`: requested offline object is absent;
|
||||||
|
- `gateway-unavailable`: Mission Core cannot reach the shared Gateway;
|
||||||
|
- `render-error`: browser/GPU/Cesium failure after one bounded recovery;
|
||||||
|
- `stale-health`: last-known-good cache statistics retained after a failed
|
||||||
|
poll.
|
||||||
|
|
||||||
|
Safe error codes remain visible to diagnostics. The UI must not collapse all
|
||||||
|
layers into a generic `502`, erase last-known-good cache state or perform
|
||||||
|
unbounded reconnect loops.
|
||||||
|
|
||||||
|
## Implementation slices
|
||||||
|
|
||||||
|
### M0 — shared contract and reachability gate
|
||||||
|
|
||||||
|
- approve the shared Cesium adapter package boundary;
|
||||||
|
- pin `Map Page 0.1.0`, Cesium `1.143.0` and Gateway route contracts;
|
||||||
|
- configure the Mission Core backend Gateway endpoint without hard-coded LAN
|
||||||
|
addresses;
|
||||||
|
- define a reviewed server-owned subject policy for the loopback-only
|
||||||
|
single-operator contour; require Launcher/Authentik identity before any
|
||||||
|
non-loopback or multi-user deployment;
|
||||||
|
- prove safe runtime-config and health reads from the intended field LAN;
|
||||||
|
- add credential-leak and route-allowlist tests.
|
||||||
|
|
||||||
|
### M1 — Mission Core Map BFF
|
||||||
|
|
||||||
|
- add bounded streaming GET/HEAD proxy routes for runtime config, asset
|
||||||
|
endpoints, cache resources and safe health;
|
||||||
|
- preserve Range, ETag, conditional headers, content type, abort and body
|
||||||
|
progress semantics;
|
||||||
|
- reject arbitrary target URLs and browser-supplied trusted identity;
|
||||||
|
- implement independent timeouts and safe error mapping;
|
||||||
|
- do not implement token rotation yet.
|
||||||
|
|
||||||
|
### M2 — real map-first workspace
|
||||||
|
|
||||||
|
- add isolated `core/map`, `components/map`, `workspaces/map` and
|
||||||
|
`styles/map.css` modules;
|
||||||
|
- consume `@nodedc/page-patterns`;
|
||||||
|
- lazy-load the shared Cesium adapter;
|
||||||
|
- replace the fake `world-map` branch only;
|
||||||
|
- remove the old map placeholder CSS from generic `workspaces.css`;
|
||||||
|
- keep `Missions → Routes` outside this change.
|
||||||
|
|
||||||
|
### M3 — Inspector, Layers and persisted view
|
||||||
|
|
||||||
|
- connect canonical Inspector controls to the versioned map view;
|
||||||
|
- add base provider visibility/readiness and cache health to Layers;
|
||||||
|
- persist camera, settings, cache intent and Inspector sections;
|
||||||
|
- implement bounded renderer recreation for explicit viewport refresh;
|
||||||
|
- keep provider credits available for any non-sandbox release.
|
||||||
|
|
||||||
|
### M4 — secure API/key control plane
|
||||||
|
|
||||||
|
- add authenticated Mission Core admin authority;
|
||||||
|
- add `API и ключи` to the existing `FeatureSettingsWindow`;
|
||||||
|
- implement write-only candidate rotation through the canonical Gateway admin
|
||||||
|
route;
|
||||||
|
- prove no secret appears in API responses, bundle, storage, logs or tests.
|
||||||
|
|
||||||
|
### M5 — real Mission Core targets
|
||||||
|
|
||||||
|
- admit a geodetic position/mission-target contract;
|
||||||
|
- adapt real subjects to the shared target presentation;
|
||||||
|
- implement selection and selected-entity details;
|
||||||
|
- add traces/routes only when their coordinate frame and authority are proved.
|
||||||
|
|
||||||
|
### M6 — operational acceptance
|
||||||
|
|
||||||
|
- cold online viewport streams while the Gateway commits objects;
|
||||||
|
- repeated viewport increases cache hits without repeating egress for the same
|
||||||
|
keys;
|
||||||
|
- provider egress/VPN loss does not break a warm viewport;
|
||||||
|
- uncached offline area produces a precise cache-miss state;
|
||||||
|
- explicit refresh failure preserves the previous cached object;
|
||||||
|
- reload restores camera, layers and Inspector state;
|
||||||
|
- each provider can fail independently;
|
||||||
|
- no fake entities survive scene changes;
|
||||||
|
- keyboard, Escape, normal/expanded map and responsive behavior pass browser
|
||||||
|
QA;
|
||||||
|
- all heavy validation remains sequential on the 18 GB Mac and the canonical
|
||||||
|
service stays on port `8000`.
|
||||||
|
|
||||||
|
## Current blockers and evidence
|
||||||
|
|
||||||
|
1. The Cesium adapter is not currently available through a published shared
|
||||||
|
package; exact code reuse is blocked until that boundary exists.
|
||||||
|
2. Mission Core lacks authenticated admin authority, so platform token rotation
|
||||||
|
cannot be exposed safely yet.
|
||||||
|
3. K1 currently has no admitted geodetic anchor, so live scanner targets are a
|
||||||
|
later data-contract slice.
|
||||||
|
4. From the current Mac network, direct safe probes to the expected private
|
||||||
|
Synology Map Gateway/Platform/AMD health endpoints timed out. End-to-end
|
||||||
|
acceptance requires the intended LAN route; no address will be hard-coded to
|
||||||
|
hide this condition.
|
||||||
|
|
||||||
|
None of these blockers requires a new product window, Engine embedding,
|
||||||
|
Ontology mutation, fake target or duplicate TileCache.
|
||||||
Reference in New Issue
Block a user