Qadam Roadmap
проектdocs/project/current-state.md

Текущее состояние проекта Qadam

Обновлён 14 апр. 2026 г., 17:16 · 0 комментариев

Текущее состояние проекта Qadam

Паспорт документа

  • Статус документа: living document
  • Актуально на: 2 апреля 2026 года
  • Владелец: backend/platform-команда
  • Пересмотр: при изменении production runtime, доменов, сервисов или deploy-контура
  • Область применения: фактическое состояние production, инфраструктуры и активных репозиториев
  • Связанные документы:

1. Краткий вывод

Qadam уже находится не в стадии заготовки, а в стадии управляемого MVP-каркаса с живым production, закрытым security-hardening пакетом, работающим OpenAPI-контуром и физически выделенными рабочими репозиториями qadam-core и qadam-web.

Главный технический разрыв проекта сейчас не в отсутствии фич, а в двух местах:

  • buyer/seller/admin потоки ещё не доведены до полностью предсказуемого UX;
  • production уже переведён на qadam-core и qadam-web, а delivery-контур вошёл в смешанную фазу: API уже работает через image-based container runtime, но qadam-web и qadam-roadmap ещё остаются на host-side systemd.

Дополнительно важно: текущая машина больше не должна восприниматься как единственный stage-контур для UI-проверок. Согласованный frontend/backend release теперь рассматривается через отдельный stage-сервер, который забирает main внешним автоматическим deploy-процессом.

2. Что уже работает

