web

package
v0.0.274 Latest Latest
Warning

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

Go to latest
Published: Jul 17, 2026 License: MIT Imports: 31 Imported by: 0

Documentation

Overview

Package web is satelle's local web server — a project page for one repo, rendered through verb.Dispatch (the same seam the CLI uses). Viewing needs no auth; the local data is served unauthenticated. It is the satellites portal style brought to the local tier: tabbed panels, an SSE realtime doorbell, inline expand/collapse, and filter chips. An OPTIONAL hosted-server sign-in (auth.go) lets the UI authenticate to satelle-server via the same OAuth client and per-user credential store the CLI uses — additive, never required for local operation. Static assets and templates are embedded so the binary stays self-contained.

Index

Constants

View Source
const ClientAddrHeader = "X-Satelle-Client-Addr"

ClientAddrHeader carries the TRUE client remote address the supervisor saw, into each proxied request (sty_ffe53865). A supervised child's own r.RemoteAddr is always the supervisor's loopback socket, so the settings-write loopback gate cannot judge the real caller from it. The supervisor Sets (never Adds) this header — overwriting any inbound value — so a client cannot spoof it; children bind 127.0.0.1 only, which is what makes the header trustworthy.

View Source
const ProjectsHeader = "X-Satelle-Projects"

ProjectsHeader carries the supervisor's live project list (slug, name, and path) into each proxied request, so a supervised child's breadcrumb can render the project switcher without knowing the registry or recomputing slugs (sty_2bc00a9d). The supervisor is the single source of the slug table (request routing), so the child never disagrees with it. Path lets the switcher disambiguate same-name projects (sty_de54f9fb).

Variables

This section is empty.

Functions

func AllocPort added in v0.0.8

func AllocPort() (int, error)

AllocPort returns a free loopback TCP port. There is a small window between close and the child binding it, acceptable for local supervision.

func Build

func Build(a *app.App) http.Handler

Build is the thin handler-only constructor used by tests (no poller).

func EncodeProjects added in v0.0.109

func EncodeProjects(projects []Project) string

EncodeProjects serializes each project's slug, name, and path for ProjectsHeader: JSON, base64url-wrapped so a non-ASCII repo basename never yields a spec-hostile header value. Empty on marshal error.

func ProjectsPage added in v0.0.9

func ProjectsPage(w http.ResponseWriter, r *http.Request, projects []Project, failed []FailedProject)

ProjectsPage renders the / landing: every served project with live counts and a link to its page at /<slug>/.

func RequestLog added in v0.0.108

func RequestLog(next http.Handler, logPath string, cfg logfile.Config) http.Handler

RequestLog wraps next so every request appends one grep-friendly line to the server log at logPath through the shared rotating writer (internal/logfile), with the same daily+size rotation as the other flat evidence logs. Best-effort: a log write never affects the response. It is wired at the serve listener (not web.New), so httptest servers stay log-free and each serve process logs to its own repo's .satelle/logs/server.log.

Line: <rfc3339>\t<LEVEL>\t<method>\t<path>\t<status>\t<duration_ms>[\t<note>]. LEVEL is INFO, WARN when slow (SSE /events exempt — it is open for its lifetime), or ERROR for status >= 500 or a recovered panic. Only r.URL.Path is logged (no query string) to keep lines short and avoid logging anything sensitive-ish.

http.ErrAbortHandler is re-panicked (not recovered), so the net/http server aborts and closes the connection as designed — recovering it would return a mid-stream (aborted-SSE) connection to the keep-alive pool, hanging the next request that reuses it (sty_fa24469a).

func SetBasePath added in v0.0.9

func SetBasePath(p string)

SetBasePath sets the mount prefix (trailing slash trimmed). Call before New.

func Slugify added in v0.0.8

func Slugify(name string) string

Slugify turns a project name into a URL-safe slug: lowercased, with any run of non [a-z0-9] folded to a single '-', trimmed. Empty input yields "project".

func WaitHealthy added in v0.0.8

func WaitHealthy(ctx context.Context, port int, timeout time.Duration) bool

WaitHealthy polls a child's /healthz until it answers 200 or the deadline passes. Returns true once healthy. A child's routes are mounted at the root (only its rendered <base href> carries the slug), so /healthz is unprefixed.

Types

type FailedProject added in v0.0.69

type FailedProject struct {
	Name, Path, Err string
}

FailedProject is a registered project whose child could not be served — shown on the landing as an errored row rather than silently omitted (sty_4ea4d4df), so "added but not shown" is diagnosable.

type Project added in v0.0.8

type Project struct {
	Slug string
	Name string
	Path string
}

Project is one served project: its display name, repo path, and URL slug. Every project is uniform — served under its own /<slug>/.

func DecodeProjects added in v0.0.109

func DecodeProjects(header string) []Project

DecodeProjects reverses EncodeProjects. ANY error (absent, malformed, spoofed) yields nil, so a bad header degrades to no switcher rather than a 500.

type Server added in v0.0.2

type Server struct {
	Handler http.Handler
	// contains filtered or unexported fields
}

Server is the local web server: an http.Handler plus the realtime hub.

func New added in v0.0.2

func New(a *app.App) *Server

New wires the server for the given bootstrap. It registers the verb-change notifier so web-initiated mutations ring the doorbell instantly; cross- process mutations (CLI edits) are picked up by StartRealtime's poller.

func (*Server) Publish added in v0.0.69

func (s *Server) Publish(topic string)

StartRealtime runs the cross-process DB-change poller until ctx is cancelled. The CLI and the server are separate processes sharing one sqlite file, so the in-process notifier alone can't see CLI edits; the poller fingerprints each panel and rings the doorbell when one changes. interval<=0 uses 1.5s. Publish fans a topic to every connected /events client — the seam an OUTSIDE supervisor uses to doorbell pages the poller can't see (e.g. the / landing's "projects" topic when the served set changes; sty_4ea4d4df).

func (*Server) StartRealtime added in v0.0.2

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

Jump to

Keyboard shortcuts

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