Перейти к основному содержимому

GET /api/v1/profile/me — Получение своего профиля ЛК (getMyProfile)

Назначение

Вернуть профиль личного кабинета текущего пользователя: реплику контактов identity (read-only), настройки ЛК, денормализованный статус верификации и вычисленную матрицу возможностей по типу пользователя — фронт по ней скрывает/блокирует смену ФИО/контактов для менеджеров застройщика (ContactsManagedBy = TalentSync, INV-IDN-001) и разделы персон/документов/шаблонов/верификации для не-инвесторов. Сама смена email/phone/ФИО выполняется в identity через confirm-flow (UC-IDN-004). Вызывает любой авторизованный пользователь для своего ЛК.

Metadata

ПолеЗначение
Сервис/контекстprofile
API areapublic
Feature groupprofile
Статусdraft
Документdocs/06-services/profile/api/public/get-my-profile.md

Актор и доступ

ПроверкаЗначение
Actor typeUser (Bearer JWT) — все типы пользователей (матрица в profile.md)
Auth policy / Permissionsauthenticated; permission profile.personal.view-self
Scope (RBAC)self (платформенный, вне tenant)
Record-levelтолько собственная запись: ProfileEntity.Id = UserId из claim sub
Tenant isolationне применяется (ADR-0052: данные инвестора вне tenant)
Auditread: не аудируется (self-чтение без PII-расшифровки — реплика identity хранится открыто)

HTTP-контракт

ПолеЗначение
MethodGET
Route/api/v1/profile/me
Success status200
Idempotency headerне применяется (безопасный read)
Correlationсквозной trace через заголовок traceparent

Входные данные / параметры запроса

ПолеИсточникТипОбязательностьВалидация / ОграниченияБезопасность
UserIdidentity claims (sub)GuidДавалидный JWT401 без токена

Модель ответа MyProfileModel

Дом полей — profile.md; здесь только проекция (дельта).

ПолеТипОбязательностьИсточникMaskingОписание
idGuidДаProfileEntity.Id= UserId.
userTypeProfileUserTypeДаProfileEntity.UserTypeInvestor / DeveloperManager / Agent / PartnerManager / PinEmployee.
companyIdGuid?НетProfileEntity.CompanyIdКомпания (реплика); null — инвестор.
contactsManagedByProfileContactsManagementModeДаProfileEntity.ContactsManagedBySelfService / TalentSync.
statusProfileStatusДаProfileEntity.StatusРеплика статуса учётки.
nameProfileNameModelДаowned FullNameself — без маски; в логах не пишетсяfirstName (string, ≤128), lastName (string, ≤128, пустая при lazy-регистрации), middleName (string?, ≤128).
contactPhonestringДаProfileEntity.ContactPhoneself — без маскиE.164; read-only реплика; смена — identity confirm-flow.
contactEmailstring?НетProfileEntity.ContactEmailself — без маскиRead-only реплика.
localestringДаProfileEntity.Localeru-RU / en-US.
timezonestring?НетProfileEntity.TimezoneIANA tz.
verificationStatusProfileVerificationStatusДаProfileEntity.VerificationStatusNotVerified / Pending / Verified / Rejected.
verifiedAtDateTimeOffset?НетProfileEntity.VerifiedAtМомент одобрения KYC.
defaultRequisiteTemplateIdGuid?НетProfileEntity.DefaultRequisiteTemplateIdШаблон по умолчанию для формы брони.
capabilitiesProfileCapabilitiesModelДаcomputed (матрица profile.md)Флаги возможностей ЛК (ниже).
versionlongДаProfileEntity.VersionДля optimistic-обновлений настроек.

Модель ProfileCapabilitiesModel (computed)

