136 Commits

Author SHA1 Message Date
Dorian
e679b4e886 feat(companion): night-test polish sweep — 0.5.9
Everything from tonight's remote field testing:

- Back-to-dashboard fixed: JS bridges on the retained WebView delegated
  through live-composition callbacks (stale closures made apps refuse to
  launch after remote ⇄ dashboard), and reattach forces a layout pass
  (top/bottom UI was wrong until a tap).
- F*CK IPs MESH branded loader: full-screen on relaunch (startup race)
  and during the first connect after scanning a node QR.
- Party 'Share this app' is now a QR of the public vps2 download link
  (scan with any camera → install over any internet); direct APK
  file-share kept as a secondary action.
- Mesh party pairing is MUTUAL: scanner announces itself to the scanned
  phone's Flare /hello — both sides get the peer, a chat entry and a
  '👋 joined the party' message; scanner auto-opens the chat.
- Party scanner asks for CAMERA permission (fresh installs/reinstalls
  landed on a black preview).
- Node: device tokens mint unique companion-<id> names — pairing a
  second phone no longer revokes the first phone's login (the source of
  'reconnecting a lot' and the second phone's failure).

Served APK: 0.5.9 (vc29).

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-24 02:03:47 +01:00
Dorian
1e20b79c3c feat(companion): kiosk session survives remote ⇄ dashboard navigation
The WEB_VIEW route recreated the WebView on every return from the
remote screen — full reload + re-login every time. The kiosk WebView is
now retained in a holder and reattached live (no race, no reload);
clients/bridges/listeners are re-bound to the new composition on
reattach, and the instance is dropped on retry, disconnect, or server
change so errored/stale sessions still reload for real.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-24 01:19:57 +01:00
Dorian
1bcf6ccadb feat(companion): share-the-app from Mesh Party + party entry on the intro screen — 0.5.8
- Party screen 'Share this app': shares this install's own APK through
  the system sheet (FileProvider over cache/share/), so a nearby friend
  gets the companion via Quick Share/Bluetooth with zero internet — the
  party-mode premise end to end.
- Intro screen: Mesh Party button under Get Started — party works with
  no node at all, so it belongs on the first screen a fresh install
  shows.
- Served APK: 0.5.8 (vc28), ready for the QR/OTA/ISO cut.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-24 01:16:54 +01:00
Dorian
f0926ece94 feat(companion): mesh party + Flare, keep-warm mesh, restored fast-start, UI fixes — 0.5.7
Combined session state from both agents (shared checkout):

- Mesh Party / Flare (experimental): phone-to-phone FIPS via party QR,
  Flare chat/beam on :5680, optional fixed UDP listen (2121); party-only
  phones get the baked-in Archipelago anchor so two bare phones reach
  each other across the internet, not just on a hotspot.
- Keep-warm mesh: a running healthy node survives app opens (restart
  only when dead or peers changed — peersDirty); requestMeshRestart for
  config changes. Cold start measured on-device: session in ~3.1s.
- Restored after regression: startup LAN-vs-mesh race (the party work
  was based on a pre-#114 file copy) and same-node routing (BTCPay/
  Pine/HA had returned to opening in the external browser).
- UI: top status-bar scrim removed (bottom-only bars); web app-session
  mobile bar is solid black — app theme colour no longer bleeds through
  the bar and its safe-area strip.

Served APK: 0.5.7 (vc27).

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-24 01:04:36 +01:00
Dorian
75ecd1d3ea feat(companion): 60s mesh probe window + session pre-warm from the VPN service
Implements the app-side recommendations from the node diagnosis
(HANDOFF-2026-07-23): first session through the public tree takes 15s+
when it works at all, far beyond the old ~8s probe window.

- connect(): mesh ULA probed inside a 60s budget, 15s per-phase timeouts.
- ArchyVpnService: session warmer probes every saved node ULA as soon as
  the tunnel is up (5s cadence first minute, then 60s keep-warm) so the
  UI hits a warm session and it never idles out.
