fix(managed-runtime): secure auth and lifecycle control across runtimes (#437)

* feat: add OpenCode server authentication with auto-generated passwords

* fix(auth): separate user env and managed OpenCode password state

* fix(auth): enforce env precedence and managed password rotation across runtimes

* fix(vscode): rotate managed auth on startup and harden webview proxy

* build: add dev icons and config for Tauri desktop development

* fix(runtime): start managed OpenCode via CLI and expose active API port

* fix(managed-runtime): control OpenCode lifecycle and surface secure diagnostics

* docs: remove VS Code plugin test runbook
This commit is contained in:
Iuliia Ivashko
2026-02-17 18:01:57 +02:00
committed by GitHub
parent 58b27fa621
commit 138772e66e
22 changed files with 717 additions and 88 deletions
+10 -1
View File
@@ -18,7 +18,16 @@ function spawnProcess(command, args, opts = {}) {
}
async function main() {
const tauriProcess = spawnProcess('bun', ['--cwd', desktopDir, 'tauri', 'dev', '--features', 'devtools']);
const tauriProcess = spawnProcess('bun', [
'--cwd',
desktopDir,
'tauri',
'dev',
'--features',
'devtools',
'--config',
'./src-tauri/tauri.dev.conf.json',
]);
let cleaning = false;
+2
View File
@@ -1187,6 +1187,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "2dff15bf788c671c1934e366d07e30c1814a8ef514e1af724a602e8a2fbe1b10"
dependencies = [
"futures-core",
"futures-sink",
]
[[package]]
@@ -3411,6 +3412,7 @@ checksum = "9d0946410b9f7b082a427e4ef5c8ff541a88b357bc6c637c40db3a68ac70a36f"
dependencies = [
"base64 0.22.1",
"bytes",
"futures-channel",
"futures-core",
"futures-util",
"http",
+1 -1
View File
@@ -16,7 +16,7 @@ devtools = ["tauri/devtools"]
anyhow = "1.0.86"
base64 = "0.22.1"
log = "0.4.28"
reqwest = { version = "0.12.4", default-features = false, features = ["rustls-tls"] }
reqwest = { version = "0.12.4", default-features = false, features = ["rustls-tls", "blocking"] }
serde = { version = "1.0.210", features = ["derive"] }
serde_json = "1.0.143"
tauri = { version = "2.9.4", features = ["macos-private-api"] }
Binary file not shown.
Binary file not shown.

After

Width:  |  Height:  |  Size: 65 KiB

+25
View File
@@ -1476,10 +1476,27 @@ fn kill_sidecar(app: tauri::AppHandle) {
return;
};
let sidecar_url = state.url.lock().expect("sidecar url mutex").clone();
if let Some(url) = sidecar_url {
let shutdown_url = format!("{}/api/system/shutdown", url.trim_end_matches('/'));
if let Ok(client) = reqwest::blocking::Client::builder()
.no_proxy()
.timeout(Duration::from_millis(1500))
.build()
{
if let Ok(resp) = client.post(shutdown_url).send() {
if resp.status().is_success() {
std::thread::sleep(Duration::from_millis(100));
}
}
}
}
let mut guard = state.child.lock().expect("sidecar mutex");
if let Some(child) = guard.take() {
let _ = child.kill();
}
*state.url.lock().expect("sidecar url mutex") = None;
}
fn build_local_url(port: u16) -> String {
@@ -1627,6 +1644,7 @@ async fn spawn_local_server(app: &tauri::AppHandle) -> Result<String> {
.args(["--port", &port.to_string()])
.env("OPENCHAMBER_HOST", "127.0.0.1")
.env("OPENCHAMBER_DIST_DIR", dist_dir.clone())
.env("OPENCHAMBER_RUNTIME", "desktop")
.env("OPENCHAMBER_DESKTOP_NOTIFY", "true")
.env("PATH", augmented_path.clone())
.env("NO_PROXY", no_proxy)
@@ -1643,6 +1661,13 @@ async fn spawn_local_server(app: &tauri::AppHandle) -> Result<String> {
}
}
if let Ok(password) = env::var("OPENCODE_SERVER_PASSWORD") {
let trimmed = password.trim();
if !trimmed.is_empty() {
cmd = cmd.env("OPENCODE_SERVER_PASSWORD", trimmed);
}
}
let (rx, child) = match cmd.spawn() {
Ok(v) => v,
Err(err) => {
@@ -0,0 +1,9 @@
{
"$schema": "../node_modules/@tauri-apps/cli/schema.json",
"bundle": {
"icon": [
"icons/dev-icon.icns",
"icons/dev-icon.png"
]
}
}