- channelRegistry: 39 validated channel secrets committed as the service
default (Public + 38 community/hashtag channels recovered via the
derivation audit); MESHCORE_CHANNEL_SECRETS env appends on top
- shared buildSummary/identifyChannel (single implementation for ingest
and offline tools)
- tools/backfillDecrypt: keyset-paginated retroactive decryption of the
stored raw_hex corpus (idempotent, resumable)
- feed: channel scope sidebar now lists every decrypted channel
Backend: schedule ONE final multi-observer resolution per path-bearing
packet after the propagation window closes (default 60s, calibrated on
real first->last observer spread p50 11s / p95 34s / p99 50s; median 17
observers per packet). The final runs with the COMPLETE observer set and
pushes into the resolve cache after invalidation, so the next API read
serves the full-propagation answer. mode=slow on /path-beta/resolve-multi
returns 202 {status:pending, remainingMs} while inside the window; new
/path-beta/slow-mode status endpoint; observability table
path_slow_resolutions (migration 034). Env knobs:
PATH_SLOW_MODE_ENABLED / PATH_SLOW_MODE_WINDOW_MS / PATH_SLOW_MODE_MIN_HOPS
/ PATH_SLOW_MODE_PENDING_MAX. Best-effort: restart loss is harmless.
Frontend: pinned packets resolve in slow mode (bounded 202 retry), local
path renders meanwhile, upgraded when the final lands. Live feed unchanged.
Tests: 4 new slowMode unit tests (dedupe, disable, bound, window timing).
Backend build clean, 257/258 (1 pre-existing workerPool timing flake on
base too); frontend build clean, 74/74.
- 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.
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>
- 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>