plugin

package
v0.2.0-alpha.2 Latest Latest
Warning

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

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

Documentation

Overview

Package plugin owns the plugin manifest: its format, its rules, and the version arithmetic that decides whether a build may run a release.

It is pure domain code with no I/O because both sides of distribution need it and they cannot share anything above core: internal/server may not import internal/config (see internal/architecture), so discovery and publication would otherwise each grow their own parser and drift apart.

Index

Constants

View Source
const ManifestFile = "plugin.yaml"

ManifestFile is the file whose presence makes a directory a plugin.

View Source
const VarPluginRoot = "BUILDMAX_PLUGIN_ROOT"

VarPluginRoot is the variable a plugin's own MCP and hook configuration uses to reach files it ships. It resolves to the directory holding plugin.yaml.

It names part of the document format, so it lives beside the format rather than beside the code that expands it.

Variables

View Source
var ErrAlreadyActivated = errors.New("this team has already activated this plugin")

ErrAlreadyActivated means the team already has an activation for this plugin. Moving to another release is a pin change, not a second activation, which is why the two are different calls.

View Source
var ErrArchived = errors.New("this plugin is archived and accepts no new releases")

ErrArchived is returned when a release is published against a plugin an administrator has retired.

View Source
var ErrNameTaken = errors.New("a plugin with this name already exists")

ErrNameTaken is returned when a catalog entry already claims a name.

View Source
var ErrVersionExists = errors.New("this plugin version has already been published")

ErrVersionExists is returned when a version has already been published.

It is returned for identical bytes too. A release is what someone reviewed and what someone else downloaded, so replacing one would leave both of those facts describing something that is no longer there.

Functions

func HasErrors

func HasErrors(findings []Finding) bool

HasErrors reports whether any finding blocks use of the manifest.

func Parse

func Parse(data []byte) (Manifest, []Finding, error)

Parse reads a plugin.yaml.

The returned error means the bytes are not a manifest document at all, which is the one case where no partial result exists. Every rule violation is a findings entry instead, so `plugin validate` can report a whole file rather than the first thing wrong with it. Callers that must decide whether to load the plugin check HasErrors.

func ValidCuration

func ValidCuration(s Curation) bool

ValidCuration reports whether s is a mode that may be stored. The write path checks it so the read path has only two values to consider.

func ValidateName

func ValidateName(name string) error

ValidateName reports why a string cannot be a plugin name. The name is also a directory name under <BUILDMAX_HOME>/plugins, so anything path-shaped is out.

Types

type ActivateInput

type ActivateInput struct {
	TeamID     string
	PluginName string
	Version    string
	Digest     string
	Origin     ActivationOrigin
	ActorID    string
}

ActivateInput pins one release for one team.

Version and Digest are supplied rather than resolved here. The caller has already read the release to decide it may be activated at all, and a store that resolved again could pin bytes nobody checked.

type Activation

type Activation struct {
	ID         string `json:"id"`
	TeamID     string `json:"team_id"`
	PluginName string `json:"plugin_name"`
	Version    string `json:"version"`
	Digest     string `json:"digest"`
	// Enabled false suspends the activation without losing the pin. A suspended
	// activation fails the runs of the agents that name it rather than quietly
	// dropping the plugin from them.
	Enabled bool             `json:"enabled"`
	Origin  ActivationOrigin `json:"origin"`

	ActivatedBy string    `json:"activated_by"`
	ActivatedAt time.Time `json:"activated_at"`
	UpdatedBy   string    `json:"updated_by,omitempty"`
	UpdatedAt   time.Time `json:"updated_at"`
}

Activation is one team's pinned use of one catalog plugin.

The pin is the point. A release published after this row was written cannot change what a run loads — in either curation mode — until a person moves it.

type ActivationOrigin

type ActivationOrigin string

ActivationOrigin says who put an activation there.

const (
	// ActivationCurated is an activation an admin made deliberately.
	ActivationCurated ActivationOrigin = "curated"
	// ActivationAutomatic is one created because an agent named the
	// plugin in an open-mode team. It is labelled so a team's list reads as the
	// history it is rather than as one somebody curated.
	ActivationAutomatic ActivationOrigin = "automatic"
)

type ClientVersion

