node

package
v0.1.0-alpha.9 Latest Latest
Warning

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

Go to latest
Published: Sep 7, 2026 License: Apache-2.0 Imports: 85 Imported by: 0

Documentation

Index

Constants

View Source
const (
	// Cache sizes
	RateLimiterSize       = 1000
	RevocationCacheSize   = 10000
	VerificationCacheSize = 1000

	// Freshness checks
	FreshnessThreshold = 5 * time.Minute

	// Key pruning
	KeyPruningInterval = 1 * time.Hour

	// Reprovide interval
	ReprovideInterval = 5 * time.Minute
)
View Source
const (
	DefaultMeshName             = "public-mesh"
	DefaultDiscoveryInterval    = "30s"
	DefaultConfigFile           = "sam-node.yaml"
	DefaultRouterConnectTimeout = 5 * time.Second
	// DefaultSocketName is the local API socket the node creates in its data directory.
	DefaultSocketName = "sam.sock"
)
View Source
const (
	// Rate limiting defaults for peers
	PeerRateLimit = 5
	PeerBurst     = 10
)
View Source
const PeerstoreKeyPrivateIPFailed = "private_ip_failed"

PeerstoreKeyPrivateIPFailed is the key used in the libp2p Peerstore to track if a peer's private IP was previously found to be unreachable or slower than a relay. This allows the node to "try once and remember", avoiding a 15-second timeout on subsequent discovery or tool calls when dialing unroutable private networks.

View Source
const (
	// StoreFile is the node database inside the data directory.
	StoreFile = "agent.db"
)

Variables

View Source
var (
	// Renewal timing defaults
	DefaultRenewalFallback = (api.BiscuitTokenTTL * 8) / 10 // 80% of TTL (19.2h)
	RenewalBuffer          = api.BiscuitTokenTTL / 5        // 20% of TTL (4.8h)
	RenewalThreshold       = api.BiscuitTokenTTL / 4        // 25% of TTL (6h)
)
View Source
var ErrAuthRejected = errors.New("auth rejected")

ErrAuthRejected marks a service-level authorization denial from a remote peer, as opposed to a transport/connectivity failure. Callers use errors.Is to tell "you're not allowed" apart from "the service is unreachable" so that discovery (find_remote_tools) can hide forbidden services instead of leaking their names.

View Source
var ErrFatalAuth = errors.New("fatal authentication error")
View Source
var ErrStoreLocked = errors.New("another sam-node instance is using this data directory")

ErrStoreLocked reports that another process already holds the data directory, which for a node data directory means a node is running.

Functions

func BuildPolicyRules

func BuildPolicyRules(roles []*api.PolicyRole, bindings []*api.PolicyBinding) []biscuit.Rule

func FetchControlPlaneInfo

func FetchControlPlaneInfo(ctx context.Context, controlPlaneURL string) (*api.ControlPlaneInfoResponse, error)

FetchControlPlaneInfo retrieves the latest configuration from the control plane's /info endpoint.

func FetchControlPlaneKeys

func FetchControlPlaneKeys(ctx context.Context, controlPlaneURL string) ([]ed25519.PublicKey, error)

FetchControlPlaneKeys retrieves the full set of currently valid control plane public keys from the /keys endpoint — the same catch-up path routers use. Enrollment only hands out the newest key, so this is how a node learns keys still in their rotation grace period, or rotations it missed while offline.

func FetchMeshPolicy

func FetchMeshPolicy(ctx context.Context, controlPlaneURL string, biscuitToken []byte) (*api.PolicyConfigGetResponse, error)

FetchMeshPolicy retrieves the latest mesh policy from the control plane's /policies endpoint using a biscuit token.

func GetDefaultDataDir

func GetDefaultDataDir() (string, error)

func GetOrGenerateKey

func GetOrGenerateKey(s *Store) crypto.PrivKey

GetOrGenerateKey retrieves a persistent private key or creates one if it's the first run

func GetRecentLogs

func GetRecentLogs() []string

GetRecentLogs returns the most recent log lines.

func NewMCPHandler

func NewMCPHandler(node *SamNode) http.Handler

NewMCPHandler creates a new HTTP handler for the MCP server using the official SDK.

func NewMCPServer

func NewMCPServer(node *SamNode) *mcp.Server

NewMCPServer creates a new MCP server instance with all tools registered.

func NewUnauthenticatedMCPHandler

func NewUnauthenticatedMCPHandler(controlPlaneURL string) http.Handler

