rpc

package
v0.7.0 Latest Latest
Warning

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

Go to latest
Published: Apr 14, 2026 License: Apache-2.0 Imports: 62 Imported by: 0

Documentation

Index

Constants

View Source
const (
	TypeRW = iota
	TypeR
	TypeW
)
View Source
const BootstrapOID = "!bootstrap"

Variables

View Source
var (
	ErrResolveHTTP   = &ResolveError{Kind: ResolveHTTPError, Msg: "http request error"}
	ErrResolveStatus = &ResolveError{Kind: ResolveStatusError, Msg: "unexpected status code"}
	ErrResolveDecode = &ResolveError{Kind: ResolveDecodeError, Msg: "decode error"}
	ErrResolveLookup = &ResolveError{Kind: ResolveLookupError, Msg: "lookup error"}
)

Exported sentinel errors for common resolve error kinds

View Source
var (
	DefaultTransport  http3.Transport
	DefaultQUICConfig quic.Config

	DefaultLogLevel = slog.LevelInfo
)
View Source
var ErrUnauthorized = errors.New("unauthorized")

ErrUnauthorized is returned when an app-scoped caller attempts to operate on an app they are not bound to.

Functions

func AllowApp added in v0.5.0

func AllowApp(ctx context.Context, appName string) bool

AllowApp checks whether the current caller is permitted to operate on the named app. Callers that are not app-scoped (cert, JWT, anonymous) are always allowed. OIDC callers are restricted to the app their binding is for.

func AppAccessError added in v0.5.0

func AppAccessError(ctx context.Context, appName string) error

AppAccessError returns a descriptive error for an app-scoping denial.

func BoundApp added in v0.5.0

func BoundApp(ctx context.Context) string

BoundApp returns the app name that the current OIDC caller is bound to, or empty string if the caller is not app-scoped.

func CanBe

func CanBe[T, I any]() bool

func ContextWithIdentity added in v0.3.1

func ContextWithIdentity(ctx context.Context, identity *Identity) context.Context

ContextWithIdentity returns a new context with the Identity stored

func NewResolveDecodeError

func NewResolveDecodeError(err error) error

NewResolveDecodeError creates a decode error

func NewResolveError

func NewResolveError(kind ResolveErrorKind, err error, msg string) error

NewResolveError creates a new ResolveError with the specified kind and underlying error

func NewResolveHTTPError

func NewResolveHTTPError(err error, format string, args ...interface{}) error

NewResolveHTTPError creates an HTTP request error

func NewResolveLookupError

func NewResolveLookupError(msg string) error

NewResolveLookupError creates a lookup error

func NewResolveStatusError

func NewResolveStatusError(statusCode int) error

NewResolveStatusError creates a status code error

func Propagator

func Propagator() propagation.TextMapPropagator

func RegisterInterface

func RegisterInterface[T any](fn any) bool

func SetupOTelSDK

func SetupOTelSDK(ctx context.Context) (shutdown func(context.Context) error, err error)

setupOTelSDK bootstraps the OpenTelemetry pipeline. If it does not return an error, make sure to call shutdown for proper cleanup.

func SetupTracing added in v0.4.0

func SetupTracing(ctx context.Context, attrs ...attribute.KeyValue) (shutdown func(context.Context) error, err error)

SetupTracing configures OpenTelemetry tracing with an OTLP HTTP exporter. The exporter reads standard OTel env vars (OTEL_EXPORTER_OTLP_ENDPOINT, OTEL_EXPORTER_OTLP_HEADERS, etc.) so no explicit configuration is needed. Extra resource attributes (e.g. cluster identity) can be passed in. Returns a shutdown function that flushes pending spans.

func Tracer

func Tracer() otrace.Tracer

func WithRequireClientCerts

func WithRequireClientCerts(o *stateOptions)

func WithSkipVerify

func WithSkipVerify(o *stateOptions)

func Zero

func Zero[T any]() T

Types

type ActorCall

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

func (*ActorCall) Args

func (a *ActorCall) Args(v any)

func (*ActorCall) IsAuthenticated added in v0.3.1

func (a *ActorCall) IsAuthenticated() bool

IsAuthenticated returns true for actor calls since they are local and implicitly trusted.

func (*ActorCall) NewCapability

func (a *ActorCall) NewCapability(i *Interface) *Capability

func (*ActorCall) NewClient

