Commit Graph
60 Commits
Author SHA1 Message Date
Ben bfafc8a4a5 Reduce live feed client retention 2026-03-08 01:28:08 +00:00
Ben a7503ef3f2 Refine coverage, owner links, and UK feed 2026-03-08 01:16:58 +00:00
Ben d2bac3317d Fix multi-observer packet path overlays 2026-03-08 00:09:40 +00:00
BenandClaude Sonnet 4.6 bf182b8ff9 Fix beta path hop ordering and suppress red segments overlapping purple paths
- Resolver now picks shortest-hop observation (ORDER BY hop_count ASC) instead of
  most recent arrival, matching what the live feed shows for flooding packets
- Red path segments that share an edge with any purple (high-confidence) path are
  filtered out so purple always takes visual precedence

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-07 23:32:55 +00:00
BenandClaude Sonnet 4.6 c9511d8eb9 Fix multi-observer path rendering, links flicker, stale node health, and login
- usePacketPathOverlay: don't cache null beta predictions; re-fetch pinned
  packet paths when new observers arrive after pin
- MapView: stable linkedNodesKey fingerprint so linkLines memo only recomputes
  when linked node positions/roles change, not on every heartbeat
- health/status + api/routes: exclude test-network-only nodes from stale count
  and mqttNodes stat so they don't inflate thresholds
- mosquitto/acl: add meshcore-test/# readwrite for backend user
- useNodes/PacketFeed/App: merge rx_count/tx_count from DB, ALL badge when all
  MQTT regions hear a packet, improved summary extraction
- db/index: getRecentPackets now deduplicates by packet_hash with observer
  aggregation; getLastNPackets adds rx_count/tx_count and _summary support

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-07 22:53:03 +00:00
Ben 41c01bb70b Add isolated test feed and fix live public stats 2026-03-07 21:27:59 +00:00
Ben cae0580609 Support multibyte path hashes across live pathing 2026-03-07 15:51:29 +00:00
Ben 814c94d01f Update README for owner portal and current coverage 2026-03-07 03:25:54 +00:00
Ben 05514fdc18 Add owner auth DB, website refresh, and coverage rollback 2026-03-07 03:23:52 +00:00
Ben 729a966e6a Add server-side beta path resolver and mobile layer controls
- move beta path resolution onto the backend with packet-level diagnostics and live API access
- add path simulation worker plumbing, health/schema updates, and compose wiring
- update app overlays to fetch server-computed beta paths with animated rendering and request caching
- refine mobile controls so map layers collapse behind a toggle and compact the links legend
2026-03-07 00:42:31 +00:00
Ben fe56f39007 Refine beta path rendering, confidence split, and adverts source anchoring 2026-03-06 00:44:07 +00:00
Ben 0d77a5027c feat: update owner auth and refresh stats visualizations 2026-03-05 23:05:29 +00:00
Ben 833ccd8de7 health: anonymize ingest staleness and simplify active wording 2026-03-05 22:22:48 +00:00
Ben b1631be659 Improve mobile map UX and scale node markers by zoom 2026-03-05 01:59:21 +00:00
Ben 64a5b6bdf8 Polish live feed anchoring and unify MQTT docs for single-feed setup 2026-03-05 01:52:18 +00:00
Ben cd3ff83029 Unify MQTT docs and single-feed IATA routing; enable UK global stats 2026-03-05 01:49:58 +00:00
Ben ec861c4332 Refine beta links UI and lock live feed behavior 2026-03-05 01:25:18 +00:00
Ben e86912db9e Improve owner dashboard layout and deduplicated live packets 2026-03-05 01:19:33 +00:00
Ben b61f7429df Clarify Phase 5 auto-claim via Ed25519 key without login 2026-03-05 00:50:28 +00:00
Ben eca35e0016 Add repeater owner portal roadmap phase and renumber planned phases 2026-03-05 00:49:03 +00:00
Ben 8951db1bad Restore phased roadmap format in README 2026-03-05 00:46:57 +00:00
Ben 7da3b6c54e Sanitize README to remove environment-specific deployment details 2026-03-05 00:43:46 +00:00
Ben 0e365479a6 Split workers, fix frontend proxy resilience, expand health UX/docs 2026-03-05 00:39:44 +00:00
Ben 6a1caef117 Refine health page: 1h worker throughput and cleaner server stats 2026-03-05 00:09:37 +00:00
Ben 2783ab0194 Add public health page and improve beta map UX/performance 2026-03-05 00:06:12 +00:00
gadgethd d728eb0cde Update repository URL in README 2026-03-04 23:55:41 +00:00
Ben fdc754ff89 Split beta link logic and relabel links toggle 2026-03-04 23:47:40 +00:00
Ben 63e127ee8d Improve beta path accuracy with edge/motif priors and split beta pathing 2026-03-04 23:45:27 +00:00
Ben ca29010917 preload viable link metrics in initial ws state 2026-03-04 23:31:41 +00:00
Ben 135b1805db respect directional support on confirmed beta links 2026-03-04 23:28:03 +00:00
Ben 638ba72c44 add historical path-learning priors and sparse-data beta prediction 2026-03-04 23:22:36 +00:00
Ben 8d42910fca improve link visibility and network-scoped viable pairs 2026-03-04 23:10:35 +00:00
Ben 0632ec3351 fix live stats polling cache staleness on app domains 2026-03-04 23:03:46 +00:00
Ben 1359b5277d refactor app orchestration and shared site modules 2026-03-04 22:57:04 +00:00
Ben 6653d3f2f8 Refactor App pathing logic into dedicated utility module 2026-03-04 22:43:01 +00:00
Ben fb6e1369a7 Harden network filtering and coordinate handling across sites 2026-03-04 22:36:53 +00:00
BenandClaude Sonnet 4.6 83afff2401 Improve beta path resolver: directional sorting and tighter skip budget
- getCandidates: sort all tiers by alignment-toward-src combined with distance
  penalty (sortScore = cosine_similarity - dist_km/50) rather than distance alone.
  When src is unknown the alignment term is 0 so distance sorting is preserved.
