Skip to content

Первоначальная настройка

Эти шаги выполняются один раз при первоначальной настройке проекта. Для быстрого старта см. Quick Start


Архитектура платформы

Интеграционная платформа состоит из 3 проектов:

ПроектОписаниеХостинг
integ-coreМонорепозиторий с пакетами, интеграциями и GatewayCloudflare Workers
integ-apiAPI прокси: авторизация, MCP протокол, оркестрацияDigitalOcean VPS
integ-adminAdmin UI для управления интеграциямиDigitalOcean VPS
┌─────────────┐     ┌─────────────┐     ┌─────────────────────┐
│ integ-admin │────►│  integ-api  │────►│     integ-core      │
│   (UI)      │     │  (Proxy)    │     │   (Workers)         │
│   VPS       │     │   VPS       │     │   Cloudflare Edge   │
└─────────────┘     └─────────────┘     └─────────────────────┘

Этот документ описывает настройку integ-core. Для настройки integ-api и integ-admin см. документацию в соответствующих репозиториях.


Обзор integ-core

Этот документ описывает одноразовую настройку инфраструктуры:

  1. Cloudflare Account и Workers
  2. D1 базы данных
  3. KV хранилища
  4. Doppler проект
  5. CI/CD (GitHub Actions)
  6. ACCESS_TOKEN для авторизации

1. Cloudflare Setup

1.1 Создать Cloudflare Account

  1. Зарегистрироваться на cloudflare.com
  2. Настроить домен happ.tools
  3. Получить API Token с правами Workers/D1/KV

1.2 Установить Wrangler CLI

bash
npm install -g wrangler
wrangler login

1.3 Создать D1 базы данных

Создаём 2 отдельные базы для dev и prod окружений:

bash
# База для DEV окружения
wrangler d1 create integ-db-dev

# База для PROD окружения
wrangler d1 create integ-db-prod

Сохранить database_id из вывода каждой команды:

✅ Successfully created DB 'integ-db-dev'
database_id = "xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx"

✅ Successfully created DB 'integ-db-prod'
database_id = "yyyyyyyy-yyyy-yyyy-yyyy-yyyyyyyyyyyy"

1.4 Миграции

Миграции (включая создание таблицы creds) применяются автоматически при вызове POST /{integration}/setup. SQL-файлы и ручные команды wrangler d1 execute / wrangler d1 migrations apply не используются.

Все миграции (глобальные и integration-specific) являются code-based и управляются через @happ-integ/core.

1.5 Указать ID баз для dev/prod

ID баз указываются в wrangler.toml.tpl или CI/CD pipeline (не в Doppler):

toml
# templates/base/wrangler.toml.tpl или integrations/*/wrangler.toml.tpl
[[d1_databases]]
binding = "INTEG_DB"
database_name = "integ-db"
database_id = "{{D1_DB_ID}}"  # Для CI/CD можно заменить на реальный ID

Локальная разработка: При запуске pnpm start <integration> скрипт generate:env local автоматически подставляет placeholder ID. SQLite база создаётся в data/miniflare/.

1.6 Создать KV Namespaces

Создаём 2 отдельных namespace для dev и prod окружений:

bash
# KV для DEV окружения
wrangler kv namespace create integ-kv-dev

# KV для PROD окружения
wrangler kv namespace create integ-kv-prod

Сохранить id из вывода каждой команды:

🌀 Creating namespace with title "integ-kv-dev"
✨ Success!
[[kv_namespaces]]
binding = "INTEG_KV"
id = "xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx"

🌀 Creating namespace with title "integ-kv-prod"
✨ Success!
[[kv_namespaces]]
binding = "INTEG_KV"
id = "yyyyyyyy-yyyy-yyyy-yyyy-yyyyyyyyyyyy"

1.7 Обновить wrangler.toml.tpl

Для dev/prod добавьте реальные ID в wrangler.toml.tpl:

toml
name = "integ-[NAME]"
main = "dist/worker.js"
compatibility_date = "2024-01-01"

# Для локальной разработки
[[d1_databases]]
binding = "INTEG_DB"
database_name = "integ-db"
database_id = "00000000-0000-0000-0000-000000000001"

[[kv_namespaces]]
binding = "INTEG_KV"
id = "00000000000000000000000000000002"
preview_id = "00000000000000000000000000000002"

