From 3db71adb55a39e123190eba285c96acb491b94c1 Mon Sep 17 00:00:00 2001 From: Dorian Date: Mon, 20 Apr 2026 11:44:59 -0400 Subject: [PATCH] release(v1.7.3-alpha): sidebar version sync + FIPS reconnect + profile pic render MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Sidebar version detect_build_version() no longer reads /opt/archipelago/build-info.txt first. That file was written by the ISO installer at flash time and never rewritten by OTA or sideload, so after any binary swap the sidebar kept advertising whatever the ISO shipped with. Now just returns env!("CARGO_PKG_VERSION") unconditionally — always matches the running binary. FIPS card The two-column grid in FipsNetworkCard.vue placed version/npub boxes side-by-side on mobile but the anchor-status panel forced col-span-2, creating an unbalanced empty column at every desktop width. Anchor status moves to its own full-width row below the grid. When the anchor is not reached, a "Reconnect" button appears next to the status line; it calls fips.restart (45s timeout), waits 5s for the daemon to come back, then reloads fips.status. Surfaces whether the restart actually recovered the anchor in a status flash. Profile picture render Uploaded profile pictures are stored with an onion-rooted URL so external Nostr clients can fetch them. The local browser isn't Tor-routed though, so the silently 404'd and the UI fell back to showing initials. Added a displayableUrl() helper on Web5Identities.vue that rewrites http:///blob/[?...] to same-origin /blob/ for rendering, while the stored URL keeps its onion prefix so publishing to Nostr still works for external viewers. Pass-through for data: URLs and already-relative paths. Identity row title The identity list header now renders profile.display_name (when set) and keeps identity.name as a muted parenthetical. Before, only the internal name was shown and a user who'd customised their Nostr display_name saw a mismatch between their own UI and what peers rendered. Artefacts: archipelago 99184b95…22dc1b 40350664 archipelago-frontend-1.7.3-alpha.tar.gz 7b933cf4…74a8bc 76987031 Changelog layman-style per the saved feedback. Co-Authored-By: Claude Opus 4.7 (1M context) --- core/Cargo.lock | 2 +- core/archipelago/Cargo.toml | 2 +- core/archipelago/src/data_model.rs | 17 ++--- neode-ui/src/views/server/FipsNetworkCard.vue | 69 ++++++++++++++----- neode-ui/src/views/web5/Web5Identities.vue | 21 +++++- 5 files changed, 80 insertions(+), 31 deletions(-) diff --git a/core/Cargo.lock b/core/Cargo.lock index 95dc1a41..84079f9e 100644 --- a/core/Cargo.lock +++ b/core/Cargo.lock @@ -80,7 +80,7 @@ checksum = "a23eb6b1614318a8071c9b2521f36b424b2c83db5eb3a0fead4a6c0809af6e61" [[package]] name = "archipelago" -version = "1.7.2-alpha" +version = "1.7.3-alpha" dependencies = [ "anyhow", "archipelago-container", diff --git a/core/archipelago/Cargo.toml b/core/archipelago/Cargo.toml index 4aeda1a1..962e9885 100644 --- a/core/archipelago/Cargo.toml +++ b/core/archipelago/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "archipelago" -version = "1.7.2-alpha" +version = "1.7.3-alpha" edition = "2021" description = "Archipelago Bitcoin Node OS - Native backend" authors = ["Archipelago Team"] diff --git a/core/archipelago/src/data_model.rs b/core/archipelago/src/data_model.rs index bc0870bf..d3d5e7e0 100644 --- a/core/archipelago/src/data_model.rs +++ b/core/archipelago/src/data_model.rs @@ -265,16 +265,13 @@ impl DataModel { /// falling back to Cargo.toml version. This allows sequential CI build /// numbers to be reflected in the UI without recompiling the binary. fn detect_build_version() -> String { - if let Ok(content) = std::fs::read_to_string("/opt/archipelago/build-info.txt") { - for line in content.lines() { - if let Some(v) = line.strip_prefix("version=") { - let v = v.trim(); - if !v.is_empty() { - return v.to_string(); - } - } - } - } + // Always use the binary's compiled-in version. The ISO installer + // writes /opt/archipelago/build-info.txt at install time, but that + // file is never rewritten by OTA or sideload, so trusting it made + // the sidebar permanently advertise whatever the ISO shipped with + // even after the running binary had moved on. CARGO_PKG_VERSION is + // baked into the binary at compile time, so it always matches what + // is actually running. env!("CARGO_PKG_VERSION").to_string() } diff --git a/neode-ui/src/views/server/FipsNetworkCard.vue b/neode-ui/src/views/server/FipsNetworkCard.vue index 2fc44e50..011cb30e 100644 --- a/neode-ui/src/views/server/FipsNetworkCard.vue +++ b/neode-ui/src/views/server/FipsNetworkCard.vue @@ -18,27 +18,12 @@ -
+

Daemon version

{{ status.version || '—' }}

Package not installed

-
-
-
- - Anchor (fips.v0l.io): - - {{ status.anchor_connected ? 'connected' : 'not reached' }} - -
-
{{ status.authenticated_peer_count ?? 0 }} peer{{ (status.authenticated_peer_count ?? 0) === 1 ? '' : 's' }}
-
-

- Without the anchor, DHT routing to unknown npubs can't bootstrap; federation + messaging will fall back to Tor until it reconnects. -

-

FIPS npub

@@ -60,6 +45,33 @@
+ +
+
+
+ + Anchor (fips.v0l.io): + + {{ status.anchor_connected ? 'connected' : 'not reached' }} + + · + {{ status.authenticated_peer_count ?? 0 }} peer{{ (status.authenticated_peer_count ?? 0) === 1 ? '' : 's' }} +
+ +
+

+ Without the anchor, DHT routing to unknown npubs can't bootstrap; federation and messaging fall back to Tor until it reconnects. Reconnect restarts the FIPS daemon, which usually clears a stale identity cache. +

+
+
{{ statusMessage }}
@@ -97,6 +109,7 @@ const status = ref({ anchor_connected: false, }) const installing = ref(false) +const reconnecting = ref(false) const statusMessage = ref('') const statusIsError = ref(false) const copied = ref(false) @@ -167,5 +180,29 @@ async function installAndActivate() { } } +// Restart the FIPS daemon to kick it back onto the public anchor. Stale +// identity-cache entries are the usual cause of "not reached"; systemctl +// restart clears them and re-runs the bootstrap handshake. +async function reconnectAnchor() { + reconnecting.value = true + try { + await rpcClient.call({ method: 'fips.restart', timeout: 45_000 }) + // Give the daemon a few seconds to come back and re-populate its + // identity cache before we re-query status. + await new Promise((resolve) => setTimeout(resolve, 5000)) + await loadStatus() + if (status.value.anchor_connected) { + flash('Anchor reconnected') + } else { + flash('FIPS restarted — anchor still reporting unreachable. Check network / firewall.', true) + } + } catch (e: unknown) { + const msg = e instanceof Error ? e.message : String(e) + flash(`Reconnect failed: ${msg}`, true) + } finally { + reconnecting.value = false + } +} + onMounted(loadStatus) diff --git a/neode-ui/src/views/web5/Web5Identities.vue b/neode-ui/src/views/web5/Web5Identities.vue index b9ede713..27f9ac78 100644 --- a/neode-ui/src/views/web5/Web5Identities.vue +++ b/neode-ui/src/views/web5/Web5Identities.vue @@ -68,7 +68,7 @@ >