plugin

package
v0.39.6 Latest Latest
Warning

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

Go to latest
Published: Aug 18, 2026 License: MIT Imports: 23 Imported by: 0

Documentation

Overview

Package plugin is the wick connector plugin platform: the shared transport (hashicorp/go-plugin + gRPC) used by the host to drive a connector that runs in its own process, and the SDK a connector binary uses to serve itself. See docs/proposals/connector-plugin-platform.

Index

Constants

View Source
const (
	KindConnector = "connector"
	KindTool      = "tool"
	KindJob       = "job"
)

Plugin kinds. connector is the default and the only kind with a host-side execution adapter today; tool/job are accepted by the manifest + build tooling so the layout and CLI are forward-compatible (§18).

View Source
const EnvReattachOut = "WICK_PLUGIN_REATTACH_OUT"

EnvReattachOut, when set on a plugin process, switches Serve into debug (reattach) mode: instead of the normal go-plugin stdout handshake — which only works when the host is the process that spawned it — the plugin serves in test mode and writes its ReattachConfig as JSON to the named file. A host that finds a LIVE reattach file for this key attaches to this already-running process (see Manager.spawn) so breakpoints in the plugin bind.

Run the plugin binary under a debugger (dlv) with this set, let it write the file, then start wick-lab; wick-lab attaches instead of spawning its own un-debuggable child.

View Source
const ManifestSchemaVersion = 1

ManifestSchemaVersion is the current envelope format version.

View Source
const MaxGRPCMessageBytes = 64 << 20

MaxGRPCMessageBytes is the plugin transport's max gRPC message size (both directions, both ends). gRPC defaults to 4 MiB recv, which is too small for ops that carry file payloads — e.g. extension_install sends a browser extension as base64 (a 4 MB .crx becomes ~6 MB on the wire). 64 MiB matches the connector-side upload cap. Server + client must agree, so both read this.

View Source
const MinProtoVersion = 1

MinProtoVersion is the OLDEST proto version this host still accepts. The host supports the inclusive range [MinProtoVersion, ProtoVersion]; a plugin built against any version in that range loads, anything outside is rejected at handshake/verify with a clear error (never a crash).

This is the range-negotiation contract (§19.2): bumping ProtoVersion for a breaking change while leaving MinProtoVersion behind opens a transition window where v(old) and v(new) plugins both run; dropping support for an old version is a deliberate MinProtoVersion bump, not an accident.

View Source
const PluginName = "connector"

PluginName is the dispense key both sides agree on.

View Source
const ProtoVersion = 1

ProtoVersion is the wire-contract version a freshly built plugin stamps into its manifest (the version this build of the SDK speaks natively). It bumps ONLY on a breaking proto change.

Variables

View Source
var ErrPluginOp = errors.New("plugin operation error")

ErrPluginOp wraps an operation-level error returned by the plugin (vs a transport error). Callers can errors.Is against it.

View Source
var Handshake = goplugin.HandshakeConfig{
	ProtocolVersion:  ProtoVersion,
	MagicCookieKey:   "WICK_CONNECTOR_PLUGIN",
	MagicCookieValue: "b3f1c2a4-wick-connector-grpc",
}

Handshake is the basic mutual sanity check go-plugin runs before any RPC: a plugin launched without the matching magic cookie exits with a human-readable error instead of hanging.

View Source
var RequireSignature bool

RequireSignature, when true (set via ldflags in release builds), makes the loader reject any plugin without a valid signature from a trusted key. The env var WICK_PLUGIN_REQUIRE_SIGNATURE ("1"/"0") overrides it at runtime.

View Source
var TrustedPubKey string

TrustedPubKey is the publisher's base64 ed25519 public key baked into a released wick binary via -ldflags. Empty in dev builds.

View Source
var Version = "0.0.0-dev"

Version is the connector release version stamped into the manifest. It is overridden at build time via -ldflags "-X .../pkg/plugin.Version=1.2.3".

