library

module
v1.0.0-alpha.32 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Sep 18, 2026 License: Apache-2.0

README

OPM kernel

The reference implementation of the Open Platform Model runtime, packaged as a Go library. Every OPM front-end — the opm CLI, the opm-operator controller, the planned Crossplane composition function, and any future runtime — embeds this kernel and inherits its behaviour.

The kernel owns:

  • Loading and acquiring OPM artifacts (modules, module instances, platforms) from CUE module directories and OCI registries.
  • Resolving CUE module references through the native CUE module system (OCI registries, cue.mod).
  • Validating user-supplied values against #config schemas with grouped, position-aware diagnostics.
  • Rendering: one CUE build per render that imports the instance, the platform and its catalogs, runs matching and transformer execution as CUE inside that build, reports the verdicts as data, and emits platform-neutral rendered values with full provenance.

The kernel does not own:

  • Process model, command flags, exit codes, stdout/stderr formatting (lives in CLI / controller).
  • Logging output (the kernel logs nothing; any logging lives with the caller).
  • Cluster reconciliation, status reporting, GitOps wiring (lives in opm-operator).
  • Platform-native identity — frontends wrap rendered values into their own platform-specific resource types.
  • Platform directory lifecycle. A platform is a CUE module on disk that imports its catalogs; the frontend writes it by hand or generates it from coordinates with the opt-in opm/helper/platformmodule helper, owns where it lives (generations, caching), and the kernel acquires and renders against it.
  • Debug-overlay policy. #ModuleDebug is not a kernel artifact; the kernel accepts only Module, ModuleInstance, and Platform (see "Artifact types" below). Debug values live as a debugValues field on Module itself; whether the frontend layers them into the values stack is policy that lives in the helper layer (CLI / operator / XR fn).

Artifact types

The kernel accepts exactly four artifact types — every input ultimately resolves to one of them:

Artifact Schema definition Go type Role
Module #Module (v1alpha2) *module.Module Author-defined application blueprint (components, #config schema, debugValues field).
ModuleInstance #ModuleInstance *module.Instance Per-deployment instantiation of a Module with concrete user values.
Platform #Platform *platform.Platform A CUE module importing its catalogs; core derives #composedTransformers, which the render glue reads inside the build.
Catalog #Catalog *catalog.Catalog The contracts a catalog defines beside the transformers implementing them. Acquired, read and derived from — never rendered (ADR-009).

#ModuleDebug was previously contemplated as a fourth top-level artifact and has been retired; debugValues is now a field on Module. The migration is one line: read mod.Package.LookupPath(schema.DebugValues) and feed the result into the helper-side values stack at the layer your frontend prefers. The kernel itself never observes the distinction.

See CONSTITUTION.md for the full set of principles.

Layout

opm/
  core/                   Platform-neutral primitives — Compiled (terminal output)
  errors/                 Structured errors, grouped CUE diagnostics, typed render-gate causes
  schema/                 OPM core schema loader (OCILoader, Cache), CUE path inventory, metadata types
  kernel/                 Public Kernel struct — single entry point for the OPM runtime (acquire, synthesize, validate, Render)
  module/                 Module / Instance model and value-validation accessors
  platform/               Platform artifact model — a CUE module importing its catalogs; Render's sole platform input
  catalog/                Catalog artifact model (ADR-009) — Metadata, Package, Source, plus the on-demand derivations Provides() and Requires(). Read and derived from; never rendered
  helper/                 Opt-in frontend convenience layer (a frontend MAY skip these; lint-enforced)
    platformmodule/       Platform CUE module generation from catalog coordinates (files + dependency closure)
  internal/loader/        The kernel's one artifact loader: shape gate, LoadDir (the one build-and-gate step, directory or overlay), FetchArtifact (a published artifact by path@version: fetch, stage as an overlay, build through LoadDir like a directory artifact, gated to the shape the caller names) with FetchModule the #Module entry over it, adding the coordinate identity check
  internal/synth/         Instance synthesis from typed inputs, built inside the module's own staged tree
  internal/renderstage/   Single-build render staging: promoted cue.mod, skew, embedded render glue, one cue/load build
  internal/               Test-only cross-package internals (schematest, registrytest) and the CUE closedness canary (cueregression)
adr/                      Architecture decision records
enhancements/             Frozen historical proposals (cite as legacy:NNN; new work lives in the workspace enhancements/)
openspec/                 OpenSpec proposals, specs, archives
modules/                  Test-only OPM modules used by integration tests
testdata/                 CUE module fixtures consumed by package tests
Taskfile.yml              fmt / vet / lint / test entry points