NewUnauthenticatedMCPHandler creates an HTTP handler for the unauthenticated MCP server.

func NewUnauthenticatedMCPServer

func NewUnauthenticatedMCPServer(controlPlaneURL string) *mcp.Server

NewUnauthenticatedMCPServer creates a minimal MCP server that instructs the client on how to authenticate.

func StartSidecarServer

func StartSidecarServer(node *SamNode, addr, socketPath, token, certFile, keyFile, caFile string) (*http.Server, error)

StartSidecarServer serves the node's local API on a TCP address, on a Unix socket, or on both. An empty addr disables the TCP listener; an empty socketPath disables the socket.

func StartUnauthSidecarServer

func StartUnauthSidecarServer(controlPlaneURL, addr, socketPath, certFile, keyFile string) (*http.Server, error)

StartUnauthSidecarServer serves the enrollment-only API of a node that has no identity yet, on a TCP address, on a Unix socket, or on both.

func SyncMeshConfig

func SyncMeshConfig(ctx context.Context, s *Store) ([]byte, []multiaddr.Multiaddr, []string, error)

SyncMeshConfig loads the mesh configuration from the store, attempts to refresh it via HTTP from the control plane, and updates the store if successful. It returns the control plane public key, the latest multiaddresses, and the control plane's current ban set.

The ban set is deliberately not persisted. MeshEvent_BANNED is published once and gossip has no replay, so a node that restarted or was offline has to be told again; /info is that catch-up, and reading it fresh each start is also what makes an unban take effect. Nil means the control plane was not reached, which is not the same as "nothing is banned": callers must not treat it as an instruction to clear anything.

Types

type A2AService

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

A2AService proxies Agent2Agent (A2A) JSON-RPC/REST traffic to a local agent process. URL backends only: a command backend would wire the A2A route to an MCP stdio bridge no A2A client can talk to.

func (*A2AService) Handler

func (b *A2AService) Handler() http.Handler

func (*A2AService) Info

func (b *A2AService) Info() *api.ServiceInfo

func (*A2AService) Init

func (s *A2AService) Init(ctx context.Context) error

func (*A2AService) Probe

func (s *A2AService) Probe(ctx context.Context) error

Probe asks the backend for its agent card, which is the protocol's own definition of ready: an A2A agent is up exactly when it serves its card. Gating advertisement on it lets a service be declared before its agent is (a sandbox that has not bound its port yet probes as down and stays out of discovery). Deliberately not cached, like the MCP probe.

func (*A2AService) Teardown

func (b *A2AService) Teardown() error

Teardown kills the child process if any. Safe to call when cmd is nil or already dead.

type AuthMode

type AuthMode string

AuthMode selects how interactive enrollment authenticates the user.

const (
	// AuthModeAuto prefers device flow in headless environments (when the
	// provider advertises one) and the loopback browser flow otherwise, with an
	// automatic device fallback when the browser can't be opened.
	AuthModeAuto AuthMode = "auto"
	// AuthModeDevice forces the OAuth 2.0 Device Authorization Grant (RFC 8628).
	AuthModeDevice AuthMode = "device"
	// AuthModeOOB forces the out-of-band code-paste flow.
	AuthModeOOB AuthMode = "oob"
	// AuthModeBrowser forces the loopback browser (authorization code) flow.
	AuthModeBrowser AuthMode = "browser"
)

func ParseAuthMode

func ParseAuthMode(s string) (AuthMode, error)

ParseAuthMode validates a user-provided --auth-mode value. An empty string maps to AuthModeAuto.

type CallRemoteToolParams

type CallRemoteToolParams struct {
	PeerID         string         `json:"peer_id" jsonschema:"The Peer ID of the target agent"`
	ToolName       string         `json:"tool_name" jsonschema:"The name of the server to call"`
	Arguments      map[string]any `` /* 177-byte string literal not displayed */
	RequiredLabels string         `` /* 222-byte string literal not displayed */
}

CallRemoteToolParams defines the parameters for the call_remote_tool tool.

Arguments is a JSON object whose shape matches the target server's input_schema (use describe_remote_tool to fetch it). Earlier revisions took a stringified JSON blob here; that footgun is gone.

type DescribeRemoteToolParams

type DescribeRemoteToolParams struct {
	PeerID   string `json:"peer_id" jsonschema:"Peer ID of the node hosting the server. Required."`
	ToolName string `` /* 135-byte string literal not displayed */
}

