mirror of
https://github.com/Kpa-clawbot/meshcore-analyzer.git
synced 2026-05-29 17:44:15 +00:00
docs: v2.4.0 release notes — The Observatory
This commit is contained in:
+67
-54
@@ -1,70 +1,83 @@
|
||||
# Changelog
|
||||
|
||||
## [2.4.0] - 2026-03-21
|
||||
## [2.4.0] — "The Observatory" — 2026-03-22
|
||||
|
||||
146 commits. The packet viewer grew up.
|
||||
|
||||
### Highlights
|
||||
|
||||
- **Full observation model** — every packet now shows all observers, their individual paths, signal data, and timestamps. Expand any grouped packet to see how it propagated across the mesh. Sort by observer, path length, or time. Header row updates to match.
|
||||
- **Distance analytics** — haversine-calculated hop distances, link-type breakdown (R↔R, C↔R, C↔C), histogram, top 20 longest single hops, top 10 longest multi-hop paths. View any hop or path on the live map.
|
||||
- **Realistic propagation visualization** — "Realistic" toggle on live map buffers packets and animates all observation paths simultaneously, showing how packets actually spread through the mesh.
|
||||
- **Regional filtering everywhere** — shared multi-select region filter component across all tabs. Node region assignment based on ADVERT broadcasts (local presence), not data packet routing.
|
||||
- **Channel decryption overhaul** — rainbow table of pre-computed keys, simplified key architecture, zero-API live updates via WebSocket, 1-second ticking timestamps.
|
||||
- **Polished filter toolbar** — consistent control sizing, logical grouping with separators, tooltips on everything, ascending/descending sort options.
|
||||
|
||||
### Added
|
||||
- **Observation-level deeplinks** — `#/packets/HASH?obs=OBSERVER_ID` links directly to a specific observation; auto-expands group and selects the right row
|
||||
- **Observation detail pane** — clicking a child observation row shows that observation's data (observer, SNR, path) instead of the parent packet
|
||||
- **Channel name tags** in packet detail column — decrypted CHAN messages show a blue pill with channel name (#test, #sf, etc.)
|
||||
- **Distance/Range analytics tab** — haversine distance calculations, link-type breakdown (R↔R, C↔R, C↔C), distance histogram, top 20 longest hops leaderboard, top 10 multi-hop paths
|
||||
- **View on Map buttons** for distance leaderboard hops and paths
|
||||
- **Realistic packet propagation mode** on live map — "Realistic" toggle buffers WS packets by hash, animates all paths simultaneously
|
||||
- **Packet propagation time** shown in detail pane (time spread across observers)
|
||||
- **Replay sends all observations** — ▶ button uses realistic propagation animation
|
||||
- **Paths-through section** on node detail panel (both desktop and mobile)
|
||||
- **Regional filters on all tabs** — shared RegionFilter component with pill/dropdown modes
|
||||
- **Configurable map defaults** via `config.json` `mapDefaults` + `/api/config/map` endpoint
|
||||
- **Favorites filter on live map** — filter animations and feed list for packets involving favorited nodes
|
||||
- **Hash prefix labels** on map markers with deconfliction (spiral offsets, callout lines)
|
||||
- **Shareable channel URLs** (`#/channels/HASH`)
|
||||
- **Channel rainbow table** — pre-computed keys for common MeshCore channel names
|
||||
- **Zero-API live channel updates** via WebSocket — no API re-fetches on new messages
|
||||
- **Channel message dedup** by packet hash (multiple observers → one message entry)
|
||||
- **1-second ticking timeAgo labels** on channel list (was 30s full re-render)
|
||||
- **API key required** for POST `/api/packets` and `/api/perf/reset`
|
||||
- **HTTPS support** (merged from lincomatic PR #105)
|
||||
- **Graceful shutdown** (merged from lincomatic PR #109)
|
||||
- Observation-level deeplinks (`#/packets/HASH?obs=OBSERVER_ID`)
|
||||
- Observation detail pane (click any child row for its specific data)
|
||||
- Observation sort: Observer / Path ↑↓ / Time ↑↓ with persistent preference
|
||||
- Ungrouped mode flattens all observations into individual rows
|
||||
- Sort help tooltip (ⓘ) explaining each mode
|
||||
- Distance/Range analytics tab with haversine calculations
|
||||
- View on Map buttons for distance leaderboard entries
|
||||
- Realistic packet propagation mode on live map
|
||||
- Packet propagation time in detail pane
|
||||
- Replay sends all observations with realistic animation
|
||||
- Paths-through section on node detail (desktop + mobile)
|
||||
- Regional filters on all tabs (shared RegionFilter component)
|
||||
- Favorites filter on live map (packet-level, not node markers)
|
||||
- Configurable map defaults via `config.json`
|
||||
- Hash prefix labels on map with spiral deconfliction + callout lines
|
||||
- Channel rainbow table (pre-computed keys for common names)
|
||||
- Zero-API live channel updates via WebSocket
|
||||
- Channel message dedup by packet hash
|
||||
- Channel name tags (blue pill) in packet detail column
|
||||
- Shareable channel URLs (`#/channels/HASH`)
|
||||
- API key required for POST endpoints
|
||||
- HTTPS support (lincomatic PR #105)
|
||||
- Graceful shutdown (lincomatic PR #109)
|
||||
- Filter bar: logical grouping, consistent 34px height, help tooltips
|
||||
|
||||
### Changed
|
||||
- Channel key architecture simplified — `channelKeys` for pre-computed hex keys, `hashChannels` for channel names (auto-derived via SHA256)
|
||||
- Channel keys use plain `String(channelHash)` instead of composite `ch_`/`unk_` prefixes
|
||||
- Node region filtering uses ADVERT-based `_advertByObserver` index instead of data packet hashes (much more accurate)
|
||||
- Observation sort in expanded packet groups: grouped by observer, earliest-observer first
|
||||
- Transmission header row updates observer + path when earlier observation arrives
|
||||
- Max hop distance filter tightened from 1000km to 300km (LoRa world record ~250km)
|
||||
- Route view labels use deconflicted divIcons with callout lines
|
||||
- Channels page only shows decrypted messages, hides encrypted garbage
|
||||
- Channel keys: plain `String(channelHash)`, `hashChannels` for auto-derived SHA256
|
||||
- Node region filtering uses ADVERT-based index (accurate local presence vs mesh-wide routing)
|
||||
- Header row reflects first sorted observation's data
|
||||
- Max hop distance filter: 1000km → 300km (LoRa record ~250km)
|
||||
- Route view labels use deconflicted divIcons
|
||||
- Channels page hides encrypted messages, shows only decrypted
|
||||
- Dark mode: active filter buttons retain accent styling
|
||||
- Region dropdown: `IATA - Friendly Name` format, proper sizing
|
||||
|
||||
### Fixed
|
||||
- **Header row shows first observer's path** — removed server-side "longest path" override that replaced the transmission's path with the longest observation path
|
||||
- **Transmission header observer mismatch** — when a later observation has an earlier timestamp, observer_id/observer_name/path_json now update to match
|
||||
- **Observation sort field names** — sort was using wrong API field names (observer/rx_at vs observer_name/timestamp), producing random order
|
||||
- **Auto-seeding on empty DB disabled** — fake data no longer inserted automatically; requires `--seed` flag or `SEED_DB=true`
|
||||
- **Channel "10h ago" timestamp bug** — WS handler was using `packet.timestamp` (first_seen from earliest observation) instead of current time for lastActivity
|
||||
- **Stale UI / packets not updating** — `insert()` used wrong ID type for packet lookup after insert (packets table ID vs transmissions view ID)
|
||||
- **ADVERT timestamp validation removed** — field isn't stored; was rejecting valid nodes with slightly-off clocks
|
||||
- **Channels page API spam** — removed unnecessary `invalidateApiCache()` calls; WS updates are now zero-API
|
||||
- **Duplicate observations** in expanded packet view — missing dedup check in second insert code path
|
||||
- **Analytics RF 500 error** — `Math.min(...arr)` stack overflow with 193K observations; replaced with for-loop helpers
|
||||
- **Region filter bugs** — broken SQL using non-existent `sender_key` column, tab reset on filter change, missing from packets page
|
||||
- **Channel hash display** — decimal→hex in analytics, keyed by decrypted name instead of hash byte
|
||||
- **Corrupted repeater entries** — ADVERT validation at ingestion (pubkey, lat/lon, name, role)
|
||||
- **Hash_size** — uses newest ADVERT (not oldest), precomputed at startup for O(1) lookups
|
||||
- **Tab backgrounding** — skip animations when tab hidden, resume on return
|
||||
- **Feed panel position** — raised from 58px to 68px to clear VCR bar
|
||||
- **Hop disambiguation** — anchored from sender origin, not just observer position
|
||||
- **btn-icon contrast** — text nearly invisible on dark background
|
||||
- **Packet hash case normalization** for deeplink lookups
|
||||
- Header row showed longest path instead of first observer's path
|
||||
- Observer/path mismatch when earlier observation arrives later
|
||||
- Auto-seeding fake data on empty DB (now requires `--seed` flag)
|
||||
- Channel "10h ago" bug (used stale `first_seen` instead of current time)
|
||||
- Stale UI: wrong ID type for packet lookup after insert
|
||||
- ADVERT timestamp validation rejecting valid nodes
|
||||
- Channels page API spam on every WS update
|
||||
- Duplicate observations in expanded view
|
||||
- Analytics RF 500 error (stack overflow with 193K observations)
|
||||
- Region filter SQL using non-existent column
|
||||
- Channel hash: decimal→hex, keyed by decrypted name
|
||||
- Corrupted repeater entries (ADVERT validation at ingestion)
|
||||
- Hash_size: uses newest ADVERT, precomputed at startup
|
||||
- Tab backgrounding: skip animations, resume cleanly
|
||||
- Feed panel position (obscured by VCR bar)
|
||||
- Hop disambiguation anchored from sender origin
|
||||
- Packet hash case normalization for deeplinks
|
||||
- Sort help tooltip rendering (CSS pseudo-elements don't support newlines)
|
||||
|
||||
### Performance
|
||||
- `/api/analytics/distance`: 3s → 630ms
|
||||
- `/api/analytics/topology`: 289ms → 193ms
|
||||
- `/api/observers`: 3s → 130ms
|
||||
- `/api/nodes`: 50ms → 2ms (hash_size precompute)
|
||||
- Event loop max latency: 3.2s → 903ms (startup only)
|
||||
- Startup pre-warm yields event loop between endpoints via `setImmediate`
|
||||
- Client-side hop resolution (moved from server)
|
||||
- SQLite manual PASSIVE checkpointing (disabled auto-checkpoint)
|
||||
- `/api/nodes`: 50ms → 2ms (precomputed hash_size)
|
||||
- Event loop max: 3.2s → 903ms (startup only)
|
||||
- Pre-warm yields event loop via `setImmediate`
|
||||
- Client-side hop resolution
|
||||
- SQLite manual PASSIVE checkpointing
|
||||
- Single API call for packet expand (was 3)
|
||||
|
||||
## [2.3.0] - 2026-03-20
|
||||
|
||||
Reference in New Issue
Block a user