diff --git a/.ontoref/README.md b/.ontoref/README.md new file mode 100644 index 0000000..c9264a2 --- /dev/null +++ b/.ontoref/README.md @@ -0,0 +1,43 @@ +# .ontoref/ + +Runtime configuration for the `ontoref-daemon`. + +## Registry + +`registry.toml` is **derived** — do not edit it by hand. + +The source of truth is `registry.ncl`, which carries a typed Nickel schema: + +| Field | Type | Notes | +|-------|------|-------| +| `slug` | `String` | Unique project identifier | +| `root` | `String` | Absolute path to the project root | +| `keys` | `Array KeyEntry` | Optional. Each entry: `role` (`admin`\|`viewer`) + `hash` (Argon2id PHC) | + +### Why not validate paths in Nickel + +Nickel is a pure configuration language — no filesystem access. +Path existence is validated by the generator script at write time, not by the schema. +The schema enforces structure and types; the script enforces runtime semantics. + +### Generating registry.toml + +```sh +nu .ontoref/gen-registry.nu +# or via just: +just gen-registry +``` + +Projects whose `root` path does not exist are warned and skipped. +This is intentional: the registry may reference projects present on some machines but not others. + +### Adding a key (HTTP auth) + +```sh +# 1. Generate the hash +ontoref-daemon --hash-password + +# 2. Add the entry to registry.ncl under the target project's keys array +# 3. Regenerate +just gen-registry +``` diff --git a/.ontoref/gen-registry.nu b/.ontoref/gen-registry.nu new file mode 100644 index 0000000..abca6a3 --- /dev/null +++ b/.ontoref/gen-registry.nu @@ -0,0 +1,35 @@ +#!/usr/bin/env nu +# .ontoref/gen-registry.nu +# Reads registry.ncl, validates project paths, and writes registry.toml. +# registry.ncl is the source of truth; registry.toml is derived — do not edit it by hand. + +def main [] { + let script_dir = ($env.CURRENT_FILE | path dirname) + let ncl_file = $"($script_dir)/registry.ncl" + let toml_file = $"($script_dir)/registry.toml" + + let result = (do { ^nickel export --format json $ncl_file } | complete) + if $result.exit_code != 0 { + error make { msg: $"nickel export failed:\n($result.stderr)" } + } + + let registry = ($result.stdout | from json) + + let valid_projects = ($registry.projects | each { |p| + if ($p.root | path exists) { + $p + } else { + print $" (ansi yellow)WARN(ansi reset) project '($p.slug)': root not found at ($p.root) — skipping" + null + } + } | compact) + + let skipped = ($registry.projects | length) - ($valid_projects | length) + if $skipped > 0 { + print $" (ansi yellow)($skipped) project(s) skipped due to missing paths(ansi reset)" + } + + { projects: $valid_projects } | to toml | save -f $toml_file + + print $" (ansi green)OK(ansi reset) ($valid_projects | length) project\(s\) written to ($toml_file)" +} diff --git a/.ontoref/registry.ncl b/.ontoref/registry.ncl new file mode 100644 index 0000000..2895c11 --- /dev/null +++ b/.ontoref/registry.ncl @@ -0,0 +1,33 @@ +# Registry source of truth — consumed by gen-registry.nu to produce registry.toml. +# Path existence is validated at generation time (Nickel is pure; no filesystem access). +# Hash values are Argon2id PHC strings produced by: ontoref-daemon --hash-password + +let KeyRole = [| 'admin, 'viewer |] in + +let KeyEntry = { + role | KeyRole, + hash | String, +} in + +let ProjectEntry = { + slug | String, + root | String, + keys | Array KeyEntry | default = [], +} in + +{ + projects | Array ProjectEntry = [ + { + slug = "ontoref", + root = "/Users/Akasha/Development/ontoref", + }, + { + slug = "typedialog", + root = "/Users/Akasha/Development/typedialog", + }, + { + slug = "stratumiops", + root = "/Users/Akasha/Development/stratumiops", + }, + ], +} diff --git a/.ontoref/registry.toml b/.ontoref/registry.toml index 0c53a67..0a7c4fa 100644 --- a/.ontoref/registry.toml +++ b/.ontoref/registry.toml @@ -1,7 +1,14 @@ [[projects]] -slug = "ontoref" +keys = [] root = "/Users/Akasha/Development/ontoref" +slug = "ontoref" [[projects]] -slug = "typedialog" +keys = [] root = "/Users/Akasha/Development/typedialog" +slug = "typedialog" + +[[projects]] +keys = [] +root = "/Users/Akasha/Development/stratumiops" +slug = "stratumiops" diff --git a/crates/ontoref-daemon/src/registry.rs b/crates/ontoref-daemon/src/registry.rs index 9d2a444..fc407ec 100644 --- a/crates/ontoref-daemon/src/registry.rs +++ b/crates/ontoref-daemon/src/registry.rs @@ -115,10 +115,18 @@ impl ProjectRegistry { .retain(|slug, _| new_slugs.contains(slug.as_str())); for entry in file.projects { - let root = entry - .root - .canonicalize() - .map_err(|e| anyhow::anyhow!("project '{}': root path error: {}", entry.slug, e))?; + let root = match entry.root.canonicalize() { + Ok(p) => p, + Err(e) => { + warn!( + slug = %entry.slug, + path = %entry.root.display(), + error = %e, + "project root not found — skipping" + ); + continue; + } + }; if let Some(existing) = self.contexts.get(&entry.slug) { // Project already loaded — update keys only, reuse warm cache/actors. diff --git a/justfiles/ci.just b/justfiles/ci.just index 590536d..fd0f2ce 100644 --- a/justfiles/ci.just +++ b/justfiles/ci.just @@ -196,10 +196,15 @@ install-daemon: cargo build --release -p ontoref-daemon dest="${HOME}/.local/bin/ontoref-daemon" mkdir -p "${HOME}/.local/bin" + # Stop any running instance before replacing the binary; macOS kills the new process if the old one holds the file + pkill -x ontoref-daemon 2>/dev/null || true cp target/release/ontoref-daemon "${dest}" chmod +x "${dest}" echo "Installed: ${dest}" - "${dest}" --version 2>/dev/null || true + +# Generate .ontoref/registry.toml from registry.ncl (validates paths, skips missing) +gen-registry: + nu .ontoref/gen-registry.nu # ============================================================================== # Utility Commands