View Source
var VersionedPlugins = buildVersionedPlugins()

VersionedPlugins maps proto_version -> plugin set. The host advertises every version in [MinProtoVersion, ProtoVersion]; go-plugin negotiates the highest version common to host and plugin and rejects (clear error, no crash) a plugin whose version falls outside the host's range. Built from the supported range so adding a future v2 plugin set is the only edit needed.

Functions

func DataDir added in v0.28.4

func DataDir(key string) string

DataDir returns the persistent per-plugin work directory for the given plugin key — the place a plugin should store downloaded assets, caches, and session state so they SURVIVE (unlike os.TempDir(), which the OS / Storage Sense wipes).

It is resolved entirely plugin-side from the running binary's own location — no env var, no host cooperation. Installed plugin binaries live at

<appDataDir>/plugins/connectors/<key>/<key>[.exe]

so the sibling data dir is two levels up from the binary's folder, alongside the connectors/ dir:

<appDataDir>/plugins/<key>/

This sits ALONGSIDE the connectors/ dir (binaries + plugin.json), never inside it, so wiping a plugin's data never touches its installed binary or catalog.

If the binary isn't laid out under a .../plugins/connectors/ tree (e.g. a bare `go run` during development, or a `go test`), it falls back to <os-temp>/wick-plugins/<key> — good enough for throwaway runs, and the only case where OS temp is acceptable.

func DumpManifest

func DumpManifest(mod connector.Module) ([]byte, error)

DumpManifest returns json.Marshal(mod) — the manifest is the module itself, so the plugin.json on disk can never drift from the binary.

func GenerateKeypair

func GenerateKeypair() (privB64, pubB64 string)

GenerateKeypair returns a fresh ed25519 keypair as base64 strings (private = 64-byte seed||pub, public = 32-byte).

func NewServer

func NewServer(mod connector.Module) pb.ConnectorServer

NewServer builds the plugin-side service for one connector module.

func NormalizeKind

func NormalizeKind(k string) string

NormalizeKind returns a valid kind, defaulting empty/unknown to connector.

func ProtoVersionSupported

func ProtoVersionSupported(v int) bool

ProtoVersionSupported reports whether v is within the accepted range.

func ReadReattachConfig added in v0.33.0

func ReadReattachConfig(path string) (*goplugin.ReattachConfig, error)

ReadReattachConfig loads a reattach file and rebuilds the ReattachConfig a host needs to attach — but ONLY when the plugin is actually reachable. It dials the address (short timeout) as the real liveness signal: a stale file from a stopped/relaunched debugger fails the dial, and the caller falls back to a normal spawn instead of attaching to a dead process. This is what makes reattach robust against dlv relaunches (new pid/port each time).

func ReattachPluginSet added in v0.33.0

func ReattachPluginSet() goplugin.PluginSet

ReattachPluginSet is the plugin descriptor set a host must pass as ClientConfig.Plugins when reattaching. Reattach bypasses version negotiation, so go-plugin never copies the matching VersionedPlugins entry into config.Plugins on its own; without this the dispense fails with "unknown plugin type". The host descriptor carries no Impl (it receives a client).

func RequireSig

func RequireSig() bool

RequireSig reports the effective signature-required policy (env overrides the baked default).

func Serve

func Serve(mod connector.Module)

Serve is the entire main() of a connector plugin binary. Call it with the module the binary wraps. When invoked with --dump-manifest it prints the manifest JSON and exits (used by `make plugins` / CI); otherwise it serves the gRPC plugin and blocks until the host disconnects.

func SignSHA256

func SignSHA256(privKeyPath, sha256hex string) (string, error)

SignSHA256 reads a base64 ed25519 private key from privKeyPath and signs the sha256 hex string, returning the base64 signature.

func SupportedProtoVersions

func SupportedProtoVersions() []int

SupportedProtoVersions returns every proto version this host can speak, newest first. Used both to advertise VersionedPlugins to go-plugin and to validate a manifest's declared version.

func TrustedKeys

