feat(relay): mesh config seam — BUZZ_MESH / BUZZ_MESH_BIND_ADDR env parsing

Wires buzz-relay-mesh into buzz-relay: workspace + crate dependency, and
Config.mesh (buzz_relay_mesh::MeshConfig) resolved from env.

- BUZZ_MESH: on by default; 'off'/'false'/'0' is the incident kill
  switch — the relay must behave exactly like a single-instance deploy.
- BUZZ_MESH_BIND_ADDR: UDP bind for the iroh endpoint, default
  0.0.0.0:3478 (excluded from istio sidecar capture in k8s).
- registry_refresh fixed at 15s (ready-registry heartbeat; expiry 3x).

No behavior change yet: nothing constructs a mesh from this config —
AppState handle, /_mesh mount, and startup/drain wiring follow.

Co-authored-by: Tyler Longwell <tlongwell@block.xyz>
Signed-off-by: Tyler Longwell <tlongwell@block.xyz>
This commit is contained in:
npub1qyvc0c5kl4gqv2fd97fsk46tu378sqgy35vc83rvgfwne90sel7s0ed67d
2026-07-08 10:34:45 -04:00
co-authored by Tyler Longwell
parent 446a5a0f46
commit 9a24af8aa9
4 changed files with 30 additions and 0 deletions
Generated
+1
View File
@@ -1049,6 +1049,7 @@ dependencies = [
"buzz-db",
"buzz-media",
"buzz-pubsub",
"buzz-relay-mesh",
"buzz-sdk",
"buzz-search",
"buzz-workflow",
+1
View File
@@ -130,6 +130,7 @@ buzz-workflow = { path = "crates/buzz-workflow" }
buzz-media = { path = "crates/buzz-media" }
buzz-sdk = { path = "crates/buzz-sdk" }
buzz-ws-client = { path = "crates/buzz-ws-client" }
buzz-relay-mesh = { path = "crates/buzz-relay-mesh" }
# CI profile — builds the relay for desktop e2e. Dependencies keep full
# release optimization (warm from main's cache; they carry the runtime hot
+1
View File
@@ -23,6 +23,7 @@ buzz-auth = { workspace = true }
buzz-pubsub = { workspace = true }
buzz-audit = { workspace = true }
buzz-search = { workspace = true }
buzz-relay-mesh = { workspace = true }
axum = { workspace = true }
tokio = { workspace = true }
# `io` (ReaderStream) is needed to stream git subprocess stdout straight into
+27
View File
@@ -93,6 +93,13 @@ pub struct Config {
/// service lands.
pub huddle_audio_available: bool,
/// Inter-relay mesh configuration (`BUZZ_MESH`, `BUZZ_MESH_BIND_ADDR`).
/// `mesh.enabled=false` (`BUZZ_MESH=off`) is the incident kill switch: the
/// relay must behave exactly like a single-instance deployment. Even when
/// enabled, the mesh only forms once peer registry records exist, so
/// N=1 deployments carry no mesh at runtime.
pub mesh: buzz_relay_mesh::MeshConfig,
/// Optional hex-encoded pubkey of the relay owner.
/// When set, this pubkey is automatically bootstrapped into `relay_members`
/// with the `owner` role on first startup.
@@ -236,6 +243,25 @@ impl Config {
.map(|v| !(v == "false" || v == "0"))
.unwrap_or(true);
// Mesh kill switch: default enabled — the mesh is inert until peer
// registry records exist, so N=1 deployments pay nothing. `off`
// hard-disables for incidents (single-instance behavior guaranteed).
let mesh_enabled = std::env::var("BUZZ_MESH")
.map(|v| !(v.eq_ignore_ascii_case("off") || v == "false" || v == "0"))
.unwrap_or(true);
let mesh_bind_addr = std::env::var("BUZZ_MESH_BIND_ADDR")
.map(|raw| {
raw.parse::<SocketAddr>().map_err(|e| {
ConfigError::InvalidValue(format!("invalid BUZZ_MESH_BIND_ADDR: {e}"))
})
})
.unwrap_or_else(|_| Ok("0.0.0.0:3478".parse().expect("static default parses")))?;
let mesh = buzz_relay_mesh::MeshConfig {
enabled: mesh_enabled,
bind_addr: mesh_bind_addr,
registry_refresh: std::time::Duration::from_secs(15),
};
let allow_nip_oa_auth = std::env::var("BUZZ_ALLOW_NIP_OA_AUTH")
.map(|v| v == "true" || v == "1")
.unwrap_or(false);
@@ -427,6 +453,7 @@ impl Config {
pubkey_allowlist_enabled,
require_relay_membership,
huddle_audio_available,
mesh,
relay_owner_pubkey,
allow_nip_oa_auth,
media,