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

Profile API — реестр операций областей public / internal / admin

Индекс HTTP-операций контекста profile (Pin.Profile.Api) и общие правила областей: модель акторов и гейтов, разбиение по feature-группам, единый формат ошибок. Файлы операций разложены по областям-акторам (public/, internal/, admin/) и описывают только свою дельту; дом полей сущностей — ../domain/.

Metadata

ПолеЗначение
Сервис/контекстprofile (Pin.Profile)
Статусdraft
Owning teamPIN Platform Core
Областиpublic (self-service ЛК), internal (m2m-снапшоты для crm/catalog), admin (review KYC — сотрудники ПИН)

Ошибки — ProblemDetails с кодом. Смена email/phone/ФИО/пароля/2FA — не здесь, а в identity (см. ../README.md, раздел «Ответственность И Границы»).

Общие правила областей

Область public (self-service ЛК, /api/v1/profile/…)

ПравилоЗначение
Actor typeUser (Bearer JWT identity); sub = UserId. profile/persons/documents/requisites/verificationтолько UserType = Investor (INV-PRF-4); getMyProfile/updateMySettings доступны всем типам пользователей
Record-levelвладение по OwnerUserId/Id = UserId; владелец из тела/маршрута не принимается; чужая запись → 404
Tenant isolationне применяется (ADR-0052: инвестор вне tenant)
Guard-ы профиляStatus = Active (INV-PRF-3 → PROFILE_USER_BLOCKED), ContactsManagedBy = SelfService (INV-PRF-2 → PROFILE_MANAGED_EXTERNALLY)
PIIФИО/дата рождения/значения документов — шифротекст (шифрование персональных данных); наружу — маски; логи без значений PII

Область internal (m2m, /api/v1/internal/profile/…)

ПравилоЗначение
Actor typeServiceAccount — m2m service token (client-credentials), не user JWT; policy InternalServiceOnly, allowlist потребителей (crm, catalog)
Tenant isolationне применяется; владелец передаётся параметром запроса (проверяется, не выводится из токена)
Назначениесинхронная выдача расшифрованного иммутабельного снапшота реквизитов и денормализованного VerificationStatus (PII в Kafka не публикуется — simplicity-first, ADR-0056)

Область admin (review KYC, /api/v1/admin/profile/…)

ПравилоЗначение
Actor typeOperator(Admin) — ревьюер ПИН (Bearer JWT), не инвестор-владелец
Permissionprofile.verification.review (нет permission → 403; permission.md: pin-manager/care/admin)
Record-levelне применяется — ревьюер читает чужую заявку; гейт — permission, а не владение
Auditactor-stamping + отдельная запись на каждую расшифровку снапшота (viewVerificationSnapshot, read-sensitive)

Сквозные соглашения областей

Контракты, на которые операции опираются и не повторяют в каждом файле (реализация должна быть единообразной во всех областях).

СоглашениеПравило
Пагинация списковPage (>= 1, default 1) + Size (1..100, default 20); ответ — Items + Meta { Total, Take, Offset, HasMore }; нарушение диапазонов → ValidationError
Идемпотентность мутацийПо умолчанию — естественная защита (дубль-инварианты *_ALREADY_EXISTS, статус-guard, повторный archive как no-op 200); где явно указан заголовок Idempotency-Key — повтор возвращает прежний результат без второго эффекта/события
Оптимистичная блокировкаКонкурентная правка агрегата → PROFILE_CONCURRENCY_CONFLICT (409); побеждает первый зафиксировавший, проигравший перечитывает состояние и повторяет
Лаг реплики identityДо создания профиля консюмером pin.identity.users.v1 операции ЛК/internal отдают PROFILE_NOT_FOUND (404); клиент/потребитель повторяет с backoff (1–5 с)
Гарантии produced-событийПубликация через транзакционный outbox, at-least-once; порядок гарантирован в пределах ключа партиционирования (personsPersonId, verification-requestsOwnerUserId); потребители обязаны быть идемпотентны; PII в Kafka не выносится
Freshness денормализацийДенормализованные поля (Profile.VerificationStatus) меняются в одной транзакции с изменением-источником (INV-PRF-6) — синхронные чтения согласованы с соответствующим событием
Расшифровка PIIФИО/даты/значения документов расшифровываются fail-closed; недоступность ключей → PROFILE_CRYPTO_UNAVAILABLE (503); наружу PII идёт только масками (public) либо в аудируемых операциях снапшота (internal getRequisiteSnapshot, admin viewVerificationSnapshot)

Реестр операций — область public

Профиль ЛК (feature group profile, permission profile.personal.view-self/manage-self)

#ОперацияHTTPRouteДокумент
1getMyProfileGET/api/v1/profile/meget-my-profile.md
2updateMySettingsPUT/api/v1/profile/me/settingsupdate-my-settings.md

Персоны (feature group persons, permission profile.personal.view-self/manage-self)

