fix: RC hardware-test feedback — mesh serial access, federation.list, masked install errors
- 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 <noreply@anthropic.com>
This commit is contained in:
parent
b800288550
commit
ca89cb4196
@ -64,6 +64,13 @@ pub(super) fn sanitize_error_message(msg: &str) -> String {
|
|||||||
"Failed to open channel",
|
"Failed to open channel",
|
||||||
"Failed to close channel",
|
"Failed to close channel",
|
||||||
"Failed to connect to peer",
|
"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",
|
"Container",
|
||||||
"Image",
|
"Image",
|
||||||
"Bitcoin address",
|
"Bitcoin address",
|
||||||
|
|||||||
@ -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
|
RUN echo "en_US.UTF-8 UTF-8" > /etc/locale.gen && locale-gen
|
||||||
|
|
||||||
# Create archipelago user with password "archipelago"
|
# 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 "archipelago:archipelago" | chpasswd && \
|
||||||
echo "root:archipelago" | chpasswd && \
|
echo "root:archipelago" | chpasswd && \
|
||||||
echo "archipelago ALL=(ALL) NOPASSWD:ALL" > /etc/sudoers.d/archipelago
|
echo "archipelago ALL=(ALL) NOPASSWD:ALL" > /etc/sudoers.d/archipelago
|
||||||
|
|||||||
@ -101,13 +101,18 @@ async function loadFederationSummary() {
|
|||||||
federationError.value = ''
|
federationError.value = ''
|
||||||
try {
|
try {
|
||||||
const res = await rpcClient.call<{
|
const res = await rpcClient.call<{
|
||||||
nodes: Array<{ status: string }>
|
nodes: Array<{ last_seen?: string }>
|
||||||
pending_requests: Array<unknown>
|
}>({ method: 'federation.list-nodes', timeout: 5000 })
|
||||||
}>({ method: 'federation.list', timeout: 5000 })
|
|
||||||
const nodes = res.nodes || []
|
const nodes = res.nodes || []
|
||||||
nodeCount.value = nodes.length
|
nodeCount.value = nodes.length
|
||||||
onlineCount.value = nodes.filter(n => n.status === 'online' || n.status === 'connected').length
|
// list-nodes has no live status field — count a node seen in the
|
||||||
pendingCount.value = (res.pending_requests || []).length
|
// 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<unknown> }>({ method: 'federation.list-pending-requests', timeout: 5000 })
|
||||||
|
pendingCount.value = (pend.requests || []).length
|
||||||
|
} catch { pendingCount.value = 0 }
|
||||||
hasLoadedFederation.value = true
|
hasLoadedFederation.value = true
|
||||||
} catch (e: unknown) {
|
} catch (e: unknown) {
|
||||||
federationError.value = e instanceof Error ? e.message : 'Federation unavailable'
|
federationError.value = e instanceof Error ? e.message : 'Federation unavailable'
|
||||||
|
|||||||
@ -614,6 +614,23 @@ fix_missing_catatonit() {
|
|||||||
return 1
|
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 ─────────────────────────────────────────────────────
|
# ── Main ─────────────────────────────────────────────────────
|
||||||
|
|
||||||
# If remote host provided, run via SSH
|
# 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 "npm-public-hosts" fix_npm_public_hosts
|
||||||
run_fix "btcpay-route-hints" fix_btcpay_route_hints
|
run_fix "btcpay-route-hints" fix_btcpay_route_hints
|
||||||
run_fix "catatonit" fix_missing_catatonit
|
run_fix "catatonit" fix_missing_catatonit
|
||||||
|
run_fix "dialout" fix_archipelago_dialout
|
||||||
|
|
||||||
echo ""
|
echo ""
|
||||||
if [ $FIXES_APPLIED -gt 0 ]; then
|
if [ $FIXES_APPLIED -gt 0 ]; then
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user