api

package
v0.1.0 Latest Latest
Warning

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

Go to latest
Published: Jul 18, 2026 License: Apache-2.0 Imports: 21 Imported by: 0

Documentation

Index

Constants

View Source
const (
	EventPeerAdded                = "peer_added"
	EventPeerRemoved              = "peer_removed"
	EventPeerKeyRotated           = "peer_key_rotated"
	EventPeerEndpointChanged      = "peer_endpoint_changed"
	EventPolicyUpdated            = "policy_updated"
	EventActionRequest            = "action_request"
	EventSessionRevoked           = "session_revoked"
	EventSSHSessionSetup          = "ssh_session_setup"
	EventRotateKeys               = "rotate_keys"
	EventSigningKeyRotated        = "signing_key_rotated"
	EventNodeStateUpdated         = "node_state_updated"
	EventNodeSecretsUpdated       = "node_secrets_updated"
	EventBridgeConfigUpdated      = "bridge_config_updated"
	EventRelaySessionAssigned     = "relay_session_assigned"
	EventRelaySessionRevoked      = "relay_session_revoked"
	EventUserAccessConfigUpdated  = "user_access_config_updated"
	EventUserAccessPeerAssigned   = "user_access_peer_assigned"
	EventUserAccessPeerRevoked    = "user_access_peer_revoked"
	EventIngressConfigUpdated     = "ingress_config_updated"
	EventIngressRuleAssigned      = "ingress_rule_assigned"
	EventIngressRuleRevoked       = "ingress_rule_revoked"
	EventSiteToSiteConfigUpdated  = "site_to_site_config_updated"
	EventSiteToSiteTunnelAssigned = "site_to_site_tunnel_assigned"
	EventSiteToSiteTunnelRevoked  = "site_to_site_tunnel_revoked"
)
View Source
const DefaultConnectTimeout = 10 * time.Second

DefaultConnectTimeout is the default TCP connect timeout.

View Source
const DefaultRequestTimeout = 30 * time.Second

DefaultRequestTimeout is the default HTTP request timeout.

View Source
const DefaultSSEIdleTimeout = 90 * time.Second

DefaultSSEIdleTimeout is the default SSE idle timeout.

View Source
const DefaultStalenessWindow = 5 * time.Minute

DefaultStalenessWindow is the maximum age of an event before it is considered stale.

Variables

View Source
var (
	ErrBadRequest      = &APIError{StatusCode: 400, Message: "bad request"}
	ErrUnauthorized    = &APIError{StatusCode: 401, Message: "unauthorized"}
	ErrForbidden       = &APIError{StatusCode: 403, Message: "forbidden"}
	ErrNotFound        = &APIError{StatusCode: 404, Message: "not found"}
	ErrConflict        = &APIError{StatusCode: 409, Message: "conflict"}
	ErrPayloadTooLarge = &APIError{StatusCode: 413, Message: "payload too large"}
	ErrRateLimit       = &APIError{StatusCode: 429, Message: "rate limit exceeded"}
	ErrServer          = &APIError{StatusCode: 500, Message: "server error"}
)

Sentinel errors for common HTTP error status codes.

View Source
var ErrSSEIdleTimeout = errors.New("api: SSE idle timeout")

ErrSSEIdleTimeout is returned when the SSE stream receives no data within the configured idle timeout period.

Functions

This section is empty.

Types

type APIError

type APIError struct {
	StatusCode int
	Message    string
	RetryAfter time.Duration // only set for 429
}

APIError is the base error type for HTTP API errors. It supports errors.Is matching by status code and errors.As extraction.

func (*APIError) Error

func (e *APIError) Error() string

Error returns the formatted error string.

func (*APIError) Is

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

Is supports errors.Is matching by status code. ErrServer (500) matches any 5xx status code. All other sentinels require an exact status code match.

type ActionInfo

type ActionInfo struct {
	Name        string        `json:"name"`
	Description string        `json:"description"`
	Parameters  []ActionParam `json:"parameters"`
}

type ActionParam

type ActionParam struct {
	Name        string `json:"name"`
	Type        string `json:"type"`
	Required    bool   `json:"required"`
	Default     string `json:"default,omitempty"`
	Description string `json:"description"`
}

type ActionRequest

type ActionRequest struct {
	ExecutionID string            `json:"execution_id"`
	Action      string            `json:"action"`
	Parameters  map[string]string `json:"parameters,omitempty"`
	Timeout     string            `json:"timeout"`
	Checksum    string            `json:"checksum,omitempty"`
	TriggeredBy *TriggeredBy      `json:"triggered_by,omitempty"`
}

ActionRequest is the SSE payload for action_request events.

type AuditBatch

type AuditBatch = []AuditEntry

AuditBatch is the top-level payload for POST /v1/nodes/{node_id}/audit.

type AuditEntry

type AuditEntry struct {
	Timestamp time.Time       `json:"timestamp"`
	Source    string          `json:"source"`
	EventType string          `json:"event_type"`
	Subject   json.RawMessage `json:"subject"`
	Object    json.RawMessage `json:"object"`
	Action    string          `json:"action"`
	Result    string          `json:"result"`
	Hostname  string          `json:"hostname"`
	Raw       string          `json:"raw"`
}

type BinaryInfo

type BinaryInfo struct {
	Version  string `json:"version"`
	Checksum string `json:"checksum"`
}

type BridgeConfig

type BridgeConfig struct {
	AccessSubnets    []string `json:"access_subnets"`
	EnableNAT        bool     `json:"enable_nat"`
	EnableForwarding bool     `json:"enable_forwarding"`
}

BridgeConfig is the bridge configuration pushed from the control plane.

type BridgeInfo

type BridgeInfo struct {
	Enabled                 bool   `json:"enabled"`
	AccessInterface         string `json:"access_interface"`
	ActiveRoutes            int    `json:"active_routes"`
	RelayEnabled            bool   `json:"relay_enabled"`
	ActiveRelaySessions     int    `json:"active_relay_sessions"`
	IngressEnabled          bool   `json:"ingress_enabled"`
	ActiveIngressRules      int    `json:"active_ingress_rules"`
	SiteToSiteEnabled       bool   `json:"site_to_site_enabled"`
	ActiveSiteToSiteTunnels int    `json:"active_site_to_site_tunnels"`
}

BridgeInfo is the bridge status reported by the node in heartbeats.

type CapabilitiesPayload

type CapabilitiesPayload struct {
	Binary         *BinaryInfo  `json:"binary,omitempty"`
	BuiltinActions []ActionInfo `json:"builtin_actions"`
	Hooks          []HookInfo   `json:"hooks"`
}

type Clock

type Clock interface {
	Now() time.Time
	After(d time.Duration) <-chan time.Time
}

Clock abstracts time operations for testing.

type Config

type Config struct {
	// BaseURL is the control plane API base URL (required).
	// Example: "https://api.plexsphere.com"
	BaseURL string `yaml:"base_url"`

	// TLSInsecureSkipVerify disables TLS certificate verification.
	// WARNING: Only use for development/testing.
	TLSInsecureSkipVerify bool `yaml:"tls_insecure_skip_verify"`

	// ConnectTimeout is the maximum time to wait for a TCP connection.
	// Default: 10s
	ConnectTimeout time.Duration `yaml:"connect_timeout"`

	// RequestTimeout is the maximum time for a complete HTTP request/response cycle.
	// Default: 30s
	RequestTimeout time.Duration `yaml:"request_timeout"`

	// SSEIdleTimeout is the maximum time to wait for any data on the SSE stream
	// before considering the connection stale and reconnecting.
	// Default: 90s
	SSEIdleTimeout time.Duration `yaml:"sse_idle_timeout"`
}

Config holds the configuration for the ControlPlane client. Config is passed as a constructor argument — no file I/O in this package.

func (*Config) ApplyDefaults

func (c *Config) ApplyDefaults()

ApplyDefaults sets default values for zero-valued fields.

func (*Config) Validate

func (c *Config) Validate() error

Validate checks that required fields are set.

type ConnectFunc

type ConnectFunc func(ctx context.Context) error

ConnectFunc is called to establish an SSE connection. It should block while the connection is active and return when it drops.

type ControlPlane

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

ControlPlane is the client for the Plexsphere control plane API.

func NewControlPlane

func NewControlPlane(cfg Config, version string, logger *slog.Logger) (*ControlPlane, error)

NewControlPlane creates a new ControlPlane client with the given configuration.

func (*ControlPlane) AckExecution

func (c *ControlPlane) AckExecution(ctx context.Context, nodeID, executionID string, req ExecutionAck) error

AckExecution acknowledges receipt of an execution command. POST /v1/nodes/{node_id}/executions/{execution_id}/ack

func (*ControlPlane) ConnectSSE

func (c *ControlPlane) ConnectSSE(ctx context.Context, nodeID, lastEventID string) (*http.Response, error)

ConnectSSE opens an SSE connection to the node event stream. The caller is responsible for closing the response body. GET /v1/nodes/{node_id}/events

func (*ControlPlane) Deregister

func (c *ControlPlane) Deregister(ctx context.Context, nodeID string) error

Deregister removes a node from the control plane. POST /v1/nodes/{node_id}/deregister

func (*ControlPlane) FetchArtifact

func (c *ControlPlane) FetchArtifact(ctx context.Context, version, goos, arch string) (io.ReadCloser, error)

FetchArtifact downloads a plexd binary artifact. The caller is responsible for closing the returned ReadCloser. GET /v1/artifacts/plexd/{version}/{os}/{arch}

func (*ControlPlane) FetchSecret

func (c *ControlPlane) FetchSecret(ctx context.Context, nodeID, key string) (*SecretResponse, error)

FetchSecret retrieves a specific secret for the node. GET /v1/nodes/{node_id}/secrets/{key}

func (*ControlPlane) FetchState

func (c *ControlPlane) FetchState(ctx context.Context, nodeID string) (*StateResponse, error)

FetchState retrieves the full desired state for a node. GET /v1/nodes/{node_id}/state

func (*ControlPlane) GetJSON

func (c *ControlPlane) GetJSON(ctx context.Context, path string, result any) error

GetJSON sends a GET request and decodes the JSON response.

func (*ControlPlane) Heartbeat

func (c *ControlPlane) Heartbeat(ctx context.Context, nodeID string, req HeartbeatRequest) (*HeartbeatResponse, error)

Heartbeat sends a heartbeat to the control plane. POST /v1/nodes/{node_id}/heartbeat

func (*ControlPlane) Ping

func (c *ControlPlane) Ping(ctx context.Context) error

Ping sends a GET request to /v1/ping for health checking.

func (*ControlPlane) PostJSON

func (c *ControlPlane) PostJSON(ctx context.Context, path string, body any, result any) error

PostJSON sends a POST request with a JSON body and decodes the JSON response.

func (*ControlPlane) Register

Register sends a registration request to the control plane. POST /v1/register

func (*ControlPlane) ReportAudit

func (c *ControlPlane) ReportAudit(ctx context.Context, nodeID string, batch AuditBatch) error

ReportAudit sends a batch of audit events to the control plane. POST /v1/nodes/{node_id}/audit

func (*ControlPlane) ReportDrift

func (c *ControlPlane) ReportDrift(ctx context.Context, nodeID string, req DriftReport) error

ReportDrift reports drift corrections performed by the node. POST /v1/nodes/{node_id}/drift

func (*ControlPlane) ReportEndpoint

func (c *ControlPlane) ReportEndpoint(ctx context.Context, nodeID string, req EndpointReport) (*EndpointResponse, error)

ReportEndpoint reports the node's NAT endpoint information. PUT /v1/nodes/{node_id}/endpoint

func (*ControlPlane) ReportIntegrityViolation

func (c *ControlPlane) ReportIntegrityViolation(ctx context.Context, nodeID string, req IntegrityViolationReport) error

ReportIntegrityViolation reports a file integrity violation to the control plane. POST /v1/nodes/{node_id}/integrity/violations

func (*ControlPlane) ReportLogs

func (c *ControlPlane) ReportLogs(ctx context.Context, nodeID string, batch LogBatch) error

ReportLogs sends a batch of logs to the control plane. POST /v1/nodes/{node_id}/logs

func (*ControlPlane) ReportMetrics

func (c *ControlPlane) ReportMetrics(ctx context.Context, nodeID string, batch MetricBatch) error

ReportMetrics sends a batch of metrics to the control plane. POST /v1/nodes/{node_id}/metrics

func (*ControlPlane) ReportResult

func (c *ControlPlane) ReportResult(ctx context.Context, nodeID, executionID string, req ExecutionResult) error

ReportResult reports the result of an execution. POST /v1/nodes/{node_id}/executions/{execution_id}/result

func (*ControlPlane) RotateKeys

RotateKeys requests key rotation for a node. POST /v1/keys/rotate

func (*ControlPlane) SetAuthToken

func (c *ControlPlane) SetAuthToken(token string)

SetAuthToken sets the bearer token used for API authentication.

func (*ControlPlane) SyncReports

func (c *ControlPlane) SyncReports(ctx context.Context, nodeID string, req ReportSyncRequest) error

SyncReports sends report data to the control plane. POST /v1/nodes/{node_id}/report

func (*ControlPlane) TunnelClosed

func (c *ControlPlane) TunnelClosed(ctx context.Context, nodeID, sessionID string, req TunnelClosedRequest) error

TunnelClosed reports that a tunnel session has closed. POST /v1/nodes/{node_id}/tunnels/{session_id}/closed

func (*ControlPlane) TunnelReady

func (c *ControlPlane) TunnelReady(ctx context.Context, nodeID, sessionID string, req TunnelReadyRequest) error

TunnelReady reports that a tunnel listener is ready for connections. POST /v1/nodes/{node_id}/tunnels/{session_id}/ready

func (*ControlPlane) UpdateCapabilities

func (c *ControlPlane) UpdateCapabilities(ctx context.Context, nodeID string, caps CapabilitiesPayload) error

UpdateCapabilities publishes the node's capabilities. PUT /v1/nodes/{node_id}/capabilities

type DataEntry

type DataEntry struct {
	Key         string          `json:"key"`
	ContentType string          `json:"content_type"`
	Payload     json.RawMessage `json:"payload"`
	Version     int             `json:"version"`
	UpdatedAt   time.Time       `json:"updated_at"`
}

type DriftCorrection

type DriftCorrection struct {
	Type   string `json:"type"`
	Detail string `json:"detail"`
}

type DriftReport

type DriftReport struct {
	Timestamp   time.Time         `json:"timestamp"`
	Corrections []DriftCorrection `json:"corrections"`
}

type Ed25519Verifier

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

Ed25519Verifier verifies SignedEnvelope signatures using Ed25519 keys. It supports key rotation by holding both a current and an optional previous key.

func NewEd25519Verifier

func NewEd25519Verifier(currentKey ed25519.PublicKey) *Ed25519Verifier

NewEd25519Verifier returns a new verifier using the given public key.

func (*Ed25519Verifier) SetKeys

func (v *Ed25519Verifier) SetKeys(current, previous ed25519.PublicKey, transitionExpires time.Time)

SetKeys updates the verifier with a new current key, an optional previous key, and a deadline after which the previous key is no longer accepted.

func (*Ed25519Verifier) Verify

func (v *Ed25519Verifier) Verify(_ context.Context, envelope SignedEnvelope) error

Verify checks the signature and freshness of a SignedEnvelope. The nonce is recorded only after signature verification succeeds to prevent nonce exhaustion attacks via forged envelopes.

type EndpointReport

type EndpointReport struct {
	PublicEndpoint string `json:"public_endpoint"`
	NATType        string `json:"nat_type"`
}

type EndpointResponse

type EndpointResponse struct {
	PeerEndpoints []PeerEndpoint `json:"peer_endpoints"`
}

type EventDispatcher

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

EventDispatcher routes verified events to registered handlers by event type.

func NewEventDispatcher

func NewEventDispatcher(logger *slog.Logger) *EventDispatcher

NewEventDispatcher creates a new EventDispatcher.

func (*EventDispatcher) Dispatch

func (d *EventDispatcher) Dispatch(ctx context.Context, envelope SignedEnvelope)

Dispatch invokes all handlers registered for the event's type. Handler errors are logged but do not stop processing of subsequent handlers. Events with no registered handler are logged at debug level and discarded.

func (*EventDispatcher) Register

func (d *EventDispatcher) Register(eventType string, handler EventHandler)

Register adds a handler for the given event type. Multiple handlers can be registered for the same event type.

type EventHandler

type EventHandler func(ctx context.Context, envelope SignedEnvelope) error

EventHandler is a function that handles a verified SSE event.

type EventVerifier

type EventVerifier interface {
	Verify(ctx context.Context, envelope SignedEnvelope) error
}

EventVerifier verifies the signature of a SignedEnvelope.

type ExecutionAck

type ExecutionAck struct {
	ExecutionID string `json:"execution_id"`
	Status      string `json:"status"`
	Reason      string `json:"reason"`
}

type ExecutionResult

type ExecutionResult struct {
	ExecutionID string       `json:"execution_id"`
	Status      string       `json:"status"`
	ExitCode    int          `json:"exit_code"`
	Stdout      string       `json:"stdout"`
	Stderr      string       `json:"stderr"`
	Duration    string       `json:"duration"`
	FinishedAt  time.Time    `json:"finished_at"`
	TriggeredBy *TriggeredBy `json:"triggered_by,omitempty"`
}

type FailureAction

type FailureAction int

FailureAction indicates how the reconnect engine should handle a failure.

const (
	// RetryTransient means use exponential backoff (network errors, 5xx).
	RetryTransient FailureAction = iota
	// RetryAuth means invoke OnAuthFailure callback and pause (401).
	RetryAuth
	// RespectServer means use the server-provided Retry-After delay (429).
	RespectServer
	// PermanentFailure means stop reconnection entirely (403, 404).
	PermanentFailure
)

func ClassifyError

func ClassifyError(err error) FailureAction

ClassifyError determines the appropriate reconnection action for an error.

type HeartbeatRequest

type HeartbeatRequest struct {
	NodeID         string          `json:"node_id"`
	Timestamp      time.Time       `json:"timestamp"`
	Status         string          `json:"status"`
	Uptime         string          `json:"uptime"`
	BinaryChecksum string          `json:"binary_checksum"`
	Mesh           *MeshInfo       `json:"mesh,omitempty"`
	NAT            *NATInfo        `json:"nat,omitempty"`
	Bridge         *BridgeInfo     `json:"bridge,omitempty"`
	UserAccess     *UserAccessInfo `json:"user_access,omitempty"`
	Ingress        *IngressInfo    `json:"ingress,omitempty"`
	SiteToSite     *SiteToSiteInfo `json:"site_to_site,omitempty"`
}

type HeartbeatResponse

type HeartbeatResponse struct {
	Reconcile  bool `json:"reconcile"`
	RotateKeys bool `json:"rotate_keys"`
}

type HookInfo

type HookInfo struct {
	Name        string        `json:"name"`
	Description string        `json:"description"`
	Source      string        `json:"source"`
	Checksum    string        `json:"checksum"`
	Parameters  []ActionParam `json:"parameters"`
	Timeout     string        `json:"timeout"`
	Sandbox     string        `json:"sandbox"`
}

type IngressConfig

type IngressConfig struct {
	Enabled bool          `json:"enabled"`
	Rules   []IngressRule `json:"rules"`
}

IngressConfig is the ingress configuration pushed from the control plane.

type IngressInfo

type IngressInfo struct {
	Enabled         bool `json:"enabled"`
	RuleCount       int  `json:"rule_count"`
	ConnectionCount int  `json:"connection_count"`
	ACMEEnabled     bool `json:"acme_enabled"`
}

IngressInfo is the ingress status reported by the node in heartbeats.

type IngressRule

type IngressRule struct {
	RuleID     string `json:"rule_id"`
	ListenPort int    `json:"listen_port"`
	TargetAddr string `json:"target_addr"`
	// Mode is the TLS handling mode: "tcp" (passthrough), "terminate" (static cert),
	// or "acme" (automatic certificate via ACME).
	Mode     string `json:"mode"`
	CertPEM  string `json:"cert_pem,omitempty"`
	KeyPEM   string `json:"key_pem,omitempty"`
	Hostname string `json:"hostname,omitempty"`
}

IngressRule represents a single public ingress rule.

type IntegrityViolationReport

type IntegrityViolationReport struct {
	Type             string    `json:"type"`
	Path             string    `json:"path"`
	ExpectedChecksum string    `json:"expected_checksum"`
	ActualChecksum   string    `json:"actual_checksum"`
	Detail           string    `json:"detail"`
	Timestamp        time.Time `json:"timestamp"`
}

IntegrityViolationReport is sent when a file integrity check fails.

type KeyRotateRequest

type KeyRotateRequest struct {
	NodeID       string `json:"node_id"`
	NewPublicKey string `json:"new_public_key"`
}

type KeyRotateResponse

type KeyRotateResponse struct {
	UpdatedPeers []Peer `json:"updated_peers"`
}

type LocalEndpointConfig

type LocalEndpointConfig struct {
	// URL is the HTTPS endpoint URL. Must use the https:// scheme when set.
	URL string `yaml:"url"`

	// SecretKey is the authentication credential for the local endpoint.
	// Required when URL is non-empty.
	SecretKey string `yaml:"secret_key"`

	// TLSInsecureSkipVerify disables TLS certificate verification.
	TLSInsecureSkipVerify bool `yaml:"tls_insecure_skip_verify"`
}

LocalEndpointConfig holds the configuration for a local data-plane endpoint that a pipeline can send data to in addition to the platform. A zero-valued LocalEndpointConfig means "not configured" and passes validation.

func (*LocalEndpointConfig) Validate

func (c *LocalEndpointConfig) Validate(prefix string) error

Validate checks that the local endpoint configuration is well-formed. The prefix is prepended to error messages for context (e.g. "metrics").

type LogBatch

type LogBatch = []LogEntry

LogBatch is the top-level payload for POST /v1/nodes/{node_id}/logs.

type LogEntry

type LogEntry struct {
	Timestamp time.Time `json:"timestamp"`
	Source    string    `json:"source"`
	Unit      string    `json:"unit"`
	Message   string    `json:"message"`
	Severity  string    `json:"severity"`
	Hostname  string    `json:"hostname"`
}

type MeshInfo

type MeshInfo struct {
	Interface  string `json:"interface"`
	PeerCount  int    `json:"peer_count"`
	ListenPort int    `json:"listen_port"`
}

type MetricBatch

type MetricBatch = []MetricPoint

MetricBatch is the top-level payload for POST /v1/nodes/{node_id}/metrics.

type MetricPoint

type MetricPoint struct {
	Timestamp time.Time       `json:"timestamp"`
	Group     string          `json:"group"`
	PeerID    string          `json:"peer_id,omitempty"`
	Data      json.RawMessage `json:"data"`
}

type NATInfo

type NATInfo struct {
	PublicEndpoint string `json:"public_endpoint"`
	Type           string `json:"type"`
}

type NoOpVerifier

type NoOpVerifier struct{}

NoOpVerifier is an EventVerifier that accepts all envelopes without verification.

func (NoOpVerifier) Verify

Verify always returns nil.

type NonceStore

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

NonceStore tracks recently seen nonces to prevent replay attacks.

func NewNonceStore

func NewNonceStore() *NonceStore

NewNonceStore returns an initialised NonceStore.

func (*NonceStore) Add

func (s *NonceStore) Add(nonce string, issuedAt time.Time) error

Add records a nonce. It returns an error if the nonce has already been seen.

type Peer

type Peer struct {
	ID         string   `json:"id"`
	PublicKey  string   `json:"public_key"`
	MeshIP     string   `json:"mesh_ip"`
	Endpoint   string   `json:"endpoint"`
	AllowedIPs []string `json:"allowed_ips"`
	PSK        string   `json:"psk"`
}

Peer is used in registration responses and state responses.

type PeerEndpoint

type PeerEndpoint struct {
	PeerID   string `json:"peer_id"`
	Endpoint string `json:"endpoint"`
}

type Policy

type Policy struct {
	ID    string       `json:"id"`
	Rules []PolicyRule `json:"rules"`
}

type PolicyRule

type PolicyRule struct {
	Src      string `json:"src"`
	Dst      string `json:"dst"`
	Port     int    `json:"port"`
	Protocol string `json:"protocol"`
	Action   string `json:"action"`
}

type PollFunc

type PollFunc func(ctx context.Context) error

PollFunc is called during polling fallback to fetch full state.

type ReconnectEngine

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

ReconnectEngine manages SSE reconnection with backoff and polling fallback.

func NewReconnectEngine

func NewReconnectEngine(logger *slog.Logger) *ReconnectEngine

NewReconnectEngine creates a new ReconnectEngine with default settings.

func (*ReconnectEngine) Run

func (r *ReconnectEngine) Run(ctx context.Context, connectFn ConnectFunc, pollFn PollFunc) error

Run is the main state machine loop that manages SSE reconnection.

States: Connecting -> Connected | Backoff

Backoff -> Connecting | Polling
Polling -> Connecting (periodic SSE retry)

Context cancellation exits from any state.

func (*ReconnectEngine) SetBaseInterval

func (r *ReconnectEngine) SetBaseInterval(d time.Duration)

SetBaseInterval updates the base backoff interval. This is called when the SSE retry: field is received from the server.

func (*ReconnectEngine) SetClock

func (r *ReconnectEngine) SetClock(c Clock)

SetClock sets a custom clock implementation for testing.

func (*ReconnectEngine) SetIntervals

func (r *ReconnectEngine) SetIntervals(base, max time.Duration)

SetIntervals configures the base and max backoff intervals and resets the current interval to the new base. Useful for testing with fast intervals.

func (*ReconnectEngine) SetOnAuthFailure

func (r *ReconnectEngine) SetOnAuthFailure(fn func())

SetOnAuthFailure sets the callback invoked on authentication failures.

func (*ReconnectEngine) SetPollInterval

func (r *ReconnectEngine) SetPollInterval(d time.Duration)

SetPollInterval sets how often to poll during polling fallback mode.

func (*ReconnectEngine) SetPollingFallbackConfig

func (r *ReconnectEngine) SetPollingFallbackConfig(fallbackAfter, pollInterval time.Duration)

SetPollingFallbackConfig configures when to enter polling mode and how often to poll.

type RegisterRequest

type RegisterRequest struct {
	Token        string               `json:"token"`
	PublicKey    string               `json:"public_key"`
	Hostname     string               `json:"hostname"`
	Metadata     map[string]string    `json:"metadata,omitempty"`
	Capabilities *CapabilitiesPayload `json:"capabilities,omitempty"`
}

type RegisterResponse

type RegisterResponse struct {
	NodeID           string `json:"node_id"`
	MeshIP           string `json:"mesh_ip"`
	SigningPublicKey string `json:"signing_public_key"`
	NodeSecretKey    string `json:"node_secret_key"`
	Peers            []Peer `json:"peers"`
}

type RelayConfig

type RelayConfig struct {
	Sessions []RelaySessionAssignment `json:"sessions"`
}

RelayConfig is the relay configuration pushed from the control plane. It contains the list of relay session assignments for this bridge node.

type RelaySessionAssignment

type RelaySessionAssignment struct {
	SessionID     string    `json:"session_id"`
	PeerAID       string    `json:"peer_a_id"`
	PeerAEndpoint string    `json:"peer_a_endpoint"`
	PeerBID       string    `json:"peer_b_id"`
	PeerBEndpoint string    `json:"peer_b_endpoint"`
	ExpiresAt     time.Time `json:"expires_at"`
}

RelaySessionAssignment represents a relay session assigned by the control plane.

type ReportEntry

