v0.45.2

thevoiceguy/siphon-aiv0.45.2Jul 27, 2026by github-actions[bot]

Upgrading?

AI Summary

Fixes CSeq reuse for inbound legs and removes unimplemented hangup cause documentation.

Key Highlights

  • Fixed inbound legs no longer reusing `CSeq 1` for every in-dialog request.
  • Removed unimplemented `hangup` cause mapping from PROTOCOL.md documentation.

Full Release Notes

### Fixed

- **Inbound legs no longer reuse `CSeq 1` for every in-dialog request — bot-initiated hold can be resumed again** (issue #377). The daemon-wide transfer UAC — which drives an inbound call's hold/resume re-INVITEs as well as its REFER — was built without a `DialogManager`, so it got a private one. Each in-dialog send advances the dialog's local CSeq and re-inserts the dialog into *that* UAC's store, while the per-call lookup (`DialogSource::Managed`) reads the **UAS's** store, which never saw the advance: every request re-resolved the answer-time snapshot and went out as `CSeq 1`. The first request was fine, so plain hold and plain teardown always worked; the second collided. In practice `hold` → `resume` left the caller **stuck on hold** — the carrier read the repeated CSeq as a retransmission and never sent a final response, the transaction died at Timer B (~32 s) with `error { code: "hold_failed" }`, and the call ran on until the RTP-inactivity watchdog killed it (~60 s, CDR `tap_ended`); `hold` → teardown drew a **`408` thirty seconds later**, stalling teardown and inflating the CDR. This is the inbound half of #353's frozen-snapshot bug reached by a different route — that fix gave outbound legs a shared advancing dialog and left this side alone, because the shared-store assumption encoded in `DialogSource::commit`'s doc comment looked sound. `build_transfer_uac` now shares the UAS's store, exactly as `build_outbound_uac` has since #324, and `BridgingAcceptor::install_transfer` **asserts** the UAC it is handed was built over the store it is handed — a silent mis-wiring that only surfaces as a wrong CSeq on a second request now fails loudly at daemon start. Verified live over a Twilio trunk before and after.

### Documentation

- **PROTOCOL.md §4.3 no longer promises a `hangup` `cause` → SIP response mapping that has never existed** (issue #376). The spec documented `rejected` → `603 Decline`, `busy` → `486 Busy Here`, `not_acceptable` → `488 Not Acceptable Here`, and `normal` → "BYE, or 487 on an early dialog". None of it is implemented, and two independent things stand in the way: the controller's `Hangup` arm reads `cause` only to log it and always tears down with BYE, and — more fundamentally — **a WS session only ever exists on an answered call**, since the SIP `200 OK` is sent before the WebSocket is opened and `start` is delivered, so there is no moment at which a server could decline a call that hasn't been answered. Confirmed on a live trunk at the theoretical limit: a server sending `hangup { cause: "rejected" }` **1 ms after `start`** still produced INVITE → 200 OK → BYE with no 603 anywhere, a 90 ms CDR, and a call the carrier billed as connected. The mapping appears to have been written for a deferred-answer design (`BridgeIn::Answer`, still noted in CONFIG.md as targeted for 0.2.1/0.3.0) that never shipped. §4.3 now states plainly that every `hangup` is a BYE, carries an explicit warning for call-screening servers (with the routing/trunk/admission alternatives that *do* work), and points at #376 for pre-answer rejection. The `HangupCause` doc comments and the generated schema descriptions say the same, so SDK authors reading the machine-readable contract get the truth too. No wire behavior changed and the cause values stay accepted, so adding real pre-answer rejection later remains additive.

---

**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.45.2` (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