app

package
v0.29.1 Latest Latest
Warning

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

Go to latest
Published: Jun 4, 2026 License: MIT Imports: 15 Imported by: 0

Documentation

Overview

Package app defines the foundation types and capability interfaces every burrow app implements. Apps satisfy App (required) and any number of the optional capability interfaces (HasRoutes, HasMiddleware, HasMigrations, …) to opt into framework features.

The root burrow package re-exports the most-used names from this package as type aliases so that downstream code can keep writing burrow.App, burrow.AppConfig, burrow.HasRoutes and so on. Less-frequent names are reached by importing this package directly.

Index

Constants

This section is empty.

Variables

This section is empty.

Functions

func ContextValue

func ContextValue[T any](ctx context.Context, key any) (T, bool)

ContextValue retrieves a typed value from the context. It is the generic counterpart to WithContextValue, used by contrib app authors to read back app-specific context values with type safety.

func CoreFlags

func CoreFlags(configSource func(key string) cli.ValueSource) []cli.Flag

CoreFlags returns the CLI flags for core framework configuration. If configSource is provided, it is used as an additional value source (e.g. a TOML file sourcer) for each flag.

func FlagSources

func FlagSources(configSource func(key string) cli.ValueSource, envVar, tomlKey string) cli.ValueSourceChain

FlagSources builds a cli.ValueSourceChain from an environment variable and an optional TOML key. If configSource is nil, only the env var is used. This is the standard way for contrib apps to wire up flag sources:

src := app.FlagSources(configSource, "MY_ENV_VAR", "app.toml_key")

func ForwardedProto added in v0.29.0

func ForwardedProto(ctx context.Context) string

ForwardedProto returns the scheme recorded by WithForwardedProto, or "".

func IsAdmin

func IsAdmin(ctx context.Context) bool

IsAdmin returns true if the AuthChecker in context reports admin status. Returns false if no AuthChecker is set.

func IsAuthenticated

func IsAuthenticated(ctx context.Context) bool

IsAuthenticated returns true if the AuthChecker in context reports authentication. Returns false if no AuthChecker is set.

func IsLocalhost

func IsLocalhost(host string) bool

IsLocalhost checks if the host is a localhost address.

func IsStaff

func IsStaff(ctx context.Context) bool

IsStaff returns true if the AuthChecker in context reports staff status. Returns false if no AuthChecker is set. Admins are implicit staff: a well-formed AuthChecker returns true here whenever [AuthChecker.IsAdmin] would.

func Layout

func Layout(ctx context.Context) string

Layout retrieves the layout template name from the context.

func RequestIsHTTPS added in v0.29.0

func RequestIsHTTPS(r *http.Request) bool

RequestIsHTTPS reports whether the request should be treated as HTTPS for per-request security decisions (CSRF origin check, Secure cookies). It consults the trusted forwarded-proto flag first, then falls back to r.TLS. Behind a TLS-terminating proxy the connection is plain HTTP (r.TLS == nil), so the forwarded flag is what makes the scheme correct.

func RequestPath

func RequestPath(ctx context.Context) string

RequestPath retrieves the request path from the context. Returns an empty string if no path is set.

func WithAuthChecker

func WithAuthChecker(ctx context.Context, checker AuthChecker) context.Context

WithAuthChecker stores an AuthChecker in the context. This is typically called by auth middleware to make authentication state available to the core template functions without an import cycle.

func WithContextValue

func WithContextValue(ctx context.Context, key, val any) context.Context

WithContextValue returns a new context with the given key-value pair. This is a convenience wrapper around context.WithValue used primarily by contrib app authors to store app-specific values in the request context. Application developers typically use typed helpers like WithLayout or contrib-specific functions (e.g. csrf.WithToken) instead.

func WithForwardedProto added in v0.29.0

func WithForwardedProto(ctx context.Context, scheme string) context.Context

WithForwardedProto records the scheme a trusted reverse proxy reported via X-Forwarded-Proto. It is set only by the server's forwarded-headers middleware, and only after the TCP peer passed the trusted-CIDR check.

func WithLayout

func WithLayout(ctx context.Context, name string) context.Context

WithLayout stores the layout template name in the context.

func WithNavItems

func WithNavItems(ctx context.Context, items []NavItem) context.Context

WithNavItems stores navigation items in the context.

func WithRequestPath

func WithRequestPath(ctx context.Context, path string) context.Context

WithRequestPath stores the request path in the context. This is set automatically by the template middleware for HTTP requests. For non-HTTP rendering (background jobs, SSE, CLI), callers should set it explicitly if nav-link highlighting is needed.