type ReportEntry struct {
	Key         string          `json:"key"`
	ContentType string          `json:"content_type"`
	Payload     json.RawMessage `json:"payload"`
	Version     int             `json:"version"`
	UpdatedAt   time.Time       `json:"updated_at"`
}

type ReportSyncRequest

type ReportSyncRequest struct {
	Entries []ReportEntry `json:"entries"`
	Deleted []string      `json:"deleted"`
}

type RetryCallback

type RetryCallback func(interval time.Duration)

RetryCallback is called when the SSE server sends a retry: field.

type SSEEvent

type SSEEvent struct {
	Type string // from "event:" field, defaults to "message"
	Data string // concatenated data fields
	ID   string // from "id:" field
}

SSEEvent represents a single parsed SSE event.

type SSEManager

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

SSEManager is the top-level orchestrator that wires SSEStream, ReconnectEngine, EventVerifier, and EventDispatcher together.

func NewSSEManager

func NewSSEManager(client *ControlPlane, verifier EventVerifier, logger *slog.Logger) *SSEManager

NewSSEManager creates a new SSEManager. If verifier is nil, NoOpVerifier is used.

func (*SSEManager) RegisterHandler

func (m *SSEManager) RegisterHandler(eventType string, handler EventHandler)

RegisterHandler adds a handler for the given event type. Must be called before Start.

func (*SSEManager) SetPollFunc

func (m *SSEManager) SetPollFunc(fn PollFunc)

SetPollFunc sets the function called during polling fallback to fetch full state.

func (*SSEManager) SetPollingFallback

func (m *SSEManager) SetPollingFallback(fallbackAfter, pollInterval time.Duration)

SetPollingFallback configures when to enter polling mode and how often to poll.

func (*SSEManager) SetReconnectIntervals

func (m *SSEManager) SetReconnectIntervals(base, max time.Duration)

SetReconnectIntervals configures the base and max backoff intervals. Useful for testing with fast intervals.

func (*SSEManager) Shutdown

func (m *SSEManager) Shutdown()

Shutdown gracefully stops the manager by cancelling its context.

func (*SSEManager) Start

func (m *SSEManager) Start(ctx context.Context, nodeID string) error

Start begins the SSE connection loop with automatic reconnection. It blocks until the context is cancelled, Shutdown is called, or a permanent error occurs.

type SSEParser

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

SSEParser reads from an io.Reader and emits parsed SSE events.

func NewSSEParser

func NewSSEParser(r io.Reader) *SSEParser

NewSSEParser creates a parser reading from the given reader.

func (*SSEParser) LastEventID

func (p *SSEParser) LastEventID() string

LastEventID returns the most recently received event ID.

func (*SSEParser) Next

func (p *SSEParser) Next() (SSEEvent, bool)

Next reads lines until a complete event is found. Returns the event and true, or a zero event and false when the reader is exhausted.

func (*SSEParser) SetRetryCallback

func (p *SSEParser) SetRetryCallback(cb RetryCallback)

SetRetryCallback sets the function called when a retry: field is received.

type SSEStream

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

SSEStream connects to the SSE endpoint, parses events, verifies envelopes, and dispatches them to registered handlers.

func NewSSEStream

func NewSSEStream(client *ControlPlane, verifier EventVerifier, dispatcher *EventDispatcher, idleTimeout time.Duration, logger *slog.Logger) *SSEStream

NewSSEStream creates a new SSEStream.

func (*SSEStream) Connect

func (s *SSEStream) Connect(ctx context.Context, nodeID string) error

Connect establishes the SSE connection and processes events until the connection drops or context is cancelled. Returns nil when the connection closes cleanly, or an error.

func (*SSEStream) LastEventID

func (s *SSEStream) LastEventID() string

LastEventID returns the last received event ID (for reconnection).

type SSHSessionSetup

type SSHSessionSetup struct {
	SessionID     string    `json:"session_id"`
	TargetHost    string    `json:"target_host"`
	TargetPort    int       `json:"target_port"`
	AuthorizedKey string    `json:"authorized_key"`
	ExpiresAt     time.Time `json:"expires_at"`
}

SSHSessionSetup is the payload of an ssh_session_setup SSE event.

type SecretRef

type SecretRef struct {
	Key     string `json:"key"`
	Version int    `json:"version"`
}

type SecretResponse

type SecretResponse struct {
	Key        string `json:"key"`
	Ciphertext string `json:"ciphertext"`
	Nonce      string `json:"nonce"`
	Version    int    `json:"version"`
}

type SignedEnvelope

type SignedEnvelope struct {
	EventType string          `json:"event_type"`
	EventID   string          `json:"event_id"`
	IssuedAt  time.Time       `json:"issued_at"`
	Nonce     string          `json:"nonce"`
	Payload   json.RawMessage `json:"payload"`
	Signature string          `json:"signature"`
}

