validation

package module
v1.1.0 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Sep 6, 2026 License: MIT Imports: 8 Imported by: 0

README

validation

CI CodeQL Coverage Mutation Documentation Go Reference Release Go License

validation is a typed, transport-neutral validation package for Go 1.26 and later. Ordinary functions and Validator[T] are the primary API. Reports retain stable paths and rule codes without retaining rejected values.

Five-minute quickstart

package main

import (
	"fmt"

	validation "github.com/faustbrian/go-validation"
	"github.com/faustbrian/go-validation/rules"
)

func main() {
	ctx, _ := validation.NewContext(validation.DefaultLimits())
	validator := validation.All(validation.CollectAll,
		rules.RuneLength(3, 40),
		rules.Prefix("usr_"),
	)
	report := validator.Validate(ctx.WithPath(validation.Field("username")), "x")
	for _, violation := range report.Violations() {
		fmt.Println(violation.Path(), violation.Code())
	}
	// Output:
	// username rune_length
	// username prefix
}

Use validation.Value[T] when input presence matters:

missing := validation.Missing[string]()
null := validation.Null[string]()
empty := validation.Present("")
_ = []validation.Value[string]{missing, null, empty}

Core validators never perform I/O. Use AsyncValidator[T] and AsyncAll for context-aware external checks. Reflection is optional and isolated in structplan; typed plans require no tags or registry.

For context-aware validation, use report.Err() == nil as the complete success predicate. Cancellation and deadlines are terminal outcomes rather than validation findings, so a terminal report can still be Empty() and can retain completed warnings or errors.

Target-oriented integrations live under adapters/config, adapters/http, adapters/jsonapi, adapters/jsonrpc, and adapters/service. The original validationconfig, validationhttp, validationjsonapi, validationrpc, and validationservice paths remain compatible during their deprecation period.

Documentation

Local verification

make check

The Makefile delegates to the same released golib contract used by CI. Hosted CI is a release integrator's final external verification step, not a prerequisite for local development.

For ecosystem-wide selection and ownership guidance, see the versioned Golib ecosystem index and its Foundations family.

License

MIT. See LICENSE.

Documentation

Overview

Package validation provides typed, deterministic, bounded application validation without transport, binding, or persistence dependencies.

Index

Examples

Constants

This section is empty.

Variables

View Source
var (
	// ErrInvalid marks a non-empty validation result containing errors.
	ErrInvalid = errors.New("validation failed")
	// ErrLimitExceeded marks rejected work that exceeded a configured bound.
	ErrLimitExceeded = errors.New("validation limit exceeded")
	// ErrInvalidLimit marks an invalid Limits configuration.
	ErrInvalidLimit = errors.New("invalid validation limit")
	// ErrValidatorPanic is the safe cause used for an isolated custom panic.
	ErrValidatorPanic = errors.New("validator panicked")
	// ErrInvalidViolation marks an unsafe or malformed custom diagnostic.
	ErrInvalidViolation = errors.New("invalid validation diagnostic")
)

Functions

This section is empty.

Types

type AsyncValidator

type AsyncValidator[T any] interface {
	ValidateAsync(context.Context, Context, T) Report
}

AsyncValidator is the separate contract for cancellation-aware I/O validation. Implementations are not deterministic Validator values.

func IsolateAsyncPanics

func IsolateAsyncPanics[T any](validator AsyncValidator[T]) AsyncValidator[T]

IsolateAsyncPanics wraps an arbitrary asynchronous validator with the same secret-safe panic containment provided by AsyncValidatorFunc.

type AsyncValidatorFunc

type AsyncValidatorFunc[T any] func(context.Context, Context, T) Report

AsyncValidatorFunc adapts a context-aware function to AsyncValidator.

func (AsyncValidatorFunc[T]) ValidateAsync

func (f AsyncValidatorFunc[T]) ValidateAsync(
	ctx context.Context, validationContext Context, value T,
) (report Report)

ValidateAsync calls the context-aware function.

type Context

type Context struct {
	// contains filtered or unexported fields
}

Context is immutable deterministic validation state. It intentionally does not embed context.Context because ordinary validators cannot perform I/O.

func NewContext

func NewContext(limits Limits, options ...ContextOption) (Context, error)

NewContext constructs immutable validation state.

func (Context) Limits

func (c Context) Limits() Limits

Limits returns the work limits. The zero-value Context uses DefaultLimits so validators fail closed without requiring construction for simple use.

func (Context) Locale

func (c Context) Locale() string

Locale returns the application-defined locale.

func (Context) Metadata

func (c Context) Metadata(key string) (string, bool)

Metadata returns one metadata value.

func (Context) Operation

func (c Context) Operation() string

Operation returns the application-defined operation.

func (Context) Path

func (c Context) Path() Path

Path returns the current immutable path.

