v1alpha1

package
v0.4.0 Latest Latest
Warning

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

Go to latest
Published: Aug 3, 2026 License: Apache-2.0 Imports: 16 Imported by: 0

Documentation

Overview

Package v1alpha1 defines the Kubernetes-style API types for all agentregistry resources.

Every resource — Agent, MCPServer, Skill, Prompt, Deployment, Runtime, Model — uses the same envelope: apiVersion + kind + metadata + spec + status. These types are the single wire/storage/API contract propagating from a YAML manifest through the HTTP handler, Go client, service layer, and database row (spec+status as JSONB; metadata columns promoted). No intermediate DTOs, no translation functions.

Typed objects (Agent, MCPServer, etc.) are the preferred handle. RawObject is the un-typed wire envelope used during apply dispatch when the kind is not yet known; use Scheme.Decode / Scheme.DecodeMulti to route into a typed object by kind.

Index

Constants

View Source
const (
	DeploymentOriginAnnotation                = "agentregistry.solo.io/origin"
	DeploymentDiscoveredRuntimeAnnotation     = "agentregistry.solo.io/discovered-runtime"
	DeploymentDiscoveredRuntimeTypeAnnotation = "agentregistry.solo.io/discovered-runtime-type"
	DeploymentOriginManaged                   = "managed"
	DeploymentOriginDiscovered                = "discovered"
)

Deployment origin annotations distinguish registry-managed Deployment rows from provider-discovered rows materialized into the same table.

View Source
const (
	DesiredStateDeployed   = "deployed"
	DesiredStateUndeployed = "undeployed"
)

DeploymentDesiredState lifecycle intents. Empty is equivalent to DesiredStateDeployed.

View Source
const (
	KindAgent      = "Agent"
	KindMCPServer  = "MCPServer"
	KindSkill      = "Skill"
	KindPlugin     = "Plugin"
	KindPrompt     = "Prompt"
	KindDeployment = "Deployment"
	KindRuntime    = "Runtime"
	KindModel      = "Model"
)

Canonical Kind names.

View Source
const (
	ModelAuthStrategyRuntime     = "runtime"
	ModelAuthStrategySecretRef   = "secretRef"
	ModelAuthStrategyPassthrough = "passthrough"
)

Model auth strategies. See ModelAuthConfig.

View Source
const (
	TypeLocal      = "Local"
	TypeKubernetes = "Kubernetes"
)

Built-in runtime type discriminators. Canonical form is CamelCase. Manifests may write Spec.Type in any casing (`local`, `LOCAL`, `Local`); Runtime.Validate looks the input up case-insensitively in KnownRuntimeTypes and rewrites Spec.Type to the canonical CamelCase value at admission, so all downstream consumers compare against these constants with exact-match equality.

View Source
const (
	UpstreamMCPPackageNameMinLen = 1
	UpstreamMCPPackageNameMaxLen = 200
)
View Source
const DNSSubdomainMaxLen = 253

DNSSubdomainMaxLen is the upper length bound for DNS-1123 subdomain values.

View Source
const DNSSubdomainPattern = `^[a-z0-9]([-a-z0-9]{0,61}[a-z0-9])?(\.[a-z0-9]([-a-z0-9]{0,61}[a-z0-9])?)*$`

DNS-1123 subdomain form: lowercase alphanumeric, hyphens, and dots. Must start and end with alphanumeric. Each dot-separated segment is a DNS-1123 label (1-63 chars). Total length 1-253. Matches the rule Kubernetes uses for most resource `metadata.name` fields.

View Source
const DefaultModelName = "default"

DefaultModelName is the conventional namespace-scoped Model selected by a harness Agent Deployment that omits spec.modelRef. Its blank tag resolves the literal "latest" tag, so the complete implicit identity is Model/<deployment namespace>/default@latest.

View Source
const DefaultNamespace = "default"

DefaultNamespace is the namespace used when a caller doesn't supply one (blank metadata.namespace in a YAML apply, for instance). Servers fill missing namespaces with this value so identity is always fully qualified at rest. The string matches the Kubernetes convention for consistency.

View Source
const GroupVersion = "ar.dev/v1alpha1"

GroupVersion is the apiVersion string used by every resource in this package.

View Source
const (
	ModelProviderBedrock = "bedrock"
)

Supported provider families. Expand this enum only when the provider has a working runtime adapter and end-to-end coverage.

View Source
const UpstreamMCPPackageNamePattern = `^[a-zA-Z0-9._/-]+$`

Upstream MCP-ecosystem catalogue name pattern. Accepts identifier-shaped strings: alphanumeric plus `.`, `_`, `-`, `/`. The slash is optional so single-segment names (e.g. `my-mcp`) and reverse-DNS namespace/name forms (e.g. `io.github.modelcontextprotocol/server-fetch`) both validate.

Variables

View Source
var (
	ErrRequiredField       = errors.New("required field missing")
	ErrInvalidFormat       = errors.New("invalid format")
	ErrInvalidTag          = errors.New("invalid tag")
	ErrInvalidURL          = errors.New("invalid url")
	ErrInvalidLabel        = errors.New("invalid label")
	ErrInvalidRef          = errors.New("invalid resource reference")
	ErrUnknownRuntimeType  = errors.New("unknown runtime type")
	ErrInvalidDesiredState = errors.New("invalid deployment desired state")
	// ErrDanglingRef is returned by ResolverFunc implementations when the
	// referenced resource does not exist. Tests + callers identify
	// dangling references via errors.Is(err, ErrDanglingRef).
	ErrDanglingRef = errors.New("referenced resource not found")
)

Validation error sentinels. All validation errors are wrapped in a FieldError (see below) so callers can introspect the failing path.

View Source
var Default = NewScheme()

Default is the package-level Scheme. Built-in and extension kinds register onto it through MustRegisterKind at init.

View Source
var DefaultKindRegistry = NewKindRegistry()

DefaultKindRegistry is the package-level registry used by the app, stores, controller sources, and generic clients. Kind packages register here at init.

View Source
var KnownModelProviders = map[string]struct {
	AmbientIdentity bool
}{
	ModelProviderBedrock: {AmbientIdentity: true},
}

KnownModelProviders is the set of provider families the validator recognizes. Keys are the canonical lowercase provider names. The value records whether the provider supports ambient runtime identity. Add a provider only after its runtime adapter and end-to-end coverage exist.

View Source
var KnownRuntimeTypes = map[string]struct{}{
	TypeLocal:      {},
	TypeKubernetes: {},
}

KnownRuntimeTypes is the set of canonical Runtime spec.type values the generic validator recognizes. Keys are stored in their canonical CamelCase form. Validate() does the case-insensitive admission match against this set and rewrites Spec.Type to the canonical form, so downstream code can compare Spec.Type against the constants with exact-match equality. Downstream builds may register additional canonical values at init by inserting into this map.

View Source
var UpstreamMCPPackageNameRegex = regexp.MustCompile(UpstreamMCPPackageNamePattern)

Functions

func Encode

func Encode(v any) ([]byte, error)

Encode marshals a typed envelope (or any value) to YAML. It's a convenience wrapper around sigs.k8s.io/yaml.Marshal so callers don't need to import the yaml library directly.

func EncodeJSON

func EncodeJSON(v any) ([]byte, error)

EncodeJSON marshals a typed envelope to canonical JSON.

func EnvelopeFromRaw

func EnvelopeFromRaw[T Object](newObj func() T, raw *RawObject, kind string) (T, error)

EnvelopeFromRaw materializes a typed envelope T from a RawObject. It stamps TypeMeta from the package-level GroupVersion + supplied kind, copies ObjectMeta + Status, and unmarshals the raw spec JSON into the typed Spec field. newObj must return a fresh zero value on each call.

Shared helper used by every surface that reads RawObject rows (HTTP resource handler, MCP bridge, etc.) so every API surface hands back an identically-shaped envelope.

func IsContentRegistryKind

func IsContentRegistryKind(kind string) bool

IsContentRegistryKind reports whether a kind belongs to the tagged content-registry bucket.

func IsDiscoveredDeployment

func IsDiscoveredDeployment(deployment *Deployment) bool

IsDiscoveredDeployment reports whether a Deployment row was materialized from provider discovery rather than authored as registry-managed desired state.

func IsTaggedArtifactKind

func IsTaggedArtifactKind(kind string) bool

IsTaggedArtifactKind reports whether refs to kind may use tag pinning and whether the private store behavior keys rows by namespace/name/tag.

func MarshalStatusForStorage

func MarshalStatusForStorage(s Status) ([]byte, error)

MarshalStatusForStorage serializes a Status to JSON suitable for writing to the status JSONB column. Routed through the storage shapes so storage-only fields (if any are added later) survive the round trip independently of the wire schema.

func MustRegisterKind

func MustRegisterKind[T Object, S any](kind string, opts ...KindOption)

MustRegisterKind is RegisterKind that panics on error. Use at init.

func MustRegisterPlural

func MustRegisterPlural(kind, plural string)

MustRegisterPlural is RegisterPlural that panics on error. Use at init.

func PluralFor

func PluralFor(kind string) string

PluralFor returns the route-plural for a Kind (e.g. "mcpservers" for KindMCPServer). By default it mirrors the convention the generic resource handler uses when cfg.PluralKind is empty: ToLower(kind) + "s". Downstream builds can override irregular plurals with RegisterPlural.

func RegisterKind

func RegisterKind[T Object, S any](kind string, opts ...KindOption) error

RegisterKind registers kind metadata and wires the package Default scheme.

func RegisterPlural

func RegisterPlural(kind, plural string) error

RegisterPlural associates kind with the route plural used by the generic resource handlers. It is intended for downstream kinds whose plural does not match the default strings.ToLower(kind)+"s" convention.

func RegisteredKinds

func RegisteredKinds() []string

RegisteredKinds returns canonical names for every registered kind.

func ResolveObjectRefs

func ResolveObjectRefs(ctx context.Context, obj Object, resolver ResolverFunc) error

ResolveObjectRefs validates cross-resource refs when obj carries them.

func StatusPatcher

func StatusPatcher(mutate func(*Status)) func(current json.RawMessage) (json.RawMessage, error)

StatusPatcher adapts a typed Status mutator into the opaque-bytes signature that v1alpha1store.PatchOpts.Status / Store.PatchStatus expect. Callers that use the typed v1alpha1.Status schema wrap their SetCondition / ObservedGeneration logic here:

store.PatchStatus(ctx, ns, name, tag, v1alpha1.StatusPatcher(
    func(s *v1alpha1.Status) {
        s.ObservedGeneration = gen
        s.SetCondition(v1alpha1.Condition{Type: "Ready", Status: v1alpha1.ConditionTrue})
    },
))

Kinds with a custom status shape skip this helper and return their own marshaled bytes directly from the PatchStatus callback.

func UnmarshalStatusFromStorage

func UnmarshalStatusFromStorage(data []byte, s *Status) error

UnmarshalStatusFromStorage is the read-side inverse of MarshalStatusForStorage: decode a status JSONB payload back into a live Status struct, including the internal-only ObservedGeneration fields.

func ValidateObject

func ValidateObject(obj Object) error

ValidateObject runs structural validation when obj opts into it.