func TrustedKeys() []string

TrustedKeys returns every trusted base64 public key: the baked TrustedPubKey plus any in WICK_PLUGIN_PUBKEY (comma-separated).

func ValidateKey

func ValidateKey(key string) error

ValidateKey enforces that a plugin's Meta.Key is a safe slug. Key is the one identity used everywhere — the source folder, the zip name, the on-disk install dir (DefaultDir/<key>), and the runtime registry key — so it must be a plain lowercase slug with no path separators or traversal (it becomes a directory name; a key like "../x" or "a/b" would escape the plugins dir). Enforced at BOTH build time and install time so a hand-written manifest can't sneak a bad key past the build.

func VerifyManifest

func VerifyManifest(m Manifest, binaryPath string) error

VerifyManifest checks a plugin envelope against the binary at binaryPath and the host's trust policy. Returns nil when the plugin is safe to load. Order: os_arch -> proto_version -> sha256 integrity -> signature.

func VerifySHA256

func VerifySHA256(trustedPubsB64 []string, sha256hex, sigB64 string) bool

VerifySHA256 reports whether sigB64 is a valid signature of sha256hex by ANY of the trusted base64 public keys. Bad inputs return false (no panic).

Types

type ConnectorGRPCPlugin

type ConnectorGRPCPlugin struct {
	goplugin.NetRPCUnsupportedPlugin
	Impl pb.ConnectorServer
}

ConnectorGRPCPlugin is the go-plugin descriptor. Impl is set only on the plugin side (it carries the server implementation); the host leaves it nil and receives a client from GRPCClient.

func (*ConnectorGRPCPlugin) GRPCClient

func (*ConnectorGRPCPlugin) GRPCServer

func (p *ConnectorGRPCPlugin) GRPCServer(_ *goplugin.GRPCBroker, s *grpc.Server) error

type ExecCall

type ExecCall struct {
	Operation string
	Input     map[string]string
	Creds     map[string]string
	RequestID string
	SessionID string
}

ExecCall is the host-side call descriptor the adapter closure fills from a *connector.Ctx (operation + plaintext input + plaintext creds).

type GRPCConn

type GRPCConn interface {
	Execute(ctx context.Context, call ExecCall) ([]byte, error)
	ExecuteStream(ctx context.Context, call ExecCall) ([]byte, error)
	Schema(ctx context.Context) ([]byte, error)
	ResolveIdentity(ctx context.Context, accessToken string) (userID, displayName string, err error)
}

GRPCConn is the host-facing surface of a connector plugin client. The manager hands this to the adapter closure; *grpcClient implements it.

type Manifest

type Manifest struct {
	SchemaVersion int `json:"schema_version"`
	// Kind is the plugin kind: "connector" (default), "tool", or "job". The
	// platform routes installed plugins by kind into the matching registry;
	// all kinds share the same gRPC service (Execute(op,args)→result is generic
	// enough for a tool's Run(input) and a job's Run(trigger)). Empty = the
	// pre-kind default "connector" for backward compatibility.
	Kind         string           `json:"kind,omitempty"`
	Version      string           `json:"version"`
	ProtoVersion int              `json:"proto_version"`
	Entry        string           `json:"entry"`
	OSArch       []string         `json:"os_arch"`
	SHA256       string           `json:"sha256"`
	Signature    string           `json:"signature"`
	Module       connector.Module `json:"module"`
}

Manifest is the on-disk plugin.json envelope: the connector module plus the distribution metadata the host needs to verify and load it. The connector module marshals with its func fields excluded (json:"-"), so the envelope is fully round-trippable.

func BuildSelfManifest

func BuildSelfManifest(mod connector.Module, signKeyPath string) (Manifest, error)

BuildSelfManifest builds the envelope for a connector plugin binary from the binary itself (self-pack): it hashes os.Executable() and, when signKeyPath is non-empty, signs that hash. mod is the connector's module.

Directories

Path Synopsis

Jump to

Keyboard shortcuts

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