manifest

package
v0.67.0 Latest Latest
Warning

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

Go to latest
Published: Sep 3, 2026 License: AGPL-3.0 Imports: 24 Imported by: 0

Documentation

Overview

Package manifest owns manifest-declared plugins: loading the builtin manifest, applying operator overrides, validating a plugin's shape, and reconciling its mise-installed runtime against what the manifest asks for.

Manifest plugins describe traits; they can never request a host capability. That line is enforced in internal/plugin/host.

Index

Constants

This section is empty.

Variables

View Source
var ErrFieldNotOwned = errors.New("field is not overridden")

ErrFieldNotOwned reports a reset of a field that was already following the shipped definition. Callers turn it into a 404: there is nothing to undo.

Functions

func DefinitionJSON

func DefinitionJSON(p ManifestPlugin) (string, error)

DefinitionJSON serializes a plugin's whole definition. It is what an admin-added plugin stores: there is no builtin underneath it to inherit from, so the row is the plugin.

func IsOwnableField

func IsOwnableField(name string) bool

IsOwnableField reports whether name is a definition field an override may own.

func LatestVersion

func LatestVersion(ctx context.Context, stellaHome, tool string) (string, error)

LatestVersion resolves the latest installable version for a mise tool key (short name like "fd" or backend-qualified like "github:cli/cli"). It may hit the network to query the backend's available versions.

func OwnableFields

func OwnableFields() []string

OwnableFields lists every field an override may own, in definition order.

func OwnedFields

func OwnedFields(override string) ([]string, error)

OwnedFields returns the fields a stored override owns, in definition order, so the editor can show what is pinned and offer to let go of one.

func ReleaseField

func ReleaseField(override, field string) (string, error)

ReleaseField hands one field back to the definition the server ships. A legacy row is converted first, so releasing one field from it keeps every other field pinned exactly where it was.

func RuntimeMiseEnv

func RuntimeMiseEnv(stellaHome, userToolsDir, userConfigDir, workspaceDir string) map[string]string

RuntimeMiseEnv returns the mise environment for a sandbox session using mise's native system < global < workspace precedence. The shared system installs and _builtin config supply release-owned tools. A principal gets a writable tools tree plus a global config under its shared XDG config root; workspace mise.toml files remain the most specific layer. HOME and the XDG roots themselves are rendered by the selected sandbox backend.

userToolsDir deliberately stays in the STELLA_HOME frame rather than under /user: relative seed and shim links must resolve against the shared system tree identically on local, none, and Docker backends. userConfigDir is separate and lives under the principal's shared data mount, where `mise use --global` may safely write without touching Stella's system config.

When userToolsDir is empty (no safe user/group principal), runtime falls back to the read-only system tree with auto-install disabled and exposes no writable global config.

MISE_DATA_DIR is load-bearing beyond mise itself: sandbox backends recover the per-user mise home from it via pkgsandbox.PerUserMiseDataDir to prepend its shims to PATH. Keep it pointing at userToolsDir, or at the system tree when the per-user tree is unavailable.

func SaveState

func SaveState(path string, s *ManifestState) error

SaveState writes the manifest state to path atomically (write to .tmp then rename).

func ScopeConfigPath

func ScopeConfigPath(stellaHome, scope string) string

ScopeConfigPath returns the persisted mise config path for a scope.

func SetFields

func SetFields(override string, edited ManifestPlugin, fields []string) (string, error)

SetFields takes ownership of the named fields at edited's values, on top of whatever override already owns, and returns the row to store. Fields nobody mentions keep their existing ownership: a save says what it changes, not what the whole plugin should be.

A field edited to its zero value is owned as null — "I want this empty" is a decision, and absent already means "inherit".

func StatePath

func StatePath(stellaHome string) string

StatePath returns the path for the manifest state file.

func Validate

func Validate(m *Manifest) error

Types

type BinaryInstallState

type BinaryInstallState struct {
	Name string `json:"name"`
	Tool string `json:"tool"`
	// Spec is the version spec requested by the manifest (e.g. "2.40", "latest").
	// Cache hits key on it; an empty Spec (pre-Spec state files) always misses
	// and re-resolves, repopulating it.
	Spec string `json:"spec,omitempty"`
	// Version is the concrete version mise resolved for Spec at install time.
	Version     string    `json:"version"`
	InstalledAt time.Time `json:"installed_at"`
}

type BinaryReconcileResult

