Configuração
Simmetric Chat tem dois níveis de configuração: variáveis de ambiente validadas com Zod na inicialização do processo, e uma camada de configuração runtime armazenada no banco de dados que administradores podem editar pela interface sem reiniciar nenhum s…
Simmetric Chat tem dois níveis de configuração: variáveis de ambiente validadas com Zod na inicialização do processo, e uma camada de configuração runtime armazenada no banco de dados que administradores podem editar pela interface sem reiniciar nenhum serviço.
- Variáveis de ambiente (inicialização do processo) - validadas com Zod em
packages/<pkg>/src/config/env.ts;process.exit(1)quando inválidas. - Configuração runtime (DB `SystemConfig`) - editável pela UI de admin sem reinício.
Resolução:
- Chaves
ALWAYS_READONLY(JWT_SECRET,DATABASE_URL,SERVER_PORT,COLLECTOR_PORT,SERVER_URL,COLLECTOR_URL,LICENSE_SECRET):ENV > Default, não editáveis pela UI. - Todas as outras:
DB > ENV > Default, editáveis viaPUT /api/system/settings.
Os três pacotes leem .env via path.resolve(__dirname, "../../.env") (independente do diretório de trabalho). O documento de referência é .env.example na raiz do repositório.
Variáveis de ambiente - server
Schema: packages/server/src/config/env.ts. Defaults exibidos; OBR = obrigatório.
Core / infra
| Variável | Default | Obr. | Descrição |
|---|---|---|---|
NODE_ENV | development | opt | development/production/test |
SERVER_PORT | 3000 | opt | Porta da API do servidor |
COLLECTOR_PORT | 3210 | opt | Porta do collector (para a URL padrão) |
SERVER_URL | http://localhost:3000 | opt | URL pública do servidor |
COLLECTOR_URL | http://localhost:3210 | opt | URL do collector |
WIDGET_SERVICE_URL | http://localhost:3211 | opt | URL do serviço widget (push cache-bust) |
WIDGET_API_KEY | — | opt | Segredo compartilhado do push widget; ausente → cache-bust no-op (TTL 5 min) |
DATABASE_URL | postgresql://simmetricchat:[email protected]:5432/simmetricchat | opt | URL do PostgreSQL |
JWT_SECRET | — | OBR | Segredo JWT |
ENCRYPTION_KEY | — | opt | Base64 de 32 bytes para AES-256-GCM (data-at-rest). Sem valor → fallback scryptSync(JWT_SECRET, salt) |
SESSION_EXPIRY | 86400000 (24h ms) | opt | Expiração do JWT |
ALLOWED_ORIGINS | http://localhost:5173,127.0.0.1:5173,localhost:3000 | opt | Allowlist CORS global (CSV). /api/internal/widget excluído |
LOG_LEVEL | info | opt | debug/info/warn/error |
ALLOW_REGISTRATION | false | opt | Interruptor de auto-registro |
DISABLE_TELEMETRY | true | opt | Desativa telemetria |
Bootstrap admin (seed)
| Variável | Default | Descrição |
|---|---|---|
SEED_BOOTSTRAP_ADMIN | true | Auto-seed do admin no primeiro boot (transform custom: false/0/no/off/"" = desativado) |
SEED_ADMIN_USERNAME | admin | Username do admin bootstrap |
SEED_ADMIN_PASSWORD | admin123 | Senha (min 8); conta mustChangePassword=true |
SEED_ADMIN_EMAIL | [email protected] | Email do admin bootstrap |
LLM
| Variável | Default | Descrição |
|---|---|---|
LLM_PROVIDER | ollama | openai/anthropic/ollama/openrouter |
LLM_MODEL | gemma4:latest | Modelo padrão |
LLM_TEMPERATURE | 0.7 | 0–2 |
LLM_MAX_TOKENS | 4096 | Teto de tokens de conclusão |
LLM_TIMEOUT | 0 | Timeout do Axios em ms (0 = nenhum, para LLMs locais lentos) |
LLM_API_KEY / LLM_API_BASE_URL | — | Overrides genéricos |
OPENAI_API_KEY / OPENAI_MODEL | — | OpenAI |
ANTHROPIC_API_KEY / ANTHROPIC_MODEL | — | Anthropic |
OLLAMA_BASE_URL | http://ollama:11434 | Endpoint do Ollama |
OLLAMA_MODEL / OLLAMA_API_KEY | — | Override do Ollama |
OPENROUTER_API_KEY / OPENROUTER_BASE_URL / OPENROUTER_MODEL | https://openrouter.ai/api / — | OpenRouter |
Watchdog de agente (prevenção de loops/stalls)
| Variável | Default | Descrição |
|---|---|---|
AGENT_WALLCLOCK_TIMEOUT_MS | 600000 (10 min) | Limite superior absoluto para uma requisição ReAct |
AGENT_MAX_TOTAL_TOKENS | 200000 | Total prompt+completion por requisição |
AGENT_MAX_CONTEXT_BYTES | 500000 (500 KB) | Teto do tamanho do array de contexto |
AGENT_MAX_TOOL_OUTPUT_LENGTH | 5000 | Truncamento da saída por skill |
AGENT_MAX_SKILL_EXECUTION_MS | 60000 | Timeout por skill |
AGENT_LOOP_DETECTION_WINDOW | 3 | Abortar após N tool+input idênticos consecutivos |
CHAT_MAX_CONCURRENT_PER_USER | 5 | Limite de concorrência de chats por usuário |
Embedding / Vector DB / OCR / Synthesis
| Variável | Default | Descrição |
|---|---|---|
EMBEDDING_PROVIDER | local | local/openai/ollama |
EMBEDDING_MODEL | Xenova/all-MiniLM-L6-v2 | Modelo de embedding |
EMBEDDING_API_KEY | — | API key de embedding |
VECTOR_DB_PROVIDER | lancedb | lancedb/qdrant |
VECTOR_DB_URL / VECTOR_DB_API_KEY | — | Para Qdrant remoto |
OCR_MODEL | glm-ocr:latest | Modelo de visão OCR (formato model:version) |
OCR_TIMEOUT | 600000 | Timeout de visão OCR |
SYNTHESIS_LLM_MODEL | gemma4:latest | Modelo do pipeline de síntese |
PUPPETEER_EXECUTABLE_PATH | — | Chromium para export PDF de arquivos |
Licença, push, email, collector
| Variável | Default | Descrição |
|---|---|---|
LICENSE_KEY | — | JWT de licença Enterprise (HS256). Ausente → Community |
LICENSE_SECRET | — | Segredo de verificação JWT (recomendado); fallback a LICENSE_KEY |
COLLECTOR_SECRET | — | OBR — segredo compartilhado server↔collector |
VAPID_PUBLIC_KEY / VAPID_PRIVATE_KEY / VAPID_SUBJECT | — | Web Push; sem valor → chaves efêmeras geradas em dev |
SMTP_HOST / SMTP_PORT / SMTP_USER / SMTP_PASS / SMTP_FROM | — | SMTP para reset de senha + notificações de falha de backup |
LEGACY_PREVIOUS_ENCRYPTION_KEYS | — | CSV base64 32 bytes para rotação de chaves |
Variáveis em.env.examplemas gerenciadas como settings DB (não emenvSchema):OCR_ENABLED,OCR_PRECHECK_CHARS,STORAGE_PATH(collector),RESET_PASSWORD_STRATEGY.
Variáveis de ambiente - collector
Schema: packages/collector/src/config/env.ts.
| Variável | Default | Obr. | Descrição |
|---|---|---|---|
COLLECTOR_PORT | 3210 | opt | Porta HTTP |
COLLECTOR_URL | http://localhost:3210 | opt | URL própria |
SERVER_URL | http://localhost:3000 | opt | URL do servidor (callback) |
EMBEDDING_PROVIDER | local | opt | local/openai/ollama |
EMBEDDING_MODEL | — | opt | Modelo de embedding |
EMBEDDING_API_KEY | — | opt | API key |
VECTOR_DB_PROVIDER | lancedb | opt | lancedb/qdrant |
VECTOR_DB_URL / VECTOR_DB_API_KEY | — | opt | Qdrant |
OLLAMA_BASE_URL | http://ollama:11434 | opt | Ollama |
STORAGE_PATH | ./storage | opt | Armazenamento filesystem |
COLLECTOR_SECRET | — | OBR | Deve corresponder ao servidor |
Variáveis de ambiente - widget
Schema: packages/widget/src/config/env.ts.
| Variável | Default | Obr. | Descrição |
|---|---|---|---|
NODE_ENV | development | opt | Ambiente |
WIDGET_PORT | 3211 | opt | Porta HTTP |
SERVER_URL | http://localhost:3000 | opt | URL do servidor |
WIDGET_API_KEY | — | OBR | Segredo compartilhado widget↔server (deve corresponder) |
LOG_LEVEL | info | opt | Nível de log |
Frontend: sem variáveisVITE_*e sem arquivo.env. O frontend lê branding/config do servidor (GET /api/system/settings,GET /api/license/info).
Feature flags e licença
Definidos em packages/shared/src/constants/license.ts (FEATURE_FLAGS + defaults). Verificados em packages/server/src/services/licenseService.ts.
Como passar de Community para Enterprise
- Defina
LICENSE_KEY(JWT HS256) e, recomendado,LICENSE_SECRET. jwt.verify→ payload validado contralicensePayloadSchema(tier,iss,sub,iat,exp,features).tier=enterprise→ parte deENTERPRISE_FEATURE_DEFAULTS+ os overridesfeaturesdo JWT.- Expirada/inválida → fallback Community com aviso.
Graceful degradation: getLicenseInfo() verifica a expiração em runtime; se Enterprise expirar durante o uso, degrada para Community sem reinício. requireFeature(flag) → HTTP 402 quando desabilitado; requireFeatureLimit(flag, model) → 402 quando count >= limit (Enterprise = Infinity).
Flags commodity sempre ativos: desde a remoção EPA-02, os 8 flags commodity não existem mais em FEATURE_FLAGS - webhooks, push_notifications, web search, memory, lead_export, widget_analytics, auto_title, synthesis_rate_limit estão sempre ativos em Community (rotas commodity rodam sem gating). priority_support não é um flag: é um contrato comercial/SLA (EPA-08). Restam 11 flags enterprise, incluindo widget_credits_editing (edição de créditos do widget, Community false / Enterprise true) e custom_agents como limite numérico (Community 3, Enterprise Infinity).
Tabela de flags (11)
| Flag | Tipo | Community | Enterprise | O que gateia |
|---|---|---|---|---|
sso_enabled | bool | false | true | SSO Enterprise |
audit_log_immutable | bool | false | true | Imutabilidade do audit log |
white_label | bool | false | true | Branding BRANDING_* |
max_workspaces | num | 3 | Infinity | Criação de workspaces |
max_projects | num | 3 | Infinity | Criação de projetos |
custom_agents | num | 3 | Infinity | Agentes custom (limite) |
widget_enabled | bool | false | true | Widget incorporável |
max_widgets | num | 1 | Infinity | Criação de widgets |
backup_enabled | bool | false | true | Sistema de backup |
max_backup_destinations | num | 1 | Infinity | Destinos de backup |
widget_credits_editing | bool | false | true | Edição de créditos do widget |
Runtime config (DB SystemConfig)
Editável via GET/PUT /api/system/settings (bulk) e PUT /api/system/chat-retention (específica, auditada). Defaults vivem em CONFIG_DEFAULTS (packages/shared/src/constants/permissions.ts).
Grupos de chaves: LLM (LLM_PROVIDER, LLM_MODEL, LLM_TEMPERATURE, ...), Embedding/Vector, Portas/URLs do servidor, Auth (SESSION_EXPIRY), Branding (BRANDING_APP_NAME, BRANDING_PRIMARY_COLOR, BRANDING_APP_SUBTITLE, BRANDING_APP_ICON_URL - gated white_label), Feature (DISABLE_TELEMETRY, ALLOW_REGISTRATION, DLP_ENABLED), OCR (OCR_DEFAULT_MODEL, OCR_DEFAULT_MODE, OCR_DEFAULT_CUSTOM_INSTRUCTIONS, OCR_ENABLED, OCR_PRECHECK_CHARS), Synthesis (SYNTHESIS_LLM_PROVIDER_ID, SYNTHESIS_LLM_MODEL), Retention (upload_draft_retention_days, ALLOW_NON_ADMIN_UPLOAD, chat_message_retention_days).
PUT /api/system/settings sempre retorna 200 com { updated: [...], rejected: [...] } (chaves readonly são rejeitadas enquanto as demais são aplicadas).
Retenção de mensagens de chat (reaper)
Serviço: packages/server/src/services/chatMessageReaperJob.ts. Knob DB: chat_message_retention_days.
- Pass 1 (soft-delete): tombstones mensagens de chats ATIVOS além de
retentionDays. No-op quando o valor énull/""/<=0. - Pass 2 (hard-purge): exclui linhas tombstonadas além de uma graça de 7 dias (hardcoded). Sempre roda, independentemente da config de retenção (anti-vazamento de PII).
- Cadência:
setIntervalde 24h, primeiro run às 03:00 hora local. MutexisRunning. - Apenas
PUT /api/system/chat-retention(auditada,confirmDataLoss: true,retentionDays: integer|null, min 1); o endpoint bulk rejeita essa chave.
Retenção de backups
Por job (o campo retentionDays em BackupJob, default 30). backupRetentionService.ts limpa logs/arquivos além de cutoffDate. Não é global.
Rotação de chaves de criptografia
packages/server/src/services/encryptionService.ts (AES-256-GCM, chave de 32 bytes, IV de 16 bytes, salt simmetric-chat-encryption-salt).
- Chave atual:
ENCRYPTION_KEY(base64 32 bytes) quando definida; senãoscryptSync(JWT_SECRET, salt, 32). LEGACY_PREVIOUS_ENCRYPTION_KEYS(CSV base64 32 bytes) → cadeia de chaves de descriptografia[current, ...previous, scryptLegacy?].encrypt()usachain[0]. Não há job automático de re-criptografia: o procedimento é manual descriptografar-com-antiga → re-criptografar-com-nova.
Cross-link
- Endpoints de settings: 04 - API Reference
- Recursos internos: 05 - Feature Guide
- Env vars de deploy: 09 - Deployment