type ClientVersion struct {
	Version Version
	// Known is false for a build whose version cannot be placed on the release
	// line at all — "dev", a Go pseudo-version, anything unparseable. Such a
	// build satisfies every bound, because refusing to run on an unknown
	// version would break every contributor's checkout.
	Known bool
}

ClientVersion is what a running build reports about itself, which is not always a release version.

func ParseClientVersion

func ParseClientVersion(s string) ClientVersion

ParseClientVersion classifies a build's own version string.

A `git describe` version such as "0.1.0-3-gabc1234" is three commits *after* v0.1.0, but semver reads that suffix as a prerelease and would sort it below 0.1.0. It is therefore reduced to its base tag, which is the newest release the build is known to contain.

func (ClientVersion) Satisfies

func (c ClientVersion) Satisfies(min Version) bool

Satisfies reports whether this build meets a plugin's min_buildmax_version.

type CreateInput

type CreateInput struct {
	Name        string
	DisplayName string
	Description string
	CreatedBy   string
}

CreateInput creates a catalog entry.

type CreateReleaseInput

type CreateReleaseInput struct {
	PluginName         string
	Version            string
	MinBuildmaxVersion string
	Digest             string
	ObjectKey          string
	SizeBytes          int64
	Inspection         Inspection
	Source             ReleaseSource
	PublishedBy        string
}

CreateReleaseInput publishes one version. Digest, ObjectKey, and SizeBytes describe bytes the server has already stored.

type Curation

type Curation string

Curation is a team's answer to who fills its activation list.

The modes differ in that and nothing else: both produce a pinned activation with the same digest, audit event, and trace provenance. See docs/design/plugin-team-distribution.md §4.1.

const (
	// CurationOpen lets an agent name any catalog plugin and creates the
	// activation the first time one does. It is the default because the gate
	// that crosses teams is operator eligibility, not a team's housekeeping.
	CurationOpen Curation = "open"
	// CurationCurated requires an admin to activate a plugin before an
	// agent may name it.
	CurationCurated Curation = "curated"
)

func NormalizeCuration

func NormalizeCuration(s string) Curation

NormalizeCuration reads a stored value. Empty is open: a team that has never set the mode has not asked to be restricted.

type EnvVar

type EnvVar struct {
	Name        string
	Description string
	// Required defaults to true: declaring a variable at all normally means the
	// plugin wants it.
	Required bool
}

EnvVar is one declared environment variable. It carries a name and prose and never a value.

type Finding

type Finding struct {
	Severity Severity
	Field    string
	Line     int
	Message  string

	// Plugins names the plugins a finding concerns, so a surface can attribute
	// a collision to every side of it. Filtering on the message text instead
	// would break the first time a message was reworded.
	Plugins []string
}

Finding is one thing parsing or validation noticed. Line is 1-based and 0 when the position is unknown, so callers can print a plain message instead of a fake location.

func Errors

func Errors(findings []Finding) []Finding

Errors returns only the blocking findings, for a caller that reports the reason a directory was rejected.

func (Finding) Concerns

func (f Finding) Concerns(name string) bool

Concerns reports whether this finding is about the named plugin.

func (Finding) String

func (f Finding) String() string

type Hook

type Hook struct {
	Event      string `json:"event"`
	Type       string `json:"type"`
	Matcher    string `json:"matcher,omitempty"`
	Executable string `json:"executable,omitempty"`
	Host       string `json:"host,omitempty"`
	MCPServer  string `json:"mcp_server,omitempty"`
	MCPTool    string `json:"mcp_tool,omitempty"`
}

Hook is the catalog-safe part of one contributed hook.

type Inspection

type Inspection struct {
	Skills      []string    `json:"skills,omitempty"`
	Subagents   []Subagent  `json:"subagents,omitempty"`
	MCP         []MCPServer `json:"mcp,omitempty"`
	Hooks       []Hook      `json:"hooks,omitempty"`
	EnvRefs     []string    `json:"env_refs,omitempty"`
	PluginPaths []string    `json:"plugin_paths,omitempty"`
	// Warnings are the findings that did not stop publication, kept so an
	// installer can show what a publisher chose to accept.
	Warnings []string `json:"warnings,omitempty"`
}

Inspection is what a release says it contributes.

Its shapes deliberately contain only what a catalog may store: names, transports, executables, and hosts — never arguments, header values, environment values, prompts, or file contents.

