diff --git a/HISTORY/2026-08-28-obdai-receipt.md b/HISTORY/2026-08-28-obdai-receipt.md index 1179b83..51ac7cc 100644 --- a/HISTORY/2026-08-28-obdai-receipt.md +++ b/HISTORY/2026-08-28-obdai-receipt.md @@ -815,6 +815,7 @@ IP `127.0.0.1`, MIME `image/png`, размер 531101 байт, длину promp - `py_compile` изменённых Python-файлов: успешно. - `recipe_service`: `pytest -q` -> `8 passed`. + - `gemini_proxy`: `pytest -q` -> `4 passed`. ### Отдельно зафиксировано @@ -848,6 +849,82 @@ IP `127.0.0.1`, MIME `image/png`, размер 531101 байт, длину promp - `py_compile` изменённых Python-файлов: успешно. - `recipe_service`: `pytest -q` -> `10 passed`. + +## 2026-08-31: обновлённый анализ и список задач + +Зафиксирован дополнительный обзор полной цепочки +`Android -> obdai.ru/receipt -> recipe_service -> gemini_proxy -> Gemini`. +Ниже перечислены результаты анализа, выполненные проверки и задачи. На момент +записи код по этим задачам ещё не изменялся. + +### Критические дефекты + +1. В Android `ApiClient` используются `@Serializable` и + `Json.decodeFromString`, но в Gradle-конфигурации не найден плагин + `org.jetbrains.kotlin.plugin.serialization`. Необходимо подтвердить сборку + и runtime-десериализацию `ReceiptResponse`; риск состоит в невозможности + показать результат распознавания. +2. Android privacy gate блокирует легитимный рецепт по любой распознанной дате, + включая дату рецепта, и при Latin OCR недостаточно надёжно распознаёт + кириллические признаки ФИО. Поэтому фильтр одновременно создаёт false + positive и может пропускать пациентские данные. + +### Существенные дефекты + +- Поля `Usage` в Android не совпадают с именами, которые возвращаются proxy: + клиент ожидает `promptTokens`, `candidatesTokens`, `totalTokens`, а ответ + содержит `promptTokenCount`, `candidatesTokenCount`, `totalTokenCount`. +- Camera pipeline конвертирует и JPEG-кодирует каждый анализируемый кадр, хотя + отправка выполняется только после фиксации. Это создаёт лишнюю нагрузку CPU и + память. +- Два синхронных gunicorn worker при upstream timeout 180 секунд могут быть + заняты двумя медленными запросами одновременно. Нужно проверить поведение + health и новых запросов под такой нагрузкой; возможная мера — gthread/threads. +- `recipe_service` не обрабатывает `ValueError` при `response.json()` для + успешного, но невалидного ответа proxy; такой ответ может превратиться в + необработанный HTTP 500. +- Длина prompt не ограничена, а MIME изображения не подтверждается проверкой + magic bytes. Это оставляет риск чрезмерных расходов и несоответствия + заявленного типа содержимому. +- `gemini_proxy` создаёт новый `httpx.AsyncClient` на каждый запрос вместо + переиспользования клиента через lifespan. + +### Расхождения с планом + +Не реализованы справочник лекарств и resolver с `rapidfuzz`, кандидаты и +`uncertain`, структурированный ответ `{date, medications[]}`, серверные +`masked_zones`, Document Scanner и AR-overlay по bounding box. Это незавершённые +требования roadmap, а не отдельные подтверждённые runtime-баги. + +Встраивание общего Bearer-токена в Android `BuildConfig` остаётся ограничением +закрытого MVP. Для публичного APK такой токен небезопасен, поскольку его можно +извлечь из приложения. + +### Сильные стороны + +- Компоненты разделены по отдельным сервисам, virtualenv и systemd-юнитам. +- Используются `hmac.compare_digest`, ProxyFix с одним доверенным proxy и + двухуровневый rate limit. +- Изображения не записываются на диск в backend и proxy. +- Секреты хранятся в EnvironmentFile, а не в коде или HISTORY. +- Проверены health endpoints, авторизация, ограничения размера и основные + backend-сценарии; локальные unit-тесты и сборка Android выполнялись. + +### Сформированные задачи и порядок + +1. Проверить и подключить serialization plugin; подтвердить сборку и runtime + декодирование ответа Android. +2. Переработать privacy gate: не блокировать любую дату как PII, сохранить + геометрическое вырезание пациентской зоны и проверить кириллический OCR. +3. Исправить mapping usage-полей и перенести тяжёлую обработку camera pipeline + с каждого кадра на captured frame. +4. Укрепить backend: безопасно обрабатывать конфигурационную ошибку, невалидный + JSON, длину prompt и magic bytes; проверить worker-модель и общий AsyncClient. + +### Статус + +Анализ и список из четырёх задач документированы. Реализация этих задач ещё не +начиналась; требуется отдельная команда на исправление кода. - `gemini_proxy`: `pytest -q` -> `4 passed`. ### Вывод