Releases: Yeraze/meshmonitor
v3.10.0 — Major Database Refactoring & Channel Management
MeshMonitor v3.10.0
Major release featuring comprehensive database architecture refactoring — 5,672 lines of code removed across 278 files — plus new features and dozens of bug fixes.
New Features
- Channel drag-and-drop reorder with automatic message history migration (#2411)
- Dead nodes report with bulk delete on Security tab (#2414)
- Rsyslog server setting in network configuration (#2410)
- Polar grid map overlay for directional analysis (#2359)
- Configurable default map center (#2350)
- Auto responder environment variables for external scripts (#2356)
- Millisecond packet timestamps with dedicated date column (#2403)
- OIDC retry on failure — auth no longer permanently disables (#2402)
Database Architecture (5,672 lines removed)
- Full async migration — all sync database calls replaced (Phase 1-4: #2323, #2324, #2325, #2330, #2332, #2335)
- Repository pattern — monolithic DatabaseService decomposed into domain-specific repositories (#2309, #2310)
- Centralized migration registry with clean v3.7 baseline (#2315)
- N+1 query elimination in security scanner, neighbor info, and node queries (#2336, #2339, #2404)
- Cross-database helpers:
col(),upsert(),insertIgnore(),getAffectedRows()(#2372, #2374, #2376, #2389)
Bug Fixes
- Channel database no longer shadows device channels with same PSK (#2415, #2413)
- PostgreSQL connection pool exhaustion with 200+ nodes (#2404)
- Local node no longer self-flags security warnings or bounces link quality (#2407)
- Key mismatch warnings now properly clear after resolution (#2406)
- Admin keys no longer show as [object Object] (#2408)
- Traceroute race conditions and duplication (#2366, #2380, #2387)
- MQTT detection and visual distinction in traceroutes (#2302)
- PKI_UNKNOWN_PUBKEY key mismatch flagging (#2382)
- PG packet monitor showing hex IDs instead of node names (#2406)
- Time offset flags not persisted on SQLite (#2379)
- Maintenance service scheduling drift and timezone bugs (#2338)
- Packet monitor ordering with same-second timestamps (#2369, #2403)
🚀 MeshMonitor v3.10.0
📦 Installation
Docker (recommended):
docker run -d \
--name meshmonitor \
-p 8080:3001 \
-v meshmonitor-data:/data \
ghcr.io/Yeraze/meshmonitor:3.10.0🧪 Testing
✅ All tests passed
✅ TypeScript checks passed
✅ Docker images built for linux/amd64, linux/arm64, linux/arm/v7
📋 Changes
See commit history for detailed changes.
v3.10.0-RC8
Changes since RC7
Features
- feat: channel drag-and-drop reorder with message migration (#2411)
- feat: add rsyslog server setting to network configuration (#2410)
Bug Fixes
- fix: PG packet monitor names and key mismatch flag not clearing (#2406)
- fix: prevent local node from self-flagging security warnings (#2407)
- fix: admin keys showing as [object Object] in security config UI (#2408)
🚀 MeshMonitor v3.10.0-RC8
📦 Installation
Docker (recommended):
docker run -d \
--name meshmonitor \
-p 8080:3001 \
-v meshmonitor-data:/data \
ghcr.io/Yeraze/meshmonitor:3.10.0-RC8🧪 Testing
✅ All tests passed
✅ TypeScript checks passed
✅ Docker images built for linux/amd64, linux/arm64, linux/arm/v7
📋 Changes
See commit history for detailed changes.
v3.10.0-RC7
Changes since RC6
Bug Fixes
- fix: use bulk query for getAllNodes to prevent PG pool exhaustion (#2404)
- fix: packet log millisecond timestamps and date column (#2403)
- fix: OIDC init retries on failure instead of permanently disabling (#2402)
Dependencies
- chore(deps-dev): bump @vitejs/plugin-react from 5.1.4 to 6.0.1 (#2399)
- chore(deps-dev): bump vite from 7.3.1 to 8.0.1 (#2395)
- chore(deps): bump maplibre-gl from 5.19.0 to 5.21.0 (#2401)
- chore(deps): bump react-i18next from 16.5.8 to 16.6.1 (#2400)
- chore(deps): bump i18next from 25.8.18 to 25.10.4 (#2397)
- chore(deps): bump otplib from 13.3.0 to 13.4.0 (#2396)
- chore(deps): bump the production-dependencies group with 6 updates (#2393)
- chore(deps-dev): bump puppeteer from 24.39.1 to 24.40.0 (#2398)
- chore(deps-dev): bump @tanstack/react-query-devtools (#2394)
- chore(deps-dev): bump the development-dependencies group with 2 updates (#2392)
🚀 MeshMonitor v3.10.0-RC7
📦 Installation
Docker (recommended):
docker run -d \
--name meshmonitor \
-p 8080:3001 \
-v meshmonitor-data:/data \
ghcr.io/Yeraze/meshmonitor:3.10.0-RC7🧪 Testing
✅ All tests passed
✅ TypeScript checks passed
✅ Docker images built for linux/amd64, linux/arm64, linux/arm/v7
📋 Changes
See commit history for detailed changes.
v3.10.0-RC6
Changes since v3.10.0-RC5
Bug Fixes
- #2385 fix: database audit remediation across all 3 backends
- #2386 fix: database audit phase 2 — PG/MySQL crash prevention and schema alignment
- Fixed
getAuditStatsAsyncwrong column names for PG/MySQL - Added PG/MySQL guards to 6 maintenance methods that crashed via
this.db.prepare() - Added
grantedAt/grantedByto PG/MySQL permission schemas and baselines - Added
valueBefore/valueAfterto PG/MySQL audit_log baselines
- Fixed
- #2387 fix: traceroute duplication caused by bypassing deduplication logic
- Root cause:
meshtasticManager.tscalled the repository directly, bypassing theDatabaseService.insertTraceroute()dedup check
- Root cause:
- #2388 fix: packet monitor uses server time for consistent ordering
- Incoming packets used device clock (
rxTime) while outgoing used server clock, causing traceroute responses to appear before requests
- Incoming packets used device clock (
- #2390 fix: missing baseline columns + system backup + map preferences
- Added missing
routePositionscolumn to PG/MySQL traceroutes baseline - Added missing
fromLatitude/fromLongitude/toLatitude/toLongitudeto PG/MySQL route_segments baseline - Fixed
systemBackupService.listBackups()using 6 wrong column names - Fixed
getMapPreferencescrash on column name mismatches across migration states - Added comprehensive API exercise test script (134 endpoints across all 3 backends)
- Added missing
Improvements
- #2389 refactor: replace hardcoded PG column quotes with
col()helper in notifications and telemetry repos
Testing
- New
tests/api-exercise-test.sh— exercises 134 API endpoints, validated on all 3 database backends - All system tests passing (10/10)
- All soak tests passing (SQLite, PostgreSQL, MySQL)
- 3070 unit tests passing
Full Changelog: v3.10.0-RC5...v3.10.0-RC6
🚀 MeshMonitor v3.10.0-RC6
📦 Installation
Docker (recommended):
docker run -d \
--name meshmonitor \
-p 8080:3001 \
-v meshmonitor-data:/data \
ghcr.io/Yeraze/meshmonitor:3.10.0-RC6🧪 Testing
✅ All tests passed
✅ TypeScript checks passed
✅ Docker images built for linux/amd64, linux/arm64, linux/arm/v7
📋 Changes
See commit history for detailed changes.
v3.10.0-RC5
What's Changed since v3.10.0-RC4
Bug Fixes
- Fix time offset flags not persisted on SQLite —
updateNodeTimeOffsetFlagsAsyncwas missing the SQLite path, so time offset detection never showed in the frontend and log messages duplicated every scan (#2378) — #2379 - Fix duplicate traceroute pending records — outgoing traceroute was recorded twice (once on send, once on node echo), leaving a permanent "No response received" entry that hid the correct result (#2364) — #2380
- Fix channel database shadowing radio channels — server-decrypted messages now appear in both the database channel and the matching radio channel, instead of only the database channel (#2375) — #2381
- Fix PKI_UNKNOWN_PUBKEY not flagging key mismatch — PKI errors were silently suppressed when the target node wasn't in the radio's device database; now always flags keyMismatchDetected — #2382
- Fix traceroute race condition for fast-responding nodes —
recordTracerouteRequestnow properly awaited for PostgreSQL/MySQL (#2364) — #2366 - Fix packet monitor ordering within same second — added
created_at(millisecond precision) as tiebreaker sort key (#2364) — #2369 - Fix sidebar collapse on Messages/Map tabs — collapsed sidebar now shrinks to 0 width with floating expand button, reclaiming full content space — #2368
- Improve MQTT detection in traceroutes — SNR=0 (protobuf default) now correctly detected as MQTT hop; distinct lavender color and dash pattern for MQTT segments on map (@NearlCrews) — #2302
Refactoring
- Drizzle ORM Phase 1:
col()helper eliminates column quoting duplication in JOIN queries — #2372 - Drizzle ORM Phase 2:
getAffectedRows()helper normalizes affected row counts across SQLite/PG/MySQL — #2374 - Drizzle ORM Phase 3:
upsert()andinsertIgnore()helpers eliminate conflict handling duplication (10 call sites) — #2376 - Migration 014: Fix missing
decrypted_bycolumn on messages +enforceNameValidation/sortOrderon channel_database for PG/MySQL baselines — #2372 - Backend soak test: New
tests/backend-soak-test.shlaunches all 3 backends in sequence and monitors logs for errors — #2372
Documentation & Community
- Added TechTucson BBS and Mail scripts to user scripts gallery — #2370
- Updated architecture documentation with PKI error detection rules — #2382
- Translation updates from Weblate — #2273
Chores
Full Changelog: v3.10.0-RC4...v3.10.0-RC5
🚀 MeshMonitor v3.10.0-RC5
📦 Installation
Docker (recommended):
docker run -d \
--name meshmonitor \
-p 8080:3001 \
-v meshmonitor-data:/data \
ghcr.io/Yeraze/meshmonitor:3.10.0-RC5🧪 Testing
✅ All tests passed
✅ TypeScript checks passed
✅ Docker images built for linux/amd64, linux/arm64, linux/arm/v7
📋 Changes
See commit history for detailed changes.
v3.10.0-RC4
What's Changed since v3.10.0-RC3
Bug Fixes
- Fix audit_log missing columns for pre-3.7 databases — adds
ip_addressanduser_agentcolumns that were missing from pre-3.7 SQLite databases, fixing "table audit_log has no column named user_agent" errors — #2361 - Fix MQTT proxy messages not decoded locally — Virtual Node Server now intercepts
mqttClientProxyMessage, decodes theServiceEnvelope, and feeds it through the Server Channel Database decryption pipeline so MQTT-only channels appear in the UI (#2358) — #2363 - Fix key mismatch warning persisting after resolution —
keyMismatchDetectedflag now clears when keys match after a successful purge + exchange, not just when a new key arrives (#2349) — #2365 - Fix traceroute "No response received" for nearby nodes — race condition where fast responses arrived before the pending DB record was written;
recordTracerouteRequestis now properly awaited (#2364) — #2366 - Fix packet monitor ordering within same second — added
created_at(millisecond precision) as tiebreaker sort key (#2364) — #2369 - Fix sidebar collapse on Messages tab — sidebar content disappeared but container stayed 350px wide; now properly collapses — #2368
- Reclaim full space when sidebar collapsed — collapsed sidebar shrinks to 0 width with floating expand button overlay on both Map and Messages tabs — #2368
Documentation
- Updated migration documentation — CLAUDE.md and ARCHITECTURE_LESSONS.md now document the migration registry pattern instead of the old "3 places in database.ts" approach — #2362
- Added TechTucson BBS and Mail scripts to user scripts gallery — #2370
Chores
- Bump version to 3.10.0-RC4 — #2371
Full Changelog: v3.10.0-RC3...v3.10.0-RC4
🚀 MeshMonitor v3.10.0-RC4
📦 Installation
Docker (recommended):
docker run -d \
--name meshmonitor \
-p 8080:3001 \
-v meshmonitor-data:/data \
ghcr.io/Yeraze/meshmonitor:3.10.0-RC4🧪 Testing
✅ All tests passed
✅ TypeScript checks passed
✅ Docker images built for linux/amd64, linux/arm64, linux/arm/v7
📋 Changes
See commit history for detailed changes.
v3.10.0-RC3
What's Changed since v3.10.0-RC2
Features
- Polar grid leaflet overlay — switchable map overlay with range rings, azimuth sector lines, and distance/bearing labels centered on own node position (#2307) — #2359
- Auto responder tokens as environment variables — all message replacement tokens now available as env vars for auto responder scripts (#2314) — #2356
Bug Fixes
- Fix admin key crash in ConfigurationTab — coerce admin keys to strings to prevent
.trim()error on numeric values (#2353) — #2354
Improvements
- i18n for map overlay labels — all 10 map overlay checkbox labels now use translation keys — #2359
- Claude Code Review switched to experimental-review mode — inline PR comments instead of summary reviews — #2355
Chores
- Bump version to 3.10.0-RC3 — #2360
Full Changelog: v3.10.0-RC2...v3.10.0-RC3
🚀 MeshMonitor v3.10.0-RC3
📦 Installation
Docker (recommended):
docker run -d \
--name meshmonitor \
-p 8080:3001 \
-v meshmonitor-data:/data \
ghcr.io/Yeraze/meshmonitor:3.10.0-RC3🧪 Testing
✅ All tests passed
✅ TypeScript checks passed
✅ Docker images built for linux/amd64, linux/arm64, linux/arm/v7
📋 Changes
See commit history for detailed changes.
v3.10.0-RC2
MeshMonitor v3.10.0-RC2
⚠️ Pre-release — This is a release candidate. It may contain bugs and is not recommended for production use.
Summary
This release candidate adds configurable default map center location, fixes a persistent "not in your radio's database" warning that never cleared even after receiving NodeInfo from the node, and resolves security config settings (like Debug Log API) not persisting after save. It also includes several backend improvements: N+1 query fixes in neighbor info and security scanner, maintenance service scheduling drift and timezone bug fixes, channel decryption optimizations, CI improvements including PostgreSQL service in the release pipeline and Dockerfile base image verification, and multiple database migration fixes for PostgreSQL/MySQL.
What's Changed
Features
Bug Fixes
- Resolve persistent device DB warning and security config not saving #2351
- Prevent scheduling drift, timezone bugs, and data wipe in maintenance service #2338
- Correct portnum range, add enabled guard, and optimize channel decryption #2337
- Update dead MQTT proxy setup instructions link #2344 (#2329)
- Pre-3.7 check recognizes databases created by new baseline #2343
- Update DB backing test to check consistency instead of hardcoded favorite #2342
- Add missing canViewOnMap to channel_database_permissions on PG/MySQL #2340, #2341
Refactoring
- Fix N+1 queries, timestamp units, and data integrity in neighbor info #2339
- Fix N+1 queries, stale data, and write amplification in security scanner #2336
CI/DevOps
- Add Dockerfile base image verification workflow #2348
- Revert Snyk node base image upgrade #2347
- Add PostgreSQL service to release pipeline #2346
Dependencies
- Revert "[Snyk] Security upgrade node from 22-slim to 22.22.1-trixie-slim" #2347
Issues Resolved
New Contributors
- @NearlCrews made their first contributions in #2336, #2337, #2338, #2339
Full Changelog: v3.10.0-RC1...v3.10.0-RC2
🚀 MeshMonitor v3.10.0-RC2
📦 Installation
Docker (recommended):
docker run -d \
--name meshmonitor \
-p 8080:3001 \
-v meshmonitor-data:/data \
ghcr.io/Yeraze/meshmonitor:3.10.0-RC2🧪 Testing
✅ All tests passed
✅ TypeScript checks passed
✅ Docker images built for linux/amd64, linux/arm64, linux/arm/v7
📋 Changes
See commit history for detailed changes.
v3.10.0-RC1
MeshMonitor v3.10.0-RC1
Release Candidate 1 for v3.10.0. This is a pre-release — not recommended for production use.
Major: Database Architecture Remediation
Complete overhaul of the multi-database architecture across 20+ PRs:
Migration System
- Clean break at v3.7 — replaced 89 migration files with a single v3.7 baseline + 11 uniform post-baseline migrations (#2315)
- Declarative migration registry — prevents ordering bugs like #2301 (#2306, #2309)
- Pre-3.7 detection — clear error message for users on older versions (#2343)
Repository Layer
- Active Schema Map — eliminated 440+ three-way if/else branches in repositories (#2306)
- 57 Async wrappers removed — callers migrated to direct repository access (#2309, #2310)
- AuthRepository enabled for SQLite — unified auth across all backends (#2318)
- All sync callers migrated to async — zero production code calls sync DB methods (#2323, #2324, #2325, #2328, #2330, #2332, #2335)
Schema Fixes
- BIGINT bug fix —
messages.relayNodeandackFromNodeupgraded for PG/MySQL (#2306) - Schema drift resolved — 8 known column/type mismatches fixed across backends (#2318, #2322, #2340, #2341)
- Raw SQL schema files deleted — single source of truth is now Drizzle ORM (#2315)
- Permission resource names fixed — admin/user creation now uses valid CHECK constraint values (#2320, #2321)
CI & Testing
- PostgreSQL added to CI — multi-DB tests now run in CI instead of silently skipping (#2313)
- 21 new regression tests — BIGINT round-trip and schema integrity tests (#2306)
- 10/10 system tests passing (#2342)
Other Improvements
- fix: correct portnum range, add enabled guard, and optimize channel decryption (#2337)
- fix: prevent scheduling drift, timezone bugs, and data wipe in maintenance service (#2338)
- fix: auto-recover from stale SQLite SHM files after upgrades (#2304, fixes #2303)
- fix: SQLite migrations 083/084 skipped due to early return in 082 (#2301)
- fix: allow 0 for traceroute expiration hours setting (#2300)
- fix: clarified PKI key mismatch warning messages (#2343)
- fix: startup errors from early settings access before DB ready (#2343)
- fix: dead MQTT proxy setup instructions link (#2344, fixes #2329)
- ci: add PostgreSQL service to release pipeline (#2346)
Security
- Security upgrade node from 24-alpine to 24.14.0-alpine3.22 (#2312)
- Security upgrade node from 22-slim to 22.22.1-trixie-slim (#2311)
Upgrade Notes
Full Changelog: v3.9.5...v3.10.0-RC1
🚀 MeshMonitor v3.10.0-RC1
📦 Installation
Docker (recommended):
docker run -d \
--name meshmonitor \
-p 8080:3001 \
-v meshmonitor-data:/data \
ghcr.io/Yeraze/meshmonitor:3.10.0-RC1🧪 Testing
✅ All tests passed
✅ TypeScript checks passed
✅ Docker images built for linux/amd64, linux/arm64, linux/arm/v7
📋 Changes
See commit history for detailed changes.
v3.9.5
What's Changed in v3.9.5
Bug Fixes
- fix: SQLite migrations 083/084 skipped due to early return in 082 — Users upgrading from pre-3.9 on SQLite were missing the
lastMeshReceivedKeycolumn, crashing node queries and auto-delete-by-distance. (#2301, fixes #2296) - fix: allow 0 for traceroute expiration hours setting — Backend rejected 0 for "Re-traceroute after" even though the frontend and server route allowed it. (#2300)
- fix: polish Auto Delete by Distance UI — Aligned header checkbox pattern, Run Now button, disabled states, and fixed "Invalid Date" on PostgreSQL. (#2297)
- fix: use correct column names for inactive node queries on PostgreSQL/MySQL — Fixed nullable
lastHeardcausing TypeScript null check failures. (#2282, fixes #2281) - fix: guard against local node echo processing and reboot-merge races — Prevents local node echoed NodeInfo from overwriting data or triggering false key mismatch flags. (#2278, fixes #2277)
- fix: stop broadcasting stale public key in NodeInfo exchanges — Fixed MeshMonitor broadcasting cached stale keys, causing firmware 2.7.19 to reject the node. (#2276, fixes #2275)
- fix: adjust auto-traceroute interval and expiration limits — (#2272)
- fix: preserve traceroute request node order from virtual node — (#2279)
- fix: rename Exchange User Info to Exchange Node Info — (#2280)
Features
- feat: auto delete nodes by distance — Automatically remove nodes outside a configured radius. (#2270)
- feat: direct radio links visualization with simplified map overlays — (#2268)
Dependency Updates
- better-sqlite3 12.6.2 → 12.8.0 (#2295)
- mysql2 3.19.0 → 3.20.0 (#2288)
- jsdom 28.1.0 → 29.0.0 (#2292)
- docker/build-push-action 6 → 7 (#2285)
- dorny/paths-filter 3 → 4 (#2284)
- @typescript-eslint/eslint-plugin 8.56.1 → 8.57.0 (#2294)
- @typescript-eslint/parser 8.56.1 → 8.57.0 (#2289)
- @vitest/coverage-v8 4.0.18 → 4.1.0 (#2290)
- puppeteer 24.38.0 → 24.39.1 (#2291)
- Production dependencies group update (#2287)
- Development dependencies group update (#2286)
Other
- chore: add /create-pr slash command for PR workflow (#2298)
- Translations update from Hosted Weblate (#2271)
Full Changelog: v3.9.4...v3.9.5
🚀 MeshMonitor v3.9.5
📦 Installation
Docker (recommended):
docker run -d \
--name meshmonitor \
-p 8080:3001 \
-v meshmonitor-data:/data \
ghcr.io/Yeraze/meshmonitor:3.9.5🧪 Testing
✅ All tests passed
✅ TypeScript checks passed
✅ Docker images built for linux/amd64, linux/arm64, linux/arm/v7
📋 Changes
See commit history for detailed changes.