v0.24.0

thevoiceguy/siphon-aiv0.24.0Jul 8, 2026by github-actions[bot]

Upgrading?

AI Summary

Adds encryption at rest for recordings using AES-256-GCM envelopes and introduces a CLI tool for decrypting recordings.

Key Highlights

  • Recordings encrypted at rest using `.wava` envelopes with AES-256-GCM.
  • New `siphon-ai decrypt-recording` CLI tool.
  • Renaming behavior changed: recordings appear as `.part` during capture.
  • KEK rotation does not require re-encrypting audio.

New Features

  • Recording encryption at rest
  • CLI decryption tool
  • Renaming to `.part` during capture

Full Release Notes

### Added

- **Recording encryption at rest — `[recording.encryption]`** (P1 "Recording
  compliance & storage", first sub-item; design note
  `docs/design/DESIGN_RECORDING_COMPLIANCE.md`). With `enabled = true`, a
  `kek` (64 hex chars, referenced via `${file:}`/`${cred:}`) and a `key_id`,
  recordings are written as encrypted **`.wava` envelopes** instead of
  plaintext WAV — nothing plaintext ever touches disk. Envelope encryption:
  a fresh random 256-bit data key per recording seals the audio in
  independent AES-256-GCM chunks; the data key travels in the file header,
  wrapped by your KEK. The header names the `key_id` that wrapped it, so
  **rotating the KEK never re-encrypts audio**. Config is validated
  fail-loud at startup; a runtime wrap failure fails the *recording*
  (`recording_failed`), never the call. The CDR gains an additive
  `recording_encrypted` flag (schema version unchanged). Decrypt offline
  with the new **`siphon-ai decrypt-recording <file> --kek-file <hex>`**
  subcommand — needs no daemon config; a wrong key names the `key_id` the
  recording requires; `--allow-unfinalized` recovers a crashed capture. The
  `SAIWAVA1` container format is documented in `docs/RECORDING.md` §8 for
  third-party implementations. **Off by default.** Deps: `aes-gcm` +
  `zeroize` promoted from transitive to direct (RustCrypto; no new vendor).

### Changed

- **Recordings now appear as `<name>.part` while in progress** and are
  renamed to their final `.wav`/`.wava` name only when finalized — for
  *plaintext* recordings too. A bare `.wav` on disk is now always a
  complete file (safe for a watcher/uploader to pick up), and a daemon
  crash leaves only a `.part` instead of a WAV with placeholder header
  sizes. **If you watch the recording directory, match the final names and
  ignore `*.part`.**

---

**Artifacts**

- Static musl binaries for `x86_64` and `aarch64` (`.tar.gz`).
- Debian packages (`.deb`) for `amd64` and `arm64` — `apt install ./siphon-ai_*_amd64.deb`.
- `SHA256SUMS` — verify with `sha256sum -c SHA256SUMS`.
- `*-sbom.cdx.json` — CycloneDX SBOM.
- `SHA256SUMS.cosign.bundle` — cosign keyless signature over the checksums.
- Container: `ghcr.io/thevoiceguy/siphon-ai:v0.24.0` (multi-arch, cosign-signed).

Verify the checksums signature:
```
cosign verify-blob --bundle SHA256SUMS.cosign.bundle \
  --certificate-oidc-issuer https://token.actions.githubusercontent.com \
  --certificate-identity-regexp 'release.yml@' SHA256SUMS
```

Related Repositories