web

package
v0.1.0 Latest Latest
Warning

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

Go to latest
Published: Oct 4, 2026 License: MIT Imports: 26 Imported by: 0

Documentation

Overview

Package web serves the Wherefolk UI over HTTP.

The server binds loopback only. That is a security property, not a setting: ADR-0001 removed authentication on the grounds that the tailnet authenticates and the binary cannot be reached from beyond the host. See ADR-0007.

Index

Constants

View Source
const Host = "127.0.0.1"

Host is the only interface the server ever binds. It is deliberately not configurable; only the port is. See ADR-0007.

Variables

This section is empty.

Functions

This section is empty.

Types

type Clock

type Clock func() time.Time

Clock reports the current time. Injected because an export's content depends on the date — ages are computed at export time (§5.7) — so tests must pin it.

type Exporter

type Exporter interface {
	PDF(ctx context.Context, d render.Directory) ([]byte, error)
	SVG(ctx context.Context, d render.Directory) ([][]byte, error)
}

Exporter compiles a filtered Directory. render.Renderer satisfies it; it is an interface so this package's tests need no typst binary, and so the web layer holds no path to a template or a binary (see Meta).

type Meta

type Meta struct {
	DocumentPath string

	// TypstVersion and TemplatePath are what main learned when it verified the
	// renderer at startup. They are strings rather than a render.Renderer
	// because this package never invokes Typst: /status reports the fact, and
	// the renderer itself arrives as the Exporter.
	TypstVersion string
	TemplatePath string
}

Meta carries Operator-facing facts about the running service that the Document itself does not contain. It holds resolved values, never paths to resolve: internal/web must stay free of filesystem concerns.

type NewHouseholdIDFunc

type NewHouseholdIDFunc func() (rolo.HouseholdID, error)

NewHouseholdIDFunc mints a stable identity for a new Household. Injected so that tests can assert on whole documents with fixed IDs rather than matching a prefix and looking the record up.

type NewPersonIDFunc

type NewPersonIDFunc func() (rolo.PersonID, error)

NewPersonIDFunc mints a stable identity for a new Person, injected for the same reason as NewHouseholdIDFunc.

type Saver

type Saver func(prev, next store.State) error

Saver persists the Directory, its Trash and the settings. web.New hands it to the live.Copy as its Writer. It is handed the state being replaced as well as the new one, so it can tell which files changed and write them in an order that cannot lose a Household (store.Persist, ADR-0012).

It is injected rather than called directly so that internal/web keeps the freedom from filesystem concerns that New's signature exists to preserve: main closes over the document path and this package never learns it.

It is called synchronously inside the request that triggered it. The atomic temp/fsync/rename in internal/store protects a write that has begun, not one that never got to run, and main's graceful shutdown waits for in-flight requests — a save handed to a goroutine would escape both.

type Server

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

Server renders the Directory that its live.Copy serves, and makes the Editor's changes through it. The Copy is the single writer, which is what gives Undo a coherent place to live (internal/live).

func New

func New(
	state store.State,
	cfg config.Config,
	logger *slog.Logger,
	meta Meta,
	save Saver,
	newHouseholdID NewHouseholdIDFunc,
	newPersonID NewPersonIDFunc,
	exporter Exporter,
	now Clock,
) (*Server, error)

New builds a Server over an already-loaded state. It takes a loaded state rather than paths so the web layer has no filesystem dependency; main owns loading and treats failure as fatal.

The logger is injected rather than taken from slog's package default so that nothing here depends on process-global state: main builds it at the level cfg carries and owns where the output goes.

save, newHouseholdID, newPersonID, exporter and now are the write path's and the export path's dependencies. They are plain parameters rather than a struct so that a caller cannot leave one unset by forgetting a field; every one is checked here. save becomes the live.Copy's Writer.

func (*Server) Handler

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

Handler returns the server's routes.

Jump to

Keyboard shortcuts

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