Уровень изложения ТЗ (analyst altitude)
Главное правило стиля для всей документации-постановки PIN (docs/06-services/**, use-cases, сущности,
события, сценарии). Определяет уровень абстракции: что писать, что опускать, какой блок когда включать.
Остальные правила (algorithm-documentation-rules, cqrs-documentation-rules, api-documentation-rules,
entity-documentation-rules, event-documentation-rules, task-specification-rules) и шаблоны
99-templates/* подчиняются этому уровню.
Основной принцип
ТЗ — это постановка задачи от аналитика для аналитиков, разработчиков и тестировщиков, а не описание кода. Документ отвечает на вопросы:
- что система делает и зачем (бизнес-цель);
- кто имеет право это делать (актор, permission, scope);
- какую сущность по каким условиям получить/проверить;
- что делать при успехе и при каждом отказе (happy path + negative paths);
- как понять, что реализовано корректно (acceptance criteria, ошибки, наблюдаемость).
Документ не отвечает на вопрос «как это в коде»: имена классов/хендлеров/валидаторов, вызовы репозиториев, монада результата, транзакции SDK, конверты сообщений — это детали реализации, им в ТЗ не место. Пиши так, будто система строится с нуля (greenfield): нет прототипов, нет старого Node-BFF, нет «as-is».
Оставляем — это и есть контракт ТЗ
- Доменные имена: сущности/агрегаты, поля и их типы/ограничения (в таблицах), enum-значения, статусы и
переходы, инварианты (
INV-*), коды ошибок + HTTP-статус + условие, HTTP-роуты, имена топиков и событий. - Доступ: актор, permission/policy, scope, tenant, record-level, audit — каждый пункт только если применим.
- Данные: модели запроса и ответа таблицами (поле, тип, обязательность, источник/маппинг, ограничения).
- Проверяемость: acceptance criteria, таблица ошибок, политика retry/DLQ, сигналы наблюдаемости (logs/metrics/traces), правила совместимости (additive/breaking, unknown enum).
Убираем — это детали реализации и мусор
- Секцию
## CQRSцеликом; именаCommand/Query/Handler/Validator; интерфейсыIOperationRequest/ITenantedOperationRequest/IOperationHandler; словоFluentValidation. - Вызовы репозиториев и переменные:
xxxRepository.FindBy(...),.FindById/.GetById/.Add/.Update/.Search/.Count, присваивания промежуточных переменных. - Монаду и конверты:
Result.Fail(CODE)-форму (сам КОД остаётся в таблице ошибок),Result<…>,IUnitOfWork.SaveChanges,RaiseDomainEvent(...),RestApiResponse/RequestTraceModel/PagingResult<T>/IOperationExecutor,KafkaEventMessageEnvelope. - В сущностях: таблицы
### Реализуемые capability-интерфейсы (Talent.Common.*), механику EF owned types, строкиRowVersion=xmin/IVersionedEntity, любыеAs-is (drizzle, Node-BFF) → to-beтаблицы. - Неприменимые блоки и шаги — опускаем целиком. Никаких
не применяется — Query, никаких## Побочные эффектысо всемиnone, никаких пустых строк «нет/none». - Мета-ссылки внутри спека: «по [Правилам Документирования Алгоритма]», «Cross-cutting требования — по [Общим Требованиям…]», «реестр «один дом»», «заполнен inline», шапку «Один файл = одна HTTP-операция…». Спек ссылается на контракты (сущности, события, соседние операции), а не на правила авторинга.
- Brownfield-рамку: as-is/to-be, Node-BFF, absorb-node, drizzle, «поглощает операцию…».
- Технологические протечки в актёрах: «админка Vite», «admin-система» → «администратор платформы» /
«admin API»;
orval/swagger/@pin/admin— убрать или обезличить.
Матрица блоков — когда какой блок включать
Включай блок, только когда ему есть что сказать. Пустой блок = удалённый блок.
| Тип документа | Обязательные блоки | Условные (только если есть содержание) | Всегда убрать |
|---|---|---|---|
API-операция (api/**) | H1 · Назначение · Metadata · Актор и доступ · HTTP-контракт · Входные данные · Модель ответа · Алгоритм · Ошибки и failure modes · Совместимость и наблюдаемость · Связанные документы | Побочные эффекты (только реальные события/внешние вызовы/проекции/уведомления) · Диаграмма (нетривиальное поведение) · record-level/tenant/audit-строки | ## CQRS, шапка-boilerplate, конверт RestApiResponse |
Consumer (consumers/**) | Назначение · Триггер (топики) · Маппинг «событие → эффект» (бизнес-термины) · payload→проекция · Алгоритм · Идемпотентность/version-guard · Retry/DLQ · Наблюдаемость | Диаграмма | таблица consumer/command/handler, «Change context: Absorb Node-BFF» |
Use-case (use-cases/**) | Назначение · Актор · Предусловие · Триггер · Основной поток · Постусловие · Acceptance Criteria | Альтернативные потоки · Ошибки · События (если публикуются) · Диаграмма | шаги с не применяется, вызовы репозиториев в потоке |
Entity (domain/**) | Назначение · Классификация (контекст, source of truth, таблица) · Поля · Инварианты · Связи | Переходы состояний (если это state machine) · Enum · События · JSONB-модели · Индексы/хранение/безопасность | capability-интерфейсы, As-is → to-be, EF owned-types механика |
Event (events/**) | Назначение · Metadata · Payload · Когда публикуется · Потребители · Версионирование/совместимость | Безопасность/PII · Вложенные модели | конверт KafkaEventMessageEnvelope, : IKafkaEvent в заголовке, не применяется unknown-enum |
Background job (background/**) | Назначение · Расписание и locking · Вход · Алгоритм · Идемпотентность/retry · Наблюдаемость | Диаграмма · Связанный runbook | CQRS request/handler/validator, CancellationToken, имена шины |
| Saga / search / system-scenario | по своим шаблонам (уже на целевом уровне) | — | остаточные мета-ссылки и SDK-имена |
Как писать «Назначение»
2–4 предложения простым языком: бизнес-цель операции, кто её вызывает, что получает на выходе.
Без ссылок на ТЗ.md:NNN, без мета-ссылок на правила, без деталей реализации. Читатель за 10 секунд должен
понять, зачем этот эндпоинт/сущность существует.
- Плохо: «Возвращает admin-системе (таб «Корпуса» админки Vite) картину… Поглощает as-is операцию Node-BFF
adminGetOverride. Cross-cutting требования — по [Общим Требованиям…]». - Хорошо: «Отдаёт администратору платформы карточку витринного оверрайда корпуса: исходные значения из источника, текущий оверрайд и эффективные значения витрины — чтобы решить, какие поля переопределить».
Как писать «Предусловие»
Короткий список бизнес-условий, которые должны выполняться до сценария (состояние актора, статус сущности, наличие данных). Не валидация входа (это в Алгоритме/Ошибках), а именно контекст запуска.
- Пример: «Пользователь авторизован. Объект опубликован (
Status = Published). Метрики аналитики синхронизированы (иначе — деградация: блок метрик скрыт)».
Как писать «Алгоритм»
Нумерованные бизнес-шаги: happy path + negative paths. Для каждого шага — какую сущность по каким
условиям получаем и что решаем; при отказе — какой код ошибки возвращаем (коды дублируются в таблице
«Ошибки»). Без CancellationToken, без вызовов репозиториев, без Result.Fail(...)-формы, без транзакций
SDK. Тривиальный CRUD описывается одним абзацем без нумерации.
Пример шага: «Найти правило ранжирования по цели (тип + id). Если активное правило уже есть → отказ
CATALOG_RANKING_RULE_DUPLICATE. Иначе создать правило со статусом Active и в одном согласованном
изменении пересчитать приоритет затронутых карточек».
Диаграммы
Mermaid оставляем там, где он проясняет поток, но участники — бизнес/доменные роли (актор, сервис,
витрина, внешняя система), а не IDbRepository/IUnitOfWork/Handler/Outbox. Для тривиального CRUD
диаграмму не рисуем.
Пример «до/после» (фрагмент алгоритма)
- До (кодовый уровень):
2. **Валидация.** FluentValidation: TargetId != Guid.Empty → ValidationError. targetProject = projectCardRepository.FindById(TargetId); null → Result.Fail(CATALOG_RANKING_TARGET_NOT_FOUND). - После (аналитический уровень):
2. Проверить вход: тип цели ∈ {Проект, Объект}, приоритет в диапазоне 0..1000. Убедиться, что цель существует, принадлежит компании застройщика и не снята с публикации; иначе — ошибка (не найдена / не принадлежит / уже есть правило).
Полнота и глубина спека (analyst altitude, но исчерпывающе)
Уровень абстракции — аналитический, но спек должен быть достаточным для реализации и интеграции без домысливания. Аналитик пишет для другого аналитика/разработчика: из спека должно быть однозначно понятно что построить, в каком порядке взаимодействуют части и как проверить. Углубляем — добавляя смысл, не код. «Глубже» ≠ «ближе к коду».
Углубляем (добавляем, если релевантно типу документа):
- Исчерпывающие потоки. Happy path + все значимые negative/alternative paths: граничные значения, пустые/предельные входы, конкурентные изменения, повторные вызовы, частичный отказ зависимостей, просроченные/отозванные права. Каждый шаг: какую сущность по каким условиям берём, что решаем, к какому исходу (успех / конкретный код ошибки) ведём.
- Интеграционные последовательности. Явно: кто кому что шлёт и в каком порядке — синхронные вызовы соседних сервисов и событийные цепочки (какое событие публикуется, кто потребляет, что делает, какое следствие-событие). Отметить синхронно/асинхронно, порядок, окно eventual-consistency, что видит пользователь в промежуточном состоянии.
- Кросс-сервисные контракты. Что этот сервис ожидает от других (входные события/поля/гарантии) и что предоставляет (исходящие события/поля/гарантии, ключ партиционирования, версия). Явные предположения о данных из реплик и поведение при их отсутствии/устаревании.
- Предусловия и постусловия. Что должно быть истинно до сценария и что гарантированно истинно после (какие сущности/статусы/счётчики изменились, какие события ушли).
- Инварианты, статусы, валидации — полностью перечислены. Все
INV-*, все переходы статусов (из/в, условие, кто инициирует), все правила валидации полей (границы, форматы, взаимозависимости). - Отказы и восстановление как бизнес-правила. Идемпотентность (ключ, поведение при повторе), retry/DLQ (что ретраится, сколько, что в DLQ), version-guard/конкурентность (кто побеждает, что видит проигравший), компенсации/саги при многошаговых эффектах.
- Acceptance criteria в форме Given/When/Then, покрывающие и happy path, и ключевые edge-cases и отказы.
- Наблюдаемость и НФТ по бизнес-смыслу. Что логировать/мерить (без секретов/PII), ключевые метрики и пороги, целевая нагрузка/латентность (envelope), требования безопасности/доступа на операцию.
Не добавляем (это НЕ углубление): код, имена классов/методов/хендлеров, вызовы репозиториев, SDK-типы, DDL таблиц, псевдокод «как код», mermaid с инфраструктурными участниками. Список «Убираем» выше остаётся в силе — углубление никогда не возвращает пламбинг.
Чек-лист «спек полон» по типам:
- API-операция: контракт (роут/вход/ответ) + актор/доступ + исчерпывающий алгоритм (happy + negative) + все коды ошибок с условиями + побочные эффекты (события/проекции/уведомления) + интеграция с соседями + acceptance + наблюдаемость + совместимость.
- Use-case: предусловие + триггер + основной поток + все альтернативные/ошибочные потоки + постусловие + межсервисная последовательность (события/вызовы) + acceptance (Given/When/Then).
- Entity: все поля с типами/ограничениями + все
INV-*+ полная state-machine (если есть) + связи + какие события порождает и при каком изменении + правила видимости/PII. - Event: payload (все поля) + точное условие публикации + все потребители и их реакция + гарантии доставки/порядка/идемпотентности + версионирование/совместимость (unknown enum, additive/breaking).
- Consumer: триггер-топики + маппинг «событие → эффект» + идемпотентность/version-guard + retry/DLQ + что при неизвестном/устаревшем событии + наблюдаемость.
- Background job: расписание/locking + вход + алгоритм + идемпотентность/retry + что при частичном прогоне/падении + наблюдаемость.
Дополняем существующий контракт, не переписывая и не теряя уже задокументированное (коды ошибок,
INV-*, enum, статусы, топики, события сохраняются). Если блок уже полон — не раздуваем ради объёма.
Обратные ссылки
Автоссылки: где используется этот документ.
- algorithm-documentation-rules.md (1): Правила Документирования Алгоритма
- cqrs-documentation-rules.md (1): Правила Документирования CQRS
- cross-cutting-document-requirements.md (1): Общие Требования К Документам
- ddd-rich-model-rules.md (1): DDD И Rich Model: Правила И Практика
- index.md (1): Шаблоны Документации
- api-method-template.md (1): <HTTP-метод>
— <Название операции> - command-query-template.md (1): Внутренняя операция: <НазваниеОперации>
- consumer-template.md (1): Consumer:
Связанные документы
- Эталоны стиля: saga-template.md, search-document-template.md, system-scenario-template.md.
- Структура алгоритма: algorithm-documentation-rules.md.
- Общие требования: cross-cutting-document-requirements.md.
- Постановка задачи: task-specification-rules.md.