chore: import broken Phase-1 extension as received

Snapshot of /home/parf/Downloads/manifest.zip as delivered, before any
GSD-driven remediation. Contains a partially-broken first attempt at the
Russian SPEC "Тз расширение фаза1.md" (Phase 1 of operator-session-recorder).

Source layout:
- manifest.json — MV3 declaration with tabCapture/activeTab/downloads/etc.
- src/background/index.ts — service worker (video buffer + archive packaging)
- src/content/index.ts — rrweb + user-event logger
- src/popup/{index.html,index.ts,style.css} — Russian popup UI
- offscreen/{index.html,index.ts} — orphaned offscreen (see audit)
- vite.config.ts — inline plugin emitting a separate live offscreen.js
- generate-icons.js, icons/ — minimal PNG icons
- "Тз расширение фаза1.md" — authoritative Russian SPEC

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
2026-05-15 15:16:23 +02:00
commit 555eb0543f
21 changed files with 3935 additions and 0 deletions

View File

@@ -0,0 +1,200 @@
# Техническое задание: Браузерное расширение для записи сессий операторов
## Фаза 1 — Локальная запись + экспорт архива
---
## 1. Контекст и цель
Операторы работают в браузере и периодически совершают ошибки, причины которых сложно диагностировать.
Цель Фазы 1 — незаметно для оператора вести непрерывную запись его сессии,
а по нажатию кнопки — сохранять архив с данными сессии в папку «Загрузки» для передачи в поддержку.
---
## 2. Стек
| Компонент | Технология |
|---|---|
| Тип расширения | Chrome Extension, Manifest V3 |
| Service Worker | Background script (Manifest V3) |
| Захват экрана | `chrome.tabCapture` API |
| Захват DOM | `rrweb` (npm: rrweb) |
| Лог событий | Content Script |
| Упаковка архива | `JSZip` (npm: jszip) |
| Сохранение файла | `chrome.downloads` API |
| Хранение буфера | In-memory (Service Worker + Content Script) |
---
## 3. Структура расширения
```
extension/
├── manifest.json
├── background/
│ └── service-worker.js # координатор, буфер видео, упаковка архива
├── content/
│ ├── recorder.js # rrweb + лог событий
│ └── inject.js # инжектируется на каждую страницу
├── popup/
│ ├── popup.html # кнопка «Сохранить архив»
│ └── popup.js
└── libs/
├── rrweb.min.js
└── jszip.min.js
```
---
## 4. Что записывается
### 4.1 Кольцевой видеобуфер (последние 30 секунд)
- Захват активной вкладки через `chrome.tabCapture.capture()`
- Кодек: `video/webm; codecs=vp9`
- Битрейт: `400 000 bps` (~3 МБ/мин)
- `MediaRecorder` пишет чанки каждые `2000 мс`
- Буфер хранится в памяти Service Worker как массив `{ data: Blob, timestamp: number }`
- Чанки старше 30 секунд удаляются автоматически после каждого нового чанка
- Первый чанк (WebM-заголовок) **никогда не удаляется** — он нужен для корректного воспроизведения файла
**Ожидаемый размер в памяти:** ~1.52 МБ постоянно
### 4.2 DOM-снимки через rrweb (последние 10 минут)
- `rrweb.record()` пишет события в массив
- Хранится в Content Script, передаётся в Service Worker по запросу
- События старше 10 минут удаляются по таймеру каждые 60 секунд
- Маскирование чувствительных полей: все `input[type=password]` и поля с `data-sensitive="true"` маскируются через `rrweb` опцию `maskInputSelector`
**Ожидаемый размер в памяти:** ~13 МБ
### 4.3 Лог действий пользователя (последние 10 минут)
Каждая запись лога:
```json
{
"timestamp": 1716800000000,
"type": "click | input | navigation | error | network",
"target": "CSS-селектор элемента",
"value": "текст/значение (маскируется для паролей)",
"url": "текущий URL",
"meta": {}
}
```
Перехватываемые события:
- `click` — клик по любому элементу (фиксируется `target`, текст элемента)
- `input` — изменение значения поля (без паролей)
- `navigation``popstate`, `hashchange`, переходы по страницам
- `js_error``window.onerror`, `window.onunhandledrejection`
- `network_error``fetch` / `XMLHttpRequest` с кодом ответа `>= 400`
**Ожидаемый размер в памяти:** ~100300 КБ
### 4.4 Скриншот текущего состояния
- Делается в момент нажатия кнопки «Сохранить архив»
- Через `chrome.tabs.captureVisibleTab()`
- Формат: PNG, сохраняется как `screenshot.png` в архив
---
## 5. Кнопка «Сохранить архив» (Popup)
### UI
- Минималистичный popup: одна кнопка **«Сохранить отчёт об ошибке»**
- Под кнопкой: серый текст «Последние 30 сек видео + 10 мин лога»
- Состояния кнопки: `idle``Сохраняю...``Готово! ✓``idle` (через 3 сек)
### Поведение при нажатии
1. Сделать скриншот активной вкладки
2. Запросить у Service Worker: видеобуфер + лог событий
3. Запросить у Content Script: rrweb-снимки
4. Собрать архив (см. раздел 6)
5. Скачать архив через `chrome.downloads.download()`
6. Показать статус «Готово! ✓»
---
## 6. Структура архива
Имя файла: `session_report_YYYY-MM-DD_HH-MM-SS.zip`
```
session_report_2025-05-15_14-32-10.zip
├── video/
│ └── last_30sec.webm # склеенные чанки видеобуфера
├── rrweb/
│ └── session.json # массив DOM-событий rrweb
├── logs/
│ └── events.json # лог действий пользователя
├── screenshot.png # скриншот в момент сохранения
└── meta.json # метаданные сессии
```
Содержимое `meta.json`:
```json
{
"timestamp": "2025-05-15T14:32:10Z",
"url": "https://...",
"userAgent": "Chrome/...",
"extensionVersion": "1.0.0",
"videoBufferSeconds": 30,
"logDurationMinutes": 10,
"totalEvents": 143
}
```
---
## 7. Разрешения в manifest.json
```json
{
"permissions": [
"tabCapture",
"activeTab",
"downloads",
"scripting",
"storage"
],
"host_permissions": [
"<all_urls>"
]
}
```
> **Примечание:** `tabCapture` требует жеста пользователя при первом запуске.
> При первой установке расширение запрашивает разрешение явно.
---
## 8. Важные ограничения и решения
| Проблема | Решение |
|---|---|
| WebM без заголовка не воспроизводится | Первый чанк (header) хранится всегда, не удаляется из буфера |
| Service Worker выгружается через 30 сек простоя | Keepalive через `chrome.alarms` каждые 20 сек |
| `tabCapture` только для активной вкладки | Фиксируется при активации расширения; при смене вкладки — переподключение |
| Большой объём rrweb-данных | Лимит буфера: 5 000 событий; при превышении удаляются самые старые |
| Пароли и чувствительные данные | `maskInputSelector` в rrweb + фильтр в логгере событий |
---
## 9. Что НЕ входит в Фазу 1
- Отправка данных на сервер
- AI-диагностика
- Автоматическое создание тикетов
- Аналитический дашборд
- Запись звука
Эти функции — Фаза 2.
---
## 10. Критерии приёмки Фазы 1
- [ ] Расширение устанавливается в Chrome без ошибок
- [ ] Видеобуфер непрерывно работает на любой вкладке
- [ ] В буфере всегда есть не более 30 секунд видео
- [ ] rrweb пишет DOM-события без ошибок на типовых страницах (формы, таблицы, модальные окна)
- [ ] Лог событий фиксирует клики, навигацию и сетевые ошибки
- [ ] При нажатии кнопки архив скачивается в «Загрузки» за < 5 секунд
- [ ] Архив открывается, `last_30sec.webm` воспроизводится в браузере
- [ ] Пароли не попадают в лог и rrweb-снимки
- [ ] RAM-потребление расширения не превышает 50 МБ в фоне