refactor: remove obsolete authentication documentation and files

- Deleted multiple markdown files related to authentication analysis, push notifications configuration, and environment variable setup to streamline the documentation.
- Removed outdated scripts and guides that are no longer relevant due to the migration to Better Auth.
- Cleaned up the repository by eliminating unnecessary files, ensuring a more focused and maintainable codebase.
This commit is contained in:
2025-11-08 17:16:29 -03:00
parent 9a5f2b294d
commit 4e30d6a2ba
13 changed files with 0 additions and 1860 deletions

View File

@@ -1,179 +0,0 @@
# Análise: Migração para Better Auth
## 📊 Situação Atual
### Sistema Customizado (Atual)
-**Funciona**: Sistema próprio com tokens na tabela `sessoes`
-**Características**:
- Login via `api.autenticacao.login` (mutation customizada)
- Tokens gerados manualmente
- Armazenamento em `localStorage` no frontend
- Uso de `ConvexHttpClient.setAuth(token)` para autenticar requisições
- ⚠️ **Problema encontrado**: Vulnerabilidade onde mensagens eram enviadas em nome errado
-**Estado após correção**: Agora falha porque `ctx.auth.getUserIdentity()` retorna `null` (Better Auth não configurado)
### Better Auth (Parcialmente Configurado)
-**Frontend**: Cliente criado em `lib/auth.ts`
-**API Route**: Handler em `/api/auth/[...all]/+server.ts`
-**Backend Convex**: **NÃO CONFIGURADO** - `convex.config.ts` não tem integração
-**Integração**: Código comentado no `+layout.svelte`
## 🔍 Por que está falhando agora?
Após remover o fallback inseguro:
```typescript
// Antes (inseguro, mas funcionava):
if (!usuarioAtual) {
sessaoAtiva = sessaoMaisRecente(); // ❌ Pegava qualquer usuário
}
// Agora (seguro, mas não funciona):
// Só usa Better Auth, que não está configurado
// Resultado: ctx.auth.getUserIdentity() retorna null
```
O código está tentando usar `ctx.auth.getUserIdentity()` do Convex, mas isso **só funciona** se Better Auth estiver integrado ao Convex via `convex.config.ts`.
## 📈 Comparação: Sistema Customizado vs Better Auth
| Aspecto | Sistema Customizado | Better Auth |
|---------|-------------------|-------------|
| **Segurança** | ⚠️ Média (token manual, vulnerável a problemas) | ✅ Alta (padrão da indústria) |
| **Manutenção** | ⚠️ Alta (manter código próprio) | ✅ Baixa (biblioteca mantida) |
| **Funcionalidades** | ⚠️ Básicas | ✅ Completas (OAuth, 2FA, etc) |
| **Confiabilidade** | ⚠️ Dependente da implementação | ✅ Testado e confiável |
| **Migração** | - | ⚠️ Trabalhosa (mas única vez) |
| **Tempo** | ✅ Já funciona | ⚠️ Requer configuração |
## 🎯 Impacto da Migração para Better Auth
### ✅ Vantagens
1. **Segurança**: Elimina vulnerabilidades de identificação incorreta
2. **Confiabilidade**: Biblioteca testada e mantida pela comunidade
3. **Features**: OAuth, 2FA, recuperação de senha, etc
4. **Padrão**: Usa `ctx.auth.getUserIdentity()` nativo do Convex
5. **Futuro**: Mais fácil adicionar novos métodos de auth
### ⚠️ Desvantagens/Custos
1. **Trabalho inicial**: Configurar Better Auth no Convex
2. **Migração de dados**: Migrar sessões ativas
3. **Mudanças no frontend**: Alterar fluxo de login
4. **Breaking changes**: Usuários precisarão fazer login novamente
5. **Tempo**: 2-4 horas de trabalho
### 📝 Arquivos que precisam mudar
**Backend:**
- `packages/backend/convex/convex.config.ts` - Adicionar Better Auth provider
- `packages/backend/convex/autenticacao.ts` - Manter para features específicas (logs, etc)
- `packages/backend/convex/chat.ts` - Já usa Better Auth (precisa configurar)
- `packages/backend/convex/usuarios.ts` - Já usa Better Auth (precisa configurar)
**Frontend:**
- `apps/web/src/routes/+layout.svelte` - Descomentar integração Better Auth
- `apps/web/src/lib/components/Sidebar.svelte` - Migrar login para Better Auth
- `apps/web/src/lib/stores/auth.svelte.ts` - Adaptar para Better Auth
- Qualquer lugar que use `convex.setAuth(token)`
## 🚀 Recomendação
**SIM, migrar para Better Auth é melhor**, porque:
1. ✅ Mais seguro (resolve o problema atual)
2. ✅ Padrão da indústria
3. ✅ Menos código para manter
4. ✅ Melhor integração com Convex
5. ⚠️ Custo inicial é aceitável (única vez)
## 📋 Plano de Migração (se aprovar)
### Fase 1: Configurar Better Auth no Convex
- Configurar provider no `convex.config.ts`
- Testar `ctx.auth.getUserIdentity()` funcionando
### Fase 2: Migrar Login no Frontend
- Usar Better Auth para login/logout
- Manter sistema customizado como fallback temporário
### Fase 3: Migrar Todas as Queries/Mutations
- Garantir que todas usam Better Auth
- Remover dependências de tokens customizados
### Fase 4: Limpeza
- Remover código de sessões customizadas (ou manter apenas para logs)
- Atualizar documentação
## ⚠️ Alternativa: Corrigir Sistema Customizado
Se preferir manter o sistema customizado, precisamos:
1. Configurar Custom Auth Provider no `convex.config.ts` para ler token do header
2. Modificar `getUsuarioAutenticado` para buscar sessão pelo token específico
3. Garantir que tokens customizados sejam validados corretamente
**Desvantagem**: Continua mantendo código customizado que pode ter bugs futuros.
## 🔧 Solução Imediata: Configurar Custom Auth Provider
Para fazer o sistema customizado funcionar AGORA, precisamos configurar um auth provider no Convex:
```typescript
// convex.config.ts
import { defineApp } from "convex/server";
import { createCustomAuth } from "convex/server";
const app = defineApp({
auth: createCustomAuth({
// Função que extrai o token do header da requisição
getToken: async (request) => {
const authHeader = request.headers.get("authorization");
if (authHeader?.startsWith("Bearer ")) {
return authHeader.substring(7);
}
return null;
},
// Função que valida o token e retorna identity
getIdentity: async (token, ctx) => {
// Buscar sessão pelo token
const sessao = await ctx.db
.query("sessoes")
.withIndex("by_token", (q) => q.eq("token", token))
.filter((q) => q.eq(q.field("ativo"), true))
.first();
if (!sessao || sessao.expiraEm < Date.now()) {
return null; // Token inválido ou expirado
}
const usuario = await ctx.db.get(sessao.usuarioId);
if (!usuario || !usuario.ativo) {
return null;
}
// Retornar identity compatível com Better Auth
return {
subject: usuario._id,
email: usuario.email,
emailVerified: true,
};
},
}),
});
export default app;
```
Depois disso, `ctx.auth.getUserIdentity()` funcionará com tokens customizados!
## 💡 Minha Recomendação Final
**Opção A - Migrar para Better Auth (RECOMENDADO)**:
- ✅ Mais seguro e confiável
- ✅ Padrão da indústria
- ⚠️ 2-4 horas de trabalho
- ✅ Solução definitiva
**Opção B - Configurar Custom Auth Provider (RÁPIDO)**:
- ✅ Funciona imediatamente
- ✅ Mantém sistema atual
- ⚠️ Continua código customizado
- ⚠️ Mais manutenção futura

View File