The OPM core schema is no longer vendored or embedded — it is fetched at runtime from CUE_REGISTRY via opm/schema (the apis/ tree and the old opm/api / opm/apiversion packages were removed). Artifact loading and instance synthesis are kernel internals (opm/internal/loader, opm/internal/synth) reached through the acquire verbs and Kernel.SynthesizeInstance; their sentinels are declared in opm/errors. A standalone opm/validate/ package was contemplated but never landed — the one validation primitive lives on *kernel.Kernel (ValidateConfigDetailed; a single value is a one-element []Source), composed with the ConfigSchema() accessors on *module.Module / *module.Instance.

Render

Kernel.AcquireInstanceFromDir | Kernel.SynthesizeInstance  ->  *module.Instance   (validated, carries Source)
Kernel.AcquirePlatformFromDir                             ->  *platform.Platform (carries Source)
Kernel.Render(RenderInput{Instance, Platform, RuntimeName, Skew, LocalReplacements})
        stage one generated render module (cue.mod promoted from both inputs; each input imported by directory replacement)
        promote the inputs' own local-module.cue replacements under LocalReplacements (platform whole, instance on
        instance-only paths) -> RenderDiagnostics.Replacements rows; refuse an input carrying one when the opt-in is off
        verify every OPM-namespace path either input requires is covered; apply the skew policy (SkewWarn | SkewRefuse)
        build once in a fresh cue.Context, dropped on return
        decode `diagnostics` -> RenderDiagnostics (pairs, unmatched, unresolved, unify, unhandled traits, over-subscribed, resolved versions)
        fail-closed gate     -> *RenderError carrying the diagnostics and typed causes (errors.As)
        decode `rendered`    -> []*kernel.Compiled with instance / component / transformer provenance

Render is the kernel's single render verb. Matching and transformer execution are CUE inside the build (the glue in opm/internal/renderstage/render.cue.tmpl), not Go; the build reports its verdicts as data and the kernel decodes them. A dry run is Render with Compiled discarded: the build evaluates every pair regardless, and RenderDiagnostics carries the pairing diagnosis. A developer's cue.mod/local-module.cue (a dependency redirected to a directory or another module) reaches the render only under RenderInput.LocalReplacements; off, an input carrying a replacement is refused rather than silently rendered against the published pin. Values are validated where they are applied: AcquireInstanceFromDir and SynthesizeInstance unify them inside the instance build and assert concreteness on the result, and Render performs no validation pass of its own.

Each render is its own CUE build in its own cue.Context that does not outlive the call (ADR-005), and every other verb works the same way (ADR-007): the Kernel holds no build context, an acquired artifact's Package pins the context of the call that built it for as long as the caller holds the artifact, and nothing else is retained. A single Kernel is safe for concurrent use across its method calls, so a consumer shares one Kernel per process; a render pool is sized by memory rather than by core count; see the opm/kernel package documentation.

*kernel.Compiled is the kernel's terminal output. Platform identity for compiled output is the frontend's concern — each consumer wraps Compiled in its own platform-specific resource type.

Quick start

See docs/getting-started.md for an end-to-end walkthrough — constructing a Kernel, loading a Module, layered values validation, acquiring an instance and a platform module, and rendering the instance into *kernel.Compiled values.

API stability

The library follows SemVer 2.0.0. The public surface is everything under opm/. Two distinct compatibility tracks coexist and must not be confused:

  • Go module SemVer governs the Go types and function signatures consumed by downstream binaries. A breaking change here is a major bump of the library.
  • OPM schema versioning governs the CUE shapes consumed at runtime — #Module, #ModuleInstance, #Platform, #Component, transformer contracts. The kernel MUST be able to load and render older schema versions seamlessly so that downstream implementations inherit multi-version support without per-implementation effort.

The two tracks are independent: within an OPM schema major, additive shape changes are absorbed by floating-major resolution and require no Go-side bump; a shape break in the schema is itself a coordinated library-breaking event.

OPM schema resolution

The library does NOT vendor or embed the OPM core schema. At runtime the kernel resolves opmodel.dev/core@v2 through CUE's module system against CUE_REGISTRY, then memoizes the built cue.Value in a per-Kernel *schema.Cache.