func (Context) WithPath

func (c Context) WithPath(segment Segment) Context

WithPath returns a copy with segment appended.

type ContextError added in v1.1.0

type ContextError struct {
	// contains filtered or unexported fields
}

ContextError is the structured terminal error returned by Report.Err.

Example
package main

import (
	"context"
	"errors"
	"fmt"

	validation "github.com/faustbrian/go-validation"
	validationjsonapi "github.com/faustbrian/go-validation/adapters/jsonapi"
)

func main() {
	vctx, _ := validation.NewContext(validation.DefaultLimits())
	ctx, cancel := context.WithCancel(context.Background())
	cancel()
	report := validation.AsyncAll[int](ctx, vctx, 1)
	var terminal *validation.ContextError
	if err := report.Err(); errors.As(err, &terminal) {
		fmt.Println(terminal.Error())
	} else {
		_ = validationjsonapi.Errors(report)
	}
}
Output:
validation canceled

func (*ContextError) Error added in v1.1.0

func (e *ContextError) Error() string

Error returns a bounded context-terminal summary.

func (*ContextError) Report added in v1.1.0

func (e *ContextError) Report() Report

Report returns the immutable partial validation report.

func (*ContextError) Unwrap added in v1.1.0

func (e *ContextError) Unwrap() []error

Unwrap exposes stable context and validation error identities.

type ContextOption

type ContextOption func(*contextConfig)

ContextOption configures NewContext.

func WithLocale

func WithLocale(locale string) ContextOption

WithLocale records an application-defined locale identifier.

func WithMetadata

func WithMetadata(key, value string) ContextOption

WithMetadata adds bounded non-sensitive metadata.

func WithOperation

func WithOperation(operation string) ContextOption

WithOperation records an application-defined operation identifier.

type InvalidError

type InvalidError struct {
	// contains filtered or unexported fields
}

InvalidError exposes a validation report through errors.As.

Example
package main

import (
	"errors"
	"fmt"

	validation "github.com/faustbrian/go-validation"
	"github.com/faustbrian/go-validation/rules"
)

func main() {
	ctx, _ := validation.NewContext(validation.DefaultLimits())
	err := rules.Email().Validate(ctx, "invalid").Err()
	fmt.Println(errors.Is(err, validation.ErrInvalid))
}
Output:
true

func (*InvalidError) Error

func (e *InvalidError) Error() string

Error returns a value-safe summary.

func (*InvalidError) Report

func (e *InvalidError) Report() Report

Report returns the immutable validation report.

func (*InvalidError) Unwrap

func (e *InvalidError) Unwrap() error

Unwrap makes InvalidError compatible with errors.Is and ErrInvalid.

type Limits

type Limits struct {
	MaxDepth               int
	MaxCollectionSize      int
	MaxStringLength        int
	MaxViolations          int
	MaxPathLength          int
	MaxMetadataEntries     int
	MaxMetadataKeyLength   int
	MaxMetadataValueLength int
	MaxRegexPatternLength  int
	MaxCustomConcurrency   int
	MaxStructFields        int
	MaxTagLength           int
	MaxCompiledPlans       int
}

Limits bounds validation work performed on untrusted input.

func DefaultLimits

func DefaultLimits() Limits

DefaultLimits returns conservative limits suitable for application input.

type Mode

type Mode uint8

Mode controls whether composition stops after a decisive result.

const (
	// ShortCircuit stops after the first decisive failure or success.
	ShortCircuit Mode = iota + 1
	// CollectAll evaluates every relevant validator in declaration order.
	CollectAll
)

type Path

type Path struct {
	// contains filtered or unexported fields
}

Path is an immutable ordered location.

func RootPath

func RootPath() Path

RootPath returns an empty root path.

func (Path) Append

func (p Path) Append(segment Segment) Path

Append returns a path copy with segment appended.

func (Path) JSONPointer

func (p Path) JSONPointer() string

JSONPointer serializes typed segments as RFC 6901 reference tokens. It does not evaluate the pointer or assign JSON Patch semantics to Item.

func (Path) Segments

func (p Path) Segments() []Segment

Segments returns a defensive copy of the path segments.

func (Path) String

func (p Path) String() string

String renders a stable human-readable location.

type Presence

type Presence uint8

Presence represents whether an input was omitted, explicitly null, or set.

const (
	// MissingState means no input was supplied.
	MissingState Presence = iota
	// NullState means an explicit null was supplied.
	NullState
	// PresentState means a typed value was supplied.
	PresentState
)

type Report

type Report struct {
	// contains filtered or unexported fields
}

Report is an immutable, ordered, deduplicated collection of violations with an optional context-terminal state.

func AsyncAll

func AsyncAll[T any](ctx context.Context, validationContext Context, value T,
	validators ...AsyncValidator[T],
) Report

AsyncAll executes context-aware validators with bounded concurrency and merges their reports in declaration order. Cancellation stops unscheduled work; validators already running remain responsible for honoring ctx.

Example
package main

import (
	"context"
	"fmt"

	validation "github.com/faustbrian/go-validation"
)

func main() {
	ctx, _ := validation.NewContext(validation.DefaultLimits())
	check := validation.AsyncValidatorFunc[string](func(
		_ context.Context, ctx validation.Context, _ string,
	) validation.Report {
		return validation.NewReport(ctx.Limits())
	})
	report := validation.AsyncAll(context.Background(), ctx, "user", check)
	fmt.Println(report.Err() == nil)
}
Output:
true

func ContextReport added in v1.1.0

func ContextReport(validationContext Context, ctx context.Context) Report

ContextReport returns an empty report that snapshots ctx.Err(). An active context produces no terminal state.

func NewReport

func NewReport(limits Limits) Report

NewReport creates an empty report governed by limits.

func (Report) Add

func (r Report) Add(violation Violation) Report

Add returns a report with a violation appended if it is not a duplicate.

func (Report) ContextError added in v1.1.0

func (r Report) ContextError() error

ContextError reports the captured context terminal identity, if any.

func (Report) Empty

func (r Report) Empty() bool

Empty reports whether no violations were retained.

func (Report) Err

func (r Report) Err() error

Err returns a typed error if validation did not complete or contains a blocking violation.

func (Report) HasCode

func (r Report) HasCode(code string) bool

HasCode reports whether a retained violation has code.

func (Report) HasErrors

func (r Report) HasErrors() bool

HasErrors reports whether any blocking violation was observed, including one omitted because MaxViolations was reached.

func (Report) Len

func (r Report) Len() int

Len returns the number of retained violations.

func (Report) Merge

func (r Report) Merge(other Report) Report

Merge returns a report with other's violations appended in their order.

func (Report) String

func (r Report) String() string

String returns a value-safe report summary.

func (Report) Truncated

func (r Report) Truncated() bool

Truncated reports whether a violation was omitted by the configured limit.

func (Report) Violations

func (r Report) Violations() []Violation

Violations returns a defensive copy preserving validation order.

type Segment

type Segment struct {
	// contains filtered or unexported fields
}

Segment is one typed path component.

func Field

func Field(name string) Segment

Field creates a field segment.

func Index

func Index(index int) Segment

Index creates an index segment.

func Item

func Item() Segment

Item creates a generic item segment.

func Key

func Key(key string) Segment

Key creates a map-key segment.

func (Segment) Kind

func (s Segment) Kind() SegmentKind

Kind returns the segment type.

func (Segment) Value

func (s Segment) Value() string

Value returns the segment's safe location value.

type SegmentKind

type SegmentKind uint8

SegmentKind distinguishes fields, collection indexes, keys, and items.

const (
	// FieldSegment names an object field.
	FieldSegment SegmentKind = iota + 1
	// IndexSegment identifies a collection index.
	IndexSegment
	// KeySegment identifies a map key.
	KeySegment
	// ItemSegment identifies the current collection item in a plan.
	ItemSegment
)

type Severity

type Severity uint8

Severity distinguishes blocking errors from advisory warnings.

const (
	// Error is a blocking validation failure.
	Error Severity = iota + 1
	// Warning is a non-blocking validation observation.
	Warning
)

type Validator

type Validator[T any] interface {
	Validate(Context, T) Report
}

Validator is the deterministic, side-effect-free validation contract.

Example
package main

import (
	"fmt"

	validation "github.com/faustbrian/go-validation"
	"github.com/faustbrian/go-validation/rules"
)

func main() {
	ctx, _ := validation.NewContext(validation.DefaultLimits())
	validator := validation.All(validation.CollectAll,
		rules.RuneLength(3, 20), rules.Prefix("usr_"))
	report := validator.Validate(ctx.WithPath(validation.Field("username")), "x")
	for _, violation := range report.Violations() {
		fmt.Println(violation.Path(), violation.Code())
	}
}
Output:
username rune_length
username prefix

func All

func All[T any](mode Mode, validators ...Validator[T]) Validator[T]

All requires every validator to pass.

func Any

func Any[T any](mode Mode, validators ...Validator[T]) Validator[T]

Any requires at least one validator to pass. Failed alternatives are returned only when every alternative fails.

func Dependent

func Dependent[T any](prerequisite, dependent Validator[T]) Validator[T]

Dependent runs dependent only when prerequisite has no blocking errors.

func IsolatePanics

func IsolatePanics[T any](validator Validator[T]) Validator[T]

IsolatePanics explicitly wraps a custom validator with panic containment. The panic payload and rejected value are deliberately discarded.

func Not

func Not[T any](validator Validator[T]) Validator[T]

