# Spec Delta: scan-emulator ## Purpose Эмулятор ИС Сканирование для разработки и тестов: воспроизводит протокол горячих папок и формат ответов Content AI, отдавая реальные ответы из `../fixtures/ocr` по имени файла, чтобы конвейер `scan-gateway` проверялся без доступа к банковской системе. ## ADDED Requirements ### Requirement: Эмулятор отвечает по протоколу горячих папок Процесс `python -m src.scan_emulator` SHALL опрашивать входящий каталог каждую секунду; для нового файла `_.` через `SCAN_EMULATOR_DELAY` секунд (по умолчанию 2) SHALL создать `//.json`; после обработки входящий файл SHALL быть переименован в `_..done`, чтобы не обрабатываться повторно. #### Scenario: Один файл - **WHEN** во входящем каталоге появляется `3f1c…_aep_5.pdf` - **THEN** через ≤ 5 с существует `Output/3f1c…/3f1c….json`, а входящий файл переименован в `…pdf.done` ### Requirement: Ответ берётся из фикстур по имени Эмулятор SHALL искать в `SCAN_FIXTURES_DIR` файл `.json`, затем `*.json` (первый по алфавиту), где `` — имя входящего файла без префикса `_` и расширения; содержимое SHALL быть записано в ответ с `file_uid = `. #### Scenario: Точное имя - **WHEN** входящий файл — `…_aep_5.pdf`, в фикстурах есть `aep_5.json` - **THEN** ответ равен `aep_5.json` с заменённым `file_uid` #### Scenario: Префикс - **WHEN** входящий файл — `…_aep_8.pdf`, в фикстурах есть `aep_8_form4.json` - **THEN** ответ равен `aep_8_form4.json` с заменённым `file_uid` ### Requirement: Неизвестный файл — ошибка в формате Content AI Если пара не найдена, эмулятор SHALL записать ответ `{"file_uid": "", "error": {"code": "INVALID_DOCUMENT", "message": "<имя>: нет эталонного ответа в фикстурах"}, "data_ocr": []}`. #### Scenario: Нет пары - **WHEN** входящий файл — `…_unknown.pdf` - **THEN** ответ содержит `error.code = INVALID_DOCUMENT` и пустой `data_ocr`; `scan-gateway` публикует конверт с тем же кодом ### Requirement: Эмулятор запускается из того же образа В `docs/dev/docker-compose.yml` сервис `scan-emulator` SHALL использовать образ `scan-gateway` с командой `python -m src.scan_emulator`, общий том `hotfolder` и `../../fixtures/ocr`, смонтированный только для чтения. #### Scenario: Compose - **WHEN** выполнен `docker compose --profile services up -d` - **THEN** контейнер `scan-emulator` работает, его лог сообщает каталоги и число найденных пар фикстур