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
