diff --git a/internal/adapter/templates/templates/components/service/internal/adapter/memory/auth_code.go.tmpl b/internal/adapter/templates/templates/components/service/internal/adapter/memory/auth_code.go.tmpl index c9bc42e..f60ad1a 100644 --- a/internal/adapter/templates/templates/components/service/internal/adapter/memory/auth_code.go.tmpl +++ b/internal/adapter/templates/templates/components/service/internal/adapter/memory/auth_code.go.tmpl @@ -2,6 +2,7 @@ package memory import ( "context" + "log/slog" "sync" "time" @@ -31,6 +32,16 @@ func (r *AuthCodeRepository) Create(_ context.Context, code *domain.AuthCode) er cp := *code r.codes[code.ID] = &cp + + // In standalone dev mode the code lives only in memory and is lost on restart. + // Always log it so the developer can copy-paste the code from the terminal + // even when NOTIFY_URL is set and an email is also being delivered. + slog.Warn("[DEV] auth code created — use this code to log in", + "email", code.Email, + "purpose", code.Purpose, + "code", code.Code, + "expires_at", code.ExpiresAt.Format("15:04:05"), + ) return nil } diff --git a/internal/adapter/templates/templates/skeleton/CLAUDE.md.tmpl b/internal/adapter/templates/templates/skeleton/CLAUDE.md.tmpl index 7e60593..22a843b 100644 --- a/internal/adapter/templates/templates/skeleton/CLAUDE.md.tmpl +++ b/internal/adapter/templates/templates/skeleton/CLAUDE.md.tmpl @@ -49,7 +49,8 @@ - **No fake progress:** Never simulate progress with timers. Real progress comes from real events. - **Auth tokens:** 15-minute access tokens with embedded session ID (`sid`). Refresh via POST `/auth/refresh`. Session revocation invalidates all tokens for that session. - **Passwords:** Bcrypt cost 12, min 8 chars, max 72. Hashing lives in `pkg/auth/password.go`. Never store plaintext. -- **Auth codes:** OTP/magic link/reset codes are single-use and time-limited. In dev mode (`NOTIFY_URL` unset), codes are logged to stdout. In production, emails go through the notify service (`NOTIFY_URL`/`NOTIFY_API_KEY`/`NOTIFY_HOST`/`NOTIFY_FROM`). +- **Auth codes:** OTP/magic link/reset codes are single-use and time-limited. In standalone dev mode (no `DATABASE_URL`), the code is **always** logged to stdout as `[DEV] auth code created — use this code to log in code=XXXXXX` — check the server terminal to get it. This works even when `NOTIFY_URL` is set. In production (with `DATABASE_URL`), emails go through the notify service (`NOTIFY_URL`/`NOTIFY_API_KEY`/`NOTIFY_HOST`/`NOTIFY_FROM`). +- **Dev user:** Set `DEV_USER_EMAIL=you@example.com` (and optionally `DEV_USER_PASSWORD`) to seed your account into the in-memory store on startup so it survives restarts without re-registering. ## Architecture