Files
iu 8638d1bbfc chore(openspec): archive completed changes and sync main specs
- 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
2026-10-11 10:19:44 +03:00

80 lines
5.5 KiB
Markdown

# metadata-backends Specification
## Purpose
Выбор и работа слоя метаданных: внешняя PostgreSQL или встроенная SQLite, с
паритетным поведением для одного экземпляра приложения.
## Requirements
### Requirement: Выбор бэкенда метаданных
Система SHALL поддерживать выбор бэкенда слоя метаданных параметром конфигурации,
при этом встроенная SQLite SHALL быть значением по умолчанию.
#### Scenario: Выбор по умолчанию
- **WHEN** бэкенд метаданных не задан в конфигурации
- **THEN** система использует встроенную SQLite с путём по умолчанию
#### Scenario: Выбор PostgreSQL
- **WHEN** в конфигурации задан бэкенд PostgreSQL
- **THEN** метаданные читаются и пишутся во внешнюю PostgreSQL
#### Scenario: Выбор встроенной SQLite
- **WHEN** в конфигурации задан бэкенд SQLite
- **THEN** метаданные читаются и пишутся в локальный файл SQLite без внешней службы
#### Scenario: Неполная конфигурация
- **WHEN** конфигурация выбранного бэкенда неполна
- **THEN** система отказывается стартовать с явной ошибкой конфигурации
### Requirement: Паритет поведения бэкендов
Оба бэкенда метаданных SHALL обеспечивать одинаковое наблюдаемое поведение системы:
аутентификацию, альбомы, роли и доступ, фото, объектный журнал, сборку мусора и
очередь генерации вариантов.
#### Scenario: Одинаковое поведение API
- **WHEN** один и тот же сценарий выполняется на PostgreSQL и на SQLite
- **THEN** наблюдаемые результаты и ошибки API совпадают
#### Scenario: Соблюдение прав доступа
- **WHEN** на любом бэкенде участник без прав выполняет запрещённое действие
- **THEN** система отклоняет действие одинаковым образом
### Requirement: Встроенный одиночный экземпляр
Бэкенд SQLite SHALL работать как самодостаточный режим для одного экземпляра приложения,
и система SHALL отвергать или явно документировать использование одного файла SQLite
несколькими экземплярами.
#### Scenario: Один экземпляр
- **WHEN** приложение запущено в единственном экземпляре
- **THEN** SQLite корректно обслуживает всех пользователей этого экземпляра
#### Scenario: Совместная работа с файлом
- **WHEN** предполагается совместная работа нескольких экземпляров с одним файлом SQLite
- **THEN** конфигурация считает такой режим неподдерживаемым
### Requirement: Атомарность жизненного цикла объектов
На обоих бэкендах привязка готового объекта к фото и заявка объекта на удаление SHALL
быть атомарными и SHALL исключать привязку объекта, который собирается быть удалён, и
удаление используемого объекта.
#### Scenario: Конкурентная привязка и сборка мусора
- **WHEN** привязка объекта и заявка на его удаление происходят одновременно
- **THEN** система либо привязывает объект без удаления, либо удаляет его без привязки
#### Scenario: Повторная привязка
- **WHEN** объект уже привязан к фото в роли
- **THEN** повторная привязка приводит к согласованному состоянию без дублей
### Requirement: Устойчивость к перезапуску
Очередь генерации вариантов и сборка мусора SHALL восстанавливаться из состояния слоя
метаданных после перезапуска на обоих бэкендах, и система SHALL применять схему
метаданных при старте.
#### Scenario: Незавершённые задания
- **WHEN** процесс перезапускается с незавершёнными заданиями генерации вариантов
- **THEN** обработка заданий продолжается
#### Scenario: Применение схемы
- **WHEN** приложение стартует с выбранным бэкендом
- **THEN** схема метаданных выбранного бэкенда приведена к актуальному состоянию