# 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** она использует выбранные бэкенды хранения и метаданных без изменений кода