Из этой статьи вы узнаете, какие преимущества предоставляет контроль контракта API, что можно и нужно контролировать и как организовать процедуры контроля для исключения негативного влияния на производство.

Когда в 1825 году Англия первыми из всех запустила железнодорожное сообщение между городами, мир еще жил по солнечному времени, ориентируясь на полдень – момент верхней кульминации солнца. Фактическая разница во времени между городами в одной географической полосе могла достигать 30 минут. Отсутствовала синхронизация.

Поезд, который отправлялся из Лондона в 12:00 по местному времени и должен был прибыть в Бристоль в 13:00, по местному времени прибывал в 13:30. Для местных жителей и пассажиров поезда это не было критичным явлением, но для компании-перевозчика, которая строит бизнес вокруг расписаний, планировать работу с каждым новым маршрутом становилось дорогим удовольствием. К стандартным проблемам, как опоздания, сбои в работе или аварии, прибавилась еще одна – каждый новый маршрут кратно увеличивал затраты на перевозку.

В итоге ввели специальный стандарт времени – железнодорожное время. Синхронизировали часы в каждом городе, где проходят пути. Решение было сложным и непопулярным среди жителей городов, но в итоге в 1880 году новый стандарт обрел правовой статус.

Переведём эту историю на язык ИТ и получим, что сопровождение интеграционных стыков, каждый из которых требует уникального подхода, приводит к кратному удорожанию продукта. И цена продукта будет расти с каждой новой интеграцией. Если для одного продукта (условного поезда) это не так заметно, то для компании с десятками подключаемых модулей (условного перевозчика) – это серьезная нагрузка на бюджет.

Каждый разработчик API знает, что такое обратная совместимость, что контракт необходимо соблюдать и что в этот контракт включить, чтобы он был ожидаем потребителем. Но представьте – вы учли все Best Practices, подробно расписали суть сервиса, добились соответствия сервиса контракту API, но сроки интеграции при этом не сократились, а затраты на интеграцию остались прежними.

Попробуем разобраться.

Но сперва договоримся о терминах. В рамках текущего материала контрактом API обозначается любая цифровая информация (цифровой артефакт), который описывает программный интерфейс, его поведение и изменения во времени. Такой артефакт, в зависимости от решаемой задачи, называется API Documentation, API Specification, API Definition, API Agreements или API Reference. Однако мы, чтобы упростить картину восприятия интеграционного домена и систематизировать знания, объединим их в один термин – контракт API.

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

Сервис означает исполняемый модуль, предоставляющий точку для удаленного вызова (SOAP, REST и т.д.)

Ниже речь идет об HTTP API, но концепция применима и к другим типам.

Для погружения в контекст еще пример. Вы провели в квартиру интернет, но не имеете представление, что это такое, как настраивать роутер, что такое сети. Идеальным выходом для вас будет автоматическая настройка соединения или помощь провайдера, но это происходит не всегда. Оптимальный вариант — предоставить вам инструкцию, где написано «воткни провод, нажми кнопку, смотри картинки». И главные вопросы в этой истории про соответствия ваших действий ожидаемому результату и про полноту предлагаемой инструкции. В случае с контрактом API вопросы те же – соответствует ли сервис описанию, и все ли необходимое указано в описании?

Начнем…

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



Другими словами, цифровой продукт – это цепочка интеграций из множества разных протоколов и, соответственно, типов API – REST, RPC, SOAP и т.д. Все узлы цепи, в свою очередь, отдельные продукты со своими возможностями. А каждый узел – это история: продукта, интеграции, кода.



Спросите своих коллег-разработчиков, каким образом появился тот или иной API. Вскроется много интересного, потому что стыки эти разрабатываются, как правило, где-то быстро на коленке, где-то – кропотливо на протяжении многих месяцев.

Какая бы история ни была, без описания API она не произойдет.

С другой стороны, если история продукта привела к описанию оригинального контракта API, отличающегося от неких общепринятых индустриальных стандартов, вы получаете долгую и мучительную интеграцию. Усилий на подключение необходимо прикладывать больше.

