Docs

07 — Segurança e Observabilidade

Documentação do boilerplate — o que já está no monorepo vs o que o fork configura em produção. Detalhe de deploy e health checks: 05-deploy-infrastructure.

Segurança

Secrets

OndeO quê
Local.env por app (apps/*/.env) + .env na raiz (SSH, DB prod) — templates em .env.example
ProduçãoPainel Dokploy por Application — ver cloud/dokploy/environments/*.production.env.example
GitNunca commitar .env ou valores reais — só .env.example com placeholders

Boilerplate já exige (service): JWT_SECRET, HASURA_GRAPHQL_ADMIN_SECRET, POSTGRES_URL, STRIPE_*, S3_*, GOOGLE_*, BACKOFFICE_ADMIN_EMAILS.

Rotação (definir no fork):

SecretFrequência sugeridaComo
JWT_SECRET / Hasura JWT90–180 dias ou pós-incidenteGerar novo valor; atualizar service + Hasura (HASURA_GRAPHQL_JWT_SECRET); invalida sessões ativas
HASURA_GRAPHQL_ADMIN_SECRET90 diasDokploy → hasura + service; smoke test GraphQL
Stripe webhook secretQuando rotacionar no Stripe DashboardAtualizar STRIPE_WEBHOOK_SECRET no service
SSH / DBAnual ou pós-exposiçãoDO + .env raiz

Acesso prod: SSH por chave default (~/.ssh); scripts carregam .env da raiz — confirmar com usuário antes de ações destrutivas (TRUNCATE, DROP, restart em massa). Ver .cursor/rules/server-ssh.mdc.

Autenticação

Modelo JWT Bearer emitido pelo apps/service; clients (app, backoffice) enviam Authorization: Bearer <access_token> em REST e GraphQL.

CamadaMecanismo
REST (service)JwtAuthGuard + @Public() em rotas abertas (/auth/*, webhooks)
GraphQL (Hasura)Mesmo JWT; claims https://hasura.io/jwt/claims com x-hasura-user-id, x-hasura-role, x-hasura-allowed-roles
RefreshPOST /auth/refresh-token; access token default JWT_EXPIRES_IN=7d
OAuthGoogle (GOOGLE_CLIENT_ID / secret); callback no service

Roles Hasura (metadata):

RoleUso
userCliente logado — row-level filters (user_id, company_id)
anonymousLeitura pública limitada (ex.: plans)
Admin secretService e migrations — nunca expor ao browser

Backoffice (plataforma): não é role Hasura separada — lista BACKOFFICE_ADMIN_EMAILS no service; login backoffice exige e-mail na lista (assertPlatformAdmin). Rotas admin REST usam PlatformAdminGuard.

Princípio do menor privilégio: regras de negócio sensíveis no service; Hasura só expõe o mínimo com permissions por tabela. Operações admin (users, companies globais) só via service + guard.

Contrato completo: 04-api-integrations · spec 002-auth-module.

Dados

PII no boilerplate: e-mail, nome, avatar, dados de billing (Stripe), membros de empresa, uploads em storage. No fork, documentar campos adicionais (ex.: domínios analisados) e base legal LGPD/GDPR.

PráticaDetalhe
Isolamento multi-tenantRow-level security Hasura por company_id / user_id
Logs de aplicaçãoTabela error_logs — não incluir senhas, tokens completos, API keys
ErrorLoggingInterceptorSanitiza contexto de request; códigos categorizados (AUTH_001–AUTH_006, etc.)
Exclusão de contaFluxo user-facing em spec 002 — garantir cascade ou anonimização conforme política do fork
BackupsPostgres em volume Docker — definir frequência e teste de restore no fork (05-deploy runbooks)

Dependências

pnpm audit          # revisão periódica (mensal sugerida)
pnpm lint && pnpm build   # gate antes de merge em main
  • Priorizar patches de NestJS, React, Hasura engine e dependências com CVE alto/critical
  • Atualizar deps major com plano: lint + build + smoke manual nos fluxos auth/billing afetados
  • O boilerplate não roda suite automatizada no CI — aceite manual após bump relevante (06-testing-quality)

Observabilidade

Estado shipped vs opcional / fork:

SinalTool (boilerplate)RetençãoNotas
Logs app/servicepnpm server:docker -- logs --tail N framework-<app>Docker log driver (default)Sem agregador central incluso
Errors (service)ErrorLoggingService → Postgres error_logsIndefinida — definir política de purge no forkSempre ativo — DB + stdout (docker logs)
Uptime / healthEndpoints HTTP + pnpm dokploy:healthManual / externoConfigurar UptimeRobot ou similar no fork
DB / infradocker stats, queries admin—Postgres :5439, PgBouncer :6432 prod
APM / tracesNão incluso—Adicionar no fork se necessário (Datadog, etc.)
Produto (funil)GA4, GTM, HotjarConforme vendorVer 06-tracking-attribution

Health checks (produção)

AppPathComando local
service/healthcurl -sf localhost:3002/health
website/healthzcurl -sf localhost:3000/healthz
hasura/healthzcurl -sf localhost:8080/healthz
app / backoffice/resposta 200 na raiz

Verificação remota após deploy:

pnpm dokploy:health
./scripts/prod/server-ssh.sh 'docker ps --format "table {{.Names}}\t{{.Status}}"'

Fluxo de erro (service)

Exception → ErrorLoggingInterceptor → ErrorLoggingService
              ├─ 1. INSERT error_logs (Postgres via Hasura admin)
              └─ 2. Logger NestJS (stdout → docker logs)

Consultar erros recentes (prod, não interativo):

pnpm db:query -- "SELECT error_code, severity, error_message, created_at FROM error_logs ORDER BY created_at DESC LIMIT 20"

Usuário autenticado vê apenas próprios logs via Hasura (user_id = X-Hasura-User-Id).

Alertas (produção)

Boilerplate não inclui pager automático — configurar monitor externo no fork. Condições mínimas sugeridas:

CondiçãoSeveridadeAção
service /health fail 2× consecutivasP1Logs: pnpm server:docker -- logs --tail 100 framework-service; checar postgres/redis; rollback Dokploy se deploy recente
Hasura /healthz failP1Logs framework-hasura; verificar PgBouncer e postgres
app ou backoffice downP1Logs do container; verificar build/env vars
website downP2Marketing offline — prioridade abaixo de API
Disk > 85% no dropletP2df -h via SSH; limpar logs/images Docker; expandir volume se recorrente
Spike error_logs severity ≥ highP2Query acima; correlacionar com deploy
Stripe webhook failuresP2Stripe Dashboard → Webhooks; logs service em /webhooks/stripe
Redis unreachableP2Impacto em cache/filas; restart framework-redis após confirmar

Canal interno: definir no fork (Slack, e-mail, WhatsApp founder).

Incident response (leve)

Playbook mínimo para equipe pequena:

  1. Detectar — alerta externo, cliente, ou pnpm dokploy:health falhando
  2. Triagem (5 min) — qual app, desde quando, deploy recente? (docker ps, health URLs)
  3. Comunicar — status interno; status page pública se configurada no fork
  4. Mitigar — restart container, rollback Dokploy para imagem anterior, revert commit + redeploy — confirmar se destrutivo ou afeta dados
  5. Resolver — fix forward ou rollback; validar health + login smoke test
  6. Post-mortem breve — causa, timeline, ação preventiva; entrada user-facing em 08-changelog se impacto visível

Nunca sem confirmação explícita: TRUNCATE, DROP, delete de volumes, restart em massa de postgres.

Acesso remoto

Scripts carregam .env da raiz (load-root-env.sh → ssh-env.sh → SSH_TARGET):

./scripts/prod/server-ssh.sh 'comando'
pnpm server:docker -- ps
pnpm server:docker -- logs --tail 100 framework-service
pnpm db:query -- "SELECT 1"
pnpm db:psql          # interativo prod via SSH

Ver .cursor/rules/server-ssh.mdc e scripts/README.md.

Checklist pré-público (fork)

Itens operacionais antes de abrir tráfego real — complementa PLAYBOOK Fase 5–6:

  • Secrets prod preenchidos no Dokploy (sem placeholders REPLACE_*)
  • pnpm dokploy:health verde nos 5 endpoints
  • Processo de revisão periódica de error_logs (query acima ou backoffice)
  • Monitor de uptime apontando para /health e /healthz
  • Backup Postgres documentado e testado uma vez
  • Política de retenção/purge de error_logs e logs Docker
  • BACKOFFICE_ADMIN_EMAILS restrito a contas reais da equipe

Links relacionados