Слои-слайсы
Эта страница — свод правил: 8 групп, одно правило зависимостей и ментальные модели, которые решают, куда идёт новый код. Полный список всех подслайсов — в Разборе слайсов; почему api вообще устроен так — в Обзоре.
8 групп
Внутри api/src/slices/ каждый вертикальный слайс CleanSlice принадлежит одной из 8 групп, упорядоченных от фундамента к вершине:
| # | Группа | Одна задача |
|---|---|---|
| L0 | infra | адаптеры к внешним системам (БД · кэш · blob · вектор) — чистые I/O-драйверы, без домена |
| L0 | setup | плумбинг фреймворка и экспозиции (core = REST, mcp = MCP) — без собственной способности |
| L1 | system | общие сервисы, каждый что-то делает: замеряет, ограничивает, уведомляет, инферит, хранит файлы |
| L2 | user | идентичность и тенантность — тенант = команда |
| L3 | admin | опс и аудит; читает данные других групп через Prisma, ничего сверху не импортирует |
| L4 | runtime | эфемерный конвейер исполнения: очередь → под → поток событий |
| L5 | agent | домен агента и мозг (orchestrator) |
| L6 | billing | верхний сток — деньги; его не импортирует никто |
Одно правило
Зависимости идут только вниз. Без циклов. Группа может импортировать только группы ниже себя.
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, шлюзы).