Files
ds-galo/openspec/specs/phone-album-sync/spec.md
T
iu 98aaa3156a chore(openspec): архивировать add-orphaned-preview-handling и синхронизировать спеки
Новое требование в phone-album-sync о потере/возврате серверной копии у
разгруженного превью, требование в android-client о метке потерянного элемента
и действии удаления с устройства.
2026-10-16 14:13:01 +03:00

306 lines
20 KiB
Markdown

# phone-album-sync Specification
## Purpose
Синхронизация альбома устройства с существующим серверным альбомом: режимы A/B/C,
отслеживание изменений, идентичность и дедупликация, политика удалений, разгрузка
места и провенанс разгруженных превью.
## Requirements
### Requirement: Режимы синхронизации альбома устройства
Альбом устройства SHALL иметь выбираемый режим синхронизации: выключена (A — только
локально), копии оригиналов на сервере (B), перенос оригиналов на сервер (C). Пока
режим A, приложение SHALL показывать альбом локально и SHALL NOT обращаться к
серверу по этому альбому.
#### Scenario: Выключенная синхронизация
- **WHEN** у альбома устройства выбран режим A
- **THEN** приложение показывает альбом из локальных файлов и не отправляет запросы на сервер по этому альбому
#### Scenario: Копии оригиналов
- **WHEN** у альбома устройства выбран режим B
- **THEN** оригиналы остаются на устройстве, а их копии загружаются в целевой серверный альбом
#### Scenario: Перенос оригиналов
- **WHEN** у альбома устройства выбран режим C
- **THEN** оригиналы загружаются на сервер, а на устройстве вместо них остаются превью
### Requirement: Выбор целевого серверного альбома
При включении синхронизации пользователь SHALL выбрать серверный альбом назначения —
существующий или созданный на месте, с именем, предзаполненным именем альбома
устройства. Несколько альбомов устройства SHALL иметь возможность указывать на один
серверный альбом.
#### Scenario: Выбор цели
- **WHEN** пользователь включает синхронизацию альбома устройства
- **THEN** приложение предлагает выбрать существующий серверный альбом или создать новый с предзаполненным именем и сохраняет выбор
#### Scenario: Несколько источников в одну цель
- **WHEN** два альбома устройства указывают на один серверный альбом
- **THEN** оба синхронизируются в него, а связь каждого отражается отдельно
### Requirement: Отслеживание изменений на устройстве
Приложение SHALL отслеживать изменения содержимого синхронизируемого альбома
устройства — добавление, удаление, переименование, перенос между альбомами и
изменение содержимого — и SHALL хранить локальный индекс, позволяющий обнаружить
удаления, произошедшие вне приложения.
#### Scenario: Добавление
- **WHEN** в альбоме устройства появляется новое медиа
- **THEN** приложение фиксирует его как новое и ставит в очередь синхронизации
#### Scenario: Удаление вне приложения
- **WHEN** медиа удалено из альбома устройства другим приложением или системной галереей
- **THEN** приложение обнаруживает отсутствие по локальному индексу
#### Scenario: Переименование и перенос
- **WHEN** медиа переименовано или перемещено между альбомами устройства
- **THEN** приложение фиксирует изменение имени или принадлежности альбому
### Requirement: Синхронизация изменений с сервером
Для каждого отслеженного изменения приложение SHALL применить его к целевому
серверному альбому: загрузить новое содержимое, переименовать и перенести через
API, а изменение содержимого SHALL трактовать как новую загрузку с удалением
устаревшей собственной загрузки.
#### Scenario: Новое содержимое
- **WHEN** в альбоме устройства появилось медиа, которого нет на сервере
- **THEN** приложение загружает его в целевой серверный альбом
#### Scenario: Переименование доходит до сервера
- **WHEN** медиа переименовано на устройстве и уже синхронизировано
- **THEN** приложение переименовывает соответствующее серверное фото
#### Scenario: Изменение содержимого
- **WHEN** содержимое медиа изменено на устройстве
- **THEN** приложение загружает новую версию, а устаревшую собственную загрузку удаляет
### Requirement: Идентичность по контрольной сумме
Приложение SHALL сопоставлять локальный ассет с серверным фото по контрольной сумме
содержимого и SHALL NOT повторно загружать содержимое, уже присутствующее на
сервере.
#### Scenario: Повторная синхронизация
- **WHEN** синхронизация запускается повторно без изменений содержимого
- **THEN** приложение не создаёт новых загрузок
#### Scenario: Уже загруженное содержимое
- **WHEN** содержимое ассета уже присутствует на сервере (в том числе загружено ранее)
- **THEN** приложение связывает ассет с существующим серверным фото без загрузки
### Requirement: Удаление только собственных загрузок
При удалении содержимого на устройстве приложение SHALL удалять на сервере только
фото, загруженные этим клиентом, и SHALL сохранять остальные фото целевого альбома,
в том числе загруженные из других источников.
#### Scenario: Собственная загрузка
- **WHEN** удалено содержимое, которое загрузил этот клиент, и его контрольная сумма отсутствует во всех локальных альбомах, льющихся в этот серверный
- **THEN** приложение удаляет соответствующее серверное фото
#### Scenario: Чужие фото
- **WHEN** в целевом серверном альбоме есть фото, загруженные из других источников
- **THEN** приложение не удаляет их
### Requirement: Отражение серверных изменений на устройстве
Приложение SHALL отражать изменения целевого серверного альбома — новые фото,
переименования, теги, подписи и удаления — в локальном представлении, SHALL NOT
изменять или удалять оригиналы на устройстве.
#### Scenario: Новое с другого устройства
- **WHEN** другое устройство добавляет фото в целевой серверный альбом
- **THEN** приложение показывает его в серверном представлении альбома
#### Scenario: Удалено на сервере
- **WHEN** серверное фото удалено на сервере
- **THEN** приложение убирает его из локального представления, не трогая оригинал на устройстве
### Requirement: Разгрузка оригиналов в режиме переноса
В режиме C после успешной загрузки приложение SHALL автоматически заменять оригинал
на устройстве превью, без отдельного действия на экране; видео SHALL заменяться
постером-кадром. При включении режима C приложение SHALL запрашивать широкий доступ
к файлам, чтобы замена выполнялась без системного диалога согласия.
#### Scenario: Разгрузка фото
- **WHEN** оригинал фото успешно загружен
- **THEN** файл в галерее автоматически заменяется превью с сохранением даты съёмки и места в альбоме
#### Scenario: Разгрузка видео
- **WHEN** оригинал видео успешно загружен
- **THEN** видео в галерее автоматически заменяется статичным постером-кадром, а элемент в приложении остаётся видео с оригиналом на сервере
#### Scenario: Доступ к файлам для разгрузки
- **WHEN** пользователь включает режим переноса
- **THEN** приложение запрашивает широкий доступ к файлам, и разгрузка выполняется без системного диалога согласия
### Requirement: Провенанс разгруженных превью
Разгруженные превью и постеры видео SHALL содержать метаданные провенанса,
достаточные для восстановления связи с серверным альбомом и принадлежности
загрузок после переустановки приложения.
#### Scenario: Восстановление после переустановки
- **WHEN** приложение переустановлено или его данные очищены, а альбом устройства содержит разгруженные превью
- **THEN** приложение восстанавливает связь с серверным альбомом и принадлежность своих загрузок из метаданных превью
#### Scenario: Метка утрачена
- **WHEN** метаданные провенанса недоступны (например, файл перезаписан сторонним редактором)
- **THEN** элемент считается неопознанным, не удаляется и не загружается повторно
### Requirement: Возврат оригиналов и отвязка
При выходе из режима C приложение SHALL предложить вернуть оригиналы на устройство
и SHALL предупредить, если пользователь отказывается. Отвязка альбома и выключение
синхронизации SHALL NOT удалять фото с сервера.
#### Scenario: Возврат оригиналов
- **WHEN** пользователь выходит из режима C и соглашается вернуть оригиналы
- **THEN** приложение возвращает оригиналы на устройство вместо превью
#### Scenario: Отказ от возврата
- **WHEN** пользователь выходит из режима C и отказывается возвращать оригиналы
- **THEN** приложение предупреждает, что на устройстве останутся только превью
#### Scenario: Отвязка
- **WHEN** пользователь отвязывает альбом устройства от серверного
- **THEN** фото на сервере сохраняются
#### Scenario: Выключение синхронизации
- **WHEN** пользователь выключает синхронизацию альбома устройства
- **THEN** связь с серверным альбомом снимается, а фото на сервере сохраняются
### Requirement: Автоматическая фоновая синхронизация
Синхронизация SHALL выполняться автоматически: при открытом приложении — по
событиям изменения, в фоне — периодически, с учётом ограничений сети, выбранных
пользователем. В режиме C разгрузка оригиналов SHALL выполняться автоматически
после успешной загрузки.
#### Scenario: Фоновая синхронизация
- **WHEN** приложение не открыто, а в альбоме устройства появились изменения
- **THEN** синхронизация выполняется в фоне при ближайшей возможности
#### Scenario: Ограничение сети
- **WHEN** включено ограничение «только Wi-Fi», а доступна только сотовая сеть
- **THEN** синхронизация не начинается до появления Wi-Fi
#### Scenario: Автоматическая разгрузка
- **WHEN** оригиналы загружены в режиме C
- **THEN** замена оригиналов превью выполняется автоматически, без отдельного подтверждения
### Requirement: Локальные превью
Приложение SHALL генерировать превью на устройстве и хранить их локально; при
просмотре элемента без локального оригинала приложение SHALL подгружать оригинал с
сервера.
#### Scenario: Сетка из превью
- **WHEN** открыт альбом устройства
- **THEN** сетка показывает локальные превью
#### Scenario: Просмотр без локального оригинала
- **WHEN** пользователь открывает элемент, чей оригинал разгружен на сервер
- **THEN** приложение подгружает оригинал с сервера для полноэкранного просмотра
### Requirement: Обнаружение потери серверной копии превью
При проверке синхронизации приложение SHALL сопоставлять серверное фото каждого
разгруженного превью с фото целевого альбома и при его отсутствии SHALL помечать
элемент как потерявший серверную копию, сохраняя превью и провенанс.
#### Scenario: Копии больше нет
- **WHEN** серверное фото разгруженного превью отсутствует в целевом альбоме
- **THEN** приложение помечает элемент как потерявший серверную копию
#### Scenario: Превью не трогается
- **WHEN** элемент помечен как потерявший серверную копию
- **THEN** превью-файл на устройстве сохраняется и не загружается повторно как оригинал
### Requirement: Восстановление связи при возврате серверного фото
При проверке синхронизации приложение SHALL снимать пометку с элемента, если его
серверное фото снова присутствует в целевом альбоме.
#### Scenario: Фото вернулось на сервер
- **WHEN** серверное фото помеченного элемента снова присутствует в целевом альбоме
- **THEN** элемент возвращается к обычному разгруженному состоянию с серверной копией
### Requirement: Удаление потерянного превью с устройства
Приложение SHALL позволять удалить потерявшее серверную копию превью с устройства;
удаление SHALL удалять превью-файл и запись локального индекса и SHALL NOT
обращаться к серверу, поскольку копии там уже нет.
#### Scenario: Удаление с устройства
- **WHEN** пользователь удаляет потерявшее серверную копию превью с устройства
- **THEN** превью-файл и запись локального индекса удаляются, а сервер не затрагивается
#### Scenario: Согласие системы
- **WHEN** превью-файл не принадлежит приложению
- **THEN** удаление выполняется после системного согласия на удаление
### Requirement: Повторная заливка вернувшегося оригинала
Если содержимое с исходной контрольной суммой потерявшего копию элемента снова
присутствует на устройстве, приложение SHALL загрузить его на сервер как новую
загрузку этого элемента.
#### Scenario: Вернулся в тот же альбом
- **WHEN** оригинал с исходной контрольной суммой снова появился в альбоме устройства
- **THEN** приложение загружает его в целевой серверный альбом
#### Scenario: Вернулся в другой альбом
- **WHEN** содержимое с исходной контрольной суммой присутствует в другом альбоме устройства
- **THEN** приложение загружает его в целевой серверный альбом
#### Scenario: Режим переноса
- **WHEN** загрузка вернувшегося оригинала завершена в режиме переноса
- **THEN** элемент снова проходит обычную разгрузку в превью