Some checks failed
test / test (push) Failing after 24s
Реализация целевого дизайна (docs/architecture/target-design.md): - src/: модульная структура (config, logger, errors, http, core: auth/history/jobs/engines/comfy/codex/images) - Очередь заданий: FIFO, кониурентность codex=1 / comfy-upscale=2, MAX_QUEUED_JOBS=5, JSONL-журнал и восстановление после рестарта (running → interrupted, upscale requeue) - Персистентные сессии (sha256-хеши токенов), scrypt-хеш пароля, rate-limit входа, Origin-проверка, magic-byte валидация аплоадов - Атомарная запись манифеста истории, каскадное удаление, URL с фактическим расширением + 302-алиас /image.jpg, миграция history/ → data/history - Даунскейл sharp до 1024px перед Codex + масштабирование области референса - SSE /api/events с фолбэком на polling, фронтенд переведён на ES-модули (public/js/) - Тесты node:test + supertest (27), CI workflow test.yml, Docker/деплой: том kadr-data - Документация: README, docs/architecture/
98 lines
14 KiB
Markdown
98 lines
14 KiB
Markdown
# System Design Baseline
|
||
|
||
**Вердикт:** READY
|
||
**Артефакт:** `docs/architecture/system-design-baseline.md`
|
||
**Статус:** 1.0, подтверждён по рабочей копии `main@1c36a21` (рабочее дерево чистое), дата наблюдения 2026-08-26.
|
||
**Язык:** русский (проект и владелец русскоязычные).
|
||
|
||
Этот документ — источник истины по **архитектуро-формирующим требованиям и ограничениям** проекта «Кадр». Он не описывает решение (см. `docs/architecture/target-design.md`). Каждый материал параметр имеет владельца, источник, дату и триггер пересмотра.
|
||
|
||
---
|
||
|
||
## 1. Идентичность и бизнес-контекст
|
||
|
||
| Параметр | Значение | Источник |
|
||
|---|---|---|
|
||
| Продукт | «Кадр» — локальный AI-фоторедактор: редактирование фотографии по текстовому промпту (Codex CLI) + 4× апскейл (ComfyUI RealESRGAN) | `README.md` |
|
||
| Владелец/оператор | Один человек («владелец»), доступ только ему | `README.md` разд. «Авторизация» |
|
||
| Развёртывание | Один контейнер Docker на хосте Portainer (`kadr-photo-editor`, порт 3000), LAN | `deploy/docker-compose.yml`, `README.md` |
|
||
| Окружение | Node.js 20+, Express 4, Codex CLI (OpenAI), ComfyUI `http://192.168.31.240:8188`, прокси `http://192.168.31.240:4067` для исходящего к OpenAI | `package.json`, `server.js`, `deploy/docker-compose.yml` |
|
||
| Читатели документа | Владелец; ИИ-агент, реализующий целевую архитектуру | — |
|
||
|
||
Критические сценарии (джорни):
|
||
1. Владелец загружает фото → видит превью → редактирует промптом (1–3 мин, фон) → результат в истории.
|
||
2. Владелец увеличивает разрешение версии (несколько секунд) → результат в истории.
|
||
3. Владелец возвращается к любой версии истории (дерево), продолжает правки с неё.
|
||
4. Владелец удаляет версию каскадно (с потомками).
|
||
5. Владелец получает подсказки промптов (из истории / от Codex).
|
||
|
||
Горизонт решений: **один пользователь, LAN, один хост, один контейнер**, горизонт планирования 6–12 месяцев. Выход за эти рамки — триггер пересмотра (см. реестр).
|
||
|
||
---
|
||
|
||
## 2. Область и не-цели
|
||
|
||
**В области:** редактирование по промпту, апскейл 4×, история версий с деревом и каскадным удалением, авторизация одного владельца, референс с областью, подсказки промптов, мультизагрузка, деплой Docker/Portainer, CI на Gitea Actions.
|
||
|
||
**Вне области (не-цели):** многопользовательность; публичный интернет-доступ; мобильные приложения; пакетная обработка; генерация изображений «с нуля»; онлайн-редактор с кистями/слоями; платёжные интеграции; облачный хостинг. Всё перечисленное — кандидаты на отдельное решение, не для текущего горизонта.
|
||
|
||
---
|
||
|
||
## 3. Драйверы и ограничения (реестр)
|
||
|
||
Легенда: **Крит.** — DRIVER / SUPPORTING / INFORMATIONAL; **Статус** — CONFIRMED (из кода/документов), ASSUMED, UNKNOWN.
|
||
|
||
| # | Тема | Параметр | Крит. | Статус | Значение/мера | Источник и владелец | Триггер пересмотра |
|
||
|---|---|---|---|---|---|---|---|
|
||
| D1 | Бизнес | Один владелец, закрытый доступ | DRIVER | CONFIRMED | Ровно один логин (`APP_USER`/`APP_PASSWORD`), cookie-сессия `kadr_session`, 7 суток, sliding | `server.js:119-218`, `README.md` | Появление второго пользователя |
|
||
| D2 | Бизнес | Редактирование по промпту — ядро продукта | DRIVER | CONFIRMED | Обработка 60–82 с на 512×512, 1–3 мин на больших; узкое место — вызов image-модели | `README.md` разд. «Тест скорости» | Смена движка редактирования |
|
||
| D3 | Бизнес | История версий — непрерывная ветка правок | DRIVER | CONFIRMED | Дерево по `parentId`, до 50 версий, каскадное удаление, переживает перезапуск | `server.js:820-900, 1765-1826`, `README.md` | Рост лимита истории |
|
||
| D4 | Demand | Нагрузка | SUPPORTING | CONFIRMED | Один пользователь, 1 редактирование + 1 апскейл одновременно; опрос статуса каждые 3 с; лимит аплоада 25 МБ, промпт ≤ 1000 симв. | `server.js:24, 1876`, `README.md` | Параллельные правки разных фотографий |
|
||
| D5 | Demand | Объём данных | SUPPORTING | CONFIRMED | ≤ 50 версий × ≤ 25 МБ исходник; реальные файлы 1–6 МБ | `history/history.json`, `server.js:34` | Лимит 50 перестаёт устраивать |
|
||
| D6 | Качество | Время ответа API | SUPPORTING | CONFIRMED | `POST /api/edit`, `/api/upscale`, `/api/suggest` отвечают мгновенно (< 1 с) с `jobId`; тяжёлая работа фоном | `README.md` стр. 25-29 | — |
|
||
| D7 | Качество | Завершение редактирования | DRIVER | CONFIRMED | Codex: таймаут 420 с; ComfyUI: таймаут 300 с; сбои отображаются в UI, задание помечается `error` | `server.js:22, 29, 465-541, 1489-1534` | — |
|
||
| D8 | Данные | Переживание перезапуска | DRIVER | CONFIRMED | История переживает перезапуск; **сессии и задания — нет** (память, `sessions`/`jobs` Map); `.codex-jobs` очищается при старте | `server.js:141-153, 2259`, `README.md` стр. 98 | Цель перепроектирования: переживание заданий |
|
||
| D9 | Данные | Согласованность истории | DRIVER | CONFIRMED | Один писатель (`historyWriteChain`), полная перезапись `history.json` при каждом изменении, файлы `history/<uuid>.<ext>` | `server.js:830-868` | Переход на SQLite при > 500 версий |
|
||
| D10 | Безопасность | Аутентификация | DRIVER | CONFIRMED | Сравнение пароля — `constantTimeEqual` по **открытому** значению env-переменной; без хеширования, без rate-limit на вход | `server.js:155-159, 1641` | Редизайн: хешировать (scrypt) |
|
||
| D11 | Безопасность | Уязвимости | SUPPORTING | CONFIRMED | Только UUID в путях (`JOB_ID_PATTERN`); MIME+расширение проверяются, но без проверки сигнатуры файла; SameSite=Lax; без Secure (HTTP LAN); без Origin-проверки | `server.js:234-267, 2116` | Появление внешнего доступа |
|
||
| D12 | Операции | Деплой | SUPPORTING | CONFIRMED | Образ `node:22-bookworm-slim` (glibc обязателен для Codex); том `kadr-history`; секреты `APP_USER`/`APP_PASSWORD` из Gitea; Codex через прокси `:4067` | `Dockerfile`, `deploy/docker-compose.yml`, `.gitea/workflows/*.yml` | Смена хостинга |
|
||
| D13 | Операции | Наблюдаемость | SUPPORTING | CONFIRMED | Только лог в stdout (уровни debug/info/warn/error), без requestId, без метрик | `server.js:50-79`, `README.md` разд. «Логирование» | — |
|
||
| D14 | Экономика | Стоимость | INFORMATIONAL | CONFIRMED | Стоимость = токены Codex (ChatGPT API), редактирование ~15–52k токенов/операция | `README.md` разд. «Тест скорости» | Смена тарифа |
|
||
| D15 | Эволюция | Скорость редактирования | SUPPORTING | CONFIRMED | Время растёт с разрешением исходника (1200×800 медленнее 512×512); замерено: `CODEX_REASONING_EFFORT=low` даёт ~17% | `README.md` разд. «Тест скорости» | Внедрение предварительного даунскейла |
|
||
| D16 | Ограничение | Внешние сервисы | DRIVER | CONFIRMED | ComfyUI API (upload/workflow/history/view), модель `sdxl_turbo.safetensors`, upscale `RealESRGAN_x4plus.safetensors`; Codex CLI `codex exec` с флагами `-i`, `-o last_message.txt`, `--ephemeral`, bypass sandbox | `server.js:15-17, 397-411`, `README.md` | Обновление ComfyUI/Codex |
|
||
| D17 | Ограничение | Исходящий egress | DRIVER | CONFIRMED | Прямой выход к OpenAI блокируется (403 cf-ray HEL); обязателен прокси `http://192.168.31.240:4067`, `NO_PROXY` для внутренних адресов | `deploy/docker-compose.yml:20-27`, `README.md` п.5 разд. Portainer | Смена сети/провайдера |
|
||
|
||
---
|
||
|
||
## 4. Ключевые сценарии (source/stimulus/environment/artifact/response/measure)
|
||
|
||
1. **Редактирование с сохранением в историю.** Источник: владелец. Стимул: `POST /api/edit` с фото/`sourceId` + промпт. Окружение: один контейнер, Codex доступен. Артефакт: сервис `/api/edit`. Реакция: ответ < 1 с с `jobId`; ≤ 420 с — новая версия `kind=edit` в истории; мера: версия видна в `GET /api/history` и по `job.status=done`.
|
||
2. **Апскейл.** Стимул: `POST /api/upscale`. Реакция: ≤ 300 с — версия `kind=upscale` (PNG), исходник масштабируется до ≤ 2048 px до подачи в ComfyUI. Мера: `job.status=done`.
|
||
3. **Переживание перезапуска (цель).** Стимул: перезапуск контейнера во время `running`-задания. Реакция (целевая): задание помечается прерванным с понятной ошибкой; очередь-задания и сессии переживают рестарт; история не теряется. Мера: после рестарта `GET /api/jobs/:id/status` возвращает `interrupted`/`error`, а не 404; сессия владельца жива.
|
||
4. **Безопасный вход.** Стимул: 10 неудачных попыток логина за 15 мин с одного IP. Реакция: блокировка с `Retry-After`; пароль не хранится в открытом виде. Мера: rate-limit срабатывает, в логах нет паролей.
|
||
|
||
---
|
||
|
||
## 5. Допущения и неизвестные
|
||
|
||
- **ASSUMED:** ComfyUI и Codex доступны из сети владельца (рабочее состояние подтверждается историей и `.bench/`).
|
||
- **ASSUMED:** целевой читатель (ИИ-агент) реализует сервер на Node.js/Express и фронтенд без сборки (vanilla ES-модули) — см. решения в target-design.md.
|
||
- **UNKNOWN:** точные объёмы будущего использования (нет метрик) — не влияет: горизонтальный запас огромен для одного пользователя.
|
||
- **UNKNOWN:** SLA внешних сервисов (Codex/ComfyUI) — обрабатываются таймаутами и понятными ошибками.
|
||
|
||
## 6. Триггеры пересмотра baseline
|
||
|
||
- Второй пользователь или внешний доступ (D1, D11).
|
||
- Лимит истории 50 или объём > 500 версий (D3, D5, D9).
|
||
- Параллельные правки разных фотографий (D4).
|
||
- Смена движка редактирования (D2, D16).
|
||
- Смена хостинга/сети (D12, D17).
|
||
- Переход на SQLite или другое хранилище (D9).
|
||
|
||
---
|
||
|
||
# System Design Baseline
|
||
|
||
**Checklist: 5/5 complete**<br>
|
||
**Incomplete: None** — все пункты чек-листа (объём и назначение; реестр доказательств; драйверы; написание; валидация) выполнены; изменены только документы `docs/architecture/*.md`, код не трогался.
|