packagebridge

package
v4.2.0 Latest Latest
Warning

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

Go to latest
Published: Oct 11, 2026 License: MIT Imports: 43 Imported by: 0

Documentation

Overview

Package packagebridge exposes narrow, generation-bound kernel operations to a single supervised package host. It intentionally has no database, file, configuration, or arbitrary-query API.

Index

Constants

View Source
const (
	RouteModeLegacy = "legacy"
	RouteModeShadow = "shadow"
	RouteModeNative = "native"
)

Route modes a package host applies per v2 route.

View Source
const (
	DefaultHeartbeatInterval = 5 * time.Second
	DefaultSessionTTL        = 15 * time.Second
)

Module bridge timing defaults.

View Source
const (

	// DefaultMaxResponseBodyBytes bounds a bridge response body when a
	// session is created without SessionOptions.MaxResponseBodyBytes.
	DefaultMaxResponseBodyBytes int64 = 1 << 20
)
View Source
const SessionMetadataKey = "x-anix-bridge-session"

SessionMetadataKey carries the Bind session token on every later bridge call of a remote module instance.

Variables

View Source
var (
	ErrCapabilityRejected = errors.New("package bridge capability rejected")
	ErrBridgeClosed       = errors.New("package bridge is closed")
	// ErrResponseTooLarge reports a bridged response body above the session
	// limit. The bridge returns it to the host as codes.ResourceExhausted.
	ErrResponseTooLarge = errors.New("package bridge response exceeds its limit")
)
View Source
var ErrBindingRejected = errors.New("package bridge request binding rejected")

ErrBindingRejected is a request binding that names no live request of the calling host: an unknown, consumed, revoked or expired capability, or one minted for another host generation.

View Source
var ErrHostFenced = errors.New("package host is not the current installation generation")

ErrHostFenced reports that the calling host no longer matches the current installation: another version or lifecycle generation is desired, or the package is disabled. The host must not act on stale authority.

View Source
var ErrNotRemote = errors.New("package has no enabled remote installation at this version")

ErrNotRemote means the package has no enabled installation that runs in the remote runtime at the requested version.

View Source
var ErrStorageUnavailable = errors.New("package storage is unavailable")

ErrStorageUnavailable reports that the kernel cannot lease storage to the host, for example because its manifest does not declare kernel.storage.v1 or the kernel database role cannot create package roles. The error text is returned to the host.

Functions

func BoundRequest added in v4.1.0

func BoundRequest(ctx context.Context, raw []byte) (HostIdentity, Request, error)

BoundRequest returns the live request a request binding names: a capability the kernel minted for a dispatch to the calling host, found only on the generation the call arrived on (its local session or its module instance's generation), without consuming it. Contracts that act for a v2 request (KernelNodeOps) verify their RequestBinding with it.

Types

type Allowlist

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

Allowlist binds every bridge operation to one package and v2 route id.

func NewAllowlistWithFallback

func NewAllowlistWithFallback(fallback OperationResolver, operations ...Operation) (*Allowlist, error)

NewAllowlistWithFallback composes static package operations with a resolver that still requires an exact package, route, and operation match.

func (*Allowlist) Allows

func (a *Allowlist) Allows(packageID, routeID, operation string) bool

func (*Allowlist) Invoke

func (a *Allowlist) Invoke(ctx context.Context, call Call) (Response, error)

type Binder added in v4.1.0

type Binder interface {
	BindInstance(ctx context.Context, binding InstanceBinding) (*GenerationSession, error)
}

Binder admits a remote instance and returns the generation it serves. The remote runtime manager implements it; it must check that the installation is enabled, runs remotely and desires this version.

type BoundInstance added in v4.1.0

type BoundInstance struct {
	InstanceBinding
	Identity   moduletls.Identity
	Generation uint64
	BoundAt    time.Time
	LastSeen   time.Time
	// contains filtered or unexported fields
}

BoundInstance is one remote module process attached to a generation.

type Call

type Call struct {
	Host      HostIdentity
	Request   Request
	Operation string
	Payload   []byte
}

Call is delivered only after a capability, package identity, route, and operation have all been verified.

type Factory

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

func NewFactory

func NewFactory(allowlist *Allowlist, webSocketResolvers ...WebSocketOperationResolver) *Factory

func (*Factory) NewGenerationSession added in v4.1.0

func (f *Factory) NewGenerationSession(identity HostIdentity) (*GenerationSession, error)

NewGenerationSession returns the transport-independent state of a remote generation with the factory's operations and limits.

func (*Factory) NewSession

func (f *Factory) NewSession(identity HostIdentity) (*Session, *os.File, error)

func (*Factory) WithSessionOptions added in v4.1.0

func (f *Factory) WithSessionOptions(options SessionOptions) *Factory

WithSessionOptions sets the payload limits applied to every session the factory creates and returns the factory.

type GenerationSession added in v4.1.0

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

GenerationSession is the kernel-side state of one package host generation: its identity, the one-shot capabilities minted for its requests, and the operations it may call. It is independent of the transport: a local host reaches it through its own socketpair Session, and every remote instance of the same generation shares one through the module bridge, so any of them can redeem a capability minted for the generation.

func NewGenerationSession added in v4.1.0

func NewGenerationSession(identity HostIdentity, handler *Allowlist, options SessionOptions, webSocketResolvers ...WebSocketOperationResolver) (*GenerationSession, error)

NewGenerationSession returns the state of one host generation.

func (*GenerationSession) Close added in v4.1.0

func (s *GenerationSession) Close() error

Close fences the generation: unconsumed capabilities are dropped and every later call is rejected.

func (*GenerationSession) Closed added in v4.1.0

func (g *GenerationSession) Closed() bool

Closed reports whether the generation is fenced.

func (*GenerationSession) Draining added in v4.1.0

func (g *GenerationSession) Draining() bool

Draining reports whether the kernel is draining the generation.

func (*GenerationSession) Identity added in v4.1.0

func (g *GenerationSession) Identity() HostIdentity

Identity returns the generation's host identity.

func (*GenerationSession) Mint added in v4.1.0

func (s *GenerationSession) Mint(request Request) ([]byte, error)

Mint creates an opaque one-shot capability for a dispatch already admitted by the kernel. It is not an authority token that a package can fabricate.

func (*GenerationSession) Peek added in v4.1.0

func (s *GenerationSession) Peek(raw []byte) (Request, bool)

Peek returns the request a live capability was minted for, without consuming it: minted by this generation, not yet consumed or revoked, and before its deadline. KernelNodeOps verifies request bindings with it.

func (*GenerationSession) Revoke added in v4.1.0

func (s *GenerationSession) Revoke(raw []byte)

Revoke removes an unconsumed capability once the outer package-host dispatch returns. Calling it after a successful bridge call is harmless.

func (*GenerationSession) ServeLegacy added in v4.1.0

func (s *GenerationSession) ServeLegacy(ctx context.Context, request Request, operation string) (Response, error)

ServeLegacy runs the kernel's legacy operation for a request without a capability and without the package host: the v2 gateway's fail-closed path when a request's secrets cannot be sealed. The operation must be one the generation's allowlist binds to the request's route, as for a capability.

func (*GenerationSession) SetDraining added in v4.1.0

func (g *GenerationSession) SetDraining(draining bool)

SetDraining records whether the kernel is draining the generation; remote instances learn it from their heartbeat.

type GenerationSessionFactory added in v4.1.0

type GenerationSessionFactory interface {
	NewGenerationSession(HostIdentity) (*GenerationSession, error)
}

GenerationSessionFactory creates bridge state for remote generations, which have no socketpair.

type Header struct {
	Name  string
	Value string
}

type HostIdentity

type HostIdentity struct {
	PackageID  string
	Version    string
	Generation uint64
	// Remote marks a generation served by network module instances rather
	// than a local child process.
	Remote bool
}

HostIdentity is fixed when a child process is started. The socketpair makes this identity process-local rather than client-asserted.

type HostOperations added in v4.1.0

type HostOperations interface {
	PackageConfig(ctx context.Context, host HostIdentity) (PackageConfig, error)
	LeaseStorage(ctx context.Context, host HostIdentity) (StorageLease, error)
}

HostOperations serves session-scoped RPCs. They carry no per-request capability: the caller is authorized by the session identity, which the kernel bound to the inherited socketpair when it started the host. Implementations must fence every call against the current installation.

type InstanceBinding added in v4.1.0

type InstanceBinding struct {
	PackageID     string
	Version       string
	InstanceID    string
	AdvertiseAddr string
	LeaseID       string
	// ImageDigest is advisory: the kernel cannot prove what a remote
	// process runs.
	ImageDigest string
}

InstanceBinding is what a remote module instance reports when it binds.

type KernelForwardProvider added in v4.2.0

type KernelForwardProvider func(HostIdentity) forwardv1.ForwardControlServer

KernelForwardProvider returns the ForwardControl server that one calling host reaches. The server authorizes the host on every call.

type KernelIdentityProvider added in v4.1.0

type KernelIdentityProvider func(HostIdentity) kernelidentityv1.KernelIdentityServer

KernelIdentityProvider returns the KernelIdentity server that one calling host reaches. The server authorizes the host on every call.

type KernelNodeOpsProvider added in v4.1.0

type KernelNodeOpsProvider func(HostIdentity) kernelnodeopsv1.KernelNodeOpsServer

KernelNodeOpsProvider returns the KernelNodeOps server that one calling host reaches. The server authorizes the host on every call.

type KernelOrderProvider added in v4.1.0

type KernelOrderProvider func(HostIdentity) kernelorderv1.KernelOrderServer

KernelOrderProvider returns the KernelOrder server that one calling host reaches. The server authorizes the host on every call.

type KernelSettingsProvider added in v4.1.0

type KernelSettingsProvider func(HostIdentity) kernelsettingsv1.KernelSettingsServer

KernelSettingsProvider returns the KernelSettings server that one calling host reaches. The server authorizes the host on every call.

type KernelSubscriberProvider added in v4.1.0

type KernelSubscriberProvider func(HostIdentity) kernelsubscriberv1.KernelSubscriberServer

KernelSubscriberProvider returns the KernelSubscriber server that one calling host reaches. The server authorizes the host on every call.

type KernelTelemetryProvider added in v4.1.0

type KernelTelemetryProvider func(HostIdentity) kerneltelemetryv1.KernelTelemetryServer

KernelTelemetryProvider returns the KernelTelemetry server that one calling host reaches. The server authorizes the host on every call.

type ModuleBridge added in v4.1.0

type ModuleBridge struct {
	packagebridgev1.UnimplementedKernelPackageBridgeServer
	// contains filtered or unexported fields
}

ModuleBridge serves KernelPackageBridge to remote module instances over the kernel's mTLS module listener. An instance is authenticated by its client certificate identity; Bind admits it to a generation and returns a session token that every later call presents in SessionMetadataKey. The token is pinned to the module identity rather than to one certificate, because instances renew their certificates while the session lives.

func NewModuleBridge added in v4.1.0

func NewModuleBridge(binder Binder, options ModuleBridgeOptions) (*ModuleBridge, error)

NewModuleBridge returns a bridge that admits instances through binder. A nil binder rejects every Bind.

func (*ModuleBridge) Bind added in v4.1.0

Bind admits the calling instance to the generation its package runs.

func (*ModuleBridge) GetPackageConfig added in v4.1.0

func (*ModuleBridge) Heartbeat added in v4.1.0

Heartbeat keeps a session alive and reports whether its generation is fenced or draining. A fenced instance must Bind again.

func (*ModuleBridge) Instances added in v4.1.0

func (b *ModuleBridge) Instances(packageID string, generation uint64) []BoundInstance

Instances returns the live instances bound to generation of packageID, ordered by instance id, for dispatch.

func (*ModuleBridge) Invoke added in v4.1.0

func (*ModuleBridge) KernelForwardServer added in v4.2.0

func (b *ModuleBridge) KernelForwardServer(provider KernelForwardProvider) forwardv1.ForwardControlServer

KernelForwardServer serves ForwardControl on the module listener: each call is resolved to the bound instance's generation and handed to provider with that generation's host identity.

func (*ModuleBridge) KernelIdentityServer added in v4.1.0

KernelIdentityServer serves KernelIdentity on the module listener: each call is resolved to the bound instance's generation, as the package bridge RPCs are, and handed to provider with that generation's host identity.

func (*ModuleBridge) KernelNodeOpsServer added in v4.1.0

func (b *ModuleBridge) KernelNodeOpsServer(provider KernelNodeOpsProvider) kernelnodeopsv1.KernelNodeOpsServer

KernelNodeOpsServer serves KernelNodeOps on the module listener: each call, unary or streaming, is resolved to the bound instance's generation and handed to provider with that generation's host identity.

func (*ModuleBridge) KernelOrderServer added in v4.1.0

func (b *ModuleBridge) KernelOrderServer(provider KernelOrderProvider) kernelorderv1.KernelOrderServer

KernelOrderServer serves KernelOrder on the module listener: each call is resolved to the bound instance's generation and handed to provider with that generation's host identity.

func (*ModuleBridge) KernelSettingsServer added in v4.1.0

KernelSettingsServer serves KernelSettings on the module listener: each call is resolved to the bound instance's generation and handed to provider with that generation's host identity.

func (*ModuleBridge) KernelSubscriberServer added in v4.1.0

KernelSubscriberServer serves KernelSubscriber on the module listener: each call is resolved to the bound instance's generation and handed to provider with that generation's host identity.

func (*ModuleBridge) KernelTelemetryServer added in v4.1.0

KernelTelemetryServer serves KernelTelemetry on the module listener: each call is resolved to the bound instance's generation and handed to provider with that generation's host identity.

func (*ModuleBridge) LeaseStorage added in v4.1.0

func (*ModuleBridge) OpenWebSocket added in v4.1.0

func (*ModuleBridge) Run added in v4.1.0

func (b *ModuleBridge) Run(ctx context.Context)

Run sweeps expired sessions until ctx ends.

func (*ModuleBridge) Sweep added in v4.1.0

func (b *ModuleBridge) Sweep()

Sweep drops sessions whose heartbeat expired or whose generation is fenced.

type ModuleBridgeOptions added in v4.1.0

type ModuleBridgeOptions struct {
	// Cluster is the SPIFFE cluster whose modules may bind.
	Cluster           string
	HeartbeatInterval time.Duration
	SessionTTL        time.Duration
	Now               func() time.Time
}

ModuleBridgeOptions configures a ModuleBridge.

type Operation

type Operation struct {
	PackageID string
	RouteID   string
	Name      string
	Handler   OperationHandler
}

type OperationHandler

type OperationHandler func(context.Context, Call) (Response, error)

func NewHTTPAdapter

func NewHTTPAdapter(handler gin.HandlerFunc) OperationHandler

NewHTTPAdapter turns a deliberately allowlisted legacy Gin handler into a bridge operation. It uses only the request snapshot retained by Session; package-supplied payload bytes are never treated as an HTTP request.

type OperationResolver

type OperationResolver interface {
	Resolve(packageID, routeID, operation string) (OperationHandler, bool)
}

OperationResolver provides an additional exact operation source. It is used for handlers registered during router construction, not for path matching or arbitrary package-supplied operation names.

type PackageConfig added in v4.1.0

type PackageConfig struct {
	Revision   int64
	ConfigHash string
	// RouteModes maps route ids to RouteModeShadow or RouteModeNative; routes
	// that are absent run in legacy mode.
	RouteModes map[string]string
}

PackageConfig is the configuration a host reads for itself.

type Request

type Request struct {
	RequestID string
	RouteID   string
	Method    string
	// Body is the request as the client sent it: the legacy handler reads
	// it, also when the package host read a body with sealed secrets.
	Body          []byte
	PrincipalJSON []byte
	MetadataJSON  []byte
	Deadline      time.Time
	// SealedRequest names the request's sealed secrets
	// (internal/sealedsecrets): a KernelNodeOps call bound to this
	// capability resolves only them. Empty when nothing was sealed.
	SealedRequest string
}

Request is kernel-derived request state retained behind a capability. A package never supplies these values to the bridge RPC.

type Response

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

Response is an explicit parent-produced answer to one allowed bridge operation. Package code cannot obtain this authority except by consuming a verified capability.

type RouteRegistry

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

RouteRegistry is populated only while Gin routes are constructed. It keeps the legacy-compatible handler behind the kernel's exact bridge operation checks; it does not inspect package-controlled paths or route declarations.

func DefaultRouteRegistry

func DefaultRouteRegistry() *RouteRegistry

DefaultRouteRegistry is shared by the production router and its host supervisor. Tests may use NewRouteRegistry for isolated contracts.

func NewRouteRegistry

func NewRouteRegistry() *RouteRegistry

func (*RouteRegistry) Allowlist

func (r *RouteRegistry) Allowlist() *Allowlist

Allowlist exposes the registered routes through the same exact-operation interface used by static bridge handlers.

func (*RouteRegistry) MustRegister

func (r *RouteRegistry) MustRegister(packageID, routeID string, handler gin.HandlerFunc)

MustRegister is for static router declarations. A bad declaration is a process-startup error, not a recoverable request-time condition.

func (*RouteRegistry) MustRegisterWebSocket

func (r *RouteRegistry) MustRegisterWebSocket(packageID, routeID string, handler gin.HandlerFunc)

MustRegisterWebSocket is for static router declarations. Invalid ownership is a process-startup error, not a request-time fallback condition.

func (*RouteRegistry) Register

func (r *RouteRegistry) Register(packageID, routeID string, handler gin.HandlerFunc) error

Register binds an exact package route to one Gin handler. Rebuilding a router may replace the handler for the same package/route, but a route id can never be rebound to another package.

func (*RouteRegistry) RegisterWebSocket

func (r *RouteRegistry) RegisterWebSocket(packageID, routeID string, handler gin.HandlerFunc) error

RegisterWebSocket binds an exact package route to a legacy-compatible WebSocket handler. It shares ownership checks with unary routes.

func (*RouteRegistry) Resolve

func (r *RouteRegistry) Resolve(packageID, routeID, operation string) (OperationHandler, bool)

func (*RouteRegistry) ResolveWebSocket

func (r *RouteRegistry) ResolveWebSocket(packageID, routeID, operation string) (WebSocketOperationHandler, bool)

type Session

type Session struct {
	packagebridgev1.UnimplementedKernelPackageBridgeServer

	*GenerationSession
	// contains filtered or unexported fields
}

Session owns one endpoint of an inherited Unix socketpair. The returned child file is passed once through exec.ExtraFiles and is never addressable by a filesystem path.

func NewSession

func NewSession(identity HostIdentity, handler *Allowlist, webSocketResolvers ...WebSocketOperationResolver) (*Session, *os.File, error)

func NewSessionWithOptions added in v4.1.0

func NewSessionWithOptions(identity HostIdentity, handler *Allowlist, options SessionOptions, webSocketResolvers ...WebSocketOperationResolver) (*Session, *os.File, error)

NewSessionWithOptions is NewSession with explicit payload limits.

func (*Session) Close

func (s *Session) Close() error

Close fences the generation and closes the socketpair.

func (*Session) GetPackageConfig added in v4.1.0

GetPackageConfig returns the calling host's installation configuration.

func (*Session) Invoke

func (*Session) LeaseStorage added in v4.1.0

LeaseStorage returns fresh credentials for the calling host's storage.

func (*Session) OpenWebSocket

type SessionFactory

type SessionFactory interface {
	NewSession(HostIdentity) (*Session, *os.File, error)
}

SessionFactory creates a fresh private endpoint for every supervised host.

type SessionOptions added in v4.1.0

type SessionOptions struct {
	// MaxResponseBodyBytes bounds a response body returned to the package
	// host. Zero selects DefaultMaxResponseBodyBytes.
	MaxResponseBodyBytes int64
	// MaxRequestBodyBytes is the kernel's request body limit. The bridge uses
	// it only to size its gRPC receive window for host payloads.
	MaxRequestBodyBytes int64
	// HostOperations serves the session-scoped RPCs (GetPackageConfig and
	// LeaseStorage). Nil answers them with codes.Unimplemented, which hosts
	// treat as "no configuration": every route stays in legacy mode and no
	// storage is available.
	HostOperations HostOperations
	// KernelIdentity, when set, serves the KernelIdentity contract on the
	// session; the provided server authorizes the host on every call.
	KernelIdentity KernelIdentityProvider
	// KernelOrder, when set, serves the KernelOrder contract on the
	// session, authorized per capability on every call.
	KernelOrder KernelOrderProvider
	// KernelSubscriber, when set, serves the KernelSubscriber contract on
	// the session, authorized per capability on every call.
	KernelSubscriber KernelSubscriberProvider
	// KernelSettings, when set, serves the KernelSettings contract on the
	// session, authorized per namespace capability on every call.
	KernelSettings KernelSettingsProvider
	// KernelTelemetry, when set, serves the KernelTelemetry contract on the
	// session, authorized per capability on every call.
	KernelTelemetry KernelTelemetryProvider
	// KernelNodeOps, when set, serves the KernelNodeOps contract on the
	// session, authorized per operation family on every call.
	KernelNodeOps KernelNodeOpsProvider
	// KernelForward, when set, serves the ForwardControl contract on the
	// session, authorized for kernel.forward.v1 on every call.
	KernelForward KernelForwardProvider
}

SessionOptions carries the kernel's configured payload limits into a bridge session.

type StorageLease added in v4.1.0

type StorageLease struct {
	Driver          string
	DSN             string
	Schema          string
	TablePrefix     string
	LeaseGeneration int64
	AdoptedTables   []string
	Views           []string
}

StorageLease carries the credentials of a package's own storage. It never contains kernel credentials.

type WebSocketClose

type WebSocketClose struct {
	Code   uint32
	Reason string
}

type WebSocketFrame

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

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

type WebSocketOperationHandler

type WebSocketOperationHandler func(context.Context, Call, WebSocketStream) error

func NewWebSocketAdapter

func NewWebSocketAdapter(handler gin.HandlerFunc) WebSocketOperationHandler

NewWebSocketAdapter runs an allowlisted legacy Gin WebSocket handler over a private in-memory connection. The package host receives only opaque frames; the legacy handler and its database access remain in the kernel process.

type WebSocketOperationResolver

type WebSocketOperationResolver interface {
	ResolveWebSocket(packageID, routeID, operation string) (WebSocketOperationHandler, bool)
}

WebSocketOperationResolver provides exact streaming operations registered during router construction. It is separate from unary operations so a package cannot upgrade a route merely by changing a declaration.

type WebSocketStream

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

WebSocketStream is the kernel-side end of a private package bridge stream. Exactly one reader and one writer may operate concurrently.

Jump to

Keyboard shortcuts

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