# Proposal ## Why Аватар профиля задуман, но не реализован: колонка `users.avatar_url`, поля `PublicUser.AvatarURL`/`SelfUser.AvatarURL` и `avatarUrl` в клиентах существуют, однако никто их не пишет, изображение никто не отдаёт, а интерфейс везде показывает только имена. Пользователи не могут выделить себя визуально. Нужно замкнуть эту заготовку в рабочую круглую фотографию профиля с загрузкой и кадрированием на обеих платформах. ## What Changes - Загрузка и удаление аватара: `POST /api/auth/me/avatar` (клиент присылает уже готовый квадрат после кадрирования) и `DELETE /api/auth/me/avatar` (сброс к дефолту). - Серверная нормализация загруженного изображения: отклонение не-изображений, снятие EXIF/GPS повторным энкодом, две квадратные WebP-нарезки — `avatar_small` (128) и `avatar` (512). - Аватар хранится как объект журнала, привязанный к пользователю; сборка мусора учитывает эту привязку, поэтому замена и сброс аватара сами освобождают старый блоб. - Стабильная отдача под авторизацией: `GET /api/avatars/:userID/:version` (версия в пути, чтобы клиентские и браузерные кэши инвалидировались при замене), `?size=large` отдаёт крупную нарезку. - `users.avatar_url` заполняется стабильной ссылкой, поэтому существующие публичные представления пользователя (участники альбома, комментарии, авторы) начинают отдавать аватар без изменения своих запросов. - Веб-интерфейс: круглый аватар и загрузка с кадрированием на странице профиля; круглый аватар в шапке, у участников, в комментариях и у автора фото. - Android-клиент: круглый аватар и загрузка с кадрированием на экране профиля; круглый аватар в шапке списка альбомов. - Дефолт при отсутствии аватара — нейтральная иконка-силуэт; в веб-спрайт добавляется иконка `person`. ## Capabilities ### New Capabilities ### Modified Capabilities - `user-profile`: добавляются требования к аватару — загрузка с кадрированием на клиенте, круглое отображение в вебе (шапка, страница профиля, участники, комментарии, автор) и в Android (экран профиля, шапка списка альбомов), дефолтная заглушка и удаление аватара. - `media-objects`: пользовательский аватар становится объектом журнала, привязанным к пользователю, и учитывается сборкой мусора наряду с привязками к фото. ## Impact - Backend: `internal/auth` (хендлеры/сервис/сторы), новая привязка объектов аватара и её учёт в сборке мусора (`internal/photos/objects.go`, `sqlite_objects.go` или выделенный слой), маршрутизация и отдача (`internal/app`), миграции Postgres и SQLite, журнал объектов. - Frontend: `lib/api.ts`, `lib/stores/auth.svelte.ts`, `lib/icons/registry.ts`, страница `routes/(app)/profile`, `AppShell.svelte`, `Comments.svelte`, `PhotoPanel.svelte`, экран участников. - Android: `ProfileScreen`/`ProfileViewModel`/`ProfileApi`/`GaloApi`, `AlbumsScreen`, экран(ы) кадрирования; `UserDto.avatarUrl` уже есть. - API: новые маршруты `/auth/me/avatar` и `/avatars/:userID/:version`. - Спеки: `user-profile`, `media-objects`.