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

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 areapublic
Feature grouppersons
Статусdraft
Документdocs/06-services/profile/api/public/archive-person.md

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

ПроверкаЗначение
Actor typeUser (Bearer JWT), UserType = Investor
Auth policy / Permissionsauthenticated; permission profile.personal.manage-self
Scope (RBAC)self
Record-levelOwnerUserId = UserId; чужой personId → 404
Tenant isolationне применяется (ADR-0052)
Auditdelete (soft): DeletedAt = now, DeletedByUserId = UserId, Version++, PersonArchivedEvent

HTTP-контракт

ПолеЗначение
MethodPOST
Route/api/v1/profile/persons/{personId}/archive
Success status200
Idempotency headerне применяется (повторный archive архивной персоны — идемпотентный no-op 200)
CorrelationOpenTelemetry trace (traceparent)

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

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

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

Дом модели — list-persons.md; возвращается персона со status = Archived.

Алгоритм

  1. Контекст и доступ. Операцию выполняет инвестор (UserId = sub) с permission profile.personal.manage-self. Tenant не применяется (ADR-0052).
  2. Проверка входа. personId не пустой — иначе ValidationError.
  3. Проверка профиля, персоны и ссылок. Профиль 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).
  4. Переход и каскад. Персона переходит Active → Archived (stateDiagram person.md); каскадом каждый активный документ: Status = Archived, DeletedAt = now, DeletedByUserId = UserId; DocumentsCount = 0; у персоны DeletedAt = now, DeletedByUserId = UserId.
  5. События. PersonUpsertedKafkaEvent (топик pin.profile.persons.v1, key Id; Status = Archived, DocumentsCount = 0, Version — без PII).
  6. Согласованность. Персона, её документы и публикация события фиксируются атомарно; гонка версии → PROFILE_CONCURRENCY_CONFLICT (409).
  7. Результат. PersonModel (status = Archived). HTTP 200. Файлы сканов в storage не удаляются немедленно — retention-политика storage (person-document.md).

Диаграмма

Побочные эффекты

ТипДетали
Integration eventsPersonUpsertedKafkaEvent / pin.profile.persons.v1 / key = PersonId
External callsnone (файлы storage — отложенная retention-политика)
Cache / projections / searchnone
Notificationsnone

Ошибки и failure modes

КодHTTP statusУсловиеСообщениеRetry
— (auth)401Нет/просрочен JWTбез телаre-login
ValidationError400Пустой personIdRestApiValidationErrorResponseno retry
PROFILE_NOT_FOUND404Профиль не создан«Профиль ещё создаётся»retry
PROFILE_USER_BLOCKED400Status != Active«Учётная запись заблокирована»no retry
PROFILE_MANAGED_EXTERNALLY403TalentSync«Данные управляются внешней системой»no retry
PROFILE_PERSONS_NOT_ALLOWED_FOR_USER_TYPE403не Investor«Доступно только инвесторам»no retry
PROFILE_PERSON_NOT_FOUND404Нет персоны / чужая«Персона не найдена»no retry
PROFILE_SELF_PERSON_NOT_ARCHIVABLE400Relation = Self (INV-PRS-6)«Основную персону нельзя архивировать»no retry
PROFILE_PERSON_USED_IN_TEMPLATE409Активный шаблон ссылается (INV-PRS-4)«Персона используется в шаблоне реквизитов»после архива шаблона
PROFILE_PERSON_HAS_ACTIVE_VERIFICATION409Заявка Draft/Submitted/InReview (INV-PRS-5)«По персоне идёт верификация»после завершения/отзыва
PROFILE_CONCURRENCY_CONFLICT409Гонка (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; Then 200, Active → Archived + каскадная архивация активных документов, DocumentsCount = 0, опубликован PersonUpsertedKafkaEvent(Status = Archived).
  • Идемпотентность. Given персона уже Archived; When archive; Then 200 (no-op); каскада и события нет.
  • Основная персона. Given Relation = Self; When archive; Then 400 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; Then 409 PROFILE_PERSON_HAS_ACTIVE_VERIFICATION (INV-PRS-5).
  • Гонка. Given параллельное создание шаблона/верификации на эту персону; When обе операции фиксируются; Then победитель — 200, проигравший — 409 PROFILE_CONCURRENCY_CONFLICT.
  • История сохраняется. Given персона заархивирована; When проверяют исторические ссылки; Then сделки CRM и завершённые верификации остаются валидными; файлы сканов удаляются отложенно retention-политикой storage.

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

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

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

  • Сущность: person.md (INV-PRS-4..6, метод Archive, каскад child).
  • Обратная операция: restore-person.md; удаление PII — ADR-0053 (admin-регламент).