- backend: user_avatar_objects binding (PG+SQLite), GC preserves avatar blobs, avatar service (EXIF-stripping WebP 128/512), public avatar read route - web: avatar upload/crop on profile, round avatar in header/members/comments/author - android: avatar upload/crop, round avatar on profile and albums header - openspec: add-user-avatar proposal/design/specs/tasks
6.5 KiB
Spec Delta
ADDED Requirements
Requirement: Загрузка фото профиля с выбором области
Пользователь SHALL загружать собственное фото в профиль, выбирая видимую квадратную область. Сохранённый аватар SHALL соответствовать выбранной области. Загрузка SHALL быть доступна только владельцу профиля.
Scenario: Успешная загрузка
- WHEN пользователь выбирает изображение и подтверждает квадратную область
- THEN аватар обновляется и возвращается в профиле
Scenario: Выбранная область учтена
- WHEN пользователь сдвигает или масштабирует область перед подтверждением
- THEN сохранённый аватар показывает именно выбранную область
Scenario: Не изображение
- WHEN загруженный файл не является декодируемым изображением
- THEN система отклоняет запрос и не меняет аватар
Requirement: Нормализация аватара и снятие метаданных
Система SHALL сохранять аватар в виде квадратных изображений фиксированных размеров и SHALL NOT сохранять EXIF-метаданные загруженного файла.
Scenario: Метаданные не сохраняются
- WHEN загружено изображение с EXIF, включая GPS-координаты
- THEN сохранённый аватар не содержит EXIF и GPS
Scenario: Слишком большой файл
- WHEN размер загруженного файла превышает допустимый предел
- THEN система отклоняет запрос и не меняет аватар
Requirement: Отдача аватара по стабильному URL
Профиль и публичные представления пользователя SHALL содержать URL аватара, когда он задан. URL SHALL быть стабильным и SHALL изменяться при обновлении аватара, чтобы клиентские кэши инвалидировались. Изображение SHALL отдаваться по публичной ссылке без аутентификации, чтобы его могли загружать теги изображений и клиентские загрузчики.
Scenario: Ссылка в представлениях пользователя
- WHEN аутентифицированный клиент запрашивает профиль, участников альбома, комментарии или автора фото
- THEN представления содержат URL аватара, если он задан
Scenario: Кэш инвалидируется при замене
- WHEN пользователь заменяет аватар
- THEN URL аватара изменяется
Scenario: Загрузка изображения без заголовка авторизации
- WHEN браузер или клиентский загрузчик изображений запрашивает изображение аватара по URL без заголовка авторизации
- THEN система отдаёт изображение
Requirement: Круглое отображение аватара в веб-интерфейсе
Веб-приложение SHALL отображать аватар пользователя круглым в шапке, на странице профиля, у участников альбома, в комментариях и у автора фото.
Scenario: Аватар в шапке
- WHEN аутентифицированный пользователь открывает любое место приложения
- THEN в шапке отображается его круглый аватар
Scenario: Аватар рядом с другими пользователями
- WHEN пользователь просматривает участников, комментарии или автора фото
- THEN аватары этих пользователей отображаются круглыми
Requirement: Круглое отображение аватара в Android-клиенте
Android-приложение SHALL отображать аватар пользователя круглым на экране профиля и в шапке списка альбомов.
Scenario: Аватар на экране профиля
- WHEN пользователь открывает экран профиля
- THEN отображается его круглый аватар
Scenario: Аватар в шапке списка альбомов
- WHEN пользователь открывает список альбомов
- THEN в шапке отображается его круглый аватар
Requirement: Заглушка при отсутствии аватара
Когда аватар не задан, система SHALL показывать нейтральную заглушку-силуэт вместо изображения.
Scenario: Аватар не задан
- WHEN у пользователя нет аватара и его представление отображается в вебе или Android
- THEN вместо изображения показывается нейтральная круглая заглушка-силуэт
Requirement: Удаление аватара
Пользователь SHALL удалять свой аватар; после удаления SHALL показываться заглушка, а связанные объекты хранилища SHALL освобождаться.
Scenario: Сброс аватара
- WHEN пользователь удаляет аватар
- THEN представления возвращаются к заглушке, а объекты старого аватара освобождаются