Not passes only when validator fails.

func When

func When[T any](predicate func(T) bool, then, otherwise Validator[T]) Validator[T]

When chooses a validator using a deterministic typed predicate.

type ValidatorFunc

type ValidatorFunc[T any] func(Context, T) Report

ValidatorFunc adapts an ordinary function to Validator.

func (ValidatorFunc[T]) Validate

func (f ValidatorFunc[T]) Validate(ctx Context, value T) (report Report)

Validate calls the underlying validation function.

type Value

type Value[T any] struct {
	// contains filtered or unexported fields
}

Value preserves presence separately from a typed value.

Example
package main

import (
	"fmt"

	validation "github.com/faustbrian/go-validation"
	"github.com/faustbrian/go-validation/rules"
)

func main() {
	ctx, _ := validation.NewContext(validation.DefaultLimits())
	report := rules.Required[string]().Validate(ctx, validation.Missing[string]())
	fmt.Println(report.HasCode("required"))
}
Output:
true

func Missing

func Missing[T any]() Value[T]

Missing returns an omitted typed value.

func Null

func Null[T any]() Value[T]

Null returns an explicitly null typed value.

func Present

func Present[T any](value T) Value[T]

Present returns a supplied typed value, including its zero value.

func (Value[T]) Get

func (v Value[T]) Get() (T, bool)

Get returns the supplied value and whether it is present.

func (Value[T]) IsEmpty

func (v Value[T]) IsEmpty() bool

IsEmpty reports whether a present string, collection, or map has length zero. Other values are empty when they are their Go zero value.

func (Value[T]) IsPresent

func (v Value[T]) IsPresent() bool

IsPresent reports whether a typed value was supplied.

func (Value[T]) IsZero

func (v Value[T]) IsZero() bool

IsZero reports whether a present value is its Go zero value.

func (Value[T]) Presence

func (v Value[T]) Presence() Presence

Presence returns the explicit input state.

type Violation

type Violation struct {
	// contains filtered or unexported fields
}

Violation is a value-safe machine-readable validation finding.

func NewViolation

func NewViolation(path Path, code string, severity Severity,
	parameters map[string]string, safeCause error,
) Violation

NewViolation constructs a violation. Parameters and paths are copied; malformed or unsafe diagnostic metadata fails closed.

func (Violation) Cause

func (v Violation) Cause() error

Cause returns an explicitly safe underlying cause.

func (Violation) Code

func (v Violation) Code() string

Code returns the machine-readable rule identity.

func (Violation) Parameters

func (v Violation) Parameters() map[string]string

Parameters returns a defensive copy of safe message parameters.

func (Violation) Path

func (v Violation) Path() Path

Path returns the stable field location.

func (Violation) Severity

func (v Violation) Severity() Severity

Severity returns whether the finding blocks acceptance.

func (Violation) String

func (v Violation) String() string

String deliberately excludes parameters, causes, and rejected values.

Directories

Path Synopsis
adapters
config
Package validationconfig adapts typed validators to a small configuration validation contract.
Package validationconfig adapts typed validators to a small configuration validation contract.
http
Package validationhttp provides router-neutral HTTP report projection.
Package validationhttp provides router-neutral HTTP report projection.
jsonapi
Package validationjsonapi projects reports into JSON:API error objects.
Package validationjsonapi projects reports into JSON:API error objects.
jsonrpc
Package validationjsonrpc projects reports into JSON-RPC invalid-params errors.
Package validationjsonrpc projects reports into JSON-RPC invalid-params errors.
service
Package validationservice provides transport-neutral service hook contracts.
Package validationservice provides transport-neutral service hook contracts.
Package rules provides reusable typed deterministic validators.
Package rules provides reusable typed deterministic validators.
Package structplan provides optional typed and startup-compiled struct plans.
Package structplan provides optional typed and startup-compiled struct plans.
Package validationconfig adapts typed validators to a small config contract.
Package validationconfig adapts typed validators to a small config contract.
Package validationhttp provides router-neutral HTTP report projection.
Package validationhttp provides router-neutral HTTP report projection.
Package validationjsonapi projects reports into JSON:API error objects.
Package validationjsonapi projects reports into JSON:API error objects.
Package validationobserve exposes non-sensitive observation hooks.
Package validationobserve exposes non-sensitive observation hooks.
Package validationrpc projects reports into JSON-RPC invalid-params errors.
Package validationrpc projects reports into JSON-RPC invalid-params errors.
Package validationservice provides transport-neutral service hook contracts.
Package validationservice provides transport-neutral service hook contracts.
Package validationtest provides reusable report assertions and conformance helpers for consumers.
Package validationtest provides reusable report assertions and conformance helpers for consumers.
Package validationtext applies application-supplied message catalogs.
Package validationtext applies application-supplied message catalogs.

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL