v1.0.177: History — объединение history+History, 5 подпапок

This commit is contained in:
“Naeel”
2026-06-25 07:53:56 +04:00
parent 14cca9f8cf
commit c40d8eb5a8
54 changed files with 0 additions and 0 deletions
@@ -0,0 +1,258 @@
# Аудит для 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 проблем, которые надо чинить прямо сейчас.