v4.0.0: дизайн Nubes, логотип, ZIP без mapping.csv внутри, CSV отдельно с датой-временем
Deploy drhider / validate (push) Waiting to run

This commit is contained in:
2026-07-12 13:52:24 +04:00
parent 59f7601266
commit adf3002e3d
14 changed files with 412 additions and 340 deletions
@@ -0,0 +1,47 @@
# Запрос к Соннету — нумерация вместо генерации фейков (2026-07-12)
## Контекст
DrHider обфусцирует документы: ищет ПДн → заменяет на фиктивные значения.
Сейчас используется генерация "похожих" фейков (Иванов И.И., ООО «Ромашка», +7(495)...).
## Проблема
1. **Адреса → абракадабра.** Ул. Стекольная → иг. 8ц Лжчюсвхшбр. Потому что fallback-генератор меняет кириллицу на случайную кириллицу.
2. **Сложность.** 11 генераторов под каждый тип данных. Каждый надо поддерживать.
3. **Ложное ощущение реальности.** Фейковые ИНН с правильной контрольной суммой выглядят как настоящие.
## Идея
Заменить всю генерацию на **нумерацию по типам:**
| Оригинал | Замена |
|---|---|
| Иванов И.И. | `Лицо_0042` |
| ООО «НУБЕС» | `Компания_0003` |
| ул. Стекольная, д.7 | `Адрес_0015` |
| +7 (495) 789-41-35 | `Телефон_0007` |
| info@nubes.ru | `Email_0004` |
| ИНН 9706005293 | `ИНН_0002` |
| Р/с 40702... | `Счёт_0001` |
| договор-XXX001.docx | `Файл_0006` |
## Вопросы
1. **Плюсы/минусы** нумерации vs генерации фейков для задачи обфускации документов?
2. **Как нумеровать?** Глобальный счётчик на каждый тип? Или в рамках одного документа?
3. **Стоит ли сохранять формат?** Например `Телефон_0007` vs `+7 (000) 000-00-07`?
4. **mapping.csv** — при нумерации он становится главным документом аудита. Это ок?
5. **UUID вместо номеров?** `Лицо_a3f4b2` — лучше или хуже последовательных номеров?
## Текущий mapping.csv (для контекста)
```csv
тип_данных,оригинал,замена
phone,+7 (495) 789-41-35,+7 (495) 906-87-80
email,info@nubes.ru,ypiorej@company.local
company,"ЗАО ""XXX001""",ООО «Альянс»
inn_ul,ИНН 9706005293,ИНН 1846691249
text,Исполнителем Заказчику Сторонами,Кузнецов О.В.
text,"115404, г. Москва, ул. 1-я Стекольная, д.7с2","084810, б. Ввжзгд, гф. 6-в Фтпжыобнзщ, я.8с1"
```
@@ -0,0 +1,54 @@
# Запрос к Соннету — нумерация vs фейки для downstream LLM (2026-07-12)
## Контекст
Я делаю сервис **DrHider** — обфускация документов. Находит ПДн → заменяет.
После обфускации документы идут на дальнейшую LLM-обработку — **сверка спецификаций**
(другой сервис contracts, извлекает типы/номера/даты/контрагентов через LLM).
Сейчас генерация фейков: `Иванов И.И.``Петров А.С.`, `ООО «Ромашка»``ООО «Спектр»`.
**Проблема:** для неизвестных типов (адреса, нестандартные ID) — character-class замена
даёт абракадабру: `ул. Стекольная``иг. 8ц Лжчюсвхшбр`. Downstream LLM не может это обработать.
## Варианты замены
### А. Чистая нумерация
`Иванов И.И.``Лицо_0042`, `ООО «Ромашка»``Компания_0003`, `ул. Ленина``Адрес_0015`
Плюс: никакой абракадабры. Минус: LLM теряет контекст («Лицо_0042 заключил договор» — не понимает семантику).
### Б. Фейки (сейчас)
`Иванов И.И.``Петров А.С.`, `ООО «Ромашка»``ООО «Спектр»`
Плюс: LLM понимает роли. Минус: сложно (11 генераторов), ложное ощущение реальности,
для неизвестных типов — абракадабра.
### В. Гибрид: шаблон + номер
`Иванов И.И.``Иванов_5677`, `ООО «Ромашка»``ООО_Технология_0034`,
`ул. Стекольная, д.7``ул_Ленина_0015`, `+7 (495) 789-41-35``+7_495_000_0042`,
`info@nubes.ru``email_0007@fake`
Плюс: LLM видит что это человек/компания/адрес, номер гарантирует уникальность и обфускацию.
Минус: всё равно нужны шаблоны для каждого типа.
## Вопросы
1. Какой вариант лучше для downstream LLM-обработки (извлечение контрагентов, дат, номеров)?
2. Вариант В — достаточно ли LLM поймёт что `Иванов_5677` это персональные данные?
3. Для неизвестных типов — `[Данные_NNNN]` как fallback, ок?
4. Глобальная нумерация (сквозная через все документы пакета) vs локальная (в рамках одного файла)?
5. Стоит ли сохранять частичную структуру (например телефон `+7_495_000_0042` сохраняет формат номера)?
## Downstream задача (для контекста)
LLM в сервисе contracts получает текст документа и должна извлечь:
- Контрагент («с кем договор»)
- Номер и дату договора
- Список услуг с ценами (таблица)
Промпт для contracts LLM (фрагмент):
```
Извлеки из текста: тип документа, номер, дату, контрагента.
Верни JSON: {"type":"договор","number":"...","date":"...","counterparty":"..."}
```
@@ -0,0 +1,46 @@
# Ответ Соннета v3 — нумерация вместо генерации фейков (2026-07-12)
## Q1. Нумерация vs фейки
- ✅ Адреса без абракадабры, код проще, аудит прозрачнее
- ❌ Документ нечитаем (`Лицо_0042 заключил договор с Компания_0003`)
- Вывод: для аудита/хранения — отлично, для показа людям — фейки лучше
## Q2. Глобальный счётчик на весь пакет
Одна сущность в разных документах → один номер. `TwoPassObfuscator` хранит counters.
## Q3. Сохранять формат?
Рекомендация: `Тип_NNNN` — проще всего, аудит максимально прозрачен.
## Q4. mapping.csv — главный документ аудита
Да, это улучшение. mapping.csv — секретный ключ деобфускации.
## Q5. Номера vs UUID
Номера (`Лицо_0042`) — лучше для читаемости и аудита.
---
## План изменений
### Удалить
- `drhider/generators/` — все 12 файлов
- `drhider/checksum.py` — больше не нужен (ИНН без контрольных сумм)
- `drhider/random_utils.py` — больше не нужен
### Изменить
- `scanner.py`: добавить `TYPE_PREFIXES` + `_next_token()`, убрать импорты генераторов
- `obfuscator.py`: `TwoPassObfuscator` хранит `counters` dict
- `config.py`: убрать словари имён/городов (RU_SURNAMES, ...)
### Новая логика замены
```python
TYPE_PREFIXES = {
"person_name": "Лицо", "company": "Компания", "phone": "Телефон",
"email": "Email", "address": "Адрес", "inn": "ИНН", ...
}
_FALLBACK = "Данные"
def _next_token(entity_type, counters):
prefix = TYPE_PREFIXES.get(entity_type, _FALLBACK)
counters[prefix] = counters.get(prefix, 0) + 1
return f"{prefix}_{counters[prefix]:04d}"
```
@@ -0,0 +1,19 @@
# Ответ Соннета v4 — гибридный формат замен (2026-07-12)
## Итог: Вариант В (шаблон + номер)
| Тип | Формат замены | Пример |
|---|---|---|
| ФИО | `Фамилия_NNNN` | `Иванов_5677` |
| Компания | `ООО_Слово_NNNN` | `ООО_Технология_0034` |
| Адрес | `ул_Шаблон_NNNN` | `ул_Ленина_0015` |
| Телефон | `+7_код_000_NNNN` | `+7_495_000_0042` |
| Email | `email_NNNN@fake` | `email_0007@fake` |
| ИНН | `ИНН_NNNNNNNNNN` | `ИНН_0000000042` |
| Неизвестный тип | `[Тип_NNNN]` | `[Адрес_0023]` |
## Ключевые принципы
1. **Читаемо человеком** — не ужиматься, пусть будет естественно
2. **Однозначно для LLM** — префикс указывает тип сущности
3. **Глобальная нумерация** — одна сущность = один номер во всех файлах пакета
4. **Цены/суммы** — не обфусцировать (нужны для downstream сверки)