Инфраструктура и домены

  • Публичный продукт доступен на https://qadam.2fab.app.
  • Портал документации доступен на https://qadam-roadmap.2fab.app.
  • Для обоих доменов выпущены сертификаты Let's Encrypt.
  • На сервере настроены systemd-сервисы qadam-api, qadam-api-container, qadam-web и qadam-roadmap.
  • На сервере дополнительно настроен systemd-сервис qadam-core-runner для Gitea Actions.
  • На сервере дополнительно настроены qadam-monitor.service и qadam-monitor.timer для внешнего uptime/TLS monitoring.
  • На сервере дополнительно настроены qadam-backup.service и qadam-backup.timer для автоматического backup baseline и off-host retention.
  • qadam-core-runner больше не хранит тяжёлый cache/workspace на корневом разделе: runner cache и hostexecutor workspace перенесены в /tmp, чтобы CI не конкурировал с production runtime за root disk.
  • На сервере установлен Docker Engine; его data-root вынесен на отдельный диск /mnt/qadam100gb/docker, чтобы image build и container smoke не конкурировали с host runtime за корневой раздел.
  • Внешний трафик обслуживает host-level nginx.
  • Локально на хосте установлены PostgreSQL 17 и Redis.
  • Публичный /api/* трафик qadam.2fab.app теперь идёт через nginx upstream qadam_api_backend на 127.0.0.1:5002, где работает qadam-api-container.service.
  • Legacy qadam-api.service больше не обслуживает production-трафик и сохранён как rollback-контур на 127.0.0.1:5001.

Репозитории и архитектура

  • Текущий production runtime на сервере живёт в /data/qadam-core и /data/qadam-web.
  • Отдельный backend/bootstrap-репозиторий создан и запушен в Gitea:
    • https://git.2fab.app/eldar/qadam-core.git
  • Отдельный frontend/bootstrap-репозиторий создан и запушен в Gitea:
    • https://git.2fab.app/eldar/qadam-web.git
  • Старый checkout /data/uzbek остаётся на сервере только как legacy-копия и больше не является production source of truth.
  • qadam-core содержит apps/api, packages/prisma, packages/shared, docs, specs.
  • qadam-web содержит apps/web, отдельный сервис документации apps/roadmap, локальный OpenAPI artifact openapi/openapi.json, свой build-конфиг и отдельный frontend handoff-документ.
  • Отдельная памятка для frontend-команды зафиксирована в docs/frontend/frontend-handoff.md; в qadam-web/docs/frontend-handoff.md лежит её короткая локальная версия для repo onboarding.
  • qadam-web теперь рассматривается как отдельный рабочий контур для внешней frontend-команды, а qadam-core — как источник истины по API, документации и платформенной логике.
  • локальная разработка и change packages готовятся здесь, но stage-проверочный контур живёт отдельно и должен обновляться через merge в main, а не как ручной обязательный deploy с этой машины.
  • Product frontend больше не несёт roadmap-портал внутри apps/web; портал вынесен в отдельный standalone-сервис apps/roadmap.
  • Основной web runtime уже живёт в apps/web/src/app и FSD-подобных слоях src/shared, src/entities, src/features, src/widgets, src/views.
  • Backend публикует Swagger UI на /api/docs и OpenAPI JSON на /api/openapi.json.
  • qadam-web уже умеет генерировать frontend contract types из собственного openapi/openapi.json, а не из backend-исходников.
  • qadam-core и qadam-web уже являются каноническими рабочими репозиториями и реальным production runtime.
  • В qadam-core теперь работает repo-side Gitea Actions workflow Quality Gate на self-hosted runner qadam-core-runner-01.
  • Self-hosted runner qadam-core-runner-01 теперь использует XDG_CACHE_HOME=/tmp/act_runner-cache и TMPDIR=/tmp/act_runner-tmp, поэтому Prisma engines и act workspace не забивают /.
  • qadam-core-runner-01 теперь дополнительно входит в группу docker, поэтому repo-side workflow может собирать API image и прогонять container smoke без ручного root-вмешательства.
  • qadam-core-runner-01 уже имеет registry-auth к git.2fab.app, поэтому repo-side workflow может не только собрать API image, но и публиковать versioned tags в Gitea Container Registry.
  • Data layer централизован в @repo/prisma: schema, migrations, generated client, seed и select helpers лежат в одном пакете.
  • Observability-контур уже использует Pino, optional Axiom transport и append-only EventLog для продуктовых событий.
  • Исторические implementation plans из plans/ проаудированы и формально переведены в архивный, а не канонический слой документации.
  • Документационный контур усилен отдельными runbook по backup/restore, incident response, environment matrix, post-deploy checklist, ownership model и change-package process.
  • У проекта теперь есть отдельные execution checkpoints и project change log как operational delivery-слой поверх roadmap.

Реализованные прикладные области

  • Авторизация: legacy register/login/me/logout/refresh, плюс новый registration flow check-availability, register/buyer, register/seller, password reset и add-buyer-role.
  • Каталог: публичная выдача, карточка айтема, получение отзывов, subjects, locations.
  • Публичный каталог во frontend уже работает через searchParams-based filter context, SSR-prefetch и infinite scroll без старого "Загрузить ещё"-паттерна.
  • Seller area: профиль с duplicate-safe contact updates, адреса, Telegram verify/unbind, айтемы, лиды, сотрудники, onboarding.
  • Buyer area: профиль, дети, интересы, лиды, отзывы и multi-role buyer profile flow.
  • Admin area: лиды, статистика, модерация, reference data и seller account status management.
  • Tracking: базовая отправка событий.
  • Аналитика и observability: структурные JSON-логи, EventLog и базовый tracking endpoint.
  • Monitoring runtime: публичные health/live/ready probes и loopback-only Prometheus-compatible /metrics.
  • Alert delivery baseline: operational Telegram-канал уже подключён через TELEGRAM_BOT_TOKEN и TELEGRAM_ALERT_CHAT_ID.
  • External monitoring baseline: qadam-monitor проверяет product web, API readiness, roadmap web и TLS по обоим доменам, а изменения статуса отправляет в Telegram-канал.
  • Backup baseline: qadam-backup ежедневно снимает PostgreSQL dump, API/roadmap storage snapshot, runtime config, локально верифицирует артефакты и выгружает off-host archive в S3-compatible storage.
  • Docker migration baseline: для qadam-core/api уже подтверждён первый container smoke через apps/api/Dockerfile и deploy/compose/docker-compose.api-runtime.yml; контейнер проходит migrate и отвечает 200 на /api/v1/health.
  • Для qadam-core/api теперь есть канонический image build script deploy/scripts/build-api-image.sh и compose-based shadow smoke deploy/scripts/smoke-api-runtime-compose.sh, который поднимает container runtime на 127.0.0.1:5002 поверх production env без остановки host-level qadam-api.
  • Для qadam-core/api уже подтверждён Gitea Container Registry namespace git.2fab.app/eldar/qadam-core-api: image можно не только собрать локально, но и опубликовать и затем поднять через registry-tag в shadow smoke.
  • Для qadam-core/api уже подготовлен и применён reversible cutover path: host nginx использует named upstream qadam_api_backend, production API переведён на qadam-api-container.service, а rollback обратно на qadam-api.service стандартизирован отдельным скриптом.
  • Для qadam-web уже добавлен product web runtime image baseline: лёгкий Dockerfile собирает image из .next/standalone, registry namespace git.2fab.app/eldar/qadam-web-app подтверждён publish/pull smoke, а shadow runtime успешно поднимается на 127.0.0.1:3002 от registry image без локального next build на production-сервере.
  • Repo-side quality gate qadam-core теперь дополнен отдельным API Container Smoke: он поднимает временные PostgreSQL и Redis контейнеры, запускает migrations внутри API image и проверяет health/ready и metrics без подключения к production БД.
  • Uploads: product media теперь уходят через S3-compatible storage в DigitalOcean Spaces; backend возвращает готовый публичный URL, а локальный /uploads/images/... остаётся только как compatibility/fallback-контур для local driver.
  • Public seller profile backend теперь публикует санитизированный публичный контракт и explicit seo block (canonicalUrl, openGraph, jsonLd) для SSR/metadata слоя; непубличный seller должен отвечать 404.
  • Минимальный stage-oriented web smoke baseline уже не только добавлен в qadam-web, но и подтверждён живым прогоном на stage: 10 из 10 проверок (runtime health, public pages, public item, public seller profile, buyer/seller/admin dashboards) прошли успешно.
  • Внутренний портал roadmap/docs: просмотр markdown из docs/, upload, delete, комментарии.

3. Что реализовано частично

Buyer-поток

  • Backend buyer profile flow уже переведён на account-centric контракт: POST/PATCH /me/profile, GET/POST/PATCH/DELETE /me/children, PATCH /me/interests.
  • Multi-role сценарий теперь поддержан на API-уровне через POST /auth/add-buyer-role.
  • Review flow на backend теперь тоже перестал быть "автопубликацией": новые отзывы создаются в PENDING, а buyer cabinet получает status и moderationNote через GET /me/reviews.
  • На web-слое всё ещё почти нет полноценных smoke/e2e-проверок buyer-потока.

Seller-поток

  • Backend seller onboarding и профиль уже расширены: POST /auth/register/seller, PATCH /seller/profile, address CRUD, POST /seller/telegram/verify, DELETE /seller/telegram.
  • Item lifecycle на backend теперь идёт через явный DRAFT -> PENDING -> ACTIVE/REJECTED: seller создаёт/редактирует айтем в draft, явно отправляет его на модерацию, может отозвать pending-айтем обратно в draft, а seller item responses получают latestModerationRecord с последней причиной/комментарием модерации.
  • Для seller review surface backend уже публикует GET /seller/reviews, PATCH /seller/reviews/:id/reply, POST /seller/reviews/:id/complaint: продавец видит статус отзыва, может ответить на опубликованный отзыв в пределах 48 часов и может отправить спорный отзыв на повторную модерацию через complaint-driven переход в PENDING_MODERATION.
  • Для seller notifications backend теперь публикует GET/PATCH /seller/notification-settings, автоматически создаёт дефолтные notification settings для исторических seller-аккаунтов и при новом лиде сначала пытается Telegram-доставку, а затем при необходимости переходит на SMTP-capable email fallback.
  • Seller Telegram onboarding на backend больше не сводится к ручному вводу кода без потока выдачи: seller получает GET /seller/telegram/connect-link, бот принимает POST /api/v1/internal/telegram/webhook, выдаёт одноразовый 6-значный код и POST /seller/telegram/verify теперь жёстче обрабатывает ALREADY_VERIFIED, CODE_INVALID/CODE_EXPIRED и TELEGRAM_ALREADY_BOUND.
  • В seller notification settings sellerEmail теперь резолвится из seller profile email с fallback на account email, чтобы email fallback не зависел только от auth-слоя.
  • notifyStatusChangeTelegram больше не является пустым флагом: owner-facing status-change уведомления уже работают, когда статус лида меняет активный SELLER_STAFF, а список отслеживаемых статусов задаётся через SELLER_STATUS_CHANGE_NOTIFY_STATUSES и по умолчанию включает CONTACTED, ENROLLED, REJECTED.
  • CRUD по лидам и сотрудникам реализован, но seller UX и smoke/e2e-контур по-прежнему требуют продуктовой доводки.
  • Не все продуктовые правила доведены до финального UX и admin-governance слоя.

Admin-поток

  • Страницы и API есть; item moderation теперь принимает решения только по PENDING айтемам и публикует историю последних seller-visible moderation records.
  • Admin seller directory теперь публикуется через GET /admin/sellers с фильтрами и item counters, поэтому status management больше не держится на ручном знании sellerId.
  • Для review moderation на backend теперь есть отдельный admin surface: GET /admin/moderation/reviews, GET /admin/moderation/reviews/:id, PATCH /admin/moderation/reviews/:id; seller complaint flow уже подаёт туда спорные отзывы как PENDING_MODERATION.
  • После admin status change seller-facing защищённые маршруты возвращают явные ACCOUNT_UNDER_REVIEW / ACCOUNT_BLOCKED, а не generic token error.
  • Public seller profile на backend больше не должен переиспользовать приватный seller profile shape как есть: наружу уходит отдельный public contract с очищенными полями, public-only адресами и backend-generated SEO metadata.

4. Что ещё не реализовано

  • SMS/phone verification.
  • Frontend adoption seller Telegram onboarding flow и stage/browser smoke по нему ещё не доведены до end-to-end product UX.
  • SMTP-capable email fallback для seller lead notifications уже реализован в коде, но включение конкретного provider/env на целевом runtime остаётся отдельным operational шагом.
  • Owner-facing status-change notifications для seller уже включены на backend только для non-owner actor (SELLER_STAFF); дальнейшее расширение на новые actor/source-of-change сценарии остаётся отдельным продуктовым пакетом.
  • Карта поиска офлайн-центров.
  • Полноценный CPL billing.
  • CRM-слой v1.0.
  • Онлайн-платежи и транзакционная модель.
  • Нормальный e2e-контур для веба.
  • Image-based delivery и docker/image-based runtime.
  • CDN/fronting и lifecycle policy поверх уже включённого object storage для product media; roadmap storage пока осознанно остаётся локальным.

5. Состояние инфраструктуры на текущем сервере

Сервисы

  • qadam-api: legacy rollback-сервис, запускается из /data/qadam-core/apps/api/dist/main.js и держится остановленным, пока public upstream обслуживает контейнер.
  • qadam-api-container: production runtime API из registry image на 127.0.0.1:5002.
  • qadam-web: запускает standalone-сборку product frontend Next.js на 127.0.0.1:3000.
  • qadam-web: для product frontend дополнительно существует container shadow runtime на 127.0.0.1:3002, но production-трафик пока обслуживает host-level systemd сервис на 127.0.0.1:3000.
  • qadam-roadmap: запускает standalone-сборку сервиса документации на 127.0.0.1:3001.
  • qadam-monitor: запускает /data/qadam-core/scripts/monitor-runtime.mjs по systemd timer.
  • qadam-backup: запускает /data/qadam-core/scripts/backup-runtime.mjs по systemd timer.
  • qadam-api: после security-hardening и после cutover остаётся только rollback-сервисом на 127.0.0.1:5001, а не основным public runtime.
  • qadam-api: дополнительно публикует GET /api/v1/health/live, GET /api/v1/health/ready и loopback-only GET /api/v1/metrics.
  • nginx: проксирует qadam.2fab.app и qadam-roadmap.2fab.app.
  • Docker Engine использует data-root=/mnt/qadam100gb/docker; старый /var/lib/docker больше не является каноническим storage для контейнерного runtime.

Важные системные файлы

  • /etc/systemd/system/qadam-api.service
  • /etc/systemd/system/qadam-api-container.service
  • /etc/systemd/system/qadam-web.service
  • /etc/systemd/system/qadam-roadmap.service
  • /etc/systemd/system/qadam-monitor.service
  • /etc/systemd/system/qadam-monitor.timer
  • /etc/systemd/system/qadam-backup.service
  • /etc/systemd/system/qadam-backup.timer
  • /etc/nginx/sites-available/qadam.2fab.app.conf
  • /etc/nginx/sites-available/qadam-roadmap.2fab.app.conf
  • /etc/nginx/conf.d/qadam-api-upstream.conf
  • /etc/docker/daemon.json
  • /etc/qadam/qadam.env
  • /etc/qadam/qadam-api-runtime.env
  • /etc/qadam/qadam-monitor.env
  • /etc/qadam/qadam-backup.env
  • /etc/qadam/qadam-roadmap.env

Портал документации

  • Сейчас читает markdown из /data/qadam-core/docs через QADAM_PROJECT_ROOT=/data/qadam-core.
  • Runtime портала больше не обслуживается через qadam-web; домен qadam-roadmap.2fab.app идёт напрямую в отдельный сервис qadam-roadmap.
  • Внутренние относительные markdown-ссылки внутри канонической документации теперь открываются внутри roadmap-портала, включая переходы в связанные specs и docs/Agents.
  • На главной roadmap-портала теперь есть отдельный блок Что сейчас должна сделать frontend-команда, который автоматически собирается из docs/frontend/frontend-change-log.md.
  • Архивные processed plans лежат в /data/qadam-core/plans/archived/2026-03-28-integrated и по умолчанию скрыты в библиотеке roadmap-портала; они показываются только при включённом Show archived.
  • Загруженные документы хранит в /var/lib/qadam-roadmap/uploads.
  • Комментарии хранит в /var/lib/qadam-roadmap/comments.json.
  • Ответ frontend-команды по backend-пакетам хранит в /var/lib/qadam-roadmap/frontend-package-feedback.json как operational overlay со статусами pending / in_progress / done / ignored.
  • Доступ закрыт basic auth.
  • qadam-roadmap.2fab.app больше не зависит от /data/uzbek/docs.

6. Качество и технический долг

Что уже в хорошем состоянии

  • Production-домены и HTTPS работают стабильно.
  • API и web собираются и запускаются на хосте.
  • Security review от 2026-03-27 закрыт по критичным и high-замечаниям.
  • qadam-core проходит install + check-types + test + build + export:openapi.
  • qadam-web проходит install + generate:api-contract + check-types + build.
  • apps/roadmap проходит check-types + build как отдельный runtime внутри репозитория qadam-web.
  • Repo-side Gitea workflow Quality Gate для qadam-core уже подтверждён первым успешным run на self-hosted runner.
  • React/Next production-сборка работает на актуальном src/app, а не на legacy-дереве.
  • Базовый машиночитаемый API-контракт поднят через OpenAPI/Swagger и доступен на production-домене.
  • Prisma data layer оформлен как отдельный workspace-пакет с migrations, seed и generated client.
  • Structured logging и product event logging уже описываются отдельными каноническими документами по observability и Prisma.
  • В CI появился quality gate pnpm check:api-contract для проверки drift OpenAPI artifact и generated web types.
  • В qadam-core появился pnpm check:docs для проверки паспорта документов, относительных markdown-ссылок и синхронизации с docs/README.md.
  • В qadam-web уже работают searchParams-based filters, infinite scroll каталога, SVGR icons и базовый auth-layer через proxy.ts.
  • Для срезов auth, leads, catalog, reviews, public seller profile и buyer reviews cabinet web уже использует generated OpenAPI response types вместо ручных response-интерфейсов.
  • Seller leads экран, reviews block и submit-review flow уже сидят на общем query/mutation слое.
  • Production-фактический runtime уже переведён на qadam-core и qadam-web.
  • Roadmap-портал теперь рендерит markdown через полноценный GFM-совместимый слой, а не через упрощённый самодельный форматтер.
  • В qadam-web добавлен минимальный stage-oriented smoke baseline pnpm smoke:web:flows, который проверяет runtime health, публичные страницы и buyer/seller/admin dashboard flows через реальный login.

Что требует ближайшей доработки

  • Buyer profile flow всё ещё не доведён до законченного продуктового сценария.
  • Полноценного regression/e2e-контура во frontend всё ещё нет: сейчас есть только минимальный stage-oriented smoke baseline без browser-level пользовательских интеракций.
  • Generated contract layer на backend уже полностью покрывает admin API; во frontend нужно дожать именно adoption и cleanup остаточного legacy API-layer.
  • В qadam-web остаются исторические дублирующиеся слои components, lib, src/components, src/lib, которые нужно целенаправленно убрать.
  • В qadam-web ещё остались прямые fetch-пути и конкурирующие API-слои, особенно в admin/reference-срезах.
  • Frontend auth/register UI ещё не синхронизирован до конца с новым registration API и buyer profile flow из qadam-core.
  • Репозиторий qadam-web теперь содержит два приложения с разной зоной ответственности: apps/web для продуктового frontend и apps/roadmap для внутреннего сервиса документации. Это нужно учитывать в CI и handoff.
  • На сервере всё ещё лежит legacy checkout /data/uzbek, и его нужно не использовать как рабочую площадку новой разработки.
  • Image-based release для новых репозиториев ещё не доведён до полного рабочего контура.
  • Для qadam-core/api уже есть рабочий image/container runtime с живым production cutover, а для qadam-web уже подтверждён registry-backed shadow runtime; при этом product web и qadam-roadmap пока всё ещё обслуживают production через host-based systemd.
  • Нужен более зрелый analytics backlog поверх уже существующего EventLog и observability-контура.

7. Каноническая модель деплоя

На сегодня канонический production-сценарий для этого сервера такой:

  1. Обновление qadam-core и qadam-web.
  2. Проверка qadam-core, экспорт OpenAPI и применение Prisma migrations.
  3. Для API: сборка/publish image, обновление QADAM_API_IMAGE в /etc/qadam/qadam-api-runtime.env и cutover через qadam-api-container.service.
  4. Для product web и roadmap: пока ещё сборка qadam-web/apps/web и qadam-web/apps/roadmap с боевыми env и запуск через systemd.
  5. Reverse proxy через host-level nginx, где /api/* уже идёт через upstream qadam_api_backend, а /* и qadam-roadmap пока остаются на host-level сервисах.
  6. TLS через Let’s Encrypt и certbot.

Важно: runtime уже переведён на split-репозитории, а production-контур стал смешанным: API уже работает через image-based container runtime, qadam-web уже имеет подтверждённый registry-backed shadow runtime, но полный docker/image-based delivery для product web и qadam-roadmap ещё не завершён.

Отдельно от этого production runbook теперь действует release-модель для stage:

  • backend и frontend доводятся до merge-ready состояния в своих репозиториях;
  • после согласования обе стороны мержат изменения в main;
  • отдельный stage-сервер автоматически подтягивает main и разворачивает UI-проверочный контур;
  • поэтому текущая машина не должна считаться обязательной финальной точкой для ручного frontend stage deploy.

8. Главные риски

  • Риск случайной разработки в legacy checkout /data/uzbek, который больше не должен считаться рабочим репозиторием.
  • Риск отсутствия web regression-защиты: фронтенд без e2e/smoke-покрытия будет ломаться незаметно.
  • Риск ложного ощущения "MVP уже готов": функциональность есть, но не все критичные потоки доведены до предсказуемого UX.
  • Риск конфигурационного дрейфа между уже контейнеризированным api и всё ещё host-based runtime для qadam-web/qadam-roadmap.