Skip to content

Модульная структура

Приложение организовано по domain-driven принципам. Каждый модуль отвечает за отдельный аспект функциональности.

Архитектура: Два уровня API

Высокоуровневые API (Бизнес-логика)
├── /api/integrations     -> Управление интеграциями + handlers
├── /api/auth             -> Аутентификация (sign-up, sign-in, me)
├── /api/access-tokens    -> Токены доступа
├── /api/testing          -> Тестирование AI интеграций
└── /api/inngest          -> URLs для Inngest dashboard

Низкоуровневые API (integ-core прокси)
├── /api/core/secrets     -> Управление секретами (D1)
├── /api/core/cache       -> Управление KV (группировка по интеграции)
├── /api/core/d1          -> Прямой доступ к D1 таблицам
└── /api/core/kv          -> Прямой доступ к KV namespaces

Обзор модулей

src/app/
├── core/              # Глобальные конфигурации
├── shared/            # Общие утилиты и модули
│   ├── constants/     # Глобальные константы
│   ├── decorators/    # Декораторы (Swagger, etc)
│   ├── dtos/          # Data Transfer Objects
│   ├── entities/      # Базовые сущности
│   ├── enums/         # Глобальные enum'ы
│   ├── guards/        # Общие guards
│   ├── interceptors/  # Общие interceptors
│   ├── interfaces/    # Общие интерфейсы
│   ├── modules/
│   │   ├── crypto/    # Шифрование (@Global)
│   │   ├── health/    # Health check endpoint
│   │   ├── logger/    # Логирование (@Global)
│   │   ├── mcp/       # Model Context Protocol
│   │   ├── swagger/   # Scalar конфигурация
│   │   └── types/     # Типы
│   └── utils/         # Утилиты
├── auth/              # JWT аутентификация
│   └── access-tokens/ # Токены доступа (M2M)
├── users/             # Управление пользователями
├── integrations/      # REST API для управления интеграциями
│   ├── handlers/      # Event handlers
│   └── prompts/       # Prompt templates
├── emulator/          # Эмулятор API запросов
│   ├── collections/   # Коллекции запросов
│   ├── saved-requests/# Сохраненные запросы
│   ├── proxy/         # Прокси для запросов
│   └── secrets/       # Секреты эмулятора
├── testing/           # Автоматизированное тестирование AI интеграций
│   └── chats/         # Тестовые чаты
└── third-parties/     # Внешние сервисы
    ├── inngest/       # Inngest event processing
    └── integ-core/    # Cloudflare D1/KV/Cache/Secrets прокси
        └── controllers/
            ├── cache.controller.ts    # /api/core/cache
            ├── d1.controller.ts       # /api/core/d1
            ├── kv.controller.ts       # /api/core/kv
            └── secrets.controller.ts  # /api/core/secrets

Core Module

Путь: src/app/core/

Глобальные конфигурации и bootstrapping приложения.

Структура

core/
├── configs/
│   └── typeorm.config.ts       # TypeORM конфигурация
├── interceptors.ts             # Глобальные interceptors
└── core.module.ts              # Модуль

Ответственность

  • Конфигурация TypeORM (подключение к PostgreSQL)
  • Настройка глобальных interceptors
  • Базовые настройки приложения

Shared Module

Путь: src/app/shared/

Переиспользуемые компоненты для всех модулей.

Структура

shared/
├── constants/                       # Глобальные константы
│   └── index.ts
├── decorators/
│   └── swagger-auth.decorator.ts    # Swagger декоратор
├── dtos/                            # Data Transfer Objects
├── entities/
│   └── base.entity.ts               # Базовая entity
├── enums/                           # Глобальные enum'ы
│   └── index.ts
├── guards/
│   └── (index.ts)                   # Общие guards
├── interceptors/
│   └── (index.ts)                   # Общие interceptors
├── interfaces/
│   ├── base.interface.ts            # IBase интерфейс
│   ├── d1.interface.ts              # D1 Provider interface
│   └── kv.interface.ts              # KV Provider interface
├── modules/
│   ├── crypto/                      # Шифрование (@Global)
│   │   ├── crypto.module.ts
│   │   ├── services/
│   │   └── interfaces/
│   ├── health/                      # Health check
│   │   ├── controllers/
│   │   └── health.module.ts
│   ├── logger/                      # Логирование (@Global)
│   │   ├── services/
│   │   │   └── logger.service.ts
│   │   └── logger.module.ts
│   ├── mcp/                         # Model Context Protocol
│   │   ├── controllers/
│   │   ├── dtos/
│   │   ├── interfaces/
│   │   ├── services/
│   │   ├── tools/
│   │   └── mcp.module.ts
│   ├── swagger/                     # Swagger конфигурация
│   │   └── utils/
│   └── types/                       # Типы
│       └── types.module.ts
└── utils/                           # Утилиты
    └── index.ts

