You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Архитектурный RFC: как довести существующий Web API (api.php → /api/v1) до coherent headless-контракта для Nuxt без rewrite cart/order/customer и без дублирования уже открытых issues #563–#576.
Этот issue не заменяет child-issues. Он фиксирует цель, карту зависимостей, что в core / addon, минимальный MVP и roadmap P0–P2.
Проблема, которую решает
Аудит дал пачку точечных issues. Без RFC легко:
сделать два PLP-контракта (filters vs facets) несовместимыми;
Уже достаточно для «гостевой корзина + checkout с известными delivery_id/payment_id» (как Fenom). Недостаточно для навигации каталога и выбора доставки/оплаты без хардкода ID.
Proposed API
Инкремент к /api/v1, те же middleware и Response.
Новые публичные (без TokenMiddleware, как product):
GET /api/v1/product/list|get/{id}
POST /api/v1/cart/*
GET /api/v1/cart/get
* /api/v1/order/* (draft + submit + cost)
POST /api/v1/customer/login|register|logout|forgot-password|reset-password
GET /api/v1/customer/token/get
* /api/v1/customer/addresses*
* /api/v1/customer/orders*
GET /api/v1/health
Добавить в core (child issues)
GET /api/v1/category/list
GET /api/v1/category/get/{id}
GET /api/v1/category/tree
GET /api/v1/product/filters # facets
GET /api/v1/delivery/list
GET /api/v1/payment/list?delivery_id=
GET /api/v1/customer/me
Расширения query product/list и полей get — в #564/#566/#567, не новые path без нужды.
P0: list/get + category (#563) + perf list (#575) до тяжёлого трафика.
P1: filters (#564), images (#566).
P2: deep search / synonyms → addon (не Elasticsearch в ядре).
Categories
#563 — list / get / tree. Только published msCategory. Nested product listing через parent + позже member scope в #564.
Зависимость: SEO category (#567) после get category.
Filters
#564 — query params на product/list (price range, vendor, options, nested/members) совместимо с текущими parent|category, query, sort, limit.
Не ломать default без новых params.
Facets
#565 — отдельный GET /product/filters (counts). Делить с #564 общую модель «filterable fields», не дублировать два диалекта option keys.
Зависимость: семантика фильтров #564 (хотя бы черновик контракта) до или вместе с facets.
Merge recommendation: не закрывать issues в один PR обязательно; связать cross-link и общий lexicon ключей. Дубликатами не считать.
Cart
Существующий API достаточен. #570 — стабилизировать cart object vs array + totals в status. Breaking только если кто-то парсил пустую корзину как [] vs {} — задокументировать / version soft.
Checkout
Поток уже есть: address/set → set delivery_id/payment_id → cost → submit.
Блокер UX: #568 + #569 (discovery). Рекомендация merge в один milestone/PR-пакет «checkout discovery» (два route, один сервис pairing как mgr #374).
BFF только на Nuxt server — быстрее старт, каждый магазин изобретает category/delivery. RFC предпочитает core discovery.
Использовать mgr API с service account — security anti-pattern; отклонено.
Большой bang rewrite /api/v2 — без доказанной несовместимости v1; отклонено.
Примеры использования
Nuxt SSR PLP:
GET /api/v1/category/tree
GET /api/v1/product/list?parent=12&limit=24&sort=price&dir=asc
GET /api/v1/product/filters?parent=12 # P1
Checkout:
GET /api/v1/delivery/list
GET /api/v1/payment/list?delivery_id=2
POST /api/v1/order/set { delivery_id, payment_id, ... }
GET /api/v1/order/cost
POST /api/v1/order/submit
Описание функции
Архитектурный RFC: как довести существующий Web API (
api.php→/api/v1) до coherent headless-контракта для Nuxt без rewrite cart/order/customer и без дублирования уже открытых issues #563–#576.Этот issue не заменяет child-issues. Он фиксирует цель, карту зависимостей, что в core / addon, минимальный MVP и roadmap P0–P2.
Проблема, которую решает
Аудит дал пачку точечных issues. Без RFC легко:
ms3.routes.d.Goal
Production Nuxt storefront на инкрементальных добавлениях к
/api/v1:success/message/data+ честный HTTP status);ApiClient.js).Не цели RFC: GraphQL, JWT, отдельный BFF в ядре, Manager API для витрины.
Current API
Источник истины:
config/routes/web.php./api/v1; Token на cart/order/cabinetGET /product/list,GET /product/get/{id}/me— #571customer_id > 0GET /healthУже достаточно для «гостевой корзина + checkout с известными delivery_id/payment_id» (как Fenom). Недостаточно для навигации каталога и выбора доставки/оплаты без хардкода ID.
Proposed API
Инкремент к
/api/v1, те же middleware иResponse.Новые публичные (без TokenMiddleware, как product):
GET /category/list|get/{id}|tree([Feature] Web API: публичный Category API для headless (list / get / tree) #563)GET /product/filtersfacets ([Feature] Web API: product/filters — facets для headless PLP #565) + расширенные query наproduct/list([Feature] Web API: расширенные фильтры product/list для headless #564)GET /delivery/list,GET /payment/list([Feature] Web API: публичный список методов доставки (delivery/list) #568, [Feature] Web API: публичный список методов оплаты (payment/list) #569)seoв get product/category ([Feature] Web API: seo-блок для product/category (headless SSR) #567)images[]в product get (и opt-in list) ([Feature] Web API: галерея изображений товара (images[]) для headless #566)Новые/уточнённые auth:
GET /customer/me(+ документированный TTL/cookie+Bearer) ([Feature] Web API: контракт customer auth для Nuxt SSR (me / TTL / cookie+Bearer) #571)Без смены URL существующих cart/order методов. Нормализация формы
cart/get(#570) и HTTP envelope (#572) — additive / bugfix где status теряется.Architecture
Правила:
/api/mgr/.ms3_routes_web.custom.php/ms3.routes.d/web/*.php([Bug] Api\Index грузит web-роуты через connector без mgr Auth на /api/v1 #384).msOnGetProductPrice|Fieldsостаются; list-perf не отключает их молча ([Feature] Web API: производительность ProductCatalogService (N+1 Data, COUNT, hooks) #575).success([Feature] Web API: единый контракт ошибок и HTTP-статусов для TypeScript/Nuxt #572).Endpoints
Уже в core (сохранить)
Добавить в core (child issues)
Расширения query
product/listи полей get — в #564/#566/#567, не новые path без нужды.Authentication
Текущее: opaque
msCustomerToken; Bearer → MS3TOKEN → cookie httpOnly; guest auto-mint на cart/order.RFC требует:
/me, явный TTL/lifetime в ответах login/token/get, SSR cookie vs Bearer)Catalog
База:
ProductCatalogService+ProductController.P0: list/get + category (#563) + perf list (#575) до тяжёлого трафика.
P1: filters (#564), images (#566).
P2: deep search / synonyms → addon (не Elasticsearch в ядре).
Categories
#563 — list / get / tree. Только published
msCategory. Nested product listing черезparent+ позже member scope в #564.Зависимость: SEO category (#567) после get category.
Filters
#564 — query params на
product/list(price range, vendor, options, nested/members) совместимо с текущимиparent|category,query,sort,limit.Не ломать default без новых params.
Facets
#565 — отдельный
GET /product/filters(counts). Делить с #564 общую модель «filterable fields», не дублировать два диалекта option keys.Зависимость: семантика фильтров #564 (хотя бы черновик контракта) до или вместе с facets.
Merge recommendation: не закрывать issues в один PR обязательно; связать cross-link и общий lexicon ключей. Дубликатами не считать.
Cart
Существующий API достаточен. #570 — стабилизировать
cartobject vs array + totals вstatus. Breaking только если кто-то парсил пустую корзину как[]vs{}— задокументировать / version soft.Checkout
Поток уже есть: address/set → set delivery_id/payment_id → cost → submit.
Блокер UX: #568 + #569 (discovery). Рекомендация merge в один milestone/PR-пакет «checkout discovery» (два route, один сервис pairing как mgr #374).
Delivery
Сейчас: validation-rules / required-fields при выбранной доставке.
Нужно: #568
delivery/list(active + цена/правила кратко).Payment
Сейчас: set
payment_idвслепую.Нужно: #569
payment/list?delivery_id=с member filter.Customers
Auth + addresses + profile уже в core. #571
/me. Email verify оставить.Wishlist / loyalty / social login → addons.
Orders
Cabinet list/get/cancel scoped by
customer_id— OK.Submit redirect payment — сохранить.
Programmatic mgr orders (#507) — другой вход, не витрина.
SEO
#567 — derived
seoblock на product/category get. Не отдельный/seoresource server в MVP.Зависимости: product get есть; category get из #563.
Error contract
#572 — HTTP status через Router::send; стабильные
code/errors; не терять status вgetData()питомниках.Делать рано (P0): иначе #573 и Nuxt types плывут.
Security
#576 — P0 до production CORS headless.
Auth processor RateLimiter (login/register/forgot) уже есть — не дублировать в RFC как gap.
Performance
#575 — N+1 Data, COUNT, hooks на list. P0/P1 до marketing traffic.
Facets (#565) проектировать batch SQL сразу, не N+1 counts.
Backward compatibility
include_images,include_options).Testing strategy
#574 — один Integration WebApi journey (Router boundary).
Плюс unit на каждый child (#575 query count, #576 RL/CORS, #572 status).
Порядок: security + envelope tests раньше полного journey; journey зеленеет по мере появления delivery/payment list (fixture IDs до #568/569).
Documentation
#573 — OpenAPI-ish / TS types от фактического
web.php+ lexicon errors.Писать после #572 и P0 endpoints; обновлять тем же PR что route.
Existing issues map
Duplicates
Явных дублей среди #563–#576 нет. Не закрывать одно как dup другого.
Should merge (implementation packaging, not GitHub close)
Missing dependencies (зафиксировать в child issues)
Over-engineered (out of RFC / addon)
/carts/{id})Core vs addon
Кастом магазинов:
core/config/ms3.routes.d/web/*.php.Minimal API for production Nuxt storefront
MVP (можно открыть магазин с простым PLP):
Ещё не MVP, но production polish: facets, images[], seo, /me, cart shape, docs, full journey CI.
Implementation roadmap
P0 — required for Nuxt MVP
/me+ TTL docs (если SSR cabinet в MVP)P1 — required for production
P2 — future
Альтернативные варианты
/api/v2— без доказанной несовместимости v1; отклонено.Примеры использования
Nuxt SSR PLP:
Checkout:
Критерии приёмки (для этого RFC)
/api/v2в ближайшем roadmap; нет JWT в core без нового RFC.Дополнительный контекст
assets/components/minishop3/api.phpcore/components/minishop3/config/routes/web.php