From ca89cb419603bcc3af8a8a687a539f777ef095c5 Mon Sep 17 00:00:00 2001 From: Dorian Date: Mon, 13 Jul 2026 18:08:25 +0100 Subject: [PATCH] =?UTF-8?q?fix:=20RC=20hardware-test=20feedback=20?= =?UTF-8?q?=E2=80=94=20mesh=20serial=20access,=20federation.list,=20masked?= =?UTF-8?q?=20install=20errors?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - image: create archipelago user with dialout so the backend can open /dev/ttyUSB*/ttyACM* LoRa radios; doctor Fix 14 heals existing nodes (verified live on the .65 RC install — device detected after the fix) - Web5Federation.vue called nonexistent federation.list (Unknown method); now uses federation.list-nodes + federation.list-pending-requests with a last-seen-based online count - sanitizer: let app-install dependency errors through — 'LND requires a running Bitcoin node' was masked as 'Check server logs', so install failures on fresh nodes looked random Co-Authored-By: Claude Fable 5 --- core/archipelago/src/api/rpc/middleware.rs | 7 +++++++ .../_archived/build-auto-installer-iso.sh | 2 +- neode-ui/src/views/web5/Web5Federation.vue | 15 ++++++++++----- scripts/container-doctor.sh | 18 ++++++++++++++++++ 4 files changed, 36 insertions(+), 6 deletions(-) diff --git a/core/archipelago/src/api/rpc/middleware.rs b/core/archipelago/src/api/rpc/middleware.rs index 5233d8ff..51e04557 100644 --- a/core/archipelago/src/api/rpc/middleware.rs +++ b/core/archipelago/src/api/rpc/middleware.rs @@ -64,6 +64,13 @@ pub(super) fn sanitize_error_message(msg: &str) -> String { "Failed to open channel", "Failed to close channel", "Failed to connect to peer", + // App-install dependency errors (package/dependencies.rs) — masking + // these left users retrying installs blind ("LND install failed" on a + // fresh node was really "Bitcoin Knots isn't running yet") + "LND requires", + "ElectrumX requires", + "BTCPay Server requires", + "Mempool requires", "Container", "Image", "Bitcoin address", diff --git a/image-recipe/_archived/build-auto-installer-iso.sh b/image-recipe/_archived/build-auto-installer-iso.sh index 5025cb4f..c909c80a 100755 --- a/image-recipe/_archived/build-auto-installer-iso.sh +++ b/image-recipe/_archived/build-auto-installer-iso.sh @@ -398,7 +398,7 @@ RUN apt-get update && apt-get -y full-upgrade && apt-get install -y --no-install RUN echo "en_US.UTF-8 UTF-8" > /etc/locale.gen && locale-gen # Create archipelago user with password "archipelago" -RUN useradd -m -s /bin/bash -G sudo archipelago && \ +RUN useradd -m -s /bin/bash -G sudo,dialout archipelago && \ echo "archipelago:archipelago" | chpasswd && \ echo "root:archipelago" | chpasswd && \ echo "archipelago ALL=(ALL) NOPASSWD:ALL" > /etc/sudoers.d/archipelago diff --git a/neode-ui/src/views/web5/Web5Federation.vue b/neode-ui/src/views/web5/Web5Federation.vue index d6720cb6..d66ca364 100644 --- a/neode-ui/src/views/web5/Web5Federation.vue +++ b/neode-ui/src/views/web5/Web5Federation.vue @@ -101,13 +101,18 @@ async function loadFederationSummary() { federationError.value = '' try { const res = await rpcClient.call<{ - nodes: Array<{ status: string }> - pending_requests: Array - }>({ method: 'federation.list', timeout: 5000 }) + nodes: Array<{ last_seen?: string }> + }>({ method: 'federation.list-nodes', timeout: 5000 }) const nodes = res.nodes || [] nodeCount.value = nodes.length - onlineCount.value = nodes.filter(n => n.status === 'online' || n.status === 'connected').length - pendingCount.value = (res.pending_requests || []).length + // list-nodes has no live status field — count a node seen in the + // last 10 minutes as online + const cutoff = Date.now() - 10 * 60 * 1000 + onlineCount.value = nodes.filter(n => n.last_seen && new Date(n.last_seen).getTime() > cutoff).length + try { + const pend = await rpcClient.call<{ requests: Array }>({ method: 'federation.list-pending-requests', timeout: 5000 }) + pendingCount.value = (pend.requests || []).length + } catch { pendingCount.value = 0 } hasLoadedFederation.value = true } catch (e: unknown) { federationError.value = e instanceof Error ? e.message : 'Federation unavailable' diff --git a/scripts/container-doctor.sh b/scripts/container-doctor.sh index d7f2ada3..e2b41359 100755 --- a/scripts/container-doctor.sh +++ b/scripts/container-doctor.sh @@ -614,6 +614,23 @@ fix_missing_catatonit() { return 1 } +# ── Fix 14: archipelago user missing dialout (mesh radios) ─── +# The image used to create the archipelago user with only `sudo`, so the +# backend couldn't open /dev/ttyUSB*/ttyACM* serial LoRa radios — Mesh +# never detected a plugged-in device (observed on the 1.7.99 RC install +# 2026-07-13). Group change takes effect on the next service restart; we +# restart archipelago only if a serial device is actually present. +fix_archipelago_dialout() { + id -nG archipelago 2>/dev/null | grep -qw dialout && return 1 + usermod -aG dialout archipelago 2>/dev/null || return 1 + log "Added archipelago to dialout (serial mesh radios were unreadable)" + if ls /dev/ttyUSB* /dev/ttyACM* >/dev/null 2>&1; then + systemctl try-restart archipelago 2>/dev/null || true + log "Restarted archipelago to pick up dialout (radio present)" + fi + return 0 +} + # ── Main ───────────────────────────────────────────────────── # If remote host provided, run via SSH @@ -646,6 +663,7 @@ run_fix "rootless-ports" fix_missing_rootless_ports run_fix "npm-public-hosts" fix_npm_public_hosts run_fix "btcpay-route-hints" fix_btcpay_route_hints run_fix "catatonit" fix_missing_catatonit +run_fix "dialout" fix_archipelago_dialout echo "" if [ $FIXES_APPLIED -gt 0 ]; then