Files
photo-editor/docs/architecture/system-design-baseline.md
Coder 401969cfdb
Some checks failed
test / test (push) Failing after 24s
v2: модульный монолит — очередь, персистентность, безопасность, SSE, тесты
Реализация целевого дизайна (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/
2026-08-27 12:52:27 +07:00

14 KiB
Raw Permalink Blame History

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. Владелец загружает фото → видит превью → редактирует промптом (13 мин, фон) → результат в истории.
  2. Владелец увеличивает разрешение версии (несколько секунд) → результат в истории.
  3. Владелец возвращается к любой версии истории (дерево), продолжает правки с неё.
  4. Владелец удаляет версию каскадно (с потомками).
  5. Владелец получает подсказки промптов (из истории / от Codex).

Горизонт решений: один пользователь, LAN, один хост, один контейнер, горизонт планирования 612 месяцев. Выход за эти рамки — триггер пересмотра (см. реестр).


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 Обработка 6082 с на 512×512, 13 мин на больших; узкое место — вызов 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 МБ исходник; реальные файлы 16 МБ 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), редактирование ~1552k токенов/операция 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
Incomplete: None — все пункты чек-листа (объём и назначение; реестр доказательств; драйверы; написание; валидация) выполнены; изменены только документы docs/architecture/*.md, код не трогался.