Очевидно, что, если описание контракта понятное, полностью соответствует поведению сервиса и для него существует множество программных инструментов, количество потребителей будет расти. В таком случае время жизни сервиса ограничено только временем жизни технологии (например, SOAP).



Приведу пример описания API в OpenAPI спецификации (исходный текст: swagger.io/docs/specification/describing-request-body).



Что определяет соответствие контракта вашего API некоему стандарту? Каковы критерии соответствия контракта API этому стандарту? Достаточно ли описать сервис в OpenAPI спецификации или в GraphQL и считать, что задача выполнена?

Как и в любой задаче с неизвестными, определим ключевые объекты предметной области и события. Для этого обозначим ключевой объект API, участников интеграции, их действия и инструменты, которые обеспечивают их действия.

С точки зрения происходящих событий любая интеграция – это последовательность действий, направленных на стыковку продуктов или изменение характеристик интеграции. В этих действиях принимают участие три стороны: владелец API, поставщик API и регулятор

Регулятором является тот, кто согласует возможность интеграции: информационная безопасность, корпоративная архитектура, отдел качества, юристы и прочие службы контроля. Участник с каждой стороны выполняет некоторый набор операций, чтобы началась передача данных по каналу интеграции. Но первое действие в любой интеграции – это заявление потребителя о наличии сервиса с удаленной точкой вызова. Это заявление владелец может передать через полноценный цифровой контракт, или от руки на бумажной салфетке.



Но вне зависимости от способа описания и используемого стандарта, суть содержимого контракта API всегда одна и включает три категории информации:

  • ЧТО предоставляется (данные, функции, ресурсы);
  • КАК предоставляется (условия использования);
  • ГДЕ предоставляется (расположение).

В общем, как и с любым договором купли-продажи товара.

Если погружаться в детали, состав контракта API можно разделить на множество категорий:

  1. Атрибуты и их описание – именование, типизация (например, в зависимости от семантики);
  2. Версионирование, обратная совместимость;
  3. Условия доступности – авторизация, квоты, гранулярность, монетизация.

В зависимости от типа ваших потребителей к вашей интеграции предъявляется разный набор требований со стороны регулятора и потребителя.

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



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

Когда вы предоставляете API партнерам, он становится «лицом» вашего программного продукта. Подключение партнера всегда более чувствительный процесс, чем интеграция двух продуктов внутри одной компании. Даже если на стороне партнера такой же разработчик, как и вы, их внутренние правила производства, культура и предметная область могут сильно отличаться от вашей. На этом уровне появляются требования бизнес-модели продукта к интеграции (например, не более 1 млн запросов бесплатно), добавляется строгий контроль качества, юридический контроль и контроль информационной безопасности.

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

Рассмотрим подробнее интеграцию как последовательный процесс, а также каким образом в этом процессе участвует контракт API.

Если глобально, интеграция состоит из трех этапов: подготовка, согласование и управление.



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

Как Владелец я обязан описать сервис, сообщить или выложить его на ресурс и заявить, что к моему продукту имеется точка доступа. Все действия, начиная с момента «я решил предоставлять API» до «заявил о наличии сервиса».

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

На этом этапе контракт API закрывает потребность Владельца – «как быстрее объяснить возможности сервиса» и потребность Потребителя – «получить подробную информацию о возможности сервиса и подключиться».

Второй этап – согласование. Здесь Регулятор допускает или отклоняет интеграцию по множеству факторов – чувствительность передаваемых данных, свойства потребителя, география, бизнес-модель сервиса, модель данных и т.д.

Как Регулятор от контроля качества (QA), я должен подтвердить соответствие уровня доступности сервиса (SLA) моим требованиям. Например, если сервис приема платежей будет доступен только 50% времени, тогда только каждый второй платеж будет доходить по назначению, что в итоге может привести не только к потере репутации компании.

