server

package
v0.1.23 Latest Latest
Warning

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

Go to latest
Published: Mar 22, 2026 License: MIT Imports: 26 Imported by: 0

Documentation

Index

Constants

This section is empty.

Variables

This section is empty.

Functions

func BearerAuth

func BearerAuth(token string, keyStore *KeyStore) func(http.Handler) http.Handler

BearerAuth returns middleware that validates Bearer token authentication. It checks the env-var token first (backwards compatible), then falls back to the KeyStore if provided. If both token and keyStore are empty/nil, the middleware is a no-op (passes through).

func BearerOrSessionAuth added in v0.1.21

func BearerOrSessionAuth(token string, keyStore *KeyStore, sessions *SessionManager) func(http.Handler) http.Handler

BearerOrSessionAuth returns middleware that accepts EITHER a valid Bearer token (for programmatic/MCP access) OR a valid session cookie (for SPA browser access). If auth is not configured (empty token + nil keyStore + nil sessions), the middleware is a no-op.

func CFAccessMiddleware added in v0.1.23

func CFAccessMiddleware(teamDomain string, sessions cfSessionStore) func(http.Handler) http.Handler

CFAccessMiddleware auto-issues a session when a valid Cloudflare Access JWT is present in the Cf-Access-Jwt-Assertion header. Only active when teamDomain is non-empty (CF_ACCESS_TEAM_DOMAIN env var).

On valid JWT: create session → set cookie → redirect to / On missing/invalid JWT: fall through to next handler (no error returned) On disabled (teamDomain=""): fall through immediately

The middleware only intercepts GET / and GET /login; all other paths pass through.

func GetSessionID added in v0.1.21

func GetSessionID(r *http.Request) string

GetSessionID reads the session ID from the request cookie.

Types

type APIKey

type APIKey struct {
	Name      string   `yaml:"name"`
	Hash      string   `yaml:"hash"`                // SHA-256 hex of the plaintext key
	Projects  []string `yaml:"projects"`            // empty = all projects
	Scope     string   `yaml:"scope,omitempty"`     // "admin", "worker", or "" (default = admin)
	WorkerID  string   `yaml:"worker_id,omitempty"` // required when scope=worker
	CreatedAt string   `yaml:"created_at"`          // RFC3339
}

APIKey represents a stored API key with metadata.

type APIRegistrar

type APIRegistrar interface {
	RegisterRoutes(mux *http.ServeMux)
}

APIRegistrar can register REST API routes on an http.ServeMux.

type Config

type Config struct {
	Addr               string           // listen address, e.g. ":8080"
	AuthToken          string           //nolint:gosec // G117: config field, not a hardcoded secret
	KeyStore           *KeyStore        // YAML-backed API key store (may be nil)
	SessionFile        string           // optional path for persistent session storage (survive restarts)
	MCPHandler         http.Handler     // optional MCP protocol handler; nil keeps the 501 placeholder
	APIHandler         APIRegistrar     // optional REST API handler; nil keeps the 501 placeholder
	PressureProvider   PressureProvider // optional; /healthz omits pressure field when nil
	CFAccessTeamDomain string           // Cloudflare Access team domain; empty = CF auto-login disabled
}

Config holds server configuration.

type Hub added in v0.1.22

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

Hub manages WebSocket client connections and broadcasts events.

func NewHub added in v0.1.22

func NewHub(logger *zap.Logger) *Hub

NewHub creates a Hub ready to Run.

func (*Hub) Broadcast added in v0.1.22

func (h *Hub) Broadcast(data []byte)

Broadcast enqueues data for delivery to all connected clients. It never blocks; if the broadcast channel is full the message is dropped.

func (*Hub) Run added in v0.1.22

func (h *Hub) Run(ctx context.Context)

Run starts the hub event loop. It blocks until ctx is cancelled.

type KeyStore

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

KeyStore manages API keys stored in a YAML file.

func NewKeyStore

func NewKeyStore(path string) (*KeyStore, error)

NewKeyStore loads a KeyStore from the given YAML file path. If the file does not exist, it is created with an empty key list.

func (*KeyStore) Create

func (ks *KeyStore) Create(name string, projects []string) (string, error)

Create generates a new API key, stores its hash, and returns the plaintext. The plaintext is only available at creation time.

func (*KeyStore) CreateScoped added in v0.1.13

func (ks *KeyStore) CreateScoped(name string, projects []string, scope, workerID string) (plaintext string, err error)

