diff --git a/docs/lk-contract/v1/README.md b/docs/lk-contract/v1/README.md index dc9341b..59ba01c 100644 --- a/docs/lk-contract/v1/README.md +++ b/docs/lk-contract/v1/README.md @@ -1,18 +1,58 @@ -# docs/lk-contract/v1 — контракт с ЛК клиента (ESIA Finance) +# docs/lk-contract/v1 — контракт с ЛК клиента (ESIA Finance API V1) -ЛК клиента работает на платформе **ESIA Finance**, контракт описан -в `DOC/API ЛК ЕСИА.pdf` (`/api/v1/back_office/...`, Basic HTTP, JSON, +ЛК клиента работает на платформе **ESIA Finance**, контракт описан в +`DOC/API ЛК ЕСИА.pdf` (`/api/v1/back_office/...`, Basic HTTP, JSON, UTF-8). -На этапе M1 в `lk-emulator` мы воспроизводим этот контракт для запуска -сквозного потока. Реальный ЛК подключится по тому же контракту, без -правок на нашей стороне. +На этапе M1 в `lk-emulator` (отдельный PR) мы реализуем этот контракт +как «как-будто-ЛК» для запуска сквозного потока. Реальный ЛК +подключится по тому же контракту без правок на нашей стороне. -В этом каталоге будут: +## Состав каталога -- `openapi.yaml` — наш OpenAPI-контракт `lk-gateway`, согласованный - с командой ЛК. -- `examples/` — примеры заявлений и ответов. -- `changelog.md` — версионирование контракта. +- **`openapi.yaml`** — OpenAPI 3.0 контракт lk-gateway. Описывает + четыре операции: создание, чтение, callback статуса и список заявок. + Модель `Claim` включает все поля, нужные m2m-core для формирования + `M2MTransferRequest`. +- **`examples/`**: + - `claim-request.json` — пример заявки на перевод (3 ЦБ, ИИС T03). + - `claim-response.json` — пример ответа на создание. + - `callback-confirmed.json` — callback подтверждения (status_code + INFO, 3 коды 01). + - `callback-rejected.json` — callback отказа (status_code ERROR). + - `error-422.json` — ошибка валидации подписи. +- **`changelog.md`** — версионирование контракта. -Реализация — задача M1. +## Что входит в модель заявки + +- Идентификация инвестора (UUID в ЛК, ФИО, документ). +- Реквизиты передающего и принимающего депозитариев (ИНН). +- Информация об учёте стоимости (`cost_info: yes | no`). +- Опциональный блок ИИС (тип T12/T03, номер договора, дата, ИНН брокера). +- Массив ценных бумаг (1..N), каждая с: + - `security_code` (НРД-код, 12 символов), + - идентификацией (`isin` или развёрнутый `security_info`), + - количеством (целое `whole` или дробное `fractional` до 16 знаков), + - списком счетов депо (`settlement_accounts[]`). +- Подписанный XML заявления (base64) и формат подписи + (XMLDSig-GOST или XMLDSig-RSA). + +## Что входит в callback статуса + +- `claim_id`, `new_status`, `updated_at`. +- Для `rejected`/`timed_out`: код и текст причины из ответа НРД. +- Полное `nsd_response` (опц., для аудита). + +## Порядок согласования + +1. Передать команде ЛК ссылку на эту папку (тег `lk-contract-v1`). +2. Обсудить базовый URL, авторизацию (Basic, через VPN), окна. +3. Запустить `lk-emulator` на нашей стороне как опорную реализацию. +4. После приёмки — поднимать реальную интеграцию. + +## Принципы + +- OpenAPI 3.0, валидный по spectral / openapi-cli. +- Operation IDs в snake_case. +- Описания на русском, имена полей на английском. +- Enum'ы значений M2M — буквально как в XSD НРД (T12/T03, BOND/SHAR/MFUN, ...). diff --git a/docs/lk-contract/v1/changelog.md b/docs/lk-contract/v1/changelog.md new file mode 100644 index 0000000..7c6a28b --- /dev/null +++ b/docs/lk-contract/v1/changelog.md @@ -0,0 +1,34 @@ +# Changelog контракта lk-gateway + +## v1.0.0 (2026-05-14) + +Первая опубликованная версия контракта. Соответствует ESIA Finance +API V1 (`DOC/API ЛК ЕСИА.pdf`). + +Поддерживаемые операции: + +- `POST /api/v1/back_office/claims/` — создание заявки. +- `GET /api/v1/back_office/claims` — список с фильтрами. +- `GET /api/v1/back_office/claims/{id}` — деталь. +- `PATCH /api/v1/back_office/claims/{id}` — callback статуса. + +Модели: + +- `Claim` — заявка с массивом `securities[]` (1..N ЦБ). +- `CreateClaimRequest` — входное тело создания. +- `StatusCallback` — обновление статуса с `nsd_response` для аудита. +- `ErrorResponse` — формат идентичен ESIA Finance V1. + +Совместимость: + +- HTTP Basic-auth. +- UTF-8, JSON. +- Поля enum — буквально как в XSD M2M (T12/T03, BOND/SHAR/MFUN, + ORDN/PREF/UKWN, INFO/ERROR). + +## Принципы версионирования + +- Несовместимые изменения — `v2/`, `v3/` (новая папка, отдельный + changelog). +- Совместимые добавления — minor-версия в этом файле. +- Документация исправлений — patch-версия в этом файле. diff --git a/docs/lk-contract/v1/examples/callback-confirmed.json b/docs/lk-contract/v1/examples/callback-confirmed.json new file mode 100644 index 0000000..e2b7b4b --- /dev/null +++ b/docs/lk-contract/v1/examples/callback-confirmed.json @@ -0,0 +1,26 @@ +{ + "claim_id": "c02a1d5e-c2af-4799-bab4-953f133c5133", + "new_status": "confirmed", + "updated_at": "2026-03-02T14:38:12Z", + "nsd_response": { + "guid": "c02a1d5e-c2af-4799-bab4-953f133c5133", + "status_code": "INFO", + "responses": [ + { + "reference_id": "M2M2026030200001", + "code": "01", + "text": "Запрос на перевод принят и подтверждён принимающей стороной." + }, + { + "reference_id": "M2M2026030200002", + "code": "01", + "text": "Запрос на перевод принят и подтверждён принимающей стороной." + }, + { + "reference_id": "M2M2026030200003", + "code": "01", + "text": "Запрос на перевод принят и подтверждён принимающей стороной." + } + ] + } +} diff --git a/docs/lk-contract/v1/examples/callback-rejected.json b/docs/lk-contract/v1/examples/callback-rejected.json new file mode 100644 index 0000000..2b7778a --- /dev/null +++ b/docs/lk-contract/v1/examples/callback-rejected.json @@ -0,0 +1,17 @@ +{ + "claim_id": "c02a1d5e-c2af-4799-bab4-953f133c5133", + "new_status": "rejected", + "reason_code": "07", + "reason_text": "Не найдена сделка с таким GUID на стороне принимающего депозитария.", + "updated_at": "2026-03-02T14:40:00Z", + "nsd_response": { + "guid": "c02a1d5e-c2af-4799-bab4-953f133c5133", + "status_code": "ERROR", + "responses": [ + { + "code": "07", + "text": "Не найдена сделка с таким GUID." + } + ] + } +} diff --git a/docs/lk-contract/v1/examples/claim-request.json b/docs/lk-contract/v1/examples/claim-request.json new file mode 100644 index 0000000..cab68b7 --- /dev/null +++ b/docs/lk-contract/v1/examples/claim-request.json @@ -0,0 +1,104 @@ +{ + "investor": { + "id": "11111111-1111-1111-1111-111111111111", + "last_name": "Иванов", + "first_name": "Иван", + "middle_name": "Иванович", + "document": { + "document_type": "21", + "series": "4512", + "number": "654321" + } + }, + "transferring_depository_inn": "0702345678", + "receiving_depository_inn": "0710987654", + "cost_info": { + "yes": { + "code": "MC0010300032" + } + }, + "iia_agreement": { + "agreement_type": "T03", + "agreement_number": "ИИС78/2024", + "agreement_date": "2026-01-15", + "broker_inn": "0707083893" + }, + "securities": [ + { + "security_code": "MM0766162534", + "security_details": { + "isin": "RU0007661625" + }, + "quantity": { + "whole": 1500 + }, + "settlement_accounts": [ + { + "settlement_requisites_inn": "7702070139", + "settlement_location": { + "deponent_code": "DP789456", + "account_id": "31MC0021900000F01", + "section_id": "P001" + } + }, + { + "settlement_requisites_inn": "7802031669", + "settlement_location": { + "deponent_code": "AA789451", + "account_id": "33MC0021900000F02", + "section_id": "F002" + } + } + ] + }, + { + "security_code": "MM0907654321", + "security_details": { + "isin": "RU0009029540" + }, + "quantity": { + "whole": 300 + }, + "settlement_accounts": [ + { + "settlement_requisites_inn": "7702070139", + "settlement_location": { + "deponent_code": "DP789456", + "account_id": "31MC0021900000F01", + "section_id": "P001" + } + } + ] + }, + { + "security_code": "MM2300100100", + "security_details": { + "security_info": { + "classification": "MFUN", + "category": "UKWN", + "identification_details": { + "fund_shares": { + "reg_number": "23-001", + "class": "A" + } + } + } + }, + "quantity": { + "fractional": "2500.75" + }, + "settlement_accounts": [ + { + "settlement_requisites_inn": "7702070139", + "settlement_location": { + "deponent_code": "DP789456", + "account_id": "31MC0021900000F01", + "section_id": "P001" + } + } + ] + } + ], + "signed_document": "PD94bWwgdmVyc2lvbj0iMS4wIiBlbmNvZGluZz0id2luZG93cy0xMjUxIj8+...base64-XML...", + "signature_format": "XMLDSig-GOST" +} diff --git a/docs/lk-contract/v1/examples/claim-response.json b/docs/lk-contract/v1/examples/claim-response.json new file mode 100644 index 0000000..b85caa6 --- /dev/null +++ b/docs/lk-contract/v1/examples/claim-response.json @@ -0,0 +1,6 @@ +{ + "id": "c02a1d5e-c2af-4799-bab4-953f133c5133", + "status": "submitted", + "created_at": "2026-03-02T14:30:45Z", + "success": true +} diff --git a/docs/lk-contract/v1/examples/error-422.json b/docs/lk-contract/v1/examples/error-422.json new file mode 100644 index 0000000..189b76b --- /dev/null +++ b/docs/lk-contract/v1/examples/error-422.json @@ -0,0 +1,15 @@ +{ + "error": true, + "status": 422, + "code": "invalid_signature", + "title": "Подпись заявления не прошла проверку", + "meta": { + "message": "Сертификат подписанта недействителен или цепочка доверия не построена.", + "errors": [ + { + "field": "signed_document", + "message": "XMLDSig: certificate chain not trusted (signer CN = ИВАНОВ И.И.)." + } + ] + } +} diff --git a/docs/lk-contract/v1/openapi.yaml b/docs/lk-contract/v1/openapi.yaml new file mode 100644 index 0000000..8717681 --- /dev/null +++ b/docs/lk-contract/v1/openapi.yaml @@ -0,0 +1,656 @@ +openapi: 3.0.3 +info: + title: lk-gateway API + version: 1.0.0 + description: | + REST-контракт между сервисом `lk-gateway` (Bridge-and-Join-s) и ЛК + инвестора на платформе ESIA Finance. Версия V1 совместима с + официальным API ESIA Finance (`DOC/API ЛК ЕСИА.pdf`). + + Контракт обслуживает жизненный цикл заявки M2M-перевода: создание, + получение, обновление статуса и список заявок. + + Аутентификация — HTTP Basic. Кодировка — UTF-8. Тело запросов и + ответов — JSON. +servers: + - url: https://lk-gateway.bridge-and-joins.local + description: Production lk-gateway + - url: http://localhost:8080 + description: Локальный эмулятор (lk-emulator) +security: + - basicAuth: [] + +paths: + /api/v1/back_office/claims/: + post: + operationId: create_claim + summary: Создать заявку на M2M-перевод + description: | + Принимает подписанное (XMLDSig) заявление инвестора. Сервис + проверяет подпись через crypto-service, валидирует данные, + создаёт сделку и инициирует отправку в НРД. + requestBody: + required: true + content: + application/json: + schema: + $ref: '#/components/schemas/CreateClaimRequest' + examples: + full_claim: + summary: Заявка с тремя ЦБ, ИИС T03 + externalValue: ./examples/claim-request.json + responses: + '201': + description: Заявка создана + content: + application/json: + schema: + $ref: '#/components/schemas/CreateClaimResponse' + '400': + description: Невалидные входные данные + content: + application/json: + schema: + $ref: '#/components/schemas/ErrorResponse' + '401': + description: Не авторизован + content: + application/json: + schema: + $ref: '#/components/schemas/ErrorResponse' + '422': + description: Подпись неверна или данные не прошли бизнес-валидацию + content: + application/json: + schema: + $ref: '#/components/schemas/ErrorResponse' + + /api/v1/back_office/claims: + get: + operationId: list_claims + summary: Список заявок + description: Возвращает список заявок с фильтрацией по статусу, периоду и инвестору. + parameters: + - name: status + in: query + description: Фильтр по статусу. + required: false + schema: + $ref: '#/components/schemas/ClaimStatus' + - name: investor_id + in: query + description: UUID инвестора в ЛК. + required: false + schema: + type: string + format: uuid + - name: created_from + in: query + description: Нижняя граница периода создания (ISO 8601, UTC). + required: false + schema: + type: string + format: date-time + - name: created_to + in: query + description: Верхняя граница периода создания (ISO 8601, UTC). + required: false + schema: + type: string + format: date-time + - name: limit + in: query + required: false + schema: + type: integer + minimum: 1 + maximum: 200 + default: 50 + - name: offset + in: query + required: false + schema: + type: integer + minimum: 0 + default: 0 + responses: + '200': + description: Страница списка заявок + content: + application/json: + schema: + $ref: '#/components/schemas/ClaimsPage' + + /api/v1/back_office/claims/{id}: + get: + operationId: get_claim + summary: Получить заявку и её статус + parameters: + - name: id + in: path + required: true + description: UUID заявки. + schema: + type: string + format: uuid + responses: + '200': + description: Заявка + content: + application/json: + schema: + $ref: '#/components/schemas/Claim' + '404': + description: Заявка не найдена + content: + application/json: + schema: + $ref: '#/components/schemas/ErrorResponse' + patch: + operationId: update_claim_status + summary: Callback обновления статуса (от lk-gateway к ЛК) + description: | + Используется лгатвей-ом для уведомления ЛК о смене статуса + сделки на стороне НРД. Подтверждение, отказ или таймаут. + parameters: + - name: id + in: path + required: true + description: UUID заявки. + schema: + type: string + format: uuid + requestBody: + required: true + content: + application/json: + schema: + $ref: '#/components/schemas/StatusCallback' + examples: + confirmed: + summary: Подтверждение + externalValue: ./examples/callback-confirmed.json + rejected: + summary: Отказ + externalValue: ./examples/callback-rejected.json + responses: + '200': + description: Callback принят + content: + application/json: + schema: + $ref: '#/components/schemas/CallbackResponse' + '404': + description: Заявка не найдена + +components: + securitySchemes: + basicAuth: + type: http + scheme: basic + + schemas: + ClaimStatus: + type: string + description: | + Жизненный цикл заявки на M2M-перевод. + - `draft` — черновик, ещё не подписан. + - `signed` — подписан, но не отправлен. + - `submitted` — отправлен в НРД. + - `in_progress` — НРД принял, ждём решение от принимающей стороны. + - `confirmed` — подтверждён, перевод исполнен. + - `rejected` — отклонён. + - `timed_out` — превышен SLA, ручной разбор. + enum: + - draft + - signed + - submitted + - in_progress + - confirmed + - rejected + - timed_out + + SignatureFormat: + type: string + description: Тип цифровой подписи заявления. + enum: + - XMLDSig-GOST + - XMLDSig-RSA + + AgreementType: + type: string + description: | + Тип договора ИИС. + - `T12` — ИИС-1 или ИИС-2 (старый формат). + - `T03` — ИИС-3 (новый). + enum: + - T12 + - T03 + + SecurityClassification: + type: string + description: Тип ценной бумаги. + enum: + - BOND + - SHAR + - MFUN + + SecurityCategory: + type: string + description: Категория акций. + enum: + - ORDN + - PREF + - UKWN + + Investor: + type: object + description: Анкета инвестора. + required: + - last_name + - first_name + - document + properties: + id: + type: string + format: uuid + description: UUID инвестора в ЛК (если уже известен). + last_name: + type: string + maxLength: 50 + example: Иванов + first_name: + type: string + maxLength: 50 + example: Иван + middle_name: + type: string + maxLength: 50 + example: Иванович + document: + $ref: '#/components/schemas/IdentityDocument' + + IdentityDocument: + type: object + description: Документ, удостоверяющий личность. + required: + - document_type + - number + properties: + document_type: + type: string + pattern: '^(0[1-7]|09|1[0-4]|2[1-37]|26|91)$' + description: Код документа по справочнику НРД. + example: '21' + series: + type: string + pattern: '^\S+$' + example: '4512' + number: + type: string + pattern: '^\S+$' + example: '654321' + + Quantity: + type: object + description: Количество ценных бумаг — choice (ровно одно поле). + properties: + whole: + type: integer + format: int64 + minimum: 1 + example: 1500 + fractional: + type: string + description: Десятичная строка с не более 16 знаками после точки. + pattern: '^[0-9]+(\.[0-9]{1,16})?$' + example: '2500.75' + + FundShares: + type: object + required: + - reg_number + properties: + reg_number: + type: string + maxLength: 256 + example: '23-001' + class: + type: string + maxLength: 120 + example: A + + IdentificationDetails: + type: object + description: Идентификация ЦБ — choice (ровно одно поле). + properties: + reg_number: + type: string + maxLength: 20 + fund_shares: + $ref: '#/components/schemas/FundShares' + + SecurityInfo: + type: object + description: Описание ЦБ при отсутствии ISIN. + required: + - classification + - category + - identification_details + properties: + classification: + $ref: '#/components/schemas/SecurityClassification' + category: + $ref: '#/components/schemas/SecurityCategory' + security_type: + type: string + maxLength: 256 + security_series: + type: string + identification_details: + $ref: '#/components/schemas/IdentificationDetails' + + SecurityDetails: + type: object + description: Идентификация ЦБ — choice (ровно одно поле). + properties: + isin: + type: string + pattern: '^[A-Z]{2}[A-Z0-9]{9}[0-9]$' + example: RU0007661625 + security_info: + $ref: '#/components/schemas/SecurityInfo' + + SettlementLocation: + type: object + required: + - deponent_code + - account_id + - section_id + properties: + deponent_code: + type: string + maxLength: 50 + example: DP789456 + account_id: + type: string + maxLength: 50 + example: 31MC0021900000F01 + section_id: + type: string + maxLength: 50 + example: P001 + + SettlementAccount: + type: object + required: + - settlement_requisites_inn + - settlement_location + properties: + settlement_requisites_inn: + type: string + pattern: '^[0-9]{10}$' + example: '7702070139' + settlement_location: + $ref: '#/components/schemas/SettlementLocation' + + ClaimSecurity: + type: object + required: + - security_code + - security_details + - quantity + - settlement_accounts + properties: + security_code: + type: string + pattern: '^[0-9A-Z_/-]{12}$' + example: MM0766162534 + security_details: + $ref: '#/components/schemas/SecurityDetails' + quantity: + $ref: '#/components/schemas/Quantity' + settlement_accounts: + type: array + minItems: 1 + items: + $ref: '#/components/schemas/SettlementAccount' + + CostInfo: + type: object + description: | + Информация об учёте стоимости приобретения. Choice: либо + `yes` (с кодом депонента-источника), либо `no` (учёт не ведётся). + properties: + yes: + type: object + required: [code] + properties: + code: + type: string + pattern: '^[A-Z0-9]+$' + maxLength: 12 + example: MC0010300032 + no: + type: object + description: Пустой объект — учёт не ведётся. + + IIAAgreement: + type: object + description: Реквизиты договора ИИС (нужно, если перевод идёт по ИИС). + required: + - agreement_type + - agreement_number + - agreement_date + - broker_inn + properties: + agreement_type: + $ref: '#/components/schemas/AgreementType' + agreement_number: + type: string + maxLength: 128 + example: ИИС78/2024 + agreement_date: + type: string + format: date + example: '2026-01-15' + broker_inn: + type: string + pattern: '^[0-9]{10}$' + example: '0707083893' + + CreateClaimRequest: + type: object + required: + - investor + - transferring_depository_inn + - receiving_depository_inn + - cost_info + - securities + - signed_document + - signature_format + properties: + investor: + $ref: '#/components/schemas/Investor' + transferring_depository_inn: + type: string + pattern: '^[0-9]{10}$' + receiving_depository_inn: + type: string + pattern: '^[0-9]{10}$' + cost_info: + $ref: '#/components/schemas/CostInfo' + iia_agreement: + $ref: '#/components/schemas/IIAAgreement' + securities: + type: array + minItems: 1 + items: + $ref: '#/components/schemas/ClaimSecurity' + signed_document: + type: string + format: byte + description: Подписанный XML заявления в base64. + signature_format: + $ref: '#/components/schemas/SignatureFormat' + + CreateClaimResponse: + type: object + required: [id, status, created_at, success] + properties: + id: + type: string + format: uuid + status: + $ref: '#/components/schemas/ClaimStatus' + created_at: + type: string + format: date-time + success: + type: boolean + example: true + + Claim: + type: object + description: Полная сущность заявки. + required: + - id + - status + - created_at + - updated_at + - investor + - transferring_depository_inn + - receiving_depository_inn + - securities + properties: + id: + type: string + format: uuid + status: + $ref: '#/components/schemas/ClaimStatus' + created_at: + type: string + format: date-time + updated_at: + type: string + format: date-time + investor: + $ref: '#/components/schemas/Investor' + transferring_depository_inn: + type: string + pattern: '^[0-9]{10}$' + receiving_depository_inn: + type: string + pattern: '^[0-9]{10}$' + cost_info: + $ref: '#/components/schemas/CostInfo' + iia_agreement: + $ref: '#/components/schemas/IIAAgreement' + securities: + type: array + items: + $ref: '#/components/schemas/ClaimSecurity' + last_callback: + $ref: '#/components/schemas/StatusCallback' + + ClaimsPage: + type: object + required: [items, total, limit, offset] + properties: + items: + type: array + items: + $ref: '#/components/schemas/Claim' + total: + type: integer + minimum: 0 + limit: + type: integer + offset: + type: integer + + StatusCallback: + type: object + description: Callback обновления статуса от lk-gateway к ЛК. + required: + - claim_id + - new_status + - updated_at + properties: + claim_id: + type: string + format: uuid + new_status: + $ref: '#/components/schemas/ClaimStatus' + reason_code: + type: string + maxLength: 6 + description: Код причины (для rejected/timed_out) из M2MTransferResponse или M2MTransferDecision. + example: '01' + reason_text: + type: string + maxLength: 1024 + updated_at: + type: string + format: date-time + nsd_response: + type: object + description: Оригинал ответа НРД (необязательно, для аудита). + properties: + guid: + type: string + format: uuid + status_code: + type: string + enum: [INFO, ERROR] + responses: + type: array + items: + type: object + properties: + reference_id: + type: string + pattern: '^M2M[A-Z0-9]{13}$' + code: + type: string + text: + type: string + + CallbackResponse: + type: object + required: [success] + properties: + success: + type: boolean + + ErrorResponse: + type: object + description: Формат ошибки, идентичный API ESIA Finance V1. + required: [error, status] + properties: + error: + type: boolean + example: true + status: + type: integer + example: 422 + code: + type: string + example: invalid_signature + title: + type: string + example: Подпись не прошла проверку + meta: + type: object + properties: + message: + type: string + errors: + type: array + items: + type: object + properties: + field: + type: string + message: + type: string diff --git a/docs/tasks/README.md b/docs/tasks/README.md index a72039b..7bfddca 100644 --- a/docs/tasks/README.md +++ b/docs/tasks/README.md @@ -13,7 +13,7 @@ PR-1 → PR-N. Каждая задача — самостоятельный ос |----|------|--------|-----------| | PR-1 | `PR-1-go-models-m2m.md` | выполнено | — | | PR-2 | `PR-2-fansy-ddl.md` | выполнено | — (параллельно с PR-1) | -| PR-3 | `PR-3-lk-openapi.md` | готово к запуску | — (параллельно с PR-1) | +| PR-3 | `PR-3-lk-openapi.md` | выполнено | — (параллельно с PR-1) | | PR-4 | `PR-4-m2m-core-skeleton.md` | готово к запуску | PR-1 | | PR-5 | `PR-5-nsd-adapter-skeleton.md` | ждёт ИШ НРД и сертификаты | PR-1, PR-4 | | PR-6 | `PR-6-crypto-service-skeleton.md` | ждёт КриптоПро JCP | PR-1 |