Перейти к основному содержимому

GET /api/messenger/recordings/{recordingId} — Карточка записи

Метаданные одной записи по её идентификатору — проекция CallRecordingEntity (дом полей, статусы, инварианты — там). Возвращает состояние и характеристики файла, но не ссылку на скачивание: ссылка выдаётся отдельным методом get-recording-download.md.

Назначение

Дать участнику сессии-владельца (1:1-звонка или конференции) карточку записи: статус жизненного цикла, модальность, длительность/размер/формат готового файла. Метод универсален по типу сессии — авторизация различается по SessionKind. Owning-сервис — messenger, feature group recordings.

Metadata

ПолеЗначение
Сервис/контекстmessenger
API arearecordings
Feature grouprecordings
Статусdraft
Документdocs/06-services/messenger/api/recordings/get-recording.md

Актор и доступ

ПроверкаЗначение
Actor typeUser — участник сессии-владельца записи
Auth policy / Permissionspermission messenger.recordings.view
Scope (RBAC)не применяется (доступ — по участию в сессии)
Record-levelDirect: actor.UserId ∈ {CallerUserId, CalleeUserId} звонка; Conference: активное членство в ChatId конференции (INV-CHAT-4)
Tenant isolationнет (кросс-tenant); изоляция — по участию/членству
Auditread (нечувствительный): карточка без FileId-ссылки/URL; скачивание — отдельный аудируемый метод

HTTP-контракт

ПолеЗначение
MethodGET
Route/api/messenger/recordings/{recordingId}
Success status200 (OK)
Idempotency headerне применяется (чтение)
Correlationсквозной trace через traceparent

Входные данные / параметры запроса

ПолеИсточникТипОбязательностьВалидация / ОграниченияБезопасность
RecordingIdrouteGuidДа!= Empty; существующая запись, актор — участник её сессии (шаги 3–4)
ActorUserIdidentity claimsGuidДаиз JWT; участник сессии-владельца

Модель ответа RecordingModel

Проекция CallRecordingEntity (дом — сущность). FileId присутствует только при Status == Available (INV-REC-6); ссылки/URL модель не несёт.

ПолеТипОбязательностьИсточникMaskingОписание
RecordingIdGuidДаCallRecordingEntity.IdИдентификатор записи.
SessionKindSessionKindДа.SessionKindDirect / Conference.
SessionIdGuidДа.CallSessionId / .ConferenceSessionIdСессия-владелец.
ChatIdGuid?Нет.ChatIdDeal-чат (для конференций); null для 1:1.
DealIdGuid?Нет.DealIdСделка (для конференций).
StatusRecordingStatusДа.StatusPending/Recording/Uploading/Available/Failed/Deleted.
TriggerRecordingTriggerДа.TriggerAutoPolicy/Manual.
MediaTypeCallMediaTypeДа.MediaTypeAudio/Video.
FileIdGuid?Нет.FileIdСсылка на бинарь; задан только при Available.
DurationSecondsint?Нет.DurationSecondsДлительность; null до Available.
SizeByteslong?Нет.SizeBytesРазмер файла; null до Available.
FormatRecordingFormat?Нет.FormatКонтейнер (Mp4/Webm/Mkv/Mp3); null до Available.
StartedAtDateTimeOffset?Нет.StartedAtПодтверждённый старт захвата.
EndedAtDateTimeOffset?Нет.StoppedAtОстановка захвата.
CreatedAtDateTimeOffsetДа.CreatedAtМомент провизии записи.

Скачивание бинаря — через get-recording-download.md (короткоживущий пресайн, аудит ReadSensitive).

Алгоритм

  1. Контекст и доступ. Операцию выполняет участник сессии-владельца (User); ActorUserId — из JWT; требуется право messenger.recordings.view. Запись включена флагом RECORDINGS_ENABLED, иначе MSG_RECORDINGS_DISABLED.
  2. Проверка входа. RecordingId непустой; иначе ошибка валидации.
  3. Загрузка записи. Запись по RecordingId; нет → MSG_RECORDING_NOT_FOUND. Читаем SessionKind и ссылку на сессию-владельца.
  4. Право (по типу сессии). Direct — актор ∈ {Caller, Callee} звонка; Conference — актор активный член ChatId конференции (INV-CHAT-4). Иначе → MSG_RECORDING_FORBIDDEN (либо MSG_RECORDING_NOT_FOUND для сокрытия чужой записи). Для Conference право проверяется по актуальному членству: участник, исключённый из Deal-чата (RemovedAt проставлен), доступ к карточке теряет, даже если присутствовал на встрече; новый член чата, добавленный после встречи, карточку видит (история команды сделки).
  5. Результат. RecordingModel; FileId отдаётся только при Status == Available; в неконечных (Pending/Recording/Uploading) и терминальных Failed/Deletednull (INV-REC-6), ссылки/URL нет → HTTP 200 OK. Терминалы возвращаются как есть (статус Failed/Deleted), а не как 404, — UI показывает «запись не удалась»/«запись удалена». Снимок — на момент чтения: если запись конкурентно переходит в Available, новое состояние (с FileId) актор увидит при следующем запросе (freshness — по факту чтения, не подписка).

Ошибки и failure modes

КодHTTP statusУсловиеСообщениеRetry
VALIDATION_FAILED400RecordingId = Empty«Проверьте параметры запроса»no retry
MSG_RECORDING_NOT_FOUND404записи нет или актор не участник сессии (сокрытие)«Запись не найдена»no retry
MSG_RECORDING_FORBIDDEN403актор не участник сессии-владельца«Недостаточно прав»no retry
MSG_RECORDINGS_DISABLED503RECORDINGS_ENABLED = false«Записи временно недоступны»retry позже

Acceptance Criteria

  • Given запись Available и актор — участник её сессии, When запрашивает карточку, Then 200 с RecordingModel, где заполнены FileId, DurationSeconds, SizeBytes, Format; ссылки на скачивание в ответе нет (скачивание — отдельным методом).
  • Given запись в неконечном статусе (Pending/Recording/Uploading), When участник запрашивает карточку, Then 200 со статусом текущего этапа и FileId = null.
  • Given запись в терминале Failed/Deleted, When участник запрашивает карточку, Then 200 с соответствующим статусом и FileId = null (не 404) — клиент отражает исход.
  • Given актор не участник сессии-владельца, When запрашивает карточку, Then 404 MSG_RECORDING_NOT_FOUND (чужая запись неотличима от несуществующей).
  • Given актор был участником встречи, но исключён из Deal-чата конференции, When запрашивает карточку, Then 403 MSG_RECORDING_FORBIDDEN/404 MSG_RECORDING_NOT_FOUND (доступ — по актуальному членству).
  • Given RECORDINGS_ENABLED = false, When любой запрос, Then 503 MSG_RECORDINGS_DISABLED.

Совместимость и наблюдаемость

  • Новые optional-поля — additive; удаление/смена типа — breaking. Kafka-контракта нет.
  • Logs: recording fetched (RecordingId, Status, участник); metrics: messenger_recording_get_total{result}, latency p95; correlation через traceparent; FileId/URL/бинарь в логи не пишутся.

Обратные ссылки

Автоссылки: где используется этот документ.

Связанные документы