Key pieces:

  • opm/schema — schema loader (Loader interface, OCILoader sole public implementation), per-instance memoization (Cache), CUE path inventory, metadata types, and the PublicRegistry const (opmodel.dev=ghcr.io/open-platform-model,registry.cue.works).
  • opm/kernel — kernel.WithSchemaLoader(schema.Loader) configures which Loader the Kernel's cache wraps; (*Kernel).SchemaCache() exposes the cache to callers (a bare-major loader makes instance synthesis resolve the core release through it; a pinned loader, the default, needs no load). kernel.WithRegistry(string) sets the ONE registry mapping every kernel operation resolves through: the render build's catalog imports, registry module acquisition, directory acquisition, instance synthesis, the compilation of file-backed values sources (a values file that imports a registry module) and the default schema cache.

Frontends (CLI, operator, future Crossplane fn) set CUE_REGISTRY (typically to schema.PublicRegistry) before constructing the Kernel. The library auto-applies no default; this keeps Principle I (kernel neutrality) intact and avoids hidden lookups. See docs/getting-started.md for the deployment pattern, including the warm-cache pre-seeding pattern for restricted environments.

Helper boundary (opm/helper/)

Anything under opm/helper/ is opt-in convenience for embedding the kernel; a frontend MAY skip it and call the kernel directly. Anything outside opm/helper/ is part of the kernel contract.

The boundary is enforced by task lint, not just documented: a depguard rule in .golangci.yml forbids opm/kernel, opm/module, opm/platform, opm/schema, opm/errors and every package under opm/internal/ from importing anything under opm/helper/.

Today this layer holds exactly one subpackage:

  • opm/helper/platformmodule — Platform module generation from catalog coordinates: Roots + Closure derive the tidied dependency list from published module files (through a caller-configured ModFileSource), Generate renders cue.mod/module.cue and platform.cue deterministically, Files.WriteTo writes them into a caller-owned directory for Kernel.AcquirePlatformFromDir. The core pin defaults to schema.DefaultSchemaVersion().

Layered values validation lives on the kernel itself — see Kernel.ValidateConfigDetailed and the Source type in opm/kernel. See enhancements/001-kernel-redesign-around-platform/02-design.md.

The loader and synth subpackages that used to live here folded into opm/internal/loader and opm/internal/synth: the kernel imported both, so the "opt-in" tier was mandatory. Their behaviour is unchanged and reached through the acquire verbs and Kernel.SynthesizeInstance; the sentinels a frontend branches on (ErrInvalidPackage, ErrWrongKind, ErrMissingRequiredField, ErrMissingModule, ErrMissingName, ErrMissingNamespace, ErrMissingSource, ErrSchemaUnavailable) are declared in opm/errors.

Quality gates

task fmt
task vet
task lint
task test
# or all four
task check

Further reading

  • CONSTITUTION.md — design principles (kernel neutrality, type safety, separation of concerns, SemVer discipline, small batches).
  • openspec/config.yaml — normative constitution source.
  • opmodel.dev/core@v2 — current OPM schema, published as an OCI CUE module (sources live in the workspace core/ repo).
  • docs/getting-started.md — end-to-end embedding walkthrough.
  • docs/design/ — CUE evaluator notes: the v0.17.x closedness regression and its canary, plus historical bug records whose code no longer exists.
  • enhancements/ — frozen historical proposals; the single-build render design is workspace enhancement 0019.
  • adr/ — architecture decision records (ADR-006: one CUE build per artifact; ADR-005: shares-nothing renders; ADR-008: the kernel plans lifecycle and never runs it).
  • CHANGELOG.md — released-version history (generated by release-please).
  • migrations/README.md — migration-documentation policy: per-change fragments, dormant until GA (pre-GA breaking changes are recorded in CHANGELOG.md and the OpenSpec archive).

Directories

