Спецификация сервиса — контракт между бизнесом и разработкой. Описывает один Bounded Context в доменных терминах: заполняется совместно бизнес-аналитиком, архитектором и разработчиками, читается человеком, используется AI-агентом как memory bank и как источник для генерации кода, диаграмм (Structurizr) и индексации (GraphRAG).

Перед заполнением — соберите данные через Event Storming. Workshop на 4–8 часов выявляет события, акторов, бизнес-правила, агрегаты и границы контекстов; каждый артефакт ложится в конкретный раздел спеки. См. стратегические паттерны DDD.

Заполненные примеры по сервисам маркетплейса — в разделе Кейс.


Принципы

  1. Единица спеки — Bounded Context, не агрегат. Один контекст = одна спека. Если в контексте несколько агрегатов — спека разбивается на корневой файл (секции уровня контекста) и по файлу на агрегат. Дробить контекст по агрегатам на отдельные спеки нельзя: Ubiquitous Language, Context Map, роли — свойства контекста.
  2. Домен без техники. Все секции, кроме «Технической реализации», — в доменных терминах. Фреймворки, аннотации, схема БД, механизмы доставки (Outbox), топики, стек — только в «Технической реализации».
  3. Ничего не дублируется. Каждый факт — в одном каноническом месте; остальные ссылаются. События описываются у агрегата-владельца; переходы — в матрице жизненного цикла; ошибки — в командах и бизнес-правилах.
  4. Карточки + строгие таблицы. Команды, запросы, use cases — карточки ### Имя с размеченными полями (читаемо человеку, парсится агентом). Структурные секции (доступ, события, интеграции) — таблицы с нормализованным словарём.
  5. Контекст не претендует на знание соседей. Соседние контексты — только как рёбра на стыке (Context Map). Полная Context Map и классификация субдоменов — артефакт уровня домена.

Раскладка файлов

docs/spec/
  <service>-spec.md          # корень: секции уровня КОНТЕКСТА
  aggregates/
    <aggregate>.md           # по файлу на агрегат: секции уровня АГРЕГАТА

Домен-юнит — всегда в отдельном файле aggregates/<name>.md, даже если он один и на любом уровне зрелости; корень держит только секции контекста. Домен-юнит — это агрегат на Уровне 3; на Уровне 1–2 (DDD-агрегатов нет) — центральная сущность контекста (product.md, notification.md). Единая структура «корень + aggregates/» во всех спеках.

Минимальный frontmatter — для идентичности чанка при индексации: корень context + bounded-context + level; файл юнита context + aggregate + level. Больше ничего: что выводимо из путей/имён или есть в теле — не дублируем.

Секции уровня контекста (корневой файл)

РазделЧто внутри
1Bounded Contextконтекст, субдомен (Core/Supporting/Generic), владелец, миссия; таблица агрегатов; что внутри/вне границы; стыки
2Интеграции (Context Map)контекст-карта (одна mermaid) + таблица рёбер (нормализованный словарь) + контракты (ссылки на OpenAPI/AsyncAPI)
3Ubiquitous Languageглоссарий контекста; «не путать»
4Роли и доступроли + общие ABAC-правила + PII; доступ к операциям — в каждом агрегате
5Доменные событияконтракт публикуемого языка: «агрегат → внешние события → топик»
6Use Casesсквозные сценарии карточками ### UC-N
7ПроцессыSaga / Process Manager: кросс-агрегатные процессы, sequence-диаграммы
8UI-спецификациясвязь статусов с UI, тексты ошибок для пользователя
9Критерии приёмкиGiven / When / Then
10Нефункциональные требованиятаблица: производительность, доступность, согласованность, безопасность, наблюдаемость (целевые значения, без инструментов)
11Техническая реализацияединственный технический раздел: контейнеры C2, таблица «слой → стек → реализация», схема БД (ER + индексы)

Секции уровня агрегата (файл агрегата)

