# DrHider — Полный аудит и план рефакторинга

**Дата:** 2026-07-12
**Платформа:** Штурвал (Managed Flask) — запускает Flask сам, без Dockerfile/gunicorn
**URL:** https://drhider.pythonk8s.dev.nubes.ru/
**Репозиторий:** https://gitea.services.ngcloud.ru/Nail/drhider

---

## Текущее состояние (аудит каждого файла)

| Файл | Статус | Решение |
|---|---|---|
| `Dockerfile` | ❌ НЕ НУЖЕН | Штурвал сам запускает Flask. Удалить. |
| `drhider_server.py` | ❌ НЕ НУЖЕН | Standalone-сервер с ВМ (:8767). Flask app.py уже обрабатывает /api/drhider. Удалить. |
| `requirements.txt` | ⚠️ Нужны правки | Убрать `gunicorn` и `gevent`. Оставить `flask`, `python-docx`, `pdfplumber`, `httpx`. |
| `.gitignore` | ✅ OK | Без изменений. |
| `.gitea/workflows/deploy.yaml` | ✅ OK | CI для Штурвала. |
| `site/app.py` | ⚠️ Нужны правки | Удалить блок `if __name__ == "__main__"` (gunicorn). При рефакторинге — вынести LLMClient. |
| `site/templates/index.html` | ✅ OK | UI. |
| `site/static/favicon.svg` | ✅ OK | Иконка (из loadtest). |
| `drhider.py` | ⚠️ МОНОЛИТ | 560 строк. Разбить на ~20 модулей. |
| `History/` | ✅ OK | Документация. |

---

## План рефакторинга (Фаза 1: удаление лишнего)

### Шаг 1.1 — Удалить `Dockerfile`
### Шаг 1.2 — Удалить `drhider_server.py`
### Шаг 1.3 — Исправить `requirements.txt` (убрать gunicorn, gevent)
### Шаг 1.4 — Исправить `site/app.py` (убрать блок `if __name__ == "__main__"`)
### Шаг 1.5 — Проверить синтаксис → commit → push

---

## План рефакторинга (Фаза 2: модульная структура)

### Новая структура `drhider/` пакета (вместо `drhider.py` 560 строк):

```
drhider/                          # Пакет ядра обфускации
├── __init__.py                   # re-export: obfuscate_files()
├── config.py                     # Константы: ENTITY_PATTERNS, COMPANY_PATTERN, PERSON_PATTERN,
│                                  #   RU_SURNAMES, RU_NAMES, RU_PATRONYMICS,
│                                  #   RU_CITIES, RU_STREETS, FAKE_DOMAINS
├── checksum.py                   # _checksum_inn10, _checksum_inn12, _checksum_ogrn
├── random_utils.py               # _random_digits, _random_letters
├── generators/                   # Генераторы фиктивных значений
│   ├── __init__.py               # ENTITY_GENERATORS маппинг
│   ├── phone.py                  # generate_phone
│   ├── email.py                  # generate_email
│   ├── inn.py                    # generate_inn10, generate_inn12
│   ├── ogrn.py                   # generate_ogrn
│   ├── kpp.py                    # generate_kpp
│   ├── bik.py                    # generate_bik
│   ├── accounts.py               # generate_rs, generate_ks
│   ├── passport.py               # generate_passport
│   ├── company.py                # generate_company
│   ├── person.py                 # generate_person
│   └── address.py                # generate_address
├── extractor.py                  # _extract_text, _expand_zips, _convert_pdfs_to_docx
├── scanner.py                    # Проход 1: _scan_regex, _scan_llm_ner
├── replacer.py                   # Проход 2: _replace_in_docx, _replace_in_text, _apply_replacements
├── builder.py                    # Сборка: _build_zip, _build_mapping_csv
├── obfuscator.py                 # TwoPassObfuscator — оркестратор
└── llm_client.py                 # LLMClient (из app.py → сюда)

site/                             # Flask-приложение
├── __init__.py
├── app.py                        # Только create_app() + регистрация blueprint'ов
├── routes/
│   ├── __init__.py               # Регистрация всех blueprint'ов
│   ├── main_bp.py                # GET /
│   ├── health_bp.py              # GET /health
│   └── api_bp.py                 # POST /api/drhider
├── templates/index.html
└── static/favicon.svg
```

### Принципы:
- Каждый файл ≤ 50 строк (где возможно)
- Каждый файл — одна ответственность
- Максимум docstring и инлайн-комментариев
- Все импорты явные, никаких `import *`

---

## Результат рефакторинга (2026-07-12)

### Итоговая структура

```
drhider/                              # Пакет ядра обфускации
├── __init__.py                       # re-export: obfuscate_files, LLMClient, TwoPassObfuscator
├── config.py                         # Константы: ENTITY_PATTERNS, словари имён/городов/улиц
├── checksum.py                       # Контрольные суммы: ИНН10, ИНН12, ОГРН
├── random_utils.py                   # Утилиты: random_digits, random_letters
├── llm_client.py                     # LLMClient — HTTP-клиент к LLM API
├── extractor.py                      # Извлечение текста + expand_zips + convert_pdfs_to_docx
├── scanner.py                        # Проход 1: scan_regex, scan_llm_ner
├── replacer.py                       # Проход 2: apply_replacements, replace_in_docx, replace_in_text
├── builder.py                        # Сборка: build_zip, build_mapping_csv
├── obfuscator.py                     # TwoPassObfuscator — оркестратор
└── generators/                       # Генераторы фиктивных значений
    ├── __init__.py                   # ENTITY_GENERATORS маппинг
    ├── phone.py, email.py            # Телефон, email
    ├── inn.py, ogrn.py, kpp.py       # ИНН, ОГРН, КПП
    ├── bik.py, accounts.py           # БИК, счета (р/с, к/с)
    ├── passport.py                   # Паспорт
    ├── company.py, person.py         # Компания, ФИО
    └── address.py                    # Адрес

site/                                 # Flask-приложение
├── app.py                            # create_app() + VERSION (20 строк)
├── routes/
│   ├── __init__.py                   # register_routes()
│   ├── main_bp.py                    # GET /
│   ├── health_bp.py                  # GET /health
│   └── api_bp.py                     # POST /api/drhider
├── templates/index.html
└── static/favicon.svg
```

### Что изменилось

| Было | Стало |
|---|---|
| `drhider.py` — 560 строк монолит | Пакет `drhider/` — 22 модуля по 20–100 строк |
| `site/app.py` — 100 строк (всё в одном файле) | `app.py` 33 строки + 3 blueprint'а по 20–50 строк |
| `Dockerfile` | Удалён (Штурвал сам) |
| `drhider_server.py` | Удалён (Flask заменяет) |

### Коммиты

- `a2f754a` — Фаза 1: удалён Dockerfile, drhider_server.py, gunicorn
- `37581eb` — Фаза 2: config.py, checksum.py, random_utils.py, generators/
- `2cf4e08` — Фаза 2: llm_client.py, extractor.py, scanner.py, replacer.py, builder.py, obfuscator.py
- `51bc1a7` — Фаза 2: site/app.py → blueprint'ы, старый drhider.py удалён

| Переменная | Значение |
|---|---|
| `LLM_API_KEY` | `sk-ucI5YvOticoOQ9Kuj5K9mQ` |
| `LLM_URL` | `https://api.aillm.ru/v1/chat/completions` |
| `LLM_MODEL` | `gpt-oss-120b` |