func ValidateObjectRegistries

func ValidateObjectRegistries(ctx context.Context, obj Object, v RegistryValidatorFunc) error

ValidateObjectRegistries validates package registries when obj exposes them.

Types

type Agent

type Agent struct {
	TypeMeta `json:",inline" yaml:",inline"`
	Metadata ObjectMeta `json:"metadata" yaml:"metadata"`
	Spec     AgentSpec  `json:"spec" yaml:"spec"`
	Status   Status     `json:"status,omitzero" yaml:"status,omitempty"`
}

Agent is the typed envelope for kind=Agent resources.

func (*Agent) GetMetadata

func (a *Agent) GetMetadata() *ObjectMeta

func (*Agent) MarshalSpec

func (a *Agent) MarshalSpec() (json.RawMessage, error)

func (*Agent) MarshalStatus

func (a *Agent) MarshalStatus() (json.RawMessage, error)

func (*Agent) ResolveRefs

func (a *Agent) ResolveRefs(ctx context.Context, resolver ResolverFunc) error

ResolveRefs checks every ResourceRef in the Agent's spec exists by calling resolver. Returns nil if all refs resolve (or resolver is nil), otherwise a FieldErrors listing each dangling ref.

func (*Agent) SetMetadata

func (a *Agent) SetMetadata(meta ObjectMeta)

func (*Agent) UnmarshalSpec

func (a *Agent) UnmarshalSpec(data json.RawMessage) error

func (*Agent) UnmarshalStatus

func (a *Agent) UnmarshalStatus(data json.RawMessage) error

func (*Agent) Validate

func (a *Agent) Validate() error

Validate runs structural validation on the Agent envelope: ObjectMeta format + Spec-level rules. No network I/O; ref existence is covered by ResolveRefs.

type AgentProtocol

type AgentProtocol string

AgentProtocol is the application protocol exposed by an Agent source.

const (
	AgentProtocolA2A  AgentProtocol = "A2A"
	AgentProtocolHTTP AgentProtocol = "HTTP"
)

type AgentSource

type AgentSource struct {
	// Image is the OCI container image reference that runs the agent.
	// Format: <registry>/<name>:<tag> (e.g. ghcr.io/owner/agent:1.0.0).
	Image string `json:"image,omitempty" yaml:"image,omitempty"`

	// Repository links to the source code the image was built from.
	Repository *Repository `json:"repository,omitempty" yaml:"repository,omitempty"`

	// Protocol is the application protocol spoken by every runnable form of the
	// agent, whether built from Repository or supplied as Image. When omitted,
	// A2A is inferred as the default.
	Protocol *AgentProtocol `json:"protocol,omitempty" yaml:"protocol,omitempty" enum:"A2A,HTTP"`
}

AgentSource is the distribution origin of a bring-your-own container/source agent. Harness-based deployments select a compatible harness from AgentSpec.CompatibleHarnesses at Deployment time.

type AgentSpec

type AgentSpec struct {
	// Core fields.
	Title       string `json:"title,omitempty" yaml:"title,omitempty"`
	Description string `json:"description,omitempty" yaml:"description,omitempty"`

	// ModelProvider and ModelName are retained for one release so existing
	// Agent resources continue to decode and round-trip without data loss.
	//
	// Deprecated: these fields do not select or configure a runtime model.
	// New and migrated Deployments must use spec.modelRef; distributions may
	// temporarily preserve Deployment MODEL_PROVIDER / MODEL_NAME environment
	// values when modelRef is omitted.
	ModelProvider string `json:"modelProvider,omitempty" yaml:"modelProvider,omitempty" deprecated:"true"`
	ModelName     string `json:"modelName,omitempty" yaml:"modelName,omitempty" deprecated:"true"`

	// Source declares where the agent comes from — Image (the runtime
	// container) and/or Repository (the source code).
	Source *AgentSource `json:"source,omitempty" yaml:"source,omitempty"`

	// CompatibleHarnesses declares which coding harnesses this Agent can run
	// under. The Deployment selects the concrete harness type for a
	// rollout; Agent remains the portable compatibility contract.
	CompatibleHarnesses []HarnessCompatibility `json:"compatibleHarnesses,omitempty" yaml:"compatibleHarnesses,omitempty"`

	// Composition — top-level, harness-agnostic references to what the agent
	// is assembled from. The selected Deployment harness materializes what it
	// supports and drops-with-warning the rest (capability matrix). Plugins,
	// Skills, and Instructions require compatibleHarnesses because a prebuilt
	// Image cannot consume them by itself. MCPServers flow to harness runtimes
	// and remain available to any other runtime that supports MCP. Each ref's
	// Kind defaults to the field's resource kind; empty Tag means "resolve
	// latest at reference time".
	Plugins      []ResourceRef `json:"plugins,omitempty" yaml:"plugins,omitempty"`
	Skills       []ResourceRef `json:"skills,omitempty" yaml:"skills,omitempty"`
	Instructions *ResourceRef  `json:"instructions,omitempty" yaml:"instructions,omitempty"`
	MCPServers   []ResourceRef `json:"mcpServers,omitempty" yaml:"mcpServers,omitempty"`
}

AgentSpec is the agent resource's declarative body.

References to other resources (MCP servers) are pure ResourceRefs — no inline runtime configuration. To deploy an agent with a specific MCP server wired in, define a top-level MCPServer resource and reference it here.

func (AgentSpec) HasLegacyModelConfiguration

func (s AgentSpec) HasLegacyModelConfiguration() bool

HasLegacyModelConfiguration reports whether an Agent still carries the one-release compatibility fields. The fields are intentionally non-authoritative; callers should use this only for warnings and migration inventory.

type CommandEntry

type CommandEntry struct {
	Source       string   `json:"source,omitempty" yaml:"source,omitempty"`
	Content      string   `json:"content,omitempty" yaml:"content,omitempty"`
	Description  string   `json:"description,omitempty" yaml:"description,omitempty"`
	ArgumentHint string   `json:"argumentHint,omitempty" yaml:"argumentHint,omitempty"`
	Model        string   `json:"model,omitempty" yaml:"model,omitempty"`
	AllowedTools []string `json:"allowedTools,omitempty" yaml:"allowedTools,omitempty"`
}

CommandEntry is one named command in the object form.

type CommandsField

type CommandsField struct {
	Paths *PathOrPaths
	Map   map[string]CommandEntry
}

CommandsField models `commands`: paths (string|array) and/or an object map of named command entries.

func (CommandsField) MarshalJSON

func (c CommandsField) MarshalJSON() ([]byte, error)

func (*CommandsField) UnmarshalJSON

func (c *CommandsField) UnmarshalJSON(data []byte) error

type Condition

type Condition struct {
	Type               string          `json:"type" yaml:"type"`
	Status             ConditionStatus `json:"status" yaml:"status"`
	Reason             string          `json:"reason,omitempty" yaml:"reason,omitempty"`
	Message            string          `json:"message,omitempty" yaml:"message,omitempty"`
	LastTransitionTime time.Time       `json:"lastTransitionTime,omitzero" yaml:"lastTransitionTime,omitempty"`
	ObservedGeneration int64           `json:"-" yaml:"-"`
}

Condition describes one facet of a resource's observed state. Modeled after Kubernetes v1.Condition: Type is the named condition (e.g. "Ready", "Validated", "Published"); Status is True/False/Unknown; Reason is a machine-readable CamelCase token; Message is a human-readable explanation; LastTransitionTime is when Status last flipped.

ObservedGeneration is the spec generation this condition was derived from. Like ObjectMeta.Generation it is an internal reconciler convergence signal: kept on the struct for controllers to read, persisted in storage, but hidden from the wire so the user-facing metadata surface stays minimal.

type ConditionStatus

type ConditionStatus string

ConditionStatus values, matching Kubernetes apimachinery/pkg/apis/meta/v1.

const (
	ConditionTrue    ConditionStatus = "True"
	ConditionFalse   ConditionStatus = "False"
	ConditionUnknown ConditionStatus = "Unknown"
)

type Deployment

type Deployment struct {
	TypeMeta `json:",inline" yaml:",inline"`
	Metadata ObjectMeta     `json:"metadata" yaml:"metadata"`
	Spec     DeploymentSpec `json:"spec" yaml:"spec"`
	Status   Status         `json:"status,omitzero" yaml:"status,omitempty"`
}

Deployment is the typed envelope for kind=Deployment resources.

Deployment's metadata.name is independent from the thing it deploys (Spec.TemplateRef), so multiple Deployments can target the same Agent or MCPServer with different user-chosen names, runtimes, and configs. Identity is namespace/name; the deployed content is pinned separately through spec.targetRef.tag.

func (*Deployment) GetMetadata

func (d *Deployment) GetMetadata() *ObjectMeta

func (*Deployment) MarshalSpec

func (d *Deployment) MarshalSpec() (json.RawMessage, error)

func (*Deployment) MarshalStatus

func (d *Deployment) MarshalStatus() (json.RawMessage, error)

func (*Deployment) ResolveRefs

func (d *Deployment) ResolveRefs(ctx context.Context, resolver ResolverFunc) error

ResolveRefs checks that TargetRef, RuntimeRef, the effective ModelRef, and every entry in DeploymentRefs resolve. A harness Agent Deployment that omits ModelRef resolves Model/default@latest in its own namespace. The referenced objects must live in the referenced namespace; when ref.Namespace is blank on the wire we inherit the Deployment's own namespace (mirroring how kubectl treats blank metadata.namespace).

func (*Deployment) SetMetadata

func (d *Deployment) SetMetadata(meta ObjectMeta)

func (*Deployment) UnmarshalSpec

func (d *Deployment) UnmarshalSpec(data json.RawMessage) error

func (*Deployment) UnmarshalStatus

func (d *Deployment) UnmarshalStatus(data json.RawMessage) error

func (*Deployment) Validate

func (d *Deployment) Validate() error

Validate runs Deployment's structural checks.

Deployment is unversioned: it's a runtime binding ("deploy resource X to runtime Y"). The thing being deployed carries its own tag via spec.targetRef.tag; when that tag is omitted, reference resolution uses the literal "latest" tag. Deployment's public identity is (namespace, name).

type DeploymentHarness

type DeploymentHarness struct {
	// Type is the selected harness family, e.g. "claude-code", "codex".
	Type string `json:"type" yaml:"type"`

	// PermissionMode controls the harness tool-permission posture, e.g.
	// "default", "acceptEdits", "bypassPermissions". Empty defaults to
	// "bypassPermissions" for headless harness runtimes (no interactive
	// approval is possible); subject to security review.
	PermissionMode string `json:"permissionMode,omitempty" yaml:"permissionMode,omitempty"`
}

DeploymentHarness selects the concrete harness to run for one Deployment. The target Agent declares compatibility; the Runtime supplies concrete runner support such as container images.

type DeploymentRef

type DeploymentRef struct {
	Namespace string `json:"namespace,omitempty" yaml:"namespace,omitempty"`
	Name      string `json:"name" yaml:"name"`
}

DeploymentRef is a typed reference to another Deployment resource. Kind is implicit (always Deployment) and Tag is omitted because Deployment is a mutable-object kind keyed by namespace/name.

