# DrHider — обфускация документов (Managed Flask)

**URL:** https://drhider.pythonk8s.dev.nubes.ru/
**Репозиторий:** https://gitea.services.ngcloud.ru/Nail/drhider
**Платформа:** Штурвал (Managed Flask на pythonk8s)
**Дизайн фронтенда:** `/home/naeel/nubes/design/`

---

## Что делает

Загружаешь документы (.docx, .pdf, .txt, .zip) — получаешь ZIP с обфусцированными копиями.
Все персональные данные, реквизиты, телефоны, email заменяются на фиктивные.
В архиве — mapping.csv с таблицей замен (оригинал → фиктивное).

Обфускация двухпроходная:
1. **Проход 1 (сбор):** regex + LLM находят все сущности во всех файлах → глобальный словарь замен
2. **Проход 2 (замена):** применяем замены ко всем файлам → ZIP

Согласованность: одна и та же сущность во всех файлах → одно и то же фиктивное значение.

---

## ⛔ ПРАВИЛА ДЛЯ АГЕНТОВ (читать перед ЛЮБЫМ действием)

### 1. НЕ смотреть локальные папки contracts/contracts-flask
Весь старый код drhider — ТОЛЬКО на ВМ (`5.172.178.213`). НЕ локально.
Единственное исключение: `/home/naeel/nubes/loadtest/` (образец структуры managed Flask).

### 2. Штурвал запускает Flask САМ
- БЕЗ Dockerfile (удалён)
- БЕЗ gunicorn (нет в requirements.txt)
- Точка входа: `site/app.py` → `app = create_app()`
- Деплой: `git push origin master` → авто-деплой в UI Штурвала

### 3. НЕ менять код без «делай»
Даже если ошибка очевидна. Показать → описать → ЖДАТЬ.

### 4. После ЛЮБОЙ правки:
```bash
python3 -c "import py_compile; py_compile.compile('файл.py', doraise=True)"
git add -A && git commit -m "подробное описание" && git push
```

### 5. Документировать ВСЁ в History/
Каждое изменение, план, ошибку — в отдельный .md файл.

---

## Структура проекта

### `drhider/` — пакет ядра обфускации

| Файл | Назначение | Строк |
|---|---|---|
| `__init__.py` | re-export: `obfuscate_files`, `LLMClient`, `TwoPassObfuscator` | 10 |
| `config.py` | Константы: regex-паттерны (ENTITY_PATTERNS, COMPANY_PATTERN, PERSON_PATTERN), словари имён/городов/улиц | 80 |
| `checksum.py` | Контрольные суммы: ИНН10, ИНН12, ОГРН | 60 |
| `random_utils.py` | Утилиты: `random_digits`, `random_letters` | 20 |
| `llm_client.py` | LLMClient — HTTP-клиент к LLM API (aillm.ru) | 50 |
| `extractor.py` | Извлечение текста из .docx/.pdf/.txt + `expand_zips` + `convert_pdfs_to_docx` | 180 |
| `scanner.py` | Проход 1: `scan_regex` (regex) + `scan_llm_ner` (LLM NER) | 110 |
| `replacer.py` | Проход 2: `apply_replacements`, `replace_in_docx`, `replace_in_text` | 100 |
| `builder.py` | Сборка: `build_zip`, `build_mapping_csv` | 65 |
| `obfuscator.py` | `TwoPassObfuscator` — оркестратор + `obfuscate_files()` | 100 |

### `drhider/generators/` — генераторы фиктивных значений

Каждый файл — один генератор (10–40 строк). Интерфейс: `generate_xxx(original: str) -> str`.

| Файл | Что генерирует |
|---|---|
| `phone.py` | +7 (XXX) XXX-XX-XX |
| `email.py` | user@fake-domain |
| `inn.py` | ИНН 10 и 12 знаков (с контрольной суммой) |
| `ogrn.py` | ОГРН 13 знаков |
| `kpp.py` | КПП 9 знаков |
| `bik.py` | БИК 9 знаков (04XXXXXXX) |
| `accounts.py` | Расчётный счёт (40702...) + корр. счёт (30101...) |
| `passport.py` | Паспорт (XX XX XXXXXX) |
| `company.py` | ООО/ЗАО/АО «СлучайноеНазвание» |
| `person.py` | Фамилия И.О. |
| `address.py` | Город, ул. Улица, д. N |

`__init__.py` содержит `ENTITY_GENERATORS` — маппинг `entity_type → генератор`.

### `site/` — Flask-приложение

| Файл | Назначение |
|---|---|
| `app.py` | `create_app()` — создание Flask, регистрация blueprint'ов, VERSION |
| `routes/__init__.py` | `register_routes(app)` |
| `routes/main_bp.py` | `GET /` — HTML-интерфейс |
| `routes/health_bp.py` | `GET /health` — `{"ok": true, "version": "..."}` |
| `routes/api_bp.py` | `POST /api/drhider` — multipart files → ZIP |
| `templates/index.html` | UI (выбор файлов, прогресс, скачивание) |
| `static/favicon.svg` | Иконка |

### Корневые файлы

| Файл | Назначение |
|---|---|
| `requirements.txt` | `flask`, `python-docx`, `pdfplumber`, `httpx` |
| `.gitignore` | `__pycache__/`, `*.pyc`, `.env` |
| `.gitea/workflows/deploy.yaml` | CI: валидация Python |
| `History/` | Документация всех изменений |
| `README.md` | Этот файл |
| `docs/ARCHITECTURE.md` | Архитектура |
| `docs/DEPLOY.md` | Деплой, ВМ, переменные окружения |
| `docs/DEVELOPMENT.md` | Порядок действий при изменении кода |

---

## API

| Метод | Путь | Что делает |
|---|---|---|
| `GET` | `/` | HTML-интерфейс |
| `GET` | `/health` | `{"ok": true, "version": "2.0.0"}` |
| `POST` | `/api/drhider` | multipart/form-data (поле `files`) → `application/zip` |

---

## Переменные окружения (Штурвал)

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

---

## Связь с ВМ contracts (legacy)

На ВМ `5.172.178.213` (contracts.kube5s.ru) есть старая версия drhider:
- `drhider_server.py` на порту 8767 — standalone HTTP-сервер
- `drhider.py` — та же логика, что и в этом проекте (скопирована оттуда)

Этот проект (`drhider.pythonk8s.dev.nubes.ru`) — **независимый managed Flask**, заменяет ВМ-версию.

SSH к ВМ: `ssh -i ~/.ssh/naeel_vm_id_ed25519 naeel@5.172.178.213`