- maxSkips: changed from pathHashes.length (skip everything) to
  min(2, floor(N/3)) — prevents degenerate paths on sparse data

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-04 22:12:07 +00:00
BenandClaude Sonnet 4.6 9ef68829c4 Add network column to nodes + network filtering for multi-domain support
- schema.sql: ADD COLUMN nodes.network TEXT DEFAULT 'teesside'
- db/index.ts: upsertNode accepts network, getNodes/getLastNPackets filter by network
- mqtt/client.ts: pass network to all three upsertNode call sites
- ws/server.ts: read ?network= query param, filter initial state nodes/packets
- api/routes.ts: /api/stats and /api/coverage accept ?network= filter
- useWebSocket.ts: accept network param, append ?network= to WS URL
- useCoverage.ts: accept network param, append ?network= to fetch URL
- App.tsx: compute networkFilter (teesside unless VITE_NETWORK=ukmesh), pass to hooks and stats fetch
- UKMqttPage.tsx: replace installer-based broker setup with accurate TOML config block

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-04 11:40:11 +00:00
BenandClaude Sonnet 4.6 8865a6444d Add ukmesh.com frontend and MQTT infrastructure
www.ukmesh.com (website-ukmesh container, port 3004):
- UKLayout, UKHomePage, UKInstallPage, UKMqttPage components
- VITE_SITE=ukmesh build arg routes to UK pages in main.tsx
- Stats fetched via relative /api path (proxied by Nginx)

app.ukmesh.com (app-ukmesh container, port 3003):
- Same dashboard build with VITE_APP_HOSTNAME=app.ukmesh.com
- VITE_NETWORK=ukmesh for future API filtering

MQTT:
- node-ukmesh Mosquitto user for ukmesh observer nodes
- ACL updated: backend reads meshcore/# and ukmesh/#
- ukmesh nodes publish to ukmesh/{IATA}/{PUBKEY}/packets

Cloudflare routes to add in Zero Trust:
  www.ukmesh.com  -> http://website-ukmesh:80
  app.ukmesh.com  -> http://app-ukmesh:80
  mqtt.ukmesh.com -> http://mosquitto:9001

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-04 11:16:26 +00:00
BenandClaude Sonnet 4.6 a946a07488 Separate frontend and backend into distinct containers
Splits the monolithic app container into:
- backend: Node.js handling MQTT, WebSocket, API, DB (no static files)
- app: Nginx serving the React SPA, proxying /api and /ws to backend

This means future dashboards (app.ukmesh.com etc.) can be added as
additional Nginx containers pointing at the same backend with no
duplicate calculations or DB connections.

Also updates nginx.website.conf to proxy to backend instead of app,
and bumps website host port from 3001 to 3002 to avoid conflict.

