Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
54 changes: 36 additions & 18 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -9,9 +9,42 @@ Versioning: [Semantic Versioning](https://semver.org/spec/v2.0.0.html).

## [Unreleased]

## [2.26.0] - 2026-10-04

Minor release: the Verbara.Sdk `2.7.0` / Verbara.Sdk.Pro `2.17.1-pro` cascade, with the queue-call
ownership behaviour it brings; idle `Available` agents keep receiving queue calls; and message history
is readable again on PostgreSQL. There is no database migration.

### Upgrading from 2.25.x

- **AMI read class `agent`.** Queued calls now get an owner only when the queue reports that a member
took the call, which arrives on the AMI `agent` class. The bundled
`docker/asterisk-config/manager.conf.template` already grants it. If Platform connects to your own
Asterisk with its own AMI user, add `agent` to that user's `read =` line in `manager.conf` and
reload the manager (`manager reload`), or queue calls stay without an owner.

### Known issues

- **Compose start-up order leaves Asterisk's `queue_members` column cache empty** when Asterisk starts
before the API has run its migrations (#333). Running `module reload app_queue.so` in the Asterisk
container after the API is up refreshes the cache.

### Fixed

- **Message history can be read again on PostgreSQL.** Every read of a stored message failed with a server error (500). Postgres stores message content as `jsonb`, which reorders the keys of each block, and the reader required the block's type to come first. The bug was latent since message storage first shipped (1.2.0). It broke `GET /api/v1/conversations/{id}/messages`, `GET /api/v1/supervisor/conversations/{id}/messages`, typification suggestions, the GDPR export, the conversation summary report, delivery-status webhooks, de-duplication of redelivered inbound messages and email thread matching. The in-memory store was not affected. No migration is needed: rows already stored are read correctly after the upgrade.
- **Message history can be read again on PostgreSQL.** Every read of a stored message failed with a server error (500). Postgres stores message content as `jsonb`, which reorders the keys of each block, and the reader required the block's type to come first. The bug was latent since message storage first shipped (1.2.0). It broke `GET /api/v1/conversations/{id}/messages`, `GET /api/v1/supervisor/conversations/{id}/messages`, typification suggestions, the GDPR export, the conversation summary report, delivery-status webhooks, de-duplication of redelivered inbound messages and email thread matching. The in-memory store was not affected. No migration is needed: rows already stored are read correctly after the upgrade. (#337)
- **An idle `Available` agent no longer stops receiving queue calls after a minute.** Every 60 s the
realtime reconciliation (and every queue-membership save) re-wrote the agent's Asterisk Realtime
`queue_members` rows with `paused = 1`, so `app_queue` skipped an agent the console still showed as
`Available` until the agent changed state by hand, and callers waited while a free agent sat idle.
Verbara.Sdk.Pro `2.17.1-pro` now keeps an existing row's `paused` value on re-upsert, and Platform
re-asserts the agent's real pause state after every member upsert it issues (reconcile pass and
membership save): it re-reads the agent under the same per-agent lock the state bridge uses and
pauses only a non-routable agent (`Available` and `Busy` are routable) or one with a pending pause.
This also unpauses a member created, or re-created after orphan cleanup, for an agent who is
already `Available`. Rows already stuck at `paused = 1` are corrected by the first reconcile after
the upgrade. **Known limitation:** the per-agent lock is per process. With several API replicas,
one pod's reconcile can still briefly race another pod's state change; the next state change or
reconcile re-asserts the correct value. A cross-pod lock is a separate change. (#338)

### Dependencies

Expand Down Expand Up @@ -42,29 +75,14 @@ Versioning: [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
overload and the `StateChanged` event — to the primary connection. The interface gives them default
bodies, so the wrapper compiled clean while answering `false`, dropping the outcome and raising
nothing; four tests now lock the forwarding. Platform does not call any of them yet.
- **`Scalar.AspNetCore` `2.17.10` → `2.17.11`** (Dependabot, #322).
- **Deliberately out of scope** (`Verbara.Sdk/ADR-0040` D4): `Microsoft.Extensions.TimeProvider.Testing`
stays at `10.10.0`, and neither `OpenTelemetry` itself nor `NATS.Client.Core` gains a direct pin.
The second hop, Sdk `2.8.0` (H142), is a separate change. decision_ref `Verbara.Sdk/ADR-0040`.
- **Verbara.Sdk.Pro `2.17.0-pro` → `2.17.1-pro`** — all 22 `Verbara.Sdk.Pro.*` pins move together
(Pro packages depend on their siblings at the same version, so a partial bump risks `NU1605`).
A patch with no API change: the `queue_members` upsert stops overwriting `paused` on conflict (see
*Fixed*). (#N)

### Fixed

- **An idle `Available` agent no longer stops receiving queue calls after a minute.** Every 60 s the
realtime reconciliation (and every queue-membership save) re-wrote the agent's Asterisk Realtime
`queue_members` rows with `paused = 1`, so `app_queue` skipped an agent the console still showed as
`Available` until the agent changed state by hand, and callers waited while a free agent sat idle.
Verbara.Sdk.Pro `2.17.1-pro` now keeps an existing row's `paused` value on re-upsert, and Platform
re-asserts the agent's real pause state after every member upsert it issues (reconcile pass and
membership save): it re-reads the agent under the same per-agent lock the state bridge uses and
pauses only a non-routable agent (`Available` and `Busy` are routable) or one with a pending pause.
This also unpauses a member created, or re-created after orphan cleanup, for an agent who is
already `Available`. Rows already stuck at `paused = 1` are corrected by the first reconcile after
the upgrade. **Known limitation:** the per-agent lock is per process. With several API replicas,
one pod's reconcile can still briefly race another pod's state change; the next state change or
reconcile re-asserts the correct value. A cross-pod lock is a separate change. (#N)
*Fixed*). (#338)

---

Expand Down
2 changes: 1 addition & 1 deletion Directory.Build.props
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@
<RepositoryType>git</RepositoryType>
<RepositoryUrl>https://github.com/verbara/verbara-platform</RepositoryUrl>
<PackageTags>verbara;platform;contact-center;omnichannel;native-aot</PackageTags>
<PackageVersion>2.25.0</PackageVersion>
<PackageVersion>2.26.0</PackageVersion>
</PropertyGroup>

<PropertyGroup Condition="$(MSBuildProjectDirectory.Contains('src'))">
Expand Down
Loading