package usecase import ( "context" "gateway/internal/model/member/domain/enum" ) // GenerateOTPRequest creates a new OTP challenge. type GenerateOTPRequest struct { TenantID string UID string Purpose enum.OTPPurpose Target string // email or phone for verification flows Identifier string // optional audit key when uid is empty } // VerifyOTPRequest validates a challenge. type VerifyOTPRequest struct { TenantID string UID string // must match challenge UID when the challenge was issued with a UID ChallengeID string Code string Purpose enum.OTPPurpose } // MatchChallengeRequest validates persisted challenge metadata before orchestration. type MatchChallengeRequest struct { ChallengeID string TenantID string Purpose enum.OTPPurpose RequireUID bool RequireTarget bool } // OTPUseCase is the purpose-agnostic OTP primitive. type OTPUseCase interface { Generate(ctx context.Context, req *GenerateOTPRequest) (*OTPChallengeDTO, string, error) // Verify returns the challenge target (e.g. email/phone) after successful validation. Verify(ctx context.Context, req *VerifyOTPRequest) (target string, err error) Invalidate(ctx context.Context, challengeID string) error // GetChallenge returns persisted challenge metadata for orchestration (e.g. register resend). GetChallenge(ctx context.Context, challengeID string) (*OTPChallengeInfo, error) // MatchChallenge loads a challenge and validates tenant / purpose / required fields. MatchChallenge(ctx context.Context, req *MatchChallengeRequest) (*OTPChallengeInfo, error) } // OTPChallengeInfo is read-only challenge metadata. type OTPChallengeInfo struct { TenantID string UID string Purpose enum.OTPPurpose Target string }