Help us shape the future of Go! Take the 2026 Go Developer Survey

manifestv2

package
v1.4.14 Latest Latest
Warning

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

Go to latest
Published: Oct 12, 2026 License: MIT Imports: 14 Imported by: 0

Documentation

Overview

Package manifestv2 owns the plugin manifest v2 contract (contract:plugin.manifest).

Purpose: one machine-checkable definition of plugin.json. The Go types here generate schemas/plugin-manifest.v2.schema.json (tools/schemagen), Load is the single reader (v2 natively, v1 through one normalizer), and Projection is the single derivation of the compatibility keys that released 1.4.x CLIs decode.

Inputs: plugin.json bytes or a path. Outputs: a validated *Manifest or a coded error (E106, E111-E114). Constraints: layer L0 (Constitution 2.1): the standard library, internal/errs and internal/compat only; it never imports internal/plugin or cmd/. Released CLIs decode plugin.json permissively, so a v2 key never reuses a v1 key with another JSON type (Epic D1, ADR 0009).

Index

Constants

View Source
const (
	LicenseFree     = "free"
	LicenseLicensed = "licensed"
)

Licence values (D2: bundle membership is not a manifest field).

View Source
const (
	MaturityImplemented  = "implemented"
	MaturityExperimental = "experimental"
	MaturityScaffolded   = "scaffolded"
	MaturityPlanned      = "planned"
	MaturityDeferred     = "deferred"
)

Maturity values (the lifecycle enum; the v1 `status` key is a compatibility key).

View Source
const (
	StateDeprecated = "deprecated"
	StateEOL        = "eol"
)

Deprecation states (deprecation.state, required when maturity is deferred).

View Source
const (
	KindCompose = "compose"
	KindCLI     = "cli"
	KindLibrary = "library"
)

Service kinds.

View Source
const (
	SideRead        = "read"
	SideWrite       = "write"
	SideRemote      = "remote"
	SideDestructive = "destructive"
	OutDocument     = "document"
	OutStream       = "stream"
	OutInteractive  = "interactive"
	JSONNone        = "none"
	JSONLegacy      = "legacy"
	JSONEnvelope    = "envelope"
	SurfaceAll      = "all"
	SurfaceCLIOnly  = "cli-only"
)

Command attribute values (CANON D5-D7 vocabulary).

View Source
const (
	NamePattern    = `^[a-z][a-z0-9-]*$`
	BinaryPattern  = `^nself-[a-z][a-z0-9-]*$`
	VersionPattern = `^v?[0-9]+\.[0-9]+\.[0-9]+(-[a-zA-Z0-9.]+)?(\+[a-zA-Z0-9.]+)?$`
)

Patterns, shared by validation and the generated schema.

View Source
const ManifestVersion = 2

ManifestVersion is the value of manifest_version in a v2 file.

Variables

Enum lists, shared by validation and the generated schema.

View Source
var CoreVerbs = []string{"init", "start", "stop", "restart", "status", "logs", "doctor", "build", "reset",
	"clean", "add", "remove", "config", "db", "backup", "deploy", "update", "license", "mcp", "exec"}

CoreVerbs are the ADR 0016 core command verbs a plugin may not claim (E113). TestCoreVerbsMatchCanon keeps this list equal to internal/canon.Verbs.

View Source
var ForbiddenKeys = []string{"author_public_key", "bundles", "checksum", "signature", "tier_pair"}

ForbiddenKeys are rejected (E111) in a v2 file: they belong to the registry, the release pipeline or ADR 0008 (bundle membership), never to a manifest.

Functions

func ApplyCompat

func ApplyCompat(data []byte) ([]byte, error)

ApplyCompat returns the canonical bytes of a v2 file with only its compatibility keys rewritten to Projection (E112 is what a stale file fails). Every other key keeps its value.

func ApplyProjection

func ApplyProjection(m *Manifest)

ApplyProjection writes Projection(m) into m's compatibility keys.

func Canonical

func Canonical(data []byte) ([]byte, error)

