# Versions ## v1.8.4 (04-17-2026) - Fixed the post-`v1.7.0` route regression where some meshes stopped showing routes that previously rendered in `v1.6.6`. - Added `ROUTE_ALLOW_AMBIGUOUS_ONE_BYTE_FALLBACK` so operators can restore the legacy closest/time-based fallback for colliding 1-byte hop prefixes when conservative prefix handling is too strict for their network. - Kept conservative ambiguous 1-byte routing as the default, but made the legacy fallback opt-in for deployments that need the older route rendering behavior. - Passed `ROUTE_ALLOW_AMBIGUOUS_ONE_BYTE_FALLBACK` through `docker-compose.yaml` and documented the new routing toggle in the setup docs. - Added issue #55: LOS and Propagation panels can now be minimized on mobile without turning the tool off, making it easier to interact with the map while the tool stays active. - Extended the issue #55 minimize/expand control to History, Peers, and Route Details so side panels can be collapsed instead of closed with a separate `×` flow. - Added issue #56: the LOS elevation profile now renders upper and lower Fresnel-zone lines similar to the MeshCore app. - LOS profile hover now reports Fresnel radius along with terrain and LOS height, and Fresnel rendering stays segment-local for multi-pin LOS routes so chained paths do not get incorrect full-route curves. - Fixed the issue #55 panel-regression fallout so History sliders, Peers, Route Details clearing, LOS point selection, and Propagation opening continue to work correctly. ## v1.8.3 (04-16-2026) - Fixed issue #53: the LOS tool now accounts for Earth curvature instead of using a purely straight terrain-vs-line check. - Added LOS curvature controls `LOS_CURVATURE_ENABLED` and `LOS_CURVATURE_FACTOR`, both defaulting to enabled curvature with a `1.333333` effective Earth radius factor when unset. - Applied the same curvature math to both the frontend realtime LOS path and the backend `/los` fallback so live interaction and server responses stay consistent. - Updated the LOS profile and blockage calculation to use curvature-adjusted terrain samples, which can correctly mark longer paths as blocked where the old LOS tool showed clear. - Clarified MQTT broker authentication docs for `meshcore-mqtt-broker`: the map normally uses a broker `SUBSCRIBER_N` username/password pair instead of node-style signed publisher auth. ## v1.8.2 (04-07-2026) - Added issue #48: node popups now let users click the short key under the node name to copy the full public key without adding a duplicate full-key line to the popup body. - Added optional MeshCore-compatible contact QR generation for node popups via `QR_CODE_BUTTON_ENABLED=true`. - Changed the QR action to open an in-page modal instead of navigating to a separate browser tab, and made the modal follow the active light/dark map theme. - Tuned the QR modal and generator for better on-screen scanning by enlarging the modal presentation and reducing QR density to better match the official app export. - The QR modal now uses the node name as its title and shows a clickable truncated public key line that still copies the full key. - Added a local `/qr` PNG endpoint for popup QR generation and protected it with the existing prod token flow. - Fixed `docker-compose.yaml` so `QR_CODE_BUTTON_ENABLED` is passed into the container and the feature can actually be enabled from `.env`. - Improved MeshMapper coverage performance by caching the expanded rectangle set and only toggling visible squares on pan/zoom instead of rebuilding every rectangle each viewport change. - Fixed peer-history accounting so `/peers/{device_id}` still counts adjacent route hops from `point_ids` even when a route segment cannot be drawn because its coordinates are missing, zeroed, or otherwise filtered out. - Fixed stale-node cleanup so nodes that are still MQTT-online keep their last known map position instead of disappearing while `/status` or `/internal` presence is still active. ## v1.8.1 (04-06-2026) - Fixed issue #43: location updates now key devices from the advert owner pubkey only, avoiding bogus ghost nodes created from unrelated decoded `publicKey` fields. - Added a startup/state cleanup pass that removes exact same-name/same-location duplicate device entries so already-persisted ghost markers disappear after restart instead of lingering until TTL expiry. - Fixed issue #45: MeshMapper coverage now rebuilds the visible square set from cached source data on zoom and pan, so tiles no longer change incorrectly when the viewport scale changes. - Fixed issue #46: peer-list limits no longer use a hardcoded maximum, so `/peers/{device_id}?limit=` can request any positive count. - Added issue #44: upstream-style hidden arcade Pacman mode that animates a flow marker along live route direction and can be enabled with the Konami sequence or `/waka` in search. ## v1.8.0 (03-28-2026) - Switched the runtime decoder back to the official `@michaelhart/meshcore-decoder` package now that the published decoder supports multibyte path decoding needed by the map. - Added issue #41: the LOS tool now supports multiple chained pins so you can build a proposed relay path one segment at a time instead of being limited to a single two-point LOS check. - LOS elevation profile now spans the chained path instead of only the active two-point segment. - Removed the old `Keep A` LOS workflow and updated the LOS panel copy/labels to match chained pins instead of fixed A/B endpoints. - LOS height inputs are now stored per pin instead of as a single shared A/B pair, so changing segment heights no longer overwrites unrelated segments in a chained LOS path. - Simplified the LOS helper copy so the selected-segment height controls read more directly. - Added `Remove last pin` to the LOS tool so chained paths can be trimmed without clearing the whole route. - Fixed chained LOS recomputation when moving an intermediate pin so both adjacent segments are recalculated instead of leaving the earlier segment stale. - Added automatic runtime backups as timestamped `.tar.gz` archives. - MeshMapper coverage rendering now expands each returned square to match MeshMapper's displayed neighboring coverage fill, so the live map matches the MeshMapper site more closely instead of showing only the center square. - Softened the expanded MeshMapper coverage fill so the map keeps the fuller coverage footprint without the grid looking overly harsh. - Tuned MeshMapper coverage styling again with slightly brighter fill and subtle grid lines restored for readability. - Backups now collect existing live-state files such as `state.json`, `device_roles.json`, `device_coords.json`, `neighbor_overrides.json`, `channel_secrets.json`, `map_boundary.json`, `route_history.jsonl`, and `coverage_cache.json`. - Added new backup envs: `BACKUP_ENABLED`, `BACKUP_INTERVAL_SECONDS`, `BACKUP_DIR`, and `BACKUP_RETENTION_DAYS`. - Backup archives now default to `/backup` instead of `/data`, so live state and archives stay separate. - Backup interval now defaults to `43200` seconds (12 hours). - Added retention pruning for old backup archives based on `BACKUP_RETENTION_DAYS`. - Added `./backup:/backup` to `docker-compose.yaml` and ignored `/backup/` in git so local backup archives stay out of the repo. - Added backup tests covering archive creation and retention pruning. ## v1.7.8.1 (03-24-2026) - Fixed issue #38: the Peers tool `Clear peers` action now removes both incoming and outgoing lines even when the same peer appears in both directions. - Fixed a follow-on Peers tool bug where clearing peers could leave a stale in-flight lookup active, preventing a new node selection from taking over until the tool was reopened. - Made peer lines non-interactive so the Peers tool no longer blocks node clicks while peer links are displayed. - Moved peer lines into a dedicated non-interactive pane so repeated node selections keep working while the Peers tool is open. ## v1.7.8 (03-24-2026) - Adjusted MeshMapper coverage rendering to match the native MeshMapper look more closely by removing visible square borders and increasing fill density. - Legacy coverage rendering is unchanged; the visual change applies only to MeshMapper `grid_squares`. - Added a MeshMapper coverage legend in the HUD that appears only while the Coverage layer is active, using the native MeshMapper categories: `BIDIR`, `DISC / TRACE`, `TX`, `RX`, `DEAD`, and `DROP`. - Enabled Leaflet canvas rendering for the main map and moved node, history, and coverage drawing onto canvas-backed rendering while keeping animated route/trail lines on SVG so visuals stay unchanged. - Added viewport culling for nodes and coverage tiles so off-screen markers and coverage squares are not rendered until they are near the visible map area. - Batched realtime websocket updates onto `requestAnimationFrame` so bursts of node/route/history events no longer force repeated synchronous redraws and stats recalculations in a single frame. ## v1.7.7 (03-22-2026) - Added `PEERS_DEFAULT_LIMIT` so the Peers tool default list size is configurable from env instead of being hardcoded to `8`. - `/peers/{device_id}` still allows `?limit=` overrides, and both the env default and query override are clamped to a max of `50`. - Added optional boundary mode support with `MAP_BOUNDARY_MODE=polygon`, `MAP_BOUNDARY_FILE`, and `MAP_BOUNDARY_SHOW`; default behavior remains radius mode. - Polygon boundaries now filter devices, routes, and history consistently, and the frontend can render the active polygon overlay from backend-injected JSON. - Added `map_boundary.example.json` plus a standalone builder at `tools/map-boundary-builder.html` for generating polygon JSON files outside the live app; hosted copy: [https://yellowcooln.com/map-boundary-builder/](https://yellowcooln.com/map-boundary-builder/). ## v1.7.5 (03-22-2026) - Added independent scrollable incoming/outgoing peer lists so the Peers panel can show the full peer set without truncating the panel content. - Route Details now preserves companion endpoints in the popup when the route line itself begins or ends at infrastructure nodes, including non-spatial endpoint rows for companions without GPS coordinates. - Route Details can now show a display-only sender-name row as hop 0 when the packet decode includes a message sender name but not a stable sender identity. - Route Details hop counts now match the visible list when a display-only sender companion row is present, and that sender row is labeled with role `Companion`. - Added optional `PACKET_ANALYZER_URL` so Route Details hashes can link directly to an external packet analyzer. - Route Details now shows the full packet hash in the header instead of truncating it. - Route Details now prefers the MQTT packet hash for route identity and analyzer links instead of a shorter decoder `messageHash` when both are present. - Fixed the prod route payload so Route Details keeps the packet hash and sender name instead of falling back to the internal `hash:receiver` route id in the title. - Added `CHANNEL_SECRETS_FILE` support and a shipped `channel_secrets.example.json` so group-text sender names can be decrypted without using a long env var list. - Made the node popup `Location:` line clickable so it copies the displayed `Location: , ` text directly to the clipboard. ## v1.7.0 (03-20-2026) - Added dual coverage API support so the Coverage button now works with both the legacy `/get-samples` API and the new MeshMapper Coverage API. - Added MeshMapper API detection for the documented `https://meshmapper.net/coverage.php` endpoint, with automatic requests to `coverage.php`. - Added optional `COVERAGE_API_KEY` support for MeshMapper coverage requests without changing the legacy coverage integration. - Coverage rendering now supports MeshMapper `grid_squares` directly, preserving server-provided bounds and colors instead of forcing the legacy geohash tile aggregation. - Added MeshMapper-only server-side sync that stores coverage in a local cache file and serves users from that file instead of refetching `coverage.php` per request. - Added MeshMapper rate-limit cooldown handling for HTTP 429 responses, using `resets_in_hours` when provided and falling back to a local cooldown value otherwise. - When MeshMapper is rate-limited and cached coverage exists, the app now serves the last successful coverage payload instead of failing immediately. - Added coverage age filtering with `COVERAGE_MAX_AGE_DAYS` (default `30`) so the map only shows recent coverage while MeshMapper can still cache the full upstream dataset locally. - Added new MeshMapper-only coverage envs: `COVERAGE_API_KEY`, `COVERAGE_MAX_AGE_DAYS`, `COVERAGE_RATE_LIMIT_COOLDOWN_SECONDS`, `COVERAGE_CACHE_FILE`, and `COVERAGE_SYNC_INTERVAL_SECONDS` (these are not used by legacy coverage maps). - MeshMapper coverage now preserves the API `region` code in the local cache and response headers, and the map shows a bottom-right `MeshMapper` link to `https://.meshmapper.net` when the Coverage layer is active. - Added regression tests covering legacy coverage fetches, MeshMapper URL building, local cache-file serving/writes, and 429 fallback behavior. - Fixed route snapshot handling so nearly expired routes are not sent to newly loaded clients and immediately removed on page load. - Fixed route expiry timing in the frontend to use server-relative time instead of raw browser clock time, reducing premature route disappearance on clients with clock skew. - Fixed MQTT online marker styling to use the same server-relative time source, restoring the green outline on MQTT-connected nodes when the browser clock is ahead of the server. - Tightened ambiguous 1-byte hop resolution so colliding first-byte prefixes are no longer guessed from generic closest/time-based fallbacks. - Ambiguous 1-byte hops now resolve only when there is stronger evidence such as a unique candidate or neighbor/manual adjacency, reducing impossible long-distance links on large meshes. - Added websocket snapshot regression coverage for server time injection and near-expired route filtering. ## v1.6.6 (03-19-2026) - Fixed the Peers tool 24h counts on large meshes by moving peer statistics off raw `route_history_segments` and onto dedicated rolling peer-history buckets. - Peer counts are now time-windowed independently of `ROUTE_HISTORY_MAX_SEGMENTS`, so high traffic no longer causes the effective 24h window to shrink to a few hours. - Added peer-history bucket pruning/state persistence so `/peers/{device_id}` survives restarts and keeps the expected rolling window behavior. - Added regression tests covering peer counts after segment-cap pruning and peer-history state round trips. ## v1.6.5 (03-14-2026) - Made MQTT role detection conservative for accuracy: the map now only assigns roles from explicit role fields and numeric MeshCore role codes. - Stopped inferring device roles from weak MQTT name/model/client/origin/description hints that could mislabel normal nodes as room servers. - Added regression coverage to ensure model/origin strings like `PyMC-Repeater` or `PR-Room-Server` no longer assign a role by themselves. - Added runtime version logging on startup in both the server logs and browser console so the running map version is visible without checking docs. - Fixed backend route hash normalization to respect decoder `pathLength` for low-range multibyte repeater IDs, so 2-byte and 3-byte integer hashes like `0x00AB` and `0x0000AB` do not collapse to shorter prefixes. - Added regression tests covering low-range 2-byte and 3-byte path-hash padding before route resolution. ## v1.6.2 (03-11-2026) - Fixed route-details hop ordering in the UI by using backend route order and `point_ids` directly instead of frontend reversal/name heuristics. - Fixed hop-prefix display in the route details panel so 1-byte (`AB`), 2-byte (`ABCD`), and 3-byte (`ABCDEF`) prefixes all render correctly. - Improved device role detection from MQTT payloads by accepting nested role fields, numeric role codes, and common model/client hints from status and decoded packet data. - Added decoder role tests covering nested MQTT role hints and numeric-string MeshCore role codes. - Dev route debugging now includes resolved `point_id` / `point_label` data to make hop attribution issues easier to verify. - Fixed the Show Hops panel to display each matched node's true prefix from `point_id` instead of showing the incoming path token on the wrong row. ## v1.6.1 (03-11-2026) - Replaced the official `@michaelhart/meshcore-decoder` package with [`meshcore-decoder-multibyte-patch`](https://www.npmjs.com/package/meshcore-decoder-multibyte-patch) in the container runtime. - Expanded route prefix normalization and matching to support 1-byte (`AB`), 2-byte (`ABCD`), and 3-byte (`ABCDEF`) path segments. - Updated route resolution tests to cover mixed 1/2/3-byte paths and exact-prefix matching behavior. - Live dev validation now shows multibyte path strings arriving from the mesh feed; this release is intended to be ready for upcoming multibyte repeater rollouts. - Multibyte path ingest and resolution are now supported in the map, but full field validation across all mixed-network scenarios is still ongoing. ## v1.6.0 (03-07-2026) - Refactored weather backend logic into `backend/weather.py` and mounted it as a router (`/weather/radar/country-bounds`) to match the module layout used by LOS/history. - Weather is now treated as a right-side tool panel with independent `Radar` and `Wind` layer toggles. - Added share-link support for per-layer weather state via `weather_radar` and `weather_wind` URL params. - Added browser persistence for Weather layer toggles (`Radar`/`Wind`) via local storage. - Added backend weather endpoint tests for invalid coords, prod token enforcement, and cache behavior. - Expanded backend test coverage to 44 passing tests with new cases for websocket auth, prefix routing, neighbor pruning/priority, weather flags, and persistence robustness. - Hardened `/coverage` parsing for invalid upstream schemas (non-list `keys` now returns `[]`). - Replaced deprecated FastAPI startup/shutdown event decorators with a lifespan handler. - Expanded docs for all weather env settings and what each one controls. - New env controls documented for this release line: - `WEATHER_RADAR_ENABLED` - `WEATHER_RADAR_COUNTRY_BOUNDS_ENABLED` - `WEATHER_RADAR_COUNTRY_LOOKUP_URL` - `WEATHER_WIND_ENABLED` - `WEATHER_WIND_API_URL` - `WEATHER_WIND_GRID_SIZE` - `WEATHER_WIND_REFRESH_SECONDS` - `MQTT_ONLINE_STATUS_TTL_SECONDS` - `MQTT_ONLINE_INTERNAL_TTL_SECONDS` - `MQTT_ACTIVITY_PACKETS_TTL_SECONDS` - `MQTT_STATUS_OFFLINE_VALUES` ## v1.5.0 (03-06-2026) - Reworked MQTT presence tracking to follow MeshCore topic semantics: - MQTT connectivity now derives from `/status` and `/internal` heartbeats. - Explicit status values in `MQTT_STATUS_OFFLINE_VALUES` force offline quickly. - `/packets` activity is tracked separately from connectivity. - Added MQTT presence summary counters in `/snapshot`, `/stats`, and WebSocket updates so the UI can show total MQTT-connected nodes (including nodes without map coordinates). - Updated the HUD stats line to show MQTT-connected totals vs on-map MQTT-connected counts. - Popup cleanup: nodes now only show `MQTT: Online` when online; offline labels were removed. - Added new env controls: - `MQTT_ONLINE_STATUS_TTL_SECONDS` - `MQTT_ONLINE_INTERNAL_TTL_SECONDS` - `MQTT_ACTIVITY_PACKETS_TTL_SECONDS` - `MQTT_STATUS_OFFLINE_VALUES` - Passed new MQTT presence envs through `docker-compose.yaml` and expanded regression coverage with `tests/test_mqtt_online_presence.py`. ## v1.4.2 (03-05-2026) - Migrated app lifecycle from deprecated FastAPI `@app.on_event("startup"/"shutdown")` handlers to a lifespan context manager. - Kept MQTT connect/disconnect and background task startup behavior equivalent under the new lifespan flow. - Added `.venv/` to `.gitignore` for local developer test environments. ## v1.4.1 (03-05-2026) - Fixed route payload serialization in `PROD_MODE` so hop metadata needed by the Show Hops UI is included (`hashes`, `point_ids`, `origin_id`, `receiver_id`). - Added regression coverage to ensure prod route payloads keep hop hashes for prefix display. - Added tests for neighbor-priority route resolution and `/api/nodes` format/delta modes. - Reworked `.env.example` into grouped sections with clearer defaults and full key coverage to make setup easier. ## v1.4.0 (03-05-2026) - Added mixed hop prefix support in route parsing/resolution so paths can include both 1-byte (`AB`) and 2-byte (`ABCD`) repeater prefixes. - Route hash candidate mapping now indexes both prefix widths per device to reduce collisions/phantom hops on larger networks. - Show Hops now labels prefixes as `Prefix: AB` or `Prefix: ABCD` (no `0x`) and aligns prefix display with the rendered route direction. - 2-byte prefix support is implemented and expected to be ready, but has not been fully field-tested yet. - Added a pytest suite + CI workflow covering prefix parsing, route resolution, API auth/modes, LOS endpoints, coverage endpoint behavior, neighbor override loading, websocket snapshot payloads, and state/history persistence round-trips. ## v1.3.5 (02-06-2026) - Added dual stale-window support so `DEVICE_TTL_HOURS` and `PATH_TTL_SECONDS` work together instead of replacing each other. - Node pruning now supports both windows at once (with 4-day device defaults and 48-hour path defaults in examples/compose). - Environment docs and examples now describe the `DEVICE_TTL_HOURS` + `PATH_TTL_SECONDS` model and default values. - Added `DEVICE_COORDS_FILE` config path support (default: `/data/device_coords.json`) in compose and env docs. - Credit: `PATH_TTL_SECONDS` flow by https://github.com/djp3. - Credit: `DEVICE_TTL_HOURS` flow by https://github.com/chrisdavis2110. ## v1.3.1 (02-03-2026) - Propagation tool now includes an adjustable **TX antenna gain (dBi)** field that feeds directly into range and coverage calculations. - Propagation defaults now start with **Rx AGL = 1m** (previously 5m). - Credit: C2D. ## v1.3.0 (02-03-2026) - LOS tool now supports realtime endpoint dragging with throttled live recompute for smoother interaction (PR #18, credit: https://github.com/mitchellmoss). - Added elevation fetch proxy endpoint (`/los/elevations`) with frontend caching/backoff to reduce API spam and avoid elevation rate-limit failures while dragging. - Added `LOS_ELEVATION_PROXY_URL` env/config support so LOS elevation requests can be routed through the backend. - Fixed LOS point repositioning so you can click/select point A/B and click the map to move that specific point (plus visual selected-point highlight). - Updated LOS docs and feature notes for the new realtime drag + proxy workflow. ## v1.2.6 (02-02-2026) - API compatibility update for MeshBuddy and similar clients: - `/api/nodes` now defaults to a flat payload (`"data": [...]`). - Added top-level `"nodes": [...]` alias for legacy consumers. - `updated_since` now applies delta filtering automatically. - `mode=full` (or `all`/`snapshot`) forces full list responses. - `format=nested` returns wrapped payloads (`"data":{"nodes":[...]}`). ## v1.2.5 (02-02-2026) - Route line IDs are now observer-aware (`message_hash:receiver_id`) so simultaneous receptions from multiple MQTT observers do not overwrite each other. - WebSocket auth now accepts `?auth=` in addition to cookie/header auth, reducing reconnect loops during Turnstile-gated sessions. - PROD token checks now always require `PROD_TOKEN` for protected API routes; Turnstile session auth no longer bypasses API token requirements. - `ROUTE_INFRA_ONLY` endpoint logic was relaxed so direct routes can still render when at least one endpoint is infrastructure (repeater/room). ## v1.2.4 (01-29-2026) - Turnstile auth now grants access to `/snapshot`, `/stats`, `/peers`, and WebSocket without requiring a PROD token (prevents WS reconnect spam). - Show Hops panel now includes total route distance (sum of hop-to-hop segments) and updates live with unit toggles. ## v1.2.2 (01-29-2026) - Fix: Route lines now rely only on decoded packet paths, avoiding MQTT observer/receiver fallback links. - Fix: Turnstile can enable when `PROD_MODE=true` by passing `PROD_MODE`/`PROD_TOKEN` into the container. - UI: Added `darkreader-lock` meta on the map + landing pages to prevent Dark Reader overrides. ## v1.2.1 (01-29-2026) - Feature: Display hop numbers on route paths with a toggle button (credit: https://github.com/slack-t). - Feature: Consistent hop coloring based on route hash (credit: https://github.com/slack-t). - Feature: Route details panel with hop list, hash byte IDs, and per-hop/cumulative distance (credit: https://github.com/slack-t). - Fix: Route details updates live when hops arrive and respects km/mi unit toggles. - Fix: Route details panel now stacks with other tools (no overlap); LOS panel is scrollable. ## v1.2.0 (01-27-2026) - Add Cloudflare Turnstile protection with a landing/verification flow and auth cookie. - Turnstile now only activates when `PROD_MODE=true` (even if `TURNSTILE_ENABLED=true`). - Preserve Discord/social embeds by allowlisting common bots via user-agent bypass. - Hide the Turnstile site key from the page while still providing it to the widget. - Credit: Nasticator (PR #13). - New envs: - `TURNSTILE_ENABLED` - `TURNSTILE_SITE_KEY` - `TURNSTILE_SECRET_KEY` - `TURNSTILE_API_URL` - `TURNSTILE_TOKEN_TTL_SECONDS` - `TURNSTILE_BOT_BYPASS` - `TURNSTILE_BOT_ALLOWLIST` ## v1.1.2 (01-27-2026) - Dev route debug: route lines are now clickable (when `PROD_MODE=false`) and log rich hop-by-hop details to the browser console (distance, hops, hashes, origin/receiver, timestamps). Credit: https://github.com/sefator (PR #14). ## v1.1.1 (01-26-2026) - Fix: First-hop route selection now prefers the closest repeater/room to the origin when short-hash collisions occur, preventing cross-city mis-picks (Issue: https://github.com/yellowcooln/meshcore-mqtt-live-map/issues/11). ## v1.1.0 (01-21-2026) - History panel can be dismissed with an X while keeping history lines visible (re-open via History tool). - Bump service worker cache and asset version to ensure the new History panel behavior loads. ## v1.0.9 (01-16-2026) - Enforce `ROUTE_MAX_HOP_DISTANCE` for fallback-selected hops to prevent unrealistic jumps (credit: https://github.com/sefator). ## v1.0.8 (01-14-2026) - Enforce `ROUTE_MAX_HOP_DISTANCE` across fallback hops, direct routes, and receiver appends to prevent cross-region path jumps. ## v1.0.7 (01-14-2026) - Route hash collisions now prefer known neighbor pairs before falling back to closest-hop selection. - Add optional neighbor override map via `NEIGHBOR_OVERRIDES_FILE` (default `data/neighbor_overrides.json`). - Neighbor edges auto-expire using `DEVICE_TTL_SECONDS` (legacy env name, now `DEVICE_TTL_HOURS`) to prevent stale adjacency picks. ## v1.0.6 (01-13-2026) - Peers panel now labels line colors (blue = incoming, purple = outgoing). - Propagation origins can be removed individually by clicking their markers. - HUD scrollbars styled in Chromium for a cleaner look. - Bump PWA cache version to force asset refresh. - Suggestions from Zaos. ## v1.0.5 (01-13-2026) - Resolve short-hash collisions by choosing the closest node in the route chain (credit: https://github.com/sefator) - Drop hops that exceed `ROUTE_MAX_HOP_DISTANCE` to avoid unrealistic jumps - Add `ROUTE_INFRA_ONLY` to restrict route lines to repeaters/rooms - Document new route env defaults in `.env.example` ## v1.0.4 (01-13-2026) - Open Graph preview URL no longer double-slashes the `/preview.png` path (credit: https://github.com/chrisdavis2110) - Preview image now renders in-bounds device dots (not just the center pin; credit: https://github.com/chrisdavis2110) - Fix preview renderer NameError by importing `Tuple` ## v1.0.3 (01-12-2026) - Fix route decoding to return the correct tuple when paths exceed max length (credit: https://github.com/sefator) ## v1.0.2 (01-11-2026) - Fix update banner Hide action by honoring the hidden state in CSS - Remove update banner debug logging after verification ## v1.0.1 (01-11-2025) - Update check banner (git local vs upstream) with dismiss + auto recheck every 12 hours - Custom HUD link button (configurable via env, hidden when unset) - Update banner rendered from HTML dataset to avoid JS/token fetch issues - Git repo mounted into container for update checks; safe.directory configured automatically - Update banner Hide button styled to match HUD controls - New envs: `CUSTOM_LINK_URL`, `MQTT_ONLINE_FORCE_NAMES`, `GIT_CHECK_ENABLED`, `GIT_CHECK_FETCH`, `GIT_CHECK_PATH`, `GIT_CHECK_INTERVAL_SECONDS` ## v1.0.0 (01-10-2025) - Live MeshCore node map with MQTT ingest, websocket updates, and Leaflet UI - Node markers with roles, names, and MQTT online ring - Trace/path, message, and advert route lines with animations - Heatmap for recent activity (toggle + intensity slider) - 24h history tool with heat filter + link weight slider - Peers tool showing inbound/outbound neighbors with map lines - LOS tool with elevation profile, peaks, relay suggestion, and mobile support - Propagation tool with right-side panel and map overlay - Search, labels toggle, hide nodes, map layer toggles, and shareable URL params - Distance unit toggle (km/mi) with per-user preference - PWA install support (manifest + service worker) - Persistent state + route history on disk