webui

package
v1.1.3 Latest Latest
Warning

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

Go to latest
Published: Aug 15, 2026 License: MIT Imports: 24 Imported by: 0

Documentation

Overview

Package webui serves the agent's control center: a privileged HTTP API under /control and the console that drives it, whose source lives in frontend/ and whose build is embedded by embed.go.

It imports no agent internals; everything it needs is declared here as Host and supplied by the caller.

Index

Constants

This section is empty.

Variables

This section is empty.

Functions

func Console

func Console() http.Handler

Console serves the built console, or nil if no build is embedded.

Types

type AgentInfo

type AgentInfo struct {
	Name      string    `json:"name"`
	Version   string    `json:"version"`
	Dev       bool      `json:"dev"`
	Running   bool      `json:"running"`
	StartedAt time.Time `json:"startedAt"`
	UptimeSec int64     `json:"uptimeSec"`
	ConfigDir string    `json:"configDir"`
	Platform  string    `json:"platform"`
}

AgentInfo covers identity and lifecycle.

type Auth

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

Auth mints and verifies the credentials for the control surface. Handoff tokens are single-use: the tray puts one in the URL it opens and the console exchanges it for a session cookie, so a leaked URL is already spent.

func NewAuth

func NewAuth() *Auth

NewAuth returns an empty credential store.

func (*Auth) MintHandoff

func (a *Auth) MintHandoff() (string, error)

MintHandoff issues a single-use token for the tray to place in the console URL it opens.

func (*Auth) RedeemHandoff

func (a *Auth) RedeemHandoff(token string) (string, bool)

RedeemHandoff exchanges a handoff token for a session token, consuming it. A token that is unknown, already redeemed or expired returns false.

func (*Auth) RevokeAll

func (a *Auth) RevokeAll()

RevokeAll ends every session and discards unclaimed tokens.

func (*Auth) RevokeSession

func (a *Auth) RevokeSession(token string)

RevokeSession ends one session, used when the console signs out.

func (*Auth) SessionCount

func (a *Auth) SessionCount() int

SessionCount returns the number of live sessions, for display.

func (*Auth) ValidSession

func (a *Auth) ValidSession(token string) bool

ValidSession reports whether a session token is current.

type CaptureInfo

type CaptureInfo struct {
	LogEntries int `json:"logEntries"`
	LogSeq     int `json:"logSeq"`
}

CaptureInfo reports the log ring's state.

type CertInfo

type CertInfo struct {
	Subject     string    `json:"subject"`
	Issuer      string    `json:"issuer"`
	NotBefore   time.Time `json:"notBefore"`
	NotAfter    time.Time `json:"notAfter"`
	ExpiresInHr int64     `json:"expiresInHr"`
	Expired     bool      `json:"expired"`
	SelfSigned  bool      `json:"selfSigned"`
	Hosts       []string  `json:"hosts"`
	Fingerprint string    `json:"fingerprint"`
}

CertInfo describes the certificate being served.

type Client

type Client struct {
	ID          string
	Origin      string
	RemoteAddr  string
	UserAgent   string
	ConnectedAt time.Time
	Writes      int
	Locks       int
}

Client is the console's view of a connected client application.

type ClientInfo

type ClientInfo struct {
	ID          string    `json:"id"`
	Origin      string    `json:"origin,omitempty"`
	RemoteAddr  string    `json:"remoteAddr"`
	UserAgent   string    `json:"userAgent,omitempty"`
	ConnectedAt time.Time `json:"connectedAt"`
	Writes      int       `json:"writes"`
	Locks       int       `json:"locks"`
}

ClientInfo is a connected client application as the console lists it.

type Config

type Config struct {
	// Host is the agent under administration. Required.
	Host Host

	// Logs is the ring the console tails. Nil disables the log views.
	Logs *logbuf.Ring

	Name    string
	Version string
	Dev     bool
}

Config assembles a Server.

type DeviceInfo

type DeviceInfo struct {
	ID       string    `json:"id"`
	Name     string    `json:"name"`
	Platform string    `json:"platform"`
	PairedAt time.Time `json:"pairedAt"`
	LastSeen time.Time `json:"lastSeen,omitempty"`
	Online   bool      `json:"online"`
}

DeviceInfo is a paired device as the console lists it.

type Host