Canonical re-encodes any JSON document with sorted keys, 2-space indent and a trailing newline. Numbers keep their literal text.

func Canonicalize

func Canonicalize(m *Manifest)

Canonicalize makes absent and empty the same value (nil), so a v1 file and its v2 twin decode to equal Manifests. confirm.flags keeps its empty list.

func CheckCLITargets added in v1.4.14

func CheckCLITargets(plugin string, targets []CLITarget) error

CheckCLITargets refuses command targets the proxy cannot serve (D-0259).

A command outside NamePattern (a space, an upper-case letter, a leading digit) or a binary outside BinaryPattern is never reached by `nself <command>`; a core verb never reaches the proxy because the built-in command wins, so its binary would sit unused; a command declared twice publishes one binary over itself. plugin names the plugin in the message.

Outputs: nil, E106 (name or binary pattern, duplicate) or E113 (core verb), for the first bad target. CoreVerbs is the canon list (TestCoreVerbsMatchCanon keeps it equal to internal/canon.Verbs).

func CheckCompat

func CheckCompat(m *Manifest) error

CheckCompat proves the compatibility keys of m equal Projection(m) (E112). Only the derived keys are compared: the carried ones have no v2 source.

func IsMappedV1Key

func IsMappedV1Key(k string) bool

IsMappedV1Key reports whether the normalizer carries or converts the v1 key k in at least one shape (the migrate tool refuses a drop list that names one).

func IsV1Version

func IsV1Version(v json.RawMessage) bool

IsV1Version reports whether a raw manifest_version value marks a v1 file. Released CLIs ignore the key, so every spelling of "one or nothing" loads as v1: null, 0, "1", 1 and 1.0 (an absent key is v1 too).

func Marshal

func Marshal(m *Manifest) ([]byte, error)

Marshal renders m as the canonical plugin.json: keys sorted at every level, 2-space indent, trailing newline, HTML never escaped.

func PostgresExtensions

func PostgresExtensions(m *Manifest) []string

PostgresExtensions returns requires.postgres_extensions, empty when absent (the install check of P7-ADOPT-06 reads it).

func RegistryKeys

func RegistryKeys(data []byte) []string

RegistryKeys lists the registry-owned keys (E111 in v2) a v1 file carries; converting removes them on purpose and the migrate tool says so.

func Validate

func Validate(m *Manifest) error

Validate checks the structural rules of a v2 manifest: required keys, slug and semver shape, enums, service rules, np_ tables, boot migrations, deprecation state and the commands block. Failures are E106 naming the field, except a core-verb command, which is E113. It does not check compatibility keys (CheckCompat, E112) or the runtime permission allowlist.

Types

type Arg

type Arg struct {
	Name     string `json:"name"`
	Required bool   `json:"required,omitempty"`
	Variadic bool   `json:"variadic,omitempty"`
	Secret   bool   `json:"secret,omitempty"`
}

Arg is a positional argument (registry Arg shape plus secret).

type CLICommand

type CLICommand struct {
	Name        string `json:"name"`
	Description string `json:"description"`
}

CLICommand is one v1 cliCommands entry.

type CLITarget

type CLITarget struct {
	Binary  string
	Command string
}

CLITarget is one command binary a CLI plugin publishes: the binary file name the command proxy execs and the command that names it.

func CLITargets

func CLITargets(name, pluginType, binaryName string, commands []string) []CLITarget

CLITargets returns every command binary a plugin installs, by the installer's rule (P7-PLUG-55). It is the one definition: internal/plugin cliBinaryNames calls it, and manifestv2migrate -targets prints it, so the release pipeline builds exactly what the installer will look for.

Inputs are the v1 view of a manifest (a v2 manifest through Projection): pluginType, binaryName and the cliCommands names. A plugin whose pluginType is set and is not "cli" has none. Each cliCommands entry with a name publishes nself-<name>. With no usable entry, an explicit binaryName is the single binary, and pluginType "cli" without one falls back to nself-<name>. The command of a single binary is its name without the nself- prefix.

func CLITargetsOf

func CLITargetsOf(m *Manifest) []CLITarget

