From 7c7cd76c1c01d3f52ec2dff71589a68504a75789 Mon Sep 17 00:00:00 2001 From: archipelago Date: Fri, 7 Aug 2026 19:17:24 -0400 Subject: [PATCH] fix(package): btcpay wipe removes the whole stack's data, not just its own dir MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit get_data_dirs_for_app had no btcpay arm — the default mapped to /var/lib/archipelago/btcpay alone, leaving postgres-btcpay (where the ACCOUNT lives) and nbxplorer on disk. Uninstall-with-wipe then reinstalled to the old account still enabled. The btcpay arm now covers all three dirs, for every alias and stack-member id. The map stays deliberately hardcoded: deletion code must never derive its targets from a manifest at uninstall time (a bad manifest could aim the wipe at another app's data). Co-Authored-By: Claude --- .../archipelago/src/api/rpc/package/config.rs | 28 ++++++++++++++++++- 1 file changed, 27 insertions(+), 1 deletion(-) diff --git a/core/archipelago/src/api/rpc/package/config.rs b/core/archipelago/src/api/rpc/package/config.rs index b672430e..03d6ec0b 100644 --- a/core/archipelago/src/api/rpc/package/config.rs +++ b/core/archipelago/src/api/rpc/package/config.rs @@ -541,7 +541,7 @@ pub(in crate::api::rpc) async fn get_containers_for_app(package_id: &str) -> Res #[cfg(test)] mod tests { - use super::{all_container_names, get_health_check_args}; + use super::{all_container_names, get_data_dirs_for_app, get_health_check_args}; #[test] fn bitcoin_variant_container_names_are_precise() { @@ -566,6 +566,21 @@ mod tests { assert!(health_cmd.contains("test -w /var/lib/grafana/grafana.db")); assert!(health_cmd.contains("http://localhost:3000/api/health")); } + + /// The BTCPay wipe bug (operator report 2026-08-07): a wipe must remove + /// the postgres volume — that is where the account lives — plus nbxplorer + /// and the app's own dir. The pre-fix map removed only `…/btcpay`, so a + /// "fresh" reinstall came back with the old account still enabled. + #[test] + fn btcpay_wipe_includes_postgres_and_nbxplorer() { + let dirs = get_data_dirs_for_app("btcpay-server"); + assert!(dirs.contains(&"/var/lib/archipelago/btcpay".to_string())); + assert!(dirs.contains(&"/var/lib/archipelago/postgres-btcpay".to_string())); + assert!(dirs.contains(&"/var/lib/archipelago/nbxplorer".to_string())); + // Aliases and the stack-member ids must map to the same set. + assert_eq!(get_data_dirs_for_app("btcpay"), dirs); + assert_eq!(get_data_dirs_for_app("archy-btcpay-db"), dirs); + } } /// Get data directories to clean for an app. @@ -581,6 +596,17 @@ pub(super) fn get_data_dirs_for_app(package_id: &str) -> Vec { format!("{}/mysql-mempool", base), format!("{}/electrumx", base), ], + // The whole btcpay stack — the default arm's lone `…/btcpay` left + // postgres-btcpay (accounts!) and nbxplorer behind, so a + // wipe-and-reinstall came back with the old account still enabled + // (operator report, 2026-08-07). This list is deliberately hardcoded + // and reviewed: deletion code must never derive its targets from a + // manifest at uninstall time (a bad manifest could aim the wipe). + "btcpay-server" | "btcpayserver" | "btcpay" | "archy-btcpay-db" | "archy-nbxplorer" => vec![ + format!("{}/btcpay", base), + format!("{}/postgres-btcpay", base), + format!("{}/nbxplorer", base), + ], "fedimint" => vec![ format!("{}/fedimint", base), format!("{}/fedimint-gateway", base),