Liga o adapter SMTP existente (packages/integrations, já era fail-soft) a um consumidor de verdade e adiciona o fluxo completo de recuperação de senha, faltante desde a Fase 1. - UsersService.invite() agora envia e-mail com a senha temporária (mantém o retorno na resposta também — dupla entrega, eden.md §4.8). - POST /v1/auth/forgot-password + POST /v1/auth/reset-password: token de 256 bits, só o hash SHA-256 persistido (users.reset_token_hash/ reset_token_expires_at — colunas que já existiam desde a baseline da Fase 1, nunca usadas até agora), validade de 1h, uso único, revoga todas as sessões ativas do usuário ao concluir. Mesma disciplina anti-enumeração do login: resposta idêntica para e-mail cadastrado ou não. - Frontend: link "Esqueci minha senha" no LoginPage, novas ForgotPasswordPage/ResetPasswordPage. Teste de integração novo (password-reset.spec.ts, 3 testes) usa vi.mock para interceptar sendMail e recuperar o token real do corpo do e-mail — única forma de testar o caminho feliz de ponta a ponta, já que o token nunca é devolvido na resposta da API. Suíte completa: 33/33 (30→33). pnpm turbo run typecheck build (28/28). Testado ao vivo através do proxy same-origin: anti-enumeração confirmada com curl real, token gravado no Postgres, token bogus rejeitado (400). Claude-Session: https://claude.ai/code/session_01BcWWuKfykGtUweXmHD6cKx Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
47 lines
1.3 KiB
JSON
47 lines
1.3 KiB
JSON
{
|
|
"name": "@eden/api",
|
|
"version": "0.1.0",
|
|
"private": true,
|
|
"scripts": {
|
|
"build": "tsc -p tsconfig.json",
|
|
"start": "node dist/main.js",
|
|
"dev": "tsx watch src/main.ts",
|
|
"typecheck": "tsc -p tsconfig.json --noEmit && tsc -p tsconfig.test.json",
|
|
"lint": "echo 'no linter configured yet'",
|
|
"test": "vitest run",
|
|
"test:watch": "vitest"
|
|
},
|
|
"dependencies": {
|
|
"@eden/config": "workspace:*",
|
|
"@eden/database": "workspace:*",
|
|
"@eden/domain-shared": "workspace:*",
|
|
"@eden/integrations": "workspace:*",
|
|
"@nestjs/common": "^10.4.15",
|
|
"@nestjs/core": "^10.4.15",
|
|
"@nestjs/platform-express": "^10.4.15",
|
|
"@nestjs/swagger": "^8.1.0",
|
|
"@nestjs/terminus": "^10.2.3",
|
|
"argon2": "^0.41.1",
|
|
"class-transformer": "^0.5.1",
|
|
"class-validator": "^0.14.1",
|
|
"express": "^4.21.2",
|
|
"jsonwebtoken": "^9.0.2",
|
|
"otplib": "^13.5.0",
|
|
"reflect-metadata": "^0.2.2",
|
|
"rxjs": "^7.8.1"
|
|
},
|
|
"devDependencies": {
|
|
"@nestjs/testing": "^10.4.15",
|
|
"@swc/core": "^1.10.1",
|
|
"@types/express": "^5.0.0",
|
|
"@types/jsonwebtoken": "^9.0.7",
|
|
"@types/node": "^22.10.5",
|
|
"@types/supertest": "^6.0.2",
|
|
"supertest": "^7.0.0",
|
|
"tsx": "^4.19.2",
|
|
"typescript": "^5.7.3",
|
|
"unplugin-swc": "^1.5.1",
|
|
"vitest": "^2.1.8"
|
|
}
|
|
}
|