func (a *ActorCall) NewClient(capa *Capability) Client

func (*ActorCall) Results

func (a *ActorCall) Results(v any)

type ActorClient

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

func (*ActorClient) Call

func (a *ActorClient) Call(ctx context.Context, name string, arg, ret any) error

func (*ActorClient) CallWithCaps

func (a *ActorClient) CallWithCaps(ctx context.Context, method string, args, result any, caps map[OID]*InlineCapability) error

func (*ActorClient) Close

func (a *ActorClient) Close() error

func (*ActorClient) NewClient

func (a *ActorClient) NewClient(capa *Capability) Client

func (*ActorClient) NewInlineCapability

func (a *ActorClient) NewInlineCapability(i *Interface, lower any) (*InlineCapability, OID, *Capability)

type ActorRegistry

type ActorRegistry interface {
	Register(ctx context.Context, name string, iface *Interface) error
	Client(ctx context.Context, name string) (Client, error)
	Close(ctx context.Context) error
}

func NewLocalActorRegistry

func NewLocalActorRegistry() ActorRegistry

type ActorResolver

type ActorResolver interface {
	Resolve(ctx context.Context, name string) (string, error)
}

type AuthMethod added in v0.3.1

type AuthMethod string

AuthMethod indicates how a caller was authenticated

const (
	AuthMethodCert      AuthMethod = "cert"      // TLS client certificate
	AuthMethodJWT       AuthMethod = "jwt"       // JWT token (e.g., from Miren Cloud)
	AuthMethodAnonymous AuthMethod = "anonymous" // No authentication (public methods)
	AuthMethodToken     AuthMethod = "token"     // Bearer token (e.g., outboard)
	AuthMethodOIDC      AuthMethod = "oidc"      // External OIDC token (e.g., GitHub Actions)
)

type Authenticator

type Authenticator interface {
	// Authenticate validates the request's credentials and returns the caller's identity.
	// Returns:
	//   - (*Identity, nil) if credentials are valid
	//   - (nil, nil) if no credentials present or credentials are invalid
	//   - (nil, error) if an error occurred during authentication
	Authenticate(ctx context.Context, r *http.Request) (*Identity, error)
}

Authenticator validates credentials and returns caller identity

type Authorizer added in v0.3.1

type Authorizer interface {
	// Authorize checks if the identity is allowed to perform the action on the resource.
	// For RPC methods, resource is typically the interface name (lowercase) and
	// action is the method name (lowercase).
	// Returns nil if allowed, or an error describing why access was denied.
	Authorize(ctx context.Context, identity *Identity, resource, action string) error
}

Authorizer checks if an identity is allowed to perform an action on a resource

type Call

type Call interface {
	NewClient(capa *Capability) Client
	Args(v any)
	Results(v any)
	NewCapability(i *Interface) *Capability
	// IsAuthenticated returns true if the caller presented a valid TLS client certificate.
	// This is used by methods that need to distinguish between authenticated and
	// unauthenticated callers (e.g., runner registration allows unauthenticated Join
	// but requires authentication for admin operations like CreateInvite).
	IsAuthenticated() bool
}

type Capability

type Capability struct {
	OID     OID    `cbor:"0,keyasint" json:"oid"`
	Address string `cbor:"1,keyasint" json:"address"`
	User    []byte `cbor:"2,keyasint" json:"owner"`
	Issuer  []byte `cbor:"3,keyasint" json:"issue"`

	RestoreState *InterfaceState `cbor:"4,keyasint" json:"restore-state"`

	Inline bool `cbor:"5,keyasint" json:"inline"`
}

type Client

type Client interface {
	CallWithCaps(ctx context.Context, method string, args, result any, caps map[OID]*InlineCapability) error
	Call(ctx context.Context, method string, args, result any) error
	NewInlineCapability(i *Interface, lower any) (*InlineCapability, OID, *Capability)
	NewClient(capa *Capability) Client
	Close() error
}

type CurrentConnectionInfo

type CurrentConnectionInfo struct {
	PeerSubject string
}

func ConnectionInfo

func ConnectionInfo(ctx context.Context) *CurrentConnectionInfo

type DebugAuthResponse

type DebugAuthResponse struct {
	Success       bool              `json:"success"`
	ServerVersion string            `json:"server_version,omitempty"`
	AuthMethod    string            `json:"auth_method,omitempty"`
	Identity      string            `json:"identity,omitempty"`
	UserInfo      map[string]string `json:"user_info,omitempty"`
	Message       string            `json:"message,omitempty"`
}

