ADR 0015: браузерный UI на отдельном origin
Статус: accepted. Дата: 2026-09-23.
Контекст
Native API, Bearer-авторизация, repository ACL и portable SDK уже существуют. Встроенная консоль была привязана к location.origin, а браузерный UI на другом сервере не мог пройти preflight для заголовка Authorization. Нужна работа внешнего UI без общего доступа к БД и без ослабления проверки токена.
Решение
ARKVORY_CORS_ORIGINSзадаёт не более 16 точных origins внешних UI. По умолчанию список пуст. Разрешён HTTPS; HTTP только для loopback-разработки. При старте API проверяет конфигурацию и отклоняет wildcard, пути, query, credentials и неподходящую схему.- CORS применяется к native
/api/v1/*и/health/ready, включая ошибки авторизации.OPTIONSдля разрешённого origin обрабатывается до Bearer. Методы, заголовки и открываемые заголовки ответа фиксированы в API_CONTRACTS. Ответ содержит конкретный origin иVary; cookies/credentials не разрешаются. Запрос с чужим origin получает 403. Запросы без Origin сохраняют прежнее поведение. - Каждая обычная операция по-прежнему проверяет Bearer и права на сервере. Сервисный ключ ограничивается репозиториями и правами; пользовательская сессия использует группы. CORS не является правом доступа.
- Встроенная консоль читает необязательный
arkvory-api-base-urlиз HTML meta, по умолчанию использует текущий origin. Это позволяет разместить статические файлы на отдельном HTTPS-сервере без изменения SDK или API маршрутов.
После браузерной проверки добавлено уточнение: запросы встроенной консоли с тем же Host пропускаются CORS-фильтром и проходят обычную Bearer/ACL-проверку даже при пустом списке внешних origins. Reverse proxy должен сохранять исходный Host. Иной порт требует явного разрешения в ARKVORY_CORS_ORIGINS.
Альтернативы
Проксировать все запросы через сервер UI можно и сейчас, но это заставляет оператора реализовать безопасную передачу токена и потоков. Разрешать произвольные origins с wildcard и доверять браузеру проверку ACL нельзя. Cookie-сессии для cross-origin UI потребовали бы отдельной модели CSRF и управления cookies.
Последствия
Миграция БД не требуется. Разрешённый сайт, включая внедрённый в него сторонний скрипт, сможет отправлять запросы с токеном, которым владеет этот UI; оператор отвечает за безопасность своего origin и Content Security Policy. При ошибке origin страница получит сетевую CORS-ошибку; неверный токен даст обычный API-ответ с request ID. Сервисные ключи и сессии не передаются в URL или cookies. Подробный порядок развёртывания — EXTERNAL_UI.
Проверка
Unit-тесты проверяют нормализацию и отклонение небезопасных origins. Интеграционные HTTP-тесты проверяют preflight без Bearer, разрешённые и запрещённые origins, доступность ошибок авторизации и прежнее поведение запросов без Origin. Консоль проверяется на широком и узком экране с фильтрами и переходами страниц.