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