POST /api/v1/profile/persons/{personId}/archive — Архивация персоны (archivePerson)
Назначение
Архивировать персону (soft-delete): персона скрывается из списков и недоступна для новых шаблонов
реквизитов/верификации, но исторические ссылки (сделки CRM, завершённые верификации) остаются валидными
(person.md). Полное удаление PII в self-service недоступно — регламент
администратора платформы (ADR-0053, crypto-erase). Персона Self не архивируется (INV-PRS-6); персона, на
которую ссылаются активные шаблоны или незавершённая верификация, — тоже (INV-PRS-4/5).
Metadata
| Поле | Значение |
|---|---|
| Сервис/контекст | profile |
| API area | public |
| Feature group | persons |
| Статус | draft |
| Документ | docs/06-services/profile/api/public/archive-person.md |
Актор и доступ
| Проверка | Значение |
|---|---|
| Actor type | User (Bearer JWT), UserType = Investor |
| Auth policy / Permissions | authenticated; permission profile.personal.manage-self |
| Scope (RBAC) | self |
| Record-level | OwnerUserId = UserId; чужой personId → 404 |
| Tenant isolation | не применяется (ADR-0052) |
| Audit | delete (soft): DeletedAt = now, DeletedByUserId = UserId, Version++, PersonArchivedEvent |
HTTP-контракт
| Поле | Значение |
|---|---|
| Method | POST |
| Route | /api/v1/profile/persons/{personId}/archive |
| Success status | 200 |
| Idempotency header | не применяется (повторный archive архивной персоны — идемпотентный no-op 200) |
| Correlation | OpenTelemetry trace (traceparent) |
Входные данные / параметры запроса
| Поле | Источник | Тип | Обязательность | Валидация / Ограничения | Безопасность |
|---|---|---|---|---|---|
UserId | identity claims (sub) | Guid | Да | валидный JWT | 401 без токена |
personId | route | Guid | Да | NotEmpty; персона владельца | чужая → 404 |
Модель ответа PersonModel
Дом модели — list-persons.md; возвращается персона со status = Archived.
Алгоритм
- Контекст и доступ. Операцию выполняет инвестор (
UserId=sub) с permissionprofile.personal.manage-self. Tenant не применяется (ADR-0052). - Проверка входа.
personIdне пустой — иначеValidationError. - Проверка профиля, персоны и ссылок. Профиль self-service (guard-ы INV-PRF-2..4; отсутствие профиля →
PROFILE_NOT_FOUND). Персона должна принадлежать владельцу — иначеPROFILE_PERSON_NOT_FOUND; ужеArchived— идемпотентный успех. Порядок проверок инвариантов:Relation != Self(INV-PRS-6, иначеPROFILE_SELF_PERSON_NOT_ARCHIVABLE); на персону не ссылается ни один активный шаблон реквизитов (INV-PRS-4, иначеPROFILE_PERSON_USED_IN_TEMPLATE); по персоне нет незавершённой верификации (Status ∈ {Draft, Submitted, InReview}) (INV-PRS-5, иначеPROFILE_PERSON_HAS_ACTIVE_VERIFICATION). - Переход и каскад. Персона переходит
Active → Archived(stateDiagram person.md); каскадом каждый активный документ:Status = Archived,DeletedAt = now,DeletedByUserId = UserId;DocumentsCount = 0; у персоныDeletedAt = now,DeletedByUserId = UserId. - События.
PersonUpsertedKafkaEvent(топикpin.profile.persons.v1, keyId;Status = Archived,DocumentsCount = 0,Version— без PII). - Согласованность. Персона, её документы и публикация события фиксируются атомарно; гонка версии →
PROFILE_CONCURRENCY_CONFLICT(409). - Результат.
PersonModel(status = Archived). HTTP 200. Файлы сканов в storage не удаляются немедленно — retention-политика storage (person-document.md).
Диаграмма
Побочные эффекты
| Тип | Детали |
|---|---|
| Integration events | PersonUpsertedKafkaEvent / pin.profile.persons.v1 / key = PersonId |
| External calls | none (файлы storage — отложенная retention-политика) |
| Cache / projections / search | none |
| Notifications | none |
Ошибки и failure modes
| Код | HTTP status | Условие | Сообщение | Retry |
|---|---|---|---|---|
| — (auth) | 401 | Нет/просрочен JWT | без тела | re-login |
ValidationError | 400 | Пустой personId | RestApiValidationErrorResponse | no retry |
PROFILE_NOT_FOUND | 404 | Профиль не создан | «Профиль ещё создаётся» | retry |
PROFILE_USER_BLOCKED | 400 | Status != Active | «Учётная запись заблокирована» | no retry |
PROFILE_MANAGED_EXTERNALLY | 403 | TalentSync | «Данные управляются внешней системой» | no retry |
PROFILE_PERSONS_NOT_ALLOWED_FOR_USER_TYPE | 403 | не Investor | «Доступно только инвесторам» | no retry |
PROFILE_PERSON_NOT_FOUND | 404 | Нет персоны / чужая | «Персона не найдена» | no retry |
PROFILE_SELF_PERSON_NOT_ARCHIVABLE | 400 | Relation = Self (INV-PRS-6) | «Основную персону нельзя архивировать» | no retry |
PROFILE_PERSON_USED_IN_TEMPLATE | 409 | Активный шаблон ссылается (INV-PRS-4) | «Персона используется в шаблоне реквизитов» | после архива шаблона |
PROFILE_PERSON_HAS_ACTIVE_VERIFICATION | 409 | Заявка Draft/Submitted/InReview (INV-PRS-5) | «По персоне идёт верификация» | после завершения/отзыва |
PROFILE_CONCURRENCY_CONFLICT | 409 | Гонка (xmin) | «Данные изменены, повторите» | retry |
Совместимость и наблюдаемость
- Семантика archive стабильна (hard-delete не появится в public API — ADR-0053).
- Logs:
UserId,PersonId, число заархивированных документов; metrics:profile_api_operations_total{operation="archivePerson",result}; traces — OTel.
Acceptance Criteria
- Happy path. Given активная персона
Relation != Selfбез активных шаблонов и незавершённой верификации; When archive; Then200,Active → Archived+ каскадная архивация активных документов,DocumentsCount = 0, опубликованPersonUpsertedKafkaEvent(Status = Archived). - Идемпотентность. Given персона уже
Archived; When archive; Then200(no-op); каскада и события нет. - Основная персона. Given
Relation = Self; When archive; Then400 PROFILE_SELF_PERSON_NOT_ARCHIVABLE(INV-PRS-6). - Ссылка из шаблона. Given персону использует активный шаблон реквизитов; When archive; Then
409 PROFILE_PERSON_USED_IN_TEMPLATE(INV-PRS-4). - Незавершённая верификация. Given по персоне есть заявка
Draft/Submitted/InReview; When archive; Then409 PROFILE_PERSON_HAS_ACTIVE_VERIFICATION(INV-PRS-5). - Гонка. Given параллельное создание шаблона/верификации на эту персону; When обе операции фиксируются; Then победитель —
200, проигравший —409 PROFILE_CONCURRENCY_CONFLICT. - История сохраняется. Given персона заархивирована; When проверяют исторические ссылки; Then сделки CRM и завершённые верификации остаются валидными; файлы сканов удаляются отложенно retention-политикой storage.
Обратные ссылки
Автоссылки: где используется этот документ.
- API (4): GET /api/v1/profile/persons — Список персон аккаунта (listPersons), POST /api/v1/profile/persons/{personId}/restore — Восстановление персоны (restorePerson), Profile API — реестр операций областей public / internal / admin, PUT /api/v1/profile/persons/{personId} — Обновление персоны (updatePerson)
- registries (1): Реестр API-методов PIN
Связанные документы
- Сущность: person.md (INV-PRS-4..6, метод
Archive, каскад child). - Обратная операция: restore-person.md; удаление PII — ADR-0053 (admin-регламент).