Message details could only ever say "my region" or "another region". The request was a user-maintained region list so the scope line resolves to a real name. The mechanism was already here. transport_codes[0] is HMAC(region key, payload) truncated to 16 bits -- per-packet, not a region id, which is why the raw hex changes on every message (#259) and no code-to-name table can work. The only way to name a region is to recompute the code with a key you hold and compare, while the packet is still in hand. MyMesh has done that since #259, for exactly one key: our own default scope. This widens it from one key to N. Storage and key derivation are MeshCore's RegionMap + TransportKeyStore, which already ship in every build (helpers/*.cpp is in the library's src filter) and were simply never instantiated here. A public "#tag" region's key is plain SHA256("#tag"), which is byte-for-byte what MyMesh::setRegionScope already derives for our own region, so a name is the whole record. Two things are deliberately not reused: RegionMap::findMatch() returns the FIRST match. A 16-bit tag collides at roughly N/65534 per packet with N keys live, and a confident wrong region name is worse than none, so the loop here counts every match and reports ambiguity instead of picking one. RegionEntry::id is a uint16 that climbs as regions are added, and per-message storage has 4 bits. So messages record a SLOT (1..14, 15 = ambiguous, 0 = unknown) assigned once and never renumbered -- deleting or reordering regions cannot silently relabel old history, which #271 called out specifically. Those 4 bits are the free top nibble of meta_flags, which is already persisted at a fixed offset. No record growth, no history version bump, and no segment migration: messages written before a region was registered read back slot 0, which is the honest "unknown" state for a message received before we could name it. Note this fills meta_flags -- bits 0-3 are the existing semantics, 4-7 are now the slot -- so the next per-message bit does need a record change. The registry seeds itself: the default region in MyMesh::begin(), per-channel scope overrides in UITask::begin() (touch prefs, readable only on that side), and both save paths register on change so naming starts from the next packet rather than the next boot. No list-management UI yet; that sits cleanly on top. Scope reads "#denmark", or "ambiguous (several regions matched)", or falls back to the old my-region / another-region answer when nothing matched. Known limits, both honest states rather than bugs: private "$region" keys never match, because TransportKeyStore::loadKeysFor/saveKeysFor are unimplemented stubs in MeshCore 1.10 -- when the core fills them in, getTransportKeysFor() starts returning keys and this works unchanged. And codes[1], the reply-region hint, is still shown under "Scope" as #157 left it; giving it its own line needs a spare meta bit, which no longer exists. T-Deck, T-Lora Pager, ThinkNode M9, Heltec V4 and RAK Tap V2 all build. One new string in 13 .lang files, English both sides per 4709c81; the audit's 3 other gaps are pre-existing on main from the beta_68 SDK work. Not hardware-tested -- matching is only exercised by real scoped traffic from a second node. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
wadamesh.com infrastructure
Distribution stack for wadamesh: a VPS nginx origin behind Cloudflare.
tiles.wadamesh.com →CF (HTTP, edge-cached) → nginx → OpenStreetMap / OpenTopoMap
firmware.wadamesh.com →CF (cache bins) → nginx → /srv/wadamesh/firmware
flasher.wadamesh.com →CF (HTTPS) → web flasher (TODO — see below)
wadamesh.com →CF (HTTPS) → landing page (later)
Map tile styles. The default /{z}/{x}/{y}.jpg route serves OpenStreetMap
(the firmware default). An opt-in OpenTopoMap topographic style is served from
/opentopo/{z}/{x}/{y}.jpg (explicit OSM alias at /osm/...); the device requests
it only when the user enables Map → Options → Topographic map. Legal: OpenTopoMap
map tiles are © OpenTopoMap (CC-BY-SA) over © OpenStreetMap contributors
(ODbL) + SRTM — the touch UI shows that attribution when topo is active, and the
14-day disk cache keeps each tile hitting OpenTopoMap at most once per fortnight
(their tile-usage policy asks for a contactable UA + caching, both of which the
transcode service provides). Deploying the topo routes = update
tiles.wadamesh.com.conf + tile-transcode.py, then
systemctl restart wadamesh-tile-transcode && nginx -t && systemctl reload nginx
and purge the Cloudflare cache for tiles.wadamesh.com/opentopo/*.
The firmware fetches tiles + the update-check over plain HTTP (on-device HTTPS isn't viable — mbedTLS needs ~30 KB heap, only ~5 KB is free post-Wi-Fi), so the tile + firmware hosts must stay reachable over HTTP. Cloudflare provides the edge cache, HTTPS for the flasher, and hides the origin IP (so no IP lives in this repo or the firmware).
1. VPS (origin)
sudo apt install nginx
sudo mkdir -p /srv/wadamesh/firmware/releases/TOUCH /var/cache/nginx/wadamesh-tiles
sudo cp deploy/nginx/tiles.wadamesh.com.conf /etc/nginx/sites-available/
sudo cp deploy/nginx/firmware.wadamesh.com.conf /etc/nginx/sites-available/
sudo ln -s /etc/nginx/sites-available/tiles.wadamesh.com.conf /etc/nginx/sites-enabled/
sudo ln -s /etc/nginx/sites-available/firmware.wadamesh.com.conf /etc/nginx/sites-enabled/
sudo nginx -t && sudo systemctl reload nginx
2. Cloudflare
- DNS:
A/AAAArecords fortiles,firmware,flasher,@→ the VPS IP, all Proxied (orange cloud). - SSL/TLS: mode Flexible (CF↔origin HTTP) is enough since the origin is
HTTP-only. Do NOT enable "Always Use HTTPS" on
tiles.orfirmware.— the firmware needs plain HTTP there. - Cache Rules:
tiles.wadamesh.com/*→ Eligible for cache, Edge TTL ~14d.firmware.wadamesh.com/releases/*/*.bin→ cache, Edge TTL ~1d.firmware.wadamesh.com/releases/TOUCH(the listing) → short TTL (~60s) or Bypass, so new releases appear promptly.
3. Publishing a release
From a wadamesh checkout (builds both boards, refreshes the listing, rsyncs up):
WADAMESH_VPS=user@your-vps scripts/release.sh beta_2
The on-device check GETs http://firmware.wadamesh.com/releases/TOUCH, finds the
highest beta_<N>, and (once OTA-over-Wi-Fi is re-enabled) pulls
…/releases/TOUCH/beta_<N>/<board>.bin.
Done
- Web flasher ✅ at
flasher.wadamesh.com—deploy/flasher/(esp-web-tools / Web Serial, board picker, manifests pointing at the rolling/latest/merged bins;release.shrefreshes/latest/each publish). - Apex
wadamesh.com301-redirects to the flasher — activate by pointing thewadamesh.comA record at the VPS in Cloudflare (it's still on the parking IP).
TODO before public launch
- Re-enable OTA-over-Wi-Fi in the firmware (currently it version-checks then defers to manual flashing).
- Flip
wadameshrepo public = launch. - Decide tile-proxy sharing: dedicated
tiles.wadamesh.com(this config) vs reusing the meshcomod proxy.
Never commit the VPS IP, SSH keys, or
WADAMESH_VPS. Cloudflare fronts the origin; the deploy target is supplied via the environment at publish time.