Перейти к основному содержимому

Разработка

Шаблон department scope

Новые аутентифицированные маршруты должны применять изоляцию отдела через forUser() из src/lib/department-scope.ts. forDepartment() остаётся как совместимый алиас, но forUser() даёт помощники для разрешений и scope нескольких отделов.

Используйте самый узкий хелпер, подходящий под форму данных:

const scope = forUser(request.user);

// Model has departmentId directly.
await prisma.knowledgeBase.findMany({
where: { ...scope.directWhere() },
});

// Model is scoped through Namespace.
await prisma.agentTask.findMany({
where: { ...scope.nestedWhere('namespace') },
});

Пользователи с global scope получают доступ ко всем отделам. Остальные ограничены рассчитанным scope.deptIds; не позволяйте параметрам запроса departmentId переопределять scope.canSeeDept() или scope.directWhere().

Для raw SQL, где допустим только один department-фильтр, стройте фильтры из scope.departmentId и передавайте значения как параметры Prisma SQL:

const departmentFilter = scope.departmentId
? Prisma.sql`AND kb."departmentId" = ${scope.departmentId}`
: Prisma.empty;

Для multi-department scope используйте scope.deptIds и фильтр IN (...), а не предполагайте, что scope.departmentId задан.

Маршруты также могут читать request.departmentScope, который после аутентификации декорируется через src/plugins/department-scope.ts.

Чеклист маршрута

  • Добавьте fastify.authenticate в каждый закрытый маршрут.
  • Добавьте RBAC-middleware (например, requirePermission()) там, где операция меняет привилегированные данные.
  • Примените forDepartment() или request.departmentScope перед запросом данных уровня отдела.
  • Возвращайте явные ошибки через sendError(), чтобы в ответах был формат { error, message, statusCode, details? }.
  • Добавьте route schemas, чтобы /docs соответствовал реальному поведению.
  • Добавляйте или расширяйте тесты изоляции отдела, когда новый эндпоинт отдаёт данные уровня отдела.

Пайплайн agent tasks

Handlers входящих каналов не должны владеть решениями про RAG, confidence и HITL. Для нового канала:

  1. распарсить транспортный payload;
  2. найти или создать пользователя, разговор и входящее сообщение;
  3. создать AgentTask;
  4. положить в очередь agent-tasks;
  5. пробросить outbound-зависимость, чтобы agent executor мог отправлять одобренные или авто-пропущенные ответы.

Agent executor worker владеет шагами inject_profile, rag_search, generate и confidence_check. См. ADR-001.