NOTE: Cloudflare Zero Trust tunnel route for app.teessidemesh.com
must be updated from http://app:3000 to http://app:80.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-04 10:58:23 +00:00
BenandClaude Sonnet 4.6 1e38a98418 Add network column and multi-network MQTT support
Lays groundwork for ukmesh.com alongside teessidemesh.com:
- Add network TEXT column to packets (default teesside)
- Parse network from topic prefix: meshcore/* = teesside, ukmesh/* = ukmesh
- Subscribe to both meshcore/# and ukmesh/# on connect
- Pass network through insertPacket so every packet is tagged at source

All existing packets default to teesside. UK-wide nodes publishing
to the ukmesh/ topic prefix will be tagged ukmesh automatically.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-04 10:49:53 +00:00
BenandClaude Sonnet 4.6 63e145c050 Remove IATA filter, accept packets from all observers
Removes the MME-only DISPLAY_IATA gate so packets from any observer
location are stored and emitted to the live dashboard. teessidemesh.com
only has MME observers anyway so behaviour is unchanged there.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-04 03:58:52 +00:00
BenandClaude Sonnet 4.6 97a9917748 Remove packet retention policy, keep all data indefinitely
Removes the 1-year TimescaleDB retention policy from the packets
hypertable so no data is ever automatically deleted. All tables
(nodes, node_links, packets, etc.) are now kept permanently.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-04 03:17:07 +00:00
BenandClaude Sonnet 4.6 17fd8cbb9b Add force_viable links, restore fade margin, improve path routing
- Add force_viable column to node_links to permanently force specific
  RF links regardless of ITM path loss calculation
- Force Hartlepool-RPT <-> YM-NM-RPT link (147.6 dB, confirmed by 4368
  observations but above the 138 dB fade margin threshold)
- Restore FADE_MARGIN_DB=10 in ITM viability check (both code paths)
- Reduce last-resort fallback distance from 500 km to 150 km in the
  backtracking DFS path resolver
- getViableLinkPairs and /api/nodes/:id/links now include force_viable=true
- Add useLinks hook for link state management

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-04 03:14:24 +00:00
BenandClaude Sonnet 4.6 437cb9efa9 Extend packet retention from 28 days to 1 year
Longer history is needed for training path-resolution algorithms (Viterbi
etc.) on real observed relay paths. At current traffic (~10 MB/day) a year
of data is ~3.6 GB — manageable on local storage.

Schema uses a DO block to update an existing retention policy via alter_job
rather than requiring a manual DB migration.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-04 03:03:14 +00:00
BenandClaude Sonnet 4.6 4969ac28b7 Live confirmed-link learning and real-time frontend updates
- Worker loads confirmed links (itm_viable + observed_count >= 5) when
  resolving relay hashes — prefers known neighbours over geographic
  proximity, creating a self-improving feedback loop as traffic accumulates
- Visited-node set added to worker resolver (each node relays once per packet)
- Frontend handles live link_update WebSocket messages: linkPairs and
  viablePairsArr updated in real-time without page refresh
- MIN_LINK_OBSERVATIONS constant defined in both worker and frontend (5)
- link_update added to WSMessageType union

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-04 02:39:30 +00:00
BenandClaude Sonnet 4.6 eb413a2f68 Require minimum 5 observations before a link is considered confirmed
Single and double observation links are likely noise from path hash
collisions or one-off propagation events. MIN_LINK_OBSERVATIONS=5
applied to the Links map layer, node popup neighbours, and the
backtracking path resolver link pair set.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-04 02:31:15 +00:00
BenandClaude Sonnet 4.6 99daf1e4d2 Add node links, improved path resolution, and confirmed neighbours
- node_links table: stores ITM-viable hop pairs from observed packet paths
  with directional counts (count_a_to_b / count_b_to_a) and path loss dB
- Historical backfill: decodes all stored packets on first run to populate links
- Per-node /api/nodes/:id/links endpoint: fetched on popup open (not preloaded)
- Node popup: shows confirmed neighbours with directional arrows and path loss
- Links layer: amber polylines on map showing all ITM-viable link pairs
- Beta path resolver rewritten as backtracking DFS:
  - Confirmed neighbours tried first (real observed link data)
  - Falls back to closest node within terrain-derived radio range
  - Backtracks when a candidate leads to dead ends at subsequent hops
  - Skips capped at ceil(hops/3) to prevent degenerate all-skip paths
  - Visited set enforces each node appears at most once per path
  - hopCount used to slice path_hashes to actual relay count
- Viable link pairs sent in WebSocket initial_state for path resolution
- LINK_BUDGET_DB raised to 148 dB; fade margin removed from viability check
- Viewshed worker: directional link tracking, UK mainland clipping fixes

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-04 02:27:27 +00:00
BenandClaude Sonnet 4.6 6fdeaf7d01 Skip prohibited nodes in packet path resolution
Filter out nodes with 🚫 in their name from hop candidates in both
resolvePathWaypoints and resolveBetaPath. For beta paths, change
empty-candidates from return null (abort) to continue (skip hop),
so a prohibited relay is simply omitted from the displayed path.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-03 23:32:54 +00:00
BenandClaude Sonnet 4.6 2af0b7bc9b Animate packet path dashes via rAF loop
Replace CSS keyframe animation (unreliable due to Leaflet calling
_updateStyle on every prop change) with a requestAnimationFrame loop
that directly increments stroke-dashoffset on the Leaflet SVG _path
element. Dashes march forward at ~1.2 cycles/s for both regular and
beta paths.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-03 23:28:44 +00:00