config

package
v0.0.0-...-ca72162 Latest Latest
Warning

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

Go to latest
Published: Mar 1, 2026 License: GPL-3.0 Imports: 18 Imported by: 0

README

Configuration Domain Layer

internal/config defines the in-memory (domain) representation of the Firelynx server configuration.

Responsibilities

  • Load & convert – transform the protobuf pb.ServerConfig produced by the loader into Go structs (config.Config) and back.
  • Validate – enforce cross-object rules that TOML or protobuf schemas cannot express (e.g. every Endpoint.ListenerIDs must reference an existing listener).
  • Query – helper methods to quickly locate listeners, endpoints, routes, and apps.

Out of Scope

The package does not:

  • Start listeners, run apps, or keep runtime state.
  • Pre-load configuration during component construction. Runnables fetch config via callbacks during Run or on Reload.

Relationship to Protobuf

TOML → loader → pb.ServerConfig ↔ internal/config ↔ server/core ↔ runtime components

Protobuf is the persistence/wire schema. Domain structs mirror the proto messages but add:

  • idiomatic Go naming and zero-values,
  • collection helpers (e.g. FindByID),
  • validation and string/tree utilities.

Conversions are performed by NewFromProto and ToProto.

Config Transactions

Validated configs are wrapped in a transaction.ConfigTransaction (internal/config/transaction). The transaction layer:

  1. assigns a UUID and source to the change,
  2. tracks progress with a state machine,
  3. coordinates participants so all components apply or all roll back.

The saga logic lives entirely in the transaction package; the domain layer is only the payload.

Quick Start

cfg, _ := config.NewConfig("config.toml")
_ = cfg.Validate()

fmt.Println(cfg.Version)

// Use direct collection methods
listener, found := cfg.Listeners.FindByID("public-http")
if found {
    fmt.Printf("Listener: %s at %s\n", listener.ID, listener.Address)
}

// Iterate over apps using Go 1.23 iterator pattern
for app := range cfg.Apps.All() {
    fmt.Printf("App: %s\n", app.GetID())
}

The rest of the server interacts with configuration exclusively through this API, allowing the TOML and protobuf schemas to evolve without touching runtime code.

Collection Architecture

Configuration uses structured collections with consistent APIs:

  • AppCollection: Struct with encapsulated app instances and iterator methods
  • ListenerCollection, EndpointCollection: Slice types with finder methods
  • Go 1.23 Iterators: All collections provide All() and specialized finders returning iter.Seq[T]
  • Direct Collection Access: Use config.Listeners.GetHTTPListeners() instead of deprecated config-level wrappers

Default Value Pattern

Configuration types should provide reasonable defaults when users omit optional fields:

  1. Define constants with Default prefix for all configurable values
  2. Constructor applies all defaults (e.g., NewHTTP())
  3. FromProto conversion always starts with defaults, only overrides when protobuf fields are provided
  4. Parent conversion always calls FromProto, even when protobuf fields are nil

This ensures users get reasonable defaults even when configuration sections are completely omitted. See internal/config/listeners/options/http.go for the reference implementation.

Note: Protobuf Duration fields cannot have default values in the schema, so defaults must be implemented in the Go conversion layer.

Validation Architecture

Configuration validation follows a strict two-phase architecture:

Phase 1: Domain Creation
  • NewFromProto() - Converts protobuf to domain objects
  • Applies defaults - Sets reasonable defaults for omitted fields
  • NO validation - Only data transformation, never validates business rules
Phase 2: Validation
  • Validate() - Validates business rules and cross-object constraints
  • Environment variable interpolation - Expands ${VAR_NAME} syntax during validation
  • Error accumulation - Collects all validation errors using errors.Join()
Timing
  • Interpolation happens during validation - Not during conversion from protobuf
  • Validate interpolated values - Business rules apply to expanded values, not templates
  • Explicit validation required - Callers must call .Validate() explicitly

Validation Flow

The configuration validation happens in the following order:

  1. Basic structure validation - Validate IDs, required fields, and data types
  2. App expansion for routes (expandAppsForRoutes) - Create route-specific app instances with merged static data
  3. Individual component validation - Validate apps, listeners, endpoints individually
  4. Cross-component validation - Validate references between components (routes to apps, endpoints to listeners)

App Expansion

Apps are expanded during the validation phase to create route-specific instances. Each route that references an app gets its own instance with merged static data from both the app definition and route-specific configuration.

Key Points:

  • Expansion happens in validation phase, not during protobuf conversion
  • Each route gets a dedicated app instance with pre-merged static data
  • Static data merging is completed before server instantiation
  • Server components receive fully-prepared app instances

Environment Variable Interpolation

Config fields support environment variable interpolation using ${VAR_NAME} and ${VAR_NAME:default} syntax.

Implementation
  • Tag-based control: Use env_interpolation:"yes"/"no" struct tags
  • Validation-time only: Interpolation happens during Validate(), not conversion
  • Fields without tags: Default to NOT being interpolated
Supported Fields
  • Paths and URIs: File paths, URLs, addresses
  • User content: Messages, responses, configuration values
  • Network: Host names, ports, endpoints
Not Interpolated
  • Identifiers: App IDs, listener IDs, middleware IDs
  • Code content: Script source, function names, entrypoints
  • Structured data: JSON, YAML, or other parseable content

Documentation

Overview

Package config provides configuration management for the firelynx server.

Package config provides domain model for server configuration

Index

Constants

View Source
const (
	// VersionLatest is the latest supported configuration version
	VersionLatest = version.Version

	// VersionUnknown is used when a version is not specified
	VersionUnknown = "unknown"
)

Configuration version constants

Variables