type BinaryReconcileResult struct {
	Name     string
	Version  string
	CacheHit bool
	Err      error
}

BinaryReconcileResult holds the result for a single binary within a plugin.

type Manifest

type Manifest struct {
	OAuthProviders []ManifestOAuthProvider `json:"oauth_providers,omitempty" yaml:"oauth_providers,omitempty"`
	Plugins        []ManifestPlugin        `json:"plugins" yaml:"plugins"`
}

func LoadBuiltin

func LoadBuiltin() (*Manifest, error)

LoadBuiltin returns the manifest baked into the binary at build time. This is the single source of truth for plugin defaults; overrides live in the plugin_override DB table.

func Resolve

func Resolve(builtin *Manifest, overrides []StoredOverride, onCorrupt func(pluginID string, err error)) *Manifest

Resolve overlays stored overrides on the builtin manifest and returns the plugin set the server should actually run.

There is exactly one of these on purpose. The startup wiring and the admin control plane both need the resolved manifest, and when they each carried their own copy of the rule they drifted: one applied definition overrides and the other silently applied only the enable flag, so a customization worked until the process restarted and then quietly didn't.

onCorrupt reports a row that cannot be read. A bad row is skipped rather than fatal: one unreadable customization must not take the whole plugin set down with it.

type ManifestBinary

type ManifestBinary struct {
	// Name is the binary name written to $STELLA_HOME/bin/.
	Name string `json:"name" yaml:"name"`

	// Tool is the mise tool key, e.g.:
	//   uv   bun   github:cli/cli   pipx:mypy   npm:serve   http:sentinel
	Tool string `json:"tool" yaml:"tool"`

	// Version to install; defaults to "latest" when omitted.
	Version string `json:"version,omitempty" yaml:"version,omitempty"`

	// Options are mise tool options, using the same names as mise.toml.
	Options map[string]any `json:"options,omitempty" yaml:",inline"`
}

type ManifestOAuthFlow

type ManifestOAuthFlow struct {
	Type          string `json:"type" yaml:"type"`
	AuthURL       string `json:"auth_url,omitempty" yaml:"auth_url,omitempty"`
	DeviceAuthURL string `json:"device_auth_url,omitempty" yaml:"device_auth_url,omitempty"`
	TokenURL      string `json:"token_url" yaml:"token_url"`
	AuthStyle     string `json:"auth_style,omitempty" yaml:"auth_style,omitempty"`
	PKCE          bool   `json:"pkce,omitempty" yaml:"pkce,omitempty"`
}

type ManifestOAuthProvider

type ManifestOAuthProvider struct {
	ID           string              `json:"id" yaml:"id"`
	Icon         string              `json:"icon,omitempty" yaml:"icon,omitempty"`
	Scopes       []string            `json:"scopes" yaml:"scopes"`
	VaultKey     string              `json:"vault_key" yaml:"vault_key"`
	Flows        []ManifestOAuthFlow `json:"flows" yaml:"flows"`
	ClientID     string              `json:"client_id,omitempty" yaml:"client_id,omitempty"`
	ClientSecret string              `json:"client_secret,omitempty" yaml:"client_secret,omitempty"`
}

type ManifestPlugin

type ManifestPlugin struct {
	ID      string `json:"id" yaml:"id"`
	Kind    string `json:"kind" yaml:"kind"`
	Enabled bool   `json:"enabled" yaml:"enabled"`

	// Essential marks a plugin the runtime depends on (e.g. rg/fd back the
	// Grep/Glob tools). It is shipped server policy, not editable definition.
	Essential bool `json:"essential,omitempty" yaml:"essential,omitempty"`

	ManifestPluginDefinition `yaml:",inline"`

	// Builtin marks a plugin that ships with the server. It is computed when the
	// manifest is resolved, never read from a manifest or an override: a builtin
	// definition can be customized or disabled, but only an admin-added plugin
	// can be removed. `yaml:"-"` keeps it out of the shipped manifest.
	Builtin bool `json:"builtin,omitempty" yaml:"-"`

	// OverriddenFields names the definition fields an admin has taken ownership
	// of, so the editor can mark them and offer to hand one back. Like Builtin it
	// is computed at resolve time and never stored — the override row is what it
	// reports on. A boolean here would be cheaper and useless: "customized" cannot
	// tell an admin which of two pinned fields is the one they want released.
	OverriddenFields []string `json:"overridden_fields,omitempty" yaml:"-"`
}

func ApplyOverride