CLITargetsOf is CLITargets over a parsed manifest through its compatibility projection, which is what a released CLI reads from a v2 plugin.json.

func CheckedCLITargets added in v1.4.14

func CheckedCLITargets(name, pluginType, binaryName string, commands []string) ([]CLITarget, error)

CheckedCLITargets is CLITargets followed by CheckCLITargets: the binaries an installer may publish for the plugin, or the reason it must refuse it.

type Commands

type Commands struct {
	Command     string       `json:"command"`
	Binary      string       `json:"binary"`
	Summary     string       `json:"summary,omitempty"`
	SideEffect  string       `json:"side_effect,omitempty"`
	Output      string       `json:"output,omitempty"`
	JSON        string       `json:"json,omitempty"`
	Confirm     *Confirm     `json:"confirm,omitempty"`
	Surface     string       `json:"surface,omitempty"`
	Subcommands []Subcommand `json:"subcommands,omitempty"`
}

Commands is the CLI surface block (v1 `cli` is a different key and type). The optional root summary, side_effect, output and json decode and round-trip; absent they mean side_effect destructive and json none (CANON mount contract).

type Compat

type Compat struct {
	PluginType      string       `json:"pluginType,omitempty"`
	BinaryName      string       `json:"binaryName,omitempty"`
	CLICommands     []CLICommand `json:"cliCommands,omitempty"`
	EntryPoint      string       `json:"entryPoint,omitempty"`
	Runtime         string       `json:"runtime,omitempty"`
	CLI             string       `json:"cli,omitempty"`
	MinNselfVersion string       `json:"minNselfVersion,omitempty"`
	Status          string       `json:"status,omitempty"`
	IsCommercial    bool         `json:"isCommercial,omitempty"`
	LicenseType     string       `json:"licenseType,omitempty"`
	RequiresLicense bool         `json:"requires_license,omitempty"`
	Tier            string       `json:"tier,omitempty"`
}

Compat holds the generated compatibility keys (Epic D1). They exist so released 1.4.x CLIs keep decoding a v2 file; authors never write them. Projection derives them; CheckCompat (E112) proves they match. They are removed at v1.6.0.

EntryPoint, Runtime, CLI and the cliCommands entries other than the canonical command are carried verbatim from v1: no v2 field defines them. Tier and LicenseType are carried for a licensed plugin (max, cloud, internal) and generated as free for a free one.

func Projection

func Projection(m *Manifest) Compat

Projection derives the compatibility keys of m (Epic D1). Derived keys are recomputed from the v2 fields: pluginType and binaryName from commands, minNselfVersion from requires.nself, status from maturity and deprecation.state, isCommercial, licenseType, requires_license and tier from license, and the description of the canonical command's cliCommands entry from commands.summary. EntryPoint, Runtime, CLI and the other cliCommands entries are carried from m unchanged, and so are a licensed plugin's tier and licenseType (pro when it has none).

type CompatBlock

type CompatBlock struct {
	Nself    string            `json:"nself,omitempty"`
	Requires map[string]string `json:"requires,omitempty"`
}

CompatBlock is the v1 `compat` key: CLI and service version ranges.

type Confirm

type Confirm struct {
	Flags []string `json:"flags"`
	Plan  *Plan    `json:"plan,omitempty"`
}

Confirm names the bool flags that confirm a destructive action. An empty Flags list is valid: a nonce-only round trip (Epic D16).

type Deprecation

type Deprecation struct {
	AnnouncedDate   string `json:"announcedDate,omitempty"`
	EOLDate         string `json:"eolDate,omitempty"`
	ReplacedBy      string `json:"replacedBy,omitempty"`
	MigrationGuide  string `json:"migrationGuide,omitempty"`
	MigrationScript string `json:"migrationScript,omitempty"`
	// State is deprecated or eol; released CLIs ignore it.
	State string `json:"state,omitempty"`
}

Deprecation is the v1 deprecation block plus the v2 state.

type Env

type Env struct {
	Required []string `json:"required,omitempty"`
	Optional []string `json:"optional,omitempty"`
}

