Files
contracts/History/llm-analysis/sonnet-audit-request.md
T

259 lines
12 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# Аудит для Sonnet — пофайловый разбор
Ты должен прочитать КАЖДЫЙ файл из списка ниже и выдать по нему детальный отчёт.
## Формат отчёта ПОФАЙЛОВО
Для каждого файла:
```
### convert_server.py
| Строка | Тип | Серьёзность | Что не так | Как исправить |
|--------|-----|-------------|------------|---------------|
| 242 | dead code | low | Дубликат _handle_cleanup | Удалить второй |
```
После пофайлового разбора — СВОДНАЯ ТАБЛИЦА всех проблем по серьёзности: critical → high → medium → low.
---
## Файл 1: `contractor/deploy/convert_server.py`
**Что это:** HTTP роутер на http.server + ThreadingMixIn. Все endpoint'ы приложения.
**Что смотреть:**
- ВСЕ `do_GET`, `do_POST`, `do_DELETE` — правильная диспетчеризация? Нет мёртвых путей?
- `_handle_process_v2` — валидация UUID? SSE корректно закрывается при ошибке? Утечка соединений?
- `_handle_upload` — размер тела? Content-Type проверка? Таумаут?
- `_handle_cleanup` — ДВА определения (строки ~242 и ~255). Второй перекрывает первый. Dead code. Порядок DELETE правильный?
- `_handle_api_sync` — читает JSON body. Что если тело пустое/битое? Что если keep_ids содержит 10000 id? Нет лимита.
- `_handle_api_document` — doc_id из URL без валидации UUID → psycopg2.InvalidTextRepresentation на "fake-id".
- `_handle_api_document_delete` — cascade порядок: spec_current → spec_events → supplements → document. Правильный?
- `_handle_classify_batch` — batch_id из JSON без валидации UUID.
- `_handle_apply_groups` — валидация структуры groups?
- `_handle_api_prompts_*` — role из query params без валидации.
- `_json()` — экранирует ли спецсимволы в данных?
- `_sse()` — f-string с json.dumps. Данные от LLM могут содержать спецсимволы.
- Импорт `execute` на строке 12 — не конфликтует с другими импортами?
- `ALTER TABLE ADD COLUMN IF NOT EXISTS` — права на DDL? Идемпотентно?
- CORS — `_send_cors()` вызывается везде? OPTIONS?
---
## Файл 2: `contractor/deploy/app.js`
**Что это:** Весь фронтенд (42KB). Загрузка, классификация, группы, сравнение, промпты.
**Что смотреть:**
- `fileQueue`, `contractId`, `batchId` — глобальные. Где расходятся с сервером?
- `renderTable()``innerHTML` из `fileQueue[].name`, `fileQueue[].status`. XSS?
- `fileInput change` — гонка удаления старых + upload новых?
- `syncDB()` — fire-and-forget, без await, без проверки ответа.
- `runClassify()` — утечка таймеров при ошибке?
- `loadGroups()` — ЕДИНСТВЕННОЕ место где diffBody. Больше никто не должен.
- `runCompareForGroup()` — compareCard. Все ссылки compareBody/compareStatus?
- `llmBtn` — compareCard. То же.
- SSE handler'ы — ДВА почти идентичных. Дублирование.
- `showText()``escHtml(classify_raw)` ок, но `counterparty`, `own_number` — НЕ экранированы! XSS.
- `escHtml()` — экранирует `<>&"'`?
- `stepDone/Active/resetStepper` — innerHTML через replace. Спецсимволы в id?
- `window._groupsData` — устаревает после remove→re-classify. runCompareForGroup использует индекс.
- `showClassifyBtn()` — идемпотентно?
- `lucide.createIcons()` — не ломает onclick?
---
## Файл 3: `contractor/deploy/app_utils.js`
**Что это:** Утилиты: форматирование, removeFile, escHtml, модалки.
**Что смотреть:**
- `removeFile()` — syncDB+resetStepper+showClassifyBtn через typeof. Если нет — молча.
- `formatDate()`, `formatSize()` — null/undefined safe?
- `escHtml()` — все опасные символы: `< > & " '`?
- `moveUp/Down` — не вызывают syncDB (правильно, состав не меняется).
---
## Файл 4: `contractor/deploy/services/classify.py`
**Что это:** LLM-классификация. ThreadPoolExecutor, выжимка, вызов LLM.
**Что смотреть:**
- `classify_batch()` — reset + list_pending. Гонка между ними?
- `_classify_one()``_smart_extract` может упасть до LLM. Обрабатывается?
- `_smart_extract()` — неожиданная структура elements_json?
- `_call_llm_classify()` — httpx `verify=False`. MITM уязвимость.
- `_safe_json_parse()` — edge cases: Null/None, числа без кавычек, пустой ответ.
- `MAX_WORKERS=4` — 4 одновременных запроса создают каждый свой пул?
- `LLM_KEY` из env — если не задан?
- API key в коде? (берётся из env, ок)
---
## Файл 5: `contractor/deploy/services/grouping.py`
**Что это:** Группировка документов по контрактам + виртуальные группы.
**Что смотреть:**
- `group_documents()` — виртуальные группы: что если parent_number и own_number оба null?
- Коллизия normalize_number: разные номера → одинаковый нормализованный.
- Сортировка по doc_date: None у всех → нестабильный порядок.
- `apply_groups()` — нет проверки на существующий contract (дубликат при повторе).
- `supplements_list.remove(s)` внутри цикла for — может пропускать элементы.
---
## Файл 6: `contractor/deploy/services/process.py`
**Что это:** SSE пайплайн сравнения.
**Что смотреть:**
- `run_pipeline()` — битая ссылка supplement→document? timeout? retry?
- `call_llm()` — таймаут?
- SSE события — все ли обрабатываются на фронте?
---
## Файл 7: `contractor/deploy/services/parse.py`
**Что это:** Парсинг PDF/DOCX.
**Что смотреть:**
- Расширение: .PDF uppercase? Без расширения?
- PDF: битый/зашифрованный → исключение?
- DOCX: .doc (OLE) → исключение?
- Таблицы: пустые, объединённые ячейки?
- file_data = None?
---
## Файл 8: `contractor/deploy/services/upload.py`
**Что это:** Multipart загрузка через cgi.FieldStorage.
**Что смотреть:**
- cgi.FieldStorage deprecated. Большие файлы?
- content_length — отрицательное/огромное → rfile.read?
- filename — path traversal (`../../etc/passwd`)?
- 100MB файл → весь в памяти.
- contract_id без валидации → SQL.
- `delete_by_document` до создания нового → исключение = потеря старого без создания нового.
- base64 → +33% размер.
---
## Файл 9: `contractor/deploy/db/connection.py`
**Что это:** ThreadedConnectionPool.
**Что смотреть:**
- `DB_PASS` из env, пустой → ошибка подключения.
- `minconn=1, maxconn=10` — достаточно?
- getconn/putconn всегда в finally?
- `_connection` глобальная — сервер не стартует без БД.
---
## Файл 10: `contractor/deploy/db/documents.py`
**Что это:** CRUD documents + classify_raw.
**Что смотреть:**
- `insert()` — все параметры через %s?
- `set_classification()` — classify_raw=None → NULL.
- `set_classify_failed()` — не чистит старые поля классификации.
- `delete()` — без cascade!
- `get()` — SELECT *, может вернуть base64 original_bytes.
---
## Файл 11: `contractor/deploy/db/supplements.py`
**Что это:** CRUD supplements + cascade.
**Что смотреть:**
- `delete_by_document()` — spec_current WHERE contract_id удаляет ВСЁ для контракта. Если несколько supplements → остальные теряют spec_current.
- `list_by_contract()` — orphan supplements игнорируются.
- `insert()` — нет FK проверки.
---
## Файл 12: `contractor/deploy/db/contracts.py`
**Что это:** CRUD contracts.
**Что смотреть:**
- `insert()` — нет уникальности, можно дубликат.
- `delete_orphaned()` — вызывается? Где?
---
## Файл 13: `contractor/deploy/db/spec_events.py`
**Что это:** Event Sourcing.
**Что смотреть:**
- `get_next_seq()``MAX(seq)+1`. Гонка! Два потока → одинаковый seq.
- `reset()` — необратимо.
- `apply_ops()` — валидация структуры?
---
## Файл 14: `contractor/deploy/db/spec_current.py`
**Что это:** Текущая спецификация.
**Что смотреть:**
- Кто обновляет spec_current после удаления spec_events?
- `get_elements_json()` — где используется?
---
## Файл 15: `contractor/deploy/db/prompts.py`
**Что это:** CRUD промптов с версионированием.
**Что смотреть:**
- `seed_defaults()``if count>0: return` — если есть extract но нет classify → classify не создастся.
- `_ensure_classify_prompt()` — отдельный механизм, почему?
- `save_new_version()` — UPDATE+INSERT не атомарно. Гонка.
- `activate()` — гонка.
- `delete_prompt()` — проверка is_active потом DELETE. Гонка.
- `_serialize()` — мутирует словарь.
---
## Файл 16: `contractor/deploy/llm_prompt.py`
**Что это:** Билдер промптов.
**Что смотреть:**
- `build_prompt()` — f-string с данными парсинга. Безопасно?
- `_fetch_prompt()` — HTTP к Lucee. Таймаут? Fallback при недоступности?
- `build_classify_prompt()` — прямой доступ к БД, не через HTTP. Почему?
- FALLBACK_* хардкод — дублирование с БД.
---
## Файл 17: `contractor/index.cfm`
**Что это:** HTML-оболочка.
**Что смотреть:**
- `?v=1.0.175` хардкод — менять при каждом обновлении JS.
- pipelineStepper — ○⏳✓ через replace. Надёжно?
- XSS через prompt body в textarea/div?
- Z-index конфликты модалок?
- inline onclick — ломаются при перезагрузке JS?
---
## СВОДНАЯ ТАБЛИЦА (выдать после пофайлового разбора)
| # | Файл:строка | Серьёзность | Тип | Описание | Как исправить |
|---|-------------|-------------|-----|----------|---------------|
## ТОП-5 (срочно)
5 проблем, которые надо чинить прямо сейчас.