Path Synopsis
opm
catalog
Package catalog defines the Catalog type, mirroring the #Catalog definition in the OPM core schema: the contracts a catalog defines (#resources, #traits, #blueprints) beside the transformers that implement them (#transformers).
Package catalog defines the Catalog type, mirroring the #Catalog definition in the OPM core schema: the contracts a catalog defines (#resources, #traits, #blueprints) beside the transformers that implement them (#transformers).
errors
Package errors provides the structured verdict rows and error types of OPM.
Package errors provides the structured verdict rows and error types of OPM.
helper
Package helper is the opt-in convenience boundary of the OPM library.
Package helper is the opt-in convenience boundary of the OPM library.
helper/platformmodule
Package platformmodule generates a platform CUE module from catalog coordinates (enhancement 0019 D5/D13).
Package platformmodule generates a platform CUE module from catalog coordinates (enhancement 0019 D5/D13).
internal/cueenv
Package cueenv builds the environment slice a cue/load or mod/modconfig call consults when the caller wants to override CUE_REGISTRY or CUE_CACHE_DIR for that one operation.
Package cueenv builds the environment slice a cue/load or mod/modconfig call consults when the caller wants to override CUE_REGISTRY or CUE_CACHE_DIR for that one operation.
internal/loader
Package loader is the kernel's one artifact-loading routine: it builds a single CUE package — from a directory or from an in-memory overlay — and runs the OPM artifact shape gate over the result, and it fetches a published artifact of any OPM kind from an OCI registry through CUE's native module machinery (FetchArtifact, with FetchModule the #Module entry over it; ADR-009).
Package loader is the kernel's one artifact-loading routine: it builds a single CUE package — from a directory or from an in-memory overlay — and runs the OPM artifact shape gate over the result, and it fetches a published artifact of any OPM kind from an OCI registry through CUE's native module machinery (FetchArtifact, with FetchModule the #Module entry over it; ADR-009).
internal/registrytest
Package registrytest provides an in-memory OCI registry harness for tests that need catalogs and modules resolvable by import without a live registry.
Package registrytest provides an in-memory OCI registry harness for tests that need catalogs and modules resolvable by import without a live registry.
internal/renderstage
Package renderstage assembles the single-build render module (enhancement 0019 D9): it reads the two committed cue.mod/module.cue resolutions the render inputs carry, promotes them into the render module's dependency list (D13), checks that list for OPM-namespace coverage (the D13 refusal invariant), compares the two committed lists for catalog version skew (D7/D18), stages the generated render module into a directory, and builds it once in a caller-supplied cue.Context (D8).
Package renderstage assembles the single-build render module (enhancement 0019 D9): it reads the two committed cue.mod/module.cue resolutions the render inputs carry, promotes them into the render module's dependency list (D13), checks that list for OPM-namespace coverage (the D13 refusal invariant), compares the two committed lists for catalog version skew (D7/D18), stages the generated render module into a directory, and builds it once in a caller-supplied cue.Context (D8).
internal/schematest
Package schematest is a test-only helper for pointing tests at the workspace-local CUE module cache, and for handing a test a CUE module cache directory to build in.
Package schematest is a test-only helper for pointing tests at the workspace-local CUE module cache, and for handing a test a CUE module cache directory to build in.
internal/sourcetree
Package sourcetree walks, reads, names and writes the source tree a module.Source describes, in both of its modes: on-disk (Overlay nil, the tree is read from Root on the filesystem) and overlay (every file is an entry of Overlay, its bytes keyed by its absolute path under Root).
Package sourcetree walks, reads, names and writes the source tree a module.Source describes, in both of its modes: on-disk (Overlay nil, the tree is read from Root on the filesystem) and overlay (every file is an entry of Overlay, its bytes keyed by its absolute path under Root).
internal/synth
Package synth builds an OPM #ModuleInstance CUE value from typed in-memory inputs: caller-supplied identity (name, namespace, values, labels, annotations) against a module the caller already acquired with its staged source.
Package synth builds an OPM #ModuleInstance CUE value from typed in-memory inputs: caller-supplied identity (name, namespace, values, labels, annotations) against a module the caller already acquired with its staged source.
internal/valuesfile
Package valuesfile renders a values cue.Value as the source of a package file declaring the top-level `values` field.
Package valuesfile renders a values cue.Value as the source of a package file declaring the top-level `values` field.
kernel
Package kernel exposes the OPM runtime as a single struct, Kernel.
Package kernel exposes the OPM runtime as a single struct, Kernel.
module
Package module defines the Module type, mirroring the #Module definition in the OPM core schema.
Package module defines the Module type, mirroring the #Module definition in the OPM core schema.
platform
Package platform defines the Platform and PlatformMetadata types, mirroring the #Platform definition of the OPM core schema.
Package platform defines the Platform and PlatformMetadata types, mirroring the #Platform definition of the OPM core schema.
schema
Package schema is the kernel's single source of truth for OPM schema-side knowledge: CUE paths, metadata types, and the OCI-backed schema loader.
Package schema is the kernel's single source of truth for OPM schema-side knowledge: CUE paths, metadata types, and the OCI-backed schema loader.

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL