server

package
v0.0.0-...-592c247 Latest Latest
Warning

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

Go to latest
Published: Apr 29, 2026 License: MIT Imports: 67 Imported by: 0

Documentation

Index

Constants

View Source
const (

	// PanelRuntimeSourceLegacy reports that runtime values come from the legacy flag-based startup path.
	PanelRuntimeSourceLegacy = "legacy"
	// PanelRuntimeSourceConfigFile reports that runtime values come from config.toml.
	PanelRuntimeSourceConfigFile = "config_file"
)
View Source
const EnvForceSecureCookie = "PANVEX_FORCE_SECURE_COOKIE"

EnvForceSecureCookie unconditionally marks the session cookie Secure, regardless of TLS heuristics (Q3.U-S-13). Operators set this in any production deployment fronted by HTTPS so a misconfigured proxy or a missing X-Forwarded-Proto cannot leak the cookie over plain HTTP.

View Source
const EnvWSDevLoopback = "PANVEX_WS_DEV_LOOPBACK"

EnvWSDevLoopback opts into the development-only behaviour that allows WebSocket upgrade requests from any port on 127.0.0.1/::1/localhost. Without this env set we fall back to the strict policy: the Origin must match the exact request Host, even for loopback clients. The Vite dev server proxies /api to :8080 with Origin matching :5173, so developers must set PANVEX_WS_DEV_LOOPBACK=1 explicitly when running split-port.

Variables

View Source
var ErrAlreadyAdopted = errors.New("client already adopted")

ErrAlreadyAdopted is returned by adoptDiscoveredClient when the discovered record has already been adopted. Previously this was a generic fmt.Errorf("client already adopted"); the sentinel lets tests and HTTP handlers detect the condition reliably via errors.Is (P2-LOG-03 / L-11).

View Source
var ErrLegacyEnc1RequiresKey = errors.New("legacy ENC:v1 key requires --encryption-key-file to migrate")

ErrLegacyEnc1RequiresKey is returned when the persisted CA private key is stored in the legacy "ENC:v1" format but no encryption passphrase is configured to migrate it. P2-SEC-05: legacy ENC:v1 uses SHA-256 without a salt and must not be silently accepted — the operator must either provide the encryption key so we can re-encrypt as "ENC2:" or remove the stored key to regenerate the CA.

Functions

func AtomicReplaceBinary

func AtomicReplaceBinary(currentPath, newPath string) error

AtomicReplaceBinary replaces the binary at currentPath with the one at newPath. See updates.AtomicReplaceBinary for details.

func CompareVersions

func CompareVersions(a, b string) int

CompareVersions delegates to updates.CompareVersions.

func DownloadArchive

func DownloadArchive(ctx context.Context, url, token string) (string, error)

DownloadArchive fetches a .tar.gz archive from url. See updates.DownloadArchive for details.

func DownloadChecksum

func DownloadChecksum(ctx context.Context, url, token string) (string, error)

DownloadChecksum fetches a .sha256 checksum file and returns the hex digest. See updates.DownloadChecksum for details.

func DownloadSignature

func DownloadSignature(ctx context.Context, url, token string) ([]byte, error)

DownloadSignature fetches a detached signature file and returns its bytes. See updates.DownloadSignature for details.

func ExtractBinaryFromArchive

func ExtractBinaryFromArchive(archivePath string) (string, error)

ExtractBinaryFromArchive extracts the first file from a .tar.gz archive into a temporary executable. See updates.ExtractBinaryFromArchive for details.

func NewSlogContextHandler

func NewSlogContextHandler(inner slog.Handler) slog.Handler

NewSlogContextHandler wraps an existing handler so emitted records carry request_id when present in ctx. Returns the inner handler unchanged when given nil so callers can compose unconditionally. Exported for cmd/control-plane to install at startup.

func ParseReleaseTag

func ParseReleaseTag(tag string) (component, version string, ok bool)

ParseReleaseTag delegates to updates.ParseReleaseTag.

func ResolveAssetURLs

func ResolveAssetURLs(release *GitHubRelease, component string) (binaryURL, checksumURL, signatureURL string)

ResolveAssetURLs delegates to updates.ResolveAssetURLs.

func VerifyChecksum

func VerifyChecksum(path, expected string) error

VerifyChecksum computes the SHA256 of the file at path and compares it to the expected hex digest. See updates.VerifyChecksum for details.

Types

type Agent

type Agent struct {
	ID                  string                                 `json:"id"`
	NodeName            string                                 `json:"node_name"`
	FleetGroupID        string                                 `json:"fleet_group_id"`
	Version             string                                 `json:"version"`
	ReadOnly            bool                                   `json:"read_only"`
	PresenceState       string                                 `json:"presence_state"`
	CertificateRecovery *agentCertificateRecoveryGrantResponse `json:"certificate_recovery,omitempty"`
	CertIssuedAt        *time.Time                             `json:"cert_issued_at,omitempty"`
	CertExpiresAt       *time.Time                             `json:"cert_expires_at,omitempty"`
	// CertSerial is the serial of the most recently issued client cert.
	// Used to pin agent identity at gRPC connect time (Q4.U-S-04). Not
	// exposed in the public JSON shape — operators don't need it and
	// it's noise in the dashboard.
	CertSerial string       `json:"-"`
	Runtime    AgentRuntime `json:"runtime"`
	LastSeenAt time.Time    `json:"last_seen_at"`
}

Agent stores the control-plane view of a connected host agent.

type AgentRuntime

type AgentRuntime struct {
	AcceptingNewConnections   bool                     `json:"accepting_new_connections"`
	MERuntimeReady            bool                     `json:"me_runtime_ready"`
	ME2DCFallbackEnabled      bool                     `json:"me2dc_fallback_enabled"`
	UseMiddleProxy            bool                     `json:"use_middle_proxy"`
	StartupStatus             string                   `json:"startup_status"`
	StartupStage              string                   `json:"startup_stage"`
	StartupProgressPct        float64                  `json:"startup_progress_pct"`
	InitializationStatus      string                   `json:"initialization_status"`
	Degraded                  bool                     `json:"degraded"`
	LifecycleState            string                   `json:"lifecycle_state"`
	InitializationStage       string                   `json:"initialization_stage"`
	InitializationProgressPct float64                  `json:"initialization_progress_pct"`
	TransportMode             string                   `json:"transport_mode"`
	CurrentConnections        int                      `json:"current_connections"`
	CurrentConnectionsME      int                      `json:"current_connections_me"`
	CurrentConnectionsDirect  int                      `json:"current_connections_direct"`
	ActiveUsers               int                      `json:"active_users"`
	UptimeSeconds             float64                  `json:"uptime_seconds"`
	ConnectionsTotal          uint64                   `json:"connections_total"`
	ConnectionsBadTotal       uint64                   `json:"connections_bad_total"`
	HandshakeTimeoutsTotal    uint64                   `json:"handshake_timeouts_total"`
	ConfiguredUsers           int                      `json:"configured_users"`
	DCCoveragePct             float64                  `json:"dc_coverage_pct"`
	HealthyUpstreams          int                      `json:"healthy_upstreams"`
	TotalUpstreams            int                      `json:"total_upstreams"`
	DCs                       []RuntimeDC              `json:"dcs"`
	Upstreams                 []RuntimeUpstream        `json:"upstreams"`
	RecentEvents              []RuntimeEvent           `json:"recent_events"`
	SystemLoad                RuntimeSystemLoad        `json:"system_load"`
	MeWritersSummary          *RuntimeMeWritersSummary `json:"me_writers_summary,omitempty"`
	UpdatedAt                 time.Time                `json:"updated_at"`
}

AgentRuntime stores the normalized Telemt operator overview for one agent.

type AuditEvent

type AuditEvent struct {
	ID        string         `json:"id"`
	ActorID   string         `json:"actor_id"`
	Action    string         `json:"action"`
	TargetID  string         `json:"target_id"`
	CreatedAt time.Time      `json:"created_at"`
	Details   map[string]any `json:"details"`
}

AuditEvent stores an immutable operator or security event emitted by the control-plane.

type BulkAdoptResult

type BulkAdoptResult struct {
	ID       string `json:"id"`
	Status   string `json:"status"`
	ClientID string `json:"client_id,omitempty"`
	Name     string `json:"name,omitempty"`
	Message  string `json:"message,omitempty"`
}

BulkAdoptResult is the per-id outcome from bulkAdoptDiscoveredClients. Status is one of: "adopted" (new client or merged into existing), "already_adopted" (resolved via a sibling earlier in the batch or by a concurrent caller), "error" (Message holds details).

type FleetScopeAccess

type FleetScopeAccess struct {
	Global  bool
	Allowed map[string]struct{}
}

FleetScopeAccess captures the operator's effective fleet-group scope for one request. R-S-14 introduced this as the foundation for per-resource authorization: handlers that touch a fleet-group-scoped resource (clients, fleet groups, discovered clients, jobs targeting agents) consult the access set before reading or mutating.

Semantics:

  • Global == true → no per-group restriction; admin role always resolves to global, and an operator with no scope rows behaves the same way (single-tenant default).
  • Global == false → only fleet-group ids in Allowed are visible.

Methods on this struct are the only path callers should use; do not inspect Allowed directly so a future migration to a different scope model (regex, hierarchical) lands in one place.

func (FleetScopeAccess) Filter

func (a FleetScopeAccess) Filter(fleetGroupIDs []string) []string

Filter returns the subset of input ids the operator can access. Useful for narrowing list responses and bulk-job target lists in one pass without per-id allocation.

func (FleetScopeAccess) IsAllowed

func (a FleetScopeAccess) IsAllowed(fleetGroupID string) bool

IsAllowed reports whether the operator can act on the given fleet group id. Global access always passes; otherwise the id must be in the explicit allow-set.

func (FleetScopeAccess) IsAllowedAny

func (a FleetScopeAccess) IsAllowedAny(fleetGroupIDs []string) bool

IsAllowedAny reports whether at least one of the supplied fleet group ids is in scope. Used by client-side checks where a managed client may live in multiple groups — operator access is granted as long as ONE of those groups is in scope. An empty input means "no group affiliation"; we treat that as deny-by-default for non-global scopes (the operator cannot see fleet-orphan clients).

type GitHubAsset

type GitHubAsset = updates.GitHubReleaseAsset

GitHubRelease re-exported for handlers/tests that still reference the short name through this package.

type GitHubRelease

type GitHubRelease = updates.GitHubRelease

GitHubRelease re-exported for handlers/tests that still reference the short name through this package.

func FetchLatestVersions

func FetchLatestVersions(ctx context.Context, repo, token string) (panel, agent *GitHubRelease, err error)

FetchLatestVersions delegates to updates.FetchLatestVersions.

type Instance

type Instance struct {
	ID                string    `json:"id"`
	AgentID           string    `json:"agent_id"`
	Name              string    `json:"name"`
	Version           string    `json:"version"`
	ConfigFingerprint string    `json:"config_fingerprint"`
	ConnectedUsers    int       `json:"connected_users"`
	ReadOnly          bool      `json:"read_only"`
	UpdatedAt         time.Time `json:"updated_at"`
}

Instance stores the Telemt runtime metadata discovered through an agent.

type Intervals

type Intervals struct {
	// JobsKeyEviction is how often the jobs service scans for
	// terminal-state idempotency keys to evict.
	JobsKeyEviction time.Duration
	// JobsKeyEvictionTTL is the age at which a terminal-state key is
	// evicted.
	JobsKeyEvictionTTL time.Duration
	// JobsAckExpiry is how often the jobs service scans for
	// acknowledged-but-result-less targets.
	JobsAckExpiry time.Duration
	// JobsAckExpiryTTL is the threshold after which an acknowledged
	// target with no result is transitioned to expired. Must match
	// the agent-side idempotency cache.
	JobsAckExpiryTTL time.Duration
	// Rollup is how often the timeseries rollup worker fires.
	Rollup time.Duration
	// MetricsPoller is the cadence for sampling derived gauges
	// (agent connected count, event-hub subscribers, job queue depth,
	// lockout count, DB pool stats).
	MetricsPoller time.Duration
}

Intervals bundles the worker / poller cadences that are inherent to the control-plane lifecycle (not tied to a single feature).

Q5.U-Q-04 introduced this struct; R-Q-04 wires it through Options and Server so operators (and tests) can override individual cadences without rebuilding the binary or threading new constants through every callsite. The defaults match the legacy package-level values.

func DefaultIntervals

func DefaultIntervals() Intervals

DefaultIntervals returns the values matching the legacy package-level constants. Tests that need a fast clock can construct an Intervals literal directly and pass it through Options.Intervals.

type MetricSnapshot

type MetricSnapshot struct {
	ID         string            `json:"id"`
	AgentID    string            `json:"agent_id"`
	InstanceID string            `json:"instance_id"`
	CapturedAt time.Time         `json:"captured_at"`
	Values     map[string]uint64 `json:"values"`
}

MetricSnapshot stores an aggregated view of a single agent or instance metric set.

type Options

type Options struct {
	Now            func() time.Time
	Users          []auth.User
	Store          storage.Store
	UIFiles        fs.FS
	PanelRuntime   PanelRuntime
	RequestRestart func() error
	// TrustedProxyCIDRs lists additional CIDR ranges whose X-Forwarded-For
	// header is trusted for rate-limit key extraction. Loopback addresses
	// are always trusted regardless of this setting.
	//
	// WARNING: When the control-plane runs behind a non-loopback reverse
	// proxy and this list is empty, every inbound request resolves to the
	// proxy's IP for rate-limit keying. All clients then share a single
	// bucket and will be throttled collectively. Always configure this
	// field to include every intermediate proxy/load-balancer CIDR.
	TrustedProxyCIDRs []*net.IPNet
	// EncryptionKey, when set, encrypts the CA private key at rest using
	// AES-256-GCM. The key is derived from this passphrase via SHA-256.
	// Existing unencrypted keys are transparently migrated on next save.
	EncryptionKey string
	// Logger is the structured logger for the server. If nil, slog.Default() is used.
	Logger *slog.Logger
	// Version is the panel version string (e.g. "v1.2.3" or "dev").
	Version string
	// CommitSHA is the git commit hash baked in at build time.
	CommitSHA string
	// BuildTime is the RFC3339 build timestamp baked in at build time.
	BuildTime string
	// MetricsScrapeToken, when non-empty, enables the GET /metrics endpoint
	// and requires callers to present `Authorization: Bearer <token>` with a
	// byte-for-byte match. When empty, the /metrics route is not registered
	// at all (silent opt-in) so production deployments that never set the env
	// var cannot accidentally expose runtime telemetry.
	MetricsScrapeToken string
	// Intervals overrides the default worker / poller cadences. Zero-valued
	// fields fall back to DefaultIntervals(). Tests use this to compress
	// retention sweeps and rollup scans into milliseconds.
	Intervals Intervals
	// LoginTimingFloor sets the wall-clock minimum every login response
	// (success or failure) is padded to (R-S-19). Zero (unset) falls
	// back to the production default of 150ms. Pass any negative value
	// to disable the pad entirely — tests use this to avoid burning
	// real wall-clock seconds in the suite.
	LoginTimingFloor time.Duration
}

Options defines the runtime dependencies used by the control-plane server.

type PanelRuntime

