# Changelog
All notable changes to this project will be documented in this file.
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/),
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
## [0.12.0] - 2026-05-27
### Added
- **`make test-vendor` target** to verify that vendored dependencies produce a
working build without network access (`cargo build/test --frozen --config`).
- **Class mappings in PyO3 API.** The `ext_pillar()`, `top()`, and `load()`
functions now accept `class_mappings` (list of pattern strings) and
`class_mappings_match_path` (boolean) keyword arguments, matching the
Python reclass adapter interface.
- **Salt adapter contrib modules.** Pure-Python shim files for Salt's
`ext_pillar` and `master_tops` interfaces, shipped as reference files in
`/usr/share/ferroclass/contrib/`. Users copy or symlink them into Salt's
`extension_modules` directory.
### Changed
- **Vendored sources configuration redesigned.** The committed
`.cargo/config.toml` no longer contains the `crates-io` → `vendored-sources`
replacement. Regular `cargo build` and `cargo test` use crates.io directly
without requiring a vendor step. Vendored builds use
`.cargo/config.vendor.toml` (generated by `make vendor`, gitignored) via
`cargo --config`. The vendor tarball for RPM builds contains a merged
`.cargo/config.toml` with both build flags and vendored source
configuration.
- **`make build` no longer depends on `make vendor`.** Building from the
working tree now uses crates.io dependencies directly, eliminating the
mandatory vendor step for development builds.
- **`make release` target reordered.** The git tag is now created before
the tarballs (`tag` before `dist`), fixing the chicken-and-egg bug where
`dist` checked for a tag that hadn't been created yet.
- **`make rpm-release` target reordered.** The RPM tag is created before
the tarballs for consistency with the `release` target.
- **`make vendor` now saves `.cargo/config.vendor.toml`.** In addition to
populating the `vendor/` directory, the target saves the Cargo vendor
config so `make test-vendor` can use it.
### Fixed
- **`.cargo/config.toml` no longer forces vendored sources.** The previous
config broke `cargo build`, `cargo test`, and `cargo publish` when the
`vendor/` directory didn't exist (which is gitignored). Source tarballs
are now usable standalone without vendor dependencies.
- **`cargo publish` no longer requires `--registry crates-io` workaround.**
Since the committed config no longer replaces the crates-io source,
publishing works with the standard `cargo publish` command.
### Removed
- **Vendored source replacement removed from committed `.cargo/config.toml`.**
The `[source.crates-io]` and `[source.vendored-sources]` sections are no
longer in the committed file. They are generated at build time when
vendoring is needed.
## [0.11.1] - 2026-05-26
### Added
- **PyO3 Python bindings** (`python` feature gate). Compile the Rust library
as a native Python extension module (`cdylib`) using PyO3 0.23. Provides
`ferroclass` Python package with `ext_pillar()`, `top()`, and `load()`
functions for Salt integration and direct inventory access.
- **`python3-ferroclass` RPM subpackage** (SUSE only, maturin-built wheel).
Other distros can opt in with `--with python_subpackage`.
- **`ferroclass-salt-adapter` RPM subpackage** (noarch). Installs Salt adapter
reference files to `/usr/share/ferroclass/contrib/`.
- **`make wheel`, `make pip-install`, and `make publish-pypi` targets** for
Python wheel building and PyPI publication via maturin.
- **`pyproject.toml`** for maturin-based Python wheel builds.
### Changed
- **RPM build simplified.** Removed `cargo-rpm-macros` / `rust-packaging`
BuildRequires; removed `%cargo_prep`. The spec uses plain
`cargo build --release --frozen` commands instead of RPM cargo macros.
- **Debug packages disabled** (`%define debug_package %{nil}`). Cargo
release builds strip by default, and the Rust binary and Python `.so`
would collide on the same debuginfo package name.
### Fixed
- **`python-bytecode-inconsistent-mtime` rpmlint warning** fixed by using
`pip install --no-compile` so RPM's `brp-python-bytecompile` produces
consistent `.pyc` files.
## [0.11.0] - 2026-05-21
### Added
- **API documentation.** Added module-level (`//!`) and item-level (`///`) doc
comments across all public modules: `inventory`, `output`, `configuration`,
`storage`, `cli`, and their sub-modules. Core types (`Inventory`, `Value`,
`Key`, `Error` enums, output adapters) are fully documented.
- **Added `make doc` and `make docclean` targets** to the Makefile.
- **Added `documentation = "https://docs.rs/ferroclass"`** to `Cargo.toml`.
### Changed
- **Tightened public API surface.** Internal implementation modules
(`applications`, `interpolation`, `inv_query`, `merge`, `value_merge`,
`configuration_file`, `parser`) are now `pub(crate)` instead of `pub`. Selective
re-exports (`MergeError`, `ValueMergeError`, `merge_values`) are available
from the `inventory` module.
- **Added crate-root re-exports.** The most commonly used types are now
accessible directly from `ferroclass::` (e.g., `ferroclass::Inventory`,
`ferroclass::load`, `ferroclass::Options`, `ferroclass::StorageOptions`).
- **`docclean` Makefile target** now removes the entire `target/doc/` directory.
### Removed
- **Public access to internal modules removed.** Code that referenced
`ferroclass::inventory::value_merge::merge` should use
`ferroclass::inventory::merge_values` instead. Code that referenced
`ferroclass::inventory::merge::Error` should use
`ferroclass::inventory::MergeError` instead. This is a breaking change.
## [0.10.1] - 2026-05-19
### Changed
- **Improved error messages.** Eliminated pass-through error layers using
`#[snafu(transparent)]` so `caused by:` chains are shorter, clearer, and free
of redundant entries like "interpolation error" and "merge error". Error
messages follow the funnel principle: each line adds exactly one new fact.
- Added `docs/conventions.md` documenting error handling design rules, snafu
patterns, source chain discipline, and transparent variant usage.
- Updated `AGENTS.md` and `CONTRIBUTING.md` to reference `docs/conventions.md`.
## [0.10.0] - 2026-05-18
### Changed
- **Renamed binaries to avoid conflicts with Python reclass.** The installed
binaries are now `ferroclass`, `ferroclass-ansible`, and `ferroclass-salt`
(previously `reclass`, `reclass-ansible`, `reclass-salt`). This allows
ferroclass to coexist alongside the Python reclass package on the same
system without file conflicts on `/usr/bin/reclass*`. RPM sub-packages are
also renamed: `ferroclass-ansible` and `ferroclass-salt`.
- Added `GH_REMOTE` Makefile variable (default: `github`) for configuring
the git remote name used by the `tag` target.
## [0.9.0] - 2026-05-16
First public release. Feature-complete reimplementation of Python reclass
([salt-formulas/reclass](https://github.com/salt-formulas/reclass)) with 100% CLI
compatibility for the `reclass`, `reclass-ansible`, and `reclass-salt` commands.
### Added
- Full class inheritance with depth-first resolution
- Parameter interpolation (`${...}` references, nested references)
- Inventory queries (`$[...]` syntax: VALUE, TEST, LIST_TEST)
- Two-pass rendering pipeline for cross-node references
- Override prefix (`~key`) for replacing values instead of merging
- Constant prefix (`=key`) for locking values against later changes
- Class name interpolation with `${...}` in the classes list
- Relative class names (`.` and `..` prefix)
- Class mappings (glob/regex patterns matching node names)
- Environment support (default `base`, per-node environment)
- Exports with interpolation and inventory query resolution
- Applications list with `~` negation prefix
- `compose_node_name` for subdirectory-based node names
- `ignore_class_notfound` with regexp filtering
- `ignore_overwritten_missing_reference`
- `inventory_ignore_failed_node` / `inventory_ignore_failed_render`
- `group_errors` for error summarization
- Output formats: YAML and JSON (with pretty-print and sort options)
- Ansible dynamic inventory adapter (`--list` / `--host`)
- Salt external node classifier adapter (`--top` / `--pillar` / `--out`)
- Man pages for all three commands
- RPM packaging (SUSE and RHEL conditional macros)
### Known Incompatibilities
See [README.md](README.md#reclass-compatibility) for the full list.