Module path: internal/modules/auth
POST /api/v1/auth/signupPOST /api/v1/auth/loginPOST /api/v1/auth/verify-emailPOST /api/v1/auth/resend-verificationPOST /api/v1/auth/forgot-passwordPOST /api/v1/auth/reset-passwordPOST /api/v1/auth/change-password/request-otpPOST /api/v1/auth/change-password/confirmPOST /api/v1/auth/refreshPOST /api/v1/auth/logout
Purpose:
- create account via goAuth and persist display-name update.
Policy chain:
RequireJSONRateLimitWithKeyer(..., "auth.signup", ScopeIP, KeyByIP())when limiter enabled
Flow:
- Handler
SignupvalidatessignupRequest. - Service
Signupcallsengine.CreateAccount(...). - Service updates name with repo
UpdateUserName(...). - Service requests email verification challenge and sends OTP email (best-effort).
- Response returns user envelope.
Transaction:
- no explicit service transaction wrapper.
Side effects:
- auth account created in auth persistence layer
- rate-limit bucket incremented by IP
Failure mapping:
- existing account ->
409 - invalid payload/password policy ->
400 - rate limited ->
429 - auth dependency failure ->
503
Policy chain:
RequireJSONRateLimitWithKeyer(..., "auth.login", ScopeIP, KeyByIP())when enabled
Flow:
- Handler
Login-> ServiceLogin. - Service calls
engine.Login(identifier,password). - Service parses JWT
expclaim and returns token response.
Side effects:
- session/auth state updated by goAuth
Failures:
- invalid credentials ->
401 - rate-limited ->
429
Policy chain:
RequireJSONRateLimitWithKeyer(..., "auth.verify_email", ScopeIP, KeyByIP())when enabled
Flow:
- Handler
VerifyEmail-> ServiceVerifyEmail. - Service validates OTP payload (
verificationId+code) or legacy token payload. - Service calls
engine.ConfirmEmailVerificationCode(verificationId, code)for OTP.
Failures:
- invalid/expired OTP or token ->
400 - rate-limited ->
429
Policy chain:
RequireJSONRateLimitWithKeyer(..., "auth.resend_verification", ScopeIP, KeyByIP())when enabled
Flow:
- Handler
ResendVerification-> ServiceResendVerification. - Service calls
engine.RequestEmailVerification(email). - Service sends OTP email for pending accounts and returns generic status.
Policy chain:
RequireJSONRateLimitWithKeyer(..., "auth.forgot_password", ScopeIP, KeyByIP())when enabled
Flow:
- Handler
ForgotPassword-> ServiceForgotPassword. - Service calls
engine.RequestPasswordReset(email)with OTP strategy. - Service splits the OTP challenge (
challengeId.code) and emails the code. - Response remains enumeration-safe and includes generic message (challenge may be present).
Policy chain:
RequireJSONRateLimitWithKeyer(..., "auth.reset_password", ScopeIP, KeyByIP())when enabled
Flow:
- Handler
ResetPassword-> ServiceResetPassword. - Service accepts OTP challenge (
challengeId+code) and joins it for goAuth confirm. - Legacy
tokenpayload remains temporarily supported for migration compatibility.
Policy chain:
RequireJSONAuthRequired(engine, mode)RateLimitWithKeyer(..., "auth.change_password_request", ScopeUser, KeyByUser())when enabled
Flow:
- Handler reads authenticated principal from context.
- Service validates current password using
engine.Login(email,currentPassword). - Service calls
engine.RequestPasswordReset(email)and sends password-change OTP email.
Policy chain:
RequireJSONAuthRequired(engine, mode)RateLimitWithKeyer(..., "auth.change_password_confirm", ScopeUser, KeyByUser())when enabled
Flow:
- Handler reads authenticated principal from context.
- Service re-validates current password.
- Service confirms OTP reset challenge and emits password-changed notification email.
Policy chain:
RequireJSONRateLimitWithKeyer(..., "auth.refresh", ScopeIP, KeyByIP())when enabled
Flow:
- Handler
Refresh-> ServiceRefresh. - Service calls
engine.Refresh(refreshToken). - Service returns normalized access/refresh payload.
Note:
- compatibility endpoint retained for tooling.
Policy chain:
AuthRequired(engine, mode)RateLimitWithKeyer(..., "auth.logout", ScopeUser, KeyByUserOrProjectOrTokenHash(16))when enabled
Flow:
- Handler reads bearer token from Authorization header.
- Service
Logoutcallsengine.LogoutByAccessToken(token).
Side effects:
- refresh/session invalidation in goAuth backing store.
- 429 on repeated signup/login:
- Check auth IP limiter keys and traffic profile.
- logout returns 401:
- Check Authorization header format and token freshness.
- verify/reset loops failing:
- Check OTP expiry, challengeId/code pairing, and 6-digit code formatting.
- Keep public auth routes JSON + IP rate-limited.
- Keep logout authenticated.
- Do not add project/RBAC policies to public auth entry routes.
- Keep auth service error mapping consistent with API error codes.