web/backend/secretapi/assurance.go

66 lines
2.0 KiB
Go

package main
import (
"fmt"
"strings"
"time"
)
const (
assuranceNone = "none"
assuranceSponsoredUnattested = "sponsored_unattested"
assuranceCryptoDirect = "crypto_direct_unattested"
assuranceOnrampAttested = "onramp_attested"
)
func normalizeAssuranceLevel(value string) string {
switch strings.ToLower(strings.TrimSpace(value)) {
case assuranceNone, assuranceSponsoredUnattested, assuranceCryptoDirect, assuranceOnrampAttested:
return strings.ToLower(strings.TrimSpace(value))
default:
return assuranceNone
}
}
func defaultAssuranceForSponsorshipMode(mode string) string {
switch strings.ToLower(strings.TrimSpace(mode)) {
case "self":
return assuranceCryptoDirect
case "sponsored", "sponsored_company":
return assuranceSponsoredUnattested
default:
return assuranceNone
}
}
func resolveMembershipAssurance(quote quoteRecord, req membershipConfirmRequest, now time.Time) (string, string, string, *time.Time, error) {
level := defaultAssuranceForSponsorshipMode(quote.SponsorshipMode)
attestedBy := ""
attestationID := ""
var attestedAt *time.Time
requestedLevel := normalizeAssuranceLevel(req.IdentityAssurance)
if requestedLevel != assuranceNone {
if requestedLevel == assuranceOnrampAttested {
if !strings.EqualFold(strings.TrimSpace(quote.SponsorshipMode), "self") {
return "", "", "", nil, fmt.Errorf("onramp_attested assurance requires self-paid quote")
}
attestedBy = strings.TrimSpace(req.IdentityAttestedBy)
attestationID = strings.TrimSpace(req.IdentityAttestationID)
if attestedBy == "" {
return "", "", "", nil, fmt.Errorf("identity_attested_by required for onramp_attested assurance")
}
level = assuranceOnrampAttested
attestedAt = &now
} else if requestedLevel != level {
return "", "", "", nil, fmt.Errorf("identity assurance mismatch for sponsorship mode")
}
}
return level, attestedBy, attestationID, attestedAt, nil
}
func isOnrampAttested(level string) bool {
return strings.EqualFold(strings.TrimSpace(level), assuranceOnrampAttested)
}