type PanelRuntime struct {
	HTTPListenAddress string
	HTTPRootPath      string
	AgentHTTPRootPath string
	PanelAllowedCIDRs []*net.IPNet
	GRPCListenAddress string
	TLSMode           string
	TLSCertFile       string
	TLSKeyFile        string
	RestartSupported  bool
	ConfigSource      string
	ConfigPath        string
}

PanelRuntime describes the currently applied network and restart runtime.

type PanelSettings

type PanelSettings struct {
	HTTPPublicURL      string `json:"http_public_url"`
	GRPCPublicEndpoint string `json:"grpc_public_endpoint"`
	UpdatedAt          int64  `json:"updated_at_unix"`
}

PanelSettings stores operator-managed public access settings for the panel.

type RetentionSettings

type RetentionSettings struct {
	TSRawSeconds          int `json:"ts_raw_seconds"`
	TSHourlySeconds       int `json:"ts_hourly_seconds"`
	TSDCSeconds           int `json:"ts_dc_seconds"`
	IPHistorySeconds      int `json:"ip_history_seconds"`
	EventSeconds          int `json:"event_history_seconds"`
	AuditEventSeconds     int `json:"audit_event_seconds"`
	MetricSnapshotSeconds int `json:"metric_snapshot_seconds"`
	// JobsSeconds bounds how long terminal jobs (succeeded/failed/
	// expired) live in the jobs table before the rollup loop deletes
	// them via PruneTerminalJobs (Q2.U-P-02).
	JobsSeconds int `json:"jobs_seconds"`
}

RetentionSettings controls how long timeseries data is kept before pruning.

type RuntimeDC

type RuntimeDC struct {
	DC                 int     `json:"dc"`
	AvailableEndpoints int     `json:"available_endpoints"`
	AvailablePct       float64 `json:"available_pct"`
	RequiredWriters    int     `json:"required_writers"`
	AliveWriters       int     `json:"alive_writers"`
	CoveragePct        float64 `json:"coverage_pct"`
	FreshAliveWriters  int     `json:"fresh_alive_writers"`
	FreshCoveragePct   float64 `json:"fresh_coverage_pct"`
	RTTMs              float64 `json:"rtt_ms"`
	Load               int     `json:"load"`
}

RuntimeDC stores one DC health row reported by the local Telemt runtime.

type RuntimeEvent

type RuntimeEvent struct {
	Sequence      uint64 `json:"sequence"`
	TimestampUnix int64  `json:"timestamp_unix"`
	EventType     string `json:"event_type"`
	Context       string `json:"context"`
}

RuntimeEvent stores one recent Telemt runtime event normalized by the agent.

type RuntimeMeWritersSummary

type RuntimeMeWritersSummary struct {
	ConfiguredEndpoints int     `json:"configured_endpoints"`
	AvailableEndpoints  int     `json:"available_endpoints"`
	CoveragePct         float64 `json:"coverage_pct"`
	FreshAliveWriters   int     `json:"fresh_alive_writers"`
	FreshCoveragePct    float64 `json:"fresh_coverage_pct"`
	RequiredWriters     int     `json:"required_writers"`
	AliveWriters        int     `json:"alive_writers"`
}

RuntimeMeWritersSummary carries the ME writers pool aggregate returned by Telemt.

type RuntimeSystemLoad

type RuntimeSystemLoad struct {
	CPUUsagePct      float64 `json:"cpu_usage_pct"`
	MemoryUsedBytes  uint64  `json:"memory_used_bytes"`
	MemoryTotalBytes uint64  `json:"memory_total_bytes"`
	MemoryUsagePct   float64 `json:"memory_usage_pct"`
	DiskUsedBytes    uint64  `json:"disk_used_bytes"`
	DiskTotalBytes   uint64  `json:"disk_total_bytes"`
	DiskUsagePct     float64 `json:"disk_usage_pct"`
	Load1M           float64 `json:"load_1m"`
	Load5M           float64 `json:"load_5m"`
	Load15M          float64 `json:"load_15m"`
	NetBytesSent     uint64  `json:"net_bytes_sent"`
	NetBytesRecv     uint64  `json:"net_bytes_recv"`
}