# DEV окружение
[env.dev]
name = "integ-[NAME]-dev"

[[env.dev.d1_databases]]
binding = "INTEG_DB"
database_name = "integ-db-dev"
database_id = "РЕАЛЬНЫЙ-UUID-DEV-БАЗЫ"  # ← из wrangler d1 create integ-db-dev

[[env.dev.kv_namespaces]]
binding = "INTEG_KV"
id = "РЕАЛЬНЫЙ-UUID-DEV-KV"  # ← из wrangler kv namespace create integ-kv-dev

# PRODUCTION окружение
[env.production]
name = "integ-[NAME]"

[[env.production.d1_databases]]
binding = "INTEG_DB"
database_name = "integ-db-prod"
database_id = "РЕАЛЬНЫЙ-UUID-PROD-БАЗЫ"  # ← из wrangler d1 create integ-db-prod

[[env.production.kv_namespaces]]
binding = "INTEG_KV"
id = "РЕАЛЬНЫЙ-UUID-PROD-KV"  # ← из wrangler kv namespace create integ-kv-prod

💡 Для локальной разработки: ID 00000000-0000-0000-0000-000000000001 (D1) и 00000000000000000000000000000002 (KV) используются для local dev — Miniflare создаёт локальные SQLite/KV в data/miniflare/.

NAME — плейсхолдер, заменяется на имя интеграции при генерации.

Примечание: Routes не используются — интеграции вызываются через Gateway по Service Bindings. Публичные домены настраиваются только для Gateway через Custom Domains.

Проверка

После выполнения всех шагов Cloudflare Setup, проверить что всё работает:

bash
# Проверить авторизацию Wrangler
wrangler whoami

# Проверить D1 базы
wrangler d1 list

# Проверить KV namespaces
wrangler kv namespace list

# Проверить что таблица creds создана
wrangler d1 execute integ-db --command "SELECT name FROM sqlite_master WHERE type='table' AND name='creds'"

Если всё работает, должны увидеть:

  • Ваше имя/аккаунт в wrangler whoami
  • Список баз в wrangler d1 list (integ-db)
  • Список KV namespaces в wrangler kv namespace list
  • Таблица creds в результате SELECT запроса

2. Doppler Setup

2.1 Создать Doppler проект

  1. Зарегистрироваться на doppler.com
  2. Создать проект integ-core
  3. Создать environments: local, dev, prod

2.2 Настроить секреты

Добавить в каждый environment:

  • CRYPTO_KEY — Ключ для шифрования credentials в D1
  • CRYPTO_SALT — Соль для шифрования
  • OPENAI_API_KEY — API ключ OpenAI
  • GROQ_API_KEY — API ключ Groq
  • QDRANT_URL — URL Qdrant кластера
  • QDRANT_API_KEY — API ключ Qdrant

2.3 Сгенерировать CRYPTO_KEY и CRYPTO_SALT

bash
# Сгенерировать 32-байтный ключ
openssl rand -base64 32

# Сгенерировать соль (16+ символов)
openssl rand -base64 24

2.4 Создать doppler.yaml

yaml
# doppler.yaml (уже в репозитории)
setup:
  project: integ-core
  config: local

Проверка

После выполнения всех шагов Doppler Setup:

bash
# Проверить что Doppler настроен
doppler configs

# Проверить список секретов в dev
doppler secrets --config dev

# Проверить список секретов в prod
doppler secrets --config prod

# Проверить конкретный секрет (должен вернуть значение)
doppler secrets get CRYPTO_KEY --config dev

Если всё работает:

  • doppler configs покажет доступные configs (local, dev, prod)
  • doppler secrets покажет список всех секретов в конфиге
  • doppler secrets get вернёт значение конкретного секрета (не будет ошибки)

3. CI/CD Setup (GitHub Actions)

3.1 Добавить GitHub Secrets

В настройках репозитория (Settings → Secrets → Actions):

  • CLOUDFLARE_WORKERS_API_TOKEN — API Token для Workers (D1, KV, deploy)
  • CLOUDFLARE_PAGES_API_TOKEN — API Token для Pages (документация)
  • CLOUDFLARE_ACCOUNT_ID — ID аккаунта Cloudflare
  • DEV_DOPPLER_TOKEN — Doppler Service Token для dev
  • PROD_DOPPLER_TOKEN — Doppler Service Token для prod

