записано решение уйти с PocketBase на SQLite со своим каталогом файлов

- разведка storage-without-pocketbase: шесть ролей библиотеки в этом коде, отпавший довод перевода, шесть модулей достижимы только через неё
- ADR-2026-08-22-storage-without-pocketbase заменяет три записи: перевод в PocketBase, очередь коллекцией, файл за защищённым полем
- задача storage-without-pocketbase встала первой строкой плана стройки
This commit is contained in:
av
2026-08-22 21:00:14 +03:00
parent a8fb4793be
commit ad5b5e377f
9 changed files with 262 additions and 3 deletions
+1
View File
@@ -43,6 +43,7 @@
## Очередь
- [✨ Уйти с PocketBase на SQLite со своим каталогом файлов](items/storage-without-pocketbase.md) — Библиотека держит шесть ролей и вышла за адаптер: её типы стоят во всех пяти файлах контроллера и во всех шести его проверках, панель опубликована в интернет вместе с необойдённым /%5f/, а пространство /api/ нельзя закрыть на прокси, потому что за файлами туда ходит браузер пользователя.
- [🧹 Поднимать сервис для локальной работы одной командой](items/dev-run-task.md) — Локальная проверка требует ручной чистки каталога данных и остановки процесса, а владельца панели заводят по одноразовой ссылке из журнала.
- [✨ Сделать экран загрузки записи и её состояния](items/upload-and-status-screen.md) — Первое, ради чего приложение открывают: отдать файл и увидеть, что с ним происходит.
- [✨ Сделать экран списка своих записей и чтения текста](items/records-list-screen.md) — Расшифровка сегодня доходит одним сообщением и теряется в переписке; вернуться к ней через неделю нечем.
+47
View File
@@ -0,0 +1,47 @@
# ✨ Уйти с PocketBase на SQLite со своим каталогом файлов
- **Тип:** feature
- **Категория:** Очередь — Всё остальное строится поверх хранилища: экраны пишутся на типах контроллера, а dev-run-task заводит владельца панели, которой не станет
- **Зачем:** Библиотека держит шесть ролей и вышла за адаптер: её типы стоят во всех пяти файлах контроллера и во всех шести его проверках, панель опубликована в интернет вместе с необойдённым /%5f/, а пространство /api/ нельзя закрыть на прокси, потому что за файлами туда ходит браузер пользователя.
Сервис работает с SQLite напрямую, файлы записей лежат в своём каталоге и
отдаются своим обработчиком, маршруты и слои живут на `net/http`, схему двигают
свои шаги. Панель администратора исчезает вместе с адресами `/_/` и `/api/`.
Решение — [ADR-2026-08-22-storage-without-pocketbase](../../docs/adr/ADR-2026-08-22-storage-without-pocketbase.md),
разведка — [storage-without-pocketbase](../../docs/research/storage-without-pocketbase.md).
## Затрагивает
- каталог `internal/adapter/repo/pocketbase` целиком и его шаги схемы;
- каталог `internal/controller/http` целиком вместе с проверками;
- подъём сервера и цепочку слоёв в `cmd/transcriber/main.go`;
- раскладку каталога данных: файл базы и каталог файлов записей — **необратимое**;
- публичный контракт HTTP: пространство `/api/` и адрес `/_/` исчезают, корень
`/app/` остаётся;
- отдачу файла записи браузеру: короткий токен файла и защищённое поле коллекции;
- панель администратора как инструмент владельца сервиса;
- ключ конфига `[storage] data_dir` и перечень зависимостей `go.mod`;
- модель угроз: адрес `/_/`, дефект `/%5f/` и правило прокси на пространство
хранилища.
## Критерии приёмки
- Библиотеки нет в сборке. **Оракул:** `go list -deps ./... | grep -c pocketbase`
даёт `0`, а `go mod tidy` не возвращает её модулей в `go.mod`.
- Чужой файл недостижим по прямой ссылке. **Оракул:** тест контроллера — запрос
к файлу чужой записи и к несуществующей отвечает одинаково.
- Захват записи остаётся неделимым. **Оракул:** тест с параллельными воркерами
под `-race` — запись достаётся ровно одному, второй получает отказ по значению
признака захвата.
- Пространства хранилища не существует. **Оракул:** тест маршрутов — `/api/…`,
`/_/` и `/%5f/` отвечают тем же, чем всякий неизвестный путь.
- Схема накатывается на пустом каталоге до старта воркеров. **Оракул:** запуск на
чистом каталоге данных — ни одного отказа в журнале до первой строки о готовности.
## Рамки
Данные не переносятся: стройка, на сервере пусто. Панель не заменяется ничем —
остановленную запись возвращает в работу запрос к базе, пока этого не сделают
экраны владельца. Очередь остаётся своей таблицей с захватом одним запросом
`RETURNING`. Боевой каталог данных не трогать.