func WithTemplateExecutor

func WithTemplateExecutor(ctx context.Context, exec TemplateExecutor) context.Context

WithTemplateExecutor stores the template executor in the context.

Types

type AdminAuth

type AdminAuth interface {
	RequireAuth() func(http.Handler) http.Handler
	RequireStaff() func(http.Handler) http.Handler
	RequireAdmin() func(http.Handler) http.Handler
}

AdminAuth provides authentication and authorization middleware for the admin panel. The admin app discovers an AdminAuth provider from the registry during Configure and uses its middleware to protect /admin routes. contrib/auth implements this interface.

RequireAuth gates "logged in or not"; RequireStaff gates "may enter the admin shell" (used by the admin coordinator for the /admin/ frame); RequireAdmin gates "full admin privileges" (used per-route by apps). Roles form a hierarchy: admin implies staff implies authenticated.

type App

type App = registry.App

App is the required interface that all apps must implement. An app has a unique name used for identification in the registry, migrations, and logging.

type AppConfig

type AppConfig struct {
	DB         *den.DB
	Registry   *registry.Registry
	Config     *Config
	WithLocale func(ctx context.Context, lang string) context.Context
}

AppConfig is passed to each app's Configure method, providing access to shared framework resources.

type AuthChecker

type AuthChecker struct {
	IsAuthenticated func() bool
	IsStaff         func() bool
	IsAdmin         func() bool
}

AuthChecker provides authentication and authorization checks via closures. This allows the core framework to filter nav items by auth state without importing contrib/auth. Auth apps inject an AuthChecker into the context; the framework reads it when building NavLinks.

Roles form a hierarchy: IsAdmin implies IsStaff implies IsAuthenticated. Auth providers must keep that invariant when wiring the closures.

type ClientIPConfig added in v0.26.0

type ClientIPConfig struct {
	// Mode is one of: "remote-addr" (default), "header",
	// "xff-trusted-proxies", "xff-trusted-cidrs".
	Mode string
	// Header is the trusted single-IP header (mode=header).
	Header string
	// TrustedCIDRs is the list of CIDR prefixes covering the trusted
	// proxy fleet (mode=xff-trusted-cidrs).
	TrustedCIDRs []string
	// TrustedProxies is the number of trusted hops to walk back through
	// X-Forwarded-For (mode=xff-trusted-proxies).
	TrustedProxies int
}

ClientIPConfig selects how the framework extracts the client IP from incoming requests. Read the result via [burrow.ClientIP] / [burrow.ClientIPAddr]. There is no safe default: each non-`remote-addr` mode requires its own companion configuration so the operator picks the trust source explicitly. See docs/guide/client-ip.md.

type Config

type Config struct {
	TLS      TLSConfig
	Database DatabaseConfig
	Storage  StorageConfig
	Server   ServerConfig
}

Config holds core framework configuration.

func NewConfig

func NewConfig(cmd *cli.Command) *Config

NewConfig creates a Config from a parsed CLI command.

func (*Config) IsHTTPS

func (c *Config) IsHTTPS() bool

IsHTTPS reports whether the base URL uses HTTPS.

func (*Config) ResolveBaseURL

func (c *Config) ResolveBaseURL() string

ResolveBaseURL computes the base URL from server and TLS config if BaseURL is not explicitly set.

func (*Config) ResolvedTLSMode

func (c *Config) ResolvedTLSMode() string

ResolvedTLSMode returns the effective TLS mode after resolving "auto". "auto" maps to "off" on localhost-style hosts and "acme" otherwise.

func (*Config) ValidateClientIP added in v0.26.0

func (c *Config) ValidateClientIP(_ *cli.Command) error

ValidateClientIP checks that the client-IP configuration is consistent. Each non-default mode requires its companion flag; setting a companion flag without the matching mode is rejected so misconfigurations fail at boot rather than silently picking the wrong source. See docs/guide/client-ip.md for the trust-model rationale.

func (*Config) ValidateForwarded added in v0.29.0

func (c *Config) ValidateForwarded(_ *cli.Command) error

ValidateForwarded checks that the forwarded-headers configuration is consistent. --forwarded-trusted-cidrs is only meaningful with mode=trusted-cidrs, where it is required and each entry must parse. The default and loopback modes use built-in prefixes; off disables the feature. See docs/guide/reverse-proxy.md.

func (*Config) ValidateTLS

func (c *Config) ValidateTLS(cmd *cli.Command) error

ValidateTLS checks that the TLS configuration is consistent. Call this early (before opening the database) to fail fast on misconfigurations.

