хранилище переехало с PocketBase на SQLite со своим каталогом файлов

- база своя: два пула, захват одним UPDATE ... RETURNING, шаги схемы на goose
  под файловым замком, одна миграция начальной схемы вместо семи прежних
- транспорт переписан на net/http: свои слои, свой ограничитель частоты,
  отдача файла с проверкой владельца; панель /_/ и пространство /api/ исчезли
- по находкам ревью: журнал не пишет путь под корнем приложения, ключ бюджета
  читается справа налево, узнавание известного идёт читающим пулом
This commit is contained in:
av
2026-08-23 08:06:04 +03:00
parent 1edf8cb225
commit c9b7765646
118 changed files with 11668 additions and 6679 deletions
+22
View File
@@ -8,6 +8,11 @@ import (
// ErrOwnerRequired — приём по HTTP дошёл до заведения задачи, а владельца ему не
// назвали. Значение сентинельное: нести отказу нечего, а имя учётной записи в
// него не кладётся никогда.
//
// Достижимого случая у него нет: узнавание заводит учётную запись само, и
// предъявителя без неё под корнем приложения не бывает. Отдельной ветви ответа
// он поэтому не получает — ветвь по умолчанию читает его как аварию сервиса,
// каковой он и был бы.
var ErrOwnerRequired = errors.New("owner is required to accept a record")
// ErrRecordUnreadable — присланную запись не удалось прочитать: источник
@@ -31,6 +36,18 @@ var ErrRecordTooLarge = errors.New("uploaded record exceeds size limit")
// человек увидел бы «не найдено» на своей записи, загруженной минуту назад.
var ErrTextNotReady = errors.New("requested text view is not ready yet")
// ErrCopyNotReady — копии записи запрошенного вида у неё ещё нет. Состояние, а
// не отсутствие, и код у него тот же, что у ненаписанного текста: пустой ответ
// читался бы как пустой файл, а «не найдено» слилось бы с ответом на чужую и
// неизвестную запись — человек увидел бы его на своей записи, загруженной
// минуту назад.
var ErrCopyNotReady = errors.New("requested file copy is not ready yet")
// ErrTooManyRequests — бюджет ограничителя частоты выбран. Признак заводится
// затем, чтобы отказ ограничителя уходил той же формой тела, что и отказ
// обработчика: он рождается слоем и до обработчика не доходит вовсе.
var ErrTooManyRequests = errors.New("request rate budget is exhausted")
// ErrBadRequest — во входе запроса негодное значение: неизвестный вид текста,
// нечитаемый ключ страницы, отрицательный размер. Отличается от ErrRecordUnreadable
// тем, что негодна **просьба**, а не присланная запись.
@@ -47,6 +64,11 @@ var ErrUnauthorized = errors.New("session is required")
// отсутствующий адрес отсутствующей записью.
var ErrNotFound = errors.New("address not found")
// ErrLoginNotAcceptable — логин негоден: пустой, из одних пробельных знаков,
// длиннее предела или с управляющими знаками. Это не отказ хранилища, а негодный
// ввод, и звать по нему учётную запись не надо.
var ErrLoginNotAcceptable = errors.New("provider login is not acceptable")
type JobNotFoundError struct {
State string
Message string