Commit Graph
287 Commits
Author SHA1 Message Date
archipelago ed49cc974f docs: tracker updated — fixes landed, tests green, remaining steps are the two mnemonic ceremonies + node updates 2026-09-01 10:31:36 -04:00
archipelago 4849186ab9 docs: incident tracker for the 2026-09-01 https/launcher/LND breakage + v1.8.9 notes
Demo images / Build & push demo images (push) Successful in 3m57s
Root-cause table, fix inventory, regression-test inventory and the
deploy/live-verification checklist for today's fleet incident — written
as the working record while the fixes land, so the deploy + verify steps
can be checked off against real nodes rather than memory. CHANGELOG
carries the user-facing notes for the release these fixes ship in.
2026-09-01 10:29:10 -04:00
archipelago 3347b8b8b9 fix(ui): https app launches and the nostr bridge follow the frame's real origin
Three launcher/bridge defects combined to make HTTPS dashboards look
broken while HTTP ones worked:

1. portAuth() looked the launch port up under the name the user clicks
   ('mempool-web', 'lnd', 'bitcoin-knots'…), but the signed catalog
   declares those ports under the manifest id that owns them
   (archy-mempool-web, lnd-ui, bitcoin-ui). The lookup missed,
   portIsGateFronted answered false, and an HTTPS dashboard handed app
   frames http:// URLs — blocked as mixed content: mempool and IndeeHub
   'did not connect', bitcoin knots/core opened http:// in a new tab.
   Resolution now follows launch aliases, then a port-wide catalog scan
   that only answers when every declarer of that port agrees (a port
   any app publishes as plain HTTP is never upgraded to https).

2. The signed-catalog cache was only warmed by the Store/Discover
   views, so a user who went straight to My Apps launched apps with an
   empty cache. Warmed at dashboard mount now — fetchAppCatalog()
   already memoizes with a 1h TTL.

3. The NIP-07 bridge compared event.origin for strict equality with the
   recorded (http) app URL and replied to the recorded URL as the
   postMessage targetOrigin — both break the moment a frame is scheme-
   upgraded (cached HSTS did exactly that): every nostr request was
   silently dropped and replies to the stale origin threw. The bridge
   now matches host+port (scheme deliberately ignored) and always
   replies to event.origin — the frame's real origin.

Unit tests cover alias resolution (incl. bitcoin-knots→8334→https),
the conservative port-scan, and scheme-agnostic sender matching.
2026-09-01 10:29:05 -04:00
archipelago e382e679ae fix(apps): NPM needs /etc/letsencrypt mounted and NET_BIND_SERVICE
Converting Nginx Proxy Manager to a platform manifest (fc68c5b6) dropped
two things its image hard-requires, and the result was an endless
start/die loop — shorty-s watched it restart 3,176 times:

1. /etc/letsencrypt mount: NPM's s6 'prepare' service refuses to boot
   without it ('ERROR: /etc/letsencrypt is not mounted!'). Mounted from
   the same persistent app directory as before
   (/var/lib/archipelago/nginx-proxy-manager/letsencrypt), so existing
   certificates are preserved — no data moves, no migration.

2. NET_BIND_SERVICE: NPM's internal nginx listens on 80, 443 AND 81,
   and the orchestrator runs --cap-drop=ALL. The legacy podman-run path
   defaulted to the full capability set (and the legacy repair path in
   package/config.rs always listed it), which is why this only broke
   once the manifest became the source of truth.

The signed catalog embeds manifests with origin-wins semantics, so the
catalog carries the fix for every catalog-covered node — regenerate it
here (plus the generated store/launcher-port artifacts, which also pick
up drift from bf6ef964's retired apps). Catalog re-signing follows the
usual ceremony.
2026-09-01 10:29:05 -04:00
archipelago 77d0768a21 fix(nginx): stop pinning HSTS — actively clear it instead
The HTTPS server block sent Strict-Transport-Security:
max-age=31536000; includeSubDomains. Browsers that visited HTTPS once
cached the policy and then silently upgraded the still-open HTTP
dashboard's fetches and frames to https — a scheme change is
cross-origin, so every /rpc/v1 call died 'No Access-Control-Allow-
Origin header' while the node was perfectly healthy (framework-pt
2026-09-01: the 'Failed to fetch' storm, dashboard 'not responding',
every app frame mixed-content-blocked).

