adminui

package
v0.7.7 Latest Latest
Warning

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

Go to latest
Published: Jun 14, 2026 License: MIT Imports: 20 Imported by: 0

Documentation

Overview

Package adminui serves the local-only configuration web UI for outpost.

The server binds its own loopback listener (default 127.0.0.1:17777, override via $OUTPOST_ADMIN_ADDR). It is intentionally not part of the main HTTP server that the matrix tunnel proxies — admin is local-only by design.

On first run (no config file on disk yet) the admin API is unauthenticated: the listener is loopback-only, so any reachable caller is the OS user who just launched the binary. Once a config exists the gate engages and every API call must carry an outpost_admin session cookie minted by POST /api/login (which verifies the running OS user's password via hostauth).

Business-logic operations (validate / mutate FileConfig / mutate live registries / debounce restart) live in internal/agent/admincore so the MCP server can share them. This package is now a thin HTTP layer: session-cookie auth, JSON binding, error→status mapping.

Index

Constants

View Source
const DefaultAdminAddr = "127.0.0.1:17777"

DefaultAdminAddr is the loopback listener address the admin UI binds when neither $OUTPOST_ADMIN_ADDR nor --admin-addr is set.

Variables

This section is empty.

Functions

This section is empty.

Types

type Deps

type Deps struct {
	// Core, when non-nil, is the shared admincore.Server that mutation
	// handlers dispatch into. When nil, New() builds one from the
	// legacy fields below — the test path.
	Core *admincore.Server

	// ListenAddr is the loopback address+port the admin server binds.
	// Defaults to 127.0.0.1:17777 if empty.
	ListenAddr string
	// Auth verifies the running OS user's password on POST /api/login.
	Auth hostauth.Authenticator
	// SessionKey is the HMAC secret used to sign admin-UI session
	// cookies. Persisting it across restarts is what keeps the admin
	// logged in when a built-in toggle re-execs the binary.
	SessionKey []byte

	// MCPEndpoint is the URL the operator pastes into .mcp.json. Set
	// by main.go after constructing mcpapi. Empty when the MCP server
	// isn't wired (test paths).
	MCPEndpoint string
	// MCPToken returns the currently-accepted bearer (mcpapi rotates
	// it in memory; this closure always reads the live value).
	MCPToken func() string
	// RotateMCPToken mints a fresh token, persists it, swaps mcpapi's
	// in-memory copy, and returns the new value.
	RotateMCPToken func() (string, error)

	// OnShutdown, when set, is called once on context cancel right
	// before http.Server.Shutdown begins. Used by main.go to close
	// long-lived MCP SSE sessions so Shutdown doesn't have to wait
	// for them to drain (which would otherwise force `outpost stop`
	// into its SIGKILL fallback after 5 seconds). Synchronous; runs
	// in the Serve goroutine, so keep it bounded.
	OnShutdown func()

	ConfigPath          string
	Apps                *agent.AppRegistry
	Outbound            *agent.OutboundManager
	Restart             func()
	CloudboxBase        string
	CloudboxAccessToken string
	AgentName           string
	LLMPoolStatus       func() LLMPoolStatusView
}

Deps is what main.go threads in when constructing the admin server.

Two construction modes:

  1. Production (main.go): supply Core, plus the HTTP-only fields (ListenAddr, Auth, SessionKey). The admincore.Server is shared with mcpapi so both surfaces see the same live state, the same file-save mutex, and the same restart-debounce timer.

  2. Test convenience: leave Core nil and supply the legacy fields (ConfigPath, Apps, Outbound, ...). New() then constructs an admincore.Server internally.

type LLMPoolStatusView

type LLMPoolStatusView = admincore.LLMPoolStatusView

LLMPoolStatusView is re-exported from admincore so existing callers (main.go, tests) keep working without an import shuffle.

type Server

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

Server is the admin HTTP server. Construct with New, then call Serve.

func New

func New(deps Deps) (*Server, error)

New builds the admin server and binds its listener. The returned Server is not yet serving — call Serve.

func (*Server) Addr

func (s *Server) Addr() string

Addr returns the bound loopback address.

func (*Server) Engine

func (s *Server) Engine() *gin.Engine

Engine returns the underlying gin engine. mcpapi mounts its handler at /mcp/* here so MCP and admin UI share one loopback listener (one URL the operator copy-pastes, one port the firewall sees). The bearer-token middleware lives inside mcpapi — adminui doesn't see /mcp/* traffic; the route is registered after adminui's own routes, so admin's session-cookie middleware never inspects it.

func (*Server) Serve

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

Serve runs until ctx is canceled, then shuts the HTTP server down.

func (*Server) SetMCPEndpoint

func (s *Server) SetMCPEndpoint(url string)

SetMCPEndpoint backfills the URL the SPA's "Show .mcp.json snippet" panel renders. main.go calls this after the listener is bound (the URL isn't known earlier because :0 may resolve to a random port).

func (*Server) URL

func (s *Server) URL() string

URL is a convenience for the message printed to the console.

type Suggestion

type Suggestion = admincore.Suggestion

Suggestion is re-exported from admincore for backward compat with tests that reference the name unqualified.

Jump to

Keyboard shortcuts

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