3.2 Деплой с Turborepo Cache

Деплой происходит автоматически через Turbo cache. Turbo сам определяет, какие пакеты изменились, и деплоит только их.

Как работает:

  • Push в dev → Turbo проверяет кэш → деплоит только изменённые пакеты
  • Push в main → Turbo проверяет кэш → деплоит только изменённые пакеты

Примеры:

  • Изменили integrations/sofa/ → деплоится только sofa (gateway из кэша)
  • Изменили packages/llm/ → деплоятся все интеграции зависящие от llm
  • Изменили workers/gateway/ → деплоится только gateway

Workflows:

  • .github/workflows/deploy-to-dev.yml — деплой в dev при push в dev
  • .github/workflows/deploy-to-prod.yml — деплой в prod при push в main

Порядок деплоя:

  1. Checkout code
  2. Restore Turbo cache (actions/cache)
  3. Build all packages (turbo build)
  4. Deploy all (turbo deploy:dev --filter='./integrations/*' --filter='integ-gateway')
  5. Health check
  6. Verify deployment

Проверка

После добавления GitHub Secrets, проверить через GitHub UI:

  1. Перейти в репозиторий → Settings → Secrets and variables → Actions
  2. Должны быть видны 4 секрета
  3. Проверить что workflow работает:
    • Сделать push в ветку dev или main (с изменением в integrations/ или packages/)
    • Перейти в репозиторий → Actions
    • Должен запуститься workflow "Deploy to Dev" или "Deploy to Prod"
    • Если workflow зелёный ✅ — всё настроено правильно

4. DNS и Custom Domains

4.1 Архитектура Gateway

