Compare commits
4
Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
81ede159ac | ||
|
|
8e988be853 | ||
|
|
210f7f1b12 | ||
|
|
ed49cc974f |
Generated
+1
-1
@@ -104,7 +104,7 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "archipelago"
|
||||
version = "1.8.8-alpha"
|
||||
version = "1.8.9-alpha"
|
||||
dependencies = [
|
||||
"anyhow",
|
||||
"archipelago-container",
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
[package]
|
||||
name = "archipelago"
|
||||
version = "1.8.8-alpha"
|
||||
version = "1.8.9-alpha"
|
||||
edition = "2021"
|
||||
license.workspace = true
|
||||
description = "Archipelago Bitcoin Node OS - Native backend"
|
||||
|
||||
+21
-13
@@ -25,9 +25,9 @@ same class cannot silently return.
|
||||
| B3 HSTS: none on :80, `max-age=0` on :443 (actively clears cached policy) | `image-recipe/configs/nginx-archipelago.conf` | ✅ code |
|
||||
| B4 NPM manifest: `/etc/letsencrypt` mount + `NET_BIND_SERVICE` | `apps/nginx-proxy-manager/manifest.yml` | ✅ code |
|
||||
| B5 `portAuth` alias resolution + unanimous port-wide fallback | `neode-ui/src/views/discover/curatedApps.ts` | ✅ code |
|
||||
| B6 Catalog cache warmed at dashboard bootstrap | `neode-ui/src/App.vue` | ⬜ |
|
||||
| B7 NIP-07 bridge: host/port equality + reply to `event.origin` | `neode-ui/src/stores/appLauncher.ts` ✅ · `neode-ui/src/views/appSession/useNostrBridge.ts` ⬜ | 🔶 |
|
||||
| B8 Stale LND 0.18.4 refs in test expectations | `tests/lifecycle/remote-lifecycle.sh` + fixtures | ⬜ |
|
||||
| B6 Catalog cache warmed at dashboard bootstrap | `neode-ui/src/App.vue` | ✅ |
|
||||
| B7 NIP-07 bridge: host/port equality + reply to `event.origin` | `neode-ui/src/stores/appLauncher.ts` ✅ · `neode-ui/src/views/appSession/useNostrBridge.ts` ✅ | ✅ |
|
||||
| B8 Stale LND 0.18.4 refs in test expectations | `tests/lifecycle/remote-lifecycle.sh` | ✅ |
|
||||
|
||||
## C. Regression tests ("never again")
|
||||
|
||||
@@ -35,22 +35,30 @@ same class cannot silently return.
|
||||
|------|-------|--------|
|
||||
| C1 Rust: router v2 response shape, nested errors, failure reasons | B1 | ✅ |
|
||||
| C2 Rust: setup-token log extraction (live-captured 2.45.0 line shape) | B2 | ✅ |
|
||||
| C3 bats: `lnd-api-compat` — POST `/v2/router/send` on the running LND must answer (never 404) | B1 vs image skew at gate time | ⬜ |
|
||||
| C4 bats: nginx must NOT send HSTS on :80; :443 must send `max-age=0` | B3 | ⬜ |
|
||||
| C5 neode-ui unit: portAuth alias + unanimous-scan (incl. bitcoin-knots→8334 https) | B5/B4-mixed-content | ⬜ |
|
||||
| C6 neode-ui unit: bridge origin equality ignores scheme | B7 | ⬜ |
|
||||
| C3 bats: `lnd-api-compat` — POST `/v2/router/send` on the running LND must answer (never 404) | B1 vs image skew at gate time | ✅ (route probe verified live on shorty: HTTP 500 ≠ 404) |
|
||||
| C4 bats: nginx must NOT send HSTS on :80; :443 must send `max-age=0` | B3 | ✅ |
|
||||
| C5 neode-ui unit: portAuth alias + unanimous-scan (incl. bitcoin-knots→8334 https) | B5/B4-mixed-content | ✅ (6 tests) |
|
||||
| C6 neode-ui unit: bridge origin equality ignores scheme | B7 | ✅ (2 tests) |
|
||||
|
||||
Backend suites: 34 targeted Rust tests green (payments v2 shape, setup-token
|
||||
extraction, lnd wallet/info regressions); middleware/dispatcher suite green;
|
||||
full neode-ui suite green (62 tests in the touched areas); production bundle
|
||||
built and verified to embed the alias fix. `cargo fmt` applied.
|
||||
|
||||
## D. Deploy & live verification
|
||||
|
||||
| Step | Status |
|
||||
|------|--------|
|
||||
| D1 shorty NPM crash-loop stopped cleanly (user-stopped marker; public hosts keep serving via host nginx mirror) | ✅ 12:52Z |
|
||||
| D2 shorty live nginx HSTS patch + reload | ⬜ |
|
||||
| D3 Regenerate catalog (releases/app-catalog.json + store copies) | ⬜ |
|
||||
| D4 **User runs `scripts/sign-catalog.sh`** (signer build running in background) | ⬜ |
|
||||
| D5 Commit + push (origin + gitea-vps2 OTA mirror) | ⬜ |
|
||||
| D6 OTA on shorty-s + framework-pt (Update button; framework-pt has no SSH from here) | ⬜ |
|
||||
| D7 Post-deploy live checks: LND send+receive; mempool/IndeeHub/bitcoin-UI frames over https; NPM healthy + admin :8081; portainer token card on fresh DB; zero CORS errors | ⬜ |
|
||||
| D2 shorty live nginx HSTS patch + reload | ✅ verified: :80 and :443 both answer `max-age=0` |
|
||||
| D3 Regenerate catalog (releases/app-catalog.json + store copies) | ✅ semantic diff = exactly the two NPM fixes |
|
||||
| D4 **User runs `scripts/sign-catalog.sh`** (signer built at /tmp/archy-sign-bin) | ⬜ waiting on mnemonic |
|
||||
| D5 Commit + push (origin + gitea-vps2 OTA mirror) | ✅ 6 commits pushed (signed catalog commits after D4) |
|
||||
| D6 Release v1.8.9-alpha: `scripts/create-release.sh 1.8.9-alpha` (mnemonic) → `scripts/publish-release-assets.sh 1.8.9-alpha gitea-vps2` | ⬜ waiting on mnemonic |
|
||||
| D7 OTA on shorty-s + framework-pt (Update button; framework-pt has no SSH from here) | ⬜ |
|
||||
| D8 shorty: clear the NPM user-stopped marker + Start (or it starts via the fixed catalog) | ⬜ |
|
||||
| D9 framework-pt: Start Mempool — its containers are confirmed stopped (port 4080 refuses; gate answers on 7778/8334/50002/18083 so those apps will embed over https immediately) | ⬜ |
|
||||
| D10 Post-deploy live checks: LND send+receive; mempool/IndeeHub/bitcoin-UI frames over https; NPM healthy + admin :8081; portainer token card on fresh DB; zero CORS errors | ⬜ |
|
||||
|
||||
framework-pt immediate workaround until its OTA lands: open the dashboard by
|
||||
IP (`http://192.168.x.x`) instead of `framework-pt.local`, and/or clear the
|
||||
|
||||
Generated
+2
-2
@@ -1,12 +1,12 @@
|
||||
{
|
||||
"name": "neode-ui",
|
||||
"version": "1.8.8-alpha",
|
||||
"version": "1.8.9-alpha",
|
||||
"lockfileVersion": 3,
|
||||
"requires": true,
|
||||
"packages": {
|
||||
"": {
|
||||
"name": "neode-ui",
|
||||
"version": "1.8.8-alpha",
|
||||
"version": "1.8.9-alpha",
|
||||
"dependencies": {
|
||||
"@scure/bip39": "^2.2.0",
|
||||
"@types/dompurify": "^3.0.5",
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
{
|
||||
"name": "neode-ui",
|
||||
"private": true,
|
||||
"version": "1.8.8-alpha",
|
||||
"version": "1.8.9-alpha",
|
||||
"type": "module",
|
||||
"scripts": {
|
||||
"start": "./start-dev.sh",
|
||||
|
||||
@@ -362,6 +362,20 @@ init()
|
||||
</button>
|
||||
</div>
|
||||
<div class="overflow-y-auto flex-1 min-h-0 space-y-6 pr-1">
|
||||
<!-- v1.8.9-alpha -->
|
||||
<div>
|
||||
<div class="flex items-center gap-2 mb-3">
|
||||
<span class="text-xs font-mono px-2 py-0.5 rounded bg-orange-500/20 text-orange-300">v1.8.9-alpha</span>
|
||||
<span class="text-xs text-white/40">September 1, 2026</span>
|
||||
</div>
|
||||
<div class="space-y-3 text-sm text-white/80 pl-3 border-l border-white/10">
|
||||
<p><strong>Lightning sends work again after the LND 0.21.2 update.</strong> LND 0.21 removed the payment route the node's backend used — every send answered "Not Found". Payments now go through LND's supported v2 router route, slow multi-hop payments are still tracked to completion (never falsely declared failed), failures explain themselves in plain language, and a new test speaks the payment route directly at release-gate time so an image/backend mismatch like this can never ship silently again.</p>
|
||||
<p><strong>HTTP and HTTPS both work, and no longer break each other.</strong> The HTTPS listener used to pin a year-long browser policy (HSTS); once your browser had visited HTTPS, it silently rewrote the HTTP dashboard's calls to HTTPS — cross-origin, so everything showed "Failed to fetch"/CORS errors while the node was healthy. The pin is gone, the HTTPS listener now actively clears the stale policy browsers already cached (visit HTTPS once after this update to clear yours), and plain-HTTP access — which is deliberate on nodes whose self-signed certificate you haven't installed — keeps working exactly as before.</p>
|
||||
<p><strong>Apps open over HTTPS again, including Mempool, Bitcoin and IndeeHub.</strong> The launcher looked each app's port policy up in the signed catalog under the name you click, but the catalog lists that port under the app that owns it — so Mempool "did not connect", Bitcoin opened a plain-http tab, and Nostr sign-in on IndeeHub silently did nothing over HTTPS. Launches now follow the alias to the owning manifest, the catalog is loaded before the first app you open (not just in the App Store), and the Nostr bridge replies to the app frame's real origin instead of a stale recorded address.</p>
|
||||
<p><strong>Nginx Proxy Manager starts again.</strong> Its manifest was missing two things its image requires — the LetsEncrypt folder mount and the permission to bind low ports — leaving it in an endless restart loop on nodes that had it installed. Both are declared now; your existing certificates are untouched, and the fix arrives via the signed catalog without waiting for this release.</p>
|
||||
<p><strong>Portainer's first-run token is on the app page, not buried in "server logs".</strong> New Portainer versions hand the first admin a one-time setup token that was only printed in the container logs — on this box, that token now appears with your app's other credentials, with a copy button, and disappears once setup is done.</p>
|
||||
</div>
|
||||
</div>
|
||||
<!-- v1.8.8-alpha -->
|
||||
<div>
|
||||
<div class="flex items-center gap-2 mb-3">
|
||||
|
||||
@@ -4046,7 +4046,8 @@
|
||||
"CHOWN",
|
||||
"SETUID",
|
||||
"SETGID",
|
||||
"DAC_OVERRIDE"
|
||||
"DAC_OVERRIDE",
|
||||
"NET_BIND_SERVICE"
|
||||
],
|
||||
"network_policy": "isolated",
|
||||
"no_new_privileges": true,
|
||||
@@ -4065,6 +4066,14 @@
|
||||
"source": "/var/lib/archipelago/nginx-proxy-manager",
|
||||
"target": "/data",
|
||||
"type": "bind"
|
||||
},
|
||||
{
|
||||
"options": [
|
||||
"rw"
|
||||
],
|
||||
"source": "/var/lib/archipelago/nginx-proxy-manager/letsencrypt",
|
||||
"target": "/etc/letsencrypt",
|
||||
"type": "bind"
|
||||
}
|
||||
]
|
||||
}
|
||||
@@ -5420,7 +5429,7 @@
|
||||
}
|
||||
},
|
||||
"schema": 1,
|
||||
"signature": "5f5bbb02ab88c9fbc4bf62a2c237a3e58912bd33ecf5bba67ad2705f0331b62a08b0e04dc6b03f76c236e5d4d316d80e982b112ecf0313a5a5e29c3289531308",
|
||||
"signature": "f982faeb9823062d9d39f6e4b38a171b4442cad0f35e74792ea161b5d77246ab9128044acbdc390ec23f921363af2d13bbba66c558b188d14d06a3f9a7f42406",
|
||||
"signed_by": "did:key:z6Mkfu5LT8d4DjETtrkATvHh9Dvcbnr7zBCUwfau8Sw7DLWT",
|
||||
"updated": "2026-09-01"
|
||||
}
|
||||
|
||||
@@ -0,0 +1,32 @@
|
||||
{
|
||||
"changelog": [
|
||||
"**Lightning sends work again after the LND 0.21.2 update.** LND 0.21 removed the old synchronous payment route the node's backend paid through (`/v1/channels/transactions`) — every Lightning send answered the literal \"Not Found\" and the wallet showed \"Payment failed: Not Found\". The backend now pays through the supported Router.SendPaymentV2 route, keeps the same settle-then-report behaviour (a slow multi-hop payment is still tracked to completion, never falsely declared failed), and translates LND's failure reasons into plain advice. A new gate test speaks the payment route directly against the running LND, so an image/backend skew like this can never ship silently again.",
|
||||
"**The node no longer pins HSTS — HTTP access is a supported mode, and it stays working.** The HTTPS listener used to send `Strict-Transport-Security: max-age=31536000; includeSubDomains`; browsers that visited HTTPS once cached that and then silently upgraded the still-open HTTP dashboard's calls to HTTPS, which is a scheme change — cross-origin — so every request died as \"CORS blocked / Failed to fetch\" while the node was perfectly healthy. The HTTPS listener now actively clears the cached policy (`max-age=0`) and port 80 sends no HSTS at all, which is deliberate: the node's certificate is optional and self-signed, and devices that haven't installed the CA must keep plain-HTTP access (that's what Settings → Node certificate is for). If your browser already cached the old policy, visiting the dashboard over HTTPS once after this update clears it; a gate test now refuses any config that reintroduces the pin.",
|
||||
"**App frames open over HTTPS again — including the ones that \"did not connect.\"** The launcher asked the signed catalog for each app's port policy under the name you click (\"Mempool Web\", \"Bitcoin Knots\"), but the catalog declares those ports under the manifest that owns them (the Mempool web container, Bitcoin UI). The lookup missed, the launcher handed the iframe an `http://` address, and the browser blocked it as mixed content — the app tile went blank or spun forever. Port resolution now follows launch aliases (mempool-web, bitcoin-knots/bitcoin-core, lnd, electrs and friends), falls back to a port-wide catalog scan when the id is unknown, and the catalog is warmed as soon as the dashboard loads rather than only in the App Store, so the very first app you open already knows which ports serve TLS.",
|
||||
"**Signing in to IndeeHub with Nostr works over HTTPS.** The NIP-07 bridge compared the app frame's origin for exact equality with the recorded `http://` app URL — a frame the browser upgraded to HTTPS (or any scheme change) was silently ignored, and replies addressed to the stale origin were refused outright, so Nostr sign-in quietly did nothing. The bridge now matches host and port (scheme intentionally ignored) and always replies to the frame's real origin.",
|
||||
"**Nginx Proxy Manager starts again.** Converting it to a platform manifest dropped two things its image needs: the `/etc/letsencrypt` mount its boot script hard-requires, and the `NET_BIND_SERVICE` capability its internal nginx needs to bind ports 80/443/81 under the orchestrator's `--cap-drop=ALL`. The result was an endless start/die loop (a node watched it restart 3,176 times). Both are declared in its manifest now, its certs live on unchanged under the same persistent app directory, and the signed catalog carries the fix so installed nodes heal on the next update.",
|
||||
"**Portainer's first-run token is in the app page, not buried in \"server logs.\"** New Portainer versions mint a one-time setup token on a fresh install and print it only to the container logs — on an appliance that meant telling the user to go read a server log to get into their own app. The token now appears in the same launch interstitial as app login credentials (with a copy button), only while first-run setup is actually pending; once the admin account exists the card disappears on its own."
|
||||
],
|
||||
"components": [
|
||||
{
|
||||
"current_version": "1.8.9-alpha",
|
||||
"download_url": "https://source.archipelago-foundation.org/lfg2025/archy/releases/download/v1.8.9-alpha/archipelago",
|
||||
"name": "archipelago",
|
||||
"new_version": "1.8.9-alpha",
|
||||
"sha256": "39795958963680f56763e3c05e3fe0cd589c30edd9a09416ad325bab4c862123",
|
||||
"size_bytes": 64139152
|
||||
},
|
||||
{
|
||||
"current_version": "1.8.9-alpha",
|
||||
"download_url": "https://source.archipelago-foundation.org/lfg2025/archy/releases/download/v1.8.9-alpha/archipelago-frontend-1.8.9-alpha.tar.gz",
|
||||
"name": "archipelago-frontend-1.8.9-alpha.tar.gz",
|
||||
"new_version": "1.8.9-alpha",
|
||||
"sha256": "624dd10dfea09809be1fdddc7eac804e1fde66ff3d552cb90d56d9ac550ed944",
|
||||
"size_bytes": 97734650
|
||||
}
|
||||
],
|
||||
"release_date": "2026-09-01",
|
||||
"signature": "d7d724b910e827651240bd9520102d66932b57a8a8d674ef645c45eb77f78c123fb45d294ec07f8bbfc3713ed9bd9f98096f59ff18cd6098df51aa473e771908",
|
||||
"signed_by": "did:key:z6Mkfu5LT8d4DjETtrkATvHh9Dvcbnr7zBCUwfau8Sw7DLWT",
|
||||
"version": "1.8.9-alpha"
|
||||
}
|
||||
Reference in New Issue
Block a user