# internal/m2mcore — ядро бизнес-логики M2M Конечный автомат сделки, репозиторий, идемпотентность по GUID, сборка `M2MTransferRequest` из заявки ЛК + данных Fansy, метрики SLA. ## Состав - `fsm.go` — состояния FSM и матрица разрешённых переходов (`Draft → Validated → SubmittedToNSD → AwaitingDecision → Confirmed → AwaitingSUB16 → Done`, ветки `Rejected`, `TimedOut`, `ManualApproval`). - `deal.go` — доменная модель `Deal` с явными методами переходов (`Validate`, `Submit`, `ReceiveDecision`, `Timeout`, `SendToManualApproval`, `ApproveManually`, `RejectManually`, `CompleteSUB16`). Каждый переход проверяет текущее состояние, пишет историю в `Stages` и фиксирует событие в журнале. - `uuid.go` — генератор UUID v4 без внешних зависимостей. - `repo.go` — порт `Repository` + in-memory реализация `MemoryRepository` с идемпотентным `Create` (по GUID возвращает существующую сделку). PostgreSQL-реализация — задача M2 (миграция лежит в `migrations/m2m-core/001__deals.sql`). - `ports.go` — порты к внешним системам (`NSDSender`, `LKCallbackClient`, `CryptoVerifier`, `FansyStore`) с no-op заглушками для M1. - `enrich.go` — функция `EnrichRequest`: из `ClaimInput` (заявка ЛК) + данных Fansy собирает валидный `M2MTransferRequest`, генерирует `GUID` и `ReferenceID` по каждой ЦБ. - `metrics.go` — порт `Recorder` + `MemoryRecorder`, отдающий Prometheus text-format. В M2 заменим на `prometheus/client_golang`, когда прокси откроет Go-модули. ## Зависимости Только stdlib и собственные пакеты `internal/m2m`, `internal/nsdxml`. Никаких внешних модулей. ## Тесты - `fsm_test.go` — переходы и терминальные состояния. - `repo_test.go` — идемпотентность по GUID, фильтры в `List`. - `uuid_test.go` — формат UUID v4 и `ReferenceID`. - `metrics_test.go` — Prometheus-текст. ## Сервис cmd/m2m-core `cmd/m2m-core/main.go` — HTTP-сервер с `/healthz` и `/metrics`, in-memory репозиторий, no-op порты. Адрес из `BJ_HTTP_ADDR` (по умолчанию `:8081`). В M2 будет заменено на реальные клиенты НРД и crypto-service.