arm-scan-gateway/CLAUDE.md
Andrey Epifancev b127c02422 Срез 0 [7.5]: финальная волна, документы — T5.1, T5.3, T6.1, T6.3, T6.6, M-3
- README: верхняя граница задержки settle, шаг 5 «Полного круга»; критерии ошибочного файла (корень не объект)
- CLAUDE.md: по одному json на каждый распознанный документ; критерии ошибочного файла
- design.md: D-5 — оговорка про нестроковый error.code отдельным предложением; №79 — источник указания, SQL уборки в порядке FK
- open-questions-proposal.md п.20: замены ../docs/dev/README.md (185–187, 224–226, 252–253) и комментарий docker-compose.yml:184
- план: Task 6 — пометка про замену down -v (R-27)

Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
2026-10-04 16:01:13 +04:00

65 lines
7.4 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.

# CLAUDE.md — scan-gateway
Общий контекст системы — `../CLAUDE.md` и `../docs/`. Этот файл — только про этот сервис.
## Что это
Адаптер внешней ИС Сканирование (Content AI) для PDF/PNG/JPG: переименовать файл `UUID_имя`, положить в «Входящие»
(через `SCAN_TMP_DIR`, по умолчанию `Tmp`: `.part` пишется туда, на той же ФС/шаре, и переименовывается), забрать **все**
`Исходящие/UUID/*.json` (ИС кладёт по одному json на каждый распознанный документ), склеить и сохранить сырой ответ в S3
`raw/{job_id}.json` (в БД не регистрируется),
нормализовать в `../docs/contracts/recognition-result.schema.json` (`statementDocument`), опубликовать
`recognition.result`. Таймаут → ошибка `TIMEOUT` по `min(reply_deadline, старт + SCAN_TIMEOUT_SECONDS=300)`, старт —
запись файла во «Входящие». **Нет доступа к БД.**
## Правила
- Нормализация по фактическим ответам `../fixtures/ocr/aep_*.json`, а не по ТЗ (OQ-13, OQ-14): confidence → 0–100,
поля организации/даты — по тому, что реально приходит.
- Набор ответа готов по settle: есть `*.json`, а имена и размеры не менялись `SCAN_SETTLE_SECONDS` (по умолчанию 2;
отсчёт от первого опроса, увидевшего окончательный набор). Не ждать «один файл `<UUID>.json`».
- Склеенный `raw/{job_id}.json`: `{"job_id", "files": [{"name", "response", "parse_error"}, ...]}`, все `*.json`
каталога по возрастанию имени; нормализатор получает ровно эту структуру.
- Успех файла ответа — `error.code == ""` (`error` при этом не `null`!), ошибка — непустой `error.code`,
`parse_error` или корень ответа не объект (`INVALID_FORMAT`). Проверка `error is None` для реального ответа неверна. Ошибочные файлы — в `metrics.warnings`
(`<имя>: <код>: <сообщение>`); все файлы ошибочны → код первого, есть успешный → `NOT_IMPLEMENTED` (Срез 0).
- В одном json может быть несколько таблиц разных форм (баланс, ОФР); тип документа задаёт `label` таблицы. Таблицы не
интерпретируются в Срезе 0 — разбор в Срезе 3.
- Dev-режим: эмулятор ИС Сканирование: по входящему `<uuid>_<name>.<ext>` кладёт в `Output/<uuid>/` набор фикстур
`<name>.json` + `<name>_*.json` как `<uuid>.json` / `<uuid>_<суффикс>.json` (атомарно, через `Tmp`): `make emulator`
(то же, что `python -m src.scan_emulator` из `api/`); в контейнере — тот же образ с `command: python -m src.scan_emulator`.
- Описание сервиса, протокол горячих папок, env, запуск и коды ошибок — `README.md`; требования и решения Среза 0 —
`openspec/changes/slice-0-skeleton/` (`design.md`).
## Соглашения шаблона
Тот же шаблон команды, что у `arm-core` («Шаблон FastAPI», `RSHB/DKB_ARMKA@ba172f8`); общие соглашения —
`../docs/context/03-architecture.md`, «Соглашения шаблона команды». Репозиторий приведён к сервису **без фронта и без
БД**, но с SMB. Команды `make` — из корня репозитория (рецепты сами заходят в `api/`), `pytest` — из `api/`.
**Оставлено от шаблона:** `api/run_server.py` (точка входа платформы, `SERVER__HOST/PORT`), `api/src/app.py` (lifespan:
SMB-сессия, S3, NATS, воркер; `GET /healthcheck`; gzip/proxy middleware), `core/config.py` (pydantic-settings,
`OPENBAO__MINIO__*`, `OPENBAO__NATS__*`, `OPENBAO__SMB__*`, `DEBUG`), `core/exception_handlers.py` (подключается в
`create_app`), `api/pytest.ini`, `api/requirements*.txt` (включая `smbprotocol`), `raisa_config.yml`,
`setup/setup.sh` + `setup/pip.conf` (без npm-шага). Заглушки шаблона без кода сервиса: `src/api/` (пустой `router`,
пустые `dependencies/` и `endpoints/`), `src/schemas/` и `src/services/` (пустые пакеты), `common/exceptions.py`
(`NotFoundError`, `CouldntCreateError` нигде не используются), `core/logger.py` (`setup_logger` нигде не вызывается).
**Вырезано (Срез 0):** `web/`, `setup/.npmrc`; из `app.py` — mount SPA, CORS, `raisa_fastapi_protected_api`; `db/`,
`models/`, `repositories/`, `alembic/`; `OPENBAO.DATABASE`; из `requirements.txt` — `asyncpg`, `SQLAlchemy`, `alembic`,
`raisa_fastapi_protected_api`; шаблонные `core/nats_callback.py` и `README.md` заменены своими.
**Добавлено:**
- `api/src/gateway/` — горячие папки: протокол `HotFolder` (`hotfolder.py`: `LocalHotFolder`, `SettleTracker`, `inbox_name`),
`smb.py` (`SmbHotFolder`, импортируется лениво), фабрика `create_hotfolder`; `merge.py` — склейка файлов ответа в `raw/`; референс поллинга — `../reference-old-arm/api/src/core/PDFWorker`.
- `api/src/core/` — `worker.py` (задание: проверка → ack → S3 → горячая папка → опрос → `raw/` → нормализатор →
результат; ошибки по таблице D-7), `nats.py` (core NATS без JetStream, queue group `scan-gateway`, публикация с
повторами), `clients.py` (`S3Storage`), `health.py` (`nats`/`hotfolder` в `/healthcheck`).
- `api/src/normalizer/` — `Normalizer`, `NullNormalizer` (Срез 0: разбор по файлам склейки — все ошибочны → код
первого, есть успешный → `NOT_IMPLEMENTED`, ошибочные файлы → `metrics.warnings`); настоящая нормализация — Срез 3.
- `api/src/contract/` + `api/contracts/` — pydantic-модели и байт-в-байт копии схем `../docs/contracts`; идентичность
проверяет `api/tests/unit/test_contract.py` (входит в `make check`).
- `api/src/scan_emulator/` — эмулятор ИС Сканирование (`SCAN_FIXTURES_DIR`, `SCAN_EMULATOR_DELAY`,
`SCAN_EMULATOR_POLL_SECONDS`); в compose контейнера пока нет — `make emulator`.
- `Makefile` (`venv`, `lint`, `test`, `test-integration`, `check`, `docker-build`, `check-full`, `up`,
`emulator`), `api/pyproject.toml` (ruff, mypy), `Dockerfile` + `.dockerignore` (один образ: шлюз и эмулятор),
`api/.env.example`, `api/.env.test`.
- Тесты: `api/tests/unit/`, `api/tests/integration/` (маркеры `integration`, `fixtures`); перед PR — `make check-full`.