- Served APK: 0.5.5 (vc25); handoff updated with 25-ping evidence that
  public-tree discovery currently fails outright (supports the
  private-tree infra decision).

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-23 23:36:34 +01:00
Dorian
53037b2b71 fix(companion): TUN reader no longer dies on non-blocking fd + VPN not metered
On-device diagnosis (phone on adb, 5G): mesh sessions established but no
packet ever entered the tunnel — Android hands the VpnService TUN fd over
non-blocking, and the fips fork's dedicated blocking-read thread treats
EAGAIN as fatal, dying at startup. archy-fips-core now forces the fd into
blocking mode before Node::start_with_tun_fd. Verified on-device: reader
survives, packets flow into the mesh, and the 30s anchor-link flap is
gone (stable 8+ min on 5G).

Also setMetered(false): Android 10+ defaults VPNs to metered, flipping
the phone into data-restricted behaviour whenever the mesh is up.

Served APK: 0.5.4 (vc24). Handoff updated with the remaining node-side
blocker: phone->anchor works, phone->node ULA gets no reply — needs
fipsctl introspection on Framework PT (suspect fork/daemon session or
routing mismatch).

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-23 22:47:26 +01:00
Dorian
e49af6ff40 fix(companion): guarantee dual-path peering — LAN p2p + public anchor, always
The whole point of FIPS: the phone peers with the node's npub using the
LAN endpoint as a direct p2p dial hint AND rendezvouses via a public
anchor when away — neither LAN nor 5G location may matter. The anchor
half only existed when the scanned QR carried fanchors, so pairing
against an older node left the phone LAN-only and everything died on 5G.

The Archipelago vps2 anchor (npub + 146.59.87.168:8444/tcp, lockstep
with core fips/anchors.rs) is now baked into upsertNodePeer as a
guaranteed peer. Mesh connect retry window widened so a first-ever
pairing survives the VPN consent dialog. Served APK: 0.5.3 (vc23).

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-23 22:17:24 +01:00
Dorian
979113c598 fix(companion): mesh VPN no longer blocks IPv4 + off-LAN connect via mesh ULA
Field test on 5G (Framework PT): pairing scanned fine but connect
hard-failed on the scanned LAN IP, and enabling the mesh VPN killed the
phone's internet.

- ArchyVpnService: the TUN is IPv6-only, and Android blocks every
  address family the VPN holds no address for — allowFamily(AF_INET)
  (+ allowBypass) so normal traffic flows while only fd00::/8 is routed.
- ServerConnectScreen.connect(): when the LAN address doesn't answer and
  the entry carries a mesh ULA, bring the tunnel up (autoStartIfReady)
  and probe the ULA with retries before reporting failure — the scanned
  IP is a dial hint, the npub/ULA is the identity (npub-first contract).
