mirror of
https://github.com/block/buzz.git
synced 2026-08-18 06:50:31 +02:00
Add an absent-by-default compile-time policy that restricts locked desktop builds to the compiled relay origin. Enforce it at native connection and Tauri request boundaries, remove saved external communities before app mounting, and hide relay selection controls. Public builds remain unrestricted. Co-authored-by: Jordan Mecom <jm@squareup.com> Signed-off-by: Jordan Mecom <jm@squareup.com>
170 lines
7.8 KiB
Rust
170 lines
7.8 KiB
Rust
// Shared schema, included from the same source the runtime command parses with,
|
|
// so the build-time validation below and the runtime parse cannot drift.
|
|
include!("src/commands/reconnect_hook_config.rs");
|
|
|
|
use base64::Engine as _;
|
|
use url::Url;
|
|
|
|
fn validate_relay_origin(raw: &str) {
|
|
let parsed = Url::parse(raw)
|
|
.unwrap_or_else(|error| panic!("BUZZ_RELAY_URL must be a valid URL: {error}"));
|
|
if !matches!(parsed.scheme(), "ws" | "wss")
|
|
|| parsed.host_str().is_none()
|
|
|| !parsed.username().is_empty()
|
|
|| parsed.password().is_some()
|
|
|| !matches!(parsed.path(), "" | "/")
|
|
|| parsed.query().is_some()
|
|
|| parsed.fragment().is_some()
|
|
{
|
|
panic!("BUZZ_RELAY_URL must be a ws:// or wss:// origin without credentials, path, query, or fragment");
|
|
}
|
|
}
|
|
|
|
fn main() {
|
|
println!("cargo:rerun-if-env-changed=BUZZ_RELAY_URL");
|
|
println!("cargo:rerun-if-env-changed=BUZZ_RELAY_HTTP");
|
|
println!("cargo:rerun-if-env-changed=BUZZ_UPDATER_PUBLIC_KEY");
|
|
println!("cargo:rerun-if-env-changed=BUZZ_UPDATER_ENDPOINT");
|
|
println!("cargo:rerun-if-env-changed=BUZZ_BUILD_BUZZ_AGENT_PROVIDER");
|
|
println!("cargo:rerun-if-env-changed=BUZZ_BUILD_BUZZ_AGENT_MODEL");
|
|
println!("cargo:rerun-if-env-changed=BUZZ_BUILD_AGENT_ENV");
|
|
println!("cargo:rerun-if-env-changed=BUZZ_BUILD_RELAY_RECONNECT_CMD");
|
|
println!("cargo:rerun-if-env-changed=BUZZ_BUILD_OBSERVER_ARCHIVE_DEFAULT");
|
|
println!("cargo:rerun-if-env-changed=BUZZ_BUILD_AGENT_METRIC_ARCHIVE_DEFAULT");
|
|
println!("cargo:rerun-if-env-changed=BUZZ_BUILD_AUTO_CONNECT_DEFAULT_RELAY");
|
|
println!("cargo:rerun-if-env-changed=BUZZ_BUILD_LOCK_TO_DEFAULT_RELAY");
|
|
println!("cargo:rustc-check-cfg=cfg(buzz_updater_enabled)");
|
|
|
|
let build_relay_url = std::env::var("BUZZ_RELAY_URL")
|
|
.ok()
|
|
.map(|value| value.trim().to_string())
|
|
.filter(|value| !value.is_empty());
|
|
if let Some(relay_url) = build_relay_url.as_deref() {
|
|
println!("cargo:rustc-env=BUZZ_DESKTOP_BUILD_RELAY_URL={relay_url}");
|
|
}
|
|
|
|
if let Ok(relay_http) = std::env::var("BUZZ_RELAY_HTTP") {
|
|
println!("cargo:rustc-env=BUZZ_DESKTOP_BUILD_RELAY_HTTP={relay_http}");
|
|
}
|
|
|
|
if let Ok(provider) = std::env::var("BUZZ_BUILD_BUZZ_AGENT_PROVIDER") {
|
|
println!("cargo:rustc-env=BUZZ_DESKTOP_BUILD_BUZZ_AGENT_PROVIDER={provider}");
|
|
}
|
|
|
|
if let Ok(model) = std::env::var("BUZZ_BUILD_BUZZ_AGENT_MODEL") {
|
|
println!("cargo:rustc-env=BUZZ_DESKTOP_BUILD_BUZZ_AGENT_MODEL={model}");
|
|
}
|
|
|
|
// Generic KEY=VALUE pairs to inject into every spawned agent process.
|
|
// Newline-delimited; each line must be non-empty and contain exactly one
|
|
// `=` separator with a non-empty key. OSS builds leave this unset.
|
|
// The validated value is base64-encoded before emitting so the single-line
|
|
// Cargo build-script output carries all pairs (Cargo output is line-oriented;
|
|
// a raw multiline value would be silently truncated to the first line).
|
|
if let Ok(raw) = std::env::var("BUZZ_BUILD_AGENT_ENV") {
|
|
for (line_no, line) in raw.lines().enumerate() {
|
|
let line = line.trim();
|
|
if line.is_empty() {
|
|
continue;
|
|
}
|
|
let eq = line.find('=').unwrap_or_else(|| {
|
|
panic!(
|
|
"BUZZ_BUILD_AGENT_ENV line {}: missing '=' separator in {:?}",
|
|
line_no + 1,
|
|
line
|
|
)
|
|
});
|
|
let key = &line[..eq];
|
|
if key.is_empty() {
|
|
panic!(
|
|
"BUZZ_BUILD_AGENT_ENV line {}: key must not be empty in {:?}",
|
|
line_no + 1,
|
|
line
|
|
);
|
|
}
|
|
}
|
|
let encoded = base64::engine::general_purpose::STANDARD.encode(raw.as_bytes());
|
|
println!("cargo:rustc-env=BUZZ_DESKTOP_BUILD_AGENT_ENV={encoded}");
|
|
}
|
|
|
|
if let Ok(val) = std::env::var("BUZZ_BUILD_RELAY_RECONNECT_CMD") {
|
|
let parsed: serde_json::Value = serde_json::from_str(&val)
|
|
.unwrap_or_else(|e| panic!("BUZZ_BUILD_RELAY_RECONNECT_CMD is not valid JSON: {e}"));
|
|
serde_json::from_value::<ReconnectHookConfig>(parsed).unwrap_or_else(|e| {
|
|
panic!("BUZZ_BUILD_RELAY_RECONNECT_CMD doesn't match ReconnectHookConfig: {e}")
|
|
});
|
|
println!("cargo:rustc-env=BUZZ_DESKTOP_BUILD_RELAY_RECONNECT_CMD={val}");
|
|
}
|
|
|
|
// Presence-only flag: when set (any non-empty value), observer-feed archive
|
|
// defaults to ON for the current identity on first run. OSS builds leave
|
|
// this unset → default OFF. No JSON validation needed — the command only
|
|
// checks `.is_some()`.
|
|
if std::env::var("BUZZ_BUILD_OBSERVER_ARCHIVE_DEFAULT").is_ok() {
|
|
println!("cargo:rustc-env=BUZZ_DESKTOP_BUILD_OBSERVER_ARCHIVE_DEFAULT=1");
|
|
}
|
|
|
|
// Presence-only flag: when set (any non-empty value), agent-turn-metric
|
|
// archive defaults to ON for the current identity on first run. OSS builds
|
|
// leave this unset → default OFF.
|
|
if std::env::var("BUZZ_BUILD_AGENT_METRIC_ARCHIVE_DEFAULT").is_ok() {
|
|
println!("cargo:rustc-env=BUZZ_DESKTOP_BUILD_AGENT_METRIC_ARCHIVE_DEFAULT=1");
|
|
}
|
|
|
|
// Presence-only release capability: internal desktop builds opt into
|
|
// auto-connecting their configured default relay on first run. OSS builds
|
|
// leave this unset and retain explicit community selection.
|
|
if std::env::var("BUZZ_BUILD_AUTO_CONNECT_DEFAULT_RELAY").is_ok() {
|
|
println!("cargo:rustc-env=BUZZ_DESKTOP_BUILD_AUTO_CONNECT_DEFAULT_RELAY=1");
|
|
}
|
|
|
|
// Presence-only release policy. Locked builds may connect only to their
|
|
// immutable compiled default relay. OSS builds leave this unset and retain
|
|
// multi-community relay selection.
|
|
if std::env::var("BUZZ_BUILD_LOCK_TO_DEFAULT_RELAY").is_ok() {
|
|
let relay_url = build_relay_url.as_deref().unwrap_or_else(|| {
|
|
panic!("BUZZ_BUILD_LOCK_TO_DEFAULT_RELAY requires a non-empty BUZZ_RELAY_URL")
|
|
});
|
|
validate_relay_origin(relay_url);
|
|
println!("cargo:rustc-env=BUZZ_DESKTOP_BUILD_LOCK_TO_DEFAULT_RELAY=1");
|
|
}
|
|
|
|
let updater_public_key = std::env::var("BUZZ_UPDATER_PUBLIC_KEY")
|
|
.ok()
|
|
.map(|value| value.trim().to_string())
|
|
.filter(|value| !value.is_empty());
|
|
let updater_endpoint = std::env::var("BUZZ_UPDATER_ENDPOINT")
|
|
.ok()
|
|
.map(|value| value.trim().to_string())
|
|
.filter(|value| !value.is_empty());
|
|
|
|
if updater_public_key.is_some() && updater_endpoint.is_some() {
|
|
println!("cargo:rustc-cfg=buzz_updater_enabled");
|
|
}
|
|
|
|
// Cargo test executables get no embedded Windows manifest (tauri_build
|
|
// attaches one to bin targets only), so the loader binds comctl32 v5, which
|
|
// lacks TaskDialogIndirect (statically imported via tauri-plugin-dialog/rfd)
|
|
// and debug test exes die at load with STATUS_ENTRYPOINT_NOT_FOUND. Declaring
|
|
// the Common Controls v6 dependency makes link.exe emit a side-by-side
|
|
// <exe>.manifest that the loader honors for manifest-less executables;
|
|
// binaries with an embedded manifest (the real app) ignore it.
|
|
if std::env::var("CARGO_CFG_TARGET_OS").as_deref() == Ok("windows")
|
|
&& std::env::var("CARGO_CFG_TARGET_ENV").as_deref() == Ok("msvc")
|
|
{
|
|
println!(
|
|
"cargo:rustc-link-arg=/MANIFESTDEPENDENCY:type='win32' name='Microsoft.Windows.Common-Controls' version='6.0.0.0' processorArchitecture='*' publicKeyToken='6595b64144ccf1df' language='*'"
|
|
);
|
|
}
|
|
|
|
tauri_build::try_build(
|
|
tauri_build::Attributes::new().plugin(
|
|
"websocket",
|
|
tauri_build::InlinedPlugin::new()
|
|
.commands(&["connect", "send", "disconnect", "disconnect_all"])
|
|
.default_permission(tauri_build::DefaultPermissionRule::AllowAllCommands),
|
|
),
|
|
)
|
|
.expect("failed to build Tauri application");
|
|
}
|