diff --git a/CHANGELOG.md b/CHANGELOG.md index 7f9c610e..5e7e9aad 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -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 @@ -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) --- diff --git a/Directory.Build.props b/Directory.Build.props index dec39c38..2ab69c80 100644 --- a/Directory.Build.props +++ b/Directory.Build.props @@ -26,7 +26,7 @@ git https://github.com/verbara/verbara-platform verbara;platform;contact-center;omnichannel;native-aot - 2.25.0 + 2.26.0