# Feature Specification: Sistema de Autenticação de Clientes **Feature Branch**: `005-authentication` **Created**: 2026-04-13 **Status**: Draft **Input**: User description: "Sistema de autenticação para clientes: login com e-mail + senha (JWT, sem OAuth), auto-cadastro público." ## User Scenarios & Testing *(mandatory)* ### User Story 1 - Cadastro Público de Novo Cliente (Priority: P1) Qualquer pessoa pode criar uma conta no sistema fornecendo nome, e-mail e senha. Após o cadastro, o usuário recebe imediatamente um token de acesso e pode utilizar o sistema sem etapas adicionais de verificação. **Why this priority**: É o ponto de entrada do sistema. Sem cadastro funcional, nenhuma outra funcionalidade de autenticação é utilizável. Entregar apenas P1 já permite que um novo usuário se registre e acesse a plataforma. **Independent Test**: Pode ser testado isoladamente realizando um cadastro com dados válidos e verificando que o sistema retorna token de acesso e dados do usuário criado; e tentando cadastrar com e-mail duplicado ou senha fraca para verificar as rejeições. **Acceptance Scenarios**: 1. **Given** um visitante não autenticado, **When** ele submete nome, e-mail válido e senha com pelo menos 8 caracteres, **Then** o sistema cria a conta, retorna status 201 e fornece um token de acesso junto com os dados básicos do usuário (id, nome, e-mail). 2. **Given** um visitante tenta se cadastrar com um e-mail já existente no sistema, **When** ele submete o formulário, **Then** o sistema retorna status 409 indicando conflito, sem revelar informações sobre a conta existente. 3. **Given** um visitante tenta se cadastrar com senha contendo menos de 8 caracteres, **When** ele submete o formulário, **Then** o sistema retorna status 422 indicando que a senha não atende aos requisitos mínimos. 4. **Given** o formulário de cadastro com campo "confirmar senha" preenchido de forma diferente da senha, **When** o usuário tenta submeter, **Then** o sistema exibe mensagem de validação no formulário sem enviar a requisição. --- ### User Story 2 - Login de Cliente Existente (Priority: P2) Um cliente já cadastrado pode acessar o sistema fornecendo seu e-mail e senha. Após autenticação bem-sucedida, recebe um token de acesso e é redirecionado para sua área pessoal. **Why this priority**: É o fluxo principal de acesso recorrente ao sistema. Depende de P1 (a conta precisa existir), mas pode ser desenvolvido e testado de forma independente com dados pré-cadastrados. **Independent Test**: Pode ser testado isoladamente realizando login com credenciais válidas (espera token + dados do usuário) e com credenciais inválidas (espera 401 com mensagem genérica). Erro de rede deve exibir mensagem amigável. **Acceptance Scenarios**: 1. **Given** um cliente com conta cadastrada, **When** ele fornece e-mail e senha corretos, **Then** o sistema retorna status 200 com token de acesso e informações básicas do usuário (id, nome, e-mail). 2. **Given** um visitante, **When** ele fornece e-mail não cadastrado ou senha incorreta, **Then** o sistema retorna status 401 com mensagem genérica — sem indicar qual campo está incorreto. 3. **Given** um usuário no formulário de login, **When** ocorre erro de rede na requisição, **Then** o formulário exibe mensagem de erro amigável sem expor detalhes técnicos e permite nova tentativa. --- ### User Story 3 - Acesso a Rotas Protegidas com Token (Priority: P3) Rotas marcadas como protegidas só podem ser acessadas por clientes autenticados. Requisições sem token ou com token inválido/expirado são rejeitadas automaticamente. A interface redireciona usuários não autenticados para o login. **Why this priority**: Garante a integridade do sistema. Sem esse mecanismo, dados privados estariam acessíveis publicamente. Depende de P1 e P2 para que haja tokens válidos no sistema. **Independent Test**: Pode ser testado tentando acessar uma rota protegida sem token (espera 401 e redirecionamento para /login), com token válido (espera dados normais), e com token expirado ou adulterado (espera 401). **Acceptance Scenarios**: 1. **Given** um cliente autenticado com token válido, **When** ele acessa uma rota protegida enviando o token no cabeçalho de autorização, **Then** o sistema processa a requisição normalmente e retorna os dados solicitados. 2. **Given** uma requisição sem token de autorização, **When** tenta acessar uma rota protegida, **Then** o sistema retorna status 401. 3. **Given** uma requisição com token expirado ou adulterado, **When** tenta acessar uma rota protegida, **Then** o sistema retorna status 401. 4. **Given** um usuário não autenticado navegando na interface, **When** tenta acessar uma página protegida, **Then** a interface redireciona automaticamente para a tela de login. --- ### User Story 4 - Visualização do Perfil do Cliente Autenticado (Priority: P4) Um cliente autenticado pode consultar seus próprios dados de perfil: nome, e-mail, papel e data de criação da conta, sem precisar informar o próprio identificador na URL. **Why this priority**: Funcionalidade de suporte à identidade do usuário logado. Depende dos fluxos P1–P3 para ter sentido prático. **Independent Test**: Pode ser testado acessando o endpoint de perfil com token válido (espera dados completos do usuário autenticado) e sem token (espera 401). **Acceptance Scenarios**: 1. **Given** um cliente autenticado, **When** ele consulta o endpoint de perfil próprio, **Then** o sistema retorna id, nome, e-mail, papel (role) e data de criação da conta. 2. **Given** uma requisição sem token de autorização, **When** tenta consultar o perfil, **Then** o sistema retorna status 401. --- ### Edge Cases - **E-mail duplicado no cadastro**: Sistema retorna 409 Conflict sem revelar dados da conta existente. - **Senha abaixo do mínimo**: Sistema retorna 422 Unprocessable Entity com descrição do critério não atendido. - **Token JWT adulterado ou expirado**: Sistema retorna 401 Unauthorized em qualquer rota protegida. - **Credenciais inválidas no login**: Sistema retorna 401 com mensagem genérica — não revela se o e-mail ou a senha está errado. - **Erro de rede nos formulários**: Interface exibe mensagem de erro amigável e permite nova tentativa, sem expor erros técnicos. - **Usuário não autenticado em rota protegida**: Interface redireciona para /login preservando a intenção de navegação. - **Senha de confirmação não coincide**: Validação no formulário impede envio e exibe mensagem explicativa. - **Token armazenado localmente e sessão do servidor**: Como o sistema é stateless, não há sessão a invalidar; o logout apenas remove o token do armazenamento do navegador. ## Requirements *(mandatory)* ### Functional Requirements - **FR-001**: O sistema DEVE permitir que qualquer visitante crie uma conta fornecendo nome, e-mail e senha, sem necessidade de aprovação prévia. - **FR-002**: O sistema DEVE validar que senhas tenham no mínimo 8 caracteres no momento do cadastro e retornar erro de validação (422) quando o critério não for atendido. - **FR-003**: O sistema DEVE rejeitar cadastros com e-mail já existente retornando resposta 409, sem revelar informações sobre a conta existente. - **FR-004**: O sistema DEVE armazenar senhas de forma irreversível — nunca em texto puro. - **FR-005**: O sistema DEVE normalizar e-mails para letras minúsculas tanto no armazenamento quanto na comparação durante o login. - **FR-006**: O sistema DEVE emitir um token de acesso com validade de 7 dias após cadastro ou login bem-sucedido. - **FR-007**: O sistema DEVE retornar resposta genérica (401) em caso de credenciais inválidas no login, sem indicar qual campo (e-mail ou senha) está incorreto. - **FR-008**: O sistema DEVE proteger as rotas designadas como privadas, rejeitando com 401 qualquer requisição que não apresente token válido no cabeçalho de autorização. - **FR-009**: O sistema DEVE disponibilizar endpoint para o cliente autenticado consultar seus próprios dados de perfil (id, nome, e-mail, papel, data de criação). - **FR-010**: O sistema DEVE carregar o segredo de assinatura do token a partir de variável de ambiente — nunca embutido no código-fonte. - **FR-011**: A interface DEVE manter o estado de autenticação do usuário entre navegações na aplicação durante a vigência do token. - **FR-012**: A interface DEVE redirecionar automaticamente usuários não autenticados para a tela de login ao tentar acessar áreas protegidas. - **FR-013**: A interface DEVE redirecionar usuários para a área do cliente após login ou cadastro bem-sucedido. - **FR-014**: A interface DEVE exibir opção de "Entrar" na barra de navegação para visitantes não autenticados, e o nome do usuário com opção de "Sair" quando autenticado. - **FR-015**: A interface DEVE adicionar o token de autenticação automaticamente em todas as requisições para rotas protegidas, sem necessidade de configuração manual por página. - **FR-016**: A interface DEVE exibir mensagem de erro amigável quando ocorrer falha de rede nos formulários de login ou cadastro. ### API Contract | Endpoint | Método | Corpo da Requisição | Resposta de Sucesso | Respostas de Erro | |----------|--------|---------------------|---------------------|-------------------| | `/api/v1/auth/register` | POST | `{name, email, password}` | 201 `{access_token, user: {id, name, email}}` | 409 (e-mail duplicado), 422 (validação) | | `/api/v1/auth/login` | POST | `{email, password}` | 200 `{access_token, user: {id, name, email}}` | 401 (credenciais inválidas) | | `/api/v1/auth/me` | GET | — (Bearer token no header) | 200 `{id, name, email, role, created_at}` | 401 (sem token ou token inválido) | ### Key Entities - **ClientUser**: Representa um cliente cadastrado no sistema. Atributos: identificador único (UUID), nome completo (até 150 caracteres), e-mail (único no sistema, até 254 caracteres), senha protegida (hash irreversível), papel no sistema (padrão: 'client'), data e hora de criação da conta. ## Success Criteria *(mandatory)* ### Measurable Outcomes - **SC-001**: Um novo visitante consegue criar uma conta e receber token de acesso em menos de 2 minutos ao utilizar o formulário de cadastro. - **SC-002**: Um cliente cadastrado consegue realizar login e ser redirecionado para sua área em menos de 30 segundos. - **SC-003**: 100% das tentativas de acesso a rotas protegidas sem token válido resultam em rejeição (401) — nenhuma rota protegida é acessível sem autenticação. - **SC-004**: 100% das senhas armazenadas no sistema são protegidas — nenhuma é recuperável em texto puro a partir do banco de dados. - **SC-005**: O estado de autenticação do usuário persiste entre recarregamentos de página durante o período de validade do token. - **SC-006**: Nenhuma resposta do sistema revela se a falha de login se deve ao e-mail ou à senha incorretos — todas as falhas de credencial retornam a mesma mensagem genérica. - **SC-007**: O segredo de assinatura de token nunca aparece no código-fonte versionado — auditoria do repositório não encontra nenhuma ocorrência da chave em texto puro. ## Assumptions - **Sem verificação de e-mail**: A confirmação de conta via link de e-mail está fora do escopo desta versão (MVP). Toda conta criada é imediatamente ativa. - **Sem recuperação de senha**: O fluxo "esqueci minha senha" está fora do escopo desta versão. - **Apenas papel 'client'**: O papel 'admin' é reservado para uso futuro e não possui proteção ou fluxo de acesso implementados nesta versão. - **Sem refresh token**: A renovação automática do token de acesso está fora do escopo desta versão. O usuário precisará fazer login novamente após a expiração (7 dias). - **Sem rate limiting de login**: Limitação de tentativas de acesso é responsabilidade de infraestrutura e está fora do escopo desta feature. - **HTTPS em produção**: A segurança do token em trânsito é garantida pela camada de transporte. O sistema pressupõe ambiente HTTPS em produção. - **Token no armazenamento do navegador**: O token é mantido no armazenamento local do navegador; o logout é realizado removendo-o localmente (o servidor não invalida tokens emitidos, pois o sistema é stateless). - **Design conforme sistema vigente**: Telas de login e cadastro seguem o design system definido em `DESIGN.md` — tema Linear escuro com paleta de cores e tipografia já estabelecidas no projeto.