Documentation
¶
Index ¶
- Constants
- Variables
- func BindOperation(ctx context.Context, grant *OperationGrant) (context.Context, error)
- func BindOperatorTargets(ctx context.Context, targets []string) (context.Context, error)
- func CanonicalOperationPlan(plan PluginOperationPlan) (string, error)
- func CapabilityList() []string
- func CapabilityRisk(cap string) (string, bool)
- func DigestSHA256(artifact []byte) string
- func SHA256Hex(data []byte) string
- func SigningPayload(m Manifest) []byte
- func ValidateInvokeBudgetSpec(b InvokeBudgetSpec) error
- func ValidateManifest(m Manifest) error
- func ValidateOperationPlan(plan PluginOperationPlan) error
- func ValidateSystemPoolConfig(cfg SystemPoolConfig) error
- func VerifyManifest(m Manifest, artifact []byte, policy TrustPolicy) error
- func VersionInRange(version, rangeExpr string) bool
- type Broker
- func (b *Broker) CanExposeRPC() bool
- func (b *Broker) HTTPDo(ctx context.Context, req HostHTTPRequest) (HostHTTPResponse, error)
- func (b *Broker) HTTPOperatorDo(ctx context.Context, req HostHTTPRequest) (HostHTTPResponse, error)
- func (b *Broker) HasCapability(cap string) bool
- func (b *Broker) KVGet(ctx context.Context, key string) ([]byte, bool, error)
- func (b *Broker) KVPut(ctx context.Context, key string, value []byte) error
- func (b *Broker) Log(ctx context.Context, level, message string, fields map[string]string) error
- func (b *Broker) Notify(ctx context.Context, title, body string) error
- func (b *Broker) PluginID() string
- func (b *Broker) RPCCall(ctx context.Context, service, method string, request []byte) ([]byte, error)
- func (b *Broker) SecretDelete(ctx context.Context, key string) error
- func (b *Broker) SecretGet(ctx context.Context, key string) (string, bool, error)
- func (b *Broker) SecretPut(ctx context.Context, key, value string) error
- func (b *Broker) TaskEnqueue(ctx context.Context, req HostTaskRequest) (string, error)
- type BundleFile
- type BundleLimits
- type BundleSpec
- type CapabilityError
- type CompatibilitySpec
- type DependencySpec
- type ExtractedBundle
- type GenerationCleanupError
- type GenerationCleanupResult
- type GenerationLeasingRunner
- type HTTPHost
- type HostAccessSpec
- type HostAudit
- type HostCallEvent
- type HostHTTPRequest
- type HostHTTPResponse
- type HostLogEntry
- type HostServices
- type HostTaskRequest
- type InterfaceContract
- func (c InterfaceContract) EffectiveBacking() string
- func (c InterfaceContract) EffectiveMethodScopes(name string) ([]string, bool)
- func (c InterfaceContract) MarshalJSON() ([]byte, error)
- func (c InterfaceContract) MethodContract(name string) (InterfaceMethod, bool)
- func (c InterfaceContract) MethodContracts() []InterfaceMethod
- func (c InterfaceContract) TypedMethods() bool
- func (c *InterfaceContract) UnmarshalJSON(data []byte) error
- type InterfaceMethod
- type InvocationGenerationLease
- type InvokeBudgetSpec
- type InvokeConstraints
- type InvokeRequest
- type InvokeResponse
- type Invoker
- type KVHost
- type LoadOutcome
- type Loaded
- type Loader
- type LogHost
- type Manifest
- type ManifestUI
- type NavContribution
- type NotifyHost
- type OperationExecuteRequest
- type OperationGrant
- type OperatorHTTPHost
- type OwnerActiveFunc
- type PluginOperationPlan
- type PoolCleanupResult
- type RPCDependency
- type RPCGrant
- type RPCGrantedHost
- type RPCHandler
- type RPCHost
- type RPCRegistry
- func (r *RPCRegistry) Allow(callerPluginID, service string)
- func (r *RPCRegistry) AllowMethods(callerPluginID, service string, methods []string)
- func (r *RPCRegistry) Call(ctx context.Context, caller, service, method string, request []byte) ([]byte, error)
- func (r *RPCRegistry) CallGranted(ctx context.Context, caller string, grant RPCGrant, service, method string, ...) ([]byte, error)
- func (r *RPCRegistry) CallOperator(ctx context.Context, service, method string, request []byte) ([]byte, error)
- func (r *RPCRegistry) Owns(ownerPluginID, service string) bool
- func (r *RPCRegistry) Register(ownerPluginID, service, version string, methods []string, handler RPCHandler) error
- func (r *RPCRegistry) Revoke(callerPluginID, service string)
- func (r *RPCRegistry) Services() []RPCServiceDescriptor
- func (r *RPCRegistry) SetOwnerActive(fn OwnerActiveFunc)
- func (r *RPCRegistry) Unregister(service string)
- type RPCServiceDescriptor
- type ResolvedInvokeBudget
- type Runner
- type RunnerCloser
- type RunnerStartRequest
- type RunnerStartResult
- type RunnerStopRequest
- type RuntimeManager
- func (m *RuntimeManager) Close(ctx context.Context) error
- func (m *RuntimeManager) Invoke(ctx context.Context, pluginID, action string, payload json.RawMessage) (InvokeResponse, error)
- func (m *RuntimeManager) InvokeConstrained(ctx context.Context, pluginID, action string, payload json.RawMessage, ...) (InvokeResponse, error)
- func (m *RuntimeManager) IsArmed(pluginID string) bool
- func (m *RuntimeManager) Snapshot() map[string]RuntimeStatus
- func (m *RuntimeManager) Start(ctx context.Context, loaded Loaded) (RuntimeStatus, error)
- func (m *RuntimeManager) Status(pluginID string) (RuntimeStatus, bool)
- func (m *RuntimeManager) Stop(pluginID, message string) (RuntimeStatus, error)
- type RuntimeManagerOptions
- type RuntimeShutdownError
- type RuntimeSpec
- type RuntimeStatus
- type SecretHost
- type SystemPoolCircuitTransition
- type SystemPoolConfig
- type SystemPoolDurationPhase
- type SystemPoolLifecycleEvent
- type SystemPoolObserver
- type SystemPoolRetirementReason
- type SystemRunner
- func (r *SystemRunner) AbortGeneration(ctx context.Context, pluginID string, generation uint64) error
- func (r *SystemRunner) AcquireInvocation(pluginID string, generation uint64) (InvocationGenerationLease, error)
- func (r *SystemRunner) ActivateGeneration(pluginID string, generation uint64) error
- func (r *SystemRunner) Invoke(ctx context.Context, req InvokeRequest) (InvokeResponse, error)
- func (r *SystemRunner) Name() string
- func (r *SystemRunner) Prepare(ctx context.Context, req RunnerStartRequest) (RunnerStartResult, error)
- func (r *SystemRunner) RetireGeneration(ctx context.Context, pluginID string, generation uint64) error
- func (r *SystemRunner) Start(ctx context.Context, req RunnerStartRequest) (RunnerStartResult, error)
- func (r *SystemRunner) Stop(ctx context.Context, req RunnerStopRequest) error
- func (r *SystemRunner) StopAll(ctx context.Context) error
- type SystemRunnerOptions
- type TaskHost
- type TransactionalRunner
- type TrustPolicy
- type UIRuntimeSpec
- type ViewAction
- type ViewColumn
- type ViewContribution
- type ViewFormField
- type ViewSource
Constants ¶
const ( // BackingRuntime: the plugin's own artifact serves the method. The default. BackingRuntime = "runtime" // BackingCore: a core-registered provider owned by this plugin serves the method. // Host-risk by nature — only a system plugin may declare it, and every v2 manifest // already requires a trusted-publisher signature. BackingCore = "core" )
Backing names who actually serves an interface's methods.
A plugin is not required to carry its own engine. Some domain engines — the nftables renderer, the WireGuard key/config engine — deliberately stay in core so the trust base stays small (ADR-001 D5). What the plugin owns in that case is the UI, the validation, and the workflow intent; core owns the engine.
That arrangement is legitimate. What is not legitimate is leaving it implicit: a manifest that declares a method core secretly answers is a contract that lies, and no operator or auditor can see the difference. Backing makes the split an explicit, signed, per-service declaration.
const ( DefaultInvokeTimeoutMS = 10_000 DefaultInvokeStdoutBytes = 1 << 20 DefaultInvokeStderrBytes = 1 << 20 DefaultInvokeHostCalls = 64 HostMaxInvokeTimeoutMS = 30_000 HostMaxInvokeStdoutBytes = 8 << 20 HostMaxInvokeStderrBytes = 1 << 20 // HostMaxInvokeHostCalls bounds what a signed manifest may declare per // method. 64 was sized for CRUD shapes; the sub-store plugin's real shapes // run past it — an export reattaches one program key per script file and // the store caps at 256 records (2 + 256 = 258), and a migration is that // plus three upstream fetches (263). 512 covers the store-bounded worst // cases with headroom while still killing a runaway plugin. HostMaxInvokeHostCalls = 512 )
const ( ManifestSchemaV2 = "lattice.plugin.manifest.v2" BundleFormatTarGzip = "tar+gzip" RuntimeProtocolStdioJSONV1 = "stdio-json-v1" RuntimeProtocolStdioJSONV2 = "stdio-json-v2" UIRuntimeModeSandbox = "sandbox" UIBridgeVersion1 = "1" InterfaceEffectRead = "read" InterfaceEffectWrite = "write" InterfaceEffectPlan = "plan" )
const ( TypeSystem = "system" TypeWasm = "wasm" TypeWorker = "worker" RiskRead = "read" RiskWrite = "write" RiskHost = "host" )
const ( RuntimeStateArmed = "armed" RuntimeStateStopping = "stopping" RuntimeStateStopped = "stopped" RuntimeStateDegraded = "degraded" RuntimeStateFailed = "failed" )
Variables ¶
var ( // ErrCapabilityDenied is returned when a plugin calls a host API without // declaring the matching capability in its verified manifest. ErrCapabilityDenied = errors.New("plugin capability denied") // the server did not wire the corresponding host service into the broker. ErrHostServiceUnavailable = errors.New("plugin host service unavailable") )
var ( // ErrRPCNoService is returned when no plugin has registered the target service. ErrRPCNoService = errors.New("rpc service not found") // ErrRPCNoMethod is returned when the target service does not expose the method. ErrRPCNoMethod = errors.New("rpc method not found") // ErrRPCDenied is returned when the caller is not on the service's directed // allow-list (and is not the service owner). Distinct from "not found" so the // broker can record it as a security deny event. ErrRPCDenied = errors.New("rpc call denied") // ErrRPCInvalid is returned for a malformed service registration. ErrRPCInvalid = errors.New("invalid rpc registration") // ErrRPCOwnerInactive is returned when the plugin owning a service is not active. // Disable must stop the backend, not merely hide the UI: core-registered providers // are wired at boot and never unregistered, so without this gate a disabled plugin // kept serving — to the gateway, and to any consumer still holding a granted edge. ErrRPCOwnerInactive = errors.New("rpc service owner is not active") )
Inter-plugin RPC (design-09 §F). The registry is the server-owned bus that makes one first-party plugin's logic callable from another without exposing raw handles: a plugin with rpc:expose registers a service; a plugin with rpc:call invokes it through the broker. Every call is capability-gated at the broker, authorized here by a directed caller->callee allow-list, and audited.
var ErrCircuitOpen = errors.New("plugin circuit breaker open")
ErrCircuitOpen is returned once a plugin has failed CrashThreshold times in a row. The operator must disable+re-enable (restart) the plugin to reset it; a flapping plugin cannot keep consuming resources.
Functions ¶
func BindOperation ¶ added in v0.2.3
BindOperation attaches an approved operation's one-time authority to a single invocation. Only the approval executor calls this; an ordinary /api/plugins/call invocation binds nothing, so a plugin reached any other way holds no grant and its task.enqueue is refused.
func BindOperatorTargets ¶ added in v0.2.3
BindOperatorTargets attaches server-authorized base URLs to one invocation. Only the system runner and server tests should mint this context value.
func CanonicalOperationPlan ¶ added in v0.2.3
func CanonicalOperationPlan(plan PluginOperationPlan) (string, error)
CanonicalOperationPlan renders the reviewable plan deterministically. This string is stored in Approval.Plan and hashed by the approval plan-hash gate, so the operator approves exactly these bytes; any ambiguity in the encoding would be an ambiguity in what was approved.
func CapabilityList ¶
func CapabilityList() []string
func CapabilityRisk ¶ added in v0.2.0
func DigestSHA256 ¶ added in v0.2.0
func SHA256Hex ¶ added in v0.2.3
SHA256Hex is the one hashing helper the operation protocol uses, so plan hashes and request hashes are computed the same way.
func SigningPayload ¶ added in v0.2.0
func ValidateInvokeBudgetSpec ¶ added in v0.2.3
func ValidateInvokeBudgetSpec(b InvokeBudgetSpec) error
func ValidateManifest ¶
func ValidateOperationPlan ¶ added in v0.2.3
func ValidateOperationPlan(plan PluginOperationPlan) error
ValidateOperationPlan bounds what a plugin may propose. A plan is plugin-authored input crossing into the operator's review surface, so it is checked like any other untrusted input — before a human is asked to read it.
func ValidateSystemPoolConfig ¶ added in v0.2.3
func ValidateSystemPoolConfig(cfg SystemPoolConfig) error
ValidateSystemPoolConfig checks the host-side resource bounds without creating runtime directories or starting plugin processes.
func VerifyManifest ¶ added in v0.2.0
func VerifyManifest(m Manifest, artifact []byte, policy TrustPolicy) error
func VersionInRange ¶ added in v0.2.3
VersionInRange reports whether version satisfies the comparator set — exported for the server-side activation gate (plugin load uses the same evaluator internally).
Types ¶
type Broker ¶ added in v0.2.0
type Broker struct {
// contains filtered or unexported fields
}
Broker is the capability-scoped facade a verified plugin uses to call back into server-owned host services.
func NewBroker ¶ added in v0.2.0
func NewBroker(loaded Loaded, services HostServices) (*Broker, error)
NewBroker binds a verified plugin registry entry to server-owned host services.
func (*Broker) CanExposeRPC ¶ added in v0.2.0
CanExposeRPC reports whether the verified plugin declared rpc:expose, i.e. may register a callable service in the inter-plugin RPC registry. The server checks this before registering a plugin's handlers (design-09 §F).
func (*Broker) HTTPDo ¶ added in v0.2.0
func (b *Broker) HTTPDo(ctx context.Context, req HostHTTPRequest) (HostHTTPResponse, error)
HTTPDo performs guarded outbound HTTP and requires http:egress. The broker itself runs the SSRF/egress guard on req.URL BEFORE delegating to the HTTPHost, so egress filtering is structural at this boundary and every HTTPHost (including future ones) is guarded regardless of its own behavior.
func (*Broker) HTTPOperatorDo ¶ added in v0.2.3
func (b *Broker) HTTPOperatorDo(ctx context.Context, req HostHTTPRequest) (HostHTTPResponse, error)
HTTPOperatorDo reaches an explicitly operator-selected endpoint and requires the distinct system-only http:operator-target capability. It never weakens HTTPDo or its SSRF boundary.
func (*Broker) HasCapability ¶ added in v0.2.0
HasCapability reports whether the verified plugin declared cap.
func (*Broker) KVGet ¶ added in v0.2.0
KVGet reads a KV value and requires kv:read. The plugin-supplied key names only the entry within the plugin's own namespace; the broker pins the bucket so a plugin can never read another plugin's or the operator's keys.
func (*Broker) KVPut ¶ added in v0.2.0
KVPut writes a KV value and requires kv:write. As with KVGet, the bucket is fixed to the plugin's own namespace; the plugin only chooses the entry key.
func (*Broker) Log ¶ added in v0.2.0
Log writes a plugin-authored log entry and requires log:write. The plugin controls the level/message/fields, so the broker bounds them before they reach the sink: the level is mapped to a known set, an oversize message is truncated, and the field count is capped. This prevents a plugin from flooding or poisoning the operator log through unbounded input.
func (*Broker) Notify ¶ added in v0.2.0
Notify sends an operator notification and requires notify:send.
func (*Broker) PluginID ¶ added in v0.2.0
PluginID returns the verified plugin id attached to this broker.
func (*Broker) RPCCall ¶ added in v0.2.0
func (b *Broker) RPCCall(ctx context.Context, service, method string, request []byte) ([]byte, error)
RPCCall invokes method on another plugin's exposed service and requires rpc:call. The broker stamps the VERIFIED caller id (b.pluginID) so the registry can authorize the directed edge; a plugin cannot impersonate another caller. Registry-level denials (ErrRPCDenied) are additionally recorded as a deny event for audit visibility (the capability check itself already recorded an allow). Service/method-not-found are client errors once the directed edge is authorized, so they are returned without an extra deny event.
func (*Broker) SecretDelete ¶ added in v0.2.3
SecretDelete removes an encrypted secret and requires secret:write.
func (*Broker) SecretGet ¶ added in v0.2.3
SecretGet reads an encrypted secret and requires secret:read. As with KV, the bucket is pinned by the broker, so a plugin can only read secrets it wrote itself.
The value is returned to the PLUGIN BACKEND only. It never crosses the browser bridge: the bridge can invoke a plugin's declared interface methods, and what a method chooses to return is the plugin's own business, but the host never places a secret into a plan, an error, an audit record, or a log line.
func (*Broker) SecretPut ¶ added in v0.2.3
SecretPut writes an encrypted secret and requires secret:write.
func (*Broker) TaskEnqueue ¶ added in v0.2.3
TaskEnqueue queues agent work for an APPROVED operation and requires task:run.
The capability alone grants nothing. task:run says a plugin is *eligible* to run work; the operation grant says which work, on which nodes, under which approval — and it exists only inside an invocation the approval executor started. So the ways a plugin might try to reach a node all fail here:
- called through the ordinary gateway, there is no grant at all;
- holding a grant, it cannot aim at a node the operator did not approve;
- it cannot enqueue against a plan other than the one that was approved;
- it cannot enqueue more times than the approval allowed.
The script itself is arbitrary — `sh` on a node is full execution by design. That is exactly why the grant binds the target set: the blast radius is the reviewed one.
type BundleFile ¶ added in v0.2.3
type BundleFile struct {
Size int64 `json:"size"`
SHA256 string `json:"sha256"`
Mode uint32 `json:"mode"`
}
func ReadVerifiedBundleFile ¶ added in v0.2.3
func ReadVerifiedBundleFile(loaded Loaded, rel string) ([]byte, BundleFile, error)
ReadVerifiedBundleFile reads one inventory-pinned file from an extracted v2 tree after rechecking path components, type, mode, size, and digest. Callers serve the returned immutable bytes rather than reopening a mutable path.
type BundleLimits ¶ added in v0.2.3
type BundleLimits struct {
MaxCompressedBytes int64
MaxExpandedBytes int64
MaxFileBytes int64
MaxFiles int
MaxPathBytes int
MaxDepth int
}
func DefaultBundleLimits ¶ added in v0.2.3
func DefaultBundleLimits() BundleLimits
type BundleSpec ¶ added in v0.2.3
type CapabilityError ¶ added in v0.2.0
CapabilityError describes the exact capability a plugin lacked.
func (*CapabilityError) Error ¶ added in v0.2.0
func (e *CapabilityError) Error() string
func (*CapabilityError) Unwrap ¶ added in v0.2.0
func (e *CapabilityError) Unwrap() error
type CompatibilitySpec ¶ added in v0.2.3
type DependencySpec ¶ added in v0.2.3
type DependencySpec struct {
ID string `json:"id"`
Version string `json:"version,omitempty"`
Optional bool `json:"optional,omitempty"`
}
DependencySpec names one required or optional plugin dependency. Version is a comparator set (">=0.8.0-alpha.5, <0.9"); empty means any installed version. A missing required dependency refuses load; a present-but-inactive one refuses activation.
type ExtractedBundle ¶ added in v0.2.3
type ExtractedBundle struct {
Root string
RuntimePath string
UIRoot string
UIEntry string
Digest string
Inventory map[string]BundleFile
}
func ExtractBundleV2 ¶ added in v0.2.3
func ExtractBundleV2(cacheDir string, manifest Manifest, artifact []byte, platform string, limits BundleLimits, policy TrustPolicy) (ExtractedBundle, error)
ExtractBundleV2 verifies the signed compressed bytes before parsing, expands into a fresh cache-local staging directory, and publishes a content-addressed immutable tree. Existing cache entries are reused only after byte-for-byte hash, size, type, mode, and tree membership validation against this extraction.
type GenerationCleanupError ¶ added in v0.2.3
type GenerationCleanupError struct {
PluginID string
Generation uint64
Stage string
PendingStages []string
ResidualPGIDs []int
Transport error
Authority error
RemoveAll error
Err error
}
GenerationCleanupError preserves every residual from one generation's teardown instead of collapsing transport, authority, and filesystem failure into an apparently successful retirement.
func (*GenerationCleanupError) Error ¶ added in v0.2.3
func (e *GenerationCleanupError) Error() string
func (*GenerationCleanupError) Unwrap ¶ added in v0.2.3
func (e *GenerationCleanupError) Unwrap() error
type GenerationCleanupResult ¶ added in v0.2.3
type GenerationCleanupResult struct {
PluginID string
Generation uint64
Stage string
PendingStages []string
ResidualPGIDs []int
Transport error
Authority error
RemoveAll error
Err error
}
GenerationCleanupResult is the stable, caller-bounded view of one physical generation teardown. Pending snapshots and the immutable terminal result use the same shape so callers never lose ownership detail on timeout.
type GenerationLeasingRunner ¶ added in v0.2.3
type GenerationLeasingRunner interface {
AcquireInvocation(pluginID string, generation uint64) (InvocationGenerationLease, error)
}
type HTTPHost ¶ added in v0.2.0
type HTTPHost interface {
Do(ctx context.Context, req HostHTTPRequest) (HostHTTPResponse, error)
}
HTTPHost performs guarded outbound HTTP. Implementations must enforce the server's SSRF/egress policy before dialing.
type HostAccessSpec ¶ added in v0.2.3
type HostAccessSpec struct {
RPC []RPCDependency `json:"rpc,omitempty"`
}
HostAccessSpec declares host-mediated dependencies owned by another plugin. It is signed manifest data; the server grants it only while this plugin is active and revokes it on disable. UI code never receives this structure.
type HostAudit ¶ added in v0.2.0
type HostAudit interface {
RecordHostCall(ctx context.Context, event HostCallEvent)
}
HostAudit records broker allow/deny decisions for host API calls.
type HostCallEvent ¶ added in v0.2.0
type HostCallEvent struct {
PluginID string
Action string
Capability string
Decision string
Reason string
}
HostCallEvent records one broker authorization decision.
type HostHTTPRequest ¶ added in v0.2.0
HostHTTPRequest is the broker's stable outbound HTTP request shape.
type HostHTTPResponse ¶ added in v0.2.0
HostHTTPResponse is the broker's stable outbound HTTP response shape.
type HostLogEntry ¶ added in v0.2.0
HostLogEntry is a plugin-authored structured log entry.
type HostServices ¶ added in v0.2.0
type HostServices struct {
KV KVHost
// Secret is the encrypted namespaced store (spec §9.4). When nil, a plugin
// holding secret:read/secret:write gets ErrHostServiceUnavailable rather than
// silently falling back to plaintext KV.
Secret SecretHost
// Task enqueues agent work for an APPROVED operation (spec §9.3). Reachable only
// with task:run AND a context-bound operation grant, so a plugin cannot touch a
// node outside a plan an operator read and approved.
Task TaskHost
Notify NotifyHost
HTTP HTTPHost
OperatorHTTP OperatorHTTPHost
Log LogHost
Audit HostAudit
// RPC dispatches inter-plugin calls (design-09 §F). When nil, a plugin with
// rpc:call gets ErrHostServiceUnavailable rather than a panic.
RPC RPCHost
// GuardURL, when set, validates an outbound HTTP target's URL/host BEFORE the
// broker delegates to HTTP.Do. It makes SSRF/egress guarding structural at the
// broker boundary rather than relying on every HTTPHost implementation to
// remember to guard. A non-nil error rejects the request before any dial. When
// nil, the broker falls back to a built-in guard (see defaultGuardURL) so an
// HTTPHost is never trusted by convention alone.
GuardURL func(url string) error
GuardOperatorURL func(url string) error
}
HostServices are the real server-owned handles exposed through the broker. The broker keeps these handles behind per-call capability checks.
type HostTaskRequest ¶ added in v0.2.3
type HostTaskRequest struct {
PluginID string
ApprovalID string
NodeID string
Interpreter string
Script string
TimeoutSec int
}
HostTaskRequest is the broker's stable task-enqueue shape.
type InterfaceContract ¶ added in v0.2.0
type InterfaceContract struct {
Service string `json:"service"`
// Methods remains the normalized name list so v1 callers keep their source
// contract. MethodSpecs carries the signed v2 effect and method-level scopes.
Methods []string `json:"-"`
MethodSpecs []InterfaceMethod `json:"-"`
Scopes []string `json:"scopes,omitempty"`
// Backing is empty on manifests signed before the field existed. Empty stays
// omitted from the signing payload, so those signatures remain byte-identical
// and valid; the gateway resolves them through a logged legacy path until they
// are re-signed with an explicit declaration.
Backing string `json:"backing,omitempty"`
// contains filtered or unexported fields
}
InterfaceContract declares an interface the plugin exposes (service + methods), callable through the dashboard->plugin gateway under the given scopes.
func (InterfaceContract) EffectiveBacking ¶ added in v0.2.3
func (c InterfaceContract) EffectiveBacking() string
EffectiveBacking resolves the declared backing, defaulting to runtime.
func (InterfaceContract) EffectiveMethodScopes ¶ added in v0.2.3
func (c InterfaceContract) EffectiveMethodScopes(name string) ([]string, bool)
func (InterfaceContract) MarshalJSON ¶ added in v0.2.3
func (c InterfaceContract) MarshalJSON() ([]byte, error)
func (InterfaceContract) MethodContract ¶ added in v0.2.3
func (c InterfaceContract) MethodContract(name string) (InterfaceMethod, bool)
func (InterfaceContract) MethodContracts ¶ added in v0.2.3
func (c InterfaceContract) MethodContracts() []InterfaceMethod
func (InterfaceContract) TypedMethods ¶ added in v0.2.3
func (c InterfaceContract) TypedMethods() bool
func (*InterfaceContract) UnmarshalJSON ¶ added in v0.2.3
func (c *InterfaceContract) UnmarshalJSON(data []byte) error
type InterfaceMethod ¶ added in v0.2.3
type InterfaceMethod struct {
Name string `json:"name"`
Effect string `json:"effect"`
Scopes []string `json:"scopes,omitempty"`
OperatorTargetFields []string `json:"operator_target_fields,omitempty"`
Budget *InvokeBudgetSpec `json:"budget,omitempty"`
}
type InvocationGenerationLease ¶ added in v0.2.3
type InvocationGenerationLease interface {
Invoke(ctx context.Context, req InvokeRequest) (InvokeResponse, error)
Release()
}
type InvokeBudgetSpec ¶ added in v0.2.3
type InvokeBudgetSpec struct {
TimeoutMS int `json:"timeout_ms"`
StdoutBytes int `json:"stdout_bytes"`
StderrBytes int `json:"stderr_bytes"`
HostCalls int `json:"host_calls"`
}
InvokeBudgetSpec is signed method-level runtime data. An absent budget stays additive and resolves to the old global defaults; a present budget must be complete so host_calls:0 can be used intentionally to forbid host calls.
func DefaultInvokeBudgetSpec ¶ added in v0.2.3
func DefaultInvokeBudgetSpec() InvokeBudgetSpec
func (*InvokeBudgetSpec) UnmarshalJSON ¶ added in v0.2.3
func (b *InvokeBudgetSpec) UnmarshalJSON(data []byte) error
type InvokeConstraints ¶ added in v0.2.3
type InvokeConstraints struct {
OperatorTargets []string
// Budget is the signed method-level runtime budget resolved by the host. Nil
// is the additive compatibility path for already-signed manifests and resolves
// to the old global defaults with a host warning.
Budget *InvokeBudgetSpec
// BudgetLabel is a stable service/method label used only for host logs.
BudgetLabel string
// Operation is the one-time authority for an approved host-risk operation (§9.3).
// Like OperatorTargets it stays on the host side of the boundary: the plugin never
// receives it, so it cannot forge or widen one — it can only make a host call that
// the broker then checks against it.
Operation *OperationGrant
}
InvokeConstraints are host-owned, invocation-scoped grants. They are never serialized to the child process and therefore cannot be expanded by plugin code after the operator call has been authorized.
type InvokeRequest ¶ added in v0.2.0
type InvokeRequest struct {
PluginID string
Generation uint64
Action string
Payload json.RawMessage
Constraints InvokeConstraints
}
InvokeRequest asks an armed plugin to perform one action. Payload is the raw JSON body handed to the plugin; the runner frames {action,payload} as a single stdin line and reads the reply from stdout.
type InvokeResponse ¶ added in v0.2.0
type InvokeResponse struct {
OK bool `json:"ok"`
Message string `json:"message,omitempty"`
Result json.RawMessage `json:"result,omitempty"`
Warnings []string `json:"warnings,omitempty"`
}
InvokeResponse is the decoded plugin reply. Result carries the plugin's body (e.g. a rendered plan) for the host to act on under its own privileges.
type Invoker ¶ added in v0.2.0
type Invoker interface {
Invoke(ctx context.Context, req InvokeRequest) (InvokeResponse, error)
}
Invoker is an optional runner capability: a request/response action protocol with the plugin. The system runner implements it; the noop runner does not.
type KVHost ¶ added in v0.2.0
type KVHost interface {
Get(ctx context.Context, key string) ([]byte, bool, error)
Put(ctx context.Context, key string, value []byte) error
}
KVHost is the plugin-facing KV subset. The implementation remains server-owned.
type LoadOutcome ¶ added in v0.2.0
type LoadOutcome struct {
BundlePath string
PluginID string
Loaded bool
Reason string // failure reason when Loaded is false
}
LoadOutcome records the result of attempting to load one bundle so the caller can audit every accept and reject.
type Loaded ¶ added in v0.2.0
type Loaded struct {
Manifest Manifest
Capabilities []string
BundlePath string
ArtifactPath string
ArtifactDigest string
ExtractedRoot string
RuntimeEntry string
RuntimePath string
UIRoot string
UIEntry string
Inventory map[string]BundleFile
BundleLimits BundleLimits
}
Loaded is a verified, registered plugin: the decoded manifest plus the capabilities the trust policy granted at load time. Execution (host-API binding and invocation) is a later milestone; loading establishes the verified registry and is the point at which signature/digest/capability trust is enforced.
type Loader ¶ added in v0.2.0
type Loader struct {
Dir string
CacheDir string
Platform string
Limits BundleLimits
Policy TrustPolicy
}
Loader discovers and verifies plugin bundles under Dir against an operator TrustPolicy. It never executes anything; it only decides what is trusted enough to register.
func (Loader) Load ¶ added in v0.2.0
func (l Loader) Load() ([]Loaded, []LoadOutcome, error)
Load scans the plugin directory and verifies each bundle. It returns the verified plugins (sorted by id) and a per-bundle outcome log. A bundle that fails verification is skipped and recorded as a failure — one bad bundle never aborts the scan or blocks startup. A missing/empty directory loads nothing.
type LogHost ¶ added in v0.2.0
type LogHost interface {
Write(ctx context.Context, entry HostLogEntry) error
}
LogHost records a plugin-authored log entry after the broker stamps plugin id.
type Manifest ¶
type Manifest struct {
Schema string `json:"schema,omitempty"`
ID string `json:"id"`
Name string `json:"name"`
Type string `json:"type"`
Capabilities []string `json:"capabilities"`
Version string `json:"version,omitempty"`
Entrypoint string `json:"entrypoint,omitempty"`
Publisher string `json:"publisher,omitempty"`
DigestSHA256 string `json:"digest_sha256,omitempty"`
SignatureEd25519 string `json:"signature_ed25519,omitempty"`
Bundle *BundleSpec `json:"bundle,omitempty"`
Runtime *RuntimeSpec `json:"runtime,omitempty"`
UIRuntime *UIRuntimeSpec `json:"ui_runtime,omitempty"`
Compatibility *CompatibilitySpec `json:"compatibility,omitempty"`
MinServer string `json:"min_server,omitempty"`
HostAccess *HostAccessSpec `json:"host_access,omitempty"`
// UI + Interfaces are the design-10 dashboard contributions: declarative data
// (nav/views) + the interfaces the plugin exposes. They are covered by the
// signature (see SigningPayload) so a tampered contribution fails verification.
UI *ManifestUI `json:"ui,omitempty"`
Interfaces []InterfaceContract `json:"interfaces,omitempty"`
// Dependencies declares plugin-to-plugin requirements (design-18 D3/E1).
// Required dependencies gate both load and activation; optional ones are
// advisory. Covered by the v2 signing payload like every other field.
Dependencies []DependencySpec `json:"dependencies,omitempty"`
}
func DecodeManifest ¶ added in v0.2.3
func VerifyInstallManifest ¶ added in v0.2.0
func VerifyInstallManifest(manifestBytes, artifact []byte, policy TrustPolicy) (Manifest, error)
func (Manifest) InterfaceFor ¶ added in v0.2.3
func (m Manifest) InterfaceFor(service string) (InterfaceContract, bool)
InterfaceFor returns the contract the manifest declares for a service.
type ManifestUI ¶ added in v0.2.0
type ManifestUI struct {
Views []ViewContribution `json:"views,omitempty"`
}
ManifestUI is a plugin's dashboard contribution set.
type NavContribution ¶ added in v0.2.0
type NavContribution struct {
}
NavContribution is a sidebar entry a plugin adds. Route is plugin-relative and mounted at /plugins/<id>/<route>.
type NotifyHost ¶ added in v0.2.0
NotifyHost sends an operator notification through server-owned channels.
type OperationExecuteRequest ¶ added in v0.2.3
type OperationExecuteRequest struct {
ApprovalID string `json:"approval_id"`
Targets []string `json:"targets"`
Data json.RawMessage `json:"data,omitempty"`
}
OperationExecuteRequest is what the approval executor hands the plugin's `execute` action: the approved plan's opaque data and the approved targets. The plugin acts on this, but every task it then tries to enqueue is checked by the broker against the grant — so this payload is a convenience, not an authority.
type OperationGrant ¶ added in v0.2.3
type OperationGrant struct {
ApprovalID string
PluginID string
// PlanSHA256 is the hash of the exact approved plan text. Carried for audit so a
// task can be tied back to the approval it ran under.
PlanSHA256 string
// Targets is the approved node set. The broker refuses any task aimed elsewhere, so
// a plugin holding a legitimate grant still cannot reach an unapproved node.
Targets []string
// Remaining bounds how many tasks this single approved operation may enqueue.
Remaining int
}
OperationGrant is the one-time, invocation-scoped authority handed to a plugin when the approval executor invokes it. It is bound into the invocation's context and is NEVER serialized to the child process: the plugin cannot read it, forge it, or widen it — it can only cause the broker to consult it by making a host call.
This mirrors how operator targets are bound (InvokeConstraints.OperatorTargets): the grant lives on the host side of the boundary, and the plugin's only interaction with it is that the broker checks a request against it.
func (*OperationGrant) AllowsTarget ¶ added in v0.2.3
func (g *OperationGrant) AllowsTarget(nodeID string) bool
AllowsTarget reports whether a node was in the approved set.
type OperatorHTTPHost ¶ added in v0.2.3
type OperatorHTTPHost interface {
DoOperator(ctx context.Context, req HostHTTPRequest) (HostHTTPResponse, error)
}
OperatorHTTPHost performs HTTP to an explicitly operator-selected endpoint. It is separate from ordinary egress so private-network access cannot be enabled by a caller-controlled flag on http.do.
type OwnerActiveFunc ¶ added in v0.2.3
OwnerActiveFunc reports whether the plugin owning a service is currently active.
type PluginOperationPlan ¶ added in v0.2.3
type PluginOperationPlan struct {
// Summary is the one-line intent an operator sees first.
Summary string `json:"summary"`
// Targets are the node IDs this operation would touch. The server authorizes each
// one against the approving principal and records them as Approval.Targets; a plugin
// cannot widen its own blast radius by naming extra nodes.
Targets []string `json:"targets"`
// Preview is the redacted, human-reviewable body of the change. It is what the
// operator actually reads, so it must not contain secrets — the plugin redacts it,
// and the server never reconstructs the unredacted form (§9.4).
Preview string `json:"preview,omitempty"`
// Steps are the ordered actions the plugin intends to take.
Steps []string `json:"steps,omitempty"`
// Rollback states what undoing this looks like. A plan that cannot say how it is
// undone is a plan an operator cannot safely approve.
Rollback string `json:"rollback,omitempty"`
// Data is opaque plugin-owned state carried through approval back into execute. The
// server does not interpret it; it hands back exactly what was approved.
Data json.RawMessage `json:"data,omitempty"`
}
PluginOperationPlan is what a plugin's `plan`-effect method returns: a deterministic, reviewable description of what an apply would do. It is authored by the plugin and never trusted as authorization — only as a proposal. It is what the server stores in Approval.Plan and what the operator reads.
func ParseOperationPlan ¶ added in v0.2.3
func ParseOperationPlan(plan string) (PluginOperationPlan, error)
ParseOperationPlan reads back a stored plan.
type PoolCleanupResult ¶ added in v0.2.3
type PoolCleanupResult struct {
Generation uint64
Err error
ResidualPGIDs []int
Stage string
PendingStages []string
}
PoolCleanupResult is the owned, generation-scoped teardown ledger. A future is returned so callers can broadcast abort requests first and join all transports under their own deadline.
type RPCDependency ¶ added in v0.2.3
type RPCGrantedHost ¶ added in v0.2.3
type RPCHandler ¶ added in v0.2.0
RPCHandler serves one inter-plugin RPC method: it receives the method name and raw request bytes and returns raw response bytes. Implementations must be safe for concurrent use; the registry invokes them WITHOUT holding its lock.
type RPCHost ¶ added in v0.2.0
type RPCHost interface {
Call(ctx context.Context, caller, service, method string, request []byte) ([]byte, error)
}
RPCHost dispatches an inter-plugin RPC call to a server-owned registry that resolves the target service, enforces the directed caller->callee allow-list, and invokes the callee's handler. caller is the VERIFIED id of the calling plugin, supplied by the broker; a plugin cannot spoof it.
type RPCRegistry ¶ added in v0.2.0
type RPCRegistry struct {
// contains filtered or unexported fields
}
RPCRegistry is the server-owned inter-plugin RPC bus. It is safe for concurrent use and implements the broker's RPCHost interface.
func NewRPCRegistry ¶ added in v0.2.0
func NewRPCRegistry() *RPCRegistry
NewRPCRegistry returns an empty registry.
func (*RPCRegistry) Allow ¶ added in v0.2.0
func (r *RPCRegistry) Allow(callerPluginID, service string)
Allow grants callerPluginID permission to call service. Grants are directed and additive; a service owner can always call its own service.
func (*RPCRegistry) AllowMethods ¶ added in v0.2.3
func (r *RPCRegistry) AllowMethods(callerPluginID, service string, methods []string)
AllowMethods grants only the named methods. This prevents a plugin from inheriting future methods added to a dependency service.
func (*RPCRegistry) Call ¶ added in v0.2.0
func (r *RPCRegistry) Call(ctx context.Context, caller, service, method string, request []byte) ([]byte, error)
Call implements RPCHost: enforce the directed allow-list (the owner may always self-call), then reveal service/lifecycle/method details only to authorized callers. The handler runs OUTSIDE the lock so a slow or re-entrant handler cannot block the bus.
func (*RPCRegistry) CallGranted ¶ added in v0.2.3
func (*RPCRegistry) CallOperator ¶ added in v0.2.0
func (r *RPCRegistry) CallOperator(ctx context.Context, service, method string, request []byte) ([]byte, error)
CallOperator dispatches a service method on behalf of the OPERATOR (the dashboard gateway), bypassing the plugin->plugin directed allow-list — the HTTP layer has already enforced the interface's declared RBAC scopes + audit. Service/method-not-found are still errors. The handler runs OUTSIDE the lock.
func (*RPCRegistry) Owns ¶ added in v0.2.3
func (r *RPCRegistry) Owns(ownerPluginID, service string) bool
Owns reports whether service is registered by ownerPluginID. The dashboard gateway uses this exact owner check before dispatching a v2 plugin call to an in-core implementation; a manifest cannot claim another plugin's service.
func (*RPCRegistry) Register ¶ added in v0.2.0
func (r *RPCRegistry) Register(ownerPluginID, service, version string, methods []string, handler RPCHandler) error
Register adds (or replaces) a service exposed by ownerPluginID. service is the fully-qualified id (e.g. "latticenet.vpn-core/nodes"); it must carry >=1 non-empty method and a non-nil handler. Re-registering the same id replaces it (used on plugin restart). The caller (server) is responsible for verifying the owner declared rpc:expose before registering.
func (*RPCRegistry) Revoke ¶ added in v0.2.0
func (r *RPCRegistry) Revoke(callerPluginID, service string)
Revoke removes a previously granted directed edge.
func (*RPCRegistry) Services ¶ added in v0.2.0
func (r *RPCRegistry) Services() []RPCServiceDescriptor
Services returns descriptors for every registered service, sorted by id, for discovery (e.g. an rpc.List host call). Handlers are not exposed.
func (*RPCRegistry) SetOwnerActive ¶ added in v0.2.3
func (r *RPCRegistry) SetOwnerActive(fn OwnerActiveFunc)
SetOwnerActive installs the lifecycle predicate consulted before every dispatch. Until it is set the registry serves any registered service, which is the correct default for a bus with no lifecycle to consult (tests, boot).
func (*RPCRegistry) Unregister ¶ added in v0.2.0
func (r *RPCRegistry) Unregister(service string)
Unregister removes a service and any grants targeting it (e.g. on disable).
type RPCServiceDescriptor ¶ added in v0.2.0
type RPCServiceDescriptor struct {
Service string `json:"service"`
Owner string `json:"owner"`
Version string `json:"version"`
Methods []string `json:"methods"`
}
RPCServiceDescriptor is the discovery shape returned by RPCRegistry.Services. Handlers are never exposed.
type ResolvedInvokeBudget ¶ added in v0.2.3
type ResolvedInvokeBudget struct {
Timeout time.Duration
StdoutBytes int
StderrBytes int
HostCalls int
Declared bool
}
func ResolveInvokeBudget ¶ added in v0.2.3
func ResolveInvokeBudget(spec *InvokeBudgetSpec, defaults InvokeBudgetSpec) ResolvedInvokeBudget
type Runner ¶ added in v0.2.0
type Runner interface {
Name() string
Start(ctx context.Context, req RunnerStartRequest) (RunnerStartResult, error)
Stop(ctx context.Context, req RunnerStopRequest) error
}
Runner is the narrow runtime contract concrete plugin runtimes must satisfy. It receives a verified plugin and a capability-scoped broker, never raw server handles. Implementations must honor ctx cancellation and deadlines.
type RunnerCloser ¶ added in v0.2.3
type RunnerStartRequest ¶ added in v0.2.0
type RunnerStartResult ¶ added in v0.2.0
type RunnerStartResult struct {
Message string
}
type RunnerStopRequest ¶ added in v0.2.0
type RuntimeManager ¶ added in v0.2.0
type RuntimeManager struct {
// contains filtered or unexported fields
}
RuntimeManager binds verified plugins to capability-scoped brokers and tracks runtime health. The current implementation is an execution-safe skeleton: it arms host-API access for a verified plugin but does not spawn processes, load wasm, or invoke artifact code.
func NewRuntimeManager ¶ added in v0.2.0
func NewRuntimeManager(services HostServices) *RuntimeManager
func NewRuntimeManagerWithOptions ¶ added in v0.2.0
func NewRuntimeManagerWithOptions(opts RuntimeManagerOptions) *RuntimeManager
func (*RuntimeManager) Close ¶ added in v0.2.3
func (m *RuntimeManager) Close(ctx context.Context) error
Close atomically closes runtime admission, invalidates every pending start, and joins runner-owned generations before returning.
func (*RuntimeManager) Invoke ¶ added in v0.2.0
func (m *RuntimeManager) Invoke(ctx context.Context, pluginID, action string, payload json.RawMessage) (InvokeResponse, error)
Invoke dispatches one action to an armed plugin whose runner supports the request/response protocol. It fails closed if the plugin is not armed or its runner is not an Invoker (e.g. the noop runner), so a disabled or execution-disabled plugin can never be invoked.
func (*RuntimeManager) InvokeConstrained ¶ added in v0.2.3
func (m *RuntimeManager) InvokeConstrained(ctx context.Context, pluginID, action string, payload json.RawMessage, constraints InvokeConstraints) (InvokeResponse, error)
func (*RuntimeManager) IsArmed ¶ added in v0.2.0
func (m *RuntimeManager) IsArmed(pluginID string) bool
func (*RuntimeManager) Snapshot ¶ added in v0.2.0
func (m *RuntimeManager) Snapshot() map[string]RuntimeStatus
func (*RuntimeManager) Start ¶ added in v0.2.0
func (m *RuntimeManager) Start(ctx context.Context, loaded Loaded) (RuntimeStatus, error)
Start validates the loaded plugin, creates its broker, and marks it armed. The context is accepted now so future runners can honor cancellation without changing the call site.
func (*RuntimeManager) Status ¶ added in v0.2.0
func (m *RuntimeManager) Status(pluginID string) (RuntimeStatus, bool)
func (*RuntimeManager) Stop ¶ added in v0.2.0
func (m *RuntimeManager) Stop(pluginID, message string) (RuntimeStatus, error)
type RuntimeManagerOptions ¶ added in v0.2.0
type RuntimeManagerOptions struct {
Services HostServices
Runners map[string]Runner
StartTimeout time.Duration
}
type RuntimeShutdownError ¶ added in v0.2.3
RuntimeShutdownError reports a caller-bounded observation of physical shutdown without transferring or abandoning manager ownership.
func (*RuntimeShutdownError) Error ¶ added in v0.2.3
func (e *RuntimeShutdownError) Error() string
func (*RuntimeShutdownError) Unwrap ¶ added in v0.2.3
func (e *RuntimeShutdownError) Unwrap() error
type RuntimeSpec ¶ added in v0.2.3
type RuntimeStatus ¶ added in v0.2.0
type RuntimeStatus struct {
PluginID string `json:"plugin_id"`
State string `json:"state"`
Runner string `json:"runner,omitempty"`
Message string `json:"message,omitempty"`
StartedAt time.Time `json:"started_at,omitempty"`
StoppedAt time.Time `json:"stopped_at,omitempty"`
UpdatedAt time.Time `json:"updated_at"`
}
RuntimeStatus is the public, non-secret health view for one plugin runtime. It deliberately excludes local bundle paths and the broker itself.
type SecretHost ¶ added in v0.2.3
type SecretHost interface {
Get(ctx context.Context, key string) (string, bool, error)
Put(ctx context.Context, key, value string) error
Delete(ctx context.Context, key string) error
}
SecretHost is the plugin-facing encrypted-secret subset (spec §9.4). It is shaped like KVHost on purpose, but the implementation stores values through the server's at-rest cipher. The distinction is not a naming convention: a value written here is encrypted in the persisted state, and a value written through KVHost is not.
There is no List. A plugin reads back a key it chose to write; it cannot enumerate its own vault, so a read-only compromise cannot sweep for secrets whose names it does not already know.
type SystemPoolCircuitTransition ¶ added in v0.2.3
type SystemPoolCircuitTransition int
SystemPoolCircuitTransition names a circuit-breaker state change.
const SystemPoolCircuitOpened SystemPoolCircuitTransition = 1
SystemPoolCircuitOpened is the closed-to-open transition. Re-arming is not observed here: the pool opens the circuit at a decision point, but closing arrives from operator recovery flows whose truth lives elsewhere.
type SystemPoolConfig ¶ added in v0.2.3
type SystemPoolConfig struct {
Size int
MaxOverflow int
StartTimeout time.Duration
MaxUses int
MaxAge time.Duration
}
SystemPoolConfig configures the persistent stdio-json-v2 worker pool.
type SystemPoolDurationPhase ¶ added in v0.2.3
type SystemPoolDurationPhase int
SystemPoolDurationPhase names one measured span of a pooled invocation or worker start. The zero value is deliberately invalid so an unset phase can never masquerade as a real one.
const ( // SystemPoolDurationQueue is the wait for a pooled worker, successful or // not: the time an invocation spent owning no worker. SystemPoolDurationQueue SystemPoolDurationPhase = iota + 1 // SystemPoolDurationStart is one worker start attempt, from spawn to // readiness or failure. SystemPoolDurationStart // SystemPoolDurationHandler is the span the invocation actually held the // worker's transport. SystemPoolDurationHandler // SystemPoolDurationTotal is the whole pooled invocation as the caller // experienced it, queue included. SystemPoolDurationTotal )
type SystemPoolLifecycleEvent ¶ added in v0.2.3
type SystemPoolLifecycleEvent int
SystemPoolLifecycleEvent names one countable pool outcome.
const ( // SystemPoolLifecycleWorkerStartSuccess is a worker that reached readiness. SystemPoolLifecycleWorkerStartSuccess SystemPoolLifecycleEvent = iota + 1 // SystemPoolLifecycleWorkerStartFailure is a start attempt that did not, // canceled shutdown attempts excluded. SystemPoolLifecycleWorkerStartFailure // SystemPoolLifecycleInvocationReusable is an invocation whose worker came // back reusable. SystemPoolLifecycleInvocationReusable // SystemPoolLifecycleInvocationFailure is an invocation that poisoned its // worker. SystemPoolLifecycleInvocationFailure )
type SystemPoolObserver ¶ added in v0.2.3
type SystemPoolObserver interface {
ObserveSystemPoolDuration(phase SystemPoolDurationPhase, d time.Duration)
ObserveSystemPoolLifecycle(event SystemPoolLifecycleEvent)
ObserveSystemPoolCircuit(transition SystemPoolCircuitTransition)
ObserveSystemPoolRetirement(reason SystemPoolRetirementReason)
}
SystemPoolObserver receives warm-pool observations at the exact points where the pool decides a worker's or invocation's fate. Implementations must be cheap and must not call back into the runner or pool; a nil observer is valid and observes nothing.
type SystemPoolRetirementReason ¶ added in v0.2.3
type SystemPoolRetirementReason int
SystemPoolRetirementReason names why exactly one worker left the pool.
const ( // SystemPoolRetirementPoisoned is an invocation-declared terminal failure. SystemPoolRetirementPoisoned SystemPoolRetirementReason = iota + 1 // SystemPoolRetirementMaxUses is the configured use ceiling. SystemPoolRetirementMaxUses // SystemPoolRetirementMaxAge is the configured age ceiling. SystemPoolRetirementMaxAge // SystemPoolRetirementCircuitOpen is a worker dropped because the circuit // opened, at lease end or from the idle set. SystemPoolRetirementCircuitOpen // SystemPoolRetirementShutdown is a worker dropped by drain or close. SystemPoolRetirementShutdown // SystemPoolRetirementRejected is a worker the pool refused to keep: built // for a superseded generation, arriving past capacity, or otherwise valid // work the pool's current state has no place for. SystemPoolRetirementRejected )
type SystemRunner ¶ added in v0.2.0
type SystemRunner struct {
// contains filtered or unexported fields
}
SystemRunner implements Runner and Invoker.
func NewSystemRunner ¶ added in v0.2.0
func NewSystemRunner(opts SystemRunnerOptions) (*SystemRunner, error)
NewSystemRunner returns a checked system runner with the given options and safe defaults for any zero-valued legacy invocation bound.
func (*SystemRunner) AbortGeneration ¶ added in v0.2.3
func (*SystemRunner) AcquireInvocation ¶ added in v0.2.3
func (r *SystemRunner) AcquireInvocation(pluginID string, generation uint64) (InvocationGenerationLease, error)
func (*SystemRunner) ActivateGeneration ¶ added in v0.2.3
func (r *SystemRunner) ActivateGeneration(pluginID string, generation uint64) error
func (*SystemRunner) Invoke ¶ added in v0.2.0
func (r *SystemRunner) Invoke(ctx context.Context, req InvokeRequest) (InvokeResponse, error)
func (*SystemRunner) Name ¶ added in v0.2.0
func (r *SystemRunner) Name() string
func (*SystemRunner) Prepare ¶ added in v0.2.3
func (r *SystemRunner) Prepare(ctx context.Context, req RunnerStartRequest) (RunnerStartResult, error)
Prepare stages and starts an exact generation without admitting invocations.
func (*SystemRunner) RetireGeneration ¶ added in v0.2.3
func (*SystemRunner) Start ¶ added in v0.2.0
func (r *SystemRunner) Start(ctx context.Context, req RunnerStartRequest) (RunnerStartResult, error)
Start re-verifies the manifest-pinned digest of the artifact at the FIXED bundle path (TOCTOU defense in case the bundle changed after load), copies the bytes into a confined per-plugin 0700 working dir, and arms the runner. It always executes the staged 0700 copy, never the (possibly read-only or swapped) bundle file, and never resolves a manifest-controlled path.
func (*SystemRunner) Stop ¶ added in v0.2.0
func (r *SystemRunner) Stop(ctx context.Context, req RunnerStopRequest) error
Stop clears the plugin's staged state and removes its runtime dir. In-flight invocations are bound to their own context and terminate independently.
type SystemRunnerOptions ¶ added in v0.2.0
type SystemRunnerOptions struct {
// RuntimeDir is the root under which each plugin gets a confined 0700 working
// directory (RuntimeDir/<pluginID>) holding a 0700 copy of its verified
// artifact. Required.
RuntimeDir string
// EnvAllowlist names the environment variables forwarded to the plugin. Every
// other variable is stripped; a fixed safe PATH is always provided.
EnvAllowlist []string
// InvokeTimeout bounds one invocation (default 10s).
InvokeTimeout time.Duration
// StopGrace is the SIGTERM->SIGKILL window for a timed-out/cancelled process
// (default 3s).
StopGrace time.Duration
// MaxOutputBytes caps captured stdout and (separately) stderr per invocation
// (default 1 MiB), so a plugin cannot exhaust host memory by flooding output.
MaxOutputBytes int
// CrashThreshold trips the circuit breaker after this many consecutive failed
// invocations (default 5).
CrashThreshold int
// MaxHostCalls caps broker calls during one invocation (default 64).
MaxHostCalls int
// Logf receives host-visible runtime warnings. Nil disables warning logs.
Logf func(format string, args ...any)
// Pool controls stdio-json-v2 worker capacity and retirement. Nil uses safe
// host defaults; a non-nil value is validated exactly, including zero overflow.
Pool *SystemPoolConfig
// PoolObserver receives warm-pool telemetry at the pool's decision points.
// Nil observes nothing. The observer must be cheap and must not call back
// into the runner.
PoolObserver SystemPoolObserver
}
SystemRunnerOptions configures the trusted-subprocess runner.
type TaskHost ¶ added in v0.2.3
type TaskHost interface {
Enqueue(ctx context.Context, req HostTaskRequest) (string, error)
}
TaskHost enqueues bounded agent work. The implementation remains server-owned and applies the operator's own task validation, so a plugin can never reach a wider interpreter set, a longer timeout, or a bigger script than an operator could.
type TransactionalRunner ¶ added in v0.2.3
type TransactionalRunner interface {
Runner
Prepare(ctx context.Context, req RunnerStartRequest) (RunnerStartResult, error)
ActivateGeneration(pluginID string, generation uint64) error
AbortGeneration(ctx context.Context, pluginID string, generation uint64) error
RetireGeneration(ctx context.Context, pluginID string, generation uint64) error
}
TransactionalRunner separates candidate preparation from admission. A prepared generation must not be invokable until ActivateGeneration succeeds; failed/stale candidates are removed with AbortGeneration, while an old committed generation is retired only after the manager publishes its replacement.
type TrustPolicy ¶ added in v0.2.0
type TrustPolicy struct {
TrustedPublishers map[string]ed25519.PublicKey
// AllowUnsignedHostRisk opts OUT of signature enforcement for host-risk
// plugins. The zero value is fail-closed: host-risk plugins require a trusted
// publisher signature unless an operator explicitly sets this true (dev only).
AllowUnsignedHostRisk bool
}
func ParseTrustPolicyJSON ¶ added in v0.2.0
func ParseTrustPolicyJSON(data []byte) (TrustPolicy, error)
type UIRuntimeSpec ¶ added in v0.2.3
type ViewAction ¶ added in v0.2.0
type ViewAction struct {
Label string `json:"label"`
Interface string `json:"interface"`
Method string `json:"method"`
Form []ViewFormField `json:"form,omitempty"`
Scopes []string `json:"scopes,omitempty"`
}
ViewAction is a button that calls an interface method (optionally with a form).
type ViewColumn ¶ added in v0.2.0
type ViewColumn struct {
Key string `json:"key"`
Label string `json:"label"`
Render string `json:"render,omitempty"`
}
ViewColumn is one table column. Render selects a safe dashboard formatter.
type ViewContribution ¶ added in v0.2.0
type ViewContribution struct {
Route string `json:"route"`
Title string `json:"title"`
Kind string `json:"kind"`
Source *ViewSource `json:"source,omitempty"`
Columns []ViewColumn `json:"columns,omitempty"`
Actions []ViewAction `json:"actions,omitempty"`
}
ViewContribution is one declarative view rendered by a fixed dashboard primitive.
type ViewFormField ¶ added in v0.2.0
type ViewFormField struct {
Key string `json:"key"`
Label string `json:"label,omitempty"`
Kind string `json:"kind"`
Options []string `json:"options,omitempty"`
}
ViewFormField is one input in an action form.
type ViewSource ¶ added in v0.2.0
ViewSource binds a view's data to a plugin interface method.