Skip to content

T-IFXN-sdf-serve-static-dir-default

State: planning/draft · Impact: medium · Complexity: medium

This is a post-merge follow-up that revises a decision #2546 documents: that branch gives SDF_STATIC_DIR a compile-time default and only warns when index.html is missing. It is not a duplicate of that work. The same change can instead be settled on that PR before it merges, in which case this task closes without work.

sdf-serve should serve the front end, or stop with a clear message, no matter where its binary runs. Today the default front-end directory is baked in at compile time as a path inside the checkout that built it, so a copied binary points at a directory that may be missing, stale, or someone else’s.

  • The code is in solutions/ontological/desktop/src-tauri/src/serve.rs, ServeConfig::from_env. It reads SDF_STATIC_DIR; when unset it uses env!("CARGO_MANIFEST_DIR")/../src-nuxt/.output/public, resolved at compile time.
  • run() in the same file checks for index.html under that directory and only prints a warning (eprintln!), then serves anyway. Requests then return 404.
  • The binary is sdf-serve (src-tauri/src/bin/sdf-serve.rs); a returned Err prints sdf-serve: <message> and exits 1.
  • moon run sdf:serve (solutions/ontological/desktop/moon.yml, task serve) starts it with cargo run, with no SDF_STATIC_DIR set. The README table in solutions/ontological/desktop/README.md documents the default as the checkout’s src-nuxt/.output/public.
  • These files exist only on the branch feat/sdf-headless-server of the open pull request #2546. They are not on main yet.

SDF_STATIC_DIR is required. With it unset, empty, or pointing where index.html is missing, sdf-serve exits 1 before binding, with a message that names SDF_STATIC_DIR and the directory it checked. The moon task sdf:serve sets the variable to src-nuxt/.output/public, so the developer path is unchanged.

Decision: require the env var. Why: it is the smallest change, adds no dependency, and the failure is explicit. The server already needs the front end to exist as files, and the only caller that relies on the default is the moon task, which can pass the path itself.

Rejected: a path relative to the executable. The binary is built under target/, far from src-nuxt/.output/public, so the layout would be a guess that breaks on copy. Rejected: embedding the assets in the binary. It would work from anywhere, but it adds an embed crate, forces nuxt generate to finish before cargo build, and grows the binary. Revisit embedding only if a single-file release of sdf-serve is wanted.

  1. In ServeConfig::from_env, drop the env!("CARGO_MANIFEST_DIR") fallback. Return Err when SDF_STATIC_DIR is unset or empty, with a message that names SDF_STATIC_DIR.
  2. In run(), turn the missing-index.html warning into a returned Err with the same shape of message (directory checked, how to fix).
  3. In solutions/ontological/desktop/moon.yml, task serve, set SDF_STATIC_DIR=src-nuxt/.output/public for the cargo run command. The task already runs with its working directory at the desktop project root (it passes --manifest-path src-tauri/Cargo.toml), so the relative path resolves.
  4. Update the SDF_STATIC_DIR row in solutions/ontological/desktop/README.md and the doc comment on from_env.
  5. Extract a pure static_dir_from(Option<OsString>) -> Result<PathBuf, String> in serve.rs and unit test the unset and empty cases through it; cargo test runs tests on parallel threads, so tests must not set SDF_STATIC_DIR in the process environment. The missing-index.html case is tested through the spawned binary in src-tauri/tests/headless.rs.
AreaNote
solutions/ontological/desktop/src-tauri/src/serve.rsfrom_env default and run() check
solutions/ontological/desktop/src-tauri/tests/headless.rsConfig error cases
solutions/ontological/desktop/moon.ymlserve task passes the variable
solutions/ontological/desktop/README.mdThe env var table
  • AC-1: Running a copy of the sdf-serve binary from /tmp with SDF_STATIC_DIR unset exits 1, and stderr contains SDF_STATIC_DIR.
  • AC-2: Running it with SDF_STATIC_DIR set to a directory without index.html exits 1 and stderr names that directory and SDF_STATIC_DIR.
  • AC-3: Running the copy from /tmp with SDF_STATIC_DIR set to a built src-nuxt/.output/public serves index.html at / (HTTP 200).
  • AC-4: moon run sdf:serve still serves the front end with no variable set by hand.
  • AC-5: rg "CARGO_MANIFEST_DIR" solutions/ontological/desktop/src-tauri/src/serve.rs returns nothing.
  • cargo test --manifest-path solutions/ontological/desktop/src-tauri/Cargo.toml --test headless
  • cp <target dir>/debug/sdf-serve /tmp/sdf-serve-copy && cd /tmp && ./sdf-serve-copy; echo $?
  • cd /tmp && SDF_STATIC_DIR=<checkout>/solutions/ontological/desktop/src-nuxt/.output/public ./sdf-serve-copy & then curl -s -o /dev/null -w '%{http_code}' http://127.0.0.1:16175/
  • rg "CARGO_MANIFEST_DIR" solutions/ontological/desktop/src-tauri/src/serve.rs
  • Embedding the front end in the binary.
  • Changing SDF_HTTP_HOST, SDF_HTTP_PORT or SDF_DASHBOARD_URL.
  • Packaging or distributing sdf-serve.
  • This task cannot start until #2546 merges. serve.rs and the serve moon task exist only on its branch feat/sdf-headless-server.

← Back to Tasks