Files
potato-mesh/CHANGELOG.md
T

91 KiB
Raw Blame History

CHANGELOG

Features

  • Web/Data: Reticulum gets its own visual identity - trifoil marker on violet #7b61ff, MeshCore's tile moves to #1f2937, a four-step role color ramp, hexagon shape, and a legend group under MeshCore (SPEC RD1-RD8)
  • Data: Reticulum node roles are derived from the announce aspect, so a multi-aspect peer no longer flips roles (SPEC RD4/RE10)
  • Data/Web: the Reticulum host appears on the map at the position set by the latitude, longitude and height keys of its RNS config's first RNodeInterface block (SPEC RP1-RP10); keys already in that block are published after upgrading; remove them and restart the ingestor to stop (README Reticulum)
  • Web: the federation table renders a Reticulum zero count as a dash instead of a tile (SPEC RD8)
  • Web: the map legend stacks Reticulum under MeshCore, two columns instead of three (SPEC LS1)
  • Web: mesh.dmz.pt joins the default federation seed nodes and potatomesh.jmrp.io leaves them
  • Data/Web: MeshCore channel messages carry their path, RSSI and flood scope, and chat shows a route chip with hops and scope; path and RSSI were never captured before (#765, SPEC SC1-SC10)
  • Data: MeshCore channel messages scoped to a country code, eu, or a German or Austrian state or Swiss canton code (de-by, at-9, ch-zh) show that region also when the radio's default flood scope is another region or unset (SPEC SC3)
  • Data: MeshCore channel messages scoped to de-bebb, de-nord, de-ost, de-sued or de-west show that region also when the radio's default flood scope is another region or unset (SPEC SN1)

Fixes

  • Web: MeshCore @[Name] mentions and replies no longer create, refresh, or revive nodes (#883)
  • Web: a live refresh no longer moves the chat: a scrolled-up reader keeps their place, the channel tab strip stops sliding back, and tab focus and text selection survive (#881, SPEC DR1/DR3)
  • Web: chat lines lead with HH:MM and the message: seconds, frequency and preset move to the time's tooltip, channel tabs whose messages share one radio drop the [freq][preset] tag and protocol icon, the hop count and scope follow the text, and a reply shows an arrow and the replied-to badge (SPEC CD1-CD4)
  • Web: the chat tab bar shows the channel dropdown only when the tabs do not fit (SPEC CD6)
  • Web: chat day dividers read like "Thu 8 Oct" on a centred rule (SPEC CD5)
  • Web: on screens 660 to 1024 px wide the dashboard chat takes 40% of the height under a 45% map (SPEC CD7)
  • Web: above 900 px the full-screen chat uses 13 px type in lines of at most 120 characters and shows its right border (SPEC CD8)
  • Web: a MeshCore channel message stays on its sender's node and no longer moves to, or revives, a same-name node; a sender named by a stale roster is credited to the current key (#883)
  • Web/Matrix: MeshCore channel messages, whose sender is matched by the name in the text, carry sender_verified: false in GET /api/messages; the Matrix bridge posts them as its appservice user instead of the node's puppet. In an invite-only room, invite the appservice user (SPEC SV1-SV5)
  • Web: the chat no longer shows "unverified" on a MeshCore channel line whose sender is matched by name (SPEC SV3)
  • Web: the chat route chip shows ?? for an unknown flood scope, with an "unknown scope" tooltip, instead of scoped (SPEC SC7)
  • Web: the map legend's Reticulum group sits 12 px further below the MeshCore group (SPEC LS1)
  • Web: the map legend shows visible roles as plain text and hidden roles grey and struck through, and Clear filters turns blue while a role or protocol filter is active (SPEC ML1)
  • Web: the map zoom buttons match the dark map controls on the dashboard, /map and Federation maps, and grow to 44 px on touch screens (SPEC ML2)
  • Web: on the dashboard, /map and Federation maps the legend stays inside the map and below its buttons, and scrolls with the mouse wheel or a swipe when the map is short (SPEC ML3)
  • Web: node roles read as words, such as "Router late", in the map legend, the nodes table, the node page and the map overlays; the role code shows on hover (SPEC ML4)
  • Web: the map legend, toolbar, activity card, status message, zoom buttons and popups share one dark style, and Federation map popups are no longer white (SPEC ML5)
  • Data: the MeshCore ingestor no longer posts placeholder nodes for chat senders or mentions, so hidden-channel names stay hidden; the web app ignores such posts from older ingestors (#883)
  • Data: a MeshCore sender name shared by several roster contacts resolves to the most recently advertised one (#883)
  • Data: the MeshCore ingestor posts an advert from the radio's RX log only when its signature verifies, refusing small-order keys and replayed adverts, so a node's SNR, RSSI and hops now come from the first copy heard; roster contacts are unchanged (SPEC SG1-SG5)
  • Web: live refreshes keep unchanged nodes-table rows, so an open + row, focus, a text selection, an overlay opened from a badge and the row under a scrolled page stay put; a moved overlay's close button now works (#881, SPEC DR1)
  • Web: nodes table cells show bare numbers with fixed decimals, and each numeric column header names its unit, Frequency (MHz) included; a powered battery reads 100 ⚡ (SPEC DV1)
  • Web: long names in the nodes table are underlined only while their row is hovered or the link has keyboard focus (SPEC DV2)
  • Web: the node page and /charts align their content to the 16 px page edge, the node overlay to its dialog padding (SPEC DV4)
  • Web: the federation table uses 12 px text, the nodes table's size, and 5 px 8 px cells (SPEC DV5)
  • Web: chart titles are 15 px, chart time ranges and legends 12 px (SPEC DV6)
  • Web: code on static pages uses the app's monospace font (SPEC DV7)
  • Web: static pages no longer scroll sideways on phones; a wide code block scrolls inside the page (SPEC DV8)
  • Web: the dashboard no longer scrolls sideways on a 375 px phone; the nodes table fits its column (SPEC DV9)
  • Matrix: the bridge crate declares its crates.io package metadata, and its README screenshot no longer links outside the crate (#879)
  • Data: TRANSPORT=udp listens on both Meshtastic multicast groups by default, 239.0.0.69 (firmware 2.8+) and 224.0.0.69; MESH_UDP_GROUP takes a comma-separated list. If you set MESH_UDP_GROUP=224.0.0.69 before, remove it to also hear firmware 2.8+ nodes (#903)
  • Data: MESH_UDP_ALLOWED_SOURCES limits which hosts the UDP transport accepts packets from: comma-separated IPv4 addresses or CIDRs, e.g. your node's IP; unset accepts every host that can reach the multicast group, as before (SPEC UT1-UT4)
  • Data: MESHCORE_TELEMETRY_POLL_24H_EXEMPT reaches every packaged deployment - docker-compose.yml, both data/Dockerfile stages and the NixOS module (meshcoreTelemetryPoll24hExempt); setting it in .env had no effect under Compose or NixOS (SPEC PX5)
  • Data: mesh.sh builds data/.venv and runs pip for one start at a time, and runs no pip when requirements.txt and the venv's Python are unchanged; it also works when started from the checkout root. If a unit fails to import its packages: stop the units, remove data/.venv, start them (SPEC VL1-VL3)
  • Web: live refreshes keep map overlays, line tooltips and waypoint cards open, and repaint only the table, map or chat whose data changed (#881, SPEC DR2/DR4)
  • Web: a node role or modem preset named like a built-in object property, such as constructor, gets its protocol's base color and its derived preset code instead of an uncolored badge or a [FU] tag (SPEC FE1)
  • Web: a node id containing " no longer stops the live-update flashes of a refresh (SPEC FE2)
  • Web: on touch screens the menu, region, protocol, live and legend toggles, map toolbar, chat tabs, channel select, filter box and node dialog close are at least 44 px tall; the filter's × and the badge popover's close take taps in a 44 px square, and filter text stops short of the ×; each sort button takes taps across its header cell, now 45 px tall; none of these reaches a table row or another button (SPEC CT1)
  • Web: every button and button-like control without a focus ring of its own shows the accent focus ring when reached by keyboard, and chat tabs show it inside the tab strip (SPEC CT2)
  • Web: the protocol toggles stay hidden on an instance with one active protocol, the filter shows its × only with text in it, the region selector hides with fewer than two regions, the map's full-screen button hides where the browser has no full-screen support, and the meta row no longer jumps while the dashboard loads (SPEC CT3)
  • Web: the live toggle reads "● live · pause" and "❚❚ paused HH:MM · resume", framed in the accent while paused; on phones it reads "● live" and "❚❚ paused HH:MM" (SPEC CT4)
  • Web: the Chromium that renders /og-image.png keeps its sandbox unless OG_IMAGE_NO_SANDBOX=1, which the Docker images and the Compose default set, and keeps the same-origin policy and site isolation on (SPEC FE3/FE4)
  • Web: the federation page shows a numeric frequency or version instead of an empty cell (SPEC FE5)
  • Web: buttons, row toggles, the footer, the badge popover and the nodes table's group header use the dashboard's blue-black palette instead of neutral greys (SPEC GF1/GF2/GF3)
  • Web: the chat panel uses the dashboard's palette, and its empty-channel note meets 4.5:1 contrast (SPEC GF2)
  • Web: both pinned header rows of a table are opaque, so rows scrolled beneath them no longer show through (SPEC GF4)
  • Web: the node detail dialog has a panel fill and a hairline border and keeps a margin on every side of the window (SPEC GF5)
  • Web: the federation map is half the window tall and at least 320 px (320 px at 900 px wide and narrower), with one border, and /map no longer scrolls 2 px sideways (SPEC GF6)
  • Docs: the README documents MESHTASTIC_PSK_B64 (SPEC PX7)
  • CI: the env-surface check runs in pytest whenever a deployment surface changes, and also checks names with digits, names read through helpers, and retired names (SPEC PX6/PX8)
  • CI: test results reach Codecov also when tests fail; workflows use codecov-action v7 and checkout v7; Dependabot opens up to 20 GitHub Actions update PRs at a time (SPEC DW1/DW2/DW4)
  • Docker: the root Dockerfile builds the same image as web/Dockerfile, including Chromium for Open Graph previews (skip it with --build-arg WITH_OG_IMAGE=0), the custom pages directory, and the APP_VERSION build arg (SPEC DF1)
  • Docs: SECURITY.md says how to report a vulnerability privately (SPEC SEC1)
  • Web: /metrics no longer exports nodes that opted out or that private mode hides; series exported before an opt-out stop at once (SPEC PM1/PM2)
  • Web: with PRIVATE=1, a hidden client (CLIENT_HIDDEN) is left out of positions, telemetry, neighbors, traces, destinations, ingestors, the stats counts, the /version and well-known freshness hints, the preview image and its node page, not only the node list; a trace it relayed between other nodes keeps its other hops (SPEC HC1-HC4, HC7)
  • Web: /api/traces/:id for an opted-out node returns nothing, as for its other reads (SPEC HC7)
  • Docs: the README says how to hide a node with the U+1F6D1 (stop sign) marker, where Reticulum takes it, and how long data is kept (SPEC HC6)
  • Web: on screens 600px wide and narrower the footer scrolls with the page instead of covering its end (SPEC SH1)
  • Web: the mobile menu lists the static pages, GitHub and the chat link, the phone footer drops its links row, and the footer escapes CONTACT_LINK (SPEC SH2)
  • Web: ANNOUNCEMENT accepts [label](https://...) links, a bare link no longer swallows a trailing period or parenthesis, banner links take the banner colour, and on phones the banner shows three whole lines (SPEC SH4)
  • Web: the region, menu and close buttons draw SVG icons instead of emoji and text glyphs, and the region toggle is no longer greyed out (SPEC SH5)
  • Web: the region toggle sits beside the site title and shows an accent frame while open (SPEC SH6)
  • Web: mobile menu links and the close button are 44px targets (SPEC SH7)
  • Data/Web: Reticulum reports a frequency and LoRa preset, read from the RNS config (SPEC RL1-RL3)
  • Web: federation node counts distinguish zero from not-reported uniformly across all three protocols (SPEC RL4)
  • Web: the Reticulum destination count matches the table, and /api/destinations serves only destinations of nodes inside the node window (SPEC RA3/RA8)
  • Web: a destination's identifier links to its identity page (SPEC RL5)
  • Web/Data: ingested strings are capped in bytes by column (node name 512, message 1024, instance fields 256, instance key 2048), a numeric field that is not a number, an integer beyond 64 bits or a non-finite number is stored as NULL (before: text, an approximate REAL or infinity), a POST /api/nodes key or record id that is not a node id is skipped, as is a node entry or nested map of one that is not a mapping, an unknown ingestor protocol registers as meshtastic, and an instance announcement with a field over its cap is refused; rows stored before the upgrade keep their values until retention removes them (SPEC SL1-SL10)
  • Web: Reticulum rows match every other row's height; one dash glyph throughout the nodes table (SPEC RA11)
  • Web: a federation peer whose newest node is up to 7 days old is accepted and refreshed again, not only within 24 hours (ACCEPTANCE FS-A5)
  • Data/Web: Reticulum nodes are keyed on the announcing identity, not on each destination - one node, several destinations (SPEC RE7/RE10)
  • Data/Web: a Meshtastic NodeInfo or NeighborInfo whose node id is not exactly its sender's is dropped with a warning, whether the ingestor decodes it or the web app decrypts it, and every Meshtastic record is filed under the node that sent it
  • Web: a node keeps its names, role, position and opt-out marker against a node record under another key or none; a new key takes the node over once the old one has been silent for four weeks
  • Data/Web: a MeshCore or Reticulum node that shares its 4-byte id with another key keeps the first key's names, position, destinations and chat messages
  • Web: position, telemetry and last-seen updates no longer change the node row of another protocol that shares its id
  • Web: a Meshtastic client first heard through a position or telemetry packet no longer stays hidden after its NodeInfo arrives
  • Data: the ingestor's own node id is its primary announced identity (SPEC RE8)
  • Web: the map legend lists only protocols in view: a protocol toggled off, or with no node matching the filter, leaves it; Clear filters also clears the filter text (SPEC LP1)
  • Data: the host's own transport aspect is ingested when the stack has transport enabled (SPEC RE9)
  • Data: the Reticulum ingestor re-posts its host's own destinations every hour, so rns.transport and the host aspects stay fresh on a connection that never reconnects (SPEC RE8)
  • Data: the Reticulum ingestor logs Reticulum stack state after each connect and Reticulum announce summary every hour; the summary is a warning with hints when no announce arrives or the interface scope drops them all (SPEC RG1-RG4)
  • Data: after a failed Reticulum connect, the next connect no longer posts and counts every announce twice (SPEC RG5)
  • Web: a federation record relayed by another instance is stored only when its domain's well-known document names its key, except a refresh under the key already stored; relayed records and POST /api/instances announcements need an id equal to the SHA-256 of their public key (SPEC FS8/FS9)
  • Web: a federation crawl fetches each peer once, however often it is listed, keeps the newest signed copy of a record and never fetches this instance; FEDERATION_MAX_DOMAINS_PER_CRAWL counts the domains a crawl fetches (SPEC FL1)
  • Web: in one crawl the port variants of a host share one well-known fetch beside the bare domain's own, and a domain ending in :443 or :80 counts as the bare domain (SPEC FL1)
  • Web: the crawl and POST /api/instances judge a peer on one /api/nodes?limit=10 request and ask a peer for counts only when its record lacks one (SPEC FL2)
  • Web: an announcement no longer starts a crawl; crawls run after boot and every 8 hours, and a peer is fetched at most once per FEDERATION_PEER_FETCH_COOLDOWN (900 s), which replaces FEDERATION_CRAWL_COOLDOWN (SPEC FL3)
  • Web: federation requests revalidate with If-None-Match and If-Modified-Since, honour Retry-After on 429 and 503, and back off a failing peer for up to 24 hours (SPEC FL4)
  • Web: a crawl stops at FEDERATION_MAX_REQUESTS_PER_CRAWL (1024) requests, its domain limit or FEDERATION_TASK_TIMEOUT (SPEC FL6)
  • Web: POST /api/instances verifies a peer within REMOTE_INSTANCE_REQUEST_TIMEOUT, at most four at once, and reads its well-known only at first contact or on a key change; inside the peer's cooldown it judges the peer by what the last fetch kept, and answers 503 with Retry-After when that cannot decide (SPEC FL7)
  • Web: POST /api/instances answers an announcement under the stored key that is no newer than the stored row 201 and leaves the row as it is (SPEC FL1, FL7)
  • Docs: the README names the federation User-Agent and states the crawl after boot and every 8 hours, and deploy/nginx.example.conf has an optional rate limit for federation requests (SPEC FL8)
  • Data: PROTOCOL=reticulum needs INGESTOR_NODE_ID in Docker, when nothing on the ingestor's RNS stack announces, or when two local identities tie; otherwise the node id is derived once a local app announces (SPEC RE5/RE8)
  • Data: a set CONNECTION is no longer silently ignored under PROTOCOL=reticulum - the ingestor now logs that it is dropping the value (SPEC RN10)
  • Data/Web: Meshtastic records whose radio clock is off by more than an hour get the ingestor's receive time, so they show in charts and tables again; the node page shows a battery above 100% as the nodes table does (SPEC RK1-RK3, UX10)
  • Data: when a Meshtastic radio's clock is off by more than an hour, the node list it sends at connect is posted with each lastHeard shifted to the ingestor's clock; entries stamped more than an hour before the radio's current boot are posted as stamped when the radio reports its uptime, entries stamped ahead of its clock are skipped, and the ingestor logs one warning. Without a clock reading, an entry more than an hour ahead of the ingestor's clock is skipped (SPEC RK4)
  • Data: RETICULUM_INTERFACES now resolves interface names through the shared RNS instance, fixing an allowlist that matched nothing on a shared stack (SPEC RE3)
  • Data: a Reticulum announce with no display name no longer overwrites a stored name
  • Docs: document the Reticulum config directory, its Docker volume, and how to add interfaces to it
  • Data: ALLOWED_CHANNELS, HIDDEN_CHANNELS, and MAP_ZOOM no longer break on the packaged Compose default's quoted-empty value (ACCEPTANCE CH-A1-CH-A3)
  • Data/Web: nodes.identity_hash keeps each Reticulum node's full identity hash, as do its destinations rows (SPEC RE2/RE7)
  • Data/Web: user.publicKey carries the identity's real public key; destinations get their own table, served by GET /api/destinations, which honors the node opt-out marker (SPEC RE2)
  • Data: new RETICULUM_INTERFACES allowlist scopes announce ingestion by interface, applied from one hop out; the operator's own nodes are always ingested (SPEC RN4/RE4)
  • Data: PROTOCOL=reticulum ingests only RNode interfaces by default; set RETICULUM_INTERFACES=* to ingest every interface as before (SPEC RN4)
  • Config: configure.sh asks for INGESTOR_NODE_ID under PROTOCOL=reticulum (SPEC RE8)
  • Web: the /charts mesh-activity figure draws the Reticulum series (SPEC RN2)
  • Web: instances.reticulum_nodes_count gets its own migration (SPEC RN7)
  • Docs: every environment variable the ingestor or web app reads is documented (SPEC DOC2)
  • Docs/Config: configure.sh and the NixOS module are no longer Meshtastic-only (SPEC DOC3)
  • Docs: the README documents every route (SPEC DOC4)
  • Docs: the dual basemap-CDN egress disclosure was restored (SPEC SB6)
  • Docs: CONTRACTS.md corrected to match the served /api/destinations shape (SPEC DOC5)
  • Docs: ACCEPTANCE.md amended for the shipped Reticulum stats scope; README gains a Reticulum section
  • Web: picking a channel from the chat dropdown on mobile no longer fails while live updates arrive (#882)
  • Data: ALLOWED_CHANNELS, HIDDEN_CHANNELS and PRIMARY_CHANNEL_ONLY drop every packet type and node-list entry from excluded channels, not only text messages (#784, SPEC CF1-CF3)
  • Data: node-list snapshots no longer carry the radio library's copy of each node's last packet (#784, SPEC CF3)
  • Data: under TRANSPORT=udp, ALLOWED_CHANNELS and HIDDEN_CHANNELS match channel 0 by PRIMARY_CHANNEL_NAME (#784, SPEC CF2)
  • Data: PRIMARY_CHANNEL_ONLY accepts true/yes/on like the TX_* flags; an unrecognized value enables it (#784, SPEC CF5)
  • Data: new DROP_VIA_MQTT=1 drops Meshtastic packets and nodes relayed via MQTT, on the API and UDP transports (#884, SPEC VM1-VM2)
  • Web: the web service no longer receives the unused ALLOWED_CHANNELS/HIDDEN_CHANNELS settings (#784, SPEC CF6)
  • Docs: CHANNEL_INDEX documented as the announcement channel, not an ingest filter (#884, SPEC CF7)
  • CI: Dependabot version updates run for every ecosystem; the Ruby and Python entries use the documented bundler and pip names (SPEC DP1)
  • Web: web/Gemfile.lock is committed, so CI and the web image install the locked gems (SPEC DP2)
  • Data: data/requirements.txt pins the runtime dependencies with == and no longer installs black and pytest into the ingestor image; the dev tools move to data/requirements-dev.txt (SPEC DP3)
  • Web: the web image and the Nix web app run Ruby 3.4, the version CI tests, instead of Ruby 3.3 (SPEC DP5)
  • Data: the ingestor image runs Python 3.13, the version CI tests, instead of Python 3.12 (SPEC DP5)
  • CI: the Python workflow tests Python 3.13 and 3.14; neither CI matrix fails fast (SPEC DP5)
  • Web: a MeshCore channel message heard by two ingestors that resolved its sender to different node ids is stored once (#880)
  • Web: the first boot after upgrading deletes duplicate MeshCore messages once; on instances with several MeshCore ingestors this can remove about a fifth of the stored MeshCore messages (#880)
  • Data: each INSTANCE_DOMAIN target gets its own upload queue (10,000 records, 24 hours): a record an instance missed (connect failure, timeout, 5xx) is sent to it again once it answers, a failing instance pauses 5 s to 60 s and honours Retry-After, a 4xx other than 408, 425 and 429 is not retried, a record is dropped after 4 server errors or 8 attempts that got no reply, and an instance that is down no longer slows the others (SPEC UR1-UR5)
  • Data: uploads no longer follow redirects; a record answered with a 3xx is dropped with a warning that names the status and the redirect host. Set INSTANCE_DOMAIN to the URL the instance answers on (SPEC UR6)
  • Web: a heartbeat the ingestor resends after a lost reply no longer adds a second activity row (SPEC UR7)
  • Data/Web: a Reticulum destination's placeholder name never replaces its real name or names its node; a node with no announced name reads its own placeholder; a nameless destination is named from its own hash (SPEC RA10, RE10)
  • Web, bridge, app: Reticulum is named as its own protocol in the bridge tag ([RT]), the footer join strip (RETICULUM_PRESET and RETICULUM_FREQ), the /nodes page description and the client fallback label; the site description names no protocol; the app README states the app is Meshtastic only (SPEC RL8)
  • Docs: Reticulum is marked experimental and announce-only; the README says what the RNS stack transmits and that the channel filters ignore it (SPEC RD7/RN5)
  • Nix: the flake ingestor includes rns, so PROTOCOL=reticulum runs on NixOS; flake.lock moves nixpkgs to nixos-unstable of 2026-10-03, which brings Python 3.14 and Ruby 3.4.9 (SPEC DP8)
  • Docs: CONTRACTS.md states the Reticulum placeholder and headline name rules as amended (SPEC RA10, RE10)
  • App: the Flutter app (app/) and its CI are removed (SPEC AR1)
  • Web: on /map, /chat, /nodes and node pages the announcement banner, the header and the filter and live controls sit on the dashboard's 16 px page margin (SPEC SR1)
  • Web: on screens wider than 1024 px the footer shows PotatoMesh and the version on the same row as the page links when both fit; otherwise the links keep their own row (SPEC SR2)
  • Web: map overlays keep their dark background in browsers without color-mix() (Chrome before 111, Safari before 16.2, Firefox before 113) (SPEC SR3)
  • Web: Log announcements lead with HH:MM in the time column like chat messages, with seconds, frequency and preset in its tooltip, and wrapped lines continue under the text (SPEC LA1)
  • Web: Log lines name their kind in a word (new node, node info, telemetry, position, neighbor, waypoint, trace, encrypted) instead of a colour emoji, then one detail: up to three changed telemetry values, a position at 4 decimals, the neighbor's or the trace hops' badges; the chat filter matches these words (SPEC LA2/LA3)
  • Web: a node's node info, position and telemetry heard within 60 seconds share one Log line (SPEC LA4)
  • Web: the Log and channel tabs drop the radio tag when every line with a preset code shows the same code for the same protocol; a chat line that needs one shows only the preset code, such as MF, and chat lines no longer show the protocol icon (SPEC LA1/LA5)
  • Web: MeshCore short-name badges have square corners, like their map markers (SPEC LA5)
  • Web: a new node's long name in the chat is underlined only on hover or keyboard focus (SPEC LA6)
  • Web: long names and hardware models no longer widen the page past the nodes table's column: while the table would overflow, those cells break inside a word (SPEC PO1)
  • Web: static pages fit phone screens with long inline code and wide tables: inline code breaks anywhere, and a table wider than the page scrolls inside its own box (SPEC PO2/PO3)
  • Web: a position or telemetry record whose position, position.raw, position.payload or telemetry section is not a mapping is stored without that section, and the rest of its batch is stored; a JSON-encoded telemetry section is read without a top-level time (SPEC IB1)
  • Web: a latitude outside -90 to 90 or a longitude outside -180 to 180 stores no coordinates for a position, node or waypoint; the rest of the record is stored (SPEC IB2)
  • Web/Data: a neighbor snapshot keeps its first 16 neighbors and a trace its first 16 hops; the ingestor cuts both lists before posting (SPEC IB3)
  • Web: a heartbeat packets count above 1,000,000,000 records no activity row, and /api/stats and /api/stats/activity count each stored row at most 1,000,000,000 (SPEC IB4)
  • Web: a later message from another sender under a stored message's id no longer replaces that message's sender, recipient and text; it is dropped with a warning (SPEC KC1, KC3)
  • Web: a later copy of a stored message fills a missing recipient, text, reply, emoji or portnum and no longer replaces them (SPEC KC2)
  • Web: a position, telemetry reading or trace under an id another node already holds no longer replaces that node's row; it is dropped with a warning (SPEC KC4)
  • Web: a message naming its sender only by from_num stores that number's !xxxxxxxx id as from_id; such a copy of another sender's message is dropped (SPEC KC1)
  • Web: the warnings of dropped messages and records log at most 10 lines a minute per writer, then one line with the number suppressed (SPEC KC5)
  • Web: HTML pages send a Content-Security-Policy and every response Referrer-Policy: strict-origin-when-cross-origin; basemap tiles and images on custom pages must use https:// (SPEC HD1-HD3)
  • Web: the canonical link, og:image, robots.txt, sitemap.xml and the /og-image.png capture keep the scheme INSTANCE_DOMAIN names, and otherwise take only http or https from forwarded headers (SPEC HD4)
  • Web: the Chromium that renders /og-image.png starts without API_TOKEN or the app's other environment variables (SPEC HD5)
  • Web: the header and footer print SITE_NAME and the version as text, and asset URLs, module preloads and the import map carry the version URL-encoded (SPEC HD6)
  • Web: the unused /potatomesh-logo.svg route is removed; the static handler serves the logo as before (SPEC HD7)
  • Docs: deploy/nginx.example.conf and DOCKER.md clear the Forwarded request header, so the scheme of generated URLs comes from X-Forwarded-Proto (SPEC HD4)
  • Data: the MeshCore ingestor posts each roster contact's node once per connect instead of three times, and its position once instead of twice; a re-advert of a known contact posts its node and position once each instead of twice, or twice instead of three times on firmware 1.16 and later (SPEC CU1-CU3)
  • Web: a federation instance row is replaced in one transaction: a failed write keeps the stored row, and two writes for one domain at once no longer fail on the unique domain index (SPEC FK1)
  • Web: a database error while a crawl stores one peer is logged and the crawl goes on with the next peer (SPEC FK2)
  • Web: a keyfile that cannot be parsed stops the boot with an error naming the file and is left as it is, instead of being replaced by a new key and instance id; a legacy keyfile that cannot be parsed is not copied, and the error names it; restore the named file from a backup or delete it to start with a new key (SPEC FK3)
  • Web: Meshtastic payload decoding is bounded: a decode is killed with its process group after 4 s, one POST /api/messages decodes at most 4 messages, and each web process runs at most 2 decodes at once; a message past a bound is stored still encrypted, as when decoding fails (SPEC DB1-DB4)
  • Web: the filter box refilters the nodes table, the map and the chat once typing pauses for 200 ms, not on every keystroke; Enter applies the text at once, as do the box's ×, the role and protocol toggles and Clear filters (SPEC DE1/DE2)

Features

  • Data/Web: Reticulum protocol support - PROTOCOL=reticulum ingests announces as protocol="reticulum" nodes end-to-end (ingest, stats, federation wire, UI) (SPEC S6/FS2/MA5/MA-F2/F2-2 as amended)

v0.7.5

Features

Fixes

  • Ingestor: every mesh transmission is now off by default (TX_ENABLED, default 0), covering the activity announcement and the MeshCore on-air contact telemetry polls; announcements take a second opt-in (TX_ANNOUNCE=1) on top by @l5yth in https://github.com/l5yth/potato-mesh/pull/891
  • Ingestor: RX_ONLY no longer fails open - it was compared as an exact == "1", so RX_ONLY=true, TRUE, yes, on and " 1" all silently resolved to off and a receive-only listening post transmitted anyway; all TX flags now accept the common spellings, strip whitespace, and resolve an unrecognized value toward silence by @l5yth in https://github.com/l5yth/potato-mesh/pull/891
  • Ingestor: the TX_* flags reach every packaged deployment - docker-compose.yml, data/Dockerfile, the NixOS module (txEnabled/txAnnounce) and .env.example; the previous ANNOUNCE opt-in reached none of them, so setting it in .env had no effect at all by @l5yth in https://github.com/l5yth/potato-mesh/pull/891
  • Ingestor: the announcement's 24 h anti-spam delay is measured on a monotonic clock - it used wall clock, so on an RTC-less host a post-boot NTP step cleared it instantly by @l5yth in https://github.com/l5yth/potato-mesh/pull/891
  • Ingestor: transmit policy is stated in the log at startup without DEBUG=1, and each suppressed announcement names the gate that closed by @l5yth in https://github.com/l5yth/potato-mesh/pull/891
  • App: await the in-flight request before closing its HTTP client in loadMessages/loadNodes - the unawaited return let finally close the client mid-request by @l5yth
  • App: raise the iOS deployment target to 15.0 (from 14.0) in the Podfile, Xcode project and AppFrameworkInfo.plist - Flutter 3.47's Flutter pod requires it, and pod install could not resolve against the old target. Drops support for iOS 14 devices. by @l5yth
  • CI: the Mobile workflow matrix no longer fails fast, so an iOS failure stops hiding whether the Android build passed by @l5yth
  • Docs: README gains a Transmitting on the mesh section - what each flag turns on, the truth table, the literal announcement text, and what is never gated by @l5yth in https://github.com/l5yth/potato-mesh/pull/891

v0.7.4

Features

Fixes

Chores

v0.7.3

Features

Fixes

v0.7.2

Features

Fixes

v0.7.1

Features

Fixes

Chores

v0.7.0

Features

Fixes

Chores

v0.6.3

Features

Fixes

Chores

v0.6.2

Features

Fixes

v0.6.1

Features

Fixes

Chores

v0.6.0

Features

Fixes

Chores

v0.5.12

v0.5.11

v0.5.10

v0.5.9

v0.5.8

v0.5.7

v0.5.6

v0.5.5

v0.5.4

v0.5.3

v0.5.2

v0.5.1

v0.5.0

v0.4.0

v0.3.0

v0.2.0

v0.1.0