Skip to content

Configuração

O servidor é configurado via variáveis de ambiente. Todas são opcionais — os defaults permitem rodar em modo desenvolvimento sem configurar nada.

Variáveis de ambiente

Servidor

VariávelTipoDefaultDescrição
PORTint8080Porta de escuta
HOSTstring0.0.0.0Endereço de bind
CORS_ORIGINSstring*Origens permitidas (separadas por vírgula)

Armazenamento

VariávelTipoDefaultDescrição
STORAGE_BACKENDstringmemorymemory, sqlite ou postgres
DATABASE_URLstringCaminho do SQLite ou URI do Postgres

Autenticação

VariávelTipoDefaultDescrição
AUTH_SECRETstringSegredo HMAC-SHA256 para tokens. Se omitido, auth fica desabilitado
ACCESS_TOKEN_LIFETIMEint (segundos)900TTL do access token (clamped: 60–3600s)
REFRESH_TOKEN_LIFETIMEint (segundos)604800TTL do refresh token (7 dias)
REFRESH_FAMILY_MAX_LIFETIMEint (segundos)2592000Lifetime absoluto da família de refresh (30 dias)
TOKEN_STORE_PATHstringCaminho do arquivo JSON para persistir tokens. Se omitido, usa store in-memory

Rate Limiting

VariávelTipoDefaultDescrição
RATE_LIMIT1 ou truefalseHabilita rate limiting
RATE_LIMIT_READint120Máximo de leituras por minuto por IP
RATE_LIMIT_WRITEint60Máximo de escritas por minuto por IP
RATE_LIMIT_GENERATEint20Máximo de gerações por minuto por IP

Segurança

VariávelTipoDefaultDescrição
ALLOWED_HOSTSstringHosts permitidos para SSRF guard (separados por vírgula)
ENCRYPTION_KEYstring (base64)Chave AES-256-GCM para criptografia de conexões e assinatura de relatórios
ENCRYPTION_KEY_PREVstring (base64)Chave anterior para rotação transparente
MAX_OUTPUT_SIZEint (bytes)209715200Tamanho máximo do output (200 MB, clamped: 1 KB–2 GB)

Export Policy

VariávelTipoDefaultDescrição
EXPORT_ALLOWED_IDENTITIESstringEmails ou domínios permitidos para exportação verificada (separados por vírgula). Ex: user@example.com,acme.com. Vazio = todos permitidos
EXPORT_PROTECTED_FORMATSstringsulfite,pdfFormatos que exigem verificação OTP (separados por vírgula)
EXPORT_REQUIRE_ALL1 ou truefalseSe true, todos os formatos exigem verificação OTP
EXPORT_OTP_EXPIRATIONint (segundos)300Tempo de expiração do código OTP (5 minutos)
EXPORT_OTP_MAX_ATTEMPTSint3Tentativas máximas antes de invalidar o OTP
EXPORT_OTP_LENGTHint15Comprimento do código OTP alfanumérico

Edit Policy

VariávelTipoDefaultDescrição
EDIT_POLICY_ENABLED1 ou truefalseHabilita a política de edição com OTP
EDIT_ALLOWED_IDENTITIESstringEmails ou domínios autorizados a editar/salvar, separados por vírgula. Vazio = todos permitidos
EDIT_TOKEN_SECRETstringSegredo HMAC para assinar tokens de edição e salvamento. Se omitido, um segredo efêmero é gerado por processo (tokens expiram ao reiniciar)
EDIT_TOKEN_EXPIRATIONint (segundos)3600TTL do token de edição (1 hora)
SAVE_TOKEN_EXPIRATIONint (segundos)300TTL do token de salvamento (5 minutos)
EDIT_OTP_EXPIRATIONint (segundos)300Expiração do código OTP
EDIT_OTP_MAX_ATTEMPTSint3Tentativas máximas antes de invalidar o OTP
EDIT_OTP_LENGTHint6Comprimento do código OTP numérico

