2026-01-27 23:21:26 +00:00
// Docker Package Scanner
// Scans docker-compose containers and converts them to package data
use anyhow ::Result ;
chore(ci): rustfmt + clippy clean-up to unblock the Rust CI job
The .github/workflows/ci.yml Rust job runs cargo fmt --check, clippy
with -D warnings, and tests. All three were failing. This commit:
- Applies rustfmt across the tree (the bulk of the diff — untouched
since the last toolchain bump, so a wide sweep was unavoidable).
- Fixes the correctness-level clippy errors:
container/bitcoin_simulator.rs wildcard-in-or-pattern
container/manifest.rs from_str rename to parse (reserved name)
container/podman_client.rs .get(0) -> .first()
container/runtime.rs manual += collapse
archipelago/src/constants.rs doc-comment → module-doc
api/rpc/package/install.rs stray /// comment above a non-item
container/docker_packages.rs redundant field init
streaming/advertisement.rs missing Metric import in tests
tests/orchestration_tests.rs `vec!` in non-Vec contexts
mesh/listener/dispatch.rs unused store_plain_message import
api/rpc/tor/mod.rs and mesh/steganography.rs: push-after-new → vec!
- Quiets wide legacy surfaces with crate-level allows in main.rs for
stylistic lints (too_many_arguments, type_complexity, doc indent,
enum variant prefix, wildcard-in-or, assertions-on-constants,
drop_non_drop, unused_io_amount, ptr_arg) — these fired in dozens
of places with no correctness payoff and have been churning every
toolchain bump.
- Tags intentional-dead-code helpers: wallet/ and streaming/ modules
are WIP, mesh::send_chunked_payload and DM_V1_MARKER are kept for
rollback compatibility, vpn::get_nostr_vpn_status is surface-area
for a not-yet-landed RPC.
cargo fmt --check, cargo clippy --all-targets --all-features
-- -D warnings, and cargo test --all-features now all pass locally.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-04-18 17:23:46 -04:00
use archipelago_container ::{
ContainerRuntime as ContainerRuntimeTrait , ContainerState , PodmanClient ,
} ;
2026-01-27 23:21:26 +00:00
use std ::collections ::HashMap ;
use std ::sync ::Arc ;
use tracing ::{ debug , info } ;
chore(ci): rustfmt + clippy clean-up to unblock the Rust CI job
The .github/workflows/ci.yml Rust job runs cargo fmt --check, clippy
with -D warnings, and tests. All three were failing. This commit:
- Applies rustfmt across the tree (the bulk of the diff — untouched
since the last toolchain bump, so a wide sweep was unavoidable).
- Fixes the correctness-level clippy errors:
container/bitcoin_simulator.rs wildcard-in-or-pattern
container/manifest.rs from_str rename to parse (reserved name)
container/podman_client.rs .get(0) -> .first()
container/runtime.rs manual += collapse
archipelago/src/constants.rs doc-comment → module-doc
api/rpc/package/install.rs stray /// comment above a non-item
container/docker_packages.rs redundant field init
streaming/advertisement.rs missing Metric import in tests
tests/orchestration_tests.rs `vec!` in non-Vec contexts
mesh/listener/dispatch.rs unused store_plain_message import
api/rpc/tor/mod.rs and mesh/steganography.rs: push-after-new → vec!
- Quiets wide legacy surfaces with crate-level allows in main.rs for
stylistic lints (too_many_arguments, type_complexity, doc indent,
enum variant prefix, wildcard-in-or, assertions-on-constants,
drop_non_drop, unused_io_amount, ptr_arg) — these fired in dozens
of places with no correctness payoff and have been churning every
toolchain bump.
- Tags intentional-dead-code helpers: wallet/ and streaming/ modules
are WIP, mesh::send_chunked_payload and DM_V1_MARKER are kept for
rollback compatibility, vpn::get_nostr_vpn_status is surface-area
for a not-yet-landed RPC.
cargo fmt --check, cargo clippy --all-targets --all-features
-- -D warnings, and cargo test --all-features now all pass locally.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-04-18 17:23:46 -04:00
use super ::image_versions ;
2026-01-27 23:21:26 +00:00
use crate ::data_model ::{
Description , InstalledPackageDataEntry , InterfaceAddress , Interfaces , MainInterface , Manifest ,
PackageDataEntry , PackageState , ServiceStatus , StaticFiles ,
} ;
pub struct DockerPackageScanner {
runtime : Arc < dyn ContainerRuntimeTrait > ,
}
impl DockerPackageScanner {
pub fn new ( runtime : Arc < dyn ContainerRuntimeTrait > ) -> Self {
Self { runtime }
}
/// Scan Docker containers and convert to package data
pub async fn scan_containers ( & self ) -> Result < HashMap < String , PackageDataEntry > > {
2026-02-01 13:24:03 +00:00
let containers = match self . runtime . list_containers ( ) . await {
Ok ( c ) = > c ,
Err ( e ) = > {
debug! ( " Failed to list containers: {} " , e ) ;
return Ok ( HashMap ::new ( ) ) ;
}
} ;
chore(ci): rustfmt + clippy clean-up to unblock the Rust CI job
The .github/workflows/ci.yml Rust job runs cargo fmt --check, clippy
with -D warnings, and tests. All three were failing. This commit:
- Applies rustfmt across the tree (the bulk of the diff — untouched
since the last toolchain bump, so a wide sweep was unavoidable).
- Fixes the correctness-level clippy errors:
container/bitcoin_simulator.rs wildcard-in-or-pattern
container/manifest.rs from_str rename to parse (reserved name)
container/podman_client.rs .get(0) -> .first()
container/runtime.rs manual += collapse
archipelago/src/constants.rs doc-comment → module-doc
api/rpc/package/install.rs stray /// comment above a non-item
container/docker_packages.rs redundant field init
streaming/advertisement.rs missing Metric import in tests
tests/orchestration_tests.rs `vec!` in non-Vec contexts
mesh/listener/dispatch.rs unused store_plain_message import
api/rpc/tor/mod.rs and mesh/steganography.rs: push-after-new → vec!
- Quiets wide legacy surfaces with crate-level allows in main.rs for
stylistic lints (too_many_arguments, type_complexity, doc indent,
enum variant prefix, wildcard-in-or, assertions-on-constants,
drop_non_drop, unused_io_amount, ptr_arg) — these fired in dozens
of places with no correctness payoff and have been churning every
toolchain bump.
- Tags intentional-dead-code helpers: wallet/ and streaming/ modules
are WIP, mesh::send_chunked_payload and DM_V1_MARKER are kept for
rollback compatibility, vpn::get_nostr_vpn_status is surface-area
for a not-yet-landed RPC.
cargo fmt --check, cargo clippy --all-targets --all-features
-- -D warnings, and cargo test --all-features now all pass locally.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-04-18 17:23:46 -04:00
2026-01-27 23:21:26 +00:00
debug! ( " Found {} containers " , containers . len ( ) ) ;
chore(ci): rustfmt + clippy clean-up to unblock the Rust CI job
The .github/workflows/ci.yml Rust job runs cargo fmt --check, clippy
with -D warnings, and tests. All three were failing. This commit:
- Applies rustfmt across the tree (the bulk of the diff — untouched
since the last toolchain bump, so a wide sweep was unavoidable).
- Fixes the correctness-level clippy errors:
container/bitcoin_simulator.rs wildcard-in-or-pattern
container/manifest.rs from_str rename to parse (reserved name)
container/podman_client.rs .get(0) -> .first()
container/runtime.rs manual += collapse
archipelago/src/constants.rs doc-comment → module-doc
api/rpc/package/install.rs stray /// comment above a non-item
container/docker_packages.rs redundant field init
streaming/advertisement.rs missing Metric import in tests
tests/orchestration_tests.rs `vec!` in non-Vec contexts
mesh/listener/dispatch.rs unused store_plain_message import
api/rpc/tor/mod.rs and mesh/steganography.rs: push-after-new → vec!
- Quiets wide legacy surfaces with crate-level allows in main.rs for
stylistic lints (too_many_arguments, type_complexity, doc indent,
enum variant prefix, wildcard-in-or, assertions-on-constants,
drop_non_drop, unused_io_amount, ptr_arg) — these fired in dozens
of places with no correctness payoff and have been churning every
toolchain bump.
- Tags intentional-dead-code helpers: wallet/ and streaming/ modules
are WIP, mesh::send_chunked_payload and DM_V1_MARKER are kept for
rollback compatibility, vpn::get_nostr_vpn_status is surface-area
for a not-yet-landed RPC.
cargo fmt --check, cargo clippy --all-targets --all-features
-- -D warnings, and cargo test --all-features now all pass locally.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-04-18 17:23:46 -04:00
2026-01-27 23:21:26 +00:00
let mut packages = HashMap ::new ( ) ;
chore(ci): rustfmt + clippy clean-up to unblock the Rust CI job
The .github/workflows/ci.yml Rust job runs cargo fmt --check, clippy
with -D warnings, and tests. All three were failing. This commit:
- Applies rustfmt across the tree (the bulk of the diff — untouched
since the last toolchain bump, so a wide sweep was unavoidable).
- Fixes the correctness-level clippy errors:
container/bitcoin_simulator.rs wildcard-in-or-pattern
container/manifest.rs from_str rename to parse (reserved name)
container/podman_client.rs .get(0) -> .first()
container/runtime.rs manual += collapse
archipelago/src/constants.rs doc-comment → module-doc
api/rpc/package/install.rs stray /// comment above a non-item
container/docker_packages.rs redundant field init
streaming/advertisement.rs missing Metric import in tests
tests/orchestration_tests.rs `vec!` in non-Vec contexts
mesh/listener/dispatch.rs unused store_plain_message import
api/rpc/tor/mod.rs and mesh/steganography.rs: push-after-new → vec!
- Quiets wide legacy surfaces with crate-level allows in main.rs for
stylistic lints (too_many_arguments, type_complexity, doc indent,
enum variant prefix, wildcard-in-or, assertions-on-constants,
drop_non_drop, unused_io_amount, ptr_arg) — these fired in dozens
of places with no correctness payoff and have been churning every
toolchain bump.
- Tags intentional-dead-code helpers: wallet/ and streaming/ modules
are WIP, mesh::send_chunked_payload and DM_V1_MARKER are kept for
rollback compatibility, vpn::get_nostr_vpn_status is surface-area
for a not-yet-landed RPC.
cargo fmt --check, cargo clippy --all-targets --all-features
-- -D warnings, and cargo test --all-features now all pass locally.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-04-18 17:23:46 -04:00
2026-01-27 23:57:29 +00:00
// Backend services that should not appear as apps
let excluded_services = [
" btcpay-db " ,
2026-02-25 18:04:41 +00:00
" nbxplorer " ,
2026-01-27 23:57:29 +00:00
" mempool-db " ,
" mempool-api " ,
2026-02-25 18:04:41 +00:00
" immich_postgres " ,
" immich_redis " ,
2026-01-28 00:47:00 +00:00
" endurain-db " ,
" nextcloud-db " ,
2026-03-31 11:06:19 +01:00
" indeedhub-api " ,
" indeedhub-ffmpeg " ,
" indeedhub-postgres " ,
" indeedhub-redis " ,
" indeedhub-minio " ,
" indeedhub-relay " ,
feat: v1.2.0-alpha — E2E encrypted mesh relay, steganography, relay status polling
Phase 5 mesh networking:
- E2E encrypted TX relay (X25519 + ChaCha20-Poly1305) — non-Archy nodes
relay encrypted blobs transparently via Meshcore native routing
- Steganographic encoding modes (WeatherStation, SensorNetwork) — traffic
looks like sensor data on the wire, 0xAA marker, configurable per-node
- Pre-flight Bitcoin Core health check on relay node — specific error codes
(bitcoin_unreachable, bitcoin_syncing, tx_rejected) instead of generic fails
- mesh.relay-status RPC endpoint — frontend polls for relay result every 3s
- On-Chain / Lightning tabs in Off-Grid Bitcoin panel
- Archy Peers vs Mesh Broadcast relay mode selector
- Mesh view fills viewport (no page scroll), internal panel scrolling
- Version bump to 1.2.0-alpha
Also includes: deploy hardening, container fixes, IndeedHub updates,
boot screen, dashboard improvements, MASTER_PLAN task tracking
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-17 23:56:37 +00:00
" indeedhub-build_api_1 " ,
" indeedhub-build_postgres_1 " ,
" indeedhub-build_redis_1 " ,
" indeedhub-build_minio_1 " ,
" indeedhub-build_minio-init_1 " ,
" indeedhub-build_relay_1 " ,
" indeedhub-build_ffmpeg-worker_1 " ,
2026-05-19 15:52:50 -04:00
" netbird-server " ,
2026-05-19 19:21:43 -04:00
" netbird-dashboard " ,
2026-05-19 20:11:22 -04:00
" saleor-api " ,
" saleor-worker " ,
" saleor-db " ,
" saleor-cache " ,
" saleor-jaeger " ,
" saleor-mailpit " ,
2026-05-20 23:02:57 -04:00
" saleor-storefront " ,
" saleor-storefront-app " ,
2026-05-17 17:30:04 -04:00
" buildx_buildkit_default " ,
2026-01-27 23:57:29 +00:00
] ;
chore(ci): rustfmt + clippy clean-up to unblock the Rust CI job
The .github/workflows/ci.yml Rust job runs cargo fmt --check, clippy
with -D warnings, and tests. All three were failing. This commit:
- Applies rustfmt across the tree (the bulk of the diff — untouched
since the last toolchain bump, so a wide sweep was unavoidable).
- Fixes the correctness-level clippy errors:
container/bitcoin_simulator.rs wildcard-in-or-pattern
container/manifest.rs from_str rename to parse (reserved name)
container/podman_client.rs .get(0) -> .first()
container/runtime.rs manual += collapse
archipelago/src/constants.rs doc-comment → module-doc
api/rpc/package/install.rs stray /// comment above a non-item
container/docker_packages.rs redundant field init
streaming/advertisement.rs missing Metric import in tests
tests/orchestration_tests.rs `vec!` in non-Vec contexts
mesh/listener/dispatch.rs unused store_plain_message import
api/rpc/tor/mod.rs and mesh/steganography.rs: push-after-new → vec!
- Quiets wide legacy surfaces with crate-level allows in main.rs for
stylistic lints (too_many_arguments, type_complexity, doc indent,
enum variant prefix, wildcard-in-or, assertions-on-constants,
drop_non_drop, unused_io_amount, ptr_arg) — these fired in dozens
of places with no correctness payoff and have been churning every
toolchain bump.
- Tags intentional-dead-code helpers: wallet/ and streaming/ modules
are WIP, mesh::send_chunked_payload and DM_V1_MARKER are kept for
rollback compatibility, vpn::get_nostr_vpn_status is surface-area
for a not-yet-landed RPC.
cargo fmt --check, cargo clippy --all-targets --all-features
-- -D warnings, and cargo test --all-features now all pass locally.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-04-18 17:23:46 -04:00
2026-05-05 11:29:18 -04:00
// First pass: collect running UI containers. Custom UI-backed apps must
// not advertise a launch URL unless their companion is actually alive.
2026-02-01 13:24:03 +00:00
let mut ui_containers : HashMap < String , String > = HashMap ::new ( ) ;
for container in & containers {
if container . name . ends_with ( " -ui " ) {
2026-05-05 11:29:18 -04:00
if ! matches! ( container . state , ContainerState ::Running ) {
continue ;
}
2026-02-17 15:03:34 +00:00
// Map fedimint-ui -> fedimint, lnd-ui -> lnd (normalize archy- prefix for lookup)
chore(ci): rustfmt + clippy clean-up to unblock the Rust CI job
The .github/workflows/ci.yml Rust job runs cargo fmt --check, clippy
with -D warnings, and tests. All three were failing. This commit:
- Applies rustfmt across the tree (the bulk of the diff — untouched
since the last toolchain bump, so a wide sweep was unavoidable).
- Fixes the correctness-level clippy errors:
container/bitcoin_simulator.rs wildcard-in-or-pattern
container/manifest.rs from_str rename to parse (reserved name)
container/podman_client.rs .get(0) -> .first()
container/runtime.rs manual += collapse
archipelago/src/constants.rs doc-comment → module-doc
api/rpc/package/install.rs stray /// comment above a non-item
container/docker_packages.rs redundant field init
streaming/advertisement.rs missing Metric import in tests
tests/orchestration_tests.rs `vec!` in non-Vec contexts
mesh/listener/dispatch.rs unused store_plain_message import
api/rpc/tor/mod.rs and mesh/steganography.rs: push-after-new → vec!
- Quiets wide legacy surfaces with crate-level allows in main.rs for
stylistic lints (too_many_arguments, type_complexity, doc indent,
enum variant prefix, wildcard-in-or, assertions-on-constants,
drop_non_drop, unused_io_amount, ptr_arg) — these fired in dozens
of places with no correctness payoff and have been churning every
toolchain bump.
- Tags intentional-dead-code helpers: wallet/ and streaming/ modules
are WIP, mesh::send_chunked_payload and DM_V1_MARKER are kept for
rollback compatibility, vpn::get_nostr_vpn_status is surface-area
for a not-yet-landed RPC.
cargo fmt --check, cargo clippy --all-targets --all-features
-- -D warnings, and cargo test --all-features now all pass locally.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-04-18 17:23:46 -04:00
let parent_app = container
. name
. strip_suffix ( " -ui " )
. unwrap_or ( & container . name ) ;
2026-02-17 15:03:34 +00:00
let canonical_id = parent_app
. strip_prefix ( " archy- " )
. unwrap_or ( parent_app )
. to_string ( ) ;
2026-05-05 11:29:18 -04:00
let ui_address = extract_lan_address ( & container . ports )
. or_else ( | | companion_lan_address ( & canonical_id ) ) ;
if let Some ( ui_address ) = ui_address {
ui_containers . insert ( canonical_id , ui_address ) ;
2026-02-01 13:24:03 +00:00
}
2026-01-27 23:21:26 +00:00
}
2026-02-01 13:24:03 +00:00
}
chore(ci): rustfmt + clippy clean-up to unblock the Rust CI job
The .github/workflows/ci.yml Rust job runs cargo fmt --check, clippy
with -D warnings, and tests. All three were failing. This commit:
- Applies rustfmt across the tree (the bulk of the diff — untouched
since the last toolchain bump, so a wide sweep was unavoidable).
- Fixes the correctness-level clippy errors:
container/bitcoin_simulator.rs wildcard-in-or-pattern
container/manifest.rs from_str rename to parse (reserved name)
container/podman_client.rs .get(0) -> .first()
container/runtime.rs manual += collapse
archipelago/src/constants.rs doc-comment → module-doc
api/rpc/package/install.rs stray /// comment above a non-item
container/docker_packages.rs redundant field init
streaming/advertisement.rs missing Metric import in tests
tests/orchestration_tests.rs `vec!` in non-Vec contexts
mesh/listener/dispatch.rs unused store_plain_message import
api/rpc/tor/mod.rs and mesh/steganography.rs: push-after-new → vec!
- Quiets wide legacy surfaces with crate-level allows in main.rs for
stylistic lints (too_many_arguments, type_complexity, doc indent,
enum variant prefix, wildcard-in-or, assertions-on-constants,
drop_non_drop, unused_io_amount, ptr_arg) — these fired in dozens
of places with no correctness payoff and have been churning every
toolchain bump.
- Tags intentional-dead-code helpers: wallet/ and streaming/ modules
are WIP, mesh::send_chunked_payload and DM_V1_MARKER are kept for
rollback compatibility, vpn::get_nostr_vpn_status is surface-area
for a not-yet-landed RPC.
cargo fmt --check, cargo clippy --all-targets --all-features
-- -D warnings, and cargo test --all-features now all pass locally.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-04-18 17:23:46 -04:00
2026-02-01 13:24:03 +00:00
debug! ( " Found {} UI containers " , ui_containers . len ( ) ) ;
chore(ci): rustfmt + clippy clean-up to unblock the Rust CI job
The .github/workflows/ci.yml Rust job runs cargo fmt --check, clippy
with -D warnings, and tests. All three were failing. This commit:
- Applies rustfmt across the tree (the bulk of the diff — untouched
since the last toolchain bump, so a wide sweep was unavoidable).
- Fixes the correctness-level clippy errors:
container/bitcoin_simulator.rs wildcard-in-or-pattern
container/manifest.rs from_str rename to parse (reserved name)
container/podman_client.rs .get(0) -> .first()
container/runtime.rs manual += collapse
archipelago/src/constants.rs doc-comment → module-doc
api/rpc/package/install.rs stray /// comment above a non-item
container/docker_packages.rs redundant field init
streaming/advertisement.rs missing Metric import in tests
tests/orchestration_tests.rs `vec!` in non-Vec contexts
mesh/listener/dispatch.rs unused store_plain_message import
api/rpc/tor/mod.rs and mesh/steganography.rs: push-after-new → vec!
- Quiets wide legacy surfaces with crate-level allows in main.rs for
stylistic lints (too_many_arguments, type_complexity, doc indent,
enum variant prefix, wildcard-in-or, assertions-on-constants,
drop_non_drop, unused_io_amount, ptr_arg) — these fired in dozens
of places with no correctness payoff and have been churning every
toolchain bump.
- Tags intentional-dead-code helpers: wallet/ and streaming/ modules
are WIP, mesh::send_chunked_payload and DM_V1_MARKER are kept for
rollback compatibility, vpn::get_nostr_vpn_status is surface-area
for a not-yet-landed RPC.
cargo fmt --check, cargo clippy --all-targets --all-features
-- -D warnings, and cargo test --all-features now all pass locally.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-04-18 17:23:46 -04:00
2026-02-01 13:24:03 +00:00
for container in containers {
// Extract app ID from container name
// Support both archy-* containers (docker-compose) and plain names (manual)
let app_id = if container . name . starts_with ( " archy- " ) {
chore(ci): rustfmt + clippy clean-up to unblock the Rust CI job
The .github/workflows/ci.yml Rust job runs cargo fmt --check, clippy
with -D warnings, and tests. All three were failing. This commit:
- Applies rustfmt across the tree (the bulk of the diff — untouched
since the last toolchain bump, so a wide sweep was unavoidable).
- Fixes the correctness-level clippy errors:
container/bitcoin_simulator.rs wildcard-in-or-pattern
container/manifest.rs from_str rename to parse (reserved name)
container/podman_client.rs .get(0) -> .first()
container/runtime.rs manual += collapse
archipelago/src/constants.rs doc-comment → module-doc
api/rpc/package/install.rs stray /// comment above a non-item
container/docker_packages.rs redundant field init
streaming/advertisement.rs missing Metric import in tests
tests/orchestration_tests.rs `vec!` in non-Vec contexts
mesh/listener/dispatch.rs unused store_plain_message import
api/rpc/tor/mod.rs and mesh/steganography.rs: push-after-new → vec!
- Quiets wide legacy surfaces with crate-level allows in main.rs for
stylistic lints (too_many_arguments, type_complexity, doc indent,
enum variant prefix, wildcard-in-or, assertions-on-constants,
drop_non_drop, unused_io_amount, ptr_arg) — these fired in dozens
of places with no correctness payoff and have been churning every
toolchain bump.
- Tags intentional-dead-code helpers: wallet/ and streaming/ modules
are WIP, mesh::send_chunked_payload and DM_V1_MARKER are kept for
rollback compatibility, vpn::get_nostr_vpn_status is surface-area
for a not-yet-landed RPC.
cargo fmt --check, cargo clippy --all-targets --all-features
-- -D warnings, and cargo test --all-features now all pass locally.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-04-18 17:23:46 -04:00
container
. name
. strip_prefix ( " archy- " )
2026-02-01 13:24:03 +00:00
. unwrap_or ( & container . name )
. to_string ( )
} else {
// Use the container name as-is for manually started containers
container . name . clone ( )
} ;
feat: cloud native file browser, settings Claude auth, deploy hardening
- Add native Cloud file browser with FileBrowser API integration
- Add cloud store, filebrowser-client, useAudioPlayer, useFileType composables
- Add Cloud components: FileGrid, FileCard, FileCardGrid, CloudToolbar
- Add Claude authentication section to Settings with OAuth status check
- Harden deploy script to preserve /aiui/ and claude-login.html
- Add nginx proxies for btcpay, homeassistant, filebrowser (HTTPS block)
- Add app configs for filebrowser, searxng, penpot in package.rs
- Update goal progress tracking with app aliases
- Improve mobile back button composable with ResizeObserver
- Update various views with cloud integration and UI refinements
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-04 23:05:01 +00:00
// Normalize multi-container app IDs to their canonical names
let app_id = match app_id . as_str ( ) {
" immich_server " = > " immich " . to_string ( ) ,
_ = > app_id ,
} ;
chore(ci): rustfmt + clippy clean-up to unblock the Rust CI job
The .github/workflows/ci.yml Rust job runs cargo fmt --check, clippy
with -D warnings, and tests. All three were failing. This commit:
- Applies rustfmt across the tree (the bulk of the diff — untouched
since the last toolchain bump, so a wide sweep was unavoidable).
- Fixes the correctness-level clippy errors:
container/bitcoin_simulator.rs wildcard-in-or-pattern
container/manifest.rs from_str rename to parse (reserved name)
container/podman_client.rs .get(0) -> .first()
container/runtime.rs manual += collapse
archipelago/src/constants.rs doc-comment → module-doc
api/rpc/package/install.rs stray /// comment above a non-item
container/docker_packages.rs redundant field init
streaming/advertisement.rs missing Metric import in tests
tests/orchestration_tests.rs `vec!` in non-Vec contexts
mesh/listener/dispatch.rs unused store_plain_message import
api/rpc/tor/mod.rs and mesh/steganography.rs: push-after-new → vec!
- Quiets wide legacy surfaces with crate-level allows in main.rs for
stylistic lints (too_many_arguments, type_complexity, doc indent,
enum variant prefix, wildcard-in-or, assertions-on-constants,
drop_non_drop, unused_io_amount, ptr_arg) — these fired in dozens
of places with no correctness payoff and have been churning every
toolchain bump.
- Tags intentional-dead-code helpers: wallet/ and streaming/ modules
are WIP, mesh::send_chunked_payload and DM_V1_MARKER are kept for
rollback compatibility, vpn::get_nostr_vpn_status is surface-area
for a not-yet-landed RPC.
cargo fmt --check, cargo clippy --all-targets --all-features
-- -D warnings, and cargo test --all-features now all pass locally.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-04-18 17:23:46 -04:00
2026-01-27 23:57:29 +00:00
// Skip backend services (databases, APIs, etc.)
if excluded_services . contains ( & app_id . as_str ( ) ) {
debug! ( " Skipping backend service: {} " , app_id ) ;
continue ;
}
feat: v1.2.0-alpha — E2E encrypted mesh relay, steganography, relay status polling
Phase 5 mesh networking:
- E2E encrypted TX relay (X25519 + ChaCha20-Poly1305) — non-Archy nodes
relay encrypted blobs transparently via Meshcore native routing
- Steganographic encoding modes (WeatherStation, SensorNetwork) — traffic
looks like sensor data on the wire, 0xAA marker, configurable per-node
- Pre-flight Bitcoin Core health check on relay node — specific error codes
(bitcoin_unreachable, bitcoin_syncing, tx_rejected) instead of generic fails
- mesh.relay-status RPC endpoint — frontend polls for relay result every 3s
- On-Chain / Lightning tabs in Off-Grid Bitcoin panel
- Archy Peers vs Mesh Broadcast relay mode selector
- Mesh view fills viewport (no page scroll), internal panel scrolling
- Version bump to 1.2.0-alpha
Also includes: deploy hardening, container fixes, IndeedHub updates,
boot screen, dashboard improvements, MASTER_PLAN task tracking
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-17 23:56:37 +00:00
2026-05-20 00:28:30 -04:00
if is_transient_podman_helper ( & app_id , & container . ports ) {
debug! ( " Skipping transient Podman helper container: {} " , app_id ) ;
continue ;
}
feat: v1.2.0-alpha — E2E encrypted mesh relay, steganography, relay status polling
Phase 5 mesh networking:
- E2E encrypted TX relay (X25519 + ChaCha20-Poly1305) — non-Archy nodes
relay encrypted blobs transparently via Meshcore native routing
- Steganographic encoding modes (WeatherStation, SensorNetwork) — traffic
looks like sensor data on the wire, 0xAA marker, configurable per-node
- Pre-flight Bitcoin Core health check on relay node — specific error codes
(bitcoin_unreachable, bitcoin_syncing, tx_rejected) instead of generic fails
- mesh.relay-status RPC endpoint — frontend polls for relay result every 3s
- On-Chain / Lightning tabs in Off-Grid Bitcoin panel
- Archy Peers vs Mesh Broadcast relay mode selector
- Mesh view fills viewport (no page scroll), internal panel scrolling
- Version bump to 1.2.0-alpha
Also includes: deploy hardening, container fixes, IndeedHub updates,
boot screen, dashboard improvements, MASTER_PLAN task tracking
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-17 23:56:37 +00:00
// Skip podman-compose infrastructure containers (e.g. indeedhub-build_api_1)
// These have the project prefix pattern: {project}_{service}_{instance}
if app_id . starts_with ( " indeedhub-build_ " ) {
debug! ( " Skipping IndeedHub compose service: {} " , app_id ) ;
continue ;
}
2026-05-17 17:30:04 -04:00
if app_id . starts_with ( " buildx_buildkit " ) {
debug! ( " Skipping BuildKit helper container: {} " , app_id ) ;
continue ;
}
2026-02-01 13:24:03 +00:00
// Skip UI containers (they're merged with their parent apps)
if app_id . ends_with ( " -ui " ) {
debug! ( " Skipping UI container: {} " , app_id ) ;
continue ;
}
chore(ci): rustfmt + clippy clean-up to unblock the Rust CI job
The .github/workflows/ci.yml Rust job runs cargo fmt --check, clippy
with -D warnings, and tests. All three were failing. This commit:
- Applies rustfmt across the tree (the bulk of the diff — untouched
since the last toolchain bump, so a wide sweep was unavoidable).
- Fixes the correctness-level clippy errors:
container/bitcoin_simulator.rs wildcard-in-or-pattern
container/manifest.rs from_str rename to parse (reserved name)
container/podman_client.rs .get(0) -> .first()
container/runtime.rs manual += collapse
archipelago/src/constants.rs doc-comment → module-doc
api/rpc/package/install.rs stray /// comment above a non-item
container/docker_packages.rs redundant field init
streaming/advertisement.rs missing Metric import in tests
tests/orchestration_tests.rs `vec!` in non-Vec contexts
mesh/listener/dispatch.rs unused store_plain_message import
api/rpc/tor/mod.rs and mesh/steganography.rs: push-after-new → vec!
- Quiets wide legacy surfaces with crate-level allows in main.rs for
stylistic lints (too_many_arguments, type_complexity, doc indent,
enum variant prefix, wildcard-in-or, assertions-on-constants,
drop_non_drop, unused_io_amount, ptr_arg) — these fired in dozens
of places with no correctness payoff and have been churning every
toolchain bump.
- Tags intentional-dead-code helpers: wallet/ and streaming/ modules
are WIP, mesh::send_chunked_payload and DM_V1_MARKER are kept for
rollback compatibility, vpn::get_nostr_vpn_status is surface-area
for a not-yet-landed RPC.
cargo fmt --check, cargo clippy --all-targets --all-features
-- -D warnings, and cargo test --all-features now all pass locally.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-04-18 17:23:46 -04:00
2026-01-27 23:21:26 +00:00
// Get metadata for this app
let metadata = get_app_metadata ( & app_id ) ;
chore(ci): rustfmt + clippy clean-up to unblock the Rust CI job
The .github/workflows/ci.yml Rust job runs cargo fmt --check, clippy
with -D warnings, and tests. All three were failing. This commit:
- Applies rustfmt across the tree (the bulk of the diff — untouched
since the last toolchain bump, so a wide sweep was unavoidable).
- Fixes the correctness-level clippy errors:
container/bitcoin_simulator.rs wildcard-in-or-pattern
container/manifest.rs from_str rename to parse (reserved name)
container/podman_client.rs .get(0) -> .first()
container/runtime.rs manual += collapse
archipelago/src/constants.rs doc-comment → module-doc
api/rpc/package/install.rs stray /// comment above a non-item
container/docker_packages.rs redundant field init
streaming/advertisement.rs missing Metric import in tests
tests/orchestration_tests.rs `vec!` in non-Vec contexts
mesh/listener/dispatch.rs unused store_plain_message import
api/rpc/tor/mod.rs and mesh/steganography.rs: push-after-new → vec!
- Quiets wide legacy surfaces with crate-level allows in main.rs for
stylistic lints (too_many_arguments, type_complexity, doc indent,
enum variant prefix, wildcard-in-or, assertions-on-constants,
drop_non_drop, unused_io_amount, ptr_arg) — these fired in dozens
of places with no correctness payoff and have been churning every
toolchain bump.
- Tags intentional-dead-code helpers: wallet/ and streaming/ modules
are WIP, mesh::send_chunked_payload and DM_V1_MARKER are kept for
rollback compatibility, vpn::get_nostr_vpn_status is surface-area
for a not-yet-landed RPC.
cargo fmt --check, cargo clippy --all-targets --all-features
-- -D warnings, and cargo test --all-features now all pass locally.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-04-18 17:23:46 -04:00
2026-03-18 16:29:03 +00:00
// Resolve UI address: separate UI containers > static map > dynamic ports
2026-05-19 21:45:17 -04:00
let lan_address = if app_id = = " netbird " {
reachable_lan_address ( & app_id , netbird_configured_launch_url ( ) . await ) . await
} else if let Some ( ui_address ) = ui_containers . get ( & app_id ) {
2026-03-18 16:29:03 +00:00
// Apps with separate UI containers (e.g. archy-bitcoin-ui, archy-lnd-ui)
debug! ( " Using UI container for {}: {} " , app_id , ui_address ) ;
2026-05-13 15:09:22 -04:00
reachable_lan_address ( & app_id , Some ( ui_address . clone ( ) ) ) . await
2026-02-01 13:24:03 +00:00
} else {
2026-05-13 15:09:22 -04:00
// Prefer the known web UI port over arbitrary first binding
// (for example Gitea exposes SSH on 2222 before web on 3001).
2026-05-17 17:30:04 -04:00
let candidate = if uses_allocated_launch_port ( & app_id ) {
extract_lan_address ( & container . ports )
. or_else ( | | PodmanClient ::lan_address_for ( & app_id ) )
} else {
PodmanClient ::lan_address_for ( & app_id )
. or_else ( | | extract_lan_address ( & container . ports ) )
} ;
2026-05-13 15:09:22 -04:00
reachable_lan_address ( & app_id , candidate ) . await
2026-02-01 13:24:03 +00:00
} ;
chore(ci): rustfmt + clippy clean-up to unblock the Rust CI job
The .github/workflows/ci.yml Rust job runs cargo fmt --check, clippy
with -D warnings, and tests. All three were failing. This commit:
- Applies rustfmt across the tree (the bulk of the diff — untouched
since the last toolchain bump, so a wide sweep was unavoidable).
- Fixes the correctness-level clippy errors:
container/bitcoin_simulator.rs wildcard-in-or-pattern
container/manifest.rs from_str rename to parse (reserved name)
container/podman_client.rs .get(0) -> .first()
container/runtime.rs manual += collapse
archipelago/src/constants.rs doc-comment → module-doc
api/rpc/package/install.rs stray /// comment above a non-item
container/docker_packages.rs redundant field init
streaming/advertisement.rs missing Metric import in tests
tests/orchestration_tests.rs `vec!` in non-Vec contexts
mesh/listener/dispatch.rs unused store_plain_message import
api/rpc/tor/mod.rs and mesh/steganography.rs: push-after-new → vec!
- Quiets wide legacy surfaces with crate-level allows in main.rs for
stylistic lints (too_many_arguments, type_complexity, doc indent,
enum variant prefix, wildcard-in-or, assertions-on-constants,
drop_non_drop, unused_io_amount, ptr_arg) — these fired in dozens
of places with no correctness payoff and have been churning every
toolchain bump.
- Tags intentional-dead-code helpers: wallet/ and streaming/ modules
are WIP, mesh::send_chunked_payload and DM_V1_MARKER are kept for
rollback compatibility, vpn::get_nostr_vpn_status is surface-area
for a not-yet-landed RPC.
cargo fmt --check, cargo clippy --all-targets --all-features
-- -D warnings, and cargo test --all-features now all pass locally.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-04-18 17:23:46 -04:00
debug! (
" Container {}: ports={:?}, lan_address={:?} " ,
app_id , container . ports , lan_address
) ;
2026-01-27 23:21:26 +00:00
// Convert container state to package/service state
let ( package_state , service_status ) = convert_state ( & container . state ) ;
chore(ci): rustfmt + clippy clean-up to unblock the Rust CI job
The .github/workflows/ci.yml Rust job runs cargo fmt --check, clippy
with -D warnings, and tests. All three were failing. This commit:
- Applies rustfmt across the tree (the bulk of the diff — untouched
since the last toolchain bump, so a wide sweep was unavoidable).
- Fixes the correctness-level clippy errors:
container/bitcoin_simulator.rs wildcard-in-or-pattern
container/manifest.rs from_str rename to parse (reserved name)
container/podman_client.rs .get(0) -> .first()
container/runtime.rs manual += collapse
archipelago/src/constants.rs doc-comment → module-doc
api/rpc/package/install.rs stray /// comment above a non-item
container/docker_packages.rs redundant field init
streaming/advertisement.rs missing Metric import in tests
tests/orchestration_tests.rs `vec!` in non-Vec contexts
mesh/listener/dispatch.rs unused store_plain_message import
api/rpc/tor/mod.rs and mesh/steganography.rs: push-after-new → vec!
- Quiets wide legacy surfaces with crate-level allows in main.rs for
stylistic lints (too_many_arguments, type_complexity, doc indent,
enum variant prefix, wildcard-in-or, assertions-on-constants,
drop_non_drop, unused_io_amount, ptr_arg) — these fired in dozens
of places with no correctness payoff and have been churning every
toolchain bump.
- Tags intentional-dead-code helpers: wallet/ and streaming/ modules
are WIP, mesh::send_chunked_payload and DM_V1_MARKER are kept for
rollback compatibility, vpn::get_nostr_vpn_status is surface-area
for a not-yet-landed RPC.
cargo fmt --check, cargo clippy --all-targets --all-features
-- -D warnings, and cargo test --all-features now all pass locally.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-04-18 17:23:46 -04:00
2026-03-21 01:21:08 +00:00
let tor_address = read_tor_address ( & app_id ) . await ;
2026-02-17 15:03:34 +00:00
2026-04-09 11:47:35 +02:00
// Extract actual version from container image tag
let running_version = image_versions ::extract_version_from_image ( & container . image ) ;
chore(ci): rustfmt + clippy clean-up to unblock the Rust CI job
The .github/workflows/ci.yml Rust job runs cargo fmt --check, clippy
with -D warnings, and tests. All three were failing. This commit:
- Applies rustfmt across the tree (the bulk of the diff — untouched
since the last toolchain bump, so a wide sweep was unavoidable).
- Fixes the correctness-level clippy errors:
container/bitcoin_simulator.rs wildcard-in-or-pattern
container/manifest.rs from_str rename to parse (reserved name)
container/podman_client.rs .get(0) -> .first()
container/runtime.rs manual += collapse
archipelago/src/constants.rs doc-comment → module-doc
api/rpc/package/install.rs stray /// comment above a non-item
container/docker_packages.rs redundant field init
streaming/advertisement.rs missing Metric import in tests
tests/orchestration_tests.rs `vec!` in non-Vec contexts
mesh/listener/dispatch.rs unused store_plain_message import
api/rpc/tor/mod.rs and mesh/steganography.rs: push-after-new → vec!
- Quiets wide legacy surfaces with crate-level allows in main.rs for
stylistic lints (too_many_arguments, type_complexity, doc indent,
enum variant prefix, wildcard-in-or, assertions-on-constants,
drop_non_drop, unused_io_amount, ptr_arg) — these fired in dozens
of places with no correctness payoff and have been churning every
toolchain bump.
- Tags intentional-dead-code helpers: wallet/ and streaming/ modules
are WIP, mesh::send_chunked_payload and DM_V1_MARKER are kept for
rollback compatibility, vpn::get_nostr_vpn_status is surface-area
for a not-yet-landed RPC.
cargo fmt --check, cargo clippy --all-targets --all-features
-- -D warnings, and cargo test --all-features now all pass locally.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-04-18 17:23:46 -04:00
let available_update =
2026-05-13 15:09:22 -04:00
image_versions ::available_update_for_app ( & app_id , & container . image ) ;
2026-04-09 11:47:35 +02:00
2026-01-27 23:21:26 +00:00
let package = PackageDataEntry {
state : package_state . clone ( ) ,
security+feat: v1.3.0 — pentest remediation, container reliability, UI overhaul
Security (33 pentest findings addressed):
- CRITICAL: backend binds 127.0.0.1, path traversal in tor.rs/dwn fixed
- HIGH: federation requires signatures, XSS login redirect, RBAC viewer restricted
- HIGH: tar slip prevention, S3 SSRF validation, backup ID validation
- MEDIUM: remember-me random secret, TOTP session rotation, password re-auth
- LOW: CSP unsafe-inline removed, CORS dev-only, onion/webhook validation
Container reliability:
- Memory limits on all 37 containers (OOM prevention)
- Exited vs stopped state distinction with health-aware status badges
- Crash recovery coordination (no more restart cascade)
- User-stopped tracking survives reboots
- Tiered boot recovery (databases → core → services → apps)
UI:
- Wallet TransactionsModal, health-aware app status badges
- Restart button on containers, exited/crashed red state
- Mesh view overhaul, glass button updates, BaseModal/ToggleSwitch
- Apps sticky header removed, dev faucet, mutable mock wallet
Infrastructure:
- LND REST port 8080 exposed over Tor (LND Connect fix)
- Nginx cookie_session fix, deploy script Tor config updated
- Dev environment: podman auto-start, boot mode simulation
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-19 12:44:31 +00:00
health : container . health . clone ( ) ,
chore(ci): rustfmt + clippy clean-up to unblock the Rust CI job
The .github/workflows/ci.yml Rust job runs cargo fmt --check, clippy
with -D warnings, and tests. All three were failing. This commit:
- Applies rustfmt across the tree (the bulk of the diff — untouched
since the last toolchain bump, so a wide sweep was unavoidable).
- Fixes the correctness-level clippy errors:
container/bitcoin_simulator.rs wildcard-in-or-pattern
container/manifest.rs from_str rename to parse (reserved name)
container/podman_client.rs .get(0) -> .first()
container/runtime.rs manual += collapse
archipelago/src/constants.rs doc-comment → module-doc
api/rpc/package/install.rs stray /// comment above a non-item
container/docker_packages.rs redundant field init
streaming/advertisement.rs missing Metric import in tests
tests/orchestration_tests.rs `vec!` in non-Vec contexts
mesh/listener/dispatch.rs unused store_plain_message import
api/rpc/tor/mod.rs and mesh/steganography.rs: push-after-new → vec!
- Quiets wide legacy surfaces with crate-level allows in main.rs for
stylistic lints (too_many_arguments, type_complexity, doc indent,
enum variant prefix, wildcard-in-or, assertions-on-constants,
drop_non_drop, unused_io_amount, ptr_arg) — these fired in dozens
of places with no correctness payoff and have been churning every
toolchain bump.
- Tags intentional-dead-code helpers: wallet/ and streaming/ modules
are WIP, mesh::send_chunked_payload and DM_V1_MARKER are kept for
rollback compatibility, vpn::get_nostr_vpn_status is surface-area
for a not-yet-landed RPC.
cargo fmt --check, cargo clippy --all-targets --all-features
-- -D warnings, and cargo test --all-features now all pass locally.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-04-18 17:23:46 -04:00
exit_code : if package_state = = PackageState ::Exited {
container . exit_code
} else {
None
} ,
2026-01-27 23:21:26 +00:00
static_files : StaticFiles {
license : " MIT " . to_string ( ) ,
instructions : metadata . description . clone ( ) ,
icon : metadata . icon . clone ( ) ,
} ,
manifest : Manifest {
id : app_id . clone ( ) ,
title : metadata . title . clone ( ) ,
2026-04-09 11:47:35 +02:00
version : running_version ,
2026-01-27 23:21:26 +00:00
description : Description {
short : metadata . description . clone ( ) ,
long : metadata . description . clone ( ) ,
} ,
release_notes : " Docker container " . to_string ( ) ,
license : " MIT " . to_string ( ) ,
wrapper_repo : metadata . repo . clone ( ) ,
upstream_repo : metadata . repo . clone ( ) ,
support_site : metadata . repo . clone ( ) ,
marketing_site : metadata . repo . clone ( ) ,
donation_url : None ,
author : Some ( " Archipelago " . to_string ( ) ) ,
website : lan_address . clone ( ) ,
feat: add app tier system — core/recommended/optional (SCALE-02, SCALE-03)
get_app_tier() classifies all apps:
- core: Bitcoin, LND, Electrs, Mempool, BTCPay, DWN, FileBrowser
- recommended: Fedimint, Grafana, Vaultwarden, Kuma, SearXNG, etc.
- optional: everything else
Tier field added to Manifest struct (data_model.rs) and exposed
via WebSocket package data for frontend tier badges.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-14 03:27:51 +00:00
tier : Some ( metadata . tier . to_string ( ) ) ,
2026-02-17 15:03:34 +00:00
interfaces : if lan_address . is_some ( ) | | tor_address . is_some ( ) {
2026-01-27 23:21:26 +00:00
Some ( Interfaces {
main : Some ( MainInterface {
ui : Some ( " true " . to_string ( ) ) ,
2026-02-17 15:03:34 +00:00
tor_config : tor_address . clone ( ) ,
2026-01-27 23:21:26 +00:00
lan_config : None ,
} ) ,
} )
} else {
None
} ,
} ,
2026-04-09 11:47:35 +02:00
available_update ,
2026-01-27 23:21:26 +00:00
installed : Some ( InstalledPackageDataEntry {
current_dependents : HashMap ::new ( ) ,
current_dependencies : HashMap ::new ( ) ,
last_backup : None ,
2026-02-17 15:03:34 +00:00
interface_addresses : if lan_address . is_some ( ) | | tor_address . is_some ( ) {
2026-01-27 23:21:26 +00:00
let mut addresses = HashMap ::new ( ) ;
2026-02-17 15:03:34 +00:00
// Only include tor_address if we have a real v3 .onion (not placeholder)
let tor = tor_address
. filter ( | s | is_real_onion_address ( s ) )
. unwrap_or_default ( ) ;
2026-01-27 23:21:26 +00:00
addresses . insert (
" main " . to_string ( ) ,
InterfaceAddress {
2026-02-17 15:03:34 +00:00
tor_address : tor ,
chore(ci): rustfmt + clippy clean-up to unblock the Rust CI job
The .github/workflows/ci.yml Rust job runs cargo fmt --check, clippy
with -D warnings, and tests. All three were failing. This commit:
- Applies rustfmt across the tree (the bulk of the diff — untouched
since the last toolchain bump, so a wide sweep was unavoidable).
- Fixes the correctness-level clippy errors:
container/bitcoin_simulator.rs wildcard-in-or-pattern
container/manifest.rs from_str rename to parse (reserved name)
container/podman_client.rs .get(0) -> .first()
container/runtime.rs manual += collapse
archipelago/src/constants.rs doc-comment → module-doc
api/rpc/package/install.rs stray /// comment above a non-item
container/docker_packages.rs redundant field init
streaming/advertisement.rs missing Metric import in tests
tests/orchestration_tests.rs `vec!` in non-Vec contexts
mesh/listener/dispatch.rs unused store_plain_message import
api/rpc/tor/mod.rs and mesh/steganography.rs: push-after-new → vec!
- Quiets wide legacy surfaces with crate-level allows in main.rs for
stylistic lints (too_many_arguments, type_complexity, doc indent,
enum variant prefix, wildcard-in-or, assertions-on-constants,
drop_non_drop, unused_io_amount, ptr_arg) — these fired in dozens
of places with no correctness payoff and have been churning every
toolchain bump.
- Tags intentional-dead-code helpers: wallet/ and streaming/ modules
are WIP, mesh::send_chunked_payload and DM_V1_MARKER are kept for
rollback compatibility, vpn::get_nostr_vpn_status is surface-area
for a not-yet-landed RPC.
cargo fmt --check, cargo clippy --all-targets --all-features
-- -D warnings, and cargo test --all-features now all pass locally.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-04-18 17:23:46 -04:00
lan_address ,
2026-01-27 23:21:26 +00:00
} ,
) ;
addresses
} else {
HashMap ::new ( )
} ,
status : service_status ,
} ) ,
install_progress : None ,
2026-04-21 19:11:36 -04:00
uninstall_stage : None ,
2026-01-27 23:21:26 +00:00
} ;
chore(ci): rustfmt + clippy clean-up to unblock the Rust CI job
The .github/workflows/ci.yml Rust job runs cargo fmt --check, clippy
with -D warnings, and tests. All three were failing. This commit:
- Applies rustfmt across the tree (the bulk of the diff — untouched
since the last toolchain bump, so a wide sweep was unavoidable).
- Fixes the correctness-level clippy errors:
container/bitcoin_simulator.rs wildcard-in-or-pattern
container/manifest.rs from_str rename to parse (reserved name)
container/podman_client.rs .get(0) -> .first()
container/runtime.rs manual += collapse
archipelago/src/constants.rs doc-comment → module-doc
api/rpc/package/install.rs stray /// comment above a non-item
container/docker_packages.rs redundant field init
streaming/advertisement.rs missing Metric import in tests
tests/orchestration_tests.rs `vec!` in non-Vec contexts
mesh/listener/dispatch.rs unused store_plain_message import
api/rpc/tor/mod.rs and mesh/steganography.rs: push-after-new → vec!
- Quiets wide legacy surfaces with crate-level allows in main.rs for
stylistic lints (too_many_arguments, type_complexity, doc indent,
enum variant prefix, wildcard-in-or, assertions-on-constants,
drop_non_drop, unused_io_amount, ptr_arg) — these fired in dozens
of places with no correctness payoff and have been churning every
toolchain bump.
- Tags intentional-dead-code helpers: wallet/ and streaming/ modules
are WIP, mesh::send_chunked_payload and DM_V1_MARKER are kept for
rollback compatibility, vpn::get_nostr_vpn_status is surface-area
for a not-yet-landed RPC.
cargo fmt --check, cargo clippy --all-targets --all-features
-- -D warnings, and cargo test --all-features now all pass locally.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-04-18 17:23:46 -04:00
2026-01-27 23:21:26 +00:00
packages . insert ( app_id . clone ( ) , package ) ;
chore(ci): rustfmt + clippy clean-up to unblock the Rust CI job
The .github/workflows/ci.yml Rust job runs cargo fmt --check, clippy
with -D warnings, and tests. All three were failing. This commit:
- Applies rustfmt across the tree (the bulk of the diff — untouched
since the last toolchain bump, so a wide sweep was unavoidable).
- Fixes the correctness-level clippy errors:
container/bitcoin_simulator.rs wildcard-in-or-pattern
container/manifest.rs from_str rename to parse (reserved name)
container/podman_client.rs .get(0) -> .first()
container/runtime.rs manual += collapse
archipelago/src/constants.rs doc-comment → module-doc
api/rpc/package/install.rs stray /// comment above a non-item
container/docker_packages.rs redundant field init
streaming/advertisement.rs missing Metric import in tests
tests/orchestration_tests.rs `vec!` in non-Vec contexts
mesh/listener/dispatch.rs unused store_plain_message import
api/rpc/tor/mod.rs and mesh/steganography.rs: push-after-new → vec!
- Quiets wide legacy surfaces with crate-level allows in main.rs for
stylistic lints (too_many_arguments, type_complexity, doc indent,
enum variant prefix, wildcard-in-or, assertions-on-constants,
drop_non_drop, unused_io_amount, ptr_arg) — these fired in dozens
of places with no correctness payoff and have been churning every
toolchain bump.
- Tags intentional-dead-code helpers: wallet/ and streaming/ modules
are WIP, mesh::send_chunked_payload and DM_V1_MARKER are kept for
rollback compatibility, vpn::get_nostr_vpn_status is surface-area
for a not-yet-landed RPC.
cargo fmt --check, cargo clippy --all-targets --all-features
-- -D warnings, and cargo test --all-features now all pass locally.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-04-18 17:23:46 -04:00
info! (
" Detected container: {} ({}) " ,
metadata . title ,
package_state_str ( & package_state )
) ;
2026-01-27 23:21:26 +00:00
}
chore(ci): rustfmt + clippy clean-up to unblock the Rust CI job
The .github/workflows/ci.yml Rust job runs cargo fmt --check, clippy
with -D warnings, and tests. All three were failing. This commit:
- Applies rustfmt across the tree (the bulk of the diff — untouched
since the last toolchain bump, so a wide sweep was unavoidable).
- Fixes the correctness-level clippy errors:
container/bitcoin_simulator.rs wildcard-in-or-pattern
container/manifest.rs from_str rename to parse (reserved name)
container/podman_client.rs .get(0) -> .first()
container/runtime.rs manual += collapse
archipelago/src/constants.rs doc-comment → module-doc
api/rpc/package/install.rs stray /// comment above a non-item
container/docker_packages.rs redundant field init
streaming/advertisement.rs missing Metric import in tests
tests/orchestration_tests.rs `vec!` in non-Vec contexts
mesh/listener/dispatch.rs unused store_plain_message import
api/rpc/tor/mod.rs and mesh/steganography.rs: push-after-new → vec!
- Quiets wide legacy surfaces with crate-level allows in main.rs for
stylistic lints (too_many_arguments, type_complexity, doc indent,
enum variant prefix, wildcard-in-or, assertions-on-constants,
drop_non_drop, unused_io_amount, ptr_arg) — these fired in dozens
of places with no correctness payoff and have been churning every
toolchain bump.
- Tags intentional-dead-code helpers: wallet/ and streaming/ modules
are WIP, mesh::send_chunked_payload and DM_V1_MARKER are kept for
rollback compatibility, vpn::get_nostr_vpn_status is surface-area
for a not-yet-landed RPC.
cargo fmt --check, cargo clippy --all-targets --all-features
-- -D warnings, and cargo test --all-features now all pass locally.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-04-18 17:23:46 -04:00
2026-01-27 23:21:26 +00:00
Ok ( packages )
}
}
struct AppMetadata {
title : String ,
description : String ,
icon : String ,
repo : String ,
feat: add app tier system — core/recommended/optional (SCALE-02, SCALE-03)
get_app_tier() classifies all apps:
- core: Bitcoin, LND, Electrs, Mempool, BTCPay, DWN, FileBrowser
- recommended: Fedimint, Grafana, Vaultwarden, Kuma, SearXNG, etc.
- optional: everything else
Tier field added to Manifest struct (data_model.rs) and exposed
via WebSocket package data for frontend tier badges.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-14 03:27:51 +00:00
tier : & 'static str ,
2026-01-27 23:21:26 +00:00
}
feat: add app tier system — core/recommended/optional (SCALE-02, SCALE-03)
get_app_tier() classifies all apps:
- core: Bitcoin, LND, Electrs, Mempool, BTCPay, DWN, FileBrowser
- recommended: Fedimint, Grafana, Vaultwarden, Kuma, SearXNG, etc.
- optional: everything else
Tier field added to Manifest struct (data_model.rs) and exposed
via WebSocket package data for frontend tier badges.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-14 03:27:51 +00:00
/// Get the app tier: "core", "recommended", or "optional".
2026-03-14 03:39:17 +00:00
fn get_app_tier ( app_id : & str ) -> & 'static str {
2026-01-27 23:21:26 +00:00
match app_id {
feat: add app tier system — core/recommended/optional (SCALE-02, SCALE-03)
get_app_tier() classifies all apps:
- core: Bitcoin, LND, Electrs, Mempool, BTCPay, DWN, FileBrowser
- recommended: Fedimint, Grafana, Vaultwarden, Kuma, SearXNG, etc.
- optional: everything else
Tier field added to Manifest struct (data_model.rs) and exposed
via WebSocket package data for frontend tier badges.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-14 03:27:51 +00:00
// Core: required for basic Bitcoin node
" bitcoin " | " bitcoin-core " | " bitcoin-knots " = > " core " ,
" lnd " = > " core " ,
chore(ci): rustfmt + clippy clean-up to unblock the Rust CI job
The .github/workflows/ci.yml Rust job runs cargo fmt --check, clippy
with -D warnings, and tests. All three were failing. This commit:
- Applies rustfmt across the tree (the bulk of the diff — untouched
since the last toolchain bump, so a wide sweep was unavoidable).
- Fixes the correctness-level clippy errors:
container/bitcoin_simulator.rs wildcard-in-or-pattern
container/manifest.rs from_str rename to parse (reserved name)
container/podman_client.rs .get(0) -> .first()
container/runtime.rs manual += collapse
archipelago/src/constants.rs doc-comment → module-doc
api/rpc/package/install.rs stray /// comment above a non-item
container/docker_packages.rs redundant field init
streaming/advertisement.rs missing Metric import in tests
tests/orchestration_tests.rs `vec!` in non-Vec contexts
mesh/listener/dispatch.rs unused store_plain_message import
api/rpc/tor/mod.rs and mesh/steganography.rs: push-after-new → vec!
- Quiets wide legacy surfaces with crate-level allows in main.rs for
stylistic lints (too_many_arguments, type_complexity, doc indent,
enum variant prefix, wildcard-in-or, assertions-on-constants,
drop_non_drop, unused_io_amount, ptr_arg) — these fired in dozens
of places with no correctness payoff and have been churning every
toolchain bump.
- Tags intentional-dead-code helpers: wallet/ and streaming/ modules
are WIP, mesh::send_chunked_payload and DM_V1_MARKER are kept for
rollback compatibility, vpn::get_nostr_vpn_status is surface-area
for a not-yet-landed RPC.
cargo fmt --check, cargo clippy --all-targets --all-features
-- -D warnings, and cargo test --all-features now all pass locally.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-04-18 17:23:46 -04:00
" mempool " | " mempool-web " | " mempool-api " | " electrumx " | " mempool-electrs " | " electrs " = > {
" core "
}
feat: add app tier system — core/recommended/optional (SCALE-02, SCALE-03)
get_app_tier() classifies all apps:
- core: Bitcoin, LND, Electrs, Mempool, BTCPay, DWN, FileBrowser
- recommended: Fedimint, Grafana, Vaultwarden, Kuma, SearXNG, etc.
- optional: everything else
Tier field added to Manifest struct (data_model.rs) and exposed
via WebSocket package data for frontend tier badges.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-14 03:27:51 +00:00
" btcpay " | " btcpay-server " | " btcpayserver " = > " core " ,
" dwn " = > " core " ,
" filebrowser " = > " core " ,
// Recommended: enhanced functionality
" fedimint " | " fedimint-gateway " = > " recommended " ,
" vaultwarden " = > " recommended " ,
" uptime-kuma " = > " recommended " ,
" grafana " = > " recommended " ,
" searxng " = > " recommended " ,
2026-05-19 20:11:22 -04:00
" saleor " = > " recommended " ,
2026-05-19 14:29:20 -04:00
" tailscale " | " netbird " = > " recommended " ,
feat: add app tier system — core/recommended/optional (SCALE-02, SCALE-03)
get_app_tier() classifies all apps:
- core: Bitcoin, LND, Electrs, Mempool, BTCPay, DWN, FileBrowser
- recommended: Fedimint, Grafana, Vaultwarden, Kuma, SearXNG, etc.
- optional: everything else
Tier field added to Manifest struct (data_model.rs) and exposed
via WebSocket package data for frontend tier badges.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-14 03:27:51 +00:00
" portainer " = > " recommended " ,
// Optional: everything else
_ = > " optional " ,
}
}
2026-05-20 00:28:30 -04:00
fn is_transient_podman_helper ( app_id : & str , ports : & [ String ] ) -> bool {
if ! ports . is_empty ( ) {
return false ;
}
let Some ( ( left , right ) ) = app_id . split_once ( '_' ) else {
return false ;
} ;
! left . is_empty ( )
& & ! right . is_empty ( )
& & left . chars ( ) . all ( | c | c . is_ascii_lowercase ( ) )
& & right . chars ( ) . all ( | c | c . is_ascii_lowercase ( ) )
}
feat: add app tier system — core/recommended/optional (SCALE-02, SCALE-03)
get_app_tier() classifies all apps:
- core: Bitcoin, LND, Electrs, Mempool, BTCPay, DWN, FileBrowser
- recommended: Fedimint, Grafana, Vaultwarden, Kuma, SearXNG, etc.
- optional: everything else
Tier field added to Manifest struct (data_model.rs) and exposed
via WebSocket package data for frontend tier badges.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-14 03:27:51 +00:00
fn get_app_metadata ( app_id : & str ) -> AppMetadata {
let mut meta = match app_id {
release(v1.7.37-alpha): bitcoin-core install fixes + dynamic node UI + full-archive default
Install flow
- api/rpc/package/install.rs: always append the literal image URL as a
last-resort pull candidate in do_pull_image, so images not carried by
any configured mirror (docker.io/bitcoin/bitcoin:28.4) still install
instead of masquerading as a generic pull failure across every mirror.
- api/rpc/package/install.rs: write_bitcoin_conf now skips on any stat
error, not just "file exists". Once bitcoin-knots' first-boot chowns
/var/lib/archipelago/bitcoin into the container's user namespace (700
perms, UID 100100/100101), the archipelago daemon can't even traverse
in — try_exists returns Err which unwrap_or(false) treated as "not
present" and drove a doomed write. Now errors out of the directory
traversal are treated as "conf already owned by container user" and
the write is skipped. Mirrors the lnd.conf pattern.
- api/rpc/package/install.rs: drop the hardcoded `prune=550` from the
conf default. Operators with multi-TB drives shouldn't be silently
pruned; users who want a pruned node can set it in bitcoin.conf
themselves. Full archive is the only honest default.
- api/rpc/package/config.rs: bitcoin-core now passes explicit
-server/-rpcbind/-rpcallowip/-rpcport/-printtoconsole/-datadir CLI
args. Vanilla bitcoin/bitcoin:28.4 has no entrypoint wrapper and
reads conf + argv only; without these the RPC listens on 127.0.0.1
inside the container and rootlessport can't reach it, so the
bitcoin-ui companion gets 502 on every /bitcoin-rpc/ call.
Bitcoin Knots keeps its own entrypoint-driven defaults.
- container/docker_packages.rs: split bitcoin-core out of the shared
AppMetadata arm. bitcoin-core now surfaces as "Bitcoin Core" with
bitcoin-core.svg and a Reference-implementation description; the
bitcoin + bitcoin-knots ids keep the Knots branding. Fixes the home
card showing "Bitcoin Knots" for a Core install.
Bitcoin node UI (docker/bitcoin-ui)
- index.html: impl name/tagline/logo now dynamic. applyImplBranding()
reads subversion from getnetworkinfo — /Satoshi:X/Knots:Y/ resolves
to Bitcoin Knots, plain /Satoshi:X/ resolves to Bitcoin Core. Both
get their own icon and subtitle. Settings modal replaced its
hardcoded Regtest/txindex=1/port-18443 placeholders with live values
from getblockchaininfo + getindexinfo + getzmqnotifications.
- index.html: new Storage info card (Full Archive · X GB /
Pruned · X GB from blockchainInfo.pruned + size_on_disk) visible on
the main dashboard, same level as Network. Settings modal mirrors it
with the prune height when applicable.
- Dockerfile + assets/: bitcoin-core.svg, bitcoin-knots.webp, and the
bg-network.jpg used by the dashboard are now COPY'd into the image
under /usr/share/nginx/html/assets. Previously the <img src> pointed
at paths that 404'd into the SPA fallback and the onerror handler
hid the broken logo silently.
Frontend
- appSession/appSessionConfig.ts: add bitcoin-core to APP_PORTS (8334),
HTTPS_PROXY_PATHS (/app/bitcoin-ui/), and APP_TITLES (Bitcoin Core).
Without these the AppSessionFrame showed "No URL found for
bitcoin-core" and the home/app-list title fell through to the raw id.
- settings/AccountInfoSection.vue: backfill What's New entries for
v1.7.31 through v1.7.37 that had been missed in earlier cuts.
Release plumbing
- releases/v1.7.37-alpha/: binary + frontend tarball.
- releases/manifest.json: v1.7.37-alpha, sha256/size refreshed.
- Cargo.toml / package.json: version bumps.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-04-22 11:03:47 -04:00
" bitcoin-core " = > AppMetadata {
title : " Bitcoin Core " . to_string ( ) ,
description : " Reference Bitcoin node implementation " . to_string ( ) ,
icon : " /assets/img/app-icons/bitcoin-core.svg " . to_string ( ) ,
repo : " https://github.com/bitcoin/bitcoin " . to_string ( ) ,
tier : " " ,
} ,
" bitcoin " | " bitcoin-knots " = > AppMetadata {
2026-02-01 13:24:03 +00:00
title : " Bitcoin Knots " . to_string ( ) ,
release(v1.7.37-alpha): bitcoin-core install fixes + dynamic node UI + full-archive default
Install flow
- api/rpc/package/install.rs: always append the literal image URL as a
last-resort pull candidate in do_pull_image, so images not carried by
any configured mirror (docker.io/bitcoin/bitcoin:28.4) still install
instead of masquerading as a generic pull failure across every mirror.
- api/rpc/package/install.rs: write_bitcoin_conf now skips on any stat
error, not just "file exists". Once bitcoin-knots' first-boot chowns
/var/lib/archipelago/bitcoin into the container's user namespace (700
perms, UID 100100/100101), the archipelago daemon can't even traverse
in — try_exists returns Err which unwrap_or(false) treated as "not
present" and drove a doomed write. Now errors out of the directory
traversal are treated as "conf already owned by container user" and
the write is skipped. Mirrors the lnd.conf pattern.
- api/rpc/package/install.rs: drop the hardcoded `prune=550` from the
conf default. Operators with multi-TB drives shouldn't be silently
pruned; users who want a pruned node can set it in bitcoin.conf
themselves. Full archive is the only honest default.
- api/rpc/package/config.rs: bitcoin-core now passes explicit
-server/-rpcbind/-rpcallowip/-rpcport/-printtoconsole/-datadir CLI
args. Vanilla bitcoin/bitcoin:28.4 has no entrypoint wrapper and
reads conf + argv only; without these the RPC listens on 127.0.0.1
inside the container and rootlessport can't reach it, so the
bitcoin-ui companion gets 502 on every /bitcoin-rpc/ call.
Bitcoin Knots keeps its own entrypoint-driven defaults.
- container/docker_packages.rs: split bitcoin-core out of the shared
AppMetadata arm. bitcoin-core now surfaces as "Bitcoin Core" with
bitcoin-core.svg and a Reference-implementation description; the
bitcoin + bitcoin-knots ids keep the Knots branding. Fixes the home
card showing "Bitcoin Knots" for a Core install.
Bitcoin node UI (docker/bitcoin-ui)
- index.html: impl name/tagline/logo now dynamic. applyImplBranding()
reads subversion from getnetworkinfo — /Satoshi:X/Knots:Y/ resolves
to Bitcoin Knots, plain /Satoshi:X/ resolves to Bitcoin Core. Both
get their own icon and subtitle. Settings modal replaced its
hardcoded Regtest/txindex=1/port-18443 placeholders with live values
from getblockchaininfo + getindexinfo + getzmqnotifications.
- index.html: new Storage info card (Full Archive · X GB /
Pruned · X GB from blockchainInfo.pruned + size_on_disk) visible on
the main dashboard, same level as Network. Settings modal mirrors it
with the prune height when applicable.
- Dockerfile + assets/: bitcoin-core.svg, bitcoin-knots.webp, and the
bg-network.jpg used by the dashboard are now COPY'd into the image
under /usr/share/nginx/html/assets. Previously the <img src> pointed
at paths that 404'd into the SPA fallback and the onerror handler
hid the broken logo silently.
Frontend
- appSession/appSessionConfig.ts: add bitcoin-core to APP_PORTS (8334),
HTTPS_PROXY_PATHS (/app/bitcoin-ui/), and APP_TITLES (Bitcoin Core).
Without these the AppSessionFrame showed "No URL found for
bitcoin-core" and the home/app-list title fell through to the raw id.
- settings/AccountInfoSection.vue: backfill What's New entries for
v1.7.31 through v1.7.37 that had been missed in earlier cuts.
Release plumbing
- releases/v1.7.37-alpha/: binary + frontend tarball.
- releases/manifest.json: v1.7.37-alpha, sha256/size refreshed.
- Cargo.toml / package.json: version bumps.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-04-22 11:03:47 -04:00
description : " Enhanced Bitcoin node implementation " . to_string ( ) ,
2026-02-01 13:24:03 +00:00
icon : " /assets/img/app-icons/bitcoin-knots.webp " . to_string ( ) ,
repo : " https://github.com/bitcoinknots/bitcoin " . to_string ( ) ,
feat: add app tier system — core/recommended/optional (SCALE-02, SCALE-03)
get_app_tier() classifies all apps:
- core: Bitcoin, LND, Electrs, Mempool, BTCPay, DWN, FileBrowser
- recommended: Fedimint, Grafana, Vaultwarden, Kuma, SearXNG, etc.
- optional: everything else
Tier field added to Manifest struct (data_model.rs) and exposed
via WebSocket package data for frontend tier badges.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-14 03:27:51 +00:00
tier : " " ,
2026-01-27 23:21:26 +00:00
} ,
2026-02-01 18:46:35 +00:00
" btcpay " | " btcpay-server " | " btcpayserver " = > AppMetadata {
2026-01-27 23:21:26 +00:00
title : " BTCPay Server " . to_string ( ) ,
description : " Self-hosted Bitcoin payment processor " . to_string ( ) ,
icon : " /assets/img/app-icons/btcpay-server.png " . to_string ( ) ,
repo : " https://github.com/btcpayserver/btcpayserver " . to_string ( ) ,
2026-03-14 03:36:44 +00:00
tier : " " ,
2026-01-27 23:21:26 +00:00
} ,
2026-02-25 18:04:41 +00:00
" homeassistant " | " home-assistant " = > AppMetadata {
2026-01-27 23:21:26 +00:00
title : " Home Assistant " . to_string ( ) ,
description : " Open source home automation platform " . to_string ( ) ,
icon : " /assets/img/app-icons/homeassistant.png " . to_string ( ) ,
repo : " https://github.com/home-assistant/core " . to_string ( ) ,
2026-03-14 03:36:44 +00:00
tier : " " ,
2026-01-27 23:21:26 +00:00
} ,
" grafana " = > AppMetadata {
title : " Grafana " . to_string ( ) ,
description : " Analytics and monitoring platform " . to_string ( ) ,
2026-03-06 18:05:25 +00:00
icon : " /assets/img/app-icons/grafana.png " . to_string ( ) ,
2026-01-27 23:21:26 +00:00
repo : " https://github.com/grafana/grafana " . to_string ( ) ,
2026-03-14 03:36:44 +00:00
tier : " " ,
2026-01-27 23:21:26 +00:00
} ,
" endurain " = > AppMetadata {
title : " Endurain " . to_string ( ) ,
2026-01-28 00:47:00 +00:00
description : " Self-hosted fitness tracking platform " . to_string ( ) ,
icon : " /assets/img/app-icons/endurain.png " . to_string ( ) ,
repo : " https://github.com/joaovitoriasilva/endurain " . to_string ( ) ,
2026-03-14 03:36:44 +00:00
tier : " " ,
2026-01-27 23:21:26 +00:00
} ,
2026-03-18 17:56:45 +00:00
" fedimint " | " fedimintd " = > AppMetadata {
title : " Fedimint Guardian " . to_string ( ) ,
description : " Federated Bitcoin mint — Guardian node for federation consensus " . to_string ( ) ,
2026-03-09 07:43:12 +00:00
icon : " /assets/img/app-icons/fedimint.png " . to_string ( ) ,
repo : " https://github.com/fedimint/fedimint " . to_string ( ) ,
2026-03-14 03:36:44 +00:00
tier : " " ,
2026-03-09 07:43:12 +00:00
} ,
" fedimint-gateway " = > AppMetadata {
title : " Fedimint Gateway " . to_string ( ) ,
description : " Fedimint Lightning gateway for ecash payments " . to_string ( ) ,
2026-02-17 15:03:34 +00:00
icon : " /assets/img/app-icons/fedimint.png " . to_string ( ) ,
2026-01-27 23:21:26 +00:00
repo : " https://github.com/fedimint/fedimint " . to_string ( ) ,
2026-03-14 03:36:44 +00:00
tier : " " ,
2026-01-27 23:21:26 +00:00
} ,
" morphos " | " morphos-server " = > AppMetadata {
2026-01-28 00:47:00 +00:00
title : " Morphos " . to_string ( ) ,
description : " Self-hosted file converter " . to_string ( ) ,
2026-03-06 18:05:25 +00:00
icon : " /assets/img/app-icons/morphos.png " . to_string ( ) ,
2026-01-28 00:47:00 +00:00
repo : " https://github.com/danvergara/morphos " . to_string ( ) ,
2026-03-14 03:36:44 +00:00
tier : " " ,
2026-01-27 23:21:26 +00:00
} ,
" lnd " | " lightning-stack " = > AppMetadata {
2026-01-28 00:47:00 +00:00
title : " LND " . to_string ( ) ,
description : " Lightning Network Daemon " . to_string ( ) ,
icon : " /assets/img/app-icons/lnd.svg " . to_string ( ) ,
2026-01-27 23:21:26 +00:00
repo : " https://github.com/lightningnetwork/lnd " . to_string ( ) ,
2026-03-14 03:36:44 +00:00
tier : " " ,
2026-01-27 23:21:26 +00:00
} ,
" mempool " | " mempool-web " = > AppMetadata {
title : " Mempool " . to_string ( ) ,
description : " Bitcoin blockchain explorer " . to_string ( ) ,
2026-01-28 00:47:00 +00:00
icon : " /assets/img/app-icons/mempool.webp " . to_string ( ) ,
2026-01-27 23:21:26 +00:00
repo : " https://github.com/mempool/mempool " . to_string ( ) ,
2026-03-14 03:36:44 +00:00
tier : " " ,
2026-01-27 23:21:26 +00:00
} ,
2026-03-16 12:58:35 +00:00
" electrumx " | " mempool-electrs " | " electrs " = > AppMetadata {
title : " ElectrumX " . to_string ( ) ,
description : " ElectrumX server — full Electrum protocol indexer for Bitcoin. Powers Mempool and Electrum wallets. " . to_string ( ) ,
2026-02-17 15:03:34 +00:00
icon : " /assets/img/app-icons/electrs.svg " . to_string ( ) ,
2026-03-16 12:58:35 +00:00
repo : " https://github.com/spesmilo/electrumx " . to_string ( ) ,
2026-03-14 03:36:44 +00:00
tier : " " ,
2026-02-17 15:03:34 +00:00
} ,
2026-01-27 23:21:26 +00:00
" ollama " = > AppMetadata {
title : " Ollama " . to_string ( ) ,
description : " Run large language models locally " . to_string ( ) ,
2026-03-06 18:05:25 +00:00
icon : " /assets/img/app-icons/ollama.png " . to_string ( ) ,
2026-01-27 23:21:26 +00:00
repo : " https://github.com/ollama/ollama " . to_string ( ) ,
2026-03-14 03:36:44 +00:00
tier : " " ,
2026-01-27 23:21:26 +00:00
} ,
2026-03-14 05:53:41 +00:00
" monerod " | " monero " = > AppMetadata {
title : " Monero " . to_string ( ) ,
description : " Private cryptocurrency full node (Monero) " . to_string ( ) ,
icon : " /assets/img/app-icons/monero.png " . to_string ( ) ,
repo : " https://github.com/monero-project/monero " . to_string ( ) ,
tier : " " ,
} ,
" elementsd " | " liquid " = > AppMetadata {
title : " Liquid Network " . to_string ( ) ,
description : " Bitcoin sidechain for confidential transactions and faster settlements " . to_string ( ) ,
icon : " /assets/img/app-icons/liquid.png " . to_string ( ) ,
repo : " https://github.com/ElementsProject/elements " . to_string ( ) ,
tier : " " ,
} ,
2026-01-27 23:21:26 +00:00
" searxng " = > AppMetadata {
title : " SearXNG " . to_string ( ) ,
description : " Privacy-respecting metasearch engine " . to_string ( ) ,
icon : " /assets/img/app-icons/searxng.png " . to_string ( ) ,
repo : " https://github.com/searxng/searxng " . to_string ( ) ,
2026-03-14 03:36:44 +00:00
tier : " " ,
2026-01-27 23:21:26 +00:00
} ,
2026-04-02 16:15:04 +01:00
" cryptpad " = > AppMetadata {
title : " CryptPad " . to_string ( ) ,
description : " End-to-end encrypted document collaboration " . to_string ( ) ,
icon : " /assets/img/app-icons/cryptpad.webp " . to_string ( ) ,
repo : " https://github.com/cryptpad/cryptpad " . to_string ( ) ,
2026-03-14 03:36:44 +00:00
tier : " " ,
2026-01-27 23:21:26 +00:00
} ,
2026-01-28 00:47:00 +00:00
" nextcloud " = > AppMetadata {
title : " Nextcloud " . to_string ( ) ,
description : " Self-hosted cloud storage and file management " . to_string ( ) ,
2026-02-01 18:46:35 +00:00
icon : " /assets/img/app-icons/nextcloud.webp " . to_string ( ) ,
2026-01-28 00:47:00 +00:00
repo : " https://github.com/nextcloud/server " . to_string ( ) ,
2026-03-14 03:36:44 +00:00
tier : " " ,
2026-01-28 00:47:00 +00:00
} ,
2026-02-01 18:46:35 +00:00
" vaultwarden " = > AppMetadata {
title : " Vaultwarden " . to_string ( ) ,
description : " Self-hosted password manager (Bitwarden compatible) " . to_string ( ) ,
2026-03-06 18:05:25 +00:00
icon : " /assets/img/app-icons/vaultwarden.webp " . to_string ( ) ,
2026-02-01 18:46:35 +00:00
repo : " https://github.com/dani-garcia/vaultwarden " . to_string ( ) ,
2026-03-14 03:36:44 +00:00
tier : " " ,
2026-02-01 18:46:35 +00:00
} ,
" jellyfin " = > AppMetadata {
title : " Jellyfin " . to_string ( ) ,
description : " Free media server system " . to_string ( ) ,
2026-03-06 18:05:25 +00:00
icon : " /assets/img/app-icons/jellyfin.webp " . to_string ( ) ,
2026-02-01 18:46:35 +00:00
repo : " https://github.com/jellyfin/jellyfin " . to_string ( ) ,
2026-03-14 03:36:44 +00:00
tier : " " ,
2026-02-01 18:46:35 +00:00
} ,
" photoprism " = > AppMetadata {
title : " PhotoPrism " . to_string ( ) ,
description : " AI-powered photo management " . to_string ( ) ,
2026-03-15 04:01:12 +00:00
icon : " /assets/img/app-icons/photoprism.svg " . to_string ( ) ,
2026-02-01 18:46:35 +00:00
repo : " https://github.com/photoprism/photoprism " . to_string ( ) ,
2026-03-14 03:36:44 +00:00
tier : " " ,
2026-02-01 18:46:35 +00:00
} ,
2026-02-25 18:04:41 +00:00
" immich " | " immich_server " = > AppMetadata {
2026-02-01 18:46:35 +00:00
title : " Immich " . to_string ( ) ,
description : " High-performance self-hosted photo and video backup " . to_string ( ) ,
2026-03-06 18:05:25 +00:00
icon : " /assets/img/app-icons/immich.png " . to_string ( ) ,
2026-02-01 18:46:35 +00:00
repo : " https://github.com/immich-app/immich " . to_string ( ) ,
2026-03-14 03:36:44 +00:00
tier : " " ,
2026-02-01 18:46:35 +00:00
} ,
" filebrowser " = > AppMetadata {
title : " File Browser " . to_string ( ) ,
description : " Web-based file manager " . to_string ( ) ,
icon : " /assets/img/app-icons/file-browser.webp " . to_string ( ) ,
repo : " https://github.com/filebrowser/filebrowser " . to_string ( ) ,
2026-03-14 03:36:44 +00:00
tier : " " ,
2026-02-01 18:46:35 +00:00
} ,
" nginx-proxy-manager " = > AppMetadata {
title : " Nginx Proxy Manager " . to_string ( ) ,
description : " Easy proxy management with SSL " . to_string ( ) ,
icon : " /assets/img/app-icons/nginx.svg " . to_string ( ) ,
repo : " https://github.com/NginxProxyManager/nginx-proxy-manager " . to_string ( ) ,
2026-03-14 03:36:44 +00:00
tier : " " ,
2026-02-01 18:46:35 +00:00
} ,
" portainer " = > AppMetadata {
title : " Portainer " . to_string ( ) ,
description : " Container management UI " . to_string ( ) ,
icon : " /assets/img/app-icons/portainer.webp " . to_string ( ) ,
repo : " https://github.com/portainer/portainer " . to_string ( ) ,
2026-03-14 03:36:44 +00:00
tier : " " ,
2026-02-01 18:46:35 +00:00
} ,
" uptime-kuma " = > AppMetadata {
title : " Uptime Kuma " . to_string ( ) ,
description : " Self-hosted monitoring tool " . to_string ( ) ,
icon : " /assets/img/app-icons/uptime-kuma.webp " . to_string ( ) ,
repo : " https://github.com/louislam/uptime-kuma " . to_string ( ) ,
2026-03-14 03:36:44 +00:00
tier : " " ,
2026-02-01 18:46:35 +00:00
} ,
" tailscale " = > AppMetadata {
title : " Tailscale " . to_string ( ) ,
description : " Zero-config VPN for secure remote access " . to_string ( ) ,
icon : " /assets/img/app-icons/tailscale.webp " . to_string ( ) ,
repo : " https://github.com/tailscale/tailscale " . to_string ( ) ,
2026-03-14 03:36:44 +00:00
tier : " " ,
2026-02-01 18:46:35 +00:00
} ,
2026-05-19 14:29:20 -04:00
" netbird " = > AppMetadata {
title : " NetBird " . to_string ( ) ,
2026-05-19 15:52:50 -04:00
description : " Self-hosted WireGuard mesh VPN control plane and dashboard " . to_string ( ) ,
2026-05-19 14:29:20 -04:00
icon : " /assets/img/app-icons/netbird.svg " . to_string ( ) ,
repo : " https://github.com/netbirdio/netbird " . to_string ( ) ,
tier : " " ,
} ,
2026-05-19 20:11:22 -04:00
" saleor " = > AppMetadata {
title : " Saleor " . to_string ( ) ,
2026-05-20 23:02:57 -04:00
description : " Composable commerce platform with storefront, dashboard, and GraphQL API. The customer storefront opens on port 9011; admin dashboard is on 9010 with admin@example.com credentials stored on the node. " . to_string ( ) ,
2026-05-19 20:11:22 -04:00
icon : " /assets/img/app-icons/saleor.svg " . to_string ( ) ,
repo : " https://github.com/saleor/saleor " . to_string ( ) ,
tier : " " ,
} ,
2026-05-19 17:20:32 -04:00
" gitea " = > AppMetadata {
title : " Gitea " . to_string ( ) ,
description : " Self-hosted Git service with repository and package hosting " . to_string ( ) ,
icon : " /assets/img/app-icons/gitea.svg " . to_string ( ) ,
repo : " https://gitea.com " . to_string ( ) ,
tier : " " ,
} ,
2026-03-14 17:12:41 +00:00
" indeedhub " | " indeehub " = > AppMetadata {
2026-03-15 04:01:58 +00:00
title : " IndeedHub " . to_string ( ) ,
2026-02-03 21:43:33 +00:00
description : " Decentralized media streaming platform " . to_string ( ) ,
2026-03-15 04:01:58 +00:00
icon : " /assets/img/app-icons/indeedhub.png " . to_string ( ) ,
2026-02-03 21:43:33 +00:00
repo : " https://github.com/indeedhub/indeedhub " . to_string ( ) ,
2026-03-14 03:36:44 +00:00
tier : " " ,
2026-02-03 21:43:33 +00:00
} ,
2026-03-09 07:43:12 +00:00
" dwn " = > AppMetadata {
title : " Decentralized Web Node " . to_string ( ) ,
description : " Store and sync personal data with DID-based access control " . to_string ( ) ,
icon : " /assets/img/app-icons/dwn.svg " . to_string ( ) ,
repo : " https://github.com/TBD54566975/dwn-server " . to_string ( ) ,
2026-03-14 03:36:44 +00:00
tier : " " ,
2026-03-09 07:43:12 +00:00
} ,
2026-03-06 18:05:25 +00:00
" tor " | " archy-tor " = > AppMetadata {
title : " Tor " . to_string ( ) ,
description : " Anonymous overlay network for privacy " . to_string ( ) ,
icon : " /assets/img/app-icons/tor.svg " . to_string ( ) ,
repo : " https://gitlab.torproject.org/tpo/core/tor " . to_string ( ) ,
2026-03-14 03:36:44 +00:00
tier : " " ,
2026-03-06 18:05:25 +00:00
} ,
2026-03-12 00:19:30 +00:00
" botfights " = > AppMetadata {
title : " BotFights " . to_string ( ) ,
description : " AI bot arena — build, train, and battle autonomous agents " . to_string ( ) ,
icon : " /assets/img/app-icons/botfights.svg " . to_string ( ) ,
repo : " https://botfights.net " . to_string ( ) ,
2026-03-14 03:36:44 +00:00
tier : " " ,
2026-03-12 00:19:30 +00:00
} ,
" nwnn " = > AppMetadata {
title : " Next Web News Network " . to_string ( ) ,
description : " Decentralized news and link aggregator, synced from Telegram " . to_string ( ) ,
icon : " /assets/img/app-icons/nwnn.png " . to_string ( ) ,
repo : " https://nwnn.l484.com " . to_string ( ) ,
2026-03-14 03:36:44 +00:00
tier : " " ,
2026-03-12 00:19:30 +00:00
} ,
" 484-kitchen " = > AppMetadata {
title : " 484 Kitchen " . to_string ( ) ,
description : " K484 application platform " . to_string ( ) ,
icon : " /assets/img/app-icons/484-kitchen.png " . to_string ( ) ,
repo : " https://484.kitchen " . to_string ( ) ,
2026-03-14 03:36:44 +00:00
tier : " " ,
2026-03-12 00:19:30 +00:00
} ,
" call-the-operator " = > AppMetadata {
title : " Call the Operator " . to_string ( ) ,
description : " Escape the Matrix — explore decentralized alternatives " . to_string ( ) ,
icon : " /assets/img/app-icons/call-the-operator.png " . to_string ( ) ,
repo : " https://cta.tx1138.com " . to_string ( ) ,
2026-03-14 03:36:44 +00:00
tier : " " ,
2026-03-12 00:19:30 +00:00
} ,
" arch-presentation " = > AppMetadata {
title : " Arch Presentation " . to_string ( ) ,
description : " Archipelago: The Future of Decentralized Infrastructure " . to_string ( ) ,
icon : " /assets/img/app-icons/arch-presentation.png " . to_string ( ) ,
repo : " https://present.l484.com " . to_string ( ) ,
2026-03-14 03:36:44 +00:00
tier : " " ,
2026-03-12 00:19:30 +00:00
} ,
" syntropy-institute " = > AppMetadata {
title : " Syntropy Institute " . to_string ( ) ,
description : " Medicine Reimagined — frequency analysis-therapy and digital homeopathy " . to_string ( ) ,
icon : " /assets/img/app-icons/syntropy-institute.png " . to_string ( ) ,
repo : " https://syntropy.institute " . to_string ( ) ,
2026-03-14 03:36:44 +00:00
tier : " " ,
2026-03-12 00:19:30 +00:00
} ,
" t-zero " = > AppMetadata {
title : " T-0 " . to_string ( ) ,
description : " Documentary series on decentralization, Bitcoin, and the ungovernable future " . to_string ( ) ,
icon : " /assets/img/app-icons/t-zero.png " . to_string ( ) ,
repo : " https://teeminuszero.net " . to_string ( ) ,
2026-03-14 03:36:44 +00:00
tier : " " ,
2026-03-12 00:19:30 +00:00
} ,
2026-01-27 23:21:26 +00:00
_ = > AppMetadata {
title : app_id . to_string ( ) ,
description : format ! ( " {} application " , app_id ) ,
icon : " /assets/img/favico.png " . to_string ( ) ,
repo : " # " . to_string ( ) ,
feat: add app tier system — core/recommended/optional (SCALE-02, SCALE-03)
get_app_tier() classifies all apps:
- core: Bitcoin, LND, Electrs, Mempool, BTCPay, DWN, FileBrowser
- recommended: Fedimint, Grafana, Vaultwarden, Kuma, SearXNG, etc.
- optional: everything else
Tier field added to Manifest struct (data_model.rs) and exposed
via WebSocket package data for frontend tier badges.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-14 03:27:51 +00:00
tier : " " ,
2026-01-27 23:21:26 +00:00
} ,
feat: add app tier system — core/recommended/optional (SCALE-02, SCALE-03)
get_app_tier() classifies all apps:
- core: Bitcoin, LND, Electrs, Mempool, BTCPay, DWN, FileBrowser
- recommended: Fedimint, Grafana, Vaultwarden, Kuma, SearXNG, etc.
- optional: everything else
Tier field added to Manifest struct (data_model.rs) and exposed
via WebSocket package data for frontend tier badges.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-14 03:27:51 +00:00
} ;
2026-05-17 19:22:18 -04:00
apply_dynamic_metadata ( app_id , & mut meta ) ;
feat: add app tier system — core/recommended/optional (SCALE-02, SCALE-03)
get_app_tier() classifies all apps:
- core: Bitcoin, LND, Electrs, Mempool, BTCPay, DWN, FileBrowser
- recommended: Fedimint, Grafana, Vaultwarden, Kuma, SearXNG, etc.
- optional: everything else
Tier field added to Manifest struct (data_model.rs) and exposed
via WebSocket package data for frontend tier badges.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-14 03:27:51 +00:00
meta . tier = get_app_tier ( app_id ) ;
meta
2026-01-27 23:21:26 +00:00
}
2026-05-17 19:22:18 -04:00
fn apply_dynamic_metadata ( app_id : & str , meta : & mut AppMetadata ) {
let config_path = format! ( " /var/lib/archipelago/app-configs/ {} .json " , app_id ) ;
let Ok ( data ) = std ::fs ::read_to_string ( config_path ) else {
return ;
} ;
let Ok ( cfg ) = serde_json ::from_str ::< serde_json ::Value > ( & data ) else {
return ;
} ;
if let Some ( title ) = cfg
. get ( " title " )
. and_then ( | v | v . as_str ( ) )
. map ( str ::trim )
. filter ( | s | ! s . is_empty ( ) & & s . len ( ) < = 80 )
{
meta . title = title . to_string ( ) ;
}
if let Some ( description ) = cfg
. get ( " description " )
. and_then ( | v | v . as_str ( ) )
. map ( str ::trim )
. filter ( | s | ! s . is_empty ( ) & & s . len ( ) < = 240 )
{
meta . description = description . to_string ( ) ;
}
}
2026-02-17 15:03:34 +00:00
/// Map app_id to Tor hidden service directory name.
/// "archipelago" is the main web UI (nginx port 80).
/// Supports container names from deploy (archy-*, btcpay-server, etc.).
fn tor_service_name ( app_id : & str ) -> Option < & 'static str > {
match app_id {
" archipelago " = > Some ( " archipelago " ) ,
2026-04-01 18:22:30 +01:00
" bitcoin " | " bitcoin-knots " | " bitcoind " = > Some ( " bitcoin " ) ,
" electrumx " | " electrs " | " electrum " = > Some ( " electrumx " ) ,
2026-02-17 15:03:34 +00:00
" lnd " | " lnd-ui " = > Some ( " lnd " ) ,
" btcpay " | " btcpay-server " | " btcpayserver " = > Some ( " btcpay " ) ,
" mempool " | " mempool-web " | " mempool-frontend " = > Some ( " mempool " ) ,
2026-04-01 18:22:30 +01:00
" fedimint " | " fedimint-gateway " = > Some ( " fedimint " ) ,
" filebrowser " = > Some ( " filebrowser " ) ,
2026-02-17 15:03:34 +00:00
_ = > None ,
}
}
/// V3 onion addresses are 56 base32 chars + ".onion". Placeholders like "btcpay.onion" are not real.
fn is_real_onion_address ( s : & str ) -> bool {
s . ends_with ( " .onion " ) & & s . len ( ) > = 60 & & s . len ( ) < = 70
}
/// Read real .onion address from Tor hidden service hostname file.
/// Service name "archipelago" is for the main web UI (nginx port 80).
/// Uses TOR_DATA_DIR env var if set, else /var/lib/archipelago/tor.
2026-03-21 01:21:08 +00:00
pub async fn read_tor_address ( app_id : & str ) -> Option < String > {
2026-02-17 15:03:34 +00:00
let service = tor_service_name ( app_id ) ? ;
chore(ci): rustfmt + clippy clean-up to unblock the Rust CI job
The .github/workflows/ci.yml Rust job runs cargo fmt --check, clippy
with -D warnings, and tests. All three were failing. This commit:
- Applies rustfmt across the tree (the bulk of the diff — untouched
since the last toolchain bump, so a wide sweep was unavoidable).
- Fixes the correctness-level clippy errors:
container/bitcoin_simulator.rs wildcard-in-or-pattern
container/manifest.rs from_str rename to parse (reserved name)
container/podman_client.rs .get(0) -> .first()
container/runtime.rs manual += collapse
archipelago/src/constants.rs doc-comment → module-doc
api/rpc/package/install.rs stray /// comment above a non-item
container/docker_packages.rs redundant field init
streaming/advertisement.rs missing Metric import in tests
tests/orchestration_tests.rs `vec!` in non-Vec contexts
mesh/listener/dispatch.rs unused store_plain_message import
api/rpc/tor/mod.rs and mesh/steganography.rs: push-after-new → vec!
- Quiets wide legacy surfaces with crate-level allows in main.rs for
stylistic lints (too_many_arguments, type_complexity, doc indent,
enum variant prefix, wildcard-in-or, assertions-on-constants,
drop_non_drop, unused_io_amount, ptr_arg) — these fired in dozens
of places with no correctness payoff and have been churning every
toolchain bump.
- Tags intentional-dead-code helpers: wallet/ and streaming/ modules
are WIP, mesh::send_chunked_payload and DM_V1_MARKER are kept for
rollback compatibility, vpn::get_nostr_vpn_status is surface-area
for a not-yet-landed RPC.
cargo fmt --check, cargo clippy --all-targets --all-features
-- -D warnings, and cargo test --all-features now all pass locally.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-04-18 17:23:46 -04:00
let base =
std ::env ::var ( " TOR_DATA_DIR " ) . unwrap_or_else ( | _ | " /var/lib/archipelago/tor " . to_string ( ) ) ;
2026-03-13 01:52:50 +00:00
// Try readable hostname copy first (when system Tor owns hidden_service dirs)
let hostnames_path = std ::path ::Path ::new ( & base )
. parent ( )
. unwrap_or ( std ::path ::Path ::new ( " /var/lib/archipelago " ) )
. join ( " tor-hostnames " )
. join ( service ) ;
2026-03-21 01:21:08 +00:00
if let Some ( addr ) = tokio ::fs ::read_to_string ( & hostnames_path )
. await
2026-03-13 01:52:50 +00:00
. ok ( )
. map ( | s | s . trim ( ) . to_string ( ) )
. filter ( | s | s . ends_with ( " .onion " ) & & ! s . is_empty ( ) )
{
return Some ( addr ) ;
}
// Fall back to hidden_service directory
2026-02-17 15:03:34 +00:00
let path = std ::path ::Path ::new ( & base )
. join ( format! ( " hidden_service_ {} " , service ) )
. join ( " hostname " ) ;
2026-03-21 01:21:08 +00:00
tokio ::fs ::read_to_string ( & path )
. await
2026-02-17 15:03:34 +00:00
. ok ( )
. map ( | s | s . trim ( ) . to_string ( ) )
. filter ( | s | s . ends_with ( " .onion " ) & & ! s . is_empty ( ) )
}
2026-01-27 23:21:26 +00:00
fn extract_lan_address ( ports : & [ String ] ) -> Option < String > {
for port_str in ports {
// Parse port strings like "0.0.0.0:18443->18443/tcp" or "0.0.0.0:18443-18444->18443-18444/tcp"
if let Some ( public_part ) = port_str . split ( " -> " ) . next ( ) {
if let Some ( port_part ) = public_part . split ( ':' ) . nth ( 1 ) {
// Extract just the first port if it's a range (e.g., "18443-18444" -> "18443")
let single_port = port_part . split ( '-' ) . next ( ) . unwrap_or ( port_part ) ;
return Some ( format! ( " http://localhost: {} " , single_port ) ) ;
}
}
}
None
}
2026-05-19 21:45:17 -04:00
async fn netbird_configured_launch_url ( ) -> Option < String > {
let env = tokio ::fs ::read_to_string ( " /var/lib/archipelago/netbird/dashboard.env " )
. await
. ok ( ) ? ;
env . lines ( )
. find_map ( | line | line . strip_prefix ( " NETBIRD_MGMT_API_ENDPOINT= " ) )
. map ( str ::trim )
. filter ( | s | ! s . is_empty ( ) )
. map ( ToOwned ::to_owned )
. or_else ( | | PodmanClient ::lan_address_for ( " netbird " ) )
}
2026-05-13 15:09:22 -04:00
async fn reachable_lan_address ( app_id : & str , candidate : Option < String > ) -> Option < String > {
let url = candidate ? ;
if ! requires_reachable_launch ( app_id ) {
return Some ( url ) ;
}
let Some ( port ) = url . rsplit ( ':' ) . next ( ) . and_then ( | p | p . parse ::< u16 > ( ) . ok ( ) ) else {
return None ;
} ;
match tokio ::time ::timeout (
std ::time ::Duration ::from_secs ( 2 ) ,
tokio ::net ::TcpStream ::connect ( ( " 127.0.0.1 " , port ) ) ,
)
. await
{
Ok ( Ok ( _ ) ) = > Some ( url ) ,
_ = > {
debug! ( app_id = % app_id , port , " suppressing unreachable launch URL " ) ;
None
}
}
}
fn requires_reachable_launch ( app_id : & str ) -> bool {
matches! (
app_id ,
" botfights "
| " btcpay-server "
| " fedimint "
| " filebrowser "
| " grafana "
| " homeassistant "
| " home-assistant "
| " jellyfin "
| " mempool "
| " nginx-proxy-manager "
| " uptime-kuma "
| " gitea "
| " nextcloud "
| " portainer "
| " tailscale "
| " immich "
| " searxng "
2026-05-19 20:11:22 -04:00
| " saleor "
2026-05-13 15:09:22 -04:00
)
}
2026-05-05 11:29:18 -04:00
fn companion_lan_address ( app_id : & str ) -> Option < String > {
match app_id {
" bitcoin " | " bitcoin-knots " | " bitcoin-core " = > Some ( " http://localhost:8334 " . to_string ( ) ) ,
" electrumx " | " mempool-electrs " | " electrs " = > Some ( " http://localhost:50002 " . to_string ( ) ) ,
_ = > None ,
}
}
2026-05-17 17:30:04 -04:00
fn uses_allocated_launch_port ( app_id : & str ) -> bool {
matches! (
app_id ,
" filebrowser " | " nextcloud " | " nginx-proxy-manager " | " vaultwarden "
)
}
2026-01-27 23:21:26 +00:00
fn convert_state ( container_state : & ContainerState ) -> ( PackageState , ServiceStatus ) {
match container_state {
ContainerState ::Running = > ( PackageState ::Running , ServiceStatus ::Running ) ,
2026-05-13 15:09:22 -04:00
ContainerState ::Stopping = > ( PackageState ::Stopping , ServiceStatus ::Stopped ) ,
security+feat: v1.3.0 — pentest remediation, container reliability, UI overhaul
Security (33 pentest findings addressed):
- CRITICAL: backend binds 127.0.0.1, path traversal in tor.rs/dwn fixed
- HIGH: federation requires signatures, XSS login redirect, RBAC viewer restricted
- HIGH: tar slip prevention, S3 SSRF validation, backup ID validation
- MEDIUM: remember-me random secret, TOTP session rotation, password re-auth
- LOW: CSP unsafe-inline removed, CORS dev-only, onion/webhook validation
Container reliability:
- Memory limits on all 37 containers (OOM prevention)
- Exited vs stopped state distinction with health-aware status badges
- Crash recovery coordination (no more restart cascade)
- User-stopped tracking survives reboots
- Tiered boot recovery (databases → core → services → apps)
UI:
- Wallet TransactionsModal, health-aware app status badges
- Restart button on containers, exited/crashed red state
- Mesh view overhaul, glass button updates, BaseModal/ToggleSwitch
- Apps sticky header removed, dev faucet, mutable mock wallet
Infrastructure:
- LND REST port 8080 exposed over Tor (LND Connect fix)
- Nginx cookie_session fix, deploy script Tor config updated
- Dev environment: podman auto-start, boot mode simulation
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-19 12:44:31 +00:00
ContainerState ::Stopped = > ( PackageState ::Stopped , ServiceStatus ::Stopped ) ,
ContainerState ::Exited = > ( PackageState ::Exited , ServiceStatus ::Stopped ) ,
fix: container state mapping + marketplace install aliases
- Created containers now show as "stopped" not "starting" (fixes
ollama/tailscale perpetual "starting" state)
- Comprehensive INSTALLED_ALIASES map: fedimint, electrumx, grafana,
jellyfin, vaultwarden, searxng, homeassistant, photoprism, lnd,
filebrowser, tailscale, ollama — prevents marketplace showing
"Install" for already-installed containers
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-18 15:18:43 +00:00
ContainerState ::Created = > ( PackageState ::Stopped , ServiceStatus ::Stopped ) ,
2026-01-27 23:21:26 +00:00
ContainerState ::Paused = > ( PackageState ::Stopped , ServiceStatus ::Stopped ) ,
ContainerState ::Unknown ( _ ) = > ( PackageState ::Stopped , ServiceStatus ::Stopped ) ,
}
}
fn package_state_str ( state : & PackageState ) -> & str {
match state {
PackageState ::Installing = > " installing " ,
PackageState ::Installed = > " installed " ,
PackageState ::Stopping = > " stopping " ,
PackageState ::Stopped = > " stopped " ,
security+feat: v1.3.0 — pentest remediation, container reliability, UI overhaul
Security (33 pentest findings addressed):
- CRITICAL: backend binds 127.0.0.1, path traversal in tor.rs/dwn fixed
- HIGH: federation requires signatures, XSS login redirect, RBAC viewer restricted
- HIGH: tar slip prevention, S3 SSRF validation, backup ID validation
- MEDIUM: remember-me random secret, TOTP session rotation, password re-auth
- LOW: CSP unsafe-inline removed, CORS dev-only, onion/webhook validation
Container reliability:
- Memory limits on all 37 containers (OOM prevention)
- Exited vs stopped state distinction with health-aware status badges
- Crash recovery coordination (no more restart cascade)
- User-stopped tracking survives reboots
- Tiered boot recovery (databases → core → services → apps)
UI:
- Wallet TransactionsModal, health-aware app status badges
- Restart button on containers, exited/crashed red state
- Mesh view overhaul, glass button updates, BaseModal/ToggleSwitch
- Apps sticky header removed, dev faucet, mutable mock wallet
Infrastructure:
- LND REST port 8080 exposed over Tor (LND Connect fix)
- Nginx cookie_session fix, deploy script Tor config updated
- Dev environment: podman auto-start, boot mode simulation
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-19 12:44:31 +00:00
PackageState ::Exited = > " exited " ,
2026-01-27 23:21:26 +00:00
PackageState ::Starting = > " starting " ,
PackageState ::Running = > " running " ,
PackageState ::Restarting = > " restarting " ,
PackageState ::CreatingBackup = > " creating-backup " ,
PackageState ::RestoringBackup = > " restoring-backup " ,
PackageState ::Removing = > " removing " ,
PackageState ::BackingUp = > " backing-up " ,
2026-04-09 11:47:35 +02:00
PackageState ::Updating = > " updating " ,
2026-01-27 23:21:26 +00:00
}
}