Commit graph

4 commits

Author SHA1 Message Date
senke
41f4a50618 feat(auth): RGPD/COPPA age gate at registration (16+ minimum)
v1.0.10 légal item 2. The signup endpoint /api/v1/auth/register and
its frontend form now require a date of birth and refuse registrations
where the registrant would be < 16 years old at registration time.

Threshold rationale :
  COPPA (US, < 13 forbidden) + RGPD strict (< 16 needs parental
  consent in every EU member state at the highest interpretation).
  16 is the conservative single cutoff that satisfies both regimes
  without per-jurisdiction branching. If a future market needs a
  different threshold, change MinRegistrationAgeYears in
  internal/core/auth/service.go ; the frontend reads the same
  constant so they stay aligned.

Backend changes
  * dto.RegisterRequest gets a `Birthdate string` field, validated
    `required,datetime=2006-01-02` so swaggo / orval emit the right
    OpenAPI schema and the validator catches malformed values
    before the handler even runs.
  * AuthService.Register signature is now
    (ctx, email, username, password, birthdate *time.Time). The
    pointer lets internal seed paths / tests pass nil while the
    public handler always supplies a parsed value.
  * Age check uses a yearsBetween helper that handles the "anniversary
    hasn't passed yet this year" case correctly (someone born
    2008-05-01 is 16 on 2008+16-05-01, not on 2008+16-01-01).
  * New sentinel auth.ErrUnderage ; handler maps it to 400 with a
    friendly message ("You must be at least 16 years old to register")
    so the SPA can render the right copy without parsing the message.
  * 11 test call sites updated : test-only paths pass nil ; the
    public-handler test (TestRegister_Success) and the in-package
    handler test pass a fixture Birthdate "2000-01-15".

Frontend changes
  * RegisterFormData type + zod schema in RegisterForm.tsx + initial
    form state get a `birthdate` field.
  * RegisterPageForm.tsx renders an `<AuthInput type="date">` with a
    `max=` attr 16 years ago today (UX guard ; legal floor stays in
    the API).
  * useRegisterPage's validate() computes age client-side with the
    same algorithm as backend ; emits localised errors
    `birthdateRequired` / `birthdateInvalid` / `birthdateUnderage`
    so the user gets immediate feedback.
  * services/api/auth.ts RegisterRequest interface + register()
    body include the new field.

Tests : `go test ./internal/core/auth ./internal/handlers -short`
passes ; `tsc --noEmit` clean ; `eslint src` 754 (baseline unchanged).

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-01 18:05:47 +02:00
senke
083b5718a7 feat(auth): defer JWT to post-verify + verify-email header (v1.0.9 items 1.3+1.4)
Item 1.4 — Register no longer issues an access+refresh token pair. The
prior flow set httpOnly cookies at register but the AuthMiddleware
refused them on every protected route until the user had verified
their email (`core/auth/service.go:527`). Users ended up with dead
credentials and a "logged in but locked out" UX. Register now returns
{user, verification_required: true, message} and the SPA's existing
"check your email" notice fires naturally.

Item 1.3 — `POST /auth/verify-email` reads the token from the
`X-Verify-Token` header in preference to the `?token=…` query param.
Query param logged a deprecation warning but stays accepted so emails
dispatched before this release still work. Headers don't leak through
proxy/CDN access logs that record URL but not headers.

Tests: 18 test files updated (sed `_, _, err :=` → `_, err :=` for the
new Register signature). `core/auth/handler_test.go` gets a
`registerVerifyLogin` helper for tests that exercise post-login flows
(refresh, logout). Two new E2E `@critical` specs lock in the defer-JWT
contract and the header read-path.

OpenAPI + orval regenerated to reflect the new RegisterResponse shape
and the verify-email header parameter.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-04-26 22:56:31 +02:00
senke
9ed60e5719 fix(backend,infra): send real verification emails + fail-loud in prod
Registration was setting `IsVerified: true` at user-create time and the
"send email" block was a `logger.Info("Sending verification email")` — no
SMTP call. On production this meant any attacker-typo or typosquat email
got a fully-verified account because the user never had to prove
ownership. In development the hack let people "log in" without checking
MailHog, masking SMTP misconfiguration.

Changes:

  * `core/auth/service.go`: new users start with `IsVerified: false`. The
    existing `POST /auth/verify-email` flow (unchanged) flips the bit
    when the user clicks the link.
  * Registration now calls `emailService.SendVerificationEmail(...)` for
    real. On SMTP failure the handler returns `500` in production (no
    stuck account with no recovery path) and logs a warning in
    development (local sign-ups keep flowing).
  * Same treatment for `password_reset_handler.RequestPasswordReset` —
    production fails loud instead of returning the generic success
    message after a silent SMTP drop.
  * New helper `isProductionEnv()` centralises the
    `APP_ENV=="production"` check in both `core/auth` and `handlers`.
  * `docker-compose.yml` + `docker-compose.dev.yml` now ship MailHog
    (`mailhog/mailhog:v1.0.1`, SMTP 1025, UI 8025). Backend dev env
    vars `SMTP_HOST=mailhog SMTP_PORT=1025` pre-wired so dev sign-ups
    actually deliver.

Tests: auth test mocks updated (`expectRegister` adds a
`SendVerificationEmail` mock). `TestAuthService_Login_Success` +
`TestAuthHandler_Login_Success` flip `is_verified` directly after
`Register` to simulate the verification click.
`TestLogin_EmailNotVerified` now asserts `403` (previously asserted
`200` — the test was codifying the bug this commit fixes).

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-16 14:52:46 +02:00
senke
b28d0e7eac [T0-006] test(backend): Ajout tests pour frontend_log_handler
- Tests complets pour frontend_log_handler.go (12 tests)
- Tests couvrent NewFrontendLogHandler et ReceiveLog
- Tests pour tous les niveaux de log (DEBUG, INFO, WARN, ERROR)
- Tests pour gestion des erreurs et validation JSON
- Couverture actuelle: 30.6% (objectif: 80%)

Files: veza-backend-api/internal/handlers/frontend_log_handler_test.go
       VEZA_ROADMAP.json
Hours: 16 estimated, 23 actual
2026-01-04 01:44:22 +01:00