Email

O servidor suporta dois providers de email (para share notifications, OTP de exportação e OTP de edição):

VariávelProviderDescrição
RESEND_API_TOKENResendAPI token do Resend
RESEND_FROM_EMAILResendEndereço de envio verificado
RESEND_FROM_NAMEResendNome do remetente (default: Sulfite)
MAILERSEND_API_TOKENMailerSendAPI token do MailerSend
MAILERSEND_FROM_EMAILMailerSendEndereço de envio verificado
MAILERSEND_FROM_NAMEMailerSendNome do remetente (default: Sulfite)

Se nenhum provider for configurado, o servidor usa LogEmailProvider — emails são logados no stdout mas não enviados.

Exemplos de configuração

Desenvolvimento local

bash
# Sem auth, sem persistência — tudo em memória
dart run bin/sulfite_server.dart

Produção com SQLite

bash
export AUTH_SECRET="meu-segredo-longo-e-aleatorio"
export STORAGE_BACKEND=sqlite
export DATABASE_URL=./data/reports.db
export CORS_ORIGINS="https://meuapp.com,https://admin.meuapp.com"
export RATE_LIMIT=true
export TOKEN_STORE_PATH=./data/tokens.json
dart run bin/sulfite_server.dart

Produção com PostgreSQL e criptografia

bash
export AUTH_SECRET="segredo-de-producao"
export STORAGE_BACKEND=postgres
export DATABASE_URL="postgres://user:pass@host:5432/sulfite"
export ENCRYPTION_KEY="base64-encoded-32-byte-key"
export ALLOWED_HOSTS="api.externa.com,supabase.co"
export CORS_ORIGINS="https://app.meudominio.com"
export RATE_LIMIT=true
export RATE_LIMIT_GENERATE=10
export MAX_OUTPUT_SIZE=104857600  # 100 MB
dart run bin/sulfite_server.dart

Docker

dockerfile
FROM dart:stable AS build
WORKDIR /app
COPY packages/sulfite_server/ .
RUN dart pub get
RUN dart compile exe bin/sulfite_server.dart -o server

FROM scratch
COPY --from=build /runtime/ /
COPY --from=build /app/server /app/server
EXPOSE 8080
CMD ["/app/server"]

Fluxo de inicialização

O servidor inicializa os componentes nesta ordem:

  1. ServerConfig — carrega variáveis de ambiente
  2. ReportRepository — cria backend de armazenamento (SQLite, Postgres ou memória)
  3. ConnectionRegistry — registro de conexões (opcionalmente com criptografia AES-256-GCM)
  4. SulfiteEngine — instância do motor de renderização
  5. DataSourceResolversRestDataSourceResolver, PostgresDataSourceResolver, PostgRestDataSourceResolver
  6. SsrfGuard — proteção SSRF (se ALLOWED_HOSTS configurado)
  7. JobQueue — fila de geração assíncrona
  8. RateLimiter — rate limiting por IP (se RATE_LIMIT=true)
  9. TokenStore — store de refresh tokens (persistente ou in-memory)
  10. ReportSigner — assinatura de relatórios (se ENCRYPTION_KEY configurado)
  11. SulfiteServer — monta o app HTTP com middleware pipeline e handlers

Pipeline de middleware

Cada request passa por esta cadeia (nesta ordem):

→ CORS middleware        Valida origens, envia headers CORS
→ Security headers       X-Content-Type-Options, X-Frame-Options, Cache-Control
→ Error middleware        Captura exceções, sanitiza logs
→ Request logger         Loga método, path, status, duração
→ Auth middleware         Valida Bearer/X-API-Key, anexa AuthToken ao request
→ Rate limiter           Limita requests por IP (se habilitado)
→ Handler                Processa a request

Sulfite do 🇧🇷 para o mundo © 2026 Rafael S. Pinheiro