API gateway: маршрутизация по tenant без смешения данных
Запрос «API gateway для OpenAI маршрутизация по tenant» решается в приложении: tenant определяется из вашей сессии, затем server-side policy выбирает только разрешённый маршрут и предел. RussiaAPI — независимый сторонний API gateway; статья не является заявлением об официальном OpenAI API, изоляции данных поставщика или доступности модели.
Не берите tenant из тела запроса
Идентификатор tenant, роль и окружение должны возникать из аутентифицированной серверной сессии или проверенного внутреннего контекста. Поле в JSON, query string или браузерном local storage не является доказательством принадлежности. Если клиент может подставить чужой tenant, он может увидеть не только неправильный маршрут, но и неверную политику доступа.
Сделайте сервер единственным местом, где сопоставляются пользователь, проект и локальная policy. Клиент передаёт задачу, но не выбирает произвольный account scope, ключ или разрешение. При отсутствии контекста остановите запрос с понятной ошибкой приложения; не назначайте «tenant по умолчанию» и не пытайтесь угадать владельца по имени модели.
Разделите права, модели и квоты
Одна таблица «tenant → модель» редко достаточно безопасна. Отдельно задайте допустимые действия, список проверенных model alias, предел конкурентности и правило review. Например, тестовый tenant может выполнить только синтетический запрос, а production-проект — пройти дополнительную проверку роли. Эти правила принадлежат вашему продукту, а не внешнему маршруту.
Не выдавайте локальную allowlist за каталог, цену или гарантию качества. Каталог и контракт могут измениться; перед включением нового alias проведите небольшой тест и сохраните дату решения. Если alias неизвестен policy, сервер не должен молча заменять его на другой: верните безопасный отказ или направьте запрос оператору.
Передавайте наружу минимум контекста
Маршрутизация по tenant не требует помещать имя клиента, права или внутренние метки в prompt. Для локального адаптера часто достаточно своей конфигурации соединения и обезличенного operation ID. Любой дополнительный заголовок или поле должен иметь конкретную цель, документацию и срок хранения в вашей системе.
Никогда не используйте один tenant как оправдание для доступа к данным другого. Разделяйте журнал и счётчики по внутренней области, проверяйте доступ на каждой операции и не пишите ключи в диагностические сообщения. Если требуется разбор инцидента, сохраните безопасную категорию решения, а не полный пользовательский текст и не авторизационные заголовки.
Ограничьте параллельность до вызова
Локальный лимит конкурентности защищает очередь приложения и делает отказ предсказуемым. Он не равен внешнему rate limit, остаткам, SLA или резерву мощности. Счётчик должен быть атомарным в вашей инфраструктуре и освобождаться только по известному завершению либо контролируемому истечению локального lease.
При timeout не уменьшайте счётчик на основании предположения, что работа не началась. Зафиксируйте unknown, сохраните operation ID и сверяйте локальное состояние безопасным способом. Для side effect применяйте собственную идемпотентность и ручную проверку вместо нового запроса с теми же данными.
Проверьте отрицательные сценарии
На staging протестируйте пустой tenant, tenant другого пользователя, запрещённый alias, превышение локального лимита и повтор одного operation ID. Каждый случай должен завершаться до сетевого вызова или требовать review. Это важнее красивого happy path: именно отрицательные тесты показывают, что policy не смешивает роли и проекты.
Продолжите с ролями доступа проекта, лимитом параллельных запросов и policy выбора модели. Это материалы о локальном управлении приложением, а не подтверждение функций внешнего поставщика.
Начните с локальной границы
До интеграции определите, какое решение остаётся за приложением: доступ пользователя, разрешённая модель, схема результата или публикация побочного действия. Ответ модели, HTTP-статус и имя маршрута не заменяют это решение. Явная граница не даёт превратить пример кода в несуществующую гарантию поставщика.
Проверяйте логику синтетическим сценарием с обезличенными значениями. Не помещайте в fixture настоящий prompt, вложение, cookie, заголовок Authorization или чужой ключ. Для журнала обычно достаточно времени, версии адаптера, локального operation ID, категории исхода и хэша нормализованной структуры.
Тестируйте изменения на staging
Минимальный тест различает корректный ответ, ошибку валидации, отказ в доступе, временную сеть и неизвестный итог. Для каждого состояния заранее назначьте действие: остановка, ручной review или безопасное повторение. Бесконечный retry не исправляет неверный контракт и не доказывает, что внешняя операция не была выполнена.
Фиксируйте дату, версию клиента и условия теста. Если меняются SDK, каталог или формат ответа, повторите небольшой контрактный тест до расширения трафика. Один удачный вызов показывает только наблюдаемый сценарий в конкретной конфигурации, а не постоянную совместимость или качество модели.
Минимизируйте технические данные
Не записывайте в логи секреты, полный пользовательский текст, media URL и сырой ответ, если они не нужны для диагностики. Отделите короткое пользовательское сообщение от защищённой серверной записи. Доступ к журналу ограничьте ролями, а срок хранения задайте локальной политикой и классификацией данных.
Пример ниже выполняет только локальную проверку: он не вызывает сеть, не содержит ключей и не подтверждает поддержку endpoint. Используйте только собственный ключ RussiaAPI на сервере и сверяйте актуальный контракт и каталог в аккаунте перед реальным вызовом.
Сохраняйте обратимый путь
Новый маршрут, лимит или обработчик включайте так, чтобы его можно было отключить без изменения пользовательских данных. Оставьте известный безопасный сценарий, короткую запись решения и критерий остановки. Если статус неясен, направьте операцию на review вместо повторной отправки или автоматического действия.
Это не обход правил, ограничений или условий поставщика. Напротив, обратимый rollout помогает команде соблюдать свои процедуры и остановиться при расхождении контракта. Не заявляйте пользователю итог, цену или доступность, пока они не подтверждены вашим текущим разрешённым маршрутом.
Безопасный server-side пример
Этот пример не делает сетевой вызов, не содержит реальных ключей и не подтверждает доступность endpoint. Перед подключением сверяйте актуальный контракт, каталог и условия своего аккаунта.
export function chooseTenantRoute({ session, requestedAlias, running }) {
if (!session?.tenantId || !session.roles?.includes('api:invoke')) return { ok: false, code: 'forbidden' };
const policy = session.policy;
if (!policy?.aliases?.includes(requestedAlias)) return { ok: false, code: 'alias_not_allowed' };
if (!Number.isSafeInteger(running) || running >= policy.maxConcurrent) return { ok: false, code: 'local_concurrency_limit' };
return { ok: true, route: { tenantId: session.tenantId, alias: requestedAlias, operationState: 'pending' } };
}Источники и границы
OWASP Authorization Cheat Sheet · OpenAI API documentation
Источники описывают общие инженерные принципы. Они не подтверждают, что конкретная возможность включена у RussiaAPI или в вашем аккаунте. Соблюдайте применимые правила и не передавайте секреты в браузер или лог.
FAQ
Можно ли передать tenant из браузера?
Нет, браузерное поле не доказывает принадлежность. Tenant и роль лучше получать из проверенной server-side сессии или внутреннего контекста, затем сверять их на каждой операции.
Это лимит RussiaAPI?
Нет. Описанный предел конкурентности — локальная политика вашего приложения. Он не сообщает лимит, остаток, цену или SLA какого-либо внешнего маршрута.
Нужно ли писать tenant в prompt?
Обычно нет. Для маршрутизации используйте локальную конфигурацию и обезличенный operation ID. Не добавляйте в prompt внутренние права, ключи или данные другого проекта.
Следующий шаг
Откройте RussiaAPI, подтвердите маршрут в своём аккаунте и проверьте синтетический сценарий на staging. Затем продолжите с материалами: Роли доступа проекта · Лимит параллельных запросов · Policy выбора модели.