
За последние годы аудитория Трекера выросла до 600 000 пользователей — пропорционально выросло и количество запросов на новые функции. Бэклог разросся до уровня ответов «внесли в список, но обещать ничего не можем». При этом рынок трекеров очень конкурентный, и останавливать развитие core‑продукта ради разбора кастомных запросов нельзя.
В какой‑то момент мы пришли к выводу: сколько бы ни увеличивали команду разработки, запросов от пользователей всегда будет больше. Это не проблема планирования, а скорее структурное свойство зрелого продукта с большой аудиторией. Единственный способ масштабироваться в этой точке — не делать всё своими руками.
Сегодня мы запустили платформу плагинов — отдельный механизм, который позволяет без навыков кодинга расширять Трекер собственными модулями под специфические задачи.
Привет, Хабр! Меня зовут Женя Успенский, я руковожу разработкой фронтенда в Яндекс Трекере и отвечаю за архитектуру платформы плагинов. Со статьёй мне помогал мой коллега Дима Куприк, который отвечает за весь проект целиком. Он расскажет, почему мы вообще решили дать возможность пользователям самим модифицировать Трекер, как плагины помогают решать специфические задачи команд и какие сценарии мы автоматизировали первыми.
В технической части я подробно разберу, какие задачи перед нами стояли и как мы их решили: изоляция стороннего кода, разрешения, proxy для внешних API и всё, что позволяет пускать чужой код в B2B‑продукт и спать спокойно.
Почему мы на это решились
Способ кратно масштабировать решение фича‑реквестов известен в индустрии давно — создать платформу плагинов. А для нас сошлись сразу три фактора:
Миграция с Jira. Множество компаний, переезжающих к нам, годами были завязаны на продукты Atlassian, в которых много самописных расширений. В силу того, что Jira больше нет на российском рынке и компании не хотят рисковать своими данными и процессами, замыкая их в контур не присутствующего на рынке игрока, мы видим приток миграций в Трекер. Но бизнесам нужно мигрировать в том числе свою кастомизацию.
Эпоха вайбкодинга. Порог входа в разработку резко снизился: сценарий, который раньше требовал участия разработчика, сегодня может собрать аналитик или админ с AI‑ассистентом. Экосистема расширений впервые может расти не только силами профессиональных команд.
Зрелость Трекера. Пользовательских сценариев и спроса на расширения стало достаточно, чтобы платформа не простаивала.
Так появилась платформа плагинов, где плагин — самостоятельный модуль, который добавляет в Трекер новый сценарий, интеграцию или элемент интерфейса без изменений в ядре продукта.


