v3.13.0
16 commits since v3.12.0: 10 fix, 4 test, 2 feat. Two feats, so minor not patch.
Read this before upgrading
The first start after this release backfills advert route evidence in the
background, and flood counts read low until it finishes.
#2088 records, per advert, whether it was seen arriving by flood, by direct with
an empty path, or both. New adverts get this at ingest. For the adverts already
in your database, the ingestor runs a one-off background job
(advert_route_evidence_v1) that reads their stored observations. Until it
completes, the Analytics advert split and each node's flood-advert count only
know the adverts it has reached so far, so they undercount.
Measured on two instances of the same deployment, both on a 4-core ARM64 host:
| observations | database | duration | |
|---|---|---|---|
| live | 16.8M | 10.6 GB | 24m 1s |
| staging, sharing the host with live | 16.5M | 10.3 GB | 36m 23s |
The author measured 5m43s on 11M observations on other hardware, so expect a
wide spread.
Startup does not wait for it, and ingest carries on alongside it: on the live
instance the 15 minutes from 13:00, inside the backfill window, stored 2,803
observations against 2,605 to 3,194 in the quarter hours before the deploy.
It runs once per database. Its progress is kept in the database
(advert_evidence_backfill holds the cursors, _async_migrations the status),
so a restart resumes rather than repeats it. There is no setting to skip it.
What it cannot recover: an observation that was overwritten before this release
keeps only its last frame, so some old adverts stay unclassified. The Analytics
page says so under the chart.
Features
- Adverts are split by the route they arrived on (#2088, closes #2041) -
Analytics separates flood adverts from direct adverts with an empty path, and
shows adverts seen both ways as mixed. Node flood-advert counts use the same
evidence. An empty remaining path is labelled as exactly that: the firmware
can forward a direct advert down to an empty path, so it does not prove the
advert was sent zero-hop or from nearby. If writing the evidence fails, the
error is logged and counted and the observation is still stored. - Node detail groups recent adverts the same way (#2085, closes #2073) -
both the side pane and the full page group by the server's classification.
An advert without evidence goes to "other" rather than being guessed from the
first stored frame, which could belong to a different route than later
observations of the same advert.
Paths and packets
- Path hops are resolved with the observer that heard them (#2099, closes
#2097) - a 1-byte hop prefix matches several repeaters. Resolution now uses the
receiving observer's position, and the packets list shows one warning at the
start of a path saying how many of its hops have more than one candidate. The
detail pane keeps a badge on each such hop, tied to its name. - The packets table is compact (#2090) - short columns such as time, size
and hop count are sized to their content instead of a share of the screen, a
grouped row draws one expand arrow, and a Full Names toggle shows observer
and hop names unabbreviated. - Packet links keep the selected observation (#2093, closes #2091) -
changing the type or observer filter no longer drops?obs=from the URL.
Interface
- Channel state survives a channel-list refresh (#2096, closes #2095) -
unread counts, last-message previews and the channels you added with a key
are kept when the region filter or the show-encrypted toggle reloads the list.
Before, every unread count reset and an open key-only channel was closed. - Live accepts node-filter input only once it can process it (#2103, closes
#2094) - typing while the initial node list loaded was silently lost. - Heard By drops a Region column that was always empty (#2077, closes
#2062) - the endpoint never sent that field. - Navigation and channel buttons are one size, 48px (#2078, closes #2052).
- The route sidebar no longer covers Path Inspector candidates (#2082,
closes #2060 and #2081).
Tests, CI and release tooling
- The GitHub release body is these notes (#2076) - v3.10.1, v3.11.0 and
v3.12.0 were published with an empty body. - Four intermittent E2E and server-test failures fixed (#2084, #2087, #2105,
#2109) - #2109 is the Path Inspector failure that turned master red twice on
2026-10-03. - Packets fixture tests are stable, mobile empty states kept (#2080, closes
#2054).
Issues closed
14 issues, from the 16 pull requests in this range. Collected from each pull
request's closing references rather than from commit text.
- #2041 [feat] #/analytics split advert into flood-advert and zero-hop-advert
- #2052 style.css declares .nav-btn and .ch-icon-btn at both 48px and 44px
- #2054 26 wired E2E suites depend on the packets page's 15-minute window surviving the length of the job
- #2060 The E2E fixture's neighbour graph yields no path-inspector candidates, so two assertions cannot run
- #2062 Node detail "Heard By": the Regions line and Region column read a field the endpoint does not emit
- #2073 [feat] node detail, separate flood-adv from zero-hop adv
- #2081 bug(map): route sidebar shifts Leaflet over Path Inspector candidates
- #2083 test(server): node-path regressions race asynchronous index readiness
- #2086 test(e2e): channel WS assertions race initial channel loading
- #2091 Packets: changing the type or observer filter drops ?obs= from a packet detail URL
- #2094 bug(live): node filter accepts input before its handler is ready
- #2095 channels: loadChannels() replaces the channel array and discards all client-only state
- #2097 packets: an ambiguous path hop is shown as a single certain name, resolved without the geographic filter
- #2104 test(packets): observation hex test clicks stale DOM handles
Contributors
Pull request authors: @n30nex (11), @efiten (4), @sylr (1).
No co-authors other than tooling are credited in the commits.
Issues in this release were reported by @efiten (6), @n30nex (5),
@damn-simple-scripts (2), @dborup (1).
@n30nex wrote 11 of the 16 pull requests, including both features. @efiten, the
interim maintainer, wrote 4 and reviewed and merged the rest.
Upgrade notes
No manual migration step. #2088 adds the advert_route_evidence table, created
at boot, and the background backfill described at the top fills it for existing
adverts. It needs no action, only the awareness that flood counts are low until
it finishes.
Nothing is opt-in and no configuration key was added or changed.
What's Changed
- fix(release): publish the release notes as the release body by @efiten in #2076
- test(server): await indexes before node-path regression requests by @n30nex in #2084
- test(channels): isolate WS assertions from initial loading by @n30nex in #2087
- fix(nodes): remove unsupported region fields from Heard By by @n30nex in #2077
- fix(packets): preserve observation selection in detail URLs by @n30nex in #2093
- fix(ui): use consistent 48px navigation and channel buttons by @n30nex in #2078
- fix(packets): stabilize fixture tests and preserve mobile empty states by @n30nex in #2080
- fix(map): keep Path Inspector candidates accessible and cover route replacement by @n30nex in #2082
- fix(packets): pack short columns, one expand arrow, Full Names toggle by @sylr in #2090
- feat(analytics): split adverts using recorded route evidence by @n30nex in #2088
- fix(live): enable node filtering after its handlers are ready by @n30nex in #2103
- fix(channels): keep client-only state across a channel-list refresh (#2095) by @efiten in #2096
- fix(packets): resolve path hops with the observer that heard them (#2097) by @efiten in #2099
- test(packets): verify observation hex after rerenders by @n30nex in #2105
- feat(nodes): group adverts by observed route evidence by @n30nex in #2085
- test(map): wait for the new route sidebar before measuring it by @efiten in #2109
- docs(release): notes and changelog for v3.13.0 by @efiten in #2110
Full Changelog: v3.12.0...v3.13.0