Skip to content

Environment Variables / Переменные окружения

Обзор

В проекте используется двухуровневая система секретов:

┌─────────────────────────────────────────────────────────────────────┐
│                         DOPPLER (Уровень 1)                         │
│                      Глобальные секреты                             │
├─────────────────────────────────────────────────────────────────────┤
│  CRYPTO_KEY / CRYPTO_SALT — ключ и соль шифрования для D1           │
│  OPENAI_API_KEY           — API ключи внешних сервисов             │
└─────────────────────────────────────────────────────────────────────┘


┌─────────────────────────────────────────────────────────────────────┐
│                    CLOUDFLARE D1 (Уровень 2)                        │
│                Per-integration секреты и данные                     │
├─────────────────────────────────────────────────────────────────────┤
│  integ-db (binding: INTEG_DB)                                       │
│  ├── creds                — зашифрованные секреты интеграций        │
│  │   ├── sofa/NETHUNT_API_KEY                                       │
│  │   ├── sofa/SAAS_ASSISTANT_ID                                     │
│  │   └── rozetka/CRM_TOKEN                                          │
│  │                                                                   │
│  └── {integration}_*        — данные интеграций (создаются вами)    │
│      ├── sofa_calls                                                  │
│      ├── sofa_leads                                                  │
│      └── rozetka_orders                                              │
└─────────────────────────────────────────────────────────────────────┘


┌─────────────────────────────────────────────────────────────────────┐
│                    CLOUDFLARE KV (Кэш и флаги)                      │
├─────────────────────────────────────────────────────────────────────┤
│  integ-kv (binding: INTEG_KV)                                       │
│  ├── sofa:rate_limit:user123                                        │
│  ├── sofa:cache:lead:456                                            │
│  └── rozetka:feature_flags                                          │
└─────────────────────────────────────────────────────────────────────┘

Когда использовать что?

ХранилищеИспользуй дляПримеры
DopplerГлобальные API ключи, ключи шифрованияOPENAI_API_KEY, CRYPTO_KEY, CRYPTO_SALT
D1 credsСекреты конкретной интеграцииNETHUNT_API_KEY, CRM_TOKEN
D1 {name}_dataПерсистентные данные интеграцииЗвонки, лиды, заказы
KVКэш, rate limiting, feature flagsTTL-based кэш, счётчики

Doppler секреты — полная таблица

Обязательные переменные

ПеременнаяОписаниеГде взять
CRYPTO_KEYКлюч шифрования credentials в D1openssl rand -hex 32
CRYPTO_SALTСоль для шифрования (16+ символов)Любая строка 16+ символов
CLOUDFLARE_INTEG_DB_IDID D1 базы данныхCloudflare Dashboard или placeholder
CLOUDFLARE_INTEG_KV_IDID KV namespaceCloudflare Dashboard или placeholder

💡 Примечание: ID для D1 и KV хранятся в Doppler для каждого окружения. Скрипт generate:env подставляет их в wrangler.toml.

Опциональные переменные

ПеременнаяОписаниеГде взять
DATABASE_URLPostgreSQL connection stringNeon / локальный Postgres
OPENAI_API_KEYAPI ключ OpenAIOpenAI Platform
CLAUDE_API_KEYAPI ключ AnthropicAnthropic Console
GROQ_API_KEYAPI ключ GroqGroq Console
QDRANT_URLURL Qdrant сервераQdrant Cloud
QDRANT_API_KEYAPI ключ QdrantQdrant Cloud
SAAS_API_URLURL SaaS APIapi.dev.happ.tools (dev) / api.happ.tools (prod)
SAAS_ACCESS_TOKENТокен доступа к SaaS APIСгенерированный токен
DEBUGВключить debug логированиеtrue / false

Примеры значений по окружениям

Local (для локальной разработки)

bash
# Cloudflare resource IDs — placeholder для локальной разработки
CLOUDFLARE_INTEG_DB_ID=00000000-0000-0000-0000-000000000001
CLOUDFLARE_INTEG_KV_ID=00000000000000000000000000000002

# Шифрование — ОБЯЗАТЕЛЬНО
CRYPTO_KEY=a75a9de60aeebfc889967594f6aa94cfd745737486a441a83dc51c10928c89a1
CRYPTO_SALT=integ-core

# PostgreSQL (если используется)
DATABASE_URL=postgresql://postgres:postgres@localhost:5432/integ

# Опционально
OPENAI_API_KEY=sk-...
GROQ_API_KEY=gsk_...

💡 D1 и KV: Для локальной разработки wrangler создаёт SQLite базы в data/miniflare/. Placeholder ID используются для генерации правильных имён файлов.

Dev / Prod (Cloudflare)

bash
# Cloudflare resource IDs — реальные ID из Cloudflare Dashboard
CLOUDFLARE_INTEG_DB_ID=<uuid-d1-database>
CLOUDFLARE_INTEG_KV_ID=<uuid-kv-namespace>

# Шифрование — УНИКАЛЬНЫЕ для каждого окружения!
CRYPTO_KEY=<уникальный-ключ-для-окружения>
CRYPTO_SALT=<уникальная-соль-для-окружения>

# PostgreSQL (Neon)
DATABASE_URL=postgres://user:pass@ep-xxx.neon.tech/integ?sslmode=require

# LLM
OPENAI_API_KEY=sk-...

💡 D1/KV для dev/prod: ID ресурсов хранятся в Doppler и подставляются скриптом generate:env.


Создание ресурсов на Cloudflare (dev/prod)

Создание D1 на Cloudflare

  1. Перейдите в Cloudflare DashboardWorkers & PagesD1 SQL Databases
  2. Нажмите Create database
  3. Имя базы: integ-db-dev или integ-db-prod
  4. После создания скопируйте Database ID (UUID)
  5. Укажите ID в wrangler.toml.tpl или CI/CD
bash
# Или через CLI:
wrangler d1 create integ-db-dev
# → Created database 'integ-db-dev' with id: xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx

Применение миграций:

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

bash
# После создания базы и деплоя — вызовите setup для применения миграций
curl -X POST https://integ.dev.happ.tools/sofa/setup

Создание KV на Cloudflare

  1. Перейдите в Cloudflare DashboardWorkers & PagesKV
  2. Нажмите Create a namespace
  3. Имя namespace: integ-kv-dev или integ-kv-prod
  4. После создания скопируйте Namespace ID
  5. Укажите ID в wrangler.toml.tpl или CI/CD
bash
# Или через CLI:
wrangler kv namespace create integ-kv-dev
wrangler kv namespace create integ-kv-prod
# → Created namespace "integ-kv-dev" with id: yyyyyyyy-yyyy-yyyy-yyyy-yyyyyyyyyyyy

Локальная разработка

При локальной разработке (pnpm start <integration>):

  1. D1 база — автоматически создаётся SQLite файл в data/miniflare/
  2. KV — автоматически создаётся SQLite файл в data/miniflare/
  3. Секреты — читаются из .dev.vars (генерируется из Doppler)
bash
# Генерация .dev.vars из Doppler
pnpm generate:env local

# База данных и KV создаются автоматически при первом запуске
pnpm start sofa

Локальные файлы

data/miniflare/v3/
├── d1/miniflare-D1DatabaseObject/
│   └── 7ac1b8d7...sqlite     ← integ-db (SHA256 от placeholder ID)
└── kv/miniflare-KVNamespaceObject/
    └── ...sqlite             ← integ-kv

Хеши файлов:

bash
# D1: placeholder ID
echo -n "00000000-0000-0000-0000-000000000001" | shasum -a 256
# → 7ac1b8d7010bb6cd3a3e84e7f90136b880bbc899e428ece49333372911ab9052

# KV: placeholder ID
echo -n "00000000000000000000000000000002" | shasum -a 256

Важно: Для локальной разработки не нужно создавать базы на Cloudflare — всё работает локально!


Cloudflare Bindings (wrangler.toml)

Важно: wrangler.toml генерируется автоматически из шаблонов в templates/. Не редактируйте его напрямую!

D1 Database

