— Где актуальный контракт сервиса рассрочек?
— В репозитории.
— В каком?
— Сейчас найду ссылку.

У нас этот диалог повторялся регулярно. Формально API-документация была. Фактически реестр хранился в памяти нескольких сотрудников, а поиск работал через WB Wiki и корпоративный мессенджер Band.

Меня зовут Олег Леонов, я руковожу отделом системного анализа в финтехе RWB. Мы занимаемся рассрочками и кредитами, инвесткопилкой и WB Кошельком в мобильном приложении и на сайте.

Swagger Aggregator я начинал как pet-проект. Хотел собрать контракты в одном месте и искать по ним примерно так же, как по коду. Потом агрегатор прижился у команды. Расскажу, что в итоге получилось и на каких местах я потратил больше времени, чем рассчитывал.

Swagger UI тут не помогал

Swagger UI нормально показывает одну спецификацию. Проблема в том, что у нас их много, а лежат они где угодно:

  • YAML или JSON во внутреннем GitLab;

  • документ по HTTP-адресу dev-сервиса;

  • ссылка в Wiki, которая когда-то была актуальной;

  • ссылка в чате, которую ещё надо найти.

    Аналитик обычно ищет не конкретный файл. Он ищет понятие: где используется paymentToken, какой сервис возвращает статус заявки, у кого поле суммы называется amount. Открывать контракты по одному и искать внутри каждого можно, но делать так каждый день быстро надоедает.

    Мне был нужен каталог с поиском по содержимому, версиями, diff и возможностью сразу продолжить работу с найденной ручкой.

Почему не взяли готовое решение

Сначала я посмотрел, что уже есть на рынке:

Решение

Что умеет

Почему не подошло

SwaggerHub

Совместное проектирование, style guide, портал документации

SaaS для внутренних контрактов не подходит. Enterprise on-prem требует лицензий, бюджета и отдельного администрирования. Для команды из 15 аналитиков тяжеловесно

Redocly

OpenAPI-first, docs-as-code, сборка сайта документации

Хорошо работает с документацией вокруг спецификации, но не решает наш сценарий поиска по содержимому всех контрактов

Stoplight

Визуальный редактор, валидация, governance

Это отдельная платформа со своей авторизацией и хранилищем. Интеграцию с внутренним GitLab пришлось бы собирать отдельно

Apicurio Registry

Реестр схем, артефакты, версии

Хороший registry, но для ежедневной работы аналитика не хватило просмотра операций, поиска по полям и прототипов

Postman

Тестирование, коллекции, совместная работа

Работает с контрактом в первую очередь как с артефактом тестирования. Мне был нужен именно каталог

Первым отвалился SaaS. Контракты финтеха нельзя загружать наружу: в них видны внутренние сервисы, модели и бизнес-логика. Я бы не стал этого делать даже без формального запрета.

Дальше упёрлись в корпоративный GitLab и его права. Агрегатор должен читать файл прямо из репозитория по проекту, ветке и пути. Если добавить промежуточный импорт, появится ещё одна копия, которая обязательно когда-нибудь устареет.

Дальше требования набрались из обычной работы: глобальный поиск, diff версий, проверка breaking changes, mock и конструктор прототипов с общей ссылкой. Готового решения со всем этим я не нашёл.

Ну и мне просто хотелось написать свой инструмент. Для pet-проекта это нормальная причина.

Весь проект — чистый вайбкод. Я задавал архитектуру и направление, тестировал и деплоил, а основную массу реализаций писал ИИ-кодинг-агент. Для внутренней штуки это идеальный сценарий: не нужно заказывать доработку у разработчиков, можно вечером сесть и за пару сессий выкатить очередную фичу.

Дерево решения: своё или готовое
Выбор между своим инструментом и готовым порталом.

Как агрегатор получает контракты

Сейчас есть два типа источников.

Для GitLab указываются проект, ветка и точный путь к файлу. Адаптер забирает raw-содержимое через API v4. Для развёрнутого сервиса достаточно URL.

Формат сначала определяется по Content-Type. Но часть сервисов отвечает application/octet-stream, поэтому есть запасной вариант: агрегатор смотрит на первый значимый символ и понимает, JSON перед ним или YAML.

После синхронизации контракт появляется в каталоге. В центре открывается Swagger UI 5, сверху лежат сведения о средах и ответственных. Сервисы можно раскладывать по папкам и перетаскивать. Это оказалось удобнее, чем держать список ссылок.

Каталог спецификаций
Каталог спецификаций

Каталог слева, Swagger UI по центру, метаданные сверху.

Открытая спецификация сервиса User Balance
Открытая спецификация сервиса User Balance

В контракте User Balance 72 операции.

Поиск

В левой панели сервисы фильтруются по имени. Внутри открытой спецификации поиск проверяет параметры, request body, ответы, вложенные схемы и массивы. На экране остаются только подходящие операции.

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

*combo-payment нашёлся в контракте User Balance.
*combo-payment нашёлся в контракте User Balance.

По клику агрегатор открывает нужный контракт, разворачивает операцию и подсвечивает её. Отсюда можно скопировать curl, получить описание ручки в Markdown, создать mock или перейти к сравнению версий.

Открытая спецификация сервиса User Balance
Переход из глобального поиска к найденной операции.
*Поиск по amount внутри одной спецификации.
*Поиск по amount внутри одной спецификации.

Всю спецификацию можно выгрузить как Postman Collection 2.1.

Версии и breaking changes

При изменении источника предыдущая версия уходит в архив. Семантический diff сравнивает операции, параметры, request body и ответы. Можно открыть две версии рядом или посмотреть короткий список изменений.

