provisioning/schemas/catalog/manifest.ncl

202 lines
9.3 KiB
Text
Raw Normal View History

# 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 "<noun> <verb>" commands)
# just → extensions/just/<name>.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/<name>.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 = [],
},
}