#ОперацияHTTPRouteДокумент
3listPersonsGET/api/v1/profile/personslist-persons.md
4getPersonGET/api/v1/profile/persons/{personId}get-person.md
5createPersonPOST/api/v1/profile/personscreate-person.md
6updatePersonPUT/api/v1/profile/persons/{personId}update-person.md
7archivePersonPOST/api/v1/profile/persons/{personId}/archivearchive-person.md
8restorePersonPOST/api/v1/profile/persons/{personId}/restorerestore-person.md

Документы персон (feature group documents, permission profile.documents.view-self/manage-self)

#ОперацияHTTPRouteДокумент
9listPersonDocumentsGET/api/v1/profile/persons/{personId}/documentslist-person-documents.md
10addPersonDocumentPOST/api/v1/profile/persons/{personId}/documentsadd-person-document.md
11updatePersonDocumentPUT/api/v1/profile/persons/{personId}/documents/{documentId}update-person-document.md
12archivePersonDocumentPOST/api/v1/profile/persons/{personId}/documents/{documentId}/archivearchive-person-document.md
13attachDocumentScanPOST/api/v1/profile/persons/{personId}/documents/{documentId}/scansattach-document-scan.md
14removeDocumentScanDELETE/api/v1/profile/persons/{personId}/documents/{documentId}/scans/{fileId}remove-document-scan.md
15getDocumentScanLinkGET/api/v1/profile/persons/{personId}/documents/{documentId}/scans/{fileId}/download-linkget-document-scan-link.md

Шаблоны реквизитов (feature group requisites, permission profile.requisites.manage-self)

#ОперацияHTTPRouteДокумент
16listRequisiteTemplatesGET/api/v1/profile/requisite-templateslist-requisite-templates.md
17createRequisiteTemplatePOST/api/v1/profile/requisite-templatescreate-requisite-template.md
18updateRequisiteTemplatePUT/api/v1/profile/requisite-templates/{templateId}update-requisite-template.md
19setDefaultTemplatePOST/api/v1/profile/requisite-templates/{templateId}/set-defaultset-default-template.md
20archiveRequisiteTemplatePOST/api/v1/profile/requisite-templates/{templateId}/archivearchive-requisite-template.md

Верификация инвестора (feature group verification, permission profile.verification.submit)

#ОперацияHTTPRouteДокумент
21getMyVerificationGET/api/v1/profile/verificationget-my-verification.md
22createVerificationRequestPOST/api/v1/profile/verificationcreate-verification-request.md
23updateVerificationDraftPUT/api/v1/profile/verification/{requestId}update-verification-draft.md
24submitVerificationPOST/api/v1/profile/verification/{requestId}/submitsubmit-verification.md
25revokeVerificationPOST/api/v1/profile/verification/{requestId}/revokerevoke-verification.md

Реестр операций — область internal (m2m)

#ОперацияHTTPRouteПотребительДокумент
26getRequisiteSnapshot (+RegisterUsage)POST/api/v1/internal/profile/requisite-snapshotcrmget-requisite-snapshot.md
27getVerificationStatusGET/api/v1/internal/profile/verification-status/{userId}crm, catalogget-verification-status.md

Реестр операций — область admin (review KYC, permission profile.verification.review)

#ОперацияHTTPRouteДокумент
28listVerificationQueueGET/api/v1/admin/profile/verification-queuelist-verification-queue.md
29takeVerificationInReviewPOST/api/v1/admin/profile/verification/{requestId}/taketake-verification-in-review.md
30approveVerificationPOST/api/v1/admin/profile/verification/{requestId}/approveapprove-verification.md
31rejectVerificationPOST/api/v1/admin/profile/verification/{requestId}/rejectreject-verification.md
32viewVerificationSnapshotGET/api/v1/admin/profile/verification/{requestId}/snapshotview-verification-snapshot.md

Сквозные ошибки областей (не повторяются в каждом файле)

КодHTTP statusУсловие
ValidationError400Нарушение format/min/max/pattern/enum
UNAUTHORIZED401Нет/просрочен JWT (public/admin) или m2m-токен (internal)
FORBIDDEN403Нет требуемого permission / ContactsManagedBy = TalentSync (public)
PROFILE_NOT_FOUND404Профиль ещё не создан консюмером pin.identity.users.v1 (лаг реплики; retry)
PROFILE_USER_BLOCKED400Profile.Status != Active (INV-PRF-3)
PROFILE_MANAGED_EXTERNALLY403Контакты управляются identity (INV-PRF-2)
PROFILE_PERSONS_NOT_ALLOWED_FOR_USER_TYPE403UserType != Investor для investor-only операций (INV-PRF-4)
PROFILE_CONCURRENCY_CONFLICT409Несовпадение версии агрегата (optimistic)
PROFILE_CRYPTO_UNAVAILABLE503Ключ шифрования персональных данных недоступен (Vault, fail-closed)

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