This commit is contained in:
Kelorastus
2026-09-25 10:14:44 +02:00
parent 4d620fc5ad
commit 21d6e6bffb
34 changed files with 615 additions and 321 deletions
+28
View File
@@ -19,6 +19,12 @@ pub struct Settings {
/// The site's MCP, which runs the Keycloak sign-in.
#[serde(default)]
pub mcp_url: String,
/// Where ODIAN's AI features live (destination prediction, chat, vision): the MCP that
/// serves `/api/ai/...`, reached over the internet. Empty keeps ODIAN wholly offline, which
/// is what an install with no line out wants; set, it is the one address the client is
/// allowed to reach, and the AI features stop saying "not available offline".
#[serde(default)]
pub ai_url: String,
#[serde(default)]
pub install_dir: String,
/// Display name from site.json; the UI's settings form does not edit it.
@@ -34,6 +40,8 @@ struct SiteFile {
site_url: String,
#[serde(default)]
mcp_url: String,
#[serde(default)]
ai_url: String,
/// This launcher ships on an ODIAN drive: see `portable_root`.
#[serde(default)]
portable: bool,
@@ -190,6 +198,15 @@ fn folder_problem_on(folder: &Path, drive: &Path) -> Option<String> {
}
}
/// Whether a drive's install folder still needs the grant below: only while nothing has
/// been installed into it. Handing it out on a folder that already holds an install makes
/// Windows walk every file under it to push the inheritable entry down - on a drive
/// carrying a million map tiles that grinds for hours, with the install waiting on it.
/// Everything written into the folder afterwards inherits the grant on its own.
pub fn grant_still_needed(install_dir: &Path) -> bool {
!install_dir.join("versions").exists()
}
/// Is this folder on the drive the launcher runs from? Only then does the install travel,
/// and only then is it worth opening to every account of every PC the drive is plugged into.
pub fn installs_on_the_drive(folder: &Path) -> bool {
@@ -252,6 +269,7 @@ impl Settings {
let settings = Settings {
site_url: normalize_url(&site.site_url),
mcp_url: normalize_url(&site.mcp_url),
ai_url: normalize_url(&site.ai_url),
install_dir: default_install_dir(),
site_name: site.name,
};
@@ -296,6 +314,16 @@ impl Settings {
mod tests {
use super::*;
#[test]
fn the_account_grant_is_for_an_empty_folder_only() {
let dir = std::env::temp_dir().join(format!("odian-grant-{}", uuid::Uuid::new_v4().simple()));
std::fs::create_dir_all(&dir).unwrap();
assert!(grant_still_needed(&dir), "nothing installed yet: hand it out");
std::fs::create_dir_all(dir.join("versions").join("0.1.0")).unwrap();
assert!(!grant_still_needed(&dir), "an install is there: walking it would take hours");
std::fs::remove_dir_all(&dir).unwrap();
}
#[test]
fn a_drives_own_launcher_installs_on_that_drive_whatever_its_letter() {
for (exe, want) in [