ТTessora Docs

Архитектура

Схема системы и ключевые архитектурные решения

Общая схема

Browser (React 19, TanStack Query, Zustand, Tailwind CSS v4)

Next.js 16 App Router (Vercel, Node runtime)
├── src/app/(app)/...    защищённые страницы
├── src/app/api/...      HTTP API (Route Handlers)
├── src/lib/auth/        Better Auth + RBAC
├── src/lib/ai/          AIService (multi-provider + fallback chain)
└── src/lib/storage/     S3-клиент (R2 / MinIO)

PostgreSQL (Prisma 6) + Redis (BullMQ) + R2/MinIO (S3 API)

Бэкенда как отдельного сервиса нет: API routes Next.js = бэкенд. Тяжёлая фоновая работа (скачивание видео Safebot) вынесена в BullMQ-воркер на Railway.

Ключевые решения

  1. Единый Next.js — App Router рендерит страницы, Route Handlers дают HTTP API. Один деплой, один кодстайл.
  2. RBAC в 4 уровня — подробно в разделе Auth и RBAC:
    • src/proxy.ts (middleware) — проверка сессии;
    • server-side redirect по ролям (lib/auth/redirects.ts);
    • withPermission("key", handler) — guard каждого API endpoint;
    • usePermissions() / <Can> — скрытие элементов UI.
  3. Динамические permissions — базовая матрица ROLE_PERMISSIONS_MATRIX + точечные overrides в таблице UserPermission.
  4. Invitation-only — публичная регистрация заблокирована, вход в систему только по приглашению.
  5. AI Service — мультипровайдер (Gemini → OpenAI → Template), ключи хранятся в БД, управление через admin UI /ai, бюджет-лимиты. Прямые вызовы AI-SDK запрещены — только aiService.generate().
  6. Уведомления в 3 канала — in-app (polling 30s), browser push (Web Push API + Service Worker), Telegram (bot). WebSockets сознательно не используются.
  7. Multi-tenancy — все данные привязаны к companyId. Клиент видит только свою компанию, Monster Team — всех клиентов. Скоуп решается в lib/api/scope.ts.
  8. Soft delete — физическое удаление запрещено: везде deletedAt (+ deletedBy для задач).
  9. Reference Categories — database-driven — категории референсов лежат в таблице (не enum) и управляются через REST API.
  10. Единая пагинация — хук usePagination + компонент <Pagination />, состояние в URL.

Поток данных на примере задачи

  1. POST /api/taskswithPermission("task.create") → Zod-валидация тела → Prisma-транзакция (Task + TaskSelectedItem + TaskStyle + TaskInteriorType + Material).
  2. auditLog() пишет действие в AuditLog.
  3. notifyMonsterTeam() рассылает уведомления команде (in-app + push + telegram).
  4. Клиентский кэш обновляется через TanStack Query invalidation.

Файлы: presigned upload

Файлы не проходят через сервер приложения:

Клиент → POST /api/uploads/presign  → presigned PUT URL (S3)
Клиент → PUT файл напрямую в R2/MinIO
Клиент → POST /api/uploads/confirm/[fileId] → запись FileObject в БД

Правила кода (жёсткие)

  • Нельзя вызывать AI напрямую — только lib/ai/service.ts.
  • Нельзя хардкодить цвета — только CSS-переменные (8 тем!). См. Стилизация.
  • Нельзя писать кастомные кнопки — только UI Kit (@/components/ui).
  • Нельзя хардкодить permissions и категории референсов.
  • Нельзя удалять физически — только soft delete.
  • Каждая фича/фикс — запись в CHANGELOG.md ([Unreleased]); рефакторинги и стили не записываются.

On this page