Deploy drhider / validate (push) Canceled after 0s
- Update upload/ module to v0.2.2 with modular Layer 1 (FilePicker) and Layer 2 (Streaming transit upload) - Replace legacy manual file table in site/templates/index.html with FilePicker.initFilePicker - Wire uploadViaVM with per-file status updates and abort signal support - Add dist bundles to dist/ and site/static/dist/ with routes in site/routes/main_bp.py - Add test_hardening.py and test_safe_name.py from upload-platform - Bump version to 0.0.78 in site/app.py - Document integration plan and report in History/upload-integration/
103 lines
8.3 KiB
Markdown
103 lines
8.3 KiB
Markdown
# План интеграции upload-platform (v0.2.2) в drhider
|
||
|
||
**Дата:** 2026-09-15
|
||
**Статус:** План составлен, ожидает команды на выполнение
|
||
**Целевой сервис:** drhider (Managed Flask на платформе Штурвал)
|
||
**Источник модуля:** `upload-platform/` (релиз v0.2.2, commit `df0576a`)
|
||
|
||
---
|
||
|
||
## 1. Контекст и цели
|
||
|
||
В `drhider` (v0.0.77) модуль загрузки `upload/` зафиксирован в промежуточном состоянии:
|
||
- Фронтенд Слоя 1 использует устаревшую табличную вёрстку с ручным парсингом ZIP без поддержки древовидного сворачивания.
|
||
- Слой 2 работает по смешанной схеме, в то время как в `upload-platform` v0.2.2 реализован и протестирован чистый пофайловый транзит (Streaming transit: PUT $\to$ POST `/api/upload_refs` $\to$ исходящий pull в RAM $\to$ немедленный DELETE $\to$ repeat).
|
||
|
||
**Цель интеграции:**
|
||
Заменить устаревшие наработки в `upload/` и `site/templates/index.html` на проверенную автономную версию `upload-platform` v0.2.2 без нарушения бизнес-логики обфускации (Слой 3: LLM, SSE-стриминг, генерация ZIP).
|
||
|
||
---
|
||
|
||
## 2. Границы ответственности слоёв
|
||
|
||
```
|
||
┌────────────────────────────────────────────────────────────────────────┐
|
||
│ БРАУЗЕР │
|
||
│ [ Слой 1: FilePicker ] ──► [ Слой 2: uploadViaVM ] │
|
||
└─────────────────────────────────────┬──────────────────────────────────┘
|
||
│ 1. PUT файл
|
||
▼
|
||
┌─────────────────────────────┐
|
||
│ ВМ-буфер (RAM WebDAV) │
|
||
└──────────────┬──────────────┘
|
||
│ 3. Исходящий GET (pull в RAM)
|
||
│ 4. DELETE с ВМ
|
||
▼
|
||
┌────────────────────────────────────────────────────────────────────────┐
|
||
│ FLASK BACKEND │
|
||
│ [ Слой 2: Blueprint upload_refs ] ──► [ RAM-сессия: add_file ] │
|
||
│ │ │
|
||
│ [ Слой 3: drhider engine ] ◄─────────────────────┘ get_files(sid) │
|
||
│ (SSE-прогресс, обфускация, mapping, download) │
|
||
└────────────────────────────────────────────────────────────────────────┘
|
||
```
|
||
|
||
- **Слой 1 (Фронтенд)**: инициализация через `FilePicker.initFilePicker()`. Полностью изолирован от транспорта. Возвращает список объектов `File` через `picker.getFiles()`.
|
||
- **Слой 2 (Фронтенд + Бэкенд)**: `uploadViaVM` передаёт файлы по одному через буфер на ВМ в RAM сессии Flask.
|
||
- **Слой 3 (drhider)**: логика обфускации забирает готовые файлы из `upload.backend.session.get_files(sid)` и запускает существующий пайплайн (`/api/drhider/<sid>`).
|
||
|
||
---
|
||
|
||
## 3. Этапы интеграции
|
||
|
||
### Этап 1. Синхронизация модуля ядра (`upload/`)
|
||
1. Заменить содержимое `upload/` в корне `drhider` на актуальную версию из `upload-platform/upload/`:
|
||
- `upload/backend/`: актуальные `upload_refs/` (поддержка `httpxTransport`, безопасный pull, санитизация `safe_name`) и `session/` (хранилище в RAM, TTL, блокировки).
|
||
- `upload/frontend/`: чистые ES-модули (`index.js`, `table/`, `upload/`, `zip/` на базе `fflate`).
|
||
2. Скопировать готовые бандлы из `upload-platform/dist/` в `site/static/dist/` (или настроить прямую раздачу из `upload/frontend` через `main_bp.py`).
|
||
|
||
### Этап 2. Проверка и настройка бэкенда (`site/routes/`)
|
||
1. Проверить регистрацию Blueprint в [site/routes/__init__.py](site/routes/__init__.py):
|
||
```python
|
||
app.register_blueprint(create_upload_refs_blueprint({
|
||
"apiPrefix": "/api",
|
||
"vmUploadPrefix": "https://contracts.kube5s.ru/drhider-upload/",
|
||
"maxFileBytes": 50 * 1024 * 1024,
|
||
"maxSessionBytes": 500 * 1024 * 1024,
|
||
"ttlSeconds": 30 * 60,
|
||
"pullRetries": 3,
|
||
"pullRetryDelay": 2,
|
||
}))
|
||
```
|
||
2. Убедиться, что [site/routes/api_bp.py](site/routes/api_bp.py) бесшовно использует сессии из обновлённого `upload.backend.session`.
|
||
|
||
### Этап 3. Обновление пользовательского интерфейса (`site/templates/index.html`)
|
||
1. Заменить устаревшую ручную вёрстку таблицы и инпутов на контейнер для монтирования Слой 1:
|
||
```html
|
||
<div id="file-picker-container"></div>
|
||
```
|
||
2. Подключить модуль `initFilePicker` и сконфигурировать фильтрацию по `.pdf, .doc, .docx, .txt, .md`.
|
||
3. Модифицировать обработчик кнопки «🛡️ Обфусцировать»:
|
||
- Вызов `uploadViaVM(files, { vmUploadUrl, backendUploadUrl, onFileStatus, onProgress })`.
|
||
- По завершении загрузки всех файлов — автоматический переход к Стек/Фазе 2: запуск SSE-стрима `/api/drhider/<sid>`.
|
||
4. Сохранить существующий трёхсекционный рендер обработки (Готово / Обрабатывается / Ожидают) и индикацию ETA/статистики LLM.
|
||
|
||
### Этап 4. Тестирование и валидация
|
||
1. **Автономные тесты модуля `upload`**:
|
||
- Запуск pytest для `upload/` внутри `drhider`.
|
||
2. **Интеграционные тесты `drhider`**:
|
||
- Запуск существующих тестов `tests/test_builder.py`, `tests/test_extractor.py`, `tests/test_replacer.py`, `tests/test_scanner.py`.
|
||
3. **Ручная/Smoke проверка сквозного цикла**:
|
||
- Выбор одиночного документа, папки и архива ZIP.
|
||
- Проверка пофайловой загрузки через буфер и немедленного удаления с ВМ.
|
||
- Проверка успешного прохождения двухпроходной обфускации и скачивания результирующего архива.
|
||
|
||
---
|
||
|
||
## 4. Контрольные точки (Definition of Done)
|
||
- [ ] Все тесты `pytest tests/` завершаются успешно (PASS).
|
||
- [ ] Отсутствуют временные файлы на диске (всё в RAM).
|
||
- [ ] Не нарушена логика отмены (`cancel`) и работы со стримами SSE.
|
||
- [ ] Сборка и синтаксис проверены через `py_compile`.
|
||
- [ ] Документ с отчётом о завершении зафиксирован в `History/upload-integration/`.
|