chore(catalog): sign catalog with the repaired bitcoin start script

Unbreaks Bitcoin on every node running the 1.7.124 catalog: the embedded
start script had a shell syntax error, so bitcoind never launched and the
app vanished. Delivered by catalog rather than a release because manifests
reach nodes through the signed catalog.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
This commit is contained in:
archipelago
2026-08-05 18:54:37 -04:00
co-authored by Claude Fable 5
parent e88c51d80b
commit 188411b79c
2 changed files with 24 additions and 9 deletions
+21 -6
View File
@@ -548,7 +548,7 @@ const LOGIN_BACKGROUNDS: [&str; 4] = [
/// join: the name arrives in a URL, and the gate answers before any
/// authentication, so nothing here may be caller-controlled beyond this set.
fn read_ui_asset(name: &str) -> Option<(Vec<u8>, &'static str)> {
let allowed = LOGIN_BACKGROUNDS.contains(&name) || name == "logo-archipelago.svg";
let allowed = LOGIN_BACKGROUNDS.contains(&name) || name == "favico-black-v2.svg";
if !allowed {
return None;
}
@@ -557,6 +557,9 @@ fn read_ui_asset(name: &str) -> Option<(Vec<u8>, &'static str)> {
"/opt/archipelago/web-ui/assets/img",
"web/dist/neode-ui/assets/img",
"neode-ui/public/assets/img",
"/opt/archipelago/web-ui/assets/icon",
"web/dist/neode-ui/assets/icon",
"neode-ui/public/assets/icon",
] {
if let Ok(bytes) = std::fs::read(std::path::Path::new(root).join(name)) {
return Some((bytes, mime));
@@ -631,9 +634,21 @@ fn page(title: &str, app: &GatedPort, body: &str, status: StatusCode) -> Respons
bundle exists, and the CSP forbids external stylesheets and script. */
:root {{ color-scheme: dark; }}
* {{ box-sizing: border-box; }}
body {{ margin:0; min-height:100vh; display:grid; place-items:center; padding:1rem;
background:#05070a; color:#fff; overflow:hidden;
font:16px/1.5 system-ui,-apple-system,"Segoe UI",sans-serif; }}
html {{ height:100%; }}
body {{ margin:0; color:#fff; background:#05070a; overflow:hidden;
font:16px/1.5 system-ui,-apple-system,"Segoe UI",sans-serif;
/* Fixed to the viewport rather than a tall scrolling page: an on-screen
keyboard then overlays the card instead of scrolling it away, and the
card stays optically centred. min-height:100vh scrolled with the
keyboard on mobile and left the card off-centre (reported 2026-08-05). */
position:fixed; inset:0;
display:grid; place-items:center; padding:1rem;
height:100vh; height:100svh; }}
/* Very short viewports (landscape phone, or a keyboard eating most of it):
allow the card to scroll INSIDE the fixed frame rather than overflow. */
@media (max-height:640px) {{
body {{ align-items:start; overflow-y:auto; padding-top:3rem; }}
}}
/* Rotating backgrounds: each layer holds its image and cross-fades on a
shared cycle, so the art moves the way /login does with no script. */
.bg {{ position:fixed; inset:0; z-index:0; background-size:cover;
@@ -726,7 +741,7 @@ button:active {{ transform:translateY(1px); }}
/// password by an unexplained page.
fn login_page(app: &GatedPort, error: Option<&str>, status: StatusCode) -> Response<Body> {
let body = format!(
r#"<div class="logo"><img src="{prefix}asset/logo-archipelago.svg" alt="Archipelago"></div>
r#"<div class="logo"><img src="{prefix}asset/favico-black-v2.svg" alt="Archipelago"></div>
{icon}
<h1>Sign in to open {name}</h1>
<p class="sub">This app is protected by your node password.</p>
@@ -863,7 +878,7 @@ mod tests {
let resp = login_page(&app(), None, StatusCode::UNAUTHORIZED);
let body = hyper::body::to_bytes(resp.into_body()).await.unwrap();
let html = String::from_utf8_lossy(&body).to_string();
assert!(html.contains(&format!("{GATE_PREFIX}asset/logo-archipelago.svg")));
assert!(html.contains(&format!("{GATE_PREFIX}asset/favico-black-v2.svg")));
for name in LOGIN_BACKGROUNDS {
assert!(
html.contains(&format!("{GATE_PREFIX}asset/{name}")),