# infra-catalog Component Manifest Schema # # Every component distributed through any infra-catalog source — regardless of # which registry or peer hosts it — must satisfy this contract. # # This schema is the sole coupling point between the catalog ecosystem and any # tool that consumes it (Provisioning, lian-build, Vapora, or others). Tools # validate manifests against it; they do not need to know anything else about # the component source. # # Identity comes from content hash (OCI digest), not from registry location. # The `source` field is informational only. # # Deployment modes # A component may support 'cluster (K8s) and/or 'systemd (host-level). # Each mode has its own installer script declared in mode_installers. # Most components are cluster-only; systemd mode is for components that run # outside K8s (e.g. lian_build daemon, hccm on bare metal). # # Extensions # When a component is installed, the manager discovers and loads any # extensions it declares: CLI commands (Nu module), Justfile recipes, # or helper scripts. Extensions must be present at the declared paths. # # Usage: # let Catalog = import "schemas/catalog/manifest.ncl" in # { ... } | Catalog.Manifest { # ── Kind enum ───────────────────────────────────────────────────────────────── # Each kind binds the component to a specific interface contract. # Tools that need a capability load the corresponding entry point. ComponentKind = [| 'ComputeProvider, # spawns/destroys ephemeral compute — implements runner.nu interface 'StorageProvider, # manages persistent volumes — implements storage.nu interface 'RegistryAdapter, # OCI registry operations — implements registry.nu interface 'DeploymentComponent, # deploys a service — implements installer.nu interface 'AgentProvider, # AI/agent capabilities — implements agent.nu interface 'SchemaLibrary, # reusable Nickel schemas — no runtime entry point |], # ── Tool requirement ────────────────────────────────────────────────────────── # Declares an external CLI that the component's scripts invoke. ToolRequirement = { name | String, min_version | String | optional, check | String | optional | doc "Shell expression that exits 0 when the tool is available.", }, # ── Catalog dependency ──────────────────────────────────────────────────────── # Another catalog component required at runtime. CatalogDep = { name | String, kind | ComponentKind, version | String, }, # ── Source reference ────────────────────────────────────────────────────────── # Informational. Content trust is established by OCI digest and signature, # not by source URL. Multiple sources are mirrors of the same content. SourceRef = { radicle | String | optional | doc "Radicle project ID, e.g. rad:z6MkhDvY...", git | String | optional | doc "Git remote URL (mirror or upstream).", oci | String | optional | doc "Canonical OCI reference (without digest — digest is in the artifact manifest).", }, # ── Deployment modes ───────────────────────────────────────────────────────── # Declares which deployment modes the component supports. # The manager uses this to validate that the requested mode is available # before attempting to install. DeploymentModes = { cluster | Bool | doc "Supports in-cluster K8s deployment via cluster/install.sh." | default = false, systemd | Bool | doc "Supports host-level deployment as a systemd unit via systemd/install.sh." | default = false, }, # ── Mode installers ─────────────────────────────────────────────────────────── # Paths relative to the component root after installation. # Only required when the corresponding mode is true in deployment_modes. # Convention: cluster → "cluster/install.sh", systemd → "systemd/install.sh". ModeInstallers = { cluster | String | doc "Installer script for cluster mode. Implements install/uninstall/status/upgrade." | optional, systemd | String | doc "Installer script for systemd mode. Implements install/uninstall/enable/disable." | optional, }, # ── Extensions ──────────────────────────────────────────────────────────────── # Capabilities the component adds to the manager when installed. # The manager loads declared extensions at startup so callers get new # subcommands and recipes without modifying the manager itself. # # Convention: # cli → extensions/cli/commands.nu (Nu module; exports " " commands) # just → extensions/just/.just (Justfile module; recipe prefix = name) # scripts → extensions/scripts/ (helper scripts; no discovery contract) Extensions = { cli | Bool | doc "Provides extensions/cli/commands.nu — loaded by the manager CLI dispatcher." | default = false, just | Bool | doc "Provides extensions/just/.just — Justfile module for workspace recipes." | default = false, scripts | Bool | doc "Provides extensions/scripts/ — helper scripts for direct invocation." | default = false, }, # ── Entry points ────────────────────────────────────────────────────────────── # Runtime interface entry points — paths relative to component root after installation. # Each ComponentKind mandates its corresponding entry point. EntryPoints = { runner | String | optional | doc "ComputeProvider: script implementing spawn/destroy/status/describe.", storage | String | optional | doc "StorageProvider: script implementing create/delete/attach/detach.", registry | String | optional | doc "RegistryAdapter: script implementing push/pull/list/delete.", installer | String | optional | doc "DeploymentComponent: fallback installer when mode_installers is absent.", agent | String | optional | doc "AgentProvider: script implementing run/cancel/status.", schema | String | optional | doc "SchemaLibrary: primary .ncl export path.", }, # ── Capabilities ───────────────────────────────────────────────────────────── # Declared before loading so callers can query without executing the component. Capabilities = { ephemeral_compute | Bool | default = false, persistent_compute | Bool | default = false, snapshot_create | Bool | default = false, network_management | Bool | default = false, multi_region | Bool | default = false, arm64 | Bool | default = false, amd64 | Bool | default = false, storage_block | Bool | default = false, storage_object | Bool | default = false, storage_file | Bool | default = false, oci_push | Bool | default = false, oci_pull | Bool | default = false, llm | Bool | default = false, rag | Bool | default = false, workflow | Bool | default = false, }, # ── Manifest (root contract) ────────────────────────────────────────────────── Manifest = { name | String | doc "Lowercase, hyphenated identifier. Unique within a kind.", version | String | doc "Semver string: MAJOR.MINOR.PATCH.", kind | ComponentKind, description | String | doc "One sentence — catalog entry, search index, and discovery text.", requires = { nu | String | optional | doc "Minimum Nushell version.", nickel | String | optional | doc "Minimum Nickel version.", tools | Array ToolRequirement | default = [], }, catalog_deps | Array CatalogDep | default = [], deployment_modes | DeploymentModes | default = {}, mode_installers | ModeInstallers | default = {}, extensions | Extensions | default = {}, entry_points | EntryPoints | default = {}, capabilities | Capabilities | default = {}, source | SourceRef | default = {}, authors | Array String | default = [], }, }