Как Регулятор от корпоративной архитектуры (Enterprise Architect), я должен подтвердить, что модели данных публичных сервисов идентичны. Например, если выводится еще один сервис работы с платежами, но наименование атрибутов запроса-ответа отличается от предыдущего, потребителю придется реализовать mapping параметров для работы с обоими сервисами одновременно.

Как Регулятор от информационной безопасности, я должен проверить наличие чувствительной информации в сервисе. Например, если он возвращает персональные данные, но выставлен за обычным TLS каналом, то компания может получить серьезный штраф за нарушение законов Российской Федерации (ФЗ-152).

Контракт, как описание API может и должен описывать каждую деталь в зависимости от потребности Регулятора. Эту информацию он будет искать в любом случае и подтверждать, но ее наличие в контракте кратно сокращает сроки согласования.

По факту согласования интеграции происходит получение доступа к сервису и первый вызов.

Третий этап – управление потреблением.

Хотя подключение состоялось и задача решена, у каждого участника все еще возникают вопросы, и ответить на них может только контракт API.

Как Владелец API, я хочу понять, к какой версии сервиса подключен партнер Х, а к какому – Y, чтобы определить условия потребления у этих сервисов и могу ли я их изменить.

Как Потребитель API, я хочу понимать свои права в случае нарушения SLA.

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

Если взять 1000 различных API, действия для всех участников будут типичными: заявить, ознакомиться, попробовать, согласовать, подключиться, потреблять. Чем больше похожи эти операции, тем выше вероятность их автоматизации.



При отсутствии автоматизации, операции выполняются вручную. Это означает затраты продукта и, в конечном итоге, компании. Первые два этапа – затраты на организацию стыка, третий – на поддержание стабильности.

Получается, если у вас есть некое описание API, которое не подчиняется общепринятым стандартам, не содержит ожидаемый набор информации, каждая интеграция будет требовать прохода по всем этапам от начала до конца снова и снова.



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



Вывод: стандарт необходим для унификации действий участников интеграции и сокращения их затрат. Соответствие контракта API стандарту определяется не используемым технологиям, но и по возможности унификации вне зависимости от его семантики. Чем больше работ удастся унифицировать за счет оцифровки, тем выше шанс автоматизации.

Предположим, мы осознали, что не только команда партнера хочет знать, что у вас вписано в контракте API, а еще информационная безопасность и контроль качества. Добившись типизации их работ, мы сократили сроки интеграции. Но как как определить, какие данные важны участникам и что именно ускорит процесс интеграции?

Для этого вспомним цель интеграции – выполнение некоего бизнес-процесса или получение данных. Все это выполняется вашим сервисом, запущенным в среде исполнения, и к нему у определенных лиц всегда есть требования и ожидания.



Владелец сервиса (бизнес-владелец): хочу, чтобы партнер нажатием кнопки в своем приложении мог вызвать такси;

Информационная безопасность: персональные данные только в определенно защищенном канале;

Контроль качества: доступность сервиса должна соответствовать заявленному уровню.

Как это выглядит. Рассмотрим сервис в виде пирамиды Маслоу, где каждый слой выполняет свою задачу. На нижнем уровне находится железо, сети, виртуализация – все, что отвечает за физическую (и немного программную) среду передачи данных. Этот слой определяет ширину канала и общую физическую пропускную способность. Нижний уровень фиксируется в контракте, как обязательство придерживаться ширины канала, типа шифрования, адреса хостов.

Выше инфраструктуры – архитектурный компонент продукта (исполняемый код). Этот уровень объясняет, как организовано хранение данных и какие технологии взаимодействия компонентов. Информация с него обычно указывается в соглашении в виде «разрешено выполнять не более 100 вызовов в минуту» или «вызовы полностью логируются».

Следом архитектура модели данных, или предметная область продукта. Здесь уже история про семантику сервиса, типизацию атрибутов, коды ошибок, версионирование и обратную совместимость, авторизацию. Этот уровень обычно полностью вписывается в контракт, объясняет схему запроса и ответа, технические условия подключения.

