Appearance
Autenticação com Clerk
Como funciona
O CRM usa o Clerk como provedor de autenticação. O Clerk gerencia:
- Login / cadastro de usuários
- Sessões e tokens JWT
- Organização de usuários (multi-tenancy no Clerk)
- Webhooks de ciclo de vida (usuário criado/atualizado/deletado)
Fluxo de autenticação
1. Usuário faz login no frontend (crm.galdix.com.br)
└─ Clerk SDK autentica (email/senha, SSO)
└─ Clerk retorna JWT para o browser
2. Frontend inclui JWT no header de cada request:
Authorization: Bearer <clerk_jwt>
3. Backend (ClerkAuthGuard):
└─ Extrai token do header Authorization
└─ Chama clerkClient.verifyToken(token)
└─ Clerk SDK valida assinatura + expiração
└─ Extrai sub (Clerk User ID) do payload
└─ Busca usuário no banco por clerkId
└─ Se não encontrado: auto-sync com Clerk API
4. Usuario é anexado em request.user
└─ Contém: id, email, role, organizationId, accessibleStores
5. TenantInterceptor:
└─ Define organizationId no AsyncLocalStorage
└─ Todas as queries subsequentes usam esse organizationIdAuto-sync no primeiro login
Se o usuário faz login mas não existe no banco local:
- Busca dados do usuário na Clerk API
- Cria ou atualiza registro local
- Associa ao papel e organização corretos
- Permite acesso (não bloqueia)
Webhooks do Clerk
O Clerk envia webhooks para POST /webhooks/clerk quando há mudanças de usuário.
Verificação: Headers Svix (svix-id, svix-timestamp, svix-signature) validados com CLERK_WEBHOOK_SECRET.
Eventos tratados:
| Evento | Ação |
|---|---|
user.created | Sync do novo usuário |
user.updated | Atualiza dados |
user.deleted | Remove do banco |
invitation.revoked | Remove convite pendente |
organization_membership.deleted | Remove da organização |
Endpoints públicos
Marcados com @Public() no código — ignoram ClerkAuthGuard:
typescript
@Public()
@Get('/public/survey/respond')
async respond() { ... }Bootstrap de sincronização
Na inicialização do backend, o ClerkBootstrapService sincroniza todas as organizações e membros do Clerk com o banco local. Esse processo é não-fatal — falhas são logadas mas não impedem o boot.
Roles padrão criados automaticamente
Por organização, na criação:
- Super Admin (level 0) — acesso total
- Usuário (level 2) — papel padrão para novos membros
Mapeamento Clerk → Role local:
org:adminno Clerk → Super Adminorg:memberno Clerk → Usuário padrão
Convites
Fluxo via POST /users/invite:
- Cria convite na organização Clerk
- Cria usuário local com
status = 'INVITED'eclerkInvitationId - Clerk envia email automaticamente
- Usuário clica no link → signup na URL
{FRONTEND_URL}/sign-up - Webhook
user.created→ auto-sync completa o registro
Reset de senha
POST /users/:id/reset-password:
- Revoga todas as sessões ativas do usuário no Clerk
- Usuário precisa usar "Forgot Password" no próximo login
- Ação é auditada (action:
ADMIN_PASSWORD_RESET)