- шесть записей по кластерам причин: журнал под внешним значением, нулевой код ответа в журнале, затирание вложения бедным ответом, открытый анониму адрес подтверждения почты, рубеж расшифровки без работы, пределы длительности - находка про код 500 у отказа приёма дописана в json-api-for-spa: там живёт единая точка отображения доменной ошибки - telegram-account-link и bot-api-only-through-bot-client оставлены с оговоркой, что предмета у них нет до возвращения входа
5.9 KiB
✨ Свести приём и чтение записей к одному контракту для приложения
- Тип: feature
- Категория: Очередь — Единая точка трансляции доменной ошибки — база и для экранов, и для токенов; список своих записей заводится после владельца, а не до.
- Зачем: Сегодняшний API отвечает 404 на любую ошибку чтения и 500 на любую ошибку приёма: строить на нём экраны нечем.
Экраны заводят задачу, видят её состояние и листают список — всё через один контракт.
Обработчик GET /api/status/:id сегодня отвечает 404 на любую ошибку
чтения, включая сбой базы, а POST /api/audio — 500 на любую ошибку заведения,
включая негодный файл. Экран, построенный на таком контракте, показывает «не
найдено» при упавшей базе.
Отдельная ветка того же класса найдена ревью задачи remove-telegram-intake
2026-08-15, проход сверки требований: приём отвергает пустого владельца своей
ошибкой, а транспорт переводит любую ошибку службы в 500. Спека приёма при
этом держит эту проверку ради понятного отказа — «отвечает отправителю понятным
отказом до того, как запись попадёт в память». Сегодня путь недостижим: слой
предъявления отвергает такого вызывающего раньше. Он становится достижимым вместе
с личными токенами и экранами приложения, то есть ровно здесь.
Затрагивает
POST /api/audioиGET /api/status/:id— коды ответа и форма ошибки;- новый эндпоинт списка своих записей с постраничным чтением;
- единая точка отображения доменной ошибки в код ответа — её сегодня нет (conventions/errors.md);
internal/contract— доменные ошибки под отображение;internal/controller/httpцеликом;docs/architecture.md, раздел «Единые точки проекта».
Критерии приёмки
- Код ответа отвечает причине отказа, а не месту, где он случился: сбой базы при
чтении даёт
500, а не404, негодный файл —400с человекочитаемым текстом, а не500, а отказ приёма по пустому владельцу —403, как и отказ слоя предъявления. Оракул — три теста: репозиторий, возвращающий ошибку драйвера; файл, который отвергает разбор метаданных; вызов приёма без учётной записи. - Тело ошибки одной формы на всех эндпоинтах, не содержит сырого
err.Error()и опечаткиtranscibe. Оракул — тест на четырёх ветвях отказа (форма совпадает, текста внутренней ошибки в теле нет) плюс пустойgrep -rn 'transcibe' internal/. - Список записей отдаётся страницами и упорядочен по времени создания. Оракул — тест на выборке больше страницы.
- Отображение ошибки живёт в одной функции, и она названа в
docs/architecture.md. Оракул —task gate, шагdocs.py check. - Ответ приёма отдаёт список заведённых записей и место под признак повторного файла, даже когда файл в запросе один. Оракул — тест приёма: тело ответа — список из одного элемента, у элемента есть поле признака повтора.
Рамки
Аутентификацию и владельца не заводим — это oidc-login и record-ownership;
задача про форму контракта. Публичный контракт после мерджа обратной правкой не
откатывается, и по решению владельца от 2026-08-12 форма ответа приёма
согласуется здесь один раз — сразу списком и с местом под признак повтора, —
чтобы dedup-by-content-hash, multi-file-upload и reject-oversized-recording
её не переписывали, а экран загрузки не переделывался под вторую форму. Приём
по-прежнему берёт из запроса один файл: меняется форма ответа, не число файлов.
Сюда же приехала опечатка transcibe в тексте ошибки приёма (нашёл проход review-specs на ревью change
2026-08-11-fix-http-handler-tests): в одиночку текст ошибки менять нельзя,
а здесь контракт переписывается целиком.