type Configurable

type Configurable interface {
	Configure(cfg *AppConfig, cmd *cli.Command) error
}

Configurable is implemented by apps that need to read their configuration and perform setup (create repositories, register icons, wire handlers). Configure receives the shared AppConfig and the parsed CLI command.

type DatabaseConfig

type DatabaseConfig struct {
	DSN string
}

DatabaseConfig holds database settings.

type ForwardedConfig added in v0.29.0

type ForwardedConfig struct {
	// Mode is one of: "private" (default — trust loopback + RFC1918 + ULA
	// peers), "loopback" (loopback only), "trusted-cidrs" (explicit allowlist
	// via TrustedCIDRs), "off" (ignore forwarded headers entirely).
	Mode string
	// TrustedCIDRs is the explicit trusted-proxy allowlist (mode=trusted-cidrs).
	TrustedCIDRs []string
	// TrustHost, when true, also applies X-Forwarded-Host to r.Host. Off by
	// default — Host injection enables cache poisoning / poisoned absolute URLs.
	TrustHost bool
}

ForwardedConfig controls whether the framework trusts a reverse proxy's X-Forwarded-Proto (and optionally X-Forwarded-Host) to derive the public request scheme — so CSRF, Secure cookies, and HSTS work behind a TLS-terminating proxy. Trust is gated on the direct TCP peer. See docs/guide/reverse-proxy.md.

type HasAdmin

type HasAdmin interface {
	AdminRoutes(r chi.Router)
	AdminNavItems() []NavItem
}

HasAdmin is implemented by apps that contribute admin panel routes and navigation items. AdminRoutes receives a chi router already prefixed with /admin and protected by auth middleware.

type HasCLICommands

type HasCLICommands interface {
	CLICommands() []*cli.Command
}

HasCLICommands is implemented by apps that contribute subcommands.

type HasDocuments

type HasDocuments interface {
	Documents() []document.Document
}

HasDocuments is implemented by apps that register Den document types. The returned slice should contain zero-value pointers, e.g. &User{}, &Job{}. document.Document is Den's sealed marker interface — only types that embed document.Base satisfy it, so non-document types fail at compile time. Den's Register() creates tables and indexes automatically from the struct tags.

type HasFlags

type HasFlags interface {
	Flags(configSource func(key string) cli.ValueSource) []cli.Flag
}

HasFlags is implemented by apps that define CLI flags. The configSource parameter enables TOML file sourcing; it may be nil when only ENV/CLI sources are used.

type HasFuncMap

type HasFuncMap interface {
	FuncMap() template.FuncMap
}

HasFuncMap is implemented by apps that provide static template functions. These are added once at boot time and available in all templates.

type HasMiddleware

type HasMiddleware interface {
	Middleware() []func(http.Handler) http.Handler
}

HasMiddleware is implemented by apps that contribute HTTP middleware.

type HasMigrations

type HasMigrations interface {
	Migrations() []NamedMigration
}

HasMigrations is implemented by apps that ship versioned, run-once migrations on top of the auto-discovered document schema. The server applies them automatically at boot via Den's migrate package — each migration runs exactly once across processes, tracked in the _den_migrations collection. Versions are namespaced by app name so two contribs can both ship "001_initial" without colliding.

type HasNavItems

type HasNavItems interface {
	NavItems() []NavItem
}

HasNavItems is implemented by apps that contribute navigation items.

type HasRequestFuncMap

type HasRequestFuncMap interface {
	RequestFuncMap(ctx context.Context) template.FuncMap
}

HasRequestFuncMap is implemented by apps that provide context-scoped template functions (e.g., CSRF tokens, current user, translations). These are added per request via middleware using template.Clone(). The context carries all request-scoped values needed by the functions; this enables template rendering outside HTTP handlers (background jobs, SSE broadcasts, CLI commands).

type HasRoutes

type HasRoutes interface {
	Routes(r chi.Router)
}

HasRoutes is implemented by apps that register HTTP routes.

type HasShutdown

type HasShutdown interface {
	Shutdown(ctx context.Context) error
}

HasShutdown is implemented by apps that need to perform cleanup during graceful shutdown (e.g., stopping background goroutines, flushing buffers). Called in reverse registration order before the HTTP server stops.

type HasStaticFiles

type HasStaticFiles interface {
	StaticFS() (prefix string, fsys fs.FS)
}

HasStaticFiles is implemented by apps that contribute static file assets. The returned prefix namespaces the files under the static URL path (e.g., prefix "admin" serves files at /static/admin/...).

