Skip to main content
Raw configuration is scoped data. Executable configuration is a validated immutable value.
HeavenBase separates configuration storage from configuration meaning. CM_HVNB manages retained scope layers, while ConfigEngine resolves a domain through one fixed pipeline.

1. Why Configuration Exists

Without a config owner, every wrapper carries knobs it does not own:
HeavenBase keeps those defaults in scoped data and lets the owning domain resolve them:
Your application carries the scope or an explicit override, not every provider and backend detail. This keeps function signatures focused and gives each scope retained history.

2. Understand the Ownership Split

  • Context owns the machine backend and its named Registry namespaces.
  • ConfigManager owns defaults, scopes, versioned layers, interpolation, and snapshots.
  • ConfigEngine owns deterministic domain resolution and Apply profiles.
  • Domain engines own LLM, database, workspace, and filesystem policy.
Config scope records use the same persistent Registry protocol as other durable definitions. There is no separate configuration database schema and no second persistence path.

3. Read and Edit Scoped Data

Read one active value with get(...):
Use scoped(...) as a context manager or decorator:
Narrower scopes inherit broader layers. For heavenbase.workspace.docs-demo, resolution reads heavenbase, then heavenbase.workspace, then the complete target scope. Use snapshot() for repeated immutable reads, layer(...) for one raw scope layer, and history(...) for retained versions:
unset(...) writes a tombstone so a child scope can hide an inherited key. setdef(...) writes only when the resolved value is missing. List paths support items[0], items[], and items[2+].
remove(...), compact(..., reset=True), and setup(reset=True) change retained configuration. Use them only on scopes you intend to clean up.

4. Resolve a Domain Configuration

Every ConfigEngine follows the same stages:
  1. Preset expands a complete named template.
  2. Normalize resolves aliases, shorthand, precedence, and canonical values.
  3. Validate checks the canonical value without repairing it.
  4. Apply(profile) returns a deterministic detached value.
The result of Resolve is a ConfigSpec:
ConfigSpec.data contains canonical user-facing fields. bindings contains selected executable contracts. raw and meta remain diagnostic. to_dict() and from_dict() preserve the executable envelope.
A serialized spec can contain credentials in bindings. Use the domain’s redacted print profile for logs and CLI output.

5. Use Apply Profiles

Apply profiles turn one validated spec into a specific value:
Database profiles return SQLAlchemy URLs, serialized URIs, engine arguments, cache keys, pragmas, lifecycle config, or redacted display values. LLM gateway profiles return detached client arguments. Live engines and SDK clients stay in their downstream caches. validate(restored_spec) and apply(restored_spec, ...) do not reread the original manager or catalog. This makes an executable spec portable across process boundaries that share the same code contract.

6. Use Strict Local File URIs

Explicit local storage uses one grammar: Writable locations reject the resource alias. Network authorities, backslashes, root escapes, query strings, fragments, and legacy file: spellings are rejected. A database field may use a separator-free logical name. DBEngine resolves it below heavenbase.db.local_root and stores the canonical file:/// URI in DBSpec.
scripts/migrate_config_locations.py converts owned legacy config files. It defaults to dry-run and verifies that each replacement resolves to the same native target before writing.

7. Understand Caches and Interpolation

Each domain engine has bounded caches for resolved specs and Apply values. Cache identity includes the active scope generations, referenced environment values, root overlay, selected catalog revision, and domain contract revisions. Environment interpolation is enabled by default; command interpolation is disabled:
Use engine.clear_cache() for local domain-cache invalidation and CM_HVNB.refresh() when the next source read must observe the current Registry revision immediately.

8. Extend Configuration Safely

When you add a domain, subclass ConfigEngine, declare one stable domain, and implement protected Normalize, Bind, Validate, and default-profile hooks. Register value-returning Apply profiles instead of branching in generic config. Add tests for idempotence, serialization, source-free restored-spec Apply, cache invalidation, and redaction. Keep provider selection, dialect facts, file policy, SDK behavior, and live resources in the owning domain.
Use engine.assert_idempotent(raw) during development. It checks two uncached Normalize/Bind passes against one frozen source and reports the first changed path.

Further Exploration

Related resources: