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 ¶
- Variables
- func DefinitionJSON(p ManifestPlugin) (string, error)
- func IsOwnableField(name string) bool
- func LatestVersion(ctx context.Context, stellaHome, tool string) (string, error)
- func OwnableFields() []string
- func OwnedFields(override string) ([]string, error)
- func ReleaseField(override, field string) (string, error)
- func RuntimeMiseEnv(stellaHome, userToolsDir, userConfigDir, workspaceDir string) map[string]string
- func SaveState(path string, s *ManifestState) error
- func ScopeConfigPath(stellaHome, scope string) string
- func SetFields(override string, edited ManifestPlugin, fields []string) (string, error)
- func StatePath(stellaHome string) string
- func Validate(m *Manifest) error
- type BinaryInstallState
- type BinaryReconcileResult
- type Manifest
- type ManifestBinary
- type ManifestOAuthFlow
- type ManifestOAuthProvider
- type ManifestPlugin
- type ManifestPluginDefinition
- type ManifestSessionEnv
- type ManifestSkill
- type ManifestState
- type PluginInstallState
- type PluginReconcileResult
- type ReconcileResult
- type RegistryTool
- type SkillInstallState
- type StoredOverride
Constants ¶
This section is empty.
Variables ¶
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 ¶
IsOwnableField reports whether name is a definition field an override may own.
func LatestVersion ¶
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 ¶
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 ¶
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 ¶
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 ¶
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".
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 ¶
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 ¶
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 ManifestSkill ¶
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.
type RegistryTool ¶
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 StoredOverride ¶
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.