Список изменений

Заметки о версиях из репозитория MeshChatX, сначала новые. Невыпущенная работа остаётся сверху, пока не выйдет.

  1. v4.8.9 Выпущено

    Fixed

    • Re-releases the LXMF inbound attachment rejection fix from 4.8.8 with corrected test lint. The delivery resource policy no longer treats the local lxmf.delivery identity as the sender, so large messages transfer before the backchannel identifies the remote peer. Closes #94.
  2. v4.8.8 Выпущено

    Fixed

    • Fixed LXMF inbound attachment rejection. The delivery resource policy no longer treats the local lxmf.delivery identity as the sender, so large messages transfer before the backchannel identifies the remote peer. Closes #94.
  3. v4.8.7 Выпущено

    Security

    • Hardened Electron shell, Android navigation, map export, plugin endpoint host checks, identity switch copy, docs ZIP extraction, and local file handling.

    Fixed

    • Moved blocking identity teardown and maintenance DB work off the async event loop.
    • Fixed WebSocket coalescing, broadcast ordering, stale cursor recovery, delivery state regression, conversation failed count, active-conversation reset, handler isolation, nomad download race, and map export locking.
  4. v4.8.6 Выпущено

    Added

    • Bug Reports Extension (off by default): Capture crashes and issues locally, group duplicates, and send a redacted report over the RNS when you choose. Crash screens can open or save into Bug Reports.
    • Release channels: Testing, Beta, and Stable. The sidebar shows which channel you are on. Testing and Beta ask once how to file useful bug reports.
    • Install options: Flatpak channels at https://cdn.meshchatx.com/flatpak/ (testing, beta, stable). Docker images with testing and beta tags.
    • Plugins: Richer plugin pages (tabs, tables, images, and more). Enabled plugins appear as their own destinations in the app. Plugin pages follow the theme and accent colors.
    • Archives: Search shows short previews. Open Micron, Markdown, or HTML previews from a card. Recrawl a page from the viewer. Layout stacks on phones.
    • Smart Crawler: Crawls less aggressively (about one request per node per day). Sites can opt out with # nocrawl or Archives settings.
    • Nomad private tabs: Ctrl+Shift+P opens a purple private tab that is not archived, favourited, or saved in history.
    • Micron publish: Publish can create a mesh server, upload the page, and open it in NomadNet in one step. Publish site uploads several tabs as pages with editable filenames, drag or arrow reordering, and an optional index page linking them all. Editor tabs can be dragged to reorder.
    • Nomad identify-on-connect (schema 58): Sticky per-favourite Identify when connecting, matching NomadNet. Auto-identifies on link before page requests. Fingerprint toggle and favourites import/export carry the identify flag.

    Security

    • DeepSource security pass: Fixed or suppressed the first three batches of DeepSource security findings, including front-end rel attributes, Android TLS validation, stricter file permissions, and Python binding and subprocess audit rules.

    Fixed

    • Micron WASM: ASCII-art whitespace is preserved again. Consecutive spaces in Micron markup were being collapsed by the WASM renderer, breaking ASCII art. Bumped micron-parser-go to v1.1.5.
    • Micron WASM: PUA/Nerd Font icon glyphs now render with Roboto Mono Nerd Font by wrapping them in a span. Bumped micron-parser-go to v1.1.2.
    • Reticulum config: MeshChatX no longer overwrites an existing .reticulum/config on startup. Existing parseable configs are preserved and only missing [reticulum] or [interfaces] sections are added.
    • Messages: Coming back to an open chat marks it read and clears badges and desktop notifications.
    • Messages (propagated): Propagated send waits for a path to the preferred propagation node. Missing node or path gets a clear error and delivery help tip. Failed pending bubbles stay visible with the error.
    • NomadNet: Opening a node while the app is still connecting no longer sticks on Loading. A stuck page no longer freezes the whole Nomad UI. Switching away and back no longer falsely claims the page renderer stopped.
    • Desktop app: Startup and crash screens respect dark mode instead of flashing white.
    • Map: Interface and telemetry markers update again.
    • UI: Dropdown menus match the theme.
    • Permissions-Policy: Only microphone, camera, and autoplay are listed. Hardware and speaker-selection tokens are left to browser defaults so Brave and Chrome stop logging unrecognized feature warnings.
    • Header buttons: Navbar icons, sync, and compose share one size and hover circle. The language menu icon matches the rest.
    • Stranger banner: The not-in-contacts warning is a slim single row instead of a large box.

    Removed

    • ALTCHA: The proof-of-work login challenge is gone from login, setup, the demo stack, and all builds. Password and session auth still apply.

    Changed

    • Theme consistency pass: Shared primitives, conversation viewer, message entry, messages, about, settings, tutorial, call, and add-interface pages now use semantic color tokens instead of raw Tailwind classes. The audit script and fixtures track the remaining raw token inventory. The raw Tailwind color count in frontend components dropped from about 4990 to about 3758.
    • Docker files: Dockerfiles and compose files moved under docker/. Update commands to docker/Dockerfile and docker/docker-compose.yml.
    • Dependencies: Electron 44, jsdom 30, vis-network 10, vis-data 8, and assorted patch bumps. Dependency audit reports no known vulnerabilities.
    • Vite and Vitest configs: Renamed to .mjs so the ESM config warning is gone.
    • Dev script: task dev output is colored and single-prefixed.
    • Smart Crawler: Finished crawls stay finished until you refresh. Fewer crawls run at once.
    • Reticulum: RNS 1.5.3.
    • WebTransport: aioquic 1.3.0 is a normal dependency. Android builds ship aioquic and pylsqpack Chaquopy wheels.
    • Micron: Micron-Parser-Go WASM v1.2.0.
    • Docs: Short READMEs at the repo root. Full install and contributor guides under docs/en/.
  5. v4.8.5 Выпущено

    Changed

    • About: Open-file count and nofile limits sit next to memory usage.
    • Docker Compose: Process open-file soft limit is raised to 65536 when the hard limit allows it.

    Fixed

    • Docker (too many open files): Announce-thread SQLite handles close when the thread exits. RNS ratchet writes share one worker. Websocket reconnects close the previous socket. Finished RNS websocket clients drop their sockets. Log rollover writes to stderr when the log file cannot reopen.
    • Messages: Conversation list and thread load keep working while announces arrive. A closed database handle reopens instead of returning HTTP 500.
    • UI WebSocket: The UI socket returns 503 after 64 clients. Ready-status broadcasts encode the payload as JSON so the send does not reject a dict.
    • CSP: Drop invalid IPv6 localhost WebSocket connect-src entries. Permissions-Policy is set without a duplicate Feature-Policy header.
  6. v4.8.4 Выпущено

    Changed

    • Community interface presets: Build-time fetch uses https://meshchatx.com/api/mcx-interfaces instead of directory.rns.recipes.
    • Android release APK: GitHub assets use ReticulumMeshChatX-vVERSION-android-universal.apk, matching desktop installer names.
    • Confirm and prompt dialogs: Electron uses the in-app dialogs instead of native OS prompts.
    • Collapsed sidebar: The active rail item uses an inset pressed fill instead of the expanded blue pill. Collapsed buttons are square.
    • Map announce: Off until a pack is published.

    Fixed

    • Relay Chat room keys: Hosted room lists mark keyed public rooms with [+k] and never send the key. Clicking an unkeyed listed room joins without a prompt. A stored key or a later bad-key error still supplies or asks for the key.
    • Map catalog: Catalog on Discover lists packs instead of hanging. Empty catalogs show a message.
    • In-process memory growth: Announce-rate, LXMF flood, RNCP, auto-resend, Mesh Server, and map overlay lists prune on append instead of waiting for About to poll. Identity teardown drops ringtone, notification-sound, translator, and community-interface managers.
    • macOS universal: Intel NumPy OpenBLAS libraries stay in the freeze tree so the x86_64 slice can load numpy. The Intel slice runs as x86_64 instead of starting as arm64 and failing on zlib.
    • Relay Chat loopback: Typed /help and /nick stay above the hub notice when talking to a locally hosted hub.
    • macOS desktop: Frozen builds include Codec2 so LXST calls start instead of crashing on a missing library.
    • Disconnected banner: Stopping or restarting the backend keeps the red banner until the backend answers again.
    • Messages (path wait): Direct and opportunistic send wait for a path to the peer mail destination. A pasted identity hash is not a mail address and is no longer waited on.
    • Telephone dial overlay: Initiation status stays while LXST is calling or ringing, so the overlay does not close mid-ring.
    • Relay Chat: A welcome timeout tears the link and reconnects. Outbound chat is recorded locally only after it goes on the wire. A ban with no room name leaves every joined room.
    • RNCP and FileSync: Send, save, and sync-root paths refuse reserved identity-storage tops and files named identity, plus session secrets and app security config.
    • Plugins: Install refuses a source tree or zip that contains symbolic links. Hook dispatch returns immediately when the plugin runtime is disabled. Locale lookup stays inside the plugin install tree.
    • Docs zip import: Zip members with NUL bytes, absolute paths, parent directory segments, or a colon are skipped.
    • Map overlays: Cache writes refuse a temp path that is already a symlink or directory.
    • Identity switch: Relay Chat mention badge and LXMF unread refetch after switch. Compose drafts stay in the previous identity's storage bucket. Auto-resend locks and deferred managers drop with the torn-down identity.
    • Messages: An LXMF upsert with blank content, title, or fields keeps the stored values instead of wiping them.
    • NomadNet: Keep-alive tabs skip background polls when Nomad is not on screen. Opening a destination hash in the URL activates that tab.
    • Telephone: Audio context close is skipped when close is missing, so Android call teardown does not throw.
    • Map local URL: Unparseable tile or nominatim URLs are not treated as local.
  7. v4.8.3

    Fixed

    • Electron AppImage: Loading screen shows the real package version instead of v0.0.0, and desktop IPC works in packaged builds.
    • Database backup: Identity zip backups no longer fail schema upgrades when files have timestamps before 1980.
    • Navigation: Sidebar works after Docker or backend restart without a full page reload.
    • NomadNet tabs: Tab labels stay visible on short screens such as 800x600.
  8. v4.8.2

    Added

    • Local developer tooling: Vue DevTools overlay on task dev (localhost Vite only, MESHCHAT_VUE_DEVTOOLS=0 to disable). task debug attaches debugpy on 127.0.0.1:5678. Debugger launch config: MeshChatX: Vite + Python. Playwright e2e keeps DevTools off.
    • Public demo mode: Read-only mesh showcase via MESHCHAT_DEMO_MODE or --demo. Optional ALTCHA on login/setup, login page hint text, and docker-compose.demo.yml for Coolify.
    • Database upgrades: Automatic zip backup before schema migrations (skip with MESHCHAT_SKIP_PRE_MIGRATE_BACKUP=1). CLI --list-backups and --export-backup for rollback. Post-migrate checks, retention of five pre-migrate zips by default, storage lock for single-writer volumes, and N-1/N-2 upgrade tests.
    • App sidebar: Grouped layout is the default (Communicate, Explore, Network, App, plus More). Appearance can switch back to Classic. Compact identity footer with announce, QR, and auto-announce interval. Press and hold to reorder links and groups while expanded.
    • Tools page: Tools are listed under Diagnostics, Transfer, Messaging, Network, and Other instead of one ungrouped grid.
    • Mesh Server executable pages: Opt-in per node to run executable pages as shebang scripts (chmod +x on Linux/macOS, node config flag on Windows). Request fields are passed in the environment. Script stdout is the page body. Editing always shows the file source.
    • Electron hardware choosers: Serial, USB, and Bluetooth device requests open a native picker (RNode flasher, Web Serial).
    • Propagation nodes: Preferred node hash can be pasted from the clipboard, with path-request and clear actions on the preferred row.
    • Database health toast: SQLite health issues warn once per issue per session, not on every poll. The same text remains on About > Database.
    • Landlock extra read roots: Sideband command-plugin folder from Settings is allowed when it exists on disk. /sys is readable so USB serial metadata lookups work.
    • Map discovery: Publish sanitized GeoJSON/KML/KMZ packs from the Map page. Peers hear a slim announce, fetch the catalog over an RNS Link, and add the pack as a local overlay. NomadNet file links and RNGit stay as advanced sources.
    • KML/KMZ sanitizer: Strips remote links, unsafe zip entries, and DTD/ENTITY before overlay import or mesh publish. Remote icon URLs are removed.
    • RNStatus: Shows the same fields as the rnstatus CLI, including a copyable I2P address, transport/network IDs, path-request rates, and tunnel state. RX/TX rates are labeled as speeds, not packet counts.

    Changed

    • Community interface presets: Runtime no longer fetches directory.rns.recipes. Presets come from a bundled JSON file refreshed at build time, or an optional public override.
    • Runtime clearnet fetches: Micron WASM no longer installs from GitHub at runtime. Repository bundled-wheel refresh is build-time only.
    • Slow-interface path and link waits: Cold path requests wait using first-hop timeout plus an airtime floor from the slowest online interface (down to 5 bps). New links wait on establishment timeout plus 5 seconds. Nomad, FileSync, LXMF, LXST, map fetches, and related paths use those helpers so a short timeout cannot finish a slow radio exchange.
    • Dependencies: LXMF 1.1.1. Unanswered path requests during propagation peer sync apply sync backoff instead of retrying immediately. Requires RNS 1.4.2.
    • App sidebar: Network Visualiser is under Explore with Nomad Network and Map, not in More.
    • Messages empty state: The no-conversations view sits near the top of the list without a dashed box. Actions are See announces and Add contact.
    • Mesh Server UI: Remaining mesh-server strings are translated. Announce interval 0 is labeled as manual-only.
    • Docs: Getting started lists sidebar More destinations. Linux sandbox guide covers USB serial under Landlock, executable Mesh Server pages, and plugin folders that must already exist on an allowed root at process start.
    • Map page: Discover / Publish / Layers / Offline side tabs. Drawing toolbar keeps the core tools. MBTiles export, Share, and Ping left the always-visible row (Ping stays on right-click).
    • Map tiles and markers: Tile cache keeps a memory LRU and stops rewriting IndexedDB metadata on every hit. Markers cluster on a grid. Inactive map tabs wait until first shown before building OpenLayers. Online tile fetch timeout is 8s.
    • Settings search: Query splits on hyphens and punctuation, matches compact forms, and treats short tokens as whole words. Tab names are searchable. Slash focuses the search field.
    • Network visualiser planet view: Each interface is its own globe around your node. Peers sit on the interface they use. Drag orbits, scroll zooms. WebGL only.
    • Mobile header: Relay Chat and Telephone icon buttons sit in the top bar with Compose and propagation sync. Relay Chat is omitted when RRC is disabled.

    Fixed

    • Sidebar last announced: Relative time on the identity footer recomputes on the shell poll. Auto-announce events update the stamp without a page reload.
    • Docker frontend build: Vite helper script is copied into the Node stage so production builds do not fail with a missing import.
    • Map KMZ import: ArcGIS KMZ files (including GhostMaps ATAK exports) import again. Unused balloon stylesheets are skipped. CDATA HTML is flattened to plain text. Placemarks and local raster icons still import.
    • Collapsed sidebar: Icons in the app rail and Messages/Nomad collapse chevrons sit on the vertical center line.
    • Messages (personal notes): Sending to your own LXMF address is stored locally as delivered, so self-chat no longer hangs waiting.
    • Messages sidebar: Conversation list updates when you press Send, before the server acknowledges.
    • E2E: Playwright helpers attach CSRF tokens for backend POSTs. Chromium is installed before the suite runs.
    • Android LXST / Codec2: Empty pycodec2 stub falls back to a ctypes binding over bundled libcodec2 so Codec2 voice profiles work on device.
    • Android RNode flasher: Open native flasher returns a real status and surfaces startup failures. Bluetooth settings tries GrapheneOS-friendly fallbacks. In-page Flash/DFU/detect reopen the native flasher instead of failing with a confusing Web Serial error. Firmware is chosen with a file picker.
    • Connection banners: Do not flash disconnected on startup before the first successful WebSocket open. Disconnect UI waits 2.5s. Reconnected only shows after a real disconnect banner.
    • Android calls: Native mic and speaker go through the telephone audio bridge, not browser getUserMedia. Device pickers that do nothing on native audio are hidden.
    • Browser calls (Docker / HTTPS): Refresh Devices asks for mic permission with a bare audio prompt first so Brave and Chromium show the dialog. Clearer toasts for insecure HTTP and denied mic permission.
    • HTTP security headers: Permissions-Policy allows microphone, camera, bluetooth, serial, and usb for this origin so reverse proxies that omit the header do not block capture or RNode hardware APIs.
    • RNode flasher Bluetooth: Detect Brave's disabled-by-default Web Bluetooth API, show how to enable it, and offer Try Bluetooth / Recheck.
    • UI language: Persist language changes over the config HTTP API, normalize legacy locale codes, and stop the Reticulum manual language picker from overwriting app UI language.
    • Network visualizer: WebGL background follows light theme. Layout springs and repulsion are softer so the graph settles. Planet view keeps nodes on the front hemisphere and reloads after an identity switch.
    • Electron / Android shell origin allowlists: Parse URLs before treating them as the local backend (userinfo tricks are not loopback). Electron denies untrusted in-window data and blob navigations. Android WebView stays on the configured backend origin only.
    • WebSocket Origin and read gating: UI and telephone audio sockets reject a browser Origin that does not match the request authority. When password auth is on, every socket type except ping requires a session.
    • FileSync sync-root picker: Identity-storage ssl (TLS key material) cannot be chosen as a sync directory.
    • Plugin integrity at invoke: Invoke and hook dispatch re-hash the install tree and refuse tampered backends. Stale Python bytecode next to the entry file is cleared on load.
    • Peer HTML sanitizers: One XSS payload list runs against Markdown, Nomad HTML, Micron, and KML. Formatted pages still render. Scriptable nodes fail the oracle.
    • v-html: ESLint errors on v-html unless the nearby disable comment names a sanitizer.
    • LAN bind: Browser UI shows a persistent banner when bound off loopback with authentication off. Electron and Android hide it.
    • Mesh payload caps: Announce app data above 2048 bytes is omitted from storage. Map zip and Relay Chat line caps keep matching oracles.
    • Outbound HTTP: New backend HTTP clients must go through the outbound URL guard. Remaining app fetches are translator and map tiles.
    • Translator (Landlock): On Linux, user-local pipx CLIs and Argos Translate data dirs are allowed so local translation works with the filesystem sandbox.
    • Tests: Landlock integration probes for subprocess spawn, Argos language listing, user-local CLI execution, and home write denial outside allowed roots.
    • Windows desktop: AppContainer sandboxing is opt-in (MESHCHAT_APPCONTAINER=1) instead of on by default.
    • Portable mode (Electron): --data-dir / MESHCHAT_DATA_DIR and related storage flags work on Linux and macOS, not just the Windows portable exe. Storage, Reticulum config, crash reports, and logs resolve from the same root. Bots default to the app reticulum config dir.
    • Mesh Server (page nodes): Page nodes re-announce on a timer so peers do not lose the route after the first announce expires. Each server has its own interval (default 15 minutes) and an automatic-announce toggle.
    • Auth middleware: Public API paths are exact matches. status.json is no longer public via a status prefix match. Plugin .js/.json/.wasm assets require auth.
    • Interfaces / serial ports: Serial port listing no longer returns 500 when Landlock blocks USB sysfs reads. It falls back to common /dev/ttyUSB and ttyACM style device globs.
    • Announce interval 0: Mesh Server and Relay Chat keep 0 as manual announce instead of snapping the slider back to 15 minutes.
    • Propagation sync API: Propagation sync and stop-sync are POST (CSRF and demo-mode blocked), not GET.
    • Android startup: If the listen port already answers MeshChatX status, the wrapper reuses that backend instead of treating the port as busy. I2P is only disabled on first recovery when the error text mentions I2P.
    • Relay Chat hosting: /unregister removes the room. /list omits a dangling dash on rooms with no topic. Ban, invite, and op checks do not create a room just to answer. /ban list requires op first.
    • I2P interface: New I2P interfaces default connectable to off, matching RNS. Transport Mode opens a server SAM destination. Add Interface requires at least one b32 peer and states SAM must listen on 127.0.0.1:7656.
    • Identity switch logs: Persistent log handler flushes the in-memory buffer to the old database before swapping, so lines queued during switch are not dropped.
  9. v4.8.1

    Fixed

    • Windows desktop: Frozen backends start again instead of failing when aiohttp imports the standard library email package.
    • Desktop packaging: Only the correct LXST filterlib binary ships per platform so integrity checks match the installer. CI runs a frozen import smoke test before release.
  10. v4.8.0

    Added

    • Browser PWA shell caching for UI assets, with a network-first fallback during short backend restarts (not used in Electron)
    • Plugin system: ZIP and WASM install, signed packages (RSG), Python and Sideband backends, install consent, and Settings management
    • Bundled Bug Reports plugin, plus plugin translations, UI slots, and contribution registries
    • Map overlays from NomadNet and RNGit (KMZ, KML, GeoJSON) with cache and refresh
    • RNS Link WebSocket API for external apps and plugins
    • RNS File Sync for shared folders on the mesh, with an in-app file manager to browse, upload, download, and delete files
    • Settings: Reticulum instance and share controls, tabbed Settings navigation, and desktop close or tray behavior
    • Nomad favourites: per-identity section layout
    • Optional pip-rns and rngit install path for RNS packages and docs
    • Message export and import with contacts and read state
    • Message maintenance in Settings: purge old local messages and clear duplicates
    • Host battery status on About and in the header (Electron, Android, Chromium)
    • System resource monitoring for CPU and memory in the UI
    • RSM signing and verification for meshchatx.rsm
    • Notification sound settings
    • LXMFy 2.0.1 with RRC hub client support for bots
    • Network visualiser WebGL and WASM renderer, with a vis-network fallback and a Settings preference
    • Interfaces: internal mode, recursive path requests, announces-from-internal, discovery location command, and Backbone fast-flapping options
    • Reticulum interface module management from the UI
    • Reticulum 1.4.1 and LXMF 1.1.0, including propagation node options and cancel for incoming large message downloads
    • Interfaces: path gravity, announces-to-internal, and discovery autoconnect gravity and mode options
    • Relay Chat room keys so hosts can require a key to join a room
    • Desktop privacy: Windows screen security to omit MeshChatX from screenshots, recording, and Recall
    • Android privacy options to block screenshots and clear the clipboard when backgrounded
    • About shows the git commit. Nightly, preview, and local builds also show a short channel label in the sidebar
    • Tutorial connect: Internet plus local (recommended) adds AutoInterface and pre-selects three random community TCP bootstraps
    • Remote management allow-list for identities that may query this instance with rnstatus and rnpath
    • Post-install prompts for existing users after upgrades
    • Coolify-oriented Docker Compose with resource limits for deployments
    • LXST telephony half-duplex mode, live duplex switching, push-to-talk, and richer in-call stats
    • Optional Linux seccomp-BPF syscall denylist alongside Landlock
    • Bundled RNS-over-HTTP HTTPInterface with Interfaces page client and server setup, auto-install into the Reticulum interface path, and httpx support on Android
    • Docker extra image variant with i2pd and yggdrasil, published beside the standard and hardened images

    Changed

    • Tutorial: language and theme controls no longer overlay bootstrap titles. Connection and bootstrap actions stay locked while discovery or random pick is running
    • Tutorial connect and bootstrap: recommended mode stays on the bootstrap step for next and back, Finish is only on the last step, and random pick no longer sticks busy without a selection
    • Tutorial privacy and security step: shorter mobile copy and toggle layout so labels and switches fit
    • Auto propagation finder: requires usable paths and a scarce LXMF sync probe, remembers verified peers per identity, prefers live announces, cools down failures, and avoids re-probing a working preferred peer
    • Community interface presets refreshed from directory.rns.recipes (69 online listings)
    • Bundled Reticulum manual updated
    • Discovery map markers use dual-halo badge icons with banded cluster badges, zoom-gated labels, and cached styles for denser maps
    • Map default basemap is OpenStreetMap. Style presets list OSM first, and identity config wins over stale cached tile URLs
    • UI opens sooner: HTTP binds first, Reticulum starts in the background
    • Conversations load faster with slim list and thread queries
    • Conversation list uses a per-peer summary so refreshes no longer scan full message history
    • Conversation list omits contact image blobs and limits heavy callers such as Map and Network Visualiser
    • Messages page conversation poll is slower and skips while the tab is hidden
    • Fresh database init stays fast by skipping empty message-flag backfill
    • Outbound message status icons and titles reflect delivery method and state more clearly
    • Relay Chat: denser hub UI, announce interval, collapsed system lines, and reconnect notices
    • Relay Chat: clickable Nomad and LXMF links plus basic markdown for code, bold, italic, and strikethrough
    • Low-memory cleanup and SQLite tuning under memory pressure
    • Auto-resend keeps attachments and cleans duplicate outbound rows more reliably
    • Calls and audio work in Docker and headless setups via hostless LXST backends and the web audio bridge
    • Hardened identity path handling, stamp enforcement, plugin integrity, Nomad downloads, and local file path jails
    • Plugin strings live in plugin bundles, not main locale files
    • Docker frontend build includes the visualiser WASM and fails if those artifacts are missing

    Fixed

    • LXMF outbound progress polling stops on REJECTED as well as delivered, failed, and cancelled states
    • Android Codec2: preload native libcodec2 before Python codec imports
    • Android RNode flasher is a native Activity with USB serial and ESP32 ROM flash. Tools opens it instead of a WebView serial polyfill
    • Android RNode flasher: Bluetooth permission request returns real status, handles the result callback, and opens app settings when permanently denied
    • Web Sync Messages after a backgrounded browser tab recovers a stale WebSocket, refreshes CSRF, and does not abort sync when path priming fails
    • Conversations: re-opening an already-read thread no longer decrements the Messages unread badge
    • Notifications: Do Not Disturb still updates the Messages unread badge. It only suppresses OS notifications and sound
    • Identity switch clears Relay Chat, NomadNet browser tabs, Map tabs, and RNSh session UI so keep-alive pages cannot show the previous identity
    • Map local URL checks use the private 172.16.0.0/12 range instead of treating all 172.x hosts as local
    • Messages unread badge is no longer overwritten by a paginated or filtered conversation page count
    • Deep-link or compose open marks the conversation read so the sidebar unread state clears
    • Map my-location prefers LXMF address hash telemetry, not only identity hash
    • RNode flasher integrity lookup matches flat and nested keys so required scripts load
    • Relay Chat kick, ban, and failed auto-rejoin clear unread counts so room pills do not stick
    • Nomad archive load owns its download id so mismatched replies cannot leave the spinner stuck
    • Relay Chat invite-only rooms grant a reconnect invite on unexpected link drop so auto-rejoin still works after the one-shot invite was consumed
    • Map remote overlay loads no longer undo layers from a stale generation, and tile cache view keys are identity-scoped
    • Nomad micron LXMF links route to Messages instead of being ignored
    • RNSh session config and identity paths stay under storage or the shared Reticulum config dir. Free-form extra args are rejected
    • Failed identity switch no longer wipes keep-alive UI and clears the switching overlay correctly
    • Settings, About, and Interfaces refresh identity-scoped state after an identity switch
    • About snapshot and backup restore guards concurrent restores and reloads the web UI after a successful restore
    • Interfaces enable and disable write the enabled flag when neither legacy key exists, and disable returns the correct success message
    • Interfaces enable and disable roll back in-memory config when the Reticulum config write fails
    • Disabling block-all-from-strangers restores a prior inbound stamp cost of 0 instead of forcing 8
    • Discovery settings save returns an error when RNS reload fails after a successful disk write
    • Interfaces stats map is replaced each poll so deleted interfaces cannot stay Connected
    • Desktop AppImage: logs always append to the storage logs folder. Stdout is only used when a terminal is attached, so background launches no longer raise broken-pipe dialogs
    • Android: LXMFy packaging, flock soft-lock, splash and logo clipping, Landlock skipped on Android
    • Android RNode BLE and USB via Chaquopy
    • Startup checks and disables unsupported interfaces
    • Nomad favourites: no more Unknown Node or lost custom sections
    • Relay Chat message dedupe. Network visualiser faster on large meshes
    • Bots and RNSh work in frozen macOS and Windows builds
    • Sensitive config is no longer mutable over WebSocket. Reticulum config repair on startup
    • Paper message URI encoding for non-ASCII title and content
    • LXMA contact import works with current RNS public-key loading and remembers the peer key before announce
    • Android calls: overlay accept opens the phone tab so native audio attaches. Web audio is no longer permanently disabled after a bridge error
    • Android Codec2: reliable native preload, builds fail without Codec2 wheels or jniLibs, and unavailable Codec2 profiles are hidden
    • Unknown meshchatx links return a clear error instead of falling through to LXMF
    • NomadNet Micron copy no longer inserts a newline between every character
    • Unread message count is a red pill on the Messages nav icon
    • Missed call count is a red pill on the Calls nav icon
    • Notification bell removed from the header
    • Unread badge stays circular and remains visible when the sidebar is collapsed
    • Open conversations mark as read when a new message arrives without needing to reselect the thread
    • Unread badges dismiss when navigating back to an already-open Messages or Relay Chat room
    • Startup stage logs no longer print the same stage twice
    • Ctrl+C shutdown no longer floods reentrant logging errors
    • RNStatus interface mode labels match Reticulum modes again, including Internal