func ApplyOverride(base ManifestPlugin, override string) (ManifestPlugin, error)

ApplyOverride lays a stored override over the builtin definition. Fields the override does not own keep whatever the running binary ships, which is the entire point; a null owns one as empty.

func PluginFromDefinition

func PluginFromDefinition(id, override string) (ManifestPlugin, error)

PluginFromDefinition reads a whole stored definition as a plugin. Used for admin-added plugins, which have no builtin base.

type ManifestPluginDefinition

type ManifestPluginDefinition struct {
	Name          string               `json:"name" yaml:"name"`
	DisplayName   string               `json:"display_name" yaml:"display_name"`
	Description   string               `json:"description" yaml:"description"`
	Category      string               `json:"category,omitempty" yaml:"category,omitempty"`
	Prompt        string               `json:"prompt,omitempty" yaml:"prompt,omitempty"`
	Binaries      []ManifestBinary     `json:"binaries,omitempty" yaml:"binaries,omitempty"`
	Skills        []ManifestSkill      `json:"skills,omitempty" yaml:"skills,omitempty"`
	SessionEnvs   []ManifestSessionEnv `json:"session_env,omitempty" yaml:"session_env,omitempty"`
	OAuthProvider string               `json:"oauth_provider,omitempty" yaml:"oauth_provider,omitempty"`
}

ManifestPluginDefinition is the editable definition of a manifest plugin. Resource state and server-owned metadata live on ManifestPlugin instead.

type ManifestSessionEnv

type ManifestSessionEnv struct {
	EnvVar   string `json:"env_var" yaml:"env_var"`
	Source   string `json:"source" yaml:"source"`
	Value    string `json:"value,omitempty" yaml:"value,omitempty"`
	Required bool   `json:"required,omitempty" yaml:"required,omitempty"`
}

type ManifestSkill

type ManifestSkill struct {
	Repo string `json:"repo" yaml:"repo"`
	Name string `json:"name" yaml:"name"`
}

type ManifestState

type ManifestState struct {
	UpdatedAt time.Time                     `json:"updated_at"`
	Plugins   map[string]PluginInstallState `json:"plugins"`
}

func LoadState

func LoadState(path string) (*ManifestState, error)

LoadState reads the manifest state file at path. If the file does not exist, an empty state is returned.

type PluginInstallState

type PluginInstallState struct {
	Binaries []BinaryInstallState `json:"binaries,omitempty"`
	Skills   []SkillInstallState  `json:"skills,omitempty"`
}

type PluginReconcileResult

type PluginReconcileResult struct {
	PluginID string
	Binaries []BinaryReconcileResult
	// Skills not yet implemented (bundled-only in v1), but reserved for future use
	Err error
}

PluginReconcileResult holds the result for a single plugin.

type ReconcileResult

type ReconcileResult struct {
	EnabledCount int
	// Per-plugin results, keyed by plugin ID
	Plugins map[string]PluginReconcileResult
}

ReconcileResult summarizes one reconcile run.

func Reconcile

func Reconcile(ctx context.Context, m *Manifest, stellaHome string) ReconcileResult

Reconcile processes all enabled plugins in the manifest, downloading any binaries that are not already at the correct version according to the state file.

type RegistryTool

type RegistryTool struct {
	Name     string   `json:"name"`
	Backends []string `json:"backends"`
}

RegistryTool is one entry from `mise registry`: a short name and the backend keys that can provide it (e.g. "aqua:anthropics/claude-code", "npm:@anthropic-ai/claude-code"). Either the short name or a backend key is a valid mise tool spec for a manifest binary.

func SearchRegistry

func SearchRegistry(ctx context.Context, stellaHome, query string, limit int) ([]RegistryTool, error)

SearchRegistry returns registry tools whose name or backend keys contain query (case-insensitive), ranked by name relevance. An empty query returns nothing — the registry has thousands of entries and is meant to be filtered. Results are capped at limit (default 30).

type SkillInstallState

type SkillInstallState struct {
	Repo        string    `json:"repo"`
	Name        string    `json:"name"`
	InstalledAt time.Time `json:"installed_at"`
}

type StoredOverride

type StoredOverride struct {
	PluginID string
	Enabled  *bool
	Config   string
}

StoredOverride is one persisted customization, as the caller's store holds it. It is declared here rather than imported so this package keeps owning the merge protocol without depending on the storage layer that happens to carry it.

Jump to

Keyboard shortcuts

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