Skip to content

Releases: Kpa-clawbot/CoreScope

CoreScope v3.9.2

13 Jun 04:48
Immutable release. Only release title and notes can be modified.

Choose a tag to compare

Upgrade urgency: Recommended. Big batch of operator-felt wins.

Highlights

Accessibility (#1668 — M2/M3/M4/M5 merged; M6 in flight)

  • Two-tier CSS palette with semantic tokens (--palette-*--color-*/--text-*); operators can now hot-swap theme palettes
  • WCAG AA color-contrast hits across all 22 audited routes — 443 baseline violations → 0 verified by the new axe CI gate (#1696)
  • Typography pass: 14px body / 12px+500 chip floor across the entire chrome (#1679)
  • Hash-cell analytics palette, badge contrast, /live VCR controls (#1681)
  • Audio-lab BPM + Volume sliders now have aria-labels

MQTT observability

  • Per-source MQTT status endpoint + Observers panel (#1682) — connected/disconnected/last-packet/error counters per broker
  • Mobile-friendly: cards at ≤640px instead of squished table (#1698)

Cold-load + analytics correctness

  • Packet-store cold-load actually loads the database now (#1691). Pre-fix: after restart, only 0.3% of DB rows were loaded into RAM, dashboards looked empty for hours. Root cause: hot-load filtered by first_seen (immutable per hash) instead of effective recency. New transmissions.last_seen denormalized column + writer-side update fixes this end-to-end.
  • Analytics endpoint returns 503 Retry-After during warm-up (#1688) — operators no longer see post-restart partial slices
  • Warm-up banner surfaces backfill state in the UI (#1683)

Firmware 1.16 sync

  • Server-side decoder parity for extended ACK payloads (#1695)
  • Customizer toggle to hide 1-byte path hops (collide ~8-way at 2k nodes) — #1689

Performance

  • /packets init parallelizes loadObservers + loadPackets (#1693) — first-row time dropped from 25-40s to <5s on slow links
  • Confidence rating weighted by hash mode (#1687) — 1-byte sightings carry less weight than 6-byte

CI / operability

  • OpenAPI completeness gate (#1678 Phase 1)
  • Release fast-path: re-tag :edge → :vX.Y.Z when SHA matches (#1680) — most patch releases now skip the 30min full pipeline rerun
  • Staging disk monitor + cleanup cron (#1686)
  • Slideover E2E flake-gate reduced 20× → 3×, root cause fixed in #1693

Container image

ghcr.io/kpa-clawbot/corescope:v3.9.2 (multi-arch: amd64, arm64)

Verification

  • 22 routes × 2 themes × 2 viewports automated a11y gate (axe-core, #1696)
  • All 19 PRs ran through the full polish chain (parallel reviewers + Kent Beck TDD gate)
  • Cold-load fix verified by transmissions.last_seen test fixture (#1691)

Operator upgrade (MikroTik)

/container add remote-image=ghcr.io/kpa-clawbot/corescope:v3.9.2 envlist=cs-env mounts=cs-data,cs-caddyfile interface=veth-corescope start-on-boot=yes name=corescope-prod-v392

Acknowledgements

External contributors carry over from v3.9.1.

CoreScope v3.9.1

12 Jun 06:41
Immutable release. Only release title and notes can be modified.
f0addfd

Choose a tag to compare

Upgrade urgency: Recommended — v3.9.1 is what v3.9.0 should have been. v3.9.0's container image never published (Playwright flake gated Docker build). v3.9.1 includes everything in v3.9.0 plus:

  • WCAG AA contrast pass — new two-tier CSS palette (raw --palette-* → semantic --color-*/--text-*); muted-text family bumped to ≥4.5:1 in both themes (most well above — --text-muted on dark surface goes 3.5 → 11.58:1). Operator-reported unknown-repeater chip ("dark-blue text on dark-blue background") fixed (2.75:1 → 4.95:1). Closes #1671. Partial fix for #1668. (#1676, f0addfd)
  • Slideover test stabilitytest-slideover-1056-e2e.js was racing the packets virtual-scroll spacer; tightened selectors, bumped data-row wait to 20s. Cleared the day-of-release CI flakes. Fixes #1662. (#1663+followups, f06359d)

Verification

Test plan: workspace-meshcore/test-plans/v3.9.0-cdp-test-plan.md (93 tests, applies unchanged to v3.9.1).
M1 a11y audit: workspace-meshcore/a11y-audit/reports/violations-summary.md (2,429 BLOCKER → estimated 85% cleared by M2).

Acknowledgements

External contributors from v3.9.0 still apply: @efiten, @EldoonNemar. No new external PRs since v3.9.0.

CoreScope v3.9.0

12 Jun 02:55
Immutable release. Only release title and notes can be modified.

Choose a tag to compare

Upgrade urgency: Medium — fixes the post-restart "relay timelines empty" regression, surfaces silent /api/nodes truncation, and ships operator-controlled per-name hiding.

257 commits since v3.8.3 (72 substantive + 185 auto-generated coverage bumps). Every bullet ends with a commit SHA — git show <sha> to verify.

Highlights

  • Your relay timelines survive a restart. Before v3.9.0, every container restart left repeater nodes with empty hop histories until live traffic replayed enough adverts to re-attribute. Now the relay-hop index is rebuilt from path_json during cold load — per-relay timelines, hop counts, and route stats are intact the moment the server says it's ready. (#1643, 938153d)
  • /api/nodes stops silently truncating at 500 rows. The hard cap was hiding nodes from the map, analytics and packets pages on any mesh of meaningful size — without any warning. Now properly paginated across every consumer, with internal UI requests bypassing the per-page clamp. (#1607, 2610574; #1637, 9002b25; #1589, 7421ead)
  • Hide your own node from a public dashboard with a prefix rename. New hiddenNamePrefixes config (default ["🚫"]) drops matching nodes from /api/nodes* while keeping DB rows for analytics — same convention other MeshCore dashboards already follow, no DB surgery, no permanent loss of history. (#1655, 825b264)
  • Observer Compare is finally discoverable. The compare page existed before but was a hidden URL trick; now there are three entry points (header CTA, sticky selector strip, observer-table multi-select) leading into a Tufte-grade compare view with state-preserving selection. (#1642, 531bc8a; #1645, c93ae67; #1647, 167af54)
  • Per-node Reach. New /api/nodes/{pubkey}/reach + UI surfaces directional link quality per neighbor — answers "is my link to X any good in both directions" without staring at a topology graph. (#1627, e2212f5)

What's New

Observer Compare

  • Promote observer comparison to first-class: header CTA, sticky selector strip, observer-table multi-select. (#1642, 531bc8a)
  • Tufte-grade compare page with themed button vocabulary + state-preserving multi-select across navigations. (#1645, c93ae67)
  • Polish: tightened checkboxes, hierarchy, selector strip + mobile fixes. (#1647, 167af54)
  • Wire TableSort on the observers table with numeric/time column types so the sort affordance actually sorts. (#1641, d72ab69)

Reach & Nodes

  • Per-node Reach page + GET /api/nodes/{pubkey}/reach (directional link quality). (#1627, e2212f5)
  • Paginate /api/nodes across map/live/analytics/packets/area-map so the 500-row server cap stops silently truncating UIs. (#1607, 2610574; #1637, 9002b25)
  • Sortable First Seen column on the Nodes table. (#1587, 7533b3b)
  • Firmware repeat:on|off hint now excludes listener-only observers from the disambiguator. (#1624, a477655)
  • Link RTC-reset warnings on node detail to the offending packet hashes. (#1590, 1a2b8c4)

Analytics

  • Relay Airtime Share endpoint + dumbbell chart. (#1601, 3898688)
  • 5-minute rolling-baseline anomaly detection for Write Sources. (#1593, a26a412)
  • TRACE packets overlay per-hop SNR on the path graph. (#1622, e9aed64)
  • Multi-byte prefix repeaters now show up in the 1-byte hash-usage matrix view. (#1591, 3df8924)

Live & Map

  • Fullscreen toggle on the live map + controls collapsed by default. (#1572, d7bd9d5)
  • Colorblind simulation overlay (Brettel/Vienot) with reset-to-Wong button. (#1600, 571c960)
  • Path symbols legend disclosure on packets. (#1570, 5fd8900)
  • OSM / Stamen tile providers with per-provider Leaflet layer control. (#1533, d7cd920)
  • Operator-configurable liveMap.maxNodes (default 2000). (#1577, 1bdb92d)

Config & Operator Surfaces

  • hiddenNamePrefixes (default ["🚫"]) — drop matching nodes from /api/nodes* while preserving DB rows. (#1655, 825b264)
  • Config-driven disabled-tabs list in the customizer modal. (#1579, 7292d60)
  • branding.homeUrl override for embedded deployments. (#1576, 9b36b7c)
  • Configurable observer-health thresholds. (#1556, 65bd954)
  • Detect CDN-fronted deployment + document bypass requirement. (#1564, 63bfa3d)
  • Expose --nav-active-bg as a themeable token. (#1571, 892eb2c)

Performance

  • Chunked Load with early HTTP readiness — server accepts requests while heavy load completes in the background. (#1596, bc1822e)
  • Background subpath + pathHop index builds with ready gates. (#1604, df61660)
  • Lazy distance-index build on first request. (#1597, 5629a48)
  • neighbor_api: fold first_seen into cached map — fixes the #1627 r3 regression. (#1632, 078225a)
  • GOMEMLIMIT via runtime.maxMemoryMB in server + ingestor. (#1595, 1b112f0)
  • SQLite writer-lock wait/hold instrumentation per component. (#1594, 222bfdf)

Bug Fixes

Ingestor

  • Subscribe to MQTT before startup maintenance; buffer until the writer is free. (#1609, 18810b5)
  • Decode firmware 1.16.0 extended ACK (5/6-byte payloads). (#1618, 9612f08)
  • Write resolved_path on new observations (regression from #1289). (#1548, 3feb97f)
  • Defense-in-depth empty-scope guard in UpdateNodeDefaultScope. (#1575, cd19285)
  • Skip default_scope update when ScopeName is empty. (#1569, 05af6c6)
  • Address #1609 follow-up findings — config doc, receipt-time liveness, buffer stop/clamp warn. (#1623, 3d12266)

Reach

  • Bust response cache on blacklist change. (#1636, 8295c21)
  • scanReachRows DB errors must surface as 500, not 404. (#1635, 43be1bb)
  • Narrow-viewport CSS — no horizontal scroll, map no longer shrunken. (#1634, 59d6646)

Frontend / UI

  • Render analytics Channels group-header sprites as HTML, not escaped text. (#1658, fb6bb08)
  • Bump feed-detail-card z-index + make popup draggable. (#1620, f66ff40)
  • Theme-track .vcr-scope-btn.active + .copy-link-btn:hover backgrounds. (#1578, 16c7ea4)
  • Replay handoff no longer freezes the map (suppressLive flag). (#1603, 1f65d78)
  • Detach slide-over panel on close — architectural focus-restore fix + --repeat-each=20 CI gate. (#1617, 37a7a92)
  • getTileUrl() now invokes function-typed provider URLs + regression tests. (#1615, dc433e4)
  • Reliably restore row focus on panel close. (#1602, 1be0aec)
  • Gesture hints — edge-drawer mobile-only + row-swipe widening (re-fix). (#1586, 116efe4)
  • Honor time-window filter on Route Patterns analytics. (#1592, d6384c3)
  • Live corner-cycle button clears drag state. (#1568, 2b45f78)
  • Observers aggregate header shows "Last updated" timestamp. (#1563, a7ad2be)
  • Mirror Load's resolved_path indexing into loadChunk. (#1582, 9465949)
  • Remove dead server-side backfill flag (stuck backfilling=true). (#1583, f7571a2)
  • Additional follow-up fixes for #1532. (#1580, 373ee81)
  • Document writeStatsAtomic symlink-replace semantics + regression test. (#1588, af66943)

API

  • Bypass API limit clamps for internal UI requests (revisit of #1540). (#1589, 7421ead)
  • Emit Cache-Control: no-store on /api/* responses. (#1553, 0c908d2)

Performance

  • Chunked Load early-readiness, background index builds, lazy distance index, cached first_seen, GOMEMLIMIT honored, writer-lock instrumentation — see "Performance" under What's New.

Security

  • Detect CDN-fronted deployment and document the bypass requirement so rate limits and PoW gates can't be silently routed around. (#1564, 63bfa3d)

Breaking changes

None.

Operator-facing changes / config

New config (config.example.json, all opt-in, safe defaults):

  • hiddenNamePrefixes: ["🚫"] — node-name prefixes that hide a node from /api/nodes, /api/nodes/search, /api/nodes/{pubkey}. DB rows preserved; analytics history intact. Mirrors the convention used by other MeshCore map dashboards. Opt out with []. (#1655, 825b264)
  • liveMap.maxNodes: 2000 — cap nodes rendered on the live map; raise for big meshes, lower for low-power dashboards. (#1577, 1bdb92d)
  • runtime.maxMemoryMB — sets GOMEMLIMIT for server + ingestor; tune against container limits. (#1595, 1b112f0)
  • Observer-health thresholds — previously hard-coded, now configurable. (#1556, 65bd954)
  • branding.homeUrl — override the "Home" link target for embedded deployments. (#1576, 9b36b7c)
  • Customizer disabled-tabs — config-driven hide list. (#1579, 7292d60)

Behavior changes:

  • /api/nodes paginates instead of silently truncating at the 500-row cap; internal UI requests bypass the clamp. (#1607, 2610574; #1589, 7421ead)
  • /api/* responses now emit Cache-Control: no-store. (#1553, 0c908d2)
  • Per-node Reach available at GET /api/nodes/{pubkey}/reach. (#1627, e2212f5)
  • Hashtag channels from meshcore-channels catalogue appear in the channels list without manual config. (#1656, e04c711)

Behind the scenes

  • Emoji → Phosphor migration (six PRs). M1 top-nav/mobile-nav/Compare (#1649, 55e4d95) · M2 page headers + table chrome (#1650, 3062745) · M3 detail panes + badges (#1651, b812a98) · M4 map + route overlays (#1652, 2b6809c) · M5 settings + customize (#1653, 1116801) · M6 final sweep + lint gate + carry-forwards (#1654, 89eade6). Tracking: #1648.
  • CI: bump go test timeout 10m → 15m (suite grew past 10m post-#1655). (#1661, 0712c5f)
  • Test: tighten slideover row selector to avoid the virtual-scroll spacer race. (#1663, 037dc8c)
  • Test: subpaths_window tests wait for index readiness after the #1595 chunked load. (#1621, ad41b9b)
  • Test: mock /api/nodes/search in home-coverage E2E (closes #1313). (#1584, 6a027b0)
  • Refactor: extract pure helpers into route-view-utils.js. (#1581, 545013d)

Verification

Test plan: workspace-meshcore/test-plans/v3.9.0-cdp-test-plan.md (93 tests across 16 sections)

Initial run (master pre-#1665, 2026-06-12 00:45 UTC): 56 pass / 22 partial / 5 fail / 14 skipped. Two BLOCKER lint-gate breaches surfaced — .obs-clock-naive-chip (#v384-1.2, 14× ⚠️) and analytics Channels encrypted labels (#v384-12....

Read more

CoreScope v3.8.3

04 Jun 01:49
Immutable release. Only release title and notes can be modified.
e4a21fc

Choose a tag to compare

CoreScope v3.8.3

Upgrade urgency: High — contains a stored XSS fix. Public dashboards should upgrade immediately.

187 commits since v3.8.2 (47 substantive + 140 auto-generated coverage bumps). Every bullet ends with a commit SHA — git show <sha> to verify.

Highlights

  • The live map is buttery now. Packet animations and node pulses moved off SVG-per-frame onto a hardware-accelerated canvas overlay — 60 FPS even when the mesh is firing on all cylinders. (#1490, 914f869; #1521, 75a38f0)
  • Dashboards and APIs feel snappier under load. /api/observers p95 dropped from ~10.8s to sub-second on busy meshes, /api/stats is no longer re-scanning the observations table every 15s for the navbar, and per-observer analytics stopped re-parsing every timestamp three times. (#1483, 13bdee5; #1516, 3850600)
  • Stored XSS class closed — same class as CVE-2026-45323. Mesh-advertised node names and observer names were rendered to the DOM unescaped on app/nodes/observers/packets/live/analytics/route-view/area-map; a payload like <img src=x onerror=…> executed. All sinks now escape; follow-up audits closed three more XSS sinks, an unbounded-limit DoS, and several log-injection paths. New CI gate hard-fails PRs that reintroduce either class. (#1537, f15b677; #1539, 53339e0; #1540, 800d61c; #1544, 7b43045; #1543, e4a21fc)
  • Cross-domain embeds. ?embed=1 on /#/map and /#/channels strips the chrome, and a new CORS_ALLOWED_ORIGINS env unlocks Home Assistant / Grafana panel embeds. (#1500, 367265e)
  • The map's region filter now actually filters the map. Selecting a region hides non-region nodes by default; a "Show all nodes" toggle preserves the old behavior. (#1501, 28713fa)
  • Observers with broken clocks now name themselves. Observers emitting zone-less timestamps get a ⚠️ chip on the observer list and a banner on detail with fix instructions — no more "why is this observer showing 1970?" support tickets. (#1480, 43b93c6)
  • Operators with big DBs no longer wait minutes for ingestor startup. Heavy index builds run in the background via a new async-migration runner; the ingestor accepts packets immediately on boot. (#1541, e438451)
  • Fresh deploys can decrypt #Public out of the box. Default Public channel key now ships in channel-rainbow.json. (#897, 451b5e8)
Stored-XSS sink list (for security verification)

HTML-escaped at: app.js global search dropdown (node + channel name); nodes.js table row + Leaflet popups (×2); observers.js table name cell; packets.js observer-name cells (×4) + multi-select checkbox label; live.js node-filter <option> + map tooltip + hop popup; analytics.js topology tooltip + RF-health aria-label; packets.js CHAN hex decode fields; route-view.js hop + union tooltips (×2); area-map.html node popups (×2). Global escapeHtml now covers the full 5-char OWASP set (& < > " '). map.js safeEsc was a no-op identity since #48 — now wired to the real escaper. Backend sanitizeName() deliberately keeps < > " & for lossless storage / meshcore:// deep-links; fix is at the sink per OWASP. Round-2 sweep added: traces.js URL-fragment in popups, observer-detail.js MQTT-meta tooltip, analytics.js RF-health aria-label. Pinned by test-xss-escape-sinks.js and test-anl1-tooltip-render.js with tag-injection and attribute-breakout payloads. (#1537, #1539)

Features

  • Hide non-region nodes by default on the live map when a region is selected; "Show all nodes" toggle restores legacy view; state in localStorage['mc-region-show-all-nodes']. Fixes #1108. (#1501, 28713fa)
  • ?embed=1 on /#/map or /#/channels suppresses top-nav, bottom-nav, drawer; new corsAllowedOrigins config + CORS_ALLOWED_ORIGINS env; Access-Control-Allow-Methods tightened to GET, HEAD, OPTIONS. Fixes #1369. (#1500, 367265e)
  • Customizer: marker stroke color/width/opacity tunable via Colors → Marker Stroke; backed by --mc-marker-stroke-* CSS vars + markerStroke config block. Fixes #1488. (#1494, ca2c3d6)
  • Observers: "⚠️ Naive clock" chip on the observer list + banner on detail; backed by observers_clock_naive_v1 migration. Fixes #1478. (#1480, 43b93c6)

Fixes (selected)

  • Live page mobile: filter dropdowns no longer clipped by the scrolling toggle bar; settings cog pushed right. Fixes #1529. (#1531, 99cea7b)
  • Live nav-pin: 📌 button moved into .nav-right so it stops squeezing search/theme/hamburger. Fixes #1526. (0273f15)
  • Live: requestAnimationFrame dt clamped to 32ms — no more 8× fast-forward when a backgrounded tab wakes. (#1524, 3e4c456); VCR speed no longer leaks into live mode. Fixes #1346. (#1427, b71b26a)
  • Live: animations restored to a custom Leaflet pane (z=650) — were painting behind markers since #1334. Fixes #1485. (#1491, 268751f)
  • Live canvas follow-up: DPR listener {once:true}, scratch buffers hoisted, whitespace churn reverted. Fixes #1514. (#1520, bf8bb87)
  • Channels: selectChannel() / refreshMessages() no longer stomp WS-pushed messages during the REST replacement window — real production bug. Fixes #1498. (#1513, c9b98cb)
  • Marker stroke: server defaults restored to v3.7.2 visual after #1494's translucent default looked weak on upgrade. Fixes #1506. (#1507, a7b156d)
  • Customizer "🗑️ Reset All" now actually clears everything (CB preset, encrypted-channel toggle, dark-tile pick, marker-stroke vars, per-role writes). Fixes #1496. (#1497, 9bed0e8)
  • Packets: collapse chevron on grouped rows no longer reopens a just-closed detail panel. Fixes #1486. (#1492, 7fcb226); HB column uses getPathLenOffset(route_type) (TRANSPORT path_len is at offset 5). Fixes #1469. (d4280be)
  • Nodes dark mode: --card-bg aligned with --surface-2 — was washed-out. Fixes #1470. (#1517, 24a840d)
  • BYOP modal header no longer occludes body content on mobile. Fixes #1487. (#1493, c841dbc)
  • Trace tool: validated hash written back via history.replaceState, so #/tools/trace/<hash> is shareable. Fixes #1522. (#1523, 73ceb47)
  • Ingestor: readProcSelfIO() stops stamping time.Now() before os.Open — eliminates phantom rate spikes after transient failures. Fixes #1169. (#1428, 196f1c6)
  • Ingestor: per-message naive-timestamp warning silenced; observer.last_seen and per-packet rxTime already clamped. (#1479, 0a58aa1)
  • Version/commit badge moved from navbar to a Version card on /#/perf. (#1503, 788a509)
  • Mobile nav follow-ups (#1471 series): duplicate .filter-toggle-btn hidden so navbar mirror is the only visible affordance (#1475 f0da38f, #1482 b6e0050); More-sheet mirrors re-injected on each open via click delegate (#1476, 497e419).
  • Live: "ghost" hops renamed to "inferred". Partial fix for #1505. (#1527, deafe32)
  • Live: nav-pin state persisted in localStorage['live-nav-pinned']. Fixes #1510. (#1515, 878d162)

Upgrade Notes

New config (config.example.json, all opt-in, safe defaults):

  • corsAllowedOrigins: [] — cross-origin allowlist for embed (#1369). Env: CORS_ALLOWED_ORIGINS (comma-separated).
  • markerStroke: { color: "#fff", width: 2, opacity: 1 } — v3.7.2-matching defaults (#1488/#1506).
  • neighborGraph.cacheRecomputeIntervalSeconds: 300 (#1483).
  • observersCache.ttlSeconds: 30 (#1483).

Auto-applied migrations:

  • observers_clock_naive_v1clock_skew_seconds, clock_skew_count_24h, clock_last_naive_at on observers (#1480).
  • obs_observer_ts_idx_v1 — composite (observer_idx, timestamp) index on observations, runs async via the new RunAsyncMigration helper; ingestor accepts packets while it builds (#1483/#1541). State tracked in _async_migrations; idempotent across restarts.

Behavior changes:

  • Live map: selecting a region hides non-region nodes by default. Toggle "Show all nodes" once to opt out (persists in localStorage). (#1501)
  • Access-Control-Allow-Methods no longer advertises POST — cross-origin writes fail preflight by design; same-origin admin writes unaffected. (#1500)
  • List endpoints silently clamp limit to 500 (lists) / 200 (analytics, bulk-health). Requests over the cap return the cap. (#1540)
  • Version badge lives on /#/perf now, not the navbar. (#1503)

No breaking config removals or deprecations.

Acknowledgements

  • @mxsasha (Sasha Romijn) — responsible disclosure of the stored XSS in #1536.
  • @efiten — audit and fix across all unescaped sinks in #1537.

Tagging

git tag -a v3.8.3 e4a21fc9 -m "v3.8.3"

v3.8.2 — Mobile UX, Customizer, Performance

29 May 02:50
Immutable release. Only release title and notes can be modified.
93b2f4b

Choose a tag to compare

v3.8.2 — Mobile UX, Customizer, Performance

(Draft for operator review. ~3 weeks of work since v3.8.1, ~25 substantive commits.)

Headliners

  • Mobile UX overhaul — packets surface redesigned mobile-first with single-row navbar, semantic-first detail panel, hidden chrome rail; nav controls (Favorites/Search/Customize) finally reachable on phones (#1471 — closes #1415/#1458/#1461/#1467/#1468/#1470).
  • Customizer reframe — CB preset is now an end-user OPT-IN, not a force-override. Operator's config.json nodeColors are honored by default; per-user customizer override beats the preset (#1446/#1447/#1448/#1449 — fixes longstanding "config not honored" reports).
  • Dark-tile provider picker — 4 dark map variants pickable in customizer: Carto Dark, Esri Dark Gray, Voyager Inverted, Positron Inverted (#1420/#1430). Honored across all map surfaces including node-detail inset (#1470).
  • Observer timestamps fixed — California (UTC-7) observers were perpetually 7h stale because naive timestamps were treated as UTC. Now: observer.last_seen always uses ingest time, per-packet rxTime keeps envelope time with symmetric clamp (#1463/#1464/#1465/#1466).
  • Cold-path cache/api/nodes no longer blocks on stale-cache rebuild; serves stale-while-revalidate (#1272/#1436).

Operator-facing changes

UI / UX

  • New customizer toggle: Show encrypted channels (default OFF — finally a way to control the encrypted-channel flood without DevTools) (#1454/#1455)
  • Traffic share label replaces the misleading "Usefulness" score (renamed everywhere; new traffic_share_score JSON field added alongside the legacy usefulness_score for API compat). Tooltips explain both Traffic share and Bridge score with tap-to-toast on mobile (#1456/#1457)
  • Custom navbar logos no longer squished to 125×36 — proportional aspect preserved for square, tall, wide variants (#1450/#1451)
  • Per-role color overrides now actually propagate to marker SVGs (was silently dropped before — #1438/#1439/#1441/#1443)
  • "unknown" fake channel no longer accumulates in the channel list (live router was synthesizing it from undecryptable CHAN messages — #1468)
  • Hash matrix marks 0x00 and 0xFF as reserved prefixes per MeshCore firmware keygen convention (@halo779 report — #1473/#1474)
  • Mobile gesture hints — touch-only gate added (no longer show on desktop), width:fit-content fix for off-screen pills (#1065 chain)

Server / Performance

  • repeaterEnrichTTL cache cold-path now stale-while-revalidate; first request after expiry no longer blocks (#1272/#1436)
  • Hourly SQLite WAL checkpoint prevents unbounded WAL growth (#1435)
  • Startup warning when GOMEMLIMIT < 50% of container memory limit — prevents future OOMs (#1264/#1429)
  • WebSocket MQTT broker support (ws:// / wss://) documented + tested (#902)
  • Paths-through-node now sorted by recency (LastSeen DESC) with count as tiebreaker — was non-deterministic map iteration order (#1145/#1431)

Bug fixes

  • Naive (zone-less) ISO timestamps in MQTT envelopes now symmetrically clamped (was: only future-skew rejected, past-skew passed through verbatim — California observers perpetually stale) (#1463/#1464)
  • Observer.last_seen always uses ingest time, never envelope time (architectural cleanup, eliminates whole class of TZ bugs) (#1465/#1466)
  • Hop-name mis-resolution on prefix collision — regression test added for #1144 (the production fix shipped earlier; this guards against re-introduction) (#1433)
  • Channel-color-picker outside-click E2E flake fixed for real this time (race with setTimeout(0) listener install — proper fix using rAF×2 + retry) (#1462)
  • CI: master runs no longer cancelled by subsequent commits (was dropping Deploy Staging silently — #1395/#1426)
  • CSS parse-error: stray non-comment text after #1062 block was eating the next CSS rule from CSSOM (gesture-hint .width:fit-content wasn't taking effect for weeks) (#1065/#1453)

Community contributions this cycle

  • @efiten#1145 paths sort, #1264 GOMEMLIMIT warning, #1272 cold-path cache, #902 WS MQTT docs, #1395 CI concurrency fix, WAL checkpoint
  • @halo779#1473 reserved-prefix report (your in-game testing flagged the firmware convention CoreScope was ignoring)

Thanks 🙏

Known issues / follow-ups

Resolved from v3.8.1's known-issues list:

  • ✅ CB preset switching now applies everywhere without reload (#1446 reframe + cascade fix)
  • ✅ Customizer (🎨) reachable on mobile portrait via bottom-nav More sheet (#1467, no more rotate-to-landscape workaround)

Still pending from v3.8.1 (carried forward):

  • Mobile route view auto-fit can briefly overshoot on iOS Safari URL bar collapse
  • Sidebar drag-resize doesn't persist when localStorage is blocked
  • "Scan QR" for PSK channel not yet functional
  • Analytics → Distance tab still launches the route map via legacy sessionStorage flow (not deep-link)

New in v3.8.2:

  • Node-detail card backgrounds are technically dark but visually close to page bg (#1470 deferred — operator's call: ship or revisit)
  • Group-header rows in /packets render 200-700px tall in some cases (existing grouping behavior, not new this cycle)

Upgrade notes

  • Frontend cache-bust automatic via __BUST__ token
  • Backend image: ghcr.io/kpa-clawbot/corescope:v3.8.2 (will tag on release)
  • No config migration required
  • New traffic_share_score field appears in /api/nodes and /api/nodes/{pk} responses alongside existing usefulness_score — no breaking change

v3.8.1 — Route, Refined

27 May 08:29
Immutable release. Only release title and notes can be modified.
f0c69d5

Choose a tag to compare

CoreScope v3.8.1 — Route, Refined

Released 2026-05-27. Previous: v3.7.2 (2026-05-06). Supersedes v3.8.0 (released earlier today, before this perf fix landed).

⚡ Patch in v3.8.1: /api/nodes TTL fix

Community contribution from @efiten (#1425). The repeaterEnrichTTL was 15 seconds but the background recomputer runs every 5 minutes — so the cache was stale for 4m45s out of every 5min. On dense hop-graph deployments that meant 18s /api/nodes cold-miss responses. TTL is now derived as 2 * recomputer interval so the cache stays warm between ticks. Measured 18.6s → ~0.5s on the contributor's prod mesh (analyzer.on8ar.eu).

If you already deployed v3.8.0, just upgrade to v3.8.1 — same image semantics, drop-in.


Three weeks, 135 merged PRs. The headline is the Route Viewer redesign — packets and the paths they travel, finally rendered as one coherent story. Underneath: startup-window improvements for large DBs, a near-complete mobile chrome overhaul.


🗺️ NEW: Route Viewer

The new route viewer (route-view.js + route-view.css) puts packet context, observer paths, and resolved hops in one sidebar — and reflows cleanly to a bottom sheet on mobile.

  • Packet context block in the sidebar header — per-type fact list (ADVERT name/role/sig/pubkey, DM src→dst with encryption state, GRP_TXT channel + decrypted preview, TRACE official-vs-observed hops, PATH src→dst with payload-source chips). Merges pkt.decoded_json + obs.decoded_json and falls back to byte-level raw_hex parsing for encrypted DMs.
  • Multi-path picker — chip per unique observer-path (<count>/<total> + hex hop string). Click to isolate; "All" renders an edge-deduplicated UNION view (each unique edge once, stroke weight = observer count).
  • Deep-link URLs#/map?packet=<hash>&obs=<id>. Bookmarkable, shareable, single source of truth. sessionStorage flow removed.
  • Hop resolution priority chain — server resolved_path → shared HopResolver (observer-IATA-aware, same as packets page) → raw prefix. Kills a whole class of "route view named hops differently than packet detail" bugs.
  • Markers — uniform 22 px filled circle with seq number inside, hollow endpoint ring for SRC/DST, double concentric ring on SRC=DST loops, spider-fan for sub-14 px collisions debounced to zoomend.
  • Colorblind-preset live colorsrouteRamp per preset (viridis / plasma / pure-luminance) written to --mc-rt-ramp-0..4 CSS vars and hot-recoloured on cb-preset-changed / theme-changed.
  • Desktop chrome — drag-to-resize sidebar persisted to localStorage, Material/Drive-style collapse chevron centred on the right edge.
  • Mobile bottom sheet — anchored above bottom-nav + safe-area inset, thin summary line when collapsed (TYPE · N hops · X km · M obs), expands to ~75 vh. All three legacy mobile detail panels closed on route entry.

Closes: #1418, #1419, #1422 · PR #1423

Related map work that landed this cycle: role-aware marker shapes + outline rings (#1334), WCAG 2.2 AA pass on cluster bubbles + role pills + multi-byte labels (#1357), thinner always-on marker outline (#1347).


⚡ Startup

  • Hot startup window — new packetStore.hotStartupHours config loads only N hours of packet history synchronously and fills the rest in background daily chunks. Large DBs (multi-GB) no longer block the HTTP listener on a full-retention load before serving traffic (#1187).
  • Ingestor now owns the neighbor-graph and all schema migrations; the server is read-only. Removes a class of startup races where two processes raced the same migration (#1286, #1289).

🔬 NEW: Protocol decoder coverage

The MeshCore decoder now handles every documented payload type, with the legend updated end-to-end so operators see real names instead of Type 6.

  • GRP_DATA + MULTIPART wire-format decoded (#1280) — group-data sensor payloads + multipart fragmentation are no longer opaque blobs.
  • CONTROL flags + advertRole fix — accurate role attribution on ADVERTs from edge cases that were previously misclassified (#1280).
  • payloadTypeNames table centralised, exposed at the API + UI; new TransportCodes / Feat1 / Feat2 enums; RAW_CUSTOM type plumbed through; sensor-payload docs published (#1291).

🆕 NEW: Operator features

  • Repeater "usefulness score" (bridge axis) — second of four planned ranking dimensions for how much a repeater is structurally necessary to mesh connectivity (#1275, #672 axis 2/4).
  • Area-based visual node filter — define GPS polygons in config; attribute and filter packets by transmitter location across nodes/packets/map/live/analytics (#839).
  • Scoped vs unscoped transport-route statistics — per-region HMAC slicing of route stats; mirrors the existing hashChannels pattern (#915).
  • Sortable Scope column on the Nodes list (#1195).
  • Observer IATA badges on packets, with new filter grammar to slice by observer location (#1189).
  • Multi-byte hash capability is now persisted across restart with O(1) per-key lookup; operator-friendly capability badge surfaces it in the UI (#1324).
  • Material Design dark mode — properly polished pass (closes #893, #1389). Primary surface set, contrast, button + chip + form-control restyle.
  • Colorblind presets in the theme customizer — Wong / Deuteranopia-tuned / Plasma / Achromat ramps, applied to roles + multi-byte tiers + (in this release) the new route viewer's sequence ramp (#1378, #1408, #1414, #1407).
  • Mobile gesture system — swipe rows for actions, swipe tabs to switch sections, slide-over dismiss (#1185); edge-swipe to open the nav drawer (#1184); first-visit hints so the gestures are discoverable (#1186).
  • New CoreScope logo + Aldrich webfont (#1137, #1138).

🐛 Bug Fixes

Protocol / Ingest

  • MQTT decode no longer panics on malformed path length — bounds check prevents slice [218:15] panic (#1214).
  • MQTT half-open TCP recovery — watchdog forces paho reconnect on stall (#1336); per-attempt logging surfaces silent reconnect-loop death (#1216).
  • Ingest-time vs observer time — ingestor stamps server now() for packet/observation storage; reverted earlier envelope-timestamp path that was driving counters wrong (#1233, #1372).
  • Hop disambiguator quality — source-diversity confidence weighting in tier-1 resolver (#1235), hop-context + observation-count tiebreak (#1198), 6 deferred quality items (#1200).
  • Geo-implausible edges rejected at neighbor-graph build time (#1230).
  • Clock-skew robustness — RTC-reset outliers excluded from hash median + recent-bad count (#1288).
  • Canonical resolved_path everywhere — /api/nodes/{pk}/paths (#1282) and paths-through resolver (#1353) now use the persisted resolved path instead of naive prefix matching; fixes wrong-node attribution.
  • Structural pubkey attribution via new from_pubkey column (#1152).
  • dbschema startup race fixed by giving optional-column migrations a canonical source (#1322).

UI / Channels / Packets

  • Channels page — chat-app redesign restores prod row layout + detail view (#1376); shows latest message time, not first-seen (#1368); drops ghost "unknown" bucket for encrypted-no-key packets (#1377); stops force-enabling "show encrypted" on every init (#1410); mobile UX overhaul (#1227).
  • Packets page — orders by ingest id rather than rxTime so fresh activity is actually visible (#1349); observer IATA shown on packets with new filter grammar (#1189).
  • Scopes tab — fixed JSON.parse by dropping duplicate /api prefix in scope-stats fetch path (#1379).
  • Live region filter no longer wipes the feed — correctly parses {observers:[...]} response shape (#1140).
  • Prefix Tool Network Overview shows configured-hash-size counts, not math-only slices (#1271).
  • CustomizernodeColors stopped force-overriding ROLE_COLORS so CB presets actually propagate (#1408, #1414).
  • Node detail full-page renders error state on 404 instead of silent blank (#1158); restored WCAG AA contrast on "Paths Through" links in dark mode (#1159); section reorder puts Recent Packets above Paths (#1160); dropped orphan separators from "Heard By" rows (#1161).

🎨 UI / UX Polish

  • Material Design dark-mode polish (#1389, closes #893) — primary surface set, contrast pass, button + chip + form-control restyle.
  • Customizer — live preview pane mirroring map / nodes / packets (#1408 deps), per-preset WCAG validator on save (#1407 chain).
  • Multi-byte hash UI — capability badge with operator-friendly tooltip (#1324), config-driven counts everywhere (#1271).
  • Nodes page — neighbor-aware reference-node selector (#1389 chain), geo/role/hash-size filter URL params survive reloads.
  • Live page — reconnect indicator + last-event-ago badge.
  • Theme — operator-customizable accent + role colors via single JSON file, shared across map / nodes / packets / live / channels.

🔧 Operator & Infra

  • New config keys (see Upgrade notes for full list): packetStore.hotStartupHours, compression.gzip, compression.websocket, areas, hashRegions.
  • Compression — opt-in HTTP gzip + WebSocket permessage-deflate, both default-off (#934).
  • Area-based filters — define GPS polygons in config; surfaces an Area: selector across analytics / nodes / packets / map / live (#839).
  • Scoped transport-route statshashRegions HMAC mirrors the hashChannels pattern, lets operators slice transport-route metrics by region (#915).
  • /api/perf/io — exposes cancelledWriteBytesPerSec from /proc/self/io plus ingestor side (#1167).
  • Ingestor/server architectural split — neighbor-graph + schema migrations are now ingestor-owned (#1286, #1289); see Upgrade notes.
  • /#/perf page — parallel health fetch + sort + auto...
Read more

v3.8.0 — Route, Refined (superseded by v3.8.1)

27 May 08:11
Immutable release. Only release title and notes can be modified.
77d1925

Choose a tag to compare

⚠️ Superseded by v3.8.1 — released the same day with a community-contributed /api/nodes TTL fix (#1425, @efiten). Use v3.8.1 instead.


CoreScope v3.8.0 — Route, Refined

Released 2026-05-27. Previous: v3.7.2 (2026-05-06).

Three weeks, 135 merged PRs. The headline is the Route Viewer redesign — packets and the paths they travel, finally rendered as one coherent story. Underneath: startup-window improvements for large DBs, a near-complete mobile chrome overhaul.


🗺️ NEW: Route Viewer

The new route viewer (route-view.js + route-view.css) puts packet context, observer paths, and resolved hops in one sidebar — and reflows cleanly to a bottom sheet on mobile.

  • Packet context block in the sidebar header — per-type fact list (ADVERT name/role/sig/pubkey, DM src→dst with encryption state, GRP_TXT channel + decrypted preview, TRACE official-vs-observed hops, PATH src→dst with payload-source chips). Merges pkt.decoded_json + obs.decoded_json and falls back to byte-level raw_hex parsing for encrypted DMs.
  • Multi-path picker — chip per unique observer-path (<count>/<total> + hex hop string). Click to isolate; "All" renders an edge-deduplicated UNION view (each unique edge once, stroke weight = observer count).
  • Deep-link URLs#/map?packet=<hash>&obs=<id>. Bookmarkable, shareable, single source of truth. sessionStorage flow removed.
  • Hop resolution priority chain — server resolved_path → shared HopResolver (observer-IATA-aware, same as packets page) → raw prefix. Kills a whole class of "route view named hops differently than packet detail" bugs.
  • Markers — uniform 22 px filled circle with seq number inside, hollow endpoint ring for SRC/DST, double concentric ring on SRC=DST loops, spider-fan for sub-14 px collisions debounced to zoomend.
  • Colorblind-preset live colorsrouteRamp per preset (viridis / plasma / pure-luminance) written to --mc-rt-ramp-0..4 CSS vars and hot-recoloured on cb-preset-changed / theme-changed.
  • Desktop chrome — drag-to-resize sidebar persisted to localStorage, Material/Drive-style collapse chevron centred on the right edge.
  • Mobile bottom sheet — anchored above bottom-nav + safe-area inset, thin summary line when collapsed (TYPE · N hops · X km · M obs), expands to ~75 vh. All three legacy mobile detail panels closed on route entry.

Closes: #1418, #1419, #1422 · PR #1423

Related map work that landed this cycle: role-aware marker shapes + outline rings (#1334), WCAG 2.2 AA pass on cluster bubbles + role pills + multi-byte labels (#1357), thinner always-on marker outline (#1347).


⚡ Startup

  • Hot startup window — new packetStore.hotStartupHours config loads only N hours of packet history synchronously and fills the rest in background daily chunks. Large DBs (multi-GB) no longer block the HTTP listener on a full-retention load before serving traffic (#1187).
  • Ingestor now owns the neighbor-graph and all schema migrations; the server is read-only. Removes a class of startup races where two processes raced the same migration (#1286, #1289).

🔬 NEW: Protocol decoder coverage

The MeshCore decoder now handles every documented payload type, with the legend updated end-to-end so operators see real names instead of Type 6.

  • GRP_DATA + MULTIPART wire-format decoded (#1280) — group-data sensor payloads + multipart fragmentation are no longer opaque blobs.
  • CONTROL flags + advertRole fix — accurate role attribution on ADVERTs from edge cases that were previously misclassified (#1280).
  • payloadTypeNames table centralised, exposed at the API + UI; new TransportCodes / Feat1 / Feat2 enums; RAW_CUSTOM type plumbed through; sensor-payload docs published (#1291).

🆕 NEW: Operator features

  • Repeater "usefulness score" (bridge axis) — second of four planned ranking dimensions for how much a repeater is structurally necessary to mesh connectivity (#1275, #672 axis 2/4).
  • Area-based visual node filter — define GPS polygons in config; attribute and filter packets by transmitter location across nodes/packets/map/live/analytics (#839).
  • Scoped vs unscoped transport-route statistics — per-region HMAC slicing of route stats; mirrors the existing hashChannels pattern (#915).
  • Sortable Scope column on the Nodes list (#1195).
  • Observer IATA badges on packets, with new filter grammar to slice by observer location (#1189).
  • Multi-byte hash capability is now persisted across restart with O(1) per-key lookup; operator-friendly capability badge surfaces it in the UI (#1324).
  • Material Design dark mode — properly polished pass (closes #893, #1389). Primary surface set, contrast, button + chip + form-control restyle.
  • Colorblind presets in the theme customizer — Wong / Deuteranopia-tuned / Plasma / Achromat ramps, applied to roles + multi-byte tiers + (in this release) the new route viewer's sequence ramp (#1378, #1408, #1414, #1407).
  • Mobile gesture system — swipe rows for actions, swipe tabs to switch sections, slide-over dismiss (#1185); edge-swipe to open the nav drawer (#1184); first-visit hints so the gestures are discoverable (#1186).
  • New CoreScope logo + Aldrich webfont (#1137, #1138).

🐛 Bug Fixes

Protocol / Ingest

  • MQTT decode no longer panics on malformed path length — bounds check prevents slice [218:15] panic (#1214).
  • MQTT half-open TCP recovery — watchdog forces paho reconnect on stall (#1336); per-attempt logging surfaces silent reconnect-loop death (#1216).
  • Ingest-time vs observer time — ingestor stamps server now() for packet/observation storage; reverted earlier envelope-timestamp path that was driving counters wrong (#1233, #1372).
  • Hop disambiguator quality — source-diversity confidence weighting in tier-1 resolver (#1235), hop-context + observation-count tiebreak (#1198), 6 deferred quality items (#1200).
  • Geo-implausible edges rejected at neighbor-graph build time (#1230).
  • Clock-skew robustness — RTC-reset outliers excluded from hash median + recent-bad count (#1288).
  • Canonical resolved_path everywhere — /api/nodes/{pk}/paths (#1282) and paths-through resolver (#1353) now use the persisted resolved path instead of naive prefix matching; fixes wrong-node attribution.
  • Structural pubkey attribution via new from_pubkey column (#1152).
  • dbschema startup race fixed by giving optional-column migrations a canonical source (#1322).

UI / Channels / Packets

  • Channels page — chat-app redesign restores prod row layout + detail view (#1376); shows latest message time, not first-seen (#1368); drops ghost "unknown" bucket for encrypted-no-key packets (#1377); stops force-enabling "show encrypted" on every init (#1410); mobile UX overhaul (#1227).
  • Packets page — orders by ingest id rather than rxTime so fresh activity is actually visible (#1349); observer IATA shown on packets with new filter grammar (#1189).
  • Scopes tab — fixed JSON.parse by dropping duplicate /api prefix in scope-stats fetch path (#1379).
  • Live region filter no longer wipes the feed — correctly parses {observers:[...]} response shape (#1140).
  • Prefix Tool Network Overview shows configured-hash-size counts, not math-only slices (#1271).
  • CustomizernodeColors stopped force-overriding ROLE_COLORS so CB presets actually propagate (#1408, #1414).
  • Node detail full-page renders error state on 404 instead of silent blank (#1158); restored WCAG AA contrast on "Paths Through" links in dark mode (#1159); section reorder puts Recent Packets above Paths (#1160); dropped orphan separators from "Heard By" rows (#1161).

🎨 UI / UX Polish

  • Material Design dark-mode polish (#1389, closes #893) — primary surface set, contrast pass, button + chip + form-control restyle.
  • Customizer — live preview pane mirroring map / nodes / packets (#1408 deps), per-preset WCAG validator on save (#1407 chain).
  • Multi-byte hash UI — capability badge with operator-friendly tooltip (#1324), config-driven counts everywhere (#1271).
  • Nodes page — neighbor-aware reference-node selector (#1389 chain), geo/role/hash-size filter URL params survive reloads.
  • Live page — reconnect indicator + last-event-ago badge.
  • Theme — operator-customizable accent + role colors via single JSON file, shared across map / nodes / packets / live / channels.

🔧 Operator & Infra

  • New config keys (see Upgrade notes for full list): packetStore.hotStartupHours, compression.gzip, compression.websocket, areas, hashRegions.
  • Compression — opt-in HTTP gzip + WebSocket permessage-deflate, both default-off (#934).
  • Area-based filters — define GPS polygons in config; surfaces an Area: selector across analytics / nodes / packets / map / live (#839).
  • Scoped transport-route statshashRegions HMAC mirrors the hashChannels pattern, lets operators slice transport-route metrics by region (#915).
  • /api/perf/io — exposes cancelledWriteBytesPerSec from /proc/self/io plus ingestor side (#1167).
  • Ingestor/server architectural split — neighbor-graph + schema migrations are now ingestor-owned (#1286, #1289); see Upgrade notes.
  • /#/perf page — parallel health fetch + sort + auto-pause refresh when tab is hidden (#1261).

🧪 Testing & dev

  • Playwright E2E suite stabilized — flake fixes that unblocked master (#1330, #1310, #1317).
  • 122 new assertions for the route viewer covering hop resolution priority, raw_hex byte extraction, edge weight scales (incl. boundary fix), spider-fan collision grouping + loop double-ring, channel hash → name resolution, and CB-preset CSS var integration.
  • CI workflow updated to run the new route-view tests on every PR....
Read more

v3.7.2

06 May 19:33
Immutable release. Only release title and notes can be modified.

Choose a tag to compare

v3.7.2 — hotfix: ingestor backfill infinite-loop fix (#1119, #1121)

v3.7.1

05 May 00:08
Immutable release. Only release title and notes can be modified.
26daa76

Choose a tag to compare

Identical to v3.7.0 + live PSK decrypt fix (#1031). This is the tagged release with the Docker image on GHCR.

docker pull ghcr.io/kpa-clawbot/corescope:v3.7.1

See v3.7.0 release notes for full changelog.

v3.7.0 — Operator's Toolkit

04 May 05:13
Immutable release. Only release title and notes can be modified.

Choose a tag to compare

CoreScope v3.7.0 — "Operator's Toolkit"

50 commits · 30 issues closed · 95 files changed · +7,710 / -293 LOC


Channel Decryption

Rebuilt from scratch. Pure-JS AES-128-ECB + SHA-256/HMAC — works on HTTP and HTTPS. PSK channels: add by key, name them, delete them, see decrypt count. Live WebSocket auto-decrypt with unread badges. Channel hash-byte dedup fixed.

Analytics

Selectable timeframes (1h/24h/7d/30d). Region attribution by repeater home, not observer. "All" filter fixed. Topology dedup (no more triple-counted repeaters). Timestamp format applied to chart axes.

New Surfaces

  • /#/roles — role distribution + per-role clock-skew
  • /api/backup — API-key gated SQLite export via VACUUM INTO
  • /api/healthz — readiness probe

Packets & Filters

Transport route type filter (transport == true, T_FLOOD, T_DIRECT). Clear filters button. Scroll position preserved. Null hash/timestamp packets cleaned. GRP_DATA type 6 support.

Map & Nodes

Short pubkey-prefix URLs (📡 Copy short URL). Multi-byte hash support indicator on markers. Channel color picker fixed.

MQTT & Ingestor

Async path_json backfill (no more startup blocks). Per-source region field. MQTT startup resilience (unreachable sources don't block). Configurable connect timeout. Observer IATA whitelist + blacklist. Per-hop TRACE SNR extraction in ingestor.

Observer & Node

Flood/direct filter on comparison page. TRACE per-hop SNR in byte breakdown. Clock skew evidence UI. Separate last-status vs last-packet timestamps. Soft-deleted observers excluded. Export/import includes favorites.

Infra

CORS allowlist. RW SQLite connection cache. GeoFilter Builder draft save/load/download. False-positive path exclusion.


Upgrade: New config fields in config.example.json: observerIATAWhitelist, observerBlacklist, per-source region/connectTimeoutSec, CORS allowedOrigins. One-time DB migration runs async on startup.


⚠️ Docker image not available for this tag (CI trigger issue). Use v3.7.1 for the container image: ghcr.io/kpa-clawbot/corescope:v3.7.1