DebugAuthResponse represents the response from the debug-auth endpoint

type DescField

type DescField struct {
	Name  string `yaml:"name"`
	Type  string `yaml:"type"`
	Index int    `yaml:"index"`

	Element string       `yaml:"element"`
	Union   []UnionField `yaml:"union,omitempty"`
	Key     string       `yaml:"key,omitempty"`
	Value   string       `yaml:"value,omitempty"`
	// contains filtered or unexported fields
}

type DescFile

type DescFile struct {
	Imports    map[string]Import `yaml:"imports"`
	Types      []*DescType       `yaml:"types"`
	Interfaces []*DescInterface  `yaml:"interfaces"`
}

type DescInterface

type DescInterface struct {
	Name        string         `yaml:"name"`
	Method      []*DescMethods `yaml:"methods"`
	Generic     []string       `yaml:"generic,omitempty"`
	Constraints []string       `yaml:"constraints,omitempty"`
}

type DescMethods

type DescMethods struct {
	Name       string           `yaml:"name"`
	Index      int              `yaml:"index"`
	Parameters []*DescParamater `yaml:"parameters"`
	Results    []*DescParamater `yaml:"results"`
	// Public marks this method as accessible without TLS client certificate authentication.
	// Public methods still require capability-level auth (Ed25519 signatures) but allow
	// unauthenticated callers (e.g., for registration flows where the client doesn't have certs yet).
	Public bool `yaml:"public,omitempty"`
}

type DescParamater

type DescParamater struct {
	Name    string `yaml:"name"`
	Type    string `yaml:"type"`
	Element string `yaml:"element,omitempty"`
	Key     string `yaml:"key,omitempty"`
	Value   string `yaml:"value,omitempty"`
}

type DescType

type DescType struct {
	Type        string       `yaml:"type"`
	Fields      []*DescField `yaml:"fields"`
	Compact     bool         `yaml:"compact,omitempty"`
	Generic     []string     `yaml:"generic,omitempty"`
	Constraints []string     `yaml:"constraints,omitempty"`
	// contains filtered or unexported fields
}

func (*DescType) CalculateOffsets

func (t *DescType) CalculateOffsets(usertypes map[string]*DescType)

func (*DescType) Readable

func (t *DescType) Readable() bool

func (*DescType) Validate

func (t *DescType) Validate() error

func (*DescType) Writeable

func (t *DescType) Writeable() bool

type Dispatcher

type Dispatcher interface {
	Dispatch(ctx context.Context, oid OID, method string, call Call) error
	Bind(oid OID, iface *Interface) error
}

type ErrorCategory

type ErrorCategory interface {
	ErrorCategory() string
}

type ErrorCode

type ErrorCode interface {
	ErrorCode() string
}

type ErrorMessage

type ErrorMessage interface {
	ErrorMessage() string
}

type ForbidRestore

type ForbidRestore interface {
	// contains filtered or unexported methods
}

type Generator

type Generator struct {
	Imports    map[string]Import
	Types      []*DescType
	Interfaces []*DescInterface
	// contains filtered or unexported fields
}

func NewGenerator

func NewGenerator() (*Generator, error)

func (*Generator) Generate

func (g *Generator) Generate(pkgName string) (string, error)

func (*Generator) Read

func (g *Generator) Read(path string) error

type HasReconstructFromState

type HasReconstructFromState interface {
	ReconstructFromState(is *InterfaceState) (*Interface, error)
}

type HasRestoreState

type HasRestoreState interface {
	RestoreState(iface any) (any, error)
}

type Identity added in v0.3.1

type Identity struct {
	// Subject is the primary identifier (cert CN, JWT subject, etc.)
	Subject string

	// Groups contains group memberships (from JWT claims, etc.)
	Groups []string

	// Method indicates how the caller was authenticated
	Method AuthMethod

	// Metadata holds auth-method-specific data (e.g., OrganizationID for cloud auth)
	Metadata map[string]any
}

Identity represents an authenticated caller

func IdentityFromContext added in v0.3.1

func IdentityFromContext(ctx context.Context) *Identity

IdentityFromContext retrieves the Identity from the context, if present

type IfaceReg

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

func NewIfaceReg

func NewIfaceReg() *IfaceReg

type Import

