Skip to content

0045. Только нативный API без совместимости с внешними протоколами ​

Статус: accepted. Дата: 2026-09-30. Заменяет ADR 0010.

Контекст ​

Arkvory развивается как самостоятельное хранилище артефактов с собственным API /api/v1, SDK и CLI arkvoryctl. Кроме него сервер публиковал поднабор скачиваний в формате внешнего протокола: три семейства маршрутов вне /api/v1, catch-all пути, отдельный пакет адаптеров и две дополнительные схемы аутентификации, действовавшие только для этих маршрутов. Поднабор не проверялся на реальных клиентах, ошибки оставались native, а поддержка требовала отдельных правил CORS, inventory и документации ограничений.

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

Решение ​

  • Удалить пакет адаптеров внешнего протокола и маршруты /api/packages/{repository}/download, /upack/{repository}/download/..., /endpoints/{repository}/content/.... Тег OpenAPI Legacy и область compatibility каталога операций удаляются.
  • Удалить аутентификацию заголовком X-ApiKey и Authorization: Basic с именем api. Все защищённые операции принимают только Authorization: Bearer: managed и file-based сервисные ключи, пользовательские сессии.
  • Перенести сценарии скачивания по идентичности в нативный API:
    • GET|HEAD /api/v1/repositories/{repository}/packages/content?group=&name=&version= — точная версия UPack; без version — старшая SemVer-версия (после ADR 0047 — старшая стабильная, prerelease только явно). operationId downloadPackageContent.
    • GET|HEAD /api/v1/repositories/{repository}/asset/content?path= — текущая ревизия файла по пути. operationId downloadAssetContent.
  • Оба маршрута на каждом запросе разрешают один неизменяемый артефакт и далее используют тот же путь выдачи, что GET|HEAD .../artifacts/{id}/content: право content.read (для file keys и групп — coarse read), admission, bandwidth, content pins, Range/ETag/If-Range, 304/416. Операции относятся к области transfers и, как остальные GET/HEAD, доступны на reader.
  • Публичный контракт /api/v1, OpenAPI и SDK далее меняются аддитивно либо через ADR; поддержка проверяется собственными SDK/CLI и фикстурами с известным происхождением.

Альтернативы ​

  • Сохранить поднабор: остаются непроверенная поверхность, дополнительные схемы аутентификации и обязательство следовать чужому контракту.
  • Расширить совместимость до публикации и каталога: большой объём работы без подтверждённого сценария и стенда, противоречит позиционированию самостоятельного продукта.
  • Оставить прежние адреса как псевдонимы нативных маршрутов: сохраняет catch-all пути и дополнительные схемы аутентификации без пользы для новых клиентов.

Последствия ​

  • Безопасность: одна схема аутентификации вместо трёх; ключ больше не передаётся в Basic или отдельном заголовке; нет маршрутов вне /api/v1 и /health и исключений из CORS-контракта. Поверхность атаки и объём проверок уменьшаются.
  • Клиенты внешнего протокола больше не поддерживаются; интеграции используют native API, SDK или arkvoryctl. Переходный период не предусмотрен: продукт ещё не используется в установках (ADR 0040).
  • Схема БД, данные, ACL и permissions не меняются. Число операций и версия OpenAPI меняются; snapshot inventory обновляется вместе с кодом.
  • latest и путь файла разрешаются заново на каждом запросе, поэтому URL не закрепляет объект. Для докачки клиент использует If-Range с полученным ETag либо скачивание по artifact ID.
  • Импорт подготовленного каталога сохраняется (MIGRATION). Инструменты миграции из внешних репозиториев артефактов могут быть добавлены позднее отдельным решением, без возврата совместимости протокола.

Проверка ​

  • Contract guard и snapshot tests/fixtures/api-operations.json: удалённые маршруты отсутствуют, новые операции описаны с правами, retry и gateway metadata.
  • PostgreSQL/HTTP: exact и latest при каталоге более 1000 версий, отсутствующие версия или путь, те же байты и ETag, что у artifacts/{id}/content, Range/If-Range, content.read без права перечисления, reader, общий bandwidth, обрыв при усечении blob.
  • Прежние схемы аутентификации не принимаются: запрос без Bearer получает 401.

Arkvory · ProAnimaStudio