12. Configuration: The Codex
Context and Problem Statement
Configuration fragmentation creates structural blindness. When intent is scattered across hardcoded paths, environment variables, and implicit runtime state, the system loses determinism. In a Sepulcher that bridges Host and Container, this fragmentation produces port collisions, permission mismatches, and non-reproducible infrastructure states.
A sovereign system requires a single source of truth, strict validation before manifestation, and a deterministic mapping between filesystem topology and runtime behavior.
Requirements
- Single Source of Truth: All user intent must reside within a bounded configuration domain.
- Type Authority: Configuration must be validated through explicit schemas before any infrastructure is generated.
- Deterministic Discovery: Filesystem hierarchy must uniquely determine schema ownership and instance identity.
- Fail-Fast Validation: Port conflicts, duplicate singleton declarations, and schema violations must abort loading before Quadlets are written.
- Secret Discipline: Sensitive values must be protected from accidental exposure and validated for permission correctness.
- Privatization Policy: Context egress thresholds and anonymization requirements must be configurable as first-class policy.
- Extensibility Contract: Extensions must integrate into the configuration system without custom parsers or ad-hoc loading logic.
- Infrastructure Integrity: Configuration must be fully validated before container units are manifested.
Considered Options
Option 1: Monolithic Configuration
Placing all configuration — global settings and multi-instance infrastructure — into a single lychd.toml.
- Pros: Easy to locate and edit.
- Cons: Structural Degeneration. Instance identity becomes implicit. Ordering matters. Silent overwrites become possible. Extension grafting becomes fragile.
Option 2: Environment-Driven Configuration
Relying primarily on environment variables or distributed .env files.
- Pros: Familiar pattern.
- Cons: Opaque State. Environment variables are invisible to version control and cannot express multi-instance topology. Structural validation cannot occur before process startup.
Option 3: Layered Codex Architecture
Separating configuration into a typed Schema Layer and anchored Rune Schemas.
- Pros:
- Deterministic Topology: Directory structure defines schema ownership.
- Type Enforcement: All configuration validated through Pydantic models.
- Extension Compatibility: Any extension inheriting
RuneConfigparticipates in the same loading model. - Fail-Fast Infrastructure: Quadlets are generated only after full validation succeeds.
- Clear Secret Model: Explicit at-rest protection and runtime boundary definition.
Decision Outcome
A layered configuration system is adopted, structured around the Codex. This ADR defines the Codex contract (global settings, rune schemas, ownership, discovery, validation, and loading order). Layout (ADR 13) defines the filesystem geography and mount topology where that contract resides.
The Codex resides at:
~/.config/lychd/
XDG path resolution and Host/Container symmetry for this domain are specified in Layout (ADR 13).
It contains two distinct domains:
- The Application Settings
- Rune Schemas
1. The Application Settings (lychd.toml)
Contains global configuration only.
Examples include:
- Application-level settings
- Core service configuration
- Coven alliances
- Global defaults
Schema authority for global settings resides in src/lychd/config/settings.py.
src/lychd/config/components.py consumes the validated settings object into framework component configuration.
It carries no multi-instance infrastructure definitions.
If secret references are declared in Codex:
- The file must be owned by the Magus.
- File permissions must be
0600. - Startup validation emits a structured warning if permissions are broader.
The Global config defines global truth.
2. The Schema Layer (src/lychd/config/settings.py)
The Schema Layer provides type authority and deterministic loading.
It is implemented using Pydantic and defines:
- Required fields
- Strict typing
- Secret-reference enforcement for credentials (
*_secretfields) - Deterministic source precedence (
Settings.settings_customise_sources()):
Init kwargs → Explicit Environment Overrides → Codex `.env` → `lychd.toml` → File Secrets → Model Defaults
Environment variables enter through explicit override channels in the schema loader.
If .env files are used:
- They must reside within the Codex boundary.
- They must be
0600. - Permission violations produce warnings.
The Schema Layer validates global state before any infrastructure intent is processed.
Exact source precedence and reserved-port validation are implemented in src/lychd/config/settings.py:321:
Live snippet: src/lychd/config/settings.py:321
codex_issues = codex_permission_issues(PATH_LYCHD_TOML)
if codex_issues:
import warnings
warnings.warn(
f"codex_permissions_policy_violation: path={PATH_LYCHD_TOML} issues={codex_issues}",
UserWarning,
stacklevel=2,
)
return self
def ensure_internal_secret_fallbacks(settings: Settings) -> list[str]:
"""Ensure app/db runtime secrets exist even before Podman bind.
This is a startup safety-net for direct process execution (development,
tests, or any flow that boots without mounted Podman secrets). It does not
replace bind-time Podman secret provisioning.
"""
created: list[str] = []
if needs_generated_secret_fallback(
value_env_keys=("APP__SECRET_KEY", "APP_SECRET_KEY"),
file_env_keys=("APP__SECRET_KEY_FILE", "APP_SECRET_KEY_FILE"),
default_file=Path("/run/secrets") / settings.app.secret_key_secret,
):
settings.app.set_runtime_secret_key_override(secrets.token_hex(32))
created.append(settings.app.secret_key_secret)
if needs_generated_secret_fallback(
value_env_keys=("DB__PASSWORD", "DB_PASSWORD"),
file_env_keys=("DB__PASSWORD_FILE", "DB_PASSWORD_FILE"),
default_file=Path("/run/secrets") / settings.db.password_secret,
):
settings.db.set_runtime_password_override(secrets.token_urlsafe(16))
created.append(settings.db.password_secret)
return created
@lru_cache(maxsize=1, typed=True)
def get_settings() -> Settings:
settings = Settings()
ensure_internal_secret_fallbacks(settings)
return settings
3. Rune Schemas (Instance Scrolls)
Infrastructure intent is declared through Rune Schemas.
Each schema:
- Inherits from
RuneConfig - Declares
relative_pathrooted at~/.config/lychd/runes/(orNonefor runes root) - Uses
singleton: bool | NonewhereNoneenables auto topology inference
Rune instances are stored as TOML files under their Anchor directory.
Example structure:
~/.config/lychd/
lychd.toml
runes/
animator/
animator.toml
soulstones/
vision.toml
ocr.toml
portals/
openai.toml
The Anchor Doctrine
Each RuneConfig schema owns exactly one anchor territory.
- Folder location determines schema type.
- Anchors may not overlap.
- No internal
type=switching is permitted. - The filesystem hierarchy is authoritative.
Schema ownership is structural, not dynamic.
Loader enforcement for anchor scanning, singleton exclusivity, top-level TOML payload, and duplicate identity rejection lives in src/lychd/config/runes/loader.py:19:
Live snippet: src/lychd/config/runes/loader.py:19
class ConfigLoader:
"""Validation loader for explicit RuneConfig schemas."""
def __init__(self, runes_dir: Path | None = None) -> None:
"""Create a loader for runes under a specific root."""
self._runes_dir = runes_dir or RuneConfig.config_root
def load_all(self, schemas: Sequence[type[RuneConfig]]) -> list[RuneConfig]:
"""Load and validate all rune instances for explicit schema classes."""
loaded: list[RuneConfig] = []
for cls in schemas:
loaded.extend(self._load_class_instances(cls))
logger.debug("runes_loaded", count=len(loaded), classes=[c.__name__ for c in schemas])
return loaded
def _load_class_instances(self, cls: type[RuneConfig]) -> list[RuneConfig]:
files = self._candidate_files(cls)
instances: list[RuneConfig] = []
for file_path in files:
payload = self._read_payload(file_path, cls)
instance = cls.model_validate(payload).with_file_name(file_path)
instances.append(instance)
if cls.effective_singleton() and len(instances) > 1:
msg = f"Schema '{cls.__name__}' is singleton but found {len(instances)} files in '{cls.anchor_dir()}'."
raise RuneConfigError(msg)
self._assert_unique_identity(cls, files)
return instances
def _candidate_files(self, cls: type[RuneConfig]) -> list[Path]:
if cls.relative_path is None:
singleton_path = self._runes_dir / cls.default_file_name()
return [singleton_path] if singleton_path.exists() else []
anchor = self._runes_dir / cls.relative_path
if not anchor.exists():
return []
files = sorted(anchor.rglob("*.toml"))
if not files:
return []
# Parent schemas do not sweep child anchors.
child_anchors = [self._runes_dir / rel for rel in self._descendant_relative_paths(cls)]
if not child_anchors:
return files
return [path for path in files if not any(path.is_relative_to(child) for child in child_anchors)]
def _descendant_relative_paths(self, cls: type[RuneConfig]) -> set[Path]:
paths: set[Path] = set()
for sub in cls.__subclasses__():
if sub.relative_path is not None:
paths.add(sub.relative_path)
paths.update(self._descendant_relative_paths(sub))
return paths
def _read_payload(self, file_path: Path, cls: type[RuneConfig]) -> dict[str, Any]:
try:
parsed = tomllib.loads(file_path.read_text(encoding="utf-8"))
except tomllib.TOMLDecodeError as exc:
msg = f"Malformed TOML in '{file_path}'."
raise RuneConfigError(msg) from exc
except OSError as exc:
msg = f"Could not read '{file_path}'."
raise RuneConfigError(msg) from exc
content: dict[str, Any] = {str(k): v for k, v in parsed.items()}
if "model" in content and isinstance(content["model"], dict) and "model" not in cls.model_fields:
msg = (
f"File '{file_path}' uses legacy '[model]' envelope syntax. "
"Rune payload must be written at TOML top level."
)
raise RuneConfigError(msg)
return content
def _assert_unique_identity(self, cls: type[RuneConfig], files: list[Path]) -> None:
seen: set[str] = set()
The Instance Doctrine
Within an Anchor:
- One TOML file equals one instance.
- Instance payload resides at TOML top level (arrays-of-tables are forbidden for instance encoding).
- Instance identity is derived from relative path.
- Duplicate identity across files is forbidden.
If a schema resolves as singleton, only one file may exist.
Violations abort configuration loading.
The Leaf Principle
Only leaf schemas (those without subclasses) may define multiple instances by default.
Non-leaf schemas are singleton by default.
Explicit singleton=True/False overrides auto behavior.
This prevents ambiguous discovery and implicit polymorphic loading.
4. The Configurable Contract (Extension Integration)
Configuration extensibility is governed by a single structural contract: RuneConfig.
Any extension that wishes to declare configuration must:
- Inherit from
RuneConfig - Declare
relative_path(orNonefor top-level singleton) - Optionally declare
singletonoverride
Example contract and helper methods are defined directly in src/lychd/config/runes/base.py (see RuneConfig snippet above).
Registration Doctrine
Configuration schemas are registered structurally, not procedurally.
- The subclass itself is the registration signal.
- Runtime import plus subclass discovery determines ownership.
- No extension may implement custom configuration loaders.
- No dynamic
type=dispatch is permitted.
Inheritance automatically binds the schema to:
~/.config/lychd/runes/<relative_path>/
If an extension is installed:
- Its
RuneConfigsubclasses are discovered. - Their Anchors become valid Codex territories.
- One TOML file equals one instance and payload lives at TOML top level.
- Instances located in those directories are validated and loaded.
- Validated instances become infrastructure intent.
Extension import + inheritance registers schema ownership under the shared loader.
The Codex loader remains singular and authoritative.
Structural Guarantees
This model ensures:
- Extensions cannot fragment configuration loading.
- Configuration remains globally validated.
- Infrastructure manifestation remains downstream of schema authority.
- Removal of an extension invalidates only its anchor territory.
Configuration extensibility is therefore achieved without sacrificing determinism.
5. Port Arbitration
Port ownership is validated before Quadlet generation.
The validator aggregates:
- Reserved core ports
- Ports declared by Rune Schemas
If any collision is detected:
- Configuration loading fails immediately.
- No Quadlets are written.
Infrastructure is never generated from invalid state.
6. Runtime Realization (lychd init)
At runtime, initialization follows a deterministic inscription path:
lychd initcallsCodexService.inscribe().RuneSchemaDiscovery.discover_classes()imports built-in extensions and discovers allRuneConfigsubclasses.ConfigWriter.initialize_anchors()materializes all anchor directories.ConfigWriter.inscribe_samples()writes one sample TOML per schema only when no instance file exists yet.
This keeps extension configuration registration structural (inheritance/import), not procedural.
Animation follows the same path: AnimatorLoader consumes the same RuneConfig runes under runes/animator/.
Discovery import + subclass traversal (RuneSchemaDiscovery) is implemented in src/lychd/config/runes/discovery.py:10:
Live snippet: src/lychd/config/runes/discovery.py:10
class RuneSchemaDiscovery:
"""Discover RuneConfig schemas after runtime import/bootstrap."""
def __init__(
self,
*,
include_builtin_extensions: bool = True,
external_packages: Iterable[str] = (),
) -> None:
"""Create a schema discoverer.
Args:
include_builtin_extensions: Import built-in extension modules.
external_packages: Additional extension package trees to import.
"""
self._include_builtin_extensions = include_builtin_extensions
self._external_packages = tuple(external_packages)
def discover_classes(self) -> list[type[RuneConfig]]:
"""Return all currently imported RuneConfig subclasses."""
# Import core schema module before subclass traversal.
importlib.import_module("lychd.domain.animation.schemas")
discovery = ExtensionDiscovery()
if self._include_builtin_extensions:
discovery.import_builtin_modules()
if self._external_packages:
discovery.import_packages(self._external_packages)
discovered: set[type[RuneConfig]] = set()
self._collect_subclasses(RuneConfig, discovered)
filtered = [cls for cls in discovered if self._is_allowed_schema_module(cls)]
return sorted(filtered, key=lambda cls: (cls.__module__, cls.__qualname__))
def _collect_subclasses(self, parent: type[RuneConfig], discovered: set[type[RuneConfig]]) -> None:
for subclass in parent.__subclasses__():
self._collect_subclasses(subclass, discovered)
discovered.add(subclass)
def _is_allowed_schema_module(self, cls: type[RuneConfig]) -> bool:
module = cls.__module__
allowed_packages = ("lychd", *self._external_packages)
return any(module == package or module.startswith(f"{package}.") for package in allowed_packages)
Anchor creation and sample inscription (ConfigWriter) are implemented in src/lychd/config/runes/writer.py:16:
Live snippet: src/lychd/config/runes/writer.py:16
def __init__(self, runes_dir: Path | None = None) -> None:
"""Create a writer for runes under a specific root."""
self._runes_dir = runes_dir or RuneConfig.config_root
def initialize_anchors(self, schemas: list[type[RuneConfig]]) -> None:
"""Ensure all schema anchor directories exist."""
for schema in schemas:
anchor = self._runes_dir if schema.relative_path is None else self._runes_dir / schema.relative_path
anchor.mkdir(parents=True, exist_ok=True)
logger.debug("anchor_initialized", schema=schema.__name__, anchor=str(anchor))
def inscribe_samples(self, schemas: list[type[RuneConfig]]) -> list[Path]:
"""Write one sample TOML per schema when no files exist yet."""
created: list[Path] = []
for schema in schemas:
target = self._target_sample_file(schema)
if target is None:
continue
target.parent.mkdir(parents=True, exist_ok=True)
target.write_text(self._render_sample(schema), encoding="utf-8")
created.append(target)
logger.info("rune_sample_inscribed", schema=schema.__name__, path=str(target))
return created
def _target_sample_file(self, schema: type[RuneConfig]) -> Path | None:
"""Return sample target path if schema has no existing TOML instances."""
if schema.relative_path is None:
target = self._runes_dir / schema.default_file_name()
return None if target.exists() else target
anchor = self._runes_dir / schema.relative_path
existing = list(anchor.rglob("*.toml")) if anchor.exists() else []
child_anchors = [self._runes_dir / rel for rel in self._descendant_relative_paths(schema)]
if child_anchors:
existing = [path for path in existing if not any(path.is_relative_to(child) for child in child_anchors)]
if existing:
return None
return anchor / schema.default_file_name()
def _descendant_relative_paths(self, schema: type[RuneConfig]) -> set[Path]:
paths: set[Path] = set()
for sub in schema.__subclasses__():
if sub.relative_path is not None:
paths.add(sub.relative_path)
paths.update(self._descendant_relative_paths(sub))
return paths
def _render_sample(self, schema: type[RuneConfig]) -> str:
lines: list[str] = []
7. Assembly Pipeline
The configuration lifecycle proceeds in strict order:
- Load Global config.
- Validate Schema Layer.
- Discover Anchored Rune Schemas.
- Validate each instance.
- Enforce:
- Singleton exclusivity
- Duplicate identity rejection
- Port arbitration
- Only after full validation:
- Generate Quadlets.
Infrastructure is a manifestation of validated intent.
8. Secret Covenant
Secrets are declared by reference:
- Codex stores secret names (
*_secret) only. - Soulstones may map runtime env vars to secret names via
secret_env_files. - Values live in rootless Podman secret storage.
- Generated Quadlets bind them through
Secret=directives.
Secrets:
- Are not stored inline in
lychd.tomlor rune TOMLs - Are mounted only into units that require them
- Are accessible to the process boundary that consumes them
Example lifecycle:
printf '%s' "$OPENAI_API_KEY" | podman secret create --replace portal_openai_main -
podman secret ls
Filesystem permissions protect secrets from other host users.
They do not protect secrets from code executing within the same Quadlet unit.
If isolation from agent-level execution is required, the secret must reside in a separate service boundary.
9. Context Privatization Policy
Privatization policy is configured in the Codex and enforced by runtime dispatch:
portal_threshold: minimum weight requiring anonymization before portal egress.forbidden_threshold: minimum weight forbidding raw portal egress.require_anonymization_workflow: fail-closed if no sanitization path exists.
Canonical source is Codex (lychd.toml).
Phylactery-backed policy records, when enabled for adaptive tuning, must remain equal or stricter than the Codex baseline.
Conceptual shape:
[security.privatization]
portal_threshold = 0.40
forbidden_threshold = 0.70
require_anonymization_workflow = true
10. Dual-Plane Trust Delta
Configuration is now split by trust boundary:
- Vessel config is the only source of truth for secrets, persistence, and policy.
- The Tomb config is a generated runtime envelope with only task-safe fields.
- The Tomb config is derived data, never an alternate source of truth.
- The Tomb schema forbids secret fields and infrastructure authority fields.
- Provider/API keys are never serialized into Tomb payloads.
- The Tomb cannot override queue, network, or authority policy.
5. Authority Matrix
| Dimension | Vessel (Trusted Control Plane) | The Tomb (Untrusted Execution Plane) |
|---|---|---|
| Secrets | Loaded via Podman secret references and mounted into trusted units. | Secret fields are forbidden by schema. |
| Mounts | Codex-backed config and durable state mounts. | Sanitized task-scoped config artifact only. |
| Network | Resolves provider and broker routes per policy. | No direct secret-bearing provider routes. |
| Queue Ownership | Owns queue workflow configuration. | No queue configuration ownership. |
| Context Privatization | Defines thresholds and anonymization policy for portal egress. | Cannot lower thresholds or bypass sanitization gates. |
| Authority Boundaries | Defines and signs runtime envelopes. | Consumes envelope; cannot redefine authority. |
Consequences
Positive
- Deterministic Topology: Filesystem structure defines schema ownership and instance identity.
- Fail-Fast Guarantees: Invalid configuration aborts before infrastructure generation.
- Extension Uniformity: Any extension inheriting
RuneConfigintegrates without special handling. - Clear Trust Boundaries: Secret visibility is explicit and aligned with process boundaries.
Negative
- Strict Structural Discipline: Incorrect directory placement or duplicate identity causes immediate failure.
- Shared Process Trust Domain: Secrets available to a Quadlet unit are accessible to code within that unit.
- Operational Responsibility: File permissions must be maintained to preserve at-rest protection.