# ADR-020: Схема SQLite, миграции и драйвер ## Контекст ADR-003 выбирает SQLite, но не схему и не драйвер. Выбор драйвера решает, нужен ли cgo: от этого зависит, можно ли собрать бинарь для Linux на Mac одной командой. Формулировка «ровно три внешних пакета» требует уточнения: прямые зависимости или всё содержимое `go.sum`. ## Решение - Драйвер — `modernc.org/sqlite`, чистый Go. Сборка с `CGO_ENABLED=0`, кросс-компиляция тривиальна. - «Три внешних пакета» — три прямые зависимости в `go.mod`: `modernc.org/sqlite`, `github.com/SherClockHolmes/webpush-go`, `golang.org/x/crypto` (ради `argon2`). Их транзитивные зависимости допускаются: они не выбираются нами и не импортируются напрямую. - Режим базы: `journal_mode=WAL`, `busy_timeout=5000`, `foreign_keys=ON`, `synchronous=NORMAL`. Один файл, путь из конфигурации. - Миграции — нумерованные SQL-файлы, встроенные в бинарь через `embed`. Версия схемы — `PRAGMA user_version`. При старте сервер применяет недостающие миграции по порядку, каждую в своей транзакции. Откатов нет: новая миграция исправляет предыдущую. - Таблицы: `users`, `sessions`, `devices`, `contacts`, `rooms`, `room_members`, `room_keys`, `queue`. Полная схема — `docs/storage.md`. Никаких таблиц с историей сообщений. - Фоновые задачи раз в час: удаление из `queue` записей старше 30 дней, устройств с `last_seen` старше 90 дней, истёкших сессий, лишних ключей комнат сверх двух последних. ## Следствия - `go build` без тулчейна C. Деплой — `GOOS=linux GOARCH=amd64 CGO_ENABLED=0 go build`. - `modernc.org/sqlite` медленнее cgo-варианта в разы на тяжёлых запросах. Для очереди и метаданных маленького чата это незаметно. - Бэкап — копия файла базы при остановленном сервере или `VACUUM INTO`. WAL-файл без основного файла бесполезен.