chore: каркас моно-репо и скрипт первичной подготовки dev-ВМ
Содержимое первого коммита:
- Структура моно-репо: cmd/{lk-gateway,m2m-core,nsd-adapter,lk-emulator,notify}/,
internal/{m2m,nsdxml,fansystore,notify}/, services/crypto-service/,
web/admin-ui/, deploy/docker-compose/, migrations/, docs/.
- Заглушки main.go во всех cmd/ — make build проходит из коробки.
- Makefile с целями build/test/lint/fmt/vet/tidy/ci/compose-up/compose-down.
- .golangci.yml, .gitignore, README.md (на русском).
- .claude/settings.json — общие ограничения Claude Code для команды
(запрет sudo, rm -rf, доступа к /etc/cryptopro, /var/cryptopro).
- README в каждом каталоге — назначение и стадия (M1..M5).
- docs/architecture/overview.md — выжимка из плана проекта.
- docs/fansy-contract/v1/, docs/lk-contract/v1/ — точки сборки контрактов
с командами Fansy и ЛК клиента.
- deploy/docker-compose/docker-compose.yml — dev-стек (PostgreSQL, MinIO).
- scripts/setup-dev-vm.sh — первичная подготовка dev-ВМ под РЕД ОС 7.x
и Ubuntu 22.04+ (для компаний без бюджета на лицензии); ставит Go 1.23,
Liberica JDK 21, Node.js 20 LTS, Podman, podman-compose, Claude Code CLI;
создаёт пользователя dev, /srv/dev, аудит-history. Идемпотентен.
- scripts/README.md — описание скрипта и ограничений.
Что НЕ коммитим:
- Секреты, ключи, сертификаты — закрыто в .gitignore.
- Локальные настройки Claude Code (settings.local.json) и сессионные
каталоги (.claude/projects/, .claude/worktrees/, .claude/logs/).
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -0,0 +1,50 @@
|
|||||||
|
{
|
||||||
|
"$schema": "https://json.schemastore.org/claude-code-settings.json",
|
||||||
|
"permissions": {
|
||||||
|
"allow": [
|
||||||
|
"Bash(go *)",
|
||||||
|
"Bash(make *)",
|
||||||
|
"Bash(git status)",
|
||||||
|
"Bash(git diff *)",
|
||||||
|
"Bash(git log *)",
|
||||||
|
"Bash(git branch *)",
|
||||||
|
"Bash(git fetch *)",
|
||||||
|
"Bash(git pull *)",
|
||||||
|
"Bash(git remote -v)",
|
||||||
|
"Bash(podman *)",
|
||||||
|
"Bash(podman-compose *)",
|
||||||
|
"Bash(docker *)",
|
||||||
|
"Bash(docker-compose *)",
|
||||||
|
"Bash(xmlstarlet *)",
|
||||||
|
"Bash(jq *)",
|
||||||
|
"Bash(ls *)",
|
||||||
|
"Bash(cat *)",
|
||||||
|
"Bash(grep *)",
|
||||||
|
"Bash(find *)",
|
||||||
|
"Bash(npm run *)",
|
||||||
|
"Bash(npx *)",
|
||||||
|
"Bash(./scripts/*)"
|
||||||
|
],
|
||||||
|
"deny": [
|
||||||
|
"Bash(rm -rf /*)",
|
||||||
|
"Bash(rm -rf ~)",
|
||||||
|
"Bash(rm -rf $HOME)",
|
||||||
|
"Bash(sudo *)",
|
||||||
|
"Bash(dd *)",
|
||||||
|
"Bash(mkfs *)",
|
||||||
|
"Bash(curl * | sh)",
|
||||||
|
"Bash(curl * | bash)",
|
||||||
|
"Bash(wget * | sh)",
|
||||||
|
"Bash(wget * | bash)",
|
||||||
|
"Read(/etc/cryptopro/**)",
|
||||||
|
"Read(/var/cryptopro/**)",
|
||||||
|
"Read(/etc/ipsec.d/**)",
|
||||||
|
"Read(/root/**)",
|
||||||
|
"Read(/home/admin/**)",
|
||||||
|
"Write(/etc/**)",
|
||||||
|
"Write(/var/**)",
|
||||||
|
"Write(/root/**)",
|
||||||
|
"Write(/home/admin/**)"
|
||||||
|
]
|
||||||
|
}
|
||||||
|
}
|
||||||
+60
@@ -0,0 +1,60 @@
|
|||||||
|
# Сборки
|
||||||
|
/bin/
|
||||||
|
/dist/
|
||||||
|
*.exe
|
||||||
|
*.test
|
||||||
|
*.out
|
||||||
|
|
||||||
|
# Go
|
||||||
|
vendor/
|
||||||
|
go.sum.lock
|
||||||
|
|
||||||
|
# Java / crypto-service
|
||||||
|
services/crypto-service/build/
|
||||||
|
services/crypto-service/.gradle/
|
||||||
|
services/crypto-service/target/
|
||||||
|
*.jar
|
||||||
|
*.class
|
||||||
|
|
||||||
|
# Node / admin-ui
|
||||||
|
web/admin-ui/node_modules/
|
||||||
|
web/admin-ui/dist/
|
||||||
|
|
||||||
|
# Локальные конфиги и секреты
|
||||||
|
.env
|
||||||
|
.env.local
|
||||||
|
*.local.yaml
|
||||||
|
*.local.yml
|
||||||
|
secrets/
|
||||||
|
certs/private/
|
||||||
|
|
||||||
|
# Контейнеры ключей и сертификаты — никогда не коммитим
|
||||||
|
*.p12
|
||||||
|
*.pfx
|
||||||
|
*.pem
|
||||||
|
*.key
|
||||||
|
*.cer.priv
|
||||||
|
|
||||||
|
# IDE и временные файлы
|
||||||
|
.idea/
|
||||||
|
.vscode/
|
||||||
|
*.swp
|
||||||
|
.DS_Store
|
||||||
|
|
||||||
|
# Логи
|
||||||
|
*.log
|
||||||
|
logs/
|
||||||
|
|
||||||
|
# Тестовые артефакты
|
||||||
|
coverage.out
|
||||||
|
coverage.html
|
||||||
|
test-results/
|
||||||
|
|
||||||
|
# Claude Code сессионные логи и локальные настройки
|
||||||
|
.claude/logs/
|
||||||
|
.claude/settings.local.json
|
||||||
|
.claude/projects/
|
||||||
|
.claude/worktrees/
|
||||||
|
|
||||||
|
# macOS
|
||||||
|
.DS_Store
|
||||||
@@ -0,0 +1,44 @@
|
|||||||
|
run:
|
||||||
|
timeout: 3m
|
||||||
|
go: "1.23"
|
||||||
|
|
||||||
|
linters:
|
||||||
|
disable-all: true
|
||||||
|
enable:
|
||||||
|
- errcheck
|
||||||
|
- gosimple
|
||||||
|
- govet
|
||||||
|
- ineffassign
|
||||||
|
- staticcheck
|
||||||
|
- unused
|
||||||
|
- gofmt
|
||||||
|
- goimports
|
||||||
|
- misspell
|
||||||
|
- revive
|
||||||
|
- gocritic
|
||||||
|
- bodyclose
|
||||||
|
- errorlint
|
||||||
|
- nilerr
|
||||||
|
- prealloc
|
||||||
|
- unconvert
|
||||||
|
- unparam
|
||||||
|
- whitespace
|
||||||
|
|
||||||
|
linters-settings:
|
||||||
|
goimports:
|
||||||
|
local-prefixes: git.zetit.ru/zuevav/Bridge-and-Join-s
|
||||||
|
misspell:
|
||||||
|
locale: US
|
||||||
|
revive:
|
||||||
|
rules:
|
||||||
|
- name: var-naming
|
||||||
|
disabled: false
|
||||||
|
- name: package-comments
|
||||||
|
disabled: true
|
||||||
|
|
||||||
|
issues:
|
||||||
|
exclude-rules:
|
||||||
|
- path: _test\.go
|
||||||
|
linters:
|
||||||
|
- errcheck
|
||||||
|
- unparam
|
||||||
@@ -0,0 +1,52 @@
|
|||||||
|
.PHONY: help build test lint fmt vet clean tidy ci compose-up compose-down
|
||||||
|
|
||||||
|
GO ?= go
|
||||||
|
GOLANGCI_LINT ?= golangci-lint
|
||||||
|
COMPOSE ?= podman-compose
|
||||||
|
|
||||||
|
help:
|
||||||
|
@echo "Цели:"
|
||||||
|
@echo " make build - сборка всех бинарников Go"
|
||||||
|
@echo " make test - юнит-тесты"
|
||||||
|
@echo " make lint - golangci-lint"
|
||||||
|
@echo " make fmt - gofmt + goimports"
|
||||||
|
@echo " make vet - go vet"
|
||||||
|
@echo " make tidy - go mod tidy"
|
||||||
|
@echo " make ci - все проверки CI локально"
|
||||||
|
@echo " make compose-up - поднять локальный стек (PostgreSQL, MinIO, заглушки)"
|
||||||
|
@echo " make compose-down - остановить локальный стек"
|
||||||
|
@echo " make clean - удалить артефакты"
|
||||||
|
|
||||||
|
build:
|
||||||
|
@mkdir -p bin
|
||||||
|
$(GO) build -o bin/lk-gateway ./cmd/lk-gateway
|
||||||
|
$(GO) build -o bin/m2m-core ./cmd/m2m-core
|
||||||
|
$(GO) build -o bin/nsd-adapter ./cmd/nsd-adapter
|
||||||
|
$(GO) build -o bin/lk-emulator ./cmd/lk-emulator
|
||||||
|
$(GO) build -o bin/notify ./cmd/notify
|
||||||
|
|
||||||
|
test:
|
||||||
|
$(GO) test ./... -race -count=1
|
||||||
|
|
||||||
|
lint:
|
||||||
|
$(GOLANGCI_LINT) run ./...
|
||||||
|
|
||||||
|
fmt:
|
||||||
|
$(GO) fmt ./...
|
||||||
|
|
||||||
|
vet:
|
||||||
|
$(GO) vet ./...
|
||||||
|
|
||||||
|
tidy:
|
||||||
|
$(GO) mod tidy
|
||||||
|
|
||||||
|
ci: tidy fmt vet lint test build
|
||||||
|
|
||||||
|
compose-up:
|
||||||
|
$(COMPOSE) -f deploy/docker-compose/docker-compose.yml up -d
|
||||||
|
|
||||||
|
compose-down:
|
||||||
|
$(COMPOSE) -f deploy/docker-compose/docker-compose.yml down
|
||||||
|
|
||||||
|
clean:
|
||||||
|
rm -rf bin/ dist/ coverage.out coverage.html
|
||||||
@@ -0,0 +1,61 @@
|
|||||||
|
# Bridge and Join's — сервис M2M-перевода ценных бумаг через НРД
|
||||||
|
|
||||||
|
Внутренний модуль брокера для обмена с НРД сообщениями о переводе ценных бумаг
|
||||||
|
(M2M, ЭДО НРД, сервис MOEX MOST). Реализация — российское ПО, готовится к
|
||||||
|
включению в Реестр (ПП РФ № 1236).
|
||||||
|
|
||||||
|
## Назначение
|
||||||
|
|
||||||
|
Связующий модуль между:
|
||||||
|
|
||||||
|
- личным кабинетом клиента на платформе ESIA Finance (источник заявлений инвестора);
|
||||||
|
- учётной системой `Fansy` (источник реквизитов и остатков, выгрузка в нашу
|
||||||
|
принимающую БД делает отдельная команда);
|
||||||
|
- НРД через Интеграционный шлюз / Web-сервис ONYX (формат XML по схемам
|
||||||
|
`M2MTransferRequest/Decision/Response/Handbook/ParticipantForm`).
|
||||||
|
|
||||||
|
Подробное описание архитектуры, потока, регуляторных требований, SLA и
|
||||||
|
дорожной карты — см. `docs/architecture/overview.md` и план в репозитории
|
||||||
|
команды.
|
||||||
|
|
||||||
|
## Стек
|
||||||
|
|
||||||
|
- Go 1.23+ — ядро (`cmd/`, `internal/`).
|
||||||
|
- Java 21 (Liberica JDK) + КриптоПро JCP — `services/crypto-service` (XMLDSig
|
||||||
|
по ГОСТ Р 34.10-2012, серверная подпись действий оператора).
|
||||||
|
- React + Vite — `web/admin-ui` (журнал, ручное согласование, сертификаты).
|
||||||
|
- PostgreSQL Pro Certified — основная БД (`m2m-core`, `fansy-store`, аудит).
|
||||||
|
- MinIO — эталоны подписанных XML.
|
||||||
|
- Развёртывание — одна ВМ внутри контура брокера, `podman-compose`.
|
||||||
|
|
||||||
|
## Документация
|
||||||
|
|
||||||
|
- `DOC/` — оригинальная документация НРД (схемы XSD, инструкции, эталоны).
|
||||||
|
- `docs/architecture/overview.md` — обзор архитектуры.
|
||||||
|
- `docs/fansy-contract/v1/` — DDL и контракт данных для команды Fansy.
|
||||||
|
- `docs/lk-contract/v1/` — OpenAPI контракта с ЛК клиента (ESIA Finance).
|
||||||
|
- `scripts/setup-dev-vm.sh` — скрипт первичной подготовки dev-ВМ.
|
||||||
|
|
||||||
|
## Быстрый старт (на dev-ВМ)
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# под admin (один раз на ВМ)
|
||||||
|
sudo bash scripts/setup-dev-vm.sh
|
||||||
|
|
||||||
|
# под dev
|
||||||
|
git clone https://git.zetit.ru/zuevav/Bridge-and-Join-s.git
|
||||||
|
cd Bridge-and-Join-s
|
||||||
|
make build
|
||||||
|
make test
|
||||||
|
```
|
||||||
|
|
||||||
|
## Ветви
|
||||||
|
|
||||||
|
- `main` — стабильная.
|
||||||
|
- `feature/<имя>` — рабочие ветви, в основную через merge request.
|
||||||
|
- `claude/<...>` — служебные ветви автоматизированных правок.
|
||||||
|
|
||||||
|
## Лицензия
|
||||||
|
|
||||||
|
Внутренняя разработка. Лицензионная модель будет определена при подаче
|
||||||
|
в Реестр российского ПО.
|
||||||
@@ -0,0 +1,20 @@
|
|||||||
|
// Package main — сервис lk-emulator. Эмулятор ЛК клиента (ESIA Finance API V1)
|
||||||
|
// на время, пока реальный ЛК не готов. Позволяет «как будто загрузить»
|
||||||
|
// заявление через веб-форму и запустить полный путь обработки документа.
|
||||||
|
//
|
||||||
|
// Когда реальный ЛК подключится — эмулятор остаётся как тестовый инструмент
|
||||||
|
// в QA-окружении.
|
||||||
|
//
|
||||||
|
// На этапе M1 — заглушка.
|
||||||
|
package main
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"os"
|
||||||
|
)
|
||||||
|
|
||||||
|
const serviceName = "lk-emulator"
|
||||||
|
|
||||||
|
func main() {
|
||||||
|
fmt.Fprintf(os.Stdout, "%s: запуск (заглушка M1)\n", serviceName)
|
||||||
|
}
|
||||||
@@ -0,0 +1,17 @@
|
|||||||
|
// Package main — сервис lk-gateway. Принимает заявления от ЛК клиента
|
||||||
|
// (платформа ESIA Finance, /api/v1/back_office/...), валидирует их подпись,
|
||||||
|
// передаёт в m2m-core, отдаёт callback-статусы обратно в ЛК.
|
||||||
|
//
|
||||||
|
// На этапе M1 — заглушка. Реализация контракта — M2.
|
||||||
|
package main
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"os"
|
||||||
|
)
|
||||||
|
|
||||||
|
const serviceName = "lk-gateway"
|
||||||
|
|
||||||
|
func main() {
|
||||||
|
fmt.Fprintf(os.Stdout, "%s: запуск (заглушка M1)\n", serviceName)
|
||||||
|
}
|
||||||
@@ -0,0 +1,17 @@
|
|||||||
|
// Package main — сервис m2m-core. Бизнес-логика и FSM сделки M2M-перевода:
|
||||||
|
// идемпотентность по GUID, валидация по XSD, метрики SLA, ветка ручного
|
||||||
|
// согласования и таймаут-отказа MOST.
|
||||||
|
//
|
||||||
|
// На этапе M1 — заглушка.
|
||||||
|
package main
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"os"
|
||||||
|
)
|
||||||
|
|
||||||
|
const serviceName = "m2m-core"
|
||||||
|
|
||||||
|
func main() {
|
||||||
|
fmt.Fprintf(os.Stdout, "%s: запуск (заглушка M1)\n", serviceName)
|
||||||
|
}
|
||||||
@@ -0,0 +1,19 @@
|
|||||||
|
// Package main — сервис notify. Отправка уведомлений по нескольким каналам:
|
||||||
|
// e-mail (SMTP), Yandex Messenger (Yandex 360), WebSocket-push в admin-ui,
|
||||||
|
// плюс расширяемая модель провайдеров-плагинов (smtp, yandex360, telegram,
|
||||||
|
// mattermost, webhook) под единый интерфейс Notifier — для тиражирования
|
||||||
|
// продукта другим компаниям.
|
||||||
|
//
|
||||||
|
// На этапе M1 — заглушка.
|
||||||
|
package main
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"os"
|
||||||
|
)
|
||||||
|
|
||||||
|
const serviceName = "notify"
|
||||||
|
|
||||||
|
func main() {
|
||||||
|
fmt.Fprintf(os.Stdout, "%s: запуск (заглушка M1)\n", serviceName)
|
||||||
|
}
|
||||||
@@ -0,0 +1,22 @@
|
|||||||
|
// Package main — сервис nsd-adapter. Транспорт к НРД:
|
||||||
|
// - Интеграционный шлюз через REST API (основной канал, ИШ сам подписывает);
|
||||||
|
// - Web-сервис ONYX напрямую (резерв);
|
||||||
|
// - Файловый шлюз / обменные папки ИШ (fallback).
|
||||||
|
//
|
||||||
|
// Сериализация и парсинг XML по схемам M2MSchemas в windows-1251,
|
||||||
|
// маршрутизация по типам пакетов (#M2MTR / #M2MTD / #M2MER / SUBBR / SUBER /
|
||||||
|
// SUB16 / Справки / квитанции ЭДО).
|
||||||
|
//
|
||||||
|
// На этапе M1 — заглушка.
|
||||||
|
package main
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"os"
|
||||||
|
)
|
||||||
|
|
||||||
|
const serviceName = "nsd-adapter"
|
||||||
|
|
||||||
|
func main() {
|
||||||
|
fmt.Fprintf(os.Stdout, "%s: запуск (заглушка M1)\n", serviceName)
|
||||||
|
}
|
||||||
@@ -0,0 +1,37 @@
|
|||||||
|
version: "3.9"
|
||||||
|
|
||||||
|
# Локальный стек разработки и тестирования.
|
||||||
|
# В прод-среде сервисы поднимаются через systemd-юниты или podman-compose
|
||||||
|
# с production-overlay. Здесь — dev-конфиг с минимальными настройками
|
||||||
|
# и без секретов.
|
||||||
|
|
||||||
|
services:
|
||||||
|
postgres:
|
||||||
|
image: postgres:16
|
||||||
|
# В проде заменить на postgrespro/std-16 или registry.postgrespro.ru/pgpro/...
|
||||||
|
container_name: bj-postgres
|
||||||
|
environment:
|
||||||
|
POSTGRES_USER: bj
|
||||||
|
POSTGRES_PASSWORD: bj_dev
|
||||||
|
POSTGRES_DB: bj
|
||||||
|
ports:
|
||||||
|
- "127.0.0.1:5432:5432"
|
||||||
|
volumes:
|
||||||
|
- bj-postgres-data:/var/lib/postgresql/data
|
||||||
|
|
||||||
|
minio:
|
||||||
|
image: minio/minio:latest
|
||||||
|
container_name: bj-minio
|
||||||
|
command: server /data --console-address ":9001"
|
||||||
|
environment:
|
||||||
|
MINIO_ROOT_USER: bj
|
||||||
|
MINIO_ROOT_PASSWORD: bj_dev_minio
|
||||||
|
ports:
|
||||||
|
- "127.0.0.1:9000:9000"
|
||||||
|
- "127.0.0.1:9001:9001"
|
||||||
|
volumes:
|
||||||
|
- bj-minio-data:/data
|
||||||
|
|
||||||
|
volumes:
|
||||||
|
bj-postgres-data:
|
||||||
|
bj-minio-data:
|
||||||
@@ -0,0 +1,52 @@
|
|||||||
|
# Архитектура — обзор
|
||||||
|
|
||||||
|
Краткая выжимка из плана проекта. Полный план хранится у разработки в
|
||||||
|
`/.claude/plans/precious-percolating-axolotl.md` (внешний документ).
|
||||||
|
|
||||||
|
## Что строим
|
||||||
|
|
||||||
|
Внутренний модуль брокера для M2M-перевода ценных бумаг через НРД
|
||||||
|
(сервис MOEX MOST). Сейчас разрабатывается «для себя», но архитектура
|
||||||
|
изначально закладывается под тиражирование другим компаниям.
|
||||||
|
|
||||||
|
## Состав
|
||||||
|
|
||||||
|
- `lk-gateway` — интеграция с ЛК клиента (ESIA Finance API V1).
|
||||||
|
- `lk-emulator` — эмулятор ЛК на время, пока реальный ЛК не готов.
|
||||||
|
- `m2m-core` — бизнес-логика и FSM сделки.
|
||||||
|
- `nsd-adapter` — три транспорта к НРД (ИШ REST — основной, WS ONYX —
|
||||||
|
резерв, ФШ — fallback) и маршрутизация по типам пакетов
|
||||||
|
(`#M2MTR/#M2MTD/#M2MER/SUBBR/SUBER/SUB16/Справки/квитанции ЭДО`).
|
||||||
|
- `crypto-service` — Java + КриптоПро JCP, КС1.
|
||||||
|
- `notify` — уведомления (e-mail, Yandex Messenger 360, WS-push,
|
||||||
|
webhook), архитектура плагинов.
|
||||||
|
- `fansy-store` — принимающая БД для выгрузки от команды Fansy.
|
||||||
|
- `admin-ui` — веб-интерфейс администратора и сотрудника депозитария.
|
||||||
|
|
||||||
|
## Стек
|
||||||
|
|
||||||
|
- Go 1.23, Java 21 (Liberica JDK), React + Vite + TypeScript.
|
||||||
|
- PostgreSQL Pro Certified (на проде), MinIO.
|
||||||
|
- Развёртывание — одна ВМ, podman-compose.
|
||||||
|
- Класс СКЗИ — КС1 (КриптоПро CSP/JCP).
|
||||||
|
|
||||||
|
## Ключевые ограничения
|
||||||
|
|
||||||
|
- SLA: 5 мин/этап на старте, 2 мин/этап в проде. Регуляторный таймаут
|
||||||
|
отсутствия ответа от Брокера 2 — 10 → 5 мин.
|
||||||
|
- Дедлайн прод-релиза — **01.09.2026** (вступление 124-ФЗ + Указания ЦБ).
|
||||||
|
- Реестр российского ПО (ПП-1236) — заявка на M5; стек и архитектура
|
||||||
|
соответствуют.
|
||||||
|
- Кодировка XML — windows-1251; формат `NSDDateTime` — только МСК-зона.
|
||||||
|
|
||||||
|
## Документация интеграций
|
||||||
|
|
||||||
|
- `docs/fansy-contract/v1/` — DDL и контракт данных для команды Fansy
|
||||||
|
(мы передаём, ETL делают они).
|
||||||
|
- `docs/lk-contract/v1/` — OpenAPI контракта с ЛК клиента.
|
||||||
|
|
||||||
|
## Развёртывание
|
||||||
|
|
||||||
|
- `deploy/docker-compose/docker-compose.yml` — dev-стек (PostgreSQL +
|
||||||
|
MinIO).
|
||||||
|
- `scripts/setup-dev-vm.sh` — подготовка dev-ВМ под РЕД ОС или Ubuntu.
|
||||||
@@ -0,0 +1,33 @@
|
|||||||
|
# docs/fansy-contract/v1 — контракт данных с командой Fansy
|
||||||
|
|
||||||
|
ETL Fansy → принимающая БД (`fansy-store`) реализует **другая команда
|
||||||
|
разработки**. С нашей стороны:
|
||||||
|
|
||||||
|
1. Спроектировать таблицы по требованиям документации НРД к данным M2M.
|
||||||
|
2. Передать команде Fansy DDL и контракт данных.
|
||||||
|
3. Согласовать тип load (UPSERT в staging), окна обновления, SLA на
|
||||||
|
свежесть данных.
|
||||||
|
4. Не давать ETL-роли DDL-прав в принимающей схеме.
|
||||||
|
|
||||||
|
Состав каталога (создаём в M1, отправляем в начале M2):
|
||||||
|
|
||||||
|
- `ddl/` — `*.sql` миграции PostgreSQL для всех таблиц.
|
||||||
|
- `data-dictionary.md` — семантика каждого поля (источник в Fansy,
|
||||||
|
nullable, единицы, примеры).
|
||||||
|
- `etl-requirements.md` — требования к процессу выгрузки: тип load,
|
||||||
|
расписание, способ записи, окна простоя, обработка ошибок,
|
||||||
|
конфиденциальность.
|
||||||
|
- `examples/` — пример заявки M2M «end-to-end», 5–10 тестовых клиентов
|
||||||
|
и заявок для совместного приёмочного теста.
|
||||||
|
|
||||||
|
Минимальный набор таблиц (см. план):
|
||||||
|
|
||||||
|
- Депоненты / клиенты.
|
||||||
|
- Документы инвестора (`IdentityDocumentCodeEnum`).
|
||||||
|
- ИИС-договоры (`IIAContractTypeEnum ∈ {T12, T03}`).
|
||||||
|
- Депо-счета и разделы (`AccountId`, `SectionId`, `DeponentCode`).
|
||||||
|
- Реквизиты расчётов (ИНН депозитария).
|
||||||
|
- Портфели и остатки (Whole / Fractional, `IsolationStatus = SGDN`).
|
||||||
|
- Справочник ЦБ (`SecurityCode`, `ISIN`, `Classification`, `Category`).
|
||||||
|
- Контрагенты-участники сервиса MOST (Справочник пользователей).
|
||||||
|
- Audit / staging-таблицы для каждой основной.
|
||||||
@@ -0,0 +1,18 @@
|
|||||||
|
# docs/lk-contract/v1 — контракт с ЛК клиента (ESIA Finance)
|
||||||
|
|
||||||
|
ЛК клиента работает на платформе **ESIA Finance**, контракт описан
|
||||||
|
в `DOC/API ЛК ЕСИА.pdf` (`/api/v1/back_office/...`, Basic HTTP, JSON,
|
||||||
|
UTF-8).
|
||||||
|
|
||||||
|
На этапе M1 в `lk-emulator` мы воспроизводим этот контракт для запуска
|
||||||
|
сквозного потока. Реальный ЛК подключится по тому же контракту, без
|
||||||
|
правок на нашей стороне.
|
||||||
|
|
||||||
|
В этом каталоге будут:
|
||||||
|
|
||||||
|
- `openapi.yaml` — наш OpenAPI-контракт `lk-gateway`, согласованный
|
||||||
|
с командой ЛК.
|
||||||
|
- `examples/` — примеры заявлений и ответов.
|
||||||
|
- `changelog.md` — версионирование контракта.
|
||||||
|
|
||||||
|
Реализация — задача M1.
|
||||||
@@ -0,0 +1,8 @@
|
|||||||
|
# internal/fansystore — Go-репозиторий чтения нашей принимающей БД
|
||||||
|
|
||||||
|
ETL Fansy → принимающая БД делает **отдельная команда**. Здесь только
|
||||||
|
типизированный Go-доступ на чтение/обогащение из `m2m-core`.
|
||||||
|
|
||||||
|
DDL и контракт данных — `docs/fansy-contract/v1/`.
|
||||||
|
|
||||||
|
Реализация — задача M2 (см. план).
|
||||||
@@ -0,0 +1,24 @@
|
|||||||
|
# internal/m2m — доменные модели сообщений M2M
|
||||||
|
|
||||||
|
Go-модели, генерируемые/выровненные по XSD из `DOC/M2MSchemas_260408/`
|
||||||
|
(namespace `http://nsd.ru/schemas/m2m/...`, version `2026-04-08`).
|
||||||
|
|
||||||
|
Состав:
|
||||||
|
|
||||||
|
- `M2MTransferRequest` — запрос на перевод.
|
||||||
|
- `M2MTransferDecision` — решение принимающей стороны.
|
||||||
|
- `M2MTransferResponse` — тех. ответ НРД (`StatusCode ∈ {INFO, ERROR}`).
|
||||||
|
- `M2MTransferHandbook(+Request)` — справочник участников.
|
||||||
|
- `M2MTransferParticipantForm` — карточка участника.
|
||||||
|
|
||||||
|
Точные ограничения (валидаторы):
|
||||||
|
|
||||||
|
- `ReferenceId` — длина 16, pattern `M2M[A-Z0-9]{13}`.
|
||||||
|
- `DeponentCode` — до 12 символов, `[A-Z0-9]*`.
|
||||||
|
- `ISIN` — длина 12, `[A-Z]{2}[A-Z0-9]{9}[0-9]`.
|
||||||
|
- `OrganizationINN` — ровно 10 цифр.
|
||||||
|
- `IIAContractType` — `T12 | T03`.
|
||||||
|
- `SecurityClassification` — `BOND | SHAR | MFUN`.
|
||||||
|
- `IsolationStatus` — единственное значение `SGDN`.
|
||||||
|
|
||||||
|
Реализация — задача M1 (см. план).
|
||||||
@@ -0,0 +1,15 @@
|
|||||||
|
# internal/notify — провайдеры уведомлений
|
||||||
|
|
||||||
|
Архитектура — плагины под единый интерфейс `Notifier`. Реализации в
|
||||||
|
конфиге включаются/выключаются без изменений в коде:
|
||||||
|
|
||||||
|
- `smtp` — внутренняя корпоративная почта.
|
||||||
|
- `yandex360` — Yandex Messenger через Yandex 360 для бизнеса
|
||||||
|
(используем готового бота заказчика).
|
||||||
|
- `webhook` — универсальный POST по URL, для лёгкого подключения
|
||||||
|
других систем при тиражировании.
|
||||||
|
- `wspush` — push-уведомления в `admin-ui` через WebSocket.
|
||||||
|
- (опционально) `telegram`, `mattermost`, `rocketchat` — заглушки с
|
||||||
|
примером расширения.
|
||||||
|
|
||||||
|
Реализация — задача M4 (см. план).
|
||||||
@@ -0,0 +1,14 @@
|
|||||||
|
# internal/nsdxml — сериализация и парсинг XML по правилам НРД
|
||||||
|
|
||||||
|
Особенности, которые этот пакет обязан учитывать:
|
||||||
|
|
||||||
|
- **Кодировка `windows-1251`** на чтение и запись (XML-объявление и тело).
|
||||||
|
Для конвертации — `golang.org/x/text/encoding/charmap.Windows1251`.
|
||||||
|
- **Тип `NSDDateTime`** — формат `YYYY-MM-DDThh:mm:ss(МСК[+/-N])`,
|
||||||
|
pattern из XSD:
|
||||||
|
`[0-9]{4}-(0[1-9]|1[0-2])-(0[1-9]|[12][0-9]|3[01])T([01][0-9]|2[0-3]):[0-5][0-9]:[0-5][0-9]\(МСК([+-][0-9]{1,2})?\)`.
|
||||||
|
Только зона МСК, опциональный сдвиг.
|
||||||
|
- **Каноникализация `xml-exc-c14n`** для проверки совпадения с эталоном.
|
||||||
|
- **Round-trip**: `Marshal(Unmarshal(x)) == x` после канонизации.
|
||||||
|
|
||||||
|
Реализация — задача M1 (см. план).
|
||||||
@@ -0,0 +1,56 @@
|
|||||||
|
# scripts — служебные скрипты
|
||||||
|
|
||||||
|
## setup-dev-vm.sh
|
||||||
|
|
||||||
|
Первичная подготовка dev-ВМ.
|
||||||
|
|
||||||
|
Поддерживаемые ОС:
|
||||||
|
|
||||||
|
- **РЕД ОС 7.x** — целевая прод-ОС.
|
||||||
|
- **Ubuntu 22.04+** / **Debian 12+** — бюджетная альтернатива для
|
||||||
|
разработки и для компаний без лицензий на сертифицированные ОС.
|
||||||
|
- **Astra Linux** (deb-семейство) — поддерживается базовый сценарий.
|
||||||
|
- RHEL-совместимые (Rocky, Alma) — для разработки.
|
||||||
|
|
||||||
|
Что ставит:
|
||||||
|
|
||||||
|
- базовый dev-стек (git, make, jq, xmlstarlet и т. п.),
|
||||||
|
- Podman + podman-compose,
|
||||||
|
- Go 1.23,
|
||||||
|
- Liberica JDK 21 (BellSoft),
|
||||||
|
- Node.js 20 LTS,
|
||||||
|
- Claude Code CLI (`@anthropic-ai/claude-code`).
|
||||||
|
|
||||||
|
Что готовит:
|
||||||
|
|
||||||
|
- пользователя `dev` с домашней директорией, без sudo по умолчанию,
|
||||||
|
- рабочий каталог `/srv/dev`,
|
||||||
|
- bash-историю с timestamp для аудита,
|
||||||
|
- `/etc/profile.d/go.sh` для PATH к Go.
|
||||||
|
|
||||||
|
Запуск:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
sudo bash scripts/setup-dev-vm.sh
|
||||||
|
```
|
||||||
|
|
||||||
|
Тонкая настройка через переменные окружения — см. шапку скрипта.
|
||||||
|
|
||||||
|
Идемпотентен — повторный запуск ничего не ломает.
|
||||||
|
|
||||||
|
### Что НЕ делает скрипт
|
||||||
|
|
||||||
|
Эти шаги — вручную, по мере получения артефактов:
|
||||||
|
|
||||||
|
1. Установка КриптоПро CSP и КриптоПро JCP под целевую ОС.
|
||||||
|
2. Установка дистрибутива Интеграционного шлюза НРД.
|
||||||
|
3. Импорт тестовых сертификатов GUEST/TEST3 (ГОСТ + RSA).
|
||||||
|
4. Настройка исходящего файрвола / прокси (whitelist для НРД,
|
||||||
|
git.zetit.ru, npmjs, golang, anthropic).
|
||||||
|
|
||||||
|
### Прод-ограничения
|
||||||
|
|
||||||
|
Скрипт удобен для разработки на любой из перечисленных ОС, но для
|
||||||
|
прод-стенда в финансовом секторе требуется **сертифицированная РЕД ОС
|
||||||
|
или Astra SE** + лицензированный **КриптоПро КС1**. Ubuntu/Debian/Rocky
|
||||||
|
для прода финсектора не подходят.
|
||||||
Executable
+373
@@ -0,0 +1,373 @@
|
|||||||
|
#!/usr/bin/env bash
|
||||||
|
# Скрипт первичной подготовки dev-ВМ для проекта Bridge and Join's
|
||||||
|
# (сервис M2M-перевода ЦБ через НРД).
|
||||||
|
#
|
||||||
|
# Поддерживаемые ОС:
|
||||||
|
# - РЕД ОС 7.x — целевая прод-ОС (вариант с бюджетом на лицензии)
|
||||||
|
# - Ubuntu 22.04+ — бюджетная альтернатива для разработки и для
|
||||||
|
# компаний, у которых ещё нет лицензий на РЕД ОС
|
||||||
|
# (для прод-сертификации в финсекторе всё равно
|
||||||
|
# потребуется РЕД ОС / Astra SE с сертификатом ФСТЭК)
|
||||||
|
#
|
||||||
|
# Что делает:
|
||||||
|
# - определяет ОС и пакетный менеджер;
|
||||||
|
# - устанавливает базовый dev-стек (Git, Make, jq, xmlstarlet, ...);
|
||||||
|
# - устанавливает Go 1.23, Liberica JDK 21, Node.js 20 LTS, Podman;
|
||||||
|
# - устанавливает Claude Code CLI;
|
||||||
|
# - создаёт пользователя dev и каталог /srv/dev;
|
||||||
|
# - готовит безопасный shell-history с timestamp.
|
||||||
|
#
|
||||||
|
# Запуск (под root или через sudo):
|
||||||
|
# sudo bash scripts/setup-dev-vm.sh
|
||||||
|
#
|
||||||
|
# Переменные окружения для тонкой настройки:
|
||||||
|
# GO_VERSION — версия Go (по умолчанию 1.23.4)
|
||||||
|
# JDK_VERSION — версия Liberica JDK (по умолчанию 21)
|
||||||
|
# NODE_VERSION — версия Node (по умолчанию 20)
|
||||||
|
# DEV_USER — имя пользователя для разработки (по умолчанию dev)
|
||||||
|
# DEV_HOME — домашняя директория dev (по умолчанию /home/dev)
|
||||||
|
# WORKSPACE_ROOT — корень рабочих репо (по умолчанию /srv/dev)
|
||||||
|
# SKIP_USER — 1, чтобы не создавать пользователя
|
||||||
|
# SKIP_CLAUDE — 1, чтобы не ставить Claude Code CLI
|
||||||
|
#
|
||||||
|
# Скрипт идемпотентен — повторный запуск не ломает то, что уже сделано.
|
||||||
|
|
||||||
|
set -euo pipefail
|
||||||
|
|
||||||
|
# --------------------------------------------------------------------- #
|
||||||
|
# Параметры
|
||||||
|
# --------------------------------------------------------------------- #
|
||||||
|
GO_VERSION="${GO_VERSION:-1.23.4}"
|
||||||
|
JDK_VERSION="${JDK_VERSION:-21}"
|
||||||
|
NODE_VERSION="${NODE_VERSION:-20}"
|
||||||
|
DEV_USER="${DEV_USER:-dev}"
|
||||||
|
DEV_HOME="${DEV_HOME:-/home/${DEV_USER}}"
|
||||||
|
WORKSPACE_ROOT="${WORKSPACE_ROOT:-/srv/dev}"
|
||||||
|
SKIP_USER="${SKIP_USER:-0}"
|
||||||
|
SKIP_CLAUDE="${SKIP_CLAUDE:-0}"
|
||||||
|
|
||||||
|
REPO_URL="https://git.zetit.ru/zuevav/Bridge-and-Join-s.git"
|
||||||
|
|
||||||
|
# --------------------------------------------------------------------- #
|
||||||
|
# Хелперы
|
||||||
|
# --------------------------------------------------------------------- #
|
||||||
|
log() { printf '[%s] %s\n' "$(date +'%Y-%m-%d %H:%M:%S')" "$*"; }
|
||||||
|
die() { printf '[ОШИБКА] %s\n' "$*" >&2; exit 1; }
|
||||||
|
need_root() { [[ "$EUID" -eq 0 ]] || die "Нужны права root. Запусти через sudo."; }
|
||||||
|
|
||||||
|
# --------------------------------------------------------------------- #
|
||||||
|
# 0. Предусловия — определение ОС и менеджера пакетов
|
||||||
|
# --------------------------------------------------------------------- #
|
||||||
|
need_root
|
||||||
|
|
||||||
|
if [[ ! -f /etc/os-release ]]; then
|
||||||
|
die "Файл /etc/os-release не найден. Проверь, что ОС поддерживает FHS."
|
||||||
|
fi
|
||||||
|
|
||||||
|
# shellcheck disable=SC1091
|
||||||
|
. /etc/os-release
|
||||||
|
|
||||||
|
OS_FAMILY="" # rpm | deb
|
||||||
|
OS_HUMAN=""
|
||||||
|
|
||||||
|
case "${ID:-}" in
|
||||||
|
redos)
|
||||||
|
OS_FAMILY="rpm"
|
||||||
|
OS_HUMAN="РЕД ОС ${VERSION_ID:-?}"
|
||||||
|
;;
|
||||||
|
rhel|centos|rocky|almalinux|fedora)
|
||||||
|
OS_FAMILY="rpm"
|
||||||
|
OS_HUMAN="${PRETTY_NAME:-RHEL-совместимая}"
|
||||||
|
log "ВНИМАНИЕ: ОС ${OS_HUMAN} — для разработки подходит, для прод-сертификации в финсекторе нужна РЕД ОС / Astra SE."
|
||||||
|
;;
|
||||||
|
ubuntu|debian)
|
||||||
|
OS_FAMILY="deb"
|
||||||
|
OS_HUMAN="${PRETTY_NAME:-${ID} ${VERSION_ID:-?}}"
|
||||||
|
log "ОС ${OS_HUMAN} — бюджетный вариант для разработки. Для прода в финсекторе нужна РЕД ОС / Astra SE с сертификатом ФСТЭК."
|
||||||
|
;;
|
||||||
|
astra)
|
||||||
|
OS_FAMILY="deb"
|
||||||
|
OS_HUMAN="Astra Linux ${VERSION_ID:-?}"
|
||||||
|
;;
|
||||||
|
*)
|
||||||
|
log "ВНИМАНИЕ: ОС определена как ${ID:-неизвестно} ${VERSION_ID:-?}."
|
||||||
|
if command -v dnf >/dev/null 2>&1 || command -v yum >/dev/null 2>&1; then
|
||||||
|
OS_FAMILY="rpm"
|
||||||
|
elif command -v apt-get >/dev/null 2>&1; then
|
||||||
|
OS_FAMILY="deb"
|
||||||
|
else
|
||||||
|
die "Не удалось определить пакетный менеджер. Поддерживаются dnf/yum (РЕД ОС, RHEL) и apt (Ubuntu, Debian, Astra)."
|
||||||
|
fi
|
||||||
|
log "Пробуем как ${OS_FAMILY}-совместимую."
|
||||||
|
;;
|
||||||
|
esac
|
||||||
|
|
||||||
|
log "ОС: ${OS_HUMAN}, семейство: ${OS_FAMILY}"
|
||||||
|
|
||||||
|
PKG_INSTALL=""
|
||||||
|
PKG_UPDATE=""
|
||||||
|
case "${OS_FAMILY}" in
|
||||||
|
rpm)
|
||||||
|
if command -v dnf >/dev/null 2>&1; then PKG_INSTALL="dnf install -y"; PKG_UPDATE="dnf -y makecache"
|
||||||
|
elif command -v yum >/dev/null 2>&1; then PKG_INSTALL="yum install -y"; PKG_UPDATE="yum -y makecache"
|
||||||
|
else die "Не найден dnf/yum"
|
||||||
|
fi
|
||||||
|
;;
|
||||||
|
deb)
|
||||||
|
export DEBIAN_FRONTEND=noninteractive
|
||||||
|
PKG_INSTALL="apt-get install -y --no-install-recommends"
|
||||||
|
PKG_UPDATE="apt-get update -y"
|
||||||
|
;;
|
||||||
|
esac
|
||||||
|
|
||||||
|
log "Обновление кэша пакетов"
|
||||||
|
${PKG_UPDATE}
|
||||||
|
|
||||||
|
# --------------------------------------------------------------------- #
|
||||||
|
# 1. Базовый системный стек
|
||||||
|
# --------------------------------------------------------------------- #
|
||||||
|
log "Шаг 1/8: установка базовых пакетов"
|
||||||
|
case "${OS_FAMILY}" in
|
||||||
|
rpm)
|
||||||
|
${PKG_INSTALL} \
|
||||||
|
git make curl wget tar gzip unzip ca-certificates \
|
||||||
|
jq xmlstarlet libxml2 \
|
||||||
|
gcc gcc-c++ binutils \
|
||||||
|
python3 python3-pip \
|
||||||
|
postgresql-libs \
|
||||||
|
openssl-libs
|
||||||
|
;;
|
||||||
|
deb)
|
||||||
|
${PKG_INSTALL} \
|
||||||
|
git make curl wget tar gzip unzip ca-certificates \
|
||||||
|
jq xmlstarlet libxml2-utils \
|
||||||
|
build-essential \
|
||||||
|
python3 python3-pip python3-venv \
|
||||||
|
libpq5 \
|
||||||
|
libssl3 \
|
||||||
|
gnupg lsb-release software-properties-common
|
||||||
|
;;
|
||||||
|
esac
|
||||||
|
|
||||||
|
# --------------------------------------------------------------------- #
|
||||||
|
# 2. Podman + podman-compose
|
||||||
|
# --------------------------------------------------------------------- #
|
||||||
|
log "Шаг 2/8: установка Podman и podman-compose"
|
||||||
|
case "${OS_FAMILY}" in
|
||||||
|
rpm)
|
||||||
|
${PKG_INSTALL} podman podman-docker || true
|
||||||
|
;;
|
||||||
|
deb)
|
||||||
|
${PKG_INSTALL} podman || true
|
||||||
|
# podman-docker может отсутствовать — не критично
|
||||||
|
apt-get install -y --no-install-recommends podman-docker 2>/dev/null || true
|
||||||
|
;;
|
||||||
|
esac
|
||||||
|
|
||||||
|
if ! command -v podman-compose >/dev/null 2>&1; then
|
||||||
|
pip3 install --quiet podman-compose || \
|
||||||
|
log "ВНИМАНИЕ: не удалось установить podman-compose через pip3. Поставь вручную."
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Включаем сокет podman, чтобы клиенты, ожидающие docker.sock, работали без правок
|
||||||
|
systemctl enable --now podman.socket 2>/dev/null || true
|
||||||
|
|
||||||
|
# --------------------------------------------------------------------- #
|
||||||
|
# 3. Go
|
||||||
|
# --------------------------------------------------------------------- #
|
||||||
|
log "Шаг 3/8: установка Go ${GO_VERSION}"
|
||||||
|
GO_TARBALL="go${GO_VERSION}.linux-amd64.tar.gz"
|
||||||
|
GO_URL="https://go.dev/dl/${GO_TARBALL}"
|
||||||
|
|
||||||
|
if [[ -d /usr/local/go && -x /usr/local/go/bin/go ]]; then
|
||||||
|
CURRENT_GO_VER="$(/usr/local/go/bin/go version | awk '{print $3}' | sed 's/go//')"
|
||||||
|
if [[ "${CURRENT_GO_VER}" == "${GO_VERSION}" ]]; then
|
||||||
|
log "Go ${GO_VERSION} уже установлен"
|
||||||
|
else
|
||||||
|
log "Найден Go ${CURRENT_GO_VER}, переустанавливаем на ${GO_VERSION}"
|
||||||
|
rm -rf /usr/local/go
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
|
||||||
|
if [[ ! -d /usr/local/go ]]; then
|
||||||
|
TMP_TAR="/tmp/${GO_TARBALL}"
|
||||||
|
wget -q --show-progress -O "${TMP_TAR}" "${GO_URL}"
|
||||||
|
tar -C /usr/local -xzf "${TMP_TAR}"
|
||||||
|
rm -f "${TMP_TAR}"
|
||||||
|
fi
|
||||||
|
|
||||||
|
cat > /etc/profile.d/go.sh <<'EOF'
|
||||||
|
export PATH=$PATH:/usr/local/go/bin
|
||||||
|
export GOPATH=$HOME/go
|
||||||
|
export PATH=$PATH:$GOPATH/bin
|
||||||
|
EOF
|
||||||
|
chmod 0644 /etc/profile.d/go.sh
|
||||||
|
|
||||||
|
# --------------------------------------------------------------------- #
|
||||||
|
# 4. Liberica JDK
|
||||||
|
# --------------------------------------------------------------------- #
|
||||||
|
log "Шаг 4/8: установка Liberica JDK ${JDK_VERSION}"
|
||||||
|
case "${OS_FAMILY}" in
|
||||||
|
rpm)
|
||||||
|
if [[ ! -f /etc/yum.repos.d/bellsoft.repo ]]; then
|
||||||
|
cat > /etc/yum.repos.d/bellsoft.repo <<'EOF'
|
||||||
|
[bellsoft]
|
||||||
|
name=BellSoft Repository
|
||||||
|
baseurl=https://yum.bell-sw.com/
|
||||||
|
enabled=1
|
||||||
|
gpgcheck=1
|
||||||
|
gpgkey=https://download.bell-sw.com/pki/GPG-KEY-bellsoft
|
||||||
|
EOF
|
||||||
|
fi
|
||||||
|
${PKG_INSTALL} "bellsoft-java${JDK_VERSION}" || \
|
||||||
|
log "ВНИМАНИЕ: не удалось установить bellsoft-java${JDK_VERSION}. Альтернатива — скачать tar.gz с https://bell-sw.com/pages/downloads/."
|
||||||
|
;;
|
||||||
|
deb)
|
||||||
|
if [[ ! -f /etc/apt/sources.list.d/bellsoft.list ]]; then
|
||||||
|
curl -fsSL https://download.bell-sw.com/pki/GPG-KEY-bellsoft \
|
||||||
|
| gpg --dearmor -o /usr/share/keyrings/bellsoft.gpg
|
||||||
|
echo "deb [signed-by=/usr/share/keyrings/bellsoft.gpg] https://apt.bell-sw.com/ stable main" \
|
||||||
|
> /etc/apt/sources.list.d/bellsoft.list
|
||||||
|
apt-get update -y
|
||||||
|
fi
|
||||||
|
${PKG_INSTALL} "bellsoft-java${JDK_VERSION}-full" || \
|
||||||
|
${PKG_INSTALL} "bellsoft-java${JDK_VERSION}" || \
|
||||||
|
log "ВНИМАНИЕ: не удалось установить bellsoft-java${JDK_VERSION}. Альтернатива — скачать tar.gz с https://bell-sw.com/pages/downloads/."
|
||||||
|
;;
|
||||||
|
esac
|
||||||
|
|
||||||
|
# --------------------------------------------------------------------- #
|
||||||
|
# 5. Node.js LTS (для admin-ui и Claude Code CLI)
|
||||||
|
# --------------------------------------------------------------------- #
|
||||||
|
log "Шаг 5/8: установка Node.js ${NODE_VERSION} LTS"
|
||||||
|
need_install_node=1
|
||||||
|
if command -v node >/dev/null 2>&1; then
|
||||||
|
CUR_NODE_MAJOR="$(node --version | sed 's/v//;s/\..*//')"
|
||||||
|
if [[ "${CUR_NODE_MAJOR}" == "${NODE_VERSION}" ]]; then
|
||||||
|
log "Node.js ${NODE_VERSION} уже установлен"
|
||||||
|
need_install_node=0
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
|
||||||
|
if [[ "${need_install_node}" == "1" ]]; then
|
||||||
|
case "${OS_FAMILY}" in
|
||||||
|
rpm)
|
||||||
|
curl -fsSL "https://rpm.nodesource.com/setup_${NODE_VERSION}.x" | bash -
|
||||||
|
${PKG_INSTALL} nodejs
|
||||||
|
;;
|
||||||
|
deb)
|
||||||
|
curl -fsSL "https://deb.nodesource.com/setup_${NODE_VERSION}.x" | bash -
|
||||||
|
${PKG_INSTALL} nodejs
|
||||||
|
;;
|
||||||
|
esac
|
||||||
|
fi
|
||||||
|
|
||||||
|
# --------------------------------------------------------------------- #
|
||||||
|
# 6. Claude Code CLI
|
||||||
|
# --------------------------------------------------------------------- #
|
||||||
|
if [[ "${SKIP_CLAUDE}" != "1" ]]; then
|
||||||
|
log "Шаг 6/8: установка Claude Code CLI"
|
||||||
|
npm install -g @anthropic-ai/claude-code
|
||||||
|
else
|
||||||
|
log "Шаг 6/8: пропуск установки Claude Code CLI (SKIP_CLAUDE=1)"
|
||||||
|
fi
|
||||||
|
|
||||||
|
# --------------------------------------------------------------------- #
|
||||||
|
# 7. Пользователь dev и рабочая директория
|
||||||
|
# --------------------------------------------------------------------- #
|
||||||
|
if [[ "${SKIP_USER}" != "1" ]]; then
|
||||||
|
log "Шаг 7/8: подготовка пользователя ${DEV_USER}"
|
||||||
|
if ! id -u "${DEV_USER}" >/dev/null 2>&1; then
|
||||||
|
useradd -m -s /bin/bash -d "${DEV_HOME}" "${DEV_USER}"
|
||||||
|
log "Создан пользователь ${DEV_USER}"
|
||||||
|
else
|
||||||
|
log "Пользователь ${DEV_USER} уже существует"
|
||||||
|
fi
|
||||||
|
|
||||||
|
mkdir -p "${WORKSPACE_ROOT}"
|
||||||
|
chown "${DEV_USER}:${DEV_USER}" "${WORKSPACE_ROOT}"
|
||||||
|
|
||||||
|
HIST_SNIPPET="${DEV_HOME}/.bashrc.d-history"
|
||||||
|
cat > "${HIST_SNIPPET}" <<'EOF'
|
||||||
|
# История с timestamp и общая для всех сессий — для аудита.
|
||||||
|
export HISTTIMEFORMAT="%F %T "
|
||||||
|
export HISTSIZE=10000
|
||||||
|
export HISTFILESIZE=20000
|
||||||
|
shopt -s histappend
|
||||||
|
PROMPT_COMMAND="history -a; ${PROMPT_COMMAND:-}"
|
||||||
|
EOF
|
||||||
|
chown "${DEV_USER}:${DEV_USER}" "${HIST_SNIPPET}"
|
||||||
|
|
||||||
|
if ! grep -q "bashrc.d-history" "${DEV_HOME}/.bashrc" 2>/dev/null; then
|
||||||
|
echo "[ -f ${HIST_SNIPPET} ] && . ${HIST_SNIPPET}" >> "${DEV_HOME}/.bashrc"
|
||||||
|
fi
|
||||||
|
|
||||||
|
if ! grep -q "/usr/local/go/bin" "${DEV_HOME}/.bashrc" 2>/dev/null; then
|
||||||
|
cat >> "${DEV_HOME}/.bashrc" <<'EOF'
|
||||||
|
[ -f /etc/profile.d/go.sh ] && . /etc/profile.d/go.sh
|
||||||
|
EOF
|
||||||
|
fi
|
||||||
|
else
|
||||||
|
log "Шаг 7/8: пропуск подготовки пользователя (SKIP_USER=1)"
|
||||||
|
fi
|
||||||
|
|
||||||
|
# --------------------------------------------------------------------- #
|
||||||
|
# 8. Финальные проверки
|
||||||
|
# --------------------------------------------------------------------- #
|
||||||
|
log "Шаг 8/8: проверка установленных версий"
|
||||||
|
{
|
||||||
|
printf 'git: '; git --version
|
||||||
|
printf 'make: '; make --version | head -n1
|
||||||
|
printf 'jq: '; jq --version
|
||||||
|
printf 'xmlstarlet: '; xmlstarlet --version | head -n1
|
||||||
|
printf 'podman: '; podman --version 2>/dev/null || echo "(не установлен)"
|
||||||
|
printf 'podman-compose:'; podman-compose --version 2>/dev/null || echo "(не установлен)"
|
||||||
|
printf 'go: '; /usr/local/go/bin/go version
|
||||||
|
printf 'java: '; java -version 2>&1 | head -n1
|
||||||
|
printf 'node: '; node --version 2>/dev/null || echo "(не установлен)"
|
||||||
|
printf 'npm: '; npm --version 2>/dev/null || echo "(не установлен)"
|
||||||
|
if [[ "${SKIP_CLAUDE}" != "1" ]]; then
|
||||||
|
printf 'claude: '; claude --version 2>/dev/null || echo "(не установлен или требует первого запуска)"
|
||||||
|
fi
|
||||||
|
} || true
|
||||||
|
|
||||||
|
cat <<EOF
|
||||||
|
|
||||||
|
──────────────────────────────────────────────────────────────────────
|
||||||
|
Подготовка dev-ВМ завершена.
|
||||||
|
ОС: ${OS_HUMAN}
|
||||||
|
|
||||||
|
Дальше — под пользователем ${DEV_USER}:
|
||||||
|
|
||||||
|
su - ${DEV_USER}
|
||||||
|
cd ${WORKSPACE_ROOT}
|
||||||
|
|
||||||
|
# Положи свой публичный SSH-ключ в ~/.ssh/id_ed25519.pub
|
||||||
|
# и добавь его в git.zetit.ru → Settings → SSH Keys
|
||||||
|
|
||||||
|
git clone ${REPO_URL}
|
||||||
|
cd Bridge-and-Join-s
|
||||||
|
|
||||||
|
make ci # локальный прогон линтера, тестов и сборки
|
||||||
|
make compose-up # PostgreSQL + MinIO для разработки
|
||||||
|
|
||||||
|
# Запуск Claude Code из корня репо:
|
||||||
|
claude
|
||||||
|
|
||||||
|
Дополнительные шаги, которые НЕ автоматизированы (делаются вручную при
|
||||||
|
получении соответствующих артефактов от заказчика):
|
||||||
|
|
||||||
|
1. Установка КриптоПро CSP и КриптоПро JCP под целевую ОС.
|
||||||
|
2. Установка дистрибутива Интеграционного шлюза НРД.
|
||||||
|
3. Импорт тестовых сертификатов GUEST/TEST3 (ГОСТ + RSA).
|
||||||
|
4. Конфигурирование исходящего прокси/whitelist для git.zetit.ru,
|
||||||
|
gost-*.nsd.ru, rsa-*.nsd.ru, registry.npmjs.org, proxy.golang.org,
|
||||||
|
api.anthropic.com.
|
||||||
|
|
||||||
|
ВАЖНО про прод:
|
||||||
|
Эта ВМ годится для разработки и тестирования. Для прод-стенда в
|
||||||
|
финсекторе обязательны РЕД ОС / Astra SE с сертификатом ФСТЭК и
|
||||||
|
лицензированный КриптоПро класса КС1 — Ubuntu/Debian для прода
|
||||||
|
финсектора не подходят.
|
||||||
|
──────────────────────────────────────────────────────────────────────
|
||||||
|
EOF
|
||||||
@@ -0,0 +1,24 @@
|
|||||||
|
# services/crypto-service — Java + КриптоПро JCP
|
||||||
|
|
||||||
|
Изолированный сервис для криптографических операций по ГОСТ:
|
||||||
|
|
||||||
|
- проверка подписи входящих квитанций ЭДО, ответов НРД и сообщений
|
||||||
|
от брокеров;
|
||||||
|
- серверная подпись действий оператора в `admin-ui` (ради соблюдения
|
||||||
|
SLA 2 мин — клиентский КриптоПро на АРМ исключён);
|
||||||
|
- резервный канал отправки в НРД через WS ONYX напрямую (когда ИШ не
|
||||||
|
задействован — упаковка и подпись на нашей стороне);
|
||||||
|
- криптографические проверки целостности эталонов в MinIO.
|
||||||
|
|
||||||
|
Стек: Java 21 (Liberica JDK), Apache Santuario с ГОСТ-патчем, КриптоПро
|
||||||
|
JCP. КриптоПро CSP ставится на ВМ. Класс СКЗИ — **КС1** (программная
|
||||||
|
защита, без HSM).
|
||||||
|
|
||||||
|
Канал общения с Go-ядром — gRPC по Unix Domain Socket (без сетевого хопа,
|
||||||
|
минимальная задержка).
|
||||||
|
|
||||||
|
Архитектурно сохранена `Provider`-абстракция (Валидата JCP / VipNet и
|
||||||
|
прочее) — для тиражирования другим компаниям. На M1 реализован только
|
||||||
|
КриптоПро.
|
||||||
|
|
||||||
|
Реализация — задача M1-M2 (заглушка gRPC) и M3-M4 (полный функционал).
|
||||||
@@ -0,0 +1,18 @@
|
|||||||
|
# web/admin-ui — веб-интерфейс администратора и сотрудника депозитария
|
||||||
|
|
||||||
|
Стек: React + Vite + TypeScript. Реализация — M3.
|
||||||
|
|
||||||
|
Разделы:
|
||||||
|
|
||||||
|
- Журнал входящих и исходящих сообщений (фильтры по GUID / инвестору /
|
||||||
|
статусу / периоду / типу пакета).
|
||||||
|
- Ручное согласование (manual-approval) сделок с подписью оператора
|
||||||
|
серверной ЭП через `crypto-service`.
|
||||||
|
- Раздел «Сертификаты» — обновление сертификатов для подписи (закрытые
|
||||||
|
ключи через UI не выгружаются), сроки, алерты, аудит.
|
||||||
|
- Раздел «Уведомления» — включение и настройка провайдеров плагинов.
|
||||||
|
- SLA-дашборд по этапам.
|
||||||
|
- Переключатель канала отправки (ИШ / ONYX / ФШ) для тестов.
|
||||||
|
|
||||||
|
Роли: Администратор, Администратор СКЗИ, Сотрудник депозитария,
|
||||||
|
Оператор, Аудитор.
|
||||||
Reference in New Issue
Block a user