Documentation
¶
Index ¶
- Constants
- Variables
- func ApplyDatabasePoolDefaults(cfg *DatabaseConfig) error
- func ApplyDatabasePoolDefaultsForKey(cfg *DatabaseConfig, resourceKey string) error
- func CoversAddressFamily(nets []*net.IPNet, bits int) bool
- func DefaultResolverOrder() []string
- func IsDatabaseConfigured(cfg *DatabaseConfig) bool
- func IsDevelopment(env string) bool
- func IsMessagingConfigured(cfg *MessagingConfig) bool
- func IsNotConfigured(err error) bool
- func IsProduction(env string) bool
- func NormalizeIPNet(n *net.IPNet) (ip net.IP, ones, bits int)
- func ParseTrustedProxyCIDR(entry string) (*net.IPNet, error)
- func QualifyCacheConfigErrorForKey(err error, resourceKey string) error
- func UntypedDatabaseSections(cfg *Config) []string
- func Validate(cfg *Config) error
- type AppConfig
- type BrokerConfig
- type CacheConfig
- type CacheManagerConfig
- type Config
- func (c *Config) All() map[string]any
- func (c *Config) Bool(key string, defaultVal ...bool) bool
- func (c *Config) Custom() map[string]any
- func (c *Config) Exists(key string) bool
- func (c *Config) Float64(key string, defaultVal ...float64) float64
- func (c *Config) InjectInto(target any) error
- func (c *Config) Int(key string, defaultVal ...int) int
- func (c *Config) Int64(key string, defaultVal ...int64) int64
- func (c *Config) IsCacheCritical() bool
- func (c *Config) PerTenantJobKeys() []string
- func (c *Config) RequiredBool(key string) (bool, error)
- func (c *Config) RequiredFloat64(key string) (float64, error)
- func (c *Config) RequiredInt(key string) (int, error)
- func (c *Config) RequiredInt64(key string) (int64, error)
- func (c *Config) RequiredString(key string) (string, error)
- func (c *Config) ShouldLogRoutes() bool
- func (c *Config) String(key string, defaultVal ...string) string
- func (c *Config) Unmarshal(key string, out any) error
- type ConfigError
- func NewConnectionError(resource, message string, troubleshooting []string) *ConfigError
- func NewInvalidFieldError(field, message string, validOptions []string) *ConfigError
- func NewMissingFieldError(field, envVar, yamlPath string) *ConfigError
- func NewMultiTenantError(tenantID, field, message, action string) *ConfigError
- func NewNamedDatabaseError(name string) *ConfigError
- func NewNotConfiguredError(feature, envVar, yamlPath string) *ConfigError
- func NewValidationError(field, message string) *ConfigError
- type DatabaseConfig
- type DatabaseManagerConfig
- type DebugConfig
- type DebugEndpointsConfig
- type ForwardedClientCertConfig
- type GzipConfig
- type IPPreGuardConfig
- type InboxConfig
- type InboxHoldConfig
- type KeyPairConfig
- type KeySourceConfig
- type KeyStoreConfig
- type LifetimeConfig
- type LimitsConfig
- type LogConfig
- type MessagingConfig
- type MultitenantConfig
- type OracleConfig
- type OutboxConfig
- type OutputConfig
- type PKCS12SourceConfig
- type PasswordSourceConfig
- type PathConfig
- type PathResolverConfig
- type PoolConfig
- type PoolIdleConfig
- type PoolKeepAliveConfig
- type PoolMaxConfig
- type PostgreSQLConfig
- type PublisherPoolConfig
- type QueryConfig
- type QueryLogConfig
- type RateConfig
- type ReconnectConfig
- type RedisConfig
- type ResolverConfig
- type ResponseTimeConfig
- type RoutingConfig
- type SchedulerConfig
- type SchedulerSecurityConfig
- type SchedulerTimeoutConfig
- type SealConfig
- type ServerConfig
- type ServerTLSConfig
- type ServiceConfig
- type SlowQueryConfig
- type SourceConfig
- type StartupConfig
- type StreamsAddressResolverConfig
- type StreamsConfig
- type StreamsOffsetStoreConfig
- type TLSConfig
- type TenantEntry
- type TenantMessagingConfig
- type TenantStore
- func (s *TenantStore) AddTenant(tenantID string, entry *TenantEntry)
- func (s *TenantStore) BrokerURL(_ context.Context, key string) (string, error)
- func (s *TenantStore) CacheConfig(_ context.Context, key string) (*CacheConfig, error)
- func (s *TenantStore) DBConfig(_ context.Context, key string) (*DatabaseConfig, error)
- func (s *TenantStore) HasNamedDatabase(name string) bool
- func (s *TenantStore) HasTenant(tenantID string) bool
- func (s *TenantStore) IsDynamic() bool
- func (s *TenantStore) NamedDatabases() map[string]DatabaseConfig
- func (s *TenantStore) RemoveTenant(tenantID string)
- func (s *TenantStore) Tenants() map[string]TenantEntry
- type TimeoutConfig
Constants ¶
const ( // DefaultDatabaseManagerCleanupInterval is the default for database.manager.cleanupinterval. DefaultDatabaseManagerCleanupInterval = 5 * time.Minute // DefaultCacheManagerCleanupInterval is the default for cache.manager.cleanupinterval. DefaultCacheManagerCleanupInterval = 5 * time.Minute // DefaultPublisherCleanupInterval is the default for messaging.publisher.cleanupinterval. DefaultPublisherCleanupInterval = 2 * time.Minute )
Resource-manager cleanup-interval defaults. Each is the single declaration of its key's default: normalization fills the key with it, and the manager that owns the pool cites the same constant where a hand-built options struct leaves the interval non-positive. Two independent literals per key is what let the ADR-075 scheduler timeouts drift apart, so a manager must reference these rather than repeat the value.
const ( // DefaultTimezone is the IANA timezone applied when a timezone config field // (database.timezone, scheduler.timezone) is unset. UTC is opinionated to keep // behavior identical across environments regardless of host or server defaults. DefaultTimezone = "UTC" // DefaultDatabaseTimezone is the default IANA timezone for database sessions. // Retained as a domain-named alias of DefaultTimezone for readability at // database call sites. DefaultDatabaseTimezone = DefaultTimezone // TimezoneDisabledSentinel opts out of session-level timezone enforcement, // preserving the database server's default timezone (legacy behavior). // Connection layers compare against this constant to decide whether to // apply per-connection timezone setup. TimezoneDisabledSentinel = "-" // DefaultBodyLimitBytes is the maximum request body size (10 MB) applied when // server.bodylimit is unset. Single source of truth: the normalize fill applies // it (normalizeServer) and the koanf default derives from that fill rather than // rendering it a second time (derivedDefaultKeys). The <=0 guard in // server.SetupMiddlewares is a backstop for callers that never run Validate. DefaultBodyLimitBytes int64 = 10 * 1024 * 1024 // DefaultKeyStoreSecretMinLength is the byte floor for symmetric keystore // secrets when keystore.secretminlength is absent. Single source of truth: the // normalize fill applies it (normalizeKeyStore) and the koanf default derives // from that fill rather than rendering it a second time (derivedDefaultKeys). DefaultKeyStoreSecretMinLength = 32 )
Database session defaults
const ( PostgreSQL = "postgresql" Oracle = "oracle" )
Database type constants
const ( EnvDevelopment = "development" EnvStaging = "staging" EnvProduction = "production" )
Environment constants
const ( SourceTypeStatic = "static" SourceTypeDynamic = "dynamic" )
Source type constants
const ( TenancyPerTenant = "per-tenant" )
Ledger tenancy constants (outbox.tenancy / inbox.tenancy)
const ( ResolverTypeHeader = "header" ResolverTypeSubdomain = "subdomain" ResolverTypePath = "path" ResolverTypeComposite = "composite" )
Tenant resolver type constants
const (
CacheTypeRedis = "redis"
)
Cache type constants
const MinDatabasePasswordLength = 8
MinDatabasePasswordLength is the minimum length for a non-empty database password. Below this, the migration engine cannot safely substring-redact the password from Flyway output and suppresses the whole output instead, which hides a migration's outcome (see migration.redactPassword). Empty passwords (trust/IAM auth) are exempt.
const NamedDatabasePrefix = "named:"
NamedDatabasePrefix is the key prefix used to identify named database lookups. When DBConfig receives a key starting with this prefix, it looks up the named database configuration instead of tenant configuration.
Variables ¶
var ( // ErrNotConfigured indicates a feature is intentionally not configured (not an error state) ErrNotConfigured = errors.New("not configured") )
Sentinel errors for common configuration states
Functions ¶
func ApplyDatabasePoolDefaults ¶ added in v0.49.1
func ApplyDatabasePoolDefaults(cfg *DatabaseConfig) error
ApplyDatabasePoolDefaults normalizes a DatabaseConfig for connection: it infers a missing Type from a recognized connectionstring scheme, rejects vendor field combinations the driver would silently drop, and fills zero-value Pool, Timezone, and Query (log/slow-threshold) settings with the documented defaults (25 max connections, idle tracks max, keepalive rules, UTC timezone).
Exported so callers that bypass Validate — notably dynamic multi-tenant DBConfigProviders resolved in DbManager — get the same normalization as static config; the inference (ADR-050) is what lets a provider's DSN-only config dial instead of failing on the factory's empty-type dispatch. Unlike config.Validate, this seam never errors on an explicit Type that contradicts the scheme — it is on the per-tenant connection path, where the vendor dial error is the right failure. It does reject Oracle TLS material, an unpaired PostgreSQL sslcert/sslkey, and a PostgreSQL section with no connectionstring and an empty host, because those failure modes are silent and open rather than loud at dial — the empty host reaches libpq's default unix socket, where TLS is skipped (ADR-050 amendment). The asymmetry is deliberate.
It is the connect-strictness door of the database-section normalization module (database_section.go); a rejected config returns untouched.
It addresses its errors to the ROOT database section. A caller that knows which section the config came from should use ApplyDatabasePoolDefaultsForKey instead, so a failure names that section rather than the root (ADR-076 addendum, C60.19).
func ApplyDatabasePoolDefaultsForKey ¶ added in v0.60.0
func ApplyDatabasePoolDefaultsForKey(cfg *DatabaseConfig, resourceKey string) error
ApplyDatabasePoolDefaultsForKey is ApplyDatabasePoolDefaults addressed to the section the config was resolved for. resourceKey is the DBConfigProvider key: "" is the root database, a NamedDatabasePrefix key is databases.<name>, and anything else is a tenant id.
Passing it is what lets a dynamically-resolved tenant report the same multitenant.tenants.<id>.database.<key> field a statically-declared one does, so a consumer routing on ConfigError.Field cannot tell the startup and runtime doors apart. It is a separate function rather than a second parameter because tools/migration is a separate module pinned to a RELEASED go-bricks, so an arity change there cannot compile until the next tag — see C60.19.
func CoversAddressFamily ¶ added in v0.60.0
CoversAddressFamily reports whether nets, merged, span an ENTIRE address family.
This is the rule for a trusted-proxy list, and it is deliberately about coverage rather than about spelling. "0.0.0.0/0" is only the most obvious way to trust everyone; ["0.0.0.0/1","128.0.0.0/1"] and ["0.0.0.0/1","128.0.0.0/2","192.0.0.0/2"] do the same thing with properly-masked, non-default-route entries, and no per-entry test reaches them. Trusting every address makes every peer a trusted proxy, which is what lets a caller connecting directly have their forwarding headers believed (ADR-080).
Merging is exact and there is no threshold: a list covering all-but-one-address is NOT rejected. See the residual note in ADR-080 — any cut-off would be arbitrary and would refuse legitimate large lists, and a list built that way is not an accident.
func DefaultResolverOrder ¶ added in v0.50.0
func DefaultResolverOrder() []string
DefaultResolverOrder returns the recommended composite sub-resolver order as a fresh slice — callers may freely mutate the result. It is NOT an implicit default: config.Validate requires multitenant.resolver.order to be set explicitly for type: composite, because only the operator can know which sub-resolvers are attacker-reachable versus gateway-asserted in their deployment. This function serves two purposes: (1) the value to point operators at from validation error messages, and (2) a last-resort fallback used by server.compositeSubResolvers for a ResolverConfig that was never passed through config.Validate (e.g. hand-built by an embedding app or a test), so such a config doesn't silently end up with zero sub-resolvers.
func IsDatabaseConfigured ¶ added in v0.4.1
func IsDatabaseConfigured(cfg *DatabaseConfig) bool
IsDatabaseConfigured reports whether a database is intentionally configured (ADR-003, ADR-047).
Any connection-identity field counts as intent. The strictness is the point: a partially delivered database section must fail validation loudly rather than read as an intentionally database-free service, because everything downstream treats "no database at all" as a benign posture. Only a section with literally zero identity fields is absence.
Fields that applyDatabasePoolDefaults fills in (timezone, pool, query) are deliberately excluded, so the verdict is identical before and after defaulting.
A field delivered as an EMPTY string (an empty secretKeyRef, envsubst over an unset variable) is indistinguishable from an unset one here and reads as absence — but that shape is now caught at Load time by validateNoDeliveredEmptyDatabase (ADR-051), which consults the presence recorded at the merge seam (ADR-104) rather than decoded values. The remaining blind spots are hand-built Config values (no source, so every key reads absent) and dynamic-source tenant configs (resolved from a remote store, never loaded). TLS material is likewise excluded from this predicate — it identifies no database on its own.
The answer must not change across normalizeDatabaseSection: normalization never adds identity to a section that had none, which is what lets check consult this predicate after normalize (validateNoSingleTenantConflict).
func IsDevelopment ¶ added in v0.33.1
IsDevelopment reports whether env matches a development alias.
func IsMessagingConfigured ¶ added in v0.11.2
func IsMessagingConfigured(cfg *MessagingConfig) bool
IsMessagingConfigured determines if messaging is intentionally configured. This mirrors the logic used to determine if messaging should be initialized.
func IsNotConfigured ¶ added in v0.11.3
IsNotConfigured checks if an error indicates a feature is not configured. Returns true for ConfigError with category "not_configured" or errors wrapping ErrNotConfigured.
func IsProduction ¶ added in v0.33.1
IsProduction reports whether env matches a production alias.
func NormalizeIPNet ¶ added in v0.60.0
NormalizeIPNet returns a net's address and mask size as the family net.IPNet.Contains will actually use them. It exists because Mask.Size() and Contains disagree on a v4-mapped IPv6 net: "::ffff:0.0.0.0/96" measures 96 of 128 bits, but Contains re-derives a 4-byte mask and matches every IPv4 address — so a mask-size test reads it as a /96 while it behaves as 0.0.0.0/0. Measuring the wrong one is how a default route walks past a default-route check.
func ParseTrustedProxyCIDR ¶ added in v0.59.0
ParseTrustedProxyCIDR parses one server.trustedproxies entry and rejects every shape that would make the list trust more than the operator wrote:
- anything net.ParseCIDR cannot parse, including a bare address — an operator writing a single host gets an error instead of a silently dropped entry;
- an entry whose host bits are set: net.ParseCIDR accepts 10.1.2.3/8 and silently masks it to 10.0.0.0/8, widening the range past what was written;
- a default route, which trusts every hop, so echo's walk finds nothing untrusted and returns the caller-authored left-most X-Forwarded-For entry.
Surrounding whitespace is trimmed, matching validateCIDRList and server.ParseCIDRs, so a YAML sequence entry with incidental spacing is accepted.
Both config validation and the server's extractor wiring call this, so the rule set cannot drift between what startup accepts and what actually gets trusted. On the host-bits rejection the returned net is the masked range the entry would have silently become, so a caller can name it; every other failure returns nil.
func QualifyCacheConfigErrorForKey ¶ added in v0.61.0
QualifyCacheConfigErrorForKey addresses a cache configuration error to the resource key that produced it. It is the cache door onto the shared addressing engine, the way ApplyDatabasePoolDefaultsForKey is the database door — both resolve a resource key to a section via their kind and let section.qualify do the rewriting, so the two kinds cannot drift apart the way cache_section.go's own copy of this recipe once did (ADR-076).
A nil err is returned nil regardless of key: the engine's qualify is never invoked with one (every other caller only qualifies an err it already knows is non-nil), so this guard is the door's own convenience rather than a property of the shared engine.
func UntypedDatabaseSections ¶ added in v0.59.0
UntypedDatabaseSections returns the path of every database section that carries a connectionstring whose vendor is still unresolved after normalization — a scheme inference does not recognize (ADR-050). Whether that is fatal depends on who connects, so this only reports; app.Builder decides. Paths come back in walk order, which is lexicographic. Nil when none.
Types ¶
type AppConfig ¶
type AppConfig struct {
Name string `koanf:"name" json:"name" yaml:"name" toml:"name" mapstructure:"name"`
Version string `koanf:"version" json:"version" yaml:"version" toml:"version" mapstructure:"version"`
Env string `koanf:"env" json:"env" yaml:"env" toml:"env" mapstructure:"env"`
Debug bool `koanf:"debug" json:"debug" yaml:"debug" toml:"debug" mapstructure:"debug"`
Namespace string `koanf:"namespace" json:"namespace" yaml:"namespace" toml:"namespace" mapstructure:"namespace"`
Rate RateConfig `koanf:"rate" json:"rate" yaml:"rate" toml:"rate" mapstructure:"rate"`
Startup StartupConfig `koanf:"startup" json:"startup" yaml:"startup" toml:"startup" mapstructure:"startup"`
}
AppConfig holds general application settings.
func (*AppConfig) IsDevelopment ¶ added in v0.33.1
IsDevelopment reports whether a.Env matches a development alias.
func (*AppConfig) IsProduction ¶ added in v0.33.1
IsProduction reports whether a.Env matches a production alias.
type BrokerConfig ¶ added in v0.7.1
type BrokerConfig struct {
URL string `koanf:"url" json:"url" yaml:"url" toml:"url" mapstructure:"url"`
VirtualHost string `koanf:"virtualhost" json:"virtualhost" yaml:"virtualhost" toml:"virtualhost" mapstructure:"virtualhost"`
}
BrokerConfig holds message broker connection settings.
type CacheConfig ¶ added in v0.18.0
type CacheConfig struct {
Enabled bool `koanf:"enabled" json:"enabled" yaml:"enabled" toml:"enabled" mapstructure:"enabled"`
// Critical fails /ready with 503 when the cache probe errors. Absent means
// non-critical (ADR-094), so a plain bool: no koanf default is registered
// (#1316). Read through Config.IsCacheCritical. See wiki/cache.md#readiness.
Critical bool `koanf:"critical" json:"critical" yaml:"critical" toml:"critical" mapstructure:"critical"`
Type string `koanf:"type" json:"type" yaml:"type" toml:"type" mapstructure:"type"` // redis
Redis RedisConfig `koanf:"redis" json:"redis" yaml:"redis" toml:"redis" mapstructure:"redis"`
Manager CacheManagerConfig `koanf:"manager" json:"manager" yaml:"manager" toml:"manager" mapstructure:"manager"`
// LoadTimeout bounds each cache leg of cache.LoadThrough — the lookup and the
// detached write-back — so a slow-but-reachable cache cannot spend the caller's
// whole request budget before the origin loader runs. Default 500ms; 0 means
// "unset, use the default" and a negative value is rejected, so there is no way
// to express an unbounded leg. Per-tenant values are honored: the bound travels
// on the resolved cache instance, not on a process-wide global.
// See wiki/cache.md#load-through-reads.
LoadTimeout time.Duration `koanf:"loadtimeout" json:"loadtimeout" yaml:"loadtimeout" toml:"loadtimeout" mapstructure:"loadtimeout"`
}
CacheConfig holds cache backend settings. Production-safe defaults are applied automatically when cache is enabled.
type CacheManagerConfig ¶ added in v0.19.0
type CacheManagerConfig struct {
// MaxSize is the maximum number of active cache instances. 0 = use default
// (100 single-tenant; in multi-tenant mode zero is preserved so
// app.ManagerConfigBuilder scales the pool to multitenant.limits.tenants);
// negative values are invalid.
MaxSize int `koanf:"maxsize" json:"maxsize" yaml:"maxsize" toml:"maxsize" mapstructure:"maxsize"`
// IdleTTL is the idle timeout before cache instances are closed.
// Default: 15m. Set lower for memory-constrained environments.
IdleTTL time.Duration `koanf:"idlettl" json:"idlettl" yaml:"idlettl" toml:"idlettl" mapstructure:"idlettl"`
// CleanupInterval is how often the cleanup goroutine runs.
// Default: 5m. Should be less than IdleTTL for effective cleanup.
CleanupInterval time.Duration `koanf:"cleanupinterval" json:"cleanupinterval" yaml:"cleanupinterval" toml:"cleanupinterval" mapstructure:"cleanupinterval"`
}
CacheManagerConfig holds cache manager lifecycle settings. Production-safe defaults are applied automatically:
- MaxSize: 100 (maximum tenant cache instances, single-tenant; multi-tenant scales to multitenant.limits.tenants when unset)
- IdleTTL: 15m (idle timeout per cache)
- CleanupInterval: 5m (cleanup goroutine frequency)
type Config ¶
type Config struct {
App AppConfig `koanf:"app" json:"app" yaml:"app" toml:"app" mapstructure:"app"`
Server ServerConfig `koanf:"server" json:"server" yaml:"server" toml:"server" mapstructure:"server"`
Database DatabaseConfig `koanf:"database" json:"database" yaml:"database" toml:"database" mapstructure:"database"`
Databases map[string]DatabaseConfig `koanf:"databases" json:"databases" yaml:"databases" toml:"databases" mapstructure:"databases"`
Cache CacheConfig `koanf:"cache" json:"cache" yaml:"cache" toml:"cache" mapstructure:"cache"`
Log LogConfig `koanf:"log" json:"log" yaml:"log" toml:"log" mapstructure:"log"`
Messaging MessagingConfig `koanf:"messaging" json:"messaging" yaml:"messaging" toml:"messaging" mapstructure:"messaging"`
Multitenant MultitenantConfig `koanf:"multitenant" json:"multitenant" yaml:"multitenant" toml:"multitenant" mapstructure:"multitenant"`
Debug DebugConfig `koanf:"debug" json:"debug" yaml:"debug" toml:"debug" mapstructure:"debug"`
Source SourceConfig `koanf:"source" json:"source" yaml:"source" toml:"source" mapstructure:"source"`
Scheduler SchedulerConfig `koanf:"scheduler" json:"scheduler" yaml:"scheduler" toml:"scheduler" mapstructure:"scheduler"`
Outbox OutboxConfig `koanf:"outbox" json:"outbox" yaml:"outbox" toml:"outbox" mapstructure:"outbox"`
Inbox InboxConfig `koanf:"inbox" json:"inbox" yaml:"inbox" toml:"inbox" mapstructure:"inbox"`
KeyStore KeyStoreConfig `koanf:"keystore" json:"keystore" yaml:"keystore" toml:"keystore" mapstructure:"keystore"`
// contains filtered or unexported fields
}
Config represents the overall application configuration structure. It includes sections for application settings, server parameters, database connection details, logging preferences, and messaging options. The underlying source (the unexported src field) allows for flexible access to additional custom configurations not explicitly defined in the struct, and carries the presence record the delivered-empty doors read (ADR-104).
func Load ¶
Load loads configuration from multiple sources with priority: 1. Environment variables (highest priority) 2. YAML configuration files 3. Default values (lowest priority)
The three operator layers (both YAML files and the environment) load through the source's recording merge, so presence — which keys the operator actually delivered — is recorded at the merge seam itself; the defaults load silently (ADR-104).
func (*Config) Bool ¶ added in v0.19.0
Bool retrieves a bool value from the configuration or the provided default. See getLenient for the absent / unusable contract; RequiredBool is the error-returning door.
func (*Config) Float64 ¶ added in v0.19.0
Float64 retrieves a float64 value from the configuration or the provided default. See getLenient for the absent / unusable contract; RequiredFloat64 is the error-returning door.
func (*Config) InjectInto ¶ added in v0.6.0
InjectInto populates a struct with configuration values based on struct tags. It supports the following struct tags:
- `config:"key.path"` - specifies the configuration key to use
- `required:"true"` - marks the field as required (default: false)
- `default:"value"` - provides a default value if the config key is missing
Supported field types: string, int, int64, float64, bool, time.Duration, []string ([]string accepts a comma-separated string from env/default tags or a native YAML sequence)
func (*Config) Int ¶ added in v0.19.0
Int retrieves an int value from the configuration or the provided default. See getLenient for the absent / unusable contract; RequiredInt is the error-returning door.
func (*Config) Int64 ¶ added in v0.19.0
Int64 retrieves an int64 value from the configuration or the provided default. See getLenient for the absent / unusable contract; RequiredInt64 is the error-returning door.
func (*Config) IsCacheCritical ¶ added in v0.56.0
IsCacheCritical reports whether a failing cache probe should fail /ready with 503. Non-critical by default (ADR-094): only an explicit cache.critical=true opts into readiness gating, so an absent key — and a nil receiver — leaves the probe informational.
func (*Config) PerTenantJobKeys ¶ added in v0.42.0
PerTenantJobKeys returns the tenant keys a per-tenant background job (e.g. the outbox relay or the outbox/inbox cleanup jobs) should iterate each cycle:
- single-tenant mode → a single "" key (one pass with no tenant in context; multitenant.SetTenant with "" is a no-op);
- static multi-tenant mode → the configured tenant IDs, sorted for deterministic iteration.
The result is empty ONLY for a degenerate static multi-tenant config with no tenants (multitenant.enabled=true but multitenant.tenants omitted) — callers must reject that, because a per-tenant job would otherwise silently iterate nothing. Dynamic multi-tenant sources are not enumerable here; callers reject them (or run in shared tenancy, which does not fan out) before relying on this.
func (*Config) RequiredBool ¶ added in v0.19.0
RequiredBool retrieves a required bool value from the configuration.
func (*Config) RequiredFloat64 ¶ added in v0.19.0
RequiredFloat64 retrieves a required float64 value from the configuration.
func (*Config) RequiredInt ¶ added in v0.19.0
RequiredInt retrieves a required int value from the configuration.
func (*Config) RequiredInt64 ¶ added in v0.19.0
RequiredInt64 retrieves a required int64 value from the configuration.
func (*Config) RequiredString ¶ added in v0.19.0
RequiredString retrieves a required string value from the configuration.
func (*Config) ShouldLogRoutes ¶ added in v0.49.0
ShouldLogRoutes reports whether the per-route "Route registered" startup lines should be emitted. An explicit server.logroutes value always wins; an absent key (nil) defaults to development mode (see AppConfig.IsDevelopment) so routes are visible at first `go run` while production stays silent. Nil-safe so it is correct whether or not Validate has run (a Builder assembled without WithConfig, or any Config built by hand outside app.NewWithConfig, still reaches this unvalidated).
type ConfigError ¶ added in v0.11.3
type ConfigError struct {
Category string // error category: "missing", "invalid", "not_configured", "connection"
Field string // config field path (e.g., "database.host", "messaging.broker.url")
Message string // user-friendly error message (lowercase)
Action string // actionable instruction (lowercase)
Details []string // additional details or examples
}
ConfigError represents a configuration error with actionable guidance. All error messages are lowercase following Go conventions.
func NewConnectionError ¶ added in v0.11.3
func NewConnectionError(resource, message string, troubleshooting []string) *ConfigError
NewConnectionError creates an error for connection failures with configured resources.
func NewInvalidFieldError ¶ added in v0.11.3
func NewInvalidFieldError(field, message string, validOptions []string) *ConfigError
NewInvalidFieldError creates an error for an invalid configuration value.
func NewMissingFieldError ¶ added in v0.11.3
func NewMissingFieldError(field, envVar, yamlPath string) *ConfigError
NewMissingFieldError creates an error for a required missing configuration field.
func NewMultiTenantError ¶ added in v0.11.3
func NewMultiTenantError(tenantID, field, message, action string) *ConfigError
NewMultiTenantError creates an error specific to multi-tenant configuration.
func NewNamedDatabaseError ¶ added in v0.22.0
func NewNamedDatabaseError(name string) *ConfigError
NewNamedDatabaseError creates an error for a missing named database configuration. This is used when DBByName() is called with a name that doesn't exist in the databases config section.
func NewNotConfiguredError ¶ added in v0.11.3
func NewNotConfiguredError(feature, envVar, yamlPath string) *ConfigError
NewNotConfiguredError creates an informational error for optional features. This indicates the feature is intentionally not configured, not an error state.
func NewValidationError ¶ added in v0.11.3
func NewValidationError(field, message string) *ConfigError
NewValidationError creates a general validation error with custom message.
func (*ConfigError) Error ¶ added in v0.11.3
func (e *ConfigError) Error() string
Error implements the error interface with lowercase formatting.
func (*ConfigError) Unwrap ¶ added in v0.11.3
func (e *ConfigError) Unwrap() error
Unwrap returns nil to maintain compatibility with error wrapping. ConfigError is a leaf error that contains all necessary context.
type DatabaseConfig ¶
type DatabaseConfig struct {
Type string `koanf:"type" json:"type" yaml:"type" toml:"type" mapstructure:"type"`
Host string `koanf:"host" json:"host" yaml:"host" toml:"host" mapstructure:"host"`
Port int `koanf:"port" json:"port" yaml:"port" toml:"port" mapstructure:"port"`
Database string `koanf:"database" json:"database" yaml:"database" toml:"database" mapstructure:"database"`
Username string `koanf:"username" json:"username" yaml:"username" toml:"username" mapstructure:"username"`
Password string `koanf:"password" json:"password" yaml:"password" toml:"password" mapstructure:"password"`
ConnectionString string `` /* 128-byte string literal not displayed */
// Timezone is the IANA timezone name applied to every new database session.
// Validated via time.LoadLocation at startup (fail-fast on invalid names).
// Default: "UTC". Set to "-" to disable session-level timezone enforcement
// (sessions then inherit the database server's default timezone).
// The literal "Local" is rejected; "-" is the only host-local spelling (ADR-093).
// Applies to both PostgreSQL (via pgx RuntimeParams) and Oracle (via
// ALTER SESSION SET TIME_ZONE on every new physical connection).
Timezone string `koanf:"timezone" json:"timezone" yaml:"timezone" toml:"timezone" mapstructure:"timezone"`
Pool PoolConfig `koanf:"pool" json:"pool" yaml:"pool" toml:"pool" mapstructure:"pool"`
Query QueryConfig `koanf:"query" json:"query" yaml:"query" toml:"query" mapstructure:"query"`
TLS TLSConfig `koanf:"tls" json:"tls" yaml:"tls" toml:"tls" mapstructure:"tls"`
PostgreSQL PostgreSQLConfig `koanf:"postgresql" json:"postgresql" yaml:"postgresql" toml:"postgresql" mapstructure:"postgresql"`
Oracle OracleConfig `koanf:"oracle" json:"oracle" yaml:"oracle" toml:"oracle" mapstructure:"oracle"`
// Manager applies only to the primary Config.Database, whose single
// database.DbManager also caches named databases.<name> and per-tenant handles.
Manager DatabaseManagerConfig `koanf:"manager" json:"manager" yaml:"manager" toml:"manager" mapstructure:"manager"`
}
DatabaseConfig holds database connection settings.
type DatabaseManagerConfig ¶ added in v0.49.0
type DatabaseManagerConfig struct {
// MaxSize is the maximum number of active database handles. 0 = use default
// (10 single-tenant / tenant limit multi-tenant); negative values are invalid.
MaxSize int `koanf:"maxsize" json:"maxsize" yaml:"maxsize" toml:"maxsize" mapstructure:"maxsize"`
// IdleTTL is the idle timeout before a database handle is closed.
// Default: 1h single-tenant / 30m multi-tenant.
IdleTTL time.Duration `koanf:"idlettl" json:"idlettl" yaml:"idlettl" toml:"idlettl" mapstructure:"idlettl"`
// CleanupInterval is how often the cleanup goroutine runs. Default: 5m.
CleanupInterval time.Duration `koanf:"cleanupinterval" json:"cleanupinterval" yaml:"cleanupinterval" toml:"cleanupinterval" mapstructure:"cleanupinterval"`
}
DatabaseManagerConfig holds database manager (key-cached connection pool) lifecycle settings. Per-mode defaults are documented on each field.
type DebugConfig ¶ added in v0.11.0
type DebugConfig struct {
Enabled bool `koanf:"enabled" json:"enabled" yaml:"enabled" toml:"enabled" mapstructure:"enabled"` // Enable debug endpoints
PathPrefix string `koanf:"pathprefix" json:"pathprefix" yaml:"pathprefix" toml:"pathprefix" mapstructure:"pathprefix"` // URL path prefix for debug endpoints
AllowedIPs []string `koanf:"allowedips" json:"allowedips" yaml:"allowedips" toml:"allowedips" mapstructure:"allowedips"` // List of allowed IP addresses/CIDRs
// TrustedProxies holds CIDR ranges of reverse proxies trusted to set X-Forwarded-For.
// X-Real-IP is never honored (ADR-057, completed by ADR-080), and a default route is
// rejected at startup.
// When empty (the default), proxy headers are IGNORED and the immediate peer
// IP is used for the AllowedIPs check — so the allowlist cannot be bypassed by spoofing
// X-Forwarded-For. Only set this to the CIDRs of proxies actually in front of the service.
TrustedProxies []string `koanf:"trustedproxies" json:"trustedproxies" yaml:"trustedproxies" toml:"trustedproxies" mapstructure:"trustedproxies"`
BearerToken string `koanf:"bearertoken" json:"bearertoken" yaml:"bearertoken" toml:"bearertoken" mapstructure:"bearertoken"`
Endpoints DebugEndpointsConfig `koanf:"endpoints" json:"endpoints" yaml:"endpoints" toml:"endpoints" mapstructure:"endpoints"` // Individual endpoint settings
}
DebugConfig holds debug endpoint settings.
type DebugEndpointsConfig ¶ added in v0.11.0
type DebugEndpointsConfig struct {
Goroutines bool `koanf:"goroutines" json:"goroutines" yaml:"goroutines" toml:"goroutines" mapstructure:"goroutines"` // Enable goroutine analysis endpoint
GC bool `koanf:"gc" json:"gc" yaml:"gc" toml:"gc" mapstructure:"gc"` // Enable garbage collection endpoints
Health bool `koanf:"health" json:"health" yaml:"health" toml:"health" mapstructure:"health"` // Enable enhanced health endpoint
Info bool `koanf:"info" json:"info" yaml:"info" toml:"info" mapstructure:"info"` // Enable system info endpoint
}
DebugEndpointsConfig holds settings for individual debug endpoints.
type ForwardedClientCertConfig ¶ added in v0.56.0
type ForwardedClientCertConfig struct {
Enabled bool `koanf:"enabled" json:"enabled" yaml:"enabled" toml:"enabled" mapstructure:"enabled"`
// Require rejects (401) any non-probe request whose identity headers are
// absent (neither -Subject nor -Serial-Number present); a malformed -Leaf
// alone never rejects. False = parse-and-expose only.
Require bool `koanf:"require" json:"require" yaml:"require" toml:"require" mapstructure:"require"`
}
ForwardedClientCertConfig consumes the client-certificate identity an AWS ALB forwards after terminating mutual TLS (X-Amzn-Mtls-Clientcert-* headers, verify mode). Enabling it is an explicit operator assertion that an mTLS-verify ALB listener fronts this service, direct target access is closed (security groups), and the target group is reachable only through that listener — the headers are trusted on that deployment posture alone. AWS does not document sanitization of client-supplied copies of these headers; see wiki/forwarded_client_cert.md for the trust model.
type GzipConfig ¶ added in v0.41.0
type GzipConfig struct {
// MinLength is the minimum response size in bytes before gzip compression is
// applied. Responses smaller than this are sent uncompressed, since the gzip
// header/overhead can exceed the savings for small payloads. Default: 1024.
MinLength int `koanf:"minlength" json:"minlength" yaml:"minlength" toml:"minlength" mapstructure:"minlength"`
}
GzipConfig holds HTTP response compression settings.
type IPPreGuardConfig ¶ added in v0.9.0
type IPPreGuardConfig struct {
Enabled bool `koanf:"enabled" json:"enabled" yaml:"enabled" toml:"enabled" mapstructure:"enabled"` // enable IP pre-guard rate limiting
Threshold int `koanf:"threshold" json:"threshold" yaml:"threshold" toml:"threshold" mapstructure:"threshold"` // requests per second limit per IP
}
IPPreGuardConfig holds IP pre-guard rate limiting settings.
type InboxConfig ¶ added in v0.40.0
type InboxConfig struct {
// Enabled activates the consumer-side inbox.
// When false, the inbox module is a no-op and deps.Inbox is nil.
Enabled bool `koanf:"enabled" json:"enabled" yaml:"enabled" toml:"enabled" mapstructure:"enabled"`
// TableName is the inbox ledger table name in the database.
// Default: "gobricks_inbox". Must be unqualified (no schema prefix) because the
// Oracle store derives a primary-key constraint name from it.
TableName string `koanf:"tablename" json:"tablename" yaml:"tablename" toml:"tablename" mapstructure:"tablename"`
// AutoCreateTable creates the inbox table on first use if it doesn't exist.
// Default: false (opt-in). Set true to auto-create (e.g. in development); leave
// false in production with managed migrations.
AutoCreateTable bool `koanf:"autocreatetable" json:"autocreatetable" yaml:"autocreatetable" toml:"autocreatetable" mapstructure:"autocreatetable"`
// RetentionPeriod is how long processed-event records are kept before cleanup.
// It MUST exceed the broker's maximum redelivery window, or a late redelivery
// could be reprocessed. The same window bounds every DLQ drain and every outbox
// re-drive: a message replayed after its ledger row was swept is processed
// again, so the retention period IS the replay window a deployment accepts.
// A zero value is treated as unset and replaced by the default; increase it to
// retain longer. Default: 168h (7 days).
RetentionPeriod time.Duration `koanf:"retentionperiod" json:"retentionperiod" yaml:"retentionperiod" toml:"retentionperiod" mapstructure:"retentionperiod"`
// Tenancy selects where the ledger lives when multitenant.enabled is true:
// - "per-tenant" (default): one dedup ledger per tenant DB; the retention
// cleanup job fans out across static multitenant.tenants.
// - "shared": one control-plane ledger resolved via the empty ("") key —
// the root database: block for the built-in store, or whatever a custom
// resource source returns for "". The cleanup job runs a single pass and
// ProcessOnce records/dedups against the shared ledger. See
// wiki/outbox.md and ADR-041.
// In single-tenant mode both values behave identically.
Tenancy string `koanf:"tenancy" json:"tenancy" yaml:"tenancy" toml:"tenancy" mapstructure:"tenancy"`
// Hold configures per-tenant parking of failed stream deliveries.
Hold InboxHoldConfig `koanf:"hold" json:"hold" yaml:"hold" toml:"hold" mapstructure:"hold"`
}
InboxConfig holds consumer-side idempotency (inbox) settings. The inbox is the durable complement to the outbox: it records processed event ids in a ledger so redeliveries are skipped. Default values when inbox is enabled (AutoCreateTable is opt-in: its default false is the zero value, not actively applied):
- TableName: "gobricks_inbox"
- AutoCreateTable: false (opt-in; set true to create the table on first use)
- RetentionPeriod: 168h / 7d (must exceed the broker's max redelivery window)
type InboxHoldConfig ¶ added in v0.61.0
type InboxHoldConfig struct {
// Enabled activates the hold ledger and its drain job.
// Default: false (opt-in).
Enabled bool `koanf:"enabled" json:"enabled" yaml:"enabled" toml:"enabled" mapstructure:"enabled"`
// TableName is the hold row table; the tenant table is "<tablename>_tenant".
// Must be unqualified. Default: "gobricks_inbox_hold".
TableName string `koanf:"tablename" json:"tablename" yaml:"tablename" toml:"tablename" mapstructure:"tablename"`
// DrainInterval is how often the drain job looks for due tenants.
// Default: 5s.
DrainInterval time.Duration `koanf:"draininterval" json:"draininterval" yaml:"draininterval" toml:"draininterval" mapstructure:"draininterval"`
// MaxBackoff caps the drain's per-tenant retry backoff. Default: 5m.
MaxBackoff time.Duration `koanf:"maxbackoff" json:"maxbackoff" yaml:"maxbackoff" toml:"maxbackoff" mapstructure:"maxbackoff"`
// MaxAge is how long a tenant may stay held before each drain pass logs one
// WARN naming it. Default: 1h.
MaxAge time.Duration `koanf:"maxage" json:"maxage" yaml:"maxage" toml:"maxage" mapstructure:"maxage"`
// LeaseDuration is how long one drainer holds a tenant, and therefore the
// time bound on a replayed handler. Default: 60s.
LeaseDuration time.Duration `koanf:"leaseduration" json:"leaseduration" yaml:"leaseduration" toml:"leaseduration" mapstructure:"leaseduration"`
}
InboxHoldConfig holds the per-tenant hold ledger's settings. A hold keeps a tenant's later messages behind a failed one while the rest of the partition keeps flowing, and a scheduled drain replays them in order.
It requires inbox.tenancy: shared — a tenant whose own database is down cannot hold its own messages. Held rows are never dropped automatically: only a successful replay removes one, and an operator deletes the rest by hand. The DDL for managed migrations is in wiki/outbox.md.
type KeyPairConfig ¶ added in v0.27.0
type KeyPairConfig struct {
Public KeySourceConfig `koanf:"public" json:"public" yaml:"public" toml:"public" mapstructure:"public"`
Private KeySourceConfig `koanf:"private" json:"private" yaml:"private" toml:"private" mapstructure:"private"`
// Secret holds raw symmetric key material (HMAC/CMAC key, HKDF input).
// Mutually exclusive with Public/Private.
Secret KeySourceConfig `koanf:"secret" json:"secret" yaml:"secret" toml:"secret" mapstructure:"secret"`
// PKCS12 loads the RSA pair from a password-protected PKCS#12 bundle.
// Mutually exclusive with Public/Private and Secret.
PKCS12 PKCS12SourceConfig `koanf:"pkcs12" json:"pkcs12" yaml:"pkcs12" toml:"pkcs12" mapstructure:"pkcs12"`
}
KeyPairConfig holds key material for one logical name. An entry is exactly one of: an RSA key pair (Public required, Private optional), a symmetric Secret, or a PKCS12 bundle. A mixed entry is rejected at startup (structural detection; no explicit discriminator needed).
type KeySourceConfig ¶ added in v0.27.0
type KeySourceConfig struct {
File string `koanf:"file" json:"file" yaml:"file" toml:"file" mapstructure:"file"`
Value string `koanf:"value" json:"value" yaml:"value" toml:"value" mapstructure:"value"`
}
KeySourceConfig specifies where to load a key from. For required keys (e.g., public), exactly one of File or Value must be set. For optional keys (e.g., private in verification-only services), both may be empty.
- File: path to a key file — DER bytes for RSA, raw key bytes for a secret (local development)
- Value: base64-encoded bytes — DER for RSA, raw key material for a secret (EKS deployment via env vars)
func (*KeySourceConfig) IsSet ¶ added in v0.35.0
func (s *KeySourceConfig) IsSet() bool
IsSet reports whether this source has any material configured (file or value). It is the single source of truth for "is a key source populated", shared by config validation and the keystore loader.
type KeyStoreConfig ¶ added in v0.27.0
type KeyStoreConfig struct {
// Keys maps logical names to key material configurations; see
// KeyPairConfig for the accepted shapes.
// Example names: "signing", "encryption", "legacy", "my-mac-key".
Keys map[string]KeyPairConfig `koanf:"keys" json:"keys" yaml:"keys" toml:"keys" mapstructure:"keys"`
// SecretMinLength is the minimum byte length enforced for symmetric secret
// entries at startup. nil means the default applies
// (DefaultKeyStoreSecretMinLength, 32), filled by normalize; a set value
// can only raise the floor — anything below 32, the former 0 opt-out
// included, is rejected by check (ADR-095). A pointer so the koanf and
// literal doors both tell absent from explicit, see CONTEXT.md.
SecretMinLength *int `koanf:"secretminlength" json:"secretminlength" yaml:"secretminlength" toml:"secretminlength" mapstructure:"secretminlength"`
}
KeyStoreConfig holds named key material configuration. Keys can be loaded from files (local dev) or base64-encoded values (EKS deployment).
func (*KeyStoreConfig) SecretFloor ¶ added in v0.59.0
func (c *KeyStoreConfig) SecretFloor() int
SecretFloor is the effective keystore.secretminlength: the documented default when the pointer is nil, otherwise the configured value, which check has bounded at that default or above (ADR-095). Validate's normalize fills the pointer with this same answer, so after Validate the two never disagree; the accessor exists for the reader, as IsCacheCritical does for cache.critical.
type LifetimeConfig ¶ added in v0.7.1
type LifetimeConfig struct {
// Max is the maximum duration a connection may be reused before closing.
// This forces periodic connection recycling for memory hygiene, DNS re-resolution,
// and server-side resource cleanup.
// Default: 30m. Set to 0 for no lifetime limit (not recommended for cloud deployments).
Max time.Duration `koanf:"max" json:"max" yaml:"max" toml:"max" mapstructure:"max"`
}
LifetimeConfig holds maximum lifetime settings for connections.
type LimitsConfig ¶ added in v0.9.0
type LimitsConfig struct {
Tenants int `koanf:"tenants" json:"tenants" yaml:"tenants" toml:"tenants" mapstructure:"tenants"`
}
LimitsConfig holds resource limits for multi-tenant operation.
type LogConfig ¶
type LogConfig struct {
Level string `koanf:"level" json:"level" yaml:"level" toml:"level" mapstructure:"level"`
Pretty bool `koanf:"pretty" json:"pretty" yaml:"pretty" toml:"pretty" mapstructure:"pretty"`
Output OutputConfig `koanf:"output" json:"output" yaml:"output" toml:"output" mapstructure:"output"`
// SensitiveFields extends logger.DefaultFilterConfig with extra field
// names whose values must be masked in log output. Matching is
// case-insensitive substring on the field name, so "pan" masks "pan",
// "card_pan", and "panHash" — not the reverse; "primary_account_number"
// is its own default needle.
// Use this for PAN variants and service-specific PII (SSN, tax ID, etc.) without writing
// Go code. For full control over the FilterConfig (e.g., custom MaskValue
// or opting out of defaults), set app.Options.LoggerFilterConfig instead;
// that field takes precedence over this one.
SensitiveFields []string `koanf:"sensitivefields" json:"sensitivefields" yaml:"sensitivefields" toml:"sensitivefields" mapstructure:"sensitivefields"`
}
LogConfig holds logging settings. See OutputConfig.Format for the rendering-mode selector (auto/console/json) and the legacy Pretty override.
type MessagingConfig ¶
type MessagingConfig struct {
Broker BrokerConfig `koanf:"broker" json:"broker" yaml:"broker" toml:"broker" mapstructure:"broker"`
Routing RoutingConfig `koanf:"routing" json:"routing" yaml:"routing" toml:"routing" mapstructure:"routing"`
Headers map[string]string `koanf:"headers" json:"headers" yaml:"headers" toml:"headers" mapstructure:"headers"`
Reconnect ReconnectConfig `koanf:"reconnect" json:"reconnect" yaml:"reconnect" toml:"reconnect" mapstructure:"reconnect"`
Publisher PublisherPoolConfig `koanf:"publisher" json:"publisher" yaml:"publisher" toml:"publisher" mapstructure:"publisher"`
Streams StreamsConfig `koanf:"streams" json:"streams" yaml:"streams" toml:"streams" mapstructure:"streams"`
// Tenancy selects which key the messaging kind's consumers and publishers are
// resolved and replayed under when multitenant.enabled is true:
// - "per-tenant" (default): one client per tenant, replayed lazily from
// multitenant.tenants.<id>.messaging or the resource source.
// - "shared": one control-plane client resolved via the empty ("") key —
// the root messaging: block, or whatever a custom resource source returns
// for "". Consumers replay once at boot and the tenant travels as the
// x-tenant-id stamp. That is the contract this key names; it is served
// from the classic-lane slice onward, and the config layer accepts it
// first so the two land as reviewable steps. See wiki/messaging.md and
// ADR-087.
// In single-tenant mode both values behave identically.
Tenancy string `koanf:"tenancy" json:"tenancy" yaml:"tenancy" toml:"tenancy" mapstructure:"tenancy"`
// Seal holds the producer-side AMQP payload-sealing settings.
Seal SealConfig `koanf:"seal" json:"seal" yaml:"seal" toml:"seal" mapstructure:"seal"`
// PublishTimeout is the aggregate per-publish bound: when set (> 0), the whole
// publish — readiness pre-flight plus the entire retry loop — runs under a
// context deadline of this duration, layered under any tighter caller deadline.
// Unset or zero is unbounded (the pre-key behavior). Startup rejects a negative
// value, and any value below messaging.reconnect.readytimeout +
// messaging.reconnect.connectiontimeout, which could truncate a healthy
// cold-path first attempt into a false failure. A value below
// reconnect.maxpublishattempts × reconnect.connectiontimeout deliberately
// lowers the effective retry count, and is accepted without a warning.
// The bound governs waiting, not an in-flight socket write: waiting for the
// publish slot is bounded by the deadline, the socket write is not.
// amqp091-go's PublishWithContext checks the context only before it starts,
// so a broker that stops reading can hold that one publish past the deadline
// until the write returns; the publishers queued behind it acquire the slot
// under their own context and are released at their own deadlines with
// context.DeadlineExceeded.
// See wiki/messaging.md#aggregate-publish-bound-publishtimeout.
PublishTimeout time.Duration `koanf:"publishtimeout" json:"publishtimeout" yaml:"publishtimeout" toml:"publishtimeout" mapstructure:"publishtimeout"`
}
MessagingConfig holds messaging/broker settings. Production-safe defaults are applied unconditionally at startup — even when messaging.broker.url is unset (see config/messaging_section.go: normalizeMessaging).
type MultitenantConfig ¶ added in v0.9.0
type MultitenantConfig struct {
Enabled bool `koanf:"enabled" json:"enabled" yaml:"enabled" toml:"enabled" mapstructure:"enabled"`
Resolver ResolverConfig `koanf:"resolver" json:"resolver" yaml:"resolver" toml:"resolver" mapstructure:"resolver"`
Limits LimitsConfig `koanf:"limits" json:"limits" yaml:"limits" toml:"limits" mapstructure:"limits"`
Tenants map[string]TenantEntry `koanf:"tenants" json:"tenants" yaml:"tenants" toml:"tenants" mapstructure:"tenants"`
}
MultitenantConfig holds multi-tenant specific settings.
type OracleConfig ¶ added in v0.7.1
type OracleConfig struct {
Service ServiceConfig `koanf:"service" json:"service" yaml:"service" toml:"service" mapstructure:"service"`
}
OracleConfig holds Oracle-specific database settings.
type OutboxConfig ¶ added in v0.27.0
type OutboxConfig struct {
// Enabled activates the transactional outbox pattern.
// When false, the outbox module is a no-op and deps.Outbox is nil.
Enabled bool `koanf:"enabled" json:"enabled" yaml:"enabled" toml:"enabled" mapstructure:"enabled"`
// TableName is the outbox table name in the database.
// The table segment is bounded at 49 bytes so every identifier derived from it — the
// "idx_<name>_published" index and the "<name>_leader" companion table — stays distinct
// under PostgreSQL's 63-byte truncation.
// Default: "gobricks_outbox".
TableName string `koanf:"tablename" json:"tablename" yaml:"tablename" toml:"tablename" mapstructure:"tablename"`
// AutoCreateTable creates the outbox table on first use if it doesn't exist.
// Default: false (opt-in). Set true to auto-create (e.g. in development); leave
// false in production with managed migrations.
AutoCreateTable bool `koanf:"autocreatetable" json:"autocreatetable" yaml:"autocreatetable" toml:"autocreatetable" mapstructure:"autocreatetable"`
// DefaultExchange is the fallback AMQP exchange when Event.Exchange is empty.
// Default: "" (empty, which publishes to the default exchange). It must fit the AMQP
// shortstr limit (255 bytes) — a longer value makes every event that falls back to it
// unpublishable, so the outbox module fails to start.
DefaultExchange string `koanf:"defaultexchange" json:"defaultexchange" yaml:"defaultexchange" toml:"defaultexchange" mapstructure:"defaultexchange"`
// PollInterval is how often the relay checks for pending events.
// Default: 5s. Lower values reduce latency but increase database load.
PollInterval time.Duration `koanf:"pollinterval" json:"pollinterval" yaml:"pollinterval" toml:"pollinterval" mapstructure:"pollinterval"`
// BatchSize is the maximum number of events processed per relay cycle.
// Default: 100. Higher values improve throughput but increase memory usage.
BatchSize int `koanf:"batchsize" json:"batchsize" yaml:"batchsize" toml:"batchsize" mapstructure:"batchsize"`
// MaxRetries is the retry ceiling after which a *poison* event — one of the
// deterministic, broker-independent classes enumerated in wiki/outbox.md under
// Retry & Dead-Lettering — is dead-lettered to status "failed" and stops being
// retried. Connectivity failures (broker down, NACK, confirmation timeout) advance
// retry_count but are NEVER dead-lettered by this count, so neither a prolonged outage
// nor a transient broker fault can park healthy events. Default: 5.
MaxRetries int `koanf:"maxretries" json:"maxretries" yaml:"maxretries" toml:"maxretries" mapstructure:"maxretries"`
// RetentionPeriod is how long published events are kept before cleanup.
// Set to 0 to disable automatic cleanup.
// Default: 72h.
RetentionPeriod time.Duration `koanf:"retentionperiod" json:"retentionperiod" yaml:"retentionperiod" toml:"retentionperiod" mapstructure:"retentionperiod"`
// PublishTimeout bounds a single relay publish attempt so one stuck record cannot
// block the whole relay cycle (and starve the rest of the batch). It MUST be >=
// messaging.reconnect.connectiontimeout — the outbox module fails to start otherwise,
// because a shorter value truncates every legitimate confirmation into a false failure
// and re-publishes the (already-delivered) event every cycle. Default: 60s.
PublishTimeout time.Duration `koanf:"publishtimeout" json:"publishtimeout" yaml:"publishtimeout" toml:"publishtimeout" mapstructure:"publishtimeout"`
// Tenancy selects where the ledger lives when multitenant.enabled is true:
// - "per-tenant" (default): one ledger per tenant DB; relay/cleanup fan out
// across static multitenant.tenants.
// - "shared": one control-plane ledger resolved via the empty ("") key —
// the root database:/messaging: blocks for the built-in store, or
// whatever a custom resource source returns for "". Relay/cleanup run a
// single pass. See wiki/outbox.md and ADR-041.
// In single-tenant mode both values behave identically.
Tenancy string `koanf:"tenancy" json:"tenancy" yaml:"tenancy" toml:"tenancy" mapstructure:"tenancy"`
// SuperStreams lists the super streams the relay may publish to over the native streams
// lane. Each name must be declared as a super stream by a module's DeclareStreams; the
// outbox declares its own publisher for each. Requires messaging.streams.uri.
// Default: none — every event stays on the AMQP lane.
// Listing a name here declares one publisher for it, so a super stream the outbox
// targets cannot also be published to directly by another module in the process.
SuperStreams []string `koanf:"superstreams" json:"superstreams" yaml:"superstreams" toml:"superstreams" mapstructure:"superstreams"`
}
OutboxConfig holds transactional outbox settings. Default values when outbox is enabled (AutoCreateTable is opt-in: its default false is the zero value, not actively applied):
- TableName: "gobricks_outbox"
- AutoCreateTable: false (opt-in; set true to create the table on first use)
- PollInterval: 5s (relay poll frequency)
- BatchSize: 100 (events per relay cycle)
- MaxRetries: 5 (poison-event dead-letter ceiling; connectivity failures advance retry_count but are never dead-lettered by this count — see the MaxRetries field doc)
- RetentionPeriod: 72h (cleanup published events older than this)
- PublishTimeout: 60s (per-record relay publish bound)
type OutputConfig ¶ added in v0.7.1
type OutputConfig struct {
Format string `koanf:"format" json:"format" yaml:"format" toml:"format" mapstructure:"format"`
File string `koanf:"file" json:"file" yaml:"file" toml:"file" mapstructure:"file"`
}
OutputConfig holds log output settings.
Format selects the rendering mode for stdout, evaluated case-insensitively:
- "auto" (default): console output only when stdout is a terminal AND OTLP log export is not active; otherwise JSON.
- "console" / "pretty": always console (colored).
- "json" / "structured": always JSON.
LogConfig.Pretty=true is a legacy override that always forces console output. Console output is incompatible with OTLP log export — that combination panics at startup via logger.WithOTelProvider.
type PKCS12SourceConfig ¶ added in v0.62.0
type PKCS12SourceConfig struct {
File string `koanf:"file" json:"file" yaml:"file" toml:"file" mapstructure:"file"`
Value string `koanf:"value" json:"value" yaml:"value" toml:"value" mapstructure:"value"`
Password PasswordSourceConfig `koanf:"password" json:"password" yaml:"password" toml:"password" mapstructure:"password"`
}
PKCS12SourceConfig names a password-protected PKCS#12 (.p12/.pfx) bundle: exactly one of File (path) or Value (base64 DER), plus the Password source.
func (*PKCS12SourceConfig) Bundle ¶ added in v0.62.0
func (p *PKCS12SourceConfig) Bundle() KeySourceConfig
Bundle is the bundle's file-or-value source, for the shared loader path.
func (*PKCS12SourceConfig) IsSet ¶ added in v0.62.0
func (p *PKCS12SourceConfig) IsSet() bool
IsSet reports whether any part of the PKCS#12 stanza is configured.
type PasswordSourceConfig ¶ added in v0.62.0
type PasswordSourceConfig struct {
Env string `koanf:"env" json:"env" yaml:"env" toml:"env" mapstructure:"env"`
File string `koanf:"file" json:"file" yaml:"file" toml:"file" mapstructure:"file"`
}
PasswordSourceConfig names where a password is read from at startup — the environment variable Env or the file File — never the password itself.
func (*PasswordSourceConfig) IsSet ¶ added in v0.62.0
func (p *PasswordSourceConfig) IsSet() bool
IsSet reports whether a password source is configured.
type PathConfig ¶ added in v0.7.1
type PathConfig struct {
Base string `koanf:"base" json:"base" yaml:"base" toml:"base" mapstructure:"base"`
Health string `koanf:"health" json:"health" yaml:"health" toml:"health" mapstructure:"health"`
Ready string `koanf:"ready" json:"ready" yaml:"ready" toml:"ready" mapstructure:"ready"`
}
PathConfig holds URL path settings for the server.
type PathResolverConfig ¶ added in v0.34.0
type PathResolverConfig struct {
Segment int `koanf:"segment" json:"segment" yaml:"segment" toml:"segment" mapstructure:"segment"`
Prefix string `koanf:"prefix" json:"prefix" yaml:"prefix" toml:"prefix" mapstructure:"prefix"`
}
PathResolverConfig holds settings for the path-segment tenant resolver.
Segment is 1-indexed: 1 = first non-empty path part after the leading slash. Prefix is an optional gate — when set, only requests whose path equals Prefix exactly or starts with "Prefix/" are eligible for extraction (useful when a service hosts both tenant-scoped and non-tenant-scoped routes).
type PoolConfig ¶ added in v0.7.1
type PoolConfig struct {
Max PoolMaxConfig `koanf:"max" json:"max" yaml:"max" toml:"max" mapstructure:"max"`
Idle PoolIdleConfig `koanf:"idle" json:"idle" yaml:"idle" toml:"idle" mapstructure:"idle"`
Lifetime LifetimeConfig `koanf:"lifetime" json:"lifetime" yaml:"lifetime" toml:"lifetime" mapstructure:"lifetime"`
KeepAlive PoolKeepAliveConfig `koanf:"keepalive" json:"keepalive" yaml:"keepalive" toml:"keepalive" mapstructure:"keepalive"`
}
PoolConfig holds connection pool settings. Production-safe defaults are applied automatically when database is configured:
- Max.Connections: 25 (maximum open connections)
- Idle.Connections: tracks Max.Connections (idle cap, avoids connection churn)
- Idle.Time: 5m (close idle connections before NAT/firewall timeout)
- Lifetime.Max: 30m (periodic connection recycling)
- KeepAlive.Enabled: true (TCP keep-alive probes)
- KeepAlive.Interval: 60s (probe interval, below typical NAT timeouts)
type PoolIdleConfig ¶ added in v0.7.1
type PoolIdleConfig struct {
// Connections is the maximum number of idle connections kept open in the pool.
// This is a cap (database/sql clamps it to Max.Connections), not a floor — the
// pool does not pre-warm connections.
// Default: tracks Max.Connections. Keeping idle below max causes the pool to
// churn physical connections under sustained load; set a lower value only when
// you deliberately want to release idle connections back to the database.
Connections int32 `koanf:"connections" json:"connections" yaml:"connections" toml:"connections" mapstructure:"connections"`
// Time is the maximum duration an idle connection may remain unused before closing.
// This prevents stale connections from accumulating when traffic decreases.
// Default: 5m. Should be shorter than NAT/firewall idle timeouts (AWS: 350s, GCP: 30s).
// Combined with KeepAlive, connections are recycled before becoming stale.
Time time.Duration `koanf:"time" json:"time" yaml:"time" toml:"time" mapstructure:"time"`
}
PoolIdleConfig holds idle connections settings.
type PoolKeepAliveConfig ¶ added in v0.18.2
type PoolKeepAliveConfig struct {
// Enabled enables TCP keep-alive probes on database connections.
// Default: true. Recommended for all cloud deployments.
//
// A pointer is used so an absent key (nil) is distinguishable from an
// explicit false: validation defaults nil to true, but an explicit
// enabled=false is always honored — even when Interval is left at its
// zero default. Use IsEnabled for nil-safe reads.
Enabled *bool `koanf:"enabled" json:"enabled" yaml:"enabled" toml:"enabled" mapstructure:"enabled"`
// Interval is the time between keep-alive probes (TCP_KEEPINTVL).
// The kernel sends a probe every Interval to keep the connection alive.
// Default: 60s. Should be less than NAT/LB idle timeout (AWS: 350s, GCP: 600s).
Interval time.Duration `koanf:"interval" json:"interval" yaml:"interval" toml:"interval" mapstructure:"interval"`
}
PoolKeepAliveConfig holds TCP keep-alive settings for database connections. TCP Keep-Alive sends periodic probes to prevent NAT gateways, load balancers, and firewalls from dropping idle connections. This is essential for cloud deployments (AWS, GCP, Azure) where infrastructure typically has idle connection timeouts (e.g., AWS NAT Gateway: 350 seconds).
func (PoolKeepAliveConfig) IsEnabled ¶ added in v0.43.0
func (c PoolKeepAliveConfig) IsEnabled() bool
IsEnabled reports whether TCP keep-alive is enabled, treating an absent (nil) Enabled as disabled. After config validation Enabled is always non-nil; the nil guard protects direct struct construction (e.g. tests) that bypasses validation.
type PoolMaxConfig ¶ added in v0.7.1
type PoolMaxConfig struct {
// Connections is the maximum number of open connections to the database.
// Default: 25. Set based on your workload and database server capacity.
Connections int32 `koanf:"connections" json:"connections" yaml:"connections" toml:"connections" mapstructure:"connections"`
}
PoolMaxConfig holds maximum connections settings.
type PostgreSQLConfig ¶ added in v0.12.0
type PostgreSQLConfig struct {
Schema string `koanf:"schema" json:"schema" yaml:"schema" toml:"schema" mapstructure:"schema"`
}
PostgreSQLConfig holds PostgreSQL-specific database settings.
type PublisherPoolConfig ¶ added in v0.19.0
type PublisherPoolConfig struct {
// MaxCached is the maximum number of publisher clients to keep in the cache.
// Default: 50. Set higher for applications with many tenants.
MaxCached int `koanf:"maxcached" json:"maxcached" yaml:"maxcached" toml:"maxcached" mapstructure:"maxcached"`
// IdleTTL is the time after which idle publisher clients are evicted.
// Default: 1h when multitenant.enabled is false, 10m when true (see
// config/messaging_section.go: applyMessagingDefaults). Set lower for
// memory-constrained environments.
IdleTTL time.Duration `koanf:"idlettl" json:"idlettl" yaml:"idlettl" toml:"idlettl" mapstructure:"idlettl"`
// CleanupInterval is how often the publisher-pool cleanup goroutine runs.
// Default: 2m. Should be less than IdleTTL for effective cleanup.
CleanupInterval time.Duration `koanf:"cleanupinterval" json:"cleanupinterval" yaml:"cleanupinterval" toml:"cleanupinterval" mapstructure:"cleanupinterval"`
}
PublisherPoolConfig holds publisher cache/pool settings. Production-safe defaults are applied automatically:
- MaxCached: 50 (maximum publisher clients in cache)
- IdleTTL: 1h single-tenant / 10m multi-tenant (time before idle publishers are evicted)
- CleanupInterval: 2m (cleanup goroutine frequency)
type QueryConfig ¶ added in v0.7.1
type QueryConfig struct {
Slow SlowQueryConfig `koanf:"slow" json:"slow" yaml:"slow" toml:"slow" mapstructure:"slow"`
Log QueryLogConfig `koanf:"log" json:"log" yaml:"log" toml:"log" mapstructure:"log"`
}
QueryConfig holds settings related to query logging and slow query detection.
type QueryLogConfig ¶ added in v0.7.1
type QueryLogConfig struct {
Parameters bool `koanf:"parameters" json:"parameters" yaml:"parameters" toml:"parameters" mapstructure:"parameters"`
MaxLength int `koanf:"max" json:"max" yaml:"max" toml:"max" mapstructure:"max"`
}
QueryLogConfig holds settings for query logging.
type RateConfig ¶ added in v0.7.0
type RateConfig struct {
Limit int `koanf:"limit" json:"limit" yaml:"limit" toml:"limit" mapstructure:"limit"`
Burst int `koanf:"burst" json:"burst" yaml:"burst" toml:"burst" mapstructure:"burst"`
IPPreGuard IPPreGuardConfig `koanf:"ippreguard" json:"ippreguard" yaml:"ippreguard" toml:"ippreguard" mapstructure:"ippreguard"`
}
RateConfig holds rate limiting settings.
type ReconnectConfig ¶ added in v0.19.0
type ReconnectConfig struct {
// Delay is the initial delay between reconnection attempts.
// Default: 5s. Set higher for unstable networks.
Delay time.Duration `koanf:"delay" json:"delay" yaml:"delay" toml:"delay" mapstructure:"delay"`
// ReinitDelay is the delay before channel reinitialization after failure.
// Default: 2s.
ReinitDelay time.Duration `koanf:"reinitdelay" json:"reinitdelay" yaml:"reinitdelay" toml:"reinitdelay" mapstructure:"reinitdelay"`
// ResendDelay is the delay before retrying a failed publish operation.
// Default: 5s.
ResendDelay time.Duration `koanf:"resenddelay" json:"resenddelay" yaml:"resenddelay" toml:"resenddelay" mapstructure:"resenddelay"`
// ConnectionTimeout is the per-publish broker confirmation timeout — how long a
// confirmed publish waits for the broker's ACK/NACK before the attempt is retried.
// The TCP/AMQP connection dial itself is bounded by amqp091-go's amqp.Dial default,
// not by this value. Default: 30s. Set higher for high-latency networks.
ConnectionTimeout time.Duration `` /* 133-byte string literal not displayed */
// ReadyTimeout bounds how long a publish will wait, before entering the
// bounded retry loop, for a not-yet-ready client (cold start or
// mid-reconnect) to become ready. The wait does not consume a
// MaxPublishAttempts slot. Default: 5s. Must be >= 0.
ReadyTimeout time.Duration `koanf:"readytimeout" json:"readytimeout" yaml:"readytimeout" toml:"readytimeout" mapstructure:"readytimeout"`
// MaxPublishAttempts bounds the per-publish retry loop: after this many failed
// attempts a publish returns an error instead of retrying forever. This is what
// lets the outbox relay regain control and advance an event's retry_count.
// Default: 5. Must be >= 1 (0 applies the default).
MaxPublishAttempts int `` /* 138-byte string literal not displayed */
// MaxDelay is the maximum delay for exponential backoff during reconnection.
// Default: 60s. Prevents unbounded delays during prolonged outages.
MaxDelay time.Duration `koanf:"maxdelay" json:"maxdelay" yaml:"maxdelay" toml:"maxdelay" mapstructure:"maxdelay"`
}
ReconnectConfig holds AMQP reconnection settings. Production-safe defaults are applied automatically:
- Delay: 5s (initial delay between reconnection attempts)
- ReinitDelay: 2s (delay before channel reinitialization)
- ResendDelay: 5s (delay before retrying failed publishes)
- ConnectionTimeout: 30s (per-publish broker ACK/NACK confirmation wait)
- ReadyTimeout: 5s (pre-flight wait for a not-yet-ready client, before a publish begins)
- MaxPublishAttempts: 5 (bounded publish retry attempts before giving up)
- MaxDelay: 60s (maximum delay for exponential backoff cap)
type RedisConfig ¶ added in v0.18.0
type RedisConfig struct {
Host string `koanf:"host" json:"host" yaml:"host" toml:"host" mapstructure:"host"`
Port int `koanf:"port" json:"port" yaml:"port" toml:"port" mapstructure:"port"`
Password string `koanf:"password" json:"password" yaml:"password" toml:"password" mapstructure:"password"`
Database int `koanf:"database" json:"database" yaml:"database" toml:"database" mapstructure:"database"`
PoolSize int `koanf:"poolsize" json:"poolsize" yaml:"poolsize" toml:"poolsize" mapstructure:"poolsize"`
DialTimeout time.Duration `koanf:"dialtimeout" json:"dialtimeout" yaml:"dialtimeout" toml:"dialtimeout" mapstructure:"dialtimeout"`
ReadTimeout time.Duration `koanf:"readtimeout" json:"readtimeout" yaml:"readtimeout" toml:"readtimeout" mapstructure:"readtimeout"`
WriteTimeout time.Duration `koanf:"writetimeout" json:"writetimeout" yaml:"writetimeout" toml:"writetimeout" mapstructure:"writetimeout"`
MaxRetries int `koanf:"maxretries" json:"maxretries" yaml:"maxretries" toml:"maxretries" mapstructure:"maxretries"`
MinRetryBackoff time.Duration `koanf:"minretrybackoff" json:"minretrybackoff" yaml:"minretrybackoff" toml:"minretrybackoff" mapstructure:"minretrybackoff"`
MaxRetryBackoff time.Duration `koanf:"maxretrybackoff" json:"maxretrybackoff" yaml:"maxretrybackoff" toml:"maxretrybackoff" mapstructure:"maxretrybackoff"`
}
RedisConfig holds Redis-specific cache settings.
type ResolverConfig ¶ added in v0.9.0
type ResolverConfig struct {
Type string `koanf:"type" json:"type" yaml:"type" toml:"type" mapstructure:"type"` // header, subdomain, path, composite
Header string `koanf:"header" json:"header" yaml:"header" toml:"header" mapstructure:"header"` // default: X-Tenant-ID
Domain string `koanf:"domain" json:"domain" yaml:"domain" toml:"domain" mapstructure:"domain"` // e.g., api.example.com or .api.example.com (leading dot optional)
Proxies bool `koanf:"proxies" json:"proxies" yaml:"proxies" toml:"proxies" mapstructure:"proxies"` // trust X-Forwarded-Host
Path PathResolverConfig `koanf:"path" json:"path" yaml:"path" toml:"path" mapstructure:"path"` // path-segment resolver settings
// Order controls composite sub-resolver precedence (type: composite only) and
// is REQUIRED when type is composite — there is no implicit default; a
// composite config with an empty Order fails validation. Valid entries:
// header, subdomain, path. A sub-resolver named in Order must also be
// configured: Validate REJECTS a composite naming path without
// path.segment > 0, or subdomain without a domain. (Only a config that
// bypasses Validate entirely reaches the builder, where an unconfigured
// sub-resolver is skipped instead.) See DefaultResolverOrder for the
// recommended value and the rationale for not defaulting it.
Order []string `koanf:"order" json:"order" yaml:"order" toml:"order" mapstructure:"order"`
}
ResolverConfig holds tenant resolution strategy settings.
type ResponseTimeConfig ¶ added in v0.41.0
type ResponseTimeConfig struct {
// Enabled adds an X-Response-Time response header (per-request processing
// time) when true. Default false: the header costs a per-response header
// allocation and OTel provides richer latency telemetry. Opt in for local
// debugging or when a consumer depends on the header.
Enabled bool `koanf:"enabled" json:"enabled" yaml:"enabled" toml:"enabled" mapstructure:"enabled"`
}
ResponseTimeConfig controls the optional X-Response-Time diagnostic header.
type RoutingConfig ¶ added in v0.7.1
type RoutingConfig struct {
Exchange string `koanf:"exchange" json:"exchange" yaml:"exchange" toml:"exchange" mapstructure:"exchange"`
Key string `koanf:"key" json:"key" yaml:"key" toml:"key" mapstructure:"key"`
}
RoutingConfig holds message routing settings.
type SchedulerConfig ¶ added in v0.14.0
type SchedulerConfig struct {
Security SchedulerSecurityConfig `koanf:"security" json:"security" yaml:"security" toml:"security" mapstructure:"security"`
Timeout SchedulerTimeoutConfig `koanf:"timeout" json:"timeout" yaml:"timeout" toml:"timeout" mapstructure:"timeout"`
// Timezone is the IANA timezone name the scheduler uses to interpret
// wall-clock schedules (DailyAt/WeeklyAt/MonthlyAt/HourlyAt). Validated via
// time.LoadLocation at startup (fail-fast on invalid names).
// Default: "UTC". Set to "-" to use the host's local time (legacy behavior).
// The literal "Local" is rejected; "-" is the only host-local spelling (ADR-093).
Timezone string `koanf:"timezone" json:"timezone" yaml:"timezone" toml:"timezone" mapstructure:"timezone"`
}
SchedulerConfig holds job scheduler settings.
type SchedulerSecurityConfig ¶ added in v0.14.0
type SchedulerSecurityConfig struct {
// CIDRAllowlist holds CIDR ranges allowed to access /_sys/job* endpoints.
// Empty list = localhost-only access (127.0.0.1, ::1).
// Non-empty list = restrict to matching IP ranges only.
CIDRAllowlist []string `koanf:"cidrallowlist" json:"cidrallowlist" yaml:"cidrallowlist" toml:"cidrallowlist" mapstructure:"cidrallowlist"`
// TrustedProxies holds CIDR ranges of trusted reverse proxies.
// X-Forwarded-For is ONLY honored if the immediate peer matches one of these CIDR
// ranges. Empty list = do not trust any proxy headers. X-Real-IP is never honored
// (ADR-057, completed by ADR-080). A default route is rejected at startup.
TrustedProxies []string `koanf:"trustedproxies" json:"trustedproxies" yaml:"trustedproxies" toml:"trustedproxies" mapstructure:"trustedproxies"`
}
SchedulerSecurityConfig holds security settings for scheduler system APIs.
type SchedulerTimeoutConfig ¶ added in v0.14.0
type SchedulerTimeoutConfig struct {
// Shutdown is the graceful shutdown timeout for in-flight jobs.
// Zero applies the default; negative is rejected. Default: 30s.
Shutdown time.Duration `koanf:"shutdown" json:"shutdown" yaml:"shutdown" toml:"shutdown" mapstructure:"shutdown"`
// SlowJob is the execution duration threshold for marking jobs as slow.
// Jobs exceeding this duration are logged with result_code="WARN" even if successful.
// Zero applies the default; negative is rejected. Default: 25s.
SlowJob time.Duration `koanf:"slowjob" json:"slowjob" yaml:"slowjob" toml:"slowjob" mapstructure:"slowjob"`
}
SchedulerTimeoutConfig holds timeout and threshold settings for scheduler operations.
type SealConfig ¶ added in v0.63.0
type SealConfig struct {
// Active is the Activation selector: Logical kid -> generation ("v2") that
// seals new traffic. Its domain is every Logical kid the producer resolves,
// sign and encrypt alike. Absent for a family with exactly one provisioned
// generation, that one is active; with several, startup refuses to guess.
// The value grammar is ^v[1-9][0-9]*$ (checked here); resolution against
// the keystore is keystore.ActiveGeneration. Environment form:
// MESSAGING_SEAL_ACTIVE_<LOGICAL>=v2 — a hyphenated Logical kid is settable
// only where the runtime permits '-' in a variable name (ADR-090).
Active map[string]string `koanf:"active" json:"active" yaml:"active" toml:"active" mapstructure:"active"`
}
SealConfig holds the producer's payload-sealing choices. Key material itself lives in keystore.keys; this block only selects among provisioned generations.
type ServerConfig ¶
type ServerConfig struct {
Host string `koanf:"host" json:"host" yaml:"host" toml:"host" mapstructure:"host"`
Port int `koanf:"port" json:"port" yaml:"port" toml:"port" mapstructure:"port"`
Timeout TimeoutConfig `koanf:"timeout" json:"timeout" yaml:"timeout" toml:"timeout" mapstructure:"timeout"`
Path PathConfig `koanf:"path" json:"path" yaml:"path" toml:"path" mapstructure:"path"`
Gzip GzipConfig `koanf:"gzip" json:"gzip" yaml:"gzip" toml:"gzip" mapstructure:"gzip"`
TLS ServerTLSConfig `koanf:"tls" json:"tls" yaml:"tls" toml:"tls" mapstructure:"tls"`
ForwardedClientCert ForwardedClientCertConfig `` /* 143-byte string literal not displayed */
// TrustedProxies holds CIDR ranges of reverse proxies whose
// X-Forwarded-For entries are believed when deriving the client IP for
// rate limiting and request logging. Loopback, link-local and RFC1918
// ranges are trusted by default, so a service behind an in-VPC load
// balancer needs no entry here; add one only when a proxy sits on a
// public address. An invalid entry fails startup rather than silently
// changing who is trusted.
TrustedProxies []string `koanf:"trustedproxies" json:"trustedproxies" yaml:"trustedproxies" toml:"trustedproxies" mapstructure:"trustedproxies"`
// BodyLimit is the maximum request body size in bytes. A value of 0 is filled
// with the framework default (10 MB) by config normalization; a negative value
// is rejected by config validation.
BodyLimit int64 `koanf:"bodylimit" json:"bodylimit" yaml:"bodylimit" toml:"bodylimit" mapstructure:"bodylimit"`
ResponseTime ResponseTimeConfig `koanf:"responsetime" json:"responsetime" yaml:"responsetime" toml:"responsetime" mapstructure:"responsetime"`
// LogRoutes toggles the per-route "Route registered" startup log lines
// (one Info line per registered HTTP route). Pointer tri-state: an explicit
// server.logroutes value always wins; an absent key (nil) defaults to
// app-env development via Config.ShouldLogRoutes (on in dev/local, off in
// prod/staging), so a large service pays zero extra boot lines in production
// unless an operator opts in. Env override: SERVER_LOGROUTES.
LogRoutes *bool `koanf:"logroutes" json:"logroutes" yaml:"logroutes" toml:"logroutes" mapstructure:"logroutes"`
}
ServerConfig holds HTTP server settings.
type ServerTLSConfig ¶ added in v0.55.0
type ServerTLSConfig struct {
Enabled bool `koanf:"enabled" json:"enabled" yaml:"enabled" toml:"enabled" mapstructure:"enabled"`
CertFile string `koanf:"certfile" json:"certfile" yaml:"certfile" toml:"certfile" mapstructure:"certfile"`
CertValue string `koanf:"certvalue" json:"certvalue" yaml:"certvalue" toml:"certvalue" mapstructure:"certvalue"`
KeyFile string `koanf:"keyfile" json:"keyfile" yaml:"keyfile" toml:"keyfile" mapstructure:"keyfile"`
KeyValue string `koanf:"keyvalue" json:"keyvalue" yaml:"keyvalue" toml:"keyvalue" mapstructure:"keyvalue"`
// MinVersion: "" or "1.2" (default floor) | "1.3".
MinVersion string `koanf:"minversion" json:"minversion" yaml:"minversion" toml:"minversion" mapstructure:"minversion"`
}
ServerTLSConfig enables HTTPS on the HTTP server listener. Each PEM piece comes from a file path (*File) or a base64-encoded PEM string (*Value) — exactly one source per piece. Zero value = TLS disabled (plaintext listener, today's behavior). Client-certificate verification is not part of this struct yet (deferred; see ADR-042).
type ServiceConfig ¶ added in v0.7.0
type ServiceConfig struct {
Name string `koanf:"name" json:"name" yaml:"name" toml:"name" mapstructure:"name"`
SID string `koanf:"sid" json:"sid" yaml:"sid" toml:"sid" mapstructure:"sid"`
}
ServiceConfig holds Oracle service connection settings.
type SlowQueryConfig ¶ added in v0.7.1
type SlowQueryConfig struct {
Threshold time.Duration `koanf:"threshold" json:"threshold" yaml:"threshold" toml:"threshold" mapstructure:"threshold"`
Enabled bool `koanf:"enabled" json:"enabled" yaml:"enabled" toml:"enabled" mapstructure:"enabled"`
}
SlowQueryConfig holds settings for slow query detection.
type SourceConfig ¶ added in v0.11.0
type SourceConfig struct {
Type string `koanf:"type" json:"type" yaml:"type" toml:"type" mapstructure:"type"` // SourceTypeStatic for YAML config, SourceTypeDynamic for external stores
}
SourceConfig controls how tenant configuration is loaded.
type StartupConfig ¶ added in v0.11.2
type StartupConfig struct {
// Timeout is the overall startup timeout (fallback when component-specific not set).
// Default: 10s.
Timeout time.Duration `koanf:"timeout" json:"timeout" yaml:"timeout" toml:"timeout" mapstructure:"timeout"`
// Database is the timeout for database health check during startup.
// Default: 10s. Set higher for slow network connections.
Database time.Duration `koanf:"database" json:"database" yaml:"database" toml:"database" mapstructure:"database"`
// Messaging is the timeout for broker connection during startup.
// Default: 10s. Set higher for cluster failover scenarios.
Messaging time.Duration `koanf:"messaging" json:"messaging" yaml:"messaging" toml:"messaging" mapstructure:"messaging"`
// Cache is the timeout for cache initialization during startup.
// Default: 5s. Cache is fast to connect; lower timeout prevents blocking.
Cache time.Duration `koanf:"cache" json:"cache" yaml:"cache" toml:"cache" mapstructure:"cache"`
// Observability is the timeout for OTLP provider initialization.
// Default: 15s. Remote OTLP endpoints may need extra time for TLS handshake.
Observability time.Duration `koanf:"observability" json:"observability" yaml:"observability" toml:"observability" mapstructure:"observability"`
}
StartupConfig holds application startup settings. Production-safe defaults are applied automatically:
- Timeout: 10s (overall startup timeout, fallback for unset components)
- Database: 10s (database health check timeout)
- Messaging: 10s (broker connection timeout)
- Cache: 5s (cache initialization timeout)
- Observability: 15s (OTLP provider initialization timeout)
type StreamsAddressResolverConfig ¶ added in v0.59.0
type StreamsAddressResolverConfig struct {
// Host is the entry-point hostname clients dial instead of the address the
// broker advertises in its metadata response.
Host string `koanf:"host" json:"host" yaml:"host" toml:"host" mapstructure:"host"`
// Port is the entry-point port. Must be 1-65535 when Host is set.
Port int `koanf:"port" json:"port" yaml:"port" toml:"port" mapstructure:"port"`
}
StreamsAddressResolverConfig pins stream connections to one advertised endpoint.
type StreamsConfig ¶ added in v0.59.0
type StreamsConfig struct {
// URI is the stream-protocol endpoint, scheme rabbitmq-stream:// (or
// rabbitmq-stream+tls://), default port 5552. Required when any module
// declares stream consumers. Deliberately NOT derived from
// messaging.broker.url — the stream protocol is a separate listener that a
// deployment may not expose at all (explicit > implicit).
URI string `koanf:"uri" json:"uri" yaml:"uri" toml:"uri" mapstructure:"uri"`
// AddressResolver pins the client to a single entry point (load balancer,
// NAT, or Docker port mapping), which the broker's own metadata cannot
// describe. Set both fields or neither.
AddressResolver StreamsAddressResolverConfig `koanf:"addressresolver" json:"addressresolver" yaml:"addressresolver" toml:"addressresolver" mapstructure:"addressresolver"`
// OffsetStore tunes how often successfully handled offsets are committed
// server-side.
OffsetStore StreamsOffsetStoreConfig `koanf:"offsetstore" json:"offsetstore" yaml:"offsetstore" toml:"offsetstore" mapstructure:"offsetstore"`
}
StreamsConfig holds native RabbitMQ stream-protocol settings (consumption). Requires single-tenant mode or messaging.tenancy: shared, which consumes once on the control-plane key: multitenant.enabled together with a stream URI under per-tenant tenancy is a startup validation error (see config/messaging_section.go: checkMessagingStreams).
type StreamsOffsetStoreConfig ¶ added in v0.59.0
type StreamsOffsetStoreConfig struct {
// CountBeforeStorage is how many successfully handled messages accumulate
// before the offset is committed. Default: 500. Must be >= 0 (0 applies the default).
CountBeforeStorage int `` /* 138-byte string literal not displayed */
// FlushInterval is how long after the last commit a pending offset is
// committed even if CountBeforeStorage was not reached. Default: 5s.
// Must be >= 0 (0 applies the default).
FlushInterval time.Duration `koanf:"flushinterval" json:"flushinterval" yaml:"flushinterval" toml:"flushinterval" mapstructure:"flushinterval"`
}
StreamsOffsetStoreConfig tunes the server-side offset commit cadence. Offsets are only ever committed AFTER a handler returned successfully, so these keys trade commit traffic against how much already-handled work a crash replays.
type TLSConfig ¶ added in v0.7.1
type TLSConfig struct {
Mode string `koanf:"mode" json:"mode" yaml:"mode" toml:"mode" mapstructure:"mode"`
CertFile string `koanf:"cert" json:"cert" yaml:"cert" toml:"cert" mapstructure:"cert"`
KeyFile string `koanf:"key" json:"key" yaml:"key" toml:"key" mapstructure:"key"`
CAFile string `koanf:"ca" json:"ca" yaml:"ca" toml:"ca" mapstructure:"ca"`
}
TLSConfig holds TLS/SSL settings for database connections.
type TenantEntry ¶ added in v0.9.0
type TenantEntry struct {
Database DatabaseConfig `koanf:"database" json:"database" yaml:"database" toml:"database" mapstructure:"database"`
Messaging TenantMessagingConfig `koanf:"messaging" json:"messaging" yaml:"messaging" toml:"messaging" mapstructure:"messaging"`
Cache CacheConfig `koanf:"cache" json:"cache" yaml:"cache" toml:"cache" mapstructure:"cache"`
}
TenantEntry represents a single tenant's resource configuration
type TenantMessagingConfig ¶ added in v0.9.0
type TenantMessagingConfig struct {
URL string `koanf:"url" json:"url" yaml:"url" toml:"url" mapstructure:"url"`
}
TenantMessagingConfig holds messaging configuration for a tenant
type TenantStore ¶ added in v0.9.0
type TenantStore struct {
// contains filtered or unexported fields
}
TenantStore provides per-key database, messaging, and cache configurations. This is the default config-backed implementation that uses the static tenant map.
func NewTenantStore ¶ added in v0.9.0
func NewTenantStore(cfg *Config) *TenantStore
NewTenantStore creates a config-backed tenant store
func (*TenantStore) AddTenant ¶ added in v0.9.0
func (s *TenantStore) AddTenant(tenantID string, entry *TenantEntry)
AddTenant adds a new tenant configuration at runtime (useful for dynamic tenant management)
func (*TenantStore) BrokerURL ¶ added in v0.11.1
BrokerURL returns the AMQP broker URL for the given key. For single-tenant (key=""), returns the default broker URL. For multi-tenant (key=tenantID), returns the tenant-specific URL. Returns an error if messaging is not configured or misconfigured.
func (*TenantStore) CacheConfig ¶ added in v0.18.0
func (s *TenantStore) CacheConfig(_ context.Context, key string) (*CacheConfig, error)
CacheConfig returns the cache configuration for the given key. For single-tenant (key=""), returns the default cache config. For multi-tenant (key=tenantID), returns the tenant-specific cache config.
func (*TenantStore) DBConfig ¶ added in v0.9.0
func (s *TenantStore) DBConfig(_ context.Context, key string) (*DatabaseConfig, error)
DBConfig returns the database configuration for the given key. Key semantics:
- "" (empty): Returns the default database config (single-tenant mode)
- "named:<name>": Returns named database config from databases.<name> section
- "<tenantID>": Returns tenant-specific database config (multi-tenant mode)
func (*TenantStore) HasNamedDatabase ¶ added in v0.22.0
func (s *TenantStore) HasNamedDatabase(name string) bool
HasNamedDatabase checks if a named database configuration exists.
func (*TenantStore) HasTenant ¶ added in v0.9.0
func (s *TenantStore) HasTenant(tenantID string) bool
HasTenant checks if a tenant configuration exists
func (*TenantStore) IsDynamic ¶ added in v0.11.0
func (s *TenantStore) IsDynamic() bool
IsDynamic returns false since this store uses static YAML configuration
func (*TenantStore) NamedDatabases ¶ added in v0.22.0
func (s *TenantStore) NamedDatabases() map[string]DatabaseConfig
NamedDatabases returns a copy of all named database configurations. This is useful for introspection and validation.
func (*TenantStore) RemoveTenant ¶ added in v0.9.0
func (s *TenantStore) RemoveTenant(tenantID string)
RemoveTenant removes a tenant configuration at runtime
func (*TenantStore) Tenants ¶ added in v0.19.0
func (s *TenantStore) Tenants() map[string]TenantEntry
Tenants returns a copy of all tenant configurations
type TimeoutConfig ¶ added in v0.7.1
type TimeoutConfig struct {
Read time.Duration `koanf:"read" json:"read" yaml:"read" toml:"read" mapstructure:"read"`
Write time.Duration `koanf:"write" json:"write" yaml:"write" toml:"write" mapstructure:"write"`
Idle time.Duration `koanf:"idle" json:"idle" yaml:"idle" toml:"idle" mapstructure:"idle"`
Middleware time.Duration `koanf:"middleware" json:"middleware" yaml:"middleware" toml:"middleware" mapstructure:"middleware"`
Shutdown time.Duration `koanf:"shutdown" json:"shutdown" yaml:"shutdown" toml:"shutdown" mapstructure:"shutdown"`
}
TimeoutConfig holds various timeout durations for the server.
Source Files
¶
- app_section.go
- cache_section.go
- cidr.go
- config.go
- converters.go
- database_section.go
- debug_section.go
- defaults.go
- delivered_empty.go
- env.go
- errors.go
- getters.go
- injection.go
- keystore_section.go
- log_section.go
- messaging_section.go
- multitenant_section.go
- phases.go
- resolver_section.go
- scheduler_section.go
- section.go
- section_name.go
- server_section.go
- source.go
- tenant_store.go
- types.go