Files
iu 3a44844ff9 chore(openspec): архивировать fix-album-sync-churn-and-degradation и синхронизировать спеки
В спеку phone-album-sync добавлены требования о роли локального файла,
подтверждении новой версии до удаления устаревшей и разгрузке без
незавершённой загрузки; уточнены синхронизация изменений, провенанс и
возврат оригиналов.
2026-10-20 20:35:52 +03:00

13 KiB

Spec Delta

ADDED Requirements

Requirement: Роль локального файла не является содержимым

Приложение SHALL отличать превью, созданное им самим при разгрузке (в том числе по метке провенанса), от новой версии оригинала: разгруженный элемент SHALL NOT загружаться повторно и SHALL NOT вызывать удаление серверной копии, а расхождение состояния в локальном индексе SHALL выправляться. Это SHALL относиться и к постеру, которым в режиме переноса заменяется видео.

Scenario: Разгруженный элемент не создаёт новую версию

  • WHEN серверная копия элемента есть в целевом альбоме, а на устройстве лежит созданное приложением превью, в том числе если состояние локального индекса ошибочно указывает оригинал
  • THEN приложение не ставит загрузку и не удаляет серверную копию

Scenario: Состояние выправляется

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

Scenario: Постер разгруженного видео

  • WHEN видео разгружено (заменено постером под новым элементом MediaStore), а его метка указывает на исходное видео
  • THEN приложение связывает элемент с серверным фото видео и не удаляет это фото на сервере, а постер не загружается как новое фото

Scenario: Настоящее изменение содержимого

  • WHEN содержимое медиа заменено содержимым, не созданным приложением при разгрузке
  • THEN приложение загружает новую версию элемента

Requirement: Подтверждение новой версии до удаления устаревшей

Устаревшая собственная загрузка элемента SHALL удаляться только после подтверждения новой версии: сообщённая сервером контрольная сумма принятого объекта SHALL совпадать с отправленной. При расхождении приложение SHALL отклонить загрузку, удалив принятую копию, и SHALL NOT считать элемент загруженным. Если сервер контрольную сумму не сообщил, загрузка SHALL считаться состоявшейся, но устаревшая копия SHALL NOT удаляться, а замена SHALL повториться при следующей синхронизации.

Scenario: Новая версия подтверждена

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

Scenario: Контрольная сумма не совпала

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

Scenario: Контрольная сумма не сообщена

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

Scenario: Загрузка не удалась

  • WHEN загрузка новой версии завершилась ошибкой
  • THEN прежняя серверная копия остаётся в альбоме

Requirement: Разгрузка без незавершённой загрузки

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

Scenario: Загрузка в очереди

  • WHEN для элемента есть задание загрузки в очереди или выполняющееся
  • THEN оригинал на устройстве не заменяется превью

Scenario: Загрузка подтверждена

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

MODIFIED Requirements

Requirement: Синхронизация изменений с сервером

Для каждого отслеженного изменения приложение SHALL применить его к целевому серверному альбому: загрузить новое содержимое, переименовать и перенести через API. Изменение содержимого SHALL трактоваться как новая загрузка, а устаревшая собственная загрузка SHALL удаляться после подтверждения новой версии и SHALL NOT удаляться из-за смены локальной роли файла (оригинал ↔ превью).

Scenario: Новое содержимое

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

Scenario: Переименование доходит до сервера

  • WHEN медиа переименовано на устройстве и уже синхронизировано
  • THEN приложение переименовывает соответствующее серверное фото

Scenario: Изменение содержимого

  • WHEN содержимое медиа изменено на устройстве
  • THEN приложение загружает новую версию и после её подтверждения удаляет устаревшую собственную загрузку

Requirement: Провенанс разгруженных превью

Разгруженные превью, постеры видео и скачанные с сервера элементы SHALL содержать метаданные провенанса, включая признак происхождения (загружено клиентом или скачано с сервера), достаточные для восстановления связи с серверным альбомом и принадлежности загрузок после переустановки приложения. Метка SHALL также служить признаком того, что локальный файл является созданным приложением превью: элемент с такой меткой SHALL NOT считаться содержащим оригинал, даже если состояние локального индекса утверждает обратное.

Scenario: Восстановление после переустановки

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

Scenario: Метка скачанного элемента

  • WHEN метка провенанса восстанавливается у элемента, скачанного с сервера
  • THEN элемент восстанавливается как скачанный, а не как собственная загрузка клиента

Scenario: Метка утрачена

  • WHEN метаданные провенанса недоступны (например, файл перезаписан сторонним редактором)
  • THEN элемент считается неопознанным, не удаляется и не загружается повторно

Scenario: Метка против состояния индекса

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

Requirement: Возврат оригиналов и отвязка

При выходе из режима C приложение SHALL предложить вернуть оригиналы на устройство и SHALL предупредить, если пользователь отказывается. Отвязка альбома и выключение синхронизации SHALL NOT удалять фото с сервера, а скачанные с сервера файлы SHALL оставаться в галерее как обычные. Выключение синхронизации SHALL быть явным и устойчивым: восстановление происхождения SHALL NOT возобновлять связь, пока пользователь не включит синхронизацию снова.

Scenario: Возврат оригиналов

  • WHEN пользователь выходит из режима C и соглашается вернуть оригиналы
  • THEN приложение возвращает оригиналы на устройство вместо превью

Scenario: Отказ от возврата

  • WHEN пользователь выходит из режима C и отказывается возвращать оригиналы
  • THEN приложение предупреждает, что на устройстве останутся только превью

Scenario: Отвязка

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

Scenario: Выключение синхронизации

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

Scenario: Выключение не отменяется восстановлением

  • WHEN пользователь выключил синхронизацию (или отвязал альбом), и затем выполняется проверка с восстановлением происхождения по меткам превью
  • THEN связь не восстанавливается, а альбом остаётся локальным с выбранным режимом выключено

Scenario: Повторное включение

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

Scenario: Возврат устойчив

  • WHEN оригиналы возвращены на устройство после выхода из режима переноса
  • THEN приложение не разгружает их повторно, пока альбом не переведён в режим переноса снова