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 area | public |
| Feature group | profile |
| Статус | draft |
| Документ | docs/06-services/profile/api/public/get-my-profile.md |
Актор и доступ
| Проверка | Значение |
|---|---|
| Actor type | User (Bearer JWT) — все типы пользователей (матрица в profile.md) |
| Auth policy / Permissions | authenticated; permission profile.personal.view-self |
| Scope (RBAC) | self (платформенный, вне tenant) |
| Record-level | только собственная запись: ProfileEntity.Id = UserId из claim sub |
| Tenant isolation | не применяется (ADR-0052: данные инвестора вне tenant) |
| Audit | read: не аудируется (self-чтение без PII-расшифровки — реплика identity хранится открыто) |
HTTP-контракт
| Поле | Значение |
|---|---|
| Method | GET |
| Route | /api/v1/profile/me |
| Success status | 200 |
| Idempotency header | не применяется (безопасный read) |
| Correlation | сквозной trace через заголовок traceparent |
Входные данные / параметры запроса
| Поле | Источник | Тип | Обязательность | Валидация / Ограничения | Безопасность |
|---|---|---|---|---|---|
UserId | identity claims (sub) | Guid | Да | валидный JWT | 401 без токена |
Модель ответа MyProfileModel
Дом полей — profile.md; здесь только проекция (дельта).
| Поле | Тип | Обязательность | Источник | Masking | Описание |
|---|---|---|---|---|---|
id | Guid | Да | ProfileEntity.Id | — | = UserId. |
userType | ProfileUserType | Да | ProfileEntity.UserType | — | Investor / DeveloperManager / Agent / PartnerManager / PinEmployee. |
companyId | Guid? | Нет | ProfileEntity.CompanyId | — | Компания (реплика); null — инвестор. |
contactsManagedBy | ProfileContactsManagementMode | Да | ProfileEntity.ContactsManagedBy | — | SelfService / TalentSync. |
status | ProfileStatus | Да | ProfileEntity.Status | — | Реплика статуса учётки. |
name | ProfileNameModel | Да | owned FullName | self — без маски; в логах не пишется | firstName (string, ≤128), lastName (string, ≤128, пустая при lazy-регистрации), middleName (string?, ≤128). |
contactPhone | string | Да | ProfileEntity.ContactPhone | self — без маски | E.164; read-only реплика; смена — identity confirm-flow. |
contactEmail | string? | Нет | ProfileEntity.ContactEmail | self — без маски | Read-only реплика. |
locale | string | Да | ProfileEntity.Locale | — | ru-RU / en-US. |
timezone | string? | Нет | ProfileEntity.Timezone | — | IANA tz. |
verificationStatus | ProfileVerificationStatus | Да | ProfileEntity.VerificationStatus | — | NotVerified / Pending / Verified / Rejected. |
verifiedAt | DateTimeOffset? | Нет | ProfileEntity.VerifiedAt | — | Момент одобрения KYC. |
defaultRequisiteTemplateId | Guid? | Нет | ProfileEntity.DefaultRequisiteTemplateId | — | Шаблон по умолчанию для формы брони. |
capabilities | ProfileCapabilitiesModel | Да | computed (матрица profile.md) | — | Флаги возможностей ЛК (ниже). |
version | long | Да | ProfileEntity.Version | — | Для optimistic-обновлений настроек. |
Модель ProfileCapabilitiesModel (computed)
| Поле | Тип | Обязательность | Правило вычисления |
|---|---|---|---|
canEditName | bool | Да | ContactsManagedBy = SelfService (иначе false — менеджер застройщика, источник Talent). |
canChangeContacts | bool | Да | ContactsManagedBy = SelfService — смена email/phone по отдельности через identity confirm-flow. |
canManageSecurity | bool | Да | всегда true при Status = Active — 2FA/пароль/пин PIN-локальные (identity). |
canManagePersons | bool | Да | UserType = Investor и ContactsManagedBy = SelfService и Status = Active (INV-PRF-2..4). |
canManageRequisites | bool | Да | то же условие (INV-RQT-6). |
canSubmitVerification | bool | Да | то же условие + feature flag profile.verification.enabled + VerificationStatus != Verified (INV-VRF-5, INV-VRF-9). |
Алгоритм
- Контекст и доступ. Операцию выполняет авторизованный пользователь любого типа (
UserIdиз токена); tenant не применяется (ADR-0052); требуется правоprofile.personal.view-self. - Проверка входа.
UserIdприсутствует в claims. Состояние не ограничивает чтение (заблокированный пользователь видит свой профиль read-only; мутации гейтятся INV-PRF-3). - Загрузка. Найти профиль по
UserId; если его ещё нет (профиль ещё не создан консюмеромpin.identity.users.v1, см. identity-users-sync.md) →PROFILE_NOT_FOUND(клиент повторяет запрос). Дополнительные агрегаты не загружаются. - Маппинг. Спроецировать
ProfileEntity → MyProfileModel(таблица выше). Флагиcapabilitiesвычисляются изUserType+ContactsManagedBy+Status+VerificationStatus+ feature flag по матрице возможностей profile.md. Расшифровка не выполняется (реплика identity хранится открыто; шифрованные данные — в персонах). - Результат. Модель
MyProfileModel; HTTP200. Freshness: реплика identity может отставать на лаг консюмера (< 1 мин, SLO README) — фронт после confirm-flow identity показывает значение из ответа identity, не ожидая реплику.
Диаграмма
Ошибки и failure modes
| Код | HTTP status | Условие | Сообщение | Retry |
|---|---|---|---|---|
| — (auth) | 401 | Нет/просрочен JWT | без тела | re-login |
ValidationError | 400 | Пустой UserId в claims | перечень невалидных полей | no retry |
PROFILE_NOT_FOUND | 404 | Профиль ещё не создан консюмером 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. Dashboardprofile-overview; runbook — replay DLQ identity-sync (при всплескеPROFILE_NOT_FOUND).
Acceptance Criteria
- Given авторизованный пользователь с существующим профилем, When
GET/me, Then200MyProfileModel; флагиcapabilitiesвычислены изUserType+ContactsManagedBy+Status+VerificationStatus+ feature flag по матрице profile.md. - Given инвестор
SelfServiceActive, WhenGET, ThencanManagePersons = true,canManageRequisites = true,canSubmitVerification = true(при включённом флаге иVerificationStatus != Verified). - Given менеджер застройщика (
ContactsManagedBy = TalentSync), WhenGET, ThencanEditName = false,canChangeContacts = false,canManagePersons = false— источник данных внешний (INV-IDN-001). - Given заблокированный пользователь (
Status != Active), WhenGET, Then200профиль read-only;canManageSecurity = false; мутации гейтятся отдельно (INV-PRF-3). - Given
VerificationStatus = Verified, WhenGET, ThencanSubmitVerification = false(INV-VRF-9). - Given профиль ещё не создан консюмером
pin.identity.users.v1, WhenGET, ThenPROFILE_NOT_FOUND(404); клиент повторяет с backoff 1–5 с. - Given сразу после identity confirm-flow смены контакта, When
GET, Then реплика может отставать < 1 мин — фронт показывает значение из ответа identity, не ожидая реплику. - Given нет/просрочен JWT, When
GET, Then401.
Обратные ссылки
Автоссылки: где используется этот документ.
- API (4): GET /api/v1/internal/profile/verification-status/{userId} — Статус верификации для m2m (getVerificationStatus), GET /api/v1/profile/verification — Моя заявка на верификацию (getMyVerification), Profile API — реестр операций областей public / internal / admin, PUT /api/v1/profile/me/settings — Обновление настроек ЛК (updateMySettings)
- registries (1): Реестр API-методов PIN
Связанные документы
- Сущность: profile.md (матрица возможностей, INV-PRF-1..6).
- Смена контактов/2FA/пароля: identity — request-email-change.md, request-phone-change.md, update-investor.md.
- Настройки: update-my-settings.md; консюмер реплики — identity-users-sync.md.