CreateScoped generates a new API key with scope and optional worker ID. Scope must be "admin", "worker", or "" (treated as admin). When scope is "worker", workerID is required.

func (*KeyStore) List

func (ks *KeyStore) List() []APIKey

List returns all stored keys. Hashes are included for display purposes.

func (*KeyStore) Revoke

func (ks *KeyStore) Revoke(name string) error

Revoke removes a key by name.

func (*KeyStore) Validate

func (ks *KeyStore) Validate(token string) (*APIKey, bool)

Validate checks a plaintext token against all stored key hashes. Returns the matching APIKey and true if found, or nil and false otherwise. Uses constant-time comparison to prevent timing attacks.

func (*KeyStore) ValidateForProject

func (ks *KeyStore) ValidateForProject(token, project string) bool

ValidateForProject checks a plaintext token and verifies it has access to the given project. Unscoped keys (empty Projects) have access to all projects.

func (*KeyStore) ValidateWorker added in v0.1.13

func (ks *KeyStore) ValidateWorker(token, workerID string) bool

ValidateWorker checks a token, verifies it is authorized for worker operations, and that the workerID matches the key's WorkerID field. Admin-scoped keys (scope="" or scope="admin") pass unconditionally.

type PressureProvider added in v0.1.11

type PressureProvider interface {
	Pressure() string
}

PressureProvider returns the current resource pressure level string ("low", "moderate", "high", or "critical"). Used by /healthz.

type Server

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

Server is the main HTTP server.

func New

func New(cfg Config, logger *zap.Logger) *Server

New creates a new Server with routes registered.

func (*Server) Addr

func (s *Server) Addr() string

Addr returns the address the server is listening on. This is useful in tests when Addr is ":0" (random port). Safe for concurrent use.

func (*Server) Handler

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

Handler returns the underlying http.Handler for use in httptest.NewServer.

func (*Server) Hub added in v0.1.22

func (s *Server) Hub() *Hub

Hub returns the WebSocket hub. Callers can call Hub().Broadcast to push events to all connected dashboard clients.

func (*Server) Sessions added in v0.1.21

func (s *Server) Sessions() *SessionManager

Sessions returns the session manager (may be nil if auth is not configured). Exposed for the MCP-only listener to share sessions with the main server.

func (*Server) Shutdown

func (s *Server) Shutdown(ctx context.Context) error

Shutdown gracefully stops the server and cleans up sessions.

func (*Server) Start

func (s *Server) Start(ctx context.Context) error

Start begins listening. It blocks until ctx is cancelled or an error occurs. When ctx is cancelled, Start calls Shutdown and returns nil.

type Session added in v0.1.21

type Session struct {
	ID        string    `json:"id"`
	CreatedAt time.Time `json:"created_at"`
	ExpiresAt time.Time `json:"expires_at"`
}

Session represents an authenticated browser session.

type SessionManager added in v0.1.21

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

SessionManager stores browser sessions in memory with optional disk persistence. Acceptable for single-server deployment.

func NewSessionManager added in v0.1.21

func NewSessionManager() *SessionManager

NewSessionManager creates an in-memory SessionManager and starts background cleanup.

func NewSessionManagerWithFile added in v0.1.22

func NewSessionManagerWithFile(path string) *SessionManager

NewSessionManagerWithFile creates a SessionManager that persists sessions to disk. On creation, any previously saved valid sessions are loaded from the file.

func (*SessionManager) ClearCookie added in v0.1.21

func (sm *SessionManager) ClearCookie(w http.ResponseWriter)

ClearCookie removes the session cookie from the browser.

func (*SessionManager) Create added in v0.1.21

func (sm *SessionManager) Create() (string, error)

Create generates a new session, persists it, and returns its ID.

func (*SessionManager) Delete added in v0.1.21

func (sm *SessionManager) Delete(id string)

Delete removes a session (logout) and persists the change.

func (*SessionManager) SetCookie added in v0.1.21

func (sm *SessionManager) SetCookie(w http.ResponseWriter, sessionID string)

SetCookie writes the session cookie to the response.

func (*SessionManager) Stop added in v0.1.21

func (sm *SessionManager) Stop()

Stop halts the background cleanup goroutine.

func (*SessionManager) Validate added in v0.1.21

func (sm *SessionManager) Validate(id string) bool

Validate checks whether a session ID is valid and not expired.

Jump to

Keyboard shortcuts

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