Канон документов, каталог задач и OpenSpec

docs/ по канону 12: паспорт с целью проекта, архитектура сегодняшнего
устройства, схема хранилища, модель угроз, конвенции кода, журнал ревью.
Конвенции перенесены из jellybit; места, где код им не следует, помечены
строкой «Расхождение» как объявленный долг.

tasks/ с роадмапом: две достигнутые цели, две запланированные (веб и
многопользовательский режим), два направления (все форматы, долгие
записи) и пять задач в беклоге.

openspec/config.yaml — маршрутизатор с адресами документов, спек пока нет.

CLAUDE.md переписан по форме канона: инварианты с severity, семантика
гейта, запреты с путями. Taskfile получил task gate.
This commit is contained in:
av
2026-08-10 21:19:07 +03:00
parent a4646c0930
commit 4d1c2bf44c
40 changed files with 3656 additions and 71 deletions
+46
View File
@@ -0,0 +1,46 @@
# 🧹 Задать таймауты обращениям к внешним сервисам
- **Тип:** chore
- **Категория:** Инфра
- **Зачем:** Ни у Telegram, ни у Object Storage, ни у SpeechKit нет таймаута: молчащий собеседник держит шаг конвейера до истечения часового захвата.
Все обращения наружу идут с `context.Background()` либо через `http.Get` без
клиента со своим таймаутом. Отказ такого рода в
[architecture.md](../../docs/architecture.md) назван условием: собеседник,
который «отвечает медленно», сегодня останавливает воркер целиком, и заметить
это можно только по тому, что задачи перестали двигаться.
Сюда же контекст: воркеры получают `ctx` и отменяют его при остановке, но ни
один шаг конвейера внутрь его не передаёт — мягкая остановка ждёт таймаута
вместо того, чтобы прервать вызов.
## Затрагивает
- `internal/adapter/recognizer/yandex/s3.go` — заливка объекта;
- `internal/adapter/recognizer/yandex/speechkit.go` — запуск распознавания,
чтение потока, опрос операции;
- `internal/controller/tg/tg.go` — скачивание файла через `http.Get`;
- `internal/adapter/telegram/sender.go` — отправка сообщения;
- `internal/contract/contract.go` — интерфейсам нужен `context.Context` первым
аргументом;
- `internal/controller/worker/worker.go` и `internal/service/transcribe.go`
протаскивание контекста в шаг;
- `config.dist.toml` и `internal/config` — числа таймаутов;
- `docs/database.md`, таблица настроек с числовым значением.
## Критерии приёмки
- У каждого обращения наружу есть таймаут, и его значение задаётся конфигом.
Оракул — тест на подставном сервере, который не отвечает: вызов
возвращается с ошибкой за назначенное время, а не висит.
- Отмена контекста при остановке приложения прерывает шаг конвейера. Оракул —
тест: отменённый контекст возвращает управление из шага, задача остаётся в
прежнем состоянии.
- Прерванная по таймауту задача достаётся повторно и доходит до текста. Оракул
— тест на повторный прогон шага после отказа по таймауту.
- Числа таймаутов записаны в `docs/database.md`. Оракул — `task gate`.
## Рамки
Повторов с нарастающей паузой не заводим — это отдельная работа; здесь только
таймаут и отмена.