type Layer

type Layer string

Layer is one of the three places a contributed definition can come from. They are named here because plugins made the layering visible: before a third source existed, "the other directory" needed no vocabulary.

const (
	LayerWorkspace Layer = "workspace"
	LayerGlobal    Layer = "global"
	LayerPlugin    Layer = "plugin"
)

type MCPServer

type MCPServer struct {
	ID         string `json:"id"`
	Transport  string `json:"transport"`
	Executable string `json:"executable,omitempty"`
	Host       string `json:"host,omitempty"`
}

MCPServer is the catalog-safe part of one contributed MCP server.

type Manifest

type Manifest struct {
	Name        string
	Version     string
	Description string

	DisplayName string
	Homepage    string
	Maintainer  string
	License     string

	MinBuildmaxVersion string

	// Env is the declared environment contract, in file order.
	Env []EnvVar

	// Unknown lists top-level keys this build did not recognise, in file
	// order. They are kept rather than dropped so `plugin validate` can show a
	// misspelling that would otherwise be invisible.
	Unknown []string
}

Manifest is a parsed plugin.yaml. Only Name is required to load a plugin; Version is additionally required to publish one.

func (Manifest) DisplayTitle

func (m Manifest) DisplayTitle() string

DisplayTitle is what a catalog or a Desktop list shows.

func (Manifest) EnvVarByName

func (m Manifest) EnvVarByName(name string) (EnvVar, bool)

EnvVarByName returns the declared entry for a variable name.

type MovePinInput

type MovePinInput struct {
	TeamID     string
	PluginName string
	Version    string
	Digest     string
	ActorID    string
}

MovePinInput repoints an existing activation at another release. It is separate from activation because it is the action that needs a person to have read the new release's capability report.

type Origin

type Origin struct {
	Layer Layer
	// Plugin is the plugin's name when Layer is LayerPlugin.
	Plugin string
	// Dir is the directory that was scanned.
	Dir string
}

Origin is where one definition was found.

func (Origin) String

func (o Origin) String() string

type Pin

type Pin struct {
	PluginName string `json:"plugin_name"`
	Version    string `json:"version"`
	Digest     string `json:"digest"`
}

Pin is one resolved activation as a run receives it.

It is the activation reduced to what materializing needs — which package, and the digest to check it against — because a worker has no business holding a team's activation record.

type Plugin

type Plugin struct {
	// Name is the manifest name, unique in the deployment, and the slug every
	// route addresses the plugin by.
	Name        string `json:"name"`
	DisplayName string `json:"display_name,omitempty"`
	Description string `json:"description,omitempty"`
	// ArchivedAt hides the entry from the default catalog and refuses new
	// releases. It never deletes anything: a local copy someone installed keeps
	// working, and the record still explains where that copy came from.
	ArchivedAt *time.Time `json:"archived_at,omitempty"`
	CreatedBy  string     `json:"created_by"`
	CreatedAt  time.Time  `json:"created_at"`
	UpdatedAt  time.Time  `json:"updated_at"`
}

Plugin is a catalog entry: the stable identity releases are published under.

The entry belongs to the deployment rather than to a team, so it carries no team. Publishing is a System Administrator action; see docs/design/plugin-marketplace.md §7.1.

func (Plugin) Archived

func (p Plugin) Archived() bool

Archived reports whether the entry has been retired.

type Provenance

type Provenance struct {
	Name   string `json:"name"`
	Source string `json:"source,omitempty"`

	RemoteURL string `json:"remote_url,omitempty"`
	Commit    string `json:"commit,omitempty"`
	Branch    string `json:"branch,omitempty"`
	// Dirty is a pointer so a clean checkout records false rather than
	// omitting the field: an absent flag reads as "nobody looked", and a
	// reader resolving that silence in the run's favour would credit it with
	// an immutable input it did not have.
	Dirty *bool `json:"dirty,omitempty"`

	MarketplaceServer string `json:"marketplace_server,omitempty"`
	CatalogID         string `json:"catalog_id,omitempty"`
	Version           string `json:"version,omitempty"`
	Digest            string `json:"digest,omitempty"`
}

Provenance is the bounded metadata a run records about one plugin: enough to identify what was loaded, and nothing from inside the package.