View Source
var (
	// Top-level error categories
	ErrFailedToLoadConfig     = errz.ErrFailedToLoadConfig
	ErrFailedToConvertConfig  = errz.ErrFailedToConvertConfig
	ErrFailedToValidateConfig = errz.ErrFailedToValidateConfig
	ErrUnsupportedConfigVer   = errz.ErrUnsupportedConfigVer

	// Validation specific errors
	ErrDuplicateID          = errz.ErrDuplicateID
	ErrEmptyID              = errz.ErrEmptyID
	ErrInvalidReference     = errz.ErrInvalidReference
	ErrMissingRequiredField = errz.ErrMissingRequiredField
	ErrRouteConflict        = errz.ErrRouteConflict

	// Type specific errors
	ErrInvalidListenerType = errz.ErrInvalidListenerType
	ErrInvalidRouteType    = errz.ErrInvalidRouteType
	ErrRouteTypeMismatch   = errz.ErrRouteTypeMismatch
	ErrInvalidAppType      = errz.ErrInvalidAppType
	ErrInvalidEvaluator    = errz.ErrInvalidEvaluator

	// Reference specific errors
	ErrListenerNotFound = errz.ErrListenerNotFound
	ErrAppNotFound      = errz.ErrAppNotFound
	ErrEndpointNotFound = errz.ErrEndpointNotFound
	ErrRouteNotFound    = errz.ErrRouteNotFound
)

Re-export errors for backward compatibility and convenience

Functions

func ConfigTree

func ConfigTree(cfg *Config) string

ConfigTree converts a Config struct into a rendered tree string

Types

type Config

type Config struct {
	Version   string
	Listeners listeners.ListenerCollection
	Endpoints endpoints.EndpointCollection
	Apps      *apps.AppCollection

	// ValidationCompleted is set after the config has been validated. If the config is invalid, this will still be true.
	ValidationCompleted bool
	// contains filtered or unexported fields
}

Config represents the complete server configuration

func NewConfig

func NewConfig(filePath string) (*Config, error)

NewConfig loads configuration from a TOML file path, converts it to the domain model. It does NOT validate the config.

func NewConfigFromBytes

func NewConfigFromBytes(data []byte) (*Config, error)

NewConfigFromBytes loads configuration from TOML bytes, converts it to the domain model. It does NOT validate the config.

func NewConfigFromReader

func NewConfigFromReader(reader io.Reader) (*Config, error)

NewConfigFromReader loads configuration from an io.Reader providing TOML data, converts it to the domain model. It does NOT validate the config.

func NewFromProto

func NewFromProto(pbConfig *pb.ServerConfig) (*Config, error)

NewFromProto creates a domain Config from a protobuf ServerConfig. This is the recommended function for converting from protobuf to domain model as it handles defaults and error collection. It does NOT validate the config.

func (*Config) Equals

func (c *Config) Equals(other *Config) bool

Equals compares two Config objects for equality.

func (*Config) String

func (c *Config) String() string

String returns a pretty-printed tree representation of the config

func (*Config) ToProto

func (c *Config) ToProto() *pb.ServerConfig

ToProto converts the domain Config to a protobuf ServerConfig

func (*Config) Validate

func (c *Config) Validate() error

Validate recursively validates all configuration components and their cross-references

type Validatable

type Validatable interface {
	// Validate performs validation on the object and returns an error if validation fails.
	// The error should contain specific information about what validation checks failed.
	// If multiple validations fail, all errors should be combined using errors.Join().
	Validate() error
}

Validatable defines an interface for objects that can validate themselves. Any struct that implements this interface can be validated as part of a validation chain.

Directories

Path Synopsis
Package apps provides types and functionality for application configuration in the firelynx server.
Package apps provides types and functionality for application configuration in the firelynx server.
composite
Package composite provides types and utilities for composite script applications in firelynx.
Package composite provides types and utilities for composite script applications in firelynx.
echo
Package echo provides app-specific configurations for the firelynx server.
Package echo provides app-specific configurations for the firelynx server.
mcp
Package mcp provides types and utilities for MCP-based applications in firelynx.
Package mcp provides types and utilities for MCP-based applications in firelynx.
scripts
Package scripts provides types and utilities for script-based applications in firelynx.
Package scripts provides types and utilities for script-based applications in firelynx.
scripts/evaluators
Package evaluators provides types and utilities for various script evaluators used in firelynx.
Package evaluators provides types and utilities for various script evaluators used in firelynx.
Package endpoints provides configuration types and utilities for routing in the firelynx server.
Package endpoints provides configuration types and utilities for routing in the firelynx server.
middleware
Package middleware provides types and functionality for middleware configuration in the firelynx server.
Package middleware provides types and functionality for middleware configuration in the firelynx server.
routes
Package routes provides configuration types and utilities for request routing in the firelynx server.
Package routes provides configuration types and utilities for request routing in the firelynx server.
Package errz provides shared error definitions for the config package and its subpackages.
Package errz provides shared error definitions for the config package and its subpackages.
Package listeners provides configuration types and utilities for network listeners in the firelynx server.
Package listeners provides configuration types and utilities for network listeners in the firelynx server.
toml
Package toml provides TOML configuration loading with protobuf post-processing.
Package toml provides TOML configuration loading with protobuf post-processing.
Package staticdata provides types and utilities for handling static data that can be passed to apps and routes in firelynx.
Package staticdata provides types and utilities for handling static data that can be passed to apps and routes in firelynx.
TODO: change the param order, standardize on a metadata struct
TODO: change the param order, standardize on a metadata struct
finitestate
Configuration saga state machine implementation.
Configuration saga state machine implementation.
Package validation provides validation utilities for domain config types.
Package validation provides validation utilities for domain config types.

Jump to

Keyboard shortcuts

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