From a33107fe25320652b0a254c2c2d79770364c3326 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E2=80=9CNaeel=E2=80=9D?= Date: Sun, 28 Jun 2026 10:06:42 +0400 Subject: [PATCH] =?UTF-8?q?docs:=20Opus=20=E2=80=94=20=D0=B4=D0=BE=D0=BF?= =?UTF-8?q?=D0=BE=D0=BB=D0=BD=D0=B8=D1=82=D0=B5=D0=BB=D1=8C=D0=BD=D1=8B?= =?UTF-8?q?=D0=B5=20=D0=B7=D0=B0=D1=81=D0=B0=D0=B4=D1=8B=20(careless=20use?= =?UTF-8?q?r,=2015=20=D0=BF=D1=83=D0=BD=D0=BA=D1=82=D0=BE=D0=B2)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- History/opus-dedup-2026-06-28.md | 53 ++++++++++++++++++++++++++++++++ 1 file changed, 53 insertions(+) diff --git a/History/opus-dedup-2026-06-28.md b/History/opus-dedup-2026-06-28.md index 575d9f7..980c4ef 100644 --- a/History/opus-dedup-2026-06-28.md +++ b/History/opus-dedup-2026-06-28.md @@ -111,3 +111,56 @@ UPSERT по имени уже есть. Реальная проблема: **las 1. `documents.content_hash` + дедуп по нему на загрузке 2. Сортировка допников по `doc_date` 3. Опционально: `date_start` в `name_hash` + +--- + +## Ответ Opus — дополнительные засады (careless user) + +### 🔴 Критичное — «юзер грузит хуйню» + +**1. ZIP-бомба / нет лимитов.** unzip.py распаковывает всё без ограничений. Нужно: лимит ≤500 файлов, суммарный размер, проверка ratio. + +**2. Имена из ZIP без санитизации.** Path-traversal не отсекается для файлов из архива. Нужно: та же проверка `..`/`/` + cp437→utf8. + +**3. `try/except: pass` глушит ошибки удаления.** Минимум — логировать. + +**4. Ручной парс multipart по `PK\x03\x04`.** Хрупко. Лучше `cgi.FieldStorage`. + +### 🟠 Битый/мусорный контент + +**5. Supplement создаётся ДО парсинга.** Битый файл → висячий supplement. Нужно: не создавать при ошибке. + +**6. Пустой парсинг = тихо пропадает.** Скан/зашифрованный PDF → `elements_json` пуст → файл игнорируется без предупреждения. + +**7. Регистр/дубли имён.** `Договор.pdf` vs `договор.pdf` — разные документы. → закрыто `content_hash`. + +### 🟡 LLM возвращает мусор в ops + +**8. Пустой `target_hash` молча no-op.** → нужно `UNRESOLVED`. + +**9. ADD с пустым именем схлопывается.** → отбраковывать. + +**10. Неизвестный `action` молча игнорируется.** Опечатка LLM → без сигнала. + +**11. Арифметика только логируется.** `sum ≠ price*qty` — стоит флаг в UI. + +### 🟢 Числа, даты, нормализация + +**12. Локализованные числа теряются.** `"1 000,50"` → `None`. Нужна нормализация. + +**13. Даты без нормализации.** `01.01.2026` vs `2026-01-01`. Канонизировать перед хешем. + +### 🔵 Конкурентность + +**14. Гонка двух прогонов.** `reset()` без блокировки → каша. Нужен advisory-lock. + +**15. Нет идемпотентности батча.** → закрыто `content_hash`. + +### Приоритет + +1. Лимиты + санитизация ZIP (п.1,2,4) +2. `content_hash`-дедуп — ✅ уже сделано +3. Явный статус «не распознан» (п.5,6) +4. `UNRESOLVED` вместо тихих no-op (п.8,9,10) +5. Нормализация чисел/дат (п.12,13) +6. Advisory-lock (п.14) — при многопользовательности