На вершине пирамиды формируется бизнес ценность – чтобы нажал кнопку, и приехало такси. Но и этот уровень обычно описывается в соглашении к сервису как описание бизнес-модели.

После того как сервис реализован, каждому участнику необходимо убедиться, что он соответствует требованиям. Обычно это подтверждаются вычиткой описания, точечными тестами или полноценным тестированием с помощью определенных инструментов, например, с помощью Postman. Но для выполнения требуемых операций Postman должен поддерживать этот вид контракта. А контракт вы не будет заполнять руками – оптимально сгенерировать его из кода.

Получается, что требования к сервису и требования к контракту API взаимозависимы и влияют друг на друга. Вы создаете сервис c определенной моделью данных и предоставляете его описание, чтобы регуляторы подтвердили его соответствие их требованиям. В случае если подтверждение выполняется «глазами», продукт несет затраты, а для автоматического подтверждения, необходимо заложить в контракт разделы, которые поддержат соответствующие инструменты.



Еще раз взглянем на процесс интеграции. Все требования к сервису в итоге выливаются в операции по их подтверждению.

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



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

Но как подтвердить, что контракт содержит необходимые данные и что сервис соответствует контракту, чтобы доверять ему?

Решение простое, как в истории с железнодорожным временем, но внедрение скорее будет крайне сложным.



Определяете необходимый состав контракта API, встраиваете его наполнение в процессы производства, контролируете соответствие контракта необходимой схеме в design time, и контролируете поведения сервиса на соответствие контракту в run time.

Разберем контроль контракта на примере OpenAPI спецификации (для подхода CodeFirst) в DesignTime:

1. Допустим у вас есть репозиторий с описанием корпоративной модели данных:
a. В нем указано, что все методы работы с платежами содержат в имени ресурса «pay», а все атрибуты, оперирующие номером счета, имеют строковый тип длиной ровно 10 символов и называются pay_number.
b. Для всех методов работы с платежами уровень доступности не менее 99%.
c. Определенным паттернам входных/выходных данных соответствует категория данных по ИБ и определенные категории могут быть доступны только за своими каналами. Например, набор из паспортных данных и ФИО однозначно определяется как персональные и могут быть доступны только за ГОСТ TLS.
d. К методам, которые возвращают скоринговую информацию, необходима расширенная авторизация по атрибутам партнера и обязательно проверка баланса при вызовы, т.к. потребление платное. Так же здесь же можно указать допустимый rate limit и т.д.
2. В процессе производства, в зависимости от названия методов и указанных переменных, в спецификацию добавляются необходимые разделы, описывающие схему авторизации, уровень доступности, категория данных;
3. На выходе получаете описанный API, который содержит необходимую информацию о потоке данных, способах авторизации и уровнях доступности. И каждый раздел контракта можно проверить и провалидировать автоматически.

Пример категоризации метода через extensions в OpenAPI


И контроль поведения сервиса контракту в режиме RunTime:
1. Организуете инфраструктуру, которая содержит элементы API Gateway, Microgateway, Observability
2. При выводе сервиса на ИТ-ландшафт, в зависимости от категории данных в аннотации, сервис прописывается за соответствующими хостами
3. В момент потребления
a. схема данных в транзакции сверяется со схемой в контракте
b. определяется уровень доступности сервиса
c. определяется интенсивность потребления сервиса
d. определяются свойства потребителя
4. И в случае несоответствия требованиям контракта, сервис будет доступен или не доступен для потребления с описанием причины

Пример валидации схемы запроса, на соответствие схеме контракта


На базе указанных операций управляется доступность сервиса – валиден или недоступен в потреблении или не доступен на витрине для подключения.



Как итог, от контроля контракта и соответствия сервиса контракту вы получаете:

  1. Сокращение времени и затрат на интеграцию (всех участников);
  2. Сокращение затрат на поддержку сервиса;
  3. Масштабирование потребителей без увеличения стоимости продукта;
  4. Источник монетизации продукта.

В случае несоблюдения контракта затраты и ошибки будут расти с каждой новой интеграцией.