web

package
v0.2.2 Latest Latest
Warning

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

Go to latest
Published: Jun 17, 2026 License: Apache-2.0 Imports: 65 Imported by: 0

Documentation

Overview

Package web implements the HTTP control plane: the fail-closed request pipeline (plan §5), the auth/session handlers, and the admin UI shell. It binds loopback only (plan §3); the managed edge fronts the public ports.

Index

Constants

This section is empty.

Variables

This section is empty.

Functions

func CSRFToken

func CSRFToken(ctx context.Context) string

CSRFToken returns the per-request CSRF token for template injection.

func ClientIP

func ClientIP(ctx context.Context) netip.Addr

ClientIP returns the resolved client IP (the real peer, or the single overwritten XFF value when the peer is a trusted proxy). Zero value if unset.

func SessionFrom

func SessionFrom(ctx context.Context) *session.Session

SessionFrom returns the loaded session, or nil if unauthenticated.

func TokenID

func TokenID(ctx context.Context) string

TokenID returns the authenticated API token id (for audit), or "" on the browser plane.

Types

type Deps

type Deps struct {
	DB          *store.DB
	ConfigPath  string // for SIGHUP allowlist+auth reload
	Log         *slog.Logger
	Monitor     *monitor.Monitor
	OpsStore    *ops.ConfigStore
	Prober      *ops.Prober
	Runner      *dockerexec.Runner
	Docker      *docker.Client
	EnvStore    *envstore.Store
	CfgStore    *cfgstore.Store
	GitStore    *gitstore.Store
	ProvStore   *provstore.Store
	SetupStore  *setupstore.Store
	AlertStore  *alertstore.Store
	EdgeRoutes  *edge.RouteStore
	EdgeRecon   *edge.Reconciler            // nil when the edge isn't owned (external/unavailable)
	EdgeReason  string                      // why the edge isn't owned (banner), "" when owned
	L4Routes    *l4.RouteStore              // managed L4 (TCP/UDP) routes (nil when L4 LB disabled)
	L4Reconcile func(context.Context) error // push the L4 route set to the nginx-stream LB (nil when disabled)
	SelfHeal    *selfheal.Store             // supervisor FSM + expected_down leases (may be nil)
	Scaling     *scale.Store                // auto-scaling policies + state (may be nil)
	DockerSem   *dockerexec.Semaphore       // global one-docker-child semaphore (shared with Runner)
	APITokens   *apitoken.Store             // scoped read/deploy API tokens (M19; may be nil → /api/v1 disabled)
	Backups     *backupstore.Store          // encrypted Helmsman-state backups (may be nil)
}

Deps are the (mostly optional) collaborators a Server uses. Anything nil degrades gracefully (e.g. nil mon → "collecting…"; nil runner → write plane shown disabled).

type Server

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

Server holds everything the request pipeline needs. Construct with New.

func New

func New(cfg *config.Config, d Deps) (*Server, error)

New builds a Server from a validated config and its dependencies.

func (*Server) Handler

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

Handler assembles the full middleware chain in pipeline order.

func (*Server) Reload

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

Reload re-reads the config file and hot-swaps the allowlist + auth (plan §5.1). On any validation error the current state is kept (fail-closed: a bad edit never widens or breaks the running policy).

func (*Server) Remediate

func (s *Server) Remediate(ctx context.Context, app monitor.App, service string, rung selfheal.Rung) error

Remediate makes *Server the supervisor's Actioner: it runs the rung through the SAME write path the operator uses (env render, §5.6 validation + config-file materialization for recreate/redeploy), but via RunHeld — the supervisor's safety gate already holds the one-docker-child semaphore, so re-acquiring would deadlock. Authority never widens what may run: a protected project is refused here too.

func (*Server) Run

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

Run starts the loopback HTTP server and blocks until ctx is cancelled.

func (*Server) RunGitPoller

func (s *Server) RunGitPoller(ctx context.Context, interval time.Duration)

RunGitPoller is the "just connect the repo and it works" loop: it FETCHES every connected repo so change-detection needs NO webhook setup. It is READ-PLANE ONLY — it never deploys; it surfaces an "update available" the operator deploys with a click (push-to-deploy stays an explicit opt-in via the webhook + auto_deploy, never this loop). A fetch never mutates a running app, and the loop is serialized through the same single-flight gate as deploys, so it can never pile up docker/git children.

Because Helmsman never auto-deploys, fetching when nobody is looking is wasted work — so the loop only fetches while a focused dashboard is open (the heartbeat above). When the operator opens/returns to the dashboard, the next tick fetches.

interval <= 0 disables polling. Blocks until ctx is cancelled.

func (*Server) Scale

func (s *Server) Scale(ctx context.Context, appProject, service string, replicas int) error

Scale makes *Server the auto-scaler's Scaler: it changes a service's replica count with a static-argv `docker compose up -d --no-deps --no-recreate --scale <svc>=<n>` through the gated write path (env render + §5.6 validation), via RunHeld — the scaler's safety gate already holds the one-docker-child semaphore. A protected project is refused (authority never widens what may run).

func (*Server) SetCircuitClearer

func (s *Server) SetCircuitClearer(c func(project, service string))

SetCircuitClearer wires the supervisor's clear-circuit entry point (set by cmd_serve after both the server and the watcher exist — avoids an import cycle).

Jump to

Keyboard shortcuts

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