star-toml 26.7.3

Framework for loading, layering, and validating any *.toml configuration file
Documentation
# star-toml

**Version**: v26.6.29

A framework for loading, layering, validating, and **admitting** configuration files in Rust — the `*` in `*.toml`.

Most configuration frameworks parse a file into a struct and stop. `star-toml` treats configuration as **operational law** and provides the core substrate for **config admission**.

```text
Do not build a path.
Build the bounded space of paths,
the laws that admit them,
the generators that manufacture them,
the detectors that falsify them,
the witnesses that preserve them,
and the gate that decides standing.
```

---

## Crate Ecosystem

| Crate | Description |
|-------|-------------|
| [`star-toml`] | Core admission framework — schema, layering, validation |
| [`star-toml-derive`] | Procedural macros for custom validator derivation |
| [`star-toml-json-schema`] | JSON Schema bridge — import/export, 16-check bridge validation |
| [`star-toml-config-test`] | Runtime conformance test helpers and DfCM matrix runner |
| [`star-toml-lsp`] | LSP server — live diagnostics, hover cards, release-verifier commands |

[`star-toml`]: https://crates.io/crates/star-toml
[`star-toml-derive`]: https://crates.io/crates/star-toml-derive
[`star-toml-json-schema`]: https://crates.io/crates/star-toml-json-schema
[`star-toml-config-test`]: https://crates.io/crates/star-toml-config-test
[`star-toml-lsp`]: https://crates.io/crates/star-toml-lsp

---

## 🏛️ The Core Thesis: Configuration is Operational Law

Most software systems do not fail because they lack code. They fail because their operational law is implicit, underbounded, or non-witnessed.

`star-toml` replaces **narrative authority** ("trust me, it works") with **machine-visible standing**:
* **Raw Parse ≠ Trusted Config:** Syntactically valid TOML is not an admitted configuration.
* **OCEL = Lifecycle/Process History:** Process-mining logs (`wasm4pm-compat` OCEL export) record the process history but do not compute $q_{config}$ or grant standing.
* **q_config = Standing Decision:** The configuration standing bit ($q_{config} = 1$) is calculated from pipeline completeness, witness integrity, and an empty failset.
* **AdmittedConfig<T>:** The terminal, immutable, witness-backed envelope representing a configuration with standing.

---

## 🚀 The Config Admission Pipeline

`star-toml` provides two typestate-guaranteed pipelines depending on whether you need full provenance tracking:

**Simple path** (`Loader`) — compose layers, deserialize, validate, freeze:
```text
Raw (String/File)
 ↳ Merged          — traced layer merge (deep_merge_traced + WinnerMap)
    ↳ Deserialized<T>  — schema alignment, serde
       ↳ Validated<T>  — Pydantic-grade custom rules (Validate trait)
          ↳ Frozen<T>  — immutable; save_canonical() writes sorted TOML to disk
```

**Provenance-tracked admission path** (`TrustedLoader`) — full standing decision with witness:
```text
Raw (String/File)
 ↳ BoundedSources  — source list checked, provenance reports built
    ↳ EnvResolved  — prefixed environment variable overrides applied
       ↳ Deserialized<T>
          ↳ Validated<T>
             ↳ Frozen<T>
                ↳ AdmittedConfig<T>  — terminal admitted config
                   • ConfigWitness (BLAKE3) computed internally and bound to all provenance inputs
                   • save_canonical() available before this step on Validated/Frozen
```

> **Note:** `CanonicalSaved` and `Witnessed` are **not** typestates — `save_canonical()` is a
> method on `Config<Validated<T>>` / `Config<Frozen<T>>`, and the `ConfigWitness` is computed
> inside `load_admitted()`. `Merged` only exists on the simple `Loader` path; `TrustedLoader`
> uses `BoundedSources → EnvResolved` instead.
>
> `load_admitted_strict()` is **deprecated** since v26.6.28. Use `load_admitted()` (strict by
> default) or `load_admitted_exploratory()` to allow unknown fields during schema development.

