Compare commits
3 Commits
v1.7.10-al
...
v1.7.13-al
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
30a26f94f7 | ||
|
|
26d6eddb1c | ||
|
|
c9f6697f02 |
2
core/Cargo.lock
generated
2
core/Cargo.lock
generated
@@ -80,7 +80,7 @@ checksum = "a23eb6b1614318a8071c9b2521f36b424b2c83db5eb3a0fead4a6c0809af6e61"
|
||||
|
||||
[[package]]
|
||||
name = "archipelago"
|
||||
version = "1.7.10-alpha"
|
||||
version = "1.7.13-alpha"
|
||||
dependencies = [
|
||||
"anyhow",
|
||||
"archipelago-container",
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
[package]
|
||||
name = "archipelago"
|
||||
version = "1.7.10-alpha"
|
||||
version = "1.7.13-alpha"
|
||||
edition = "2021"
|
||||
description = "Archipelago Bitcoin Node OS - Native backend"
|
||||
authors = ["Archipelago Team"]
|
||||
|
||||
@@ -113,6 +113,53 @@ impl ApiHandler {
|
||||
}
|
||||
}
|
||||
|
||||
/// Server-side fetch of the upstream app catalog so the browser can
|
||||
/// 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
|
||||
/// upstream URLs in the same order the frontend used, returns the
|
||||
/// first 2xx response. 15s total timeout.
|
||||
async fn handle_app_catalog_proxy() -> Result<Response<hyper::Body>> {
|
||||
const UPSTREAMS: &[&str] = &[
|
||||
"https://git.tx1138.com/lfg2025/app-catalog/raw/branch/main/catalog.json",
|
||||
"http://23.182.128.160:3000/lfg2025/app-catalog/raw/branch/main/catalog.json",
|
||||
];
|
||||
let client = match reqwest::Client::builder()
|
||||
.timeout(std::time::Duration::from_secs(15))
|
||||
.build()
|
||||
{
|
||||
Ok(c) => c,
|
||||
Err(e) => {
|
||||
return Ok(build_response(
|
||||
hyper::StatusCode::INTERNAL_SERVER_ERROR,
|
||||
"text/plain",
|
||||
hyper::Body::from(format!("client build failed: {}", e)),
|
||||
));
|
||||
}
|
||||
};
|
||||
for url in UPSTREAMS {
|
||||
match client.get(*url).send().await {
|
||||
Ok(resp) if resp.status().is_success() => {
|
||||
if let Ok(bytes) = resp.bytes().await {
|
||||
return Ok(Response::builder()
|
||||
.status(hyper::StatusCode::OK)
|
||||
.header("Content-Type", "application/json")
|
||||
.header("Cache-Control", "public, max-age=3600")
|
||||
.body(hyper::Body::from(bytes))
|
||||
.unwrap_or_else(|_| {
|
||||
Response::new(hyper::Body::from("proxy response build failed"))
|
||||
}));
|
||||
}
|
||||
}
|
||||
_ => continue,
|
||||
}
|
||||
}
|
||||
Ok(build_response(
|
||||
hyper::StatusCode::BAD_GATEWAY,
|
||||
"text/plain",
|
||||
hyper::Body::from("all upstream catalog URLs failed"),
|
||||
))
|
||||
}
|
||||
|
||||
/// Build a 401 Unauthorized JSON response.
|
||||
fn unauthorized() -> Response<hyper::Body> {
|
||||
let body = serde_json::json!({ "error": "Unauthorized" });
|
||||
@@ -352,6 +399,18 @@ impl ApiHandler {
|
||||
// Electrs status — unauthenticated (read-only sync status)
|
||||
(Method::GET, "/electrs-status") => Self::handle_electrs_status().await,
|
||||
|
||||
// App-catalog proxy — fetches catalog.json from the configured
|
||||
// upstream URLs server-side so the browser doesn't hit CORS
|
||||
// (git.tx1138.com has no ACAO header) or CSP (IP-port upstream
|
||||
// falls outside `connect-src`). Session-authenticated so only
|
||||
// the logged-in node owner can spin up fetches.
|
||||
(Method::GET, "/api/app-catalog") => {
|
||||
if !self.is_authenticated(&headers).await {
|
||||
return Ok(Self::unauthorized());
|
||||
}
|
||||
Self::handle_app_catalog_proxy().await
|
||||
}
|
||||
|
||||
// LND connect info — nginx validates session cookie (presence check),
|
||||
// backend is bound to 127.0.0.1 so only nginx can reach it.
|
||||
// No backend auth check here because the LND UI iframe fetches this
|
||||
|
||||
@@ -22,13 +22,13 @@ let cachedCatalog: AppCatalog | null = null
|
||||
let catalogFetchedAt = 0
|
||||
const CATALOG_TTL = 60 * 60 * 1000 // 1 hour cache
|
||||
|
||||
/** Remote catalog URLs — tried in order. First success wins. */
|
||||
/** Catalog URLs tried in order. First success wins.
|
||||
* Primary is the backend proxy (`/api/app-catalog`) — server-side fetch
|
||||
* bypasses CORS on git.tx1138.com and CSP restrictions on the IP-port
|
||||
* fallback. If the backend is offline (mid-restart etc.) we fall back
|
||||
* to the static copy baked into the frontend build. */
|
||||
const CATALOG_URLS = [
|
||||
// Primary: git.tx1138.com raw file (HTTPS, dynamic, updated without frontend rebuild)
|
||||
'https://git.tx1138.com/lfg2025/app-catalog/raw/branch/main/catalog.json',
|
||||
// Fallback: direct IP (HTTP, only works if CSP allows http://$host:*)
|
||||
'http://23.182.128.160:3000/lfg2025/app-catalog/raw/branch/main/catalog.json',
|
||||
// Last resort: local static file (baked into frontend build)
|
||||
'/api/app-catalog',
|
||||
'/catalog.json',
|
||||
]
|
||||
|
||||
@@ -40,7 +40,7 @@ export async function fetchAppCatalog(): Promise<AppCatalog | null> {
|
||||
|
||||
for (const url of CATALOG_URLS) {
|
||||
try {
|
||||
const res = await fetch(url, { signal: AbortSignal.timeout(5000) })
|
||||
const res = await fetch(url, { credentials: 'include', signal: AbortSignal.timeout(20000) })
|
||||
if (!res.ok) continue
|
||||
const data = await res.json() as AppCatalog
|
||||
if (!data.apps?.length) continue
|
||||
|
||||
@@ -1,28 +1,25 @@
|
||||
{
|
||||
"version": "1.7.10-alpha",
|
||||
"version": "1.7.13-alpha",
|
||||
"release_date": "2026-04-20",
|
||||
"changelog": [
|
||||
"Install Update actually applies now. The installer had to write into system folders that the backend service was sandboxed out of — every earlier 'Failed to apply update' was a layer of that onion. Fixed by running the file swaps in a separate system context.",
|
||||
"FIPS status on the Home and Server pages now reflects whether the public anchor is reachable. You'll see 'Active · N peers' (green) when healthy or 'No anchor' (orange) when the network is blocking the bootstrap — same signal as the full FIPS card.",
|
||||
"Pasting an https://… URL into the profile picture or banner now previews correctly. Before, if the URL failed to load, the UI would silently blank out instead of showing your initial as a placeholder.",
|
||||
"Uploaded profile pictures under 64 KB are now embedded directly in your Nostr profile (as a data URL), so any Nostr client can see them — not just ones routing over Tor. Larger uploads keep the onion URL for now, with a hint to paste a public URL for wider visibility."
|
||||
"App catalog now loads reliably. Before, the Marketplace / Discover page couldn't fetch the catalog of apps because the upstream host wasn't sending the right CORS headers and the node's security policy didn't allow the fallback URL either. The node now fetches the catalog server-side and serves it same-origin to the browser — no more blank app lists."
|
||||
],
|
||||
"components": [
|
||||
{
|
||||
"name": "archipelago",
|
||||
"current_version": "1.7.9-alpha",
|
||||
"new_version": "1.7.10-alpha",
|
||||
"download_url": "https://git.tx1138.com/lfg2025/archy/raw/branch/main/releases/v1.7.10-alpha/archipelago",
|
||||
"sha256": "4a77c704b5c1ac0b424ccfc7ed123c50e2708764ac2b4916af534e80382aa6f8",
|
||||
"size_bytes": 40379696
|
||||
"current_version": "1.7.12-alpha",
|
||||
"new_version": "1.7.13-alpha",
|
||||
"download_url": "https://git.tx1138.com/lfg2025/archy/raw/branch/main/releases/v1.7.13-alpha/archipelago",
|
||||
"sha256": "0aaf72625a6cb164b35e30e0dc6f6084cbc96fd8d9da9480b78e85f4b979f22c",
|
||||
"size_bytes": 40371192
|
||||
},
|
||||
{
|
||||
"name": "archipelago-frontend-1.7.10-alpha.tar.gz",
|
||||
"current_version": "1.7.9-alpha",
|
||||
"new_version": "1.7.10-alpha",
|
||||
"download_url": "https://git.tx1138.com/lfg2025/archy/raw/branch/main/releases/v1.7.10-alpha/archipelago-frontend-1.7.10-alpha.tar.gz",
|
||||
"sha256": "0644a43611309031efbb9b235a3602f0828f709fcaec0047543d96e1cbd54f58",
|
||||
"size_bytes": 76983846
|
||||
"name": "archipelago-frontend-1.7.13-alpha.tar.gz",
|
||||
"current_version": "1.7.12-alpha",
|
||||
"new_version": "1.7.13-alpha",
|
||||
"download_url": "https://git.tx1138.com/lfg2025/archy/raw/branch/main/releases/v1.7.13-alpha/archipelago-frontend-1.7.13-alpha.tar.gz",
|
||||
"sha256": "27505811ffcae22a33cc895e2dc630b3efef7d0682841eeeea517d5efc6f4142",
|
||||
"size_bytes": 76982505
|
||||
}
|
||||
]
|
||||
}
|
||||
|
||||
BIN
releases/v1.7.11-alpha/archipelago
Executable file
BIN
releases/v1.7.11-alpha/archipelago
Executable file
Binary file not shown.
BIN
releases/v1.7.11-alpha/archipelago-frontend-1.7.11-alpha.tar.gz
Normal file
BIN
releases/v1.7.11-alpha/archipelago-frontend-1.7.11-alpha.tar.gz
Normal file
Binary file not shown.
BIN
releases/v1.7.12-alpha/archipelago
Executable file
BIN
releases/v1.7.12-alpha/archipelago
Executable file
Binary file not shown.
BIN
releases/v1.7.12-alpha/archipelago-frontend-1.7.12-alpha.tar.gz
Normal file
BIN
releases/v1.7.12-alpha/archipelago-frontend-1.7.12-alpha.tar.gz
Normal file
Binary file not shown.
BIN
releases/v1.7.13-alpha/archipelago
Executable file
BIN
releases/v1.7.13-alpha/archipelago
Executable file
Binary file not shown.
BIN
releases/v1.7.13-alpha/archipelago-frontend-1.7.13-alpha.tar.gz
Normal file
BIN
releases/v1.7.13-alpha/archipelago-frontend-1.7.13-alpha.tar.gz
Normal file
Binary file not shown.
Reference in New Issue
Block a user