Срез 0 (issue #1): раздел «Соглашения шаблона» (что оставлено от шаблона команды, что вырезается, что добавляется); change openspec/changes/slice-0-skeleton — proposal, design с таблицей «Decisions made without discussion», спеки и tasks; в openspec/config.yaml строки с двоеточием взяты в кавычки (YAML разбирал их как словари). Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
41 lines
4.2 KiB
Markdown
41 lines
4.2 KiB
Markdown
# 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`.
|