arm-ka-docs/dev/README.md
2026-10-04 05:27:21 +04:00

170 lines
13 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

# Окружение разработки АРМ КА (`docs/dev/`)
Локальная инфраструктура workspace одной командой: PostgreSQL 16, NATS 2.10 без JetStream и MinIO с бакетом `arm-ka`.
**Статус (фаза 1):** в compose сейчас только инфраструктура (`postgres`, `nats`, `minio`, `minio-init`). Профиль
`services` (контейнеры `arm-core`, `tabular-parser`, `scan-gateway`, `scan-emulator`) **планируется** — добавляется позже
(задача 5.3), здесь не описан. До этого сервисы запускаются из venv против этой инфраструктуры (см. ниже).
## Предварительные требования
- Docker и compose v2 (проверено на docker 28 / compose 2.34).
- `uv` и Python 3.11 — для запуска сервисов из venv (версия Python — как на платформе).
- Свободные порты хоста (по умолчанию доступны только с `127.0.0.1`, см. `BIND_ADDR`): 5432 (PostgreSQL), 4222 и 8222 (NATS и его мониторинг), 9000 и 9001 (MinIO API и консоль).
Занятые порты меняются в `.env` (см. «Типичные проблемы»).
## Запуск инфраструктуры
Команды — из каталога `docs/dev/`:
```bash
cp .env.example .env # .env в git не попадает
docker compose up -d # вернётся сразу; healthy — примерно через 6 с
```
Ожидание готовности (для скриптов и `Makefile`):
```bash
docker compose up -d && docker compose up -d --wait postgres nats minio
```
Голый `docker compose up -d --wait` **возвращает код 1**: одноразовый `minio-init` (создаёт бакет и завершается с
кодом 0) compose 2.34 считает сбоем (`container arm-ka-minio-init-1 exited (0)`). Поэтому `--wait` нужно давать со
списком долгоживущих сервисов — как выше.
Проверка:
```bash
docker compose ps # postgres, nats, minio — Up (healthy); minio-init — Exited (0)
docker compose exec postgres sh -c 'psql -U "$POSTGRES_USER" -d "$POSTGRES_DB" -c "select version()"'
curl -s localhost:8222/healthz # {"status":"ok"}
curl -s localhost:8222/varz | grep -A1 jetstream # "jetstream": {} — JetStream не включён
docker compose run --rm --entrypoint sh minio-init -c 'mc alias set local http://minio:9000 "$MINIO_ROOT_USER" "$MINIO_ROOT_PASSWORD" >/dev/null && mc ls local'
# [...] 0B arm-ka/
```
Консоль MinIO — <http://localhost:9001> (по умолчанию `minioadmin` / `minioadmin`); S3 API — `localhost:9000`.
Схема БД (`dkb`) создаётся миграциями `arm-core`, не compose.
## Переменные `.env`
Файл читают `docker compose` (из этого каталога) и, вторым блоком, сервисы при запуске из venv. Значения по умолчанию —
только для dev.
Блок compose:
| Переменная | По умолчанию | Для чего |
|---|---|---|
| `BIND_ADDR` | `127.0.0.1` | адрес привязки всех портов хоста; `0.0.0.0` — доступ с других машин (небезопасно, см. «Примечания») |
| `POSTGRES_DB` | `armka` | имя БД |
| `POSTGRES_USER` | `armka` | пользователь БД |
| `POSTGRES_PASSWORD` | `armka` | пароль БД |
| `POSTGRES_PORT` | `5432` | порт PostgreSQL на хосте |
| `NATS_PORT` | `4222` | клиентский порт NATS на хосте |
| `NATS_MONITOR_PORT` | `8222` | порт мониторинга NATS (`/varz`, `/healthz`) |
| `MINIO_ROOT_USER` | `minioadmin` | администратор MinIO |
| `MINIO_ROOT_PASSWORD` | `minioadmin` | пароль администратора MinIO |
| `MINIO_API_PORT` | `9000` | порт S3 API на хосте |
| `MINIO_CONSOLE_PORT` | `9001` | порт консоли MinIO на хосте |
| `MINIO_BUCKET` | `arm-ka` | единственный бакет, создаётся `minio-init` |
Блок сервисов (запуск из venv против compose по `localhost`, формат шаблона команды):
| Переменная | По умолчанию | Для чего |
|---|---|---|
| `DEBUG` | `true` | dev-режим: пакеты `raisa_*` импортируются условно |
| `OPENBAO__DATABASE__DATABASE_URL` | `postgresql+asyncpg://armka:armka@localhost:5432/armka` | подключение к PostgreSQL (asyncpg) |
| `OPENBAO__MINIO__MINIO_URL` | `localhost:9000` | адрес MinIO без схемы (`host:port`, так ждёт `miniopy-async`) |
| `OPENBAO__MINIO__MINIO_ADMIN_LOGIN` | `minioadmin` | логин MinIO |
| `OPENBAO__MINIO__MINIO_ADMIN_PASSWORD` | `minioadmin` | пароль MinIO |
| `OPENBAO__MINIO__MINIO_BUCKET` | `arm-ka` | бакет |
| `OPENBAO__NATS__NATS_URL` | `nats://localhost:4222` | адрес NATS |
| `OPENBAO__NATS__NATS_SEED` | пусто | nkey seed; пусто — подключение без nkeys |
| `OPENBAO__NATS__NATS_JWT` | пусто | JWT NATS; пусто — подключение без nkeys |
| `OPENBAO__SMB__SMB_HOST` | `localhost` | заглушка SMB (в Срезе 0 не используется); блок обязателен для `Settings` arm-core |
| `OPENBAO__SMB__SMB_PATH` | `share` | заглушка SMB |
| `OPENBAO__SMB__SMB_LOGIN` | `user` | заглушка SMB |
| `OPENBAO__SMB__SMB_PASSWORD` | `password` | заглушка SMB |
| `NATS_ENABLED` | `true` | включает подключение arm-core к NATS; без него `/healthcheck` показывает `nats=off` |
Два блока описывают одни и те же ресурсы: **при смене порта, пароля, пользователя или бакета меняйте обе части.**
## Сброс окружения
```bash
docker compose down # останавливает контейнеры; тома postgres-data и minio-data сохраняются
docker compose down -v # полный сброс: удаляет тома postgres-data и minio-data (БД и бакет — с нуля)
```
Имя проекта compose фиксировано (`name: arm-ka`), поэтому тома общие для любого worktree (`.wt/<срез>/docs/dev`):
сброс из одного worktree затрагивает все.
## Запуск сервисов из venv без Nexus (черновик)
> Черновик: будет дописан и проверен вручную в задаче 5.4 (сквозная проверка). `make venv` и `make test-integration`
> в `tabular-parser` и `scan-gateway` будут доступны после задач этих сервисов; сейчас они есть в `arm-core`.
Пакеты `raisa_*` из Nexus банка вне банка недоступны (D-10). Поэтому `make venv` ставит `requirements.txt` без строк
`raisa_*` (фильтр `grep -v '^raisa_'`), код импортирует `raisa_*` условно (при `DEBUG=true`), а npm-пакеты `raisa-*`
в `web/package.json` вынесены в `optionalDependencies`.
Шаги для сервиса (пути — относительно каталога его репозитория; в workspace `docs/` лежит рядом, `../docs/dev/`):
```bash
# 1. поднять инфраструктуру (из docs/dev/, см. выше)
# 2. из корня репозитория сервиса:
cp ../docs/dev/.env.example api/.env
make venv # api/.venv: Python 3.11 + зависимости без raisa_*
cd api && .venv/bin/python run_server.py # сервис подключается к PostgreSQL/NATS/MinIO по localhost
# 3. в другом терминале:
curl -s localhost:<порт сервиса>/healthcheck
```
Порт сервиса задаётся его настройками; в профиле `services` по spec это 8000 (`arm-core`), 8001 (`tabular-parser`),
8002 (`scan-gateway`). Для `arm-core` в ответе `/healthcheck` ожидаются `version` и `nats = ok` — при `NATS_ENABLED=true`
(задан в `.env.example`; без него `nats = off`). Для `tabular-parser` и `scan-gateway` ожидаемые поля и переменные
зависят от их настроек — будет уточнено в задачах 5.x.
## Интеграционные тесты сервисов против compose (черновик)
> Черновик: уточняется после задач 3.x и 5.x.
Общий набор целей (`up`, `test`, `test-integration`, `lint`, `check`, `check-full`) есть во всех сервисных репозиториях
(`arm-core`, `tabular-parser`, `scan-gateway`); семантика, состав `check-full`, порядок перед PR и пропуск тестов без
`docs`/`fixtures` описаны в [`checks.md`](checks.md); эталон рецептов общих целей — [`Makefile.common`](Makefile.common). Кратко: `make check` — быстрые проверки без Docker, `make check-full` —
`check` + интеграционные тесты против этого compose + образ (для `arm-core` ещё сверка с DBML, миграции и `web`);
выполняется перед созданием PR.
Интеграционные тесты **требуют поднятой инфраструктуры**: сначала `docker compose up -d && docker compose up -d --wait
postgres nats minio`, затем `make test-integration` (или `make check-full`) в репозитории сервиса. Для `scan-gateway`
эмулятор ИС Сканирование поднимается в процессе интеграционного теста (отдельный контейнер появится вместе с профилем
`services`). Общее описание проверок — [`checks.md`](checks.md).
## Проверка контракта
Из корня репозитория `docs`: `python scripts/validate_contracts.py` — валидирует примеры в
[`contracts/examples/`](../contracts/examples/) тремя схемами из [`contracts/`](../contracts/) (3 схемы, 8 примеров;
нужен `jsonschema`). Или `make venv && make check` (ещё `openspec validate`), см. [`checks.md`](checks.md).
## Примечания
- **Образы MinIO неофициальные.** Официальные `minio/minio` и `minio/mc` недоступны (Docker Hub — denied, на quay.io нет
нужных тегов), поэтому в compose стоят `alpine/minio:RELEASE.2025-10-15T17-29-55Z` и
`bitnamilegacy/minio-client:2025.7.21`, а сервис `minio` запущен с `user: "0:0"` (иначе образ не пишет в свежий том) —
только для dev. Решения R-5/R-6: [`design.md`](../openspec/changes/slice-0-skeleton/design.md), раздел
«Decisions made without discussion», решения №16–17. Замена на официальные образы — две строки `image:` в
`docker-compose.yml` (и удаление `user: "0:0"`).
- **Безопасность.** По умолчанию порты публикуются только на `127.0.0.1` (`BIND_ADDR`), снаружи машины они недоступны.
Чтобы открыть их для других машин, задайте в `.env` `BIND_ADDR=0.0.0.0` — но пароли по умолчанию (`armka`,
`minioadmin`) годятся только для dev, поэтому сначала смените их (в обоих блоках `.env`) и не делайте этого в
недоверенной сети.
## Типичные проблемы
- **Порт занят** (`address already in use`): измените `*_PORT` в `.env` и одновременно соответствующий порт в
`OPENBAO__*` (`DATABASE_URL`, `MINIO_URL`, `NATS_URL`); перезапустите `docker compose up -d`.
- **`minio-init` завис или завершился с ошибкой:** `docker compose logs minio-init`; чаще всего `minio` не стал healthy —
`docker compose logs minio`. Повторный `docker compose up -d` идемпотентен.
- **Остаточные тома от прошлых запусков** (старый пароль БД, бакет не тот): `docker compose down -v` и запуск заново.
- **`up -d --wait` возвращает код 1:** см. раздел «Запуск инфраструктуры» — указывайте сервисы явно.