From 6507f1bad96ce1d00c282cc845916f968650bbf8 Mon Sep 17 00:00:00 2001 From: LoopX Agent <337587101+loopx-agent@users.noreply.github.com> Date: Sat, 17 Oct 2026 17:20:38 +0800 Subject: [PATCH 1/2] test(desktop): qualify supervisor against an isolated installed Core Signed-off-by: LoopX Agent <337587101+loopx-agent@users.noreply.github.com> --- apps/desktop/loopx-control-plane/README.md | 28 ++++ .../src-tauri/src/services.rs | 4 + .../src/services_real_runtime_tests.rs | 122 ++++++++++++++++++ 3 files changed, 154 insertions(+) create mode 100644 apps/desktop/loopx-control-plane/src-tauri/src/services_real_runtime_tests.rs diff --git a/apps/desktop/loopx-control-plane/README.md b/apps/desktop/loopx-control-plane/README.md index cb34a8b457..f047f388aa 100644 --- a/apps/desktop/loopx-control-plane/README.md +++ b/apps/desktop/loopx-control-plane/README.md @@ -350,6 +350,34 @@ cd .. npm run build ``` +To qualify the native supervisor against an actual installed Core, first build +the runtime bundle as above, then run from `src-tauri`: + +```sh +qa_root="$(mktemp -d)" +mkdir "$qa_root/state" +printf '%s\n' '{"goals":[]}' > "$qa_root/state/registry.global.json" +( + set -e + export LOOPX_REGISTRY="$qa_root/state/registry.global.json" + export LOOPX_RUNTIME_ROOT="$qa_root/state" + export LOOPX_TEST_PRIVATE_RUNTIME="$qa_root/runtime" + export LOOPX_TEST_BUNDLE="$PWD/../runtime" + cargo test --lib real_private_installer_keeps_the_default_cli_owner -- --ignored --nocapture + cargo test --lib real_private_runtime_serves_and_rejects_stale_identity -- --ignored --nocapture +) +``` + +This installs only in the disposable root. The second test uses an explicit +local launch pin to route the production supervisor's two services to its own +fresh empty registry and data directory. It checks both artifact identities, +serves the packaged Chat document, reads zero Goals/Sessions, stops and reopens +the services, and rejects +a stale expected identity without leaving owned listeners. It does not launch +the installed App, run a model, or qualify automatic runtime selection, native +window reopening, signed replacement or rendered UI. The incognito WebKit +regression above covers its separate navigation failure boundary. + On macOS, also qualify a released artifact using the opt-in checks below (run from `src-tauri`, replacing the paths with downloaded release artifacts). Keep the updater archive's `.sig` file beside it: diff --git a/apps/desktop/loopx-control-plane/src-tauri/src/services.rs b/apps/desktop/loopx-control-plane/src-tauri/src/services.rs index ee681c19d7..ce679ed1ef 100644 --- a/apps/desktop/loopx-control-plane/src-tauri/src/services.rs +++ b/apps/desktop/loopx-control-plane/src-tauri/src/services.rs @@ -1625,3 +1625,7 @@ mod tests { #[cfg(test)] #[path = "services_tests.rs"] mod supervisor_tests; + +#[cfg(all(test, unix))] +#[path = "services_real_runtime_tests.rs"] +mod real_runtime_tests; diff --git a/apps/desktop/loopx-control-plane/src-tauri/src/services_real_runtime_tests.rs b/apps/desktop/loopx-control-plane/src-tauri/src/services_real_runtime_tests.rs new file mode 100644 index 0000000000..63406154d1 --- /dev/null +++ b/apps/desktop/loopx-control-plane/src-tauri/src/services_real_runtime_tests.rs @@ -0,0 +1,122 @@ +//! Opt-in production supervisor + installed Core. Never use an active registry. +use super::*; +use std::os::unix::fs::PermissionsExt; + +fn response_body(port: u16, path: &str) -> String { + let mut stream = TcpStream::connect(("127.0.0.1", port)).unwrap(); + stream + .set_read_timeout(Some(Duration::from_secs(5))) + .unwrap(); + write!( + stream, + "GET {path} HTTP/1.1\r\nHost: 127.0.0.1:{port}\r\nConnection: close\r\n\r\n" + ) + .unwrap(); + let mut raw = String::new(); + stream + .take(MAX_PROBE_RESPONSE_BYTES + 1) + .read_to_string(&mut raw) + .unwrap(); + assert!(raw.len() as u64 <= MAX_PROBE_RESPONSE_BYTES); + let (headers, body) = raw.split_once("\r\n\r\n").unwrap(); + assert!(headers.starts_with("HTTP/1.0 200 ") || headers.starts_with("HTTP/1.1 200 ")); + body.to_owned() +} + +fn assert_stopped(endpoints: ServiceEndpoints) { + for kind in SERVICE_KINDS { + assert_eq!( + probe_on_port(kind, endpoints.port(kind), None), + Probe::Unavailable + ); + } +} + +#[test] +#[ignore = "requires a disposable Core install and empty isolated registry; see Desktop README"] +fn real_private_runtime_serves_and_rejects_stale_identity() { + let root = PathBuf::from(env::var("LOOPX_TEST_PRIVATE_RUNTIME").unwrap()); + // A caller's empty registry can still share a runtime with bound private + // conversations. Own a fresh data root rather than trusting that shortcut. + let data = tempfile::tempdir().unwrap(); + let state = fs::canonicalize(data.path()).unwrap(); + let registry = state.join("registry.global.json"); + fs::write(®istry, b"{\"goals\":[]}").unwrap(); + let executable = fs::canonicalize(root.join("bin/loopx")).unwrap(); + let identity = runtime_identity_for_executable(executable.to_str().unwrap()).unwrap(); + + // The production service commands use --global-registry. An explicit local + // launch pin supplies their real CLI route, not a second identity/provider. + // Use shell quoting for paths, including spaces, quotes and dollar signs. + let quoted = |path: &Path| format!("'{}'", path.to_str().unwrap().replace('\'', "'\"'\"'")); + let wrapper = tempfile::tempdir().unwrap(); + let pin = wrapper.path().join("isolated-core"); + fs::write( + &pin, + format!( + "#!/bin/sh\nexec {} --registry {} --runtime-root {} \"$@\"\n", + quoted(&executable), + quoted(®istry), + quoted(&state) + ), + ) + .unwrap(); + fs::set_permissions(&pin, fs::Permissions::from_mode(0o700)).unwrap(); + let runtime = SelectedRuntime { + executable: pin.to_string_lossy().into_owned(), + identity: Some(identity.clone()), + }; + let mut origins = Vec::new(); + for _ in 0..2 { + let endpoints = ServiceEndpoints::allocate(true).unwrap(); + let mut services = ServiceSet::start(&runtime, &endpoints, |_| {}).unwrap(); + for kind in SERVICE_KINDS { + assert_eq!( + probe_on_port(kind, endpoints.port(kind), Some(&identity)), + Probe::Matching + ); + } + let status: serde_json::Value = serde_json::from_str(&response_body( + endpoints.port(ServiceKind::Status), + "/status.json", + )) + .unwrap(); + assert_eq!(status["goal_count"], 0); + assert_eq!( + status["registry"].as_str(), + registry.to_str(), + "the real backend must use only this disposable registry" + ); + let sessions: serde_json::Value = serde_json::from_str(&response_body( + endpoints.port(ServiceKind::Chat), + "/api/chat/sessions", + )) + .unwrap(); + assert!(sessions["sessions"].as_array().is_some_and(Vec::is_empty)); + assert!(response_body(endpoints.port(ServiceKind::Chat), "/chat/") + .to_ascii_lowercase() + .contains("")); + origins.push(endpoints.workspace_origin()); + services.stop(); + assert_stopped(endpoints); + } + + // The production owner must reject an actual backend from the wrong frozen + // artifact and clean up both children, including a successful peer start. + let mut mismatched = identity.clone(); + mismatched["source_revision"] = serde_json::json!("0000000000000000000000000000000000000000"); + let invalid = SelectedRuntime { + executable: runtime.executable.clone(), + identity: Some(mismatched), + }; + let endpoints = ServiceEndpoints::allocate(true).unwrap(); + let error = ServiceSet::start(&invalid, &endpoints, |_| {}) + .err() + .expect("a stale artifact must fail readiness"); + assert!(error.to_string().contains("unexpected listener")); + assert_stopped(endpoints); + println!( + "{}", + serde_json::json!({"private_service_reopens":origins.len(), "workspace_origins":origins, "runtime_identity":identity, "goals":0, "sessions":0, "stale_identity_rejected":true, "owned_children_stopped":true}) + ); +} From a1303b8197a36e0f26288b7e8833b7df8ba8d9be Mon Sep 17 00:00:00 2001 From: LoopX Agent <337587101+loopx-agent@users.noreply.github.com> Date: Sat, 17 Oct 2026 18:15:36 +0800 Subject: [PATCH 2/2] test(desktop): require telemetry opt-out for synthetic Core qualification Signed-off-by: LoopX Agent <337587101+loopx-agent@users.noreply.github.com> --- apps/desktop/loopx-control-plane/README.md | 8 +++++++- .../loopx-control-plane/src-tauri/src/bundled_runtime.rs | 5 +++++ .../src-tauri/src/services_real_runtime_tests.rs | 5 +++++ 3 files changed, 17 insertions(+), 1 deletion(-) diff --git a/apps/desktop/loopx-control-plane/README.md b/apps/desktop/loopx-control-plane/README.md index f047f388aa..33ddd47d1b 100644 --- a/apps/desktop/loopx-control-plane/README.md +++ b/apps/desktop/loopx-control-plane/README.md @@ -351,7 +351,7 @@ npm run build ``` To qualify the native supervisor against an actual installed Core, first build -the runtime bundle as above, then run from `src-tauri`: +the runtime bundle as above with `LOOPX_USAGE_PING=0`, then run from `src-tauri`: ```sh qa_root="$(mktemp -d)" @@ -359,6 +359,7 @@ mkdir "$qa_root/state" printf '%s\n' '{"goals":[]}' > "$qa_root/state/registry.global.json" ( set -e + export LOOPX_USAGE_PING=0 export LOOPX_REGISTRY="$qa_root/state/registry.global.json" export LOOPX_RUNTIME_ROOT="$qa_root/state" export LOOPX_TEST_PRIVATE_RUNTIME="$qa_root/runtime" @@ -368,6 +369,11 @@ printf '%s\n' '{"goals":[]}' > "$qa_root/state/registry.global.json" ) ``` +Both opt-in tests require the telemetry opt-out before invoking Core. A +disposable registry does not isolate machine-wide usage reporting; this +synthetic run must not contribute adoption or installation telemetry. The +opt-out applies only to this test invocation and leaves user consent unchanged. + This installs only in the disposable root. The second test uses an explicit local launch pin to route the production supervisor's two services to its own fresh empty registry and data directory. It checks both artifact identities, diff --git a/apps/desktop/loopx-control-plane/src-tauri/src/bundled_runtime.rs b/apps/desktop/loopx-control-plane/src-tauri/src/bundled_runtime.rs index 04452f2847..858eb610e7 100644 --- a/apps/desktop/loopx-control-plane/src-tauri/src/bundled_runtime.rs +++ b/apps/desktop/loopx-control-plane/src-tauri/src/bundled_runtime.rs @@ -367,6 +367,11 @@ mod tests { #[test] #[ignore = "requires an isolated private installer root and built App bundle"] fn real_private_installer_keeps_the_default_cli_owner() { + assert_eq!( + std::env::var("LOOPX_USAGE_PING").as_deref(), + Ok("0"), + "synthetic Core qualification requires LOOPX_USAGE_PING=0" + ); let bundle = std::path::PathBuf::from(std::env::var("LOOPX_TEST_BUNDLE").unwrap()); let root = std::path::PathBuf::from(std::env::var("LOOPX_TEST_PRIVATE_RUNTIME").unwrap()); for key in ["LOOPX_REGISTRY", "LOOPX_RUNTIME_ROOT"] { diff --git a/apps/desktop/loopx-control-plane/src-tauri/src/services_real_runtime_tests.rs b/apps/desktop/loopx-control-plane/src-tauri/src/services_real_runtime_tests.rs index 63406154d1..66f448e630 100644 --- a/apps/desktop/loopx-control-plane/src-tauri/src/services_real_runtime_tests.rs +++ b/apps/desktop/loopx-control-plane/src-tauri/src/services_real_runtime_tests.rs @@ -35,6 +35,11 @@ fn assert_stopped(endpoints: ServiceEndpoints) { #[test] #[ignore = "requires a disposable Core install and empty isolated registry; see Desktop README"] fn real_private_runtime_serves_and_rejects_stale_identity() { + assert_eq!( + env::var("LOOPX_USAGE_PING").as_deref(), + Ok("0"), + "synthetic Core qualification requires LOOPX_USAGE_PING=0" + ); let root = PathBuf::from(env::var("LOOPX_TEST_PRIVATE_RUNTIME").unwrap()); // A caller's empty registry can still share a runtime with bound private // conversations. Own a fresh data root rather than trusting that shortcut.