POST /api/investors/me/pin-code/set — Установка/обновление пин-кода (setPinCode)
Назначение
Установить или обновить пин-код быстрого входа (4–12 цифр) текущего пользователя. Вызывается
аутентифицированным пользователем; подтверждений не требует (пользователь уже аутентифицирован токеном).
После установки вход предлагает шаг RequiresPinCode.
Metadata
| Поле | Значение |
|---|---|
| Сервис/контекст | identity |
| API area | public |
| Feature group | security |
| Статус | approved |
| Документ | docs/06-services/identity/api/investor/set-pin-code.md |
Актор и доступ
| Проверка | Значение |
|---|---|
| Actor type | User (Bearer JWT) |
| Auth policy / Permissions | authenticated; permission identity.security.manage-self |
| Scope (RBAC) | self |
| Record-level | только собственная запись (UserId из sub) |
| Tenant isolation | не применяется (ADR-0052) |
| Audit | security-change: событие UserSecurityChangedEvent (PinCodeSet) |
HTTP-контракт
| Поле | Значение |
|---|---|
| Method | POST |
| Route | /api/investors/me/pin-code/set |
| Success status | 200 |
| Idempotency header | не применяется (повтор с тем же пином — та же цель) |
| Correlation | сквозной trace через traceparent |
Входные данные / параметры запроса (body SetPinCodeForm)
| Поле | Источник | Тип | Обязательность | Валидация / Ограничения | Безопасность |
|---|---|---|---|---|---|
UserId | identity claims (sub) | Guid | Да | валидный JWT | 401 без токена |
pinCode | body | string | Да | min 1; pattern ^\d{4,12}$ (INV-5 PinCodeFormat) | никогда не логируется |
Модель ответа SetPinCodeCommandResult
| Поле | Тип | Обязательность | Источник | Masking | Описание |
|---|---|---|---|---|---|
investorId | string (Guid) | Да | UserEntity.Id | — | Идентификатор пользователя. |
Алгоритм
- Проверить формат пин-кода: строго
^\d{4,12}$(INV-5) — 4–12 цифр, ведущие нули значимы (пин — строка, не число); пустой ввод, нецифровые символы, длина < 4 или > 12 →ValidationError. - Получить пользователя-актора (
UserIdиз токена); он должен бытьActive→ иначеIDENTITY_USER_BLOCKED. - Установить пин-код (хэш Argon2id), перезаписывая прежний, если был (INV-5); обнулить счётчик неудачных
попыток (
FailedAccessAttempts = 0). - Зафиксировать доменное событие
UserSecurityChangedEvent(видPinCodeSet) для аудита. - Ответ —
investorId, HTTP 200.
Операция не отзывает активные сессии (INV-S7 охватывает смену пароля/телефона и блокировку, но не
установку пин-кода). Повтор с любым валидным значением — та же цель (перезапись); конкурентная установка
разрешается оптимистической блокировкой (побеждает последняя запись по значению). Производный флаг
hasPinCode станет true при следующем чтении профиля
(get-current-investor.md). Пин-код и хэш наружу/в
события/в снапшот pin.identity.users.v1 не попадают.
Предусловия и постусловия
- Пред: пользователь аутентифицирован и
Active;pinCodeсоответствует^\d{4,12}$. - Пост (успех):
PinCodeHashустановлен/перезаписан;FailedAccessAttempts = 0; зафиксирован доменныйUserSecurityChangedEvent(PinCodeSet)(лента админ-аудита);hasPinCode = true; активные сессии сохранены; интеграционные события не публикуются.
Acceptance Criteria
- Given
Active-пользователь, WhenPOST .../pin-code/setсpinCode = "1234", Then200{investorId};hasPinCodeпри следующемGET /me=true; последующий вход предлагает шагRequiresPinCode. - Given пользователь с уже заданным пин-кодом, When установка нового валидного значения, Then
прежний хэш перезаписан,
FailedAccessAttemptsобнулён, активные сессии не отозваны. - Given
pinCode = "0007", When установка, Then200— ведущие нули сохранены (значение — строка). - Given
pinCodeкороче 4 / длиннее 12 / с нецифровыми символами / пустой, When установка, ThenValidationError(400) (INV-5). - Given учётка
Blocked/Archived, When установка, ThenIDENTITY_USER_BLOCKED(400). - Given запрос без валидного JWT, When установка, Then
401, клиент уходит на re-login.
Ошибки и failure modes
| Код | HTTP status | Условие | Сообщение | Retry |
|---|---|---|---|---|
| — (auth) | 401 | Нет/просрочен JWT | клиент выполняет re-login | re-login |
ValidationError | 400 | Пин-код не соответствует ^\d{4,12}$ (INV-5) | Список ошибок валидации | no retry |
IDENTITY_USER_BLOCKED | 400 | Status != Active | «Учётная запись заблокирована» | no retry |
Совместимость и наблюдаемость
Паттерн пин-кода — контрактный, менять нельзя без миграции клиентов.
Logs: UserId, факт установки (без значения); metrics: identity_pin_code_set_total; traces — OTel.
Обратные ссылки
Автоссылки: где используется этот документ.
- API (3): GET /api/investors/me — Текущий инвестор (getCurrentInvestor), Identity API — карта областей и реестр investor-области, POST /api/investors/me/pin-code/clear — Удаление пин-кода (clearPinCode)
- registries (1): Реестр API-методов PIN
Связанные документы
- Сущность: user.md (INV-5,
PinCodeHash). - Смежные: clear-pin-code.md; использование пин-кода — confirm-sign-in.md.