From e05e356d6450938c0104c69a237ffda469b59ad8 Mon Sep 17 00:00:00 2001 From: archipelago Date: Sun, 17 May 2026 18:40:50 -0400 Subject: [PATCH] chore: release v1.7.58-alpha --- CHANGELOG.md | 14 ++++++++ core/Cargo.lock | 2 +- core/archipelago/Cargo.toml | 2 +- core/archipelago/src/bootstrap.rs | 31 ++++++++++++++++ image-recipe/configs/nginx-archipelago.conf | 16 +++++++++ neode-ui/package-lock.json | 4 +-- neode-ui/package.json | 2 +- release-manifest.json | 39 ++++++++++++--------- releases/manifest.json | 39 ++++++++++++--------- 9 files changed, 110 insertions(+), 39 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 35b7d0f9..cb91ef82 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,19 @@ # Changelog +## v1.7.58-alpha (2026-05-17) + +- Mesh networking now supports Meshtastic radios over the Meshtastic serial API in addition to existing MeshCore Companion USB radios. +- The mesh listener now probes preferred and auto-detected serial paths for both MeshCore and Meshtastic firmware, preserving the existing reconnect loop so unplug/replug and firmware hot-swap behavior stays consistent. +- Meshtastic text packets are translated into the existing Archipelago mesh frame pipeline, so current RPC handlers, transport routing, message storage, typed-message decoding, and UI state continue to work without a separate frontend path. +- Meshtastic node information is surfaced as normal mesh contacts using stable synthetic public keys derived from Meshtastic node numbers, allowing peer refresh and message attribution to reuse existing MeshCore contact handling. +- Outbound Archipelago mesh messages can now be sent through Meshtastic as channel text packets using the same command path used by MeshCore channel broadcasts. +- Device status now reports the detected firmware family as `meshcore` or `meshtastic` from the shared listener abstraction. +- Radio udev rules now include USB CDC ACM serial devices (`ttyACM*`) alongside CP2102, CH340, and FTDI adapters so Meshtastic boards are more likely to appear through the stable `/dev/mesh-radio` symlink. +- Host nginx now serves `/assets/*` hashed frontend chunks as immutable static files with a hard 404 on misses instead of falling back to `index.html`, preventing strict MIME errors when a browser has a stale pre-update HTML shell. +- The SPA HTML shell and service-worker files now revalidate on every load, reducing stale frontend references after OTA updates. +- OTA runtime promotion now installs the bundled `nginx-archipelago.conf` into `/etc/nginx/sites-available/archipelago` and reloads nginx after a successful config test, so frontend cache/fallback fixes reach existing nodes without a manual deploy. +- Local validation passed with `cargo check -p archipelago`; live SSH testing against `100.70.96.88` was not completed because temporary public-key authentication was rejected on the target. + ## v1.7.57-alpha (2026-05-17) - Nginx Proxy Manager now avoids privileged rootless Podman host port `81`, preferring `8081:81` while host nginx keeps a compatibility proxy on `:81` for stale cached launch buttons. diff --git a/core/Cargo.lock b/core/Cargo.lock index a1a84fb4..73117878 100644 --- a/core/Cargo.lock +++ b/core/Cargo.lock @@ -80,7 +80,7 @@ checksum = "a23eb6b1614318a8071c9b2521f36b424b2c83db5eb3a0fead4a6c0809af6e61" [[package]] name = "archipelago" -version = "1.7.57-alpha" +version = "1.7.58-alpha" dependencies = [ "anyhow", "archipelago-container", diff --git a/core/archipelago/Cargo.toml b/core/archipelago/Cargo.toml index 79868ad4..b36aa646 100644 --- a/core/archipelago/Cargo.toml +++ b/core/archipelago/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "archipelago" -version = "1.7.57-alpha" +version = "1.7.58-alpha" edition = "2021" description = "Archipelago Bitcoin Node OS - Native backend" authors = ["Archipelago Team"] diff --git a/core/archipelago/src/bootstrap.rs b/core/archipelago/src/bootstrap.rs index 459c7b08..d766632f 100644 --- a/core/archipelago/src/bootstrap.rs +++ b/core/archipelago/src/bootstrap.rs @@ -233,6 +233,24 @@ async fn run_runtime_assets() -> Result { } let configs = runtime_dir.join("image-recipe/configs"); + let nginx_src = configs.join("nginx-archipelago.conf"); + if nginx_src.exists() { + let src_s = nginx_src.to_string_lossy().to_string(); + let status = host_sudo(&[ + "install", + "-m", + "644", + &src_s, + "/etc/nginx/sites-available/archipelago", + ]) + .await + .context("install nginx-archipelago.conf")?; + if !status.success() { + anyhow::bail!("install nginx-archipelago.conf exited with {}", status); + } + changed = true; + } + for unit in ["archipelago-doctor.service", "archipelago-doctor.timer"] { let src = configs.join(unit); if src.exists() { @@ -250,6 +268,19 @@ async fn run_runtime_assets() -> Result { if changed { let _ = host_sudo(&["systemctl", "daemon-reload"]).await; + if nginx_src.exists() { + match host_sudo(&["nginx", "-t"]).await { + Ok(status) if status.success() => { + let _ = host_sudo(&["systemctl", "reload", "nginx"]).await; + } + Ok(status) => { + tracing::warn!("nginx config test failed after runtime sync: {}", status); + } + Err(e) => { + tracing::warn!("failed to test nginx config after runtime sync: {}", e); + } + } + } } Ok(changed) } diff --git a/image-recipe/configs/nginx-archipelago.conf b/image-recipe/configs/nginx-archipelago.conf index c631bf8d..d52e9856 100644 --- a/image-recipe/configs/nginx-archipelago.conf +++ b/image-recipe/configs/nginx-archipelago.conf @@ -105,9 +105,25 @@ server { try_files $uri =404; } + # Versioned Vite assets must never fall through to index.html. During OTA + # a browser can keep an old HTML shell that references now-removed hashed + # chunks; returning HTML for /assets/*.js triggers strict MIME failures. + # A real 404 plus immutable/no-cache split lets the app/browser recover on + # refresh without caching the wrong content type. + location /assets/ { + try_files $uri =404; + add_header Cache-Control "public, max-age=31536000, immutable" always; + } + + location ~* ^/(registerSW\.js|sw\.js|workbox-[^/]+\.js)$ { + try_files $uri =404; + add_header Cache-Control "no-cache, must-revalidate" always; + } + # Serve static files (Vue.js SPA) location / { try_files $uri $uri/ /index.html; + add_header Cache-Control "no-cache, must-revalidate"; } # Peer-to-peer node messaging (receives from other nodes over Tor) diff --git a/neode-ui/package-lock.json b/neode-ui/package-lock.json index 07ead57d..41708c7b 100644 --- a/neode-ui/package-lock.json +++ b/neode-ui/package-lock.json @@ -1,12 +1,12 @@ { "name": "neode-ui", - "version": "1.7.57-alpha", + "version": "1.7.58-alpha", "lockfileVersion": 3, "requires": true, "packages": { "": { "name": "neode-ui", - "version": "1.7.57-alpha", + "version": "1.7.58-alpha", "dependencies": { "@types/dompurify": "^3.0.5", "@vue-leaflet/vue-leaflet": "^0.10.1", diff --git a/neode-ui/package.json b/neode-ui/package.json index 9639f80a..eaf31f38 100644 --- a/neode-ui/package.json +++ b/neode-ui/package.json @@ -1,7 +1,7 @@ { "name": "neode-ui", "private": true, - "version": "1.7.57-alpha", + "version": "1.7.58-alpha", "type": "module", "scripts": { "start": "./start-dev.sh", diff --git a/release-manifest.json b/release-manifest.json index 8047cfac..2c32ce57 100644 --- a/release-manifest.json +++ b/release-manifest.json @@ -1,29 +1,34 @@ { - "version": "1.7.57-alpha", + "version": "1.7.58-alpha", "release_date": "2026-05-17", "changelog": [ - "Nginx Proxy Manager now avoids privileged rootless Podman host port `81`, preferring `8081:81` while host nginx keeps a compatibility proxy on `:81` for stale cached launch buttons.", - "App installs now allocate ports by checking live host bind availability, falling back to a free high port when preferred ports are already occupied.", - "Portainer-created launchable containers are separated into a `Websites` tab and launch through their discovered published host port instead of hard-coded app URLs.", - "Internal BuildKit helper containers such as `buildx_buildkit_default` are hidden from the Apps UI.", - "Portainer works out of the box on Debian 13/Podman installs by including `catatonit` and by preserving the Podman socket mount as a socket rather than creating it as a directory." + "Mesh networking now supports Meshtastic radios over the Meshtastic serial API in addition to existing MeshCore Companion USB radios.", + "The mesh listener now probes preferred and auto-detected serial paths for both MeshCore and Meshtastic firmware, preserving the existing reconnect loop so unplug/replug and firmware hot-swap behavior stays consistent.", + "Meshtastic text packets are translated into the existing Archipelago mesh frame pipeline, so current RPC handlers, transport routing, message storage, typed-message decoding, and UI state continue to work without a separate frontend path.", + "Meshtastic node information is surfaced as normal mesh contacts using stable synthetic public keys derived from Meshtastic node numbers, allowing peer refresh and message attribution to reuse existing MeshCore contact handling.", + "Outbound Archipelago mesh messages can now be sent through Meshtastic as channel text packets using the same command path used by MeshCore channel broadcasts.", + "Device status now reports the detected firmware family as `meshcore` or `meshtastic` from the shared listener abstraction.", + "Radio udev rules now include USB CDC ACM serial devices (`ttyACM*`) alongside CP2102, CH340, and FTDI adapters so Meshtastic boards are more likely to appear through the stable `/dev/mesh-radio` symlink.", + "Host nginx now serves `/assets/*` hashed frontend chunks as immutable static files with a hard 404 on misses instead of falling back to `index.html`, preventing strict MIME errors when a browser has a stale pre-update HTML shell.", + "The SPA HTML shell and service-worker files now revalidate on every load, reducing stale frontend references after OTA updates.", + "OTA runtime promotion now installs the bundled `nginx-archipelago.conf` into `/etc/nginx/sites-available/archipelago` and reloads nginx after a successful config test, so frontend cache/fallback fixes reach existing nodes without a manual deploy." ], "components": [ { "name": "archipelago", - "current_version": "1.7.57-alpha", - "new_version": "1.7.57-alpha", - "download_url": "http://146.59.87.168:3000/lfg2025/archy/releases/download/v1.7.57-alpha/archipelago", - "sha256": "e96d657c28f84c72c1358fdbbc014184530763341a2d02242b3a479f36dc2aef", - "size_bytes": 42647224 + "current_version": "1.7.58-alpha", + "new_version": "1.7.58-alpha", + "download_url": "http://146.59.87.168:3000/lfg2025/archy/releases/download/v1.7.58-alpha/archipelago", + "sha256": "2aa6e5f5b3d2cc74360ee2ce76098f9b0543d043cac23492062ece11c009c673", + "size_bytes": 42886144 }, { - "name": "archipelago-frontend-1.7.57-alpha.tar.gz", - "current_version": "1.7.57-alpha", - "new_version": "1.7.57-alpha", - "download_url": "http://146.59.87.168:3000/lfg2025/archy/releases/download/v1.7.57-alpha/archipelago-frontend-1.7.57-alpha.tar.gz", - "sha256": "a09c1507afb4b7e9f5279b92215e92ebc0b86155ae53ac2c0baaecd07522c7ee", - "size_bytes": 78322316 + "name": "archipelago-frontend-1.7.58-alpha.tar.gz", + "current_version": "1.7.58-alpha", + "new_version": "1.7.58-alpha", + "download_url": "http://146.59.87.168:3000/lfg2025/archy/releases/download/v1.7.58-alpha/archipelago-frontend-1.7.58-alpha.tar.gz", + "sha256": "a800c9e88a0cf088559b3ae227b6d1ed2ebdbb8c1e562b7c95cb35def7623804", + "size_bytes": 166466572 } ] } diff --git a/releases/manifest.json b/releases/manifest.json index 8047cfac..2c32ce57 100644 --- a/releases/manifest.json +++ b/releases/manifest.json @@ -1,29 +1,34 @@ { - "version": "1.7.57-alpha", + "version": "1.7.58-alpha", "release_date": "2026-05-17", "changelog": [ - "Nginx Proxy Manager now avoids privileged rootless Podman host port `81`, preferring `8081:81` while host nginx keeps a compatibility proxy on `:81` for stale cached launch buttons.", - "App installs now allocate ports by checking live host bind availability, falling back to a free high port when preferred ports are already occupied.", - "Portainer-created launchable containers are separated into a `Websites` tab and launch through their discovered published host port instead of hard-coded app URLs.", - "Internal BuildKit helper containers such as `buildx_buildkit_default` are hidden from the Apps UI.", - "Portainer works out of the box on Debian 13/Podman installs by including `catatonit` and by preserving the Podman socket mount as a socket rather than creating it as a directory." + "Mesh networking now supports Meshtastic radios over the Meshtastic serial API in addition to existing MeshCore Companion USB radios.", + "The mesh listener now probes preferred and auto-detected serial paths for both MeshCore and Meshtastic firmware, preserving the existing reconnect loop so unplug/replug and firmware hot-swap behavior stays consistent.", + "Meshtastic text packets are translated into the existing Archipelago mesh frame pipeline, so current RPC handlers, transport routing, message storage, typed-message decoding, and UI state continue to work without a separate frontend path.", + "Meshtastic node information is surfaced as normal mesh contacts using stable synthetic public keys derived from Meshtastic node numbers, allowing peer refresh and message attribution to reuse existing MeshCore contact handling.", + "Outbound Archipelago mesh messages can now be sent through Meshtastic as channel text packets using the same command path used by MeshCore channel broadcasts.", + "Device status now reports the detected firmware family as `meshcore` or `meshtastic` from the shared listener abstraction.", + "Radio udev rules now include USB CDC ACM serial devices (`ttyACM*`) alongside CP2102, CH340, and FTDI adapters so Meshtastic boards are more likely to appear through the stable `/dev/mesh-radio` symlink.", + "Host nginx now serves `/assets/*` hashed frontend chunks as immutable static files with a hard 404 on misses instead of falling back to `index.html`, preventing strict MIME errors when a browser has a stale pre-update HTML shell.", + "The SPA HTML shell and service-worker files now revalidate on every load, reducing stale frontend references after OTA updates.", + "OTA runtime promotion now installs the bundled `nginx-archipelago.conf` into `/etc/nginx/sites-available/archipelago` and reloads nginx after a successful config test, so frontend cache/fallback fixes reach existing nodes without a manual deploy." ], "components": [ { "name": "archipelago", - "current_version": "1.7.57-alpha", - "new_version": "1.7.57-alpha", - "download_url": "http://146.59.87.168:3000/lfg2025/archy/releases/download/v1.7.57-alpha/archipelago", - "sha256": "e96d657c28f84c72c1358fdbbc014184530763341a2d02242b3a479f36dc2aef", - "size_bytes": 42647224 + "current_version": "1.7.58-alpha", + "new_version": "1.7.58-alpha", + "download_url": "http://146.59.87.168:3000/lfg2025/archy/releases/download/v1.7.58-alpha/archipelago", + "sha256": "2aa6e5f5b3d2cc74360ee2ce76098f9b0543d043cac23492062ece11c009c673", + "size_bytes": 42886144 }, { - "name": "archipelago-frontend-1.7.57-alpha.tar.gz", - "current_version": "1.7.57-alpha", - "new_version": "1.7.57-alpha", - "download_url": "http://146.59.87.168:3000/lfg2025/archy/releases/download/v1.7.57-alpha/archipelago-frontend-1.7.57-alpha.tar.gz", - "sha256": "a09c1507afb4b7e9f5279b92215e92ebc0b86155ae53ac2c0baaecd07522c7ee", - "size_bytes": 78322316 + "name": "archipelago-frontend-1.7.58-alpha.tar.gz", + "current_version": "1.7.58-alpha", + "new_version": "1.7.58-alpha", + "download_url": "http://146.59.87.168:3000/lfg2025/archy/releases/download/v1.7.58-alpha/archipelago-frontend-1.7.58-alpha.tar.gz", + "sha256": "a800c9e88a0cf088559b3ae227b6d1ed2ebdbb8c1e562b7c95cb35def7623804", + "size_bytes": 166466572 } ] }