Система: границы и контракт
Эта страница — живой системный контракт текущего продукта «Колорика». Она фиксирует поддерживаемую границу решения, роли, возможности и инварианты, но не заменяет ролевые инструкции, спецификации отдельных изменений, QA-проверки и техническую документацию.
Оглавление
- Как читать этот документ
- Назначение, бизнес-результаты и не-цели
- Граница и контекст решения
- Что входит в продукт
- Что находится вне продукта
- Контекстная диаграмма
- Операционная среда верхнего уровня
- Заинтересованные стороны, роли и права
- Карта возможностей
- Каталог и контент
- Покупатель, аккаунт, корзина и избранное
- Checkout, платёж и заказ
- Доставка, отмена и возврат
- Управление каталогом, заказами и доступами
- Учёт, остатки и операционная синхронизация
- Управление контентом
- Платформенная эксплуатация
- Критические сквозные сценарии и состояния
- Бизнес-правила и инварианты
- Доменная модель и данные
- Концептуальная модель объектов
- Состояния и жизненные циклы
- Владение, копии и согласованность данных
- Получение, целостность, хранение и удаление
- Внешние интерфейсы
- Атрибуты качества
- Безопасность и приватность
- Производительность и ёмкость
- Надёжность, доступность и восстановление
- Согласованность и идемпотентность
- Удобство и доступность интерфейсов
- Наблюдаемость и сопровождаемость
- Развёртываемость и переносимость
- Ограничения, предположения и зависимости
- Инварианты продукта и настройки компании
- Известные отклонения и уровень доказательств
- Архитектура требований и порядок сопровождения
- Термины и ссылки
1. Как читать этот документ
Статус и область действия
В основном тексте описан поддерживаемый текущий контракт:
- действующая возможность формулируется как наблюдаемый результат, а не как экран, маршрут API или элемент кода;
- слово «должна» или «не должна» обозначает нормативное требование;
- известное нарушение требования не переписывает норму: рядом указывается только ID
из
docs/qa/active-limitations.md; ЖИВ-*означает, что интерфейс реализован, но ещё не доказан на целевом договоре или аккаунте; это не подтверждение и не описание дефекта;- задуманная, но не реализованная функция в текущий baseline не входит;
- пометка
(*)вdocs/feature-inventory.md— сигнал проверить отклонение, а не основание объявить функцию работающей.
Обозначения
| Обозначение | Смысл | Где используется |
|---|---|---|
SYS-CAP-NN | Устойчивая группа возможностей и результат для роли | Раздел 5 |
SYS-BR-NN | Долговечное бизнес-правило или инвариант | Раздел 7 |
SYS-DAT-NN | Требование к доменным данным | Раздел 8 |
SYS-INT-NN | Контракт пересечения внешней границы | Раздел 9 |
SYS-QLT-NN | Проверяемый атрибут качества | Раздел 10 |
SYS-CON-NN | Устойчивое ограничение или зависимость | Раздел 11 |
ОГР-* | Подтверждённое активное отклонение | docs/qa/active-limitations.md |
ЖИВ-* | Не завершённая проверка на живой внешней системе | docs/qa/active-limitations.md |
ПЛТ-* | Осознанное ограничение платформы, а не дефект | docs/qa/active-limitations.md |
ПУТ-* | Пользовательский или операционный путь и его бизнес-риск | docs/qa/user-journeys.md |
TBD | Решение нельзя достоверно вывести из реализации; его должен принять владелец | Блок открытых вопросов в конце страницы |
ID сохраняются при изменении формулировки и не выдаются другому требованию после удаления. Git хранит историю версий; ручной номер документа и журнал правок здесь не ведутся.
Где искать подробности
| Вопрос | Канонический источник |
|---|---|
| Где заканчивается продукт и какие инварианты действуют? | Эта страница |
| Как выполнить действие покупателю или сотруднику? | Раздел покупателя, администратора, владельца или склада |
| Что именно менялось и по каким критериям принималось? | docs/specs/<feature>/spec.md; завершённые контракты — docs/specs/_archive/ |
| Каков бизнес-риск, как проверить поведение и какие отклонения активны? | docs/qa/user-journeys.md, docs/qa/test-cases/, docs/qa/active-limitations.md |
| Что фактически найдено в коде? | docs/feature-inventory.md |
| Как устроены API, фоновые процессы, окружение и эксплуатация? | Раздел разработчика, а также README.md, CLAUDE.md и docs/known-quirks.md |
| Какие общие инженерные и UX-принципы применяются? | docs/specs/constitution.md и docs/specs/storefront-ux-core.md |
При расхождении нормативное ожидание берётся отсюда, текущее отклонение — из
docs/qa/active-limitations.md, а фактическое поведение подтверждается QA, кодом и
живым прогоном. Архивная feature spec объясняет принятое тогда решение, но не
переписывается под новое состояние системы.
2. Назначение, бизнес-результаты и не-цели
Назначение решения
«Колорика» — интернет-магазин лакокрасочных изделий и сопутствующих товаров для автомобилей. Решение связывает публичный путь покупки, управление магазином, складской учёт, оплату, доставку и контент в одном разворачиваемом экземпляре для одной компании.
Наблюдаемые результаты действующего решения
Эти результаты подтверждены реализацией и документацией, но источники не задают владельческие KPI и не доказывают, что перечень является утверждённой бизнес-стратегией.
| Поддерживаемый результат | Как система его обеспечивает | Основные возможности |
|---|---|---|
| Покупатель может найти товар и оформить физический заказ без обязательной регистрации | Каталог, актуализация корзины, выбор доставки, опциональная онлайн-оплата и создание заказа | SYS-CAP-01–SYS-CAP-04 |
| Деньги, корзина и заказ не расходятся при повторных или параллельных сигналах оплаты | Сверка с платёжным провайдером, блокировки, резервы и идемпотентная финализация | SYS-CAP-03 |
| Сотрудники могут вести магазин и восстанавливать критические интеграционные операции | Панель магазина, журнал синхронизации, статусы отправлений, ручные повторы и разграничение доступов | SYS-CAP-04–SYS-CAP-06 |
| Компания может управлять публичным контентом отдельно от выпуска кода | Черновики и публикация CMS, проверка целей и устойчивый снимок для витрины | SYS-CAP-07 |
| Один и тот же программный комплект можно развернуть как отдельный экземпляр другой компании | Автонастройка базового commerce-контура и конфигурируемые подключения при изоляции данных и секретов экземпляра | SYS-CAP-08 |
TBD (решение владельца): [TBD-01] Утвердить, являются ли пять результатов выше целевыми бизнес-результатами продукта, кто владеет каждым результатом и по каким метрикам или наблюдаемым исходам оценивается успех.
Не-цели
Текущая граница не включает встроенную финансовую BI-аналитику, международную доставку, единый мультитенантный runtime для нескольких компаний и полную двустороннюю синхронизацию каталога с МойСклад. Отсутствие этих возможностей само по себе не делает их постоянными не-целями: такого решения владельца в источниках нет.
TBD (решение владельца): [TBD-02] Какие из направлений — международная доставка, встроенная финансовая аналитика, мультитенантность, фискализация онлайн-платежей и полная двусторонняя синхронизация каталога с МойСклад — являются постоянными не-целями, а какие остаются возможным будущим развитием?
Система запрашивает согласие на обработку данных, но действующий юридический и safety-контракт в репозитории не утверждён; видимое отклонение страницы политики зафиксировано как ОГР-14.
TBD (решение владельца): [TBD-03] Какие юридические, приватностные и отраслевые обязательства продукт должен выполнять, включая текст и срок действия согласия, сроки хранения и удаления персональных данных, правила рассылок и ограничения для лакокрасочных или опасных грузов?
3. Граница и контекст решения
3.1. Что входит в продукт
| Часть решения | Ответственность продукта | Статус в границе |
|---|---|---|
| Публичная витрина | Показ каталога и контента, работа с серверной корзиной, checkout, аккаунт и понятные состояния успеха, ошибки и недоступности | Доменная часть продукта |
| Commerce backend и панель магазина | Истина по товарам, вариантам, ценам, продаваемому остатку, корзинам и заказам; серверная валидация, права и оркестрация интеграций | Доменное ядро продукта |
| Панель контента | Черновики и публикация главной, настроек сайта, медиа и SEO-записей; действующие ограничения результата перечислены ссылочно в docs/qa/active-limitations.md | Доменная часть продукта |
| Управляемые фоновые процессы | Обновление остатков, повтор передачи заказов, истечение платёжных корзин, обновление статусов и ПВЗ, снимок CMS, напоминания | Доменная автоматика продукта |
| PostgreSQL, Redis, Meilisearch и S3-совместимое хранилище | Постоянное хранение, координация процессов, поисковая копия и файлы; доменные решения остаются в приложениях | Обязательные классы runtime-сервисов в поставляемом комплекте, но не самостоятельные бизнес-возможности |
| База знаний | Ролевые инструкции, системный контракт и технические runbook-страницы | Сопровождающая часть поставки, не участник commerce-транзакций |
Наличие сервиса в поставляемом комплекте не делает его источником доменной истины. Например, Meilisearch ускоряет выдачу, но не решает, существует ли товар и можно ли его продать.
3.2. Что находится вне продукта
| Внешняя сторона | За что она отвечает | За что продукт всё равно отвечает на границе |
|---|---|---|
| Покупатель и сотрудник | Корректный ввод данных, выбор действий и сохранность собственных учётных данных | Проверить ввод и право на сервере, применить действие не более одного раза и показать однозначный исход |
| МойСклад | Физический складской учёт, номенклатура, доступный остаток и дальнейшая обработка документа заказа | Однозначно сопоставить данные, перенести остаток в продаваемый inventory, передать заказ, не потерять ошибку и дать повтор |
| ЮKassa | Приём и фактический статус онлайн-платежа, возврат средств на стороне эквайринга | Не хранить данные карт, сверить статус и сумму через авторизованный API, создать не более одного заказа и не выполнить двойной возврат |
| СДЭК и ApiShip | Расчёт перевозчика, регистрация и фактическое состояние отправления, печатные формы | Нормализовать варианты, сохранить связь с заказом, не регрессировать статус, обеспечить безопасный повтор и понятную деградацию |
| YouTube и Vimeo | Видеоплеер, доступность видео и обработка прямого запроса браузера | Допускать встраивание только для распознанных источников, обозначить privacy-границу и сохранить внешнюю ссылку как fallback |
| SMTP-сервис и почтовая сеть | Доставка сообщения в почтовый ящик | Сформировать разрешённое уведомление, не раскрыть секреты и не разрушить основную операцию при сбое; активные пробелы повторов перечислены в docs/qa/active-limitations.md |
| Reverse proxy, DNS и TLS-терминация | Публичная маршрутизация, сертификаты и защищённый транспорт до приложений | Корректно работать за доверенной границей, ограничивать разрешённые origins и не считать клиентскую конфигурацию авторизацией |
| Хостинг и внешняя реализация PostgreSQL/Redis/S3/поиска | Ресурсы, сеть, диски, резервирование и доступность выбранного сервиса | Соблюдать доменную модель владения, корректно переживать известные классы отказов и не переносить секреты в публичные данные |
Международные правила перевозки, банковские и складские процессы провайдеров, физическая упаковка/отгрузка и фактическая доставка письма или посылки находятся за границей приложения.
3.3. Контекстная диаграмма
Стрелка показывает пересечение границы, а не владение внешней системой. CMS и инфраструктурные сервисы показаны внутри поставляемого решения; при использовании внешнего managed-сервиса ответственность провайдера начинается только с его доступности и ресурсов, а доменный контракт приложения не меняется.
3.4. Операционная среда верхнего уровня
| Слой | Контракт среды |
|---|---|
| Клиент | Современный браузер открывает публичную витрину, панель магазина, панель контента или базу знаний; права всегда подтверждаются сервером |
| Приложения | Витрина, backend/admin, CMS и документация развёртываются как отдельные серверные приложения и связываются по сетевым интерфейсам |
| Состояние | PostgreSQL хранит постоянные данные приложений; Redis обязателен для production-координации backend; поиск и файлы вынесены в специализированные сервисы |
| Сеть | Публичный экземпляр предполагает HTTPS и reverse proxy; исходящие соединения нужны к платёжной, учётной, доставочным и почтовой системам |
| Изоляция | Один deployment представляет одну компанию. Данные, домены, реквизиты и секреты разных компаний не разделяются внутри общего мультитенантного экземпляра |
| Восстановление | Критические асинхронные операции имеют устойчивое состояние, повтор или ручное восстановление там, где это является частью доменного контракта |
Версии, команды, порты, переменные и порядок запуска находятся в
архитектуре, инфраструктуре,
развёртывании и корневом README.md.
4. Заинтересованные стороны, роли и права
Роли людей
| Роль / профиль | Цель и поверхность | Разрешённый результат | Что не разрешено этой ролью |
|---|---|---|---|
| Покупатель без аккаунта | Публичная витрина | Каталог, серверная корзина, checkout и оплата без регистрации | История заказов, профиль, постоянное избранное, отмена, возврат и отслеживание через кабинет |
| Зарегистрированный покупатель | Витрина и личный кабинет | Всё гостевое плюс профиль, избранное, собственные заказы, отслеживание, допустимая отмена и заявка на возврат | Данные и заказы других покупателей; административные операции |
| Администратор магазина | Панель магазина | Разрешённые ролью стандартные операции с каталогом, заказами, клиентами и доступами; все проектные страницы после входа | Реквизиты оплаты при включённом RBAC без роли Super Admin; любой доступ в панель контента без отдельного аккаунта |
| Супер-администратор | Панель магазина | Полный административный контур, пользователи/роли и реквизиты оплаты | Публикация CMS без отдельной учётной записи Publisher |
| Редактор контента | Панель контента | Создание, чтение и изменение черновиков Homepage, SEO entry, Site settings и работа с медиатекой | Публикация и удаление записей |
| Публикатор контента | Панель контента | Возможности редактора плюс публикация | Удаление записей; операции панели магазина без отдельного аккаунта |
| Владелец продукта / магазина | Утверждение контракта и операционные кабинеты | Принимает решения о целях, границе, правилах и настройках; runtime-действия выполняет через назначенные аккаунты | Отдельной встроенной роли «владелец» нет; название профиля само по себе прав не даёт |
| Складской оператор | Панель магазина и внешняя учётная система | Контроль передачи заказов, остатков, этикеток и физической отгрузки в пределах назначенной Medusa-роли | Отдельной встроенной роли «склад» нет; доступ к МойСклад и Medusa выдаётся независимо |
| Сопровождающий разработчик / оператор | Техническая среда и база знаний | Развёртывание, конфигурация, диагностика и восстановление в пределах внешне выданного инфраструктурного доступа | Инфраструктурный доступ не создаётся и не ограничивается ролями покупателя, Medusa Admin или Strapi |
«Владелец» и «складской оператор» — заинтересованные профили, а не дополнительные механизмы авторизации. Инструкции по назначению прав находятся на страницах пользователей админки и доступов владельца.
Серверные границы привилегированных действий
| Привилегированное действие | Кто вправе инициировать | Где принимается решение | Обязательная серверная граница |
|---|---|---|---|
| Читать и менять профиль, избранное и список заказов | Зарегистрированный покупатель | Customer/Auth и Store API backend | Действующая customer-сессия или bearer-токен; выборка ограничена владельцем ресурса |
| Читать и менять незавершённую корзину | Браузер или получатель ссылки восстановления, знающий идентификатор корзины | Store API backend | Идентификатор корзины действует как bearer capability: customer-сессия, отдельная подпись и срок действия ссылки не проверяются; разглашение идентификатора передаёт доступ к чтению и изменениям |
| Отменить заказ, запросить возврат или отслеживание | Зарегистрированный покупатель — владелец заказа | Защищённый Store API и доменный workflow | Аутентификация, принадлежность заказа и проверка его текущих состояний выполняются до внешнего или необратимого действия |
| Вести товары, варианты, цены, категории, клиентов, заказы, пользователей и роли | При включённом RBAC — администратор с назначенными разрешениями или Super Admin; при выключенном — вошедший администратор | Admin API Medusa | Admin-аутентификация и, когда RBAC включён, серверные разрешения стандартного ресурса; скрытая кнопка не заменяет проверку |
| Повторить финансовый возврат из заказа | Администратор с разрешением order:update | Admin API и workflow возврата | Серверное разрешение, блокировка заказа и идемпотентность возврата |
| Читать или менять реквизиты оплаты | При включённом RBAC — только Super Admin; при выключенном — любой вошедший администратор | Admin API настройки платежей | Серверная проверка режима RBAC и роли; сохранённый секрет наружу не возвращается |
| Настраивать МойСклад, доставку, заявки на возврат и legacy-контент панели магазина | Любой вошедший пользователь Medusa Admin в текущей реализации | Проектные Admin API и страницы | Есть admin-аутентификация, но отдельных permission-проверок по роли для этих страниц нет |
| Создавать и менять черновики CMS | Editor или Publisher | Strapi Admin | Отдельная Strapi-аутентификация и права content type; роли восстанавливаются к заданному набору при старте CMS |
| Публиковать CMS-контент | Только Publisher | Strapi Admin | Серверное право публикации; Editor не может обойти его прямым запросом |
| Удалять записи Homepage, SEO entry и Site settings | Никто из Editor/Publisher | Strapi Admin | Право удаления этим ролям не выдаётся |
| Менять deployment, инфраструктурные секреты или production-данные | Только внешний оператор с отдельно выданным доступом | Хостинг, secret store, БД и поставочная система вне приложений | Ни одна прикладная роль автоматически не даёт такого доступа |
Идентификатор незавершённой корзины является possession-boundary: браузер хранит его локально, а ссылка восстановления передаёт его без подписи и срока действия. Держатель идентификатора может без customer-аутентификации читать состав и менять корзину до её завершения или недоступности. Отдельный публичный запрос проверки статуса платежа также принимает идентификатор корзины без customer-аутентификации, но не должен возвращать профиль или данные чужого заказа. Ни одна из этих границ не является правом роли покупателя.
TBD (решение владельца): [TBD-04] Считать ли текущий доступ любого вошедшего администратора к проектным страницам «МойСклад», «Доставка», «Возвраты» и legacy- контенту допустимым постоянным контрактом или ввести отдельные серверные разрешения?
TBD (решение владельца): [TBD-05] Нужны ли формальные профили прав для владельца и склада, или для каждого сотрудника достаточно индивидуально назначать существующие права Medusa и отдельный доступ к МойСклад?
TBD (решение владельца): [TBD-06] Достаточно ли знания непредсказуемого идентификатора корзины для публичной проверки статуса платежа, или этот read-path должен требовать дополнительное подтверждение покупателя?
TBD (решение владельца): [TBD-13] Допустим ли текущий bearer-доступ к незавершённой корзине по одному идентификатору из ссылки восстановления, или ссылка должна получить подпись, срок действия либо одноразовость?
Машинные участники
Вебхуки ЮKassa, СДЭК и CMS не получают пользовательскую роль. Их право инициировать обработку ограничивается отдельной доверительной границей: проверкой источника, подписи, свежести или последующим чтением факта из авторизованного API. Фоновые задания действуют как часть backend и не расширяют права людей.
5. Карта возможностей
Карта группирует функциональность по наблюдаемому результату. UI, API, workflow, job и хранилище, которые вместе дают один результат, не считаются отдельными возможностями.
SYS-CAP-01. Каталог и контент
- Роли и результат: гость и зарегистрированный покупатель открывают главную, каталог, категории и карточку; ищут и фильтруют товары; видят цену, вариант, наличие, описание и доступные материалы.
- Входы / выходы: опубликованные товары Medusa с непустыми ID, названием, положительной ценой и названием хотя бы одной категории, продаваемый inventory и действующий снимок контента превращаются в навигацию, выдачу, карточку товара и информационные страницы.
- Ключевые правила и данные:
SYS-BR-01–SYS-BR-04,SYS-BR-06;SYS-DAT-01,SYS-DAT-02,SYS-DAT-08. - Основной и альтернативный исходы: доступный товар ведёт к действиям корзины; страница категории дополнительно скрывает неактивную или внутреннюю категорию и ветку с непубличным предком, хотя общие выдача, карточка и проверка корзины этих признаков категории не учитывают; отсутствующая карточка даёт 404, пустая выдача отличается от отказа поиска, а отказ отдельной секции не должен скрывать остальную страницу.
- Внешние интерфейсы:
SYS-INT-06,SYS-INT-09–SYS-INT-11,SYS-INT-14. - Требования к качеству:
SYS-QLT-06,SYS-QLT-11,SYS-QLT-15–SYS-QLT-17,SYS-QLT-19,SYS-QLT-26; UX-инварианты —docs/specs/storefront-ux-core.md. - Проверка / свидетельства:
docs/feature-inventory.md, разделы 1.1–1.5, 1.13, 2.1 и 2.8; ПУТ-9–ПУТ-11, ПУТ-23–ПУТ-25; каталог, категории и карточка товара.
Множественная галерея, переход баннера на коллекцию, онлайн-подбор цвета и
неограниченные справочники брендов/категорий не заявляются работающими: см. ОГР-07,
ОГР-13, ОГР-22, ОГР-24 и ОГР-29 в docs/qa/active-limitations.md. Нарушение
требования к состояниям чтения — ОГР-33.
SYS-CAP-02. Покупатель, аккаунт, корзина и избранное
- Роли и результат: гость ведёт серверную корзину без регистрации; покупатель с аккаунтом управляет профилем, избранным и списками своих заказов, а гостевая корзина при входе объединяется с аккаунтной.
- Входы / выходы: идентификатор корзины в браузере или ссылке восстановления, customer-сессия, профиль и действия над товарами превращаются в серверную корзину, избранное, подстановку контактов и восстановимый покупательский контекст.
- Ключевые правила и данные:
SYS-BR-03,SYS-BR-04,SYS-BR-06,SYS-BR-20;SYS-DAT-03–SYS-DAT-05. - Основной и альтернативный исходы: регистрация и вход открывают кабинет; ссылка из напоминания восстанавливает корзину без customer-аутентификации, а её идентификатор передаёт bearer-доступ к чтению и изменениям; сбой записи не должен выдаваться за применённое действие, а повреждённая локальная ссылка на корзину заменяется новой без утраты серверной модели.
- Внешние интерфейсы:
SYS-INT-05,SYS-INT-07,SYS-INT-08,SYS-INT-11. - Требования к качеству:
SYS-QLT-01,SYS-QLT-06,SYS-QLT-17–SYS-QLT-20. - Проверка / свидетельства:
docs/feature-inventory.md, разделы 1.6, 1.10–1.12, 1.14, 2.4 и соответствующие части 2.5/2.10/2.11; ПУТ-12, ПУТ-15–ПУТ-19, ПУТ-21, ПУТ-22, ПУТ-26 и ПУТ-37; аккаунт, корзина и избранное.
Повторный доступ гостя к заказу, устойчивость UI-состояния «в корзине» и часть почтовых исходов ограничены ОГР-02, ОГР-08, ОГР-09, ОГР-25, ОГР-26 и ОГР-31. Допустимость текущей границы ссылки восстановления корзины требует решения TBD-13.
SYS-CAP-03. Checkout, платёж и заказ
- Роли и результат: гость или зарегистрированный покупатель проходит единую форму checkout, выбирает доступные получение и оплату и получает ровно один заказ; администратор настраивает онлайн-оплату и видит её состояние.
- Входы / выходы: актуальная корзина, контакты, адрес, выбранная доставка и способ оплаты превращаются в платёжную сессию, заказ, номер и зафиксированный состав с суммой.
- Ключевые правила и данные:
SYS-BR-03,SYS-BR-08–SYS-BR-14;SYS-DAT-03,SYS-DAT-05,SYS-DAT-06. - Основной и альтернативный исходы: успешная онлайн-оплата финализирует заказ из возврата покупателя или вебхука; без онлайн-провайдера заказ создаётся в ожидании оплаты; отказ или прерывание оплаты сохраняет корзину для новой попытки.
- Внешние интерфейсы:
SYS-INT-02–SYS-INT-05,SYS-INT-07,SYS-INT-08,SYS-INT-11. - Требования к качеству:
SYS-QLT-02,SYS-QLT-03,SYS-QLT-05,SYS-QLT-08–SYS-QLT-10,SYS-QLT-12,SYS-QLT-16–SYS-QLT-18,SYS-QLT-21. - Проверка / свидетельства:
docs/feature-inventory.md, разделы 1.7–1.9, 2.2, платёжно-заказная часть 2.5 и раздел 5; ПУТ-1–ПУТ-5 и ПУТ-13; оформление заказа и настройка оплаты.
Подтверждающее письмо, маркировка иной валюты как рублей, повторная проверка тарифа ApiShip, фактический режим платёжного подключения, истечение отдельных корзин и объяснение расхождения оплаченной суммы имеют отклонения ОГР-01, ОГР-03, ОГР-04, ОГР-06, ОГР-27 и ОГР-30.
SYS-CAP-04. Доставка, отмена и возврат
- Роли и результат: покупатель выбирает тариф/ПВЗ и отслеживает заказ; покупатель с аккаунтом инициирует допустимую отмену или возврат; администратор восстанавливает отправление, получает этикетку, решает заявку и повторяет финансовый возврат.
- Входы / выходы: корзина и адрес, конфигурация провайдера, заказ, события перевозчика и решение администратора превращаются в выбранный тариф, отправление, трекинг, отмену либо обратную отправку.
- Ключевые правила и данные:
SYS-BR-08,SYS-BR-15–SYS-BR-19;SYS-DAT-05,SYS-DAT-07. - Основной и альтернативный исходы: сбой одного провайдера оставляет варианты другого; ошибка создания отправления не откатывает заказ и допускает повтор; после приёма СДЭК отмена становится заявкой на возврат.
- Внешние интерфейсы:
SYS-INT-02–SYS-INT-05,SYS-INT-07,SYS-INT-08,SYS-INT-11. - Требования к качеству:
SYS-QLT-01–SYS-QLT-03,SYS-QLT-05,SYS-QLT-08–SYS-QLT-10,SYS-QLT-12–SYS-QLT-15,SYS-QLT-17–SYS-QLT-19,SYS-QLT-21. - Проверка / свидетельства:
docs/feature-inventory.md, разделы 2.3, 2.6 и shipping/cancel/return-части 1.7, 1.11, 2.4, 2.5, 2.10, 2.11 и 4; ПУТ-6–ПУТ-8, ПУТ-20, ПУТ-29–ПУТ-32; заказы покупателя и обработка заказа.
Действующий baseline ограничен ОГР-10, ОГР-18, ОГР-20 и ОГР-25; доказательство на целевых подключениях — ЖИВ-01, ЖИВ-02 и ЖИВ-04. ПЛТ-01 и ПЛТ-03 описывают ожидаемую асимметрию адреса и трекинга.
SYS-CAP-05. Управление каталогом, заказами и доступами
- Роли и результат: администратор с назначенными правами ведёт товары, варианты, категории, цены, остатки, промо, клиентов и заказы; Super Admin управляет пользователями/ролями и полным контуром настроек.
- Входы / выходы: проверенные административные изменения превращаются в канонические commerce-данные, операционные статусы, выгрузки и публично доступный каталог.
- Ключевые правила и данные:
SYS-BR-01,SYS-BR-02,SYS-BR-05,SYS-BR-06,SYS-BR-20,SYS-BR-21;SYS-DAT-01,SYS-DAT-02,SYS-DAT-05,SYS-DAT-07. - Основной и альтернативный исходы: валидное действие применяется сервером и инициирует связанные обновления; нарушение уникальности, формата файла или права отклоняется до изменения канонических данных.
- Внешние интерфейсы:
SYS-INT-07,SYS-INT-08,SYS-INT-10,SYS-INT-11. - Требования к качеству:
SYS-QLT-01,SYS-QLT-02,SYS-QLT-04,SYS-QLT-09,SYS-QLT-21,SYS-QLT-27. - Проверка / свидетельства:
docs/feature-inventory.md, commerce-части разделов 2.13, 4.2 и 4.3; ПУТ-28, ПУТ-34 и ПУТ-35; создание товара, организация каталога и пользователи админки.
Встроенной панели финансовой аналитики нет; это текущая граница, а не обещанная возможность. Отчётные обходные пути описаны в разделе владельца.
SYS-CAP-06. Учёт, остатки и операционная синхронизация
- Роли и результат: администратор или складской оператор настраивает подключение, видит качество сопоставления и восстанавливает обмен; система получает остатки, передаёт заказ и отмечает его отмену.
- Входы / выходы: код номенклатуры МойСклад, SKU варианта, внешний остаток и заказ магазина превращаются в продаваемый inventory, внешний документ заказа, журнал и диагностику несопоставленных позиций.
- Ключевые правила и данные:
SYS-BR-05–SYS-BR-07,SYS-BR-15;SYS-DAT-01,SYS-DAT-02,SYS-DAT-05. - Основной и альтернативный исходы: однозначные позиции синхронизируются; сомнительная связь не изменяет остаток и видна сотруднику; сбой заказа не откатывает заказ магазина и уходит в автоматический либо ручной повтор.
- Внешние интерфейсы:
SYS-INT-01,SYS-INT-07,SYS-INT-08,SYS-INT-11. - Требования к качеству:
SYS-QLT-01,SYS-QLT-02,SYS-QLT-07,SYS-QLT-09,SYS-QLT-10,SYS-QLT-15,SYS-QLT-16,SYS-QLT-21,SYS-QLT-27. - Проверка / свидетельства:
docs/feature-inventory.md, разделы 2.7 и доменные части 2.11/4.1/4.2/7; ПУТ-8, ПУТ-31 и ПУТ-33; работа с МойСклад,docs/specs/moysklad-live-fixes/spec.md.
Читающий доступ подтверждён, но полный живой цикл записи и остатков на целевом аккаунте не принят: ЖИВ-03.
SYS-CAP-07. Управление контентом
- Роли и результат: Editor готовит, Publisher публикует главную и настройки сайта; администратор отдельно ведёт фактически используемые legacy-тексты контактов и доставки.
- Входы / выходы: черновики, медиа и типизированные commerce-цели превращаются после проверки в опубликованную ревизию и снимок, который безопасно читает витрина.
- Ключевые правила и данные:
SYS-BR-01,SYS-BR-06,SYS-BR-20,SYS-BR-21;SYS-DAT-08. - Основной и альтернативный исходы: валидная публикация обновляет снимок; недоступная внутренняя цель закрывается fail-closed; сбой webhook компенсируется периодическим чтением, а витрина сохраняет последний успешный снимок.
- Внешние интерфейсы:
SYS-INT-06,SYS-INT-07,SYS-INT-10,SYS-INT-11. - Требования к качеству:
SYS-QLT-01–SYS-QLT-03,SYS-QLT-11,SYS-QLT-15–SYS-QLT-17,SYS-QLT-21,SYS-QLT-27,SYS-QLT-29. - Проверка / свидетельства:
docs/feature-inventory.md, разделы 1.2, 1.13, 1.15, 2.9, 3 и content-часть 4.1; ПУТ-24, ПУТ-25, ПУТ-27, ПУТ-34 и ПУТ-36; контент главной и схема публикации.
Полнота preview, применение SEO-записей, часть legacy-полей и атомарность обновления снимка ограничены ОГР-15, ОГР-16, ОГР-23 и ОГР-28.
SYS-CAP-08. Платформенная эксплуатация
- Роли и результат: сопровождающий поддерживает развёрнутый комплект; приложения получают обязательную базовую конфигурацию, фоновые механизмы и возможность восстановить поисковую копию.
- Входы / выходы: конфигурация экземпляра и доступность runtime-сервисов превращаются в работающие web/backend/CMS/docs, инициализированный commerce-контур, индекс и файлы.
- Ключевые правила и данные:
SYS-BR-06,SYS-BR-15,SYS-BR-21;SYS-DAT-01–SYS-DAT-08. - Основной и альтернативный исходы: штатный запуск подготавливает постоянное состояние до приёма трафика; временный отказ не должен менять источники истины на кэш или индекс.
- Внешние интерфейсы:
SYS-INT-07–SYS-INT-11; runtime-сервисы могут поставляться рядом или как managed dependencies. - Требования к качеству:
SYS-QLT-02,SYS-QLT-10,SYS-QLT-11,SYS-QLT-15,SYS-QLT-16,SYS-QLT-21,SYS-QLT-22,SYS-QLT-24–SYS-QLT-27. - Проверка / свидетельства:
docs/feature-inventory.md, служебные части 1.1/1.16, 2.8/2.11–2.13, инфраструктурные части 3.3/4.3, разделы 6 и 7; архитектура, инфраструктура и развёртывание.
Покрытие реестра функциональности
Таблица ниже — контроль классификации docs/feature-inventory.md. Если раздел
смешанный, перечислены именно его части; одна и та же наблюдаемая функция не должна
получать две группы.
| Область реестра | Единственный владелец результата |
|---|---|
| 1.1: навигация и публичный shell | SYS-CAP-01; счётчик/связь с корзиной — SYS-CAP-02; telemetry и proxy-механика — SYS-CAP-08 |
| 1.2–1.5: главная, каталог, категории, чтение карточки | SYS-CAP-01; изменение корзины/избранного — SYS-CAP-02; «Купить в 1 клик» как вход в checkout — SYS-CAP-03 |
| 1.6: корзина | SYS-CAP-02; проверка перед финальным оформлением — SYS-CAP-03 |
| 1.7: форма и оркестрация checkout | SYS-CAP-03; расчёт тарифов и ПВЗ — SYS-CAP-04 |
| 1.8–1.9: платёжный возврат и подтверждение заказа | SYS-CAP-03 |
| 1.10–1.12: auth, профиль, списки заказов, избранное | SYS-CAP-02; отмена, возврат и tracking заказа — SYS-CAP-04 |
| 1.13–1.15: информационные страницы, отписка, preview | чтение страниц — SYS-CAP-01; отписка — SYS-CAP-02; preview — SYS-CAP-07; неработающие обещания остаются только в ОГР-* |
| 1.16: health, proxy, cache, error boundary и общие примитивы | внутренние/служебные механизмы SYS-CAP-08; пользовательский 404 и рекомендации — SYS-CAP-01 |
| 2.1: публичные операции | чтение каталога — SYS-CAP-01; проверка корзины и оформление — SYS-CAP-03; выдача контента сайта и CMS-снимка — SYS-CAP-07; runtime-конфигурация и CORS — SYS-CAP-08 |
| 2.2 и 5: платёжные операции и ЮKassa | SYS-CAP-03 |
| 2.3 и 2.6: доставка | SYS-CAP-04 |
| 2.4: профиль, auth, wishlist, merge и unsubscribe | SYS-CAP-02; cancel/return/tracking — SYS-CAP-04 |
| 2.5: заказ, оплата, резервы и промо | SYS-CAP-03; merge/wishlist — SYS-CAP-02; cancel/refund — SYS-CAP-04; безопасная очистка файлов товара — служебная часть SYS-CAP-05 |
| 2.7: МойСклад | SYS-CAP-06 |
| 2.8: поисковая выдача и её семантика | SYS-CAP-01; поддержание и восстановление индекса — SYS-CAP-08 |
| 2.9: снимок и проверка контента | SYS-CAP-07 |
| 2.10: письма | reset/брошенная корзина — SYS-CAP-02; отмена/возврат — SYS-CAP-04; транспорт провайдера — внутренний механизм SYS-CAP-08 |
| 2.11: доменные jobs | abandoned cart — SYS-CAP-02; payment expiry — SYS-CAP-03; shipping/PVZ — SYS-CAP-04; МойСклад — SYS-CAP-06; CMS snapshot — SYS-CAP-07; scheduler/event bus — SYS-CAP-08 |
| 2.12–2.13: первый запуск и runtime | SYS-CAP-08; SKU и документы товара — проверки SYS-CAP-05 |
| 3.1–3.3: CMS-модели, роли и публикация | SYS-CAP-07; БД, S3, runtime-конфигурация и миграционные/seed-скрипты — внутренние механизмы SYS-CAP-08 |
| 4.1: проектные разделы админки | payment — SYS-CAP-03; shipping/returns — SYS-CAP-04; site content — SYS-CAP-07; МойСклад — SYS-CAP-06 |
| 4.2: виджеты | order details/product content — SYS-CAP-05; shipping/refund — SYS-CAP-04; МойСклад — SYS-CAP-06 |
| 4.3: пользователи, роли и RBAC | SYS-CAP-05; клиент и локализация расширений — внутренний механизм SYS-CAP-08 |
| 6: инфраструктура | внутренние/служебные механизмы SYS-CAP-08, не отдельные продуктовые возможности |
| 7: служебные инструменты | импорт из МойСклад поддерживает SYS-CAP-06; probes, benchmark, reindex и seeds — внутренние инструменты соответствующих групп, не самостоятельные возможности |
6. Критические сквозные сценарии и состояния
Здесь оставлены семь P0 или сложных межсистемных сценариев. Подробные шаги и
Given/When/Then не повторяются: они принадлежат docs/qa/user-journeys.md и
docs/qa/test-cases/.
Критические сценарии
| Сценарий | Основной результат | Альтернатива или отказ | Связи и доказательство |
|---|---|---|---|
| Актуализация корзины перед покупкой | При показе корзины и в начале checkout система читает текущую каталоговую цену, публикацию и остаток; на серверной границе блокируются неопубликованные, непродаваемые или превышающие управляемый остаток позиции | Проблемная позиция остаётся видимой, оформление блокируется до уменьшения количества или удаления. При финализации уже оплаченной корзины текущая каталоговая цена и публикация повторно не сверяются | SYS-CAP-01–SYS-CAP-03; SYS-BR-01–SYS-BR-04; ПУТ-5, ПУТ-13 |
| Доставка и онлайн-оплата до одного заказа | Покупатель выбирает курьера или ПВЗ, платит у ЮKassa; возврат на сайт и webhook сходятся в одну идемпотентную финализацию | Ошибка одного перевозчика оставляет второго; прерванная/отклонённая оплата не создаёт заказ и сохраняет корзину | SYS-CAP-03, SYS-CAP-04; SYS-BR-08, SYS-BR-10–SYS-BR-13; ПУТ-1, ПУТ-2, ПУТ-4 |
| Заказ без онлайн-оплаты | При отсутствии доступного online-провайдера валидная корзина с доставкой становится заказом, ожидающим оплату | Отсутствие доставки остаётся блокером; отсутствие онлайн-оплаты — нет | SYS-CAP-03; SYS-BR-08, SYS-BR-09; ПУТ-3 |
| Остаток из МойСклад до статуса на витрине | Однозначно сопоставленный остаток переносится в Medusa, наличие вычисляется и индекс обновляется как копия | Неоднозначная позиция не применяется и попадает в диагностику; карточка и checkout опираются на Medusa, даже если индекс отстаёт | SYS-CAP-01, SYS-CAP-06, SYS-CAP-08; SYS-BR-02, SYS-BR-05–SYS-BR-07; ПУТ-13, ПУТ-33 |
| Автоматика после создания заказа | Отдельные обработчики создают отправление и передают копию заказа в МойСклад; сотрудник получает этикетку и контрольные статусы | Сбой одной интеграции не откатывает заказ и не блокирует вторую; ошибка видна и восстанавливается автоматическим или ручным повтором | SYS-CAP-04, SYS-CAP-06; SYS-BR-15; ПУТ-8, ПУТ-31, ПУТ-32 |
| Отмена заказа и возврат оплаты | Допустимая отмена сначала согласуется с перевозчиком, затем отменяет заказ; оплаченная отмена запускает идемпотентный возврат денег | Отказ перевозчика не меняет состояния; после приёма СДЭК создаётся заявка на возврат; сбой денег виден для ручного повтора | SYS-CAP-04; SYS-BR-16–SYS-BR-18; ПУТ-6, ПУТ-7 |
| Возврат после передачи отправления | Покупатель с аккаунтом создаёт одну заявку; администратор отклоняет её или подтверждает создание обратной отправки | Повтор решения не создаёт дубль, смена принятого решения запрещена; денежный возврат выполняется отдельно после операционного решения | SYS-CAP-04; SYS-BR-17–SYS-BR-19; ПУТ-20, ПУТ-30 |
Независимые оси состояния
Состояние заказа, платежа, отправления и возврата не сворачивается в один общий статус. Вкладки «в работе» и «история» — представление для покупателя, а не новое состояние заказа.
Переход на диаграмме показывает подтверждённое проектом направление. Статусы «требует действия» и «в архиве» видимы в кабинете, но проект не задаёт для них свою схему переходов поверх стандартной модели Medusa. Переход не означает, что соседняя ось меняется автоматически: например, подтверждение заявки создаёт обратную отправку, но само по себе не возвращает деньги и не меняет финансовый статус.
7. Бизнес-правила и инварианты
Продаваемость, цена и источник истины
| ID | Требование | Основание / источник | Проверка / свидетельство |
|---|---|---|---|
SYS-BR-01 | Общая граница публичной продажи должна принимать товар только при статусе published, непустых ID и названии, положительной цене и непустом названии хотя бы одной категории; показанная валюта должна соответствовать валюте выбранной цены. Страница категории дополнительно должна принимать только активную невнутреннюю категорию, все предки которой также публичны; общие выдача, карточка и проверка корзины эти признаки категории не проверяют. Текущее нарушение маркировки валюты — ОГР-03. | docs/feature-inventory.md, §2.1; финансовая однозначность | docs/qa/test-cases/01-catalog-search.md, 02-product-cart.md; ОГР-03 |
SYS-BR-02 | Система должна вычислять наличие, а не хранить его как редактируемое бизнес-поле: вариант без управляемого inventory — «в наличии» без количественного ограничения; при управляемом inventory остаток больше нуля — «в наличии»; нулевой остаток с backorder — «под заказ»; иначе — «нет в наличии». | docs/specs/storefront-ux-core.md; CLAUDE.md; стандартный inventory Medusa | docs/qa/test-cases/01-catalog-search.md, 02-product-cart.md |
SYS-BR-03 | При начале checkout и прямом создании заказа без онлайн-оплаты сервер повторно проверяет публикацию, продаваемость и доступный управляемый остаток; недопустимая позиция блокирует действие. Общей сверки текущей каталоговой цены с ценой позиции корзины нет; при финализации оплаченной корзины повторная каталоговая проверка не выполняется, а заказ получает сохранённую цену корзины. | Текущая граница валидации checkout; docs/specs/storefront-ux-core.md | ПУТ-5, ПУТ-13; docs/qa/test-cases/02-product-cart.md, 03-checkout-shipping.md |
SYS-BR-04 | Штатная витрина ограничивает количество одной позиции целым значением от 1 до 99. Checkout на сервере приводит положительное конечное значение к целому без верхнего предела и блокирует превышение доступного остатка только для управляемого inventory без backorder. Повторное добавление в штатной витрине увеличивает существующую позицию. | docs/feature-inventory.md, §1.5–1.6; docs/specs/storefront-ux-core.md | ПУТ-11–ПУТ-13; docs/qa/test-cases/02-product-cart.md |
SYS-BR-05 | SKU варианта необязателен, но после удаления внешних пробелов должен быть уникален; для обмена с МойСклад он обязан однозначно совпадать с полем «Код» номенклатуры. Неоднозначное соответствие не применяется. | CLAUDE.md; docs/specs/moysklad-live-fixes/spec.md; целостность каталога | ПУТ-33; docs/qa/test-cases/09-admin-operations.md; диагностика МойСклад |
SYS-BR-06 | При расхождении данные разрешаются по владельцу: Medusa/PostgreSQL — товары, категории, цены, продаваемый inventory, корзины и заказы; ЮKassa — факт оплаты; перевозчик — факт отправления; Strapi — опубликованный CMS-контент. Meilisearch и локальные интеграционные записи являются копиями. | Матрица владения docs/qa/business-overview.md | Карточка товара против устаревшего индекса; сверка платежа; tracking; обновление CMS-снимка |
SYS-BR-07 | При переносе остатка из МойСклад система должна вычесть неотменённые заказы витрины за последние 48 часов и ограничить результат снизу нулём, чтобы задержка внешнего учёта не создавала повторную продажу уже обещанного товара. | docs/feature-inventory.md, §2.7; складской контур | ПУТ-13, ПУТ-33; отчёт полного цикла синхронизации |
Checkout, платёж и заказ
Отправление, отмена и возврат
Доступ и чувствительные действия
8. Доменная модель и данные
8.1. Концептуальная модель объектов
Модель описывает бизнес-смысл и связи, а не способ физического хранения. Цена, остаток, платёж и отправление относятся к варианту, корзине или заказу независимо друг от друга; их нельзя сводить в один общий статус.
8.2. Состояния и жизненные циклы
| Объект | Поддерживаемые переходы | Запрещённое смешение или переход |
|---|---|---|
| Товар и вариант | Черновик или скрытый товар → опубликованный → скрытый либо удалённый; вариант создаётся, изменяется или удаляется внутри товара | Публикация сама по себе не делает неполный товар продаваемым; удалённый или скрытый товар не должен оставаться доступным из поисковой копии |
| Остаток | Текущее количество изменяется административно или очередным циклом МойСклад; резерв временно уменьшает доступное количество и переносится с корзины на заказ | Нельзя редактировать отдельный статус наличия или отпускать резерв между оплаченной корзиной и заказом |
| Корзина | Активна → ожидает онлайн-оплату → завершена заказом либо платёж истёк; после отказа оплаты возвращается к новой попытке | Отказ оплаты не создаёт заказ; истечение освобождает резерв, но не считается удалением корзины |
| Покупатель | Гость → аккаунт после регистрации; аккаунт → активная или истёкшая сессия | Регистрация прежнего гостя не должна создавать вторую покупательскую личность с тем же нормализованным email |
| Заказ | В кабинет без преобразования передаются и показываются статусы ожидания обработки, завершения, архива, отмены и требуемого действия. Проектные пути явно создают заказ в ожидании, а затем могут завершить или отменить его; другие переходы остаются стандартной границей Medusa | «В работе» и «История» — группы кабинета, а не состояния заказа: отменённый заказ или заказ с отменённой/доставленной доставкой попадает в историю, всё остальное — в работу. Сбой отправления, учёта или письма не откатывает заказ |
| Платёж | Не начат → ожидается → авторизован/подтверждён либо отменён; подтверждён → возврат в обработке → возвращён либо ошибка возврата → повтор | Сигнал webhook не равен подтверждённым деньгам; повтор не создаёт новый заказ или второй возврат той же суммы |
| Отправление | Не создано → создаётся → создано/ошибка → принято → в пути → доставлено либо отменено; ошибка допускает повтор | Неизвестный, устаревший или регрессирующий статус не перезаписывает принятый; состояние отправления не заменяет состояние заказа |
| Заявка на возврат | Нет → ожидает решения → отклонена либо подтверждена → обратная отправка → завершение обратной доставки | Одновременно ожидает не более одной заявки; принятое решение не меняется; финансовый возврат выполняется отдельно |
| Контент | Черновик → публикация → согласованный снимок; новая публикация заменяет публичную ревизию после проверки | Более старая или нестабильная ревизия не перезаписывает новый снимок; preview не становится публикацией |
8.3. Владение, копии и согласованность данных
| Объект | Владелец данных | Копии и внешние представления | Разрешение расхождения и окно согласования | Чувствительность |
|---|---|---|---|---|
| Товар, вариант, категория и цена | Commerce backend / Medusa | Meilisearch; разовый импорт может создать исходную копию из МойСклад | Medusa побеждает; индекс обновляется событием или полной переиндексацией. Копия не подтверждает продаваемость | Публичные после публикации; черновики и закупочная информация — административные |
| Остаток и наличие | Medusa принимает решение о продаже; МойСклад поставляет физический остаток для включённого обмена; для варианта без управляемого inventory количественный остаток не ограничивает продажу | Meilisearch хранит вычисленное наличие; МойСклад хранит внешний складской факт | Следующий цикл МойСклад — каждые 15 минут; из внешнего остатка вычитаются заказы последних 48 часов. Карточка и checkout читают Medusa, индекс исправляется повторной синхронизацией | Операционные данные магазина |
| Корзина и резерв | Medusa | В браузере и ссылке восстановления хранится идентификатор корзины; платёжный провайдер знает связанную операцию | Серверная корзина перечитывается перед покупкой; потеря идентификатора теряет ссылку, а не серверные данные, тогда как его разглашение передаёт bearer-доступ к чтению и изменениям без customer-аутентификации. Неоплаченная сессия попадает в выборку истечения после 24 часов и обрабатывается часовым заданием | Контакты и адрес могут быть персональными |
| Покупатель и избранное | Medusa Customer/Auth | SMTP получает адрес и содержание отдельного письма | Нормализованный email связывает гостевые и аккаунтные заказы; серверное владение ресурса сильнее локального состояния браузера | Персональные и аутентификационные данные |
| Заказ | Medusa | Документ заказа в МойСклад; письмо покупателю; представление в кабинете | Заказ Medusa не удаляется и не откатывается из-за сбоя копии; журнал обмена и ручной повтор исправляют МойСклад | Персональные, коммерческие и финансовые данные |
| Платёж и денежный возврат | ЮKassa владеет фактом списания и возврата; Medusa — связью с корзиной/заказом и локальным состоянием | Webhook и browser-return — только сигналы; локальные транзакции — подтверждённое представление | Перед финализацией или возвратом Medusa перечитывает провайдера и сверяет ID, сумму и валюту; расхождение блокирует действие | Финансовые данные без реквизитов банковской карты |
| Отправление | СДЭК или перевозчик за ApiShip владеет фактическим исполнением | Medusa хранит связь, последний статус, трек-номер и журнал событий; локальная копия ПВЗ СДЭК | СДЭК сходится по webhook, ApiShip — прямым чтением с 60-секундным кэшем и часовым опросом; регрессии игнорируются | Адрес, телефон и состав отправления — персональные/операционные |
| Заявка на возврат | Medusa владеет решением; СДЭК исполняет обратную отправку | Обратный заказ СДЭК и локальный последний статус | Стабильный номер позволяет найти уже созданную обратную отправку; повтор решения не создаёт копию | Персональные и операционные данные; причина возврата может быть чувствительной |
| Контент и медиа | Strapi владеет черновиком и публикацией; Medusa — принятым снимком | Витрина читает снимок; S3 хранит публичные файлы; legacy-тексты контактов и доставки отдельно принадлежат Medusa Admin | Валидная публикация подхватывается webhook или минутным чтением; при сбое остаётся предыдущий снимок. Повреждение одной записи влияет на весь снимок — ОГР-28 | Черновик и preview не входят в публичный снимок, но байты загруженного CMS-медиа доступны по известному объектному URL независимо от публикации |
8.4. Получение, целостность, хранение и удаление
| Объект | Как возникает или обновляется | Контроль целостности | Хранение и удаление |
|---|---|---|---|
| Товар и вариант | Административное действие либо отдельный разовый импорт | Для общей границы продажи — публикация, непустые ID, название и имя хотя бы одной категории, положительная цена; для страницы категории — также активность, отсутствие внутреннего признака и публичность предков; SKU уникален, когда задан | Живут до административного скрытия/удаления; удаление товара очищает только больше нигде не используемые документы. Автоматический срок удаления не установлен |
| Остаток | Административное изменение или однозначное сопоставление с МойСклад | Один SKU ↔ один код; неоднозначная позиция пропускается; результат не ниже нуля | Хранится текущее значение inventory; отдельная история остатков и срок её хранения не входят в подтверждённый контракт |
| Корзина и резерв | Серверные действия покупателя; идентификатор сохраняется браузером или передаётся ссылкой восстановления | Витрина ограничивает количество 1–99; сервер в checkout приводит положительное значение к целому и проверяет публикацию/остаток, но не универсально повторно сверяет текущую цену и не применяет верхний предел 99; оплата и финализация защищены блокировками; владение незавершённой корзиной определяется знанием bearer-идентификатора — TBD-13 | Платёжная сессия становится кандидатом на истечение через 24 часа и проверяется часовым заданием. Срок удаления самой корзины и её персональных данных не утверждён — TBD-03 и TBD-09 |
| Покупатель | Гостевой checkout, регистрация или изменение профиля | Email нормализуется; права проверяются сервером; wishlist защищён от дублей | Срок хранения, удаление аккаунта и обезличивание заказов не утверждены — TBD-03 |
| Заказ | Только успешная серверная финализация валидной корзины | Одна связь корзина–заказ, фиксированные сумма/валюта, перенос резервов без окна освобождения | Автоматическое удаление не заявлено. Юридический срок и порядок удаления/обезличивания персональных данных — TBD-03 |
| Платёж | Ответ ЮKassa после сверки с локальной сессией | Совпадение ID, суммы и валюты; возврат не выше невозвращённой суммы; повтор не создаёт вторую транзакцию | Карточные данные не поступают. Состояние отдельных workflow хранится 3 или 90 дней, но это не утверждённый срок хранения платёжных данных; решение — TBD-03 и TBD-09 |
| Отправление и возврат | Ответ/событие перевозчика и решение покупателя или администратора | Уникальность активного отправления и ожидающей заявки, монотонность статуса, идемпотентное решение | Автоматическое удаление не заявлено; срок хранения связи заказа, адреса, журналов и заявок — TBD-03 и TBD-09 |
| Контент и медиа | Черновик и публикация CMS либо изменение двух legacy-страниц в Medusa Admin | Строгая схема, допустимые цели и форматы, совпавшие ревизии, запрет отката снимка | Текущий снимок заменяется принятой ревизией; Editor/Publisher не могут удалять записи. Общий срок хранения черновиков, старых ревизий и неиспользуемых CMS-медиа не утверждён — TBD-09 |
9. Внешние интерфейсы
Карточки описывают ответственность на границе. Протокольные поля, маршруты и операционные команды находятся в dev-документации.
SYS-INT-01. МойСклад
| Поле | Контракт |
|---|---|
| Назначение и направление | МойСклад → продукт: физические остатки. Продукт → МойСклад: копия нового заказа и отметка его отмены. Регулярного двустороннего обмена каталогом, ценами и статусами исполнения нет |
| Данные и источник истины | SKU варианта сопоставляется только с кодом номенклатуры. Medusa остаётся владельцем продаваемого inventory и заказа; МойСклад — внешний источник физического остатка и исполнитель учётного документа |
| Авторизация / доверительная граница | Реквизиты проверяются перед сохранением, хранятся зашифрованно и целиком обратно не выдаются; доступ задаётся отдельным аккаунтом компании |
| Триггер и синхронность | Заказ отправляется событием после оформления; необходимость повтора проверяется каждую минуту. Остатки читаются фоновым циклом каждые 15 минут |
| Успех | Заказ связан с единственным внешним документом; отмена отмечена отдельно; цикл остатков завершён отчётом, а все однозначные позиции применены |
| Таймаут, повтор, идемпотентность | Текущий HTTP-таймаут — 30 секунд; общий вес запросов — не более 45 за 3 секунды; при 429 — до трёх транспортных повторов. Доменный повтор заказа идёт через 1, 5, 30, 120 и 720 минут, всего до шести попыток с первой. Повтор ищет уже созданный документ и не делает второй |
| Деградация и действия оператора | Заказ магазина сохраняется. После исчерпания автоматических попыток запись остаётся с ошибкой; складской оператор исправляет реквизиты/SKU или внешний документ и запускает ручной повтор. При сбое остатков покупатель видит последнее значение Medusa; оператор сверяет отчёт |
| Настройка экземпляра | Администратор или складской оператор вводит реквизиты и включает обмен; ключ шифрования задаёт оператор deployment. Полный живой цикл «Колорики» ещё не принят — ЖИВ-03 |
| Подробности и свидетельства | Устройство МойСклад, инструкция склада, docs/specs/moysklad-live-fixes/, ПУТ-8, ПУТ-31, ПУТ-33 |
SYS-INT-02. ЮKassa
| Поле | Контракт |
|---|---|
| Назначение и направление | Продукт создаёт и проверяет онлайн-платёж, отменяет его и запрашивает полный или частичный возврат; ЮKassa присылает уведомление об изменении |
| Данные и источник истины | ЮKassa владеет фактом денег. Продукт хранит связь операции с корзиной/заказом, сумму, валюту и локальное состояние; уведомление не является источником статуса |
| Авторизация / доверительная граница | Исходящие операции используют сохранённые зашифрованные реквизиты. Входящий webhook допускается только от доверенного адреса/цепочки proxy, затем факт перечитывается через авторизованный API. Данные карт продукту не передаются |
| Триггер и синхронность | Покупатель синхронно начинает оплату и проверяет статус; browser-return и webhook независимо публикуют запрос асинхронной финализации. Возврат после отмены также выполняется асинхронно |
| Успех | ID операции, сумма и валюта совпали с локальной сессией; одна корзина дала не более одного заказа, а подтверждённый возврат увеличил общую возвращённую сумму на ожидаемое значение |
| Таймаут, повтор, идемпотентность | Продуктовый таймаут внешнего API в источниках не закреплён. Повтор инициации переиспользует пригодную сессию; финализация блокируется по корзине; webhook дедуплицируется; временный отказ просит провайдера повторить; event bus повторяет выброшенную ошибку до пяти раз. Возврат имеет ключ идемпотентности |
| Деградация и действия оператора | Способ остаётся видимым по настройке, даже когда API недоступен; ошибка проявляется при операции, корзина сохраняется. Super Admin проверяет включение и реквизиты, затем состояние провайдера; ошибку возврата повторяет из заказа |
| Настройка экземпляра | Super Admin сохраняет реквизиты и включает способ; оператор deployment задаёт отдельный ключ шифрования и доверенную proxy-границу. Подпись «тестовый/боевой» не выбирает фактический контур — ОГР-06 |
| Подробности и свидетельства | Устройство оплаты, настройка оплаты, docs/specs/_archive/payment-providers/, ПУТ-1, ПУТ-4, ПУТ-7, ПУТ-28 |
SYS-INT-03. СДЭК
| Поле | Контракт |
|---|---|
| Назначение и направление | Продукт получает договорные тарифы и ПВЗ, создаёт/отменяет прямое и обратное отправление и получает этикетку; СДЭК присылает статусы и готовность печатной формы |
| Данные и источник истины | СДЭК владеет фактическим отправлением. Продукт хранит его связь с заказом, последний принятый статус, трек-номер, выбранный тариф и локальную копию ПВЗ |
| Авторизация / доверительная граница | Реквизиты и webhook-секрет хранятся зашифрованно. Входящее событие проверяется HMAC в постоянном времени; фактический контракт подписи требует подтверждения провайдера — ЖИВ-02 |
| Триггер и синхронность | Тарифы и выбор ПВЗ — синхронная часть checkout; отправление создаётся асинхронно после заказа; статусы приходят webhook; ПВЗ обновляются ежедневно |
| Успех | Возвращён допустимый тариф/ПВЗ; внешний заказ найден или создан и не отклонён; событие применено один раз без регрессии; этикетка связана с отправлением |
| Таймаут, повтор, идемпотентность | Авторизация и тарифы ограничены примерно 8 секундами. Создание сериализуется ожиданием до 20 секунд и после потери ответа ищет заказ по стабильному номеру; этикетка переиспользует UUID и блокируется до 15 секунд. UUID webhook уникален |
| Деградация и действия оператора | Сбой расчёта убирает только тарифы СДЭК; тарифы ApiShip сохраняются. Сбой создания не откатывает заказ и виден для ручного повтора. Администратор проверяет реквизиты, коробку, договор и статус; владелец предоставляет договор/доступы |
| Настройка экземпляра | Администратор задаёт договор, отправителя, тарифы и видимость; оператор deployment — ключ шифрования и адрес целевого контура. Сквозной путь целевого договора «Колорики» не принят — ЖИВ-01 |
| Подробности и свидетельства | Устройство доставки, настройка, docs/specs/shipping-providers/, ПУТ-2, ПУТ-6, ПУТ-20, ПУТ-29–ПУТ-30 |
SYS-INT-04. ApiShip
| Поле | Контракт |
|---|---|
| Назначение и направление | Продукт через установленный плагин получает тарифы и ПВЗ подключённых перевозчиков, создаёт/отменяет отправление, получает этикетку и читает tracking |
| Данные и источник истины | Фактическое отправление принадлежит перевозчику за ApiShip; продукт хранит связь и нормализованное представление статуса. Цена, выбранная в checkout, относится к заказу Medusa |
| Авторизация / доверительная граница | Реквизиты и подключения принадлежат отдельной панели плагина; требование к хранению и возврату секрета сейчас нарушено — ОГР-32. Видимость ApiShip в checkout не доказывает, что хотя бы один перевозчик настроен |
| Триггер и синхронность | Тарифы/ПВЗ читаются синхронно; отправление создаётся после заказа; tracking читается по запросу покупателя и часовым фоновым опросом |
| Успех | Тарифы нормализованы и дедуплицированы; отправление имеет внешний ID; status не регрессирует; этикетка доступна сотруднику |
| Таймаут, повтор, идемпотентность | Каждый отдельный незавершённый запрос браузера к backend при расчёте прекращается через 10 секунд; единого десятисекундного предела для всей последовательности и подтверждённого предела запроса backend к ApiShip нет. Этикетка ограничена 15 секундами. Tracking кэшируется 60 секунд, параллельные чтения объединяются. Повтор создания/этикетки предусмотрен плагином и административным действием; цена при финализации сейчас не перечитывается — ОГР-04 |
| Деградация и действия оператора | Сбой убирает тарифы ApiShip, не скрывая СДЭК; сбой отправления не откатывает заказ и допускает повтор. Администратор проверяет подключения перевозчиков и видимость, затем передаёт транспортную ошибку сопровождающему |
| Настройка экземпляра | Подключения перевозчиков и их реквизиты настраиваются в панели ApiShip; отдельный переключатель управляет видимостью на витрине. Операции записи на целевом подключении не приняты — ЖИВ-04 |
| Подробности и свидетельства | Устройство доставки, настройка, docs/specs/_archive/apiship-plugin-integration/, ПУТ-2, ПУТ-6, ПУТ-29, ПУТ-32 |
SYS-INT-05. SMTP и почтовая сеть
| Поле | Контракт |
|---|---|
| Назначение и направление | Продукт отправляет письма восстановления доступа, напоминания и уведомления о заказных событиях; почтовая сеть отвечает за доставку в ящик |
| Данные и источник истины | Продукт владеет событием и шаблоном; SMTP получает адрес, тему, тело и допустимые вложения. Факт принятия сервером не доказывает доставку адресату |
| Авторизация / доверительная граница | Доступ к SMTP задаётся только в конфигурации deployment; секреты не возвращаются клиенту и не должны попадать в логи |
| Триггер и синхронность | Письмо вызывается событием или ежедневным заданием; основная операция не ждёт гарантированной доставки |
| Успех | Вызов уведомления завершился без ошибки для инициатора; для напоминания после этого записывается отметка. Провайдер подавляет ошибку SMTP, поэтому такой исход не доказывает ни принятие SMTP-сервером, ни доставку/прочтение |
| Таймаут, повтор, идемпотентность | Продуктовый таймаут production SMTP не закреплён. Ошибки подавляются; автоматического повтора reset, отмены и решения по возврату нет. Напоминание может как получить ложную отметку после транспортной ошибки, так и прийти дублем при обратном разрыве — ОГР-25, ОГР-26, ОГР-31 |
| Деградация и действия оператора | Заказ, отмена, возврат и reset-запрос продолжаются, но письмо может отсутствовать. Оператор восстанавливает SMTP; администратор связывается с покупателем вручную там, где это требует процесс |
| Настройка экземпляра | Оператор задаёт сервер, отправителя и реквизиты компании; изменение набора шаблонов требует изменения продукта |
| Подробности и свидетельства | Окружение: почта, письма покупателя, docs/feature-inventory.md, §2.10–2.11; ПУТ-8, ПУТ-26, ПУТ-37 |
SYS-INT-06. Strapi CMS
| Поле | Контракт |
|---|---|
| Назначение и направление | Strapi принимает черновики и публикации; backend проверяет цели, читает согласованную публикацию и формирует снимок; preview выдаётся только авторизованному редакционному потоку |
| Данные и источник истины | Strapi владеет черновиком и опубликованной ревизией; Medusa владеет последним принятым снимком; витрина напрямую CMS не читает |
| Авторизация / доверительная граница | Чтение использует отдельный read-доступ; публикационный webhook подписан и имеет пятиминутное окно; preview использует два независимых секрета и токен на 10 минут |
| Триггер и синхронность | Публикация посылает webhook; backend дополнительно перечитывает CMS каждую минуту. Проверка внутренних целей из CMS в Medusa синхронна и закрывается отказом |
| Успех | Две соседние ревизии совпали, все данные прошли строгий разбор, недействительные внутренние цели скрыты, а новый снимок не старше уже принятого |
| Таймаут, повтор, идемпотентность | Webhook, preview и проверка целей ограничены 5 секундами. Алгоритм согласованности делает до четырёх полных чтений снимка; каждое чтение обращается к homepage, settings и ко всем страницам SEO, поэтому общее число HTTP-запросов зависит от пагинации SEO. Проигранная запись снимка повторяется один раз. Потерянный webhook компенсирует минутный цикл |
| Деградация и действия оператора | Витрина показывает последний снимок. Редактор исправляет невалидную запись/цель; оператор восстанавливает CMS, read-доступ или время серверов. Одна повреждённая запись блокирует весь новый снимок — ОГР-28 |
| Настройка экземпляра | Оператор связывает CMS, backend, публичную витрину и отдельное хранилище; Editor/Publisher меняют контент без выпуска кода, но набор их прав восстанавливается из кода |
| Подробности и свидетельства | Путь публикации, контент главной, docs/feature-inventory.md, §2.9 и §3; ПУТ-24, ПУТ-25, ПУТ-27, ПУТ-36 |
SYS-INT-07. PostgreSQL
| Поле | Контракт |
|---|---|
| Назначение и направление | Backend и CMS читают и изменяют постоянные данные своих доменов; миграции подготавливают структуру до приёма трафика |
| Данные и источник истины | База Medusa — каноническое постоянное состояние commerce; база CMS — постоянное состояние контента. Поиск, кэш и внешние документы не заменяют их |
| Авторизация / доверительная граница | Базы Medusa и CMS разделены именами, но поставляемая конфигурация использует один общий PostgreSQL principal для приложений, миграций и инициализации; публичный браузер к БД не подключается |
| Триггер и синхронность | Доменная запись синхронна внутри операции; фоновые процессы читают и обновляют состояние по расписанию |
| Успех | Транзакция зафиксирована и последующее чтение владельца возвращает результат; схема соответствует версии приложений |
| Таймаут, повтор, идемпотентность | Общего продуктового таймаута или автоматического повтора произвольной транзакции не установлено; идемпотентность реализуется владеющим workflow. Миграции и init запускаются повторяемо до backend |
| Деградация и действия оператора | При недоступности базы владеющее приложение не должно переключать истину на индекс/кэш; операция или приложение недоступны. Оператор восстанавливает сервис и целостность, затем проверяет миграции и фоновые очереди |
| Настройка экземпляра | Каждая компания получает изолированные базы/схемы и реквизиты; политика резервного копирования и восстановления не утверждена — TBD-08 |
| Подробности и свидетельства | Архитектура, инфраструктура, развёртывание |
SYS-INT-08. Redis
| Поле | Контракт |
|---|---|
| Назначение и направление | Backend использует Redis для кэша, событий, workflow и распределённых блокировок |
| Данные и источник истины | Redis хранит координационное и временное состояние; PostgreSQL и внешние владельцы остаются источниками доменных фактов |
| Авторизация / доверительная граница | В поставляемой конфигурации доступ ограничен непубличной Docker-сетью без отдельной Redis-аутентификации; браузеры и внешние провайдеры к Redis не обращаются |
| Триггер и синхронность | Используется при каждом применимом кэше, событии, workflow или lock; production backend считает сервис обязательным |
| Успех | Событие принято, workflow/lock согласованы, а кэш не изменил доменное решение |
| Таймаут, повтор, идемпотентность | Событие с выброшенной ошибкой повторяется до пяти раз с экспоненциальной базой 5 секунд; ошибка хранится до 7 дней. Идемпотентность побочных эффектов остаётся обязанностью подписчика |
| Деградация и действия оператора | Production не переключается на in-memory как штатный fallback; запуск или координационные операции нарушаются. Оператор восстанавливает Redis и проверяет сохранённые ошибки/повторы |
| Настройка экземпляра | Каждый deployment использует отдельную логическую или физическую область Redis и непубличный доступ |
| Подробности и свидетельства | Архитектура, event bus, docs/feature-inventory.md, §2.13 |
SYS-INT-09. Meilisearch
| Поле | Контракт |
|---|---|
| Назначение и направление | Backend индексирует публичный каталог; витрина получает поиск, фильтры, фасеты и сортировку через backend |
| Данные и источник истины | Индекс — восстановимая копия товаров, вариантов, цены, категории и вычисленного наличия; PostgreSQL/Medusa остаётся владельцем |
| Авторизация / доверительная граница | Backend обращается с закрытым ключом; браузер не получает административный доступ к индексу |
| Триггер и синхронность | Точечные или полные обновления следуют за доменными событиями; полная переиндексация доступна сопровождающему |
| Успех | Выдача соответствует фильтрам и каноническим публичным объектам, а карточка/checkout повторно подтверждают продаваемость в Medusa |
| Таймаут, повтор, идемпотентность | Ошибка несовместимых настроек индекса запускает их обновление и один повтор запроса. Отсутствующий индекс трактуется как пустая выдача; недоступный сервис — как отдельная ошибка |
| Деградация и действия оператора | Заказные данные не повреждаются. Покупатель видит отличимое состояние ошибки либо пустой свежий индекс; оператор восстанавливает сервис и запускает полную переиндексацию |
| Настройка экземпляра | Оператор задаёт отдельный сервер/индекс и ключ для экземпляра; данные другой компании не смешиваются |
| Подробности и свидетельства | API и поиск, архитектура, docs/feature-inventory.md, §2.8; ПУТ-9, ПУТ-23 |
SYS-INT-10. S3-совместимое объектное хранилище
| Поле | Контракт |
|---|---|
| Назначение и направление | Medusa сохраняет изображения и документы товаров; CMS сохраняет публичные медиа контента |
| Данные и источник истины | Объектное хранилище владеет байтами файла; доменные приложения владеют ссылкой и разрешением использовать файл |
| Авторизация / доверительная граница | Запись выполняется отдельными реквизитами; Medusa и CMS используют изолированные бакеты/пользователей. Оба бакета допускают анонимное чтение, а CMS дополнительно записывает объекты как публичные: публикация доменной записи управляет выдачей ссылки приложением, но не правом чтения уже загруженных байтов по известному URL |
| Триггер и синхронность | Загрузка и удаление выполняются при административном действии; браузер читает публичный объект по ссылке |
| Успех | В штатном потоке виджета документ принят только при допустимых размере и сигнатуре и совпадении заявленного MIME; перед связыванием сохранённые байты повторно читаются и проверяются по размеру и сигнатуре, но исходный MIME непомеченной загрузки на этой границе не извлекается и повторно не сравнивается. CMS выполняет content-based MIME detection и применяет настроенные списки типов и размер; если обнаруженный допустимый тип не совпал с допустимым типом расширения либо detection не дал результата, возможен выбор по расширению или заявленному MIME, а повторного чтения объекта перед публикацией нет |
| Таймаут, повтор, идемпотентность | Общий продуктовый таймаут/повтор не утверждён. Удаление товара удаляет документ только когда на него больше не ссылается активный товар; CMS-медиа автоматически не очищаются по подтверждённому контракту |
| Деградация и действия оператора | Новая загрузка/чтение файла не проходит, но доменные записи не должны подменяться пустыми. Оператор восстанавливает доступ и проверяет связи; редактор или администратор повторяет загрузку |
| Настройка экземпляра | Оператор задаёт публичный адрес, бакеты и отдельные реквизиты; текущий предел загрузки CMS настраивается, значение по умолчанию 8 МиБ не объявляется неизменным продуктовым лимитом |
| Подробности и свидетельства | Окружение: хранилище, инфраструктура, docs/feature-inventory.md, §2.13 и §3.3 |
SYS-INT-11. Публичная сетевая граница
| Поле | Контракт |
|---|---|
| Назначение и направление | DNS, reverse proxy и TLS доставляют browser/API-трафик к витрине, backend, admin, CMS и документации |
| Данные и источник истины | Приложения владеют ответами и сессиями; edge владеет публичным именем, сертификатом и маршрутизацией |
| Авторизация / доверительная граница | HTTPS защищает транспорт; списки origin ограничивают browser-доступ; forwarded-адрес доверяется только перечисленным proxy. Публичная конфигурация не является авторизацией |
| Триггер и синхронность | Каждый публичный запрос проходит edge синхронно |
| Успех | Публичное имя приводит к правильному приложению, сертификат действителен, cookie и origin соответствуют выбранному HTTPS-контуру |
| Таймаут, повтор, идемпотентность | Единый продуктовый edge-таймаут не утверждён; повтор мутации не считается допустимым без доменной идемпотентности |
| Деградация и действия оператора | Неверный маршрут/origin блокирует API или вход; отсутствие TLS несовместимо с secure-cookie. Инфраструктурный оператор исправляет DNS, сертификат, proxy и согласованные origin |
| Настройка экземпляра | Домен, сертификат, публичные и внутренние адреса и разрешённые origin задаются отдельно для каждой компании без изменения доменной логики |
| Подробности и свидетельства | Окружение, инфраструктура, развёртывание |
SYS-INT-14. YouTube и Vimeo
| Поле | Контракт |
|---|---|
| Назначение и направление | Витрина строит встраиваемый плеер для распознанной ссылки YouTube/Vimeo; браузер покупателя загружает плеер напрямую у видеопровайдера |
| Данные и источник истины | Medusa хранит заданный для товара URL; провайдер владеет плеером и доступностью видео. Распознаётся ограниченный набор хостов YouTube, youtu.be, youtube-nocookie.com и Vimeo |
| Авторизация / доверительная граница | Серверные реквизиты не используются. Запрос пересекает сетевую и privacy-границу из браузера к третьей стороне; referrer ограничен origin, а cookie и дальнейшая обработка принадлежат границе браузера/провайдера |
| Триггер и синхронность | iframe присутствует при открытии карточки, а фактическая загрузка отложена браузерным lazy-режимом. Нераспознанный HTTP(S)-URL отображается только как внешняя ссылка |
| Успех | Плеер загружен в карточке, при этом под ним сохраняется ссылка на исходный URL |
| Таймаут, повтор, идемпотентность | Продуктовый таймаут и автоматический повтор не заданы; загрузкой и повтором управляет браузер |
| Деградация и действия оператора | Компонент помечает ошибку iframe и заменяет его внешней ссылкой; ссылка также всегда показана под плеером. Недоступность видео не блокирует карточку или покупку |
| Настройка экземпляра | Ссылки задаются для конкретного товара; список поддержанных провайдеров меняется только с кодом |
| Подробности и свидетельства | Карточка товара, docs/feature-inventory.md, §1.5; компонентные тесты распознавания URL и fallback |
TBD (решение владельца): [TBD-12] Допустима ли текущая автоматическая lazy- загрузка стороннего плеера при открытии карточки, или до запроса к YouTube/Vimeo нужны явное действие/согласие покупателя?
10. Атрибуты качества
Каждая строка ниже имеет объективный порог. Значения, которые найдены в текущей реализации, но не утверждены как SLA или постоянный продуктовый лимит, прямо так и помечены.
10.1. Безопасность и приватность
Сроки хранения, удаление и обезличивание персональных данных нельзя вывести из этих технических мер: решение остаётся в TBD-03.
10.2. Производительность и ёмкость
TBD (решение владельца): [TBD-07] Утвердить целевые перцентили времени ответа, конкурентность и объёмы каталога/заказов для поиска, карточки, корзины, checkout и панелей; текущий benchmark и лимиты страниц сами по себе не являются SLA.
10.3. Надёжность, доступность и восстановление
TBD (решение владельца): [TBD-08] Утвердить доступность, RTO/RPO, резервное копирование, частоту проверки восстановления и ответственных для PostgreSQL, CMS, объектных файлов, Redis и поискового индекса. Эти значения не выводятся из health-check и restart policy.
10.4. Согласованность и идемпотентность
10.5. Удобство и доступность интерфейсов
10.6. Наблюдаемость и сопровождаемость
10.7. Развёртываемость и переносимость
11. Ограничения, предположения и зависимости
| ID | Тип | Ограничение, предположение или зависимость | Последствие нарушения | Основание / проверка |
|---|---|---|---|---|
SYS-CON-01 | Архитектурное ограничение | Один deployment и его постоянные хранилища обслуживают одну компанию; общего мультитенантного runtime нет | Совместное использование смешает домены, customer-сессии, данные и секреты компаний; такая установка не поддерживается | Раздел 3.4; SYS-QLT-25; архитектура |
SYS-CON-02 | Платформенная зависимость | Production требует совместимые PostgreSQL, Redis, Meilisearch и S3, а также поддерживаемые версии Node/npm и приложений; тестовые in-memory-замены не являются production-режимом | Backend не стартует или теряет события, workflow, поиск/файлы; зелёные тесты на заменах не доказывают работу реального стека | README.md; окружение; инфраструктура |
SYS-CON-03 | Бизнес-ограничение | Текущий продукт продаёт физические товары через серверную корзину: получение обязательно, регистрация и онлайн-оплата — нет; inventory/backorder управляет доступностью | Каталог услуг/digital goods, обязательная регистрация или заказ без получения требуют новой feature spec и пересмотра SYS-BR-02–SYS-BR-09 | docs/specs/storefront-ux-core.md; ПУТ-1–ПУТ-5 |
SYS-CON-04 | Платформенное правило | Стандартные Store/Admin API, модули и workflow Medusa используются прежде кастомной реализации; кастомная граница допустима только для подтверждённого пробела | Параллельная реализация расходится со стандартными заказами, правами, резервами или миграциями и становится неподдерживаемой | CLAUDE.md; docs/specs/constitution.md; архитектура |
SYS-CON-05 | Внешний договор | Онлайн-оплата, прямой СДЭК, ApiShip и МойСклад предполагают действующий договор/аккаунт, разрешённые операции и выданные реквизиты компании | Провайдер не возвращает тариф/ПВЗ, не принимает запись или не подтверждает деньги; функция считается только настроенной, но не принятой. Пробелы живой приёмки — ЖИВ-01…ЖИВ-04 | Карточки SYS-INT-01–SYS-INT-04; docs/qa/active-limitations.md |
SYS-CON-06 | Предположение о данных | Для постоянного обмена МойСклад каждый участвующий вариант имеет уникальный непустой SKU, совпадающий ровно с одним кодом номенклатуры | Неоднозначная/пустая позиция пропускается, остаток не обновляется, заказ требует исправления или ручной обработки | SYS-BR-05; ПУТ-31, ПУТ-33; МойСклад |
SYS-CON-07 | Криптографическая зависимость | Шифруемые реквизиты МойСклад, ЮKassa и СДЭК зависят от непустого ключа вне данных; ключ остаётся тем же, пока реквизиты не заменены. Конфигурация позволяет повторно использовать один ключ в разных окружениях, и продукт не проверяет его уникальность | После смены/потери ключа существующие реквизиты не расшифровываются; повтор ключа между окружениями ослабляет изоляцию. Расхождение ApiShip с общим правилом — ОГР-32 | SYS-BR-21; окружение; ОГР-32; TBD-11 |
SYS-CON-08 | Сетевая зависимость | Публичный экземпляр предполагает согласованные домены/origin, HTTPS reverse proxy и корректную доверительную цепочку forwarded-адресов | Browser блокирует API/CORS или не сохраняет secure-cookie; webhook ЮKassa может быть отклонён либо довериться подменённому адресу | SYS-INT-11; окружение |
SYS-CON-09 | Предположение о времени | Часы CMS и backend синхронизированы с расхождением не более 5 минут | Честный CMS-webhook отклоняется как replay; снимок обновится только периодическим чтением | SYS-INT-06; путь CMS |
SYS-CON-10 | Предположение о контенте | Публикация CMS соответствует схеме, а внутренние цели доступны Medusa в момент проверки | Невалидный черновик не сохраняется; недоступная цель скрывается; повреждённая запись сохраняет прежний снимок целиком — ОГР-28 | SYS-DAT-08; путь CMS |
SYS-CON-11 | Внешний контракт | Форматы, статусы, подписи, rate limits и идемпотентность провайдеров соответствуют их целевому аккаунту, а не только мокам | Автотесты остаются зелёными, но живой запрос может быть отклонён или интерпретирован иначе; до живого прогона уровень доказательства ограничен | docs/known-quirks.md; ЖИВ-01…ЖИВ-04; CLAUDE.md |
SYS-CON-12 | Операционное ограничение | SMTP — best-effort зависимость: недоступность не блокирует commerce/auth-операцию, а подтверждённой очереди доставки для всех типов писем нет | Пользователь может получить UI-успех без письма; оператор/администратор восстанавливает канал или связывается вручную. Активные отклонения — ОГР-01, ОГР-25, ОГР-31 | SYS-INT-05; docs/qa/business-overview.md |
SYS-CON-13 | Платформенное ограничение | Расчёт доставки получает город, регион и индекс, но не улицу/дом; СДЭК tracking читается из webhook-копии, ApiShip — прямым запросом | Нельзя обещать тариф с точностью до дома или одинаковую свежесть tracking двух провайдеров без изменения платформенной границы | ПЛТ-01, ПЛТ-03; доставка |
TBD (решение владельца): [TBD-11] Считать ли уникальный для каждого окружения ключ шифрования обязательным продуктовым инвариантом с запретом пустых/default-значений при запуске, или оставить разделение ключей операторской мерой?
12. Инварианты продукта и настройки компании
«Без кода» означает изменение данных через штатную панель либо deployment- конфигурацию с перезапуском. Значение из seed или примера не считается подтверждённой production-настройкой.
| Аспект | Инвариант продукта | Tenant-настройка | Значение «Колорики» | Владелец настройки | Способ проверки |
|---|---|---|---|---|---|
| Изоляция компании | Один deployment обслуживает одну компанию; доменные данные и секреты между экземплярами не разделяются | Новый экземпляр создаётся отдельным deployment и постоянными хранилищами, без изменения кода | Один экземпляр для магазина «Колорика»; общего мультитенантного режима нет | Владелец утверждает границу; инфраструктурный оператор создаёт экземпляр | Сверить домены, базы, бакеты и ключи двух экземпляров; SYS-CON-01, SYS-QLT-25 |
| Бренд и название | У публичного экземпляра одно согласованное имя; CMS-название управляет частью главной, но не обязано переименовывать shell/SEO | Site settings меняется Publisher без кода; вордмарк, footer и большая часть metadata сейчас меняются только кодом и новой сборкой | «Колорика» жёстко присутствует в shell и metadata; резерв CMS до первой публикации — «Магазин автокрасок» | Владелец задаёт бренд; Publisher меняет CMS; разработчик — жёсткие строки | Сравнить shell, metadata страниц, CMS Site settings и пустой снимок; решение о полной no-code вариативности — TBD-10 |
| Публичный домен | Приложения должны использовать согласованные публичные/внутренние адреса, origin и secure-cookie | DNS, TLS, reverse proxy и адреса приложений меняются в deployment без кода | В ролевой инструкции стенда указан qa-a.mirkrasok.termitsdigital.ru; канонический production-домен источниками не подтверждён | Владелец выбирает домен; инфраструктурный оператор настраивает | Открыть web/admin/CMS/docs по целевым именам, проверить TLS, login, API и preview; TBD-10 |
| Контент и контакты | Публичная главная получает целостный CMS-снимок; отдельные страницы контактов/доставки принадлежат legacy-разделу Medusa Admin | Homepage/Site settings меняются Editor/Publisher; контакты и доставка — администратором, без кода | Репозиторий и инструкция содержат демонстрационные телефон, email, адрес и условия доставки; реальные значения не подтверждены | Владелец предоставляет данные; Editor/Publisher и администратор публикуют в своих границах | Сверить главную, страницы контактов/доставки и ревизию CMS; карта контактов; TBD-10 |
| Локаль, страна и валюта | Валюта заказа/оплаты должна совпадать на всём пути; формат не должен подменять код валюты | Commerce-регион и цены меняются в Medusa, но публичный UI частично жёстко ориентирован на русскую локаль и ₽; полноценная смена требует кода и отдельной spec | Самонастройка создаёт Russia/RUB; UI использует ru-RU; иная валюта имеет активное отклонение ОГР-03 | Владелец принимает рынок/валюту; Super Admin меняет commerce-данные; разработчик устраняет жёсткие привязки | Оформить тестовый заказ и платёж, сверить код/знак валюты на всех экранах и у провайдера |
| Каталог и ассортимент | Товары, варианты, категории, цены и публикация принадлежат Medusa; наличие вычисляется | Администратор меняет каталог без кода; разовый импорт допустим как отдельная операция | Конкретный ассортимент и цены не являются системным инвариантом; актуальное значение берётся из Medusa | Администратор магазина | Проверить опубликованный каталог и SYS-BR-01–SYS-BR-05, не сравнивая с demo seed как эталоном |
| Склад и inventory | Должна существовать складская локация, связанная с каналом продаж; продаваемый inventory остаётся в Medusa | Склад, остатки и backorder меняются в Medusa; физический остаток может приходить из МойСклад; адрес отправителя и коробка задаются в доставке | Самонастройка создаёт Main Warehouse; реальный адрес, размеры, вес и остатки в Git не хранятся и не подтверждены | Владелец/складской оператор; администратор доставки | Сверить связь склада/канала, контрольный SKU и остаток, адрес отправителя и тариф после сохранения коробки; TBD-10 |
| Платёжные провайдеры | Заказ без online-провайдера допустим; подключение не хранит карты и не прекращает обслуживание ранее начатых платежей при выключении | Реквизиты/видимость ЮKassa меняет Super Admin без кода; новый тип провайдера требует кода и feature spec | Поддерживаются manual/system и ЮKassa; активность и реальные реквизиты целевого экземпляра в репозитории не определяются | Владелец договора и Super Admin; оператор хранит ключ шифрования | Проверить список способов, полный платёж/отказ/возврат и отключение новых оплат; фактический контур не определять по подписи режима — ОГР-06 |
| Службы доставки | Checkout требует реальный способ получения; отказ одной службы изолирован; manual-provider остаётся для непроектных способов | ApiShip и СДЭК настраиваются/включаются в admin; добавление нового прямого провайдера требует кода | Поддерживаются ApiShip, прямой СДЭК и manual. DPD доступен только через ApiShip; целевые write-сценарии не приняты — ЖИВ-01, ЖИВ-04 | Владелец договоров и администратор доставки | Контрольный расчёт курьер/ПВЗ, заказ, отмена, tracking и этикетка на целевом аккаунте |
| Учётная система | Постоянный обмен ограничен остатками в продукт и заказами/отменами наружу; ключ сопоставления — SKU ↔ код | Реквизиты и активность МойСклад меняются в admin без кода; замена типа учётной системы требует кода | МойСклад поддержан; read-only доступ проверен, живые остатки и запись заказов не приняты — ЖИВ-03 | Владелец аккаунта и складской оператор; оператор хранит ключ шифрования | Живой контрольный SKU, заказ и отмена плюс отчёт несопоставленных позиций |
| Ключи и секреты | Секреты разделены по назначению и не входят в клиентскую конфигурацию; ключи шифрования сохраняются на срок жизни реквизитов. Уникальность ключа между окружениями кодом не проверяется. Текущее нарушение общего правила хранения и возврата — ОГР-32 | Инфраструктурные секреты меняет оператор; реквизиты МойСклад/ЮKassa/ApiShip/СДЭК вводятся уполномоченным сотрудником в admin | Реальные значения намеренно отсутствуют в Git; поставляемая конфигурация допускает повторное fallback-значение ключа МойСклад, поэтому фактическая изоляция зависит от оператора — TBD-11; ОГР-32 | Инфраструктурный оператор и владелец внешнего аккаунта | Secret scan, проверка маскирования и ревью фактических ключей двух окружений; ротация шифруемых интеграционных реквизитов только вместе с их повторным вводом |
| Почта | Сбой SMTP не откатывает породившую письмо доменную операцию | Сервер, отправитель и реквизиты меняются в deployment без кода; шаблон и перечень событий требуют кода | В примере указан no-reply@example.com; фактический отправитель и production SMTP не подтверждены | Владелец выбирает sender; инфраструктурный оператор настраивает | Отправить reset и операционное письмо на контролируемый адрес, проверить From и отсутствие секрета в логах; TBD-10 |
| Sales channel и publishable key | Публичный ключ связан с storefront-каналом и выдаётся витрине в runtime; он не даёт административных прав | Автоматически создаются на пустом экземпляре; администратор может отозвать/заменить ключ без пересборки витрины | Baseline-имена seed — Auto Paint Storefront и связанный publishable key; сам токен в документацию не входит | Super Admin; начальную связь обеспечивает самонастройка | На пустом экземпляре выполнить первый и повторный init, проверить один активный связанный ключ и успешный публичный запрос |
| Режим административных ролей | При включённом RBAC сервер проверяет permissions; CMS-роли Editor/Publisher восстанавливаются из кода | RBAC включается в deployment; назначения Medusa-пользователей меняет Super Admin; состав CMS-ролей требует кода | Документация требует включённый RBAC; фактическое runtime-значение целевого экземпляра из Git не определяется | Владелец утверждает матрицу; Super Admin назначает; оператор включает режим | Негативные запросы обычного admin/Super Admin и рестарт CMS с проверкой восстановленных ролей; TBD-04, TBD-05 |
13. Известные отклонения и уровень доказательств
Легенда доказательств
| Уровень | Что он доказывает | Чего не доказывает |
|---|---|---|
| D1 — репозиторий | Контракт найден в коде, документации или конфигурации | Что путь выполнялся в runtime |
| D2 — автоматическая проверка | Внутреннее поведение прошло unit/HTTP/integration-тест на заглушках | Совместимость с реальным внешним аккаунтом |
| D3 — реальный read/sandbox | Отдельная операция прошла против реального API или песочницы | Полный write-путь на договоре компании |
| D4 — целевой сквозной прогон | Сценарий прошёл на целевом аккаунте/договоре с проверкой результата во всех системах | Будущую доступность провайдера |
ОГР-* — подтверждённое нарушение или видимый разрыв; ЖИВ-* — отсутствующий
уровень D4, а не подтверждение работы или дефект; ПЛТ-* — подтверждённая граница,
которую проверка должна принять. Подробность и статус существуют только в
docs/qa/active-limitations.md.
Отклонения
| ID | Влияние на системный контракт | Единственная подробная запись |
|---|---|---|
ОГР-01 | SYS-CAP-03, SYS-BR-15, SYS-INT-05, SYS-QLT-09 | docs/qa/active-limitations.md#ogr-01 |
ОГР-02 | SYS-CAP-02, SYS-DAT-05 | docs/qa/active-limitations.md#ogr-02 |
ОГР-03 | SYS-BR-01, SYS-DAT-01, SYS-QLT-16 | docs/qa/active-limitations.md#ogr-03 |
ОГР-04 | SYS-BR-08, SYS-INT-04, SYS-QLT-08 | docs/qa/active-limitations.md#ogr-04 |
ОГР-05 | SYS-BR-21, SYS-INT-02, SYS-QLT-02 | docs/qa/active-limitations.md#ogr-05 |
ОГР-06 | SYS-CAP-03, SYS-INT-02, SYS-CON-05 | docs/qa/active-limitations.md#ogr-06 |
ОГР-07 | SYS-CAP-01, SYS-DAT-01 | docs/qa/active-limitations.md#ogr-07 |
ОГР-08 | SYS-CAP-02, SYS-QLT-18 | docs/qa/active-limitations.md#ogr-08 |
ОГР-09 | SYS-CAP-02, SYS-DAT-03, SYS-QLT-18 | docs/qa/active-limitations.md#ogr-09 |
ОГР-10 | SYS-BR-19, SYS-DAT-07 | docs/qa/active-limitations.md#ogr-10 |
ОГР-11 | SYS-CAP-01, SYS-QLT-06 | docs/qa/active-limitations.md#ogr-11 |
ОГР-12 | SYS-CAP-01, SYS-QLT-17 | docs/qa/active-limitations.md#ogr-12 |
ОГР-13 | SYS-CAP-01, SYS-DAT-08 | docs/qa/active-limitations.md#ogr-13 |
ОГР-14 | SYS-BR-21, SYS-QLT-02 | docs/qa/active-limitations.md#ogr-14 |
ОГР-15 | SYS-CAP-07, SYS-DAT-08, SYS-QLT-17 | docs/qa/active-limitations.md#ogr-15 |
ОГР-16 | SYS-CAP-07, SYS-DAT-08 | docs/qa/active-limitations.md#ogr-16 |
ОГР-17 | SYS-CAP-05 | docs/qa/active-limitations.md#ogr-17 |
ОГР-18 | SYS-CAP-04, SYS-INT-03, SYS-INT-04 | docs/qa/active-limitations.md#ogr-18 |
ОГР-20 | SYS-BR-17, SYS-BR-19, SYS-DAT-07, SYS-INT-03 | docs/qa/active-limitations.md#ogr-20 |
ОГР-22 | SYS-CAP-01 | docs/qa/active-limitations.md#ogr-22 |
ОГР-23 | SYS-CAP-07, SYS-DAT-08 | docs/qa/active-limitations.md#ogr-23 |
ОГР-24 | SYS-CAP-01, SYS-QLT-06 | docs/qa/active-limitations.md#ogr-24 |
ОГР-25 | SYS-BR-15, SYS-INT-05, SYS-CON-12 | docs/qa/active-limitations.md#ogr-25 |
ОГР-26 | SYS-CAP-02, SYS-INT-05 | docs/qa/active-limitations.md#ogr-26 |
ОГР-27 | SYS-BR-13, SYS-QLT-10 | docs/qa/active-limitations.md#ogr-27 |
ОГР-28 | SYS-BR-06, SYS-DAT-08, SYS-INT-06, SYS-QLT-11 | docs/qa/active-limitations.md#ogr-28 |
ОГР-29 | SYS-CAP-01, SYS-INT-09, SYS-QLT-06 | docs/qa/active-limitations.md#ogr-29 |
ОГР-30 | SYS-BR-11, SYS-DAT-06, SYS-QLT-18 | docs/qa/active-limitations.md#ogr-30 |
ОГР-31 | SYS-CAP-02, SYS-INT-05, SYS-CON-12 | docs/qa/active-limitations.md#ogr-31 |
ОГР-32 | SYS-BR-21, SYS-INT-04, SYS-QLT-02, SYS-CON-07 | docs/qa/active-limitations.md#ogr-32 |
ОГР-33 | SYS-CAP-01, SYS-QLT-17 | docs/qa/active-limitations.md#ogr-33 |
ОГР-34 | SYS-QLT-02, SYS-QLT-22 | docs/qa/active-limitations.md#ogr-34 |
Неполное живое доказательство
| ID | Влияние на системный контракт | Единственная подробная запись |
|---|---|---|
ЖИВ-01 | SYS-CAP-04, SYS-INT-03, SYS-CON-05 | docs/qa/active-limitations.md#ziv-01 |
ЖИВ-02 | SYS-INT-03, SYS-QLT-03, SYS-CON-11 | docs/qa/active-limitations.md#ziv-02 |
ЖИВ-03 | SYS-CAP-06, SYS-INT-01, SYS-QLT-07, SYS-CON-05 | docs/qa/active-limitations.md#ziv-03 |
ЖИВ-04 | SYS-CAP-04, SYS-INT-04, SYS-CON-05 | docs/qa/active-limitations.md#ziv-04 |
Платформенные границы
| ID | Влияние на системный контракт | Единственная подробная запись |
|---|---|---|
ПЛТ-01 | SYS-BR-08, SYS-DAT-05, SYS-INT-03, SYS-INT-04, SYS-CON-13 | docs/qa/active-limitations.md#plt-01 |
ПЛТ-02 | SYS-CAP-02, SYS-QLT-20 | docs/qa/active-limitations.md#plt-02 |
ПЛТ-03 | SYS-DAT-07, SYS-INT-03, SYS-INT-04, SYS-QLT-15, SYS-CON-13 | docs/qa/active-limitations.md#plt-03 |
14. Архитектура требований и порядок сопровождения
Иерархия и обязательные связи
Долговечное требование имеет ровно четыре сопровождаемых атрибута: стабильный ID,
одно проверяемое утверждение, основание/источник и проверку/свидетельство. Автор,
версия и история изменения берутся из Git; приоритет будущей работы — из issue,
feature spec и риска ПУТ-*, а не из второго рейтинга этой страницы.
Владение документом
| Ответственный | Обязанность |
|---|---|
| Владелец продукта | Владеет baseline и утверждает цели, in/out, бизнес-правила, допустимые качества, не-цели, открытые TBD и вариативность компаний |
| Автор feature spec / изменения | Выполняет impact analysis по SYS-*, меняет затронутые контракты и ссылки в той же задаче, не переносит будущее состояние в baseline раньше приёмки |
| Разработчик | Обеспечивает реализацию producer/consumer-границ и автоматическое доказательство там, где оно поддерживается репозиторием |
| QA / принимающий | Связывает изменённые ID с ПУТ-*/test case, фиксирует уровень доказательства и обновляет единственный реестр отклонений |
| Сопровождающий документацию | Проверяет якоря, относительные ссылки, уникальность ID и согласованность role/dev-страниц; это может быть тот же автор изменения |
Правило изменения
- До реализации автор добавляет в feature spec раздел «Затрагиваемые системные
требования» и перечисляет каждый
SYS-*ID со статусом сохраняется, изменяется, удаляется или новое. Если контракт не затронут, spec обязана явно сказать почему. Фраза «новая область» допустима только до выдачи следующего свободного ID в этой странице. - Новый долговечный контракт получает следующий свободный ID своего типа. Смысл существующего ID можно уточнять без подмены требования; удалённый ID никогда не переиспользуется.
- До реализации и проверки желаемое состояние живёт только в feature spec. После приёмки автор в той же задаче обновляет baseline, относящиеся role/dev docs и QA- свидетельства. Архивная spec остаётся историей решения и не переписывается.
- Если реализация нарушает действующую норму, норма остаётся в baseline, а подробная
запись создаётся или обновляется только в
docs/qa/active-limitations.md; здесь остаётся ссылка и влияние на ID. - Изменение владельца истины, внешней границы, схемы состояний, доступа, хранения, tenant-вариативности или измеримого порога всегда считается изменением системного контракта, даже если публичный UI визуально не изменился.
Definition of Done изменения системного контракта
Изменение готово только когда одновременно выполнены все применимые пункты:
- feature spec перечисляет затронутые
SYS-*и связывает их с целью, ролью илиПУТ-*; - реализация согласована на обеих сторонах изменённого контракта: producer и consumer, read и write path, основной и ошибочный исход;
- у каждого нового или изменённого
SYS-*есть объективная проверка и фактическое свидетельство; внешний mock не выдан за D4; - эта страница описывает только уже принятое текущее состояние, а role/dev/QA- документы обновлены там, где изменился их собственный контракт;
- закрытый
ОГР-*/ЖИВ-*удалён из активного реестра, новый разрыв добавлен туда один раз, а ссылки раздела 13 синхронизированы; - документационный гейт не находит битых внутренних ссылок, якоря и
SYS-*уникальны, секреты и реальные персональные данные в изменения не попали.
Порядок аудита baseline
Владелец продукта инициирует аудит перед значимым релизом и после крупного обновления
docs/feature-inventory.md; автор релиза и QA выполняют сверку. Последовательно
проверяются граница раздела 3, владельцы/копии раздела 8, все карточки раздела 9,
пороги раздела 10, зависимости и tenant-матрица, затем соответствие раздела 13
активному реестру. Отдельно проверяются уникальность SYS-*, наличие проверки у
каждой нормативной строки и ссылки feature specs на изменённые ID. Результат хранится
в изменениях Git/задаче релиза; ручной номер версии и журнал правок не ведутся.
15. Термины и ссылки
Доменные термины
| Термин | Значение в этом контракте |
|---|---|
| Товар | Общая карточка продаваемого предмета с категорией, контентом и одним или несколькими вариантами; публикация не гарантирует продаваемость без цены и категории |
| Вариант | Конкретная продаваемая конфигурация товара со своей ценой, SKU, inventory и backorder; товар без выбора конфигурации имеет один вариант |
| SKU | Необязательный уникальный код варианта после удаления внешних пробелов; единственный ключ постоянного сопоставления с кодом номенклатуры МойСклад |
| Остаток / inventory | Количество варианта, которое Medusa использует для решения о продаже; может обновляться из МойСклад, но не равно вычисленному статусу наличия |
| Backorder / «под заказ» | Разрешение оформить вариант при нулевом остатке; срок поставки этим термином не обещается |
| Наличие | Вычисляемый результат: «в наличии», «под заказ» или «нет в наличии» по SYS-BR-02; учитывает режим управления inventory, остаток и backorder и не является отдельным редактируемым полем |
| Корзина | Серверный изменяемый набор позиций до заказа; идентификатор в браузере или ссылке восстановления является bearer capability для чтения и изменения незавершённой корзины без customer-аутентификации |
| Резерв | Временное выделение продаваемого остатка корзине или заказу; при финализации владелец меняется без промежуточного освобождения |
| Покупатель-гость | Покупатель без аккаунта, который может оформить заказ, но не получает кабинетные права отмены/возврата/истории |
| Заказ | Канонический факт продажи в Medusa с зафиксированным составом, суммой, валютой, контактами и получением; не равен платёжному или логистическому статусу |
| Платёжная сессия | Локальная связь корзины с операцией провайдера, суммой и валютой; не является доказательством списания |
| Отправление / fulfillment | Исполнение доставки конкретным провайдером, связанное с заказом и имеющее независимый жизненный цикл |
| Заявка на возврат | Решение о допустимости обратной логистики; подтверждение создаёт обратную отправку и не означает денежный возврат |
| Денежный возврат / refund | Операция возврата захваченных денег у платёжного провайдера; выполняется отдельно от заявки и обратной доставки |
| Публикация CMS | Редакционная ревизия Strapi, доступная read-интерфейсу; до принятия backend не является публичным снимком |
| Снимок контента | Последняя целостная ревизия CMS, принятая и сохранённая backend для чтения витриной |
| Источник истины | Система, решение которой побеждает при расхождении. Кэш, индекс, webhook и внешний документ не становятся владельцем только потому, что содержат копию |
| Экземпляр компании / tenant | Изолированный deployment одной компании со своими доменами, данными, секретами и внешними аккаунтами; не строка tenant внутри общего runtime |
| Идемпотентность | Повтор одного логического намерения не создаёт дополнительный заказ, платёжный/денежный эффект, отправление или решение |
Карта канонических документов
| Вопрос | Канонический документ | Статус относительно этой страницы |
|---|---|---|
| Текущие границы, инварианты, данные, интерфейсы и качества | Эта страница | Нормативный системный baseline |
| Общие инженерные и UX-принципы | docs/specs/constitution.md, docs/specs/storefront-ux-core.md | Вышестоящие принципы; не заменяют конкретный SYS-* |
| Контракт отдельного изменения и его задачи | docs/specs/<feature>/spec.md, stack.md, tasks.md; завершённые — docs/specs/_archive/ | Дельта и история решения; будущее состояние до приёмки |
| Фактический реестр по коду | docs/feature-inventory.md | As-built свидетельство и индекс, не нормативная копия baseline |
| Роли, процессы и владельцы данных | docs/qa/business-overview.md | QA-модель для сверки системного смысла |
| Риск и проверка поведения | docs/qa/user-journeys.md, docs/qa/test-cases/ | ПУТ-*, Given/When/Then и свидетельства SYS-* |
| Активное нарушение, живой пробел или платформенная граница | docs/qa/active-limitations.md | Единственный реестр ОГР-*, ЖИВ-*, ПЛТ-* |
| Особенности внешнего API и стенда | docs/known-quirks.md | Диагностический источник; не переопределяет норму |
| Действия покупателя и сотрудников | Покупатель, администратор, владелец, склад | Пошаговые инструкции без дублирования системного контракта |
| Реализация API, CMS, платежей, доставки, учёта и инфраструктуры | Раздел разработчика | Технические детали интерфейсов и runbook |
| Состав, setup и правила работы с репозиторием | README.md, CLAUDE.md | Операционная и инженерная инструкция |
Открытые вопросы к владельцу
- TBD-01 — бизнес-результаты: являются ли пять результатов раздела 2 целевыми бизнес-результатами продукта, кто владеет каждым и какими метриками или наблюдаемыми исходами измеряется успех?
- TBD-02 — постоянные не-цели: какие из направлений — международная доставка, встроенная финансовая аналитика, мультитенантность, фискализация онлайн-платежей и полная двусторонняя синхронизация каталога с МойСклад — исключены постоянно, а какие остаются возможным будущим развитием?
- TBD-03 — юридические и safety-обязательства: какие обязательства действуют для согласия и персональных данных, сроков хранения и удаления, рассылок, лакокрасочных товаров и опасных грузов?
- TBD-04 — специальные страницы админки: допустим ли постоянный доступ любого вошедшего администратора к МойСклад, доставке, возвратам и legacy-контенту или нужны отдельные серверные разрешения?
- TBD-05 — профили владельца и склада: нужны ли формальные роли с утверждённой матрицей прав или достаточно индивидуальных назначений Medusa и отдельного доступа к МойСклад?
- TBD-06 — чтение статуса платежа: достаточно ли знания непредсказуемого идентификатора корзины или требуется дополнительное подтверждение покупателя?
- TBD-07 — производительность и ёмкость: какие целевые перцентили времени ответа, конкурентность и объёмы каталога/заказов утверждаются для поиска, карточки, корзины, checkout и административных панелей?
- TBD-08 — доступность и восстановление: какие SLA, RTO/RPO, схема резервного копирования, частота теста восстановления и ответственные утверждаются для постоянных данных, CMS, файлов, Redis и поиска?
- TBD-09 — операционное хранение: как долго хранить и когда удалять неперсональные корзины, состояния workflow, журналы webhook/синхронизаций, старые снимки и неиспользуемые файлы? Персональные данные остаются частью TBD-03.
- TBD-10 — профиль экземпляра «Колорики»: подтвердить production-домен, брендовые значения, реальные контакты/контент, склад и коробку, включённые внешние аккаунты, платёжный контур и почтового отправителя; какие из жёстких привязок бренда, локали и валюты должны стать tenant-настройками без кода?
- TBD-11 — изоляция ключей: считать ли уникальный для каждого окружения ключ шифрования обязательным продуктовым инвариантом с запретом пустых/default-значений при запуске, или оставить разделение ключей операторской мерой?
- TBD-12 — privacy-граница видео: допустима ли автоматическая lazy-загрузка плеера YouTube/Vimeo при открытии карточки товара, или до прямого запроса браузера к видеопровайдеру нужны явное действие или согласие покупателя?
- TBD-13 — ссылка восстановления корзины: допустим ли текущий bearer-доступ к незавершённой корзине по одному идентификатору или ссылка должна получить подпись, срок действия либо одноразовость?