A repository plugin is identified by its checkout, a Marketplace plugin by the release it came from. Neither half carries configuration values, prompts, or secrets.

type Release

type Release struct {
	// PluginName is denormalised so a release can be reported without a second
	// read; the catalog entry remains the owner of the name.
	PluginName string `json:"plugin_name"`
	Version    string `json:"version"`
	// MinBuildmaxVersion is the release's own lower bound, kept as a column
	// because default install selection filters on it.
	MinBuildmaxVersion string `json:"min_buildmax_version,omitempty"`

	// Digest is the labelled SHA-256 of the stored bytes, calculated by the
	// server rather than accepted from the publisher.
	Digest    string `json:"digest"`
	ObjectKey string `json:"object_key"`
	SizeBytes int64  `json:"size_bytes"`

	// Inspection is the sanitized capability report shown before an install.
	Inspection Inspection `json:"inspection"`
	// Source is where the publisher says the bytes came from. Unlike the
	// digest, the server cannot verify it, so it is presented as a claim.
	Source ReleaseSource `json:"source"`

	PublishedBy string    `json:"published_by"`
	PublishedAt time.Time `json:"published_at"`

	// YankedAt removes the release from default selection without deleting it.
	// An existing local copy keeps working, and an exact version can still be
	// recovered by someone who acknowledges the state.
	YankedAt     *time.Time `json:"yanked_at,omitempty"`
	YankedBy     string     `json:"yanked_by,omitempty"`
	YankedReason string     `json:"yanked_reason,omitempty"`
}

Release is one immutable published version.

func (Release) Yanked

func (r Release) Yanked() bool

Yanked reports whether the release has been withdrawn from default selection.

type ReleaseSource

type ReleaseSource struct {
	RemoteURL string `json:"remote_url,omitempty"`
	Commit    string `json:"commit,omitempty"`
	Branch    string `json:"branch,omitempty"`
	// Dirty says the working tree held uncommitted changes when it was packed,
	// which means the commit above does not describe these bytes.
	Dirty bool `json:"dirty,omitempty"`
}

ReleaseSource is the publisher's claim about where the bytes came from.

A package assembled by hand rather than committed is a legitimate case, so an empty record is not an error — it is the absence of a claim.

type Severity

type Severity int

Severity separates what stops a plugin from loading from what a reader should merely be told.

const (
	SeverityError Severity = iota
	SeverityWarning
)

func (Severity) String

func (s Severity) String() string

type Shadowed

type Shadowed struct {
	Name   string
	Winner Origin
	Loser  Origin
}

Shadowed records a definition that lost to a higher-priority one. It is data rather than a warning: a workspace overriding a plugin is the documented precedence working, and the only failure would be showing the plugin as fully active when part of it never loads.

type Source

type Source struct {
	Dir    string
	Origin Origin
}

Source is one directory to scan for contributed definitions, and what that directory represents.

It lives in core so that the package building the list and the package doing the scanning need not import each other: internal/config owns where to look, internal/tool owns how to read what is there.

type Subagent

type Subagent struct {
	Name  string   `json:"name"`
	Tools []string `json:"tools,omitempty"`
	Model string   `json:"model,omitempty"`
}

Subagent is the catalog-safe part of one contributed subagent. Its prompt is deliberately absent.

type UpdateInput

type UpdateInput struct {
	DisplayName string
	Description string
}

UpdateInput changes the display metadata of an entry. The name is not here: it identifies the plugin every installed copy came from.

type Version

type Version struct {
	Major int
	Minor int
	Patch int
	// Pre holds prerelease identifiers, empty for a release version.
	Pre []string
}

Version is a semantic version. Build metadata is accepted and discarded: it never affects ordering, and keeping it would invite comparisons that do.

func ParseVersion

func ParseVersion(s string) (Version, error)

ParseVersion parses a plugin or bound version. A leading "v" is rejected rather than trimmed, so one spelling reaches the catalog.

func (Version) Compare

func (v Version) Compare(o Version) int

Compare orders two versions by semantic version precedence: -1, 0, or 1.

func (Version) IsRelease

func (v Version) IsRelease() bool

IsRelease reports whether this version is not a prerelease. Default install selection skips everything else.

func (Version) String

func (v Version) String() string

Jump to

Keyboard shortcuts

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