DescribeRemoteToolParams defines parameters for the describe_remote_tool sidecar tool.

type DiscoverRemoteServicesParams

type DiscoverRemoteServicesParams struct {
	Type   string `json:"type" jsonschema:"Service type (mcp, inference, a2a)"`
	Name   string `json:"name,omitempty" jsonschema:"Optional service name. Omit to list all services of the given type."`
	Limit  int    `json:"limit,omitempty" jsonschema:"Optional limit for pagination. Defaults to 20."`
	Offset int    `json:"offset,omitempty" jsonschema:"Optional offset for pagination. Defaults to 0."`
}

DiscoverRemoteServicesParams defines the parameters for the discover_remote_services tool.

type FindRemoteToolsParams

type FindRemoteToolsParams struct {
	Intent      string `` /* 170-byte string literal not displayed */
	PeerID      string `json:"peer_id,omitempty" jsonschema:"Restrict the search to a single peer. Empty means search the whole mesh."`
	ServiceName string `` /* 166-byte string literal not displayed */
	ToolName    string `` /* 223-byte string literal not displayed */
}

FindRemoteToolsParams defines the parameters for the find_remote_tools tool.

type GetMeshInfoParams

type GetMeshInfoParams struct{}

GetMeshInfoParams defines the parameters for the get_mesh_info tool.

type InferenceEngine

type InferenceEngine interface {
	// Models returns the model IDs the backend currently serves.
	Models(ctx context.Context) ([]string, error)
}

InferenceEngine is the connector between SAM and an inference backend. Implementations adapt one backend family; the service and facade layers stay backend-agnostic.

type InferenceService

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

InferenceService provides intelligent LLM gateway features: traffic routing and token usage tracking for OpenAI-compatible endpoints.

func (*InferenceService) ActiveRequests

func (s *InferenceService) ActiveRequests() uint32

ActiveRequests reports in-flight requests, a load hint for announcements.

func (*InferenceService) Handler

func (b *InferenceService) Handler() http.Handler

func (*InferenceService) Info

func (b *InferenceService) Info() *api.ServiceInfo

func (*InferenceService) Init

func (s *InferenceService) Init(ctx context.Context) error

func (*InferenceService) Models

func (s *InferenceService) Models(ctx context.Context) ([]string, error)

Models returns the model IDs the backend serves, cached briefly since both the discovery announcer and the OpenAI facade call it repeatedly.

func (*InferenceService) Teardown

func (b *InferenceService) Teardown() error

Teardown kills the child process if any. Safe to call when cmd is nil or already dead.

type ListLocalServicesParams

type ListLocalServicesParams struct {
	Type string `json:"type,omitempty" jsonschema:"Optional service type filter (mcp, inference, a2a). Empty means all types."`
}

ListLocalServicesParams defines the parameters for the list_local_services tool.

type MCPService

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

MCPService extends baseService to handle MCP protocol proxying.

func (*MCPService) HandleStreamPassThrough

func (m *MCPService) HandleStreamPassThrough(s network.Stream)

HandleStreamPassThrough connects to the backend and proxies JSON-RPC messages.

func (*MCPService) Handler

func (b *MCPService) Handler() http.Handler

func (*MCPService) Info

func (b *MCPService) Info() *api.ServiceInfo

func (*MCPService) Init

func (m *MCPService) Init(ctx context.Context) error

Init initializes the base service.

func (*MCPService) Probe

func (m *MCPService) Probe(ctx context.Context) error

Probe reports whether the backend actually speaks MCP, by completing an initialize against it.

Deliberately weaker than Tools: a backend serving only resources or prompts has no tools and is still a working MCP server, so an empty tool list is no reason to withhold it. Failing to initialize is — that is a backend which is down, or was never an MCP server to begin with.

The result is deliberately not cached. Callers are the registry's advertise path, which asks once per service per reprovide, so the cost is negligible; caching would make a backend that has just come up wait out the TTL, which is the delay this gating exists to avoid.

func (*MCPService) Teardown

func (m *MCPService) Teardown() error

Teardown chains to baseService.Teardown.

func (*MCPService) Tools

func (m *MCPService) Tools(ctx context.Context) ([]string, error)

Tools lists the backend's tool names (sorted), cached briefly since the discovery announcer polls it on every tick.

type MeshPubsubBroadcastParams

type MeshPubsubBroadcastParams struct {
	Topic   string `json:"topic" jsonschema:"GossipSub topic name"`
	Payload string `json:"payload" jsonschema:"Payload to publish"`
}

