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
- func AllocPort() (int, error)
- func Build(a *app.App) http.Handler
- func EncodeProjects(projects []Project) string
- func ProjectsPage(w http.ResponseWriter, r *http.Request, projects []Project, ...)
- func RequestLog(next http.Handler, logPath string, cfg logfile.Config) http.Handler
- func SetBasePath(p string)
- func Slugify(name string) string
- func WaitHealthy(ctx context.Context, port int, timeout time.Duration) bool
- type FailedProject
- type Project
- type Server
Constants ¶
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.
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
AllocPort returns a free loopback TCP port. There is a small window between close and the child binding it, acceptable for local supervision.
func EncodeProjects ¶ added in v0.0.109
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
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
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
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
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
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
Server is the local web server: an http.Handler plus the realtime hub.
func New ¶ added in v0.0.2
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
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).