@@ -1,117 +0,0 @@
# 🔔 Configuração de Push Notifications
## Passo 1: Configurar VAPID Keys
### 1.1 Gerar VAPID Keys (se ainda não tiver)
Execute no diretório do backend:
```bash
cd packages/backend
bunx web-push generate-vapid-keys
```
Isso gerará duas chaves:
- **Public Key**: Segura para expor no frontend
- **Private Key**: Deve ser mantida em segredo, apenas no backend
### 1.2 Configurar no Convex (Backend)
As variáveis de ambiente no Convex são configuradas via dashboard ou CLI:
#### Opção A: Via Dashboard Convex
1. Acesse https://dashboard.convex.dev
2. Selecione seu projeto
3. Vá em **Settings** > **Environment Variables**
4. Adicione as seguintes variáveis:
```
VAPID_PUBLIC_KEY=BDerX0lK_hBCLpC7EbuxoJb2EJ7bcCLaHWxkNumVbvrx9w0MmJduHxJOP3WBwBP-SpQGcueMOyHCv7LFK3KnQks
VAPID_PRIVATE_KEY=KWkJLMxCuCPQQiRXIJEt06G4pTdW0FaUN_vMyY02sc4
FRONTEND_URL=http://localhost:5173
```
#### Opção B: Via CLI Convex
```bash
cd packages/backend
npx convex env set VAPID_PUBLIC_KEY "BDerX0lK_hBCLpC7EbuxoJb2EJ7bcCLaHWxkNumVbvrx9w0MmJduHxJOP3WBwBP-SpQGcueMOyHCv7LFK3KnQks"
npx convex env set VAPID_PRIVATE_KEY "KWkJLMxCuCPQQiRXIJEt06G4pTdW0FaUN_vMyY02sc4"
npx convex env set FRONTEND_URL "http://localhost:5173"
```
### 1.3 Configurar no Frontend
Crie um arquivo `.env` no diretório `apps/web/` com:
```env
VITE_VAPID_PUBLIC_KEY=BDerX0lK_hBCLpC7EbuxoJb2EJ7bcCLaHWxkNumVbvrx9w0MmJduHxJOP3WBwBP-SpQGcueMOyHCv7LFK3KnQks
```
**Importante**: Reinicie o servidor de desenvolvimento após criar/modificar o `.env`.
## Passo 2: Configurar FRONTEND_URL
A variável `FRONTEND_URL` é usada nos templates de email para gerar links de volta ao sistema.
### Para Desenvolvimento:
```
FRONTEND_URL=http://localhost:5173
```
### Para Produção:
```
FRONTEND_URL=https://seu-dominio.com
```
## Passo 3: Testar Push Notifications
### 3.1 Registrar Subscription no Frontend
O sistema automaticamente solicita permissão e registra a subscription quando:
1. O usuário faz login
2. Acessa o chat pela primeira vez
3. O Service Worker é instalado
### 3.2 Verificar se está funcionando
1. Abra o DevTools do navegador (F12)
2. Vá na aba **Application** > **Service Workers**
3. Verifique se o Service Worker está registrado
4. Vá em **Application** > **Notifications**
5. Verifique se a permissão está concedida
### 3.3 Testar envio de push
1. Abra o chat em duas abas/janelas diferentes
2. Faça login com usuários diferentes
3. Envie uma mensagem de um usuário para o outro
4. A mensagem deve aparecer como notificação push na outra aba
## Troubleshooting
### Push notifications não funcionam
1. **Verificar VAPID keys**: Certifique-se de que as keys estão configuradas corretamente
2. **Verificar Service Worker**: O arquivo `sw.js` deve estar em `/static/sw.js`
3. **Verificar permissões**: O navegador deve ter permissão para notificações
4. **Verificar console**: Procure por erros no console do navegador e do Convex
### Erro "VAPID keys não configuradas"
- Verifique se as variáveis de ambiente estão configuradas no Convex
- Reinicie o servidor Convex após configurar as variáveis
- Verifique se os nomes das variáveis estão corretos (case-sensitive)
### Service Worker não registra
- Verifique se o arquivo `sw.js` existe em `apps/web/static/sw.js`
- Verifique se o servidor está servindo arquivos estáticos corretamente
- Limpe o cache do navegador e tente novamente
## Segurança
⚠️ **IMPORTANTE**:
- A **Private Key** nunca deve ser exposta no frontend
- Use variáveis de ambiente diferentes para desenvolvimento e produção
- Regenere as keys se suspeitar de comprometimento
- Mantenha as keys em segredo (não commite no Git)

View File

@@ -1,61 +0,0 @@
# 🔧 Correção Crítica: Autenticação no Chat
## 🐛 Problema Identificado
Erros no console:
- `[getUsuarioAutenticado] Usuário não autenticado - Better Auth não configurado ou token inválido`
- `Uncaught Error: Não autenticado at handler (../convex/chat.ts:757:14)`
- Chat não abre conversas (tela branca)
**Causa Raiz**: Token não está sendo passado nas requisições Convex do `convex-svelte`
## ✅ Correções Aplicadas
### 1. `apps/web/src/routes/+layout.svelte`
- ✅ Monkey patch no `ConvexHttpClient.prototype` para adicionar token automaticamente
- ✅ Token é injetado em todas chamadas `mutation()` e `query()`
### 2. `apps/web/src/lib/components/chat/PresenceManager.svelte`
- ✅ Configuração manual do token no `onMount`
- ✅ Garante que `atualizarStatusPresenca` tenha token
### 3. `apps/web/src/lib/components/chat/ChatWindow.svelte`
- ✅ Configuração manual do token no cliente
- ✅ Garante que queries de conversas funcionem
### 4. Backend (`packages/backend/convex/convex.config.ts`)
- ✅ Custom Auth Provider já configurado com logs extensivos
- ✅ Busca sessão por token específico (seguro)
## 🧪 Como Testar
1. **Limpar cache do navegador** (importante!)
2. **Fazer login novamente**
3. **Abrir console do navegador** e verificar:
- Não deve aparecer mais "Não autenticado"
- Deve aparecer logs do Custom Auth Provider no backend
4. **Testar chat**:
- Abrir conversa
- Verificar se mensagens carregam
- Enviar mensagem
## 🔍 Verificar Logs do Backend
No terminal do Convex, deve aparecer:
- `🔍 [Custom Auth] Headers recebidos:` - Se token está chegando
- `✅ [Custom Auth] Token extraído:` - Se token foi encontrado
- `✅ [Custom Auth] Identity criada:` - Se usuário foi identificado
## ⚠️ Se Ainda Não Funcionar
1. Verificar se token está no `authStore`: `console.log(authStore.token)`
2. Verificar logs do backend Convex para ver qual etapa está falhando
3. Verificar se sessão ainda está ativa no banco
## 📝 Arquivos Modificados
- `apps/web/src/routes/+layout.svelte`
- `apps/web/src/lib/components/chat/PresenceManager.svelte`
- `apps/web/src/lib/components/chat/ChatWindow.svelte`
- Backend já estava correto desde Fase 1

View File

@@ -1,82 +0,0 @@
# ✅ FASE 1 COMPLETA: Configurar Auth Provider no Convex
## 🎯 Objetivo
Configurar Custom Auth Provider no Convex que funciona com o sistema atual (tokens customizados) e prepara para Better Auth.
## ✅ O que foi implementado:
### 1. `packages/backend/convex/convex.config.ts`
- ✅ Adicionado Custom Auth Provider
-`getToken()` - Extrai token do header `Authorization: Bearer <token>`
-`getIdentity()` - Valida token buscando sessão na tabela `sessoes`
- ✅ Retorna identity formatada compatível com Better Auth
- ✅ Valida expiração e status ativo
### 2. `packages/backend/convex/chat.ts`
- ✅ Atualizado `getUsuarioAutenticado()` para usar Custom Auth Provider
- ✅ Adicionado logs de debug em desenvolvimento
- ✅ Mantida compatibilidade com sistema atual
### 3. `packages/backend/convex/usuarios.ts`
- ✅ Atualizado `getUsuarioAutenticado()` para usar Custom Auth Provider
- ✅ Mantida compatibilidade
## 🔍 Como funciona agora:
1. **Frontend envia token**: `ConvexHttpClient.setAuth(token)` → header `Authorization: Bearer <token>`
2. **Convex recebe**: O Custom Auth Provider extrai o token do header
3. **Provider valida**:
- Busca sessão na tabela `sessoes` por token
- Verifica se está ativa e não expirada
- Busca usuário e retorna identity
4. **Backend usa**: `ctx.auth.getUserIdentity()` agora retorna identity válida!
## ✅ Garantias de segurança:
- ✅ Busca sessão por **token específico** (não mais recente)
- ✅ Valida expiração do token
- ✅ Verifica se usuário está ativo
- ✅ Retorna `null` se token inválido (não assume usuário errado)
## 🧪 Como testar:
1. **Iniciar backend**:
```bash
cd packages/backend
npm run dev
```
2. **Fazer login** no sistema (como sempre)
3. **Verificar logs**:
- Deve aparecer: `✅ [getUsuarioAutenticado] Usuário identificado via Custom Auth Provider`
- Enviar mensagem no chat deve funcionar
- Ver perfil deve funcionar
4. **Testar mutations críticas**:
- ✅ Enviar mensagem no chat
- ✅ Ver perfil do usuário
- ✅ Criar conversa
- ✅ Qualquer mutation que use `getUsuarioAutenticado()`
## ⚠️ Se algo der errado:
**Rollback rápido**: Comentar o bloco `auth: { ... }` no `convex.config.ts`:
```typescript
const app = defineApp();
// auth: { ... } // Comentado temporariamente
```
## 📝 Próximos passos (Fase 2):
- Configurar Better Auth no frontend para funcionar junto
- Migrar login gradualmente
- Adicionar suporte a tokens Better Auth no provider
## ✨ Status: FASE 1 COMPLETA ✅
O sistema atual deve funcionar normalmente, mas agora com `ctx.auth.getUserIdentity()` funcionando corretamente!

