Skip to content

Слои-слайсы

Эта страница — свод правил: 8 групп, одно правило зависимостей и ментальные модели, которые решают, куда идёт новый код. Полный список всех подслайсов — в Разборе слайсов; почему api вообще устроен так — в Обзоре.

8 групп

Внутри api/src/slices/ каждый вертикальный слайс CleanSlice принадлежит одной из 8 групп, упорядоченных от фундамента к вершине:

#ГруппаОдна задача
L0infraадаптеры к внешним системам (БД · кэш · blob · вектор) — чистые I/O-драйверы, без домена
L0setupплумбинг фреймворка и экспозиции (core = REST, mcp = MCP) — без собственной способности
L1systemобщие сервисы, каждый что-то делает: замеряет, ограничивает, уведомляет, инферит, хранит файлы
L2userидентичность и тенантность — тенант = команда
L3adminопс и аудит; читает данные других групп через Prisma, ничего сверху не импортирует
L4runtimeэфемерный конвейер исполнения: очередь → под → поток событий
L5agentдомен агента и мозг (orchestrator)
L6billingверхний сток — деньги; его не импортирует никто

Одно правило

Зависимости идут только вниз. Без циклов. Группа может импортировать только группы ниже себя.

infra   ← никто
setup   ← (максимум) infra
system  ← infra · setup
user    ← system · setup · infra
admin   ← user (+ читает остальных через Prisma)
runtime ← system · setup · infra            (никаких рёбер в agent)
agent   ← runtime · system · user · …       (мозг тянется вниз ко всем)
billing ← system · user · notification      (ВЕРШИНА: billing не импортирует никто)

Инвариант принуждается в CI (boundary-проверка валит сборку на импорте вверх — см. Реализацию). Всё остальное на этой странице отвечает на один вопрос: в какую группу идёт мой новый слайс?

В какую группу? — ментальные модели

infra vs setup vs system:

  • infra = адаптеры к внешним системам (БД, кэш, blob, вектор). Чистые I/O-драйверы.
  • setup = плумбинг фреймворка/экспозиции без собственной способности — экспонирует функциональность других слайсов. core = REST-экспозиция, mcp = MCP-экспозиция.
  • system = общие L1-сервисы, каждый из которых что-то делает (записывает / ограничивает / уведомляет / инферит / хранит).

system vs runtime:

  • system = состояние и способность (что истинно / фундаментально). Персистентно, низко.
  • runtime = механизм и действие (как выполняется задача): очередь → эфемерный под → стрим.

Тест на членство в system: L1-лист (зависимости только от infra/setup), используемый несколькими верхними слоями. Держите критерий строгим, иначе system снова обрастёт в жирную свалку.

Вынесенные решения (не пересматривать без причины)

  • orchestrator — это мозг → живёт в agent, не в runtime. Runtime = чистые механизмы; мозг читает состояние домена агента и погоняет механизмы, поэтому сидит выше них.
  • billing — чистый сток → вершина (L6). Billing не импортирует никто; setting читает team.planId (который billing пишет) вместо импорта billing (инверсия зависимости).
  • llm и file — в system, не в runtime — фундаментальные способности, используемые многими слоями, а не часть конвейера исполнения. («Эмитит usage» — не критерий соседства.)
  • mcp остаётся в setup, не в system — это транспорт, экспонирующий тулы других слайсов (близнец REST у core), без собственной способности.
  • admin остаётся внизу (L3), читая данные других слайсов напрямую через Prisma (без импортов feature-модулей), — чтобы не тащить agent/runtime-зависимости в низкий слой.
Как мы к этому пришли (переименования 1.x → 2.0)

platform переименован в system. Старая жирная группа «account» распущена: user, admin, billing стали своими группами; usage/setting/notification/llm/file — общие L1-сервисы. publicApi распущен (rate-limit → core, доставка вебхуков → notification, ключи уже в user/apiKey). runtime/artifacts влился в system/file.

Смотрите также

  • Разбор слайсов — все подслайсы каждой группы, по таблице на группу.
  • Обзор — почему api — один образ с двумя ролями.
  • Реализация — build-промпт, который прошивает группы + CI boundary-проверку.
  • Конвенции — правила CleanSlice внутри слайса (domain/data/dtos, шлюзы).