Решения владельца 06.10.2026: в контур едут arm-core, tabular-parser, scan-gateway снимками без истории; docs и fixtures не переносятся (разработка снаружи); вырезаются .claude/, CLAUDE.md, docs/superpowers/, Dockerfile; openspec остаётся. Скрипт scripts/prepare-contour-snapshot.sh: git archive, вырезание, Makefile без uv и docker-build (venv через python -m venv + pip с Nexus), замена ссылок на внешний Gitea, SNAPSHOT.md, проверки. Снимки трёх сервисов проходят make check без docs/fixtures (1084/1087/726 passed, пропуски только fixtures/contract). Closes #34 Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com> Claude-Session: cedd7915-2efe-41e5-988c-a9117033598b
17 KiB
Перенос сервисов АРМ КА в контур банка: гайд для разработчика
Разработка ведётся снаружи (workspace awp-ca, Gitea проекта). В контур банка (Gitea платформы РАИСА и её CI/CD)
уезжают только три сервисных репозитория — arm-core, tabular-parser, scan-gateway — снимками дерева, без
истории. Репозитории docs и fixtures в контур не переносятся: решение владельца 06.10.2026. Этот документ — что
именно уезжает, чего в платформе нет, как подготовить снимок скриптом и как его положить в контур.
Соглашения платформы, от которых всё отталкивается, — context/03-architecture.md, разделы «Соглашения шаблона команды»
и «Что ожидаем от платформы». Проверки качества — dev/checks.md.
1. Что переносится и что нет
| Что | В контур | Почему |
|---|---|---|
api/ (код, тесты, contracts/, rules/, alembic/, scripts/), web/ (arm-core), README.md, Makefile, setup/, raisa_config.yml, api/.env.example, api/.env.test |
да | это и есть сервис по шаблону платформы |
openspec/specs/, openspec/changes/archive/, openspec/config.yaml |
да | спецификация системы и журнал решений (design.md); без них код в контуре нечем объяснять |
.claude/, CLAUDE.md |
нет | инструкции и skills AI-агента, инструментарий внешней разработки |
docs/superpowers/ (планы, ledger) |
нет | рабочие артефакты процесса, содержат локальные пути разработчика |
Dockerfile, .dockerignore |
нет | образ для локального make check-full; в контуре образ собирает платформа своим CI (шаблон держит Dockerfile в .gitignore) |
| История коммитов | нет | снимок одним коммитом; в истории снаружи — трейлеры Co-Authored-By: Claude …, Claude-Session, ссылки на внешний Gitea |
Репозиторий docs |
нет | контекст, модель, контракты, экспорт ТЗ — остаются снаружи; копия контракта лежит в api/contracts/ каждого сервиса |
Репозиторий fixtures |
нет | реальная отчётность для регрессии парсера; тесты с маркером fixtures в контуре пропускаются |
reference-old-arm |
нет | старый репозиторий банка, читался только для справки |
Снимок получает файл SNAPSHOT.md с хешем коммита-источника и датой: по нему потом сверяется, что уже перенесено.
2. Чего в платформе нет и что есть
Нет в контуре (всё это скрипт вырезает или заменяет):
uv—make venvснаружи ставит окружение черезuv venv --python 3.11иuv pip. В снимке цельvenvпереписана наpython3.11 -m venv+pipсsetup/pip.conf(Nexus), как делаетsetup/setup.shшаблона.- Docker и
docker compose— локальная инфраструктура (docs/dev/docker-compose.yml) живёт вdocs, которого в контуре нет. Целиmake up,test-integration,check-fullв контуре не запускаются;docker-buildудалена изMakefile. docsиfixturesрядом с сервисом — тесты идентичности контракта и тесты на реальных данных пропускаются (раздел 5), сверка ORM с DBML (make dbml-checkв arm-core) не выполняется.tea,codegraph,openspec(CLI), хуки.claude/hooks— инструментарий процесса; в снимке только их следы вopenspec/config.yaml(контекст для агента, безвреден).- Внешний Gitea
git.aepif.ru— ссылки видаhttps://git.aepif.ru/RSHB/arm-core/pulls/19в архивах change'ей скрипт превращает вRSHB/arm-core#19(номера относятся к внешнему Gitea, в контуре их нет).
Есть только в контуре (снаружи заменено заглушками, в снимке остаётся как есть):
- Nexus
nexus.dev.raisa.go.rshbank.ru(setup/pip.conf,setup/.npmrc) и пакетыraisa_fastapi_protected_api(api/requirements.txtarm-core),raisa-fastapi-protected-web,raisa-ui(web/package.json,optionalDependencies). Снаружиmake venvих пропускает (grep -v '^raisa_'), импортraisa_fastapi_protected_apiусловный — только приDEBUG=false. В контуре всё ставится штатно. - Запуск платформой:
api/run_server.py,SERVER__HOST/SERVER__PORT, ресурсыraisa_config.yml, секретыOPENBAO__*из OpenBao, Python 3.11 в базовом образе. - PostgreSQL 16 (схема
dkb), NATS без JetStream (nkeys/JWT), S3-совместимое хранилище, JWT РАИСА для входа.
3. Подготовка снимка: scripts/prepare-contour-snapshot.sh
Запуск из workspace, по одному репозиторию:
docs/scripts/prepare-contour-snapshot.sh arm-core /tmp/contour
docs/scripts/prepare-contour-snapshot.sh tabular-parser /tmp/contour
docs/scripts/prepare-contour-snapshot.sh scan-gateway /tmp/contour
# третий аргумент — ref; по умолчанию origin/main (снимок всегда с сервера, не из рабочего дерева)
Что делает скрипт (репозиторий-источник не меняется):
git archive <ref>→/tmp/contour/<repo>/— дерево коммита без.gitи без игнорируемых файлов.- Удаляет
.claude/,CLAUDE.md,docs/superpowers/,Dockerfile,.dockerignore. - Правит
Makefile: цельvenv→python3.11 -m venv+pip install -r requirements-dev.txtсsetup/pip.conf(переменнаяPYTHON, по умолчаниюpython3.11); удаляет цельdocker-buildи её упоминания вcheck-full,.PHONY,help. - Заменяет ссылки на внешний Gitea на
RSHB/<repo>#<n>. - Пишет
SNAPSHOT.md(источник, хеш, дата, что вырезано). - Проверяет: нет
.claude/CLAUDE.md/планов/Dockerfile, нет локальных путей (/Users/…,/home/…), нетuvиgit.aepif.ru, на месте платформенные файлы (raisa_config.yml,setup/,run_server.py,requirements.txt,.env.test,contracts/). Любая проблема — код возврата 1 и список.
Проверено 06.10.2026: снимки arm-core@1d7f2c8, tabular-parser@3b32462, scan-gateway@dffc18a проходят make check без
docs и fixtures (1084 / 1087 / 726 passed, пропуски только по причинам из раздела 5).
4. Как положить снимок в контур
Репозитории контура — по одному на сервис, имена как снаружи. Первый перенос и каждый следующий делаются одинаково:
git clone <url контура>/arm-core contour-arm-core
cd contour-arm-core && git switch -c sync/arm-core-1d7f2c8 # ветка по правилам контура
rsync -a --delete --exclude .git /tmp/contour/arm-core/ ./ # дерево = снимок, удалённые снаружи файлы исчезают
git status --short # прочитать diff: он должен совпадать с изменениями снаружи
git add -A
git commit -m "sync: arm-core@1d7f2c8 (2026-10-06)" # хеш и дата — из SNAPSHOT.md
git push -u origin sync/arm-core-1d7f2c8 # дальше PR/мерж по регламенту контура
--delete обязателен: иначе файлы, удалённые или переименованные снаружи, останутся в контуре. Если в контуре делали
локальные правки (раздел 7), сначала вернуть их наружу, иначе rsync --delete их перезапишет.
Порядок сервисов при одной синхронизации: arm-core → tabular-parser → scan-gateway (ядро — потребитель контракта,
его копия схемы должна быть не старше копий сервисов). Если снаружи поднималась версия контракта (api/contracts/*.json,
CONTRACT_VERSION в api/src/contract/common.py), переносить все три сервиса одним заходом.
5. Проверка в контуре перед PR
make venv # python3.11 -m venv + pip через Nexus (вместо setup/setup.sh; тот ставит только прод-зависимости)
make check # ruff, mypy, pytest без интеграционных тестов
Ожидаемые пропуски (pytest -rs покажет причины), это не ошибки:
| Сервис | Пропускается | Причина |
|---|---|---|
| все | тест идентичности api/contracts/ с docs/contracts/ |
docs нет; идентичность проверена снаружи перед снимком |
| все | тесты с маркером fixtures (golden-снимки, property-тесты на реальных ОСВ/формах, покрытие словарей) |
fixtures нет; регрессия на реальных данных — снаружи |
| arm-core | сверка ORM с DBML в тестах | DBML в docs |
| scan-gateway | тесты с реальными ответами ИС Сканирование (fixtures/ocr) |
то же |
Не запускать в контуре: make up, make test-integration, make check-full, make dbml-check, make e2e — им нужны
compose из docs либо Docker. Интеграционные тесты против PostgreSQL/NATS/MinIO прогоняются снаружи перед каждым снимком;
пайплайну платформы отдаётся make check.
Фронт arm-core: make web-check (npm install через .npmrc Nexus, biome, tsc, npm run build). В контуре
raisa-fastapi-protected-web и raisa-ui ставятся штатно, снаружи они в optionalDependencies и пропускаются.
web/package-lock.json снаружи не коммитится (OQ-63) — в контуре lock-файл появится при первом npm install, решение о его
коммите за контуром.
6. Что нужно от платформы для запуска
Переменные окружения — api/.env.example каждого сервиса (имена и смысл), секреты под префиксом OPENBAO__*.
Минимум для arm-core:
OPENBAO__DATABASE__DATABASE_URL(asyncpg, схемаdkb),OPENBAO__MINIO__{MINIO_URL, MINIO_ADMIN_LOGIN, MINIO_ADMIN_PASSWORD, MINIO_BUCKET}(MINIO_SECURE=trueпо умолчанию),OPENBAO__NATS__{NATS_URL, NATS_SEED, NATS_JWT}.DEBUG=false(включает middleware РАИСА, выключает/docsи dev-токены),CORS_ORIGINS(явный список; пусто — кросс-доменные запросы запрещены),FORWARDED_ALLOW_IPS(адреса прокси платформы, иначе IP в аудите — адрес прокси),AUTH_JWKS_URLилиAUTH_PUBLIC_KEY+AUTH_ISSUER,AUTH_AUDIENCE,AUTH_EMAIL_CLAIM— параметры JWT РАИСА (открытый вопрос OQ вcontext/07-open-questions.md).AUTH_DEV_ISSUER/AUTH_DEV_SECRETв проде не задавать.- Миграции и seed при деплое: из
api/—alembic upgrade head, затемpython -m scripts.seed(справочники: план счетов, правила элиминации, роли и права;--devтолько для стенда разработки). Те же команды — целиmake migrateиmake seed(README.mdarm-core, «Быстрый старт», шаг 4 «Миграции и справочники»).
tabular-parser и scan-gateway: только OPENBAO__MINIO__*, OPENBAO__NATS__*, DEBUG, NATS_ENABLED=true; у парсера
PARSE_MAX_BYTES, PARSE_TIMEOUT_SECONDS; у шлюза SCAN_HOTFOLDER_MODE=smb и OPENBAO__SMB__{SMB_HOST, SMB_PATH, SMB_LOGIN, SMB_PASSWORD} (режим local и эмулятор make emulator — только для разработки). Subjects NATS, схема ключей S3
и ресурсы — context/03-architecture.md.
7. Правки внутри контура и обратный поток
Правило: источник истины — репозитории снаружи. Любая правка в контуре (чаще всего под пайплайн платформы: пути, переменные,
raisa_config.yml) возвращается наружу до следующей синхронизации:
cd contour-arm-core
git diff <коммит sync> HEAD -- . ':!SNAPSHOT.md' > /tmp/contour-arm-core.patch # база — коммит последнего sync
Патч применяется снаружи в ветку и проходит обычный PR; после его мержа следующий снимок уже содержит правку, и
rsync --delete ничего не потеряет. Если правка касается только контура (например, секретов платформы), её место — вне
репозитория: переменные окружения OpenBao, а не код.
8. Чек-лист одной синхронизации
- Снаружи: нужные PR слиты в
mainтрёх сервисов;make check-fullзелёный в каждом; контракт вdocs/contractsи копииapi/contractsидентичны. - Правки из контура (раздел 7) возвращены наружу и слиты.
prepare-contour-snapshot.shпо каждому сервису; скрипт завершился словами «снимок готов».- В контуре: клон, ветка,
rsync --delete, просмотрgit status, коммитsync: <repo>@<hash> (<дата>),make venv,make check(пропуски — только из раздела 5), для arm-coremake web-check, PR по регламенту контура. - Порядок мержа при смене версии контракта: arm-core → tabular-parser → scan-gateway.
- Снаружи в
context/09-delivery-plan.mdили в issue синхронизации отметить, какие хеши перенесены.
9. Известные неточности снимка
README.mdсервисов описываютmake venvчерезuvи ссылаются на../docs,../fixtures,docs/dev/qa-guide.md; скрипт их не переписывает. Ориентир для контура — этот документ иSNAPSHOT.md.- В
openspec/changes/archive/*/остаются относительные пути вида../docs/openspec/...и../fixtures/...: это ссылки на внешний workspace, в контуре они никуда не ведут. openspec/config.yamlсодержит контекст для AI-агента (упоминает../docs, фикстуры, стек); на сборку не влияет.- Тесты, которые снаружи пропускаются без
fixtures, в контуре не выполняются никогда. Поэтому перед каждым снимком снаружи обязателенmake check-fullс доступнымиdocsиfixtures(dev/checks.md, раздел «Порядок перед PR»).