MeshPubsubBroadcastParams defines the parameters for the mesh_pubsub_broadcast tool.

type NodeConfigComplete

type NodeConfigComplete struct {
	Policies []biscuit.Policy
	Checks   []biscuit.Check
	Rules    []biscuit.Rule
	Services []api.ServiceConfig
}

func LoadNodeConfig

func LoadNodeConfig(path string) (*NodeConfigComplete, error)

LoadNodeConfig loads the node configuration from the specified path. If the file is missing, it returns an empty initialized config.

type OIDCEndpoints

type OIDCEndpoints struct {
	TokenURL      string
	AuthURL       string
	DeviceAuthURL string
}

OIDCEndpoints contains discovered OIDC endpoint URLs.

type Options

type Options struct {
	PrivKey            crypto.PrivKey
	ControlPlanePubKey ed25519.PublicKey
	RouterAddrs        []multiaddr.Multiaddr
	Store              *Store

	// BannedPeerIDs seeds the revocation cache from the control plane's ban
	// set (see SyncMeshConfig). Without it a restarted node would enforce no
	// ban until the next MeshEvent_BANNED, which for an existing ban never
	// comes.
	BannedPeerIDs     []string
	MeshID            string
	DiscoveryInterval string
	ListenAddrs       []string
	EnableRelay       bool
	NodeConfig        *NodeConfigComplete
	KeyGracePeriod    time.Duration
	AllowLoopback     bool
	// AnnouncePrivateAddrs controls whether RFC1918/ULA addresses are published
	// to the mesh. Nil means true: private meshes reach each other over exactly
	// those addresses. Set false on nodes that are only reachable via routers or
	// public addresses, so peers do not learn the host's internal topology.
	AnnouncePrivateAddrs *bool
	MonitorBootstrap     time.Duration
	MonitorInterval      time.Duration
	AutoRelayMinInterval time.Duration
	AutoRelayBootDelay   time.Duration
	AutoRelayBackoff     time.Duration
	// RouterConnectTimeout bounds each router address's dial (connect + stream open).
	RouterConnectTimeout time.Duration
	// BiscuitTimeout bounds Datalog evaluation when verifying biscuit tokens.
	BiscuitTimeout time.Duration
	// DHT Options
	DHTProviderAddrTTL   time.Duration
	DHTMaxRecordAge      time.Duration
	DHTLookupLimit       int
	DiscoveryConcurrency int
	// RequiredRole restricts enrollment and startup to only accept tokens containing this role.
	RequiredRole string
	// Labels are operator-declared key=value claims for this node (e.g.
	// {"region": "us-east-1"}, see api/labels.go). Empty means no claims;
	// consumers with a label requirement will not select this node.
	Labels map[string]string
	// PolicySyncInterval specifies how often the node syncs the mesh policy from the control plane.
	PolicySyncInterval time.Duration
	// PolicySyncJitter specifies the maximum jitter delay when scheduling policy syncs on event broadcasts.
	PolicySyncJitter time.Duration
}

Options holds all configuration options for a SamNode.

func (*Options) Default

func (o *Options) Default()

Default applies default values to Options if they are not specified.

func (*Options) Validate

func (o *Options) Validate() error

Validate verifies that the required options are provided and valid.

type PeerRateLimiter

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

PeerRateLimiter tracks rate limits per peer using an LRU cache.

func NewPeerRateLimiter

func NewPeerRateLimiter(size int) (*PeerRateLimiter, error)

NewPeerRateLimiter creates a new PeerRateLimiter with specified cache size.

func (*PeerRateLimiter) Allow

func (prl *PeerRateLimiter) Allow(peerID string) bool

Allow checks if the peer is allowed to perform an action.

type PollMessagesParams

type PollMessagesParams struct {
	Topic string `json:"topic" jsonschema:"GossipSub topic name"`
}

PollMessagesParams defines the parameters for the poll_messages tool.

type RefreshError

type RefreshError struct {
	StatusCode int
	Message    string
}

func (*RefreshError) Error

func (e *RefreshError) Error() string

type RequestContext

type RequestContext struct {
	PeerID   peer.ID
	User     string
	Group    string
	Protocol string
	Target   string

	// Agent is the principal the calling node says the request is for, and it
	// is exactly that: the calling node's word. It arrives beside the token
	// rather than inside it, because Biscuit deliberately hides an appended
	// block's facts from the authorizer (see internal/identity's
	// TestAttenuationBlockFactsAreInvisibleToTheAuthorizer). Nothing is lost by
	// that: whoever can append a block can append any block, so a claim in a
	// block would be worth no more than a claim in a header on the same
	// authenticated connection.
	//
	// So it is attribution, not proof. Policy that cares should also constrain
	// which peers may speak for which agent namespaces.
	Agent string
}