Plain HTTP is a supported access mode BY DESIGN on this platform: the
node's certificate is optional and self-signed (Settings → Node
certificate, /ca.crt flow), and setup-node-ca.sh deliberately keeps
port 80 serving for devices that haven't installed the CA. So:

- port 80 sends no HSTS at all (with the rationale inline)
- port 443 sends max-age=0, which ACTIVELY DELETES the policy already
  cached by affected browsers — leaving it absent would have kept every
  stranded browser broken for a year

tests/lifecycle/bats/nginx-hsts.bats pins all three properties at the
gate: no live policy on :80, max-age=0 (never 31536000) on :443, and
no long-lived pin anywhere in the deployed config.
2026-09-01 10:28:57 -04:00
archipelago f133d5555a feat(apps): surface Portainer's first-run setup token in the credentials interstitial
Portainer >=2.21 no longer lets whoever loads the page first claim the
admin account: on a fresh install it mints a one-time setup token and
prints it ONLY to the server logs. On an appliance that is a dead end —
'check the Portainer server logs' is exactly what a user cannot follow,
and after the 2.45.0 update it made a freshly restarted Portainer look
broken ('disappeared', then demands a token nobody can find).

package.credentials — the same RPC that powers the login-credentials
card on the app page — now extracts the setup_token line from
portainer's recent container logs and hands it over with the existing
copy-button treatment, titled and explained for a first-time user. The
token stops being printed once setup completes, and any container
recreate drops the log line, so the card disappears on its own and no
dead token lingers. Parsing is a pure, unit-tested scan against the
live-captured 2.45.0 log shape (64 hex chars after setup_token=).
2026-09-01 10:28:57 -04:00
archipelago cbd5314dd9 fix(lnd): pay through Router.SendPaymentV2 — LND 0.21 removed the old route
LND 0.21.2 removed the deprecated Lightning.SendPaymentSync REST route
(/v1/channels/transactions). The backend still called it, so every
Lightning send answered literal HTTP 404 and the wallet UI reported
'Payment failed: Not Found' fleet-wide right after the pin bump —
receive worked, which made it look intermittent.

Pay through the supported Router.SendPaymentV2 route (/v2/router/send)
instead, keeping the existing contract with the UI:
- single-record responses (no_inflight_updates) unwrapped from the
  grpc-gateway result envelope, transport errors from the nested error
- a slow multi-hop payment still resolves as pending + payment hash
  (only LND may declare failure), never a false 'Payment failed'
- LND's failure_reason codes translated to the same plain-language
  advice, invoice-expiry still says 'ask for a fresh invoice'

Guard it at the gate: tests/lifecycle/bats/lnd-api-compat.bats POSTs a
deliberately-invalid invoice to /v2/router/send on the RUNNING LND and
fails if the route answers 404 — the image/backend skew that shipped
silently last time because no test ever spoke the payment endpoint.
Also bumps the stale lnd image expectation in remote-lifecycle.sh.
2026-09-01 10:28:49 -04:00
archipelago 9fb2e1ed9e chore(catalog): sign the Cuprate logging fix 2026-09-01 08:47:29 -04:00
archipelago 7125dea05d Merge PR #152: fix Cuprate logging defaults 2026-09-01 08:39:26 -04:00
ssmithxandClaude Sonnet 5 bcdf2c75be fix(cuprate): file log level should be info, not cuprated's debug default
The previous commit on this branch copied cuprated's raw
--generate-config defaults (stdout=info, file=debug, max_log_files=7)
verbatim. Turns out that's the wrong reference: compared against
ssmithx@archy-dev-pa:/home/ssmithx/cuprate/Cuprated.toml — the actual
dev config this app was built and tested against — file logging is
meant to run at "info" with 14 rotated files, not the binary's raw
"debug"/7. Confirmed live on amishparadise: podman logs (stdout) was
already clean at info, but the on-disk file log
(.local/share/cuprate/logs/<date>) was flooding with per-peer DEBUG
gossip (~400KB in 2 minutes) because it inherited the binary default
instead of the intended one.