РазделЧто внутри
1Доменная модельагрегат-корень + сущности, value objects (через инвариант), class-диаграмма
2Жизненный циклстатусы + матрица переходов (команды, события, политики/таймауты) + state-диаграмма
3Доступматрица «операция × роль» + ABAC
4Бизнес-правиласписок BR-<префикс>NN с типом, командой и кодом ошибки
5Командыкарточки: Переход · Вход · Предусловия · Логика · Эмитит · Ошибки
6Доменные событиятаблица «событие — триггер — scope — подписчики»
7Запросыкарточки: Вопрос · Параметры · Возвращает · Логика (источник чтения, фильтр, согласованность)

Конвенции

  • Value Objects описываются через инвариант, который защищают (не через поля/типы — это БД). Для sum-типов — варианты (Discount: Percentage | Fixed).
  • Бизнес-правила — код с префиксом агрегата (BR-O01, BR-D01), чтобы не сталкивались.
  • Команды vs реакции/политики. В «Командах» — только публичные команды от акторов. Реакции на события и политики (таймауты) не выносятся отдельными карточками — они уже в матрице переходов и «Доменных событиях».
  • Каталога ошибок нет. Коды — в «Командах» (поле «Ошибки») и «Бизнес-правилах»; тексты для пользователя — в «UI»; HTTP-маппинг — артефакт API.
  • Кросс-агрегатные ссылки — по ID, без FK (<other>_id — логическая ссылка); это отражается и в class-диаграммах, и в ER.
  • Интеграции — нормализованный словарь (inbound|outbound|bidirectional, sync|async, customer-supplier|conformist|ohs). Контракты на рёбрах — ссылки: REST → OpenAPI, async → AsyncAPI; владелец по типу связи.
  • Диаграммы: поведенческие (state machine, sequence) рисуются вручную; одна контекст-карта в «Интеграциях»; ER — в «Технической реализации». Полные C1/C2/C3 при необходимости генерирует Structurizr из таблиц.

Уровень зрелости — глубина спеки

Глубина = уровень зрелости сервиса (одна ось 0–3):

УровеньАрхитектураЧто меняется
0 — As-isреверс из кода без бизнес-брифа (ucp-spec-tier-0)снимок «как сейчас»; not-declared для пробелов; точка отсчёта для миграции
1 — СлоёныйController → Service → Repository, без usecase-patternDDD-агрегатов нет (один «модуль»); «Доменная модель» = ER + таблицы; «Доменные события» и «Процессы» пропускаются с пометкой; центральная сущность всё равно в aggregates/<name>.md
2 — Use Case Patternusecase-pattern (UseCase + Handler)команды = UseCase-классы; события — если реально публикуются; CQRS + Read Model — опция уровня
3 — DDD + Hexagonalагрегаты, доменные события, ports/adapters, ArchUnitполная глубина, разбивка по агрегатам

Уровень 0 — as-is из кода. Существующий сервис без бизнес-брифа: спеку генерирует скилл ucp-spec-tier-0, читая код, миграции и конфиги; ставит level: 0, не выдумывает агрегаты там, где код anemic, не классифицирует «правильно/неправильно»; отсутствующие данные помечает литералом not-declared — явный gap-сигнал. Это база для онбординга и точка отсчёта для миграции на нужный уровень.

Раздел, неприменимый на текущем уровне, не опускается молча — пишется заголовок и однострочная пометка («Не применимо на Уровне 1»).


Дальше

  • Заполненные примерыКейс маркетплейса: спеки сервисов в этом формате.
  • Скиллы AI-агента для генерации и ревью спеки — настройка: ucp-spec-design (по бизнес-описанию), ucp-spec-tier-0 (из кода), ucp-spec-review (design-критик).
  • Уровни зрелостиUse Case Pattern (1–3).
  • Стратегические паттерны DDDграницы контекстов и Context Map.