type HasTemplates

type HasTemplates interface {
	TemplateFS() fs.FS
}

HasTemplates is implemented by apps that provide HTML template files. The returned fs.FS should contain .html files with {{ define "appname/..." }} blocks. Templates are parsed once at boot time into the global template set.

type HasTranslations

type HasTranslations interface {
	TranslationFS() fs.FS
}

HasTranslations is implemented by apps that contribute translation files. The returned fs.FS must contain a "translations/" directory with TOML files (e.g., "translations/active.en.toml").

type NamedMigration

type NamedMigration struct {
	Version   string
	Migration migrate.Migration
}

NamedMigration pairs a version label with a Den migrate.Migration. The Version is the lexicographic ordering key inside an app; cross-app order follows the registry's dependency-resolved app order.

Migration.Forward is required. Migration.Backward is optional — omitting it locks the migration as forward-only; rollback via migrate.Down / migrate.DownOne returns an error for a migration without a Backward.

type NavItem struct {
	Label     string
	URL       string
	Icon      string
	Position  int
	AuthOnly  bool
	StaffOnly bool
	AdminOnly bool
}

NavItem represents a navigation entry contributed by an app.

Label doubles as the i18n message ID: it is passed through [i18n.T] at render time, so contribute translations keyed by the English Label. When no translation matches, the raw Label is rendered.

Icon is the name of a template define (e.g. "auth/icon_people") rendered by the layout via {{ template .Icon . }}. Each contrib keeps its icons in templates/icons.html as {{ define "<app>/icon_<name>" }} blocks.

func NavItems(ctx context.Context) []NavItem

NavItems retrieves the navigation items from the context.

type NavLink struct {
	Label    string
	URL      string
	Icon     string
	IsActive bool
}

NavLink is a template-ready navigation item with pre-computed active state. It is produced by the navLinks template function from the registered NavItems, filtered by the current user's authentication/authorization state.

Icon is a template name; see NavItem.

type PostConfigurable

type PostConfigurable interface {
	PostConfigure(cfg *AppConfig, cmd *cli.Command) error
}

PostConfigurable is implemented by apps that need a second configuration pass after all Configurable apps have been configured. This is useful when an app needs to interact with other apps' state that is only available after Configure() has run (e.g., the jobs app discovering HasJobs handlers). PostConfigure is called once, after all Configure() calls have completed.

type ReadinessChecker

type ReadinessChecker interface {
	ReadinessCheck(ctx context.Context) error
}

ReadinessChecker is implemented by apps that contribute to the readiness probe. ReadinessCheck returns nil when the app is ready to serve traffic, or an error describing what is not ready.

type ServerConfig

type ServerConfig struct {
	Host            string
	BaseURL         string
	PIDFile         string
	AppName         string
	ClientIP        ClientIPConfig
	Forwarded       ForwardedConfig
	Port            int
	MaxBodySize     int // in MB
	ShutdownTimeout int // in seconds
}

ServerConfig holds HTTP server settings.

type StorageConfig

type StorageConfig struct {
	// DSN selects the backend. Format: "<scheme>://<location>[?url_prefix=…]".
	// Supported schemes:
	//   - file:// — local filesystem. SQLAlchemy/JDBC convention:
	//     "file:///relative" (3 slashes) or "file:////absolute"
	//     (4 slashes). One leading slash is stripped on parse.
	// The optional ?url_prefix= query parameter sets the public URL
	// prefix for locally served attachments (defaults to /media/).
	// Default: file:///data/media?url_prefix=/media/ (relative path).
	DSN string
}

StorageConfig holds file-storage settings for attachments. Burrow constructs a den.Storage from these at boot and installs it on the opened den.DB via den.WithStorage, so domain apps can reach it via cfg.DB.Storage() and templates via the built-in mediaURL function. Set DSN to an empty string to disable Storage entirely.

type TLSConfig

type TLSConfig struct {
	Mode     string // auto, acme, selfsigned, manual, off
	CertDir  string
	Email    string
	CertFile string
	KeyFile  string
}

TLSConfig holds TLS settings.

type TemplateExecutor

type TemplateExecutor func(ctx context.Context, name string, data map[string]any) (template.HTML, error)

TemplateExecutor executes a named template with the given data and returns the rendered HTML. It is stored in the request context by the template middleware and used by Render. The context carries all request-scoped values needed for template rendering.

func TemplateExec

func TemplateExec(ctx context.Context) TemplateExecutor

TemplateExec retrieves the template executor from the context.

Jump to

Keyboard shortcuts

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