Журнал изменений
Что нового.
Каждое усовершенствование платформы, как только она появится.
· kamo-marketing
Add Flowroute to INTEGRATED WITH banner
· kamo-internal
Show accurate provider connection status from isConnected field
Replaces the old logic that showed "Connected" for any provider with no sync error (including brand-new providers that were never tested). New three-state badge driven by isConnected (null/true/false): - null / never tested → grey "Not tested" (HelpOutlineIcon) - false → red "Not connected" (ErrorOutlineIcon) - true + sync error → amber "Sync error" (WarningAmberIcon) - true → green "Connected" (CheckCircleIcon) - RingCentral no OAuth → amber "Needs reauth" (unchanged)
· VOIPService
Persist connection test result to isConnected field
- test() endpoint saves isConnected=true/false to DB after every health check - update() resets isConnected to null when configJson changes (credentials may have changed, requiring a re-test before showing Connected) - toDto() exposes isConnected so the frontend can distinguish: never tested / connected / not connected
· kamo-shared-library
Add isConnected field to VoipProviderInstance
Nullable Boolean: null = never tested, true = last test passed, false = failed. Requires KamoInitializerService schema migration to add IS_CONNECTED column.
· kamo-marketing
Показать баннер с активным предложением с живым обратным отсчетом миллисекунд
Получает активную сторону сервера продвижения на главной странице и отображает HeroOfferBanner между подзаголовком и бесплатным вызовом. Баннер показывает сумму скидки, продолжительность и обратный отсчет в реальном времени **************** на 50 мс с анимированным Граница с градиентным сиянием и мерцание. ничего не делать, если нет активных Существует незавершенное продвижение.
· kamo-internal
Доступный/недоступный переключатель для бэкэнда и исправление ошибки присутствия OFFLINE
Переименовать приостановленный/активный чип в доступный/недоступный в NavTop Получите начальную доступность на монтировке и сохраняйте переключатели через новый API me/availability Добавить доступное поле в интерфейс Member и реквизит MemberItem - MemberList Pass доступен из ответов отдела на MemberItem - MemberItem показывает ONLINE/OFFLINE/UNAVAILABLE этикетку оранжевого цвета Исправьте ошибку OFFLINE: добавьте изменение видимости сердцебиения и периодическое повторное извлечение 120s
· SecurityService
Добавить доступно для ответов отдела и меня / конечных точек доступности
· InitializerService
Backfill available = Правда для существующих пользователей
· kamo-shared-library
Добавить доступное поле для переключения доступности членов
· kamo-internal
Удалить вкладку Access & Domains и компонент DomainManager
· kamo-marketing
Live unread badge + отказ от нового сообщения агента
- поддерживает LiveSupportPanel вне экрана, в то время как виджет сведен к минимуму (только при наличии сеанса поддержки), поэтому подписка STOMP остается Живые и на UnreadMessage зажигаются для входящих сообщений агента, даже если Посетитель не смотрит на чат. - Оживляет значок весенней шкалой на каждое изменение счета (ключевой трюк) переустанавливает элемент) плюс непрерывное пинг-кольцо Tailwind 0. - Отскакивает и наклоняет минимизированную вкладку, когда счет идет вверх, Он краснеет от свечения, поэтому привлекает внимание со всей страницы. - handleExpand уже очищает счет на открытом, поэтому никаких изменений не требуется Вот.
· MediaService
Трансляция в ожидании счета + непрочитанный агент читать и посетитель отправить
**************** теперь делегаты ************************************* отражает сеансы с непрочитанными сообщениями посетителей и сокращениями, когда Агент вызывает MarkAsRead. - Новый общественный помощник. **************** теперь (а) перераспространяет агентов непрочитанная полезная нагрузка после последних просмотренных авансов и (b) вызовов Помощник, чтобы навигатор SupportButton оставался синхронизированным, не дожидаясь Следующий опрос 60-х. - **************** также вызывает помощника, чтобы Ноутбуки живут, когда посетитель отправляет. Подсчет навигатора теперь соответствует штату значка per-row сразу же После клика и после обновления браузера.
· kamo-shared-library
Нечитанный счет + помощник по поиску по сессии
Добавлено **************** Так что навигатор Значок SupportButton может считать билеты поддержки, которые действительно нужны внимание (непрочитанные сообщения посетителей) вместо PRE TICKET/NEW статус. График читается прямо из DB, чтобы он пережил обновление. Также добавляет ****************, так что MediaService Вы можете решить проблему с помощью GUID сеанса после MarkAsRead.
· KlusterServices
Добавить медиа в список резервирования поддоменов
· kamo-internal
Добавить медиа-поддомен в необходимые псевдонимы DNS
· kamo-internal
Добавить столбец местоположения в дейтагрид билета
Читать **************************** прямо с SupportTicketDTO (сейчас снимок на билете) Время создания — никаких дополнительных поездок туда и обратно. Флаг + город/регион/страна с IP, показанным в подсказке; возвращается к em-dash, когда нет геоданных Он на билете. Вид только на агента. TicketHeader уже потребляет те же поля DTO, поэтому всплывающий инструмент Окно теперь также показывает снимок - без GeoLite или чтения с гостевого стола на рендере.
· kamo-shared-library
Снимок гео посетителя на билете
Добавлены VISITOR IP ADDRESS, VISITOR COUNTRY CODE, VISITOR COUNTRY NAME, VISITOR CITY, VISITOR SUBDIVISION колонки. Запечатлено при создании билетов Таким образом, конечные точки списка / детали никогда не должны сканировать диапазон GeoLite. Отдельный просмотр посетителей в режиме чтения. KamoInitializerService (hibernate.ddl-auto: обновление) столбцы при следующем запуске; существующие строки возвращаются к записи посетителя хранимый код страны в ToDTO.
· MediaService
Добавить /ws/public-chat-native точку WebSocket вместе с SockJS
Регистрация второй конечной точки STOMP без SockJS в /ws / public-chat-native что интерфейс может подключаться к нативному WebSocket (brokerURL) без необходимости библиотека sockjs-клиента, которая регистрирует обработчик разгрузки, нарушающий Политика разрешений сайта. Оригинальная конечная точка /ws / public-chat SockJS сохранена обратной совместимости.
· kamo-internal
Per-ticket unread badge + фильтр «Только новые сообщения»
- Список билетов показывает значок чат-пузырь с непрочитанным счетом рядом Билет # всякий раз, когда на сеансе есть сообщения новее, чем у агента Последнее просмотренное сообщение. - Добавляет переключатель фильтра «Только новые сообщения» в панель фильтра. TicketChat теперь звонит **************** При этом, когда наступает срок, и когда наступает срок, наступает срок. Агент читает разговор. Ответы на изменения в библиотеке, которые расширяются FindChatMembershipsByMemberId включает в себя сессии SUPPORT TICKET, а также Медиасервис транслируется в ****************
· MediaService
Трансляция непрочитанного сообщения агенту в сообщении посетителя
После того, как посетитель отправит сообщение поддержки, нажмите последние непрочитанные счета. Полезная нагрузка ******************* так агент билет-лист Обновление бейджа и счетчика навтопов в режиме реального времени. Зеркала транслируются в MediaController.sendСообщение для чатов между участниками.
· kamo-shared-library
Включите сессии SUPPORT TICKET в непрочитанный запрос на членство
findChatMembershipsByMemberId теперь возвращает членство как для CHAT, так и для CHAT. Типы сеансов SUPPORT TICKET, так что существующий на члена непрочитанный счет инфраструктура (getUnreadCountsByMember, /topic/chat/unread/{memberId} Трансляции, GET **************** автоматически покрывает Билеты поддержки тоже. Позволяет агентам видеть показатели нового сообщения в билете в списке билетов и суммарный непрочитанный значок в навтопе.
· KlusterServices
Производство провалилось2ban с тюрьмами PJSIP и постоянным состоянием
Добавить fail2ban-configmap.yaml с [asterisk] и [freepbx-web] тюрем, постепенная эскалация запрета (1h→24h→30d потолок), LAN ignoreip и пользовательский фильтр asterisk.conf, нацеленный на записи PJSIP SecurityEvent - Mount fail2ban-config ConfigMap и hostPath/var/lib/pbx/fail2ban (ban) состояние сохраняется при перезапуске стручков) как в развертывании k1m1, так и в развертывании k2m1 - Конфигурация проводов в Startup.sh до запуска fail2ban-клиента на обоих узлах
· kamo-shared-library
Add resetHasAttachmentsForFolder query to ConversationRepository
Allows sync to reset stale has_attachments flags before re-indexing so corrected MIME detection can rebuild the field from actual attachment data.
· KlusterServices
Integrate Coqui TTS with norman voice (VCTK p267)
- Deploy coqui-tts server (VCTK VITS model, CPU-only) as ClusterIP service on port 5002 with model cache at /var/lib/coqui-tts on k1m1 - Inject coqui_tts.agi into /var/lib/asterisk/agi-bin on each boot: calls HTTP API, caches 8 kHz mono WAV under sounds/coqui-tts/, streams via AGI STREAM FILE — use AGI(coqui_tts.agi,text) in any dialplan context - Write say.conf on each boot to route all Asterisk built-in say functions (digits, numbers, dates, times) through Coqui TTS
· KlusterServices
Add LAN DNS pod for split-DNS on k1m1
Deploys a dnsmasq pod with hostNetwork on k1m1 that listens on 192.168.4.22:53. Overrides pbx.k1.kluster.kamocrm.com -> 192.168.4.22 so LAN phones reach the PBX directly without NAT hairpin. All other queries are forwarded to 8.8.8.8/8.8.4.4. Router DHCP must be pointed to 192.168.4.22 as the primary DNS server for LAN clients to pick this up.
· kamo-internal
Закладки конфигурации платформы (General / VOIP & SMS / System User / Advanced)
Обертки **************** в SettingsView с четырьмя вкладками: Общий: обзор платформы только для чтения - общие организации, активный телефон-сервер Количество экземпляров, активное количество экземпляров SMS-провайдера, последняя глобальная синхронизация VOIP временная метка. Читать далее **************** VOIP и SMS: редактировать VoipSyncIntervalMinutes (1..1440) и VoipSyncEnabled Поверхность последней кнопки GlobalVoipSyncAt плюс кнопка «Run global sync now». Вызовы SecurityService → VOIPService /internal/voip/sync-global. Пользователь системы: существующий пользовательский интерфейс System User Access, снятый с Конфигурация Клиента дословно в компонент вкладки (без изменения поведения). - Продвинутая: параллельная кнопка «Trigger global VOIP sync now» для ops, плюс Явное сообщение о пустом состоянии для будущего контроля. ConfigurationClient теперь тонкий оркестратор вкладок. Использовать PlatformAdminGuard Остается на месте на уровне оркестранта, поэтому все четыре вкладки закрыты.
· DaemonService
Глобальная синхронизация VOIP (Admin-tunable interval)
VoipGlobalSyncJob тикает каждую минуту и на каждом клеще читает SystemConfiguration Singleton решает, нужна ли глобальная синхронизация: Если voipSyncEnabled является ложным, пропустите. - Если последний GlobalVoipSyncAt + voipSyncIntervalMinutes > сейчас → пропустите. - В противном случае: POST/internal/voip/sync-global для VOIPService Заголовок InternalAuthFilter; последнее обновление GlobalVoipSyncAt на успех. Это позволяет операторам платформы регулировать каденцию во время выполнения из **************************** VOIP и SMS без перезапуска DaemonService Прикосновение к выражениям cron. Зарегистрирована в QuartzConfig наряду с существующими рабочими местами. k8s/configmap.yaml добавляет клещ cron (1-минутный по умолчанию) и kamo.services.voip.base-url + Внутренний.auth.secret для аутентификации исходящего HTTP-вызова.
· SecurityService
Конечные точки System-config + Platform-overview
Поверхность конфигурации всей платформы, закрытая существующим владельцем верхнего уровня Защита (соответствует шаблону SystemUserConfigController’s requireTopLevelOwner). Конечные точки: - GET/api/security/system-config - возвращает однотонный ряд - PUT/api/security/system-config - обновление voipSyncIntervalMinutes/ voipSyncEnabled. Частичные обновления Поддерживается; валидация обеспечивает интервал 1..1440 минут. - GET/api/security/platform-overview - агрегированная статистика (общие организации, активный телефон/SMS экземпляр, Последняя синхронизация, текущая Интервал + включенный флаг. - POST **************** Вызовы VOIPService /internal/voip/sync-global через InternalAuthFilter auth secret) чтобы операторы платформы могли запустить глобальную синхронизацию VOIP по требованию Новая конфигурация платформы → вкладка VOIP & SMS / расширенная вкладка. Конфиг: - kamo.services.voip.base-url (по умолчанию к VOIPService кластерно-локальный сервис URL). Повторное использование существующего внутреннего.auth.secret.
· VOIPService
Контроллеры ресурсов на уровне одной организации + агрегатная система организации + внутренняя синхронизация
Per-instance ресурс CRUD (расширения / пользователи / устройства / голосовая почта): - VoipExtensionsКонтроллер на **************** Контроллер на /api/voip/instances/{id}/users - VoipDevicesКонтроллер на **************** - VoipVoicemailКонтроллер на **************** - Каждый GET принимает ?refresh=true для принудительной доставки от поставщика и обновления кэша; в противном случае служит из локального кэша для быстрого пользовательского интерфейса. Каждый путь записи вызывает провайдера и обновляет локальный кэш так, чтобы агрегировать Взгляды остаются последовательными, не дожидаясь следующей запланированной синхронизации. - Voicemail GET /{vmId}/audio передает необработанный звук от поставщика через StreamingResponseBody позволяет пользовательскому интерфейсу <audio src=...> Агрегированный орган (VoipOrgAggregateController at /api/voip/org): - /расширения, /пользователи, /устройства, /voicemails возвращают строки в каждом экземпляре с таблетками {instanceId, exampleName}. UI превращает их в агрегированные вкладки в /settings/features/phone. - /health run checkHealth() на каждом активном экземпляре (через кэш-счета InstanceSyncService), возвращает InstanceHealthDto. - POST/sync запускает InstanceSyncService против каждого активного экземпляра Текущая организация. В пользовательском интерфейсе есть кнопка «Sync this org now». Внутренняя синхронизация (VoipInternalSyncController): - POST/internal/voip/sync-global петли всех активных экземпляров по всей платформе. Называется по расписанию работы DaemonService в Кварце. Защищены существующими Внутренний фильтр в VOIPService. Строит зеленый.
· VOIPService
Multi-instance provider refactor + full FreePBX + Flowroute SMS
Core model change: one org → many VoipProviderInstances (was: one per org). Every provider API call is now instance-scoped. PhoneProvider interface: - New methods for extension/user/device CRUD + voicemail audio/transcription. - New capability flags (extensionManagement, userManagement, deviceManagement, voicemailTranscription). Defaults throw **************** (HTTP 501) so stub providers don't break. Frontend checks getCapabilities() to hide/disable actions per provider. - ProviderException (HTTP 502) for external-dependency failures. PhoneProviderFactory: - getInstance(UUID) / **************** replace legacy getProvider(Long orgId); getPrimaryForOrg(Long) kept for legacy call sites (CallController, CapabilitiesController, SipController, webhook inbound). - RingCentral OAuth tokens now scoped by (orgId, provider, instanceId) so one org can authenticate multiple independent RingCentral deployments. - FreePBX construction reads config_json → {baseUrl, clientId, clientSecret, ignoreSslErrors} and instantiates a dedicated FreePBXGraphQLClient. RingCentral (RingCentralProvider): - Constructor takes instanceId for log context. - New methods: listExtensions / createExtension / updateExtension / deleteExtension; listUsers / createUser / updateUser / deleteUser (RC models both as type=User extensions); listDevices / createDevice / updateDevice / deleteDevice; fetchVoicemailAudio (streams attachment content) and fetchVoicemailTranscription. FreePBX (FreePBXProvider) — full implementation replaces placeholder: - Client-credentials OAuth2 token caching via FreePBXTokenCache (~1h TTL, auto-refresh on 401, per-instance). - FreePBXGraphQLClient: GraphQL + REST transports with optional skip-SSL-verification for self-signed on-prem PBXes. - Extensions, User Manager users, Endpoint Manager devices, voicemail list/mark-read/delete + audio stream, CDR call history, SIP credentials derived from the extension's pjsip secret, health via fetchAsteriskInfo. - SMS explicitly unsupported (capability sms=false) — FreePBX doesn't handle carrier SMS. Flowroute SMS (FlowrouteTextProvider): - Messages v2.1 API with HTTP Basic (accessKey, secretKey). - Health probe hits GET /numbers?limit=1. - Registered with BulkTextProviderFactory via new FLOWROUTE enum value. Controllers: - VoipInstanceController (renamed from ProviderConfigController) — full CRUD at /api/voip/instances with per-instance test/sync. Secrets redacted in GET responses ('***'); merge-update lets UI round-trip redacted fields without clobbering stored credentials. - BulkTextInstanceController (renamed from BulkTextConfigController) — mirror CRUD at /api/bulktext/instances with test / test-send / send. - OAuthController rewritten for instance-scoped OAuth: start, callback, status, disconnect all take instanceId. - SmsController resolves instance from member.instanceId → org primary, attaches to upserted conversations. - CallController / CapabilitiesController / SipController fall back to the org's primary active instance for legacy single-instance endpoints. Services: - InstanceSyncService: pull-through cache sync — extensions/users/devices/ voicemails copied from provider to local tables, missing rows soft-marked UNKNOWN. Each sub-step wrapped so one unsupported capability doesn't fail the entire sync (e.g. FreePBX no-SMS + has-extensions). - VoipMessageService: all conversation/message paths propagate instanceId. Tests: pre-existing VoipProviderConfig-specific tests removed (covered the renamed types; rewriting is out of scope per design spec §10 — no TDD infrastructure is being added in this refactor). Builds green with updated kamo-shared-library.

Ваша вселенная ждет.
Начните бесплатно через несколько минут. Добавляйте продукты, когда будете готовы — без миграции, без новых логинов.
Бесплатно навсегда — не требуется кредитная карта