# CLAUDE.md — scan-gateway Общий контекст системы — `../CLAUDE.md` и `../docs/`. Этот файл — только про этот сервис. ## Что это Адаптер внешней ИС Сканирование (Content AI) для PDF/PNG/JPG: переименовать файл `UUID_имя`, положить в «Входящие», забрать `Исходящие/UUID/UUID.json`, сохранить сырой ответ в S3 `raw/{job_id}.json` (в БД не регистрируется), нормализовать в `../docs/contracts/recognition-result.schema.json` (`statementDocument`), опубликовать `recognition.result`. Таймаут 5 мин → `timeout`. **Нет доступа к БД.** ## Правила - Нормализация по фактическим ответам `../fixtures/ocr/aep_*.json`, а не по ТЗ (OQ-13, OQ-14): confidence → 0–100, поля организации/даты — по тому, что реально приходит. - Один PDF может содержать ББ и ОФР → два документа в результате. - Dev-режим: эмулятор ИС Сканирование, возвращающий `aep_N.json` по имени файла (`SCAN_EMULATOR=1`). ## Соглашения шаблона Тот же шаблон команды, что у `arm-core` («Шаблон FastAPI», `RSHB/DKB_ARMKA@ba172f8`); общие соглашения — `../docs/context/03-architecture.md`, «Соглашения шаблона команды». Сейчас репозиторий — полная копия каркаса `arm-core`; change `slice-0-skeleton` приводит его к сервису **без фронта и без БД**, но с SMB. Все команды — из `api/`. **Оставлено от шаблона:** `api/run_server.py` (точка входа платформы, `SERVER__HOST/PORT`), `api/src/app.py` (lifespan с регистрацией SMB-сессии, `GET /healthcheck`, gzip/proxy middleware, обработчики ошибок), `core/config.py` (pydantic-settings, `OPENBAO__MINIO__*`, `OPENBAO__NATS__*`, `OPENBAO__SMB__*`, `DEBUG`), `core/clients.py` (S3), `core/nats_callback.py`, `core/logger.py`, `core/exception_handlers.py`, `common/exceptions.py`, `pytest.ini`, `requirements*.txt` (включая `smbprotocol`), `raisa_config.yml`, `setup/setup.sh` + `pip.conf` (без npm-шага). **Вырезано (Срез 0):** `web/` целиком и `setup/.npmrc`; из `app.py` — mount SPA (`SPAStaticFiles`, `os.makedirs("web")`), CORS, импорт `raisa_fastapi_protected_api`; `db/`, `models/`, `repositories/`, `alembic/`, `alembic.ini`; из настроек — `OPENBAO.DATABASE`; из `requirements.txt` — `asyncpg`, `SQLAlchemy`, `alembic`, `argon2-cffi`, `raisa_fastapi_protected_api`; шаблонный `README.md` заменён описанием сервиса. **Добавлено:** `api/src/gateway/` (горячие папки: положить `UUID_имя.pdf` во «Входящие», опрашивать «Исходящие/UUID/UUID.json»; режим `local` — обычный каталог для dev, `smb` — как в шаблоне через `smbclient`; референс поллинга — `../reference-old-arm/api/src/core/PDFWorker`), `api/src/normalizer/` (ответ Content AI → `statementDocument`; Срез 3), `api/src/contract/` (pydantic-модели `recognition-result` v1.0; идентичность с `../docs/contracts` проверяется в CI), `api/src/core/worker.py` (durable-подписка `recognition.image.request` → S3 → горячая папка → ожидание ≤ `reply_deadline` → S3 `raw/` и `results/` → `recognition.result`), `api/src/scan_emulator/` (эмулятор ИС Сканирование для compose: следит за «Входящими», кладёт `../fixtures/ocr/aep_N.json` по имени файла в «Исходящие»; запускается тем же образом, `SCAN_EMULATOR=1`), `Dockerfile`, `api/pyproject.toml` (ruff, mypy). Проверки: `pytest`, `ruff check . && ruff format --check .`, `mypy src`.