RuntimeSystemLoad carries server resource utilization metrics.

type RuntimeUpstream

type RuntimeUpstream struct {
	UpstreamID         int      `json:"upstream_id"`
	RouteKind          string   `json:"route_kind"`
	Address            string   `json:"address"`
	Healthy            bool     `json:"healthy"`
	Fails              int      `json:"fails"`
	EffectiveLatencyMs float64  `json:"effective_latency_ms"`
	Weight             int      `json:"weight"`
	LastCheckAgeSecs   int      `json:"last_check_age_secs"`
	Scopes             []string `json:"scopes,omitempty"`
}

RuntimeUpstream stores one upstream health row reported by the local Telemt runtime.

type Server

type Server struct {
	gatewayrpc.UnimplementedAgentGatewayServer
	// contains filtered or unexported fields
}

Server wires local-auth, inventory, jobs, and operator APIs into one HTTP surface.

func New

func New(options Options) *Server

func (*Server) Close

func (s *Server) Close()

Close stops background workers and drains pending writes. It should be called before closing the storage backend.

Shutdown ordering (P2-LOG-10 / M-R4 / P7-R6):

  1. batchWriter.StopWithTimeout(10s) FIRST — drains the audit-events queue (and the 7 other streams) before any background goroutine that might still be producing audits is shut down. This bounds the worst-case shutdown time at 10s so a wedged DB cannot hang the process indefinitely, while still giving the DB a realistic window to absorb in-flight rows.
  2. metrics / rollup goroutines stop afterwards.

Events enqueued AFTER this point may race with the final drain and can be dropped — upstream callers (HTTP handlers, gRPC streams) must stop before Close() runs to guarantee zero loss.

func (*Server) Connect

func (*Server) GRPCTLSConfig

func (s *Server) GRPCTLSConfig() *tls.Config

GRPCTLSConfig returns the TLS configuration used by the agent gateway listener.

func (*Server) Handler

func (s *Server) Handler() http.Handler

Handler returns the configured HTTP handler for the control-plane API.

func (*Server) RenewCertificate

RenewCertificate rotates the short-lived mTLS material for an authenticated agent.

func (*Server) StartupError

func (s *Server) StartupError() error

StartupError reports the first initialization error encountered while restoring persisted state.

type UpdateSettings

type UpdateSettings struct {
	CheckIntervalHours  int    `json:"check_interval_hours"`
	AutoUpdatePanel     bool   `json:"auto_update_panel"`
	AutoUpdateAgents    bool   `json:"auto_update_agents"`
	GitHubRepo          string `json:"github_repo"`
	GitHubToken         string `json:"github_token,omitempty"`
	AgentDownloadSource string `json:"agent_download_source"`
}

UpdateSettings controls how the panel checks for and applies updates.

type UpdateState

type UpdateState struct {
	LatestPanelVersion string `json:"latest_panel_version"`
	LatestAgentVersion string `json:"latest_agent_version"`
	PanelDownloadURL   string `json:"panel_download_url"`
	PanelChecksumURL   string `json:"panel_checksum_url"`
	PanelSignatureURL  string `json:"panel_signature_url"`
	AgentDownloadURL   string `json:"agent_download_url"`
	AgentChecksumURL   string `json:"agent_checksum_url"`
	AgentSignatureURL  string `json:"agent_signature_url"`
	PanelChangelog     string `json:"panel_changelog"`
	AgentChangelog     string `json:"agent_changelog"`
	LastCheckedAt      int64  `json:"last_checked_at"`
}

UpdateState caches the latest known versions from GitHub.

type UserAppearance

type UserAppearance struct {
	Theme     string `json:"theme"`
	Density   string `json:"density"`
	HelpMode  string `json:"help_mode"`
	UpdatedAt int64  `json:"updated_at_unix"`
}

UserAppearance stores the current user's persisted appearance preferences.

Jump to

Keyboard shortcuts

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