tasks: заведён урожай ревью remove-telegram-intake
- шесть записей по кластерам причин: журнал под внешним значением, нулевой код ответа в журнале, затирание вложения бедным ответом, открытый анониму адрес подтверждения почты, рубеж расшифровки без работы, пределы длительности - находка про код 500 у отказа приёма дописана в json-api-for-spa: там живёт единая точка отображения доменной ошибки - telegram-account-link и bot-api-only-through-bot-client оставлены с оговоркой, что предмета у них нет до возвращения входа
This commit is contained in:
@@ -95,4 +95,10 @@
|
||||
- [🔬 Уведомление SpeechKit о готовности вместо опроса](items/speechkit-callback-fit.md) — Шаг проверки дёргает операцию раз в 5 секунд всё время распознавания: часовая запись даёт порядка 720 обращений к платному сервису вместо одного ответа.
|
||||
- [✨ Считать объём, минуты и расход по каждому пользователю](items/usage-accounting.md) — Ни объём, ни длительность, ни обращения к платным сервисам никуда не записываются: восстановить расход задним числом не из чего.
|
||||
- [✨ Сделать страницу статистики для владельца](items/admin-stats-screen.md) — Собранный учёт читается только запросом к базе руками: ни страницы, ни признака владельца в приложении нет.
|
||||
- [🐞 Не давать отправителю задавать, что уедет в журнал](items/journal-fields-bounded-by-service.md) — Путь запроса уезжает в журнал целиком: аноним пишет туда до мегабайта своего текста одной строкой, а хвост имени файла приезжает внутри чужого текста ошибки вместо своего поля.
|
||||
- [🐞 Писать в журнал код ответа отвергнутого запроса](items/response-code-in-journal.md) — У всякого запроса, отвергнутого роутером, в журнале стоит нулевой код: всплеск отказов доступа неотличим от обычного трафика.
|
||||
- [🐞 Не затирать сохранённое вложение более бедным ответом](items/payload-not-overwritten-by-poorer-answer.md) — Пустой ответ распознавателя сохранённое больше не стирает, а более короткий — стирает: вложение заменяется, и пересчитать архив становится нечем.
|
||||
- [🐞 Закрыть анониму адрес подтверждения почты](items/close-verification-endpoint.md) — Адрес подтверждения почты хранилища открыт без сессии: зная адрес вошедшего, аноним вызывает у сервиса отправку письма — сегодня безвредно, потому что почтового отправителя нет.
|
||||
- [🔬 Судьба рубежа расшифровки, у которого не осталось работы](items/transcribed-stage-without-work.md) — Шаг завершения после убранной доставки только двигает колонку, а рубеж при этом подпадает под сторож застревания: готовая расшифровка платит отдельный захват и час сторожа.
|
||||
- [🔬 Пределы длительности, приходящей из метаданных](items/duration-bounds-from-metadata.md) — Длительность приходит от ffprobe числом и не проверяется ничем: приведение к целому переполняется, а испорченная гистограмма чинится только перезапуском.
|
||||
- [🔬 Квота по общему размеру загруженного на пользователя](items/per-user-size-quota.md) — Паспорт и security.md запрещают отказы по квоте пользователю, а заметка владельца просит квоту по умолчанию 5 ГБ — открытое противоречие с границей домена, которое владелец решил не разбирать сейчас.
|
||||
|
||||
@@ -21,6 +21,13 @@
|
||||
Ступень по лестнице механизации — четвёртая: свойство о структуре, а не о
|
||||
вызове, и выражается тест-сканером в `internal/archrules`.
|
||||
|
||||
|
||||
**Предмета у задачи сейчас нет.** Клиент бота удалён вместе со входом задачей
|
||||
`remove-telegram-intake` 2026-08-15 — временно, решение записано
|
||||
[ADR-2026-08-15-telegram-intake-removed-temporarily](../../docs/adr/ADR-2026-08-15-telegram-intake-removed-temporarily.md).
|
||||
Запись остаётся гигиеной **возврата**: класс стоил проекту одного дефекта, и
|
||||
запрет надо ставить вместе с новым клиентом, а не после него.
|
||||
|
||||
## Затрагивает
|
||||
|
||||
- `internal/archrules` — новое правило-сканер и его перечень предметов;
|
||||
|
||||
@@ -0,0 +1,52 @@
|
||||
# 🐞 Закрыть анониму адрес подтверждения почты
|
||||
|
||||
- **Тип:** fix
|
||||
- **Категория:** Очередь — Заведена урожаем ревью и встала в конец машинально: место в плане стройки назначает человек.
|
||||
- **Зачем:** Адрес подтверждения почты хранилища открыт без сессии: зная адрес вошедшего, аноним вызывает у сервиса отправку письма — сегодня безвредно, потому что почтового отправителя нет.
|
||||
- **Теги:** review-2026-08-15
|
||||
|
||||
Поверхность коллекции пользователей закрывается тем же способом, что и остальные
|
||||
её адреса.
|
||||
|
||||
Шаг схемы входа через провайдера закрыл заведение записи, вход паролем и
|
||||
одноразовый код — но не запрос подтверждения почты. Проверено прогоном по
|
||||
собранному роутеру: запрос без сессии отвечает `204`.
|
||||
|
||||
Сервис своей проверки почты не делает вовсе: учётные записи заводит и проверяет
|
||||
внешний провайдер, а адрес приезжает вместе с входом. То есть адрес не просто
|
||||
открыт — он не нужен.
|
||||
|
||||
Сегодня безвреден: почтовый сервер не настроен, письмо уходить некуда. Каналом
|
||||
досаждения он становится вместе с задачей `email-notification`, которая почту как
|
||||
раз заводит, — и закрыть его дешевле до неё, чем после.
|
||||
|
||||
## Воспроизведение
|
||||
|
||||
Собрать роутер сервиса и послать `POST /api/collections/users/request-verification`
|
||||
без сессии, назвав адрес почты вошедшего. Ответ — `204`: сервис принял запрос от
|
||||
неузнанного и завёл отправку письма. Ожидается отказ, как у прочих адресов
|
||||
коллекции пользователей.
|
||||
|
||||
Письма при этом не уходит, и потому вреда сегодня нет: почтовый сервер не
|
||||
настроен. Проверка судит **код ответа**, а не доставку.
|
||||
|
||||
## Затрагивает
|
||||
|
||||
- шаг схемы, закрывающий адреса коллекции пользователей: заводится новый, прежний
|
||||
не переписывается;
|
||||
- `docs/security.md`, раздел о поверхности хранилища — перечень закрытых адресов.
|
||||
|
||||
## Критерии приёмки
|
||||
|
||||
- Запрос подтверждения почты без сессии отвергается. Оракул: проверка по
|
||||
собранному роутеру — ответ не `204`, письма не заводится.
|
||||
- Прочие способы открыть сессию остались закрытыми. Оракул: существующие
|
||||
проверки поверхности хранилища зелёные, состав их не сокращён.
|
||||
- Перечень закрытых адресов в модели угроз назван заново. Оракул: строка в
|
||||
`docs/security.md`.
|
||||
|
||||
## Рамки
|
||||
|
||||
Новый шаг схемы — применённые не переписываются. Найдено прогоном ревью задачи
|
||||
`remove-telegram-intake` 2026-08-15, враждебный проход, секция свойств без
|
||||
построенного пути.
|
||||
@@ -0,0 +1,49 @@
|
||||
# 🔬 Пределы длительности, приходящей из метаданных
|
||||
|
||||
- **Тип:** research
|
||||
- **Категория:** Очередь — Заведена урожаем ревью и встала в конец машинально: место в плане стройки назначает человек.
|
||||
- **Зачем:** Длительность приходит от ffprobe числом и не проверяется ничем: приведение к целому переполняется, а испорченная гистограмма чинится только перезапуском.
|
||||
- **Теги:** review-2026-08-15
|
||||
|
||||
Длительность записи сервис берёт у источника метаданных и не проверяет ни на
|
||||
знак, ни на потолок. Дальше сервис приводит её к целому, умножает на тысячу и
|
||||
кладёт колонкой записи, а заодно отправляет в гистограмму длительностей.
|
||||
|
||||
Число вне диапазона целого при приведении даёт наименьшее возможное значение —
|
||||
отрицательное. Оно портит сумму семейства метрик необратимо: ряд не чинится
|
||||
ничем, кроме перезапуска процесса, а страница метрик открыта без проверки
|
||||
отправителя.
|
||||
|
||||
Потолок записи у проекта объявлен — шесть часов, — и из него выведен предел
|
||||
размера файла. Длительность такого предела не имеет вовсе.
|
||||
|
||||
## Вопрос
|
||||
|
||||
Может ли `ffprobe` вернуть длительность вне диапазона целого на входе, который
|
||||
собрал отправитель, — и какой предел ставить на границе адаптера?
|
||||
|
||||
Что для ответа нужно узнать:
|
||||
|
||||
- какое поле и в какой форме `ffprobe` берёт за длительность у контейнеров,
|
||||
которые сервис принимает: доверяет ли объявленному в контейнере числу или
|
||||
считает по потоку;
|
||||
- есть ли контейнер, где число объявлено явно и потому подделывается: Matroska
|
||||
либо Ogg с подделанной меткой позиции — первые кандидаты;
|
||||
- что делает приём, если длительность отрицательна либо больше объявленного
|
||||
потолка: отвергать запись, обрезать значение или принимать, назвав в журнале.
|
||||
|
||||
## Куда ляжет ответ
|
||||
|
||||
Наблюдение о поведении `ffprobe` — в `docs/research/`, своей записью с командой и
|
||||
условиями замера: разведки о `ffmpeg` у проекта пока нет ни одной, а открытые
|
||||
вопросы про долгие записи и видео стоят в
|
||||
[architecture.md](../../docs/architecture.md). Выбранный предел — задачей
|
||||
следующим прогоном.
|
||||
|
||||
## Рамки
|
||||
|
||||
Прогон на реальных ключах Yandex запрещён и здесь не нужен: разведка меряет
|
||||
`ffprobe`, а не распознавание. Найдено прогоном ревью задачи
|
||||
`remove-telegram-intake` 2026-08-15, враждебный проход, секция свойств без
|
||||
построенного пути — путь не достроен именно потому, что нужен специально
|
||||
собранный контейнер.
|
||||
@@ -0,0 +1,66 @@
|
||||
# 🐞 Не давать отправителю задавать, что уедет в журнал
|
||||
|
||||
- **Тип:** fix
|
||||
- **Категория:** Очередь — Заведена урожаем ревью и встала в конец машинально: место в плане стройки назначает человек.
|
||||
- **Зачем:** Путь запроса уезжает в журнал целиком: аноним пишет туда до мегабайта своего текста одной строкой, а хвост имени файла приезжает внутри чужого текста ошибки вместо своего поля.
|
||||
- **Теги:** review-2026-08-15
|
||||
|
||||
Длину и содержимое строки журнала задаёт тот, кто прислал запрос, а не сервис.
|
||||
|
||||
Мест два, причина одна. Слой журнала пишет путь запроса полем `http.route`
|
||||
целиком: приведение режет только последний сегмент и только у ссылок на файлы.
|
||||
Отказ подготовки рабочей копии пересказывает отказ библиотеки целиком, а тот
|
||||
несёт полное имя временного файла — вместе с расширением, взятым из имени
|
||||
отправителя.
|
||||
|
||||
Журнал в этом проекте — место, где наблюдаются инварианты: по нему видно
|
||||
недоставку, остановку конвейера и молчаливый выход из шага. Вытесненный чужим
|
||||
текстом, он перестаёт отвечать на вопрос, ради которого заведён.
|
||||
|
||||
Класс проект уже назвал недопустимым в приведении отказа провайдера входа
|
||||
([conventions/logging.md](../../docs/conventions/logging.md)): «без приведения
|
||||
аноним пишет в журнал что угодно и сколько угодно». Здесь тот же канал шире и
|
||||
дешевле — сессия для него не нужна.
|
||||
|
||||
## Воспроизведение
|
||||
|
||||
**Путь запроса.** Поднять сервис и послать запрос, чей путь длиной 900 000 байт:
|
||||
|
||||
```
|
||||
python3 -c 'socket … GET /<900000×"A"> HTTP/1.1'
|
||||
```
|
||||
|
||||
Ответ — `404`, журнал вырастает с 1048 до 901 194 байт одной строкой. Потолок
|
||||
замерен: 1 048 000 байт ещё проходят, 1 100 000 отвергаются кодом `431`.
|
||||
Внедрения строк при этом нет — библиотека журнала квотирует значение.
|
||||
|
||||
**Хвост имени.** Принять запись, чьё имя несёт 280 байт после последней точки.
|
||||
Отказ подготовки рабочей копии приезжает в журнал уровня `ERROR` строкой вида
|
||||
`error="failed to create work file: open /tmp/transcriber-<число>.<280 байт>:
|
||||
file name too long"`, и поля `file_ext` в ней нет вовсе.
|
||||
|
||||
## Затрагивает
|
||||
|
||||
- слой журнала запроса в `main.go` и приведение пути `journalRoute`;
|
||||
- отказ подготовки рабочей копии в `internal/service`, шаг приёма записи;
|
||||
- `docs/conventions/logging.md` — правило о длине поля журнала;
|
||||
- умолчание `MaxHeaderBytes` у сервера: сегодня оно единственное неназванное
|
||||
рядом с названным сроком чтения.
|
||||
|
||||
## Критерии приёмки
|
||||
|
||||
- Путь запроса в журнале не длиннее объявленного предела, и усечение видно в
|
||||
самой строке. Оракул: тот же запрос с путём в 900 000 байт — прирост журнала
|
||||
не превышает предела, а маршрут по первым байтам по-прежнему различим.
|
||||
- Отказ подготовки рабочей копии не пересказывает отказ библиотеки: расширение
|
||||
идёт своим полем. Оракул: проверка приёма с длинным хвостом имени — строки с
|
||||
этим хвостом в журнале нет, поле `file_ext` есть.
|
||||
- Правило записано конвенцией: длину поля журнала не задаёт вызывающий. Оракул:
|
||||
строка в `docs/conventions/logging.md` и ссылка на неё из обеих правок.
|
||||
|
||||
## Рамки
|
||||
|
||||
Приведение пути не должно делать маршрут неразличимым: по журналу отличают
|
||||
`/api/audio` от `/api/status/:id`. Найдено прогоном ревью задачи
|
||||
`remove-telegram-intake` 2026-08-15, враждебный проход; дефект существовал до той
|
||||
правки, и владелец решил вынести его задачей.
|
||||
@@ -12,6 +12,14 @@
|
||||
включая негодный файл. Экран, построенный на таком контракте, показывает «не
|
||||
найдено» при упавшей базе.
|
||||
|
||||
Отдельная ветка того же класса найдена ревью задачи `remove-telegram-intake`
|
||||
2026-08-15, проход сверки требований: приём отвергает пустого владельца своей
|
||||
ошибкой, а транспорт переводит **любую** ошибку службы в `500`. Спека приёма при
|
||||
этом держит эту проверку ради понятного отказа — «отвечает отправителю понятным
|
||||
отказом до того, как запись попадёт в память». Сегодня путь недостижим: слой
|
||||
предъявления отвергает такого вызывающего раньше. Он становится достижимым вместе
|
||||
с личными токенами и экранами приложения, то есть ровно здесь.
|
||||
|
||||
## Затрагивает
|
||||
|
||||
- `POST /api/audio` и `GET /api/status/:id` — коды ответа и форма ошибки;
|
||||
@@ -26,8 +34,10 @@
|
||||
|
||||
- Код ответа отвечает причине отказа, а не месту, где он случился: сбой базы при
|
||||
чтении даёт `500`, а не `404`, негодный файл — `400` с человекочитаемым
|
||||
текстом, а не `500`. Оракул — два теста: репозиторий, возвращающий ошибку
|
||||
драйвера, и файл, который отвергает разбор метаданных.
|
||||
текстом, а не `500`, а отказ приёма по пустому владельцу — `403`, как и отказ
|
||||
слоя предъявления. Оракул — три теста: репозиторий, возвращающий ошибку
|
||||
драйвера; файл, который отвергает разбор метаданных; вызов приёма без учётной
|
||||
записи.
|
||||
- Тело ошибки одной формы на всех эндпоинтах, не содержит сырого `err.Error()` и
|
||||
опечатки `transcibe`. Оракул — тест на четырёх ветвях отказа (форма совпадает,
|
||||
текста внутренней ошибки в теле нет) плюс пустой `grep -rn 'transcibe'
|
||||
|
||||
@@ -0,0 +1,57 @@
|
||||
# 🐞 Не затирать сохранённое вложение более бедным ответом
|
||||
|
||||
- **Тип:** fix
|
||||
- **Категория:** Очередь — Заведена урожаем ревью и встала в конец машинально: место в плане стройки назначает человек.
|
||||
- **Зачем:** Пустой ответ распознавателя сохранённое больше не стирает, а более короткий — стирает: вложение заменяется, и пересчитать архив становится нечем.
|
||||
- **Теги:** review-2026-08-15
|
||||
|
||||
Сохранённый ответ провайдера заменяется только тем, что не беднее прежнего.
|
||||
|
||||
Задача `remove-telegram-intake` закрыла половину этого класса: текст и структура
|
||||
реплик пустым больше не затираются, и норма записана требованием спеки хранилища
|
||||
«Пустой результат не кладётся поверх сохранённого». Сырой ответ провайдера
|
||||
защищён только от **пустого** — условием на непустую длину; ответ не пустой, но
|
||||
короче прежнего, проходит это условие и заменяет сохранённое.
|
||||
|
||||
Цена именно у вложения самая высокая. Оно единственное, из чего архив
|
||||
пересчитывается без повторной оплаты: решение хранить его дословно записано
|
||||
[ADR-2026-08-14-provider-payload-stored-verbatim](../../docs/adr/ADR-2026-08-14-provider-payload-stored-verbatim.md),
|
||||
и обещание там прямое — «когда мы научимся размечать говорящих, архив
|
||||
пересчитается из сохранённого без единого рубля».
|
||||
|
||||
## Воспроизведение
|
||||
|
||||
Повторный опрос одной операции наступает штатно: держатель захвата умер,
|
||||
сохранение рубежа отказало, человек снял признак остановки в панели.
|
||||
|
||||
Довести запись до сохранённого ответа, вернуть её на рубеж отправленной и
|
||||
опросить снова, отдав со стороны провайдера ответ короче прежнего. Вложение
|
||||
заменяется на короткое; прежнего не остаётся нигде. Оракул того же класса для
|
||||
пустого ответа уже написан — `TestEmptySecondAnswerKeepsArchivedText`, — и этот
|
||||
пишется по его образцу.
|
||||
|
||||
## Затрагивает
|
||||
|
||||
- коллекция `recognitions`, колонка `payload` — сохранённый ответ провайдера вложением;
|
||||
- спека `storage`, требование «Пустой результат не кладётся поверх сохранённого»
|
||||
— норма расширяется с пустого на «беднее прежнего»;
|
||||
- определение «беднее»: длина в байтах либо число реплик разбора — выбирается
|
||||
задачей.
|
||||
|
||||
## Критерии приёмки
|
||||
|
||||
- Более короткий ответ сохранённое вложение не заменяет. Оракул: проверка по
|
||||
образцу `TestEmptySecondAnswerKeepsArchivedText` — второй опрос отдаёт ответ
|
||||
короче, сохранённое вложение остаётся прежним, и проверка убеждается, что до
|
||||
второго обращения дело дошло.
|
||||
- Более полный ответ сохранённое заменяет. Оракул: та же проверка наоборот —
|
||||
второй ответ длиннее, вложение обновилось.
|
||||
- Норма записана требованием спеки, а не только кодом. Оракул: правленое
|
||||
требование `storage` и ссылка на него из кода.
|
||||
|
||||
## Рамки
|
||||
|
||||
Найдено прогоном ревью задачи `remove-telegram-intake` 2026-08-15, враждебный
|
||||
проход, секция свойств без построенного пути: пустой случай доказан падающим
|
||||
тестом и закрыт, этот — выведен из того же кода и оракула не имеет. Тексту и
|
||||
структуре реплик защита уже стоит, трогать их не надо.
|
||||
@@ -0,0 +1,50 @@
|
||||
# 🐞 Писать в журнал код ответа отвергнутого запроса
|
||||
|
||||
- **Тип:** fix
|
||||
- **Категория:** Очередь — Заведена урожаем ревью и встала в конец машинально: место в плане стройки назначает человек.
|
||||
- **Зачем:** У всякого запроса, отвергнутого роутером, в журнале стоит нулевой код: всплеск отказов доступа неотличим от обычного трафика.
|
||||
- **Теги:** review-2026-08-15
|
||||
|
||||
Код ответа в журнале называет исход запроса, а не ноль.
|
||||
|
||||
Обработчик, завершившийся отказом роутера — `401` без сессии, `403` без учётной
|
||||
записи, `404` на чужой записи, `500` на сбое, — пишет статус в ответ **после**
|
||||
возврата из слоя журнала. Слой читает его раньше и получает ноль. Верное значение
|
||||
попадает в журнал только у обработчиков, отвечающих самостоятельно.
|
||||
|
||||
Разграничение записей по владельцу устроено так, что чужая запись отвечает тем
|
||||
же, чем несуществующая. Единственное место, где виден перебор идентификаторов, —
|
||||
журнал; а именно эти строки и приезжают с нулём.
|
||||
|
||||
## Воспроизведение
|
||||
|
||||
Поднять сервис и послать четыре запроса подряд:
|
||||
|
||||
```
|
||||
/auth/login → 302 ... http.route=/auth/login http.status_code=302
|
||||
/api/audio → 404 ... http.route=/api/audio http.status_code=0
|
||||
/nope → 404 ... http.route=/nope http.status_code=0
|
||||
POST /api/audio без сессии → 401 ... http.status_code=0
|
||||
```
|
||||
|
||||
Первый обработчик отвечает сам и код пишет верно; три остальных отвергнуты
|
||||
роутером и дают ноль.
|
||||
|
||||
## Затрагивает
|
||||
|
||||
- слой журнала запроса в `main.go`: место, где снимается код ответа;
|
||||
- `docs/conventions/logging.md` — словарь полей запроса.
|
||||
|
||||
## Критерии приёмки
|
||||
|
||||
- Отвергнутый запрос пишет в журнал свой код. Оракул: те же четыре запроса —
|
||||
`401`, `403`, `404` и `500` приезжают в поле кода, ноля в нём нет ни у одного.
|
||||
- Обработчик, отвечающий самостоятельно, продолжает писать свой код. Оракул:
|
||||
запрос входа по-прежнему даёт `302`.
|
||||
|
||||
## Рамки
|
||||
|
||||
Найдено прогоном ревью задачи `remove-telegram-intake` 2026-08-15, враждебный
|
||||
проход, оракул — живой прогон. Дефект существовал до той правки: изменение этот
|
||||
слой не трогало. Метрики кодов ответа у сервиса нет вовсе, и заводить её этой задачей не
|
||||
надо — она про журнал.
|
||||
@@ -10,6 +10,14 @@
|
||||
Берётся после `record-ownership`: связывать не с чем, пока у записи нет
|
||||
владельца.
|
||||
|
||||
|
||||
**Предмета у задачи сейчас нет.** Вход Telegram убран задачей
|
||||
`remove-telegram-intake` 2026-08-15 — временно, решение записано
|
||||
[ADR-2026-08-15-telegram-intake-removed-temporarily](../../docs/adr/ADR-2026-08-15-telegram-intake-removed-temporarily.md).
|
||||
Эта задача остаётся **условием возврата**: без связи чата с учётной записью вход
|
||||
вернуть нельзя — записи снова пошли бы без владельца, а колонка владельца пустого
|
||||
значения больше не принимает.
|
||||
|
||||
## Затрагивает
|
||||
|
||||
- связь учётной записи с чатом Telegram: таблица и её миграция;
|
||||
|
||||
@@ -0,0 +1,56 @@
|
||||
# 🔬 Судьба рубежа расшифровки, у которого не осталось работы
|
||||
|
||||
- **Тип:** research
|
||||
- **Категория:** Очередь — Заведена урожаем ревью и встала в конец машинально: место в плане стройки назначает человек.
|
||||
- **Зачем:** Шаг завершения после убранной доставки только двигает колонку, а рубеж при этом подпадает под сторож застревания: готовая расшифровка платит отдельный захват и час сторожа.
|
||||
- **Теги:** review-2026-08-15
|
||||
|
||||
Шаг завершения заводился ради ответа отправителю: он читал текст расшифровки и
|
||||
отправлял его в чат, а перевод записи на конечный рубеж был хвостом этой работы.
|
||||
Доставка убрана задачей `remove-telegram-intake`, и от шага осталось присваивание
|
||||
колонки с сохранением.
|
||||
|
||||
Цена этого остатка не нулевая. Между «расшифровка сохранена» и конечным рубежом
|
||||
лежит полный круг воркера: захват с ростом числа отказов, чтение, сохранение,
|
||||
строка журнала событий, счётчик. Рубеж при этом числится своей работой и потому
|
||||
подпадает под предел простоя — час. Запись с готовым текстом, простоявшая этот час
|
||||
без свободного воркера (очередь, ноль воркеров настройкой, окно выкладки),
|
||||
останавливается признаком с причиной «застряла», и отправитель видит остановку у
|
||||
записи, чья расшифровка лежит в хранилище.
|
||||
|
||||
Вопрос не в том, дефект это или нет: сегодня и то и другое поведение законно.
|
||||
Вопрос в том, чем рубеж остаётся дальше.
|
||||
|
||||
## Вопрос
|
||||
|
||||
Остаётся ли рубеж расшифровки отдельным шагом конвейера — и если да, какую работу
|
||||
он держит?
|
||||
|
||||
Две формы ответа видны сразу, и у каждой своя цена:
|
||||
|
||||
- **шаг опроса двигает запись сразу на конечный рубеж**, а рубеж расшифровки
|
||||
уходит к отжившим состояниям. Круг воркера и час сторожа исчезают; цена —
|
||||
правка спеки конвейера (цепочка рубежей, требование «Рубеж записи называет
|
||||
достигнутое») и значение, остающееся в перечне схемы;
|
||||
- **рубеж остаётся объявленным местом** под задачу выводов из текста — заголовок,
|
||||
пересказ и темы считаются шагом, который встанет ровно сюда. Тогда это надо
|
||||
сказать словами в конвейере и в спеке, иначе следующий читатель прочтёт шаг как
|
||||
забытый код. Цена — час сторожа над готовой записью, и его тоже надо назвать.
|
||||
|
||||
Ответ зависит от того, чем станет `llm-insights-adapter`: отдельным шагом
|
||||
конвейера или продолжением распознавания. Открытым вопросом это стоит в
|
||||
[architecture.md](../../docs/architecture.md).
|
||||
|
||||
## Куда ляжет ответ
|
||||
|
||||
Решение — в `docs/adr/`, продвижением записки; сама записка не нужна, разведка
|
||||
здесь выбирает форму, а не измеряет внешний мир. Изменение спеки конвейера, если
|
||||
выбран первый ответ, заводит следующий прогон.
|
||||
|
||||
## Рамки
|
||||
|
||||
Перечень рубежей закрыт схемой, и удаление значения из него потребовало бы шага
|
||||
схемы: разведка это только называет ценой, а решение принимает человек. Найдено
|
||||
прогоном ревью задачи `remove-telegram-intake` 2026-08-15, архитектурный проход;
|
||||
оракула у находки нет — случай выведен из кода и предела простоя, но не
|
||||
воспроизведён.
|
||||
Reference in New Issue
Block a user