Мы, конечно же, не изобрели что‑то новое: плагинная модель Atlassian — состоявшаяся экосистема, и для многих команд именно маркетплейс, а не базовая Jira, был причиной оставаться на ней годами. Уход вендора лишил компании огромного пласта накопленных кастомизаций, интеграций и привычных модулей.
Мы хотим вернуть эту гибкость, но со строгой инженерной оговоркой: перенести старые Jira‑плагины как есть — сейчас технически невозможно. Архитектура современных облачных платформ, и нашей в частности, сильно отличается от Atlassian. В первую очередь это касается модели безопасности, изоляции стороннего кода и работы с API. Во второй части подробно разберём, почему мы выбрали именно такую архитектуру и как она защищает B2B‑контур. При этом собрать аналог старого плагина на нашей платформе существенно быстрее и дешевле, чем писать сервис заново.
Как работает платформа плагинов
Если процессу нужен специфический workflow, кастомная отчётность или связка с внутренним сервисом, разработчикам больше не придётся заводить множество тикетов в бэклоге, а команде — месяцами ждать релиза в ядре. Нужный модуль пишется и раскатывается силами самой команды или интегратора, а путь от идеи до продaкшена сокращается до нескольких дней.
Но при этом ни один плагин не может развернуться незаметно или получить доступ к лишним данным. Администратор организации сразу видит полный список запрашиваемых разрешений и управляет доступом.
Такой подход закрывает и проблему последней мили при миграции с других платформ. Теперь можно не ломать привычные процессы команды, подгоняя их под интерфейс, а дописать плагином недостающую узкоспециализированную фичу.
Мы выделяем три основные точки расширения, которые можно достроить кодом:
встраивание кастомных компонентов в заранее размеченные зоны интерфейса (новые панели, кнопки, отдельные вкладки на странице задачи или виджеты);
безопасный обмен данными с внешними сервисами и настройка сквозных триггеров;
кастомные вычисления, агрегация метрик и их вывод в интерфейс или экспорт во внешние системы.
Важная развилка, которую мы прошли на старте: строить платформу под Трекер или сразу как общий механизм. Мы выбрали второе, так как хотим, чтобы плагины могли закрывать кросс‑сервисные сценарии в нашей экосистеме. Спроектировали слой изоляции, авторизации и доставки плагинов так, чтобы в будущем на эту же инфраструктуру можно было безболезненно раскатывать расширения и для других продуктов Яндекс 360.
Как мы тестировали платформу внутри Яндекса
Прежде чем открывать платформу наружу, мы прогнали её через самый требовательный полигон, который у нас есть, — сам Яндекс. Трекером ежедневно пользуются сотни внутренних команд, у каждой из которых свои процессы и привычки.
Результаты закрытой беты за первые несколько месяцев:
25 плагинов за первый месяц. От дерева задач и импорта из CSV до AI‑суммаризации и коннектора к Мессенджеру.
Плагатон. Мы провели плагатон — внутренний хакатон, на котором команды за день сделали ещё 25 рабочих плагинов. Это стало лучшим подтверждением того, что разработка не требует долгого погружения.
Кейс небольшой фичи. Плагин для закрепления важных комментариев в задаче — та самая мелочь, которая вряд ли когда‑то пробилась бы в core‑роадмап. В виде плагина она мгновенно набрала около 5,5 тысячи DAU.
AI‑ассистенты и low‑code. Часть плагинов написали специалисты вне классической разработки — с помощью LLM‑кодогенерации. Например, первый рабочий плагин, генератор Excel‑отчётов, автор собрал буквально за пару промптов.
Параллельно мы запустили пилоты с пятью компаниями‑партнёрами: два партнёра за неделю довели свои решения до production‑ready‑состояния. У нескольких компаний была узкая, но важная потребность: массовое клонирование проектов. В core‑бэклоге такая функция могла бы ждать своей очереди неограниченно долго — слишком нишевый запрос. Вместо этого один из наших архитекторов реализовала её как плагин.
Как пустить чужой код в В2В и спать спокойно
Когда в воздухе стала витать идея: «А давайте дадим пользователям возможность писать свой код прямо внутри Трекера», первая реакция бэкендеров и безопасников была:
— Вы что? С ума сошли?
Пустить сторонний JavaScript, написанный неизвестно кем, в B2B‑продукт с чувствительными данными — это прямой путь к XSS, вытаскиванию токенов и утечкам. Нам нужна была архитектура, которая позволит создавать сложные интерактивные плагины с динамическим UI, но при этом упакует их в железную изоляцию.
Мы изучили, как задачу встраивания стороннего кода решают другие платформы, и заметили, что весь опыт сводится к трём паттернам:
Код выполняется в виртуальном JS‑движке. Код плагина выполняется в отдельной песочнице, например в изолированном JS‑интерпретаторе прямо в браузере. Отлично подходит для генерации статичных элементов или расчётов, но не для полноценных интерфейсов.
iframe на безкуковом домене. Код и UI плагина находятся на отдельном изолированном домене без доступа к cookie и API основного приложения. Плюс: можно ограничить сетевые запросы, запретив обращения на любые внешние адреса, кроме явно разрешённых. Минусы: любые всплывающие элементы (попапы, модалки, выпадающие списки) зажаты рамками iframe, что требует костылей для их отображения поверх интерфейса Трекера; каждый iframe заново грузит ресурсы, без дополнительных оптимизаций он будет пересоздаваться при каждом переходе внутри сервиса.
Код в iframe + рендеринг в основном DOM. Код плагина крутится внутри iframe, но инструкции по отрисовке отправляются через postMessage в основной DOM‑контур приложения. Плюсы: нативный визуал без лишних отступов и рамок, бесшовные попапы и возможность использовать один iframe для нескольких компонентов на странице. Минусы: сложная кастомная логика проксирования, которая повышает вероятность ошибки, и сложная совместимость версий. Если плагин и основной сервис используют разные версии UI‑библиотек, например React или Gravity UI, поддержание обратной совместимости становится кошмаром.
Наш выбор изоляции: классический iframe, зажатый в гиперизоляцию
Взвесив все за и против, мы остановились на классической изоляции через iframe. Это решение выглядит не так концептуально, зато оно даёт гарантии безопасности и позволяет быстро выйти в продакшен.
Как именно устроена изоляция:
каждый плагин отдаётся с отдельного изолированного хоста, у которого нет доступа к cookie и хранилищу основного приложения;
в параметрах iframe мы явно разрешаем только выполнение скриптов (allow‑scripts), жёстко ограничивая все остальные возможности;
политика безопасности запрещает практически всё, в том числе сетевые запросы на любые внешние адреса, отличные от собственного домена iframe.
Для создания UI мы предлагаем авторам плагинов использовать Gravity UI — открытую дизайн‑систему с готовым набором компонентов, адаптивностью и встроенной локализацией.
Все ключевые модули получившейся системы мы оформили как самостоятельные независимые пакеты. Это позволяет подключать к платформе плагинов любые другие сервисы и не переписывать архитектуру изоляции с нуля.
Давайте подробно разберём, из каких компонентов состоит эта система.
Bridge
Всё общение плагина с сервисом и внешним миром происходит через специальный объект Bridge, который для транспорта использует postMessage. Bridge состоит из хостовой части, которая выступает диспетчером для плагинов (вызов — ответ), и клиентской части, которая подключается из NPM.