Старая и новая версии контракта.
Старая и новая версии контракта.

Проверка обратной совместимости ловит удаление операции или параметра, появление нового обязательного параметра и смену типа.

Сразу обозначу ограничение: полноценной сохранённой классификации breaking / non-breaking / patch для каждой версии пока нет. Сама проверка breaking changes работает, трёхуровневая классификация ещё в планах.

Конструктор прототипов

Аналитик собирает OpenAPI-контракт через формы и сразу видит результат в Swagger UI. Сохранённый прототип открывается по share-токену без авторизации.

Сценарий простой: собрал контракт, отправил ссылку разработчику, внёс изменения, отправил ту же ссылку ещё раз. YAML руками править не обязательно.

Открытая спецификация сервиса User Balance
Сборка контракта через формы.

Mock, который возвращает что-то полезнее {}

Mock-сессия живёт от одного до 24 часов и хранит выбранные операции. Запрос сопоставляется одновременно по HTTP-методу и пути. Если смотреть только на путь, GET /users и POST /users начинают конфликтовать.

Если тело ответа не задано вручную, генератор ищет 200, 201 или первый 2xx. Затем раскрывает локальные $ref и строит JSON по схеме. Поддерживаются примеры, объекты, массивы, числа, строки, boolean и композиция схем.

Для каждого запроса создаётся отдельный генератор. Иначе параллельные обработчики делили бы случайное состояние и разобранную спецификацию.

Список активных mock-сессий
Список активных mock-сессий

Активные mock-сессии и оставшееся время жизни.

Путь, body, headers и cookies можно переопределить. Настраиваемого status code, задержки и отдельного mock-поддомена сейчас нет. Это именно планы, а не работающий функционал.

Архитектура

В основе порты и адаптеры. Ядро знает интерфейсы. HTTP-обработчики работают с ним через порты. GitLab, HTTP-источники, PostgreSQL, SQLite и уведомления подключены адаптерами.

Архитектура основных компонентов
Архитектура основных компонентов

Схема основных компонентов.

Хранилище выбирается переменной окружения, оба варианта реализуют одинаковые порты. Я не считаю, что каждый пет-проект обязательно надо строить так. Здесь подход оказался удобным: можно локально запустить SQLite, а в окружении подключить PostgreSQL без изменений в ядре.

Планировщик синхронизирует источники по расписанию, по умолчанию раз в сутки. Авторизацию можно включить через Keycloak OIDC. Для локального запуска она не нужна.

Жизненный цикл контракта
Жизненный цикл контракта

Синхронизация, проверка хеша, архив и дальнейшая работа с версией.

Где я потратил больше всего времени

Дубли ключей в YAML

В одной спецификации встретились одинаковые ключи на одном уровне. Человек такой дубль легко пропускает, а парсер отказывается декодировать документ.

Терять весь контракт из-за одного ключа не хотелось. Теперь синхронизатор сначала строит дерево YAML, рекурсивно убирает дубли и оставляет последнее значение. Только после этого документ разбирается как OpenAPI.

Важно, что YAML пересобирается лишь при реальном дубле. Если нормализовать каждый файл всегда, косметические изменения форматирования меняют хеш и создают ложные версии.

Контракт от такой обработки не становится правильным. Он просто остаётся доступен в каталоге, а проблему можно увидеть и исправить в источнике.

Автообнаружение Swagger в GitLab

Первая идея была очевидной: рекурсивно пройти репозиторий и найти все swagger.yaml. На монорепозитории этот вариант быстро перестал нравиться. GitLab отдаёт дерево страницами, оно может измениться между запросами, а большая часть найденных файлов не относится к нужному сервису.

Для отдельного discovery-скрипта работает проверка небольшого набора известных путей через лёгкие запросы. В самом приложении источник хранит точный путь, и адаптер забирает raw-файл.

Автоматического сканера групп сейчас нет. Управляемый список оказался надёжнее робота, который иногда приносит не тот Swagger.

Что есть в репозитории сейчас

Цифры в таблице — срез по актуальной базе (август 2026). Всего в агрегаторе 209 спецификаций, большая часть приходит из GitLab (194) и deployed-хостов (15).

Метрика

Значение

Спецификаций

209

Источников GitLab / URL

194 / 15

Методов

2 467

Суммарный размер контрактов

7 767 980 байт, около 7,4 МиБ

Пользователей

82

Для меня важнее не размер каталога. Важно, что поиск API теперь начинается с сущности или поля, а не с вопроса в чат: «У кого была ссылка?»

Пара слов в конце

Полезен агрегатор оказался не перечнем функций, а тем, что из работы ушёл один вопрос: где лежит актуальный контракт и что в нём поменялось. Сейчас в каталоге 209 спецификаций и 2467 методов, ими пользуются 82 человека. Для команды это уже не эксперимент, который один раз показали на встрече, а постоянно открытая вкладка. В ней ищут по всем контрактам, смотрят версии и diff, поднимают mock, собирают прототипы. Начиналось всё с простого желания не тратить пару минут на поиск ссылки в чатах — с этим мы справились.

Заодно выяснил, что полезная внутренняя штука часто вырастает не из большого замысла, а из одной надоевшей проблемы, которую наконец перестали терпеть. Если у вас похоже — интересно сравнить, как это организовано у вас. Где живут ваши OpenAPI-спецификации, как вы ищете сразу по нескольким контрактам, кто разбирается с версиями и breaking changes? Расскажите в комментариях, что из этой рутины раздражает сильнее всего и как вы с этим справляетесь.

Комментарии (1)


  1. chemtech
    28.08.2026 03:01

    А где исходники?