ontoref/install/config-setup.nu

141 lines
5.3 KiB
Plaintext
Raw Permalink Normal View History

#!/usr/bin/env nu
# install/config-setup.nu — validate config.ncl and probe external services
#
# Run after editing config (or after first install) to confirm everything is wired correctly.
# Safe to run any time — read-only, no side effects.
#
# Usage:
# nu install/config-setup.nu
# nu install/config-setup.nu --config /custom/path/config.ncl
def main [
--config: string = "", # path to config.ncl (default: ~/.config/ontoref/config.ncl)
] {
let platform = (sys host | get name)
feat: config surface, NCL contracts, override-layer mutation, on+re update Config surface — per-project config introspection, coherence verification, and audited mutation without destroying NCL structure (ADR-008): - crates/ontoref-daemon/src/config.rs — typed DaemonNclConfig (parse-at-boundary pattern); all section structs derive ConfigFields + config_section(id, ncl_file) emitting inventory::submit!(ConfigFieldsEntry{...}) at link time - crates/ontoref-derive/src/lib.rs — #[derive(ConfigFields)] proc-macro; serde rename support; serde_rename_of() helper extracted to fix excessive_nesting - crates/ontoref-daemon/src/main.rs — 3-tuple bootstrap block (nickel_import_path, loaded_ncl_config: Option<DaemonNclConfig>, stdin_raw); apply_ui_config takes &UiConfig; NATS call site typed; resolve_asset_dir cfg(feature = "ui") - crates/ontoref-daemon/src/api.rs — config GET/PUT endpoints, quickref, coherence, cross-project comparison; index_section_fields() extracted (excessive_nesting) - crates/ontoref-daemon/src/config_coherence.rs — multi-consumer coherence; merge_meta_into_section() extracted; and() replaces unnecessary and_then NCL contracts for ontoref's own config: - .ontoref/contracts.ncl — LogConfig (LogLevel, LogRotation, PositiveInt) and DaemonConfig (Port, optional overrides); std.contract.from_validator throughout - .ontoref/config.ncl — log | C.LogConfig applied - .ontology/manifest.ncl — contracts_path, log/daemon contract refs, daemon section with DaemonRuntimeConfig consumer and 7 declared fields Protocol: - adrs/adr-008-ncl-first-config-validation-and-override-layer.ncl — NCL contracts as single validation gate; Rust structs are contract-trusted; override-layer mutation writes {section}.overrides.ncl + _overrides_meta, never touches source on+re update: - .ontology/core.ncl — config-surface node (28 practices); adr-lifecycle extended to adr-007 + adr-008; 6 new edges (ManifestsIn daemon, DependsOn ontology-crate, Complements api-catalog-surface/dag-formalized/self-describing/adopt-ontoref) - .ontology/state.ncl — protocol-maturity blocker and self-description-coverage catalyst updated for session 2026-03-26 - README.md / CHANGELOG.md updated
2026-03-26 20:20:22 +00:00
let is_mac = ((^uname) == "Darwin")
let config_path = if ($config | is-empty) {
$"($env.HOME)/.config/ontoref/config.ncl"
} else {
$config
}
let data_dir = if $is_mac {
$"($env.HOME)/Library/Application Support/ontoref"
} else {
$"($env.HOME)/.local/share/ontoref"
}
print "ontoref config-setup"
print $" config ($config_path)"
print ""
# ── 1. Config file exists ──────────────────────────────────────────────────
if not ($config_path | path exists) {
print "✗ config not found"
print $" copy the example: cp ($data_dir)/nulib/bootstrap.nu ... "
print $" or: cp (($config_path | path dirname))/config.ncl.example ($config_path)"
error make { msg: "config not found" }
}
print "✓ config file exists"
# ── 2. Nickel typecheck ────────────────────────────────────────────────────
let config_dir = ($config_path | path dirname)
feat: config surface, NCL contracts, override-layer mutation, on+re update Config surface — per-project config introspection, coherence verification, and audited mutation without destroying NCL structure (ADR-008): - crates/ontoref-daemon/src/config.rs — typed DaemonNclConfig (parse-at-boundary pattern); all section structs derive ConfigFields + config_section(id, ncl_file) emitting inventory::submit!(ConfigFieldsEntry{...}) at link time - crates/ontoref-derive/src/lib.rs — #[derive(ConfigFields)] proc-macro; serde rename support; serde_rename_of() helper extracted to fix excessive_nesting - crates/ontoref-daemon/src/main.rs — 3-tuple bootstrap block (nickel_import_path, loaded_ncl_config: Option<DaemonNclConfig>, stdin_raw); apply_ui_config takes &UiConfig; NATS call site typed; resolve_asset_dir cfg(feature = "ui") - crates/ontoref-daemon/src/api.rs — config GET/PUT endpoints, quickref, coherence, cross-project comparison; index_section_fields() extracted (excessive_nesting) - crates/ontoref-daemon/src/config_coherence.rs — multi-consumer coherence; merge_meta_into_section() extracted; and() replaces unnecessary and_then NCL contracts for ontoref's own config: - .ontoref/contracts.ncl — LogConfig (LogLevel, LogRotation, PositiveInt) and DaemonConfig (Port, optional overrides); std.contract.from_validator throughout - .ontoref/config.ncl — log | C.LogConfig applied - .ontology/manifest.ncl — contracts_path, log/daemon contract refs, daemon section with DaemonRuntimeConfig consumer and 7 declared fields Protocol: - adrs/adr-008-ncl-first-config-validation-and-override-layer.ncl — NCL contracts as single validation gate; Rust structs are contract-trusted; override-layer mutation writes {section}.overrides.ncl + _overrides_meta, never touches source on+re update: - .ontology/core.ncl — config-surface node (28 practices); adr-lifecycle extended to adr-007 + adr-008; 6 new edges (ManifestsIn daemon, DependsOn ontology-crate, Complements api-catalog-surface/dag-formalized/self-describing/adopt-ontoref) - .ontology/state.ncl — protocol-maturity blocker and self-description-coverage catalyst updated for session 2026-03-26 - README.md / CHANGELOG.md updated
2026-03-26 20:20:22 +00:00
let import_path = $"($config_dir):($config_dir)/schemas:($data_dir)/schemas:($data_dir)"
let check = (do {
with-env { NICKEL_IMPORT_PATH: $import_path } {
^nickel typecheck $config_path
}
} | complete)
if $check.exit_code != 0 {
print "✗ nickel typecheck failed"
print ($check.stderr | str trim)
error make { msg: "config schema validation failed" }
}
print "✓ nickel typecheck passed"
# ── 3. Parse config values ─────────────────────────────────────────────────
let export = (do {
with-env { NICKEL_IMPORT_PATH: $import_path } {
^nickel export --format json $config_path
}
} | complete)
if $export.exit_code != 0 {
print "✗ nickel export failed"
print ($export.stderr | str trim)
error make { msg: "config export failed" }
}
let cfg = ($export.stdout | from json)
# ── 4. Resolve and verify path dirs ───────────────────────────────────────
let log_path = if ($cfg.log.path | is-empty) {
if $is_mac { $"($env.HOME)/Library/Logs/ontoref" } else { $"($env.HOME)/.local/state/ontoref/logs" }
} else { $cfg.log.path }
let cache_path = if ($cfg.cache.path | is-empty) {
if $is_mac { $"($env.HOME)/Library/Caches/ontoref" } else { $"($env.HOME)/.cache/ontoref" }
} else { $cfg.cache.path }
let templates_dir = if ($cfg.ui.templates_dir | is-empty) {
$"($data_dir)/templates"
} else { $cfg.ui.templates_dir }
let public_dir = if ($cfg.ui.public_dir | is-empty) {
$"($data_dir)/public"
} else { $cfg.ui.public_dir }
print ""
print "── paths ──────────────────────────────────────────────"
for entry in [
{ label: "data dir", path: $data_dir },
{ label: "templates", path: $templates_dir },
{ label: "public", path: $public_dir },
{ label: "log dir", path: $log_path },
{ label: "cache dir", path: $cache_path },
] {
let exists = ($entry.path | path exists)
let mark = if $exists { "✓" } else { "⚠ missing (will be created on first run)" }
print $" ($mark) ($entry.label) ($entry.path)"
}
# ── 5. Liveness probes ────────────────────────────────────────────────────
print ""
print "── services ───────────────────────────────────────────"
# DB probe
if $cfg.db.enabled {
let db_url = $cfg.db.url
# Extract host:port from surrealdb://host:port/...
let addr = ($db_url | parse "surrealdb://{rest}" | get rest.0? | default "" | split row "/" | first)
let probe = (do { ^nc -z -w2 ...($addr | split row ":") } | complete)
if $probe.exit_code == 0 {
print $" ✓ db ($db_url)"
} else {
print $" ✗ db ($db_url) — not reachable"
}
} else {
print " — db disabled"
}
# NATS probe
if $cfg.nats_events.enabled {
let nats_url = $cfg.nats_events.url
let addr = ($nats_url | parse "nats://{rest}" | get rest.0? | default "" | split row "/" | first)
let probe = (do { ^nc -z -w2 ...($addr | split row ":") } | complete)
if $probe.exit_code == 0 {
print $" ✓ nats ($nats_url)"
} else {
print $" ✗ nats ($nats_url) — not reachable"
}
} else {
print " — nats disabled"
}
print ""
print $"config-setup complete platform=($platform)"
}