---

## 🛠️ Usage Example

```rust
use serde::{Deserialize, Serialize};
use star_toml::{
    loader::{ConfigLifecycle, TrustedLoader},
    Validate, Validator,
};

#[derive(Debug, Deserialize, Serialize, Clone)]
struct AppConfig {
    name: String,
    port: u16,
}

impl Validate for AppConfig {
    fn validate(&self, v: &mut Validator) {
        v.check_non_empty("name", &self.name);
        v.check_range("port", self.port, 1024..=65535);
    }
}
impl ConfigLifecycle for AppConfig {}

fn main() {
    // TrustedLoader: provenance-tracked admission path with BLAKE3 witness
    match TrustedLoader::new()
        .layer_file_if_exists("config.toml")  // optional base file
        .env_prefix("APP_")                    // APP_NAME, APP_PORT override
        .load_admitted::<AppConfig>()          // strict: rejects unknown fields
    {
        Ok(admitted) => {
            println!("Admission Granted (q_config = 1)");
            println!("Config: {:?}", admitted.value());
            println!("Witness: {}", admitted.witness().hash()); // 64-char BLAKE3 hex
        }
        Err(e) => {
            println!("Admission Refused (q_config = 0): {e}");
        }
    }
}
```

**Key API surface:**

| Builder | Method | Returns |
|---------|--------|---------|
| `TrustedLoader` | `.load_admitted::<T>()` | `Result<AdmittedConfig<T>>` — strict, witness-backed |
| `TrustedLoader` | `.load_admitted_exploratory::<T>()` | `Result<AdmittedConfig<T>>` — allows unknown fields |
| `TrustedLoader` | `.load_frozen::<T>()` | `Result<FrozenLoadResult<T>>` — full provenance reports |
| `Loader` | `.load_validated::<T>()` | `Result<Config<Validated<T>>>` — simple path |
| Free fn | `save_canonical(path, &T)` | `Result<()>` — alphabetically sorted TOML |
| Free fn | `save_pretty(path, &T)` | `Result<()>` — human-readable TOML |
| Free fn | `deep_merge_traced(base, overlay, id, prefix, winner_map)` | provenance-tracked merge |
| Type | `WinnerMap` | `BTreeMap<String, String>` — field path → winning layer id |

---

## 📐 DfCM (Design for Combinatorial Maximalism)

`star-toml` is designed under the **DfCM** discipline. MVP asks: *"What is the smallest happy path?"* DfCM asks: *"What is the complete bounded variant space this system must survive?"*

Every configuration loader evaluates:
1. **Sources:** Inline, required file, optional file, environment.
2. **Layers:** Defaults $\rightarrow$ base $\rightarrow$ profile $\rightarrow$ env.
3. **Paths:** Validated against Sandbox, RelativeOnly, or BlockForbidden policies.
4. **Validation:** Invariant rules with error or fatal severities.

---

## 🔍 Verification & Conformance

`star-toml` includes a built-in verifier that checks for active counterexamples (such as directory traversals, unknown fields accepted in trusted mode, and validation errors without paths) to ensure the release has absolute conformance.

Run the verifier report:
```bash
cargo run --bin verifier_report
```

Run DfCM examples (demonstrative):
```bash
cargo run --example basic_admitted_config
cargo run --example layered_profiles
cargo run --example env_overrides
cargo run --example strict_unknown_fields
cargo run --example path_policy_sandbox
cargo run --example witness_and_q_config
cargo run --example ocel_lifecycle_export
```

Run DfCM combinatorial integration tests (assertive — panic on violation):
```bash
cargo run --example dfcm_validation_matrix   # all 12 Validator checks × pass/fail + analytics
cargo run --example dfcm_error_variants      # all 5 Error variants produced and matched
cargo run --example dfcm_merge_semantics     # 7 layer-merge invariants asserted
```