type Import struct {
	Path   string   `yaml:"path"`
	Import string   `yaml:"import"`
	Types  []string `yaml:"types"`
}

type InlineCapability

type InlineCapability struct {
	*Capability
	*Interface
}

type Interface

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

func NewInterface

func NewInterface(methods []Method, obj any) *Interface

func (*Interface) SetAroundContext

func (i *Interface) SetAroundContext(fn func(ctx context.Context, call Call) (context.Context, func()))

func (*Interface) Value

func (i *Interface) Value() any

type InterfaceCreators

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

func NewInterfaceCreators

func NewInterfaceCreators() *InterfaceCreators

type InterfaceDescriptor

type InterfaceDescriptor struct {
}

type InterfaceState

type InterfaceState struct {
	Category  string `cbor:"0,keyasint" json:"category"`
	Interface string `cbor:"1,keyasint" json:"interface"`
	Data      any    `cbor:"2,keyasint" json:"data"`
}

func (*InterfaceState) Decode

func (i *InterfaceState) Decode(v any) error

type LocalActorRegistry

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

func (*LocalActorRegistry) Client

func (r *LocalActorRegistry) Client(ctx context.Context, name string) (Client, error)

func (*LocalActorRegistry) Close

func (r *LocalActorRegistry) Close(ctx context.Context) error

func (*LocalActorRegistry) Register

func (r *LocalActorRegistry) Register(ctx context.Context, name string, iface *Interface) error

type LocalOnlyAuthenticator added in v0.2.0

type LocalOnlyAuthenticator struct{}

LocalOnlyAuthenticator requires a valid TLS client certificate. Used when cloud authentication is not enabled.

func (*LocalOnlyAuthenticator) Authenticate added in v0.3.1

func (l *LocalOnlyAuthenticator) Authenticate(ctx context.Context, r *http.Request) (*Identity, error)

type Method

type Method struct {
	Name          string
	InterfaceName string
	Index         int
	Handler       func(ctx context.Context, call Call) error
	// Public marks this method as accessible without TLS client certificate authentication.
	// The RPC layer will reject unauthenticated calls to non-public methods automatically.
	Public bool
}

type NetworkCall

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

func Local

func Local(args ...any) *NetworkCall

func (*NetworkCall) Args

func (c *NetworkCall) Args(v any)

func (*NetworkCall) IsAuthenticated added in v0.3.1

func (c *NetworkCall) IsAuthenticated() bool

IsAuthenticated returns true if the caller presented a valid TLS client certificate, or if this is a local call (used in tests).

func (*NetworkCall) NewCapability

func (c *NetworkCall) NewCapability(i *Interface) *Capability

func (*NetworkCall) NewClient

func (c *NetworkCall) NewClient(capa *Capability) Client

func (*NetworkCall) RemoteAddr

func (c *NetworkCall) RemoteAddr() string

func (*NetworkCall) Results

func (c *NetworkCall) Results(v any)

func (*NetworkCall) SkipArgs added in v0.2.0

func (c *NetworkCall) SkipArgs()

SkipArgs consumes and discards args if they haven't been consumed yet. This prevents leftover args data from being misinterpreted as the next request.

func (*NetworkCall) String

func (c *NetworkCall) String() string

type NetworkClient

type NetworkClient struct {
	State *State
	// contains filtered or unexported fields
}

func LocalClient

func LocalClient(iface *Interface) *NetworkClient

func (*NetworkClient) Call

func (c *NetworkClient) Call(ctx context.Context, method string, args, result any) error

func (*NetworkClient) CallWithCaps

func (c *NetworkClient) CallWithCaps(ctx context.Context, method string, args, result any, caps map[OID]*InlineCapability) error

func (*NetworkClient) Close

func (c *NetworkClient) Close() error

func (*NetworkClient) HasMethod

func (c *NetworkClient) HasMethod(ctx context.Context, method string) bool

HasMethod checks if the remote interface supports a given method. Returns false if the method doesn't exist or if the server doesn't support introspection.

func (*NetworkClient) ListMethods

func (c *NetworkClient) ListMethods(ctx context.Context) ([]string, error)

ListMethods returns the list of methods available on this capability. Returns an error if the server doesn't support method introspection (old servers).

func (*NetworkClient) NewCapability

func (c *NetworkClient) NewCapability(i *Interface, lower any) *Capability

func (*NetworkClient) NewClient