BindingDatabaseОписание
INTEG_DBinteg-dbЕдиная база данных (credentials + данные)
toml
# Генерируется автоматически из templates/wrangler.integration.toml.tpl
[[d1_databases]]
binding = "INTEG_DB"
database_name = "integ-db"
database_id = "{{D1_DB_ID}}"  # Подставляется из CLOUDFLARE_INTEG_DB_ID

KV Namespace

BindingNamespaceОписание
INTEG_KVinteg-kvKV для кэширования
toml
[[kv_namespaces]]
binding = "INTEG_KV"
id = "{{KV_ID}}"  # Подставляется из CLOUDFLARE_INTEG_KV_ID

Структура таблиц в D1

integ-db
├── creds               # Системная таблица (создаётся автоматически)
│   ├── integration_name    # "sofa", "rozetka"
│   ├── key                 # "NETHUNT_API_KEY"
│   └── encrypted_value     # Зашифрованное значение

└── {integration}_{table}   # Таблицы данных (создаёте вы)
    ├── sofa_calls          # Примеры
    ├── sofa_leads
    └── rozetka_orders

Создание таблицы для интеграции:

Все миграции определяются в коде интеграции (в файле конфигурации src/config/migrations.ts) и применяются автоматически при вызове POST /{integration}/setup. SQL-файлы миграций не используются.

typescript
// src/config/migrations.ts — пример миграции для таблицы sofa_calls
export const migrations = [
  {
    name: "create_sofa_calls",
    sql: `CREATE TABLE IF NOT EXISTS sofa_calls (
      id TEXT PRIMARY KEY,
      phone TEXT NOT NULL,
      status TEXT NOT NULL,
      created_at TEXT DEFAULT (datetime('now'))
    )`,
  },
];
bash
# Применить миграции (после деплоя)
curl -X POST https://integ.dev.happ.tools/sofa/setup
curl -X POST https://integ.happ.tools/sofa/setup

Per-integration переменные (D1 creds)

Уникальные переменные для каждой интеграции хранятся зашифрованными в D1.

Добавление секретов через CLI

bash
# Добавить секрет для интеграции sofa
pnpm cli creds set --integration sofa --key NETHUNT_API_KEY --value "your-api-key"

# Просмотреть секреты
pnpm cli creds list --integration sofa

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

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

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

// Получить credentials
const secrets = await creds.get<{
	NETHUNT_EMAIL: string;
	NETHUNT_API_KEY: string;
}>("sofa");

console.log(secrets.NETHUNT_EMAIL);

Примеры использования KV

typescript
// Rate limiting
await env.INTEG_KV.put(`sofa:rate_limit:${userId}`, "1", { expirationTtl: 60 });

// Кэширование
await env.INTEG_KV.put(`sofa:cache:lead:${id}`, JSON.stringify(lead), { expirationTtl: 300 });

// Feature flags
const flags = await env.INTEG_KV.get("sofa:feature_flags", "json");

Конфигурация по окружениям

ОкружениеDoppler ConfigИсточник secrets
Locallocal.dev.vars файлы
DevdevCloudflare Workers Secrets
ProductionprodCloudflare Workers Secrets

Команды

bash
# Генерация .env и wrangler.toml из Doppler
pnpm generate:env local   # для локальной разработки
pnpm generate:env dev     # для dev окружения
pnpm generate:env prod    # для production

# Запуск локально
doppler run -- pnpm dev

# Деплой
pnpm --filter integ-sofa deploy:dev
pnpm --filter integ-sofa deploy:prod

Quick Reference — где что брать

ПеременнаяLocalDev/Prod
CLOUDFLARE_INTEG_DB_IDPlaceholder UUIDCloudflare Dashboard
CLOUDFLARE_INTEG_KV_IDPlaceholder UUIDCloudflare Dashboard
CRYPTO_KEYopenssl rand -hex 32openssl rand -hex 32
CRYPTO_SALTЛюбая строка 16+ символовЛюбая строка 16+ символов
DATABASE_URLpostgresql://...@localhostNeon Console
OPENAI_API_KEYOpenAI PlatformOpenAI Platform
GROQ_API_KEYGroq ConsoleGroq Console

💡 D1/KV ID: Все ID хранятся в Doppler и подставляются скриптом generate:env.


Связанные документы