Ключевые компоненты

BaseEntity

Базовая сущность, от которой наследуются все остальные:

typescript
export abstract class BaseEntity implements IBase {
	@PrimaryGeneratedColumn("uuid")
	id: string;

	@CreateDateColumn({ name: "created_at" })
	createdAt: Date;

	@UpdateDateColumn({ name: "updated_at" })
	updatedAt: Date;
}

Crypto Module (@Global)

Шифрование и хеширование данных. Используется для защиты credentials.

Logger Module (@Global)

Централизованный логирующий сервис для всего приложения.

Swagger Module

Централизованная конфигурация Swagger документации.

Auth Module

Путь: src/app/auth/

Аутентификация и авторизация пользователей.

Структура

auth/
├── controllers/
│   └── auth.controller.ts
├── dtos/
│   ├── login.dto.ts
│   └── register.dto.ts
├── guards/
│   └── jwt.guard.ts
├── middlewares/
│   ├── auth.middleware.ts
│   └── index.ts
├── services/
│   └── auth.service.ts
└── auth.module.ts

Основные эндпоинты

POST   /api/auth/sign-up      # Регистрация
POST   /api/auth/sign-in      # Вход
GET    /api/auth/me            # Профиль текущего пользователя
PATCH  /api/auth/me            # Обновление профиля

JWT Strategy

  1. Пользователь отправляет credentials (email + password)
  2. Сервер проверяет и возвращает JWT токен
  3. Клиент отправляет токен в заголовке Authorization: Bearer <token>
  4. JWT Guard проверяет токен и добавляет пользователя в request

Users Module

Путь: src/app/users/

Управление пользователями приложения.

Структура

users/
├── entities/
│   └── user.entity.ts
├── interfaces/
│   └── user.interface.ts
├── services/
│   └── users.service.ts
└── users.module.ts

User Entity

typescript
@Entity("users")
export class UserEntity extends BaseEntity implements IUser {
	@Column()
	email: string;

	@Column()
	password: string;

	@Column({ name: "verification_status" })
	verificationStatus: string;
}

Users Service

CRUD операции с пользователями:

  • findMany() - поиск множества пользователей с пагинацией
  • findOne() - поиск одного пользователя
  • create() - создание пользователя
  • update() - обновление пользователя
  • delete() - удаление пользователя

Access Tokens Module

Путь: src/app/auth/access-tokens/

Управление токенами доступа пользователей для аутентификации API запросов.

Структура

access-tokens/
├── controllers/
│   ├── access-token.controller.ts
│   └── index.ts
├── dtos/
│   ├── create-access-token.dto.ts
│   └── index.ts
├── entities/
│   ├── access-token.entity.ts
│   └── index.ts
├── services/
│   ├── access-token.service.ts
│   └── index.ts
└── access-tokens.module.ts

Основные эндпоинты

POST   /api/access-tokens           # Создать токен доступа
GET    /api/access-tokens           # Получить все токены пользователя
DELETE /api/access-tokens/:tokenId  # Отозвать токен

Access Token Entity

typescript
@Entity("access_tokens")
export class AccessToken extends BaseEntity implements IAccessToken {
	@Column()
	userId: string;

	@ManyToOne(() => UserEntity, { onDelete: "CASCADE" })
	user: UserEntity;

	@Column()
	token: string;

	@Column({ nullable: true })
	name?: string;

	@Column({ nullable: true })
	expiresAt?: Date;

	@Column({ nullable: true })
	lastUsedAt?: Date;
}

Access Token Service

Управление токенами:

  • create() - создание нового токена доступа
  • findByToken() - поиск по значению токена
  • findAllByUserId() - получение всех токенов пользователя
  • updateLastUsed() - обновление времени последнего использования
  • revoke() - отзыв токена
  • revokeAll() - отзыв всех токенов пользователя

Integrations Module

Путь: src/app/integrations/

REST API для управления интеграциями и handlers. Для управления секретами используйте Secrets Module.

Структура

