Files
ds-galo/openspec/specs/user-profile/spec.md
T

15 KiB

user-profile Specification

Purpose

Управление аккаунтом пользователя: просмотр и изменение профиля, смена пароля с отзывом сессий, добавление второго идентификатора входа и удаление аккаунта со всем содержимым — единообразно в веб-интерфейсе и Android-клиенте.

Requirements

Requirement: Просмотр собственного профиля

Пользователь SHALL получать свой профиль с именем, email, телефоном и аватаром. Телефон SHALL быть виден только владельцу и SHALL NOT попадать в публичные представления пользователя (участники альбома, загрузчики, комментарии).

Scenario: Получение профиля

  • WHEN аутентифицированный пользователь запрашивает свой профиль
  • THEN ответ содержит его имя, email (если задан), телефон (если задан) и аватар

Scenario: Телефон не утекает

  • WHEN пользователь просматривает участников альбома
  • THEN представления других пользователей не содержат телефон

Requirement: Изменение имени

Пользователь SHALL изменять своё имя. Пустое имя SHALL отклоняться. Смена имени SHALL применяться немедленно и отражаться при следующем чтении профиля.

Scenario: Успешное изменение

  • WHEN пользователь отправляет непустое имя
  • THEN система сохраняет его и возвращает обновлённый профиль

Scenario: Пустое имя

  • WHEN пользователь отправляет пустое имя
  • THEN система отклоняет запрос и не меняет профиль

Requirement: Смена пароля с отзывом сессий

Пользователь SHALL менять пароль, подтвердив текущий пароль. Система SHALL отклонять неверный текущий пароль и новый пароль короче 8 символов. Успешная смена SHALL отзывать все refresh-токены пользователя на всех устройствах.

Scenario: Успешная смена

  • WHEN пользователь вводит верный текущий пароль и новый пароль допустимой длины
  • THEN система сохраняет новый хэш и отзывает все refresh-токены пользователя

Scenario: Неверный текущий пароль

  • WHEN пользователь вводит неверный текущий пароль
  • THEN система возвращает ошибку и не меняет пароль

Scenario: Слабый новый пароль

  • WHEN новый пароль короче 8 символов
  • THEN система отклоняет запрос и сохраняет старый пароль

Requirement: Добавление недостающего идентификатора

Пользователь с одним заданным идентификатором (email или телефон) SHALL добавить недостающий один раз после проверки уникальности. Система SHALL отклонять добавление, когда оба идентификатора уже заданы, а также изменение или удаление заданного. После добавления оба идентификатора SHALL работать для входа.

Scenario: Добавление телефона

  • WHEN пользователь без телефона добавляет свободный номер в формате E.164
  • THEN система сохраняет номер, и вход по нему становится возможен

Scenario: Занятый идентификатор

  • WHEN добавляемый email или телефон уже принадлежит другому пользователю
  • THEN система возвращает ошибку конфликта и не меняет профиль

Scenario: Оба уже заданы

  • WHEN у пользователя уже заданы и email, и телефон, и он пытается добавить третий
  • THEN система отклоняет запрос

Requirement: Удаление аккаунта со всем содержимым

Пользователь SHALL удалять свой аккаунт, подтвердив текущий пароль. Неверный пароль SHALL отклоняться. Успешное удаление SHALL быть немедленным и необратимым: SHALL каскадно удаляться альбомы пользователя (вместе с доступом других участников), его фото, комментарии, лайки, метки, уведомления, share-ссылки и приглашения. Блобы SHALL освобождаться фоновой сверкой хранилища, а не в транзакции удаления.

Scenario: Успешное удаление

  • WHEN пользователь подтверждает удаление верным текущим паролем
  • THEN учётная запись и связанное содержимое удаляются, и вход больше невозможен

Scenario: Общие альбомы

  • WHEN удаляемый пользователь владеет альбомом, в котором есть другие участники
  • THEN альбом удаляется вместе с ними

Scenario: Неверный пароль

  • WHEN пользователь подтверждает удаление неверным паролем
  • THEN система возвращает ошибку и не удаляет аккаунт

Requirement: Страница профиля в веб-интерфейсе

Веб-приложение SHALL предоставлять отдельную страницу профиля, доступную из шапки, с показом идентификаторов и формами изменения имени, смены пароля и удаления аккаунта.

Scenario: Открытие страницы

  • WHEN аутентифицированный пользователь открывает профиль из шапки
  • THEN отображаются его идентификаторы и формы редактирования

Scenario: Выход после смены пароля

  • WHEN смена пароля завершилась успешно
  • THEN клиент очищает токены и перенаправляет на страницу входа

Scenario: Выход после удаления

  • WHEN удаление аккаунта завершилось успешно
  • THEN клиент очищает токены и перенаправляет на страницу входа

Requirement: Экран профиля в Android-клиенте

Android-приложение SHALL предоставлять отдельный экран профиля, доступный из списка альбомов, с теми же возможностями, что и веб-страница.

Scenario: Открытие экрана

  • WHEN пользователь открывает профиль из списка альбомов
  • THEN отображаются идентификаторы и формы редактирования

Scenario: Возврат после смены пароля

  • WHEN смена пароля завершилась успешно
  • THEN приложение очищает токены и возвращает на экран входа

Scenario: Возврат после удаления

  • WHEN удаление аккаунта завершилось успешно
  • THEN приложение очищает токены и возвращает на экран входа

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 представления возвращаются к заглушке, а объекты старого аватара освобождаются