API
Обзор
Слой API с самого начала служит границей между runtime (веб-клиентом), состоянием комнаты и медиасервисами. Контракты M0 намеренно узкие, а их версии задаёт схема манифеста.
Эндпоинты
GET /health
Возвращает признак того, что сервис работает (liveness). Нужен для smoke-проверок локально и на staging.
Ответ:
{
"status": "ok",
"service": "api",
"port": 4000
}
GET /api/rooms/:roomId/manifest
Возвращает манифест комнаты, который runtime читает при запуске.
Структура ответа:
{
"schemaVersion": 1,
"tenantId": "demo-tenant",
"roomId": "demo-room",
"template": "meeting-room-basic",
"features": {
"voice": true,
"spatialAudio": true,
"screenShare": false
},
"quality": {
"default": "desktop-standard",
"mobile": "mobile-lite",
"xr": "xr"
},
"access": {
"joinMode": "link",
"guestAllowed": true
}
}
POST /api/tokens/state
Возвращает короткоживущий подписанный токен сессии комнаты. Его используют runtime, apps/room-state и выдача медиатокенов.
Запрос:
{
"roomId": "demo-room",
"participantId": "p1",
"displayName": "Guest",
"requestedRole": "guest"
}
Ответ:
{
"token": "base64url-payload.hmac-signature",
"expiresInSeconds": 900,
"sessionId": "session-id",
"role": "guest",
"permissions": ["room.join", "audio.join", "surface.view"]
}
Подписанная полезная нагрузка содержит claims tenantId, roomId, participantId, displayName, role, необязательный roleSource, permissions, sessionId, iat, exp и jti. При проверке токена сервер приводит права в соответствие с подписанной ролью.
POST /api/tokens/media
Возвращает данные токена для подключения к медиаплоскости LiveKit.
Требует заголовок Authorization: Bearer <room-session-token>. Токен сессии должен относиться к запрошенным комнате и участнику. Разрешения на публикацию API выводит из подписанных прав комнаты и не доверяет ролям, которые передал вызывающий.
Запрос:
{
"roomId": "demo-room",
"participantId": "p1",
"canPublishAudio": true,
"canPublishVideo": false
}
Тот же токен сессии нужен и эндпоинтам, которые меняют данные runtime:
PUT /api/rooms/:roomId/presence/:participantIdDELETE /api/rooms/:roomId/presence/:participantIdPOST /api/rooms/:roomId/diagnosticsPUT /api/rooms/:roomId/xr-telemetry/:participantIdPOST /api/tokens/remote-browser-frame
Ответ:
{
"token": "base64url-encoded-payload",
"expiresInSeconds": 900,
"livekitUrl": "ws://localhost:7880"
}
Аутентификация и авторизация в control plane
Защищённые действия control plane по умолчанию запрещены. Для них нужен либо x-vrata-admin-token: <CONTROL_PLANE_ADMIN_TOKEN>, либо Authorization: Bearer <room-session-token>.
Оператора или администратора удостоверяет только заголовок с CONTROL_PLANE_ADMIN_TOKEN. Подписанные токены сессии комнаты разрешают лишь явно допущенные действия в пределах комнаты; роль admin в сессии комнаты не считается администратором control plane.
Действия ведущего в control plane требуют доверенного источника роли в сессии комнаты. Токены, выпущенные в режиме dev-ролей через query-параметр, годятся для runtime, но для действий ведущего в control plane отклоняются.
Если идентификация не передана, возвращается 401 с reason: "missing_identity". Если идентификация верна, но заявленного права нет, возвращается 403 с reason: "permission_denied".
Текущая матрица прав описана в docs/security/permissions.md. Защищены такие группы эндпоинтов:
- запись тенантов
- создание, изменение и удаление комнат
- привязка пакета сцены ведущим к своей комнате
- запись ассетов
- запись пакетов сцен
- чтение XR-телеметрии администратором или ведущим своей комнаты
- чтение аудита control plane
Каждое решение об авторизации защищённого действия попадает в аудит control plane с полями requestId, actor, action, object, permission и result. Операторы могут просмотреть журнал в памяти ограниченного размера через GET /api/audit/control-plane, если передадут идентификацию администратора.
Документы комнаты и медиа для показа
GET /api/rooms/:roomId/documentsтребуетdocument.view.POST /api/rooms/:roomId/documentsтребуетdocument.upload. Загружаемые PDF, PNG, JPEG, WebP, MP4 и WebM проверяются до сохранения. Размеры изображений сервер читает сам; у видео он определяет контейнер по содержимому, а размеры и длительность, которые прочитал браузер, ограничивает своими пределами.GET /api/rooms/:roomId/documents/:documentId/downloadтребуетdocument.downloadи отдаёт файл как вложение.POST /api/rooms/:roomId/documents/:documentId/surfaceтребуетdocument.present; привязать можно только прошедшие проверку PDF, изображения и видео.GET /api/rooms/:roomId/documents/:documentId/presentationтребуетsurface.viewи отдаёт PDF для встроенного просмотра, только пока документ привязан. Им пользуются зрители в комнате, в том числе гости.GET /api/rooms/:roomId/documents/:documentId/contentтребуетsurface.viewи отдаёт байты изображения или видео ограниченного размера, только пока документ привязан.DELETE /api/rooms/:roomId/documents/:documentIdтребуетdocument.delete: через внутренний API сервиса состояния комнаты убирает соответствующие активные объекты PDF, изображений и видео, удаляет blob и мягко удаляет метаданные.
Право document.present есть у ролей presenter, host и у операторской роли admin. Участники и гости могут только смотреть показ, но не управлять им. Изображения ограничены 16 384 пикселями по каждой стороне и 67 млн пикселей в сумме, видео — четырьмя часами. Общий предел размера загрузки для PDF, изображений и видео задаёт DOCUMENT_UPLOAD_MAX_BYTES, а число страниц — PDF_PRESENTATION_MAX_PAGES. Видео намеренно отдаётся из того же blob загрузки ограниченного размера: адаптивного стриминга и перекодирования нет.
Примечания
- Токены сессии комнаты подписываются секретом
STATE_TOKEN_SECRET, срок их действия задаёт claimexp. - Повышать роль через
requestedRoleдля разработки можно только при включённом режиме dev-ролей через query-параметр; в конфигурациях для production он выключен. schemaVersionдолжен быть явно указан в каждом манифесте.- Если медиа или XR-функции недоступны, runtime должен продолжать работу с урезанными возможностями.
Права control plane
Способы идентификации
Защищённые действия control plane принимают один из двух способов идентификации:
x-vrata-admin-token: <CONTROL_PLANE_ADMIN_TOKEN>— для администрирования оператором при самостоятельном запуске.Authorization: Bearer <room-session-token>— для участников с подписанной сессией комнаты, которую выдалPOST /api/tokens/state.
Без идентификации возвращается 401. Недействительный токен тоже даёт 401. Верная идентификация без нужного права даёт 403.
Права ведущего в сессии комнаты требуют доверенного источника роли в подписанном токене. Токены, выпущенные в режиме dev-ролей через query-параметр (?role=host / requestedRole=host), годятся для runtime, но для действий ведущего в control plane не считаются доверенными.
Матрица прав
| Право | Группа эндпоинтов | Токен администратора | Сессия ведущего в комнате | Участник | Гость |
|---|---|---|---|---|---|
tenant.write |
POST/PATCH/DELETE /api/tenants |
да | нет | нет | нет |
room.create |
POST /api/rooms |
да | нет | нет | нет |
room.update |
PATCH /api/rooms/:roomId |
да | нет | нет | нет |
room.bind-scene-bundle |
POST /api/rooms/:roomId/bind-scene-bundle |
да | только своя комната | нет | нет |
room.delete |
DELETE /api/rooms/:roomId |
да | нет | нет | нет |
asset.write |
POST/PATCH/DELETE /api/assets |
да | нет | нет | нет |
scene-bundle.write |
эндпоинты пакетов сцен: создание, версии, статус, текущая версия | да | нет | нет | нет |
xr-telemetry.read |
GET /api/rooms/:roomId/xr-telemetry |
да | только своя комната | нет | нет |
audit.read |
GET /api/audit/control-plane |
да | нет | нет | нет |
Подписанные роли сессии комнаты не удостоверяют оператора. Токен сессии комнаты с ролью admin всё равно не получает административных прав control plane, если в запросе нет заголовка CONTROL_PLANE_ADMIN_TOKEN.
Эндпоинтов для жизненного цикла ссылок-приглашений в текущем API нет. Закрытый доступ к комнатам, а также создание, отзыв и использование приглашений относятся к VRATA-FEAT-014. Когда эти эндпоинты появятся, они должны объявлять явные права и писать записи в аудит control plane.
Публичные эндпоинты runtime
Эндпоинты для запуска runtime и чтения данных публичны намеренно и не должны менять состояние тенантов или комнат:
GET /health,GET /health/live,GET /health/ready,GET /metrics- статические ассеты runtime и control plane
GET /api/templatesGET /api/assetsGET /api/tenantsGET /api/roomsGET /api/rooms/:roomIdGET /api/rooms/:roomId/manifestGET /api/rooms/:roomId/spacesGET /api/rooms/:roomId/presenceGET /api/rooms/:roomId/diagnostics- эндпоинты списка и чтения пакетов сцен
Журнал аудита
Каждое решение об авторизации защищённого действия control plane записывается структурированным событием аудита в stdout и в журнал в памяти ограниченного размера, доступный для просмотра.
Записи аудита содержат:
requestIdactionpermissionobject.typeи необязательныйobject.idresult(allowedилиdenied)reasonдля отклонённых запросовactorбез исходных токенов и секретов
Чтобы сопоставить запросы клиента с записями аудита, используйте x-request-id.
Источник: docs/api-contracts.md, docs/security/permissions.md в vrata-labs/platform на ревизии 380b2e7ff1dd, лицензия Apache-2.0. GitHub