- шесть записей по кластерам причин: журнал под внешним значением, нулевой код ответа в журнале, затирание вложения бедным ответом, открытый анониму адрес подтверждения почты, рубеж расшифровки без работы, пределы длительности - находка про код 500 у отказа приёма дописана в json-api-for-spa: там живёт единая точка отображения доменной ошибки - telegram-account-link и bot-api-only-through-bot-client оставлены с оговоркой, что предмета у них нет до возвращения входа
65 lines
5.9 KiB
Markdown
65 lines
5.9 KiB
Markdown
# ✨ Свести приём и чтение записей к одному контракту для приложения
|
||
|
||
- **Тип:** 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](../../docs/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`): в одиночку текст ошибки менять нельзя,
|
||
а здесь контракт переписывается целиком.
|