Files
ds-galo/openspec/changes/archive/2026-10-16-phone-album-two-way-sync/proposal.md
T
iu cc85d792ea chore(openspec): архивировать phone-album-two-way-sync и синхронизировать спеки
Дельта-спеки перенесены в основные: phone-album-sync (+8 требований, 6 изменено,
1 удалено — «Удаление только собственных загрузок»), android-client.

Change перемещён в openspec/changes/archive/2026-10-16-phone-album-two-way-sync.
2026-10-16 23:20:04 +03:00

60 lines
5.5 KiB
Markdown

# Proposal
## Why
Синхронизация альбома устройства сегодня односторонняя по содержимому: устройство отдаёт
байты, сервер возвращает только метаданные. Фото, добавленное в целевой серверный альбом из
веба или с другого устройства, на телефон не приезжает, а связанный серверный альбом ещё и
скрыт из списка — увидеть его в приложении нельзя. Пользователь ожидает, что
синхронизированный альбом — один и тот же набор медиа на телефоне и на сервере.
## What Changes
- Связанная пара «альбом устройства → серверный альбом» становится **двусторонним миррором**:
состав медиа совпадает, добавление и удаление ходят в обе стороны.
- **Материализация серверных фото на устройстве**: в режиме копий (B) скачивается оригинал, в
режиме переноса (C) — превью (для видео — постер). Файлы пишутся в галерею (MediaStore)
бакета альбома устройства и видны системной галерее.
- Вводится явный **признак происхождения** элемента (`own` — загружено этим клиентом,
`mirror` — скачано с сервера). Политика удалений, разгрузка и восстановление после
переустановки опираются на него, а не на наличие `serverPhotoId`.
- **Удаление в обе стороны**: удаление элемента на устройстве удаляет соответствующее фото на
сервере (мягко, в корзину); серверное удаление убирает локальный элемент. Удаление
принадлежащего иному источнику элемента на устройстве подчиняется правам сервера.
- **Журнал удалений (надгробия)**: локально удалённый элемент не скачивается заново, пока
серверное удаление не подтверждено; серверные события не дают эха.
- Восстановление серверного фото из корзины заново материализует элемент на устройстве.
- **Отвязка и выключение синхронизации** остаются неразрушающими: фото на сервере сохраняются,
уже скачанные файлы остаются в галерее как обычные.
- **Выключение синхронизации устойчиво**: восстановление происхождения по меткам превью не
возобновляет связь, пока пользователь не включит синхронизацию снова.
- **Первый проход**: выбор «скачать всё содержимое альбома» или «только новое с этого момента»;
ограничение «только Wi-Fi» распространяется и на скачивание.
- **BREAKING**: нет — поведение аддитивное, существующие связи продолжают работать.
## Capabilities
### New Capabilities
Нет — поведение относится к существующей способности синхронизации альбома устройства.
### Modified Capabilities
- `phone-album-sync`: двусторонний миррор — материализация серверных фото по режимам, признак
происхождения, надгробия, политика удалений в обе стороны, восстановление из корзины,
поведение при отвязке.
- `android-client`: сетка альбома устройства включает скачанные (серверные) элементы, а
связанный альбом читается как один двусторонний альбом.
## Impact
- `android/`: движок синхронизации (`data/sync/*` — `SyncPlan`, `SyncCoordinator`, `SyncCheck`,
`SyncRecovery`, `ProvenanceStamp`, `OffloadManager`, `RestoreManager`, `LocalAssetProvider`),
новый загрузчик серверных фото, запись в MediaStore без диалога согласия (файлы приложения),
Room-схема (признак происхождения, надгробия, watermark первого прохода), UI
(`DeviceAlbumScreen`/`DeviceAlbumViewModel`, `AlbumsScreen`/`AlbumListBuilder`,
`SyncRepository`).
- `backend/`: изменений API не требуется — `preview_url`/`medium_url`/`original_url`, `?since=`,
мягкое удаление и восстановление из корзины уже есть.
- Спеки: `phone-album-sync`, `android-client`.