func (c *NetworkClient) NewClient(capa *Capability) Client

func (*NetworkClient) NewInlineCapability

func (c *NetworkClient) NewInlineCapability(i *Interface, lower any) (*InlineCapability, OID, *Capability)

func (*NetworkClient) String

func (c *NetworkClient) String() string

type NoOpAuthenticator

type NoOpAuthenticator struct{}

NoOpAuthenticator allows all requests without checking credentials. Used for testing only.

func (*NoOpAuthenticator) Authenticate added in v0.3.1

func (n *NoOpAuthenticator) Authenticate(ctx context.Context, r *http.Request) (*Identity, error)

type NoRestore

type NoRestore struct{}

type OID

type OID string

type ResolveError

type ResolveError struct {
	Kind       ResolveErrorKind
	Err        error
	Msg        string
	StatusCode int // HTTP status code for ResolveStatusError
}

ResolveError represents an error that occurred during capability resolution

func (*ResolveError) Error

func (e *ResolveError) Error() string

func (*ResolveError) Is

func (e *ResolveError) Is(target error) bool

func (*ResolveError) Unwrap

func (e *ResolveError) Unwrap() error

type ResolveErrorKind

type ResolveErrorKind int

ResolveErrorKind represents different kinds of capability resolution errors

const (
	ResolveHTTPError ResolveErrorKind = iota
	ResolveStatusError
	ResolveDecodeError
	ResolveLookupError
)

type ResolverFunc

type ResolverFunc func(ctx context.Context, name string) (string, error)

func (ResolverFunc) Resolve

func (f ResolverFunc) Resolve(ctx context.Context, name string) (string, error)

type Server

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

func (*Server) Clone

func (s *Server) Clone(state *State) *Server

func (*Server) Deref

func (s *Server) Deref(oid OID) bool

func (*Server) ExposeValue

func (s *Server) ExposeValue(name string, iface *Interface)

func (*Server) ServeHTTP

func (s *Server) ServeHTTP(w http.ResponseWriter, r *http.Request)

type ServiceID added in v0.3.1

type ServiceID = string

ServiceID represents an RPC service identifier. These are used with RPCClient() and server.ExposeValue() to identify services.

Currently a type alias for incremental adoption. When all call sites use constants, this can become a distinct type (type ServiceID string) and function signatures can be updated for full type safety.

const (
	ServiceRunner ServiceID = "dev.miren.runtime/runner"
)

Runtime service identifiers. Add new services here to maintain type safety and avoid string typos.

type State

type State struct {
	*StateCommon
	// contains filtered or unexported fields
}

func NewState

func NewState(ctx context.Context, opts ...StateOption) (*State, error)

func (*State) Client

func (s *State) Client(name string) (*NetworkClient, error)

func (*State) Close

func (s *State) Close() error

func (*State) Connect

func (s *State) Connect(remote string, name string) (*NetworkClient, error)

func (*State) ListenAddr

func (s *State) ListenAddr() string

func (*State) LoopbackAddr

func (s *State) LoopbackAddr() string

func (*State) Server

func (s *State) Server() *Server

type StateCommon

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

type StateOption

type StateOption func(*stateOptions)

func WithAuthenticator

func WithAuthenticator(auth Authenticator) StateOption

func WithAuthorizer added in v0.3.1

func WithAuthorizer(authz Authorizer) StateOption

func WithBearerToken

func WithBearerToken(token string) StateOption

func WithBindAddr

func WithBindAddr(addr string) StateOption

func WithCert

func WithCert(certPath, keyPath string) StateOption

func WithCertPEMs

func WithCertPEMs(certData, keyData []byte) StateOption

func WithCertificateVerification

func WithCertificateVerification(caCert []byte) StateOption

func WithEndpoint

func WithEndpoint(endpoint string) StateOption

func WithLocalConnect

func WithLocalConnect(addr string) StateOption

func WithLocalServer

func WithLocalServer(addr string) StateOption

func WithLogLevel

func WithLogLevel(level slog.Level) StateOption

func WithLogger

func WithLogger(log *slog.Logger) StateOption

type UnionField

type UnionField struct {
	Name    string `yaml:"name"`
	Index   int    `yaml:"index"`
	Type    string `yaml:"type"`
	Element string `yaml:"element,omitempty"`
}

Directories

Path Synopsis
cmd
rpcgen command

Jump to

Keyboard shortcuts

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