# Configuration Input Contract This document owns ConfigKit's currently implemented source-input and YAML syntax contracts. The parser and owned document representation are private; a public typed loading lifecycle has not been implemented yet. ## Sources ConfigKit exposes opaque sources through these constructors: | Constructor | Current contract | | --- | --- | | `File(path)` | Requires a nonempty path, opens a regular file for each consumption, and closes only the library-owned file handle. Missing, inaccessible, unreadable, directory, and other nonregular inputs fail. | | `Bytes(label, data)` | Requires a nonempty, non-secret diagnostic label and snapshots bytes during construction. Later caller mutation cannot affect the source. | | `Reader(label, input)` | Requires a nonempty, non-secret label and non-nil reader. The reader is claimed once across all copies of the source, consumed but never closed, and cannot be reused. | | `NoSource()` | Represents an explicit absence of input and creates no source record. Its defaults-only lifecycle behavior will become available with `Load`. | The zero `Source` is invalid. Constructor argument failures are retained inside the opaque source and become safe structured diagnostics when the source is consumed. File sources can observe file changes between consumptions; byte sources cannot. Each source is limited to 8 MiB. A load will be limited to 64 MiB across all source and override input when those layers are implemented. Reads request at most the remaining allowance plus one byte so excess data is rejected rather than silently truncated. Data returned together with a read error is not accepted as partial input. ## YAML documents The private YAML boundary currently accepts exactly one nonempty document whose root is a mapping. Comments and block or flow collections are supported. It rejects: - empty input or an empty document; - every additional document, including an empty one; - duplicate decoded mapping keys; - non-string mapping keys; - explicit tags, anchors, aliases, and merge keys; - a quoted or plain mapping key equal to `<<`; and - input exceeding the fixed depth or node limits. Mapping key comparison is exact: it performs no case folding or Unicode normalization. The private document tree retains declaration order, exact validated number spelling, source identifiers, and separate key/value line and column locations. It contains no upstream parser nodes or types. Root depth is zero. Input depth is limited to 256 and each parsed input tree to 1,000,000 nodes, counting mapping keys as input nodes. The upstream parser also has a private calibrated depth guard; passing that guard never bypasses ConfigKit's tree limits. ## Scalars Scalar meaning is determined by ConfigKit rather than upstream coercion: | Input form | Meaning | | --- | --- | | Quoted, literal, or folded scalar | String | | Plain `true` or `false` | Boolean | | Plain `null`, `~`, or an empty mapping value | Null | | JSON decimal number | Number, retaining its exact spelling | | Date/time-looking or other ordinary plain text | String | JSON numbers permit an optional minus, a zero or nonzero decimal integer without a leading zero, an optional fraction with at least one digit, and an optional decimal exponent. Hexadecimal, octal, digit separators, leading plus, leading/trailing-dot forms, incomplete exponents, and non-finite values are rejected. Legacy boolean words (`yes`, `no`, `on`, and `off`) and non-lowercase variants of the reserved boolean/null words are rejected unless quoted. Mapping keys use the same scalar classification and must classify as strings. Quote keys that otherwise classify as a boolean, number, or null. ## Safe failures Source failures use stable `source.*` codes and YAML failures use stable `yaml.*` codes declared by the root package. Diagnostics contain safe classifications, semantic paths when applicable, and available source coordinates. Raw parser, conversion, reader-error, and input text is not forwarded. Source labels and diagnostic messages are application-visible and therefore must never contain secrets; terminal control characters are escaped by `WriteDiagnostics`.