- core/archipelago/src/bootstrap.rs (NEW): embed scripts/container-doctor.sh
and image-recipe/configs/archipelago-doctor.{service,timer} via
include_str! and sync to disk + enable the timer on every archipelago
startup. Idempotent (content-hash compare), dev-box symlink guard keeps
the git checkout untouched, best-effort (warn-only on failure) so
bootstrap never blocks server readiness. Wired in main.rs as a
background tokio task.
- scripts/container-doctor.sh: add fix_rootless_netns_egress(). Detects
when the rootless-netns has lost its pasta tap (container-to-container
still works but outbound DNS/TCP fails) via an nsenter probe into
aardvark-dns; with a two-probe 10s debounce to rule out transients and
a host-precheck that bails out if the host itself is offline. When the
rootless-netns is truly broken, does a graceful podman stop --all /
start --all so pasta + aardvark-dns rebuild the netns from scratch.
Bitcoin-knots and every other outbound container recover in one cycle.
- core/archipelago/src/update.rs: host_sudo → pub(crate) so bootstrap.rs
can reuse the existing systemd-run escape hatch.
- apps/bitcoin-core/manifest.yml: bump app version 24.0.0 → 28.4.0 and
image bitcoin/bitcoin:24.0 → bitcoin/bitcoin:28.4. Resources aligned
with the real container-specs.sh large-disk tune (4 GiB memory cap,
cpu_limit: 0 so bitcoind can run -par=auto across every core).
- neode-ui/src/views/apps/AppCard.vue + Apps.vue: add an Update button
+ Updating spinner to every app card that has available-update set.
Wires through serverStore.updatePackage(id) — the same RPC the detail
view already calls. common.update / common.updating i18n keys added in
en.json and es.json.
- core/archipelago/src/identity_manager.rs: add create_from_signing_key()
that mirrors an existing Ed25519 key as a manager-level identity with
a deterministic id (`node-<pubkey16>`). Idempotent across restarts,
gets the hex-SVG master avatar.
- core/archipelago/src/server.rs: the auto-create path on first boot now
mirrors the node's own signing_key (seed-derived on onboarded installs)
as a "Node" identity instead of generating a random "Default" keypair.
Once this ships, the DID on the Web5 DID Status card (via node.did
RPC), the Node entry on the Identities page (via identity.list), and
the DID used for peer-to-peer connects (via server_info.pubkey) all
resolve to the same seed-derived pubkey.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Install UX
SystemUpdate.vue now shows a full-screen overlay after apply: the
BitcoinFaceAscii logo, a target-version label, an indeterminate
progress stripe (solid orange; solid green on ready), and an
elapsed-time readout. Polls /health every 1.5s and auto-reloads
once the backend reports the new version. 3-min stall → "Reload
now" button. Download UI also shows a spinner + "Finishing
download — verifying checksum…" while the fake bar sits at 95%.
FIPS reconnect — for real this time
New fips.reconnect RPC does stop → start → wait 20s → re-poll →
classify. Classification buckets: connected / daemon_down /
no_seed_key / no_outbound_udp_or_anchor_down / peers_but_no_anchor,
each with a plain-language hint surfaced verbatim by the Reconnect
button. The real reason nodes like .198/.253 couldn't reach the
anchor: identity::write_fips_key_from_seed was writing fips_key.pub
as a bech32 npub TEXT file, but upstream fips expects 32 raw
bytes. The daemon silently authenticated with garbage. Fix:
PublicKey::to_bytes() → raw 32 bytes, and new
fips::config::normalize_pub_file migrates legacy files by decoding
the npub and rewriting in place. fips.reconnect also re-installs
the config + healed keys to /etc/fips before restarting.
AIUI preservation + restore
apply_update was wiping /opt/archipelago/web-ui/aiui because the
Vue build doesn't include it — every OTA lost the Claude sidebar.
The preserve block now copies aiui/ + archipelago-companion.apk
from the old web-ui into the staging dir before the swap, and
prefers new-tar versions if present. To restore it on the three
nodes that already lost it (.116/.198/.253), this release bundles
the 85 MB aiui build into the frontend tarball. Frontend component
size is now ~155 MB.
Download / install timeouts
Backend download client timeout 1800s → 3600s (1 h). Larger
tarball + slow gitea raw throughput put us above the old cap.
Frontend update.download rpc timeout 30 min → 65 min to match.
package.install rpc timeout 15 min → 45 min — IndeedHub pulls
6 images and was timing out mid-install.
UI nit
"Rollback to Previous" → "Rollback Available".
App-catalog proxy already landed in v1.7.13.
Artefacts:
archipelago 725e18e6…3c525e6 40462288
archipelago-frontend-1.7.14-alpha.tar.gz c35284be…ff2c16 162077052 (+aiui)
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Three user-visible fixes shipped together.
1. update.apply permission-denied
apply_update() was doing fs::copy into /usr/local/bin/archipelago and
tar xzf into /opt/archipelago as the archipelago user — both root-owned.
The backup step succeeded (it wrote to data_dir) but the swap failed
with a silent permission denied, wrapped as "Failed to apply archipelago".
Now uses `sudo install -m 0755` for the binary and `sudo tar -xzf` for
the frontend, plus a post-apply `sudo systemctl --no-block restart
archipelago` scheduled 2s after the RPC reply so the UI sees success.
2. Apply → Install label
en/es locale strings: applyUpdate / applyTitle / applyNow changed from
"Apply" to "Install". Matches the user's mental model and distinguishes
the user-facing verb from the internal apply_update() function.
3. Identity avatar backfill
Identities created before df83163f had profile=None on disk and so
rendered as initials. load_record() now synthesizes an IdentityProfile
with a default picture (identicon for regular identities, the hex node
SVG for derivation_index=0) when profile is missing. The synthetic
profile lives only in the returned record; the file stays untouched so
a later explicit Save persists whatever the user actually chose.
Artefacts:
archipelago 70e5444e…67c589 40381960
archipelago-frontend-1.7.2-alpha.tar.gz 806b027b…358a824 76983699
Changelog rewritten layman-style per saved feedback.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Two fixes bundled into the OTA:
1. update.download hard-fail on git-path nodes. handle_update_check's git
branch reported update_available=true + update_method="git" but never
populated state.available_update, so update.download returned "No update
available to download" even though the UI showed one. SystemUpdate.vue
now routes update_method=="git" through update.git-apply (pull+rebuild+
restart via self-update.sh); manifest-path nodes keep the download→apply
flow. i18n strings + confirm modal added for the git path.
2. Reconciler creating containers behind the user's back. On fresh
unbundled installs (.198, .253) archy-mempool-db and archy-btcpay-db
materialised ~10 min after first boot because reconcile-containers.sh
walked container-specs.sh's canonical tier list and created any
"missing" container. reset_spec() now defaults SPEC_OPTIONAL="true",
so reconcile is strictly a repair tool — baseline comes from
first-boot-containers.sh (filebrowser on unbundled), everything else
from the install RPC.
Also forces OTA trigger for nodes on 1.6.0-alpha that otherwise saw
"I'm at manifest.version, nothing to do" and skipped the refreshed 1.6
artifacts.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
UEFI boot:
- xorriso now uses -append_partition with ESP type GUID
(C12A7328-F81F-11D2-BA4B-00A0C93EC93B) instead of -isohybrid-gpt-basdat
which only creates "basic data" partitions. Strict UEFI firmware
requires the correct ESP type to find BOOTX64.EFI.
- Uses Arch Linux ISO approach: -append_partition + appended_part_as_gpt
WebSocket/login from LAN browser:
- HTTPS nginx /ws block was missing proxy_set_header Cookie $http_cookie
Session cookie wasn't forwarded → backend returned 401 → WS failed
Password UX:
- Renamed "Change Password" → "Set Password" with description explaining
default password is password123
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Switch IndeedHub to staging API, add _next asset caching in nginx,
simplify NostrIdentityPicker component, and update Apps/Web5/Marketplace views.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
- Simplify DHT encoding: use JSON instead of DNS packets (drop simple-dns)
- Fix mainline crate API: SigningKey takes 32 bytes, get_mutable returns Result
- Add missing dht_did field to IdentityRecord constructor
- Store DID Document as JSON in DHT (DNS encoding deferred)
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
- Added new dependencies: `adler2`, `crc32fast`, `flate2`, `miniz_oxide`, and `libredox`.
- Updated existing dependencies: `tokio-rustls` to version 0.26.4 and `filetime` to version 0.2.27.
- Removed the `backup.rs` file as it is no longer needed.
- Introduced tests for configuration and credential management.
- Enhanced the `identity` module to generate W3C compliant DID documents.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Set up vue-i18n with English locale file containing 500+ keys organized
by view namespace. All 15 views converted to use t() calls instead of
hardcoded strings. Infrastructure ready for community translations.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>