release(v1.7.36-alpha): bitcoin-core in App Store + Sovereignty Stack + dynamic catalog URL
- neode-ui/public/assets/img/app-icons/bitcoin-core.svg (NEW): 256×256 Umbrel community Bitcoin icon sourced from getumbrel.github.io/ umbrel-apps-gallery/bitcoin/icon.svg. Referenced by the static catalog, the curated fallback, and the upstream lfg2025/app-catalog entry so every surface shows the same image. - app-catalog/catalog.json + neode-ui/public/catalog.json: add bitcoin-core (v28.4) entry pointing at bitcoin/bitcoin:28.4. Same entry pushed to the lfg2025/app-catalog repo on .160 and the local gitea mirror so nodes see it without needing a full archipelago update. Sovereignty Stack entry added to FEATURED_DEFINITIONS with a description that frames it as a Knots alternative, not a rival. - core/archipelago/src/api/handler/mod.rs: handle_app_catalog_proxy is now instance-scoped (&self) and derives its upstream list from load_registries — each active container registry contributes one `<scheme>://<reg.url>/app-catalog/raw/branch/main/catalog.json` URL in priority order (scheme follows tls_verify). When the operator switches mirrors in Settings, the App Store now follows. Falls back to the legacy hardcoded .160/tx1138 pair only when registry config can't be loaded, so the App Store still renders on nodes that haven't persisted one yet. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
parent
a7048f6d8e
commit
9cf1177b73
@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"version": 2,
|
"version": 2,
|
||||||
"updated": "2026-04-12T00:00:00Z",
|
"updated": "2026-04-22T00:00:00Z",
|
||||||
"registry": "git.tx1138.com/lfg2025",
|
"registry": "git.tx1138.com/lfg2025",
|
||||||
"featured": {
|
"featured": {
|
||||||
"id": "indeedhub",
|
"id": "indeedhub",
|
||||||
@ -18,6 +18,14 @@
|
|||||||
"dockerImage": "git.tx1138.com/lfg2025/bitcoin-knots:latest",
|
"dockerImage": "git.tx1138.com/lfg2025/bitcoin-knots:latest",
|
||||||
"repoUrl": "https://github.com/bitcoinknots/bitcoin"
|
"repoUrl": "https://github.com/bitcoinknots/bitcoin"
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
"id": "bitcoin-core", "title": "Bitcoin Core", "version": "28.4",
|
||||||
|
"description": "Reference implementation of the Bitcoin protocol. Run a full node validating and relaying blocks.",
|
||||||
|
"icon": "/assets/img/app-icons/bitcoin-core.svg",
|
||||||
|
"author": "Bitcoin Core contributors", "category": "money", "tier": "optional",
|
||||||
|
"dockerImage": "bitcoin/bitcoin:28.4",
|
||||||
|
"repoUrl": "https://github.com/bitcoin/bitcoin"
|
||||||
|
},
|
||||||
{
|
{
|
||||||
"id": "lnd", "title": "LND", "version": "0.18.4",
|
"id": "lnd", "title": "LND", "version": "0.18.4",
|
||||||
"description": "Lightning Network Daemon. Fast Bitcoin payments through Lightning.",
|
"description": "Lightning Network Daemon. Fast Bitcoin payments through Lightning.",
|
||||||
|
|||||||
2
core/Cargo.lock
generated
2
core/Cargo.lock
generated
@ -80,7 +80,7 @@ checksum = "a23eb6b1614318a8071c9b2521f36b424b2c83db5eb3a0fead4a6c0809af6e61"
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "archipelago"
|
name = "archipelago"
|
||||||
version = "1.7.35-alpha"
|
version = "1.7.36-alpha"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"anyhow",
|
"anyhow",
|
||||||
"archipelago-container",
|
"archipelago-container",
|
||||||
|
|||||||
@ -1,6 +1,6 @@
|
|||||||
[package]
|
[package]
|
||||||
name = "archipelago"
|
name = "archipelago"
|
||||||
version = "1.7.35-alpha"
|
version = "1.7.36-alpha"
|
||||||
edition = "2021"
|
edition = "2021"
|
||||||
description = "Archipelago Bitcoin Node OS - Native backend"
|
description = "Archipelago Bitcoin Node OS - Native backend"
|
||||||
authors = ["Archipelago Team"]
|
authors = ["Archipelago Team"]
|
||||||
|
|||||||
@ -115,14 +115,41 @@ impl ApiHandler {
|
|||||||
|
|
||||||
/// Server-side fetch of the upstream app catalog so the browser can
|
/// Server-side fetch of the upstream app catalog so the browser can
|
||||||
/// load it without fighting CORS (git.tx1138.com emits no ACAO) or
|
/// load it without fighting CORS (git.tx1138.com emits no ACAO) or
|
||||||
/// CSP (the fallback IP-port URL isn't in `connect-src`). Tries the
|
/// CSP (the fallback IP-port URL isn't in `connect-src`). The upstream
|
||||||
/// upstream URLs in the same order the frontend used, returns the
|
/// list is derived from the operator's configured container registries
|
||||||
/// first 2xx response. 15s total timeout.
|
/// so switching mirrors in Settings changes the App Store source too —
|
||||||
async fn handle_app_catalog_proxy() -> Result<Response<hyper::Body>> {
|
/// each active registry contributes one Gitea `raw/branch/main/catalog.json`
|
||||||
const UPSTREAMS: &[&str] = &[
|
/// URL (http or https per `tls_verify`), tried in priority order.
|
||||||
"http://23.182.128.160:3000/lfg2025/app-catalog/raw/branch/main/catalog.json",
|
/// If registry config can't be loaded, falls back to the legacy
|
||||||
"https://git.tx1138.com/lfg2025/app-catalog/raw/branch/main/catalog.json",
|
/// hardcoded pair so the App Store still renders on nodes that haven't
|
||||||
];
|
/// persisted a registry config yet. 15s total timeout.
|
||||||
|
async fn handle_app_catalog_proxy(&self) -> Result<Response<hyper::Body>> {
|
||||||
|
let mut upstreams: Vec<String> = Vec::new();
|
||||||
|
if let Ok(config) =
|
||||||
|
crate::container::registry::load_registries(&self.config.data_dir).await
|
||||||
|
{
|
||||||
|
for reg in config.active_registries() {
|
||||||
|
let scheme = if reg.tls_verify { "https" } else { "http" };
|
||||||
|
// Gitea raw URL: <scheme>://<host>/<namespace>/app-catalog/raw/branch/main/catalog.json.
|
||||||
|
// reg.url already includes the namespace (e.g. "host/lfg2025"),
|
||||||
|
// so we just tack on the repo + raw path.
|
||||||
|
upstreams.push(format!(
|
||||||
|
"{}://{}/app-catalog/raw/branch/main/catalog.json",
|
||||||
|
scheme, reg.url
|
||||||
|
));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if upstreams.is_empty() {
|
||||||
|
upstreams.push(
|
||||||
|
"http://23.182.128.160:3000/lfg2025/app-catalog/raw/branch/main/catalog.json"
|
||||||
|
.to_string(),
|
||||||
|
);
|
||||||
|
upstreams.push(
|
||||||
|
"https://git.tx1138.com/lfg2025/app-catalog/raw/branch/main/catalog.json"
|
||||||
|
.to_string(),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
let client = match reqwest::Client::builder()
|
let client = match reqwest::Client::builder()
|
||||||
.timeout(std::time::Duration::from_secs(15))
|
.timeout(std::time::Duration::from_secs(15))
|
||||||
.build()
|
.build()
|
||||||
@ -136,8 +163,8 @@ impl ApiHandler {
|
|||||||
));
|
));
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
for url in UPSTREAMS {
|
for url in &upstreams {
|
||||||
match client.get(*url).send().await {
|
match client.get(url).send().await {
|
||||||
Ok(resp) if resp.status().is_success() => {
|
Ok(resp) if resp.status().is_success() => {
|
||||||
if let Ok(bytes) = resp.bytes().await {
|
if let Ok(bytes) = resp.bytes().await {
|
||||||
return Ok(Response::builder()
|
return Ok(Response::builder()
|
||||||
@ -408,7 +435,7 @@ impl ApiHandler {
|
|||||||
if !self.is_authenticated(&headers).await {
|
if !self.is_authenticated(&headers).await {
|
||||||
return Ok(Self::unauthorized());
|
return Ok(Self::unauthorized());
|
||||||
}
|
}
|
||||||
Self::handle_app_catalog_proxy().await
|
self.handle_app_catalog_proxy().await
|
||||||
}
|
}
|
||||||
|
|
||||||
// LND connect info — nginx validates session cookie (presence check),
|
// LND connect info — nginx validates session cookie (presence check),
|
||||||
|
|||||||
4
neode-ui/package-lock.json
generated
4
neode-ui/package-lock.json
generated
@ -1,12 +1,12 @@
|
|||||||
{
|
{
|
||||||
"name": "neode-ui",
|
"name": "neode-ui",
|
||||||
"version": "1.6.0-alpha",
|
"version": "1.7.36-alpha",
|
||||||
"lockfileVersion": 3,
|
"lockfileVersion": 3,
|
||||||
"requires": true,
|
"requires": true,
|
||||||
"packages": {
|
"packages": {
|
||||||
"": {
|
"": {
|
||||||
"name": "neode-ui",
|
"name": "neode-ui",
|
||||||
"version": "1.6.0-alpha",
|
"version": "1.7.36-alpha",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@types/dompurify": "^3.0.5",
|
"@types/dompurify": "^3.0.5",
|
||||||
"@vue-leaflet/vue-leaflet": "^0.10.1",
|
"@vue-leaflet/vue-leaflet": "^0.10.1",
|
||||||
|
|||||||
@ -1,7 +1,7 @@
|
|||||||
{
|
{
|
||||||
"name": "neode-ui",
|
"name": "neode-ui",
|
||||||
"private": true,
|
"private": true,
|
||||||
"version": "1.7.35-alpha",
|
"version": "1.7.36-alpha",
|
||||||
"type": "module",
|
"type": "module",
|
||||||
"scripts": {
|
"scripts": {
|
||||||
"start": "./start-dev.sh",
|
"start": "./start-dev.sh",
|
||||||
|
|||||||
14
neode-ui/public/assets/img/app-icons/bitcoin-core.svg
Normal file
14
neode-ui/public/assets/img/app-icons/bitcoin-core.svg
Normal file
File diff suppressed because one or more lines are too long
|
After Width: | Height: | Size: 24 KiB |
@ -22,6 +22,18 @@
|
|||||||
"category": "money",
|
"category": "money",
|
||||||
"tier": "core"
|
"tier": "core"
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
"id": "bitcoin-core",
|
||||||
|
"title": "Bitcoin Core",
|
||||||
|
"version": "28.4",
|
||||||
|
"description": "Reference implementation of the Bitcoin protocol. Run a full node validating and relaying blocks on the Bitcoin network.",
|
||||||
|
"icon": "/assets/img/app-icons/bitcoin-core.svg",
|
||||||
|
"author": "Bitcoin Core contributors",
|
||||||
|
"dockerImage": "bitcoin/bitcoin:28.4",
|
||||||
|
"repoUrl": "https://github.com/bitcoin/bitcoin",
|
||||||
|
"category": "money",
|
||||||
|
"tier": "optional"
|
||||||
|
},
|
||||||
{
|
{
|
||||||
"id": "lnd",
|
"id": "lnd",
|
||||||
"title": "LND",
|
"title": "LND",
|
||||||
|
|||||||
@ -77,6 +77,7 @@ export async function fetchAppCatalog(): Promise<AppCatalog | null> {
|
|||||||
export function getCuratedAppList(): MarketplaceApp[] {
|
export function getCuratedAppList(): MarketplaceApp[] {
|
||||||
return [
|
return [
|
||||||
{ id: 'bitcoin-knots', title: 'Bitcoin Knots', version: '28.1.0', description: 'Run a full Bitcoin node. Validate and relay blocks and transactions on the Bitcoin network.', icon: '/assets/img/app-icons/bitcoin-knots.webp', author: 'Bitcoin Knots', dockerImage: `${R}/bitcoin-knots:latest`, repoUrl: 'https://github.com/bitcoinknots/bitcoin' },
|
{ id: 'bitcoin-knots', title: 'Bitcoin Knots', version: '28.1.0', description: 'Run a full Bitcoin node. Validate and relay blocks and transactions on the Bitcoin network.', icon: '/assets/img/app-icons/bitcoin-knots.webp', author: 'Bitcoin Knots', dockerImage: `${R}/bitcoin-knots:latest`, repoUrl: 'https://github.com/bitcoinknots/bitcoin' },
|
||||||
|
{ id: 'bitcoin-core', title: 'Bitcoin Core', version: '28.4', description: 'Reference implementation of the Bitcoin protocol. Run a full node validating and relaying blocks on the Bitcoin network.', icon: '/assets/img/app-icons/bitcoin-core.svg', author: 'Bitcoin Core contributors', dockerImage: 'bitcoin/bitcoin:28.4', repoUrl: 'https://github.com/bitcoin/bitcoin' },
|
||||||
{ id: 'btcpay-server', title: 'BTCPay Server', version: '1.13.7', description: 'Self-hosted Bitcoin payment processor. Accept Bitcoin payments without intermediaries or fees.', icon: '/assets/img/app-icons/btcpay-server.png', author: 'BTCPay Server Foundation', dockerImage: `${R}/btcpayserver:1.13.7`, repoUrl: 'https://github.com/btcpayserver/btcpayserver' },
|
{ id: 'btcpay-server', title: 'BTCPay Server', version: '1.13.7', description: 'Self-hosted Bitcoin payment processor. Accept Bitcoin payments without intermediaries or fees.', icon: '/assets/img/app-icons/btcpay-server.png', author: 'BTCPay Server Foundation', dockerImage: `${R}/btcpayserver:1.13.7`, repoUrl: 'https://github.com/btcpayserver/btcpayserver' },
|
||||||
{ id: 'lnd', title: 'LND', version: '0.18.4', description: 'Lightning Network Daemon. Fast and cheap Bitcoin payments through the Lightning Network.', icon: '/assets/img/app-icons/lnd.svg', author: 'Lightning Labs', dockerImage: `${R}/lnd:v0.18.4-beta`, repoUrl: 'https://github.com/lightningnetwork/lnd' },
|
{ id: 'lnd', title: 'LND', version: '0.18.4', description: 'Lightning Network Daemon. Fast and cheap Bitcoin payments through the Lightning Network.', icon: '/assets/img/app-icons/lnd.svg', author: 'Lightning Labs', dockerImage: `${R}/lnd:v0.18.4-beta`, repoUrl: 'https://github.com/lightningnetwork/lnd' },
|
||||||
{ id: 'mempool', title: 'Mempool Explorer', version: '3.0.0', description: 'Self-hosted Bitcoin blockchain and mempool visualizer. Monitor transactions without revealing your addresses to third parties.', icon: '/assets/img/app-icons/mempool.webp', author: 'Mempool', dockerImage: `${R}/mempool-frontend:v3.0.0`, repoUrl: 'https://github.com/mempool/mempool' },
|
{ id: 'mempool', title: 'Mempool Explorer', version: '3.0.0', description: 'Self-hosted Bitcoin blockchain and mempool visualizer. Monitor transactions without revealing your addresses to third parties.', icon: '/assets/img/app-icons/mempool.webp', author: 'Mempool', dockerImage: `${R}/mempool-frontend:v3.0.0`, repoUrl: 'https://github.com/mempool/mempool' },
|
||||||
@ -164,6 +165,11 @@ export const FEATURED_DEFINITIONS: {
|
|||||||
desc: 'The foundation of sovereignty. Run a full Bitcoin node to validate every transaction yourself. No trusted third parties. No asking permission. Your node enforces the consensus rules that protect your wealth. Don\'t trust — verify.',
|
desc: 'The foundation of sovereignty. Run a full Bitcoin node to validate every transaction yourself. No trusted third parties. No asking permission. Your node enforces the consensus rules that protect your wealth. Don\'t trust — verify.',
|
||||||
tag: 'FULL VALIDATION // ZERO TRUST',
|
tag: 'FULL VALIDATION // ZERO TRUST',
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
id: 'bitcoin-core',
|
||||||
|
desc: 'The reference Bitcoin implementation. Same full-node guarantees as Knots, tracking upstream releases from the Bitcoin Core maintainers. Pick this if you\'d rather run mainline Bitcoin Core than Knots — both validate every block themselves.',
|
||||||
|
tag: 'REFERENCE CLIENT // ZERO TRUST',
|
||||||
|
},
|
||||||
{
|
{
|
||||||
id: 'lnd',
|
id: 'lnd',
|
||||||
desc: 'Lightning-fast payments over the Lightning Network. Open channels, route transactions, and earn routing fees — all from your sovereign node. Instant settlement. Near-zero fees. The future of money, running on your hardware.',
|
desc: 'Lightning-fast payments over the Lightning Network. Open channels, route transactions, and earn routing fees — all from your sovereign node. Instant settlement. Near-zero fees. The future of money, running on your hardware.',
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user