package repository import ( "context" "time" "gateway/internal/model/member/domain/enum" ) // OTPChallenge is persisted state for a single OTP issuance. type OTPChallenge struct { TenantID string UID string Purpose enum.OTPPurpose Target string CodeHash string Attempts int } // OTPChallengeStore stores OTP challenges (Redis). type OTPChallengeStore interface { Save(ctx context.Context, challengeID string, ch *OTPChallenge, ttl time.Duration) error Get(ctx context.Context, challengeID string) (*OTPChallenge, error) // IncrementAttempts atomically increments failed-verify count; returns ErrChallengeNotFound when missing. IncrementAttempts(ctx context.Context, challengeID string) (int, error) Delete(ctx context.Context, challengeID string) error } // VerifyRateStore enforces resend cooldown and daily verification caps. type VerifyRateStore interface { TryResendLock(ctx context.Context, key string, ttl time.Duration) (bool, error) IncrDaily(ctx context.Context, key string, ttl time.Duration) (int64, error) }