Left the resource-tuning knobs in the reference config (8GB
target_max_memory, tokio/rayon thread counts, P2P connection counts,
explicit reader_threads) out of this file — those were sized for
ssmithx's dev box and don't apply here; this manifest's
target_max_memory already stays deliberately under the container's
4Gi memory_limit.

Regenerated releases/app-catalog.json (still unsigned).

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Ga6N8Jk1YdCTMMX1LjDpAr
2026-09-01 12:27:33 +00:00
ssmithxandClaude Sonnet 5 e77f60085d fix(cuprate): make Cuprated.toml logging levels explicit
apps/cuprate/manifest.yml only ever wrote network/target_max_memory/
rpc.restricted.enable into Cuprated.toml, so the [tracing.stdout] and
[tracing.file] tables were silently absent — cuprated still applied
its built-in info/debug/7 defaults, but nothing on disk showed it.
Verified live on amishparadise 2026-09-01: the deployed 5-line file
had no [tracing] section at all, and the level was only discoverable
by running `cuprated --generate-config` and diffing.

Add both tables to the manifest's files[].content with the same
values cuprated already defaults to, so every new install ships a
Cuprated.toml an operator can actually read and tune. overwrite:false
means already-deployed nodes (amishparadise included) keep their
existing file untouched — this only changes what fresh installs get.