View File

@@ -1,39 +0,0 @@
# ✅ FASE 2 COMPLETA: Migração Dual - Login
## 🎯 Objetivo
Preparar sistema de login para suportar tanto Better Auth quanto sistema customizado, mantendo ambos funcionando simultaneamente.
## ✅ O que foi implementado:
### 1. `apps/web/src/lib/stores/auth.svelte.ts`
- ✅ Método `login()` atualizado com logs e preparação para Better Auth
- ✅ Método `loginWithBetterAuth()` criado (estrutura pronta, aguardando configuração)
- ✅ Sistema customizado continua funcionando normalmente
### 2. `apps/web/src/lib/components/Sidebar.svelte`
-`handleLogin()` preparado com estrutura dual
- ✅ Comentários mostram onde Better Auth será integrado
- ✅ Fallback para sistema customizado mantido
### 3. `apps/web/src/routes/+layout.svelte`
-`setupConvex` configurado para passar token automaticamente
- ✅ Token do `authStore` é incluído em todas as requisições
## 🔄 Como funciona agora:
**Login atual (Sistema Customizado)**:
1. Usuário faz login via `api.autenticacao.login`
2. Recebe `token` e `usuario`
3. `authStore.login()` salva no localStorage
4. Token é passado automaticamente para todas requisições Convex
**Preparado para Better Auth**:
- Estrutura pronta em `loginWithBetterAuth()`
- Quando Better Auth estiver configurado, será descomentado o código em `handleLogin()`
- Sistema continuará funcionando com fallback automático
## ✨ Status: FASE 2 COMPLETA ✅
Sistema está preparado para Better Auth, mas ainda usa sistema customizado normalmente.
Próximo passo: Fase 3 (já parcialmente feito na Fase 1)

View File

@@ -1,56 +0,0 @@
# ✅ FASE 4 COMPLETA: Integração Better Auth no Frontend
## 🎯 Objetivo
Preparar integração Better Auth no frontend, mantendo compatibilidade com sistema customizado.
## ✅ O que foi implementado:
### 1. `apps/web/src/lib/auth.ts`
-`authClient` atualizado com configuração dinâmica
- ✅ Plugin `convexClient` configurado corretamente
- ✅ Base URL ajustada para funcionar em produção/dev
### 2. `apps/web/src/routes/+layout.svelte`
- ✅ Comentários e estrutura preparada para Better Auth
- ✅ Sistema customizado continua funcionando
- ✅ Preparado para descomentar quando Better Auth estiver pronto
### 3. `apps/web/src/routes/api/auth/[...all]/+server.ts`
- ✅ Handler SvelteKit já existe e está funcionando
- ✅ Processa requisições Better Auth automaticamente
### 4. `packages/backend/convex/betterAuth.ts`
- ✅ Arquivo criado (estrutura preparada)
- ✅ Será configurado quando Better Auth estiver totalmente integrado
## 🔄 Como funciona agora:
**Sistema Atual (Funcionando)**:
- ✅ Login via sistema customizado
- ✅ Tokens passados automaticamente
- ✅ Custom Auth Provider valida tokens
**Preparado para Better Auth**:
- ✅ Cliente Better Auth configurado
- ✅ Handler SvelteKit pronto
- ⏳ Aguardando configuração completa do backend
## ⚠️ Status Atual:
Better Auth está **parcialmente configurado**:
- ✅ Frontend preparado
- ✅ Handler API pronto
- ⏳ Backend Convex precisa de configuração adicional
- ⏳ Tabelas Better Auth precisam ser geradas
**Próximos Passos**:
1. Configurar Better Auth no backend Convex (quando pacote suportar)
2. Gerar/migrar tabelas Better Auth
3. Descomentar integração no `+layout.svelte`
4. Testar login via Better Auth
## ✨ Status: FASE 4 COMPLETA (Estrutura) ✅
Estrutura está pronta. Sistema customizado continua funcionando normalmente.
Better Auth será ativado quando backend estiver completamente configurado.

View File

