Skip to content

Configuration Capability (Flow)

This document describes the end-to-end technical flow for configuration management across SmrtHub components.

Subsystem contract reference: README.Files/Subsystems/Configuration/README.md

Purpose and scope

  • Explain how components locate config/state artifacts and decide roaming vs local scope.
  • Describe the expected lifecycle: defaults, load, validate, migrate, save, observe.
  • Provide failure-mode guidance for operators and developers.

Entry points

Typical initiators of configuration flows:

  • Component startup: load configuration and state prior to starting long-running services.
  • Operator actions: configuration updates (UI, CLI, or tool-driven) that must persist atomically.
  • Background jobs: periodic refreshes or state snapshots (for example health/telemetry).

Participating Components/Subsystems

  • Configuration Subsystem (contracts and canonical paths): README.Files/Subsystems/Configuration/README.md
  • Logging Subsystem (where to observe failures): README.Files/Subsystems/Logging/README.md
  • Core library (C#): SmrtApps/src/Smrt.Config/README.md
  • Python runtime: SmrtApps/PythonApp/python_core/** (uses the Python config path resolver)
  • Consumers: any component that owns config/state artifacts under the Operational Data Policy.

Sequence / flow

  1. Determine component slug and scope
  2. Resolve the component slug (kebab-case) and choose scope (roaming vs local) based on the artifact’s intent (user profile vs machine/runtime).

  3. Resolve canonical paths

  4. Compute the canonical directory and file name per Operational Data Policy.
  5. Ensure the directory exists.

  6. Seed defaults (first run only)

  7. If the config file is absent and the component ships defaults, copy defaults into the canonical location.
  8. Defaults must not contain secrets.

  9. Load and validate

  10. Load JSON into a strongly typed model or validated object.
  11. Handle common error cases: missing file, parse failure, schema mismatch.
  12. When recoverable, fall back to defaults and log a clear diagnostic.

  13. Migrate (when versioned)

  14. If schemaVersion indicates an older version, apply a forward migration and persist the migrated result atomically.
  15. If forward migration is unsupported, fail fast or regenerate defaults (component-defined), and log the operator impact.

  16. Persist updates atomically

  17. All updates are written atomically; if a previous copy exists, produce a single .bak.
  18. For multi-process updates, enforce a single-writer guard (mutex/lock) before writing.

  19. Observe and troubleshoot

  20. Use unified per-component logs to identify failures.
  21. Confirm on disk that artifacts exist under the canonical config directory for the component slug.

Contracts and data shapes

  • Configuration is UTF-8 JSON with deterministic serialization.
  • Secrets never appear in persisted JSON; only references/IDs.
  • State JSON is treated like config with the same atomic and backup behaviors.

Failure modes and expected behaviors

  • File missing: seed defaults (if available) or initialize to safe defaults; log at Information/Warning.
  • Parse failure / corruption: attempt recovery, fall back to defaults, preserve .bak when overwriting; log at Warning/Error with guidance.
  • Permission failure: fail fast with an actionable error (directory, scope, expected location).
  • Schema mismatch: either migrate or fail with a clear operator message; do not silently ignore.

Observability & diagnostics

  • Primary evidence is unified per-component logs (and the initiating component’s logs).
  • See the Logging Subsystem doc for log locations and troubleshooting workflow: README.Files/Subsystems/Logging/README.md.
  • Not documented yet: standardized event names for config load/validate/migrate failures.

Testing & validation expectations

  • Unit tests for path resolution and filename conventions.
  • Integration tests that exercise atomic write + .bak behavior.
  • Cross-runtime parity tests for shared slugs and artifact kinds.
  • Manual smoke: edit a config file, verify the component reloads (if supported) or reads it on next start, and verify the error path when JSON is malformed.