проектdocs/project/execution-checkpoints.md
Execution checkpoints проекта
Обновлён 14 апр. 2026 г., 17:16 · 0 комментариев
Execution checkpoints проекта
Паспорт документа
- Статус документа: living document
- Актуально на: 2 апреля 2026 года
- Владелец: backend/platform-команда
- Пересмотр: при изменении статуса этапов, завершении change package или пересборке delivery-плана
- Область применения: операционный контроль поэтапной реализации проекта с фиксацией факта исполнения
- Связанные документы:
Цель документа
Roadmap отвечает на вопрос “куда идём”. Этот документ отвечает на вопрос “что уже закрыто по факту, что в работе и что ещё не начато”.
Каждый checkpoint должен обновляться только по факту исполнения, а не по обещанию.
Этот документ в детальном виде покрывает активные и ближайшие execution-пакеты фаз A и B, а также delivery maturity. Фазы C, D и E из roadmap пока остаются стратегическими и не дробятся на checkpoint'ы до закрытия MVP hardening, чтобы не создавать ложную детализацию.
Статусы
[x] completed— выполнено и подтверждено кодом, runtime или документально[~] in progress— активная работа идёт, но exit criteria ещё не закрыты[ ] planned— запланировано, но не начато[!] blocked— работа упёрлась во внешний или внутренний blocker
1. Foundation и transferability
CP-001 — Split-репозитории и production cutover
- Статус:
[x] completed - Суть:
qadam-coreиqadam-webвыделены, production переведён на них - Факт исполнения:
- runtime работает из
/data/qadam-coreи/data/qadam-web - legacy
/data/uzbekбольше не production source of truth
- runtime работает из
- Доказательства:
CP-002 — Roadmap вынесен в отдельный сервис
- Статус:
[x] completed - Суть:
qadam-roadmapотделён от product web - Факт исполнения:
- отдельный
systemdunitqadam-roadmap - отдельный runtime
qadam-web/apps/roadmap https://qadam.2fab.app/roadmapвозвращает404
- отдельный
- Доказательства:
CP-003 — Канонический docs-layer и стандарт документации
- Статус:
[x] completed - Суть: документация разложена по разделам, введён
Паспорт документа, работает перелинковка - Факт исполнения:
- канонический слой живёт в
qadam-core/docs - roadmap-портал читает живые markdown-файлы
- действует Стандарт документации
- канонический слой живёт в
- Доказательства:
CP-004 — Ops/governance baseline для handover
- Статус:
[x] completed - Суть: закрыты базовые runbook и governance-пробелы по эксплуатации, ownership и change package
- Факт исполнения:
- добавлены backup/restore, incident response, environment matrix, post-deploy checklist
- зафиксированы ownership model и change package standard
- Доказательства:
CP-005 — Docs quality gate
- Статус:
[x] completed - Суть: у документационного слоя есть исполнимая машинная проверка
- Факт исполнения:
- в
qadam-coreсуществует командаpnpm check:docs - она проверяет паспорт документа и относительные markdown-ссылки
- в
- Доказательства:
package.jsonиscripts/check-docs.mjsвqadam-core
CP-006 — Backend test и quality gate stabilization
- Статус:
[x] completed - Суть: довести backend test contour и merge gates до предсказуемо зелёного состояния после auth/registration/openapi drift
- Факт исполнения:
pnpm -C /data/qadam-core testпроходит штатно- контрактно-чувствительные spec'и
jwt-auth.guardи OpenAPI schemas синхронизированы с текущей реализацией - backend change packages больше не стартуют из состояния с красным test gate
- Exit criteria:
pnpm -C /data/qadam-core testпроходит штатно- контрактно-чувствительные spec'и auth/profile/guards синхронизированы с текущей реализацией
- backend change packages закрываются без ручных оговорок по test gate
- Доказательства:
CP-007 — Repo-side CI gate и PR review discipline
- Статус:
[x] completed - Суть: перевести quality gate из только локального процесса в обязательный репозиторный workflow и зафиксировать PR review/security gate как формальный контур
- Факт исполнения:
- в
qadam-coreдобавлен.gitea/workflows/quality-gate.yml - в
qadam-coreдобавлен.gitea/PULL_REQUEST_TEMPLATE.md - governance и CI rules синхронизированы с обязательным repo-side quality gate и security review checklist
- на сервере поднят
act_runnerкакsystemd-сервисqadam-core-runner - repo runner
qadam-core-runner-01зарегистрирован в Gitea и находится в статусеonline - первый workflow run
Quality Gateдляqadam-coreзавершился в Gitea со статусомsuccess
- в
- Exit criteria:
- существует обязательный workflow, который гоняет
check-types,test,build,export:openapiиcheck:docs - первый успешный run этого workflow подтверждён в Gitea
- PR review/security checklist используется как обязательный слой для нетривиальных change packages
- существует обязательный workflow, который гоняет
- Доказательства:
2. Contract и API foundation
CP-101 — OpenAPI и contract workflow
- Статус:
[x] completed - Суть: backend публикует OpenAPI и Swagger, frontend может синхронизировать generated types
- Факт исполнения:
- живой OpenAPI на
https://qadam.2fab.app/api/openapi.json - versioned artifact в
qadam-core/apps/api/openapi/openapi.json - frontend handoff и frontend changelog работают как обязательный процесс
- живой OpenAPI на
- Доказательства:
CP-102 — Registration API и профильные контракты buyer/seller
- Статус:
[x] completed - Суть: backend закрывает новый registration flow и профили buyer/seller
- Факт исполнения:
- новые auth routes опубликованы и описаны
- buyer/seller profile flows переведены на канонические write-contracts
- Доказательства:
CP-103 — Frontend adoption нового registration/profile контракта
- Статус:
[~] in progress - Суть: отдельная frontend-команда должна довести
qadam-webдо нового backend-контракта - Текущее положение:
- backend и OpenAPI готовы
- handoff и frontend changelog подготовлены
- текущие красные зоны
qadam-webразложены в отдельный remediation backlog для frontend-команды - buyer/seller profile response schemas уже закрыты и больше не считаются blocker'ом по OpenAPI coverage
auth auxiliary,staff,reference,seller itemsиadminresponse schemas уже закрыты и доступны frontend-команде через OpenAPI artifact- активных backend-blocker'ов по OpenAPI response coverage больше нет; оставшаяся работа лежит на внедрении этого контракта во frontend
- финальное UI-принятие зависит от внешней frontend-команды
- Exit criteria:
- buyer/seller registration UI не использует legacy
/auth/register - buyer profile flow использует
POST/PATCH /me/profile - seller profile flow использует канонический
PATCH - profile screens не держат ручные transport-типы там, где backend уже публикует response schemas
- buyer/seller registration UI не использует legacy
- Доказательства:
CP-104 — Закрытие OpenAPI response gaps для remaining core/admin endpoints
- Статус:
[x] completed - Суть: довести OpenAPI coverage до уровня, где web перестаёт держать ручные transport types на оставшихся buyer/seller/admin flows
- Факт исполнения:
- базовый OpenAPI и versioned artifact работают как единый contract layer
- buyer/seller profile,
Auth auxiliary flows,Staff,Reference data,Seller Items,Admin DashboardиAdmin Moderationпубликуют responsecontentв OpenAPI pnpm -C /data/qadam-core export:openapiподтверждает, что активный frontend-значимый response-gap backlog составляет0204 No Contentdelete-маршруты остаются техническим хвостом, но не считаются blocker'ом для generated contract layer
- Exit criteria:
- все endpoint'ы из
openapi-gaps.mdпубликуют responsecontentв OpenAPI там, где frontend ожидает response body - после
pnpm export:openapiweb может перегенерировать типы без ручных response-заглушек для этих flows Seller Items,Admin DashboardиAdmin Moderationбольше не считаются manual-contract зоной
- все endpoint'ы из
- Доказательства:
3. MVP hardening
CP-201 — Buyer profile flow end-to-end
- Статус:
[ ] planned - Exit criteria:
- корректный UI для отсутствующего buyer profile
- children/interests flow без legacy assumptions
- regression checks на уровне backend и web
CP-202 — Seller item и moderation flow
- Статус:
[x] completed - Суть: seller item lifecycle и базовый admin moderation flow доведены до предсказуемой status-модели без скрытых переходов
- Факт исполнения:
- у item status-модели появился явный
DRAFT, поэтому create/update больше не отправляют айтем на модерацию молча - seller теперь явно управляет переходом
DRAFT -> PENDINGчерезsubmitи может вернутьPENDING -> DRAFTчерезwithdraw - seller не может редактировать айтем в статусе
PENDING; backend требует сначала отозвать его с модерации - seller item responses публикуют
latestModerationRecord, чтобы UI видел последнюю причину/комментарий модерации - admin approve/reject работают только для
PENDINGайтемов и режут повторную модерацию как статусный конфликт, а не как неявное поведение
- у item status-модели появился явный
- Exit criteria:
- seller item workflow предсказуем от создания до модерации
- admin moderation не ломает seller UX
- статусы и причины отклонения доведены до рабочего сценария
- Доказательства:
CP-203 — Admin operational surface
- Статус:
[x] completed - Суть: admin operational surface доведён до реального рабочего контура вокруг seller status management и moderation
- Факт исполнения:
- backend публикует
GET /admin/sellersс фильтрамиsearch,status,sellerType,page,limit - admin seller summary теперь отдаёт
displayName, contact fields,telegramConnectedи item counters, поэтому status management больше не держится на ручном знанииsellerId PATCH /admin/sellers/:sellerId/statusподтверждён runtime smoke-сценариемACTIVE -> UNDER_REVIEWна временном seller-аккаунте- после admin status change seller-facing защищённые маршруты теперь возвращают явные
ACCOUNT_UNDER_REVIEW/ACCOUNT_BLOCKED, а не genericInvalid or expired token - admin API остаётся полностью покрыт contract-layer, а
GET /admin/sellersдобавлен в OpenAPI и карту API
- backend публикует
- Exit criteria:
- базовые admin сценарии предсказуемы
- account status management и moderation работают end-to-end
- admin API покрыт contract-layer и smoke checks
- Доказательства:
CP-204 — Web smoke/e2e baseline
- Статус:
[~] in progress - Факт исполнения:
- в
qadam-webдобавлен минимальный stage-oriented smoke baselinepnpm smoke:web:flowsбез отдельного browser runner - baseline уже проверяет runtime health, публичные страницы
/,/login,/register,/forgot-passwordи role-based web flows buyer/seller/admin через реальный login и cookies - public item и public seller profile включены как stage-driven слой через env, без правок кода
- живой stage-прогон уже подтверждён:
10из10проверок (runtime health, public pages, public item, public seller profile, buyer dashboard, seller dashboard, admin dashboard) завершились успешно
- в
- Exit criteria:
- есть automated smoke/e2e для ключевых buyer/seller/admin flows
- regressions ловятся до production
- Открытый хвост:
- baseline ещё нужно встроить во внешний stage release-контур, чтобы он выполнялся автоматически после deploy на проверочный сервер
- это пока smoke layer, а не полноценный browser-level e2e с пользовательскими интеракциями
CP-205 — Reviews и status model
- Статус:
[~] in progress - Факт исполнения:
- в
qadam-coreвведена backend status-модельReview: новые отзывы создаются вPENDING, исторические существующие отзывы мигрированы вPUBLISHED - публичный
GET /catalog/items/:slug/reviewsи rating/reviews aggregates в catalog/public seller profile теперь учитывают толькоPUBLISHED - buyer cabinet
GET /me/reviewsтеперь публикуетstatusиmoderationNote, чтобы frontend не держал скрытое допущение "любой отзыв сразу опубликован" - backend публикует admin review moderation endpoints
GET /admin/moderation/reviews,GET /admin/moderation/reviews/:id,PATCH /admin/moderation/reviews/:id - seller review surface доведён на backend:
GET /seller/reviews,PATCH /seller/reviews/:id/reply,POST /seller/reviews/:id/complaint - complaint-driven moderation уже замкнута end-to-end: seller complaint переводит отзыв в
PENDING_MODERATION, скрывает его из public aggregates, а admin moderation принимает финальное решение с фиксацией complaint resolution
- в
- Exit criteria:
- reviews submission, moderation и public display следуют явной status-модели
- buyer cabinet и публичные страницы показывают согласованное review-состояние без скрытых допущений
- review API и UI покрыты contract-layer и smoke/e2e по уровню риска
- Открытый хвост:
- frontend-команда должна внедрить buyer/public/admin/seller review UI под новый контракт
- review-сценарии пока не включены в автоматизированный web smoke/e2e baseline
CP-206 — Public seller profile и SEO baseline
- Статус:
[~] in progress - Факт исполнения:
- public seller profile backend очищен от внутренних seller-only полей и теперь публикует отдельный public contract вместо прямого reuse приватного seller profile shape
GET /sellers/:idтеперь отдаёт explicitseoblock:title,description,canonicalUrl,openGraph,jsonLd- canonical/SEO URLs могут браться из
PUBLIC_WEB_BASE_URL, а при его отсутствии backend выводит базовый public URL изNEXT_PUBLIC_API_URL - non-active seller profile режется как
404, а hidden seller addresses не включаются в публичный payload
- Exit criteria:
- public seller profile работает как стабильная SSR entry point
- meta/SEO baseline описан явно и не держится на скрытых предположениях
- public seller profile включён в smoke/e2e baseline там, где это оправдано риском
- Открытый хвост:
- frontend-команда должна внедрить backend-generated
seoblock в SSR metadata/public seller page - browser-level e2e для public seller profile и metadata всё ещё не закрыт, даже несмотря на успешный stage smoke baseline
- frontend-команда должна внедрить backend-generated
4. Delivery и operations maturity
CP-301 — Image-based delivery и docker contour
- Статус:
[~] in progress - Факт исполнения:
- на production-сервер установлен Docker Engine с compose plugin, но container runtime ещё не заменил канонический
systemd-контур приложений - Docker
data-rootвынесен на отдельный диск/mnt/qadam100gb/docker, поэтому image build больше не конкурирует с production runtime за корневой раздел - в
qadam-coreканонизированapps/api/Dockerfile: runtime user,dumb-init, healthcheck, отдельные helper scripts для migrations/seed и отказ от legacy entrypoint - в
qadam-coreдобавлен первый канонический deployment manifestdeploy/compose/docker-compose.api-runtime.ymlдляapi,migrateиseed - для
apiдобавлен канонический image build scriptdeploy/scripts/build-api-image.sh, который собирает образ с OCI labels и результативным тегомqadam-core-api:git-<commit> - для
apiдобавлен publish scriptdeploy/scripts/publish-api-image.sh, который публикует versioned image tag в Gitea Container Registrygit.2fab.app/eldar/qadam-core-api - для
apiдобавлен compose-based shadow smokedeploy/scripts/smoke-api-runtime-compose.sh, который поднимает runtime-manifest на127.0.0.1:5002с production env и подтверждаетhealth/ready+metricsбез cutover host-levelqadam-api - API image
qadam-core-api:cp301-smokeсобран на сервере, контейнерный smoke подтверждён:/app/bin/run-migrations.shпроходит, аGET http://127.0.0.1:5002/api/v1/healthотвечает200 - registry path подтверждён по факту:
git.2fab.app/eldar/qadam-core-api:registry-smoke-4805b86успешно опубликован и может использоваться как source image для shadow smoke - для
apiдобавлены source-controlled cutover/rollback-скриптыdeploy/scripts/cutover-api-to-container.sh,deploy/scripts/rollback-api-to-systemd.shи nginx upstream switcherdeploy/scripts/set-api-upstream.sh - на сервере поднят
qadam-api-container.service, а/etc/qadam/qadam-api-runtime.envзафиксировал канонический registry image tag для container runtime - public
/api/*трафик реально переведён наqadam-api-container.service: host nginx используетqadam_api_backend -> 127.0.0.1:5002, legacyqadam-api.serviceостановлен и оставлен как rollback path - для
qadam-webдобавленыDockerfile, build/publish/smoke scripts и runtime manifestdeploy/compose/docker-compose.web-runtime.yml - registry namespace
git.2fab.app/eldar/qadam-web-appподтверждён по факту: product web image опубликован, затем независимо вытянут черезdocker pullи поднят как shadow runtime qadam-webshadow smoke уже проходит от registry image на127.0.0.1:3002без локальногоnext buildна production-сервере- backend bootstrap больше не требует writable локальный uploads path при
OBJECT_STORAGE_DRIVER=s3: static/uploadsи создание каталогов включаются только для local driver - self-hosted runner
qadam-core-runnerтеперь имеет доступ к Docker daemon, а repo-side workflow дополнен отдельным jobAPI Container Smoke - repo-side workflow дополнен job
Publish API Image, который после зелёного smoke публикует versioned image tag в Gitea Container Registry наpushвmain - container smoke стал self-contained: workflow поднимает временные PostgreSQL и Redis контейнеры, прогоняет migrations внутри image и проверяет
health/readyиmetricsбез зависимости от production БД
- на production-сервер установлен Docker Engine с compose plugin, но container runtime ещё не заменил канонический
- Exit criteria:
- есть управляемый app-level image-based delivery
- host-based deploy перестаёт быть единственным рабочим контуром
qadam-webиqadam-roadmapполучают такой же канонический image-based runtime или documented mixed-runtime status перестаёт быть временной промежуточной фазой
CP-302 — Backup automation и off-host retention
- Статус:
[x] completed - Факт исполнения:
- в
qadam-coreдобавлен исполняемый backup runtimescripts/backup-runtime.mjsи root-командаpnpm backup:run - на сервере подняты
qadam-backup.serviceиqadam-backup.timer; timer ежедневно запускает backup baseline без ручного вмешательства - backup-сценарий снимает
pg_dump, архивы API/roadmap storage, roadmap feedback overlay и runtime config (env,systemd,nginx) - backup локально верифицируется через
pg_restore --listиSHA256SUMS, а результат последнего прогона фиксируется в/var/lib/qadam-backup/state.json - off-host archive реально выгружается в S3-compatible storage по префиксу
backups/runtime/<STAMP>.tar.gz - retention policy уже применяется автоматически:
7дней локально и30дней off-host
- в
- Exit criteria:
- backup перестаёт быть только ручной процедурой
- есть off-host copy и retention policy
- Доказательства:
CP-303 — Monitoring и alerting baseline
- Статус:
[x] completed - Факт исполнения:
- backend уже публикует отдельный monitoring baseline:
GET /health,GET /health/live,GET /health/ready - readiness probe на production реально проверяет primary PostgreSQL и Redis и отдаёт machine-readable component status с latency
- backend публикует Prometheus-compatible
GET /metrics, но сознательно режет его на403для не-loopback запросов и оставляет доступным только с сервера - в API появился базовый HTTP/runtime metrics contour на
prom-client: default process metrics,http_requests_totalиhttp_request_duration_seconds - для operational alerts подготовлен delivery channel: в production зафиксирован
TELEGRAM_ALERT_CHAT_ID, а вqadam-coreпоявился reusable senderpnpm telegram:alert - на сервере подняты
qadam-monitor.serviceиqadam-monitor.timer: они внешне проверяютqadam.2fab.app,api/v1/health/ready,qadam-roadmap.2fab.appи TLS обоих доменов - runtime monitor сохраняет state в
/var/lib/qadam-monitor/state.jsonи шлёт алерты в Telegram только на изменение статуса или recovery, без постоянного спама
- backend уже публикует отдельный monitoring baseline:
- Exit criteria:
- есть uptime/TLS monitoring
- есть operational visibility по API, web и roadmap runtime
CP-304 — Product media object storage
- Статус:
[x] completed - Факт исполнения:
- в
qadam-coreреализован storage adapterlocal | s3дляPOST /api/v1/upload/image - production runtime
qadam-apiпереведён наOBJECT_STORAGE_DRIVER=s3с S3-compatible backendDigitalOcean Spaces - upload contract сохранён: backend по-прежнему возвращает
{ url }, а frontend должен считатьurlopaque public URL - живой smoke upload подтвердил публично читаемый объект по absolute Spaces URL и успешное удаление тестового объекта после проверки
- в
- Exit criteria:
POST /api/v1/upload/imageработает через storage adapter и S3-совместимый backend- seller logo/photo и item image больше не зависят от локального
/var/lib/qadam-core/uploads - внешний API-контракт upload endpoint остаётся стабильным: backend по-прежнему возвращает
{ url } - S3 credentials не зашиваются в Dockerfile или образ, а поставляются только через runtime env/secrets
- storage
qadam-roadmapосознанно остаётся отдельным контуром и не мигрируется в этот пакет по умолчанию
5. Правило обновления этого документа
Этот документ обновляется:
- после завершения change package, который реально закрыл этап;
- после появления блокера, который переводит checkpoint в
[!] blocked; - после rollback, если фактический статус этапа ухудшился;
- одновременно с обновлением project-change-log.md.