проектdocs/frontend/frontend-change-log.md
Change Log для frontend-команды
Обновлён 14 апр. 2026 г., 17:16 · 0 комментариев
Change Log для frontend-команды
Паспорт документа
- Статус документа: living document
- Актуально на: 2 апреля 2026 года
- Владелец: backend/platform-команда, совместно с frontend-командой
- Пересмотр: при изменении backend/frontend handoff-процесса, ownership-модели или API change workflow
- Область применения: операционная модель взаимодействия backend/platform-команды и отдельной frontend-команды
- Связанные документы:
Цель документа
Этот документ фиксирует change packages, которые backend/platform-команда передаёт отдельной frontend-команде. Его задача не заменить OpenAPI и не дублировать всю документацию, а дать короткий операционный слой:
- что уже готово на backend;
- какие endpoint-группы можно брать в работу;
- какие изменения важны для UI и integration layer;
- какие проверки нужны со стороны frontend после внедрения.
Источники истины
- Канонический backend handoff: frontend-handoff.md
- Актуальный OpenAPI runtime:
https://qadam.2fab.app/api/openapi.json - Swagger UI:
https://qadam.2fab.app/api/docs - Человекочитаемая карта API: api-routes.md
- Текущее состояние production: current-state.md
- Статус платформенной реализации: ../../specs/qadam-platform/implementation.md
Правила публикации change package
Каждый новый backend change package, который влияет на frontend, должен обновлять этот документ.
Минимальный состав записи:
Package IDСтатусЧто изменилось на backendКакие endpoint'ы / контракты затронутыЧто должна сделать frontend-командаЧто считать готовностьюЕсть ли breaking / migration noteТребуется ли действие frontendна roadmap-портале
Статусы пакетов
ready_for_frontend— backend-контур готов, можно брать в работу на frontendin_progress— backend ещё меняется, фронту брать только после отдельного подтвержденияadopted_by_frontend— пакет уже внедрён frontend-командойsuperseded— пакет исторический и заменён более новым change package
Обратная связь от frontend на roadmap-портале
Главная страница https://qadam-roadmap.2fab.app автоматически собирает отдельный блок Что сейчас должна сделать frontend-команда из этого документа.
Правила такие:
- в блок попадают только пакеты со статусом
ready_for_frontend; - если пакет требует действий от frontend, на портале показываются кнопки
В работе,Сделано,Игнорировать; - если запись носит только информационный характер, в ней нужно явно указать строку
- Требуется действие frontend: нет, и тогда кнопки подтверждения не показываются; - если строка не указана, пакет по умолчанию считается требующим действия, когда у него есть статус
ready_for_frontendи непустой блокЧто должна сделать frontend-команда; - feedback-статусы на портале являются operational overlay и не заменяют канонический changelog: backend-пакет остаётся источником истины, а портал только фиксирует факт реакции frontend-команды.
Допустимые значения обратной связи:
В работе— frontend-пакет взят в реализацию;Сделано— frontend-команда подтверждает внедрение;Игнорировать— пакет сознательно не берётся в работу сейчас и не должен висеть как немая задача.
Пакеты изменений
FE-BE-2026-04-06-01 — Refresh cookie qadam_rt переведена на root path для server-side refresh
- Статус:
ready_for_frontend - Scope: web auth stability, full page reload after access token expiry, proxy refresh behavior
Backend scope
POST /api/v1/auth/loginPOST /api/v1/auth/registerPOST /api/v1/auth/register/buyerPOST /api/v1/auth/register/sellerPOST /api/v1/auth/refreshPOST /api/v1/auth/reset-passwordPOST /api/v1/auth/logout
Важные контрактные детали
qadam_rtтеперь выставляется сpath=/, а не только сpath=/api/v1/auth- это сделано не ради нового security behavior, а чтобы server-side proxy на маршрутах вроде
/sellerи/meмог читать refresh cookie после истеченияqadam_at - backend при выдаче новой пары токенов дополнительно чистит legacy
qadam_rtсpath=/api/v1/auth, чтобы не оставлять два refresh-cookie с одним именем и разными path - logout/clear tokens теперь тоже чистит обе версии refresh-cookie: legacy и новую root-scoped
Что должна сделать frontend-команда
- Никакой новой интеграции не требуется
- Перестать считать logout after reload через ~15 минут “известным ограничением backend”
- При проверке stage/prod сценариев отдельно подтвердить: full page reload после истечения access token больше не должен выбрасывать пользователя на
/login, если refresh token ещё жив
Acceptance для frontend
- Web session переживает полную перезагрузку страницы после истечения
qadam_at, еслиqadam_rtещё валидна - Proxy refresh не ломается только из-за cookie path mismatch
Breaking / migration note
- Для уже существующих браузерных сессий, выпущенных до фикса, может понадобиться один новый login, потому что legacy refresh-cookie с
path=/api/v1/authуже была выдана ранее - Требуется действие frontend: нет
FE-BE-2026-04-02-05 — Owner-facing status-change notifications включены для seller staff flow
- Статус:
ready_for_frontend - Scope: seller notification settings copy, seller/staff leads UX, operational expectations around owner alerts
Backend scope
GET /api/v1/seller/leadsPUT /api/v1/seller/leads/:id/statusGET /api/v1/seller/notification-settingsPATCH /api/v1/seller/notification-settings
Важные контрактные детали
- Owner-facing status-change notifications больше не являются purely forward-compatible: если статус лида меняет активный
SELLER_STAFF, backend отправляет owner-уведомление по каналамTelegram -> Email fallback - Список статусов для таких уведомлений не захардкожен во frontend и может меняться через runtime env
SELLER_STATUS_CHANGE_NOTIFY_STATUSES; дефолтный набор на backend сейчасCONTACTED,ENROLLED,REJECTED - Если статус меняет сам owner (
SELLER), backend не шлёт ему уведомление о его же собственном действии - Публичный HTTP-контракт notification settings не менялся: новых полей и новых endpoint'ов нет
Что должна сделать frontend-команда
- Не считать
notifyStatusChangeTelegrampurely informational toggle: на окружениях с включённым seller notifications runtime он уже управляет live owner-facing уведомлениями для staff-driven status changes - Если в seller/staff UX есть текст, будто status-change alerts "появятся позже", обновить его под фактическое поведение backend
Acceptance для frontend
- Seller settings UI не вводит пользователя в заблуждение относительно live status-change alerts
- Seller/staff lead UX не обещает owner-уведомления для self-update сценария, которого backend сознательно не делает
Breaking / migration note
- Это изменение поведения доставки без расширения публичного API-контракта
- Требуется действие frontend: нет
FE-BE-2026-04-02-04 — Seller email fallback подготовлен на backend
- Статус:
ready_for_frontend - Scope: seller notification settings copy, operational expectations around email channel
Backend scope
POST /api/v1/leadsGET /api/v1/seller/notification-settingsPATCH /api/v1/seller/notification-settings
Важные контрактные детали
- Для новых лидов backend теперь не ограничивается Telegram-only попыткой доставки: при недоступном Telegram и включённом
notifyNewLeadEmailон умеет перейти на SMTP-capable email fallback sellerEmailвGET /seller/notification-settingsтеперь резолвится из seller profile email с fallback на account email- Публичный HTTP-контракт не менялся: новых endpoint'ов и новых полей нет
- Email fallback реально срабатывает только на тех окружениях, где backend/platform-команда настроила
SMTP_*runtime env notifyStatusChangeTelegramтеперь уже управляет live owner-facing уведомлениями в non-owner staff flow; отдельный пакет ниже фиксирует это как поведенческое изменение без расширения API-контракта
Что должна сделать frontend-команда
- Не считать
notifyNewLeadEmailpurely forward-compatible флагом на окружениях, где backend подтвердил SMTP runtime - Если в UI есть жёсткий текст "email ещё не работает", убрать его только после подтверждения, что конкретный target runtime уже получил
SMTP_*конфиг - Показывать
sellerEmailкак фактический email-адрес доставки, а не только как account email из auth-контекста
Acceptance для frontend
- Settings screen не вводит seller в заблуждение относительно email-канала
- UI понимает, что email delivery зависит не только от toggle, но и от runtime readiness конкретного окружения
Breaking / migration note
- Migration касается поведения доставки, а не формы API-ответа
- Требуется действие frontend: нет
FE-BE-2026-04-02-03 — Seller Telegram onboarding bot flow подготовлен для frontend
- Статус:
ready_for_frontend - Scope: seller notifications UX, Telegram connect/disconnect CTA, onboarding follow-up
Backend scope
GET /api/v1/seller/telegram/connect-linkPOST /api/v1/seller/telegram/verifyDELETE /api/v1/seller/telegram
Важные контрактные детали
- Backend теперь отдаёт seller-facing deep link:
botUsername: stringconnectUrl: stringexpiresAt: string
connectUrlуже готов для открытия в Telegram и ведёт в bot/startflow; frontend не должен собирать deep link вручнуюGET /seller/telegram/connect-linkможет вернутьTELEGRAM_NOT_CONFIGURED, если seller-bot не настроен на конкретном окружении; это operational state, а не generic network errorPOST /seller/telegram/verifyтеперь явно возвращаетALREADY_VERIFIED, если Telegram уже подключён к sellerDELETE /seller/telegramтеперь явно возвращаетNOT_CONNECTED, если seller пытается отключить Telegram без текущей привязки- Internal route
POST /api/v1/internal/telegram/webhookпредназначен для Telegram и не требует frontend-работ
Что должна сделать frontend-команда
- Добавить CTA/кнопку подключения Telegram через
GET /seller/telegram/connect-link - Открывать
connectUrlкак внешний переход в Telegram, а не через локальную строковую сборку bot URL - На verify/disconnect корректно обрабатывать
ALREADY_VERIFIEDиNOT_CONNECTEDкак продуктовые состояния, а не как generic error - Синхронизировать seller notification settings screen с новым connect flow, чтобы
telegramConnectedиtelegramUsernameобновлялись после успешной привязки
Acceptance для frontend
- Seller может запустить Telegram connect flow из кабинета без ручного знания bot username или start token
- UI различает состояния
подключено,уже подключено,не подключено - После успешного bot flow seller возвращается в кабинет и может завершить привязку кодом без локальных manual types
Breaking / migration note
- Это расширение существующего Telegram flow; старые settings endpoints не ломаются
- Frontend больше не должен считать, что seller сам знает, где взять verification code: source-of-truth теперь
GET /seller/telegram/connect-link - Требуется действие frontend: да
FE-BE-2026-04-02-02 — Seller notifications baseline подготовлен для frontend
- Статус:
ready_for_frontend - Scope: seller settings page, lead notification preferences, seller onboarding follow-up
Backend scope
GET /api/v1/seller/notification-settingsPATCH /api/v1/seller/notification-settings
Важные контрактные детали
- Backend публикует новый seller-facing settings contract:
notifyNewLeadTelegram: booleannotifyNewLeadEmail: booleannotifyStatusChangeTelegram: booleantelegramConnected: booleantelegramUsername: string | nullsellerEmail: string | null
- Если запись
NotificationSettingsотсутствует у исторического seller-аккаунта, backend создаёт её автоматически с дефолтами - После
POST /leadsbackend уже запускает неблокирующую попытку Telegram-доставки продавцу, но email transport пока не включён:notifyNewLeadEmailуже существует как forward-compatible setting, а не как подтверждённый delivery channel - Успешность или пропуск доставки не влияет на ответ создания лида: lead create остаётся продуктовым primary path
Что должна сделать frontend-команда
- Добавить экран или секцию seller notification settings на
GET/PATCH /seller/notification-settings - Показывать состояние Telegram binding по
telegramConnectedиtelegramUsername, а не по локальным эвристикам - Не обещать пользователю живой email delivery, пока backend отдельно не подтвердит SMTP/provider package
- Использовать
sellerEmailтолько как read-only operational hint в настройках, а не как отдельный источник истины о seller profile
Acceptance для frontend
- Seller видит текущие notification settings и может менять их без ручных локальных типов
- UI корректно различает
Telegram подключён / не подключён - Lead settings screen не вводит пользователя в заблуждение относительно email delivery
Breaking / migration note
- Это новый settings surface; существующие seller profile и lead flows не ломаются
- Email toggle уже появляется в контракте, но не означает, что email-канал backend уже доведён до production delivery
- Требуется действие frontend: да
FE-BE-2026-04-02-01 — Auth contract получил change-password из кабинета
- Статус:
ready_for_frontend - Scope: buyer/seller account settings, password settings form, auth security UX
Backend scope
POST /api/v1/auth/change-password
Важные контрактные детали
- Новый endpoint принимает:
currentPassword: stringnewPassword: string
newPasswordиспользует те же password rules, что и registration/reset-password:- минимум 8 символов
- минимум одна цифра
- Успешный ответ:
{ message: string }
- При неверном текущем пароле backend возвращает
INVALID_CREDENTIALS - После успешной смены пароля backend отзывает refresh token family, поэтому фронт не должен рассчитывать на долгоживущие старые сессии на других устройствах
Что должна сделать frontend-команда
- Добавить форму смены пароля в buyer/seller кабинете на
POST /auth/change-password - Валидировать
newPasswordпо тем же правилам, что и registration/reset-password - Показать отдельное UX-сообщение для неверного текущего пароля вместо generic error toast
- После успешной смены пароля корректно показать success-state и быть готовыми к тому, что старые refresh-сессии на других устройствах больше невалидны
Acceptance для frontend
- Из кабинета можно сменить пароль без flow
forgot-password - Неверный текущий пароль отображается как ожидаемая продуктовая ошибка
- Успешная смена пароля показывает явный success-state по
messageиз backend
Breaking / migration note
- Это новый endpoint, а не замена
forgot-password/reset-password - Сброс пароля по коду и смена пароля из авторизованного кабинета теперь должны сосуществовать как два разных UX-потока
- Требуется действие frontend: да
FE-BE-2026-03-31-03 — Public seller profile начал отдавать backend-generated SEO metadata
- Статус:
ready_for_frontend - Scope: public seller profile SSR page и metadata layer должны перейти с ad-hoc сборки SEO на backend-generated contract
Backend scope
GET /api/v1/sellers/:id
Важные контрактные детали
- Public seller profile response теперь публикует не только витринные поля seller и список опубликованных айтемов, но и explicit
seoblock:titledescriptioncanonicalUrlopenGraphjsonLd
- Public response очищен от seller-only внутреннего контекста: backend больше не должен отдавать приватный seller profile shape как есть
- Непубличный seller должен резаться как
404; contract для public page теперь рассчитан только наACTIVEseller profile - Hidden addresses не должны попадать в public payload даже в обнулённом виде
Что должна сделать frontend-команда
- Перевести public seller page metadata на backend-generated
seoblock вместо локальной ad-hoc сборки - Использовать
seo.canonicalUrl,seo.openGraphиseo.jsonLdкак канонический источник для SSR metadata и structured data - Не предполагать, что hidden seller addresses приходят в payload: если массив
addressesпуст, секция не должна рендериться - Обрабатывать
404как нормальный SEO-safe сценарий для non-active / missing seller profile
Acceptance для frontend
- Public seller page использует backend-generated SEO metadata без ручного дублирования формул title/description/canonical
- JSON-LD на seller page строится из
seo.jsonLd, а не из разрозненных local selectors - Non-active / missing seller profile даёт корректный 404 page flow без пустого
200
Breaking / migration note
- Это не просто cosmetic addition: contract public seller profile стал более строгим и более пригодным для SSR/SEO
- Frontend не должен опираться на скрытые seller-only поля, если они раньше случайно приезжали в response
- Требуется действие frontend: да
FE-BE-2026-03-31-02 — Seller review surface и complaint-driven moderation готовы для frontend
- Статус:
ready_for_frontend - Scope: seller review dashboard, seller reply/complaint UX, buyer/public/admin review screens должны учесть seller reply и complaint-driven moderation
Backend scope
GET /api/v1/seller/reviewsPATCH /api/v1/seller/reviews/:id/replyPOST /api/v1/seller/reviews/:id/complaintGET /api/v1/me/reviewsGET /api/v1/catalog/items/:slug/reviewsGET /api/v1/admin/moderation/reviews/:id
Важные контрактные детали
GET /seller/reviewsвозвращает список отзывов по айтемам продавца c полями:reviewIdstatusratingtextsellerReplysellerReplyAtmoderationNotecanReplycanEditReplyactiveComplaintitembuyer
PATCH /seller/reviews/:id/replyдоступен только дляPUBLISHED-отзывов- После первого ответа продавца backend разрешает редактировать reply только в пределах 48 часов; затем возвращает
REPLY_EDIT_WINDOW_EXPIRED POST /seller/reviews/:id/complaintдоступен только дляPUBLISHED-отзывов и переводит отзыв вPENDING_MODERATION- Повторная жалоба на отзыв с активной нерешённой complaint запрещена и возвращает
COMPLAINT_ALREADY_EXISTS - Buyer/public/admin review payloads теперь могут содержать seller reply и active complaint context:
GET /me/reviewsпубликуетsellerReplyиsellerReplyAtGET /catalog/items/:slug/reviewsпубликует seller reply только дляPUBLISHED-отзывовGET /admin/moderation/reviews/:idпубликуетsellerReply,sellerReplyAtиactiveComplaint
Что должна сделать frontend-команда
- Построить seller review list/dashboard на
GET /seller/reviews - Добавить seller reply editor с state-driven блокировкой по
canReply/canEditReply - Обработать
REVIEW_NOT_PUBLISHED,REPLY_EDIT_WINDOW_EXPIRED,COMPLAINT_ALREADY_EXISTSкак ожидаемые продуктовые состояния, а не generic error - Добавить seller complaint UX и после успешной жалобы переводить review-card в состояние
PENDING_MODERATION - Показывать seller reply в buyer cabinet и public review blocks там, где он приходит из backend
- В admin review detail показывать active complaint context, если отзыв попал на повторную модерацию
Acceptance для frontend
- Seller видит список отзывов по своим айтемам и различает
PUBLISHED / PENDING / REJECTED / PENDING_MODERATION - Seller может ответить на опубликованный отзыв и видит, когда reply уже нельзя редактировать
- Seller может отправить complaint на опубликованный отзыв и после этого UI показывает review как
PENDING_MODERATION - Buyer/public/admin review screens корректно отображают seller reply и complaint-driven moderation state
Breaking / migration note
- Это расширение review-контракта и seller dashboard surface, а не изолированный новый экран
- Frontend больше не должен считать seller review interaction "локальной заметкой": reply и complaint влияют на public/admin review state machine
- Требуется действие frontend: да
FE-BE-2026-03-31-01 — Backend review status model и admin review moderation baseline
- Статус:
ready_for_frontend - Scope: buyer reviews cabinet, public item reviews и admin review moderation
Backend scope
POST /api/v1/me/reviewsGET /api/v1/me/reviewsGET /api/v1/catalog/items/:slug/reviewsGET /api/v1/admin/moderation/reviewsGET /api/v1/admin/moderation/reviews/:idPATCH /api/v1/admin/moderation/reviews/:id
Важные контрактные детали
- Review flow на backend больше не предполагает мгновенную публикацию: новые отзывы создаются в
PENDING - Исторические существующие отзывы мигрированы в
PUBLISHED, чтобы не обнулить текущий public/social proof GET /me/reviewsтеперь возвращает для каждого отзыва:reviewIditemIditemNameitemSlugratingtextstatusmoderationNotecreatedAt
- Публичный
GET /catalog/items/:slug/reviewsи rating/reviews aggregates теперь учитывают толькоPUBLISHED - Появился новый admin moderation surface для отзывов:
GET /admin/moderation/reviewsGET /admin/moderation/reviews/:idPATCH /admin/moderation/reviews/:id
PATCH /admin/moderation/reviews/:idпринимает:decision: PUBLISHED | REJECTEDnote?: string
- При
REJECTEDmoderation note обязателен PENDING_MODERATIONуже существует в contract-layer как допустимыйReviewStatus, но complaint-driven переход в этот статус будет отдельным follow-up пакетом
Что должна сделать frontend-команда
- Добавить buyer-facing UI для review status badge вместо скрытого допущения "отзыв всегда сразу опубликован"
- Показывать
moderationNote, если отзыв отклонён или имеет seller-visible moderation пояснение - В public item reviews и rating widgets больше не ожидать, что новые только что отправленные отзывы появятся мгновенно
- Построить admin review moderation queue/detail на новых
/admin/moderation/reviews*endpoints - Обработать
INVALID_STATUS_TRANSITIONдля race-safe admin moderation UI
Acceptance для frontend
- Buyer cabinet показывает
PENDING / PUBLISHED / REJECTED / PENDING_MODERATIONкак отдельные UI-состояния - Public item reviews и rating counters не завышаются за счёт
PENDINGотзывов - Admin может открыть очередь review moderation, посмотреть карточку отзыва и перевести отзыв в
PUBLISHEDилиREJECTED
Breaking / migration note
- Это контрактное изменение поведения, а не только добавление admin endpoints
- Старое frontend-допущение "отзыв после submit сразу виден в public UI" теперь неверно
- Требуется действие frontend: да
FE-BE-2026-03-30-05 — Admin seller operational surface доведён до рабочего контура
- Статус:
ready_for_frontend - Scope: admin seller directory, status management и seller-facing реакция на account status
Backend scope
GET /api/v1/admin/sellersPATCH /api/v1/admin/sellers/:sellerId/status- seller-facing защищённые маршруты, которые проходят через
JwtAuthGuard
Важные контрактные детали
- Появился новый endpoint
GET /admin/sellersс фильтрамиsearch,status,sellerType,page,limit - Ответ
GET /admin/sellersимеет форму{ items, total, page, limit, totalPages } - Каждый seller summary теперь содержит:
sellerIdaccountIdsellerTypeaccountStatusdisplayNamephoneemailtelegramConnectedtotalItemspendingItemsactiveItemscreatedAt
PATCH /admin/sellers/:sellerId/statusостаётся прежним по shape ответа, но теперь у admin есть полноценный list/search surface, из которого этот action можно вызывать без ручного знанияsellerId- После перевода seller в
UNDER_REVIEWилиBLOCKEDзащищённые seller-facing маршруты больше не отвечают generic401 Invalid or expired token - Вместо этого backend возвращает явные domain errors:
403 ACCOUNT_UNDER_REVIEW403 ACCOUNT_BLOCKED
Что должна сделать frontend-команда
- Построить admin seller directory/list screen на
GET /admin/sellers - Подключить фильтры
search,status,sellerType,page,limit - Показывать seller summary и item counters прямо из backend response, а не собирать их вручную из разрозненных API
- Использовать
PATCH /admin/sellers/:sellerId/statusиз этого списка как основной status-management action - В seller-facing UI перестать трактовать response после status change как token expiry:
ACCOUNT_UNDER_REVIEWиACCOUNT_BLOCKEDдолжны обрабатываться как account state
Acceptance для frontend
- Admin может найти seller по имени/телефону/email и отфильтровать список по
ACTIVE / UNDER_REVIEW / BLOCKED - Admin seller list показывает текущее состояние аккаунта и item counters без дополнительных ad-hoc запросов
- После перевода seller в
UNDER_REVIEWилиBLOCKEDseller-facing UI показывает корректный state-driven экран/ошибку, а не generic auth expiry
Breaking / migration note
- Нового breaking route change нет
- Это operational contract package: статус account management теперь считается полноценным рабочим срезом, а не isolated action endpoint
- Требуется действие frontend: да
FE-BE-2026-03-30-04 — Seller item moderation state machine доведён до рабочего вида
- Статус:
ready_for_frontend - Scope: seller item dashboard и admin moderation должны перейти на явный moderation lifecycle вместо старых неявных переходов
Backend scope
GET /api/v1/seller/itemsPOST /api/v1/seller/itemsGET /api/v1/seller/items/:idPUT /api/v1/seller/items/:idPOST /api/v1/seller/items/:id/submitPOST /api/v1/seller/items/:id/withdrawPOST /api/v1/admin/moderation/items/:id/approvePOST /api/v1/admin/moderation/items/:id/rejectGET /api/v1/admin/moderation/itemsGET /api/v1/admin/moderation/items/:id
Важные контрактные детали
- Item status-модель теперь включает
DRAFT,PENDING,ACTIVE,REJECTED - Новый item после
POST /seller/itemsсоздаётся вDRAFT, а не уходит на модерацию автоматически PUT /seller/items/:idбольше не разрешён дляPENDINGайтемов; backend отдаёт400 ITEM_PENDINGPOST /seller/items/:id/submitтеперь валидирует обязательные поля и может вернутьITEM_ALREADY_PENDING,ITEM_ALREADY_ACTIVE,ITEM_MISSING_REQUIRED_FIELDS- Появился новый endpoint
POST /seller/items/:id/withdraw, который возвращает pending-айтем обратно вDRAFT GET /seller/itemsиGET /seller/items/:idтеперь публикуютlatestModerationRecordGET /admin/moderation/itemsпубликуетlatestModerationRecord, аGET /admin/moderation/items/:idпубликуетlatestModerationRecordиmoderationHistoryapproveиrejectтеперь работают только дляPENDINGайтемов и отдают409 ITEM_NOT_PENDING, если item уже промодерирован
Что должна сделать frontend-команда
- Добавить явный seller badge/UX для статуса
DRAFT - Перестать считать, что create/update автоматически отправляют айтем на модерацию
- Добавить UX для
withdrawперед редактированием pending-айтема - Показывать
latestModerationRecord.reason/commentв seller item dashboard и detail screen - Обработать новые item error codes:
ITEM_PENDING,ITEM_ALREADY_PENDING,ITEM_ALREADY_ACTIVE,ITEM_MISSING_REQUIRED_FIELDS,ITEM_NOT_PENDING - Обновить admin moderation UI под новый race-safe сценарий, где non-pending item больше нельзя approve/reject
Acceptance для frontend
- Seller item dashboard корректно показывает
DRAFT / PENDING / ACTIVE / REJECTED - Seller может открыть причину последнего reject через
latestModerationRecord - Редактирование pending-айтема не делается в обход backend, а требует сначала
withdraw - Admin moderation UI корректно обрабатывает
409 ITEM_NOT_PENDINGкак race-condition, а не как неизвестную ошибку
Breaking / migration note
- Это контрактное изменение поведения, а не только новый endpoint
- Старое frontend-допущение “create/update автоматически отправляют item на модерацию” теперь неверно
- Требуется действие frontend: да
FE-BE-2026-03-30-03 — Upload URL стал storage-agnostic
- Статус:
ready_for_frontend - Scope: подготовить frontend к object storage без ломки API-контракта upload endpoint
Backend scope
POST /api/v1/upload/image
Важные контрактные детали
- Shape ответа не меняется: upload endpoint по-прежнему возвращает
{ url: string } - Значение
urlтеперь нужно считать opaque public URL - При локальном storage это может быть
/uploads/images/<fileName> - При S3/CDN storage это может быть абсолютный URL вида
https://cdn.example.com/images/<fileName> - В текущем production для product media уже используется абсолютный URL из
DigitalOcean Spaces - Frontend не должен собирать upload URL вручную и не должен предполагать same-origin относительный путь
Что должна сделать frontend-команда
- Использовать
urlиз backend response как готовыйsrc/asset URL без преобразований - Не завязывать upload UI на префикс
/uploads/images/ - Проверить, что seller logo/photo и item image flows не ломаются от абсолютного CDN/S3 URL
Acceptance для frontend
- Upload UI и asset forms сохраняют в модель ровно тот
url, который вернул backend - Отрисовка изображений работает как для относительных, так и для абсолютных URL
- В коде нет ручной конкатенации same-origin upload paths
Breaking / migration note
- Формально breaking route change нет
- Семантически это важное contract clarification:
urlбольше не должен считаться обязательно локальным path
FE-BE-2026-03-30-02 — OpenAPI response schemas для seller items и admin
- Статус:
ready_for_frontend - Scope: убрать manual response layer на seller item dashboard и admin slices; активный backend-blocker backlog по OpenAPI coverage теперь равен
0
Backend scope
GET /api/v1/seller/itemsPOST /api/v1/seller/itemsGET /api/v1/seller/items/:idPUT /api/v1/seller/items/:idDELETE /api/v1/seller/items/:idPOST /api/v1/seller/items/:id/submitPOST /api/v1/seller/items/:id/archiveGET /api/v1/admin/statsGET /api/v1/admin/leadsGET /api/v1/admin/moderation/itemsGET /api/v1/admin/moderation/items/:idPOST /api/v1/admin/moderation/items/:id/approvePOST /api/v1/admin/moderation/items/:id/reject
Важные контрактные детали
- Seller item dashboard теперь публикует точные response schemas для списка, detail, create, update, delete, submit и archive flows
admin/leadsиadmin/moderation/itemsописаны как массивы, а не как ad-hoc обёртки{ items: ... }admin/moderation/items/:id/approveиrejectвозвращают{ id, name, slug, moderationStatus, isVisible }- Активный frontend-значимый OpenAPI gap backlog теперь составляет
0
Что должна сделать frontend-команда
- Перегенерировать
openapi/openapi.jsonи contract layer - Убрать ручные response-типы на seller item dashboard и admin slices
- Перевести item/admin queries и mutations на generated response types без локальных transport-заглушек
- Считать оставшиеся ручные response-интерфейсы в этих зонах техническим долгом, а не допустимым baseline
Acceptance для frontend
- Seller item dashboard использует generated response types для list/detail/create/update/delete/submit/archive
- Admin dashboard и moderation UI используют generated response types без ручного response typing
- После синхронизации frontend больше не держит manual response layer на
seller itemsиadminslices
Breaking / migration note
- Breaking route change нет
- Это финальный contract-completeness package по
CP-104: новые backend schema fixes для этих endpoint'ов больше не требуются 204 No Contentdelete-маршруты остаются техническим хвостом OpenAPI-оформления, но не считаются blocker'ом для frontend
FE-BE-2026-03-30-01 — OpenAPI response schemas для auth auxiliary, staff и reference
- Статус:
ready_for_frontend - Scope: убрать manual transport layer на auth auxiliary, staff и reference slices
Backend scope
POST /api/v1/auth/forgot-passwordPOST /api/v1/auth/verify-reset-codePOST /api/v1/auth/reset-passwordPOST /api/v1/auth/add-buyer-roleGET /api/v1/seller/staffPOST /api/v1/seller/staffPUT /api/v1/seller/staff/:idDELETE /api/v1/seller/staff/:idGET /api/v1/catalog/subjectsPOST /api/v1/catalog/subjectsPUT /api/v1/catalog/subjects/:idDELETE /api/v1/catalog/subjects/:idGET /api/v1/catalog/locationsPOST /api/v1/catalog/locationsPUT /api/v1/catalog/locations/:idDELETE /api/v1/catalog/locations/:idGET /api/v1/subjects
Важные контрактные детали
- Эти endpoint'ы теперь публикуют response
contentв OpenAPI и готовы к generated response types reset-passwordпубликует тот же session response contract, что и login/register flowsadd-buyer-roleвозвращает{ profile }, а не отдельную ad-hoc формуseller/staffстабилизирован на форме{ staff: ... }catalog/subjects,catalog/locationsи публичный/subjectsотдают явные списки/объекты справочников без необходимости ручного frontend typing
Что должна сделать frontend-команда
- Перегенерировать
openapi/openapi.jsonи contract layer - Убрать ручные response-типы на password reset auxiliary flow, seller staff и reference slices
- Использовать generated response layer для buyer-role bind flow
- Не держать custom parsers там, где shape теперь уже стабилизирован в OpenAPI
Acceptance для frontend
- Password reset auxiliary flow использует generated response types
- Staff management UI использует generated response types без ручных transport interfaces
- Reference/admin reference screens используют generated response types для subjects/locations
- Public
/subjectsбольше не типизируется вручную
Breaking / migration note
- Breaking route change нет
- Это не новый endpoint package, а contract-completeness package: старые ручные response-типы теперь считаются техническим долгом и должны вытесняться generated contract layer
FE-BE-2026-03-28-01 — OpenAPI и контрактный контур
- Статус:
ready_for_frontend - Scope: source-of-truth контракт и базовый workflow синхронизации frontend с backend
Что сделано на backend
- Поднят Swagger UI:
GET /api/docs - Поднят runtime OpenAPI artifact:
GET /api/openapi.json - Версионируемый OpenAPI artifact хранится в
qadam-core/apps/api/openapi/openapi.json - Backend публикует точные response-схемы для ключевых auth/buyer/seller/public flows
Что должна сделать frontend-команда
- Считать OpenAPI единственным источником истины по transport-типам
- Не поддерживать вручную параллельные request/response types, если endpoint уже описан в OpenAPI
- Для каждого backend-пакета сначала обновлять
openapi/openapi.json, затем прогонять codegen
Acceptance для frontend
- Обновлён
qadam-web/openapi/openapi.json - Выполнен
pnpm generate:api-contract - Нет ручного contract drift относительно backend artifact
Breaking note
- Breaking change как таковой нет, но ручные transport-типы считаются legacy и подлежат вытеснению generated contract layer
FE-BE-2026-03-28-02 — Auth registration и password reset
- Статус:
ready_for_frontend - Scope: новый registration API и восстановление пароля
Backend scope
POST /api/v1/auth/check-availabilityPOST /api/v1/auth/register/buyerPOST /api/v1/auth/register/sellerPOST /api/v1/auth/forgot-passwordPOST /api/v1/auth/verify-reset-codePOST /api/v1/auth/reset-passwordPOST /api/v1/auth/add-buyer-role
Важные контрактные детали
- Для duplicate validation используются отдельные ошибки
PHONE_TAKENиEMAIL_TAKEN - Buyer может регистрироваться без email
- Seller registration требует полный seller payload, включая
sellerType, profile fields иsubjectIds - Web-клиент продолжает жить на cookie auth (
qadam_at,qadam_rt) - Mobile-клиенты по-прежнему могут получать токены в body
- Password reset transport пока stub-овый: API создаёт токен/код корректно, но внешняя доставка пока не интегрирована с реальным SMS/email provider
Что должна сделать frontend-команда
- Собрать новый registration wizard поверх
check-availability,register/buyer,register/seller - Нормально маппить
PHONE_TAKENиEMAIL_TAKENв field-level ошибки - Не строить отдельный frontend-only reset flow в обход backend-контракта
- Использовать новый
add-buyer-roleдля multi-role сценария seller → buyer
Acceptance для frontend
- Регистрация buyer проходит end-to-end на новых endpoint'ах
- Регистрация seller проходит end-to-end на новых endpoint'ах
- Ошибки availability и финального register показываются на конкретных полях
- Password reset UI использует backend token/code flow, а не локальные временные обходы
Breaking / migration note
- Старый
POST /api/v1/auth/registerсохранён только как legacy route и не должен быть опорой новой frontend-разработки
FE-BE-2026-03-28-03 — Buyer profile, children, interests
- Статус:
ready_for_frontend - Scope: buyer cabinet и post-registration buyer flow
Backend scope
GET /api/v1/me/profilePOST /api/v1/me/profilePATCH /api/v1/me/profilePUT /api/v1/me/profile— legacy aliasGET /api/v1/me/childrenPOST /api/v1/me/childrenPATCH /api/v1/me/children/:studentIdDELETE /api/v1/me/children/:studentIdPATCH /api/v1/me/interests
Важные контрактные детали
- Канонический write-contract —
PATCH, а неPUT - Отсутствующий buyer profile должен обрабатываться как отдельное UI-состояние, а не как “тихий create”
- Buyer profile работает от account-centric модели
- Parent и student сценарии расходятся по доступным endpoint'ам и состояниям
Что должна сделать frontend-команда
- Собрать UI-сценарий отсутствующего buyer profile
- Развести parent и student ветки кабинета
- Перевести buyer profile flow на
POST/PATCH /me/profile - Подключить children CRUD и interests update к новому контракту
Acceptance для frontend
- Buyer profile create/edit не использует legacy assumptions
- Parent видит children list и children CRUD
- Student видит и обновляет interests
- UI устойчив к
BUYER_NOT_FOUND,PHONE_TAKEN,EMAIL_TAKEN,MAX_CHILDREN_REACHED,CHILD_NOT_FOUND
Breaking / migration note
PUT /me/profileне должен использоваться как канонический путь для новой реализации
FE-BE-2026-03-28-04 — Seller profile, addresses, Telegram, uploads
- Статус:
ready_for_frontend - Scope: seller onboarding/profile management и asset-related flows
Backend scope
GET /api/v1/seller/profilePOST /api/v1/seller/profilePATCH /api/v1/seller/profilePUT /api/v1/seller/profile— legacy aliasGET /api/v1/seller/addressesPOST /api/v1/seller/addressesPATCH /api/v1/seller/addresses/:addressIdDELETE /api/v1/seller/addresses/:addressIdPATCH /api/v1/seller/addresses/:addressId/set-primaryPOST /api/v1/seller/telegram/verifyDELETE /api/v1/seller/telegramPOST /api/v1/upload/image
Важные контрактные детали
PATCH /seller/profileтеперь возвращает специфичныеPHONE_TAKENиEMAIL_TAKEN, если contact phone/email конфликтуют с другим аккаунтом- Telegram verify возвращает
{ success, username }, гдеusernameможет бытьnull - Upload endpoint принимает
multipart/form-data, файл в полеfile - Upload validation:
JPG/PNG/WebP, max5 MB, min200x200 - Успешный upload возвращает
urlкак готовый публичный URL; он может быть как локальным/uploads/images/<fileName>, так и абсолютным S3/CDN URL
Что должна сделать frontend-команда
- Довести seller onboarding/profile UI до актуального backend-контракта
- Нормально обрабатывать field-level duplicate errors для contact phone/email
- Подключить address CRUD и primary switch к новому seller area
- Подключить Telegram verification/unbind без самодельного контракта
- Использовать backend upload endpoint для logo/photo/image flows
Acceptance для frontend
- Seller profile edit работает через
PATCH - Address management использует backend CRUD напрямую
- Telegram binding flow использует
POST /seller/telegram/verify - Upload UI корректно обрабатывает
FILE_TOO_LARGE,INVALID_FORMAT,IMAGE_TOO_SMALL
Breaking / migration note
PUT /seller/profile— только legacy alias, новые UI-сценарии должны строиться наPATCH
FE-BE-2026-03-28-05 — Admin / governance hooks
- Статус:
ready_for_frontend - Scope: backend hooks, которые понадобятся admin-поверхности и governance-сценариям
Backend scope
PATCH /api/v1/admin/sellers/:sellerId/status
Важные контрактные детали
- Валидные переходы состояний ограничены
- После смены статуса seller refresh sessions инвалидируются на backend
- Auth guard проверяет живой account status, а не только JWT payload
Что должна сделать frontend-команда
- Использовать этот endpoint только в admin scope
- Явно закладывать UI для
INVALID_STATUS_TRANSITION - Не предполагать, что заблокированный seller сможет жить на старой refresh-сессии
Acceptance для frontend
- Admin UI корректно меняет seller status и показывает новое состояние
- После блокировки/under_review seller-facing UI правильно реагирует на новые auth errors
Что не считается frontend blocker прямо сейчас
- Stub transport у password reset не блокирует UI-интеграцию, если flow строится против реального API-контракта
- Локальный upload storage не блокирует frontend, если UI работает только через возвращаемый URL
- Legacy compatibility поля в Prisma не должны протекать во frontend как источник истины
Как обновлять этот документ дальше
При каждом новом backend change package:
- Добавить новый блок в этот changelog
- Обновить
frontend-handoff.md, если поменялся workflow handoff - Обновить
api-routes.md, если появился новый endpoint или changed behavior - Обновить OpenAPI artifact
- Только после этого передавать пакет frontend-команде