devconfig

package
v0.1.0-dev.20260814023953 Latest Latest
Warning

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

Go to latest
Published: Aug 14, 2026 License: Apache-2.0 Imports: 9 Imported by: 0

Documentation

Overview

Package devconfig is the domain-free foundation for devlore's unified configuration model.

Configuration is a distributed-participation problem: independent participants — providers, subsystems, and star extensions — each own a slice of the configuration surface, announce their schema, and a registry assembles the announcements into one resolved Config per application process. This package holds the foundation types only; owner packages elsewhere in the repo define their own concrete sections, and the loader builds a Config by rolling values up through a fixed precedence. See docs/architecture/configuration.md for the full design.

The section family has two shapes. A Go-typed section is a plain struct embedding SectionBase: its fields are the settings, read directly by Go consumers. A DataSection holds settings as a typed key/value bag and is the shape runtime-discovered star extensions take; it crosses into Starlark as a sealed mapping. Both satisfy the Section interface, so a Config holds them uniformly.

Index

Constants

This section is empty.

Variables

This section is empty.

Functions

func AnnounceSection

func AnnounceSection(sectionType reflect.Type, construct SectionConstructor)

AnnounceSection registers a Go-typed section's constructor — the Go announcement path, called from a package init().

The section is keyed by the name its constructor reports. A duplicate name is a programmer error — two compiled-in packages claiming one name — so it is **fatal** at announce time, both claimants named: the Go Must idiom, the same shape as the workflow framework's provider announcement. The constructor is invoked once here to read the name, and is retained for the loader to call again at the config build.

Parameters:

  • `sectionType`: the section's concrete `reflect.Type`, recorded for collision diagnostics.
  • `construct`: the factory that builds the section pre-floored; must be non-nil.

func AnnounceSectionSpec

func AnnounceSectionSpec(spec SectionSpec) error

AnnounceSectionSpec registers a data-path section schema — the data announcement path, called at extension-discovery time.

The spec is user-supplied data (a star extension), so a duplicate name — two extensions, or one shadowing a framework name — is a user error, **returned, never fatal**; the first writer keeps the name.

Parameters:

  • `spec`: the data-path schema; its `Name` is the registry key and must not be empty.

Returns:

  • `error`: non-nil when the name is empty or already announced.

func AnnouncedSectionNames

func AnnouncedSectionNames() []string

AnnouncedSectionNames returns the names of all announced sections in sorted order, for diagnostics and tests.

Returns:

  • `[]string`: the announced section names, sorted.

func Get

func Get[T any](section *DataSection, name string) (T, bool)

Get returns a setting from a DataSection as type T — an assertion over the stored value, never a parse.

It is a free function, not a method, because methods cannot be generic and because the section's Starlark face already claims the name Get for starlark.Mapping.

Parameters:

  • `section`: the section to read.
  • `name`: the setting name.

Returns:

  • `T`: the setting's value, or the zero value of T when absent or of another type.
  • `bool`: true when the setting is present and of type T.

func SectionOf

func SectionOf[T Section](c *Config) (T, bool)

SectionOf returns the section of concrete type T from a Config.

It finds the one section whose concrete type matches T — Go-typed owners wrap it so consumers never assert by hand (e.g. signing.SectionFrom). No registry lookup is needed: there is one section per type, found by assertion.

Parameters:

  • `c`: the configuration to search.

Returns:

  • `T`: the matching section, or the zero value of T when none matches.
  • `bool`: true when a section of type T is present.

Types

type Config

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

Config is one application's resolved configuration: the family of sections, keyed by name, the build produced.

It is constructed once per application process by the loader, snapshotting the schema registry, and is sealed thereafter — the sections it hands back are the registered instances, and mutating them after the build is a bug. Alongside the sections it carries a provenance sidecar recording which source won each setting, read through Config.Provenance for diagnostics.

func NewConfig

func NewConfig(sections map[string]Section, provenance map[string]map[string]SettingSourceKind) *Config

NewConfig assembles a Config from resolved sections and their provenance sidecar.

The loader calls this once, after the roll-up, with the fully resolved maps; the result is sealed. Both maps are retained by reference, not copied — the caller must not mutate them after construction.

