Deploy the optimized, accuracy-gated HopReach RF pipeline and native progressive map layer after all CI, performance, full-stack, mobile, and secret-scan gates passed.
- Extract shared path-modal styles into pages/path-modal.css so the feed
modal regains its panel styling (regression from 83d770a: rules only in
stats-page.css, which the feed page never imports)
- Embed the path map in the modal above the tree
- Tree readability: Unknown hop for unresolved trace hops, matched/ambiguous/
unmatched dot variants, decluttered meta, honest hop summary header
- Include the July-29 feed refactor (FeedDialogs/FeedPathViews/feedModel/
feedState/PacketPathMap) already live in the deployed build
Deployed fixes from visual QA of ukmesh.com / app.ukmesh.com / healthcheck.ukmesh.com:
- Cookie consent: static full-width bottom bar with reserved page spacing (no longer overlays content)
- Landing: Live Map nav marked external with arrow, hero buttons and secondary text contrast
- Map app: readable place labels in both themes, packet feed top row no longer clipped,
aligned feed columns, bordered header tool buttons
- Site pages: dark-themed Region select, brighter topology graph, Repeaters empty state,
Companions bar scale legend, themed Spam controls/checkbox, Install badges
- Health: firmware chart label dedupe/rotation with Include Unknown toggle
- Docs: mobile code blocks scrollable
- Health Check: No data yet empty states, contrast, status pill a11y
- Healthcheck overrides: merged empty-state and a11y changes into deployed bind-mounted files
* Fix map node freshness consistency
* Harden output, ingest, caches, and WebSocket limits
* Enforce public visibility across derived data
* Harden proxy and operator deployment boundary
* Make owner grants authoritative and reconcile ACLs safely
* Bound path, spam, and statistics analysis
* Make link and coverage jobs crash-safe
* Implement strategic security remediation
* Fix production cutover configuration
* Fix disabled viewshed worker health signal
* Serve stale stats during background refresh
* Retain stale stats through refresh windows
* Bound analytics work to protect ingestion
* Prioritize summary warmup over chart scans
* Throttle path history rebuilds
* Bound path history result memory
* Stream path history aggregation
* Give bounded path rebuild one CPU
* Serve stale charts during bounded refresh
* Prioritize startup stats before chart scans
* Bound path history segment cardinality
* Pin path rebuild context to privacy generation
* Self-host original frontend fonts
* Allow bounded path rebuild to complete
* Improve live map UI and low-latency group feed
- Dock node details on the right with selection highlight and collapsible layers
- Add node legend, 24h activity sparkline, copy-link, and layout/overlap fixes
- Keep all repeaters visible during Live Path focus
- Send GroupText feed packets immediately over WebSocket (no batch delay)
- Cache expensive stats/observer activity more aggressively to protect ingest
- Remove stale local planning/audit markdown from the tree
* fix(ci): supply OPERATOR_SITE_TOKEN for compose validation
Workers/Compose CI failed because docker-compose requires
OPERATOR_SITE_TOKEN. Add CI placeholders for that and MQTT_PASSWORD.
Keep the dark theme but fix low-contrast, small text reported in the
repeater tree window and elsewhere:
- globals.css: --text-muted #71839b -> #8697b0. It was the only text
token failing WCAG AA (down to 3.8:1 on the lighter panels); now
5.0-6.6:1 on every background. primary/secondary left unchanged.
- Bump 9-10px muted/secondary labels to 11-12px (repeater-tree
metadata, node drawer, timeline, watchlist, planner, detail panel).
- Replace hard-coded greys (#9ca3af zoom hint, #aaa popup label) with
var(--text-muted) so they track the palette.
- Add an axe color-contrast e2e assertion on /feed to guard regressions.
Fixes#3
Co-authored-by: Claude Opus 4.8 <noreply@anthropic.com>
Consolidates the stacked backend, privacy, network-intelligence, frontend, operations, mobile, and owner-cache changes after resolving main conflicts and passing the full CI suite.
- index.html: add #region-filter div above observer list, cache-busting
query strings on CSS/JS, data-map-observer-scope="expected" on body
- ukmesh-theme.css: add .region-btn styles (UKMesh blue/cyan colour scheme),
remove now-redundant .score-ring__track override (SVG ring handles it)
The region filter UI is implemented in the gadgethd/meshcore-health-check fork
and activated server-side via REGIONS_FILE env var.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Backend: derive observer IATA from packet topic instead of node table,
send messages separately in WS initial state, add tiered prefix/edge
priors to lazy path resolver for more accurate hash disambiguation.
Frontend: add SeoHead, JsonLd, and vite-seo plugin for per-route meta
tags and structured data. Add earth-curvature correction to custom LOS
tool. Owner portal last-hop chart supports hiding/showing individual
series with cookie persistence. Feed page and path map refactored.
Cache-busting build filenames. Track firstSeenTs on aggregated packets.
Infra: serve robots.txt and sitemap.xml via nginx, add manifest.json,
reduce Mosquitto log verbosity. Viewshed worker supports per-node
antenna heights, configurable profile step, and SNR-median calibration.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
The teesside page directory is gitignored but main.tsx still imported
TeessieDashboard, causing TS2307 on any clean clone. Remove the import
and redirect the teesside index route to /install inside Layout.
Fixes#1
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Use ${TERRAIN_TILES_PATH:-./terrain-tiles} so the path is configurable
per-host without leaking machine-specific paths in the repo.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
- Multi-node LOS: multiple repeaters can have LOS active simultaneously,
each auto-expiring after 15 seconds; LOS persists after popup closes
- Custom LOS tool: desktop-only map button to sample terrain between two
points (click map or repeater); renders per-segment green/clear or
red/obstructed based on terrain height; prohibited nodes are excluded
- Terrain exaggeration: deck.gl altitudes multiplied by exaggeration factor
(2×) to match MapLibre's visual terrain mesh
- LOS line rendering: bloom+core PathLayer tube effect with ScatterplotLayer
endpoint markers; popup z-index fix so it renders above deck.gl canvas
- Terrain sampler: client-side Terrarium PNG tile decoder for elevation sampling
- DB schema: terrain_profile_json JSONB column added to node_links
- Nginx: terrain tile serving block added
- Docker: terrain tiles volume mount added
Excluded: PacketDetailPanel, UKFeedPage, styles/globals.css (unrelated local
changes), backfill_profiles.py (server-side utility, not intended for repo)
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
- Load terrain source and hillshade dynamically (only when 3D mode is on)
to prevent tile loading at idle, fixing low-zoom WebGL crash
- Restore terrain correctly on page reload by applying inside map load handler
- Clean up source, hillshade, and sky layers fully when terrain is toggled off
- Raise minZoom to 6 to prevent crash at extreme zoom-out
- Reduce terrain exaggeration to 3x as a stable middle ground
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
- Add SRTM raster-dem terrain source (AWS Terrarium tiles) to map style
- Add hillshade layer always visible for terrain relief in 2D and 3D
- Add sky layer for atmosphere effect in 3D mode
- Replace Links filter row with 3D Terrain toggle in the Layers panel
- Lock map pitch to 0 by default; terrain toggle unlocks and tilts to 45°
- Wire showTerrain prop through Filters → App → MapLibreMap via useEffect
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
- Lazy path resolver: geographic hop reconstruction from path_hashes without
pre-training data; fixes observer self-hash trimming bug
- ACL watcher worker: auto-provisions Mosquitto ACL entries when PUBLISH is
denied for a known user; eliminates the recurring gnomemoe ACL removal issue
- connectionMonitor: increase historical scan to 50 MB; fix OOM by streaming
lines instead of buffering; fixes missed backfill on restart
- Feed page: replace path-beta with lazy paths; add clickable node markers
showing name and public key; observer column nowrap; summary text unclipped
- PacketFeed: GRP-only message store protected from ADV eviction; scroll to
bottom on new message; 24-hour message backfill on initial load
- getRecentMessages: separate DB query for last 50 GRP messages last 24h
- getPacketDetail: new endpoint for full packet detail including observations
- Grafana/Loki/Promtail observability stack with Docker log collection
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
- New aclManager.ts rewrites a user's ACL block (all linked nodes) and
sends SIGHUP to the Mosquitto container whenever autoLinkOwnerNodeIds
runs at owner login, eliminating the need to manually edit the ACL
file when a user connects a second node.
- requireOwnerSession now resolves node IDs from owner_account_nodes
on every request instead of using the frozen session cookie list,
so manually- or auto-linked nodes are visible without re-login.
- docker-compose: mount mosquitto config dir (rw) and Docker socket
into backend so it can update the ACL file and signal Mosquitto.
- Add dockerode dependency for container SIGHUP signalling.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
- limit owner last-hop data to selected-node cached queries
- replace broad owner-node prewarm with rolling per-node cache updates
- incrementally refresh the latest cached hour and drop data outside the 7-day window