RequestContext carries the security metadata for a specific stream request

type RingBufferSink

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

RingBufferSink implements zap.Sink to capture logs in memory.

func (*RingBufferSink) Close

func (s *RingBufferSink) Close() error

Close implements zap.Sink

func (*RingBufferSink) Sync

func (s *RingBufferSink) Sync() error

Sync implements zap.Sink

func (*RingBufferSink) Write

func (s *RingBufferSink) Write(p []byte) (n int, err error)

Write implements io.Writer

type SamNode

type SamNode struct {
	Host         host.Host
	DHT          *dht.IpfsDHT
	PubSub       *pubsub.PubSub
	Discovery    *samdiscovery.Discovery
	Store        *Store
	RouterPeerID peer.ID

	LocalPolicy *NodeConfigComplete

	MeshPolicyRules []biscuit.Rule
	MeshPolicyMu    sync.RWMutex

	BoundHTTPAddr   string
	BoundSocketPath string
	AllowLoopback   bool

	BiscuitTimeout time.Duration
	// contains filtered or unexported fields
}

func NewSamNode

func NewSamNode(cfg Options) (*SamNode, error)

NewSamNode creates a new Agent instance secured with the 4-layer pipeline. NewSamNode initializes options and structures without starting background tasks or network interfaces.

func (*SamNode) Authorize

func (n *SamNode) Authorize(rawToken []byte, req RequestContext, pubKey ed25519.PublicKey) error

func (*SamNode) CallMCPTool

func (n *SamNode) CallMCPTool(ctx context.Context, targetPeer peer.ID, toolName string, params any, requiredLabels map[string]string) (*mcp.CallToolResult, error)

CallMCPTool opens a stream to a remote peer, performs the handshake, and calls a tool. CallMCPTool opens a stream to a remote peer, performs the handshake, and calls a tool. requiredLabels, when non-empty, fail-closed verifies the peer's control-plane-attested labels (see checkPeerLabels) before the tool is invoked; nil means no requirement.

func (*SamNode) ConnectAndAuthWithRouter

func (n *SamNode) ConnectAndAuthWithRouter(ctx context.Context, addr multiaddr.Multiaddr) error

func (*SamNode) ConnectMCPSession

func (n *SamNode) ConnectMCPSession(ctx context.Context, targetPeer peer.ID, targetService string, requiredLabels map[string]string) (*mcp.ClientSession, func(), error)

func (*SamNode) DeviceLogin

func (n *SamNode) DeviceLogin(ctx context.Context, deviceAuthURL, tokenURL, clientID, audience string, requestRefresh bool) (string, error)

DeviceLogin performs OAuth 2.0 Device Authorization Grant (RFC 8628).

func (*SamNode) DiscoverEndpoints

func (n *SamNode) DiscoverEndpoints(ctx context.Context, issuerURL string) (tokenURL, authURL string, err error)

DiscoverEndpoints discovers both token and authorization endpoints.

func (*SamNode) DiscoverEndpointsWithDevice

func (n *SamNode) DiscoverEndpointsWithDevice(ctx context.Context, issuerURL string) (*OIDCEndpoints, error)

DiscoverEndpointsWithDevice discovers token, authorization and device authorization endpoints.

func (*SamNode) DiscoverRemoteServices

func (n *SamNode) DiscoverRemoteServices(ctx context.Context, serviceType api.ServiceType, serviceName string) ([]*api.DiscoveredProvider, error)

DiscoverRemoteServices dispatches to the named or type-only path based on whether serviceName is provided.

func (*SamNode) DiscoverRemoteServicesStream

func (n *SamNode) DiscoverRemoteServicesStream(ctx context.Context, serviceType api.ServiceType, serviceName string) (<-chan *api.DiscoveredProvider, error)

DiscoverRemoteServicesStream performs service discovery and streams results down the returned channel. The channel is closed automatically when discovery completes or the context is cancelled.

func (*SamNode) DiscoverTokenURL

func (n *SamNode) DiscoverTokenURL(ctx context.Context, issuerURL string) (string, error)

DiscoverTokenURL discovers the token URL from the OIDC issuer.