- Served companion APK refreshed as 0.5.2 (vc22); handoff doc updated.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-23 22:00:15 +01:00
Dorian
35849c88c6 chore(android): companion 0.5.1 (vc21) — refresh served APK + deploy handoff
The APK served from the pairing QR predated today's scanner fixes, so
the download-then-scan flow still hit the laggy scanner. Bumps the
version so phones update in place, refreshes the served artifact
(signed v1+v2+v3, verified), and adds the archi-dev-box deploy handoff.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-23 21:53:29 +01:00
Dorian
97464779d4 chore(android): update companion APK download [skip ci] 2026-07-22 22:06:32 +01:00
archipelago
184257390d feat(pine): 1.3.0 manifests — openwakeword member + live node status on the launcher page
Some checks failed
Demo images / Build & push demo images (push) Failing after 1m40s
pine-openwakeword manifest (wyoming-openwakeword 2.1.0, :10400, /custom model
dir for the future Yo Archy model). Pine 1.3.0: launcher page gains a live
node-status card fed by /api/pine/status via a same-origin nginx proxy, and
copy for the new intents / Claude fallback / mesh announcements. Catalogs,
app-session config, drift ids regenerated; release catalog embeds 56
manifests (unsigned until the ceremony). Framework PT test plan in docs/.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-22 02:59:34 -04:00
archipelago
46cfc2ccd7 chore(catalog): sync presentation catalogs — HA 2026.7.3, Pine 1.2.0
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-22 01:25:55 -04:00
Dorian
61d37c9798 chore(android): update companion apk download
All checks were successful
Demo images / Build & push demo images (push) Successful in 2m53s
2026-07-21 18:56:52 +01:00
archipelago
a71a18bffd fix(pine): serve the Connect-to-WiFi button over an http->https redirect
All checks were successful
Demo images / Build & push demo images (push) Successful in 2m47s
The launcher must be a secure context for Web Bluetooth, but the UI opens local
apps as http://host:port (resolveAppUrl), so an https-only launcher (v1.1.0)
would break the Open button with a TLS mismatch. Serve http on 10380 (the Open
target) that 301-redirects to the https listener on 10381, so the new tab lands
on https where navigator.bluetooth is available. Bump pine 1.1.0 -> 1.1.1;
re-sign the catalog (only the pine entry changes).

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-07-21 08:32:52 -04:00
archipelago
24cab326e2 feat(pine): interactive "Connect Pine to WiFi" button + republish catalog
All checks were successful
Demo images / Build & push demo images (push) Successful in 2m47s
Replace the launcher's text instructions with the real Improv-over-BLE
Web-Bluetooth provisioner (a "Connect Pine to WiFi" button, SSID/password
fields, live log) ported from the pine repo. Web Bluetooth needs a secure
context, so the launcher now serves HTTPS (self-signed): :80 (published 10380,
the Open target) 301-redirects to :10381, and open_in_new_tab keeps BLE out of
an iframe. Bump pine 1.0.0 -> 1.1.0.

Regenerate + re-sign releases/app-catalog.json (only the pine entry changes vs
v1.7.109) so nodes reconcile the button page live. Signed by the release-root
key did🔑z6MkkidEnEpo6qHMCNSZoNKWtvQvxq3whnaME9wGgEFhq7ur.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-07-21 08:25:24 -04:00
archipelago
c1dfc6672c feat(pine): surface Pine in the app catalog + UI
All checks were successful
Demo images / Build & push demo images (push) Successful in 2m48s
- catalog.json (app-catalog + neode-ui/public): one "pine" entry, home
  category; engines stay out of the catalog
- appsConfig.ts: pine → home category, pine-whisper/pine-piper → SERVICE_NAMES
  (render in Services, not as extra cards), pine-* icon fallback
- generatedAppSessionConfig.ts: regenerated (pine port 10380 + titles +
  open-in-new-tab), via scripts/generate-app-catalog.py

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-07-21 05:14:32 -04:00
archipelago
1730d02003 feat(pine): add Pine voice-assistant app package (manifests + icon)
Package the PineVoice/Wyoming local voice assistant as ONE store app "Pine"
that runs three rootless containers:

- pine-whisper — Wyoming faster-whisper STT (docker.io/rhasspy/wyoming-whisper
  3.4.1, model base-int8/en), publishes :10300
- pine-piper   — Wyoming Piper TTS (2.2.2, voice en_GB-alba-medium),
  publishes :10200
- pine         — nginx launcher serving a self-contained setup/status page
  (WiFi provisioning + Home Assistant wiring instructions), the Open target

The two engines publish their Wyoming ports so Home Assistant reaches them via
host.containers.internal. All rootless (cap-drop=ALL, no_new_privileges),
manifest-driven — no hardcoded podman/installer. The engines are internal stack
members (added to the drift-check INTERNAL_MANIFEST_IDS allowlist); only "pine"
carries a catalog entry.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-07-21 05:14:32 -04:00
archipelago
f32c4db7e2 style(ui): companion banner uses the Setup-tab hero image
Some checks failed
Demo images / Build & push demo images (push) Failing after 3m10s
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-16 21:51:12 -04:00
archipelago
3aebbcbbb8 feat(setup): Zeus lightning journey — fund-wallet step, IBD timer + finish-setup toast, channel suggestions
Every Lightning setup (Open a Shop, Accept Payments, Run a Lightning Node)
gains a guided path to a working channel:

- New "Fund Your Bitcoin Wallet" step, gated on the blockchain finishing
  its initial sync: while syncing it shows a live progress bar with a
  counting-down time-remaining estimate; once synced it shows the on-chain
  balance and a "Fund Wallet" button that opens the receive modal with a
  fresh address, QR, and the Zeus channel limits (min 150,000 / max
  1,500,000 sats) noted.
- When the sync finishes while a Lightning setup is mid-flight, a toast
  pops with a "Finish setup" link straight back to the wizard (toasts now
  support action links). If several setups are in flight, one is chosen —
  the shared steps complete the lightning part of any of them.
- Channel steps are Zeus-branded (logo + copy) and land on the Lightning
  Channels screen, which now carries an "Open a channel with Zeus" card
  that prefills the open-channel modal with the Olympus peer URI, 150k
  sats, and private-channel checked. "Get Zeus" links to zeusln.com.
- Setup completion now actually requires walking the manual steps (fund,
  open channel, configure) — previously any step whose app was installed
  was silently auto-ticked and running apps marked the whole goal done.
- Completion CTAs now go to the app you just set up ("Go to my shop
  (BTCPay)" etc.) instead of the generic services list; iframe apps open
  in the on-top app overlay.
- On-chain send modal gains a "Send all funds" sweep toggle, backed by
  LND's send_all on the backend (amount no longer required when sweeping).
- Demo/mock: bitcoin.getinfo now returns the block_height/sync_progress
  contract the UI reads and simulates a ~90s IBD ramp per visitor so the
  timer, toast, and fund flow can all be demoed live; channel list data
  fixed (status/channel_point/liquidity totals — the panel previously
  crashed on the missing status field); sendcoins supports send_all.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-16 21:51:12 -04:00
Dorian
af2dfd0bd6 chore(ui): mirror official WireGuard Android APK for the pairing flow
com.wireguard.android 1.0.20260315 (versionCode 519) from
download.wireguard.com, signer WireGuard LLC (cert sha256 84a13fa2…),
file sha256 f92971bc804f4c448e8845ae97e426095eab06ec09a2473a3fa2cfe7288e3298.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-17 02:32:02 +01:00
Dorian
bb231e82b4 fix(ui): web5 cards mobile polish + demo identity avatars
- Identities render as profile cards (banner, overlapping avatar, bio)
  in narrow containers via container query; wide/desktop row untouched
- Demo identities get purpose-tinted SVG avatars (public/demo-avatars)
  in both mock identity.list/get branches
- Node Visibility: description stacks under icon+title on mobile,
  Refresh is a full-width bottom action on all sizes, discoverable
  warning line removed, and the demo no longer exposes an onion address

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-17 02:12:54 +01:00
Dorian
a48499daeb chore(android): update companion apk download 2026-07-17 02:03:27 +01:00
9d21dd5111 Merge pull request 'feat(android): companion QR pairing — scan, deep link, auto-login (v0.4.13)' (#92) from companion-qr-pairing into main
All checks were successful
Demo images / Build & push demo images (push) Successful in 2m34s
2026-07-17 00:46:47 +00:00
Dorian
ddbfaf1d00 chore(android): update companion apk download 2026-07-17 01:46:24 +01:00
archipelago
2e5f67a59a feat(ui): companion app banner in the App Store + APK download unblocked
Some checks failed
Demo images / Build & push demo images (push) Has been cancelled
The App Store gains a "Your Node. In Your Pocket." hero banner for the
mobile companion app, in the same format as the featured-app banner, with
the app running on a phone mockup rising out of the right edge. Install
(or clicking anywhere on it) opens the Remote Companion download/pairing
modal — now openable on demand via a shared trigger instead of only
auto-showing once.

Also fixes the companion APK download on PWA installs: /packages/ now
bypasses the service worker's SPA fallback, which was answering the
download click with index.html instead of the file.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-16 20:46:08 -04:00
Dorian
785fb3d2be chore(android): update companion apk download 2026-07-17 01:41:59 +01:00
Dorian
efd1ae41de fix(intro): splash always honors App's decision + video streams 3x lighter
- SplashScreen no longer re-checks neode_intro_seen itself: it silently
  skipped the whole logo-tap/typing sequence for any browser that had
  seen the intro before, even when App.vue explicitly requested it (demo
  fresh visits, Replay Intro). App.vue is the single decision point.
- Intro video re-encoded 12.7MB/12.6Mbps → 4.3MB/4.2Mbps (1920x1080 CRF23
  faststart, muted track dropped) — visually identical on this
  illustrated content; cache-buster bumped to v=8.
- Video is <link rel=preload>ed the moment the splash is scheduled (the
  <video> element only mounts ~20s in, so cold caches used to start the
  download mid-sequence and stutter).
- nginx demo cache regex now covers mp4/webm/mp3/webp/woff2 so repeat
  visits play from browser cache.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-15 11:53:14 +01:00
Dorian
128c13e965 Merge remote-tracking branch 'origin/main' into ark-merge 2026-07-14 22:08:55 +01:00
Dorian
6fa0aa46a9 feat(ui): Ark wallet tab, balances, history badge + demo mocks
Ark tab in Wallet Settings (status, balances, receive address,
board/offboard, server config via wallet.ark-*), teal Ark badge in the
transactions modal, Ark row on the home wallet card (hidden until barkd
reports a balance), official bark icon, and wallet.ark-* mocks so the
public demo renders the tab.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-14 21:57:12 +01:00
archipelago
7b36b5cc34 feat(mesh): device-detected setup modal with board images + full radio settings
Plugging in a LoRa radio now pops a global two-step setup modal on any
page: step 1 shows the ACTUAL detected board (25 board SVGs vendored
from the Meshtastic web-flasher, GPL-3.0; matched by USB product string
on native-USB boards, vid:pid heuristics for bridge chips, animated
fallback otherwise); step 2 configures with Archipelago presets — the
LoRa region pre-selected from the node's location (new lat/lon→region
mapping), channel 'archipelago', node name, and an advanced firmware
pin. Options adapt per protocol: region+channel program Meshtastic;
MeshCore shows its community frequency plan (firmware owns RF); RNode
defers to the Reticulum daemon config.

Backend: mesh.configure now accepts lora_region (validated against the
driver's region table) and device_kind (probe pin); mesh.status returns
the persisted values plus per-port USB identity (sysfs vid/pid/product)
for board identification. The Mesh Device tab gains a full settings
form (region with duty-cycle/legality hints, firmware pin, channel,
name, identity broadcast) replacing the read-only panel; the old
Mesh-page-only onboarding modal is superseded by the global flow.

Mock backend: stateful mesh config so the dev UI demos the full
detect→configure round-trip (disable mesh → modal fires with Heltec V3).

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-14 08:40:18 -04:00
archipelago
b48ea85961 chore(apps): remove six fake bookmark apps
484.kitchen, Arch Presentation, Call the Operator, Next Web News
Network, Syntropy Institute, and T-0 were hardcoded web-only bookmark
apps (no manifests/containers). Removed across the frontend app grid /
curated / marketplace / session / launcher data, the backend
AppMetadata table, their icons, and the nginx /ext/ proxy blocks
(external-app-proxies.conf deleted — nothing installed it anymore).
botfights/nostrudel/gitea keep the shared external-app code paths.

Frontend: vue-tsc clean, 672 tests pass, production build verified
clean of the removed slugs. Backend: cargo check clean.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-14 06:56:03 -04:00
archipelago
13ee019b85 revert(ui): restore previous web5 dashboard background image
The Jul 10 asset swap (75ed3041) replaced the progressive JPEG with a
baseline re-encode that trips the known Chromium compositor black-layer
bug in the 3D perspective background stack — the image paints for a
second, then the layer drops and the #000 container fill shows through.
Restore the pre-swap progressive encoding.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-14 05:29:20 -04:00
Dorian
59cc10f4aa fix: LND icon svg→png in neode-ui public catalog too
00a70c6 fixed app-catalog/catalog.json but the served copy in
neode-ui/public/catalog.json still pointed at the nonexistent lnd.svg.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-13 20:09:34 +01:00
Dorian
4b0e44fc6c chore: purge retired git.tx1138.com registry host from the codebase
The tx1138 Gitea was retired as a release server 2026-06-13 and its registry
frontend is fully dead (500 on every /v2 manifest read, observed 2026-07-10).
Nothing may reference it anymore:

- registry.rs: no longer a default registry, no longer force-enabled on
  load; saved configs are stripped of it on load (same one-time migration
  treatment as the decommissioned Hetzner mirror), with a regression test.
- image_policy.rs: removed from TRUSTED_REGISTRIES — refs through the dead
  host are now refused at the pull site (rejection test added).
- api/handler: dropped the legacy catalog-proxy fallback URL.
- .gitmodules: indeedhub submodule repointed to the OVH Gitea.
- scripts, image-recipe, app-catalog data, neode-ui strings, docs, and all
  test fixtures repointed to 146.59.87.168:3000 (or neutral example hosts).
- image-versions.sh: ARCHY_REGISTRY_FALLBACK emptied (guarded consumers
  skip it); reconcile-containers.sh candidate guard hardened.

The only remaining occurrences of the host string are the strip/reject
enforcement paths and their regression tests — the code that guarantees it
is never used again.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-10 18:55:32 +01:00
archipelago
9b1c090e21 Merge feat/mesh-archy-command: lightning channel controls + open-race fix
Channel open fee control, channels tab in wallet settings, mempool tx
link, and the channel-open async peer-connect race fix. Conflict in
LightningChannels.vue resolved to the branch's extracted
LightningChannelsPanel component, with main's Teleport-to-body modal
fixes and glass-button-warning class (8256fde1) ported into the panel
so they aren't lost. lnd tests 16/16, LightningChannels vitest green.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-10 10:42:54 -04:00
Dorian
75ed3041dc chore(ui): update bg-web5 background asset
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-10 15:12:01 +01:00
archipelago
c375ecc441 fix: fresh-ISO feedback bug-bash — onboarding, status truthfulness, recovery, kiosk, logs
Fixes from real fresh-install feedback (Framework node .81) + its log bundle:

Backend:
- websocket: subscribe before initial snapshot — broadcasts in the gap were
  silently lost, stranding clients on stale state until a hard refresh
  (the "everything needs ctrl-r" bug: My Apps stuck Loading, App Store
  stuck Checking, containers-scanned never arriving)
- crash recovery: check the crash marker BEFORE writing our own PID —
  recovery had never run on any node (always saw its own PID and skipped);
  PID-reuse guard via /proc cmdline
- boot status: pending-boot-starts registry (recovery, stack recovery,
  reconciler, adoption) — scanner overlays queued-but-down apps as
  Restarting instead of Stopped after a reboot; scanner-authored
  Restarting resolves immediately on a settled scan (no transitional wedge)
- install deps: bounded wait (36x5s) when a dependency is installed but
  still starting ("Waiting for Bitcoin to start…") instead of instant
  rejection; dependency-gate rejections remove the optimistic entry (no
  phantom Stopped tile) and surface as a notification
- seed backup: auth.setup persists the onboarding mnemonic as the
  encrypted seed backup (reveal previously failed on EVERY node — nothing
  ever wrote master_seed.enc); seed.restore stashes too; error sanitizer
  lets seed/2FA errors through instead of "Check server logs"
- lnd: bitcoind.rpchost resolved from the running Bitcoin variant
  (hardcoded bitcoin-knots broke Core nodes); manifest uses derived_env
- bitcoin status: clean human message for connection-reset/startup; raw
  URLs + os-error chains no longer reach the app card
- fedimint-clientd: chown /var/lib/archipelago/fmcd to 1000:1000 (root-
  created dir crash-looped the rootless container, EACCES) — first-boot
  script + pre-start self-heal
- log volume (>1GB/day on a day-old node): journald caps drop-in (ISO +
  bootstrap self-heal), bitcoind -printtoconsole=0 everywhere (90% of the
  journal was IBD UpdateTip spam), tracing default debug→info

Frontend:
- Login: Enter advances to confirm field then submits; submit always
  clickable with inline errors (was silently disabled on mismatch);
  Restart Onboarding needs a confirming second click (the mismatch →
  "onboarding restarted" trap)
- sync store: 30s state reconciliation + refetch on re-entrant connect;
  20s containers-scanned escape hatch so Checking can never show forever;
  fresh empty node reaches the real "no apps yet" state
- intro video: CRF20 re-encode (SSIM 0.988) + faststart — moov was at EOF
  so playback needed the full 15MB first (the intro lag)
- backgrounds: 10 heaviest JPEGs → WebP q90 (9.4MB→6.6MB); 7 stayed JPEG
  (WebP larger on noisy sources)
- Web5ConnectedNodes: drop unused template ref that failed vue-tsc -b

ISO/kiosk:
- nginx: /assets/ 404s no longer cached immutable for a year; HTTPS block
  gained the missing /assets/ location (served index.html as images)
- kiosk: launcher/service spliced from configs/ at ISO build (stale
  heredoc force-disabled GPU); MemoryHigh/Max 1200/1500→2200/2800M (kiosk
  rode the reclaim throttle = the lag); firmware-intel-graphics +
  firmware-amd-graphics (trixie split DMC blobs out of misc-nonfree)

Verified: cargo test 898/898 green, npm run build green with dist
contents confirmed (webp refs, lnd.png, faststart video, new strings).
Handover for ISO build + deploy: docs/HANDOVER-2026-07-02-iso-feedback.md

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-02 08:00:39 -04:00
archipelago
4c3aa8cc8e fix(icons): remove remaining electrs icon references, use electrumx.png
GoalDetail.vue, EasyHome.vue, and the backend's docker_packages.rs
metadata still pointed electrs-family app ids at the old electrs
icon (svg). Point them at electrumx.png like every other reference,
and delete the now-unused electrs.svg asset.
2026-07-01 14:48:14 -04:00
archipelago
ed95d54ffe chore(assets): replace lnd icon svg with png
lnd.svg no longer exists; every reference now points at lnd.png.
2026-07-01 14:41:15 -04:00
archipelago
7d2ac1f842 chore(assets): update searxng app icon 2026-07-01 14:36:12 -04:00
archipelago
c2c4b5af7d merge: demo build updates
# Conflicts:
#	neode-ui/src/stores/appLauncher.ts
#	neode-ui/src/views/AppSession.vue
2026-06-30 05:22:42 -04:00
archipelago
df9d3a55be integration: preserve deployed 1.8.0 OTA work 2026-06-30 05:08:17 -04:00
archipelago
6734947c3e fix(fmcd): cap CPU + watchdog-restart the iroh relay hot-loop
On NAT'd nodes that can reach the iroh federation neither directly nor
via iroh's public relays, fmcd's embedded iroh networking enters a
relay/hole-punch reconnect hot-loop that pegs its entire CPU allotment
indefinitely (observed ~1 core sustained for 4 days on a Tailscale node,
while LAN nodes that reach the guardian directly stay <3%). fmcd 0.8.0
exposes no iroh/relay knobs, so:

- fmcd-run now samples fmcd's own CPU and restarts it when it stays near
  its allotment for ~15 min (a restart demonstrably clears the stuck iroh
  state; real work is bursty and never flat-pegs a core for minutes).
- Lower cpu_limit 1 -> 0.25 core so a stuck instance can't starve the
  node (steady-state is <3% of a core; joins are brief).

Ships as fmcd:0.8.1 (launcher-only rebuild, same fmcd binary). Bumped the
image pin + cpu_limit in the manifest, image-versions.sh, the embedded
catalog manifest (releases/app-catalog.json), and the UI catalogs.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-28 12:19:27 -04:00
archipelago
f9a6ae3f32 feat(mesh): Meshtastic region + shared-channel auto-provisioning (MeshCore parity)
Fresh Meshtastic radios ship region-UNSET (RF-silent) and on mismatched
channels, so nodes only ever saw themselves. Bring them to MeshCore parity
using the official Meshtastic admin API:

- Auto-provision LoRa region (set_config, AdminMessage field 34) from a new
  mesh-config `lora_region` (e.g. EU_868) when the radio's region differs.
- Auto-provision a shared primary channel (set_channel, field 33) with a
  PSK derived deterministically from channel_name, so every node converges on
  one mesh — the parity equivalent of MeshCore's named "archipelago" channel.
- Read current region/channel from want_config; only write when different
  (no reboot loop); cap attempts so a radio that won't persist can't loop.
- Active NodeInfo advert scaffolding + aggressive serial drain.

Verified on .116+.228: region+channel persist, discovery works (both see each
other as named reachable contacts), bidirectional RF + sending confirmed.
Receiving in the running driver is still under diagnosis (instrumentation added).

Also removes the unwanted `meshtastic` daemon app from the registry (it was
never meant to be a container — native driver provides system-level support):
deletes apps/meshtastic + catalog entries (app-catalog, neode-ui, releases) +
test refs. Meshtastic stays native, like MeshCore.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-27 04:46:35 -04:00
Dorian
38d2bbf570 chore(android): update companion APK download [skip ci] 2026-06-26 13:08:37 +01:00
Dorian
a90fea80ed feat(android): edit server entries from in-app settings menu (NESMenu); bump to 0.4.12 (vc16)
The 0.4.11 edit affordance only lived on ServerConnectScreen, which a
connected user never sees. Add edit to NESMenu — the settings modal
reached via two-finger hold while connected: a ✎ pencil on each saved
server opens the form pre-populated (Edit Server header + Cancel),
persists via ServerPreferences.updateSavedServer(), and reconnects when
the edited server is the live one.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-26 13:08:18 +01:00
Dorian
389e602097 chore(android): update companion APK download [skip ci] 2026-06-26 12:54:52 +01:00
Dorian
5677f9cca1 feat(android): edit saved server entries; bump companion to 0.4.11 (vc15)
Add an edit affordance to each saved server in ServerConnectScreen: a
pencil button loads the entry into the form (Edit Server mode) with
Save Changes / Cancel actions. Persisted via a new
ServerPreferences.updateSavedServer() that replaces by connection
identity (address/port/scheme) and keeps the active record in sync when
the edited server is the active one.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-26 12:54:07 +01:00
Dorian
ac59771560 fix(android): force v1+v2+v3 signing & clean-build guards in companion publish
The published companion APK was v2-only (AGP silently ignores
enableV1Signing for minSdk>=24) and clean builds broke on stray
space-named resource dirs. Harden scripts/publish-companion-apk.sh:
clean build, remove/ýreject space-named res dirs, force v1+v2+v3 via
zipalign+apksigner, and abort unless all three schemes verify. Wire
ship-companion.sh to the shared script. Re-sign the served 0.4.10 APK.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-26 11:53:25 +01:00
Dorian
d1f9e9ce88 chore(android): update companion apk download 2026-06-26 11:32:00 +01:00