Files
slm-design/DRAFT/rules/level-2.md
2026-08-02 22:53:05 +03:00

16 KiB
Raw Blame History

Правила SLM второго уровня

Доменный пакет Level 2 соблюдает правила Level 1 и дополнительные правила этого реестра. Для предметной области в пакетной форме SLM-L1-DOMAIN-R015 заменяется правилами доменного пакета; остальные предметные области того же SLM root могут сохранять форму доменного модуля Level 1. SLM-L1-GROUP-R007 сохраняется для Groups внутри пакета и вне слоя domains, а для навигационных Groups слоя domains заменяется SLM-L2-GROUP-R004. Для модуля api правило SLM-L1-MODULE-A004 уточняется SLM-L2-API-A019: объявленные фасеты вместе образуют один логический публичный API и не считаются deep imports. Ранее использовавшиеся номера SLM-L2-DOMAIN-R001 и SLM-L2-MIGRATION-A017 не переиспользуются.

Граница доменного пакета

SLM-L2-DOMAIN-R002

Предметная граница пакета

Каждая предметная область, использующая пакетную форму Level 2, представлена ровно одним доменным пакетом; все его модули относятся только к этой предметной области.

SLM-L2-DOMAIN-A003

Корень доменного пакета

Корень доменного пакета содержит только декларативную metadata, модуль api и допустимые Groups и не содержит других прямых модулей, исполняемых файлов, изменяемого состояния, ресурсов жизненного цикла, публичного API или реэкспортов.

SLM-L2-GROUP-R004

Навигационная Group доменов

Group, расположенная непосредственно в слое domains или другой такой Group, содержит только доменные модули Level 1, доменные пакеты Level 2 и навигационные Groups и не владеет реализацией, состоянием, жизненным циклом или публичным API.

Доменный API

SLM-L2-API-R005

Модуль api

Каждый доменный пакет содержит ровно один модуль api, который объявляет один или несколько именованных Domain API, их публичные модели, результаты, ошибки, dependency ports и фабрики.

SLM-L2-API-R006

Семантическая власть Domain API

Доступные приложению доменные данные, модели, validation, семантика команд и запросов, результаты и ожидаемые ошибки производятся или проверяются модулем api; adapters, assemblies и framework bindings не определяют параллельную предметную модель или переход.

SLM-L2-API-A007

Импортная замкнутость api

Все runtime- и type-only импорты модуля api, кроме междоменных зависимостей по SLM-L2-DEPENDENCY-A012, ведут только к файлам этого модуля, объявленным environment-neutral ресурсам shared и внешним пакетам, объявленным как API-safe.

SLM-L2-FACTORY-R008

Фабрики Domain API

Каждому публичному Domain API соответствует ровно одна именованная фабрика фасета api/factory; фабрика получает явные ports и cross-domain API, создаёт только этот Domain API, не выбирает adapter или assembly и не запускает скрытые ресурсы жизненного цикла.

Ошибки домена

SLM-L2-ERROR-R009

Публичный контракт ошибок

Каждый ожидаемый сбой публичной операции Domain API представлен именованным readonly сериализуемым типом собственной доменной ошибки с устойчивым кодом; тип экспортируется через api, а необходимые внешним потребителям runtime-коды и guards только через api/runtime.

SLM-L2-ERROR-R010

Изоляция исходных ошибок

Сбой provider, adapter, SDK, транспорта, storage или другого домена, доступный приложению через Domain API, представлен только безопасной ошибкой собственного доменного контракта и не раскрывает исходный объект, тип, message, status, payload или cause.

Assemblies и зависимости

SLM-L2-ASSEMBLY-R011

Роль assembly

Каждая assembly является SLM-модулем одного объявленного production-контекста, выбирает adapter-модули, вызывает одну или несколько фабрик своего api и возвращает явный именованный граф готовых Domain API, не добавляя предметные операции, модели или ошибки.

SLM-L2-DEPENDENCY-A012

Междоменные импорты Level 2

Статическая связь между разными доменными границами, хотя бы одна из которых является пакетом Level 2, допускает только type-only импорт публичного API доменного модуля Level 1 или фасета api пакета Level 2 либо runtime-импорт api/runtime пакета Level 2; остальные публичные и внутренние пути другого домена не импортируются.

SLM-L2-ENVIRONMENT-A013

Совместимость среды выполнения

Для каждой объявленной точки входа, поддерживаемого набора resolver conditions и framework execution phase её достижимый executable import-граф не содержит несовместимых runtime capabilities; type-only связи, framework reference и deferred edges проверяются отдельно и не считаются обычным выполнением.

Framework Groups и тестирование

SLM-L2-FRAMEWORK-R014

Framework Group домена

Framework binding modules доменного пакета размещаются в Group, названной по фреймворку, и каждый прямой дочерний элемент этой Group является framework binding module.

SLM-L2-FRAMEWORK-R015

Framework binding module

