Files
transcriber/docs/passport.md
T
av 8af8ec2e54 у записи появился владелец: чужую больше не отдают
- колонка `owner` связью с `users` в обеих коллекциях новым шагом схемы
  `202608140001`; чтение задачи сужено владельцем, и чужая, ничья и
  несуществующая дают один ответ; правило просмотра файлов сужено им же
- приём по HTTP берёт владельца из сессии, а предъявителя без учётной записи
  пользователя отвергает до чтения тела: позже пришлось бы убирать уложенный
  файл, а уборки файлов сервис не умеет. Выборка воркера владельцем не сужается
- удаление учётной записи с записями отвергается стражем, и вешает его сама
  сборка хранилища: сборка, забывшая его позвать, теряла защиту молча
2026-08-14 12:18:11 +03:00

12 KiB
Raw Blame History

Паспорт проекта

Зачем это и для кого. architecture.md отвечает «как устроено», tasks/BACKLOG.md — «в каком порядке», паспорт — «зачем и для кого».

Цель

Превращать записанную речь в текст, который можно читать и искать, и хранить этот текст вместе с записью.

Сервис — архив, и это решено 2026-08-11. Прежде граница читалась «отдаём текст и на этом заканчиваем»; теперь расшифровки и исходные записи лежат бессрочно, а список отбирается по темам. Причина в основном сценарии: семейный архив загружают один раз, а возвращаются к нему годами.

Потребители — список закрытый: он определяет, что считать нужным, а что интересным.

Кто Что ему нужно от нас
Владелец сервиса Загрузить диктофонную запись или видео из семейного архива с телефона и получить текст. Видеть, кто сколько загрузил и во что это обошлось
Приглашённый пользователь Войти в приложение через свою учётную запись, загрузить запись, забрать текст, вернуться к ней через месяц. Приложение ставится на телефон; каждый видит только свои записи
Пользователь Telegram Отправить боту голосовое сообщение и получить текст ответом. Работает сегодня
Внешняя программа Отдать файл по HTTP, представившись своим токеном, и опросить готовность. Сегодня почти не работает: приём и опрос закрыты сессией OIDC, а своего токена у программы нет — годится только чужая сессия, снятая из браузера и предъявленная кукой либо заголовком Authorization. Токен приносит api-tokens

Основной вход — приложение, бот и HTTP API дополняют его. До 2026-08-11 основным был бот, и порядок здесь перевёрнут сознательно: диктофонная запись на несколько часов через Telegram не проходит вовсе.

Цель достигнута, когда:

  • запись любого распространённого формата принимается без предварительной подготовки, включая дорожку из видео;
  • запись расчётного потолка — шести часов — доходит до текста, а не прерывается ошибкой при достижении предела (норма — openspec/specs/storage);
  • сервисом пользуются несколько человек, и записи одного не видны другому;
  • текст доступен там же, где загружали, — в приложении и в Telegram. Человек узнаёт о его готовности, не держа приложение открытым;
  • расшифровка не теряется: к записи возвращаются через месяц и находят её по заголовку и темам;
  • владелец видит расход по каждому пользователю и понимает, во что обходится приглашение ещё одного человека.

Что целью не является

Граница домена. По ней в теме architecture судят, не перенесено ли понятие через границу.

  • Правка текста руками. Машинную вычитку расшифровки отдаём — литературный текст стоит рядом с сырым, — а редактором не становимся: текст руками не правим, не размечаем и не экспортируем в форматы документов. Граница сдвинута 2026-08-11: до того запрет читался «расшифровку отдаём как есть».
  • Разговор о записи. Ответы на вопросы по содержанию и поиск по смыслу — за границей. Заголовок, пересказ и темы внутри границы: она сдвинута 2026-08-10, и до того запись читалась «мы отдаём текст, а не выводы из него». Считать уровни текста берётся задача llm-insights-adapter.
  • Собственные модели. Не обучаем и не держим у себя ни модель распознавания, ни языковую модель: и речь, и выводы из текста считает внешний сервис.
  • Управление учётными записями. Пользователей заводит и проверяет внешний провайдер, свою регистрацию и свои пароли не делаем. Одно исключение появилось 2026-08-11 вместе с решением про PocketBase: в панель администратора владелец входит своим паролем, потому что подпустить к ней внешнего провайдера PocketBase не даёт.
  • Живая расшифровка. Работаем с готовой записью, поток в реальном времени не обрабатываем.
  • Диктофон. Запись звука делает телефон, а приложение принимает готовый файл. Своей записи и работы без сети не делаем.
  • Файловое хранилище общего назначения. Храним аудио и видео, отданные ради речи в них. Складом произвольных файлов и папками сервис не становится. Общего доступа к чужим записям целью нет, и с 2026-08-14 его нет и на деле: у записи есть владелец, и чужую по её идентификатору не отдают (security.md, «Периметр»). Закрыла это задача record-ownership.
  • Учёт денег. Считаем объём, минуты и токены по каждому пользователю и показываем их владельцу. Цен, счетов и отказов по исчерпании квоты не делаем: пользователя, потратившего слишком много, останавливает разговор или отзыв доступа в Authelia.

Типовые сценарии

Первые два — основные, и сегодня не работает ни один: приложения нет.

  1. Семейный архив. Человек открывает приложение на телефоне, выбирает до десяти записей разом — диктофонные дорожки и видео, — и закрывает его. Загрузка показывает ход. Файл, который уже загружали, не грузится второй раз. Когда текст готов, приходит уведомление; в списке запись видна заголовком и темами.
  2. Возвращение к записи. Через месяц человек открывает список, находит запись по заголовку или теме и читает вычитанный текст, а при нужде — сырую расшифровку.
  3. Голосовое из Telegram. Пользователь шлёт боту голосовое сообщение, бот отвечает «обрабатываю», через минуту приходит текст ответом на то же сообщение. Записи, чей текст длиннее предела сообщения Telegram, приходят несколькими частями. Работает сегодня.
  4. Файл через Telegram. То же для аудиофайла или документа с аудио: бот отличает их по MIME-типу и расширению. Работает сегодня.
  5. Загрузка по HTTP. Программа шлёт POST /api/audio со своим токеном, получает идентификатор задачи и опрашивает GET /api/status/:id, пока не увидит done и текст. Сегодня доступно только предъявившему сессию OIDC: анонимный запрос обоими адресами отклоняется. Своего входа у программы нет — его заводит api-tokens. Записи при этом разграничены: программа с чужой сессией видит только записи того, чью сессию предъявила.
  6. Отказ на середине. Конвертация или распознавание не удались — задача переходит в failed, а пользователь получает сообщение о том, что именно не вышло, и предложение повторить.

Референсы

Где смотреть prior art, когда упёрлись.

  • Yandex SpeechKit, отложенное распознавание — модель deferred-general, которой пользуемся: она и задаёт потолок по длине записи и формату.
  • Whisper и его серверные обёртки — запасной путь, если внешний сервис перестанет устраивать по цене или по качеству русской речи. PocketBase из референсов ушла: она больше не кандидат — в стек её перевела задача pocketbase-storage 2026-08-12 (adr); там она держит хранилище, файлы и панель владельца. Схема и раскладка — database.md. Учётные записи она хранит и получает от Authelia своим провайдером OIDC, но источником их не становится: заводит и проверяет людей по-прежнему Authelia.