# PR-5: Каркас `nsd-adapter` — клиент к ИШ НРД (REST), резерв через WS ONYX

## Цель

Реализовать транспорт к НРД. Основной канал — Интеграционный шлюз НРД
через REST API (ИШ сам подписывает и упаковывает пакеты ЭДО, нам
XMLDSig не нужен). Резерв — WS ONYX (с подписью на нашей стороне через
`crypto-service`, реализуется когда КриптоПро JCP будет доступен).

## Зависимости

- PR-1 (Go-модели).
- PR-4 (`m2m-core` — туда инжектим `NSDSender`).
- Внешние: установленный ИШ НРД на ВМ, тестовые сертификаты GUEST/TEST3.

## Состояние блокеров

Этот PR можно начать **только после**:

- НРД выдал тестовые сертификаты GUEST/TEST3 (ГОСТ или RSA);
- получен и установлен дистрибутив Интеграционного шлюза;
- доступен REST-эндпоинт ИШ (обычно `http://localhost:8080/api/...`).

До этого — оставить PR-5 в очереди, не блокировать другие PR.

## Источники

- `DOC/Инструкция по передаче эталонного запроса на перевод M2M 08.04 (1).pdf`
- `DOC/Презентация MOEX MOST.pdf`
- `DOC/instr_podkl_stend_v3.pdf`
- `DOC/Ссылки для доступа в тестовые контуры.pdf`

## Состав PR

### 1. REST-клиент ИШ

`internal/nsdadapter/igw/client.go`:

Методы:
- `SendPackage(ctx, channel, packageType, body []byte) (packageID string, err error)`
  → `POST /api/package/{channel}/file`, тело: ZIP в base64 в JSON.
- `GetStatus(ctx, packageID) (Status, err error)`
  → `GET /api/package/status/{id}`.
- `ListIncoming(ctx, channel, since time.Time, packageType string) ([]Package, error)`
  → `GET /api/package?channel=&date=&type=...`.

Поддержка типов пакетов: `#M2MTR`, `#M2MTD`, `#M2MER`, `SUBBR`, `SUBER`,
`SUB16`, Assets_investment_*, стандартные квитанции ЭДО.

### 2. Маршрутизация и пакетирование

`internal/nsdadapter/router.go`:

Функция «доменное сообщение → тип пакета ЭДО + содержимое ZIP».

Каждое сообщение M2M упаковывается в ZIP вместе с `config.xml` по
Правилам ЭДО — но если ИШ работает в режиме «принимаю XML, сам
формирую пакет», достаточно отправить чистый XML и тип пакета.

### 3. Реализация `NSDSender` из PR-4

`internal/nsdadapter/sender.go`:

Реализует интерфейс `m2mcore.NSDSender`, использует REST-клиент ИШ.

### 4. Конфигурация

`internal/nsdadapter/config.go`:

Профили: `guest-gost`, `guest-rsa`, `test3-gost`, `test3-rsa`,
`prod-gost`, `prod-rsa`.

Каждый профиль: URL ИШ, путь к ключевому контейнеру (на стороне ИШ),
таймауты, retry-политика.

### 5. Резервный канал WS ONYX (опц., если время позволяет)

`internal/nsdadapter/onyx/`:

SOAP-клиент к `OnyxEdoWSService`. Подпись пакета через
`crypto-service` (gRPC). Реализуется когда `crypto-service` будет
готов (PR-6).

В PR-5 — структуры и заглушка с TODO.

### 6. Опрос входящих

`cmd/nsd-adapter/main.go`:

Минимальный сервис: каждые N секунд (конфиг) делает
`ListIncoming` для актуальных типов пакетов, скачивает новые,
сохраняет в БД (`incoming_packages` таблица), эмитит событие в
`m2m-core` через шину или прямой вызов.

### 7. Интеграционный тест на стенде

`internal/nsdadapter/igw/integration_test.go`:

- Помечен `//go:build integration`.
- Запускает эталонный запрос из
  `DOC/Инструкция по передаче эталонного запроса на перевод M2M 08.04 (1).pdf`
  на TEST3.
- Проверяет, что приходит `#M2MTD` (от тестового брокера 2) или
  `#M2MER` (тех. ошибка).
- Поднимается только когда `BJ_INTEGRATION_TEST_NSD=1`.

## Требования

- Логировать каждое обращение к ИШ (метод, URL, HTTP-статус,
  package_id, длительность). **Не логировать содержимое пакета**
  (там могут быть ПДн).
- Маскировать ПДн (ФИО, документы) в любых логах.
- Без эмодзи.

## Коммит

```
feat(nsd-adapter): REST-клиент ИШ НРД + маршрутизация типов пакетов

- internal/nsdadapter/igw/: REST-клиент ИШ (SendPackage, GetStatus, ListIncoming)
- internal/nsdadapter/router.go: маршрутизация по типам пакетов ЭДО
- internal/nsdadapter/sender.go: реализация m2mcore.NSDSender
- internal/nsdadapter/config.go: профили GUEST/TEST3/PROD x ГОСТ/RSA
- internal/nsdadapter/onyx/: каркас резервного канала WS ONYX
- cmd/nsd-adapter/main.go: опрос входящих пакетов

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
```

## После коммита

Обновить `docs/tasks/README.md`: PR-5 — «выполнено».
