Skip to content

Sinter v1.2.0

Choose a tag to compare

@hagix9 hagix9 released this 06 Oct 11:06
· 15 commits to main since this release

Sinter v1.2.0

Highlights

A new-capability release: local account management, encrypted secrets, and fewer remote commands per run on some targets. Recipes, command lines and --format json documents that do not use the new features are unchanged: the additions are new resource types, a new command group (sinter secrets), new optional fields, and internal changes to how a run observes the target.

  • group and user resources for local Linux accounts. Only declared dimensions are managed and audited. Accounts are observed with getent -s files; an account that only another identity source provides is an error, never a create. Every command is a fixed executable with explicit arguments, never a shell. An existing account is never renumbered or renamed, its home is never moved, and supplementary group membership is never removed (a uid/gid mismatch is refused in plan and apply and reported as drift by audit). state: absent runs userdel/groupdel without -r/-f: the home directory and mail spool are kept. Removal is refused for root, the account the run executes as, and a group that is some user's primary group.
  • Encrypted secrets (age). sinter secrets encrypt | decrypt | list work on secret files in the standard age format (recipients or a terminal-entered passphrase). decrypt writes plaintext to standard output only and refuses a terminal. Passphrases are never taken from argv, the environment or standard input.
  • file.content: { secret: <path> }. A file resource can take its bytes from an encrypted secret. A resource that holds a secret is always sensitive (redacted diff, 0600 default, redacted report text). validate never decrypts. MCP manifest tools refuse secret references.
  • user.password_hash: { secret: <path> }. Sets a local user's password from a pre-generated $y$ (yescrypt) or $6$ (sha512crypt) hash kept as an encrypted secret; $y$ is refused on RHEL-family 9. The hash is applied with sudo -n chpasswd -e over standard input, never argv, and only on a mismatch. --sudo is required. There is no plaintext password field.
  • sinter secrets list --recipe FILE (repeatable) adds which of the recipes you name reference each listed secret, and still never decrypts, prompts or looks for an identity.
  • Fewer remote commands per run in two situations. Output, --format json documents and the safety checks are unchanged, apart from one refusal message noted below.
    • Repeated lookups of the same owner, group or primary group within one run on one target are answered once and reused where the safety contract allows; any command, file, directory, link or account change clears them. Lookups for sensitive resources are never reused, and only a numeric id is kept.
    • On targets without getfacl (in pre-release testing on real hosts: Ubuntu 24.04 and 26.04, and Rocky Linux, RHEL and AlmaLinux 10), the trusted-parent check before a write batches stat for all ancestor directories into one command and, only if every ancestor passes, getfattr into one command, instead of separate commands per ancestor. Every check is a fresh observation. Targets that have getfacl (Rocky Linux, RHEL and AlmaLinux 9) keep the per-ancestor check, unchanged.
    • Example, measured on real hosts without getfacl with a pre-release build: applying three resources (a new file, a new directory and a replaced file) under a seven-directory path took 149–150 remote commands before and 65–66 after; the trusted-parent checks alone went from 98 to 14 commands. These are command counts, not timings.
    • For a missing ancestor directory, the refusal message on the batched path says that stat failed and a parent directory may be missing or inaccessible, instead of naming the missing ancestor; the operation is refused either way.
    • Remote commands are also counted internally for tests and measurement (program name, resource-type label, duration and outcome; never arguments, environment, input or output); the counts are never printed or sent anywhere.
  • New dependencies: age 0.12.1 (exact pin; standard age format only, no plugins) and zeroize, with their transitive crates.

See CHANGELOG.md for the complete entry.

Supported platforms

Linux x86_64: Ubuntu 24.04 / 26.04 LTS, Rocky Linux 9 / 10, RHEL 9 / 10, AlmaLinux 9 / 10 — one artifact for all of them.

Acceptance-tested point releases for this artifact: Ubuntu 24.04.5 LTS, Ubuntu 26.04.1 LTS, Rocky Linux 9.8, Rocky Linux 10.2, RHEL 9.8, RHEL 10.2, AlmaLinux 9.8, AlmaLinux 10.2. Other point releases have not each been independently accepted.

Downloads

  • sinter-v1.2.0-linux-x86_64.tar.gz and SHA256SUMS
  • Acceptance evidence: sinter-v1.2.0-acceptance-manifest.json, sinter-v1.2.0-acceptance-evidence.tar.gz, sinter-v1.2.0-acceptance-SHA256SUMS
sha256sum -c SHA256SUMS
sha256sum -c sinter-v1.2.0-acceptance-SHA256SUMS

Validation

  • Linux x86_64 validation gate on Ubuntu 24.04 in strict mode (a missing test prerequisite fails instead of skipping): formatting, lints and all tests passed — 1307 root tests including the Linux-only suites and the real-sshd SSH suites, 18 installer tests, 82 checker tests, 198 gateway tests; 0 failed, 0 skipped.
  • Acceptance: the same artifact (SHA-256 03c36256c36709d148ae2739bae5ce3fe8e7f798b110fd1e17215729906b0363) passed on all eight targets — 1240 checks passed, 0 failed (155 per target). Each target ran the established single-host acceptance suite and a real-host group → user → directory → file lifecycle (create, converge, update, drift and audit, refusals, removal), 103 checks per target, using only synthetic test accounts and no passwords or secrets.
  • The secrets features (sinter secrets, file.content: { secret }, user.password_hash, secrets list --recipe) were accepted on all eight targets on 2026-10-04 on a pre-release build, not on this release artifact. The user.password_hash path was not re-run on this artifact.
  • The remote-command reductions above were measured on pre-release builds; the acceptance run of this artifact did not measure command counts or timings.
  • Verify the evidence with release/check_acceptance_manifest.py from the tagged source (see release/ACCEPTANCE_EVIDENCE.md).

Known limitations

  • Linux x86_64 only; Oracle Linux is recognized but not part of the acceptance matrix.
  • group and user manage local accounts only (/etc/passwd, /etc/group); accounts that only another identity source provides are not managed. Removal keeps the home directory and mail spool.
  • plan does not simulate the removal of a user earlier in the same recipe: a recipe that removes a user together with that user's primary group has the group removal refused at plan time, although apply removes them in dependency order.
  • user.password_hash requires --sudo, and $y$ hashes are refused on RHEL-family 9.
  • The per-target release acceptance scenarios are single-host; multi-host behavior is covered by the Linux gate test suites (including throwaway local sshd hosts).
  • The systemd manager synchronization (introduced in v1.1.3) covers the system manager only and is local to one run.
  • A server that offers only legacy SSH algorithms cannot be managed; there is no override (unchanged since v1.1.2).
  • Package resources do not pin versions.
  • On DNF targets, a package change is refused (fail-closed, nothing is installed) while the dnf package cache still holds downloaded packages left behind by an interrupted transaction; dnf clean packages clears them. This behavior is unchanged from earlier releases.