- шаг схемы закрывает поверхность, которую хранилище приносит открытой: собственную регистрацию, вход по паролю и одноразовый код — без этого закрытие приёма обходилось двумя запросами - продление сессии выключено, срок семь суток: иначе отзыв доступа у провайдера до сервиса не доходит никогда - файл записи отдаётся вошедшему по токену файла — пересмотр ADR-2026-08-12-file-link-open-but-not-logged
7.0 KiB
MODIFIED Requirements
Requirement: Приём записи по HTTP
Сервис SHALL принимать запись от внешней программы запросом POST /api/audio с
телом multipart/form-data и полем audio только от узнанного отправителя.
Запрос без сессии MUST получать код 401, и по нему MUST не заводиться ни файл,
ни задача расшифровки. Принятая запись от узнанного отправителя MUST быть
сохранена и получить заведённую под неё задачу расшифровки в состоянии
created; ответ MUST нести идентификатор задачи полем job_id и её состояние
полем status.
Отказ по отсутствию сессии наступает раньше чтения тела: запись, за которую не заплатит узнанный отправитель, не должна попасть даже в память.
Имена полей ответа нормативны: контракт HTTP API объявлен проектом необратимым, и переименование поля ломает внешнюю программу молча. Появление отказа без сессии — намеренная ломка этого контракта: до неё приём стоял открытым наружу.
Приём не судит о годности записи сам: расширение он берёт из имени файла, а пригодность содержимого узнаёт у источника метаданных.
Куда именно ложится принятая запись, приёму не принадлежит: раскладку выбирает
хранилище, и нормирует её capability storage.
Владельца у принятой записи приём не заводит: после входа видно ровно то же, что видно было анонимно.
Scenario: Запись принята
- GIVEN источник метаданных читает запись и отдаёт её длительность
- AND отправитель предъявил сессию
- WHEN программа шлёт
POST /api/audioс полемaudio - THEN ответ имеет код
201, а в теле лежат непустойjob_idиstatusсо значениемcreated - AND содержимое записи целиком лежит в хранилище одним файлом
Scenario: Сессии нет
- WHEN программа шлёт
POST /api/audioс полемaudioбез сессии - THEN ответ имеет код
401 - AND ни файла, ни задачи не заводится
- AND тело ответа не несёт данных задачи
Scenario: Поля с записью нет
- GIVEN отправитель предъявил сессию
- WHEN программа шлёт
POST /api/audioбез поляaudio - THEN ответ имеет код
400и сообщение об отсутствии записи - AND ни файла, ни задачи не заводится
Scenario: Размеру записи приём не судья
- GIVEN источник метаданных читает запись и отдаёт её длительность
- AND отправитель предъявил сессию
- WHEN программа шлёт запись нулевой длины
- THEN ответ имеет код
201: собственного порога по размеру у приёма нет
Requirement: Опрос готовности задачи
Сервис SHALL отдавать состояние задачи расшифровки по запросу
GET /api/status/:id только узнанному отправителю. Запрос без сессии MUST
получать код 401, и тело такого ответа MUST не нести ни состояния задачи, ни
текста расшифровки. Ответ узнанному отправителю MUST нести идентификатор полем
job_id, состояние полем status и время заведения полем created_at, а текст
расшифровки полем transcription_text, и это поле MUST отсутствовать в ответе,
пока текста нет: пустая строка на месте отсутствующего текста читается как
«расшифровка пуста».
Отказ без сессии MUST не зависеть от того, есть такая задача или нет: иначе по кодам ответа перебирается список заведённых задач.
Выборку по владельцу опрос не сужает: узнанный отправитель видит любую задачу по её идентификатору ровно как прежде. Сужение придёт отдельной задачей.
Scenario: Задача найдена
- GIVEN отправитель предъявил сессию
- WHEN программа спрашивает состояние заведённой задачи
- THEN ответ имеет код
200и несётjob_id,statusиcreated_at
Scenario: Сессии нет
- WHEN программа спрашивает состояние заведённой задачи без сессии
- THEN ответ имеет код
401 - AND тело ответа не несёт ни состояния задачи, ни текста расшифровки
Scenario: Без сессии неизвестная задача неотличима от заведённой
- WHEN программа без сессии спрашивает состояние заведённой задачи, а затем состояние по неизвестному идентификатору
- THEN оба ответа имеют код
401
Scenario: Расшифровки ещё нет
- GIVEN отправитель предъявил сессию
- WHEN программа спрашивает состояние задачи, которая ещё не дошла до текста
- THEN поля
transcription_textв ответе нет вовсе
Scenario: Задачи с таким идентификатором нет
- GIVEN отправитель предъявил сессию
- WHEN программа спрашивает состояние по неизвестному идентификатору
- THEN ответ имеет код
404и сообщение о ненайденной задаче