Skip to main content

Runtime Backend

@lowcode/runtime-backend (директория apps/runtime-backend) — это отдельный сервис для безопасного выполнения dataSources в режиме превью. Он нужен, чтобы:

  • выполнять запросы без утечки секретов на клиент;
  • обеспечивать единый контракт ответов для runtime-core;
  • изолировать доступ к внешним системам и preview‑БД.

1. Текущий каркас сервиса

Сервис построен на Fastify и сейчас содержит минимальный функционал:

  • GET /health — проверка доступности сервиса;
  • базовые настройки логирования через LOG_LEVEL;
  • CORS для доступа из browser‑клиентов.

2. Конфигурация окружения

Сервис читает переменные окружения:

  • PORT — порт HTTP‑сервера (по умолчанию 3001);
  • HOST — адрес бинда (по умолчанию 0.0.0.0);
  • LOG_LEVEL — уровень логирования (info по умолчанию).
  • RUNTIME_BACKEND_AUTH_TOKEN — сервисный токен для входящих запросов.
  • RUNTIME_BACKEND_RATE_LIMIT_MAX — лимит запросов за окно (по умолчанию 300).
  • RUNTIME_BACKEND_RATE_LIMIT_WINDOW_MS — окно rate limit (по умолчанию 60000).
  • RUNTIME_BACKEND_REQUEST_TIMEOUT_MS — тайм‑аут запроса (по умолчанию 30000).
  • PREVIEW_ALLOW_DESTRUCTIVE_MIGRATIONS — разрешить разрушительные миграции (по умолчанию false).
  • PREVIEW_APPLY_SEEDS — применять seed‑данные в preview (по умолчанию false).

Пример файла: apps/runtime-backend/.env.example.

Входящая аутентификация (F6)

Модель: service token в заголовке Authorization.

Authorization: Bearer <RUNTIME_BACKEND_AUTH_TOKEN>

Токен проверяется на runtime‑backend (hook onRequest). При отсутствии или неверном токене возвращается 401/403. Это защищает runtime‑backend от прямых внешних вызовов.


3. Docker и запуск

Docker‑артефакты лежат в infra/docker/:

  • infra/docker/Dockerfile.runtime-backend — Dockerfile сервиса;
  • infra/docker/docker-compose.dev.yml — dev‑compose с сервисом runtime-backend-dev.

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

В рамках Epic F будут добавлены:

  • выполнение REST/DB dataSources;
  • интеграция с preview‑DB и secrets;
  • наблюдаемость и тесты.

5. Preview DB

В runtime-backend используется preview‑БД PostgreSQL с изоляцией по schema:

  • для каждого проекта используется tenant‑schema вида preview_<projectId>;
  • projectId нормализуется (slug) перед формированием имени схемы;
  • запросы выполняются только по DSL‑описанию (list/get/create/update/delete).

Для подключения используется DATABASE_URL с доступом к preview‑БД.

Рекомендации по безопасности:

  • используйте отдельного пользователя БД для runtime-backend;
  • выдайте минимальные права только на схемы preview_* (SELECT/INSERT/UPDATE/DELETE);
  • не используйте учётку API или администратора БД.

Preview schema создаётся автоматически при первом DB‑вызове:

  • runtime-backend выполняет CREATE SCHEMA IF NOT EXISTS preview_<projectId>.

После создания схемы runtime-backend применяет миграции из DSL:

  • CREATE TABLE IF NOT EXISTS для таблиц;
  • ALTER TABLE ADD COLUMN IF NOT EXISTS для новых полей;
  • CREATE INDEX IF NOT EXISTS для индексов.

Логи миграций пишутся в таблицу __lowcode_migrations_log внутри tenant‑схемы. Если требуется применять разрушительные операции (например, NOT NULL без default), нужно включить PREVIEW_ALLOW_DESTRUCTIVE_MIGRATIONS=true.

Preview seeds применяются только при включенном флаге:

  • PREVIEW_APPLY_SEEDS=true — применяет DbDataSource.seeds.
  • запись о применении хранится в __lowcode_seeds_log (внутри tenant‑схемы).

Для runtime-host доступен статус миграций:

  • GET /preview/status/:projectId{ status, lastAppliedAt, lastError }.

6. Secrets provider

Runtime-backend получает секреты проекта через API:

  • GET /internal/projects/:projectId/secrets/runtime (service token обязателен);
  • ответ: { secrets: Record<string, string> };
  • используется кэширование по TTL (по умолчанию 60 секунд).

Переменные окружения для доступа к API:

  • API_BASE_URL
  • API_SERVICE_ID
  • API_SERVICE_SECRET

7. Observability

Runtime-backend пишет унифицированные события dataSources и метрики:

  • x-trace-id берётся из заголовка или генерируется;
  • события dataSource.call.* содержат traceId, requestId, durationMs, status;
  • ошибки в логах маскируются от секретов.