chore(release): prep v1.8.11 notes and link checks
This commit is contained in:
@@ -1,5 +1,11 @@
|
|||||||
# Changelog
|
# Changelog
|
||||||
|
|
||||||
|
## v1.8.11-alpha (2026-09-07)
|
||||||
|
|
||||||
|
- **Cuprate now syncs without burning a core for days.** The app's shipped config now enables Cuprate's checkpoint-backed `fast_sync` path, raises the database cache to 8 GiB, and gives the container a 10 GiB memory limit so the cache has real headroom. A live comparison that motivated the change saw the affected node sit around 45% CPU while the corrected config held near low single digits at the same chain height and block rate. The restricted RPC remains fronted through the safe app gate/Tor path.
|
||||||
|
|
||||||
|
- **OpenWrt Gateway setup is documented from a real install, and two setup bugs are fixed.** The new guide walks a node operator through flashing a GL.iNet AX3000 to stock OpenWrt, pairing it with Archipelago, and installing TollGate pay-as-you-go WiFi. The installer now finds `opkg`/`apk` through the router's actual `PATH` instead of assuming `/usr/bin`, the UI no longer sends an empty password over a saved router connection, and the pinned TollGate package moves to `v0.5.0` with a native `.apk` install path where upstream provides one.
|
||||||
|
|
||||||
## v1.8.10-alpha (2026-09-02)
|
## v1.8.10-alpha (2026-09-02)
|
||||||
|
|
||||||
- **Lightning sends work again — v1.8.9's payment switch lost the fee budget.** Moving payments to LND 0.21's supported route (Router.SendPaymentV2) shipped without a fee limit, and the v2 API treats an absent limit as **zero allowed fees**: every real route carries a routing fee, so the pathfinder rejected them all and the wallet answered "No route to the recipient" on every send — all day, on healthy channels with plenty of liquidity. The router debug log made it unambiguous (`fee_limit=0 mSAT` on every failing wallet payment; the same payment succeeded by hand the moment a fee limit was set). Payments now carry lncli's default budget (the payment amount), the wallet's amount handling for zero-value invoices is preserved, and a unit test pins the limit can never be zero again.
|
- **Lightning sends work again — v1.8.9's payment switch lost the fee budget.** Moving payments to LND 0.21's supported route (Router.SendPaymentV2) shipped without a fee limit, and the v2 API treats an absent limit as **zero allowed fees**: every real route carries a routing fee, so the pathfinder rejected them all and the wallet answered "No route to the recipient" on every send — all day, on healthy channels with plenty of liquidity. The router debug log made it unambiguous (`fee_limit=0 mSAT` on every failing wallet payment; the same payment succeeded by hand the moment a fee limit was set). Payments now carry lncli's default budget (the payment amount), the wallet's amount handling for zero-value invoices is preserved, and a unit test pins the limit can never be zero again.
|
||||||
|
|||||||
@@ -362,6 +362,17 @@ init()
|
|||||||
</button>
|
</button>
|
||||||
</div>
|
</div>
|
||||||
<div class="overflow-y-auto flex-1 min-h-0 space-y-6 pr-1">
|
<div class="overflow-y-auto flex-1 min-h-0 space-y-6 pr-1">
|
||||||
|
<!-- v1.8.11-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.11-alpha</span>
|
||||||
|
<span class="text-xs text-white/40">September 7, 2026</span>
|
||||||
|
</div>
|
||||||
|
<div class="space-y-3 text-sm text-white/80 pl-3 border-l border-white/10">
|
||||||
|
<p><strong>Cuprate now syncs without burning a core for days.</strong> The app's shipped config now enables Cuprate's checkpoint-backed fast_sync path, raises the database cache to 8 GiB, and gives the container a 10 GiB memory limit so the cache has real headroom. A live comparison that motivated the change saw the affected node sit around 45% CPU while the corrected config held near low single digits at the same chain height and block rate. The restricted RPC remains fronted through the safe app gate/Tor path.</p>
|
||||||
|
<p><strong>OpenWrt Gateway setup is documented from a real install, and two setup bugs are fixed.</strong> The new guide walks a node operator through flashing a GL.iNet AX3000 to stock OpenWrt, pairing it with Archipelago, and installing TollGate pay-as-you-go WiFi. The installer now finds opkg/apk through the router's actual PATH instead of assuming /usr/bin, the UI no longer sends an empty password over a saved router connection, and the pinned TollGate package moves to v0.5.0 with a native .apk install path where upstream provides one.</p>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
<!-- v1.8.10-alpha -->
|
<!-- v1.8.10-alpha -->
|
||||||
<div>
|
<div>
|
||||||
<div class="flex items-center gap-2 mb-3">
|
<div class="flex items-center gap-2 mb-3">
|
||||||
@@ -369,9 +380,9 @@ init()
|
|||||||
<span class="text-xs text-white/40">September 2, 2026</span>
|
<span class="text-xs text-white/40">September 2, 2026</span>
|
||||||
</div>
|
</div>
|
||||||
<div class="space-y-3 text-sm text-white/80 pl-3 border-l border-white/10">
|
<div class="space-y-3 text-sm text-white/80 pl-3 border-l border-white/10">
|
||||||
<p><strong>Lightning sends work again.</strong> v1.8.9's move to LND 0.21's supported payment route shipped without a fee budget, and the API treats a missing one as zero allowed fees — so every wallet send failed "No route to the recipient" all day, on perfectly healthy channels. Payments now carry a proper fee budget and a test keeps it from ever regressing.</p>
|
<p><strong>Lightning sends work again — v1.8.9's payment switch lost the fee budget.</strong> Moving payments to LND 0.21's supported route (Router.SendPaymentV2) shipped without a fee limit, and the v2 API treats an absent limit as <strong>zero allowed fees</strong>: every real route carries a routing fee, so the pathfinder rejected them all and the wallet answered "No route to the recipient" on every send — all day, on healthy channels with plenty of liquidity. The router debug log made it unambiguous (fee_limit=0 mSAT on every failing wallet payment; the same payment succeeded by hand the moment a fee limit was set). Payments now carry lncli's default budget (the payment amount), the wallet's amount handling for zero-value invoices is preserved, and a unit test pins the limit can never be zero again.</p>
|
||||||
<p><strong>A channel that drops its peer link now heals itself — on every node.</strong> Restarting LND (an app update, a reboot, container churn) can leave a channel's peer connection down for hours while both endpoints keep the channel flagged disabled in the routing graph: the node looks perfectly healthy, the wallet shows balance, and every payment in either direction fails "no route to the recipient". The daemon now watches the channel graph as desired state — every open channel should have a live peer — and reconnects any that don't. Nodes without LND are untouched; an unreachable peer is retried gently.</p>
|
<p><strong>A channel that drops its peer link now heals itself — on every node.</strong> Restarting LND (an app update, a reboot, container churn) can leave a channel's peer connection down for hours while both endpoints keep the channel flagged disabled in the routing graph: the node looks perfectly healthy, the wallet shows balance, and every payment in either direction fails "no route to the recipient". Observed live: a node's only channel sat unroutable for ~17 hours after the LND 0.21.2 update, with no sign of it in any dashboard. The daemon now watches the channel graph as desired state — every open channel should have a live peer — and reconnects any that don't, using the peer's advertised addresses. Nodes without LND are untouched; an unreachable peer is retried gently, not hammered.</p>
|
||||||
<p><strong>The Lightning wallet says what's actually wrong, instead of "you have no channel".</strong> Trying to send while a channel you just opened was still confirming — or when all its balance sits on the far side — produced a modal claiming you had no channel at all, and payment routing failures even showed the receiving copy. The gate now reads your real channel list: a confirming channel gets "it unlocks automatically once confirmed, nothing is needed from you", a far-side balance gets "you can receive, but there's nothing to send right now", and only a genuinely channel-less node is sent to open one.</p>
|
<p><strong>The Lightning wallet states the node's real funding state instead of "you have no channel."</strong> Trying to send while a freshly opened channel was still waiting for on-chain confirmations — or when all its balance sits on the far side — raised a modal that claimed the node had NO channel at all (the outbound sum is legitimately zero in both states), pointed the user at opening a second channel, and — for payment routing failures — even showed the <em>receiving</em> copy. The funding gate now reads the channel list it already fetched: a confirming channel gets "it unlocks automatically once confirmed, nothing is needed from you", a far-side balance gets "you can receive, but there's nothing to send right now", a routing/liquidity payment failure says so instead of claiming channel problems, and only a genuinely channel-less node keeps the open-one guidance.</p>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<!-- v1.8.9-alpha -->
|
<!-- v1.8.9-alpha -->
|
||||||
@@ -381,12 +392,13 @@ init()
|
|||||||
<span class="text-xs text-white/40">September 1, 2026</span>
|
<span class="text-xs text-white/40">September 1, 2026</span>
|
||||||
</div>
|
</div>
|
||||||
<div class="space-y-3 text-sm text-white/80 pl-3 border-l border-white/10">
|
<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>Lightning sends work again after the LND 0.21.2 update.</strong> 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.</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>The node no longer pins HSTS — HTTP access is a supported mode, and it stays working.</strong> 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.</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>App frames open over HTTPS again — including the ones that "did not connect."</strong> 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.</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>Signing in to IndeeHub with Nostr works over HTTPS.</strong> 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.</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>
|
<p><strong>Nginx Proxy Manager starts again.</strong> 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.</p>
|
||||||
<p><strong>The Lightning wallet says what's actually wrong, instead of "you have no channel".</strong> Trying to send while a channel you just opened was still confirming — or when all its balance sits on the far side — produced a modal claiming you had no channel at all. The gate now looks at your real channel list: a confirming channel gets "it unlocks automatically once confirmed, nothing needed from you", a far-side balance gets "you can receive but there's nothing to send right now", and only a genuinely channel-less node is sent to open one.</p>
|
<p><strong>Portainer's first-run token is in the app page, not buried in "server logs."</strong> 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.</p>
|
||||||
|
<p><strong>The Lightning wallet states the node's real funding state instead of "you have no channel."</strong> Trying to send while a freshly opened channel was still waiting for on-chain confirmations — or when all its balance sits on the far side — raised a modal that claimed the node had no channel at all (the outbound sum is legitimately zero in both states). The funding gate now reads the channel list it already fetched: a confirming channel gets "it unlocks automatically once confirmed, nothing is needed from you", a far-side balance gets "you can receive, but there's nothing to send right now", a routing/liquidity payment failure says so instead of pointing at channel setup, and only a genuinely channel-less node is sent to open one.</p>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<!-- v1.8.8-alpha -->
|
<!-- v1.8.8-alpha -->
|
||||||
|
|||||||
+85
@@ -0,0 +1,85 @@
|
|||||||
|
#!/usr/bin/env bash
|
||||||
|
# check-gitea-release-download-links.sh - verify Gitea's public release page
|
||||||
|
# points users at the canonical HTTPS download URLs, not an internal ROOT_URL.
|
||||||
|
#
|
||||||
|
# Usage:
|
||||||
|
# scripts/check-gitea-release-download-links.sh VERSION ASSET_NAME...
|
||||||
|
|
||||||
|
set -euo pipefail
|
||||||
|
|
||||||
|
VERSION="${1:-}"
|
||||||
|
if [ -z "$VERSION" ] || [ "$#" -lt 2 ]; then
|
||||||
|
echo "usage: $0 VERSION ASSET_NAME..." >&2
|
||||||
|
exit 2
|
||||||
|
fi
|
||||||
|
shift
|
||||||
|
|
||||||
|
PUBLIC_BASE="${ARCHY_RELEASE_PUBLIC_BASE:-https://source.archipelago-foundation.org/lfg2025/archy}"
|
||||||
|
page_url="$PUBLIC_BASE/releases/tag/v$VERSION"
|
||||||
|
|
||||||
|
command -v curl >/dev/null 2>&1 || { echo "ERROR: curl required" >&2; exit 2; }
|
||||||
|
command -v python3 >/dev/null 2>&1 || { echo "ERROR: python3 required" >&2; exit 2; }
|
||||||
|
|
||||||
|
tmp="$(mktemp)"
|
||||||
|
trap 'rm -f "$tmp"' EXIT
|
||||||
|
curl -fsSL "$page_url" -o "$tmp"
|
||||||
|
|
||||||
|
python3 - "$tmp" "$PUBLIC_BASE" "$VERSION" "$page_url" "$@" <<'PY'
|
||||||
|
from html.parser import HTMLParser
|
||||||
|
from urllib.parse import quote
|
||||||
|
import sys
|
||||||
|
|
||||||
|
html_path, public_base, version, page_url, *assets = sys.argv[1:]
|
||||||
|
with open(html_path, encoding="utf-8") as f:
|
||||||
|
html = f.read()
|
||||||
|
|
||||||
|
class LinkParser(HTMLParser):
|
||||||
|
def __init__(self):
|
||||||
|
super().__init__()
|
||||||
|
self.hrefs = []
|
||||||
|
|
||||||
|
def handle_starttag(self, tag, attrs):
|
||||||
|
if tag.lower() != "a":
|
||||||
|
return
|
||||||
|
attrs = dict(attrs)
|
||||||
|
href = attrs.get("href")
|
||||||
|
if href:
|
||||||
|
self.hrefs.append(href)
|
||||||
|
|
||||||
|
parser = LinkParser()
|
||||||
|
parser.feed(html)
|
||||||
|
hrefs = set(parser.hrefs)
|
||||||
|
|
||||||
|
bad_internal = sorted(
|
||||||
|
h for h in hrefs
|
||||||
|
if "/releases/download/" in h and h.startswith(("http://", "https://"))
|
||||||
|
and not h.startswith(public_base + "/releases/download/")
|
||||||
|
)
|
||||||
|
|
||||||
|
failures = []
|
||||||
|
for asset in assets:
|
||||||
|
expected = f"{public_base}/releases/download/v{quote(version)}/{quote(asset)}"
|
||||||
|
if expected not in hrefs:
|
||||||
|
matches = sorted(h for h in hrefs if h.endswith("/" + quote(asset)))
|
||||||
|
if matches:
|
||||||
|
failures.append(f"{asset}: expected {expected}, found {matches[0]}")
|
||||||
|
else:
|
||||||
|
failures.append(f"{asset}: expected {expected}, but no matching release-page link was found")
|
||||||
|
|
||||||
|
if bad_internal:
|
||||||
|
failures.append("release page contains non-canonical download href(s):")
|
||||||
|
failures.extend(f" {h}" for h in bad_internal[:10])
|
||||||
|
|
||||||
|
if failures:
|
||||||
|
print(f"FAIL: public release page has broken download links: {page_url}", file=sys.stderr)
|
||||||
|
for failure in failures:
|
||||||
|
print(f" {failure}", file=sys.stderr)
|
||||||
|
print(
|
||||||
|
"Fix the Gitea public URL/proxy configuration so release links are generated "
|
||||||
|
"from the canonical HTTPS origin, then re-run the publish check.",
|
||||||
|
file=sys.stderr,
|
||||||
|
)
|
||||||
|
sys.exit(1)
|
||||||
|
|
||||||
|
print(f"OK: public release page download links use {public_base}")
|
||||||
|
PY
|
||||||
@@ -145,6 +145,11 @@ echo "Verifying public download URLs (full GET + size + sha256)..."
|
|||||||
"$PROJECT_ROOT/scripts/check-release-assets.sh" "$MANIFEST" \
|
"$PROJECT_ROOT/scripts/check-release-assets.sh" "$MANIFEST" \
|
||||||
|| fail "asset verification failed — NOT pushing main. The manifest stays off the branch nodes read, so no node sees a version it cannot fetch. Repair the assets and re-run."
|
|| fail "asset verification failed — NOT pushing main. The manifest stays off the branch nodes read, so no node sees a version it cannot fetch. Repair the assets and re-run."
|
||||||
|
|
||||||
|
"$PROJECT_ROOT/scripts/check-gitea-release-download-links.sh" "$VERSION" \
|
||||||
|
"archipelago" \
|
||||||
|
"archipelago-frontend-${VERSION}.tar.gz" \
|
||||||
|
|| fail "release page download links are not public HTTPS URLs — fix Gitea ROOT_URL/proxy configuration before publishing."
|
||||||
|
|
||||||
# Assets are proven fetchable — only now may the manifest become live. First
|
# Assets are proven fetchable — only now may the manifest become live. First
|
||||||
# incorporate concurrent work, then promote in a dedicated commit. Until the
|
# incorporate concurrent work, then promote in a dedicated commit. Until the
|
||||||
# final push succeeds the remote still serves the previous manifest.
|
# final push succeeds the remote still serves the previous manifest.
|
||||||
@@ -261,4 +266,10 @@ for b in bad:
|
|||||||
sys.exit(1 if bad else 0)
|
sys.exit(1 if bad else 0)
|
||||||
PY
|
PY
|
||||||
|
|
||||||
|
"$PROJECT_ROOT/scripts/check-gitea-release-download-links.sh" "$VERSION" \
|
||||||
|
"$ISO_NAME" \
|
||||||
|
"$ISO_NAME.sha256" \
|
||||||
|
"$ISO_NAME.sha256.json" \
|
||||||
|
|| fail "ISO is uploaded but the release page links are not public HTTPS URLs — fix Gitea ROOT_URL/proxy configuration."
|
||||||
|
|
||||||
echo "ISO for v${VERSION} published and verified on $REMOTE."
|
echo "ISO for v${VERSION} published and verified on $REMOTE."
|
||||||
|
|||||||
Reference in New Issue
Block a user