Parameters:

  • `sections`: the resolved sections, keyed by section name.
  • `provenance`: per-section maps of setting name to the source that won it.

Returns:

  • `*Config`: the assembled, sealed configuration.

func (*Config) Provenance

func (c *Config) Provenance(section, setting string) (SettingSourceKind, bool)

Provenance reports which source won a setting's resolved value.

Provenance is recorded per setting, not per section: within one section, different settings may come from different layers. Every declared setting has a source — SourceBuiltin at the floor — so a false result means the section or setting is unknown, never that a real setting lacks provenance.

Parameters:

  • `section`: the section name.
  • `setting`: the setting name within that section.

Returns:

  • `SettingSourceKind`: the source that won the setting's value.
  • `bool`: true when the section and setting are both known.

func (*Config) Provenances

func (c *Config) Provenances(section string) map[string]SettingSourceKind

Provenances reports the source of every setting in a section, for whole-section diagnostics (config explain).

The returned map is a copy; mutating it does not affect the sealed Config.

Parameters:

  • `section`: the section name.

Returns:

  • `map[string]SettingSourceKind`: setting name to winning source; nil when the section is unknown.

func (*Config) Section

func (c *Config) Section(name string) (Section, bool)

Section returns the resolved section registered under name.

Parameters:

  • `name`: the section name (e.g. "signing", "lint.copyright").

Returns:

  • `Section`: the resolved section.
  • `bool`: true when a section is registered under name.

type DataSection

type DataSection struct {
	SectionBase
	// contains filtered or unexported fields
}

DataSection is a section whose settings are a typed key/value bag rather than struct fields.

It is the shape runtime-discovered star extensions take — built from a SectionSpec — and the form any section crosses into Starlark as. It satisfies starlark.Value, starlark.Mapping, and starlark.IterableMapping so a script reads it by indexing (section["enabled"]) and iterates it like a mapping; starlark.HasAttrs is deliberately not implemented, so there is one access idiom and a missing key is a loud error, not a silent default. It is sealed after the build: the values are read, never written, through this type.

func NewDataSection

func NewDataSection(name string, values map[string]any) *DataSection

NewDataSection builds a DataSection with the given name and settings.

The values are retained by reference; callers must not mutate the map after construction, since the section is sealed. Each value is expected to already hold its declared type — instantiation happens during the build, not here.

Parameters:

  • `name`: the section name.
  • `values`: the settings, keyed by setting name, each already of its declared type.

Returns:

  • `*DataSection`: the constructed section.

func (*DataSection) Freeze

func (d *DataSection) Freeze()

Freeze is a no-op: a DataSection is already sealed by the build.

func (*DataSection) Get

func (d *DataSection) Get(key starlark.Value) (starlark.Value, bool, error)

Get returns a setting's value as a Starlark value, implementing starlark.Mapping for index access.

A missing key returns found=false with no error, so Starlark's indexing raises a loud "key not in" error (a schema typo, since the floor guarantees every declared setting is present) while membership tests still report false.

Parameters:

  • `key`: the setting name as a Starlark string.

Returns:

  • `starlark.Value`: the setting's value projected to Starlark.
  • `bool`: true when the setting is present.
  • `error`: non-nil only when the key is not a string or the value cannot be projected.

func (*DataSection) Hash

func (d *DataSection) Hash() (uint32, error)

Hash reports the section as unhashable, matching Starlark's dict.

Returns:

  • `uint32`: always 0.
  • `error`: always non-nil — a section is not hashable.

func (*DataSection) Items

func (d *DataSection) Items() []starlark.Tuple

Items returns the section's settings as (name, value) pairs in sorted order, implementing starlark.IterableMapping.

Returns:

  • `[]starlark.Tuple`: one (name, value) tuple per setting, sorted by name.

func (*DataSection) Iterate

func (d *DataSection) Iterate() starlark.Iterator

Iterate returns an iterator over the section's setting names, implementing starlark.IterableMapping.

Returns:

  • `starlark.Iterator`: an iterator yielding setting names in sorted order.

func (*DataSection) Lookup

func (d *DataSection) Lookup(name string) (any, bool)

Lookup returns a setting's value as its stored Go type, for dynamic Go-side reads.

The value is returned as stored — already of its declared type — with no conversion. For a statically known type, prefer the generic Get.

