package identity import ( "context" "errors" "fmt" "log" ) // UserVerificationStatus represents the current verification status of a user type UserVerificationStatus string const ( // StatusUnverified means the user has not been verified at all StatusUnverified UserVerificationStatus = "Unverified" // StatusVerified means the user's citizenship is verified but not necessarily eligible StatusVerified UserVerificationStatus = "Verified" // StatusFullyEligible means the user is both verified and eligible StatusFullyEligible UserVerificationStatus = "Fully Eligible" ) // VerificationResult holds the results of a verification attempt type VerificationResult struct { // Status indicates the verification level achieved Status UserVerificationStatus // CitizenshipVerified indicates if the citizenship verification passed CitizenshipVerified bool // EligibilityVerified indicates if the eligibility verification passed EligibilityVerified bool // Error contains any error that occurred during verification Error error } // VerificationError defines a structured error for verification failures type VerificationError struct { Code string Message string } // Common error codes const ( ErrorCodeInvalidInput = "INVALID_INPUT" ErrorCodeServiceUnavailable = "SERVICE_UNAVAILABLE" ErrorCodeInvalidZKP = "INVALID_ZKP" ErrorCodeProviderNotFound = "PROVIDER_NOT_FOUND" ) // NewVerificationError creates a new verification error func NewVerificationError(code, message string) *VerificationError { return &VerificationError{ Code: code, Message: message, } } // Error implements the error interface func (e *VerificationError) Error() string { return fmt.Sprintf("%s: %s", e.Code, e.Message) } // VerificationService manages the verification process type VerificationService struct { providers map[string]VerificationProvider } // NewVerificationService creates a new verification service func NewVerificationService() *VerificationService { return &VerificationService{ providers: make(map[string]VerificationProvider), } } // RegisterProvider adds a verification provider to the service func (s *VerificationService) RegisterProvider(provider VerificationProvider) { country := provider.GetCountry() s.providers[country] = provider log.Printf("Registered verification provider for %s", country) } // VerifyUser verifies a user's identity and eligibility func (s *VerificationService) VerifyUser(ctx context.Context, country string, userData map[string]string) VerificationResult { result := VerificationResult{ Status: StatusUnverified, } // Validate input if country == "" { result.Error = NewVerificationError(ErrorCodeInvalidInput, "country is required") return result } // Get the appropriate provider for the requested country provider, exists := s.providers[country] if !exists { // If no provider is registered, get a default one provider = GetVerificationProvider(country) s.RegisterProvider(provider) } // Verify citizenship citizenshipVerified, err := provider.VerifyCitizenship(ctx, userData) if err != nil { log.Printf("Citizenship verification failed: %v", err) // Check for specific error types if ve, ok := err.(*VerificationError); ok { result.Error = ve } else if errors.Is(err, context.DeadlineExceeded) { result.Error = NewVerificationError(ErrorCodeServiceUnavailable, "verification service timed out") } else if errors.Is(err, context.Canceled) { result.Error = NewVerificationError(ErrorCodeServiceUnavailable, "verification request was canceled") } else { // Generic error handling if errStr := err.Error(); len(errStr) > 0 { if errStr == "invalid ZKP proof" { result.Error = NewVerificationError(ErrorCodeInvalidZKP, errStr) } else if errStr == "verification service unavailable" { result.Error = NewVerificationError(ErrorCodeServiceUnavailable, errStr) } else { result.Error = NewVerificationError(ErrorCodeServiceUnavailable, errStr) } } else { result.Error = NewVerificationError(ErrorCodeServiceUnavailable, "unknown verification error") } } return result } result.CitizenshipVerified = citizenshipVerified // If citizenship is verified, update the status if citizenshipVerified { result.Status = StatusVerified // Verify eligibility eligibilityVerified, err := provider.VerifyEligibility(ctx, userData) if err != nil { log.Printf("Eligibility verification failed: %v", err) // Still keep the verified status, but note the eligibility failure if ve, ok := err.(*VerificationError); ok { result.Error = ve } else { result.Error = NewVerificationError(ErrorCodeInvalidInput, err.Error()) } return result } result.EligibilityVerified = eligibilityVerified // If both citizenship and eligibility are verified, user is fully eligible if eligibilityVerified { result.Status = StatusFullyEligible } } log.Printf("Verification completed for %s: Status=%s, Citizenship=%v, Eligibility=%v", country, result.Status, result.CitizenshipVerified, result.EligibilityVerified) return result }