Env lists environment variable names.

type EnvVar

type EnvVar struct {
	Name        string `json:"name"`
	Required    bool   `json:"required"`
	Description string `json:"description"`
	Default     string `json:"default,omitempty"`
}

EnvVar describes an environment variable (v1 shape).

type Flag

type Flag struct {
	Name       string `json:"name"`
	Shorthand  string `json:"shorthand,omitempty"`
	Type       string `json:"type"`
	Default    string `json:"default,omitempty"`
	Usage      string `json:"usage,omitempty"`
	Hidden     bool   `json:"hidden,omitempty"`
	Required   bool   `json:"required,omitempty"`
	Persistent bool   `json:"persistent,omitempty"`
	Env        string `json:"env,omitempty"`
	SideEffect string `json:"side_effect,omitempty"`
	JSON       string `json:"json,omitempty"`
	Output     string `json:"output,omitempty"`
	Secret     bool   `json:"secret,omitempty"`
	CLIOnly    bool   `json:"cli_only,omitempty"`
}

Flag is a flag (registry Flag shape plus secret and cli_only).

type GraphQLBlock

type GraphQLBlock struct {
	Enabled      bool               `json:"enabled"`
	SubgraphName string             `json:"subgraph_name"`
	SubgraphURL  string             `json:"subgraph_url"`
	SchemaPath   string             `json:"schema_path,omitempty"`
	Entities     []GraphQLEntityKey `json:"entities,omitempty"`
}

GraphQLBlock registers the plugin as a federation subgraph (v1 shape).

type GraphQLEntityKey

type GraphQLEntityKey struct {
	Type string `json:"type"`
	Key  string `json:"key"`
}

GraphQLEntityKey names an Apollo Federation entity type.

type Manifest

type Manifest struct {
	ManifestVersion int    `json:"manifest_version"`
	Name            string `json:"name"`
	Version         string `json:"version"`
	Description     string `json:"description"`
	Category        string `json:"category"`
	// License is free or licensed (a v1 plugin.json carried an SPDX-style string
	// here; released CLIs only require it to be non-empty).
	License string `json:"license"`
	// LicenseSPDX is the licence text a v1 file carried in `license` (an SPDX
	// identifier or "Source-Available"). Optional; `plugin info` shows it.
	LicenseSPDX string `json:"license_spdx,omitempty"`
	Maturity    string `json:"maturity"`
	// Installable defaults to true when absent (ADR 0009).
	Installable *bool     `json:"installable,omitempty"`
	Requires    *Requires `json:"requires,omitempty"`
	Service     *Service  `json:"service"`
	// Commands is nil for a plugin that adds no CLI command.
	Commands   *Commands   `json:"commands,omitempty"`
	Schema     *string     `json:"schema,omitempty"`
	Migrations *Migrations `json:"migrations,omitempty"`
	Seed       *Seed       `json:"seed,omitempty"`
	Env        *Env        `json:"env,omitempty"`
	Routes     []Route     `json:"routes,omitempty"`
	// Capabilities lists what the plugin offers (a v1 key some plugins carry,
	// read from the installed plugin.json by the MCP plugin). Optional, same
	// name and type as v1.
	Capabilities []string `json:"capabilities,omitempty"`
	DocsURL      string   `json:"docs_url,omitempty"`

	Shared
	Compat
}

Manifest is a manifest_version 2 plugin.json: the canonical v2 keys, the shared v1 keys (same name and JSON type as v1) and the generated compatibility keys.

func DecodeV2

func DecodeV2(data []byte) (*Manifest, error)

DecodeV2 decodes and validates a v2 file without the compatibility check.

func Load

func Load(path string) (*Manifest, error)

Load reads a plugin.json and returns the validated v2 Manifest. A v2 file is decoded strictly and checked (Validate, CheckCompat); a v1 file (no manifest_version, or 1) is converted by the one normalizer (Normalize). Under compat.V15() a v1 file also prints the once-per-process deprecation notice.

func Normalize

func Normalize(data []byte) (*Manifest, error)