Parameters:

  • `name`: the setting name.

Returns:

  • `any`: the setting's value.
  • `bool`: true when the setting is present.

func (*DataSection) Names

func (d *DataSection) Names() []string

Names returns the section's setting names in sorted order.

Returns:

  • `[]string`: the setting names, sorted.

func (*DataSection) String

func (d *DataSection) String() string

String returns a Starlark representation of the section.

Returns:

  • `string`: the section's settings rendered as a mapping.

func (*DataSection) Truth

func (d *DataSection) Truth() starlark.Bool

Truth reports the section as truthy when it holds at least one setting.

Returns:

  • `starlark.Bool`: true when the section is non-empty.

func (*DataSection) Type

func (d *DataSection) Type() string

Type returns the Starlark type name.

Returns:

  • `string`: always "config.section".

type Section

type Section interface {
	Name() string
}

Section is the contract every configuration section satisfies: it has a name, its key within a Config.

Concrete sections embed SectionBase for the name and add their settings — as struct fields (a Go-typed owner like SigningSection) or as a key/value bag (a DataSection). The interface lets a Config hold both shapes uniformly.

type SectionBase

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

SectionBase is the embeddable identity every concrete section carries — the codebase's *Base convention (cf. ResourceBase, OriginBase). It holds the section name, set once at construction and immutable thereafter.

func NewSectionBase

func NewSectionBase(name string) SectionBase

NewSectionBase returns the identity base for a section registered under name.

Parameters:

  • `name`: the section name (its key in a Config).

Returns:

  • `SectionBase`: the identity base to embed in a concrete section.

func (SectionBase) Name

func (b SectionBase) Name() string

Name reports the section's key within a Config (e.g. "signing", "lint.copyright").

Returns:

  • `string`: the section name.

type SectionConstructor

type SectionConstructor func() Section

SectionConstructor builds a Go-typed section pre-floored — its builtin defaults applied — for the Go announcement path. The registry calls it at the config build to obtain the section the loader then overlays.

func ConstructorFor

func ConstructorFor(name string) (SectionConstructor, bool)

ConstructorFor returns the Go-path constructor announced under name. The loader calls it at the config build.

Parameters:

  • `name`: the section name.

Returns:

  • `SectionConstructor`: the announced constructor, or nil when name has no Go-path constructor.
  • `bool`: true when name has a Go-path constructor.

type SectionSpec

type SectionSpec struct {
	Name     string
	Defaults map[string]*yaml.Node
}

SectionSpec is the data-path schema: a section declared as data (a star extension's config block) rather than a Go struct. AnnounceSectionSpec turns it into a factory that builds a pre-floored DataSection.

Under the tagged-defaults model the schema is the floor: each default value's YAML tag declares its setting's type (Go's := applied to configuration). Defaults holds the parsed default nodes, keyed by setting name; a node's resolved Tag names the type and the node itself is the floor value.

func SpecFor

func SpecFor(name string) (SectionSpec, bool)

SpecFor returns the data-path spec announced under name. The loader calls it at the config build.

Parameters:

  • `name`: the section name.

Returns:

  • `SectionSpec`: the announced spec, or the zero value when name has no data-path spec.
  • `bool`: true when name has a data-path spec.

type SettingSourceKind

type SettingSourceKind uint8

SettingSourceKind identifies which overlay layer won a setting's resolved value.

The values are ordered low to high by precedence; every resolved setting has at least SourceBuiltin, the floor the section constructor or tagged defaults provide. It applies per setting, not per section: a section's settings may each be won by a different layer.

const (
	SourceBuiltin  SettingSourceKind = iota // the constructor / tagged-default floor
	SourceDefaults                          // user config.yaml, defaults: scope
	SourceApp                               // user config.yaml, <app>: scope
	SourceProject                           // app-elected project config
	SourceEnv                               // environment variables (DEVLORE_* / <APP>_*)
	SourceCLI                               // command-line flags
)

The setting sources, in ascending precedence order.

func (SettingSourceKind) String

func (k SettingSourceKind) String() string

String returns the layer's name, for diagnostics (config explain).

Returns:

  • `string`: the layer name (e.g. "builtin", "cli"); "unknown(N)" for an out-of-range value.

Jump to

Keyboard shortcuts

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