v0.42.0
thevoiceguy/siphon-aiv0.42.0Jul 25, 2026by github-actions[bot]
Upgrading?
Release notes summary
Fixes SRTP replay warnings during SSRC changes, corrects CDR transfer handling, and resolves NOTIFY acceptance issues following REFER transfers.
Key Highlights
- SRTP no longer logs false 'replay attack detected' warnings when the peer's RTCP SSRC changes (upstream fix).
- CDR now records a transfer as `termination.cause = 'transfer'` (schema v6).
- Post-REFER NOTIFYs are now accepted with `200 OK` instead of `405 Method Not Allowed`.
- New metric `siphon_ai_notify_total` tracks NOTIFY results.
Full Release Notes
### Fixed
- **SRTP calls no longer log false "SRTCP replay attack detected" warnings when the peer's RTCP SSRC changes** (fixed upstream by [forge-media#98](https://github.com/thevoiceguy/forge-media/pull/98), pin bumped `6e3fcd2e7c6f` → `003b5e1be563`). The SRTP receive context kept a **single** SRTCP replay window keyed only by the SRTCP index, but RFC 3711 §3.4 replay protection is **per-SSRC** — each SSRC has its own index space. When the inbound RTCP SSRC changed mid-call (Twilio does this transitioning from ringback/early media to the answered stream), the new SSRC's fresh low indices were rejected by the shared window as replays until they climbed past the old SSRC's high-water mark: spurious `SRTCP unprotect failed … replay attack detected` WARNs on normal secure-trunk calls, false positives in `forge_srtcp_replay_attacks_blocked_total`, and dropped RTCP reports (feeding the RTT/quality stats) during the changeover. The SRTCP sibling of the per-SSRC RTP-stats fix (#94, shipped in 0.40.0's pin). Upstream replaces the shared window with a per-SSRC `ReplayWindow` map, creates/advances a window **only after successful authentication** (forged packets can't grow the map or advance any window), and keeps genuine per-SSRC replays blocked — regression-tested upstream (`test_srtcp_replay_window_is_per_ssrc`, red before the fix). No siphon-ai code change; no API change.
- **CDR now records a transfer as `termination.cause = "transfer"`** (issue #356; **CDR schema v5 → v6**). When the WS server transferred a call away (`transfer` → the peer accepted the REFER), the WS emitted `stop { reason: "transfer" }` but the CDR recorded `termination.cause = "local_shutdown"` — so the billing-grade, durable record couldn't tell a hand-off from an admin force-hangup, a CANCEL, or an RFC 4028 session-expiry. This is the same WS-vs-CDR divergence that #332 fixed for `caller_hangup`. New `Transfer` variant on `CallTermination` / the CDR `TerminationCause` (serialises `"transfer"`, matching the WS `stop` reason); the controller now sets it on a successful REFER instead of `LocalShutdown`. Additive for parsers that treat `termination.cause` as an open string, but the schema `version` bumps to 6 so a consumer that exhaustively matches the v5 cause set can gate on it. Verified live: the transfer that recorded `local_shutdown` before now records `transfer`.
- **Post-REFER NOTIFYs are now accepted with `200 OK` instead of `405 Method Not Allowed`** (issue #357). After a transfer REFER is accepted, the peer reports transfer progress on the implicit refer subscription (`NOTIFY Event: refer`, RFC 3515 §2.4.4). SiphonAI answered it `405` — contradicting `docs/PROTOCOL.md` §4.4, which promised those NOTIFYs are "accepted". The transfer itself was unaffected (the REFER+BYE pattern never consumes the subscription), but a progress-tracking peer saw a spurious `405`, and the doc was wrong about the wire behavior. `RoutingHandler` now answers NOTIFY itself: `Event: refer` → `200 OK` (dropped, not surfaced over the WS; deliberately dialog-blind, since the NOTIFY normally arrives after our BYE tore the dialog down); an unsupported event package → `489 Bad Event` + `Allow-Events: refer` (RFC 6665); no `Event` header → `400`. NOTIFY is now advertised in `Allow` (405/OPTIONS responses), keeping RFC 3261 §20.5 honest. New counter `siphon_ai_notify_total{result=accepted|bad_event|bad_request}`. This supersedes #358's interim doc-only resolution of the same issue (which documented the 405): PROTOCOL.md §4.4 now promises — and the daemon delivers — the `200 OK`. No siphon-rs change — the `on_notify` hook already existed.
---
**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.42.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
A cross-platform desktop All-in-One assistant for Claude Code, Codex, OpenCode, OpenClaw, Grok Build & Hermes Agent. Only official website: ccswitch.io
An open-source remote desktop application designed for self-hosting, as an alternative to TeamViewer.
Build smaller, faster, and more secure desktop and mobile applications with a web frontend.
π RuView turns commodity WiFi signals into real-time spatial intelligence, vital sign monitoring, and presence detection — all without a single pixel of video.
Incredibly fast JavaScript runtime, bundler, test runner, and package manager – all in one