- порядок беклога и роадмапа назначен слоями: проверки, которым можно верить → долги входа → владелец записи и контракт API → конвейер под тестами → приложение и возможности поверх; у каждого движения записана причина; - заведены восемь задач под пункты «Завершения», которых не закрывала ни одна запись, — цель any-audio-source была без задач вовсе; - у четырёх задач сняты критерии, требовавшие того, что делает задача ниже по очереди; исправлены ссылки на несуществующий repo/sqlite и на отменённую разведку об очереди.
49 lines
3.8 KiB
Markdown
49 lines
3.8 KiB
Markdown
# ✨ Отправлять готовый текст через apprise и ntfy
|
||
|
||
- **Тип:** feature
|
||
- **Категория:** Очередь — Канал уведомлений выбирается в настройках, которые уже есть.
|
||
- **Зачем:** Пользователь веба узнаёт о готовности только опросом с открытого экрана.
|
||
- **Теги:** goal:ready-notification
|
||
|
||
Двигает пункты 1, 2, 4 и 5 «Завершения» цели: готовый текст и отказ доходят до
|
||
пользователя веба без открытого приложения, отказ канала задачу не роняет, а
|
||
пользователь Telegram получает ответ по-прежнему ботом. Выбор канала самим
|
||
пользователем (пункт 3) заводит `settings-screen`.
|
||
|
||
Сегодня `completeJob` и `failJob` отвечают только источнику `telegram`;
|
||
источник `api` не получает ничего. Здесь появляется второй способ доставки, и
|
||
выбор между ними обязан остаться в одной точке — той же, что сейчас.
|
||
|
||
## Затрагивает
|
||
|
||
- `internal/contract` — интерфейс отправителя уведомления;
|
||
- `internal/service`, `completeJob` и `failJob` — выбор канала по источнику
|
||
задачи;
|
||
- новый адаптер поверх apprise либо прямого HTTP к ntfy;
|
||
- адрес канала у учётной записи: колонка и её миграция (экран настройки заводит
|
||
`settings-screen`);
|
||
- секция конфигурации: адрес сервера ntfy, способ вызова apprise;
|
||
- `docs/architecture.md` — новая внешняя зависимость и чем она отказывает;
|
||
- `docs/security.md` — текст расшифровки уходит на внешний сервис;
|
||
- `docs/database.md` — настройки числами.
|
||
|
||
## Критерии приёмки
|
||
|
||
- Задача из веба, дошедшая до `done`, отправляет текст в канал владельца.
|
||
Оракул — тест с подставным отправителем: вызов ровно один, с текстом задачи и
|
||
адресом владельца.
|
||
- Задача из Telegram по-прежнему отвечает ботом и вторым каналом не дублируется.
|
||
Оракул — тот же тест на источнике `telegram`: подставной отправитель ntfy не
|
||
вызван.
|
||
- Недоступный канал уведомлений не мешает задаче завершиться: состояние `done` и
|
||
текст в приложении остаются. Оракул — тест с отправителем, возвращающим
|
||
ошибку: задача в `done`, текст на месте, в логе одна запись уровня `WARN`.
|
||
- Отказ задачи доходит тем же каналом и тем же человекочитаемым текстом, что
|
||
видит пользователь Telegram. Оракул — тест на ветке `failJob`.
|
||
|
||
## Рамки
|
||
|
||
Web Push с VAPID и своим хранением подписок не делаем. Своего сервера ntfy не
|
||
поднимаем — адрес приходит конфигом. Текст расшифровки уходит на внешний сервис,
|
||
и это сдвиг периметра: строка в `docs/security.md` обязательна.
|