Files
transcriber/tasks/items/usage-accounting.md
T
av 8739b18a9f tasks: очередь расставлена от базы к деталям
- порядок беклога и роадмапа назначен слоями: проверки, которым можно
  верить → долги входа → владелец записи и контракт API → конвейер под
  тестами → приложение и возможности поверх; у каждого движения записана
  причина;
- заведены восемь задач под пункты «Завершения», которых не закрывала ни
  одна запись, — цель any-audio-source была без задач вовсе;
- у четырёх задач сняты критерии, требовавшие того, что делает задача ниже
  по очереди; исправлены ссылки на несуществующий repo/sqlite и на
  отменённую разведку об очереди.
2026-08-12 20:48:53 +03:00

48 lines
3.8 KiB
Markdown

# ✨ Считать объём, минуты и расход по каждому пользователю
- **Тип:** feature
- **Категория:** Очередь — Учёт по пользователям требует владельца записи и метрик расхода — оба выше.
- **Зачем:** Ни объём, ни длительность, ни обращения к платным сервисам никуда не записываются: восстановить расход задним числом не из чего.
- **Теги:** goal:usage-stats
Двигает пункты 1, 2 и 4 «Завершения» цели: по каждому пользователю копятся
объём, минуты и расход на внешние сервисы, и повтор шага не удваивает счёт.
Учёт ведётся записями о потреблении, а не счётчиком в строке пользователя:
счётчик, увеличенный дважды при повторе шага, обратно не отматывается.
## Затрагивает
- таблица записей потребления: владелец, задача, вид ресурса, величина, время —
и её миграция;
- `TranscribeService.createTranscribeJob` — размер файла и длительность записи
на приёме;
- `TranscribeService.completeJob` и `failJob` — запись потребления после
успешного шага и после отказа;
- адаптер SpeechKit и адаптер языковой модели: откуда берутся минуты и токены;
- `internal/metrics` — счётчики того же расхода без разбивки по людям;
- `docs/database.md` — представление данных.
## Критерии приёмки
- Дошедшая до `done` запись оставляет строки потребления: объём файла,
длительность в минутах, минуты распознавания и токены языковой модели. Оракул
— тест конвейера на подставных адаптерах: четыре строки с владельцем задачи.
- Повторный проход шага после перезапуска не удваивает потребление. Оракул — тест:
шаг выполнен дважды, сумма по задаче не изменилась.
- Отказавшая задача сохраняет то, что уже потрачено, а не обнуляет счёт. Оракул
— тест на ветке `failJob` после успешной конвертации.
- Величина расхода не смешивает пользователей: выборка по владельцу отдаёт
только его строки. Оракул — тест на двух владельцах.
## Рамки
Снаружи эта задача не видна сама по себе: ни экрана, ни эндпоинта она не
заводит — их строит `admin-stats-screen`. Тип оставлен `feature` сознательно,
как шаг цели.
Потолков и отказов по исчерпании квоты не заводим — цель показывает, а не
ограничивает. Пересчёт расхода в деньги здесь не делается: копятся минуты и
токены, цена прайс-листа живёт вне сервиса. Данные о потреблении содержат
идентификаторы, но не текст записи и не имя файла (инвариант приватности).