- archive local-fs-storage-backend, sqlite-metadata-backend, storage-orphan-reconciliation, metadata-managed-jwt-secret, default-local-backends - sync specs: storage-backends, metadata-backends, storage-reconciliation, app-secrets; update photos/share-links - defaults reflected in specs: SQLite and local FS
112 lines
7.6 KiB
Markdown
112 lines
7.6 KiB
Markdown
# storage-backends Specification
|
|
|
|
## Purpose
|
|
Выбор и работа объектного хранилища: S3-совместимое (Garage) или локальная файловая
|
|
система. Блобы всегда отдаются через бэкенд по подписанному URL, хранилище клиенту не
|
|
раскрывается.
|
|
|
|
## Requirements
|
|
|
|
### Requirement: Выбор бэкенда хранилища
|
|
Система SHALL поддерживать выбор бэкенда объектного хранилища параметром конфигурации,
|
|
при этом локальная файловая система SHALL быть значением по умолчанию.
|
|
|
|
#### Scenario: Выбор по умолчанию
|
|
- **WHEN** бэкенд хранилища не задан в конфигурации
|
|
- **THEN** система хранит и отдаёт блобы из локальной файловой системы с корнем по умолчанию
|
|
|
|
#### Scenario: Выбор S3-совместимого бэкенда
|
|
- **WHEN** в конфигурации задан S3-совместимый бэкенд
|
|
- **THEN** система хранит и отдаёт блобы через S3-совместимое хранилище
|
|
|
|
#### Scenario: Выбор локальной ФС
|
|
- **WHEN** в конфигурации задан бэкенд локальной ФС
|
|
- **THEN** система хранит и отдаёт блобы из каталога локальной файловой системы
|
|
|
|
#### Scenario: Неполная конфигурация
|
|
- **WHEN** конфигурация выбранного бэкенда неполна
|
|
- **THEN** система отказывается стартовать с явной ошибкой конфигурации
|
|
|
|
### Requirement: Единая абстракция хранилища
|
|
Операции записи, чтения, удаления и проверки доступности SHALL выполняться через единый
|
|
интерфейс хранилища, одинаковый для всех бэкендов; ключи объектов SHALL оставаться
|
|
непрозрачными и независимыми от бэкенда.
|
|
|
|
#### Scenario: Ключи переносимы между бэкендами
|
|
- **WHEN** один и тот же ключ объекта используется на разных бэкендах
|
|
- **THEN** он адресует тот же логический блоб без изменения формата
|
|
|
|
#### Scenario: Удаление объекта
|
|
- **WHEN** система удаляет объект через интерфейс хранилища
|
|
- **THEN** блоб удаляется выбранным бэкендом
|
|
|
|
### Requirement: Отдача блобов через бэкенд
|
|
Клиент SHALL получать любой блоб по URL, обслуживаемому бэкендом, с ограниченным сроком
|
|
действия; ни один бэкенд SHALL не отдавать клиенту ссылку напрямую на объектное
|
|
хранилище. Для анонимного доступа по share-ссылке подписанный URL SHALL быть действителен
|
|
без пользовательской сессии.
|
|
|
|
#### Scenario: Свежий URL просмотра
|
|
- **WHEN** клиент запрашивает фото
|
|
- **THEN** система возвращает подписанный URL бэкенда со сроком действия до 1 часа
|
|
|
|
#### Scenario: Доступ по share-ссылке
|
|
- **WHEN** аноним открывает альбом по действующей share-ссылке
|
|
- **THEN** полученные подписанные URL позволяют загрузить фото без сессии
|
|
|
|
#### Scenario: Истёкшая подпись
|
|
- **WHEN** клиент обращается к URL с истёкшей или неверной подписью
|
|
- **THEN** система отказывает в доступе
|
|
|
|
### Requirement: Хранилище не раскрывается клиенту
|
|
Адрес и учётные данные объектного хранилища SHALL оставаться внутренними; клиент SHALL
|
|
взаимодействовать с медиа только через бэкенд, независимо от бэкенда хранения.
|
|
|
|
#### Scenario: S3-совместимый бэкенд
|
|
- **WHEN** хранилищем выбран S3-совместимый бэкенд
|
|
- **THEN** выдаваемый клиенту URL указывает на бэкенд, а не на S3-эндпоинт
|
|
|
|
#### Scenario: Локальная ФС
|
|
- **WHEN** хранилищем выбрана локальная ФС
|
|
- **THEN** выдаваемый клиенту URL указывает на бэкенд
|
|
|
|
#### Scenario: Хранилище недоступно извне
|
|
- **WHEN** объектное хранилище недоступно из внешней сети
|
|
- **THEN** просмотр и скачивание медиа продолжают работать
|
|
|
|
### Requirement: Локальное хранение на ФС
|
|
Бэкенд локальной ФС SHALL хранить блобы в пределах заданного корневого каталога по
|
|
непрозрачным ключам объектов и SHALL отвергать ключи, выводящие за пределы корня.
|
|
|
|
#### Scenario: Запись и чтение блоба
|
|
- **WHEN** система сохраняет объект с ключом
|
|
- **THEN** блоб размещается под корневым каталогом и позже читается по тому же ключу
|
|
|
|
#### Scenario: Попытка выхода из корня
|
|
- **WHEN** ключ содержит элементы обхода каталога
|
|
- **THEN** система отвергает операцию и не обращается за пределы корня
|
|
|
|
### Requirement: Диапазонные запросы и тип содержимого
|
|
При отдаче блоба система SHALL возвращать корректный тип содержимого и SHALL
|
|
поддерживать диапазонные запросы для докачки и больших файлов.
|
|
|
|
#### Scenario: Запрос диапазона
|
|
- **WHEN** клиент запрашивает часть блоба через диапазон
|
|
- **THEN** система возвращает запрошенный диапазон и соответствующий статус
|
|
|
|
#### Scenario: Тип содержимого
|
|
- **WHEN** клиент загружает блоб
|
|
- **THEN** ответ содержит тип содержимого, соответствующий объекту
|
|
|
|
### Requirement: Доступность выбранного хранилища
|
|
Система SHALL сообщать о доступности выбранного бэкенда хранилища и отражать его в
|
|
состоянии здоровья сервиса.
|
|
|
|
#### Scenario: Хранилище доступно
|
|
- **WHEN** выбранный бэкенд отвечает на проверку
|
|
- **THEN** состоянии здоровья отражает хранилище как доступное
|
|
|
|
#### Scenario: Хранилище недоступно
|
|
- **WHEN** выбранный бэкенд не отвечает на проверку
|
|
- **THEN** состояние здоровья отражает деградацию
|