type Host interface {
	Running() bool
	ConfigDir() string
	StartAgent() error
	StopAgent()
	QuitAgent()
	RestartServers() error

	ReaderMode() string
	DevicePath() string
	AvailableDevices() []string
	AllCardTypes() []string
	// CurrentCard reports the tag on the reader, if any.
	CurrentCard() (uid, cardType string, present bool)
	RemoteDevices() (total, active int)
	SelectDevice(devicePath string) error

	Port() int
	BootstrapPort() int
	CertFile() string
	TLSEnabled() bool
	LocalIPs() []string
	ClientCount() int
	Clients() []Client
	DisconnectClient(id string) error

	APISecret() string
	RotateAPISecret() (string, error)
	PublicKeyPin() string
	PairingPIN() string
	RotatePairingPIN() (string, error)
	CAInstalled() bool
	CAFingerprint() (string, error)
	// InstallCA puts a local authority in the system trust store, which is what
	// makes a browser accept the agent. Prompts for a password.
	InstallCA() error
	RegenerateCertificate() error

	PairedDevices() []PairedDevice
	RevokeDevice(id string) error
	RevokeAllDevices() error
	RequirePairedDevice() bool

	AllowedOrigins() []string
	BlockedOrigins() []string
	OriginCheckDisabled() bool
	AllowOrigin(origin string) error
	RevokeOrigin(origin string) error
	SetOriginCheckDisabled(bool)

	Settings() settings.Settings
	// SaveSettings persists a mutation and applies it to the running agent.
	SaveSettings(mutate func(*settings.Settings)) (settings.Settings, error)
}

Host is what the console needs from the agent it administers. Stating it as one interface makes the complete list of what the console can do readable in one place.

type OriginsInfo

type OriginsInfo struct {
	Allowed  []string `json:"allowed"`
	Blocked  []string `json:"blocked"`
	AllowAny bool     `json:"allowAny"`
}

OriginsInfo is the browser allowlist and what it has recently refused.

type PairedDevice

type PairedDevice struct {
	ID       string
	Name     string
	Platform string
	PairedAt time.Time
	LastSeen time.Time
	Online   bool
}

PairedDevice is the console's view of a stored device credential.

type ReaderInfo

type ReaderInfo struct {
	Mode          string   `json:"mode"`
	DevicePath    string   `json:"devicePath"`
	Available     []string `json:"available"`
	CardPresent   bool     `json:"cardPresent"`
	CardUID       string   `json:"cardUID,omitempty"`
	CardType      string   `json:"cardType,omitempty"`
	AllCardTypes  []string `json:"allCardTypes"`
	RemoteDevices int      `json:"remoteDevices"`
	RemoteActive  int      `json:"remoteActive"`
}

ReaderInfo covers the NFC reader and the card currently on it.

type SecurityInfo

type SecurityInfo struct {
	APISecret           string    `json:"apiSecret"`
	PairingPIN          string    `json:"pairingPIN,omitempty"`
	PublicKeyPin        string    `json:"publicKeyPin,omitempty"`
	RequirePairedDevice bool      `json:"requirePairedDevice"`
	CAInstalled         bool      `json:"caInstalled"`
	CAFingerprint       string    `json:"caFingerprint,omitempty"`
	Cert                *CertInfo `json:"cert,omitempty"`
	ControlSessions     int       `json:"controlSessions"`
}

SecurityInfo covers the credentials and the certificate. The API secret is included in full: the console's gate is a higher bar than reading the file it comes from.

type Server

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

Server serves the console's privileged API. See auth.go for the gate.

Tag reading and writing are absent by design: the console does those over the ordinary client endpoint, so there is one implementation of the write path.

func New

func New(config Config) *Server

New builds the console API over a host.

func (*Server) ConsoleURL

func (c *Server) ConsoleURL() (string, error)

ConsoleURL returns the console address carrying a fresh single-use token.

func (*Server) Handler

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

Handler returns the control routes. Everything but the session handoff runs through requireSession; the handoff is what a browser arrives at without a session and carries its own single-use credential.

func (*Server) NotifyChange

func (c *Server) NotifyChange()

NotifyChange pushes fresh state to connected consoles. Safe from any goroutine, and coalesces.

type ServerInfo

type ServerInfo struct {
	Port          int      `json:"port"`
	BootstrapPort int      `json:"bootstrapPort"`
	TLS           bool     `json:"tls"`
	ClientURL     string   `json:"clientURL"`
	DeviceURL     string   `json:"deviceURL"`
	PairingURL    string   `json:"pairingURL,omitempty"`
	LocalIPs      []string `json:"localIPs"`
	Clients       int      `json:"clients"`
}

ServerInfo covers the listener and the URLs a client would use.

type State

type State struct {
	Agent    AgentInfo         `json:"agent"`
	Reader   ReaderInfo        `json:"reader"`
	Server   ServerInfo        `json:"server"`
	Security SecurityInfo      `json:"security"`
	Settings settings.Settings `json:"settings"`
	Devices  []DeviceInfo      `json:"devices"`
	Clients  []ClientInfo      `json:"clients"`
	Origins  OriginsInfo       `json:"origins"`
	Capture  CaptureInfo       `json:"capture"`
}

State is the whole picture the console renders from. Sent as a snapshot rather than deltas, so the console can never show a half-applied combination of settings.

Jump to

Keyboard shortcuts

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