Compare commits
1
Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
614c00edea |
@@ -259,6 +259,65 @@ thoughts 477, total 1627. Стоимость по тарифу Gemini 3.6 Flash
|
||||
candidate output как выход: $0.00092, то есть около 9 копеек при курсе 95
|
||||
рублей за доллар.
|
||||
|
||||
## 2026-08-31: Критическая валидация отчета Opus
|
||||
|
||||
Пользователь запросил документировать анализ Opus, выполнить критическую
|
||||
сверку по коду и сформулировать вопросы до внесения изменений.
|
||||
|
||||
### Что подтверждено по коду
|
||||
|
||||
- `recipe_service/app.py`: есть дублирование вызовов `record(...)` по веткам
|
||||
ответа; единый финализатор уменьшит риск расхождений полей метрик.
|
||||
- `recipe_service/app.py`: `duration_ms` считается только в ветке `401`,
|
||||
в остальных ветках передается `0`.
|
||||
- `recipe_service/app.py`: используется `__import__('time').monotonic()`
|
||||
вместо обычного `import time`.
|
||||
- `recipe_service/app.py`: сравнение Bearer-токена выполнено через `==`,
|
||||
без constant-time сравнения.
|
||||
- `recipe_service/metrics.py`: `record()` вызывает `initialize()` на каждый
|
||||
запрос, что приводит к повторной инициализации схемы БД.
|
||||
- `gemini_proxy/app.py`: endpoint принимает `api_key_override` из формы.
|
||||
- `android-app/app/build.gradle.kts`: `RECEIPT_API_TOKEN` попадает в
|
||||
`BuildConfig`, значит секрет присутствует в клиентском APK.
|
||||
- `android-app/app/src/main/java/ru/obdai/receipt/camera/CameraManager.kt`:
|
||||
на каждом кадре выполняется цепочка YUV -> JPEG -> Bitmap.
|
||||
- `android-app/app/src/main/java/ru/obdai/receipt/MainActivity.kt`:
|
||||
текст результата выводится и в `Column`, и в `ResultOverlay`.
|
||||
- `android-app/app/src/main/java/ru/obdai/receipt/crop/MedicationZoneDetector.kt`:
|
||||
дата в формате `dd.mm.yyyy` сама по себе триггерит `PatientDataDetected`.
|
||||
|
||||
### Что уточнено по замечаниям Opus
|
||||
|
||||
- Замечание про `client_ip=127.0.0.1` корректно как риск достоверности
|
||||
метрик за nginx. Для надежного учета реального IP требуется явная политика
|
||||
доверия прокси и корректная обработка заголовков.
|
||||
- Замечание про детализацию `502` корректно как вопрос баланса между
|
||||
диагностикой и минимизацией утечки деталей провайдера.
|
||||
- Замечание про отсутствие тестов для `recipe_service` подтверждено: в
|
||||
текущем дереве есть `gemini_proxy/test_app.py`, но нет тестового файла
|
||||
для `recipe_service`.
|
||||
|
||||
### Вопросы к Opus (блокеры перед правками)
|
||||
|
||||
1. По `gemini_proxy/app.py`: удаляем `api_key_override` полностью или
|
||||
оставляем только в debug-режиме под отдельным флагом окружения?
|
||||
2. По `recipe_service/app.py` ветке `502`: какой контракт ошибки нужен
|
||||
клиенту - единое сообщение, коды причин, или ограниченный whitelist
|
||||
провайдерских причин без сырого текста?
|
||||
3. По учету IP за nginx: доверяем строго одному прокси (`x_for=1`) или
|
||||
нужен более строгий trust chain по сети/подсети?
|
||||
4. По Android токену: подтверждаем переход на краткоживущие серверные
|
||||
токены (token exchange), или остается текущая схема MVP с явной
|
||||
фиксацией риска?
|
||||
5. По privacy-gate: дата в medication-зоне должна блокировать отправку,
|
||||
или только снижать confidence и требовать подтверждение пользователя?
|
||||
|
||||
### Итог
|
||||
|
||||
Отчет Opus в значительной части подтвержден фактами по текущему коду.
|
||||
Критичные изменения backend можно готовить после ответов на вопросы выше,
|
||||
чтобы не сломать контракт клиента и не ослабить security-policy.
|
||||
|
||||
Вывод: лимит 500 токенов оказался недостаточным; следующий независимый тест
|
||||
проводится с существенно большим лимитом и ещё более короткой JSON-схемой.
|
||||
|
||||
@@ -641,3 +700,49 @@ nginx-маршруты без redirect и health `/receipt/health`. Старые
|
||||
IP `127.0.0.1`, MIME `image/png`, размер 531101 байт, длину prompt 88 и
|
||||
непустой usage JSON. Тестовый image-файл удалён после запроса; приложение
|
||||
читает изображение в память и не пишет его на диск.
|
||||
|
||||
## 2026-08-31: критическая валидация отчета Opus и обновление плана
|
||||
|
||||
Проведена проверка утверждений Opus по фактическому коду и конфигурации.
|
||||
|
||||
Подтверждено по backend:
|
||||
|
||||
- В `recipe_service/app.py` есть многократное дублирование блоков `record(...)` по веткам обработки.
|
||||
- В `recipe_service/app.py` длительность `duration_ms` в большинстве веток фиксируется как `0`; фактический расчет есть только для `401`.
|
||||
- В `recipe_service/app.py` используется `__import__('time').monotonic()` вместо нормального `import time`.
|
||||
- В `recipe_service/app.py` сравнение bearer-токена выполнено через `==`, без constant-time сравнения.
|
||||
- В `recipe_service/app.py` в `502` наружу пробрасывается provider detail, что может раскрывать внутренние детали upstream-ошибок.
|
||||
- В `recipe_service/metrics.py` функция `record()` вызывает `initialize()` на каждый запрос.
|
||||
- `recipe_service/nginx-recipe.conf` передает `X-Real-IP` и `X-Forwarded-For`, но в Flask используется `request.remote_addr`; без `ProxyFix` это адрес прокси.
|
||||
|
||||
Подтверждено по инфраструктуре:
|
||||
|
||||
- `recipe_service/recipe.service` слушает только `127.0.0.1:8770`.
|
||||
- `gemini_proxy/gemini-proxy.service` слушает только `127.0.0.1:8768`.
|
||||
|
||||
Подтверждено по Android:
|
||||
|
||||
- `android-app/app/build.gradle.kts` задает `BuildConfig.RECEIPT_API_TOKEN`, токен попадает в клиентское приложение.
|
||||
- `android-app/app/src/main/java/ru/obdai/receipt/network/ApiClient.kt` отправляет `Authorization: Bearer ...` из `BuildConfig`.
|
||||
- `android-app/app/src/main/java/ru/obdai/receipt/camera/CameraManager.kt` выполняет YUV->JPEG->Bitmap на кадр в analyzer.
|
||||
- `android-app/app/src/main/java/ru/obdai/receipt/MainActivity.kt` выводит результат и в `Column`, и в `ResultOverlay`.
|
||||
- `android-app/app/src/main/java/ru/obdai/receipt/crop/MedicationZoneDetector.kt` блокирует при любой дате по regex, что дает ложные privacy-срабатывания.
|
||||
- `android-app/app/src/main/AndroidManifest.xml` содержит `usesCleartextTraffic="false"`.
|
||||
|
||||
Подтверждено по тестам и зависимостям:
|
||||
|
||||
- Тесты присутствуют только в `gemini_proxy/test_app.py`.
|
||||
- Для `recipe_service` тестов нет.
|
||||
- Корневой `requirements.txt` и `recipe_service/requirements.txt` расходятся по version bounds.
|
||||
|
||||
Дополнительные риски, подтвержденные параллельным аудитом секретов:
|
||||
|
||||
- В локальных репозиториях обнаружены реальные токены/JWT и tracked secret-like файлы; часть секретов не отслеживается Git, но присутствует в рабочих каталогах.
|
||||
- В `tf_provider` обнаружен tracked `secrets/llm.key`; в истории есть многочисленные совпадения по маркерам `sk-`.
|
||||
- В `nifi_fork` история содержит совпадения по маркерам `sk-` и `AKIA`; часть совпадений относится к документации/тестам и требует ручной triage по значениям.
|
||||
|
||||
Статус:
|
||||
|
||||
- Отчет Opus по backend и Android в критических пунктах в основном подтвержден.
|
||||
- Для части исторических совпадений по секретам нужна ручная классификация: реальный ключ, тестовый маркер или документационный пример.
|
||||
- Код в этой итерации не менялся; выполнено документирование и валидация.
|
||||
|
||||
@@ -182,3 +182,38 @@ crop лекарственной строки
|
||||
- начать с SQLite и перейти на отдельный PostgreSQL только при появлении требований к параллельной записи, админке или нескольким экземплярам сервиса.
|
||||
|
||||
Перед фиксацией порогов и коэффициентов scoring провести эксперимент на 50–200 обезличенных рецептах.
|
||||
|
||||
## 12. Критический план по результатам валидации Opus (2026-08-31)
|
||||
|
||||
### Подтвержденные проблемы и приоритет
|
||||
|
||||
1. `recipe_service/metrics.py`: убрать `initialize()` из `record()`; инициализация должна быть только на старте сервиса.
|
||||
2. `recipe_service/app.py`: устранить дублирование `record(...)` через единый финализатор/обертку завершения запроса.
|
||||
3. `recipe_service/app.py`: считать `duration_ms` во всех ветках, а не только при `401`.
|
||||
4. `recipe_service/app.py`: заменить сравнение токена на constant-time (`hmac.compare_digest`).
|
||||
5. `recipe_service/app.py`: минимизировать детализацию `502` для клиента, подробности оставлять в логах.
|
||||
6. `recipe_service/app.py`: добавить учет заголовков прокси (`ProxyFix`) для корректного client IP.
|
||||
7. Тесты: добавить `recipe_service/test_app.py` с кейсами `401/400/415/413/200`.
|
||||
8. `requirements.txt`: выровнять root и `recipe_service/requirements.txt` по version bounds.
|
||||
|
||||
### Android-блок (после подтверждения модели безопасности)
|
||||
|
||||
1. Убрать долговременный статический секрет из APK или перейти на схему краткоживущих токенов.
|
||||
2. Оптимизировать pipeline камеры: снизить частоту тяжелой конвертации или заменить способ получения bitmap.
|
||||
3. Убрать двойной вывод результата (`Column` и `ResultOverlay`) и оставить один источник отображения.
|
||||
4. Пересмотреть `containsPatientData` в `MedicationZoneDetector`: дата сама по себе не должна блокировать распознавание.
|
||||
|
||||
### Вопросы к Opus (требуют уточнения до правок)
|
||||
|
||||
1. `api_key_override` в `gemini_proxy/app.py`: удалять полностью или оставить только для локального debug-режима за флагом окружения?
|
||||
2. По `502`: какой клиентский формат ошибки нужен — единое сообщение или кодизированные причины без деталей провайдера?
|
||||
3. Для `ProxyFix`: доверяем ровно одному прокси (`x_for=1`) или нужен более строгий trust chain?
|
||||
4. Для Android: подтверждаем перенос от статического API-токена к короткоживущему серверному token exchange?
|
||||
5. По privacy-гейту: дата рецепта в medication-зоне допустима или должна только понижать confidence без блокировки?
|
||||
|
||||
### План выполнения после подтверждения
|
||||
|
||||
1. Backend фаза A: `metrics.py` + `app.py` (инициализация, duration, record-finalizer, compare_digest, ProxyFix).
|
||||
2. Backend фаза B: тесты `recipe_service/test_app.py` + проверка pytest.
|
||||
3. Backend фаза C: harmonize requirements.
|
||||
4. Android фаза D: безопасность токена + оптимизация камеры + privacy-gate.
|
||||
|
||||
Reference in New Issue
Block a user