SignedEnvelope is the wire format for SSE events received from the control plane.

func ParseEnvelope

func ParseEnvelope(data []byte) (SignedEnvelope, error)

ParseEnvelope unmarshals data into a SignedEnvelope and validates required fields.

type SigningKeys

type SigningKeys struct {
	Current           string     `json:"current"`
	Previous          string     `json:"previous,omitempty"`
	TransitionExpires *time.Time `json:"transition_expires,omitempty"`
}

type SiteToSiteConfig

type SiteToSiteConfig struct {
	Enabled bool               `json:"enabled"`
	Tunnels []SiteToSiteTunnel `json:"tunnels"`
}

SiteToSiteConfig is the site-to-site VPN configuration pushed from the control plane.

type SiteToSiteInfo

type SiteToSiteInfo struct {
	Enabled             bool     `json:"enabled"`
	TunnelCount         int      `json:"tunnel_count"`
	TunnelProviderNames []string `json:"tunnel_provider_names,omitempty"`
}

SiteToSiteInfo is the site-to-site VPN status reported by the node in heartbeats.

type SiteToSiteTunnel

type SiteToSiteTunnel struct {
	TunnelID        string   `json:"tunnel_id"`
	RemoteEndpoint  string   `json:"remote_endpoint"`
	RemotePublicKey string   `json:"remote_public_key"`
	LocalSubnets    []string `json:"local_subnets"`
	RemoteSubnets   []string `json:"remote_subnets"`
	PSK             string   `json:"psk,omitempty"`
	InterfaceName   string   `json:"interface_name"`
	ListenPort      int      `json:"listen_port"`
	// ProviderType specifies which tunnel provider to use for this tunnel.
	// Empty or "wireguard" means the default WireGuard-based approach.
	// Other values (e.g. "ipsec", "openvpn") delegate to the corresponding TunnelProvider.
	ProviderType string `json:"provider_type,omitempty"`
}

SiteToSiteTunnel represents a single site-to-site VPN tunnel definition.

type StateResponse

type StateResponse struct {
	Peers            []Peer            `json:"peers"`
	Policies         []Policy          `json:"policies"`
	SigningKeys      *SigningKeys      `json:"signing_keys,omitempty"`
	Metadata         map[string]string `json:"metadata,omitempty"`
	BridgeConfig     *BridgeConfig     `json:"bridge_config,omitempty"`
	RelayConfig      *RelayConfig      `json:"relay_config,omitempty"`
	UserAccessConfig *UserAccessConfig `json:"user_access_config,omitempty"`
	IngressConfig    *IngressConfig    `json:"ingress_config,omitempty"`
	SiteToSiteConfig *SiteToSiteConfig `json:"site_to_site_config,omitempty"`
	Data             []DataEntry       `json:"data"`
	SecretRefs       []SecretRef       `json:"secret_refs"`
}

type TriggeredBy

type TriggeredBy struct {
	Type      string `json:"type"`
	SessionID string `json:"session_id"`
	UserID    string `json:"user_id"`
	Email     string `json:"email"`
}

type TunnelClosedRequest

type TunnelClosedRequest struct {
	Reason    string    `json:"reason"`
	Duration  string    `json:"duration"`
	Timestamp time.Time `json:"timestamp"`
}

TunnelClosedRequest is sent when a tunnel session closes.

type TunnelReadyRequest

type TunnelReadyRequest struct {
	ListenAddr string    `json:"listen_addr"`
	Timestamp  time.Time `json:"timestamp"`
}

TunnelReadyRequest is sent when a tunnel listener is ready.

type UserAccessConfig

type UserAccessConfig struct {
	Enabled       bool             `json:"enabled"`
	InterfaceName string           `json:"interface_name"`
	ListenPort    int              `json:"listen_port"`
	Peers         []UserAccessPeer `json:"peers"`
}

UserAccessConfig is the user access configuration pushed from the control plane.

type UserAccessInfo

type UserAccessInfo struct {
	Enabled        bool   `json:"enabled"`
	InterfaceName  string `json:"interface_name"`
	PeerCount      int    `json:"peer_count"`
	ListenPort     int    `json:"listen_port"`
	ProviderName   string `json:"provider_name,omitempty"`
	ProviderStatus string `json:"provider_status,omitempty"`
}

UserAccessInfo is the user access status reported by the node in heartbeats.

type UserAccessPeer

type UserAccessPeer struct {
	PublicKey  string   `json:"public_key"`
	AllowedIPs []string `json:"allowed_ips"`
	PSK        string   `json:"psk,omitempty"`
	Label      string   `json:"label"`
}

UserAccessPeer represents a user access peer (external VPN client).

Jump to

Keyboard shortcuts

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