Проект использует Gateway Worker как единую точку входа:

                        integ.happ.tools/*


                    ┌───────────────────────┐
                    │    integ-gateway      │
                    │   ─────────────────   │
                    │   • Auth (x-access)   │
                    │   • Rate limiting     │
                    │   • Trace ID          │
                    │   • Routing           │
                    └───────────┬───────────┘

                Service Bindings (внутренние вызовы)

          ┌─────────────────────┼─────────────────────┐
          ▼                     ▼                     ▼
   ┌────────────┐        ┌────────────┐        ┌────────────┐
   │ integ-sofa │        │ integ-prom │        │    ...     │
   └────────────┘        └────────────┘        └────────────┘

Домены:

  • integ.happ.tools → Gateway (prod)
  • integ.dev.happ.tools → Gateway (dev)

URL структура:

  • /health — health check gateway
  • /sofa/* → Worker integ-sofa
  • /prom/* → Worker integ-prom

4.2 Добавить домен в Cloudflare

  1. Перейти в Cloudflare Dashboard
  2. Add a site → ввести happ.tools
  3. Выбрать план (Free подойдёт)
  4. Изменить nameservers у регистратора домена на те, что показал Cloudflare

4.3 Custom Domains для Gateway (ВАЖНО!)

⚠️ Этот шаг выполняется вручную после первого деплоя Gateway!

Проект использует Custom Domains (не Routes) для подключения доменов к Gateway Worker. Custom Domains — рекомендуемый способ от Cloudflare:

СпособDNSSSLРекомендация
Routes (старый)ВручнуюВручную❌ Устаревший
Custom DomainsАвтоматическиАвтоматическиРекомендуемый

После первого деплоя Gateway выполнить:

  1. Перейти в Cloudflare Dashboard → Workers & Pages
  2. Выбрать integ-gateway-dev (или integ-gateway)
  3. SettingsDomains & Routes+ AddCustom domain
  4. Ввести домен:
    • Для dev: integ.dev.happ.tools
    • Для prod: integ.happ.tools
  5. Cloudflare автоматически создаст DNS запись и настроит SSL
┌─────────────────────────────────────────────────────────────┐
│  Cloudflare Workers Dashboard                                │
│                                                              │
│  integ-gateway-dev                                          │
│  ├── Settings                                                │
│  │   └── Domains & Routes                                   │
│  │       ├── workers.dev: Inactive                          │
│  │       └── Custom domains:                                │
│  │           └── ✅ integ.dev.happ.tools  ← добавить сюда   │
│  └── ...                                                     │
└─────────────────────────────────────────────────────────────┘

Почему не Routes? Routes требуют ручной настройки DNS и могут конфликтовать с Custom Domains. В wrangler.toml routes не используются — домены настраиваются через Dashboard.

4.4 Service Bindings

Gateway связывается с интеграциями через Service Bindings:

toml
# workers/gateway/wrangler.toml

[[env.production.services]]
binding = "SOFA"
service = "integ-sofa"

[[env.dev.services]]
binding = "SOFA"
service = "integ-sofa-dev"

Интеграции не имеют публичных доменов — вызываются через Gateway по Service Bindings.

ℹ️ При добавлении новой интеграции — см. Quick Start → Создание интеграции

4.5 Деплой

🚀 Деплой происходит автоматически через CI/CD!

См. раздел 4. CI/CD Setup

  • Push в dev branch → Автодеплой интеграций + Gateway в dev
  • Push в main branch → Автодеплой интеграций + Gateway в production

Порядок деплоя в CI/CD:

  1. Сначала деплоятся все интеграции (они должны существовать для Service Bindings)
  2. Потом деплоится Gateway

⚠️ После первого деплоя:

При первом деплое Gateway будет доступен только по *.workers.dev URL. Чтобы он работал на кастомном домене:

  1. Добавить Custom Domain через Cloudflare Dashboard (см. раздел 5.3)
  2. Дождаться активации DNS (1-2 минуты)

4.6 Проверка

bash
# Health check Gateway
curl https://integ.happ.tools/health

# Запрос к интеграции (через Gateway)
curl -H "x-access-token: YOUR_TOKEN" https://integ.happ.tools/sofa/webhook/webinar-call-originate

5. Архитектура секретов

Проект использует два типа секретов:

5.1 Глобальные секреты (Doppler → CF Workers)

Одинаковые для всех интеграций. Хранятся в Doppler, синхронизируются в CF Workers env vars.

Список глобальных секретов:

  • CRYPTO_KEY — ключ для шифрования уникальных секретов
  • CRYPTO_SALT — соль для шифрования
  • DATABASE_URL — Neon PostgreSQL
  • OPENAI_API_KEY — OpenAI API
  • GROQ_API_KEY — Groq API
  • QDRANT_URL — Qdrant cluster URL
  • QDRANT_API_KEY — Qdrant API key

Синхронизация (автоматически при деплое):

bash
# Из директории интеграции:
cd integrations/sofa
pnpm sync-secrets:dev   # dev окружение
pnpm sync-secrets:prod  # production окружение

ℹ️ Синхронизация запускается автоматически при deploy:dev и deploy:prod

5.2 Уникальные секреты (D1 integ-db)

Специфичные для каждой интеграции. Хранятся в D1 зашифрованными (AES-256-GCM).

Примеры:

ИнтеграцияКлючОписание
sofaNETHUNT_API_KEYAPI ключ NetHunt
sofaNETHUNT_EMAILEmail для NetHunt
bookingBOOKING_SECRETСекрет для booking API

Использование в коде:

typescript
import { Creds } from "@happ-integ/creds";

const creds = new Creds({
	d1: env.DB,
	masterKey: env.CRYPTO_KEY,
	salt: env.CRYPTO_SALT,
});

// Получить все секреты интеграции
const secrets = await creds.get<{
	NETHUNT_API_KEY: string;
	NETHUNT_EMAIL: string;
}>("sofa");

console.log(secrets.NETHUNT_API_KEY);

Управление уникальными секретами:

typescript
// Установить секрет (через Admin UI или CLI)
await creds.set("sofa", "NETHUNT_API_KEY", "secret-value");

// Удалить секрет
await creds.delete("sofa", "NETHUNT_API_KEY");

// Список всех ключей интеграции
const keys = await creds.listKeys("sofa");

5.3 Проверка

bash
# Проверить глобальные секреты в CF Workers
cd integrations/sofa
wrangler secret list --env dev

# Должны быть:
# - CRYPTO_KEY
# - CRYPTO_SALT
# - DATABASE_URL
# - OPENAI_API_KEY
# - GROQ_API_KEY

Уникальные секреты проверяются через Admin UI или в коде через creds.listKeys('sofa')


6. ACCESS_TOKEN для Gateway

ACCESS_TOKEN — токен авторизации между integ-api и Gateway Worker. Все запросы к Gateway должны содержать заголовок x-access-token.

6.1 Сгенерировать токен

bash
# Генерация случайного токена (32 байта = 64 hex символа)
openssl rand -hex 32

6.2 Добавить в Doppler

Добавить токен в Doppler → integ-core:

EnvironmentКлючЗначение
devACCESS_TOKENваш_токен_для_dev
prodACCESS_TOKENваш_токен_для_prod

Важно: Используйте разные токены для dev и prod окружений.

6.3 Синхронизировать в Gateway Worker

bash
cd workers/gateway

# Dev
doppler secrets download --config dev --format json --no-file | \
  jq -r '.ACCESS_TOKEN' | \
  wrangler secret put ACCESS_TOKEN --env dev

# Production
doppler secrets download --config prod --format json --no-file | \
  jq -r '.ACCESS_TOKEN' | \
  wrangler secret put ACCESS_TOKEN --env production

Убедитесь, что jq установлен: brew install jq (macOS) или apt install jq (Linux)

6.4 Использование

Все запросы от integ-api к Gateway должны содержать заголовок:

bash
curl -H "x-access-token: ВАШ_ACCESS_TOKEN" \
  https://integ.happ.tools/sofa/webhook/webinar-call-originate

6.5 Проверка

bash
cd workers/gateway

# Проверить что токен добавлен
wrangler secret list --env dev | grep ACCESS_TOKEN
wrangler secret list --env production | grep ACCESS_TOKEN

Примечание: Если ACCESS_TOKEN не настроен, Gateway пропускает авторизацию (удобно для локальной разработки). В production обязательно настройте токен!


7. Logging и Alerting Setup

7.1 Cloudflare Workers Logs

Логирование уже настроено в wrangler.toml каждой интеграции:

toml
[observability.logs]
enabled = true
head_sampling_rate = 1
invocation_logs = true

Параметры:

  • enabled: включить сбор логов
  • head_sampling_rate: 1 = собирать 100% логов (0.1 = 10%, и т.д.)
  • invocation_logs: логировать вызовы workers

Эти логи будут доступны в Cloudflare Dashboard → Workers → Logs.

7.2 Slack Webhook - создание incoming webhook

  1. Перейти в Slack: Browse → поиск "Incoming Webhooks" → откройте приложение
  2. Нажать "Add New Webhook to Workspace"
  3. Выбрать канал для алертов (например #alerts-integ или создать новый)
  4. Нажать "Add Incoming Webhooks Integration"
  5. Скопировать Webhook URL (выглядит как https://hooks.slack.com/services/T.../B.../...)

Сохранить этот URL — он понадобится на следующем шаге.

7.3 Cloudflare Notification Destination

  1. Перейти в Cloudflare Dashboard
  2. Перейти в Notifications (слева в боковом меню)
  3. Выбрать Destinations (вкладка)
  4. Нажать "Create" → выбрать "Webhook"
  5. Заполнить поля:
    • Name: Slack Alerts
    • URL: вставить ваш Slack Webhook URL (из шага 8.2)
    • Secret: оставить пустым (Slack не требует)
  6. Нажать "Save and test" (должна придти тестовая ошибка в Slack)

7.4 Alert Policy - настройка алертов на ошибки Workers

  1. В Notifications выбрать вкладку Alert Policies
  2. Нажать "Create"
  3. Выбрать тип alert: WorkersWorkers Error
  4. Настроить параметры:
    • Alert Name: Workers Error Alert
    • Products: Workers
    • Alert Type: Workers Error
    • Script: выбрать интеграции (или оставить All scripts для всех):
      • integ-sofa-dev + integ-sofa (для Dev и Production)
      • Или оставить All scripts чтобы отслеживать все интеграции
    • Notification Destinations: выбрать созданный Slack Alerts webhook
  5. Нажать "Save"

Результат: При ошибке в Workers автоматически придёт сообщение в Slack.

7.5 Структурированное логирование в коде

В файлах интеграции используйте функции logError() и logInfo() для логирования:

typescript
// В handlers используйте ctx.log из handler context
import { defineHandler } from "@happ-integ/core";

export const myHandler = defineHandler({
	name: "my-handler",
	endpoint: "POST /webhook/my-handler",

	async handler({ payload, ctx }) {
		ctx.log("info", "handler:start", { phone: payload.phone_number });

		try {
			// ... бизнес-логика ...
			ctx.log("info", "handler:success", { phone: payload.phone_number });
			return { success: true };
		} catch (error) {
			ctx.log("error", "handler:error", { error: String(error) });
			return { success: false };
		}
	},
});

Примечание: Логирование через ctx.log() автоматически добавляет traceId, handler, timestamp и другие метаданные. Используйте формат "context:event" для первого аргумента.

7.6 Проверка что алерты работают

  1. Деплой интеграции:
bash
cd integrations/sofa
pnpm build
pnpm deploy:dev
  1. Отправить тестовый запрос с ошибкой:
bash
# Запрос без обязательного параметра (это вызовет ошибку)
curl -X POST https://integ.dev.happ.tools/sofa/webhook/webinar-call-originate \
  -H "x-access-token: YOUR_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{}' # Пусто - вызовет ошибку (phone_number is required)
  1. Проверить логи в Cloudflare Dashboard:

    • Перейти в Workers and Pagesinteg-sofa-devLogs
    • Должны видеть JSON логи с level: "error", контекстом и деталями
  2. Проверить Slack:

    • В канале #alerts-integ должно появиться сообщение об ошибке

7.7 Просмотр логов по трассе

Каждый запрос имеет traceId для отслеживания через все сервисы:

bash
# В логах вы увидите:
{
  "level": "error",
  "context": "webhook",
  "traceId": "550e8400-e29b-41d4-a716-446655440000",
  "message": "Request failed",
  "timestamp": "2024-01-01T12:00:00Z",
  "action": "init"
}

Используйте этот traceId для поиска всех логов этого запроса:

  1. Cloudflare Dashboard → Workers → Logs
  2. В поле поиска введите: 550e8400-e29b-41d4-a716-446655440000
  3. Должны увидеть все логи этого запроса во всех сервисах

Проверка

После выполнения всех шагов Setup:

bash
# Проверить что интеграция деплоена
wrangler deployments list --name integ-sofa-dev

# Проверить что Slack webhook работает
# (должны видеть сообщение "Test message" в Slack)

# Проверить что Alert Policy создана
# Cloudflare Dashboard → Notifications → Alert Policies
# Должна быть `Workers Error Alert` в списке

Чеклист готовности

  • [ ] Cloudflare account настроен
  • [ ] D1 база создана (integ-db)
  • [ ] Миграции применены
  • [ ] KV namespace создан
  • [ ] wrangler.toml обновлён с реальными ID
  • [ ] Doppler проект создан с 3 environments
  • [ ] Секреты добавлены в Doppler
  • [ ] GitHub Secrets добавлены
  • [ ] Секреты синхронизированы в CF Workers
  • [ ] ACCESS_TOKEN добавлен в Gateway Worker
  • [ ] Logging и Alerting настроены:
    • [ ] Slack Incoming Webhook создан
    • [ ] Cloudflare Notification Destination добавлена
    • [ ] Alert Policy для Workers Errors создана
  • [ ] Custom Domains настроены для Gateway (после первого деплоя):
    • [ ] integ.dev.happ.toolsinteg-gateway-dev
    • [ ] integ.happ.toolsinteg-gateway

Финальная проверка

Детальные проверки каждого компонента уже описаны в соответствующих разделах. Эта секция для быстрой общей проверки что всё работает вместе.

Быстрая проверка перед началом работы:

bash
# 1. Doppler работает
doppler secrets --config dev

# 2. Wrangler авторизован в Cloudflare
wrangler whoami

# 3. D1 база доступна и содержит таблицу credentials
wrangler d1 execute integ-db --command "SELECT 1"

# 4. KV доступен
wrangler kv namespace list

Если все команды выполнены успешно — инфраструктура готова к использованию!


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

После выполнения этих шагов:

  1. ✅ Можно приступать к работе по Quick Start
  2. ✅ Деплой через CI/CD работает автоматически
  3. ✅ Новые интеграции создаются через pnpm generate:integration