ПолеТипОбязательностьПравило вычисления
canEditNameboolДаContactsManagedBy = SelfService (иначе false — менеджер застройщика, источник Talent).
canChangeContactsboolДаContactsManagedBy = SelfService — смена email/phone по отдельности через identity confirm-flow.
canManageSecurityboolДавсегда true при Status = Active — 2FA/пароль/пин PIN-локальные (identity).
canManagePersonsboolДаUserType = Investor и ContactsManagedBy = SelfService и Status = Active (INV-PRF-2..4).
canManageRequisitesboolДато же условие (INV-RQT-6).
canSubmitVerificationboolДато же условие + feature flag profile.verification.enabled + VerificationStatus != Verified (INV-VRF-5, INV-VRF-9).

Алгоритм

  1. Контекст и доступ. Операцию выполняет авторизованный пользователь любого типа (UserId из токена); tenant не применяется (ADR-0052); требуется право profile.personal.view-self.
  2. Проверка входа. UserId присутствует в claims. Состояние не ограничивает чтение (заблокированный пользователь видит свой профиль read-only; мутации гейтятся INV-PRF-3).
  3. Загрузка. Найти профиль по UserId; если его ещё нет (профиль ещё не создан консюмером pin.identity.users.v1, см. identity-users-sync.md) → PROFILE_NOT_FOUND (клиент повторяет запрос). Дополнительные агрегаты не загружаются.
  4. Маппинг. Спроецировать ProfileEntity → MyProfileModel (таблица выше). Флаги capabilities вычисляются из UserType + ContactsManagedBy + Status + VerificationStatus + feature flag по матрице возможностей profile.md. Расшифровка не выполняется (реплика identity хранится открыто; шифрованные данные — в персонах).
  5. Результат. Модель MyProfileModel; HTTP 200. Freshness: реплика identity может отставать на лаг консюмера (< 1 мин, SLO README) — фронт после confirm-flow identity показывает значение из ответа identity, не ожидая реплику.

Диаграмма

Ошибки и failure modes

КодHTTP statusУсловиеСообщениеRetry
— (auth)401Нет/просрочен JWTбез телаre-login
ValidationError400Пустой UserId в claimsперечень невалидных полейno retry
PROFILE_NOT_FOUND404Профиль ещё не создан консюмером identity (лаг реплики)«Профиль ещё создаётся, повторите»retry с backoff (1–5 с)

Совместимость и наблюдаемость

  • Новые optional поля ответа (в т.ч. новые флаги capabilities) — additive, без breaking change; удаление/переименование — breaking. Unknown enum у клиента — трактовать как «возможность недоступна».
  • Logs: UserId, latency (без значений контактов/ФИО); metrics: profile_api_operations_total{operation="getMyProfile",result}; traces — OTel. Dashboard profile-overview; runbook — replay DLQ identity-sync (при всплеске PROFILE_NOT_FOUND).

Acceptance Criteria

  • Given авторизованный пользователь с существующим профилем, When GET /me, Then 200 MyProfileModel; флаги capabilities вычислены из UserType + ContactsManagedBy + Status + VerificationStatus + feature flag по матрице profile.md.
  • Given инвестор SelfService Active, When GET, Then canManagePersons = true, canManageRequisites = true, canSubmitVerification = true (при включённом флаге и VerificationStatus != Verified).
  • Given менеджер застройщика (ContactsManagedBy = TalentSync), When GET, Then canEditName = false, canChangeContacts = false, canManagePersons = false — источник данных внешний (INV-IDN-001).
  • Given заблокированный пользователь (Status != Active), When GET, Then 200 профиль read-only; canManageSecurity = false; мутации гейтятся отдельно (INV-PRF-3).
  • Given VerificationStatus = Verified, When GET, Then canSubmitVerification = false (INV-VRF-9).
  • Given профиль ещё не создан консюмером pin.identity.users.v1, When GET, Then PROFILE_NOT_FOUND (404); клиент повторяет с backoff 1–5 с.
  • Given сразу после identity confirm-flow смены контакта, When GET, Then реплика может отставать < 1 мин — фронт показывает значение из ответа identity, не ожидая реплику.
  • Given нет/просрочен JWT, When GET, Then 401.

Обратные ссылки

Автоссылки: где используется этот документ.

Связанные документы