Configuration — current state¶
Version: 0.3 · Last Updated: 2026-09-08 · Status: 🔴 evidence refreshed; design ratification unchanged
Verified against source revision 2465fcc (develop baseline). Test references
below identify the executable contracts; they are not a new coverage percentage.
Recipe, grammar and precedence¶
AsgiConfigBuilder combines the contrib configuration builder with
AsgiServerGrammar. A recipe overrides main(self, root). BaseConfiguration
supplies package defaults through server_section and storage_mounts; the
site: mount is anchored to the working directory when the recipe runs.
DefaultConfig.parents_for layers package defaults, optional machine defaults,
then the site recipe. default_config=False opts out of machine defaults; an
explicit missing path raises ConfigError. The machine home resolves from the
explicit argument, GENRO_ASGI_HOME, then ~/.genroasgi.
ConfigurationHandler is a read interface. Its inherited precedence is written
value, grammar signature default, call-site default, then KeyError. Closed
signatures are read attribute by attribute; open kwargs use resolved runtime
values. BaseApplication.config reads relative to applications.<code>.
AsgiServer consumes the resulting kwargs and builds applications itself.
Claim anchors: AsgiConfigBuilder, AsgiServerGrammar, AsgiServer, BaseConfiguration, server_section, storage_mounts, DefaultConfig, parents_for, ConfigError, ConfigurationHandler.
Server and application vocabulary¶
The grammar declares server, middleware, authentication, storage, applications,
databases, plugins and OpenAPI sections. The OpenAPI root section has no current
core consumer. server includes shutdown_timeout_seconds; its children
include session, tasks and websocket. websocket.origins is a comma-separated
recipe value converted to a list; max_concurrent defaults to 16.
Storage mounts use the storage application's foreign grammar. Each application
mounts its own app_class.grammar, so the multiworker SPA's pool is under
applications.<code>.orchestration.commander, never a server-level section.
admin_password must be a resolver and must resolve to a nonempty string.
Claim anchors: websocket, admin_password, admin_password.
Live group settings versus general live configuration¶
SPA group profiles support live apply and reload. SpaApplication composes
defaults, recipe settings, a profile and environment settings. GroupPolicy
validates the result before SpaCommander.apply_group_settings commits it under
its configuration lock. A named profile requires exactly one group.
The general writable configuration tree remains unimplemented: there is no
apply_configuration or handler mutator and no server subscriber for dynamic
application installation. The group-settings API is a bounded operation on an
existing pool, not evidence that the general live-tree design has landed.
Claim anchors: SpaApplication, GroupPolicy, SpaCommander, apply_group_settings.
Source and test evidence¶
- src/genro_asgi/config/builder.py
- src/genro_asgi/config/default_config.py
- src/genro_asgi/config/elements.py
- src/genro_asgi/config/handler.py
- src/genro_asgi/asgi_server.py
- src/genro_asgi_multiworker_spa/spa_app.py
- src/genro_asgi_multiworker_spa/orchestration/group_policy.py
- src/genro_asgi_multiworker_spa/orchestration/spa_commander.py
- tests/core/test_config.py
- tests/core/test_config_env.py
- tests/spa/test_spa_profile_grammar.py
- tests/spa/test_spa_app_profiles.py
- tests/spa/test_apply_group_settings.py