Skip to content

Иерархия и зависимости модулей

Статус: актуализировано 15.07.2026 по строкам requires:/provides: всех 121 ТЗ (modules/*.md). Модули не изолированы — между ними обязательные связи и иерархия, которые ядро обязано знать, проверять и соблюдать. Проверено скриптом: циклов в графе нет, максимальная глубина цепочки от ядра — 6 (коммерция).

Движок «Типы контента» (property-sets + связи + шаблоны + генерик-ресурс) — не модуль, а подсистема ядра; в графе requires не участвует как узел. Пресеты blog/reviews/galleries/faq/banners планируются к переезду на него, faq — кандидат в пресет (модуль уже реализован в коде); ревизия каждого ТЗ-пресета предстоит, не свершившийся факт — engine §16.

⚠️ Довнесено под корп-MVP (15.07.2026): 5 новых модулей — cms/catalog-showcase, cms/section-patterns, cms/form-builder, cms/head-scripts, cms/ai-content — включены в таблицу слоёв (ярус графа сверен по фактическим requires) и в ASCII-графы ниже; requires/приоритеты P0–P2 — источник build-layer-2 «Группа E». Граница «ядро vs модуль» — реестр критериев ядра §10; манифест и канонический реестр provides — стандарт §2.

Зачем это нужно

Принцип «всё — модуль» без управления зависимостями опасен:

  • порядок загрузки: модуль A использует события модуля B — B должен загрузиться раньше;
  • обязательные требования: модуль «Заказы» бессмысленен без «Каталога» и «Корзины»;
  • каскад включения: включил «Магазин» → должны включиться «Каталог» + «Корзина» + «Заказы» + «Платежи»;
  • каскад выключения/удаления: нельзя выключить «Каталог», пока включён «Заказы» (preflight disable — стандарт §3);
  • конфликты версий: модуль требует ядро ≥ 2.0, а установлено 1.5 → блокировать.

Два уровня зависимостей

1. Composer-уровень (пакеты)

Технический слой — composer.json каждого модуля:

  • require: { "cms/core-contracts": "^2.0", "cms/commerce-catalog": "^1.3" } — composer сам решает граф, версии, конфликты, порядок автозагрузки провайдеров. Зависимость от ядра — только через cms/core-contracts, никогда cms/core (см. центр обновлений);
  • minimum_core_version в манифесте (сверх composer — для UI и понятных ошибок);
  • это бесплатно даёт Laravel/composer — не переизобретаем.

2. Домейн-уровень (включение/иерархия в рантайме)

Логический слой поверх composer — манифест extra.cms (стандарт §2):

Поле манифестаСмысл
requiresМодули, без которых не работает (жёсткая зависимость)
suggestsМодули, усиливающие функциональность (мягкая, опциональная)
conflictsМодули, несовместимые с этим (пример: cms/multisitecms/multitenancy — одновременное включение запрещено)
providesКонтракт из канонического реестра (напр. payment-gateway); новый контракт — только ревизией ядра
load_afterПорядок: загрузиться после указанных (для событий/хуков)
minimum_core_versionМинимальная версия ядра для UI-проверки

Реестр модулей ядра строит из деклараций граф зависимостей и:

  • не даёт включить модуль без его requires;
  • предлагает включить suggests;
  • блокирует включение при conflicts;
  • сортирует загрузку по load_after (топологическая сортировка);
  • при выключении/удалении проверяет обратные зависимости (кто зависит от меня).

Правила направления стрелок (инварианты графа)

Проверяются CI-линтером манифестов; нарушение любого — блокер ревью:

  1. Ядро не требует ничего. Ни одной стрелки из ядра в модуль. Если способности ядра нужен модуль (поиск, гео, капча, сканер загрузок) — зависимость инвертируется через provides-контракт: ядро резолвит реализацию через DI, 0 реализаций = деградация.
  2. Циклы запрещены. Сейчас в графе requires циклов нет (проверено топологической сортировкой по всем 117 манифестам); появление цикла — ошибка проектирования, решается выделением общего контракта или события.
  3. Нижний слой не знает о верхнем. cms/commerce-orders не может требовать cms/loyalty; связь «заказ начисляет бонусы» — событие OrderPaid, которое слушает loyalty. Стрелка requires всегда направлена к более базовому модулю.
  4. Альтернативные зависимости («ИЛИ») в requires не выражаются. Пример: cms/seo-filter требует источник фасетов — cms/commerce-facets илиcms/services. Канон: оба — в suggests, а self-test на enable (стандарт §3) проверяет наличие хотя бы одного и отказывает во включении с внятной ошибкой.
  5. requires ссылается на конкретные модули. Шорткат ТЗ «cms/commerce-model (заказы)» — ссылка на доменную модель, в манифесте он разворачивается в конкретный модуль слоя: «(заказы)» = cms/commerce-orders, «(каталог)» = cms/commerce-catalog и т.д.

Слои графа (фактическое состояние)

Ярус = максимальная глубина цепочки requires от ядра. Чем глубже модуль, тем длиннее каскад включения и тем позже он в порядке сборки.

Развёртка яруса 2 в рабочее ТЗ волны разработки — Слой 2 — ТЗ волны модулей.

ЯрусМодули (по манифестам)
0 — ядроcms/core + cms/core-contracts + cms/testing — не требуют ничего
1 — независимыеapi-tokens, session, domains, email-templates, storage-s3, notifications-bus, multisite, multitenancy, onboarding, dev-panel, fleet-dashboardrequires: —, расширяют ядро только через контракты
1 — от ядраобязательная пятёрка (health, backup, sentry, attack-monitor; updates — ярус 2, см. ниже), integrations-bus, webhooks-in/out, realtime, search, moderation, весь корпсайт-контент (services, blog, faq, galleries, landings, reviews, …), SEO (seo-engine, seo-filter, multicity, multilang), auth-надстройки (oauth, two-factor, magic-login, password-policy), cabinet-b2c, commerce-catalog, корп-MVP на блоках ядра (section-patterns, catalog-showcase, form-builder, head-scriptsrequires только ядро, см. build-layer-2 «Группа E»)
2–3потребители хабов (sms, telegram, web-push, dadata, cbr-rates, transport-providers, …), updates (← backup + health), cabinet-b2b, services-seo/services-axes, ugc (← moderation), chat (← realtime), commerce-pricingcommerce-cart, ai-content (← integrations-bus, сверх ядра — глубже яруса 1; P2, реализация отложена)
4–6коммерческая цепочка: commerce-orders (4) → commerce-payments (5) → pay-gateways-ru, crypto-payments, commerce-receipts, commerce-rma, commerce-digital, commerce-subscriptions (6); loyalty (5) → referral (6); commerce-invoices (5) → edo (6)

Хабы графа (in-degree по requires)

Модуль, который требуют многие, — квази-ядро своего домена: его публичные сервисы и события де-факто контракты. Правило: у хаба (≥ 5 входящих requires) изменение сигнатур/событий проходит по той же дисциплине, что ревизия ядра, — deprecation-окно минимум один минор, мажор только с миграцией потребителей.

ХабКто требуетРоль
cms/integrations-bus16: calendars, cbr-rates, crypto-payments, dadata, delivery-ru, edo, erp, integration-crm/google/yandex/marketplaces, messengers, ofd, pay-gateways-ru, transport-providers, video-hostingвсе внешние APIединая точка: креды, rate-limit, ретраи, журнал вызовов
cms/commerce-orders10 (через шорткат «commerce-model (заказы)»): b2b, delivery, digital, payments, promo, receipts, rma, services, tax, vendorкоммерцияцентр доменной модели магазина
cms/commerce-payments6: digital, receipts, rma, subscriptions, crypto-payments, pay-gateways-ruплатёжный слойшлюзы подключаются к нему через payment-gateway
cms/notifications-bus6: messengers, mobile-api, notifications-inbox, sms, telegram, web-pushканалы уведомленийроутер; ядро шлёт через NotificationDispatch с log-fallback без него
cms/commerce-catalog5, cms/commerce-pricing5коммерциябазовые слои модели
cms/webhooks-in4: integration-crm, pay-gateways-ru, telegram, messengersприём внешних колбэковединая точка подписи/верификации

Граф по доменам

Стрелка A ◄── B = «B требует A».

Обязательная пятёрка managed-парка (стандарт §3) — все от ядра, updates дополнительно требует своих страховок:

ядро ◄── health ◄──┐
ядро ◄── backup ◄──┤── updates ◄── marketplace-modules
ядро ◄── sentry    │
ядро ◄── attack-monitor

Инфраструктура и каналы:

ядро ◄── integrations-bus ◄── dadata, cbr-rates, erp, ofd, calendars, video-hosting*,
│                             transport-providers, integration-{1c,crm,google,yandex,marketplaces},
│                             messengers*, delivery-ru*, pay-gateways-ru*, crypto-payments*, edo*,
│                             ai-content (P2, реализация отложена)
├─── webhooks-in ◄── integration-crm, pay-gateways-ru, telegram, messengers
├─── realtime ◄── chat
└─── (без requires) notifications-bus ◄── sms**, telegram, web-push, messengers,
                                          mobile-api, notifications-inbox
     (без requires) storage-s3 ◄── video-hosting
   * — вторая зависимость в другом домене   ** — sms требует ещё transport-providers

Корпоративный сайт (приоритет фазы 1 — все на расстоянии 1–2 от ядра, это осознанно):

ядро ◄── services ◄── services-seo ◄── services-axes
├─── blog (пресет), faq (пресет), galleries (пресет), landings, reviews (пресет),
│    comments, calculator, wizard, popups, banners (пресет), surveys,
│    related-content, scheduled-publishing
├─── корп-MVP, ярус 1 (Группа E, build-layer-2): section-patterns (P0),
│    catalog-showcase (P1), form-builder (P1), head-scripts (P1) — requires только
│    ядро, без commerce-*/друг друга
├─── seo-engine, seo-filter (фасеты: commerce-facets ИЛИ services — через suggests),
│    multicity, multilang, search
├─── oauth, two-factor, magic-login, password-policy ─ auth-надстройки
├─── cabinet-b2c ◄── cabinet-b2b
├─── consents ◄── esia          cookie-consent ◄── pixels
└─── newsletter ◄── email-marketing ──► email-templates (без requires)

Коммерция (фаза 3; самая глубокая ветка графа):

ядро ◄── commerce-catalog ◄── commerce-attributes ◄── commerce-facets
              ▲    ▲    ▲
              │    │    └── commerce-stock ◄── integration-1c*, integration-marketplaces*
              │    └── commerce-wishlist
              └── commerce-pricing ◄── commerce-currencies ◄── (suggests) cbr-rates

         commerce-cart ─┘ ◄── commerce-abandoned

         commerce-orders ◄── commerce-invoices ◄── edo*
              ▲       ▲
              │       └── loyalty ◄── referral      (loyalty также требует pricing)
         commerce-payments ◄── pay-gateways-ru*, crypto-payments*, commerce-digital,
              ▲                commerce-receipts, commerce-rma, commerce-subscriptions

   (через «commerce-model (заказы)») commerce-b2b, commerce-delivery ◄── delivery-ru*,
                                     commerce-promo ◄── coupons, commerce-services,
                                     commerce-tax, commerce-vendor
   * — вторая зависимость: integrations-bus / webhooks-in / import

UGC и модерация: ядро ◄── moderation ◄── ugc; antifraud/antispam — от ядра, подключаются к потребителям контрактами fraud-signal/spam-filter.

Иерархия связей внутри ядра

Даже внутри ядра подсистемы связаны и порядок важен (состав — ТЗ ядра):

Подсистема ядраЗависит отИспользуется
События/фильтры (FilterBus)всеми
Движок полей (FieldTypeRegistry)типы контента, формы, блоки, каталог
Кеш-слой (CacheTags) + RequestContextнастройкиpage-cache, все модули
API-слойаутентификация, RBACмобильные, интеграции, кабинеты
Типы контентадвижок полейкаталог, услуги, блог
Страницы/блоки (BlockRegistry)движок полей, ревизиивсе контентные модули
SEO-база + SitemapRegistry + RedirectServiceстраницыseo-engine, seo-filter, multicity, все с URL
Формы/заявки (LeadService)движок полей, очередивсе модули с лид-формами
Медиатека (MediaService)хранилище (storage-backend)все модули с изображениями
NotificationDispatchочередилиды, auth-события; расширяется notifications-bus
PrivacyRegistrycms:privacy:export/forget по всем модулям
ScheduleRegistrarпланировщиквсе модули с cron
Движок типов контента (property-sets + связи + шаблоны + генерик-ресурс)движок полейпресеты типа контента: blog, reviews, galleries, faq, новости, ленты (см. карта пресетов)

Полный список контрактов — ТЗ ядра.

Граф и граница «ядро vs модуль»

Граф даёт проверяемые дополнения к тесту четырёх «да» (реестр критериев §10):

  • направление стрелок: как только проектируемая способность ядра требует стрелку ядро → модуль — способность спроектирована неверно; либо она целиком уезжает в модуль, либо в ядре остаётся контракт (реестр/сервис), а реализация — в модуле;
  • in-degree: если способность требуют ≥ 2 модулей из разных доменов — это аргумент за контракт в ядре (критерий 3 теста); если потребители из одного домена — это хаб домена (как commerce-orders), не ядро;
  • глубина: способность на ярусе 1 (зависит только от ядра) — здоровый модуль; способность, которую пришлось бы класть на ярус 0, — кандидат в ядро только если проходит остальные три «да».

Санитария графа (проверка 14.07.2026)

  • Циклов нет — в том числе потенциально опасная пара updates ↔ backup/health направлена в одну сторону (updates требует их, не наоборот).
  • cms/geoip — фантом: упоминается в 4 ТЗ (multicity, session, cookie-consent) как реализация geo-provider, но в каталоге/реестре модуля нет — у контракта 0 реализаций. Деградация штатна (так и задумано), но для продакшена мультигорода нужен модуль — кандидат зафиксирован в открытых вопросах.
  • cms/captcha — фантом: реальные реализации captcha-providercms/integration-yandex (SmartCaptcha) и cms/integration-google (reCAPTCHA); упоминания «cms/captcha» в ТЗ читать как «любая реализация контракта».
  • cms/commerce-model — шорткат ТЗ, не пакет: 10 commerce-модулей используют его как ссылку на доменную модель; в манифестах разворачивается в конкретные модули (правило 5 выше).

Метапакеты (наборы под типовой заказ)

Чтобы не собирать вручную десяток модулей на каждый заказ — composer metapackage, который через зависимости подтягивает набор. Канонические составы — в каталоге модулей; заявки, SEO-база и конструктор форм — ядро, в метапакеты не входят.

Метапакет = один composer require cms/preset-shop, дальше composer + граф разворачивают всё корректно. Глубина коммерческой ветки (6 ярусов) — ещё один довод за метапакеты: ручное включение цепочки из 6+ модулей в правильном порядке — источник ошибок, каскад enables делает это атомарно.

Что это даёт Claude Code

Граф зависимостей — не только рантайм-механизм, но и карта для AI-агента: по манифестам модулей Claude Code видит, что от чего зависит, что можно безопасно менять, а что затронет соседей. Хаб-модули (таблица выше) — сигнал агенту: изменение их публичных сервисов требует прохода по всем потребителям. См. удобство для Claude Code.

Связь с другими разделами

Механика деклараций — стандарт модуля §2–3 (манифест каноничен там; контракт модуля — обзор). Каскад включения/выключения и lifecycle (activate/deactivate/remove) — из исследования Botble. Порядок загрузки по load_after — из Drupal/TYPO3.

Внутренняя база знаний студии