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

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

- Статус документа: living document
- Актуально на: 2 апреля 2026 года
- Владелец: backend/platform-команда
- Пересмотр: при изменении production runtime, доменов, сервисов или deploy-контура
- Область применения: фактическое состояние production, инфраструктуры и активных репозиториев
- Связанные документы:
  - [Roadmap](./roadmap.md)
  - [Runbook эксплуатации и деплоя](../operations/deployment-runbook.md)
  - [Платформенный implementation status](../../specs/qadam-platform/implementation.md)

## 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](./execution-checkpoints.md) и [project change log](./project-change-log.md) как 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`.
