Foundation for the passwordless auth migration (ADR-0028 Phase A) and the BDD email-parallel strategy (ADR-0030). This PR ships only the infrastructure — no auth code yet ; that lands in subsequent PRs. Changes: - docker-compose.yml: add mailpit service (axllent/mailpit:latest), SMTP on :1025, HTTP UI/API on :8025, MP_MAX_MESSAGES=5000 - pkg/email/sender.go: provider-agnostic Sender interface + Message struct - pkg/email/smtp_sender.go: SMTPSender implementation (net/smtp), with Mailpit-friendly defaults (localhost:1025, no TLS, no AUTH), context- aware Send with timeout, supports plain text and multipart/alternative - pkg/config: AuthConfig.Email field + EmailConfig struct + GetEmailConfig getter + 7 new env vars (DLC_AUTH_EMAIL_*) + defaults - documentation/EMAIL.md: setup, inspection (UI + API), code examples, cross-refs to ADR-0028/0029/0030 Tests (pkg/email/smtp_sender_test.go): - validateMessage rejects missing fields, accepts minimal - buildRFC5322 plain-text path produces single-part text/plain with expected headers - buildRFC5322 multipart path produces multipart/alternative with both parts and a closing boundary - buildRFC5322 custom headers are canonicalised (lowercase keys → Title-Case) - NewSMTPSender defaults are Mailpit-friendly - Send respects context cancellation (no 10s wait when ctx cancelled) Race detector clean. Build clean. Vet clean. Out of scope for this PR (Phase A.2+): - BDD email-steps helper package (pkg/bdd/mailpit/, pkg/bdd/steps/email_steps.go) - magic_link_tokens table + repository - magic-link/request and magic-link/consume HTTP handlers - BDD scenarios for the magic-link flow
64 lines
1.8 KiB
YAML
64 lines
1.8 KiB
YAML
services:
|
|
postgres:
|
|
image: postgres:16-alpine
|
|
container_name: dance-lessons-coach-postgres
|
|
environment:
|
|
POSTGRES_USER: postgres
|
|
POSTGRES_PASSWORD: postgres
|
|
POSTGRES_DB: dance_lessons_coach
|
|
ports:
|
|
- "5432:5432"
|
|
volumes:
|
|
- postgres_data:/var/lib/postgresql/data
|
|
healthcheck:
|
|
test: ["CMD-SHELL", "pg_isready -U postgres"]
|
|
interval: 5s
|
|
timeout: 5s
|
|
retries: 5
|
|
networks:
|
|
- dance-lessons-coach-network
|
|
restart: unless-stopped
|
|
|
|
# Mailpit — local SMTP capture for dev + BDD parallel email tests.
|
|
# Cf. ADR-0029 (email infrastructure) and ADR-0030 (BDD parallel strategy).
|
|
# SMTP submission on :1025 (used by the app), HTTP UI + API on :8025
|
|
# (used by tests + manual inspection at http://localhost:8025).
|
|
mailpit:
|
|
image: axllent/mailpit:latest
|
|
container_name: dance-lessons-coach-mailpit
|
|
ports:
|
|
- "1025:1025" # SMTP submission
|
|
- "8025:8025" # HTTP UI / API
|
|
environment:
|
|
MP_MAX_MESSAGES: 5000
|
|
MP_SMTP_AUTH_ALLOW_INSECURE: 1 # local dev only - no TLS, no real auth
|
|
networks:
|
|
- dance-lessons-coach-network
|
|
restart: unless-stopped
|
|
|
|
# Application service (for reference)
|
|
# app:
|
|
# build: .
|
|
# container_name: dance-lessons-coach-app
|
|
# ports:
|
|
# - "8080:8080"
|
|
# environment:
|
|
# - DLC_DATABASE_HOST=postgres
|
|
# - DLC_DATABASE_PORT=5432
|
|
# - DLC_DATABASE_USER=postgres
|
|
# - DLC_DATABASE_PASSWORD=postgres
|
|
# - DLC_DATABASE_NAME=dance_lessons_coach
|
|
# - DLC_DATABASE_SSL_MODE=disable
|
|
# depends_on:
|
|
# postgres:
|
|
# condition: service_healthy
|
|
# restart: unless-stopped
|
|
|
|
volumes:
|
|
postgres_data:
|
|
driver: local
|
|
|
|
networks:
|
|
dance-lessons-coach-network:
|
|
name: dance-lessons-coach-network
|
|
driver: bridge |