Keyboard shortcuts

Press or to navigate between chapters

Press S or / to search in the book

Press ? to show this help

Press Esc to hide this help

Explain as a Contract

explain(path) answers the only question that matters at 3am: why is this value what it is? Its answer is a stable type, not a log line — which makes it something a CLI, a debug endpoint, or a support script can build on. What follows is the shape that will not change under the compatibility contract.

The shape

An Explanation is every configured layer's row for one path, lowest precedence first — absent layers included, because "the env layer supplied nothing" is half of most surprises:

db.pool = 32

  layer            source                          value
  defaults         set_defaults                    8
  file             /etc/app/config.toml            16
  env              APP_DB__POOL                    32   ← winner
  flags            —                               (nothing)
  override         —                               (nothing)

Each row is a Contribution { layer, origin, value, aliased_from }; winner() is the highest row that supplies anything; the rows slice is public for anything that formats its own table.

The guarantees

  • Row order is precedence order. The table is the precedence documentation, generated from the same code that merges — it cannot drift from reality.
  • Absent layers appear by name. A layer you configured that supplies nothing shows as such; a layer you never configured is not invented.
  • Aliases say both halves: the row is labelled alias db::timeout (the old spelling) and the origin names the file. Where it came from, and under which key.
  • Display shows values; Debug never does. A routine debug!(?explanation) cannot leak — the value field prints .... redacted() blanks values while keeping origins: where a secret comes from is the useful half, and the safe one.
  • Values render short: tables and lists show their shape (a table (3 keys)), not their contents.

The three surfaces

SurfaceCall
RustAppConfig::explain("db.pool")? / free explain(&spec, path)
CLIdynamic-config explain db.pool
Python / Nodeexplain("db.pool") — same rows, same order

The bindings return the same rows in language-native shapes; the conformance suite holds provenance parity across all three.

What it is for

Wire it to a /debug/config endpoint (redacted), a support-bundle dump, or a startup --explain <path> flag. The type is stable so those integrations survive engine upgrades — that is the contract in the page title.