integrations/
├── controllers/
│   ├── integrations.controller.ts
│   └── index.ts
├── dtos/
│   ├── create-handler.dto.ts
│   ├── handler-response.dto.ts
│   └── index.ts
├── entities/
│   ├── integration.entity.ts
│   ├── integration-handler.entity.ts
│   └── index.ts
├── services/
│   ├── handlers.service.ts
│   ├── integrations.service.ts
│   └── index.ts
└── integrations.module.ts

Основные эндпоинты

GET    /api/integrations                                # Список интеграций пользователя
POST   /api/integrations                                # Создать интеграцию
GET    /api/integrations/:id                            # Получить интеграцию
PATCH  /api/integrations/:id                            # Обновить интеграцию
DELETE /api/integrations/:id                            # Удалить интеграцию

# Handlers API (прямые пути без вложенности)
GET    /api/handlers?integrationId=xxx                                     # Список handlers
GET    /api/handlers/:id                                                   # Получить handler
POST   /api/handlers                                                       # Создать handler (integrationId в body)
POST   /api/handlers/:id/invoke                                            # Вызвать handler
DELETE /api/handlers/:id                                                   # Удалить handler

Entities

IntegrationEntity

typescript
@Entity("integrations")
export class IntegrationEntity {
	@PrimaryGeneratedColumn("uuid")
	id: string;

	@Column()
	name: string;

	@Column({ name: "owner_id" })
	ownerId: string;

	@CreateDateColumn({ name: "created_at" })
	createdAt: Date;

	@UpdateDateColumn({ name: "updated_at" })
	updatedAt: Date;
}

IntegrationHandler

Определяет обработчики и их default arguments для интеграций.

Services

IntegrationsService

Управление интеграциями:

  • findByOwnerId() - интеграции пользователя
  • findById() - получить интеграцию по ID
  • create() - создать новую интеграцию
  • update() - обновить интеграцию
  • delete() - удалить интеграцию

HandlersService

Управление handlers (обработчики):

  • getHandlers() - получить все handlers
  • create() - создать handler
  • findOne() - получить handler по ID
  • update() - обновить handler
  • delete() - удалить handler
  • invokeHandler() - вызвать handler с аргументами

Testing Module

Шлях: src/app/testing/

Автоматизоване тестування AI-агентів через LLM-діалоги з оцінкою якості. Один шлях виконання: TextDialogRunner (Tester LLM vs Agent LLM) → EvaluatorService (LLM-оцінка 0-100).

Архітектура

TestPersona (профіль дзвінка)

TextDialogRunner (Tester LLM ↔ Agent LLM, до 10 реплік)

EvaluatorService (LLM-оцінка: 5 критеріїв, 0-100 балів)

TestResult (score, evaluation, transcript)
  • TestPersona — описує поведінку дзвінка (persona, goal, constraints, tags)
  • TestRun — запуск набору персон проти агента інтеграції
  • TestResult — результат кожної персони (score, evaluation, transcript)
  • TestSchedule — cron-розклад автоматичних запусків

Структура

testing/
├── constants/
│   └── testing.constant.ts
├── controllers/
│   ├── test-personas.controller.ts        # CRUD персон + AI-генерація
│   ├── test-runs.controller.ts            # Запуски + Quick Test + Cancel + Delete
│   └── test-schedules.controller.ts       # CRUD розкладів + Toggle
├── dtos/
│   ├── create-test-persona.dto.ts
│   ├── update-test-persona.dto.ts
│   ├── test-personas-query.dto.ts
│   ├── create-test-run.dto.ts
│   ├── test-runs-query.dto.ts
│   ├── create-test-schedule.dto.ts
│   ├── update-test-schedule.dto.ts
│   ├── test-schedules-query.dto.ts
│   ├── generate-personas.dto.ts
│   └── example-message.dto.ts
├── entities/
│   ├── test-persona.entity.ts             # ManyToOne → Integration, User
│   ├── test-run.entity.ts                 # ManyToOne → Integration, User
│   ├── test-result.entity.ts              # ManyToOne → TestRun, TestPersona
│   └── test-schedule.entity.ts            # ManyToOne → Integration, User
├── enums/
│   └── test-status.enum.ts               # TestStatusEnum, TestRunStatusEnum, TestRunTriggerEnum
├── interfaces/
│   ├── evaluate-params.interface.ts
│   ├── evaluation.interface.ts            # IEvaluation, ICriteriaResult
│   ├── generate-suite.interface.ts
│   ├── runner.interface.ts                # IRunnerContext, IRunnerResult
│   ├── test-execution-event.interface.ts
│   ├── test-persona.interface.ts          # ITestPersona, IExampleMessage
│   ├── test-result.interface.ts
│   ├── test-run.interface.ts              # ITestRun, ICreateTestRunParams, IExecuteRunParams
│   └── test-schedule.interface.ts
├── runners/
│   ├── base-runner.ts                     # buildTesterPrompt(persona)
│   └── text-dialog-runner.ts              # run(agentPrompt, persona, context)
├── services/
│   ├── test-personas.service.ts           # CRUD персон
│   ├── test-runs.service.ts               # CRUD запусків + startRun + quickRun
│   ├── test-runner.service.ts             # executeRun (promisePool, concurrency=3)
│   ├── test-execution.listener.ts         # @OnEvent handler + AbortController
│   ├── test-schedules.service.ts          # CRUD розкладів
│   ├── test-scheduler.service.ts          # Cron-джоби (SchedulerRegistry)
│   ├── evaluator.service.ts               # LLM-оцінка транскрипту
│   └── test-generator.service.ts          # AI-генерація персон з agentPrompt
├── swagger/
│   └── testing-decorators.swagger.ts
├── chats/                                 # Інтерактивне тестування через чат
│   ├── controllers/
│   ├── entities/
│   ├── dtos/
│   └── services/
└── testing.module.ts

