Skip to content

Secrets & Criptografia

Onde ficam os secrets

Em produção (Azure Key Vault)

Todos os secrets sensíveis ficam no Azure Key Vault. O deploy.sh busca automaticamente antes de fazer build.

O backend usa DefaultAzureCredential para acessar o Key Vault em runtime — sem secrets hardcoded na imagem.

Secrets no Key Vault:

  • CLERK-SECRET-KEY
  • NEXT-PUBLIC-CLERK-PUBLISHABLE-KEY
  • DATABASE-URL
  • MASTER-ENCRYPTION-KEY
  • CLERK-WEBHOOK-SECRET
  • REDIS-PASSWORD
  • Tokens e credenciais de integrações

Em desenvolvimento

Arquivo .env.secrets na raiz do projeto (nunca commitado). Ver /inicio-rapido/variaveis-de-ambiente para a lista completa.

Criptografia de dados sensíveis no banco

Alguns dados são criptografados antes de salvar no banco usando AES-256-GCM (Authenticated Encryption):

MASTER_ENCRYPTION_KEY (env)
  → normalizado para 32 bytes via SHA-256
  → usado para cifrar/decifrar

Formato armazenado: {iv}:{encrypted_content}:{auth_tag}
  iv: 16 bytes aleatórios (hex)
  encrypted: ciphertext AES-256-GCM (hex)
  auth_tag: tag de integridade GCM (hex)

Dados criptografados:

CampoTabela
pass (senha SMTP por loja)Store email config
pass (senha SMTP da org)OrganizationSmtpSettings
token (Evolution/ZAPI)StoreWhatsappNumber
accessToken (Meta Cloud)StoreWhatsappNumber
appSecret (Meta webhook)StoreWhatsappNumber

A API nunca retorna esses valores em texto puro. Sempre retorna '********'. O valor real é descriptografado apenas internamente para enviar mensagens.

Hashing irreversível

CPF

CPF original → normalizar (remover pontos/traços) → SHA-256 → cpfHash

O CPF em texto puro nunca é armazenado. Para busca, o sistema hasheia o CPF fornecido e compara com o hash.

Display: ***.***.*XX-** (campo cpfMasked — gerado no sync).

Tokens de survey

Tokens de pesquisa de satisfação são UUIDs aleatórios. O sistema armazena apenas tokenHash = SHA-256(token) — o token real é enviado ao cliente via URL e nunca fica no banco.

Webhook verify token (Meta WhatsApp)

O webhookVerifyToken é armazenado como SHA-256. Ao verificar um webhook entrante, o sistema hasheia o token recebido e compara.

Masked output de tokens WhatsApp

Ao listar instâncias WhatsApp via API:

  • token: sempre '********'
  • accessToken: sempre '********'
  • appSecret: sempre '********'

Ao criar uma nova instância: o token real é retornado uma única vez para o usuário copiar. Depois disso, só '********'.

Ao atualizar: se o campo enviado for '********', o valor atual é mantido sem re-criptografar.

Pseudonimização nos logs HTTP

O middleware HTTP log usa:

  • IP: últimos octeto/grupos mascarados (IPv4: x.x.x.*, IPv6: primeiros 4 grupos + ****)
  • userId: SHA-256(userId).substring(0, 12) — rastreável internamente mas não diretamente identificável em logs externos

Rotação de secrets

SecretQuando rotacionarImpacto
MASTER_ENCRYPTION_KEYEm caso de comprometimentoCrítico — todos os dados criptografados ficam ilegíveis. Requer re-criptografia de todo o banco
CLERK_SECRET_KEYEm caso de comprometimentoTodos os usuários perdem sessão ativa
CLERK_WEBHOOK_SECRETA cada 6 meses (boas práticas)Webhooks do Clerk param até nova configuração
INTERNAL_API_KEYEm caso de comprometimentoIntegrações internas (n8n) param até atualizar
Tokens WhatsAppQuando Meta expirar ou comprometerEnvio de mensagens para aquela loja para até reconfigurar