Namespace is optional: blank means "same namespace as the referencing Deployment".

type DeploymentSpec

type DeploymentSpec struct {
	TargetRef  ResourceRef `json:"targetRef" yaml:"targetRef"`
	RuntimeRef ResourceRef `json:"runtimeRef" yaml:"runtimeRef"`
	// ModelRef selects the tagged Model for this Deployment. When omitted from
	// a harness Agent Deployment, it defaults to Model/default@latest in the
	// Deployment namespace. It remains optional with no implicit selection for
	// non-harness Agent and MCPServer Deployments. Provider, endpoint, and auth
	// configuration remain on the referenced Model.
	ModelRef     *ModelRef `json:"modelRef,omitempty" yaml:"modelRef,omitempty"`
	DesiredState string    `json:"desiredState,omitempty" yaml:"desiredState,omitempty"`
	// DeploymentRefs declaratively binds this Deployment to other
	// Deployments — e.g. an Agent Deployment binding to the MCPServer
	// Deployments whose status should feed its runtime config. Stored
	// and structurally validated; binding semantics are owned by the
	// kind's reconciler.
	DeploymentRefs []DeploymentRef   `json:"deploymentRefs,omitempty" yaml:"deploymentRefs,omitempty"`
	Env            map[string]string `json:"env,omitempty" yaml:"env,omitempty"`
	// EnvFrom sources environment variables for the deployed workload from
	// references the runtime resolves. Only Secret references are supported
	// for MCPServer deployments. Explicit Env entries win over keys sourced
	// via EnvFrom.
	EnvFrom       []EnvFromSource `json:"envFrom,omitempty" yaml:"envFrom,omitempty"`
	RuntimeConfig map[string]any  `json:"runtimeConfig,omitempty" yaml:"runtimeConfig,omitempty"`
	// Harness selects a compatible harness for Agent deployments and configures
	// rollout-specific harness policy. Omitted for BYO image/source Agent
	// deployments and MCPServer deployments.
	Harness *DeploymentHarness `json:"harness,omitempty" yaml:"harness,omitempty"`
}

DeploymentSpec is the deployment resource's declarative body.

TargetRef is required and must name a top-level Agent or MCPServer. The referenced resource's spec is the source of truth for what to run; this Deployment contributes only runtime overrides (env, runtimeConfig) and lifecycle intent (desiredState).

RuntimeRef is required and must name a top-level Runtime. The Runtime resolves how/where the target is executed (local Docker, Kubernetes, etc.).

func (*DeploymentSpec) EffectiveModelRef

func (s *DeploymentSpec) EffectiveModelRef() *ModelRef

EffectiveModelRef returns the explicit ModelRef or the conventional namespace-scoped default for a harness Agent Deployment. It returns nil for non-harness Agent and MCPServer Deployments that omit ModelRef.

type EnvFromSource

type EnvFromSource struct {
	// SecretRef names a Secret whose keys become environment variables in
	// the deployed workload. The Secret is runtime-local (e.g. for Kubernetes,
	// a Secret in the runtime's namespace), not a registry Secret.
	SecretRef *SecretEnvSource `json:"secretRef,omitempty" yaml:"secretRef,omitempty"`
}

EnvFromSource selects one external source of environment variables. Exactly one member must be set. Only SecretRef is supported.

type FieldError

type FieldError struct {
	Path  string
	Cause error
}

FieldError pins a validation failure to a dot-path inside the object. Examples: "metadata.name", "spec.packages[0].identifier", "spec.mcpServers[2]".

func (FieldError) Error

func (fe FieldError) Error() string

func (FieldError) Unwrap

func (fe FieldError) Unwrap() error

type FieldErrors

type FieldErrors []FieldError

FieldErrors is the accumulated result of a validation pass. A nil or empty FieldErrors means success. It satisfies error so callers can return it directly.

func ValidateObjectMeta

func ValidateObjectMeta(m ObjectMeta) FieldErrors

ValidateObjectMeta checks the namespace/name format and label shape. Server-managed fields (CreatedAt, UpdatedAt, DeletionTimestamp) are ignored. Content resources use metadata.tag for identity; mutable object kinds expose only namespace/name.

Taggable artifact kinds and mutable object kinds call this same validator because ObjectMeta exposes one public shape for both identities.

func (*FieldErrors) Append

func (fe *FieldErrors) Append(path string, cause error)

Append records a new field error under pathPrefix+path. If cause is nil, it's a no-op.

func (FieldErrors) Error

func (fe FieldErrors) Error() string

type GetterFunc

type GetterFunc func(ctx context.Context, ref ResourceRef) (Object, error)

GetterFunc fetches a ResourceRef as a typed Object. It returns ErrDanglingRef when the referenced object is missing; other errors propagate as-is. Used by reconcilers / runtime adapters that need the target's Spec (not just an existence check) — for example, the local adapter walking an AgentSpec.MCPServers entry to build agentgateway upstream config.

type HTTPHeader

type HTTPHeader struct {
	Name  string `json:"name" yaml:"name"`
	Value string `json:"value,omitempty" yaml:"value,omitempty"`
}

HTTPHeader is an HTTP header sent on requests to a remote MCP server.

type HarnessCompatibility

type HarnessCompatibility struct {
	// Type is the harness family, e.g. "claude-code", "codex", "opencode".
	Type string `json:"type" yaml:"type"`
}

HarnessCompatibility declares one harness family this Agent can run under. Rollout policy selection lives on Deployment so the same Agent can be rolled out with different compatible harnesses.

type HookEntry

type HookEntry struct {
	Type string `json:"type" yaml:"type"`

	Command string `json:"command,omitempty" yaml:"command,omitempty"`
	Shell   string `json:"shell,omitempty" yaml:"shell,omitempty"`

	Prompt string `json:"prompt,omitempty" yaml:"prompt,omitempty"`
	Model  string `json:"model,omitempty" yaml:"model,omitempty"`

	URL            string            `json:"url,omitempty" yaml:"url,omitempty"`
	Headers        map[string]string `json:"headers,omitempty" yaml:"headers,omitempty"`
	AllowedEnvVars []string          `json:"allowedEnvVars,omitempty" yaml:"allowedEnvVars,omitempty"`

	Server string          `json:"server,omitempty" yaml:"server,omitempty"`
	Tool   string          `json:"tool,omitempty" yaml:"tool,omitempty"`
	Input  json.RawMessage `json:"input,omitempty" yaml:"input,omitempty"`

	If string `json:"if,omitempty" yaml:"if,omitempty"`
	// Timeout is a pointer so an explicit "timeout": 0 (disable) round-trips
	// losslessly — a float64 with omitempty would silently drop the zero.
	Timeout       *float64 `json:"timeout,omitempty" yaml:"timeout,omitempty"`
	StatusMessage string   `json:"statusMessage,omitempty" yaml:"statusMessage,omitempty"`
	Once          *bool    `json:"once,omitempty" yaml:"once,omitempty"`
	Async         *bool    `json:"async,omitempty" yaml:"async,omitempty"`
	AsyncRewake   *bool    `json:"asyncRewake,omitempty" yaml:"asyncRewake,omitempty"`
}

HookEntry is one hook action discriminated by Type (command|prompt|agent| http|mcp_tool). Variant fields are flattened with omitempty; per-type required/forbidden sets are enforced in plugin_validate.go.

type HookMatcherGroup

type HookMatcherGroup struct {
	Matcher string      `json:"matcher,omitempty" yaml:"matcher,omitempty"`
	Hooks   []HookEntry `json:"hooks" yaml:"hooks"`
}

HookMatcherGroup is one matcher group under an event.

type HooksField

type HooksField struct {
	Path   string
	Events map[string][]HookMatcherGroup
	Raw    json.RawMessage
}