На старте плагин получает минимально необходимую ему информацию. Например, id открытого сейчас тикета. Для получения других данных, например информации о текущем пользователе, нужно вызывать методы публичного API и запрашивать соответствующие права.
Обращение к API Трекера и внешний мир
Для обращения к публичному API Трекера есть интерфейс в клиентской части пакета Bridge со всеми методами и сущностями публичного API. Под капотом происходит обращение к сервисной части, которая проверяет каждый вызов на предмет прав, прописанных в плагине, и выполняет запрос с правами текущего пользователя. Таким образом, права плагина — это всегда подмножество прав текущего пользователя.
Для походов во внешний мир плагин обязан задекларировать используемые домены в манифесте и указать способ авторизации. Для сервисов с авторизацией Трекер сам спросит токены для каждого домена, сохранит в защищённое хранилище и будет подмешивать при запросах. Плагин никогда не получает к ним прямого доступа.
Манифест
Самый главный файл плагина, который содержит основную информацию о нём: точки встраивания, права доступов и так далее
{ ... "slots": { "tracker": { "issue.action": [ { "entrypoint": "index.html", "title": { "ru": "Моё действие", "en": "My action" }, } ] } }, ... "permissions": { "data": [ "tracker:issues:read", "tracker:issues:write", "tracker:queues:read", ], "ui": ["toaster", "confirm"] }, }
Инструментарий
Для разработки плагинов мы сделали консольную утилиту в виде NPM‑пакета. Она закрывает весь жизненный цикл плагина: создание, отладку, проверку и публикацию.
Основа качественного DevExp — это быстрое получение результата. Поэтому у нашего CLI есть режим отладки, который не требует развёртывания окружений или отправки кода на внешние серверы. В сочетании с широким набором готовых шаблонов это позволяет сразу увидеть работу плагина в интерфейсе Трекера и дальше дорабатывать его под свою бизнес‑логику.
ИИ‑доступность
Как было написано выше, одним из драйверов запуска платформы стала эпоха вайбкодинга. Но плагин — это интеграция с API Трекера, а написать правильную интеграцию без точного контекста не поможет никакой AI‑ассистент. Поэтому мы постарались дать максимум контекстной информации и разработчикам, и LLM‑моделям:
JSDoc‑документация и типы прямо в коде;
все стартовые шаблоны в нашем CLI сразу содержат подготовленный файл AGENTS.md;
рекомендуемый Gravity UI сам по себе активно развивает ИИ‑доступность — например, планируется выпустить плагин для Claude, который помогает генерировать интерфейсы по гайдлайнам дизайн‑системы;
сквозная типизация публичного API.
Если первые пункты — это скорее хорошая инженерная гигиена и задействование готовых экосистемных инструментов, то над сквозной типизацией API нам пришлось поломать голову.
Мы хотели дать авторам плагинов хороший Developer Experience: строгую типизацию, автокомплит параметров в IDE и подсказки. У нас было два стандартных пути, и оба, если честно, плохие:
Сгенерировать гигантский SDK с глубокими неймспейсами (
sdk.api.issues.getById(...)). Каждый метод превращается в реальную JavaScript‑функцию. Для сотен эндпоинтов это сотни килобайт исполняемого кода, а Tree‑shaking в таких структурах не всегда работает предсказуемо. Отдавать такой бандл каждому плагину — значит убить производительность фронтенда.Сделать обёрточный метод над fetch вида sdk.request(
GET,/issues/123). Размер бандла близок к нулю, но DX совершенно нас не устроил: нет подсказок, автокомплита, а разработчики и нейросети постоянно опечатываются в ручках и параметрах.
Нам требовался святой Грааль: получить DX и автокомплит «толстого» клиента, сохранив размер бандла «тонкого». И мы нашли его на стыке возможностей TypeScript‑типов и объекта Proxy.
Шаг 1. Compile‑Time: строковые литералы вместо методов
Мы отказались от генерации JS‑кода в пользу генерации исключительно TypeScript‑типов (.d.ts) напрямую из нашей OpenAPI‑схемы. Вместо абстрактных имён методов мы используем нативные REST‑пути в виде строковых литералов. Синтаксис вызова API в нашем SDK выглядит так:
const issue = await sdk.api.v3.get['/issues/{id}']({ path: { id: 'QUEUE-123' }, query: { expand: 'comments' } });
Обратите внимание на синтаксис обращения: get['/путь']. Когда разработчик пишет sdk.api.v3.get[ и ставит открывающую кавычку, TypeScript воспринимает это как обращение к свойству огромного интерфейса.
Благодаря этому движки автокомплита и в VS Code, и в WebStorm моментально выводят список всех доступных эндпоинтов. И самое главное — IDE показывает полную JSDoc‑документацию прямо во время набора строки, чего невозможно добиться при передаче строки обычным аргументом функции.
Типы заставляют разработчика передавать переменные пути строго в объект path, защищая от ошибок динамической интерполяции (/issues/${id}), что сильно упрощает статический анализ кода плагинов.
Шаг 2. Рантайм: чёрная дыра на базе Proxy
Но как реализовать объект get, у которого есть сотни свойств‑функций (под каждый эндпоинт), не написав при этом мегабайты кода? В исполняемом JS‑файле нашего SDK нет ни одного упоминания эндпоинтов. Весь рантайм‑роутер умещается буквально в 10 строк благодаря ES6 Proxy:
class ApiV3 { // Перехватываем любое обращение к свойству (например, к '/issues/{id}') get = new Proxy({}, { get: (target, pathString) => { // Возвращаем универсальную функцию, которая выполнит запрос return async (payload) => { let resolvedUrl = pathString; // Подставляем параметры в URL, если они есть if (payload?.path) { for (const [key, value] of Object.entries(payload.path)) { resolvedUrl = resolvedUrl.replace(`{${key}}`, String(value)); } } return httpClient.request('GET', resolvedUrl, payload?.query); }; } }); }
Результаты такого подхода
Zero‑cost‑масштабирование. Бэкенд может добавить хоть 10, хоть 10 000 новых методов — размер исполняемого JS‑кода SDK при этом увеличится ровно на 0 байт. Растёт только файл деклараций.d.ts, который используется исключительно на этапе разработки и полностью исчезает из финального продакшен‑бандла.
AI‑friendly‑архитектура. Нейросети намного проще сгенерировать понятный HTTP‑путь вида '/users/{id}' по текстовому запросу, чем угадывать, как именно авторы «толстого» SDK назвали конкретный метод или класс в своей абстракции.
Синхронизация с документацией. Разработчики плагинов получают в IDE ровно ту же актуальную документацию, что и в нашем Swagger/OpenAPI, без необходимости переключаться в браузер.
Таким образом мы разделяем ответственность между слоями: TypeScript берёт на себя проверку контрактов и автокомплита, а рантайм отправляет сетевые запросы.
Что в итоге
Нам удалось собрать платформу плагинов, которая сочетает два противоположных требования:
Безопасность и контроль: сэндбоксинг через iframe, изоляция JS‑кода, проксирование вызовов и scopes не дают плагину выйти за пределы B2B‑контура.
Низкий порог входа и DevExp: благодаря отладке в CLI, готовым шаблонам, автоматической типизации API и ориентации на AI‑инструменты путь от задумки до работающего модуля занимает дни, а иногда и часы.
Ставить, писать и запускать плагины могут те пользователи, у которых есть платный тариф Яндекс Трекера и лицензия полного доступа. Прежде чем плагин попадёт в каталог, его проверяют на модерации. При установке администратор видит, какие разрешения плагин запрашивает, а через публичный API плагин получает только те данные Трекера, которые и так открыты пользователю, — своих прав он не добавляет.
Если вы хотите собрать свой первый плагин под задачи компании или сделать решение для экосистемы:
Изучите документацию:
Разверните стартовый шаблон с помощью нашего CLI‑инструмента.
Задавайте вопросы, делитесь идеями и фидбэком в комментариях к статье — мы обязательно придём, чтобы на них ответить! Будем рады сравнить опыт с теми, кто писал плагины под Jira или строил свои платформы.
Ну и напоследок: угадайте, что за плагин сделали умельцы? Только неправильные ответы:)

