API Reference: Autenticacao
Base URL: /api/auth
O modulo de autenticacao gerencia signup, login, aprovacao/rejeicao de membros, recuperacao de senha e refresh de tokens. Suporta multi-membership: um usuario pode pertencer a varios nucleos simultaneamente.
POST /api/auth/signup
Cadastra um novo usuario. Se o email/CPF ja existir em outro nucleo, cria apenas uma nova membership PENDENTE como convidado (is_nucleo_origem=false). Se for usuario novo, cria auth + usuario + membership como nucleo de origem (is_nucleo_origem=true).
Permissao
Publica (sem autenticacao)
Body
{
"nome": "Joao da Silva",
"email": "joao@email.com",
"senha": "Senha123",
"cpf": "123.456.789-00",
"telefone": "(27) 99999-9999",
"dataNascimento": "1990-05-15",
"nucleoId": "uuid-do-nucleo",
"endereco": {
"cep": "29000-000",
"rua": "Rua das Flores",
"numero": "42",
"complemento": "Apto 101",
"bairro": "Centro",
"cidade": "Vitoria",
"estado": "ES"
},
"competencias": [
{ "microId": "uuid-da-competencia", "nivel": "AVANCADO" }
],
"consentimentoLgpd": true,
"codigoReferral": "MBL-ES-A1B2"
}Validacoes (Zod via signupSchema)
nome: min 3 caracteresemail: formato validosenha: min 8 chars, 1 maiuscula, 1 numerocpf: formato 000.000.000-00nucleoId: obrigatorio (UUID do nucleo)consentimentoLgpd: deve sertruecompetencias,codigoReferral: opcionais
Response 201 (usuario novo)
{
"message": "Cadastro realizado com sucesso. Aguarde aprovacao.",
"usuario": {
"id": "uuid",
"nome": "Joao da Silva",
"email": "joao@email.com",
"status": "PENDENTE",
"codigoReferral": "MBL-ES-X7K2"
}
}Response 201 (usuario existente pedindo acesso a outro nucleo)
{
"message": "Pedido de acesso enviado. Aguarde aprovacao deste nucleo.",
"usuario": {
"id": "uuid",
"nome": "Joao da Silva",
"email": "joao@email.com",
"status": "PENDENTE",
"codigoReferral": ""
}
}Erros
400: Nucleo nao encontrado / Email ou CPF ja cadastrado com dados diferentes / Ja possui cadastro neste nucleo
Notas Multi-Membership
- Cria linha em
membros_nucleoscomis_nucleo_origem=truepara usuario novo - Cria linha com
is_nucleo_origem=falsepara usuario existente pedindo acesso a outro nucleo - Plano Free e atribuido automaticamente apenas no nucleo de origem
POST /api/auth/login
Valida credenciais e retorna a lista de nucleos ativos do usuario para que o frontend permita a escolha. NAO retorna tokens (accessToken, refreshToken e expiresIn sao retornados como valores vazios/zero) — a sessao e gerenciada pelo browser via cookies do Supabase Auth.
Permissao
Publica (sem autenticacao)
Body
{
"email": "joao@email.com",
"senha": "Senha123"
}Response 200
{
"accessToken": "",
"refreshToken": "",
"expiresIn": 0,
"usuario": {
"id": "uuid",
"nome": "Joao da Silva",
"email": "joao@email.com",
"cargo": "MEMBRO"
},
"nucleos": [
{
"id": "uuid-nucleo-1",
"nome": "MBL Vitoria",
"slug": "mbl-vitoria",
"logoUrl": "https://...",
"corPrimaria": "#5CBCAE",
"cargo": "MEMBRO",
"isNucleoOrigem": true,
"isConvidado": false
},
{
"id": "uuid-nucleo-2",
"nome": "MBL Vila Velha",
"slug": "mbl-vila-velha",
"logoUrl": null,
"corPrimaria": null,
"cargo": "MEMBRO",
"isNucleoOrigem": false,
"isConvidado": true
}
]
}Erros
401: Email ou senha invalidos403: Cadastro pendente em todos os nucleos / Conta suspensa / Cadastro rejeitado / Sem acesso a nenhum nucleo
Notas
- SUPER_ADMIN recebe
nucleos: [](escolhe nucleo via dropdown global) - Apenas memberships com status ATIVO aparecem na lista de nucleos
- O frontend deve usar
nucleos[]para permitir seletor de nucleo ao usuario
GET /api/auth/me
Retorna perfil completo do usuario logado, incluindo competencias e plano.
Permissao
Autenticado (AuthGuard)
Header
Authorization: Bearer token
Response 200
{
"id": "uuid",
"nome": "Joao da Silva",
"email": "joao@email.com",
"cpf": "123.456.789-00",
"telefone": "(27) 99999-9999",
"data_nascimento": "1990-05-15",
"endereco": { "cidade": "Vitoria", ... },
"cargo": "MEMBRO",
"status": "ATIVO",
"saldo_capixacoins": 1500,
"codigo_referral": "MBL-ES-X7K2",
"foto_url": null,
"primeiro_login": false,
"receber_whatsapp": true,
"criado_em": "2026-03-01T10:00:00Z",
"planos": { "id": "uuid", "nome": "Free" },
"usuario_competencias": [
{
"nivel_proficiencia": "AVANCADO",
"competencias_micro": {
"id": "uuid",
"nome": "Edicao de Video",
"competencias_macro": { "id": "uuid", "nome": "Digital" }
}
}
]
}Erros
404: Usuario nao encontrado
POST /api/auth/approve
Aprova a membership de um usuario num nucleo especifico. Funciona tanto para cadastros novos (nucleo de origem) quanto para pedidos de acesso de convidados de outros nucleos.
Permissao
COORDENADOR ou ADMINISTRADOR (AuthGuard + RolesGuard)
Body
{ "usuarioId": "uuid-do-usuario" }O nucleoId e extraido automaticamente do token do usuario logado via @CurrentUser('nucleoId').
Response 200
{ "message": "Membership aprovada com sucesso" }Side Effects
- Membership atualizada para status
ATIVOcomaprovado_poreaprovado_em - Se for nucleo de origem e usuario.status=PENDENTE, atualiza
usuarios.statuspara ATIVO - 100 CC creditadas ao referral (apenas se is_nucleo_origem=true e referral_id existir)
- Entrada no feed: "Bem-vindo ao [nucleo]!" (origem) ou "[nome] foi aceito como convidado"
- Notificacao para o usuario aprovado
- Email de boas-vindas enviado via MailService/Resend (template
aprovacao)
Erros
400: nucleoId nao identificado / Membership nao esta pendente404: Membership nao encontrada para este usuario neste nucleo
POST /api/auth/reject
Rejeita a membership de um usuario num nucleo especifico. Se for o nucleo de origem, tambem marca usuarios.status como REJEITADO.
Permissao
COORDENADOR ou ADMINISTRADOR (AuthGuard + RolesGuard). Body validado com approveRejectSchema (Zod).
Body
{ "usuarioId": "uuid-do-usuario" }O nucleoId e extraido automaticamente do token via @CurrentUser('nucleoId').
Response 200
{ "message": "Membership rejeitada" }Side Effects
- Membership atualizada para status
REJEITADO - Se for nucleo de origem (is_nucleo_origem=true), tambem atualiza
usuarios.statuspara REJEITADO - Email de rejeicao enviado via MailService/Resend (template
rejeicao)
Erros
400: nucleoId nao identificado / Membership nao esta pendente404: Membership nao encontrada para este usuario neste nucleo
POST /api/auth/refresh
Renova o access token usando o refresh token via Supabase Auth (anon client).
Permissao
Publica (sem autenticacao)
Body
{ "refreshToken": "xxx" }Response 200
{
"accessToken": "eyJhbGci...",
"refreshToken": "novo-refresh",
"expiresIn": 3600
}Erros
401: Refresh token invalido
POST /api/auth/forgot-password
Envia email de recuperacao de senha. Usa admin.generateLink(type: 'recovery')para gerar o token_hash e envia via MailService/Resend com template brandado (recuperacao_senha). NAO dispara o email nativo do Supabase.
Permissao
Publica (sem autenticacao)
Body
{ "email": "joao@email.com" }Response 200
{ "message": "Se o email estiver cadastrado, voce recebera um link de recuperacao." }Notas de Seguranca
- Retorna sempre a mesma mensagem, independentemente de o email existir ou nao
- O link gerado aponta para
{CORS_ORIGIN}/auth/reset-password?token_hash=...&type=recovery - O email usa o template
recuperacao_senhacom branding do nucleo do usuario - O link expira em 1 hora (definido pelo Supabase)
PATCH /api/auth/dismiss-first-login
Marca primeiro_login como false na tabela usuarios. Usado apos o onboarding tour.
Permissao
Autenticado (AuthGuard)
Body
Nenhum (o userId e extraido do token).
Response 200
{ "message": "Primeiro login marcado como concluido" }Cargos do Sistema
O campo cargo pode assumir os seguintes valores:
| Cargo | Descricao |
|---|---|
MEMBRO | Usuario base |
LIDER_PROJETO | Lider de projeto |
PORTA_VOZ | Permissoes de comunicacao (comunicados, enquetes, emails, tarefas, IA) |
COORDENADOR | Gerente do nucleo |
ADMINISTRADOR | Acesso total ao nucleo |
SUPER_ADMIN | Acesso irrestrito a todos os nucleos |