pluginhostsdk

package
v0.0.0-...-aeed61c Latest Latest
Warning

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

Go to latest
Published: Oct 9, 2026 License: MIT Imports: 26 Imported by: 0

Documentation

Index

Constants

View Source
const (
	// MaxResponseBytesEnvironment carries the kernel's configured response
	// body limit (plugins.control_host_max_response_bytes) to a package host.
	MaxResponseBytesEnvironment = "ANIX_CONTROL_HOST_MAX_RESPONSE_BYTES"
	// MaxConfigurableResponseBytes is the largest limit a host accepts from
	// its environment; it matches the kernel configuration bound.
	MaxConfigurableResponseBytes = 64 << 20
	// ResponseEnvelopeBytes is the fixed allowance for everything in a
	// DispatchResponse except the body (status, headers, identifiers). The
	// body alone is held to the configured limit, which is the same rule the
	// kernel package bridge applies, so a legacy response the bridge accepts
	// is never rejected here for its envelope.
	ResponseEnvelopeBytes = 64 << 10
)
View Source
const (
	RouteModeLegacy = "legacy"
	RouteModeShadow = "shadow"
	RouteModeNative = "native"
)

Route modes, as configured in the installation's "routes" document.

View Source
const DefaultMaxResponseBytes = 1 << 20

DefaultMaxResponseBytes is the response body limit used when ServerConfig.MaxResponseBytes is zero.

View Source
const IndexMigrationPrefix = "index."

IndexMigrationPrefix starts the id of a migration run that applies a package's whole migration index.

Variables

View Source
var ErrNativeRoutePanicked = errors.New("native route panicked")

ErrNativeRoutePanicked reports a recovered panic in a native route. A panic in a background shadow run would otherwise terminate the host process.

View Source
var ErrNativeUnavailable = errors.New("native route cannot serve this request")

ErrNativeUnavailable is what a native handler returns when it cannot answer this request as the legacy handler would, for example because the kernel did not send request metadata the handler needs (an older kernel sends no request scheme and host). The router then answers from the legacy handler in native mode, and skips the comparison in shadow mode.

Functions

func HostServerOptions

func HostServerOptions() []grpc.ServerOption

HostServerOptions returns the recommended gRPC server options for a package host: RecoveryServerOptions plus a receive limit large enough for any request body the kernel may be configured to forward. The host socket is private to the kernel, which enforces the configured request limit before a request reaches the host.

func MaxResponseBytesFromEnvironment

func MaxResponseBytesFromEnvironment() (int, error)

MaxResponseBytesFromEnvironment returns the response body limit configured by the kernel, or zero (the SDK default) when the variable is unset.

func MessageSizeLimit

func MessageSizeLimit(bodyLimit int) int

MessageSizeLimit returns the gRPC message size needed to carry a body of bodyLimit bytes plus the fixed envelope, never below grpc-go's default.

func RecoveryServerOptions

func RecoveryServerOptions() []grpc.ServerOption

RecoveryServerOptions returns gRPC server options whose unary and stream interceptors turn a panic anywhere in a host RPC into codes.Internal instead of terminating the package host process. Hosts pass them to grpc.NewServer; chain any further interceptors after them so recovery stays outermost.

Types

type DispatchRequest

type DispatchRequest struct {
	PackageID          string
	PackageVersion     string
	RouteGeneration    uint64
	RequestID          string
	IdempotencyKey     string
	RouteID            string
	Method             string
	RequestBody        []byte
	PrincipalJSON      []byte
	Metadata           RequestMetadata
	BridgeCapability   []byte
	DeadlineUnixMillis int64
}

type DispatchResponse

type DispatchResponse struct {
	StatusCode   uint32
	ResponseBody []byte
	Headers      []Header
	OperationID  string
	FailureCode  string
}

type DrainResponse

type DrainResponse struct {
	Drained  bool
	InFlight uint64
}
type Header struct {
	Name  string
	Value string
}

type HealthResponse

type HealthResponse struct {
	Healthy     bool
	LeaseID     string
	DetailsJSON string
}

type MigrationRequest

type MigrationRequest struct {
	PackageID          string
	PackageVersion     string
	MigrationID        string
	Checkpoint         string
	RouteGeneration    uint64
	BridgeCapability   []byte
	DeadlineUnixMillis int64
}

type MigrationResponse

type MigrationResponse struct {
	Checkpoint       string
	ValidationDigest string
	Complete         bool
	FailureCode      string
}

type NativeHandler

type NativeHandler func(context.Context, NativeRequest) (NativeResponse, error)

NativeHandler implements one v2 route inside the package host.

type NativeRequest

