# | KCL core lib schema contracts # | Migrated from: provisioning/kcl/lib.k # | Pattern: Schema definitions only let _concerns_lib = import "concerns.ncl" in { StorageVol = { name | String, size | Number, total | Number, type | String, mount | Bool, mount_path | String | optional, fstab | Bool, }, Storage = { name | String, size | Number, total | Number, type | String, mount | Bool, mount_path | String | optional, fstab | Bool, parts, }, TaskServDependency = { name | String, kind | [| 'Requires, 'PrefersBefore, 'ConflictsWith |] | default = 'Requires, condition | String | default = "", }, TaskServDef = { name | String, install_mode | String | default = "library", profile | String | default = "default", target_save_path | String | default = "", depends_on | Array { name | String, kind | [| 'Requires, 'PrefersBefore, 'ConflictsWith |] | default = 'Requires, condition | String | default = "", } | default = [], on_error | [| 'Stop, 'Continue, 'Retry |] | default = 'Stop, max_retries | Number | default = 0, params | { .. } | default = {}, .. }, ClusterDef = { name | String, profile | String | default = "default", target_save_path | String | default = "", }, # Unified component model — deployment mode selector DeployMode = [| 'taskserv, 'cluster, 'container |], # Port exposure requirements declared by a component PortRequirement = { port | Number, protocol | String | default = "TCP", exposure | [| 'public, 'private, 'internal |] | default = 'internal, }, # What a component needs from the infrastructure ComponentRequires = { storage | { size | String, persistent | Bool } | optional, ports | Array { port | Number, protocol | String | default = "TCP", exposure | [| 'public, 'private, 'internal |] | default = 'internal, } | default = [], credentials | Array String | default = [], }, # What a component exposes to other components ComponentProvides = { service | String | optional, port | Number | optional, databases | Array String | default = [], endpoints | Array String | default = [], }, # Operations supported by a component (maps to CMD_TSK dispatch in scripts) ComponentOperations = { install | Bool | default = true, update | Bool | default = false, reinstall | Bool | default = false, delete | Bool | default = false, backup | Bool | default = false, restore | Bool | default = false, health | Bool | default = false, config | Bool | default = false, scripts | Bool | default = false, restart | Bool | default = false, }, # How to verify a component is live after deployment. # Orthogonal to mode (provisioning mechanism) — describes runtime observability strategy. LiveCheckDef = { # 'k8s_pods — kubectl get pods filtered by namespace+selector (via CP SSH) # 'k8s_nodes — kubectl get nodes filtered by selector; healthy = all Ready (for worker components) # 'k8s_api — proxy: apiserver reachable if kubectl returns node list # 'systemd — systemctl is-active on target servers (skipped in ll fast path) # 'none — no observable runtime state (one-shot ops, bare binaries) strategy | [| 'k8s_pods, 'k8s_nodes, 'k8s_api, 'systemd, 'none |] | default = 'none, # 'cp_only — SSH to control-plane only (kubectl sees all pods/nodes from there) # 'target — SSH to component.target (typically CP for taskservs with explicit target) # 'all_servers — check all servers in workspace state (systemd only; skipped in ll) # 'workers_only — check only worker nodes (k8s_nodes for kubernetes_worker) scope | [| 'cp_only, 'target, 'all_servers, 'workers_only |] | default = 'cp_only, namespace | String | default = "", # overrides component.namespace for pod filter selector | String | default = "", # overrides component.pod_selector; also used as node name filter service | String | default = "", # systemd unit name # Aggregation for multi-server checks (all_servers / workers_only scope): # 'all_must_pass — any failure → degraded (runtimes, DNS) # 'any_active — at least one live → partial acceptable # 'majority — >50% live → healthy aggregate | [| 'all_must_pass, 'any_active, 'majority |] | default = 'all_must_pass, }, # Unified component definition — extends TaskServDef shape with mode, requires, provides. # Open record with defaults on new fields: existing taskservs satisfy ComponentDef. ComponentDef = { name | String, mode | [| 'taskserv, 'cluster, 'container |] | default = 'taskserv, target | String | optional, # server hostname (taskserv mode) namespace | String | optional, # k8s namespace (cluster mode) pod_selector | String | optional, # k8s pod name search pattern (overrides component name when k8s release name differs) live_check | LiveCheckDef | default = { strategy = 'none, scope = 'cp_only, namespace = "", selector = "", service = "", aggregate = 'all_must_pass }, node_selector | { _ | String } | optional, # k8s node affinity (cluster mode) install_mode | String | default = "library", profile | String | default = "default", target_save_path | String | default = "", depends_on | Array { name | String, kind | [| 'Requires, 'PrefersBefore, 'ConflictsWith |] | default = 'Requires, condition | String | default = "", } | default = [], on_error | [| 'Stop, 'Continue, 'Retry |] | default = 'Stop, max_retries | Number | default = 0, params | { .. } | default = {}, requires | { storage | { size | String, persistent | Bool } | optional, ports | Array { port | Number, protocol | String | default = "TCP", exposure | [| 'public, 'private, 'internal |] | default = 'internal, } | default = [], credentials | Array String | default = [], } | default = {}, provides | { service | String | optional, port | Number | optional, databases | Array String | default = [], endpoints | Array String | default = [], } | default = {}, operations | { install | Bool | default = true, update | Bool | default = false, reinstall | Bool | default = false, delete | Bool | default = false, backup | Bool | default = false, restore | Bool | default = false, health | Bool | default = false, config | Bool | default = false, scripts | Bool | default = false, restart | Bool | default = false, } | default = {}, # Mandatory declarative surface for service-level concerns. Each entry is a # ConcernState variant (enabled/disabled/pending/inherited). Components that # don't implement a concern declare 'pending {reason, backlog_ref} or # 'disabled {reason} — never omit. CI/ontoref consume this surface to emit # backlog priorities and architecture documentation. concerns | _concerns_lib.ServiceConcerns, .. }, ScaleData = { def | String, disabled | Bool, mode | String, expire | Dyn | optional, from | Dyn | optional, to | Dyn | optional, }, ScaleResource = { default, fallback | Dyn | optional, up | Dyn | optional, down | Dyn | optional, min | Dyn | optional, max | Dyn | optional, path | String, }, }