Основні ендпоінти

# Personas (Персони — профілі дзвінків)
GET    /api/testing/personas               # Список персон
POST   /api/testing/personas               # Створити персону
GET    /api/testing/personas/:id           # Отримати персону
PATCH  /api/testing/personas/:id           # Оновити персону
DELETE /api/testing/personas/:id           # Видалити персону
POST   /api/testing/personas/generate      # AI-генерація персон

# Runs (Запуски тестів)
GET    /api/testing/runs                   # Список запусків
POST   /api/testing/runs                   # Запустити тести (personaIds?, scoreThreshold?)
POST   /api/testing/runs/quick             # Quick Test (автогенерація + запуск)
GET    /api/testing/runs/:id               # Отримати запуск
GET    /api/testing/runs/:id/results       # Детальні результати з транскриптами
POST   /api/testing/runs/:id/cancel        # Скасувати запуск
DELETE /api/testing/runs/:id               # Видалити запуск

# Schedules (Розклади)
GET    /api/testing/schedules              # Список розкладів
POST   /api/testing/schedules              # Створити розклад
PATCH  /api/testing/schedules/:id          # Оновити розклад
DELETE /api/testing/schedules/:id          # Видалити розклад
POST   /api/testing/schedules/:id/toggle   # Увімкнути/вимкнути

# Chats (Інтерактивне тестування)
POST   /api/integrations/:id/chats         # Створити чат
GET    /api/integrations/:id/chats         # Список чатів
GET    /api/chats/:chatId                  # Отримати чат
DELETE /api/chats/:chatId                  # Видалити чат
GET    /api/chats/:chatId/messages         # Повідомлення
POST   /api/chats/:chatId/messages         # Надіслати повідомлення

TestGeneratorService

AI-генерація персон з agentPrompt інтеграції через LlmService. Аналізує конфігурацію агента (name, prompt, language, tools, firstMessage) і генерує 5-8 різноманітних персон. Дедуплікація за іменем.

EvaluatorService

LLM-оцінка завершених діалогів. Критерії: Goal Achievement, Persona Handling, Tone & Professionalism, Information Accuracy, Conversation Flow. Повертає IEvaluation з загальним score (0-100) та breakdown по критеріях.

Залежності

  • IntegrationsModule — зв'язок з інтеграціями (agentPrompt, ownership)
  • LlmModule — LLM-провайдер (Groq/Claude) для діалогів та оцінки
  • @nestjs/schedule — cron-розклади

MCP Module

Путь: src/app/shared/modules/mcp/

Model Context Protocol интеграция для AI взаимодействия с интеграциями.

Структура

shared/modules/mcp/
├── controllers/
│   └── mcp.controller.ts
├── interfaces/
│   └── mcp.interface.ts
├── services/
│   └── mcp.service.ts
├── tools/
│   ├── index.ts
│   └── integrations.tools.ts
└── mcp.module.ts

Назначение

  • Предоставление инструментов для AI моделей
  • Интеграция с Model Context Protocol
  • Tools для работы с интеграциями через IntegrationsService

Взаимодействие

MCP Module импортирует IntegrationsModule и предоставляет access к функциям управления интеграциями через MCP tools.

Health Module

Путь: src/app/shared/modules/health/

Health check endpoint для мониторинга приложения.

Структура

