удалён вход Telegram, владелец записи стал обязателен в схеме
- убраны клиент бота, транспорт обновлений, отправитель сообщений, сборка входа при старте, секция настроек и зависимость go-telegram-bot-api; из конвейера ушла доставка ответа отправителю — исход виден опросом готовности. Колонки адресата и значение источника остались в схеме: применённые шаги не переписываются - шаг 202608140003 запрещает пустого владельца у аудиозаписи и у файла; существующие строки он не проверяет, и это принято сознательно — искать их надо запросом до выкладки - ревью нашло два пред-существующих дефекта, оба закрыты: пустой второй ответ распознавателя стирал сохранённую расшифровку, а пустая расшифровка перестала быть заметной вместе с убранной доставкой. Попутно поднят golang.org/x/image до v0.45.0 — красный шаг vulns, воспроизводился и на чистом master
This commit is contained in:
@@ -9,11 +9,12 @@
|
||||
|
||||
## Что это
|
||||
|
||||
Сервис расшифровки аудио в текст. Принимает запись двумя входами — Telegram-бот и
|
||||
HTTP API, — конвертирует её `ffmpeg` в ogg, отдаёт на отложенное распознавание
|
||||
Yandex SpeechKit и возвращает текст туда, откуда пришла запись. Состояние задач,
|
||||
метаданные и сами файлы лежат во встроенной PocketBase, и она же даёт владельцу
|
||||
панель администратора.
|
||||
Сервис расшифровки аудио в текст. Принимает запись одним входом — HTTP API, —
|
||||
конвертирует её `ffmpeg` в ogg, отдаёт на отложенное распознавание Yandex
|
||||
SpeechKit и отдаёт текст тому, кто запись загрузил, по опросу готовности.
|
||||
Состояние записей, метаданные и сами файлы лежат во встроенной PocketBase, и она
|
||||
же даёт владельцу панель администратора. Вход Telegram убран 2026-08-14 —
|
||||
временно, до задачи, которая свяжет чат с учётной записью.
|
||||
|
||||
Чего **не** делает: сам речь не распознаёт и своих моделей не держит, текст
|
||||
руками не правит и в форматы документов не экспортирует, учётных записей не
|
||||
@@ -25,7 +26,7 @@ Yandex SpeechKit и возвращает текст туда, откуда пр
|
||||
## Стек
|
||||
|
||||
Go 1.26 (сборке CGO не нужен; детектору гонок в гейте — нужен), встроенная PocketBase — хранилище, файлы записей и
|
||||
панель администратора, — `go-telegram-bot-api`, `aws-sdk-go-v2` для Object
|
||||
панель администратора, — `aws-sdk-go-v2` для Object
|
||||
Storage, gRPC-клиент Yandex SpeechKit v3, Prometheus, `slog`. Сборка —
|
||||
Taskfile, образ — Docker, выкладка — Ansible из `pet-project-server`.
|
||||
|
||||
@@ -33,7 +34,7 @@ Taskfile, образ — Docker, выкладка — Ansible из `pet-project-
|
||||
|
||||
Что нарушать нельзя.
|
||||
|
||||
- **Секрет не покидает конфиг.** Токен бота, ключ SpeechKit, пара ключей Object
|
||||
- **Секрет не покидает конфиг.** Ключ SpeechKit, пара ключей Object
|
||||
Storage и секрет клиента OIDC не попадают в git, в лог, в ответ пользователю и
|
||||
в колонку `error_text`. Нарушение необратимо: утёкший ключ отзывают и меняют
|
||||
вручную во всех местах выкладки. **critical**
|
||||
@@ -53,14 +54,13 @@ Taskfile, образ — Docker, выкладка — Ansible из `pet-project-
|
||||
приведённым к перечню известных форматов. Границу держит спека `intake`,
|
||||
цена — [adr/ADR-2026-08-11-known-format-label.md](docs/adr/ADR-2026-08-11-known-format-label.md),
|
||||
остаток — [docs/security.md](docs/security.md).
|
||||
- **Бот отвечает только тем, кто в белом списке.** Бот проверяет отправителя до
|
||||
любой работы, включая скачивание файла. Нарушение обратимо правкой конфига, но
|
||||
чужие записи к тому моменту уже обработаны за наши деньги. **critical**
|
||||
- **Принятая запись не теряется молча.** Отказ на любом шаге либо оставляет
|
||||
задачу пригодной к повтору, либо переводит её в `failed` и сообщает
|
||||
пользователю. Молчаливый выход из шага без записи в лог и без смены состояния
|
||||
запрещён. Обратимо повторной отправкой, но пользователь об этом не узнает.
|
||||
**major**
|
||||
запись пригодной к повтору, либо ставит на неё признак остановки с причиной —
|
||||
и тогда причина видна её владельцу опросом готовности, а владельцу сервиса
|
||||
журналом. Молчаливый выход из шага без записи в лог и без смены состояния
|
||||
запрещён. Обязанность сменила направление 2026-08-14 вместе с убранным входом
|
||||
Telegram: прежде об отказе сообщали, теперь отказ доступен спросившему, и
|
||||
отправитель, который не спрашивает, о нём не узнаёт. **major**
|
||||
- **`NoopJobError` — не ошибка.** Значение «задач в этом состоянии нет» не
|
||||
логируется, не считается в метрику и не поднимает уровень. Нарушение даёт
|
||||
запись раз в секунду на каждый воркер. **major**
|
||||
@@ -89,12 +89,21 @@ Taskfile, образ — Docker, выкладка — Ansible из `pet-project-
|
||||
Признак захвата уникален для каждого захвата, и запись результата условна по
|
||||
нему, а не по занятости записи. Шаг, чей захват за время работы достался
|
||||
другому — по протуханию срока или после того, как человек снял признак
|
||||
остановки в панели, — завершается без записи и без ответа отправителю. Условие
|
||||
остановки в панели, — завершается без записи результата. Условие
|
||||
по непустоте признака пропустило бы обоих: два воркера писали бы в одну запись
|
||||
по очереди, а отправитель получал бы два ответа. **major**
|
||||
- **Остановленная запись сообщает отправителю, какой бы ни была причина.**
|
||||
Причин три — приговор шага, исчерпанные отказы, застревание. Остановленная
|
||||
запись захвату не выдаётся, значит исход «пригодна к повтору» исключён.
|
||||
по очереди, портя её результат. **major**
|
||||
- **У записи есть владелец, и колонка пустого значения не принимает.** Ничья
|
||||
запись не заводится ничем — ни приёмом, ни конвейером, ни рукой в панели, — и
|
||||
держит это схема хранилища, а не договорённость. Пока обязательность жила в
|
||||
одном приёме, ничью запись заводили в панели, она уходила в конвейер, стоила
|
||||
денег на распознавание и не доставалась потом никому. Правило со стороны
|
||||
спрашивающего при этом остаётся: пустой владелец не совпадает ни с одной
|
||||
записью, потому что схема запрещает **заводить** ничью, а это правило —
|
||||
**спрашивать** ничьим именем. **major**
|
||||
- **Остановленная запись несёт причину, какой бы та ни была.** Причин три —
|
||||
приговор шага, исчерпанные отказы, застревание, — и каждая записывается в саму
|
||||
запись и в её журнал событий. Остановленная запись захвату не выдаётся, значит
|
||||
исход «пригодна к повтору» исключён, и другого следа у неё не будет.
|
||||
Обязанность, записанная у одной причины, у остальных читалась бы как снятая.
|
||||
**major**
|
||||
|
||||
@@ -200,16 +209,12 @@ task gate # весь набор проверок разом
|
||||
база (`data/data.db`), и записи живых людей
|
||||
(`data/storage/<коллекция>/<запись>/`). Локальный каталог данных — свой, его
|
||||
ронять и пересоздавать можно свободно.
|
||||
- **Боевым токеном бота не запускаться.** Второй процесс с тем же токеном
|
||||
перехватывает обновления у работающего, и пользователь теряет ответы. Запускай
|
||||
с `telegram.enabled = false`: сервис поднимается без Telegram, к нему не уходит
|
||||
ни одного обращения, и работает он одним входом, по HTTP. Пустого
|
||||
`bot_token` для этого мало и больше не значит ничего: включён вход или нет,
|
||||
решает отдельный признак `telegram.enabled`, а пустой ключ при `enabled = true`
|
||||
роняет старт. Выключенного входа
|
||||
для подъёма тоже мало: секции `[auth]` и `[yandex]` проверяются на старте, но
|
||||
наружу при этом не ходят, так что годятся выдуманные непустые значения;
|
||||
подробности строками в `config.example.toml`.
|
||||
- **Локальный запуск не ходит наружу.** Секции `[auth]` и `[yandex]`
|
||||
проверяются на старте, но наружу при этом не обращаются, так что годятся
|
||||
выдуманные непустые значения — адреса `[auth]` должны лишь разбираться как
|
||||
ссылки. Расшифровка при выдуманных ключах не работает: её подменяют
|
||||
`internal/adapter/recognizer/memory.go`. Подробности строками в
|
||||
`config.example.toml`.
|
||||
- **Yandex Cloud за деньги.** Распознавание и хранение в Object Storage
|
||||
оплачиваются по факту. Прогон на реальных ключах ради проверки кода запрещён —
|
||||
подставляй `internal/adapter/recognizer/memory.go`.
|
||||
@@ -249,7 +254,7 @@ task gate # весь набор проверок разом
|
||||
|
||||
- Документация, комментарии, сообщения коммитов — русский.
|
||||
- Код и идентификаторы — английский.
|
||||
- Текст, который видит пользователь Telegram, — русский.
|
||||
- Текст, который видит пользователь сервиса, — русский.
|
||||
- **Точного числа накопленного в документах нет.** «Три capability», «пять
|
||||
прогонов ревью», «две типизированные ошибки» расходятся с действительностью на
|
||||
первой же задаче, которая прибавит четвёртую, — и расходятся молча: машина
|
||||
|
||||
Reference in New Issue
Block a user