Documentation
¶
Overview ¶
Package config loads and validates Forge runtime configuration.
Index ¶
- Constants
- func CheckTrustedProxy(prefix netip.Prefix) error
- func LoopbackHost(host string) bool
- func ParseMailbox(value string) (name, email string, err error)
- func ParseTrustedProxies(list string) ([]netip.Prefix, error)
- func ValidMailDomain(domain string) bool
- func ValidateMailbox(name, email string) error
- type Adapter
- type Auth
- type Cache
- type Config
- type Database
- type Environment
- type HTTP
- type I18n
- type Jobs
- type Log
- type LogFormat
- type Mail
- type MailEndpoint
- type MailTransport
- type MailboxError
- type OpenAPI
- type RateLimit
- type Secret
- type Storage
- type Telemetry
- type TelemetryExporter
- type TelemetryLogsExporter
- type TransportMode
Constants ¶
const EnvMigrationDatabaseURL = "FORGE_MIGRATION_DATABASE_URL"
EnvMigrationDatabaseURL names the connection URL of the migration role: the role that owns the schema and applies migrations, separate from the less-privileged role FORGE_DATABASE_URL serves with.
Variables ¶
This section is empty.
Functions ¶
func CheckTrustedProxy ¶
CheckTrustedProxy reports why prefix is not a safe trusted proxy network, or nil. It is the single definition of the rules: ParseTrustedProxies, Config.Validate and web.NewTrustedProxies all apply it. The error text completes the sentence "entry N ...", names no value, and never echoes the prefix.
It refuses invalid prefixes, IPv4-mapped IPv6 prefixes (peers are compared in their IPv4 form, so they would never match), IPv4 prefixes shorter than /8 and IPv6 prefixes shorter than /16 (they would trust far more than a proxy network; this includes /0, which trusts every address). A bare address is a /32 or /128 and is unaffected.
func LoopbackHost ¶
LoopbackHost reports whether host is "localhost", a 127.0.0.0/8 address or ::1: a destination the traffic never leaves the machine for. Host names other than "localhost" are not resolved, so they are never loopback here.
func ParseMailbox ¶
ParseMailbox parses "user@example.com" or "Display Name <user@example.com>" with net/mail and validates the result with ValidateMailbox.
func ParseTrustedProxies ¶
ParseTrustedProxies parses FORGE_HTTP_TRUSTED_PROXIES: a comma-separated list of CIDR prefixes or bare addresses (a bare address is a /32 or /128), such as "172.18.0.0/16, fd00:1::/64, 10.0.0.7". A blank list trusts nobody. Empty entries, malformed entries, overly broad prefixes (IPv4 shorter than /8, IPv6 shorter than /16, which includes /0) and IPv4-mapped IPv6 prefixes (peers are compared in their IPv4 form, so they would never match) are errors naming the entry's position, never its text (see CheckTrustedProxy). Prefixes are returned masked.
func ValidMailDomain ¶
ValidMailDomain reports whether domain is an LDH host name of up to 253 bytes. A single label such as "localhost" is allowed for development.
func ValidateMailbox ¶
ValidateMailbox checks a display name and an addr-spec.
The address must be ASCII dot-atom `local@domain` with an LDH host name; quoted local parts, comments, route addresses, domain literals and display forms are rejected, which removes the ambiguity used to smuggle recipients or SMTP commands. The display name may be any text without control, line-break or bidirectional-override characters.
Types ¶
type Adapter ¶
type Adapter string
Adapter identifies the database adapter selected by FORGE_DATABASE_URL's scheme.
type Auth ¶
type Auth struct {
// MFAKey is the canonical unpadded base64url encoding of 32 random bytes
// used by the built-in AES-256-GCM TOTP secret cipher.
MFAKey Secret
// PasswordResetURL is the absolute URL of the page password-reset emails
// link to, such as https://app.example.com/passwords/edit
// (FORGE_AUTH_PASSWORD_RESET_URL). It must be https, or http on a
// loopback host for development. Empty disables reset emails.
PasswordResetURL string
// SessionIdleTimeout ends a session nobody used for this long, before
// its absolute expiry (FORGE_AUTH_SESSION_IDLE_TIMEOUT, default 2h,
// between 5m and 720h). auth/postgres.WithSessionIdleTimeout applies it.
SessionIdleTimeout time.Duration
}
Auth contains optional secrets for identity features. Zero values keep the corresponding feature disabled rather than inventing insecure defaults.
type Cache ¶
type Cache struct {
// MaxEntries bounds the entries of a cache (FORGE_CACHE_MAX_ENTRIES,
// default 10000).
MaxEntries int
// MaxBytes bounds the memory of the in-memory cache
// (FORGE_CACHE_MAX_BYTES, default 64 MiB).
MaxBytes int64
// MaxValueBytes bounds one cached value (FORGE_CACHE_MAX_VALUE_BYTES,
// default 1 MiB, at most 8 MiB).
MaxValueBytes int
// DefaultTTL applies when a write names no time to live
// (FORGE_CACHE_DEFAULT_TTL, default 1h).
DefaultTTL time.Duration
}
Cache configures the application cache (ADR 0032). Zero values select the defaults.
type Config ¶
type Config struct {
Environment Environment
HTTP HTTP
Auth Auth
Database Database
Mail Mail
RateLimit RateLimit
Cache Cache
Storage Storage
Telemetry Telemetry
Log Log
I18n I18n
OpenAPI OpenAPI
Jobs Jobs
}
Config is the application's configuration. Default returns safe defaults; Load reads FORGE_* variables over them.
func Default ¶
func Default() Config
Default returns the defaults: the development environment, plain HTTP on 127.0.0.1:8080, conservative timeouts and size limits, and no database.
func Load ¶
Load reads the configuration from the process environment, over Default, and validates it.
func LoadWithLookup ¶
LoadWithLookup is Load with lookup in place of the process environment. It returns an error for an unparsable or invalid setting.
func (Config) EventLevel ¶
EventLevel returns the level of the request, SQL and job lines, which follow a request or a job step by step: Info in development, where they are the development log, and Debug elsewhere, where FORGE_LOG_LEVEL=debug turns them on.
func (Config) MigrationDatabase ¶
MigrationDatabase returns the connection the migrate and rollback commands use. When FORGE_MIGRATION_DATABASE_URL is set (read through lookup), it supplies the role: its user, password, host, port and parameters, validated like FORGE_DATABASE_URL (production TLS rules included) and of the same adapter. Its database is ignored: migrations always change the database FORGE_DATABASE_URL names, the one the application serves. Without it, or for SQLite, which has no roles, the result is c.Database unchanged.
func (Config) ServesOpenAPI ¶
ServesOpenAPI reports whether the application serves its OpenAPI document at GET /openapi.json.
func (Config) ShowsMissingTranslations ¶
ShowsMissingTranslations reports whether missing translations are shown as "translation missing: LOCALE.KEY" (development and test) instead of falling back to the default locale (staging and production).
type Database ¶
type Database struct {
// URL is a postgres://, mysql:// or sqlite: URL. It usually embeds a
// password.
URL Secret
MaxConns int32
MinConns int32
MaxConnLifetime time.Duration
MaxConnIdleTime time.Duration
ConnectTimeout time.Duration
// StatementTimeout bounds statements server-side: every statement on
// PostgreSQL and MariaDB, SELECT only on MySQL. SQLite has no server; its
// queries stop through context cancellation.
StatementTimeout time.Duration
// AllowPlaintext permits production connections without TLS, for
// databases reachable only over a trusted private network.
AllowPlaintext bool
// Environment is the environment the pool serves in. Outside
// development and test, postgres.Open refuses a role that could bypass
// row-level security unless postgres.AllowRowSecurityBypass is passed.
// Load and forge.New copy Config.Environment into it. Default leaves it
// empty, like a Database built in code: the empty value is neither
// development nor test, so such a pool is checked (fail closed) until
// the environment is set explicitly.
Environment Environment
}
Database configures the database connection pool. The URL's scheme selects the adapter (see Adapter). An empty URL means the application runs without a database.
func (Database) Adapter ¶
Adapter reports the adapter the URL selects, or "" when no database is configured. The URL has been validated, so any other value cannot occur.
func (Database) SQLitePath ¶
SQLitePath returns the database file of a sqlite: URL, or "".
type Environment ¶
type Environment string
Environment is the deployment environment selected by FORGE_ENV.
const ( Development Environment = "development" Test Environment = "test" Staging Environment = "staging" Production Environment = "production" )
The supported environments. Production and staging are stricter about transport security and fallbacks.
type HTTP ¶
type HTTP struct {
Address string
Transport TransportMode
TLSCertFile string
TLSKeyFile string
ReadHeaderTimeout time.Duration
ReadTimeout time.Duration
WriteTimeout time.Duration
IdleTimeout time.Duration
ShutdownTimeout time.Duration
MaxHeaderBytes int
MaxBodyBytes int64
// TrustedProxies are the networks of the reverse proxies whose
// X-Forwarded-For header is believed when resolving the client address
// (FORGE_HTTP_TRUSTED_PROXIES, ADR 0037). Empty, the default, trusts
// nobody: the client address is the TCP peer.
TrustedProxies []netip.Prefix
}
HTTP configures the HTTP server: address, transport, timeouts and size limits.
type I18n ¶
type I18n struct {
// DefaultLocale is the locale requests fall back to
// (FORGE_I18N_DEFAULT_LOCALE), such as "en" or "pt-BR". Empty lets the
// application choose; generated applications use the locale given to
// `forge new --locale`, "en" by default.
DefaultLocale string
}
I18n configures translations (package i18n, ADR 0042).
type Jobs ¶
type Jobs struct {
// Notify is FORGE_JOBS_NOTIFY: enqueues announce due jobs and job workers
// LISTEN for them, the meaning of queuepostgres.WithNotify(). Nil (unset)
// keeps the code's choice; false turns an announcing store off per
// deployment. Only PostgreSQL has a wake-up.
Notify *bool
}
Jobs configures durable jobs (package queue, ADR 0047).
type Log ¶
type Log struct {
// Format is FORGE_LOG_FORMAT: auto (default), pretty, text or json.
Format LogFormat
// Level is FORGE_LOG_LEVEL, the lowest level written: debug, info
// (default), warn or error.
Level string
// SlowQuery is FORGE_LOG_SLOW_QUERY (default 100ms): a SQL line of a
// statement slower than this is marked slow, and yellow in the pretty
// format.
SlowQuery time.Duration
// RedactKeys is FORGE_LOG_REDACT_KEYS, a comma-separated list of key
// fragments added to the default ones (password, secret, token, email...):
// the value of every log attribute whose key contains one of them,
// whatever its case, is written as [REDACTED].
RedactKeys []string
}
Log configures the application log: its format, the slowest query that is not flagged and the attribute keys that are never written.
type LogFormat ¶
type LogFormat string
LogFormat is how the application writes its logs (FORGE_LOG_FORMAT).
type Mail ¶
type Mail struct {
// URL selects and configures the transport and usually embeds a
// password:
//
// smtp://user:password@smtp.example.com:587 STARTTLS (default port 587)
// smtps://user:password@smtp.example.com:465 implicit TLS (default 465)
// file:///var/tmp/forge-mail development .eml files
//
// Percent-encode "@", ":" and "/" inside the user name and password.
URL Secret
// From is the default sender, "name@example.com" or
// "Name <name@example.com>". It is required when URL is set.
From string
// AllowPlaintext lets the SMTP sender proceed when the server does not
// offer STARTTLS, including authentication over that connection. Use only
// on a trusted private network or against a local development server.
AllowPlaintext bool
// Timeout bounds one delivery attempt. Zero means 30 seconds.
Timeout time.Duration
// Preview enables the development mail preview handler
// (FORGE_MAIL_PREVIEW=true). It must be set deliberately: an unset
// FORGE_ENV means development, so the environment alone is not a safe
// gate. Only valid in development and test.
Preview bool
// CAFile is a PEM bundle of extra trusted roots for a private mail relay.
// There is no setting to skip certificate verification.
CAFile string
}
Mail configures outgoing email. An empty URL means the application sends no mail (features that need it, such as password recovery, fail closed).
func (Mail) EffectiveTimeout ¶
EffectiveTimeout returns Timeout, or the 30 second default when unset.
func (Mail) SMTP ¶
func (m Mail) SMTP() (MailEndpoint, bool)
SMTP returns the server of an smtp:// or smtps:// URL.
func (Mail) Transport ¶
func (m Mail) Transport() MailTransport
Transport reports the transport the URL selects, or MailDisabled.
type MailEndpoint ¶
type MailEndpoint struct {
Host string
Port int
Username string
Password Secret
// ImplicitTLS is true for smtps://.
ImplicitTLS bool
}
MailEndpoint is the SMTP server described by Mail.URL.
type MailTransport ¶
type MailTransport string
MailTransport identifies how FORGE_MAIL_URL's scheme delivers mail.
const ( // MailDisabled means no mail URL is configured. MailDisabled MailTransport = "" // MailSTARTTLS is smtp://: connect, then upgrade with STARTTLS (port 587). MailSTARTTLS MailTransport = "smtp" // MailImplicitTLS is smtps://: TLS from the first byte (port 465). MailImplicitTLS MailTransport = "smtps" // MailFile is file://: the development sender writing .eml files. It is // refused in production. MailFile MailTransport = "file" )
type MailboxError ¶
type MailboxError struct {
Reason string
// Unsupported marks input that is valid in the wild but outside what
// Forge implements: addresses with non-ASCII characters (SMTPUTF8 and
// IDNA are not supported). Callers can report it distinctly.
Unsupported bool
}
MailboxError explains why a mailbox cannot be used. Reason is a static sentence; it never contains the offending value.
func (*MailboxError) Error ¶
func (e *MailboxError) Error() string
type OpenAPI ¶
type OpenAPI struct {
// Enabled is FORGE_OPENAPI_ENABLED. Nil (unset) serves the document in
// development and test only: it lists every documented route,
// including internal ones, so staging and production publish it only
// when it is set to true.
Enabled *bool
}
OpenAPI configures the GET /openapi.json route (package openapi, ADR 0043).
type RateLimit ¶
type RateLimit struct {
// MaxKeys bounds the buckets the in-memory limiter holds
// (FORGE_RATE_LIMIT_MAX_KEYS, default 100000).
MaxKeys int
}
RateLimit configures the in-memory rate limiter (ADR 0031). Zero values select the defaults, so a Config built without Default still validates.
func (RateLimit) EffectiveMaxKeys ¶
EffectiveMaxKeys returns MaxKeys, or the default when unset.
type Secret ¶
type Secret struct {
// contains filtered or unexported fields
}
Secret holds a sensitive value such as a database URL. Every formatting, logging and serialization path prints [REDACTED]; only Reveal returns the value, which makes each use explicit and easy to audit.
The value sits behind a pointer on purpose: fmt cannot call String or GoString on an unexported struct field and would print the fields it finds, so a Secret held in an unexported field (`%+v` of a struct) would leak its text. Behind a pointer it prints an address. Consequently two Secrets must be compared with Equal, not ==, which compares identity.
func (Secret) Equal ¶
Equal reports whether both secrets hold the same value, in constant time for values of equal length.
func (Secret) MarshalText ¶
MarshalText encodes [REDACTED], so JSON and other text encodings never carry the value.
type Storage ¶
type Storage struct {
// Root is the directory the disk adapter stores files in
// (FORGE_STORAGE_ROOT). In production it must be an absolute path on a
// persistent volume.
Root string
// SigningKey is the canonical unpadded base64url encoding of at least 32
// random bytes (FORGE_STORAGE_SIGNING_KEY), the HMAC key of signed links.
// Production requires it whenever Root is set. Generate one with
// "openssl rand -base64 32 | tr '+/' '-_' | tr -d '='".
SigningKey Secret
// MaxUploadBytes bounds one uploaded file (FORGE_STORAGE_MAX_UPLOAD_BYTES,
// default 512 KiB). When Root is set it cannot exceed
// FORGE_HTTP_MAX_BODY_BYTES, which caps every request body.
MaxUploadBytes int64
// LinkTTL is the lifetime of signed links (FORGE_STORAGE_LINK_TTL, default
// 15m, at most 7 days).
LinkTTL time.Duration
}
Storage configures file storage (ADR 0033). An empty Root means the application does not use disk storage.
func (Storage) EffectiveLinkTTL ¶
EffectiveLinkTTL returns LinkTTL, or the default when unset.
func (Storage) EffectiveMaxUploadBytes ¶
EffectiveMaxUploadBytes returns MaxUploadBytes, or the default when unset.
func (Storage) SigningKeyBytes ¶
SigningKeyBytes decodes SigningKey. It returns nil, nil when no key is configured and an error (that never contains the value) when it is not canonical unpadded base64url of 32 to 1024 bytes.
type Telemetry ¶
type Telemetry struct {
// Enabled turns instrumentation on (FORGE_TELEMETRY_ENABLED, default
// true). When false no telemetry middleware or instrument exists and
// the cost is zero.
Enabled bool
// ServiceName is the service.name resource attribute. Empty means
// "unknown_service:" followed by the executable name.
ServiceName string
ServiceVersion string
// Exporter is none (default), otlp or log.
Exporter TelemetryExporter
// LogsExporter is none (default) or otlp
// (FORGE_TELEMETRY_LOGS_EXPORTER). It is independent of Exporter: logs
// may go to the collector while spans and metrics do not, and the other
// way round. otlp needs OTLPEndpoint.
LogsExporter TelemetryLogsExporter
// LogsLevel is the lowest slog level sent to the log exporter:
// debug, info (default), warn or error (FORGE_TELEMETRY_LOGS_LEVEL).
// Standard output keeps the application logger's own level.
LogsLevel string
// OTLPEndpoint is the collector's base URL, such as
// http://otel-collector:4318. Required for the otlp exporters. Production
// requires https unless OTLPAllowPlaintext is set.
OTLPEndpoint string
// OTLPHeaders are "name=value" pairs separated by commas, values
// percent-encoded, sent with every export: typically an API key.
OTLPHeaders Secret
OTLPTimeout time.Duration
OTLPCompression string
OTLPAllowPlaintext bool
// SampleRatio is the fraction of new traces that are sampled, 0 to 1
// (default 1). Child spans follow their parent's decision.
SampleRatio float64
// TrustTraceparent continues traces from incoming traceparent and
// tracestate headers (FORGE_TELEMETRY_TRUST_TRACEPARENT, default false).
// Untrusted, every request starts a new trace, so clients can neither
// choose trace IDs, force sampling past SampleRatio, nor push tracestate
// to downstream services. Enable it only behind a proxy or gateway that
// sets or sanitizes these headers.
TrustTraceparent bool
// MetricsAddress is the host:port of the separate Prometheus listener,
// serving GET /metrics. Empty (default) means no listener. It has no
// authentication: a non-loopback address must be confirmed with
// MetricsPublic, or production refuses to start and other environments
// log a warning.
MetricsAddress string
// MetricsPublic (FORGE_TELEMETRY_METRICS_PUBLIC) confirms that a
// non-loopback MetricsAddress is intended, for example 0.0.0.0:9464 in a
// container whose port only the cluster network can reach.
MetricsPublic bool
// MetricsInterval is how often metrics are pushed with the otlp
// exporter (default 1 minute).
MetricsInterval time.Duration
}
Telemetry configures tracing, metrics and log correlation (package telemetry, docs/OBSERVABILITY.md).
func (Telemetry) LogLevel ¶
LogLevel returns the slog level LogsLevel names, and false when it names none.
func (Telemetry) MetricsLoopback ¶
MetricsLoopback reports whether MetricsAddress binds only to loopback (localhost, 127.0.0.0/8 or ::1). An empty host, 0.0.0.0 and any other address are reachable from the network.
type TelemetryExporter ¶
type TelemetryExporter string
TelemetryExporter selects where sampled spans and pushed metrics go.
const ( // TelemetryExporterNone exports nothing: traces still correlate logs and // propagate to downstream services, and metrics are served by the // metrics listener when FORGE_TELEMETRY_METRICS_ADDR is set. TelemetryExporterNone TelemetryExporter = "none" // TelemetryExporterOTLP sends spans and metrics to an OpenTelemetry // Collector over OTLP/HTTP with JSON encoding. TelemetryExporterOTLP TelemetryExporter = "otlp" // TelemetryExporterLog writes spans to the application log. It is for // development and refused in production. TelemetryExporterLog TelemetryExporter = "log" )
type TelemetryLogsExporter ¶
type TelemetryLogsExporter string
TelemetryLogsExporter selects where application log records go in addition to standard output.
const ( // TelemetryLogsExporterNone (the default) leaves logs on standard output. TelemetryLogsExporterNone TelemetryLogsExporter = "none" // TelemetryLogsExporterOTLP also sends every log record, with the trace // and span IDs of its context, to the OpenTelemetry Collector's // /v1/logs over OTLP/HTTP with JSON encoding, using the same // FORGE_TELEMETRY_OTLP_* settings as spans and metrics. TelemetryLogsExporterOTLP TelemetryLogsExporter = "otlp" )
type TransportMode ¶
type TransportMode string
TransportMode is how the server terminates HTTP, selected by FORGE_HTTP_TRANSPORT.
const ( TransportPlain TransportMode = "plain" TransportTLS TransportMode = "tls" TransportTrustedProxy TransportMode = "trusted-proxy" )
The supported transports: plain HTTP, TLS terminated by the server, and plain HTTP behind a trusted TLS-terminating proxy.