@@ -1,214 +0,0 @@
# 🧪 Guia de Teste - Push Notifications e Melhorias do Chat
## Pré-requisitos
1. ✅ Convex rodando (`cd packages/backend && bun run dev`)
2. ✅ Frontend rodando (`cd apps/web && bun run dev`)
3. ✅ Variáveis de ambiente configuradas (ver `configurar-variaveis-ambiente.md`)
4. ✅ Usuários criados no sistema
## Teste 1: Configuração de Push Notifications
### 1.1 Verificar Service Worker
1. Abra o navegador em `http://localhost:5173`
2. Faça login no sistema
3. Abra DevTools (F12)
4. Vá em **Application** > **Service Workers**
5. ✅ Verifique se `sw.js` está registrado e ativo
### 1.2 Solicitar Permissão de Notificações
1. Abra o chat no sistema
2. O sistema deve solicitar permissão para notificações automaticamente
3. Clique em **Permitir**
4. ✅ Verifique em **Application** > **Notifications** que a permissão está concedida
### 1.3 Verificar Subscription
1. Abra o Console do DevTools
2. Execute:
```javascript
navigator.serviceWorker.ready.then(reg => {
reg.pushManager.getSubscription().then(sub => {
console.log('Subscription:', sub);
});
});
```
3. ✅ Deve retornar um objeto Subscription com endpoint e keys
## Teste 2: Envio e Recebimento de Push Notifications
### 2.1 Teste Básico
1. Abra o sistema em **duas abas diferentes** (ou dois navegadores)
2. Faça login com usuários diferentes em cada aba
3. Na aba 1, abra uma conversa com o usuário da aba 2
4. Envie uma mensagem da aba 1
5. ✅ A aba 2 deve receber uma notificação push (mesmo se estiver em background)
### 2.2 Teste de Menção
1. Na aba 1, envie uma mensagem mencionando o usuário da aba 2 (use @)
2. ✅ A aba 2 deve receber uma notificação push destacada
### 2.3 Teste Offline
1. Feche a aba 2 (ou coloque o navegador em modo offline)
2. Envie uma mensagem da aba 1
3. ✅ O sistema deve enviar um email para o usuário da aba 2 (se estiver offline)
## Teste 3: Edição de Mensagens
### 3.1 Editar Mensagem Própria
1. Envie uma mensagem no chat
2. Clique no ícone ✏️ ao lado da mensagem
3. Edite o conteúdo
4. Pressione **Ctrl+Enter** ou clique em **Salvar**
5. ✅ A mensagem deve ser atualizada com indicador "(editado)"
### 3.2 Tentar Editar Mensagem de Outro Usuário
1. Tente editar uma mensagem de outro usuário
2. ✅ Não deve aparecer o botão de editar (ou deve retornar erro)
## Teste 4: Soft Delete de Mensagens
### 4.1 Deletar Mensagem Própria
1. Envie uma mensagem
2. Clique no ícone 🗑️ ao lado da mensagem
3. Confirme a exclusão
4. ✅ A mensagem deve ser marcada como "Mensagem deletada"
### 4.2 Tentar Deletar Mensagem de Outro Usuário
1. Tente deletar uma mensagem de outro usuário
2. ✅ Não deve aparecer o botão de deletar (ou deve retornar erro)
## Teste 5: Respostas Encadeadas
### 5.1 Responder Mensagem
1. Clique no botão **↪️ Responder** em uma mensagem
2. ✅ Deve aparecer um preview da mensagem original no campo de input
3. Digite sua resposta e envie
4. ✅ A mensagem enviada deve mostrar o preview da mensagem original acima
### 5.2 Visualizar Thread
1. Envie várias respostas para diferentes mensagens
2. ✅ Cada resposta deve mostrar claramente qual mensagem está respondendo
## Teste 6: Preview de Links
### 6.1 Enviar Mensagem com URL
1. Envie uma mensagem contendo uma URL (ex: `https://www.google.com`)
2. Aguarde alguns segundos
3. ✅ Deve aparecer um preview do link abaixo da mensagem com:
- Imagem (se disponível)
- Título
- Descrição
- Site/nome do domínio
### 6.2 Testar Diferentes URLs
Teste com diferentes tipos de URLs:
- ✅ Google: `https://www.google.com`
- ✅ YouTube: `https://www.youtube.com`
- ✅ Artigo de notícia
- ✅ Site sem Open Graph (deve funcionar mesmo assim)
## Teste 7: Busca Full-Text
### 7.1 Busca Básica
1. Envie algumas mensagens com palavras específicas
2. Use a busca no chat (se implementada) ou a query de busca
3. ✅ Deve encontrar mensagens mesmo com acentos diferentes
### 7.2 Busca com Filtros
1. Busque mensagens por:
- ✅ Remetente específico
- ✅ Tipo (texto, arquivo, imagem)
- ✅ Período de data
2. ✅ Os filtros devem funcionar corretamente
## Teste 8: Rate Limiting de Emails
### 8.1 Enviar Múltiplos Emails
1. Configure o sistema para enviar emails
2. Tente enviar mais de 10 emails em 1 minuto
3. ✅ Deve retornar erro de rate limit após o limite
### 8.2 Verificar Delay Exponencial
1. Aguarde o rate limit ser aplicado
2. Tente enviar novamente
3. ✅ Deve haver um delay antes de permitir novo envio
## Checklist de Validação
- [ ] Service Worker registrado e funcionando
- [ ] Permissão de notificações concedida
- [ ] Push notifications sendo recebidas
- [ ] Emails sendo enviados quando usuário offline
- [ ] Edição de mensagens funcionando
- [ ] Soft delete funcionando
- [ ] Respostas encadeadas funcionando
- [ ] Preview de links aparecendo
- [ ] Busca full-text funcionando
- [ ] Rate limiting de emails funcionando
## Problemas Comuns e Soluções
### Push notifications não funcionam
**Problema**: Notificações não aparecem
**Soluções**:
1. Verifique se as VAPID keys estão configuradas no Convex
2. Verifique se `VITE_VAPID_PUBLIC_KEY` está no `.env` do frontend
3. Reinicie o servidor Convex e frontend
4. Limpe o cache do navegador
5. Verifique o console para erros
### Preview de links não aparece
**Problema**: Links não geram preview
**Soluções**:
1. Verifique se a URL é válida (começa com http:// ou https://)
2. Aguarde alguns segundos (processamento é assíncrono)
3. Verifique o console do Convex para erros na extração
4. Alguns sites bloqueiam scrapers - isso é normal
### Edição não funciona
**Problema**: Botão de editar não aparece ou não funciona
**Soluções**:
1. Verifique se a mensagem é sua (só pode editar próprias mensagens)
2. Verifique se a mensagem não foi deletada
3. Verifique o console para erros
4. Certifique-se de que a mutation `editarMensagem` está funcionando
## Relatório de Testes
Após completar os testes, preencha:
- **Data**: ___________
- **Testador**: ___________
- **Ambiente**: [ ] Desenvolvimento [ ] Produção
- **Navegador**: ___________
- **Resultados**: ___________
**Observações**:
_______________________________________
_______________________________________
_______________________________________

View File

@@ -1,163 +0,0 @@
# 📋 Passo a Passo - Configuração Completa
## ✅ Passo 1: Configurar VAPID Keys
### 1.1 Configurar no Convex (Backend)
**Opção A: Via Dashboard (Recomendado)**
1. Acesse https://dashboard.convex.dev
2. Selecione seu projeto
3. Vá em **Settings** > **Environment Variables**
4. Adicione as seguintes variáveis:
```
VAPID_PUBLIC_KEY=BDerX0lK_hBCLpC7EbuxoJb2EJ7bcCLaHWxkNumVbvrx9w0MmJduHxJOP3WBwBP-SpQGcueMOyHCv7LFK3KnQks
VAPID_PRIVATE_KEY=KWkJLMxCuCPQQiRXIJEt06G4pTdW0FaUN_vMyY02sc4
FRONTEND_URL=http://localhost:5173
```
**Opção B: Via CLI**
Execute do diretório raiz do projeto:
```powershell
cd packages/backend
npx convex env set VAPID_PUBLIC_KEY "BDerX0lK_hBCLpC7EbuxoJb2EJ7bcCLaHWxkNumVbvrx9w0MmJduHxJOP3WBwBP-SpQGcueMOyHCv7LFK3KnQks"
npx convex env set VAPID_PRIVATE_KEY "KWkJLMxCuCPQQiRXIJEt06G4pTdW0FaUN_vMyY02sc4"
npx convex env set FRONTEND_URL "http://localhost:5173"
```
**Opção C: Usar Script Automático**
Execute na raiz do projeto:
```powershell
.\scripts\configurar-push-notifications.ps1
```
### 1.2 Configurar no Frontend
Crie o arquivo `apps/web/.env` com:
```env
VITE_VAPID_PUBLIC_KEY=BDerX0lK_hBCLpC7EbuxoJb2EJ7bcCLaHWxkNumVbvrx9w0MmJduHxJOP3WBwBP-SpQGcueMOyHCv7LFK3KnQks
```
**Importante**: Reinicie o servidor frontend após criar/modificar o `.env`
## ✅ Passo 2: Configurar FRONTEND_URL
A variável `FRONTEND_URL` já foi configurada no Passo 1.1. Ela é usada nos templates de email para gerar links de volta ao sistema.
**Para Desenvolvimento:**
```
FRONTEND_URL=http://localhost:5173
```
**Para Produção (quando fizer deploy):**
```
FRONTEND_URL=https://seu-dominio.com
```
## ✅ Passo 3: Testar Funcionalidades
### 3.1 Verificar Configuração Inicial
1. **Inicie o Convex** (se não estiver rodando):
```bash
cd packages/backend
bun run dev
```
2. **Inicie o Frontend** (se não estiver rodando):
```bash
cd apps/web
bun run dev
```
3. **Verifique as variáveis de ambiente**:
- No Convex Dashboard: Settings > Environment Variables
- No Frontend: Verifique se `apps/web/.env` existe
### 3.2 Testar Push Notifications
1. Abra `http://localhost:5173` no navegador
2. Faça login no sistema
3. Abra DevTools (F12) > **Application** > **Service Workers**
4. ✅ Verifique se `sw.js` está registrado
5. ✅ Verifique se a permissão de notificações foi solicitada
### 3.3 Testar Chat Completo
Siga o guia completo em `GUIA_TESTE_PUSH_NOTIFICATIONS.md` para testar:
- ✅ Push notifications
- ✅ Edição de mensagens
- ✅ Soft delete
- ✅ Respostas encadeadas
- ✅ Preview de links
- ✅ Busca full-text
## 🔍 Verificação Rápida
Execute estes comandos para verificar:
### Verificar Variáveis no Convex:
```bash
cd packages/backend
npx convex env list
```
Deve mostrar:
- `VAPID_PUBLIC_KEY`
- `VAPID_PRIVATE_KEY`
- `FRONTEND_URL`
### Verificar Frontend:
```bash
cd apps/web
# Verifique se o arquivo .env existe
cat .env
```
## 🐛 Troubleshooting
### Problema: Variáveis não aparecem no Convex
**Solução**:
- Certifique-se de estar no projeto correto no dashboard
- Reinicie o servidor Convex após configurar
- Use `npx convex env list` para verificar
### Problema: Frontend não encontra VAPID_PUBLIC_KEY
**Solução**:
- Verifique se o arquivo `.env` está em `apps/web/.env`
- Verifique se a variável começa com `VITE_`
- Reinicie o servidor frontend
- Limpe o cache do navegador
### Problema: Service Worker não registra
**Solução**:
- Verifique se `apps/web/static/sw.js` existe
- Abra DevTools > Application > Service Workers
- Clique em "Unregister" e recarregue a página
- Verifique o console para erros
## 📝 Checklist Final
- [ ] VAPID keys configuradas no Convex
- [ ] FRONTEND_URL configurada no Convex
- [ ] VITE_VAPID_PUBLIC_KEY no `.env` do frontend
- [ ] Convex rodando
- [ ] Frontend rodando
- [ ] Service Worker registrado
- [ ] Permissão de notificações concedida
- [ ] Push notifications funcionando
- [ ] Todas as funcionalidades testadas
## 🎉 Pronto!
Após completar os 3 passos, o sistema estará totalmente configurado e pronto para uso!

View File

@@ -1,226 +0,0 @@
# Plano de Migração para Better Auth - Garantia de Funcionamento
## 🎯 Estratégia: Migração Dual (Zero Downtime)
**Garantia**: Sistema atual continua funcionando durante toda a migração. Se algo falhar, simplesmente revertemos uma linha de código.
## 📋 Análise Completa de Dependências
### Backend (7 arquivos usando `getUsuarioAutenticado`):
1.`chat.ts` - Crítico (mensagens)
2.`usuarios.ts` - Crítico (perfil)
3.`pushNotifications.ts` - Importante
4.`preferenciasNotificacao.ts` - Importante
5.`atestadosLicencas.ts` - Médio
6.`permissoesAcoes.ts` - Médio
7.`monitoramento.ts` - Baixo
### Frontend (24 arquivos usando `authStore`):
- ✅ Todos usam `useConvexClient()` que pega auth automaticamente
- ✅ Não há `setAuth()` manual nos componentes (exceto refresh)
-`Sidebar.svelte` é o único lugar que faz login customizado
## 🔄 Fases de Migração (Cada fase é testável e reversível)
### ✅ FASE 0: Preparação (Sem Risco)
- [x] Documentação completa
- [x] Análise de dependências
- [ ] Backups de configuração atual
### ✅ FASE 1: Configurar Better Auth no Convex (Baixo Risco)
**Status**: Configuração apenas, sistema atual continua funcionando
**Arquivo**: `packages/backend/convex/convex.config.ts`
- Adicionar Better Auth provider
- Testar `ctx.auth.getUserIdentity()` retornando dados
**Rollback**: Simplesmente comentar a configuração
**Tempo**: 30 minutos
---
### ✅ FASE 2: Migração Dual - Login (Médio Risco)
**Status**: Ambos sistemas funcionam simultaneamente
**Estratégia**:
- Better Auth como primário
- Sistema customizado como fallback
- Logs para comparar resultados
**Arquivos**:
- `apps/web/src/lib/components/Sidebar.svelte` - Suportar ambos logins
- `apps/web/src/lib/stores/auth.svelte.ts` - Detectar qual método usar
**Teste**: Login com Better Auth e verificar que tudo funciona
**Rollback**: Remover código Better Auth, manter apenas customizado
**Tempo**: 1 hora
---
### ✅ FASE 3: Migração Dual - Backend Helpers (Baixo Risco)
**Status**: Helper tenta Better Auth primeiro, fallback para customizado
**Arquivos** (7 arquivos):
- `packages/backend/convex/chat.ts`
- `packages/backend/convex/usuarios.ts`
- `packages/backend/convex/pushNotifications.ts`
- `packages/backend/convex/preferenciasNotificacao.ts`
- `packages/backend/convex/atestadosLicencas.ts`
- `packages/backend/convex/permissoesAcoes.ts`
- `packages/backend/convex/monitoramento.ts`
**Estratégia**:
```typescript
async function getUsuarioAutenticado(ctx) {
// 1. Tentar Better Auth primeiro
const identity = await ctx.auth.getUserIdentity();
if (identity?.email) {
// Buscar usuário do Better Auth
const usuario = await buscarPorEmail(identity.email);
if (usuario) return usuario;
}
// 2. Fallback para sistema customizado (se Better Auth não funcionar)
// ... código atual ...
}
```
**Teste**: Cada mutation/query deve funcionar com ambos sistemas
**Rollback**: Remover código Better Auth, manter apenas fallback
**Tempo**: 1 hora
---
### ✅ FASE 4: Integrar Convex com Better Auth (Médio Risco)
**Status**: Convex passa a usar Better Auth automaticamente
**Arquivo**: `apps/web/src/routes/+layout.svelte`
- Descomentar `createSvelteAuthClient`
- Configurar Convex para usar Better Auth automaticamente
**Teste**: Todas requisições devem funcionar sem `setAuth()` manual
**Rollback**: Comentar novamente
**Tempo**: 30 minutos
---
### ✅ FASE 5: Migração Completa - Frontend (Médio Risco)
**Status**: Remover sistema customizado do frontend
**Arquivos**:
- `apps/web/src/lib/components/Sidebar.svelte` - Usar apenas Better Auth
- `apps/web/src/lib/stores/auth.svelte.ts` - Adaptar para Better Auth
- Remover `auth_token` do localStorage
**Teste**: Login/logout completo
**Rollback**: Reverter para código anterior
**Tempo**: 1 hora
---
### ✅ FASE 6: Migração Completa - Backend (Baixo Risco)
**Status**: Remover fallback customizado dos helpers
**Arquivos**: Os mesmos 7 arquivos da Fase 3
- Remover código de fallback customizado
- Manter apenas Better Auth
**Teste**: Tudo deve funcionar apenas com Better Auth
**Rollback**: Restaurar código com fallback
**Tempo**: 30 minutos
---
### ✅ FASE 7: Limpeza (Sem Risco)
**Status**: Remover código não usado
**Arquivos**:
- `packages/backend/convex/autenticacao.ts` - Manter para logs históricos ou remover
- Limpar tokens antigos do localStorage (se houver)
**Tempo**: 30 minutos
---
## ⚠️ Pontos de Atenção e Como Mitigar
### 1. **Sessões Ativas Existentes**
**Problema**: Usuários logados perderão sessão
**Mitigação**:
- Fazer migração fora do horário de pico
- Avisar usuários para fazer logout/login
- Manter ambos sistemas por alguns dias
### 2. **Tokens no localStorage**
**Problema**: Tokens antigos podem causar confusão
**Mitigação**:
- Criar script de migração que limpa tokens antigos
- Detectar e migrar automaticamente na primeira abertura
### 3. **Email como Identificador Único**
**Problema**: Better Auth usa email, sistema atual usa ID
**Mitigação**:
- Verificar que todos usuários têm email único
- Criar índices no banco se necessário
### 4. **Testes em Produção**
**Problema**: Diferenças entre dev e produção
**Mitigação**:
- Testar em ambiente de staging primeiro
- Migração gradual por módulo
- Monitorar logs de erro
## ✅ Checklist de Garantia
Antes de completar cada fase:
- [ ] Testar login/logout
- [ ] Testar queries críticas
- [ ] Testar mutations críticas
- [ ] Verificar logs de erro
- [ ] Testar com múltiplos usuários
- [ ] Verificar autenticação em componentes críticos (Chat, Perfil, etc)
## 🚨 Plano de Rollback
Se algo der errado em qualquer fase:
1. **Fase 1-3**: Comentar configuração Better Auth, manter sistema atual
2. **Fase 4**: Reverter layout.svelte para código anterior
3. **Fase 5**: Restaurar código de Sidebar e authStore
4. **Fase 6**: Restaurar helpers com fallback
**Tempo de rollback**: Máximo 5 minutos por fase
## 📊 Garantia Final
**Posso garantir**:
- ✅ Sistema atual continua funcionando durante migração
- ✅ Rollback rápido em caso de problemas
- ✅ Testes em cada fase antes de prosseguir
- ✅ Documentação completa de cada passo
**Não posso garantir**:
- ❌ Zero bugs (impossível sem testes reais)
- ❌ Compatibilidade 100% sem testar em ambiente real
- ❌ Que não haverá necessidade de ajustes finos
**Mas posso garantir**:
- ✅ Que se algo falhar, revertemos imediatamente
- ✅ Que testes serão feitos antes de cada avanço
- ✅ Que código estará documentado para debugging fácil
## 🎬 Decisão
**Opções**:
1. **Migração completa** (6 horas total, fases separadas)
2. **Solução rápida** (Configurar Custom Auth Provider - 1 hora)
3. **Manter como está** (Corrigir apenas o problema imediato)
**Minha recomendação**: Opção 1, mas fazer fase por fase, testando bem entre cada uma.

View File

@@ -1,68 +0,0 @@
# ✅ Resumo da Configuração Completa
## 📋 Passo 1: VAPID Keys - CONCLUÍDO
### Keys Geradas:
- **Public Key**: `BDerX0lK_hBCLpC7EbuxoJb2EJ7bcCLaHWxkNumVbvrx9w0MmJduHxJOP3WBwBP-SpQGcueMOyHCv7LFK3KnQks`
- **Private Key**: `KWkJLMxCuCPQQiRXIJEt06G4pTdW0FaUN_vMyY02sc4`
### Configuração Necessária:
**1. No Convex (Backend):**
- Via Dashboard: Settings > Environment Variables
- Adicionar: `VAPID_PUBLIC_KEY`, `VAPID_PRIVATE_KEY`, `FRONTEND_URL`
- OU executar: `.\scripts\configurar-push-notifications.ps1`
**2. No Frontend:**
- Criar arquivo `apps/web/.env`
- Adicionar: `VITE_VAPID_PUBLIC_KEY=BDerX0lK_hBCLpC7EbuxoJb2EJ7bcCLaHWxkNumVbvrx9w0MmJduHxJOP3WBwBP-SpQGcueMOyHCv7LFK3KnQks`
## 📋 Passo 2: FRONTEND_URL - CONCLUÍDO
- Valor padrão: `http://localhost:5173`
- Configurar no Convex junto com as VAPID keys
- Usado nos templates de email para links de retorno
## 📋 Passo 3: Testes - PRONTO PARA EXECUTAR
### Arquivos Criados:
-`PushNotificationManager.svelte` - Registra subscription automaticamente
-`GUIA_TESTE_PUSH_NOTIFICATIONS.md` - Guia completo de testes
-`PASSO_A_PASSO_CONFIGURACAO.md` - Instruções detalhadas
-`CONFIGURACAO_PUSH_NOTIFICATIONS.md` - Documentação técnica
-`scripts/configurar-push-notifications.ps1` - Script automático
### Para Testar:
1. **Configure as variáveis** (ver Passo 1)
2. **Reinicie os servidores** (Convex e Frontend)
3. **Faça login** no sistema
4. **Siga o guia**: `GUIA_TESTE_PUSH_NOTIFICATIONS.md`
## 🎯 Checklist de Configuração
- [ ] VAPID keys configuradas no Convex Dashboard
- [ ] FRONTEND_URL configurada no Convex
- [ ] Arquivo `apps/web/.env` criado com VITE_VAPID_PUBLIC_KEY
- [ ] Convex reiniciado após configurar variáveis
- [ ] Frontend reiniciado após criar .env
- [ ] Service Worker registrado (verificar DevTools)
- [ ] Permissão de notificações concedida
- [ ] Testes executados conforme guia
## 📚 Documentação Disponível
1. **CONFIGURACAO_PUSH_NOTIFICATIONS.md** - Configuração técnica detalhada
2. **PASSO_A_PASSO_CONFIGURACAO.md** - Instruções passo a passo
3. **GUIA_TESTE_PUSH_NOTIFICATIONS.md** - Guia completo de testes
4. **configurar-variaveis-ambiente.md** - Referência rápida
## 🚀 Próximos Passos
1. Execute o script de configuração OU configure manualmente
2. Reinicie os servidores
3. Teste todas as funcionalidades
4. Reporte qualquer problema encontrado
**Tudo pronto para configuração e testes!** 🎉

View File

@@ -1,178 +0,0 @@
# 📋 Resumo da Migração para Better Auth
## ✅ STATUS GERAL: FASES 1-4 COMPLETAS
Migração gradual implementada com sucesso. Sistema atual funcionando + estrutura Better Auth preparada.
---
## 🎯 O QUE FOI FEITO
### ✅ FASE 1: Custom Auth Provider no Convex
**Arquivos modificados:**
- `packages/backend/convex/convex.config.ts` - Custom Auth Provider configurado
- `packages/backend/convex/chat.ts` - Helper atualizado
- `packages/backend/convex/usuarios.ts` - Helper atualizado
**Resultado:**
-`ctx.auth.getUserIdentity()` agora funciona com tokens customizados
- ✅ Busca sessão por token específico (seguro, não mais "mais recente")
- ✅ Logs de debug extensivos adicionados
---
### ✅ FASE 2: Migração Dual - Login
**Arquivos modificados:**
- `apps/web/src/lib/stores/auth.svelte.ts` - Estrutura dual preparada
- `apps/web/src/lib/components/Sidebar.svelte` - Login com fallback preparado
- `apps/web/src/routes/+layout.svelte` - Token passado automaticamente
**Resultado:**
- ✅ Sistema customizado continua funcionando normalmente
- ✅ Estrutura pronta para Better Auth
- ✅ Token passado automaticamente em todas requisições
---
### ✅ FASE 3: Backend Helpers (Já feito na Fase 1)
**Arquivos modificados:**
- Mesmos arquivos da Fase 1
**Resultado:**
- ✅ Todos helpers usam Custom Auth Provider
- ✅ Fallback seguro implementado
---
### ✅ FASE 4: Integração Better Auth Frontend
**Arquivos modificados:**
- `apps/web/src/lib/auth.ts` - Cliente Better Auth configurado
- `apps/web/src/routes/+layout.svelte` - Integração preparada
- `apps/web/src/routes/api/auth/[...all]/+server.ts` - Handler já existia
- `packages/backend/convex/betterAuth.ts` - Estrutura criada
**Resultado:**
- ✅ Cliente Better Auth configurado corretamente
- ✅ Handler SvelteKit pronto
- ⏳ Aguardando configuração completa do backend
---
## 🔒 SEGURANÇA
### Problemas corrigidos:
1.**Bug crítico**: Removido fallback inseguro que buscava "sessão mais recente"
2.**Identificação correta**: Agora busca sessão por token específico
3.**Validação**: Verifica expiração e status ativo
4.**Logs**: Debug extensivo para troubleshooting
### Garantias:
- ✅ Nenhum usuário será identificado incorretamente
- ✅ Tokens são validados antes de usar
- ✅ Sessões expiradas são rejeitadas
- ✅ Usuários inativos são bloqueados
---
## 🧪 TESTES NECESSÁRIOS
### Testes Imediatos:
1.**Login**: Fazer login e verificar que funciona
2.**Enviar Mensagem**: Testar chat funcionando
3.**Ver Perfil**: Verificar que perfil carrega
4.**Logs**: Verificar logs do Convex para debug
### Testes Futuros (quando Better Auth ativo):
1. ⏳ Login via Better Auth
2. ⏳ Comparar tokens Better Auth vs customizado
3. ⏳ Validar que ambos funcionam simultaneamente
4. ⏳ Migração de usuários existentes
---
## 📊 ESTADO ATUAL DO SISTEMA
### ✅ Funcionando:
- Login via sistema customizado
- Autenticação em todas mutations/queries
- Token passado automaticamente
- Custom Auth Provider validando tokens
### ⏳ Preparado mas não ativo:
- Cliente Better Auth configurado
- Handler SvelteKit pronto
- Estrutura dual no login
- Integração no layout
### ❌ Pendente:
- Configuração completa Better Auth backend
- Migração de sessões existentes
- Ativação Better Auth (descomentar código)
---
## 🚀 PRÓXIMOS PASSOS
### Curto Prazo (Para resolver erros):
1. **Verificar logs do Convex** para entender por que tokens não estão chegando
2. **Ajustar `setupConvex`** se necessário para passar token corretamente
3. **Testar em ambiente real** e ajustar conforme necessário
### Médio Prazo (Completar Better Auth):
1. Configurar Better Auth backend completamente
2. Gerar tabelas Better Auth no Convex
3. Descomentar integração no `+layout.svelte`
4. Testar login via Better Auth
5. Validar que ambos sistemas funcionam
### Longo Prazo (Migração completa):
1. Migrar todos usuários para Better Auth
2. Remover sistema customizado (ou manter como fallback)
3. Atualizar documentação
4. Remover código comentado
---
## ⚠️ ROLLBACK PLAN
Se algo der errado, reverta em ordem:
1. **Comentar Custom Auth Provider**: Remover `auth: { ... }` de `convex.config.ts`
2. **Reverter helpers**: Voltar para busca de sessão (mas não "mais recente"!)
3. **Reverter layout**: Remover configuração `auth` de `setupConvex`
**Tempo estimado de rollback**: 5-10 minutos
---
## 📝 ARQUIVOS CRIADOS/MODIFICADOS
### Criados:
- `FASE1_COMPLETA.md`
- `FASE2_COMPLETA.md`
- `FASE4_COMPLETA.md`
- `RESUMO_MIGRACAO.md`
- `packages/backend/convex/betterAuth.ts`
### Modificados:
- `packages/backend/convex/convex.config.ts`
- `packages/backend/convex/chat.ts`
- `packages/backend/convex/usuarios.ts`
- `apps/web/src/routes/+layout.svelte`
- `apps/web/src/lib/auth.ts`
- `apps/web/src/lib/stores/auth.svelte.ts`
- `apps/web/src/lib/components/Sidebar.svelte`
---
## ✨ CONCLUSÃO
**Migração gradual implementada com sucesso!**
- ✅ Sistema atual funcionando com Custom Auth Provider seguro
- ✅ Estrutura Better Auth preparada e pronta
- ✅ Migração reversível e testável
- ✅ Documentação completa
**Próximo passo**: Testar sistema atual e verificar logs para ajustar se necessário.

View File

@@ -1,77 +0,0 @@
# ⚙️ Configuração de Variáveis de Ambiente
## Passo 1: Configurar VAPID Keys no Convex
### Opção A: Via Dashboard Convex (Recomendado)
1. Acesse https://dashboard.convex.dev
2. Selecione seu projeto SGSE
3. Vá em **Settings** > **Environment Variables**
4. Clique em **Add Variable** e adicione uma por vez:
**Variável 1:**
- **Name**: `VAPID_PUBLIC_KEY`
- **Value**: `BDerX0lK_hBCLpC7EbuxoJb2EJ7bcCLaHWxkNumVbvrx9w0MmJduHxJOP3WBwBP-SpQGcueMOyHCv7LFK3KnQks`
**Variável 2:**
- **Name**: `VAPID_PRIVATE_KEY`
- **Value**: `KWkJLMxCuCPQQiRXIJEt06G4pTdW0FaUN_vMyY02sc4`
**Variável 3:**
- **Name**: `FRONTEND_URL`
- **Value**: `http://localhost:5173` (ou sua URL de produção)
### Opção B: Via CLI Convex
Execute os seguintes comandos no diretório `packages/backend`:
```bash
cd packages/backend
# Configurar VAPID Public Key
npx convex env set VAPID_PUBLIC_KEY "BDerX0lK_hBCLpC7EbuxoJb2EJ7bcCLaHWxkNumVbvrx9w0MmJduHxJOP3WBwBP-SpQGcueMOyHCv7LFK3KnQks"
# Configurar VAPID Private Key
npx convex env set VAPID_PRIVATE_KEY "KWkJLMxCuCPQQiRXIJEt06G4pTdW0FaUN_vMyY02sc4"
# Configurar URL do Frontend
npx convex env set FRONTEND_URL "http://localhost:5173"
```
## Passo 2: Configurar VAPID Public Key no Frontend
Crie um arquivo `.env` no diretório `apps/web/` com o seguinte conteúdo:
```env
VITE_VAPID_PUBLIC_KEY=BDerX0lK_hBCLpC7EbuxoJb2EJ7bcCLaHWxkNumVbvrx9w0MmJduHxJOP3WBwBP-SpQGcueMOyHCv7LFK3KnQks
```
**Importante**:
- Após criar/modificar o `.env`, reinicie o servidor de desenvolvimento do frontend
- O arquivo `.env` já está no `.gitignore`, então não será commitado
## Passo 3: Verificar Configuração
### Verificar no Convex Dashboard:
1. Acesse https://dashboard.convex.dev
2. Vá em **Settings** > **Environment Variables**
3. Verifique se as 3 variáveis estão listadas
### Verificar no Frontend:
1. Execute o frontend: `cd apps/web && bun run dev`
2. Abra o DevTools (F12)
3. Vá em **Console** e execute: `console.log(import.meta.env.VITE_VAPID_PUBLIC_KEY)`
4. Deve exibir a chave pública (ou `undefined` se não estiver configurado)
## Chaves Geradas
As seguintes VAPID keys foram geradas para este projeto:
- **Public Key**: `BDerX0lK_hBCLpC7EbuxoJb2EJ7bcCLaHWxkNumVbvrx9w0MmJduHxJOP3WBwBP-SpQGcueMOyHCv7LFK3KnQks`
- **Private Key**: `KWkJLMxCuCPQQiRXIJEt06G4pTdW0FaUN_vMyY02sc4`
⚠️ **IMPORTANTE**:
- A Private Key deve ser mantida em segredo
- Nunca exponha a Private Key no frontend ou em código público
- Se suspeitar de comprometimento, regenere as keys com `bunx web-push generate-vapid-keys`

View File

@@ -1,400 +0,0 @@
const fs = require('fs');
const path = require('path');
const baseDir = 'apps/web/src/routes/(dashboard)/recursos-humanos/funcionarios';
const cadastroPath = path.join(baseDir, 'cadastro/+page.svelte');
const editarPath = path.join(baseDir, '[funcionarioId]/editar/+page.svelte');
console.log('Reading files...');
const cadastro = fs.readFileSync(cadastroPath, 'utf8');
// Create the edit file from scratch
const editContent = `<script lang="ts">
import { useConvexClient } from "convex-svelte";
import { api } from "@sgse-app/backend/convex/_generated/api";
import { goto } from "$app/navigation";
import { page } from "$app/stores";
import type { SimboloTipo } from "@sgse-app/backend/convex/schema";
import FileUpload from "$lib/components/FileUpload.svelte";
import {
maskCPF, maskCEP, maskPhone, maskDate, onlyDigits,
validateCPF, validateDate
} from "$lib/utils/masks";
import {
SEXO_OPTIONS, ESTADO_CIVIL_OPTIONS, GRAU_INSTRUCAO_OPTIONS,
GRUPO_SANGUINEO_OPTIONS, FATOR_RH_OPTIONS, APOSENTADO_OPTIONS, UFS_BRASIL
} from "$lib/utils/constants";
import { documentos, categoriasDocumentos, getDocumentosByCategoria } from "$lib/utils/documentos";
import ModelosDeclaracoes from "$lib/components/ModelosDeclaracoes.svelte";
const client = useConvexClient();
let funcionarioId = $derived($page.params.funcionarioId as string);
let simbolos: Array<{
_id: string;
nome: string;
tipo: SimboloTipo;
descricao: string;
}> = [];
let tipo: SimboloTipo = "cargo_comissionado";
let loading = $state(false);
let loadingData = $state(true);
let notice = $state<{ kind: "success" | "error"; text: string } | null>(null);
// Campos obrigatórios
let nome = $state("");
let matricula = $state("");
let cpf = $state("");
let rg = $state("");
let nascimento = $state("");
let email = $state("");
let telefone = $state("");
let endereco = $state("");
let cep = $state("");
let cidade = $state("");
let uf = $state("");
let simboloId = $state("");
let admissaoData = $state("");
// Dados Pessoais Adicionais
let nomePai = $state("");
let nomeMae = $state("");
let naturalidade = $state("");
let naturalidadeUF = $state("");
let sexo = $state("");
let estadoCivil = $state("");
let nacionalidade = $state("Brasileira");
// Documentos Pessoais
let rgOrgaoExpedidor = $state("");
let rgDataEmissao = $state("");
let carteiraProfissionalNumero = $state("");
let carteiraProfissionalSerie = $state("");
let carteiraProfissionalDataEmissao = $state("");
let reservistaNumero = $state("");
let reservistaSerie = $state("");
let tituloEleitorNumero = $state("");
let tituloEleitorZona = $state("");
let tituloEleitorSecao = $state("");
let pisNumero = $state("");
// Formação e Saúde
let grauInstrucao = $state("");
let formacao = $state("");
let formacaoRegistro = $state("");
let grupoSanguineo = $state("");
let fatorRH = $state("");
// Cargo e Vínculo
let descricaoCargo = $state("");
let nomeacaoPortaria = $state("");
let nomeacaoData = $state("");
let nomeacaoDOE = $state("");
let pertenceOrgaoPublico = $state(false);
let orgaoOrigem = $state("");
let aposentado = $state("nao");
// Dados Bancários
let contaBradescoNumero = $state("");
let contaBradescoDV = $state("");
let contaBradescoAgencia = $state("");
// Documentos (Storage IDs)
let documentosStorage: Record<string, string | undefined> = $state({});
async function loadSimbolos() {
const list = await client.query(api.simbolos.getAll, {} as any);
simbolos = list.map((s: any) => ({
_id: s._id,
nome: s.nome,
tipo: s.tipo,
descricao: s.descricao
}));
}
async function loadFuncionario() {
try {
const func = await client.query(api.funcionarios.getById, { id: funcionarioId as any });
// Preencher campos
nome = func.nome;
matricula = func.matricula;
cpf = maskCPF(func.cpf);
rg = func.rg;
nascimento = func.nascimento;
email = func.email;
telefone = maskPhone(func.telefone);
endereco = func.endereco;
cep = maskCEP(func.cep);
cidade = func.cidade;
uf = func.uf;
simboloId = func.simboloId;
tipo = func.simboloTipo;
admissaoData = func.admissaoData || "";
// Dados adicionais
nomePai = func.nomePai || "";
nomeMae = func.nomeMae || "";
naturalidade = func.naturalidade || "";
naturalidadeUF = func.naturalidadeUF || "";
sexo = func.sexo || "";
estadoCivil = func.estadoCivil || "";
nacionalidade = func.nacionalidade || "Brasileira";
rgOrgaoExpedidor = func.rgOrgaoExpedidor || "";
rgDataEmissao = func.rgDataEmissao || "";
carteiraProfissionalNumero = func.carteiraProfissionalNumero || "";
carteiraProfissionalSerie = func.carteiraProfissionalSerie || "";
carteiraProfissionalDataEmissao = func.carteiraProfissionalDataEmissao || "";
reservistaNumero = func.reservistaNumero || "";
reservistaSerie = func.reservistaSerie || "";
tituloEleitorNumero = func.tituloEleitorNumero || "";
tituloEleitorZona = func.tituloEleitorZona || "";
tituloEleitorSecao = func.tituloEleitorSecao || "";
pisNumero = func.pisNumero || "";
grauInstrucao = func.grauInstrucao || "";
formacao = func.formacao || "";
formacaoRegistro = func.formacaoRegistro || "";
grupoSanguineo = func.grupoSanguineo || "";
fatorRH = func.fatorRH || "";
descricaoCargo = func.descricaoCargo || "";
nomeacaoPortaria = func.nomeacaoPortaria || "";
nomeacaoData = func.nomeacaoData || "";
nomeacaoDOE = func.nomeacaoDOE || "";
pertenceOrgaoPublico = func.pertenceOrgaoPublico || false;
orgaoOrigem = func.orgaoOrigem || "";
aposentado = func.aposentado || "nao";
contaBradescoNumero = func.contaBradescoNumero || "";
contaBradescoDV = func.contaBradescoDV || "";
contaBradescoAgencia = func.contaBradescoAgencia || "";
// Documentos
documentosStorage = {};
documentos.forEach(doc => {
const storageId = (func as any)[doc.campo];
if (storageId) {
documentosStorage[doc.campo] = storageId;
}
});
} catch (error) {
console.error("Erro ao carregar funcionário:", error);
notice = { kind: "error", text: "Erro ao carregar dados do funcionário" };
} finally {
loadingData = false;
}
}
async function fillFromCEP(cepValue: string) {
const cepDigits = onlyDigits(cepValue);
if (cepDigits.length !== 8) return;
try {
const res = await fetch(\`https://viacep.com.br/ws/\${cepDigits}/json/\`);
const data = await res.json();
if (!data || data.erro) return;
const enderecoFull = [data.logradouro, data.bairro].filter(Boolean).join(", ");
endereco = enderecoFull;
cidade = data.localidade || "";
uf = data.uf || "";
} catch {}
}
async function handleDocumentoUpload(campo: string, file: File) {
try {
const uploadUrl = await client.mutation(api.documentos.generateUploadUrl, {});
const result = await fetch(uploadUrl, {
method: "POST",
headers: { "Content-Type": file.type },
body: file,
});
const { storageId } = await result.json();
documentosStorage[campo] = storageId;
} catch (err: any) {
throw new Error(err?.message || "Erro ao fazer upload");
}
}
async function handleDocumentoRemove(campo: string) {
documentosStorage[campo] = undefined;
}
async function handleSubmit() {
if (!nome || !matricula || !cpf || !rg || !nascimento || !email || !telefone) {
notice = { kind: "error", text: "Preencha todos os campos obrigatórios" };
return;
}
if (!validateCPF(cpf)) {
notice = { kind: "error", text: "CPF inválido" };
return;
}
if (!validateDate(nascimento)) {
notice = { kind: "error", text: "Data de nascimento inválida" };
return;
}
if (!simboloId) {
notice = { kind: "error", text: "Selecione um símbolo" };
return;
}
try {
loading = true;
const payload = {
nome,
matricula,
cpf: onlyDigits(cpf),
rg: onlyDigits(rg),
nascimento,
email,
telefone: onlyDigits(telefone),
endereco,
cep: onlyDigits(cep),
cidade,
uf: uf.toUpperCase(),
simboloId: simboloId as any,
simboloTipo: tipo,
admissaoData: admissaoData || undefined,
nomePai: nomePai || undefined,
nomeMae: nomeMae || undefined,
naturalidade: naturalidade || undefined,
naturalidadeUF: naturalidadeUF ? naturalidadeUF.toUpperCase() : undefined,
sexo: sexo || undefined,
estadoCivil: estadoCivil || undefined,
nacionalidade: nacionalidade || undefined,
rgOrgaoExpedidor: rgOrgaoExpedidor || undefined,
rgDataEmissao: rgDataEmissao || undefined,
carteiraProfissionalNumero: carteiraProfissionalNumero || undefined,
carteiraProfissionalSerie: carteiraProfissionalSerie || undefined,
carteiraProfissionalDataEmissao: carteiraProfissionalDataEmissao || undefined,
reservistaNumero: reservistaNumero || undefined,
reservistaSerie: reservistaSerie || undefined,
tituloEleitorNumero: tituloEleitorNumero || undefined,
tituloEleitorZona: tituloEleitorZona || undefined,
tituloEleitorSecao: tituloEleitorSecao || undefined,
pisNumero: pisNumero || undefined,
grauInstrucao: grauInstrucao || undefined,
formacao: formacao || undefined,
formacaoRegistro: formacaoRegistro || undefined,
grupoSanguineo: grupoSanguineo || undefined,
fatorRH: fatorRH || undefined,
descricaoCargo: descricaoCargo || undefined,
nomeacaoPortaria: nomeacaoPortaria || undefined,
nomeacaoData: nomeacaoData || undefined,
nomeacaoDOE: nomeacaoDOE || undefined,
pertenceOrgaoPublico: pertenceOrgaoPublico || undefined,
orgaoOrigem: orgaoOrigem || undefined,
aposentado: aposentado || undefined,
contaBradescoNumero: contaBradescoNumero || undefined,
contaBradescoDV: contaBradescoDV || undefined,
contaBradescoAgencia: contaBradescoAgencia || undefined,
...Object.fromEntries(
Object.entries(documentosStorage).map(([key, value]) => [key, value as any])
),
};
await client.mutation(api.funcionarios.update, { id: funcionarioId as any, ...payload as any });
notice = { kind: "success", text: "Funcionário atualizado com sucesso!" };
setTimeout(() => goto("/recursos-humanos/funcionarios"), 600);
} catch (e: any) {
notice = { kind: "error", text: "Erro ao atualizar funcionário." };
} finally {
loading = false;
}
}
async function init() {
await loadSimbolos();
await loadFuncionario();
}
$effect(() => {
if (funcionarioId) {
init();
}
});
</script>
{#if loadingData}
<div class="flex items-center justify-center min-h-screen">
<span class="loading loading-spinner loading-lg"></span>
</div>
{:else}
<main class="container mx-auto px-4 py-4 max-w-7xl">
<!-- Breadcrumb -->
<div class="text-sm breadcrumbs mb-4">
<ul>
<li><a href="/recursos-humanos" class="text-primary hover:underline">Recursos Humanos</a></li>
<li><a href="/recursos-humanos/funcionarios" class="text-primary hover:underline">Funcionários</a></li>
<li>Editar</li>
</ul>
</div>
<!-- Cabeçalho -->
<div class="mb-6">
<div class="flex items-center gap-4 mb-2">
<div class="p-3 bg-yellow-500/20 rounded-xl">
<svg xmlns="http://www.w3.org/2000/svg" class="h-8 w-8 text-yellow-600" fill="none" viewBox="0 0 24 24" stroke="currentColor">
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M11 5H6a2 2 0 00-2 2v11a2 2 0 002 2h11a2 2 0 002-2v-5m-1.414-9.414a2 2 0 112.828 2.828L11.828 15H9v-2.828l8.586-8.586z" />
</svg>
</div>
<div>
<h1 class="text-3xl font-bold text-primary">Editar Funcionário</h1>
<p class="text-base-content/70">Atualize as informações do funcionário</p>
</div>
</div>
</div>
<!-- Alertas -->
{#if notice}
<div class="alert mb-6 shadow-lg" class:alert-success={notice.kind === "success"} class:alert-error={notice.kind === "error"}>
<svg xmlns="http://www.w3.org/2000/svg" class="stroke-current shrink-0 h-6 w-6" fill="none" viewBox="0 0 24 24">
{#if notice.kind === "success"}
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M9 12l2 2 4-4m6 2a9 9 0 11-18 0 9 9 0 0118 0z" />
{:else}
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M10 14l2-2m0 0l2-2m-2 2l-2-2m2 2l2 2m7-2a9 9 0 11-18 0 9 9 0 0118 0z" />
{/if}
</svg>
<span>{notice.text}</span>
</div>
{/if}
<!-- Formulário de Edição -->
<form class="space-y-6" onsubmit={(e) => { e.preventDefault(); handleSubmit(); }}>
`;
// Extract form from cadastro (from line 294 to 1181)
const cadastroLines = cadastro.split('\n');
const formLines = cadastroLines.slice(293, 1181); // Get lines 294-1181 (0-indexed)
const formContent = formLines.join('\n');
// Replace "Cadastrar" with "Atualizar" in button
const fixedForm = formContent
.replace('Cadastrar Funcionário', 'Atualizar Funcionário')
.replace('Cadastrando...', 'Atualizando...');
const finalContent = editContent + fixedForm + '\n </form>\n </main>\n{/if}';
fs.writeFileSync(editarPath, finalContent, 'utf8');
console.log(`✓ File created successfully!`);
console.log(` Total lines: ${finalContent.split('\n').length}`);
console.log(` File saved to: ${editarPath}`);