type NativeRequest struct {
	RouteID string
	Method  string
	// Body is the request body. For the routes the kernel lists in
	// config/node-secret-fields.json, every node secret in it is a sealed
	// handle (v2compat.SealedHandlePrefix) that only the kernel resolves.
	Body      []byte
	Principal Principal
	Metadata  RequestMetadata
	// Binding is the request binding a KernelNodeOps call passes as
	// RequestBinding.bridge_capability: the kernel resolves the request's
	// sealed handles, and mints the handles its answer shows, only for it.
	// It is nil in a shadow run, which must not act, and whose handles are
	// never resolved.
	Binding []byte
}

NativeRequest is what a package-native route implementation receives.

type NativeResponse

type NativeResponse struct {
	StatusCode uint32
	Body       []byte
	Headers    []Header
}

NativeResponse is a native route's HTTP-level answer; the kernel gateway applies the route's declared envelope rules to it, as for legacy answers.

func PanelJSON

func PanelJSON(panel v2compat.Panel) (NativeResponse, error)

PanelJSON is a NativeResponse carrying a panel envelope, byte-identical to the kernel's legacy panel responses.

type Principal

type Principal struct {
	ActorID   uint   `json:"actor_id"`
	Admin     bool   `json:"admin"`
	PackageID string `json:"package_id"`
}

Principal is the kernel-authenticated caller of a v2 route.

type RequestMetadata

type RequestMetadata struct {
	Path                             string              `json:"path,omitempty"`
	Query                            map[string][]string `json:"query,omitempty"`
	Headers                          map[string][]string `json:"headers,omitempty"`
	PathParams                       map[string]string   `json:"path_params,omitempty"`
	ClientIP                         string              `json:"client_ip,omitempty"`
	UserAgent                        string              `json:"user_agent,omitempty"`
	NodeID                           uint                `json:"node_id,omitempty"`
	TrustedAgentWebSocketAuth        bool                `json:"trusted_agent_websocket_auth,omitempty"`
	TrustedAgentWebSocketForwardNode bool                `json:"trusted_agent_websocket_forward_node,omitempty"`
	Scheme                           string              `json:"-"`
	Host                             string              `json:"-"`
}

RequestMetadata is kernel-provided HTTP address metadata. It is distinct from signed route selection and lets a package preserve the legacy v2 request contract without consulting kernel routing state.

Scheme and Host are the original request's scheme ("http" or "https", from the connection's TLS state) and Host header (a host[:port] the kernel validated). The kernel sends them as protobuf fields of their own, not in the metadata JSON, which hosts built with the v4.0.0 SDK decode strictly. A kernel that predates them leaves both empty; a handler that needs them then returns ErrNativeUnavailable.

type ResumablePackage

type ResumablePackage interface {
	Resume(context.Context) error
}

ResumablePackage undoes a Drain. Network modules implement it because the kernel cannot restart them: a drained instance serves again after it binds to a new generation or the kernel calls Resume.

type Router

type Router struct {
	// contains filtered or unexported fields
}

Router is a Package that applies per-route modes. Legacy routes pass through the package bridge to the kernel's legacy handler; native routes are answered by the package; shadow routes (GET only) answer from legacy and compare a background native run.

func NewRouter

func NewRouter(config RouterConfig) (*Router, error)

NewRouter validates the configuration. Call Run to start polling the installation configuration; until the first successful poll every route is in legacy mode.

func (*Router) Dispatch

func (r *Router) Dispatch(ctx context.Context, request DispatchRequest) (DispatchResponse, error)

func (*Router) Drain

func (r *Router) Drain(context.Context) (DrainResponse, error)

func (*Router) Draining

func (r *Router) Draining() bool

Draining reports whether the router refuses new requests.

func (*Router) Health

func (r *Router) Health(context.Context) (HealthResponse, error)

func (*Router) Migrate

func (r *Router) Migrate(ctx context.Context, request MigrationRequest) (MigrationResponse, error)

Migrate forwards a migration to its kernel bridge operation.

func (*Router) Mode

func (r *Router) Mode(routeID string) (configured, effective string)

Mode returns the configured and the effective mode of a route. The effective mode is legacy whenever the package has no native implementation.

func (*Router) OpenWebSocket

func (r *Router) OpenWebSocket(ctx context.Context, open WebSocketOpen, stream WebSocketStream) error

OpenWebSocket relays WebSocket routes to the kernel; they always run in legacy mode.

func (*Router) Refresh

func (r *Router) Refresh(ctx context.Context)

Refresh reads the configuration once. A failed read keeps the last successful modes; a kernel without session operations means all-legacy.

func (*Router) Resume

