feat: SMTP full ENV override, password reset flow, and E2E email testing

- SMTP: SMTP_HOST/PORT/USER/FROM/TLS now all have ENV override support
  (previously only SMTP_PASSWORD was env-aware). ENV takes priority over DB.
- docker-compose.yml: forward all SMTP_* env vars to app container + add
  Mailhog service (ports 1025 SMTP / 8025 HTTP, always available in dev)
- Password reset: PasswordResetToken Prisma model + authRouter with
  requestPasswordReset (timing-safe, no email enumeration) + resetPassword
- UI: /auth/forgot-password, /auth/reset-password/[token] pages +
  "Forgot password?" link on sign-in page
- E2E: Mailhog helpers (getLatestEmailTo, clearMailhog, extractUrlFromEmail)
  + invite-flow.spec.ts + password-reset.spec.ts

Co-Authored-By: claude-flow <ruv@ruv.net>
This commit is contained in:
2026-04-02 08:55:39 +02:00
parent e5ecea81c5
commit fceceeee4b
14 changed files with 1030 additions and 11 deletions
+21 -5
View File
@@ -34,6 +34,12 @@ services:
timeout: 3s
retries: 5
mailhog:
image: mailhog/mailhog
ports:
- "1025:1025" # SMTP
- "8025:8025" # HTTP API / Web UI
pgadmin:
image: dpage/pgadmin4
ports:
@@ -67,6 +73,13 @@ services:
AZURE_OPENAI_API_KEY: ${AZURE_OPENAI_API_KEY:-}
OPENAI_API_KEY: ${OPENAI_API_KEY:-}
GEMINI_API_KEY: ${GEMINI_API_KEY:-}
# SMTP — forwarded from host .env; overrides SystemSettings DB values
SMTP_HOST: ${SMTP_HOST:-}
SMTP_PORT: ${SMTP_PORT:-}
SMTP_USER: ${SMTP_USER:-}
SMTP_FROM: ${SMTP_FROM:-}
SMTP_TLS: ${SMTP_TLS:-}
SMTP_PASSWORD: ${SMTP_PASSWORD:-}
depends_on:
postgres:
condition: service_healthy
@@ -74,11 +87,10 @@ services:
condition: service_healthy
volumes:
- .:/app
# Anonymous volumes mask the bind-mount for generated/installed artefacts.
# Docker seeds them from the image layer on first start; they persist across restarts.
# pnpm stores all packages in the root node_modules/.pnpm virtual store — one volume covers it all.
- /app/node_modules
- /app/apps/web/.next
# Named volumes mask the bind-mount for generated/installed artefacts.
# Named (not anonymous) so they can be selectively removed: docker volume rm capakraken_node_modules
- capakraken_node_modules:/app/node_modules
- capakraken_next:/app/apps/web/.next
profiles:
- full
@@ -98,3 +110,7 @@ services:
volumes:
capakraken_pgdata:
name: capakraken_pgdata
capakraken_node_modules:
name: capakraken_node_modules
capakraken_next:
name: capakraken_next