func (*SamNode) Enroll

func (n *SamNode) Enroll(ctx context.Context, controlPlaneURL string, jwt string) error

func (*SamNode) EnrollBootstrap

func (n *SamNode) EnrollBootstrap(ctx context.Context, controlPlaneURL string, bootstrapToken string) error

EnrollBootstrap enrolls the node with the control plane using a pre-shared bootstrap token. If the enrollment status is PENDING, it polls the status endpoint until approved or rejected.

func (*SamNode) FetchJWT

func (n *SamNode) FetchJWT(ctx context.Context, tokenURL, clientID, clientSecret string) (string, error)

FetchJWT fetches a JWT token using the Client Credentials flow.

func (*SamNode) FindProvidersByName

func (n *SamNode) FindProvidersByName(ctx context.Context, serviceType api.ServiceType, serviceName string) ([]peer.AddrInfo, error)

FindProvidersByName returns peers hosting a specific {type, name} service.

func (*SamNode) FindProvidersByType

func (n *SamNode) FindProvidersByType(ctx context.Context, serviceType api.ServiceType) ([]peer.AddrInfo, error)

FindProvidersByType returns peers hosting at least one service of the given type.

func (*SamNode) GetIdentity

func (n *SamNode) GetIdentity() []byte

GetIdentity returns the node's biscuit identity, caching it in memory.

func (*SamNode) HandleAuthHandshake

func (n *SamNode) HandleAuthHandshake(s network.Stream)

HandleAuthHandshake is the core libp2p stream handler for /sam/auth/1.0.0. This is the "Admission Office" of the mesh node.

func (*SamNode) HandleMCPStream

func (n *SamNode) HandleMCPStream(s network.Stream, reqCtx RequestContext)

HandleMCPStream is the libp2p stream handler for the MCP protocol. It routes the authenticated stream to the appropriate backend service, or serves the internal MCP catalog if the TargetService is empty/catalog.

func (*SamNode) InteractiveLogin

func (n *SamNode) InteractiveLogin(ctx context.Context, authURL, tokenURL, clientID, audience string, requestRefresh bool, headless bool) (string, error)

InteractiveLogin prompts the user to go to a URL and enter a code.

func (*SamNode) InteractiveLoginWithDeviceAuth

func (n *SamNode) InteractiveLoginWithDeviceAuth(ctx context.Context, authURL, tokenURL, deviceAuthURL, clientID, audience string, requestRefresh bool, headless bool) (string, error)

InteractiveLoginWithDeviceAuth authenticates using AuthModeAuto: it prefers the OAuth Device Authorization Grant in headless mode when the provider exposes a device authorization endpoint, and otherwise uses the loopback browser flow with a device fallback.

func (*SamNode) InteractiveLoginWithMode

func (n *SamNode) InteractiveLoginWithMode(ctx context.Context, authURL, tokenURL, deviceAuthURL, clientID, audience string, requestRefresh bool, headless bool, mode AuthMode) (string, error)

InteractiveLoginWithMode authenticates the user using an explicit AuthMode, letting callers (e.g. CUJ harnesses) force a deterministic flow instead of relying on headless environment detection.

func (*SamNode) IsConnected

func (n *SamNode) IsConnected() bool

func (*SamNode) IsServiceRegistered

func (n *SamNode) IsServiceRegistered(serviceName string) bool

func (*SamNode) ListLocalServices

func (n *SamNode) ListLocalServices(typeFilter api.ServiceType) []*api.ServiceInfo

ListLocalServices returns services registered on this node. If typeFilter is SERVICE_TYPE_UNSPECIFIED, all services are returned.

func (*SamNode) LoadControlPlaneURL

func (n *SamNode) LoadControlPlaneURL() (string, error)

func (*SamNode) LoadMeshConfig

func (n *SamNode) LoadMeshConfig() ([]byte, []string, error)

func (*SamNode) RefreshEnrollment

func (n *SamNode) RefreshEnrollment(ctx context.Context) error

RefreshEnrollment trades the expiring biscuit token for a new one using a cryptographic challenge.

func (*SamNode) RefreshJWT

func (n *SamNode) RefreshJWT(ctx context.Context, tokenURL, clientID, clientSecret, refreshToken string) (string, string, error)

RefreshJWT refreshes the OIDC token using the stored refresh token.

func (*SamNode) RegisterService

func (n *SamNode) RegisterService(ctx context.Context, req *api.RegisterServiceRequest) error