Модуль внутри Framework Group владеет одной domain-specific framework-ответственностью, получает готовые Domain API, материализует их значения средствами фреймворка и не вызывает фабрики, не выбирает adapters, не обращается к предметному внешнему источнику в обход Domain API и не владеет страницей, маршрутом или multi-domain композицией.

SLM-L2-TEST-R016

Проверка владельцев Level 2

Каждый публичный сценарий проверяется через фабрику владеющего им Domain API, каждый adapter — по контракту реализуемого port, а основные тесты assembly и framework binding module проверяют только собственные публичные границы и не повторяют полный набор сценариев Domain API.

Совместное применение форм

SLM-L2-DOMAIN-A026

Однозначная форма домена

Каждая предметная область объявлена ровно в одной форме: как доменный модуль Level 1 либо как доменный пакет Level 2; один SLM root может одновременно содержать разные предметные области обеих форм.

Внешние библиотеки api

SLM-L2-API-R018

API-safe внешний пакет

Внешний пакет объявляется API-safe только если он детерминирован, не выполняет ввод-вывод, не владеет изменяемым состоянием или runtime capability и не является SDK, generated client, storage, state/query manager, framework или другой технической интеграцией.

Публичные фасеты api

SLM-L2-API-A019

Публичные фасеты api

Публичный API модуля api имеет обязательные entry points api только с type exports и api/factory только с runtime exports, может иметь api/ports только при наличии объявленного dependency port и только с type exports и api/runtime только с runtime exports и не имеет других публичных путей или deep imports.

Обязательная штатная сборка

SLM-L2-ASSEMBLY-A020

Обязательная assembly default

Корень каждого доменного пакета содержит ровно одну непустую Group assemblies с ровно одним прямым модулем default; каждый другой прямой дочерний элемент Group также является объявленной границей assembly-модуля.

SLM-L2-ADAPTER-R021

Модули production adapters

Если хотя бы одна фабрика имеет dependency port, корень доменного пакета содержит непустую Group adapters, а каждая связная production-реализация одного или нескольких ports принадлежит ровно одному adapter-модулю этой Group и не определяется в другом месте production-графа.

SLM-L2-API-A022

Потребители фасетов и сборочных модулей

Фасет api импортируется извне только через import type, api/ports импортируют только adapters своего домена, assemblies и тесты, api/factory и concrete adapters в production импортируют только assemblies своего домена, а api/runtime не импортируют adapters и используют только через объявленный публичный путь с соблюдением правил слоёв и междоменных зависимостей.

Жизненный цикл assembly

SLM-L2-ASSEMBLY-R023

Транзакционный lifecycle assembly

Assembly не запускает скрытую долгоживущую работу; cleanup каждого созданного ею ресурса и каждого полученного adapter lifecycle handle немедленно регистрируется, при частичной ошибке выполняется в обратном порядке, а успешный результат с cleanup obligations предоставляет идемпотентный aggregate cleanup, после завершения которого resources не вызывают callbacks.

Недетерминизм api

SLM-L2-API-R024

Явные источники недетерминизма

Операция Domain API получает текущее время, timer, random, ID generator, environment и другие источники недетерминизма только через явные ports фабрики и не читает их из скрытого runtime-окружения.

Публичный runtime api

SLM-L2-API-R025

Детерминированный runtime api

Фасет api/runtime экспортирует только необходимые реальным внешним потребителям детерминированные значения и функции без ввода-вывода, изменяемого состояния, runtime capability или environment-specific поведения.

Dependency ports

SLM-L2-PORT-R027

Consumer-owned port

Каждый dependency port принадлежит модулю api, описывает минимальную необходимую ему capability и закрытый набор ожидаемых port failures без concrete provider, SDK, framework или transport types; adapter реализует этот контракт, но не определяет его семантику.

Материализация состояния

SLM-L2-STATE-R028

Framework-owned materialization

Framework binding или composition может владеть framework metadata и собственным UI-state, но материализует доменный payload только из values, outcomes и events, произведённых или проверенных Domain API, и применяет предметный optimistic merge, reconciliation или transition только через операцию либо детерминированный runtime модуля api.

Realtime

SLM-L2-REALTIME-R029

Проверяемый realtime-контракт

Каждый realtime port явно определяет correlation, момент подтверждения команды, ordering, duplicate, reconnect, resync, cancellation и cleanup semantics; adapter скрывает transport protocol, а Domain API публикует только проверенные события, outcomes и собственные стабильные ошибки.

Runtime-граф assemblies

SLM-L2-ASSEMBLY-R030

Ацикличная runtime-сборка

Runtime-граф публичных API доменных модулей Level 1 и Domain API пакетов Level 2, включая assembly inputs, factory dependencies и передаваемые callbacks, не содержит циклов, а graph owner создаёт независимые API раньше зависимых и очищает их в обратном порядке.

SLM-L2-ASSEMBLY-R031

Контекст default assembly

assemblies/default представляет один объявленный штатный production-набор API, dependencies, runtime capabilities и lifecycle; имя default само по себе не означает browser-, server- или isomorphic-совместимость, а отличающийся контекст получает отдельную именованную assembly.