feat(app-tauri): cycle de vie du serveur embarqué et persistance de l'exposition (#68 B2)
Permet d'activer le serveur web depuis l'app desktop — la fonctionnalité demandée à l'origine du ticket. - `embedded_server.rs` : `EmbeddedServerController` porté par `AppState`, avec les commandes `embedded_server_start` / `stop` / `status` et `get` / `save` / `preview_server_exposure_settings`. - `FsServerExposureSettingsStore` : écrit `<app-data-dir>/deployment/server-exposure.json`. C'est de la config de sécurité, pas une préférence d'UI — d'où l'app-data-dir global plutôt que `localStorage`. Écriture atomique : temporaire, `0600` posé AVANT le `rename`, donc le fichier final n'est jamais brièvement lisible par tous. - Arrêt du serveur câblé sur la sortie de l'app (`lib.rs`), aux côtés des autres nettoyages. Le serveur embarqué appelle `run_embedded_with_core` avec le `BackendCore` partagé du desktop, jamais `run_embedded` — c'est tout l'intérêt du seam ouvert par B1 : une seule composition root dans le processus, pas deux. DETTE CONNUE, consignée au carnet, non bloquante : - `preview_settings` valide avant de prévisualiser (`embedded_server.rs:211`), ce qui verrouille la liste des candidats : un brouillon en mode `remoteProxyOtherMachine` ne peut pas être prévisualisé tant qu'il n'a pas le `lanBindAddress` que cette liste doit justement fournir. Contourné côté frontend par une sonde `localOnly` toujours valide. Défaut d'ordonnancement, pas une fatalité. - Le warning `missingTrustedProxy` (`embedded_server.rs:452`) est du code mort : `validate_settings` rejette les `trustedProxies` vides en mode 3 avant que `preview_settings` ne puisse le produire. QA ré-exécutée par Git HORS SANDBOX (DevBackend et QA sont bloqués par EPERM sur `bind` ; un vert sandboxé ne prouve rien sur ces crates) : `cargo test -p app-tauri` 43 passed, 1 ignored · `-p web-server` 66 passed, 0 échec. Le test ignoré `mcp_bridge::tests::end_to_end_over_real_loopback` est PRÉEXISTANT sur `develop` et non touché par ce lot ; lancé explicitement hors sandbox avec `--ignored`, il passe. C'est une garde d'environnement, pas un faux vert — distinction qui nous a déjà coûté deux fois aujourd'hui. Invariants vérifiés par Git : appelant `run_embedded_with_core` confirmé, aucune fuite d'`EmbeddedServer*`/`ServerExposure*` dans `domain` ni `application`, ordre chmod/rename correct, `stop()` bien appelé à la fermeture. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
@ -16,6 +16,7 @@
|
||||
pub mod chat;
|
||||
pub mod commands;
|
||||
pub mod dto;
|
||||
pub mod embedded_server;
|
||||
pub mod events;
|
||||
pub mod mcp_bridge;
|
||||
pub mod mcp_endpoint;
|
||||
@ -129,6 +130,7 @@ pub fn run() {
|
||||
let snapshot = std::sync::Arc::clone(&state.snapshot_running_agents);
|
||||
let model_servers =
|
||||
std::sync::Arc::clone(&state.ensure_local_model_server);
|
||||
let embedded_server = std::sync::Arc::clone(&state.embedded_server);
|
||||
let open_projects = state.open_project_ids();
|
||||
let handles = state.terminal_sessions.handles();
|
||||
tauri::async_runtime::block_on(async move {
|
||||
@ -148,6 +150,7 @@ pub fn run() {
|
||||
let _ = pty.kill(&h).await;
|
||||
}
|
||||
let _ = model_servers.stop_on_app_exit().await;
|
||||
let _ = embedded_server.stop().await;
|
||||
});
|
||||
}
|
||||
|
||||
@ -282,6 +285,12 @@ pub fn run() {
|
||||
commands::cancel_background_task,
|
||||
commands::retry_background_task,
|
||||
commands::list_background_tasks,
|
||||
commands::get_server_exposure_settings,
|
||||
commands::save_server_exposure_settings,
|
||||
commands::preview_server_exposure_settings,
|
||||
commands::embedded_server_status,
|
||||
commands::embedded_server_start,
|
||||
commands::embedded_server_stop,
|
||||
])
|
||||
.run(tauri::generate_context!())
|
||||
.expect("error while running IdeA Tauri application");
|
||||
|
||||
Reference in New Issue
Block a user