v/1.12.0
Платформа
-
Агрегирующие запросы к коллекциям (параметр aggr): добавлена функция count_distinct — количество различных значений в группе, например уникальных сущностей по дням.
-
Статические файлы веб-сервера (справка, админка, ресурсы ролевых приложений) поддерживают HTTP Range: работает перемотка аудио и видео.
-
Исправлены HEAD-запросы к REST: публичные ресурсы отвечали 401, /public/version — 405.
-
SIP по WebSocket (ws/wss): поддержан CRLF-keepalive; раньше соединение закрывалось.
-
SIP по WebSocket (ws/wss) и мобильные устройства:
-
закрытие прежнего соединения устройства, переподключившегося с тем же +sip.instance и reg-id, больше не снимает его новую регистрацию;
-
SG проверяет подключения WebSocket ping (параметр роли sg ws_ping_interval, по умолчанию 25 секунд): устройство, пропавшее без разрыва соединения, снимается за 50—75 секунд вместо трех минут;
-
вызов на потерянное подключение сразу уходит на другое подключение устройства, а без него вызывающий получает 480 вместо 503 (для переадресации — условие
dnd); -
резервный вызов устройства с несколькими подключениями начинается через 2 секунды и при одинаковом Contact; раньше — 408 через 30 секунд;
-
устройство, переподключившееся во время входящего звонка, получает отмену вызова в новое подключение, а UPDATE без SDP отвечается 481, если вызов уже отменен;
-
мобильное приложение с push-уведомлениями, чье подключение живо, но не отвечает: через 2 секунды устройство будится push-уведомлением и получает вызов через новое подключение; раньше — 408 через 30 секунд;
-
отказ пользователя (486, 6xx) на одном подключении устройства сразу завершает вызов на этом устройстве; другие устройства пользователя продолжают звонить.
-
-
BYE вызывающего до ответа (после 180/183) отменяет вызов так же, как CANCEL; раньше — 481, и вызов продолжался.
-
ESG: запросы внутри диалога до ACK ставятся в очередь, как в B2B, и последовательно обрабатываются при завершении всех подготовительных состояний.
-
Подписки мастер-домена на класс событий callevents или confevents (либо отдельное событие класса) с objects any получают события всех доменов платформы: слушатель всех событий телефонии через websocket Token-API. Подписка мастер-домена на эти классы с объектами отклоняется.
-
SG, ESG, redirect и WS начинают принимать запросы на адресах из настроек sip_ifaces, http_ifaces, https_ifaces, появившихся на сервере после запуска роли, в течение 30 секунд; раньше требовался перезапуск узла.
-
Компоненты сценариев «Синтез речи (Yandex Cloud SpeechKit)» и «Распознавание речи (Yandex Cloud SpeechKit)» переведены на API v3 (gRPC). Распознавание выполняется потоково по мере записи, синтез воспроизводится, не дожидаясь окончания. Добавлены новые голоса и амплуа синтеза, громкость, высота голоса, кэширование; для распознавания — нормализация и литературное оформление текста, режим одной фразы, настройки определения конца фразы, текст без нормализации в отдельную переменную. Настройки существующих сценариев применяются без изменений: голос Alyss заменяется на Dasha, неподдерживаемые голосом эмоции не передаются, темы maps, dates, names, numbers заменяются на general. В настройке домена yandex_cloud адреса сервисов задаются полями grpc_tts, grpc_stt; поля uri_tts, uri_asr_short больше не используются.
-
Медиашлюз: доработан механизм переключения отправки на другой сокет при смене входящего потока.
-
Внешние хосты веб-сервера (ws/ExternalRoutedHosts): режим archive_referers записи или маршрута сохраняет переходы клиентов (IP, URL, utm-метки, Referer, User-Agent) в новую коллекцию ws/ArchiveReferers. По умолчанию выключен.
-
Проксирование внешних хостов веб-сервера (ws/ExternalRoutedHosts): исправлена передача cookie; cookie и токен сессии платформы на сервер назначения не передаются.
-
Бот администраторов заменяет Telegram-бот мониторинга:
-
работает в Telegram, MAX и VK через учетные записи мессенджеров мастер-домена; используются только мессенджеры с проверкой подлинности входящих сообщений;
-
администратор подключает чат одноразовым кодом, подтверждая его в приложении администрирования; пароль в мессенджер не передается;
-
каждый администратор может исключить разделы состояния системы из уведомлений и выбрать язык сообщений (команда /lang);
-
файл состояния отправляется при появлении и изменении проблем, при неизменных проблемах — напоминание; время ежедневного отчета настраивается;
-
команды с параметрами можно выбирать из меню мессенджера;
-
бот и подключенные администраторы прежнего Telegram-бота переносятся автоматически, в том числе с версий до 1.10; параметры system_telegram_bot и telegram_bot_token заменены на admin_imi_options.
-
-
Каналы мессенджеров (uc/imchannels) доступны и в мастер-домене.
-
Сообщения мессенджеров (im/Messages): опции отправки sendOptions (disable_notification, parse_mode) учитываются в Telegram.
-
Исправлено: классы служебных коллекций system/audit/RestrictedLogons, system/licensing/Indicators и telephony/ArchiveDialogs пересоздавались при изменении классов домена и при запуске серверов.
-
Коллекции с хранением transactionlog (Kafka + ClickHouse):
-
дата-время хранится в UTC с миллисекундами, как в PostgreSQL; чтение и фильтры по интервалу не зависят от часового пояса сервера ClickHouse. Таблицы, созданные ранее, преобразуются при загрузке класса: поле партиции сохраняет точность до секунды;
-
незаданные поля типов uuid и enum возвращаются отсутствующими, а не нулевым идентификатором и пустой строкой;
-
логин и пароль ClickHouse передаются в заголовках запроса: пароль может содержать любые символы.
-
-
Секреты в настройках домена шифруются при сохранении и не возвращаются в открытом виде: ключи и секреты yandex_cloud, sber_salute, azure_cloud (в том числе в accounts) и серверов record_asr_options, пароль в project_postgresql_connstr. Ранее сохраненные значения шифруются при следующем изменении настройки. Сценарии, читающие эти значения через системные переменные domain.settings, получают их в зашифрованном виде: параметры подключения сценарий задает самостоятельно.
-
Хранилища типа s3 (/rest/v1/domain/storages): секретный ключ secretKey шифруется при сохранении и не возвращается в открытом виде; ранее сохраненные ключи шифруются при следующем изменении хранилища.
-
Сборка trn-логов и диаграмма последовательности звонка (/api/monitor/v1/trace):
-
доступны и после очистки кэша связей (около 3 часов): связи звонка берутся из журналов callid микросервисов (глубина — параметр days), уже удаленные с нод журналы — из logstore при свободных ресурсах (параметр logstore);
-
порядок стрелок соответствует порядку событий: ответ не показывается раньше запроса, расхождение часов микросервисов учитывается;
-
сборка меньше нагружает микросервисы; параметр time (время звонка) сокращает ее еще.
-
-
Состояние системы: сравнение файлов платформы на серверах (version_files_diffs, version_all_files_diffs, уровни 1–3) выполняется за доли секунды вместо десятков секунд — сравниваются размер и время изменения файлов, каталоги резервных копий и сборки не учитываются; на односерверной системе сравнение не выполняется.
-
Кодеки в SDP инициируемых вызовов (параметр payloads_audio_offer ролей b2b, conf, esg, ivr, prompt, sg, а также payloads_video_offer) предлагаются в порядке списка; базовые PCMU, PCMA и telephone-event, не указанные в списке, добавляются после указанных. Префикс
-исключает кодек из добавляемых (-— все неуказанные базовые),--— также из SDP входящего вызова, передаваемого на другое плечо (с--— в порядке списка). CN и telephone-event размещаются в конце. Подробнее — статья Кодеки и согласование медиа. -
У провайдера (opts.payloads_audio) telephone-event можно исключить:
-telephone-event/8000или-*. -
Список кодеков провайдера (opts.payloads_audio) применяется только на плече провайдера: внутренние плечи им не ограничиваются (при необходимости транскодинг), предложение внутрь платформы содержит кодеки провайдера из списка в порядке провайдера. Без списка при reinvite = 0 предложение провайдера передается внутрь с его кодеками, без дополнения по payloads_audio_offer esg. Если в SDP провайдера (в том числе в re-INVITE и INVITE с Replaces) нет кодека из списка или нет ни одного известного платформе кодека, esg отвечает 488 Not Acceptable Here вместо 415.
-
Исправлено: esg при reinvite = 0 отвечал на re-INVITE и INVITE с Replaces кодеками, которых не было в предложении. Теперь ответ содержит только кодеки предложения, при отсутствии общих — 488 Not Acceptable Here (re-INVITE отклоняется без разрыва вызова).
-
Исправлено: при пересылке re-INVITE через esg без транскодинга в предложении и ответе оставались кодеки, убранные новым предложением.
-
Имена кодеков в параметрах и у провайдера указываются без учета регистра.
-
Ответ SDP содержит динамические форматы (например, telephone-event) под номерами из предложения (RFC 3264). Если стороны вызова объявили для одного кодека разные номера, медиашлюз сопоставляет их по имени кодека.
-
Провайдер:
G723/8000в opts.payloads_audio не поддерживается — при добавлении ошибка, ранее сохраненное значение отбрасывается. -
Серверы записи: при заданном
audio_formatsпредлагаются ровно указанные кодеки в порядке списка. -
BREAKING CHANGE. Если payloads_audio_offer не задан (у любой роли, в том числе esg и sg), G729 больше не предлагается: добавьте
G729/8000в параметр, если он нужен. Порядок кодеков в SDP может измениться: теперь он определяется порядком в конфигурации, а не прежним постоянным порядком платформы (например,[PCMA, PCMU, G722, CN]дает PCMA первым вместо PCMU). -
Служебные задачи (service/svctasks): поля dtstart и dtstop необязательны — незаданное значение не ограничивает период активности. Регулярная задача без них выполняется по расписанию, однократная — сразу после включения. Раньше подставлялось текущее время, и задача, созданная без этих полей, не запускалась. Даты существующих задач не меняются.
-
Исправлено: подстановка
{A}в модификаторе отображаемого имени SIP-пользователя (displayname контакта адресной книги по номеру) всегда давала пустую строку. -
Исправлено: синхронизация данных между системами (ETL, режим выживания) не переносила контакты адресной книги.
-
Сервис телефонных оповещений (alertcall) снова включён. Изменения оповещений применяются сразу по уведомлениям, без постоянного опроса; исправлено сохранение статуса и статистики оповещения (запись отклонялась).
Рефакторинг
-
Подключен статический анализатор кода, позволивший обнаружить и устранить ряд замечаний:
-
BREAKING CHANGE. Агрегирующая функция join (параметр aggr) теперь принимает разделитель первым аргументом, как функция общего назначения join и как указано в справке:
["join",", ",["property","name"]]. Запросы с прежним порядком аргументов нужно исправить. В PostgreSQL-коллекциях join соединяет и нестроковые значения. -
BREAKING CHANGE. Имя класса динамической модели данных при создании и переименовании должно содержать раздел (section/name); имена без раздела зарезервированы за статической моделью. Существующие классы не затрагиваются.
-
BREAKING CHANGE. REST домена (/rest/v1/domain/domains): поле solution больше не возвращается и не принимается; удалён /rest/v1/domain/solutions.
-
BREAKING CHANGE. Правила IAM с режимом authenticated снова требуют аутентификации: REST-запрос без сессии к таким маршрутам получает 401.
-
BREAKING CHANGE. Событие приложения веб-конструктора по websocket (send_app_event) проверяет роли пользователя так же, как HTTP-доступ к приложению; без подходящей роли — ошибка «Invalid app name. Role mismatch».
-
BREAKING CHANGE. Функции даты в сценариях (year, month, day, hour, minute, second, millisecond, dayofyear, dayofweek, weekofyear, tick, datetimeutc, datetimelocal, localtoutc, utctolocal) при невалидной дате завершают выполнение ошибкой «Invalid datetime» вместо подстановки 2000-01-01; valid_date для невалидной даты возвращает false. Явно записанная дата 1970-01-01 с нулевым временем валидна.
-
BREAKING CHANGE. Вложенность eval в сценариях ограничена 16 уровнями (ошибка «eval: nesting is too deep»).
-
BREAKING CHANGE. Копирование сценария («Сохранить как» и ext.copied_from): принимается только идентификатор существующего сценария того же типа.
-
BREAKING CHANGE. SIP-пользователь без регистрации (reg=false): число устройств (devices) при создании и изменении не может превышать установленное для него значение lic.devices (проверка раньше не срабатывала). Сохранённые объекты загружаются как прежде.
-
BREAKING CHANGE. Неявный вызов из конференции в конференцию блокируется (проверка раньше не срабатывала).
-
BREAKING CHANGE. Получение почты по IMAP: параметр ssl учитывается (по умолчанию true; порт 993 — всегда TLS); раньше соединение всегда устанавливалось через TLS.
-
B2B: INFO без DTMF пересылается на другую сторону как SIP INFO (было 408).
-
ESG: исправлена передача X-Era-Extaccount с urlencode для значений, позволяющей избегать спецсимволов в коде провайдеров.
-
Добавлены операции info и message в /rest/v1/uc/sipusers/<id>/device; в справке описаны resync, event, headers, content.
-
Подписка (BLF) на внешние номера из настройки blf_external_numbers и chief_mobile комплекта руководителя работает; раньше отклонялась.
-
Обнаружены и исправлены несколько уязвимостей при работе с файлами через API авторизованных пользователей: временные файлы websocket-сессии (имена файла и подкаталога ограничены папкой сессии); файловые API (выход за пределы каталога через
..и символические ссылки); системный API приложений ролей (обход url_mask дважды закодированными сегментами). -
Исправлено удаление папки в файловом хранилище (REST fs): без заданного корня могли удаляться пустые каталоги выше корня.
-
Исправлены ответы API, которые давали 500 или обрыв: список сессий при неответившем домене; запрос коллекции DC по полю для пустой коллекции; остановка сценария при недоступном узле сценариев; rest по websocket с classpath не коллекции; на неизвестную команду привязок и переключение конференции в недопустимом состоянии — ошибка сразу, а не таймаут.
-
Вход через служебный сценарий аутентификации (по паролю или токену) работает при любой форме результата сценария; раньше в части случаев вход завершался внутренней ошибкой.
-
Вызов серверной части приложения полки (служебного сценария приложения) через HTTP /api/roleapp/v1/<appkey> работает; раньше запрос всегда завершался ошибкой.
-
Исправлена доставка части событий по websocket-подпискам и подписка на события модели (modelevents) с коротким путём класса.
-
Функции сценариев dc_read и dc_find по полю id находят объекты и тех классов, где ключ записи не id (пользователи, группы, роли и т.п.); раньше возвращался пустой результат.
-
Установка и обновление продукта не прерываются ошибкой, если какой-либо объект домена обновился с предупреждениями.
-
Проксирование websocket учитывает порт из адреса назначения host:port.
-
SIP: исправлены уведомления о присутствии (PIDF), в том числе для BLF телефонов Cisco (cpim-pidf+xml); REGISTER без Contact через SG получает 200; SUBSCRIBE с Expires 1..29 — 423 Interval Too Brief; на внешнее направление — ошибка маршрута вместо 500.
-
B2B: исправлены reinvite и завершение диалога при ошибке миграции медиа; недоступный доменный центр не обрывает звонок при проверке переадресаций; REFER продолжает маршрутизацию при недоступном удалённом B2BUA; INVITE+Replaces на внешнее направление при ошибке маршрута возвращает 403.
-
ESG: сценарий нормализации без переменных или прерванный не задерживает вызов на 10 с; исправлен биллинг RADIUS при сервере без порта.
-
SG, взаимная супервизия экземпляров (режим reregister): при падении экземпляра SG зарегистрированным через него устройствам снова отправляется команда на внеплановую перерегистрацию; раньше после сбоя служебного процесса режим мог перестать работать до перезапуска узла.
-
IVR: исправлены Replaces в состоянии ringing и до ответа (заменённый INVITE отвечается 487); несовпадение режима медиа при REFER возвращается в сценарий как operation_failed.
-
Музыка на удержании: при отсутствующем или неверном music_on_hold играет мелодия по умолчанию.
-
Ошибки создания каталогов, копирования и удаления файлов (хранилище NFS, микшер, временные файлы) больше не выдаются за успех: например, при сбое копирования записи разговора её скачивание возвращает ошибку, а не пустой файл.
-
Сценарии: исправлены компоненты сценариев в части толерантности к некорректным значениям, влекущим прерывание работы компонента и завершение сценария.
-
Сценарии: компонент LDAP теперь поддерживает многострочные фильтры и not(…), компонент получения почты декодирует заголовки =?charset?…?=.
-
Исправлено скачивание файла из свойств типа filelink в multi=true в коллекциях динамической модели данных.
-
Запросы к коллекции динамической модели данных, пришедшие во время загрузки ее класса, выполняются после загрузки; раньше при нескольких таких запросах часть завершалась по таймауту.
-
Диаграмма звонка по логам версий до 1.9.7: сообщение без адреса не делает диаграмму ошибочной.
-
Журнал диалогов (СОРМ3/ArchiveDialogs): событиям ставится реальная дата вместо 1970-01-01.
-
Kafka для generic-событий: работают режимы разбиения по партициям random и random_by_key.
-
ACME для автоматической генерации сертификатов: неудачная подготовка повторяется через 10 с; исправлено восстановление сертификатов из резервной копии.
-
Сервис распределения учетных записей провайдеров телефонии по экземплярам ESG теперь учитывает конфигурационную опцию excludedomains ESG.
-
Резервный режим (survival): исправлена проверка токена при нескольких адресах.
-
Событие CCS connection_failure содержит sipcode и reason.
-
Голосовая почта: исправлена отметка сообщения прослушанным через REST.
-
Голосовая почта: ночная очистка больше не падает на пустом каталоге, ранее писала в лог.
-
Получение почты по IMAP: закрытие соединения почтовым сервером не роняет компонент сценария, ранее была способна обрушить сценарий.
-
Исправлен выбор ведущего сайта в межсайтовом кворуме при разделении сети.
-
Исправлена уязвимость редактора сценариев: операции с вложенными файлами сценария принимают только имя файла, без пути.
-
Событие statesevents.user_state_changed доставляется в подписки (веб-хуки, websocket, Kafka) корректным JSON с полем presence; раньше приходило как invalid_data.
-
Веб-хуки: подписка с объектами вида {"type": "sipuser", "sipuser": "sip1"} снова фильтрует события (с 1.11.0 события по таким подпискам не приходили), поддержаны также типы other, conf, provider, user; подписка на modelevents через веб-хуки отклоняется — для них используется websocket; в ответе GET поле expires — оставшееся время подписки в секундах.
-
Websocket: ответы с ошибкой, содержащей детали (например, неверный пароль при login), снова приходят с кодом и error_details (с 1.11.0 возвращалась внутренняя ошибка 1501).
-
Websocket: login по ненайденной или истёкшей сессии (sessionid, rsessionid) без логина и пароля возвращает ошибку «Session not found or expired.» (msg_code 10025) вместо требования домена.
-
Подписки веб-хуков (/rest/v1/service/webhooks): expires больше 86400 уменьшается до 86400; применённое значение возвращается в ответе в поле expires и определяет срок продления.
-
Подписки на события модели: строковая маска (exargs.mask) совместно с политикой безопасности класса не приводит к ошибке подписки; формат веб-хуков ext.http_notify_format применяется и для /api/token/v1/<token>/subscribe, неизвестное значение формата — JSON-тело.
-
Коллекции динамической модели с хранением ets: новые классы снова запускаются (с 1.10.5 класс не загружался, запросы получали «DataModel server is not loaded»); постраничное snapshot-чтение возвращает страницы в порядке сортировки и не смешивает выборки с разными фильтрами.
-