Files
ds-galo/openspec/specs/storage-reconciliation/spec.md
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

4.4 KiB

storage-reconciliation Specification

Purpose

Ручная сверка объектного хранилища с журналом метаданных: инвентаризация обеих сторон, отчёт о расхождениях и безопасное удаление осиротевших блобов.

Requirements

Requirement: Инвентаризация хранилища

Слой хранения SHALL перечислять объекты под заданным префиксом, возвращая ключ, размер и время изменения, независимо от бэкенда (S3-совместимое или локальная ФС).

Scenario: Перечисление в S3-совместимом хранилище

  • WHEN запрашивается список объектов под префиксом
  • THEN возвращаются все ключи с этим префиксом с их размером и временем изменения

Scenario: Перечисление в локальной ФС

  • WHEN хранилищем выбрана локальная ФС
  • THEN возвращаются ключи всех блобов под префиксом с их размером и временем изменения

Requirement: Инвентаризация журнала

Слой метаданных SHALL возвращать все ключи, зарегистрированные в журнале objects, на обоих бэкендах (PostgreSQL и SQLite).

Scenario: Ключи журнала

  • WHEN запрашиваются ключи журнала
  • THEN возвращается множество ключей всех строк objects

Requirement: Отчёт о расхождениях

По умолчанию сверка SHALL выполняться в режиме отчёта и SHALL не изменять хранилище; отчёт SHALL различать сироты (в хранилище есть, в журнале нет) и пропавшие (в журнале есть, в хранилище нет).

Scenario: Только отчёт

  • WHEN сверка запущена без флага удаления
  • THEN система выводит число и примеры сирот и пропавших, ничего не удаляя

Scenario: Пропавшие не восстанавливаются

  • WHEN ключ есть в журнале, но отсутствует в хранилище
  • THEN он сообщается как пропавший и не создаётся и не удаляется

Requirement: Удаление сирот по явному запросу

Удаление сирот SHALL выполняться только по явному флагу, только для ключей под префиксом объектов и только для блобов старше заданного минимального возраста.

Scenario: Удаление включено

  • WHEN сверка запущена с флагом удаления
  • THEN сироты старше минимального возраста удаляются из хранилища, а более молодые пропускаются

Scenario: Защита от гонки с загрузкой

  • WHEN блоб создан недавно (моложе минимального возраста)
  • THEN он не удаляется, даже если строки в журнале ещё нет

Scenario: Ограничение области

  • WHEN удаление включено
  • THEN удаляются только ключи под префиксом объектов, остальные не затрагиваются

Requirement: Независимость от бэкендов

Сверка SHALL работать с любой комбинацией бэкенда хранения (S3 или ФС) и бэкенда метаданных (PostgreSQL или SQLite).

Scenario: Комбинации бэкендов

  • WHEN сверка запускается на выбранной конфигурации
  • THEN она использует выбранные бэкенды хранения и метаданных без изменений кода