Tier: Foundational · Status: Full · Java original:
firefly-common-validators· .NET project:FireflyFramework.Validators
validators is the canonical input-validation tier — pure
functions that return nil on success or an error wrapping
validators.ErrInvalid with a human-readable reason on failure. Every
function is allocation-free for the success path and safe for
concurrent use.
Coverage:
| Validator | What it checks |
|---|---|
ValidateIBAN |
ISO 13616 mod-97 + per-country length (76 country codes ship in the table) |
ValidateBIC |
ISO 9362 — 8 or 11 alnum chars |
ValidateLuhn |
Luhn checksum (credit cards, IMEI, SIN) |
ValidateCreditCard |
Luhn + length 12..19 |
ValidatePhoneE164 |
+<country><subscriber>, 8..16 chars |
ValidateCurrency |
ISO 4217 — 3 uppercase letters |
ValidateEmail |
RFC 5322 syntactic |
ValidatePassword |
Configurable policy (length, upper, lower, digit, symbol) |
ValidateSortCode |
UK 6-digit sort code (XXXXXX or XX-XX-XX) |
ValidateBSB |
AU 6-digit Bank-State-Branch |
ValidateSSN |
US Social Security Number |
ValidateVAT |
EU-style VAT (CC + 2..12 alnum) |
ValidateDNI |
Spanish DNI with letter checksum |
ValidateNIE |
Spanish NIE (X/Y/Z prefix variant) |
ValidateNIF |
Spanish NIF (DNI ∪ NIE) |
The .NET port uses validation attributes ([ValidIban]); Java uses
Jakarta Bean Validation annotations. Go has no annotation runtime, so
struct tags + a third-party library would be the closest equivalent —
but every adapter introduces a different set of trade-offs. By
exposing the validators as plain functions returning error, services
can:
- Call them directly from CQRS handler
Validate()methods. - Adapt them to
go-playground/validator/v10custom tags in three lines of code. - Combine them via
errors.Joinfor multi-field validation.
var ErrInvalid = errors.New("firefly/validators: invalid")
func ValidateIBAN(s string) error
func ValidateBIC(s string) error
func ValidateLuhn(s string) error
func ValidateCreditCard(s string) error
func ValidatePhoneE164(s string) error
func ValidateCurrency(s string) error
func ValidateEmail(s string) error
func ValidatePassword(s string, p PasswordPolicy) error
func ValidateSortCode(s string) error
func ValidateBSB(s string) error
func ValidateSSN(s string) error
func ValidateVAT(s string) error
func ValidateDNI(s string) error
func ValidateNIE(s string) error
func ValidateNIF(s string) error
type PasswordPolicy struct {
MinLength int
RequireUpper bool
RequireLower bool
RequireDigit bool
RequireSym bool
}
func DefaultPasswordPolicy() PasswordPolicy
var IBANCountryLengths map[string]intimport (
"errors"
"github.com/fireflyframework/fireflyframework-go/validators"
"github.com/fireflyframework/fireflyframework-go/kernel"
)
type RegisterCmd struct {
Email string
Password string
IBAN string
}
func (c RegisterCmd) Validate() error {
var errs []error
if err := validators.ValidateEmail(c.Email); err != nil {
errs = append(errs, fmt.Errorf("email: %w", err))
}
if err := validators.ValidatePassword(c.Password, validators.DefaultPasswordPolicy()); err != nil {
errs = append(errs, fmt.Errorf("password: %w", err))
}
if err := validators.ValidateIBAN(c.IBAN); err != nil {
errs = append(errs, fmt.Errorf("iban: %w", err))
}
if len(errs) > 0 {
return kernel.NewValidation(errors.Join(errs...).Error())
}
return nil
}cd validators
go test ./...Suite includes mod-97 round-trips on canonical IBAN test vectors (GB, DE, FR, ES), Luhn against a known-good and known-bad pair, DNI checksum letter table, and password-policy boundary cases.