chore(openspec): archive completed changes and sync main specs

- fix-large-album-load -> photos, realtime, media-objects
- fix-album-cover -> photos, albums
This commit is contained in:
iu
2026-10-11 14:16:38 +03:00
parent d7a37328f0
commit d99ac77587
17 changed files with 69 additions and 14 deletions
+3 -4
View File
@@ -54,10 +54,10 @@
- **WHEN** у альбома нет обложки или фото обложки удалено
- **THEN** ответ не содержит URL обложки, и клиент показывает плейсхолдер
### Requirement: Выбор обложки
Владелец и админ SHALL иметь возможность назначить обложкой любое фото альбома или сбросить
обложку; после сброса обложка определяется заново по умолчанию.
обложку; после сброса обложка SHALL становиться не заданной (без возврата к значению по
умолчанию).
#### Scenario: Назначение обложки
- **WHEN** владелец выбирает фото альбома как обложку
@@ -65,13 +65,12 @@
#### Scenario: Сброс обложки
- **WHEN** админ сбрасывает обложку
- **THEN** система удаляет явный выбор, и обложка возвращается к значению по умолчанию
- **THEN** система снимает обложку, и альбом отображается без обложки, пока обложку не назначат снова
#### Scenario: Нет прав на смену обложки
- **WHEN** участник без права редактирования пытается сменить обложку
- **THEN** система отклоняет запрос
### Requirement: Счётчики альбома
Данные альбома SHALL включать количество фото и участников, чтобы панель и карточки могли
показать их без отдельных запросов.
+11 -2
View File
@@ -79,7 +79,8 @@ MIME-типом, размером, габаритами и состоянием;
### Requirement: Генерация вариантов
Генерация thumb и preview SHALL выполняться через надёжную очередь заданий с
однократным выполнением и повтором при сбое; готовый результат SHALL
транслироваться подписчикам альбома.
транслироваться подписчикам альбома. Очередь SHALL поддерживать настраиваемую
пропускную способность и SHALL обрабатывать более свежие фото раньше остальных.
#### Scenario: Повтор после рестарта
- **WHEN** процесс перезапускается с незавершёнными заданиями
@@ -87,4 +88,12 @@ MIME-типом, размером, габаритами и состоянием;
#### Scenario: Событие после генерации
- **WHEN** варианты фото готовы
- **THEN** подписчикам альбома публикуется событие с этим фото
- **THEN** подписчикам альбома публикуется событие обновления этого фото
#### Scenario: Приоритет свежих фото
- **WHEN** в очереди есть готовые к обработке задания разного возраста
- **THEN** система обрабатывает более свежие фото раньше
#### Scenario: Настраиваемая пропускная способность
- **WHEN** задан уровень параллелизма генерации
- **THEN** система обрабатывает варианты с этим уровнем параллелизма
+35 -7
View File
@@ -33,11 +33,17 @@
### Requirement: Получение фото по требованию
Клиент SHALL иметь возможность получить актуальные данные фото с подписанным URL,
обслуживаемым бэкендом, независимо от бэкенда хранения.
обслуживаемым бэкендом, независимо от бэкенда хранения. Подпись SHALL быть
детерминированной в пределах окна действия, чтобы повторные выдачи одного и того же
объекта давали идентичный URL.
#### Scenario: Выдача свежего URL
- **WHEN** клиент запрашивает фото по id
- **THEN** система возвращает свежий подписанный URL бэкенда (срок до 1 часа) для просмотра
- **THEN** система возвращает подписанный URL бэкенда для просмотра
#### Scenario: Повторная выдача совпадает
- **WHEN** один и тот же объект запрашивается повторно в пределах окна действия подписи
- **THEN** система возвращает идентичный URL
### Requirement: Скачивание одиночного фото
Любой участник, включая viewer, SHALL иметь возможность скачать одиночное фото.
@@ -58,17 +64,26 @@
- **THEN** система отклоняет запрос
### Requirement: Обложка по умолчанию
При обработке загруженного фото система SHALL назначать его обложкой альбома только если
обложка ещё не задана.
При загрузке фото система SHALL назначать его обложкой альбома, если обложка ещё не задана,
то есть обложкой становится первое загруженное фото. Когда фото, выбранное обложкой, покидает
альбом (помещено в корзину или перенесено в другой альбом), система SHALL снять обложку.
#### Scenario: Первое фото
- **WHEN** фото обработано, и у альбома нет обложки
- **THEN** система назначает это фото обложкой
- **WHEN** фото загружено, и у альбома нет обложки
- **THEN** система назначает это фото обложкой альбома
#### Scenario: Обложка уже задана
- **WHEN** фото обработано, а обложка уже задана
- **WHEN** фото загружено, а обложка уже задана
- **THEN** система не меняет обложку
#### Scenario: Фото-обложка в корзине
- **WHEN** фото, назначенное обложкой, помещается в корзину
- **THEN** система снимает обложку, и альбом отображается без обложки
#### Scenario: Фото-обложка перенесено
- **WHEN** фото, назначенное обложкой, переносится в другой альбом
- **THEN** система снимает обложку исходного альбома
### Requirement: Переименование фото
Автор фото, владелец и админ альбома SHALL иметь возможность изменить имя файла фото;
остальные SHALL получать отказ, а пустое имя SHALL отклоняться.
@@ -171,3 +186,16 @@
#### Scenario: Снятие метки
- **WHEN** пользователь убирает метку с фото
- **THEN** метка отвязывается от фото
### Requirement: Кэширование объектов
Доставка объектов SHALL помечать ответы как кэшируемые, чтобы браузер переиспользовал
уже полученные превью, а повторное открытие альбома не вызывало повторную загрузку
неизменившихся объектов.
#### Scenario: Заголовки кэширования
- **WHEN** клиент получает объект (оригинал, превью или thumb) по подписанному URL
- **THEN** ответ содержит заголовок кэширования с ограниченным сроком годности
#### Scenario: Повторный показ без перезагрузки
- **WHEN** сетка превью перерисовывается, а URL объектов не изменились
- **THEN** браузер отдаёт объекты из кэша без повторного запроса к бэкенду
+20 -1
View File
@@ -14,12 +14,19 @@
- **THEN** система устанавливает text/event-stream и отправляет heartbeat
### Requirement: События альбома
Система SHALL публиковать события photo.created, photo.deleted, comment.created, like.added, like.removed, member.joined, member.left, album.updated.
Система SHALL публиковать события photo.created, photo.updated, photo.deleted,
comment.created, like.added, like.removed, member.joined, member.left, album.updated.
Событие photo.created SHALL обозначать появление фото в альбоме, а готовность вариантов
существующего фото SHALL публиковаться как photo.updated.
#### Scenario: Новое фото
- **WHEN** в альбоме появляется фото
- **THEN** подписчики получают событие photo.created с метаданными и URL превью
#### Scenario: Готовы варианты
- **WHEN** для существующего фото сгенерированы thumb и preview
- **THEN** подписчики получают событие photo.updated с этим фото
### Requirement: Персональный поток
Клиент SHALL иметь возможность подписаться на персональный поток (приглашения, уведомления).
@@ -47,3 +54,15 @@
#### Scenario: Переподключение
- **WHEN** клиент переподключается после разрыва
- **THEN** клиент догоняет события через запрос фото с параметром since
### Requirement: Различение добавления и обновления фото
Клиент SHALL различать добавление нового фото в альбом и обновление уже показанного:
обновление SHALL изменять фото на месте, не меняя порядок сетки.
#### Scenario: Обновление отображаемого фото
- **WHEN** приходит событие обновления для фото, которое уже показано
- **THEN** клиент обновляет его на месте, порядок сетки не меняется
#### Scenario: Обновление отсутствующего фото
- **WHEN** приходит событие обновления для фото, которого нет в текущем списке
- **THEN** клиент не добавляет его в сетку