Regenerated releases/app-catalog.json (unsigned) to embed the updated
manifest; needs scripts/sign-catalog.sh before it's authoritative for
the fleet.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Ga6N8Jk1YdCTMMX1LjDpAr
2026-09-01 12:19:20 +00:00
archipelago 6c31eb9d4a chore(catalog): sign the LND 0.21.2 sweep 2026-09-01 07:45:39 -04:00
archipelago 63e6c64c63 fix(ci): drop the remaining stray Claude-worktree gitlinks 2026-09-01 05:27:15 -04:00
archipelago 4d8bb1fd44 fix(ci): drop a stray gitlink that broke every demo build
A Claude worktree under aiui/ was committed as a submodule gitlink
(160000) with no .gitmodules entry, so actions/checkout's recursive
submodule pass exited 128 and every 'Build & push demo images' run since
v1.8.6 failed. Removing the index entry — the worktree is local state
and was never meant to be tracked.
2026-09-01 05:27:00 -04:00
archipelago 2b4b60013c feat(lnd): build LND 0.21.2-beta in-house and sweep the pin
Demo images / Build & push demo images (push) Failing after 40s
Upstream publishes no docker images; our v0.18.4 image was built in-house.
This pass: official v0.21.2-beta release binaries (sha256-verified against
the signed release manifest), static, on alpine with the same entrypoint
shape as our existing image, pushed to our registry and smoke-run.
LND 0.21 auto-migrates the channel DB on first start (keeping a backup) —
the Update button is user-initiated, never auto-applied.
2026-09-01 05:14:50 -04:00
archipelago f0ef410948 chore(catalog): sign the swept pins 2026-09-01 04:52:28 -04:00
archipelago 19467e9b7c chore(apps): sweep pin bumps — gitea 1.27.3, vaultwarden 1.37.2, filebrowser 2.63.23, home-assistant 2026.8.3, adguardhome 0.107.79, portainer 2.45.0, pine-whisper 3.6.0
Demo images / Build & push demo images (push) Failing after 39s
First upstream sweep since v1.8.5: the safe patch/minor pins, mirrored
into our registry first (source.archipelago-foundation.org/lfg2025/*).
Held for their own careful passes: the majors (grafana 11, nextcloud,
uptime-kuma 2, bitcoin-core 29, the DBs) and consensus-sensitive apps
(fedimint, electrumx 2.0). LND 0.21.2 needs an in-house image build —
upstream publishes none.
2026-09-01 04:50:49 -04:00
archipelago 628ed252b4 chore: publish release v1.8.8-alpha 2026-09-01 04:18:16 -04:00
archipelago bc94445ca0 chore: sign the v1.8.8 app catalog + release manifest v1.8.8-alpha 2026-09-01 03:57:23 -04:00
archipelago 04cf0f663a chore: drop the superseded v1.8.8 prep for rebuild 2026-09-01 03:49:16 -04:00
archipelago 576c642da4 fix(apps): ollama resource type + adguardhome port; gate on collisions
Demo images / Build & push demo images (push) Failing after 38s
Ollama's embedded manifest failed the typed parse (memory_limit wants a
string) so the catalog overlay was skipped for it; AdGuard Home's
conventional :3000 collided with Grafana's. The release gate now runs
the host-port collision test (repo_app_manifests_have_no_host_port_collisions)
so this class can never ship untested again.
2026-09-01 03:31:02 -04:00
archipelago 12866db84a chore: sign the v1.8.8 app catalog + release manifest 2026-09-01 03:16:10 -04:00
archipelago a184254706 style: rustfmt the ssh-mesh module 2026-09-01 02:42:39 -04:00
archipelago 192e045426 feat(ui): SSH-over-mesh card, store-listing filter, icon treatment
Demo images / Build & push demo images (push) Failing after 41s
Settings gains the SSH-over-mesh card (danger-zone confirmation for the
any-peer scope, sshd preflights, fipssh copy hint). The signed-catalog
merge filters components via the shared serviceNames module; Discover
grids get the standard icon container; install no longer yanks the user
to My Apps; v1.8.8 release notes.
2026-09-01 02:41:55 -04:00
archipelago 9ac46a69f8 feat(fips): SSH-over-mesh toggle + manifest-driven package metadata
fips/ssh_mesh.rs owns the 90-ssh.nft drop-in lifecycle: off by default,
any-peer scope behind the UI's danger confirmation or an explicit mesh
address list, reconciled on every daemon config install. The scanner now
takes installed apps' icons from their real manifest metadata (Cuprate's
Services tile) and classifies manifest-declared UI apps as launchable
even when the address probe misses (Alby Hub).
2026-09-01 02:41:55 -04:00
archipelago bf6ef9644c chore(apps): retire morphos-server, did-wallet, lightning-stack, cryptpad
Store-listing components are filtered via the shared serviceNames canon;
these four never earn a tile: MorphOS server is old, the Web5 DID wallet
and CryptPad are untested, Lightning Stack is an untracked upstream
bundle (LND covers it).
2026-09-01 02:41:55 -04:00
archipelago c32910809e chore: publish release v1.8.7-alpha 2026-09-01 01:42:12 -04:00
archipelago d2174128c5 chore: sign the v1.8.7 app catalog + release manifest v1.8.7-alpha 2026-09-01 01:37:24 -04:00
archipelago 2ad0171e5f fix(ui): drop the now-unused scheme helper
Demo images / Build & push demo images (push) Failing after 36s
2026-08-31 19:08:17 -04:00
archipelago 46cb0bfd37 fix(ui): gate-fronted https launches + signed-catalog App Store
Demo images / Build & push demo images (push) Failing after 36s
directAppUrl(), the legacy open() path, and resolveRuntimeLaunchUrl()
now upgrade to https only for ports the app gate fronts — decided from
the signed catalog's embedded manifest ports (auth gated/open), so
plain-HTTP publishes (legacy installs, auth:none API ports like
Cuprate's RPC) keep http instead of failing outright. fetchAppCatalog()
merges the daemon-verified signed catalog into the App Store listing
(signed entries appear immediately; community copy supplies featured
and curated metadata), and Marketplace.vue uses the same dynamic fetcher
as Discover so the grid sees signed-new apps too.
2026-08-31 18:41:00 -04:00
archipelago b8593c9090 docs(release): v1.8.7 notes — https app launches + platform round
Demo images / Build & push demo images (push) Failing after 34s
2026-08-31 18:40:51 -04:00
archipelago fc68c5b680 feat(apps): complete the manifest platform — convert the last five stragglers
Demo images / Build & push demo images (push) Failing after 36s
Nginx Proxy Manager, Tailscale, Ollama, CryptPad, and AdGuard Home now
carry full manifests: the app gate fronts their web ports (TLS on the
same port, node login where appropriate), installs run through the
orchestrator, and pins live in the signed catalog. Tailscale mirrors its
legacy shape exactly (userspace networking, web console on 8240, plain
HTTP for the gate to front). Ollama stays loopback-only — the
assistant's local model backend, not a web app.

Retires the four already-removed apps for good (FIPS, Nostr VPN,
Routstr, Penpot pins dropped from image-versions.sh, the generator map,
and image_versions.rs), fixes Cuprate's duplicated metadata block that
strict YAML parsers reject, and updates the port-inventory review gates
for the new open (3 own-login consoles) and exempt (2 DNS) ports.
2026-08-31 18:40:39 -04:00
archipelago 3ed75c328d style: rustfmt the signed-catalog serving 2026-08-31 17:09:16 -04:00
archipelago 687196ad3b chore: prepare release v1.8.7-alpha
Demo images / Build & push demo images (push) Failing after 37s
2026-08-31 17:08:37 -04:00
archipelago e2bd6330a1 test(app-catalog): pin the signed-catalog body gate 2026-08-31 17:08:37 -04:00
archipelago 7c0a492c43 fix(ui): launch apps on the page's scheme over HTTPS
New-tab apps and the companion WebView got hardcoded http:// URLs, so a
node reached over HTTPS opened Vaultwarden, BTCPay, Grafana et al in
cleartext. Every app port is gate-owned and serves TLS on the same port
(appgate/tls.rs), so directAppUrl(), the legacy open() path, and
resolveRuntimeLaunchUrl() now follow the page's scheme. HTTP pages (the
kiosk, LAN) are unchanged; netbird keeps its unconditional https.
2026-08-31 17:08:26 -04:00
archipelago 3089624969 Merge remote-tracking branch 'gitea-vps2/main' 2026-08-31 16:15:17 -04:00
archipelago 5b658cec67 feat(app-catalog): serve the signed catalog from the node first 2026-08-31 16:15:13 -04:00
archipelago 21b8d4b1ee catalog: add Cuprate (0.1.0-preview) 2026-08-31 16:10:38 -04:00
lfg2025 6f05f5583f Merge pull request 'docs: session record — companion 0.5.28 shipped + deployment playbook' (#151) from companion/session-2026-08-31 into main 2026-08-31 20:03:03 +00:00
Dorian 02ac4396d1 docs: session record — companion 0.5.28 shipped + the deployment playbook
Full state at session end (all public surfaces verified byte-identical
at 0.5.28/vc48; only node web-bundle redeploys outstanding), the feature
map, and the operational playbook next sessions need: Tor SOCKS proxy
for Gitea API/curl (the 'unreachable API' was a missing proxy flag),
token scopes, protected-main ship flow via -ship branch + PR + API merge,
stale local main lineage, the foundation server's two surfaces, demo CI
auto-redeploy, build/test commands, and the open items.
2026-08-31 21:02:59 +01:00
archipelago 5ffdcc9936 docs(release): explain the v1.8.7 correction
Demo images / Build & push demo images (push) Failing after 39s
2026-08-31 15:46:18 -04:00
archipelago 9cf07e1eac fix(release): enforce the v1.8 What's New floor
Demo images / Build & push demo images (push) Failing after 39s
2026-08-31 15:44:48 -04:00
archipelago e7854702c0 chore: publish release v1.8.6-alpha
Demo images / Build & push demo images (push) Failing after 36s
2026-08-31 15:40:23 -04:00
archipelago d4018a6e73 chore: prepare release v1.8.6-alpha v1.8.6-alpha 2026-08-31 15:34:51 -04:00
archipelago b57cba63d1 Merge remote-tracking branch 'gitea-vps2/main'
Demo images / Build & push demo images (push) Failing after 36s
2026-08-31 15:12:59 -04:00
archipelago 7bc9f69b1f fix(settings): start What's New history at v1.8.0 2026-08-31 15:12:18 -04:00
lfg2025 913743923c Merge pull request 'docs: deploy handoff — companion 0.5.28 to the live surfaces' (#150) from companion/0.5.28-deploy-handoff into main 2026-08-31 19:01:58 +00:00
Dorian 241e8cfca4 docs: handoff — deploy companion 0.5.28 (vc48) to the live surfaces
For the archi-dev-box agent: companion 0.5.28 is on main (PR #149) and
Gitea raw serves it (verified byte-identical, v1+v2+v3). Remaining: the
foundation server's static /packages mirror (the real-node QR download
URL — currently 0.5.27), node web-bundle redeploys (same as the
2026-07-23 flow), and confirming the demo stack flipped after CI's
webhook redeploy. Exact commands, expected shasum, and final verify
block included.
2026-08-31 20:01:44 +01:00
archipelago 017505c431 fix(release): include every curated changelog item 2026-08-31 14:52:47 -04:00