# SOW v0.7.0

> SOW 0.7.0 adds flat RPM pruning and password-file signing, fixes recovery and publication defects, and preserves workspace formats.

---

LLMS index: [llms.txt](/llms.txt)

---

**v0\.7\.0 · 2026-11-09**
- [View release](https://github.com/pgsty/sow/releases/tag/v0.7.0)
- [Source · tar\.gz](https://github.com/pgsty/sow/archive/refs/tags/v0.7.0.tar.gz)
- [Source · zip](https://github.com/pgsty/sow/archive/refs/tags/v0.7.0.zip)
- [pgsty\/sow](https://github.com/pgsty/sow)

SOW 0.7.0 adds **flat RPM pruning** and a shared **password-file signing interface**. It also fixes defects in migration, recovery, publication, RPM signature verification, and version ordering found during the release review.

**Availability:** SOW 0.7.0 is available on [GitHub](https://github.com/pgsty/sow/releases/tag/v0.7.0) and the [Download page](/download/).

These notes cover the changes since **0.6.1**. Database schema **v13**, configuration schema **sow/v3**, and the public repository layout stay unchanged. Workspaces on 0.5.0 through 0.6.1 need no schema migration.

## Prune old RPM versions

`sow prune DIR` keeps the highest Epoch/Version/Release for each package name and architecture, publishes the filtered index, then deletes older RPMs.

```bash
sow prune /srv/candidate --dry-run --protect age_18 --protect age_18-llvmjit
sow prune /srv/candidate --protect age_18 --protect age_18-llvmjit
```

- `--dry-run` validates and previews without writes. Each repeatable `--protect NAME` preserves all versions of an exact package name and must match a package.
- `--metadata-timestamp SECONDS` sets the index publication time, with the same default of `0` as `create`.
- Replacement packages must pass embedded digest checks. SOW binds the verified and indexed bytes to a stable file identity, including change time, and checks it before every deletion and before completion. An in-place rewrite with restored size and mtime stops further deletion.
- You can resume an interrupted cleanup by rerunning `sow prune`. SOW refreshes an existing `repo_complete` marker only after successful completion. Errors report completed changes, and SOW does not restore already deleted packages.

Prune works on top-level regular binary RPMs in a local publication source. It rejects managed workspaces, DEB packages or indexes, package symlinks, source RPMs, equal EVRs within a name/architecture group, RPM v6 packages, signed `repomd.xml`, and independent metadata that SOW cannot generate. It does not sign packages. Clients with cached old indexes may still need the old RPMs: account for that before publishing a pruned repository.

See the [prune command reference](/docs/command/prune/).

## Sign with password files

Use `--passfile PATH`, `SOW_GPG_PASSFILE`, or a per-key `passfile` in `sow.yml` for protected RPM package keys and RPM/APT metadata keys, including GPG agent keys.

```bash
sow create ./packages --sign-with 0123456789ABCDEF --passfile /run/secrets/gpg-password
```

The priority is CLI, per-key configuration (including a legacy `passphrase` reference), then environment. The file contains one nonempty UTF-8 line, at most 64 KiB. SOW removes one final LF or CRLF without trimming spaces or tabs. Use a literal path, not `file://`. Relative CLI/environment paths use the current directory; configured paths use the workspace root. SOW searches no default file.

The interface also covers signing preflight, initialization, migration, leaf export, and recovery of interrupted operations. Credentials do not enter process arguments, repository state, or public files. Password files must be regular files with no symlinks in the path. Keep them outside the repository with private access permissions. Legacy metadata `passphrase` references remain supported.

See the [password-file contract](/docs/reference/config/#passfile), including command coverage and external GPG requirements.

## RPM compatibility

- **ECDSA and EdDSA signatures:** accept these header signatures in RPM's tag 267 (`RPMSIGTAG_DSA`), where modern RPM stores them. Real Ed25519 and ECDSA packages now verify; SOW still rejects a mismatched RSA signature in that tag.
- **Caret ordering:** fix Version and Release comparisons so a snapshot such as `2.0^20250611` sorts before `2.0.1`. Managed version limits consequently retain the newer release.
- **Foreign metadata:** `create` keeps its existing behavior of replacing `repomd.xml` without groups, updateinfo, modules, or unknown records that SOW does not generate. This preserves compatibility with legacy Pigsty repositories, including the modules generated by Pigsty v4.4.0 on EL8/9. Human output now warns about dropped types; JSON output adds `dropped_metadata` when nonempty. SOW does not maintain the external metadata files or signatures themselves.
- **Prune metadata guard:** prune rejects those independent records before mutation and rechecks before publication. Prune allows SQLite and zchunk encodings of the package indexes. Prune also rejects an old index larger than the 16 MiB inspection limit. Create can still replace oversized or malformed indexes, but cannot report types it could not inspect.

If clients need the extra metadata, continue maintaining it with the appropriate generator. Refresh external `repomd.xml.asc` signatures after rebuilding.

## Managed repositories and recovery

- **Migrated repositories remain writable.** A completed C2 migration retains the identity of the Generation it created. Later builds no longer cause `check`, `build`, `add`, or `gc` to reject that migration anchor, and `repo rm` no longer mistakes a completed migration for an active transition. Affected repositories recover after upgrading without manual database repair.
- **Protect every published pointer.** The withdrawal guard now checks the complete published Generation, including views unchanged by the latest publication. SOW rejects removing a Dist, architecture, or signing companion while a configured target still publishes it. Retire that target binding first, or publish under a new target name and prefix. Retired public files remain available for you to remove separately; ordinary publication does not withdraw them automatically.
- **Unrelated offline targets no longer block operations.** Publication, abort, and target GC compare the selected target against prospective paths of other targets. SOW still rejects actual physical path overlap.
- **Recover interrupted plan writes.** SOW can discard empty, partial, or hash-invalid GC plans in the planned phase before any deletion. It can rebuild retained-removal plans while the original target still exists. Contradictory state after destructive work remains an error.
- **Export carried-forward Dists.** `export rpm-leaf` accepts a clean Dist that a later Generation did not rebuild, with or without signing.
- **Tolerate a backward clock step.** Mutation recovery identifies the sole active operation by its ID instead of choosing by wall-clock order.

## Dependencies and release checks

| Component | 0.6.1 | 0.7.0 |
|---|---|---|
| AWS SDK core / S3 | 1.47.3 / 1.114.4 | 1.47.8 / 1.114.9 |
| Smithy | 1.28.6 | 1.28.8 |
| SQLite / libc | 1.61.0 / 1.79.0 | 1.62.0 / 1.80.1 |
| Debian package parser | 0.21.1 | 0.21.3 |
| YAML | `go.yaml.in/yaml/v3` 3.0.5 | `go.yaml.in/yaml/v4` 4.0.0 |
| GoReleaser | 2.18.3 | 2.20.0 |
{.wide .expand}

Go **1.27.3** remains the build baseline. YAML retains strict single-document validation and canonical configuration output. This release updates the bounded local RPM parser patch and third-party notices with the dependency changes.

Integration now requires protected-key signing tests on **EL8, EL9, and EL10**. The EL8 test detects whether `rpmsign --rpmv3` exists and skips only the unsupported repeated-signature case. Release gates cover unit and race tests, APT/DNF clients, S3-compatible publication, static analysis, vulnerability reachability, reproducible clean-source builds, and archive/RPM/DEB contents. Hosted R2 live testing is optional and was not run for this review; macOS amd64 was cross-built on the arm64 review host.

## Upgrade

Stop writers, back up the complete workspace while preserving hard links, install 0.7.0, then run these commands for each configured Repository:

```bash
sow version
sow build -r REPOSITORY -C /srv/sow
sow check -r REPOSITORY -C /srv/sow
```

An unchanged build is a no-op. Workspaces from 0.3 or 0.4 still need `sow repo migrate REPOSITORY` first. Plain repositories have no database migration.

SOW 0.6.1 and older cannot load a configuration that contains `passfile`; remove those fields before downgrading. The no-symlink rule for password files remains in force. SOW does not support RPM v6.

The release produces Linux and macOS archives for `amd64` and `arm64`, two RPMs, two DEBs, and `SHA256SUMS`. See the [installation guide](/docs/start/install/#upgrade-to-070) and [all changes since 0.6.1](https://github.com/pgsty/sow/compare/v0.6.1...v0.7.0).

### `.rpm`

| File | Checksum |
| --- | --- |
| [sow\-0\.7\.0\-1PGSTY\.aarch64\.rpm](https://github.com/pgsty/sow/releases/download/v0.7.0/sow-0.7.0-1PGSTY.aarch64.rpm) | SHA-256 · `ea62ad17c62c39c606c2c942d6f0b0acbfb1d0788df71d872746b653753fefdf` |
| [sow\-0\.7\.0\-1PGSTY\.x86\_64\.rpm](https://github.com/pgsty/sow/releases/download/v0.7.0/sow-0.7.0-1PGSTY.x86_64.rpm) | SHA-256 · `3111afe9857fc44d22a63072ab520d47cd96df4074b632f255c4087030833055` |

### `.deb`

| File | Checksum |
| --- | --- |
| [sow\_0\.7\.0\-1PGSTY\_amd64\.deb](https://github.com/pgsty/sow/releases/download/v0.7.0/sow_0.7.0-1PGSTY_amd64.deb) | SHA-256 · `9e579c560b0564bd45481f5d205cfa76edadcb1eedd6e787bd845ed5aba5425f` |
| [sow\_0\.7\.0\-1PGSTY\_arm64\.deb](https://github.com/pgsty/sow/releases/download/v0.7.0/sow_0.7.0-1PGSTY_arm64.deb) | SHA-256 · `4384d343890e84dec8f917c5f8d6a8612bc98af28b55aec96000f1ea9d2bb59b` |

### `.tar.gz`

| File | Checksum |
| --- | --- |
| [sow\_0\.7\.0\_darwin\_amd64\.tar\.gz](https://github.com/pgsty/sow/releases/download/v0.7.0/sow_0.7.0_darwin_amd64.tar.gz) | SHA-256 · `21f276d940b44264be67ac1b020e50004ec9e77292f12061b880093175f01af1` |
| [sow\_0\.7\.0\_darwin\_arm64\.tar\.gz](https://github.com/pgsty/sow/releases/download/v0.7.0/sow_0.7.0_darwin_arm64.tar.gz) | SHA-256 · `bd4232eec5d329a51ed2db8f58d43341c30875e8693278b4c5d10c946d814433` |
| [sow\_0\.7\.0\_linux\_amd64\.tar\.gz](https://github.com/pgsty/sow/releases/download/v0.7.0/sow_0.7.0_linux_amd64.tar.gz) | SHA-256 · `4ad5c1faa853f3e295abab3b1c070b1e9d2c337af3afcbca7384808c3c3df291` |
| [sow\_0\.7\.0\_linux\_arm64\.tar\.gz](https://github.com/pgsty/sow/releases/download/v0.7.0/sow_0.7.0_linux_arm64.tar.gz) | SHA-256 · `9453c84501406a0a31044120c9b26ef0eb4865bf45c0d204efd043cf650b323c` |
