diff --git a/docs/21_MISSION_CORE_MAP_PAGE_INTEGRATION_PLAN.md b/docs/21_MISSION_CORE_MAP_PAGE_INTEGRATION_PLAN.md new file mode 100644 index 0000000..fb0114b --- /dev/null +++ b/docs/21_MISSION_CORE_MAP_PAGE_INTEGRATION_PLAN.md @@ -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.