shared/modules/health/
├── controllers/
│   ├── health.controller.ts
│   └── index.ts
└── health.module.ts

Эндпоинт

GET /health   # Проверка здоровья приложения

Диаграмма взаимодействия модулей

mermaid
graph TB
    subgraph HighLevel [Высокоуровневые API]
        Integrations["Integrations Module<br/>/api/integrations"]
        Inngest["Inngest Module<br/>/api/inngest"]
        Testing["Testing Module<br/>/api/testing"]
    end

    subgraph IntegCore [integ-core Прокси API]
        Secrets["Secrets Module<br/>/api/core/secrets"]
        Cache["Cache Module<br/>/api/core/cache"]
        D1API["D1 Module<br/>/api/core/d1"]
        KVAPI["KV Module<br/>/api/core/kv"]
    end

    subgraph Core_Auth [Core & Auth]
        Auth["Auth Module"]
        Users["Users Module"]
        AccessTokens["Access Tokens Module"]
        Core["Core Module"]
    end

    subgraph Shared_Global [Shared Global Modules]
        Crypto["Crypto (@Global)"]
        Logger["Logger (@Global)"]
    end

    subgraph Storage [Storage]
        PostgreSQL["PostgreSQL<br/>TypeORM"]
        D1["Cloudflare D1<br/>(integ-creds, integ-data)"]
        KV["Cloudflare KV<br/>(CACHE)"]
    end

    subgraph ThirdParties [Third Parties]
        CF["Cloudflare API"]
        Inngest_Service["Inngest Service"]
        Miniflare["Miniflare"]
        LLM["LLM Provider (Groq/Claude)"]
    end

    Auth -->|JWT| Users
    AccessTokens -->|userId| Users

    Integrations -->|ownerId| Users
    Integrations -->|Handlers| PostgreSQL
    Inngest -->|URLs| Inngest_Service

    Testing -->|integrationId| Integrations
    Testing -->|Tester+Agent+Evaluator| LLM
    Testing -->|Results| PostgreSQL

    Secrets -->|Query| D1
    Cache -->|KV ops| KV

    D1API -->|Raw SQL| D1
    KVAPI -->|Raw ops| KV

    Secrets -->|Encrypt/Decrypt| Crypto
    Integrations -->|Encrypt| Crypto
    AccessTokens -->|Encrypt| Crypto

    Secrets -->|Log| Logger
    Integrations -->|Log| Logger
    D1API -->|Log| Logger
    KVAPI -->|Log| Logger

    D1API -->|API calls| CF
    KVAPI -->|API calls| CF

    Core -->|Config| PostgreSQL
    Core -->|Init| Crypto
    Core -->|Init| Logger

    style Crypto fill:#90EE90
    style Logger fill:#90EE90
    style Core fill:#FFB6C1
    style HighLevel fill:#87CEEB
    style LowLevel fill:#FFA500

Глобальные модули

@Global() Модули

Эти модули доступны во всём приложении без дополнительных импортов:

  • Crypto Module - Шифрование/дешифрование
  • Logger Module - Логирование

Локальные модули

Эти модули импортируются только где они нужны:

  • Health Module - Импортируется в AppModule
  • Swagger Module - Используется через utils в main.ts

Принципы организации

Глобальность

Только критически важные модули должны быть глобальными:

typescript
// ✅ @Global() - Используется везде
@Global()
@Module({
	providers: [LoggerService],
	exports: [LoggerService]
})
export class LoggerModule {}

// ✅ @Global() - Нужен для шифрования данных
@Global()
@Module({
	providers: [CryptoService],
	exports: [CryptoService]
})
export class CryptoModule {}

// ❌ Не глобальный - импортируется явно
@Module({
	imports: [HealthModule],
	...
})
export class AppModule {}

Принципы межмодульного взаимодействия

✅ Правильно

typescript
// Использование сервиса другого модуля
@Injectable()
export class IntegrationsService {
	constructor(
		private readonly _usersService: UsersService,
		private readonly _gatewayService: GatewayService
	) {}

	async getIntegrations(userId: string) {
		const user = await this._usersService.findOne({ where: { id: userId } });
		if (!user) return null;

		return this._gatewayService.listIntegrations();
	}
}

❌ Неправильно

typescript
// НИКОГДА не обращаемся к repository другого модуля напрямую!
@Injectable()
export class IntegrationsService {
	constructor(
		@InjectRepository(UserEntity)
		private readonly _userRepo: Repository<UserEntity> // ❌ Плохо!
	) {}
}

Следующие шаги