package auth

import "errors"

// Sentinel errors emitted by Service methods. Handlers translate them
// into HTTP responses; callers in tests can match on them with
// errors.Is.
var (
	// ErrChallengeNotFound is returned when a confirm-email-code request
	// references a challenge_id that does not exist, has already been
	// consumed, or has expired. Returned as a single sentinel because the
	// API surface deliberately does not differentiate between these cases
	// — distinguishing them would leak whether a challenge_id was ever
	// valid, which is signal an attacker should not have.
	ErrChallengeNotFound = errors.New("auth: challenge is not redeemable")

	// ErrTooManyAttempts is returned when confirm-email-code increments
	// the attempts counter past the configured ceiling. The challenge row
	// remains in the database with its incremented counter so further
	// attempts on the same challenge_id continue to fail with the same
	// error until the row expires.
	ErrTooManyAttempts = errors.New("auth: too many attempts")

	// ErrCodeMismatch is returned when the supplied code does not match
	// the stored bcrypt hash. The challenge stays un-consumed so the user
	// can try again — bounded by ErrTooManyAttempts.
	ErrCodeMismatch = errors.New("auth: code is incorrect")

	// ErrEmailPermanentlyBlocked is returned by SendEmailCode when the
	// supplied email maps to an existing account whose `permanent_block`
	// column is true. This is the only path that does not return an
	// opaque success shape.
	ErrEmailPermanentlyBlocked = errors.New("auth: email is permanently blocked")

	// ErrSessionNotFound is returned by GetSession (and the revoke
	// helpers in their look-it-up-after-zero-rows fallback) when the
	// device_session_id does not name a row in `device_sessions`.
	ErrSessionNotFound = errors.New("auth: session not found")
)