func (*SamNode) RegisterStaticServices

func (n *SamNode) RegisterStaticServices(ctx context.Context, services []api.ServiceConfig) error

func (*SamNode) SaveMeshConfig

func (n *SamNode) SaveMeshConfig(pubKey []byte, addrs []string) error

func (*SamNode) SetIdentityCache

func (n *SamNode) SetIdentityCache(b []byte)

SetIdentityCache explicitly updates the cached identity.

func (*SamNode) Start

func (n *SamNode) Start(ctx context.Context) error

Start initializes the libp2p host, DHT, connects to the routers, and starts runtime components.

func (*SamNode) StartIngressServer

func (n *SamNode) StartIngressServer(ctx context.Context) error

func (*SamNode) StartRenewalLoop

func (n *SamNode) StartRenewalLoop(ctx context.Context, issuerURL, clientID, clientSecret, jwtPath string)

func (*SamNode) Teardown

func (n *SamNode) Teardown() error

Teardown detaches all registered services and closes the libp2p host. Store is owned by the caller and is not closed here.

func (*SamNode) UnregisterService

func (n *SamNode) UnregisterService(ctx context.Context, serviceName string) error

func (*SamNode) UpdateRelays

func (n *SamNode) UpdateRelays(addrs []multiaddr.Multiaddr)

UpdateRelays updates the current relays used by AutoRelay.

func (*SamNode) VerifyBiscuitToken

func (n *SamNode) VerifyBiscuitToken(biscuitBytes []byte, reqCtx RequestContext) error

VerifyBiscuitToken checks revocation, cache, and evaluates the token against trusted keys and local policies.

func (*SamNode) VerifyPeerLabels

func (n *SamNode) VerifyPeerLabels(ctx context.Context, peerID peer.ID, required map[string]string) error

VerifyPeerLabels ensures the peer holds control-plane-attested labels satisfying any of the required key=value pairs (canonical, pre-validated). A nil/empty requirement passes without network traffic. Positive verdicts are cached.

func (*SamNode) WithBiscuitAuth

func (n *SamNode) WithBiscuitAuth(next func(network.Stream, RequestContext)) network.StreamHandler

WithBiscuitAuth enforces a Protobuf handshake on a stream before calling the next handler.

type Service

type Service interface {
	Info() *api.ServiceInfo
	Init(ctx context.Context) error
	Handler() http.Handler
	Teardown() error
}

Service is the contract the ServiceRegistry and ingress server use. Implementations own all type-specific behaviour; the registry stays type-agnostic.

func NewServiceFromRequest

func NewServiceFromRequest(req *api.RegisterServiceRequest) (Service, error)

type ServiceRegistry

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

ServiceRegistry is the type-agnostic owner of registered services.

func NewServiceRegistry

func NewServiceRegistry(d dhtProvider) *ServiceRegistry

func (*ServiceRegistry) Get

func (r *ServiceRegistry) Get(name string) (Service, bool)

Get returns the service registered under name, if any.

func (*ServiceRegistry) List

func (r *ServiceRegistry) List(typeFilter api.ServiceType) []*api.ServiceInfo

List returns the ServiceInfo for every registered service, optionally filtered by type. SERVICE_TYPE_UNSPECIFIED means "all types."

func (*ServiceRegistry) Register

func (r *ServiceRegistry) Register(ctx context.Context, svc Service) error

Register initialises a service, advertises it on the DHT, and inserts it into the map. Init runs before Provide so a failed handler-build never briefly advertises an unservable name.

A backend that does not answer is registered but not advertised, rather than rejected: backends routinely start after the node does, and the reprovide loop picks them up once they answer.

func (*ServiceRegistry) ReprovideAll

func (r *ServiceRegistry) ReprovideAll(ctx context.Context) int

ReprovideAll re-provides all registered services to the DHT concurrently and reports how many were withheld because their backend did not answer. A service whose backend has stopped answering falls out of the DHT by not being reprovided, and returns on a later tick once it answers again.

func (*ServiceRegistry) TeardownAll

func (r *ServiceRegistry) TeardownAll()

TeardownAll calls Teardown on every registered service and clears the map. Per-service errors are logged; iteration continues.

func (*ServiceRegistry) Unregister

func (r *ServiceRegistry) Unregister(ctx context.Context, name string) error

Unregister removes the service from the map and calls Teardown. Unknown names are a no-op.

type StdioBridge

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

func (*StdioBridge) Send

func (b *StdioBridge) Send(data []byte) error

Send writes data to the child's stdin, appending a newline.

func (*StdioBridge) ServeHTTP

func (b *StdioBridge) ServeHTTP(w http.ResponseWriter, r *http.Request)

func (*StdioBridge) Start

func (b *StdioBridge) Start()

func (*StdioBridge) Subscribe

func (b *StdioBridge) Subscribe() (<-chan string, func())

Subscribe registers a new subscriber channel for stdout lines and returns it along with an idempotent unsubscribe function. Buffered (cap 10); drops on slow consumers match the SSE behaviour in ServeHTTP.

type Store

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

func NewStore

func NewStore(dir string) (*Store, error)

func (*Store) Close

func (s *Store) Close() error

func (*Store) LoadControlPlaneURL

func (s *Store) LoadControlPlaneURL() (string, error)

func (*Store) LoadIdentity

func (s *Store) LoadIdentity() ([]byte, error)

func (*Store) LoadIdentityExpiration

func (s *Store) LoadIdentityExpiration() (int64, error)

func (*Store) LoadKey

func (s *Store) LoadKey() ([]byte, error)

func (*Store) LoadMeshConfig

func (s *Store) LoadMeshConfig() ([]byte, []string, error)

func (*Store) LoadOIDCConfig

func (s *Store) LoadOIDCConfig() (string, string, string, error)

func (*Store) LoadRefreshToken

func (s *Store) LoadRefreshToken() (string, error)

func (*Store) LoadTrustedKeys

func (s *Store) LoadTrustedKeys() ([]TrustedKey, error)

func (*Store) ResetMeshIdentity

func (s *Store) ResetMeshIdentity() error

ResetMeshIdentity clears everything about a node's mesh membership (its Biscuit, mesh/control-plane config, and OIDC session state) so it can join a different mesh. It keeps the long-lived libp2p key (node_private_key), so the node's PeerID survives the switch.

func (*Store) SaveControlPlaneURL

func (s *Store) SaveControlPlaneURL(url string) error

func (*Store) SaveIdentity

func (s *Store) SaveIdentity(biscuit []byte) error

func (*Store) SaveIdentityExpiration

func (s *Store) SaveIdentityExpiration(exp int64) error

func (*Store) SaveKey

func (s *Store) SaveKey(key []byte) error

func (*Store) SaveMeshConfig

func (s *Store) SaveMeshConfig(pubKey []byte, addrs []string) error

func (*Store) SaveOIDCConfig

func (s *Store) SaveOIDCConfig(issuer, clientID, audience string) error

func (*Store) SaveRefreshToken

func (s *Store) SaveRefreshToken(token string) error

func (*Store) SaveTrustedKeys

func (s *Store) SaveTrustedKeys(keys []TrustedKey) error

SaveTrustedKeys persists the full set of control plane public keys the node currently trusts, so keys learned from rotation events or /keys survive restarts (the singular mesh-config key only tracks enrollment).

type StreamTransport

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

StreamTransport implements the mcp.Transport interface for a libp2p stream.

func NewStreamTransport

func NewStreamTransport(s network.Stream) *StreamTransport

NewStreamTransport creates a new StreamTransport for the given stream.

func (*StreamTransport) Close

func (t *StreamTransport) Close() error

Close closes the stream.

func (*StreamTransport) Connect

func (t *StreamTransport) Connect(ctx context.Context) (mcp.Connection, error)

Connect satisfies the mcp.Transport interface. For a stream, it's already connected.

func (*StreamTransport) Read

Read reads a message from the stream.

func (*StreamTransport) Send

func (t *StreamTransport) Send(data []byte) error

Send sends a message over the stream.

func (*StreamTransport) SessionID

func (t *StreamTransport) SessionID() string

SessionID satisfies the mcp.Connection interface.

func (*StreamTransport) Write

func (t *StreamTransport) Write(ctx context.Context, msg jsonrpc.Message) error

Write writes a message to the stream.

type SubscribeTopicParams

type SubscribeTopicParams struct {
	Topic string `json:"topic" jsonschema:"GossipSub topic name"`
}

SubscribeTopicParams defines the parameters for the subscribe_topic tool.

type TrustedKey

type TrustedKey struct {
	Key        ed25519.PublicKey
	ReceivedAt time.Time
}

Directories

Path Synopsis
Package discovery provides interest-scoped service announcements over GossipSub.
Package discovery provides interest-scoped service announcements over GossipSub.

Jump to

Keyboard shortcuts

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