Normalize converts v1 plugin.json bytes into a validated v2 Manifest. It is the one v1 reader: the shape rules of released CLIs (grouped dependencies, object-form webhooks and envVars, object-form apiEndpoints), the status and licence tables of Epic D1, the commands mapping (binaryName becomes commands.binary, the cliCommands entry named like it becomes commands.command, `binaryName: null` becomes `commands: null`) and the service block. It checks what v1.4.12's validateManifest checks and no more (validateV1), so a file the released CLI accepts always normalizes; Validate is for v2-native input. Keys no v1.4.12 reader decodes are not mapped: UnmappedV1Keys lists them and the migrate tool refuses to write a file that has any.

func Parse

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

Parse is Load for bytes already read.

func ParseQuiet

func ParseQuiet(data []byte) (*Manifest, error)

ParseQuiet is Parse without the v1 deprecation notice, for tools that convert v1 files on purpose.

type Migrations

type Migrations struct {
	Dir   string `json:"dir"`
	Apply string `json:"apply"`
}

Migrations declares boot-applied SQL (ADR 0010).

type MultiApp

type MultiApp struct {
	Supported       bool   `json:"supported"`
	IsolationColumn string `json:"isolationColumn,omitempty"`
	PKStrategy      string `json:"pkStrategy,omitempty"`
	DefaultValue    string `json:"defaultValue,omitempty"`
}

MultiApp describes multi-tenancy (v1 shape).

type Plan

type Plan struct {
	Flag   string `json:"flag"`
	IDFlag string `json:"id_flag"`
}

Plan names the flags of a plan/apply pair of one command.

type Requires

type Requires struct {
	// Nself is a semver range for the CLI, e.g. ">=1.5.0".
	Nself string `json:"nself,omitempty"`
	// Plugins are plugin slugs.
	Plugins []string `json:"plugins,omitempty"`
	// PostgresExtensions are extension names checked at install (ADOPT).
	PostgresExtensions []string `json:"postgres_extensions,omitempty"`
}

Requires lists what must exist before the plugin can run.

type RestRoute

type RestRoute struct {
	Method  string `json:"method"`
	Path    string `json:"path"`
	Summary string `json:"summary,omitempty"`
	Auth    string `json:"auth,omitempty"`
	HMAC    string `json:"hmac,omitempty"`
}

RestRoute is one entry of the v1 rest_routes key (read by apidocs). Auth and HMAC are optional additions that carry the v1 routes entries' auth scheme and the name of the env var holding the webhook secret; released readers ignore them.

type Route

type Route struct {
	Path         string `json:"path"`
	UpstreamPort int    `json:"upstream_port"`
}

Route exposes a plugin port through nginx.

type Seed

type Seed struct {
	Command []string `json:"command"`
}

Seed is an idempotent argv run inside the plugin's service.

type Service

type Service struct {
	Kind        string  `json:"kind"`
	Compose     *string `json:"compose,omitempty"`
	Image       *string `json:"image,omitempty"`
	Port        *int    `json:"port,omitempty"`
	Healthcheck *string `json:"healthcheck,omitempty"`
}

Service describes how the plugin runs.

type Shared

