36 lines
2.9 KiB
Markdown
36 lines
2.9 KiB
Markdown
# 04 — Autenticação e cadastro do cliente
|
||
|
||
## Contexto do projeto (leia sempre)
|
||
Sistema web "Briefing de Site" da SeConectai: o cliente se cadastra e depois preenche o briefing de criação do site, com um botão **Ajuda** em cada pergunta que abre um popup com o texto do guia auxiliar. O dono (Tiago) acompanha tudo por um painel admin.
|
||
**Stack fixa:** Next.js 14+ (App Router) + TypeScript, PostgreSQL 16, Prisma, Tailwind + shadcn/ui, React Hook Form + Zod, Auth.js v5 (Credentials, estratégia JWT), Docker Compose. Idioma da interface: pt-BR.
|
||
**Regras gerais:** leia `00-arquitetura-briefing-site.md` e `99-progresso.md` antes de começar; não avance se a etapa anterior estiver incompleta; ao terminar, devolva o `99-progresso.md` atualizado. Não invente dependências fora da stack. Nada de senhas de clientes em lugar nenhum.
|
||
|
||
## Pré-requisito
|
||
Etapas 01–03 concluídas.
|
||
|
||
## Tarefa
|
||
### Cadastro (`/cadastro`)
|
||
Campos: **Nome completo, CPF, WhatsApp, E-mail, Senha (mín. 8) e confirmação**. Seletor "Este site é para uma empresa?" — se sim, exibir **Razão Social, CNPJ e Endereço** (CEP com busca opcional no ViaCEP *no navegador*, logradouro, número, complemento, bairro, cidade, UF). Checkbox obrigatório de aceite da Política de Privacidade/LGPD (guardar `lgpdAceiteEm`).
|
||
|
||
Validações Zod (cliente + servidor) em `lib/validators.ts`: CPF e CNPJ com dígito verificador; WhatsApp brasileiro (DDD + 9 dígitos, normalizar para `+55DDDNÚMERO`); e-mail normalizado em minúsculas; máscara de entrada para CPF/CNPJ/WhatsApp/CEP.
|
||
|
||
Servidor: criar `User` + `Cliente` em transação; CPF → `lib/crypto.ts` (`encrypt`/`decrypt` AES-256-GCM com `CPF_ENC_KEY`, `hashCpf` HMAC-SHA256 com `CPF_HASH_KEY`); rejeitar e-mail ou CPF já cadastrados com mensagem genérica que não revele qual existe; senha com argon2.
|
||
|
||
### Login e sessão
|
||
Auth.js v5 com provider Credentials, JWT, cookie httpOnly/secure/sameSite=lax; sessão contém `userId` e `papel`. `middleware.ts` protege `/briefings*` (CLIENTE) e `/admin*` (ADMIN) e redireciona para `/login`. Limitar tentativas de login (rate limit simples em memória por IP+e-mail).
|
||
|
||
### Recuperar senha
|
||
`/recuperar-senha` (pede e-mail; resposta sempre igual exista ou não a conta) → e-mail com link de token aleatório (guardar só o hash, expira em 1 h, uso único) → `/redefinir-senha`. Enviar por SMTP via `lib/mail.ts` (nodemailer).
|
||
|
||
### Após o login
|
||
Cliente cai em `/briefings` (lista vazia com botão "Iniciar meu briefing"). Admin cai em `/admin`.
|
||
|
||
## Critérios de aceite
|
||
- [ ] Cadastro PF e PJ funcionam; campos de empresa só aparecem/são exigidos no modo PJ.
|
||
- [ ] CPF/CNPJ inválidos são recusados; CPF não aparece em texto puro no banco nem em logs.
|
||
- [ ] E-mail/CPF duplicado é recusado sem revelar qual.
|
||
- [ ] Rotas protegidas redirecionam; cliente não acessa `/admin`.
|
||
- [ ] Recuperação de senha funciona de ponta a ponta (token expira e é de uso único).
|
||
|
||
Atualize `99-progresso.md` (04).
|