HooksField models `hooks`: a `./*.json` path (Path), an inline event->matcher object (Events), or an array form (kept Raw for lossless round-trip; read the derived PluginInventory for the array form's risk surface).

func (HooksField) MarshalJSON

func (h HooksField) MarshalJSON() ([]byte, error)

func (*HooksField) UnmarshalJSON

func (h *HooksField) UnmarshalJSON(data []byte) error

type KindDescriptor

type KindDescriptor struct {
	Kind       string
	SpecSample any
	NewObject  func() any
	Plural     string
	Table      string
	Storage    KindStorage
}

KindDescriptor is the single registration record for a v1alpha1 kind. Scheme decoding, store construction, plural routing, and source projection all share this metadata.

func KindDescriptorFor

func KindDescriptorFor(kind string) (KindDescriptor, bool)

KindDescriptorFor returns descriptor for kind.

func KindDescriptors

func KindDescriptors() []KindDescriptor

KindDescriptors returns descriptors for every registered kind.

type KindOption

type KindOption func(*KindDescriptor)

KindOption customizes RegisterKind defaults.

func WithMutableObjectStorage

func WithMutableObjectStorage() KindOption

WithMutableObjectStorage marks the kind as namespace/name mutable state.

func WithPlural

func WithPlural(plural string) KindOption

WithPlural sets the route plural for the kind.

type KindRegistry

type KindRegistry struct {
	// contains filtered or unexported fields
}

KindRegistry owns registered v1alpha1 kind metadata.

func NewKindRegistry

func NewKindRegistry() *KindRegistry

NewKindRegistry constructs an empty kind registry.

func (*KindRegistry) Descriptors

func (r *KindRegistry) Descriptors() []KindDescriptor

Descriptors returns registered descriptors in deterministic kind order.

func (*KindRegistry) Kinds

func (r *KindRegistry) Kinds() []string

Kinds returns registered canonical kind names in deterministic order.

func (*KindRegistry) Lookup

func (r *KindRegistry) Lookup(kind string) (KindDescriptor, bool)

Lookup returns descriptor for kind.

func (*KindRegistry) Register

func (r *KindRegistry) Register(descriptor KindDescriptor) error

Register adds descriptor to the registry.

func (*KindRegistry) UpdatePlural

func (r *KindRegistry) UpdatePlural(kind, plural string) error

UpdatePlural updates or records the route plural for kind.

type KindStorage

type KindStorage string

KindStorage describes the private persistence semantics attached to a v1alpha1 kind.

const (
	KindStorageTaggedArtifact KindStorage = "TaggedArtifact"
	KindStorageMutableObject  KindStorage = "MutableObject"
)

type LSPServerEntry

type LSPServerEntry struct {
	Command               string            `json:"command" yaml:"command"`
	Args                  []string          `json:"args,omitempty" yaml:"args,omitempty"`
	ExtensionToLanguage   map[string]string `json:"extensionToLanguage" yaml:"extensionToLanguage"`
	Transport             string            `json:"transport,omitempty" yaml:"transport,omitempty"`
	Env                   map[string]string `json:"env,omitempty" yaml:"env,omitempty"`
	InitializationOptions json.RawMessage   `json:"initializationOptions,omitempty" yaml:"initializationOptions,omitempty"`
	Settings              json.RawMessage   `json:"settings,omitempty" yaml:"settings,omitempty"`
	WorkspaceFolder       string            `json:"workspaceFolder,omitempty" yaml:"workspaceFolder,omitempty"`
	StartupTimeout        *int              `json:"startupTimeout,omitempty" yaml:"startupTimeout,omitempty"`
	MaxRestarts           *int              `json:"maxRestarts,omitempty" yaml:"maxRestarts,omitempty"`
}

LSPServerEntry is one inline LSP server config.

type LSPServersField

type LSPServersField struct {
	Path    string
	Servers map[string]LSPServerEntry
	Raw     json.RawMessage
}

LSPServersField models `lspServers`: a path string, an inline name->config object, or an array form (Raw).

func (LSPServersField) MarshalJSON

func (f LSPServersField) MarshalJSON() ([]byte, error)

func (*LSPServersField) UnmarshalJSON

func (f *LSPServersField) UnmarshalJSON(data []byte) error

type MCPArgument

type MCPArgument struct {
	Type  MCPArgumentType `json:"type" yaml:"type"`
	Name  string          `json:"name,omitempty" yaml:"name,omitempty"`
	Value string          `json:"value,omitempty" yaml:"value,omitempty"`
}

MCPArgument is one command-line argument.

type MCPArgumentType

type MCPArgumentType string
const (
	MCPArgumentTypePositional MCPArgumentType = "positional"
	MCPArgumentTypeNamed      MCPArgumentType = "named"
)

type MCPKeyValueInput

type MCPKeyValueInput struct {
	Name       string `json:"name" yaml:"name"`
	Value      string `json:"value,omitempty" yaml:"value,omitempty"`
	IsRequired bool   `json:"isRequired,omitempty" yaml:"isRequired,omitempty"`
}

MCPKeyValueInput is one declared environment variable.

type MCPPackage

type MCPPackage struct {
	Origin    MCPPackageOrigin  `json:"origin" yaml:"origin"`
	Launch    *MCPPackageLaunch `json:"launch,omitempty" yaml:"launch,omitempty"`
	Transport MCPTransport      `json:"transport" yaml:"transport"`
}

MCPPackage is a runnable distribution of an MCP server, grouped by concern: Origin (what to fetch), Launch (how to start it), Transport (how to talk to it).

type MCPPackageLaunch

type MCPPackageLaunch struct {
	Command string             `json:"command,omitempty" yaml:"command,omitempty"`
	Args    []MCPArgument      `json:"args,omitempty" yaml:"args,omitempty"`
	Env     []MCPKeyValueInput `json:"env,omitempty" yaml:"env,omitempty"`
}

MCPPackageLaunch declares how to start the fetched package. If Launch is nil, the resolver derives Command and Args from Origin.Type defaults (npm → "npx -y <id>@<ver>"; pypi → "uvx <id>==<ver>"; oci → image entrypoint). If Launch is set, the manifest owns Command and Args verbatim — no implicit identifier injection. Command may be empty only for oci.

type MCPPackageOrigin

type MCPPackageOrigin struct {
	Type       MCPPackageOriginType `json:"type" yaml:"type"`
	Identifier string               `json:"identifier" yaml:"identifier"`

	NPM  *MCPPackageOriginNPM  `json:"npm,omitempty"  yaml:"npm,omitempty"`
	PyPI *MCPPackageOriginPyPI `json:"pypi,omitempty" yaml:"pypi,omitempty"`
	OCI  *MCPPackageOriginOCI  `json:"oci,omitempty"  yaml:"oci,omitempty"`
}

MCPPackageOrigin identifies the package and where to fetch it. The Type discriminator selects which per-type sub-struct must be set; exactly one of NPM/PyPI/OCI is non-nil, matching Type.

type MCPPackageOriginNPM

type MCPPackageOriginNPM struct {
	Version    string `json:"version" yaml:"version"`
	Mirror     string `json:"mirror,omitempty" yaml:"mirror,omitempty"`
	ServerName string `json:"serverName" yaml:"serverName"`
}

MCPPackageOriginNPM holds npm-specific fetch inputs.

type MCPPackageOriginOCI

type MCPPackageOriginOCI struct {
	ServerName string `json:"serverName" yaml:"serverName"`
}

MCPPackageOriginOCI holds oci-specific fetch inputs. Version is encoded in Identifier (e.g. "ghcr.io/foo/bar:1.0.0" or "...@sha256:..."); bare image refs that would silently resolve `:latest` are rejected by the validator.

type MCPPackageOriginPyPI

type MCPPackageOriginPyPI struct {
	Version    string `json:"version" yaml:"version"`
	Mirror     string `json:"mirror,omitempty" yaml:"mirror,omitempty"`
	ServerName string `json:"serverName" yaml:"serverName"`
}

MCPPackageOriginPyPI holds pypi-specific fetch inputs.

type MCPPackageOriginType

type MCPPackageOriginType string
const (
	MCPPackageOriginTypeNPM  MCPPackageOriginType = "npm"
	MCPPackageOriginTypePyPI MCPPackageOriginType = "pypi"
	MCPPackageOriginTypeOCI  MCPPackageOriginType = "oci"
)

type MCPRemote

type MCPRemote struct {
	Type    string       `json:"type" yaml:"type"`
	URL     string       `json:"url" yaml:"url"`
	Headers []HTTPHeader `json:"headers,omitempty" yaml:"headers,omitempty"`
}

MCPRemote describes a pre-running remote MCP server that the registry does not deploy. Distinct from MCPTransport (used inside MCPPackage to describe a deployable package's transport) because remote headers carry only static name/value pairs - no templating.

type MCPServer

type MCPServer struct {
	TypeMeta `json:",inline" yaml:",inline"`
	Metadata ObjectMeta    `json:"metadata" yaml:"metadata"`
	Spec     MCPServerSpec `json:"spec" yaml:"spec"`
	Status   Status        `json:"status,omitzero" yaml:"status,omitempty"`
}

MCPServer is the typed envelope for kind=MCPServer resources.

func (*MCPServer) GetMetadata

func (m *MCPServer) GetMetadata() *ObjectMeta

func (*MCPServer) MarshalSpec

func (m *MCPServer) MarshalSpec() (json.RawMessage, error)

func (*MCPServer) MarshalStatus

func (m *MCPServer) MarshalStatus() (json.RawMessage, error)

func (*MCPServer) SetMetadata

func (m *MCPServer) SetMetadata(meta ObjectMeta)

func (*MCPServer) UnmarshalSpec

func (m *MCPServer) UnmarshalSpec(data json.RawMessage) error

func (*MCPServer) UnmarshalStatus

func (m *MCPServer) UnmarshalStatus(data json.RawMessage) error

func (*MCPServer) Validate

func (m *MCPServer) Validate() error

Validate runs structural validation on the MCPServer envelope.

func (*MCPServer) ValidateRegistries

func (m *MCPServer) ValidateRegistries(ctx context.Context, v RegistryValidatorFunc) error

ValidateRegistries on *MCPServer dispatches the bundled MCPPackage's Origin to the caller-supplied per-registry validator.

type MCPServerEntry

type MCPServerEntry struct {
	Type    string            `json:"type,omitempty" yaml:"type,omitempty"`
	Command string            `json:"command,omitempty" yaml:"command,omitempty"`
	Args    []string          `json:"args,omitempty" yaml:"args,omitempty"`
	Env     map[string]string `json:"env,omitempty" yaml:"env,omitempty"`

	URL           string            `json:"url,omitempty" yaml:"url,omitempty"`
	Headers       map[string]string `json:"headers,omitempty" yaml:"headers,omitempty"`
	HeadersHelper string            `json:"headersHelper,omitempty" yaml:"headersHelper,omitempty"`
	OAuth         *MCPServerOAuth   `json:"oauth,omitempty" yaml:"oauth,omitempty"`
}

MCPServerEntry is one inline MCP server config (stdio|sse|http|ws).

type MCPServerOAuth

type MCPServerOAuth struct {
	ClientID string `json:"clientId,omitempty" yaml:"clientId,omitempty"`
	// Pointer so an explicit callbackPort:0 round-trips (omitempty would drop it).
	CallbackPort          *int     `json:"callbackPort,omitempty" yaml:"callbackPort,omitempty"`
	AuthServerMetadataURL string   `json:"authServerMetadataUrl,omitempty" yaml:"authServerMetadataUrl,omitempty"`
	Scopes                []string `json:"scopes,omitempty" yaml:"scopes,omitempty"`
}

MCPServerOAuth is the sse/http oauth sub-block.

type MCPServerSource

type MCPServerSource struct {
	// Package is the runnable distribution (stdio binary, container image,
	// npm package, etc.) of this MCP server.
	Package *MCPPackage `json:"package,omitempty" yaml:"package,omitempty"`

	// Repository links to the source code the package was built from.
	Repository *Repository `json:"repository,omitempty" yaml:"repository,omitempty"`
}

MCPServerSource is the distribution origin of a bundled MCP server — either a published artifact (Package) or a source repository the registry builds from.

type MCPServerSpec

type MCPServerSpec struct {
	Title       string `json:"title,omitempty" yaml:"title,omitempty"`
	Description string `json:"description,omitempty" yaml:"description,omitempty"`

	// Source declares where the bundled MCP server comes from — Package (the
	// runnable distribution) and/or Repository (the source code).
	Source *MCPServerSource `json:"source,omitempty" yaml:"source,omitempty"`

	// Remote declares a remote MCP server instead of a bundled one. These are pre-existing
	// MCP servers that the registry does not deploy but can be referenced by Agents.
	Remote *MCPRemote `json:"remote,omitempty" yaml:"remote,omitempty"`
}

MCPServerSpec is the MCP server's declarative body.

type MCPServersField

type MCPServersField struct {
	Path    string
	Servers map[string]MCPServerEntry
	Raw     json.RawMessage
}

MCPServersField models `mcpServers`: a path/MCPB string (Path), an inline name->config object (Servers), or an array form (Raw).

func (MCPServersField) MarshalJSON

func (f MCPServersField) MarshalJSON() ([]byte, error)

func (*MCPServersField) UnmarshalJSON

func (f *MCPServersField) UnmarshalJSON(data []byte) error

type MCPTransport

type MCPTransport struct {
	Type string `json:"type" yaml:"type"`                     // "http" | "stdio"
	Port uint16 `json:"port,omitempty" yaml:"port,omitempty"` // http listen port 1-65535 (ignored for stdio)
	Path string `json:"path,omitempty" yaml:"path,omitempty"` // http endpoint path, e.g. "/mcp" (ignored for stdio)
}

MCPTransport describes how a deployable MCPPackage exposes itself. Used only inside MCPPackage; remotes use MCPRemote, which carries its own URL. For http, the listen Port and endpoint Path are set explicitly because the host is constructed at deploy time. Both are ignored for stdio.

type Model

type Model struct {
	TypeMeta `json:",inline" yaml:",inline"`
	Metadata ObjectMeta `json:"metadata" yaml:"metadata"`
	Spec     ModelSpec  `json:"spec" yaml:"spec"`
	Status   Status     `json:"status,omitzero" yaml:"status,omitempty"`
}

Model is the typed envelope for kind=Model resources. A Model is an admin-owned model definition: the model's identity (provider family and provider-scoped identifier) plus how the platform reaches and authenticates to it (endpoint, auth posture, secret refs).

func (*Model) GetMetadata

func (m *Model) GetMetadata() *ObjectMeta

func (*Model) MarshalSpec

func (m *Model) MarshalSpec() (json.RawMessage, error)

func (*Model) MarshalStatus

func (m *Model) MarshalStatus() (json.RawMessage, error)

func (*Model) SetMetadata

func (m *Model) SetMetadata(meta ObjectMeta)

func (*Model) UnmarshalSpec

func (m *Model) UnmarshalSpec(data json.RawMessage) error

func (*Model) UnmarshalStatus

func (m *Model) UnmarshalStatus(data json.RawMessage) error

func (*Model) Validate

func (m *Model) Validate() error

Validate runs Model's structural checks.

All model rules land at apply time on the Model (provider and auth live on one object):

  • provider in the known set; model non-empty.
  • auth.strategy in {runtime, secretRef, passthrough}; secretRef present iff strategy is secretRef.
  • "runtime" only for ambient-identity providers (currently bedrock); key-based providers must declare secretRef or passthrough.

Model is versioned: identity is (namespace, name, tag). Auth/endpoint edits publish a new configuration tag when callers need to preserve existing Deployment pins.

type ModelAuthConfig

type ModelAuthConfig struct {
	// Strategy is "runtime" (ambient cloud identity), "secretRef" (key
	// material from a registry Secret), or "passthrough" (inbound bearer
	// token forwarded as the provider key).
	Strategy string `json:"strategy" yaml:"strategy" enum:"runtime,secretRef,passthrough"`
	// SecretRef is required iff Strategy == "secretRef".
	SecretRef *SecretKeyRef `json:"secretRef,omitempty" yaml:"secretRef,omitempty"`
}

ModelAuthConfig declares the auth posture for reaching the provider. OSS stores SecretRef opaquely and never resolves it; resolution is owned by distributions with a secret store.

type ModelEndpointConfig

type ModelEndpointConfig struct {
	BaseURL string `json:"baseUrl,omitempty" yaml:"baseUrl,omitempty"`
	// Region overrides the model-endpoint region (bedrock); empty means the
	// provider default.
	Region string          `json:"region,omitempty" yaml:"region,omitempty"`
	TLS    *ModelTLSConfig `json:"tls,omitempty" yaml:"tls,omitempty"`
}

ModelEndpointConfig overrides how the provider is reached.

type ModelRef

type ModelRef struct {
	Namespace string `json:"namespace,omitempty" yaml:"namespace,omitempty"`
	Name      string `json:"name" yaml:"name"`
	Tag       string `json:"tag,omitempty" yaml:"tag,omitempty"`
}

ModelRef selects a tagged Model. Kind is implicit (always Model).

Namespace is optional: blank means "same namespace as the referencing Deployment". Tag is optional: blank resolves the literal "latest" tag. When a harness Agent Deployment omits ModelRef entirely, it defaults to {name: "default"} in the Deployment namespace.

type ModelSpec

type ModelSpec struct {
	// Catalog display metadata.
	Title       string `json:"title,omitempty" yaml:"title,omitempty"`
	Description string `json:"description,omitempty" yaml:"description,omitempty"`

	// Provider family. Currently only "bedrock" is supported.
	Provider string `json:"provider" yaml:"provider" enum:"bedrock"`

	// Model is the provider-scoped model identifier, e.g.
	// "us.anthropic.claude-opus-4-8".
	Model string `json:"model" yaml:"model"`

	// Auth is how the platform authenticates to the provider. Omitted means
	// the provider default: ambient runtime identity for Bedrock.
	Auth *ModelAuthConfig `json:"auth,omitempty" yaml:"auth,omitempty"`

	// Endpoint overrides how the provider is reached. Omitted means
	// provider defaults.
	Endpoint *ModelEndpointConfig `json:"endpoint,omitempty" yaml:"endpoint,omitempty"`
}

ModelSpec describes one model: catalog display metadata, provider-scoped identity, and platform-owned connection posture.

Model is a tagged catalog artifact. Provider identity and platform-owned auth/endpoint posture are versioned together so Deployments can pin the complete model configuration they consume.

type ModelTLSConfig

type ModelTLSConfig struct {
	// CACertSecretRef names CA material for private gateways.
	CACertSecretRef *SecretKeyRef `json:"caCertSecretRef,omitempty" yaml:"caCertSecretRef,omitempty"`
	// DisableVerify is for dev/test only.
	DisableVerify bool `json:"disableVerify,omitempty" yaml:"disableVerify,omitempty"`
}

ModelTLSConfig carries TLS settings for private gateway endpoints.

type MonitorEntry

type MonitorEntry struct {
	Name        string `json:"name" yaml:"name"`
	Command     string `json:"command" yaml:"command"`
	Description string `json:"description" yaml:"description"`
	When        string `json:"when,omitempty" yaml:"when,omitempty"`
}

MonitorEntry is one inline monitor.

type MonitorsField

type MonitorsField struct {
	Path    string
	Entries []MonitorEntry
}

MonitorsField models `monitors`: a `./*.json` path or an array of monitors.

func (MonitorsField) MarshalJSON

func (f MonitorsField) MarshalJSON() ([]byte, error)

func (*MonitorsField) UnmarshalJSON

func (f *MonitorsField) UnmarshalJSON(data []byte) error

type Object

type Object interface {
	GetAPIVersion() string
	GetKind() string
	SetTypeMeta(TypeMeta)
	GetMetadata() *ObjectMeta
	SetMetadata(ObjectMeta)
	// MarshalSpec returns the JSON encoding of this object's Spec field.
	MarshalSpec() (json.RawMessage, error)
	// UnmarshalSpec decodes the given JSON bytes into this object's Spec field.
	UnmarshalSpec(data json.RawMessage) error
	// MarshalStatus returns the JSON encoding of this object's Status field.
	// Empty-status objects return `nil, nil`.
	MarshalStatus() (json.RawMessage, error)
	// UnmarshalStatus decodes the given JSON bytes into this object's Status
	// field. Empty/nil input resets the status to its zero value.
	UnmarshalStatus(data json.RawMessage) error
}

Object is the minimal interface satisfied by every typed v1alpha1 envelope (Agent, MCPServer, Skill, Prompt, Runtime, Deployment; extension kinds opt in too). It lets generic code operate on any resource without reflection.

Status is intentionally exchanged as json.RawMessage on this interface. The envelope itself stays agnostic to per-kind status schemas:

  • OSS kinds currently bind Status to the typed v1alpha1.Status (K8s-style Conditions) via the accessor methods below.
  • Extension kinds can use any shape they like without conforming to meta.v1 conditions.

MarshalStatus / UnmarshalStatus are the codec hooks the generic Store and handlers use to read/write status from the status JSONB column.

type ObjectMeta

type ObjectMeta struct {
	Namespace   string            `json:"namespace,omitempty" yaml:"namespace,omitempty"`
	Name        string            `json:"name" yaml:"name"`
	UID         string            `json:"uid,omitempty" yaml:"uid,omitempty"`
	Labels      map[string]string `json:"labels,omitempty" yaml:"labels,omitempty"`
	Annotations map[string]string `json:"annotations,omitempty" yaml:"annotations,omitempty"`

	// Tag is the user-visible identity for content-registry kinds
	// (Agent, MCPServer, Model, Plugin, Skill, Prompt).
	Tag string `json:"tag,omitempty" yaml:"tag,omitempty"`

	// Generation is server-managed and internal. Populated from the DB row for
	// internal Go consumers (coordinators, status reconcilers); hidden from the
	// wire.
	Generation int64     `json:"-" yaml:"-"`
	CreatedAt  time.Time `json:"createdAt,omitzero" yaml:"createdAt,omitempty"`
	UpdatedAt  time.Time `json:"updatedAt,omitzero" yaml:"updatedAt,omitempty"`

	// DeletionTimestamp is set by the Store when Delete is called. A non-nil
	// DeletionTimestamp means the object is terminating; the row stays
	// observable via Get until the GC pass purges it. Clients MUST NOT
	// set this on apply.
	DeletionTimestamp *time.Time `json:"deletionTimestamp,omitempty" yaml:"deletionTimestamp,omitempty"`
}

ObjectMeta is the metadata block common to every resource.

Namespace, Name, Labels, Annotations, and Tag are user-settable. Tag is meaningful for content-registry kinds. UID, Generation, CreatedAt, UpdatedAt, and DeletionTimestamp are server-managed. Content resources use Tag and mutable resources use Namespace/Name.

Generation is an internal coordination primitive that drives reconciler convergence (paired with Status.ObservedGeneration). It is populated from the database row and used by internal Go code, but is NOT emitted on the wire: the JSON/YAML tags are `-`, so OpenAPI schemas don't reveal it and clients can't set it on apply.

Content-registry identity is (Namespace, Name, Tag). Users may supply metadata.tag to pin manifests declaratively before applying anything to a live server. When Tag is omitted, the store fills it with the literal "latest" tag.

Mutable-object kinds (Runtime, Deployment, and additional downstream control-plane/config kinds) use Namespace/Name as their full identity. Namespace is an internal detail today — it defaults to "default" on apply and is stripped from responses when it equals "default" so the multi-tenant surface stays hidden until we deliberately enable it.

UID is a server-assigned UUID stamped at row creation and never mutated afterwards — same contract as Kubernetes' metadata.uid. Public identity may be reused across delete + recreate cycles; UID is not, so it disambiguates "the row I observed earlier" from "a fresh row at the same identity". The apply pipeline strips caller-supplied values before the store sees them, and Postgres assigns the value via a column default.

Labels vs Annotations (Kubernetes convention):

  • Labels are queryable: short key/value pairs, GIN-indexed, used for filtering + selection. Enforce the K8s label format.
  • Annotations are narrative: arbitrary key/value pairs for controller state, tool metadata, etc. Not indexed; can carry larger payloads. Callers read annotations by key; the server never filters on them.

DeletionTimestamp marks a row as terminating. Soft-delete is server-side: a DELETE call sets DeletionTimestamp and the row is later hard-deleted by the GC pass. There is no user-facing finalizer API; controllers may seed internal finalizers for async teardown (for example Deployment adapter removal) before GC purges the row.

func (*ObjectMeta) GetMetadata

func (m *ObjectMeta) GetMetadata() *ObjectMeta

func (ObjectMeta) MarshalJSON

func (m ObjectMeta) MarshalJSON() ([]byte, error)

MarshalJSON strips Namespace when it equals DefaultNamespace so responses don't leak the namespace surface while it remains hidden from the user-facing API. Internal storage always carries the full identity; this only affects wire rendering.

Inbound defaulting from empty to "default" happens at the apply boundary (see resource.prepareApplyDoc), not on UnmarshalJSON. Callers need to keep the empty-namespace signal around so they can layer their own default on top.

func (ObjectMeta) NamespaceOrDefault

func (m ObjectMeta) NamespaceOrDefault() string

NamespaceOrDefault returns m.Namespace, or DefaultNamespace when the field is empty. Use when building display strings / ids that should include the effective namespace even though the wire has elided the default namespace.

func (*ObjectMeta) SetMetadata

func (m *ObjectMeta) SetMetadata(meta ObjectMeta)

type PathOrPaths

type PathOrPaths struct {
	Values   []string
	WasArray bool
}

PathOrPaths models a `string | array<string>` component-path override. It normalizes to []string but remembers whether the source was a scalar so it re-emits the original form.

func (PathOrPaths) MarshalJSON

func (p PathOrPaths) MarshalJSON() ([]byte, error)

func (*PathOrPaths) UnmarshalJSON

func (p *PathOrPaths) UnmarshalJSON(data []byte) error

type Plugin

type Plugin struct {
	TypeMeta `json:",inline" yaml:",inline"`
	Metadata ObjectMeta   `json:"metadata" yaml:"metadata"`
	Spec     PluginSpec   `json:"spec" yaml:"spec"`
	Status   PluginStatus `json:"status,omitzero" yaml:"status,omitempty"`
}

Plugin is the typed envelope for kind=Plugin resources.

A Plugin is a self-contained, versioned bundle of harness extensions — skills, MCP servers, hooks, and sub-agents — modeled on the Claude Code plugin format. The Spec is USER INTENT ONLY: a pinned pointer to an external source (a git commit or — later — an OCI digest), the same source-based model agents and skills use. The registry hosts NOTHING; the Plugin controller resolves the pointer to a concrete commit/digest and scans the source for its manifest and inventory OUT OF BAND, recording that server-determined data in Status — never in Spec. The bundle is materialized from its source into a harness layout at deploy time.

func (*Plugin) GetMetadata

func (p *Plugin) GetMetadata() *ObjectMeta

func (*Plugin) MarshalSpec

func (p *Plugin) MarshalSpec() (json.RawMessage, error)

func (*Plugin) MarshalStatus

func (p *Plugin) MarshalStatus() (json.RawMessage, error)

MarshalStatus serializes the typed PluginStatus: the embedded Status via the storage codec, with the server-determined ResolvedSource/Manifest/Inventory spliced onto the same object. Nil custom fields are omitted (no stray nulls) so the store's patch-skip byte comparison stays stable.

func (*Plugin) SetMetadata

func (p *Plugin) SetMetadata(meta ObjectMeta)

func (*Plugin) UnmarshalSpec

func (p *Plugin) UnmarshalSpec(data json.RawMessage) error

func (*Plugin) UnmarshalStatus

func (p *Plugin) UnmarshalStatus(data json.RawMessage) error

func (*Plugin) Validate

func (p *Plugin) Validate() error

type PluginAuthor

type PluginAuthor struct {
	Name  string `json:"name" yaml:"name"`
	Email string `json:"email,omitempty" yaml:"email,omitempty"`
	URL   string `json:"url,omitempty" yaml:"url,omitempty"`
}

PluginAuthor is the `author` block; Name is required when the block exists.

type PluginChannel

type PluginChannel struct {
	Server      string                           `json:"server" yaml:"server"`
	DisplayName string                           `json:"displayName,omitempty" yaml:"displayName,omitempty"`
	UserConfig  map[string]PluginUserConfigField `json:"userConfig,omitempty" yaml:"userConfig,omitempty"`
}

PluginChannel declares an MCP-server-backed message channel.

type PluginDependency

type PluginDependency struct {
	Ref         string `json:"-" yaml:"-"`
	Name        string `json:"name,omitempty" yaml:"name,omitempty"`
	Marketplace string `json:"marketplace,omitempty" yaml:"marketplace,omitempty"`
	Version     string `json:"version,omitempty" yaml:"version,omitempty"`
}

PluginDependency is one `dependencies[]` entry: a string spec ("name", "name@marketplace", "name@^1.2.3") OR an object {name, marketplace, version}. Exactly one form is populated and preserved by (Un)MarshalJSON.

func (PluginDependency) MarshalJSON

func (d PluginDependency) MarshalJSON() ([]byte, error)

func (*PluginDependency) UnmarshalJSON

func (d *PluginDependency) UnmarshalJSON(data []byte) error

type PluginExperimental

type PluginExperimental struct {
	Themes   *PathOrPaths   `json:"themes,omitempty" yaml:"themes,omitempty"`
	Monitors *MonitorsField `json:"monitors,omitempty" yaml:"monitors,omitempty"`
}

PluginExperimental is the docs-preferred nesting for themes/monitors. Typed (not raw) so the derived inventory/governance can read it; unknown experimental keys are not separately preserved.

type PluginHook

type PluginHook struct {
	// Event is the lifecycle event, e.g. "PreToolUse", "PostToolUse",
	// "SessionStart".
	Event string `json:"event" yaml:"event"`
	// Type is the handler kind: command|http|mcp_tool|prompt|agent.
	Type string `json:"type,omitempty" yaml:"type,omitempty"`
}

PluginHook is one lifecycle hook the bundle registers.

type PluginInventory

type PluginInventory struct {
	Skills   []PluginSkill `json:"skills,omitempty" yaml:"skills,omitempty"`
	Commands []string      `json:"commands,omitempty" yaml:"commands,omitempty"`
	// Agents are sub-agent names; sub-agents are markdown prompt files in the
	// bundle, not manifest entries.
	Agents []string `json:"agents,omitempty" yaml:"agents,omitempty"`
	// Hooks are lifecycle hooks the bundle registers (arbitrary code).
	Hooks      []PluginHook `json:"hooks,omitempty" yaml:"hooks,omitempty"`
	MCPServers []string     `json:"mcpServers,omitempty" yaml:"mcpServers,omitempty"`
	// Executables are bin/ entries the bundle ships (arbitrary code).
	Executables []string `json:"executables,omitempty" yaml:"executables,omitempty"`
}

PluginInventory is the server-derived index of a bundle's actual contents, computed by scanning the bundle files (not the author-supplied manifest). It is the legible governance risk surface and the search index.

type PluginManifest

type PluginManifest struct {
	Schema      string   `json:"$schema,omitempty" yaml:"$schema,omitempty"`
	Name        string   `json:"name" yaml:"name"`
	Version     string   `json:"version,omitempty" yaml:"version,omitempty"`
	Description string   `json:"description,omitempty" yaml:"description,omitempty"`
	Homepage    string   `json:"homepage,omitempty" yaml:"homepage,omitempty"`
	Repository  string   `json:"repository,omitempty" yaml:"repository,omitempty"`
	License     string   `json:"license,omitempty" yaml:"license,omitempty"`
	Keywords    []string `json:"keywords,omitempty" yaml:"keywords,omitempty"`

	Author *PluginAuthor `json:"author,omitempty" yaml:"author,omitempty"`

	// Settings is an opaque allowlisted settings-merge object (schema models it
	// as open additionalProperties), held raw to round-trip losslessly.
	Settings json.RawMessage `json:"settings,omitempty" yaml:"settings,omitempty"`

	Dependencies []PluginDependency `json:"dependencies,omitempty" yaml:"dependencies,omitempty"`

	// Component path overrides — string|array|object unions (see types below).
	Commands     *CommandsField   `json:"commands,omitempty" yaml:"commands,omitempty"`
	Agents       *PathOrPaths     `json:"agents,omitempty" yaml:"agents,omitempty"`
	Skills       *PathOrPaths     `json:"skills,omitempty" yaml:"skills,omitempty"`
	OutputStyles *PathOrPaths     `json:"outputStyles,omitempty" yaml:"outputStyles,omitempty"`
	Hooks        *HooksField      `json:"hooks,omitempty" yaml:"hooks,omitempty"`
	MCPServers   *MCPServersField `json:"mcpServers,omitempty" yaml:"mcpServers,omitempty"`
	LSPServers   *LSPServersField `json:"lspServers,omitempty" yaml:"lspServers,omitempty"`

	UserConfig map[string]PluginUserConfigField `json:"userConfig,omitempty" yaml:"userConfig,omitempty"`
	Channels   []PluginChannel                  `json:"channels,omitempty" yaml:"channels,omitempty"`

	// Themes/Monitors are the schemastore top-level placement; Experimental is
	// the docs-preferred nesting. Both are modeled so we re-emit whichever the
	// source used.
	Themes       *PathOrPaths        `json:"themes,omitempty" yaml:"themes,omitempty"`
	Monitors     *MonitorsField      `json:"monitors,omitempty" yaml:"monitors,omitempty"`
	Experimental *PluginExperimental `json:"experimental,omitempty" yaml:"experimental,omitempty"`

	// DisplayName / DefaultEnabled are docs-only (not in the schemastore schema)
	// but Claude loads them; modeled so real data isn't dropped.
	DisplayName    string `json:"displayName,omitempty" yaml:"displayName,omitempty"`
	DefaultEnabled *bool  `json:"defaultEnabled,omitempty" yaml:"defaultEnabled,omitempty"`

	// Extras captures any top-level key not modeled above (Codex interface/apps,
	// forward-compat keys) so the manifest is a true cross-harness superset.
	// Spliced in/out by (Un)MarshalJSON; never carries a known key.
	Extras map[string]json.RawMessage `json:"-" yaml:"-"`
}

PluginManifest is a faithful, lossless Go representation of a Claude Code plugin manifest (`.claude-plugin/plugin.json`). The registry records it as server-derived Plugin status after resolving and scanning the configured source; it does not make the manifest or bundle bytes part of the user-owned Plugin spec. It is grounded in the official schema (json.schemastore.org/claude-code-plugin-manifest.json).

Fidelity rules:

  • Every field maps to the real plugin.json key with an exact json tag.
  • Optional scalars/objects use pointers or omitempty so a sparse manifest round-trips to the same sparse JSON (no zero-value injection).
  • Fields whose JSON is a `string | array | object` union use the custom union types in this file, which preserve the source's exact form.
  • Foreign-ecosystem and forward-compat top-level keys (e.g. Codex `interface`, `apps`) land in Extras, making this a true cross-harness superset rather than relying on lenient "ignore unknown fields" behavior.

Scope notes: the array forms of hooks/mcpServers/lspServers are preserved verbatim (Raw) for lossless round-trip; the legible risk surface for those is the server-derived PluginInventory (which scans the actual bundle files), not this author-supplied manifest. Unknown keys inside the open object forms of dependencies/commands/monitors are not separately preserved.

This type is NOT a registry kind; it is parsed from a plugin bundle and embedded in Plugin status (see plugin.go).

func (PluginManifest) MarshalJSON

func (m PluginManifest) MarshalJSON() ([]byte, error)

MarshalJSON emits the modeled fields plus any Extras keys, re-merged at the top level. Modeled keys win on collision (Extras should never hold one).

func (*PluginManifest) UnmarshalJSON

func (m *PluginManifest) UnmarshalJSON(data []byte) error

UnmarshalJSON decodes the modeled fields and stashes every other top-level key in Extras, so no source data is lost on round-trip.

type PluginResolvedSource

type PluginResolvedSource struct {
	Type PluginSourceType `json:"type" yaml:"type"`
	// Commit is the resolved full git commit SHA (Type=git).
	Commit string `json:"commit,omitempty" yaml:"commit,omitempty"`
	// Digest is the resolved OCI digest, e.g. "sha256:…" (Type=oci; future).
	Digest string `json:"digest,omitempty" yaml:"digest,omitempty"`
}

PluginResolvedSource records the concrete, immutable revision the controller pinned the user's source pointer to. Exactly one of Commit/Digest is set, matching Type. It is the reproducibility anchor: deploys materialize from this pin, not from the (possibly moving) ref the user supplied.

type PluginSkill

type PluginSkill struct {
	Name        string `json:"name" yaml:"name"`
	Description string `json:"description,omitempty" yaml:"description,omitempty"`
}

PluginSkill is one skill shipped in the bundle (from its SKILL.md frontmatter).

type PluginSource

type PluginSource struct {
	Type PluginSourceType `json:"type" yaml:"type"`
	Git  *PluginSourceGit `json:"git,omitempty" yaml:"git,omitempty"`
	OCI  *PluginSourceOCI `json:"oci,omitempty" yaml:"oci,omitempty"`
}

PluginSource identifies where the bundle came from. Exactly one of Git/OCI is set, matching Type. The reference must be pinned (git commit / OCI digest) so the published tag is reproducible.

type PluginSourceGit

type PluginSourceGit struct {
	Repository *Repository `json:"repository" yaml:"repository"`
}

PluginSourceGit is a git source. Repository may pin a Commit, a Branch, or a tag (empty => the remote default branch); the Plugin controller resolves whatever ref is supplied to a concrete commit SHA and records that immutable pin in status.ResolvedSource. Repository.Subfolder selects a plugin inside a monorepo.

type PluginSourceOCI

type PluginSourceOCI struct {
	Reference string `json:"reference" yaml:"reference"`
}

PluginSourceOCI is a digest-pinned OCI artifact reference, e.g. "ghcr.io/org/plugin@sha256:...". Bare/tag-only refs are rejected.

type PluginSourceType

type PluginSourceType string

PluginSourceType selects which source sub-struct is set.

const (
	PluginSourceTypeGit PluginSourceType = "git"
	PluginSourceTypeOCI PluginSourceType = "oci"
)

type PluginSpec

type PluginSpec struct {
	Title       string `json:"title,omitempty" yaml:"title,omitempty"`
	Description string `json:"description,omitempty" yaml:"description,omitempty"`

	// Harnesses lists the harness formats this bundle carries native manifests
	// for (e.g. "claude-code", "codex"). It is informational in this phase;
	// deploy-time adapters decide which harnesses they can consume.
	Harnesses []string `json:"harnesses,omitempty" yaml:"harnesses,omitempty"`

	// Source is where the bundle is ingested from, pinned (git commit / OCI
	// digest) so a published tag is reproducible.
	Source *PluginSource `json:"source,omitempty" yaml:"source,omitempty"`
}

PluginSpec is the plugin resource's declarative body — USER INTENT ONLY. Server-derived data (the resolved source pin, the parsed Manifest, and the derived Inventory) lives in PluginStatus, populated out of band by the Plugin controller. Keeping it out of the spec means a status write never changes the spec content hash, so re-applying identical intent is an UpsertNoOp.

type PluginStatus

type PluginStatus struct {
	Status `json:",inline" yaml:",inline"`

	// ResolvedSource is the controller's immutable pin of the user's source
	// pointer (the concrete commit/digest the source resolved to).
	ResolvedSource *PluginResolvedSource `json:"resolvedSource,omitempty" yaml:"resolvedSource,omitempty"`
	// Manifest is the canonical typed plugin.json parsed from the source.
	Manifest *PluginManifest `json:"manifest,omitempty" yaml:"manifest,omitempty"`
	// Inventory is the server-derived risk surface / search index.
	Inventory *PluginInventory `json:"inventory,omitempty" yaml:"inventory,omitempty"`
}

PluginStatus is the Plugin observed-state subresource, written by the Plugin controller out of band of the API write. It embeds the shared Status (conditions + observedGeneration) and adds the server-determined resolution data.

Readiness contract: consumers MUST treat the absence of a Ready=True condition (or ResolvedSource==nil) as "not yet resolved". The controller sets Ready=False/Reason=Progressing on first observe, Ready=True/Reason=Resolved once the pointer is pinned and the source scanned, and Ready=False with a specific reason (SourceUnresolvable, SourceUnsupported, SourceInvalid) on failure.

type PluginUserConfigField

type PluginUserConfigField struct {
	Type        string          `json:"type" yaml:"type"`
	Title       string          `json:"title" yaml:"title"`
	Description string          `json:"description" yaml:"description"`
	Required    *bool           `json:"required,omitempty" yaml:"required,omitempty"`
	Default     json.RawMessage `json:"default,omitempty" yaml:"default,omitempty"`
	Multiple    *bool           `json:"multiple,omitempty" yaml:"multiple,omitempty"`
	Sensitive   *bool           `json:"sensitive,omitempty" yaml:"sensitive,omitempty"`
	Min         *float64        `json:"min,omitempty" yaml:"min,omitempty"`
	Max         *float64        `json:"max,omitempty" yaml:"max,omitempty"`
}

PluginUserConfigField is one typed enable-time prompt. Default is a string|number|boolean|string[] union held raw.

type Prompt

type Prompt struct {
	TypeMeta `json:",inline" yaml:",inline"`
	Metadata ObjectMeta `json:"metadata" yaml:"metadata"`
	Spec     PromptSpec `json:"spec" yaml:"spec"`
	Status   Status     `json:"status,omitzero" yaml:"status,omitempty"`
}

Prompt is the typed envelope for kind=Prompt resources.

func (*Prompt) GetMetadata

func (p *Prompt) GetMetadata() *ObjectMeta

func (*Prompt) MarshalSpec

func (p *Prompt) MarshalSpec() (json.RawMessage, error)

func (*Prompt) MarshalStatus

func (p *Prompt) MarshalStatus() (json.RawMessage, error)

func (*Prompt) SetMetadata

func (p *Prompt) SetMetadata(meta ObjectMeta)

func (*Prompt) UnmarshalSpec

func (p *Prompt) UnmarshalSpec(data json.RawMessage) error

func (*Prompt) UnmarshalStatus

func (p *Prompt) UnmarshalStatus(data json.RawMessage) error

func (*Prompt) Validate

func (p *Prompt) Validate() error

type PromptSpec

type PromptSpec struct {
	Description string `json:"description,omitempty" yaml:"description,omitempty"`
	Content     string `json:"content,omitempty" yaml:"content,omitempty"`
}

PromptSpec is the prompt resource's declarative body. Content holds the prompt text inline; for large bodies or binary assets, use references via a Skill resource instead.

type RawObject

type RawObject struct {
	TypeMeta `json:",inline" yaml:",inline"`
	Metadata ObjectMeta      `json:"metadata" yaml:"metadata"`
	Spec     json.RawMessage `json:"spec,omitempty" yaml:"spec,omitempty"`
	Status   json.RawMessage `json:"status,omitempty" yaml:"status,omitempty"`
}

RawObject is the generic wire envelope used during decode and apply dispatch when the concrete Kind is not yet known. Spec AND Status are both held as raw JSON bytes so the envelope layer stays agnostic to per-kind schemas: OSS kinds layer a typed v1alpha1.Status (K8s-style conditions) on top; extension kinds can ship any JSON shape they like without having to conform to meta.v1 conditions.

Callers route into a typed object via Scheme.Decode / Scheme.DecodeMulti (or EnvelopeFromRaw); each kind's UnmarshalStatus is the inverse of the per-kind MarshalStatus and decides how to decode the bytes.

type RefResolver

type RefResolver interface {
	ResolveRefs(ctx context.Context, resolver ResolverFunc) error
}

RefResolver validates cross-resource references for an envelope.

type RegistryValidatable

type RegistryValidatable interface {
	ValidateRegistries(ctx context.Context, v RegistryValidatorFunc) error
}

RegistryValidatable validates packages against external registry metadata.

type RegistryValidatorFunc

type RegistryValidatorFunc func(ctx context.Context, origin MCPPackageOrigin, expectedServerName string) error

RegistryValidatorFunc validates a single package's origin against its referenced external registry. Implementations fan out by which sub-struct (Origin.NPM/PyPI/OCI) is non-nil to the appropriate per-registry validator. expectedServerName is the upstream-claimed server identity declared on the origin's sub-struct (e.g. origin.oci.serverName), passed through to ownership-annotation checks (e.g. OCI's io.modelcontextprotocol.server.name label match).

A nil RegistryValidatorFunc is a no-op on the ValidateRegistries methods; callers that aren't wired with a dispatcher skip the check.

type Repository

type Repository struct {
	URL       string `json:"url,omitempty" yaml:"url,omitempty"`
	Branch    string `json:"branch,omitempty" yaml:"branch,omitempty"`
	Commit    string `json:"commit,omitempty" yaml:"commit,omitempty"`
	Subfolder string `json:"subfolder,omitempty" yaml:"subfolder,omitempty"`
}

Repository is a source-code location shared by several resource kinds.

Branch and Commit are optional pinning hints for consumers that need to fetch source for deployment or other runtime work. When both are empty, consumers should fall back to the repository's default branch (i.e. `git clone` without `--branch`), not a hardcoded branch name.

type ResolverFunc

type ResolverFunc func(ctx context.Context, ref ResourceRef) error

ResolverFunc resolves a ResourceRef to an existing object. It should return ErrDanglingRef if the referenced object isn't found. Other errors (DB failures, etc.) propagate as-is.

type ResourceRef

type ResourceRef struct {
	Kind      string `json:"kind" yaml:"kind"`
	Namespace string `json:"namespace,omitempty" yaml:"namespace,omitempty"`
	Name      string `json:"name" yaml:"name"`
	Tag       string `json:"tag,omitempty" yaml:"tag,omitempty"`
}

ResourceRef is a typed reference to another resource in the registry. Public references use one shape across v1alpha1: {Kind, Namespace, Name, Tag}. Tag is meaningful only for taggable registry artifacts.

Namespace is optional: blank means "same namespace as the referencing object" (the common case). Tag is optional: blank means "resolve to the literal latest tag" for taggable artifacts or "resolve by namespace/name" for mutable object kinds.

type Runtime

type Runtime struct {
	TypeMeta `json:",inline" yaml:",inline"`
	Metadata ObjectMeta  `json:"metadata" yaml:"metadata"`
	Spec     RuntimeSpec `json:"spec" yaml:"spec"`
	Status   Status      `json:"status,omitzero" yaml:"status,omitempty"`
}

Runtime is the typed envelope for kind=Runtime resources. A Runtime describes an execution target (local docker daemon, a Kubernetes cluster, a hosted agent runtime) that Deployment resources reference via spec.runtimeRef.

func (*Runtime) GetMetadata

func (r *Runtime) GetMetadata() *ObjectMeta

func (*Runtime) MarshalSpec

func (r *Runtime) MarshalSpec() (json.RawMessage, error)

func (*Runtime) MarshalStatus

func (r *Runtime) MarshalStatus() (json.RawMessage, error)

func (*Runtime) SetMetadata

func (r *Runtime) SetMetadata(meta ObjectMeta)

func (*Runtime) UnmarshalSpec

func (r *Runtime) UnmarshalSpec(data json.RawMessage) error

func (*Runtime) UnmarshalStatus

func (r *Runtime) UnmarshalStatus(data json.RawMessage) error

func (*Runtime) Validate

func (r *Runtime) Validate() error

Validate runs Runtime's structural checks and canonicalizes Spec.Type to its CamelCase form.

Manifests may write Spec.Type in any casing (`local`, `LOCAL`, `Local`) for ergonomic UX; the validator looks the input up in KnownRuntimeTypes case-insensitively and rewrites Spec.Type in place to the canonical CamelCase value. Every consumer downstream of Validate (adapter dispatch, status messages, storage) compares Spec.Type with exact-match equality, so case-insensitivity lives in exactly one place.

Runtime is unversioned: a connection handle to one execution target (an AWS account + role, a kagent cluster, a local Docker engine). Multiple coexisting versions of the same (namespace, name) carry no meaning — there is no "v1" vs "v2" of the same AWS role — so the (namespace, name) pair is the identity.

type RuntimeSpec

type RuntimeSpec struct {
	Type              string         `json:"type" yaml:"type"`
	Config            map[string]any `json:"config,omitempty" yaml:"config,omitempty"`
	TelemetryEndpoint string         `json:"telemetryEndpoint,omitempty" yaml:"telemetryEndpoint,omitempty"`
}

RuntimeSpec describes a deployment target. Type is the discriminator; Config carries type-specific configuration that downstream adapters (internal/registry/runtimes/...) interpret. TelemetryEndpoint, when set, is exported to every Deployment served by this Runtime as OTEL_EXPORTER_OTLP_ENDPOINT on the workload — telemetry is a property of where things run, not of an individual Deployment.

type Scheme

type Scheme struct {
	// contains filtered or unexported fields
}

Scheme routes a raw YAML/JSON envelope to a typed object by kind. Apply handlers, CLI decode, and the generic store all share one instance.

A zero-value Scheme is not usable — construct via NewScheme or use the package-level Default.

func NewScheme

func NewScheme() *Scheme

NewScheme returns an empty Scheme. Prefer Default for the built-in kinds.

func (*Scheme) Decode

func (s *Scheme) Decode(data []byte) (any, error)

Decode parses a single YAML or JSON document into a typed object pointer (*Agent, *MCPServer, etc.) routed by its kind field. Unknown kinds return an error. Input may be YAML or JSON — detection is delegated to sigs.k8s.io/yaml.

func (*Scheme) DecodeInto

func (s *Scheme) DecodeInto(data []byte, dst any) error

DecodeInto is a typed-destination variant: the caller provides the empty typed envelope (e.g. &Agent{}) and Decode fills it in place. Useful when the kind is known statically.

func (*Scheme) DecodeMulti

func (s *Scheme) DecodeMulti(data []byte) ([]any, error)

DecodeMulti parses a YAML stream (possibly containing multiple `---`- separated documents) or a single JSON document, returning one typed object per non-empty document. Empty documents are skipped.

func (*Scheme) Kinds

func (s *Scheme) Kinds() []string

Kinds returns the registered kind names in lexical order.

func (*Scheme) Lookup

func (s *Scheme) Lookup(kind string) (reflect.Type, func() any, bool)

Lookup returns the spec reflect.Type and envelope constructor for a kind, or (nil, nil, false) if the kind is unknown.

func (*Scheme) MustRegister

func (s *Scheme) MustRegister(kind string, specSample any, newObject func() any)

MustRegister is Register that panics on error. Use at init.

func (*Scheme) Register

func (s *Scheme) Register(kind string, specSample any, newObject func() any) error

Register associates a kind name with a spec type and a constructor for the typed envelope. newObject must return a pointer to a zero-valued envelope (e.g. &Agent{}). Kind names are matched case-insensitively but stored in their canonical form.

type SecretEnvSource

type SecretEnvSource struct {
	Name string `json:"name" yaml:"name"`
}

SecretEnvSource identifies the referenced Secret by name.

type SecretKeyRef

type SecretKeyRef struct {
	Namespace string `json:"namespace,omitempty" yaml:"namespace,omitempty"`
	Name      string `json:"name" yaml:"name"`
	Key       string `json:"key,omitempty" yaml:"key,omitempty"`
}

SecretKeyRef names a key in a registry Secret. OSS stores and structurally validates it but never resolves it. Secret values are not stored on Model resources.

type Skill

type Skill struct {
	TypeMeta `json:",inline" yaml:",inline"`
	Metadata ObjectMeta  `json:"metadata" yaml:"metadata"`
	Spec     SkillSpec   `json:"spec" yaml:"spec"`
	Status   SkillStatus `json:"status,omitzero" yaml:"status,omitempty"`
}

Skill is the typed envelope for kind=Skill resources.

func (*Skill) GetMetadata

func (s *Skill) GetMetadata() *ObjectMeta

func (*Skill) MarshalSpec

func (s *Skill) MarshalSpec() (json.RawMessage, error)

func (*Skill) MarshalStatus

func (s *Skill) MarshalStatus() (json.RawMessage, error)

MarshalStatus serializes the typed SkillStatus: the embedded Status via the storage codec, with the controller-determined ResolvedSource spliced onto the same object. A nil ResolvedSource is omitted (no stray null) so the store's patch-skip byte comparison stays stable.

func (*Skill) SetMetadata

func (s *Skill) SetMetadata(meta ObjectMeta)

func (*Skill) UnmarshalSpec

func (s *Skill) UnmarshalSpec(data json.RawMessage) error

func (*Skill) UnmarshalStatus

func (s *Skill) UnmarshalStatus(data json.RawMessage) error

func (*Skill) Validate

func (s *Skill) Validate() error

type SkillResolvedSource

type SkillResolvedSource struct {
	// Commit is the resolved full git commit SHA.
	Commit string `json:"commit,omitempty" yaml:"commit,omitempty"`
}

SkillResolvedSource records the concrete commit the Skill controller pinned the skill's git source to. It is the reproducibility anchor: deploys materialize from this pin, not from the (possibly moving) ref the user gave.

type SkillSource

type SkillSource struct {
	Repository *Repository `json:"repository,omitempty" yaml:"repository,omitempty"`
}

SkillSource is the distribution origin of a skill. Currently just a git repository where the skill content lives. Future distribution channels (e.g. published artifact) would land here.

type SkillSpec

type SkillSpec struct {
	Title       string       `json:"title,omitempty" yaml:"title,omitempty"`
	Description string       `json:"description,omitempty" yaml:"description,omitempty"`
	Source      *SkillSource `json:"source,omitempty" yaml:"source,omitempty"`
}

SkillSpec is the skill resource's declarative body.

type SkillStatus

type SkillStatus struct {
	Status `json:",inline" yaml:",inline"`

	// ResolvedSource is the controller's immutable pin of the skill's git
	// source (the concrete commit the source ref resolved to).
	ResolvedSource *SkillResolvedSource `json:"resolvedSource,omitempty" yaml:"resolvedSource,omitempty"`
}

SkillStatus is the Skill observed-state subresource, written by the Skill controller out of band of the API write. It embeds the shared Status (conditions + observedGeneration) and records the controller's immutable pin of the skill's git source — mirroring the Plugin resolve-and-pin model so a harness deploy can materialize the skill from a fixed commit.

Readiness: absence of Ready=True (or ResolvedSource==nil) means "not yet resolved". The controller sets Ready=False/Progressing on first observe, Ready=True/Resolved once the source is pinned, and Ready=False with a specific reason (SourceUnresolvable, SourceInvalid) on failure.

type Status

type Status struct {
	ObservedGeneration int64       `json:"-" yaml:"-"`
	Conditions         []Condition `json:"conditions,omitempty" yaml:"conditions,omitempty"`

	// Details is an opaque JSON object populated by controllers and runtime
	// adapters that need to surface structured state beyond what Conditions can
	// express. Each writer owns its own top-level key inside Details; consumers
	// parse only the keys they care about. Empty when no writer has stored
	// details.
	//
	// Use SetDetailsKey / GetDetailsKey to merge or read keys without clobbering
	// other adapters' state.
	Details json.RawMessage `json:"details,omitempty" yaml:"details,omitempty"`
}

Status is the observed-state subresource. ObservedGeneration is the highest metadata.generation any reconciler has acted on; Conditions is the list of fine-grained state facets written by the reconciler and service layer. No Phase roll-up — K8s deprecated it in favor of Conditions, and carrying a string summary encourages downstream string-comparison anti-patterns.

ObservedGeneration is internal-only (matches ObjectMeta.Generation).

func (*Status) GetCondition

func (s *Status) GetCondition(conditionType string) *Condition

GetCondition returns a pointer to the condition with the matching Type, or nil if none exists. The returned pointer aliases the slice element, so callers must not mutate through it while holding the Status.

func (*Status) GetDetailsKey

func (s *Status) GetDetailsKey(key string, out any) (bool, error)

GetDetailsKey unmarshals the value at key in s.Details into out. Returns (false, nil) when the key is absent. Returns an error if Details is malformed or out cannot receive the value.

func (*Status) IsConditionTrue

func (s *Status) IsConditionTrue(conditionType string) bool

IsConditionTrue reports whether the condition with the given Type exists and has Status == ConditionTrue.

func (*Status) SetCondition

func (s *Status) SetCondition(c Condition)

SetCondition adds or updates the condition matching c.Type on s. If an entry exists and its Status matches c.Status, the existing LastTransitionTime is preserved; otherwise LastTransitionTime is set to now (or c.LastTransitionTime if non-zero). Reason and Message are always overwritten.

func (*Status) SetDetailsKey

func (s *Status) SetDetailsKey(key string, value any) error

SetDetailsKey merges value (as JSON) under key in s.Details. Other top-level keys in s.Details are preserved; a nil value removes the key. Returns an error if value cannot be marshaled or if existing Details is not a JSON object.

func (*Status) SetDetailsKeyJSON

func (s *Status) SetDetailsKeyJSON(key string, encoded json.RawMessage) error

SetDetailsKeyJSON is SetDetailsKey for callers that already hold the value as pre-encoded JSON bytes. Skips the marshal step so byte equality is preserved (useful when the caller wants the on-disk JSON to match a canonical form). encoded must be a valid JSON value; pass nil to remove the key.

type StructuralValidator

type StructuralValidator interface {
	Validate() error
}

StructuralValidator runs zero-I/O validation on an envelope.

type TypeMeta

type TypeMeta struct {
	APIVersion string `json:"apiVersion" yaml:"apiVersion"`
	Kind       string `json:"kind" yaml:"kind"`
}

TypeMeta carries apiVersion + kind. Every typed object embeds this inline so that marshaled output matches the Kubernetes-style envelope.

func (*TypeMeta) GetAPIVersion

func (tm *TypeMeta) GetAPIVersion() string

func (*TypeMeta) GetKind

func (tm *TypeMeta) GetKind() string

func (*TypeMeta) SetTypeMeta

func (tm *TypeMeta) SetTypeMeta(t TypeMeta)

Directories

Path Synopsis
Package registries holds the per-registry validators that confirm a package exists in its upstream registry and carries an ownership annotation matching the resource's expected server name.
Package registries holds the per-registry validators that confirm a package exists in its upstream registry and carries an ownership annotation matching the resource's expected server name.
internal/testutil
Package testutil provides shared helpers for the registries package tests.
Package testutil provides shared helpers for the registries package tests.

Jump to

Keyboard shortcuts

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