type Shared struct {
	Author     string   `json:"author,omitempty"`
	Homepage   string   `json:"homepage,omitempty"`
	Repository string   `json:"repository,omitempty"`
	Tags       []string `json:"tags,omitempty"`

	Language       string   `json:"language,omitempty"`
	Port           int      `json:"port,omitempty"`
	HealthEndpoint string   `json:"health_endpoint,omitempty"`
	PackageManager string   `json:"packageManager,omitempty"`
	Framework      string   `json:"framework,omitempty"`
	MinNodeVersion string   `json:"minNodeVersion,omitempty"`
	ArchSupport    []string `json:"arch_support,omitempty"`

	Tables []string `json:"tables,omitempty"`
	Views  []string `json:"views,omitempty"`

	APIEndpoints []string    `json:"apiEndpoints,omitempty"`
	Webhooks     []string    `json:"webhooks,omitempty"`
	RestRoutes   []RestRoute `json:"rest_routes,omitempty"`
	EnvVars      []EnvVar    `json:"envVars,omitempty"`

	Dependencies         []string            `json:"dependencies,omitempty"`
	OptionalDependencies []string            `json:"optionalDependencies,omitempty"`
	SystemDependencies   *SystemDependencies `json:"systemDependencies,omitempty"`
	Consumes             []string            `json:"consumes,omitempty"`
	Provides             []string            `json:"provides,omitempty"`

	MultiApp *MultiApp `json:"multiApp,omitempty"`
	// Permissions keeps its v1 shape: an array of canonical permission strings
	// or an object grouping actions by category. Validation checks the shape;
	// the fail-closed allowlist stays with the runtime (internal/plugin).
	Permissions any `json:"permissions,omitempty"`

	CompatBlock *CompatBlock  `json:"compat,omitempty"`
	Deprecation *Deprecation  `json:"deprecation,omitempty"`
	GraphQL     *GraphQLBlock `json:"graphql,omitempty"`

	RequiredEntitlements []string          `json:"requiredEntitlements,omitempty"`
	MaxNselfVersion      string            `json:"maxNselfVersion,omitempty"`
	Visibility           string            `json:"visibility,omitempty"`
	UpdatedAt            string            `json:"updated_at,omitempty"`
	PlatformChecksums    map[string]string `json:"platform_checksums,omitempty"`
}

Shared holds the v1 keys that v2 keeps with the same name and JSON type. The authoritative list is tools/manifestv2migrate/testdata/v1412-readers.txt (the keys every v1.4.12 reader decodes); TestReaderScan keeps it covered. Polymorphic v1 shapes (grouped dependencies, object-form webhooks and so on) are authored in their one canonical shape here; the v1 normalizer converts.

type Subcommand

type Subcommand struct {
	// Name is one or more space-separated segments.
	Name       string   `json:"name"`
	Summary    string   `json:"summary,omitempty"`
	SideEffect string   `json:"side_effect,omitempty"`
	Output     string   `json:"output,omitempty"`
	JSON       string   `json:"json,omitempty"`
	Args       []Arg    `json:"args,omitempty"`
	Flags      []Flag   `json:"flags,omitempty"`
	Confirm    *Confirm `json:"confirm,omitempty"`
	Surface    string   `json:"surface,omitempty"`
}

Subcommand is one nested command path below the root.

type SystemDependencies

type SystemDependencies struct {
	Required    []SystemDependency `json:"required,omitempty"`
	Recommended []SystemDependency `json:"recommended,omitempty"`
}

SystemDependencies groups required and recommended host dependencies.

type SystemDependency

type SystemDependency struct {
	Name          string `json:"name"`
	Verify        string `json:"verify"`
	MinVersion    string `json:"minVersion,omitempty"`
	Apt           string `json:"apt,omitempty"`
	Brew          string `json:"brew,omitempty"`
	CustomInstall string `json:"custom_install,omitempty"`
}

SystemDependency is a host-level dependency (v1 shape).

type Unmapped

type Unmapped struct {
	Key  string // top-level key as written
	Path string // JSON path of its value, e.g. $.config
	Kind string // object, array, string, number or bool
	Size int    // entries of an object or array, else 0
}

Unmapped is one v1 key the normalizer has no v2 home for.

func UnmappedV1Keys

func UnmappedV1Keys(data []byte) ([]Unmapped, error)

UnmappedV1Keys lists the non-empty top-level keys of a v1 plugin.json that the normalizer does not carry into v2 (config, hooks, actions, notes, api_version, entry and so on, plus a routes, capabilities, env or env_vars value whose shape does not convert losslessly), sorted by key. Registry-owned keys (ForbiddenKeys) are not listed: ADR 0008 and the release pipeline own them, see RegistryKeys. A null, empty string, empty list or empty object has nothing to lose and is skipped.

func (Unmapped) String

func (u Unmapped) String() string

String renders "$.config (object, 3 entries)".

Jump to

Keyboard shortcuts

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