Binding.md
PuduLangEnvironment.Binding
type: module path: "@root/src/PuduLangEnvironment/Binding.pudu" fidelity: Active grammar: "[[grammar/pudu]]" depth_score: 0.8 depth_status: DEEP tags: [module] aliases: [PuduLangEnvironment.Binding]
Purpose
Records read from variables by derivation, and rendered with their secrets hidden.
Interface
Signatures
export trait Variable {
fn fromVariable(key: Str, text: Option[Str]) -> Result[Self, Environment.Problem]
fn optional() -> Bool
fn rendered(self: &Self) -> Str
}
impl Variable for Str
impl Variable for Int
impl Variable for Float64
impl Variable for Decimal
impl Variable for Bool
impl Variable for Secret.Secret
impl [A: Variable] Variable for Option[A]
export trait Bind {
fn bind(variables: &Variables.Variables) -> Result[Self, Environment.Problem]
}
export derive Bind for T: Record
export trait Redacted {
fn redacted(self: &Self) -> Str
}
export derive Redacted for T: RecordLinkage
- Requires: [[src/PuduLangEnvironment]], [[src/PuduLangEnvironment/Constants/Names]], [[src/PuduLangEnvironment/Domain/Keys]], [[src/PuduLangEnvironment/Domain/Values]], [[src/PuduLangEnvironment/Variables]].
- Consumed by: [[src/PuduLangEnvironment/Settings]], package users, the suites, and
examples/.
Algorithm
- A field reads the variable
@env("NAME")names, else its own name in upper snake case ([[src/PuduLangEnvironment/Domain/Keys]]). - An unset or empty variable takes
@default("text")when the field has one. - First pass: every required field whose variable is unset and has no default is gathered, and all of them are refused at once as
Missing. - Second pass: each field converts its text through its
Variableimplementation; the first that does not convert is refused asMalformedwith its key and kind. RedactedrendersName{field: value, ...}: each field renders itself throughVariable.rendered, where aSecret.Secret— alone or inside anOption— always renders as[REDACTED], and a field marked@secretrenders as[REDACTED]whatever its type.
Negative Logic (Prohibited Paths)
- No conversion refusal holds the text it refused ([[decisions/ADR-0001-problems-never-carry-values]]).
- The gathering pass asks
optional(), neverfromVariable: a nested static call through a type parameter insideMeta.collectfails on the 0.1.3 compiler (pudu-lang#457).
Edge Cases
Option[A]isNonewhen unset and refuses a set value thatAcannot read.- A default is converted like any other text, so
@default("eight")on anIntisMalformed.
Depth
DEPTH 0.8 (DEEP). Tested by test/PuduLangEnvironment/BindingTest.pudu and test/Integration/LoadScenarioTest.pudu.
Grill Log
- Q: Why a derive rather than a function the caller writes per record? A: The record already states every field and type; a derive reads them at compile time, so adding a setting is adding a field. _Rejected:_ a hand-written build function per record (the mapping repeated in code that drifts from the type).
- Q: Why report every missing variable but only the first malformed one? A: A missing variable is fixed by adding a line, and a deployment usually misses several at once; a malformed one needs reading, and the build pass stops at its first failure. _Rejected:_ stopping at the first missing variable (one restart per missing key).
- Q: Why does a secret render hidden without
@secret? A:showoverStd.App.Secretprints its raw value, so a secret field someone forgot to mark would be printed by the one function meant to be safe. The type decides; the attribute only adds fields of other types. _Rejected:_ rendering unmarked fields withshow(a forgotten attribute leaks). - Q: Why does
Redactedneed its fields to beVariabletypes? A: Rendering goes through the same trait that reads them, so a settings record derives both with no extra trait. The recursion intoOptionis an instance call, whichMeta.collecthandles (pudu-lang#457 affects only static calls). _Rejected:_showfor unmarked fields (leaks secrets, as above).
Referenced by
[[CHANGELOG]] · [[architecture/LANGUAGE]] · [[architecture/_MOC]] · [[decisions/ADR-0005-binding-by-derivation]] · [[handoffs/2026-10-07-initial-package]] · [[src/PuduLangEnvironment/Constants/Names]] · [[src/PuduLangEnvironment/Domain/Keys]] · [[src/PuduLangEnvironment/Domain/Values]] · [[src/PuduLangEnvironment/Settings]] · [[src/PuduLangEnvironment/Variables]] · [[src/PuduLangEnvironment/_MOC]]
