Расширение интеграции с Linear, улучшения рабочих процессов и устранение критических уязвимостей
Релиз охватывает сразу четыре ключевых направления: устранение критических уязвимостей в ПМ агенте, расширение функциональности интеграции с Linear, улучшение UX в разделе встреч и исправление логики расчетов в модуле отсутствий. Дополнительно исправлен ряд ошибок в глобальных фильтрах и парсинге GitLab.
Даты релизов: 26.03.2026
Улучшения интеграции с Linear
Устранена ошибка "Integrity Error" при удалении доски Linear с привязанными компонентами. Исправлена проблема каскадного удаления досок Linear: теперь при удалении доски автоматически удаляются все привязанные компоненты и метки из Linear, устранен конфликт ограничений внешнего ключа, обеспечена корректная обработка зависимостей на уровне базы данных. Также добавлена поддержка удаления устаревших записей, включая унаследованные данные с компонентами.
Реализовано каскадное удаление интеграций Linear с автоматической очисткой связанных данных. При удалении доски из проекта через интерфейс автоматически удаляются все связанные данные из базы: задачи, журналы работ, комментарии, статусы и активности. Операция выполняется атомарно с корректной обработкой ограничений внешнего ключа. В интерфейсе добавлена индикация процесса удаления.
Реализован автоматический мониторинг токенов Linear с уведомлением менеджеров о проблемах доступа. Проверка валидности токенов Linear интегрирована в существующий процесс мониторинга – наряду с Jira, GitLab, GitHub и Notion система теперь автоматически проверяет актуальность API-токенов Linear. При обнаружении недействительного или просроченного токена создается оповещение в ленте активностей и отправляется персональное уведомление в мессенджер (Slack или Telegram согласно настройкам проекта) менеджерам проекта (PM, DM) с указанием того, какая доска требует переподключения. Тем самым обеспечивается единая система мониторинга состояния всех интеграций.
Добавлена кнопка "Fetch Statuses" для ручной синхронизации статусов задач. В интерфейсе управления интеграцией с Linear появилась кнопка, позволяющая вручную инициировать загрузку статусов задач через API. Полученные данные сохраняются в формате, необходимом для расчёта Agile-метрик (Lead Time, Cycle Time, Throughput), с корректным сопоставлением статусов этапам рабочего процесса для последующей аналитики.
Добавлена опция "Fetch missing worklogs" для гибкого управления синхронизацией журналов работ. После первой успешной синхронизации система фиксирует дату и время последней загрузки данных для каждой доски. В настройках конкретной доски доступна возможность вручную изменить это значение для повторной загрузки данных с указанной даты. На уровне проекта реализована глобальная опция "Fetch missing worklogs", позволяющая массово сбросить дату начала синхронизации сразу для всех подключённых досок, что позволяет восстановить исторические данные или закрыть пробелы в синхронизации.
Реализована полная интеграция спринтов Linear для Ongoing-дашборды и ПМ агента. Циклы Linear (Cycles) теперь обрабатываются как эквивалент спринтов: система парсит и сохраняет название, даты начала и окончания, состав задач с их статусами и прогрессом. Данные доступны в Ongoing-дашборде для планирования спринтов и отслеживания скорости команды (velocity), а также интегрированы в контекст ПМ агента для ответов на вопросы о текущем спринте, прогрессе и закрытых story points. Реализован механизм инкрементального обновления: если в завершенном спринте изменились название, даты или состав задач, система автоматически синхронизирует актуальные данные на стороне Enji.
Улучшения в Meetings
Добавлена возможность удаления встреч с транскриптами через интерфейс с защитой от случайного удаления. Реализован полный процесс удаления записей встреч: в каждой строке таблицы "Meetings" добавлена иконка удаления, при клике на которую открывается диалоговое окно подтверждения с наименованием удаляемой встречи и предупреждением о необратимости действия и потере транскрипции. Управление окном осуществляется двумя кнопками – "Cancel" и "Confirm" – с индикатором загрузки при обработке. После успешного удаления отображается уведомление "The {meeting_name} meeting has been deleted", список встреч автоматически обновляется. Реализована обработка ошибок с соответствующими уведомлениями. Диалоговое окно закрывается при клике вне его области или нажатии кнопки "Cancel" без удаления.
Добавлена возможность удаления встречи непосредственно при просмотре ее карточки. В заголовке карточки "Meeting info" добавлена иконка удаления. При клике открывается диалоговое окно подтверждения, идентичное тому, что используется в списке встреч: с предупреждением о потере транскрипции и кнопками "Cancel" и "Confirm" с индикатором загрузки. После успешного удаления выполняется автоматический переход на страницу "Meetings" с отображением уведомления "The {meeting_name} meeting has been deleted". UX-поведение согласовано с удалением из списка.
Реализовано массовое назначение проектов встречам. После выбора нескольких встреч через чекбоксы в нижней панели страницы появляются кнопки "Delete" и "Assign project". При клике на "Assign project" открывается диалоговое окно "Project Assignment" с таблицей, содержащей следующие колонки:
- "Meeting" – название встречи с датой и временем ее проведения
- "Current project" – текущая привязка к проекту или значение "Not defined",
- "New assignment" – выпадающий список для выбора нового проекта
Переключатель “Same for all” позволяет применить один проект ко всем выбранным встречам с синхронизацией всех выпадающих списков. Доступны действия: "Clear selection" (сброс выбора), "Cancel" (закрытие без изменений) и "Confirm" с индикатором загрузки и отправкой PATCH-запросов. После успешного применения в правом верхнем углу на 3-5 секунд появляется уведомление "{number} meetings have been reassigned to other projects", список встреч автоматически обновляется.
Реализовано назначение и переназначение проекта митингу из карточки встречи. В правой панели карточки "Meeting info" блок "Project" отображает текущий назначенный проект с иконкой и названием, а также иконку редактирования. Если проект не назначен, вместо него отображается кнопка "+ Assign project". Клик на кнопку, иконку редактирования или на само название проекта открывает выпадающий список с полем поиска "Search" для фильтрации проектов по названию в реальном времени и перечнем всех доступных проектов с цветными иконками и названиями (текущий проект также присутствует в списке). При выборе проекта отправляется PATCH-запрос, список закрывается, блок "Project" обновляется. При первичном назначении отображается уведомление "Meeting has been assigned to project", при переназначении – "Meeting has been reassigned to another project".
Реализованы информативные состояния-заглушки для разделов "Summary" и "Transcription". Предусмотрен набор состояний для различных ситуаций:
- "Processing in progress" – отображается во время генерации сразу после завершения встречи.
- "Meeting processing in progress"-- когда точное время не определено.
- "Oops! Something went wrong" – при ошибках загрузки или генерации.
- Состояние пустого списка встреч с дополнительной информацией о подключении сервиса.
Улучшения и исправления в Absence
Реализована защита от обхода лимита отгулов (Day Off) через множественные заявки. Внедрена система контроля последовательных отгулов с защитой от обхода через раздельные заявки – теперь сотрудники не могут оформить более двух отгулов подряд независимо от количества заявок. Например, нельзя оформить 1-2 августа одной заявкой, а затем 3 августа – отдельной. Следующий отгул можно оформить не ранее чем через 3 рабочих дня после последнего; при создании новой заявки система проверяет все подтвержденные и ожидающие подтверждения заявки сотрудника. Дополнительно добавлена защита от оформления отгула в выходные дни. HR-пользователи выведены из-под ограничений и могут создавать любые последовательности отгулов. При нарушении правил система отображает информативное сообщение об ошибке с указанием ближайшей допустимой даты.
Реализована блокировка отгулов (Day Off) и больничных (Sick Leave) для сотрудников в первые 3 месяца работы. Система теперь блокирует подачу заявок на отгулы и больничные для сотрудников, не завершивших испытательный срок. При попытке создания заявки пользователь получает информативное предупреждение с объяснением причины блокировки и датой, когда функция станет доступна. Валидация обеспечена на уровне как клиентской, так и серверной части.
Устранено расхождение между "Absence Overview" и профилем сотрудника, реализована единая система расчета. Исправлена критическая ошибка расчёта остатка отпускных дней: колонка "Остаток на текущий момент" в "Absence Overview" теперь отображает фактическое значение, совпадающее с данными в профиле сотрудника, вместо дублирования значения "Остаток на начало года". Система начисления отпусков переписана с унификацией логики расчета для всех типов сотрудников, в профиль добавлена история начислений и списаний. В настройках "Absence Settings" реализована кнопка глобального перерасчета отпусков для всех сотрудников для корректировки исторических данных. Также исправлены граничные случаи с запоздалыми записями о работе и одновременным запуском отпуска и начисления.
Исправлено применение пользовательских правил отпусков по хронологии даты начала. Исправлена критическая ошибка в логике применения пользовательских правил отсутствия в "Personal Settings": теперь правила применяются строго в хронологическом порядке по полю "Start date" независимо от последовательности их создания в интерфейсе. Реализован автоматический расчет даты окончания действия правила для записей без явно указанного "End date" при добавлении нового правила с более поздней датой начала. Обработаны граничные случаи с жестким перекрытием периодов, добавлена сортировка правил в таблице по убыванию даты начала. Перерасчет балансов выполняется только при создании новых правил и не затрагивает существующие данные ретроактивно.
Отключено автоматическое создание задач в Jira при утверждении заявок на отсутствие. При создании и утверждении заявок на отпуск, отгул или больничный задачи в Jira больше не создаются – весь процесс обработки заявок теперь полностью происходит внутри Enji. Процесс выглядит следующим образом: сотрудник создает заявку → она отображается у HR и согласующих в Enji → заявка утверждается → статус обновляется в Enji, без промежуточных задач во внешнем трекере.
Улучшения и безопастность в ПМ агенте
Устранена критическая уязвимость утечки данных между проектами через векторный поиск. Исправлена проблема безопасности (CWE-284: Improper Access Control, HIGH severity): флаг is_chat_agent=True в execute_query() полностью отключал установку переменной сессии copilot.projects_ids, что приводило к выполнению SQL-запросов без какой-либо фильтрации по проектам. В три критические точки добавлены защитные проверки по принципу fail-closed: при отсутствии или пустом project_ids функции немедленно возвращают пустой результат с предупреждением в логах вместо выполнения поиска по всей базе данных. Добавлено 9 юнит-тестов, покрывающих все сценарии защиты.
КАК ВЛИЯЕТ: Закрыта уязвимость, при которой запрос к ПМ агенту без указания project_ids или с пустым списком проектов инициировал поиск по всей векторной базе данных, включая документы, чаты, метаданные и ссылки на треды из проектов других пользователей и компаний, что представляло прямую утечку конфиденциальных данных.
Устранена критическая уязвимость: SQL-запросы агентов чатов и конференций игнорировали ограничение по проекту. Исправлена проблема безопасности (CWE-284: Improper Access Control, HIGH severity) в SQL-путях агентов чатов и конференций. Ограничение по проекту теперь устанавливается обязательно для всех агентов, включая chat_agent и conf_agent; удалён механизм обхода parameters = None; добавлена принудительная фильтрация WHERE project_id = ANY(...) на уровне базы данных; поведение представления изменено с разрешающего по умолчанию на запрещающее при отсутствии явного указания проекта.
КАК ВЛИЯЕТ: Закрыта уязвимость, позволявшая получить доступ к чатам и записям встреч из других проектов. Ранее изоляция данных зависела исключительно от формулировки промпта к языковой модели, которая могла быть проигнорирована или обманута, – вместо принудительного ограничения на уровне базы данных. Принцип deny-by-default критичен для соответствия стандартам SOC 2 Type II и ISO 27001, а также для защиты от внутренних угроз в компаниях с разделёнными командами и сотнями проектов.
Исправлена ошибка отправки запросов в ПМ агент при клике мышью. Устранена ошибка "Input data should be a string" (400 Bad Request), возникавшая при отправке запроса кликом вместо нажатия Enter. Теперь данные корректно сериализуются и проходят валидацию на серверной стороне независимо от способа отправки.
Прочие улучшения
Исправлена ошибка выбора единственного элемента в глобальных фильтрах. Исправлена логика определения состояния "All" в компоненте фильтра: теперь для проверки того, выбраны ли все доступные варианты, система всегда использует полный список вместо отфильтрованного. Это устраняет ошибочную активацию режима "All" при выборе единственного найденного элемента в поиске и обеспечивает корректную работу фильтра независимо от количества элементов в отфильтрованном списке.
Исправлен парсинг коммитов GitLab Self-hosted при изменении списка веток. Исправлена проблема парсинга GitLab Self-hosted: при изменении набора отслеживаемых веток репозитория (например, с ветки по умолчанию на .*? для всех веток) теперь автоматически сбрасывается дата последнего парсинга в таблице Group и удаляется контрольная точка из настроек gitlab.repository.commit.forward.<repository_id>. Это обеспечивает полный повторный парсинг коммитов с самого начала, включая исторические коммиты из добавленных веток, которые ранее игнорировались из-за сохранения устаревшей даты последней синхронизации.
Добавлен информативное состояние-заглушка для ИИ Суммаризатора при недоступности ПМ агента. В виджете AI Summary вкладки "Activities" в профиле сотрудника вместо статичного текста-заглушки, имитирующего реальную аналитику, теперь отображается понятное сообщение о том, что ПМ агент не подключен к организации или сервис недоступен. При наличии и доступности ПМ агента виджет работает в штатном режиме, отображая реальные аналитические данные.
Добавлен умный выпадающий список для выбора PM Site при подключении интеграций в мастере создания проекта. На шаге "Add integrations" текстовое поле ввода URL заменено на выпадающий список, который автоматически загружает существующие PM Sites текущей организации с фильтрацией по типу источника: при подключении Jira отображаются только Jira PM Sites, YouTrack → только YouTrack и т.д. При выборе PM Site из списка URL и тип инстанса подставляются в форму автоматически. Если нужный PM Site еще не существует, его можно создать прямо в поле ввода – при отправке формы новый PM Site будет создан с соответствующим типом источника. Также реализованы заглушки для случаев, когда подходящие PM Sites отсутствуют. Обеспечена обратная совместимость: при полном отсутствии PM Sites поле ведет себя как обычное поле ввода URL.