A dev web launch on a PC without Node.js - a fresh one, or another PC the dev
drive was plugged into - failed with nothing but "stopped while starting (exit
code: 1)": `cmd /c npm run dev` had no npm to run, so nothing said why.
New nodejs.rs finds the folder holding node.exe AND npm.cmd - this process's
PATH first, then %ProgramFiles%\nodejs, where the installer puts it (an
install adds itself to the SYSTEM PATH, which the running launcher never sees).
Launcher::ensure_node runs before a web run's build/start: with no Node.js it
logs why and runs `winget install --id OpenJS.NodeJS.LTS --exact --source
winget --accept-*-agreements` in its own console (progress, Windows' permission
prompt and any failure stay on screen), then judges by what is on disk - not
by winget's exit code, which is non-zero for "already installed" too. No Node
afterwards stops the launch with the manual step spelled out.
`npm run dev` (web_command) and `npm install` (install_web) now get that folder
first on their PATH, so the launch goes on straight after the install without
restarting the launcher. start_web keeps a guard with a real message.
Spot-check: `winget show --id OpenJS.NodeJS.LTS --exact --source winget` names
the nodejs.org x64 MSI; nodejs::tests cover PATH-first, the fresh-install
folder, npm-without-node, and the argument list.
Two reasons an offline dev run's web client had no map:
1. Vite proxied every tile to the public tile host. web_command now sets
ODIAN_TILE_SERVER_URL=http://127.0.0.1:18081 for the Vite it starts, and
ODIAN_Engine's _WEB/vite.config.ts sends /basemap, /mvt and /netlayer there:
the site while it answers, this PC's installed tiles when it does not - the
same path the .exe already draws from.
2. The power-grid netlayer had no source offline. datasets.json named every
PostGIS overlay but `powerv2_postgis`, so the tile server answered
/netlayer/<ds>/powerv2/* with 404 "powerv2_render_sqlite not found" while
postgis_power_entities / _links / _topology sat in the local snapshot. Added
to POSTGIS_SOURCES; the tile server resolves it through the same
ODIAN_TILE_POSTGIS_DSN as the others.
Spot-check: with the site unreachable, /netlayer/<ds>/powerv2/bbox/8/128/86/131/89.json
answers 200 (721064 B, the same body the site serves) and topology.bin 200.
A dev run's web client showed no live tracks while the .exe beside it did.
Root cause: the local API relays a request to the DHP only when it carries a
token that API minted itself (main.cpp's forwarder, the guard that keeps it
from being an open proxy). The .exe mints one with ODIAN_MINT_SECRET; the web
client was opened with ?user= only, so every /session/* call it made was
served from this PC's database.
The launcher now mints a token from this stack's API for the run's operator
(stack::mint_web_token) and opens the browser with it in the URL FRAGMENT
(StackConfig::web_url_signed). A fragment never reaches a request line or a
server log, and the launcher's own log still prints the tokenless address.
If the mint fails the web opens as before and the log says it shows this PC's
data only. Needs ODIAN_Engine's _WEB/src/auth.ts to read #token=.
Spot-check: launch dev mode with the web target while online; the API log
reads "now LIVE on the DHP" and the browser shows live tracks.
- Tauri 2 + Svelte 5 hub in ODIAN dark: patch notes and roadmap, install and
update progress, local stack status, settings with DHP and MCP addresses.
- crates/odian-packs: Rust installer for pack format v1 (signed manifests,
resumable verified downloads from a DHP or an ODIAN drive), byte-compatible
with ODIAN_MCP_Server's Python odian_packs.
- Local stack on 127.0.0.1: Postgres -> Engine API -> tile server -> Odian.exe,
one Job Object, clean shutdown; database snapshot restore on a fresh PC only.
- Keycloak sign-in through the DHP's MCP, remembered until Sign out with a
launcher session that renews the Engine token silently.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>