func (r *Router) Resume(context.Context) error

Resume serves again after a Drain.

func (*Router) Run

func (r *Router) Run(ctx context.Context)

Run polls the installation configuration until ctx ends.

type RouterBridge

type RouterBridge interface {
	Invoke(ctx context.Context, capability []byte, operation string, payload []byte) (packagebridgesdk.Response, error)
	GetPackageConfig(ctx context.Context) (packagebridgesdk.PackageConfig, error)
}

RouterBridge is the part of the package bridge client the router uses.

type RouterConfig

type RouterConfig struct {
	PackageID string
	LeaseID   string
	Bridge    RouterBridge
	// Native maps route ids to package-native implementations. Routes without
	// one always run in legacy mode, whatever the configuration says.
	Native map[string]NativeHandler
	// AllowRoute, when set, rejects dispatch for route ids it returns false for.
	AllowRoute func(routeID string) bool
	// MigrationOperation maps a migration id to its bridge operation; nil uses
	// "migration.<package>.<id>". It returns false for unsupported migrations.
	MigrationOperation func(migrationID string) (string, bool)
	// IndexMigration runs the package's own migration index when the kernel
	// sends a migration id with IndexMigrationPrefix, which it does only for
	// packages that declare kernel.storage.v1. It needs no bridge capability;
	// packagestoresdk.IndexMigrator implements it.
	IndexMigration func(ctx context.Context, request MigrationRequest) (MigrationResponse, error)
	// Compare decides whether a shadow run matched; nil compares the status
	// code and v2compat-normalized bodies.
	Compare func(legacy, native NativeResponse) bool

	PollInterval      time.Duration
	ShadowTimeout     time.Duration
	ShadowConcurrency int
	Logf              func(format string, args ...any)
	Now               func() time.Time
}

RouterConfig configures a Router.

type RouterWebSocketBridge

type RouterWebSocketBridge interface {
	OpenWebSocket(ctx context.Context, capability []byte, operation string) (packagebridgesdk.WebSocketStream, error)
}

RouterWebSocketBridge is implemented by bridges that relay WebSocket routes.

type Server

type Server struct {
	pluginhostv1.UnimplementedControlPackageHostServer
	// contains filtered or unexported fields
}

func NewServer

func NewServer(config ServerConfig, packageImpl Package) (*Server, error)

func (*Server) Dispatch

func (*Server) Drain

func (s *Server) Drain(ctx context.Context, request *pluginhostv1.DrainRequest) (_ *pluginhostv1.DrainResponse, err error)

func (*Server) Health

func (s *Server) Health(ctx context.Context, request *pluginhostv1.HealthRequest) (_ *pluginhostv1.HealthResponse, err error)

func (*Server) Migrate

func (*Server) OpenWebSocket

func (s *Server) OpenWebSocket(stream pluginhostv1.ControlPackageHost_OpenWebSocketServer) (err error)

func (*Server) Resume

func (s *Server) Resume(ctx context.Context, request *pluginhostv1.ResumeRequest) (_ *pluginhostv1.ResumeResponse, err error)

Resume undoes a Drain when the package supports it.

type ServerConfig

type ServerConfig struct {
	PackageID      string
	PackageVersion string
	// MaxResponseBytes bounds DispatchResponse.ResponseBody; the whole
	// encoded response may additionally use ResponseEnvelopeBytes. Hosts
	// should set it from MaxResponseBytesFromEnvironment. Zero selects
	// DefaultMaxResponseBytes.
	MaxResponseBytes int
}

type WebSocketClose

type WebSocketClose struct {
	Code   uint32
	Reason string
}

type WebSocketFrame

type WebSocketFrame struct {
	Data  []byte
	Close *WebSocketClose
}

WebSocketFrame is a post-open package-host frame. A nil Close denotes a data frame, including an empty opaque payload.

type WebSocketOpen

type WebSocketOpen struct {
	PackageID          string
	PackageVersion     string
	RouteGeneration    uint64
	RouteID            string
	PrincipalJSON      []byte
	Metadata           RequestMetadata
	RequestID          string
	IdempotencyKey     string
	DeadlineUnixMillis int64
	BridgeCapability   []byte
}

type WebSocketPackage

type WebSocketPackage interface {
	OpenWebSocket(context.Context, WebSocketOpen, WebSocketStream) error
}

WebSocketPackage is intentionally optional so a host cannot accidentally claim WebSocket support merely by implementing unary package methods.

type WebSocketStream

type WebSocketStream interface {
	Recv() (WebSocketFrame, error)
	Send(WebSocketFrame) error
}

Jump to

Keyboard shortcuts

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