# 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** приложение не разгружает их повторно, пока альбом не переведён в режим переноса снова